Fix reading of startposition FEN starting with *
[xboard.git] / backend.c
index 674a9d3..6cd2224 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -5399,8 +5399,8 @@ Sweep (int step)
        if(step && !(toggleFlag && Partner(&promoSweep))) promoSweep -= step;
        if(promoSweep == EmptySquare) promoSweep = BlackPawn; // wrap
        else if((int)promoSweep == -1) promoSweep = WhiteKing;
-       else if(promoSweep == BlackPawn && step < 0) promoSweep = WhitePawn;
-       else if(promoSweep == WhiteKing && step > 0) promoSweep = BlackKing;
+       else if(promoSweep == BlackPawn && step < 0 && !toggleFlag) promoSweep = WhitePawn;
+       else if(promoSweep == WhiteKing && step > 0 && !toggleFlag) promoSweep = BlackKing;
        if(!step) step = -1;
     } while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' || promoSweep == pawn ||
            !toggleFlag && PieceToChar(promoSweep) == '+' || // skip promoted versions of other
@@ -5527,7 +5527,12 @@ ParseOneMove (char *move, int moveNum, ChessMove *moveType, int *fromX, int *fro
       case BlackASideCastleFR:
       /* End of code added by Tord */
       case IllegalMove:                /* bug or odd chess variant */
-       if(currentMoveString[1] == '@') goto drop; // illegal drop
+       if(currentMoveString[1] == '@') { // illegal drop
+         *fromX = WhiteOnMove(moveNum) ?
+           (int) CharToPiece(ToUpper(currentMoveString[0])) :
+           (int) CharToPiece(ToLower(currentMoveString[0]));
+         goto drop;
+       }
         *fromX = currentMoveString[0] - AAA;
         *fromY = currentMoveString[1] - ONE;
         *toX = currentMoveString[2] - AAA;
@@ -5551,10 +5556,10 @@ ParseOneMove (char *move, int moveNum, ChessMove *moveType, int *fromX, int *fro
 
       case WhiteDrop:
       case BlackDrop:
-      drop:
        *fromX = *moveType == WhiteDrop ?
          (int) CharToPiece(ToUpper(currentMoveString[0])) :
          (int) CharToPiece(ToLower(currentMoveString[0]));
+      drop:
        *fromY = DROP_RANK;
         *toX = currentMoveString[2] - AAA;
         *toY = currentMoveString[3] - ONE;
@@ -6561,7 +6566,7 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i
         promotionZoneSize = BOARD_HEIGHT/3;
         highestPromotingPiece = (p >= WhiteLion || PieceToChar(piece + 22) == '.') ? WhitePawn : WhiteLion;
     } else if(gameInfo.variant == VariantShogi) {
-        promotionZoneSize = BOARD_HEIGHT/3;
+        promotionZoneSize = BOARD_HEIGHT/3 +(BOARD_HEIGHT == 8);
         highestPromotingPiece = (int)WhiteAlfil;
     } else if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess) {
         promotionZoneSize = 3;
@@ -7519,7 +7524,7 @@ printf("to click %d,%d\n",x,y);
        toP = boards[currentMove][y][x];
        frc = appData.fischerCastling || gameInfo.variant == VariantSChess;
        if( (killX < 0 || x != fromX || y != fromY) && // [HGM] lion: do not interpret igui as deselect!
-           legal[y][x] == 0 && // if engine told we can move to here, do it even if own piece
+           marker[y][x] == 0 && // if engine told we can move to here, do it even if own piece
           ((WhitePawn <= fromP && fromP <= WhiteKing &&
             WhitePawn <= toP && toP <= WhiteKing &&
             !(fromP == WhiteKing && toP == WhiteRook && frc) &&
@@ -7551,7 +7556,7 @@ printf("to click %d,%d\n",x,y);
                else gatingPiece = doubleClick ? fromP : EmptySquare;
                fromX = x;
                fromY = y; dragging = 1;
-               ReportClick("lift", x, y);
+               if(!second) ReportClick("lift", x, y);
                MarkTargetSquares(0);
                DragPieceBegin(xPix, yPix, FALSE);
                if(appData.sweepSelect && CanPromote(piece = boards[currentMove][y][x], y)) {
@@ -7574,7 +7579,7 @@ printf("A type=%d\n",clickType);
        return;
     }
 
-    if (clickType == Release && x == fromX && y == fromY && killX < 0) {
+    if (clickType == Release && x == fromX && y == fromY && killX < 0 && !sweepSelecting) {
        DragPieceEnd(xPix, yPix); dragging = 0;
        if(clearFlag) {
            // a deferred attempt to click-click move an empty square on top of a piece
@@ -7588,10 +7593,9 @@ printf("A type=%d\n",clickType);
            /* Undo animation damage if any */
            DrawPosition(FALSE, NULL);
        }
-       if (second || sweepSelecting) {
+       if (second) {
            /* Second up/down in same square; just abort move */
-           if(sweepSelecting) DrawPosition(FALSE, boards[currentMove]);
-           second = sweepSelecting = 0;
+           second = 0;
            fromX = fromY = -1;
            gatingPiece = EmptySquare;
            MarkTargetSquares(1);
@@ -7726,7 +7730,9 @@ printf("(%d,%d)-(%d,%d) %d %d\n",fromX,fromY,toX,toY,x,y);
 
     if(gatingPiece != EmptySquare && gameInfo.variant == VariantSChess) promoChoice = ToLower(PieceToChar(gatingPiece));
 
-    if (HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, appData.sweepSelect)) {
+    if(legal[toY][toX] == 2) promoChoice = ToLower(PieceToChar(defaultPromoChoice)); // highlight-induced promotion
+
+    if (legal[toY][toX] == 2 && !appData.sweepSelect || HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, appData.sweepSelect)) {
        SetHighlights(fromX, fromY, toX, toY);
         MarkTargetSquares(1);
        if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand) {
@@ -12069,8 +12075,13 @@ LoadGameOneMove (ChessMove readAhead)
            if (appData.debugMode)
              fprintf(debugFP, "Parsed %s into IllegalMove %s\n",
                      yy_text, currentMoveString);
-            fromX = currentMoveString[0] - AAA;
-            fromY = currentMoveString[1] - ONE;
+            if(currentMoveString[1] == '@') {
+                fromX = CharToPiece(WhiteOnMove(currentMove) ? ToUpper(currentMoveString[0]) : ToLower(currentMoveString[0]));
+                fromY = DROP_RANK;
+            } else {
+                fromX = currentMoveString[0] - AAA;
+                fromY = currentMoveString[1] - ONE;
+            }
             toX = currentMoveString[2] - AAA;
             toY = currentMoveString[3] - ONE;
            promoChar = currentMoveString[4];
@@ -12687,7 +12698,10 @@ LoadGame (FILE *f, int gameNumber, char *title, int useList)
     int numPGNTags = 0;
     int err, pos = -1;
     GameMode oldGameMode;
-    VariantClass oldVariant = gameInfo.variant; /* [HGM] PGNvariant */
+    VariantClass v, oldVariant = gameInfo.variant; /* [HGM] PGNvariant */
+    char oldName[MSG_SIZ];
+
+    safeStrCpy(oldName, engineVariant, MSG_SIZ); v = oldVariant;
 
     if (appData.debugMode)
        fprintf(debugFP, "LoadGame(): on entry, gameMode %d\n", gameMode);
@@ -13045,6 +13059,10 @@ LoadGame (FILE *f, int gameNumber, char *title, int useList)
        StartChessProgram(&first);
     }
     InitChessProgram(&first, FALSE);
+    if(gameInfo.variant == VariantUnknown && *oldName) {
+       safeStrCpy(engineVariant, oldName, MSG_SIZ);
+       gameInfo.variant = v;
+    }
     SendToProgram("force\n", &first);
     if (startedFromSetupPosition) {
        SendBoard(&first, forwardMostMove);
@@ -13237,8 +13255,8 @@ LoadPosition (FILE *f, int positionNumber, char *title)
        DisplayError(_("Position not found in file"), 0);
        return FALSE;
     }
-    // [HGM] FEN can begin with digit, any piece letter valid in this variant, or a + for Shogi promoted pieces
-    fenMode = line[0] >= '0' && line[0] <= '9' || line[0] == '+' || CharToPiece(line[0]) != EmptySquare;
+    // [HGM] FEN can begin with digit, any piece letter valid in this variant, or a + for Shogi promoted pieces (or * for blackout)
+    fenMode = line[0] >= '0' && line[0] <= '9' || line[0] == '+' || line[0] == '*' || CharToPiece(line[0]) != EmptySquare;
 
     if (pn >= 2) {
        if (fenMode || line[0] == '#') pn--;