Exemple #1
0
    public void FindPinnedPieces()
    {
        var ownKingSquare          = Bitwise.FirstSetSquare(GetKing(ColorToMove));
        var ownPieces              = ColorOccupancy[(int)ColorToMove];
        var enemyRankFileAttackers = GetRooks(ColorLastMoved) | GetQueens(ColorLastMoved);
        var enemyDiagonalAttackers = GetBishops(ColorLastMoved) | GetQueens(ColorLastMoved);
        var enemyPieces            = ColorOccupancy[(int)ColorLastMoved];

        // Find pieces pinned to own king by enemy rank / file attackers.
        PinnedPieces = 0;
        Square attackerSquare;

        while ((attackerSquare = Bitwise.PopFirstSetSquare(ref enemyRankFileAttackers)) != Square.Illegal)
        {
            var betweenSquares = Board.RankFileBetweenSquares[(int)attackerSquare][(int)ownKingSquare];
            if (betweenSquares == 0)
            {
                continue;
            }
            if ((betweenSquares & enemyPieces) == 0)
            {
                // No enemy pieces between enemy attacker and own king.
                var pinnedPieces = betweenSquares & ownPieces;
                if (Bitwise.CountSetBits(pinnedPieces) == 1)
                {
                    // Exactly one own piece between enemy attacker and own king.
                    // Piece is pinned to own king.
                    PinnedPieces |= pinnedPieces;
                }
            }
        }
        // Find pieces pinned to own king by enemy diagonal attackers.
        while ((attackerSquare = Bitwise.PopFirstSetSquare(ref enemyDiagonalAttackers)) != Square.Illegal)
        {
            var betweenSquares = Board.DiagonalBetweenSquares[(int)attackerSquare][(int)ownKingSquare];
            if (betweenSquares == 0)
            {
                continue;
            }
            if ((betweenSquares & enemyPieces) == 0)
            {
                // No enemy pieces between enemy attacker and own king.
                var pinnedPieces = betweenSquares & ownPieces;
                if (Bitwise.CountSetBits(pinnedPieces) == 1)
                {
                    // Exactly one own piece between enemy attacker and own king.
                    // Piece is pinned to own king.
                    PinnedPieces |= pinnedPieces;
                }
            }
        }
    }
Exemple #2
0
 private void GeneratePieceMoves(MoveGeneration moveGeneration, ulong fromSquareMask, ulong toSquareMask)
 {
     for (var colorlessPiece = ColorlessPiece.Knight; colorlessPiece <= ColorlessPiece.Queen; colorlessPiece++)
     {
         var attacker = PieceHelper.GetPieceOfColor(colorlessPiece, ColorToMove);
         var pieces   = PieceBitboards[(int)attacker] & fromSquareMask;
         if (pieces == 0)
         {
             continue;
         }
         var    getPieceMovesMask        = Board.PieceMoveMaskDelegates[(int)colorlessPiece];
         var    unOrEnemyOccupiedSquares = ~ColorOccupancy[(int)ColorToMove];
         var    enemyOccupiedSquares     = ColorOccupancy[(int)ColorLastMoved];
         Square fromSquare;
         while ((fromSquare = Bitwise.PopFirstSetSquare(ref pieces)) != Square.Illegal)
         {
             var pieceDestinations = moveGeneration switch
             {
                 MoveGeneration.AllMoves => getPieceMovesMask(fromSquare, Occupancy) & unOrEnemyOccupiedSquares & toSquareMask,
                 MoveGeneration.OnlyCaptures => getPieceMovesMask(fromSquare, Occupancy) & enemyOccupiedSquares & toSquareMask,
                 MoveGeneration.OnlyNonCaptures => getPieceMovesMask(fromSquare, Occupancy) & ~Occupancy & toSquareMask,
                 _ => throw new Exception($"{moveGeneration} move generation not supported.")
             };
             Square toSquare;
             while ((toSquare = Bitwise.PopFirstSetSquare(ref pieceDestinations)) != Square.Illegal)
             {
                 var victim = GetPiece(toSquare);
                 var move   = Move.Null;
                 Move.SetPiece(ref move, attacker);
                 Move.SetFrom(ref move, fromSquare);
                 Move.SetTo(ref move, toSquare);
                 if (victim != Piece.None)
                 {
                     Move.SetCaptureAttacker(ref move, attacker);
                 }
                 Move.SetCaptureVictim(ref move, victim);
                 Moves[MoveIndex] = move;
                 MoveIndex++;
             }
         }
     }
 }
