rubywarrior 0.1.0

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 (107) hide show
  1. data/CHANGELOG.rdoc +3 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +170 -0
  4. data/Rakefile +21 -0
  5. data/bin/rubywarrior +5 -0
  6. data/features/command_options.feature +46 -0
  7. data/features/levels.feature +51 -0
  8. data/features/profiles.feature +56 -0
  9. data/features/step_definitions/common_steps.rb +19 -0
  10. data/features/step_definitions/interaction_steps.rb +65 -0
  11. data/features/support/env.rb +12 -0
  12. data/features/support/mockio.rb +57 -0
  13. data/features/towers.feature +14 -0
  14. data/lib/ruby_warrior.rb +44 -0
  15. data/lib/ruby_warrior/abilities/attack.rb +24 -0
  16. data/lib/ruby_warrior/abilities/base.rb +36 -0
  17. data/lib/ruby_warrior/abilities/bind.rb +19 -0
  18. data/lib/ruby_warrior/abilities/direction_of.rb +13 -0
  19. data/lib/ruby_warrior/abilities/direction_of_stairs.rb +13 -0
  20. data/lib/ruby_warrior/abilities/distance.rb +13 -0
  21. data/lib/ruby_warrior/abilities/explode.rb +16 -0
  22. data/lib/ruby_warrior/abilities/feel.rb +13 -0
  23. data/lib/ruby_warrior/abilities/health.rb +13 -0
  24. data/lib/ruby_warrior/abilities/listen.rb +15 -0
  25. data/lib/ruby_warrior/abilities/look.rb +15 -0
  26. data/lib/ruby_warrior/abilities/pivot.rb +16 -0
  27. data/lib/ruby_warrior/abilities/rescue.rb +23 -0
  28. data/lib/ruby_warrior/abilities/rest.rb +20 -0
  29. data/lib/ruby_warrior/abilities/shoot.rb +23 -0
  30. data/lib/ruby_warrior/abilities/walk.rb +20 -0
  31. data/lib/ruby_warrior/config.rb +22 -0
  32. data/lib/ruby_warrior/core_additions.rb +25 -0
  33. data/lib/ruby_warrior/floor.rb +71 -0
  34. data/lib/ruby_warrior/game.rb +193 -0
  35. data/lib/ruby_warrior/level.rb +119 -0
  36. data/lib/ruby_warrior/level_loader.rb +56 -0
  37. data/lib/ruby_warrior/player_generator.rb +41 -0
  38. data/lib/ruby_warrior/position.rb +80 -0
  39. data/lib/ruby_warrior/profile.rb +104 -0
  40. data/lib/ruby_warrior/runner.rb +33 -0
  41. data/lib/ruby_warrior/space.rb +63 -0
  42. data/lib/ruby_warrior/tower.rb +14 -0
  43. data/lib/ruby_warrior/turn.rb +38 -0
  44. data/lib/ruby_warrior/ui.rb +54 -0
  45. data/lib/ruby_warrior/units/archer.rb +34 -0
  46. data/lib/ruby_warrior/units/base.rb +95 -0
  47. data/lib/ruby_warrior/units/captive.rb +30 -0
  48. data/lib/ruby_warrior/units/sludge.rb +30 -0
  49. data/lib/ruby_warrior/units/thick_sludge.rb +13 -0
  50. data/lib/ruby_warrior/units/warrior.rb +58 -0
  51. data/lib/ruby_warrior/units/wizard.rb +34 -0
  52. data/spec/fixtures/short-tower/level_001.rb +15 -0
  53. data/spec/fixtures/short-tower/level_002.rb +15 -0
  54. data/spec/fixtures/walking_player.rb +5 -0
  55. data/spec/ruby_warrior/abilities/attack_spec.rb +51 -0
  56. data/spec/ruby_warrior/abilities/base_spec.rb +24 -0
  57. data/spec/ruby_warrior/abilities/bind_spec.rb +19 -0
  58. data/spec/ruby_warrior/abilities/direction_of_spec.rb +13 -0
  59. data/spec/ruby_warrior/abilities/direction_of_stairs_spec.rb +13 -0
  60. data/spec/ruby_warrior/abilities/distance_spec.rb +13 -0
  61. data/spec/ruby_warrior/abilities/explode_spec.rb +21 -0
  62. data/spec/ruby_warrior/abilities/feel_spec.rb +13 -0
  63. data/spec/ruby_warrior/abilities/health_spec.rb +13 -0
  64. data/spec/ruby_warrior/abilities/listen_spec.rb +17 -0
  65. data/spec/ruby_warrior/abilities/look_spec.rb +15 -0
  66. data/spec/ruby_warrior/abilities/pivot_spec.rb +18 -0
  67. data/spec/ruby_warrior/abilities/rescue_spec.rb +40 -0
  68. data/spec/ruby_warrior/abilities/rest_spec.rb +29 -0
  69. data/spec/ruby_warrior/abilities/shoot_spec.rb +22 -0
  70. data/spec/ruby_warrior/abilities/walk_spec.rb +25 -0
  71. data/spec/ruby_warrior/floor_spec.rb +81 -0
  72. data/spec/ruby_warrior/game_spec.rb +119 -0
  73. data/spec/ruby_warrior/level_loader_spec.rb +54 -0
  74. data/spec/ruby_warrior/level_spec.rb +203 -0
  75. data/spec/ruby_warrior/player_generator_spec.rb +12 -0
  76. data/spec/ruby_warrior/position_spec.rb +103 -0
  77. data/spec/ruby_warrior/profile_spec.rb +144 -0
  78. data/spec/ruby_warrior/space_spec.rb +165 -0
  79. data/spec/ruby_warrior/tower_spec.rb +15 -0
  80. data/spec/ruby_warrior/turn_spec.rb +42 -0
  81. data/spec/ruby_warrior/ui_spec.rb +93 -0
  82. data/spec/ruby_warrior/units/archer_spec.rb +23 -0
  83. data/spec/ruby_warrior/units/base_spec.rb +133 -0
  84. data/spec/ruby_warrior/units/captive_spec.rb +34 -0
  85. data/spec/ruby_warrior/units/sludge_spec.rb +27 -0
  86. data/spec/ruby_warrior/units/thick_sludge_spec.rb +19 -0
  87. data/spec/ruby_warrior/units/warrior_spec.rb +60 -0
  88. data/spec/ruby_warrior/units/wizard_spec.rb +23 -0
  89. data/spec/spec_helper.rb +10 -0
  90. data/templates/README.erb +20 -0
  91. data/templates/player.rb +5 -0
  92. data/towers/beginner/level_001.rb +16 -0
  93. data/towers/beginner/level_002.rb +18 -0
  94. data/towers/beginner/level_003.rb +21 -0
  95. data/towers/beginner/level_004.rb +18 -0
  96. data/towers/beginner/level_005.rb +22 -0
  97. data/towers/beginner/level_006.rb +19 -0
  98. data/towers/beginner/level_007.rb +18 -0
  99. data/towers/beginner/level_008.rb +21 -0
  100. data/towers/beginner/level_009.rb +20 -0
  101. data/towers/intermediate/level_001.rb +18 -0
  102. data/towers/intermediate/level_002.rb +20 -0
  103. data/towers/intermediate/level_003.rb +23 -0
  104. data/towers/intermediate/level_004.rb +24 -0
  105. data/towers/intermediate/level_005.rb +19 -0
  106. data/towers/intermediate/level_006.rb +24 -0
  107. metadata +167 -0
