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,95 @@
1
+ module RubyWarrior
2
+ module Units
3
+ class Base
4
+ attr_writer :health
5
+ attr_accessor :position
6
+
7
+ def attack_power
8
+ 0
9
+ end
10
+
11
+ def max_health
12
+ 0
13
+ end
14
+
15
+ def earn_points(points)
16
+ end
17
+
18
+ def health
19
+ @health ||= max_health
20
+ end
21
+
22
+ def take_damage(amount)
23
+ unbind if bound?
24
+ if health
25
+ self.health -= amount
26
+ say "takes #{amount} damage, #{health} health power left"
27
+ if health <= 0
28
+ @position = nil
29
+ say "dies"
30
+ end
31
+ end
32
+ end
33
+
34
+ def alive?
35
+ !position.nil?
36
+ end
37
+
38
+ def bound?
39
+ @bound
40
+ end
41
+
42
+ def unbind
43
+ say "released from bonds"
44
+ @bound = false
45
+ end
46
+
47
+ def bind
48
+ @bound = true
49
+ end
50
+
51
+ def say(msg)
52
+ UI.puts_with_delay "#{name} #{msg}"
53
+ end
54
+
55
+ def name
56
+ self.class.name.split('::').last.titleize
57
+ end
58
+ alias_method :to_s, :name
59
+
60
+ def add_abilities(*new_abilities)
61
+ new_abilities.each do |ability|
62
+ abilities[ability] = eval("Abilities::#{ability.to_s.sub('!', '').camelize}").new(self) # TODO use something similar to constantize here
63
+ end
64
+ end
65
+
66
+ def next_turn
67
+ Turn.new(abilities)
68
+ end
69
+
70
+ def prepare_turn
71
+ @current_turn = next_turn
72
+ play_turn(@current_turn)
73
+ end
74
+
75
+ def perform_turn
76
+ if @current_turn.action && @position && !bound?
77
+ name, *args = @current_turn.action
78
+ abilities[name].perform(*args)
79
+ end
80
+ end
81
+
82
+ def play_turn(turn)
83
+ # to be overriden by subclass
84
+ end
85
+
86
+ def abilities
87
+ @abilities ||= {}
88
+ end
89
+
90
+ def character
91
+ "?"
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,30 @@
1
+ module RubyWarrior
2
+ module Units
3
+ class Captive < Base
4
+ attr_accessor :bomb_time
5
+
6
+ def initialize
7
+ add_abilities :explode!
8
+ bind
9
+ end
10
+
11
+ def max_health
12
+ 1
13
+ end
14
+
15
+ def character
16
+ "C"
17
+ end
18
+
19
+ def play_turn(turn)
20
+ if @bomb_time
21
+ @bomb_time -= 1
22
+ if @bomb_time.zero?
23
+ @bound = false # unbind so it can perform an action
24
+ turn.explode!
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ module RubyWarrior
2
+ module Units
3
+ class Sludge < Base
4
+ def initialize
5
+ add_abilities :attack!, :feel
6
+ end
7
+
8
+ def play_turn(turn)
9
+ [:forward, :left, :right, :backward].each do |direction|
10
+ if turn.feel(direction).warrior?
11
+ turn.attack!(direction)
12
+ return
13
+ end
14
+ end
15
+ end
16
+
17
+ def attack_power
18
+ 3
19
+ end
20
+
21
+ def max_health
22
+ 12
23
+ end
24
+
25
+ def character
26
+ "s"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ module RubyWarrior
2
+ module Units
3
+ class ThickSludge < Sludge
4
+ def max_health
5
+ 24
6
+ end
7
+
8
+ def character
9
+ "S"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,58 @@
1
+ module RubyWarrior
2
+ module Units
3
+ class Warrior < Base
4
+ attr_writer :name
5
+ attr_reader :score
6
+
7
+ def initialize
8
+ @score = 0 # TODO make score dynamic
9
+ end
10
+
11
+ def play_turn(turn)
12
+ player.play_turn(turn)
13
+ end
14
+
15
+ def player
16
+ @player ||= Player.new
17
+ end
18
+
19
+ def earn_points(points)
20
+ @score += points
21
+ say "earns #{points} points"
22
+ end
23
+
24
+ def attack_power
25
+ 5
26
+ end
27
+
28
+ def shoot_power
29
+ 3
30
+ end
31
+
32
+ def max_health
33
+ 20
34
+ end
35
+
36
+ def name
37
+ if @name && !@name.empty?
38
+ @name
39
+ else
40
+ "Warrior"
41
+ end
42
+ end
43
+
44
+ def to_s
45
+ name
46
+ end
47
+
48
+ def character
49
+ "@"
50
+ end
51
+
52
+ def perform_turn
53
+ say "does nothing" if @current_turn.action.nil?
54
+ super
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,34 @@
1
+ module RubyWarrior
2
+ module Units
3
+ class Wizard < Base
4
+ def initialize
5
+ add_abilities :shoot!, :look
6
+ end
7
+
8
+ def play_turn(turn)
9
+ [:forward, :left, :right].each do |direction|
10
+ turn.look(direction).each do |space|
11
+ if space.warrior?
12
+ turn.shoot!(direction)
13
+ return
14
+ elsif !space.empty?
15
+ break
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ def shoot_power
22
+ 11
23
+ end
24
+
25
+ def max_health
26
+ 3
27
+ end
28
+
29
+ def character
30
+ "w"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ # --
2
+ # |@>|
3
+ # --
4
+
5
+ description "You see before yourself a long hallway with stairs at the end. There is nothing in the way."
6
+ tip "Call warrior.walk! to walk forward in the Player 'play_turn' method."
7
+
8
+ time_bonus 15
9
+ ace_score 17
10
+ size 2, 1
11
+ stairs 1, 0
12
+
13
+ warrior 0, 0, :east do |u|
14
+ u.add_abilities :walk!
15
+ end
@@ -0,0 +1,15 @@
1
+ # --
2
+ # |@>|
3
+ # --
4
+
5
+ description "You see before yourself a long hallway with stairs at the end. There is nothing in the way."
6
+ tip "Call warrior.walk! to walk forward in the Player 'play_turn' method."
7
+
8
+ time_bonus 15
9
+ ace_score 17
10
+ size 2, 1
11
+ stairs 1, 0
12
+
13
+ warrior 0, 0, :east do |u|
14
+ u.add_abilities :walk!
15
+ end
@@ -0,0 +1,5 @@
1
+ class Player
2
+ def play_turn(warrior)
3
+ warrior.walk!
4
+ end
5
+ end
@@ -0,0 +1,51 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Attack do
4
+ before(:each) do
5
+ @attacker = stub(:position => stub, :attack_power => 3, :say => nil)
6
+ @attack = RubyWarrior::Abilities::Attack.new(@attacker)
7
+ end
8
+
9
+ it "should subtract attack power amount from health" do
10
+ receiver = RubyWarrior::Units::Base.new
11
+ receiver.stubs(:alive?).returns(true)
12
+ receiver.health = 5
13
+ @attack.stubs(:unit).returns(receiver)
14
+ @attack.perform
15
+ receiver.health.should == 2
16
+ end
17
+
18
+ it "should do nothing if recipient is nil" do
19
+ @attack.stubs(:unit).returns(nil)
20
+ lambda { @attack.perform }.should_not raise_error
21
+ end
22
+
23
+ it "should get object at position from offset" do
24
+ @attacker.position.expects(:relative_space).with(1, 0)
25
+ @attack.space(:forward)
26
+ end
27
+
28
+ it "should award points when killing unit" do
29
+ receiver = stub(:take_damage => nil, :max_health => 8, :alive? => false)
30
+ @attack.stubs(:unit).returns(receiver)
31
+ @attacker.expects(:earn_points).with(8)
32
+ @attack.perform
33
+ end
34
+
35
+ it "should not award points when not killing unit" do
36
+ receiver = stub(:max_health => 8, :alive? => true)
37
+ receiver.expects(:take_damage)
38
+ @attack.stubs(:unit).returns(receiver)
39
+ @attacker.expects(:earn_points).never
40
+ @attack.perform
41
+ end
42
+
43
+ it "should reduce attack power when attacking backward" do
44
+ receiver = RubyWarrior::Units::Base.new
45
+ receiver.stubs(:alive?).returns(true)
46
+ receiver.health = 5
47
+ @attack.stubs(:unit).returns(receiver)
48
+ @attack.perform(:backward)
49
+ receiver.health.should == 3
50
+ end
51
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Base do
4
+ before(:each) do
5
+ @unit = stub
6
+ @ability = RubyWarrior::Abilities::Base.new(@unit)
7
+ end
8
+
9
+ it "should have offset for directions" do
10
+ @ability.offset(:forward).should == [1, 0]
11
+ @ability.offset(:right).should == [0, 1]
12
+ @ability.offset(:backward).should == [-1, 0]
13
+ @ability.offset(:left).should == [0, -1]
14
+ end
15
+
16
+ it "should fetch unit at given direction with distance" do
17
+ @ability.expects(:space).with(:right, 3).returns(stub(:unit => 'unit'))
18
+ @ability.unit(:right, 3).should == 'unit'
19
+ end
20
+
21
+ it "should have no description" do
22
+ @ability.description.should be_nil
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Bind do
4
+ before(:each) do
5
+ @bind = RubyWarrior::Abilities::Bind.new(stub(:say => nil))
6
+ end
7
+
8
+ it "should bind recipient" do
9
+ receiver = RubyWarrior::Units::Base.new
10
+ @bind.stubs(:unit).returns(receiver)
11
+ @bind.perform
12
+ receiver.should be_bound
13
+ end
14
+
15
+ it "should do nothing if no recipient" do
16
+ @bind.stubs(:unit).returns(nil)
17
+ lambda { @bind.perform }.should_not raise_error
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::DirectionOf do
4
+ before(:each) do
5
+ @position = stub
6
+ @distance = RubyWarrior::Abilities::DirectionOf.new(stub(:position => @position, :say => nil))
7
+ end
8
+
9
+ it "should return relative direction of given space" do
10
+ @position.stubs(:relative_direction_of).with(:space).returns(:left)
11
+ @distance.perform(:space).should == :left
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::DirectionOfStairs do
4
+ before(:each) do
5
+ @position = stub
6
+ @distance = RubyWarrior::Abilities::DirectionOfStairs.new(stub(:position => @position, :say => nil))
7
+ end
8
+
9
+ it "should return relative direction of stairs" do
10
+ @position.stubs(:relative_direction_of_stairs).returns(:left)
11
+ @distance.perform.should == :left
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Distance do
4
+ before(:each) do
5
+ @position = stub
6
+ @distance = RubyWarrior::Abilities::Distance.new(stub(:position => @position, :say => nil))
7
+ end
8
+
9
+ it "should return distance from stairs" do
10
+ @position.stubs(:distance_from_stairs).returns(5)
11
+ @distance.perform.should == 5
12
+ end
13
+ end