UG_RRobots 1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. data/bin/rrobots +202 -0
  2. data/bin/tournament +413 -0
  3. data/config/rrobots.yml +15 -0
  4. data/contribs/allbots.rb +0 -0
  5. data/doc/manual.rdoc +126 -0
  6. data/doc/manual_fr.rdoc +129 -0
  7. data/images/explosion00.gif +0 -0
  8. data/images/explosion01.gif +0 -0
  9. data/images/explosion02.gif +0 -0
  10. data/images/explosion03.gif +0 -0
  11. data/images/explosion04.gif +0 -0
  12. data/images/explosion05.gif +0 -0
  13. data/images/explosion06.gif +0 -0
  14. data/images/explosion07.gif +0 -0
  15. data/images/explosion08.gif +0 -0
  16. data/images/explosion09.gif +0 -0
  17. data/images/explosion10.gif +0 -0
  18. data/images/explosion11.gif +0 -0
  19. data/images/explosion12.gif +0 -0
  20. data/images/explosion13.gif +0 -0
  21. data/images/explosion14.gif +0 -0
  22. data/images/red_body000.gif +0 -0
  23. data/images/red_body010.gif +0 -0
  24. data/images/red_body020.gif +0 -0
  25. data/images/red_body030.gif +0 -0
  26. data/images/red_body040.gif +0 -0
  27. data/images/red_body050.gif +0 -0
  28. data/images/red_body060.gif +0 -0
  29. data/images/red_body070.gif +0 -0
  30. data/images/red_body080.gif +0 -0
  31. data/images/red_body090.gif +0 -0
  32. data/images/red_body100.gif +0 -0
  33. data/images/red_body110.gif +0 -0
  34. data/images/red_body120.gif +0 -0
  35. data/images/red_body130.gif +0 -0
  36. data/images/red_body140.gif +0 -0
  37. data/images/red_body150.gif +0 -0
  38. data/images/red_body160.gif +0 -0
  39. data/images/red_body170.gif +0 -0
  40. data/images/red_body180.gif +0 -0
  41. data/images/red_body190.gif +0 -0
  42. data/images/red_body200.gif +0 -0
  43. data/images/red_body210.gif +0 -0
  44. data/images/red_body220.gif +0 -0
  45. data/images/red_body230.gif +0 -0
  46. data/images/red_body240.gif +0 -0
  47. data/images/red_body250.gif +0 -0
  48. data/images/red_body260.gif +0 -0
  49. data/images/red_body270.gif +0 -0
  50. data/images/red_body280.gif +0 -0
  51. data/images/red_body290.gif +0 -0
  52. data/images/red_body300.gif +0 -0
  53. data/images/red_body310.gif +0 -0
  54. data/images/red_body320.gif +0 -0
  55. data/images/red_body330.gif +0 -0
  56. data/images/red_body340.gif +0 -0
  57. data/images/red_body350.gif +0 -0
  58. data/images/red_radar000.gif +0 -0
  59. data/images/red_radar010.gif +0 -0
  60. data/images/red_radar020.gif +0 -0
  61. data/images/red_radar030.gif +0 -0
  62. data/images/red_radar040.gif +0 -0
  63. data/images/red_radar050.gif +0 -0
  64. data/images/red_radar060.gif +0 -0
  65. data/images/red_radar070.gif +0 -0
  66. data/images/red_radar080.gif +0 -0
  67. data/images/red_radar090.gif +0 -0
  68. data/images/red_radar100.gif +0 -0
  69. data/images/red_radar110.gif +0 -0
  70. data/images/red_radar120.gif +0 -0
  71. data/images/red_radar130.gif +0 -0
  72. data/images/red_radar140.gif +0 -0
  73. data/images/red_radar150.gif +0 -0
  74. data/images/red_radar160.gif +0 -0
  75. data/images/red_radar170.gif +0 -0
  76. data/images/red_radar180.gif +0 -0
  77. data/images/red_radar190.gif +0 -0
  78. data/images/red_radar200.gif +0 -0
  79. data/images/red_radar210.gif +0 -0
  80. data/images/red_radar220.gif +0 -0
  81. data/images/red_radar230.gif +0 -0
  82. data/images/red_radar240.gif +0 -0
  83. data/images/red_radar250.gif +0 -0
  84. data/images/red_radar260.gif +0 -0
  85. data/images/red_radar270.gif +0 -0
  86. data/images/red_radar280.gif +0 -0
  87. data/images/red_radar290.gif +0 -0
  88. data/images/red_radar300.gif +0 -0
  89. data/images/red_radar310.gif +0 -0
  90. data/images/red_radar320.gif +0 -0
  91. data/images/red_radar330.gif +0 -0
  92. data/images/red_radar340.gif +0 -0
  93. data/images/red_radar350.gif +0 -0
  94. data/images/red_turret000.gif +0 -0
  95. data/images/red_turret010.gif +0 -0
  96. data/images/red_turret020.gif +0 -0
  97. data/images/red_turret030.gif +0 -0
  98. data/images/red_turret040.gif +0 -0
  99. data/images/red_turret050.gif +0 -0
  100. data/images/red_turret060.gif +0 -0
  101. data/images/red_turret070.gif +0 -0
  102. data/images/red_turret080.gif +0 -0
  103. data/images/red_turret090.gif +0 -0
  104. data/images/red_turret100.gif +0 -0
  105. data/images/red_turret110.gif +0 -0
  106. data/images/red_turret120.gif +0 -0
  107. data/images/red_turret130.gif +0 -0
  108. data/images/red_turret140.gif +0 -0
  109. data/images/red_turret150.gif +0 -0
  110. data/images/red_turret160.gif +0 -0
  111. data/images/red_turret170.gif +0 -0
  112. data/images/red_turret180.gif +0 -0
  113. data/images/red_turret190.gif +0 -0
  114. data/images/red_turret200.gif +0 -0
  115. data/images/red_turret210.gif +0 -0
  116. data/images/red_turret220.gif +0 -0
  117. data/images/red_turret230.gif +0 -0
  118. data/images/red_turret240.gif +0 -0
  119. data/images/red_turret250.gif +0 -0
  120. data/images/red_turret260.gif +0 -0
  121. data/images/red_turret270.gif +0 -0
  122. data/images/red_turret280.gif +0 -0
  123. data/images/red_turret290.gif +0 -0
  124. data/images/red_turret300.gif +0 -0
  125. data/images/red_turret310.gif +0 -0
  126. data/images/red_turret320.gif +0 -0
  127. data/images/red_turret330.gif +0 -0
  128. data/images/red_turret340.gif +0 -0
  129. data/images/red_turret350.gif +0 -0
  130. data/images/toolbox.gif +0 -0
  131. data/lib/battlefield.rb +102 -0
  132. data/lib/bullets.rb +39 -0
  133. data/lib/configuration.rb +26 -0
  134. data/lib/explosions.rb +20 -0
  135. data/lib/overloads.rb +10 -0
  136. data/lib/robot.rb +122 -0
  137. data/lib/robotrunner.rb +260 -0
  138. data/lib/tkarena.rb +197 -0
  139. data/lib/toolboxes.rb +28 -0
  140. data/robots/BillDuck.rb +92 -0
  141. data/robots/BotOne.rb +39 -0
  142. data/robots/DuckBill.rb +384 -0
  143. data/robots/DuckBill04.rb +330 -0
  144. data/robots/DuckToEndAllDucks.rb +140 -0
  145. data/robots/EdgeBot.rb +203 -0
  146. data/robots/HuntingDuck.rb +74 -0
  147. data/robots/HyperactiveDuck.rb +15 -0
  148. data/robots/Killer.rb +58 -0
  149. data/robots/Kite.rb +193 -0
  150. data/robots/KoDuck.rb +57 -0
  151. data/robots/LinearShooter.rb +279 -0
  152. data/robots/LuckyDuck.rb +83 -0
  153. data/robots/MoxonoM.rb +85 -0
  154. data/robots/MsgBot.rb +13 -0
  155. data/robots/NervousDuck.rb +13 -0
  156. data/robots/Polisher.rb +15 -0
  157. data/robots/RomBot.rb +514 -0
  158. data/robots/RoomPainter.rb +205 -0
  159. data/robots/Rrrkele.rb +48 -0
  160. data/robots/Seeker.rb +57 -0
  161. data/robots/ShootingStation.rb +15 -0
  162. data/robots/SittingDuck.rb +18 -0
  163. data/robots/SniperDuck.rb +277 -0
  164. data/robots/WallPainter.rb +224 -0
  165. metadata +220 -0
