Exemplo n.º 1
0
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)
Exemplo n.º 2
0
def test_floor_properties():
    """ Basic stupid tests for floor grid object """

    floor = Floor()

    assert floor.transparent
    assert not floor.blocks
    assert floor.color == Color.NONE
    assert not floor.can_be_picked_up
    assert floor.state_index == 0

    assert floor.can_be_represented_in_state()
    assert floor.render_as_char() == ' '
    assert floor.num_states() == 1
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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())
Exemplo n.º 5
0
def test_box_basic_properties():
    """Tests basic properties of box """

    box = Box(Floor())

    assert box.transparent
    assert box.blocks
    assert box.color == Color.NONE
    assert not box.can_be_picked_up
    assert box.state_index == 0

    assert not box.can_be_represented_in_state()
    assert box.render_as_char() == 'b'
    assert box.num_states() == 1
Exemplo n.º 6
0
def pickup_mechanics(
        state: State,
        action: Action,
        *,
        rng: Optional[rnd.Generator] = None,  # pylint: disable=unused-argument
) -> None:
    """Implements the effect of the pickup and drop action

    Pickup applies to the item *in front* of the agent
    There are multiple scenarii

    * There is no (pick-up-able) item to pickup under the agent:
        * The agent is not holding any object -> No effect
        * The agent is holding an object:
            * Position in front of agent is floor -> drop current object
            * Position in front is not a floor -> No effect
    * There is a (pick-up-able) item to pickup under the agent:
        * The agent is not holding any object -> Pick up, put floor in stead
        * The agent is holding an object -> Swap items

    Args:
        state (`State`):
        action (`Action`):
        rng (`Generator, optional`)

    Returns:
        None:
    """

    if action != Action.PICK_N_DROP:
        return

    obj_in_front_of_agent = state.grid[state.agent.position_in_front()]
    obj_holding = state.agent.obj

    can_pickup = obj_in_front_of_agent.can_be_picked_up
    can_drop = isinstance(obj_in_front_of_agent, Floor) or can_pickup

    if not can_pickup and not can_drop:
        return

    state.grid[state.agent.position_in_front()] = (
        obj_holding if can_drop and not isinstance(obj_holding, NoneGridObject)
        else Floor()  # We know we are picking up if not dropping
    )

    # Know for sure that if not can_pickup then we have dropped
    state.agent.obj = obj_in_front_of_agent if can_pickup else NoneGridObject()
Exemplo n.º 7
0
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
Exemplo n.º 8
0
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 simplest_reset(
        *,
        rng: Optional[rnd.Generator] = None,  # pylint: disable=unused-argument
) -> State:
    """smallest possible room with goal right in front of agent"""

    # constructed the grid directly from objects
    grid = Grid.from_objects([
        [Wall(), Wall(), Wall()],
        [Wall(), Goal(), Wall()],
        [Wall(), Floor(), Wall()],
        [Wall(), Wall(), Wall()],
    ])

    # positioning the agent in the above grid
    agent = Agent((2, 1), Orientation.N)

    return State(grid, agent)
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
Exemplo n.º 11
0
def _change_grid(observation: Observation):
    """changes one object in the grid"""
    observation.grid[0, 0] = (
        Wall() if isinstance(observation.grid[0, 0], Floor) else Floor()
    )
    assert observation.grid.shape == Shape(6, 5)
    assert isinstance(observation.grid[3, 0], Wall)


