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,205 @@
|
|
|
1
|
+
# RoomPainter
|
|
2
|
+
# written by Jannis Harder (jix) in 2005
|
|
3
|
+
|
|
4
|
+
require 'robot'
|
|
5
|
+
|
|
6
|
+
# avoid clashes with other state robots
|
|
7
|
+
|
|
8
|
+
module RoomPainterTools
|
|
9
|
+
|
|
10
|
+
# a state based robot
|
|
11
|
+
class StateRobot
|
|
12
|
+
include Robot
|
|
13
|
+
|
|
14
|
+
def initialize(*)
|
|
15
|
+
super
|
|
16
|
+
@mode = :idle
|
|
17
|
+
@sec_modes = []
|
|
18
|
+
init
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# set mode for next tick
|
|
22
|
+
def next_mode new_mode
|
|
23
|
+
if has_mode? new_mode
|
|
24
|
+
@mode = new_mode
|
|
25
|
+
else
|
|
26
|
+
warn "Robot #{self.class} switched to unknown mode :#{new_mode}!"
|
|
27
|
+
@mode = :idle
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# activate a secondary mode
|
|
32
|
+
def add_sec_mode new_mode
|
|
33
|
+
if has_mode? new_mode
|
|
34
|
+
@sec_modes << new_mode
|
|
35
|
+
else
|
|
36
|
+
warn "Robot #{self.class} switched to unknown secondary mode :#{new_mode}!"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# activate some secondary modes
|
|
41
|
+
def add_sec_modes *modes
|
|
42
|
+
modes.flatten.each do |new_mode|
|
|
43
|
+
add_sec_mode new_mode
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# deactivate a secondary mode
|
|
48
|
+
def del_sec_mode old_mode
|
|
49
|
+
@sec_modes.delete old_mode
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# deactivate some secondary modes
|
|
53
|
+
def del_sec_modes *modes
|
|
54
|
+
modes.flatten.each do |old_mode|
|
|
55
|
+
del_sec_mode old_mode
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# test for a mode
|
|
60
|
+
def has_mode? new_mode
|
|
61
|
+
respond_to? new_mode.to_s<<'_tick'
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# set new mode and tick it once
|
|
65
|
+
def mode new_mode
|
|
66
|
+
next_mode new_mode
|
|
67
|
+
tick @events
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# tick a mode
|
|
71
|
+
def tick_mode temp_mode
|
|
72
|
+
send temp_mode.to_s<<'_tick'
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# default tick
|
|
76
|
+
def idle_tick
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# processing
|
|
80
|
+
def tick events
|
|
81
|
+
@events = events
|
|
82
|
+
tick_mode @mode
|
|
83
|
+
@sec_modes.each do |smode|
|
|
84
|
+
tick_mode smode
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
attr_reader :events
|
|
90
|
+
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
class RoomPainter < RoomPainterTools::StateRobot
|
|
96
|
+
|
|
97
|
+
def init
|
|
98
|
+
next_mode :move
|
|
99
|
+
add_sec_modes :aim, :scan, :fire
|
|
100
|
+
@scan_range = 2
|
|
101
|
+
@tracking = 0
|
|
102
|
+
@fire = [nil]*2
|
|
103
|
+
@turning = 0
|
|
104
|
+
@deg = 0
|
|
105
|
+
@acc = 1
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
#helpers
|
|
110
|
+
|
|
111
|
+
def offset(heading_a,heading_b)
|
|
112
|
+
my_offset = heading_a-heading_b % 360
|
|
113
|
+
my_offset = my_offset -360 if my_offset > 180
|
|
114
|
+
my_offset
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def on_wall
|
|
118
|
+
x <= size or \
|
|
119
|
+
y <= size or \
|
|
120
|
+
x >= battlefield_width-size or \
|
|
121
|
+
y >= battlefield_height-size
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def nth?(n)
|
|
125
|
+
time % n == 0
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
#ticks
|
|
129
|
+
|
|
130
|
+
def turn_upwards_tick
|
|
131
|
+
stop
|
|
132
|
+
if heading == 90
|
|
133
|
+
mode :paint
|
|
134
|
+
|
|
135
|
+
else
|
|
136
|
+
turn 90-heading
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def scan_tick
|
|
141
|
+
@scan_range = [@scan_range,10].min
|
|
142
|
+
|
|
143
|
+
radar_offset = offset(radar_heading,gun_heading)
|
|
144
|
+
if nth? 2
|
|
145
|
+
turn_radar -@scan_range-radar_offset
|
|
146
|
+
else
|
|
147
|
+
turn_radar +@scan_range-radar_offset
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def fire_tick
|
|
152
|
+
if x = @fire.pop
|
|
153
|
+
fire x
|
|
154
|
+
end
|
|
155
|
+
if scanned = events['robot_scanned'].first
|
|
156
|
+
away = scanned.first
|
|
157
|
+
str = [0.1,800.0/away].max
|
|
158
|
+
@fire << str
|
|
159
|
+
else
|
|
160
|
+
@fire << nil
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def aim_tick
|
|
166
|
+
|
|
167
|
+
if scanned = events['robot_scanned'].first
|
|
168
|
+
away = scanned.first
|
|
169
|
+
@scan_range = 1.2
|
|
170
|
+
|
|
171
|
+
@last_offset = offset(radar_heading,gun_heading)/2.0
|
|
172
|
+
turn_gun(@last_offset)
|
|
173
|
+
@tracking = 10
|
|
174
|
+
elsif @tracking <= 0
|
|
175
|
+
@scan_range += 0.1
|
|
176
|
+
if @deg > 0
|
|
177
|
+
turn_gun(-30)
|
|
178
|
+
else
|
|
179
|
+
turn_gun(30)
|
|
180
|
+
end
|
|
181
|
+
else
|
|
182
|
+
@tracking-=1
|
|
183
|
+
@last_offset*=-2
|
|
184
|
+
turn_gun(@last_offset)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def move_tick
|
|
190
|
+
accelerate(@acc)
|
|
191
|
+
if @turning <= 0
|
|
192
|
+
@turning = rand(30)
|
|
193
|
+
@deg = (rand*4)*(1-rand(2)*2)
|
|
194
|
+
end
|
|
195
|
+
@turning-=1
|
|
196
|
+
if on_wall and (velocity < 0) == (@acc < 0) and velocity.abs > 4
|
|
197
|
+
@acc *= -1
|
|
198
|
+
else
|
|
199
|
+
turn(@deg)
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
end
|
data/robots/Rrrkele.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'robot'
|
|
2
|
+
|
|
3
|
+
class Rrrkele
|
|
4
|
+
include Robot
|
|
5
|
+
|
|
6
|
+
def limit 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
|
+
if time == 0
|
|
16
|
+
@acc = 1
|
|
17
|
+
@target_distance = 250
|
|
18
|
+
@target_heading = rand * 360
|
|
19
|
+
@scanning_range = 60
|
|
20
|
+
@velocity = 0
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
unless events['robot_scanned'].empty?
|
|
24
|
+
@target_distance = events["robot_scanned"].first.first
|
|
25
|
+
@target_heading = @radar_heading
|
|
26
|
+
@scanning_range *= -0.5 if @scanning_range.abs > 0.5
|
|
27
|
+
else
|
|
28
|
+
@scanning_range *= -2 if @scanning_range.abs < 60
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
unless events['got_hit'].empty?
|
|
32
|
+
@acc *= -1
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
fire 0.1
|
|
36
|
+
|
|
37
|
+
body_turn_angle = limit(@heading - @target_heading + 90, 10)
|
|
38
|
+
gun_turn_angle = limit(@target_heading - @gun_heading - body_turn_angle, 30)
|
|
39
|
+
radar_turn_angle = limit(@scanning_range - gun_turn_angle - body_turn_angle, 60)
|
|
40
|
+
|
|
41
|
+
turn(body_turn_angle)
|
|
42
|
+
turn_gun(gun_turn_angle)
|
|
43
|
+
turn_radar(radar_turn_angle)
|
|
44
|
+
|
|
45
|
+
accelerate(@acc)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
data/robots/Seeker.rb
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# follows and shoots
|
|
2
|
+
require 'robot'
|
|
3
|
+
|
|
4
|
+
class Seeker
|
|
5
|
+
include Robot
|
|
6
|
+
|
|
7
|
+
attr_accessor
|
|
8
|
+
|
|
9
|
+
def initialize *args, &block
|
|
10
|
+
@rt = @radar_scan = 10
|
|
11
|
+
@min_radar_scan = 10.0
|
|
12
|
+
@max_radar_scan = 30.0
|
|
13
|
+
@radar_turned = false
|
|
14
|
+
@min_distance = 0
|
|
15
|
+
@direction = 1
|
|
16
|
+
super
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def tick events
|
|
20
|
+
@direction = @min_distance - 175
|
|
21
|
+
accelerate(@direction)
|
|
22
|
+
wturn = 180 - ((radar_heading-heading)%360) + @rt*0.5
|
|
23
|
+
wturn = [-10,[10,wturn].min].max
|
|
24
|
+
turn wturn
|
|
25
|
+
scan events
|
|
26
|
+
turn_radar @rt - wturn
|
|
27
|
+
fire @direction > 0 ? 0.5 : 3.0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def scan events
|
|
31
|
+
if events['robot_scanned'].empty?
|
|
32
|
+
increase_radar_scan
|
|
33
|
+
else
|
|
34
|
+
decrease_radar_scan
|
|
35
|
+
@min_distance = events['robot_scanned'].min.first
|
|
36
|
+
end
|
|
37
|
+
@rt = if @radar_turned
|
|
38
|
+
-@radar_scan
|
|
39
|
+
else
|
|
40
|
+
@radar_scan
|
|
41
|
+
end if @radar_scan.abs < @max_radar_scan - 0.1
|
|
42
|
+
@radar_turned = !@radar_turned
|
|
43
|
+
@rt
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def increase_radar_scan
|
|
47
|
+
@radar_scan *= 1.5
|
|
48
|
+
@radar_scan = [@radar_scan, @max_radar_scan].min
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def decrease_radar_scan
|
|
52
|
+
@radar_scan *= 0.5
|
|
53
|
+
@radar_scan = [@radar_scan, @min_radar_scan].max
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'robot'
|
|
2
|
+
|
|
3
|
+
class SittingDuck
|
|
4
|
+
include Robot
|
|
5
|
+
|
|
6
|
+
def tick events
|
|
7
|
+
turn_radar 5 if time == 0
|
|
8
|
+
fire 3 unless events['robot_scanned'].empty?
|
|
9
|
+
turn_gun 10
|
|
10
|
+
|
|
11
|
+
@last_hit = time unless events['got_hit'].empty?
|
|
12
|
+
if @last_hit && time - @last_hit < 20
|
|
13
|
+
accelerate(1)
|
|
14
|
+
else
|
|
15
|
+
stop
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,277 @@
|
|
|
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 SniperDuck
|
|
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 = if @radar_turned
|
|
79
|
+
-@radar_scan
|
|
80
|
+
else
|
|
81
|
+
@radar_scan
|
|
82
|
+
end if @radar_scan.abs < @max_radar_scan - 0.1
|
|
83
|
+
@wanted_radar_turn += @rt
|
|
84
|
+
@radar_turned = !@radar_turned
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def firing_solution events
|
|
88
|
+
add_target_position(events['robot_scanned'])
|
|
89
|
+
gtd = gun_target_distance
|
|
90
|
+
@firepower = [1.5e5 / (@min_distance)**2, 3*25 / (@vsd||1500)].max
|
|
91
|
+
fire @firepower if @on_target
|
|
92
|
+
if @lock and gtd and gtd.abs < @firing_threshold
|
|
93
|
+
@wanted_gun_turn = gtd
|
|
94
|
+
@on_target = true
|
|
95
|
+
else
|
|
96
|
+
fire @firepower
|
|
97
|
+
@wanted_gun_turn = (gtd || (gun_radar_distance/3.0) + Math.sin(time*0.2)*(@vsd||50)/10)
|
|
98
|
+
@on_target = false
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def add_target_position(distances)
|
|
103
|
+
unless distances.empty?
|
|
104
|
+
positions = distances.map{|d|
|
|
105
|
+
tx = x + Math.cos((radar_heading - @radar_scan.abs / 2.0).deg2rad) * d[0]
|
|
106
|
+
ty = y - Math.sin((radar_heading - @radar_scan.abs / 2.0).deg2rad) * d[0]
|
|
107
|
+
[d, Vector[tx,ty]]
|
|
108
|
+
}
|
|
109
|
+
last = @target_positions.last
|
|
110
|
+
position = if last
|
|
111
|
+
positions.min{|a,b| (a[1] - last).r <=> (b[1] - last).r }[1]
|
|
112
|
+
else
|
|
113
|
+
positions.min{|a,b| a[0] <=> b[0]}[1]
|
|
114
|
+
end
|
|
115
|
+
@min_distance = distances.min{|a,b| a[0]<=>b[0]}[0]
|
|
116
|
+
@target_positions.push position if position
|
|
117
|
+
end
|
|
118
|
+
@target_positions.shift if @target_positions.size > 200
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def average_four_last_positions
|
|
122
|
+
c = 5
|
|
123
|
+
tps = @target_positions[-20,20]
|
|
124
|
+
ptas = (0...tps.size/c).map{|i| tps[i*c,c] }
|
|
125
|
+
ptas.map{|pta| average(pta) }
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def average arr
|
|
129
|
+
arr.inject{|s,i| s+i} * (1.0/arr.size)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def sd arr
|
|
133
|
+
Math.sqrt(arr.map{|v| v[0]}.sd**2 + arr.map{|v| v[1]}.sd**2)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def gun_target_distance
|
|
137
|
+
return nil if @target_positions.size < 20
|
|
138
|
+
p1,p2,p3,p4 = average_four_last_positions
|
|
139
|
+
#p format([p1,p2,p3,p4].map{|i|i.to_a})
|
|
140
|
+
vs = [p1,p2,p3].zip([p2,p3,p4]).map{|a,b|b-a}
|
|
141
|
+
@vsd = sd vs
|
|
142
|
+
return nil if @vsd > @sd_limit
|
|
143
|
+
v = average(vs) * 0.2
|
|
144
|
+
return gun_radar_distance if v.r < 4.0
|
|
145
|
+
p4 = p4 + (v*3)
|
|
146
|
+
distance = p4 - Vector[x,y]
|
|
147
|
+
a = distance[0]**2 + distance[1]**2
|
|
148
|
+
b = 2*distance[0]*v[0] + 2*distance[1]*v[1]
|
|
149
|
+
c = v[0]**2 + v[1]**2
|
|
150
|
+
shot_speed = (30/8.0)*v.r
|
|
151
|
+
#p shot_speed
|
|
152
|
+
d = c - shot_speed**2
|
|
153
|
+
n = b**2 - 4*a*d
|
|
154
|
+
if n < 0
|
|
155
|
+
return nil
|
|
156
|
+
end
|
|
157
|
+
t = 2*a / (-b + Math.sqrt(n))
|
|
158
|
+
ep = p4 + v*t
|
|
159
|
+
estimated_position = Vector[[size, [battlefield_width-size, ep[0]].min].max, [size, [battlefield_height-size, ep[1]].min].max]
|
|
160
|
+
est_head = heading_for(estimated_position)
|
|
161
|
+
hd = heading_distance(gun_heading, est_head+rand*(@vsd-@vsd/2.0)/(distance.r/500))
|
|
162
|
+
#p format( [@target_positions.last, p4, v, [t], estimated_position, [est_head, gun_heading, hd]].map{|i|i.to_a} )
|
|
163
|
+
hd
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def format(arr, precision = 1)
|
|
167
|
+
case arr
|
|
168
|
+
when Float
|
|
169
|
+
(arr * 10**precision).round * 10**-precision
|
|
170
|
+
when Array
|
|
171
|
+
arr.map{|i| format i, precision}
|
|
172
|
+
else
|
|
173
|
+
arr
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def gun_vector
|
|
178
|
+
Vector[Math.cos(gun_heading.deg2rad), -Math.sin(gun_heading.deg2rad)]
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def heading_for(position)
|
|
182
|
+
distance = position - Vector[x,y]
|
|
183
|
+
heading = (Math.atan2(-distance[1], distance[0])).rad2deg
|
|
184
|
+
heading += 360 if heading < 0
|
|
185
|
+
heading
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def navigate events
|
|
189
|
+
if events['got_hit'].empty?
|
|
190
|
+
@serial_hit_counter -= 0.05 if @serial_hit_counter > 0
|
|
191
|
+
accelerate(@racc_dir) if velocity.abs < 7.9
|
|
192
|
+
else
|
|
193
|
+
@serial_hit_counter += @prev_health - events['got_hit'].last.last
|
|
194
|
+
@serial_hit_counter = [@serial_hit_counter, @serial_hit_limit + 0.04].max
|
|
195
|
+
if @serial_hit_counter > @serial_hit_limit
|
|
196
|
+
acc = velocity > 0 ? 1 : -1
|
|
197
|
+
accelerate(acc) if velocity.abs < 7.9
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
if @serial_hit_counter > @serial_hit_limit and not events['got_hit'].empty? and @wanted_turn <= 1
|
|
201
|
+
@wanted_turn = @rturn_dir * 30
|
|
202
|
+
@rturn_dir *= -1 if rand < 0.05
|
|
203
|
+
elsif approaching_wall? and @wanted_turn <= 1
|
|
204
|
+
@wanted_turn = 60 * @rturn_dir
|
|
205
|
+
@rturn_dir *= -1 if rand < 0.5
|
|
206
|
+
elsif rand < 0.15
|
|
207
|
+
@wanted_turn += rand * 10 * @rturn_dir
|
|
208
|
+
elsif rand < 0.01
|
|
209
|
+
@rturn_dir *= -1
|
|
210
|
+
elsif rand < 0.01
|
|
211
|
+
@racc_dir *= -1
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def increase_radar_scan
|
|
216
|
+
@radar_scan *= 1.5
|
|
217
|
+
@radar_scan = [@radar_scan, @max_radar_scan].min
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def decrease_radar_scan
|
|
221
|
+
@radar_scan *= 0.5
|
|
222
|
+
@radar_scan = [@radar_scan, @min_radar_scan].max
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def heading_distance h1, h2
|
|
226
|
+
limit h2 - h1, 180
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def limit value, m
|
|
230
|
+
value -= 360 if value > 180
|
|
231
|
+
value += 360 if value < -180
|
|
232
|
+
value = -m if value < -m
|
|
233
|
+
value = m if value > m
|
|
234
|
+
return value
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def gun_radar_distance
|
|
238
|
+
heading_distance gun_heading, radar_heading
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def turn_hull
|
|
242
|
+
turn_amt = [-10.0, [@wanted_turn, 10.0].min].max
|
|
243
|
+
#puts "Turning hull by: #{turn_amt}" if turn_amt.abs > 1
|
|
244
|
+
turn turn_amt
|
|
245
|
+
@wanted_turn -= turn_amt
|
|
246
|
+
@wanted_gun_turn -= turn_amt
|
|
247
|
+
@wanted_radar_turn -= turn_amt
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def turn_turret
|
|
251
|
+
turn_amt = [-30.0, [@wanted_gun_turn, 30.0].min].max
|
|
252
|
+
#puts "Turning gun by: #{turn_amt}" if turn_amt.abs > 1
|
|
253
|
+
turn_gun turn_amt
|
|
254
|
+
@wanted_gun_turn -= turn_amt
|
|
255
|
+
@wanted_radar_turn -= turn_amt
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def turn_radar_dish
|
|
259
|
+
turn_amt = [-60.0, [@wanted_radar_turn, 60.0].min].max
|
|
260
|
+
#puts "Turning radar by: #{turn_amt}" if turn_amt.abs > 1
|
|
261
|
+
turn_radar turn_amt
|
|
262
|
+
@wanted_radar_turn -= turn_amt
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def approaching_wall?
|
|
266
|
+
if not ( (velocity > 0) ^ heading.between?(0.0, 180.0) )
|
|
267
|
+
y < 100
|
|
268
|
+
else
|
|
269
|
+
y > battlefield_height - 100
|
|
270
|
+
end or if not ( (velocity > 0) ^ heading.between?(90.0, 270.0) )
|
|
271
|
+
x < 100
|
|
272
|
+
else
|
|
273
|
+
x > battlefield_width - 100
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
end
|