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.
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
+