UG_RRobots 1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|