Пример #1
0
        private void GenerateQueenMoves(MoveGeneration MoveGeneration, ulong FromSquareMask, ulong ToSquareMask)
        {
            ulong queens;
            ulong unOrEnemyOccupiedSquares;
            ulong enemyOccupiedSquares;
            int   attacker;

            if (WhiteMove)
            {
                // White Move
                queens = WhiteQueens & FromSquareMask;
                unOrEnemyOccupiedSquares = ~OccupancyWhite;
                enemyOccupiedSquares     = OccupancyBlack;
                attacker = Piece.WhiteQueen;
            }
            else
            {
                // Black Move
                queens = BlackQueens & FromSquareMask;
                unOrEnemyOccupiedSquares = ~OccupancyBlack;
                enemyOccupiedSquares     = OccupancyWhite;
                attacker = Piece.BlackQueen;
            }
            int fromSquare;

            while ((fromSquare = Bitwise.FindFirstSetBit(queens)) != Square.Illegal)
            {
                var bishopOccupancy   = Board.BishopMoveMasks[fromSquare] & Occupancy;
                var rookOccupancy     = Board.RookMoveMasks[fromSquare] & Occupancy;
                var queenDestinations = MoveGeneration switch
                {
                    MoveGeneration.AllMoves => (Board.PrecalculatedMoves.GetBishopMovesMask(fromSquare, bishopOccupancy) | Board.PrecalculatedMoves.GetRookMovesMask(fromSquare, rookOccupancy)) & unOrEnemyOccupiedSquares & ToSquareMask,
                    MoveGeneration.OnlyCaptures => (Board.PrecalculatedMoves.GetBishopMovesMask(fromSquare, bishopOccupancy) | Board.PrecalculatedMoves.GetRookMovesMask(fromSquare, rookOccupancy)) & enemyOccupiedSquares & ToSquareMask,
                    MoveGeneration.OnlyNonCaptures => (Board.PrecalculatedMoves.GetBishopMovesMask(fromSquare, bishopOccupancy) | Board.PrecalculatedMoves.GetRookMovesMask(fromSquare, rookOccupancy)) & ~Occupancy & ToSquareMask,
                    _ => throw new Exception($"{MoveGeneration} move generation not supported.")
                };
                int toSquare;
                while ((toSquare = Bitwise.FindFirstSetBit(queenDestinations)) != Square.Illegal)
                {
                    var victim = GetPiece(toSquare);
                    var move   = Move.Null;
                    Move.SetFrom(ref move, fromSquare);
                    Move.SetTo(ref move, toSquare);
                    if (victim != Piece.None)
                    {
                        Move.SetCaptureAttacker(ref move, attacker);
                    }
                    Move.SetCaptureVictim(ref move, victim);
                    Move.SetIsQuiet(ref move, victim == Piece.None);
                    Moves[MoveIndex] = move;
                    MoveIndex++;
                    Bitwise.ClearBit(ref queenDestinations, toSquare);
                }
                Bitwise.ClearBit(ref queens, fromSquare);
            }
        }
Пример #2
0
        private void GenerateKnightMoves(MoveGeneration MoveGeneration, ulong FromSquareMask, ulong ToSquareMask)
        {
            ulong knights;
            ulong unOrEnemyOccupiedSquares;
            ulong enemyOccupiedSquares;
            int   attacker;

            if (WhiteMove)
            {
                // White Move
                knights = WhiteKnights & FromSquareMask;
                unOrEnemyOccupiedSquares = ~OccupancyWhite;
                enemyOccupiedSquares     = OccupancyBlack;
                attacker = Piece.WhiteKnight;
            }
            else
            {
                // Black Move
                knights = BlackKnights & FromSquareMask;
                unOrEnemyOccupiedSquares = ~OccupancyBlack;
                enemyOccupiedSquares     = OccupancyWhite;
                attacker = Piece.BlackKnight;
            }
            int fromSquare;

            while ((fromSquare = Bitwise.FindFirstSetBit(knights)) != Square.Illegal)
            {
                var knightDestinations = MoveGeneration switch
                {
                    MoveGeneration.AllMoves => Board.KnightMoveMasks[fromSquare] & unOrEnemyOccupiedSquares & ToSquareMask,
                    MoveGeneration.OnlyCaptures => Board.KnightMoveMasks[fromSquare] & enemyOccupiedSquares & ToSquareMask,
                    MoveGeneration.OnlyNonCaptures => Board.KnightMoveMasks[fromSquare] & ~Occupancy & ToSquareMask,
                    _ => throw new Exception($"{MoveGeneration} move generation not supported.")
                };
                int toSquare;
                while ((toSquare = Bitwise.FindFirstSetBit(knightDestinations)) != Square.Illegal)
                {
                    var victim = GetPiece(toSquare);
                    var move   = Move.Null;
                    Move.SetFrom(ref move, fromSquare);
                    Move.SetTo(ref move, toSquare);
                    if (victim != Piece.None)
                    {
                        Move.SetCaptureAttacker(ref move, attacker);
                    }
                    Move.SetCaptureVictim(ref move, victim);
                    Move.SetIsQuiet(ref move, victim == Piece.None);
                    Moves[MoveIndex] = move;
                    MoveIndex++;
                    Bitwise.ClearBit(ref knightDestinations, toSquare);
                }
                Bitwise.ClearBit(ref knights, fromSquare);
            }
        }
