rubywarrior 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/CHANGELOG.rdoc +13 -0
  2. data/README.rdoc +14 -0
  3. data/lib/ruby_warrior.rb +4 -1
  4. data/lib/ruby_warrior/abilities/attack.rb +4 -3
  5. data/lib/ruby_warrior/abilities/base.rb +21 -13
  6. data/lib/ruby_warrior/abilities/bind.rb +4 -3
  7. data/lib/ruby_warrior/abilities/detonate.rb +34 -0
  8. data/lib/ruby_warrior/abilities/direction_of_stairs.rb +1 -1
  9. data/lib/ruby_warrior/abilities/distance_of.rb +13 -0
  10. data/lib/ruby_warrior/abilities/explode.rb +11 -1
  11. data/lib/ruby_warrior/abilities/feel.rb +1 -0
  12. data/lib/ruby_warrior/abilities/form.rb +25 -0
  13. data/lib/ruby_warrior/abilities/look.rb +2 -1
  14. data/lib/ruby_warrior/abilities/pivot.rb +1 -0
  15. data/lib/ruby_warrior/abilities/rescue.rb +3 -2
  16. data/lib/ruby_warrior/abilities/shoot.rb +2 -1
  17. data/lib/ruby_warrior/abilities/walk.rb +2 -1
  18. data/lib/ruby_warrior/core_additions.rb +4 -0
  19. data/lib/ruby_warrior/game.rb +1 -1
  20. data/lib/ruby_warrior/position.rb +6 -4
  21. data/lib/ruby_warrior/space.rb +10 -2
  22. data/lib/ruby_warrior/units/archer.rb +1 -1
  23. data/lib/ruby_warrior/units/base.rb +8 -3
  24. data/lib/ruby_warrior/units/captive.rb +0 -13
  25. data/lib/ruby_warrior/units/golem.rb +20 -0
  26. data/lib/ruby_warrior/units/sludge.rb +1 -1
  27. data/lib/ruby_warrior/units/warrior.rb +15 -0
  28. data/lib/ruby_warrior/units/wizard.rb +1 -1
  29. data/spec/ruby_warrior/abilities/base_spec.rb +16 -2
  30. data/spec/ruby_warrior/abilities/distance_of_spec.rb +13 -0
  31. data/spec/ruby_warrior/abilities/explode_spec.rb +10 -0
  32. data/spec/ruby_warrior/abilities/form_spec.rb +48 -0
  33. data/spec/ruby_warrior/abilities/throw_spec.rb +46 -0
  34. data/spec/ruby_warrior/core_additions_spec.rb +7 -0
  35. data/spec/ruby_warrior/position_spec.rb +5 -0
  36. data/spec/ruby_warrior/space_spec.rb +27 -2
  37. data/spec/ruby_warrior/units/captive_spec.rb +3 -14
  38. data/spec/ruby_warrior/units/golem_spec.rb +28 -0
  39. data/spec/ruby_warrior/units/warrior_spec.rb +5 -0
  40. data/templates/README.erb +14 -1
  41. data/towers/intermediate/level_006.rb +3 -2
  42. data/towers/intermediate/level_007.rb +3 -2
  43. data/towers/intermediate/level_008.rb +23 -0
  44. data/towers/intermediate/level_009.rb +31 -0
  45. metadata +38 -22
  46. data/lib/ruby_warrior/abilities/distance.rb +0 -13
  47. data/spec/ruby_warrior/abilities/distance_spec.rb +0 -13
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,16 @@
1
+ 0.1.2 (September 23, 2010)
2
+
3
+ * Adding intermediate level 9 with distance_of ability
4
+
5
+ * Adding intermediate level 8 with look and detonate abilities
6
+
7
+ * Raising an exception when performing an ability with a bad direction.
8
+
9
+ * Hard wrapping clue text to 80 characters
10
+
11
+ * Mention direction when ability is performed
12
+
13
+
1
14
  0.1.1 (Jan 3, 2010)
2
15
 
3
16
  * Speeding up play speed a little
data/README.rdoc CHANGED
@@ -136,12 +136,26 @@ Whenever you sense an area, often one or multiple spaces (in an array) will be r
136
136
 
137
137
  space.ticking?
138
138
  Returns true if this space contains a bomb which will explode in time.
139
+
140
+ space.golem?
141
+ Returns true if a golem is occupying this space.
139
142
 
140
143
  You will often call these methods directly after a sense. For example, the "feel" sense returns one space. You can call "captive?" on this to determine if a captive is in front of you.
141
144
 
142
145
  warrior.feel.captive?
143
146
 
144
147
 
148
+ == Golem
149
+
150
+ Along your journey you may discover the ability to create a golem. This is a separate unit which you also control. The turn handling is done through a block. Here is an example.
151
+
152
+ warrior.form! do |golem|
153
+ golem.attack! if golem.feel.enemy?
154
+ end
155
+
156
+ Complex logic can be placed in this block just like in the player turn method. You may want to move the logic into its own class or create multiple classes for different types of golems. You can create multiple golems in a level, but each one will take half of the warrior's health.
157
+
158
+
145
159
  == Epic Mode
146
160
 
147
161
  Once you reach the top of the tower, you will enter epic mode. When running rubywarrior again it will run your current player.rb through all levels in the tower without stopping.
data/lib/ruby_warrior.rb CHANGED
@@ -25,6 +25,7 @@ require 'ruby_warrior/units/archer'
25
25
  require 'ruby_warrior/units/thick_sludge'
26
26
  require 'ruby_warrior/units/captive'
