MiniCraft - KeyCorridor

Reproduces the minigrid KeyCorridor gridworld environment as a HierarchyCraft environment.

Minigrid representation:

HierarchyCraft requirements graph:

  1from typing import List
  2
  3from hcraft.elements import Item, Zone
  4from hcraft.task import GetItemTask
  5from hcraft.transformation import Transformation, Use, Yield, PLAYER, CURRENT_ZONE
  6
  7from hcraft.examples.minicraft.minicraft import MiniCraftEnv
  8
  9MINICRAFT_NAME = "KeyCorridor"
 10__doc__ = MiniCraftEnv.description(MINICRAFT_NAME, for_module_header=True)
 11
 12
 13class MiniHCraftKeyCorridor(MiniCraftEnv):
 14    MINICRAFT_NAME = MINICRAFT_NAME
 15    __doc__ = MiniCraftEnv.description(MINICRAFT_NAME)
 16
 17    START = Zone("start_room")
 18    """Start room."""
 19    KEY_ROOM = Zone("key_room")
 20    """Room containing a key."""
 21    LOCKED_ROOM = Zone("locked_room")
 22    """Room behind a locked door."""
 23
 24    KEY = Item("key")
 25    """Key used to unlock locked door."""
 26    BALL = Item("ball")
 27    """Ball to pickup."""
 28    WEIGHT = Item("weight")
 29    """Weight of carried items."""
 30
 31    OPEN_DOOR = Item("open_door")
 32    """Opened lockedroom door."""
 33    OPEN_KEY_DOOR = Item("blue_open_door")
 34    """Opened keyroom door."""
 35    CLOSED_KEY_DOOR = Item("blue_closed_door")
 36    """Closed keyroom door."""
 37    LOCKED_DOOR = Item("locked_door")
 38    """Locked door, can be unlocked with a key."""
 39
 40    def __init__(self, **kwargs) -> None:
 41        self.task = GetItemTask(self.BALL)
 42        super().__init__(
 43            self.MINICRAFT_NAME,
 44            start_zone=self.START,
 45            start_zones_items={
 46                self.START: [self.CLOSED_KEY_DOOR, self.LOCKED_DOOR],
 47                self.LOCKED_ROOM: [self.BALL],
 48            },
 49            purpose=self.task,
 50            **kwargs,
 51        )
 52
 53    def build_transformations(self) -> List[Transformation]:
 54        transformations = []
 55
 56        # Ensure key cannot be created if anywhere else
 57        search_for_key = Transformation(
 58            "search_for_key",
 59            inventory_changes=[
 60                Yield(CURRENT_ZONE, self.KEY, create=1, max=0),
 61                Yield(PLAYER, self.KEY, create=0, max=0),
 62                Yield(self.START, self.KEY, create=0, max=0),
 63                Yield(self.KEY_ROOM, self.KEY, create=0, max=0),
 64                Yield(self.LOCKED_ROOM, self.KEY, create=0, max=0),
 65            ],
 66            zone=self.KEY_ROOM,
 67        )
 68        transformations.append(search_for_key)
 69
 70        pickup = Transformation(
 71            "pickup_key",
 72            inventory_changes=[
 73                Use(CURRENT_ZONE, self.KEY, consume=1),
 74                Yield(PLAYER, self.KEY),
 75                Yield(PLAYER, self.WEIGHT, max=0),
 76            ],
 77        )
 78        put_down = Transformation(
 79            "put_down_key",
 80            inventory_changes=[
 81                Use(PLAYER, self.KEY, consume=1),
 82                Use(PLAYER, self.WEIGHT, consume=1),
 83                Yield(CURRENT_ZONE, self.KEY, create=1),
 84            ],
 85        )
 86        transformations += [pickup, put_down]
 87
 88        open_door = Transformation(
 89            "open_door",
 90            inventory_changes=[
 91                Use(CURRENT_ZONE, self.CLOSED_KEY_DOOR, consume=1),
 92                Yield(CURRENT_ZONE, self.OPEN_KEY_DOOR, create=1),
 93            ],
 94        )
 95        transformations.append(open_door)
 96
 97        move_to_key_room = Transformation(
 98            "move_to_key_room",
 99            destination=self.KEY_ROOM,
100            inventory_changes=[Use(CURRENT_ZONE, self.OPEN_KEY_DOOR)],
101            zone=self.START,
102        )
103        transformations.append(move_to_key_room)
104
105        for from_zone in [self.KEY_ROOM, self.LOCKED_ROOM]:
106            move_to_start_room = Transformation(
107                f"move_to_start_room_from_{from_zone.name}",
108                destination=self.START,
109                zone=from_zone,
110            )
111            transformations.append(move_to_start_room)
112
113        unlock_door = Transformation(
114            "unlock_door",
115            inventory_changes=[
116                Use(PLAYER, self.KEY),
117                Use(CURRENT_ZONE, self.LOCKED_DOOR, consume=1),
118                Yield(CURRENT_ZONE, self.OPEN_DOOR, create=1),
119            ],
120        )
121        transformations.append(unlock_door)
122
123        move_to_locked_room = Transformation(
124            "move_to_locked_room",
125            destination=self.LOCKED_ROOM,
126            inventory_changes=[Use(CURRENT_ZONE, self.OPEN_DOOR)],
127            zone=self.START,
128        )
129        transformations.append(move_to_locked_room)
130
131        pickup_ball = Transformation(
132            "pickup_ball",
133            inventory_changes=[
134                Use(CURRENT_ZONE, self.BALL, consume=1),
135                Yield(PLAYER, self.BALL),
136                Yield(PLAYER, self.WEIGHT, max=0),
137            ],
138        )
139        transformations.append(pickup_ball)
140
141        return transformations

