+ Score bonus = SCORE_ZERO;
+ Bitboard squaresToQueen, defendedSquares, unsafeSquares, supportingPawns;
+ Bitboard b = ei.pi->passed_pawns(Us);
+
+ if (!b)
+ return SCORE_ZERO;
+
+ do {
+ Square s = pop_1st_bit(&b);
+
+ assert(pos.pawn_is_passed(Us, s));
+
+ int r = int(relative_rank(Us, s) - RANK_2);
+ int rr = r * (r - 1);
+
+ // Base bonus based on rank
+ Value mbonus = Value(20 * rr);
+ Value ebonus = Value(10 * (rr + r + 1));
+
+ if (rr)
+ {
+ Square blockSq = s + pawn_push(Us);
+
+ // Adjust bonus based on kings proximity
+ ebonus -= Value(square_distance(pos.king_square(Us), blockSq) * 3 * rr);
+ ebonus -= Value(square_distance(pos.king_square(Us), blockSq + pawn_push(Us)) * rr);
+ ebonus += Value(square_distance(pos.king_square(Them), blockSq) * 6 * rr);
+
+ // If the pawn is free to advance, increase bonus
+ if (pos.square_is_empty(blockSq))
+ {
+ squaresToQueen = squares_in_front_of(Us, s);
+ defendedSquares = squaresToQueen & ei.attackedBy[Us][0];
+
+ // If there is an enemy rook or queen attacking the pawn from behind,
+ // add all X-ray attacks by the rook or queen. Otherwise consider only
+ // the squares in the pawn's path attacked or occupied by the enemy.
+ if ( (squares_behind(Us, s) & pos.pieces(ROOK, QUEEN, Them))
+ && (squares_behind(Us, s) & pos.pieces(ROOK, QUEEN, Them) & pos.attacks_from<ROOK>(s)))
+ unsafeSquares = squaresToQueen;
+ else
+ unsafeSquares = squaresToQueen & (ei.attackedBy[Them][0] | pos.pieces_of_color(Them));
+
+ // If there aren't enemy attacks or pieces along the path to queen give
+ // huge bonus. Even bigger if we protect the pawn's path.
+ if (!unsafeSquares)
+ ebonus += Value(rr * (squaresToQueen == defendedSquares ? 17 : 15));
+ else
+ // OK, there are enemy attacks or pieces (but not pawns). Are those
+ // squares which are attacked by the enemy also attacked by us ?
+ // If yes, big bonus (but smaller than when there are no enemy attacks),
+ // if no, somewhat smaller bonus.
+ ebonus += Value(rr * ((unsafeSquares & defendedSquares) == unsafeSquares ? 13 : 8));
+
+ // At last, add a small bonus when there are no *friendly* pieces
+ // in the pawn's path.
+ if (!(squaresToQueen & pos.pieces_of_color(Us)))
+ ebonus += Value(rr);
+ }
+ } // rr != 0
+
+ // Increase the bonus if the passed pawn is supported by a friendly pawn
+ // on the same rank and a bit smaller if it's on the previous rank.
+ supportingPawns = pos.pieces(PAWN, Us) & neighboring_files_bb(s);
+ if (supportingPawns & rank_bb(s))
+ ebonus += Value(r * 20);
+ else if (supportingPawns & rank_bb(s - pawn_push(Us)))
+ ebonus += Value(r * 12);
+
+ // Rook pawns are a special case: They are sometimes worse, and
+ // sometimes better than other passed pawns. It is difficult to find
+ // good rules for determining whether they are good or bad. For now,
+ // we try the following: Increase the value for rook pawns if the
+ // other side has no pieces apart from a knight, and decrease the
+ // value if the other side has a rook or queen.
+ if (square_file(s) == FILE_A || square_file(s) == FILE_H)
+ {
+ if (pos.non_pawn_material(Them) <= KnightValueMidgame)
+ ebonus += ebonus / 4;
+ else if (pos.pieces(ROOK, QUEEN, Them))
+ ebonus -= ebonus / 4;
+ }
+ bonus += make_score(mbonus, ebonus);
+
+ } while (b);
+
+ // Add the scores to the middle game and endgame eval
+ return apply_weight(bonus, Weights[PassedPawns]);
+ }
+
+ // evaluate_unstoppable_pawns() evaluates the unstoppable passed pawns for both sides
+ template<bool HasPopCnt>
+ Score evaluate_unstoppable_pawns(const Position& pos, EvalInfo& ei) {
+
+ const BitCountType Max15 = HasPopCnt ? CNT_POPCNT : CpuIs64Bit ? CNT64_MAX15 : CNT32_MAX15;
+
+ // Step 1. Hunt for unstoppable pawns. If we find at least one, record how many plies
+ // are required for promotion
+ int pliesToGo[2] = {256, 256};
+
+ for (Color c = WHITE; c <= BLACK; c++)