MiniCraft - BlockedUnlockPickup

Reproduces the minigrid BlockedUnlockPickup 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 = "BlockedUnlockPickup"
 10__doc__ = MiniCraftEnv.description(MINICRAFT_NAME, for_module_header=True)
 11
 12
 13class MiniHCraftBlockedUnlockPickup(MiniCraftEnv):
 14    MINICRAFT_NAME = MINICRAFT_NAME
 15    __doc__ = MiniCraftEnv.description(MINICRAFT_NAME)
 16
 17    START = Zone("start_room")
 18    """Start room."""
 19    BOX_ROOM = Zone("box_room")
 20    """Room with a box inside."""
 21
 22    KEY = Item("key")
 23    """Key used to unlock the door."""
 24    BOX = Item("box")
 25    """Box to pickup."""
 26    BALL = Item("ball")
 27    """Ball blocking the door."""
 28    WEIGHT = Item("weight")
 29    """Weight of carried items, can only be less than 1."""
 30
 31    OPEN_DOOR = Item("open_door")
 32    """Open door between the two rooms."""
 33    LOCKED_DOOR = Item("locked_door")
 34    """Locked door between the two rooms, can be unlocked with a key."""
 35    BLOCKED_DOOR = Item("blocked_door")
 36    """Open but blocked door between the two rooms."""
 37    BLOCKED_LOCKED_DOOR = Item("blocked_locked_door")
 38    """Locked and blocked door between the two rooms."""
 39
 40    def __init__(self, **kwargs) -> None:
 41        self.task = GetItemTask(self.BOX)
 42        super().__init__(
 43            self.MINICRAFT_NAME,
 44            purpose=self.task,
 45            start_zone=self.START,
 46            **kwargs,
 47        )
 48
 49    def build_transformations(self) -> List[Transformation]:
 50        transformations = []
 51
 52        zones = (self.START, self.BOX_ROOM)
 53        items_in_zone = [(self.KEY, self.START), (self.BOX, self.BOX_ROOM)]
 54
 55        for item, zone in items_in_zone:
 56            inventory_changes = [
 57                Yield(CURRENT_ZONE, item, create=1),
 58                # Prevent searching if already found
 59                Yield(PLAYER, item, create=0, max=0),
 60            ]
 61            # Prevent searching if item was placed elsewhere
 62            inventory_changes += [Yield(zone, item, create=0, max=0) for zone in zones]
 63            search_for_item = Transformation(
 64                f"search_for_{item.name}",
 65                inventory_changes=inventory_changes,
 66                zone=zone,
 67            )
 68            transformations.append(search_for_item)
 69
 70        for item in (self.KEY, self.BOX, self.BALL):
 71            pickup = Transformation(
 72                f"pickup_{item.name}",
 73                inventory_changes=[
 74                    Use(CURRENT_ZONE, item, consume=1),
 75                    Yield(PLAYER, item, create=1),
 76                    # WEIGHT prevents carrying more than one item
 77                    Yield(PLAYER, self.WEIGHT, create=1, max=0),
 78                ],
 79            )
 80            put_down = Transformation(
 81                f"put_down_{item.name}",
 82                inventory_changes=[
 83                    Use(PLAYER, item, consume=1),
 84                    Yield(CURRENT_ZONE, item, create=1),
 85                    # WEIGHT prevents carrying more than one item
 86                    Use(PLAYER, self.WEIGHT, consume=1),
 87                ],
 88            )
 89            transformations += [pickup, put_down]
 90
 91        search_for_door = Transformation(
 92            "search_for_door",
 93            inventory_changes=[
 94                Yield(self.START, self.BLOCKED_LOCKED_DOOR, create=1, max=0),
 95                Yield(self.START, self.BLOCKED_DOOR, create=0, max=0),
 96                Yield(self.START, self.LOCKED_DOOR, create=0, max=0),
 97                Yield(self.START, self.OPEN_DOOR, create=0, max=0),
 98            ],
 99            zone=self.START,
100        )
101        transformations.append(search_for_door)
102
103        unblock_locked_door = Transformation(
104            "unblock_locked_door",
105            inventory_changes=[
106                Yield(PLAYER, self.BALL, create=1),
107                Yield(PLAYER, self.WEIGHT, create=1, max=0),
108                Use(self.START, self.BLOCKED_LOCKED_DOOR, consume=1),
109                Yield(self.START, self.LOCKED_DOOR, create=1),
110            ],
111        )
112        transformations.append(unblock_locked_door)
113
114        block_locked_door = Transformation(
115            "block_locked_door",
116            inventory_changes=[
117                Use(PLAYER, self.BALL, consume=1),
118                Use(PLAYER, self.WEIGHT, consume=1),
119                Use(self.START, self.LOCKED_DOOR, consume=1),
120                Yield(self.START, self.BLOCKED_LOCKED_DOOR, create=1),
121            ],
122        )
123        transformations.append(block_locked_door)
124
125        unlock_door = Transformation(
126            "unlock_door",
127            inventory_changes=[
128                Use(PLAYER, self.KEY),
129                Use(self.START, self.LOCKED_DOOR, consume=1),
130                Yield(self.START, self.OPEN_DOOR, create=1),
131            ],
132        )
133        transformations.append(unlock_door)
134
135        block_door = Transformation(
136            "block_door",
137            inventory_changes=[
138                Use(PLAYER, self.BALL, consume=1),
139                Use(PLAYER, self.WEIGHT, consume=1),
140                Use(self.START, self.OPEN_DOOR, consume=1),
141                Yield(self.START, self.BLOCKED_DOOR, create=1),
142            ],
143        )
144        transformations.append(block_door)
145
146        unblock_door = Transformation(
147            "unblock_door",
148            inventory_changes=[
149                Yield(PLAYER, self.BALL, create=1),
150                Yield(PLAYER, self.WEIGHT, create=1, max=0),
151                Use(self.START, self.BLOCKED_DOOR, consume=1),
152                Yield(self.START, self.OPEN_DOOR, create=1),
153            ],
154        )
155        transformations.append(unblock_door)
156
157        move_to_box_room = Transformation(
158            "move_to_box_room",
159            destination=self.BOX_ROOM,
160            inventory_changes=[Use(CURRENT_ZONE, self.OPEN_DOOR)],
161            zone=self.START,
162        )
163        transformations.append(move_to_box_room)
164
165        move_to_start_room = Transformation(
166            "move_to_start_room",
167            destination=self.START,
168            zone=self.BOX_ROOM,
169        )
170        transformations.append(move_to_start_room)
171
172        return transformations

