Add variant Spartan Chess
authorH.G. Muller <h.g.muller@hccnet.nl>
Mon, 3 Jan 2011 11:37:17 +0000 (12:37 +0100)
committerArun Persaud <arun@nubati.net>
Tue, 11 Jan 2011 05:22:04 +0000 (21:22 -0800)
In the WB menu it takes the place of the defunct Twilight Chess item.
The setup routine needed patching for setting up Lances in stead of
Pawns for black, the check test had to be adapted to handle duple check,
Alfil and Dragon moves were fine tuned in this variant to make the exact
moves, and the promotion popup was adapted to show King and interpret
Rook and Bishop as Dragon and Alfil for black. The Alfil now always
moves as Modern Elephant except in Shatranj and Courier.

backend.c
common.h
moves.c
winboard/language.txt
winboard/winboard.c
winboard/winboard.rc
winboard/woptions.c
xboard.c
xoptions.c

index dc2972c..cd53ac6 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -516,6 +516,13 @@ ChessSquare  KnightmateArray[2][BOARD_FILES] = {
         BlackUnicorn, BlackBishop, BlackMan, BlackRook }
 };
 
+ChessSquare SpartanArray[2][BOARD_FILES] = {
+    { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,
+        WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
+    { BlackAlfil, BlackMarshall, BlackKing, BlackDragon,
+        BlackDragon, BlackKing, BlackAngel, BlackAlfil }
+};
+
 ChessSquare fairyArray[2][BOARD_FILES] = { /* [HGM] Queen side differs from King side */
     { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,
         WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
@@ -955,6 +962,7 @@ InitBackEnd1()
       case VariantSuper:      /* experimental */
       case VariantGreat:      /* experimental, requires legality testing to be off */
       case VariantSChess:     /* S-Chess, should work */
+      case VariantSpartan:    /* should work */
        break;
       }
     }
@@ -5413,6 +5421,10 @@ InitPosition(redraw)
       pieces = KnightmateArray;
       SetCharTable(pieceToChar, "P.BRQ.....M.........K.p.brq.....m.........k.");
       break;
+    case VariantSpartan:
+      pieces = SpartanArray;
+      SetCharTable(pieceToChar, "PNBRQ................K......lwg.....c...h..k");
+      break;
     case VariantFairy:
       pieces = fairyArray;
       SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVLSUKpnbrqfeacwmohijgdvlsuk");
@@ -5483,7 +5495,7 @@ InitPosition(redraw)
         if(j < BOARD_LEFT || j >= BOARD_RGHT || overrule) continue;
         initialPosition[0][j] = pieces[0][j-gameInfo.holdingsWidth];
         initialPosition[pawnRow][j] = WhitePawn;
-        initialPosition[BOARD_HEIGHT-pawnRow-1][j] = BlackPawn;
+        initialPosition[BOARD_HEIGHT-pawnRow-1][j] = gameInfo.variant == VariantSpartan ? BlackLance : BlackPawn;
         if(gameInfo.variant == VariantXiangqi) {
             if(j&1) {
                 initialPosition[pawnRow][j] =
index cf16a68..d0850c7 100644 (file)
--- a/common.h
+++ b/common.h
@@ -320,6 +320,7 @@ typedef enum {
     VariantTwilight,
     VariantMakruk,
     VariantSChess,
+    VariantSpartan,
     VariantUnknown       /* Catchall for other unknown variants */
 } VariantClass;
 
@@ -364,6 +365,7 @@ typedef enum {
   "twilight",\
   "makruk",\
   "seirawan",\
+  "spartan",\
   "unknown" \
 }
 
diff --git a/moves.c b/moves.c
index f0b2af7..594bb12 100644 (file)
--- a/moves.c
+++ b/moves.c
@@ -182,6 +182,7 @@ void GenPseudoLegal(board, flags, callback, closure)
     for (rf = 0; rf < BOARD_HEIGHT; rf++)
       for (ff = BOARD_LEFT; ff < BOARD_RGHT; ff++) {
           ChessSquare piece;
+          int rookRange = 1000;
 
          if (flags & F_WHITE_ON_MOVE) {
              if (!WhitePiece(board[rf][ff])) continue;
@@ -418,7 +419,7 @@ void GenPseudoLegal(board, flags, callback, closure)
                           && !SameColor(board[rf][ff], board[rt][ft]))
                                callback(board, flags, NormalMove,
                                         rf, ff, rt, ft, closure);
-                      if(gameInfo.variant != VariantFairy && gameInfo.variant != VariantGreat) continue;
+                      if(gameInfo.variant == VariantShatranj && gameInfo.variant == VariantCourier) continue; // classical Alfil
                       rt = rf + rs; // in unknown variant we assume Modern Elephant, which can also do one step
                       ft = ff + fs;
                       if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT)
@@ -426,6 +427,12 @@ void GenPseudoLegal(board, flags, callback, closure)
                                callback(board, flags, NormalMove,
                                         rf, ff, rt, ft, closure);
                  }
+                if(gameInfo.variant == VariantSpartan)
+                   for(fs = -1; fs <= 1; fs += 2) {
+                      ft = ff + fs;
+                      if (!(ft < BOARD_LEFT || ft >= BOARD_RGHT) && board[rf][ft] == EmptySquare)
+                               callback(board, flags, NormalMove, rf, ff, rf, ft, closure);
+                   }
                 break;
 
             /* Make Dragon-Horse also do Dababba moves outside Shogi, for better disambiguation in variant Fairy */
@@ -507,6 +514,7 @@ void GenPseudoLegal(board, flags, callback, closure)
                      if (SameColor(board[rf][ff], board[rt][ft])) continue;
                      callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
                  }
+              if(gameInfo.variant == VariantSpartan) rookRange = 2; // in Spartan Chess restrict range to modern Dababba
               goto doRook;
               
             /* Shogi Dragon King has to continue as Ferz after Rook moves */
@@ -518,6 +526,7 @@ void GenPseudoLegal(board, flags, callback, closure)
             case WhiteMarshall:
             case BlackMarshall:
               m++;
+              m += (gameInfo.variant == VariantSpartan); // in Spartan Chess Chancellor is used for Dragon King.
 
             /* Shogi Rooks are ordinary Rooks */
             case SHOGI WhiteRook:
@@ -534,7 +543,7 @@ void GenPseudoLegal(board, flags, callback, closure)
                      if (SameColor(board[rf][ff], board[rt][ft])) break;
                      callback(board, flags, NormalMove,
                               rf, ff, rt, ft, closure);
-                     if (board[rt][ft] != EmptySquare) break;
+                     if (board[rt][ft] != EmptySquare || i == rookRange) break;
                  }
                 if(m==1) goto mounted;
                 if(m==2) goto finishSilver;