@pytest.mark.parametrize(
    'agent,expected_objects',
    [
        (
            Agent((2, 1), Orientation.N),
            [
                [Hidden(), Hidden(), Hidden(), Hidden(), Hidden()],
                [Hidden(), Hidden(), Hidden(), Hidden(), Hidden()],
                [Hidden(), Hidden(), Hidden(), Hidden(), Hidden()],
                [Hidden(), Hidden(), Hidden(), Hidden(), Hidden()],
                [Hidden(), Wall(), Wall(), Wall(), Hidden()],
                [Hidden(), Floor(), Floor(), Floor(), Hidden()],
            ],
        ),
        (
            Agent((0, 1), Orientation.S),
            [
                [Hidden(), Hidden(), Hidden(), Hidden(), Hidden()],
                [Hidden(), Hidden(), Hidden(), Hidden(), Hidden()],
                [Hidden(), Hidden(), Hidden(), Hidden(), Hidden()],
                [Hidden(), Hidden(), Hidden(), Hidden(), Hidden()],
                [Hidden(), Wall(), Wall(), Wall(), Hidden()],
                [Hidden(), Floor(), Floor(), Floor(), Hidden()],
            ],
        ),
        (
            Agent((2, 1), Orientation.E),
Exemplo n.º 13
0
    factory,
    full_visibility,
    minigrid_visibility,
    partial_visibility,
    raytracing_visibility,
)
from gym_gridverse.geometry import Position
from gym_gridverse.grid import Grid
from gym_gridverse.grid_object import Floor, GridObject, Wall


@pytest.mark.parametrize(
    'objects',
    [
        [
            [Floor(), Floor(), Floor()],
            [Floor(), Floor(), Floor()],
            [Floor(), Floor(), Floor()],
        ],
        [
            [Wall(), Wall(), Wall()],
            [Wall(), Wall(), Wall()],
            [Wall(), Wall(), Wall()],
        ],
    ],
)
def test_full_visibility(objects: Sequence[Sequence[GridObject]]):
    grid = Grid.from_objects(objects)
    for position in grid.positions():
        visibility = full_visibility(grid, position)
Exemplo n.º 14
0
def simple_state_without_object() -> State:
    """ Returns a 2x2 (empty) grid with an agent without an item """
    return State(
        Grid(height=2, width=2),
        Agent(position=(0, 0), orientation=Orientation.N, obj=Floor()),
    )
Exemplo n.º 15
0

@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()],
                [Hidden(),
                 Wall(), Floor(),
                 Wall(), Floor(),
                 Hidden()],
                [Hidden(),
                 Hidden(),
                 Hidden(),
                 Hidden(),
                 Hidden(),
Exemplo n.º 16
0
def reset_crossing(  # pylint: disable=too-many-locals
    height: int,
    width: int,
    num_rivers: int,
    object_type: Type[GridObject],
    *,
    rng: Optional[rnd.Generator] = None,
) -> State:
    """An environment with "rivers" to be crosses

    Creates a height x width (including wall) grid with random rows/columns of
    objects called "rivers". The agent needs to navigate river openings to
    reach the goal.  For example::

        #########
        #@    # #
        #### ####
        #     # #
        ## ######
        #       #
        #     # #
        #     #G#
        #########

    Args:
        height (`int`): odd height of grid
        width (`int`): odd width of grid
        num_rivers (`int`): number of `rivers`
        object_type (`Type[GridObject]`): river's object type
        rng: (`Generator, optional`)

    Returns:
        State:
    """
    if height < 5 or height % 2 == 0:
        raise ValueError(
            f"Crossing environment height must be odd and >= 5, given {height}"
        )

    if width < 5 or width % 2 == 0:
        raise ValueError(
            f"Crossing environment width must be odd and >= 5, given {width}")

    if num_rivers < 0:
        raise ValueError(
            f"Crossing environment number of walls must be >= 0, given {height}"
        )

    rng = get_gv_rng_if_none(rng)

    state = reset_empty(height, width)
    assert isinstance(state.grid[height - 2, width - 2], Goal)

    # token `horizontal` and `vertical` objects
    h, v = object(), object()

    # all rivers specified by orientation and position
    rivers = list(
        itt.chain(
            ((h, i) for i in range(2, height - 2, 2)),
            ((v, j) for j in range(2, width - 2, 2)),
        ))

    # sample subset of random rivers
    rng.shuffle(rivers)  # NOTE: faster than rng.choice
    rivers = rivers[:num_rivers]

    # create horizontal rivers without crossings
    rivers_h = sorted([pos for direction, pos in rivers if direction is h])
    for y in rivers_h:
        draw_line_horizontal(state.grid, y, range(1, width - 1), object_type)

    # create vertical rivers without crossings
    rivers_v = sorted([pos for direction, pos in rivers if direction is v])
    for x in rivers_v:
        draw_line_vertical(state.grid, range(1, height - 1), x, object_type)

    # sample path to goal
    path = [h] * len(rivers_v) + [v] * len(rivers_h)
    rng.shuffle(path)

    # create crossing
    limits_h = [0] + rivers_h + [height - 1]  # horizontal river boundaries
    limits_v = [0] + rivers_v + [width - 1]  # vertical river boundaries
    room_i, room_j = 0, 0  # coordinates of current "room"
    for step_direction in path:
        if step_direction is h:
            i = rng.integers(limits_h[room_i] + 1, limits_h[room_i + 1])
            j = limits_v[room_j + 1]
            room_j += 1

        elif step_direction is v:
            i = limits_h[room_i + 1]
            j = rng.integers(limits_v[room_j] + 1, limits_v[room_j + 1])
            room_i += 1

        else:
            assert False

        state.grid[i, j] = Floor()

    # Place agent on top left
    state.agent.position = (1, 1)  # type: ignore
    state.agent.orientation = Orientation.E

    return state
Exemplo n.º 17
0
        ('none_grid_object', {}),
        ('Hidden', {}),
        ('hidden', {}),
        ('Floor', {}),
        ('floor', {}),
        ('Wall', {}),
        ('wall', {}),
        ('Goal', {}),
        ('goal', {}),
        ('Door', {'status': 'LOCKED', 'color': 'RED'}),
        ('door', {'status': 'LOCKED', 'color': 'RED'}),
        ('Key', {'color': 'RED'}),
        ('key', {'color': 'RED'}),
        ('MovingObstacle', {}),
        ('moving_obstacle', {}),
        ('Box', {'obj': Floor()}),
        ('box', {'obj': Floor()}),
        ('Telepod', {'color': 'RED'}),
        ('telepod', {'color': 'RED'}),
    ],
)
def test_factory_valid(name: str, kwargs):
    factory(name, **kwargs)


