karnowski-ruby-warrior 0.0.1

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 (108) hide show
  1. data/.gitignore +3 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +156 -0
  4. data/Rakefile +36 -0
  5. data/VERSION +1 -0
  6. data/bin/rubywarrior +8 -0
  7. data/features/levels.feature +50 -0
  8. data/features/profiles.feature +46 -0
  9. data/features/step_definitions/common_steps.rb +7 -0
  10. data/features/step_definitions/interaction_steps.rb +53 -0
  11. data/features/support/env.rb +8 -0
  12. data/features/support/mockio.rb +57 -0
  13. data/features/towers.feature +14 -0
  14. data/lib/ruby_warrior.rb +41 -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 +11 -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 +160 -0
  35. data/lib/ruby_warrior/level.rb +93 -0
  36. data/lib/ruby_warrior/level_loader.rb +52 -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 +86 -0
  40. data/lib/ruby_warrior/space.rb +63 -0
  41. data/lib/ruby_warrior/tower.rb +14 -0
  42. data/lib/ruby_warrior/turn.rb +38 -0
  43. data/lib/ruby_warrior/ui.rb +64 -0
  44. data/lib/ruby_warrior/units/archer.rb +34 -0
  45. data/lib/ruby_warrior/units/base.rb +95 -0
  46. data/lib/ruby_warrior/units/captive.rb +30 -0
  47. data/lib/ruby_warrior/units/sludge.rb +30 -0
  48. data/lib/ruby_warrior/units/thick_sludge.rb +13 -0
  49. data/lib/ruby_warrior/units/warrior.rb +58 -0
  50. data/lib/ruby_warrior/units/wizard.rb +34 -0
  51. data/ruby-warrior.gemspec +191 -0
  52. data/script/console +8 -0
  53. data/spec/fixtures/short-tower/level_001.rb +14 -0
  54. data/spec/fixtures/short-tower/level_002.rb +14 -0
  55. data/spec/fixtures/walking_player.rb +5 -0
  56. data/spec/ruby_warrior/abilities/attack_spec.rb +51 -0
  57. data/spec/ruby_warrior/abilities/base_spec.rb +24 -0
  58. data/spec/ruby_warrior/abilities/bind_spec.rb +19 -0
  59. data/spec/ruby_warrior/abilities/direction_of_spec.rb +13 -0
  60. data/spec/ruby_warrior/abilities/direction_of_stairs_spec.rb +13 -0
  61. data/spec/ruby_warrior/abilities/distance_spec.rb +13 -0
  62. data/spec/ruby_warrior/abilities/explode_spec.rb +21 -0
  63. data/spec/ruby_warrior/abilities/feel_spec.rb +13 -0
  64. data/spec/ruby_warrior/abilities/health_spec.rb +13 -0
  65. data/spec/ruby_warrior/abilities/listen_spec.rb +17 -0
  66. data/spec/ruby_warrior/abilities/look_spec.rb +15 -0
  67. data/spec/ruby_warrior/abilities/pivot_spec.rb +18 -0
  68. data/spec/ruby_warrior/abilities/rescue_spec.rb +40 -0
  69. data/spec/ruby_warrior/abilities/rest_spec.rb +29 -0
  70. data/spec/ruby_warrior/abilities/shoot_spec.rb +22 -0
  71. data/spec/ruby_warrior/abilities/walk_spec.rb +25 -0
  72. data/spec/ruby_warrior/floor_spec.rb +81 -0
  73. data/spec/ruby_warrior/game_spec.rb +96 -0
  74. data/spec/ruby_warrior/level_loader_spec.rb +54 -0
  75. data/spec/ruby_warrior/level_spec.rb +163 -0
  76. data/spec/ruby_warrior/player_generator_spec.rb +12 -0
  77. data/spec/ruby_warrior/position_spec.rb +103 -0
  78. data/spec/ruby_warrior/profile_spec.rb +125 -0
  79. data/spec/ruby_warrior/space_spec.rb +165 -0
  80. data/spec/ruby_warrior/tower_spec.rb +15 -0
  81. data/spec/ruby_warrior/turn_spec.rb +42 -0
  82. data/spec/ruby_warrior/ui_spec.rb +96 -0
  83. data/spec/ruby_warrior/units/archer_spec.rb +23 -0
  84. data/spec/ruby_warrior/units/base_spec.rb +133 -0
  85. data/spec/ruby_warrior/units/captive_spec.rb +34 -0
  86. data/spec/ruby_warrior/units/sludge_spec.rb +27 -0
  87. data/spec/ruby_warrior/units/thick_sludge_spec.rb +19 -0
  88. data/spec/ruby_warrior/units/warrior_spec.rb +60 -0
  89. data/spec/ruby_warrior/units/wizard_spec.rb +23 -0
  90. data/spec/spec_helper.rb +7 -0
  91. data/templates/README.erb +20 -0
  92. data/templates/player.rb +5 -0
  93. data/towers/beginner/level_001.rb +15 -0
  94. data/towers/beginner/level_002.rb +17 -0
  95. data/towers/beginner/level_003.rb +20 -0
  96. data/towers/beginner/level_004.rb +17 -0
  97. data/towers/beginner/level_005.rb +21 -0
  98. data/towers/beginner/level_006.rb +18 -0
  99. data/towers/beginner/level_007.rb +17 -0
  100. data/towers/beginner/level_008.rb +20 -0
  101. data/towers/beginner/level_009.rb +19 -0
  102. data/towers/intermediate/level_001.rb +17 -0
  103. data/towers/intermediate/level_002.rb +19 -0
  104. data/towers/intermediate/level_003.rb +22 -0
  105. data/towers/intermediate/level_004.rb +23 -0
  106. data/towers/intermediate/level_005.rb +18 -0
  107. data/towers/intermediate/level_006.rb +23 -0
  108. metadata +218 -0