27
27
  require 'ruby_warrior/units/wizard'
28
+ require 'ruby_warrior/units/golem'
28
29
 
29
30
  require 'ruby_warrior/abilities/base'
30
31
  require 'ruby_warrior/abilities/walk'
@@ -36,9 +37,11 @@ require 'ruby_warrior/abilities/look'
36
37
  require 'ruby_warrior/abilities/shoot'
37
38
  require 'ruby_warrior/abilities/rescue'
38
39
  require 'ruby_warrior/abilities/pivot'
39
- require 'ruby_warrior/abilities/distance'
40
+ require 'ruby_warrior/abilities/distance_of'
40
41
  require 'ruby_warrior/abilities/bind'
41
42
  require 'ruby_warrior/abilities/listen'
42
43
  require 'ruby_warrior/abilities/direction_of_stairs'
43
44
  require 'ruby_warrior/abilities/direction_of'
44
45
  require 'ruby_warrior/abilities/explode'
46
+ require 'ruby_warrior/abilities/detonate'
47
+ require 'ruby_warrior/abilities/form'
@@ -2,13 +2,14 @@ module RubyWarrior
2
2
  module Abilities
3
3
  class Attack < Base
4
4
  def description
5
- "Attack the unit in given direction (forward by default)."
5
+ "Attacks a unit in given direction (forward by default)."
6
6
  end
7
7
 
8
8
  def perform(direction = :forward)
9
+ verify_direction(direction)
9
10
  receiver = unit(direction)
10
11
  if receiver
11
- @unit.say "attacks #{receiver}"
12
+ @unit.say "attacks #{direction} and hits #{receiver}"
12
13
  if direction == :backward
13
14
  power = (@unit.attack_power/2.0).ceil
14
15
  else
@@ -16,7 +17,7 @@ module RubyWarrior
16
17
  end
17
18
  damage(receiver, power)
18
19
  else
19
- @unit.say "attacks and hits nothing"
20
+ @unit.say "attacks #{direction} and hits nothing"
20
21
  end
21
22
  end
22
23
  end
@@ -1,27 +1,25 @@
1
1
  module RubyWarrior
2
2
  module Abilities
3
3
  class Base
4
- DIRECTIONS = {
5
- :forward => [1, 0],
6
- :right => [0, 1],
7
- :backward => [-1, 0],
8
- :left => [0, -1]
9
- }
10
-
11
4
  def initialize(unit)
12
5
  @unit = unit
13
6
  end
14
7
 
15
- def offset(direction, amount = 1)
16
- DIRECTIONS[direction].map { |i| i*amount }
8
+ def offset(direction, forward = 1, right = 0)
9
+ case direction
10
+ when :forward then [forward, -right]
11
+ when :backward then [-forward, right]
12
+ when :right then [right, forward]
13
+ when :left then [-right, -forward]
14
+ end
17
15
  end
18
16
 
19
- def space(direction, amount = 1)
20
- @unit.position.relative_space(*offset(direction, amount))
17
+ def space(direction, forward = 1, right = 0)
18
+ @unit.position.relative_space(*offset(direction, forward, right))
21
19
  end
22
20
 
23
- def unit(direction, amount = 1)
24
- space(direction, amount).unit
21
+ def unit(direction, forward = 1, right = 0)
22
+ space(direction, forward, right).unit
25
23
  end
26
24
 
27
25
  def damage(receiver, amount)
@@ -31,6 +29,16 @@ module RubyWarrior
31
29
 
32
30
  def description
33
31
  end
32
+
33
+ def pass_turn
34
+ # callback which is triggered every turn
35
+ end
36
+
37
+ def verify_direction(direction)
38
+ unless Position::RELATIVE_DIRECTIONS.include? direction
39
+ raise "Unknown direction #{direction.inspect}. Should be :forward, :backward, :left or :right."
40
+ end
41
+ end
34
42
  end
35
43
  end
36
44
  end
@@ -2,16 +2,17 @@ module RubyWarrior
2
2
  module Abilities
3
3
  class Bind < Base
4
4
  def description
5
- "Bind unit in given direction to keep him from moving (forward by default)."
5
+ "Binds a unit in given direction to keep him from moving (forward by default)."
6
6
  end
7
7
 
8
8
  def perform(direction = :forward)
9
+ verify_direction(direction)
9
10
  receiver = unit(direction)
10
11
  if receiver
11
- @unit.say "binds #{receiver}"
12
+ @unit.say "binds #{direction} and restricts #{receiver}"
12
13
  receiver.bind
13
14
  else
14
- @unit.say "binds nothing"
15
+ @unit.say "binds #{direction} and restricts nothing"
15
16
  end
16
17
  end
17
18
  end
@@ -0,0 +1,34 @@
1
+ module RubyWarrior
2
+ module Abilities
3
+ class Detonate < Base
4
+ def description
5
+ "Detonate a bomb in a given direction (forward by default) which damages that space and surrounding 4 spaces (including yourself)."
6
+ end
7
+
8
+ def perform(direction = :forward)
9
+ verify_direction(direction)
10
+ if @unit.position
11
+ @unit.say "detonates a bomb #{direction} launching a deadly explosion."
12
+ bomb(direction, 1, 0, 8)
13
+ [[1, 1], [1, -1], [2, 0], [0, 0]].each do |x, y|
14
+ bomb(direction, x, y, 4)
15
+ end
16
+ end
17
+ end
18
+
19
+ def bomb(direction, x, y, damage_amount)
20
+ if @unit.position
21
+ receiver = space(direction, x, y).unit
22
+ if receiver
23
+ if receiver.abilities[:explode!]
24
+ receiver.say "caught in bomb's flames which detonates ticking explosive"
25
+ receiver.abilities[:explode!].perform
26
+ else
27
+ damage(receiver, damage_amount)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -10,4 +10,4 @@ module RubyWarrior
10
10
  end
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -0,0 +1,13 @@
1
+ module RubyWarrior
2
+ module Abilities
3
+ class DistanceOf < Base
4
+ def description
5
+ "Pass a Space as an argument, and it will return an integer representing the distance to that space."
6
+ end
7
+
8
+ def perform(space)
9
+ @unit.position.distance_of(space)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,18 +1,28 @@
1
1
  module RubyWarrior
