def test_move_of_non_existent_character(self, character,
                                         non_existent_character):
     roster = Roster.for_mapping({Point(0, 0): character},
                                 Area(Point(0, 0), Point(5, 5)))
     move = Move(non_existent_character, Point(1, 1), Point(2, 1))
     with pytest.raises(ValueError):
         move.next_roster(roster)
    def test_move_to_occupied_position(self, mover, obstacle):
        positions = {Point(0, 0): mover, Point(1, 1): obstacle}

        roster = Roster.for_mapping(positions, area_containing(positions))
        move = Move(mover, Point(0, 0), Point(1, 1))
        with pytest.raises(ValueError):
            move.next_roster(roster)
    def test_preserves_instigator(self, instigator, target):
        positions = {Point(0, 0): instigator, Point(1, 1): target}

        roster = Roster.for_mapping(positions, area_containing(positions))
        paint = ChangeCharacter(instigator, Point(1, 1), paint_blue)
        new_roster = paint.next_roster(roster)
        assert new_roster.character_at(Point(0, 0)) is instigator
def area_containing(points):
    min_x = min((p.x for p in points), default=0)
    min_y = min((p.y for p in points), default=0)
    max_x = max((p.x for p in points), default=0)
    max_y = max((p.y for p in points), default=0)

    return Area(lower=Point(min_x, min_y), upper=Point(max_x + 1, max_y + 1))
Esempio n. 5
0
 def turn(self, turn):
     a, b = self.velocity
     if turn == Robot.LEFT:
         return Point((-b, a))
     elif turn == Robot.RIGHT:
         return Point((b, -a))
     raise "Invalid turn"
Esempio n. 6
0
def travel(stretch, origin):
    vector = switch(lambda direction, length: direction, {
        'U': lambda direction, length: Point((0, length)),
        'R': lambda direction, length: Point((length, 0)),
        'D': lambda direction, length: Point((0, -length)),
        'L': lambda direction, length: Point((-length, 0)),
    })
    return Point(origin) + vector(**stretch)
Esempio n. 7
0
 def positions(self) -> Generator[Tuple[Point, BarrierPoint], None, None]:
     for point in self.points:
         bp = BarrierPoint(
             above=self.occupied(Point(point.x, point.y - 1)),
             below=self.occupied(Point(point.x, point.y + 1)),
             left=self.occupied(Point(point.x - 1, point.y)),
             right=self.occupied(Point(point.x + 1, point.y)),
         )
         yield (point, bp)
    def test_changes_target(self, instigator):
        target = Character(colour="red")
        positions = {Point(0, 0): instigator, Point(1, 1): target}

        roster = Roster.for_mapping(positions, area_containing(positions))
        paint = ChangeCharacter(instigator, Point(1, 1), paint_blue)
        new_roster = paint.next_roster(roster)

        new_character = new_roster.character_at(Point(1, 1))
        assert new_character is not None
        assert new_character.colour == "blue"
 def test_viewpoint_multiple_characters(self, char1, char2):
     roster = Roster.for_mapping(
         {
             Point(1, 1): char1,
             Point(2, 0): char2
         },
         area=Area(Point(0, 0), Point(3, 3)),
     )
     viewpoint = Viewpoint(Point(0, 1), roster)
     assert viewpoint.occupied_points_in(
         BoundingBox.range(1)) == {Vector(1, 0)}
     assert viewpoint.occupied_points_in(BoundingBox.range(5)) == {
         Vector(1, 0),
         Vector(2, -1),
     }
Esempio n. 10
0
def rosters(draw,
            inhabitants=st.one_of(st.builds(default_human),
                                  st.builds(default_zombie))):
    width, height = draw(world_dimensions), draw(world_dimensions)
    assume(width > 0)
    assume(height > 0)
    area = Area(Point(0, 0), Point(width, height))
    points = st.builds(
        Point,
        st.integers(min_value=0, max_value=width - 1),
        st.integers(min_value=0, max_value=height - 1),
    )
    characters = draw(st.dictionaries(points, inhabitants))
    return Roster.partitioned(characters,
                              area=area,
                              partition_func=LifeState.for_character)
Esempio n. 11
0
 def from_string(self, string):
     self.update({
         Point((i, j)): char
         for j, line in enumerate(string.split('\n'))
         for i, char in enumerate(list(line))
     })
     return self
 def test_dead_human(self):
     dead_human = Character(LifeState.DEAD)
     world = World(
         width=3,
         height=1,
         positions=[(Point(1, 0), dead_human)],
     )
     renderer = Renderer(world)
     assert renderer.lines == [". \U0001F480 . "]
