// Backward pawn penalty by opposed flag and file
const Score Backward[2][FILE_NB] = {
- { S(30, 42), S(43, 46), S(49, 46), S(49, 46),
- S(49, 46), S(49, 46), S(43, 46), S(30, 42) },
- { S(20, 28), S(29, 31), S(33, 31), S(33, 31),
- S(33, 31), S(33, 31), S(29, 31), S(20, 28) } };
+ { S(50, 52), S(63, 56), S(69, 56), S(69, 56),
+ S(69, 56), S(69, 56), S(63, 56), S(50, 52) },
+ { S(40, 38), S(49, 41), S(53, 41), S(53, 41),
+ S(53, 41), S(53, 41), S(49, 41), S(40, 38) } };
- // Connected pawn bonus by opposed, phalanx flags and rank
- Score Connected[2][2][RANK_NB];
+ // Connected pawn bonus by opposed, phalanx, twice supported and rank
+ Score Connected[2][2][2][RANK_NB];
// Levers bonus by rank
const Score Lever[RANK_NB] = {
const Square Right = (Us == WHITE ? DELTA_NE : DELTA_SW);
const Square Left = (Us == WHITE ? DELTA_NW : DELTA_SE);
- Bitboard b, p, doubled, connected;
+ Bitboard b, neighbours, doubled, supported, phalanx;
Square s;
- bool passed, isolated, opposed, phalanx, backward, unsupported, lever;
+ bool passed, isolated, opposed, backward, lever, connected;
Score score = SCORE_ZERO;
const Square* pl = pos.list<PAWN>(Us);
const Bitboard* pawnAttacksBB = StepAttacksBB[make_piece(Us, PAWN)];
// This file cannot be semi-open
e->semiopenFiles[Us] &= ~(1 << f);
- // Previous rank
- p = rank_bb(s - pawn_push(Us));
-
- // Flag the pawn as passed, isolated, doubled,
- // unsupported or connected (but not the backward one).
- connected = ourPawns & adjacent_files_bb(f) & (rank_bb(s) | p);
- phalanx = connected & rank_bb(s);
- unsupported = !(ourPawns & adjacent_files_bb(f) & p);
- isolated = !(ourPawns & adjacent_files_bb(f));
+ // Flag the pawn
+ neighbours = ourPawns & adjacent_files_bb(f);
doubled = ourPawns & forward_bb(Us, s);
opposed = theirPawns & forward_bb(Us, s);
passed = !(theirPawns & passed_pawn_mask(Us, s));
lever = theirPawns & pawnAttacksBB[s];
+ phalanx = neighbours & rank_bb(s);
+ supported = neighbours & rank_bb(s - Up);
+ connected = supported | phalanx;
+ isolated = !neighbours;
// Test for backward pawn.
- // If the pawn is passed, isolated, connected or a lever it cannot be
+ // If the pawn is passed, isolated, lever or connected it cannot be
// backward. If there are friendly pawns behind on adjacent files
// it cannot be backward either.
if ( (passed | isolated | lever | connected)
backward = false;
else
{
- // We now know that there are no friendly pawns beside or behind this
+ // We now know there are no friendly pawns beside or behind this
// pawn on adjacent files. We now check whether the pawn is
// backward by looking in the forward direction on the adjacent
// files, and picking the closest pawn there.
if (isolated)
score -= Isolated[opposed][f];
- if (unsupported && !isolated)
+ else if (backward)
+ score -= Backward[opposed][f];
+
+ else if (!supported)
score -= UnsupportedPawnPenalty;
+ if (connected)
+ score += Connected[opposed][!!phalanx][more_than_one(supported)][relative_rank(Us, s)];
+
if (doubled)
score -= Doubled[f] / distance<Rank>(s, frontmost_sq(Us, doubled));
- if (backward)
- score -= Backward[opposed][f];
-
- if (connected)
- score += Connected[opposed][phalanx][relative_rank(Us, s)];
-
if (lever)
score += Lever[relative_rank(Us, s)];
}
for (int opposed = 0; opposed <= 1; ++opposed)
for (int phalanx = 0; phalanx <= 1; ++phalanx)
- for (Rank r = RANK_2; r < RANK_8; ++r)
- {
- int bonus = Seed[r] + (phalanx ? (Seed[r + 1] - Seed[r]) / 2 : 0);
- Connected[opposed][phalanx][r] = make_score(bonus / 2, bonus >> opposed);
- }
+ for (int apex = 0; apex <= 1; ++apex)
+ for (Rank r = RANK_2; r < RANK_8; ++r)
+ {
+ int v = (Seed[r] + (phalanx ? (Seed[r + 1] - Seed[r]) / 2 : 0)) >> opposed;
+ v += (apex ? v / 2 : 0);
+ Connected[opposed][phalanx][apex][r] = make_score(3 * v / 2, v);
+ }
}
kingSquares[Us] = ksq;
castlingRights[Us] = pos.can_castle(Us);
- minKingPawnDistance[Us] = 0;
+ int minKingPawnDistance = 0;
Bitboard pawns = pos.pieces(Us, PAWN);
if (pawns)
- while (!(DistanceRingBB[ksq][minKingPawnDistance[Us]++] & pawns)) {}
+ while (!(DistanceRingBB[ksq][minKingPawnDistance++] & pawns)) {}
if (relative_rank(Us, ksq) > RANK_4)
- return make_score(0, -16 * minKingPawnDistance[Us]);
+ return make_score(0, -16 * minKingPawnDistance);
Value bonus = shelter_storm<Us>(pos, ksq);
if (pos.can_castle(MakeCastling<Us, QUEEN_SIDE>::right))
bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_C1)));
- return make_score(bonus, -16 * minKingPawnDistance[Us]);
+ return make_score(bonus, -16 * minKingPawnDistance);
}
// Explicit template instantiation