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,63 @@
1
+ module RubyWarrior
2
+ class Space
3
+ def initialize(floor, x, y)
4
+ @floor, @x, @y = floor, x, y
5
+ end
6
+
7
+ def wall?
8
+ @floor.out_of_bounds? @x, @y
9
+ end
10
+
11
+ def warrior?
12
+ unit.kind_of? Units::Warrior
13
+ end
14
+
15
+ def enemy?
16
+ unit && !warrior? && !captive?
17
+ end
18
+
19
+ def captive?
20
+ unit && unit.bound?
21
+ end
22
+
23
+ def empty?
24
+ unit.nil? && !wall?
25
+ end
26
+
27
+ def stairs?
28
+ @floor.stairs_location == location
29
+ end
30
+
31
+ def ticking?
32
+ unit.respond_to?(:bomb_time) && unit.bomb_time
33
+ end
34
+
35
+ def unit
36
+ @floor.get(@x, @y)
37
+ end
38
+
39
+ def location
40
+ [@x, @y]
41
+ end
42
+
43
+ def to_map
44
+ if unit
45
+ unit.to_map
46
+ elsif stairs?
47
+ ">"
48
+ else
49
+ " "
50
+ end
51
+ end
52
+
53
+ def to_s
54
+ if unit
55
+ unit.to_s
56
+ elsif wall?
57
+ 'wall'
58
+ else
59
+ 'nothing'
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,14 @@
1
+ module RubyWarrior
2
+ class Tower
3
+ attr_reader :path
4
+
5
+ def initialize(path)
6
+ @path = path
7
+ end
8
+
9
+ def name
10
+ File.basename(path)
11
+ end
12
+ alias_method :to_s, :name
13
+ end
14
+ end
@@ -0,0 +1,38 @@
1
+ module RubyWarrior
2
+ class Turn
3
+ attr_reader :action
4
+
5
+ def initialize(abilities)
6
+ @action = nil
7
+ @senses = {}
8
+
9
+ abilities.each do |name, sense|
10
+ if name.to_s =~ /\!$/
11
+ add_action(name)
12
+ else
13
+ add_sense(name, sense)
14
+ end
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def add_action(action)
21
+ instance_eval <<-EOS
22
+ def #{action}(*args)
23
+ raise "Only one action can be performed per turn." if @action
24
+ @action = [:#{action}, *args]
25
+ end
26
+ EOS
27
+ end
28
+
29
+ def add_sense(name, sense)
30
+ instance_eval <<-EOS
31
+ def #{name}(*args)
32
+ @senses[:#{name}].perform(*args)
33
+ end
34
+ EOS
35
+ @senses[name] = sense
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,64 @@
1
+ module RubyWarrior
2
+ class UI
3
+ class << self
4
+ attr_accessor :delay
5
+
6
+ def in_stream=(in_stream)
7
+ @in = in_stream
8
+ end
9
+
10
+ def out_stream=(stream)
11
+ @out = stream
12
+ end
13
+
14
+ def puts(msg)
15
+ @out.puts(msg) if @out
16
+ end
17
+
18
+ def puts_with_delay(msg)
19
+ result = puts(msg)
20
+ sleep(@delay) if @delay
21
+ result
22
+ end
23
+
24
+ def print(msg)
25
+ @out.print(msg) if @out
26
+ end
27
+
28
+ def gets
29
+ @in ? @in.gets : ''
30
+ end
31
+
32
+ def request(msg)
33
+ print(msg)
34
+ gets.chomp
35
+ end
36
+
37
+ def ask(msg)
38
+ request("#{msg} [yn] ") == 'y'
39
+ end
40
+
41
+ # REFACTORME
42
+ def choose(item, options)
43
+ if options.length == 1
44
+ response = options.first
45
+ else
46
+ options.each_with_index do |option, i|
47
+ if option.kind_of? Array
48
+ puts "[#{i+1}] #{option.last}"
49
+ else
50
+ puts "[#{i+1}] #{option}"
51
+ end
52
+ end
53
+ choice = request("Choose #{item} by typing the number: ")
54
+ response = options[choice.to_i-1]
55
+ end
56
+ if response.kind_of? Array
57
+ response.first
58
+ else
59
+ response
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,34 @@
1
+ module RubyWarrior
2
+ module Units
3
+ class Archer < 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
+ 3
23
+ end
24
+
25
+ def max_health
26
+ 7
27
+ end
28
+
29
+ def to_map
30
+ "a"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -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 to_map
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 to_map
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 to_map
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 to_map
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 to_map
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