From: Alain SAVARD Date: Sun, 10 Dec 2017 15:13:28 +0000 (-0500) Subject: Simplify other checks #1334 X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=020dd69a3512d01c7f189b1aea64fa75c7e1b7cd Simplify other checks #1334 Simplify the other check penalty computation. Compared to current master, a) it uses a 143 kingDanger penalty instead of S(10, 10) for the "otherCheck" (credits to ElbertoOne for finding a suitable kingDanger range to replace the score and to Guardian for showing this could also be a neutral change at LTC). This makes our king safety model more consistent and simpler. b) it might also score more than one "otherCheck" penalty for a given piece type instead of just one c) it might score many pinned penalties instead of just one. d) It also remove 3 conditionals and uses simpler expressions. So it was tested as a SPRT[-3, 1] Passed STC http://tests.stockfishchess.org/tests/view/5a2b560b0ebc590ccbb8ba6b LLR: 2.96 (-2.94,2.94) [-3.00,1.00] Total: 11705 W: 2217 L: 2080 D: 7408 And LTC http://tests.stockfishchess.org/tests/view/5a2bfd0d0ebc590ccbb8bab0 LLR: 2.94 (-2.94,2.94) [-3.00,1.00] Total: 26812 W: 3575 L: 3463 D: 19774 Trying to improve on b) another attempt was made to score also the "otherchecks" for piece types which had some safe checks, but this failed STC http://tests.stockfishchess.org/tests/view/5a2c79e60ebc590ccbb8badd bench: 5149133 --- diff --git a/src/evaluate.cpp b/src/evaluate.cpp index a0bcd29d..08796159 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); @@ -428,7 +428,7 @@ namespace { : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB); const Square ksq = pos.square(Us); - Bitboard weak, b, b1, b2, safe, other; + Bitboard weak, b, b1, b2, safe, unsafeChecks; int kingDanger; // King shelter and enemy pawns storm @@ -442,18 +442,7 @@ 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 * bool(pos.pinned_pieces(Us)) - - 848 * !pos.count(Them) - - 9 * mg_value(score) / 8 - + 40; + kingDanger = unsafeChecks = 0; // Analyse the safe enemy's checks which are possible on next move safe = ~pos.pieces(Them); @@ -464,35 +453,42 @@ namespace { // 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 not defended by our pawns or occupied by a blocked pawn. + unsafeChecks &= ~( attackedBy[Us][PAWN] + | (pos.pieces(Them, PAWN) & shift(pos.pieces(PAWN)))); + + 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)