Forums | Admin

Discussion Forums: robots

Start New Thread Start New Thread

 

By: moxio ricody
RE: DuckBill [ reply ]  
2005-12-09 06:03
nice duck, busts up a bunch of my ducks!

By: sox box
DuckBill [ reply ]  
2005-12-09 04:52
Way to much code, but it does a good job of laying
down some lead. Also has an overly complicated turn/aim/scan block to facilitate 'turn to angle' type commands. Does pretty good against the other bots.

require 'robot'

class DuckBill
include Robot
Res = [2,4,8,16,32,60]
# ###########
# # Initialize
# ###########
def initialize bf
super(bf)
@outerlimit = battlefield_width + battlefield_height
@mode = 0 # mode of high level logic
@stage = 0 # sequences within mode
@dir = 0 # direction we are going
@walldir = 1 # dirrection we travel around perimeter in, 1 = ccw,-1=cw
@hit_filter = 0 #low pass filter tells how much damage we are taking
@sincehit = 100 #how long since we were hit
@sinceblip = 100 #how long since we saw someone in our radar
@since_evade = 0 #time since we took evasive action
@closest = 0 #distance to closest robot scanned since last tick
@range = 10000 #distance of closest robot
@turns = [0,0,0,0,0,0,0,0,0,0,0,0] # holds data for turn/aim calculations
end
# ###########
# # Controls
# ###########
def min(a,b)
(a < b)? a : b
end
def max(a,b)
(a > b)? a : b
end
#dir is 1 for ccw, -1 for cw, and 0 for whichever is quickest
def aimtank(angle,rate=10,dir=0)
@turns[0,3] = angle%360,rate,dir
angle%360 == heading
end
def aimgun(angle,rate=30,dir=0)
@turns[4,3] = angle%360,rate,dir
angle%360 == gun_heading
end
def aimrad(angle,rate=60,dir=0)
@turns[8,3] = angle%360,rate,dir
angle%360 == radar_heading
end
def doturns
#this translates directional commands from robot into motor actions
#turns: 0=desired heading, 1=max speed,2=dir[1=ccw,-1=cw,0=fastest],
# 3=computed turn, 0-3 for tank, 4-7 for gun, 8-11 for radar
#compute turns for tank, gun, and radar headings
#print "computed turns = #{@turns.inspect}\n"
ccw = (@turns[0] - heading) % 360
cw = 360 - ccw
dir = (@turns[2] == 0)? ((ccw<cw)? 1 : -1) : @turns[2]
@turns[3] = dir * min((dir==1)? ccw : cw,@turns[1])
ccw = (@turns[4] - @turns[3] - gun_heading) % 360
cw = 360 - ccw
dir = (@turns[6] == 0)? ((ccw<cw)? 1 : -1) : @turns[6]
@turns[7] = dir * min((dir==1)? ccw : cw,@turns[5])
ccw = (@turns[8] - @turns[7] - @turns[3] - radar_heading) % 360
cw = 360 - ccw
dir = (@turns[10] == 0)? ((ccw<cw)? 1 : -1) : @turns[10]
@turns[11] = dir * min(((dir==1)? ccw : cw),@turns[9])
#print "computed turns = #{@turns.inspect}\n"
turn @turns[3]
turn_gun @turns[7]
turn_radar @turns[11]
end

