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); }
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); }