UG_RRobots 1.3 → 2.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/bullets.rb CHANGED
@@ -35,5 +35,16 @@ class Bullet
35
35
  @dead = true
36
36
  end
37
37
  end
38
+
39
+ @battlefield.mines.each do |mine|
40
+ if (Math.hypot(@y - mine.y, mine.x - @x) < 10) && (!mine.dead) && (mine.origin != origin) then
41
+ explosion = Explosion.new(@battlefield, mine.x, mine.y)
42
+ @battlefield << explosion
43
+ mine.destroy if self.energy > @battlefield.config.mines[:bullet_energy_resistance]
44
+ origin.destroyed_mines += 1
45
+ @dead = true
46
+ end
47
+ end
48
+
38
49
  end
39
50
  end
data/lib/configuration.rb CHANGED
@@ -4,6 +4,7 @@ module Configuration_accessors
4
4
  attr_accessor :robots
5
5
  attr_accessor :bullets
6
6
  attr_accessor :battlefield
7
+ attr_accessor :mines
7
8
  end
8
9
 
9
10
  class Configuration
@@ -20,9 +21,10 @@ class Configuration
20
21
  @filename = filename
21
22
  @game = { :timeout => 50000 }
22
23
  @toolboxes = { :with_toolboxes => false, :life_time => 200, :spawning_chances => 100, :energy_heal_points => 20 }
23
- @robots = { :energy_max => 100 }
24
+ @robots = { :energy_max => 100, :nb_mines => 3, :radar_mine_scanning_performance => 500 }
24
25
  @bullets = { :speed => 30 }
25
26
  @battlefield = { :height => 800, :width => 800 }
27
+ @mines = { :with_mines => false, :energy_hit_points => 20, :bullet_energy_resistance => 2 }
26
28
  end
27
29
 
28
30
  end
data/lib/misc.rb ADDED
@@ -0,0 +1,29 @@
1
+
2
+ def gem_path(path='')
3
+ # TODO : Perhaps a better way to do it ...
4
+ # regarder Rubygems pour avoir le path direct ..
5
+ table_map = Gem.location_of_caller.first.split('/')
6
+ 2.times do
7
+ table_map.pop
8
+ end
9
+ table_map.push path unless path.empty?
10
+ path_prefix = table_map.join('/')
11
+ return false unless File::exist?(path_prefix)
12
+ return path_prefix
13
+ end
14
+
15
+ def init_I18n(locales)
16
+ I18n.default_locale = locales
17
+ locales_path = gem_path('config').concat("/locales")
18
+ I18n.load_path << Dir["#{locales_path}/*.yml"]
19
+ end
20
+
21
+ def get_locale_from_env
22
+ if not ENV['LANGUAGE'].empty? then
23
+ locale = ENV['LANGUAGE'].split('_').first
24
+ elsif not ENV['LANG'].empty? then
25
+ locale = ENV['LANG'].split('_').first
26
+ else
27
+ locale = 'en'
28
+ end
29
+ end
data/lib/overloads.rb CHANGED
@@ -7,4 +7,28 @@ class Numeric
7
7
  def to_deg
8
8
  self * TO_DEG
9
9
  end
10
- end
10
+ end
11
+
12
+ module RDoc
13
+ # File lib/rdoc/usage.rb, line 98
14
+ def RDoc.file_no_exit(filename,*args)
15
+ content = IO.readlines(filename).join
16
+ markup = SM::SimpleMarkup.new
17
+ flow_convertor = SM::ToFlow.new
18
+ flow = markup.convert(content, flow_convertor)
19
+
20
+ format = "plain"
21
+
22
+ unless args.empty?
23
+ flow = extract_sections(flow, args)
24
+ end
25
+
26
+ options = RI::Options.instance
27
+ if args = ENV["RI"]
28
+ options.parse(args.split)
29
+ end
30
+ formatter = options.formatter.new(options, "")
31
+ formatter.display_flow(flow)
32
+ end
33
+ end
34
+
data/lib/robot.rb CHANGED
@@ -14,13 +14,22 @@ module Robot
14
14
  define_method(n){|param| @actions[n] = param }
