Evaluate illegal checkmates as losing.
for (PieceType pt = PAWN; pt < KING; ++pt)
si->checkSquares[pt] = ksq != SQ_NONE ? attacks_from(~sideToMove, pt, ksq) : 0;
si->checkSquares[KING] = 0;
+ si->shak = si->checkersBB & (byTypeBB[KNIGHT] | byTypeBB[ROOK] | byTypeBB[BERS]);
}
Bitboard pinners[COLOR_NB];
Bitboard checkSquares[PIECE_TYPE_NB];
bool capturedpromoted;
+ bool shak;
};
/// A list to keep track of the position states along the setup moves (from the
inline Value Position::stalemate_value(int ply) const {
assert(var != nullptr);
- Value v = var->stalemateValue;
- return v == VALUE_MATE ? mate_in(ply)
- : v == -VALUE_MATE ? mated_in(ply)
- : v;
+ return convert_mate_value(var->stalemateValue, ply);
}
inline Value Position::checkmate_value(int ply) const {
assert(var != nullptr);
- Value v = var->checkmateValue;
- return v == VALUE_MATE ? mate_in(ply)
- : v == -VALUE_MATE ? mated_in(ply)
- : v;
+ // Check for illegal mate by shogi pawn drop
+ if ( var->shogiPawnDropMateIllegal
+ && !(checkers() & ~pieces(SHOGI_PAWN))
+ && !st->capturedPiece
+ && st->pliesFromNull > 0
+ && (st->materialKey != st->previous->materialKey))
+ {
+ return mate_in(ply);
+ }
+ // Check for shatar mate rule
+ if (var->shatarMateRule)
+ {
+ // Mate by knight is illegal
+ if (!(checkers() & ~pieces(KNIGHT)))
+ return mate_in(ply);
+
+ StateInfo* stp = st;
+ while (stp->checkersBB)
+ {
+ // Return mate score if there is at least one shak in series of checks
+ if (stp->shak)
+ return convert_mate_value(var->checkmateValue, ply);
+
+ if (stp->pliesFromNull < 2)
+ break;
+
+ stp = stp->previous->previous;
+ }
+ // Niol
+ return VALUE_DRAW;
+ }
+ // Return mate value
+ return convert_mate_value(var->checkmateValue, ply);
}
inline Value Position::bare_king_value(int ply) const {
assert(var != nullptr);
- Value v = var->bareKingValue;
- return v == VALUE_MATE ? mate_in(ply)
- : v == -VALUE_MATE ? mated_in(ply)
- : v;
+ return convert_mate_value(var->bareKingValue, ply);
}
inline Value Position::extinction_value(int ply) const {
assert(var != nullptr);
- Value v = var->extinctionValue;
- return v == VALUE_MATE ? mate_in(ply)
- : v == -VALUE_MATE ? mated_in(ply)
- : v;
+ return convert_mate_value(var->extinctionValue, ply);
}
inline bool Position::bare_king_move() const {
// All legal moves have been searched. A special case: If we're in check
// and no legal moves were found, it is checkmate.
if (inCheck && bestValue == -VALUE_INFINITE)
- return mated_in(ss->ply); // Plies to mate from the root
+ return pos.checkmate_value(ss->ply); // Plies to mate from the root
tte->save(posKey, value_to_tt(bestValue, ss->ply),
PvNode && bestValue > oldAlpha ? BOUND_EXACT : BOUND_UPPER,
return -VALUE_MATE + ply;
}
+constexpr Value convert_mate_value(Value v, int ply) {
+ return v == VALUE_MATE ? mate_in(ply)
+ : v == -VALUE_MATE ? mated_in(ply)
+ : v;
+}
+
constexpr Square make_square(File f, Rank r) {
return Square((r << 3) + f);
}
v->promotedPieceType[ROOK] = DRAGON;
v->mandatoryPiecePromotion = true;
v->immobilityIllegal = true;
+ v->shogiPawnDropMateIllegal = true;
return v;
} ();
const Variant* judkinsshogi = [&]{
v->promotedPieceType[BISHOP] = HORSE;
v->promotedPieceType[ROOK] = DRAGON;
v->immobilityIllegal = true;
+ v->shogiPawnDropMateIllegal = true;
return v;
} ();
const Variant* minishogi = [&]{
v->promotedPieceType[BISHOP] = HORSE;
v->promotedPieceType[ROOK] = DRAGON;
v->immobilityIllegal = true;
+ v->shogiPawnDropMateIllegal = true;
return v;
} ();
const Variant* losalamos = [&]{
v->endgameEval = true;
v->doubleStep = false;
v->castling = false;
- v->bareKingValue = VALUE_DRAW;
- // TODO: illegal checkmates
+ v->bareKingValue = VALUE_DRAW; // Robado
+ v->shatarMateRule = true;
return v;
} ();
const Variant* clobber = [&]{
// game end
Value stalemateValue = VALUE_DRAW;
Value checkmateValue = -VALUE_MATE;
+ bool shogiPawnDropMateIllegal = false;
+ bool shatarMateRule = false;
Value bareKingValue = VALUE_NONE;
Value extinctionValue = VALUE_NONE;
bool bareKingMove = false;