Skip to content

Unlock

Unlock and UnlockPickup - the simplest case of MiniGrid's RoomGrid (num_rows=1, num_cols=2, a single door connecting two equal-sized rooms). See issue #10/#175/#176 - a full RoomGrid port (arbitrary num_rows/num_cols, issue #174) is deliberately not needed for either of these two environments, so this file builds the 1x2 layout directly rather than a general room-grid primitive.

Bases: Environment

UnlockPickup (#176), plus a Ball placed directly in front of the door on the first room's side, obstructing the direct approach (#181). Unlike a Key/Box, picking the ball up doesn't need to be followed by carrying it anywhere in particular - actions.pickup moves it straight to the discard pile, so the blocked cell is clear the instant it's picked up. It does need to be dropped again before the key can be picked up, though (the player's pocket only holds one id at a time) - "step around it" isn't a real option: the door, like every Openable, can only be toggled from the one exact cell directly in front of it, which is exactly where the ball sits. Reuses two_equal_rooms_with_door(block_door=True) directly - no RoomGrid (#174) needed, despite this issue's own header suggesting otherwise.

Bases: Environment

The agent has to open a locked door - a matching key is in the same (left) room; the other (right) room is otherwise empty. Reward + termination on opening the door (see rewards.on_door_open/ terminations.on_door_open) - not on reaching any further goal, opening the door is the success condition.

Bases: Environment

Unlock, plus a Box placed in the second (right) room - the agent must unlock the door, then pick up the box. Reward + termination on picking up the box (see rewards.on_box_pickup/ terminations.on_box_pickup).

Builds the shared layout Unlock/UnlockPickup both start from: two height x height-square rooms side by side (wall_col = height - 1 apart, width == 2 * (height - 1) + 1), connected by one locked Door at a random row, with a matching Key and the agent both placed randomly in the first (left) room. Mirrors MiniGrid's RoomGrid(room_size=height, num_rows=1, num_cols=2) - add_door(0, 0, door_idx=0, locked=True) + add_object(0, 0, "key", door.color) + place_agent(0, 0).

Parameters:

Name Type Description Default
key Array

PRNG key.

required
height int

Height of each room (MiniGrid's room_size).

required
width int

Must be 2 * (height - 1) + 1.

required
block_door bool

If True (used by BlockedUnlockPickup, #181), also places a Ball directly in front of the door on the first room's side, and excludes that cell from player/key placement - a static Python bool (not a traced value), so this branches at trace-construction time, not runtime; the door's position is already known at this point inside the function (unlike a caller trying to add a blocking ball afterwards, which would risk colliding with an already-randomly-placed player/key).

False

Returns:

Type Description
Array

Tuple[Array, ...]: `(key, grid, wall_col, entities_dict, first_room,

Array

door_colour)-entities_dicthasEntities.PLAYER/KEY/DOOR`

int

(and Entities.BALL if block_door) already batched

Dict[str, Entity]

([None]-indexed) and ready to merge into a State; first_room

Array

(the left room's own grid-shaped mask, walls everywhere outside

Array

it) is returned too, so UnlockPickup can build its own

Tuple[Array, Array, int, Dict[str, Entity], Array, Array]

second_room mask from the same wall_col without recomputing

Tuple[Array, Array, int, Dict[str, Entity], Array, Array]

the base grid.