Class: Demiurge::AgentInternal::AgentActionIntention Private
- Inherits:
-
Demiurge::ActionItemInternal::ActionIntention
- Object
- Intention
- Demiurge::ActionItemInternal::ActionIntention
- Demiurge::AgentInternal::AgentActionIntention
- Defined in:
- lib/demiurge/agent.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
There is a bit of weirdness in how this intention handles #allowed? and #offer. We want to be able to queue an action on the same tick that we execute it if the agent is idle. So we count this intention as #allowed? even if the queue is empty, then silent-cancel the intention during #offer if nobody has added anything to it. If you see a lot of cancel notifications from this object with "silent" set, now you know why.
An AgentActionIntention is how the agent takes queued actions each tick.
Instance Attribute Summary collapse
-
#action_name ⇒ String
readonly
private
The queued action name this Intention will next take.
-
#agent ⇒ StateItem
readonly
private
The agent to whom this Intention applies.
Attributes inherited from Demiurge::ActionItemInternal::ActionIntention
Instance Method Summary collapse
-
#allowed? ⇒ Boolean
private
This action is allowed if the agent is not busy, or will become not-busy soon.
-
#apply ⇒ Object
private
If the agent can do so, take the action in question.
-
#apply_notification ⇒ void
private
Send out a notification to indicate this ActionIntention was applied.
-
#cancel_notification ⇒ void
private
Send out a notification to indicate this ActionIntention was cancelled.
-
#initialize(name, engine) ⇒ AgentActionIntention
constructor
private
Constructor.
-
#offer ⇒ Object
private
An action being pulled from the action queue is offered normally.
Methods inherited from Intention
#cancel, #cancelled?, #try_apply
Constructor Details
#initialize(name, engine) ⇒ AgentActionIntention
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Constructor. Takes an agent name and an engine
167 168 169 170 171 172 |
# File 'lib/demiurge/agent.rb', line 167 def initialize(name, engine) super(engine, name, "") @agent = engine.item_by_name(name) raise ::Demiurge::Errors::NoSuchAgentError.new("No such agent as #{name.inspect} found in AgentActionIntention!", "agent" => name, execution_context: engine.execution_context) unless @agent end |
Instance Attribute Details
#action_name ⇒ String (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns The queued action name this Intention will next take
164 165 166 |
# File 'lib/demiurge/agent.rb', line 164 def action_name @action_name end |
#agent ⇒ StateItem (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns The agent to whom this Intention applies
162 163 164 |
# File 'lib/demiurge/agent.rb', line 162 def agent @agent end |
Instance Method Details
#allowed? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This action is allowed if the agent is not busy, or will become not-busy soon
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/demiurge/agent.rb', line 193 def allowed? # If the agent's busy state will clear this turn, this action # could happen. We intentionally don't send a "disallowed" # notification for the action. It's not cancelled, nor is it # dispatched successfully. It's just waiting for a later tick to # do one of those two things. return false if @agent.state["busy"] > 1 # A dilemma: if we cancel now when no actions are queued, then # any action queued this turn (e.g. from an # EveryXActionsIntention) won't be executed -- we said this # intention wasn't happening. If we *don't* return false in the # "allowed?" phase then we'll wind up sending out a cancel # notice every turn when there are no actions. So we add a # "silent" info option to the normal-every-turn cancellations, # but we *do* allow-then-cancel even in perfectly normal # circumstances. true end |
#apply ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
If the agent can do so, take the action in question.
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/demiurge/agent.rb', line 214 def apply unless agent.state["busy"] > 0 || agent.state["queued_actions"].empty? # Pull the first entry off the action queue queue = @agent.state["queued_actions"] if queue && queue.size > 0 if @action_queue_number != queue[0][2] @engine.admin_warning("Somehow the agent's action queue has gotten screwed up mid-offer!", "agent" => @name) else queue.shift # Remove the queue entry end end agent.run_action(@action_name, *@action_args, current_intention: self) agent.state["busy"] += (@action_struct["busy"] || 1) end end |
#apply_notification ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Send out a notification to indicate this ActionIntention was applied.
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/demiurge/agent.rb', line 261 def apply_notification @engine.send_notification({ id: @intention_id, intention_type: self.class.to_s, queue_number: @action_queue_number, action_name: @action_name, action_args: @action_args, }, type: Demiurge::Notifications::IntentionApplied, zone: @item.zone_name, location: @item.location_name, actor: @item.name, include_context: true) nil end |
#cancel_notification ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Send out a notification to indicate this ActionIntention was cancelled. If "silent" is set to true in the cancellation info, no notification will be sent.
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/demiurge/agent.rb', line 236 def cancel_notification return if @cancelled_info && @cancelled_info["silent"] @engine.send_notification({ reason: @cancelled_reason, by: @cancelled_by, id: @intention_id, intention_type: self.class.to_s, info: @cancelled_info, queue_number: @action_queue_number, action_name: @action_name, action_args: @action_args, }, type: Demiurge::Notifications::IntentionCancelled, zone: @item.zone_name, location: @item.location_name, actor: @item.name, include_context: true) nil end |
#offer ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
An action being pulled from the action queue is offered normally.
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/demiurge/agent.rb', line 175 def offer # Don't offer the action if it's going to be a no-op. if @agent.state["busy"] > 0 # See comment on "silent" in #allowed? below. self.cancel "Agent #{@name.inspect} was too busy to act (#{@agent.state["busy"]}).", "silent" => "true" return elsif @agent.state["queued_actions"].empty? self.cancel "Agent #{@name.inspect} had no actions during the 'offer' phase.", "silent" => "true" return end # Now offer the agent's action via the usual channels action = @agent.state["queued_actions"][0] @action_name, @action_args, @action_queue_number = *action @action_struct = @agent.get_action(@action_name) super end |