brawl 0.0.0.alpha → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/.gitignore +1 -0
  2. data/.rspec +0 -0
  3. data/README.md +43 -0
  4. data/_design/ClassDescriptions.txt +98 -0
  5. data/_design/Psudo_Program.rb +113 -0
  6. data/_design/array.rb +4 -0
  7. data/_design/threads.rb +71 -0
  8. data/_spike/Communications/communications.rb +2 -0
  9. data/_spike/Communications/lib/communications/com_linker.rb +11 -0
  10. data/_spike/Communications/lib/communications/null_modem.rb +11 -0
  11. data/_spike/Communications/spec/communications/com_linker_spec.rb +37 -0
  12. data/_spike/DRb/arena.rb +32 -0
  13. data/_spike/DRb/battle_controller.rb +54 -0
  14. data/_spike/DRb/bot.rb +23 -0
  15. data/_spike/DRb/bot_runner.rb +110 -0
  16. data/_spike/DRb/comment.txt +11 -0
  17. data/_spike/DRb/server.rb +28 -0
  18. data/_spike/DRb/test_bot.rb +6 -0
  19. data/_spike/array.rb +7 -0
  20. data/_spike/atan2.rb +39 -0
  21. data/_spike/battle.rb +202 -0
  22. data/_spike/break.rb +10 -0
  23. data/_spike/circles.rb +29 -0
  24. data/_spike/cleaner_attribs.rb +13 -0
  25. data/_spike/comlink.rb +61 -0
  26. data/_spike/concat.rb +27 -0
  27. data/_spike/example_bot.rb +42 -0
  28. data/_spike/forwarding_instance.rb +32 -0
  29. data/_spike/hash_loop.rb +17 -0
  30. data/_spike/hashing.rb +7 -0
  31. data/_spike/hook.rb +19 -0
  32. data/_spike/mod.rb +10 -0
  33. data/_spike/point_in_cone.rb +20 -0
  34. data/_spike/runner.rb +44 -0
  35. data/_spike/safe.rb +28 -0
  36. data/brawl.gemspec +4 -3
  37. data/example/example_battle.rb +173 -0
  38. data/example/logview.txt +6394 -0
  39. data/lib/brawl.rb +14 -3
  40. data/lib/brawl/_helper.rb +65 -0
  41. data/lib/brawl/arena.rb +118 -0
  42. data/lib/brawl/basic_arena_object.rb +35 -0
  43. data/lib/brawl/basic_bot.rb +69 -0
  44. data/lib/brawl/battle_controller.rb +97 -0
  45. data/lib/brawl/bot_proxy.rb +60 -0
  46. data/lib/brawl/clock.rb +36 -0
  47. data/lib/brawl/parts.rb +3 -0
  48. data/lib/brawl/parts/basic_motor.rb +55 -0
  49. data/lib/brawl/parts/basic_scanner.rb +33 -0
  50. data/lib/brawl/parts/basic_weapon.rb +47 -0
  51. data/lib/brawl/version.rb +1 -1
  52. data/lib/brawl/wall.rb +9 -0
  53. data/spec/brawl/arena_spec.rb +163 -0
  54. data/spec/brawl/basic_arena_object_spec.rb +40 -0
  55. data/spec/brawl/basic_bot_spec.rb +84 -0
  56. data/spec/brawl/battle_controller_spec.rb +138 -0
  57. data/spec/brawl/clock_spec.rb +28 -0
  58. data/spec/brawl/helper_spec.rb +23 -0
  59. data/spec/brawl/parts/basic_motor_spec.rb +220 -0
  60. data/spec/brawl/parts/basic_scanner_spec.rb +101 -0
  61. data/spec/brawl/parts/basic_weapon_spec.rb +146 -0
  62. data/spec/spec_helper.rb +5 -0
  63. metadata +101 -10