Exemple #3
0
    private void GenerateKingMoves(MoveGeneration moveGeneration, ulong fromSquareMask, ulong toSquareMask)
    {
        var king = GetKing(ColorToMove) & fromSquareMask;

        if (king == 0)
        {
            return;
        }
        var   unOrEnemyOccupiedSquares = ~ColorOccupancy[(int)ColorToMove];
        var   enemyOccupiedSquares     = ColorOccupancy[(int)ColorLastMoved];
        var   attacker = PieceHelper.GetPieceOfColor(ColorlessPiece.King, ColorToMove);
        ulong move;
        var   fromSquare = Bitwise.FirstSetSquare(king);

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

        while ((toSquare = Bitwise.PopFirstSetSquare(ref kingDestinations)) != Square.Illegal)
        {
            var victim = GetPiece(toSquare);
            move = Move.Null;
            Move.SetPiece(ref move, attacker);
            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);
            Moves[MoveIndex] = move;
            MoveIndex++;
        }
        if (moveGeneration != MoveGeneration.OnlyCaptures)
        {
            for (var boardSide = BoardSide.Queen; boardSide <= BoardSide.King; boardSide++)
            {
                var castleEmptySquaresMask = Board.CastleEmptySquaresMask[(int)ColorToMove][(int)boardSide];
                if (!KingInCheck && Game.Castling.Permitted(Castling, ColorToMove, boardSide) && ((Occupancy & castleEmptySquaresMask) == 0))
                {
                    // Castle
                    toSquare = Board.CastleToSquares[(int)ColorToMove][(int)boardSide];
                    if ((Board.SquareMasks[(int)toSquare] & toSquareMask) > 0)
                    {
                        move = Move.Null;
                        Move.SetPiece(ref move, attacker);
                        Move.SetFrom(ref move, fromSquare);
                        Move.SetTo(ref move, toSquare);
                        Move.SetIsCastling(ref move, true);
                        Move.SetIsKingMove(ref move, true);
                        Moves[MoveIndex] = move;
                        MoveIndex++;
                    }
                }
            }
        }
    }
