Ejemplo n.º 1
0
def draw_area(grid: Grid, area: Area, factory: GridObjectFactory, *,
              fill) -> List[Position]:
    """use factory-created grid-objects to draw area on grid"""
    positions = list(area.positions() if fill else area.positions_border())
    for pos in positions:
        grid[pos] = factory()

    return positions
Ejemplo n.º 2
0
    def __init__(
        self,
        grid_shape: Shape,
        object_types: Sequence[Type[GridObject]],
        colors: Sequence[Color],
    ):
        if grid_shape.width % 2 == 0:
            raise ValueError('shape should have an odd width')

        self.grid_shape = grid_shape
        self.object_types = list(object_types)
        self.colors = set(colors) | {Color.NONE}

        self._grid_object_types = set(object_types) | {Hidden}
        self._agent_object_types = set(object_types) | {NoneGridObject}

        # TODO eventually let this substitute the `grid_shape` input altogether
        # this area represents the observable area, with (0, 0) representing
        # the agent's position, when the agent is pointing N
        self.area = Area(
            (-self.grid_shape.height + 1, 0),
            (-(self.grid_shape.width // 2), self.grid_shape.width // 2),
        )

        # NOTE this position is relative to the top right coordinate of the area
        self.agent_position = Position(self.area.height - 1,
                                       self.area.width // 2)
Ejemplo n.º 3
0
def stochastic_raytracing_visibility(  # TODO add test
    grid: Grid,
    position: Position,
    *,
    rng: Optional[rnd.Generator] = None,
) -> np.ndarray:
    rng = get_gv_rng_if_none(rng)

    area = Area((0, grid.height - 1), (0, grid.width - 1))
    rays = cached_compute_rays_fancy(position, area)

    counts_num = np.zeros((area.height, area.width), dtype=int)
    counts_den = np.zeros((area.height, area.width), dtype=int)

    for ray in rays:
        light = True
        for pos in ray:
            if light:
                counts_num[pos.y, pos.x] += 1

            counts_den[pos.y, pos.x] += 1

            light = light and grid[pos].transparent

    probs = np.nan_to_num(counts_num / counts_den)
    visibility = probs <= rng.random(probs.shape)
    return visibility
Ejemplo n.º 4
0
def raytracing_visibility(
        grid: Grid,
        position: Position,
        *,
        rng: Optional[rnd.Generator] = None,  # pylint: disable=unused-argument
) -> np.ndarray:

    area = Area((0, grid.height - 1), (0, grid.width - 1))
    rays = cached_compute_rays_fancy(position, area)

    counts_num = np.zeros((area.height, area.width), dtype=int)
    counts_den = np.zeros((area.height, area.width), dtype=int)

    for ray in rays:
        light = True
        for pos in ray:
            if light:
                counts_num[pos.y, pos.x] += 1

            counts_den[pos.y, pos.x] += 1

            light = light and grid[pos].transparent

    # TODO add as parameter to function
    visibility = counts_num > 0  # at least one ray makes it
    # visibility = counts_num > 0.5 * counts_den # half of the rays make it
    # visibility = counts_num > 0.1 * counts_den  # 10% of the rays make it
    # visibility = counts_num > 1  # at least 2 rays make it

    return visibility
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
def compute_ray(
    position: PositionOrTuple,
    area: Area,
    *,
    radians: float,
    step_size: float,
    unique: bool = True,
) -> Ray:
    """Returns a ray from a given position.

    A ray is a list of positions which are hit by a direct line starting at the
    center of the given position and moving along the given direction (in
    radians) until the area is left.

    Args:
        position (PositionOrTuple): initial position, must be in area.
        area (Area): boundary over rays.
        radians (float): ray direction.
        step_size (float): ray step granularity.
        unique (bool): If true, the same position can appear twice in the ray.

    Returns:
        Ray: ray from the given position until the area boundary
    """

    if not area.contains(position):
        raise ValueError(f'position {position} must be inside area {area}')

    position = Position.from_position_or_tuple(position)

    y0, x0 = float(position.y), float(position.x)
    dy = step_size * math.sin(radians)
    dx = step_size * math.cos(radians)

    ys = (y0 + i * dy for i in itt.count())
    xs = (x0 + i * dx for i in itt.count())
    positions: Iterable[Position]
    positions = (Position(round(y), round(x)) for y, x in zip(ys, xs))
    positions = itt.takewhile(area.contains, positions)
    positions = mitt.unique_everseen(positions) if unique else positions

    return list(positions)
Ejemplo n.º 7
0
        assert isinstance(grid[y, 0], Wall)
        assert isinstance(grid[y, grid.width - 1], Wall)

    for x in range(grid.width):
        assert isinstance(grid[0, x], Wall)
        assert isinstance(grid[grid.height - 1, x], Wall)

    for y in range(1, grid.height - 1):
        for x in range(1, grid.width - 1):
            assert isinstance(grid[y, x], Floor)


@pytest.mark.parametrize(
    'grid,area,expected_num_walls',
    [
        (Grid(4, 5), Area((0, 3), (0, 4)), 14),
        (Grid(4, 5), Area((1, 2), (1, 3)), 6),
    ],
)
def test_draw_room(grid: Grid, area: Area, expected_num_walls: int):
    positions = draw_room(grid, area, 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


@pytest.mark.parametrize(
    'grid,ys,xs,expected_num_walls',
    [
        (Grid(3, 5), [0, 2], [0, 2, 4], 13),
Ejemplo n.º 8
0
def partial_visibility(
        grid: Grid,
        position: Position,
        *,
        rng: Optional[rnd.Generator] = None,  # pylint: disable=unused-argument
) -> np.ndarray:

    if position.y != grid.height - 1:
        #  gym-minigrid does not handle this case, and we are not currently
        #  generalizing it
        raise NotImplementedError

    visibility = np.zeros((grid.height, grid.width), dtype=bool)
    visibility[position.y, position.x] = True  # agent

    # front
    x = position.x
    for y in range(position.y - 1, -1, -1):
        visibility[y, x] = visibility[y + 1, x] and grid[y + 1, x].transparent

    # right
    y = position.y
    for x in range(position.x + 1, grid.width):
        visibility[y, x] = visibility[y, x - 1] and grid[y, x - 1].transparent

    # left
    y = position.y
    for x in range(position.x - 1, -1, -1):
        visibility[y, x] = visibility[y, x + 1] and grid[y, x + 1].transparent

    # top left
    positions = diagonal_strides(
        Area(
            (0, position.y - 1),
            (0, position.x - 1),
        ),
        StrideDirection.NW,
    )
    for p in positions:
        visibility[p.y, p.x] = (
            (grid[p.y + 1, p.x].transparent and visibility[p.y + 1, p.x])
            or (grid[p.y, p.x + 1].transparent and visibility[p.y, p.x + 1])
            or (grid[p.y + 1, p.x + 1].transparent
                and visibility[p.y + 1, p.x + 1]))

    # top right
    positions = diagonal_strides(
        Area(
            (0, position.y - 1),
            (position.x + 1, grid.width - 1),
        ),
        StrideDirection.NE,
    )
    for p in positions:
        visibility[p.y, p.x] = (
            (grid[p.y + 1, p.x].transparent and visibility[p.y + 1, p.x])
            or (grid[p.y, p.x - 1].transparent and visibility[p.y, p.x - 1])
            or (grid[p.y + 1, p.x - 1].transparent
                and visibility[p.y + 1, p.x - 1]))

    return visibility
Ejemplo n.º 9
0
from typing import List

import pytest

from gym_gridverse.geometry import Area, PositionOrTuple
from gym_gridverse.utils.raytracing import (
    compute_ray,
    compute_rays,
    compute_rays_fancy,
)


@pytest.mark.parametrize(
    'position,area',
    [
        ((2, 0), Area((-1, 1), (-2, 2))),
        ((-2, 0), Area((-1, 1), (-2, 2))),
        ((0, 3), Area((-1, 1), (-2, 2))),
        ((0, -3), Area((-1, 1), (-2, 2))),
    ],
)
def test_compute_ray_value_error(position: PositionOrTuple, area: Area):
    with pytest.raises(ValueError):
        compute_ray(position, area, radians=0.0, step_size=0.01)


@pytest.mark.parametrize(
    'position,area,degrees,expected',
    [
        # from center
        ((0, 0), Area((-1, 1), (-2, 2)), 0, [(0, 0), (0, 1), (0, 2)]),
Ejemplo n.º 10
0
def test_get_pov_area(position: PositionOrTuple, orientation: Orientation,
                      expected: Area):
    relative_area = Area((-6, 0), (-3, 3))
    agent = Agent(position, orientation)
    assert agent.get_pov_area(relative_area) == expected
Ejemplo n.º 11
0
    # 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]


@pytest.mark.parametrize(
    'area,expected_objects',
    [
        (
            Area((-1, 3), (-1, 4)),
            [
                [Hidden(),
                 Hidden(),
                 Hidden(),
                 Hidden(),
                 Hidden(),
                 Hidden()],
                [Hidden(),
                 Wall(), Floor(),
                 Wall(), Floor(),
                 Hidden()],
                [Hidden(),
                 Floor(), Wall(),
                 Floor(), Wall(),
                 Hidden()],
Ejemplo n.º 12
0
def test_area_translate(area: Area, position: PositionOrTuple, expected: Area):
    assert area.translate(position) == expected
Ejemplo n.º 13
0
def test_area_contains(area: Area, position: PositionOrTuple, expected: bool):
    assert area.contains(position) == expected
Ejemplo n.º 14
0
def test_area_rotate(area: Area, orientation: Orientation, expected: Area):
    assert area.rotate(orientation) == expected
Ejemplo n.º 15
0
import pytest

from gym_gridverse.geometry import (
    Area,
    Orientation,
    Pose,
    Position,
    PositionOrTuple,
    StrideDirection,
    diagonal_strides,
    get_manhattan_boundary,
)


@pytest.mark.parametrize('area,expected', [(Area((0, 1), (0, 2)), 2),
                                           (Area((-1, 1), (-2, 2)), 3)])
def test_area_height(area: Area, expected: int):
    assert area.height == expected


@pytest.mark.parametrize('area,expected', [(Area((0, 1), (0, 2)), 3),
                                           (Area((-1, 1), (-2, 2)), 5)])
def test_area_width(area: Area, expected: int):
    assert area.width == expected


@pytest.mark.parametrize(
    'area,expected',
    [(Area((0, 1), (0, 2)), (0, 0)), (Area((-1, 1), (-2, 2)), (-1, -2))],
)