Class: Demiurge::TiledLocation

Inherits:
Location show all
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.

Since:

  • 0.3.0

Direct Known Subclasses

Demiurge::Tmx::TmxLocation

Constant Summary

Constants inherited from ActionItem

ActionItem::ACTION_LEGAL_KEYS

Instance Attribute Summary

Attributes inherited from StateItem

#engine, #name

Class Method Summary collapse

Instance Method Summary collapse

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

Parameters:

  • pos (String)

    The position string to parse

Returns:

  • (Array<Integer,Integer>)

    The x, y coordinates

Since:

  • 0.2.0



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

Parameters:

  • pos (String)

    The position string to parse

Returns:

  • (Array<String,Integer,Integer>)

    The location name and x, y coordinates

Since:

  • 0.2.0



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

Since:

  • 0.3.0



232
233
234
235
236
237
238
239
# File 'lib/demiurge/location.rb', line 232

def adjacent_positions(pos, options = {})
  location, pos_spec = pos.split("#", 2)
  loc = @engine.item_by_name(location)
  x, y = pos_spec.split(",").map(&:to_i)

  shape = options[: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

Return a legal position in this location

Returns:

  • (String)

    A legal position string

Since:

  • 0.3.0



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.

Parameters:

  • agent (Demiurge::Agent)

    The agent being checked

  • position (String)

    The position being checked

Returns:

  • (Boolean)

    Whether the position can accomodate the agent

Since:

  • 0.2.0



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.

Parameters:

  • left_x (Integer)

    The lower (leftmost) X coordinate

  • upper_y (Integer)

    The higher (upper) Y coordinate

  • width (Integer)

    How wide the checked object is

  • height (Integer)

    How high the checked object is

Returns:

  • (Boolean)

    Whether the object can be accomodated

Since:

  • 0.3.0



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.

Parameters:

  • left_x (Integer)

    The lower (leftmost) X coordinate

  • upper_y (Integer)

    The higher (upper) Y coordinate

Returns:

  • (Boolean)

    Whether the object can be accomodated

Since:

  • 0.3.0



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.

Parameters:

  • item (String)

    The item changing position

  • old_pos (String)

    The position string the item is moving from

  • new_pos (String)

    The position string the item is moving to

Since:

  • 0.2.0



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

Parameters:

  • x (Integer)

    The X coordinate

  • y (Integer)

    The Y coordinate

Returns:

  • (Boolean)

    Whether the coordinate is valid

Since:

  • 0.3.0



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.

Parameters:

  • pos (String)

    The position being checked

Returns:

  • (Boolean)

    Whether the position is valid

Since:

  • 0.2.0



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