Consider a check given by a rook or a minor to be a "safe check"
also in the case where supported by another piece,
and given on a square only defended by a queen
Was yellow STC
http://tests.stockfishchess.org/tests/view/
576fcbc80ebc5972faa163e8
LLR: -2.96 (-2.94,2.94) [0.00,5.00]
Total: 55453 W: 10431 L: 10315 D: 34707
Passed LTC
http://tests.stockfishchess.org/tests/view/
57733a0b0ebc5972faa164b7
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 54550 W: 7671 L: 7365 D: 39514
bench:
7398346
// attacked by a given color and piece type (can be also ALL_PIECES).
Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB];
// attacked by a given color and piece type (can be also ALL_PIECES).
Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB];
+ // attackedBy2[color] are the squares attacked by 2 pieces of a given color,
+ // possibly via x-ray or by one pawn and one piece. Diagonal x-ray through
+ // pawn or squares attacked by 2 pawns are not explicitly added.
+ Bitboard attackedBy2[COLOR_NB];
+
// kingRing[color] is the zone around the king which is considered
// by the king safety evaluation. This consists of the squares directly
// adjacent to the king, and the three (or two, for a king on an edge file)
// kingRing[color] is the zone around the king which is considered
// by the king safety evaluation. This consists of the squares directly
// adjacent to the king, and the three (or two, for a king on an edge file)
const Square Down = (Us == WHITE ? DELTA_S : DELTA_N);
ei.pinnedPieces[Us] = pos.pinned_pieces(Us);
const Square Down = (Us == WHITE ? DELTA_S : DELTA_N);
ei.pinnedPieces[Us] = pos.pinned_pieces(Us);
- Bitboard b = ei.attackedBy[Them][KING] = pos.attacks_from<KING>(pos.square<KING>(Them));
+ Bitboard b = ei.attackedBy[Them][KING];
ei.attackedBy[Them][ALL_PIECES] |= b;
ei.attackedBy[Us][ALL_PIECES] |= ei.attackedBy[Us][PAWN] = ei.pi->pawn_attacks(Us);
ei.attackedBy[Them][ALL_PIECES] |= b;
ei.attackedBy[Us][ALL_PIECES] |= ei.attackedBy[Us][PAWN] = ei.pi->pawn_attacks(Us);
+ ei.attackedBy2[Us] = ei.attackedBy[Us][PAWN] & ei.attackedBy[Us][KING];
// Init king safety tables only if we are going to use them
if (pos.non_pawn_material(Us) >= QueenValueMg)
// Init king safety tables only if we are going to use them
if (pos.non_pawn_material(Us) >= QueenValueMg)
if (ei.pinnedPieces[Us] & s)
b &= LineBB[pos.square<KING>(Us)][s];
if (ei.pinnedPieces[Us] & s)
b &= LineBB[pos.square<KING>(Us)][s];
+ ei.attackedBy2[Us] |= ei.attackedBy[Us][ALL_PIECES] & b;
ei.attackedBy[Us][ALL_PIECES] |= ei.attackedBy[Us][Pt] |= b;
if (b & ei.kingRing[Them])
ei.attackedBy[Us][ALL_PIECES] |= ei.attackedBy[Us][Pt] |= b;
if (b & ei.kingRing[Them])
if (ei.kingAttackersCount[Them])
{
// Find the attacked squares which are defended only by the king...
if (ei.kingAttackersCount[Them])
{
// Find the attacked squares which are defended only by the king...
- undefended = ei.attackedBy[Them][ALL_PIECES]
- & ei.attackedBy[Us][KING]
- & ~( ei.attackedBy[Us][PAWN] | ei.attackedBy[Us][KNIGHT]
- | ei.attackedBy[Us][BISHOP] | ei.attackedBy[Us][ROOK]
- | ei.attackedBy[Us][QUEEN]);
+ undefended = ei.attackedBy[Them][ALL_PIECES]
+ & ei.attackedBy[Us][KING]
+ & ~ei.attackedBy2[Us];
// ... and those which are not defended at all in the larger king ring
b = ei.attackedBy[Them][ALL_PIECES] & ~ei.attackedBy[Us][ALL_PIECES]
// ... and those which are not defended at all in the larger king ring
b = ei.attackedBy[Them][ALL_PIECES] & ~ei.attackedBy[Us][ALL_PIECES]
// Analyse the enemy's safe queen contact checks. Firstly, find the
// undefended squares around the king reachable by the enemy queen...
b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them);
// Analyse the enemy's safe queen contact checks. Firstly, find the
// undefended squares around the king reachable by the enemy queen...
b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them);
- if (b)
- {
- // ...and then remove squares not supported by another enemy piece
- b &= ei.attackedBy[Them][PAWN] | ei.attackedBy[Them][KNIGHT]
- | ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK]
- | ei.attackedBy[Them][KING];
- attackUnits += QueenContactCheck * popcount(b);
- }
+ // ...and keep squares supported by another enemy piece
+ attackUnits += QueenContactCheck * popcount(b & ei.attackedBy2[Them]);
// Analyse the safe enemy's checks which are possible on next move...
safe = ~(ei.attackedBy[Us][ALL_PIECES] | pos.pieces(Them));
// Analyse the safe enemy's checks which are possible on next move...
safe = ~(ei.attackedBy[Us][ALL_PIECES] | pos.pieces(Them));
if ((b1 | b2) & ei.attackedBy[Them][QUEEN] & safe)
attackUnits += QueenCheck, score -= SafeCheck;
if ((b1 | b2) & ei.attackedBy[Them][QUEEN] & safe)
attackUnits += QueenCheck, score -= SafeCheck;
+ // For other pieces, also consider the square safe if attacked twice,
+ // and only defended by a queen.
+ safe |= ei.attackedBy2[Them]
+ & ~(ei.attackedBy2[Us] | pos.pieces(Them))
+ & ei.attackedBy[Us][QUEEN];
+
// Enemy rooks safe and other checks
if (b1 & ei.attackedBy[Them][ROOK] & safe)
attackUnits += RookCheck, score -= SafeCheck;
// Enemy rooks safe and other checks
if (b1 & ei.attackedBy[Them][ROOK] & safe)
attackUnits += RookCheck, score -= SafeCheck;
// Initialize attack and king safety bitboards
ei.attackedBy[WHITE][ALL_PIECES] = ei.attackedBy[BLACK][ALL_PIECES] = 0;
// Initialize attack and king safety bitboards
ei.attackedBy[WHITE][ALL_PIECES] = ei.attackedBy[BLACK][ALL_PIECES] = 0;
+ ei.attackedBy[WHITE][KING] = pos.attacks_from<KING>(pos.square<KING>(WHITE));
+ ei.attackedBy[BLACK][KING] = pos.attacks_from<KING>(pos.square<KING>(BLACK));
eval_init<WHITE>(pos, ei);
eval_init<BLACK>(pos, ei);
eval_init<WHITE>(pos, ei);
eval_init<BLACK>(pos, ei);