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