from gym_minigrid.minigrid import ( COLOR_NAMES, Door, Goal, Grid, Key, MiniGridEnv, MissionSpace, Wall, ) class LockedRoom: def __init__(self, top, size, doorPos): self.top = top self.size = size self.doorPos = doorPos self.color = None self.locked = False def rand_pos(self, env): topX, topY = self.top sizeX, sizeY = self.size return env._rand_pos(topX + 1, topX + sizeX - 1, topY + 1, topY + sizeY - 1) class LockedRoomEnv(MiniGridEnv): """ Environment in which the agent is instructed to go to a given object named using an English text string """ def __init__(self, size=19, **kwargs): self.size = size mission_space = MissionSpace( mission_func=lambda lockedroom_color, keyroom_color, door_color: f"get the {lockedroom_color} key from the {keyroom_color} room, unlock the {door_color} door and go to the goal", ordered_placeholders=[COLOR_NAMES] * 3, ) super().__init__( mission_space=mission_space, width=size, height=size, max_steps=10 * size, **kwargs, ) def _gen_grid(self, width, height): # Create the grid self.grid = Grid(width, height) # Generate the surrounding walls for i in range(0, width): self.grid.set(i, 0, Wall()) self.grid.set(i, height - 1, Wall()) for j in range(0, height): self.grid.set(0, j, Wall()) self.grid.set(width - 1, j, Wall()) # Hallway walls lWallIdx = width // 2 - 2 rWallIdx = width // 2 + 2 for j in range(0, height): self.grid.set(lWallIdx, j, Wall()) self.grid.set(rWallIdx, j, Wall()) self.rooms = [] # Room splitting walls for n in range(0, 3): j = n * (height // 3) for i in range(0, lWallIdx): self.grid.set(i, j, Wall()) for i in range(rWallIdx, width): self.grid.set(i, j, Wall()) roomW = lWallIdx + 1 roomH = height // 3 + 1 self.rooms.append(LockedRoom((0, j), (roomW, roomH), (lWallIdx, j + 3))) self.rooms.append( LockedRoom((rWallIdx, j), (roomW, roomH), (rWallIdx, j + 3)) ) # Choose one random room to be locked lockedRoom = self._rand_elem(self.rooms) lockedRoom.locked = True goalPos = lockedRoom.rand_pos(self) self.grid.set(*goalPos, Goal()) # Assign the door colors colors = set(COLOR_NAMES) for room in self.rooms: color = self._rand_elem(sorted(colors)) colors.remove(color) room.color = color if room.locked: self.grid.set(*room.doorPos, Door(color, is_locked=True)) else: self.grid.set(*room.doorPos, Door(color)) # Select a random room to contain the key while True: keyRoom = self._rand_elem(self.rooms) if keyRoom != lockedRoom: break keyPos = keyRoom.rand_pos(self) self.grid.set(*keyPos, Key(lockedRoom.color)) # Randomize the player start position and orientation self.agent_pos = self.place_agent( top=(lWallIdx, 0), size=(rWallIdx - lWallIdx, height) ) # Generate the mission string self.mission = ( "get the %s key from the %s room, " "unlock the %s door and " "go to the goal" ) % (lockedRoom.color, keyRoom.color, lockedRoom.color)