namespace {
// Threshold for lazy and space evaluation
- constexpr Value LazyThreshold = Value(1500);
+ constexpr Value LazyThreshold = Value(1400);
constexpr Value SpaceThreshold = Value(12222);
// KingAttackWeights[PieceType] contains king attack weights by piece type
};
// Assorted bonuses and penalties
+ constexpr Score AttacksOnSpaceArea = S( 4, 0);
constexpr Score BishopPawns = S( 3, 7);
constexpr Score CorneredBishop = S( 50, 50);
constexpr Score FlankAttacks = S( 8, 0);
constexpr Score KnightOnQueen = S( 16, 12);
constexpr Score LongDiagonalBishop = S( 45, 0);
constexpr Score MinorBehindPawn = S( 18, 3);
- constexpr Score Outpost = S( 9, 3);
+ constexpr Score Outpost = S( 36, 12);
constexpr Score PawnlessFlank = S( 17, 95);
constexpr Score RestrictedPiece = S( 7, 7);
constexpr Score RookOnPawn = S( 10, 32);
constexpr Score ThreatBySafePawn = S(173, 94);
constexpr Score TrappedRook = S( 47, 4);
constexpr Score WeakQueen = S( 49, 15);
- constexpr Score WeakUnopposedPawn = S( 12, 23);
#undef S
// color, including x-rays. But diagonal x-rays through pawns are not computed.
Bitboard attackedBy2[COLOR_NB];
- // kingRing[color] are the squares adjacent to the king, plus (only for a
- // king on its first rank) the squares two ranks in front. For instance,
- // if black's king is on g8, kingRing[BLACK] is f8, h8, f7, g7, h7, f6, g6
- // and h6.
+ // kingRing[color] are the squares adjacent to the king plus some other
+ // very near squares, depending on king position.
Bitboard kingRing[COLOR_NB];
// kingAttackersCount[color] is the number of pieces of the given color
if (Pt == BISHOP || Pt == KNIGHT)
{
// Bonus if piece is on an outpost square or can reach one
- bb = OutpostRanks & ~pe->pawn_attacks_span(Them);
+ bb = OutpostRanks & attackedBy[Us][PAWN] & ~pe->pawn_attacks_span(Them);
if (bb & s)
- score += Outpost * (Pt == KNIGHT ? 4 : 2)
- * ((attackedBy[Us][PAWN] & s) ? 2 : 1);
+ score += Outpost * (Pt == KNIGHT ? 2 : 1);
- else if (bb &= b & ~pos.pieces(Us))
- score += Outpost * (Pt == KNIGHT ? 2 : 1)
- * ((attackedBy[Us][PAWN] & bb) ? 2 : 1);
+ else if (bb & b & ~pos.pieces(Us))
+ score += Outpost / (Pt == KNIGHT ? 1 : 2);
// Knight and Bishop bonus for being right behind a pawn
if (shift<Down>(pos.pieces(PAWN)) & s)
score += RookOnPawn * popcount(pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s]);
// Bonus for rook on an open or semi-open file
- if (pos.is_semiopen_file(Us, file_of(s)))
- score += RookOnFile[bool(pos.is_semiopen_file(Them, file_of(s)))];
+ if (pos.is_on_semiopen_file(Us, s))
+ score += RookOnFile[bool(pos.is_on_semiopen_file(Them, s))];
// Penalty when trapped by the king, even more if the king cannot castle
else if (mob <= 3)
score += RestrictedPiece * popcount(b);
- // Bonus for enemy unopposed weak pawns
- if (pos.pieces(Us, ROOK, QUEEN))
- score += WeakUnopposedPawn * pe->weak_unopposed(Them);
-
// Find squares where our pawns can push on the next move
b = shift<Up>(pos.pieces(Us, PAWN)) & ~pos.pieces();
b |= shift<Up>(b & TRank3BB) & ~pos.pieces();
// If the pawn is free to advance, then increase the bonus
if (pos.empty(blockSq))
{
- // If there is a rook or queen attacking/defending the pawn from behind,
- // consider all the squaresToQueen. Otherwise consider only the squares
- // in the pawn's path attacked or occupied by the enemy.
- defendedSquares = unsafeSquares = squaresToQueen = forward_file_bb(Us, s);
+ defendedSquares = squaresToQueen = forward_file_bb(Us, s);
+ unsafeSquares = passed_pawn_span(Us, s);
- bb = forward_file_bb(Them, s) & pos.pieces(ROOK, QUEEN) & pos.attacks_from<ROOK>(s);
+ bb = forward_file_bb(Them, s) & pos.pieces(ROOK, QUEEN);
if (!(pos.pieces(Us) & bb))
defendedSquares &= attackedBy[Us][ALL_PIECES];
if (!(pos.pieces(Them) & bb))
unsafeSquares &= attackedBy[Them][ALL_PIECES] | pos.pieces(Them);
- // If there aren't any enemy attacks, assign a big bonus. Otherwise
- // assign a smaller bonus if the block square isn't attacked.
- int k = !unsafeSquares ? 20 : !(unsafeSquares & blockSq) ? 9 : 0;
-
- // If the path to the queen is fully defended, assign a big bonus.
- // Otherwise assign a smaller bonus if the block square is defended.
- if (defendedSquares == squaresToQueen)
- k += 6;
+ // If there are no enemy attacks on passed pawn span, assign a big bonus.
+ // Otherwise assign a smaller bonus if the path to queen is not attacked
+ // and even smaller bonus if it is attacked but block square is not.
+ int k = !unsafeSquares ? 35 :
+ !(unsafeSquares & squaresToQueen) ? 20 :
+ !(unsafeSquares & blockSq) ? 9 :
+ 0 ;
- else if (defendedSquares & blockSq)
- k += 4;
+ // Assign a larger bonus if the block square is defended.
+ if (defendedSquares & blockSq)
+ k += 5;
bonus += make_score(k * w, k * w);
}
int weight = pos.count<ALL_PIECES>(Us) - 1;
Score score = make_score(bonus * weight * weight / 16, 0);
+ score -= AttacksOnSpaceArea * popcount(attackedBy[Them][ALL_PIECES] & behind & safe);
+
if (T)
Trace::add(SPACE, Us, score);
// Early exit if score is high
Value v = (mg_value(score) + eg_value(score)) / 2;
- if (abs(v) > LazyThreshold)
+ if (abs(v) > LazyThreshold + pos.non_pawn_material() / 64)
return pos.side_to_move() == WHITE ? v : -v;
// Main evaluation begins here