rrobots 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/README.rdoc +93 -0
  4. data/Rakefile +1 -0
  5. data/VERSION +1 -0
  6. data/bin/rrobots +154 -0
  7. data/bin/tournament +275 -0
  8. data/lib/rrobots.rb +6 -0
  9. data/lib/rrobots/battlefield.rb +69 -0
  10. data/lib/rrobots/bullet.rb +39 -0
  11. data/lib/rrobots/explosion.rb +20 -0
  12. data/lib/rrobots/gui.rb +2 -0
  13. data/lib/rrobots/gui/gosuarena.rb +124 -0
  14. data/lib/rrobots/gui/leaderboard.rb +19 -0
  15. data/lib/rrobots/images/blue_body000.bmp +0 -0
  16. data/lib/rrobots/images/blue_radar000.bmp +0 -0
  17. data/lib/rrobots/images/blue_turret000.bmp +0 -0
  18. data/lib/rrobots/images/bullet.png +0 -0
  19. data/lib/rrobots/images/explosion00.bmp +0 -0
  20. data/lib/rrobots/images/explosion01.bmp +0 -0
  21. data/lib/rrobots/images/explosion02.bmp +0 -0
  22. data/lib/rrobots/images/explosion03.bmp +0 -0
  23. data/lib/rrobots/images/explosion04.bmp +0 -0
  24. data/lib/rrobots/images/explosion05.bmp +0 -0
  25. data/lib/rrobots/images/explosion06.bmp +0 -0
  26. data/lib/rrobots/images/explosion07.bmp +0 -0
  27. data/lib/rrobots/images/explosion08.bmp +0 -0
  28. data/lib/rrobots/images/explosion09.bmp +0 -0
  29. data/lib/rrobots/images/explosion10.bmp +0 -0
  30. data/lib/rrobots/images/explosion11.bmp +0 -0
  31. data/lib/rrobots/images/explosion12.bmp +0 -0
  32. data/lib/rrobots/images/explosion13.bmp +0 -0
  33. data/lib/rrobots/images/explosion14.bmp +0 -0
  34. data/lib/rrobots/images/lime_body000.bmp +0 -0
  35. data/lib/rrobots/images/lime_radar000.bmp +0 -0
  36. data/lib/rrobots/images/lime_turret000.bmp +0 -0
  37. data/lib/rrobots/images/red_body000.bmp +0 -0
  38. data/lib/rrobots/images/red_radar000.bmp +0 -0
  39. data/lib/rrobots/images/red_turret000.bmp +0 -0
  40. data/lib/rrobots/images/space.png +0 -0
  41. data/lib/rrobots/images/white_body000.bmp +0 -0
  42. data/lib/rrobots/images/white_radar000.bmp +0 -0
  43. data/lib/rrobots/images/white_turret000.bmp +0 -0
  44. data/lib/rrobots/images/yellow_body000.bmp +0 -0
  45. data/lib/rrobots/images/yellow_radar000.bmp +0 -0
  46. data/lib/rrobots/images/yellow_turret000.bmp +0 -0
  47. data/lib/rrobots/numeric.rb +10 -0
  48. data/lib/rrobots/robot.rb +115 -0
  49. data/lib/rrobots/robot_runner.rb +237 -0
  50. data/lib/rrobots/tournament.rb +2 -0
  51. data/lib/rrobots/tournament/match.rb +71 -0
  52. data/lib/rrobots/tournament/round.rb +56 -0
  53. data/lib/rrobots/version.rb +3 -0
  54. data/rrobots.gemspec +25 -0
  55. metadata +113 -0