15
15
  }
16
16
  end
17
-
17
+
18
+ def self.attr_order(*names)
19
+ names.each{|n|
20
+ n = n.to_sym
21
+ define_method(n){ @orders[n] = true }
22
+ }
23
+ end
24
+
18
25
  def self.attr_event(*names)
19
26
  names.each{|n|
20
27
  n = n.to_sym
21
28
  define_method(n){ @events[n] }
22
29
  }
23
30
  end
31
+
32
+
24
33
 
25
34
  #the state hash of your robot. also accessible through the attr_state methods
26
35
  attr_accessor :state
@@ -30,6 +39,8 @@ module Robot
30
39
 
31
40
  #the event hash of your robot
32
41
  attr_accessor :events
42
+
43
+ attr_accessor :orders
33
44
 
34
45
  #path to where your robot's optional skin images are
35
46
  attr_accessor :skin_prefix
@@ -87,6 +98,8 @@ module Robot
87
98
 
88
99
  #fires a bullet in the direction of your gun, power is 0.1 - 3, this power is taken from your energy
89
100
  attr_action :fire
101
+
102
+ attr_order :drop_mine
90
103
 
91
104
  #turns the robot (and the gun and the radar), max 10 degrees per tick
92
105
  attr_action :turn
@@ -99,6 +112,9 @@ module Robot
99
112
 
100
113
  #broadcast message to other robots
101
114
  attr_action :broadcast
115
+
116
+ #team_broadcast message to other robots
117
+ attr_action :team_broadcast
102
118
 
103
119
  #say something to the spectators
104
120
  attr_action :say
@@ -109,12 +125,18 @@ module Robot
109
125
  #distances to robots your radar swept over during last tick
110
126
  attr_event :robot_scanned
111
127
 
112
- #distances to robots your radar swept over during last tick
128
+ #distances to toolboxes your radar swept over during last tick
113
129
  attr_event :toolbox_scanned
130
+
131
+ #distances to mines your radar swept over during last tick
132
+ attr_event :mine_scanned
114
133
 
115
134
  #broadcasts received last turn
116
135
  attr_event :broadcasts
117
136
 
137
+ #Team broadcasts received last turn
138
+ attr_event :team_broadcasts
139
+
118
140
  end
119
141
 
120
142
  require 'robotrunner'
data/lib/robotrunner.rb CHANGED
@@ -2,7 +2,9 @@ class RobotRunner
2
2
 
3
3
  STATE_IVARS = [ :x, :y, :gun_heat, :heading, :gun_heading, :radar_heading, :time, :size, :speed, :energy, :team ]
4
4
  NUMERIC_ACTIONS = [ :fire, :turn, :turn_gun, :turn_radar, :accelerate ]
5
- STRING_ACTIONS = [ :say, :broadcast ]
5
+ STRING_ACTIONS = [ :say, :broadcast, :team_broadcast ]
6
+ ORDERS = [ :drop_mine ]
7
+
6
8
 
7
9
  STATE_IVARS.each{|iv|
8
10
  attr_accessor iv
@@ -14,6 +16,10 @@ class RobotRunner
14
16
  attr_accessor "#{iv}_max"
15
17
  }
16
18
 
19
+ ORDERS.each{|iv|
20
+ attr_accessor "#{iv}_max"
21
+ }
22
+
17
23
  #AI of this robot
18
24
  attr_accessor :robot
19
25
 
@@ -26,10 +32,14 @@ class RobotRunner
26
32
  #keeps track of the kills
27
33
  attr_accessor :kills
28
34
 
35
+ attr_accessor :destroyed_mines
36
+ attr_accessor :trigged_mines
37
+ attr_accessor :dropped_mines
38
+
29
39
  #keeps track of the catched toolboxes
30
40
  attr_accessor :catched_toolboxes
31
41
 
32
- attr_reader :actions, :speech
42
+ attr_reader :actions, :speech, :orders
33
43
 