Пример #3
0
        public void FindPinnedPieces()
        {
            int   ownKingSquare;
            ulong ownPieces;
            ulong enemyRankFileAttackers;
            ulong enemyDiagonalAttackers;
            ulong enemyPieces;

            if (WhiteMove)
            {
                // White Move
                ownKingSquare          = Bitwise.FindFirstSetBit(WhiteKing);
                ownPieces              = OccupancyWhite;
                enemyRankFileAttackers = BlackRooks | BlackQueens;
                enemyDiagonalAttackers = BlackBishops | BlackQueens;
                enemyPieces            = OccupancyBlack;
            }
            else
            {
                // Black Move
                ownKingSquare          = Bitwise.FindFirstSetBit(BlackKing);
                ownPieces              = OccupancyBlack;
                enemyRankFileAttackers = WhiteRooks | WhiteQueens;
                enemyDiagonalAttackers = WhiteBishops | WhiteQueens;
                enemyPieces            = OccupancyWhite;
            }
            // Find pieces pinned to own king by enemy rank / file attackers.
            PinnedPieces = 0;
            int attackerSquare;

            while ((attackerSquare = Bitwise.FindFirstSetBit(enemyRankFileAttackers)) != Square.Illegal)
            {
                var betweenSquares = Board.RankFileBetweenSquares[attackerSquare][ownKingSquare];
                if (betweenSquares == 0)
                {
                    Bitwise.ClearBit(ref enemyRankFileAttackers, attackerSquare);
                    continue;
                }
                if ((betweenSquares & enemyPieces) == 0)
                {
                    // No enemy pieces between enemy attacker and own king.
                    var potentiallyPinnedPieces = betweenSquares & ownPieces;
                    if (Bitwise.CountSetBits(potentiallyPinnedPieces) == 1)
                    {
                        // Exactly one own piece between enemy attacker and own king.
                        // Piece is pinned to own king.
                        PinnedPieces |= potentiallyPinnedPieces;
                    }
                }
                Bitwise.ClearBit(ref enemyRankFileAttackers, attackerSquare);
            }
            // Find pieces pinned to own king by enemy diagonal attackers.
            while ((attackerSquare = Bitwise.FindFirstSetBit(enemyDiagonalAttackers)) != Square.Illegal)
            {
                var betweenSquares = Board.DiagonalBetweenSquares[attackerSquare][ownKingSquare];
                if (betweenSquares == 0)
                {
                    Bitwise.ClearBit(ref enemyDiagonalAttackers, attackerSquare);
                    continue;
                }
                if ((betweenSquares & enemyPieces) == 0)
                {
                    // No enemy pieces between enemy attacker and own king.
                    var potentiallyPinnedPieces = betweenSquares & ownPieces;
                    if (Bitwise.CountSetBits(potentiallyPinnedPieces) == 1)
                    {
                        // Exactly one own piece between enemy attacker and own king.
                        // Piece is pinned to own king.
                        PinnedPieces |= potentiallyPinnedPieces;
                    }
                }
                Bitwise.ClearBit(ref enemyDiagonalAttackers, attackerSquare);
            }
        }
