Run as a simplification
a) insures that pawn attacks are always included in the pawn span
(this "fixes" the case where some outpost or reachable outpost
bonus were awarded on squares controlled by enemy pawns).
b) compute the full span only if not "backward" or not "blocked".
By looking at "blocked" instead of "opposed", we get a nice simpli-
fication and the "new" outpost detection is almost identical, except
a few borderline cases on rank 4.
passed STC
http://tests.stockfishchess.org/tests/view/
5d9950730ebc5902b6cefb90
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 79113 W: 17168 L: 17159 D: 44786
passed LTC
http://tests.stockfishchess.org/tests/view/
5d99d14e0ebc5902b6cf0692
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 41286 W: 6819 L: 6731 D: 27736
See https://github.com/official-stockfish/Stockfish/pull/2348
bench:
3812891
constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH);
Bitboard neighbours, stoppers, support, phalanx, opposed;
constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH);
Bitboard neighbours, stoppers, support, phalanx, opposed;
- Bitboard lever, leverPush;
+ Bitboard lever, leverPush, blocked;
Square s;
bool backward, passed, doubled;
Score score = SCORE_ZERO;
Square s;
bool backward, passed, doubled;
Score score = SCORE_ZERO;
Bitboard doubleAttackThem = pawn_double_attacks_bb<Them>(theirPawns);
Bitboard doubleAttackThem = pawn_double_attacks_bb<Them>(theirPawns);
- e->passedPawns[Us] = e->pawnAttacksSpan[Us] = 0;
+ e->passedPawns[Us] = 0;
e->kingSquares[Us] = SQ_NONE;
e->kingSquares[Us] = SQ_NONE;
- e->pawnAttacks[Us] = pawn_attacks_bb<Us>(ourPawns);
+ e->pawnAttacks[Us] = e->pawnAttacksSpan[Us] = pawn_attacks_bb<Us>(ourPawns);
// Loop through all pawns of the current color and score each pawn
while ((s = *pl++) != SQ_NONE)
// Loop through all pawns of the current color and score each pawn
while ((s = *pl++) != SQ_NONE)
// Flag the pawn
opposed = theirPawns & forward_file_bb(Us, s);
// Flag the pawn
opposed = theirPawns & forward_file_bb(Us, s);
+ blocked = theirPawns & (s + Up);
stoppers = theirPawns & passed_pawn_span(Us, s);
lever = theirPawns & PawnAttacks[Us][s];
leverPush = theirPawns & PawnAttacks[Us][s + Up];
stoppers = theirPawns & passed_pawn_span(Us, s);
lever = theirPawns & PawnAttacks[Us][s];
leverPush = theirPawns & PawnAttacks[Us][s + Up];
support = neighbours & rank_bb(s - Up);
// A pawn is backward when it is behind all pawns of the same color on
support = neighbours & rank_bb(s - Up);
// A pawn is backward when it is behind all pawns of the same color on
- // the adjacent files and cannot safely advance. Phalanx and isolated
- // pawns will be excluded when the pawn is scored.
- backward = !(neighbours & forward_ranks_bb(Them, s))
- && (stoppers & (leverPush | (s + Up)));
-
- // Span of backward pawns and span behind opposing pawns are not included
- // in the pawnAttacksSpan bitboard.
- if (!backward || phalanx)
- {
- if (opposed)
- e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s) &
- ~pawn_attack_span(Us, frontmost_sq(Them, opposed));
- else
- e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s);
- }
+ // the adjacent files and cannot safely advance.
+ backward = !(neighbours & forward_ranks_bb(Them, s + Up))
+ && (stoppers & (leverPush | blocked));
+
+ // Compute additional span if pawn is not backward nor blocked
+ if (!backward && !blocked)
+ e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s);
// A pawn is passed if one of the three following conditions is true:
// (a) there is no stoppers except some levers
// A pawn is passed if one of the three following conditions is true:
// (a) there is no stoppers except some levers
passed = !(stoppers ^ lever)
|| ( !(stoppers ^ leverPush)
&& popcount(phalanx) >= popcount(leverPush))
passed = !(stoppers ^ lever)
|| ( !(stoppers ^ leverPush)
&& popcount(phalanx) >= popcount(leverPush))
- || ( stoppers == square_bb(s + Up) && r >= RANK_5
+ || ( stoppers == blocked && r >= RANK_5
&& (shift<Up>(support) & ~(theirPawns | doubleAttackThem)));
// Passed pawns will be properly scored later in evaluation when we have
&& (shift<Up>(support) & ~(theirPawns | doubleAttackThem)));
// Passed pawns will be properly scored later in evaluation when we have