API Documentation

MINICRAFT_NAME = 'KeyCorridor'
class MiniHCraftKeyCorridor(typing.Generic[~ObsType, ~ActType]):
 14class MiniHCraftKeyCorridor(MiniCraftEnv):
 15    MINICRAFT_NAME = MINICRAFT_NAME
 16    __doc__ = MiniCraftEnv.description(MINICRAFT_NAME)
 17
 18    START = Zone("start_room")
 19    """Start room."""
 20    KEY_ROOM = Zone("key_room")
 21    """Room containing a key."""
 22    LOCKED_ROOM = Zone("locked_room")
 23    """Room behind a locked door."""
 24
 25    KEY = Item("key")
 26    """Key used to unlock locked door."""
 27    BALL = Item("ball")
 28    """Ball to pickup."""
 29    WEIGHT = Item("weight")
 30    """Weight of carried items."""
 31
 32    OPEN_DOOR = Item("open_door")
 33    """Opened lockedroom door."""
 34    OPEN_KEY_DOOR = Item("blue_open_door")
 35    """Opened keyroom door."""
 36    CLOSED_KEY_DOOR = Item("blue_closed_door")
 37    """Closed keyroom door."""
 38    LOCKED_DOOR = Item("locked_door")
 39    """Locked door, can be unlocked with a key."""
 40
 41    def __init__(self, **kwargs) -> None:
 42        self.task = GetItemTask(self.BALL)
 43        super().__init__(
 44            self.MINICRAFT_NAME,
 45            start_zone=self.START,
 46            start_zones_items={
 47                self.START: [self.CLOSED_KEY_DOOR, self.LOCKED_DOOR],
 48                self.LOCKED_ROOM: [self.BALL],
 49            },
 50            purpose=self.task,
 51            **kwargs,
 52        )
 53
 54    def build_transformations(self) -> List[Transformation]:
 55        transformations = []
 56
 57        # Ensure key cannot be created if anywhere else
 58        search_for_key = Transformation(
 59            "search_for_key",
 60            inventory_changes=[
 61                Yield(CURRENT_ZONE, self.KEY, create=1, max=0),
 62                Yield(PLAYER, self.KEY, create=0, max=0),
 63                Yield(self.START, self.KEY, create=0, max=0),
 64                Yield(self.KEY_ROOM, self.KEY, create=0, max=0),
 65                Yield(self.LOCKED_ROOM, self.KEY, create=0, max=0),
 66            ],
 67            zone=self.KEY_ROOM,
 68        )
 69        transformations.append(search_for_key)
 70
 71        pickup = Transformation(
 72            "pickup_key",
 73            inventory_changes=[
 74                Use(CURRENT_ZONE, self.KEY, consume=1),
 75                Yield(PLAYER, self.KEY),
 76                Yield(PLAYER, self.WEIGHT, max=0),
 77            ],
 78        )
 79        put_down = Transformation(
 80            "put_down_key",
 81            inventory_changes=[
 82                Use(PLAYER, self.KEY, consume=1),
 83                Use(PLAYER, self.WEIGHT, consume=1),
 84                Yield(CURRENT_ZONE, self.KEY, create=1),
 85            ],
 86        )
 87        transformations += [pickup, put_down]
 88
 89        open_door = Transformation(
 90            "open_door",
 91            inventory_changes=[
 92                Use(CURRENT_ZONE, self.CLOSED_KEY_DOOR, consume=1),
 93                Yield(CURRENT_ZONE, self.OPEN_KEY_DOOR, create=1),
 94            ],
 95        )
 96        transformations.append(open_door)
 97
 98        move_to_key_room = Transformation(
 99            "move_to_key_room",
100            destination=self.KEY_ROOM,
101            inventory_changes=[Use(CURRENT_ZONE, self.OPEN_KEY_DOOR)],
102            zone=self.START,
103        )
104        transformations.append(move_to_key_room)
105
106        for from_zone in [self.KEY_ROOM, self.LOCKED_ROOM]:
107            move_to_start_room = Transformation(
108                f"move_to_start_room_from_{from_zone.name}",
109                destination=self.START,
110                zone=from_zone,
111            )
112            transformations.append(move_to_start_room)
113
114        unlock_door = Transformation(
115            "unlock_door",
116            inventory_changes=[
117                Use(PLAYER, self.KEY),
118                Use(CURRENT_ZONE, self.LOCKED_DOOR, consume=1),
119                Yield(CURRENT_ZONE, self.OPEN_DOOR, create=1),
120            ],
121        )
122        transformations.append(unlock_door)
123
124        move_to_locked_room = Transformation(
125            "move_to_locked_room",
126            destination=self.LOCKED_ROOM,
127            inventory_changes=[Use(CURRENT_ZONE, self.OPEN_DOOR)],
128            zone=self.START,
129        )
130        transformations.append(move_to_locked_room)
131
132        pickup_ball = Transformation(
133            "pickup_ball",
134            inventory_changes=[
135                Use(CURRENT_ZONE, self.BALL, consume=1),
136                Yield(PLAYER, self.BALL),
137                Yield(PLAYER, self.WEIGHT, max=0),
138            ],
139        )
140        transformations.append(pickup_ball)
141
142        return transformations