@@ -0,0 +1,54 @@
1
+ #require 'uuidtools'
2
+ $DEBUG = true
3
+
4
+ require_relative 'arena'
5
+ require_relative 'server'
6
+ require_relative 'bot_runner'
7
+
8
+ class RunIt
9
+ def run(server, code)
10
+ bot = BotRunner.new(code)
11
+ fork do
12
+ Signal.trap("HUP") { puts "Die! #{server}"; bot.stop; exit}
13
+ bot.connect(server)
14
+ bot.run
15
+ while true
16
+ sleep(0.25)
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ arena = Arena.new
23
+ code = File.read("test_bot.rb")
24
+ puts "test code: #{code}"
25
+ client_id1 = "client1"
26
+ arena_proxy1 = ArenaProxy.new(arena, client_id1)
27
+ arena.add_bot(client_id1)
28
+ bot1_server = Server.new
29
+ bot1_server.start(object: arena_proxy1)
30
+ r1 = RunIt.new
31
+ pid1 = r1.run(bot1_server.uri, code)
32
+
33
+ client_id2 = "client2"
34
+ arena_proxy2 = ArenaProxy.new(arena, client_id2)
35
+ arena.add_bot(client_id2)
36
+ bot2_server = Server.new
37
+ bot2_server.start(object: arena_proxy2)
38
+ r2 = RunIt.new
39
+ pid2 = r2.run(bot2_server.uri, code)
40
+
41
+ timeout = Time.now + 3
42
+ while Time.now < timeout
43
+ sleep(0.05)
44
+ end
45
+ bot1_server.stop
46
+ Process.kill("HUP", pid1)
47
+ sleep(2.0)
48
+ bot2_server.stop
49
+ Process.kill("HUP", pid2)
50
+ Process.wait
51
+
52
+
53
+
54
+
data/_spike/DRb/bot.rb ADDED
@@ -0,0 +1,23 @@
1
+ module Brawl
2
+ class Bot
3
+
4
+ def initialize(msg, response)
5
+ @msg = msg
6
+ @response = response
7
+ end
8
+
9
+ def move(amount)
10
+ @msg.clear
11
+ @msg.concat [:move, amount]
12
+ sleep(0.05) while @response.empty?
13
+ return_value = Marshal.load(Marshal.dump(@response))
14
+ @response.clear
15
+ return_value
16
+ end
17
+
18
+ def loop
19
+ yield self
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,110 @@
1
+ require 'drb'
2
+ require_relative 'bot'
3
+
4
+ class BotRunner
5
+
6
+ attr_reader :proxy
7
+
8
+ def initialize(code)
9
+ @mutex = Mutex.new
10
+ make_run(code)
11
+ end
12
+
13
+ def connect(server)
14
+ @server = server
15
+ @run = true
16
+ puts "connecting: #{@server}"
17
+ DRb.start_service
18
+ @proxy = DRbObject.new(nil, server)
19
+ end
20
+
21
+ def stop
22
+ @run = false
23
+ DRb.stop_service
24
+ end
25
+
26
+
27
+ # def run
28
+ # Thread.start {
29
+ # msg = []
30
+ # response = []
31
+ # Thread.start {
32
+ # $SAFE = 1
33
+ # code = Brawl::Bot.new(msg, response)
34
+ # while @run
35
+ # sleep(rand(0))
36
+ # code.loop do |bot|
37
+ # puts "bot code loop"
38
+ # value = @proxy.move([rand(3)])
39
+ # puts "value: #{value}"
40
+ # end
41
+ # end
42
+ # }
43
+ # }
44
+ # end
45
+
46
+
47
+ # def run
48
+ # Thread.start {
49
+ # msg = []
50
+ # response = []
51
+ # Thread.start {
52
+ # $SAFE = 3
53
+ # code = Brawl::Bot.new(msg, response)
54
+ # while @run
55
+ # sleep(rand(0))
56
+ # code.loop do |bot|
57
+ # puts "bot code loop"
58
+ # value = bot.move rand(3)+1
59
+ # puts "value: #{value}"
60
+ # end
61
+ # end
62
+ # }
63
+ # while @run
64
+ # sleep(0.05) while msg.empty?
65
+ # puts "got a message"
66
+ # sleep(0.25)
67
+ # proxy_response = @proxy.send msg.first, msg[1..-1]
68
+ # msg.clear
69
+ # response << proxy_response
70
+ # end
71
+ # }
72
+ # end
73
+
74
+ private
75
+
76
+ def make_run(code)
77
+ method =
78
+ %Q{
79
+ def run
80
+ Thread.start {
81
+ msg = []
82
+ response = []
83
+ Thread.start {
84
+ $SAFE = 3
85
+ code = Brawl::Bot.new(msg, response)
86
+ while @run
87
+ puts "looping"
88
+ sleep(rand(0))
89
+ #{code}
90
+ end
91
+ }
92
+ while @run
93
+ sleep(0.05) while msg.empty?
94
+ puts "got a message"
95
+ sleep(0.25)
96
+ proxy_response = @proxy.send msg.first, msg[1..-1]
97
+ msg.clear
98
+ response << proxy_response
99
+ end
100
+ }
101
+ end
102
+ }
103
+ instance_eval(method)
104
+ end
105
+
106
+ def send(msg)
107
+ @msg = msg
108
+ end
109
+
110
+ end
@@ -0,0 +1,11 @@
1
+ I've started a rewrite on this app to fix all the horrible Demeter violations and just bad design all around but in the process I've come up with a rough version of a security model.
2
+
3
+ Can you guys take a look and tell me what you think?
4
+
5
+ [https://github.com/mikbe/Brawl/blob/master/_spike/DRb/bot.rb](https://github.com/mikbe/Brawl/blob/master/_spike/DRb/bot.rb)
6
+
7
+ You can run the battle_controller.rb file and it should load up everything else. It demonstrates two bots running through the same arena.
8
+
9
+ The code for the bot is as safe as $SAFE can make it while still allowing the user to do very basic things like make an array ($SAFE = 3). Plus it's isolated into another process from the rest of the code, including other bots, and uses DRb to communicate inter-process. There's probably a simpler way of doing that communication but that was actually pretty easy. Oh and an ArenaProxy class is used so all of the Arena methods and properties aren't exposed to the bots.
10
+
11
+ The reason I'm doing the weird array messaging in two looping threads is because DRb will only work at $SAFE 1 or 0.
@@ -0,0 +1,28 @@
1
+ require 'drb'
2
+
3
+ class Server
4
+
5
+ def start(params)
6
+ port = params[:port] ? "druby://:#{params[:port]}" : nil
7
+ object = params[:object]
8
+ @service = DRb.start_service(port, object)
9
+ end
10
+
11
+ def stop
12
+ @service.stop_service
13
+ end
14
+
15
+ def uri
16
+ @service.uri
17
+ end
18
+
19
+ end
20
+
21
+ # server = Server.new
22
+ # server.start(object: ArenaProxy.new)
23
+ # puts server
24
+ # puts server.uri
25
+ # DRb.thread.join
26
+
27
+
28
+
@@ -0,0 +1,6 @@
1
+ puts "running test_bot"
2
+ code.loop do |bot|
3
+ puts "bot code loop"
4
+ value = bot.move rand(3)+1
5
+ puts "value: #{value}"
6
+ end
data/_spike/array.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'benchmark'
2
+
3
+ Benchmark.bmbm do |bm|
4
+ bm.report {x = []; 100000.times {x << "A"}}
5
+ bm.report {x = []; 10000.times {x.concat ["A"]}}
6
+ bm.report {x = []; 100000.times {x.push "A"}}
7
+ end
data/_spike/atan2.rb ADDED
@@ -0,0 +1,39 @@
1
+
2
+ def to_radians(angle)
3
+ angle * (Math::PI / 180)
4
+ end
5
+
6
+ def to_degrees(angle)
7
+ angle * (180.0 / Math::PI)
8
+ end
9
+
10
+ # x1, y1 = 5,5
11
+ # x2, y2 = 6,6
12
+ # x2, y2 = 5,5
13
+ # x1, y1 = 6,6
14
+
15
+ x1, y1 = 5,5
16
+ x2, y2 = 5,6
17
+ puts "0 : #{to_degrees(Math.atan2(x2 - x1, y2 - y1)) % 360}"
18
+
19
+ x2, y2 = 6,6
20
+ puts "45 : #{to_degrees(Math.atan2(x2 - x1, y2 - y1)) % 360}"
21
+
22
+ x2, y2 = 6,5
23
+ puts "90 : #{to_degrees(Math.atan2(x2 - x1, y2 - y1)) % 360}"
24
+
25
+ x2, y2 = 6,4
26
+ puts "135 : #{to_degrees(Math.atan2(x2 - x1, y2 - y1)) % 360}"
27
+
28
+ x2, y2 = 5,4
29
+ puts "180 : #{to_degrees(Math.atan2(x2 - x1, y2 - y1)) % 360}"
30
+
31
+ x2, y2 = 4,4
32
+ puts "225 : #{to_degrees(Math.atan2(x2 - x1, y2 - y1)) % 360}"
33
+
34
+ x2, y2 = 4,5
35
+ puts "270 : #{to_degrees(Math.atan2(x2 - x1, y2 - y1)) % 360}"
36
+
37
+ x2, y2 = 4,6
38
+ puts "315 : #{to_degrees(Math.atan2(x2 - x1, y2 - y1)) % 360}"
39
+
data/_spike/battle.rb ADDED
@@ -0,0 +1,202 @@
1
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "/../lib"))
2
+ require 'brawl'
3
+ $DEBUG=true
4
+ Thread.abort_on_exception
5
+
6
+ module Brawl
7
+
8
+ class CommandSync
9
+
10
+ attr_reader :ticks, :run
11
+
12
+ def initialize(min_time=0.5)
13
+ @min_time = min_time
14
+ @run = :wait
15
+ @ticks = 0
16
+ end
17
+
18
+ def start
19
+ @run = :run
20
+ Thread.start{
21
+ until @run == :stop
22
+ sleep(@min_time)
23
+ #puts "incrementing ticks: #{@ticks}"
24
+ @ticks += 1
25
+ end
26
+ puts "Command sync stopped "
27
+ }
28
+ end
29
+
30
+ def stop
31
+ @run = :stop
32
+ end
33
+
34
+ end
35
+
36
+ class Proxy
37
+
38
+ attr_accessor :bot, :name, :last_tick
39
+
40
+ def initialize(params)
41
+ @sync = params[:sync]
42
+
43
+ # probably just put this all in one object
44
+ @name = params[:name]
45
+ @bot = params[:bot]
46
+ @code = params[:code]
47
+
48
+ @last_tick = @sync.ticks
49
+ @run = false
50
+ add_proxy_methods
51
+ end
52
+
53
+ def add_proxy_methods
54
+ puts "proxy: #{@bot.public_methods(false)}"
55
+ @bot.public_methods(false).each do |method|
56
+ singleton_class.send :define_method, method do |*params, &block|
57
+ puts "#{@name}: #{method}(#{params.join})"
58
+ sleep(0.01) while @sync.ticks <= @last_tick
59
+ @last_tick = @sync.ticks
60
+ @bot.send method, *params, &block
61
+ puts "#{@name}: #{@bot.properties[:location]}"
62
+ end
63
+ end
64
+ end
65
+
66
+ def start
67
+ @run = true
68
+ # for security in produciton will use a process fork but for now...
69
+ Thread.start {
70
+ # wait for command sync to start
71
+ until @sync.run == :stop || !@run
72
+ sleep(0.01) if @sync.run == :wait
73
+ if @sync.run == :run
74
+ instance_eval("Thread.start{$SAFE=3;#{@code}}.join")
75
+ end
76
+ end
77
+ puts "#{@name} stopped"
78
+ @run = false
79
+ }
80
+ end
81
+
82
+ def stop
83
+ @run = false
84
+ end
85
+
86
+ def code
87
+ yield self
88
+ end
89
+
90
+ end
91
+
92
+ class BattleController
93
+
94
+ attr_accessor :arena, :bots
95
+
96
+ def initialize(params)
97
+ super
98
+
99
+ @sync = CommandSync.new(params[:min_tick])
100
+
101
+ arena = params[:arena]
102
+ bots = params[:bots]
103
+ @arena = arena[:class].new(arena[:parameters])
104
+
105
+ @bot_proxies = []
106
+ bots.each do |bot|
107
+ puts "add: #{bot[:name]}, #{bot[:class]}"
108
+ bot[:parameters].merge!(location: {x: rand(100), y:rand(100)})
109
+
110
+ bot_instance = bot[:class].new(bot[:parameters].merge(arena: @arena))
111
+ @bot_proxies << {
112
+ name: bot[:name],
113
+ proxy: Proxy.new(
114
+ sync: @sync,
115
+ bot: bot_instance,
116
+ code: bot[:code],
117
+ name: bot[:name]
118
+ )
119
+ }
120
+ end
121
+ end
122
+
123
+ def start
124
+ @bot_proxies.each do |bot|
125
+ puts
126
+ puts "Starting: #{bot[:name]}"
127
+ bot[:proxy].start
128
+ end
129
+ @sync.start
130
+ end
131
+
132
+ def stop
133
+ @sync.stop
134
+ end
135
+
136
+ end
137
+
138
+ arena = {
139
+ class: Arena,
140
+ parameters: {
141
+ size: {width: 100, length: 100}
142
+ }
143
+ }
144
+
145
+ bot_code = <<-CODE
146
+ code do |bot|
147
+ if rand(0) > 0.5
148
+ bot.turn [:left,:right,:around].sample
149
+ end
150
+ bot.move rand(3) + 1
151
+ end
152
+ CODE
153
+
154
+ bots = [
155
+ { name: "BasicBot1",
156
+ class: BasicBot,
157
+ parameters: {
158
+ arena: arena,
159
+ parts: {Brawl::BasicMotor=>{move_max: 3, turn_max: 360}}
160
+ },
161
+ code:bot_code
162
+ },
163
+ { name: "BasicBot2",
164
+ class: BasicBot,
165
+ parameters: {
166
+ arena: arena,
167
+ parts: {Brawl::BasicMotor=>{move_max: 3, turn_max: 360}}
168
+ },
169
+ code:bot_code
170
+ }
171
+ ]
172
+
173
+ battle = Brawl::BattleController.new(
174
+ arena: arena,
175
+ bots: bots,
176
+ min_tick: 0.01
177
+ )
178
+
179
+ battle.start
180
+
181
+ timeout = Time.now + 5
182
+ while Time.now <= timeout
183
+ sleep(0.1)
184
+ end
185
+ battle.stop
186
+ sleep(1)
187
+
188
+ end
189
+
190
+
191
+
192
+
193
+
194
+
195
+
196
+
197
+
198
+
199
+
200
+
201
+
202
+