UG_RRobots 1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/rrobots +202 -0
- data/bin/tournament +413 -0
- data/config/rrobots.yml +15 -0
- data/contribs/allbots.rb +0 -0
- data/doc/manual.rdoc +126 -0
- data/doc/manual_fr.rdoc +129 -0
- data/images/explosion00.gif +0 -0
- data/images/explosion01.gif +0 -0
- data/images/explosion02.gif +0 -0
- data/images/explosion03.gif +0 -0
- data/images/explosion04.gif +0 -0
- data/images/explosion05.gif +0 -0
- data/images/explosion06.gif +0 -0
- data/images/explosion07.gif +0 -0
- data/images/explosion08.gif +0 -0
- data/images/explosion09.gif +0 -0
- data/images/explosion10.gif +0 -0
- data/images/explosion11.gif +0 -0
- data/images/explosion12.gif +0 -0
- data/images/explosion13.gif +0 -0
- data/images/explosion14.gif +0 -0
- data/images/red_body000.gif +0 -0
- data/images/red_body010.gif +0 -0
- data/images/red_body020.gif +0 -0
- data/images/red_body030.gif +0 -0
- data/images/red_body040.gif +0 -0
- data/images/red_body050.gif +0 -0
- data/images/red_body060.gif +0 -0
- data/images/red_body070.gif +0 -0
- data/images/red_body080.gif +0 -0
- data/images/red_body090.gif +0 -0
- data/images/red_body100.gif +0 -0
- data/images/red_body110.gif +0 -0
- data/images/red_body120.gif +0 -0
- data/images/red_body130.gif +0 -0
- data/images/red_body140.gif +0 -0
- data/images/red_body150.gif +0 -0
- data/images/red_body160.gif +0 -0
- data/images/red_body170.gif +0 -0
- data/images/red_body180.gif +0 -0
- data/images/red_body190.gif +0 -0
- data/images/red_body200.gif +0 -0
- data/images/red_body210.gif +0 -0
- data/images/red_body220.gif +0 -0
- data/images/red_body230.gif +0 -0
- data/images/red_body240.gif +0 -0
- data/images/red_body250.gif +0 -0
- data/images/red_body260.gif +0 -0
- data/images/red_body270.gif +0 -0
- data/images/red_body280.gif +0 -0
- data/images/red_body290.gif +0 -0
- data/images/red_body300.gif +0 -0
- data/images/red_body310.gif +0 -0
- data/images/red_body320.gif +0 -0
- data/images/red_body330.gif +0 -0
- data/images/red_body340.gif +0 -0
- data/images/red_body350.gif +0 -0
- data/images/red_radar000.gif +0 -0
- data/images/red_radar010.gif +0 -0
- data/images/red_radar020.gif +0 -0
- data/images/red_radar030.gif +0 -0
- data/images/red_radar040.gif +0 -0
- data/images/red_radar050.gif +0 -0
- data/images/red_radar060.gif +0 -0
- data/images/red_radar070.gif +0 -0
- data/images/red_radar080.gif +0 -0
- data/images/red_radar090.gif +0 -0
- data/images/red_radar100.gif +0 -0
- data/images/red_radar110.gif +0 -0
- data/images/red_radar120.gif +0 -0
- data/images/red_radar130.gif +0 -0
- data/images/red_radar140.gif +0 -0
- data/images/red_radar150.gif +0 -0
- data/images/red_radar160.gif +0 -0
- data/images/red_radar170.gif +0 -0
- data/images/red_radar180.gif +0 -0
- data/images/red_radar190.gif +0 -0
- data/images/red_radar200.gif +0 -0
- data/images/red_radar210.gif +0 -0
- data/images/red_radar220.gif +0 -0
- data/images/red_radar230.gif +0 -0
- data/images/red_radar240.gif +0 -0
- data/images/red_radar250.gif +0 -0
- data/images/red_radar260.gif +0 -0
- data/images/red_radar270.gif +0 -0
- data/images/red_radar280.gif +0 -0
- data/images/red_radar290.gif +0 -0
- data/images/red_radar300.gif +0 -0
- data/images/red_radar310.gif +0 -0
- data/images/red_radar320.gif +0 -0
- data/images/red_radar330.gif +0 -0
- data/images/red_radar340.gif +0 -0
- data/images/red_radar350.gif +0 -0
- data/images/red_turret000.gif +0 -0
- data/images/red_turret010.gif +0 -0
- data/images/red_turret020.gif +0 -0
- data/images/red_turret030.gif +0 -0
- data/images/red_turret040.gif +0 -0
- data/images/red_turret050.gif +0 -0
- data/images/red_turret060.gif +0 -0
- data/images/red_turret070.gif +0 -0
- data/images/red_turret080.gif +0 -0
- data/images/red_turret090.gif +0 -0
- data/images/red_turret100.gif +0 -0
- data/images/red_turret110.gif +0 -0
- data/images/red_turret120.gif +0 -0
- data/images/red_turret130.gif +0 -0
- data/images/red_turret140.gif +0 -0
- data/images/red_turret150.gif +0 -0
- data/images/red_turret160.gif +0 -0
- data/images/red_turret170.gif +0 -0
- data/images/red_turret180.gif +0 -0
- data/images/red_turret190.gif +0 -0
- data/images/red_turret200.gif +0 -0
- data/images/red_turret210.gif +0 -0
- data/images/red_turret220.gif +0 -0
- data/images/red_turret230.gif +0 -0
- data/images/red_turret240.gif +0 -0
- data/images/red_turret250.gif +0 -0
- data/images/red_turret260.gif +0 -0
- data/images/red_turret270.gif +0 -0
- data/images/red_turret280.gif +0 -0
- data/images/red_turret290.gif +0 -0
- data/images/red_turret300.gif +0 -0
- data/images/red_turret310.gif +0 -0
- data/images/red_turret320.gif +0 -0
- data/images/red_turret330.gif +0 -0
- data/images/red_turret340.gif +0 -0
- data/images/red_turret350.gif +0 -0
- data/images/toolbox.gif +0 -0
- data/lib/battlefield.rb +102 -0
- data/lib/bullets.rb +39 -0
- data/lib/configuration.rb +26 -0
- data/lib/explosions.rb +20 -0
- data/lib/overloads.rb +10 -0
- data/lib/robot.rb +122 -0
- data/lib/robotrunner.rb +260 -0
- data/lib/tkarena.rb +197 -0
- data/lib/toolboxes.rb +28 -0
- data/robots/BillDuck.rb +92 -0
- data/robots/BotOne.rb +39 -0
- data/robots/DuckBill.rb +384 -0
- data/robots/DuckBill04.rb +330 -0
- data/robots/DuckToEndAllDucks.rb +140 -0
- data/robots/EdgeBot.rb +203 -0
- data/robots/HuntingDuck.rb +74 -0
- data/robots/HyperactiveDuck.rb +15 -0
- data/robots/Killer.rb +58 -0
- data/robots/Kite.rb +193 -0
- data/robots/KoDuck.rb +57 -0
- data/robots/LinearShooter.rb +279 -0
- data/robots/LuckyDuck.rb +83 -0
- data/robots/MoxonoM.rb +85 -0
- data/robots/MsgBot.rb +13 -0
- data/robots/NervousDuck.rb +13 -0
- data/robots/Polisher.rb +15 -0
- data/robots/RomBot.rb +514 -0
- data/robots/RoomPainter.rb +205 -0
- data/robots/Rrrkele.rb +48 -0
- data/robots/Seeker.rb +57 -0
- data/robots/ShootingStation.rb +15 -0
- data/robots/SittingDuck.rb +18 -0
- data/robots/SniperDuck.rb +277 -0
- data/robots/WallPainter.rb +224 -0
- metadata +220 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
require 'robot'
|
|
2
|
+
|
|
3
|
+
class DuckBill04
|
|
4
|
+
include Robot
|
|
5
|
+
# ###########
|
|
6
|
+
# # Initialize
|
|
7
|
+
# ###########
|
|
8
|
+
def initialize *bf
|
|
9
|
+
super(bf[0]) if bf.size != 0
|
|
10
|
+
super if bf.size == 0
|
|
11
|
+
@ScanRes = [1,2,4,8,16,32,60]
|
|
12
|
+
@mode = 0 # mode of high level logic
|
|
13
|
+
@stage = 0 # sequences within mode
|
|
14
|
+
@dir = 0 # direction we are going
|
|
15
|
+
@walldir = 1 # dirrection we travel around perimeter in, 1 = ccw,-1=cw
|
|
16
|
+
@hit_filter = 0 #low pass filter tells how much damage we are taking
|
|
17
|
+
@sincehit = 100 #how long since we were hit
|
|
18
|
+
@sinceblip = 100 #how long since we saw someone in our radar
|
|
19
|
+
@time_sync = 0 #time since we took evasive action
|
|
20
|
+
@sinceturn = 0
|
|
21
|
+
@closest = 0 #distance to closest robot scanned since last tick
|
|
22
|
+
@range = 10000 #distance of closest robot
|
|
23
|
+
@tangle = 0
|
|
24
|
+
@radar_old = 0
|
|
25
|
+
@mytrack = Tracking.new(battlefield_width,battlefield_height)
|
|
26
|
+
@turns = [0,0,0,0,0,0,0,0,0,0,0,0] # holds data for turn/aim calculations
|
|
27
|
+
@duckdbg = false
|
|
28
|
+
end
|
|
29
|
+
def debug(a)
|
|
30
|
+
print a if @duckdbg
|
|
31
|
+
STDOUT.flush if @duckdbg
|
|
32
|
+
end
|
|
33
|
+
# ###########
|
|
34
|
+
# # Controls
|
|
35
|
+
# ###########
|
|
36
|
+
def min(a,b)
|
|
37
|
+
(a < b)? a : b
|
|
38
|
+
end
|
|
39
|
+
def max(a,b)
|
|
40
|
+
(a > b)? a : b
|
|
41
|
+
end
|
|
42
|
+
#dir is 1 for ccw, -1 for cw, and 0 for whichever is quickest
|
|
43
|
+
def aimtank(angle,rate=10,dir=0)
|
|
44
|
+
@turns[0,3] = angle%360,rate,dir
|
|
45
|
+
angle%360 == heading
|
|
46
|
+
end
|
|
47
|
+
def aimgun(angle,rate=30,dir=0)
|
|
48
|
+
@turns[4,3] = angle%360,rate,dir
|
|
49
|
+
angle%360 == gun_heading
|
|
50
|
+
end
|
|
51
|
+
def aimrad(angle,rate=60,dir=0)
|
|
52
|
+
@turns[8,3] = angle%360,rate,dir
|
|
53
|
+
angle%360 == radar_heading
|
|
54
|
+
end
|
|
55
|
+
def doturns
|
|
56
|
+
#this translates directional commands from robot into motor actions
|
|
57
|
+
#turns: 0=desired heading, 1=max speed,2=dir[1=ccw,-1=cw,0=fastest],
|
|
58
|
+
# 3=computed turn, 0-3 for tank, 4-7 for gun, 8-11 for radar
|
|
59
|
+
#compute turns for tank, gun, and radar headings
|
|
60
|
+
#print "computed turns = #{@turns.inspect}\n"
|
|
61
|
+
ccw = (@turns[0] - heading) % 360
|
|
62
|
+
cw = 360 - ccw
|
|
63
|
+
dir = (@turns[2] == 0)? ((ccw<cw)? 1 : -1) : @turns[2]
|
|
64
|
+
@turns[3] = dir * min((dir==1)? ccw : cw,@turns[1])
|
|
65
|
+
ccw = (@turns[4] - @turns[3] - gun_heading) % 360
|
|
66
|
+
cw = 360 - ccw
|
|
67
|
+
dir = (@turns[6] == 0)? ((ccw<cw)? 1 : -1) : @turns[6]
|
|
68
|
+
@turns[7] = dir * min((dir==1)? ccw : cw,@turns[5])
|
|
69
|
+
ccw = (@turns[8] - @turns[7] - @turns[3] - radar_heading) % 360
|
|
70
|
+
cw = 360 - ccw
|
|
71
|
+
dir = (@turns[10] == 0)? ((ccw<cw)? 1 : -1) : @turns[10]
|
|
72
|
+
@turns[11] = dir * min(((dir==1)? ccw : cw),@turns[9])
|
|
73
|
+
#print "computed turns = #{@turns.inspect}\n"
|
|
74
|
+
turn @turns[3]
|
|
75
|
+
turn_gun @turns[7]
|
|
76
|
+
turn_radar @turns[11]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# ###########
|
|
80
|
+
# # TICK, the Robot code
|
|
81
|
+
# ###########
|
|
82
|
+
def tick events
|
|
83
|
+
@outerlimit = (battlefield_width + battlefield_height)*2
|
|
84
|
+
debug "\nmode=#{@mode},stage=#{@stage},dir=#{@dir},walldir=#{@walldir}\n"
|
|
85
|
+
debug "at (#{x},#{y}) at #{time}, radar=#{radar_heading}, gun=#{gun_heading}\n"
|
|
86
|
+
debug "trk_dir=#{@trk_dir}, trk_res=#{@trk_res},range=#{@range}\n"
|
|
87
|
+
#mode nil is startup and initialize variables
|
|
88
|
+
#STDOUT.flush
|
|
89
|
+
# ###########
|
|
90
|
+
# # Sensors
|
|
91
|
+
# ###########
|
|
92
|
+
raddif = (radar_heading - @radar_old)%360
|
|
93
|
+
raddif = 360 -raddif if raddif >= 180
|
|
94
|
+
@radave = (radar_heading + raddif/2.0)%360
|
|
95
|
+
@sincehit += 1
|
|
96
|
+
@sinceturn += 1
|
|
97
|
+
@sincehit = 0 if not events['got_hit'].empty?
|
|
98
|
+
events['got_hit'].each{|e| @hit_filter += e.first}
|
|
99
|
+
@hit_filter *= 0.99
|
|
100
|
+
if events['robot_scanned'].empty?
|
|
101
|
+
@sinceblip += 1
|
|
102
|
+
@closest = @outerlimit
|
|
103
|
+
#print"\n"
|
|
104
|
+
else
|
|
105
|
+
@closest = events['robot_scanned'].collect{|e| e.first}.sort.first
|
|
106
|
+
@sinceblip = 0
|
|
107
|
+
debug ",blip=#{@closest} sweep=(#{@radar_old},#{radar_heading})\n"
|
|
108
|
+
end
|
|
109
|
+
# ###########
|
|
110
|
+
# # High level logic - state machine
|
|
111
|
+
# ###########
|
|
112
|
+
#print "sincehit=#{@sincehit},closest=#{@closest},range=#{@range}\n"
|
|
113
|
+
#mode 0 is orient tank
|
|
114
|
+
if @mode == 0
|
|
115
|
+
@stage = 0
|
|
116
|
+
@range = @outerlimit
|
|
117
|
+
@mode = 1 if aimrad(@dir*90)
|
|
118
|
+
#mode 1 find range of nearest target
|
|
119
|
+
elsif @mode == 1
|
|
120
|
+
#setup radar for a scan
|
|
121
|
+
if @stage==0
|
|
122
|
+
aimrad(@dir*90 + 180,60,@walldir)
|
|
123
|
+
@range = min(@range,@closest)
|
|
124
|
+
@stage +=1
|
|
125
|
+
#continue around for full circle
|
|
126
|
+
elsif @stage == 1
|
|
127
|
+
@range = min(@range,@closest)
|
|
128
|
+
if aimrad(@dir*90,60,@walldir)
|
|
129
|
+
#did we see a bot?
|
|
130
|
+
if @range == @outerlimit
|
|
131
|
+
@stage = 0
|
|
132
|
+
else
|
|
133
|
+
@mode = 2
|
|
134
|
+
@stage = 0
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
#mode 2: find the nearestbot
|
|
139
|
+
elsif @mode == 2
|
|
140
|
+
#start next circle to re find the closest bot
|
|
141
|
+
if @stage == 0
|
|
142
|
+
#print "range is #{@range}\n"
|
|
143
|
+
aimrad(@dir*90 + 180,60,@walldir)
|
|
144
|
+
@stage +=1
|
|
145
|
+
#continue scan for the closest bot
|
|
146
|
+
elsif @stage == 1
|
|
147
|
+
#print "dir=#{@dir},angle=#{radar_heading}, closest=#{@closest}\n"
|
|
148
|
+
if @closest < @range * 1.25
|
|
149
|
+
@range = @closest
|
|
150
|
+
@mode = 3
|
|
151
|
+
@stage = 1
|
|
152
|
+
@tangle = radar_heading
|
|
153
|
+
@trk_dir,@trk_res = -@walldir,5
|
|
154
|
+
@tangle += @ScanRes[@trk_res] * @trk_dir
|
|
155
|
+
aimrad(@tangle)
|
|
156
|
+
debug "found target at angle #{@tangle}\n"
|
|
157
|
+
#if we finished the scan, and didn't find close target, recompute range
|
|
158
|
+
elsif aimrad(@dir*90,60,@walldir)
|
|
159
|
+
@mode = 0
|
|
160
|
+
@stage =0
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
#mode 3 is tracking bot
|
|
164
|
+
elsif @mode == 3
|
|
165
|
+
#entry from previous mode, determine whether to scan ccw or cw
|
|
166
|
+
if @stage == 0
|
|
167
|
+
@trk_dir,@trk_res,@stage = -1,4,2
|
|
168
|
+
#first scan in this direction
|
|
169
|
+
elsif @stage == 1
|
|
170
|
+
if @closest < @range * 1.25
|
|
171
|
+
@range = @closest
|
|
172
|
+
@trk_dir = -@trk_dir
|
|
173
|
+
@trk_res = max(@trk_res - 1,0)
|
|
174
|
+
@mytrack.add(x,y,@radave, @range , time) if @trk_res < 3
|
|
175
|
+
else
|
|
176
|
+
@stage = 2
|
|
177
|
+
end
|
|
178
|
+
#second scan in this direction
|
|
179
|
+
elsif @stage == 2
|
|
180
|
+
if @closest < @range * 1.25
|
|
181
|
+
@range = @closest
|
|
182
|
+
@trk_dir = -@trk_dir
|
|
183
|
+
@trk_res = max(@trk_res - 1,0)
|
|
184
|
+
@mytrack.add(x,y,@radave, @range , time) if @trk_res < 3
|
|
185
|
+
@stage = 1
|
|
186
|
+
else
|
|
187
|
+
@trk_dir = -@trk_dir
|
|
188
|
+
@trk_res = min(@trk_res + 2,4)
|
|
189
|
+
@stage = 3
|
|
190
|
+
end
|
|
191
|
+
#the target bot has moved out of our window, expand the window
|
|
192
|
+
elsif @stage == 3
|
|
193
|
+
if @closest < @range * 1.25
|
|
194
|
+
@range = @closest
|
|
195
|
+
@trk_dir = - @trk_dir
|
|
196
|
+
@trk_res = max(@trk_res - 2,0)
|
|
197
|
+
@mytrack.add(x,y,@radave, @range , time) if @trk_res < 3
|
|
198
|
+
@stage = 1
|
|
199
|
+
elsif @trk_res < 6
|
|
200
|
+
@trk_dir = - @trk_dir
|
|
201
|
+
@trk_res = @trk_res +1
|
|
202
|
+
else
|
|
203
|
+
#we lost our target, reaquire from scratch
|
|
204
|
+
@mode = 0
|
|
205
|
+
@stage = 0
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
@tangle += @ScanRes[@trk_res] * @trk_dir
|
|
209
|
+
aimrad(@tangle)
|
|
210
|
+
#print"tangle=#{@tangle}, res=#{@ScanRes[@trk_res]}, rot=#{@trk_dir}\n"
|
|
211
|
+
end
|
|
212
|
+
#compute the distances to the four walls
|
|
213
|
+
walls = [battlefield_width - x,y,x,battlefield_height - y]
|
|
214
|
+
toleftwall,torightwall = walls[(@dir+1)%4],walls[(@dir-1)%4]
|
|
215
|
+
#debug "wallroom left=#{toleftwall}, right=#{torightwall}\n"
|
|
216
|
+
if walls.sort.first < 100 and @sinceturn > 30
|
|
217
|
+
if walls.sort[1] < 300
|
|
218
|
+
@dir = walls.index(walls.sort.first)
|
|
219
|
+
aimtank((@dir * 90 + 180)%360)
|
|
220
|
+
else
|
|
221
|
+
aimtank((heading + 180)%360)
|
|
222
|
+
end
|
|
223
|
+
@walldir *= -1
|
|
224
|
+
@sinceturn = 0
|
|
225
|
+
else
|
|
226
|
+
if @range > 800
|
|
227
|
+
aimtank((@tangle + @walldir* 70)%360)
|
|
228
|
+
elsif @range <600
|
|
229
|
+
aimtank((@tangle + @walldir* 110)%360)
|
|
230
|
+
else
|
|
231
|
+
aimtank((@tangle + @walldir* 90)%360)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
debug "time=#{time}, time_sync=#{@time_sync},mod=#{(time+@time_sync)%20}\n"
|
|
235
|
+
if (time+@time_sync) % 20 < 10
|
|
236
|
+
stop
|
|
237
|
+
else
|
|
238
|
+
accelerate 1
|
|
239
|
+
end
|
|
240
|
+
@time_sync = 25 - time%20 if @sincehit == 0
|
|
241
|
+
aim = @mytrack.predict(x,y,time) || (@dir * 90)%360
|
|
242
|
+
aimgun(aim)
|
|
243
|
+
fire 0.1
|
|
244
|
+
doturns #we already computed our turns, now execute them
|
|
245
|
+
@radar_old = radar_heading
|
|
246
|
+
STDOUT.flush
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
class Tracking
|
|
250
|
+
def debug(a)
|
|
251
|
+
print a if @trkdbg
|
|
252
|
+
STDOUT.flush if @trkdbg
|
|
253
|
+
end
|
|
254
|
+
def initialize(width,height)
|
|
255
|
+
@trkdbg = false
|
|
256
|
+
@tracking = []
|
|
257
|
+
@width = width
|
|
258
|
+
@height = height
|
|
259
|
+
end
|
|
260
|
+
def add(x,y,angle,dist,time)
|
|
261
|
+
@tracking << [x + Math::cos(angle.to_rad)*dist,y - Math::sin(angle.to_rad)*dist,time]
|
|
262
|
+
debug "added track angle=#{angle},dist=#{dist},#{@tracking.last.inspect}\n"
|
|
263
|
+
end
|
|
264
|
+
def trim(time)
|
|
265
|
+
#delete really old samples
|
|
266
|
+
@tracking.delete_if{|e| time - e[2] > 30}
|
|
267
|
+
#limit to 10 samples
|
|
268
|
+
@tracking.shift while @tracking.size>10
|
|
269
|
+
#eliminate samples if they came from a different robot. we can tell this because they have max speed of 8
|
|
270
|
+
gap = 0
|
|
271
|
+
(@tracking.size- 1).times{|i|
|
|
272
|
+
if (v=velocity(@tracking[i],@tracking[i+1])) > 40
|
|
273
|
+
gap = i+1
|
|
274
|
+
debug "traking gap #{@tracking[i].inspect},#{@tracking[i+1].inspect},v=#{v}\n"
|
|
275
|
+
end
|
|
276
|
+
}
|
|
277
|
+
gap.times{@tracking.shift}
|
|
278
|
+
#normalize the time
|
|
279
|
+
#@tracking.size.times{|i| @tracking[@tracking.size-1-i][2] -=@tracking[0][2]}
|
|
280
|
+
end
|
|
281
|
+
def velocity (e1,e2)
|
|
282
|
+
distance(e1[0],e1[1],e2[0],e2[1])/(e1[2]-e2[2]).abs
|
|
283
|
+
end
|
|
284
|
+
def distance (x1,y1,x2,y2)
|
|
285
|
+
((x1-x2)**2 + (y1-y2)**2)**(0.5)
|
|
286
|
+
end
|
|
287
|
+
def findline
|
|
288
|
+
sx=sy=st=sxt=syt=stt=0.0
|
|
289
|
+
@tracking.each{|e|
|
|
290
|
+
debug " findline element = #{e.inspect}\n"
|
|
291
|
+
sx += e[0]
|
|
292
|
+
sxt += e[2]*e[0]
|
|
293
|
+
sy += e[1]
|
|
294
|
+
syt += e[2]*e[1]
|
|
295
|
+
st += e[2]
|
|
296
|
+
stt += e[2]*e[2]
|
|
297
|
+
}
|
|
298
|
+
n=@tracking.size
|
|
299
|
+
c2 = (sxt/st-sx/n)/(stt/st-st/n)
|
|
300
|
+
c1 = sx/n-(st/n)*c2
|
|
301
|
+
f2 = (syt/st-sy/n)/(stt/st-st/n)
|
|
302
|
+
f1 = sy/n-(st/n)*f2
|
|
303
|
+
debug "x = #{c2}t + #{c1}\n"
|
|
304
|
+
debug "y = #{f2}t + #{f1}\n"
|
|
305
|
+
[c2,c1,f2,f1]
|
|
306
|
+
end
|
|
307
|
+
def predict(x,y,time)
|
|
308
|
+
trim(time)
|
|
309
|
+
if @tracking.size < 1
|
|
310
|
+
return false
|
|
311
|
+
elsif @tracking.size == 1
|
|
312
|
+
interceptx,intercepty = @tracking[0][0],@tracking[0][1]
|
|
313
|
+
else
|
|
314
|
+
a,b,c,d = findline
|
|
315
|
+
intercepttime = time + distance(a*time+b,c*time+d,x,y)/30.0
|
|
316
|
+
#interceptx,intercepty = limitcoord(intercepttime*a + b, intercepttime*c+d)
|
|
317
|
+
interceptx,intercepty = intercepttime*a + b, intercepttime*c+d
|
|
318
|
+
end
|
|
319
|
+
debug"intercept at (#{interceptx},#{intercepty},#{intercepttime})\n"
|
|
320
|
+
angle = (Math.atan2(y - intercepty,interceptx - x) * 180 / Math::PI)%360
|
|
321
|
+
debug "firing angle is #{angle}\n"
|
|
322
|
+
angle
|
|
323
|
+
end
|
|
324
|
+
def limitcoord(x,y)
|
|
325
|
+
nx=[x,0.0].max
|
|
326
|
+
nx = [nx,@width.to_f].min
|
|
327
|
+
ny = [ny,@height.to_f].min
|
|
328
|
+
[nx,ny]
|
|
329
|
+
end
|
|
330
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
require 'robot'
|
|
2
|
+
|
|
3
|
+
class DuckToEndAllDucks
|
|
4
|
+
include Robot
|
|
5
|
+
|
|
6
|
+
def tick events
|
|
7
|
+
accelerate 1 if velocity < 7
|
|
8
|
+
if close_to_edge
|
|
9
|
+
turn_towards_quadrant get_other_quadrant
|
|
10
|
+
end
|
|
11
|
+
@post_hit_turn ||= 0
|
|
12
|
+
if !events['got_hit'].empty?
|
|
13
|
+
@post_hit_turn = 10
|
|
14
|
+
end
|
|
15
|
+
if @post_hit_turn > 0
|
|
16
|
+
if @post_hit_turn < 70
|
|
17
|
+
turn 10
|
|
18
|
+
@post_hit_turn += 10
|
|
19
|
+
else
|
|
20
|
+
@post_hit_turn = 0
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
@gun_turn_back ||= 50
|
|
25
|
+
@robot_sighted ||= 0
|
|
26
|
+
@fire_in_ticks ||= 2
|
|
27
|
+
if !events['robot_scanned'].empty? and @gun_turn_back > 40
|
|
28
|
+
@robot_sighted = radar_heading
|
|
29
|
+
@turnstep = -5
|
|
30
|
+
@gun_turn_back = 10
|
|
31
|
+
@distance = events['robot_scanned'][0][0]
|
|
32
|
+
if @distance < 500 then fire 3 end
|
|
33
|
+
else
|
|
34
|
+
if @gun_turn_back == 20
|
|
35
|
+
turn_gun @turnstep
|
|
36
|
+
@gun_turn_back += 10
|
|
37
|
+
if @distance < 500
|
|
38
|
+
fire 3
|
|
39
|
+
else
|
|
40
|
+
fire 1
|
|
41
|
+
end
|
|
42
|
+
elsif @gun_turn_back <= 40
|
|
43
|
+
turn_gun @turnstep
|
|
44
|
+
@gun_turn_back += 10
|
|
45
|
+
else
|
|
46
|
+
turn_gun 10
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def close_to_edge
|
|
53
|
+
margins = [x, (x - battlefield_width).abs, y, (y - battlefield_height).abs]
|
|
54
|
+
true if margins.min < 200
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def get_other_quadrant
|
|
58
|
+
other = quadrant
|
|
59
|
+
until other != quadrant do
|
|
60
|
+
other = (rand * 4).to_i
|
|
61
|
+
end
|
|
62
|
+
other
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Return 1, 2, 3, 4 depending on which quadrant of the battlefield the robot is in
|
|
66
|
+
# -----
|
|
67
|
+
# |1 2|
|
|
68
|
+
# |3 4|
|
|
69
|
+
# -----
|
|
70
|
+
def quadrant
|
|
71
|
+
left = x < battlefield_width / 2
|
|
72
|
+
right = !left
|
|
73
|
+
top = y < battlefield_height / 2
|
|
74
|
+
bottom = !top
|
|
75
|
+
if left and top
|
|
76
|
+
1
|
|
77
|
+
elsif right and top
|
|
78
|
+
2
|
|
79
|
+
elsif left and bottom
|
|
80
|
+
3
|
|
81
|
+
else
|
|
82
|
+
4
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def simple_heading
|
|
87
|
+
if (heading <= 90)
|
|
88
|
+
"ne"
|
|
89
|
+
elsif (heading > 90) and (heading <= 180)
|
|
90
|
+
"nw"
|
|
91
|
+
elsif (heading > 180) and (heading <= 270)
|
|
92
|
+
"sw"
|
|
93
|
+
else
|
|
94
|
+
"se"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def turn_towards_quadrant(target_quadrant)
|
|
99
|
+
case quadrant
|
|
100
|
+
when 1
|
|
101
|
+
case target_quadrant
|
|
102
|
+
when 2
|
|
103
|
+
if simple_heading != "ne" then turn 20 end
|
|
104
|
+
when 3
|
|
105
|
+
if simple_heading != "sw" then turn 20 end
|
|
106
|
+
when 4
|
|
107
|
+
if simple_heading != "se" then turn 20 end
|
|
108
|
+
end
|
|
109
|
+
when 2
|
|
110
|
+
case target_quadrant
|
|
111
|
+
when 1
|
|
112
|
+
if simple_heading != "nw" then turn 20 end
|
|
113
|
+
when 3
|
|
114
|
+
if simple_heading != "sw" then turn 20 end
|
|
115
|
+
when 4
|
|
116
|
+
if simple_heading != "se" then turn 20 end
|
|
117
|
+
end
|
|
118
|
+
when 3
|
|
119
|
+
case target_quadrant
|
|
120
|
+
when 1
|
|
121
|
+
if simple_heading != "nw" then turn 20 end
|
|
122
|
+
when 2
|
|
123
|
+
if simple_heading != "ne" then turn 20 end
|
|
124
|
+
when 4
|
|
125
|
+
if simple_heading != "se" then turn 20 end
|
|
126
|
+
end
|
|
127
|
+
when 4
|
|
128
|
+
case target_quadrant
|
|
129
|
+
when 1
|
|
130
|
+
if simple_heading != "nw" then turn 20 end
|
|
131
|
+
when 2
|
|
132
|
+
if simple_heading != "ne" then turn 20 end
|
|
133
|
+
when 3
|
|
134
|
+
if simple_heading != "sw" then turn 20 end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
|