Ejemplo n.º 1
0
    def __possible_meeple_positions(game_state: CarcassonneGameState) -> [CoordinateWithSide]:
        playing_positions: [CoordinateWithSide] = []
        last_tile_action: TileAction = game_state.last_tile_action
        last_played_tile: Tile = last_tile_action.tile
        last_played_position: Coordinate = last_tile_action.coordinate

        if last_played_tile.chapel:
            playing_positions.append(CoordinateWithSide(coordinate=last_played_position, side=Side.CENTER))

        for side in [Side.TOP, Side.RIGHT, Side.BOTTOM, Side.LEFT]:
            if last_played_tile.get_type(side) == TerrainType.CITY:
                connected_cities = CityUtil.find_city(
                    game_state,
                    CoordinateWithSide(coordinate=last_played_position, side=side)
                )
                if CityUtil.city_contains_meeples(game_state, connected_cities):
                    continue
                else:
                    playing_positions.append(CoordinateWithSide(coordinate=last_played_position, side=side))

            if last_played_tile.get_type(side) == TerrainType.ROAD:
                connected_roads = RoadUtil.find_road(
                    game_state,
                    CoordinateWithSide(coordinate=last_played_position, side=side)
                )
                if RoadUtil.road_contains_meeples(game_state, connected_roads):
                    continue
                else:
                    playing_positions.append(CoordinateWithSide(coordinate=last_played_position, side=side))

        return playing_positions
Ejemplo n.º 2
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)
Ejemplo 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)
Ejemplo n.º 4
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])
Ejemplo n.º 5
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)
Ejemplo n.º 6
0
    def count_farm_points(cls, game_state: CarcassonneGameState, farm: Farm):
        cities: Set[City] = set()

        points = 0

        farmer_connection_with_coordinate: FarmerConnectionWithCoordinate
        for farmer_connection_with_coordinate in farm.farmer_connections_with_coordinate:
            cities = cities.union(
                CityUtil.find_cities(
                    game_state=game_state,
                    coordinate=farmer_connection_with_coordinate.coordinate,
                    sides=farmer_connection_with_coordinate.farmer_connection.
                    city_sides))

        city: City
        for city in cities:
            if city.finished:
                points += 3

        return points
Ejemplo n.º 7
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)
Ejemplo n.º 8
0
    def count_final_scores(cls, game_state: CarcassonneGameState):
        for player, placed_meeples in enumerate(game_state.placed_meeples):

            # TODO also remove meeples from meeples_to_remove, when there are multiple

            meeples_to_remove: Set[MeeplePosition] = set(placed_meeples)
            while len(meeples_to_remove) > 0:
                meeple_position: MeeplePosition = meeples_to_remove.pop()

                tile: Tile = game_state.board[
                    meeple_position.coordinate_with_side.coordinate.row][
                        meeple_position.coordinate_with_side.coordinate.column]

                terrrain_type: TerrainType = tile.get_type(
                    meeple_position.coordinate_with_side.side)

                if terrrain_type == TerrainType.CITY:
                    city: City = CityUtil.find_city(
                        game_state=game_state,
                        city_position=meeple_position.coordinate_with_side)
                    meeples: [CoordinateWithSide
                              ] = CityUtil.find_meeples(game_state=game_state,
                                                        city=city)
                    meeple_counts_per_player = cls.get_meeple_counts_per_player(
                        meeples)
                    print("Collecting points for unfinished city. Meeples:",
                          json.dumps(meeple_counts_per_player))
                    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", player)
                        game_state.scores[winning_player] += points

                    MeepleUtil.remove_meeples(game_state=game_state,
                                              meeples=meeples)
                    continue

                if terrrain_type == TerrainType.ROAD:
                    road: [Road] = RoadUtil.find_road(
                        game_state=game_state,
                        road_position=meeple_position.coordinate_with_side)
                    meeples: [CoordinateWithSide
                              ] = RoadUtil.find_meeples(game_state=game_state,
                                                        road=road)
                    meeple_counts_per_player = cls.get_meeple_counts_per_player(
                        meeples)
                    print("Collecting points for unfinished road. Meeples:",
                          json.dumps(meeple_counts_per_player))
                    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", player)
                        game_state.scores[winning_player] += points
                    MeepleUtil.remove_meeples(game_state=game_state,
                                              meeples=meeples)
                    continue

                if terrrain_type == TerrainType.CHAPEL or terrrain_type == TerrainType.FLOWERS:
                    points = cls.chapel_or_flowers_points(
                        game_state=game_state,
                        coordinate=meeple_position.coordinate_with_side.
                        coordinate)
                    print(
                        "Collecting points for unfinished chapel or flowers for player",
                        str(player))
                    print(points, "points for player", player)
                    game_state.scores[player] += points

                    meeples_per_player = []
                    for _ in range(game_state.players):
                        meeples_per_player.append([])
                    meeples_per_player[player].append(meeple_position)

                    MeepleUtil.remove_meeples(game_state=game_state,
                                              meeples=meeples_per_player)
                    continue

                if meeple_position.meeple_type == MeepleType.FARMER or meeple_position.meeple_type == MeepleType.BIG_FARMER:
                    farm: Farm = FarmUtil.find_farm_by_coordinate(
                        game_state=game_state,
                        position=meeple_position.coordinate_with_side)
                    meeples: [[MeeplePosition]
                              ] = FarmUtil.find_meeples(game_state=game_state,
                                                        farm=farm)
                    meeple_counts_per_player = cls.get_meeple_counts_per_player(
                        meeples)
                    print("Collecting points for farm. Meeples:",
                          json.dumps(meeple_counts_per_player))
                    winning_player = cls.get_winning_player(
                        meeple_counts_per_player)
                    if winning_player is not None:
                        points = cls.count_farm_points(game_state=game_state,
                                                       farm=farm)
                        print(points, "points for player", winning_player)
                        game_state.scores[winning_player] += points
                    MeepleUtil.remove_meeples(game_state=game_state,
                                              meeples=meeples)
                    continue

                print("Collecting points for unknown type", terrrain_type)