From d7a2d5a44588676abf9b49e35a5a567fd57ec3b0 Mon Sep 17 00:00:00 2001 From: Lolligerhans Date: Sat, 11 Apr 2020 17:28:45 +0200 Subject: [PATCH] Remove candidate passers w/o feasible lever +-------+ | o . . | o their pawns | x . . | x our pawns | . x . | <- Can sacrifice to create passer? +-------+ yes 1 2 3 4 5 +-------+ +-------+ +-------+ +-------+ +-------+ | o . . | | o r . | | o r . | | o . b | | o . b | lowercase: theirs | x b . | | x . . | | x . R | | x . R | | x . . | uppercase: ours | . x . | | . x . | | . x . | | . x . | | . x B | +-------+ +-------+ +-------+ +-------+ +-------+ no no yes no yes The value of our top pawn depends on our ability to advance our bottom pawn, levering their blocker. Previously, this pawn configuration was always scored as passer (although a blocked one). Add requirements for the square s above our (possibly) sacrificed pawn: - s must not be occupied by them (1). - If they attack s (2), we must attack s (3). - If they attack s with a minor (4), we must attack s with a minor (5). The attack from their blocker is ignored because it is inherent in the structure; we are ok with sacrificing our bottom pawn. LTC LLR: 2.95 (-2.94,2.94) {0.25,1.75} Total: 37030 W: 4962 L: 4682 D: 27386 Ptnml(0-2): 266, 3445, 10863, 3625, 316 https://tests.stockfishchess.org/tests/view/5e92a2b4be6ede5b954bf239 STC LLR: 2.94 (-2.94,2.94) {-0.50,1.50} Total: 40874 W: 8066 L: 7813 D: 24995 Ptnml(0-2): 706, 4753, 9324, 4890, 764 https://tests.stockfishchess.org/tests/view/5e922199af0a0143109dc90e closes https://github.com/official-stockfish/Stockfish/pull/2624 Bench: 4828294 --- src/evaluate.cpp | 19 ++++++++++++++++++- src/pawns.cpp | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index a2e5ef7b..2698c813 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -578,16 +578,33 @@ namespace { constexpr Color Them = ~Us; constexpr Direction Up = pawn_push(Us); + constexpr Direction Down = -Up; auto king_proximity = [&](Color c, Square s) { return std::min(distance(pos.square(c), s), 5); }; - Bitboard b, bb, squaresToQueen, unsafeSquares; + Bitboard b, bb, squaresToQueen, unsafeSquares, candidatePassers, leverable; Score score = SCORE_ZERO; b = pe->passed_pawns(Us); + candidatePassers = b & shift(pos.pieces(Them, PAWN)); + if (candidatePassers) + { + // Can we lever the blocker of a candidate passer? + leverable = shift(pos.pieces(Us, PAWN)) + & ~pos.pieces(Them) + & (~attackedBy2[Them] | attackedBy[Us][ALL_PIECES]) + & (~(attackedBy[Them][KNIGHT] | attackedBy[Them][BISHOP]) + | (attackedBy[Us ][KNIGHT] | attackedBy[Us ][BISHOP])); + + // Remove candidate otherwise + b &= ~candidatePassers + | shift(leverable) + | shift(leverable); + } + while (b) { Square s = pop_lsb(&b); diff --git a/src/pawns.cpp b/src/pawns.cpp index 0017b804..63bc596f 100644 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@ -118,6 +118,7 @@ namespace { // (a) there is no stoppers except some levers // (b) the only stoppers are the leverPush, but we outnumber them // (c) there is only one front stopper which can be levered. + // (Refined in Evaluation::passed) passed = !(stoppers ^ lever) || ( !(stoppers ^ leverPush) && popcount(phalanx) >= popcount(leverPush)) -- 2.39.2