@@ -0,0 +1,12 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe RubyWarrior::PlayerGenerator do
4
+ before(:each) do
5
+ @level = RubyWarrior::Level.new(RubyWarrior::Profile.new, 15)
6
+ @generator = RubyWarrior::PlayerGenerator.new(@level)
7
+ end
8
+
9
+ it "should know templates path" do
10
+ @generator.templates_path.should == File.expand_path(File.dirname(__FILE__) + "/../../templates")
11
+ end
12
+ end
@@ -0,0 +1,103 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe RubyWarrior::Position do
4
+ before(:each) do
5
+ @unit = RubyWarrior::Units::Base.new
6
+ @floor = RubyWarrior::Floor.new
7
+ @floor.width = 6
8
+ @floor.height = 5
9
+ @floor.add(@unit, 1, 2, :north)
10
+ @position = @unit.position
11
+ end
12
+
13
+ it "should rotate clockwise" do
14
+ @position.direction.should == :north
15
+ [:east, :south, :west, :north, :east].each do |dir|
16
+ @position.rotate(1)
17
+ @position.direction.should == dir
18
+ end
19
+ end
20
+
21
+ it "should rotate counterclockwise" do
22
+ @position.direction.should == :north
23
+ [:west, :south, :east, :north, :west].each do |dir|
24
+ @position.rotate(-1)
25
+ @position.direction.should == dir
26
+ end
27
+ end
28
+
29
+ it "should get relative space in front" do
30
+ unit = RubyWarrior::Units::Base.new
31
+ @floor.add(unit, 1, 1)
32
+ @position.relative_space(1).should_not be_empty
33
+ end
34
+
35
+ it "should get relative object in front when rotated" do
36
+ unit = RubyWarrior::Units::Base.new
37
+ @floor.add(unit, 2, 2)
38
+ @position.rotate(1)
39
+ @position.relative_space(1).should_not be_empty
40
+ end
41
+
42
+ it "should get relative object diagonally" do
43
+ unit = RubyWarrior::Units::Base.new
44
+ @floor.add(unit, 0, 1)
45
+ @position.relative_space(1, -1).should_not be_empty
46
+ end
47
+
48
+ it "should get relative object diagonally when rotating" do
49
+ unit = RubyWarrior::Units::Base.new
50
+ @floor.add(unit, 0, 1)
51
+ @position.rotate(2)
52
+ @position.relative_space(-1, 1).should_not be_empty
53
+ end
54
+
55
+ it "should move object on floor relatively" do
56
+ @floor.get(1, 2).should == @unit
57
+ @position.move(-1, 2)
58
+ @floor.get(1, 2).should be_nil
59
+ @floor.get(3, 3).should == @unit
60
+ @position.rotate(1)
61
+ @position.move(-1)
62
+ @floor.get(3, 3).should be_nil
63
+ @floor.get(2, 3).should == @unit
64
+ end
65
+
66
+ it "should return distance from stairs as 0 when on stairs" do
67
+ @floor.place_stairs(1, 2)
68
+ @position.distance_from_stairs.should == 0
69
+ end
70
+
71
+ it "should return distance from stairs in both directions" do
72
+ @floor.place_stairs(0, 3)
73
+ @position.distance_from_stairs.should == 2
74
+ end
75
+
76
+ it "should return relative direction of stairs" do
77
+ @floor.place_stairs(0, 0)
78
+ @position.relative_direction_of_stairs.should == :forward
79
+ end
80
+
81
+ it "should return relative direction of given space" do
82
+ @position.relative_direction_of(@floor.space(5, 3)).should == :right
83
+ @position.rotate 1
84
+ @position.relative_direction_of(@floor.space(1, 4)).should == :right
85
+ end
86
+
87
+ it "should be able to determine relative direction" do
88
+ @position.relative_direction(:north).should == :forward
89
+ @position.relative_direction(:south).should == :backward
90
+ @position.relative_direction(:west).should == :left
91
+ @position.relative_direction(:east).should == :right
92
+ @position.rotate 1
93
+ @position.relative_direction(:north).should == :left
94
+ @position.rotate 1
95
+ @position.relative_direction(:north).should == :backward
96
+ @position.rotate 1
97
+ @position.relative_direction(:north).should == :right
98
+ end
99
+
100
+ it "should return a space at the same location as position" do
101
+ @position.space.location.should == [1, 2]
102
+ end
103
+ end
@@ -0,0 +1,125 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe RubyWarrior::Profile do
4
+ before(:each) do
5
+ @profile = RubyWarrior::Profile.new
6
+ end
7
+
8
+ it "should have warrior name" do
9
+ @profile.warrior_name = 'Joe'
10
+ @profile.warrior_name.should == 'Joe'
11
+ end
12
+
13
+ it "should start level number at 0" do
14
+ @profile.level_number.should be_zero
15
+ end
16
+
17
+ it "should start score at 0 and allow it to increment" do
18
+ @profile.score.should be_zero
19
+ @profile.score += 5
20
+ @profile.score.should == 5
21
+ end
22
+
23
+ it "should have no abilities and allow adding" do
24
+ @profile.abilities.should == []
25
+ @profile.abilities += [:foo, :bar]
26
+ @profile.abilities.should == [:foo, :bar]
27
+ end
28
+
29
+ it "should encode with marshal + base64" do
30
+ @profile.encode.should == Base64.encode64(Marshal.dump(@profile))
31
+ end
32
+
33
+ it "should decode with marshal + base64" do
34
+ RubyWarrior::Profile.decode(@profile.encode).warrior_name.should == @profile.warrior_name
35
+ end
36
+
37
+ it "load should read file, decode and set player path" do
38
+ profile = 'profile'
39
+ profile.expects(:player_path=).with('path/to')
40
+ File.expects(:read).with('path/to/.profile').returns('encoded_profile')
41
+ RubyWarrior::Profile.expects(:decode).with('encoded_profile').returns(profile)
42
+ RubyWarrior::Profile.load('path/to/.profile').should == profile
43
+ end
44
+
45
+
46
+ it "should add abilities and remove duplicates" do
47
+ @profile.add_abilities(:foo, :bar, :blah, :bar)
48
+ @profile.abilities.should == [:foo, :bar, :blah]
49
+ end
50
+
51
+ it "should fetch new level with current number" do
52
+ @profile.level_number = 1
53
+ @profile.current_level.number.should == 1
54
+ end
55
+
56
+ it "should fetch next level" do
57
+ @profile.level_number = 1
58
+ @profile.next_level.number.should == 2
59
+ end
60
+
61
+ it "should enable epic mode and reset scores if nil" do
62
+ @profile.epic_score = nil
63
+ @profile.current_epic_score = nil
64
+ @profile.enable_epic_mode
65
+ @profile.should be_epic
66
+ @profile.epic_score.should be_zero
67
+ @profile.current_epic_score.should be_zero
68
+ end
69
+
70
+ it "should override epic score with current one if it is higher" do
71
+ @profile.enable_epic_mode
72
+ @profile.epic_score.should be_zero
73
+ @profile.current_epic_score = 123
74
+ @profile.update_epic_score
75
+ @profile.epic_score.should == 123
76
+ end
77
+
78
+ it "should not override epic score with current one if it is lower" do
79
+ @profile.enable_epic_mode
80
+ @profile.epic_score = 124
81
+ @profile.current_epic_score = 123
82
+ @profile.update_epic_score
83
+ @profile.epic_score.should == 124
84
+ end
85
+
86
+ describe "with tower path" do
87
+ before(:each) do
88
+ @profile.warrior_name = "John Smith"
89
+ @profile.tower_path = 'path/to/tower'
90
+ end
91
+
92
+ it "save should write file with encoded profile" do
93
+ file = stub
94
+ file.expects(:write).with('encoded_profile')
95
+ File.expects(:open).with(@profile.player_path + '/.profile', 'w').yields(file)
96
+ @profile.expects(:encode).returns('encoded_profile')
97
+ @profile.save
98
+ end
99
+
100
+ it "should have a nice string representation" do
101
+ @profile.warrior_name = 'Joe'
102
+ @profile.to_s.should == "Joe - tower - level 0 - score 0"
103
+ end
104
+
105
+ it "should include epic score in string representation" do
106
+ @profile.warrior_name = 'Joe'
107
+ @profile.enable_epic_mode
108
+ @profile.to_s.should == "Joe - tower - first score 0 - epic score 0"
109
+ end
110
+
111
+ it "should guess at the player path" do
112
+ @profile.player_path.should == './ruby-warrior/john-smith-tower'
113
+ end
114
+
115
+ it "should use specified player path" do
116
+ @profile.player_path = "path/to/player"
117
+ @profile.player_path.should == "path/to/player"
118
+ end
119
+
120
+ it "should load tower from path" do
121
+ RubyWarrior::Tower.expects(:new).with('path/to/tower').returns('tower')
122
+ @profile.tower.should == 'tower'
123
+ end
124
+ end
125
+ end
@@ -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