class Gamefic::World::Playbook
A collection of rules for performing commands.
Attributes
An array of available syntaxes.
@return [Array<Gamefic::Syntax>]
An array of defined validators.
@return [Array<Proc>]
Public Class Methods
@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
An array of available actions.
@return [Array<Gamefic::Action>]
# File lib/gamefic/world/playbook.rb, line 31 def actions @commands.values.flatten end
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
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
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
# File lib/gamefic/world/playbook.rb, line 157 def freeze @commands.freeze @syntaxes.freeze end
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
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
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
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
An array of recognized verbs.
@return [Array<Symbol>]
# File lib/gamefic/world/playbook.rb, line 38 def verbs @commands.keys end
Private Instance Methods
# 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
# 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
# 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
# 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
# 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