# ###########
# # TICK, the Robot code
# ###########
def tick events
#print "mode=#{@mode},stage=#{@stage},dir=#{@dir},walldir=#{@walldir}\n"
#mode nil is startup and initialize variables
#STDOUT.flush
# ###########
# # Sensors
# ###########
@since_evade += 1
@sincehit += 1
@sincehit = 0 if not events['got_hit'].empty?
events['got_hit'].each{|e| @hit_filter += e.first}
@hit_filter *= 0.99
if events['robot_scanned'].empty?
@sinceblip += 1
@closest = @outerlimit
#print"\n"
else
@closest = events['robot_scanned'].collect{|e| e.first}.sort.first
@sinceblip = 0
#print ",blip=#{@closest}\n"
end
# ###########
# # High level logic - state machine
# ###########
#print "sincehit=#{@sincehit},closest=#{@closest},range=#{@range}\n"
#mode 0 is orient tank
if @mode == 0
@stage = 0
@range = @outerlimit
b,c = aimgun(@dir*90),aimrad(@dir*90)
@mode = 1 if b and c
#mode 1 find range of nearest target
elsif @mode == 1
#setup radar for a scan
if @stage==0
aimrad(@dir*90 + 180,60,1)
@range = min(@range,@closest)
@stage +=1
#continue around for full circle
elsif @stage == 1
@range = min(@range,@closest)
if aimrad(@dir*90,60,1)
#did we see a bot?
if @range == @outerlimit
@stage = 0
else
@mode = 2
@stage = 0
end
end
end
aimgun(@dir*90)
#mode 2: find the nearestbot
elsif @mode == 2
#start next circle to re find the closest bot
if @stage == 0
#print "range is #{@range}\n"
aimrad(@dir*90 + 180,60,1)
@stage +=1
#continue scan for the closest bot
elsif @stage == 1
#print "dir=#{@dir},angle=#{radar_heading}, closest=#{@closest}\n"
if @closest < @range * 1.25
@range = @closest
@mode = 3
@stage = 0
@tangle = radar_heading
#print "found target at angle #{@tangle}\n"
#if we finished the scan, and didn't find close target, recompute range
elsif aimrad(@dir*90,60,1)
@mode = 0
@stage =0
end
end
aimgun(@dir*90 )
#mode 3 is tracking bot
elsif @mode == 3
#entry from previous mode, determine whether to scan ccw or cw
if @stage == 0
@trk_dir,@trk_res,@stage = -1,4,2
#first scan in this direction
elsif @stage == 1
if @closest < @range * 1.25
@range = @closest
@trk_dir = -@trk_dir /> @trk_res = max(@trk_res - 1,0)
else
@stage = 2
end
#second scan in this direction
elsif @stage == 2
if @closest < @range * 1.25
@range = @closest
@trk_dir =
-@trk_dir /> @trk_res = max(@trk_res - 1,0)
@stage = 1
else
@trk_dir =
-@trk_dir /> @trk_res = min(@trk_res + 2,4)
@stage = 3
end
#the target bot has moved out of our window, expand the window
elsif @stage == 3
if @closest < @range * 1.25
@range = @closest
@trk_dir = - @trk_dir
@trk_res = max(@trk_res - 2,0)
@stage = 1
elsif @trk_res < 5
@trk_dir = - @trk_dir
@trk_res = @trk_res +1
else
#we lost our target, reaquire from scratch
@mode = 0
@stage = 0
end
end
@tangle += Res[@trk_res] * @trk_dir
aimrad(@tangle)
aimgun(@tangle)
#print"tangle=#{@tangle}, res=#{Res[@trk_res]}, rot=#{@trk_dir}\n"
elsif @mode == 4
#determine which corner to go to
if @stage == 0
@stage += 1 if aimrad(@dir*90 + 95*@walldir)
#first scan in direction of prev corner
elsif @stage == 1
aimrad(@dir*90 + 60*@walldir)
@stage += 1
#save count of robots in next corner, and swing radar to previous corner
elsif @stage == 2
@prevCorner = events['robot_scanned'].size
aimrad(@dir*90 + 30*@walldir)
@stage += 1
elsif @stage == 3
aimrad(@dir*90 -5*@walldir)
@stage += 1
elsif @stage == 4
@nextCorner = events['robot_scanned'].size
#print "next corner=#{@nextCorner}, prev corner=#{@prevCorner}\n"
if @nextCorner > @prevCorner
@dir = (@dir + @walldir)%4
@walldir *= -1
end
@stage = 0
@mode = 0
end
aimgun(@dir*90)
end
#compute the distances to the four walls
walls = [battlefield_width - x,y,x,battlefield_height - y]
#hug the wall, if we are slightly off the wall, than move back to the wall
toleftwall,torightwall = walls[(@dir+1)%4],walls[(@dir-1)%4]
#print "wallroom left=#{toleftwall}, right=#{torightwall}\n"
if toleftwall > 80 and toleftwall < 200
aimtank(@dir * 90 + 20)
elsif torightwall > 80 and torightwall < 200
aimtank(@dir * 90 - 20)
else
aimtank(@dir * 90)
end
#If we reach a corner or wall, turn towards farthest corner on this wall
if walls[@dir] < 100
if toleftwall > torightwall
@walldir = 1 #we are now going ccw
@dir = (@dir+1)%4 # turn ccw
#print "turn left\n"
else
@walldir = -1 #we are now going cw
@dir = (@dir-1)%4 #turn cw
#print "turn right\n"
end
#don't check corners at T junction
if toleftwall > 100 and torightwall > 100
@mode = 0 # follow through with turn
@stage = 0
else
@mode = 4 # determin if previous corner was safer
@stage = 0
end
#If we are getting hammered, turn now to evade damage
# once we evade, avoid making another evasive manuver or we will turn in circles
elsif @hit_filter > 400 and @since_evade > 100
@dir = (@dir+@walldir)%4
@hit_filter = 0
@since_evade = 0
end
accelerate 1
fire 0.1
doturns #we already computed our turns, now execute them
STDOUT.flush
end
end