Exemplo n.º 1
0
 def opposite_edge(cls, coordinate_with_farmer_side: CoordinateWithFarmerSide) -> CoordinateWithFarmerSide:
     if coordinate_with_farmer_side.farmer_side.get_side() == Side.TOP:
         return CoordinateWithFarmerSide(
             Coordinate(coordinate_with_farmer_side.coordinate.row - 1,
                        coordinate_with_farmer_side.coordinate.column),
             SideModificationUtil.opposite_farmer_side(coordinate_with_farmer_side.farmer_side)
         )
     elif coordinate_with_farmer_side.farmer_side.get_side() == Side.RIGHT:
         return CoordinateWithFarmerSide(
             Coordinate(coordinate_with_farmer_side.coordinate.row,
                        coordinate_with_farmer_side.coordinate.column + 1),
             SideModificationUtil.opposite_farmer_side(coordinate_with_farmer_side.farmer_side)
         )
     elif coordinate_with_farmer_side.farmer_side.get_side() == Side.BOTTOM:
         return CoordinateWithFarmerSide(
             Coordinate(coordinate_with_farmer_side.coordinate.row + 1,
                        coordinate_with_farmer_side.coordinate.column),
             SideModificationUtil.opposite_farmer_side(coordinate_with_farmer_side.farmer_side)
         )
     elif coordinate_with_farmer_side.farmer_side.get_side() == Side.LEFT:
         return CoordinateWithFarmerSide(
             Coordinate(coordinate_with_farmer_side.coordinate.row,
                        coordinate_with_farmer_side.coordinate.column - 1),
             SideModificationUtil.opposite_farmer_side(coordinate_with_farmer_side.farmer_side)
         )
Exemplo n.º 2
0
    def test_find_road(self):
        """
        Find the positions for a city with a top and a bottom
        """

        # Given
        game_state: CarcassonneGameState = CarcassonneGameState()

        crossroads = base_tiles["crossroads"]

        game_state.board = [[None for column in range(1)] for row in range(2)]

        game_state.board[0][0] = crossroads
        game_state.board[1][0] = crossroads

        # When
        road: Road = RoadUtil.find_road(game_state=game_state,
                                        road_position=CoordinateWithSide(
                                            Coordinate(0, 0), Side.BOTTOM))

        # Then
        self.assertTrue(road.finished)
        self.assertEqual(2, len(road.road_positions))
        self.assertIn(CoordinateWithSide(Coordinate(0, 0), Side.BOTTOM),
                      road.road_positions)
        self.assertIn(CoordinateWithSide(Coordinate(1, 0), Side.TOP),
                      road.road_positions)
Exemplo n.º 3
0
    def test_find_city(self):
        """
        Find the positions for a city with a top and a bottom
        """

        # Given
        game_state: CarcassonneGameState = CarcassonneGameState()

        city_top = base_tiles["city_top"]
        city_bottom = city_top.turn(2)

        game_state.board = [[None for column in range(1)] for row in range(2)]

        game_state.board[0][0] = city_bottom
        game_state.board[1][0] = city_top

        # When
        city: City = CityUtil.find_city(game_state=game_state,
                                        city_position=CoordinateWithSide(
                                            Coordinate(0, 0), Side.BOTTOM))

        # Then
        self.assertTrue(city.finished)
        self.assertEqual(2, len(city.city_positions))
        self.assertIn(CoordinateWithSide(Coordinate(0, 0), Side.BOTTOM),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(1, 0), Side.TOP),
                      city.city_positions)
Exemplo n.º 4
0
 def opposite_edge(cls, city_position: CoordinateWithSide):
     if city_position.side == Side.TOP:
         return CoordinateWithSide(Coordinate(city_position.coordinate.row - 1, city_position.coordinate.column),
                                   Side.BOTTOM)
     elif city_position.side == Side.RIGHT:
         return CoordinateWithSide(Coordinate(city_position.coordinate.row, city_position.coordinate.column + 1),
                                   Side.LEFT)
     elif city_position.side == Side.BOTTOM:
         return CoordinateWithSide(Coordinate(city_position.coordinate.row + 1, city_position.coordinate.column),
                                   Side.TOP)
     elif city_position.side == Side.LEFT:
         return CoordinateWithSide(Coordinate(city_position.coordinate.row, city_position.coordinate.column - 1),
                                   Side.RIGHT)
