karnowski-ruby-warrior 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,13 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Health do
4
+ before(:each) do
5
+ @warrior = RubyWarrior::Units::Warrior.new
6
+ @health = RubyWarrior::Abilities::Health.new(@warrior)
7
+ end
8
+
9
+ it "should return the amount of health" do
10
+ @warrior.health = 10
11
+ @health.perform.should == 10
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Listen do
4
+ before(:each) do
5
+ @floor = RubyWarrior::Floor.new
6
+ @floor.width = 2
7
+ @floor.height = 3
8
+ @warrior = RubyWarrior::Units::Warrior.new
9
+ @floor.add(@warrior, 0, 0)
10
+ @listen = RubyWarrior::Abilities::Listen.new(@warrior)
11
+ end
12
+
13
+ it "should return an array of spaces which have units on them besides main unit" do
14
+ @floor.add(RubyWarrior::Units::Base.new, 0, 1)
15
+ @listen.perform.should have(1).record
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Look do
4
+ before(:each) do
5
+ @unit = stub(:position => stub, :say => nil)
6
+ @feel = RubyWarrior::Abilities::Look.new(@unit)
7
+ end
8
+
9
+ it "should get 3 objects at position from offset" do
10
+ @unit.position.expects(:relative_space).with(1, 0).returns(1)
11
+ @unit.position.expects(:relative_space).with(2, 0).returns(2)
12
+ @unit.position.expects(:relative_space).with(3, 0).returns(3)
13
+ @feel.perform(:forward).should == [1, 2, 3]
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Pivot do
4
+ before(:each) do
5
+ @position = stub
6
+ @pivot = RubyWarrior::Abilities::Pivot.new(stub(:position => @position, :say => nil))
7
+ end
8
+
9
+ it "should flip around when not passing arguments" do
10
+ @position.expects(:rotate).with(2)
11
+ @pivot.perform
12
+ end
13
+
14
+ it "should rotate 1 when pivoting right" do
15
+ @position.expects(:rotate).with(1)
16
+ @pivot.perform(:right)
17
+ end
18
+ end
@@ -0,0 +1,40 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Rescue do
4
+ before(:each) do
5
+ @warrior = RubyWarrior::Units::Warrior.new
6
+ @rescue = RubyWarrior::Abilities::Rescue.new(@warrior)
7
+ end
8
+
9
+ it "should rescue captive" do
10
+ captive = RubyWarrior::Units::Captive.new
11
+ captive.position = stub
12
+ @rescue.expects(:space).with(:forward).returns(stub(:captive? => true))
13
+ @rescue.expects(:unit).with(:forward).returns(captive)
14
+ @warrior.expects(:earn_points).with(20)
15
+ @rescue.perform
16
+ captive.position.should be_nil
17
+ end
18
+
19
+ it "should do nothing to other unit if not bound" do
20
+ unit = RubyWarrior::Units::Base.new
21
+ unit.position = stub
22
+ @rescue.expects(:space).with(:forward).returns(stub(:captive? => false))
23
+ @rescue.expects(:unit).with(:forward).never
24
+ @warrior.expects(:earn_points).never
25
+ @rescue.perform
26
+ unit.position.should_not be_nil
27
+ end
28
+
29
+ it "should release other unit when bound" do
30
+ unit = RubyWarrior::Units::Base.new
31
+ unit.bind
32
+ unit.position = stub
33
+ @rescue.expects(:space).with(:forward).returns(stub(:captive? => true))
34
+ @rescue.expects(:unit).with(:forward).returns(unit)
35
+ @warrior.expects(:earn_points).never
36
+ @rescue.perform
37
+ unit.should_not be_bound
38
+ unit.position.should_not be_nil
39
+ end
40
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Rest do
4
+ before(:each) do
5
+ @warrior = RubyWarrior::Units::Warrior.new
6
+ @rest = RubyWarrior::Abilities::Rest.new(@warrior)
7
+ end
8
+
9
+ it "should give 10% health back" do
10
+ @warrior.stubs(:max_health).returns(20)
11
+ @warrior.health = 10
12
+ @rest.perform
13
+ @warrior.health.should == 12
14
+ end
15
+
16
+ it "should add health when at max" do
17
+ @warrior.stubs(:max_health).returns(20)
18
+ @warrior.health = 20
19
+ @rest.perform
20
+ @warrior.health.should == 20
21
+ end
22
+
23
+ it "should not go over max health" do
24
+ @warrior.stubs(:max_health).returns(20)
25
+ @warrior.health = 19
26
+ @rest.perform
27
+ @warrior.health.should == 20
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Shoot do
4
+ before(:each) do
5
+ @shooter = stub(:position => stub, :shoot_power => 2, :say => nil)
6
+ @shoot = RubyWarrior::Abilities::Shoot.new(@shooter)
7
+ end
8
+
9
+ it "should shoot only first unit" do
10
+ receiver = stub(:alive? => true)
11
+ receiver.expects(:take_damage).with(2)
12
+ other = stub(:alive? => true)
13
+ other.expects(:take_damage).never
14
+ @shoot.expects(:multi_unit).with(:forward, anything).returns([nil, receiver, other, nil])
15
+ @shoot.perform
16
+ end
17
+
18
+ it "should shoot and do nothing if no units in the way" do
19
+ @shoot.expects(:multi_unit).with(:forward, anything).returns([nil, nil])
20
+ lambda { @shoot.perform }.should_not raise_error
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Walk do
4
+ before(:each) do
5
+ @space = stub(:empty? => true, :unit => nil)
6
+ @position = stub(:relative_space => @space, :move => nil)
7
+ @walk = RubyWarrior::Abilities::Walk.new(stub(:position => @position, :say => nil))
8
+ end
9
+
10
+ it "should move position forward when calling perform" do
11
+ @position.expects(:move).with(1, 0)
12
+ @walk.perform
13
+ end
14
+
15
+ it "should move position right if that is direction" do
16
+ @position.expects(:move).with(0, 1)
17
+ @walk.perform(:right)
18
+ end
19
+
20
+ it "should keep position if something is in the way" do
21
+ @position.stubs(:move).raises("shouldn't be called")
22
+ @space.stubs(:empty?).returns(false)
23
+ lambda { @walk.perform(:right) }.should_not raise_error
24
+ end
25
+ end
@@ -0,0 +1,81 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe RubyWarrior::Floor do
4
+ describe "2x3" do
5
+ before(:each) do
6
+ @floor = RubyWarrior::Floor.new
7
+ @floor.width = 2
8
+ @floor.height = 3
9
+ end
10
+
11
+ it "should be able to add a unit and fetch it at that position" do
12
+ unit = RubyWarrior::Units::Base.new
13
+ @floor.add(unit, 0, 1, :north)
14
+ @floor.get(0, 1).should == unit
15
+ end
16
+
17
+ it "should not consider unit on floor if no position" do
18
+ unit = RubyWarrior::Units::Base.new
19
+ @floor.add(unit, 0, 1, :north)
20
+ unit.position = nil
21
+ @floor.units.should_not include(unit)
22
+ end
23
+
24
+ it "should fetch other units not warrior" do
25
+ unit = RubyWarrior::Units::Base.new
26
+ warrior = RubyWarrior::Units::Warrior.new
27
+ @floor.add(unit, 0, 0, :north)
28
+ @floor.add(warrior, 1, 0, :north)
29
+ @floor.other_units.should_not include(warrior)
30
+ @floor.other_units.should include(unit)
31
+ end
32
+
33
+ it "should not consider corners out of bounds" do
34
+ @floor.should_not be_out_of_bounds(0, 0)
35
+ @floor.should_not be_out_of_bounds(1, 0)
36
+ @floor.should_not be_out_of_bounds(1, 2)
37
+ @floor.should_not be_out_of_bounds(0, 2)
38
+ end
39
+
40
+ it "should consider out of bounds when going beyond sides" do
41
+ @floor.should be_out_of_bounds(-1, 0)
42
+ @floor.should be_out_of_bounds(0, -1)
43
+ @floor.should be_out_of_bounds(0, 3)
44
+ @floor.should be_out_of_bounds(2, 0)
45
+ end
46
+
47
+ it "should return space at the specified location" do
48
+ @floor.space(0, 0).should be_kind_of(RubyWarrior::Space)
49
+ end
50
+
51
+ it "should place stairs and be able to fetch the location" do
52
+ @floor.place_stairs(1, 2)
53
+ @floor.stairs_location.should == [1, 2]
54
+ end
55
+ end
56
+
57
+ describe "3x1" do
58
+ before(:each) do
59
+ @floor = RubyWarrior::Floor.new
60
+ @floor.width = 3
61
+ @floor.height = 1
62
+ end
63
+
64
+ it "should print map with stairs and unit" do
65
+ @floor.add(RubyWarrior::Units::Warrior.new, 0, 0)
66
+ @floor.place_stairs(2, 0)
67
+ @floor.to_map.should == <<-MAP
68
+ ---
69
+ |@ >|
70
+ ---
71
+ MAP
72
+ end
73
+
74
+ it "should return unique units" do
75
+ u1 = RubyWarrior::Units::Base.new
76
+ @floor.add(u1, 0, 0)
77
+ @floor.add(RubyWarrior::Units::Base.new, 1, 0)
78
+ @floor.unique_units.should == [u1]
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,96 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe RubyWarrior::Game do
4
+ before(:each) do
5
+ @game = RubyWarrior::Game.new
6
+ end
7
+
8
+ # GAME DIR
9
+
10
+ it "should make game directory if player says so" do
11
+ RubyWarrior::UI.stubs(:ask).returns(true)
12
+ Dir.expects(:mkdir).with('./ruby-warrior')
13
+ @game.make_game_directory
14
+ end
15
+
16
+ it "should not make game and exit if player says no" do
17
+ RubyWarrior::UI.stubs(:ask).returns(false)
18
+ Dir.stubs(:mkdir).raises('should not be called')
19
+ lambda { @game.make_game_directory }.should raise_error(SystemExit)
20
+ end
21
+
22
+
23
+ # PROFILES
24
+
25
+ it "should load profiles for each profile path" do
26
+ RubyWarrior::Profile.expects(:load).with('foo/.profile').returns(1)
27
+ RubyWarrior::Profile.expects(:load).with('bar/.profile').returns(2)
28
+ @game.stubs(:profile_paths).returns(['foo/.profile', 'bar/.profile'])
29
+ @game.profiles.should == [1, 2]
30
+ end
31
+
32
+ it "should find profile paths using Dir[] search" do
33
+ Dir.expects(:[]).with("./ruby-warrior/**/.profile")
34
+ @game.profile_paths
35
+ end
36
+
37
+ it "should try to create profile when no profile paths are specified" do
38
+ @game.stubs(:profiles).returns([])
39
+ @game.expects(:new_profile).returns('profile')
40
+ @game.profile.should == 'profile'
41
+ end
42
+
43
+ it "should ask a player to choose a profile if multiple profiles are available, but only once" do
44
+ RubyWarrior::UI.expects(:choose).with('profile', [:profile1, [:new, 'New Profile']]).returns(:profile1)
45
+ @game.stubs(:profiles).returns([:profile1])
46
+ 2.times { @game.profile.should == :profile1 }
47
+ end
48
+
49
+ it "should ask user to choose a tower when creating a new profile" do
50
+ RubyWarrior::UI.stubs(:gets).returns('')
51
+ @game.stubs(:towers).returns([:tower1, :tower2])
52
+ RubyWarrior::UI.expects(:choose).with('tower', [:tower1, :tower2]).returns(stub(:path => '/foo/bar'))
53
+ @game.new_profile
54
+ end
55
+
56
+ it "should pass name and selected tower to profile" do
57
+ profile = stub
58
+ RubyWarrior::UI.stubs(:choose).returns(stub(:path => 'tower_path'))
59
+ RubyWarrior::UI.stubs(:request).returns('name')
60
+ RubyWarrior::Profile.expects(:new).returns(profile)
61
+ profile.expects(:tower_path=).with('tower_path')
62
+ profile.expects(:warrior_name=).with('name')
63
+ @game.new_profile.should == profile
64
+ end
65
+
66
+
67
+ # TOWERS
68
+
69
+ it "load towers for each tower path" do
70
+ RubyWarrior::Tower.expects(:new).with('towers/foo').returns(1)
71
+ RubyWarrior::Tower.expects(:new).with('towers/bar').returns(2)
72
+ @game.stubs(:tower_paths).returns(['towers/foo', 'towers/bar'])
73
+ @game.towers.should == [1, 2]
74
+ end
75
+
76
+ it "should find tower paths using Dir[] search" do
77
+ Dir.expects(:[]).with(File.expand_path(File.dirname(__FILE__) + '/../../towers/*'))
78
+ @game.tower_paths
79
+ end
80
+
81
+
82
+ # LEVEL
83
+
84
+ it "should fetch current level from profile and cache it" do
85
+ @game.stubs(:profile).returns(stub)
86
+ @game.profile.expects(:current_level).returns('foo')
87
+ 2.times { @game.current_level.should == 'foo' }
88
+ end
89
+
90
+ it "should fetch next level from profile and cache it" do
91
+ @game.stubs(:profile).returns(stub)
92
+ @game.profile.expects(:next_level).returns('bar')
93
+ 2.times { @game.next_level.should == 'bar' }
94
+ end
95
+
96
+ end
@@ -0,0 +1,54 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe RubyWarrior::LevelLoader do
4
+ describe "with profile" do
5
+ before(:each) do
6
+ @profile = RubyWarrior::Profile.new
7
+ @level = RubyWarrior::Level.new(@profile, 1)
8
+ @loader = RubyWarrior::LevelLoader.new(@level)
9
+ end
10
+
11
+ it "should be able to add description, tip and clue" do
12
+ @loader.description "foo"
13
+ @loader.tip "bar"
14
+ @loader.clue "clue"
15
+ @level.description.should == "foo"
16
+ @level.tip.should == "bar"
17
+ @level.clue.should == "clue"
18
+ end
19
+
20
+ it "should be able to set size" do
21
+ @loader.size 5, 3
22
+ @level.floor.width.should == 5
23
+ @level.floor.height.should == 3
24
+ end
25
+
26
+ it "should be able to add stairs" do
27
+ @level.floor.expects(:place_stairs).with(1, 2)
28
+ @loader.stairs 1, 2
29
+ end
30
+
31
+ it "should yield new unit when building" do
32
+ @loader.unit :base, 1, 2 do |unit|
33
+ unit.should be_kind_of(RubyWarrior::Units::Base)
34
+ unit.position.should be_at(1, 2)
35
+ end
36
+ end
37
+
38
+ it "should be able to add multi-word units" do
39
+ lambda { @loader.unit :thick_sludge, 1, 2 }.should_not raise_error
40
+ end
41
+
42
+ it "should build warrior from profile" do
43
+ @loader.warrior 1, 2 do |unit|
44
+ unit.should be_kind_of(RubyWarrior::Units::Warrior)
45
+ unit.position.should be_at(1, 2)
46
+ end
47
+ end
48
+
49
+ it "should be able to set time bonus" do
50
+ @loader.time_bonus 100
51
+ @level.time_bonus.should == 100
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,163 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require 'set'
3
+
4
+ describe RubyWarrior::Level do
5
+ before(:each) do
6
+ @profile = RubyWarrior::Profile.new
7
+ @floor = RubyWarrior::Floor.new
8
+ @level = RubyWarrior::Level.new(@profile, 1)
9
+ @level.floor = @floor
10
+ @level.stubs(:failed?).returns(false)
11
+ end
12
+
13
+ it "should consider passed when warrior is on stairs" do
14
+ @level.warrior = RubyWarrior::Units::Warrior.new
15
+ @floor.add(@level.warrior, 0, 0, :north)
16
+ @floor.place_stairs(0, 0)
17
+ @level.should be_passed
18
+ end
19
+
20
+ it "should default time bonus to zero" do
21
+ @level.time_bonus.should be_zero
22
+ end
23
+
24
+ it "should load file contents into level" do
25
+ @level.stubs(:load_path).returns('path/to/level.rb')
26
+ File.expects(:read).with('path/to/level.rb').returns("description 'foo'")
27
+ @level.load_level
28
+ @level.description.should == 'foo'
29
+ end
30
+
31
+ it "should have a player path from profile" do
32
+ @profile.stubs(:player_path).returns('path/to/player')
33
+ @level.player_path.should == 'path/to/player'
34
+ end
35
+
36
+ it "should have a load path from profile tower with level number in it" do
37
+ @profile.stubs(:tower_path).returns('path/to/tower')
38
+ @level.load_path.should == 'path/to/tower/level_001.rb'
39
+ end
40
+
41
+ it "should exist if file exists" do
42
+ @level.stubs(:load_path).returns('/foo/bar')
43
+ File.expects(:exist?).with('/foo/bar').returns(true)
44
+ @level.exists?.should be_true
45
+ end
46
+
47
+ it "should load player and player path" do
48
+ @level.stubs(:player_path).returns('player/path')
49
+ $:.expects(:<<).with('player/path')
50
+ @level.expects(:load).with('player.rb')
51
+ @level.load_player
52
+ end
53
+
54
+ it "should generate player files" do
55
+ @level.expects(:load_level)
56
+ generator = stub
57
+ generator.expects(:generate)
58
+ RubyWarrior::PlayerGenerator.expects(:new).with(@level).returns(generator)
59
+ @level.generate_player_files
60
+ end
61
+
62
+ it "should setup warrior with profile abilities" do
63
+ @profile.abilities = [:foo, :bar]
64
+ warrior = stub_everything
65
+ warrior.expects(:add_abilities).with(:foo, :bar)
66
+ @level.setup_warrior(warrior)
67
+ end
68
+
69
+ it "should setup warrior with profile name" do
70
+ @profile.warrior_name = "Joe"
71
+ warrior = stub_everything
72
+ warrior.expects(:name=).with("Joe")
73
+ @level.setup_warrior(warrior)
74
+ end
75
+
76
+ describe "playing" do
77
+ before(:each) do
78
+ @level.stubs(:load_level)
79
+ end
80
+
81
+ it "should load level once when playing multiple turns" do
82
+ @level.expects(:load_level)
83
+ @level.play(2)
84
+ end
85
+
86
+ it "should call prepare_turn and play_turn on each object specified number of times" do
87
+ object = RubyWarrior::Units::Base.new
88
+ object.expects(:prepare_turn).times(2)
89
+ object.expects(:perform_turn).times(2)
90
+ @floor.add(object, 0, 0, :north)
91
+ @level.play(2)
92
+ end
93
+
94
+ it "should return immediately when passed" do
95
+ object = RubyWarrior::Units::Base.new
96
+ object.expects(:turn).times(0)
97
+ @floor.add(object, 0, 0, :north)
98
+ @level.stubs(:passed?).returns(true)
99
+ @level.play(2)
100
+ end
101
+
102
+ it "should yield to block in play method for each turn" do
103
+ int = 0
104
+ @level.play(2) do
105
+ int += 1
106
+ end
107
+ int.should == 2
108
+ end
109
+
110
+ it "should count down time_bonus once each turn" do
111
+ @level.time_bonus = 10
112
+ @level.play(3)
113
+ @level.time_bonus.should == 7
114
+ end
115
+
116
+ it "should count down time_bonus below 0" do
117
+ @level.time_bonus = 2
118
+ @level.play(5)
119
+ @level.time_bonus.should be_zero
120
+ end
121
+ end
122
+
123
+ describe "tallying points" do
124
+ before(:each) do
125
+ @warrior = stub(:score => 0, :abilities => {})
126
+ @level.stubs(:warrior).returns(@warrior)
127
+ @level.floor.stubs(:other_units).returns([stub])
128
+ end
129
+
130
+ it "should add warrior score to profile" do
131
+ @warrior.stubs(:score).returns(30)
132
+ @level.tally_points
133
+ @profile.score.should == 30
134
+ end
135
+
136
+ it "should add warrior score to profile for epic mode" do
137
+ @profile.enable_epic_mode
138
+ @warrior.stubs(:score).returns(30)
139
+ @level.tally_points
140
+ @profile.current_epic_score.should == 30
141
+ end
142
+
143
+ it "should apply warrior abilities to profile" do
144
+ @warrior.stubs(:abilities).returns({:foo => nil, :bar => nil})
145
+ @level.tally_points
146
+ @profile.abilities.to_set.should == [:foo, :bar].to_set
147
+ end
148
+
149
+ it "should apply time bonus to profile score" do
150
+ @level.time_bonus = 20
151
+ @level.tally_points
152
+ @profile.score.should == 20
153
+ end
154
+
155
+ it "should give 20% bonus when no other units left" do
156
+ @level.floor.stubs(:other_units).returns([])
157
+ @warrior.stubs(:score).returns(10)
158
+ @level.time_bonus = 10
159
+ @level.tally_points
160
+ @profile.score.should == 24
161
+ end
162
+ end
163
+ end