예제 #1
0
    def test_board_pieces(self):
        board = Board()
        assert board.get_board_pieces() == []

        board.get_tile(0, 1).place_piece(Piece(PLAYER_1_ID, PieceType.four))
        board.get_tile(2, 2).place_piece(Piece(PLAYER_1_ID, PieceType.two))
        board.get_tile(3, 3).place_piece(Piece(PLAYER_1_ID, PieceType.one))

        assert len(board.get_board_pieces()) == 3
        assert len(board.get_board_pieces(exclude_perimeter=True)) == 2
예제 #2
0
def evaluate_board(board: Board, player_id: int, opponent_id: int) -> int:
    # First check if we have this score in the cache already #
    cache_key = f"{player_id}#{board.to_string_notation()}"
    if BOARD_SCORE_CACHE.get(cache_key):
        return BOARD_SCORE_CACHE[cache_key]

    result = board.get_game_result(player_id, opponent_id)
    score = 0
    if result is not None:
        score = game_result_to_score(result)
    else:
        pieces = board.get_board_pieces(exclude_perimeter=True)
        for piece in pieces:
            tile_multiplier = TILE_SCORE_MULTIPLIER[piece.tile.x][
                piece.tile.y][piece.direction]
            piece_score = PLACED_PIECE_SCORE[piece.type] * tile_multiplier
            if piece.owner_id == player_id:
                score += piece_score
            else:
                score -= piece_score
    BOARD_SCORE_CACHE[cache_key] = score
    return score
예제 #3
0
class Game(object):
    def __init__(self, on_player_moves_executed: Optional[Callable] = None):
        self.on_player_moves_executed = on_player_moves_executed
        self.board = Board()
        self.player_1 = Player(PLAYER_1_ID, self.board, self)
        self.player_2 = Player(PLAYER_2_ID, self.board, self)
        self.starting_player = self.player_1
        self.first_move_executed = False
        self.player_moves = {PLAYER_1_ID: list(), PLAYER_2_ID: list()}
        self.turns = 0
        self.result: GameResult = None

    def play_game(self, player_1_strategy_fn: StrategyFunction,
                  player_2_strategy_fn: StrategyFunction) -> GameResult:
        logger.info(f"Game starting...")
        while self.result is None:
            self.first_move_executed = False
            self.execute_player_moves(player_1_strategy_fn,
                                      player_2_strategy_fn)
            if self.on_player_moves_executed is not None:
                self.on_player_moves_executed()
            self.board.execute_board_movements(self.starting_player.id)
            self.turns += 1
            self.switch_starting_player()
            self.result = self.get_current_result()
        logger.info(
            f"Game finished in {self.turns} turns with result: {self.result}")
        return self.result

    def execute_player_moves(self, player_1_strategy_fn: StrategyFunction,
                             player_2_strategy_fn: StrategyFunction):
        starting_strategy_fn = player_1_strategy_fn if self.starting_player.id == self.player_1.id else player_2_strategy_fn
        starting_move = starting_strategy_fn(self.starting_player,
                                             self.get_secondary_player(), True)
        if starting_move is not None:
            starting_move.execute()
        self.first_move_executed = True
        logger.debug(
            f"{self.starting_player!r} executed move {starting_move!r}")
        second_strategy_fn = player_1_strategy_fn if self.get_secondary_player(
        ).id == self.player_1.id else player_2_strategy_fn
        second_move = second_strategy_fn(self.get_secondary_player(),
                                         self.starting_player, False)
        if second_move is not None:
            second_move.execute()
        logger.debug(
            f"{self.get_secondary_player()!r} executed move {second_move!r}")
        self.player_moves[self.starting_player.id].append(starting_move)
        self.player_moves[self.get_secondary_player().id].append(second_move)

    def get_current_result(self) -> GameResult:
        return self.board.get_game_result(self.player_1.id, self.player_2.id)

    def get_player_by_id(self, player_id) -> Player:
        if player_id == PLAYER_1_ID:
            return self.player_1
        elif player_id == PLAYER_2_ID:
            return self.player_2
        else:
            raise ValueError(f"Unknown player ID specified: {player_id}.")

    # Returns the player that is next to play
    def get_active_player(self):
        return self.get_secondary_player(
        ) if self.first_move_executed else self.starting_player

    def switch_starting_player(self):
        self.starting_player = self.get_secondary_player()

    def get_secondary_player(self) -> Player:
        if self.starting_player is self.player_1:
            return self.player_2
        return self.player_1

    def clone(self) -> Game:
        clone_game = Game()
        clone_game.starting_player = clone_game.get_player_by_id(
            self.starting_player.id)
        clone_game.first_move_executed = self.first_move_executed
        board_pieces = self.board.get_board_pieces()
        for board_piece in board_pieces:
            owner = clone_game.get_player_by_id(board_piece.owner_id)
            target_piece = owner.get_piece_by_type(board_piece.type)
            target_piece.set_movement_direction(board_piece.direction)
            target_tile = clone_game.board.get_tile(board_piece.tile.x,
                                                    board_piece.tile.y)
            target_tile.place_piece(target_piece)
        return clone_game