class Gemwarrior::Repl

Constants

ERROR_SOUND_NOT_ENABLED
GITHUB_NAME
GITHUB_PROJECT
QUIT_MESSAGE
SCREEN_WIDTH_MAX
SCREEN_WIDTH_MIN

CONSTANTS

SPLASH_MESSAGE

Attributes

evaluator[RW]
game[RW]
world[RW]

Public Class Methods

new(game, world, evaluator) click to toggle source
# File lib/gemwarrior/repl.rb, line 32
def initialize(game, world, evaluator)
  self.game         = game
  self.world        = world
  self.evaluator    = evaluator

  GameOptions.data['wrap_width'] = get_screen_width
end

Public Instance Methods

get_screen_width() click to toggle source
# File lib/gemwarrior/repl.rb, line 40
def get_screen_width
  screen_width = SCREEN_WIDTH_MIN

  begin
    require 'io/console'
    screen_width = IO.console.winsize[1]
  rescue
    if command_exists?('tput')
      screen_width = `tput cols`.to_i
    elsif command_exists?('stty')
      screen_width = `stty size`.split.last.to_i
    elsif command_exists?('mode')
      mode_output = `mode`.split
      screen_width = mode_output[mode_output.index('Columns:')+1].to_i
    end
  end

  case
  when screen_width.nil?, screen_width <= 0
    return SCREEN_WIDTH_MIN
  else
    return [screen_width, SCREEN_WIDTH_MAX].min
  end
end
main_loop(ext_input = nil) click to toggle source
# File lib/gemwarrior/repl.rb, line 92
def main_loop(ext_input = nil)
  input = ext_input.nil? ? read_line : ext_input
  result = evaluator.parse(input)
  if result.eql?('exit')
    exit
  elsif result.eql?('checkupdate')
    check_for_new_release
  else
    puts result
  end
end
start(initial_command, extra_command, new_skip, resume_skip) click to toggle source
# File lib/gemwarrior/repl.rb, line 65
def start(initial_command, extra_command, new_skip, resume_skip)
  setup_screen(initial_command, extra_command, new_skip, resume_skip)

  clocker = Clocker.new

  at_exit do
    update_duration(clocker.stop)
    game.update_options_file
    log_stats(world.duration, world.player)
    save_game(world)
  end

  clocker.clock do
    # main loop
    loop do
      prompt
      begin
        main_loop
      rescue Interrupt
        puts
        puts QUIT_MESSAGE
        exit
      end
    end
  end
end

Private Instance Methods

check_for_new_release() click to toggle source
# File lib/gemwarrior/repl.rb, line 197
def check_for_new_release
  new_release_available = false
  puts 'Checking releases...'
  remote_release = Gems.versions('gemwarrior').first['number']
  local_release = Gemwarrior::VERSION

  0.upto(2) do |i|
    if remote_release.split('.')[i].to_i > local_release.split('.')[i].to_i
      new_release_available = true
    end
  end

  if new_release_available
    puts "GW v#{remote_release} available! Please exit and run 'gem update' before continuing."
    puts
  else
    puts 'You have the latest version. Fantastic!'
    puts
  end
end
clear_screen() click to toggle source
timer observer

def update(command)

main_loop(command)

end

# File lib/gemwarrior/repl.rb, line 111
def clear_screen
  OS.windows? ? system('cls') : system('clear')
end
command_exists?(cmd) click to toggle source
# File lib/gemwarrior/repl.rb, line 706
def command_exists?(cmd)
  ENV['PATH'].split(File::PATH_SEPARATOR).collect { |d|
    Dir.entries d if Dir.exist? d
  }.flatten.include?(cmd)
end
display_log_of_attempts() click to toggle source
# File lib/gemwarrior/repl.rb, line 175
def display_log_of_attempts
  if File.exist?(GameOptions.data['log_file_path']) and !File.zero?(GameOptions.data['log_file_path'])
    File.open(GameOptions.data['log_file_path']).readlines.each do |line|
      print "#{line}"
    end
    if GameOptions.data['debug_mode']
      print 'Clear log of attempts? (y/n) '
      answer = gets.chomp.downcase

      case answer
      when 'y', 'yes'
        File.truncate(GameOptions.data['log_file_path'], 0)
        puts 'Log of attempts: erased!'
      end

      puts
    end
  else
    puts 'No attempts made yet!'
  end
end
get_save_file_name() click to toggle source
# File lib/gemwarrior/repl.rb, line 120
def get_save_file_name
  if save_file_exist?
    File.open(GameOptions.data['save_file_yaml_path'], 'r') do |f|
      return YAML.unsafe_load(f)
    end
  end
end
load_saved_world(result) click to toggle source
# File lib/gemwarrior/repl.rb, line 626
def load_saved_world(result)
  self.world = result
  self.evaluator = Evaluator.new(self.world)
