示例#1
0
        /// <summary>
        /// Reverts last move applied to the board
        /// </summary>
        public void RevertLastMove()
        {
            MoveInformation lastMove = Moves.Last();

            Moves.RemoveAt(Moves.Count() - 1);

            ChessPiece lastPieceMoved = FindPieceAt(lastMove.End.File, lastMove.End.Rank);

            lastPieceMoved.Move(lastMove.Start.File, lastMove.Start.Rank);
            if (lastMove.FirstMove)
            {
                lastPieceMoved.Deployed = false; // Reset first move
            }

            // Undo captures
            lastMoveWasCapture = false;
            if (lastMove.IsCapture)
            {
                lastMove.CapturedPiece.Captured = false;
                lastMoveWasCapture = true;
            }

            if (lastMove.IsPromotion)
            {
                lastPieceMoved.Demote();
            }

            // Undo a castling move
            if (lastMove.IsCastle)
            {
                // Move the rook back as well
                ChessPiece rook             = lastMove.CastlingRook;
                PieceFile  castleTargetFile = lastMove.End.File;
                int        rookRank         = (rook.Color == PieceColor.White) ? 1 : 8;
                if (castleTargetFile.ToInt() == 7) // g->h
                {
                    rook.Move(new PieceFile('h'), rookRank);
                }
                else if (castleTargetFile.ToInt() == 3) // c->a
                {
                    rook.Move(new PieceFile('a'), rookRank);
                }
                else
                {
                    // It has to be one of the above if logic is correct
                    throw new IndexOutOfRangeException();
                }
                rook.Deployed = false;
            }

            // Reset castling rights
            ActivePlayerCastlingRights = lastMove.CastlingRights;

            // Flip players
            activePlayer = OppositeColor(activePlayer);

            // Set last FEN
            currentFEN = lastMove.PreviousFEN;
        }
示例#2
0
        /// <summary>
        /// Moves the rook for a castle move of a King.  At this point the castling
        /// has (or should have) been detected.  This is called to bring the rook
        /// along for the ride when the king is moved. See IsCastling for detection
        /// </summary>
        /// <param name="targetFile">ChessFile the King is moving to</param>
        /// <param name="moveInfo">Extended move information</param>
        private void PerformCastle(PieceFile targetFile, ref MoveInformation moveInfo)
        {
            // Find the corresponding Rook and move it too
            int       rookRank    = (activePlayer == PieceColor.White) ? 1 : 8;
            PieceFile gTargetFile = new PieceFile('g');
            PieceFile cTargetFile = new PieceFile('c');
            PieceFile rookStartFile;
            PieceFile rookTargetFile;

            // These are the only 2 legal files to move a king when castling
            // and they are the same for both players (only the rank differs above)
            if (targetFile == gTargetFile)
            {
                rookStartFile  = new PieceFile('h');
                rookTargetFile = new PieceFile('f');
            }
            else if (targetFile == cTargetFile)
            {
                rookStartFile  = new PieceFile('a');
                rookTargetFile = new PieceFile('d');
            }
            else
            {
                // If the above chess logic was sound, this should not happen.
                throw new ArgumentOutOfRangeException();
            }

            // Get the rook (which should exist if logic is sound)
            ChessPiece castleRook = FindPieceAt(rookStartFile, rookRank);

            // Move it
            castleRook.Move(rookTargetFile, rookRank);

            // Save the castling info
            moveInfo.CastlingRook = castleRook;

            // Remove all castling rights for the active player
            if (activePlayer == PieceColor.White)
            {
                whiteCastlingRights = BoardSide.None;
            }
            else
            {
                blackCastlingRights = BoardSide.None;
            }
        }
示例#3
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);
        }