fix crash on engine crash
[xboard.git] / backend.c
index 5b8dcfa..342b6f8 100755 (executable)
--- a/backend.c
+++ b/backend.c
@@ -607,7 +607,7 @@ InitBackEnd1()
     ShowThinkingEvent(); // [HGM] thinking: make sure post/nopost state is set according to options
 
     GetTimeMark(&programStartTime);
-    srand(programStartTime.ms); // [HGM] book: makes sure random is unpredictabe to msec level
+    srandom((programStartTime.ms + 1000*programStartTime.sec)*0x1001001); // [HGM] book: makes sure random is unpredictabe to msec level
 
     ClearProgramStats();
     programStats.ok_to_send = 1;
@@ -1904,6 +1904,8 @@ CopyHoldings(Board board, char *holdings, ChessSquare lowestPiece)
     ChessSquare piece;
 
     if(gameInfo.holdingsWidth < 2)  return;
+    if(gameInfo.variant != VariantBughouse && board[BOARD_SIZE-1][BOARD_SIZE-2])
+       return; // prevent overwriting by pre-board holdings
 
     if( (int)lowestPiece >= BlackPawn ) {
         holdingsColumn = 0;
@@ -1932,7 +1934,6 @@ CopyHoldings(Board board, char *holdings, ChessSquare lowestPiece)
         board[holdingsStartRow+j*direction][holdingsColumn] = piece;
         board[holdingsStartRow+j*direction][countsColumn]++;
     }
-
 }
 
 
@@ -1940,6 +1941,7 @@ void
 VariantSwitch(Board board, VariantClass newVariant)
 {
    int newHoldingsWidth, newWidth = 8, newHeight = 8, i, j;
+   Board oldBoard;
 
    startedFromPositionFile = FALSE;
    if(gameInfo.variant == newVariant) return;
@@ -1977,7 +1979,7 @@ VariantSwitch(Board board, VariantClass newVariant)
      case VariantSuper:
        newHoldingsWidth = 2;
        gameInfo.holdingsSize = 8;
-       return;
+       break;
      case VariantGothic:
      case VariantCapablanca:
      case VariantCapaRandom:
@@ -2011,10 +2013,10 @@ VariantSwitch(Board board, VariantClass newVariant)
      gameInfo.holdingsWidth = newHoldingsWidth;
      gameInfo.variant = newVariant;
      InitDrawingSizes(-2, 0);
+   } else gameInfo.variant = newVariant;
+   CopyBoard(oldBoard, board);   // remember correctly formatted board
      InitPosition(FALSE);          /* this sets up board[0], but also other stuff        */
-   } else { gameInfo.variant = newVariant; InitPosition(FALSE); }
-   
-   DrawPosition(TRUE, boards[currentMove]);
+   DrawPosition(TRUE, currentMove ? boards[currentMove] : oldBoard);
 }
 
 static int loggedOn = FALSE;
@@ -2903,7 +2905,7 @@ read_from_ics(isr, closure, data, count, error)
                        currentMove = forwardMostMove;
                        ClearHighlights();/*!!could figure this out*/
                        flipView = appData.flipView;
-                       DrawPosition(FALSE, boards[currentMove]);
+                       DrawPosition(TRUE, boards[currentMove]);
                        DisplayBothClocks();
                        sprintf(str, "%s vs. %s",
                                gameInfo.white, gameInfo.black);
