// Penalties for enemy's safe checks
constexpr int QueenSafeCheck = 780;
- constexpr int RookSafeCheck = 1080;
+ constexpr int RookSafeCheck = 1078;
constexpr int BishopSafeCheck = 635;
constexpr int KnightSafeCheck = 790;
+ constexpr int OtherSafeCheck = 600;
#define S(mg, eg) make_score(mg, eg)
{ S(-48,-59), S(-20,-23), S( 16, -3), S( 26, 13), S( 38, 24), S( 51, 42), // Bishop
S( 55, 54), S( 63, 57), S( 63, 65), S( 68, 73), S( 81, 78), S( 81, 86),
S( 91, 88), S( 98, 97) },
- { S(-58,-76), S(-27,-18), S(-15, 28), S(-10, 55), S( -5, 69), S( -2, 82), // Rook
- S( 9,112), S( 16,118), S( 30,132), S( 29,142), S( 32,155), S( 38,165),
- S( 46,166), S( 48,169), S( 58,171) },
- { S(-39,-36), S(-21,-15), S( 3, 8), S( 3, 18), S( 14, 34), S( 22, 54), // Queen
- S( 28, 61), S( 41, 73), S( 43, 79), S( 48, 92), S( 56, 94), S( 60,104),
- S( 60,113), S( 66,120), S( 67,123), S( 70,126), S( 71,133), S( 73,136),
- S( 79,140), S( 88,143), S( 88,148), S( 99,166), S(102,170), S(102,175),
- S(106,184), S(109,191), S(113,206), S(116,212) }
+ { S(-60,-78), S(-20,-17), S( 2, 23), S( 3, 39), S( 3, 70), S( 11, 99), // Rook
+ S( 22,103), S( 31,121), S( 40,134), S( 40,139), S( 41,158), S( 48,164),
+ S( 57,168), S( 57,169), S( 62,172) },
+ { S(-34,-36), S(-15,-21), S(-10, -1), S(-10, 22), S( 20, 41), S( 23, 56), // Queen
+ S( 23, 59), S( 35, 75), S( 38, 78), S( 53, 96), S( 64, 96), S( 65,100),
+ S( 65,121), S( 66,127), S( 67,131), S( 67,133), S( 72,136), S( 72,141),
+ S( 77,147), S( 79,150), S( 93,151), S(108,168), S(108,168), S(108,171),
+ S(110,182), S(114,182), S(114,192), S(116,219) }
};
+ constexpr Score MaxMobility = S(150, 200);
+ constexpr Score DropMobility = S(10, 10);
// RookOnFile[semiopen/open] contains bonuses for each rook when there is
// no (friendly) pawn on the rook file.
constexpr Color Them = ~Us;
constexpr Direction Up = pawn_push(Us);
+ constexpr Direction Down = -Up;
auto king_proximity = [&](Color c, Square s) {
- return std::min(distance(pos.square<KING>(c), s), 5);
+ return pos.extinction_value() == VALUE_MATE ? 0 : pos.count<KING>(c) ? std::min(distance(pos.square<KING>(c), s), 5) : 5;
};
- Bitboard b, bb, squaresToQueen, unsafeSquares;
+ Bitboard b, bb, squaresToQueen, unsafeSquares, candidatePassers, leverable;
Score score = SCORE_ZERO;
b = pe->passed_pawns(Us);
behind |= shift<Down>(behind);
behind |= shift<Down+Down>(behind);
+ if (pawnsOnly)
+ {
+ safe = behind & ~attackedBy[Them][ALL_PIECES];
+ behind = 0;
+ }
int bonus = popcount(safe) + popcount(behind & safe & ~attackedBy[Them][ALL_PIECES]);
- int weight = pos.count<ALL_PIECES>(Us) - 1;
+ int weight = pos.count<ALL_PIECES>(Us) - 3 + std::min(pe->blocked_count(), 9);
Score score = make_score(bonus * weight * weight / 16, 0);
+ if (pos.capture_the_flag(Us))
+ score += make_score(200, 200) * popcount(behind & safe & pos.capture_the_flag(Us));
+
if (T)
Trace::add(SPACE, Us, score);
// Flag the pawn
opposed = theirPawns & forward_file_bb(Us, s);
- blocked = theirPawns & (s + Up);
+ blocked = is_ok(s + Up) ? theirPawns & (s + Up) : Bitboard(0);
stoppers = theirPawns & passed_pawn_span(Us, s);
- lever = theirPawns & PawnAttacks[Us][s];
- leverPush = theirPawns & PawnAttacks[Us][s + Up];
- doubled = ourPawns & (s - Up);
+ lever = theirPawns & PseudoAttacks[Us][PAWN][s];
+ leverPush = relative_rank(Them, s, pos.max_rank()) > RANK_1 ? theirPawns & PseudoAttacks[Us][PAWN][s + Up] : Bitboard(0);
+ doubled = r > RANK_1 ? ourPawns & (s - Up) : Bitboard(0);
neighbours = ourPawns & adjacent_files_bb(s);
phalanx = neighbours & rank_bb(s);
- support = neighbours & rank_bb(s - Up);
+ support = r > RANK_1 ? neighbours & rank_bb(s - Up) : Bitboard(0);
+ e->blockedCount[Us] += blocked || more_than_one(leverPush);
+
// A pawn is backward when it is behind all pawns of the same color on
// the adjacent files and cannot safely advance.
- backward = !(neighbours & forward_ranks_bb(Them, s + Up))
- && (leverPush | blocked);
+ backward = is_ok(s + Up)
+ && !(neighbours & forward_ranks_bb(Them, s + Up))
+ && (stoppers & blocked);
// Compute additional span if pawn is not backward nor blocked
if (!backward && !blocked)
e->passedPawns[Us] |= s;
// Score this pawn
- if (support | phalanx)
+ if ((support | phalanx) && (r < pos.promotion_rank() || !pos.mandatory_pawn_promotion()))
{
- int v = Connected[r] * (2 + bool(phalanx) - bool(opposed)) * (r == RANK_2 && pos.captures_to_hand() ? 3 : 1)
- int v = Connected[r] * (4 + 2 * bool(phalanx) - 2 * bool(opposed) - bool(blocked)) / 2
++ int v = Connected[r] * (4 + 2 * bool(phalanx) - 2 * bool(opposed) - bool(blocked)) / 2 * (r == RANK_2 && pos.captures_to_hand() ? 3 : 1)
+ 21 * popcount(support);
+ if (r >= RANK_4 && pos.count<PAWN>(Us) > popcount(pos.board_bb()) / 4)
+ v = popcount(support | phalanx) * 50 / (opposed ? 2 : 1);
score += make_score(v, v * (r - 2) / 4);
}