2
2
  module Abilities
3
3
  class Explode < Base
4
+ attr_accessor :time
5
+
4
6
  def description
5
7
  "Kills you and all surrounding units. You probably don't want to do this intentionally."
6
8
  end
7
9
 
8
10
  def perform
9
11
  if @unit.position
10
- @unit.say "explodes, collapsing the cealing and damanging every unit."
12
+ @unit.say "explodes, collapsing the ceiling and damanging every unit."
11
13
  @unit.position.floor.units.map do |unit|
12
14
  unit.take_damage(100)
13
15
  end
14
16
  end
15
17
  end
18
+
19
+ def pass_turn
20
+ if @time && @unit.position
21
+ @unit.say "is ticking"
22
+ @time -= 1
23
+ perform if @time.zero?
24
+ end
25
+ end
16
26
  end
17
27
  end
18
28
  end
@@ -6,6 +6,7 @@ module RubyWarrior
6
6
  end
7
7
 
8
8
  def perform(direction = :forward)
9
+ verify_direction(direction)
9
10
  space(direction)
10
11
  end
11
12
  end
@@ -0,0 +1,25 @@
1
+ module RubyWarrior
2
+ module Abilities
3
+ class Form < Base
4
+ def description
5
+ "Forms a golem in given direction taking half of invoker's health. The passed block is executed for each golem turn."
6
+ end
7
+
8
+ def perform(direction = :forward, &block)
9
+ verify_direction(direction)
10
+ if space(direction).empty?
11
+ x, y = @unit.position.translate_offset(*offset(direction))
12
+ health = (@unit.health/2.0).floor
13
+ golem = @unit.base_golem
14
+ golem.max_health = health
15
+ golem.turn = block
16
+ @unit.health -= health
17
+ @unit.position.floor.add(golem, x, y, @unit.position.direction)
18
+ @unit.say "forms a golem #{direction} and gives half of his health (#{health})"
19
+ else
20
+ @unit.say "fails to form golem because something is blocking the way."
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -2,10 +2,11 @@ module RubyWarrior
2
2
  module Abilities
3
3
  class Look < Base
4
4
  def description
5
- "Returns an array of Spaces in given direction (forward by default)."
5
+ "Returns an array of up to three Spaces in the given direction (forward by default)."
6
6
  end
7
7
 
8
8
  def perform(direction = :forward)
9
+ verify_direction(direction)
9
10
  [1, 2, 3].map do |amount|
10
11
  space(direction, amount)
11
12
  end
@@ -8,6 +8,7 @@ module RubyWarrior
8
8
  end
9
9
 
10
10
  def perform(direction = :backward)
11
+ verify_direction(direction)
11
12
  @unit.position.rotate(ROTATION_DIRECTIONS.index(direction))
12
13
  @unit.say "pivots #{direction}"
13
14
  end
@@ -6,16 +6,17 @@ module RubyWarrior
6
6
  end
7
7
 
8
8
  def perform(direction = :forward)
9
+ verify_direction(direction)
9
10
  if space(direction).captive?
10
11
  recipient = unit(direction)
11
- @unit.say "unbinds #{recipient}"
12
+ @unit.say "unbinds #{direction} and rescues #{recipient}"
12
13
  recipient.unbind
13
14
  if recipient.kind_of? Units::Captive
14
15
  recipient.position = nil
15
16
  @unit.earn_points(20)
16
17
  end
17
18
  else
18
- @unit.say "rescues nothing"
19
+ @unit.say "unbinds #{direction} and rescues nothing"
19
20
  end
20
21
  end
21
22
  end
@@ -6,9 +6,10 @@ module RubyWarrior
6
6
  end
7
7
 
8
8
  def perform(direction = :forward)
9
+ verify_direction(direction)
9
10
  receiver = multi_unit(direction, 1..3).compact.first
10
11
  if receiver
11
- @unit.say "shoots #{receiver}"
12
+ @unit.say "shoots #{direction} and hits #{receiver}"
12
13
  damage(receiver, @unit.shoot_power)
13
14
  else
14
15
  @unit.say "shoots and hits nothing"
@@ -2,10 +2,11 @@ module RubyWarrior
2
2
  module Abilities
3
3
  class Walk < Base
4
4
  def description
5
- "Move in given direction (forward by default)."
5
+ "Move in the given direction (forward by default)."
6
6
  end
7
7
 
8
8
  def perform(direction = :forward)
9
+ verify_direction(direction)
9
10
  if @unit.position
10
11
  @unit.say "walks #{direction}"
11
12
  if space(direction).empty?
@@ -22,4 +22,8 @@ class String
22
22
  def titleize
