const Score RookOpenFile = make_score(43, 21);
const Score RookSemiopenFile = make_score(19, 10);
const Score BishopPawns = make_score( 8, 12);
+ const Score MinorBehindPawn = make_score(16, 0);
const Score UndefendedMinor = make_score(25, 10);
const Score TrappedRook = make_score(90, 0);
Score evaluate_pieces_of_color(const Position& pos, EvalInfo& ei, Score& mobility);
template<Color Us, bool Trace>
- Score evaluate_king(const Position& pos, EvalInfo& ei, Value margins[]);
+ Score evaluate_king(const Position& pos, const EvalInfo& ei, Value margins[]);
template<Color Us, bool Trace>
- Score evaluate_threats(const Position& pos, EvalInfo& ei);
+ Score evaluate_threats(const Position& pos, const EvalInfo& ei);
template<Color Us, bool Trace>
- Score evaluate_passed_pawns(const Position& pos, EvalInfo& ei);
+ Score evaluate_passed_pawns(const Position& pos, const EvalInfo& ei);
template<Color Us>
- int evaluate_space(const Position& pos, EvalInfo& ei);
+ int evaluate_space(const Position& pos, const EvalInfo& ei);
- Score evaluate_unstoppable_pawns(const Position& pos, EvalInfo& ei);
+ Score evaluate_unstoppable_pawns(const Position& pos, const EvalInfo& ei);
Value interpolate(const Score& v, Phase ph, ScaleFactor sf);
Score apply_weight(Score v, Score w);
if (ei.mi->space_weight())
{
int s = evaluate_space<WHITE>(pos, ei) - evaluate_space<BLACK>(pos, ei);
- score += apply_weight(make_score(s * ei.mi->space_weight(), 0), Weights[Space]);
+ score += apply_weight(s * ei.mi->space_weight(), Weights[Space]);
}
// Scale winning side if position is more drawish that what it appears
Tracing::add(IMBALANCE, ei.mi->material_value());
Tracing::add(PAWN, ei.pi->pawns_value());
Tracing::add(UNSTOPPABLE, evaluate_unstoppable_pawns(pos, ei));
- Score w = make_score(ei.mi->space_weight() * evaluate_space<WHITE>(pos, ei), 0);
- Score b = make_score(ei.mi->space_weight() * evaluate_space<BLACK>(pos, ei), 0);
+ Score w = ei.mi->space_weight() * evaluate_space<WHITE>(pos, ei);
+ Score b = ei.mi->space_weight() * evaluate_space<BLACK>(pos, ei);
Tracing::add(SPACE, apply_weight(w, Weights[Space]), apply_weight(b, Weights[Space]));
Tracing::add(TOTAL, score);
Tracing::stream << "\nUncertainty margin: White: " << to_cp(margins[WHITE])
if (bonus && (ei.attackedBy[Us][PAWN] & s))
{
if ( !pos.pieces(Them, KNIGHT)
- && !(same_color_squares(s) & pos.pieces(Them, BISHOP)))
+ && !(squares_of_color(s) & pos.pieces(Them, BISHOP)))
bonus += bonus + bonus / 2;
else
bonus += bonus / 2;
ei.kingAdjacentZoneAttacksCount[Us] += popcount<Max15>(bb);
}
- int mob = popcount<Piece == QUEEN ? Full : Max15>(b & mobilityArea);
+ int mob = Piece != QUEEN ? popcount<Max15>(b & mobilityArea)
+ : popcount<Full >(b & mobilityArea);
+
mobility += MobilityBonus[Piece][mob];
// Decrease score if we are attacked by an enemy pawn. Remaining part
if (Piece == BISHOP)
score -= BishopPawns * ei.pi->pawns_on_same_color_squares(Us, s);
- // Bishop and knight outposts squares
- if ( (Piece == BISHOP || Piece == KNIGHT)
- && !(pos.pieces(Them, PAWN) & attack_span_mask(Us, s)))
- score += evaluate_outposts<Piece, Us>(pos, ei, s);
+ if (Piece == BISHOP || Piece == KNIGHT)
+ {
+ // Bishop and knight outposts squares
+ if (!(pos.pieces(Them, PAWN) & pawn_attack_span(Us, s)))
+ score += evaluate_outposts<Piece, Us>(pos, ei, s);
+
+ // Bishop or knight behind a pawn
+ if ( relative_rank(Us, s) < RANK_5
+ && (pos.pieces(PAWN) & (s + pawn_push(Us))))
+ score += MinorBehindPawn;
+ }
if ( (Piece == ROOK || Piece == QUEEN)
&& relative_rank(Us, s) >= RANK_5)
if (ei.pi->semiopen(Us, file_of(s)))
score += ei.pi->semiopen(Them, file_of(s)) ? RookOpenFile : RookSemiopenFile;
- if (mob > 6 || ei.pi->semiopen(Us, file_of(s)))
+ if (mob > 3 || ei.pi->semiopen(Us, file_of(s)))
continue;
Square ksq = pos.king_square(Us);
// and the type of attacked one.
template<Color Us, bool Trace>
- Score evaluate_threats(const Position& pos, EvalInfo& ei) {
+ Score evaluate_threats(const Position& pos, const EvalInfo& ei) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
// evaluate_king<>() assigns bonuses and penalties to a king of a given color
template<Color Us, bool Trace>
- Score evaluate_king(const Position& pos, EvalInfo& ei, Value margins[]) {
+ Score evaluate_king(const Position& pos, const EvalInfo& ei, Value margins[]) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
// evaluate_passed_pawns<>() evaluates the passed pawns of the given color
template<Color Us, bool Trace>
- Score evaluate_passed_pawns(const Position& pos, EvalInfo& ei) {
+ Score evaluate_passed_pawns(const Position& pos, const EvalInfo& ei) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
if (pos.is_empty(blockSq))
{
squaresToQueen = forward_bb(Us, s);
- defendedSquares = squaresToQueen & ei.attackedBy[Us][ALL_PIECES];
// If there is an enemy rook or queen attacking the pawn from behind,
// add all X-ray attacks by the rook or queen. Otherwise consider only
// the squares in the pawn's path attacked or occupied by the enemy.
- if (forward_bb(Them, s) & pos.pieces(Them, ROOK, QUEEN) & pos.attacks_from<ROOK>(s))
+ if ( unlikely(forward_bb(Them, s) & pos.pieces(Them, ROOK, QUEEN))
+ && (forward_bb(Them, s) & pos.pieces(Them, ROOK, QUEEN) & pos.attacks_from<ROOK>(s)))
unsafeSquares = squaresToQueen;
else
unsafeSquares = squaresToQueen & (ei.attackedBy[Them][ALL_PIECES] | pos.pieces(Them));
+ if ( unlikely(forward_bb(Them, s) & pos.pieces(Us, ROOK, QUEEN))
+ && (forward_bb(Them, s) & pos.pieces(Us, ROOK, QUEEN) & pos.attacks_from<ROOK>(s)))
+ defendedSquares = squaresToQueen;
+ else
+ defendedSquares = squaresToQueen & ei.attackedBy[Us][ALL_PIECES];
+
// If there aren't enemy attacks huge bonus, a bit smaller if at
// least block square is not attacked, otherwise smallest bonus.
int k = !unsafeSquares ? 15 : !(unsafeSquares & blockSq) ? 9 : 3;
// evaluate_unstoppable_pawns() evaluates the unstoppable passed pawns for both sides, this is quite
// conservative and returns a winning score only when we are very sure that the pawn is winning.
- Score evaluate_unstoppable_pawns(const Position& pos, EvalInfo& ei) {
+ Score evaluate_unstoppable_pawns(const Position& pos, const EvalInfo& ei) {
Bitboard b, b2, blockers, supporters, queeningPath, candidates;
Square s, blockSq, queeningSquare;
// black pawns: a4, b4 white: b2 then pawn in b4 is giving support.
if (!opposed)
{
- b2 = supporters & in_front_bb(winnerSide, blockSq + pawn_push(winnerSide));
+ b2 = supporters & in_front_bb(winnerSide, rank_of(blockSq + pawn_push(winnerSide)));
while (b2) // This while-loop could be replaced with LSB/MSB (depending on color)
{
}
// Check pawns that can be sacrificed against the blocking pawn
- b2 = attack_span_mask(winnerSide, blockSq) & candidates & ~(1ULL << s);
+ b2 = pawn_attack_span(winnerSide, blockSq) & candidates & ~(1ULL << s);
while (b2) // This while-loop could be replaced with LSB/MSB (depending on color)
{
// twice. Finally, the space bonus is scaled by a weight taken from the
// material hash table. The aim is to improve play on game opening.
template<Color Us>
- int evaluate_space(const Position& pos, EvalInfo& ei) {
+ int evaluate_space(const Position& pos, const EvalInfo& ei) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
assert(eg_value(v) > -VALUE_INFINITE && eg_value(v) < VALUE_INFINITE);
assert(ph >= PHASE_ENDGAME && ph <= PHASE_MIDGAME);
- int ev = (eg_value(v) * int(sf)) / SCALE_FACTOR_NORMAL;
- int result = (mg_value(v) * int(ph) + ev * int(128 - ph)) / 128;
- return Value((result + GrainSize / 2) & ~(GrainSize - 1));
+ int e = (eg_value(v) * int(sf)) / SCALE_FACTOR_NORMAL;
+ int r = (mg_value(v) * int(ph) + e * int(PHASE_MIDGAME - ph)) / PHASE_MIDGAME;
+ return Value((r / GrainSize) * GrainSize); // Sign independent
}
// apply_weight() weights score v by score w trying to prevent overflow
std::string Tracing::do_trace(const Position& pos) {
- Search::RootColor = pos.side_to_move();
-
stream.str("");
stream << std::showpoint << std::showpos << std::fixed << std::setprecision(2);
- memset(scores, 0, 2 * (TOTAL + 1) * sizeof(Score));
+ std::memset(scores, 0, 2 * (TOTAL + 1) * sizeof(Score));
Value margin;
do_evaluate<true>(pos, margin);