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.
- data/.gitignore +1 -0
- data/.rspec +0 -0
- data/README.md +43 -0
- data/_design/ClassDescriptions.txt +98 -0
- data/_design/Psudo_Program.rb +113 -0
- data/_design/array.rb +4 -0
- data/_design/threads.rb +71 -0
- data/_spike/Communications/communications.rb +2 -0
- data/_spike/Communications/lib/communications/com_linker.rb +11 -0
- data/_spike/Communications/lib/communications/null_modem.rb +11 -0
- data/_spike/Communications/spec/communications/com_linker_spec.rb +37 -0
- data/_spike/DRb/arena.rb +32 -0
- data/_spike/DRb/battle_controller.rb +54 -0
- data/_spike/DRb/bot.rb +23 -0
- data/_spike/DRb/bot_runner.rb +110 -0
- data/_spike/DRb/comment.txt +11 -0
- data/_spike/DRb/server.rb +28 -0
- data/_spike/DRb/test_bot.rb +6 -0
- data/_spike/array.rb +7 -0
- data/_spike/atan2.rb +39 -0
- data/_spike/battle.rb +202 -0
- data/_spike/break.rb +10 -0
- data/_spike/circles.rb +29 -0
- data/_spike/cleaner_attribs.rb +13 -0
- data/_spike/comlink.rb +61 -0
- data/_spike/concat.rb +27 -0
- data/_spike/example_bot.rb +42 -0
- data/_spike/forwarding_instance.rb +32 -0
- data/_spike/hash_loop.rb +17 -0
- data/_spike/hashing.rb +7 -0
- data/_spike/hook.rb +19 -0
- data/_spike/mod.rb +10 -0
- data/_spike/point_in_cone.rb +20 -0
- data/_spike/runner.rb +44 -0
- data/_spike/safe.rb +28 -0
- data/brawl.gemspec +4 -3
- data/example/example_battle.rb +173 -0
- data/example/logview.txt +6394 -0
- data/lib/brawl.rb +14 -3
- data/lib/brawl/_helper.rb +65 -0
- data/lib/brawl/arena.rb +118 -0
- data/lib/brawl/basic_arena_object.rb +35 -0
- data/lib/brawl/basic_bot.rb +69 -0
- data/lib/brawl/battle_controller.rb +97 -0
- data/lib/brawl/bot_proxy.rb +60 -0
- data/lib/brawl/clock.rb +36 -0
- data/lib/brawl/parts.rb +3 -0
- data/lib/brawl/parts/basic_motor.rb +55 -0
- data/lib/brawl/parts/basic_scanner.rb +33 -0
- data/lib/brawl/parts/basic_weapon.rb +47 -0
- data/lib/brawl/version.rb +1 -1
- data/lib/brawl/wall.rb +9 -0
- data/spec/brawl/arena_spec.rb +163 -0
- data/spec/brawl/basic_arena_object_spec.rb +40 -0
- data/spec/brawl/basic_bot_spec.rb +84 -0
- data/spec/brawl/battle_controller_spec.rb +138 -0
- data/spec/brawl/clock_spec.rb +28 -0
- data/spec/brawl/helper_spec.rb +23 -0
- data/spec/brawl/parts/basic_motor_spec.rb +220 -0
- data/spec/brawl/parts/basic_scanner_spec.rb +101 -0
- data/spec/brawl/parts/basic_weapon_spec.rb +146 -0
- data/spec/spec_helper.rb +5 -0
- 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
|
+
|
data/_spike/array.rb
ADDED
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
|
+
|