Module: TextPlayer

Defined in:
lib/text_player.rb,
lib/text_player/cli.rb,
lib/text_player/dfrotz.rb,
lib/text_player/session.rb,
lib/text_player/version.rb,
lib/text_player/commands.rb,
lib/text_player/gamefile.rb,
lib/text_player/savefile.rb,
lib/text_player/formatters.rb,
lib/text_player/commands/quit.rb,
lib/text_player/commands/save.rb,
lib/text_player/command_result.rb,
lib/text_player/commands/score.rb,
lib/text_player/commands/start.rb,
lib/text_player/commands/action.rb,
lib/text_player/formatters/base.rb,
lib/text_player/formatters/data.rb,
lib/text_player/formatters/json.rb,
lib/text_player/formatters/text.rb,
lib/text_player/commands/restore.rb,
lib/text_player/formatters/shell.rb

Defined Under Namespace

Modules: Commands, Formatters Classes: CLI, Dfrotz, Error, Session

Constant Summary collapse

AUTO_SAVE_SLOT =
"autosave"
FILENAME_PROMPT_REGEX =
/Please enter a filename \[.*\]: /
PROMPT_REGEX =
/^>\s*$/
SCORE_REGEX =
/([0-9]+) ?(?:\(total [points ]*[out ]*of [a mxiuof]*[a posible]*([0-9]+)\))?/i
GAME_DIR =
Pathname.new(__dir__).join("../games")
FAILURE_PATTERNS =
[
  /I don't understand/i,
  /I don't know/i,
  /You can't/i,
  /You're not/i,
  /I can't see/i,
  /That doesn't make sense/i,
  /That's not a verb I recognize/i,
  /What do you want to/i,
  /You don't see/i,
  /There is no/i,
  /I don't see/i,
  /I beg your pardon/i
].freeze
VERSION =
"0.1.0"
Gamefile =

Gamefile - A game file and its name

Data.define(:name, :path) do
  def self.from_input(input)
    if input.include?("/")
      path = Pathname.new(input)
      new(name: path.basename.to_s, path:)
    else # must be a simple game name
      matches = TextPlayer::GAME_DIR.glob("#{input}.*")

      if matches.size == 1
        path = matches.first
        new(name: path.basename.to_s, path:)
      else
        names = matches.map { |m| m.basename }
        raise ArgumentError, "Multiple games found for '#{input}':\n#{names.join("\n")}"
      end
    end
  end

  def initialize(name:, path:)
    super(name: name.to_s, path: Pathname.new(path))
  end

  def exist? = path.exist?

  def full_path = path.expand_path.to_s
end
Savefile =

Utilities for saving and restoring game state

Data.define(:game_name, :slot) do
  def initialize(game_name: nil, slot: nil)
    slot = slot.to_s.strip
    slot = TextPlayer::AUTO_SAVE_SLOT if slot.empty?
    super
  end

  def filename
    basename = [game_name, slot].compact.join("_")
    "saves/#{basename}.qzl"
  end

  def exist?
    File.exist?(filename)
  end

  def delete
    File.delete(filename)
  end
end
CommandResult =

Encapsulates the result of executing a command

Data.define(:input, :raw_output, :operation, :success, :message, :details) do
  # Common failure patterns in text adventure games

  def initialize(input:, raw_output: "", operation: :action, success: true, message: nil, **details)
    super(input:, raw_output:, operation:, success:, message:, details:)
  end

  def action_command? = operation == :action

  def system_command? = !action_command?

  def success? = success

  def failure? = !success

  def to_h
    super.merge(details)
  end

  private

  def respond_to_missing?(method, include_private = false)
    details.key?(method) || super
  end

  def method_missing(method, *args, &block)
    if details.key?(method)
      details[method]
    else
      super
    end
  end
end