bugfix: segfault when invalid option argument was given (bug #27427)
[xboard.git] / backend.c
index 9e70440..5fb842c 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -4557,7 +4557,6 @@ InitPosition(redraw)
     oldh = gameInfo.holdingsWidth,
     oldv = gameInfo.variant;
 
-    currentMove = forwardMostMove = backwardMostMove = 0;
     if(appData.icsActive) shuffleOpenings = FALSE; // [HGM] shuffle: in ICS mode, only shuffle on ICS request
 
     /* [AS] Initialize pv info list [HGM] and game status */
@@ -5159,6 +5158,12 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar)
                    fprintf(debugFP, "Got premove: fromX %d,"
                            "fromY %d, toX %d, toY %d\n",
                            fromX, fromY, toX, toY);
+               if(!WhiteOnMove(currentMove) && gotPremove == 1) {
+                   // [HGM] race: we must have been hit by an opponent move from the ICS while preparing the premove
+                   if (appData.debugMode) 
+                       fprintf(debugFP, "Execute as normal move\n");
+                   gotPremove = 0; break;
+               }
            }
             return ImpossibleMove;
        }
@@ -5180,6 +5185,12 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar)
                    fprintf(debugFP, "Got premove: fromX %d,"
                            "fromY %d, toX %d, toY %d\n",
                            fromX, fromY, toX, toY);
+               if(WhiteOnMove(currentMove) && gotPremove == 1) {
+                   // [HGM] race: we must have been hit by an opponent move from the ICS while preparing the premove
+                   if (appData.debugMode) 
+                       fprintf(debugFP, "Execute as normal move\n");
+                   gotPremove = 0; break;
+               }
            }
             return ImpossibleMove;
        }
@@ -6379,6 +6390,29 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
        }
 #endif
        if (pausing) PauseEvent();
+      if(appData.forceIllegal) {
+           // [HGM] illegal: machine refused move; force position after move into it
+          SendToProgram("force\n", cps);
+          if(!cps->useSetboard) { // hideous kludge on kludge, because SendBoard sucks.
+               // we have a real problem now, as SendBoard will use the a2a3 kludge
+               // when black is to move, while there might be nothing on a2 or black
+               // might already have the move. So send the board as if white has the move.
+               // But first we must change the stm of the engine, as it refused the last move
+               SendBoard(cps, 0); // always kludgeless, as white is to move on boards[0]
+               if(WhiteOnMove(forwardMostMove)) {
+                   SendToProgram("a7a6\n", cps); // for the engine black still had the move
+                   SendBoard(cps, forwardMostMove); // kludgeless board
+               } else {
+                   SendToProgram("a2a3\n", cps); // for the engine white still had the move
+                   CopyBoard(boards[forwardMostMove+1], boards[forwardMostMove]);
+                   SendBoard(cps, forwardMostMove+1); // kludgeless board
+               }
+          } else SendBoard(cps, forwardMostMove); // FEN case, also sets stm properly
+           if(gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack ||
+                gameMode == TwoMachinesPlay)
+              SendToProgram("go\n", cps);
+           return;
+      } else
        if (gameMode == PlayFromGameFile) {
            /* Stop reading this game file */
            gameMode = EditGame;
@@ -8281,6 +8315,7 @@ Reset(redraw, init)
     gameMode = BeginningOfGame;
     ModeHighlight();
     if(appData.icsActive) gameInfo.variant = VariantNormal;
+    currentMove = forwardMostMove = backwardMostMove = 0;
     InitPosition(redraw);
     for (i = 0; i < MAX_MOVES; i++) {
        if (commentList[i] != NULL) {