@@ -3234,16 +3236,14 @@ read_from_ics(isr, closure, data, count, error)
                      if (currentMove == 0 &&
                          gameMode == IcsPlayingWhite &&
                          appData.premoveWhite) {
-                       sprintf(str, "%s%s\n", ics_prefix,
-                               appData.premoveWhiteText);
+                       sprintf(str, "%s\n", appData.premoveWhiteText);
                        if (appData.debugMode)
                          fprintf(debugFP, "Sending premove:\n");
                        SendToICS(str);
                      } else if (currentMove == 1 &&
                                 gameMode == IcsPlayingBlack &&
                                 appData.premoveBlack) {
-                       sprintf(str, "%s%s\n", ics_prefix,
-                               appData.premoveBlackText);
+                       sprintf(str, "%s\n", appData.premoveBlackText);
                        if (appData.debugMode)
                          fprintf(debugFP, "Sending premove:\n");
                        SendToICS(str);
@@ -3260,6 +3260,7 @@ read_from_ics(isr, closure, data, count, error)
 
                    /* Usually suppress following prompt */
                    if (!(forwardMostMove == 0 && gameMode == IcsExamining)) {
+                       while(looking_at(buf, &i, "\n")); // [HGM] skip empty lines
                        if (looking_at(buf, &i, "*% ")) {
                            savingComment = FALSE;
                        }
@@ -3281,7 +3282,13 @@ read_from_ics(isr, closure, data, count, error)
                            * to move the position two files to the right to
                            * create room for them!
                            */
-                          VariantSwitch(boards[currentMove], VariantCrazyhouse); /* temp guess */
+                         VariantClass newVariant;
+                         switch(gameInfo.boardWidth) { // base guess on board width
+                               case 9:  newVariant = VariantShogi; break;
+                               case 10: newVariant = VariantGreat; break;
+                               default: newVariant = VariantCrazyhouse; break;
+                         }
+                          VariantSwitch(boards[currentMove], newVariant); /* temp guess */
                          /* Get a move list just to see the header, which
                             will tell us whether this is really bug or zh */
                          if (ics_getting_history == H_FALSE) {
@@ -3297,8 +3304,9 @@ read_from_ics(isr, closure, data, count, error)
                         white_holding[strlen(white_holding)-1] = NULLCHAR;
                         black_holding[strlen(black_holding)-1] = NULLCHAR;
                         /* [HGM] copy holdings to board holdings area */
-                        CopyHoldings(boards[currentMove], white_holding, WhitePawn);
-                        CopyHoldings(boards[currentMove], black_holding, BlackPawn);
+                        CopyHoldings(boards[forwardMostMove], white_holding, WhitePawn);
+                        CopyHoldings(boards[forwardMostMove], black_holding, BlackPawn);
+                        boards[forwardMostMove][BOARD_SIZE-1][BOARD_SIZE-2] = 1; // flag holdings as set
 #if ZIPPY
                        if (appData.zippyPlay && first.initDone) {
                            ZippyHoldings(white_holding, black_holding,
@@ -3322,6 +3330,7 @@ read_from_ics(isr, closure, data, count, error)
                    }
                    /* Suppress following prompt */
                    if (looking_at(buf, &i, "*% ")) {
+                       if(strchr(star_match[0], 7)) SendToPlayer("\007", 1); // Bell(); // FICS fuses bell for next board with prompt in zh captures
                        savingComment = FALSE;
                    }
                    next_out = i;
@@ -3391,6 +3400,7 @@ ParseBoard12(string)
     char promoChar;
     int ranks=1, files=0; /* [HGM] ICS80: allow variable board size */
     char *bookHit = NULL; // [HGM] book
+    Boolean weird = FALSE, reqFlag = FALSE;
 
     fromX = fromY = toX = toY = -1;
     
@@ -3406,6 +3416,7 @@ ParseBoard12(string)
         while(i < 199 && (string[i] != ' ' || string[i+2] != ' ')) {
            if(string[i] == ' ') { ranks++; files = 0; }
             else files++;
+           if(!strchr(" -pnbrqkPNBRQK" , string[i])) weird = TRUE; // test for fairies
            i++;
        }
        for(j = 0; j <i; j++) board_chars[j] = string[j];
@@ -3495,6 +3506,27 @@ ParseBoard12(string)
        ics_getting_history = H_FALSE;
        return;
     }
+
+   if (gameInfo.boardHeight != ranks || gameInfo.boardWidth != files || 
+                                       weird && (int)gameInfo.variant <= (int)VariantShogi) {
+     /* [HGM] We seem to have switched variant unexpectedly
+      * Try to guess new variant from board size
+      */
+         VariantClass newVariant = VariantFairy; // if 8x8, but fairies present
+         if(ranks == 8 && files == 10) newVariant = VariantCapablanca; else
+         if(ranks == 10 && files == 9) newVariant = VariantXiangqi; else
+         if(ranks == 8 && files == 12) newVariant = VariantCourier; else
+         if(ranks == 9 && files == 9)  newVariant = VariantShogi; else
+         if(!weird) newVariant = VariantNormal;
+          VariantSwitch(boards[currentMove], newVariant); /* temp guess */
+         /* Get a move list just to see the header, which
+            will tell us whether this is really bug or zh */
+         if (ics_getting_history == H_FALSE) {
+           ics_getting_history = H_REQUESTED; reqFlag = TRUE;
+           sprintf(str, "%smoves %d\n", ics_prefix, gamenum);
+           SendToICS(str);
+         }
+    }
     
     /* Take action if this is the first board of a new game, or of a
        different game than is currently being displayed.  */
@@ -3503,15 +3535,15 @@ ParseBoard12(string)
        
        /* Forget the old game and get the history (if any) of the new one */
        if (gameMode != BeginningOfGame) {
-         Reset(FALSE, TRUE);
+         Reset(TRUE, TRUE);
        }
        newGame = TRUE;
        if (appData.autoRaiseBoard) BoardToTop();
        prevMove = -3;
        if (gamenum == -1) {
            newGameMode = IcsIdle;
-       } else if (moveNum > 0 && newGameMode != IcsIdle &&
-                  appData.getMoveList) {
+       } else if ((moveNum > 0 || newGameMode == IcsObserving) && newGameMode != IcsIdle &&
+                  appData.getMoveList && !reqFlag) {
            /* Need to get game history */
            ics_getting_history = H_REQUESTED;
            sprintf(str, "%smoves %d\n", ics_prefix, gamenum);
@@ -3547,7 +3579,7 @@ ParseBoard12(string)
        timeIncrement = increment * 1000;
        movesPerSession = 0;
        gameInfo.timeControl = TimeControlTagValue();
-        VariantSwitch(board, StringToVariant(gameInfo.event) );
+        VariantSwitch(boards[currentMove], StringToVariant(gameInfo.event) );
   if (appData.debugMode) {
     fprintf(debugFP, "ParseBoard says variant = '%s'\n", gameInfo.event);
     fprintf(debugFP, "recognized as %s\n", VariantName(gameInfo.variant));
@@ -3627,6 +3659,7 @@ ParseBoard12(string)
       }
     }
     CopyBoard(boards[moveNum], board);
+    boards[moveNum][BOARD_SIZE-1][BOARD_SIZE-2] = 0; // [HGM] indicate holdings not set
     if (moveNum == 0) {
        startedFromSetupPosition =
          !CompareBoards(board, initialPosition);
@@ -3693,15 +3726,6 @@ ParseBoard12(string)
     /* Update currentMove and known move number limits */
     newMove = newGame || moveNum > forwardMostMove;
 
-    /* [DM] If we found takebacks during icsEngineAnalyze try send to engine */
-    if (!newGame && appData.icsEngineAnalyze && moveNum < forwardMostMove) {
-        takeback = forwardMostMove - moveNum;
-        for (i = 0; i < takeback; i++) {
-             if (appData.debugMode) fprintf(debugFP, "take back move\n");
-             SendToProgram("undo\n", &first);
-        }
-    }
-
     if (newGame) {
        forwardMostMove = backwardMostMove = currentMove = moveNum;
        if (gameMode == IcsExamining && moveNum == 0) {
@@ -3714,6 +3738,20 @@ ParseBoard12(string)
        }
     } else if (moveNum == forwardMostMove + 1 || moveNum == forwardMostMove
               || (moveNum < forwardMostMove && moveNum >= backwardMostMove)) {
+#if ZIPPY
+       /* [DM] If we found takebacks during icsEngineAnalyze try send to engine */
+       /* [HGM] applied this also to an engine that is silently watching        */
+       if (appData.zippyPlay && moveNum < forwardMostMove && first.initDone &&
+           (gameMode == IcsObserving || gameMode == IcsExamining) &&
+           gameInfo.variant == currentlyInitializedVariant) {
+         takeback = forwardMostMove - moveNum;
+         for (i = 0; i < takeback; i++) {
+           if (appData.debugMode) fprintf(debugFP, "take back move\n");
+           SendToProgram("undo\n", &first);
+         }
+       }
+#endif
+
        forwardMostMove = moveNum;
        if (!pausing || currentMove > forwardMostMove)
          currentMove = forwardMostMove;
@@ -3724,12 +3762,20 @@ ParseBoard12(string)
            forwardMostMove = pauseExamForwardMostMove;
            return;
        }
-       forwardMostMove = backwardMostMove = currentMove = moveNum;
        if (gameMode == IcsExamining && moveNum > 0 && appData.getMoveList) {
+#if ZIPPY
+           if(appData.zippyPlay && forwardMostMove > 0 && first.initDone) {
+               // [HGM] when we will receive the move list we now request, it will be
+               // fed to the engine from the first move on. So if the engine is not
+               // in the initial position now, bring it there.
+               InitChessProgram(&first, 0);
+           }
+#endif
            ics_getting_history = H_REQUESTED;
            sprintf(str, "%smoves %d\n", ics_prefix, gamenum);
            SendToICS(str);
        }
+       forwardMostMove = backwardMostMove = currentMove = moveNum;
     }
     
     /* Update the clocks */
@@ -5231,6 +5277,7 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
         return ImpossibleMove;
     }
 
+    if(toX < 0 || toY < 0) return ImpossibleMove;
     pdown = boards[currentMove][fromY][fromX];
     pup = boards[currentMove][toY][toX];
 
@@ -5262,7 +5309,7 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
             return ImpossibleMove;
        }
     }