@@ -0,0 +1,57 @@
1
+ require 'robot'
2
+
3
+ class KoDuck
4
+ include Robot
5
+
6
+ def initialize *bd
7
+ super
8
+ end
9
+
10
+ def near_wall?
11
+ if x+10 <= size || y+10 < size || (x+size+10 >= battlefield_width) ||
12
+ (y+size+10 >= battlefield_height)
13
+ return true
14
+ else
15
+ return false
16
+ end
17
+ end
18
+
19
+ def tick events
20
+ @out_of_wall = 0
21
+ if time == 0 && near_wall?
22
+ turn -10
23
+ accelerate 1
24
+ return
25
+ end
26
+ n = (rand + 0.5) * -1
27
+ if near_wall? && @out_of_wall.zero?
28
+ n *= 10
29
+ @out_of_wall += 1
30
+ turn n
31
+ else
32
+ @out_of_wall += 1 unless @out_of_wall.zero?
33
+ turn n
34
+ accelerate 1
35
+ if @out_of_wall > 100
36
+ @out_of_wall = 0
37
+ if n.abs > 5
38
+ n /=5.0
39
+ end
40
+ end
41
+ end
42
+ if !events['robot_scanned'].empty?
43
+ fire 3
44
+ if (n * 5).abs > 30
45
+ n = (n > 0) ? 3: -3
46
+ end
47
+ turn_gun(-n * 10)
48
+ else
49
+ turn_gun -6
50
+ fire 0.1
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+
57
+
@@ -0,0 +1,279 @@
1
+ require 'robot'
2
+ require 'matrix'
3
+
4
+
5
+ class Numeric
6
+
7
+ def deg2rad
8
+ self * 0.0174532925199433
9
+ end
10
+
11
+ def rad2deg
12
+ self * 57.2957795130823
13
+ end
14
+
15
+ end
16
+
17
+ class Array
18
+ def average
19
+ inject{|s,i|s+i} / size.to_f
20
+ end
21
+ def sd
22
+ avg = average
23
+ Math.sqrt( inject(0){|s,i| s+(i-avg)**2} / (size-1.0) )
24
+ end
25
+ end
26
+
27
+ class Vector
28
+ include Enumerable
29
+
30
+ def each &block
31
+ @elements.each(&block)
32
+ end
33
+
34
+ end
35
+
36
+
37
+ class LinearShooter
38
+ include Robot
39
+
40
+ def initialize *args, &block
41
+ super
42
+ @rt = @radar_scan = 15
43
+ @min_radar_scan = 1.5
44
+ @max_radar_scan = 60.0
45
+ @radar_turned = false
46
+ @lock = false
47
+ @lock_threshold = 15.0
48
+ @firing_threshold = 20.0
49
+ @wanted_turn = @wanted_gun_turn = @wanted_radar_turn = 0
50
+ @rturn_dir = 1
51
+ @racc_dir = 1
52
+ @serial_hit_limit = 10
53
+ @serial_hit_counter = 0
54
+ @target_positions = []
55
+ @min_distance = 1500
56
+ @sd_limit = 30
57
+ end
58
+
59
+ def tick events
60
+ @prev_health = energy if time == 0
61
+ scan events
62
+ firing_solution events
63
+ navigate events
64
+ turn_hull
65
+ turn_turret
66
+ turn_radar_dish
67
+ @prev_health = energy
68
+ end
69
+
70
+ def scan events
71
+ if events['robot_scanned'].empty?
72
+ increase_radar_scan
73
+ @lock = false
74
+ else
75
+ decrease_radar_scan
76
+ @lock = @radar_scan.abs < @lock_threshold
77
+ end
78
+ @rt = (time/2 % 2 < 1 ? -@radar_scan/2.0 : @radar_scan/2.0) if @radar_scan.abs < @max_radar_scan - 0.1
79
+ @wanted_radar_turn += @rt
80
+ end
81
+
82
+ def firing_solution events
83
+ add_target_position(events['robot_scanned'])
84
+ th = target_heading
85
+ gtd = heading_distance(gun_heading, th) if th
86
+ @firepower = [1.5e5 / (@min_distance)**2, 3*25 / (@vsd||1500)].max / 2.0
87
+ msg = "Hope this hits.."
88
+ msg = "On target." if @firepower > 1.5
89
+ msg = "Takedown!" if @firepower > 2.25
90
+ msg = "SURE HIT!" if @firepower > 3.0
91
+ say msg if @on_target and gun_heat == 0
92
+ fire @firepower if @on_target
93
+ if @lock and gtd and gtd.abs < @firing_threshold
94
+ @wanted_gun_turn = gtd
95
+ @on_target = true
96
+ else
97
+ #fire @firepower*0.3
98
+ @wanted_gun_turn = gtd || (gun_radar_distance/3.0) + Math.sin(time*0.2)*(1000.0/@min_distance)
99
+ @on_target = false
100
+ end
101
+ end
102
+
103
+ def add_target_position(distances)
104
+ unless distances.empty?
105
+ positions = distances.map{|d|
106
+ tx = x + Math.cos((radar_heading - @radar_scan.abs / 2.0).deg2rad) * d[0]
107
+ ty = y - Math.sin((radar_heading - @radar_scan.abs / 2.0).deg2rad) * d[0]
108
+ [d, Vector[tx,ty]]
109
+ }
110
+ last = @target_positions.last
111
+ position = if last
112
+ positions.min{|a,b| (a[1] - last).r <=> (b[1] - last).r }[1]
113
+ else
114
+ positions.min{|a,b| a[0] <=> b[0]}[1]
115
+ end
116
+ @min_distance = distances.min{|a,b| a[0]<=>b[0]}[0]
117
+ @target_positions.push position if position
118
+ end
119
+ @target_positions.shift if @target_positions.size > 200
120
+ end
121
+
122
+ def average_last_positions(c=4)
123
+ tps = @target_positions[-10,10]
124
+ d = tps.size/c
125
+ ptas = (0...c).map{|i| tps[i*d,d] }
126
+ ptas.map{|pta| average(pta) }
127
+ end
128
+
129
+ def average arr
130
+ arr.inject{|s,i| s+i} * (1.0/arr.size)
131
+ end
132
+
133
+ def sd arr
134
+ Math.sqrt(arr.map{|v| v[0]}.sd**2 + arr.map{|v| v[1]}.sd**2)
135
+ end
136
+
137
+ def deltas arr
138
+ arr[0..-2].zip(arr[1..-1]).map{|a,b| b - a}
139
+ end
140
+
141
+ def target_heading
142
+ return nil if @target_positions.size < 10
143
+ return radar_heading if @min_distance < 200
144
+ lps = average_last_positions(5)
145
+ p4 = lps.last
146
+ vs = deltas(lps).map{|v| v * 0.5 }
147
+ @vsd = sd vs
148
+ return nil if @vsd > @sd_limit
149
+ v = average(vs)
150
+ if v.r < 4.0
151
+ #say 'Stationary targeting'
152
+ return heading_for(average(lps))
153
+ end
154
+ p4 = p4 + (v*0.5)
155
+ distance = p4 - Vector[x,y]
156
+ shot_speed = (30/8.0)*v.r
157
+ a = distance[0]**2 + distance[1]**2
158
+ b = 2*distance[0]*v[0] + 2*distance[1]*v[1]
159
+ c = v[0]**2 + v[1]**2 - shot_speed**2
160
+ t = 2*a / (-b + Math.sqrt(b**2-4*a*c))
161
+ ep = p4 + v*t
162
+ estimated_position = Vector[[size, [battlefield_width-size, ep[0]].min].max, [size, [battlefield_height-size, ep[1]].min].max]
163
+ est_head = heading_for(estimated_position)
164
+ #say 'Linear targeting'
165
+ est_head + (rand-0.5)*@vsd*0.2
166
+ end
167
+
168
+ def format(arr, precision = 1)
169
+ case arr
170
+ when Float
171
+ (arr * 10**precision).round * 10**-precision
172
+ when Array
173
+ arr.map{|i| format i, precision}
174
+ else
175
+ arr
176
+ end
177
+ end
178
+
179
+ def gun_vector
180
+ Vector[Math.cos(gun_heading.deg2rad), -Math.sin(gun_heading.deg2rad)]
181
+ end
182
+
183
+ def heading_for(position)
184
+ distance = position - Vector[x,y]
185
+ heading = (Math.atan2(-distance[1], distance[0])).rad2deg
186
+ heading += 360 if heading < 0
187
+ heading
188
+ end
189
+
190
+ def navigate events
191
+ if events['got_hit'].empty?
192
+ @serial_hit_counter -= 0.05 if @serial_hit_counter > 0
193
+ accelerate(@racc_dir) if velocity.abs < 7.9
194
+ else
195
+ @serial_hit_counter += @prev_health - events['got_hit'].last.last
196
+ @serial_hit_counter = [@serial_hit_counter, @serial_hit_limit + 0.04].max
197
+ if @serial_hit_counter > @serial_hit_limit
198
+ acc = velocity > 0 ? 1 : -1
199
+ accelerate(acc) if velocity.abs < 7.9
200
+ end
201
+ end
202
+ if @serial_hit_counter > @serial_hit_limit and not events['got_hit'].empty? and @wanted_turn <= 1
203
+ @wanted_turn = @rturn_dir * 30
204
+ @rturn_dir *= -1 if rand < 0.05
205
+ elsif approaching_wall? and @wanted_turn <= 1
206
+ @wanted_turn = 60 * @rturn_dir
207
+ @rturn_dir *= -1 if rand < 0.5
208
+ elsif rand < 0.15
209
+ @wanted_turn += rand * 10 * @rturn_dir
210
+ elsif rand < 0.01
211
+ @rturn_dir *= -1
212
+ elsif rand < 0.01
213
+ @racc_dir *= -1
214
+ end
215
+ end
216
+
217
+ def increase_radar_scan
218
+ @radar_scan *= 1.5
219
+ @radar_scan = [@radar_scan, @max_radar_scan].min
220
+ end
221
+
222
+ def decrease_radar_scan
223
+ @radar_scan *= 0.6
224
+ @radar_scan = [@radar_scan, @min_radar_scan].max
225
+ end
226
+
227
+ def heading_distance h1, h2
228
+ limit h2 - h1, 180
229
+ end
230
+
231
+ def limit value, m
232
+ value -= 360 if value > 180
233
+ value += 360 if value < -180
234
+ value = -m if value < -m
235
+ value = m if value > m
236
+ return value
237
+ end
238
+
239
+ def gun_radar_distance
240
+ heading_distance gun_heading, radar_heading
241
+ end
242
+
243
+ def turn_hull
244
+ turn_amt = [-10.0, [@wanted_turn, 10.0].min].max
245
+ #puts "Turning hull by: #{turn_amt}" if turn_amt.abs > 1
246
+ turn turn_amt
247
+ @wanted_turn -= turn_amt
248
+ @wanted_gun_turn -= turn_amt
249
+ @wanted_radar_turn -= turn_amt
250
+ end
251
+
252
+ def turn_turret
253
+ turn_amt = [-30.0, [@wanted_gun_turn, 30.0].min].max
254
+ #puts "Turning gun by: #{turn_amt}" if turn_amt.abs > 1
255
+ turn_gun turn_amt
256
+ @wanted_gun_turn -= turn_amt
257
+ @wanted_radar_turn -= turn_amt
258
+ end
259
+
260
+ def turn_radar_dish
261
+ turn_amt = [-60.0, [@wanted_radar_turn, 60.0].min].max
262
+ #puts "Turning radar by: #{turn_amt}" if turn_amt.abs > 1
263
+ turn_radar turn_amt
264
+ @wanted_radar_turn -= turn_amt
265
+ end
266
+
267
+ def approaching_wall?
268
+ if not ( (velocity > 0) ^ heading.between?(0.0, 180.0) )
269
+ y < 100
270
+ else
271
+ y > battlefield_height - 100
272
+ end or if not ( (velocity > 0) ^ heading.between?(90.0, 270.0) )
273
+ x < 100
274
+ else
275
+ x > battlefield_width - 100
276
+ end
277
+ end
278
+
279
+ end
@@ -0,0 +1,83 @@
1
+ require 'robot'
2
+ class LuckyDuck
3
+ include Robot
4
+ def initialize *bf
5
+ if bf.size != 0
6
+ super(bf[0])
7
+ @tourney = false
8
+ else
9
+ super
10
+ @tourney = true
11
+ end
12
+ @lastchange = time
13
+ @dc = []
14
+ @dc[300] = 3
15
+ @dc[300] = 3
16
+ @dc[300] = 3
17
+ @dc[300] = 3
18
+ @dc[300] = 3
19
+ end
20
+
21
+ def rel_direction(from, to)
22
+ rel = to -from
23
+ if rel > 180
24
+ rel = -360 + rel
25
+ end
26
+ if rel < -180
27
+ rel = 360 + rel
28
+ end
29
+ return rel
30
+ end
31
+
32
+ def a_rand(*args)
33
+ args.flatten!
34
+ return args[rand(args.size)]
35
+ end
36
+
37
+ def tick events
38
+ @enemy = 0 unless @enemy
39
+ @dist = 400 unless @dist
40
+ @gun_head = nil unless @gun_head
41
+ @head = (@head||=90)
42
+ @gun_head_to = (@gun_head_to||=90)
43
+ istop = (y-size <= size*2)
44
+ isleft = (x-size <= size*2)
45
+ isbottom = (battlefield_height-size <= (y+size))
46
+ isright = (battlefield_width-size <= (x+size))
47
+ if (time-@lastchange >= 5 || !events['got_hit'].empty?)
48
+ (isleft) ? (@head = a_rand([270,90])) : nil
49
+ (isbottom) ? (@head = a_rand([180,0])) : nil
50
+ (isright) ? (@head = a_rand([270,90])) : nil
51
+ (istop) ? (@head = a_rand([180,0])) : nil
52
+ (isleft && istop) ? (@head = a_rand([270,0])) : nil
53
+ (isleft && isbottom) ? (@head = a_rand([90,0])) : nil
54
+ (isright && istop) ? (@head = a_rand([270,180])) : nil
55
+ (isright && isbottom) ? (@head = a_rand([90,180])) : nil
56
+ @lastchange = time
57
+ end
58
+ if !events['robot_scanned'].empty?
59
+ @enemy = 10
60
+ @dist = events['robot_scanned'].first.first
61
+ @gun_head = gun_heading
62
+ end
63
+ rel = rel_direction(heading, @head)
64
+ (rel >= 5) ? (turn(rel*10);turn_gun(-(rel*10))) : turn(0)
65
+ if gun_heat <= 0
66
+ if @enemy >= 1
67
+ offset = (gun_heading+(@dist/200).to_i).abs
68
+ gun_rel = rel_direction(gun_heading, @gun_head)
69
+ puts "[#{gun_rel} | #{@gun_head} ~~ #{gun_heading} (#{offset})"
70
+ #(gun_rel != 0) ? turn_gun(gun_rel) : turn_gun(+2)
71
+ turn_gun(gun_rel/2)
72
+
73
+ (@dist <= 600) ? fire(3) : fire(0.1)*30
74
+ end
75
+ end
76
+ turn_gun(-10) if @gun_head.nil?
77
+ accelerate(1)
78
+ @enemy = ((@enemy <= 0) ? (@ememy; @gun_head = nil) : (@enemy-1))
79
+ if @enemy == 1
80
+ turn_gun(15)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,85 @@
1
+ require 'robot'
2
+ class MoxonoM
3
+ include Robot
4
+ def initialize *bf
5
+ if bf.size != 0
6
+ super(bf[0])
7
+ @tourney = false
8
+ else
9
+ super
10
+ @tourney = true
11
+ end
12
+ @adjust_radar = true
13
+ @turn_gun_range = (-5..5).to_a
14
+ @turn_range = (-10..10).to_a
15
+ @lastchange = time
16
+ end
17
+
18
+ def rel_direction(from, to)
19
+ rel = to -from
20
+ if rel > 180
21
+ rel = -360 + rel
22
+ end
23
+ if rel < -180
24
+ rel = 360 + rel
25
+ end
26
+ return rel
27
+ end
28
+
29
+ def a_rand(*args)
30
+ args.flatten!
31
+ return args[rand(args.size)]
32
+ end
33
+
34
+ def tick events
35
+ @enemy = 0 unless @enemy
36
+ @dist = 400 unless @dist
37
+ @gun_head = nil unless @gun_head
38
+ @adjust = nil unless @adjust
39
+ if !@adjust
40
+ turn_radar(-5)
41
+ @adjust = true
42
+ end
43
+ @head = (@head||=90)
44
+ @gun_head_to = (@gun_head_to||=90)
45
+ top = y-size
46
+ left = x-size
47
+ bottom = battlefield_height-size
48
+ right = battlefield_width-size
49
+ istop = (top <= size)
50
+ isleft = (left <= size)
51
+ isbottom = (bottom <= (y+size))
52
+ isright = (right <= (x+size))
53
+ if (time-@lastchange >= 15 || !events['got_hit'].empty?)
54
+ (isleft) ? (@head = a_rand([270,90,0])) : nil
55
+ (isbottom) ? (@head = a_rand([180,90,0])) : nil
56
+ (isright) ? (@head = a_rand([270,90,180])) : nil
57
+ (istop) ? (@head = a_rand([270,180,0])) : nil
58
+ (isleft && istop) ? (@head = a_rand([315,270,0])) : nil
59
+ (isleft && isbottom) ? (@head = a_rand([45,90,0])) : nil
60
+ (isright && istop) ? (@head = a_rand([270,180,225])) : nil
61
+ (isright && isbottom) ? (@head = a_rand([135,90,180])) : nil
62
+ @lastchange = time
63
+ end
64
+ if !events['robot_scanned'].empty?
65
+ @enemy = 5
66
+ @dist = events['robot_scanned'].first.first
67
+ @gun_head = gun_heading
68
+ fire(3)
69
+ end
70
+ rel = rel_direction(heading, @head)
71
+ (rel >= 5) ? (turn(rel*10);turn_gun(-(rel*10))) : turn(0)
72
+ if gun_heat <= 0
73
+ if @enemy >= 1
74
+ (@dist <= 300) ? fire(3) : fire(3)
75
+ gun_rel = rel_direction(gun_heading, @gun_head-5)
76
+ (gun_rel >= 10) ? turn(gun_rel*rand(15)) : turn(0)
77
+ else
78
+ fire(0.5)
79
+ end
80
+ end
81
+ turn_gun(-15) if @gun_head.nil?
82
+ accelerate(1)
83
+ @enemy = ((@enemy <= 0) ? (@ememy; @gun_head = nil) : (@enemy-1))
84
+ end
85
+ end