Exemple #4
0
    private void GeneratePawnMoves(MoveGeneration moveGeneration, ulong fromSquareMask, ulong toSquareMask)
    {
        var pawns = GetPawns(ColorToMove) & fromSquareMask;

        if (pawns == 0)
        {
            return;
        }
        var    pawnMoveMasks        = Board.PawnMoveMasks[(int)ColorToMove];
        var    pawnDoubleMoveMasks  = Board.PawnDoubleMoveMasks[(int)ColorToMove];
        var    pawnAttackMasks      = Board.PawnAttackMasks[(int)ColorToMove];
        var    enemyOccupiedSquares = ColorOccupancy[(int)ColorLastMoved];
        var    unoccupiedSquares    = ~Occupancy;
        var    ranks           = Board.Ranks[(int)ColorToMove];
        var    attacker        = PieceHelper.GetPieceOfColor(ColorlessPiece.Pawn, ColorToMove);
        var    queen           = PieceHelper.GetPieceOfColor(ColorlessPiece.Queen, ColorToMove);
        var    knight          = PieceHelper.GetPieceOfColor(ColorlessPiece.Knight, ColorToMove);
        var    enPassantVictim = PieceHelper.GetPieceOfColor(ColorlessPiece.Pawn, ColorLastMoved);
        Square fromSquare;
        ulong  move;

        if ((EnPassantSquare != Square.Illegal) && ((Board.SquareMasks[(int)EnPassantSquare] & toSquareMask) > 0) && (moveGeneration != MoveGeneration.OnlyNonCaptures))
        {
            var enPassantAttackers = Board.EnPassantAttackerMasks[(int)EnPassantSquare] & pawns;
            while ((fromSquare = Bitwise.PopFirstSetSquare(ref enPassantAttackers)) != Square.Illegal)
            {
                // Capture pawn en passant.
                move = Move.Null;
                Move.SetPiece(ref move, attacker);
                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);
                Moves[MoveIndex] = move;
                MoveIndex++;
            }
        }
        while ((fromSquare = Bitwise.PopFirstSetSquare(ref pawns)) != Square.Illegal)
        {
            ulong  pawnDestinations;
            Square 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[(int)fromSquare] & unoccupiedSquares & toSquareMask;
                while ((toSquare = Bitwise.PopFirstSetSquare(ref pawnDestinations)) != Square.Illegal)
                {
                    var doubleMove = Board.SquareDistances[(int)fromSquare][(int)toSquare] == 2;
                    if (doubleMove && ((Occupancy & pawnDoubleMoveMasks[(int)fromSquare]) > 0))
                    {
                        continue;                                                                         // Double move is blocked.
                    }
                    toSquareRank = ranks[(int)toSquare];
                    if (toSquareRank < 7)
                    {
                        move = Move.Null;
                        Move.SetPiece(ref move, attacker);
                        Move.SetFrom(ref move, fromSquare);
                        Move.SetTo(ref move, toSquare);
                        Move.SetIsDoublePawnMove(ref move, doubleMove);
                        Move.SetIsPawnMove(ref move, true);
                        Moves[MoveIndex] = move;
                        MoveIndex++;
                    }
                    else
                    {
                        for (var promotedPiece = queen; promotedPiece >= knight; promotedPiece--)
                        {
                            // Promote pawn.
                            move = Move.Null;
                            Move.SetPiece(ref move, attacker);
                            Move.SetFrom(ref move, fromSquare);
                            Move.SetTo(ref move, toSquare);
                            Move.SetPromotedPiece(ref move, promotedPiece);
                            Move.SetIsPawnMove(ref move, true);
                            Moves[MoveIndex] = move;
                            MoveIndex++;
                        }
                    }
                }
            }
            if (moveGeneration != MoveGeneration.OnlyNonCaptures)
            {
                // Pawns may attack diagonally forward one square if occupied by enemy.
                pawnDestinations = pawnAttackMasks[(int)fromSquare] & enemyOccupiedSquares & toSquareMask;
                while ((toSquare = Bitwise.PopFirstSetSquare(ref pawnDestinations)) != Square.Illegal)
                {
                    toSquareRank = ranks[(int)toSquare];
                    var victim = GetPiece(toSquare);
                    if (toSquareRank < 7)
                    {
                        move = Move.Null;
                        Move.SetPiece(ref move, attacker);
                        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);
                        Moves[MoveIndex] = move;
                        MoveIndex++;
                    }
                    else
                    {
                        for (var promotedPiece = queen; promotedPiece >= knight; promotedPiece--)
                        {
                            // Promote pawn.
                            move = Move.Null;
                            Move.SetPiece(ref move, attacker);
                            Move.SetFrom(ref move, fromSquare);
                            Move.SetTo(ref move, toSquare);
                            Move.SetCaptureAttacker(ref move, attacker);
                            Move.SetPromotedPiece(ref move, promotedPiece);
                            Move.SetCaptureVictim(ref move, victim);
                            Move.SetIsPawnMove(ref move, true);
                            Moves[MoveIndex] = move;
                            MoveIndex++;
                        }
                    }
                }
            }
        }
    }