Esempio n. 13
0
    def _split(self) -> Tuple[Area, Area, LowerFunc]:
        if self._area.width >= self._area.height:
            # Split horizontally
            midpoint_x = (self._area._lower.x + self._area._upper.x) // 2
            lower_area = Area(self._area._lower,
                              Point(midpoint_x, self._area._upper.y))
            upper_area = Area(Point(midpoint_x, self._area._lower.y),
                              self._area._upper)
            lower_func = lambda point: point.x < midpoint_x

            return (lower_area, upper_area, lower_func)
        else:
            # Split vertically
            midpoint_y = (self._area._lower.y + self._area._upper.y) // 2
            lower_area = Area(self._area._lower,
                              Point(self._area._upper.x, midpoint_y))
            upper_area = Area(Point(self._area._lower.x, midpoint_y),
                              self._area._upper)
            lower_func = lambda point: point.y < midpoint_y

            return (lower_area, upper_area, lower_func)
Esempio n. 14
0
def random_barriers(counter: Iterable[Any], area: Area) -> Barriers:
    def x_coord() -> int:
        return random.randint(area._lower.x, area._upper.x - 1)

    def y_coord() -> int:
        return random.randint(area._lower.y, area._upper.y - 1)

    barrier_areas = set()
    for _ in counter:
        if random.choice([True, False]):
            # Vertical barrier
            x1 = x_coord()
            x2 = x1 + 1
            y1, y2 = sorted([y_coord(), y_coord()])
        else:
            # Horizontal barrier
            x1, x2 = sorted([x_coord(), x_coord()])
            y1 = y_coord()
            y2 = y1 + 1

        barrier_areas.add(Area(Point(x1, y1), Point(x2, y2)))

    return Barriers.for_areas(barrier_areas)
Esempio n. 15
0
def find_path(grid):
    robot = next(coords for coords in grid if grid[coords] in '<^>v')
    path = [Point(robot)]
    while True:
        adjacent = [
            p for p in path[-1].adjacent(1)
            if walkable(p, grid) and (len(path) < 2 or p != path[-2])
        ]
        go_straight = lambda position: -1 if len(path) < 2 or (path[-1] - path[
            -2]) == (position - path[-1]) else 1
        move = min(adjacent, key=go_straight, default=None)
        # final position reached; exit
        if move is None:
            break
        path.append(move)
    return path
Esempio n. 16
0
def trace(asteroids):
    for i in range(len(asteroids)):
        asteroid = asteroids[i]
        for j in range(i + 1, len(asteroids)):
            other = asteroids[j]
            x, y = (a - b for a, b in zip(asteroid.coords, other.coords))
            slope = (y / x) if x != 0 else infinity
            positive = other.coords > asteroid.coords
            asteroid.traces[(slope, positive)].append(other)
            other.traces[(slope, not positive)].append(asteroid)

    # sort by distance
    for asteroid in asteroids:
        sortByDistance = compose(Point(asteroid.coords).manhattan, Point, attr('coords'))
        for slope in asteroid.traces:
            asteroid.traces[slope] = sorted(asteroid.traces[slope], key=sortByDistance)
        
    return asteroids
Esempio n. 17
0
    def test_zombie_approaches_human(self):
        zombie = default_zombie()
        human = default_human()

        characters = {Point(0, 0): zombie, Point(2, 2): human}
        area = Area(Point(0, 0), Point(3, 3))
        roster = Roster.partitioned(characters,
                                    area=area,
                                    partition_func=LifeState.for_character)

        roster = Tick(roster).next()

        assert sorted(roster.positions) == [(Point(1, 1), zombie),
                                            (Point(2, 2), human)]
Esempio n. 18
0
    def test_height(self):
        lower = Point(0, 0)
        upper = Point(2, 2)
        area = Area(lower, upper)

        assert area.height == 2
Esempio n. 19
0
    def test_width(self):
        lower = Point(0, 0)
        upper = Point(2, 2)
        area = Area(lower, upper)

        assert area.width == 2
Esempio n. 20
0
 def test_construction_from_zero(self, width, height):
     assert Area.from_zero(width, height) == Area(Point(0, 0),
                                                  Point(width, height))
Esempio n. 21
0
 def test_single_arg_constructor(self):
     with pytest.raises(TypeError):
         Area(Point(1, 3))  # type: ignore
