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.
- data/CHANGELOG.rdoc +3 -0
- data/LICENSE +20 -0
- data/README.rdoc +170 -0
- data/Rakefile +21 -0
- data/bin/rubywarrior +5 -0
- data/features/command_options.feature +46 -0
- data/features/levels.feature +51 -0
- data/features/profiles.feature +56 -0
- data/features/step_definitions/common_steps.rb +19 -0
- data/features/step_definitions/interaction_steps.rb +65 -0
- data/features/support/env.rb +12 -0
- data/features/support/mockio.rb +57 -0
- data/features/towers.feature +14 -0
- data/lib/ruby_warrior.rb +44 -0
- data/lib/ruby_warrior/abilities/attack.rb +24 -0
- data/lib/ruby_warrior/abilities/base.rb +36 -0
- data/lib/ruby_warrior/abilities/bind.rb +19 -0
- data/lib/ruby_warrior/abilities/direction_of.rb +13 -0
- data/lib/ruby_warrior/abilities/direction_of_stairs.rb +13 -0
- data/lib/ruby_warrior/abilities/distance.rb +13 -0
- data/lib/ruby_warrior/abilities/explode.rb +16 -0
- data/lib/ruby_warrior/abilities/feel.rb +13 -0
- data/lib/ruby_warrior/abilities/health.rb +13 -0
- data/lib/ruby_warrior/abilities/listen.rb +15 -0
- data/lib/ruby_warrior/abilities/look.rb +15 -0
- data/lib/ruby_warrior/abilities/pivot.rb +16 -0
- data/lib/ruby_warrior/abilities/rescue.rb +23 -0
- data/lib/ruby_warrior/abilities/rest.rb +20 -0
- data/lib/ruby_warrior/abilities/shoot.rb +23 -0
- data/lib/ruby_warrior/abilities/walk.rb +20 -0
- data/lib/ruby_warrior/config.rb +22 -0
- data/lib/ruby_warrior/core_additions.rb +25 -0
- data/lib/ruby_warrior/floor.rb +71 -0
- data/lib/ruby_warrior/game.rb +193 -0
- data/lib/ruby_warrior/level.rb +119 -0
- data/lib/ruby_warrior/level_loader.rb +56 -0
- data/lib/ruby_warrior/player_generator.rb +41 -0
- data/lib/ruby_warrior/position.rb +80 -0
- data/lib/ruby_warrior/profile.rb +104 -0
- data/lib/ruby_warrior/runner.rb +33 -0
- data/lib/ruby_warrior/space.rb +63 -0
- data/lib/ruby_warrior/tower.rb +14 -0
- data/lib/ruby_warrior/turn.rb +38 -0
- data/lib/ruby_warrior/ui.rb +54 -0
- data/lib/ruby_warrior/units/archer.rb +34 -0
- data/lib/ruby_warrior/units/base.rb +95 -0
- data/lib/ruby_warrior/units/captive.rb +30 -0
- data/lib/ruby_warrior/units/sludge.rb +30 -0
- data/lib/ruby_warrior/units/thick_sludge.rb +13 -0
- data/lib/ruby_warrior/units/warrior.rb +58 -0
- data/lib/ruby_warrior/units/wizard.rb +34 -0
- data/spec/fixtures/short-tower/level_001.rb +15 -0
- data/spec/fixtures/short-tower/level_002.rb +15 -0
- data/spec/fixtures/walking_player.rb +5 -0
- data/spec/ruby_warrior/abilities/attack_spec.rb +51 -0
- data/spec/ruby_warrior/abilities/base_spec.rb +24 -0
- data/spec/ruby_warrior/abilities/bind_spec.rb +19 -0
- data/spec/ruby_warrior/abilities/direction_of_spec.rb +13 -0
- data/spec/ruby_warrior/abilities/direction_of_stairs_spec.rb +13 -0
- data/spec/ruby_warrior/abilities/distance_spec.rb +13 -0
- data/spec/ruby_warrior/abilities/explode_spec.rb +21 -0
- data/spec/ruby_warrior/abilities/feel_spec.rb +13 -0
- data/spec/ruby_warrior/abilities/health_spec.rb +13 -0
- data/spec/ruby_warrior/abilities/listen_spec.rb +17 -0
- data/spec/ruby_warrior/abilities/look_spec.rb +15 -0
- data/spec/ruby_warrior/abilities/pivot_spec.rb +18 -0
- data/spec/ruby_warrior/abilities/rescue_spec.rb +40 -0
- data/spec/ruby_warrior/abilities/rest_spec.rb +29 -0
- data/spec/ruby_warrior/abilities/shoot_spec.rb +22 -0
- data/spec/ruby_warrior/abilities/walk_spec.rb +25 -0
- data/spec/ruby_warrior/floor_spec.rb +81 -0
- data/spec/ruby_warrior/game_spec.rb +119 -0
- data/spec/ruby_warrior/level_loader_spec.rb +54 -0
- data/spec/ruby_warrior/level_spec.rb +203 -0
- data/spec/ruby_warrior/player_generator_spec.rb +12 -0
- data/spec/ruby_warrior/position_spec.rb +103 -0
- data/spec/ruby_warrior/profile_spec.rb +144 -0
- data/spec/ruby_warrior/space_spec.rb +165 -0
- data/spec/ruby_warrior/tower_spec.rb +15 -0
- data/spec/ruby_warrior/turn_spec.rb +42 -0
- data/spec/ruby_warrior/ui_spec.rb +93 -0
- data/spec/ruby_warrior/units/archer_spec.rb +23 -0
- data/spec/ruby_warrior/units/base_spec.rb +133 -0
- data/spec/ruby_warrior/units/captive_spec.rb +34 -0
- data/spec/ruby_warrior/units/sludge_spec.rb +27 -0
- data/spec/ruby_warrior/units/thick_sludge_spec.rb +19 -0
- data/spec/ruby_warrior/units/warrior_spec.rb +60 -0
- data/spec/ruby_warrior/units/wizard_spec.rb +23 -0
- data/spec/spec_helper.rb +10 -0
- data/templates/README.erb +20 -0
- data/templates/player.rb +5 -0
- data/towers/beginner/level_001.rb +16 -0
- data/towers/beginner/level_002.rb +18 -0
- data/towers/beginner/level_003.rb +21 -0
- data/towers/beginner/level_004.rb +18 -0
- data/towers/beginner/level_005.rb +22 -0
- data/towers/beginner/level_006.rb +19 -0
- data/towers/beginner/level_007.rb +18 -0
- data/towers/beginner/level_008.rb +21 -0
- data/towers/beginner/level_009.rb +20 -0
- data/towers/intermediate/level_001.rb +18 -0
- data/towers/intermediate/level_002.rb +20 -0
- data/towers/intermediate/level_003.rb +23 -0
- data/towers/intermediate/level_004.rb +24 -0
- data/towers/intermediate/level_005.rb +19 -0
- data/towers/intermediate/level_006.rb +24 -0
- metadata +167 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
require 'erb'
|
|
4
|
+
|
|
5
|
+
module RubyWarrior
|
|
6
|
+
class PlayerGenerator
|
|
7
|
+
def initialize(level)
|
|
8
|
+
@level = level
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def level
|
|
12
|
+
@level
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def previous_level
|
|
16
|
+
@previous_level ||= Level.new(level.profile, level.number-1)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# TODO refactor and test this method
|
|
20
|
+
def generate
|
|
21
|
+
if level.number == 1
|
|
22
|
+
FileUtils.mkdir_p(level.player_path)
|
|
23
|
+
FileUtils.cp(templates_path + '/player.rb', level.player_path)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
File.open(level.player_path + '/README', 'w') do |f|
|
|
27
|
+
f.write read_template(templates_path + '/README.erb')
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def templates_path
|
|
32
|
+
File.expand_path(File.dirname(__FILE__) + "/../../templates")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def read_template(path)
|
|
38
|
+
ERB.new(File.read(path), nil, '-').result(binding)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
module RubyWarrior
|
|
2
|
+
class Position
|
|
3
|
+
attr_reader :floor
|
|
4
|
+
DIRECTIONS = [:north, :east, :south, :west]
|
|
5
|
+
RELATIVE_DIRECTIONS = [:forward, :right, :backward, :left]
|
|
6
|
+
|
|
7
|
+
def initialize(floor, x, y, direction = nil)
|
|
8
|
+
@floor = floor
|
|
9
|
+
@x = x
|
|
10
|
+
@y = y
|
|
11
|
+
@direction_index = DIRECTIONS.index(direction || :north)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def at?(x, y)
|
|
15
|
+
@x == x && @y == y
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def direction
|
|
19
|
+
DIRECTIONS[@direction_index]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def rotate(amount)
|
|
23
|
+
@direction_index += amount
|
|
24
|
+
@direction_index -= 4 while @direction_index > 3
|
|
25
|
+
@direction_index += 4 while @direction_index < 0
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def relative_space(forward, right = 0)
|
|
29
|
+
@floor.space(*translate_offset(forward, right))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def space
|
|
33
|
+
@floor.space(@x, @y)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def move(forward, right = 0)
|
|
37
|
+
@x, @y = *translate_offset(forward, right)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def distance_from_stairs
|
|
41
|
+
stairs_x, stairs_y = *@floor.stairs_location
|
|
42
|
+
(@x - stairs_x).abs + (@y - stairs_y).abs
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def relative_direction_of_stairs
|
|
46
|
+
relative_direction_of(@floor.stairs_space)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def relative_direction_of(space)
|
|
50
|
+
relative_direction(direction_of(space))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def direction_of(space)
|
|
54
|
+
space_x, space_y = *space.location
|
|
55
|
+
if (@x - space_x).abs > (@y - space_y).abs
|
|
56
|
+
space_x > @x ? :east : :west
|
|
57
|
+
else
|
|
58
|
+
space_y > @y ? :south : :north
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def relative_direction(direction)
|
|
63
|
+
offset = DIRECTIONS.index(direction) - @direction_index
|
|
64
|
+
offset -= 4 while offset > 3
|
|
65
|
+
offset += 4 while offset < 0
|
|
66
|
+
RELATIVE_DIRECTIONS[offset]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def translate_offset(forward, right)
|
|
72
|
+
case direction
|
|
73
|
+
when :north then [@x + right, @y - forward]
|
|
74
|
+
when :east then [@x + forward, @y + right]
|
|
75
|
+
when :south then [@x - right, @y + forward]
|
|
76
|
+
when :west then [@x - forward, @y - right]
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
require 'base64'
|
|
2
|
+
|
|
3
|
+
module RubyWarrior
|
|
4
|
+
class Profile
|
|
5
|
+
attr_accessor :score, :epic_score, :current_epic_score, :average_grade, :current_epic_grades, :abilities, :level_number, :tower_path, :warrior_name, :player_path
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@tower_path = nil
|
|
9
|
+
@warrior_name = nil
|
|
10
|
+
@score = 0
|
|
11
|
+
@current_epic_score = 0
|
|
12
|
+
@current_epic_grades = {}
|
|
13
|
+
@epic_score = 0
|
|
14
|
+
@average_grade = nil
|
|
15
|
+
@abilities = []
|
|
16
|
+
@level_number = 0
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def encode
|
|
20
|
+
Base64.encode64(Marshal.dump(self))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def save
|
|
24
|
+
update_epic_score
|
|
25
|
+
@level_number = 0 if epic?
|
|
26
|
+
File.open(player_path + '/.profile', 'w') { |f| f.write(encode) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.decode(str)
|
|
30
|
+
Marshal.load(Base64.decode64(str))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.load(path)
|
|
34
|
+
player = decode(File.read(path))
|
|
35
|
+
player.player_path = File.dirname(path)
|
|
36
|
+
player
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def player_path
|
|
40
|
+
@player_path || Config.path_prefix + "/rubywarrior/#{directory_name}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def directory_name
|
|
44
|
+
[warrior_name.downcase.gsub(/[^a-z0-9]+/, '-'), tower.name].join('-')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def to_s
|
|
48
|
+
if epic?
|
|
49
|
+
[warrior_name, tower.name, "first score #{score}", "epic score #{epic_score_with_grade}"].join(' - ')
|
|
50
|
+
else
|
|
51
|
+
[warrior_name, tower.name, "level #{level_number}", "score #{score}"].join(' - ')
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def epic_score_with_grade
|
|
56
|
+
if average_grade
|
|
57
|
+
"#{epic_score} (#{Level.grade_letter(average_grade)})"
|
|
58
|
+
else
|
|
59
|
+
epic_score
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def tower
|
|
64
|
+
Tower.new(@tower_path)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def current_level
|
|
68
|
+
Level.new(self, level_number)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def next_level
|
|
72
|
+
Level.new(self, level_number+1)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def add_abilities(*abilities)
|
|
76
|
+
@abilities += abilities
|
|
77
|
+
@abilities.uniq!
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def enable_epic_mode
|
|
81
|
+
@epic = true
|
|
82
|
+
@epic_score ||= 0
|
|
83
|
+
@current_epic_score ||= 0
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def epic?
|
|
87
|
+
@epic
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def update_epic_score
|
|
91
|
+
if @current_epic_score > @epic_score
|
|
92
|
+
@epic_score = @current_epic_score
|
|
93
|
+
@average_grade = calculate_average_grade
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def calculate_average_grade
|
|
98
|
+
if @current_epic_grades.size > 0
|
|
99
|
+
sum = @current_epic_grades.values.inject(0) { |sum, value| sum + value }
|
|
100
|
+
sum / @current_epic_grades.size
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'optparse'
|
|
2
|
+
|
|
3
|
+
module RubyWarrior
|
|
4
|
+
class Runner
|
|
5
|
+
def initialize(arguments, stdin, stdout)
|
|
6
|
+
@arguments = arguments
|
|
7
|
+
@stdin = stdin
|
|
8
|
+
@stdout = stdout
|
|
9
|
+
@game = RubyWarrior::Game.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def run
|
|
13
|
+
Config.in_stream = @stdin
|
|
14
|
+
Config.out_stream = @stdout
|
|
15
|
+
Config.delay = 0.8
|
|
16
|
+
parse_options
|
|
17
|
+
@game.start
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def parse_options
|
|
23
|
+
options = OptionParser.new
|
|
24
|
+
options.banner = "Usage: rubywarrior [options]"
|
|
25
|
+
options.on('-d', '--directory DIR', "Run under given directory") { |dir| Config.path_prefix = dir }
|
|
26
|
+
options.on('-l', '--level LEVEL', "Practice level on epic") { |level| Config.practice_level = level.to_i }
|
|
27
|
+
options.on('-s', '--skip', "Skip user input") { Config.skip_input = true }
|
|
28
|
+
options.on('-t', '--time SECONDS', "Delay each turn by seconds") { |seconds| Config.delay = seconds.to_f }
|
|
29
|
+
options.on('-h', '--help', "Show this message") { puts(options); exit }
|
|
30
|
+
options.parse!(@arguments)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -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 character
|
|
44
|
+
if unit
|
|
45
|
+
unit.character
|
|
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,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,54 @@
|
|
|
1
|
+
module RubyWarrior
|
|
2
|
+
class UI
|
|
3
|
+
class << self
|
|
4
|
+
def puts(msg)
|
|
5
|
+
Config.out_stream.puts(msg) if Config.out_stream
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def puts_with_delay(msg)
|
|
9
|
+
result = puts(msg)
|
|
10
|
+
sleep(Config.delay) if Config.delay
|
|
11
|
+
result
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def print(msg)
|
|
15
|
+
Config.out_stream.print(msg) if Config.out_stream
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def gets
|
|
19
|
+
Config.in_stream ? Config.in_stream.gets : ''
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def request(msg)
|
|
23
|
+
print(msg)
|
|
24
|
+
gets.chomp
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def ask(msg)
|
|
28
|
+
request("#{msg} [yn] ") == 'y'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# REFACTORME
|
|
32
|
+
def choose(item, options)
|
|
33
|
+
if options.length == 1
|
|
34
|
+
response = options.first
|
|
35
|
+
else
|
|
36
|
+
options.each_with_index do |option, i|
|
|
37
|
+
if option.kind_of? Array
|
|
38
|
+
puts "[#{i+1}] #{option.last}"
|
|
39
|
+
else
|
|
40
|
+
puts "[#{i+1}] #{option}"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
choice = request("Choose #{item} by typing the number: ")
|
|
44
|
+
response = options[choice.to_i-1]
|
|
45
|
+
end
|
|
46
|
+
if response.kind_of? Array
|
|
47
|
+
response.first
|
|
48
|
+
else
|
|
49
|
+
response
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
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 character
|
|
30
|
+
"a"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|