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,36 @@
1
+ module Brawl
2
+
3
+ class Clock
4
+
5
+ attr_reader :tick_rate, :ticks, :state
6
+
7
+ def initialize(tick_rate=0.05)
8
+ @tick_rate = tick_rate
9
+ @state = :wait
10
+ @ticks = 0
11
+ end
12
+
13
+ def start
14
+ @state = :running
15
+ ticking
16
+ end
17
+
18
+ def stop
19
+ @state = :stopping
20
+ end
21
+
22
+ private
23
+
24
+ def ticking
25
+ Thread.start {
26
+ while @state == :running
27
+ sleep(@tick_rate)
28
+ @ticks += 1
29
+ end
30
+ @state = :stopped
31
+ }
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,3 @@
1
+ require_relative "parts/basic_motor"
2
+ require_relative "parts/basic_scanner"
3
+ require_relative "parts/basic_weapon"
@@ -0,0 +1,55 @@
1
+ module Brawl
2
+
3
+ module BasicMotor
4
+
5
+ attr_reader :move_max, :turn_max
6
+
7
+ def initialize(params={})
8
+ @move_max = params[:move_max] || 5
9
+ @turn_max = params[:turn_max] || 90
10
+ end
11
+
12
+ def move(count=1)
13
+
14
+ heading_radian = Helper.to_radians((@heading + (count < 0 ? 180 : 0)))
15
+ count = count.abs
16
+ count = [count, @move_max].min
17
+
18
+ count.times do
19
+ x = @location[:x] + Math.sin(heading_radian).round(DECIMAL_PLACES)
20
+ y = @location[:y] + Math.cos(heading_radian).round(DECIMAL_PLACES)
21
+ break unless @arena.in_bounds?({x: x, y: y})
22
+ @location[:x], @location[:y] = x, y
23
+ end
24
+ end
25
+
26
+ def turn(params)
27
+ # refactor
28
+ if params.is_a?(Hash)
29
+ turn_to(params[:to_angle]) if params[:to_angle]
30
+ turn_by(params[:by_degrees]) if params[:by_degrees]
31
+ else
32
+ angles = {left: -90, right: 90, around: 180}
33
+ turn_by(angles[params])
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def turn_to(angle)
40
+ turn_by_angle = Helper.wrap_angle(angle - @heading)
41
+ turn_by(turn_by_angle)
42
+ end
43
+
44
+ def turn_by(degrees)
45
+ degrees = boundscheck_angle(degrees)
46
+ @heading = (@heading + degrees) % 360
47
+ end
48
+
49
+ def boundscheck_angle(angle)
50
+ [angle.abs % 360, @turn_max].min * (angle.abs / angle)
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,33 @@
1
+ module Brawl
2
+ module BasicScanner
3
+
4
+ attr_reader :scan_max, :angle_max
5
+
6
+ DECIMAL_PLACES = 1
7
+
8
+ def initialize(params={})
9
+ @scan_max = params[:scan_max] || 10
10
+ @angle_max = params[:angle_max] || 45
11
+ end
12
+
13
+ def scan(params={})
14
+ angle = [@angle_max, params[:angle] ||= @angle_max].min
15
+
16
+ cone = {
17
+ origin: @location,
18
+ direction: params[:direction],
19
+ radius: @scan_max,
20
+ angle: angle,
21
+ }
22
+
23
+ @arena.get_all_objects.collect do |info_hash|
24
+ next if info_hash[:id] == @id
25
+ if obj = Helper.point_in_cone?(cone.merge(point: info_hash[:location]))
26
+ info_hash.merge(obj)
27
+ end
28
+ end.compact
29
+
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,47 @@
1
+ module Brawl
2
+ module BasicWeapon
3
+
4
+ attr_reader :range, :reload_time, :power
5
+
6
+ def initialize(params={})
7
+
8
+ @reload_time = params[:reload_time] || 10
9
+ @range = params[:range] || 10
10
+ @power = params[:power] || 1
11
+
12
+ @reload_countdown = 0
13
+ end
14
+
15
+ def shoot(direction=@heading)
16
+ return false if reload_countdown > 0
17
+ @reload_countdown = @reload_time + @arena.ticks
18
+
19
+ cone = {
20
+ origin: @location,
21
+ direction: direction,
22
+ radius: @range,
23
+ angle: 2
24
+ }
25
+
26
+ # refactor
27
+ possible_hits = @arena.get_all_objects.collect do |object|
28
+ if object[:id] != @id &&
29
+ hit = Helper.point_in_cone?(cone.merge(point: object[:location]))
30
+ object.merge(hit)
31
+ end
32
+ end.compact
33
+ return if possible_hits.empty?
34
+
35
+ # refactor
36
+ hit = possible_hits.sort{|a,b| a[:distance] <=> b[:distance]}.first
37
+ @arena.forward_damage(damage: @power, target: hit[:id])
38
+ hit
39
+ end
40
+
41
+ def reload_countdown
42
+ return 0 if @reload_countdown <= @arena.ticks
43
+ @reload_countdown - @arena.ticks
44
+ end
45
+
46
+ end
47
+ end
data/lib/brawl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Brawl
2
- VERSION = "0.0.0.alpha"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/brawl/wall.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Brawl
2
+
3
+ class Wall < BasicArenaObject
4
+ def damage(params={})
5
+ # walls can't be damaged
6
+ end
7
+ end
8
+
9
+ end
@@ -0,0 +1,163 @@
1
+ require 'spec_helper'
2
+
3
+ describe Brawl::Arena do
4
+
5
+ let(:arena){Brawl::Arena.new(size: {width: 10, length: 10})}
6
+ let(:object1){Brawl::BasicArenaObject.new}
7
+ let(:object2){Brawl::BasicArenaobject.new}
8
+
9
+ context "when initializing" do
10
+
11
+ it "should start the clock automatically" do
12
+ arena = Brawl::Arena.new(size: {width: 100, length: 100})
13
+ expect{sleep(0.1)}.should change(arena, :ticks)
14
+ end
15
+ end
16
+
17
+ context "when determining size" do
18
+
19
+ it "should set the size when initialized" do
20
+ Brawl::Arena.new(
21
+ size: {width: 100, length: 100}
22
+ ).size.should == {width: 100, length: 100}
23
+ end
24
+
25
+ it "should have convinence method for length" do
26
+ arena = Brawl::Arena.new(size: {width: 44, length: 923})
27
+ arena.length.should == 923
28
+ end
29
+
30
+ it "should have convinence method for width" do
31
+ arena = Brawl::Arena.new(size: {width: 234, length: 63})
32
+ arena.width.should == 234
33
+ end
34
+
35
+ end
36
+
37
+ context "when adding objects" do
38
+
39
+ it "should place an object" do
40
+ arena.add_object(object1).should be_true
41
+ end
42
+
43
+ it "should not place objects where there is an object already" do
44
+ object1 = Brawl::BasicArenaObject.new(location: {x: 10, y: 10})
45
+ object2 = Brawl::BasicArenaObject.new(location: {x: 10, y: 10})
46
+ arena.add_object(object1)
47
+ arena.add_object(object2).should be_false
48
+ end
49
+
50
+ it "should not place objects that already exist" do
51
+ arena.add_object(object1)
52
+ arena.add_object(object1).should be_false
53
+ end
54
+
55
+ end
56
+
57
+ context "when removing objects" do
58
+
59
+ it "should remove an object using the object itself" do
60
+ arena.add_object(object1)
61
+ arena.remove_object(object1).should == object1
62
+ end
63
+
64
+ it "should not remove objects that don't exist" do
65
+ arena.remove_object(object1).should be_nil
66
+ end
67
+
68
+ end
69
+
70
+ context "when moving objects" do
71
+
72
+ before(:each) do
73
+ object1 = Brawl::BasicArenaObject.new(location: {x: 5, y: 5})
74
+ arena.add_object(object1)
75
+ end
76
+
77
+ it "should move an object from one location to another" do
78
+ arena.move_object(object1 => {x: 1, y: 1}).should be_true
79
+ end
80
+
81
+ it "should not move an object if its already in the location" do
82
+ arena.move_object(object1 => {x: 5, y: 5}).should_not be_true
83
+ end
84
+
85
+ it "should move an object to the correct location" do
86
+ arena.move_object(object1 => {x: 1, y: 1})
87
+ object1.location.should == {x: 1, y: 1}
88
+ end
89
+
90
+ it "should not move above the bounds" do
91
+ # note the zero based locations
92
+ arena.move_object(object1 => {x: 0, y: 100}).should be_false
93
+ end
94
+
95
+ it "should not move below the bounds" do
96
+ arena.move_object(object1 => {x: -1, y: 5}).should be_false
97
+ end
98
+
99
+ end
100
+
101
+ context "when getting objects" do
102
+
103
+ it "should retrieve objects by a key and value" do
104
+ object1 = Brawl::BasicArenaObject.new(location: {x: 5, y: 5})
105
+ arena.add_object(object1)
106
+ arena.get_object(id: object1.id).should_not be_nil
107
+ end
108
+
109
+ it "should retrieve public object properties not the object itself" do
110
+ object1 = Brawl::BasicArenaObject.new(location: {x: 5, y: 5})
111
+ arena.add_object(object1)
112
+ arena.get_object(id: object1.id).should == object1.properties
113
+ end
114
+
115
+ end
116
+
117
+ context "when pinging locations for objects" do
118
+
119
+ it "should return object information for a location" do
120
+ object1 = Brawl::BasicArenaObject.new(location: {x: 5, y: 5})
121
+ arena.add_object(object1)
122
+ arena.ping(x: 5, y: 5).should == object1.properties
123
+ end
124
+
125
+ it "should return nothing for an empty location" do
126
+ arena.ping(x: 5, y: 5).should be_nil
127
+ end
128
+
129
+ it "should return a wall for the areas around the arena" do
130
+ arena.ping(x:-1,y:0).select{|k,_|[:class,:location].include? k}.should ==
131
+ {class: Brawl::Wall, location: {x:-1, y:0}}
132
+ end
133
+
134
+ it "should return nothing for areas outside the wall" do
135
+ # note that corners can't be "seen" from inside the arena so are not walls
136
+ arena.ping(x:-1,y:-1).should be_nil
137
+ arena.ping(x:10,y:10).should be_nil
138
+ arena.ping(x:-1,y:10).should be_nil
139
+ arena.ping(x:10,y:-1).should be_nil
140
+ arena.ping(x:0,y:101).should be_nil
141
+ arena.ping(x:11,y:0).should be_nil
142
+ arena.ping(x:11,y:11).should be_nil
143
+ end
144
+
145
+ end
146
+
147
+ context "when damage occurs" do
148
+
149
+ it 'should forward damage to the damaged object' do
150
+ expect{arena.forward_damage(damage: 1, target: object1.id)}.should
151
+ change(object1, :health).by(-1)
152
+ end
153
+
154
+ end
155
+
156
+ it "should set the clock to the given clock object" do
157
+ clock = Brawl::Clock.new
158
+ arena.set_clock clock
159
+ arena.clock.should == clock
160
+ end
161
+
162
+
163
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Brawl::BasicArenaObject do
4
+
5
+ let(:object){Brawl::BasicArenaObject.new}
6
+
7
+ it "should set a globally unique ID" do
8
+ object.id.should_not be_nil
9
+ end
10
+
11
+ it "should set a default location of {x: 0, y: 0}" do
12
+ object.location.should == {x: 0, y: 0}
13
+ end
14
+
15
+ it "should set a default heading of 0" do
16
+ object.heading.should == 0
17
+ end
18
+
19
+ it "should set a default health of 1" do
20
+ object.health.should == 1
21
+ end
22
+
23
+ it "should override a default value if a specific value is given" do
24
+ object = Brawl::BasicArenaObject.new(health: 20)
25
+ object.health.should == 20
26
+ end
27
+
28
+ it "should have a hash of property values" do
29
+ object.properties.should be_a(Hash)
30
+ end
31
+
32
+ it "should reduce its health based on damage received" do
33
+ expect{object.damage(1)}.should change(object, :health).by(-1)
34
+ end
35
+
36
+ it "should never reduce health to less than 0" do
37
+ expect{object.damage(100)}.should change(object, :health).to(0)
38
+ end
39
+
40
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ describe Brawl::BasicBot do
4
+
5
+ let(:arena){Brawl::Arena.new(size: {width: 100, length: 100})}
6
+ let(:bot) {Brawl::BasicBot.new(arena: arena, location: {x: 0.0, y: 0.0})}
7
+
8
+ it "should provide a hash of 'public' properites for the arena" do
9
+ bot.properties.should_not be_nil
10
+ end
11
+
12
+ it "should have the methods of the parts that are injected into it" do
13
+ bot = Brawl::BasicBot.new(
14
+ location: {x: 0.0, y: 0.0},
15
+ heading: 0,
16
+ arena: arena,
17
+ parts: {Foo => {baz: "Baz set"}}
18
+ )
19
+ bot.should respond_to(:bar)
20
+ end
21
+
22
+ it "should access properties of the instance" do
23
+ bot = Brawl::BasicBot.new(
24
+ location: {x: 53.0, y: 34.0},
25
+ heading: 0,
26
+ arena: arena,
27
+ parts: {Foo => {baz: "Baz set"}}
28
+ )
29
+ bot.bar.should == {x: 53.0, y: 34.0}
30
+ end
31
+
32
+ it "should initialize parts" do
33
+ bot = Brawl::BasicBot.new(
34
+ location: {x: 0.0, y: 0.0},
35
+ heading: 0,
36
+ arena: arena,
37
+ parts: {Foo => {baz: "Baz set"}}
38
+ )
39
+ bot.baz.should == "Baz set"
40
+ end
41
+
42
+ it "should initialize more than one part" do
43
+ bot = Brawl::BasicBot.new(
44
+ location: {x: 0.0, y: 0.0},
45
+ heading: 0,
46
+ arena: arena,
47
+ parts: {Foo => {baz: "Baz set"}, Qux => {quux: "Quux set"}}
48
+ )
49
+ bot.quux.should == "Quux set"
50
+ end
51
+
52
+ it "should have methods of more than one part" do
53
+ bot = Brawl::BasicBot.new(
54
+ location: {x: 11.0, y: 222.0},
55
+ heading: 0,
56
+ arena: arena,
57
+ parts: {Foo => {baz: "Baz set"}, Qux => {quux: "Quux set"}}
58
+ )
59
+ bot.phoo.should == {x: 11.0, y: 222.0}
60
+ end
61
+
62
+ end
63
+
64
+ module Foo
65
+ attr_accessor :baz
66
+ def initialize(params={})
67
+ @baz = params[:baz]
68
+ end
69
+ def bar
70
+ @location
71
+ end
72
+ end
73
+
74
+ module Qux
75
+ attr_accessor :quux
76
+ def initialize(params={})
77
+ @quux = params[:quux]
78
+ end
79
+ def phoo
80
+ @location
81
+ end
82
+ end
83
+
84
+