assert(pos.endgame_eval() == EG_EVAL_ATOMIC);
- // Stalemate detection with lone king
+ // Stalemate/checkmate detection with lone king
if (pos.side_to_move() == weakSide && !MoveList<LEGAL>(pos).size())
- return VALUE_DRAW;
+ return std::min(pos.stalemate_value(), VALUE_MATE_IN_MAX_PLY - 1);
Square winnerKSq = pos.square<COMMONER>(strongSide);
Square loserKSq = pos.square<COMMONER>(weakSide);
assert(pos.endgame_eval() == EG_EVAL_ATOMIC);
- // Stalemate detection with lone king
+ // Stalemate/checkmate detection with lone king
if (pos.side_to_move() == weakSide && !MoveList<LEGAL>(pos).size())
- return VALUE_DRAW;
+ return std::min(pos.stalemate_value(), VALUE_MATE_IN_MAX_PLY - 1);
Square winnerKSq = pos.square<COMMONER>(strongSide);
Square loserKSq = pos.square<COMMONER>(weakSide);
int dist = distance(winnerKSq, loserKSq);
// Draw in case of adjacent kings
- // In the case of dist == 2, the square adjacent to both kings is ensured
- // not be occupied by the queen, since eval is not called when in check.
- if (dist <= (strongSide == pos.side_to_move() ? 1 : 2))
+ if (dist == 1)
+ return VALUE_DRAW;
+ // If the weaker side is to move and there is a way to connect kings, it is a draw
+ if ( pos.side_to_move() == weakSide
+ && (attacks_bb<KING>(winnerKSq) & attacks_bb<KING>(loserKSq) & ~pos.pieces()))
return VALUE_DRAW;
- Value result = pos.non_pawn_material(strongSide)
- + push_to_edge(loserKSq, pos)
+ Value result = Value(push_to_edge(loserKSq, pos))
+ push_away(winnerKSq, loserKSq);
if (dist >= (strongSide == pos.side_to_move() ? 3 : 4))
}
// Sum up blast piece values
+ bool extinctsUs = false;
+ bool extinctsThem = false;
while (blast)
{
Piece bpc = piece_on(pop_lsb(blast));
if (extinction_piece_types() & type_of(bpc))
- return color_of(bpc) == us ? extinction_value()
- : capture(m) ? -extinction_value()
- : VALUE_ZERO;
+ {
+ if (color_of(bpc) == us)
+ extinctsUs = true;
+ else
+ extinctsThem = true;
+ }
result += color_of(bpc) == us ? -CapturePieceValue[MG][bpc] : CapturePieceValue[MG][bpc];
}
+ // Evaluate extinctions
+ if (!capture(m))
+ {
+ // For quiet moves, the opponent can decide whether to capture or not
+ // so they can pick the better of the two
+ if (extinctsThem && extinctsUs)
+ return VALUE_ZERO;
+ if (extinctsThem)
+ return std::min(-extinction_value(), VALUE_ZERO);
+ if (extinctsUs)
+ return std::min(extinction_value(), VALUE_ZERO);
+ }
+ else
+ {
+ if (extinctsUs)
+ return extinction_value();
+ if (extinctsThem)
+ return -extinction_value();
+ }
+
return capture(m) || must_capture() ? result - 1 : std::min(result, VALUE_ZERO);
}