Merge commit 'v4.4.1.20091022' into gtk
authorArun Persaud <arun@nubati.net>
Wed, 4 Nov 2009 02:42:34 +0000 (18:42 -0800)
committerArun Persaud <arun@nubati.net>
Wed, 4 Nov 2009 02:42:34 +0000 (18:42 -0800)
Conflicts:
backend.c
configure.ac
xboard.c

1  2 
backend.c
xengineoutput.c

diff --combined backend.c
+++ b/backend.c
@@@ -126,15 -126,15 +126,15 @@@ extern int gettimeofday(struct timeval 
  # include "zippy.h"
  #endif
  #include "backendz.h"
 -#include "gettext.h" 
 - 
 -#ifdef ENABLE_NLS 
 -# define _(s) gettext (s) 
 -# define N_(s) gettext_noop (s) 
 -#else 
 -# define _(s) (s) 
 -# define N_(s) s 
 -#endif 
 +#include "gettext.h"
 +
 +#ifdef ENABLE_NLS
 +# define _(s) gettext (s)
 +# define N_(s) gettext_noop (s)
 +#else
 +# define _(s) (s)
 +# define N_(s) s
 +#endif
  
  
  /* A point in time */
@@@ -347,7 -347,7 +347,7 @@@ PosFlags(index
    case VariantKriegspiel:
      flags |= F_KRIEGSPIEL_CAPTURE;
      break;
 -  case VariantCapaRandom: 
 +  case VariantCapaRandom:
    case VariantFischeRandom:
      flags |= F_FRC_TYPE_CASTLING; /* [HGM] enable this through flag */
    case VariantNoCastle:
  
  FILE *gameFileFP, *debugFP;
  
 -/* 
 +/*
      [AS] Note: sometimes, the sscanf() function is used to parse the input
      into a fixed-size buffer. Because of this, we must be prepared to
      receive strings as long as the size of the input buffer, which is currently
@@@ -449,7 -449,7 +449,7 @@@ int   nrCastlingRights; // For TwoKings
  int   initialRulePlies, FENrulePlies;
  char  FENepStatus;
  FILE  *serverMoves = NULL; // next two for broadcasting (/serverMoves option)
 -int loadFlag = 0; 
 +int loadFlag = 0;
  int shuffleOpenings;
  int mute; // mute all sounds
  
@@@ -505,31 -505,31 +505,31 @@@ ChessSquare XiangqiArray[2][BOARD_SIZE
  };
  
  ChessSquare CapablancaArray[2][BOARD_SIZE] = {
 -    { WhiteRook, WhiteKnight, WhiteAngel, WhiteBishop, WhiteQueen, 
 +    { WhiteRook, WhiteKnight, WhiteAngel, WhiteBishop, WhiteQueen,
          WhiteKing, WhiteBishop, WhiteMarshall, WhiteKnight, WhiteRook },
 -    { BlackRook, BlackKnight, BlackAngel, BlackBishop, BlackQueen, 
 +    { BlackRook, BlackKnight, BlackAngel, BlackBishop, BlackQueen,
          BlackKing, BlackBishop, BlackMarshall, BlackKnight, BlackRook }
  };
  
  ChessSquare GreatArray[2][BOARD_SIZE] = {
 -    { WhiteDragon, WhiteKnight, WhiteAlfil, WhiteGrasshopper, WhiteKing, 
 +    { WhiteDragon, WhiteKnight, WhiteAlfil, WhiteGrasshopper, WhiteKing,
          WhiteSilver, WhiteCardinal, WhiteAlfil, WhiteKnight, WhiteDragon },
 -    { BlackDragon, BlackKnight, BlackAlfil, BlackGrasshopper, BlackKing, 
 +    { BlackDragon, BlackKnight, BlackAlfil, BlackGrasshopper, BlackKing,
          BlackSilver, BlackCardinal, BlackAlfil, BlackKnight, BlackDragon },
  };
  
  ChessSquare JanusArray[2][BOARD_SIZE] = {
 -    { WhiteRook, WhiteAngel, WhiteKnight, WhiteBishop, WhiteKing, 
 +    { WhiteRook, WhiteAngel, WhiteKnight, WhiteBishop, WhiteKing,
          WhiteQueen, WhiteBishop, WhiteKnight, WhiteAngel, WhiteRook },
 -    { BlackRook, BlackAngel, BlackKnight, BlackBishop, BlackKing, 
 +    { BlackRook, BlackAngel, BlackKnight, BlackBishop, BlackKing,
          BlackQueen, BlackBishop, BlackKnight, BlackAngel, BlackRook }
  };
  
  #ifdef GOTHIC
  ChessSquare GothicArray[2][BOARD_SIZE] = {
 -    { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteMarshall, 
 +    { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteMarshall,
          WhiteKing, WhiteAngel, WhiteBishop, WhiteKnight, WhiteRook },
 -    { BlackRook, BlackKnight, BlackBishop, BlackQueen, BlackMarshall, 
 +    { BlackRook, BlackKnight, BlackBishop, BlackQueen, BlackMarshall,
          BlackKing, BlackAngel, BlackBishop, BlackKnight, BlackRook }
  };
  #else // !GOTHIC
  
  #ifdef FALCON
  ChessSquare FalconArray[2][BOARD_SIZE] = {
 -    { WhiteRook, WhiteKnight, WhiteBishop, WhiteLance, WhiteQueen, 
 +    { WhiteRook, WhiteKnight, WhiteBishop, WhiteLance, WhiteQueen,
          WhiteKing, WhiteLance, WhiteBishop, WhiteKnight, WhiteRook },
 -    { BlackRook, BlackKnight, BlackBishop, BlackLance, BlackQueen, 
 +    { BlackRook, BlackKnight, BlackBishop, BlackLance, BlackQueen,
          BlackKing, BlackLance, BlackBishop, BlackKnight, BlackRook }
  };
  #else // !FALCON
@@@ -607,7 -607,7 +607,7 @@@ InitBackEnd1(
      ShowThinkingEvent(); // [HGM] thinking: make sure post/nopost state is set according to options
  
      GetTimeMark(&programStartTime);
-     srandom(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;
      if (appData.icsActive) {
        appData.matchMode = FALSE;
        appData.matchGames = 0;
 -#if ZIPPY     
 +#if ZIPPY
        appData.noChessProgram = !appData.zippyPlay;
  #else
        appData.zippyPlay = FALSE;
  
      /* [AS] Adjudication threshold */
      adjudicateLossThreshold = appData.adjudicateLossThreshold;
 -    
 +
      first.which = "first";
      second.which = "second";
      first.maybeThinking = second.maybeThinking = FALSE;
        appData.clockMode = FALSE;
        first.sendTime = second.sendTime = 0;
      }
 -    
 +
  #if ZIPPY
      /* Override some settings from environment variables, for backward
         compatibility.  Unfortunately it's not feasible to have the env
        ZippyInit();
      }
  #endif
 -    
 +
      if (appData.noChessProgram) {
        programVersion = (char*) malloc(5 + strlen(PACKAGE_STRING));
        sprintf(programVersion, "%s", PACKAGE_STRING);
@@@ -943,7 -943,7 +943,7 @@@ int NextSessionFromString( char ** str
              if(result = NextIntegerFromString( str, &temp2)) return -1;
              *inc = temp2 * 1000;
          } else *inc = 0;
 -        *moves = 0; *tc = temp * 1000; 
 +        *moves = 0; *tc = temp * 1000;
          return 0;
      } else if(temp % 60 != 0) return -1;     /* moves was given as min:sec */
  
@@@ -1038,31 -1038,31 +1038,31 @@@ ParseTimeControl(tc, ti, mps
  void
  InitBackEnd2()
  {
 -    if (appData.debugMode) {
 -      fprintf(debugFP, "%s\n", programVersion);
 -    }
 +  if (appData.debugMode) {
 +    fprintf(debugFP, "%s\n", programVersion);
 +  }
  
 -    set_cont_sequence(appData.wrapContSeq);
 -    if (appData.matchGames > 0) {
 -      appData.matchMode = TRUE;
 -    } else if (appData.matchMode) {
 -      appData.matchGames = 1;
 -    }
 -    if(appData.matchMode && appData.sameColorGames > 0) /* [HGM] alternate: overrule matchGames */
 -      appData.matchGames = appData.sameColorGames;
 -    if(appData.rewindIndex > 1) { /* [HGM] autoinc: rewind implies auto-increment and overrules given index */
 -      if(appData.loadPositionIndex >= 0) appData.loadPositionIndex = -1;
 -      if(appData.loadGameIndex >= 0) appData.loadGameIndex = -1;
 -    }
 -    Reset(TRUE, FALSE);
 -    if (appData.noChessProgram || first.protocolVersion == 1) {
 -      InitBackEnd3();
 +  set_cont_sequence(appData.wrapContSeq);
 +  if (appData.matchGames > 0) {
 +    appData.matchMode = TRUE;
 +  } else if (appData.matchMode) {
 +    appData.matchGames = 1;
 +  }
 +  if(appData.matchMode && appData.sameColorGames > 0) /* [HGM] alternate: overrule matchGames */
 +    appData.matchGames = appData.sameColorGames;
 +  if(appData.rewindIndex > 1) { /* [HGM] autoinc: rewind implies auto-increment and overrules given index */
 +    if(appData.loadPositionIndex >= 0) appData.loadPositionIndex = -1;
 +    if(appData.loadGameIndex >= 0) appData.loadGameIndex = -1;
 +  }
 +  Reset(TRUE, FALSE);
 +  if (appData.noChessProgram || first.protocolVersion == 1) {
 +    InitBackEnd3();
      } else {
 -      /* kludge: allow timeout for initial "feature" commands */
 -      FreezeUI();
 -      DisplayMessage("", _("Starting chess program"));
 -      ScheduleDelayedEvent(InitBackEnd3, FEATURE_TIMEOUT);
 -    }
 +    /* kludge: allow timeout for initial "feature" commands */
 +    FreezeUI();
 +    DisplayMessage("", _("Starting chess program"));
 +    ScheduleDelayedEvent(InitBackEnd3, FEATURE_TIMEOUT);
 +  }
  }
  
  void
@@@ -1078,15 -1078,15 +1078,15 @@@ InitBackEnd3 P((void)
      if (appData.icsActive) {
  #ifdef WIN32
          /* [DM] Make a console window if needed [HGM] merged ifs */
 -        ConsoleCreate(); 
 +        ConsoleCreate();
  #endif
        err = establish();
        if (err != 0) {
            if (*appData.icsCommPort != NULLCHAR) {
 -              sprintf(buf, _("Could not open comm port %s"),  
 +              sprintf(buf, _("Could not open comm port %s"),
                        appData.icsCommPort);
            } else {
 -              snprintf(buf, sizeof(buf), _("Could not connect to host %s, port %s"),  
 +              snprintf(buf, sizeof(buf), _("Could not connect to host %s, port %s"),
                        appData.icsHost, appData.icsPort);
            }
            DisplayFatalError(buf, err, 1);
        cmailISR =
          AddInputSource(cmailPR, FALSE, CmailSigHandlerCallBack, &cmailISR);
      }
 -    
 +
      ThawUI();
      DisplayMessage("", "");
      if (StrCaseCmp(appData.initialMode, "") == 0) {
      } else if (StrCaseCmp(appData.initialMode, "TwoMachines") == 0) {
        initialMode = TwoMachinesPlay;
      } else if (StrCaseCmp(appData.initialMode, "AnalyzeFile") == 0) {
 -      initialMode = AnalyzeFile; 
 +      initialMode = AnalyzeFile;
      } else if (StrCaseCmp(appData.initialMode, "Analysis") == 0) {
        initialMode = AnalyzeMode;
      } else if (StrCaseCmp(appData.initialMode, "MachineWhite") == 0) {
@@@ -1293,7 -1293,7 +1293,7 @@@ establish(
                        appData.icsHost, appData.icsPort);
            } else {
                snprintf(buf, sizeof(buf), "%s %s -l %s %s %s %s",
 -                      appData.remoteShell, appData.gateway, 
 +                      appData.remoteShell, appData.gateway,
                        appData.remoteUser, appData.telnetProgram,
                        appData.icsHost, appData.icsPort);
            }
@@@ -1476,7 -1476,7 +1476,7 @@@ SendToICSDelayed(s,msdelay
  
  
  /* Remove all highlighting escape sequences in s
 -   Also deletes any suffix starting with '(' 
 +   Also deletes any suffix starting with '('
     */
  char *
  StripHighlightAndTitle(s)
@@@ -1566,7 -1566,7 +1566,7 @@@ StringToVariant(e
  
      if (!found) {
        if ((StrCaseStr(e, "fischer") && StrCaseStr(e, "random"))
 -        || StrCaseStr(e, "wild/fr") 
 +        || StrCaseStr(e, "wild/fr")
          || StrCaseStr(e, "frc") || StrCaseStr(e, "960")) {
          v = VariantFischeRandom;
        } else if ((i = 4, p = StrCaseStr(e, "wild")) ||
          v = VariantShatranj;
          break;
  
 -      /* Temporary names for future ICC types.  The name *will* change in 
 +      /* Temporary names for future ICC types.  The name *will* change in
           the next xboard/WinBoard release after ICC defines it. */
        case 29:
          v = Variant29;
@@@ -1751,7 -1751,7 +1751,7 @@@ looking_at(buf, index, pattern
      char *bufp = &buf[*index], *patternp = pattern;
      int star_count = 0;
      char *matchp = star_match[0];
 -    
 +
      for (;;) {
        if (*patternp == NULLCHAR) {
            *index = leftover_start = bufp - buf;
@@@ -1904,6 -1904,8 +1904,8 @@@ CopyHoldings(Board board, char *holding
      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;
          board[holdingsStartRow+j*direction][holdingsColumn] = piece;
          board[holdingsStartRow+j*direction][countsColumn]++;
      }
  }
  
  
@@@ -1955,6 -1956,7 +1956,6 @@@ VariantSwitch(Board board, VariantClas
      * but also when receiving holdings of a crazyhouse game. In the latter
      * case we want to add those holdings to the already received position.
      */
 -
     
     if (appData.debugMode) {
       fprintf(debugFP, "Switch board from %s to %s\n",
       case VariantSuper:
         newHoldingsWidth = 2;
         gameInfo.holdingsSize = 8;
-        return;
+        break;
       case VariantGothic:
       case VariantCapablanca:
       case VariantCapaRandom:
       InitDrawingSizes(-2, 0);
       InitPosition(FALSE);          /* this sets up board[0], but also other stuff        */
     } else { gameInfo.variant = newVariant; InitPosition(FALSE); }
-    
     DrawPosition(TRUE, boards[currentMove]);
  }
  
@@@ -2048,7 -2049,7 +2048,7 @@@ read_from_ics(isr, closure, data, count
  #define STARTED_CHATTER 5
  #define STARTED_COMMENT 6
  #define STARTED_MOVES_NOHIDE 7
 -    
 +
      static int started = STARTED_NONE;
      static char parse[20000];
      static int parse_pos = 0;
        buf[buf_len] = NULLCHAR;
        next_out = leftover_len;
        leftover_start = 0;
 -      
 +
        i = 0;
        while (i < buf_len) {
            /* Deal with part of the TELNET option negotiation
                  next_out = i;
                continue;
            }
 -              
 +
            /* OK, this at least will *usually* work */
            if (!loggedOn && looking_at(buf, &i, "ics%")) {
                loggedOn = TRUE;
            }
 -          
 +
            if (loggedOn && !intfSet) {
                if (ics_type == ICS_ICC) {
                  sprintf(str,
  
            oldi = i;
            // [HGM] kibitz: try to recognize opponent engine-score kibitzes, to divert them to engine-output window
 -          if (appData.autoKibitz && started == STARTED_NONE && 
 +          if (appData.autoKibitz && started == STARTED_NONE &&
                  !appData.icsEngineAnalyze &&                     // [HGM] [DM] ICS analyze
                (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack || gameMode == IcsObserving)) {
                if(looking_at(buf, &i, "* kibitzes: ") &&
 -                 (StrStr(star_match[0], gameInfo.white) == star_match[0] || 
 +                 (StrStr(star_match[0], gameInfo.white) == star_match[0] ||
                    StrStr(star_match[0], gameInfo.black) == star_match[0]   )) { // kibitz of self or opponent
                        suppressKibitz = TRUE;
                        if((StrStr(star_match[0], gameInfo.white) == star_match[0]
                            savingComment = TRUE;
                            suppressKibitz = gameMode != IcsObserving ? 2 :
                                (StrStr(star_match[0], gameInfo.white) == NULL) + 1;
 -                      } 
 +                      }
                        continue;
                } else
                if(looking_at(buf, &i, "kibitzed to")) { // suppress the acknowledgements of our own autoKibitz
                SendToICS("refresh\n");
                continue;
            }
 -          
 +
            if (!have_sent_ICS_logon && looking_at(buf, &i, "login:")) {
                ICSInitScript();
                have_sent_ICS_logon = 1;
                continue;
            }
 -            
 -          if (ics_getting_history != H_GETTING_MOVES /*smpos kludge*/ && 
 +
 +          if (ics_getting_history != H_GETTING_MOVES /*smpos kludge*/ &&
                (looking_at(buf, &i, "\n<12> ") ||
                 looking_at(buf, &i, "<12> "))) {
                loggedOn = TRUE;
                    gameInfo.whiteRating = string_to_rating(star_match[1]);
                    gameInfo.blackRating = string_to_rating(star_match[3]);
                    if (appData.debugMode)
 -                    fprintf(debugFP, _("Ratings from header: W %d, B %d\n"), 
 +                    fprintf(debugFP, _("Ratings from header: W %d, B %d\n"),
                              gameInfo.whiteRating, gameInfo.blackRating);
                }
                continue;
                    break;
                }
                continue;
 -          }                           
 -          
 +          }
 +
            if (looking_at(buf, &i, "% ") ||
                ((started == STARTED_MOVES || started == STARTED_MOVES_NOHIDE)
                 && looking_at(buf, &i, "}*"))) { char *bookHit = NULL; // [HGM] book
                            if (WhiteOnMove(forwardMostMove)) {
                                if (first.sendTime) {
                                  if (first.useColors) {
 -                                  SendToProgram("black\n", &first); 
 +                                  SendToProgram("black\n", &first);
                                  }
                                  SendTimeRemaining(&first, TRUE);
                                }
                                  firstMove = TRUE;
                                }
                            }
 -                      }                       
 +                      }
                    }
  #endif
                    if (gameMode == IcsObserving && ics_gamenum == -1) {
                        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);
                if(bookHit) { // [HGM] book: simulate book reply
                    static char bookMove[MSG_SIZ]; // a bit generous?
  
 -                  programStats.nodes = programStats.depth = programStats.time = 
 +                  programStats.nodes = programStats.depth = programStats.time =
                    programStats.score = programStats.got_only_move = 0;
                    sprintf(programStats.movelist, "%s (xbook)", bookHit);
  
                }
                continue;
            }
 -          
 +
            if ((started == STARTED_MOVES || started == STARTED_BOARD ||
                 started == STARTED_HOLDINGS ||
                 started == STARTED_MOVES_NOHIDE) && i >= leftover_len) {
                /* Accumulate characters in move list or board */
                parse[parse_pos++] = buf[i];
            }
 -          
 +
            /* Start of game messages.  Mostly we detect start of game
               when the first board image arrives.  On some versions
               of the ICS, though, we need to do a "refresh" after starting
                player2Rating = string_to_rating(star_match[3]);
  
                if (appData.debugMode)
 -                fprintf(debugFP, 
 +                fprintf(debugFP,
                          "Ratings from 'Game notification:' %s %d, %s %d\n",
                          player1Name, player1Rating,
                          player2Name, player2Rating);
                    SendToICS("refresh\n");
                }
                continue;
 -          }    
 -          
 +          }
 +
            /* Error messages */
  //        if (ics_user_moved) {
            if (1) { // [HGM] old way ignored error after move type in; ics_user_moved is not set then!
                   2    empty, white, or black (IGNORED)
                   3    player 2 name (not necessarily black)
                   4    player 2 rating
 -                 
 +
                   The names/ratings are sorted out when the game
                   actually starts (below).
                */
                player2Rating = string_to_rating(star_match[4]);
  
                if (appData.debugMode)
 -                fprintf(debugFP, 
 +                fprintf(debugFP,
                          "Ratings from 'Creating:' %s %d, %s %d\n",
                          player1Name, player1Rating,
                          player2Name, player2Rating);
  
                continue;
            }
 -          
 +
            /* Improved generic start/end-of-game messages */
            if ((tkind=0, looking_at(buf, &i, "{Game * (* vs. *) *}*")) ||
                (tkind=1, looking_at(buf, &i, "{Game * (*(*) vs. *(*)) *}*"))){
                      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);
                        ClearPremoveHighlights();
                        if (appData.debugMode)
                          fprintf(debugFP, "Sending premove:\n");
 -                          UserMoveEvent(premoveFromX, premoveFromY, 
 -                                      premoveToX, premoveToY, 
 +                          UserMoveEvent(premoveFromX, premoveFromY,
 +                                      premoveToX, premoveToY,
                                          premovePromoChar);
                      }
                    }
                          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,
  
            i++;                /* skip unparsed character and loop back */
        }
 -      
 +
        if (started != STARTED_MOVES && started != STARTED_BOARD && !suppressKibitz && // [HGM] kibitz suppress printing in ICS interaction window
            started != STARTED_HOLDINGS && i > next_out) {
            SendToPlayer(&buf[next_out], i - next_out);
            next_out = i;
        }
        suppressKibitz = FALSE; // [HGM] kibitz: has done its duty in if-statement above
 -      
 +
        leftover_len = buf_len - leftover_start;
        /* if buffer ends with something we couldn't parse,
           reparse it after appending the next read */
 -      
 +
      } else if (count == 0) {
        RemoveInputSource(isr);
          DisplayFatalError(_("Connection closed by ICS"), 0, 0);
  
  
  /* Board style 12 looks like this:
 -   
 +
     <12> r-b---k- pp----pp ---bP--- ---p---- q------- ------P- P--Q--BP -----R-K W -1 0 0 0 0 0 0 paf MaxII 0 2 12 21 25 234 174 24 Q/d7-a4 (0:06) Qxa4 0 0
 -   
 +
   * The "<12> " is stripped before it gets to this routine.  The two
   * trailing 0's (flip state and clock ticking) are later addition, and
   * some chess servers may not have them, or may have only the first.
 - * Additional trailing fields may be added in the future.  
 + * Additional trailing fields may be added in the future.
   */
  
  #define PATTERN "%c%d%d%d%d%d%d%d%s%s%d%d%d%d%d%d%d%d%s%s%s%d%d"
  void
  ParseBoard12(string)
       char *string;
 -{ 
 +{
      GameMode newGameMode;
      int gamenum, newGame, newMove, relation, basetime, increment, ics_flip = 0, i;
      int j, k, n, moveNum, white_stren, black_stren, white_time, black_time, takeback;
      Boolean weird = FALSE;
  
      fromX = fromY = toX = toY = -1;
 -    
 +
      newGame = FALSE;
  
      if (appData.debugMode)
               &white_stren, &black_stren, &white_time, &black_time,
               &moveNum, str, elapsed_time, move_str, &ics_flip,
               &ticking);
- fprintf(debugFP, "old: %dx%d   new: %dx%d weird=%d variant=%d\n",gameInfo.boardHeight,gameInfo.boardWidth,ranks,files,weird,gameInfo.variant);fflush(debugFP);
     if (gameInfo.boardHeight != ranks || gameInfo.boardWidth != files || 
                                        weird && (int)gameInfo.variant <= (int)VariantShogi) {
       /* [HGM] We seem to switch variant during a game!
          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;
+         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 */
                        0, 1);
        return;
      }
 -    
 +
      switch (relation) {
        case RELATION_OBSERVING_PLAYED:
        case RELATION_OBSERVING_STATIC:
        case RELATION_ISOLATED_BOARD:
        default:
        /* Just display this board.  If user was doing something else,
 -         we will forget about it until the next board comes. */ 
 +         we will forget about it until the next board comes. */
        newGameMode = IcsIdle;
        break;
        case RELATION_STARTING_POSITION:
        newGameMode = gameMode;
        break;
      }
 -    
 +
      /* Modify behavior for initial board display on move listing
         of wild games.
         */
        ics_getting_history = H_FALSE;
        return;
      }
 -    
 +
      /* Take action if this is the first board of a new game, or of a
         different game than is currently being displayed.  */
      if (gamenum != ics_gamenum || newGameMode != gameMode ||
        relation == RELATION_ISOLATED_BOARD) {
 -      
 +
        /* 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();
            sprintf(str, "%smoves %d\n", ics_prefix, gamenum);
            SendToICS(str);
        }
 -      
 +
        /* Initially flip the board to have black on the bottom if playing
           black or if the ICS flip flag is set, but let the user change
           it with the Flip View button. */
 -      flipView = appData.autoFlipView ? 
 +      flipView = appData.autoFlipView ?
          (newGameMode == IcsPlayingBlack) || ics_flip :
          appData.flipView;
 -      
 +
        /* Done with values from previous mode; copy in new ones */
        gameMode = newGameMode;
        ModeHighlight();
    }
  
          gameInfo.outOfBook = NULL;
 -      
 +
        /* Do we have the ratings? */
        if (strcmp(player1Name, white) == 0 &&
            strcmp(player2Name, black) == 0) {
            SendToICS("set shout 0\n");
        }
      }
 -    
 +
      /* Deal with midgame name changes */
      if (!newGame) {
        if (!gameInfo.white || strcmp(gameInfo.white, white) != 0) {
            gameInfo.black = StrSave(black);
        }
      }
 -    
 +
      /* Throw away game result if anything actually changes in examine mode */
      if (gameMode == IcsExamining && !newGame) {
        gameInfo.result = GameUnfinished;
            gameInfo.resultDetails = NULL;
        }
      }
 -    
 +
      /* In pausing && IcsExamining mode, we ignore boards coming
         in if they are in a different variation than we are. */
      if (pauseExamInvalid) return;
            return;
        }
      }
 -    
 +
    if (appData.debugMode) {
      fprintf(debugFP, "load %dx%d board\n", files, ranks);
    }
        }
      }
      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);
      /* [HGM] e.p. rights. Assume that ICS sends file number here? */
      epStatus[moveNum] = double_push == -1 ? EP_NONE : double_push + BOARD_LEFT;
  
 -    
 +
      if (ics_getting_history == H_GOT_REQ_HEADER ||
        ics_getting_history == H_GOT_UNREQ_HEADER) {
        /* This was an initial position from a move list, not
           the current position */
        return;
      }
 -    
 +
      /* 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) {
        }
      } 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;
      } else {
 -      /* New part of history that is not contiguous with old part */ 
 +      /* New part of history that is not contiguous with old part */
        if (pausing && gameMode == IcsExamining) {
            pauseExamInvalid = TRUE;
            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 */
      if (strchr(elapsed_time, '.')) {
        /* Time is in ms */
        timeRemaining[0][moveNum] = whiteTimeRemaining = white_time * 1000;
        timeRemaining[1][moveNum] = blackTimeRemaining = black_time * 1000;
      }
 -      
 +
  
  #if ZIPPY
      if (appData.zippyPlay && newGame &&
        gameMode != IcsExamining)
        ZippyFirstBoard(moveNum, basetime, increment);
  #endif
 -    
 +
      /* Put the move on the move list, first converting
         to canonical algebraic form. */
      if (moveNum > 0) {
            startedFromSetupPosition = TRUE;
            fromX = fromY = toX = toY = -1;
        } else {
 -        // [HGM] long SAN: if legality-testing is off, disambiguation might not work or give wrong move. 
 +        // [HGM] long SAN: if legality-testing is off, disambiguation might not work or give wrong move.
          //                 So we parse the long-algebraic move string in stead of the SAN move
          int valid; char buf[MSG_SIZ], *prom;
  
          // str looks something like "Q/a1-a2"; kill the slash
 -        if(str[1] == '/') 
 +        if(str[1] == '/')
                sprintf(buf, "%c%s", str[0], str+2);
          else  strcpy(buf, str); // might be castling
 -        if((prom = strstr(move_str, "=")) && !strstr(buf, "=")) 
 +        if((prom = strstr(move_str, "=")) && !strstr(buf, "="))
                strcat(buf, prom); // long move lacks promo specification!
          if(!appData.testLegality && move_str[1] != '@') { // drops never ambiguous (parser chokes on long form!)
 -              if(appData.debugMode) 
 +              if(appData.debugMode)
                        fprintf(debugFP, "replaced ICS move '%s' by '%s'\n", move_str, buf);
                strcpy(move_str, buf);
            }
  
  #if ZIPPY
        /* Send move to chess program (BEFORE animating it). */
 -      if (appData.zippyPlay && !newGame && newMove && 
 +      if (appData.zippyPlay && !newGame && newMove &&
           (!appData.getMoveList || backwardMostMove == 0) && first.initDone) {
  
            if ((gameMode == IcsPlayingWhite && WhiteOnMove(moveNum)) ||
            SetHighlights(fromX, fromY, toX, toY);
        }
      }
 -    
 +
      /* Start the clocks */
      whiteFlag = blackFlag = FALSE;
      appData.clockMode = !(basetime == 0 && increment == 0);
        DisplayBothClocks();
      else
        StartClocks();
 -    
 +
      /* Display opponents and material strengths */
      if (gameInfo.variant != VariantBughouse &&
        gameInfo.variant != VariantCrazyhouse && !appData.noGUI) {
        if (tinyLayout || smallLayout) {
            if(gameInfo.variant == VariantNormal)
 -              sprintf(str, "%s(%d) %s(%d) {%d %d}", 
 +              sprintf(str, "%s(%d) %s(%d) {%d %d}",
                    gameInfo.white, white_stren, gameInfo.black, black_stren,
                    basetime, increment);
            else
 -              sprintf(str, "%s(%d) %s(%d) {%d %d w%d}", 
 +              sprintf(str, "%s(%d) %s(%d) {%d %d w%d}",
                    gameInfo.white, white_stren, gameInfo.black, black_stren,
                    basetime, increment, (int) gameInfo.variant);
        } else {
            if(gameInfo.variant == VariantNormal)
 -              sprintf(str, "%s (%d) vs. %s (%d) {%d %d}", 
 +              sprintf(str, "%s (%d) vs. %s (%d) {%d %d}",
                    gameInfo.white, white_stren, gameInfo.black, black_stren,
                    basetime, increment);
            else
 -              sprintf(str, "%s (%d) vs. %s (%d) {%d %d %s}", 
 +              sprintf(str, "%s (%d) vs. %s (%d) {%d %d %s}",
                    gameInfo.white, white_stren, gameInfo.black, black_stren,
                    basetime, increment, VariantName(gameInfo.variant));
        }
    }
      }
  
 -   
 +
      /* Display the board */
      if (!pausing && !appData.noGUI) {
 -      
        if (appData.premove)
 -        if (!gotPremove || 
 +        if (!gotPremove ||
             ((gameMode == IcsPlayingWhite) && (WhiteOnMove(currentMove))) ||
             ((gameMode == IcsPlayingBlack) && (!WhiteOnMove(currentMove))))
              ClearPremoveHighlights();
      if(bookHit) { // [HGM] book: simulate book reply
        static char bookMove[MSG_SIZ]; // a bit generous?
  
 -      programStats.nodes = programStats.depth = programStats.time = 
 +      programStats.nodes = programStats.depth = programStats.time =
        programStats.score = programStats.got_only_move = 0;
        sprintf(programStats.movelist, "%s (xbook)", bookHit);
  
@@@ -4065,17 -4081,17 +4079,17 @@@ SendMoveToProgram(moveNum, cps
        AlphaRank(moveList[moveNum], 4); // and back
        } else
        /* Added by Tord: Send castle moves in "O-O" in FRC games if required by
 -       * the engine. It would be nice to have a better way to identify castle 
 +       * the engine. It would be nice to have a better way to identify castle
         * moves here. */
        if((gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom)
                                                                         && cps->useOOCastle) {
 -        int fromX = moveList[moveNum][0] - AAA; 
 +        int fromX = moveList[moveNum][0] - AAA;
          int fromY = moveList[moveNum][1] - ONE;
 -        int toX = moveList[moveNum][2] - AAA; 
 +        int toX = moveList[moveNum][2] - AAA;
          int toY = moveList[moveNum][3] - ONE;
 -        if((boards[moveNum][fromY][fromX] == WhiteKing 
 +        if((boards[moveNum][fromY][fromX] == WhiteKing
              && boards[moveNum][toY][toX] == WhiteRook)
 -           || (boards[moveNum][fromY][fromX] == BlackKing 
 +           || (boards[moveNum][fromY][fromX] == BlackKing
                 && boards[moveNum][toY][toX] == BlackRook)) {
          if(toX > fromX) SendToProgram("O-O\n", cps);
          else SendToProgram("O-O-O\n", cps);
@@@ -4225,7 -4241,7 +4239,7 @@@ AlphaRank(char *move, int n
          fprintf(debugFP, "alphaRank(%s,%d)\n", move, n);
      }
  
 -    if(move[1]=='*' && 
 +    if(move[1]=='*' &&
         move[2]>='0' && move[2]<='9' &&
         move[3]>='a' && move[3]<='x'    ) {
          move[1] = '@';
@@@ -4273,7 -4289,7 +4287,7 @@@ ParseOneMove(move, moveNum, moveType, f
       ChessMove *moveType;
       int *fromX, *fromY, *toX, *toY;
       char *promoChar;
 -{       
 +{
      if (appData.debugMode) {
          fprintf(debugFP, "move to parse: %s\n", move);
      }
@@@ -4396,7 -4412,7 +4410,7 @@@ int put(Board board, int pieceType, in
                        board[rank][i] = (ChessSquare) pieceType;
                        squaresLeft[((i-BOARD_LEFT)&1) + 1]--;
                        squaresLeft[ANY]--;
 -                      piecesLeft[pieceType]--; 
 +                      piecesLeft[pieceType]--;
                        return i;
                }
        }
@@@ -4524,7 -4540,7 +4538,7 @@@ int SetCharTable( char *table, const ch
  {
      int result = FALSE; int NrPieces;
  
 -    if( map != NULL && (NrPieces=strlen(map)) <= (int) EmptySquare 
 +    if( map != NULL && (NrPieces=strlen(map)) <= (int) EmptySquare
                      && NrPieces >= 12 && !(NrPieces&1)) {
          int i; /* [HGM] Accept even length from 12 to 34 */
  
  
  void Prelude(Board board)
  {     // [HGM] superchess: random selection of exo-pieces
 -      int i, j, k; ChessSquare p; 
 +      int i, j, k; ChessSquare p;
        static ChessSquare exoPieces[4] = { WhiteAngel, WhiteMarshall, WhiteSilver, WhiteLance };
  
        GetPositionNumber(); // use FRC position number
  
        if(appData.pieceToCharTable != NULL) { // select pieces to participate from given char table
            SetCharTable(pieceToChar, appData.pieceToCharTable);
 -          for(i=(int)WhiteQueen+1, j=0; i<(int)WhiteKing && j<4; i++) 
 +          for(i=(int)WhiteQueen+1, j=0; i<(int)WhiteKing && j<4; i++)
                if(PieceToChar((ChessSquare)i) != '.') exoPieces[j++] = (ChessSquare) i;
        }
  
 -      j = seed%4;                 seed /= 4; 
 +      j = seed%4;                 seed /= 4;
        p = board[0][BOARD_LEFT+j];   board[0][BOARD_LEFT+j] = EmptySquare; k = PieceToNumber(p);
        board[k][BOARD_WIDTH-1] = p;  board[k][BOARD_WIDTH-2]++;
        board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p;  board[BOARD_HEIGHT-1-k][1]++;
 -      j = seed%3 + (seed%3 >= j); seed /= 3; 
 +      j = seed%3 + (seed%3 >= j); seed /= 3;
        p = board[0][BOARD_LEFT+j];   board[0][BOARD_LEFT+j] = EmptySquare; k = PieceToNumber(p);
        board[k][BOARD_WIDTH-1] = p;  board[k][BOARD_WIDTH-2]++;
        board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p;  board[BOARD_HEIGHT-1-k][1]++;
 -      j = seed%3;                 seed /= 3; 
 +      j = seed%3;                 seed /= 3;
        p = board[0][BOARD_LEFT+j+5]; board[0][BOARD_LEFT+j+5] = EmptySquare; k = PieceToNumber(p);
        board[k][BOARD_WIDTH-1] = p;  board[k][BOARD_WIDTH-2]++;
        board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p;  board[BOARD_HEIGHT-1-k][1]++;
 -      j = seed%2 + (seed%2 >= j); seed /= 2; 
 +      j = seed%2 + (seed%2 >= j); seed /= 2;
        p = board[0][BOARD_LEFT+j+5]; board[0][BOARD_LEFT+j+5] = EmptySquare; k = PieceToNumber(p);
        board[k][BOARD_WIDTH-1] = p;  board[k][BOARD_WIDTH-2]++;
        board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p;  board[BOARD_HEIGHT-1-k][1]++;
@@@ -4605,7 -4621,7 +4619,7 @@@ InitPosition(redraw
          castlingRank[3] = castlingRank[4] = castlingRank[5] = BOARD_HEIGHT-1;
      }
  
 -    
 +
      /* [HGM] logic here is completely changed. In stead of full positions */
      /* the initialized data only consist of the two backranks. The switch */
      /* selects which one we will use, which is than copied to the Board   */
      gameInfo.holdingsSize  = 0;
      nrCastlingRights = -1; /* [HGM] Kludge to indicate default should be used */
      for(i=0; i<BOARD_SIZE; i++) initialRights[i] = -1; /* but no rights yet */
 -    SetCharTable(pieceToChar, "PNBRQ...........Kpnbrq...........k"); 
 +    SetCharTable(pieceToChar, "PNBRQ...........Kpnbrq...........k");
  
      switch (gameInfo.variant) {
      case VariantFischeRandom:
      case VariantShatranj:
        pieces = ShatranjArray;
        nrCastlingRights = 0;
 -      SetCharTable(pieceToChar, "PN.R.QB...Kpn.r.qb...k"); 
 +      SetCharTable(pieceToChar, "PN.R.QB...Kpn.r.qb...k");
        break;
      case VariantTwoKings:
        pieces = twoKingsArray;
      case VariantCapablanca:
        pieces = CapablancaArray;
        gameInfo.boardWidth = 10;
 -      SetCharTable(pieceToChar, "PNBRQ..ACKpnbrq..ack"); 
 +      SetCharTable(pieceToChar, "PNBRQ..ACKpnbrq..ack");
        break;
      case VariantGothic:
        pieces = GothicArray;
        gameInfo.boardWidth = 10;
 -      SetCharTable(pieceToChar, "PNBRQ..ACKpnbrq..ack"); 
 +      SetCharTable(pieceToChar, "PNBRQ..ACKpnbrq..ack");
        break;
      case VariantJanus:
        pieces = JanusArray;
        gameInfo.boardWidth = 10;
 -      SetCharTable(pieceToChar, "PNBRQ..JKpnbrq..jk"); 
 +      SetCharTable(pieceToChar, "PNBRQ..JKpnbrq..jk");
        nrCastlingRights = 6;
          castlingRights[0][0] = initialRights[0] = BOARD_RGHT-1;
          castlingRights[0][1] = initialRights[1] = BOARD_LEFT;
      case VariantFalcon:
        pieces = FalconArray;
        gameInfo.boardWidth = 10;
 -      SetCharTable(pieceToChar, "PNBRQ.............FKpnbrq.............fk"); 
 +      SetCharTable(pieceToChar, "PNBRQ.............FKpnbrq.............fk");
        break;
      case VariantXiangqi:
        pieces = XiangqiArray;
        gameInfo.boardWidth  = 9;
        gameInfo.boardHeight = 10;
        nrCastlingRights = 0;
 -      SetCharTable(pieceToChar, "PH.R.AE..K.C.ph.r.ae..k.c."); 
 +      SetCharTable(pieceToChar, "PH.R.AE..K.C.ph.r.ae..k.c.");
        break;
      case VariantShogi:
        pieces = ShogiArray;
        gameInfo.boardHeight = 9;
        gameInfo.holdingsSize = 7;
        nrCastlingRights = 0;
 -      SetCharTable(pieceToChar, "PNBRLS...G.++++++Kpnbrls...g.++++++k"); 
 +      SetCharTable(pieceToChar, "PNBRLS...G.++++++Kpnbrls...g.++++++k");
        break;
      case VariantCourier:
        pieces = CourierArray;
        gameInfo.boardWidth  = 12;
        nrCastlingRights = 0;
 -      SetCharTable(pieceToChar, "PNBR.FE..WMKpnbr.fe..wmk"); 
 +      SetCharTable(pieceToChar, "PNBR.FE..WMKpnbr.fe..wmk");
        for(i=0; i<BOARD_SIZE; i++) initialRights[i] = -1;
        break;
      case VariantKnightmate:
        pieces = KnightmateArray;
 -      SetCharTable(pieceToChar, "P.BRQ.....M.........K.p.brq.....m.........k."); 
 +      SetCharTable(pieceToChar, "P.BRQ.....M.........K.p.brq.....m.........k.");
        break;
      case VariantFairy:
        pieces = fairyArray;
 -      SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk"); 
 +      SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
        break;
      case VariantGreat:
        pieces = GreatArray;
      case VariantCrazyhouse:
      case VariantBughouse:
        pieces = FIDEArray;
 -      SetCharTable(pieceToChar, "PNBRQ.......~~~~Kpnbrq.......~~~~k"); 
 +      SetCharTable(pieceToChar, "PNBRQ.......~~~~Kpnbrq.......~~~~k");
        gameInfo.holdingsSize = 5;
        break;
      case VariantWildCastle:
          initialPosition[BOARD_HEIGHT-pawnRow-1][j] = BlackPawn;
          if(gameInfo.variant == VariantXiangqi) {
              if(j&1) {
 -                initialPosition[pawnRow][j] = 
 +                initialPosition[pawnRow][j] =
                  initialPosition[BOARD_HEIGHT-pawnRow-1][j] = EmptySquare;
                  if(j==BOARD_LEFT+1 || j>=BOARD_RGHT-2) {
                     initialPosition[2][j] = WhiteCannon;
          /*       This sets default castling rights from none to normal corners   */
          /* Variants with other castling rights must set them themselves above    */
          nrCastlingRights = 6;
 -       
 +
          castlingRights[0][0] = initialRights[0] = BOARD_RGHT-1;
          castlingRights[0][1] = initialRights[1] = BOARD_LEFT;
          castlingRights[0][2] = initialRights[2] = BOARD_WIDTH>>1;
      }
  
      CopyBoard(boards[0], initialPosition);
 -
      if(oldx != gameInfo.boardWidth ||
         oldy != gameInfo.boardHeight ||
         oldh != gameInfo.holdingsWidth
         gameInfo.variant == VariantFalcon
  #endif
                                           )
 +      {
              InitDrawingSizes(-2 ,0);
 +      }
  
      if (redraw)
        DrawPosition(TRUE, boards[currentMove]);
 +
  }
  
  void
@@@ -4847,7 -4861,7 +4861,7 @@@ SendBoard(cps, moveNum
       int moveNum;
  {
      char message[MSG_SIZ];
 -    
 +
      if (cps->useSetboard) {
        char* fen = PositionToFEN(moveNum, cps->fenOverride);
        sprintf(message, "setboard %s\n", fen);
        bp = &boards[moveNum][i][BOARD_LEFT];
          for (j = BOARD_LEFT; j < BOARD_RGHT; j++, bp++) {
          if ((int) *bp < (int) BlackPawn) {
 -          sprintf(message, "%c%c%c\n", PieceToChar(*bp), 
 +          sprintf(message, "%c%c%c\n", PieceToChar(*bp),
                      AAA + j, ONE + i);
              if(message[0] == '+' || message[0] == '~') {
                  sprintf(message, "%c%c%c+\n",
          }
        }
        }
 -    
 +
        SendToProgram("c\n", cps);
        for (i = BOARD_HEIGHT - 1; i >= 0; i--) {
        bp = &boards[moveNum][i][BOARD_LEFT];
          }
        }
        }
 -    
 +
        SendToProgram(".\n", cps);
      }
      setboardSpoiledMachineBlack = 0; /* [HGM] assume WB 4.2.7 already solves this after sending setboard */
@@@ -5075,11 -5089,11 +5089,11 @@@ OKToStartUserMove(x, y
        if (!white_piece && WhiteOnMove(currentMove)) {
            DisplayMoveError(_("It is White's turn"));
            return FALSE;
 -      }           
 +      }
        if (white_piece && !WhiteOnMove(currentMove)) {
            DisplayMoveError(_("It is Black's turn"));
            return FALSE;
 -      }           
 +      }
        if (cmailMsgLoaded && (currentMove < cmailOldMove)) {
            /* Editing correspondence game history */
            /* Could disallow this or prompt for confirmation */
            }
        }
        break;
 -      
 +
        case Training:
        if (!white_piece && WhiteOnMove(currentMove)) {
            DisplayMoveError(_("It is White's turn"));
            return FALSE;
 -      }           
 +      }
        if (white_piece && !WhiteOnMove(currentMove)) {
            DisplayMoveError(_("It is Black's turn"));
            return FALSE;
 -      }           
 +      }
        break;
  
        default:
@@@ -5212,7 -5226,7 +5226,7 @@@ UserMoveTest(fromX, fromY, toX, toY, pr
                premoveFromY = fromY;
                premovePromoChar = promoChar;
                gotPremove = 1;
 -              if (appData.debugMode) 
 +              if (appData.debugMode)
                    fprintf(debugFP, "Got premove: fromX %d,"
                            "fromY %d, toX %d, toY %d\n",
                            fromX, fromY, toX, toY);
                premoveFromY = fromY;
                premovePromoChar = promoChar;
                gotPremove = 1;
 -              if (appData.debugMode) 
 +              if (appData.debugMode)
                    fprintf(debugFP, "Got premove: fromX %d,"
                            "fromY %d, toX %d, toY %d\n",
                            fromX, fromY, toX, toY);
          return ImpossibleMove;
      }
  
+     if(toX < 0 || toY < 0) return ImpossibleMove;
      pdown = boards[currentMove][fromY][fromX];
      pup = boards[currentMove][toY][toX];
  
      /* [HGM] If move started in holdings, it means a drop */
 -    if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) { 
 +    if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {
           if( pup != EmptySquare ) return ImpossibleMove;
           if(appData.testLegality) {
               /* it would be more logical if LegalityTest() also figured out
      }
  
      userOfferedDraw = FALSE;
 -      
 +
      /* [HGM] always test for legality, to get promotion info */
      moveType = LegalityTest(boards[currentMove], PosFlags(currentMove),
                            epStatus[currentMove], castlingRights[currentMove],
              return ImpossibleMove;
        }
      }
 -if(appData.debugMode) fprintf(debugFP, "moveType 3 = %d, promochar = %x\n", moveType, promoChar);
 +    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
@@@ -5308,63 -5323,43 +5323,63 @@@ FinishMove(moveType, fromX, fromY, toX
       int fromX, fromY, toX, toY;
       /*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)));
 -      if(WhiteOnMove(currentMove)) {
 -          if(!boards[currentMove][k][BOARD_WIDTH-2]) return 0;
 -      } else {
 -          if(!boards[currentMove][BOARD_HEIGHT-1-k][1]) return 0;
 +  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)));
 +      if(WhiteOnMove(currentMove))
 +      {
 +        if(!boards[currentMove][k][BOARD_WIDTH-2])
 +          return 0;
 +      }
 +      else
 +      {
 +        if(!boards[currentMove][BOARD_HEIGHT-1-k][1])
 +          return 0;
        }
      }
 +  
 +  /* [HGM] <popupFix> kludge to avoid having to know the exact promotion
 +     move type in caller when we know the move is a legal promotion */
 +  if(moveType == NormalMove && promoChar)
 +    moveType = PromoCharToMoveType(WhiteOnMove(currentMove), promoChar);
  
 -    /* [HGM] <popupFix> kludge to avoid having to know the exact promotion
 -       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", 
 +  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
 -         while(PieceToChar(fromX) == '.' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) fromX++; 
 -         fromY = DROP_RANK;
 -    }
 -
 -    /* [HGM] <popupFix> The following if has been moved here from
 -       UserMoveEvent(). Because it seemed to belon 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) {
 +      //         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
 +
 +      while(PieceToChar(fromX) == '.' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) 
 +      fromX++; 
 +
 +      fromY = DROP_RANK;
 +    }
 +
 +  /* [HGM] <popupFix> The following if has been moved here from
 +     UserMoveEvent(). Because it seemed to belon 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)
 +    {
        /* compare the move played on the board to the next move in the
 -       * game. If they match, display the move and the opponent's response. 
 +       * game. If they match, display the move and the opponent's response.
         * If they don't match, display an error message.
         */
        int saveAnimate;
        CopyBoard(testBoard, boards[currentMove]);
        ApplyMove(fromX, fromY, toX, toY, promoChar, testBoard, testRights, &testStatus);
  
 -      if (CompareBoards(testBoard, boards[currentMove+1])) {
 -      ForwardInner(currentMove+1);
 +      if (CompareBoards(testBoard, boards[currentMove+1]))
 +      {
 +        ForwardInner(currentMove+1);
  
 -      /* Autoplay the opponent's response.
 -       * if appData.animate was TRUE when Training mode was entered,
 -       * the response will be animated.
 -       */
 -      saveAnimate = appData.animate;
 -      appData.animate = animateTraining;
 -      ForwardInner(currentMove+1);
 -      appData.animate = saveAnimate;
 -
 -      /* check for the end of the game */
 -      if (currentMove >= forwardMostMove) {
 -        gameMode = PlayFromGameFile;
 -        ModeHighlight();
 -        SetTrainingModeOff();
 -        DisplayInformation(_("End of game"));
 +        /* Autoplay the opponent's response.
 +         * if appData.animate was TRUE when Training mode was entered,
 +         * the response will be animated.
 +         */
 +        saveAnimate = appData.animate;
 +        appData.animate = animateTraining;
 +        ForwardInner(currentMove+1);
 +        appData.animate = saveAnimate;
 +
 +        /* check for the end of the game */
 +        if (currentMove >= forwardMostMove)
 +          {
 +            gameMode = PlayFromGameFile;
 +            ModeHighlight();
 +            SetTrainingModeOff();
 +            DisplayInformation(_("End of game"));
 +          }
 +      }
 +      else
 +      {
 +        DisplayError(_("Incorrect move"), 0);
        }
 -      } else {
 -      DisplayError(_("Incorrect move"), 0);
 -      }
        return 1;
      }
  
    /* Ok, now we know that the move is good, so we can kill
       the previous line in Analysis Mode */
 -  if (gameMode == AnalyzeMode && currentMove < forwardMostMove) {
 -    forwardMostMove = currentMove;
 -  }
 +  if (gameMode == AnalyzeMode && currentMove < forwardMostMove)
 +    {
 +      forwardMostMove = currentMove;
 +    }
  
    /* If we need the chess program but it's dead, restart it */
    ResurrectChessProgram();
  
    MakeMove(fromX, fromY, toX, toY, promoChar); /*updates forwardMostMove*/
  
 -  if (gameMode == BeginningOfGame) {
 -    if (appData.noChessProgram) {
 -      gameMode = EditGame;
 -      SetGameInfo();
 -    } else {
 -      char buf[MSG_SIZ];
 -      gameMode = MachinePlaysBlack;
 -      StartClocks();
 -      SetGameInfo();
 -      sprintf(buf, "%s vs. %s", gameInfo.white, gameInfo.black);
 -      DisplayTitle(buf);
 -      if (first.sendName) {
 -      sprintf(buf, "name %s\n", gameInfo.white);
 -      SendToProgram(buf, &first);
 -      }
 -      StartClocks();
 +  if (gameMode == BeginningOfGame)
 +    {
 +      if (appData.noChessProgram)
 +      {
 +        gameMode = EditGame;
 +        SetGameInfo();
 +      }
 +      else
 +      {
 +        char buf[MSG_SIZ];
 +        gameMode = MachinePlaysBlack;
 +        StartClocks();
 +        SetGameInfo();
 +        sprintf(buf, "%s vs. %s", gameInfo.white, gameInfo.black);
 +        DisplayTitle(buf);
 +        if (first.sendName)
 +          {
 +            sprintf(buf, "name %s\n", gameInfo.white);
 +            SendToProgram(buf, &first);
 +          }
 +        StartClocks();
 +      }
 +      ModeHighlight();
      }
 -    ModeHighlight();
 -  }
 -if(appData.debugMode) fprintf(debugFP, "moveType 2 = %d, promochar = %x\n", moveType, promoChar);
 +  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 ||
 -      gameMode == IcsExamining) {
 -      SendMoveToICS(moveType, fromX, fromY, toX, toY);
 -      ics_user_moved = 1;
 +  if (appData.icsActive)
 +    {
 +      if (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||
 +        gameMode == IcsExamining)
 +      {
 +        SendMoveToICS(moveType, fromX, fromY, toX, toY);
 +        ics_user_moved = 1;
 +      }
      }
 -  } else {
 -    if (first.sendTime && (gameMode == BeginningOfGame ||
 -                         gameMode == MachinePlaysWhite ||
 -                         gameMode == MachinePlaysBlack)) {
 -      SendTimeRemaining(&first, gameMode != MachinePlaysBlack);
 -    }
 -    if (gameMode != EditGame && gameMode != PlayFromGameFile) {
 -       // [HGM] book: if program might be playing, let it use book
 -      bookHit = SendMoveToBookUser(forwardMostMove-1, &first, FALSE);
 -      first.maybeThinking = TRUE;
 -    } else SendMoveToProgram(forwardMostMove-1, &first);
 -    if (currentMove == cmailOldMove + 1) {
 -      cmailMoveType[lastLoadGameNumber - 1] = CMAIL_MOVE;
 +  else
 +    {
 +      if (first.sendTime && (gameMode == BeginningOfGame ||
 +                           gameMode == MachinePlaysWhite ||
 +                           gameMode == MachinePlaysBlack))
 +      {
 +        SendTimeRemaining(&first, gameMode != MachinePlaysBlack);
 +      }
 +      if (gameMode != EditGame && gameMode != PlayFromGameFile)
 +      {
 +        // [HGM] book: if program might be playing, let it use book
 +        bookHit = SendMoveToBookUser(forwardMostMove-1, &first, FALSE);
 +        first.maybeThinking = TRUE;
 +      }
 +      else
 +      SendMoveToProgram(forwardMostMove-1, &first);
 +      if (currentMove == cmailOldMove + 1)
 +      {
 +        cmailMoveType[lastLoadGameNumber - 1] = CMAIL_MOVE;
 +      }
      }
  
    ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
  
 -  switch (gameMode) {
 -  case EditGame:
 -    switch (MateTest(boards[currentMove], PosFlags(currentMove),
 -                     EP_UNKNOWN, castlingRights[currentMove]) ) {
 -    case MT_NONE:
 -    case MT_CHECK:
 +  switch (gameMode)
 +    {
 +    case EditGame:
 +      switch (MateTest(boards[currentMove], PosFlags(currentMove),
 +                     EP_UNKNOWN, castlingRights[currentMove]) )
 +      {
 +      case MT_NONE:
 +      case MT_CHECK:
 +        break;
 +      case MT_CHECKMATE:
 +      case MT_STAINMATE:
 +        if (WhiteOnMove(currentMove))
 +          {
 +            GameEnds(BlackWins, "Black mates", GE_PLAYER);
 +          }
 +        else
 +          {
 +            GameEnds(WhiteWins, "White mates", GE_PLAYER);
 +          }
 +        break;
 +      case MT_STALEMATE:
 +        GameEnds(GameIsDrawn, "Stalemate", GE_PLAYER);
 +        break;
 +    }
        break;
 -    case MT_CHECKMATE:
 -    case MT_STAINMATE:
 -      if (WhiteOnMove(currentMove)) {
 -      GameEnds(BlackWins, "Black mates", GE_PLAYER);
 -      } else {
 -      GameEnds(WhiteWins, "White mates", GE_PLAYER);
 -      }
 +
 +    case MachinePlaysBlack:
 +    case MachinePlaysWhite:
 +      /* disable certain menu options while machine is thinking */
 +      SetMachineThinkingEnables();
        break;
 -    case MT_STALEMATE:
 -      GameEnds(GameIsDrawn, "Stalemate", GE_PLAYER);
 +
 +    default:
        break;
      }
 -    break;
 -    
 -  case MachinePlaysBlack:
 -  case MachinePlaysWhite:
 -    /* disable certain menu options while machine is thinking */
 -    SetMachineThinkingEnables();
 -    break;
  
 -  default:
 -    break;
 -  }
 +  if(bookHit)
 +    { // [HGM] book: simulate book reply
 +      static char bookMove[MSG_SIZ]; // a bit generous?
  
 -  if(bookHit) { // [HGM] book: simulate book reply
 -      static char bookMove[MSG_SIZ]; // a bit generous?
 -
 -      programStats.nodes = programStats.depth = programStats.time = 
 +      programStats.nodes = programStats.depth = programStats.time =
        programStats.score = programStats.got_only_move = 0;
 -      sprintf(programStats.movelist, "%s (xbook)", bookHit);
 +      sprintf(programStats.movelist, "%s (xbook)", bookHit);
 +
 +      strcpy(bookMove, "move ");
 +      strcat(bookMove, bookHit);
 +      HandleMachineMove(bookMove, &first);
 +    }
  
 -      strcpy(bookMove, "move ");
 -      strcat(bookMove, bookHit);
 -      HandleMachineMove(bookMove, &first);
 -  }
    return 1;
  }
  
@@@ -5543,7 -5511,7 +5558,7 @@@ UserMoveEvent(fromX, fromY, toX, toY, p
         slip a promotion popup in between. But that it always needs two
         calls, to the first part, (now called UserMoveTest() ), and to
         FinishMove if the first part succeeded. Calls that do not need
 -       to do anything in between, can call this routine the old way. 
 +       to do anything in between, can call this routine the old way.
      */
      ChessMove moveType = UserMoveTest(fromX, fromY, toX, toY, promoChar, FALSE);
  if(appData.debugMode) fprintf(debugFP, "moveType 4 = %d, promochar = %x\n", moveType, promoChar);
@@@ -5650,16 -5618,11 +5665,11 @@@ void LeftClick(ClickType clickType, in
            }
            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 */
        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;
        /* 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(FALSE, 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) {
@@@ -5783,7 -5758,7 +5805,7 @@@ char *SendMoveToBookUser(int moveNr, Ch
        cps->bookSuspend = FALSE; // after a 'go' we are never suspended
      } else { // 'go' might be sent based on 'firstMove' after this routine returns
        if(cps->bookSuspend && !firstMove) // 'go' needed, and it will not be done after we return
 -          SendToProgram("go\n", cps); 
 +          SendToProgram("go\n", cps);
        cps->bookSuspend = FALSE; // anyhow, we will not be suspended after a miss
      }
      return bookHit; // notify caller of hit, so it can take action to send move to opponent
@@@ -5850,7 -5825,7 +5872,7 @@@ FakeBookMove: // [HGM] book: we jump he
       * Look for machine move.
       */
      if ((sscanf(message, "%s %s %s", buf1, buf2, machineMove) == 3 && strcmp(buf2, "...") == 0) ||
 -      (sscanf(message, "%s %s", buf1, machineMove) == 2 && strcmp(buf1, "move") == 0)) 
 +      (sscanf(message, "%s %s", buf1, machineMove) == 2 && strcmp(buf1, "move") == 0))
      {
          /* This method is only useful on engines that support ping */
          if (cps->lastPing != cps->lastPong) {
@@@ -6041,8 -6016,8 +6063,8 @@@ if(appData.debugMode) fprintf(debugFP, 
              if( count >= adjudicateLossPlies ) {
                ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
  
 -                GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, 
 -                    "Xboard adjudication", 
 +                GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins,
 +                    "Xboard adjudication",
                      GE_XBOARD );
  
                  return;
                               NrWQ++; break;
                          case BlackQueen:
                               NrBQ++; break;
 -                        case EmptySquare: 
 +                        case EmptySquare:
                               break;
                          case BlackPawn:
                               m = 7-i;
                      }
                      NrPieces += (p != EmptySquare);
                      NrW += ((int)p < (int)BlackPawn);
 -                  if(gameInfo.variant == VariantXiangqi && 
 +                  if(gameInfo.variant == VariantXiangqi &&
                      (p == WhiteFerz || p == WhiteAlfil || p == BlackFerz || p == BlackAlfil)) {
                        NrPieces--; // [HGM] XQ: do not count purely defensive pieces
                          NrW -= ((int)p < (int)BlackPawn);
                     if(appData.checkMates) {
                         SendMoveToProgram(forwardMostMove-1, cps->other); // make sure opponent gets move
                           ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
 -                         GameEnds( WhiteOnMove(forwardMostMove) ? BlackWins : WhiteWins, 
 +                         GameEnds( WhiteOnMove(forwardMostMove) ? BlackWins : WhiteWins,
                                                        "Xboard adjudication: King destroyed", GE_XBOARD );
                           return;
                     }
                     if(appData.checkMates) {
                         SendMoveToProgram(forwardMostMove-1, cps->other); // make sure opponent gets to see move
                           ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
 -                         GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, 
 +                         GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins,
                                                        "Xboard adjudication: Bare king", GE_XBOARD );
                           return;
                     }
                            /* but only adjudicate if adjudication enabled */
                            SendMoveToProgram(forwardMostMove-1, cps->other); // make sure opponent gets move
                            ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
 -                          GameEnds( NrW > 1 ? WhiteWins : NrPieces - NrW > 1 ? BlackWins : GameIsDrawn, 
 +                          GameEnds( NrW > 1 ? WhiteWins : NrPieces - NrW > 1 ? BlackWins : GameIsDrawn,
                                                        "Xboard adjudication: Bare king", GE_XBOARD );
                            return;
                        }
                }
  
                  /* Next absolutely insufficient mating material. */
 -                if( NrPieces == 2 || gameInfo.variant != VariantXiangqi && 
 +                if( NrPieces == 2 || gameInfo.variant != VariantXiangqi &&
                                     gameInfo.variant != VariantShatranj && // [HGM] baring will remain possible
                        (NrPieces == 3 && NrWN+NrBN+NrWB+NrBB == 1 ||
                         NrPieces == NrBB+NrWB+2 && bishopsColor != 3)) // [HGM] all Bishops (Ferz!) same color
                  }
  
                  /* Then some trivial draws (only adjudicate, cannot be claimed) */
 -                if(NrPieces == 4 && 
 +                if(NrPieces == 4 &&
                     (   NrWR == 1 && NrBR == 1 /* KRKR */
                     || NrWQ==1 && NrBQ==1     /* KQKQ */
                     || NrWN==2 || NrBN==2     /* KNNK */
                          }
                          if( castlingRights[forwardMostMove][5] != castlingRights[k][5] &&
                               (castlingRights[k][3] >= 0 || castlingRights[k][4] >= 0) )
 -                                rights++; 
 +                                rights++;
                          if( castlingRights[forwardMostMove][5] >= 0 ) {
                              if( castlingRights[forwardMostMove][3] != castlingRights[k][3] ||
                                  castlingRights[forwardMostMove][4] != castlingRights[k][4] )
                             SendToProgram("force\n", cps->other); // suppress reply
                             SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */
                               ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
 -                           if(gameInfo.variant == VariantXiangqi && appData.testLegality) { 
 +                           if(gameInfo.variant == VariantXiangqi && appData.testLegality) {
                                // [HGM] xiangqi: check for forbidden perpetuals
                                int m, ourPerpetual = 1, hisPerpetual = 1;
                                for(m=forwardMostMove; m>k; m-=2) {
 -                                  if(MateTest(boards[m], PosFlags(m), 
 +                                  if(MateTest(boards[m], PosFlags(m),
                                                        EP_NONE, castlingRights[m]) != MT_CHECK)
                                        ourPerpetual = 0; // the current mover did not always check
 -                                  if(MateTest(boards[m-1], PosFlags(m-1), 
 +                                  if(MateTest(boards[m-1], PosFlags(m-1),
                                                        EP_NONE, castlingRights[m-1]) != MT_CHECK)
                                        hisPerpetual = 0; // the opponent did not always check
                                }
                                if(appData.debugMode) fprintf(debugFP, "XQ perpetual test, our=%d, his=%d\n",
                                                                        ourPerpetual, hisPerpetual);
                                if(ourPerpetual && !hisPerpetual) { // we are actively checking him: forfeit
 -                                  GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, 
 +                                  GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins,
                                           "Xboard adjudication: perpetual checking", GE_XBOARD );
                                    return;
                                }
                                    hisPerpetual = PerpetualChase(k, forwardMostMove);
                                    ourPerpetual = PerpetualChase(k+1, forwardMostMove);
                                    if(ourPerpetual && !hisPerpetual) { // we are actively chasing him: forfeit
 -                                      GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, 
 +                                      GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins,
                                                      "Xboard adjudication: perpetual chasing", GE_XBOARD );
                                        return;
                                    }
                  /* if we hit starting position, add initial plies */
                  if( count == backwardMostMove )
                      count -= initialRulePlies;
 -                count = forwardMostMove - count; 
 +                count = forwardMostMove - count;
                  if( count >= 100)
                           epStatus[forwardMostMove] = EP_RULE_DRAW;
                           /* this is used to judge if draw claims are legal */
        }
  
        ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
 -      
 +
          if (!pausing && appData.ringBellAfterMoves) {
            RingBell();
        }
  
 -      /* 
 +      /*
         * Reenable menu items that were disabled while
         * machine was thinking
         */
                strcat(bookMove, bookHit);
                message = bookMove;
                cps = cps->other;
 -              programStats.nodes = programStats.depth = programStats.time = 
 +              programStats.nodes = programStats.depth = programStats.time =
                programStats.score = programStats.got_only_move = 0;
                sprintf(programStats.movelist, "%s (xbook)", bookHit);
  
              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;
             for( i=0; i<nrCastlingRights; i++ )
                  castlingRights[0][i] = FENcastlingRights[i];
             if(blackPlaysFirst) gameMode = MachinePlaysWhite;
 -           else gameMode = MachinePlaysBlack;                 
 +           else gameMode = MachinePlaysBlack;
             DrawPosition(FALSE, boards[currentMove]);
          }
        return;
        AskQuestion(realname, buf2, buf1, cps->pr);
        return;
      }
 -    /* Commands from the engine directly to ICS.  We don't allow these to be 
 -     *  sent until we are logged on. Crafty kibitzes have been known to 
 +    /* Commands from the engine directly to ICS.  We don't allow these to be
 +     *  sent until we are logged on. Crafty kibitzes have been known to
       *  interfere with the login process.
       */
      if (loggedOn) {
       */
      if (strncmp(message + 1, "llegal move", 11) == 0 ||
        strncmp(message, "Error", 5) == 0) {
 -      if (StrStr(message, "name") || 
 +      if (StrStr(message, "name") ||
            StrStr(message, "rating") || StrStr(message, "?") ||
            StrStr(message, "result") || StrStr(message, "board") ||
            StrStr(message, "bk") || StrStr(message, "computer") ||
           Don't use it. */
        cps->sendTime = 0;
      }
 -    
 +
      /*
       * If chess program startup fails, exit with an error message.
       * Attempts to recover here are futile.
        DisplayFatalError(buf1, 0, 1);
        return;
      }
 -    
 -    /* 
 +
 +    /*
       * Look for hint output
       */
      if (sscanf(message, "Hint: %s", buf1) == 1) {
                r = p + 1;
            }
        }
 -            
 +
          GameEnds(GameIsDrawn, r, GE_ENGINE1 + (cps != &first));
        return;
  
        }
      }
  
 -    
 +
      /*
       * Look for thinking output
       */
                }
  
                  /* [AS] Negate score if machine is playing black and reporting absolute scores */
 -                if( cps->scoreIsAbsolute && 
 +                if( cps->scoreIsAbsolute &&
                      ((gameMode == MachinePlaysBlack) || (gameMode == TwoMachinesPlay && cps->twoMachinesColor[0] == 'b')) )
                  {
                      curscore = -curscore;
  
                        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 */
  
                  SendProgramStatsToFrontend( cps, &programStats );
  
 -                /* 
 +                /*
                      [AS] Protect the thinkOutput buffer from overflow... this
                      is only useful if buf1 hasn't overflowed first!
                  */
                sprintf(thinkOutput, "[%d]%c%+.2f %s%s",
 -                      plylev, 
 +                      plylev,
                        (gameMode == TwoMachinesPlay ?
                         ToUpper(cps->twoMachinesColor[0]) : ' '),
                        ((double) curscore) / 100.0,
                programStats.line_is_book = 1;
  
                  SendProgramStatsToFrontend( cps, &programStats );
 -                
 -              if (currentMove == forwardMostMove || gameMode==AnalyzeMode || 
 +
 +              if (currentMove == forwardMostMove || gameMode==AnalyzeMode ||
                             gameMode == AnalyzeFile || appData.icsEngineAnalyze) {
                    DisplayMove(currentMove - 1);
                }
            buf1[0] = NULLCHAR;
  
            if (sscanf(message, "%d%c %d %d " u64Display " %[^\n]\n",
 -                     &plylev, &plyext, &curscore, &time, &nodes, buf1) >= 5) 
 +                     &plylev, &plyext, &curscore, &time, &nodes, buf1) >= 5)
              {
                  ChessProgramStats cpstats;
  
  
  /* Parse a game score from the character string "game", and
     record it as the history of the current game.  The game
 -   score is NOT assumed to start from the standard position. 
 +   score is NOT assumed to start from the standard position.
     The display is not updated in any way.
     */
  void
@@@ -7340,7 -7318,7 +7365,7 @@@ ParseGameHistory(game
        strcpy(moveList[boardIndex], currentMoveString);
        strcat(moveList[boardIndex], "\n");
        boardIndex++;
 -      ApplyMove(fromX, fromY, toX, toY, promoChar, boards[boardIndex], 
 +      ApplyMove(fromX, fromY, toX, toY, promoChar, boards[boardIndex],
                                        castlingRights[boardIndex], &epStatus[boardIndex]);
          switch (MateTest(boards[boardIndex], PosFlags(boardIndex),
                                   EP_UNKNOWN, castlingRights[boardIndex]) ) {
@@@ -7380,8 -7358,8 +7405,8 @@@ ApplyMove(fromX, fromY, toX, toY, promo
        oldEP = *ep;
        *ep = EP_NONE;
  
 -      if( board[toY][toX] != EmptySquare ) 
 -           *ep = EP_CAPTURE;  
 +      if( board[toY][toX] != EmptySquare )
 +           *ep = EP_CAPTURE;
  
        if( board[fromY][fromX] == WhitePawn ) {
             if(fromY != toY) // [HGM] Xiangqi sideway Pawn moves should not count as 50-move breakers
                        gameInfo.variant != VariantBerolina || toX < fromX)
                      *ep = toX | berolina;
                 if(toX<BOARD_RGHT-1 && board[toY][toX+1] == BlackPawn &&
 -                      gameInfo.variant != VariantBerolina || toX > fromX) 
 +                      gameInfo.variant != VariantBerolina || toX > fromX)
                      *ep = toX;
           }
 -      } else 
 +      } else
        if( board[fromY][fromX] == BlackPawn ) {
             if(fromY != toY) // [HGM] Xiangqi sideway Pawn moves should not count as 50-move breakers
 -             *ep = EP_PAWN_MOVE; 
 +             *ep = EP_PAWN_MOVE;
             if( toY-fromY== -2) {
                 if(toX>BOARD_LEFT   && board[toY][toX-1] == WhitePawn &&
                        gameInfo.variant != VariantBerolina || toX < fromX)
                      *ep = toX | berolina;
                 if(toX<BOARD_RGHT-1 && board[toY][toX+1] == WhitePawn &&
 -                      gameInfo.variant != VariantBerolina || toX > fromX) 
 +                      gameInfo.variant != VariantBerolina || toX > fromX)
                      *ep = toX;
           }
         }
  
         for(i=0; i<nrCastlingRights; i++) {
             if(castling[i] == fromX && castlingRank[i] == fromY ||
 -              castling[i] == toX   && castlingRank[i] == toY   
 +              castling[i] == toX   && castlingRank[i] == toY
               ) castling[i] = -1; // revoke for moved or captured piece
         }
  
    /* [HGM] In Shatranj and Courier all promotions are to Ferz */
    if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier)
         && promoChar != 0) promoChar = PieceToChar(WhiteFerz);
 -         
 +
    if (fromX == toX && fromY == toY) return;
  
    if (fromY == DROP_RANK) {
        if (captured != EmptySquare && gameInfo.holdingsSize > 0
            && gameInfo.variant != VariantBughouse        ) {
          /* [HGM] holdings: Add to holdings, if holdings exist */
 -      if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) { 
 +      if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
                // [HGM] superchess: suppress flipping color of captured pieces by reverse pre-flip
                captured = (int) captured >= (int) BlackPawn ? BLACK_TO_WHITE captured : WHITE_TO_BLACK captured;
        }
          board[toY][toX] = (ChessSquare) (PROMOTED piece);
      }
  
 -    if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) 
 -              && promoChar != NULLCHAR && gameInfo.holdingsSize) { 
 +    if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat)
 +              && promoChar != NULLCHAR && gameInfo.holdingsSize) {
        // [HGM] superchess: take promotion piece out of holdings
        int k = PieceToNumber(CharToPiece(ToUpper(promoChar)));
        if((int)piece < (int)BlackPawn) { // determine stm from piece color
@@@ -7685,10 -7663,10 +7710,10 @@@ MakeMove(fromX, fromY, toX, toY, promoC
          if(gameInfo.variant == VariantKnightmate)
              king += (int) WhiteUnicorn - (int) WhiteKing;
          if(forwardMostMove == 0) {
 -            if(blackPlaysFirst) 
 +            if(blackPlaysFirst)
                  fprintf(serverMoves, "%s;", second.tidy);
              fprintf(serverMoves, "%s;", first.tidy);
 -            if(!blackPlaysFirst) 
 +            if(!blackPlaysFirst)
                  fprintf(serverMoves, "%s;", second.tidy);
          } else fprintf(serverMoves, loadFlag|lastLoadFlag ? ":" : ";");
          lastLoadFlag = loadFlag;
      }
      CopyBoard(boards[forwardMostMove+1], boards[forwardMostMove]);
      {int i; for(i=0; i<BOARD_SIZE; i++) castlingRights[forwardMostMove+1][i] = castlingRights[forwardMostMove][i];}
 -    ApplyMove(fromX, fromY, toX, toY, promoChar, boards[forwardMostMove+1], 
 +    ApplyMove(fromX, fromY, toX, toY, promoChar, boards[forwardMostMove+1],
                                castlingRights[forwardMostMove+1], &epStatus[forwardMostMove+1]);
      forwardMostMove++; // [HGM] bare: moved to after ApplyMove, to make sure clock interrupt finds complete board
      SwitchClocks(); // uses forwardMostMove, so must be done after incrementing it !
@@@ -7776,24 -7754,17 +7801,24 @@@ ShowMove(fromX, fromY, toX, toY
  {
      int instant = (gameMode == PlayFromGameFile) ?
        (matchMode || (appData.timeDelay == 0 && !pausing)) : pausing;
 +
      if(appData.noGUI) return;
 -    if (!pausing || gameMode == PlayFromGameFile || gameMode == AnalyzeFile) {
 -      if (!instant) {
 -          if (forwardMostMove == currentMove + 1) {
 -              AnimateMove(boards[forwardMostMove - 1],
 -                          fromX, fromY, toX, toY);
 -          }
 -          if (appData.highlightLastMove) {
 +
 +    if (!pausing || gameMode == PlayFromGameFile || gameMode == AnalyzeFile)
 +      {
 +      if (!instant)
 +        {
 +          if (forwardMostMove == currentMove + 1)
 +            {
 +//TODO
 +//            AnimateMove(boards[forwardMostMove - 1],
 +//                        fromX, fromY, toX, toY);
 +            }
 +          if (appData.highlightLastMove)
 +            {
                SetHighlights(fromX, fromY, toX, toY);
 -          }
 -      }
 +            }
 +        }
        currentMove = forwardMostMove;
      }
  
      DrawPosition(FALSE, boards[currentMove]);
      DisplayBothClocks();
      HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1);
 +
 +    return;
  }
  
  void SendEgtPath(ChessProgramState *cps)
            name[0] = ','; // extract next format name from feature and copy with prefixed ','
            while(*p && *p != ',') *q++ = *p++;
            *q++ = ':'; *q = 0;
 -          if( appData.defaultPathEGTB && appData.defaultPathEGTB[0] && 
 +          if( appData.defaultPathEGTB && appData.defaultPathEGTB[0] &&
                strcmp(name, ",nalimov:") == 0 ) {
                // take nalimov path from the menu-changeable option first, if it is defined
                sprintf(buf, "egtpath nalimov %s\n", appData.defaultPathEGTB);
@@@ -7884,7 -7853,7 +7909,7 @@@ InitChessProgram(cps, setup
             overruled = gameInfo.boardWidth != 9 || gameInfo.boardHeight != 9 || gameInfo.holdingsSize != 7;
        if( gameInfo.variant == VariantBughouse || gameInfo.variant == VariantCrazyhouse )
             overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 5;
 -      if( gameInfo.variant == VariantCapablanca || gameInfo.variant == VariantCapaRandom || 
 +      if( gameInfo.variant == VariantCapablanca || gameInfo.variant == VariantCapaRandom ||
                                 gameInfo.variant == VariantGothic  || gameInfo.variant == VariantFalcon )
             overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0;
        if( gameInfo.variant == VariantCourier )
             overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 8;
  
        if(overruled) {
 -           sprintf(b, "%dx%d+%d_%s", gameInfo.boardWidth, gameInfo.boardHeight, 
 +           sprintf(b, "%dx%d+%d_%s", gameInfo.boardWidth, gameInfo.boardHeight,
                                 gameInfo.holdingsSize, VariantName(gameInfo.variant)); // cook up sized variant name
             /* [HGM] varsize: try first if this defiant size variant is specifically known */
 -           if(StrStr(cps->variants, b) == NULL) { 
 +           if(StrStr(cps->variants, b) == NULL) {
                 // specific sized variant not known, check if general sizing allowed
                 if (cps->protocolVersion != 1) { // for protocol 1 we cannot check and hope for the best
                     if(StrStr(cps->variants, "boardsize") == NULL) {
                        timeIncrement, appData.searchDepth,
                        searchTime);
      }
 -    if (appData.showThinking 
 +    if (appData.showThinking
        // [HGM] thinking: four options require thinking output to be sent
        || !appData.hideThinkingFromHuman || appData.adjudicateLossThreshold != 0 || EngineOutputIsUp()
                                ) {
        SendToProgram(buf, cps);
      }
      cps->initDone = TRUE;
 -}   
 +}
  
  
  void
@@@ -7981,7 -7950,7 +8006,7 @@@ StartChessProgram(cps
        }
        err = StartChildProcess(buf, "", &cps->pr);
      }
 -    
 +
      if (err != 0) {
        sprintf(buf, _("Startup failure on '%s'"), cps->program);
        DisplayFatalError(buf, err, 1);
        cps->isr = NULL;
        return;
      }
 -    
 +
      cps->isr = AddInputSource(cps->pr, TRUE, ReceiveFromProgram, cps);
      if (cps->protocolVersion > 1) {
        sprintf(buf, "xboard\nprotover %d\n", cps->protocolVersion);
@@@ -8022,14 -7991,14 +8047,14 @@@ 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;
        if(index < 0) { // [HGM] autoinc
            lastIndex = index = (index == -2 && first.twoMachinesColor[0] == 'b') ? lastIndex : lastIndex+1;
            if(appData.rewindIndex > 0 && index > appData.rewindIndex) lastIndex = index = 1;
 -      } 
 +      }
        LoadGameFromFile(appData.loadGameFile,
                         index,
                         appData.loadGameFile, FALSE);
        if(index < 0) { // [HGM] autoinc
            lastIndex = index = (index == -2 && first.twoMachinesColor[0] == 'b') ? lastIndex : lastIndex+1;
            if(appData.rewindIndex > 0 && index > appData.rewindIndex) lastIndex = index = 1;
 -      } 
 +      }
        LoadPositionFromFile(appData.loadPositionFile,
                             index,
                             appData.loadPositionFile);
@@@ -8105,8 -8074,8 +8130,8 @@@ GameEnds(result, resultDetails, whosays
  
      if (appData.icsActive && (whosays == GE_ENGINE || whosays >= GE_ENGINE1)) {
        /* If we are playing on ICS, the server decides when the
 -         game is over, but the engine can offer to draw, claim 
 -         a draw, or resign. 
 +         game is over, but the engine can offer to draw, claim
 +         a draw, or resign.
         */
  #if ZIPPY
        if (appData.zippyPlay && first.initDone) {
  
      /* If this is an ICS game, only ICS can really say it's done;
         if not, anyone can. */
 -    isIcsGame = (gameMode == IcsPlayingWhite || 
 -               gameMode == IcsPlayingBlack || 
 -               gameMode == IcsObserving    || 
 +    isIcsGame = (gameMode == IcsPlayingWhite ||
 +               gameMode == IcsPlayingBlack ||
 +               gameMode == IcsObserving    ||
                 gameMode == IcsExamining);
  
      if (!isIcsGame || whosays == GE_ICS) {
        /* OK -- not an ICS game, or ICS said it was done */
        StopClocks();
 -      if (!isIcsGame && !appData.noChessProgram) 
 +      if (!isIcsGame && !appData.noChessProgram)
          SetUserThinkingEnables();
 -    
 +
          /* [HGM] if a machine claims the game end we verify this claim */
          if(gameMode == TwoMachinesPlay && appData.testClaims) {
            if(appData.testLegality && whosays >= GE_ENGINE1 ) {
                  }
                  /* (Claiming a loss is accepted no questions asked!) */
            }
 +
            /* [HGM] bare: don't allow bare King to win */
            if((gameInfo.holdingsWidth == 0 || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat)
 -             && gameInfo.variant != VariantLosers && gameInfo.variant != VariantGiveaway 
 +             && gameInfo.variant != VariantLosers && gameInfo.variant != VariantGiveaway
               && gameInfo.variant != VariantSuicide // [HGM] losers: except in losers, of course...
               && result != GameIsDrawn)
            {   int i, j, k=0, color = (result==WhiteWins ? (int)WhitePawn : (int)BlackPawn);
            }
          }
  
 -
          if(serverMoves != NULL && !loadFlag) { char c = '=';
              if(result==WhiteWins) c = '+';
              if(result==BlackWins) c = '-';
            /* display last move only if game was not loaded from file */
            if ((whosays != GE_FILE) && (currentMove == forwardMostMove))
                DisplayMove(currentMove - 1);
 -    
 +
            if (forwardMostMove != 0) {
                if (gameMode != PlayFromGameFile && gameMode != EditGame
                    && lastSavedGame != GameCheckSum() // [HGM] save: suppress duplicates
                }
            }
        } else if (gameMode == EditGame ||
 -                 gameMode == PlayFromGameFile || 
 -                 gameMode == AnalyzeMode || 
 +                 gameMode == PlayFromGameFile ||
 +                 gameMode == AnalyzeMode ||
                   gameMode == AnalyzeFile) {
            nextGameMode = gameMode;
        } else {
        if (first.isr != NULL)
          RemoveInputSource(first.isr);
        first.isr = NULL;
 -    
 +
        if (first.pr != NoProc) {
            ExitAnalyzeMode();
              DoSleep( appData.delayBeforeQuit );
        if (second.isr != NULL)
          RemoveInputSource(second.isr);
        second.isr = NULL;
 -    
 +
        if (second.pr != NoProc) {
              DoSleep( appData.delayBeforeQuit );
            SendToProgram("quit\n", &second);
  /* Assumes program was just initialized (initString sent).
     Leaves program in force mode. */
  void
 -FeedMovesToProgram(cps, upto) 
 +FeedMovesToProgram(cps, upto)
       ChessProgramState *cps;
       int upto;
  {
      int i;
 -    
 +
      if (appData.debugMode)
        fprintf(debugFP, "Feeding %smoves %d through %d to %s chess program\n",
              startedFromSetupPosition ? "position and " : "",
@@@ -8482,7 -8451,7 +8507,7 @@@ ResurrectChessProgram(
        If so, restart it and feed it all the moves made so far. */
  
      if (appData.noChessProgram || first.pr != NoProc) return;
 -    
 +
      StartChessProgram(&first);
      InitChessProgram(&first, FALSE);
      FeedMovesToProgram(&first, currentMove);
@@@ -8535,7 -8504,7 +8560,7 @@@ Reset(redraw, init
      white_holding[0] = black_holding[0] = NULLCHAR;
      ClearProgramStats();
      opponentKibitzes = FALSE; // [HGM] kibitz: do not reserve space in engine-output window in zippy mode
 -    
 +
      ResetFrontEnd();
      ClearHighlights();
      flipView = appData.flipView;
      ExitAnalyzeMode();
      gameMode = BeginningOfGame;
      ModeHighlight();
 +
      if(appData.icsActive) gameInfo.variant = VariantNormal;
      currentMove = forwardMostMove = backwardMostMove = 0;
      InitPosition(redraw);
            commentList[i] = NULL;
        }
      }
 +
      ResetClocks();
      timeRemaining[0][0] = whiteTimeRemaining;
      timeRemaining[1][0] = blackTimeRemaining;
      if (init) {
            InitChessProgram(&first, startedFromSetupPosition);
      }
 +
      DisplayTitle("");
      DisplayMessage("", "");
      HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1);
      lastSavedGame = 0; // [HGM] save: make sure next game counts as unsaved
 +    return;
  }
  
  void
@@@ -8625,7 -8590,7 +8650,7 @@@ AutoPlayOneMove(
  
        return FALSE;
      }
 -    
 +
      toX = moveList[currentMove][2] - AAA;
      toY = moveList[currentMove][3] - ONE;
  
@@@ -8664,13 -8629,13 +8689,13 @@@ LoadGameOneMove(readAhead
      ChessMove moveType;
      char move[MSG_SIZ];
      char *p, *q;
 -    
 -    if (gameMode != PlayFromGameFile && gameMode != AnalyzeFile && 
 +
 +    if (gameMode != PlayFromGameFile && gameMode != AnalyzeFile &&
        gameMode != AnalyzeMode && gameMode != Training) {
        gameFileFP = NULL;
        return FALSE;
      }
 -    
 +
      yyboardindex = forwardMostMove;
      if (readAhead != (ChessMove)0) {
        moveType = readAhead;
          return FALSE;
        moveType = (ChessMove) yylex();
      }
 -    
 +
      done = FALSE;
      switch (moveType) {
        case Comment:
 -      if (appData.debugMode) 
 +      if (appData.debugMode)
          fprintf(debugFP, "Parsed Comment: %s\n", yy_text);
        p = yy_text;
        if (*p == '{' || *p == '[' || *p == '(') {
        /* currentMoveString is set as a side-effect of yylex */
        strcat(currentMoveString, "\n");
        strcpy(moveList[forwardMostMove], currentMoveString);
 -      
 +
        thinkOutput[0] = NULLCHAR;
        MakeMove(fromX, fromY, toX, toY, promoChar);
        currentMove = forwardMostMove;
@@@ -8942,8 -8907,7 +8967,8 @@@ LoadGameFromFile(filename, n, title, us
            DisplayError(_("Cannot build game list"), error);
        } else if (!ListEmpty(&gameList) &&
                   ((ListGame *) gameList.tailPred)->number > 1) {
 -          GameListPopUp(f, title);
 +        // TODO convert to GTK
 +        //        GameListPopUp(f, title);
            return TRUE;
        }
        GameListDestroy();
@@@ -8966,7 -8930,7 +8991,7 @@@ MakeRegisteredMove(
            if (appData.debugMode)
              fprintf(debugFP, "Restoring %s for game %d\n",
                      cmailMove[lastLoadGameNumber - 1], lastLoadGameNumber);
 -    
 +
            thinkOutput[0] = NULLCHAR;
            strcpy(moveList[currentMove], cmailMove[lastLoadGameNumber - 1]);
              fromX = cmailMove[lastLoadGameNumber - 1][0] - AAA;
            promoChar = cmailMove[lastLoadGameNumber - 1][4];
            MakeMove(fromX, fromY, toX, toY, promoChar);
            ShowMove(fromX, fromY, toX, toY);
 -            
 +
            switch (MateTest(boards[currentMove], PosFlags(currentMove),
                               EP_UNKNOWN, castlingRights[currentMove]) ) {
              case MT_NONE:
              case MT_CHECK:
                break;
 -              
 +
              case MT_CHECKMATE:
              case MT_STAINMATE:
                if (WhiteOnMove(currentMove)) {
                    GameEnds(WhiteWins, "White mates", GE_PLAYER);
                }
                break;
 -              
 +
              case MT_STALEMATE:
                GameEnds(GameIsDrawn, "Stalemate", GE_PLAYER);
                break;
            }
  
            break;
 -          
 +
          case CMAIL_RESIGN:
            if (WhiteOnMove(currentMove)) {
                GameEnds(BlackWins, "White resigns", GE_PLAYER);
                GameEnds(WhiteWins, "Black resigns", GE_PLAYER);
            }
            break;
 -          
 +
          case CMAIL_ACCEPT:
            GameEnds(GameIsDrawn, "Draw agreed", GE_PLAYER);
            break;
 -            
 +
          default:
            break;
        }
@@@ -9106,90 -9070,71 +9131,90 @@@ LoadGame(f, gameNumber, title, useList
      GameMode oldGameMode;
      VariantClass oldVariant = gameInfo.variant; /* [HGM] PGNvariant */
  
 -    if (appData.debugMode) 
 +    if (appData.debugMode)
        fprintf(debugFP, "LoadGame(): on entry, gameMode %d\n", gameMode);
  
      if (gameMode == Training )
        SetTrainingModeOff();
  
      oldGameMode = gameMode;
 -    if (gameMode != BeginningOfGame) {
 -      Reset(FALSE, TRUE);
 -    }
 +    if (gameMode != BeginningOfGame) 
 +      {
 +      Reset(FALSE, TRUE);
 +      };
  
      gameFileFP = f;
 -    if (lastLoadGameFP != NULL && lastLoadGameFP != f) {
 +    if (lastLoadGameFP != NULL && lastLoadGameFP != f) 
 +      {
        fclose(lastLoadGameFP);
 -    }
 +      };
  
 -    if (useList) {
 +    if (useList) 
 +      {
        lg = (ListGame *) ListElem(&gameList, gameNumber-1);
        
 -      if (lg) {
 +      if (lg) 
 +        {
            fseek(f, lg->offset, 0);
            GameListHighlight(gameNumber);
            gn = 1;
 -      }
 -      else {
 +        }
 +      else 
 +        {
            DisplayError(_("Game number out of range"), 0);
            return FALSE;
 -      }
 -    } else {
 +        };
 +      } 
 +    else 
 +      {
        GameListDestroy();
 -      if (fseek(f, 0, 0) == -1) {
 +      if (fseek(f, 0, 0) == -1) 
 +        {
            if (f == lastLoadGameFP ?
                gameNumber == lastLoadGameNumber + 1 :
 -              gameNumber == 1) {
 +              gameNumber == 1) 
 +            {
                gn = 1;
 -          } else {
 +            } 
 +          else 
 +            {
                DisplayError(_("Can't seek on game file"), 0);
                return FALSE;
 -          }
 -      }
 -    }
 -    lastLoadGameFP = f;
 -    lastLoadGameNumber = gameNumber;
 +            };
 +        };
 +      };
 +
 +    lastLoadGameFP    = f;
 +    lastLoadGameNumber        = gameNumber;
      strcpy(lastLoadGameTitle, title);
      lastLoadGameUseList = useList;
  
      yynewfile(f);
  
 -    if (lg && lg->gameInfo.white && lg->gameInfo.black) {
 -      snprintf(buf, sizeof(buf), "%s vs. %s", lg->gameInfo.white,
 -              lg->gameInfo.black);
 -          DisplayTitle(buf);
 -    } else if (*title != NULLCHAR) {
 -      if (gameNumber > 1) {
 +    if (lg && lg->gameInfo.white && lg->gameInfo.black) 
 +      {
 +      snprintf(buf, sizeof(buf), "%s vs. %s", lg->gameInfo.white,
 +               lg->gameInfo.black);
 +      DisplayTitle(buf);
 +      } 
 +    else if (*title != NULLCHAR) 
 +      {
 +      if (gameNumber > 1) 
 +        {
            sprintf(buf, "%s %d", title, gameNumber);
            DisplayTitle(buf);
 -      } else {
 +        } 
 +      else 
 +        {
            DisplayTitle(title);
 -      }
 -    }
 +        };
 +      };
  
 -    if (gameMode != AnalyzeFile && gameMode != AnalyzeMode) {
 +    if (gameMode != AnalyzeFile && gameMode != AnalyzeMode) 
 +      {
        gameMode = PlayFromGameFile;
        ModeHighlight();
 -    }
 +      };
  
      currentMove = forwardMostMove = backwardMostMove = 0;
      CopyBoard(boards[0], initialPosition);
  
      /*
       * Skip the first gn-1 games in the file.
 -     * Also skip over anything that precedes an identifiable 
 -     * start of game marker, to avoid being confused by 
 -     * garbage at the start of the file.  Currently 
 +     * Also skip over anything that precedes an identifiable
 +     * start of game marker, to avoid being confused by
 +     * garbage at the start of the file.  Currently
       * recognized start of game markers are the move number "1",
       * the pattern "gnuchess .* game", the pattern
 -     * "^[#;%] [^ ]* game file", and a PGN tag block.  
 +     * "^[#;%] [^ ]* game file", and a PGN tag block.
       * A game that starts with one of the latter two patterns
       * will also have a move number 1, possibly
       * following a position diagram.
            gn--;
            lastLoadGameStart = cm;
            break;
 -          
 +
          case MoveNumberOne:
            switch (lastLoadGameStart) {
              case GNUChessGame:
            break;
        }
      }
 -    
 +
      if (appData.debugMode)
        fprintf(debugFP, "Parsed game start '%s' (%d)\n", yy_text, (int) cm);
  
            free(gameInfo.event);
        }
        gameInfo.event = StrSave(yy_text);
 -    } 
 +    }
  
      startedFromSetupPosition = FALSE;
      while (cm == PGNTag) {
 -      if (appData.debugMode) 
 +      if (appData.debugMode)
          fprintf(debugFP, "Parsed PGNTag: %s\n", yy_text);
        err = ParsePGNTag(yy_text, &gameInfo);
        if (!err) numPGNTags++;
              startedFromPositionFile = FALSE; /* [HGM] loadPos: variant switch likely makes position invalid */
            InitPosition(TRUE);
              oldVariant = gameInfo.variant;
 -          if (appData.debugMode) 
 +          if (appData.debugMode)
              fprintf(debugFP, "New variant %d\n", (int) oldVariant);
          }
  
        /* Handle comments interspersed among the tags */
        while (cm == Comment) {
            char *p;
 -          if (appData.debugMode) 
 +          if (appData.debugMode)
              fprintf(debugFP, "Parsed Comment: %s\n", yy_text);
            p = yy_text;
            if (*p == '{' || *p == '[' || *p == '(') {
                }
            while (*p == ' ' || *p == '\t' ||
                   *p == '\n' || *p == '\r') p++;
 -      
 +
            if (strncmp(p, "black", strlen("black"))==0)
              blackPlaysFirst = TRUE;
            else
              blackPlaysFirst = FALSE;
            startedFromSetupPosition = TRUE;
 -      
 +
            CopyBoard(boards[0], initial_position);
            if (blackPlaysFirst) {
                currentMove = forwardMostMove = backwardMostMove = 1;
          fprintf(debugFP, "Load Game\n");
      }
        DisplayBothClocks();
 -    }      
 +    }
  
      /* [HGM] server: flag to write setup moves in broadcast file as one */
      loadFlag = appData.suppressLoadMoves;
  
      while (cm == Comment) {
        char *p;
 -      if (appData.debugMode) 
 +      if (appData.debugMode)
          fprintf(debugFP, "Parsed Comment: %s\n", yy_text);
        p = yy_text;
        if (*p == '{' || *p == '[' || *p == '(') {
      if (!matchMode && (pausing || appData.timeDelay != 0)) {
        DisplayComment(currentMove - 1, commentList[currentMove]);
      }
 -    if (!matchMode && appData.timeDelay != 0) 
 +    if (!matchMode && appData.timeDelay != 0)
        DrawPosition(FALSE, boards[currentMove]);
  
      if (gameMode == AnalyzeFile || gameMode == AnalyzeMode) {
      }
  
      /* if the first token after the PGN tags is a move
 -     * and not move number 1, retrieve it from the parser 
 +     * and not move number 1, retrieve it from the parser
       */
      if (cm != MoveNumberOne)
        LoadGameOneMove(cm);
        AutoPlayGameLoop();
      }
  
 -    if (appData.debugMode) 
 +    if (appData.debugMode)
        fprintf(debugFP, "LoadGame(): on exit, gameMode %d\n", gameMode);
  
      loadFlag = 0; /* [HGM] true game starts */
@@@ -9620,7 -9565,7 +9645,7 @@@ LoadPosition(f, positionNumber, title
      char *p, line[MSG_SIZ];
      Board initial_position;
      int i, j, fenMode, pn;
 -    
 +
      if (gameMode == Training )
        SetTrainingModeOff();
  
      if (first.pr == NoProc) {
        StartChessProgram(&first);
        InitChessProgram(&first, FALSE);
 -    }    
 +    }
      pn = positionNumber;
      if (positionNumber < 0) {
        /* Negative position number means to seek to that byte offset */
      } else {
        (void) fgets(line, MSG_SIZ, f);
        (void) fgets(line, MSG_SIZ, f);
 -    
 +
          for (i = BOARD_HEIGHT - 1; i >= 0; i--) {
            (void) fgets(line, MSG_SIZ, f);
              for (p = line, j = BOARD_LEFT; j < BOARD_RGHT; p++) {
                initial_position[i][j++] = CharToPiece(*p);
            }
        }
 -    
 +
        blackPlaysFirst = FALSE;
        if (!feof(f)) {
            (void) fgets(line, MSG_SIZ, f);
        }
      }
      startedFromSetupPosition = TRUE;
 -    
 +
      SendToProgram("force\n", &first);
      CopyBoard(boards[0], initial_position);
      if (blackPlaysFirst) {
@@@ -9745,7 -9690,7 +9770,7 @@@ int i, j
      timeRemaining[0][1] = whiteTimeRemaining;
      timeRemaining[1][1] = blackTimeRemaining;
      DrawPosition(FALSE, boards[currentMove]);
 -   
 +
      return TRUE;
  }
  
@@@ -9812,7 -9757,7 +9837,7 @@@ SavePart(str
  {
      static char buf[MSG_SIZ];
      char *p;
 -    
 +
      p = strchr(str, ' ');
      if (p == NULL) return str;
      strncpy(buf, str, p - str);
@@@ -9891,7 -9836,7 +9916,7 @@@ void GetOutOfBookInfo( char * buf 
                  }
  
                  sprintf( buf+strlen(buf), "%d%s. ", (idx - offset)/2 + 1, idx & 1 ? ".." : "" );
 -                sprintf( buf+strlen(buf), "%s%.2f", 
 +                sprintf( buf+strlen(buf), "%s%.2f",
                      pvInfoList[idx].score >= 0 ? "+" : "",
                      pvInfoList[idx].score / 100.0 );
              }
@@@ -9912,11 -9857,11 +9937,11 @@@ SaveGamePGN(f
      char move_buffer[100]; /* [AS] Buffer for move+PV info */
  
      offset = backwardMostMove & (~1L); /* output move numbers start at 1 */
 -    
 +
      tm = time((time_t *) NULL);
 -    
 +
      PrintPGNTags(f, &gameInfo);
 -    
 +
      if (backwardMostMove > 0 || startedFromSetupPosition) {
          char *fen = PositionToFEN(backwardMostMove, NULL);
          fprintf(f, "[FEN \"%s\"]\n[SetUp \"1\"]\n", fen);
              GetOutOfBookInfo( buf );
  
              if( buf[0] != '\0' ) {
 -                fprintf( f, "[%s \"%s\"]\n", PGN_OUT_OF_BOOK, buf ); 
 +                fprintf( f, "[%s \"%s\"]\n", PGN_OUT_OF_BOOK, buf );
              }
          }
  
                                   sprintf(buf, " %d:%02d%c", seconds/60, seconds%60, 0);
            }
  
 -            sprintf( move_buffer, "{%s%.2f/%d%s}", 
 +            sprintf( move_buffer, "{%s%.2f/%d%s}",
                  pvInfoList[i].score >= 0 ? "+" : "",
                  pvInfoList[i].score / 100.0,
                  pvInfoList[i].depth,
  
        i++;
      }
 -    
 +
      /* Start a new line */
      if (linelen > 0) fprintf(f, "\n");
  
@@@ -10075,12 -10020,12 +10100,12 @@@ SaveGameOldStyle(f
  {
      int i, offset;
      time_t tm;
 -    
 +
      tm = time((time_t *) NULL);
 -    
 +
      fprintf(f, "# %s game file -- %s", programName, ctime(&tm));
      PrintOpponents(f);
 -    
 +
      if (backwardMostMove > 0 || startedFromSetupPosition) {
        fprintf(f, "\n[--------------\n");
        PrintPosition(f, backwardMostMove);
            i++;
        }
      }
 -    
 +
      if (commentList[i] != NULL) {
        fprintf(f, "[%s]\n", commentList[i]);
      }
@@@ -10180,10 -10125,10 +10205,10 @@@ SavePosition(f, dummy, dummy2
  {
      time_t tm;
      char *fen;
 -    
 +
      if (appData.oldSaveStyle) {
        tm = time((time_t *) NULL);
 -    
 +
        fprintf(f, "# %s position file -- %s", programName, ctime(&tm));
        PrintOpponents(f);
        fprintf(f, "[--------------\n");
@@@ -10208,7 -10153,7 +10233,7 @@@ ReloadCmailMsgEvent(unregister
      int i;
      struct stat inbuf, outbuf;
      int status;
 -    
 +
      /* Any registered moves are unregistered if unregister is set, */
      /* i.e. invoked by the signal handler */
      if (unregister) {
        outFilename = (char *) malloc(strlen(appData.cmailGameName) + 5);
        sprintf(outFilename, "%s.out", appData.cmailGameName);
      }
 -    
 +
      status = stat(outFilename, &outbuf);
      if (status < 0) {
        cmailMailedMove = FALSE;
        status = stat(inFilename, &inbuf);
        cmailMailedMove = (inbuf.st_mtime < outbuf.st_mtime);
      }
 -    
 +
      /* LoadGameFromFile(CMAIL_MAX_GAMES) with cmailMsgLoaded == TRUE
         counts the games, notes how each one terminated, etc.
 -       
 +
         It would be nice to remove this kludge and instead gather all
         the information while building the game list.  (And to keep it
         in the game list nodes instead of having a bunch of fixed-size
         */
      cmailMsgLoaded = TRUE;
      LoadGameFromFile(inFilename, CMAIL_MAX_GAMES, "", FALSE);
 -    
 +
      /* Load first game in the file or popup game menu */
      LoadGameFromFile(inFilename, 0, appData.cmailGameName, TRUE);
  
@@@ -10283,7 -10228,7 +10308,7 @@@ RegisterMove(
        cmailMoveRegistered[lastLoadGameNumber - 1] = FALSE;
        nCmailMovesRegistered --;
  
 -      if (cmailCommentList[lastLoadGameNumber - 1] != NULL) 
 +      if (cmailCommentList[lastLoadGameNumber - 1] != NULL)
          {
              free(cmailCommentList[lastLoadGameNumber - 1]);
              cmailCommentList[lastLoadGameNumber - 1] = NULL;
  
        sprintf(string,
                "%s.game.out.%d", appData.cmailGameName, lastLoadGameNumber);
 -      
 +
        f = fopen(string, "w");
        if (appData.oldSaveStyle) {
            SaveGameOldStyle(f); /* also closes the file */
 -          
 +
            sprintf(string, "%s.pos.out", appData.cmailGameName);
            f = fopen(string, "w");
            SavePosition(f, 0, NULL); /* also closes the file */
            fprintf(f, "{--------------\n");
            PrintPosition(f, currentMove);
            fprintf(f, "--------------}\n\n");
 -          
 +
            SaveGame(f, 0, NULL); /* also closes the file*/
        }
 -      
 +
        cmailMoveRegistered[lastLoadGameNumber - 1] = TRUE;
        nCmailMovesRegistered ++;
      } else if (nCmailGames == 1) {
@@@ -10388,7 -10333,7 +10413,7 @@@ MailMoveEvent(
  #endif
  
      if (! (cmailMailedMove || RegisterMove())) return;
 -    
 +
      if (   cmailMailedMove
        || (nCmailMovesRegistered + nCmailResults == nCmailGames)) {
        sprintf(string, partCommandString,
@@@ -10454,7 -10399,7 +10479,7 @@@ CmailMsg(
      char number[5];
      char string[MSG_SIZ];     /* Space for game-list */
      int  i;
 -    
 +
      if (!cmailMsgLoaded) return "";
  
      if (cmailMailedMove) {
                    sprintf(number, "%d", i + 1);
                    prependComma = 1;
                }
 -              
 +
                strcat(string, number);
            }
        }
                sprintf(cmailMsg,
                        _("Still need to make move for game\n"));
                break;
 -              
 +
              case 2:
                sprintf(cmailMsg,
                        _("Still need to make moves for both games\n"));
                break;
 -              
 +
              default:
                sprintf(cmailMsg,
                        _("Still need to make moves for all %d games\n"),
                        _("Still need to make a move for game %s\n"),
                        string);
                break;
 -              
 +
              case 0:
                if (nCmailResults == nCmailGames) {
                    sprintf(cmailMsg, _("No unfinished games\n"));
                    sprintf(cmailMsg, _("Ready to send mail\n"));
                }
                break;
 -              
 +
              default:
                sprintf(cmailMsg,
                        _("Still need to make moves for games %s\n"),
@@@ -10573,7 -10518,7 +10598,7 @@@ ExitEvent(status
      /* Kill off chess programs */
      if (first.pr != NoProc) {
        ExitAnalyzeMode();
 -        
 +
          DoSleep( appData.delayBeforeQuit );
        SendToProgram("quit\n", &first);
          DoSleep( appData.delayAfterQuit );
@@@ -10611,7 -10556,7 +10636,7 @@@ PauseEvent(
            DisplayBothClocks();
        }
        if (gameMode == PlayFromGameFile) {
 -          if (appData.timeDelay >= 0) 
 +          if (appData.timeDelay >= 0)
                AutoPlayGameLoop();
        } else if (gameMode == IcsExamining && pauseExamInvalid) {
            Reset(FALSE, TRUE);
@@@ -10750,25 -10695,25 +10775,25 @@@ MachineWhiteEvent(
        return;
  
  
 -    if (gameMode == PlayFromGameFile || 
 -      gameMode == TwoMachinesPlay  || 
 -      gameMode == Training         || 
 -      gameMode == AnalyzeMode      || 
 +    if (gameMode == PlayFromGameFile ||
 +      gameMode == TwoMachinesPlay  ||
 +      gameMode == Training         ||
 +      gameMode == AnalyzeMode      ||
        gameMode == EndOfGame)
        EditGameEvent();
  
 -    if (gameMode == EditPosition) 
 +    if (gameMode == EditPosition)
          EditPositionDone();
  
      if (!WhiteOnMove(currentMove)) {
        DisplayError(_("It is not White's turn"), 0);
        return;
      }
 -  
 +
      if (gameMode == AnalyzeMode || gameMode == AnalyzeFile)
        ExitAnalyzeMode();
  
 -    if (gameMode == EditGame || gameMode == AnalyzeMode || 
 +    if (gameMode == EditGame || gameMode == AnalyzeMode ||
        gameMode == AnalyzeFile)
        TruncateGame();
  
      if(bookHit) { // [HGM] book: simulate book reply
        static char bookMove[MSG_SIZ]; // a bit generous?
  
 -      programStats.nodes = programStats.depth = programStats.time = 
 +      programStats.nodes = programStats.depth = programStats.time =
        programStats.score = programStats.got_only_move = 0;
        sprintf(programStats.movelist, "%s (xbook)", bookHit);
  
@@@ -10831,25 -10776,25 +10856,25 @@@ MachineBlackEvent(
        return;
  
  
 -    if (gameMode == PlayFromGameFile || 
 -      gameMode == TwoMachinesPlay  || 
 -      gameMode == Training         || 
 -      gameMode == AnalyzeMode      || 
 +    if (gameMode == PlayFromGameFile ||
 +      gameMode == TwoMachinesPlay  ||
 +      gameMode == Training         ||
 +      gameMode == AnalyzeMode      ||
        gameMode == EndOfGame)
          EditGameEvent();
  
 -    if (gameMode == EditPosition) 
 +    if (gameMode == EditPosition)
          EditPositionDone();
  
      if (WhiteOnMove(currentMove)) {
        DisplayError(_("It is not Black's turn"), 0);
        return;
      }
 -    
 +
      if (gameMode == AnalyzeMode || gameMode == AnalyzeFile)
        ExitAnalyzeMode();
  
 -    if (gameMode == EditGame || gameMode == AnalyzeMode || 
 +    if (gameMode == EditGame || gameMode == AnalyzeMode ||
        gameMode == AnalyzeFile)
        TruncateGame();
  
      if(bookHit) { // [HGM] book: simulate book reply
        static char bookMove[MSG_SIZ]; // a bit generous?
  
 -      programStats.nodes = programStats.depth = programStats.time = 
 +      programStats.nodes = programStats.depth = programStats.time =
        programStats.score = programStats.got_only_move = 0;
        sprintf(programStats.movelist, "%s (xbook)", bookHit);
  
@@@ -10926,7 -10871,7 +10951,7 @@@ TwoMachinesEvent P((void)
      char buf[MSG_SIZ];
      ChessProgramState *onmove;
      char *bookHit = NULL;
 -    
 +
      if (appData.noChessProgram) return;
  
      switch (gameMode) {
      if(bookHit) { // [HGM] book: simulate book reply
        static char bookMove[MSG_SIZ]; // a bit generous?
  
 -      programStats.nodes = programStats.depth = programStats.time = 
 +      programStats.nodes = programStats.depth = programStats.time =
        programStats.score = programStats.got_only_move = 0;
        sprintf(programStats.movelist, "%s (xbook)", bookHit);
  
@@@ -11091,7 -11036,7 +11116,7 @@@ IcsClientEvent(
        case AnalyzeFile:
        ExitAnalyzeMode();
        break;
 -      
 +
        default:
        EditGameEvent();
        break;
@@@ -11156,7 -11101,7 +11181,7 @@@ EditGameEvent(
        default:
        return;
      }
 -    
 +
      pausing = FALSE;
      StopClocks();
      first.offeredDraw = second.offeredDraw = 0;
            whiteFlag = blackFlag = 0;
        }
        DisplayTitle("");
 -    }         
 -    
 +    }
 +
      gameMode = EditGame;
      ModeHighlight();
      SetGameInfo();
@@@ -11198,16 -11143,16 +11223,16 @@@ EditPositionEvent(
        EditGameEvent();
        return;
      }
 -    
 +
      EditGameEvent();
      if (gameMode != EditGame) return;
 -    
 +
      gameMode = EditPosition;
      ModeHighlight();
      SetGameInfo();
      if (currentMove > 0)
        CopyBoard(boards[0], boards[currentMove]);
 -    
 +
      blackPlaysFirst = !WhiteOnMove(currentMove);
      ResetClocks();
      currentMove = forwardMostMove = backwardMostMove = 0;
@@@ -11299,7 -11244,7 +11324,7 @@@ SendMultiLineToICS(buf
      len = strlen(buf);
      if (len > MSG_SIZ)
        len = MSG_SIZ;
 -  
 +
      strncpy(temp, buf, len);
      temp[len] = 0;
  
@@@ -11411,7 -11356,7 +11436,7 @@@ EditPositionMenuEvent(selection, x, y
             piece > (int)BlackMan && piece <= (int)BlackKing   ) {
              selection = (ChessSquare) (DEMOTED piece);
          } else if(piece == EmptySquare) selection = BlackSilver;
 -        else selection = (ChessSquare)((int)piece + 1);       
 +        else selection = (ChessSquare)((int)piece + 1);
          goto defaultlabel;
  
        case WhiteQueen:
  AcceptEvent()
  {
      /* Accept a pending offer of any kind from opponent */
 -    
 +
      if (appData.icsActive) {
          SendToICS(ics_prefix);
        SendToICS("accept\n");
  DeclineEvent()
  {
      /* Decline a pending offer of any kind from opponent */
 -    
 +
      if (appData.icsActive) {
          SendToICS(ics_prefix);
        SendToICS("decline\n");
  DrawEvent()
  {
      /* Offer draw or accept pending draw offer from opponent */
 -    
 +
      if (appData.icsActive) {
        /* Note: tournament rules require draw offers to be
           made after you make your move but before you punch
           your clock.  Currently ICS doesn't let you do that;
           instead, you immediately punch your clock after making
           a move, but you can offer a draw at any time. */
 -      
 +
          SendToICS(ics_prefix);
        SendToICS("draw\n");
      } else if (cmailMsgLoaded) {
  AdjournEvent()
  {
      /* Offer Adjourn or accept pending Adjourn offer from opponent */
 -    
 +
      if (appData.icsActive) {
          SendToICS(ics_prefix);
        SendToICS("adjourn\n");
  AbortEvent()
  {
      /* Offer Abort or accept pending Abort offer from opponent */
 -    
 +
      if (appData.icsActive) {
          SendToICS(ics_prefix);
        SendToICS("abort\n");
  ResignEvent()
  {
      /* Resign.  You can do this even if it's not your turn. */
 -    
 +
      if (appData.icsActive) {
          SendToICS(ics_prefix);
        SendToICS("resign\n");
@@@ -11716,12 -11661,12 +11741,12 @@@ ForwardInner(target
  
      if (gameMode == PlayFromGameFile && !pausing)
        PauseEvent();
 -    
 +
      if (gameMode == IcsExamining && pausing)
        limit = pauseExamForwardMostMove;
      else
        limit = forwardMostMove;
 -    
 +
      if (target > limit) target = limit;
  
      if (target > 0 && moveList[target - 1][0]) {
            }
        }
      }
 -    if (gameMode == EditGame || gameMode == AnalyzeMode || 
 -      gameMode == Training || gameMode == PlayFromGameFile || 
 +    if (gameMode == EditGame || gameMode == AnalyzeMode ||
 +      gameMode == Training || gameMode == PlayFromGameFile ||
        gameMode == AnalyzeFile) {
        while (currentMove < target) {
            SendMoveToProgram(currentMove++, &first);
      } else {
        currentMove = target;
      }
 -    
 +
      if (gameMode == EditGame || gameMode == EndOfGame) {
        whiteTimeRemaining = timeRemaining[0][currentMove];
        blackTimeRemaining = timeRemaining[1][currentMove];
@@@ -11785,13 -11730,13 +11810,13 @@@ ToEndEvent(
        /* to optimze, we temporarily turn off analysis mode while we feed
         * the remaining moves to the engine. Otherwise we get analysis output
         * after each move.
 -       */ 
 +       */
          if (first.analysisSupport) {
          SendToProgram("exit\nforce\n", &first);
          first.analyzing = FALSE;
        }
      }
 -      
 +
      if (gameMode == IcsExamining && !pausing) {
          SendToICS(ics_prefix);
        SendToICS("forward 999999\n");
@@@ -11826,7 -11771,7 +11851,7 @@@ BackwardInner(target
      }
      if (gameMode == PlayFromGameFile && !pausing)
        PauseEvent();
 -    
 +
      if (moveList[target][0]) {
        int fromX, fromY, toX, toY;
          toX = moveList[target][2] - AAA;
      } else {
        currentMove = target;
      }
 -    
 +
      if (gameMode == EditGame || gameMode == EndOfGame) {
        whiteTimeRemaining = timeRemaining[0][currentMove];
        blackTimeRemaining = timeRemaining[1][currentMove];
@@@ -11885,7 -11830,7 +11910,7 @@@ ToStartEvent(
      if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
        /* to optimze, we temporarily turn off analysis mode while we undo
         * all the moves. Otherwise we get analysis output after each undo.
 -       */ 
 +       */
          if (first.analysisSupport) {
          SendToProgram("exit\nforce\n", &first);
          first.analyzing = FALSE;
@@@ -12106,7 -12051,7 +12131,7 @@@ PrintPosition(fp, move
       int move;
  {
      int i, j;
 -    
 +
      for (i = BOARD_HEIGHT - 1; i >= 0; i--) {
          for (j = BOARD_LEFT; j < BOARD_RGHT; j++) {
            char c = PieceToChar(boards[move][i][j]);
@@@ -12442,18 -12387,18 +12467,18 @@@ SendToProgram(message, cps
  
      if (cps->pr == NULL) return;
      Attention(cps);
 -    
 +
      if (appData.debugMode) {
        TimeMark now;
        GetTimeMark(&now);
 -      fprintf(debugFP, "%ld >%-6s: %s", 
 +      fprintf(debugFP, "%ld >%-6s: %s",
                SubtractTimeMarks(&now, &programStartTime),
                cps->which, message);
      }
 -    
 +
      count = strlen(message);
      outCount = OutputToProcess(cps->pr, message, count, &error);
 -    if (outCount < count && !exiting 
 +    if (outCount < count && !exiting
                           && !endingGame) { /* [HGM] crash: to not hang GameEnds() writing to deceased engines */
        sprintf(buf, _("Error writing to %s chess program"), cps->which);
          if(gameInfo.resultDetails==NULL) { /* [HGM] crash: if game in progress, give reason for abort */
@@@ -12514,12 -12459,12 +12539,12 @@@ ReceiveFromProgram(isr, closure, messag
        }
        return;
      }
 -    
 +
      if ((end_str = strchr(message, '\r')) != NULL)
        *end_str = NULLCHAR;
      if ((end_str = strchr(message, '\n')) != NULL)
        *end_str = NULLCHAR;
 -    
 +
      if (appData.debugMode) {
        TimeMark now; int print = 1;
        char *quote = ""; char c; int i;
        if(appData.engineComments != 1) { /* [HGM] debug: decide if protocol-violating output is written */
                char start = message[0];
                if(start >='A' && start <= 'Z') start += 'a' - 'A'; // be tolerant to capitalizing
 -              if(sscanf(message, "%d%c%d%d%d", &i, &c, &i, &i, &i) != 5 && 
 +              if(sscanf(message, "%d%c%d%d%d", &i, &c, &i, &i, &i) != 5 &&
                   sscanf(message, "move %c", &c)!=1  && sscanf(message, "offer%c", &c)!=1 &&
                   sscanf(message, "resign%c", &c)!=1 && sscanf(message, "feature %c", &c)!=1 &&
                   sscanf(message, "error %c", &c)!=1 && sscanf(message, "illegal %c", &c)!=1 &&
        }
        if(print) {
                GetTimeMark(&now);
 -              fprintf(debugFP, "%ld <%-6s: %s%s\n", 
 -                      SubtractTimeMarks(&now, &programStartTime), cps->which, 
 +              fprintf(debugFP, "%ld <%-6s: %s%s\n",
 +                      SubtractTimeMarks(&now, &programStartTime), cps->which,
                        quote,
                        message);
        }
      /* [DM] if icsEngineAnalyze is active we block all whisper and kibitz output, because nobody want to see this */
      if (appData.icsEngineAnalyze) {
          if (strstr(message, "whisper") != NULL ||
 -             strstr(message, "kibitz") != NULL || 
 +             strstr(message, "kibitz") != NULL ||
              strstr(message, "tellics") != NULL) return;
      }
  
@@@ -12627,7 -12572,7 +12652,7 @@@ SendTimeControl(cps, mps, tc, inc, sd, 
  ChessProgramState *WhitePlayer()
  /* [HGM] return pointer to 'first' or 'second', depending on who plays white */
  {
 -    if(gameMode == TwoMachinesPlay && first.twoMachinesColor[0] == 'b' || 
 +    if(gameMode == TwoMachinesPlay && first.twoMachinesColor[0] == 'b' ||
         gameMode == BeginningOfGame || gameMode == MachinePlaysBlack)
          return &second;
      return &first;
@@@ -12660,7 -12605,7 +12685,7 @@@ SendTimeRemaining(cps, machineWhite
  
      if (time <= 0) time = 1;
      if (otime <= 0) otime = 1;
 -    
 +
      sprintf(message, "time %ld\n", time);
      SendToProgram(message, cps);
  
@@@ -12732,7 -12677,7 +12757,7 @@@ StringFeature(p, name, loc, cps
    return FALSE;
  }
  
 -int 
 +int
  ParseOption(Option *opt, ChessProgramState *cps)
  // [HGM] options: process the string that defines an engine option, and determine
  // name, type, default value, and allowed value range
@@@ -12827,7 -12772,7 +12852,7 @@@ FeatureDone(cps, val
  void
  ParseFeatures(args, cps)
       char* args;
 -     ChessProgramState *cps;  
 +     ChessProgramState *cps;
  {
    char *p = args;
    char *q;
      if (*p == NULLCHAR) return;
  
      if (BoolFeature(&p, "setboard", &cps->useSetboard, cps)) continue;
 -    if (BoolFeature(&p, "time", &cps->sendTime, cps)) continue;    
 -    if (BoolFeature(&p, "draw", &cps->sendDrawOffers, cps)) continue;    
 -    if (BoolFeature(&p, "sigint", &cps->useSigint, cps)) continue;    
 -    if (BoolFeature(&p, "sigterm", &cps->useSigterm, cps)) continue;    
 +    if (BoolFeature(&p, "time", &cps->sendTime, cps)) continue;
 +    if (BoolFeature(&p, "draw", &cps->sendDrawOffers, cps)) continue;
 +    if (BoolFeature(&p, "sigint", &cps->useSigint, cps)) continue;
 +    if (BoolFeature(&p, "sigterm", &cps->useSigterm, cps)) continue;
      if (BoolFeature(&p, "reuse", &val, cps)) {
        /* Engine can disable reuse, but can't enable it if user said no */
        if (!val) cps->reuse = FALSE;
@@@ -12981,7 -12926,7 +13006,7 @@@ ShowThinkingEvent(
      int newState = appData.showThinking
        // [HGM] thinking: other features now need thinking output as well
        || !appData.hideThinkingFromHuman || appData.adjudicateLossThreshold != 0 || EngineOutputIsUp();
 -    
 +
      if (oldState == newState) return;
      oldState = newState;
      if (gameMode == EditPosition) EditPositionDone();
@@@ -13018,8 -12963,8 +13043,8 @@@ DisplayMove(moveNumber
      char cpThinkOutput[MSG_SIZ];
  
      if(appData.noGUI) return; // [HGM] fast: suppress display of moves
 -    
 -    if (moveNumber == forwardMostMove - 1 || 
 +
 +    if (moveNumber == forwardMostMove - 1 ||
        gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
  
        safeStrCpy(cpThinkOutput, thinkOutput, sizeof(cpThinkOutput));
@@@ -13086,7 -13031,7 +13111,7 @@@ DisplayComment(moveNumber, text
          }
        // [HGM] PV info: display PV info together with (or as) comment
        if(moveNumber >= 0 && (depth = pvInfoList[moveNumber].depth) > 0) {
 -          if(text == NULL) text = "";                                           
 +          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);
@@@ -13234,7 -13179,7 +13259,7 @@@ GetTimeMark(tm
      struct timezone timeZone;
  
      gettimeofday(&timeVal, &timeZone);
 -    tm->sec = (long) timeVal.tv_sec; 
 +    tm->sec = (long) timeVal.tv_sec;
      tm->ms = (int) (timeVal.tv_usec / 1000L);
  
  #else /*!HAVE_GETTIMEOFDAY*/
@@@ -13273,7 -13218,7 +13298,7 @@@ SubtractTimeMarks(tm2, tm1
   * We give the human user a slight advantage if he is playing white---the
   * clocks don't run until he makes his first move, so it takes zero time.
   * Also, we don't account for network lag, so we could get out of sync
 - * with GNU Chess's clock -- but then, referees are always right.  
 + * with GNU Chess's clock -- but then, referees are always right.
   */
  
  static TimeMark tickStartTM;
@@@ -13306,7 -13251,7 +13331,7 @@@ AdjustClock(Boolean which, int dir
  
  /* Stop clocks and reset to a fresh time control */
  void
 -ResetClocks() 
 +ResetClocks()
  {
      (void) StopClockTimer();
      if (appData.icsActive) {
@@@ -13334,7 -13279,7 +13359,7 @@@ DecrementClocks(
  
      if (!appData.clockMode) return;
      if (gameMode==AnalyzeMode || gameMode == AnalyzeFile) return;
 -      
 +
      GetTimeMark(&now);
  
      lastTickLength = SubtractTimeMarks(&now, &tickStartTM);
      }
  
      if (CheckFlags()) return;
 -      
 +
      tickStartTM = now;
      intendedTickLength = NextTickLength(timeRemaining - fudge) + fudge;
      StartClockTimer(intendedTickLength);
      /* if the time remaining has fallen below the alarm threshold, sound the
       * alarm. if the alarm has sounded and (due to a takeback or time control
       * with increment) the time remaining has increased to a level above the
 -     * threshold, reset the alarm so it can sound again. 
 +     * threshold, reset the alarm so it can sound again.
       */
 -    
 +
      if (appData.icsActive && appData.icsAlarm) {
  
        /* make sure we are dealing with the user's clock */
  
        if (alarmSounded && (timeRemaining > appData.icsAlarmTime)) {
            alarmSounded = FALSE;
 -      } else if (!alarmSounded && (timeRemaining <= appData.icsAlarmTime)) { 
 +      } else if (!alarmSounded && (timeRemaining <= appData.icsAlarmTime)) {
            PlayAlarmSound();
            alarmSounded = TRUE;
        }
@@@ -13415,7 -13360,7 +13440,7 @@@ SwitchClocks(
           whiteTimeRemaining -= lastTickLength;
             /* [HGM] PGNtime: save time for PGN file if engine did not give it */
  //         if(pvInfoList[forwardMostMove-1].time == -1)
 -                 pvInfoList[forwardMostMove-1].time = 
 +                 pvInfoList[forwardMostMove-1].time =
                        (timeRemaining[0][forwardMostMove-1] - whiteTimeRemaining)/10;
        }
        flagged = CheckFlags();
        whiteTimeRemaining : blackTimeRemaining);
      StartClockTimer(intendedTickLength);
  }
 -      
 +
  
  /* Stop both clocks */
  void
  StopClocks()
 -{     
 +{
      long lastTickLength;
      TimeMark now;
  
      }
      CheckFlags();
  }
 -      
 +
  /* Start clock of player on move.  Time may have been reset, so
     if clock is already running, stop and restart it. */
  void
@@@ -13489,7 -13434,7 +13514,7 @@@ StartClocks(
        whiteTimeRemaining : blackTimeRemaining);
  
     /* [HGM] nps: figure out nps factors, by determining which engine plays white and/or black once and for all */
 -    whiteNPS = blackNPS = -1; 
 +    whiteNPS = blackNPS = -1;
      if(gameMode == MachinePlaysWhite || gameMode == TwoMachinesPlay && first.twoMachinesColor[0] == 'w'
         || appData.zippyPlay && gameMode == IcsPlayingBlack) // first (perhaps only) engine has white
        whiteNPS = first.nps;
@@@ -13512,7 -13457,7 +13537,7 @@@ TimeString(ms
      long second, minute, hour, day;
      char *sign = "";
      static char buf[32];
 -    
 +
      if (ms > 0 && ms <= 9900) {
        /* convert milliseconds to tenths, rounding up */
        double tenths = floor( ((double)(ms + 99L)) / 100.00 );
        sign = "-";
        second = -second;
      }
 -    
 +
      day = second / (60 * 60 * 24);
      second = second % (60 * 60 * 24);
      hour = second / (60 * 60);
      second = second % (60 * 60);
      minute = second / 60;
      second = second % 60;
 -    
 +
      if (day > 0)
        sprintf(buf, " %s%ld:%02ld:%02ld:%02ld ",
              sign, day, hour, minute, second);
        sprintf(buf, " %s%ld:%02ld:%02ld ", sign, hour, minute, second);
      else
        sprintf(buf, " %s%2ld:%02ld ", sign, minute, second);
 -    
 +
      return buf;
  }
  
@@@ -13558,13 -13503,13 +13583,13 @@@ StrStr(string, match
       char *string, *match;
  {
      int i, length;
 -    
 +
      length = strlen(match);
 -    
 +
      for (i = strlen(string) - length; i >= 0; i--, string++)
        if (!strncmp(match, string, length))
        return string;
 -    
 +
      return NULL;
  }
  
@@@ -13573,9 -13518,9 +13598,9 @@@ StrCaseStr(string, match
       char *string, *match;
  {
      int i, j, length;
 -    
 +
      length = strlen(match);
 -    
 +
      for (i = strlen(string) - length; i >= 0; i--, string++) {
        for (j = 0; j < length; j++) {
            if (ToLower(match[j]) != ToLower(string[j]))
@@@ -13593,7 -13538,7 +13618,7 @@@ StrCaseCmp(s1, s2
       char *s1, *s2;
  {
      char c1, c2;
 -    
 +
      for (;;) {
        c1 = ToLower(*s1++);
        c2 = ToLower(*s2++);
@@@ -13693,7 -13638,7 +13718,7 @@@ PositionToFEN(move, overrideCastling
                      /* [HGM] write promoted pieces as '+<unpromoted>' (Shogi) */
                      *p++ = '+';
                      piece = (ChessSquare)(DEMOTED piece);
 -                } 
 +                }
                  *p++ = PieceToChar(piece);
                  if(p[-1] == '~') {
                      /* [HGM] flag promoted pieces as '<promoted>~' (Crazyhouse) */
    }
  
    if(gameInfo.variant != VariantShogi    && gameInfo.variant != VariantXiangqi &&
 -     gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier ) { 
 +     gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier ) {
      /* En passant target square */
      if (move > backwardMostMove) {
          fromX = moveList[move - 1][0] - AAA;
      }
      /* Fullmove number */
      sprintf(p, "%d", (move / 2) + 1);
 -    
 +
      return StrSave(buf);
  }
  
@@@ -13933,7 -13878,7 +13958,7 @@@ ParseFEN(board, blackPlaysFirst, fen
        case 'w':
          *blackPlaysFirst = FALSE;
        break;
 -      case 'b': 
 +      case 'b':
        *blackPlaysFirst = TRUE;
        break;
        default:
  
      /* 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 ) {
        if(*p=='-') {
          p++; FENepStatus = EP_NONE;
        } else {
  
      return TRUE;
  }
 -      
 +
  void
  EditPositionPasteFEN(char *fen)
  {
diff --combined xengineoutput.c
@@@ -144,7 -144,7 +144,7 @@@ extern int opponentKibitzes
  
  /* Imports from winboard.c */
  //extern HWND engineOutputDialog;
 -extern Arg layoutArgs[2], formArgs[2], messageArgs[4];
 +extern Arg layoutArgs[2], formArgs[2];
  
  //extern WindowPlacement wpEngineOutput;
  
@@@ -851,7 -851,8 +851,8 @@@ static void UpdateControls( EngineOutpu
              strncpy( mov, ed->hint, sizeof(mov) );
              mov[ sizeof(mov)-1 ] = '\0';
  
-             sprintf( buf, "%d/%d: %s [%02d:%02d:%02d]", ed->an_move_index, ed->an_move_count, mov, time_mins / 60, time_mins % 60, time_secs % 60 );
+           sprintf( buf, "[%d] %d/%d: %s [%02d:%02d:%02d]", ed->depth, ed->an_move_index,
+                       ed->an_move_count, mov, time_mins / 60, time_mins % 60, time_secs % 60 );
          }
  
          SetEngineState( ed->which, STATE_ANALYZING, buf );