API Documentation

MINICRAFT_NAME = 'BlockedUnlockPickup'
class MiniHCraftBlockedUnlockPickup(typing.Generic[~ObsType, ~ActType]):
 14class MiniHCraftBlockedUnlockPickup(MiniCraftEnv):
 15    MINICRAFT_NAME = MINICRAFT_NAME
 16    __doc__ = MiniCraftEnv.description(MINICRAFT_NAME)
 17
 18    START = Zone("start_room")
 19    """Start room."""
 20    BOX_ROOM = Zone("box_room")
 21    """Room with a box inside."""
 22
 23    KEY = Item("key")
 24    """Key used to unlock the door."""
 25    BOX = Item("box")
 26    """Box to pickup."""
 27    BALL = Item("ball")
 28    """Ball blocking the door."""
 29    WEIGHT = Item("weight")
 30    """Weight of carried items, can only be less than 1."""
 31
 32    OPEN_DOOR = Item("open_door")
 33    """Open door between the two rooms."""
 34    LOCKED_DOOR = Item("locked_door")
 35    """Locked door between the two rooms, can be unlocked with a key."""
 36    BLOCKED_DOOR = Item("blocked_door")
 37    """Open but blocked door between the two rooms."""
 38    BLOCKED_LOCKED_DOOR = Item("blocked_locked_door")
 39    """Locked and blocked door between the two rooms."""
 40
 41    def __init__(self, **kwargs) -> None:
 42        self.task = GetItemTask(self.BOX)
 43        super().__init__(
 44            self.MINICRAFT_NAME,
 45            purpose=self.task,
 46            start_zone=self.START,
 47            **kwargs,
 48        )
 49
 50    def build_transformations(self) -> List[Transformation]:
 51        transformations = []
 52
 53        zones = (self.START, self.BOX_ROOM)
 54        items_in_zone = [(self.KEY, self.START), (self.BOX, self.BOX_ROOM)]
 55
 56        for item, zone in items_in_zone:
 57            inventory_changes = [
 58                Yield(CURRENT_ZONE, item, create=1),
 59                # Prevent searching if already found
 60                Yield(PLAYER, item, create=0, max=0),
 61            ]
 62            # Prevent searching if item was placed elsewhere
 63            inventory_changes += [Yield(zone, item, create=0, max=0) for zone in zones]
 64            search_for_item = Transformation(
 65                f"search_for_{item.name}",
 66                inventory_changes=inventory_changes,
 67                zone=zone,
 68            )
 69            transformations.append(search_for_item)
 70
 71        for item in (self.KEY, self.BOX, self.BALL):
 72            pickup = Transformation(
 73                f"pickup_{item.name}",
 74                inventory_changes=[
 75                    Use(CURRENT_ZONE, item, consume=1),
 76                    Yield(PLAYER, item, create=1),
 77                    # WEIGHT prevents carrying more than one item
 78                    Yield(PLAYER, self.WEIGHT, create=1, max=0),
 79                ],
 80            )
 81            put_down = Transformation(
 82                f"put_down_{item.name}",
 83                inventory_changes=[
 84                    Use(PLAYER, item, consume=1),
 85                    Yield(CURRENT_ZONE, item, create=1),
 86                    # WEIGHT prevents carrying more than one item
 87                    Use(PLAYER, self.WEIGHT, consume=1),
 88                ],
 89            )
 90            transformations += [pickup, put_down]
 91
 92        search_for_door = Transformation(
 93            "search_for_door",
 94            inventory_changes=[
 95                Yield(self.START, self.BLOCKED_LOCKED_DOOR, create=1, max=0),
 96                Yield(self.START, self.BLOCKED_DOOR, create=0, max=0),
 97                Yield(self.START, self.LOCKED_DOOR, create=0, max=0),
 98                Yield(self.START, self.OPEN_DOOR, create=0, max=0),
 99            ],
100            zone=self.START,
101        )
102        transformations.append(search_for_door)
103
104        unblock_locked_door = Transformation(
105            "unblock_locked_door",
106            inventory_changes=[
107                Yield(PLAYER, self.BALL, create=1),
108                Yield(PLAYER, self.WEIGHT, create=1, max=0),
109                Use(self.START, self.BLOCKED_LOCKED_DOOR, consume=1),
110                Yield(self.START, self.LOCKED_DOOR, create=1),
111            ],
112        )
113        transformations.append(unblock_locked_door)
114
115        block_locked_door = Transformation(
116            "block_locked_door",
117            inventory_changes=[
118                Use(PLAYER, self.BALL, consume=1),
119                Use(PLAYER, self.WEIGHT, consume=1),
120                Use(self.START, self.LOCKED_DOOR, consume=1),
121                Yield(self.START, self.BLOCKED_LOCKED_DOOR, create=1),
122            ],
123        )
124        transformations.append(block_locked_door)
125
126        unlock_door = Transformation(
127            "unlock_door",
128            inventory_changes=[
129                Use(PLAYER, self.KEY),
130                Use(self.START, self.LOCKED_DOOR, consume=1),
131                Yield(self.START, self.OPEN_DOOR, create=1),
132            ],
133        )
134        transformations.append(unlock_door)
135
136        block_door = Transformation(
137            "block_door",
138            inventory_changes=[
139                Use(PLAYER, self.BALL, consume=1),
140                Use(PLAYER, self.WEIGHT, consume=1),
141                Use(self.START, self.OPEN_DOOR, consume=1),
142                Yield(self.START, self.BLOCKED_DOOR, create=1),
143            ],
144        )
145        transformations.append(block_door)
146
147        unblock_door = Transformation(
148            "unblock_door",
149            inventory_changes=[
150                Yield(PLAYER, self.BALL, create=1),
151                Yield(PLAYER, self.WEIGHT, create=1, max=0),
152                Use(self.START, self.BLOCKED_DOOR, consume=1),
153                Yield(self.START, self.OPEN_DOOR, create=1),
154            ],
155        )
156        transformations.append(unblock_door)
157
158        move_to_box_room = Transformation(
159            "move_to_box_room",
160            destination=self.BOX_ROOM,
161            inventory_changes=[Use(CURRENT_ZONE, self.OPEN_DOOR)],
162            zone=self.START,
163        )
164        transformations.append(move_to_box_room)
165
166        move_to_start_room = Transformation(
167            "move_to_start_room",
168            destination=self.START,
169            zone=self.BOX_ROOM,
170        )
171        transformations.append(move_to_start_room)
172
173        return transformations

