+ // Doubled pawn is worthless
+ if (squares_in_front_of(loserSide, psq) & (pos.pieces(PAWN, loserSide)))
+ {
+ clear_bit(&potentialBB, psq);
+ continue;
+ }
+ }
+
+ // Step 4. Check new passed pawn creation through king capturing and sacrifises
+ pawnBB = potentialBB;
+
+ while(pawnBB)
+ {
+ Square psq = pop_1st_bit(&pawnBB);
+
+ int mtg = RANK_8 - relative_rank(loserSide, psq) - int(relative_rank(loserSide, psq) == RANK_2);
+ int ptg = 2 * mtg - int(loserSide == pos.side_to_move());
+
+ // Generate list of obstacles
+ Bitboard obsBB = passed_pawn_mask(loserSide, psq) & pos.pieces(PAWN, winnerSide);
+ const bool pawnIsOpposed = squares_in_front_of(loserSide, psq) & obsBB;
+ assert(obsBB);
+
+ // How many plies does it take to remove all the obstacles?
+ int sacptg = 0;
+ int realObsCount = 0;
+ int minKingDist = 256;
+
+ while(obsBB)
+ {
+ Square obSq = pop_1st_bit(&obsBB);
+ int minMoves = 256;
+
+ // Check pawns that can give support to overcome obstacle (Eg. wp: a4,b4 bp: b2. b4 is giving support)
+ if (!pawnIsOpposed && square_file(psq) != square_file(obSq))
+ {
+ Bitboard supBB = in_front_bb(winnerSide, Square(obSq + (winnerSide == WHITE ? 8 : -8)))
+ & neighboring_files_bb(psq) & potentialBB;
+
+ while(supBB) // This while-loop could be replaced with supSq = LSB/MSB(supBB) (depending on color)
+ {
+ Square supSq = pop_1st_bit(&supBB);
+ int dist = square_distance(obSq, supSq);
+ minMoves = Min(minMoves, dist - 2);
+ }
+
+ }
+
+ // Check pawns that can be sacrifised
+ Bitboard sacBB = passed_pawn_mask(winnerSide, obSq) & neighboring_files_bb(obSq) & potentialBB & ~(1ULL << psq);
+
+ while(sacBB) // This while-loop could be replaced with sacSq = LSB/MSB(sacBB) (depending on color)
+ {
+ Square sacSq = pop_1st_bit(&sacBB);
+ int dist = square_distance(obSq, sacSq);
+ minMoves = Min(minMoves, dist - 2);
+ }
+
+ // If obstacle can be destroyed with immediate pawn sacrifise, it's not real obstacle
+ if (minMoves <= 0)
+ continue;
+
+ // Pawn sac calculations
+ sacptg += minMoves * 2;
+
+ // King capture calc
+ realObsCount++;
+ int kingDist = square_distance(pos.king_square(loserSide), obSq);
+ minKingDist = Min(minKingDist, kingDist);
+ }
+
+ // Check if pawn sac plan _may_ save the day
+ if (pliesToGo[winnerSide] + 3 > ptg + sacptg)
+ return make_score(0, 0);
+
+ // Check if king capture plan _may_ save the day (contains some false positives)
+ int kingptg = (minKingDist + realObsCount) * 2;
+ if (pliesToGo[winnerSide] + 3 > ptg + kingptg)
+ return make_score(0, 0);
+ }
+
+ // Step 5. Assign bonus
+ const int Sign[2] = {1, -1};
+ return Sign[winnerSide] * make_score(0, (Value) 0x500 - 0x20 * pliesToGo[winnerSide]);