class Demiurge::Agent

Agents correspond roughly to “mobiles” in many games. An agent isn't particularly different from other Demiurge objects, but it's useful to have some helper classes for things like pathfinding. Also, humans expect agents to have some finite ability to perform actions over time, so it's nice to regulate how much an agent can get done and how “busy” it is. This keeps an AI agent from just queueing up 30 move intentions and crossing the room in a single tick, for instance. It does not keep that same AI from having an intentional 30-square move that works in a single tick, but it slows the rate of actions. Agents get a single “real” intention, unlike, say, rooms, which can have lots going on at once.

@since 0.0.1

Public Class Methods

new(*args) click to toggle source
Calls superclass method Demiurge::ActionItem::new
# File lib/demiurge/agent.rb, line 18
def initialize(*args)
  super
  state["queued_actions"] ||= []
  state["queue_number"] ||= 0
end

Public Instance Methods

agent?() click to toggle source

An Agent is, indeed, an Agent.

@return [Boolean] Return true for Agent and its subclasses. @since 0.0.1

# File lib/demiurge/agent.rb, line 34
def agent?
  true
end
clear_intention_queue() click to toggle source

Any queued actions waiting to occur will be discarded.

@return [void] @since 0.0.1

# File lib/demiurge/agent.rb, line 103
def clear_intention_queue
  state.delete "queued_actions"
  nil
end
finished_init() click to toggle source
Calls superclass method Demiurge::ActionItem#finished_init
# File lib/demiurge/agent.rb, line 24
def finished_init
  super
  @agent_maintenance = AgentInternal::AgentMaintenanceIntention.new(engine, @name)
  state["busy"] ||= 0 # By default, start out idle.
end
intentions_for_next_step() click to toggle source

Calculate the agent's intentions for the following tick. These Intentions can potentially trigger other Intentions.

@return [Array<Intention>] The Intentions for the (first part of the) following tick. @since 0.0.1

# File lib/demiurge/agent.rb, line 77
def intentions_for_next_step
  agent_action = AgentInternal::AgentActionIntention.new(@name, engine)
  super + [@agent_maintenance, agent_action]
end
move_to_position(pos, options = {}) click to toggle source

This method will move the agent and notify about that change. It doesn't use an intention or an agent's action queue, and it doesn't wait for a tick to happen. It just does it. The method does handle exits and generally allows the location to respond. But it's assumed that the offer cycle, if it needs to happen, has happened already.

@param pos [String] A position string to move to @param options [Hash] A hash of how to do the movement; Demiurge doesn't internally use this hash, but your World Files or display library may do so @return [void] @since 0.0.1

# File lib/demiurge/agent.rb, line 49
def move_to_position(pos, options = {})
  old_pos = self.position
  old_loc = self.location_name
  old_zone_name = self.zone_name
  expected_new_loc = pos.split("#")[0]

  if expected_new_loc == old_loc
    self.location.item_change_position(self, old_pos, pos)
  else
    # This also handles zone changes.
    self.location.item_change_location(self, old_pos, pos)
  end
  # We're not guaranteed to wind up where we expected, so get the
  # new location *after* item_change_location or
  # item_change_position.
  new_loc = self.location_name

  @engine.send_notification({ old_position: old_pos, old_location: old_loc, new_position: self.position, new_location: new_loc },
                              type: Demiurge::Notifications::MoveFrom, zone: old_zone_name, location: old_loc, actor: @name, include_context: true)
  @engine.send_notification({ old_position: old_pos, old_location: old_loc, new_position: self.position, new_location: new_loc, options: options },
                              type: Demiurge::Notifications::MoveTo, zone: self.zone_name, location: self.location_name, actor: @name, include_context: true)
end
queue_action(action_name, *args) click to toggle source

Queue an action to be run after previous actions are complete, and when the agent is no longer busy from taking them. The action queue entry is assigned a unique-per-agent queue number, which is returned from this action.

@param action_name [String] The name of the action to take when possible @param args [Array] Additional arguments to pass to the action's code block @return [Integer] Returns the queue number for this action - note that queue numbers are only unique per-agent @since 0.0.1

# File lib/demiurge/agent.rb, line 91
def queue_action(action_name, *args)
  raise ::Demiurge::Errors::NoSuchActionError.new("Not an action: #{action_name.inspect}!", { "action_name" => action_name },
                                                  execution_context: @engine.execution_context) unless get_action(action_name)
  state["queue_number"] += 1
  state["queued_actions"].push([action_name, args, state["queue_number"]])
  state["queue_number"]
end