rrobots 0.0.1

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 (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: []