brawl 0.0.0.alpha → 0.0.3

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 (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
+