From dc28770df1a9394e231f2985a7b188571df9655a Mon Sep 17 00:00:00 2001 From: RainRat Date: Tue, 31 Oct 2023 03:26:38 -0700 Subject: [PATCH] add Gale (#724) and improve bitboard parsing --- src/parser.cpp | 31 ++++++++++++++++++++++++++----- src/position.cpp | 26 ++++++++++++++++++++++++++ src/variant.h | 2 ++ src/variants.ini | 17 +++++++++++++++++ 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/parser.cpp b/src/parser.cpp index 1c4b4faf3..c925b2dee 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -124,19 +124,36 @@ namespace { } template <> bool set(const std::string& value, Bitboard& target) { - char file; - int rank; + std::string symbol; std::stringstream ss(value); target = 0; - while (!ss.eof() && ss >> file && file != '-' && ss >> rank) + while (!ss.eof() && ss >> symbol && symbol != "-") { - if (Rank(rank - 1) > RANK_MAX || (file != '*' && File(tolower(file) - 'a') > FILE_MAX)) + if (symbol.back() == '*') { + if (isalpha(symbol[0]) && symbol.length() == 2) { + char file = tolower(symbol[0]); + if (File(file - 'a') > FILE_MAX) return false; + target |= file_bb(File(file - 'a')); + } else { + return false; + } + } else if (symbol[0] == '*') { + int rank = std::stoi(symbol.substr(1)); + if (Rank(rank - 1) > RANK_MAX) return false; + target |= rank_bb(Rank(rank - 1)); + } else if (isalpha(symbol[0]) && symbol.length() > 1) { + char file = tolower(symbol[0]); + int rank = std::stoi(symbol.substr(1)); + if (Rank(rank - 1) > RANK_MAX || File(file - 'a') > FILE_MAX) return false; + target |= square_bb(make_square(File(file - 'a'), Rank(rank - 1))); + } else { return false; - target |= file == '*' ? rank_bb(Rank(rank - 1)) : square_bb(make_square(File(tolower(file) - 'a'), Rank(rank - 1))); + } } return !ss.fail(); } + template <> bool set(const std::string& value, CastlingRights& target) { char c; CastlingRights castlingRight; @@ -507,6 +524,10 @@ Variant* VariantParser::parse(Variant* v) { parse_attribute("connectHorizontal", v->connectHorizontal); parse_attribute("connectVertical", v->connectVertical); parse_attribute("connectDiagonal", v->connectDiagonal); + parse_attribute("connectRegion1White", v->connectRegion1[WHITE]); + parse_attribute("connectRegion2White", v->connectRegion2[WHITE]); + parse_attribute("connectRegion1Black", v->connectRegion1[BLACK]); + parse_attribute("connectRegion2Black", v->connectRegion2[BLACK]); parse_attribute("connectNxN", v->connectNxN); parse_attribute("materialCounting", v->materialCounting); parse_attribute("countingRule", v->countingRule); diff --git a/src/position.cpp b/src/position.cpp index c72a07f90..9b8ce391d 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -2807,6 +2807,32 @@ bool Position::is_immediate_game_end(Value& result, int ply) const { } } + if ((var->connectRegion1[~sideToMove] & pieces(~sideToMove)) && (var->connectRegion2[~sideToMove] & pieces(~sideToMove))) + { + Bitboard target = var->connectRegion2[~sideToMove]; + Bitboard current = var->connectRegion1[~sideToMove] & pieces(~sideToMove); + + while (true) { + Bitboard newBitboard = 0; + for (Direction d : var->connect_directions) { + newBitboard |= shift(d, current | newBitboard) & pieces(~sideToMove); // the "| newBitboard" here probably saves a few loops + } + + if (newBitboard & target) { + // A connection has been made + result = mated_in(ply); + return true; + } + + if (!(newBitboard & ~current)) { + // The expansion got stuck; no further squares to explore + break; + } + + current |= newBitboard; + } + } + if (connect_nxn()) { Bitboard connectors = pieces(~sideToMove); diff --git a/src/variant.h b/src/variant.h index 79cdc5a6e..49bc54404 100644 --- a/src/variant.h +++ b/src/variant.h @@ -152,6 +152,8 @@ struct Variant { bool connectHorizontal = true; bool connectVertical = true; bool connectDiagonal = true; + Bitboard connectRegion1[COLOR_NB] = {}; + Bitboard connectRegion2[COLOR_NB] = {}; int connectNxN = 0; MaterialCounting materialCounting = NO_MATERIAL_COUNTING; CountingRule countingRule = NO_COUNTING; diff --git a/src/variants.ini b/src/variants.ini index 926fa4231..b7dd011f9 100644 --- a/src/variants.ini +++ b/src/variants.ini @@ -279,6 +279,10 @@ # connectVertical: connectN looks at Vertical rows [bool] (default: true) # connectHorizontal: connectN looks at Horizontal rows [bool] (default: true) # connectDiagonal: connectN looks at Diagonal rows [bool] (default: true) +# connectRegion1White: connect Region 1 to Region 2 for win. obeys connectVertical, connectHorizontal, connectDiagonal [Bitboard] (default: -) +# connectRegion2White: " +# connectRegion1Black: " +# connectRegion2Black: " # connectNxN: connect a tight NxN square for win [int] (default: 0) # materialCounting: enable material counting rules [MaterialCounting] (default: none) # countingRule: enable counting rules [CountingRule] (default: none) @@ -1783,6 +1787,19 @@ extinctionPieceTypes = kq extinctionPseudoRoyal = true stalemateValue = loss +#https://www.ludii.games/details.php?keyword=Gale +[gale:snort] +maxRank = 9 +maxFile = 9 +startFen = 1p1p1p1p1/P1P1P1P1P/1p1p1p1p1/P1P1P1P1P/1p1p1p1p1/P1P1P1P1P/1p1p1p1p1/P1P1P1P1P/1p1p1p1p1 +enclosingDrop = none +connectRegion1White = a* +connectRegion2White = i* +connectRegion1Black = *1 +connectRegion2Black = *9 +#should be impossible anyway +connectDiagonal = false + #https://www.chessvariants.com/boardrules.dir/atlantis.html [atlantis:chess] wallingRule = edge