From: Fabian Fichter Date: Tue, 27 Oct 2020 18:29:36 +0000 (+0100) Subject: Support Kakao Janggi repetition rules X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=836b939aa2a72306f09b269918174b9d2231e204;p=fairystockfish.git Support Kakao Janggi repetition rules Closes #198 and #142. --- diff --git a/src/parser.cpp b/src/parser.cpp index 51caf97..99e0106 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -285,6 +285,7 @@ Variant* VariantParser::parse(Variant* v) { parse_attribute("nFoldValue", v->nFoldValue); parse_attribute("nFoldValueAbsolute", v->nFoldValueAbsolute); parse_attribute("perpetualCheckIllegal", v->perpetualCheckIllegal); + parse_attribute("moveRepetitionIllegal", v->moveRepetitionIllegal); parse_attribute("stalemateValue", v->stalemateValue); parse_attribute("stalematePieceCount", v->stalematePieceCount); parse_attribute("checkmateValue", v->checkmateValue); diff --git a/src/position.cpp b/src/position.cpp index 5d3b102..7ae6617 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1198,6 +1198,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) { std::memcpy(static_cast(&newSt), static_cast(st), offsetof(StateInfo, key)); newSt.previous = st; st = &newSt; + st->move = m; // Increment ply counters. In particular, rule50 will be reset to zero later on // in case of a capture or a pawn move. @@ -1985,16 +1986,42 @@ bool Position::is_optional_game_end(Value& result, int ply, int countStarted) co int cnt = 0; bool perpetualThem = st->checkersBB && stp->checkersBB; bool perpetualUs = st->previous->checkersBB && stp->previous->checkersBB; + int moveRepetition = var->moveRepetitionIllegal + && type_of(st->move) == NORMAL + && (board_bb(~side_to_move(), type_of(piece_on(to_sq(st->move)))) & board_bb(side_to_move(), KING)) + ? (stp->move == reverse_move(st->move) ? 2 : is_pass(stp->move) ? 1 : 0) : 0; for (int i = 4; i <= end; i += 2) { + // Janggi repetition rule + if (moveRepetition > 0) + { + if (moveRepetition < 4) + { + if (stp->previous->previous->move == reverse_move((moveRepetition == 1 ? st : stp)->move)) + moveRepetition++; + else + moveRepetition = 0; + } + else + { + assert(moveRepetition == 4); + if (!stp->previous->previous->capturedPiece && from_sq(stp->move) == to_sq(stp->previous->previous->move)) + { + result = VALUE_MATE; + return true; + } + else + moveRepetition = 0; + } + } stp = stp->previous->previous; perpetualThem &= bool(stp->checkersBB); // Return a draw score if a position repeats once earlier but strictly // after the root, or repeats twice before or at the root. if ( stp->key == st->key - && ++cnt + 1 == (ply > i ? 2 : n_fold_rule())) + && ++cnt + 1 == (ply > i && !var->moveRepetitionIllegal ? 2 : n_fold_rule())) { result = convert_mate_value( var->perpetualCheckIllegal && perpetualThem ? VALUE_MATE : var->perpetualCheckIllegal && perpetualUs ? -VALUE_MATE @@ -2144,7 +2171,7 @@ bool Position::has_game_cycle(int ply) const { int end = captures_to_hand() ? st->pliesFromNull : std::min(st->rule50, st->pliesFromNull); - if (end < 3 || var->nFoldValue != VALUE_DRAW || var->perpetualCheckIllegal || var->materialCounting) + if (end < 3 || var->nFoldValue != VALUE_DRAW || var->perpetualCheckIllegal || var->materialCounting || var->moveRepetitionIllegal) return false; Key originalKey = st->key; diff --git a/src/position.h b/src/position.h index 792daaa..49598a1 100644 --- a/src/position.h +++ b/src/position.h @@ -66,6 +66,7 @@ struct StateInfo { bool shak; bool bikjang; bool pass; + Move move; int repetition; // Used by NNUE diff --git a/src/variant.cpp b/src/variant.cpp index 8b9a66d..b9aa5d6 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -943,7 +943,8 @@ namespace { Variant* v = janggi_variant(); v->bikjangRule = false; v->materialCounting = JANGGI_MATERIAL; - v->nFoldValue = -VALUE_MATE; + v->moveRepetitionIllegal = true; + v->nFoldRule = 4; // avoid nFold being triggered before move repetition return v; } // Casual rules of Janggi, where bikjang and material counting are not considered diff --git a/src/variant.h b/src/variant.h index 5e22704..515a44f 100644 --- a/src/variant.h +++ b/src/variant.h @@ -102,6 +102,7 @@ struct Variant { Value nFoldValue = VALUE_DRAW; bool nFoldValueAbsolute = false; bool perpetualCheckIllegal = false; + bool moveRepetitionIllegal = false; Value stalemateValue = VALUE_DRAW; bool stalematePieceCount = false; // multiply stalemate value by sign(count(~stm) - count(stm)) Value checkmateValue = -VALUE_MATE; diff --git a/src/variants.ini b/src/variants.ini index ee7ecd6..103a5bf 100644 --- a/src/variants.ini +++ b/src/variants.ini @@ -166,6 +166,7 @@ # nFoldValue: result in case of 3/n-fold repetition [Value] (default: draw) # nFoldValueAbsolute: result in case of 3/n-fold repetition is from white's point of view [bool] (default: false) # perpetualCheckIllegal: prohibit perpetual checks [bool] (default: false) +# moveRepetitionIllegal: prohibit moving back and forth with the same piece nFoldRule-1 times [bool] (default: false) # stalemateValue: result in case of stalemate [Value] (default: draw) # stalematePieceCount: count material in case of stalemate [bool] (default: false) # checkmateValue: result in case of checkmate [Value] (default: loss)