public static int CalculateThreats(ChessBoard cb) { var score = 0; 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 whiteAttacks = cb.Attacks[White][All]; var whitePawnAttacks = cb.Attacks[White][Pawn]; var whiteMinorAttacks = cb.Attacks[White][Knight] | cb.Attacks[White][Bishop]; var blackAttacks = cb.Attacks[Black][All]; var blackPawnAttacks = cb.Attacks[Black][Pawn]; var blackMinorAttacks = cb.Attacks[Black][Knight] | cb.Attacks[Black][Bishop]; // double attacked pieces var piece = cb.DoubleAttacks[White] & blacks; while (piece != 0) { score += EvalConstants.DoubleAttacked[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]]; piece &= piece - 1; } piece = cb.DoubleAttacks[Black] & whites; while (piece != 0) { score -= EvalConstants.DoubleAttacked[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]]; piece &= piece - 1; } if (MaterialUtil.HasPawns(cb.MaterialKey)) { // unused outposts score += BitOperations.PopCount((ulong)(cb.PassedPawnsAndOutposts & cb.EmptySpaces & whiteMinorAttacks & whitePawnAttacks)) * EvalConstants.Threats[EvalConstants.IxUnusedOutpost]; score -= BitOperations.PopCount((ulong)(cb.PassedPawnsAndOutposts & cb.EmptySpaces & blackMinorAttacks & blackPawnAttacks)) * EvalConstants.Threats[EvalConstants.IxUnusedOutpost]; // pawn push threat piece = (whitePawns << 8) & cb.EmptySpaces & ~blackAttacks; score += BitOperations.PopCount((ulong)(Bitboard.GetWhitePawnAttacks(piece) & blacks)) * EvalConstants.Threats[EvalConstants.IxPawnPushThreat]; piece = Util.RightTripleShift(blackPawns, 8) & cb.EmptySpaces & ~whiteAttacks; score -= BitOperations.PopCount((ulong)(Bitboard.GetBlackPawnAttacks(piece) & whites)) * EvalConstants.Threats[EvalConstants.IxPawnPushThreat]; // piece attacked by pawn score += BitOperations.PopCount((ulong)(whitePawnAttacks & blacks & ~blackPawns)) * EvalConstants.Threats[EvalConstants.IxPawnAttacks]; score -= BitOperations.PopCount((ulong)(blackPawnAttacks & whites & ~whitePawns)) * EvalConstants.Threats[EvalConstants.IxPawnAttacks]; // multiple pawn attacks possible if (BitOperations.PopCount((ulong)(whitePawnAttacks & blacks)) > 1) { score += EvalConstants.Threats[EvalConstants.IxMultiplePawnAttacks]; } if (BitOperations.PopCount((ulong)(blackPawnAttacks & whites)) > 1) { score -= EvalConstants.Threats[EvalConstants.IxMultiplePawnAttacks]; } // pawn attacked score += BitOperations.PopCount((ulong)(whiteAttacks & blackPawns)) * EvalConstants.Threats[EvalConstants.IxPawnAttacked]; score -= BitOperations.PopCount((ulong)(blackAttacks & whitePawns)) * EvalConstants.Threats[EvalConstants.IxPawnAttacked]; } // minors attacked and not defended by a pawn score += BitOperations.PopCount((ulong)(whiteAttacks & (cb.Pieces[Black][Knight] | (cb.Pieces[Black][Bishop] & ~blackAttacks)))) * EvalConstants.Threats[EvalConstants.IxMajorAttacked]; score -= BitOperations.PopCount((ulong)(blackAttacks & (cb.Pieces[White][Knight] | (cb.Pieces[White][Bishop] & ~whiteAttacks)))) * EvalConstants.Threats[EvalConstants.IxMajorAttacked]; if (cb.Pieces[Black][Queen] != 0) { // queen attacked by rook score += BitOperations.PopCount((ulong)(cb.Attacks[White][Rook] & cb.Pieces[Black][Queen])) * EvalConstants.Threats[EvalConstants.IxQueenAttacked]; // queen attacked by minors score += BitOperations.PopCount((ulong)(whiteMinorAttacks & cb.Pieces[Black][Queen])) * EvalConstants.Threats[EvalConstants.IxQueenAttackedMinor]; } if (cb.Pieces[White][Queen] != 0) { // queen attacked by rook score -= BitOperations.PopCount((ulong)(cb.Attacks[Black][Rook] & cb.Pieces[White][Queen])) * EvalConstants.Threats[EvalConstants.IxQueenAttacked]; // queen attacked by minors score -= BitOperations.PopCount((ulong)(blackMinorAttacks & cb.Pieces[White][Queen])) * EvalConstants.Threats[EvalConstants.IxQueenAttackedMinor]; } // rook attacked by minors score += BitOperations.PopCount((ulong)(whiteMinorAttacks & cb.Pieces[Black][Rook])) * EvalConstants.Threats[EvalConstants.IxRookAttacked]; score -= BitOperations.PopCount((ulong)(blackMinorAttacks & cb.Pieces[White][Rook])) * EvalConstants.Threats[EvalConstants.IxRookAttacked]; return(score); }
private static int CalculatePawnScores(ChessBoard cb) { var score = 0; // penalty for doubled pawns for (var i = 0; i < 8; i++) { if (BitOperations.PopCount((ulong)(cb.Pieces[White][Pawn] & Bitboard.Files[i])) > 1) { score -= EvalConstants.PawnScores[EvalConstants.IxPawnDouble]; } if (BitOperations.PopCount((ulong)(cb.Pieces[Black][Pawn] & Bitboard.Files[i])) > 1) { score += EvalConstants.PawnScores[EvalConstants.IxPawnDouble]; } } // bonus for connected pawns var pawns = Bitboard.GetWhitePawnAttacks(cb.Pieces[White][Pawn]) & cb.Pieces[White][Pawn]; while (pawns != 0) { score += EvalConstants.PawnConnected[BitOperations.TrailingZeroCount(pawns) / 8]; pawns &= pawns - 1; } pawns = Bitboard.GetBlackPawnAttacks(cb.Pieces[Black][Pawn]) & cb.Pieces[Black][Pawn]; while (pawns != 0) { score -= EvalConstants.PawnConnected[7 - BitOperations.TrailingZeroCount(pawns) / 8]; pawns &= pawns - 1; } // bonus for neighbour pawns pawns = Bitboard.GetPawnNeighbours(cb.Pieces[White][Pawn]) & cb.Pieces[White][Pawn]; while (pawns != 0) { score += EvalConstants.PawnNeighbour[BitOperations.TrailingZeroCount(pawns) / 8]; pawns &= pawns - 1; } pawns = Bitboard.GetPawnNeighbours(cb.Pieces[Black][Pawn]) & cb.Pieces[Black][Pawn]; while (pawns != 0) { score -= EvalConstants.PawnNeighbour[7 - BitOperations.TrailingZeroCount(pawns) / 8]; pawns &= pawns - 1; } // set outposts cb.PassedPawnsAndOutposts = 0; pawns = Bitboard.GetWhitePawnAttacks(cb.Pieces[White][Pawn]) & ~cb.Pieces[White][Pawn] & ~cb.Pieces[Black][Pawn]; while (pawns != 0) { if ((Bitboard.GetWhiteAdjacentMask(BitOperations.TrailingZeroCount(pawns)) & cb.Pieces[Black][Pawn]) == 0) { cb.PassedPawnsAndOutposts |= pawns & -pawns; } pawns &= pawns - 1; } pawns = Bitboard.GetBlackPawnAttacks(cb.Pieces[Black][Pawn]) & ~cb.Pieces[White][Pawn] & ~cb.Pieces[Black][Pawn]; while (pawns != 0) { if ((Bitboard.GetBlackAdjacentMask(BitOperations.TrailingZeroCount(pawns)) & cb.Pieces[White][Pawn]) == 0) { cb.PassedPawnsAndOutposts |= pawns & -pawns; } pawns &= pawns - 1; } int index; // white pawns = cb.Pieces[White][Pawn]; while (pawns != 0) { index = BitOperations.TrailingZeroCount(pawns); // isolated pawns if ((Bitboard.FilesAdjacent[index & 7] & cb.Pieces[White][Pawn]) == 0) { score -= EvalConstants.PawnScores[EvalConstants.IxPawnIsolated]; } // backward pawns else if ((Bitboard.GetBlackAdjacentMask(index + 8) & cb.Pieces[White][Pawn]) == 0) { if ((StaticMoves.PawnAttacks[White][index + 8] & cb.Pieces[Black][Pawn]) != 0) { if ((Bitboard.Files[index & 7] & cb.Pieces[Black][Pawn]) == 0) { score -= EvalConstants.PawnScores[EvalConstants.IxPawnBackward]; } } } // pawn defending 2 pawns if (BitOperations.PopCount((ulong)(StaticMoves.PawnAttacks[White][index] & cb.Pieces[White][Pawn])) == 2) { score -= EvalConstants.PawnScores[EvalConstants.IxPawnInverse]; } // set passed pawns if ((Bitboard.GetWhitePassedPawnMask(index) & cb.Pieces[Black][Pawn]) == 0) { cb.PassedPawnsAndOutposts |= pawns & -pawns; } // candidate passed pawns (no pawns in front, more friendly pawns behind and adjacent than enemy pawns) else if (63 - BitOperations.LeadingZeroCount( (ulong)((cb.Pieces[White][Pawn] | cb.Pieces[Black][Pawn]) & Bitboard.Files[index & 7])) == index) { if (BitOperations.PopCount((ulong)(cb.Pieces[White][Pawn] & Bitboard.GetBlackPassedPawnMask(index + 8))) >= BitOperations.PopCount( (ulong)(cb.Pieces[Black][Pawn] & Bitboard.GetWhitePassedPawnMask(index)))) { score += EvalConstants.PassedCandidate[index / 8]; } } pawns &= pawns - 1; } // black pawns = cb.Pieces[Black][Pawn]; while (pawns != 0) { index = BitOperations.TrailingZeroCount(pawns); // isolated pawns if ((Bitboard.FilesAdjacent[index & 7] & cb.Pieces[Black][Pawn]) == 0) { score += EvalConstants.PawnScores[EvalConstants.IxPawnIsolated]; } // backward pawns else if ((Bitboard.GetWhiteAdjacentMask(index - 8) & cb.Pieces[Black][Pawn]) == 0) { if ((StaticMoves.PawnAttacks[Black][index - 8] & cb.Pieces[White][Pawn]) != 0) { if ((Bitboard.Files[index & 7] & cb.Pieces[White][Pawn]) == 0) { score += EvalConstants.PawnScores[EvalConstants.IxPawnBackward]; } } } // pawn defending 2 pawns if (BitOperations.PopCount((ulong)(StaticMoves.PawnAttacks[Black][index] & cb.Pieces[Black][Pawn])) == 2) { score += EvalConstants.PawnScores[EvalConstants.IxPawnInverse]; } // set passed pawns if ((Bitboard.GetBlackPassedPawnMask(index) & cb.Pieces[White][Pawn]) == 0) { cb.PassedPawnsAndOutposts |= pawns & -pawns; } // candidate passers else if (BitOperations.TrailingZeroCount((cb.Pieces[White][Pawn] | cb.Pieces[Black][Pawn]) & Bitboard.Files[index & 7]) == index) { if (BitOperations.PopCount((ulong)(cb.Pieces[Black][Pawn] & Bitboard.GetWhitePassedPawnMask(index - 8))) >= BitOperations.PopCount( (ulong)(cb.Pieces[White][Pawn] & Bitboard.GetBlackPassedPawnMask(index)))) { score -= EvalConstants.PassedCandidate[7 - index / 8]; } } pawns &= pawns - 1; } return(score); }