Пример #4
0
        private void GenerateKingMoves(MoveGeneration MoveGeneration, ulong FromSquareMask, ulong ToSquareMask)
        {
            ulong king;
            ulong unOrEnemyOccupiedSquares;
            ulong enemyOccupiedSquares;
            int   attacker;
            bool  castleQueenside;
            ulong castleQueensideMask;
            bool  castleKingside;
            ulong castleKingsideMask;

            if (WhiteMove)
            {
                // White Move
                king = WhiteKing & FromSquareMask;
                unOrEnemyOccupiedSquares = ~OccupancyWhite;
                enemyOccupiedSquares     = OccupancyBlack;
                attacker            = Piece.WhiteKing;
                castleQueenside     = Engine.Castling.WhiteQueenside(Castling);
                castleQueensideMask = Board.WhiteCastleQEmptySquaresMask;
                castleKingside      = Engine.Castling.WhiteKingside(Castling);
                castleKingsideMask  = Board.WhiteCastleKEmptySquaresMask;
            }
            else
            {
                // Black Move
                king = BlackKing & FromSquareMask;
                unOrEnemyOccupiedSquares = ~OccupancyBlack;
                enemyOccupiedSquares     = OccupancyWhite;
                attacker            = Piece.BlackKing;
                castleQueenside     = Engine.Castling.BlackQueenside(Castling);
                castleQueensideMask = Board.BlackCastleQEmptySquaresMask;
                castleKingside      = Engine.Castling.BlackKingside(Castling);
                castleKingsideMask  = Board.BlackCastleKEmptySquaresMask;
            }
            ulong move;
            var   fromSquare = Bitwise.FindFirstSetBit(king);

            if (fromSquare == Square.Illegal)
            {
                return;
            }
            var kingDestinations = MoveGeneration switch
            {
                MoveGeneration.AllMoves => Board.KingMoveMasks[fromSquare] & unOrEnemyOccupiedSquares & ToSquareMask,
                MoveGeneration.OnlyCaptures => Board.KingMoveMasks[fromSquare] & enemyOccupiedSquares & ToSquareMask,
                MoveGeneration.OnlyNonCaptures => Board.KingMoveMasks[fromSquare] & ~Occupancy & ToSquareMask,
                _ => throw new Exception($"{MoveGeneration} move generation not supported.")
            };
            int toSquare;

            while ((toSquare = Bitwise.FindFirstSetBit(kingDestinations)) != Square.Illegal)
            {
                var victim = GetPiece(toSquare);
                move = Move.Null;
                Move.SetFrom(ref move, fromSquare);
                Move.SetTo(ref move, toSquare);
                if (victim != Piece.None)
                {
                    Move.SetCaptureAttacker(ref move, attacker);
                }
                Move.SetCaptureVictim(ref move, victim);
                Move.SetIsKingMove(ref move, true);
                Move.SetIsQuiet(ref move, victim == Piece.None);
                Moves[MoveIndex] = move;
                MoveIndex++;
                Bitwise.ClearBit(ref kingDestinations, toSquare);
            }
            if (MoveGeneration != MoveGeneration.OnlyCaptures)
            {
                if (castleQueenside && ((Occupancy & castleQueensideMask) == 0))
                {
                    // Castle Queenside
                    if (WhiteMove)
                    {
                        // White Move
                        fromSquare = Square.e1;
                        toSquare   = Square.c1;
                    }
                    else
                    {
                        // Black Move
                        fromSquare = Square.e8;
                        toSquare   = Square.c8;
                    }
                    if ((Board.SquareMasks[toSquare] & ToSquareMask) > 0)
                    {
                        move = Move.Null;
                        Move.SetFrom(ref move, fromSquare);
                        Move.SetTo(ref move, toSquare);
                        Move.SetIsCastling(ref move, true);
                        Move.SetIsKingMove(ref move, true);
                        Move.SetIsQuiet(ref move, false);
                        Moves[MoveIndex] = move;
                        MoveIndex++;
                    }
                }
                if (castleKingside && ((Occupancy & castleKingsideMask) == 0))
                {
                    // Castle Kingside
                    if (WhiteMove)
                    {
                        // White Move
                        fromSquare = Square.e1;
                        toSquare   = Square.g1;
                    }
                    else
                    {
                        // Black Move
                        fromSquare = Square.e8;
                        toSquare   = Square.g8;
                    }
                    if ((Board.SquareMasks[toSquare] & ToSquareMask) > 0)
                    {
                        move = Move.Null;
                        Move.SetFrom(ref move, fromSquare);
                        Move.SetTo(ref move, toSquare);
                        Move.SetIsCastling(ref move, true);
                        Move.SetIsKingMove(ref move, true);
                        Move.SetIsQuiet(ref move, false);
                        Moves[MoveIndex] = move;
                        MoveIndex++;
                    }
                }
            }
        }
