lib/gamefic/action.rb in gamefic-2.0.2 vs lib/gamefic/action.rb in gamefic-2.0.3

- old
+ new

@@ -1,11 +1,6 @@ module Gamefic - # Exception raised when the Action's proc arity is not compatible with the - # number of queries - class ActionArgumentError < ArgumentError - end - class Action # An array of objects on which the action will operate, e.g., an entity # that is a direct object of a command. # # @return [Array<Object>] @@ -52,30 +47,37 @@ # @return [Boolean] def meta? self.class.meta? end - def self.subclass verb, *q, meta: false, &block + # @param verb [Symbol] + # @param queries [Array<Gamefic::Query::Base>] + # @param meta [Boolean] + # @return [Class<Action>] + def self.subclass verb, *queries, meta: false, &block act = Class.new(self) do self.verb = verb self.meta = meta - q.each { |q| + queries.each do |q| add_query q - } + end on_execute &block end - if !block.nil? and act.queries.length + 1 != block.arity and block.arity > 0 - raise ActionArgumentError.new("Number of parameters is not compatible with proc arguments") + if !block.nil? && act.queries.length + 1 != block.arity && block.arity > 0 + raise ArgumentError.new("Number of parameters is not compatible with proc arguments") end act end class << self - def verb - @verb - end + attr_reader :verb + # The proc to call when the action is executed + # + # @return [Proc] + attr_reader :executor + def meta? @meta ||= false end def add_query q @@ -91,11 +93,11 @@ @executor = block end def signature # @todo This is clearly unfinished - "#{verb} #{queries.map{|m| m.signature}.join(', ')}" + "#{verb} #{queries.map {|m| m.signature}.join(', ')}" end # True if this action is not intended to be performed directly by a # character. # If the action is hidden, users should not be able to perform it with a @@ -105,66 +107,60 @@ # @return [Boolean] def hidden? verb.to_s.start_with?('_') end - # The proc to call when the action is executed - # - # @return [Proc] - def executor - @executor - end - + # @return [Integer] def rank if @rank.nil? @rank = 0 - queries.each { |q| + queries.each do |q| @rank += (q.rank + 1) - } + end @rank -= 1000 if verb.nil? end @rank end def valid? actor, objects return false if objects.length != queries.length i = 0 - queries.each { |p| + queries.each do |p| return false unless p.include?(actor, objects[i]) i += 1 - } + end true end + # Return an instance of this Action if the actor can execute it with the + # provided tokens, or nil if the tokens are invalid. + # + # @param action [Gamefic::Entity] + # @param tokens [Array<String>] + # @return [self, nil] def attempt actor, tokens - i = 0 result = [] matches = Gamefic::Query::Matches.new([], '', '') - queries.each { |p| - return nil if tokens[i].nil? and matches.remaining == '' + queries.each_with_index do |p, i| + return nil if tokens[i].nil? && matches.remaining == '' matches = p.resolve(actor, "#{matches.remaining} #{tokens[i]}".strip, continued: (i < queries.length - 1)) return nil if matches.objects.empty? - accepted = matches.objects.select{|o| p.accept?(o)} + accepted = matches.objects.select { |o| p.accept?(o) } return nil if accepted.empty? if p.ambiguous? result.push accepted else return nil if accepted.length != 1 result.push accepted.first end - i += 1 - } - self.new(actor, result) + end + new(actor, result) end protected - def verb= sym - @verb = sym - end + attr_writer :verb - def meta= bool - @meta = bool - end + attr_writer :meta end end end