end
log_stats(duration, pl) click to toggle source
# File lib/gemwarrior/repl.rb, line 493
def log_stats(duration, pl)
  # display stats upon exit
  Hr.print('#')
  print 'Gem Warrior'.colorize(color: :white, background: :black)
  print " v#{Gemwarrior::VERSION}".colorize(:yellow)
  print " played for #{duration[:mins].to_s.colorize(color: :white, background: :black)} min(s)"
  print ", #{duration[:secs].to_s.colorize(color: :white, background: :black)} sec(s)"
  # print ", and #{duration[:ms].to_s.colorize(color: :white, background: :black)} ms"
  print "\n"
  Hr.print('-')
  print "#{pl.name.ljust(10).colorize(:green)} "
  print "destroyed #{pl.monsters_killed.to_s.colorize(color: :yellow, background: :black)} monster(s)"
  print "\n".ljust(12)
  print "destroyed #{pl.bosses_killed.to_s.colorize(color: :yellow, background: :black)} boss(es)"
  print "\n".ljust(12)
  print "picked up #{pl.items_taken.to_s.colorize(color: :yellow, background: :black)} item(s)"
  print "\n".ljust(12)
  print "traveled  #{pl.movements_made.to_s.colorize(color: :yellow, background: :black)} time(s)"
  print "\n".ljust(12)
  print "rested    #{pl.rests_taken.to_s.colorize(color: :yellow, background: :black)} time(s)"
  print "\n".ljust(12)
  print "died      #{pl.deaths.to_s.colorize(color: :yellow, background: :black)} time(s)"
  print "\n"
  Hr.print('#')

  # log stats to file in home directory
  File.open(GameOptions.data['log_file_path'], 'a') do |f|
    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"
  end
end
overwrite_save?() click to toggle source
# File lib/gemwarrior/repl.rb, line 579
def overwrite_save?
  mode = GameOptions.data['save_file_mode']
  save_file_path = ''

  if mode.eql? 'Y'
    save_file_path = GameOptions.data['save_file_yaml_path']
  elsif mode.eql? 'M'
    save_file_path = GameOptions.data['save_file_marshal_path']
  end

  if File.exist?(save_file_path)
    print 'Overwrite existing save file? (y/n) '
    answer = gets.chomp.downcase

    case answer
    when 'y', 'yes'
      puts 'New game started! Press any key to continue.'
      gets
      return true
    else
      puts 'New game aborted.'
      return false
    end
  end
  true
end
play_intro_tune() click to toggle source
# File lib/gemwarrior/repl.rb, line 667
def play_intro_tune
  Audio.play_synth(:intro)
end
play_resume_tune() click to toggle source
# File lib/gemwarrior/repl.rb, line 671
def play_resume_tune
  Audio.play_synth(:resume_game)
end
play_test_tune() click to toggle source
# File lib/gemwarrior/repl.rb, line 675
def play_test_tune
  Audio.play_synth(:test)
end
print_about_text() click to toggle source
print_errors() click to toggle source
print_fortune() click to toggle source
print_help_text() click to toggle source
print_main_menu() click to toggle source
print_main_menu_prompt() click to toggle source
print_options() click to toggle source
print_options_sound_sytem() click to toggle source
print_sound_test() click to toggle source
print_splash_message() click to toggle source
prompt() click to toggle source
# File lib/gemwarrior/repl.rb, line 679
def prompt
  prompt_template =  "\n"
  prompt_template += "[LV:%2s][XP:%3s][ROX:%3s][HP:%3s/%-3s] [".colorize(:yellow)
  prompt_template += "%s".colorize(:green)
  prompt_template += " @ ".colorize(:yellow)
  prompt_template += "%s".colorize(:cyan)
  prompt_template += "]".colorize(:yellow)
  prompt_template += "[%s, %s, %s]".colorize(:yellow) if GameOptions.data['debug_mode']
  prompt_template += "\n"
  prompt_template += '[c:character][i:inventory][l:look][u:use][t:take]'

  prompt_vars_arr = [
    world.player.level,
    world.player.xp,
    world.player.rox,
    world.player.hp_cur,
    world.player.hp_max,
    world.player.name,
    world.location_by_coords(world.player.cur_coords).name_display
  ]
  if GameOptions.data['debug_mode']
    prompt_vars_arr.push(world.player.cur_coords[:x], world.player.cur_coords[:y], world.player.cur_coords[:z])
  end
  print (prompt_template % prompt_vars_arr)
  print "\n"
