- // evaluate_unstoppable_pawns() evaluates the unstoppable passed pawns for both sides, this is quite
- // conservative and returns a winning score only when we are very sure that the pawn is winning.
-
- Score evaluate_unstoppable_pawns(const Position& pos, EvalInfo& ei) {
-
- Bitboard b, b2, blockers, supporters, queeningPath, candidates;
- Square s, blockSq, queeningSquare;
- Color c, winnerSide, loserSide;
- bool pathDefended, opposed;
- int pliesToGo, movesToGo, oppMovesToGo, sacptg, blockersCount, minKingDist, kingptg, d;
- int pliesToQueen[] = { 256, 256 };
-
- // Step 1. Hunt for unstoppable passed pawns. If we find at least one,
- // record how many plies are required for promotion.
- for (c = WHITE; c <= BLACK; c++)
- {
- // Skip if other side has non-pawn pieces
- if (pos.non_pawn_material(~c))
- continue;
-
- b = ei.pi->passed_pawns(c);
-
- while (b)
- {
- s = pop_lsb(&b);
- queeningSquare = relative_square(c, file_of(s) | RANK_8);
- queeningPath = forward_bb(c, s);
-
- // Compute plies to queening and check direct advancement
- movesToGo = rank_distance(s, queeningSquare) - int(relative_rank(c, s) == RANK_2);
- oppMovesToGo = square_distance(pos.king_square(~c), queeningSquare) - int(c != pos.side_to_move());
- pathDefended = ((ei.attackedBy[c][ALL_PIECES] & queeningPath) == queeningPath);
-
- if (movesToGo >= oppMovesToGo && !pathDefended)
- continue;
-
- // Opponent king cannot block because path is defended and position
- // is not in check. So only friendly pieces can be blockers.
- assert(!pos.checkers());
- assert((queeningPath & pos.pieces()) == (queeningPath & pos.pieces(c)));
-
- // Add moves needed to free the path from friendly pieces and retest condition
- movesToGo += popcount<Max15>(queeningPath & pos.pieces(c));
-
- if (movesToGo >= oppMovesToGo && !pathDefended)
- continue;
-
- pliesToGo = 2 * movesToGo - int(c == pos.side_to_move());
- pliesToQueen[c] = std::min(pliesToQueen[c], pliesToGo);
- }
- }
-
- // Step 2. If either side cannot promote at least three plies before the other side then situation
- // becomes too complex and we give up. Otherwise we determine the possibly "winning side"
- if (abs(pliesToQueen[WHITE] - pliesToQueen[BLACK]) < 3)
- return SCORE_ZERO;
-
- winnerSide = (pliesToQueen[WHITE] < pliesToQueen[BLACK] ? WHITE : BLACK);
- loserSide = ~winnerSide;
-
- // Step 3. Can the losing side possibly create a new passed pawn and thus prevent the loss?
- b = candidates = pos.pieces(loserSide, PAWN);