gemwarrior 0.15.5 → 0.15.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/gemwarrior.gemspec +2 -2
- data/lib/gemwarrior/repl.rb +610 -591
- data/lib/gemwarrior/version.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6362984240883f372d441158745f67e6363a3fa9915949c31cf2b8ccd77b5cf8
|
4
|
+
data.tar.gz: 5013a38c0ac68063ac551dd1aece3462cf6363049f5b8978575667de83b91d89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 316f08a8b23dfbd90975a39bafcf6ec760ab4a45113ef5948880095a52f5673598be3842ba306efe815601472373d4b5df59a0be9fb8ce51221004917a6ea544
|
7
|
+
data.tar.gz: ec7e62d2dbb18b2d58c489e53d424de3931f0a989c9ab537eda5697830a9448fd9ec090557fe0bbc1cde688c2c2afa8bcd08f76622112462be04f07d02441756
|
data/gemwarrior.gemspec
CHANGED
@@ -22,8 +22,8 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_runtime_dependency 'os', '~> 0.9', '>= 0.9.6'
|
23
23
|
spec.add_runtime_dependency 'http', '~> 0.8.10'
|
24
24
|
spec.add_runtime_dependency 'json', '~> 1.8.2'
|
25
|
-
spec.add_runtime_dependency 'colorize', '~> 0.
|
26
|
-
spec.add_runtime_dependency 'matrext', '~>
|
25
|
+
spec.add_runtime_dependency 'colorize', '~> 0.8'
|
26
|
+
spec.add_runtime_dependency 'matrext', '~> 1'
|
27
27
|
spec.add_runtime_dependency 'clocker', '~> 0.1.6'
|
28
28
|
spec.add_runtime_dependency 'gems', '~> 0.8.3'
|
29
29
|
|
data/lib/gemwarrior/repl.rb
CHANGED
@@ -1,591 +1,610 @@
|
|
1
|
-
# lib/gemwarrior/repl.rb
|
2
|
-
# My own, simple, Read Evaluate Print Loop module
|
3
|
-
|
4
|
-
require 'readline'
|
5
|
-
require 'os'
|
6
|
-
require 'clocker'
|
7
|
-
require 'io/console'
|
8
|
-
require 'gems'
|
9
|
-
|
10
|
-
require_relative 'misc/timer'
|
11
|
-
require_relative 'misc/wordlist'
|
12
|
-
require_relative 'evaluator'
|
13
|
-
require_relative 'game_options'
|
14
|
-
require_relative 'version'
|
15
|
-
|
16
|
-
module Gemwarrior
|
17
|
-
class Repl
|
18
|
-
# CONSTANTS
|
19
|
-
SCREEN_WIDTH_MIN = 80
|
20
|
-
SCREEN_WIDTH_MAX = 120
|
21
|
-
QUIT_MESSAGE = 'Temporal flux detected. Shutting down...'.colorize(:red)
|
22
|
-
MAIN_MENU_QUIT_MESSAGE = 'Giving up so soon? Jool will be waiting...'.colorize(:red)
|
23
|
-
SPLASH_MESSAGE = 'Welcome to *Jool*, where randomized fortune is just as likely as mayhem.'
|
24
|
-
GITHUB_NAME = 'michaelchadwick'
|
25
|
-
GITHUB_PROJECT = 'gemwarrior'
|
26
|
-
|
27
|
-
attr_accessor :game, :world, :evaluator
|
28
|
-
|
29
|
-
def initialize(game, world, evaluator)
|
30
|
-
self.game = game
|
31
|
-
self.world = world
|
32
|
-
self.evaluator = evaluator
|
33
|
-
|
34
|
-
GameOptions.data['wrap_width'] = get_screen_width
|
35
|
-
end
|
36
|
-
|
37
|
-
def get_screen_width
|
38
|
-
screen_width = SCREEN_WIDTH_MIN
|
39
|
-
|
40
|
-
begin
|
41
|
-
require 'io/console'
|
42
|
-
screen_width = IO.console.winsize[1]
|
43
|
-
rescue
|
44
|
-
if command_exists?('tput')
|
45
|
-
screen_width = `tput cols`.to_i
|
46
|
-
elsif command_exists?('stty')
|
47
|
-
screen_width = `stty size`.split.last.to_i
|
48
|
-
elsif command_exists?('mode')
|
49
|
-
mode_output = `mode`.split
|
50
|
-
screen_width = mode_output[mode_output.index('Columns:')+1].to_i
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
case
|
55
|
-
when screen_width.nil?, screen_width <= 0
|
56
|
-
return SCREEN_WIDTH_MIN
|
57
|
-
else
|
58
|
-
return [screen_width, SCREEN_WIDTH_MAX].min
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def start(initial_command, extra_command, new_skip, resume_skip)
|
63
|
-
setup_screen(initial_command, extra_command, new_skip, resume_skip)
|
64
|
-
|
65
|
-
clocker = Clocker.new
|
66
|
-
|
67
|
-
at_exit do
|
68
|
-
update_duration(clocker.stop)
|
69
|
-
game.update_options_file
|
70
|
-
log_stats(world.duration, world.player)
|
71
|
-
save_game(world)
|
72
|
-
end
|
73
|
-
|
74
|
-
clocker.clock do
|
75
|
-
# main loop
|
76
|
-
loop do
|
77
|
-
prompt
|
78
|
-
begin
|
79
|
-
main_loop
|
80
|
-
rescue Interrupt
|
81
|
-
puts
|
82
|
-
puts QUIT_MESSAGE
|
83
|
-
exit
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def main_loop(ext_input = nil)
|
90
|
-
input = ext_input.nil? ? read_line : ext_input
|
91
|
-
result = evaluator.parse(input)
|
92
|
-
if result.eql?('exit')
|
93
|
-
exit
|
94
|
-
elsif result.eql?('checkupdate')
|
95
|
-
check_for_new_release
|
96
|
-
else
|
97
|
-
puts result
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
# timer observer
|
102
|
-
#def update(command)
|
103
|
-
# main_loop(command)
|
104
|
-
#end
|
105
|
-
|
106
|
-
private
|
107
|
-
|
108
|
-
def clear_screen
|
109
|
-
OS.windows? ? system('cls') : system('clear')
|
110
|
-
end
|
111
|
-
|
112
|
-
def read_line
|
113
|
-
prompt_text = GameOptions.data['debug_mode'] ? ' GW[D]> ' : ' GW> '
|
114
|
-
Readline.readline(prompt_text, true).to_s
|
115
|
-
end
|
116
|
-
|
117
|
-
def puts(s = '', width = GameOptions.data['wrap_width'])
|
118
|
-
super s.gsub(/(.{1,#{width}})(\s+|\Z)/, "\\1\n") unless s.nil?
|
119
|
-
end
|
120
|
-
|
121
|
-
def print_logo
|
122
|
-
puts '/-+-+-+ +-+-+-+-+-+-+-\\'.colorize(:yellow)
|
123
|
-
puts '|G|E|M| |W|A|R|R|I|O|R|'.colorize(:yellow)
|
124
|
-
puts '\\-+-+-+ +-+-+-+-+-+-+-/'.colorize(:yellow)
|
125
|
-
puts '[[[[[[[DEBUGGING]]]]]]]'.colorize(:white) if GameOptions.data['debug_mode']
|
126
|
-
end
|
127
|
-
|
128
|
-
def print_splash_message
|
129
|
-
SPLASH_MESSAGE.length.times { print '=' }
|
130
|
-
puts
|
131
|
-
puts SPLASH_MESSAGE
|
132
|
-
SPLASH_MESSAGE.length.times { print '=' }
|
133
|
-
puts
|
134
|
-
end
|
135
|
-
|
136
|
-
def print_fortune
|
137
|
-
noun1_values = WordList.new('noun-plural')
|
138
|
-
noun2_values = WordList.new('noun-plural')
|
139
|
-
noun3_values = WordList.new('noun-plural')
|
140
|
-
|
141
|
-
puts "* Remember: #{noun1_values.get_random_value} and #{noun2_values.get_random_value} are the key to #{noun3_values.get_random_value} *\n\n"
|
142
|
-
puts
|
143
|
-
end
|
144
|
-
|
145
|
-
def print_about_text
|
146
|
-
puts 'Gem Warrior - A Game of Fortune and Mayhem'.colorize(:yellow)
|
147
|
-
puts '=========================================='.colorize(:yellow)
|
148
|
-
puts 'Gem Warrior is a text adventure roguelike-lite as a RubyGem created by Michael Chadwick (mike@
|
149
|
-
puts
|
150
|
-
puts 'Explore the land of Jool with the power of text, fighting enemies to improve your station, grabbing curious items that may or may not come in handy, and finally defeating Mr. Emerald himself to win the game.'
|
151
|
-
end
|
152
|
-
|
153
|
-
def print_help_text
|
154
|
-
puts 'Gem Warrior - Some Basic Help Commands'.colorize(:yellow)
|
155
|
-
puts '======================================'.colorize(:yellow)
|
156
|
-
puts '* Basic functions: look, go, character, inventory, attack *'
|
157
|
-
puts '* Type \'help\' while in-game for complete list of commands *'
|
158
|
-
puts '* Most commands can be abbreviated to their first letter *'
|
159
|
-
puts '* Note: if something isn\'t working, try: *'
|
160
|
-
puts '* 1) starting a new game *'
|
161
|
-
puts '* 2) updating the game *'
|
162
|
-
end
|
163
|
-
|
164
|
-
def display_log_of_attempts
|
165
|
-
if File.exist?(GameOptions.data['log_file_path']) and !File.zero?(GameOptions.data['log_file_path'])
|
166
|
-
File.open(GameOptions.data['log_file_path']).readlines.each do |line|
|
167
|
-
print "#{line}"
|
168
|
-
end
|
169
|
-
if GameOptions.data['debug_mode']
|
170
|
-
print 'Clear log of attempts? (y/n) '
|
171
|
-
answer = gets.chomp.downcase
|
172
|
-
|
173
|
-
case answer
|
174
|
-
when 'y', 'yes'
|
175
|
-
File.truncate(GameOptions.data['log_file_path'], 0)
|
176
|
-
puts 'Log of attempts: erased!'
|
177
|
-
end
|
178
|
-
|
179
|
-
puts
|
180
|
-
end
|
181
|
-
else
|
182
|
-
puts 'No attempts made yet!'
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
def check_for_new_release
|
187
|
-
new_release_available = false
|
188
|
-
puts 'Checking releases...'
|
189
|
-
remote_release = Gems.versions('gemwarrior').first['number']
|
190
|
-
local_release = Gemwarrior::VERSION
|
191
|
-
|
192
|
-
0.upto(2) do |i|
|
193
|
-
if remote_release.split('.')[i].to_i > local_release.split('.')[i].to_i
|
194
|
-
new_release_available = true
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
if new_release_available
|
199
|
-
puts "GW v#{remote_release} available! Please exit and run 'gem update' before continuing."
|
200
|
-
puts
|
201
|
-
else
|
202
|
-
puts 'You have the latest version. Fantastic!'
|
203
|
-
puts
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
def print_options_sound_sytem
|
208
|
-
puts
|
209
|
-
puts 'Sound System Selection'.colorize(:yellow)
|
210
|
-
puts '================================='.colorize(:yellow)
|
211
|
-
puts
|
212
|
-
print ' (1) WIN32-SOUND '
|
213
|
-
print '(SELECTED)'.colorize(:yellow) if GameOptions.data['sound_system'].eql?('win32-sound')
|
214
|
-
print "\n"
|
215
|
-
print ' (2) FEEP '
|
216
|
-
print '(SELECTED)'.colorize(:yellow) if GameOptions.data['sound_system'].eql?('feep')
|
217
|
-
print "\n"
|
218
|
-
print ' (3) BLOOPS '
|
219
|
-
print '(SELECTED)'.colorize(:yellow) if GameOptions.data['sound_system'].eql?('bloops')
|
220
|
-
print "\n"
|
221
|
-
puts
|
222
|
-
puts ' WIN32-SOUND : good quality; Windows-only'
|
223
|
-
puts ' FEEP : cross-platform; VERY SLOW and BUGGY'
|
224
|
-
puts ' BLOOPS : cross-platform; requires portaudio'
|
225
|
-
puts
|
226
|
-
puts ' NOTE: none of these are required dependencies anymore, as sound is optional.'
|
227
|
-
puts ' If you do not have the one selected installed on your machine, you will get '
|
228
|
-
puts ' an error on game load, and no sound will be heard.'
|
229
|
-
puts
|
230
|
-
puts '================================='.colorize(:yellow)
|
231
|
-
puts
|
232
|
-
puts 'Enter option number to select sound system, or any other key to exit.'
|
233
|
-
puts
|
234
|
-
print '[GW_OPTS]-[SOUND_SYSTEM]> '
|
235
|
-
answer = STDIN.getch.chomp.downcase
|
236
|
-
|
237
|
-
case answer
|
238
|
-
when '1'
|
239
|
-
GameOptions.add 'sound_system', 'win32-sound'
|
240
|
-
print_options_sound_sytem
|
241
|
-
when '2'
|
242
|
-
GameOptions.add 'sound_system', 'feep'
|
243
|
-
print_options_sound_sytem
|
244
|
-
when '3'
|
245
|
-
GameOptions.add 'sound_system', 'bloops'
|
246
|
-
print_options_sound_sytem
|
247
|
-
else
|
248
|
-
return
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
def print_options
|
253
|
-
puts
|
254
|
-
puts 'Gem Warrior General Options'.colorize(:yellow)
|
255
|
-
puts '================================='.colorize(:yellow)
|
256
|
-
puts
|
257
|
-
puts 'Change several sound options, whether Wordnik is used to generate more dynamic descriptors of entities (valid WORDNIK_API_KEY environment variable must be set), and if attack/fight commands need to have a target or not (if enabled, will attack first monster in vicinty).'
|
258
|
-
puts
|
259
|
-
puts " (1) SOUND ENABLED : #{GameOptions.data['sound_enabled']}"
|
260
|
-
puts " (2) SOUND SYSTEM : #{GameOptions.data['sound_system']}"
|
261
|
-
puts " (3) SOUND VOLUME : #{GameOptions.data['sound_volume']}"
|
262
|
-
puts " (4) USE WORDNIK : #{GameOptions.data['use_wordnik']}"
|
263
|
-
puts " (5) FIGHT COMPLETION : #{GameOptions.data['fight_completion']}"
|
264
|
-
puts
|
265
|
-
puts '================================='.colorize(:yellow)
|
266
|
-
puts
|
267
|
-
puts 'Enter option number to change value, or any other key to return to main menu.'
|
268
|
-
puts
|
269
|
-
print '[GW_OPTS]> '
|
270
|
-
|
271
|
-
answer = STDIN.getch
|
272
|
-
|
273
|
-
case answer
|
274
|
-
when '1'
|
275
|
-
print answer
|
276
|
-
GameOptions.data['sound_enabled'] = !GameOptions.data['sound_enabled']
|
277
|
-
print_options
|
278
|
-
when '2'
|
279
|
-
print answer
|
280
|
-
print "\n"
|
281
|
-
print_options_sound_sytem
|
282
|
-
print_options
|
283
|
-
when '3'
|
284
|
-
print answer
|
285
|
-
print "\n"
|
286
|
-
print 'Enter a volume from 0.0 to 1.0: '
|
287
|
-
new_vol = gets.chomp.to_f.abs
|
288
|
-
if new_vol >= 0.0 and new_vol <= 1.0
|
289
|
-
GameOptions.data['sound_volume'] = new_vol
|
290
|
-
else
|
291
|
-
puts 'Not a valid volume.'
|
292
|
-
end
|
293
|
-
print_options
|
294
|
-
when '4'
|
295
|
-
print answer
|
296
|
-
GameOptions.data['use_wordnik'] = !GameOptions.data['use_wordnik']
|
297
|
-
print_options
|
298
|
-
when '5'
|
299
|
-
print answer
|
300
|
-
GameOptions.data['fight_completion'] = !GameOptions.data['fight_completion']
|
301
|
-
print_options
|
302
|
-
else
|
303
|
-
print answer
|
304
|
-
return
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
def print_main_menu
|
309
|
-
puts
|
310
|
-
puts " GW v#{Gemwarrior::VERSION}"
|
311
|
-
puts '======================='
|
312
|
-
puts ' (R)esume Game'.colorize(:green) if save_file_exist?
|
313
|
-
puts ' (N)ew Game'
|
314
|
-
puts ' (A)bout'
|
315
|
-
puts ' (H)elp'
|
316
|
-
puts ' (O)ptions'
|
317
|
-
puts ' (L)og of Attempts'
|
318
|
-
puts ' (C)heck for Updates'
|
319
|
-
puts ' (E)xit'.colorize(:red)
|
320
|
-
puts '======================='
|
321
|
-
puts
|
322
|
-
end
|
323
|
-
|
324
|
-
def print_main_menu_prompt
|
325
|
-
print '> '
|
326
|
-
end
|
327
|
-
|
328
|
-
def run_main_menu(show_choices = true)
|
329
|
-
print_main_menu if show_choices
|
330
|
-
print_main_menu_prompt if show_choices
|
331
|
-
|
332
|
-
choice = STDIN.getch.downcase
|
333
|
-
|
334
|
-
case choice
|
335
|
-
when 'n'
|
336
|
-
if overwrite_save?
|
337
|
-
clear_screen
|
338
|
-
play_intro_tune
|
339
|
-
print_splash_message
|
340
|
-
print_fortune
|
341
|
-
return
|
342
|
-
else
|
343
|
-
run_main_menu
|
344
|
-
end
|
345
|
-
when 'r'
|
346
|
-
if save_file_exist?
|
347
|
-
result = resume_game
|
348
|
-
if result.nil?
|
349
|
-
run_main_menu
|
350
|
-
else
|
351
|
-
print_errors
|
352
|
-
load_saved_world(result)
|
353
|
-
return
|
354
|
-
end
|
355
|
-
end
|
356
|
-
when 'a'
|
357
|
-
puts choice
|
358
|
-
print_about_text
|
359
|
-
run_main_menu
|
360
|
-
when 'h'
|
361
|
-
puts choice
|
362
|
-
print_help_text
|
363
|
-
run_main_menu
|
364
|
-
when 'o'
|
365
|
-
puts choice
|
366
|
-
print_options
|
367
|
-
run_main_menu
|
368
|
-
when 'l'
|
369
|
-
puts choice
|
370
|
-
display_log_of_attempts
|
371
|
-
run_main_menu
|
372
|
-
when 'c'
|
373
|
-
puts choice
|
374
|
-
check_for_new_release
|
375
|
-
run_main_menu
|
376
|
-
when 'e', 'x', 'q'
|
377
|
-
puts choice
|
378
|
-
puts MAIN_MENU_QUIT_MESSAGE
|
379
|
-
game.update_options_file
|
380
|
-
exit
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
Hr.print('#')
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
end
|
433
|
-
|
434
|
-
def
|
435
|
-
mode = GameOptions.data['save_file_mode']
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
File.
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
1
|
+
# lib/gemwarrior/repl.rb
|
2
|
+
# My own, simple, Read Evaluate Print Loop module
|
3
|
+
|
4
|
+
require 'readline'
|
5
|
+
require 'os'
|
6
|
+
require 'clocker'
|
7
|
+
require 'io/console'
|
8
|
+
require 'gems'
|
9
|
+
|
10
|
+
require_relative 'misc/timer'
|
11
|
+
require_relative 'misc/wordlist'
|
12
|
+
require_relative 'evaluator'
|
13
|
+
require_relative 'game_options'
|
14
|
+
require_relative 'version'
|
15
|
+
|
16
|
+
module Gemwarrior
|
17
|
+
class Repl
|
18
|
+
# CONSTANTS
|
19
|
+
SCREEN_WIDTH_MIN = 80
|
20
|
+
SCREEN_WIDTH_MAX = 120
|
21
|
+
QUIT_MESSAGE = 'Temporal flux detected. Shutting down...'.colorize(:red)
|
22
|
+
MAIN_MENU_QUIT_MESSAGE = 'Giving up so soon? Jool will be waiting...'.colorize(:red)
|
23
|
+
SPLASH_MESSAGE = 'Welcome to *Jool*, where randomized fortune is just as likely as mayhem.'
|
24
|
+
GITHUB_NAME = 'michaelchadwick'
|
25
|
+
GITHUB_PROJECT = 'gemwarrior'
|
26
|
+
|
27
|
+
attr_accessor :game, :world, :evaluator
|
28
|
+
|
29
|
+
def initialize(game, world, evaluator)
|
30
|
+
self.game = game
|
31
|
+
self.world = world
|
32
|
+
self.evaluator = evaluator
|
33
|
+
|
34
|
+
GameOptions.data['wrap_width'] = get_screen_width
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_screen_width
|
38
|
+
screen_width = SCREEN_WIDTH_MIN
|
39
|
+
|
40
|
+
begin
|
41
|
+
require 'io/console'
|
42
|
+
screen_width = IO.console.winsize[1]
|
43
|
+
rescue
|
44
|
+
if command_exists?('tput')
|
45
|
+
screen_width = `tput cols`.to_i
|
46
|
+
elsif command_exists?('stty')
|
47
|
+
screen_width = `stty size`.split.last.to_i
|
48
|
+
elsif command_exists?('mode')
|
49
|
+
mode_output = `mode`.split
|
50
|
+
screen_width = mode_output[mode_output.index('Columns:')+1].to_i
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
case
|
55
|
+
when screen_width.nil?, screen_width <= 0
|
56
|
+
return SCREEN_WIDTH_MIN
|
57
|
+
else
|
58
|
+
return [screen_width, SCREEN_WIDTH_MAX].min
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def start(initial_command, extra_command, new_skip, resume_skip)
|
63
|
+
setup_screen(initial_command, extra_command, new_skip, resume_skip)
|
64
|
+
|
65
|
+
clocker = Clocker.new
|
66
|
+
|
67
|
+
at_exit do
|
68
|
+
update_duration(clocker.stop)
|
69
|
+
game.update_options_file
|
70
|
+
log_stats(world.duration, world.player)
|
71
|
+
save_game(world)
|
72
|
+
end
|
73
|
+
|
74
|
+
clocker.clock do
|
75
|
+
# main loop
|
76
|
+
loop do
|
77
|
+
prompt
|
78
|
+
begin
|
79
|
+
main_loop
|
80
|
+
rescue Interrupt
|
81
|
+
puts
|
82
|
+
puts QUIT_MESSAGE
|
83
|
+
exit
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def main_loop(ext_input = nil)
|
90
|
+
input = ext_input.nil? ? read_line : ext_input
|
91
|
+
result = evaluator.parse(input)
|
92
|
+
if result.eql?('exit')
|
93
|
+
exit
|
94
|
+
elsif result.eql?('checkupdate')
|
95
|
+
check_for_new_release
|
96
|
+
else
|
97
|
+
puts result
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# timer observer
|
102
|
+
#def update(command)
|
103
|
+
# main_loop(command)
|
104
|
+
#end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def clear_screen
|
109
|
+
OS.windows? ? system('cls') : system('clear')
|
110
|
+
end
|
111
|
+
|
112
|
+
def read_line
|
113
|
+
prompt_text = GameOptions.data['debug_mode'] ? ' GW[D]> ' : ' GW> '
|
114
|
+
Readline.readline(prompt_text, true).to_s
|
115
|
+
end
|
116
|
+
|
117
|
+
def puts(s = '', width = GameOptions.data['wrap_width'])
|
118
|
+
super s.gsub(/(.{1,#{width}})(\s+|\Z)/, "\\1\n") unless s.nil?
|
119
|
+
end
|
120
|
+
|
121
|
+
def print_logo
|
122
|
+
puts '/-+-+-+ +-+-+-+-+-+-+-\\'.colorize(:yellow)
|
123
|
+
puts '|G|E|M| |W|A|R|R|I|O|R|'.colorize(:yellow)
|
124
|
+
puts '\\-+-+-+ +-+-+-+-+-+-+-/'.colorize(:yellow)
|
125
|
+
puts '[[[[[[[DEBUGGING]]]]]]]'.colorize(:white) if GameOptions.data['debug_mode']
|
126
|
+
end
|
127
|
+
|
128
|
+
def print_splash_message
|
129
|
+
SPLASH_MESSAGE.length.times { print '=' }
|
130
|
+
puts
|
131
|
+
puts SPLASH_MESSAGE
|
132
|
+
SPLASH_MESSAGE.length.times { print '=' }
|
133
|
+
puts
|
134
|
+
end
|
135
|
+
|
136
|
+
def print_fortune
|
137
|
+
noun1_values = WordList.new('noun-plural')
|
138
|
+
noun2_values = WordList.new('noun-plural')
|
139
|
+
noun3_values = WordList.new('noun-plural')
|
140
|
+
|
141
|
+
puts "* Remember: #{noun1_values.get_random_value} and #{noun2_values.get_random_value} are the key to #{noun3_values.get_random_value} *\n\n"
|
142
|
+
puts
|
143
|
+
end
|
144
|
+
|
145
|
+
def print_about_text
|
146
|
+
puts 'Gem Warrior - A Game of Fortune and Mayhem'.colorize(:yellow)
|
147
|
+
puts '=========================================='.colorize(:yellow)
|
148
|
+
puts 'Gem Warrior is a text adventure roguelike-lite as a RubyGem created by Michael Chadwick (mike@neb.host) and released as open-source on Github. Take on the task set by Queen Ruby to defeat the evil Emerald and get back the ShinyThing(tm) he stole for terrible, dastardly reasons.'
|
149
|
+
puts
|
150
|
+
puts 'Explore the land of Jool with the power of text, fighting enemies to improve your station, grabbing curious items that may or may not come in handy, and finally defeating Mr. Emerald himself to win the game.'
|
151
|
+
end
|
152
|
+
|
153
|
+
def print_help_text
|
154
|
+
puts 'Gem Warrior - Some Basic Help Commands'.colorize(:yellow)
|
155
|
+
puts '======================================'.colorize(:yellow)
|
156
|
+
puts '* Basic functions: look, go, character, inventory, attack *'
|
157
|
+
puts '* Type \'help\' while in-game for complete list of commands *'
|
158
|
+
puts '* Most commands can be abbreviated to their first letter *'
|
159
|
+
puts '* Note: if something isn\'t working, try: *'
|
160
|
+
puts '* 1) starting a new game *'
|
161
|
+
puts '* 2) updating the game *'
|
162
|
+
end
|
163
|
+
|
164
|
+
def display_log_of_attempts
|
165
|
+
if File.exist?(GameOptions.data['log_file_path']) and !File.zero?(GameOptions.data['log_file_path'])
|
166
|
+
File.open(GameOptions.data['log_file_path']).readlines.each do |line|
|
167
|
+
print "#{line}"
|
168
|
+
end
|
169
|
+
if GameOptions.data['debug_mode']
|
170
|
+
print 'Clear log of attempts? (y/n) '
|
171
|
+
answer = gets.chomp.downcase
|
172
|
+
|
173
|
+
case answer
|
174
|
+
when 'y', 'yes'
|
175
|
+
File.truncate(GameOptions.data['log_file_path'], 0)
|
176
|
+
puts 'Log of attempts: erased!'
|
177
|
+
end
|
178
|
+
|
179
|
+
puts
|
180
|
+
end
|
181
|
+
else
|
182
|
+
puts 'No attempts made yet!'
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def check_for_new_release
|
187
|
+
new_release_available = false
|
188
|
+
puts 'Checking releases...'
|
189
|
+
remote_release = Gems.versions('gemwarrior').first['number']
|
190
|
+
local_release = Gemwarrior::VERSION
|
191
|
+
|
192
|
+
0.upto(2) do |i|
|
193
|
+
if remote_release.split('.')[i].to_i > local_release.split('.')[i].to_i
|
194
|
+
new_release_available = true
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
if new_release_available
|
199
|
+
puts "GW v#{remote_release} available! Please exit and run 'gem update' before continuing."
|
200
|
+
puts
|
201
|
+
else
|
202
|
+
puts 'You have the latest version. Fantastic!'
|
203
|
+
puts
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def print_options_sound_sytem
|
208
|
+
puts
|
209
|
+
puts 'Sound System Selection'.colorize(:yellow)
|
210
|
+
puts '================================='.colorize(:yellow)
|
211
|
+
puts
|
212
|
+
print ' (1) WIN32-SOUND '
|
213
|
+
print '(SELECTED)'.colorize(:yellow) if GameOptions.data['sound_system'].eql?('win32-sound')
|
214
|
+
print "\n"
|
215
|
+
print ' (2) FEEP '
|
216
|
+
print '(SELECTED)'.colorize(:yellow) if GameOptions.data['sound_system'].eql?('feep')
|
217
|
+
print "\n"
|
218
|
+
print ' (3) BLOOPS '
|
219
|
+
print '(SELECTED)'.colorize(:yellow) if GameOptions.data['sound_system'].eql?('bloops')
|
220
|
+
print "\n"
|
221
|
+
puts
|
222
|
+
puts ' WIN32-SOUND : good quality; Windows-only'
|
223
|
+
puts ' FEEP : cross-platform; VERY SLOW and BUGGY'
|
224
|
+
puts ' BLOOPS : cross-platform; requires portaudio'
|
225
|
+
puts
|
226
|
+
puts ' NOTE: none of these are required dependencies anymore, as sound is optional.'
|
227
|
+
puts ' If you do not have the one selected installed on your machine, you will get '
|
228
|
+
puts ' an error on game load, and no sound will be heard.'
|
229
|
+
puts
|
230
|
+
puts '================================='.colorize(:yellow)
|
231
|
+
puts
|
232
|
+
puts 'Enter option number to select sound system, or any other key to exit.'
|
233
|
+
puts
|
234
|
+
print '[GW_OPTS]-[SOUND_SYSTEM]> '
|
235
|
+
answer = STDIN.getch.chomp.downcase
|
236
|
+
|
237
|
+
case answer
|
238
|
+
when '1'
|
239
|
+
GameOptions.add 'sound_system', 'win32-sound'
|
240
|
+
print_options_sound_sytem
|
241
|
+
when '2'
|
242
|
+
GameOptions.add 'sound_system', 'feep'
|
243
|
+
print_options_sound_sytem
|
244
|
+
when '3'
|
245
|
+
GameOptions.add 'sound_system', 'bloops'
|
246
|
+
print_options_sound_sytem
|
247
|
+
else
|
248
|
+
return
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def print_options
|
253
|
+
puts
|
254
|
+
puts 'Gem Warrior General Options'.colorize(:yellow)
|
255
|
+
puts '================================='.colorize(:yellow)
|
256
|
+
puts
|
257
|
+
puts 'Change several sound options, whether Wordnik is used to generate more dynamic descriptors of entities (valid WORDNIK_API_KEY environment variable must be set), and if attack/fight commands need to have a target or not (if enabled, will attack first monster in vicinty).'
|
258
|
+
puts
|
259
|
+
puts " (1) SOUND ENABLED : #{GameOptions.data['sound_enabled']}"
|
260
|
+
puts " (2) SOUND SYSTEM : #{GameOptions.data['sound_system']}"
|
261
|
+
puts " (3) SOUND VOLUME : #{GameOptions.data['sound_volume']}"
|
262
|
+
puts " (4) USE WORDNIK : #{GameOptions.data['use_wordnik']}"
|
263
|
+
puts " (5) FIGHT COMPLETION : #{GameOptions.data['fight_completion']}"
|
264
|
+
puts
|
265
|
+
puts '================================='.colorize(:yellow)
|
266
|
+
puts
|
267
|
+
puts 'Enter option number to change value, or any other key to return to main menu.'
|
268
|
+
puts
|
269
|
+
print '[GW_OPTS]> '
|
270
|
+
|
271
|
+
answer = STDIN.getch
|
272
|
+
|
273
|
+
case answer
|
274
|
+
when '1'
|
275
|
+
print answer
|
276
|
+
GameOptions.data['sound_enabled'] = !GameOptions.data['sound_enabled']
|
277
|
+
print_options
|
278
|
+
when '2'
|
279
|
+
print answer
|
280
|
+
print "\n"
|
281
|
+
print_options_sound_sytem
|
282
|
+
print_options
|
283
|
+
when '3'
|
284
|
+
print answer
|
285
|
+
print "\n"
|
286
|
+
print 'Enter a volume from 0.0 to 1.0: '
|
287
|
+
new_vol = gets.chomp.to_f.abs
|
288
|
+
if new_vol >= 0.0 and new_vol <= 1.0
|
289
|
+
GameOptions.data['sound_volume'] = new_vol
|
290
|
+
else
|
291
|
+
puts 'Not a valid volume.'
|
292
|
+
end
|
293
|
+
print_options
|
294
|
+
when '4'
|
295
|
+
print answer
|
296
|
+
GameOptions.data['use_wordnik'] = !GameOptions.data['use_wordnik']
|
297
|
+
print_options
|
298
|
+
when '5'
|
299
|
+
print answer
|
300
|
+
GameOptions.data['fight_completion'] = !GameOptions.data['fight_completion']
|
301
|
+
print_options
|
302
|
+
else
|
303
|
+
print answer
|
304
|
+
return
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def print_main_menu
|
309
|
+
puts
|
310
|
+
puts " GW v#{Gemwarrior::VERSION}"
|
311
|
+
puts '======================='
|
312
|
+
puts ' (R)esume Game'.colorize(:green) if save_file_exist?
|
313
|
+
puts ' (N)ew Game'
|
314
|
+
puts ' (A)bout'
|
315
|
+
puts ' (H)elp'
|
316
|
+
puts ' (O)ptions'
|
317
|
+
puts ' (L)og of Attempts'
|
318
|
+
puts ' (C)heck for Updates'
|
319
|
+
puts ' (E)xit'.colorize(:red)
|
320
|
+
puts '======================='
|
321
|
+
puts
|
322
|
+
end
|
323
|
+
|
324
|
+
def print_main_menu_prompt
|
325
|
+
print '> '
|
326
|
+
end
|
327
|
+
|
328
|
+
def run_main_menu(show_choices = true)
|
329
|
+
print_main_menu if show_choices
|
330
|
+
print_main_menu_prompt if show_choices
|
331
|
+
|
332
|
+
choice = STDIN.getch.downcase
|
333
|
+
|
334
|
+
case choice
|
335
|
+
when 'n'
|
336
|
+
if overwrite_save?
|
337
|
+
clear_screen
|
338
|
+
play_intro_tune
|
339
|
+
print_splash_message
|
340
|
+
print_fortune
|
341
|
+
return
|
342
|
+
else
|
343
|
+
run_main_menu
|
344
|
+
end
|
345
|
+
when 'r'
|
346
|
+
if save_file_exist?
|
347
|
+
result = resume_game
|
348
|
+
if result.nil?
|
349
|
+
run_main_menu
|
350
|
+
else
|
351
|
+
print_errors
|
352
|
+
load_saved_world(result)
|
353
|
+
return
|
354
|
+
end
|
355
|
+
end
|
356
|
+
when 'a'
|
357
|
+
puts choice
|
358
|
+
print_about_text
|
359
|
+
run_main_menu
|
360
|
+
when 'h'
|
361
|
+
puts choice
|
362
|
+
print_help_text
|
363
|
+
run_main_menu
|
364
|
+
when 'o'
|
365
|
+
puts choice
|
366
|
+
print_options
|
367
|
+
run_main_menu
|
368
|
+
when 'l'
|
369
|
+
puts choice
|
370
|
+
display_log_of_attempts
|
371
|
+
run_main_menu
|
372
|
+
when 'c'
|
373
|
+
puts choice
|
374
|
+
check_for_new_release
|
375
|
+
run_main_menu
|
376
|
+
when 'e', 'x', 'q'
|
377
|
+
puts choice
|
378
|
+
puts MAIN_MENU_QUIT_MESSAGE
|
379
|
+
game.update_options_file
|
380
|
+
exit
|
381
|
+
when "\c?" # Backspace/Delete
|
382
|
+
refresh_menu
|
383
|
+
when "\e" # ANSI escape sequence
|
384
|
+
case STDIN.getch
|
385
|
+
when '[' # CSI
|
386
|
+
choice = STDIN.getch
|
387
|
+
puts choice
|
388
|
+
case choice
|
389
|
+
when 'A', 'B', 'C', 'D' # arrow keys
|
390
|
+
refresh_menu
|
391
|
+
end
|
392
|
+
end
|
393
|
+
else # All other invalid options
|
394
|
+
refresh_menu
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
# need this to handle any non-valid input at the main menu
|
399
|
+
def refresh_menu
|
400
|
+
clear_screen
|
401
|
+
print_logo
|
402
|
+
run_main_menu
|
403
|
+
end
|
404
|
+
|
405
|
+
def log_stats(duration, pl)
|
406
|
+
# display stats upon exit
|
407
|
+
Hr.print('#')
|
408
|
+
print 'Gem Warrior'.colorize(color: :white, background: :black)
|
409
|
+
print " v#{Gemwarrior::VERSION}".colorize(:yellow)
|
410
|
+
print " played for #{duration[:mins].to_s.colorize(color: :white, background: :black)} min(s),"
|
411
|
+
print " #{duration[:secs].to_s.colorize(color: :white, background: :black)} sec(s),"
|
412
|
+
print " and #{duration[:ms].to_s.colorize(color: :white, background: :black)} ms\n"
|
413
|
+
Hr.print('-')
|
414
|
+
print "#{pl.name.ljust(10)} killed #{pl.monsters_killed.to_s.colorize(color: :yellow, background: :black)} monster(s)"
|
415
|
+
print "\n".ljust(12)
|
416
|
+
print "killed #{pl.bosses_killed.to_s.colorize(color: :yellow, background: :black)} boss(es)"
|
417
|
+
print "\n".ljust(12)
|
418
|
+
print "picked up #{pl.items_taken.to_s.colorize(color: :yellow, background: :black)} item(s)"
|
419
|
+
print "\n".ljust(12)
|
420
|
+
print "traveled #{pl.movements_made.to_s.colorize(color: :yellow, background: :black)} time(s)"
|
421
|
+
print "\n".ljust(12)
|
422
|
+
print "rested #{pl.rests_taken.to_s.colorize(color: :yellow, background: :black)} time(s)"
|
423
|
+
print "\n".ljust(12)
|
424
|
+
print "died #{pl.deaths.to_s.colorize(color: :yellow, background: :black)} time(s)"
|
425
|
+
print "\n"
|
426
|
+
Hr.print('#')
|
427
|
+
|
428
|
+
# log stats to file in home directory
|
429
|
+
File.open(GameOptions.data['log_file_path'], 'a') do |f|
|
430
|
+
f.write "#{Time.now} #{pl.name.rjust(13)} - V:#{Gemwarrior::VERSION} LV:#{pl.level} XP:#{pl.xp} $:#{pl.rox} MK:#{pl.monsters_killed} BK:#{pl.bosses_killed} ITM:#{pl.items_taken} MOV:#{pl.movements_made} RST:#{pl.rests_taken} DTH:#{pl.deaths}\n"
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
def save_game(world)
|
435
|
+
mode = GameOptions.data['save_file_mode']
|
436
|
+
puts 'Saving game...'
|
437
|
+
|
438
|
+
if mode.eql? 'Y'
|
439
|
+
File.open(GameOptions.data['save_file_yaml_path'], 'w') do |f|
|
440
|
+
f.write YAML.dump(world)
|
441
|
+
end
|
442
|
+
elsif mode.eql? 'M'
|
443
|
+
File.open(GameOptions.data['save_file_bin_path'], 'w') do |f|
|
444
|
+
f.write Marshal.dump(world)
|
445
|
+
end
|
446
|
+
else
|
447
|
+
puts 'Error: Save file mode not set. Game not saved.'
|
448
|
+
return
|
449
|
+
end
|
450
|
+
puts 'Game saved!'
|
451
|
+
end
|
452
|
+
|
453
|
+
def save_file_exist?
|
454
|
+
mode = GameOptions.data['save_file_mode']
|
455
|
+
if mode.eql? 'Y'
|
456
|
+
File.exist?(GameOptions.data['save_file_yaml_path'])
|
457
|
+
elsif mode.eql? 'M'
|
458
|
+
File.exist?(GameOptions.data['save_file_bin_path'])
|
459
|
+
else
|
460
|
+
false
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
def resume_game
|
465
|
+
mode = GameOptions.data['save_file_mode']
|
466
|
+
puts 'Resuming game...'
|
467
|
+
|
468
|
+
if mode.eql? 'Y'
|
469
|
+
if File.exist?(GameOptions.data['save_file_yaml_path'])
|
470
|
+
File.open(GameOptions.data['save_file_yaml_path'], 'r') do |f|
|
471
|
+
return YAML.load(f)
|
472
|
+
end
|
473
|
+
else
|
474
|
+
puts 'No save file exists.'
|
475
|
+
nil
|
476
|
+
end
|
477
|
+
elsif mode.eql? 'M'
|
478
|
+
if File.exist?(GameOptions.data['save_file_marshal_path'])
|
479
|
+
File.open(GameOptions.data['save_file_marshal_path'], 'r') do |f|
|
480
|
+
return Marshal.load(f)
|
481
|
+
end
|
482
|
+
else
|
483
|
+
puts 'No save file exists.'
|
484
|
+
nil
|
485
|
+
end
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
def overwrite_save?
|
490
|
+
mode = GameOptions.data['save_file_mode']
|
491
|
+
save_file_path = ''
|
492
|
+
|
493
|
+
if mode.eql? 'Y'
|
494
|
+
save_file_path = GameOptions.data['save_file_yaml_path']
|
495
|
+
elsif mode.eql? 'M'
|
496
|
+
save_file_path = GameOptions.data['save_file_marshal_path']
|
497
|
+
end
|
498
|
+
|
499
|
+
if File.exist?(save_file_path)
|
500
|
+
print 'Overwrite existing save file? (y/n) '
|
501
|
+
answer = gets.chomp.downcase
|
502
|
+
|
503
|
+
case answer
|
504
|
+
when 'y', 'yes'
|
505
|
+
puts 'New game started! Press any key to continue.'
|
506
|
+
gets
|
507
|
+
return true
|
508
|
+
else
|
509
|
+
puts 'New game aborted.'
|
510
|
+
return false
|
511
|
+
end
|
512
|
+
end
|
513
|
+
true
|
514
|
+
end
|
515
|
+
|
516
|
+
def update_duration(new_duration)
|
517
|
+
new_mins = new_duration[:mins]
|
518
|
+
new_secs = new_duration[:secs]
|
519
|
+
new_ms = new_duration[:ms]
|
520
|
+
|
521
|
+
world.duration[:mins] += new_mins
|
522
|
+
world.duration[:secs] += new_secs
|
523
|
+
world.duration[:ms] += new_ms
|
524
|
+
|
525
|
+
if world.duration[:ms] > 1000
|
526
|
+
world.duration[:secs] += world.duration[:ms] / 1000
|
527
|
+
world.duration[:ms] = world.duration[:ms] % 1000
|
528
|
+
end
|
529
|
+
|
530
|
+
if world.duration[:secs] > 60
|
531
|
+
world.duration[:mins] += world.duration[:secs] / 60
|
532
|
+
world.duration[:secs] = world.duration[:secs] % 60
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
def load_saved_world(result)
|
537
|
+
self.world = result
|
538
|
+
self.evaluator = Evaluator.new(self.world)
|
539
|
+
end
|
540
|
+
|
541
|
+
def setup_screen(initial_command = nil, extra_command = nil, new_skip = false, resume_skip = false)
|
542
|
+
# welcome player to game
|
543
|
+
clear_screen
|
544
|
+
print_logo
|
545
|
+
|
546
|
+
# main menu loop until new game or exit
|
547
|
+
if new_skip
|
548
|
+
print_errors
|
549
|
+
play_intro_tune
|
550
|
+
print_splash_message
|
551
|
+
print_fortune
|
552
|
+
elsif resume_skip
|
553
|
+
result = resume_game
|
554
|
+
if result.nil?
|
555
|
+
run_main_menu
|
556
|
+
else
|
557
|
+
print_errors
|
558
|
+
load_saved_world(result)
|
559
|
+
end
|
560
|
+
else
|
561
|
+
run_main_menu
|
562
|
+
end
|
563
|
+
|
564
|
+
# hook to do something right off the bat
|
565
|
+
puts evaluator.parse(initial_command) unless initial_command.nil?
|
566
|
+
puts evaluator.parse(extra_command) unless extra_command.nil?
|
567
|
+
end
|
568
|
+
|
569
|
+
def print_errors
|
570
|
+
if GameOptions.data['errors']
|
571
|
+
puts GameOptions.data['errors'].colorize(:red)
|
572
|
+
end
|
573
|
+
end
|
574
|
+
|
575
|
+
def play_intro_tune
|
576
|
+
Audio.play_synth(:intro)
|
577
|
+
end
|
578
|
+
|
579
|
+
def prompt
|
580
|
+
prompt_template = "\n"
|
581
|
+
prompt_template += "[LV:%2s][XP:%3s][ROX:%3s][HP:%3s/%-3s] [".colorize(:yellow)
|
582
|
+
prompt_template += "%s".colorize(:green)
|
583
|
+
prompt_template += " @ ".colorize(:yellow)
|
584
|
+
prompt_template += "%s".colorize(:cyan)
|
585
|
+
prompt_template += "]".colorize(:yellow)
|
586
|
+
prompt_template += "[%s, %s, %s]".colorize(:yellow) if GameOptions.data['debug_mode']
|
587
|
+
|
588
|
+
prompt_vars_arr = [
|
589
|
+
world.player.level,
|
590
|
+
world.player.xp,
|
591
|
+
world.player.rox,
|
592
|
+
world.player.hp_cur,
|
593
|
+
world.player.hp_max,
|
594
|
+
world.player.name,
|
595
|
+
world.location_by_coords(world.player.cur_coords).name_display
|
596
|
+
]
|
597
|
+
if GameOptions.data['debug_mode']
|
598
|
+
prompt_vars_arr.push(world.player.cur_coords[:x], world.player.cur_coords[:y], world.player.cur_coords[:z])
|
599
|
+
end
|
600
|
+
print (prompt_template % prompt_vars_arr)
|
601
|
+
print "\n"
|
602
|
+
end
|
603
|
+
|
604
|
+
def command_exists?(cmd)
|
605
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).collect { |d|
|
606
|
+
Dir.entries d if Dir.exist? d
|
607
|
+
}.flatten.include?(cmd)
|
608
|
+
end
|
609
|
+
end
|
610
|
+
end
|