コード例 #1
0
        private bool ApplyMove(BoardPieceMove move)
        {
            // Check the moving piece belongs to the correct player and is a valid move
            if (BoardPieces[move.From.X, move.From.Y].PieceOwner != PlayerTurn ||
                !ValidMovesCalc.IsMoveValid(move, PlayerTurn, this) ||
                (GameState != GameState.Playing))
            {
                // Move is invalid
                return(false);
            }

            List <BoardChange> boardChanges = ApplyMoveToBoard(move);

            CheckPawnPromotion(move, boardChanges);

            // Store changes
            for (int i = 0; i < boardChanges.Count; i++)
            {
                GameChanges.Push(boardChanges[i]);
            }

            OnBoardChanged?.Invoke(boardChanges);

            if (ValidMovesCalc.IsPlayerInCheck(BoardPieces, BoardHelpers.GetOpponentPlayer(PlayerTurn)))
            {
                if (ValidMovesCalc.PlayerCanMove(this, BoardHelpers.GetOpponentPlayer(PlayerTurn)))
                {
                    // CHECKMATE
                    ChangeGameState(GameState.WonByCheckmate);
                    return(true);
                }

                // IN CHECK
                OnPlayerInCheck?.Invoke(BoardHelpers.GetOpponentPlayer(PlayerTurn));
            }
            else
            {
                if (ValidMovesCalc.PlayerCanMove(this, BoardHelpers.GetOpponentPlayer(PlayerTurn)))
                {
                    // STALEMATE
                    ChangeGameState(GameState.WonByStaleMate);
                    return(true);
                }
            }

            ClearEnPassant();
            SwapPlayerTurns();

            return(true);
        }
コード例 #2
0
        private float Maximise(Board board, int depth, ref BoardPieceMoveScore maxBestMove, float beta, Player currentPlayer)
        {
            // If the depth limit is reached, don't go any deeper and return the score of the board
            if (depth >= _searchDepth)
            {
                return(ScoreTheBoard(board, currentPlayer));
            }

            HashSet <BoardPieceMove> validMoves = new HashSet <BoardPieceMove>();

            ValidMovesCalc.GetValidMovesForPlayer(board, board.PlayerTurn, validMoves);

            float alpha = -10000000; // Set alpha to low num
            BoardPieceMoveScore bestChildMove = null;

            // Iterate through every available move
            foreach (var move in validMoves)
            {
                // Create a copy of the board and then perform the current move
                Board newBoard = BoardHelpers.DuplicateBoard(board);
                newBoard.BoardPieces[move.From.X, move.From.Y].HasMoved = true;
                newBoard.BoardPieces[move.To.X, move.To.Y]     = newBoard.BoardPieces[move.From.X, move.From.Y];
                newBoard.BoardPieces[move.From.X, move.From.Y] = new BoardPiece();
                newBoard.PlayerTurn = BoardHelpers.GetOpponentPlayer(newBoard.PlayerTurn);

                // Go down a layer and find the minimum score available for the enemy (PLAYER). Set it to alpha if it is greater than a previous alpha.
                alpha = Math.Max(alpha, Minimise(newBoard, depth + 1, alpha, currentPlayer));

                // If the new alpha is greater than the previous best score (or hasn't been set yet)
                if (bestChildMove == null || alpha > bestChildMove.Score)
                {
                    bestChildMove = new BoardPieceMoveScore(move, alpha);
                }

                // If a move is found to be worse than the best score currently stored, return out of the tree early.
                if (alpha > beta)
                {
                    return(alpha);
                }
            }

            // If we're on the top layer, return the best move available
            if (depth == 0)
            {
                maxBestMove = bestChildMove;
            }

            return(alpha);
        }
コード例 #3
0
        private float Minimise(Board board, int depth, float alpha, Player currentPlayer)
        {
            if (depth >= _searchDepth)
            {
                return(ScoreTheBoard(board, currentPlayer));
            }

            HashSet <BoardPieceMove> validMoves = new HashSet <BoardPieceMove>();

            ValidMovesCalc.GetValidMovesForPlayer(board, board.PlayerTurn, validMoves);

            float beta = 10000000;
            BoardPieceMoveScore bestChildMove = null;

            // Iterate through every available move
            foreach (var move in validMoves)
            {
                // Create a copy of the board and then perform the current move
                Board newBoard = BoardHelpers.DuplicateBoard(board);
                newBoard.BoardPieces[move.From.X, move.From.Y].HasMoved = true;
                newBoard.BoardPieces[move.To.X, move.To.Y]     = newBoard.BoardPieces[move.From.X, move.From.Y];
                newBoard.BoardPieces[move.From.X, move.From.Y] = new BoardPiece();
                newBoard.PlayerTurn = BoardHelpers.GetOpponentPlayer(newBoard.PlayerTurn);
                var newMove = new BoardPieceMoveScore(move, beta);

                beta = Math.Min(beta, Maximise(newBoard, depth + 1, ref newMove, beta, currentPlayer));

                if (bestChildMove == null || beta < bestChildMove.Score)
                {
                    bestChildMove = new BoardPieceMoveScore(move, beta);
                }

                if (beta < alpha)
                {
                    return(beta);
                }
            }

            return(beta);
        }