@@ -0,0 +1,237 @@
1
+ class RobotRunner
2
+
3
+ STATE_IVARS = [ :x, :y, :gun_heat, :heading, :gun_heading, :radar_heading, :time, :size, :speed, :energy, :team ]
4
+ NUMERIC_ACTIONS = [ :fire, :turn, :turn_gun, :turn_radar, :accelerate ]
5
+ STRING_ACTIONS = [ :say, :broadcast ]
6
+
7
+ STATE_IVARS.each{|iv|
8
+ attr_accessor iv
9
+ }
10
+ NUMERIC_ACTIONS.each{|iv|
11
+ attr_accessor "#{iv}_min", "#{iv}_max"
12
+ }
13
+ STRING_ACTIONS.each{|iv|
14
+ attr_accessor "#{iv}_max"
15
+ }
16
+
17
+ #AI of this robot
18
+ attr_accessor :robot
19
+
20
+ #team of this robot
21
+ attr_accessor :team
22
+
23
+ #keeps track of total damage done by this robot
24
+ attr_accessor :damage_given
25
+
26
+ #keeps track of the kills
27
+ attr_accessor :kills
28
+
29
+ attr_reader :actions, :speech
30
+
31
+ def initialize robot, bf, team=0
32
+ @robot = robot
33
+ @battlefield = bf
34
+ @team = team
35
+ set_action_limits
36
+ set_initial_state
37
+ @events = Hash.new{|h, k| h[k]=[]}
38
+ @actions = Hash.new(0)
39
+ end
40
+
41
+ def skin_prefix
42
+ @robot.skin_prefix
43
+ end
44
+
45
+ def set_initial_state
46
+ @x = @battlefield.width / 2
47
+ @y = @battlefield.height / 2
48
+ @speech_counter = -1
49
+ @speech = nil
50
+ @time = 0
51
+ @size = 60
52
+ @speed = 0
53
+ @energy = 100
54
+ @damage_given = 0
55
+ @kills = 0
56
+ teleport
57
+ end
58
+
59
+ def teleport(distance_x=@battlefield.width / 2, distance_y=@battlefield.height / 2)
60
+ @x += ((rand-0.5) * 2 * distance_x).to_i
61
+ @y += ((rand-0.5) * 2 * distance_y).to_i
62
+ @gun_heat = 3
63
+ @heading = (rand * 360).to_i
64
+ @gun_heading = @heading
65
+ @radar_heading = @heading
66
+ end
67
+
68
+ def set_action_limits
69
+ @fire_min, @fire_max = 0, 3
70
+ @turn_min, @turn_max = -10, 10
71
+ @turn_gun_min, @turn_gun_max = -30, 30
72
+ @turn_radar_min, @turn_radar_max = -60, 60
73
+ @accelerate_min, @accelerate_max = -1, 1
74
+ @teleport_min, @teleport_max = 0, 100
75
+ @say_max = 256
76
+ @broadcast_max = 16
77
+ end
78
+
79
+ def hit bullet
80
+ damage = bullet.energy
81
+ @energy -= damage
82
+ @events['got_hit'] << [@energy]
83
+ damage
84
+ end
85
+
86
+ def dead
87
+ @energy < 0
88
+ end
89
+
90
+ def clamp(var, min, max)
91
+ val = 0 + var # to guard against poisoned vars
92
+ if val > max
93
+ max
94
+ elsif val < min
95
+ min
96
+ else
97
+ val
98
+ end
99
+ end
100
+
101
+ def internal_tick
102
+ update_state
103
+ robot_tick
104
+ parse_actions
105
+ fire
106
+ turn
107
+ move
108
+ scan
109
+ speak
110
+ broadcast
111
+ @time += 1
112
+ end
113
+
114
+ def parse_actions
115
+ @actions.clear
116
+ NUMERIC_ACTIONS.each{|an|
117
+ @actions[an] = clamp(@robot.actions[an], send("#{an}_min"), send("#{an}_max"))
118
+ }
119
+ STRING_ACTIONS.each{|an|
120
+ if @robot.actions[an] != 0
121
+ @actions[an] = String(@robot.actions[an])[0, send("#{an}_max")]
122
+ end
123
+ }
124
+ @actions
125
+ end
126
+
127
+ def state
128
+ current_state = {}
129
+ STATE_IVARS.each{|iv|
130
+ current_state[iv] = send(iv)
131
+ }
132
+ current_state[:battlefield_width] = @battlefield.width
133
+ current_state[:battlefield_height] = @battlefield.height
134
+ current_state[:game_over] = @battlefield.game_over
135
+ current_state
136
+ end
137
+
138
+ def update_state
139
+ new_state = state
140
+ @robot.state = new_state
141
+ new_state.each{|k,v|
142
+ @robot.send("#{k}=", v)
143
+ }
144
+ @robot.events = @events.dup
145
+ @robot.actions ||= Hash.new(0)
146
+ @robot.actions.clear
147
+ end
148
+
149
+ def robot_tick
150
+ @robot.tick @robot.events
151
+ @events.clear
152
+ end
153
+
154
+ def fire
155
+ if (@actions[:fire] > 0) && (@gun_heat == 0)
156
+ bullet = Bullet.new(@battlefield, @x, @y, @gun_heading, 30, @actions[:fire]*3.0, self)
157
+ 3.times{bullet.tick}
158
+ @battlefield << bullet
159
+ @gun_heat = @actions[:fire]
160
+ end
161
+ @gun_heat -= 0.1
162
+ @gun_heat = 0 if @gun_heat < 0
163
+ end
164
+
165
+ def turn
166
+ @old_radar_heading = @radar_heading
167
+ @heading += @actions[:turn]
168
+ @gun_heading += (@actions[:turn] + @actions[:turn_gun])
169
+ @radar_heading += (@actions[:turn] + @actions[:turn_gun] + @actions[:turn_radar])
170
+ @new_radar_heading = @radar_heading
171
+
172
+ @heading %= 360
173
+ @gun_heading %= 360
174
+ @radar_heading %= 360
175
+ end
176
+
177
+ def move
178
+ @speed += @actions[:accelerate]
179
+ @speed = 8 if @speed > 8
180
+ @speed = -8 if @speed < -8
181
+
182
+ @x += Math::cos(@heading.to_rad) * @speed
183
+ @y -= Math::sin(@heading.to_rad) * @speed
184
+
185
+ @x = @size if @x - @size < 0
186
+ @y = @size if @y - @size < 0
187
+ @x = @battlefield.width - @size if @x + @size >= @battlefield.width
188
+ @y = @battlefield.height - @size if @y + @size >= @battlefield.height
189
+ end
190
+
191
+ def scan
192
+ @battlefield.robots.each do |other|
193
+ if (other != self) && (!other.dead)
194
+ a = Math.atan2(@y - other.y, other.x - @x) / Math::PI * 180 % 360
195
+ if (@old_radar_heading <= a && a <= @new_radar_heading) || (@old_radar_heading >= a && a >= @new_radar_heading) ||
196
+ (@old_radar_heading <= a+360 && a+360 <= @new_radar_heading) || (@old_radar_heading >= a+360 && a+360 >= new_radar_heading) ||
197
+ (@old_radar_heading <= a-360 && a-360 <= @new_radar_heading) || (@old_radar_heading >= a-360 && a-360 >= @new_radar_heading)
198
+ @events['robot_scanned'] << [Math.hypot(@y - other.y, other.x - @x)]
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ def speak
205
+ if @actions[:say] != 0
206
+ @speech = @actions[:say]
207
+ @speech_counter = 50
208
+ elsif @speech and (@speech_counter -= 1) < 0
209
+ @speech = nil
210
+ end
211
+ end
212
+
213
+ def broadcast
214
+ @battlefield.robots.each do |other|
215
+ if (other != self) && (!other.dead)
216
+ msg = other.actions[:broadcast]
217
+ if msg != 0
218
+ a = Math.atan2(@y - other.y, other.x - @x) / Math::PI * 180 % 360
219
+ dir = 'east'
220
+ dir = 'north' if a.between? 45,135
221
+ dir = 'west' if a.between? 135,225
222
+ dir = 'south' if a.between? 225,315
223
+ @events['broadcasts'] << [msg, dir]
224
+ end
225
+ end
226
+ end
227
+ end
228
+
229
+ def to_s
230
+ @robot.class.name
231
+ end
232
+
233
+ def name
234
+ @robot.class.name
235
+ end
236
+
237
+ end
@@ -0,0 +1,2 @@
1
+ require 'rrobots/tournament/match'
2
+ require 'rrobots/tournament/round'
@@ -0,0 +1,71 @@
1
+ class Match
2
+ attr_reader :bots
3
+ attr_reader :seed
4
+ attr_reader :match
5
+
6
+ def initialize(data)
7
+ @bots = data['robots']
8
+ @seed = data['seed']
9
+ @ticks= data['elapsed_ticks']
10
+ @timedout = data['timedout']
11
+ @match = data['match']
12
+ end
13
+
14
+ def winner
15
+ sorted = @bots.sort{|a,b| a[1]['damage_given'] <=> b[1]['damage_given']}
16
+ return sorted[1][0]
17
+ end
18
+
19
+ def loser
20
+ sorted = @bots.sort{|a,b| a[1]['damage_given'] <=> b[1]['damage_given']}
21
+ return sorted[0][0]
22
+ end
23
+
24
+ def tie?
25
+ return margin == 0.0
26
+ end
27
+
28
+ def margin
29
+ @bots[winner]['damage_given'] - @bots[loser]['damage_given']
30
+ end
31
+
32
+ def winner_points
33
+ return 0.5 if simul?
34
+ return winner_health / (winner_health + loser_health)
35
+ end
36
+
37
+ def loser_points
38
+ return 0.5 if simul?
39
+ return loser_health / (winner_health + loser_health)
40
+ end
41
+
42
+ def simul?
43
+ winner_health + loser_health == 0
44
+ end
45
+
46
+ def timedout?
47
+ @timedout == 1
48
+ end
49
+
50
+ #between 100 and 0
51
+ def winner_health
52
+ [100 - @bots[winner]['damage_taken'], 0].max
53
+ end
54
+
55
+ #between 100 and 0
56
+ def loser_health
57
+ [100 - @bots[loser]['damage_taken'], 0].max
58
+ end
59
+
60
+ def one_line_summary
61
+ if !tie?
62
+ line = "#{winner} beats #{loser} by #{'%.1f' % margin} energy in #{@ticks} ticks"
63
+ if @timedout then line += " (match timed out, so #{winner} gets #{winner_points}, loser gets #{loser_points})" end
64
+ else
65
+ line = "#{winner} ties #{loser} at #{'%.1f' % winner_health} energy in #{@ticks} ticks"
66
+ if @timedout then line += " (match timed out.)" end
67
+ end
68
+ line += " (timed out)" if @timeout
69
+ return line
70
+ end
71
+ end
@@ -0,0 +1,56 @@
1
+ class Round
2
+ attr_accessor :matches
3
+ attr_accessor :winner
4
+ #attr_accessor :total_margin
5
+ attr_reader :bots
6
+
7
+ # matches should be an array of Matches
8
+ def initialize (matches)
9
+ @matches = matches
10
+ @bots = Hash.new {|h,key| h[key] = {}}
11
+
12
+ both_bots = [@bots[@matches[0].winner], @bots[@matches[0].loser]]
13
+ stats_to_init = ['wins', 'points', 'ties', 'margin', 'simul', 'timedout', 'round_wins']
14
+ stats_to_init.each {|stat| both_bots.each {|b| b[stat] = 0 }}
15
+
16
+ @matches.each do |match|
17
+ @bots[match.winner]['points'] += match.winner_points
18
+ @bots[match.loser]['points'] += match.loser_points
19
+ both_bots.each {|b| b['ties'] += 1 if match.tie?}
20
+ both_bots.each {|b| b['timedout'] += 1 if match.timedout?}
21
+ both_bots.each {|b| b['simul'] += 1 if match.simul?}
22
+ @bots[match.winner]['margin'] += match.margin
23
+ if match.tie?
24
+ both_bots.each {|b| b['wins'] += 0.5}
25
+ else
26
+ @bots[match.winner]['wins'] += 1
27
+ end
28
+ if both_bots[0]['wins'] > both_bots[1]['wins'] then both_bots[0]['round_wins'] = 1 end
29
+ if both_bots[1]['wins'] > both_bots[0]['wins'] then both_bots[1]['round_wins'] = 1 end
30
+ if both_bots[1]['wins'] == both_bots[0]['wins'] then both_bots[0]['round_wins'] = 0.5 ;both_bots[1]['round_wins'] = 0.5 end
31
+ end
32
+ end
33
+
34
+ def winner
35
+ sorted = @bots.sort{|a,b| a[1]['wins'] <=> b[1]['wins']}
36
+ return sorted[1][0]
37
+ end
38
+
39
+ def loser
40
+ sorted = @bots.sort{|a,b| a[1]['wins'] <=> b[1]['wins']}
41
+ return sorted[0][0]
42
+ end
43
+
44
+ def tie?
45
+ @bots[winner]['wins'] == @bots[loser]['wins']
46
+ end
47
+ #calc how many points for losing bot
48
+
49
+ def one_line_summary
50
+ if !tie?
51
+ line = "#{winner} conquers #{loser} (#{@bots[winner]['wins']} to #{@bots[loser]['wins']} )"
52
+ else
53
+ line = "#{winner} ties #{loser} (#{@bots[winner]['wins']} to #{@bots[loser]['wins']} )"
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ module Rrobots
2
+ VERSION = "0.0.1"
3
+ end
data/rrobots.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rrobots/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rrobots"
7
+ s.version = Rrobots::VERSION
8
+ s.authors = ["Marcin Michalowski"]
9
+ s.email = ["h13ronim@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{RRobots is a C-Robots/Robocode clone written entirely in ruby.}
12
+ s.description = %q{RRobots is a simulation environment for robots, these robots have a scanner and a gun, can move forward and backwards and are entirely controlled by ruby scripts.}
13
+
14
+ s.rubyforge_project = "rrobots"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ s.add_runtime_dependency "gosu"
25
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rrobots
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Marcin Michalowski
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-24 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: gosu
16
+ requirement: &70271981755320 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70271981755320
25
+ description: RRobots is a simulation environment for robots, these robots have a scanner
26
+ and a gun, can move forward and backwards and are entirely controlled by ruby scripts.
27
+ email:
28
+ - h13ronim@gmail.com
29
+ executables:
30
+ - rrobots
31
+ - tournament
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - .gitignore
36
+ - Gemfile
37
+ - README.rdoc
38
+ - Rakefile
39
+ - VERSION
40
+ - bin/rrobots
41
+ - bin/tournament
42
+ - lib/rrobots.rb
43
+ - lib/rrobots/battlefield.rb
44
+ - lib/rrobots/bullet.rb
45
+ - lib/rrobots/explosion.rb
46
+ - lib/rrobots/gui.rb
47
+ - lib/rrobots/gui/gosuarena.rb
48
+ - lib/rrobots/gui/leaderboard.rb
49
+ - lib/rrobots/images/blue_body000.bmp
50
+ - lib/rrobots/images/blue_radar000.bmp
51
+ - lib/rrobots/images/blue_turret000.bmp
52
+ - lib/rrobots/images/bullet.png
53
+ - lib/rrobots/images/explosion00.bmp
54
+ - lib/rrobots/images/explosion01.bmp
55
+ - lib/rrobots/images/explosion02.bmp
56
+ - lib/rrobots/images/explosion03.bmp
57
+ - lib/rrobots/images/explosion04.bmp
58
+ - lib/rrobots/images/explosion05.bmp
59
+ - lib/rrobots/images/explosion06.bmp
60
+ - lib/rrobots/images/explosion07.bmp
61
+ - lib/rrobots/images/explosion08.bmp
62
+ - lib/rrobots/images/explosion09.bmp
63
+ - lib/rrobots/images/explosion10.bmp
64
+ - lib/rrobots/images/explosion11.bmp
65
+ - lib/rrobots/images/explosion12.bmp
66
+ - lib/rrobots/images/explosion13.bmp
67
+ - lib/rrobots/images/explosion14.bmp
68
+ - lib/rrobots/images/lime_body000.bmp
69
+ - lib/rrobots/images/lime_radar000.bmp
70
+ - lib/rrobots/images/lime_turret000.bmp
71
+ - lib/rrobots/images/red_body000.bmp
72
+ - lib/rrobots/images/red_radar000.bmp
73
+ - lib/rrobots/images/red_turret000.bmp
74
+ - lib/rrobots/images/space.png
75
+ - lib/rrobots/images/white_body000.bmp
76
+ - lib/rrobots/images/white_radar000.bmp
77
+ - lib/rrobots/images/white_turret000.bmp
78
+ - lib/rrobots/images/yellow_body000.bmp
79
+ - lib/rrobots/images/yellow_radar000.bmp
80
+ - lib/rrobots/images/yellow_turret000.bmp
81
+ - lib/rrobots/numeric.rb
82
+ - lib/rrobots/robot.rb
83
+ - lib/rrobots/robot_runner.rb
84
+ - lib/rrobots/tournament.rb
85
+ - lib/rrobots/tournament/match.rb
86
+ - lib/rrobots/tournament/round.rb
87
+ - lib/rrobots/version.rb
88
+ - rrobots.gemspec
89
+ homepage: ''
90
+ licenses: []
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ! '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project: rrobots
109
+ rubygems_version: 1.8.10
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: RRobots is a C-Robots/Robocode clone written entirely in ruby.
113
+ test_files: []