@@ -0,0 +1,165 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe RubyWarrior::Space do
4
+ before(:each) do
5
+ @floor = RubyWarrior::Floor.new
6
+ @floor.width = 2
7
+ @floor.height = 3
8
+ end
9
+
10
+ describe "with empty space" do
11
+ before(:each) do
12
+ @space = @floor.space(0, 0)
13
+ end
14
+
15
+ it "should not be enemy" do
16
+ @space.should_not be_enemy
17
+ end
18
+
19
+ it "should not be warrior" do
20
+ @space.should_not be_warrior
21
+ end
22
+
23
+ it "should be empty" do
24
+ @space.should be_empty
25
+ end
26
+
27
+ it "should not be wall" do
28
+ @space.should_not be_wall
29
+ end
30
+
31
+ it "should not be stairs" do
32
+ @space.should_not be_stairs
33
+ end
34
+
35
+ it "should not be captive" do
36
+ @space.should_not be_captive
37
+ end
38
+
39
+ it "should say 'nothing' as name" do
40
+ @space.to_s.should == 'nothing'
41
+ end
42
+
43
+ it "should not be ticking" do
44
+ @space.should_not be_ticking
45
+ end
46
+ end
47
+
48
+ describe "out of bounds" do
49
+ before(:each) do
50
+ @space = @floor.space(-1, 1)
51
+ end
52
+
53
+ it "should be wall" do
54
+ @space.should be_wall
55
+ end
56
+
57
+ it "should not be empty" do
58
+ @space.should_not be_empty
59
+ end
60
+
61
+ it "should have name of 'wall'" do
62
+ @space.to_s.should == 'wall'
63
+ end
64
+ end
65
+
66
+ describe "with warrior" do
67
+ before(:each) do
68
+ warrior = RubyWarrior::Units::Warrior.new
69
+ @floor.add(warrior, 0, 0)
70
+ @space = @floor.space(0, 0)
71
+ end
72
+
73
+ it "should be warrior" do
74
+ @space.should be_warrior
75
+ end
76
+
77
+ it "should not be enemy" do
78
+ @space.should_not be_enemy
79
+ end
80
+
81
+ it "should not be empty" do
82
+ @space.should_not be_enemy
83
+ end
84
+
85
+ it "should know what unit is on that space" do
86
+ @space.unit.should be_kind_of(RubyWarrior::Units::Warrior)
87
+ end
88
+ end
89
+
90
+ describe "with enemy" do
91
+ before(:each) do
92
+ @floor.add(RubyWarrior::Units::Sludge.new, 0, 0)
93
+ @space = @floor.space(0, 0)
94
+ end
95
+
96
+ it "should be enemy" do
97
+ @space.should be_enemy
98
+ end
99
+
100
+ it "should not be warrior" do
101
+ @space.should_not be_warrior
102
+ end
103
+
104
+ it "should not be empty" do
105
+ @space.should_not be_empty
106
+ end
107
+
108
+ it "should have name of unit" do
109
+ @space.to_s.should == "Sludge"
110
+ end
111
+
112
+ describe "bound" do
113
+ before(:each) do
114
+ @space.unit.bind
115
+ end
116
+
117
+ it "should be captive" do
118
+ @space.should be_captive
119
+ end
120
+
121
+ it "should not look like enemy" do
122
+ @space.should_not be_enemy
123
+ end
124
+ end
125
+ end
126
+
127
+ describe "with captive" do
128
+ before(:each) do
129
+ @floor.add(RubyWarrior::Units::Captive.new, 0, 0)
130
+ @space = @floor.space(0, 0)
131
+ end
132
+
133
+ it "should be captive" do
134
+ @space.should be_captive
135
+ end
136
+
137
+ it "should not be enemy" do
138
+ @space.should_not be_enemy
139
+ end
140
+
141
+ it "should be ticking if captive has time bomb" do
142
+ @space.unit.bomb_time = 10
143
+ @space.should be_ticking
144
+ end
145
+
146
+ it "should not be ticking if captive does not have time bomb" do
147
+ @space.should_not be_ticking
148
+ end
149
+ end
150
+
151
+ describe "at stairs" do
152
+ before(:each) do
153
+ @floor.place_stairs(0, 0)
154
+ @space = @floor.space(0, 0)
155
+ end
156
+
157
+ it "should be empty" do
158
+ @space.should be_empty
159
+ end
160
+
161
+ it "should be stairs" do
162
+ @space.should be_stairs
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe RubyWarrior::Tower do
4
+ before(:each) do
5
+ @tower = RubyWarrior::Tower.new('path/to/tower')
6
+ end
7
+
8
+ it "should consider last part of path as name" do
9
+ @tower.name.should == 'tower'
10
+ end
11
+
12
+ it "should use name when converting to string" do
13
+ @tower.to_s.should == @tower.name
14
+ end
15
+ end
@@ -0,0 +1,42 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe RubyWarrior::Turn do
4
+ describe "with actions" do
5
+ before(:each) do
6
+ @turn = RubyWarrior::Turn.new({:walk! => nil, :attack! => nil})
7
+ end
8
+
9
+ it "should have no action performed at first" do
10
+ @turn.action.should be_nil
11
+ end
12
+
13
+ it "should be able to perform action and recall it" do
14
+ @turn.walk!
15
+ @turn.action.should == [:walk!]
16
+ end
17
+
18
+ it "should include arguments passed to action" do
19
+ @turn.walk! :forward
20
+ @turn.action.should == [:walk!, :forward]
21
+ end
22
+
23
+ it "should not be able to call multiple actions per turn" do
24
+ @turn.walk! :forward
25
+ lambda { @turn.attack! }.should raise_error
26
+ end
27
+ end
28
+
29
+ describe "with senses" do
30
+ before(:each) do
31
+ @feel = RubyWarrior::Abilities::Feel.new(Object.new)
32
+ @feel.stubs(:space).returns(Object.new)
33
+ @feel.stubs(:space).with(:backward).returns(Object.new)
34
+ @turn = RubyWarrior::Turn.new({:feel => @feel})
35
+ end
36
+
37
+ it "should be able to call sense with any argument and return expected results" do
38
+ @turn.feel.should == @feel.perform
39
+ @turn.feel(:backward).should == @feel.perform(:backward)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,93 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe RubyWarrior::UI do
4
+ before(:each) do
5
+ @ui = RubyWarrior::UI
6
+ @config = RubyWarrior::Config
7
+ @out = StringIO.new
8
+ @in = StringIO.new
9
+ @config.out_stream = @out
10
+ @config.in_stream = @in
11
+ end
12
+
13
+ it "should add puts to out stream" do
14
+ @ui.puts "hello"
15
+ @out.string.should == "hello\n"
16
+ end
17
+
18
+ it "should add print to out stream without newline" do
19
+ @ui.print "hello"
20
+ @out.string.should == "hello"
21
+ end
22
+
23
+ it "should fetch gets from in stream" do
24
+ @in.puts "bar"
25
+ @in.rewind
26
+ @ui.gets.should == "bar\n"
27
+ end
28
+
29
+ it "should gets should return empty string if no input" do
30
+ @config.in_stream = nil
31
+ @ui.gets.should == ""
32
+ end
33
+
34
+ it "should request text input" do
35
+ @in.puts "bar"
36
+ @in.rewind
37
+ @ui.request("foo").should == "bar"
38
+ @out.string.should == "foo"
39
+ end
40
+
41
+ it "should ask for yes/no and return true when yes" do
42
+ @ui.expects(:request).with('foo? [yn] ').returns('y')
43
+ @ui.ask("foo?").should be_true
44
+ end
45
+
46
+ it "should ask for yes/no and return false when no" do
47
+ @ui.stubs(:request).returns('n')
48
+ @ui.ask("foo?").should be_false
49
+ end
50
+
51
+ it "should ask for yes/no and return false for any input" do
52
+ @ui.stubs(:request).returns('aklhasdf')
53
+ @ui.ask("foo?").should be_false
54
+ end
55
+
56
+ it "should present multiple options and return selected one" do
57
+ @ui.expects(:request).with(includes('item')).returns('2')
58
+ @ui.choose('item', [:foo, :bar, :test]).should == :bar
59
+ @out.string.should include('[1] foo')
60
+ @out.string.should include('[2] bar')
61
+ @out.string.should include('[3] test')
62
+ end
63
+
64
+ it "choose should accept array as option" do
65
+ @ui.stubs(:request).returns('3')
66
+ @ui.choose('item', [:foo, :bar, [:tower, 'easy']]).should == :tower
67
+ @out.string.should include('[3] easy')
68
+ end
69
+
70
+ it "choose should return option without prompt if only one item" do
71
+ @ui.expects(:puts).never
72
+ @ui.expects(:gets).never
73
+ @ui.stubs(:request).returns('3')
74
+ @ui.choose('item', [:foo]).should == :foo
75
+ end
76
+
77
+ it "choose should return first value in array of option if only on item" do
78
+ @ui.choose('item', [[:foo, :bar]]).should == :foo
79
+ end
80
+
81
+ it "should delay after puts when specified" do
82
+ @config.delay = 1.3
83
+ @ui.expects(:puts).with("foo")
84
+ @ui.expects(:sleep).with(1.3)
85
+ @ui.puts_with_delay("foo")
86
+ end
87
+
88
+ it "should not delay puts when delay isn't specified" do
89
+ @ui.expects(:puts).with("foo")
90
+ @ui.expects(:sleep).never
91
+ @ui.puts_with_delay("foo")
92
+ end
93
+ end
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Units::Archer do
4
+ before(:each) do
5
+ @archer = RubyWarrior::Units::Archer.new
6
+ end
7
+
8
+ it "should have look and shoot abilities" do
9
+ @archer.abilities.keys.to_set.should == [:shoot!, :look].to_set
10
+ end
11
+
12
+ it "should have shoot power of 3" do
13
+ @archer.shoot_power.should == 3
14
+ end
15
+
16
+ it "should have 7 max health" do
17
+ @archer.max_health.should == 7
18
+ end
19
+
20
+ it "should appear as a on map" do
21
+ @archer.character.should == "a"
22
+ end
23
+ end
@@ -0,0 +1,133 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Units::Base do
4
+ before(:each) do
5
+ @unit = RubyWarrior::Units::Base.new
6
+ end
7
+
8
+ it "should have an attack power which defaults to zero" do
9
+ @unit.attack_power.should be_zero
10
+ end
11
+
12
+ it "should consider itself dead when no position" do
13
+ @unit.position.should be_nil
14
+ @unit.should_not be_alive
15
+ end
16
+
17
+ it "should consider itself alive with position" do
18
+ @unit.position = stub
19
+ @unit.should be_alive
20
+ end
21
+
22
+ it "should default max health to 10" do
23
+ @unit.max_health.should be_zero
24
+ end
25
+
26
+ it "should do nothing when earning points" do
27
+ lambda { @unit.earn_points(10) }.should_not raise_error
28
+ end
29
+
30
+ it "should default health to max health" do
31
+ @unit.stubs(:max_health).returns(10)
32
+ @unit.health.should == 10
33
+ end
34
+
35
+ it "should subtract health when taking damage" do
36
+ @unit.stubs(:max_health).returns(10)
37
+ @unit.take_damage(3)
38
+ @unit.health.should == 7
39
+ end
40
+
41
+ it "should do nothing when taking damage if health isn't set" do
42
+ lambda { @unit.take_damage(3) }.should_not raise_error
43
+ end
44
+
45
+ it "should set position to nil when running out of health" do
46
+ @unit.position = stub
47
+ @unit.stubs(:max_health).returns(10)
48
+ @unit.take_damage(10)
49
+ @unit.position.should be_nil
50
+ end
51
+
52
+ it "should print out line with name when speaking" do
53
+ RubyWarrior::UI.expects(:puts_with_delay).with("Base foo")
54
+ @unit.say "foo"
55
+ end
56
+
57
+ it "should return name in to_s" do
58
+ @unit.name.should == 'Base'
59
+ @unit.to_s.should == 'Base'
60
+ end
61
+
62
+ it "should prepare turn by calling play_turn with next turn object" do
63
+ @unit.stubs(:next_turn).returns('next_turn')
64
+ @unit.expects(:play_turn).with('next_turn')
65
+ @unit.prepare_turn
66
+ end
67
+
68
+ it "should perform action when calling perform on turn" do
69
+ @unit.position = stub
70
+ RubyWarrior::Abilities::Walk.any_instance.expects(:perform).with(:backward)
71
+ @unit.add_abilities(:walk!)
72
+ turn = stub(:action => [:walk!, :backward])
73
+ @unit.stubs(:next_turn).returns(turn)
74
+ @unit.prepare_turn
75
+ @unit.perform_turn
76
+ end
77
+
78
+ it "should not perform action when dead (no position)" do
79
+ @unit.position = nil
80
+ RubyWarrior::Abilities::Walk.any_instance.stubs(:perform).raises("action should not be called")
81
+ @unit.add_abilities(:walk!)
82
+ turn = stub(:action => [:walk!, :backward])
83
+ @unit.stubs(:next_turn).returns(turn)
84
+ @unit.prepare_turn
85
+ @unit.perform_turn
86
+ end
87
+
88
+ it "should not raise an exception when calling perform_turn when there's no action" do
89
+ @unit.prepare_turn
90
+ lambda { @unit.perform_turn }.should_not raise_error
91
+ end
92
+
93
+ it "should pass abilities to new turn when calling next_turn" do
94
+ RubyWarrior::Turn.expects(:new).with(:walk! => nil, :attack! => nil, :feel => nil).returns('turn')
95
+ @unit.stubs(:abilities).returns(:walk! => nil, :attack! => nil, :feel => nil)
96
+ @unit.next_turn.should == 'turn'
97
+ end
98
+
99
+ it "should add ability" do
100
+ RubyWarrior::Abilities::Walk.expects(:new).with(@unit).returns('walk')
101
+ @unit.add_abilities(:walk!)
102
+ @unit.abilities.should == { :walk! => 'walk' }
103
+ end
104
+
105
+ it "should appear as question mark on map" do
106
+ @unit.character.should == "?"
107
+ end
108
+
109
+ it "should be released from bonds when taking damage" do
110
+ @unit.stubs(:max_health).returns(10)
111
+ @unit.bind
112
+ @unit.should be_bound
113
+ @unit.take_damage(2)
114
+ @unit.should_not be_bound
115
+ end
116
+
117
+ it "should be released from bonds when calling release" do
118
+ @unit.bind
119
+ @unit.unbind
120
+ @unit.should_not be_bound
121
+ end
122
+
123
+ it "should not perform action when bound" do
124
+ @unit.position = stub
125
+ @unit.bind
126
+ RubyWarrior::Abilities::Walk.any_instance.stubs(:perform).raises("action should not be called")
127
+ @unit.add_abilities(:walk!)
128
+ turn = stub(:action => [:walk!, :backward])
129
+ @unit.stubs(:next_turn).returns(turn)
130
+ @unit.prepare_turn
131
+ @unit.perform_turn
132
+ end
133
+ end