Esempio n. 1
0
        public static bool IsKrkpDrawish(ChessBoard cb)
        {
            var leadingColor = cb.Pieces[White][Rook] != 0 ? White : Black;
            var rook         = cb.Pieces[leadingColor][Rook];
            var pawn         = cb.Pieces[1 - leadingColor][Pawn];
            var pawnIndex    = BitOperations.TrailingZeroCount(pawn);
            var winningKing  = cb.Pieces[leadingColor][King];
            var losingKing   = cb.Pieces[1 - leadingColor][King];

            if ((Bitboard.GetFile(pawn) & winningKing) != 0 &&
                (leadingColor == White && pawnIndex > cb.KingIndex[leadingColor] ||
                 leadingColor == Black && pawnIndex < cb.KingIndex[leadingColor]))
            {
                // If the stronger side's king is in front of the pawn, it's a win
                return(false);
            }

            if (Util.GetDistance(losingKing, pawn) >= 3 + (cb.ColorToMove == 1 - leadingColor ? 1 : 0) &&
                Util.GetDistance(losingKing, rook) >= 3)
            {
                // If the weaker side's king is too far from the pawn and the rook, it's a win.
                return(false);
            }

            if (leadingColor == White)
            {
                if (Bitboard.GetRank(losingKing) <= Bitboard.Rank3 && Util.GetDistance(losingKing, pawn) == 1 &&
                    Bitboard.GetRank(winningKing) >= Bitboard.Rank4 &&
                    Util.GetDistance(winningKing, pawn) > 2 + (cb.ColorToMove == leadingColor ? 1 : 0))
                {
                    // If the pawn is far advanced and supported by the defending king, the position is drawish
                    return(true);
                }
            }
            else
            {
                if (Bitboard.GetRank(losingKing) >= Bitboard.Rank5 && Util.GetDistance(losingKing, pawn) == 1 &&
                    Bitboard.GetRank(winningKing) <= Bitboard.Rank5 &&
                    Util.GetDistance(winningKing, pawn) > 2 + (cb.ColorToMove == leadingColor ? 1 : 0))
                {
                    // If the pawn is far advanced and supported by the defending king, the position is drawish
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 2
0
        public static int CalculateOthers(ChessBoard cb)
        {
            var  score = 0;
            long piece;

            var whites           = cb.Pieces[White][All];
            var whitePawns       = cb.Pieces[White][Pawn];
            var blacks           = cb.Pieces[Black][All];
            var blackPawns       = cb.Pieces[Black][Pawn];
            var whitePawnAttacks = cb.Attacks[White][Pawn];
            var blackPawnAttacks = cb.Attacks[Black][Pawn];

            // side to move
            score += ColorFactor[cb.ColorToMove] * EvalConstants.SideToMoveBonus;

            // WHITE ROOK
            if (cb.Pieces[White][Rook] != 0)
            {
                piece = cb.Pieces[White][Rook];

                // rook battery (same file)
                if (BitOperations.PopCount((ulong)piece) == 2)
                {
                    if ((BitOperations.TrailingZeroCount(piece) & 7) ==
                        ((63 - BitOperations.LeadingZeroCount((ulong)piece)) & 7))
                    {
                        score += EvalConstants.OtherScores[EvalConstants.IxRookBattery];
                    }
                }

                // rook on 7th, king on 8th
                if (cb.KingIndex[Black] >= 56 && (piece & Bitboard.Rank7) != 0)
                {
                    score += BitOperations.PopCount((ulong)(piece & Bitboard.Rank7)) *
                             EvalConstants.OtherScores[EvalConstants.IxRook7ThRank];
                }

                // prison
                if ((piece & Bitboard.Rank1) != 0)
                {
                    var trapped = piece & EvalConstants.RookPrison[cb.KingIndex[White]];
                    if (trapped != 0)
                    {
                        if ((((trapped << 8) | (trapped << 16)) & whitePawns) != 0)
                        {
                            score += EvalConstants.OtherScores[EvalConstants.IxRookTrapped];
                        }
                    }
                }

                // rook on open-file (no pawns) and semi-open-file (no friendly pawns)
                while (piece != 0)
                {
                    if ((whitePawns & Bitboard.GetFile(piece)) == 0)
                    {
                        if ((blackPawns & Bitboard.GetFile(piece)) == 0)
                        {
                            score += EvalConstants.OtherScores[EvalConstants.IxRookFileOpen];
                        }
                        else if ((blackPawns & blackPawnAttacks & Bitboard.GetFile(piece)) == 0)
                        {
                            score += EvalConstants.OtherScores[EvalConstants.IxRookFileSemiOpenIsolated];
                        }
                        else
                        {
                            score += EvalConstants.OtherScores[EvalConstants.IxRookFileSemiOpen];
                        }
                    }

                    piece &= piece - 1;
                }
            }

            // BLACK ROOK
            if (cb.Pieces[Black][Rook] != 0)
            {
                piece = cb.Pieces[Black][Rook];

                // rook battery (same file)
                if (BitOperations.PopCount((ulong)piece) == 2)
                {
                    if ((BitOperations.TrailingZeroCount(piece) & 7) ==
                        ((63 - BitOperations.LeadingZeroCount((ulong)piece)) & 7))
                    {
                        score -= EvalConstants.OtherScores[EvalConstants.IxRookBattery];
                    }
                }

                // rook on 2nd, king on 1st
                if (cb.KingIndex[White] <= 7 && (piece & Bitboard.Rank2) != 0)
                {
                    score -= BitOperations.PopCount((ulong)(piece & Bitboard.Rank2)) *
                             EvalConstants.OtherScores[EvalConstants.IxRook7ThRank];
                }

                // prison
                if ((piece & Bitboard.Rank8) != 0)
                {
                    var trapped = piece & EvalConstants.RookPrison[cb.KingIndex[Black]];
                    if (trapped != 0)
                    {
                        if (((Util.RightTripleShift(trapped, 8) | Util.RightTripleShift(trapped, 16)) & blackPawns) !=
                            0)
                        {
                            score -= EvalConstants.OtherScores[EvalConstants.IxRookTrapped];
                        }
                    }
                }

                // rook on open-file (no pawns) and semi-open-file (no friendly pawns)
                while (piece != 0)
                {
                    // TODO JITWatch unpredictable branch
                    if ((blackPawns & Bitboard.GetFile(piece)) == 0)
                    {
                        if ((whitePawns & Bitboard.GetFile(piece)) == 0)
                        {
                            score -= EvalConstants.OtherScores[EvalConstants.IxRookFileOpen];
                        }
                        else if ((whitePawns & whitePawnAttacks & Bitboard.GetFile(piece)) == 0)
                        {
                            score -= EvalConstants.OtherScores[EvalConstants.IxRookFileSemiOpenIsolated];
                        }
                        else
                        {
                            score -= EvalConstants.OtherScores[EvalConstants.IxRookFileSemiOpen];
                        }
                    }

                    piece &= piece - 1;
                }
            }

            // WHITE BISHOP
            if (cb.Pieces[White][Bishop] != 0)
            {
                // bishop outpost: protected by a pawn, cannot be attacked by enemy pawns
                piece = cb.Pieces[White][Bishop] & cb.PassedPawnsAndOutposts & whitePawnAttacks;
                if (piece != 0)
                {
                    score += BitOperations.PopCount((ulong)piece) * EvalConstants.OtherScores[EvalConstants.IxOutpost];
                }

                piece = cb.Pieces[White][Bishop];
                if ((piece & Bitboard.WhiteSquares) != 0)
                {
                    // pawns on same color as bishop
                    score += EvalConstants.BishopPawn[
                        BitOperations.PopCount((ulong)(whitePawns & Bitboard.WhiteSquares))];

                    // attacking center squares
                    if (BitOperations.PopCount((ulong)(cb.Attacks[White][Bishop] & Bitboard.E4D5)) == 2)
                    {
                        score += EvalConstants.OtherScores[EvalConstants.IxBishopLong];
                    }
                }

                if ((piece & Bitboard.BlackSquares) != 0)
                {
                    // pawns on same color as bishop
                    score += EvalConstants.BishopPawn[
                        BitOperations.PopCount((ulong)(whitePawns & Bitboard.BlackSquares))];

                    // attacking center squares
                    if (BitOperations.PopCount((ulong)(cb.Attacks[White][Bishop] & Bitboard.D4E5)) == 2)
                    {
                        score += EvalConstants.OtherScores[EvalConstants.IxBishopLong];
                    }
                }

                // prison
                piece &= Bitboard.Rank2;
                while (piece != 0)
                {
                    if (BitOperations.PopCount(
                            (ulong)(EvalConstants.BishopPrison[BitOperations.TrailingZeroCount(piece)] & blackPawns)) == 2)
                    {
                        score += EvalConstants.OtherScores[EvalConstants.IxBishopPrison];
                    }

                    piece &= piece - 1;
                }
            }

            // BLACK BISHOP
            if (cb.Pieces[Black][Bishop] != 0)
            {
                // bishop outpost: protected by a pawn, cannot be attacked by enemy pawns
                piece = cb.Pieces[Black][Bishop] & cb.PassedPawnsAndOutposts & blackPawnAttacks;
                if (piece != 0)
                {
                    score -= BitOperations.PopCount((ulong)piece) * EvalConstants.OtherScores[EvalConstants.IxOutpost];
                }

                piece = cb.Pieces[Black][Bishop];
                if ((piece & Bitboard.WhiteSquares) != 0)
                {
                    // penalty for many pawns on same color as bishop
                    score -= EvalConstants.BishopPawn[
                        BitOperations.PopCount((ulong)(blackPawns & Bitboard.WhiteSquares))];

                    // bonus for attacking center squares
                    if (BitOperations.PopCount((ulong)(cb.Attacks[Black][Bishop] & Bitboard.E4D5)) == 2)
                    {
                        score -= EvalConstants.OtherScores[EvalConstants.IxBishopLong];
                    }
                }

                if ((piece & Bitboard.BlackSquares) != 0)
                {
                    // penalty for many pawns on same color as bishop
                    score -= EvalConstants.BishopPawn[
                        BitOperations.PopCount((ulong)(blackPawns & Bitboard.BlackSquares))];

                    // bonus for attacking center squares
                    if (BitOperations.PopCount((ulong)(cb.Attacks[Black][Bishop] & Bitboard.D4E5)) == 2)
                    {
                        score -= EvalConstants.OtherScores[EvalConstants.IxBishopLong];
                    }
                }

                // prison
                piece &= Bitboard.Rank7;
                while (piece != 0)
                {
                    if (BitOperations.PopCount(
                            (ulong)(EvalConstants.BishopPrison[BitOperations.TrailingZeroCount(piece)] & whitePawns)) == 2)
                    {
                        score -= EvalConstants.OtherScores[EvalConstants.IxBishopPrison];
                    }

                    piece &= piece - 1;
                }
            }

            // pieces supporting our pawns
            piece = (whitePawns << 8) & whites;
            while (piece != 0)
            {
                score += EvalConstants.PawnBlockage[Util.RightTripleShift(BitOperations.TrailingZeroCount(piece), 3)];
                piece &= piece - 1;
            }

            piece = Util.RightTripleShift(blackPawns, 8) & blacks;
            while (piece != 0)
            {
                score -= EvalConstants.PawnBlockage[7 - BitOperations.TrailingZeroCount(piece) / 8];
                piece &= piece - 1;
            }

            // knight outpost: protected by a pawn, cannot be attacked by enemy pawns
            piece = cb.Pieces[White][Knight] & cb.PassedPawnsAndOutposts & whitePawnAttacks;
            if (piece != 0)
            {
                score += BitOperations.PopCount((ulong)piece) * EvalConstants.OtherScores[EvalConstants.IxOutpost];
            }

            piece = cb.Pieces[Black][Knight] & cb.PassedPawnsAndOutposts & blackPawnAttacks;
            if (piece != 0)
            {
                score -= BitOperations.PopCount((ulong)piece) * EvalConstants.OtherScores[EvalConstants.IxOutpost];
            }

            // pinned-pieces
            if (cb.PinnedPieces != 0)
            {
                piece = cb.PinnedPieces & whites;
                while (piece != 0)
                {
                    score += EvalConstants.Pinned[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]];
                    piece &= piece - 1;
                }

                piece = cb.PinnedPieces & blacks;
                while (piece != 0)
                {
                    score -= EvalConstants.Pinned[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]];
                    piece &= piece - 1;
                }
            }

            // discovered-pieces
            if (cb.DiscoveredPieces != 0)
            {
                piece = cb.DiscoveredPieces & whites;
                while (piece != 0)
                {
                    score += EvalConstants.Discovered[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]];
                    piece &= piece - 1;
                }

                piece = cb.DiscoveredPieces & blacks;
                while (piece != 0)
                {
                    score -= EvalConstants.Discovered[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]];
                    piece &= piece - 1;
                }
            }

            if (cb.CastlingRights == 0)
            {
                return(score);
            }
            score += BitOperations.PopCount((ulong)(cb.CastlingRights & 12)) *
                     EvalConstants.OtherScores[EvalConstants.IxCastling];
            score -= BitOperations.PopCount((ulong)(cb.CastlingRights & 3)) *
                     EvalConstants.OtherScores[EvalConstants.IxCastling];

            return(score);
        }