Creating new grid objects in CuriosityGym#

This guide explains how to create new grid object subclasses for the CuriosityGym framework. Each new subclass should inherit from the GridObject base class and implement its abstract methods to define custom behaviors.

Overview of GridObject#

The GridObject class is the base for all grid objects in CuriosityGym. It provides:

  • Attributes: - position, color, and state for defining grid object characteristics.

  • Methods: - reset, step, simulate, interact, is_walkable, and is_harmful for default behaviors.

  • Abstract Methods: - render, which must be implemented to define the visual representation of the object.

Steps to Create a New Grid Object Subclass#

  1. Define a New Class Define a new subclass inheriting from GridObject.

    from curiosity_gym.objects import GridObject
    
    class CustomObject(GridObject):
        """Custom grid object with specific behavior."""
    
  2. Implement the Constructor Define the __init__ method to initialize attributes specific to your object. Call super().__init__ to inherit and initialize common attributes (position, color, state).

    def __init__(self, position, color=0, state=0):
        super().__init__(position, color, state)
        # Add custom initialization logic here
    
  3. Override the ``render`` Method Implement the render method to define how the object is visually represented in the environment. Use PyGame functions for drawing.

    def render(self, canvas, pixelsquare):
        pygame.draw.rect(
            canvas,
            IX_TO_COLOR[self.color],
            pygame.Rect(
                pygame.Vector2(*(pixelsquare * self.position)),
                (pixelsquare, pixelsquare)
            )
        )
    
  4. Customize Interaction (Optional) Override the interact method to define how agents interact with your object.

    def interact(self, agent):
        """Define interaction logic with the agent."""
        # Custom interaction logic here
    
  5. Modify Behavior During Environment Steps (Optional) Override the step method to define how the object behaves during a timestep.

    def step(self, action, front_object=None, walkable=False):
        """Custom behavior on each environment step."""
        # Custom step logic here
        return 0  # Optional reward
    
  6. Set Walkability (Optional) Override the is_walkable method if the object allows agents to move over it.

    def is_walkable(self):
        return True  # Example: The object is walkable
    
  7. Define Harmful Objects (Optional) Override is_harmful if the object should terminate the episode when the agent interacts with it.

    def is_harmful(self):
        return True  # Example: The object is harmful
    
  8. Register the Object (Automatic) Each subclass is automatically registered with a unique identifier upon definition. No additional registration is required.

Example: Creating a “Bonus” Grid Object#

The following example creates a Bonus object that rewards the agent upon interaction:

from curiosity_gym.objects import GridObject

class Bonus(GridObject):
    """Grid object that rewards the agent when collected."""

    def __init__(self, position, reward=10):
        super().__init__(position, color=5, state=0)
        self.reward = reward

    def render(self, canvas, pixelsquare):
        pygame.draw.circle(
            canvas,
            IX_TO_COLOR[self.color],
            pygame.Vector2(*((self.position + [0.5, 0.5]) * pixelsquare)),
            0.3 * pixelsquare,
        )

    def step(self, action, front_object=None, walkable=False):
        return 0  # No specific behavior during timestep

    def interact(self, agent):
        """Collect the bonus and remove it from the grid."""
        self.position = np.array([-1, -1])  # Remove from grid
        return self.reward