34
44
  def initialize robot, bf, team=0
35
45
  @robot = robot
@@ -39,6 +49,7 @@ class RobotRunner
39
49
  set_initial_state
40
50
  @events = Hash.new{|h, k| h[k]=[]}
41
51
  @actions = Hash.new(0)
52
+ @orders = Hash.new(0)
42
53
  end
43
54
 
44
55
  def skin_prefix
@@ -57,7 +68,10 @@ class RobotRunner
57
68
  @energy = @battlefield.config.robots[:energy_max]
58
69
  @damage_given = 0
59
70
  @kills = 0
71
+ @destroyed_mines = 0
60
72
  @catched_toolboxes = 0
73
+ @dropped_mines = 0
74
+ @trigged_mines = 0
61
75
  teleport
62
76
  end
63
77
 
@@ -79,6 +93,8 @@ class RobotRunner
79
93
  @teleport_min, @teleport_max = 0, 100
80
94
  @say_max = 256
81
95
  @broadcast_max = 16
96
+ @team_broadcast_max = 16
97
+ @drop_mine_max = @battlefield.config.robots[:nb_mines]
82
98
  end
83
99
 
84
100
  def hit bullet
@@ -115,15 +131,28 @@ class RobotRunner
115
131
  update_state
116
132
  robot_tick
117
133
  parse_actions
134
+ parse_orders
118
135
  fire
136
+ drop_mine if @battlefield.with_mines
119
137
  turn
120
138
  move
121
139
  scan
122
140
  speak
123
141
  broadcast
142
+ team_broadcast
124
143
  @time += 1
125
144
  end
126
145
 
146
+ def parse_orders
147
+ @orders.clear
148
+ ORDERS.each{|on|
149
+ if @robot.orders[on] = true
150
+ @orders[on] = true
151
+ end
152
+ }
153
+ @orders
154
+ end
155
+
127
156
  def parse_actions
128
157
  @actions.clear
129
158
  NUMERIC_ACTIONS.each{|an|
@@ -155,7 +184,10 @@ class RobotRunner
155
184
  @robot.send("#{k}=", v)
156
185
  }
157
186
  @robot.events = @events.dup
187
+ @robot.orders ||= Hash.new(0)
158
188
  @robot.actions ||= Hash.new(0)
189
+ @robot.orders.clear
190
+ @robot.orders[:drop_mine] = false
159
191
  @robot.actions.clear
160
192
  end
161
193
 
@@ -165,7 +197,7 @@ class RobotRunner
165
197
  end
166
198
 
167
199
  def fire
168
- if (@actions[:fire] > 0) && (@gun_heat == 0)
200
+ if (@actions[:fire] > 0) && (@gun_heat == 0)
169
201
  bullet = Bullet.new(@battlefield, @x, @y, @gun_heading, @battlefield.config.bullets[:speed] , @actions[:fire]*3.0, self)
170
202
  3.times{bullet.tick}
171
203
  @battlefield << bullet
@@ -174,6 +206,15 @@ class RobotRunner
174
206
  @gun_heat -= 0.1
175
207
  @gun_heat = 0 if @gun_heat < 0
176
208
  end
209
+
210
+ def drop_mine
211
+ if (@orders[:drop_mine] == true) && (@actions[:fire] == 0) && (@dropped_mines < @drop_mine_max) then
212
+ energy = @battlefield.config.mines[:energy_hit_points]
213
+ mine = Mine.new(@battlefield, @x, @y, energy , self)
214
+ @battlefield << mine
215
+ @dropped_mines += 1
216
+ end
217
+ end
177
218
 
178
219
  def turn
179
220
  @old_radar_heading = @radar_heading
@@ -222,6 +263,17 @@ class RobotRunner
222
263
  end
223
264
  end
224
265
  end
