- // Step 4. Check new passed pawn creation through king capturing and pawn sacrifices
- b = candidates;
-
- while (b)
- {
- s = pop_lsb(&b);
- sacptg = blockersCount = 0;
- minKingDist = kingptg = 256;
-
- // Compute plies from queening
- queeningSquare = relative_square(loserSide, file_of(s) | RANK_8);
- movesToGo = rank_distance(s, queeningSquare) - int(relative_rank(loserSide, s) == RANK_2);
- pliesToGo = 2 * movesToGo - int(loserSide == pos.side_to_move());
-
- // Generate list of blocking pawns and supporters
- supporters = adjacent_files_bb(file_of(s)) & candidates;
- opposed = forward_bb(loserSide, s) & pos.pieces(winnerSide, PAWN);
- blockers = passed_pawn_mask(loserSide, s) & pos.pieces(winnerSide, PAWN);
-
- assert(blockers);
-
- // How many plies does it take to remove all the blocking pawns?
- while (blockers)
- {
- blockSq = pop_lsb(&blockers);
- movesToGo = 256;
-
- // Check pawns that can give support to overcome obstacle, for instance
- // black pawns: a4, b4 white: b2 then pawn in b4 is giving support.
- if (!opposed)
- {
- b2 = supporters & in_front_bb(winnerSide, rank_of(blockSq + pawn_push(winnerSide)));
-
- while (b2) // This while-loop could be replaced with LSB/MSB (depending on color)
- {
- d = square_distance(blockSq, pop_lsb(&b2)) - 2;
- movesToGo = std::min(movesToGo, d);
- }
- }
-
- // Check pawns that can be sacrificed against the blocking pawn
- b2 = pawn_attack_span(winnerSide, blockSq) & candidates & ~(1ULL << s);
-
- while (b2) // This while-loop could be replaced with LSB/MSB (depending on color)
- {
- d = square_distance(blockSq, pop_lsb(&b2)) - 2;
- movesToGo = std::min(movesToGo, d);
- }
-
- // If obstacle can be destroyed with an immediate pawn exchange / sacrifice,
- // it's not a real obstacle and we have nothing to add to pliesToGo.
- if (movesToGo <= 0)
- continue;
-
- // Plies needed to sacrifice against all the blocking pawns
- sacptg += movesToGo * 2;
- blockersCount++;
-
- // Plies needed for the king to capture all the blocking pawns
- d = square_distance(pos.king_square(loserSide), blockSq);
- minKingDist = std::min(minKingDist, d);
- kingptg = (minKingDist + blockersCount) * 2;
- }
-
- // Check if pawn sacrifice plan _may_ save the day
- if (pliesToQueen[winnerSide] + 3 > pliesToGo + sacptg)
- return SCORE_ZERO;
-
- // Check if king capture plan _may_ save the day (contains some false positives)
- if (pliesToQueen[winnerSide] + 3 > pliesToGo + kingptg)
- return SCORE_ZERO;
- }
-
- // Winning pawn is unstoppable and will promote as first, return big score
- Score score = make_score(0, (Value) 1280 - 32 * pliesToQueen[winnerSide]);
- return winnerSide == WHITE ? score : -score;