-if(appData.debugMode) fprintf(debugFP, "moveType 3 = %d, promochar = %x\n", moveType, promoChar);
+
     return moveType;
     /* [HGM] <popupFix> in stead of calling FinishMove directly, this
        function is made into one that returns an OK move type if FinishMove
@@ -5281,7 +5328,7 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
      /*char*/int promoChar;
 {
     char *bookHit = 0;
-if(appData.debugMode) fprintf(debugFP, "moveType 5 = %d, promochar = %x\n", moveType, promoChar);
+
     if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) && promoChar != NULLCHAR) { 
        // [HGM] superchess: suppress promotions to non-available piece
        int k = PieceToNumber(CharToPiece(ToUpper(promoChar)));
@@ -5296,13 +5343,12 @@ if(appData.debugMode) fprintf(debugFP, "moveType 5 = %d, promochar = %x\n", move
        move type in caller when we know the move is a legal promotion */
     if(moveType == NormalMove && promoChar)
         moveType = PromoCharToMoveType(WhiteOnMove(currentMove), promoChar);
-if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", moveType, promoChar);
+
     /* [HGM] convert drag-and-drop piece drops to standard form */
     if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {
          moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop;
           if(appData.debugMode) fprintf(debugFP, "Drop move %d, curr=%d, x=%d,y=%d, p=%d\n", 
                moveType, currentMove, fromX, fromY, boards[currentMove][fromY][fromX]);
-//         fromX = boards[currentMove][fromY][fromX];
           // holdings might not be sent yet in ICS play; we have to figure out which piece belongs here
           if(fromX == 0) fromY = BOARD_HEIGHT-1 - fromY; // black holdings upside-down
           fromX = fromX ? WhitePawn : BlackPawn; // first piece type in selected holdings
@@ -5311,7 +5357,7 @@ if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", move
     }
 
     /* [HGM] <popupFix> The following if has been moved here from
-       UserMoveEvent(). Because it seemed to belon here (why not allow
+       UserMoveEvent(). Because it seemed to belong here (why not allow
        piece drops in training games?), and because it can only be
        performed after it is known to what we promote. */
     if (gameMode == Training) {
@@ -5385,7 +5431,7 @@ if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", move
     }
     ModeHighlight();
   }
-if(appData.debugMode) fprintf(debugFP, "moveType 2 = %d, promochar = %x\n", moveType, promoChar);
+
   /* Relay move to ICS or chess engine */
   if (appData.icsActive) {
     if (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||
@@ -5575,16 +5621,11 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
            }
            return;
        }
-       // ignore to-clicks in holdings
+       // ignore clicks on holdings
        if(x < BOARD_LEFT || x >= BOARD_RGHT) return;
     }
 
