Class: Demiurge::Agent
- Inherits:
-
ActionItem
- Object
- StateItem
- ActionItem
- Demiurge::Agent
- Defined in:
- lib/demiurge/agent.rb
Overview
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.
Direct Known Subclasses
Constant Summary
Constants inherited from ActionItem
Demiurge::ActionItem::ACTION_LEGAL_KEYS
Instance Attribute Summary
Attributes inherited from StateItem
Instance Method Summary collapse
-
#agent? ⇒ Boolean
An Agent is, indeed, an Agent.
-
#clear_intention_queue ⇒ void
Any queued actions waiting to occur will be discarded.
- #finished_init ⇒ Object
-
#initialize(*args) ⇒ Agent
constructor
A new instance of Agent.
-
#intentions_for_next_step ⇒ Array<Intention>
Calculate the agent's intentions for the following tick.
-
#move_to_position(pos, options = {}) ⇒ void
This method will move the agent and notify about that change.
-
#queue_action(action_name, *args) ⇒ Integer
Queue an action to be run after previous actions are complete, and when the agent is no longer busy from taking them.
Methods inherited from ActionItem
#__state_internal, #get_action, #get_actions_with_tags, #location, #location_name, #position, #register_actions, #run_action, #zone, #zone_name
Methods inherited from StateItem
from_name_type, #get_structure, #state, #state_type, #zone?
Constructor Details
#initialize(*args) ⇒ Agent
Returns a new instance of Agent
18 19 20 21 22 |
# File 'lib/demiurge/agent.rb', line 18 def initialize(*args) super state["queued_actions"] ||= [] state["queue_number"] ||= 0 end |
Instance Method Details
#agent? ⇒ Boolean
An Agent is, indeed, an Agent.
34 35 36 |
# File 'lib/demiurge/agent.rb', line 34 def agent? true end |
#clear_intention_queue ⇒ void
This method returns an undefined value.
Any queued actions waiting to occur will be discarded.
109 110 111 112 |
# File 'lib/demiurge/agent.rb', line 109 def clear_intention_queue state.delete "queued_actions" nil end |
#finished_init ⇒ Object
24 25 26 27 28 |
# 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 ⇒ Array<Intention>
Calculate the agent's intentions for the following tick. These Intentions can potentially trigger other Intentions.
83 84 85 86 |
# File 'lib/demiurge/agent.rb', line 83 def intentions_for_next_step agent_action = AgentInternal::AgentActionIntention.new(@name, engine) super + [@agent_maintenance, agent_action] end |
#move_to_position(pos, options = {}) ⇒ void
This method returns an undefined value.
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.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/demiurge/agent.rb', line 49 def move_to_position(pos, = {}) old_pos = self.position old_loc = self.location_name old_zone_name = self.zone_name expected_new_loc = pos.split("#")[0] if old_loc && !self.location raise ::Demiurge::Errors::LocationNameNotFoundError.new("Item #{@name.inspect} has an old location name (#{old_loc.inspect}) with no matching location object!", { "item_name" => @name, "location_name" => old_loc, "moving_to" => pos }, execution_context: @engine.execution_context); end if old_loc != nil && expected_new_loc == old_loc self.location.item_change_position(self, old_pos, pos) elsif old_loc != nil # 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: }, type: Demiurge::Notifications::MoveTo, zone: self.zone_name, location: self.location_name, actor: @name, include_context: true) end |
#queue_action(action_name, *args) ⇒ Integer
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.
97 98 99 100 101 102 103 |
# File 'lib/demiurge/agent.rb', line 97 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 |