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,13 @@
1
+ require 'robot'
2
+
3
+ class MsgBot
4
+ include Robot
5
+
6
+ def tick events
7
+ events['broadcasts'].each{|msg,dir|
8
+ say "Got message #{msg.inspect} from #{dir}!"
9
+ }
10
+ broadcast "Hello! Team #{team}!" if rand < 0.01
11
+ end
12
+
13
+ end
@@ -0,0 +1,13 @@
1
+ require 'robot'
2
+
3
+ class NervousDuck
4
+ include Robot
5
+
6
+ def tick events
7
+ turn_radar 1 if time == 0
8
+ turn_gun 30 if time < 3
9
+ accelerate 1
10
+ turn 2
11
+ fire 3 unless events['robot_scanned'].empty?
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ require 'robot'
2
+ class Polisher
3
+ include Robot
4
+ def tick events
5
+ @min_distance = (events['robot_scanned'].min || [0]).first
6
+ @radar_scan ||= 20.0
7
+ @mid ||= (((x - battlefield_width / 2).abs < 400) and ((y - battlefield_height / 2).abs < 400))
8
+ accelerate(@mid ? (Math.sin(time*0.1)*2)+0.8 : 1.0)
9
+ turn(@mid ? 10 : 2)
10
+ @radar_scan = events['robot_scanned'].empty? ? [40.0,@radar_scan*1.5].min : [15.0,@radar_scan*0.5].max
11
+ @rt = (@radar_scan > 39.0) ? @radar_scan : @radar_scan*((time % 2)-0.5)
12
+ turn_gun @rt - (@mid ? 10 : 2)
13
+ fire 3
14
+ end
15
+ end
@@ -0,0 +1,514 @@
1
+ require 'robot'
2
+
3
+ # utilisation des matrices
4
+ require 'matrix'
5
+
6
+
7
+ module MathRobot
8
+
9
+ def coef_dir(point_1,point_2)
10
+ x1,y1 = point_1
11
+ x2,y2 = point_2
12
+ return (y2-y1)/(x2-x1)
13
+ end
14
+
15
+ def ordonne_origine(a,point)
16
+ x,y = point
17
+ return y - a*x
18
+ end
19
+
20
+
21
+ # calcule vectoriel pour déterminer l'angle de tir pour le prédicat fait avec la regression lineaire
22
+ # en utilisant le coeficient directeur a de ma f(x) = ax + b trouvé
23
+
24
+ # dfférence de deux vecteur
25
+ def diff_vecteur(a,b)
26
+ return a.zip(b).map{|a,b| a - b}
27
+ end
28
+
29
+ # Produit scalaire carré du vecteur
30
+ def carre_scalaire_du_vecteur(a)
31
+ return produit_scalaire(a,a)
32
+ end
33
+
34
+ # produit_scalaire
35
+ def produit_scalaire(a,b)
36
+ return a.zip(b).map{|a,b| a*b}.inject(0){|a,b| a+b}
37
+ end
38
+
39
+
40
+ # On Utilise un régression linéaire pour déterminer le coef dir à suivre f(x) = ax + b
41
+ def reg_linaire(liste_x,liste_y)
42
+ somme_des_produits = 0.0
43
+ somme_des_x_au_carre = 0.0
44
+ somme_des_x = 0.0
45
+ somme_des_y = 0.0
46
+ taille = liste_x.size
47
+ # ma surcharge de Array va pas suffire
48
+ somme_des_x = liste_x.sum
49
+ somme_des_y = liste_y.sum
50
+ taille.times {|i|
51
+ somme_des_produits += liste_x[i]*liste_y[i]
52
+ somme_des_x_au_carre += liste_x[i]*liste_x[i]
53
+ }
54
+ # calcule de a et b selon une regression linaire
55
+ b = (taille*somme_des_produits - somme_des_x*somme_des_y) / (taille*somme_des_x_au_carre - somme_des_x*somme_des_x)
56
+ a = (somme_des_y - b*somme_des_x) / taille
57
+
58
+ raise ListeCoordTropPetite if a.nan? or b.nan? # on leve si a ou b tend vers - l'infini
59
+
60
+ return [a,b]
61
+ end
62
+
63
+ end
64
+
65
+
66
+
67
+ # Surcharge de Array pour calcule de Reg Lin
68
+ class Array
69
+ def sum
70
+ sumit = 0
71
+ self.each do |item|
72
+ sumit += item
73
+ end
74
+ return sumit
75
+ end
76
+ def mean
77
+ return self.sum / self.size
78
+ end
79
+ def max
80
+ self.sort.last
81
+ end
82
+ def min
83
+ self.sort.first
84
+ end
85
+ end
86
+
87
+
88
+ # surcharge de Float pour le round
89
+
90
+ class Float
91
+ def round2(precision=2)
92
+ return ("%01.#{precision}f" %self).to_f
93
+ end
94
+ end
95
+
96
+
97
+ class RobotConfig
98
+
99
+
100
+
101
+ # configuration du RomBot
102
+ attr_reader :vitesse_max_robot
103
+ attr_reader :calcul_taux_obux
104
+ attr_reader :range_correcteur_linaire
105
+ attr_reader :taux_de_tir_haut
106
+ attr_reader :taux_de_tir_bas
107
+ attr_reader :debug
108
+ attr_reader :critere_crise
109
+ attr_reader :mode_esquive
110
+ attr_reader :mode_say
111
+ attr_reader :critere_crise_vie_perte
112
+ attr_reader :critere_crise_vie_duree
113
+ attr_reader :cible_proche
114
+ attr_reader :cible_loin
115
+
116
+ def initialize
117
+ @vitesse_max_robot = 7 # max 8 min 1
118
+ @calcul_taux_obux = 30
119
+ @range_correcteur_linaire = 2 # taille de la range de mon predicteur
120
+ @taux_de_tir_haut = 0.1
121
+ @taux_de_tir_bas = 2
122
+ @debug = true
123
+ @critere_crise = 10
124
+ @mode_esquive = false
125
+ @mode_say = true
126
+ @critere_crise_vie_perte = 10
127
+ @critere_crise_vie_duree = 10
128
+ @cible_proche = 200
129
+ @cible_loin = 1000
130
+ end
131
+ end
132
+
133
+
134
+
135
+
136
+ class RomBot
137
+
138
+ include MathRobot
139
+ include Robot
140
+
141
+ def tick events
142
+ config_initiale if time == 0
143
+ maj_donnees_radar(events)
144
+ maj_donnees_canon
145
+ maj_context
146
+ reglage_taux_de_tir
147
+ detection_toolboxes(events)
148
+ if situation_crise?(events) then
149
+ @botlog.write "Situation de crise : #{@cumul_crise}\n" if @config.debug
150
+ speed = 0 if @config.mode_esquive
151
+ @taux_de_tir = @config.taux_de_tir_bas # Forçage de tir de puissance
152
+ end
153
+ accelerate 1
154
+ @botlog.write "vitesse = #{speed}\n" if @config.debug
155
+ say_msg if @config.mode_say
156
+ turn_radar(decalage_radar - @vitesse_arme_relative - @vitesse_agulaire)
157
+ turn_gun(@vitesse_arme_relative - @vitesse_agulaire)
158
+ turn(@vitesse_agulaire )
159
+ maj_vie_time
160
+ end
161
+
162
+
163
+ def detection_toolboxes(events)
164
+ unless events['toolbox_scanned'].empty? then
165
+ @botlog.write "scan toolbox #{events} pour time = #{time}\n"
166
+
167
+ end
168
+ end
169
+
170
+
171
+ def reglage_taux_de_tir
172
+ unless @distance_cible_plus_proche.nil?
173
+ dist = @distance_cible_plus_proche.to_i
174
+
175
+ if dist > @config.cible_proche and dist < @config.cible_loin then
176
+ @taux_de_tir = dist * @coef_dir_taux_de_tir + @ordonne_origine_taux_de_tir
177
+ @taux_de_tir = @taux_de_tir.round2(1)
178
+ elsif dist <= @config.cible_proche then
179
+ @taux_de_tir = @config.taux_de_tir_haut
180
+ elsif dist >= @config.cible_loin then
181
+ @taux_de_tir = @config.taux_de_tir_bas
182
+ end
183
+ end
184
+ end
185
+
186
+
187
+ def maj_vie_time
188
+ @botlog.write "energie = #{energy.to_i}\n" if @config.debug
189
+ if time == @time_derniere + @config.critere_crise_vie_duree then
190
+ if @check_vie_derniere - energy.to_i >= @config.critere_crise_vie_perte then
191
+ @cumul_crise += @config.critere_crise unless (@cumul_crise > @config.critere_crise)
192
+ @botlog.write "energie crise\n" if @config.debug
193
+ end
194
+ @check_vie_derniere = energy.to_i
195
+ @time_derniere = time
196
+ end
197
+ end
198
+
199
+
200
+ def situation_crise?(events)
201
+ res = false
202
+ # @botlog.write("scan cible x : #{@pos_cible_ennemi_x}\t y : #{@pos_cible_ennemi_y}\t pour time = #{time}\n") if @config.debug
203
+ unless events['got_hit'].empty? then
204
+ @cumul_crise += events['got_hit'].size
205
+ else
206
+ @cumul_crise -= 1 if @cumul_crise > 0
207
+ end
208
+ res = true if @cumul_crise > @config.critere_crise
209
+ return res
210
+ end
211
+
212
+
213
+ def say_msg
214
+ chaine = String::new
215
+ chaine << "X: #{x.to_i} "
216
+ chaine << "Y: #{y.to_i}\n"
217
+ chaine <<"DEBUG\n" if @config.debug
218
+ chaine << "ESQUIVE\n" if @config.mode_esquive
219
+ chaine << "Energy : #{energy.to_i}\n"
220
+ chaine << "Critic #{@cumul_crise}"
221
+ chaine << " !!" if @cumul_crise > @config.critere_crise
222
+ chaine << "\n"
223
+ chaine << "Speed : #{speed}\n"
224
+ chaine << "Fire rate : #{@taux_de_tir}\n"
225
+ chaine << "Proxy : #{@distance_cible_plus_proche.to_i}" unless @distance_cible_plus_proche.nil?
226
+ chaine << @msg
227
+ say chaine
228
+ end
229
+
230
+
231
+
232
+ def mode_recherche
233
+ @vitesse_base_radar = limiteur(@vitesse_base_radar + amplitude_angle_vers_cible_ennemi, 0, 60)
234
+
235
+ if @cumul_ticks > 0
236
+ @cumul_ticks -= 1
237
+ if @cumul_ticks == 0
238
+ @radar_direction *= -1
239
+ end
240
+ end
241
+ end
242
+
243
+ def debut_detection(dist)
244
+ @contexte_prevision_time = beam_center
245
+ @uptick_dist = dist
246
+ end
247
+
248
+ def cible_verrouille(dist)
249
+ @uptick_dist = dist
250
+ end
251
+
252
+ def perte_cible
253
+ @radar_direction *= -1
254
+ @vitesse_base_radar = limiteur(@vitesse_base_radar * 0.5, amplitude_angle_vers_cible_ennemi, 60)
255
+ marquage_cible_ennemi(angle_median(angle_median(@contexte_radar_precedant,@plus_vielle_detection_radar),@contexte_prevision_time),@uptick_dist)
256
+ @cumul_ticks = 8
257
+ end
258
+
259
+ def beam_center
260
+ angle_median(radar_heading, @contexte_radar_precedant)
261
+ end
262
+
263
+ def tirer_canon(propagation)
264
+ # je tire tout le temps même quand je suis pas en mode accrochage ou debut accrochage
265
+ # if propagation < 1
266
+ fire @taux_de_tir
267
+ # end
268
+ end
269
+
270
+
271
+ def maj_donnees_radar(events)
272
+ if events['robot_scanned'].empty?
273
+ if @cible_scannee
274
+ perte_cible
275
+ @msg = "LOOSE"
276
+ @botlog.write "perte cible\n" if @config.debug
277
+ else
278
+ @msg = "SCAN"
279
+ @botlog.write "scan cible\n" if @config.debug
280
+ mode_recherche
281
+ end
282
+ @cible_scannee = false
283
+ else
284
+ td = events['robot_scanned'].min.first
285
+ @distance_cible_plus_proche = td
286
+ if @cible_scannee
287
+ @msg = "LOCK"
288
+ @botlog.write "cible locke\n" if @config.debug
289
+ cible_verrouille(td)
290
+ else
291
+ @msg = "SEEK"
292
+ @botlog.write "acquisition cible\n" if @config.debug
293
+ debut_detection(td)
294
+ end
295
+ @cible_scannee = true
296
+ end
297
+ @plus_vielle_detection_radar = @contexte_radar_precedant
298
+ @contexte_radar_precedant = radar_heading
299
+ end
300
+
301
+
302
+ def maj_donnees_canon
303
+ diff = angle_direction(gun_heading, @detecteur.angle_de_tir(x,y,time))
304
+ @vitesse_arme_relative = limiteur(diff,-30,30)
305
+ tirer_canon(diff)
306
+ rescue ListeCoordTropPetite
307
+ end
308
+
309
+ def anti_collision_murs(range)
310
+ (2**((battlefield_width - range)/50.0))/(2**(battlefield_width/50.0))
311
+ end
312
+
313
+ def maj_context
314
+ ranges = [x-size, battlefield_height-size-y, battlefield_width-size-x, y-size]
315
+ normals = [0, 90, 180, 270]
316
+ forces = ranges.map {|r| anti_collision_murs(r)}
317
+
318
+ @xforce = forces[0] - forces[2]
319
+ @yforce = forces[3] - forces[1]
320
+ fa = Math.atan2(-@yforce,@xforce).to_deg
321
+
322
+ objectif = trajectoire_cible_ennemi + 90
323
+ unless soustraction_angles(heading, objectif) < 90
324
+ objectif = (objectif + 180) % 360
325
+ end
326
+
327
+ diff = angle_direction(objectif, fa)
328
+ objectif += diff*(forces.max)
329
+ @vitesse_agulaire = limiteur(angle_direction(heading, objectif),-10,10)
330
+ end
331
+
332
+
333
+ def config_initiale
334
+
335
+ @config = RobotConfig.new
336
+
337
+ # log file
338
+ @botlog = File.open("Rombot.log","w") if @config.debug
339
+ @botlog.write "Démmarrage du RomBot\n" if @config.debug
340
+ @coef_dir_taux_de_tir = coef_dir([@config.cible_proche,@config.taux_de_tir_bas],[@config.cible_loin,@config.taux_de_tir_haut])
341
+ @ordonne_origine_taux_de_tir = ordonne_origine( @coef_dir_taux_de_tir, [@config.cible_proche,@config.taux_de_tir_bas])
342
+ @botlog.write "le taux de tir répond à : f(x) = #{@coef_dir_taux_de_tir}.x + #{@ordonne_origine_taux_de_tir}\n" if @config.debug
343
+ @msg = "INIT"
344
+ @touche = false
345
+ @vitesse_base_radar = 60
346
+ @radar_direction = 1
347
+ @contexte_radar_precedant = 0
348
+ @plus_vielle_detection_radar = 0
349
+ @cumul_ticks = 0
350
+ @cumul_crise = 0
351
+ @taux_de_tir = @config.taux_de_tir_haut
352
+ @cible_scannee = false
353
+ @contexte_prevision_time = 0
354
+ @pos_cible_ennemi_x = @pos_cible_ennemi_y = 0
355
+ @vitesse_arme_relative = 0
356
+ @vitesse_agulaire = 0
357
+ @detecteur = DetecteurPredictif.new
358
+ @check_vie_derniere = 100
359
+ @time_derniere = 0
360
+ @distance_cible_plus_proche = 1800
361
+
362
+ @botlog.write "Fin INIT \n" if @config.debug
363
+ end
364
+
365
+ def soustraction_angles(a,b)
366
+ d = (a % 360 - b % 360).abs
367
+ d > 180 ? 360 - d : d
368
+ end
369
+
370
+ # définir le décalage positif ou negatif
371
+ def angle_direction(a,b)
372
+ azimut = soustraction_angles(a,b)
373
+ if soustraction_angles(a + 1, b) < azimut
374
+ azimut
375
+ else
376
+ -azimut
377
+ end
378
+ end
379
+
380
+ def decalage_radar
381
+ @vitesse_base_radar * @radar_direction
382
+ end
383
+
384
+ def angle_median(a,b)
385
+ (angle_direction(a,b) / 2 + a) % 360
386
+ end
387
+
388
+ def amplitude_angle_vers_cible_ennemi
389
+ 360 * @config.vitesse_max_robot / (2 * Math::PI * distance_cible_ennemi)
390
+ end
391
+
392
+ def trajectoire_cible_ennemi
393
+ Math.atan2(y- @pos_cible_ennemi_y, @pos_cible_ennemi_x - x).to_deg
394
+ end
395
+
396
+ def distance_cible_ennemi
397
+ Math.sqrt((@pos_cible_ennemi_x - x)**2 + (@pos_cible_ennemi_y - y)**2)
398
+ end
399
+
400
+ def marquage_cible_ennemi(trajectoire, distance)
401
+ rads = trajectoire.to_rad
402
+ @pos_cible_ennemi_y = y - distance * Math.sin(rads)
403
+ @pos_cible_ennemi_x = x + distance * Math.cos(rads)
404
+ @detecteur.marquage(@pos_cible_ennemi_x,@pos_cible_ennemi_y,time)
405
+ @botlog.write("scan cible x : #{@pos_cible_ennemi_x}\t y : #{@pos_cible_ennemi_y}\t pour time = #{time}\n") if @config.debug
406
+
407
+ end
408
+
409
+ def limiteur(var, min, max)
410
+ val = 0 + var
411
+ if val > max
412
+ max
413
+ elsif val < min
414
+ min
415
+ else
416
+ val
417
+ end
418
+ end
419
+
420
+ end
421
+
422
+ # classe d'exception pour les moindres carrés
423
+ class ListeCoordTropPetite < RuntimeError; end
424
+
425
+
426
+ class DetecteurPredictif
427
+
428
+
429
+ include MathRobot
430
+
431
+ def initialize(taille = 4)
432
+ @config = RobotConfig.new
433
+ @taille = taille || @config.range_correcteur_linaire
434
+ @x = Array.new(@taille,0)
435
+ @y = Array.new(@taille,0)
436
+ @t = Array.new(@taille,0)
437
+ @most_recent = 0
438
+ @solution = nil
439
+ end
440
+
441
+
442
+
443
+ def resoud
444
+ coef_dir_x, vx = reg_linaire(@t, @x)
445
+ coef_dir_y, vy = reg_linaire(@t, @y)
446
+ return [vx,vy,coef_dir_x,coef_dir_y]
447
+ end
448
+
449
+ # predits la position de la cible pour un time donné
450
+ def predit(time)
451
+ raise ListeCoordTropPetite unless @solution
452
+ vx, vy, coef_dir_x, coef_dir_y = @solution
453
+ [coef_dir_x + vx*time, coef_dir_y + vy*time]
454
+ end
455
+
456
+
457
+ def marquage(x,y,time)
458
+ @most_recent = (@most_recent + 1) % @taille
459
+ @x[@most_recent] = x
460
+ @y[@most_recent] = y
461
+ @t[@most_recent] = time
462
+ @solution = resoud
463
+ rescue
464
+ end
465
+
466
+
467
+
468
+ def point_cible(mon_x, mon_y, time)
469
+ raise ListeCoordTropPetite unless @solution
470
+ t = 0
471
+ loop do
472
+ x,y = predit(time+t) # on se base sur le dernier prédicat fiable
473
+ break if carre_scalaire_du_vecteur(diff_vecteur([x,y],[mon_x,mon_y])) < @config.calcul_taux_obux*@config.calcul_taux_obux*t*t
474
+ t += 1
475
+ raise ListeCoordTropPetite if t > 100
476
+ end
477
+ predit(time+t)
478
+ end
479
+
480
+ # calcule e fonction des coordonné du point cible de l'angle de tir via l'Arctangente du vecteur entre source tank et cible
481
+ def angle_de_tir(mon_x,mon_y,time)
482
+ x,y = point_cible(mon_x,mon_y,time)
483
+ Math.atan2(mon_y-y,x-mon_x).to_deg
484
+ end
485
+
486
+
487
+ # On Utilise un régression linéaire pour déterminer le coef dir à suivre f(x) = ax + b
488
+ def reg_linaire(liste_x,liste_y)
489
+ somme_des_produits = 0.0
490
+ somme_des_x_au_carre = 0.0
491
+ somme_des_x = 0.0
492
+ somme_des_y = 0.0
493
+ taille = liste_x.size
494
+ # ma surcharge de Array va pas suffire
495
+ somme_des_x = liste_x.sum
496
+ somme_des_y = liste_y.sum
497
+ taille.times {|i|
498
+ somme_des_produits += liste_x[i]*liste_y[i]
499
+ somme_des_x_au_carre += liste_x[i]*liste_x[i]
500
+ }
501
+ # calcule de a et b selon une regression linaire
502
+ b = (taille*somme_des_produits - somme_des_x*somme_des_y) / (taille*somme_des_x_au_carre - somme_des_x*somme_des_x)
503
+ a = (somme_des_y - b*somme_des_x) / taille
504
+
505
+ raise ListeCoordTropPetite if a.nan? or b.nan? # on leve si a ou b tend vers - l'infini
506
+
507
+ return [a,b]
508
+ end
509
+
510
+
511
+
512
+ end
513
+
514
+