@@ -985,7 +994,6 @@ int CheckTest(board, flags, rf, ff, rt, ft, enPassant)
     /* For compatibility with ICS wild 9, we scan the board in the
        order a1, a2, a3, ... b1, b2, ..., h8 to find the first king,
        and we test only whether that one is in check. */
-    cl.check = 0;
     for (cl.fking = BOARD_LEFT+0; cl.fking < BOARD_RGHT; cl.fking++)
        for (cl.rking = 0; cl.rking < BOARD_HEIGHT; cl.rking++) {
           if (board[cl.rking][cl.fking] == king) {
@@ -999,9 +1007,10 @@ int CheckTest(board, flags, rf, ff, rt, ft, enPassant)
                       board[i][cl.fking] == (dir>0 ? BlackWazir : WhiteWazir) )
                           cl.check++;
               }
-
+             cl.check = 0;
              GenPseudoLegal(board, flags ^ F_WHITE_ON_MOVE, CheckTestCallback, (VOIDSTAR) &cl);
-             goto undo_move;  /* 2-level break */
+             if(gameInfo.variant != VariantSpartan || cl.check == 0) // in Spartan Chess go on to test if other King is checked too
+                goto undo_move;  /* 2-level break */
          }
       }
 
index b0082c2..699b6be 100644 (file)
@@ -550,6 +550,7 @@ VARIANT NAMES:
 "cra&zyhouse" === ""\r
 "&bughouse" === ""\r
 "&Twilight" === ""\r
+"Sp&artan" === ""\r
 "&shogi" === ""\r
 "su&per" === ""\r
 "&knightmate" === ""\r