266
+ @battlefield.mines.each do |mine|
267
+ if (!mine.dead)
268
+ a = Math.atan2(@y - mine.y, mine.x - @x) / Math::PI * 180 % 360
269
+ if (@old_radar_heading <= a && a <= @new_radar_heading) || (@old_radar_heading >= a && a >= @new_radar_heading) ||
270
+ (@old_radar_heading <= a+360 && a+360 <= @new_radar_heading) || (@old_radar_heading >= a+360 && a+360 >= new_radar_heading) ||
271
+ (@old_radar_heading <= a-360 && a-360 <= @new_radar_heading) || (@old_radar_heading >= a-360 && a-360 >= @new_radar_heading)
272
+ dist = Math.hypot(@y - mine.y, mine.x - @x)
273
+ @events['mine_scanned'] << [dist] if (dist < @battlefield.config.robots[:radar_mine_scanning_performance]) and (self != mine.origin)
274
+ end
275
+ end
276
+ end
225
277
  end
226
278
 
227
279
  def speak
@@ -233,6 +285,22 @@ class RobotRunner
233
285
  end
234
286
  end
235
287
 
288
+ def team_broadcast
289
+ @battlefield.teams[self.team].each do |other|
290
+ if (other != self) && (!other.dead)
291
+ msg = other.actions[:team_broadcast]
292
+ if msg != 0
293
+ a = Math.atan2(@y - other.y, other.x - @x) / Math::PI * 180 % 360
294
+ dir = 'east'
295
+ dir = 'north' if a.between? 45,135
296
+ dir = 'west' if a.between? 135,225
297
+ dir = 'south' if a.between? 225,315
298
+ @events['team_broadcasts'] << [msg, dir]
299
+ end
300
+ end
301
+ end
302
+ end
303
+
236
304
  def broadcast
237
305
  @battlefield.robots.each do |other|
238
306
  if (other != self) && (!other.dead)
data/lib/tkarena.rb CHANGED
@@ -7,7 +7,7 @@ class TkArena
7
7
 
8
8
  attr_reader :battlefield, :xres, :yres
9
9
  attr_accessor :speed_multiplier, :on_game_over_handlers
10
- attr_accessor :canvas, :boom, :robots, :bullets, :explosions, :colors, :toolboxes, :toolbox_img
10
+ attr_accessor :canvas, :boom, :robots, :bullets, :explosions, :colors, :toolboxes, :toolbox_img, :mines, :mine_img
11
11
  attr_accessor :default_skin_prefix, :path_prefix
12
12
 
13
13
  def initialize battlefield, xres, yres, speed_multiplier
@@ -42,14 +42,6 @@ class TkArena
42
42
  TkPhotoImage.new(:data => Base64.encode64(data))
43
43
  end
44
44
 
45
- def usage
46
- puts "usage: rrobots.rb <FirstRobotClassName[.rb]> <SecondRobotClassName[.rb]> <...>"
47
- puts "\tthe names of the rb files have to match the class names of the robots"
48
- puts "\t(up to 8 robots)"
49
- puts "\te.g. 'ruby rrobots.rb SittingDuck NervousDuck'"
50
- exit
51
- end
52
-
53
45
  def init_canvas
54
46
  @canvas = TkCanvas.new(:height=>yres, :width=>xres, :scrollregion=>[0, 0, xres, yres], :background => '#000000').pack
55
47
  @colors = []
@@ -70,10 +62,11 @@ class TkArena
70
62
  TkPhotoImage.new(:file => "#{path_prefix}/images/explosion#{i.to_s.rjust(2, '0')}.gif")
71
63
  end
72
64
  @toolbox_img = TkPhotoImage.new(:file => "#{path_prefix}/images/toolbox.gif")
65
+ @mine_img = TkPhotoImage.new(:file => "#{path_prefix}/images/mine.gif")
73
66
  end
74
67
 
75
68
  def init_simulation