@pytest.mark.parametrize(
    'name,kwargs,exception',
    [
        ('invalid', {}, ValueError),
        ('Door', {}, ValueError),
        ('door', {}, ValueError),
Exemplo n.º 18
0
def _change_grid(state: State):
    """changes one object in the grid"""
    state.grid[0,
               0] = (Wall() if isinstance(state.grid[0,
                                                     0], Floor) else Floor())
Exemplo n.º 19
0
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)
Exemplo n.º 20
0
    with patch(
        'gym_gridverse.envs.transition_functions._step_moving_obstacle',
        new=patched_step_moving_obstacle,
    ):
        step_moving_obstacles(state, Action.PICK_N_DROP)

    assert len(counts) == 4
    assert all(count == 1 for count in counts.values())


@pytest.mark.parametrize(
    'objects,expected_objects',
    [
        (
            [[Floor(), MovingObstacle(), MovingObstacle()]],
            [[MovingObstacle(), MovingObstacle(), Floor()]],
        ),
        (
            [[MovingObstacle(), Floor(), MovingObstacle()]],
            [[Floor(), MovingObstacle(), MovingObstacle()]],
        ),
        (
            [[MovingObstacle(), MovingObstacle(), Floor()]],
            [[MovingObstacle(), Floor(), MovingObstacle()]],
        ),
    ],
)
def test_step_moving_obstacles(
    objects: Sequence[Sequence[GridObject]],
    expected_objects: Sequence[Sequence[GridObject]],