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,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
|