class Demiurge::Container
Container
is the parent class of Locations, Zones and other items that can contain items.
Public Class Methods
Constructor - set up contents
@param name [String] The Engine-unique item name @param engine [Demiurge::Engine] The Engine
this item is part of @param state [Hash] State data to initialize from @return [void] @since 0.0.1
Demiurge::ActionItem::new
# File lib/demiurge/container.rb, line 13 def initialize(name, engine, state) super state["contents"] ||= [] end
Public Instance Methods
This method determines if a given agent can exist at the specified position inside this container. By default, a container can accomodate anyone or anything. Subclass to change this behavior. This should take into account the size, shape and current condition of the agent, and might take into account whether the agent has certain movement abilities.
@param agent [Demiurge::Agent] The agent being checked @param position [String] The position being checked within this container @return [Boolean] Whether the agent can exist at that position @since 0.0.1
# File lib/demiurge/container.rb, line 183 def can_accomodate_agent?(agent, position) true end
Gets the contents array as items, not names.
@return [Array<Demiurge::StateItem>] The array of items contained in this item @since 0.3.0
# File lib/demiurge/container.rb, line 31 def contents state["contents"].map { |name| @engine.item_by_name(name) } end
Gets the array of item names of all items contained in this container.
@return [Array<String>] The array of item names @since 0.0.1
# File lib/demiurge/container.rb, line 23 def contents_names state["contents"] end
This makes sure the given item name is listed in the container's contents. It does not make sure that the item currently exists, or that its position is set to this container.
@see move_item_inside
@see ensure_does_not_contain
@param item_name [String] The item name to ensure is listed in the container @return [void] @since 0.0.1
# File lib/demiurge/container.rb, line 58 def ensure_contains(item_name) raise("Pass only item names to ensure_contains!") unless item_name.is_a?(String) @state["contents"] |= [item_name] nil end
This makes sure the given item name is not listed in the container's contents. It does not make sure the item exists, nor do anything with the item's position.
@see ensure_contains
@see move_item_inside
@param item_name [String] The item name @return [void] @since 0.0.1
# File lib/demiurge/container.rb, line 73 def ensure_does_not_contain(item_name) raise("Pass only item names to ensure_does_not_contain!") unless item_name.is_a?(String) @state["contents"] -= [item_name] nil end
The finished_init
hook is called after all items are loaded. For containers, this makes sure all items set as contents of this container also have it correctly set as their position.
@return [void] @since 0.0.1
# File lib/demiurge/container.rb, line 41 def finished_init # Can't move all items inside until they all exist, which isn't guaranteed until init is finished. state["contents"].each do |item| move_item_inside(@engine.item_by_name(item)) end nil end
This determines the intentions for the next tick for this container and for all items inside it.
@return [Array<Intention>] The array of intentions for next tick @since 0.0.1
Demiurge::ActionItem#intentions_for_next_step
# File lib/demiurge/container.rb, line 192 def intentions_for_next_step intentions = super @state["contents"].each do |item_name| item = @engine.item_by_name(item_name) intentions += item.intentions_for_next_step end intentions end
This is a callback to indicate that an item has changed from one location to another. This will normally require removing the item from its first location and adding it to a new location. A different callback is called when the item changes position within a single location.
@see item_change_position
@param item [Demiurge::StateItem] The item changing position @param old_pos [String] The pre-movement position, which is current when this is called @param new_pos [String] The post-movement position, which should be current when this method completes @return [void] @since 0.0.1
# File lib/demiurge/container.rb, line 129 def item_change_location(item, old_pos, new_pos) old_loc = old_pos.split("#")[0] old_loc_item = @engine.item_by_name(old_loc) old_loc_item.ensure_does_not_contain(item.name) new_loc = new_pos.split("#")[0] new_loc_item = @engine.item_by_name(new_loc) new_loc_item.ensure_contains(item.name) item.state["position"] = new_pos old_zone = old_loc_item.zone_name new_zone = new_loc_item.zone_name if new_zone != old_zone item.state["zone"] = new_zone end nil end
This is a callback to indicate that an item has changed position, but remains inside this location. Other than changing the item's position state variable, this may not require any changes. A different callback is called when the item changes from one location to another.
@see item_change_location
@param item [Demiurge::StateItem] The item changing position @param old_pos [String] The pre-movement position, which is current when this is called @param new_pos [String] The post-movement position, which should be current when this method completes @return [void] @since 0.0.1
# File lib/demiurge/container.rb, line 112 def item_change_position(item, old_pos, new_pos) item.state["position"] = new_pos nil end
This makes sure the given StateItem
is contained in this container. It sets the item's position to be in this container, and if there is an old location it attempts to properly remove the item from it.
@see Demiurge::Agent#move_to_position
@param item [Demiurge::StateItem] The item to be moved into this container @return [void] @since 0.0.1
# File lib/demiurge/container.rb, line 88 def move_item_inside(item) old_pos = item.position if old_pos old_loc_name = old_pos.split("#")[0] old_loc = @engine.item_by_name(old_loc_name) old_loc.ensure_does_not_contain(item.name) end @state["contents"] |= [ item.name ] nil end
When an item has an {Demiurge::Intention}, that Intention
is offered in order to be potentially modified or cancelled by environmental effects. For instance, a room might have a muddy floor that slows walking or prevents running, or an icy floor that causes sliding around. That offer is normally coordinated through the item's location. The location will receive this callback ({#receive_offer}) and make appropriate modifications to the Intention
. Any other items or agents that want to modify the Intention
will have to coordinate with the appropriate item location.
@see file:CONCEPTS.md @param action_name [String] The name of the action for this Intention
. @param intention [Demiurge::Intention] The Intention
being offered @return [void] @since 0.0.1
# File lib/demiurge/container.rb, line 162 def receive_offer(action_name, intention) # Run handlers, if any on_actions = @state["on_action_handlers"] if on_actions && (on_actions[action_name] || on_actions["all"]) run_action(on_actions["all"], intention, current_intention: intention) if on_actions["all"] run_action(on_actions[action_name], intention, current_intention: intention) if on_actions[action_name] end nil end