From e3e3615246633473d0ea262f6d3974d6a49cfd01 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Mon, 3 Jan 2011 12:37:17 +0100 Subject: [PATCH] Add variant Spartan Chess 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 | 14 +++++++++++++- common.h | 2 ++ moves.c | 19 ++++++++++++++----- winboard/language.txt | 1 + winboard/winboard.c | 3 +++ winboard/winboard.rc | 2 +- winboard/woptions.c | 4 ++-- xboard.c | 12 ++++++++++++ xoptions.c | 1 + 9 files changed, 49 insertions(+), 9 deletions(-) diff --git a/backend.c b/backend.c index dc2972c..cd53ac6 100644 --- 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] = diff --git a/common.h b/common.h index cf16a68..d0850c7 100644 --- 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 --- 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 */ } } diff --git a/winboard/language.txt b/winboard/language.txt index b0082c2..699b6be 100644 --- a/winboard/language.txt +++ b/winboard/language.txt @@ -550,6 +550,7 @@ VARIANT NAMES: "cra&zyhouse" === "" "&bughouse" === "" "&Twilight" === "" +"Sp&artan" === "" "&shogi" === "" "su&per" === "" "&knightmate" === "" diff --git a/winboard/winboard.c b/winboard/winboard.c index 3178807..773c4b9 100644 --- a/winboard/winboard.c +++ b/winboard/winboard.c @@ -4299,6 +4299,7 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) Translate(hDlg, DLG_PromotionKing); ShowWindow(GetDlgItem(hDlg, PB_King), (!appData.testLegality || gameInfo.variant == VariantSuicide || + gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove) || gameInfo.variant == VariantGiveaway || gameInfo.variant == VariantSuper ) ? SW_SHOW : SW_HIDE); /* [HGM] Only allow C & A promotions if these pieces are defined */ @@ -4346,9 +4347,11 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) break; case PB_Rook: promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteRook : BlackRook)); + if(gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove)) promoChar = PieceToChar(BlackDragon); break; case PB_Bishop: promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteBishop : BlackBishop)); + if(gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove)) promoChar = PieceToChar(BlackAlfil); break; case PB_Chancellor: promoChar = ToLower(PieceToChar(WhiteOnMove(currentMove) ? WhiteMarshall : BlackMarshall)); diff --git a/winboard/winboard.rc b/winboard/winboard.rc index 3097934..c836813 100644 --- a/winboard/winboard.rc +++ b/winboard/winboard.rc @@ -677,7 +677,7 @@ BEGIN 70,10 CONTROL "&bughouse",OPT_VariantBughouse,"Button",BS_AUTORADIOBUTTON,80,24,70, 10 - CONTROL "&Twilight",OPT_VariantTwilight,"Button",BS_AUTORADIOBUTTON,80,34,70, + CONTROL "Sp&artan",OPT_VariantTwilight,"Button",BS_AUTORADIOBUTTON,80,34,70, 10 CONTROL "&shogi",OPT_VariantShogi,"Button",BS_AUTORADIOBUTTON,80, 44,70,10 diff --git a/winboard/woptions.c b/winboard/woptions.c index 254547a..93dde9e 100644 --- a/winboard/woptions.c +++ b/winboard/woptions.c @@ -786,7 +786,7 @@ VariantWhichRadio(HWND hDlg) (IsDlgButtonChecked(hDlg, OPT_Variant3Check) ? Variant3Check : (IsDlgButtonChecked(hDlg, OPT_VariantGreat) ? VariantGreat : (IsDlgButtonChecked(hDlg, OPT_VariantGiveaway) ? VariantGiveaway : - (IsDlgButtonChecked(hDlg, OPT_VariantTwilight) ? VariantTwilight : + (IsDlgButtonChecked(hDlg, OPT_VariantTwilight) ? VariantSpartan : (IsDlgButtonChecked(hDlg, OPT_VariantMakruk) ? VariantMakruk : (IsDlgButtonChecked(hDlg, OPT_VariantSChess) ? VariantSChess : VariantNormal )))))))))))))))))))))))))))))); @@ -886,7 +886,7 @@ NewVariantDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case VariantGiveaway: CheckDlgButton(hDlg, OPT_VariantGiveaway, TRUE); break; - case VariantTwilight: + case VariantSpartan: CheckDlgButton(hDlg, OPT_VariantTwilight, TRUE); break; case VariantMakruk: diff --git a/xboard.c b/xboard.c index 1ab5f59..f3e7a76 100644 --- 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 { 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) || gameInfo.variant == VariantGiveaway) { XawDialogAddButton(dialog, _("King"), PromotionCallback, (XtPointer) dialog); diff --git a/xoptions.c b/xoptions.c index af309a1..759ea19 100644 --- a/xoptions.c +++ b/xoptions.c @@ -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} }; -- 1.7.0.4