: Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(QUEEN) ^ pos.pieces(Us, ROOK))
: pos.attacks_from<Pt>(s);
- if (pos.pinned_pieces(Us) & s)
+ if (pos.blockers_for_king(Us) & s)
b &= LineBB[pos.square<KING>(Us)][s];
attackedBy2[Us] |= attackedBy[Us][ALL_PIECES] & b;
if (Pt == QUEEN)
{
// Penalty if any relative pin or discovered attack against the queen
- Bitboard pinners;
- if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, pinners))
+ Bitboard queenPinners;
+ if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, queenPinners))
score -= WeakQueen;
}
}
: AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
const Square ksq = pos.square<KING>(Us);
- Bitboard weak, b, b1, b2, safe, unsafeChecks;
+ Bitboard weak, b, b1, b2, safe, unsafeChecks, pinned;
// King shelter and enemy pawns storm
Score score = pe->king_safety<Us>(pos, ksq);
// Unsafe or occupied checking squares will also be considered, as long as
// the square is in the attacker's mobility area.
unsafeChecks &= mobilityArea[Them];
+ pinned = pos.blockers_for_king(Us) & pos.pieces(Us);
kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them]
+ 102 * kingAdjacentZoneAttacksCount[Them]
+ 191 * popcount(kingRing[Us] & weak)
- + 143 * popcount(pos.pinned_pieces(Us) | unsafeChecks)
+ + 143 * popcount(pinned | unsafeChecks)
- 848 * !pos.count<QUEEN>(Them)
- 9 * mg_value(score) / 8
+ 40;
score -= make_score(kingDanger * kingDanger / 4096, kingDanger / 16);
}
}
- // Penalty when our king is on a pawnless flank
- if (!(pos.pieces(PAWN) & KingFlank[file_of(ksq)]))
- score -= PawnlessFlank;
- // King tropism: firstly, find attacked squares in our king flank
- b = attackedBy[Them][ALL_PIECES] & KingFlank[file_of(ksq)] & Camp;
+ Bitboard kf = KingFlank[file_of(ksq)];
- assert(((Us == WHITE ? b << 4 : b >> 4) & b) == 0);
- assert(popcount(Us == WHITE ? b << 4 : b >> 4) == popcount(b));
+ // Penalty when our king is on a pawnless flank
+ if (!(pos.pieces(PAWN) & kf))
+ score -= PawnlessFlank;
- // Secondly, add the squares which are attacked twice in that flank and
- // which are not defended by our pawns.
- b = (Us == WHITE ? b << 4 : b >> 4)
- | (b & attackedBy2[Them] & ~attackedBy[Us][PAWN]);
+ // Find the squares that opponent attacks in our king flank, and the squares
+ // which are attacked twice in that flank but not defended by our pawns.
+ b1 = attackedBy[Them][ALL_PIECES] & kf & Camp;
+ b2 = b1 & attackedBy2[Them] & ~attackedBy[Us][PAWN];
- score -= CloseEnemies * popcount(b);
+ // King tropism, to anticipate slow motion attacks on our king
+ score -= CloseEnemies * (popcount(b1) + popcount(b2));
if (T)
Trace::add(KING, Us, score);
template<Tracing T> template<Color Us>
Score Evaluation<T>::threats() const {
- const Color Them = (Us == WHITE ? BLACK : WHITE);
- const Direction Up = (Us == WHITE ? NORTH : SOUTH);
- const Direction Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
- const Direction Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
- const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ const Direction Up = (Us == WHITE ? NORTH : SOUTH);
+ const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
Bitboard b, weak, defended, nonPawnEnemies, stronglyProtected, safeThreats;
Score score = SCORE_ZERO;
b = pos.pieces(Us, PAWN)
& (~attackedBy[Them][ALL_PIECES] | attackedBy[Us][ALL_PIECES]);
- safeThreats = (shift<Right>(b) | shift<Left>(b)) & weak;
+ safeThreats = pawn_attacks_bb<Us>(b) & weak;
score += ThreatBySafePawn * popcount(safeThreats);
}
& (attackedBy[Us][ALL_PIECES] | ~attackedBy[Them][ALL_PIECES]);
// Bonus for safe pawn threats on the next move
- b = (shift<Left>(b) | shift<Right>(b))
+ b = pawn_attacks_bb<Us>(b)
& pos.pieces(Them)
& ~attackedBy[Us][PAWN];
&& (pos.pieces(PAWN) & KingSide);
// Compute the initiative bonus for the attacking side
- int initiative = 8 * outflanking
+ int complexity = 8 * outflanking
+ 8 * pe->pawn_asymmetry()
+ 12 * pos.count<PAWN>()
+ 16 * pawnsOnBothFlanks
// Now apply the bonus: note that we find the attacking side by extracting
// the sign of the endgame value, and that we carefully cap the bonus so
// that the endgame score will never change sign after the bonus.
- int v = ((eg > 0) - (eg < 0)) * std::max(initiative, -abs(eg));
+ int v = ((eg > 0) - (eg < 0)) * std::max(complexity, -abs(eg));
if (T)
Trace::add(INITIATIVE, make_score(0, v));
Trace::add(TOTAL, score);
}
- return pos.side_to_move() == WHITE ? v : -v; // Side to move point of view
+ return (pos.side_to_move() == WHITE ? v : -v) // Side to move point of view
+ + Eval::Tempo;
}
} // namespace
/// evaluation of the position from the point of view of the side to move.
Value Eval::evaluate(const Position& pos) {
- return Evaluation<NO_TRACE>(pos).value() + Eval::Tempo;
+ return Evaluation<NO_TRACE>(pos).value();
}
Eval::Contempt = SCORE_ZERO; // Reset any dynamic contempt
- Value v = Evaluation<TRACE>(pos).value() + Eval::Tempo;
+ Value v = Evaluation<TRACE>(pos).value();
v = pos.side_to_move() == WHITE ? v : -v; // Trace scores are from white's point of view