Exemple #1
0
def test_position_from_position_or_tuple(y: int, x: int):
    position = Position(y, x)
    position_from_position = Position.from_position_or_tuple(position)
    assert isinstance(position_from_position, Position)
    assert position_from_position is position

    position_from_tuple = Position.from_position_or_tuple((y, x))
    assert isinstance(position_from_tuple, Position)

    assert position_from_position == position_from_tuple
Exemple #2
0
def updated_agent_position_if_unobstructed(agent_pos: PositionOrTuple,
                                           agent_orientation: Orientation,
                                           action: Action) -> Position:
    """Returns the desired/intended position according to `action`

    NOTE: Assumes action is successful and next position is not blocking agent

    Args:
        agent_pos (`Position`): current agent position
        action (`Action`): action taken by agent

    Returns:
        Position: next position
    """
    agent_pos = Position.from_position_or_tuple(agent_pos)

    if action not in TRANSLATION_ACTIONS:
        return agent_pos

    # Map directions to relative orientation
    direction_to_relative_orientation = {
        Action.MOVE_FORWARD: agent_orientation,
        Action.MOVE_LEFT: agent_orientation.rotate_left(),
        Action.MOVE_RIGHT: agent_orientation.rotate_right(),
        Action.MOVE_BACKWARD: agent_orientation.rotate_back(),
    }

    delta = direction_to_relative_orientation[action].as_position()
    return agent_pos + delta
Exemple #3
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)
Exemple #4
0
def draw_cartesian_product(grid: Grid, ys: Iterable[int], xs: Iterable[int],
                           factory: GridObjectFactory) -> List[Position]:
    """use factory-created grid-objects to draw on grid"""
    positions = [Position(y, x) for y in ys for x in xs]
    for position in positions:
        grid[position] = factory()

    return positions
Exemple #5
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
Exemple #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)
Exemple #7
0
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 test_proportional_to_distance_default(
    position: PositionOrTuple,
    kwargs,
    expected: float,
    forbidden_state_maker,
    forbidden_action_maker,
):
    state = forbidden_state_maker()
    action = forbidden_action_maker()
    next_state = make_5x5_goal_state()
    # TODO find better way to construct this state
    next_state.agent.position = Position.from_position_or_tuple(position)

    reward = proportional_to_distance(state,
                                      action,
                                      next_state,
                                      object_type=Goal,
                                      **kwargs)
    assert round(reward, 7) == expected
Exemple #9
0
def frontal_line_of_sight(
        state: State,
        *,
        observation_space: ObservationSpace,
        rng: Optional[rnd.Generator] = None,  # pylint: disable=unused-argument
) -> Observation:
    """only tiles in front of the agent can be seen"""

    # get agent's POV grid
    area = state.agent.get_pov_area(observation_space.area)
    observation_grid = state.grid.subgrid(area).change_orientation(
        state.agent.orientation)

    # hiding all tiles which are not directly in front of agent
    for position in observation_grid.positions():
        if (
                # the tile is not in the same column as the agent
                position.x == observation_space.agent_position.x
                # or the tile is behind the agent
                or position.y < observation_space.agent_position.y):
            observation_grid[position] = Hidden()

    # boolean flag to detect whether the line of sight has run into a
    # non-transparent object
    found_non_transparent = False

    # for every y-coordinate in front of the agent
    for y in range(observation_space.agent_position.y - 1, -1, -1):
        position = Position(y, observation_space.agent_position.x)

        # hide object if we have already encountered a non-transparent object
        if found_non_transparent:
            observation_grid[position] = Hidden()

        # update the boolean flag if object is non-transparent
        found_non_transparent |= not observation_grid[position].transparent

    observation_agent = Agent(observation_space.agent_position, Orientation.N,
                              state.agent.obj)
    return Observation(observation_grid, observation_agent)
Exemple #10
0
def compute_rays_fancy(position: PositionOrTuple, area: Area) -> List[Ray]:
    """Returns rays obtained by targeting edge points.

    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 a direction until the area is
    left.  This method will search in the directions towards all other cell
    edges.

    Args:
        position (PositionOrTuple): initial position, must be in area.
        area (Area): boundary over rays.

    Returns:
        List[Ray]:
    """
    position = Position.from_position_or_tuple(position)

    # compute corners of each cell
    ys = np.linspace(area.ymin, area.ymax + 1, num=area.height + 1) - 0.5
    xs = np.linspace(area.xmin, area.xmax + 1, num=area.width + 1) - 0.5

    # center all positions
    ys = ys - position.y
    xs = xs - position.x

    # compute points and angles
    yys, xxs = np.meshgrid(ys, xs)
    radians = np.arctan2(yys, xxs)
    radians = np.sort(radians, axis=None)

    rays = [
        compute_ray(position, area, radians=rad, step_size=0.01)
        for rad in radians
    ]

    return rays
