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,22 @@
|
|
|
1
|
+
module RubyWarrior
|
|
2
|
+
class Config
|
|
3
|
+
class << self
|
|
4
|
+
attr_accessor :delay, :in_stream, :out_stream, :practice_level
|
|
5
|
+
attr_writer :path_prefix, :skip_input
|
|
6
|
+
|
|
7
|
+
def path_prefix
|
|
8
|
+
@path_prefix || "."
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def skip_input?
|
|
12
|
+
@skip_input
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def reset
|
|
16
|
+
[:@path_prefix, :@skip_input, :@delay, :@in_stream, :@out_stream, :@practice_level].each do |i|
|
|
17
|
+
remove_instance_variable(i) if instance_variable_defined?(i)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class String
|
|
2
|
+
def camelize
|
|
3
|
+
gsub(/(?:^|_)(.)/) { $1.upcase }
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def constantize
|
|
7
|
+
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self
|
|
8
|
+
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Object.module_eval("::#{$1}", __FILE__, __LINE__)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def underscore
|
|
15
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("-", "_").downcase
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def humanize
|
|
19
|
+
gsub(/_/, " ").capitalize
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def titleize
|
|
23
|
+
underscore.humanize.gsub(/\b('?[a-z])/) { $1.capitalize }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module RubyWarrior
|
|
2
|
+
class Floor
|
|
3
|
+
attr_accessor :width, :height, :grid
|
|
4
|
+
attr_reader :stairs_location
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
@width = 0
|
|
8
|
+
@height = 0
|
|
9
|
+
@units = []
|
|
10
|
+
@stairs_location = [-1, -1]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def add(unit, x, y, direction = nil)
|
|
14
|
+
@units << unit
|
|
15
|
+
unit.position = Position.new(self, x, y, direction)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def place_stairs(x, y)
|
|
19
|
+
@stairs_location = [x, y]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def stairs_space
|
|
23
|
+
space(*@stairs_location)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def units
|
|
27
|
+
@units.reject { |u| u.position.nil? }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def other_units
|
|
31
|
+
units.reject { |u| u.kind_of? Units::Warrior }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def get(x, y)
|
|
35
|
+
units.detect do |unit|
|
|
36
|
+
unit.position.at?(x, y)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def space(x, y)
|
|
41
|
+
Space.new(self, x, y)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def out_of_bounds?(x, y)
|
|
45
|
+
x < 0 || y < 0 || x > @width-1 || y > @height-1
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def character
|
|
49
|
+
rows = []
|
|
50
|
+
rows << " " + ("-" * @width)
|
|
51
|
+
@height.times do |y|
|
|
52
|
+
row = "|"
|
|
53
|
+
@width.times do |x|
|
|
54
|
+
row << space(x, y).character
|
|
55
|
+
end
|
|
56
|
+
row << "|"
|
|
57
|
+
rows << row
|
|
58
|
+
end
|
|
59
|
+
rows << " " + ("-" * @width)
|
|
60
|
+
rows.join("\n") + "\n"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def unique_units
|
|
64
|
+
unique_units = []
|
|
65
|
+
units.each do |unit|
|
|
66
|
+
unique_units << unit unless unique_units.map { |u| u.class }.include?(unit.class)
|
|
67
|
+
end
|
|
68
|
+
unique_units
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
module RubyWarrior
|
|
2
|
+
class Game
|
|
3
|
+
|
|
4
|
+
def start
|
|
5
|
+
UI.puts "Welcome to Ruby Warrior"
|
|
6
|
+
|
|
7
|
+
if File.exist?(Config.path_prefix + '/.profile')
|
|
8
|
+
@profile = Profile.load(Config.path_prefix + '/.profile')
|
|
9
|
+
else
|
|
10
|
+
if File.exist?(Config.path_prefix + '/ruby-warrior')
|
|
11
|
+
FileUtils.mv(Config.path_prefix + '/ruby-warrior', Config.path_prefix + '/rubywarrior')
|
|
12
|
+
end
|
|
13
|
+
make_game_directory unless File.exist?(Config.path_prefix + '/rubywarrior')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
profile.epic? ? play_epic_mode : play_normal_mode
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def make_game_directory
|
|
20
|
+
if UI.ask("No rubywarrior directory found, would you like to create one?")
|
|
21
|
+
Dir.mkdir(Config.path_prefix + '/rubywarrior')
|
|
22
|
+
else
|
|
23
|
+
UI.puts "Unable to continue without directory."
|
|
24
|
+
exit
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def play_epic_mode
|
|
29
|
+
Config.delay /= 2 if Config.delay # speed up UI since we're going to be doing a lot here
|
|
30
|
+
profile.current_epic_score = 0
|
|
31
|
+
profile.current_epic_grades = {}
|
|
32
|
+
if Config.practice_level
|
|
33
|
+
@current_level = @next_level = nil
|
|
34
|
+
profile.level_number = Config.practice_level
|
|
35
|
+
play_current_level
|
|
36
|
+
else
|
|
37
|
+
playing = true
|
|
38
|
+
while playing
|
|
39
|
+
@current_level = @next_level = nil
|
|
40
|
+
profile.level_number += 1
|
|
41
|
+
playing = play_current_level
|
|
42
|
+
end
|
|
43
|
+
profile.save # saves the score for epic mode
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def play_normal_mode
|
|
48
|
+
if Config.practice_level
|
|
49
|
+
UI.puts "Unable to practice level while not in epic mode, remove -l option."
|
|
50
|
+
else
|
|
51
|
+
if current_level.number.zero?
|
|
52
|
+
prepare_next_level
|
|
53
|
+
UI.puts "First level has been generated. See the rubywarrior/#{profile.directory_name}/README for instructions."
|
|
54
|
+
else
|
|
55
|
+
play_current_level
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def play_current_level
|
|
61
|
+
continue = true
|
|
62
|
+
current_level.load_player
|
|
63
|
+
UI.puts "Starting Level #{current_level.number}"
|
|
64
|
+
current_level.play
|
|
65
|
+
if current_level.passed?
|
|
66
|
+
if next_level.exists?
|
|
67
|
+
UI.puts "Success! You have found the stairs."
|
|
68
|
+
else
|
|
69
|
+
UI.puts "CONGRATULATIONS! You have climbed to the top of the tower and rescued the fair maiden Ruby."
|
|
70
|
+
continue = false
|
|
71
|
+
end
|
|
72
|
+
current_level.tally_points
|
|
73
|
+
if profile.epic?
|
|
74
|
+
UI.puts final_report if final_report && !continue
|
|
75
|
+
else
|
|
76
|
+
request_next_level
|
|
77
|
+
end
|
|
78
|
+
else
|
|
79
|
+
continue = false
|
|
80
|
+
UI.puts "Sorry, you failed level #{current_level.number}. Change your script and try again."
|
|
81
|
+
if !Config.skip_input? && current_level.clue && UI.ask("Would you like to read the additional clues for this level?")
|
|
82
|
+
UI.puts current_level.clue
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
continue
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def request_next_level
|
|
89
|
+
if !Config.skip_input? && (next_level.exists? ? UI.ask("Would you like to continue on to the next level?") : UI.ask("Would you like to continue on to epic mode?"))
|
|
90
|
+
if next_level.exists?
|
|
91
|
+
prepare_next_level
|
|
92
|
+
UI.puts "See the updated README in the rubywarrior/#{profile.directory_name} directory."
|
|
93
|
+
else
|
|
94
|
+
prepare_epic_mode
|
|
95
|
+
UI.puts "Run rubywarrior again to play epic mode."
|
|
96
|
+
end
|
|
97
|
+
else
|
|
98
|
+
UI.puts "Staying on current level. Try to earn more points next time."
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def prepare_next_level
|
|
103
|
+
next_level.generate_player_files
|
|
104
|
+
profile.level_number += 1
|
|
105
|
+
profile.save # this saves score and new abilities too
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def prepare_epic_mode
|
|
109
|
+
profile.enable_epic_mode
|
|
110
|
+
profile.level_number = 0
|
|
111
|
+
profile.save # this saves score too
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# profiles
|
|
116
|
+
|
|
117
|
+
def profiles
|
|
118
|
+
profile_paths.map { |profile| Profile.load(profile) }
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def profile_paths
|
|
122
|
+
Dir[Config.path_prefix + '/rubywarrior/**/.profile']
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def profile
|
|
126
|
+
@profile ||= choose_profile
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def new_profile
|
|
130
|
+
profile = Profile.new
|
|
131
|
+
profile.tower_path = UI.choose('tower', towers).path
|
|
132
|
+
profile.warrior_name = UI.request('Enter a name for your warrior: ')
|
|
133
|
+
profile
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
# towers
|
|
138
|
+
|
|
139
|
+
def towers
|
|
140
|
+
tower_paths.map { |path| Tower.new(path) }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def tower_paths
|
|
144
|
+
Dir[File.expand_path(File.dirname(__FILE__) + '/../../towers/*')]
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
# levels
|
|
149
|
+
|
|
150
|
+
def current_level
|
|
151
|
+
@current_level ||= profile.current_level
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def next_level
|
|
155
|
+
@next_level ||= profile.next_level
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def final_report
|
|
159
|
+
if profile.calculate_average_grade && !Config.practice_level
|
|
160
|
+
report = ""
|
|
161
|
+
report << "Your average grade for this tower is: #{Level.grade_letter(profile.calculate_average_grade)}\n\n"
|
|
162
|
+
profile.current_epic_grades.keys.sort.each do |level|
|
|
163
|
+
report << " Level #{level}: #{Level.grade_letter(profile.current_epic_grades[level])}\n"
|
|
164
|
+
end
|
|
165
|
+
report << "\nTo practice a level, use the -l option:\n\n rubywarrior -l 3"
|
|
166
|
+
report
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
private
|
|
171
|
+
|
|
172
|
+
def choose_profile # REFACTORME
|
|
173
|
+
profile = UI.choose('profile', profiles + [[:new, 'New Profile']])
|
|
174
|
+
if profile == :new
|
|
175
|
+
profile = new_profile
|
|
176
|
+
if profiles.any? { |p| p.player_path == profile.player_path }
|
|
177
|
+
if UI.ask("Are you sure you want to replace your existing profile for this tower?")
|
|
178
|
+
UI.puts "Replacing existing profile."
|
|
179
|
+
profile
|
|
180
|
+
else
|
|
181
|
+
UI.puts "Not replacing profile."
|
|
182
|
+
exit
|
|
183
|
+
end
|
|
184
|
+
else
|
|
185
|
+
profile
|
|
186
|
+
end
|
|
187
|
+
else
|
|
188
|
+
profile
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
end
|
|
193
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
module RubyWarrior
|
|
2
|
+
class Level
|
|
3
|
+
attr_reader :profile, :number
|
|
4
|
+
attr_accessor :description, :tip, :clue, :warrior, :floor, :time_bonus, :ace_score
|
|
5
|
+
|
|
6
|
+
def self.grade_letter(percent)
|
|
7
|
+
if percent >= 1.0 then "S"
|
|
8
|
+
elsif percent >= 0.9 then "A"
|
|
9
|
+
elsif percent >= 0.8 then "B"
|
|
10
|
+
elsif percent >= 0.7 then "C"
|
|
11
|
+
elsif percent >= 0.6 then "D"
|
|
12
|
+
else "F"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(profile, number)
|
|
17
|
+
@profile = profile
|
|
18
|
+
@number = number
|
|
19
|
+
@time_bonus = 0
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def player_path
|
|
23
|
+
@profile.player_path
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def load_path
|
|
27
|
+
@profile.tower_path + "/level_" + @number.to_s.rjust(3, '0') + ".rb"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def load_level
|
|
31
|
+
LevelLoader.new(self).instance_eval(File.read(load_path))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def load_player
|
|
35
|
+
$: << player_path
|
|
36
|
+
load 'player.rb'
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def generate_player_files
|
|
40
|
+
load_level
|
|
41
|
+
PlayerGenerator.new(self).generate
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def play(turns = 1000)
|
|
45
|
+
load_level
|
|
46
|
+
turns.times do |n|
|
|
47
|
+
return if passed? || failed?
|
|
48
|
+
UI.puts "- turn #{n+1} -"
|
|
49
|
+
UI.print @floor.character
|
|
50
|
+
@floor.units.each { |unit| unit.prepare_turn }
|
|
51
|
+
@floor.units.each { |unit| unit.perform_turn }
|
|
52
|
+
yield if block_given?
|
|
53
|
+
@time_bonus -= 1 if @time_bonus > 0
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def tally_points
|
|
58
|
+
score = 0
|
|
59
|
+
|
|
60
|
+
UI.puts "Level Score: #{warrior.score}"
|
|
61
|
+
score += warrior.score
|
|
62
|
+
|
|
63
|
+
UI.puts "Time Bonus: #{time_bonus}"
|
|
64
|
+
score += @time_bonus
|
|
65
|
+
|
|
66
|
+
if floor.other_units.empty?
|
|
67
|
+
UI.puts "Clear Bonus: #{clear_bonus}"
|
|
68
|
+
score += clear_bonus
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
if @profile.epic?
|
|
72
|
+
UI.puts "Level Grade: #{grade_for(score)}" if grade_for(score)
|
|
73
|
+
UI.puts "Total Score: " + score_calculation(@profile.current_epic_score, score)
|
|
74
|
+
@profile.current_epic_grades[@number] = (score / ace_score.to_f) if ace_score
|
|
75
|
+
@profile.current_epic_score += score
|
|
76
|
+
else
|
|
77
|
+
UI.puts "Total Score: " + score_calculation(@profile.score, score)
|
|
78
|
+
@profile.score += score
|
|
79
|
+
@profile.abilities = warrior.abilities.keys
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def grade_for(score)
|
|
84
|
+
if ace_score
|
|
85
|
+
self.class.grade_letter(score / ace_score.to_f)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def clear_bonus
|
|
90
|
+
((warrior.score + time_bonus)*0.2).round
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def score_calculation(current_score, addition)
|
|
94
|
+
if current_score.zero?
|
|
95
|
+
addition.to_s
|
|
96
|
+
else
|
|
97
|
+
"#{current_score} + #{addition} = #{current_score + addition}"
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def passed?
|
|
102
|
+
@floor.stairs_space.warrior?
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def failed?
|
|
106
|
+
!@floor.units.include?(warrior)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def exists?
|
|
110
|
+
File.exist? load_path
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def setup_warrior(warrior)
|
|
114
|
+
@warrior = warrior
|
|
115
|
+
@warrior.add_abilities(*profile.abilities)
|
|
116
|
+
@warrior.name = profile.warrior_name
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module RubyWarrior
|
|
2
|
+
class LevelLoader
|
|
3
|
+
def initialize(level)
|
|
4
|
+
@floor = RubyWarrior::Floor.new
|
|
5
|
+
@level = level
|
|
6
|
+
@level.floor = @floor
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def description(desc)
|
|
10
|
+
@level.description = desc
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def tip(tip)
|
|
14
|
+
@level.tip = tip
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def clue(clue)
|
|
18
|
+
@level.clue = clue
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def time_bonus(bonus)
|
|
22
|
+
@level.time_bonus = bonus
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ace_score(score)
|
|
26
|
+
@level.ace_score = score
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def size(width, height)
|
|
30
|
+
@floor.width = width
|
|
31
|
+
@floor.height = height
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def stairs(x, y)
|
|
35
|
+
@floor.place_stairs(x, y)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def unit(unit, x, y, facing = :north)
|
|
39
|
+
unit = unit_to_constant(unit).new unless unit.kind_of? Units::Base
|
|
40
|
+
@floor.add(unit, x, y, facing)
|
|
41
|
+
yield unit if block_given?
|
|
42
|
+
unit
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def warrior(*args, &block)
|
|
46
|
+
@level.setup_warrior unit(Units::Warrior.new, *args, &block)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def unit_to_constant(name)
|
|
52
|
+
camel = name.to_s.split('_').map { |s| s.capitalize }.join
|
|
53
|
+
eval("Units::#{camel}")
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|