Пример #1
0
        /// <summary>
        /// Sets up the board using the given FEN string.  It's possible not all
        /// pieces are present.
        /// </summary>
        /// <param name="fen">FEN string that describes the position
        /// (https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation)</param>
        private void CreateAndPlacePieces(string fen)
        {
            Reset();

            // String starts on the back rank on the A file then moves Left->Right
            // Top->Bottom
            string fenString = fen.Trim();

            activePlayer = FenParser.ExtractActivePlayer(fenString);
            FenParser.ExtractCastlingRights(fenString, ref whiteCastlingRights, ref blackCastlingRights);
            enPassantValid = FenParser.ExtractEnPassantTarget(fenString, out enPassantTarget);
            FenParser.ExtractMoveCounts(fenString, ref halfMoveCount, ref fullMoveCount);

            List <ChessPiece> pieces = FenParser.ExtractPieces(fenString);

            foreach (ChessPiece fenPiece in pieces)
            {
                // For pawns and rooks and kings, deployment matters, check if they're on their home
                // rank/square and if not, set it to true
                if (fenPiece.Job == PieceClass.Pawn)
                {
                    if (PawnHomeRank(fenPiece.Color) != fenPiece.Rank)
                    {
                        fenPiece.Deployed = true;
                    }
                }
                else if (fenPiece.Job == PieceClass.Rook)
                {
                    if (((fenPiece.File.ToInt() != 1) && (fenPiece.File.ToInt() != 8)) ||
                        (fenPiece.Rank != RookHomeRank(fenPiece.Color)))
                    {
                        fenPiece.Deployed = true;
                    }
                }
                else if (fenPiece.Job == PieceClass.King)
                {
                    // Both colors should be on the E file and their home rank
                    int homeRank = (fenPiece.Color == PieceColor.White) ? 1 : 8;
                    if ((fenPiece.Rank != homeRank) || (fenPiece.File != new PieceFile('e')))
                    {
                        fenPiece.Deployed = true;
                    }
                }

                if (fenPiece.Color == PieceColor.White)
                {
                    whitePieces.Add(fenPiece);
                }
                else
                {
                    blackPieces.Add(fenPiece);
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Move a piece from startFile:startRank -> targetFile:targetRank.  Because
        /// self-play is the only mode enabled right now, these moves are always
        /// going to be considered valid, since they came from the chess engine
        /// (and we will assume it is correct).  In the future, this will likely
        /// remain, and validation of the legallity for the player can be handled
        /// above this call
        /// </summary>
        /// <param name="moveInfo">detailed move information struct</param>
        public void MovePiece(ref MoveInformation moveInfo)
        {
            // Get the player piece at the starting location
            // Piece should never be null if chess logic is sound
            PieceFile startFile  = moveInfo.Start.File;
            int       startRank  = moveInfo.Start.Rank;
            PieceFile targetFile = moveInfo.End.File;
            int       targetRank = moveInfo.End.Rank;

            ChessPiece playerPiece = FindPieceAt(startFile, startRank);

            if (playerPiece.Color != activePlayer)
            {
                // This also should not be able to happen with correct game logic
                throw new InvalidOperationException();
            }

            // Get each side's pieces
            List <ChessPiece> playerPieces   = ActivePlayerPieces;
            List <ChessPiece> opponentPieces = OpponentPlayerPieces;

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // PRE-MOVE CHECKS

            // We have to detect castling.  It does not come across the wire as O-O or O-O-O
            // but rather as a regular move like e1g1.  Separate the detection from the move
            // of the rook
            bool isCastling = IsCastling(playerPiece, targetFile);

            // We also need to check for an en-passant capture if the pieces is a pawn
            if (playerPiece.Job == PieceClass.Pawn)
            {
                moveInfo.CapturedPiece = HandleEnPassant(startFile, startRank, targetFile, targetRank);
            }

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // RAW MOVE(S)
            playerPiece.Move(targetFile, targetRank);
            if (isCastling)
            {
                PerformCastle(targetFile, ref moveInfo); // Also move the rook if needed
            }

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // POST-MOVE CHECKS/UPDATES

            // For normal captures, just do a quick iteration of the opponent pieces
            // there are only 16 of these total in normal chess
            foreach (ChessPiece enemyPiece in opponentPieces)
            {
                if ((enemyPiece.Rank == targetRank) &&   // Enemy piece is located in
                    (enemyPiece.File == targetFile) &&   // the square we just moved to
                    !enemyPiece.Captured)                // and it's not already captured
                {
                    enemyPiece.Captured    = true;       // Stop drawing it (capture)
                    moveInfo.CapturedPiece = enemyPiece; // Record the capture
                    break;                               // exit the search loop
                }
            }

            // save the last capture state for external callers
            lastMoveWasCapture = moveInfo.IsCapture;

            Moves.Add(moveInfo);

            // Update our FEN
            currentFEN     = FenParser.ApplyMoveToFEN(currentFEN, moveInfo.ToString());
            enPassantValid = FenParser.ExtractEnPassantTarget(currentFEN, out enPassantTarget);

            FenParser.ExtractCastlingRights(CurrentFEN, ref whiteCastlingRights, ref blackCastlingRights);
            FenParser.ExtractMoveCounts(CurrentFEN, ref halfMoveCount, ref fullMoveCount);

            // Flip players - easy to just do here rather than parse the FEN again
            activePlayer = OppositeColor(activePlayer);
        }