Esempio n. 22
0
class TestArea:
    def test_no_arg_constructor(self):
        with pytest.raises(TypeError) as exc:
            Area()  # type: ignore

    def test_single_arg_constructor(self):
        with pytest.raises(TypeError):
            Area(Point(1, 3))  # type: ignore

    @given(points(), points())
    def test_two_point_constructor(self, point_a, point_b):
        Area(point_a, point_b)

    @given(st.integers(), st.integers())
    def test_construction_from_zero(self, width, height):
        assert Area.from_zero(width, height) == Area(Point(0, 0),
                                                     Point(width, height))

    @given(ordered_points())
    def test_contains_lower_bound(self, points):
        lower, upper = points
        assert lower in Area(lower, upper)

    def test_width(self):
        lower = Point(0, 0)
        upper = Point(2, 2)
        area = Area(lower, upper)

        assert area.width == 2

    def test_height(self):
        lower = Point(0, 0)
        upper = Point(2, 2)
        area = Area(lower, upper)

        assert area.height == 2

    @given(points(), points())
    def test_excludes_upper_bound(self, lower, upper):
        assert upper not in Area(lower, upper)

    @given(ordered_points())
    def test_includes_midpoint(self, points):
        lower, upper = points
        midpoint = Point((lower.x + upper.x) // 2, (lower.y + upper.y) // 2)
        assert midpoint in Area(lower, upper)

    def test_excludes_on_x_coordinate(self):
        area = Area(Point(0, 0), Point(3, 3))
        assert Point(4, 1) not in area

    def test_excludes_on_y_coordinate(self):
        area = Area(Point(0, 0), Point(3, 3))
        assert Point(1, 4) not in area

    @given(
        st.builds(Area, points(bound=ITERATION_BOUND),
                  points(bound=ITERATION_BOUND)))
    def test_iteration_covers_area(self, area):
        area_points = list(area)
        for point in area:
            assert point in area_points

    @given(
        area=st.builds(Area, points(bound=ITERATION_BOUND),
                       points(bound=ITERATION_BOUND)),
        point=points(),
    )
    @example(Area(Point(-2, -2), Point(3, 3)), Point(2, 3))
    def test_iteration_is_limited_to_area(self, area, point):
        assume(point not in area)
        assert point not in list(area)

    @given(points(), points(), points())
    def test_from_origin_type(self, lower, upper, origin):
        area = Area(lower, upper)
        assert isinstance(area.from_origin(origin), BoundingBox)

    @given(st.builds(Area, points(), points()), points(), points())
    @example(Area(Point(0, 0), Point(2, 2)), Point(0, 0), Point(1, 1))
    def test_from_origin_containment(self, area, origin, point):
        from_origin = area.from_origin(origin)

        assert (point in area) == ((point - origin) in from_origin)

    @given(st.builds(Area, points(), points()), points())
    def test_areas_and_boxes(self, area, origin):
        assert area.from_origin(origin).to_area(origin) == area

    @given(overlapping_areas())
    def test_overlapping_areas(self, areas):
        area_a, area_b = areas
        assert area_a.intersects_with(area_b)
        assert area_b.intersects_with(area_a)

    @given(non_overlapping_areas())
    @example([Area(Point(0, 0), Point(2, 2)), Area(Point(2, 0), Point(4, 2))])
    @example([Area(Point(0, 0), Point(2, 2)), Area(Point(0, 2), Point(2, 4))])
    def test_non_overlapping_areas(self, areas):
        area_a, area_b = areas
        assert not area_a.intersects_with(area_b)
        assert not area_b.intersects_with(area_a)

    @given(
        areas=st.lists(st.builds(Area, points(), points()), min_size=2),
        point=points(),
    )
    def test_point_outside_intersection(self, areas, point):
        assume(any(point not in area for area in areas))
        intersection = reduce(lambda a, b: a.intersect(b), areas)
        assert point not in intersection

    @given(points_and_containing_areas())
    def test_point_inside_intersection(self, point_and_areas):
        point, areas = point_and_areas
        intersection = reduce(lambda a, b: a.intersect(b), areas)
        assert point in intersection
Esempio n. 23
0
 def test_point_addition_fails(self):
     # Adding a point to a point doesn't make sense
     with pytest.raises(AttributeError):
         Point(2, 5) + Point(3, 2)  # type: ignore
Esempio n. 24
0
 def test_no_arg_constructor(self):
     with pytest.raises(TypeError) as exc:
         Point()  # type: ignore
 def test_zombie(self):
     zombie = Character(LifeState.UNDEAD)
     world = World(width=3, height=1, positions=[(Point(1, 0), zombie)])
     renderer = Renderer(world)
     assert renderer.lines == [". \U0001F9DF . "]
 def test_human(self):
     human = Character(LifeState.LIVING)
     world = World(width=3, height=1, positions=[(Point(1, 0), human)])
     renderer = Renderer(world)
     assert renderer.lines == [". \U0001F9D1 . "]
Esempio n. 27
0
 def add_portal(first_letter, second_letter, position):
     name = grid[first_letter] + grid[second_letter]
     portals[name].append(Point(position))
Esempio n. 28
0
 def test_includes_midpoint(self, points):
     lower, upper = points
     midpoint = Point((lower.x + upper.x) // 2, (lower.y + upper.y) // 2)
     assert midpoint in Area(lower, upper)
Esempio n. 29
0
 def test_excludes_on_y_coordinate(self):
     area = Area(Point(0, 0), Point(3, 3))
     assert Point(1, 4) not in area
Esempio n. 30
0
 def test_accepts_two_coordinates(self, x, y):
     point = Point(x, y)
     assert point.x == x
     assert point.y == y