index 3178807..773c4b9 100644 (file)
@@ -4299,6 +4299,7 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     Translate(hDlg, DLG_PromotionKing);\r
     ShowWindow(GetDlgItem(hDlg, PB_King), \r
       (!appData.testLegality || gameInfo.variant == VariantSuicide ||\r
+       gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove) ||\r
        gameInfo.variant == VariantGiveaway || gameInfo.variant == VariantSuper ) ?\r
               SW_SHOW : SW_HIDE);\r
     /* [HGM] Only allow C & A promotions if these pieces are defined */\r
@@ -4346,9 +4347,11 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
       break;\r
     case PB_Rook:\r
       promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteRook : BlackRook));\r
+      if(gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove)) promoChar = PieceToChar(BlackDragon);\r
       break;\r
     case PB_Bishop:\r
       promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteBishop : BlackBishop));\r
+      if(gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove)) promoChar = PieceToChar(BlackAlfil);\r
       break;\r
     case PB_Chancellor:\r
       promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteMarshall : BlackMarshall));\r
index 3097934..c836813 100644 (file)
@@ -677,7 +677,7 @@ BEGIN
                     70,10\r
     CONTROL         "&bughouse",OPT_VariantBughouse,"Button",BS_AUTORADIOBUTTON,80,24,70,\r
                     10\r
-    CONTROL         "&Twilight",OPT_VariantTwilight,"Button",BS_AUTORADIOBUTTON,80,34,70,\r
+    CONTROL         "Sp&artan",OPT_VariantTwilight,"Button",BS_AUTORADIOBUTTON,80,34,70,\r
                     10\r
     CONTROL         "&shogi",OPT_VariantShogi,"Button",BS_AUTORADIOBUTTON,80,\r
                     44,70,10\r
index 254547a..93dde9e 100644 (file)
@@ -786,7 +786,7 @@ VariantWhichRadio(HWND hDlg)
          (IsDlgButtonChecked(hDlg, OPT_Variant3Check) ? Variant3Check :\r
          (IsDlgButtonChecked(hDlg, OPT_VariantGreat) ? VariantGreat :\r
          (IsDlgButtonChecked(hDlg, OPT_VariantGiveaway) ? VariantGiveaway :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantTwilight) ? VariantTwilight :\r
+         (IsDlgButtonChecked(hDlg, OPT_VariantTwilight) ? VariantSpartan :\r
          (IsDlgButtonChecked(hDlg, OPT_VariantMakruk) ? VariantMakruk :\r
          (IsDlgButtonChecked(hDlg, OPT_VariantSChess) ? VariantSChess :\r
           VariantNormal ))))))))))))))))))))))))))))));\r
@@ -886,7 +886,7 @@ NewVariantDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     case VariantGiveaway:\r
       CheckDlgButton(hDlg, OPT_VariantGiveaway, TRUE);\r
       break;\r
-    case VariantTwilight:\r
+    case VariantSpartan:\r
       CheckDlgButton(hDlg, OPT_VariantTwilight, TRUE);\r
       break;\r
     case VariantMakruk:\r
index 1ab5f59..f3e7a76 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -5369,6 +5369,16 @@ void PromotionPopUp()
                                   layout, args, j);
 
   if(gameInfo.variant != VariantShogi) {
+   if(gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove)) {
+      XawDialogAddButton(dialog, _("Warlord"), PromotionCallback,
+                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("General"), PromotionCallback,
+                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("Lieutenant"), PromotionCallback,
+                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("Captain"), PromotionCallback,
+                        (XtPointer) dialog);
+    } else {\r
     XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
                       (XtPointer) dialog);
     XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
@@ -5377,7 +5387,9 @@ void PromotionPopUp()
                       (XtPointer) dialog);
     XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
                       (XtPointer) dialog);
+    }
     if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
+        gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove) ||\r
         gameInfo.variant == VariantGiveaway) {
       XawDialogAddButton(dialog, _("King"), PromotionCallback,
                         (XtPointer) dialog);
index af309a1..759ea19 100644 (file)
@@ -982,6 +982,7 @@ struct NewVarButton buttonDesc[] = {
 #ifdef FALCON
     {N_("Falcon (10x8)"),     "#BFBFFF", 0, VariantFalcon},
 #endif
+    {N_("Spartan"),           "#FF0000", 0, VariantSpartan},
     {NULL,                0, 0, (VariantClass) 0}
 };