X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fevaluate.cpp;h=6f2dd69ba33d7a5986fe99be7d70493d29023c76;hp=8b4a27bc112b3cad6d9997b3ea11209a5445edce;hb=4006f2c9132db034a27a94be33070d6aaab75b24;hpb=e9966d9a8ec371477f49bfa0eb69fa756e078fda diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 8b4a27bc..6f2dd69b 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -80,11 +80,11 @@ namespace { // KingAttackWeights[PieceType] contains king attack weights by piece type constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 81, 52, 44, 10 }; - // Penalties for enemy's safe checks - constexpr int QueenSafeCheck = 772; - constexpr int RookSafeCheck = 1084; - constexpr int BishopSafeCheck = 645; - constexpr int KnightSafeCheck = 792; + // 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] = { + {}, {}, {792, 1283}, {645, 967}, {1084, 1897}, {772, 1119} + }; #define S(mg, eg) make_score(mg, eg) @@ -106,6 +106,18 @@ namespace { S(110,182), S(114,182), S(114,192), S(116,219) } }; + // KingProtector[knight/bishop] contains penalty for each distance unit to own king + constexpr Score KingProtector[] = { S(8, 9), S(6, 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(56, 36), S(30, 23) }; + + // PassedRank[Rank] contains a bonus according to the rank of a passed pawn + constexpr Score PassedRank[RANK_NB] = { + S(0, 0), S(10, 28), S(17, 33), S(15, 41), S(62, 72), S(168, 177), S(276, 260) + }; + // RookOnFile[semiopen/open] contains bonuses for each rook when there is // no (friendly) pawn on the rook file. constexpr Score RookOnFile[] = { S(19, 7), S(48, 29) }; @@ -121,29 +133,20 @@ namespace { S(0, 0), S(3, 46), S(37, 68), S(42, 60), S(0, 38), S(58, 41) }; - // PassedRank[Rank] contains a bonus according to the rank of a passed pawn - constexpr Score PassedRank[RANK_NB] = { - S(0, 0), S(10, 28), S(17, 33), S(15, 41), S(62, 72), S(168, 177), S(276, 260) - }; - // Assorted bonuses and penalties - constexpr Score BishopPawns = S( 3, 7); constexpr Score BishopOnKingRing = S( 24, 0); + constexpr Score BishopPawns = S( 3, 7); constexpr Score BishopXRayPawns = S( 4, 5); constexpr Score CorneredBishop = S( 50, 50); constexpr Score FlankAttacks = S( 8, 0); constexpr Score Hanging = S( 69, 36); - constexpr Score BishopKingProtector = S( 6, 9); - constexpr Score KnightKingProtector = S( 8, 9); constexpr Score KnightOnQueen = S( 16, 11); constexpr Score LongDiagonalBishop = S( 45, 0); constexpr Score MinorBehindPawn = S( 18, 3); - constexpr Score KnightOutpost = S( 56, 36); - constexpr Score BishopOutpost = S( 30, 23); - constexpr Score ReachableOutpost = S( 31, 22); constexpr Score PassedFile = S( 11, 8); constexpr Score PawnlessFlank = S( 17, 95); constexpr Score QueenInfiltration = S( -2, 14); + constexpr Score ReachableOutpost = S( 31, 22); constexpr Score RestrictedPiece = S( 7, 7); constexpr Score RookOnKingRing = S( 16, 0); constexpr Score RookOnQueenFile = S( 6, 11); @@ -152,8 +155,9 @@ namespace { constexpr Score ThreatByPawnPush = S( 48, 39); constexpr Score ThreatBySafePawn = S(173, 94); constexpr Score TrappedRook = S( 55, 13); - constexpr Score WeakQueen = S( 56, 15); constexpr Score WeakQueenProtection = S( 14, 0); + constexpr Score WeakQueen = S( 56, 15); + #undef S @@ -216,6 +220,7 @@ namespace { // 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 template void Evaluation::initialize() { @@ -255,6 +260,7 @@ namespace { // Evaluation::pieces() scores pieces of a given color and type + template template Score Evaluation::pieces() { @@ -305,7 +311,7 @@ namespace { // Bonus if piece is on an outpost square or can reach one bb = OutpostRanks & attackedBy[Us][PAWN] & ~pe->pawn_attacks_span(Them); if (bb & s) - score += (Pt == KNIGHT) ? KnightOutpost : BishopOutpost; + score += Outpost[Pt == BISHOP]; else if (Pt == KNIGHT && bb & b & ~pos.pieces(Us)) score += ReachableOutpost; @@ -314,8 +320,7 @@ namespace { score += MinorBehindPawn; // Penalty if the piece is far from the king - score -= (Pt == KNIGHT ? KnightKingProtector - : BishopKingProtector) * distance(pos.square(Us), s); + score -= KingProtector[Pt == BISHOP] * distance(pos.square(Us), s); if (Pt == BISHOP) { @@ -377,7 +382,7 @@ namespace { // Bonus for queen on weak square in enemy camp if (relative_rank(Us, s) > RANK_4 && (~pe->pawn_attacks_span(Them) & s)) - score += QueenInfiltration; + score += QueenInfiltration; } } if (T) @@ -388,6 +393,7 @@ namespace { // Evaluation::king() assigns bonuses and penalties to a king of a given color + template template Score Evaluation::king() const { @@ -416,41 +422,33 @@ namespace { b2 = attacks_bb(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)); // Enemy rooks checks - rookChecks = b1 & safe & attackedBy[Them][ROOK]; + rookChecks = b1 & attackedBy[Them][ROOK] & safe; if (rookChecks) - kingDanger += more_than_one(rookChecks) ? RookSafeCheck * 175/100 - : RookSafeCheck; + kingDanger += SafeCheck[ROOK][more_than_one(rookChecks)]; 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. - queenChecks = (b1 | b2) - & attackedBy[Them][QUEEN] - & safe - & ~attackedBy[Us][QUEEN] - & ~rookChecks; + // Enemy queen safe checks: count them only if the checks are from squares from + // which opponent cannot give a rook check, because rook checks are more valuable. + queenChecks = (b1 | b2) & attackedBy[Them][QUEEN] & safe + & ~(attackedBy[Us][QUEEN] | rookChecks); if (queenChecks) - kingDanger += more_than_one(queenChecks) ? QueenSafeCheck * 145/100 - : 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. - bishopChecks = b2 - & attackedBy[Them][BISHOP] - & safe + kingDanger += SafeCheck[QUEEN][more_than_one(queenChecks)]; + + // Enemy bishops checks: count them only if they are from squares from which + // opponent cannot give a queen check, because queen checks are more valuable. + bishopChecks = b2 & attackedBy[Them][BISHOP] & safe & ~queenChecks; if (bishopChecks) - kingDanger += more_than_one(bishopChecks) ? BishopSafeCheck * 3/2 - : BishopSafeCheck; + kingDanger += SafeCheck[BISHOP][more_than_one(bishopChecks)]; + else unsafeChecks |= b2 & attackedBy[Them][BISHOP]; // Enemy knights checks knightChecks = attacks_bb(ksq) & attackedBy[Them][KNIGHT]; if (knightChecks & safe) - kingDanger += more_than_one(knightChecks & safe) ? KnightSafeCheck * 162/100 - : KnightSafeCheck; + kingDanger += SafeCheck[KNIGHT][more_than_one(knightChecks & safe)]; else unsafeChecks |= knightChecks; @@ -460,7 +458,7 @@ namespace { b2 = b1 & attackedBy2[Them]; b3 = attackedBy[Us][ALL_PIECES] & KingFlank[file_of(ksq)] & Camp; - int kingFlankAttack = popcount(b1) + popcount(b2); + int kingFlankAttack = popcount(b1) + popcount(b2); int kingFlankDefense = popcount(b3); kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them] @@ -496,6 +494,7 @@ namespace { // Evaluation::threats() assigns bonuses according to the types of the // attacking and the attacked pieces. + template template Score Evaluation::threats() const { @@ -720,9 +719,9 @@ namespace { } - // Evaluation::winnable() adjusts the mg and eg score components based on the - // known attacking/defending status of the players. - // A single value is derived from the mg and eg values and returned. + // Evaluation::winnable() adjusts the midgame and endgame score components, based on + // the known attacking/defending status of the players. The final value is derived + // by interpolation from the midgame and endgame values. template Value Evaluation::winnable(Score score) const { @@ -736,8 +735,8 @@ namespace { bool almostUnwinnable = outflanking < 0 && !pawnsOnBothFlanks; - bool infiltration = rank_of(pos.square(WHITE)) > RANK_4 - || rank_of(pos.square(BLACK)) < RANK_5; + bool infiltration = rank_of(pos.square(WHITE)) > RANK_4 + || rank_of(pos.square(BLACK)) < RANK_5; // Compute the initiative bonus for the attacking side int complexity = 9 * pe->passed_count() @@ -762,11 +761,10 @@ namespace { eg += v; // Compute the scale factor for the winning side - Color strongSide = eg > VALUE_DRAW ? WHITE : BLACK; int sf = me->scale_factor(pos, strongSide); - // If scale is not already specific, scale down the endgame via general heuristics + // If scale factor is not already specific, scale down via general heuristics if (sf == SCALE_FACTOR_NORMAL) { if (pos.opposite_bishops()) @@ -777,6 +775,15 @@ namespace { else sf = 22 + 3 * pos.count(strongSide); } + else if ( pos.non_pawn_material(WHITE) == RookValueMg + && pos.non_pawn_material(BLACK) == RookValueMg + && pos.count(strongSide) - pos.count(~strongSide) <= 1 + && bool(KingSide & pos.pieces(strongSide, PAWN)) != bool(QueenSide & pos.pieces(strongSide, PAWN)) + && (attackedBy[~strongSide][KING] & pos.pieces(~strongSide, PAWN))) + sf = 36; + else if (pos.count() == 1) + sf = 37 + 3 * (pos.count(WHITE) == 1 ? pos.count(BLACK) + pos.count(BLACK) + : pos.count(WHITE) + pos.count(WHITE)); else sf = std::min(sf, 36 + 7 * pos.count(strongSide)); } @@ -828,12 +835,11 @@ namespace { return pos.side_to_move() == WHITE ? v : -v; // Main evaluation begins here - initialize(); initialize(); // Pieces evaluated first (also populates attackedBy, attackedBy2). - // Note that the order of evaluation of the terms is left unspecified + // Note that the order of evaluation of the terms is left unspecified. score += pieces() - pieces() + pieces() - pieces() + pieces() - pieces()