Exemplo n.º 5
0
    def possible_playing_positions(game_state: CarcassonneGameState,
                                   tile_to_play: Tile) -> [PlayingPosition]:
        if game_state.empty_board():
            return [
                PlayingPosition(coordinate=game_state.starting_position,
                                turns=0)
            ]

        playing_positions = []

        for row_index, board_row in enumerate(game_state.board):
            for column_index, column_tile in enumerate(board_row):
                if column_tile is not None:
                    continue

                for tile_turns in range(0, 4):
                    top = game_state.get_tile(row_index - 1, column_index)
                    bottom = game_state.get_tile(row_index + 1, column_index)
                    left = game_state.get_tile(row_index, column_index - 1)
                    right = game_state.get_tile(row_index, column_index + 1)

                    if TileFitter.fits(tile_to_play.turn(tile_turns),
                                       top=top,
                                       bottom=bottom,
                                       left=left,
                                       right=right,
                                       game_state=game_state):
                        playing_positions.append(
                            PlayingPosition(coordinate=Coordinate(
                                row=row_index, column=column_index),
                                            turns=tile_turns))

        return playing_positions
Exemplo n.º 6
0
    def test_find_cities(self):
        """
        Find cities left and right
        """

        # Given
        game_state: CarcassonneGameState = CarcassonneGameState()

        city_one_side_straight_road = base_tiles[
            "city_top_straight_road"].turn(3)
        city_with_road = inns_and_cathedrals_tiles["ic_15"].turn(3)

        game_state.board = [[None for column in range(2)] for row in range(1)]

        game_state.board[0][0] = city_with_road
        game_state.board[0][1] = city_one_side_straight_road

        # When
        cities: [City] = CityUtil.find_cities(game_state=game_state,
                                              coordinate=Coordinate(0, 0))

        # Then
        self.assertEqual(1, len(cities))
        self.assertEqual(2, len(cities[0].city_positions))
        self.assertTrue(cities[0].finished)
Exemplo n.º 7
0
 def __init__(self,
              tile_sets: [TileSet] = (TileSet.BASE, TileSet.THE_RIVER,
                                      TileSet.INNS_AND_CATHEDRALS),
              supplementary_rules: [SupplementaryRule
                                    ] = (SupplementaryRule.FARMERS,
                                         SupplementaryRule.ABBOTS),
              players: int = 2,
              board_size: (int, int) = (35, 35),
              starting_position: Coordinate = Coordinate(6, 15)):
     self.deck = self.initialize_deck(tile_sets=tile_sets)
     self.supplementary_rules: [SupplementaryRule] = supplementary_rules
     self.board: [[Tile]] = [[None for column in range(board_size[1])]
                             for row in range(board_size[0])]
     self.starting_position: Coordinate = starting_position
     self.next_tile = self.deck.pop(0)
     self.players = players
     self.meeples = [7 for _ in range(players)]
     self.abbots = [
         1 if SupplementaryRule.ABBOTS in supplementary_rules else 0
         for _ in range(players)
     ]
     self.big_meeples = [
         1 if TileSet.INNS_AND_CATHEDRALS in tile_sets else 0
         for _ in range(players)
     ]
     self.placed_meeples = [[] for _ in range(players)]
     self.scores: [int] = [0 for _ in range(players)]
     self.current_player = 0
     self.phase = GamePhase.TILES
     self.last_tile_action: Optional[TileAction] = None
     self.last_river_rotation: Rotation = Rotation.NONE
Exemplo n.º 8
0
    def test_find_meeples_in_donut_city(self):
        """
        Find meeple positions for a donut shaped city
        """

        # Given
        game_state: CarcassonneGameState = self.create_donut_city_board()
        game_state.placed_meeples = [[], []]

        meeple_0_1 = MeeplePosition(meeple_type=MeepleType.NORMAL,
                                    coordinate_with_side=CoordinateWithSide(
                                        Coordinate(2, 1), Side.RIGHT))
        meeple_0_2 = MeeplePosition(meeple_type=MeepleType.NORMAL,
                                    coordinate_with_side=CoordinateWithSide(
                                        Coordinate(0, 1), Side.LEFT))
        meeple_1_1 = MeeplePosition(meeple_type=MeepleType.BIG,
                                    coordinate_with_side=CoordinateWithSide(
                                        Coordinate(1, 2), Side.TOP))

        game_state.placed_meeples[0].append(meeple_0_1)
        game_state.placed_meeples[0].append(meeple_0_2)
        game_state.placed_meeples[1].append(meeple_1_1)
        game_state.players = 2

        meeples_to_remove = [[], []]
        meeples_to_remove[0].append(copy.deepcopy(meeple_0_1))
        meeples_to_remove[1].append(copy.deepcopy(meeple_1_1))

        # When
        MeepleUtil.remove_meeples(game_state=game_state,
                                  meeples=meeples_to_remove)

        # Then
        self.assertEqual(1, len(game_state.placed_meeples[0]))
        self.assertEqual(0, len(game_state.placed_meeples[1]))
        self.assertIn(copy.deepcopy(meeple_0_2), game_state.placed_meeples[0])
