class Demiurge::Container

Container is the parent class of Locations, Zones and other items that can contain items.

Public Class Methods

new(name, engine, state) click to toggle source

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

Calls superclass method Demiurge::ActionItem::new
# File lib/demiurge/container.rb, line 13
def initialize(name, engine, state)
  super
  state["contents"] ||= []
end

Public Instance Methods

can_accomodate_agent?(agent, position) click to toggle source

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
contents() click to toggle source

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
contents_names() click to toggle source

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
ensure_contains(item_name) click to toggle source

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
ensure_does_not_contain(item_name) click to toggle source

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
finished_init() click to toggle source

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
intentions_for_next_step() click to toggle source

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

# 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
item_change_location(item, old_pos, new_pos) click to toggle source

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
item_change_position(item, old_pos, new_pos) click to toggle source

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
move_item_inside(item) click to toggle source

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
receive_offer(action_name, intention) click to toggle source

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