Support Tori shogi
authorFabian Fichter <ianfab@users.noreply.github.com>
Sat, 1 May 2021 13:02:01 +0000 (15:02 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Sat, 1 May 2021 13:02:01 +0000 (15:02 +0200)
README.md
src/parser.cpp
src/position.h
src/ucioption.cpp
src/variant.cpp
src/variant.h
src/variants.ini
tests/perft.sh

index b4c8df4..2b1d5b7 100644 (file)
--- a/README.md
+++ b/README.md
@@ -49,15 +49,16 @@ The games currently supported besides chess are listed below. Fairy-Stockfish ca
 - [Extinction](https://en.wikipedia.org/wiki/Extinction_chess), [Kinglet](https://en.wikipedia.org/wiki/V._R._Parton#Kinglet_chess), Three Kings, [Coregal](https://www.chessvariants.com/winning.dir/coregal.html)
 - [King of the Hill](https://en.wikipedia.org/wiki/King_of_the_Hill_(chess)), [Racing Kings](https://en.wikipedia.org/wiki/V._R._Parton#Racing_Kings)
 - [Three-check](https://en.wikipedia.org/wiki/Three-check_chess), Five-check
-- [Los Alamos](https://en.wikipedia.org/wiki/Los_Alamos_chess)
+- [Los Alamos](https://en.wikipedia.org/wiki/Los_Alamos_chess), [Gardner's Minichess](https://en.wikipedia.org/wiki/Minichess#5%C3%975_chess)
 - [Atomic](https://en.wikipedia.org/wiki/Atomic_chess)
 - [Horde](https://en.wikipedia.org/wiki/Dunsany%27s_Chess#Horde_Chess), [Maharajah and the Sepoys](https://en.wikipedia.org/wiki/Maharajah_and_the_Sepoys)
-- [Knightmate](https://www.chessvariants.com/diffobjective.dir/knightmate.html)
+- [Knightmate](https://www.chessvariants.com/diffobjective.dir/knightmate.html), [Nightrider](https://en.wikipedia.org/wiki/Nightrider_(chess))
 
 ### Shogi variants
 - [Minishogi](https://en.wikipedia.org/wiki/Minishogi), [EuroShogi](https://en.wikipedia.org/wiki/EuroShogi), [Judkins shogi](https://en.wikipedia.org/wiki/Judkins_shogi)
 - [Kyoto shogi](https://en.wikipedia.org/wiki/Kyoto_shogi), [Microshogi](https://en.wikipedia.org/wiki/Micro_shogi)
 - [Dobutsu shogi](https://en.wikipedia.org/wiki/Dōbutsu_shōgi), [Goro goro shogi](https://en.wikipedia.org/wiki/D%C5%8Dbutsu_sh%C5%8Dgi#Variation)
+- [Tori shogi](https://en.wikipedia.org/wiki/Tori_shogi)
 - [Yari shogi](https://en.wikipedia.org/wiki/Yari_shogi)
 - [Okisaki shogi](https://en.wikipedia.org/wiki/Okisaki_shogi)
 
index e925db3..5f8de07 100644 (file)
@@ -312,6 +312,7 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
     parse_attribute("dropOppositeColoredBishop", v->dropOppositeColoredBishop);
     parse_attribute("dropPromoted", v->dropPromoted);
     parse_attribute("dropNoDoubled", v->dropNoDoubled, v->pieceToChar);
+    parse_attribute("dropNoDoubledCount", v->dropNoDoubledCount);
     parse_attribute("immobilityIllegal", v->immobilityIllegal);
     parse_attribute("gating", v->gating);
     parse_attribute("arrowGating", v->arrowGating);
index f79b80f..a6307e8 100644 (file)
@@ -610,7 +610,7 @@ inline Bitboard Position::drop_region(Color c, PieceType pt) const {
   // Doubled shogi pawns
   if (pt == drop_no_doubled())
       for (File f = FILE_A; f <= max_file(); ++f)
-          if (file_bb(f) & pieces(c, pt))
+          if (popcount(file_bb(f) & pieces(c, pt)) >= var->dropNoDoubledCount)
               b &= ~file_bb(f);
   // Sittuyin rook drops
   if (pt == ROOK && sittuyin_rook_drop())
index c30654b..f515237 100644 (file)
@@ -128,7 +128,7 @@ void on_variant_change(const Option &o) {
                 if (pt == PAWN && !v->firstRankPawnDrops)
                     suffix += "j";
                 else if (pt == v->dropNoDoubled)
-                    suffix += "f";
+                    suffix += std::string(v->dropNoDoubledCount, 'f');
                 else if (pt == BISHOP && v->dropOppositeColoredBishop)
                     suffix += "s";
                 suffix += "@" + std::to_string(pt == PAWN && !v->promotionZonePawnDrops ? v->promotionRank : v->maxRank + 1);
index 8287d61..06e48ce 100644 (file)
@@ -198,8 +198,7 @@ namespace {
     Variant* nightrider_variant() {
         Variant* v = chess_variant_base();
         v->remove_piece(KNIGHT);
-        v->customPiece[0] = "NN";
-        v->add_piece(CUSTOM_PIECES, 'n');
+        v->add_piece(CUSTOM_PIECES, 'n', "NN");
         v->promotionPieceTypes = {QUEEN, ROOK, BISHOP, CUSTOM_PIECES};
         return v;
     }
@@ -662,6 +661,45 @@ namespace {
         v->promotedPieceType[SHOGI_KNIGHT] = GOLD;
         return v;
     }
+    // Tori shogi
+    // https://en.wikipedia.org/wiki/Tori_shogi
+    Variant* torishogi_variant() {
+        Variant* v = variant_base();
+        v->variantTemplate = "shogi";
+        v->pieceToCharTable = "S.....FLR.C+.....+.PKs.....flr.c+.....+.pk";
+        v->maxRank = RANK_7;
+        v->maxFile = FILE_G;
+        v->reset_pieces();
+        v->add_piece(SHOGI_PAWN, 's');
+        v->add_piece(KING, 'k');
+        v->add_piece(CUSTOM_PIECES, 'f', "FsfW"); // falcon
+        v->add_piece(CUSTOM_PIECES + 1, 'c', "FvW"); // crane
+        v->add_piece(CUSTOM_PIECES + 2, 'l', "fRrbBlbF"); // left quail
+        v->add_piece(CUSTOM_PIECES + 3, 'r', "fRlbBrbF"); // right quail
+        v->add_piece(CUSTOM_PIECES + 4, 'p', "bFfD"); // pheasant
+        v->add_piece(CUSTOM_PIECES + 5, 'g', "fAbD"); // goose
+        v->add_piece(CUSTOM_PIECES + 6, 'e', "KbRfBbF2"); // eagle
+        v->startFen = "rpckcpl/3f3/sssssss/2s1S2/SSSSSSS/3F3/LPCKCPR [-] w 0 1";
+        v->pieceDrops = true;
+        v->capturesToHand = true;
+        v->promotionRank = RANK_6;
+        v->promotionPieceTypes = {};
+        v->doubleStep = false;
+        v->castling = false;
+        v->promotedPieceType[SHOGI_PAWN]    = CUSTOM_PIECES + 5; // swallow promotes to goose
+        v->promotedPieceType[CUSTOM_PIECES] = CUSTOM_PIECES + 6; // falcon promotes to eagle
+        v->mandatoryPiecePromotion = true;
+        v->dropNoDoubled = SHOGI_PAWN;
+        v->dropNoDoubledCount = 2;
+        v->immobilityIllegal = true;
+        v->shogiPawnDropMateIllegal = true;
+        v->stalemateValue = -VALUE_MATE;
+        v->nFoldValue = VALUE_MATE;
+        v->nFoldRule = 3;
+        v->nMoveRule = 0;
+        v->perpetualCheckIllegal = true;
+        return v;
+    }
     // EuroShogi
     // https://en.wikipedia.org/wiki/EuroShogi
     Variant* euroshogi_variant() {
@@ -669,8 +707,7 @@ namespace {
         v->pieceToCharTable = "PNBR.....G.++++Kpnbr.....g.++++k";
         v->maxRank = RANK_8;
         v->maxFile = FILE_H;
-        v->customPiece[0] = "fNsW";
-        v->add_piece(CUSTOM_PIECES, 'n');
+        v->add_piece(CUSTOM_PIECES, 'n', std::string("fNsW"));
         v->startFen = "1nbgkgn1/1r4b1/pppppppp/8/8/PPPPPPPP/1B4R1/1NGKGBN1[-] w 0 1";
         v->promotionRank = RANK_6;
         v->promotedPieceType[CUSTOM_PIECES] = GOLD;
@@ -797,8 +834,7 @@ namespace {
         v->maxRank = RANK_7;
         v->maxFile = FILE_G;
         v->reset_pieces();
-        v->customPiece[0] = "mDmNmA";
-        v->add_piece(CUSTOM_PIECES, 'p');
+        v->add_piece(CUSTOM_PIECES, 'p', "mDmNmA");
         v->startFen = "P5p/7/7/7/7/7/p5P[PPPPPPPPPPPPPPPPPPPPPPPPPppppppppppppppppppppppppp] w 0 1";
         v->promotionPieceTypes = {};
         v->pieceDrops = true;
@@ -867,16 +903,11 @@ namespace {
         v->add_piece(KING, 'k');
         v->add_piece(SHOGI_PAWN, 'p');
         v->add_piece(ROOK, 'l');
-        v->customPiece[0] = "fRffN"; // Yari knight
-        v->add_piece(CUSTOM_PIECES, 'n');
-        v->customPiece[1] = "fFfR"; // Yari bishop
-        v->add_piece(CUSTOM_PIECES + 1, 'b');
-        v->customPiece[2] = "frlR"; // Yari rook
-        v->add_piece(CUSTOM_PIECES + 2, 'r');
-        v->customPiece[3] = "WfFbR"; // Yari gold
-        v->add_piece(CUSTOM_PIECES + 3, 'g');
-        v->customPiece[4] = "fKbR"; // Yari silver
-        v->add_piece(CUSTOM_PIECES + 4, 's');
+        v->add_piece(CUSTOM_PIECES, 'n', "fRffN"); // Yari knight
+        v->add_piece(CUSTOM_PIECES + 1, 'b', "fFfR"); // Yari bishop
+        v->add_piece(CUSTOM_PIECES + 2, 'r', "frlR"); // Yari rook
+        v->add_piece(CUSTOM_PIECES + 3, 'g', "WfFbR"); // Yari gold
+        v->add_piece(CUSTOM_PIECES + 4, 's', "fKbR"); // Yari silver
         v->startFen = "rnnkbbr/7/ppppppp/7/7/7/PPPPPPP/7/RBBKNNR[-] w 0 1";
         v->promotionRank = RANK_7;
         v->promotedPieceType[SHOGI_PAWN] = CUSTOM_PIECES + 4;
@@ -903,8 +934,7 @@ namespace {
         Variant* v = minishogi_variant_base();
         v->maxRank = RANK_10;
         v->maxFile = FILE_J;
-        v->customPiece[0] = "vR"; // Vertical slider
-        v->add_piece(CUSTOM_PIECES, 'l');
+        v->add_piece(CUSTOM_PIECES, 'l', "vR"); // Vertical slider
         v->add_piece(KNIGHT, 'n');
         v->add_piece(QUEEN, 'q');
         v->startFen = "lnsgkqgsnl/1r6b1/pppppppppp/10/10/10/10/PPPPPPPPPP/1B6R1/LNSGQKGSNL[-] w 0 1";
@@ -1106,10 +1136,8 @@ namespace {
         v->startFen = "2cwamwc2/1rnbqkbnr1/pppppppppp/10/10/10/10/PPPPPPPPPP/1RNBQKBNR1/2CWAMWC2 w - - 0 1";
         v->add_piece(ARCHBISHOP, 'a');
         v->add_piece(CHANCELLOR, 'm');
-        v->customPiece[0] = "DAW"; // Champion
-        v->customPiece[1] = "CF"; // Wizard
-        v->add_piece(CUSTOM_PIECES, 'c');
-        v->add_piece(CUSTOM_PIECES + 1, 'w');
+        v->add_piece(CUSTOM_PIECES, 'c', "DAW"); // Champion
+        v->add_piece(CUSTOM_PIECES + 1, 'w', "CF"); // Wizard
         v->promotionPieceTypes = {ARCHBISHOP, CHANCELLOR, QUEEN};
         v->promotionRank = RANK_10;
         v->doubleStepRank = RANK_3;
@@ -1157,8 +1185,7 @@ namespace {
         v->maxRank = RANK_10;
         v->maxFile = FILE_J;
         v->reset_pieces();
-        v->customPiece[0] = "mQ";
-        v->add_piece(CUSTOM_PIECES, 'q');
+        v->add_piece(CUSTOM_PIECES, 'q', "mQ");
         v->add_piece(IMMOBILE_PIECE, 'p');
         v->startFen = "3q2q3/10/10/q8q/10/10/Q8Q/10/10/3Q2Q3[PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPpppppppppppppppppppppppppppppppppppppppppppppp] w - - 0 1";
         v->stalemateValue = -VALUE_MATE;
@@ -1320,6 +1347,7 @@ void VariantMap::init() {
     add("dobutsu", dobutsu_variant()->conclude());
     add("gorogoro", gorogoroshogi_variant()->conclude());
     add("judkins", judkinsshogi_variant()->conclude());
+    add("tori", torishogi_variant()->conclude());
     add("euroshogi", euroshogi_variant()->conclude());
     add("losalamos", losalamos_variant()->conclude());
     add("gardner", gardner_variant()->conclude());
index dd03214..61cbdf7 100644 (file)
@@ -89,6 +89,7 @@ struct Variant {
   bool dropOppositeColoredBishop = false;
   bool dropPromoted = false;
   PieceType dropNoDoubled = NO_PIECE_TYPE;
+  int dropNoDoubledCount = 1;
   bool immobilityIllegal = false;
   bool gating = false;
   bool arrowGating = false;
@@ -138,12 +139,19 @@ struct Variant {
   PieceType nnueKing = KING;
   bool endgameEval = false;
 
-  void add_piece(PieceType pt, char c, char c2 = ' ') {
+  void add_piece(PieceType pt, char c, std::string betza = "", char c2 = ' ') {
       pieceToChar[make_piece(WHITE, pt)] = toupper(c);
       pieceToChar[make_piece(BLACK, pt)] = tolower(c);
       pieceToCharSynonyms[make_piece(WHITE, pt)] = toupper(c2);
       pieceToCharSynonyms[make_piece(BLACK, pt)] = tolower(c2);
       pieceTypes.insert(pt);
+      // Add betza notation for custom piece
+      if (pt >= CUSTOM_PIECES && pt <= CUSTOM_PIECES_END)
+          customPiece[pt - CUSTOM_PIECES] = betza;
+  }
+
+  void add_piece(PieceType pt, char c, char c2) {
+      add_piece(pt, c, "", c2);
   }
 
   void remove_piece(PieceType pt) {
index 6ea5280..7827066 100644 (file)
 # dropOppositeColoredBishop: dropped bishops have to be on opposite-colored squares [bool] (default: false)
 # dropPromoted: pieces may be dropped in promoted state [bool] (default: false)
 # dropNoDoubled: specified piece type can not be dropped to the same file (e.g. shogi pawn) [PieceType] (default: -)
+# dropNoDoubledCount: specifies the count of already existing pieces for dropNoDoubled [PieceType] (default: 1)
 # immobilityIllegal: pieces may not move to squares where they can never move from [bool] (default: false)
 # gating: maintain squares on backrank with extra rights in castling field of FEN [bool] (default: false)
 # arrowGating: allow gating in Game of the Amazons style [bool] (default: false)
index fab2ab8..788c8a1 100755 (executable)
@@ -104,6 +104,7 @@ if [[ $1 == "" || $1 == "variant" ]]; then
   expect perft.exp euroshogi startpos 4 380499 > /dev/null
   expect perft.exp minishogi startpos 5 533203 > /dev/null
   expect perft.exp kyotoshogi startpos 5 225903 > /dev/null
+  expect perft.exp tori startpos 4 103857 > /dev/null
   # non-chess
   expect perft.exp ataxx startpos 4 155888 > /dev/null
   expect perft.exp ataxx "fen 7/7/7/7/ppppppp/ppppppp/PPPPPPP[PPPPPPPPPPPPPPPPPPPPPppppppppppppppppppppp] w 0 1" 5 452980 > /dev/null