Reproduces the minigrid KeyCorridor gridworld environment as a HierarchyCraft environment.

MiniHCraftKeyCorridor(**kwargs)
41    def __init__(self, **kwargs) -> None:
42        self.task = GetItemTask(self.BALL)
43        super().__init__(
44            self.MINICRAFT_NAME,
45            start_zone=self.START,
46            start_zones_items={
47                self.START: [self.CLOSED_KEY_DOOR, self.LOCKED_DOOR],
48                self.LOCKED_ROOM: [self.BALL],
49            },
50            purpose=self.task,
51            **kwargs,
52        )
Arguments:
  • invalid_reward: Reward given to the agent for invalid actions. Defaults to -1.0.
  • max_step: Maximum number of steps before episode truncation. If None, never truncates the episode. Defaults to None.
  • render_window: Window using to render the environment with pygame.
MINICRAFT_NAME = 'KeyCorridor'
START = Zone(name='start_room')

Start room.

KEY_ROOM = Zone(name='key_room')

Room containing a key.

LOCKED_ROOM = Zone(name='locked_room')

Room behind a locked door.

KEY = Item(name='key')

Key used to unlock locked door.

BALL = Item(name='ball')

Ball to pickup.

WEIGHT = Item(name='weight')

Weight of carried items.

OPEN_DOOR = Item(name='open_door')

Opened lockedroom door.

OPEN_KEY_DOOR = Item(name='blue_open_door')

Opened keyroom door.

CLOSED_KEY_DOOR = Item(name='blue_closed_door')

Closed keyroom door.

