From deb3473452a674b82d27b03fcf7e570c1cb03841 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Mon, 30 Sep 2013 00:00:43 +0200 Subject: [PATCH] Implement Chu Shogi Chu Shogi is added as a new variant, usig the extended piece set. Implement Lion double-moves. Apart from a from- and a to-square, each move now also has a kill square (all represented by X and Y coordinate). This is set on receiving a pair of partial moves (and passed around as a global; sorry about that). MakeMove uses the kill-square to remove an extra piece, and append it as ";SQUARE" to the long-algebraic move. SendMoveToProgram() converts this back to a double move of the Alien protocol (two comma-separated long-algebraic moves, stepping via SQUARE). For user input, releasing or to-clicking on a cyan square sets the kill- square, and sends a lift command to prompt the engine for the markers for the second leg. The to-click of this second leg then determines the to-square. --- Makefile.am | 2 +- backend.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++----------- common.h | 10 +++-- dialogs.c | 17 +++++----- moves.c | 9 +++-- parser.c | 4 +- 6 files changed, 104 insertions(+), 36 deletions(-) diff --git a/Makefile.am b/Makefile.am index dd88170..05fd018 100644 --- a/Makefile.am +++ b/Makefile.am @@ -139,7 +139,7 @@ dist_svg_DATA = svg/icon_white.svg svg/icon_black.svg \ svg/BlackPromoBishop.svg svg/WhitePromoBishop.svg \ svg/BlackPromoRook.svg svg/WhitePromoRook.svg \ svg/BlackPromoHorse.svg svg/WhitePromoHorse.svg \ - svg/BlackPromodragon.svg svg/WhitePromoDragon.svg \ + svg/BlackPromoDragon.svg svg/WhitePromoDragon.svg \ svg/BlackPromoSword.svg svg/WhitePromoSword.svg \ svg/BlackPromoHSword.svg svg/WhitePromoHSword.svg \ svg/BlackHCrown.svg svg/WhiteHCrown.svg \ diff --git a/backend.c b/backend.c index 4249d7c..f449d26 100644 --- a/backend.c +++ b/backend.c @@ -5055,6 +5055,11 @@ SendMoveToProgram (int moveNum, ChessProgramState *cps) if(moveList[moveNum][0]== '@') snprintf(buf, MSG_SIZ, "@@@@\n"); else snprintf(buf, MSG_SIZ, "%c@%c%d%s", moveList[moveNum][0], moveList[moveNum][2], moveList[moveNum][3] - '0', moveList[moveNum]+4); + } else if(moveList[moveNum][4] == ';') { // [HGM] lion: move is double-step over intermediate square + snprintf(buf, MSG_SIZ, "%c%d%c%d,%c%d%c%d\n", moveList[moveNum][0], moveList[moveNum][1] - '0', // convert to two moves + moveList[moveNum][5], moveList[moveNum][6] - '0', + moveList[moveNum][5], moveList[moveNum][6] - '0', + moveList[moveNum][2], moveList[moveNum][3] - '0'); } else snprintf(buf, MSG_SIZ, "%c%d%c%d%s", moveList[moveNum][0], moveList[moveNum][1] - '0', moveList[moveNum][2], moveList[moveNum][3] - '0', moveList[moveNum]+4); @@ -5230,6 +5235,8 @@ UploadGameEvent () SendToICS(ics_type == ICS_ICC ? "tag result Game in progress\n" : "commit\n"); } +static int killX = -1, killY = -1; // [HGM] lion: used for passing e.p. capture square to MakeMove + void CoordsToComputerAlgebraic (int rf, int ff, int rt, int ft, char promoChar, char move[7]) { @@ -5241,6 +5248,7 @@ CoordsToComputerAlgebraic (int rf, int ff, int rt, int ft, char promoChar, char if (promoChar == 'x' || promoChar == NULLCHAR) { sprintf(move, "%c%c%c%c\n", AAA + ff, ONE + rf, AAA + ft, ONE + rt); + if(killX >= 0 && killY >= 0) sprintf(move+4, ";%c%c\n", AAA + killX, ONE + killY); } else { sprintf(move, "%c%c%c%c%c\n", AAA + ff, ONE + rf, AAA + ft, ONE + rt, promoChar); @@ -5282,7 +5290,7 @@ Sweep (int step) if(!step) step = -1; } while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' || promoSweep == pawn || appData.testLegality && (promoSweep == king || - gameInfo.variant == VariantShogi && promoSweep != PROMOTED last && last != PROMOTED promoSweep && last != promoSweep)); + IS_SHOGI(gameInfo.variant) && promoSweep != CHUPROMOTED last && last != CHUPROMOTED promoSweep && last != promoSweep)); if(toX >= 0) { int victim = boards[currentMove][toY][toX]; boards[currentMove][toY][toX] = promoSweep; @@ -6006,8 +6014,8 @@ InitPosition (int redraw) gameInfo.boardWidth = 12; gameInfo.boardHeight = 12; nrCastlingRights = 0; - SetCharTable(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN+.+++++++++++++.+++++K" - "p.brqsexogcathd.vmlifn+.+++++++++++++.+++++k"); + SetCharTable(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN+.++.++++++++++.+++++K" + "p.brqsexogcathd.vmlifn+.++.++++++++++.+++++k"); break; case VariantCourier: pieces = CourierArray; @@ -6411,9 +6419,13 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i return FALSE; piece = boards[currentMove][fromY][fromX]; - if(gameInfo.variant == VariantShogi) { + if(gameInfo.variant == VariantChu) { + int p = piece >= BlackPawn ? BLACK_TO_WHITE piece : piece; promotionZoneSize = BOARD_HEIGHT/3; - highestPromotingPiece = (int)WhiteFerz; + highestPromotingPiece = (p >= WhiteLion || PieceToChar(piece + 22) == '.') ? WhitePawn : WhiteKing; + } else if(gameInfo.variant == VariantShogi) { + promotionZoneSize = BOARD_HEIGHT/3; + highestPromotingPiece = (int)WhiteAlfil; } else if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand) { promotionZoneSize = 3; } @@ -6477,7 +6489,7 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i } // give caller the default choice even if we will not make it *promoChoice = ToLower(PieceToChar(defaultPromoChoice)); - if(gameInfo.variant == VariantShogi) *promoChoice = (defaultPromoChoice == piece ? '=' : '+'); + if(IS_SHOGI(gameInfo.variant)) *promoChoice = (defaultPromoChoice == piece ? '=' : '+'); if( sweepSelect && gameInfo.variant != VariantGreat && gameInfo.variant != VariantGrand && gameInfo.variant != VariantSuper) return FALSE; @@ -6488,7 +6500,7 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i gameMode == IcsPlayingBlack && WhiteOnMove(currentMove); if(appData.testLegality && !premove) { moveType = LegalityTest(boards[currentMove], PosFlags(currentMove), - fromY, fromX, toY, toX, gameInfo.variant == VariantShogi ? '+' : NULLCHAR); + fromY, fromX, toY, toX, IS_SHOGI(gameInfo.variant) ? '+' : NULLCHAR); if(moveType != WhitePromotion && moveType != BlackPromotion) return FALSE; } @@ -7143,7 +7155,7 @@ CanPromote (ChessSquare piece, int y) { if(gameMode == EditPosition) return FALSE; // no promotions when editing position // some variants have fixed promotion piece, no promotion at all, or another selection mechanism - if(gameInfo.variant == VariantShogi || gameInfo.variant == VariantXiangqi || + if(IS_SHOGI(gameInfo.variant) || gameInfo.variant == VariantXiangqi || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN) return FALSE; @@ -7154,10 +7166,11 @@ CanPromote (ChessSquare piece, int y) } void -HoverEvent (int hiX, int hiY, int x, int y) +HoverEvent (int xPix, int yPix, int x, int y) { static char baseMarker[BOARD_RANKS][BOARD_FILES], baseLegal[BOARD_RANKS][BOARD_FILES]; int r, f; + if(dragging == 2) DragPieceMove(xPix, yPix); // [HGM] lion: drag without button for second leg if(!first.highlight) return; if(hiX == -1 && hiY == -1 && x == fromX && y == fromY) // record markings for(r=0; r= BOARD_RGHT) return; } - if (clickType == Release && x == fromX && y == fromY) { + if (clickType == Release && x == fromX && y == fromY && killX < 0) { DragPieceEnd(xPix, yPix); dragging = 0; if(clearFlag) { // a deferred attempt to click-click move an empty square on top of a piece @@ -7399,7 +7412,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) clearFlag = 0; - if(gameMode != EditPosition && !appData.testLegality && !legal[y][x]) { + if(gameMode != EditPosition && !appData.testLegality && !legal[y][x] && (x != killX || y != killY)) { if(dragging) DragPieceEnd(xPix, yPix), dragging = 0; DisplayMessage(_("only marked squares are legal"),""); DrawPosition(TRUE, NULL); @@ -7421,11 +7434,19 @@ LeftClick (ClickType clickType, int xPix, int yPix) if(x >= BOARD_LEFT && x < BOARD_RGHT) clearFlag = 1; // and defer click-click move of empty-square to up-click return; } + if(dragging == 2) { // [HGM] lion: just turn buttonless drag into normal drag, and let release to the job + dragging = 1; + return; + } + if(x == killX && y == killY) { // second click on this square, which was selected as first-leg target + killX = killY = -1; // this informs us no second leg is coming, so treat as to-click without intermediate + } else + if(marker[y][x] == 5) return; // [HGM] lion: to-click on cyan square; defer action to release if(legal[y][x] == 2 || HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, FALSE)) { if(appData.sweepSelect) { ChessSquare piece = boards[currentMove][fromY][fromX]; promoSweep = defaultPromoChoice; - if(PieceToChar(PROMOTED piece) == '+') promoSweep = PROMOTED piece; + if(PieceToChar(CHUPROMOTED piece) == '+') promoSweep = CHUPROMOTED piece; selectFlag = 0; lastX = xPix; lastY = yPix; Sweep(0); // Pawn that is going to promote: preview promotion piece sweepSelecting = 1; @@ -7450,6 +7471,16 @@ LeftClick (ClickType clickType, int xPix, int yPix) ClearHighlights(); } #endif + if(!dragging || marker[y][x] == 5) { // [HGM] lion: this was the release of a to-click or drag on a cyan square + dragging *= 2; // flag button-less dragging if we are dragging + MarkTargetSquares(1); + if(x == killX && y == killY) killX = killY = -1; else { + killX = x; killY = y; //remeber this square as intermediate + ReportClick("put", x, y); // and inform engine + ReportClick("lift", x, y); + return; + } + } DragPieceEnd(xPix, yPix); dragging = 0; /* Don't animate move and drag both */ appData.animate = FALSE; @@ -8224,6 +8255,7 @@ static char stashedInputMove[MSG_SIZ]; void HandleMachineMove (char *message, ChessProgramState *cps) { + static char firstLeg[20]; char machineMove[MSG_SIZ], buf1[MSG_SIZ*10], buf2[MSG_SIZ]; char realname[MSG_SIZ]; int fromX, fromY, toX, toY; @@ -8366,6 +8398,24 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } if(cps->alphaRank) AlphaRank(machineMove, 4); + + // [HGM] lion: (some very limited) support for Alien protocol + killX = killY = -1; + if(machineMove[strlen(machineMove)-1] == ',') { // move ends in coma: non-final leg of composite move + safeStrCpy(firstLeg, machineMove, 20); // just remember it for processing when second leg arrives + return; + } else if(firstLeg[0]) { // there was a previous leg; + // only support case where same piece makes two step (and don't even test that!) + char buf[20], *p = machineMove+1, *q = buf+1, f; + safeStrCpy(buf, machineMove, 20); + while(isdigit(*q)) q++; // find start of to-square + safeStrCpy(machineMove, firstLeg, 20); + while(isdigit(*p)) p++; + safeStrCpy(p, q, 20); // glue to-square of second leg to from-square of first, to process over-all move + sscanf(buf, "%c%d", &f, &killY); killX = f - AAA; killY -= ONE - '0'; // pass intermediate square to MakeMove in global + firstLeg[0] = NULLCHAR; + } + if (!ParseOneMove(machineMove, forwardMostMove, &moveType, &fromX, &fromY, &toX, &toY, &promoChar)) { /* Machine move could not be parsed; ignore it. */ @@ -9579,6 +9629,10 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) } else { int i; + if( killX >= 0 && killY >= 0 ) // [HGM] lion: Lion trampled over something + board[killY][killX] = EmptySquare, + board[EP_STATUS] = EP_CAPTURE; + if( board[toY][toX] != EmptySquare ) board[EP_STATUS] = EP_CAPTURE; @@ -9762,8 +9816,9 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) board[fromY][fromX+1] = EmptySquare; } } else { - board[toY][toX] = board[fromY][fromX]; + ChessSquare piece = board[fromY][fromX]; // [HGM] lion: allow for igui (where from == to) board[fromY][fromX] = EmptySquare; + board[toY][toX] = piece; } } @@ -9846,7 +9901,7 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) } else if(promoChar == '+') { /* [HGM] Shogi-style promotions, to piece implied by original (Might overwrite ordinary Pawn promotion) */ - board[toY][toX] = (ChessSquare) (PROMOTED piece); + board[toY][toX] = (ChessSquare) (CHUPROMOTED piece); } else if(!appData.testLegality && promoChar != NULLCHAR && promoChar != '=') { // without legality testing, unconditionally believe promoChar ChessSquare newPiece = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar)); if((newPiece <= WhiteMan || newPiece >= BlackPawn && newPiece <= BlackMan) // unpromoted piece specified @@ -9872,12 +9927,18 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) void MakeMove (int fromX, int fromY, int toX, int toY, int promoChar) { + int x = toX, y = toY; + char *s = parseList[forwardMostMove]; + ChessSquare p = boards[forwardMostMove][toY][toX]; // forwardMostMove++; // [HGM] bare: moved downstream + if(killX >= 0 && killY >= 0) x = killX, y = killY; // [HGM] lion: make SAN move to intermediate square, if there is one (void) CoordsToAlgebraic(boards[forwardMostMove], PosFlags(forwardMostMove), - fromY, fromX, toY, toX, promoChar, - parseList[forwardMostMove]); + fromY, fromX, y, x, promoChar, + s); + if(killX >= 0 && killY >= 0) + sprintf(s + strlen(s), "%c%c%d", p == EmptySquare || toX == fromX && toY == fromY ? '-' : 'x', toX + AAA, toY + ONE - '0'); if(serverMoves != NULL) { /* [HGM] write moves on file for broadcasting (should be separate routine, really) */ int timeLeft; static int lastLoadFlag=0; int king, piece; @@ -9973,6 +10034,7 @@ MakeMove (int fromX, int fromY, int toX, int toY, int promoChar) break; } + killX = killY = -1; // [HGM] lion: used up } /* Updates currentMove if not pausing */ @@ -17489,7 +17551,7 @@ ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize) if(*p=='+') { piece = CharToPiece(*++p); if(piece == EmptySquare) return FALSE; /* unknown piece */ - piece = (ChessSquare) (PROMOTED piece ); p++; + piece = (ChessSquare) (CHUPROMOTED piece ); p++; if(PieceToChar(piece) != '+') return FALSE; /* unpromotable piece */ } else piece = CharToPiece(*p++); diff --git a/common.h b/common.h index 7f3c4f8..f06fbcf 100644 --- a/common.h +++ b/common.h @@ -248,17 +248,17 @@ typedef enum { WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, WhiteFerz, WhiteAlfil, WhiteAngel, WhiteMarshall, WhiteWazir, WhiteMan, WhiteCannon, WhiteNightrider, WhiteCardinal, WhiteDragon, WhiteGrasshopper, - WhiteSilver, WhiteFalcon, WhiteLance, WhiteCobra, WhiteUnicorn, WhiteNothing, + WhiteSilver, WhiteFalcon, WhiteLance, WhiteCobra, WhiteUnicorn, WhiteLion, WhiteTokin, WhiteDagger, WhitePCardinal, WhitePDragon, WhiteCat, - WhitePSword, WhiteMonarch, WhiteMother, WhiteLion, WhitePRook, WhitePDagger, + WhitePSword, WhiteMonarch, WhiteMother, WhiteNothing, WhitePRook, WhitePDagger, WhiteDolphin, WhiteVacant, WhiteHorned, WhiteEagle, WhiteSword, WhiteSkip, WhiteCrown, WhiteHorse, WhiteDrunk, WhitePBishop, WhiteKing, BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen, BlackFerz, BlackAlfil, BlackAngel, BlackMarshall, BlackWazir, BlackMan, BlackCannon, BlackNightrider, BlackCardinal, BlackDragon, BlackGrasshopper, - BlackSilver, BlackFalcon, BlackLance, BlackCobra, BlackUnicorn, BlackNothing, + BlackSilver, BlackFalcon, BlackLance, BlackCobra, BlackUnicorn, BlackLion, BlackTokin, BlackDagger, BlackPCardinal, BlackPDragon, BlackCat, - BlackPSword, BlackMonarch, BlackMother, BlackLion, BlackPRook, BlackPDagger, + BlackPSword, BlackMonarch, BlackMother, BlackNothin, BlackPRook, BlackPDagger, BlackDolphin, BlackVacant, BlackHorned, BlackEagle, BlackSword, BlackSkip, BlackCrown, BlackHorse, BlackDrunk, BlackPBishop, BlackKing, EmptySquare, DarkSquare, @@ -272,6 +272,8 @@ typedef enum { #define PROMOTED (int)WhiteDragon - (int)WhiteRook + (int) #define DEMOTED (int)WhiteRook - (int)WhiteDragon + (int) #define SHOGI (int)EmptySquare + (int) +#define CHUPROMOTED ((int)WhitePDragon - (int)WhiteDragon)*(gameInfo.variant == VariantChu) + PROMOTED +#define IS_SHOGI(V) ((V) == VariantShogi || (V) == VariantChu) typedef ChessSquare Board[BOARD_RANKS][BOARD_FILES]; diff --git a/dialogs.c b/dialogs.c index cf94dc9..4db3da7 100644 --- a/dialogs.c +++ b/dialogs.c @@ -444,10 +444,11 @@ static Option variantDescriptors[] = { { VariantLosers, 0, 135, NULL, (void*) &Pick, "#FFFFBF", NULL, Button, N_("Losers")}, { VariantShogi, SAME_ROW, 135, NULL, (void*) &Pick, "#BFFFFF", NULL, Button, N_("Shogi (9x9)")}, { VariantSpartan, 0, 135, NULL, (void*) &Pick, "#FF0000", NULL, Button, N_("Spartan")}, -{ VariantXiangqi, SAME_ROW,135, NULL, (void*) &Pick, "#BFFFFF", NULL, Button, N_("Xiangqi (9x10)")}, -{ VariantFairy, 0, 135, NULL, (void*) &Pick, "#BFBFBF", NULL, Button, N_("Fairy")}, -//{ VariantNormal, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, " "}, // dummy, to have good alignment -{ VariantCourier, SAME_ROW,135, NULL, (void*) &Pick, "#BFFFBF", NULL, Button, N_("Courier (12x8)")}, +{ VariantXiangqi, SAME_ROW,135, NULL, (void*) &Pick, "#BFFFFF", NULL, Button, N_("xiangqi (9x10)")}, +{ VariantFairy, 0, 135, NULL, (void*) &Pick, "#BFBFBF", NULL, Button, N_("fairy")}, +{ VariantCourier, SAME_ROW,135, NULL, (void*) &Pick, "#BFFFBF", NULL, Button, N_("courier (12x8)")}, +{ VariantNormal, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_(" ")}, // dummy, to have good alignment +{ VariantChu, SAME_ROW, 135, NULL, (void*) &Pick, "#BFFFBF", NULL, Button, N_("chu shogi (12x12)")}, // optional buttons for engine-defined variants { VariantUnknown, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL }, { VariantUnknown, SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL }, @@ -2169,16 +2170,16 @@ static Option * Exp (int n, int x, int y) { static int but1, but3, oldW, oldH; - int menuNr = -3, sizing; + int menuNr = -3, sizing, f, r; if(n == 0) { // motion if(SeekGraphClick(Press, x, y, 1)) return NULL; if(but1 && !PromoScroll(x, y)) DragPieceMove(x, y); if(but3) MovePV(x, y, lineGap + BOARD_HEIGHT * (squareSize + lineGap)); if(appData.highlightDragging) { - x = EventToSquare(x, BOARD_WIDTH); if ( flipView && x >= 0) x = BOARD_WIDTH - 1 - x; - y = EventToSquare(y, BOARD_HEIGHT); if (!flipView && y >= 0) y = BOARD_HEIGHT - 1 - y; - HoverEvent(hi2X, hi2Y, x, y); + f = EventToSquare(x, BOARD_WIDTH); if ( flipView && f >= 0) f = BOARD_WIDTH - 1 - f; + r = EventToSquare(y, BOARD_HEIGHT); if (!flipView && r >= 0) r = BOARD_HEIGHT - 1 - r; + HoverEvent(x, y, f, r); } return NULL; } diff --git a/moves.c b/moves.c index e6e8e1a..381b188 100644 --- a/moves.c +++ b/moves.c @@ -1136,7 +1136,7 @@ LegalityTest (Board board, int flags, int rf, int ff, int rt, int ft, int promoC if(board[BOARD_HEIGHT-1-PieceToNumber(CharToPiece(ToLower(promoChar)))][1] == 0) return ImpossibleMove; } } else - if(gameInfo.variant == VariantShogi) { + if(IS_SHOGI(gameInfo.variant)) { /* [HGM] Shogi promotions. '=' means defer */ if(rf != DROP_RANK && cl.kind == NormalMove) { ChessSquare piece = board[rf][ff]; @@ -1367,6 +1367,9 @@ Disambiguate (Board board, int flags, DisambiguateClosure *closure) if(board[BOARD_HEIGHT-1-PieceToNumber(CharToPiece(ToLower(c)))][1] == 0) closure->kind = ImpossibleMove; } } else + if(gameInfo.variant == VariantChu) { + if(c == '+') closure->kind = (flags & F_WHITE_ON_MOVE ? WhitePromotion : BlackPromotion); // for now, accept any + } else if(gameInfo.variant == VariantShogi) { /* [HGM] Shogi promotions. On input, '=' means defer, '+' promote. Afterwards, c is set to '+' for promotions, NULL other */ if(closure->rfIn != DROP_RANK && closure->kind == NormalMove) { @@ -1528,7 +1531,7 @@ CoordsToAlgebraic (Board board, int flags, int rf, int ff, int rt, int ft, int p /* Use promotion suffix style "=Q" */ *outp = NULLCHAR; if (promoChar != NULLCHAR) { - if(gameInfo.variant == VariantShogi) { + if(IS_SHOGI(gameInfo.variant)) { /* [HGM] ... but not in Shogi! */ *outp++ = promoChar == '=' ? '=' : '+'; } else { @@ -1626,7 +1629,7 @@ CoordsToAlgebraic (Board board, int flags, int rf, int ff, int rt, int ft, int p if(rt+ONE <= '9') *outp++ = rt + ONE; else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; } - if (gameInfo.variant == VariantShogi) { + if (IS_SHOGI(gameInfo.variant)) { /* [HGM] in Shogi non-pawns can promote */ *outp++ = promoChar; // Don't bother to correct move type, return value is never used! } diff --git a/parser.c b/parser.c index 6da13d4..ada3509 100644 --- a/parser.c +++ b/parser.c @@ -151,7 +151,7 @@ PromoSuffix (char **p) { char *start = *p; if(**p == 'e' && (Match("ep", p) || Match("e.p.", p))) { *p = start; return NULLCHAR; } // non-compliant e.p. suffix is no promoChar! - if(**p == '+' && gameInfo.variant == VariantShogi) { (*p)++; return '+'; } + if(**p == '+' && IS_SHOGI(gameInfo.variant)) { (*p)++; return '+'; } if(**p == '=' || (gameInfo.variant == VariantSChess) && **p == '/') (*p)++; // optional = (or / for Seirawan gating) if(**p == '(' && (*p)[2] == ')' && isalpha( (*p)[1] )) { (*p) += 3; return ToLower((*p)[-2]); } if(isalpha(**p)) return ToLower(*(*p)++); @@ -236,7 +236,7 @@ NextUnit (char **p) } else if(n == 1 && type[0] == NUMERIC && coord[0] > 1) { while(**p == '.') (*p)++; return Nothing; } // fast exit for move numbers if(n == 4 && type[2] != type[3] && // we have a valid to-square (kludge: type[3] can be NOTHING on fxg type move) (piece || !promoted) && // promoted indicator only valid on named piece type - (type[2] == ALPHABETIC || gameInfo.variant == VariantShogi)) { // in Shogi also allow alphabetic rank + (type[2] == ALPHABETIC || IS_SHOGI(gameInfo.variant))) { // in Shogi also allow alphabetic rank DisambiguateClosure cl; int fromX, fromY, toX, toY; -- 1.7.0.4