// Enemy rooks checks
rookChecks = b1 & safe & attackedBy[Them][ROOK];
-
if (rookChecks)
- kingDanger += RookSafeCheck;
+ kingDanger += more_than_one(rookChecks) ? RookSafeCheck * 3/2
+ : RookSafeCheck;
else
unsafeChecks |= b1 & attackedBy[Them][ROOK];
& safe
& ~attackedBy[Us][QUEEN]
& ~rookChecks;
-
if (queenChecks)
- kingDanger += QueenSafeCheck;
+ kingDanger += more_than_one(queenChecks) ? QueenSafeCheck * 3/2
+ : QueenSafeCheck;
// Enemy bishops checks: we count them only if they are from squares from
// which we can't give a queen check, because queen checks are more valuable.
& attackedBy[Them][BISHOP]
& safe
& ~queenChecks;
-
if (bishopChecks)
- kingDanger += BishopSafeCheck;
+ kingDanger += more_than_one(bishopChecks) ? BishopSafeCheck * 3/2
+ : BishopSafeCheck;
else
unsafeChecks |= b2 & attackedBy[Them][BISHOP];
// Enemy knights checks
knightChecks = pos.attacks_from<KNIGHT>(ksq) & attackedBy[Them][KNIGHT];
-
if (knightChecks & safe)
- kingDanger += KnightSafeCheck;
+ kingDanger += more_than_one(knightChecks & safe) ? KnightSafeCheck * 3/2
+ : KnightSafeCheck;
else
unsafeChecks |= knightChecks;
// Now apply the bonus: note that we find the attacking side by extracting the
// sign of the midgame or endgame values, and that we carefully cap the bonus
// so that the midgame and endgame scores do not change sign after the bonus.
- int u = ((mg > 0) - (mg < 0)) * std::max(std::min(complexity + 50, 0), -abs(mg));
+ int u = ((mg > 0) - (mg < 0)) * Utility::clamp(complexity + 50, -abs(mg), 0);
int v = ((eg > 0) - (eg < 0)) * std::max(complexity, -abs(eg));
if (T)
// If scale is not already specific, scale down the endgame via general heuristics
if (sf == SCALE_FACTOR_NORMAL)
{
- if ( pos.opposite_bishops()
- && pos.non_pawn_material() == 2 * BishopValueMg)
- sf = 22;
+ if (pos.opposite_bishops())
+ {
+ if ( pos.non_pawn_material(WHITE) == BishopValueMg
+ && pos.non_pawn_material(BLACK) == BishopValueMg)
+ sf = 22;
+ else
+ sf = 22 + 3 * pos.count<ALL_PIECES>(strongSide);
+ }
else
- sf = std::min(sf, 36 + (pos.opposite_bishops() ? 2 : 7) * pos.count<PAWN>(strongSide));
+ sf = std::min(sf, 36 + 7 * pos.count<PAWN>(strongSide));
sf = std::max(0, sf - (pos.rule50_count() - 12) / 4);
}
initialize<WHITE>();
initialize<BLACK>();
- // Pieces should be evaluated first (populate attack tables)
+ // Pieces evaluated first (also populates attackedBy, attackedBy2).
+ // Note that the order of evaluation of the terms is left unspecified
score += pieces<WHITE, KNIGHT>() - pieces<BLACK, KNIGHT>()
+ pieces<WHITE, BISHOP>() - pieces<BLACK, BISHOP>()
+ pieces<WHITE, ROOK >() - pieces<BLACK, ROOK >()
score += mobility[WHITE] - mobility[BLACK];
+ // More complex interactions that require fully populated attack bitboards
score += king< WHITE>() - king< BLACK>()
+ threats<WHITE>() - threats<BLACK>()
+ passed< WHITE>() - passed< BLACK>()