class Gamefic::Response

A proc to be executed in response to a command that matches its verb and queries.

Attributes

queries[R]

@return [Array<Query::Base, Query::Text>]

verb[R]

@return [Symbol]

Public Class Methods

new(verb, narrative, *args, meta: false, &block) click to toggle source

@param verb [Symbol] @param narrative [Narrative] @param args [Array<Object>] @param meta [Boolean] @param block [Proc]

# File lib/gamefic/response.rb, line 19
def initialize verb, narrative, *args, meta: false, &block
  @verb = verb
  @queries = map_queries(args, narrative)
  @meta = meta
  @callback = Callback.new(narrative, block)
end

Public Instance Methods

accept?(actor, command) click to toggle source

True if the Response can be executed for the given actor and command.

@param actor [Active] @param command [Command]

# File lib/gamefic/response.rb, line 58
def accept? actor, command
  command.verb == verb &&
    command.arguments.length == queries.length &&
    queries.zip(command.arguments).all? { |query, argument| query.accept?(actor, argument) }
end
attempt(actor, command) click to toggle source

Return an Action if the Response can accept the actor’s command.

@param actor [Entity] @param command [Command] @return [Action, nil]

# File lib/gamefic/response.rb, line 48
def attempt actor, command
  return nil unless accept?(actor, command)

  Action.new(actor, command.arguments, self)
end
execute(*args) click to toggle source
# File lib/gamefic/response.rb, line 64
def execute *args
  @callback.run(*args)
end
hidden?() click to toggle source
# File lib/gamefic/response.rb, line 35
def hidden?
  @hidden ||= verb.to_s.start_with?('_')
end
inspect() click to toggle source
# File lib/gamefic/response.rb, line 94
def inspect
  "#<#{self.class} #{([verb] + queries).map(&:inspect).join(', ')}>"
end
meta?() click to toggle source

The ‘meta?` flag is just a way for authors to identify responses that serve a purpose other than performing in-game actions. Out-of-game responses can include features like displaying help documentation or listing credits.

# File lib/gamefic/response.rb, line 31
def meta?
  @meta
end
precision() click to toggle source
# File lib/gamefic/response.rb, line 68
def precision
  @precision ||= calculate_precision
end
syntax() click to toggle source
# File lib/gamefic/response.rb, line 39
def syntax
  @syntax ||= generate_default_syntax
end
to_command(actor, expression) click to toggle source

Turn an actor and an expression into a command by matching the expression’s tokens to queries. Return nil if the expression could not be matched.

@param actor [Actor] @param expression [Expression] @return [Command, nil]

# File lib/gamefic/response.rb, line 79
def to_command actor, expression
  return log_and_discard unless expression.verb == verb && expression.tokens.length <= queries.length

  results = filter(actor, expression)
  return log_and_discard unless results

  Gamefic.logger.info "Accepted #{inspect}"
  Command.new(
    verb,
    results.map(&:match),
    results.sum(&:strictness),
    precision
  )
end

Private Instance Methods

calculate_precision() click to toggle source
# File lib/gamefic/response.rb, line 125
def calculate_precision
  total = queries.sum(&:precision)
  total -= 1000 unless verb
  total
end
filter(actor, expression) click to toggle source
# File lib/gamefic/response.rb, line 105
def filter actor, expression
  remainder = ''
  result = queries.zip(expression.tokens)
                  .map do |query, token|
                    token = "#{remainder} #{token}".strip
                    result = query.filter(actor, token)
                    return nil unless result.match

                    remainder = result.remainder
                    result
                  end
  result if remainder.empty?
end
generate_default_syntax() click to toggle source
# File lib/gamefic/response.rb, line 119
def generate_default_syntax
  args = queries.length.times.map { |num| num.zero? ? ':var' : ":var#{num + 1}" }
  tmpl = "#{verb} #{args.join(' ')}".strip
  Syntax.new(tmpl.gsub('_', ' '), tmpl)
end
log_and_discard() click to toggle source
# File lib/gamefic/response.rb, line 100
def log_and_discard
  Gamefic.logger.info "Discarded #{inspect}"
  nil
end
map_queries(args, narrative) click to toggle source
# File lib/gamefic/response.rb, line 131
def map_queries args, narrative
  args.map do |arg|
    select_query(arg, narrative).tap { |qry| qry.narrative = narrative }
  end
end
select_query(arg, narrative) click to toggle source
# File lib/gamefic/response.rb, line 137
def select_query arg, narrative
  case arg
  when Entity, Class, Module, Proc, Proxy, Proxy::Base
    narrative.available(arg)
  when String, Regexp
    narrative.plaintext(arg)
  when Query::Base, Query::Text
    arg
  else
    raise ArgumentError, "invalid argument in response: #{arg.inspect}"
  end
end