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_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 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_grid_swap(): grid = Grid(3, 4) # caching positions and objects before swap objects_before = { position: grid[position] for position in grid.positions() } pos1 = Position(0, 0) pos2 = Position(1, 1) grid.swap(pos1, pos2) # caching positions and objects after swap objects_after = {position: grid[position] for position in grid.positions()} # testing swapped objects assert objects_before[pos1] is objects_after[pos2] assert objects_before[pos2] is objects_after[pos1] # testing all other objects are the same for position in grid.positions(): if position not in (pos1, pos2): assert objects_before[position] is objects_after[position]
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 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 reset_rooms( # pylint: disable=too-many-locals height: int, width: int, layout: Tuple[int, int], *, rng: Optional[rnd.Generator] = None, ) -> State: rng = get_gv_rng_if_none(rng) # TODO test creation (e.g. count number of walls, goals, check held item) layout_height, layout_width = layout y_splits = np.linspace( 0, height - 1, num=layout_height + 1, dtype=int, ) if len(y_splits) != len(set(y_splits)): raise ValueError( f'insufficient height ({height}) for layout ({layout})') x_splits = np.linspace( 0, width - 1, num=layout_width + 1, dtype=int, ) if len(x_splits) != len(set(x_splits)): raise ValueError( f'insufficient width ({height}) for layout ({layout})') grid = Grid(height, width) draw_room_grid(grid, y_splits, x_splits, Wall) # passages in horizontal walls for y in y_splits[1:-1]: for x_from, x_to in mitt.pairwise(x_splits): x = rng.integers(x_from + 1, x_to) grid[y, x] = Floor() # passages in vertical walls for y_from, y_to in mitt.pairwise(y_splits): for x in x_splits[1:-1]: y = rng.integers(y_from + 1, y_to) grid[y, x] = Floor() # sample agent and goal positions agent_position, goal_position = rng.choice( [ position for position in grid.positions() if isinstance(grid[position], Floor) ], size=2, replace=False, ) agent_orientation = rng.choice(list(Orientation)) grid[goal_position] = Goal() agent = Agent(agent_position, agent_orientation) return State(grid, agent)
def test_grid_positions(grid: Grid, expected: int): positions = set(grid.positions()) assert len(positions) == expected for position in positions: assert position in grid