-    if (clickType == Release && (x == fromX && y == fromY ||
-       x < BOARD_LEFT || x >= BOARD_RGHT)) {
-
-       // treat drags into holding as click on start square
-       x = fromX; y = fromY;
-
+    if (clickType == Release && x == fromX && y == fromY) {
        DragPieceEnd(xPix, yPix);
        if (appData.animateDragging) {
            /* Undo animation damage if any */
@@ -5604,7 +5645,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
        return;
     }
 
-    /* we now have a different from- and to-square */
+    /* we now have a different from- and (possibly off-board) to-square */
     /* Completed move */
     toX = x;
     toY = y;
@@ -5627,6 +5668,18 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
        /* Don't animate move and drag both */
        appData.animate = FALSE;
     }
+
+    // moves into holding are invalid for now (later perhaps allow in EditPosition)
+    if(x >= 0 && x < BOARD_LEFT || x >= BOARD_RGHT) {
+       ClearHighlights();
+       fromX = fromY = -1;
+       DrawPosition(TRUE, NULL);
+       return;
+    }
+
+    // off-board moves should not be highlighted
+    if(x < 0 || x < 0) ClearHighlights();
+
     if (HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice)) {
        SetHighlights(fromX, fromY, toX, toY);
        if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
@@ -6395,7 +6448,7 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
             DisplayError(_("Bad FEN received from engine"), 0);
             return ;
         } else {
-           Reset(FALSE, FALSE);
+           Reset(TRUE, FALSE);
            CopyBoard(boards[0], initial_position);
            initialRulePlies = FENrulePlies;
            epStatus[0] = FENepStatus;
@@ -6896,9 +6949,12 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
 
                        if(cps->nps == 0) ticklen = 10*time;                    // use engine reported time
                        else ticklen = (1000. * u64ToDouble(nodes)) / cps->nps; // convert node count to time
-                       if(WhiteOnMove(forwardMostMove)) 
+                       if(WhiteOnMove(forwardMostMove) && (gameMode == MachinePlaysWhite ||
+                                               gameMode == TwoMachinesPlay && cps->twoMachinesColor[0] == 'w')) 
                             whiteTimeRemaining = timeRemaining[0][forwardMostMove] - ticklen;
-                       else blackTimeRemaining = timeRemaining[1][forwardMostMove] - ticklen;
+                       if(!WhiteOnMove(forwardMostMove) && (gameMode == MachinePlaysBlack ||
+                                               gameMode == TwoMachinesPlay && cps->twoMachinesColor[0] == 'b')) 
+                            blackTimeRemaining = timeRemaining[1][forwardMostMove] - ticklen;
                }
 
                /* Buffer overflow protection */
