X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fevaluate.cpp;h=53a54006a7a6cf1afabd0d8a9989c3a7b0b5131b;hp=8a21b0bb5b241685995a17a9cb913e516c70e694;hb=800031c94c655e64e436846911e599de6eb35a72;hpb=7a613689710939671b8af8d5fe035000573b768a diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 8a21b0bb..53a54006 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -2,7 +2,7 @@ Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad - Copyright (C) 2015-2018 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad + Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -127,7 +127,7 @@ namespace { // RookOnFile[semiopen/open] contains bonuses for each rook when there is // no (friendly) pawn on the rook file. - constexpr Score RookOnFile[] = { S(20, 7), S(45, 20) }; + constexpr Score RookOnFile[] = { S(18, 7), S(44, 20) }; // ThreatByMinor/ByRook[attacked PieceType] contains bonuses according to // which piece type attacks which one. Attacks on lesser pieces which are @@ -151,29 +151,26 @@ namespace { S(-30,-14), S(-9, -8), S( 0, 9), S( -1, 7) }; - // PassedDanger[Rank] contains a term to weight the passed score - constexpr int PassedDanger[RANK_NB] = { 0, 0, 0, 3, 7, 11, 20 }; - // Assorted bonuses and penalties constexpr Score BishopPawns = S( 3, 7); - constexpr Score CloseEnemies = S( 6, 0); + constexpr Score CloseEnemies = S( 8, 0); constexpr Score CorneredBishop = S( 50, 50); - constexpr Score Hanging = S( 57, 32); - constexpr Score KingProtector = S( 6, 6); - constexpr Score KnightOnQueen = S( 21, 11); - constexpr Score LongDiagonalBishop = S( 46, 0); - constexpr Score MinorBehindPawn = S( 16, 0); - constexpr Score Overload = S( 13, 6); - constexpr Score PawnlessFlank = S( 19, 84); - constexpr Score RookOnPawn = S( 10, 30); - constexpr Score SliderOnQueen = S( 42, 21); - constexpr Score ThreatByKing = S( 23, 76); - constexpr Score ThreatByPawnPush = S( 45, 40); - constexpr Score ThreatByRank = S( 16, 3); - constexpr Score ThreatBySafePawn = S(173,102); - constexpr Score TrappedRook = S( 92, 0); - constexpr Score WeakQueen = S( 50, 10); - constexpr Score WeakUnopposedPawn = S( 5, 29); + constexpr Score Hanging = S( 69, 36); + constexpr Score KingProtector = S( 7, 8); + constexpr Score KnightOnQueen = S( 16, 12); + constexpr Score LongDiagonalBishop = S( 45, 0); + constexpr Score MinorBehindPawn = S( 18, 3); + constexpr Score PawnlessFlank = S( 17, 95); + constexpr Score RestrictedPiece = S( 7, 7); + constexpr Score RookOnPawn = S( 10, 32); + constexpr Score SliderOnQueen = S( 59, 18); + constexpr Score ThreatByKing = S( 24, 89); + constexpr Score ThreatByPawnPush = S( 48, 39); + constexpr Score ThreatByRank = S( 13, 0); + constexpr Score ThreatBySafePawn = S(173, 94); + constexpr Score TrappedRook = S( 96, 4); + constexpr Score WeakQueen = S( 49, 15); + constexpr Score WeakUnopposedPawn = S( 12, 23); #undef S @@ -261,24 +258,20 @@ namespace { attackedBy[Us][ALL_PIECES] = attackedBy[Us][KING] | attackedBy[Us][PAWN]; attackedBy2[Us] = attackedBy[Us][KING] & attackedBy[Us][PAWN]; - // Init our king safety tables only if we are going to use them - if (pos.non_pawn_material(Them) >= RookValueMg + KnightValueMg) - { - kingRing[Us] = attackedBy[Us][KING]; - if (relative_rank(Us, pos.square(Us)) == RANK_1) - kingRing[Us] |= shift(kingRing[Us]); + // Init our king safety tables + kingRing[Us] = attackedBy[Us][KING]; + if (relative_rank(Us, pos.square(Us)) == RANK_1) + kingRing[Us] |= shift(kingRing[Us]); - if (file_of(pos.square(Us)) == FILE_H) - kingRing[Us] |= shift(kingRing[Us]); + if (file_of(pos.square(Us)) == FILE_H) + kingRing[Us] |= shift(kingRing[Us]); - else if (file_of(pos.square(Us)) == FILE_A) - kingRing[Us] |= shift(kingRing[Us]); + else if (file_of(pos.square(Us)) == FILE_A) + kingRing[Us] |= shift(kingRing[Us]); - kingAttackersCount[Them] = popcount(kingRing[Us] & pe->pawn_attacks(Them)); - kingAttacksCount[Them] = kingAttackersWeight[Them] = 0; - } - else - kingRing[Us] = kingAttackersCount[Them] = 0; + kingAttackersCount[Them] = popcount(kingRing[Us] & pe->pawn_attacks(Them)); + kingRing[Us] &= ~double_pawn_attacks_bb(pos.pieces(Us, PAWN)); + kingAttacksCount[Them] = kingAttackersWeight[Them] = 0; } @@ -384,7 +377,7 @@ namespace { { File kf = file_of(pos.square(Us)); if ((kf < FILE_E) == (file_of(s) < kf)) - score -= (TrappedRook - make_score(mob * 22, 0)) * (1 + !pos.can_castle(Us)); + score -= (TrappedRook - make_score(mob * 22, 0)) * (1 + !pos.castling_rights(Us)); } } @@ -415,81 +408,75 @@ namespace { Bitboard kingFlank, weak, b, b1, b2, safe, unsafeChecks; // King shelter and enemy pawns storm - Score score = pe->king_safety(pos, ksq); + Score score = pe->king_safety(pos); // Find the squares that opponent attacks in our king flank, and the squares - // which are attacked twice in that flank but not defended by our pawns. + // which are attacked twice in that flank. kingFlank = KingFlank[file_of(ksq)]; b1 = attackedBy[Them][ALL_PIECES] & kingFlank & Camp; - b2 = b1 & attackedBy2[Them] & ~attackedBy[Us][PAWN]; + b2 = b1 & attackedBy2[Them]; int tropism = popcount(b1) + popcount(b2); // Main king safety evaluation - if (kingAttackersCount[Them] > 1 - pos.count(Them)) - { - int kingDanger = 0; - unsafeChecks = 0; + int kingDanger = 0; + unsafeChecks = 0; - // Attacked squares defended at most once by our queen or king - weak = attackedBy[Them][ALL_PIECES] - & ~attackedBy2[Us] - & (~attackedBy[Us][ALL_PIECES] | attackedBy[Us][KING] | attackedBy[Us][QUEEN]); + // Attacked squares defended at most once by our queen or king + weak = attackedBy[Them][ALL_PIECES] + & ~attackedBy2[Us] + & (~attackedBy[Us][ALL_PIECES] | attackedBy[Us][KING] | attackedBy[Us][QUEEN]); - // Analyse the safe enemy's checks which are possible on next move - safe = ~pos.pieces(Them); - safe &= ~attackedBy[Us][ALL_PIECES] | (weak & attackedBy2[Them]); + // 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 = attacks_bb(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)); - b2 = attacks_bb(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)); + 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 += QueenSafeCheck; + // Enemy queen safe checks + if ((b1 | b2) & attackedBy[Them][QUEEN] & safe & ~attackedBy[Us][QUEEN]) + kingDanger += QueenSafeCheck; - b1 &= attackedBy[Them][ROOK]; - b2 &= attackedBy[Them][BISHOP]; + b1 &= attackedBy[Them][ROOK]; + b2 &= attackedBy[Them][BISHOP]; - // Enemy rooks checks - if (b1 & safe) - kingDanger += RookSafeCheck; - else - unsafeChecks |= b1; + // Enemy rooks checks + if (b1 & safe) + kingDanger += RookSafeCheck; + else + unsafeChecks |= b1; - // Enemy bishops checks - if (b2 & safe) - kingDanger += BishopSafeCheck; - else - unsafeChecks |= b2; + // Enemy bishops checks + if (b2 & safe) + kingDanger += BishopSafeCheck; + else + unsafeChecks |= b2; - // Enemy knights checks - b = pos.attacks_from(ksq) & attackedBy[Them][KNIGHT]; - if (b & safe) - 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] - + 69 * kingAttacksCount[Them] - + 185 * popcount(kingRing[Us] & weak) - + 150 * popcount(pos.blockers_for_king(Us) | unsafeChecks) - + 4 * tropism - - 873 * !pos.count(Them) - - 6 * mg_value(score) / 8 - - 30; - - // Transform the kingDanger units into a Score, and subtract it from the evaluation - if (kingDanger > 0) - { - int mobilityDanger = mg_value(mobility[Them] - mobility[Us]); - kingDanger = std::max(0, kingDanger + mobilityDanger); - score -= make_score(kingDanger * kingDanger / 4096, kingDanger / 16); - } - } + // Enemy knights checks + b = pos.attacks_from(ksq) & attackedBy[Them][KNIGHT]; + if (b & safe) + 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] + + 69 * kingAttacksCount[Them] + + 185 * popcount(kingRing[Us] & weak) + + 150 * popcount(pos.blockers_for_king(Us) | unsafeChecks) + + tropism * tropism / 4 + - 873 * !pos.count(Them) + - 6 * mg_value(score) / 8 + + mg_value(mobility[Them] - mobility[Us]) + - 30; + + // Transform the kingDanger units into a Score, and subtract it from the evaluation + if (kingDanger > 0) + score -= make_score(kingDanger * kingDanger / 4096, kingDanger / 16); // Penalty when our king is on a pawnless flank if (!(pos.pieces(PAWN) & kingFlank)) @@ -514,11 +501,11 @@ namespace { constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH); constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB); - Bitboard b, weak, defended, nonPawnEnemies, stronglyProtected, safe; + Bitboard b, weak, defended, nonPawnEnemies, stronglyProtected, safe, restricted; Score score = SCORE_ZERO; // Non-pawn enemies - nonPawnEnemies = pos.pieces(Them) ^ pos.pieces(Them, PAWN); + nonPawnEnemies = pos.pieces(Them) & ~pos.pieces(Them, PAWN); // Squares strongly protected by the enemy, either because they defend the // square with a pawn, or because they defend the square twice and we don't. @@ -558,12 +545,17 @@ namespace { if (weak & attackedBy[Us][KING]) score += ThreatByKing; - score += Hanging * popcount(weak & ~attackedBy[Them][ALL_PIECES]); - - b = weak & nonPawnEnemies & attackedBy[Them][ALL_PIECES]; - score += Overload * popcount(b); + b = ~attackedBy[Them][ALL_PIECES] + | (nonPawnEnemies & attackedBy2[Us]); + score += Hanging * popcount(weak & b); } + // Bonus for restricting their piece moves + restricted = attackedBy[Them][ALL_PIECES] + & ~stronglyProtected + & attackedBy[Us][ALL_PIECES]; + score += RestrictedPiece * popcount(restricted); + // Bonus for enemy unopposed weak pawns if (pos.pieces(Us, ROOK, QUEEN)) score += WeakUnopposedPawn * pe->weak_unopposed(Them); @@ -632,12 +624,12 @@ namespace { assert(!(pos.pieces(Them, PAWN) & forward_file_bb(Us, s + Up))); int r = relative_rank(Us, s); - int w = PassedDanger[r]; Score bonus = PassedRank[r]; - if (w) + if (r > RANK_3) { + int w = (r-2) * (r-2) + 2; Square blockSq = s + Up; // Adjust bonus based on the king's proximity @@ -678,7 +670,7 @@ namespace { bonus += make_score(k * w, k * w); } - } // w != 0 + } // rank > RANK_3 // Scale down bonus for candidate passers which need more than one // pawn push to become passed, or have a pawn in front of them.