+ // Do not include in mobility squares protected by enemy pawns or occupied by our pieces
+ const Bitboard no_mob_area = ~(ei.attackedBy[Them][PAWN] | pos.pieces_of_color(Us));
+
+ evaluate_pieces<KNIGHT, Us, HasPopCnt>(pos, ei, no_mob_area);
+ evaluate_pieces<BISHOP, Us, HasPopCnt>(pos, ei, no_mob_area);
+ evaluate_pieces<ROOK, Us, HasPopCnt>(pos, ei, no_mob_area);
+ evaluate_pieces<QUEEN, Us, HasPopCnt>(pos, ei, no_mob_area);
+
+ // Sum up all attacked squares
+ ei.attackedBy[Us][0] = ei.attackedBy[Us][PAWN] | ei.attackedBy[Us][KNIGHT]
+ | ei.attackedBy[Us][BISHOP] | ei.attackedBy[Us][ROOK]
+ | ei.attackedBy[Us][QUEEN] | ei.attackedBy[Us][KING];
+ }
+
+
+ // evaluate_king<>() assigns bonuses and penalties to a king of a given color
+
+ template<Color Us, bool HasPopCnt>
+ void evaluate_king(const Position& pos, EvalInfo& ei) {
+
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+
+ Bitboard undefended, b, b1, b2, safe;
+ bool sente;
+ int attackUnits, shelter = 0;
+ const Square ksq = pos.king_square(Us);
+
+ // King shelter
+ if (relative_rank(Us, ksq) <= RANK_4)
+ {
+ shelter = ei.pi->get_king_shelter(pos, Us, ksq);
+ ei.value += Sign[Us] * make_score(shelter, 0);
+ }
+
+ // King safety. This is quite complicated, and is almost certainly far
+ // from optimally tuned.
+ if ( pos.piece_count(Them, QUEEN) >= 1
+ && ei.kingAttackersCount[Them] >= 2
+ && 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 / 32;
+
+ // Analyse enemy's safe queen contact checks. First find undefended
+ // squares around the king attacked by enemy queen...
+ b = undefended & ei.attacked_by(Them, QUEEN) & ~pos.pieces_of_color(Them);
+ if (b)
+ {
+ // ...then remove squares not supported by another enemy piece
+ b &= ( ei.attacked_by(Them, PAWN) | ei.attacked_by(Them, KNIGHT)
+ | ei.attacked_by(Them, BISHOP) | ei.attacked_by(Them, ROOK));
+ if (b)
+ attackUnits += QueenContactCheckBonus * count_1s_max_15<HasPopCnt>(b) * (sente ? 2 : 1);
+ }