GridObjects#
In this section we describe the grid-object protocol, the grid-object registry, and how to write your own custom grid-objects.
The GridObject Protocol#
A grid-object is a type of python class which represents the contents of a
Grid
. A grid-object needs to inherit from
GridObject
and define some required
attributes, properties, and classmethods.
- class GridObject(*args, **kwargs)[source]
Represents the contents of a grid cell
- abstract property color: gym_gridverse.grid_object.Color
Color of this grid-object
- Return type
- abstract property blocks_movement: bool
Whether this grid-object blocks the agent from moving on it
- Return type
- abstract property blocks_vision: bool
Whether this grid-object blocks the agent’s vision.
- Return type
- abstract classmethod can_be_represented_in_state()[source]
True iff
state_index
fully represents the grid-object state.GridObjects may have an internal state which is not fully representable by a single integer
state_index
, e.g., aBox
contains a reference to anotherGridObject
as its content. The unfortunate implication is that thisGridObject
(and, by extension, any Grido or Environment which contains this type ofGridObject
) cannot produce a truly fully observable State representation, which becomes disallowed. However, the GridObject, Grid, and Environment may still be used to represent partially observable control tasks.- Return type
The GridObject Registry#
The grid_object
module contains some pre-defined
grid-objects and the
grid_object_registry
, a list-like object
through which to register and retrieve grid-objects. Grid-objects are
automatically registered through inheritance from
GridObject
.
grid_object_registry
has a
names()
method which
returns the names of registered grid-object classes, and a
from_name()
method which
returns the grid-object class associated with a name.
Custom GridObjects#
Custom grid-objects can be defined so long as they satisfy some basic rules; A custom grid-object:
MUST define the
state_index
,color
,blocks_movement
,blocks_vision
, andholdable
attributes as either class attributes, instance attributes, or instance properties.MUST implement the
num_states()
andcan_be_represented_in_state()
class methods.
Tip
We advise implementing each of the
state_index
,
color
,
blocks_movement
,
blocks_vision
, and
holdable
attributes as:
class attributes if all instances of the same grid-object class should have the same constant value, e.g.,
holdable
is implemented as a class attribute because doors are never holdable.instance attributes if different instances of the same grid-object class can have different values, but the value associated with each instances is constant and does not change, e.g.,
color
is implemented as an instance attribute because doors can have different colors, but they don’t change colors.properties if different instances of the same grid-boject class can have different values, and the value associated with each instance can also vary, e.g.,
state_index
,blocks_movement
, andblocks_vision
are impemented as properties because they will depend on whether the door is open or closed, which is determined by a separatestate
attribute.
Attention
If any of the grid-object attributes are implemented as instance attributes,
you’ll need to overwrite the respective
GridObject
abstract property. This
can be done by simply specifying a class-level typehint:
class SomeColoredGridObject(GridObject):
color: Color # this typehint is required to make `color` an instance attribute
def __init__(self, color: Color):
self.color = color
... # rest of initialization
... # rest of class definition
Practical Examples 1 & 2#
Note
The examples shown here can be found in the examples/
folder.
In the followinng examples, we are going to create two grid-objects which
thematically influence the agent movement. The first grid-objoect is an
Ice
, which may have two statuses: SMOOTH
, which indicates that the
agent may walk on it, and BROKEN
wich indicates that the agent may not walk
on it. Further, it may be thematically interesting to make the agent slip when
moving on a SMOOTH
Ice
, continuing its movement until it hits an
obstacle.
Important
Note that the grid-object only defines these properties and attributes of an
Ice
, while the behavior of the agent trying to walk on the tile should be
implemented separately as a
TransitionFunction
(we
leave this as an exercise).
from __future__ import annotations
import enum
from gym_gridverse.grid_object import Color, GridObject
class Ice(GridObject):
"""An icy tile which can be `smooth` or `broken`."""
color = Color.NONE
blocks_vision = False
holdable = False
class Status(enum.Enum):
SMOOTH = 0
BROKEN = 0
def __init__(self, state: Ice.Status):
self.state = state
@classmethod
def can_be_represented_in_state(cls) -> bool:
return True
@classmethod
def num_states(cls) -> int:
return len(Ice.Status)
@property
def state_index(self) -> int:
return self.state.value
@property
def blocks_movement(self) -> bool:
return self.is_smooth
@property
def is_smooth(self) -> bool:
return self.state is Ice.Status.SMOOTH
@property
def is_broken(self) -> bool:
return self.state is Ice.Status.BROKEN
def __repr__(self):
return f'{self.__class__.__name__}({self.state!s})'
The second grid-object is IceCleats
, a holdable object which may be used to
help an agent walk on a SMOOTH
Ice
without slipping. Once again, the
behavior of an agent walking on Ice
wihle holding IceCleats
should be
implemented by an appropriate
TransitionFunction
.
from gym_gridverse.grid_object import Color, GridObject
class IceCleats(GridObject):
state_index = 0
color = Color.NONE
blocks_movement = False
blocks_vision = False
blocks_holdable = True
@classmethod
def can_be_represented_in_state(cls) -> bool:
return True
@classmethod
def num_states(cls) -> int:
return 1