From: RainRat Date: Sat, 22 Apr 2023 12:15:24 +0000 (-0700) Subject: Flagvariants (#638) X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=6a22e430864906b6f2beac77a51433809c6fdc01;p=fairystockfish.git Flagvariants (#638) --- diff --git a/README.md b/README.md index d8194ce..f118cf3 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,9 @@ The games currently supported besides chess are listed below. Fairy-Stockfish ca - [Breakthrough](https://en.wikipedia.org/wiki/Breakthrough_(board_game)) - [Clobber](https://en.wikipedia.org/wiki/Clobber) - [Cfour](https://en.wikipedia.org/wiki/Connect_Four), [Tic-tac-toe](https://en.wikipedia.org/wiki/Tic-tac-toe) +- [Five Field Kono](https://en.wikipedia.org/wiki/Five_Field_Kono) - [Flipersi](https://en.wikipedia.org/wiki/Reversi), [Flipello](https://en.wikipedia.org/wiki/Reversi#Othello) +- [Fox and Hounds](https://boardgamegeek.com/boardgame/148180/fox-and-hounds) - [Isolation](https://boardgamegeek.com/boardgame/1875/isolation) - [Joust](https://www.chessvariants.com/programs.dir/joust.html) - [Snailtrail](https://boardgamegeek.com/boardgame/37135/snailtrail) diff --git a/src/parser.cpp b/src/parser.cpp index 9907a5b..d7eab8e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -450,6 +450,7 @@ Variant* VariantParser::parse(Variant* v) { parse_attribute("flagRegionWhite", v->flagRegion[WHITE]); parse_attribute("flagRegionBlack", v->flagRegion[BLACK]); parse_attribute("flagPieceCount", v->flagPieceCount); + parse_attribute("flagPieceBlockedWin", v->flagPieceBlockedWin); parse_attribute("flagMove", v->flagMove); parse_attribute("checkCounting", v->checkCounting); parse_attribute("connectN", v->connectN); diff --git a/src/position.cpp b/src/position.cpp index f193420..0e52486 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -2675,15 +2675,52 @@ bool Position::is_immediate_game_end(Value& result, int ply) const { // capture the flag if ( capture_the_flag_piece() && flag_move() - && (popcount(capture_the_flag(sideToMove) & pieces(sideToMove, capture_the_flag_piece()))>=flag_piece_count())) - { - result = (popcount(capture_the_flag(~sideToMove) & pieces(~sideToMove, capture_the_flag_piece()))>=flag_piece_count()) - && sideToMove == WHITE ? VALUE_DRAW : mate_in(ply); + && ( + (popcount(capture_the_flag(sideToMove) & pieces(sideToMove, capture_the_flag_piece()))>=flag_piece_count()) // opponent has >= number of pieces needed to win + || //-or- + ( + (flag_piece_blocked_win()) //flagPieceBlockedWin variant option true + && //-and- + (capture_the_flag(sideToMove) & pieces(sideToMove, capture_the_flag_piece())) //at least one piece in flag zone + && //-and- + !(capture_the_flag(sideToMove) & ~pieces()) //no empty squares in flag zone + ) + ) + ) + { + result = + ( + ( + (popcount(capture_the_flag(~sideToMove) & pieces(~sideToMove, capture_the_flag_piece()))>=flag_piece_count()) // you have >= number of pieces needed to win + || //-or- + ( + (flag_piece_blocked_win()) //flagPieceBlockedWin variant option true + && //-and- + (capture_the_flag(~sideToMove) & pieces(~sideToMove, capture_the_flag_piece())) //at least one piece in flag zone + && //-and- + !(capture_the_flag(~sideToMove) & ~pieces()) //no empty squares in flag zone + ) + ) + && + (sideToMove == WHITE) //opponent is white + ) + ? VALUE_DRAW : mate_in(ply); //then it's a draw, otherwise, win return true; } if ( capture_the_flag_piece() - && (!flag_move() || capture_the_flag_piece() == KING) - && (popcount(capture_the_flag(~sideToMove) & pieces(~sideToMove, capture_the_flag_piece()))>=flag_piece_count()) ) + && (!flag_move() || capture_the_flag_piece() == KING) //if black doesn't get an extra move to draw, or flag piece is king, + && ( //-and- + (popcount(capture_the_flag(~sideToMove) & pieces(~sideToMove, capture_the_flag_piece()))>=flag_piece_count()) // you have >= number of pieces needed to win + || //-or- + ( + (flag_piece_blocked_win()) //flagPieceBlockedWin variant option true + && //-and- + (capture_the_flag(~sideToMove) & pieces(~sideToMove, capture_the_flag_piece())) //at least one piece in flag zone + && //-and- + !(capture_the_flag(~sideToMove) & ~pieces()) //no empty squares in flag zone + ) + ) + ) { bool gameEnd = true; // Check whether king can move to CTF zone diff --git a/src/position.h b/src/position.h index 6e179c8..6cd9f6b 100644 --- a/src/position.h +++ b/src/position.h @@ -202,6 +202,7 @@ public: bool flag_move() const; bool check_counting() const; int flag_piece_count() const; + bool flag_piece_blocked_win() const; int connect_n() const; CheckCount checks_remaining(Color c) const; MaterialCounting material_counting() const; @@ -936,6 +937,11 @@ inline int Position::flag_piece_count() const { return var->flagPieceCount; } +inline bool Position::flag_piece_blocked_win() const { + assert(var != nullptr); + return var->flagPieceBlockedWin; +} + inline bool Position::check_counting() const { assert(var != nullptr); return var->checkCounting; diff --git a/src/variant.cpp b/src/variant.cpp index fd8564f..6a020a7 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -542,20 +542,6 @@ namespace { return v; } - Variant* kono_variant() { //https://en.wikipedia.org/wiki/Five_Field_Kono - Variant* v = chess_variant_base()->init(); - v->maxRank = RANK_5; - v->maxFile = FILE_E; - v->reset_pieces(); - v->add_piece(CUSTOM_PIECE_1, 'p', "mF"); //diagonally, no capture - v->startFen = "ppppp/p3p/5/P3P/PPPPP w - - 0 1"; - v->flagPiece = CUSTOM_PIECE_1; - v->flagRegion[WHITE] = make_bitboard(SQ_A5, SQ_B5, SQ_C5, SQ_D5, SQ_E5, SQ_A4, SQ_E4); - v->flagRegion[BLACK] = make_bitboard(SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_A2, SQ_E2); - v->flagPieceCount = 7; - return v; - } - Variant* fox_and_hounds_variant() { //https://boardgamegeek.com/boardgame/148180/fox-and-hounds Variant* v = chess_variant_base()->init(); v->reset_pieces(); @@ -1582,7 +1568,7 @@ namespace { v->remove_piece(KNIGHT); v->add_piece(CHANCELLOR, 'w'); // wolf v->add_piece(ARCHBISHOP, 'f'); // fox - v->add_piece(CUSTOM_PIECE_1, 's', "fKifmnD"); // seargent + v->add_piece(CUSTOM_PIECE_1, 's', "fKifmnD"); // sergeant v->add_piece(CUSTOM_PIECE_2, 'n', "NN"); // nightrider v->add_piece(CUSTOM_PIECE_3, 'e', "NNQ"); // elephant v->startFen = "qwfrbbnk/pssppssp/1pp2pp1/8/8/8/8/1PP2PP1/PSSPPSSP/KNBBRFWQ w - - 0 1"; @@ -1816,7 +1802,6 @@ void VariantMap::init() { add("isolation7x7", isolation7x7_variant()); add("snailtrail", snailtrail_variant()); add("fox-and-hounds", fox_and_hounds_variant()); - add("kono", kono_variant()); #ifdef ALLVARS add("duck", duck_variant()); #endif diff --git a/src/variant.h b/src/variant.h index 085e9b4..891b039 100644 --- a/src/variant.h +++ b/src/variant.h @@ -144,6 +144,7 @@ struct Variant { PieceType flagPiece = NO_PIECE_TYPE; Bitboard flagRegion[COLOR_NB] = {}; int flagPieceCount = 1; + bool flagPieceBlockedWin = false; bool flagMove = false; bool checkCounting = false; int connectN = 0; diff --git a/src/variants.ini b/src/variants.ini index 361c237..c882be3 100644 --- a/src/variants.ini +++ b/src/variants.ini @@ -126,7 +126,7 @@ # [PieceSet]: multiple piece types [letters defined for pieces, e.g., nbrq] # [Bitboard]: list of squares [e.g., d4 e4 d5 e5]. * can be used as wildcard for files (e.g., *1 is the first rank) # [Value]: game result for the side to move [win, loss, draw] -# [MaterialCounting]: material couting rules for adjudication [janggi, unweighted, whitedrawodds, blackdrawodds, none] +# [MaterialCounting]: material counting rules for adjudication [janggi, unweighted, whitedrawodds, blackdrawodds, none] # [CountingRule]: makruk, cambodian, or ASEAN counting rules [makruk, cambodian, asean, none] # [ChasingRule]: xiangqi chasing rules [axf, none] # [EnclosingRule]: reversi or ataxx enclosing rules [reversi, ataxx, none] @@ -251,6 +251,7 @@ # flagMove: black gets one more move after white captures the flag [bool] (default: false) # checkCounting: enable check count win rule (check count is communicated via FEN, see 3check) [bool] (default: false) # flagPieceCount: number of flag pieces that have to be in the flag zone [int] (default: 1) +# flagPieceBlockedWin: for flagPieceCount > 1. if at least one piece in flag zone and all others occupied by opponent pieces, win. [bool] (default: false) # connectN: number of aligned pieces for win [int] (default: 0) # materialCounting: enable material counting rules [MaterialCounting] (default: none) # countingRule: enable counting rules [CountingRule] (default: none) @@ -1247,7 +1248,7 @@ promotionRegionWhite = *1 *2 *3 *4 *5 *6 *7 *8 *9 promotionRegionBlack = *9 *8 *7 *6 *5 *4 *3 *2 *1 # Chess vs Hoppel-Poppel -# Assymetrical game, Chess army vs Hoppel Poppel army. Credits to Procyon for the definition. +# Asymmetrical game, Chess army vs Hoppel Poppel army. Credits to Procyon for the definition. # Variant defined in Pychess discord and previously playable with Chessboi bot. [chessvshp:chess] soldier = s @@ -1263,7 +1264,7 @@ pieceToCharTable = PNBRQ.......IJ.......Kpnbrq.......ij.......k startFen = rijqkjir/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 # Orda vs Empire -# Assymetrical game, Empire army vs Orda army. Empire (as Black again), no Soldiers, 8 x Imperial Pawns but on the 3rd rank. Empire rules in place. Yurt is a mNcK. Credits to Procyon for the definition. +# Asymmetrical game, Empire army vs Orda army. Empire (as Black again), no Soldiers, 8 x Imperial Pawns but on the 3rd rank. Empire rules in place. Yurt is a mNcK. Credits to Procyon for the definition. # Variant defined in Pychess discord and previously playable with Chessboi bot. [ordavsempire:chess] centaur = h @@ -1291,6 +1292,68 @@ pieceToCharTable = P...Q..AH..ECTDY....LKp...q..ah..ectdy....lk duckGating = true stalemateValue = win +[kono] +maxRank = 5 +maxFile = e +customPiece1 = p:mF +startFen = ppppp/p3p/5/P3P/PPPPP w - - 0 1 +flagPiece = p +flagRegionWhite = a5 b5 c5 d5 e5 a4 e4 +flagRegionBlack = a1 b1 c1 d1 e1 a2 e2 +flagPieceCount = 7 +flagPieceBlockedWin = true + +#https://www.chessvariants.com/large.dir/xhess.html +[xhess:chess] +pieceToCharTable = HNBRQ......CI........Khnbrq......ci........k +maxRank = 10 +maxFile = j +promotionRegionWhite = *10 +promotionPieceTypes = nbrqci +flagPiece = k +flagRegionWhite = *10 +flagRegionBlack = *1 +pawnTypes = h +cannon = c +customPiece1 = i:NN +customPiece2 = h:mfWcfFfhmnN +startFen = r8r/3nkqn3/hcb1ii1bch/1hhhhhhhh1/10/10/1HHHHHHHH1/HCB1II1BCH/3NKQN3/R8R +#technically not needed because of initial setup +##enPassantRegion = 0 +##castling = false + +#https://boardgamegeek.com/boardgame/32/buffalo-chess +[buffalo] +pieceToCharTable = B...D................Cb...d................c +maxRank = 7 +maxFile = k +customPiece1 = b:mfW +customPiece2 = c:K +customPiece3 = d:mQ +startFen = bbbbbbbbbbb/11/11/11/11/3DDCDD3/11 w - - 0 1 +flagPiece = b +flagRegionBlack = *1 +mobilityRegionWhiteCustomPiece2 = *2 *3 *4 *5 *6 +mobilityRegionWhiteCustomPiece3 = *2 *3 *4 *5 *6 +extinctionValue = loss +extinctionPieceTypes = * +stalemateValue = loss + +#https://www.zillions-of-games.com/cgi-bin/zilligames/submissions.cgi?do=show;id=1596 +[knights-halma] +maxRank = 8 +maxFile = h +customPiece1 = n:mN +startFen = 5nnn/5nnn/5nnn/8/8/NNN5/NNN5/NNN5 w +flagPiece = n +flagRegionWhite = f8 g8 h8 f7 g7 h7 g6 g6 h8 +flagRegionBlack = a3 b3 c3 a2 b2 c2 a1 b1 c1 +flagPieceCount = 9 +stalemateValue = loss +nFoldRule = 2 +nFoldValue = loss +nMoveRule = 0 + #https://www.zillions-of-games.com/cgi-bin/zilligames/submissions.cgi/76202?do=show;id=83 #pawns can be caught in the blast in this one [allexplodeatomic:nocheckatomic]