@@ -6906,8 +6962,8 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
                    if (strlen(buf1) >= sizeof(programStats.movelist)
                        && appData.debugMode) {
                        fprintf(debugFP,
-                               "PV is too long; using the first %d bytes.\n",
-                               sizeof(programStats.movelist) - 1);
+                               "PV is too long; using the first %u bytes.\n",
+                               (unsigned) sizeof(programStats.movelist) - 1);
                    }
 
                     safeStrCpy( programStats.movelist, buf1, sizeof(programStats.movelist) );
@@ -7514,14 +7570,20 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board, castling, ep)
         p = (int) fromX;
         if(p < (int) BlackPawn) { /* white drop */
              p -= (int)WhitePawn;
+                p = PieceToNumber((ChessSquare)p);
              if(p >= gameInfo.holdingsSize) p = 0;
-             if(--board[p][BOARD_WIDTH-2] == 0)
+             if(--board[p][BOARD_WIDTH-2] <= 0)
                   board[p][BOARD_WIDTH-1] = EmptySquare;
+             if((int)board[p][BOARD_WIDTH-2] < 0)
+                       board[p][BOARD_WIDTH-2] = 0;
         } else {                  /* black drop */
              p -= (int)BlackPawn;
+                p = PieceToNumber((ChessSquare)p);
              if(p >= gameInfo.holdingsSize) p = 0;
-             if(--board[BOARD_HEIGHT-1-p][1] == 0)
+             if(--board[BOARD_HEIGHT-1-p][1] <= 0)
                   board[BOARD_HEIGHT-1-p][0] = EmptySquare;
+             if((int)board[BOARD_HEIGHT-1-p][1] < 0)
+                       board[BOARD_HEIGHT-1-p][1] = 0;
         }
       }
       if (captured != EmptySquare && gameInfo.holdingsSize > 0
@@ -7555,7 +7617,6 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board, castling, ep)
           board[BOARD_HEIGHT-1-p][0] = WHITE_TO_BLACK captured;
        }
       }
