Class: Demiurge::TiledLocation
- Defined in:
- lib/demiurge/location.rb
Overview
A TiledLocation is a location that uses #x,y format for positions for a 2D grid in the location. Something like a TMX file defines a TiledLocation, but so does an infinitely generated tiled space.
Direct Known Subclasses
Constant Summary
Constants inherited from ActionItem
Instance Attribute Summary
Attributes inherited from StateItem
Class Method Summary collapse
-
.position_to_coords(pos) ⇒ Array<Integer,Integer>
Parse a tiled position string and return the X and Y tile coordinates.
-
.position_to_loc_coords(pos) ⇒ Array<String,Integer,Integer>
Parse a tiled position string and return the location name and the X and Y tile coordinates.
Instance Method Summary collapse
-
#adjacent_positions(pos, options = {}) ⇒ Object
Return the list of valid adjacent positions from this one.
-
#any_legal_position ⇒ String
Return a legal position in this location.
-
#can_accomodate_agent?(agent, position) ⇒ Boolean
Determine whether this position can accomodate the given agent's shape and size.
-
#can_accomodate_dimensions?(left_x, upper_y, width, height) ⇒ Boolean
Whether the location can accomodate an object of this size.
-
#can_accomodate_shape?(left_x, upper_y, shape) ⇒ Boolean
Determine whether this coordinate location can accomodate an item of the given shape.
-
#item_change_position(item, old_pos, new_pos) ⇒ void
When an item changes position in a TiledLocation, check if the new position leads out an exit.
-
#valid_coordinate?(x, y) ⇒ Boolean
Whether the coordinate is valid.
-
#valid_position?(pos) ⇒ Boolean
This just determines if the position is valid at all.
Methods inherited from Location
#add_exit, #exits, #finished_init, #initialize, #location, #location_name, #zone, #zone_name
Methods inherited from Container
#contents, #contents_names, #ensure_contains, #ensure_does_not_contain, #finished_init, #initialize, #intentions_for_next_step, #item_change_location, #move_item_inside, #receive_offer
Methods inherited from ActionItem
#__state_internal, #finished_init, #get_action, #get_actions_with_tags, #initialize, #intentions_for_next_step, #location, #location_name, #position, #register_actions, #run_action, #zone, #zone_name
Methods inherited from StateItem
#agent?, from_name_type, #get_structure, #initialize, #intentions_for_next_step, #state, #state_type, #zone?
Constructor Details
This class inherits a constructor from Demiurge::Location
Class Method Details
.position_to_coords(pos) ⇒ Array<Integer,Integer>
Parse a tiled position string and return the X and Y tile coordinates
107 108 109 110 |
# File 'lib/demiurge/location.rb', line 107 def self.position_to_coords(pos) _, x, y = position_to_loc_coords(pos) return x, y end |
.position_to_loc_coords(pos) ⇒ Array<String,Integer,Integer>
Parse a tiled position string and return the location name and the X and Y tile coordinates
117 118 119 120 121 122 123 124 125 |
# File 'lib/demiurge/location.rb', line 117 def self.position_to_loc_coords(pos) loc, coords = pos.split("#",2) if coords x, y = coords.split(",") return loc, x.to_i, y.to_i else return loc, nil, nil end end |
Instance Method Details
#adjacent_positions(pos, options = {}) ⇒ Object
Return the list of valid adjacent positions from this one
232 233 234 235 236 237 238 239 |
# File 'lib/demiurge/location.rb', line 232 def adjacent_positions(pos, = {}) location, pos_spec = pos.split("#", 2) loc = @engine.item_by_name(location) x, y = pos_spec.split(",").map(&:to_i) shape = [:shape] || "humanoid" [[x - 1, y], [x + 1, y], [x, y - 1], [x, y + 1]].select { |xp, yp| loc.can_accomodate_shape?(xp, yp, shape) } end |
#any_legal_position ⇒ String
Return a legal position in this location
227 228 229 |
# File 'lib/demiurge/location.rb', line 227 def any_legal_position "#{@name}#0,0" end |
#can_accomodate_agent?(agent, position) ⇒ Boolean
Determine whether this position can accomodate the given agent's shape and size.
172 173 174 175 176 177 |
# File 'lib/demiurge/location.rb', line 172 def can_accomodate_agent?(agent, position) loc, x, y = TiledLocation.position_to_loc_coords(position) raise "Location #{@name.inspect} asked about different location #{loc.inspect} in can_accomodate_agent!" if loc != @name shape = agent.state["shape"] || "humanoid" can_accomodate_shape?(x, y, shape) end |
#can_accomodate_dimensions?(left_x, upper_y, width, height) ⇒ Boolean
Whether the location can accomodate an object of this size.
197 198 199 |
# File 'lib/demiurge/location.rb', line 197 def can_accomodate_dimensions?(left_x, upper_y, width, height) true end |
#can_accomodate_shape?(left_x, upper_y, shape) ⇒ Boolean
Determine whether this coordinate location can accomodate an item of the given shape.
For now, don't distinguish between walkable/swimmable or whatever, just say a collision value of 0 means valid, everything else is invalid.
212 213 214 215 216 217 218 219 220 221 |
# File 'lib/demiurge/location.rb', line 212 def can_accomodate_shape?(left_x, upper_y, shape) case shape when "humanoid" return can_accomodate_dimensions?(left_x, upper_y, 2, 1) when "tiny" return can_accomodate_dimensions?(left_x, upper_y, 1, 1) else raise "Unknown shape #{shape.inspect} passed to can_accomodate_shape!" end end |
#item_change_position(item, old_pos, new_pos) ⇒ void
This method returns an undefined value.
When an item changes position in a TiledLocation, check if the new position leads out an exit. If so, send them where the exit leads instead.
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/demiurge/location.rb', line 136 def item_change_position(item, old_pos, new_pos) exit = @state["exits"].detect { |e| e["from"] == new_pos } return super unless exit # No exit? Do what you were going to. # Going to hit an exit? Cancel this motion and enqueue an # intention to do so? Or just send them through? If the former, # it's very hard to unblockably pass through an exit, even if # that's what's wanted. If the latter, it's very hard to make # going through an exit blockable. # Eh, just send them through for now. We'll figure out how to # make detecting and blocking exit intentions easy later. item_change_location(item, old_pos, exit["to"]) end |
#valid_coordinate?(x, y) ⇒ Boolean
Whether the coordinate is valid
185 186 187 |
# File 'lib/demiurge/location.rb', line 185 def valid_coordinate?(x,y) true end |
#valid_position?(pos) ⇒ Boolean
This just determines if the position is valid at all. It does not check walkable/swimmable or even if it's big enough for a humanoid to stand in.
159 160 161 162 163 164 |
# File 'lib/demiurge/location.rb', line 159 def valid_position?(pos) return false unless pos[0...@name.size] == @name return false unless pos[@name.size] == "#" x, y = pos[(@name.size + 1)..-1].split(",", 2).map(&:to_i) valid_coordinate?(x, y) end |