Exemple #11
0
def test_position_manhattan_distance(pos1: Position, pos2: Position,
                                     expected: float):
    assert Position.manhattan_distance(pos1, pos2) == expected
Exemple #12
0
def test_position_euclidean_distance(pos1: Position, pos2: Position,
                                     expected: float):
    assert Position.euclidean_distance(pos1, pos2) == expected
Exemple #13
0
        assert visibility.all()


@pytest.mark.parametrize(
    'objects,position,expected_int',
    [
        (
            [
                [Floor(), Floor(), Floor(),
                 Floor(), Floor()],
                [Floor(), Floor(), Floor(),
                 Floor(), Floor()],
                [Floor(), Floor(), Floor(),
                 Floor(), Floor()],
            ],
            Position(2, 2),
            [
                [1, 1, 1, 1, 1],
                [1, 1, 1, 1, 1],
                [1, 1, 1, 1, 1],
            ],
        ),
        (
            [
                [Floor(), Floor(), Floor(),
                 Floor(), Floor()],
                [Floor(), Wall(), Wall(),
                 Wall(), Floor()],
                [Floor(), Wall(), Floor(),
                 Wall(), Floor()],
            ],
Exemple #14
0
    [
        (Area((0, 1), (0, 2)), Area((0, 1), (0, 2)), True),
        (Area((0, 1), (0, 2)), Area((-1, 1), (-2, 2)), False),
        #
        (Area((-1, 1), (-2, 2)), Area((0, 1), (0, 2)), False),
        (Area((-1, 1), (-2, 2)), Area((-1, 1), (-2, 2)), True),
    ],
)
def test_area_eq(area1: Area, area2: Area, expected: bool):
    assert (area1 == area2) == expected


@pytest.mark.parametrize(
    'orientation,dist,delta_position',
    [
        (Orientation.N, 1, Position(-1, 0)),
        (Orientation.N, 2, Position(-2, 0)),
        #
        (Orientation.S, 1, Position(1, 0)),
        (Orientation.S, 2, Position(2, 0)),
        #
        (Orientation.E, 1, Position(0, 1)),
        (Orientation.E, 2, Position(0, 2)),
        #
        (Orientation.W, 1, Position(0, -1)),
        (Orientation.W, 2, Position(0, -2)),
    ],
)
def test_orientation_as_position(orientation: Orientation, dist: int,
                                 delta_position: Position):
    assert orientation.as_position(dist) == delta_position
Exemple #15
0
def test_grid_get_item():
    grid = Grid(3, 4)

    pos = Position(0, 0)
    assert isinstance(grid[pos], Floor)
    assert grid[pos] is grid[pos]
Exemple #16
0
        ((1, 2), Orientation.S, Area((1, 7), (-1, 5))),
        ((1, 2), Orientation.E, Area((-2, 4), (2, 8))),
        ((1, 2), Orientation.W, Area((-2, 4), (-4, 2))),
    ],
)
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


@pytest.mark.parametrize(
    'position,orientation,delta_position,expected',
    [
        ((0, 0), Orientation.N, Position(1, -1), (1, -1)),
        ((0, 0), Orientation.S, Position(1, -1), (-1, 1)),
        ((0, 0), Orientation.E, Position(1, -1), (-1, -1)),
        ((0, 0), Orientation.W, Position(1, -1), (1, 1)),
        ((1, 2), Orientation.N, Position(2, -2), (3, 0)),
        ((1, 2), Orientation.S, Position(2, -2), (-1, 4)),
        ((1, 2), Orientation.E, Position(2, -2), (-1, 0)),
        ((1, 2), Orientation.W, Position(2, -2), (3, 4)),
    ],
)
def test_agent_position_relative(
    position: PositionOrTuple,
    orientation: Orientation,
    delta_position: Position,
    expected: PositionOrTuple,
):
Exemple #17
0
def test_delta_position_rotate_basis(
    delta_position: Position,
    orientation: Orientation,
    expected: Position,
):
    assert delta_position.rotate(orientation) == expected