Exemplo n.º 9
0
    def test_find_meeples_in_donut_city(self):
        """
        Find meeple positions for a donut shaped city
        """

        # Given
        game_state: CarcassonneGameState = self.create_donut_city_board()
        game_state.placed_meeples = [[], [], []]
        game_state.placed_meeples[0].append(
            MeeplePosition(meeple_type=MeepleType.NORMAL,
                           coordinate_with_side=CoordinateWithSide(
                               Coordinate(2, 1), Side.RIGHT)))
        game_state.placed_meeples[0].append(
            MeeplePosition(meeple_type=MeepleType.NORMAL,
                           coordinate_with_side=CoordinateWithSide(
                               Coordinate(0, 1), Side.LEFT)))
        game_state.placed_meeples[1].append(
            MeeplePosition(meeple_type=MeepleType.BIG,
                           coordinate_with_side=CoordinateWithSide(
                               Coordinate(1, 2), Side.TOP)))
        game_state.players = 3

        # When
        city: City = CityUtil.find_city(game_state=game_state,
                                        city_position=CoordinateWithSide(
                                            Coordinate(0, 0), Side.BOTTOM))

        meeples: [[MeeplePosition]] = CityUtil.find_meeples(game_state, city)

        # Then
        self.assertEqual(3, len(meeples))
        self.assertEqual(2, len(meeples[0]))
        self.assertEqual(1, len(meeples[1]))
        self.assertEqual(0, len(meeples[2]))
        self.assertIn(
            MeeplePosition(MeepleType.NORMAL,
                           CoordinateWithSide(Coordinate(2, 1), Side.RIGHT)),
            meeples[0])
        self.assertIn(
            MeeplePosition(MeepleType.NORMAL,
                           CoordinateWithSide(Coordinate(0, 1), Side.LEFT)),
            meeples[0])
        self.assertIn(
            MeeplePosition(MeepleType.BIG,
                           CoordinateWithSide(Coordinate(1, 2), Side.TOP)),
            meeples[1])
    def test_collect_points_small_city_2(self):
        """
        Find cities left and right
        """

        # Given
        game_state: CarcassonneGameState = CarcassonneGameState()

        city_one_side_straight_road = base_tiles["city_top_straight_road"].turn(3)
        city_with_road = inns_and_cathedrals_tiles["ic_15"].turn(3)

        game_state.board = [[None for column in range(2)] for row in range(1)]

        game_state.board[0][0] = city_with_road
        game_state.board[0][1] = city_one_side_straight_road

        game_state.players = 2

        game_state.placed_meeples = [[], []]
        game_state.placed_meeples[0].append(MeeplePosition(meeple_type=MeepleType.NORMAL, coordinate_with_side=CoordinateWithSide(Coordinate(0, 0), Side.RIGHT)))
        game_state.placed_meeples[1].append(MeeplePosition(meeple_type=MeepleType.NORMAL, coordinate_with_side=CoordinateWithSide(Coordinate(0, 1), Side.BOTTOM)))

        # When
        PointsCollector.remove_meeples_and_collect_points(game_state=game_state, coordinate=Coordinate(0, 1))

        # Then
        self.assertEqual(0, len(game_state.placed_meeples[0]))
        self.assertEqual(1, len(game_state.placed_meeples[1]))
        self.assertEqual(4, game_state.scores[0])
        self.assertEqual(0, game_state.scores[1])
