def test_step_moving_obstacles( objects: Sequence[Sequence[GridObject]], expected_objects: Sequence[Sequence[GridObject]], ): state = State(Grid.from_objects(objects), MagicMock()) expected_state = State(Grid.from_objects(expected_objects), MagicMock()) action = MagicMock() step_moving_obstacles(state, action) assert state.grid == expected_state.grid
def test_grid_subgrid(area: Area, expected_objects: Sequence[Sequence[GridObject]]): # checkerboard pattern grid = Grid.from_objects([ [Wall(), Floor(), Wall(), Floor()], [Floor(), Wall(), Floor(), Wall()], [Wall(), Floor(), Wall(), Floor()], ]) expected = Grid.from_objects(expected_objects) assert grid.subgrid(area) == expected
def test_grid_change_orientation( orientation: Orientation, expected_objects: Sequence[Sequence[GridObject]]): # checkerboard pattern grid = Grid.from_objects([ [Wall(), Floor(), Wall(), Floor()], [Floor(), Wall(), Floor(), Wall()], [Wall(), Floor(), Wall(), Floor()], ]) expected = Grid.from_objects(expected_objects) assert grid.change_orientation(orientation) == expected
def test_draw_line_horizontal(grid: Grid, y: int, xs: Iterable[int], expected_num_walls: int): positions = draw_line_horizontal(grid, y, xs, Wall) assert len(positions) == len(set(positions)) num_walls = sum(isinstance(grid[pos], Wall) for pos in grid.positions()) assert len(positions) == num_walls == expected_num_walls
def test_draw_room_grid(grid: Grid, ys: Iterable[int], xs: Iterable[int], expected_num_walls: int): positions = draw_room_grid(grid, ys, xs, Wall) assert len(positions) == len(set(positions)) num_walls = sum(isinstance(grid[pos], Wall) for pos in grid.positions()) assert len(positions) == num_walls == expected_num_walls
def make_goal_state(agent_on_goal: bool) -> State: """makes a simple state with a wall in front of the agent""" grid = Grid(2, 1) grid[0, 0] = Goal() agent_position = (0, 0) if agent_on_goal else (1, 0) agent = Agent(agent_position, Orientation.N) return State(grid, agent)
def match_key_color( *, rng: Optional[rnd.Generator] = None, # pylint: disable=unused-argument ) -> State: """the agent has to pick the correct key to open a randomly colored door""" rng = get_gv_rng_if_none(rng) # necessary to use rng object! # only consider these colors colors = [Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW] # randomly choose location of keys key1, key2, key3, key4 = rng.permute([Key(color) for color in colors]) # randomly choose color of door door = Door(Door.Status.LOCKED, rng.choice(colors)) # grids can be constructed directly from objects grid = Grid.from_objects([ [Wall(), Wall(), Wall(), Wall(), Wall()], [Wall(), Wall(), Goal(), Wall(), Wall()], [Wall(), Wall(), door, Wall(), Wall()], [Wall(), key1, Floor(), key2, Wall()], [Wall(), key3, Floor(), key4, Wall()], [Wall(), Wall(), Wall(), Wall(), Wall()], ]) # positioning the agent in the above grid agent = Agent((4, 2), Orientation.N) return State(grid, agent)
def make_moving_obstacle_state(agent_on_obstacle: bool) -> State: """makes a simple state with goal object and agent on or off the goal""" grid = Grid(2, 1) grid[0, 0] = MovingObstacle() agent_position = (0, 0) if agent_on_obstacle else (1, 0) agent = Agent(agent_position, Orientation.N) return State(grid, agent)
def test_draw_area(grid: Grid, area: Area, fill: bool, expected_num_walls: int): positions = draw_area(grid, area, Wall, fill=fill) assert len(positions) == len(set(positions)) num_walls = sum(isinstance(grid[pos], Wall) for pos in grid.positions()) assert len(positions) == num_walls == expected_num_walls
def test_full_visibility(objects: Sequence[Sequence[GridObject]]): grid = Grid.from_objects(objects) for position in grid.positions(): visibility = full_visibility(grid, position) assert visibility.dtype == bool assert visibility.all()
def test_minigrid_observation_partially_observable( agent: Agent, expected_objects: Sequence[Sequence[GridObject]] ): grid = Grid.from_objects( [ [Floor(), Floor(), Floor()], [Wall(), Wall(), Wall()], [Floor(), Floor(), Floor()], ] ) state = State(grid, agent) observation_space = ObservationSpace(Shape(6, 5), [], []) observation = minigrid_observation( state, observation_space=observation_space ) expected = Grid.from_objects(expected_objects) assert observation.grid == expected
def test_raytracing_visibility( objects: Sequence[Sequence[GridObject]], position: Position, expected_int: Sequence[Sequence[int]], ): grid = Grid.from_objects(objects) visibility = raytracing_visibility(grid, position) assert visibility.dtype == bool assert (visibility == expected_int).all()
def test_grid_set_item(): grid = Grid(3, 4) pos = Position(0, 0) obj = Floor() assert grid[pos] is not obj grid[pos] = obj assert grid[pos] is obj
def test_move_action_blocked_by_grid_object(): """ Puts an object on (2,0) and try to move there""" grid = Grid(height=3, width=2) agent = Agent(position=(2, 1), orientation=Orientation.N) grid[2, 0] = Door(Door.Status.CLOSED, Color.YELLOW) move_agent(agent, grid, action=Action.MOVE_LEFT) assert agent.position == (2, 1)
def test_move_action_can_go_on_non_block_objects(): grid = Grid(height=3, width=2) agent = Agent(position=(2, 1), orientation=Orientation.N) grid[2, 0] = Door(Door.Status.OPEN, Color.YELLOW) move_agent(agent, grid, action=Action.MOVE_LEFT) assert agent.position == (2, 0) grid[2, 1] = Key(Color.BLUE) move_agent(agent, grid, action=Action.MOVE_RIGHT) assert agent.position == (2, 1)
def reset_empty( height: int, width: int, random_agent: bool = False, random_goal: bool = False, *, rng: Optional[rnd.Generator] = None, ) -> State: """An empty environment""" if height < 4 or width < 4: raise ValueError('height and width need to be at least 4') rng = get_gv_rng_if_none(rng) # TODO test creation (e.g. count number of walls, goals, check held item) grid = Grid(height, width) draw_wall_boundary(grid) if random_goal: goal_y = rng.integers(1, height - 2, endpoint=True) goal_x = rng.integers(1, width - 2, endpoint=True) else: goal_y = height - 2 goal_x = width - 2 grid[goal_y, goal_x] = Goal() if random_agent: agent_position = rng.choice([ position for position in grid.positions() if isinstance(grid[position], Floor) ]) agent_orientation = rng.choice(list(Orientation)) else: agent_position = (1, 1) agent_orientation = Orientation.E agent = Agent(agent_position, agent_orientation) return State(grid, agent)
def _step_moving_obstacle(grid: Grid, position: Position, *, rng: Optional[rnd.Generator] = None): """Utility for moving a single MovingObstacle randomly""" assert isinstance(grid[position], MovingObstacle) rng = get_gv_rng_if_none(rng) next_positions = [ next_position for next_position in get_manhattan_boundary(position, distance=1) if next_position in grid and isinstance(grid[next_position], Floor) ] try: next_position = rng.choice(next_positions) except ValueError: pass else: grid.swap(position, next_position)
def test_pickup_mechanics_swap(): grid = Grid(height=3, width=4) agent = Agent(position=(1, 2), orientation=Orientation.S) item_pos = (2, 2) agent.obj = Key(Color.BLUE) grid[item_pos] = Key(Color.GREEN) state = State(grid, agent) next_state = step_with_copy(state, Action.PICK_N_DROP) assert state.grid[item_pos] == next_state.agent.obj assert state.agent.obj == next_state.grid[item_pos]
def test_state_hash(): wall_position = (0, 0) agent_position = (0, 1) agent_orientation = Orientation.N agent_object = None grid = Grid(2, 2) grid[wall_position] = Wall() agent = Agent(agent_position, agent_orientation, agent_object) state = State(grid, agent) hash(state)
def test_grid_subgrid_references(): key = Key(Color.RED) box = Box(key) # weird scenario where the key is both in the box and outside the box, # only created to test references grid = Grid.from_objects([[key, box]]) subgrid = grid.subgrid(Area((0, 0), (0, 1))) key = subgrid[0, 0] box = subgrid[0, 1] assert box.content is key
def test_observation_hash(): wall_position = (0, 0) agent_position = (0, 1) agent_orientation = Orientation.N agent_object = None grid = Grid(2, 2) grid[wall_position] = Wall() agent = Agent(agent_position, agent_orientation, agent_object) observation = Observation(grid, agent) hash(observation)
def test_move_action( position: PositionOrTuple, orientation: Orientation, actions: Sequence[Action], expected: PositionOrTuple, ): grid = Grid(height=3, width=2) agent = Agent(position=position, orientation=orientation) for action in actions: move_agent(agent, grid, action=action) assert agent.position == expected
def test_actuate_box( content: GridObject, orientation: Orientation, action: Action, expected: bool, ): grid = Grid(2, 1) grid[0, 0] = box = Box(content) agent = Agent((1, 0), orientation) state = State(grid, agent) actuate_box(state, action) assert (grid[0, 0] is box) != expected assert (grid[0, 0] is content) == expected
def test_minigrid_observation(agent: Agent): grid = Grid(10, 10) grid[5, 5] = Wall() state = State(grid, agent) observation_space = ObservationSpace(Shape(6, 5), [], []) observation = minigrid_observation( state, observation_space=observation_space ) assert observation.agent.position == (5, 2) assert observation.agent.orientation == Orientation.N assert observation.agent.obj == state.agent.obj assert observation.grid.shape == Shape(6, 5) assert isinstance(observation.grid[3, 0], Wall)
def test_actuate_door( door_state: Door.Status, door_color: Color, key_color: Color, action: Action, expected_state: Door.Status, ): # agent facing door grid = Grid(2, 1) grid[0, 0] = door = Door(door_state, door_color) agent = Agent((1, 0), Orientation.N, Key(key_color)) state = State(grid, agent) actuate_door(state, action) assert door.state == expected_state # agent facing away grid = Grid(2, 1) grid[0, 0] = door = Door(door_state, door_color) agent = Agent((1, 0), Orientation.S, Key(key_color)) state = State(grid, agent) actuate_door(state, action) assert door.state == door_state
def test_teleport( position_telepod1: Position, position_telepod2: Position, position_agent: Position, expected: Position, ): grid = Grid(2, 2) grid[position_telepod1] = Telepod(Color.RED) grid[position_telepod2] = Telepod(Color.RED) agent = Agent(position_agent, Orientation.N) state = State(grid, agent) step_telepod(state, Action.ACTUATE) assert state.agent.position == expected
def _unique_object_type_positions( grid: Grid, object_type: Type[GridObject] ) -> Iterator[Tuple[Position, GridObject]]: """Utility for iterating *once* over position/objects. Every object is only yielded once, even if the objects move during the interleaved iteration. """ objects: List[GridObject] = [] for position in grid.positions(): obj = grid[position] if isinstance(obj, object_type) and not any(obj is x for x in objects): objects.append(obj) yield position, obj
def test_grid_get_position(): grid = Grid(3, 4) # testing position -> grid_object -> position roundtrip for position in grid.positions(): obj = grid[position] assert grid.get_position(obj) == position # testing exception when object is not in grid with pytest.raises(ValueError): grid.get_position(Floor())
def test_pickup_mechanics_pickup(): grid = Grid(height=3, width=4) agent = Agent(position=(1, 2), orientation=Orientation.S) item_pos = (2, 2) grid[item_pos] = Key(Color.GREEN) state = State(grid, agent) # Pick up works next_state = step_with_copy(state, Action.PICK_N_DROP) assert grid[item_pos] == next_state.agent.obj assert isinstance(next_state.grid[item_pos], Floor) # Pick up only works with correct action next_state = step_with_copy(state, Action.MOVE_LEFT) assert grid[item_pos] != next_state.agent.obj assert next_state.grid[item_pos] == grid[item_pos]
def test_pickup_mechanics_nothing_to_pickup(): grid = Grid(height=3, width=4) agent = Agent(position=(1, 2), orientation=Orientation.S) item_pos = (2, 2) state = State(grid, agent) # Cannot pickup floor next_state = step_with_copy(state, Action.PICK_N_DROP) assert state == next_state # Cannot pickup door grid[item_pos] = Door(Door.Status.CLOSED, Color.GREEN) next_state = step_with_copy(state, Action.PICK_N_DROP) assert state == next_state assert isinstance(next_state.grid[item_pos], Door)