// Penalties for enemy's safe checks
constexpr int QueenSafeCheck = 780;
- constexpr int RookSafeCheck = 880;
- constexpr int BishopSafeCheck = 435;
+ constexpr int RookSafeCheck = 1080;
+ constexpr int BishopSafeCheck = 635;
constexpr int KnightSafeCheck = 790;
#define S(mg, eg) make_score(mg, eg)
constexpr Score ThreatByPawnPush = S( 48, 39);
constexpr Score ThreatByRank = S( 13, 0);
constexpr Score ThreatBySafePawn = S(173, 94);
- constexpr Score TrappedRook = S( 96, 4);
+ constexpr Score TrappedRook = S( 47, 4);
constexpr Score WeakQueen = S( 49, 15);
constexpr Score WeakUnopposedPawn = S( 12, 23);
// kingRing[color] are the squares adjacent to the king, plus (only for a
// king on its first rank) the squares two ranks in front. For instance,
// if black's king is on g8, kingRing[BLACK] is f8, h8, f7, g7, h7, f6, g6
- // and h6. It is set to 0 when king safety evaluation is skipped.
+ // and h6.
Bitboard kingRing[COLOR_NB];
// kingAttackersCount[color] is the number of pieces of the given color
{
File kf = file_of(pos.square<KING>(Us));
if ((kf < FILE_E) == (file_of(s) < kf))
- score -= (TrappedRook - make_score(mob * 22, 0)) * (1 + !pos.castling_rights(Us));
+ score -= TrappedRook * (1 + !pos.castling_rights(Us));
}
}
b1 = attacks_bb<ROOK >(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
b2 = attacks_bb<BISHOP>(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
- // Enemy queen safe checks
- if ((b1 | b2) & attackedBy[Them][QUEEN] & safe & ~attackedBy[Us][QUEEN])
- kingDanger += QueenSafeCheck;
-
- b1 &= attackedBy[Them][ROOK];
- b2 &= attackedBy[Them][BISHOP];
-
// Enemy rooks checks
- if (b1 & safe)
+ Bitboard RookCheck = b1
+ & safe
+ & attackedBy[Them][ROOK];
+
+ if (RookCheck)
kingDanger += RookSafeCheck;
else
- unsafeChecks |= b1;
+ unsafeChecks |= b1 & attackedBy[Them][ROOK];
+
+ // Enemy queen safe checks: we count them only if they are from squares from
+ // which we can't give a rook check, because rook checks are more valuable.
+ Bitboard QueenCheck = (b1 | b2)
+ & attackedBy[Them][QUEEN]
+ & safe
+ & ~attackedBy[Us][QUEEN]
+ & ~RookCheck;
- // Enemy bishops checks
- if (b2 & safe)
+ if (QueenCheck)
+ kingDanger += 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.
+ Bitboard BishopCheck = b2
+ & attackedBy[Them][BISHOP]
+ & safe
+ & ~QueenCheck;
+
+ if (BishopCheck)
kingDanger += BishopSafeCheck;
else
- unsafeChecks |= b2;
+ unsafeChecks |= b2 & attackedBy[Them][BISHOP];
// Enemy knights checks
b = pos.attacks_from<KNIGHT>(ksq) & attackedBy[Them][KNIGHT];
+
if (b & safe)
kingDanger += KnightSafeCheck;
else
kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them]
+ 69 * kingAttacksCount[Them]
+ 185 * popcount(kingRing[Us] & weak)
+ - 100 * bool(attackedBy[Us][KNIGHT] & attackedBy[Us][KING])
+ 150 * popcount(pos.blockers_for_king(Us) | unsafeChecks)
- + tropism * tropism / 4
+ + 5 * tropism * tropism / 16
- 873 * !pos.count<QUEEN>(Them)
- 6 * mg_value(score) / 8
+ mg_value(mobility[Them] - mobility[Us])
- - 30;
+ - 25;
// Transform the kingDanger units into a Score, and subtract it from the evaluation
if (kingDanger > 0)
Score score = SCORE_ZERO;
// Non-pawn enemies
- nonPawnEnemies = pos.pieces(Them) & ~pos.pieces(Them, PAWN);
+ nonPawnEnemies = pos.pieces(Them) & ~pos.pieces(PAWN);
// Squares strongly protected by the enemy, either because they defend the
// square with a pawn, or because they defend the square twice and we don't.
if (pos.non_pawn_material() < SpaceThreshold)
return SCORE_ZERO;
- constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
+ constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
+ constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH);
constexpr Bitboard SpaceMask =
Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB)
: CenterFiles & (Rank7BB | Rank6BB | Rank5BB);
// Find all squares which are at most three squares behind some friendly pawn
Bitboard behind = pos.pieces(Us, PAWN);
- behind |= (Us == WHITE ? behind >> 8 : behind << 8);
- behind |= (Us == WHITE ? behind >> 16 : behind << 16);
+ behind |= shift<Down>(behind);
+ behind |= shift<Down>(shift<Down>(behind));
int bonus = popcount(safe) + popcount(behind & safe);
- int weight = pos.count<ALL_PIECES>(Us) - 2 * pe->open_files();
+ int weight = pos.count<ALL_PIECES>(Us)
+ - 2 * popcount(pe->semiopenFiles[WHITE] & pe->semiopenFiles[BLACK]);
Score score = make_score(bonus * weight * weight / 16, 0);
&& (pos.pieces(PAWN) & KingSide);
// Compute the initiative bonus for the attacking side
- int complexity = 8 * pe->pawn_asymmetry()
- + 12 * pos.count<PAWN>()
- + 12 * outflanking
- + 16 * pawnsOnBothFlanks
- + 48 * !pos.non_pawn_material()
- -118 ;
+ int complexity = 9 * pe->pawn_asymmetry()
+ + 11 * pos.count<PAWN>()
+ + 9 * outflanking
+ + 18 * pawnsOnBothFlanks
+ + 49 * !pos.non_pawn_material()
+ -121 ;
// Now apply the bonus: note that we find the attacking side by extracting
// the sign of the endgame value, and that we carefully cap the bonus so