76
- @robots, @bullets, @explosions, @toolboxes = {}, {}, {}, {}
69
+ @robots, @bullets, @explosions, @toolboxes, @mines = {}, {}, {}, {}, {}
77
70
  TkTimer.new(20, -1, Proc.new{
78
71
  begin
79
72
  draw_frame
@@ -93,9 +86,10 @@ class TkArena
93
86
  @explosions.reject!{|e,tko| @canvas.delete(tko) if e.dead; e.dead }
94
87
  @bullets.reject!{|b,tko| @canvas.delete(tko) if b.dead; b.dead }
95
88
  @toolboxes.reject!{|t,tko| @canvas.delete(tko) if t.dead; t.dead }
89
+ @mines.reject!{|m,tko| @canvas.delete(tko) if m.dead; m.dead }
96
90
  @robots.reject! do |ai,tko|
97
91
  if ai.dead
98
- tko.status.configure(:text => "#{ai.name.ljust(20)} dead")
92
+ tko.status.configure(:text => I18n.t('tkarena.ai_name_dead', :ai_name => ai.name.ljust(20)))
99
93
  tko.each{|part| @canvas.delete(part) if part != tko.status}
100
94
  true
101
95
  end
@@ -106,17 +100,17 @@ class TkArena
106
100
  unless @game_over
107
101
  winner = @robots.keys.first
108
102
  whohaswon = if winner.nil?
109
- "Draw!"
103
+ I18n.t('tkarena.draw')
110
104
  elsif @battlefield.teams.all?{|k,t|t.size<2}
111
- "#{winner.name} won!"
105
+ I18n.t('tkarena.no_team_won', :winner_name => winner.name)
112
106
  else
113
- "Team #{winner.team} won!"
107
+ I18n.t('tkarena.team_won', :winner_team => winner.team)
114
108
  end
115
109
  text_color = winner ? winner.team : 7
116
110
  @game_over = TkcText.new(canvas,
117
111
  :fill => @text_colors[text_color],
118
112
  :anchor => 'c', :coords => [400,400], :font=>'courier 36', :justify => 'center',
119
- :text => "GAME OVER\n#{whohaswon}")
113
+ :text => I18n.t('tkarena.game_over').concat("\n#{whohaswon}"))
120
114
  end
121
115
  end
122
116
  @battlefield.tick
@@ -125,6 +119,7 @@ class TkArena
125
119
 
126
120
  def draw_battlefield
127
121
  draw_toolboxes
122
+ draw_mines
128
123
  draw_robots
129
124
  draw_bullets
130
125
  draw_explosions
@@ -170,6 +165,13 @@ class TkArena
170
165
  bullet.x / 2 + 3, bullet.y / 2 + 3)
171
166
  end
172
167
  end
168
+
169
+ def draw_mines
170
+ @battlefield.mines.each do |mine|
171
+ @mines[mine] ||= TkcImage.new(@canvas, mine.x / 2, mine.y / 2)
172
+ @mines[mine].image(mine_img)
173
+ end
174
+ end
173
175
 
174
176
  def draw_explosions
175
177
  @battlefield.explosions.each do |explosion|
data/robots/Killer.rb CHANGED
@@ -36,7 +36,7 @@ class Killer
36
36
  else
37
37
  @radar_range *= -2 if (@radar_range.abs < 60)
38
38
  end
39
-
39
+ drop_mine if rand(100) == 50
40
40
  fire 3
41
41
 
42
42
  if ((x < 100) || (x > 1500) || (y < 100) || (y > 1500)) && (@escape.nil? || @escape.zero?)
data/robots/MsgBot.rb CHANGED
@@ -4,10 +4,18 @@ class MsgBot
4
4
  include Robot
5
5
 
6
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
7
+ priv = true
8
+ unless priv then
9
+ events['broadcasts'].each{|msg,dir|
10
+ say "Got message #{msg.inspect} from #{dir}!"
11
+ }
12
+ broadcast "Hello! Team #{team}!" if rand < 0.01
13
+ else
14
+ events['team_broadcasts'].each{|msg,dir|
15
+ say "Got priv message #{msg.inspect} from #{dir}!"
16
+ }
17
+ team_broadcast "Hello! Team #{team}!" if rand < 0.01
18
+ end
11
19
  end
12
20
 
13
21
  end