class Gamefic::Response
A proc to be executed in response to a command that matches its verb and queries.
Attributes
@return [Array<Query::Base, Query::Text
>]
@return [Symbol]
Public Class Methods
@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
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
# File lib/gamefic/response.rb, line 64 def execute *args @callback.run(*args) end
# File lib/gamefic/response.rb, line 94 def inspect "#<#{self.class} #{([verb] + queries).map(&:inspect).join(', ')}>" end
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
# File lib/gamefic/response.rb, line 68 def precision @precision ||= calculate_precision end
# File lib/gamefic/response.rb, line 39 def syntax @syntax ||= generate_default_syntax end
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
# File lib/gamefic/response.rb, line 125 def calculate_precision total = queries.sum(&:precision) total -= 1000 unless verb total end
# 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
# 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
# File lib/gamefic/response.rb, line 100 def log_and_discard Gamefic.logger.info "Discarded #{inspect}" nil end
# 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
# 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