| Home | Forums | Reviews | Guides | Newsgroups | Register | Search |
![]() |
| Thread Tools |
|
Stefan Walk
Guest
Posts: n/a
|
Hi,
here is my solution... RubberDuckLinear is a linear shooting variant of RubberDuck and runs significantly faster, but the extra code was neccessary to hit some of the dodgy robots (Kite2 for example). Rubberduck-debug includes debug code, for interested people (not a tournament entry). Regards, Stefan require 'robot' require 'ostruct' module RubberRobot MEMO_SIZE = 250 GUN_POWER = 0.1 ACC_WHILE_MOVING = false class Memo # (forgetting old values) {{{ def initialize(n) @array = [] @n = n end def << (arg) @array.unshift arg @array = @array.first(@n) end def [](arg) @array[arg] end def to_a @array end def nearest_non_nil(idx) 0.upto(51) do |offs| next if @array[idx + ((offs % 2 == 0) ? -1 : 1)*offs].nil? return idx + ((offs % 2 == 0) ? -1 : 1)*offs end nil end end # }}} class Brain # {{{ include Math # This robot knows Math! def time @robot.time end def battlefield_width @robot.battlefield_width end def battlefield_height @robot.battlefield_height end def size @robot.size end def say(string) @robot.say(string) end def trim(min, val, max) # {{{ return min if val < min return max if val > max return val end # }}} def strim(val, border) # {{{ return -border if val < -border return border if val > border return val end # }}} def initialize(robot) # {{{ @memory = OpenStruct.new @memory.rheading = Memo.new(MEMO_SIZE) @memory.pos = Memo.new(MEMO_SIZE) @memory.enemypos = Memo.new(MEMO_SIZE*4) @memory.enemyrange = Memo.new(MEMO_SIZE) @memory.enemyangle = Memo.new(MEMO_SIZE) @memory.lastseen = nil @robot = robot @tlock = 0 @lasthit = 0 @looking_since = 0 @aim_mode = :linear end # }}} # def method_missing(name, *args) # {{{ # @robot.__send__(name, *args) # end # }}} def refresh # {{{ @x = @robot.x @y = @robot.y @turn_body = 0 @turn_turret = 0 @turn_radar = 0 @power = GUN_POWER @accelerate = 0 @body_heading = @robot.heading @turret_heading = @robot.gun_heading @radar_heading = @robot.radar_heading end # }}} def tick(events) # {{{ refresh save_memory if events.has_key? 'robot_scanned' r = events['robot_scanned'][0][0] phi0 = @memory.rheading[0] phi1 = @memory.rheading[1] if (phi0 < 90 and phi1 > 270) or (phi0 > 270 and phi1 < 90) phim = (phi0 + phi1 + 90) % 360 - 90 else phim = (phi0 + phi1)/2 end phi0, phi1, phim = phi0.to_rad, phi1.to_rad, phim.to_rad dx = r*(cos(phi0) - cos(phi1)).abs/2 dy = r*(sin(phi0) - sin(phi1)).abs/2 x = @x + r * cos(phim) y = @y - r * sin(phim) @memory.lastseen = 0 @memory.enemypos << [x,dx,y,dy] @memory.enemyrange << r @memory.enemyangle << phim @memory.enemy else @memory.lastseen += 1 if @memory.lastseen @memory.enemypos << nil @memory.enemyrange << nil @memory.enemyangle << nil end if events.has_key? 'got_hit' @lasthit = 0 else @lasthit += 1 end if time == 50 say "<Patrician|Away> what does your robot do, sam" elsif time == 100 say "<bovril> it collects data about the surrounding environment, ..." elsif time == 150 say "... then discards it and drives into walls" end do_radar_aiming do_turret_aiming do_movement execute end # }}} def do_turret_aiming # {{{ if (time >= 200 and time % 100 == 0) or @schedule_calc @schedule_calc = false corr = check_correlation begin max = corr.max{|a,b| a[1] <=> b[1]} rescue ArgumentError => e p corr.sort raise e end if max[0] > 35 and max[1] > 0.35 @aim_mode = :correlation @corr_diff = max[0] else @aim_mode = :linear end end case @aim_mode when :linear @turn_turret = 1 dist = 800 i = 0 angle = nil x, y = nil, nil catch :tads do loop do x,y = predict(dist/30.0 + 1) # TODO ??? throw :tads unless x and y angle, distn = get_angle_and_dist(x,y) break if (distn - dist).abs < 15 or (i += 1) > 20 dist = distn end @turn_turret = deg_diff(angle, @turret_heading) end when :correlation =begin ``Those who cannot remember the past are condemned to repeat it.'' -- George Santayana (1863-1952) =end idx = @memory.enemypos.nearest_non_nil(@corr_diff - 25) unless idx @turn_turret = 0 @schedule_calc = true break end pos = nil angle = nil dist = nil i = 0 loop do pos = @memory.enemypos[idx] angle, dist = get_angle_and_dist(pos[0], pos[2]) idxn = @memory.enemypos.nearest_non_nil(@corr_diff - (dist/30.0).to_i) break unless idxn break if idxn == idx idx = idxn break if i >= 20 i += 1 end x,dx,y,dy = @memory.enemypos[idx] angle, dist = get_angle_and_dist(x, y) @turn_turret = deg_diff(angle, @turret_heading) else raise 'wtf?' end @angle = angle end # }}} def do_radar_aiming # {{{ @turn_radar = 10 and return unless @memory.lastseen @radar_turn_speed ||= 60 if @memory.lastseen == 0 @radar_turn_speed *= -0.5 else @memory.lastseen != 2 @radar_turn_speed *= -2 if @radar_turn_speed.abs < 60 end @turn_radar = @radar_turn_speed end # }}} def do_movement # {{{ =begin http://bash.org/?240849 <Patrician|Away> what does your robot do, sam <bovril> it collects data about the surrounding environment, then discards it and drives into walls =end @accelerate = 1 # Energie! @move_dur ||= 0 @turn_dur ||= 0 @acc_dur ||= 0 if @move_dur == 0 wangle, wdist = get_revangle_and_dist_wall if wdist < 100 @turn_dir = strim(deg_diff(wangle, @body_heading), 10) else @turn_dir = (rand > 0.5) ? 10 : -10 end @turn_dur = 7 + (rand 12) @move_dur = @turn_dur + 5 + (rand 10) @turn_body = @turn_dir if ACC_WHILE_MOVING @acc_dur = rand 7 end elsif @turn_dur == 0 @move_dur -= 1 elsif @acc_dur == 0 @move_dur -= 1 @turn_dur -= 1 @turn_body = @turn_dir else @acc_dur -= 1 @move_dur -= 1 @turn_dur -= 1 @accelerate = -1 @turn_body = @turn_dir end end # }}} def sign(x) # {{{ return 0 if x == 0 return 1 if x > 1 return -1 end # }}} def dist_to_center # {{{ hypot(battlefield_height/2 - @y, battlefield_width/2 - @x) end # }}} def angle_to_center end def get_revangle_and_dist_wall return [[@x,0], [@y,270], [battlefield_width - @x, 180], [battlefield_height - @y, 90]].min.reverse end def approaching_center # {{{ angle = (atan2(@x, @y).to_deg + 90) % 360 diff = deg_diff(angle, @body_heading).abs diff < 80 end # }}} def deg_diff(ang1, ang2) # {{{ (ang1 - ang2 + 180) % 360 - 180 end # }}} def get_angle_and_dist(x,y) # {{{ dx = x - @x dy = y - @y return [(atan2(dx, dy).to_deg - 90) % 360, hypot(dx, dy)] end # }}} def predict(ticks, maxhist = 70) # {{{ i = 0 lx = 0.0 mx = 0.0 nx = 0.0 ox = 0.0 px = 0.0 ly = 0.0 my = 0.0 ny = 0.0 oy = 0.0 py = 0.0 @memory.enemypos.to_a.each_with_index do |ev, idx| next unless ev break if idx > maxhist break if i > 5 x, dx, y, dy = ev dx *= 1 + (idx / 50.to_f) ** 2 dy *= 1 + (idx / 50.to_f) ** 2 dx = 1.0 if dx < 1.0 dy = 1.0 if dy < 1.0 t = -idx-1 i += 1 sx = dx**2 lx += t**2/sx mx += t/sx nx += t*x/sx ox += x/sx px += 1/sx sy = dy**2 ly += t**2/sy my += t/sy ny += t*y/sy oy += y/sy py += 1/sy end return unless i >= 2 ax = (px*nx - mx*ox)/(px*lx - mx**2) bx = 1/px*(mx*ax-ox) ay = (py*ny - my*oy)/(py*ly - my**2) by = 1/py*(my*ay-oy) bx *= -1 by *= -1 factor = hypot(ax, ay)/8.0 if factor > 1 ax /= factor ay /= factor end bx = battlefield_width - size if bx > battlefield_width - size by = battlefield_width - size if by > battlefield_width - size bx = size if bx < size by = size if by < size px = bx+ax*ticks py = by+ay*ticks return if px.infinite? or px.nan? or py.infinite? or py.nan? px = [battlefield_width - size, [size, px].max].min py = [battlefield_height - size, [size, py].max].min [px, py] end # }}} def execute # {{{ @turn_turret -= @turn_body @turn_radar -= @turn_body + @turn_turret @turn_body = trim(-10, @turn_body, 10) @turn_turret = trim(-30, @turn_turret, 30) @turn_radar = trim(-60, @turn_radar, 60) @robot.accelerate(@accelerate) @robot.turn(@turn_body) @robot.turn_gun(@turn_turret) @robot.turn_radar(@turn_radar) @robot.fire(@power) end # }}} def save_memory # {{{ @memory.rheading << @radar_heading @memory.pos << [@x, @y] end # }}} def check_correlation # {{{ pos = @memory.enemypos.to_a[0..500] size = @robot.size corr_values = {} 30.upto(150) do |diff| hits = 0 tries = 0 0.upto(pos.size - diff) do |idx| next unless pos[idx] and pos[idx + diff] next unless hypot(pos[idx][1],pos[idx][3]) < 100 next unless hypot(pos[idx + diff][1],pos[idx + diff][3]) < 100 dist = hypot(pos[idx][0] - pos[idx + diff][0], pos[idx][2] - pos[idx + diff][2]) tries += 1 hits += 1 if dist < size end ratio = hits.to_f/tries ratio = 0.0 unless ratio.finite? corr_values[diff] = ratio end corr_values end # }}} end # }}} class Robot # {{{ include ::Robot def initialize @my_brain = Brain.new(self) end def tick(events) @my_brain.tick(events) end end # }}} end class RubberDuck < RubberRobot::Robot; end require 'robot' require 'ostruct' module RubberRobot RUBBERDEBUG = true MEMO_SIZE = 250 GUN_POWER = 0.1 ACC_WHILE_MOVING = true class Memo # (forgetting old values) {{{ def initialize(n) @array = [] @n = n end def << (arg) @array.unshift arg @array = @array.first(@n) end def [](arg) @array[arg] end def to_a @array end def nearest_non_nil(idx) 0.upto(51) do |offs| next if @array[idx + ((offs % 2 == 0) ? -1 : 1)*offs].nil? return idx + ((offs % 2 == 0) ? -1 : 1)*offs end nil end end # }}} class Brain # {{{ include Math # This robot knows Math! def time @robot.time end def battlefield_width @robot.battlefield_width end def battlefield_height @robot.battlefield_height end def size @robot.size end def say(string) @robot.say(string) end def trim(min, val, max) # {{{ return min if val < min return max if val > max return val end # }}} def strim(val, border) # {{{ return -border if val < -border return border if val > border return val end # }}} def initialize(robot) # {{{ @memory = OpenStruct.new @memory.rheading = Memo.new(MEMO_SIZE) @memory.pos = Memo.new(MEMO_SIZE) @memory.enemypos = Memo.new(MEMO_SIZE*4) @memory.enemyrange = Memo.new(MEMO_SIZE) @memory.enemyangle = Memo.new(MEMO_SIZE) @memory.lastseen = nil @robot = robot @tlock = 0 @lasthit = 0 @looking_since = 0 @aim_mode = :linear end # }}} # def method_missing(name, *args) # {{{ # @robot.__send__(name, *args) # end # }}} if RUBBERDEBUG # {{{ paints detection and prediction onto the canvas def check_canvas return false unless defined? TkCanvas unless @canvas ObjectSpace.each_object(TkCanvas) {|o| @canvas = o } end return false unless @canvas return true end def detect_at(xmin, xmax, ymin, ymax) return unless check_canvas unless @detect_p @detect_p = TkcOval.new(@canvas, [-5,-5], [6,6], end @detect_p.coords(xmin/2,ymin/2,xmax/2,ymax/2) end def predict_at(x,y) return unless check_canvas unless @predict_p @predict_p = TkcOval.new(@canvas, [-5,-5], [6,6], end @predict_p.coords(x/2-3,y/2-3,x/2+3,y/2+3) end end # }}} def refresh # {{{ @x = @robot.x @y = @robot.y @turn_body = 0 @turn_turret = 0 @turn_radar = 0 @power = GUN_POWER @accelerate = 0 @body_heading = @robot.heading @turret_heading = @robot.gun_heading @radar_heading = @robot.radar_heading end # }}} def tick(events) # {{{ refresh save_memory if events.has_key? 'robot_scanned' r = events['robot_scanned'][0][0] phi0 = @memory.rheading[0] phi1 = @memory.rheading[1] if (phi0 < 90 and phi1 > 270) or (phi0 > 270 and phi1 < 90) phim = (phi0 + phi1 + 90) % 360 - 90 else phim = (phi0 + phi1)/2 end phi0, phi1, phim = phi0.to_rad, phi1.to_rad, phim.to_rad dx = r*(cos(phi0) - cos(phi1)).abs/2 dy = r*(sin(phi0) - sin(phi1)).abs/2 x = @x + r * cos(phim) y = @y - r * sin(phim) detect_at(x-dx,x+dx,y-dy,y+dy) if RUBBERDEBUG @memory.lastseen = 0 @memory.enemypos << [x,dx,y,dy] @memory.enemyrange << r @memory.enemyangle << phim @memory.enemy else @memory.lastseen += 1 if @memory.lastseen @memory.enemypos << nil @memory.enemyrange << nil @memory.enemyangle << nil end if events.has_key? 'got_hit' @lasthit = 0 else @lasthit += 1 end if time == 50 say "<Patrician|Away> what does your robot do, sam" elsif time == 100 say "<bovril> it collects data about the surrounding environment, ..." elsif time == 150 say "... then discards it and drives into walls" end do_radar_aiming do_turret_aiming do_movement execute end # }}} def do_turret_aiming # {{{ if (time >= 200 and time % 100 == 0) or @schedule_calc @schedule_calc = false corr = check_correlation begin max = corr.max{|a,b| a[1] <=> b[1]} rescue ArgumentError => e p corr.sort raise e end if max[0] > 35 and max[1] > 0.35 @aim_mode = :correlation @corr_diff = max[0] else @aim_mode = :linear end end case @aim_mode when :linear @turn_turret = 1 dist = 800 i = 0 angle = nil x, y = nil, nil catch :tads do loop do x,y = predict(dist/30.0 + 1) # TODO ??? throw :tads unless x and y angle, distn = get_angle_and_dist(x,y) break if (distn - dist).abs < 15 or (i += 1) > 20 dist = distn end @turn_turret = deg_diff(angle, @turret_heading) end if x and y predict_at(x, y) if RUBBERDEBUG else predict_at(0,0) if RUBBERDEBUG end when :correlation =begin ``Those who cannot remember the past are condemned to repeat it.'' -- George Santayana (1863-1952) =end idx = @memory.enemypos.nearest_non_nil(@corr_diff - 25) unless idx @turn_turret = 0 @schedule_calc = true break end pos = nil angle = nil dist = nil i = 0 loop do pos = @memory.enemypos[idx] angle, dist = get_angle_and_dist(pos[0], pos[2]) idxn = @memory.enemypos.nearest_non_nil(@corr_diff - (dist/30.0).to_i) break unless idxn break if idxn == idx idx = idxn break if i >= 20 i += 1 end x,dx,y,dy = @memory.enemypos[idx] angle, dist = get_angle_and_dist(x, y) @turn_turret = deg_diff(angle, @turret_heading) if x and y predict_at(x, y) if RUBBERDEBUG else predict_at(0,0) if RUBBERDEBUG end else raise 'wtf?' end @angle = angle end # }}} def do_radar_aiming # {{{ @turn_radar = 10 and return unless @memory.lastseen @radar_turn_speed ||= 60 if @memory.lastseen == 0 @radar_turn_speed *= -0.5 else @memory.lastseen != 2 @radar_turn_speed *= -2 if @radar_turn_speed.abs < 60 end @turn_radar = @radar_turn_speed end # }}} def do_movement # {{{ =begin http://bash.org/?240849 <Patrician|Away> what does your robot do, sam <bovril> it collects data about the surrounding environment, then discards it and drives into walls =end @accelerate = 1 # Energie! @move_dur ||= 0 @turn_dur ||= 0 @acc_dur ||= 0 if @move_dur == 0 wangle, wdist = get_revangle_and_dist_wall if wdist < 100 @turn_dir = strim(deg_diff(wangle, @body_heading), 10) else @turn_dir = (rand > 0.5) ? 10 : -10 end @turn_dur = 7 + (rand 12) @move_dur = @turn_dur + 5 + (rand 10) @turn_body = @turn_dir if ACC_WHILE_MOVING @acc_dur = rand 7 end elsif @turn_dur == 0 @move_dur -= 1 elsif @acc_dur == 0 @move_dur -= 1 @turn_dur -= 1 @turn_body = @turn_dir else @acc_dur -= 1 @move_dur -= 1 @turn_dur -= 1 @accelerate = -1 @turn_body = @turn_dir end end # }}} def sign(x) # {{{ return 0 if x == 0 return 1 if x > 1 return -1 end # }}} def dist_to_center # {{{ hypot(battlefield_height/2 - @y, battlefield_width/2 - @x) end # }}} def angle_to_center end def get_revangle_and_dist_wall return [[@x,0], [@y,270], [battlefield_width - @x, 180], [battlefield_height - @y, 90]].min.reverse end def approaching_center # {{{ angle = (atan2(@x, @y).to_deg + 90) % 360 diff = deg_diff(angle, @body_heading).abs diff < 80 end # }}} def deg_diff(ang1, ang2) # {{{ (ang1 - ang2 + 180) % 360 - 180 end # }}} def get_angle_and_dist(x,y) # {{{ dx = x - @x dy = y - @y return [(atan2(dx, dy).to_deg - 90) % 360, hypot(dx, dy)] end # }}} def predict(ticks, maxhist = 70) # {{{ i = 0 lx = 0.0 mx = 0.0 nx = 0.0 ox = 0.0 px = 0.0 ly = 0.0 my = 0.0 ny = 0.0 oy = 0.0 py = 0.0 @memory.enemypos.to_a.each_with_index do |ev, idx| next unless ev break if idx > maxhist break if i > 5 x, dx, y, dy = ev dx *= 1 + (idx / 50.to_f) ** 2 dy *= 1 + (idx / 50.to_f) ** 2 dx = 1.0 if dx < 1.0 dy = 1.0 if dy < 1.0 t = -idx-1 i += 1 sx = dx**2 lx += t**2/sx mx += t/sx nx += t*x/sx ox += x/sx px += 1/sx sy = dy**2 ly += t**2/sy my += t/sy ny += t*y/sy oy += y/sy py += 1/sy end return unless i >= 2 ax = (px*nx - mx*ox)/(px*lx - mx**2) bx = 1/px*(mx*ax-ox) ay = (py*ny - my*oy)/(py*ly - my**2) by = 1/py*(my*ay-oy) bx *= -1 by *= -1 factor = hypot(ax, ay)/8.0 if factor > 1 ax /= factor ay /= factor end bx = battlefield_width - size if bx > battlefield_width - size by = battlefield_width - size if by > battlefield_width - size bx = size if bx < size by = size if by < size px = bx+ax*ticks py = by+ay*ticks return if px.infinite? or px.nan? or py.infinite? or py.nan? px = [battlefield_width - size, [size, px].max].min py = [battlefield_height - size, [size, py].max].min [px, py] end # }}} def execute # {{{ @turn_turret -= @turn_body @turn_radar -= @turn_body + @turn_turret @turn_body = trim(-10, @turn_body, 10) @turn_turret = trim(-30, @turn_turret, 30) @turn_radar = trim(-60, @turn_radar, 60) @robot.accelerate(@accelerate) @robot.turn(@turn_body) @robot.turn_gun(@turn_turret) @robot.turn_radar(@turn_radar) @robot.fire(@power) end # }}} def save_memory # {{{ @memory.rheading << @radar_heading @memory.pos << [@x, @y] end # }}} def check_correlation # {{{ pos = @memory.enemypos.to_a[0..500] size = @robot.size corr_values = {} 30.upto(150) do |diff| hits = 0 tries = 0 0.upto(pos.size - diff) do |idx| next unless pos[idx] and pos[idx + diff] next unless hypot(pos[idx][1],pos[idx][3]) < 100 next unless hypot(pos[idx + diff][1],pos[idx + diff][3]) < 100 dist = hypot(pos[idx][0] - pos[idx + diff][0], pos[idx][2] - pos[idx + diff][2]) tries += 1 hits += 1 if dist < size end ratio = hits.to_f/tries ratio = 0.0 unless ratio.finite? corr_values[diff] = ratio end corr_values end # }}} end # }}} class Robot # {{{ include ::Robot def initialize @my_brain = Brain.new(self) end def tick(events) @my_brain.tick(events) end end # }}} end class RubberDuck < RubberRobot::Robot; end require 'robot' require 'ostruct' #same as module RubberRobotLinear MEMO_SIZE = 250 GUN_POWER = 0.1 ACC_WHILE_MOVING = true class Memo # (forgetting old values) {{{ def initialize(n) @array = [] @n = n end def << (arg) @array.unshift arg @array = @array.first(@n) end def [](arg) @array[arg] end def to_a @array end def nearest_non_nil(idx) 0.upto(51) do |offs| next if @array[idx + ((offs % 2 == 0) ? -1 : 1)*offs].nil? return idx + ((offs % 2 == 0) ? -1 : 1)*offs end nil end end # }}} class Brain # {{{ include Math # This robot knows Math! def time @robot.time end def battlefield_width @robot.battlefield_width end def battlefield_height @robot.battlefield_height end def size @robot.size end def say(string) @robot.say(string) end def trim(min, val, max) # {{{ return min if val < min return max if val > max return val end # }}} def strim(val, border) # {{{ return -border if val < -border return border if val > border return val end # }}} def initialize(robot) # {{{ @memory = OpenStruct.new @memory.rheading = Memo.new(MEMO_SIZE) @memory.pos = Memo.new(MEMO_SIZE) @memory.enemypos = Memo.new(MEMO_SIZE*4) @memory.enemyrange = Memo.new(MEMO_SIZE) @memory.enemyangle = Memo.new(MEMO_SIZE) @memory.lastseen = nil @robot = robot @tlock = 0 @lasthit = 0 @looking_since = 0 @aim_mode = :linear end # }}} # def method_missing(name, *args) # {{{ # @robot.__send__(name, *args) # end # }}} def refresh # {{{ @x = @robot.x @y = @robot.y @turn_body = 0 @turn_turret = 0 @turn_radar = 0 @power = GUN_POWER @accelerate = 0 @body_heading = @robot.heading @turret_heading = @robot.gun_heading @radar_heading = @robot.radar_heading end # }}} def tick(events) # {{{ refresh save_memory if events.has_key? 'robot_scanned' r = events['robot_scanned'][0][0] phi0 = @memory.rheading[0] phi1 = @memory.rheading[1] if (phi0 < 90 and phi1 > 270) or (phi0 > 270 and phi1 < 90) phim = (phi0 + phi1 + 90) % 360 - 90 else phim = (phi0 + phi1)/2 end phi0, phi1, phim = phi0.to_rad, phi1.to_rad, phim.to_rad dx = r*(cos(phi0) - cos(phi1)).abs/2 dy = r*(sin(phi0) - sin(phi1)).abs/2 x = @x + r * cos(phim) y = @y - r * sin(phim) @memory.lastseen = 0 @memory.enemypos << [x,dx,y,dy] @memory.enemyrange << r @memory.enemyangle << phim @memory.enemy else @memory.lastseen += 1 if @memory.lastseen @memory.enemypos << nil @memory.enemyrange << nil @memory.enemyangle << nil end if events.has_key? 'got_hit' @lasthit = 0 else @lasthit += 1 end if time == 50 say "<Patrician|Away> what does your robot do, sam" elsif time == 100 say "<bovril> it collects data about the surrounding environment, ..." elsif time == 150 say "... then discards it and drives into walls" end do_radar_aiming do_turret_aiming do_movement execute end # }}} def do_turret_aiming # {{{ @turn_turret = 1 dist = 800 i = 0 angle = nil x, y = nil, nil catch :tads do loop do x,y = predict(dist/30.0 + 1) # TODO ??? throw :tads unless x and y angle, distn = get_angle_and_dist(x,y) break if (distn - dist).abs < 15 or (i += 1) > 20 dist = distn end @turn_turret = deg_diff(angle, @turret_heading) end @angle = angle end # }}} def do_radar_aiming # {{{ @turn_radar = 10 and return unless @memory.lastseen @radar_turn_speed ||= 60 if @memory.lastseen == 0 @radar_turn_speed *= -0.5 else @memory.lastseen != 2 @radar_turn_speed *= -2 if @radar_turn_speed.abs < 60 end @turn_radar = @radar_turn_speed end # }}} def do_movement # {{{ =begin http://bash.org/?240849 <Patrician|Away> what does your robot do, sam <bovril> it collects data about the surrounding environment, then discards it and drives into walls =end @accelerate = 1 # Energie! @move_dur ||= 0 @turn_dur ||= 0 @acc_dur ||= 0 if @move_dur == 0 wangle, wdist = get_revangle_and_dist_wall if wdist < 100 @turn_dir = strim(deg_diff(wangle, @body_heading), 10) else @turn_dir = (rand > 0.5) ? 10 : -10 end @turn_dur = 7 + (rand 12) @move_dur = @turn_dur + 5 + (rand 10) @turn_body = @turn_dir if ACC_WHILE_MOVING @acc_dur = rand 7 end elsif @turn_dur == 0 @move_dur -= 1 elsif @acc_dur == 0 @move_dur -= 1 @turn_dur -= 1 @turn_body = @turn_dir else @acc_dur -= 1 @move_dur -= 1 @turn_dur -= 1 @accelerate = -1 @turn_body = @turn_dir end end # }}} def sign(x) # {{{ return 0 if x == 0 return 1 if x > 1 return -1 end # }}} def dist_to_center # {{{ hypot(battlefield_height/2 - @y, battlefield_width/2 - @x) end # }}} def angle_to_center end def get_revangle_and_dist_wall return [[@x,0], [@y,270], [battlefield_width - @x, 180], [battlefield_height - @y, 90]].min.reverse end def approaching_center # {{{ angle = (atan2(@x, @y).to_deg + 90) % 360 diff = deg_diff(angle, @body_heading).abs diff < 80 end # }}} def deg_diff(ang1, ang2) # {{{ (ang1 - ang2 + 180) % 360 - 180 end # }}} def get_angle_and_dist(x,y) # {{{ dx = x - @x dy = y - @y return [(atan2(dx, dy).to_deg - 90) % 360, hypot(dx, dy)] end # }}} def predict(ticks, maxhist = 70) # {{{ i = 0 lx = 0.0 mx = 0.0 nx = 0.0 ox = 0.0 px = 0.0 ly = 0.0 my = 0.0 ny = 0.0 oy = 0.0 py = 0.0 @memory.enemypos.to_a.each_with_index do |ev, idx| next unless ev break if idx > maxhist break if i > 5 x, dx, y, dy = ev dx *= 1 + (idx / 50.to_f) ** 2 dy *= 1 + (idx / 50.to_f) ** 2 dx = 1.0 if dx < 1.0 dy = 1.0 if dy < 1.0 t = -idx-1 i += 1 sx = dx**2 lx += t**2/sx mx += t/sx nx += t*x/sx ox += x/sx px += 1/sx sy = dy**2 ly += t**2/sy my += t/sy ny += t*y/sy oy += y/sy py += 1/sy end return unless i >= 2 ax = (px*nx - mx*ox)/(px*lx - mx**2) bx = 1/px*(mx*ax-ox) ay = (py*ny - my*oy)/(py*ly - my**2) by = 1/py*(my*ay-oy) bx *= -1 by *= -1 factor = hypot(ax, ay)/8.0 if factor > 1 ax /= factor ay /= factor end bx = battlefield_width - size if bx > battlefield_width - size by = battlefield_width - size if by > battlefield_width - size bx = size if bx < size by = size if by < size px = bx+ax*ticks py = by+ay*ticks return if px.infinite? or px.nan? or py.infinite? or py.nan? px = [battlefield_width - size, [size, px].max].min py = [battlefield_height - size, [size, py].max].min [px, py] end # }}} def execute # {{{ @turn_turret -= @turn_body @turn_radar -= @turn_body + @turn_turret @turn_body = trim(-10, @turn_body, 10) @turn_turret = trim(-30, @turn_turret, 30) @turn_radar = trim(-60, @turn_radar, 60) @robot.accelerate(@accelerate) @robot.turn(@turn_body) @robot.turn_gun(@turn_turret) @robot.turn_radar(@turn_radar) @robot.fire(@power) end # }}} def save_memory # {{{ @memory.rheading << @radar_heading @memory.pos << [@x, @y] end # }}} end # }}} class Robot # {{{ include ::Robot def initialize @my_brain = Brain.new(self) end def tick(events) @my_brain.tick(events) end end # }}} end class RubberDuckLinear < RubberRobotLinear::Robot; end |
|
|
|
|
|||
|
|||
| Stefan Walk |
|
|
|
| |
![]() |
| Thread Tools | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| [QUIZ] Gathering Ruby Quiz 2 Data (#189) | Daniel Moore | Ruby | 10 | 01-31-2009 08:36 PM |
| [QUIZ] Newbie doubts about the quiz | Marcelo Alvim | Ruby | 15 | 08-16-2006 02:08 PM |
| [QUIZ] 1-800-THE-QUIZ (#20) | Ruby Quiz | Ruby | 15 | 02-24-2005 06:05 AM |
| [SOLUTION] Ruby Quiz #15 Animal Quiz | David Tran | Ruby | 9 | 01-21-2005 02:11 AM |
| [QUIZ] Animal Quiz (#15) | Ruby Quiz | Ruby | 11 | 01-18-2005 02:42 PM |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc..
SEO by vBSEO ©2010, Crawlability, Inc. |