Пример #5
0
        private void GeneratePawnMoves(MoveGeneration MoveGeneration, ulong FromSquareMask, ulong ToSquareMask)
        {
            ulong pawns;

            ulong[] pawnMoveMasks;
            ulong[] pawnDoubleMoveMasks;
            ulong[] pawnAttackMasks;
            ulong   enemyOccupiedSquares;
            var     unoccupiedSquares = ~Occupancy;

            int[] ranks;
            int   attacker;
            int   queen;
            int   rook;
            int   bishop;
            int   knight;
            int   enPassantVictim;

            if (WhiteMove)
            {
                // White Move
                pawns                = WhitePawns & FromSquareMask;
                pawnMoveMasks        = Board.WhitePawnMoveMasks;
                pawnDoubleMoveMasks  = Board.WhitePawnDoubleMoveMasks;
                pawnAttackMasks      = Board.WhitePawnAttackMasks;
                enemyOccupiedSquares = OccupancyBlack;
                ranks                = Board.WhiteRanks;
                attacker             = Piece.WhitePawn;
                queen                = Piece.WhiteQueen;
                rook            = Piece.WhiteRook;
                bishop          = Piece.WhiteBishop;
                knight          = Piece.WhiteKnight;
                enPassantVictim = Piece.BlackPawn;
            }
            else
            {
                // Black Move
                pawns                = BlackPawns & FromSquareMask;
                pawnMoveMasks        = Board.BlackPawnMoveMasks;
                pawnDoubleMoveMasks  = Board.BlackPawnDoubleMoveMasks;
                pawnAttackMasks      = Board.BlackPawnAttackMasks;
                enemyOccupiedSquares = OccupancyWhite;
                ranks                = Board.BlackRanks;
                attacker             = Piece.BlackPawn;
                queen                = Piece.BlackQueen;
                rook            = Piece.BlackRook;
                bishop          = Piece.BlackBishop;
                knight          = Piece.BlackKnight;
                enPassantVictim = Piece.WhitePawn;
            }
            int   fromSquare;
            ulong move;

            if ((EnPassantSquare != Square.Illegal) && ((Board.SquareMasks[EnPassantSquare] & ToSquareMask) > 0) && (MoveGeneration != MoveGeneration.OnlyNonCaptures))
            {
                var enPassantAttackers = Board.EnPassantAttackerMasks[EnPassantSquare] & pawns;
                while ((fromSquare = Bitwise.FindFirstSetBit(enPassantAttackers)) != Square.Illegal)
                {
                    // Capture pawn en passant.
                    move = Move.Null;
                    Move.SetFrom(ref move, fromSquare);
                    Move.SetTo(ref move, EnPassantSquare);
                    Move.SetCaptureAttacker(ref move, attacker);
                    Move.SetCaptureVictim(ref move, enPassantVictim);
                    Move.SetIsEnPassantCapture(ref move, true);
                    Move.SetIsPawnMove(ref move, true);
                    Move.SetIsQuiet(ref move, false);
                    Moves[MoveIndex] = move;
                    MoveIndex++;
                    Bitwise.ClearBit(ref enPassantAttackers, fromSquare);
                }
            }
            while ((fromSquare = Bitwise.FindFirstSetBit(pawns)) != Square.Illegal)
            {
                ulong pawnDestinations;
                int   toSquare;
                int   toSquareRank;
                if (MoveGeneration != MoveGeneration.OnlyCaptures)
                {
                    // Pawns may move forward one square (or two if on initial square) if forward squares are unoccupied.
                    pawnDestinations = pawnMoveMasks[fromSquare] & unoccupiedSquares & ToSquareMask;
                    while ((toSquare = Bitwise.FindFirstSetBit(pawnDestinations)) != Square.Illegal)
                    {
                        var doubleMove = Board.SquareDistances[fromSquare][toSquare] == 2;
                        if (doubleMove && ((Occupancy & pawnDoubleMoveMasks[fromSquare]) > 0))
                        {
                            // Double move is blocked.
                            Bitwise.ClearBit(ref pawnDestinations, toSquare);
                            continue;
                        }
                        toSquareRank = ranks[toSquare];
                        if (toSquareRank < 7)
                        {
                            move = Move.Null;
                            Move.SetFrom(ref move, fromSquare);
                            Move.SetTo(ref move, toSquare);
                            Move.SetIsDoublePawnMove(ref move, doubleMove);
                            Move.SetIsPawnMove(ref move, true);
                            Move.SetIsQuiet(ref move, true);
                            Moves[MoveIndex] = move;
                            MoveIndex++;
                        }
                        else
                        {
                            // Promote pawn to queen.
                            move = Move.Null;
                            Move.SetFrom(ref move, fromSquare);
                            Move.SetTo(ref move, toSquare);
                            Move.SetPromotedPiece(ref move, queen);
                            Move.SetIsPawnMove(ref move, true);
                            Move.SetIsQuiet(ref move, false);
                            Moves[MoveIndex] = move;
                            MoveIndex++;
                            // Promote pawn to rook.
                            move = Move.Null;
                            Move.SetFrom(ref move, fromSquare);
                            Move.SetTo(ref move, toSquare);
                            Move.SetPromotedPiece(ref move, rook);
                            Move.SetIsPawnMove(ref move, true);
                            Move.SetIsQuiet(ref move, false);
                            Moves[MoveIndex] = move;
                            MoveIndex++;
                            // Promote pawn to bishop.
                            move = Move.Null;
                            Move.SetFrom(ref move, fromSquare);
                            Move.SetTo(ref move, toSquare);
                            Move.SetPromotedPiece(ref move, bishop);
                            Move.SetIsPawnMove(ref move, true);
                            Move.SetIsQuiet(ref move, false);
                            Moves[MoveIndex] = move;
                            MoveIndex++;
                            // Promote pawn to knight.
                            move = Move.Null;
                            Move.SetFrom(ref move, fromSquare);
                            Move.SetTo(ref move, toSquare);
                            Move.SetPromotedPiece(ref move, knight);
                            Move.SetIsPawnMove(ref move, true);
                            Move.SetIsQuiet(ref move, false);
                            Moves[MoveIndex] = move;
                            MoveIndex++;
                        }
                        Bitwise.ClearBit(ref pawnDestinations, toSquare);
                    }
                }
                if (MoveGeneration != MoveGeneration.OnlyNonCaptures)
                {
                    // Pawns may attack diagonally forward one square if occupied by enemy.
                    pawnDestinations = pawnAttackMasks[fromSquare] & enemyOccupiedSquares & ToSquareMask;
                    while ((toSquare = Bitwise.FindFirstSetBit(pawnDestinations)) != Square.Illegal)
                    {
                        toSquareRank = ranks[toSquare];
                        var victim = GetPiece(toSquare);
                        if (toSquareRank < 7)
                        {
                            move = Move.Null;
                            Move.SetFrom(ref move, fromSquare);
                            Move.SetTo(ref move, toSquare);
                            Move.SetCaptureAttacker(ref move, attacker);
                            Move.SetCaptureVictim(ref move, victim);
                            Move.SetIsPawnMove(ref move, true);
                            Move.SetIsQuiet(ref move, false);
                            Moves[MoveIndex] = move;
                            MoveIndex++;
                        }
                        else
                        {
                            // Promote pawn to queen.
                            move = Move.Null;
                            Move.SetFrom(ref move, fromSquare);
                            Move.SetTo(ref move, toSquare);
                            Move.SetPromotedPiece(ref move, queen);
                            Move.SetCaptureAttacker(ref move, attacker);
                            Move.SetCaptureVictim(ref move, victim);
                            Move.SetIsPawnMove(ref move, true);
                            Move.SetIsQuiet(ref move, false);
                            Moves[MoveIndex] = move;
                            MoveIndex++;
                            // Promote pawn to rook.
                            move = Move.Null;
                            Move.SetFrom(ref move, fromSquare);
                            Move.SetTo(ref move, toSquare);
                            Move.SetPromotedPiece(ref move, rook);
                            Move.SetCaptureAttacker(ref move, attacker);
                            Move.SetCaptureVictim(ref move, victim);
                            Move.SetIsPawnMove(ref move, true);
                            Move.SetIsQuiet(ref move, false);
                            Moves[MoveIndex] = move;
                            MoveIndex++;
                            // Promote pawn to bishop.
                            move = Move.Null;
                            Move.SetFrom(ref move, fromSquare);
                            Move.SetTo(ref move, toSquare);
                            Move.SetPromotedPiece(ref move, bishop);
                            Move.SetCaptureAttacker(ref move, attacker);
                            Move.SetCaptureVictim(ref move, victim);
                            Move.SetIsPawnMove(ref move, true);
                            Move.SetIsQuiet(ref move, false);
                            Moves[MoveIndex] = move;
                            MoveIndex++;
                            // Promote pawn to knight.
                            move = Move.Null;
                            Move.SetFrom(ref move, fromSquare);
                            Move.SetTo(ref move, toSquare);
                            Move.SetPromotedPiece(ref move, knight);
                            Move.SetCaptureAttacker(ref move, attacker);
                            Move.SetCaptureVictim(ref move, victim);
                            Move.SetIsPawnMove(ref move, true);
                            Move.SetIsQuiet(ref move, false);
                            Moves[MoveIndex] = move;
                            MoveIndex++;
                        }
                        Bitwise.ClearBit(ref pawnDestinations, toSquare);
                    }
                }
                Bitwise.ClearBit(ref pawns, fromSquare);
            }
        }