Exemplo n.º 11
0
    def remove_meeples_and_collect_points(cls,
                                          game_state: CarcassonneGameState,
                                          coordinate: Coordinate):

        # Points for finished cities
        cities: [City] = CityUtil.find_cities(game_state=game_state,
                                              coordinate=coordinate)
        for city in cities:
            if city.finished:
                meeples: [[MeeplePosition]
                          ] = CityUtil.find_meeples(game_state=game_state,
                                                    city=city)
                meeple_counts_per_player = cls.get_meeple_counts_per_player(
                    meeples)
                print("City finished. Meeples:",
                      json.dumps(meeple_counts_per_player))
                if sum(meeple_counts_per_player) == 0:
                    continue
                winning_player = cls.get_winning_player(
                    meeple_counts_per_player)
                if winning_player is not None:
                    points = cls.count_city_points(game_state=game_state,
                                                   city=city)
                    print(points, "points for player", winning_player)
                    game_state.scores[winning_player] += points
                MeepleUtil.remove_meeples(game_state=game_state,
                                          meeples=meeples)

        # Points for finished roads
        roads: [Road] = RoadUtil.find_roads(game_state=game_state,
                                            coordinate=coordinate)
        for road in roads:
            if road.finished:
                meeples: [[MeeplePosition]
                          ] = RoadUtil.find_meeples(game_state=game_state,
                                                    road=road)
                meeple_counts_per_player = cls.get_meeple_counts_per_player(
                    meeples)
                print("Road finished. Meeples:",
                      json.dumps(meeple_counts_per_player))
                if sum(meeple_counts_per_player) == 0:
                    continue
                winning_player = cls.get_winning_player(
                    meeple_counts_per_player)
                if winning_player is not None:
                    points = cls.count_road_points(game_state=game_state,
                                                   road=road)
                    print(points, "points for player", winning_player)
                    game_state.scores[winning_player] += points
                MeepleUtil.remove_meeples(game_state=game_state,
                                          meeples=meeples)

        # Points for finished chapels
        for row in range(coordinate.row - 1, coordinate.row + 2):
            for column in range(coordinate.column - 1, coordinate.column + 2):
                tile: Tile = game_state.get_tile(row, column)

                if tile is None:
                    continue

                coordinate = Coordinate(row=row, column=column)
                coordinate_with_side = CoordinateWithSide(
                    coordinate=coordinate, side=Side.CENTER)
                meeple_of_player = MeepleUtil.position_contains_meeple(
                    game_state=game_state,
                    coordinate_with_side=coordinate_with_side)
                if (tile.chapel
                        or tile.flowers) and meeple_of_player is not None:
                    points = cls.chapel_or_flowers_points(
                        game_state=game_state, coordinate=coordinate)
                    if points == 9:
                        print("Chapel or flowers finished for player",
                              str(meeple_of_player))
                        print(points, "points for player", meeple_of_player)
                        game_state.scores[meeple_of_player] += points

                        meeples_per_player = []
                        for _ in range(game_state.players):
                            meeples_per_player.append([])
                        meeples_per_player[meeple_of_player].append(
                            coordinate_with_side)

                        MeepleUtil.remove_meeples(game_state=game_state,
                                                  meeples=meeples_per_player)
Exemplo n.º 12
0
    def test_find_donut_city(self):
        """
        Find the positions for a donut shaped city
        """

        # Given
        game_state: CarcassonneGameState = self.create_donut_city_board()

        # When
        city: City = CityUtil.find_city(game_state=game_state,
                                        city_position=CoordinateWithSide(
                                            Coordinate(0, 0), Side.BOTTOM))

        # Then
        self.assertTrue(city.finished)
        self.assertEqual(16, len(city.city_positions))
        self.assertIn(CoordinateWithSide(Coordinate(0, 0), Side.BOTTOM),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(0, 0), Side.RIGHT),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(0, 1), Side.LEFT),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(0, 1), Side.RIGHT),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(0, 2), Side.LEFT),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(0, 2), Side.BOTTOM),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(1, 0), Side.TOP),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(1, 0), Side.BOTTOM),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(1, 2), Side.TOP),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(1, 2), Side.BOTTOM),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(2, 0), Side.TOP),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(2, 0), Side.RIGHT),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(2, 1), Side.LEFT),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(2, 1), Side.RIGHT),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(2, 2), Side.LEFT),
                      city.city_positions)
        self.assertIn(CoordinateWithSide(Coordinate(2, 2), Side.TOP),
                      city.city_positions)