-using namespace Trace;
-
-namespace {
-
- // Threshold for lazy and space evaluation
- constexpr Value LazyThreshold1 = Value(3631);
- constexpr Value LazyThreshold2 = Value(2084);
- constexpr Value SpaceThreshold = Value(11551);
-
- // KingAttackWeights[PieceType] contains king attack weights by piece type
- constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 81, 52, 44, 10 };
-
- // SafeCheck[PieceType][single/multiple] contains safe check bonus by piece type,
- // higher if multiple safe checks are possible for that piece type.
- constexpr int SafeCheck[][2] = {
- {}, {}, {803, 1292}, {639, 974}, {1087, 1878}, {759, 1132}
- };
-
-#define S(mg, eg) make_score(mg, eg)
-
- // MobilityBonus[PieceType-2][attacked] contains bonuses for middle and end game,
- // indexed by piece type and number of attacked squares in the mobility area.
- constexpr Score MobilityBonus[][32] = {
- { S(-62,-79), S(-53,-57), S(-12,-31), S( -3,-17), S( 3, 7), S( 12, 13), // Knight
- S( 21, 16), S( 28, 21), S( 37, 26) },
- { S(-47,-59), S(-20,-25), S( 14, -8), S( 29, 12), S( 39, 21), S( 53, 40), // Bishop
- S( 53, 56), S( 60, 58), S( 62, 65), S( 69, 72), S( 78, 78), S( 83, 87),
- S( 91, 88), S( 96, 98) },
- { S(-60,-82), S(-24,-15), S( 0, 17) ,S( 3, 43), S( 4, 72), S( 14,100), // Rook
- S( 20,102), S( 30,122), S( 41,133), S(41 ,139), S( 41,153), S( 45,160),
- S( 57,165), S( 58,170), S( 67,175) },
- { S(-29,-49), S(-16,-29), S( -8, -8), S( -8, 17), S( 18, 39), S( 25, 54), // Queen
- S( 23, 59), S( 37, 73), S( 41, 76), S( 54, 95), S( 65, 95) ,S( 68,101),
- S( 69,124), S( 70,128), S( 70,132), S( 70,133) ,S( 71,136), S( 72,140),
- S( 74,147), S( 76,149), S( 90,153), S(104,169), S(105,171), S(106,171),
- S(112,178), S(114,185), S(114,187), S(119,221) }
- };
-
- // BishopPawns[distance from edge] contains a file-dependent penalty for pawns on
- // squares of the same color as our bishop.
- constexpr Score BishopPawns[int(FILE_NB) / 2] = {
- S(3, 8), S(3, 9), S(2, 7), S(3, 7)
- };
-
- // KingProtector[knight/bishop] contains penalty for each distance unit to own king
- constexpr Score KingProtector[] = { S(9, 9), S(7, 9) };
-
- // Outpost[knight/bishop] contains bonuses for each knight or bishop occupying a
- // pawn protected square on rank 4 to 6 which is also safe from a pawn attack.
- constexpr Score Outpost[] = { S(54, 34), S(31, 25) };
-
- // PassedRank[Rank] contains a bonus according to the rank of a passed pawn
- constexpr Score PassedRank[RANK_NB] = {
- S(0, 0), S(2, 38), S(15, 36), S(22, 50), S(64, 81), S(166, 184), S(284, 269)
- };
-
- constexpr Score RookOnClosedFile = S(10, 5);
- constexpr Score RookOnOpenFile[] = { S(18, 8), S(49, 26) };
-
- // ThreatByMinor/ByRook[attacked PieceType] contains bonuses according to
- // which piece type attacks which one. Attacks on lesser pieces which are
- // pawn-defended are not considered.
- constexpr Score ThreatByMinor[PIECE_TYPE_NB] = {
- S(0, 0), S(6, 37), S(64, 50), S(82, 57), S(103, 130), S(81, 163)
- };
-
- constexpr Score ThreatByRook[PIECE_TYPE_NB] = {
- S(0, 0), S(3, 44), S(36, 71), S(44, 59), S(0, 39), S(60, 39)
- };
-
- constexpr Value CorneredBishop = Value(50);
-
- // Assorted bonuses and penalties
- constexpr Score UncontestedOutpost = S( 0, 10);
- constexpr Score BishopOnKingRing = S( 24, 0);
- constexpr Score BishopXRayPawns = S( 4, 5);
- constexpr Score FlankAttacks = S( 8, 0);
- constexpr Score Hanging = S( 72, 40);
- constexpr Score KnightOnQueen = S( 16, 11);
- constexpr Score LongDiagonalBishop = S( 45, 0);
- constexpr Score MinorBehindPawn = S( 18, 3);
- constexpr Score PassedFile = S( 13, 8);
- constexpr Score PawnlessFlank = S( 19, 97);
- constexpr Score ReachableOutpost = S( 33, 19);
- constexpr Score RestrictedPiece = S( 6, 7);
- constexpr Score RookOnKingRing = S( 16, 0);
- constexpr Score SliderOnQueen = S( 62, 21);
- constexpr Score ThreatByKing = S( 24, 87);
- constexpr Score ThreatByPawnPush = S( 48, 39);
- constexpr Score ThreatBySafePawn = S(167, 99);
- constexpr Score TrappedRook = S( 55, 13);
- constexpr Score WeakQueenProtection = S( 14, 0);
- constexpr Score WeakQueen = S( 57, 19);
-
-
-#undef S
-
- // Evaluation class computes and stores attacks tables and other working data
- template<Tracing T>
- class Evaluation {
-
- public:
- Evaluation() = delete;
- explicit Evaluation(const Position& p) : pos(p) {}
- Evaluation& operator=(const Evaluation&) = delete;
- Value value();
-
- private:
- template<Color Us> void initialize();
- template<Color Us, PieceType Pt> Score pieces();
- template<Color Us> Score king() const;
- template<Color Us> Score threats() const;
- template<Color Us> Score passed() const;
- template<Color Us> Score space() const;
- Value winnable(Score score) const;
-
- const Position& pos;
- Material::Entry* me;
- Pawns::Entry* pe;
- Bitboard mobilityArea[COLOR_NB];
- Score mobility[COLOR_NB] = { SCORE_ZERO, SCORE_ZERO };
-
- // attackedBy[color][piece type] is a bitboard representing all squares
- // attacked by a given color and piece type. Special "piece types" which
- // is also calculated is ALL_PIECES.
- Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB];
-
- // attackedBy2[color] are the squares attacked by at least 2 units of a given
- // color, including x-rays. But diagonal x-rays through pawns are not computed.
- Bitboard attackedBy2[COLOR_NB];
-
- // kingRing[color] are the squares adjacent to the king plus some other
- // very near squares, depending on king position.
- Bitboard kingRing[COLOR_NB];
-
- // kingAttackersCount[color] is the number of pieces of the given color
- // which attack a square in the kingRing of the enemy king.
- int kingAttackersCount[COLOR_NB];
-
- // kingAttackersWeight[color] is the sum of the "weights" of the pieces of
- // the given color which attack a square in the kingRing of the enemy king.
- // The weights of the individual piece types are given by the elements in
- // the KingAttackWeights array.
- int kingAttackersWeight[COLOR_NB];
-
- // kingAttacksCount[color] is the number of attacks by the given color to
- // squares directly adjacent to the enemy king. Pieces which attack more
- // than one square are counted multiple times. For instance, if there is
- // a white knight on g5 and black's king is on g8, this white knight adds 2
- // to kingAttacksCount[WHITE].
- int kingAttacksCount[COLOR_NB];
- };
-
-
- // Evaluation::initialize() computes king and pawn attacks, and the king ring
- // bitboard for a given color. This is done at the beginning of the evaluation.
-
- template<Tracing T> template<Color Us>
- void Evaluation<T>::initialize() {
-
- constexpr Color Them = ~Us;
- constexpr Direction Up = pawn_push(Us);
- constexpr Direction Down = -Up;
- constexpr Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB : Rank7BB | Rank6BB);
-
- const Square ksq = pos.square<KING>(Us);
-
- Bitboard dblAttackByPawn = pawn_double_attacks_bb<Us>(pos.pieces(Us, PAWN));
-
- // Find our pawns that are blocked or on the first two ranks
- Bitboard b = pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | LowRanks);
-
- // Squares occupied by those pawns, by our king or queen, by blockers to attacks on our king
- // or controlled by enemy pawns are excluded from the mobility area.
- mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pos.blockers_for_king(Us) | pe->pawn_attacks(Them));
-
- // Initialize attackedBy[] for king and pawns
- attackedBy[Us][KING] = attacks_bb<KING>(ksq);
- attackedBy[Us][PAWN] = pe->pawn_attacks(Us);
- attackedBy[Us][ALL_PIECES] = attackedBy[Us][KING] | attackedBy[Us][PAWN];
- attackedBy2[Us] = dblAttackByPawn | (attackedBy[Us][KING] & attackedBy[Us][PAWN]);
-
- // Init our king safety tables
- Square s = make_square(std::clamp(file_of(ksq), FILE_B, FILE_G),
- std::clamp(rank_of(ksq), RANK_2, RANK_7));
- kingRing[Us] = attacks_bb<KING>(s) | s;
-
- kingAttackersCount[Them] = popcount(kingRing[Us] & pe->pawn_attacks(Them));
- kingAttacksCount[Them] = kingAttackersWeight[Them] = 0;
-
- // Remove from kingRing[] the squares defended by two pawns
- kingRing[Us] &= ~dblAttackByPawn;
- }
-
-
- // Evaluation::pieces() scores pieces of a given color and type