Bitboard undefended, attackedByOthers, escapeSquares, occ, b, b1, b2, safe;
Square from, to;
bool sente;
- int attackUnits, count, shelter = 0;
+ int attackUnits, shelter = 0;
const Square ksq = pos.king_square(Us);
// King shelter
&& pos.non_pawn_material(Them) >= QueenValueMidgame + RookValueMidgame
&& ei.kingAdjacentZoneAttacksCount[Them])
{
- // Is it the attackers turn to move?
- sente = (Them == pos.side_to_move());
-
- // Find the attacked squares around the king which has no defenders
- // apart from the king itself
- undefended = ei.attacked_by(Them) & ei.attacked_by(Us, KING);
- undefended &= ~( ei.attacked_by(Us, PAWN) | ei.attacked_by(Us, KNIGHT)
- | ei.attacked_by(Us, BISHOP) | ei.attacked_by(Us, ROOK)
- | ei.attacked_by(Us, QUEEN));
-
- // Initialize the 'attackUnits' variable, which is used later on as an
- // index to the KingDangerTable[] array. The initial value is based on
- // the number and types of the enemy's attacking pieces, the number of
- // attacked and undefended squares around our king, the square of the
- // king, and the quality of the pawn shelter.
- attackUnits = Min(25, (ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them]) / 2)
- + 3 * (ei.kingAdjacentZoneAttacksCount[Them] + count_1s_max_15<HasPopCnt>(undefended))
- + InitKingDanger[relative_square(Us, ksq)]
- - (shelter >> 5);
-
- // Analyse safe queen contact checks
- b = undefended & ei.attacked_by(Them, QUEEN) & ~pos.pieces_of_color(Them);
- if (b)
- {
- attackedByOthers = ei.attacked_by(Them, PAWN) | ei.attacked_by(Them, KNIGHT)
- | ei.attacked_by(Them, BISHOP) | ei.attacked_by(Them, ROOK);
-
- b &= attackedByOthers;
-
- // Squares attacked by the queen and supported by another enemy piece and
- // not defended by other pieces but our king.
+ // Is it the attackers turn to move?
+ sente = (Them == pos.side_to_move());
+
+ // Find the attacked squares around the king which has no defenders
+ // apart from the king itself
+ undefended = ei.attacked_by(Them) & ei.attacked_by(Us, KING);
+ undefended &= ~( ei.attacked_by(Us, PAWN) | ei.attacked_by(Us, KNIGHT)
+ | ei.attacked_by(Us, BISHOP) | ei.attacked_by(Us, ROOK)
+ | ei.attacked_by(Us, QUEEN));
+
+ // Initialize the 'attackUnits' variable, which is used later on as an
+ // index to the KingDangerTable[] array. The initial value is based on
+ // the number and types of the enemy's attacking pieces, the number of
+ // attacked and undefended squares around our king, the square of the
+ // king, and the quality of the pawn shelter.
+ attackUnits = Min(25, (ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them]) / 2)
+ + 3 * (ei.kingAdjacentZoneAttacksCount[Them] + count_1s_max_15<HasPopCnt>(undefended))
+ + InitKingDanger[relative_square(Us, ksq)]
+ - shelter / 32;
+
+ // Analyse safe queen contact checks
+ b = undefended & ei.attacked_by(Them, QUEEN) & ~pos.pieces_of_color(Them);
if (b)
{
- // The bitboard b now contains the squares available for safe queen
- // contact checks.
- count = count_1s_max_15<HasPopCnt>(b);
- attackUnits += QueenContactCheckBonus * count * (sente ? 2 : 1);
+ attackedByOthers = ei.attacked_by(Them, PAWN) | ei.attacked_by(Them, KNIGHT)
+ | ei.attacked_by(Them, BISHOP) | ei.attacked_by(Them, ROOK);
- // Is there a mate threat?
- if (QueenContactMates && !pos.is_check())
+ b &= attackedByOthers;
+
+ // Squares attacked by the queen and supported by another enemy piece and
+ // not defended by other pieces but our king.
+ if (b)
{
- escapeSquares = pos.attacks_from<KING>(ksq) & ~pos.pieces_of_color(Us) & ~attackedByOthers;
- occ = pos.occupied_squares();
- while (b)
- {
- to = pop_1st_bit(&b);
+ // The bitboard b now contains the squares available for safe queen
+ // contact checks.
+ attackUnits += QueenContactCheckBonus * count_1s_max_15<HasPopCnt>(b) * (sente ? 2 : 1);
- // Do we have escape squares from queen contact check attack ?
- if (!(escapeSquares & ~queen_attacks_bb(to, occ & ClearMaskBB[ksq])))
+ // Is there a mate threat?
+ if (QueenContactMates && !pos.is_check())
+ {
+ escapeSquares = pos.attacks_from<KING>(ksq) & ~pos.pieces_of_color(Us) & ~attackedByOthers;
+ occ = pos.occupied_squares();
+ while (b)
{
- // We have a mate, unless the queen is pinned or there
- // is an X-ray attack through the queen.
- for (int i = 0; i < pos.piece_count(Them, QUEEN); i++)
+ to = pop_1st_bit(&b);
+
+ // Do we have escape squares from queen contact check attack ?
+ if (!(escapeSquares & ~queen_attacks_bb(to, occ & ClearMaskBB[ksq])))
{
- from = pos.piece_list(Them, QUEEN, i);
- if ( bit_is_set(pos.attacks_from<QUEEN>(from), to)
- && !bit_is_set(pos.pinned_pieces(Them), from)
- && !(rook_attacks_bb(to, occ & ClearMaskBB[from]) & pos.pieces(ROOK, QUEEN, Us))
- && !(bishop_attacks_bb(to, occ & ClearMaskBB[from]) & pos.pieces(BISHOP, QUEEN, Us)))
-
- // Set the mate threat move
- ei.mateThreat[Them] = make_move(from, to);
+ // We have a mate, unless the queen is pinned or there
+ // is an X-ray attack through the queen.
+ for (int i = 0; i < pos.piece_count(Them, QUEEN); i++)
+ {
+ from = pos.piece_list(Them, QUEEN, i);
+ if ( bit_is_set(pos.attacks_from<QUEEN>(from), to)
+ && !bit_is_set(pos.pinned_pieces(Them), from)
+ && !(rook_attacks_bb(to, occ & ClearMaskBB[from]) & pos.pieces(ROOK, QUEEN, Us))
+ && !(bishop_attacks_bb(to, occ & ClearMaskBB[from]) & pos.pieces(BISHOP, QUEEN, Us)))
+
+ // Set the mate threat move
+ ei.mateThreat[Them] = make_move(from, to);
+ }
}
}
}
}
}
- }
- // Analyse enemy's safe distance checks
- safe = ~(pos.pieces_of_color(Them) | ei.attacked_by(Us));
-
- b1 = pos.attacks_from<ROOK>(ksq) & safe;
- b2 = pos.attacks_from<BISHOP>(ksq) & safe;
-
- // Enemy rooks safe checks
- b = b1 & ei.attacked_by(Them, ROOK);
- if (b)
- attackUnits += RookCheckBonus * count_1s_max_15<HasPopCnt>(b);
-
- // Enemy bishops safe checks
- b = b2 & ei.attacked_by(Them, BISHOP);
- if (b)
- attackUnits += BishopCheckBonus * count_1s_max_15<HasPopCnt>(b);
-
- // Enemy queens safe checks
- b = (b1 | b2) & ei.attacked_by(Them, QUEEN);
- if (b)
- attackUnits += QueenCheckBonus * count_1s_max_15<HasPopCnt>(b);
-
- // Enemy knights safe checks
- b = pos.attacks_from<KNIGHT>(ksq) & ei.attacked_by(Them, KNIGHT) & safe;
- if (b)
- attackUnits += KnightCheckBonus * count_1s_max_15<HasPopCnt>(b);
-
- // Analyse discovered checks (only for non-pawns right now, consider
- // adding pawns later).
- b = pos.discovered_check_candidates(Them) & ~pos.pieces(PAWN);
- if (b)
- attackUnits += DiscoveredCheckBonus * count_1s_max_15<HasPopCnt>(b) * (sente ? 2 : 1);
-
- // Has a mate threat been found? We don't do anything here if the
- // side with the mating move is the side to move, because in that
- // case the mating side will get a huge bonus at the end of the main
- // evaluation function instead.
- if (ei.mateThreat[Them] != MOVE_NONE)
- attackUnits += MateThreatBonus;
-
- // Ensure that attackUnits is between 0 and 99, in order to avoid array
- // out of bounds errors.
- attackUnits = Min(99, Max(0, attackUnits));
-
- // Finally, extract the king danger score from the KingDangerTable[]
- // array and subtract the score from evaluation. Set also ei.kingDanger[]
- // value that will be used for pruning because this value can sometimes
- // be very big, and so capturing a single attacking piece can therefore
- // result in a score change far bigger than the value of the captured piece.
- ei.value -= Sign[Us] * KingDangerTable[Us][attackUnits];
- ei.kingDanger[Us] = mg_value(KingDangerTable[Us][attackUnits]);
+ // Analyse enemy's safe distance checks
+ safe = ~(pos.pieces_of_color(Them) | ei.attacked_by(Us));
+
+ b1 = pos.attacks_from<ROOK>(ksq) & safe;
+ b2 = pos.attacks_from<BISHOP>(ksq) & safe;
+
+ // Enemy rooks safe checks
+ b = b1 & ei.attacked_by(Them, ROOK);
+ if (b)
+ attackUnits += RookCheckBonus * count_1s_max_15<HasPopCnt>(b);
+
+ // Enemy bishops safe checks
+ b = b2 & ei.attacked_by(Them, BISHOP);
+ if (b)
+ attackUnits += BishopCheckBonus * count_1s_max_15<HasPopCnt>(b);
+
+ // Enemy queens safe checks
+ b = (b1 | b2) & ei.attacked_by(Them, QUEEN);
+ if (b)
+ attackUnits += QueenCheckBonus * count_1s_max_15<HasPopCnt>(b);
+
+ // Enemy knights safe checks
+ b = pos.attacks_from<KNIGHT>(ksq) & ei.attacked_by(Them, KNIGHT) & safe;
+ if (b)
+ attackUnits += KnightCheckBonus * count_1s_max_15<HasPopCnt>(b);
+
+ // Analyse discovered checks (only for non-pawns right now, consider
+ // adding pawns later).
+ b = pos.discovered_check_candidates(Them) & ~pos.pieces(PAWN);
+ if (b)
+ attackUnits += DiscoveredCheckBonus * count_1s_max_15<HasPopCnt>(b) * (sente ? 2 : 1);
+
+ // Has a mate threat been found? We don't do anything here if the
+ // side with the mating move is the side to move, because in that
+ // case the mating side will get a huge bonus at the end of the main
+ // evaluation function instead.
+ if (ei.mateThreat[Them] != MOVE_NONE)
+ attackUnits += MateThreatBonus;
+
+ // Ensure that attackUnits is between 0 and 99, in order to avoid array
+ // out of bounds errors.
+ attackUnits = Min(99, Max(0, attackUnits));
+
+ // Finally, extract the king danger score from the KingDangerTable[]
+ // array and subtract the score from evaluation. Set also ei.kingDanger[]
+ // value that will be used for pruning because this value can sometimes
+ // be very big, and so capturing a single attacking piece can therefore
+ // result in a score change far bigger than the value of the captured piece.
+ ei.value -= Sign[Us] * KingDangerTable[Us][attackUnits];
+ ei.kingDanger[Us] = mg_value(KingDangerTable[Us][attackUnits]);
}
}