X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fevaluate.cpp;h=d9c306e8891c8cf91e320aae85992829bce131b9;hp=e10618494cc1c87a1af02a64909be59af6c78b16;hb=f6981b1321357866e7aff688572e1d0e1fe57c08;hpb=a87a1005ad63c8076a79ea3b2648f87fea49cfc5 diff --git a/src/evaluate.cpp b/src/evaluate.cpp index e1061849..d9c306e8 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -111,7 +111,8 @@ namespace { 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 (can be also ALL_PIECES). + // attacked by a given color and piece type. Special "piece types" which are + // also calculated are QUEEN_DIAGONAL and ALL_PIECES. Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB]; // attackedBy2[color] are the squares attacked by 2 pieces of a given color, @@ -217,7 +218,6 @@ namespace { const Score RookOnPawn = S( 8, 24); const Score TrappedRook = S( 92, 0); const Score WeakQueen = S( 50, 10); - const Score OtherCheck = S( 10, 10); const Score CloseEnemies = S( 7, 0); const Score PawnlessFlank = S( 20, 80); const Score ThreatByHangingPawn = S( 71, 61); @@ -237,10 +237,10 @@ namespace { const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 78, 56, 45, 11 }; // Penalties for enemy's safe checks - const int QueenCheck = 780; - const int RookCheck = 880; - const int BishopCheck = 435; - const int KnightCheck = 790; + const int QueenSafeCheck = 780; + const int RookSafeCheck = 880; + const int BishopSafeCheck = 435; + const int KnightSafeCheck = 790; // Threshold for lazy and space evaluation const Value LazyThreshold = Value(1500); @@ -253,9 +253,9 @@ namespace { template template void Evaluation::initialize() { - const Color Them = (Us == WHITE ? BLACK : WHITE); - const Square Up = (Us == WHITE ? NORTH : SOUTH); - const Square Down = (Us == WHITE ? SOUTH : NORTH); + const Color Them = (Us == WHITE ? BLACK : WHITE); + const Direction Up = (Us == WHITE ? NORTH : SOUTH); + const Direction Down = (Us == WHITE ? SOUTH : NORTH); const Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB: Rank7BB | Rank6BB); // Find our pawns on the first two ranks, and those which are blocked @@ -342,12 +342,12 @@ namespace { // Bonus for outpost squares bb = OutpostRanks & ~pe->pawn_attacks_span(Them); if (bb & s) - score += Outpost[Pt == BISHOP][!!(attackedBy[Us][PAWN] & s)] * 2; + score += Outpost[Pt == BISHOP][bool(attackedBy[Us][PAWN] & s)] * 2; else { bb &= b & ~pos.pieces(Us); if (bb) - score += Outpost[Pt == BISHOP][!!(attackedBy[Us][PAWN] & bb)]; + score += Outpost[Pt == BISHOP][bool(attackedBy[Us][PAWN] & bb)]; } // Bonus when behind a pawn @@ -372,7 +372,7 @@ namespace { && pos.is_chess960() && (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1))) { - Square d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST); + Direction d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST); if (pos.piece_on(s + d) == make_piece(Us, PAWN)) score -= !pos.empty(s + d + pawn_push(Us)) ? TrappedBishopA1H1 * 4 : pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? TrappedBishopA1H1 * 2 @@ -388,7 +388,7 @@ namespace { // Bonus when on an open or semi-open file if (pe->semiopen_file(Us, file_of(s))) - score += RookOnFile[!!pe->semiopen_file(Them, file_of(s))]; + score += RookOnFile[bool(pe->semiopen_file(Them, file_of(s)))]; // Penalty when trapped by the king, even more if the king cannot castle else if (mob <= 3) @@ -422,14 +422,12 @@ namespace { template template Score Evaluation::evaluate_king() { - const Color Them = (Us == WHITE ? BLACK : WHITE); - const Square Up = (Us == WHITE ? NORTH : SOUTH); - const Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB - : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB); + const Color Them = (Us == WHITE ? BLACK : WHITE); + const Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB + : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB); const Square ksq = pos.square(Us); - Bitboard weak, b, b1, b2, safe, other; - int kingDanger; + Bitboard weak, b, b1, b2, safe, unsafeChecks; // King shelter and enemy pawns storm Score score = pe->king_safety(pos, ksq); @@ -442,57 +440,52 @@ namespace { & ~attackedBy2[Us] & (attackedBy[Us][KING] | attackedBy[Us][QUEEN] | ~attackedBy[Us][ALL_PIECES]); - // Initialize the 'kingDanger' variable, which will be transformed - // later into a king danger score. The initial value is based on the - // number and types of the enemy's attacking pieces, the number of - // attacked and weak squares around our king, the absence of queen and - // the quality of the pawn shelter (current 'score' value). - kingDanger = kingAttackersCount[Them] * kingAttackersWeight[Them] - + 102 * kingAdjacentZoneAttacksCount[Them] - + 191 * popcount(kingRing[Us] & weak) - + 143 * !!pos.pinned_pieces(Us) - - 848 * !pos.count(Them) - - 9 * mg_value(score) / 8 - + 40; + int kingDanger = unsafeChecks = 0; // Analyse the safe enemy's checks which are possible on next move safe = ~pos.pieces(Them); safe &= ~attackedBy[Us][ALL_PIECES] | (weak & attackedBy2[Them]); - b1 = pos.attacks_from< ROOK>(ksq); - b2 = pos.attacks_from(ksq); + b1 = attacks_bb(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)); + b2 = attacks_bb(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)); // Enemy queen safe checks if ((b1 | b2) & attackedBy[Them][QUEEN] & safe & ~attackedBy[Us][QUEEN]) - kingDanger += QueenCheck; + kingDanger += QueenSafeCheck; - // Some other potential checks are also analysed, even from squares - // currently occupied by the opponent own pieces, as long as the square - // is not attacked by our pawns, and is not occupied by a blocked pawn. - other = ~( attackedBy[Us][PAWN] - | (pos.pieces(Them, PAWN) & shift(pos.pieces(PAWN)))); + b1 &= attackedBy[Them][ROOK]; + b2 &= attackedBy[Them][BISHOP]; - // Enemy rooks safe and other checks - if (b1 & attackedBy[Them][ROOK] & safe) - kingDanger += RookCheck; + // Enemy rooks checks + if (b1 & safe) + kingDanger += RookSafeCheck; + else + unsafeChecks |= b1; - else if (b1 & attackedBy[Them][ROOK] & other) - score -= OtherCheck; + // Enemy bishops checks + if (b2 & safe) + kingDanger += BishopSafeCheck; + else + unsafeChecks |= b2; - // Enemy bishops safe and other checks - if (b2 & attackedBy[Them][BISHOP] & safe) - kingDanger += BishopCheck; - - else if (b2 & attackedBy[Them][BISHOP] & other) - score -= OtherCheck; - - // Enemy knights safe and other checks + // Enemy knights checks b = pos.attacks_from(ksq) & attackedBy[Them][KNIGHT]; if (b & safe) - kingDanger += KnightCheck; - - else if (b & other) - score -= OtherCheck; + kingDanger += KnightSafeCheck; + else + unsafeChecks |= b; + + // Unsafe or occupied checking squares will also be considered, as long as + // the square is in the attacker's mobility area. + unsafeChecks &= mobilityArea[Them]; + + kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them] + + 102 * kingAdjacentZoneAttacksCount[Them] + + 191 * popcount(kingRing[Us] & weak) + + 143 * popcount(pos.pinned_pieces(Us) | unsafeChecks) + - 848 * !pos.count(Them) + - 9 * mg_value(score) / 8 + + 40; // Transform the kingDanger units into a Score, and substract it from the evaluation if (kingDanger > 0) @@ -530,11 +523,11 @@ namespace { template template Score Evaluation::evaluate_threats() { - const Color Them = (Us == WHITE ? BLACK : WHITE); - const Square Up = (Us == WHITE ? NORTH : SOUTH); - const Square Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST); - const Square Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST); - const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB); + const Color Them = (Us == WHITE ? BLACK : WHITE); + const Direction Up = (Us == WHITE ? NORTH : SOUTH); + const Direction Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST); + const Direction Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST); + const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB); Bitboard b, weak, defended, stronglyProtected, safeThreats; Score score = SCORE_ZERO; @@ -636,8 +629,8 @@ namespace { template template Score Evaluation::evaluate_passed_pawns() { - const Color Them = (Us == WHITE ? BLACK : WHITE); - const Square Up = (Us == WHITE ? NORTH : SOUTH); + const Color Them = (Us == WHITE ? BLACK : WHITE); + const Direction Up = (Us == WHITE ? NORTH : SOUTH); Bitboard b, bb, squaresToQueen, defendedSquares, unsafeSquares; Score score = SCORE_ZERO; @@ -840,7 +833,7 @@ namespace { // Initialize score by reading the incrementally updated scores included in // the position object (material + piece square tables) and the material // imbalance. Score is computed internally from the white point of view. - Score score = pos.psq_score() + me->imbalance(); + Score score = pos.psq_score() + me->imbalance() + Eval::Contempt; // Probe the pawn hash table pe = Pawns::probe(pos); @@ -898,18 +891,19 @@ namespace { Trace::add(TOTAL, score); } - return (pos.side_to_move() == WHITE ? v : -v) + Eval::Tempo; // Side to move point of view + return pos.side_to_move() == WHITE ? v : -v; // Side to move point of view } } // namespace +Score Eval::Contempt = SCORE_ZERO; /// evaluate() is the evaluator for the outer world. It returns a static evaluation /// of the position from the point of view of the side to move. Value Eval::evaluate(const Position& pos) { - return Evaluation<>(pos).value(); + return Evaluation<>(pos).value() + Eval::Tempo; } /// trace() is like evaluate(), but instead of returning a value, it returns @@ -920,7 +914,7 @@ std::string Eval::trace(const Position& pos) { std::memset(scores, 0, sizeof(scores)); - Value v = Evaluation(pos).value(); + Value v = Evaluation(pos).value() + Eval::Tempo; v = pos.side_to_move() == WHITE ? v : -v; // White's point of view std::stringstream ss;