Reproduces the minigrid BlockedUnlockPickup gridworld environment as a HierarchyCraft environment.

MiniHCraftBlockedUnlockPickup(**kwargs)
41    def __init__(self, **kwargs) -> None:
42        self.task = GetItemTask(self.BOX)
43        super().__init__(
44            self.MINICRAFT_NAME,
45            purpose=self.task,
46            start_zone=self.START,
47            **kwargs,
48        )
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 = 'BlockedUnlockPickup'
START = Zone(name='start_room')

Start room.

BOX_ROOM = Zone(name='box_room')

Room with a box inside.

KEY = Item(name='key')

Key used to unlock the door.

BOX = Item(name='box')

Box to pickup.

BALL = Item(name='ball')

Ball blocking the door.

WEIGHT = Item(name='weight')

Weight of carried items, can only be less than 1.

OPEN_DOOR = Item(name='open_door')

Open door between the two rooms.

LOCKED_DOOR = Item(name='locked_door')

Locked door between the two rooms, can be unlocked with a key.

BLOCKED_DOOR = Item(name='blocked_door')

Open but blocked door between the two rooms.

BLOCKED_LOCKED_DOOR = Item(name='blocked_locked_door')

Locked and blocked door between the two rooms.

task
def build_transformations(self) -> List[hcraft.Transformation]:
 50    def build_transformations(self) -> List[Transformation]:
 51        transformations = []
 52
 53        zones = (self.START, self.BOX_ROOM)
 54        items_in_zone = [(self.KEY, self.START), (self.BOX, self.BOX_ROOM)]
 55
 56        for item, zone in items_in_zone:
 57            inventory_changes = [
 58                Yield(CURRENT_ZONE, item, create=1),
 59                # Prevent searching if already found
 60                Yield(PLAYER, item, create=0, max=0),
 61            ]
 62            # Prevent searching if item was placed elsewhere
 63            inventory_changes += [Yield(zone, item, create=0, max=0) for zone in zones]
 64            search_for_item = Transformation(
 65                f"search_for_{item.name}",
 66                inventory_changes=inventory_changes,
 67                zone=zone,
 68            )
 69            transformations.append(search_for_item)
 70
 71        for item in (self.KEY, self.BOX, self.BALL):
 72            pickup = Transformation(
 73                f"pickup_{item.name}",
 74                inventory_changes=[
 75                    Use(CURRENT_ZONE, item, consume=1),
 76                    Yield(PLAYER, item, create=1),
 77                    # WEIGHT prevents carrying more than one item
 78                    Yield(PLAYER, self.WEIGHT, create=1, max=0),
 79                ],
 80            )
 81            put_down = Transformation(
 82                f"put_down_{item.name}",
 83                inventory_changes=[
 84                    Use(PLAYER, item, consume=1),
 85                    Yield(CURRENT_ZONE, item, create=1),
 86                    # WEIGHT prevents carrying more than one item
 87                    Use(PLAYER, self.WEIGHT, consume=1),
 88                ],
 89            )
 90            transformations += [pickup, put_down]
 91
 92        search_for_door = Transformation(
 93            "search_for_door",
 94            inventory_changes=[
 95                Yield(self.START, self.BLOCKED_LOCKED_DOOR, create=1, max=0),
 96                Yield(self.START, self.BLOCKED_DOOR, create=0, max=0),
 97                Yield(self.START, self.LOCKED_DOOR, create=0, max=0),
 98                Yield(self.START, self.OPEN_DOOR, create=0, max=0),
 99            ],
100            zone=self.START,
101        )
102        transformations.append(search_for_door)
103
104        unblock_locked_door = Transformation(
105            "unblock_locked_door",
106            inventory_changes=[
107                Yield(PLAYER, self.BALL, create=1),
108                Yield(PLAYER, self.WEIGHT, create=1, max=0),
109                Use(self.START, self.BLOCKED_LOCKED_DOOR, consume=1),
110                Yield(self.START, self.LOCKED_DOOR, create=1),
111            ],
112        )
113        transformations.append(unblock_locked_door)
114
115        block_locked_door = Transformation(
116            "block_locked_door",
117            inventory_changes=[
118                Use(PLAYER, self.BALL, consume=1),
119                Use(PLAYER, self.WEIGHT, consume=1),
120                Use(self.START, self.LOCKED_DOOR, consume=1),
121                Yield(self.START, self.BLOCKED_LOCKED_DOOR, create=1),
122            ],
123        )
124        transformations.append(block_locked_door)
125
126        unlock_door = Transformation(
127            "unlock_door",
128            inventory_changes=[
129                Use(PLAYER, self.KEY),
130                Use(self.START, self.LOCKED_DOOR, consume=1),
131                Yield(self.START, self.OPEN_DOOR, create=1),
132            ],
133        )
134        transformations.append(unlock_door)
135
136        block_door = Transformation(
137            "block_door",
138            inventory_changes=[
139                Use(PLAYER, self.BALL, consume=1),
140                Use(PLAYER, self.WEIGHT, consume=1),
141                Use(self.START, self.OPEN_DOOR, consume=1),
142                Yield(self.START, self.BLOCKED_DOOR, create=1),
143            ],
144        )
145        transformations.append(block_door)
146
147        unblock_door = Transformation(
148            "unblock_door",
149            inventory_changes=[
150                Yield(PLAYER, self.BALL, create=1),
151                Yield(PLAYER, self.WEIGHT, create=1, max=0),
152                Use(self.START, self.BLOCKED_DOOR, consume=1),
153                Yield(self.START, self.OPEN_DOOR, create=1),
154            ],
155        )
156        transformations.append(unblock_door)
157
158        move_to_box_room = Transformation(
159            "move_to_box_room",
160            destination=self.BOX_ROOM,
161            inventory_changes=[Use(CURRENT_ZONE, self.OPEN_DOOR)],
162            zone=self.START,
163        )
164        transformations.append(move_to_box_room)
165
166        move_to_start_room = Transformation(
167            "move_to_start_room",
168            destination=self.START,
169            zone=self.BOX_ROOM,
170        )
171        transformations.append(move_to_start_room)
172
173        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