From: H.G. Muller Date: Wed, 13 Jan 2010 18:08:45 +0000 (+0100) Subject: Add variant Makruk X-Git-Tag: v4.4.3.20100220~11 X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=4a8f93572feb1fc3571887ceecc14d8caac3ced0;p=xboard.git Add variant Makruk Thai Chess, played by 2 million world-wide. Required pawn promotion to happen in a zone, and the Alfil to move as Shogi Silver, a new opening array, and unusual Pawn placement. Because of the latter, I consider it a setup position, so a FEN will always be sent to the engine. --- diff --git a/backend.c b/backend.c index ecf338c..91bc82d 100644 --- a/backend.c +++ b/backend.c @@ -355,6 +355,7 @@ PosFlags(index) case VariantNoCastle: case VariantShatranj: case VariantCourier: + case VariantMakruk: flags &= ~F_ALL_CASTLE_OK; break; default: @@ -490,6 +491,13 @@ ChessSquare ShatranjArray[2][BOARD_SIZE] = { /* [HGM] (movGen knows about Shatra BlackFerz, BlackAlfil, BlackKnight, BlackRook } }; +ChessSquare makrukArray[2][BOARD_SIZE] = { /* [HGM] (movGen knows about Shatranj Q and P) */ + { WhiteRook, WhiteKnight, WhiteMan, WhiteKing, + WhiteFerz, WhiteMan, WhiteKnight, WhiteRook }, + { BlackRook, BlackKnight, BlackMan, BlackFerz, + BlackKing, BlackMan, BlackKnight, BlackRook } +}; + #if (BOARD_SIZE>=10) ChessSquare ShogiArray[2][BOARD_SIZE] = { @@ -875,6 +883,7 @@ InitBackEnd1() case VariantAtomic: /* should work except for win condition */ case Variant3Check: /* should work except for win condition */ case VariantShatranj: /* should work except for all win conditions */ + case VariantMakruk: /* should work except for daw countdown */ case VariantBerolina: /* might work if TestLegality is off */ case VariantCapaRandom: /* should work */ case VariantJanus: /* should work */ @@ -4196,7 +4205,7 @@ SendMoveToICS(moveType, fromX, fromY, toX, toY) case BlackPromotionChancellor: case WhitePromotionArchbishop: case BlackPromotionArchbishop: - if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier) + if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk) sprintf(user_move, "%c%c%c%c=%c\n", AAA + fromX, ONE + fromY, AAA + toX, ONE + toY, PieceToChar(WhiteFerz)); @@ -4679,6 +4688,12 @@ InitPosition(redraw) nrCastlingRights = 0; SetCharTable(pieceToChar, "PN.R.QB...Kpn.r.qb...k"); break; + case VariantMakruk: + pieces = makrukArray; + nrCastlingRights = 0; + startedFromSetupPosition = TRUE; + SetCharTable(pieceToChar, "PN.R.M....SKpn.r.m....sk"); + break; case VariantTwoKings: pieces = twoKingsArray; break; @@ -4792,6 +4807,7 @@ InitPosition(redraw) pawnRow = gameInfo.boardHeight - 7; /* seems to work in all common variants */ if(pawnRow < 1) pawnRow = 1; + if(gameInfo.variant == VariantMakruk) pawnRow = 2; /* User pieceToChar list overrules defaults */ if(appData.pieceToCharTable != NULL) @@ -4977,6 +4993,8 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice) if(gameInfo.variant == VariantShogi) { promotionZoneSize = 3; highestPromotingPiece = (int)WhiteFerz; + } else if(gameInfo.variant == VariantMakruk) { + promotionZoneSize = 3; } // next weed out all moves that do not touch the promotion zone at all @@ -5020,7 +5038,7 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice) } // we either have a choice what to promote to, or (in Shogi) whether to promote - if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier) { + if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk) { *promoChoice = PieceToChar(BlackFerz); // no choice return FALSE; } @@ -7375,6 +7393,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board, castling, ep) char *ep; { ChessSquare captured = board[toY][toX], piece, king; int p, oldEP = EP_NONE, berolina = 0; + int promoRank = gameInfo.variant == VariantMakruk ? 3 : 1; /* [HGM] compute & store e.p. status and castling rights for new position */ /* we can always do that 'in place', now pointers to these rights are passed to ApplyMove */ @@ -7421,7 +7440,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board, castling, ep) } /* [HGM] In Shatranj and Courier all promotions are to Ferz */ - if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier) + if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier || gameInfo.variant == VariantMakruk) && promoChar != 0) promoChar = PieceToChar(WhiteFerz); if (fromX == toX && fromY == toY) return; @@ -7472,7 +7491,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board, castling, ep) board[toY][toX+1] = board[fromY][BOARD_LEFT]; board[fromY][BOARD_LEFT] = EmptySquare; } else if (board[fromY][fromX] == WhitePawn - && toY == BOARD_HEIGHT-1 + && toY >= BOARD_HEIGHT-promoRank && gameInfo.variant != VariantXiangqi ) { /* white pawn promotion */ @@ -7536,13 +7555,13 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board, castling, ep) board[fromY][0] = EmptySquare; board[toY][2] = BlackRook; } else if (board[fromY][fromX] == BlackPawn - && toY == 0 + && toY < promoRank && gameInfo.variant != VariantXiangqi ) { /* black pawn promotion */ - board[0][toX] = CharToPiece(ToLower(promoChar)); - if (board[0][toX] == EmptySquare) { - board[0][toX] = BlackQueen; + board[toY][toX] = CharToPiece(ToLower(promoChar)); + if (board[toY][toX] == EmptySquare) { + board[toY][toX] = BlackQueen; } if(gameInfo.variant==VariantBughouse || gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */ @@ -11391,7 +11410,8 @@ EditPositionMenuEvent(selection, x, y) case BlackQueen: if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantXiangqi || - gameInfo.variant == VariantCourier ) + gameInfo.variant == VariantCourier || + gameInfo.variant == VariantMakruk ) selection = (ChessSquare)((int)selection - (int)WhiteQueen + (int)WhiteFerz); goto defaultlabel; @@ -13747,7 +13767,7 @@ PositionToFEN(move, overrideCastling) } if(gameInfo.variant != VariantShogi && gameInfo.variant != VariantXiangqi && - gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier ) { + gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier && gameInfo.variant != VariantMakruk ) { /* En passant target square */ if (move > backwardMostMove) { fromX = moveList[move - 1][0] - AAA; @@ -14017,7 +14037,7 @@ ParseFEN(board, blackPlaysFirst, fen) /* read e.p. field in games that know e.p. capture */ if(gameInfo.variant != VariantShogi && gameInfo.variant != VariantXiangqi && - gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier ) { + gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier && gameInfo.variant != VariantMakruk ) { if(*p=='-') { p++; FENepStatus = EP_NONE; } else { diff --git a/common.h b/common.h index 0f50acd..e98d93f 100644 --- a/common.h +++ b/common.h @@ -294,6 +294,7 @@ typedef enum { VariantSuper, VariantGreat, VariantTwilight, + VariantMakruk, VariantUnknown /* Catchall for other unknown variants */ } VariantClass; @@ -336,6 +337,7 @@ typedef enum { "super",\ "great",\ "twilight",\ + "makruk",\ "unknown" \ } diff --git a/moves.c b/moves.c index 319a332..75b9434 100644 --- a/moves.c +++ b/moves.c @@ -260,6 +260,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) { int rf, ff; int i, j, d, s, fs, rs, rt, ft, m; + int promoRank = gameInfo.variant == VariantMakruk ? 3 : 1; for (rf = 0; rf < BOARD_HEIGHT; rf++) for (ff = BOARD_LEFT; ff < BOARD_RGHT; ff++) { @@ -303,7 +304,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) } if (rf < BOARD_HEIGHT-1 && board[rf + 1][ff] == EmptySquare) { callback(board, flags, - rf == BOARD_HEIGHT-2 ? WhitePromotionQueen : NormalMove, + rf >= BOARD_HEIGHT-1-promoRank ? WhitePromotionQueen : NormalMove, rf, ff, rf + 1, ff, closure); } if (rf == 1 && board[2][ff] == EmptySquare && @@ -318,7 +319,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) ((flags & F_KRIEGSPIEL_CAPTURE) || BlackPiece(board[rf + 1][ff + s]))) { callback(board, flags, - rf == BOARD_HEIGHT-2 ? WhitePromotionQueen : NormalMove, + rf >= BOARD_HEIGHT-1-promoRank ? WhitePromotionQueen : NormalMove, rf, ff, rf + 1, ff + s, closure); } if (rf == BOARD_HEIGHT-4) { @@ -353,7 +354,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) } if (rf > 0 && board[rf - 1][ff] == EmptySquare) { callback(board, flags, - rf == 1 ? BlackPromotionQueen : NormalMove, + rf <= promoRank ? BlackPromotionQueen : NormalMove, rf, ff, rf - 1, ff, closure); } if (rf == BOARD_HEIGHT-2 && board[BOARD_HEIGHT-3][ff] == EmptySquare && @@ -368,7 +369,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) ((flags & F_KRIEGSPIEL_CAPTURE) || WhitePiece(board[rf - 1][ff + s]))) { callback(board, flags, - rf == 1 ? BlackPromotionQueen : NormalMove, + rf <= promoRank ? BlackPromotionQueen : NormalMove, rf, ff, rf - 1, ff + s, closure); } if (rf == 3) { @@ -608,6 +609,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) /* Shogi Pawn and Silver General: first the Pawn move, */ /* then the General continues like a Ferz */ + case WhiteMan: + if(gameInfo.variant != VariantMakruk) goto commoner; case SHOGI WhitePawn: case SHOGI WhiteFerz: if (rf < BOARD_HEIGHT-1 && @@ -617,6 +620,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) if(piece != SHOGI WhitePawn) goto finishSilver; break; + case BlackMan: + if(gameInfo.variant != VariantMakruk) goto commoner; case SHOGI BlackPawn: case SHOGI BlackFerz: if (rf > 0 && @@ -644,8 +649,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) case WhiteSilver: case BlackSilver: m++; // [HGM] superchess: use for Centaur - case WhiteMan: - case BlackMan: + commoner: case SHOGI WhiteKing: case SHOGI BlackKing: case WhiteKing: diff --git a/parser.l b/parser.l index 788c93c..d3585c7 100755 --- a/parser.l +++ b/parser.l @@ -317,7 +317,7 @@ extern void CopyBoard P((Board to, Board from)); if (currentMoveString[4] == NULLCHAR && (result == WhitePromotionKnight || result == BlackPromotionKnight || result == WhitePromotionQueen || result == BlackPromotionQueen)) { - if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier) + if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk) currentMoveString[4] = PieceToChar(BlackFerz); else if(gameInfo.variant == VariantGreat) currentMoveString[4] = PieceToChar(BlackMan); @@ -505,7 +505,7 @@ extern void CopyBoard P((Board to, Board from)); result == WhitePromotionKnight || result == BlackPromotionKnight)) { currentMoveString[4] = PieceToChar(BlackQueen); // [HGM] shatranj: take care of variants without Queen - if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier) + if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk) currentMoveString[4] = PieceToChar(BlackFerz); if(gameInfo.variant == VariantGreat) currentMoveString[4] = PieceToChar(BlackMan); diff --git a/winboard/help/html/18.htm b/winboard/help/html/18.htm index 81a8f79..801f04f 100644 --- a/winboard/help/html/18.htm +++ b/winboard/help/html/18.htm @@ -82,6 +82,8 @@ atomicCapturing piece explodes (ICC wild 27) knightmateKing moves a Knight, and vice versa +makrukThai Chess (shatranj-like, pawns promote on 6th rank) + superSuperchess, a shuffle variant with B+N, R+N, K+N and Q+N compound greatGreat Shatranj, whithout sliders, on 10x8 board (legality testing off!) diff --git a/winboard/resource.h b/winboard/resource.h index 744509d..1dfcbf5 100644 --- a/winboard/resource.h +++ b/winboard/resource.h @@ -480,6 +480,7 @@ #define OPT_Variant3Check 1526 #define OPT_VariantGreat 1527 #define OPT_VariantTwilight 1528 +#define OPT_VariantMakruk 1529 #define IDC_Files 1550 #define IDC_Ranks 1551 #define IDC_Holdings 1552 diff --git a/winboard/winboard.rc b/winboard/winboard.rc index c61067b..1c17817 100644 --- a/winboard/winboard.rc +++ b/winboard/winboard.rc @@ -673,6 +673,8 @@ BEGIN 84,50,10 CONTROL "&fairy",OPT_VariantFairy,"Button",BS_AUTORADIOBUTTON,70, 94,50,10 + CONTROL "&makruk",OPT_VariantMakruk,"Button",BS_AUTORADIOBUTTON,70, + 104,50,10 CONTROL "&gothic",OPT_VariantGothic,"Button",BS_AUTORADIOBUTTON,134,14, 50,10 CONTROL "&capablanca",OPT_VariantCapablanca,"Button",BS_AUTORADIOBUTTON,134, diff --git a/winboard/woptions.c b/winboard/woptions.c index c7c6e6f..379a8d6 100644 --- a/winboard/woptions.c +++ b/winboard/woptions.c @@ -773,7 +773,8 @@ VariantWhichRadio(HWND hDlg) (IsDlgButtonChecked(hDlg, OPT_VariantGreat) ? VariantGreat : (IsDlgButtonChecked(hDlg, OPT_VariantGiveaway) ? VariantGiveaway : (IsDlgButtonChecked(hDlg, OPT_VariantTwilight) ? VariantTwilight : - VariantNormal )))))))))))))))))))))))))))); + (IsDlgButtonChecked(hDlg, OPT_VariantMakruk) ? VariantMakruk : + VariantNormal ))))))))))))))))))))))))))))); } LRESULT CALLBACK @@ -872,6 +873,9 @@ NewVariantDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case VariantTwilight: CheckDlgButton(hDlg, OPT_VariantTwilight, TRUE); break; + case VariantMakruk: + CheckDlgButton(hDlg, OPT_VariantMakruk, TRUE); + break; default: ; } diff --git a/xboard.texi b/xboard.texi index bd56944..57e9fe4 100644 --- a/xboard.texi +++ b/xboard.texi @@ -2210,6 +2210,7 @@ berolina Pawns capture straight ahead, and move diagonal cylinder Pieces wrap around the board edge knightmate King moves as Knight, and vice versa super Superchess (shuffle variant with 4 exo-pieces) +makruk Thai Chess (shatranj-like, P promotes on 6th rank) fairy A catchall variant in which all piece types known to XBoard can participate (8x8) unknown Catchall for other unknown variants diff --git a/xoptions.c b/xoptions.c index f662257..8a7e546 100644 --- a/xoptions.c +++ b/xoptions.c @@ -908,6 +908,7 @@ struct NewVarButton buttonDesc[] = { {N_("berolina"), "#FFFFFF", 0, VariantBerolina}, {N_("cylinder"), "#FFFFFF", 0, VariantCylinder}, {N_("shatranj"), "#FFFFFF", 0, VariantShatranj}, + {N_("makruk"), "#FFFFFF", 0, VariantMakruk}, {N_("atomic"), "#FFFFFF", 0, VariantAtomic}, {N_("two kings"), "#FFFFFF", 0, VariantTwoKings}, {N_("3-checks"), "#FFFFFF", 0, Variant3Check},