-
     } else if (gameInfo.variant == VariantAtomic) {
       if (captured != EmptySquare) {
        int y, x;
@@ -7933,7 +7994,7 @@ TwoMachinesEventIfReady P((void))
 void
 NextMatchGame P((void))
 {
-    int index; /* [HGM] autoinc: step lod index during match */
+    int index; /* [HGM] autoinc: step load index during match */
     Reset(FALSE, TRUE);
     if (*appData.loadGameFile != NULLCHAR) {
        index = appData.loadGameIndex;
@@ -10925,7 +10986,9 @@ TwoMachinesEvent P((void))
 
        strcpy(bookMove, "move ");
        strcat(bookMove, bookHit);
-       HandleMachineMove(bookMove, &first);
+       savedMessage = bookMove; // args for deferred call
+       savedState = onmove;
+       ScheduleDelayedEvent(DeferredBookMove, 1);
     }
 }
 
@@ -11768,7 +11831,7 @@ void
 ToStartEvent()
 {
     if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
-       /* to optimze, we temporarily turn off analysis mode while we undo
+       /* to optimize, we temporarily turn off analysis mode while we undo
         * all the moves. Otherwise we get analysis output after each undo.
         */ 
         if (first.analysisSupport) {
@@ -12348,7 +12411,7 @@ SendToProgram(message, cps)
             } else {
                 gameInfo.result = cps->twoMachinesColor[0]=='w' ? BlackWins : WhiteWins;
             }
-            gameInfo.resultDetails = buf;
+            gameInfo.resultDetails = StrSave(buf);
         }
         DisplayFatalError(buf, error, 1);
     }
@@ -12379,7 +12442,7 @@ ReceiveFromProgram(isr, closure, message, count, error)
                 } else {
                     gameInfo.result = cps->twoMachinesColor[0]=='w' ? BlackWins : WhiteWins;
                 }
-                gameInfo.resultDetails = buf;
+                gameInfo.resultDetails = StrSave(buf);
             }
            RemoveInputSource(cps->isr);
            DisplayFatalError(buf, 0, 1);
@@ -12786,7 +12849,7 @@ ParseFeatures(args, cps)
     /* unknown feature: complain and skip */
     q = p;
     while (*q && *q != '=') q++;
-    sprintf(buf, "rejected %.*s\n", q-p, p);
+    sprintf(buf, "rejected %.*s\n", (int)(q-p), p);
     SendToProgram(buf, cps);
     p = q;
     if (*p == '=') {
@@ -12960,26 +13023,23 @@ DisplayComment(moveNumber, text)
     char title[MSG_SIZ];
     char buf[8000]; // comment can be long!
     int score, depth;
-
-    if( appData.autoDisplayComment ) {
-        if (moveNumber < 0 || parseList[moveNumber][0] == NULLCHAR) {
-           strcpy(title, "Comment");
-        } else {
-           sprintf(title, "Comment on %d.%s%s", moveNumber / 2 + 1,
-                   WhiteOnMove(moveNumber) ? " " : ".. ",
-                   parseList[moveNumber]);
-        }
-       // [HGM] PV info: display PV info together with (or as) comment
-       if(moveNumber >= 0 && (depth = pvInfoList[moveNumber].depth) > 0) {
-           if(text == NULL) text = "";                                           
-           score = pvInfoList[moveNumber].score;
-           sprintf(buf, "%s%.2f/%d %d\n%s", score>0 ? "+" : "", score/100.,
-                              depth, (pvInfoList[moveNumber].time+50)/100, text);
-           text = buf;
-       }
-    } else title[0] = 0;
-
-    if (text != NULL)
+    
+    if (moveNumber < 0 || parseList[moveNumber][0] == NULLCHAR) {
+      strcpy(title, "Comment");
+    } else {
+      sprintf(title, "Comment on %d.%s%s", moveNumber / 2 + 1,
+             WhiteOnMove(moveNumber) ? " " : ".. ",
+             parseList[moveNumber]);
+    }
+    // [HGM] PV info: display PV info together with (or as) comment
+    if(moveNumber >= 0 && (depth = pvInfoList[moveNumber].depth) > 0) {
+      if(text == NULL) text = "";                                           
+      score = pvInfoList[moveNumber].score;
+      sprintf(buf, "%s%.2f/%d %d\n%s", score>0 ? "+" : "", score/100.,
+             depth, (pvInfoList[moveNumber].time+50)/100, text);
+      text = buf;
+    }
+    if (text != NULL && (appData.autoDisplayComment || commentUp))
         CommentPopUp(title, text);
 }
 
@@ -13986,7 +14046,7 @@ Boolean set_cont_sequence(char *new_seq)
     if (ret)
         strcpy(cseq, new_seq);
     else if (appData.debugMode)
-        fprintf(debugFP, "Invalid continuation sequence \"%s\"  (maximum length is: %d)\n", new_seq, sizeof(cseq)-1);
+        fprintf(debugFP, "Invalid continuation sequence \"%s\"  (maximum length is: %u)\n", new_seq, (unsigned) sizeof(cseq)-1);
     return ret;
 }