rubywarrior 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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