Material::Entry* me;
Pawns::Entry* pe;
- Bitboard pinnedPieces[COLOR_NB];
Bitboard mobilityArea[COLOR_NB];
// attackedBy[color][piece type] is a bitboard representing all squares
const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 78, 56, 45, 11 };
// Penalties for enemy's safe checks
- const int QueenContactCheck = 997;
const int QueenCheck = 745;
const int RookCheck = 688;
const int BishopCheck = 588;
const int KnightCheck = 924;
// Threshold for lazy evaluation
- const Value LazyEval = Value(1500);
+ const Value LazyThreshold = Value(1500);
// eval_init() initializes king and attack bitboards for a given color
// adding pawn attacks. To be done at the beginning of the evaluation.
const Square Down = (Us == WHITE ? SOUTH : NORTH);
const Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB: Rank7BB | Rank6BB);
- ei.pinnedPieces[Us] = pos.pinned_pieces(Us);
-
// Find our pawns on the first two ranks, and those which are blocked
Bitboard b = pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | LowRanks);
: Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(Us, ROOK, QUEEN))
: pos.attacks_from<Pt>(s);
- if (ei.pinnedPieces[Us] & s)
+ if (pos.pinned_pieces(Us) & s)
b &= LineBB[pos.square<KING>(Us)][s];
ei.attackedBy2[Us] |= ei.attackedBy[Us][ALL_PIECES] & b;
ei.kingAdjacentZoneAttacksCount[Us] += popcount(b & ei.attackedBy[Them][KING]);
}
- if (Pt == QUEEN)
- b &= ~( ei.attackedBy[Them][KNIGHT]
- | ei.attackedBy[Them][BISHOP]
- | ei.attackedBy[Them][ROOK]);
-
int mob = popcount(b & ei.mobilityArea[Us]);
mobility[Us] += MobilityBonus[Pt][mob];
kingDanger = std::min(807, ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them])
+ 101 * ei.kingAdjacentZoneAttacksCount[Them]
+ 235 * popcount(undefended)
- + 134 * (popcount(b) + !!ei.pinnedPieces[Us])
+ + 134 * (popcount(b) + !!pos.pinned_pieces(Us))
- 717 * !pos.count<QUEEN>(Them)
- 7 * mg_value(score) / 5 - 5;
- // Analyse the enemy's safe queen contact checks. Firstly, find the
- // undefended squares around our king reachable by the enemy queen...
- b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them);
-
- // ...and keep squares supported by another enemy piece.
- kingDanger += QueenContactCheck * popcount(b & ei.attackedBy2[Them]);
-
// Analyse the safe enemy's checks which are possible on next move
- safe = ~(ei.attackedBy[Us][ALL_PIECES] | pos.pieces(Them));
+ safe = ~pos.pieces(Them);
+ safe &= ~ei.attackedBy[Us][ALL_PIECES] | (undefended & ei.attackedBy2[Them]);
b1 = pos.attacks_from<ROOK >(ksq);
b2 = pos.attacks_from<BISHOP>(ksq);
}
- // evaluate_passed_pawns() evaluates the passed pawns of the given color
+ // evaluate_passer_pawns() evaluates the passed pawns and candidate passed
+ // pawns of the given color.
template<Color Us, bool DoTrace>
- Score evaluate_passed_pawns(const Position& pos, const EvalInfo& ei) {
+ Score evaluate_passer_pawns(const Position& pos, const EvalInfo& ei) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
{
Square s = pop_lsb(&b);
- assert(pos.pawn_passed(Us, s));
assert(!(pos.pieces(PAWN) & forward_bb(Us, s)));
bb = forward_bb(Us, s) & (ei.attackedBy[Them][ALL_PIECES] | pos.pieces(Them));
if (!pos.non_pawn_material(Them))
ebonus += 20;
+ // Scale down bonus for candidate passers which need more than one pawn
+ // push to become passed.
+ if (!pos.pawn_passed(Us, s + pawn_push(Us)))
+ mbonus /= 2, ebonus /= 2;
+
score += make_score(mbonus, ebonus) + PassedFile[file_of(s)];
}
// If we don't already have an unusual scale factor, check for certain
// types of endgames, and use a lower scale for those.
- if ( ei.me->game_phase() < PHASE_MIDGAME
- && (sf == SCALE_FACTOR_NORMAL || sf == SCALE_FACTOR_ONEPAWN))
+ if (sf == SCALE_FACTOR_NORMAL || sf == SCALE_FACTOR_ONEPAWN)
{
if (pos.opposite_bishops())
{
// is almost a draw, in case of KBP vs KB, it is even more a draw.
if ( pos.non_pawn_material(WHITE) == BishopValueMg
&& pos.non_pawn_material(BLACK) == BishopValueMg)
- sf = more_than_one(pos.pieces(PAWN)) ? ScaleFactor(31) : ScaleFactor(9);
+ return more_than_one(pos.pieces(PAWN)) ? ScaleFactor(31) : ScaleFactor(9);
// Endgame with opposite-colored bishops, but also other pieces. Still
// a bit drawish, but not as drawish as with only the two bishops.
- else
- sf = ScaleFactor(46);
+ return ScaleFactor(46);
}
// Endings where weaker side can place his king in front of the opponent's
// pawns are drawish.
else if ( abs(eg) <= BishopValueEg
&& pos.count<PAWN>(strongSide) <= 2
&& !pos.pawn_passed(~strongSide, pos.square<KING>(~strongSide)))
- sf = ScaleFactor(37 + 7 * pos.count<PAWN>(strongSide));
+ return ScaleFactor(37 + 7 * pos.count<PAWN>(strongSide));
}
return sf;
}
-
- Value lazy_eval(Value mg, Value eg) {
-
- if (mg > LazyEval && eg > LazyEval)
- return LazyEval + ((mg + eg) / 2 - LazyEval) / 4;
-
- else if (mg < -LazyEval && eg < -LazyEval)
- return -LazyEval + ((mg + eg) / 2 + LazyEval) / 4;
-
- return VALUE_ZERO;
- }
-
} // namespace
assert(!pos.checkers());
Score mobility[COLOR_NB] = { SCORE_ZERO, SCORE_ZERO };
+ Value v;
EvalInfo ei;
// Probe the material hash table
ei.pe = Pawns::probe(pos);
score += ei.pe->pawns_score();
- // We have taken into account all cheap evaluation terms.
- // If score exceeds a threshold return a lazy evaluation.
- Value lazy = lazy_eval(mg_value(score), eg_value(score));
- if (lazy)
- return pos.side_to_move() == WHITE ? lazy : -lazy;
+ // Early exit if score is high
+ v = (mg_value(score) + eg_value(score)) / 2;
+ if (abs(v) > LazyThreshold)
+ return pos.side_to_move() == WHITE ? v : -v;
// Initialize attack and king safety bitboards
eval_init<WHITE>(pos, ei);
- evaluate_threats<BLACK, DoTrace>(pos, ei);
// Evaluate passed pawns, we need full attack information including king
- score += evaluate_passed_pawns<WHITE, DoTrace>(pos, ei)
- - evaluate_passed_pawns<BLACK, DoTrace>(pos, ei);
+ score += evaluate_passer_pawns<WHITE, DoTrace>(pos, ei)
+ - evaluate_passer_pawns<BLACK, DoTrace>(pos, ei);
// Evaluate space for both sides, only during opening
if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >= 12222)
ScaleFactor sf = evaluate_scale_factor(pos, ei, eg_value(score));
// Interpolate between a middlegame and a (scaled by 'sf') endgame score
- Value v = mg_value(score) * int(ei.me->game_phase())
- + eg_value(score) * int(PHASE_MIDGAME - ei.me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
+ v = mg_value(score) * int(ei.me->game_phase())
+ + eg_value(score) * int(PHASE_MIDGAME - ei.me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
v /= int(PHASE_MIDGAME);