end
puts(s = '', width = GameOptions.data['wrap_width']) click to toggle source
Calls superclass method
# File lib/gemwarrior/repl.rb, line 128
def puts(s = '', width = GameOptions.data['wrap_width'])
  super s.gsub(/(.{1,#{width}})(\s+|\Z)/, "\\1\n") unless s.nil?
end
read_line() click to toggle source
# File lib/gemwarrior/repl.rb, line 115
def read_line
  prompt_text = GameOptions.data['debug_mode'] ? ' GW[D]> ' : ' GW> '
  Readline.readline(prompt_text, true).to_s
end
refresh_menu() click to toggle source

need this to handle any non-valid input at the main menu

# File lib/gemwarrior/repl.rb, line 487
def refresh_menu
  clear_screen
  print_logo
  run_main_menu
end
resume_game() click to toggle source
# File lib/gemwarrior/repl.rb, line 554
def resume_game
  mode = GameOptions.data['save_file_mode']
  puts 'Resuming game...'

  if mode.eql? 'Y'
    if File.exist?(GameOptions.data['save_file_yaml_path'])
      File.open(GameOptions.data['save_file_yaml_path'], 'r') do |f|
        return YAML.unsafe_load(f)
      end
    else
      puts 'No save file exists.'
      nil
    end
  elsif mode.eql? 'M'
    if File.exist?(GameOptions.data['save_file_marshal_path'])
      File.open(GameOptions.data['save_file_marshal_path'], 'r') do |f|
        return Marshal.load(f)
      end
    else
      puts 'No save file exists.'
      nil
    end
  end
end
run_main_menu(show_choices = true) click to toggle source
# File lib/gemwarrior/repl.rb, line 411
def run_main_menu(show_choices = true)
  print_main_menu if show_choices
  print_main_menu_prompt if show_choices

  choice = STDIN.getch.downcase

  case choice
  when 'n'
    if overwrite_save?
      clear_screen
      play_intro_tune
      print_splash_message
      print_fortune
      return
    else
      run_main_menu
    end
  when 'r'
    if save_file_exist?
      result = resume_game
      if result.nil?
        run_main_menu
      else
        print_errors
        play_resume_tune
        load_saved_world(result)
        return
      end
    end
  when 'a'
    puts choice
    print_about_text
    run_main_menu
  when 'h'
    puts choice
    print_help_text
    run_main_menu
  when 'o'
    puts choice
    print_options
    run_main_menu
  when 'l'
    puts choice
    display_log_of_attempts
    run_main_menu
  when 's'
    puts choice
    print_sound_test
    run_main_menu
  when 'c'
    puts choice
    check_for_new_release
    run_main_menu
  when 'e', 'x', 'q'
    puts choice
    puts MAIN_MENU_QUIT_MESSAGE
    game.update_options_file
    exit
  when "\c?"  # Backspace/Delete
    refresh_menu
  when "\e"   # ANSI escape sequence
    case STDIN.getch
    when '['  # CSI
      choice = STDIN.getch
      puts choice
      case choice
      when 'A', 'B', 'C', 'D' # arrow keys
        refresh_menu
      end
    end
  else        # All other invalid options
    refresh_menu
  end
end
save_file_exist?() click to toggle source
# File lib/gemwarrior/repl.rb, line 543
def save_file_exist?
  mode = GameOptions.data['save_file_mode']
  if mode.eql? 'Y'
    File.exist?(GameOptions.data['save_file_yaml_path'])
  elsif mode.eql? 'M'
    File.exist?(GameOptions.data['save_file_bin_path'])
  else
    false
  end
end
save_game(world) click to toggle source
# File lib/gemwarrior/repl.rb, line 524
def save_game(world)
  mode = GameOptions.data['save_file_mode']
  puts 'Saving game...'

  if mode.eql? 'Y'
    File.open(GameOptions.data['save_file_yaml_path'], 'w') do |f|
      f.write YAML.dump(world)
    end
  elsif mode.eql? 'M'
    File.open(GameOptions.data['save_file_bin_path'], 'w') do |f|
      f.write Marshal.dump(world)
    end
  else
    puts 'Error: Save file mode not set. Game not saved.'
    return
  end
  puts 'Game saved!'
end
setup_screen(initial_command = nil, extra_command = nil, new_skip = false, resume_skip = false) click to toggle source
# File lib/gemwarrior/repl.rb, line 631
def setup_screen(initial_command = nil, extra_command = nil, new_skip = false, resume_skip = false)
  # welcome player to game
  clear_screen
  print_logo

  # main menu loop until new game or exit
  if new_skip
    print_errors
    play_intro_tune
    print_splash_message
    print_fortune
  elsif resume_skip
    result = resume_game
    if result.nil?
      run_main_menu
    else
      print_errors
      load_saved_world(result)
    end
  else
    run_main_menu
  end

  # hook to do something right off the bat
  puts evaluator.parse(initial_command) unless initial_command.nil?
  puts evaluator.parse(extra_command) unless extra_command.nil?
end
update_duration(new_duration) click to toggle source
# File lib/gemwarrior/repl.rb, line 606
def update_duration(new_duration)
  new_mins = new_duration[:mins]
  new_secs = new_duration[:secs]
  new_ms   = new_duration[:ms]

  world.duration[:mins] += new_mins
  world.duration[:secs] += new_secs
  world.duration[:ms]   += new_ms

  if world.duration[:ms] > 1000
    world.duration[:secs] += world.duration[:ms] / 1000
    world.duration[:ms] = world.duration[:ms] % 1000
  end

  if world.duration[:secs] > 60
    world.duration[:mins] += world.duration[:secs] / 60
    world.duration[:secs] = world.duration[:secs] % 60
  end
end