From: Fabian Fichter Date: Sun, 16 Sep 2018 21:52:52 +0000 (+0200) Subject: Fix #7: Checkmate evaluation for shatar and shogi X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=8c385deb276a4cccdeb49da3d0d107c3964506be;p=fairystockfish.git Fix #7: Checkmate evaluation for shatar and shogi Evaluate illegal checkmates as losing. --- diff --git a/src/position.cpp b/src/position.cpp index 9cc14b8..4e07e75 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -444,6 +444,7 @@ void Position::set_check_info(StateInfo* si) const { 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]); } diff --git a/src/position.h b/src/position.h index 680a1f1..25ee85c 100644 --- a/src/position.h +++ b/src/position.h @@ -59,6 +59,7 @@ struct StateInfo { 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 @@ -368,34 +369,54 @@ inline bool Position::immobility_illegal() const { 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 { diff --git a/src/search.cpp b/src/search.cpp index dd15427..d2646cc 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1401,7 +1401,7 @@ moves_loop: // When in check, search starts from here // 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, diff --git a/src/types.h b/src/types.h index 25834b7..3e2633c 100644 --- a/src/types.h +++ b/src/types.h @@ -418,6 +418,12 @@ constexpr Value mated_in(int ply) { 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); } diff --git a/src/variant.cpp b/src/variant.cpp index 8da201a..79cdf38 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -267,6 +267,7 @@ void VariantMap::init() { v->promotedPieceType[ROOK] = DRAGON; v->mandatoryPiecePromotion = true; v->immobilityIllegal = true; + v->shogiPawnDropMateIllegal = true; return v; } (); const Variant* judkinsshogi = [&]{ @@ -296,6 +297,7 @@ void VariantMap::init() { v->promotedPieceType[BISHOP] = HORSE; v->promotedPieceType[ROOK] = DRAGON; v->immobilityIllegal = true; + v->shogiPawnDropMateIllegal = true; return v; } (); const Variant* minishogi = [&]{ @@ -323,6 +325,7 @@ void VariantMap::init() { v->promotedPieceType[BISHOP] = HORSE; v->promotedPieceType[ROOK] = DRAGON; v->immobilityIllegal = true; + v->shogiPawnDropMateIllegal = true; return v; } (); const Variant* losalamos = [&]{ @@ -363,8 +366,8 @@ void VariantMap::init() { 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 = [&]{ diff --git a/src/variant.h b/src/variant.h index a52196a..baf9d66 100644 --- a/src/variant.h +++ b/src/variant.h @@ -57,6 +57,8 @@ struct Variant { // 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;