23
23
  underscore.humanize.gsub(/\b('?[a-z])/) { $1.capitalize }
24
24
  end
25
+
26
+ def hard_wrap(width = 80)
27
+ gsub(/(.{1,#{width}})(\s+|$)/, "\\1\n").strip
28
+ end
25
29
  end
@@ -87,7 +87,7 @@ module RubyWarrior
87
87
  continue = false
88
88
  UI.puts "Sorry, you failed level #{current_level.number}. Change your script and try again."
89
89
  if !Config.skip_input? && current_level.clue && UI.ask("Would you like to read the additional clues for this level?")
90
- UI.puts current_level.clue
90
+ UI.puts current_level.clue.hard_wrap
91
91
  end
92
92
  end
93
93
  continue
@@ -38,8 +38,12 @@ module RubyWarrior
38
38
  end
39
39
 
40
40
  def distance_from_stairs
41
- stairs_x, stairs_y = *@floor.stairs_location
42
- (@x - stairs_x).abs + (@y - stairs_y).abs
41
+ distance_of(@floor.stairs_space)
42
+ end
43
+
44
+ def distance_of(space)
45
+ x, y = *space.location
46
+ (@x - x).abs + (@y - y).abs
43
47
  end
44
48
 
45
49
  def relative_direction_of_stairs
@@ -66,8 +70,6 @@ module RubyWarrior
66
70
  RELATIVE_DIRECTIONS[offset]
67
71
  end
68
72
 
69
- private
70
-
71
73
  def translate_offset(forward, right)
72
74
  case direction
73
75
  when :north then [@x + right, @y - forward]
@@ -12,8 +12,16 @@ module RubyWarrior
12
12
  unit.kind_of? Units::Warrior
13
13
  end
14
14
 
15
+ def golem?
16
+ unit.kind_of? Units::Golem
17
+ end
18
+
19
+ def player?
20
+ warrior? || golem?
21
+ end
22
+
15
23
  def enemy?
16
- unit && !warrior? && !captive?
24
+ unit && !player? && !captive?
17
25
  end
18
26
 
19
27
  def captive?
@@ -29,7 +37,7 @@ module RubyWarrior
29
37
  end
30
38
 
31
39
  def ticking?
32
- unit.respond_to?(:bomb_time) && unit.bomb_time
40
+ unit && unit.abilities.include?(:explode!)
33
41
  end
34
42
 
35
43
  def unit
@@ -8,7 +8,7 @@ module RubyWarrior
8
8
  def play_turn(turn)
9
9
  [:forward, :left, :right].each do |direction|
10
10
  turn.look(direction).each do |space|
11
- if space.warrior?
11
+ if space.player?
12
12
  turn.shoot!(direction)
13
13
  return
14
14
  elsif !space.empty?
@@ -73,9 +73,14 @@ module RubyWarrior
73
73
  end
74
74
 
75
75
  def perform_turn
76
- if @current_turn.action && @position && !bound?
77
- name, *args = @current_turn.action
78
- abilities[name].perform(*args)
76
+ if @position
77
+ abilities.values.each do |ability|
78
+ ability.pass_turn
79
+ end
80
+ if @current_turn.action && !bound?
81
+ name, *args = @current_turn.action
82
+ abilities[name].perform(*args)
83
+ end
79
84
  end
80
85
  end
81
86
 
@@ -1,10 +1,7 @@
1
1
  module RubyWarrior
2
2
  module Units
3
3
  class Captive < Base
4
- attr_accessor :bomb_time
5
-
6
4
  def initialize
7
- add_abilities :explode!
8
5
  bind
9
6
  end
10
7
 
@@ -15,16 +12,6 @@ module RubyWarrior
15
12
  def character
16
13
  "C"
17
14
  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
15
  end
29
16
  end
30
17
  end
@@ -0,0 +1,20 @@
1
+ module RubyWarrior
2
+ module Units
3
+ class Golem < Base
4
+ attr_writer :turn
5
+ attr_accessor :max_health
6
+
7
+ def play_turn(turn)
8
+ @turn.call(turn) if @turn
9
+ end
10
+
11
+ def attack_power
12
+ 3
13
+ end
14
+
15
+ def character
16
+ "G"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -7,7 +7,7 @@ module RubyWarrior
7
7
 
8
8
  def play_turn(turn)
9
9
  [:forward, :left, :right, :backward].each do |direction|
10
- if turn.feel(direction).warrior?
10
+ if turn.feel(direction).player?
11
11
  turn.attack!(direction)
12
12
  return
13
13
  end
@@ -6,6 +6,7 @@ module RubyWarrior
6
6
 
7
7
  def initialize
8
8
  @score = 0 # TODO make score dynamic
9
+ @golem_abilities = []
9
10
  end
10
11
 
11
12
  def play_turn(turn)
@@ -53,6 +54,20 @@ module RubyWarrior
53
54
  say "does nothing" if @current_turn.action.nil?
54
55
  super
55
56
  end
57
+
58
+ def add_golem_abilities(*abilities)
59
+ @golem_abilities += abilities
60
+ end
61
+
62
+ def has_golem?
63
+ !@golem_abilities.empty?
64
+ end
65
+
66
+ def base_golem
67
+ golem = Golem.new
68
+ golem.add_abilities *@golem_abilities
69
+ golem
70
+ end
56
71
  end
57
72
  end
58
73
  end
@@ -8,7 +8,7 @@ module RubyWarrior
8
8
  def play_turn(turn)
9
9
  [:forward, :left, :right].each do |direction|
10
10
  turn.look(direction).each do |space|
11
- if space.warrior?
11
+ if space.player?
12
12
  turn.shoot!(direction)
13
13
  return
14
14
  elsif !space.empty?
@@ -13,12 +13,26 @@ describe RubyWarrior::Abilities::Base do
13
13
  @ability.offset(:left).should == [0, -1]
14
14
  end
15
15
 
16
+ it "should have offset for relative forward/right amounts" do
17
+ @ability.offset(:forward, 2).should == [2, 0]
18
+ @ability.offset(:forward, 2, 1).should == [2, -1]
19
+ @ability.offset(:right, 2, 1).should == [1, 2]
20
+ @ability.offset(:backward, 2, 1).should == [-2, 1]
21
+ @ability.offset(:left, 2, 1).should == [-1, -2]
22
+ end
23
+
16
24
  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'
25
+ @ability.expects(:space).with(:right, 3, 1).returns(stub(:unit => 'unit'))
26
+ @ability.unit(:right, 3, 1).should == 'unit'
19
27
  end
20
28
 
21
29
  it "should have no description" do
22
30
  @ability.description.should be_nil
23
31
  end
32
+
33
+ it "should raise an exception if direction isn't recognized" do
34
+ lambda {
35
+ @ability.verify_direction(:foo)
36
+ }.should raise_error("Unknown direction :foo. Should be :forward, :backward, :left or :right.")
37
+ end
24
38
  end
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::DistanceOf do
4
+ before(:each) do
5
+ @position = stub
6
+ @distance = RubyWarrior::Abilities::DistanceOf.new(stub(:position => @position, :say => nil))
7
+ end
8
+
9
+ it "should return distance from stairs" do
10
+ @position.stubs(:distance_of).with(:space).returns(5)
11
+ @distance.perform(:space).should == 5
12
+ end
13
+ end
@@ -19,4 +19,14 @@ describe RubyWarrior::Abilities::Explode do
19
19
  @captive.health.should == -90
20
20
  unit.health.should == -80
21
21
  end
22
+
23
+ it "should explode when bomb time reaches zero" do
24
+ @captive.health = 10
25
+ @explode.time = 3
26
+ @explode.pass_turn
27
+ @explode.pass_turn
28
+ @captive.health.should == 10
29
+ @explode.pass_turn
30
+ @captive.health.should == -90
31
+ end
22
32
  end
@@ -0,0 +1,48 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Form 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, :east)
10
+ @form = RubyWarrior::Abilities::Form.new(@warrior)
11
+ end
12
+
13
+ it "should form a golem in front of warrior" do
14
+ @form.perform
15
+ @floor.get(1, 0).should be_kind_of(RubyWarrior::Units::Golem)
16
+ end
17
+
18
+ it "should form a golem in given direction" do
19
+ @form.perform(:right)
20
+ @floor.get(0, 1).should be_kind_of(RubyWarrior::Units::Golem)
21
+ end
22
+
23
+ it "should not form golem if space isn't empty" do
24
+ @floor.add(RubyWarrior::Units::Base.new, 1, 0)
25
+ @form.perform(:forward)
26
+ @form.perform(:left)
27
+ @floor.units.size.should == 2
28
+ end
29
+
30
+ it "should reduce warrior's health by half (rounding down) and give it to the golem" do
31
+ @warrior.health = 19
32
+ @form.perform
33
+ @warrior.health.should == 10
34
+ @floor.get(1, 0).max_health.should == 9
35
+ end
36
+
37
+ it "should add passed block as golem's turn block" do
38
+ @passed = nil
39
+ @form.perform(:forward) { |turn| @passed = turn }
40
+ @floor.get(1, 0).play_turn(:turn)
41
+ @passed.should == :turn
42
+ end
43
+
44
+ it "should start in same direction as warrior" do
45
+ @form.perform(:right)
46
+ @floor.get(0, 1).position.direction.should == :east
47
+ end
48
+ end
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Abilities::Detonate do
4
+ before(:each) do
5
+ @floor = RubyWarrior::Floor.new
6
+ @floor.width = 3
7
+ @floor.height = 3
8
+ @warrior = RubyWarrior::Units::Warrior.new
9
+ @floor.add(@warrior, 0, 0, :south)
10
+ @detonate = RubyWarrior::Abilities::Detonate.new(@warrior)
11
+ end
12
+
13
+ it "should subtract 8 from forward unit and 4 from surrounding units" do
14
+ target_unit = RubyWarrior::Units::Base.new
15
+ target_unit.health = 15
16
+ second_unit = RubyWarrior::Units::Base.new
17
+ second_unit.health = 15
18
+ @floor.add(target_unit, 0, 1)
19
+ @floor.add(second_unit, 1, 1)
20
+ @detonate.perform
21
+ target_unit.health.should == 7
22
+ second_unit.health.should == 11
23
+ end
24
+
25
+ it "should subtract 8 from left unit and 4 from surrounding units" do
26
+ target_unit = RubyWarrior::Units::Base.new
27
+ target_unit.health = 15
28
+ second_unit = RubyWarrior::Units::Base.new
29
+ second_unit.health = 15
30
+ @floor.add(target_unit, 1, 0)
31
+ @floor.add(second_unit, 1, 1)
32
+ @detonate.perform(:left)
33
+ target_unit.health.should == 7
34
+ second_unit.health.should == 11
35
+ end
36
+
37
+ it "should detonate an explosive if any unit has one" do
38
+ captive = RubyWarrior::Units::Captive.new
39
+ captive.health = 1
40
+ captive.add_abilities :explode!
41
+ @floor.add(captive, 1, 1)
42
+ @detonate.perform
43
+ captive.health.should == -99
44
+ @warrior.health.should == -80
45
+ end
46
+ end
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe String do
4
+ it "should wrap text at white space when over a specific character length" do
5
+ "foo bar blah".hard_wrap(10).should == "foo bar\nblah"
6
+ end
7
+ end
@@ -100,4 +100,9 @@ describe RubyWarrior::Position do
100
100
  it "should return a space at the same location as position" do
101
101
  @position.space.location.should == [1, 2]
102
102
  end
103
+
104
+ it "should return distance of given space" do
105
+ @position.distance_of(@floor.space(5, 3)).should == 5
106
+ @position.distance_of(@floor.space(4, 2)).should == 3
107
+ end
103
108
  end
@@ -74,6 +74,10 @@ describe RubyWarrior::Space do
74
74
  @space.should be_warrior
75
75
  end
76
76
 
77
+ it "should be player" do
78
+ @space.should be_warrior
79
+ end
80
+
77
81
  it "should not be enemy" do
78
82
  @space.should_not be_enemy
79
83
  end
@@ -126,7 +130,8 @@ describe RubyWarrior::Space do
126
130
 
127
131
  describe "with captive" do
128
132
  before(:each) do
129
- @floor.add(RubyWarrior::Units::Captive.new, 0, 0)
133
+ @captive = RubyWarrior::Units::Captive.new
134
+ @floor.add(@captive, 0, 0)
130
135
  @space = @floor.space(0, 0)
131
136
  end
132
137
 
@@ -139,7 +144,7 @@ describe RubyWarrior::Space do
139
144
  end
140
145
 
141
146
  it "should be ticking if captive has time bomb" do
142
- @space.unit.bomb_time = 10
147
+ @captive.add_abilities :explode!
143
148
  @space.should be_ticking
144
149
  end
145
150
 
@@ -148,6 +153,26 @@ describe RubyWarrior::Space do
148
153
  end
149
154
  end
150
155
 
156
+ describe "with golem" do
157
+ before(:each) do
158
+ @golem = RubyWarrior::Units::Golem.new
159
+ @floor.add(@golem, 0, 0)
160
+ @space = @floor.space(0, 0)
161
+ end
162
+
163
+ it "should be golem" do
164
+ @space.should be_golem
165
+ end
166
+
167
+ it "should not be enemy" do
168
+ @space.should_not be_enemy
169
+ end
170
+
171
+ it "should be player" do
172
+ @space.should be_player
173
+ end
174
+ end
175
+
151
176
  describe "at stairs" do
152
177
  before(:each) do
153
178
  @floor.place_stairs(0, 0)
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper'
2
2
 
3
- describe RubyWarrior::Units::ThickSludge do
3
+ describe RubyWarrior::Units::Captive do
4
4
  before(:each) do
5
5
  @captive = RubyWarrior::Units::Captive.new
6
6
  end
@@ -17,18 +17,7 @@ describe RubyWarrior::Units::ThickSludge do
17
17
  @captive.should be_bound
18
18
  end
19
19
 
20
- it "should explode when bomb time reaches 0 and unbind itself" do
21
- @captive.bomb_time = 3
22
- @captive.play_turn(stub)
23
- @captive.play_turn(stub)
24
- @captive.should be_bound
25
- turn = stub
26
- turn.expects(:explode!)
27
- @captive.play_turn(turn)
28
- @captive.should_not be_bound
29
- end
30
-
31
- it "should have explode ability" do
32
- @captive.abilities.keys.should include(:explode!)
20
+ it "should not have explode ability by default (this should be added when needed)" do
21
+ @captive.abilities.should_not include(:explode!)
33
22
  end
34
23
  end
@@ -0,0 +1,28 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RubyWarrior::Units::Golem do
4
+ before(:each) do
5
+ @golem = RubyWarrior::Units::Golem.new
6
+ end
7
+
8
+ it "should execute turn proc when playing turn" do
9
+ proc = Object.new
10
+ proc.expects(:call).with(:turn)
11
+ @golem.turn = proc
12
+ @golem.play_turn(:turn)
13
+ end
14
+
15
+ it "should set max health and update current health" do
16
+ @golem.max_health = 10
17
+ @golem.max_health.should == 10
18
+ @golem.health.should == 10
19
+ end
20
+
21
+ it "should have attack power of 3" do
22
+ @golem.attack_power.should == 3
23
+ end
24
+
25
+ it "should appear as G on map" do
26
+ @golem.character.should == "G"
27
+ end
28
+ end
@@ -57,4 +57,9 @@ describe RubyWarrior::Units::Warrior do
57
57
  it "should appear as @ on map" do
58
58
  @warrior.character.should == "@"
59
59
  end
60
+
61
+ it "should be able to add golem abilities which are used on base golem" do
62
+ @warrior.add_golem_abilities :walk!
63
+ @warrior.base_golem.abilities.keys.should == [:walk!]
64
+ end
60
65
  end
data/templates/README.erb CHANGED
@@ -12,9 +12,22 @@ Tip: <%= level.tip %>
12
12
  <%- end -%>
13
13
 
14
14
 
15
- Available Abilities:
15
+ Warrior Abilities:
16
16
  <%- level.warrior.abilities.each do |name, ability| -%>
17
17
 
18
18
  warrior.<%= name %>
19
19
  <%= ability.description %>
20
20
  <%- end -%>
21
+ <%- if level.warrior.has_golem? -%>
22
+
23
+
24
+ Golem Abilities:
25
+ <%- level.warrior.base_golem.abilities.each do |name, ability| -%>
26
+
27
+ golem.<%= name %>
28
+ <%= ability.description %>
29
+ <%- end -%>
30
+ <%- end -%>
31
+
32
+
33
+ When you're done editing player.rb, run the rubywarrior command again.
@@ -5,7 +5,7 @@
5
5
 
6
6
  description "What's that ticking? Some captives have a timed bomb at their feet!"
7
7
  tip "Hurry and rescue captives first that have space.ticking?, they'll soon go!"
8
- clue "Avoid fighting enemies at first. Go around them until you've rescued all of the ticking captives."
8
+ clue "Avoid fighting enemies at first. Use warrior.listen and space.ticking? and quickly rescue those captives."
9
9
 
10
10
  time_bonus 50
11
11
  ace_score 108
@@ -18,5 +18,6 @@ unit :sludge, 1, 0, :west
18
18
  unit :sludge, 3, 1, :west
19
19
  unit :captive, 0, 0, :west
20
20
  unit :captive, 4, 1, :west do |u|
21
- u.bomb_time = 7
21
+ u.add_abilities :explode!
22
+ u.abilities[:explode!].time = 7
22
23
  end
@@ -6,7 +6,7 @@
6
6
 
7
7
  description "Another ticking sound, but some sludge is blocking the way."
8
8
  tip "Quickly kill the sludge and rescue the captive before the bomb goes off. You can't simply go around them."
9
- clue "You'll need to bind the two other sludge first before killing the one blocking the way to the ticking captive."
9
+ clue "Determine the direction of the ticking captive and kill any enemies blocking that path. You may need to bind surrounding enemies first."
10
10
 
11
11
  time_bonus 70
12
12
  ace_score 134
@@ -19,6 +19,7 @@ unit :sludge, 1, 0, :south
19
19
  unit :sludge, 1, 2, :north
20
20
  unit :sludge, 2, 1, :west
21
21
  unit :captive, 4, 1, :west do |u|
22
- u.bomb_time = 10
22
+ u.add_abilities :explode!
23
+ u.abilities[:explode!].time = 10
23
24
  end
24
25
  unit :captive, 2, 0, :west
@@ -0,0 +1,23 @@
1
+ # -------
2
+ # |@ Ss C>|
3
+ # -------
4
+
5
+ description "You discover a satchel of bombs which will help when facing a mob of enemies."
6
+ tip "Detonate a bomb when you see a couple enemies ahead of you (warrior.look). Watch out for your health too."
7
+ clue "Calling warrior.look will return an array of Spaces. If the first two contain enemies, detonate a bomb with warrior.detonate!."
8
+
9
+ time_bonus 30
10
+ size 7, 1
11
+ stairs 6, 0
12
+
13
+ warrior 0, 0, :east do |u|
14
+ u.add_abilities :look
15
+ u.add_abilities :detonate!
16
+ end
17
+
18
+ unit :captive, 5, 0, :west do |u|
19
+ u.add_abilities :explode!
20
+ u.abilities[:explode!].time = 9
21
+ end
22
+ unit :thick_sludge, 2, 0, :west
23
+ unit :sludge, 3, 0, :west
@@ -0,0 +1,31 @@
1
+ # ----
2
+ # |ssC>|
3
+ # |@sss|
4
+ # |ssC |
5
+ # ----
6
+
7
+ description "Never before have you seen a room so full of sludge. Start the fireworks!"
8
+ tip "Be careful not to let the ticking captive get caught in the flames. Use warrior.distance_of to avoid the captives."
9
+ clue "Be sure to bind the surrounding enemies before fighting. Check your health before detonating explosives."
10
+
11
+ time_bonus 70
12
+ size 4, 3
13
+ stairs 3, 0
14
+
15
+ warrior 0, 1, :east do |u|
16
+ u.add_abilities :distance_of
17
+ end
18
+
19
+ unit :captive, 2, 0, :south do |u|
20
+ u.add_abilities :explode!
21
+ u.abilities[:explode!].time = 20
22
+ end
23
+ unit :captive, 2, 2, :north
24
+
25
+ unit :sludge, 0, 0, :south
26
+ unit :sludge, 1, 0, :south
27
+ unit :sludge, 1, 1, :east
28
+ unit :sludge, 2, 1, :east
29
+ unit :sludge, 3, 1, :east
30
+ unit :sludge, 0, 2, :north
31
+ unit :sludge, 1, 2, :north
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubywarrior
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ hash: 31
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 2
10
+ version: 0.1.2
5
11
  platform: ruby
6
12
  authors:
7
13
  - Ryan Bates
@@ -9,7 +15,7 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-01-03 00:00:00 -08:00
18
+ date: 2010-09-23 00:00:00 -07:00
13
19
  default_executable:
14
20
  dependencies: []
15
21
 
@@ -19,19 +25,19 @@ executables:
19
25
  - rubywarrior
20
26
  extensions: []
21
27
 
22
- extra_rdoc_files:
23
- - README.rdoc
24
- - CHANGELOG.rdoc
25
- - LICENSE
28
+ extra_rdoc_files: []
29
+
26
30
  files:
27
31
  - lib/ruby_warrior/abilities/attack.rb
28
32
  - lib/ruby_warrior/abilities/base.rb
29
33
  - lib/ruby_warrior/abilities/bind.rb
34
+ - lib/ruby_warrior/abilities/detonate.rb
30
35
  - lib/ruby_warrior/abilities/direction_of.rb
31
36
  - lib/ruby_warrior/abilities/direction_of_stairs.rb
32
- - lib/ruby_warrior/abilities/distance.rb
37
+ - lib/ruby_warrior/abilities/distance_of.rb
33
38
  - lib/ruby_warrior/abilities/explode.rb
34
39
  - lib/ruby_warrior/abilities/feel.rb
40
+ - lib/ruby_warrior/abilities/form.rb
35
41
  - lib/ruby_warrior/abilities/health.rb
36
42
  - lib/ruby_warrior/abilities/listen.rb
37
43
  - lib/ruby_warrior/abilities/look.rb
@@ -57,6 +63,7 @@ files:
57
63
  - lib/ruby_warrior/units/archer.rb
58
64
  - lib/ruby_warrior/units/base.rb
59
65
  - lib/ruby_warrior/units/captive.rb
66
+ - lib/ruby_warrior/units/golem.rb
60
67
  - lib/ruby_warrior/units/sludge.rb
61
68
  - lib/ruby_warrior/units/thick_sludge.rb
62
69
  - lib/ruby_warrior/units/warrior.rb
@@ -70,9 +77,10 @@ files:
70
77
  - spec/ruby_warrior/abilities/bind_spec.rb
71
78
  - spec/ruby_warrior/abilities/direction_of_spec.rb
72
79
  - spec/ruby_warrior/abilities/direction_of_stairs_spec.rb
73
- - spec/ruby_warrior/abilities/distance_spec.rb
80
+ - spec/ruby_warrior/abilities/distance_of_spec.rb
74
81
  - spec/ruby_warrior/abilities/explode_spec.rb
75
82
  - spec/ruby_warrior/abilities/feel_spec.rb
83
+ - spec/ruby_warrior/abilities/form_spec.rb
76
84
  - spec/ruby_warrior/abilities/health_spec.rb
77
85
  - spec/ruby_warrior/abilities/listen_spec.rb
78
86
  - spec/ruby_warrior/abilities/look_spec.rb
@@ -80,7 +88,9 @@ files:
80
88
  - spec/ruby_warrior/abilities/rescue_spec.rb
81
89
  - spec/ruby_warrior/abilities/rest_spec.rb
82
90
  - spec/ruby_warrior/abilities/shoot_spec.rb
91
+ - spec/ruby_warrior/abilities/throw_spec.rb
83
92
  - spec/ruby_warrior/abilities/walk_spec.rb
93
+ - spec/ruby_warrior/core_additions_spec.rb
84
94
  - spec/ruby_warrior/floor_spec.rb
85
95
  - spec/ruby_warrior/game_spec.rb
86
96
  - spec/ruby_warrior/level_loader_spec.rb
@@ -95,6 +105,7 @@ files:
95
105
  - spec/ruby_warrior/units/archer_spec.rb
96
106
  - spec/ruby_warrior/units/base_spec.rb
97
107
  - spec/ruby_warrior/units/captive_spec.rb
108
+ - spec/ruby_warrior/units/golem_spec.rb
98
109
  - spec/ruby_warrior/units/sludge_spec.rb
99
110
  - spec/ruby_warrior/units/thick_sludge_spec.rb
100
111
  - spec/ruby_warrior/units/warrior_spec.rb
@@ -124,43 +135,48 @@ files:
124
135
  - towers/intermediate/level_005.rb
125
136
  - towers/intermediate/level_006.rb
126
137
  - towers/intermediate/level_007.rb
138
+ - towers/intermediate/level_008.rb
139
+ - towers/intermediate/level_009.rb
127
140
  - templates/player.rb
128
141
  - templates/README.erb
129
142
  - bin/rubywarrior
143
+ - CHANGELOG.rdoc
130
144
  - LICENSE
131
- - README.rdoc
132
145
  - Rakefile
133
- - CHANGELOG.rdoc
146
+ - README.rdoc
134
147
  has_rdoc: true
135
148
  homepage: http://github.com/ryanb/ruby-warrior
136
149
  licenses: []
137
150
 
138
151
  post_install_message:
139
- rdoc_options:
140
- - --line-numbers
141
- - --inline-source
142
- - --title
143
- - RubyWarrior
144
- - --main
145
- - README.rdoc
152
+ rdoc_options: []
153
+
146
154
  require_paths:
147
155
  - lib
148
156
  required_ruby_version: !ruby/object:Gem::Requirement
157
+ none: false
149
158
  requirements:
150
159
  - - ">="
151
160
  - !ruby/object:Gem::Version
161
+ hash: 3
162
+ segments:
163
+ - 0
152
164
  version: "0"
153
- version:
154
165
  required_rubygems_version: !ruby/object:Gem::Requirement
166
+ none: false
155
167
  requirements:
156
168
  - - ">="
157
169
  - !ruby/object:Gem::Version
158
- version: "1.2"
159
- version:
170
+ hash: 19
171
+ segments:
172
+ - 1
173
+ - 3
174
+ - 4
175
+ version: 1.3.4
160
176
  requirements: []
161
177
 
162
- rubyforge_project:
163
- rubygems_version: 1.3.5
178
+ rubyforge_project: rubywarrior
179
+ rubygems_version: 1.3.7
164
180
  signing_key:
165
181
  specification_version: 3
166
182
  summary: Game written in Ruby for learning Ruby and artificial intelligence.
@@ -1,13 +0,0 @@
1
- module RubyWarrior
2
- module Abilities
3
- class Distance < Base
4
- def description
5
- "Returns the number of spaces the stairs are away."
6
- end
7
-
8
- def perform
9
- @unit.position.distance_from_stairs
10
- end
11
- end
12
- end
13
- end
@@ -1,13 +0,0 @@
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