require 'libdemsite' require 'libsafewrite' class Path attr_reader :mvleft, :x, :y def initialize(mvleft, x, y) @mvleft, @x, @y = mvleft, x, y end def ==(o) @x == o.x and @y == o.y end end class Case attr_accessor :ppath alias old_initialize initialize def initialize(*args) old_initialize(*args) @ppath = Array.new end alias old_inspect inspect def inspect old_inspect + ", ppath #{@ppath.inspect}" end def to_s "#@x, #@y#{" #{@pers.race} #{@pers.mat}: #{@pers.name}" if @pers}" #" end def ==(o) @x == o.x and @y == o.y end end class Vue def save(file) File.safe_write(file) { |fd| 600.times { |y| if @ys[y+1] xs = @ys[y+1] l = '' 800.times { |x| if xs[x] l << (xs[x].mv * 10).to_i else l << 10 end } fd.write l else fd.write 10.chr*800 end } } end def load(file) @ys[0] = Array.new File.open(file) { |fd| 600.times { |y| t = @ys[y+1] ||= [] xs = fd.read 800 800.times { |x| t[x] ||= Case.new(x, y, xs[x].to_f / 10) } } } end def search(name) name = Regexp.new(name, Regexp::IGNORECASE) if name.class == String @ys[@ymin..@ymax].each { |xs| xs[@xmin..@xmax].each { |c| return c if c and c.pers and (c.pers.name =~ name or c.pers.mat == name) } if xs } nil end def show(clen = 9, xhl=nil, yhl=nil, xmin=@xmin, xmax=@xmax, ymin=@ymin, ymax=@ymax, ppathidx=nil) rien = '' puts [([rien]+(xmin..xmax).to_a).map{ |e| e.to_s[0...clen].center(clen) + '|' }.join + "\n" + (('-'*clen+'+')*(xmax - xmin + 2)) ] + (ymin..ymax).map { |y| a1, a2, a3, a4 = [rien], [y], [rien], [rien] (xmin..xmax).map { |x| c = self[x, y] if c if pp = c.pers a1 << pp.name ; a2 << pp.race ; a3 << pp.mat ; a4 << c.mv else if ppathidx and (cf = c.ppath[ppathidx]) a1 << rien ; a2 << c.ppath[ppathidx].mvleft ; a3 << c.mv ; a4 << rien case [cf.x - c.x, cf.y - c.y] when [-1, -1] ; a4[-1] = '/' + ' ' * (clen-1) when [-1, 0] ; a2[-1] = '-' + a2[-1].to_s.center(clen-1) when [-1, 1] ; a1[-1] = '\\' + ' ' * (clen-1) when [ 0, -1] ; a4[-1] = '|' when [ 0, 1] ; a1[-1] = '|' when [ 1, -1] ; a4[-1] = ' ' * (clen-1) + '\\' when [ 1, 0] ; a2[-1] = a2[-1].to_s.center(clen-1) + '-' when [ 1, 1] ; a1[-1] = ' ' * (clen-1) + '/' end else a1 << rien ; a2 << rien ; a3 << c.mv ; a4 << rien end end else a1 << rien ; a2 << rien ; a3 << rien ; a4 << rien end } ([a1, a2, a3, a4].map { |a| x = xmin-2 a.map { |e| x += 1 e.to_s[0...clen].center(clen) + ((yhl == y and (xhl == x or xhl == x+1)) ? ':' : '|') }.join } + [ (('-'*clen+'+')*a1.length) ] ).join("\n") }.flatten.reverse end def showshort(clen=3, xhl=nil, yhl=nil, xmin=@xmin, xmax=@xmax, ymin=@ymin, ymax=@ymax) rien = '' puts [([rien]+(xmin..xmax).to_a).map{ |e| e.to_s[0...clen].center(clen) + '|' }.join + "\n" + (('-'*clen+'+')*(xmax - xmin + 2)) ] + (ymin..ymax).map { |y| aa = [y] (xmin..xmax).map { |x| c = self[x, y] if c aa << c.mv else aa << rien end } ([aa].map { |a| x = xmin-2 a.map { |e| x += 1 e.to_s[0...clen].center(clen) + ((yhl == y and (xhl == x or xhl == x+1)) ? ':' : '|') }.join } + [ (('-'*clen+'+')*aa.length) ] ).join("\n") }.flatten.reverse end end class Perso alias dla nextturn def events @d.events @mat end def now @d.now end def pathscan return if not @pvregen v = @vue[@plan] # clear old info v.ys.each { |xs| xs.each { |c| c.ppath[@idx] = nil if c and c.ppath[@idx] } if xs } v[@x, @y].ppath[@idx] = Path.new(@mv, @x, @y) known = [v[@x, @y]] # parcourt toutes les cases pour chercher la prochaine non known où on a le plus gros mvleft loop do max = -1 maxc = nil maxcn = nil known.each { |c| [-1, 0, 1].each { |dy| [-1, 0, 1].each { |dx| cn = v[c.x+dx, c.y+dy] # skippe si on connait déjà un chemin ou si on ne voit pas cette case next if (dx == 0 and dy == 0) or not cn or cn.ppath[@idx] if cn.pers # case occupée: on peut l'atteindre d'ici cn.ppath[@idx] = Path.new(0, c.x, c.y) elsif c.ppath[@idx].mvleft - cn.mv > max # meilleure case pour le moment max = c.ppath[@idx].mvleft - cn.mv maxc = c maxcn = cn end } } } # fini break if max < 0 maxcn.ppath[@idx] = Path.new(max, maxc.x, maxc.y) known << maxcn end end def vueh @vue[@plan] end def vue(clen = 9, pathidx = @idx) return puts("le perso est mort") if @dead sync unless @pvregen @vue[@plan].show(clen, @x, @y, @x-5, @x+5, @y-5, @y+5, pathidx) end def vueshift(dx, dy, clen = 9, pathidx = @idx) return puts('le perso est mort') if @dead sync unless @pvregen @vue[@plan].show(clen, @x, @y, @x+dx-5, @x+dx+5, @y+dy-5, @y+dy+5, pathidx) end def moverel(dx, dy) move(@x+dx, @y+dy) end def movetorec(c) return if c == self x, y = c.ppath[@idx].x, c.ppath[@idx].y movetorec(@vue[@plan][x, y]) return if @movetolim <= 0 @movetolim -= 1 move(c.x, c.y) end private :movetorec def moveto(c, y=nil, limit=50) sync if not @pvregen # x, y -> case if y c = @vue[@plan][c, y] else c = @vue[@plan][c.x, c.y] end return false if not c or not c.ppath[@idx] @movetolim = limit movetorec(c) end def movetorel(dx, dy, limit=50) pathscan unless @vue[@plan][@x+dx, @y+dy].ppath[@idx] moveto(@x+dx, @y+dy, limit) end def fullatq return if @dead sync true unless @pvregen puts 'fullatq' if setdes(@datq + @dvar, @ddef - @dvar) end def fulldef return if @dead sync true unless @pvregen puts 'fulldef' if setdes(@datq - @dvar, @ddef + @dvar) end def to_s if @dead " #@idx (mort): #@name (#@mat), #@race lvl #@lvl, #@px px, "+ "mv 0/#@mvmax, pv 0/#@pvmax, natq 0/#@natqmax" else " #@idx: #@name (#@mat), #@race lvl #@lvl, #@px px, "+ "mv #@mv/#@mvmax, natq #@natq/#@natqmax, pv #@pv/#@pvmax "+ "(#@x, #@y), DLA #{@nextturn.strftime('%d/%m %H:%M:%S') if @nextturn}"+ if @pvregen "\n#@pi pi, des: #@datq-#@ddef#{' +-'+@dvar.to_s if @dcanchg}, #@deg deg, #@nbal bals, maldef: #@maldef\ncibles: #{@cibles.inspect}, mdj: #{@mdj.inspect}" else '' end end end def inspect "" end end class Demange def Demange.play d=Demange.new d.fast_mode = true begin d.login_resume puts "resumed" rescue RuntimeError begin d.login rescue puts "login error" end end d end def map(f) @persos.map { |p| p.send f } end def vueboth(i1, i2, clen=nil, dx=0, dy=dx) p1, p2 = nil if p1 = self[i1] and p2 = self[i2] and p1.plan == p2.plan if p1.x < p2.x xmin, xmax = p1.x, p2.x else xmax, xmin = p1.x, p2.x end if p1.y < p2.y ymin, ymax = p1.y, p2.y else ymax, ymin = p1.y, p2.y end clen = (160/((xmax + 2 - xmin) + 2*dx)).to_i - 1 unless clen self.vue[p1.plan].show(clen, 0, 0, xmin-dx, xmax+dx, ymin-dy, ymax+dy) end end def updateall a = @persos.dup while not a.empty? i = rand(a.length) a[i].sync if a[i] and not a[i].pvregen a.delete_at(i) end nil end def updateall! @persos.each { |p| p.pvregen = nil } updateall end def inspect @persos.map{ |p| "#{p.idx} #{'*' if p.pvregen}#{p.name}" }.inspect end end