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
data/robots/EdgeBot.rb
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
# EdgeBot.rb
|
2
|
+
require 'robot'
|
3
|
+
|
4
|
+
class EdgeBot
|
5
|
+
include Robot
|
6
|
+
|
7
|
+
@@east = 0
|
8
|
+
@@north = 90
|
9
|
+
@@west = 180
|
10
|
+
@@south = 270
|
11
|
+
@@none = -1
|
12
|
+
|
13
|
+
@@direction = {
|
14
|
+
:east => {
|
15
|
+
:angle => @@east,
|
16
|
+
:inward_angle => @@west,
|
17
|
+
:next_edge => [:north, :south]
|
18
|
+
},
|
19
|
+
:north => {
|
20
|
+
:angle => @@north,
|
21
|
+
:inward_angle => @@south,
|
22
|
+
:next_edge => [:west, :east]
|
23
|
+
},
|
24
|
+
:west => {
|
25
|
+
:angle => @@west,
|
26
|
+
:inward_angle => @@east,
|
27
|
+
:next_edge => [:south, :north]
|
28
|
+
},
|
29
|
+
:south => {
|
30
|
+
:angle => @@south,
|
31
|
+
:inward_angle => @@north,
|
32
|
+
:next_edge => [:east, :west]
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
@@max_robot_turn = 10
|
37
|
+
@@max_gun_turn = 30
|
38
|
+
@@max_radar_turn = 60
|
39
|
+
@@max_speed = 8
|
40
|
+
|
41
|
+
@@chicken_energy = 10
|
42
|
+
|
43
|
+
def tick( events )
|
44
|
+
if time == 0
|
45
|
+
@direction = 0
|
46
|
+
@target_angle = Hash.new
|
47
|
+
@next_edge = nearest_edge
|
48
|
+
@target_angle[:robot] = @@direction[@next_edge][:angle]
|
49
|
+
@target_angle[:gun] = @@direction[@next_edge][:angle]
|
50
|
+
@target_angle[:radar] = @@direction[@next_edge][:angle]
|
51
|
+
@mode = :seek_edge
|
52
|
+
@prev_radar_heading = radar_heading
|
53
|
+
@fire_power = 3
|
54
|
+
end
|
55
|
+
|
56
|
+
rotate!
|
57
|
+
fire( @fire_power )
|
58
|
+
|
59
|
+
case @mode
|
60
|
+
when :seek_edge
|
61
|
+
# puts "seek_edge"
|
62
|
+
@fire_power = 0.1
|
63
|
+
if @turn_complete
|
64
|
+
@mode = :move_to_edge
|
65
|
+
end
|
66
|
+
when :move_to_edge
|
67
|
+
# puts "move_to_edge"
|
68
|
+
fire( 3 ) unless events['robot_scanned'].empty?
|
69
|
+
unless at_edge? @next_edge
|
70
|
+
accelerate( 1 )
|
71
|
+
else
|
72
|
+
@current_edge = @next_edge
|
73
|
+
@next_edge = @@direction[@current_edge][:next_edge][@direction]
|
74
|
+
@target_angle[:robot] = @@direction[@next_edge][:angle]
|
75
|
+
@target_angle[:gun] = @@direction[@current_edge][:inward_angle]
|
76
|
+
@target_angle[:radar] = @@direction[@next_edge][:angle]
|
77
|
+
@mode = :edge_align
|
78
|
+
end
|
79
|
+
when :edge_align
|
80
|
+
# puts "edge_align"
|
81
|
+
@fire_power = 0.1
|
82
|
+
if speed != 0
|
83
|
+
stop
|
84
|
+
end
|
85
|
+
if @turn_complete && @prev_radar_heading == radar_heading
|
86
|
+
# Pause for a still radar shot before progressing
|
87
|
+
@mode = :fire
|
88
|
+
end
|
89
|
+
if edge_occupied?( @@direction[@next_edge][:angle], events )
|
90
|
+
@mode = :clear_edge_align
|
91
|
+
@target_angle[:gun] = @@direction[@next_edge][:angle]
|
92
|
+
@target_angle[:radar] = @@direction[@next_edge][:angle]
|
93
|
+
end
|
94
|
+
when :fire
|
95
|
+
# puts "fire"
|
96
|
+
@fire_power = 0.1
|
97
|
+
if velocity < @@max_speed
|
98
|
+
accelerate( 1 )
|
99
|
+
end
|
100
|
+
if at_edge?( @next_edge )
|
101
|
+
@current_edge = @next_edge
|
102
|
+
@next_edge = @@direction[@current_edge][:next_edge][@direction]
|
103
|
+
@target_angle[:robot] = @@direction[@next_edge][:angle]
|
104
|
+
@target_angle[:gun] = @@direction[@current_edge][:inward_angle]
|
105
|
+
@target_angle[:radar] = @@direction[@next_edge][:angle]
|
106
|
+
@mode = :edge_align
|
107
|
+
elsif edge_occupied?( @@direction[@next_edge][:angle], events )
|
108
|
+
@mode = :clear_edge_align
|
109
|
+
@target_angle[:gun] = @@direction[@next_edge][:angle]
|
110
|
+
@target_angle[:radar] = @@direction[@next_edge][:angle]
|
111
|
+
end
|
112
|
+
when :clear_edge_align
|
113
|
+
# puts "clear_edge_align"
|
114
|
+
@fire_power = 0.1
|
115
|
+
if speed != 0
|
116
|
+
stop
|
117
|
+
end
|
118
|
+
if @turn_complete
|
119
|
+
@mode = :clear_edge
|
120
|
+
end
|
121
|
+
when :clear_edge
|
122
|
+
@fire_power = 0.1
|
123
|
+
if not edge_occupied?( @@direction[@next_edge][:angle], events )
|
124
|
+
@target_angle[:gun] = @@direction[@current_edge][:inward_angle]
|
125
|
+
@target_angle[:radar] = @@direction[@next_edge][:angle]
|
126
|
+
@mode = :edge_align
|
127
|
+
elsif energy < @@chicken_energy
|
128
|
+
reverse_course!
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
@prev_radar_heading = radar_heading
|
133
|
+
end
|
134
|
+
|
135
|
+
def rotate!
|
136
|
+
@turn_complete = true
|
137
|
+
if @target_angle[:robot] != @@none && heading != @target_angle[:robot]
|
138
|
+
turn( angle_to( @target_angle[:robot], heading, @@max_robot_turn ) )
|
139
|
+
@turn_complete = false
|
140
|
+
elsif @target_angle[:gun] != @@none && gun_heading != @target_angle[:gun]
|
141
|
+
turn_gun( angle_to( @target_angle[:gun], gun_heading, @@max_gun_turn ) )
|
142
|
+
@turn_complete = false
|
143
|
+
elsif @target_angle[:radar] != @@none && radar_heading != @target_angle[:radar]
|
144
|
+
turn_radar( angle_to( @target_angle[:radar], radar_heading, @@max_radar_turn ) )
|
145
|
+
@turn_complete = false
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def angle_to( target_heading, current_heading, max_turn )
|
150
|
+
normalised_heading = current_heading - target_heading
|
151
|
+
dir = (normalised_heading < 180) ? -1 : 1
|
152
|
+
if normalised_heading < max_turn
|
153
|
+
return dir * normalised_heading
|
154
|
+
else
|
155
|
+
return dir * max_turn
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def at_edge?( edge )
|
160
|
+
case edge
|
161
|
+
when :east
|
162
|
+
return x >= (battlefield_width - size)
|
163
|
+
when :north
|
164
|
+
return y <= size
|
165
|
+
when :west
|
166
|
+
return x <= size
|
167
|
+
when :south
|
168
|
+
return y >= (battlefield_height - size)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def edge_occupied?( angle, events )
|
173
|
+
return (@prev_radar_heading == angle &&
|
174
|
+
radar_heading == angle &&
|
175
|
+
!events['robot_scanned'].empty?)
|
176
|
+
end
|
177
|
+
|
178
|
+
def nearest_edge
|
179
|
+
min = [:west, x]
|
180
|
+
if y < min[1]
|
181
|
+
min = [:north, y]
|
182
|
+
end
|
183
|
+
if battlefield_width - x < min[1]
|
184
|
+
min = [:east, battlefield_width - x]
|
185
|
+
end
|
186
|
+
if battlefield_height - y < min[1]
|
187
|
+
min = [:south, battlefield_height - y]
|
188
|
+
end
|
189
|
+
return min[0]
|
190
|
+
end
|
191
|
+
|
192
|
+
def reverse_course!
|
193
|
+
@direction = (@direction + 1) % 2
|
194
|
+
@next_edge = @@direction[@current_edge][:next_edge][@direction]
|
195
|
+
@target_angle[:robot] = @@direction[@next_edge][:angle]
|
196
|
+
@target_angle[:gun] = @@direction[@current_edge][:inward_angle]
|
197
|
+
@target_angle[:radar] = @@direction[@next_edge][:angle]
|
198
|
+
@mode = :edge_align
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'robot'
|
2
|
+
|
3
|
+
class HuntingDuck
|
4
|
+
include Robot
|
5
|
+
def initialize *bf
|
6
|
+
if bf.size != 0
|
7
|
+
super(bf[0])
|
8
|
+
@tourney = false
|
9
|
+
else
|
10
|
+
super
|
11
|
+
@tourney = true
|
12
|
+
end
|
13
|
+
@time_since=10
|
14
|
+
@direction=1
|
15
|
+
@rob_distance=200
|
16
|
+
end
|
17
|
+
def rel_direction(from,to)
|
18
|
+
rel = to -from
|
19
|
+
if rel > 180
|
20
|
+
rel = -360 + rel
|
21
|
+
end
|
22
|
+
if rel < -180
|
23
|
+
rel = 360+rel
|
24
|
+
end
|
25
|
+
return rel
|
26
|
+
end
|
27
|
+
def rel_gun_heading
|
28
|
+
rel_direction(heading, gun_heading)
|
29
|
+
end
|
30
|
+
def tick events
|
31
|
+
accelerate 1
|
32
|
+
@rob_distance=events['robot_scanned'][0][0] unless events['robot_scanned'].empty?
|
33
|
+
if @rob_distance > 800
|
34
|
+
#make small turret adjustments when distance to enemy is great
|
35
|
+
turret_turn=3
|
36
|
+
else
|
37
|
+
turret_turn=6
|
38
|
+
end
|
39
|
+
#turn clockwise or counter clockwise?
|
40
|
+
@direction = -@direction if Kernel.rand < 0.02
|
41
|
+
if !events['got_hit'].empty?
|
42
|
+
#if we got hit we'd better shoot back and try to turn away
|
43
|
+
fire 2
|
44
|
+
turn -10*@direction
|
45
|
+
end
|
46
|
+
if !events['robot_scanned'].empty?
|
47
|
+
fire 3
|
48
|
+
@time_since=0
|
49
|
+
else
|
50
|
+
if @time_since < 15
|
51
|
+
#spotted the enemy, moving closer
|
52
|
+
#while moving the turret to spot him again
|
53
|
+
if Kernel.rand < 0.5 && rel_gun_heading < 30
|
54
|
+
turn_gun turret_turn
|
55
|
+
elsif rel_gun_heading > -30
|
56
|
+
turn_gun -turret_turn
|
57
|
+
else
|
58
|
+
turn_gun turret_turn
|
59
|
+
end
|
60
|
+
fire 0.5
|
61
|
+
elsif @time_since < 100
|
62
|
+
#try to spot the enemy
|
63
|
+
turn 10*@direction
|
64
|
+
else
|
65
|
+
#if we got stuck this should get us out
|
66
|
+
turn 5
|
67
|
+
end
|
68
|
+
end
|
69
|
+
@time_since += 1
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
|
data/robots/Killer.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'robot'
|
2
|
+
|
3
|
+
class Killer
|
4
|
+
include Robot
|
5
|
+
|
6
|
+
def min_max value, m
|
7
|
+
value-= 360 if value > 180
|
8
|
+
value+= 360 if value < -180
|
9
|
+
value = -m if value < -m
|
10
|
+
value = m if value > m
|
11
|
+
return value
|
12
|
+
end
|
13
|
+
|
14
|
+
def tick events
|
15
|
+
@dist = 1000 if @dist.nil?
|
16
|
+
@target_heading = 0 if @target_heading.nil?
|
17
|
+
@predicted_heading = 0 if @predicted_heading.nil?
|
18
|
+
@radar_range = 60 if @radar_range.nil?
|
19
|
+
@direction = 1 if @direction.nil?
|
20
|
+
|
21
|
+
if !events['robot_scanned'].empty?
|
22
|
+
@dist = events['robot_scanned'].first.first
|
23
|
+
@target_heading = radar_heading - @radar_range * 0.5
|
24
|
+
@predicted_heading = @target_heading + 16.0 * (rand(3)-1)
|
25
|
+
if (@dist * @radar_range.abs <= 500)
|
26
|
+
sx = x + Math::cos(@target_heading / 180 * Math::PI) * @dist
|
27
|
+
sy = y - Math::sin(@target_heading / 180 * Math::PI) * @dist
|
28
|
+
if @last_scan && (time - @last_scan[2]) == 1
|
29
|
+
px = sx + (sx - @last_scan[0]) * (@dist - 90) / 30
|
30
|
+
py = sy + (sy - @last_scan[1]) * (@dist - 90) / 30
|
31
|
+
@predicted_heading = Math.atan2(y - py, px - x) / Math::PI * 180 % 360
|
32
|
+
end
|
33
|
+
@last_scan = [sx, sy, time]
|
34
|
+
end
|
35
|
+
@radar_range = (@dist * @radar_range.abs > 250) ? -@radar_range * 0.5 : -@radar_range
|
36
|
+
else
|
37
|
+
@radar_range *= -2 if (@radar_range.abs < 60)
|
38
|
+
end
|
39
|
+
|
40
|
+
fire 3
|
41
|
+
|
42
|
+
if ((x < 100) || (x > 1500) || (y < 100) || (y > 1500)) && (@escape.nil? || @escape.zero?)
|
43
|
+
@escape = 30
|
44
|
+
@direction *= -1
|
45
|
+
end
|
46
|
+
|
47
|
+
@escape -= 1 if @escape && (@escape > 0)
|
48
|
+
accelerate(@direction)
|
49
|
+
|
50
|
+
turn_body = min_max(@target_heading - heading + 90, 10)
|
51
|
+
gun = min_max(@predicted_heading - gun_heading - turn_body, 30)
|
52
|
+
radar = min_max(@radar_range - gun - turn_body, 60)
|
53
|
+
|
54
|
+
turn(turn_body)
|
55
|
+
turn_gun(gun)
|
56
|
+
turn_radar(radar)
|
57
|
+
end
|
58
|
+
end
|
data/robots/Kite.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
# Uses linear targetting and
|
2
|
+
# moves in a way that dodges linear targetting.
|
3
|
+
# Not very good for melee.
|
4
|
+
#
|
5
|
+
require 'robot'
|
6
|
+
require 'matrix'
|
7
|
+
|
8
|
+
class Numeric
|
9
|
+
def deg2rad
|
10
|
+
self * 0.0174532925199433
|
11
|
+
end
|
12
|
+
def rad2deg
|
13
|
+
self * 57.2957795130823
|
14
|
+
end
|
15
|
+
def sign
|
16
|
+
self / abs
|
17
|
+
end
|
18
|
+
end
|
19
|
+
class Array
|
20
|
+
def average
|
21
|
+
inject{|s,i|s+i} / size.to_f
|
22
|
+
end
|
23
|
+
def sd
|
24
|
+
avg = average
|
25
|
+
Math.sqrt( inject(0){|s,i| s+(i-avg)**2} / (size-1.0) )
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Kite
|
30
|
+
include Robot
|
31
|
+
|
32
|
+
def initialize *args, &block
|
33
|
+
super
|
34
|
+
@rt = @radar_scan = 15
|
35
|
+
@min_radar_scan = 1.5
|
36
|
+
@max_radar_scan = 60.0
|
37
|
+
@lock = false
|
38
|
+
@firing_threshold = 20.0
|
39
|
+
@wanted_turn = @wanted_gun_turn = @wanted_radar_turn = 0
|
40
|
+
@rturn_dir = 1
|
41
|
+
@racc_dir = 1
|
42
|
+
@target_positions = []
|
43
|
+
@sd_limit = 30
|
44
|
+
end
|
45
|
+
|
46
|
+
def tick events
|
47
|
+
@prev_health = energy if time == 0
|
48
|
+
if events['robot_scanned'].empty?
|
49
|
+
@radar_scan = [@radar_scan * 1.5, @max_radar_scan].min
|
50
|
+
else
|
51
|
+
@radar_scan = [@radar_scan * 0.5, @min_radar_scan].max
|
52
|
+
end
|
53
|
+
@rt = (time/2 % 2 < 1 ? -@radar_scan/2.0 : @radar_scan/2.0) if @radar_scan.abs < @max_radar_scan - 0.1
|
54
|
+
@wanted_radar_turn += @rt
|
55
|
+
firing_solution events
|
56
|
+
@hit = unless events['got_hit'].empty?
|
57
|
+
@racc_dir = @racc_dir / @racc_dir.abs
|
58
|
+
20
|
59
|
+
else
|
60
|
+
(@hit||0) - 1
|
61
|
+
end
|
62
|
+
if @hit < 0
|
63
|
+
@racc_dir = (@min_distance and @min_distance < 450) ? @racc_dir.sign : Math.sin(time*0.1+rand*0.2)
|
64
|
+
end
|
65
|
+
accelerate(@racc_dir)
|
66
|
+
if approaching_wall?
|
67
|
+
@wanted_turn = 60 * @rturn_dir
|
68
|
+
elsif @target_heading and @wanted_turn <= 1
|
69
|
+
@wanted_turn = heading_distance(((@min_distance and @min_distance < 450) ? (90-@rturn_dir.sign*30)*-@racc_dir.sign : 0)+heading, 90+@target_heading)
|
70
|
+
elsif rand < 0.3
|
71
|
+
@wanted_turn += rand * 10 * @racc_dir.sign * @rturn_dir
|
72
|
+
elsif rand < 0.01
|
73
|
+
@rturn_dir *= -1
|
74
|
+
elsif rand < 0.01
|
75
|
+
@racc_dir *= -1
|
76
|
+
end
|
77
|
+
turn_hull
|
78
|
+
turn_turret
|
79
|
+
turn_radar_dish
|
80
|
+
@prev_health = energy
|
81
|
+
end
|
82
|
+
|
83
|
+
def firing_solution events
|
84
|
+
unless events['robot_scanned'].empty?
|
85
|
+
last = @target_positions.last || Vector[0,0]
|
86
|
+
position = events['robot_scanned'].map{|d|
|
87
|
+
tx = x + Math.cos((radar_heading - @radar_scan.abs / 2.0).deg2rad) * d[0]
|
88
|
+
ty = y - Math.sin((radar_heading - @radar_scan.abs / 2.0).deg2rad) * d[0]
|
89
|
+
Vector[tx,ty]
|
90
|
+
}.min{|a,b| (a - last).r <=> (b - last).r }
|
91
|
+
@target_positions.push position
|
92
|
+
@min_distance = events['robot_scanned'].flatten.min
|
93
|
+
end
|
94
|
+
@target_positions.shift if @target_positions.size > 10
|
95
|
+
@min_distance = nil if @target_positions.empty?
|
96
|
+
@target_heading = target_heading
|
97
|
+
gtd = heading_distance(gun_heading, @target_heading) if @target_heading
|
98
|
+
@firepower = [3*25 / (@vsd||1500)].max / 2.0
|
99
|
+
fire @firepower if @on_target
|
100
|
+
if gtd and gtd.abs < @firing_threshold
|
101
|
+
@wanted_gun_turn = gtd
|
102
|
+
@on_target = true
|
103
|
+
else
|
104
|
+
@wanted_gun_turn = gtd || (gun_radar_distance/3.0)
|
105
|
+
@on_target = false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def average arr
|
110
|
+
arr.inject{|s,i| s+i} * (1.0/arr.size)
|
111
|
+
end
|
112
|
+
|
113
|
+
def target_heading
|
114
|
+
return nil if @target_positions.size < 10
|
115
|
+
return radar_heading if @min_distance and @min_distance < 200
|
116
|
+
lps = (0...5).map{|i| @target_positions[i*2,2] }.map{|pta| average(pta) }
|
117
|
+
p4 = lps.last
|
118
|
+
vs = lps[0..-2].zip(lps[1..-1]).map{|a,b| (b-a) * 0.5 }
|
119
|
+
@vsd = Math.sqrt(vs.map{|v| v[0]}.sd**2 + vs.map{|v| v[1]}.sd**2)
|
120
|
+
return nil if @vsd > @sd_limit
|
121
|
+
v = average(vs)
|
122
|
+
return heading_for(average(lps)) if v.r < 4.0
|
123
|
+
p4 = p4 + (v*0.5)
|
124
|
+
distance = p4 - Vector[x,y]
|
125
|
+
shot_speed = (30/8.0)*v.r
|
126
|
+
a = distance[0]**2 + distance[1]**2
|
127
|
+
b = 2*distance[0]*v[0] + 2*distance[1]*v[1]
|
128
|
+
c = v[0]**2 + v[1]**2 - shot_speed**2
|
129
|
+
t = 2*a / (-b + Math.sqrt(b**2-4*a*c))
|
130
|
+
ep = p4 + v*t
|
131
|
+
estimated_position = Vector[
|
132
|
+
[size, [battlefield_width-size, ep[0]].min].max,
|
133
|
+
[size, [battlefield_height-size, ep[1]].min].max]
|
134
|
+
heading_for(estimated_position) + (rand-0.5)*@vsd*0.2
|
135
|
+
end
|
136
|
+
|
137
|
+
def heading_for(position)
|
138
|
+
distance = position - Vector[x,y]
|
139
|
+
heading = (Math.atan2(-distance[1], distance[0])).rad2deg
|
140
|
+
heading += 360 if heading < 0
|
141
|
+
heading
|
142
|
+
end
|
143
|
+
|
144
|
+
def heading_distance h1, h2
|
145
|
+
limit h2 - h1, 180
|
146
|
+
end
|
147
|
+
|
148
|
+
def limit value, m
|
149
|
+
value -= 360 if value > 180
|
150
|
+
value += 360 if value < -180
|
151
|
+
value = -m if value < -m
|
152
|
+
value = m if value > m
|
153
|
+
return value
|
154
|
+
end
|
155
|
+
|
156
|
+
def gun_radar_distance
|
157
|
+
heading_distance gun_heading, radar_heading
|
158
|
+
end
|
159
|
+
|
160
|
+
def turn_hull
|
161
|
+
turn_amt = [-10.0, [@wanted_turn, 10.0].min].max
|
162
|
+
turn turn_amt
|
163
|
+
@wanted_turn -= turn_amt
|
164
|
+
@wanted_gun_turn -= turn_amt
|
165
|
+
@wanted_radar_turn -= turn_amt
|
166
|
+
end
|
167
|
+
|
168
|
+
def turn_turret
|
169
|
+
turn_amt = [-30.0, [@wanted_gun_turn, 30.0].min].max
|
170
|
+
turn_gun turn_amt
|
171
|
+
@wanted_gun_turn -= turn_amt
|
172
|
+
@wanted_radar_turn -= turn_amt
|
173
|
+
end
|
174
|
+
|
175
|
+
def turn_radar_dish
|
176
|
+
turn_amt = [-60.0, [@wanted_radar_turn, 60.0].min].max
|
177
|
+
turn_radar turn_amt
|
178
|
+
@wanted_radar_turn -= turn_amt
|
179
|
+
end
|
180
|
+
|
181
|
+
def approaching_wall?
|
182
|
+
if not ( (velocity > 0) ^ heading.between?(0.0, 180.0) )
|
183
|
+
y < 100
|
184
|
+
else
|
185
|
+
y > battlefield_height - 100
|
186
|
+
end or if not ( (velocity > 0) ^ heading.between?(90.0, 270.0) )
|
187
|
+
x < 100
|
188
|
+
else
|
189
|
+
x > battlefield_width - 100
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|