LOCKED_DOOR = Item(name='locked_door')

Locked door, can be unlocked with a key.

task
def build_transformations(self) -> List[hcraft.Transformation]:
 54    def build_transformations(self) -> List[Transformation]:
 55        transformations = []
 56
 57        # Ensure key cannot be created if anywhere else
 58        search_for_key = Transformation(
 59            "search_for_key",
 60            inventory_changes=[
 61                Yield(CURRENT_ZONE, self.KEY, create=1, max=0),
 62                Yield(PLAYER, self.KEY, create=0, max=0),
 63                Yield(self.START, self.KEY, create=0, max=0),
 64                Yield(self.KEY_ROOM, self.KEY, create=0, max=0),
 65                Yield(self.LOCKED_ROOM, self.KEY, create=0, max=0),
 66            ],
 67            zone=self.KEY_ROOM,
 68        )
 69        transformations.append(search_for_key)
 70
 71        pickup = Transformation(
 72            "pickup_key",
 73            inventory_changes=[
 74                Use(CURRENT_ZONE, self.KEY, consume=1),
 75                Yield(PLAYER, self.KEY),
 76                Yield(PLAYER, self.WEIGHT, max=0),
 77            ],
 78        )
 79        put_down = Transformation(
 80            "put_down_key",
 81            inventory_changes=[
 82                Use(PLAYER, self.KEY, consume=1),
 83                Use(PLAYER, self.WEIGHT, consume=1),
 84                Yield(CURRENT_ZONE, self.KEY, create=1),
 85            ],
 86        )
 87        transformations += [pickup, put_down]
 88
 89        open_door = Transformation(
 90            "open_door",
 91            inventory_changes=[
 92                Use(CURRENT_ZONE, self.CLOSED_KEY_DOOR, consume=1),
 93                Yield(CURRENT_ZONE, self.OPEN_KEY_DOOR, create=1),
 94            ],
 95        )
 96        transformations.append(open_door)
 97
 98        move_to_key_room = Transformation(
 99            "move_to_key_room",
100            destination=self.KEY_ROOM,
101            inventory_changes=[Use(CURRENT_ZONE, self.OPEN_KEY_DOOR)],
102            zone=self.START,
103        )
104        transformations.append(move_to_key_room)
105
106        for from_zone in [self.KEY_ROOM, self.LOCKED_ROOM]:
107            move_to_start_room = Transformation(
108                f"move_to_start_room_from_{from_zone.name}",
109                destination=self.START,
110                zone=from_zone,
111            )
112            transformations.append(move_to_start_room)
113
114        unlock_door = Transformation(
115            "unlock_door",
116            inventory_changes=[
117                Use(PLAYER, self.KEY),
118                Use(CURRENT_ZONE, self.LOCKED_DOOR, consume=1),
119                Yield(CURRENT_ZONE, self.OPEN_DOOR, create=1),
120            ],
121        )
122        transformations.append(unlock_door)
123
124        move_to_locked_room = Transformation(
125            "move_to_locked_room",
126            destination=self.LOCKED_ROOM,
127            inventory_changes=[Use(CURRENT_ZONE, self.OPEN_DOOR)],
128            zone=self.START,
129        )
130        transformations.append(move_to_locked_room)
131
132        pickup_ball = Transformation(
133            "pickup_ball",
134            inventory_changes=[
135                Use(CURRENT_ZONE, self.BALL, consume=1),
136                Yield(PLAYER, self.BALL),
137                Yield(PLAYER, self.WEIGHT, max=0),
138            ],
139        )
140        transformations.append(pickup_ball)
141
142        return transformations

Build transformations for this MiniCraft environment

Inherited Members
hcraft.examples.minicraft.minicraft.MiniCraftEnv
description
hcraft.env.HcraftEnv
world
invalid_reward
max_step
name
render_window
render_mode
state
current_step
current_score
cumulated_score
episodes
task_successes
terminal_successes
purpose
metadata
truncated
observation_space
action_space
action_masks
step
render
reset
close
all_behaviors
solving_behavior
planning_problem
infos
gymnasium.core.Env
spec
unwrapped
np_random_seed
np_random
has_wrapper_attr
get_wrapper_attr
set_wrapper_attr