// 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;
+ constexpr int OtherSafeCheck = 600;
#define S(mg, eg) make_score(mg, eg)
Score Evaluation<T>::king() const {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
- constexpr Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
- : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
+ Rank r = relative_rank(Us, std::min(Rank((pos.max_rank() - 1) / 2 + 1), pos.max_rank()), pos.max_rank());
+ Bitboard Camp = AllSquares ^ forward_ranks_bb(Us, r);
+
+ if (!pos.count<KING>(Us) || !pos.checking_permitted())
+ return SCORE_ZERO;
const Square ksq = pos.square<KING>(Us);
-- Bitboard kingFlank, weak, b, b1, b2, safe, unsafeChecks;
++ Bitboard kingFlank, weak, b, b1, b2, safe, unsafeChecks, QueenCheck;
// King shelter and enemy pawns storm
Score score = pe->king_safety<Us>(pos);
safe = ~pos.pieces(Them);
safe &= ~attackedBy[Us][ALL_PIECES] | (weak & attackedBy2[Them]);
+ b1 = attacks_bb<ROOK >(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
+ b2 = attacks_bb<BISHOP>(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
+
- // Enemy rooks checks
- Bitboard RookCheck = b1
+ std::function <Bitboard (Color, PieceType)> get_attacks = [this](Color c, PieceType pt) {
+ return attackedBy[c][pt] | (pos.captures_to_hand() && pos.count_in_hand(c, pt) ? ~pos.pieces() : 0);
+ };
+ for (PieceType pt : pos.piece_types())
+ {
+ switch (pt)
+ {
+ case QUEEN:
- b = attacks_bb(Us, pt, ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)) & get_attacks(Them, pt) & safe & ~attackedBy[Us][QUEEN] & pos.board_bb();
- if (b)
++ // 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.
++ QueenCheck = (b1 | b2)
++ & get_attacks(Them, QUEEN)
+ & safe
- & attackedBy[Them][ROOK];
-
- if (RookCheck)
- kingDanger += RookSafeCheck;
- else
- 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;
-
- 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 & attackedBy[Them][BISHOP];
-
- // Enemy knights checks
- b = pos.attacks_from<KNIGHT>(ksq) & attackedBy[Them][KNIGHT];
++ & ~attackedBy[Us][QUEEN]
++ & ~(b1 & attackedBy[Them][ROOK]);
++
++ if (QueenCheck)
+ kingDanger += QueenSafeCheck;
+ break;
+ case ROOK:
+ case BISHOP:
+ case KNIGHT:
+ b = attacks_bb(Us, pt, ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)) & get_attacks(Them, pt) & pos.board_bb();
+ if (b & safe)
+ kingDanger += pt == ROOK ? RookSafeCheck
- : pt == BISHOP ? BishopSafeCheck
++ : pt == BISHOP ? BishopSafeCheck
+ : KnightSafeCheck;
+ else
+ unsafeChecks |= b;
+ break;
+ case PAWN:
+ if (pos.captures_to_hand() && pos.count_in_hand(Them, pt))
+ {
+ b = attacks_bb(Us, pt, ksq, pos.pieces()) & ~pos.pieces() & pos.board_bb();
+ if (b & safe)
+ kingDanger += OtherSafeCheck;
+ else
+ unsafeChecks |= b;
+ }
+ break;
+ case SHOGI_PAWN:
+ case KING:
+ break;
+ default:
+ b = attacks_bb(Us, pt, ksq, pos.pieces()) & get_attacks(Them, pt) & pos.board_bb();
+ if (b & safe)
+ kingDanger += OtherSafeCheck;
+ else
+ unsafeChecks |= b;
+ }
+ }
- if (b & safe)
- kingDanger += KnightSafeCheck;
- else
- unsafeChecks |= b;
+ if (pos.max_check_count())
+ kingDanger *= 2;
// Unsafe or occupied checking squares will also be considered, as long as
// the square is in the attacker's mobility area.