class Gamefic::World::Playbook

A collection of rules for performing commands.

Attributes

syntaxes[R]

An array of available syntaxes.

@return [Array<Gamefic::Syntax>]

validators[R]

An array of defined validators.

@return [Array<Proc>]

Public Class Methods

new(commands: {}) click to toggle source

@param commands [Hash] @param syntaxes [Array<Syntax>, Set<Syntax>] @param validators [Array]

# File lib/gamefic/world/playbook.rb, line 21
def initialize commands: {}, syntaxes: [], validators: []
  @commands = commands
  @syntax_set = syntaxes.to_set
  sort_syntaxes
  @validators = validators
end

Public Instance Methods

actions() click to toggle source

An array of available actions.

@return [Array<Gamefic::Action>]

# File lib/gamefic/world/playbook.rb, line 31
def actions
  @commands.values.flatten
end
actions_for(verb) click to toggle source

Get an Array of all Actions associated with the specified verb.

@param verb [Symbol] The Symbol for the verb (e.g., :go or :look) @return [Array<Class<Action>>] The verb's associated Actions

# File lib/gamefic/world/playbook.rb, line 52
def actions_for verb
  @commands[verb] || []
end
dispatch(actor, text) click to toggle source

Get a Dispatcher to select actions that can potentially be executed from the specified command string.

@param actor [Actor] @param text [String] @return [Dispatcher]

# File lib/gamefic/world/playbook.rb, line 133
def dispatch(actor, text)
  commands = Syntax.tokenize(text, actor.syntaxes)
  actions = commands.flat_map { |cmd| actions_for(cmd.verb).reject(&:hidden?) }
  Dispatcher.new(actor, commands, sort_and_reduce_actions(actions))
end
dispatch_from_params(actor, verb, params) click to toggle source

Get an array of actions, derived from the specified verb and params, that the actor can potentially execute.

@return [Array<Gamefic::Action>]

# File lib/gamefic/world/playbook.rb, line 143
def dispatch_from_params actor, verb, params
  available = actions_for(verb)
  Dispatcher.new(actor, [Command.new(verb, params)], sort_and_reduce_actions(available))
end
dup() click to toggle source

Duplicate the playbook. This method will duplicate the commands hash and the syntax array so the new playbook can be modified without affecting the original.

@return [Playbook]

# File lib/gamefic/world/playbook.rb, line 153
def dup
  Playbook.new commands: @commands.dup, syntaxes: @syntaxes.dup
end
freeze() click to toggle source
# File lib/gamefic/world/playbook.rb, line 157
def freeze
  @commands.freeze
  @syntaxes.freeze
end
interpret(input, translation) click to toggle source

Create an alternate Syntax for an Action. The command and its translation can be parameterized.

@example Create a synonym for the Inventory Action.

interpret "catalogue", "inventory"
# The command "catalogue" will be translated to "inventory"

@example Create a parameterized synonym for the Look Action.

interpret "scrutinize :entity", "look :entity"
# The command "scrutinize chair" will be translated to "look chair"

@param input [String] The format of the original command @param translation [String] The format of the translated command @return [Syntax] the Syntax object

# File lib/gamefic/world/playbook.rb, line 121
def interpret(input, translation)
  syn = Syntax.new(input, translation)
  add_syntax syn
  syn
end
meta(verb, *queries, &proc) click to toggle source

Create a Meta Action that responds to a command. Meta Actions are very similar to standard Actions, except the Plot understands them to be commands that operate above and/or outside of the actual game world. Examples of Meta Actions are commands that report the player's current score, save and restore saved games, or list the game's credits.

@example A simple Meta Action

meta :credits do |actor|
  actor.tell "This game was written by John Smith."
end

@param verb [Symbol] An imperative verb for the command @param queries [Array<Query::Base>] Filters for the command's tokens @yieldparam [Gamefic::Actor] @return [Class<Gamefic::Action>]

# File lib/gamefic/world/playbook.rb, line 101
def meta(verb, *queries, &proc)
  act = Action.subclass verb, *queries, meta: true, &proc
  add_action act
  act
end
respond(verb, *queries, &proc) click to toggle source

Create an Action that responds to a command. An Action uses the command argument to identify the imperative verb that triggers the action. It can also accept queries to tokenize the remainder of the input and filter for particular entities or properties. The block argument contains the code to be executed when the input matches all of the Action's criteria (i.e., verb and queries).

@example A simple Action.

respond :salute do |actor|
  actor.tell "Hello, sir!"
end
# The command "salute" will respond "Hello, sir!"

@example An Action that accepts a Character

respond :salute, Use.visible(Character) do |actor, character|
  actor.tell "#{The character} returns your salute."
end

@param verb [Symbol] An imperative verb for the command @param queries [Array<Query::Base>] Filters for the command's tokens @yieldparam [Gamefic::Actor] @return [Class<Gamefic::Action>]

# File lib/gamefic/world/playbook.rb, line 79
def respond(verb, *queries, &proc)
  act = Action.subclass verb, *queries, &proc
  add_action act
  act
end
validate(&block) click to toggle source

Add a block that determines whether an action can be executed.

# File lib/gamefic/world/playbook.rb, line 44
def validate &block
  @validators.push block
end
verbs() click to toggle source

An array of recognized verbs.

@return [Array<Symbol>]

# File lib/gamefic/world/playbook.rb, line 38
def verbs
  @commands.keys
end

Private Instance Methods

add_action(action) click to toggle source
# File lib/gamefic/world/playbook.rb, line 164
def add_action(action)
  @commands[action.verb] ||= []
  @commands[action.verb].push action
  generate_default_syntax action
end
add_syntax(syntax) click to toggle source
# File lib/gamefic/world/playbook.rb, line 188
def add_syntax syntax
  raise "No actions exist for \"#{syntax.verb}\"" if @commands[syntax.verb].nil?
  sort_syntaxes if @syntax_set.add?(syntax)
end
generate_default_syntax(action) click to toggle source
# File lib/gamefic/world/playbook.rb, line 170
def generate_default_syntax action
  user_friendly = action.verb.to_s.gsub(/_/, ' ')
  args = []
  used_names = []
  action.queries.each do |_c|
    num = 1
    new_name = ":var"
    while used_names.include? new_name
      num += 1
      new_name = ":var#{num}"
    end
    used_names.push new_name
    user_friendly += " #{new_name}"
    args.push new_name
  end
  add_syntax Syntax.new(user_friendly.strip, "#{action.verb} #{args.join(' ')}") unless action.verb.to_s.start_with?('_')
end
sort_and_reduce_actions(arr) click to toggle source
# File lib/gamefic/world/playbook.rb, line 193
def sort_and_reduce_actions arr
  arr.sort_by.with_index { |a, i| [a.rank, i] }.reverse.uniq
end
sort_syntaxes() click to toggle source
# File lib/gamefic/world/playbook.rb, line 197
def sort_syntaxes
  @syntaxes = @syntax_set.sort do |a, b|
    if a.token_count == b.token_count
      # For syntaxes of the same length, sort first word
      b.first_word <=> a.first_word
    else
      b.token_count <=> a.token_count
    end
  end
end