Give the dual-board option a separate board window
[xboard.git] / backend.c
index d765e81..5715e5d 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -5,7 +5,7 @@
  * Massachusetts.
  *
  * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
  *
  * Enhancements Copyright 2005 Alessandro Scotti
  *
@@ -222,6 +222,7 @@ int NextTourneyGame P((int nr, int *swap));
 int Pairing P((int nr, int nPlayers, int *w, int *b, int *sync));
 FILE *WriteTourneyFile P((char *results, FILE *f));
 void DisplayTwoMachinesTitle P(());
+static void ExcludeClick P((int index));
 
 #ifdef WIN32
        extern void ConsoleCreate();
@@ -312,7 +313,7 @@ int promoDefaultAltered;
 #define TN_PORT 23
 
 char*
-safeStrCpy( char *dst, const char *src, size_t count )
+safeStrCpy (char *dst, const char *src, size_t count)
 { // [HGM] made safe
   int i;
   assert( dst != NULL );
@@ -340,7 +341,7 @@ safeStrCpy( char *dst, const char *src, size_t count )
  * We used this for all compiler
  */
 double
-u64ToDouble(u64 value)
+u64ToDouble (u64 value)
 {
   double r;
   u64 tmp = value & u64Const(0x7fffffffffffffff);
@@ -358,7 +359,7 @@ u64ToDouble(u64 value)
    by this function.
  */
 int
-PosFlags(index)
+PosFlags (index)
 {
   int flags = F_ALL_CASTLE_OK;
   if ((index % 2) == 0) flags |= F_WHITE_ON_MOVE;
@@ -392,7 +393,8 @@ PosFlags(index)
   return flags;
 }
 
-FILE *gameFileFP, *debugFP;
+FILE *gameFileFP, *debugFP, *serverFP;
+char *currentDebugFile; // [HGM] debug split: to remember name
 
 /*
     [AS] Note: sometimes, the sscanf() function is used to parse the input
@@ -643,8 +645,7 @@ Board initialPosition;
 
    "++++", etc. Also strips ()'s */
 int
-string_to_rating(str)
-  char *str;
+string_to_rating (char *str)
 {
   while(*str && !isdigit(*str)) ++str;
   if (!*str)
@@ -654,7 +655,7 @@ string_to_rating(str)
 }
 
 void
-ClearProgramStats()
+ClearProgramStats ()
 {
     /* Init programStats */
     programStats.movelist[0] = 0;
@@ -670,7 +671,7 @@ ClearProgramStats()
 }
 
 void
-CommonEngineInit()
+CommonEngineInit ()
 {   // [HGM] moved some code here from InitBackend1 that has to be done after both engines have contributed their settings
     if (appData.firstPlaysBlack) {
        first.twoMachinesColor = "black\n";
@@ -704,7 +705,7 @@ CommonEngineInit()
 }
 
 void
-UnloadEngine(ChessProgramState *cps)
+UnloadEngine (ChessProgramState *cps)
 {
        /* Kill off first chess program */
        if (cps->isr != NULL)
@@ -723,7 +724,7 @@ UnloadEngine(ChessProgramState *cps)
 }
 
 void
-ClearOptions(ChessProgramState *cps)
+ClearOptions (ChessProgramState *cps)
 {
     int i;
     cps->nrOptions = cps->comboCnt = 0;
@@ -734,12 +735,16 @@ ClearOptions(ChessProgramState *cps)
 }
 
 char *engineNames[] = {
-"first",
-"second"
+  /* TRANSLATORS: "first" is the first of possible two chess engines. It is inserted into strings
+     such as "%s engine" / "%s chess program" / "%s machine" - all meaning the same thing */
+N_("first"),
+  /* TRANSLATORS: "second" is the second of possible two chess engines. It is inserted into strings
+     such as "%s engine" / "%s chess program" / "%s machine" - all meaning the same thing */
+N_("second")
 };
 
 void
-InitEngine(ChessProgramState *cps, int n)
+InitEngine (ChessProgramState *cps, int n)
 {   // [HGM] all engine initialiation put in a function that does one engine
 
     ClearOptions(cps);
@@ -832,7 +837,7 @@ InitEngine(ChessProgramState *cps, int n)
 ChessProgramState *savCps;
 
 void
-LoadEngine()
+LoadEngine ()
 {
     int i;
     if(WaitForEngine(savCps, LoadEngine)) return;
@@ -852,7 +857,7 @@ LoadEngine()
 }
 
 void
-ReplaceEngine(ChessProgramState *cps, int n)
+ReplaceEngine (ChessProgramState *cps, int n)
 {
     EditGameEvent();
     UnloadEngine(cps);
@@ -871,37 +876,63 @@ extern Boolean isUCI, hasBook, storeVariant, v1, addToList, useNick;
 static char resetOptions[] = 
        "-reuse -firstIsUCI false -firstHasOwnBookUCI true -firstTimeOdds 1 "
        "-firstInitString \"" INIT_STRING "\" -firstComputerString \"" COMPUTER_STRING "\" "
-       "-firstOptions \"\" -firstNPS -1 -fn \"\"";
+       "-firstFeatures \"\" -firstLogo \"\" -firstAccumulateTC 1 "
+       "-firstOptions \"\" -firstNPS -1 -fn \"\" -firstScoreAbs false";
 
 void
-Load(ChessProgramState *cps, int i)
+FloatToFront(char **list, char *engineLine)
+{
+    char buf[MSG_SIZ], tidy[MSG_SIZ], *p = buf, *q, *r = buf;
+    int i=0;
+    if(appData.recentEngines <= 0) return;
+    TidyProgramName(engineLine, "localhost", tidy+1);
+    tidy[0] = buf[0] = '\n'; strcat(tidy, "\n");
+    strncpy(buf+1, *list, MSG_SIZ-50);
+    if(p = strstr(buf, tidy)) { // tidy name appears in list
+       q = strchr(++p, '\n'); if(q == NULL) return; // malformed, don't touch
+       while(*p++ = *++q); // squeeze out
+    }
+    strcat(tidy, buf+1); // put list behind tidy name
+    p = tidy + 1; while(q = strchr(p, '\n')) i++, r = p, p = q + 1; // count entries in new list
+    if(i > appData.recentEngines) *r = NULLCHAR; // if maximum rached, strip off last
+    ASSIGN(*list, tidy+1);
+}
+
+char *insert, *wbOptions; // point in ChessProgramNames were we should insert new engine
+
+void
+Load (ChessProgramState *cps, int i)
 {
     char *p, *q, buf[MSG_SIZ], command[MSG_SIZ], buf2[MSG_SIZ];
     if(engineLine && engineLine[0]) { // an engine was selected from the combo box
        snprintf(buf, MSG_SIZ, "-fcp %s", engineLine);
        SwapEngines(i); // kludge to parse -f* / -first* like it is -s* / -second*
-       ParseArgsFromString(resetOptions); appData.fenOverride[0] = NULL; appData.pvSAN[0] = FALSE;
+       ParseArgsFromString(resetOptions); appData.pvSAN[0] = FALSE;
+       FREE(appData.fenOverride[0]); appData.fenOverride[0] = NULL;
+       appData.firstProtocolVersion = PROTOVER;
        ParseArgsFromString(buf);
        SwapEngines(i);
        ReplaceEngine(cps, i);
+       FloatToFront(&appData.recentEngineList, engineLine);
        return;
     }
     p = engineName;
     while(q = strchr(p, SLASH)) p = q+1;
     if(*p== NULLCHAR) { DisplayError(_("You did not specify the engine executable"), 0); return; }
-    if(engineDir[0] != NULLCHAR)
-       appData.directory[i] = engineDir;
-    else if(p != engineName) { // derive directory from engine path, when not given
+    if(engineDir[0] != NULLCHAR) {
+       ASSIGN(appData.directory[i], engineDir);
+    } else if(p != engineName) { // derive directory from engine path, when not given
        p[-1] = 0;
-       appData.directory[i] = strdup(engineName);
+       ASSIGN(appData.directory[i], engineName);
        p[-1] = SLASH;
-    } else appData.directory[i] = ".";
+       if(SLASH == '/' && p - engineName > 1) *(p -= 2) = '.'; // for XBoard use ./exeName as command after split!
+    } else { ASSIGN(appData.directory[i], "."); }
     if(params[0]) {
        if(strchr(p, ' ') && !strchr(p, '"')) snprintf(buf2, MSG_SIZ, "\"%s\"", p), p = buf2; // quote if it contains spaces
        snprintf(command, MSG_SIZ, "%s %s", p, params);
        p = command;
     }
-    appData.chessProgram[i] = strdup(p);
+    ASSIGN(appData.chessProgram[i], p);
     appData.isUCI[i] = isUCI;
     appData.protocolVersion[i] = v1 ? 1 : PROTOVER;
     appData.hasOwnBookUCI[i] = hasBook;
@@ -923,15 +954,18 @@ Load(ChessProgramState *cps, int i)
                        isUCI ? (isUCI == TRUE ? " -fUCI" : gameInfo.variant == VariantShogi ? " -fUSI" : " -fUCCI") : "",
                        storeVariant ? " -variant " : "",
                        storeVariant ? VariantName(gameInfo.variant) : "");
+       if(wbOptions && wbOptions[0]) snprintf(buf+strlen(buf)-1, MSG_SIZ-strlen(buf), " %s\n", wbOptions);
        firstChessProgramNames = malloc(len = strlen(q) + strlen(buf) + 1);
-       snprintf(firstChessProgramNames, len, "%s%s", q, buf);
+       if(insert != q) insert[-1] = NULLCHAR;
+       snprintf(firstChessProgramNames, len, "%s\n%s%s", q, buf, insert);
        if(q)   free(q);
+       FloatToFront(&appData.recentEngineList, buf);
     }
     ReplaceEngine(cps, i);
 }
 
 void
-InitTimeControls()
+InitTimeControls ()
 {
     int matched, min, sec;
     /*
@@ -962,7 +996,7 @@ InitTimeControls()
 }
 
 void
-InitBackEnd1()
+InitBackEnd1 ()
 {
 
     ShowThinkingEvent(); // [HGM] thinking: make sure post/nopost state is set according to options
@@ -1126,7 +1160,8 @@ InitBackEnd1()
 
 }
 
-int NextIntegerFromString( char ** str, long * value )
+int
+NextIntegerFromString (char ** str, long * value)
 {
     int result = -1;
     char * s = *str;
@@ -1151,7 +1186,8 @@ int NextIntegerFromString( char ** str, long * value )
     return result;
 }
 
-int NextTimeControlFromString( char ** str, long * value )
+int
+NextTimeControlFromString (char ** str, long * value)
 {
     long temp;
     int result = NextIntegerFromString( str, &temp );
@@ -1168,7 +1204,8 @@ int NextTimeControlFromString( char ** str, long * value )
     return result;
 }
 
-int NextSessionFromString( char ** str, int *moves, long * tc, long *inc, int *incType)
+int
+NextSessionFromString (char ** str, int *moves, long * tc, long *inc, int *incType)
 {   /* [HGM] routine added to read '+moves/time' for secondary time control. */
     int result = -1, type = 0; long temp, temp2;
 
@@ -1209,18 +1246,17 @@ int NextSessionFromString( char ** str, int *moves, long * tc, long *inc, int *i
     return result;
 }
 
-int GetTimeQuota(int movenr, int lastUsed, char *tcString)
+int
+GetTimeQuota (int movenr, int lastUsed, char *tcString)
 {   /* [HGM] get time to add from the multi-session time-control string */
     int incType, moves=1; /* kludge to force reading of first session */
     long time, increment;
     char *s = tcString;
 
     if(!*s) return 0; // empty TC string means we ran out of the last sudden-death version
-    if(appData.debugMode) fprintf(debugFP, "TC string = '%s'\n", tcString);
     do {
         if(moves) NextSessionFromString(&s, &moves, &time, &increment, &incType);
         nextSession = s; suddenDeath = moves == 0 && increment == 0;
-        if(appData.debugMode) fprintf(debugFP, "mps=%d tc=%d inc=%d\n", moves, (int) time, (int) increment);
         if(movenr == -1) return time;    /* last move before new session     */
         if(incType == '*') increment = 0; else // for sandclock, time is added while not thinking
         if(incType == '!' && lastUsed < increment) increment = lastUsed;
@@ -1232,10 +1268,7 @@ int GetTimeQuota(int movenr, int lastUsed, char *tcString)
 }
 
 int
-ParseTimeControl(tc, ti, mps)
-     char *tc;
-     float ti;
-     int mps;
+ParseTimeControl (char *tc, float ti, int mps)
 {
   long tc1;
   long tc2;
@@ -1298,11 +1331,12 @@ ParseTimeControl(tc, ti, mps)
 }
 
 void
-InitBackEnd2()
+InitBackEnd2 ()
 {
     if (appData.debugMode) {
        fprintf(debugFP, "%s\n", programVersion);
     }
+    ASSIGN(currentDebugFile, appData.nameOfDebugFile); // [HGM] debug split: remember initial name in use
 
     set_cont_sequence(appData.wrapContSeq);
     if (appData.matchGames > 0) {
@@ -1328,7 +1362,7 @@ InitBackEnd2()
 }
 
 int
-CalculateIndex(int index, int gameNr)
+CalculateIndex (int index, int gameNr)
 {   // [HGM] autoinc: absolute way to determine load index from game number (taking auto-inc and rewind into account)
     int res;
     if(index > 0) return index; // fixed nmber
@@ -1339,7 +1373,7 @@ CalculateIndex(int index, int gameNr)
 }
 
 int
-LoadGameOrPosition(int gameNr)
+LoadGameOrPosition (int gameNr)
 {   // [HGM] taken out of MatchEvent and NextMatchGame (to combine it)
     if (*appData.loadGameFile != NULLCHAR) {
        if (!LoadGameFromFile(appData.loadGameFile,
@@ -1360,7 +1394,7 @@ LoadGameOrPosition(int gameNr)
 }
 
 void
-ReserveGame(int gameNr, char resChar)
+ReserveGame (int gameNr, char resChar)
 {
     FILE *tf = fopen(appData.tourneyFile, "r+");
     char *p, *q, c, buf[MSG_SIZ];
@@ -1396,13 +1430,17 @@ ReserveGame(int gameNr, char resChar)
     free(p); appData.results = q;
     if(nextGame <= appData.matchGames && resChar != ' ' && !abortMatch &&
        (gameNr < 0 || nextGame / appData.defaultMatchGames != gameNr / appData.defaultMatchGames)) {
+      int round = appData.defaultMatchGames * appData.tourneyType;
+      if(gameNr < 0 || appData.tourneyType < 1 ||  // gauntlet engine can always stay loaded as first engine
+        appData.tourneyType > 1 && nextGame/round != gameNr/round) // in multi-gauntlet change only after round
        UnloadEngine(&first);  // next game belongs to other pairing;
        UnloadEngine(&second); // already unload the engines, so TwoMachinesEvent will load new ones.
     }
+    if(appData.debugMode) fprintf(debugFP, "Reserved, next=%d, nr=%d\n", nextGame, gameNr);
 }
 
 void
-MatchEvent(int mode)
+MatchEvent (int mode)
 {      // [HGM] moved out of InitBackend3, to make it callable when match starts through menu
        int dummy;
        if(matchMode) { // already in match mode: switch it off
@@ -1455,6 +1493,8 @@ MatchEvent(int mode)
        NextMatchGame();
 }
 
+char *comboLine = NULL; // [HGM] recent: WinBoard's first-engine combobox line
+
 void
 InitBackEnd3 P((void))
 {
@@ -1468,6 +1508,7 @@ InitBackEnd3 P((void))
        free(programVersion);
        programVersion = (char*) malloc(8 + strlen(PACKAGE_STRING) + strlen(first.tidy));
        sprintf(programVersion, "%s + %s", PACKAGE_STRING, first.tidy);
+       FloatToFront(&appData.recentEngineList, comboLine ? comboLine : appData.firstChessProgram);
     }
 
     if (appData.icsActive) {
@@ -1655,7 +1696,7 @@ InitBackEnd3 P((void))
 }
 
 void
-HistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current )
+HistorySet (char movelist[][2*MOVE_LEN], int first, int last, int current)
 {
     DisplayBook(current+1);
 
@@ -1673,7 +1714,7 @@ HistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current )
  * Returns 0 if okay, error code if not.
  */
 int
-establish()
+establish ()
 {
     char buf[MSG_SIZ];
 
@@ -1714,7 +1755,8 @@ establish()
     }
 }
 
-void EscapeExpand(char *p, char *q)
+void
+EscapeExpand (char *p, char *q)
 {      // [HGM] initstring: routine to shape up string arguments
        while(*p++ = *q++) if(p[-1] == '\\')
            switch(*q++) {
@@ -1728,10 +1770,7 @@ void EscapeExpand(char *p, char *q)
 }
 
 void
-show_bytes(fp, buf, count)
-     FILE *fp;
-     char *buf;
-     int count;
+show_bytes (FILE *fp, char *buf, int count)
 {
     while (count--) {
        if (*buf < 040 || *(unsigned char *) buf > 0177) {
@@ -1746,11 +1785,7 @@ show_bytes(fp, buf, count)
 
 /* Returns an errno value */
 int
-OutputMaybeTelnet(pr, message, count, outError)
-     ProcRef pr;
-     char *message;
-     int count;
-     int *outError;
+OutputMaybeTelnet (ProcRef pr, char *message, int count, int *outError)
 {
     char buf[8192], *p, *q, *buflim;
     int left, newcount, outcount;
@@ -1804,12 +1839,7 @@ OutputMaybeTelnet(pr, message, count, outError)
 }
 
 void
-read_from_player(isr, closure, message, count, error)
-     InputSourceRef isr;
-     VOIDSTAR closure;
-     char *message;
-     int count;
-     int error;
+read_from_player (InputSourceRef isr, VOIDSTAR closure, char *message, int count, int error)
 {
     int outError, outCount;
     static int gotEof = 0;
@@ -1831,7 +1861,7 @@ read_from_player(isr, closure, message, count, error)
 }
 
 void
-KeepAlive()
+KeepAlive ()
 {   // [HGM] alive: periodically send dummy (date) command to ICS to prevent time-out
     if(!connectionAlive) DisplayFatalError("No response from ICS", 0, 1);
     connectionAlive = FALSE; // only sticks if no response to 'date' command.
@@ -1840,7 +1870,8 @@ KeepAlive()
 }
 
 /* added routine for printf style output to ics */
-void ics_printf(char *format, ...)
+void
+ics_printf (char *format, ...)
 {
     char buffer[MSG_SIZ];
     va_list args;
@@ -1853,8 +1884,7 @@ void ics_printf(char *format, ...)
 }
 
 void
-SendToICS(s)
-     char *s;
+SendToICS (char *s)
 {
     int count, outCount, outError;
 
@@ -1871,9 +1901,7 @@ SendToICS(s)
    without a delay causes problems when using timestamp on ICC
    (at least on my machine). */
 void
-SendToICSDelayed(s,msdelay)
-     char *s;
-     long msdelay;
+SendToICSDelayed (char *s, long msdelay)
 {
     int count, outCount, outError;
 
@@ -1897,8 +1925,7 @@ SendToICSDelayed(s,msdelay)
    Also deletes any suffix starting with '('
    */
 char *
-StripHighlightAndTitle(s)
-     char *s;
+StripHighlightAndTitle (char *s)
 {
     static char retbuf[MSG_SIZ];
     char *p = retbuf;
@@ -1922,8 +1949,7 @@ StripHighlightAndTitle(s)
 
 /* Remove all highlighting escape sequences in s */
 char *
-StripHighlight(s)
-     char *s;
+StripHighlight (char *s)
 {
     static char retbuf[MSG_SIZ];
     char *p = retbuf;
@@ -1943,8 +1969,7 @@ StripHighlight(s)
 
 char *variantNames[] = VARIANT_NAMES;
 char *
-VariantName(v)
-     VariantClass v;
+VariantName (VariantClass v)
 {
     return variantNames[v];
 }
@@ -1953,8 +1978,7 @@ VariantName(v)
 /* Identify a variant from the strings the chess servers use or the
    PGN Variant tag names we use. */
 VariantClass
-StringToVariant(e)
-     char *e;
+StringToVariant (char *e)
 {
     char *p;
     int wnum = -1;
@@ -2165,10 +2189,7 @@ char star_match[STAR_MATCH_N][MSG_SIZ];
    copied into star_match.
    */
 int
-looking_at(buf, index, pattern)
-     char *buf;
-     int *index;
-     char *pattern;
+looking_at ( char *buf, int *index, char *pattern)
 {
     char *bufp = &buf[*index], *patternp = pattern;
     int star_count = 0;
@@ -2206,9 +2227,7 @@ looking_at(buf, index, pattern)
 }
 
 void
-SendToPlayer(data, length)
-     char *data;
-     int length;
+SendToPlayer (char *data, int length)
 {
     int error, outCount;
     outCount = OutputToProcess(NoProc, data, length, &error);
@@ -2218,9 +2237,7 @@ SendToPlayer(data, length)
 }
 
 void
-PackHolding(packed, holding)
-     char packed[];
-     char *holding;
+PackHolding (char packed[], char *holding)
 {
     char *p = holding;
     char *q = packed;
@@ -2255,8 +2272,7 @@ PackHolding(packed, holding)
 
 /* Telnet protocol requests from the front end */
 void
-TelnetRequest(ddww, option)
-     unsigned char ddww, option;
+TelnetRequest (unsigned char ddww, unsigned char option)
 {
     unsigned char msg[3];
     int outCount, outError;
@@ -2304,21 +2320,21 @@ TelnetRequest(ddww, option)
 }
 
 void
-DoEcho()
+DoEcho ()
 {
     if (!appData.icsActive) return;
     TelnetRequest(TN_DO, TN_ECHO);
 }
 
 void
-DontEcho()
+DontEcho ()
 {
     if (!appData.icsActive) return;
     TelnetRequest(TN_DONT, TN_ECHO);
 }
 
 void
-CopyHoldings(Board board, char *holdings, ChessSquare lowestPiece)
+CopyHoldings (Board board, char *holdings, ChessSquare lowestPiece)
 {
     /* put the holdings sent to us by the server on the board holdings area */
     int i, j, holdingsColumn, holdingsStartRow, direction, countsColumn;
@@ -2360,7 +2376,7 @@ CopyHoldings(Board board, char *holdings, ChessSquare lowestPiece)
 
 
 void
-VariantSwitch(Board board, VariantClass newVariant)
+VariantSwitch (Board board, VariantClass newVariant)
 {
    int newHoldingsWidth, newWidth = 8, newHeight = 8, i, j;
    static Board oldBoard;
@@ -2471,7 +2487,7 @@ int hMargin = 10, vMargin = 20, h, w;
 extern int squareSize, lineGap;
 
 void
-PlotSeekAd(int i)
+PlotSeekAd (int i)
 {
        int x, y, color = 0, r = ratingList[i]; float tc = tcList[i];
        xList[i] = yList[i] = -100; // outside graph, so cannot be clicked
@@ -2493,7 +2509,7 @@ PlotSeekAd(int i)
 }
 
 void
-AddAd(char *handle, char *rating, int base, int inc,  char rated, char *type, int nr, Boolean plot)
+AddAd (char *handle, char *rating, int base, int inc,  char rated, char *type, int nr, Boolean plot)
 {
        char buf[MSG_SIZ], *ext = "";
        VariantClass v = StringToVariant(type);
@@ -2517,7 +2533,7 @@ AddAd(char *handle, char *rating, int base, int inc,  char rated, char *type, in
 }
 
 void
-EraseSeekDot(int i)
+EraseSeekDot (int i)
 {
     int x = xList[i], y = yList[i], d=squareSize/4, k;
     DrawSeekBackground(x-squareSize/8, y-squareSize/8, x+squareSize/8+1, y+squareSize/8+1);
@@ -2531,7 +2547,7 @@ EraseSeekDot(int i)
 }
 
 void
-RemoveSeekAd(int nr)
+RemoveSeekAd (int nr)
 {
        int i;
        for(i=0; i<nrOfSeekAds; i++) if(seekNrList[i] == nr) {
@@ -2551,7 +2567,7 @@ RemoveSeekAd(int nr)
 }
 
 Boolean
-MatchSoughtLine(char *line)
+MatchSoughtLine (char *line)
 {
     char handle[MSG_SIZ], rating[MSG_SIZ], type[MSG_SIZ];
     int nr, base, inc, u=0; char dummy;
@@ -2569,7 +2585,7 @@ MatchSoughtLine(char *line)
 }
 
 int
-DrawSeekGraph()
+DrawSeekGraph ()
 {
     int i;
     if(!seekGraphUp) return FALSE;
@@ -2603,9 +2619,18 @@ DrawSeekGraph()
     return TRUE;
 }
 
-int SeekGraphClick(ClickType click, int x, int y, int moving)
+int
+SeekGraphClick (ClickType click, int x, int y, int moving)
 {
     static int lastDown = 0, displayed = 0, lastSecond;
+    if(y < 0) return FALSE;
+    if(!(appData.seekGraph && appData.icsActive && loggedOn &&
+       (gameMode == BeginningOfGame || gameMode == IcsIdle))) {
+       if(!seekGraphUp) return FALSE;
+       seekGraphUp = FALSE; // seek graph is up when it shouldn't be: take it down
+       DrawPosition(TRUE, NULL);
+       return TRUE;
+    }
     if(!seekGraphUp) { // initiate cration of seek graph by requesting seek-ad list
        if(click == Release || moving) return FALSE;
        nrOfSeekAds = 0;
@@ -2655,12 +2680,7 @@ int SeekGraphClick(ClickType click, int x, int y, int moving)
 }
 
 void
-read_from_ics(isr, closure, data, count, error)
-     InputSourceRef isr;
-     VOIDSTAR closure;
-     char *data;
-     int count;
-     int error;
+read_from_ics (InputSourceRef isr, VOIDSTAR closure, char *data, int count, int error)
 {
 #define BUF_SIZE (16*1024) /* overflowed at 8K with "inchannel 1" on FICS? */
 #define STARTED_NONE 0
@@ -2958,6 +2978,9 @@ read_from_ics(isr, closure, data, count, error)
                            OutputKibitz(suppressKibitz, parse);
                        } else {
                            char tmp[MSG_SIZ];
+                           if(gameMode == IcsObserving) // restore original ICS messages
+                             snprintf(tmp, MSG_SIZ, "%s kibitzes: %s", star_match[0], parse);
+                           else
                            snprintf(tmp, MSG_SIZ, _("your opponent kibitzes: %s"), parse);
                            SendToPlayer(tmp, strlen(tmp));
                        }
@@ -3091,7 +3114,8 @@ read_from_ics(isr, closure, data, count, error)
            if (appData.autoKibitz && started == STARTED_NONE &&
                 !appData.icsEngineAnalyze &&                     // [HGM] [DM] ICS analyze
                (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack || gameMode == IcsObserving)) {
-               if((looking_at(buf, &i, "* kibitzes: ") || looking_at(buf, &i, "* whispers: ")) &&
+               if((looking_at(buf, &i, "\n* kibitzes: ") || looking_at(buf, &i, "\n* whispers: ") ||
+                   looking_at(buf, &i, "* kibitzes: ") || looking_at(buf, &i, "* whispers: ")) &&
                   (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;
@@ -3126,6 +3150,8 @@ read_from_ics(isr, closure, data, count, error)
                }
            } // [HGM] kibitz: end of patch
 
+           if(looking_at(buf, &i, "* rating adjustment: * --> *\n")) continue;
+
            // [HGM] chat: intercept tells by users for which we have an open chat window
            channel = -1;
            if(started == STARTED_NONE && (looking_at(buf, &i, "* tells you:") || looking_at(buf, &i, "* says:") ||
@@ -3551,7 +3577,7 @@ read_from_ics(isr, closure, data, count, error)
            if (looking_at(buf, &i, "% ") ||
                ((started == STARTED_MOVES || started == STARTED_MOVES_NOHIDE)
                 && looking_at(buf, &i, "}*"))) { char *bookHit = NULL; // [HGM] book
-               if(ics_type == ICS_ICC && soughtPending) { // [HGM] seekgraph: on ICC sought-list has no termination line
+               if(soughtPending && nrOfSeekAds) { // [HGM] seekgraph: on ICC sought-list has no termination line
                    soughtPending = FALSE;
                    seekGraphUp = TRUE;
                    DrawSeekGraph();
@@ -3628,8 +3654,8 @@ read_from_ics(isr, closure, data, count, error)
                        flipView = appData.flipView;
                        DrawPosition(TRUE, boards[currentMove]);
                        DisplayBothClocks();
-                       snprintf(str, MSG_SIZ, _("%s vs. %s"),
-                               gameInfo.white, gameInfo.black);
+                       snprintf(str, MSG_SIZ, "%s %s %s",
+                               gameInfo.white, _("vs."),  gameInfo.black);
                        DisplayTitle(str);
                        gameMode = IcsIdle;
                    } else {
@@ -4046,8 +4072,8 @@ read_from_ics(isr, closure, data, count, error)
                            snprintf(str, MSG_SIZ, "[%s-%s] %s-%s", wh, bh,
                                    gameInfo.white, gameInfo.black);
                        } else {
-                         snprintf(str, MSG_SIZ, _("%s [%s] vs. %s [%s]"),
-                                   gameInfo.white, white_holding,
+                         snprintf(str, MSG_SIZ, "%s [%s] %s %s [%s]",
+                                   gameInfo.white, white_holding, _("vs."),
                                    gameInfo.black, black_holding);
                        }
                        if(!partnerUp) // [HGM] bughouse: when peeking at partner game we already know what he captured...
@@ -4123,8 +4149,7 @@ read_from_ics(isr, closure, data, count, error)
 #define RELATION_STARTING_POSITION  -4   /* FICS only */
 
 void
-ParseBoard12(string)
-     char *string;
+ParseBoard12 (char *string)
 {
     GameMode newGameMode;
     int gamenum, newGame, newMove, relation, basetime, increment, ics_flip = 0, i;
@@ -4200,6 +4225,7 @@ ParseBoard12(string)
        newGameMode =
          ((relation == RELATION_PLAYING_MYMOVE) == (to_play == 'W')) ?
            IcsPlayingWhite : IcsPlayingBlack;
+       soughtPending =FALSE; // [HGM] seekgraph: solve race condition
        break;
       case RELATION_EXAMINING:
        newGameMode = IcsExamining;
@@ -4239,7 +4265,10 @@ ParseBoard12(string)
       if(appData.dualBoard && !twoBoards) { twoBoards = 1; InitDrawingSizes(-2,0); }
       if(twoBoards) { partnerUp = 1; flipView = !flipView; } // [HGM] dual
       if(partnerUp) DrawPosition(FALSE, partnerBoard);
-      if(twoBoards) { partnerUp = 0; flipView = !flipView; } // [HGM] dual
+      if(twoBoards) {
+         DisplayWhiteClock(white_time, to_play == 'W');
+         DisplayBlackClock(black_time, to_play != 'W');
+                     partnerUp = 0; flipView = !flipView; } // [HGM] dual
       snprintf(partnerStatus, MSG_SIZ,"W: %d:%02d B: %d:%02d (%d-%d) %c", white_time/60000, (white_time%60000)/1000,
                 (black_time/60000), (black_time%60000)/1000, white_stren, black_stren, to_play);
       DisplayMessage(partnerStatus, "");
@@ -4431,6 +4460,13 @@ ParseBoard12(string)
            board[k][1] = board[k][BOARD_WIDTH-2] = (ChessSquare) 0;;
       }
     }
+    if(moveNum==0 && gameInfo.variant == VariantSChess) {
+      board[5][BOARD_RGHT+1] = WhiteAngel;
+      board[6][BOARD_RGHT+1] = WhiteMarshall;
+      board[1][0] = BlackMarshall;
+      board[2][0] = BlackAngel;
+      board[1][1] = board[2][1] = board[5][BOARD_RGHT] = board[6][BOARD_RGHT] = 1;
+    }
     CopyBoard(boards[moveNum], board);
     boards[moveNum][HOLDINGS_SET] = 0; // [HGM] indicate holdings not set
     if (moveNum == 0) {
@@ -4466,6 +4502,7 @@ ParseBoard12(string)
             if(board[BOARD_HEIGHT-1][i] == BlackRook) j = i;
         initialRights[4] = boards[moveNum][CASTLING][4] = (castle_bl == 0 && gameInfo.variant != VariantFischeRandom ? NoRights : j);
 
+       boards[moveNum][CASTLING][2] = boards[moveNum][CASTLING][5] = NoRights;
        if(gameInfo.variant == VariantKnightmate) { wKing = WhiteUnicorn; bKing = BlackUnicorn; }
         for(k=BOARD_LEFT; k<BOARD_RGHT; k++)
             if(board[0][k] == wKing) initialRights[2] = boards[moveNum][CASTLING][2] = k;
@@ -4491,7 +4528,10 @@ ParseBoard12(string)
         r = boards[moveNum][CASTLING][5] = initialRights[5];
     }
     /* [HGM] e.p. rights. Assume that ICS sends file number here? */
-    boards[moveNum][EP_STATUS] = double_push == -1 ? EP_NONE : double_push + BOARD_LEFT;
+    boards[moveNum][EP_STATUS] = EP_NONE;
+    if(str[0] == 'P') boards[moveNum][EP_STATUS] = EP_PAWN_MOVE;
+    if(strchr(move_str, 'x')) boards[moveNum][EP_STATUS] = EP_CAPTURE;
+    if(double_push !=  -1) boards[moveNum][EP_STATUS] = double_push + BOARD_LEFT;
 
 
     if (ics_getting_history == H_GOT_REQ_HEADER ||
@@ -4655,7 +4695,7 @@ ParseBoard12(string)
            strcat(moveList[moveNum - 1], "\n");
 
             if(gameInfo.holdingsWidth && !appData.disguise && gameInfo.variant != VariantSuper && gameInfo.variant != VariantGreat
-                                 && gameInfo.variant != VariantGrand) // inherit info that ICS does not give from previous board
+               && gameInfo.variant != VariantGrand&& gameInfo.variant != VariantSChess) // inherit info that ICS does not give from previous board
               for(k=0; k<ranks; k++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++) {
                 ChessSquare old, new = boards[moveNum][k][j];
                   if(fromY == DROP_RANK && k==toY && j==toX) continue; // dropped pieces always stand for themselves
@@ -4770,12 +4810,12 @@ ParseBoard12(string)
                    basetime, increment, (int) gameInfo.variant);
        } else {
            if(gameInfo.variant == VariantNormal)
-             snprintf(str, MSG_SIZ, _("%s (%d) vs. %s (%d) {%d %d}"),
-                   gameInfo.white, white_stren, gameInfo.black, black_stren,
+             snprintf(str, MSG_SIZ, "%s (%d) %s %s (%d) {%d %d}",
+                   gameInfo.white, white_stren, _("vs."), gameInfo.black, black_stren,
                    basetime, increment);
            else
-             snprintf(str, MSG_SIZ, _("%s (%d) vs. %s (%d) {%d %d %s}"),
-                   gameInfo.white, white_stren, gameInfo.black, black_stren,
+             snprintf(str, MSG_SIZ, "%s (%d) %s %s (%d) {%d %d %s}",
+                   gameInfo.white, white_stren, _("vs."), gameInfo.black, black_stren,
                    basetime, increment, VariantName(gameInfo.variant));
        }
        DisplayTitle(str);
@@ -4823,7 +4863,7 @@ ParseBoard12(string)
 }
 
 void
-GetMoveListEvent()
+GetMoveListEvent ()
 {
     char buf[MSG_SIZ];
     if (appData.icsActive && gameMode != IcsIdle && ics_gamenum > 0) {
@@ -4834,8 +4874,7 @@ GetMoveListEvent()
 }
 
 void
-AnalysisPeriodicEvent(force)
-     int force;
+AnalysisPeriodicEvent (int force)
 {
     if (((programStats.ok_to_send == 0 || programStats.line_is_book)
         && !force) || !appData.periodicUpdates)
@@ -4851,16 +4890,14 @@ AnalysisPeriodicEvent(force)
     programStats.ok_to_send = 0;
 }
 
-void ics_update_width(new_width)
-       int new_width;
+void
+ics_update_width (int new_width)
 {
        ics_printf("set width %d\n", new_width);
 }
 
 void
-SendMoveToProgram(moveNum, cps)
-     int moveNum;
-     ChessProgramState *cps;
+SendMoveToProgram (int moveNum, ChessProgramState *cps)
 {
     char buf[MSG_SIZ];
 
@@ -4938,17 +4975,14 @@ SendMoveToProgram(moveNum, cps)
 }
 
 void
-SendMoveToICS(moveType, fromX, fromY, toX, toY, promoChar)
-     ChessMove moveType;
-     int fromX, fromY, toX, toY;
-     char promoChar;
+SendMoveToICS (ChessMove moveType, int fromX, int fromY, int toX, int toY, char promoChar)
 {
     char user_move[MSG_SIZ];
     char suffix[4];
 
     if(gameInfo.variant == VariantSChess && promoChar) {
        snprintf(suffix, 4, "=%c", toX == BOARD_WIDTH<<1 ? ToUpper(promoChar) : ToLower(promoChar));
-       if(toX == BOARD_WIDTH>>1) moveType = WhitePromotion; // kludge to do gating at Rook
+       if(moveType == NormalMove) moveType = WhitePromotion; // kludge to do gating
     } else suffix[0] = NULLCHAR;
 
     switch (moveType) {
@@ -5018,7 +5052,7 @@ SendMoveToICS(moveType, fromX, fromY, toX, toY, promoChar)
 }
 
 void
-UploadGameEvent()
+UploadGameEvent ()
 {   // [HGM] upload: send entire stored game to ICS as long-algebraic moves.
     int i, last = forwardMostMove; // make sure ICS reply cannot pre-empt us by clearing fmm
     static char *castlingStrings[4] = { "none", "kside", "qside", "both" };
@@ -5085,10 +5119,7 @@ UploadGameEvent()
 }
 
 void
-CoordsToComputerAlgebraic(rf, ff, rt, ft, promoChar, move)
-     int rf, ff, rt, ft;
-     char promoChar;
-     char move[7];
+CoordsToComputerAlgebraic (int rf, int ff, int rt, int ft, char promoChar, char move[7])
 {
     if (rf == DROP_RANK) {
       if(ff == EmptySquare) sprintf(move, "@@@@\n"); else // [HGM] pass
@@ -5106,8 +5137,7 @@ CoordsToComputerAlgebraic(rf, ff, rt, ft, promoChar, move)
 }
 
 void
-ProcessICSInitScript(f)
-     FILE *f;
+ProcessICSInitScript (FILE *f)
 {
     char buf[MSG_SIZ];
 
@@ -5122,7 +5152,7 @@ ProcessICSInitScript(f)
 static int lastX, lastY, selectFlag, dragging;
 
 void
-Sweep(int step)
+Sweep (int step)
 {
     ChessSquare king = WhiteKing, pawn = WhitePawn, last = promoSweep;
     if(gameInfo.variant == VariantKnightmate) king = WhiteUnicorn;
@@ -5143,7 +5173,8 @@ Sweep(int step)
     ChangeDragPiece(promoSweep);
 }
 
-int PromoScroll(int x, int y)
+int
+PromoScroll (int x, int y)
 {
   int step = 0;
 
@@ -5159,7 +5190,7 @@ int PromoScroll(int x, int y)
 }
 
 void
-NextPiece(int step)
+NextPiece (int step)
 {
     ChessSquare piece = boards[currentMove][toY][toX];
     do {
@@ -5174,7 +5205,7 @@ NextPiece(int step)
 }
 /* [HGM] Shogi move preprocessor: swap digits for letters, vice versa */
 void
-AlphaRank(char *move, int n)
+AlphaRank (char *move, int n)
 {
 //    char *p = move, c; int x, y;
 
@@ -5226,12 +5257,7 @@ char yy_textstr[8000];
 
 /* Parser for moves from gnuchess, ICS, or user typein box */
 Boolean
-ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar)
-     char *move;
-     int moveNum;
-     ChessMove *moveType;
-     int *fromX, *fromY, *toX, *toY;
-     char *promoChar;
+ParseOneMove (char *move, int moveNum, ChessMove *moveType, int *fromX, int *fromY, int *toX, int *toY, char *promoChar)
 {
     *moveType = yylexstr(moveNum, move, yy_textstr, sizeof yy_textstr);
 
@@ -5314,7 +5340,7 @@ Boolean pushed = FALSE;
 char *lastParseAttempt;
 
 void
-ParsePV(char *pv, Boolean storeComments, Boolean atEnd)
+ParsePV (char *pv, Boolean storeComments, Boolean atEnd)
 { // Parse a string of PV moves, and append to current game, behind forwardMostMove
   int fromX, fromY, toX, toY; char promoChar;
   ChessMove moveType;
@@ -5331,9 +5357,6 @@ ParsePV(char *pv, Boolean storeComments, Boolean atEnd)
     if(nr == 0 && !storeComments && *pv == '(') pv++; // first (ponder) move can be in parentheses
     lastParseAttempt = pv;
     valid = ParseOneMove(pv, endPV, &moveType, &fromX, &fromY, &toX, &toY, &promoChar);
-if(appData.debugMode){
-fprintf(debugFP,"parsePV: %d %c%c%c%c yy='%s'\nPV = '%s'\n", valid, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, yy_textstr, pv);
-}
     if(!valid && nr == 0 &&
        ParseOneMove(pv, endPV-1, &moveType, &fromX, &fromY, &toX, &toY, &promoChar)){
         nr++; moveType = Comment; // First move has been played; kludge to make sure we continue
@@ -5380,7 +5403,7 @@ fprintf(debugFP,"parsePV: %d %c%c%c%c yy='%s'\nPV = '%s'\n", valid, fromX+AAA, f
 }
 
 int
-MultiPV(ChessProgramState *cps)
+MultiPV (ChessProgramState *cps)
 {      // check if engine supports MultiPV, and if so, return the number of the option that sets it
        int i;
        for(i=0; i<cps->nrOptions; i++)
@@ -5390,7 +5413,7 @@ MultiPV(ChessProgramState *cps)
 }
 
 Boolean
-LoadMultiPV(int x, int y, char *buf, int index, int *start, int *end)
+LoadMultiPV (int x, int y, char *buf, int index, int *start, int *end)
 {
        int startPV, multi, lineStart, origIndex = index;
        char *p, buf2[MSG_SIZ];
@@ -5413,6 +5436,9 @@ LoadMultiPV(int x, int y, char *buf, int index, int *start, int *end)
                first.option[multi].value = n;
                *start = *end = 0;
                return FALSE;
+       } else if(strstr(buf+lineStart, "exclude:") == buf+lineStart) { // exclude moves clicked
+               ExcludeClick(origIndex - lineStart);
+               return FALSE;
        }
        ParsePV(buf+startPV, FALSE, gameMode != AnalyzeMode);
        *start = startPV; *end = index-1;
@@ -5420,7 +5446,7 @@ LoadMultiPV(int x, int y, char *buf, int index, int *start, int *end)
 }
 
 char *
-PvToSAN(char *pv)
+PvToSAN (char *pv)
 {
        static char buf[10*MSG_SIZ];
        int i, k=0, savedEnd=endPV, saveFMM = forwardMostMove;
@@ -5439,7 +5465,7 @@ PvToSAN(char *pv)
 }
 
 Boolean
-LoadPV(int x, int y)
+LoadPV (int x, int y)
 { // called on right mouse click to load PV
   int which = gameMode == TwoMachinesPlay && (WhiteOnMove(forwardMostMove) == (second.twoMachinesColor[0] == 'w'));
   lastX = x; lastY = y;
@@ -5448,10 +5474,11 @@ LoadPV(int x, int y)
 }
 
 void
-UnLoadPV()
+UnLoadPV ()
 {
   int oldFMM = forwardMostMove; // N.B.: this was currentMove before PV was loaded!
   if(endPV < 0) return;
+  if(appData.autoCopyPV) CopyFENToClipboard();
   endPV = -1;
   if(gameMode == AnalyzeMode && currentMove > forwardMostMove) {
        Boolean saveAnimate = appData.animate;
@@ -5474,7 +5501,7 @@ UnLoadPV()
 }
 
 void
-MovePV(int x, int y, int h)
+MovePV (int x, int y, int h)
 { // step through PV based on mouse coordinates (called on mouse move)
   int margin = h>>3, step = 0, threshold = (pieceSweep == EmptySquare ? 10 : 15);
 
@@ -5509,7 +5536,8 @@ int squaresLeft[4];
 int piecesLeft[(int)BlackPawn];
 int seed, nrOfShuffles;
 
-void GetPositionNumber()
+void
+GetPositionNumber ()
 {      // sets global variable seed
        int i;
 
@@ -5521,7 +5549,8 @@ void GetPositionNumber()
        }
 }
 
-int put(Board board, int pieceType, int rank, int n, int shade)
+int
+put (Board board, int pieceType, int rank, int n, int shade)
 // put the piece on the (n-1)-th empty squares of the given shade
 {
        int i;
@@ -5539,7 +5568,8 @@ int put(Board board, int pieceType, int rank, int n, int shade)
 }
 
 
-void AddOnePiece(Board board, int pieceType, int rank, int shade)
+void
+AddOnePiece (Board board, int pieceType, int rank, int shade)
 // calculate where the next piece goes, (any empty square), and put it there
 {
        int i;
@@ -5550,7 +5580,8 @@ void AddOnePiece(Board board, int pieceType, int rank, int shade)
         put(board, pieceType, rank, i, shade);
 }
 
-void AddTwoPieces(Board board, int pieceType, int rank)
+void
+AddTwoPieces (Board board, int pieceType, int rank)
 // calculate where the next 2 identical pieces go, (any empty square), and put it there
 {
        int i, n=squaresLeft[ANY], j=n-1, k;
@@ -5565,7 +5596,8 @@ void AddTwoPieces(Board board, int pieceType, int rank)
         put(board, pieceType, rank, i, ANY);
 }
 
-void SetUpShuffle(Board board, int number)
+void
+SetUpShuffle (Board board, int number)
 {
        int i, p, first=1;
 
@@ -5653,7 +5685,8 @@ void SetUpShuffle(Board board, int number)
        if(number >= 0) appData.defaultFrcPosition %= nrOfShuffles; // normalize
 }
 
-int SetCharTable( char *table, const char * map )
+int
+SetCharTable (char *table, const char * map)
 /* [HGM] moved here from winboard.c because of its general usefulness */
 /*       Basically a safe strcpy that uses the last character as King */
 {
@@ -5677,7 +5710,8 @@ int SetCharTable( char *table, const char * map )
     return result;
 }
 
-void Prelude(Board board)
+void
+Prelude (Board board)
 {      // [HGM] superchess: random selection of exo-pieces
        int i, j, k; ChessSquare p;
        static ChessSquare exoPieces[4] = { WhiteAngel, WhiteMarshall, WhiteSilver, WhiteLance };
@@ -5714,8 +5748,7 @@ void Prelude(Board board)
 }
 
 void
-InitPosition(redraw)
-     int redraw;
+InitPosition (int redraw)
 {
     ChessSquare (* pieces)[BOARD_FILES];
     int i, j, pawnRow, overrule,
@@ -6009,9 +6042,7 @@ InitPosition(redraw)
 }
 
 void
-SendBoard(cps, moveNum)
-     ChessProgramState *cps;
-     int moveNum;
+SendBoard (ChessProgramState *cps, int moveNum)
 {
     char message[MSG_SIZ];
 
@@ -6086,8 +6117,117 @@ SendBoard(cps, moveNum)
     setboardSpoiledMachineBlack = 0; /* [HGM] assume WB 4.2.7 already solves this after sending setboard */
 }
 
+char exclusionHeader[MSG_SIZ];
+int exCnt, excludePtr;
+typedef struct { int ff, fr, tf, tr, pc, mark; } Exclusion;
+static Exclusion excluTab[200];
+static char excludeMap[(BOARD_RANKS*BOARD_FILES*BOARD_RANKS*BOARD_FILES+7)/8]; // [HGM] exclude: bitmap for excluced moves
+
+static void
+WriteMap (int s)
+{
+    int j;
+    for(j=0; j<(BOARD_RANKS*BOARD_FILES*BOARD_RANKS*BOARD_FILES+7)/8; j++) excludeMap[j] = s;
+    exclusionHeader[19] = s ? '-' : '+'; // update tail state
+}
+
+static void
+ClearMap ()
+{
+    safeStrCpy(exclusionHeader, "exclude: none best +tail                                          \n", MSG_SIZ);
+    excludePtr = 24; exCnt = 0;
+    WriteMap(0);
+}
+
+static void
+UpdateExcludeHeader (int fromY, int fromX, int toY, int toX, char promoChar, char state)
+{   // search given move in table of header moves, to know where it is listed (and add if not there), and update state
+    char buf[2*MOVE_LEN], *p;
+    Exclusion *e = excluTab;
+    int i;
+    for(i=0; i<exCnt; i++)
+       if(e[i].ff == fromX && e[i].fr == fromY &&
+          e[i].tf == toX   && e[i].tr == toY && e[i].pc == promoChar) break;
+    if(i == exCnt) { // was not in exclude list; add it
+       CoordsToAlgebraic(boards[currentMove], PosFlags(currentMove), fromY, fromX, toY, toX, promoChar, buf);
+       if(strlen(exclusionHeader + excludePtr) < strlen(buf)) { // no space to write move
+           if(state != exclusionHeader[19]) exclusionHeader[19] = '*'; // tail is now in mixed state
+           return; // abort
+       }
+       e[i].ff = fromX; e[i].fr = fromY; e[i].tf = toX; e[i].tr = toY; e[i].pc = promoChar;
+       excludePtr++; e[i].mark = excludePtr++;
+       for(p=buf; *p; p++) exclusionHeader[excludePtr++] = *p; // copy move
+       exCnt++;
+    }
+    exclusionHeader[e[i].mark] = state;
+}
+
+static int
+ExcludeOneMove (int fromY, int fromX, int toY, int toX, signed char promoChar, char state)
+{   // include or exclude the given move, as specified by state ('+' or '-'), or toggle
+    char buf[MSG_SIZ];
+    int j, k;
+    ChessMove moveType;
+    if(promoChar == -1) { // kludge to indicate best move
+       if(!ParseOneMove(lastPV[0], currentMove, &moveType, &fromX, &fromY, &toX, &toY, &promoChar)) // get current best move from last PV
+           return 1; // if unparsable, abort
+    }
+    // update exclusion map (resolving toggle by consulting existing state)
+    k=(BOARD_FILES*fromY+fromX)*BOARD_RANKS*BOARD_FILES + (BOARD_FILES*toY+toX);
+    j = k%8; k >>= 3;
+    if(state == '*') state = (excludeMap[k] & 1<<j ? '+' : '-'); // toggle
+    if(state == '-' && !promoChar) // only non-promotions get marked as excluded, to allow exclusion of under-promotions
+        excludeMap[k] |=   1<<j;
+    else excludeMap[k] &= ~(1<<j);
+    // update header
+    UpdateExcludeHeader(fromY, fromX, toY, toX, promoChar, state);
+    // inform engine
+    snprintf(buf, MSG_SIZ, "%sclude ", state == '+' ? "in" : "ex");
+    CoordsToComputerAlgebraic(fromY, fromX, toY, toX, promoChar, buf+8);
+    SendToProgram(buf, &first);
+    return (state == '+');
+}
+
+static void
+ExcludeClick (int index)
+{
+    int i, j;
+    Exclusion *e = excluTab;
+    if(index < 25) { // none, best or tail clicked
+       if(index < 13) { // none: include all
+           WriteMap(0); // clear map
+           for(i=0; i<exCnt; i++) exclusionHeader[excluTab[i].mark] = '+'; // and moves
+           SendToProgram("include all\n", &first); // and inform engine
+       } else if(index > 18) { // tail
+           if(exclusionHeader[19] == '-') { // tail was excluded
+               SendToProgram("include all\n", &first);
+               WriteMap(0); // clear map completely
+               // now re-exclude selected moves
+               for(i=0; i<exCnt; i++) if(exclusionHeader[e[i].mark] == '-')
+                   ExcludeOneMove(e[i].fr, e[i].ff, e[i].tr, e[i].tf, e[i].pc, '-');
+           } else { // tail was included or in mixed state
+               SendToProgram("exclude all\n", &first);
+               WriteMap(0xFF); // fill map completely
+               // now re-include selected moves
+               j = 0; // count them
+               for(i=0; i<exCnt; i++) if(exclusionHeader[e[i].mark] == '+')
+                   ExcludeOneMove(e[i].fr, e[i].ff, e[i].tr, e[i].tf, e[i].pc, '+'), j++;
+               if(!j) ExcludeOneMove(0, 0, 0, 0, -1, '+'); // if no moves were selected, keep best
+           }
+       } else { // best
+           ExcludeOneMove(0, 0, 0, 0, -1, '-'); // exclude it
+       }
+    } else {
+       for(i=0; i<exCnt; i++) if(i == exCnt-1 || excluTab[i+1].mark > index) {
+           char *p=exclusionHeader + excluTab[i].mark; // do trust header more than map (promotions!)
+           ExcludeOneMove(e[i].fr, e[i].ff, e[i].tr, e[i].tf, e[i].pc, *p == '+' ? '-' : '+');
+           break;
+       }
+    }
+}
+
 ChessSquare
-DefaultPromoChoice(int white)
+DefaultPromoChoice (int white)
 {
     ChessSquare result;
     if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk)
@@ -6104,7 +6244,7 @@ DefaultPromoChoice(int white)
 static int autoQueen; // [HGM] oneclick
 
 int
-HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice, int sweepSelect)
+HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, int sweepSelect)
 {
     /* [HGM] rewritten IsPromotion to only flag promotions that offer a choice */
     /* [HGM] add Shogi promotions */
@@ -6206,8 +6346,7 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice, in
 }
 
 int
-InPalace(row, column)
-     int row, column;
+InPalace (int row, int column)
 {   /* [HGM] for Xiangqi */
     if( (row < 3 || row > BOARD_HEIGHT-4) &&
          column < (BOARD_WIDTH + 4)/2 &&
@@ -6216,9 +6355,7 @@ InPalace(row, column)
 }
 
 int
-PieceForSquare (x, y)
-     int x;
-     int y;
+PieceForSquare (int x, int y)
 {
   if (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT)
      return -1;
@@ -6227,8 +6364,7 @@ PieceForSquare (x, y)
 }
 
 int
-OKToStartUserMove(x, y)
-     int x, y;
+OKToStartUserMove (int x, int y)
 {
     ChessSquare from_piece;
     int white_piece;
@@ -6328,7 +6464,8 @@ OKToStartUserMove(x, y)
 }
 
 Boolean
-OnlyMove(int *x, int *y, Boolean captures) {
+OnlyMove (int *x, int *y, Boolean captures) 
+{
     DisambiguateClosure cl;
     if (appData.zippyPlay || !appData.testLegality) return FALSE;
     switch(gameMode) {
@@ -6390,14 +6527,15 @@ int lastLoadGameNumber = 0, lastLoadPositionNumber = 0;
 int lastLoadGameUseList = FALSE;
 char lastLoadGameTitle[MSG_SIZ], lastLoadPositionTitle[MSG_SIZ];
 ChessMove lastLoadGameStart = EndOfFile;
+int doubleClick;
 
 void
-UserMoveEvent(fromX, fromY, toX, toY, promoChar)
-     int fromX, fromY, toX, toY;
-     int promoChar;
+UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar)
 {
     ChessMove moveType;
     ChessSquare pdown, pup;
+    int ff=fromX, rf=fromY, ft=toX, rt=toY;
+
 
     /* Check if the user is playing in turn.  This is complicated because we
        let the user "pick up" a piece before it is his turn.  So the piece he
@@ -6564,15 +6702,19 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar)
        }
     }
 
+    if(doubleClick) { // [HGM] exclude: move entered with double-click on from square is for exclusion, not playing
+        if(ExcludeOneMove(fromY, fromX, toY, toX, promoChar, '*')) // toggle
+            ClearPremoveHighlights(); // was included
+       else ClearHighlights(), SetPremoveHighlights(ff, rf, ft, rt); // exclusion indicated  by premove highlights
+       return;
+    }
+
     FinishMove(moveType, fromX, fromY, toX, toY, promoChar);
 }
 
 /* Common tail of UserMoveEvent and DropMenuEvent */
 int
-FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
-     ChessMove moveType;
-     int fromX, fromY, toX, toY;
-     /*char*/int promoChar;
+FinishMove (ChessMove moveType, int fromX, int fromY, int toX, int toY, int promoChar)
 {
     char *bookHit = 0;
 
@@ -6638,6 +6780,8 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
     else forwardMostMove = currentMove;
   }
 
+  ClearMap();
+
   /* If we need the chess program but it's dead, restart it */
   ResurrectChessProgram();
 
@@ -6663,7 +6807,7 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
       gameMode = MachinePlaysBlack;
       StartClocks();
       SetGameInfo();
-      snprintf(buf, MSG_SIZ, _("%s vs. %s"), gameInfo.white, gameInfo.black);
+      snprintf(buf, MSG_SIZ, "%s %s %s", gameInfo.white, _("vs."), gameInfo.black);
       DisplayTitle(buf);
       if (first.sendName) {
        snprintf(buf, MSG_SIZ,"name %s\n", gameInfo.white);
@@ -6757,12 +6901,7 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
 }
 
 void
-Mark(board, flags, kind, rf, ff, rt, ft, closure)
-     Board board;
-     int flags;
-     ChessMove kind;
-     int rf, ff, rt, ft;
-     VOIDSTAR closure;
+Mark (Board board, int flags, ChessMove kind, int rf, int ff, int rt, int ft, VOIDSTAR closure)
 {
     typedef char Markers[BOARD_RANKS][BOARD_FILES];
     Markers *m = (Markers *) closure;
@@ -6774,7 +6913,7 @@ Mark(board, flags, kind, rf, ff, rt, ft, closure)
 }
 
 void
-MarkTargetSquares(int clear)
+MarkTargetSquares (int clear)
 {
   int x, y;
   if(!appData.markers || !appData.highlightDragging || appData.icsActive && gameInfo.variant < VariantShogi ||
@@ -6794,7 +6933,7 @@ MarkTargetSquares(int clear)
 }
 
 int
-Explode(Board board, int fromX, int fromY, int toX, int toY)
+Explode (Board board, int fromX, int fromY, int toX, int toY)
 {
     if(gameInfo.variant == VariantAtomic &&
        (board[toY][toX] != EmptySquare ||                     // capture?
@@ -6809,7 +6948,8 @@ Explode(Board board, int fromX, int fromY, int toX, int toY)
 
 ChessSquare gatingPiece = EmptySquare; // exported to front-end, for dragging
 
-int CanPromote(ChessSquare piece, int y)
+int
+CanPromote (ChessSquare piece, int y)
 {
        if(gameMode == EditPosition) return FALSE; // no promotions when editing position
        // some variants have fixed promotion piece, no promotion at all, or another selection mechanism
@@ -6823,19 +6963,19 @@ int CanPromote(ChessSquare piece, int y)
                piece == WhiteLance && y == BOARD_HEIGHT-2 );
 }
 
-void LeftClick(ClickType clickType, int xPix, int yPix)
+void
+LeftClick (ClickType clickType, int xPix, int yPix)
 {
     int x, y;
     Boolean saveAnimate;
     static int second = 0, promotionChoice = 0, clearFlag = 0;
     char promoChoice = NULLCHAR;
     ChessSquare piece;
+    static TimeMark lastClickTime, prevClickTime;
 
-    if(appData.seekGraph && appData.icsActive && loggedOn &&
-       (gameMode == BeginningOfGame || gameMode == IcsIdle)) {
-       SeekGraphClick(clickType, xPix, yPix, 0);
-       return;
-    }
+    if(SeekGraphClick(clickType, xPix, yPix, 0)) return;
+
+    prevClickTime = lastClickTime; GetTimeMark(&lastClickTime);
 
     if (clickType == Press) ErrorPopDown();
 
@@ -6884,7 +7024,13 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
               || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
        return;
 
-    if(clickType == Press && fromX == x && fromY == y && promoDefaultAltered)
+    if(gotPremove && x == premoveFromX && y == premoveFromY && clickType == Release) {
+       // could be static click on premove from-square: abort premove
+       gotPremove = 0;
+       ClearPremoveHighlights();
+    }
+
+    if(clickType == Press && fromX == x && fromY == y && promoDefaultAltered && SubtractTimeMarks(&lastClickTime, &prevClickTime) >= 200)
        fromX = fromY = -1; // second click on piece after altering default promo piece treated as first click
 
     if(!promoDefaultAltered) { // determine default promotion piece, based on the side the user is moving for
@@ -6905,6 +7051,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
        }
        return;
       }
+      doubleClick = FALSE;
       fromX = x; fromY = y; toX = toY = -1;
       if(!appData.oneClick || !OnlyMove(&x, &y, FALSE) ||
         // even if only move, we treat as normal when this would trigger a promotion popup, to allow sweep selection
@@ -6951,6 +7098,10 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
             !(fromP == BlackKing && toP == BlackRook && frc))) {
            /* Clicked again on same color piece -- changed his mind */
            second = (x == fromX && y == fromY);
+           if(second && gameMode == AnalyzeMode && SubtractTimeMarks(&lastClickTime, &prevClickTime) < 200) {
+               second = FALSE; // first double-click rather than scond click
+               doubleClick = first.excludeMoves; // used by UserMoveEvent to recognize exclude moves
+           }
            promoDefaultAltered = FALSE;
            MarkTargetSquares(1);
           if(!second || appData.oneClick && !OnlyMove(&x, &y, TRUE)) {
@@ -6964,7 +7115,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
                  (fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) &&
                y == (toP < BlackPawn ? 0 : BOARD_HEIGHT-1))
                  gatingPiece = boards[currentMove][fromY][fromX];
-               else gatingPiece = EmptySquare;
+               else gatingPiece = doubleClick ? fromP : EmptySquare;
                fromX = x;
                fromY = y; dragging = 1;
                MarkTargetSquares(0);
@@ -7086,7 +7237,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
     // off-board moves should not be highlighted
     if(x < 0 || y < 0) ClearHighlights();
 
-    if(gatingPiece != EmptySquare) promoChoice = ToLower(PieceToChar(gatingPiece));
+    if(gatingPiece != EmptySquare && gameInfo.variant == VariantSChess) promoChoice = ToLower(PieceToChar(gatingPiece));
 
     if (HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, appData.sweepSelect)) {
        SetHighlights(fromX, fromY, toX, toY);
@@ -7121,7 +7272,8 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
     }
 }
 
-int RightClick(ClickType action, int x, int y, int *fromX, int *fromY)
+int
+RightClick (ClickType action, int x, int y, int *fromX, int *fromY)
 {   // front-end-free part taken out of PieceMenuPopup
     int whichMenu; int xSqr, ySqr;
 
@@ -7211,7 +7363,8 @@ int RightClick(ClickType action, int x, int y, int *fromX, int *fromY)
     return whichMenu;
 }
 
-void SendProgramStatsToFrontend( ChessProgramState * cps, ChessProgramStats * cpstats )
+void
+SendProgramStatsToFrontend (ChessProgramState * cps, ChessProgramStats * cpstats)
 {
 //    char * hint = lastHint;
     FrontEndProgramStats stats;
@@ -7238,7 +7391,7 @@ void SendProgramStatsToFrontend( ChessProgramState * cps, ChessProgramStats * cp
 }
 
 void
-ClearEngineOutputPane(int which)
+ClearEngineOutputPane (int which)
 {
     static FrontEndProgramStats dummyStats;
     dummyStats.which = which;
@@ -7249,7 +7402,7 @@ ClearEngineOutputPane(int which)
 #define MAXPLAYERS 500
 
 char *
-TourneyStandings(int display)
+TourneyStandings (int display)
 {
     int i, w, b, color, wScore, bScore, dummy, nr=0, nPlayers=0;
     int score[MAXPLAYERS], ranking[MAXPLAYERS], points[MAXPLAYERS], games[MAXPLAYERS];
@@ -7293,7 +7446,7 @@ TourneyStandings(int display)
 }
 
 void
-Count(Board board, int pCnt[], int *nW, int *nB, int *wStale, int *bStale, int *bishopColor)
+Count (Board board, int pCnt[], int *nW, int *nB, int *wStale, int *bStale, int *bishopColor)
 {      // count all piece types
        int p, f, r;
        *nB = *nW = *wStale = *bStale = *bishopColor = 0;
@@ -7311,7 +7464,7 @@ Count(Board board, int pCnt[], int *nW, int *nB, int *wStale, int *bStale, int *
 }
 
 int
-SufficientDefence(int pCnt[], int side, int nMine, int nHis)
+SufficientDefence (int pCnt[], int side, int nMine, int nHis)
 {
        int myPawns = pCnt[WhitePawn+side]; // my total Pawn count;
        int majorDefense = pCnt[BlackRook-side] + pCnt[BlackCannon-side] + pCnt[BlackKnight-side];
@@ -7340,7 +7493,7 @@ SufficientDefence(int pCnt[], int side, int nMine, int nHis)
 }
 
 int
-MatingPotential(int pCnt[], int side, int nMine, int nHis, int stale, int bisColor)
+MatingPotential (int pCnt[], int side, int nMine, int nHis, int stale, int bisColor)
 {
        VariantClass v = gameInfo.variant;
 
@@ -7390,7 +7543,7 @@ MatingPotential(int pCnt[], int side, int nMine, int nHis, int stale, int bisCol
 }
 
 int
-CompareWithRights(Board b1, Board b2)
+CompareWithRights (Board b1, Board b2)
 {
     int rights = 0;
     if(!CompareBoards(b1, b2)) return FALSE;
@@ -7412,7 +7565,7 @@ CompareWithRights(Board b1, Board b2)
 }
 
 int
-Adjudicate(ChessProgramState *cps)
+Adjudicate (ChessProgramState *cps)
 {      // [HGM] some adjudications useful with buggy engines
        // [HGM] adjudicate: made into separate routine, which now can be called after every move
        //       In any case it determnes if the game is a claimable draw (filling in EP_STATUS).
@@ -7568,14 +7721,6 @@ Adjudicate(ChessProgramState *cps)
                      }
                 } else moveCount = 6;
            }
-       if (appData.debugMode) { int i;
-           fprintf(debugFP, "repeat test fmm=%d bmm=%d ep=%d, reps=%d\n",
-                   forwardMostMove, backwardMostMove, boards[backwardMostMove][EP_STATUS],
-                   appData.drawRepeats);
-           for( i=forwardMostMove; i>=backwardMostMove; i-- )
-             fprintf(debugFP, "%d ep=%d\n", i, (signed char)boards[i][EP_STATUS]);
-
-       }
 
        // Repetition draws and 50-move rule can be applied independently of legality testing
 
@@ -7721,7 +7866,8 @@ Adjudicate(ChessProgramState *cps)
        return 0;
 }
 
-char *SendMoveToBookUser(int moveNr, ChessProgramState *cps, int initial)
+char *
+SendMoveToBookUser (int moveNr, ChessProgramState *cps, int initial)
 {   // [HGM] book: this routine intercepts moves to simulate book replies
     char *bookHit = NULL;
 
@@ -7771,7 +7917,8 @@ char *SendMoveToBookUser(int moveNr, ChessProgramState *cps, int initial)
 
 char *savedMessage;
 ChessProgramState *savedState;
-void DeferredBookMove(void)
+void
+DeferredBookMove (void)
 {
        if(savedState->lastPing != savedState->lastPong)
                    ScheduleDelayedEvent(DeferredBookMove, 10);
@@ -7782,9 +7929,7 @@ void DeferredBookMove(void)
 static int savedWhitePlayer, savedBlackPlayer, pairingReceived;
 
 void
-HandleMachineMove(message, cps)
-     char *message;
-     ChessProgramState *cps;
+HandleMachineMove (char *message, ChessProgramState *cps)
 {
     char machineMove[MSG_SIZ], buf1[MSG_SIZ*10], buf2[MSG_SIZ];
     char realname[MSG_SIZ];
@@ -7911,11 +8056,6 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
            return;
        }
 
-    if (appData.debugMode) { int f = forwardMostMove;
-        fprintf(debugFP, "machine move %d, castling = %d %d %d %d %d %d\n", f,
-                boards[f][CASTLING][0],boards[f][CASTLING][1],boards[f][CASTLING][2],
-                boards[f][CASTLING][3],boards[f][CASTLING][4],boards[f][CASTLING][5]);
-    }
         if(cps->alphaRank) AlphaRank(machineMove, 4);
         if (!ParseOneMove(machineMove, forwardMostMove, &moveType,
                               &fromX, &fromY, &toX, &toY, &promoChar)) {
@@ -7941,12 +8081,6 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
            ChessMove moveType;
            moveType = LegalityTest(boards[forwardMostMove], PosFlags(forwardMostMove),
                              fromY, fromX, toY, toX, promoChar);
-           if (appData.debugMode) {
-                int i;
-                for(i=0; i< nrCastlingRights; i++) fprintf(debugFP, "(%d,%d) ",
-                    boards[forwardMostMove][CASTLING][i], castlingRank[i]);
-                fprintf(debugFP, "castling rights\n");
-           }
             if(moveType == IllegalMove) {
              snprintf(buf1, MSG_SIZ*10, "Xboard: Forfeit due to illegal move: %s (%c%c%c%c)%c",
                         machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, 0);
@@ -8372,7 +8506,7 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
 
     /*
      * If chess program startup fails, exit with an error message.
-     * Attempts to recover here are futile.
+     * Attempts to recover here are futile. [HGM] Well, we try anyway
      */
     if ((StrStr(message, "unknown host") != NULL)
        || (StrStr(message, "No remote directory") != NULL)
@@ -8386,7 +8520,17 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
                _(cps->which), cps->program, cps->host, message);
        RemoveInputSource(cps->isr);
        if(appData.icsActive) DisplayFatalError(buf1, 0, 1); else {
-           if(cps == &first) appData.noChessProgram = TRUE;
+           cps->isr = NULL;
+           DestroyChildProcess(cps->pr, 9 ); // just to be sure
+           cps->pr = NoProc; 
+           if(cps == &first) {
+               appData.noChessProgram = TRUE;
+               gameMode = MachinePlaysBlack; ModeHighlight(); // kludge to unmark Machine Black menu
+               gameMode = BeginningOfGame; ModeHighlight();
+               SetNCPMode();
+           }
+           if(GetDelayedEvent()) CancelDelayedEvent(), ThawUI(); // [HGM] cancel remaining loading effort scheduled after feature timeout
+           DisplayMessage("", ""); // erase waiting message
            DisplayError(buf1, 0);
        }
        return;
@@ -8882,8 +9026,7 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
    The display is not updated in any way.
    */
 void
-ParseGameHistory(game)
-     char *game;
+ParseGameHistory (char *game)
 {
     ChessMove moveType;
     int fromX, fromY, toX, toY, boardIndex;
@@ -9066,10 +9209,7 @@ ParseGameHistory(game)
 
 /* Apply a move to the given board  */
 void
-ApplyMove(fromX, fromY, toX, toY, promoChar, board)
-     int fromX, fromY, toX, toY;
-     int promoChar;
-     Board board;
+ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board)
 {
   ChessSquare captured = board[toY][toX], piece, king; int p, oldEP = EP_NONE, berolina = 0;
   int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand ? 3 : 1;
@@ -9350,10 +9490,13 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
         board[fromY][fromX] = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar)); // S-Chess gating
     } else
     if(promoChar == '+') {
-        /* [HGM] Shogi-style promotions, to piece implied by original (Might overwrite orinary Pawn promotion) */
+        /* [HGM] Shogi-style promotions, to piece implied by original (Might overwrite ordinary Pawn promotion) */
         board[toY][toX] = (ChessSquare) (PROMOTED piece);
     } else if(!appData.testLegality && promoChar != NULLCHAR && promoChar != '=') { // without legality testing, unconditionally believe promoChar
-        board[toY][toX] = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar));
+        ChessSquare newPiece = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar));
+       if((newPiece <= WhiteMan || newPiece >= BlackPawn && newPiece <= BlackMan) // unpromoted piece specified
+          && pieceToChar[PROMOTED newPiece] == '~') newPiece = PROMOTED newPiece; // but promoted version available
+        board[toY][toX] = newPiece;
     }
     if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand)
                && promoChar != NULLCHAR && gameInfo.holdingsSize) {
@@ -9372,9 +9515,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
 
 /* Updates forwardMostMove */
 void
-MakeMove(fromX, fromY, toX, toY, promoChar)
-     int fromX, fromY, toX, toY;
-     int promoChar;
+MakeMove (int fromX, int fromY, int toX, int toY, int promoChar)
 {
 //    forwardMostMove++; // [HGM] bare: moved downstream
 
@@ -9471,15 +9612,12 @@ MakeMove(fromX, fromY, toX, toY, promoChar)
        strcat(parseList[forwardMostMove - 1], "#");
        break;
     }
-    if (appData.debugMode) {
-        fprintf(debugFP, "move: %s, parse: %s (%c)\n", moveList[forwardMostMove-1], parseList[forwardMostMove-1], moveList[forwardMostMove-1][4]);
-    }
 
 }
 
 /* Updates currentMove if not pausing */
 void
-ShowMove(fromX, fromY, toX, toY)
+ShowMove (int fromX, int fromY, int toX, int toY)
 {
     int instant = (gameMode == PlayFromGameFile) ?
        (matchMode || (appData.timeDelay == 0 && !pausing)) : pausing;
@@ -9505,7 +9643,8 @@ ShowMove(fromX, fromY, toX, toY)
     HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1);
 }
 
-void SendEgtPath(ChessProgramState *cps)
+void
+SendEgtPath (ChessProgramState *cps)
 {       /* [HGM] EGT: match formats given in feature with those given by user, and send info for each match */
        char buf[MSG_SIZ], name[MSG_SIZ], *p;
 
@@ -9539,9 +9678,8 @@ void SendEgtPath(ChessProgramState *cps)
 }
 
 void
-InitChessProgram(cps, setup)
-     ChessProgramState *cps;
-     int setup; /* [HGM] needed to setup FRC opening position */
+InitChessProgram (ChessProgramState *cps, int setup)
+/* setup needed to setup FRC opening position */
 {
     char buf[MSG_SIZ], b[MSG_SIZ]; int overruled;
     if (appData.noChessProgram) return;
@@ -9662,8 +9800,7 @@ InitChessProgram(cps, setup)
 
 
 void
-StartChessProgram(cps)
-     ChessProgramState *cps;
+StartChessProgram (ChessProgramState *cps)
 {
     char buf[MSG_SIZ];
     int err;
@@ -9730,7 +9867,7 @@ TwoMachinesEventIfReady P((void))
 }
 
 char *
-MakeName(char *template)
+MakeName (char *template)
 {
     time_t clock;
     struct tm *tm;
@@ -9759,7 +9896,7 @@ MakeName(char *template)
 }
 
 int
-CountPlayers(char *p)
+CountPlayers (char *p)
 {
     int n = 0;
     while(p = strchr(p, '\n')) p++, n++; // count participants
@@ -9767,7 +9904,7 @@ CountPlayers(char *p)
 }
 
 FILE *
-WriteTourneyFile(char *results, FILE *f)
+WriteTourneyFile (char *results, FILE *f)
 {   // write tournament parameters on tourneyFile; on success return the stream pointer for closing
     if(f == NULL) f = fopen(appData.tourneyFile, "w");
     if(f == NULL) DisplayError(_("Could not write on tourney file"), 0); else {
@@ -9798,10 +9935,10 @@ WriteTourneyFile(char *results, FILE *f)
     return f;
 }
 
-#define MAXENGINES 1000
 char *command[MAXENGINES], *mnemonic[MAXENGINES];
 
-void Substitute(char *participants, int expunge)
+void
+Substitute (char *participants, int expunge)
 {
     int i, changed, changes=0, nPlayers=0;
     char *p, *q, *r, buf[MSG_SIZ];
@@ -9822,7 +9959,7 @@ void Substitute(char *participants, int expunge)
        q = r; while(*q) nPlayers += (*q++ == '\n');
        p = buf; while(*r && (*p = *r++) != '\n') p++;
        *p = NULLCHAR;
-       NamesToList(firstChessProgramNames, command, mnemonic);
+       NamesToList(firstChessProgramNames, command, mnemonic, "all");
        for(i=1; mnemonic[i]; i++) if(!strcmp(buf, mnemonic[i])) break;
        if(mnemonic[i]) { // The substitute is valid
            FILE *f;
@@ -9859,7 +9996,7 @@ void Substitute(char *participants, int expunge)
 }
 
 int
-CreateTourney(char *name)
+CreateTourney (char *name)
 {
        FILE *f;
        if(matchMode && strcmp(name, appData.tourneyFile)) {
@@ -9891,18 +10028,29 @@ CreateTourney(char *name)
        return 1;
 }
 
-void NamesToList(char *names, char **engineList, char **engineMnemonic)
+int
+NamesToList (char *names, char **engineList, char **engineMnemonic, char *group)
 {
     char buf[MSG_SIZ], *p, *q;
-    int i=1;
-    while(*names) {
-       p = names; q = buf;
+    int i=1, header, skip, all = !strcmp(group, "all"), depth = 0;
+    insert = names; // afterwards, this global will point just after last retrieved engine line or group end in the 'names'
+    skip = !all && group[0]; // if group requested, we start in skip mode
+    for(;*names && depth >= 0 && i < MAXENGINES-1; names = p) {
+       p = names; q = buf; header = 0;
        while(*p && *p != '\n') *q++ = *p++;
        *q = 0;
+       if(*p == '\n') p++;
+       if(buf[0] == '#') {
+           if(strstr(buf, "# end") == buf) { if(!--depth) insert = p; continue; } // leave group, and suppress printing label
+           depth++; // we must be entering a new group
+           if(all) continue; // suppress printing group headers when complete list requested
+           header = 1;
+           if(skip && !strcmp(group, buf)) { depth = 0; skip = FALSE; } // start when we reach requested group
+       }
+       if(depth != header && !all || skip) continue; // skip contents of group (but print first-level header)
        if(engineList[i]) free(engineList[i]);
        engineList[i] = strdup(buf);
-       if(*p == '\n') p++;
-       TidyProgramName(engineList[i], "localhost", buf);
+       if(buf[0] != '#') insert = p, TidyProgramName(engineList[i], "localhost", buf); // group headers not tidied
        if(engineMnemonic[i]) free(engineMnemonic[i]);
        if((q = strstr(engineList[i]+2, "variant")) && q[-2]== ' ' && (q[-1]=='/' || q[-1]=='-') && (q[7]==' ' || q[7]=='=')) {
            strcat(buf, " (");
@@ -9910,16 +10058,17 @@ void NamesToList(char *names, char **engineList, char **engineMnemonic)
            strcat(buf, ")");
        }
        engineMnemonic[i] = strdup(buf);
-       names = p; i++;
-      if(i > MAXENGINES - 2) break;
+       i++;
     }
     engineList[i] = engineMnemonic[i] = NULL;
+    return i;
 }
 
 // following implemented as macro to avoid type limitations
 #define SWAP(item, temp) temp = appData.item[0]; appData.item[0] = appData.item[n]; appData.item[n] = temp;
 
-void SwapEngines(int n)
+void
+SwapEngines (int n)
 {   // swap settings for first engine and other engine (so far only some selected options)
     int h;
     char *p;
@@ -9936,27 +10085,51 @@ void SwapEngines(int n)
     SWAP(pgnName, p)
     SWAP(pvSAN, h)
     SWAP(engOptions, p)
+    SWAP(engInitString, p)
+    SWAP(computerString, p)
+    SWAP(features, p)
+    SWAP(fenOverride, p)
+    SWAP(NPS, h)
+    SWAP(accumulateTC, h)
+    SWAP(host, p)
 }
 
-void
-SetPlayer(int player)
+int
+SetPlayer (int player, char *p)
 {   // [HGM] find the engine line of the partcipant given by number, and parse its options.
     int i;
-    char buf[MSG_SIZ], *engineName, *p = appData.participants;
+    char buf[MSG_SIZ], *engineName;
     for(i=0; i<player; i++) p = strchr(p, '\n') + 1;
     engineName = strdup(p); if(p = strchr(engineName, '\n')) *p = NULLCHAR;
     for(i=1; command[i]; i++) if(!strcmp(mnemonic[i], engineName)) break;
     if(mnemonic[i]) {
        snprintf(buf, MSG_SIZ, "-fcp %s", command[i]);
        ParseArgsFromString(resetOptions); appData.fenOverride[0] = NULL; appData.pvSAN[0] = FALSE;
-       appData.firstHasOwnBookUCI = !appData.defNoBook;
+       appData.firstHasOwnBookUCI = !appData.defNoBook; appData.protocolVersion[0] = PROTOVER;
        ParseArgsFromString(buf);
     }
     free(engineName);
+    return i;
+}
+
+char *recentEngines;
+
+void
+RecentEngineEvent (int nr)
+{
+    int n;
+//    SwapEngines(1); // bump first to second
+//    ReplaceEngine(&second, 1); // and load it there
+    NamesToList(firstChessProgramNames, command, mnemonic, "all"); // get mnemonics of installed engines
+    n = SetPlayer(nr, recentEngines); // select new (using original menu order!)
+    if(mnemonic[n]) { // if somehow the engine with the selected nickname is no longer found in the list, we skip
+       ReplaceEngine(&first, 0);
+       FloatToFront(&appData.recentEngineList, command[n]);
+    }
 }
 
 int
-Pairing(int nr, int nPlayers, int *whitePlayer, int *blackPlayer, int *syncInterval)
+Pairing (int nr, int nPlayers, int *whitePlayer, int *blackPlayer, int *syncInterval)
 {   // determine players from game number
     int curCycle, curRound, curPairing, gamesPerCycle, gamesPerRound, roundsPerCycle=1, pairingsPerRound=1;
 
@@ -9991,6 +10164,9 @@ Pairing(int nr, int nPlayers, int *whitePlayer, int *blackPlayer, int *syncInter
            *blackPlayer = curRound + (nPlayers-1)/2 - curPairing;
            if(*blackPlayer >= nPlayers-1+(nPlayers&1)) *blackPlayer -= nPlayers-1+(nPlayers&1);
        }
+    } else if(appData.tourneyType > 1) {
+       *blackPlayer = curPairing; // in multi-gauntlet, assign gauntlet engines to second, so first an be kept loaded during round
+       *whitePlayer = curRound + appData.tourneyType;
     } else if(appData.tourneyType > 0) {
        *whitePlayer = curPairing;
        *blackPlayer = curRound + appData.tourneyType;
@@ -10002,7 +10178,7 @@ Pairing(int nr, int nPlayers, int *whitePlayer, int *blackPlayer, int *syncInter
 }
 
 int
-NextTourneyGame(int nr, int *swapColors)
+NextTourneyGame (int nr, int *swapColors)
 {   // !!!major kludge!!! fiddle appData settings to get everything in order for next tourney game
     char *p, *q;
     int whitePlayer, blackPlayer, firstBusy=1000000000, syncInterval = 0, nPlayers;
@@ -10052,26 +10228,48 @@ NextTourneyGame(int nr, int *swapColors)
        matchGame = 1; roundNr = nr / syncInterval + 1;
     }
 
-    if(first.pr != NoProc || second.pr != NoProc) return 1; // engines already loaded
+    if(first.pr != NoProc && second.pr != NoProc || nr<0) return 1; // engines already loaded
 
     // redefine engines, engine dir, etc.
-    NamesToList(firstChessProgramNames, command, mnemonic); // get mnemonics of installed engines
-    SetPlayer(whitePlayer); // find white player amongst it, and parse its engine line
-    SwapEngines(1);
-    SetPlayer(blackPlayer); // find black player amongst it, and parse its engine line
-    SwapEngines(1);         // and make that valid for second engine by swapping
-    InitEngine(&first, 0);  // initialize ChessProgramStates based on new settings.
-    InitEngine(&second, 1);
+    NamesToList(firstChessProgramNames, command, mnemonic, "all"); // get mnemonics of installed engines
+    if(first.pr == NoProc) {
+      SetPlayer(whitePlayer, appData.participants); // find white player amongst it, and parse its engine line
+      InitEngine(&first, 0);  // initialize ChessProgramStates based on new settings.
+    }
+    if(second.pr == NoProc) {
+      SwapEngines(1);
+      SetPlayer(blackPlayer, appData.participants); // find black player amongst it, and parse its engine line
+      SwapEngines(1);         // and make that valid for second engine by swapping
+      InitEngine(&second, 1);
+    }
     CommonEngineInit();     // after this TwoMachinesEvent will create correct engine processes
     UpdateLogos(FALSE);     // leave display to ModeHiglight()
     return 1;
 }
 
 void
-NextMatchGame()
+NextMatchGame ()
 {   // performs game initialization that does not invoke engines, and then tries to start the game
     int res, firstWhite, swapColors = 0;
     if(!NextTourneyGame(nextGame, &swapColors)) return; // this sets matchGame, -fcp / -scp and other options for next game, if needed
+    if(matchMode && appData.debugMode) { // [HGM] debug split: game is part of a match; we might have to create a debug file just for this game
+       char buf[MSG_SIZ];
+       snprintf(buf, MSG_SIZ, appData.nameOfDebugFile, nextGame+1); // expand name of debug file with %d in it
+       if(strcmp(buf, currentDebugFile)) { // name has changed
+           FILE *f = fopen(buf, "w");
+           if(f) { // if opening the new file failed, just keep using the old one
+               ASSIGN(currentDebugFile, buf);
+               fclose(debugFP);
+               debugFP = f;
+           }
+           if(appData.serverFileName) {
+               if(serverFP) fclose(serverFP);
+               serverFP = fopen(appData.serverFileName, "w");
+               if(serverFP && first.pr != NoProc) fprintf(serverFP, "StartChildProcess (dir=\".\") .\\%s\n", first.tidy);
+               if(serverFP && second.pr != NoProc) fprintf(serverFP, "StartChildProcess (dir=\".\") .\\%s\n", second.tidy);
+           }
+       }
+    }
     firstWhite = appData.firstPlaysBlack ^ (matchGame & 1 | appData.sameColorGames > 1); // non-incremental default
     firstWhite ^= swapColors; // reverses if NextTourneyGame says we are in an odd round
     first.twoMachinesColor =  firstWhite ? "white\n" : "black\n";   // perform actual color assignement
@@ -10085,7 +10283,8 @@ NextMatchGame()
     TwoMachinesEvent();
 }
 
-void UserAdjudicationEvent( int result )
+void
+UserAdjudicationEvent (int result)
 {
     ChessMove gameResult = GameIsDrawn;
 
@@ -10103,7 +10302,8 @@ void UserAdjudicationEvent( int result )
 
 
 // [HGM] save: calculate checksum of game to make games easily identifiable
-int StringCheckSum(char *s)
+int
+StringCheckSum (char *s)
 {
        int i = 0;
        if(s==NULL) return 0;
@@ -10111,7 +10311,8 @@ int StringCheckSum(char *s)
        return i;
 }
 
-int GameCheckSum()
+int
+GameCheckSum ()
 {
        int i, sum=0;
        for(i=backwardMostMove; i<forwardMostMove; i++) {
@@ -10125,10 +10326,7 @@ int GameCheckSum()
 } // end of save patch
 
 void
-GameEnds(result, resultDetails, whosays)
-     ChessMove result;
-     char *resultDetails;
-     int whosays;
+GameEnds (ChessMove result, char *resultDetails, int whosays)
 {
     GameMode nextGameMode;
     int isIcsGame;
@@ -10482,7 +10680,7 @@ GameEnds(result, resultDetails, whosays)
                     first.matchWins, second.matchWins,
                     appData.matchGames - (first.matchWins + second.matchWins));
            if(!appData.tourneyFile[0]) matchGame++, DisplayTwoMachinesTitle(); // [HGM] update result in window title
-           if(strcmp(ranking, "busy") && appData.afterTourney && appData.afterTourney[0]) RunCommand(appData.afterTourney);
+           if(ranking && strcmp(ranking, "busy") && appData.afterTourney && appData.afterTourney[0]) RunCommand(appData.afterTourney);
            popupRequested++; // [HGM] crash: postpone to after resetting endingGame
            if (appData.firstPlaysBlack) { // [HGM] match: back to original for next match
                first.twoMachinesColor = "black\n";
@@ -10520,9 +10718,7 @@ GameEnds(result, resultDetails, whosays)
 /* Assumes program was just initialized (initString sent).
    Leaves program in force mode. */
 void
-FeedMovesToProgram(cps, upto)
-     ChessProgramState *cps;
-     int upto;
+FeedMovesToProgram (ChessProgramState *cps, int upto)
 {
     int i;
 
@@ -10553,7 +10749,7 @@ FeedMovesToProgram(cps, upto)
 
 
 int
-ResurrectChessProgram()
+ResurrectChessProgram ()
 {
      /* The chess program may have exited.
        If so, restart it and feed it all the moves made so far. */
@@ -10592,8 +10788,7 @@ ResurrectChessProgram()
  * Button procedures
  */
 void
-Reset(redraw, init)
-     int redraw, init;
+Reset (int redraw, int init)
 {
     int i;
 
@@ -10650,6 +10845,7 @@ Reset(redraw, init)
     ModeHighlight();
     if(appData.icsActive) gameInfo.variant = VariantNormal;
     currentMove = forwardMostMove = backwardMostMove = 0;
+    MarkTargetSquares(1);
     InitPosition(redraw);
     for (i = 0; i < MAX_MOVES; i++) {
        if (commentList[i] != NULL) {
@@ -10671,10 +10867,11 @@ Reset(redraw, init)
     DisplayMessage("", "");
     HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1);
     lastSavedGame = 0; // [HGM] save: make sure next game counts as unsaved
+    ClearMap();        // [HGM] exclude: invalidate map
 }
 
 void
-AutoPlayGameLoop()
+AutoPlayGameLoop ()
 {
     for (;;) {
        if (!AutoPlayOneMove())
@@ -10690,7 +10887,7 @@ AutoPlayGameLoop()
 
 
 int
-AutoPlayOneMove()
+AutoPlayOneMove ()
 {
     int fromX, fromY, toX, toY;
 
@@ -10749,8 +10946,7 @@ AutoPlayOneMove()
 
 
 int
-LoadGameOneMove(readAhead)
-     ChessMove readAhead;
+LoadGameOneMove (ChessMove readAhead)
 {
     int fromX = 0, fromY = 0, toX = 0, toY = 0, done;
     char promoChar = NULLCHAR;
@@ -10985,11 +11181,7 @@ LoadGameOneMove(readAhead)
 
 /* Load the nth game from the given file */
 int
-LoadGameFromFile(filename, n, title, useList)
-     char *filename;
-     int n;
-     char *title;
-     /*Boolean*/ int useList;
+LoadGameFromFile (char *filename, int n, char *title, int useList)
 {
     FILE *f;
     char buf[MSG_SIZ];
@@ -11027,7 +11219,7 @@ LoadGameFromFile(filename, n, title, useList)
 
 
 void
-MakeRegisteredMove()
+MakeRegisteredMove ()
 {
     int fromX, fromY, toX, toY;
     char promoChar;
@@ -11092,11 +11284,7 @@ MakeRegisteredMove()
 
 /* Wrapper around LoadGame for use when a Cmail message is loaded */
 int
-CmailLoadGame(f, gameNumber, title, useList)
-     FILE *f;
-     int gameNumber;
-     char *title;
-     int useList;
+CmailLoadGame (FILE *f, int gameNumber, char *title, int useList)
 {
     int retVal;
 
@@ -11137,8 +11325,7 @@ CmailLoadGame(f, gameNumber, title, useList)
 
 /* Support for LoadNextGame, LoadPreviousGame, ReloadSameGame */
 int
-ReloadGame(offset)
-     int offset;
+ReloadGame (int offset)
 {
     int gameNumber = lastLoadGameNumber + offset;
     if (lastLoadGameFP == NULL) {
@@ -11161,7 +11348,7 @@ ReloadGame(offset)
 int keys[EmptySquare+1];
 
 int
-PositionMatches(Board b1, Board b2)
+PositionMatches (Board b1, Board b2)
 {
     int r, f, sum=0;
     switch(appData.searchMode) {
@@ -11208,7 +11395,8 @@ Move initialSpace[DSIZE+1000]; // gamble on that game will not be more than 500
 Move *moveDatabase = initialSpace;
 unsigned int movePtr, dataSize = DSIZE;
 
-int MakePieceList(Board board, int *counts)
+int
+MakePieceList (Board board, int *counts)
 {
     int r, f, n=Q_PROMO, total=0;
     for(r=0;r<EmptySquare;r++) counts[r] = 0; // piece-type counts
@@ -11228,7 +11416,8 @@ int MakePieceList(Board board, int *counts)
     return total;
 }
 
-void PackMove(int fromX, int fromY, int toX, int toY, ChessSquare promoPiece)
+void
+PackMove (int fromX, int fromY, int toX, int toY, ChessSquare promoPiece)
 {
     int sq = fromX + (fromY<<4);
     int piece = quickBoard[sq];
@@ -11263,14 +11452,15 @@ void PackMove(int fromX, int fromY, int toX, int toY, ChessSquare promoPiece)
     movePtr++;
 }
 
-int PackGame(Board board)
+int
+PackGame (Board board)
 {
     Move *newSpace = NULL;
     moveDatabase[movePtr].piece = 0; // terminate previous game
     if(movePtr > dataSize) {
        if(appData.debugMode) fprintf(debugFP, "move-cache overflow, enlarge to %d MB\n", dataSize/128);
        dataSize *= 8; // increase size by factor 8 (512KB -> 4MB -> 32MB -> 256MB -> 2GB)
-       if(dataSize) newSpace = (Move*) calloc(8*dataSize + 1000, sizeof(Move));
+       if(dataSize) newSpace = (Move*) calloc(dataSize + 1000, sizeof(Move));
        if(newSpace) {
            int i;
            Move *p = moveDatabase, *q = newSpace;
@@ -11287,7 +11477,8 @@ int PackGame(Board board)
     return movePtr;
 }
 
-int QuickCompare(Board board, int *minCounts, int *maxCounts)
+int
+QuickCompare (Board board, int *minCounts, int *maxCounts)
 {   // compare according to search mode
     int r, f;
     switch(appData.searchMode)
@@ -11321,7 +11512,8 @@ int QuickCompare(Board board, int *minCounts, int *maxCounts)
     return TRUE;
 }
 
-int QuickScan(Board board, Move *move)
+int
+QuickScan (Board board, Move *move)
 {   // reconstruct game,and compare all positions in it
     int cnt=0, stretch=0, total = MakePieceList(board, counts);
     do {
@@ -11371,7 +11563,8 @@ int QuickScan(Board board, Move *move)
     } while(1);
 }
 
-void InitSearch()
+void
+InitSearch ()
 {
     int r, f;
     flipSearch = FALSE;
@@ -11413,7 +11606,8 @@ void InitSearch()
 
 GameInfo dummyInfo;
 
-int GameContainsPosition(FILE *f, ListGame *lg)
+int
+GameContainsPosition (FILE *f, ListGame *lg)
 {
     int next, btm=0, plyNr=0, scratch=forwardMostMove+2&~1;
     int fromX, fromY, toX, toY;
@@ -11516,11 +11710,7 @@ int GameContainsPosition(FILE *f, ListGame *lg)
 
 /* Load the nth game from open file f */
 int
-LoadGame(f, gameNumber, title, useList)
-     FILE *f;
-     int gameNumber;
-     char *title;
-     int useList;
+LoadGame (FILE *f, int gameNumber, char *title, int useList)
 {
     ChessMove cm;
     char buf[MSG_SIZ];
@@ -11581,7 +11771,7 @@ LoadGame(f, gameNumber, title, useList)
     yynewfile(f);
 
     if (lg && lg->gameInfo.white && lg->gameInfo.black) {
-      snprintf(buf, sizeof(buf), _("%s vs. %s"), lg->gameInfo.white,
+      snprintf(buf, sizeof(buf), "%s %s %s", lg->gameInfo.white, _("vs."),
                lg->gameInfo.black);
            DisplayTitle(buf);
     } else if (*title != NULLCHAR) {
@@ -11971,8 +12161,7 @@ LoadGame(f, gameNumber, title, useList)
 
 /* Support for LoadNextPosition, LoadPreviousPosition, ReloadSamePosition */
 int
-ReloadPosition(offset)
-     int offset;
+ReloadPosition (int offset)
 {
     int positionNumber = lastLoadPositionNumber + offset;
     if (lastLoadPositionFP == NULL) {
@@ -11989,10 +12178,7 @@ ReloadPosition(offset)
 
 /* Load the nth position from the given file */
 int
-LoadPositionFromFile(filename, n, title)
-     char *filename;
-     int n;
-     char *title;
+LoadPositionFromFile (char *filename, int n, char *title)
 {
     FILE *f;
     char buf[MSG_SIZ];
@@ -12013,10 +12199,7 @@ LoadPositionFromFile(filename, n, title)
 
 /* Load the nth position from the given open file, and close it */
 int
-LoadPosition(f, positionNumber, title)
-     FILE *f;
-     int positionNumber;
-     char *title;
+LoadPosition (FILE *f, int positionNumber, char *title)
 {
     char *p, line[MSG_SIZ];
     Board initial_position;
@@ -12148,8 +12331,7 @@ int i, j;
 
 
 void
-CopyPlayerNameIntoFileName(dest, src)
-     char **dest, *src;
+CopyPlayerNameIntoFileName (char **dest, char *src)
 {
     while (*src != NULLCHAR && *src != ',') {
        if (*src == ' ') {
@@ -12161,8 +12343,8 @@ CopyPlayerNameIntoFileName(dest, src)
     }
 }
 
-char *DefaultFileName(ext)
-     char *ext;
+char *
+DefaultFileName (char *ext)
 {
     static char def[MSG_SIZ];
     char *p;
@@ -12182,9 +12364,7 @@ char *DefaultFileName(ext)
 
 /* Save the current game to the given file */
 int
-SaveGameToFile(filename, append)
-     char *filename;
-     int append;
+SaveGameToFile (char *filename, int append)
 {
     FILE *f;
     char buf[MSG_SIZ];
@@ -12218,8 +12398,7 @@ SaveGameToFile(filename, append)
 }
 
 char *
-SavePart(str)
-     char *str;
+SavePart (char *str)
 {
     static char buf[MSG_SIZ];
     char *p;
@@ -12236,8 +12415,8 @@ SavePart(str)
 #define PGN_SIDE_WHITE  0
 #define PGN_SIDE_BLACK  1
 
-/* [AS] */
-static int FindFirstMoveOutOfBook( int side )
+static int
+FindFirstMoveOutOfBook (int side)
 {
     int result = -1;
 
@@ -12280,8 +12459,8 @@ static int FindFirstMoveOutOfBook( int side )
     return result;
 }
 
-/* [AS] */
-void GetOutOfBookInfo( char * buf )
+void
+GetOutOfBookInfo (char * buf)
 {
     int oob[2];
     int i;
@@ -12312,8 +12491,7 @@ void GetOutOfBookInfo( char * buf )
 
 /* Save game in PGN style and close the file */
 int
-SaveGamePGN(f)
-     FILE *f;
+SaveGamePGN (FILE *f)
 {
     int i, offset, linelen, newblock;
     time_t tm;
@@ -12328,6 +12506,8 @@ SaveGamePGN(f)
 
     PrintPGNTags(f, &gameInfo);
 
+    if(appData.numberTag && matchMode) fprintf(f, "[Number \"%d\"]\n", nextGame+1); // [HGM] number tag
+
     if (backwardMostMove > 0 || startedFromSetupPosition) {
         char *fen = PositionToFEN(backwardMostMove, NULL);
         fprintf(f, "[FEN \"%s\"]\n[SetUp \"1\"]\n", fen);
@@ -12479,8 +12659,7 @@ SaveGamePGN(f)
 
 /* Save game in old style and close the file */
 int
-SaveGameOldStyle(f)
-     FILE *f;
+SaveGameOldStyle (FILE *f)
 {
     int i, offset;
     time_t tm;
@@ -12544,10 +12723,7 @@ SaveGameOldStyle(f)
 
 /* Save the current game to open file f and close the file */
 int
-SaveGame(f, dummy, dummy2)
-     FILE *f;
-     int dummy;
-     char *dummy2;
+SaveGame (FILE *f, int dummy, char *dummy2)
 {
     if (gameMode == EditPosition) EditPositionDone(TRUE);
     lastSavedGame = GameCheckSum(); // [HGM] save: remember ID of last saved game to prevent double saving
@@ -12559,8 +12735,7 @@ SaveGame(f, dummy, dummy2)
 
 /* Save the current position to the given file */
 int
-SavePositionToFile(filename)
-     char *filename;
+SavePositionToFile (char *filename)
 {
     FILE *f;
     char buf[MSG_SIZ];
@@ -12588,10 +12763,7 @@ SavePositionToFile(filename)
 
 /* Save the current position to the given open file and close the file */
 int
-SavePosition(f, dummy, dummy2)
-     FILE *f;
-     int dummy;
-     char *dummy2;
+SavePosition (FILE *f, int dummy, char *dummy2)
 {
     time_t tm;
     char *fen;
@@ -12615,8 +12787,7 @@ SavePosition(f, dummy, dummy2)
 }
 
 void
-ReloadCmailMsgEvent(unregister)
-     int unregister;
+ReloadCmailMsgEvent (int unregister)
 {
 #if !WIN32
     static char *inFilename = NULL;
@@ -12682,7 +12853,7 @@ ReloadCmailMsgEvent(unregister)
 }
 
 int
-RegisterMove()
+RegisterMove ()
 {
     FILE *f;
     char string[MSG_SIZ];
@@ -12772,7 +12943,7 @@ RegisterMove()
 }
 
 void
-MailMoveEvent()
+MailMoveEvent ()
 {
 #if !WIN32
     static char *partCommandString = "cmail -xv%s -remail -game %s 2>&1";
@@ -12860,7 +13031,7 @@ MailMoveEvent()
 }
 
 char *
-CmailMsg()
+CmailMsg ()
 {
 #if WIN32
     return NULL;
@@ -12933,7 +13104,7 @@ CmailMsg()
 }
 
 void
-ResetGameEvent()
+ResetGameEvent ()
 {
     if (gameMode == Training)
       SetTrainingModeOff();
@@ -12947,8 +13118,7 @@ ResetGameEvent()
 }
 
 void
-ExitEvent(status)
-     int status;
+ExitEvent (int status)
 {
     exiting++;
     if (exiting > 2) {
@@ -13010,7 +13180,7 @@ ExitEvent(status)
 }
 
 void
-PauseEvent()
+PauseEvent ()
 {
     if (appData.debugMode)
        fprintf(debugFP, "PauseEvent(): pausing %d\n", pausing);
@@ -13075,7 +13245,7 @@ PauseEvent()
 }
 
 void
-EditCommentEvent()
+EditCommentEvent ()
 {
     char title[MSG_SIZ];
 
@@ -13092,7 +13262,7 @@ EditCommentEvent()
 
 
 void
-EditTagsEvent()
+EditTagsEvent ()
 {
     char *tags = PGNTags(&gameInfo);
     bookUp = FALSE;
@@ -13101,7 +13271,7 @@ EditTagsEvent()
 }
 
 void
-AnalyzeModeEvent()
+AnalyzeModeEvent ()
 {
     if (appData.noChessProgram || gameMode == AnalyzeMode)
       return;
@@ -13129,7 +13299,7 @@ AnalyzeModeEvent()
 }
 
 void
-AnalyzeFileEvent()
+AnalyzeFileEvent ()
 {
     if (appData.noChessProgram || gameMode == AnalyzeFile)
       return;
@@ -13156,7 +13326,7 @@ AnalyzeFileEvent()
 }
 
 void
-MachineWhiteEvent()
+MachineWhiteEvent ()
 {
     char buf[MSG_SIZ];
     char *bookHit = NULL;
@@ -13196,7 +13366,7 @@ MachineWhiteEvent()
     pausing = FALSE;
     ModeHighlight();
     SetGameInfo();
-    snprintf(buf, MSG_SIZ, _("%s vs. %s"), gameInfo.white, gameInfo.black);
+    snprintf(buf, MSG_SIZ, "%s %s %s", gameInfo.white, _("vs."), gameInfo.black);
     DisplayTitle(buf);
     if (first.sendName) {
       snprintf(buf, MSG_SIZ, "name %s\n", gameInfo.black);
@@ -13237,7 +13407,7 @@ MachineWhiteEvent()
 }
 
 void
-MachineBlackEvent()
+MachineBlackEvent ()
 {
   char buf[MSG_SIZ];
   char *bookHit = NULL;
@@ -13273,7 +13443,7 @@ MachineBlackEvent()
     pausing = FALSE;
     ModeHighlight();
     SetGameInfo();
-    snprintf(buf, MSG_SIZ, _("%s vs. %s"), gameInfo.white, gameInfo.black);
+    snprintf(buf, MSG_SIZ, "%s %s %s", gameInfo.white, _("vs."), gameInfo.black);
     DisplayTitle(buf);
     if (first.sendName) {
       snprintf(buf, MSG_SIZ, "name %s\n", gameInfo.white);
@@ -13313,35 +13483,35 @@ MachineBlackEvent()
 
 
 void
-DisplayTwoMachinesTitle()
+DisplayTwoMachinesTitle ()
 {
     char buf[MSG_SIZ];
     if (appData.matchGames > 0) {
         if(appData.tourneyFile[0]) {
-         snprintf(buf, MSG_SIZ, _("%s vs. %s (%d/%d%s)"),
-                  gameInfo.white, gameInfo.black,
+         snprintf(buf, MSG_SIZ, "%s %s %s (%d/%d%s)",
+                  gameInfo.white, _("vs."), gameInfo.black,
                   nextGame+1, appData.matchGames+1,
                   appData.tourneyType>0 ? "gt" : appData.tourneyType<0 ? "sw" : "rr");
         } else 
         if (first.twoMachinesColor[0] == 'w') {
-         snprintf(buf, MSG_SIZ, _("%s vs. %s (%d-%d-%d)"),
-                  gameInfo.white, gameInfo.black,
+         snprintf(buf, MSG_SIZ, "%s %s %s (%d-%d-%d)",
+                  gameInfo.white, _("vs."),  gameInfo.black,
                   first.matchWins, second.matchWins,
                   matchGame - 1 - (first.matchWins + second.matchWins));
        } else {
-         snprintf(buf, MSG_SIZ, _("%s vs. %s (%d-%d-%d)"),
-                  gameInfo.white, gameInfo.black,
+         snprintf(buf, MSG_SIZ, "%s %s %s (%d-%d-%d)",
+                  gameInfo.white, _("vs."), gameInfo.black,
                   second.matchWins, first.matchWins,
                   matchGame - 1 - (first.matchWins + second.matchWins));
        }
     } else {
-      snprintf(buf, MSG_SIZ, _("%s vs. %s"), gameInfo.white, gameInfo.black);
+      snprintf(buf, MSG_SIZ, "%s %s %s", gameInfo.white, _("vs."), gameInfo.black);
     }
     DisplayTitle(buf);
 }
 
 void
-SettingsMenuIfReady()
+SettingsMenuIfReady ()
 {
   if (second.lastPing != second.lastPong) {
     DisplayMessage("", _("Waiting for second chess program"));
@@ -13354,7 +13524,7 @@ SettingsMenuIfReady()
 }
 
 int
-WaitForEngine(ChessProgramState *cps, DelayedEventCallback retry)
+WaitForEngine (ChessProgramState *cps, DelayedEventCallback retry)
 {
     char buf[MSG_SIZ];
     if (cps->pr == NoProc) {
@@ -13364,7 +13534,7 @@ WaitForEngine(ChessProgramState *cps, DelayedEventCallback retry)
        } else {
          /* kludge: allow timeout for initial "feature" command */
          FreezeUI();
-         snprintf(buf, MSG_SIZ, _("Starting %s chess program"), cps->which);
+         snprintf(buf, MSG_SIZ, _("Starting %s chess program"), _(cps->which));
          DisplayMessage("", buf);
          ScheduleDelayedEvent(retry, FEATURE_TIMEOUT);
        }
@@ -13386,6 +13556,11 @@ TwoMachinesEvent P((void))
 
     if (appData.noChessProgram) return;
 
+    if(second.protocolVersion >= 2 && !strstr(second.variants, VariantName(gameInfo.variant))) {
+       DisplayError("second engine does not play this", 0);
+       return;
+    }
+
     switch (gameMode) {
       case TwoMachinesPlay:
        return;
@@ -13439,6 +13614,7 @@ TwoMachinesEvent P((void))
        ScheduleDelayedEvent(TwoMachinesEventIfReady, appData.matchPause - wait);
        return;
     }
+    // we are now committed to starting the game
     stalling = 0;
     DisplayMessage("", "");
     if (startedFromSetupPosition) {
@@ -13511,7 +13687,7 @@ TwoMachinesEvent P((void))
 }
 
 void
-TrainingEvent()
+TrainingEvent ()
 {
     if (gameMode == Training) {
       SetTrainingModeOff();
@@ -13534,7 +13710,7 @@ TrainingEvent()
 }
 
 void
-IcsClientEvent()
+IcsClientEvent ()
 {
     if (!appData.icsActive) return;
     switch (gameMode) {
@@ -13568,9 +13744,8 @@ IcsClientEvent()
     return;
 }
 
-
 void
-EditGameEvent()
+EditGameEvent ()
 {
     int i;
 
@@ -13660,7 +13835,7 @@ EditGameEvent()
 
 
 void
-EditPositionEvent()
+EditPositionEvent ()
 {
     if (gameMode == EditPosition) {
        EditGameEvent();
@@ -13681,10 +13856,11 @@ EditPositionEvent()
     currentMove = forwardMostMove = backwardMostMove = 0;
     HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1);
     DisplayMove(-1);
+    if(!appData.pieceMenu) DisplayMessage(_("Click clock to clear board"), "");
 }
 
 void
-ExitAnalyzeMode()
+ExitAnalyzeMode ()
 {
     /* [DM] icsEngineAnalyze - possible call from other functions */
     if (appData.icsEngineAnalyze) {
@@ -13700,7 +13876,7 @@ ExitAnalyzeMode()
 }
 
 void
-EditPositionDone(Boolean fakeRights)
+EditPositionDone (Boolean fakeRights)
 {
     int king = gameInfo.variant == VariantKnightmate ? WhiteUnicorn : WhiteKing;
 
@@ -13743,8 +13919,7 @@ EditPositionDone(Boolean fakeRights)
 /* Pause for `ms' milliseconds */
 /* !! Ugh, this is a kludge. Fix it sometime. --tpm */
 void
-TimeDelay(ms)
-     long ms;
+TimeDelay (long ms)
 {
     TimeMark m1, m2;
 
@@ -13756,8 +13931,7 @@ TimeDelay(ms)
 
 /* !! Ugh, this is a kludge. Fix it sometime. --tpm */
 void
-SendMultiLineToICS(buf)
-     char *buf;
+SendMultiLineToICS (char *buf)
 {
     char temp[MSG_SIZ+1], *p;
     int len;
@@ -13782,7 +13956,7 @@ SendMultiLineToICS(buf)
 }
 
 void
-SetWhiteToPlayEvent()
+SetWhiteToPlayEvent ()
 {
     if (gameMode == EditPosition) {
        blackPlaysFirst = FALSE;
@@ -13794,7 +13968,7 @@ SetWhiteToPlayEvent()
 }
 
 void
-SetBlackToPlayEvent()
+SetBlackToPlayEvent ()
 {
     if (gameMode == EditPosition) {
        blackPlaysFirst = TRUE;
@@ -13808,9 +13982,7 @@ SetBlackToPlayEvent()
 }
 
 void
-EditPositionMenuEvent(selection, x, y)
-     ChessSquare selection;
-     int x, y;
+EditPositionMenuEvent (ChessSquare selection, int x, int y)
 {
     char buf[MSG_SIZ];
     ChessSquare piece = boards[0][y][x];
@@ -13931,6 +14103,8 @@ EditPositionMenuEvent(selection, x, y)
             } else
            boards[0][y][x] = selection;
            DrawPosition(TRUE, boards[0]);
+           ClearHighlights();
+           fromX = fromY = -1;
        }
        break;
     }
@@ -13938,9 +14112,7 @@ EditPositionMenuEvent(selection, x, y)
 
 
 void
-DropMenuEvent(selection, x, y)
-     ChessSquare selection;
-     int x, y;
+DropMenuEvent (ChessSquare selection, int x, int y)
 {
     ChessMove moveType;
 
@@ -13981,7 +14153,7 @@ DropMenuEvent(selection, x, y)
 }
 
 void
-AcceptEvent()
+AcceptEvent ()
 {
     /* Accept a pending offer of any kind from opponent */
 
@@ -14006,7 +14178,7 @@ AcceptEvent()
 }
 
 void
-DeclineEvent()
+DeclineEvent ()
 {
     /* Decline a pending offer of any kind from opponent */
 
@@ -14031,7 +14203,7 @@ DeclineEvent()
 }
 
 void
-RematchEvent()
+RematchEvent ()
 {
     /* Issue ICS rematch command */
     if (appData.icsActive) {
@@ -14041,7 +14213,7 @@ RematchEvent()
 }
 
 void
-CallFlagEvent()
+CallFlagEvent ()
 {
     /* Call your opponent's flag (claim a win on time) */
     if (appData.icsActive) {
@@ -14078,7 +14250,7 @@ CallFlagEvent()
 }
 
 void
-ClockClick(int which)
+ClockClick (int which)
 {      // [HGM] code moved to back-end from winboard.c
        if(which) { // black clock
          if (gameMode == EditPosition || gameMode == IcsExamining) {
@@ -14108,7 +14280,7 @@ ClockClick(int which)
 }
 
 void
-DrawEvent()
+DrawEvent ()
 {
     /* Offer draw or accept pending draw offer from opponent */
 
@@ -14150,7 +14322,7 @@ DrawEvent()
 }
 
 void
-AdjournEvent()
+AdjournEvent ()
 {
     /* Offer Adjourn or accept pending Adjourn offer from opponent */
 
@@ -14164,7 +14336,7 @@ AdjournEvent()
 
 
 void
-AbortEvent()
+AbortEvent ()
 {
     /* Offer Abort or accept pending Abort offer from opponent */
 
@@ -14177,7 +14349,7 @@ AbortEvent()
 }
 
 void
-ResignEvent()
+ResignEvent ()
 {
     /* Resign.  You can do this even if it's not your turn. */
 
@@ -14211,7 +14383,7 @@ ResignEvent()
 
 
 void
-StopObservingEvent()
+StopObservingEvent ()
 {
     /* Stop observing current games */
     SendToICS(ics_prefix);
@@ -14219,7 +14391,7 @@ StopObservingEvent()
 }
 
 void
-StopExaminingEvent()
+StopExaminingEvent ()
 {
     /* Stop observing current game */
     SendToICS(ics_prefix);
@@ -14227,10 +14399,9 @@ StopExaminingEvent()
 }
 
 void
-ForwardInner(target)
-     int target;
+ForwardInner (int target)
 {
-    int limit;
+    int limit; int oldSeekGraphUp = seekGraphUp;
 
     if (appData.debugMode)
        fprintf(debugFP, "ForwardInner(%d), current %d, forward %d\n",
@@ -14239,6 +14410,7 @@ ForwardInner(target)
     if (gameMode == EditPosition)
       return;
 
+    seekGraphUp = FALSE;
     MarkTargetSquares(1);
 
     if (gameMode == PlayFromGameFile && !pausing)
@@ -14286,16 +14458,17 @@ ForwardInner(target)
     }
     DisplayBothClocks();
     DisplayMove(currentMove - 1);
-    DrawPosition(FALSE, boards[currentMove]);
+    DrawPosition(oldSeekGraphUp, boards[currentMove]);
     HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1);
     if ( !matchMode && gameMode != Training) { // [HGM] PV info: routine tests if empty
        DisplayComment(currentMove - 1, commentList[currentMove]);
     }
+    ClearMap(); // [HGM] exclude: invalidate map
 }
 
 
 void
-ForwardEvent()
+ForwardEvent ()
 {
     if (gameMode == IcsExamining && !pausing) {
         SendToICS(ics_prefix);
@@ -14306,7 +14479,7 @@ ForwardEvent()
 }
 
 void
-ToEndEvent()
+ToEndEvent ()
 {
     if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
        /* to optimze, we temporarily turn off analysis mode while we feed
@@ -14336,8 +14509,7 @@ ToEndEvent()
 }
 
 void
-BackwardInner(target)
-     int target;
+BackwardInner (int target)
 {
     int full_redraw = TRUE; /* [AS] Was FALSE, had to change it! */
 
@@ -14346,6 +14518,7 @@ BackwardInner(target)
                target, currentMove, forwardMostMove);
 
     if (gameMode == EditPosition) return;
+    seekGraphUp = FALSE;
     MarkTargetSquares(1);
     if (currentMove <= backwardMostMove) {
        ClearHighlights();
@@ -14404,10 +14577,11 @@ BackwardInner(target)
     HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1);
     // [HGM] PV info: routine tests if comment empty
     DisplayComment(currentMove - 1, commentList[currentMove]);
+    ClearMap(); // [HGM] exclude: invalidate map
 }
 
 void
-BackwardEvent()
+BackwardEvent ()
 {
     if (gameMode == IcsExamining && !pausing) {
         SendToICS(ics_prefix);
@@ -14418,7 +14592,7 @@ BackwardEvent()
 }
 
 void
-ToStartEvent()
+ToStartEvent ()
 {
     if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
        /* to optimize, we temporarily turn off analysis mode while we undo
@@ -14447,7 +14621,7 @@ ToStartEvent()
 }
 
 void
-ToNrEvent(int to)
+ToNrEvent (int to)
 {
   if (gameMode == PlayFromGameFile && !pausing) PauseEvent();
   if (to >= forwardMostMove) to = forwardMostMove;
@@ -14460,7 +14634,7 @@ ToNrEvent(int to)
 }
 
 void
-RevertEvent(Boolean annotate)
+RevertEvent (Boolean annotate)
 {
     if(PopTail(annotate)) { // [HGM] vari: restore old game tail
        return;
@@ -14478,7 +14652,7 @@ RevertEvent(Boolean annotate)
 }
 
 void
-RetractMoveEvent()
+RetractMoveEvent ()
 {
     switch (gameMode) {
       case MachinePlaysWhite:
@@ -14517,7 +14691,7 @@ RetractMoveEvent()
 }
 
 void
-MoveNowEvent()
+MoveNowEvent ()
 {
     ChessProgramState *cps;
 
@@ -14552,7 +14726,7 @@ MoveNowEvent()
 }
 
 void
-TruncateGameEvent()
+TruncateGameEvent ()
 {
     EditGameEvent();
     if (gameMode != EditGame) return;
@@ -14560,7 +14734,7 @@ TruncateGameEvent()
 }
 
 void
-TruncateGame()
+TruncateGame ()
 {
     CleanupTail(); // [HGM] vari: only keep current variation if we explicitly truncate
     if (forwardMostMove > currentMove) {
@@ -14576,7 +14750,7 @@ TruncateGame()
 }
 
 void
-HintEvent()
+HintEvent ()
 {
     if (appData.noChessProgram) return;
     switch (gameMode) {
@@ -14602,7 +14776,7 @@ HintEvent()
 }
 
 void
-BookEvent()
+BookEvent ()
 {
     if (appData.noChessProgram) return;
     switch (gameMode) {
@@ -14633,7 +14807,7 @@ BookEvent()
 }
 
 void
-AboutGameEvent()
+AboutGameEvent ()
 {
     char *tags = PGNTags(&gameInfo);
     TagsPopUp(tags, CmailMsg());
@@ -14643,9 +14817,7 @@ AboutGameEvent()
 /* end button procedures */
 
 void
-PrintPosition(fp, move)
-     FILE *fp;
-     int move;
+PrintPosition (FILE *fp, int move)
 {
     int i, j;
 
@@ -14663,8 +14835,7 @@ PrintPosition(fp, move)
 }
 
 void
-PrintOpponents(fp)
-     FILE *fp;
+PrintOpponents (FILE *fp)
 {
     if (gameInfo.white != NULL) {
        fprintf(fp, "\t%s vs. %s\n", gameInfo.white, gameInfo.black);
@@ -14675,10 +14846,9 @@ PrintOpponents(fp)
 
 /* Find last component of program's own name, using some heuristics */
 void
-TidyProgramName(prog, host, buf)
-     char *prog, *host, buf[MSG_SIZ];
+TidyProgramName (char *prog, char *host, char buf[MSG_SIZ])
 {
-    char *p, *q;
+    char *p, *q, c;
     int local = (strcmp(host, "localhost") == 0);
     while (!local && (p = strchr(prog, ';')) != NULL) {
        p++;
@@ -14695,7 +14865,8 @@ TidyProgramName(prog, host, buf)
     while (p >= prog && *p != '/' && *p != '\\') p--;
     p++;
     if(p == prog && *p == '"') p++;
-    if (q - p >= 4 && StrCaseCmp(q - 4, ".exe") == 0) q -= 4;
+    c = *q; *q = 0;
+    if (q - p >= 4 && StrCaseCmp(q - 4, ".exe") == 0) *q = c, q -= 4; else *q = c;
     memcpy(buf, p, q - p);
     buf[q - p] = NULLCHAR;
     if (!local) {
@@ -14705,7 +14876,7 @@ TidyProgramName(prog, host, buf)
 }
 
 char *
-TimeControlTagValue()
+TimeControlTagValue ()
 {
     char buf[MSG_SIZ];
     if (!appData.clockMode) {
@@ -14721,7 +14892,7 @@ TimeControlTagValue()
 }
 
 void
-SetGameInfo()
+SetGameInfo ()
 {
     /* This routine is used only for certain modes */
     VariantClass v = gameInfo.variant;
@@ -14819,9 +14990,7 @@ SetGameInfo()
 }
 
 void
-ReplaceComment(index, text)
-     int index;
-     char *text;
+ReplaceComment (int index, char *text)
 {
     int len;
     char *p;
@@ -14862,8 +15031,7 @@ ReplaceComment(index, text)
 }
 
 void
-CrushCRs(text)
-     char *text;
+CrushCRs (char *text)
 {
   char *p = text;
   char *q = text;
@@ -14877,10 +15045,8 @@ CrushCRs(text)
 }
 
 void
-AppendComment(index, text, addBraces)
-     int index;
-     char *text;
-     Boolean addBraces; // [HGM] braces: tells if we should add {}
+AppendComment (int index, char *text, Boolean addBraces)
+/* addBraces  tells if we should add {} */
 {
     int oldlen, len;
     char *old;
@@ -14892,6 +15058,7 @@ if(appData.debugMode) fprintf(debugFP, "Append: in='%s' %d\n", text, addBraces);
     while (*text == '\n') text++;
     len = strlen(text);
     while (len > 0 && text[len - 1] == '\n') len--;
+    text[len] = NULLCHAR;
 
     if (len == 0) return;
 
@@ -14926,7 +15093,8 @@ if(appData.debugMode) fprintf(debugFP, "Append: in='%s' %d\n", text, addBraces);
     }
 }
 
-static char * FindStr( char * text, char * sub_text )
+static char *
+FindStr (char * text, char * sub_text)
 {
     char * result = strstr( text, sub_text );
 
@@ -14939,7 +15107,8 @@ static char * FindStr( char * text, char * sub_text )
 
 /* [AS] Try to extract PV info from PGN comment */
 /* [HGM] PV time: and then remove it, to prevent it appearing twice */
-char *GetInfoFromComment( int index, char * text )
+char *
+GetInfoFromComment (int index, char * text)
 {
     char * sep = text, *p;
 
@@ -15034,9 +15203,7 @@ char *GetInfoFromComment( int index, char * text )
 }
 
 void
-SendToProgram(message, cps)
-     char *message;
-     ChessProgramState *cps;
+SendToProgram (char *message, ChessProgramState *cps)
 {
     int count, outCount, error;
     char buf[MSG_SIZ];
@@ -15050,6 +15217,10 @@ SendToProgram(message, cps)
        fprintf(debugFP, "%ld >%-6s: %s",
                SubtractTimeMarks(&now, &programStartTime),
                cps->which, message);
+       if(serverFP)
+           fprintf(serverFP, "%ld >%-6s: %s",
+               SubtractTimeMarks(&now, &programStartTime),
+               cps->which, message), fflush(serverFP);
     }
 
     count = strlen(message);
@@ -15076,12 +15247,7 @@ SendToProgram(message, cps)
 }
 
 void
-ReceiveFromProgram(isr, closure, message, count, error)
-     InputSourceRef isr;
-     VOIDSTAR closure;
-     char *message;
-     int count;
-     int error;
+ReceiveFromProgram (InputSourceRef isr, VOIDSTAR closure, char *message, int count, int error)
 {
     char *end_str;
     char buf[MSG_SIZ];
@@ -15156,6 +15322,11 @@ ReceiveFromProgram(isr, closure, message, count, error)
                        SubtractTimeMarks(&now, &programStartTime), cps->which,
                        quote,
                        message);
+               if(serverFP)
+                   fprintf(serverFP, "%ld <%-6s: %s%s\n",
+                       SubtractTimeMarks(&now, &programStartTime), cps->which,
+                       quote,
+                       message), fflush(serverFP);
        }
     }
 
@@ -15171,10 +15342,7 @@ ReceiveFromProgram(isr, closure, message, count, error)
 
 
 void
-SendTimeControl(cps, mps, tc, inc, sd, st)
-     ChessProgramState *cps;
-     int mps, inc, sd, st;
-     long tc;
+SendTimeControl (ChessProgramState *cps, int mps, long tc, int inc, int sd, int st)
 {
     char buf[MSG_SIZ];
     int seconds;
@@ -15238,7 +15406,8 @@ SendTimeControl(cps, mps, tc, inc, sd, st)
     }
 }
 
-ChessProgramState *WhitePlayer()
+ChessProgramState *
+WhitePlayer ()
 /* [HGM] return pointer to 'first' or 'second', depending on who plays white */
 {
     if(gameMode == TwoMachinesPlay && first.twoMachinesColor[0] == 'b' ||
@@ -15248,9 +15417,7 @@ ChessProgramState *WhitePlayer()
 }
 
 void
-SendTimeRemaining(cps, machineWhite)
-     ChessProgramState *cps;
-     int /*boolean*/ machineWhite;
+SendTimeRemaining (ChessProgramState *cps, int machineWhite)
 {
     char message[MSG_SIZ];
     long time, otime;
@@ -15268,9 +15435,6 @@ SendTimeRemaining(cps, machineWhite)
     }
     /* [HGM] translate opponent's time by time-odds factor */
     otime = (otime * cps->other->timeOdds) / cps->timeOdds;
-    if (appData.debugMode) {
-        fprintf(debugFP, "time odds: %f %f \n", cps->timeOdds, cps->other->timeOdds);
-    }
 
     if (time <= 0) time = 1;
     if (otime <= 0) otime = 1;
@@ -15283,11 +15447,7 @@ SendTimeRemaining(cps, machineWhite)
 }
 
 int
-BoolFeature(p, name, loc, cps)
-     char **p;
-     char *name;
-     int *loc;
-     ChessProgramState *cps;
+BoolFeature (char **p, char *name, int *loc, ChessProgramState *cps)
 {
   char buf[MSG_SIZ];
   int len = strlen(name);
@@ -15307,11 +15467,7 @@ BoolFeature(p, name, loc, cps)
 }
 
 int
-IntFeature(p, name, loc, cps)
-     char **p;
-     char *name;
-     int *loc;
-     ChessProgramState *cps;
+IntFeature (char **p, char *name, int *loc, ChessProgramState *cps)
 {
   char buf[MSG_SIZ];
   int len = strlen(name);
@@ -15327,11 +15483,7 @@ IntFeature(p, name, loc, cps)
 }
 
 int
-StringFeature(p, name, loc, cps)
-     char **p;
-     char *name;
-     char loc[];
-     ChessProgramState *cps;
+StringFeature (char **p, char *name, char loc[], ChessProgramState *cps)
 {
   char buf[MSG_SIZ];
   int len = strlen(name);
@@ -15349,7 +15501,7 @@ StringFeature(p, name, loc, cps)
 }
 
 int
-ParseOption(Option *opt, ChessProgramState *cps)
+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
 {
@@ -15390,8 +15542,8 @@ ParseOption(Option *opt, ChessProgramState *cps)
            if(sscanf(p, " -check %d", &def) < 1) return FALSE;
            opt->value = (def != 0);
            opt->type = CheckBox;
-       } else if(p = strstr(opt->name, " -combo ")) {
-           opt->textValue = (char*) (&cps->comboList[cps->comboCnt]); // cheat with pointer type
+       } else if(p = strstr(opt->name, " -combo ")) {
+           opt->textValue = (char*) (opt->choice = &cps->comboList[cps->comboCnt]); // cheat with pointer type
            cps->comboList[cps->comboCnt++] = q = p+8; // holds possible choices
            if(*q == '*') cps->comboList[cps->comboCnt-1]++;
            opt->value = n = 0;
@@ -15440,9 +15592,7 @@ ParseOption(Option *opt, ChessProgramState *cps)
 }
 
 void
-FeatureDone(cps, val)
-     ChessProgramState* cps;
-     int val;
+FeatureDone (ChessProgramState *cps, int val)
 {
   DelayedEventCallback cb = GetDelayedEvent();
   if ((cb == InitBackEnd3 && cps == &first) ||
@@ -15457,9 +15607,7 @@ FeatureDone(cps, val)
 
 /* Parse feature command from engine */
 void
-ParseFeatures(args, cps)
-     char* args;
-     ChessProgramState *cps;
+ParseFeatures (char *args, ChessProgramState *cps)
 {
   char *p = args;
   char *q;
@@ -15482,7 +15630,7 @@ ParseFeatures(args, cps)
       continue;
     }
     if (BoolFeature(&p, "analyze", &cps->analysisSupport, cps)) continue;
-    if (StringFeature(&p, "myname", &cps->tidy, cps)) {
+    if (StringFeature(&p, "myname", cps->tidy, cps)) {
       if (gameMode == TwoMachinesPlay) {
        DisplayTwoMachinesTitle();
       } else {
@@ -15490,12 +15638,13 @@ ParseFeatures(args, cps)
       }
       continue;
     }
-    if (StringFeature(&p, "variants", &cps->variants, cps)) continue;
+    if (StringFeature(&p, "variants", cps->variants, cps)) continue;
     if (BoolFeature(&p, "san", &cps->useSAN, cps)) continue;
     if (BoolFeature(&p, "ping", &cps->usePing, cps)) continue;
     if (BoolFeature(&p, "playother", &cps->usePlayother, cps)) continue;
     if (BoolFeature(&p, "colors", &cps->useColors, cps)) continue;
     if (BoolFeature(&p, "usermove", &cps->useUsermove, cps)) continue;
+    if (BoolFeature(&p, "exclude", &cps->excludeMoves, cps)) continue;
     if (BoolFeature(&p, "ics", &cps->sendICS, cps)) continue;
     if (BoolFeature(&p, "name", &cps->sendName, cps)) continue;
     if (BoolFeature(&p, "pause", &val, cps)) continue; /* unused at present */
@@ -15514,8 +15663,11 @@ ParseFeatures(args, cps)
     if (IntFeature(&p, "level", &cps->maxNrOfSessions, cps)) continue;
     if (BoolFeature(&p, "memory", &cps->memSize, cps)) continue;
     if (BoolFeature(&p, "smp", &cps->maxCores, cps)) continue;
-    if (StringFeature(&p, "egt", &cps->egtFormats, cps)) continue;
-    if (StringFeature(&p, "option", &(cps->option[cps->nrOptions].name), cps)) {
+    if (StringFeature(&p, "egt", cps->egtFormats, cps)) continue;
+    if (StringFeature(&p, "option", buf, cps)) {
+       FREE(cps->option[cps->nrOptions].name);
+       cps->option[cps->nrOptions].name = malloc(MSG_SIZ);
+       safeStrCpy(cps->option[cps->nrOptions].name, buf, MSG_SIZ);
        if(!ParseOption(&(cps->option[cps->nrOptions++]), cps)) { // [HGM] options: add option feature
          snprintf(buf, MSG_SIZ, "rejected option %s\n", cps->option[--cps->nrOptions].name);
            SendToProgram(buf, cps);
@@ -15551,8 +15703,7 @@ ParseFeatures(args, cps)
 }
 
 void
-PeriodicUpdatesEvent(newState)
-     int newState;
+PeriodicUpdatesEvent (int newState)
 {
     if (newState == appData.periodicUpdates)
       return;
@@ -15570,8 +15721,7 @@ PeriodicUpdatesEvent(newState)
 }
 
 void
-PonderNextMoveEvent(newState)
-     int newState;
+PonderNextMoveEvent (int newState)
 {
     if (newState == appData.ponderNextMove) return;
     if (gameMode == EditPosition) EditPositionDone(TRUE);
@@ -15591,9 +15741,7 @@ PonderNextMoveEvent(newState)
 }
 
 void
-NewSettingEvent(option, feature, command, value)
-     char *command;
-     int option, value, *feature;
+NewSettingEvent (int option, int *feature, char *command, int value)
 {
     char buf[MSG_SIZ];
 
@@ -15606,7 +15754,7 @@ NewSettingEvent(option, feature, command, value)
 }
 
 void
-ShowThinkingEvent()
+ShowThinkingEvent ()
 // [HGM] thinking: this routine is now also called from "Options -> Engine..." popup
 {
     static int oldState = 2; // kludge alert! Neither true nor fals, so first time oldState is always updated
@@ -15633,8 +15781,7 @@ ShowThinkingEvent()
 }
 
 void
-AskQuestionEvent(title, question, replyPrefix, which)
-     char *title; char *question; char *replyPrefix; char *which;
+AskQuestionEvent (char *title, char *question, char *replyPrefix, char *which)
 {
   ProcRef pr = (which[0] == '1') ? first.pr : second.pr;
   if (pr == NoProc) return;
@@ -15642,7 +15789,7 @@ AskQuestionEvent(title, question, replyPrefix, which)
 }
 
 void
-TypeInEvent(char firstChar)
+TypeInEvent (char firstChar)
 {
     if ((gameMode == BeginningOfGame && !appData.icsActive) || 
         gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack ||
@@ -15656,7 +15803,7 @@ TypeInEvent(char firstChar)
 }
 
 void
-TypeInDoneEvent(char *move)
+TypeInDoneEvent (char *move)
 {
        Board board;
        int n, fromX, fromY, toX, toY;
@@ -15673,6 +15820,14 @@ TypeInDoneEvent(char *move)
          ToNrEvent(2*n-1);
          return;
        }
+       // undocumented kludge: allow command-line option to be typed in!
+       // (potentially fatal, and does not implement the effect of the option.)
+       // should only be used for options that are values on which future decisions will be made,
+       // and definitely not on options that would be used during initialization.
+       if(strstr(move, "!!! -") == move) {
+           ParseArgsFromString(move+4);
+           return;
+        }
 
       if (gameMode != EditGame && currentMove != forwardMostMove && 
        gameMode != Training) {
@@ -15691,8 +15846,7 @@ TypeInDoneEvent(char *move)
 }
 
 void
-DisplayMove(moveNumber)
-     int moveNumber;
+DisplayMove (int moveNumber)
 {
     char message[MSG_SIZ];
     char res[MSG_SIZ];
@@ -15749,9 +15903,7 @@ DisplayMove(moveNumber)
 }
 
 void
-DisplayComment(moveNumber, text)
-     int moveNumber;
-     char *text;
+DisplayComment (int moveNumber, char *text)
 {
     char title[MSG_SIZ];
 
@@ -15773,8 +15925,7 @@ DisplayComment(moveNumber, text)
  * ioctl, which does not work properly on some flavors of Unix.
  */
 void
-Attention(cps)
-     ChessProgramState *cps;
+Attention (ChessProgramState *cps)
 {
 #if ATTENTION
     if (!cps->useSigint) return;
@@ -15801,7 +15952,7 @@ Attention(cps)
 }
 
 int
-CheckFlags()
+CheckFlags ()
 {
     if (whiteTimeRemaining <= 0) {
        if (!whiteFlag) {
@@ -15851,7 +16002,7 @@ CheckFlags()
 }
 
 void
-CheckTimeControl()
+CheckTimeControl ()
 {
     if (!appData.clockMode || appData.icsActive || searchTime || // [HGM] st: no inc in st mode
        gameMode == PlayFromGameFile || forwardMostMove == 0) return;
@@ -15876,7 +16027,7 @@ CheckTimeControl()
 }
 
 void
-DisplayBothClocks()
+DisplayBothClocks ()
 {
     int wom = gameMode == EditPosition ?
       !blackPlaysFirst : WhiteOnMove(currentMove);
@@ -15898,8 +16049,7 @@ DisplayBothClocks()
 
 /* Get the current time as a TimeMark */
 void
-GetTimeMark(tm)
-     TimeMark *tm;
+GetTimeMark (TimeMark *tm)
 {
 #if HAVE_GETTIMEOFDAY
 
@@ -15931,8 +16081,7 @@ GetTimeMark(tm)
    time marks.  We assume the difference will fit in a long!
 */
 long
-SubtractTimeMarks(tm2, tm1)
-     TimeMark *tm2, *tm1;
+SubtractTimeMarks (TimeMark *tm2, TimeMark *tm1)
 {
     return 1000L*(tm2->sec - tm1->sec) +
            (long) (tm2->ms - tm1->ms);
@@ -15953,8 +16102,7 @@ static TimeMark tickStartTM;
 static long intendedTickLength;
 
 long
-NextTickLength(timeRemaining)
-     long timeRemaining;
+NextTickLength (long timeRemaining)
 {
     long nominalTickLength, nextTickLength;
 
@@ -15970,7 +16118,7 @@ NextTickLength(timeRemaining)
 
 /* Adjust clock one minute up or down */
 void
-AdjustClock(Boolean which, int dir)
+AdjustClock (Boolean which, int dir)
 {
     if(appData.autoCallFlag) { DisplayError(_("Clock adjustment not allowed in auto-flag mode"), 0); return; }
     if(which) blackTimeRemaining += 60000*dir;
@@ -15981,7 +16129,7 @@ AdjustClock(Boolean which, int dir)
 
 /* Stop clocks and reset to a fresh time control */
 void
-ResetClocks()
+ResetClocks ()
 {
     (void) StopClockTimer();
     if (appData.icsActive) {
@@ -16007,7 +16155,7 @@ ResetClocks()
 
 /* Decrement running clock by amount of time that has passed */
 void
-DecrementClocks()
+DecrementClocks ()
 {
     long timeRemaining;
     long lastTickLength, fudge;
@@ -16087,7 +16235,7 @@ DecrementClocks()
    from the color that is *not* on move now.
 */
 void
-SwitchClocks(int newMoveNr)
+SwitchClocks (int newMoveNr)
 {
     long lastTickLength;
     TimeMark now;
@@ -16150,7 +16298,7 @@ SwitchClocks(int newMoveNr)
 
 /* Stop both clocks */
 void
-StopClocks()
+StopClocks ()
 {
     long lastTickLength;
     TimeMark now;
@@ -16176,7 +16324,7 @@ StopClocks()
 /* Start clock of player on move.  Time may have been reset, so
    if clock is already running, stop and restart it. */
 void
-StartClocks()
+StartClocks ()
 {
     (void) StopClockTimer(); /* in case it was running already */
     DisplayBothClocks();
@@ -16207,8 +16355,7 @@ StartClocks()
 }
 
 char *
-TimeString(ms)
-     long ms;
+TimeString (long ms)
 {
     long second, minute, hour, day;
     char *sign = "";
@@ -16255,8 +16402,7 @@ TimeString(ms)
  * This is necessary because some C libraries aren't ANSI C compliant yet.
  */
 char *
-StrStr(string, match)
-     char *string, *match;
+StrStr (char *string, char *match)
 {
     int i, length;
 
@@ -16270,8 +16416,7 @@ StrStr(string, match)
 }
 
 char *
-StrCaseStr(string, match)
-     char *string, *match;
+StrCaseStr (char *string, char *match)
 {
     int i, j, length;
 
@@ -16290,8 +16435,7 @@ StrCaseStr(string, match)
 
 #ifndef _amigados
 int
-StrCaseCmp(s1, s2)
-     char *s1, *s2;
+StrCaseCmp (char *s1, char *s2)
 {
     char c1, c2;
 
@@ -16306,24 +16450,21 @@ StrCaseCmp(s1, s2)
 
 
 int
-ToLower(c)
-     int c;
+ToLower (int c)
 {
     return isupper(c) ? tolower(c) : c;
 }
 
 
 int
-ToUpper(c)
-     int c;
+ToUpper (int c)
 {
     return islower(c) ? toupper(c) : c;
 }
 #endif /* !_amigados   */
 
 char *
-StrSave(s)
-     char *s;
+StrSave (char *s)
 {
   char *ret;
 
@@ -16335,8 +16476,7 @@ StrSave(s)
 }
 
 char *
-StrSavePtr(s, savePtr)
-     char *s, **savePtr;
+StrSavePtr (char *s, char **savePtr)
 {
     if (*savePtr) {
        free(*savePtr);
@@ -16348,7 +16488,7 @@ StrSavePtr(s, savePtr)
 }
 
 char *
-PGNDate()
+PGNDate ()
 {
     time_t clock;
     struct tm *tm;
@@ -16363,9 +16503,7 @@ PGNDate()
 
 
 char *
-PositionToFEN(move, overrideCastling)
-     int move;
-     char *overrideCastling;
+PositionToFEN (int move, char *overrideCastling)
 {
     int i, j, fromX, fromY, toX, toY;
     int whiteToPlay;
@@ -16533,10 +16671,7 @@ PositionToFEN(move, overrideCastling)
 }
 
 Boolean
-ParseFEN(board, blackPlaysFirst, fen)
-    Board board;
-     int *blackPlaysFirst;
-     char *fen;
+ParseFEN (Board board, int *blackPlaysFirst, char *fen)
 {
     int i, j;
     char *p, c;
@@ -16776,7 +16911,7 @@ ParseFEN(board, blackPlaysFirst, fen)
 }
 
 void
-EditPositionPasteFEN(char *fen)
+EditPositionPasteFEN (char *fen)
 {
   if (fen != NULL) {
     Board initial_position;
@@ -16799,7 +16934,8 @@ EditPositionPasteFEN(char *fen)
 
 static char cseq[12] = "\\   ";
 
-Boolean set_cont_sequence(char *new_seq)
+Boolean
+set_cont_sequence (char *new_seq)
 {
     int len;
     Boolean ret;
@@ -16824,7 +16960,8 @@ Boolean set_cont_sequence(char *new_seq)
     for the dest buffer.  lp argument indicats line position upon entry, and it's
     passed back upon exit.
 */
-int wrap(char *dest, char *src, int count, int width, int *lp)
+int
+wrap (char *dest, char *src, int count, int width, int *lp)
 {
     int len, i, ansi, cseq_len, line, old_line, old_i, old_len, clen;
 
@@ -16908,7 +17045,7 @@ int wrap(char *dest, char *src, int count, int width, int *lp)
 Boolean modeRestore = FALSE;
 
 void
-PushInner(int firstMove, int lastMove)
+PushInner (int firstMove, int lastMove)
 {
        int i, j, nrMoves = lastMove - firstMove;
 
@@ -16939,7 +17076,7 @@ PushInner(int firstMove, int lastMove)
 }
 
 void
-PushTail(int firstMove, int lastMove)
+PushTail (int firstMove, int lastMove)
 {
        if(appData.icsActive) { // only in local mode
                forwardMostMove = currentMove; // mimic old ICS behavior
@@ -16953,7 +17090,7 @@ PushTail(int firstMove, int lastMove)
 }
 
 void
-PopInner(Boolean annotate)
+PopInner (Boolean annotate)
 {
        int i, j, nrMoves;
        char buf[8000], moveBuf[20];
@@ -17000,7 +17137,7 @@ PopInner(Boolean annotate)
 }
 
 Boolean
-PopTail(Boolean annotate)
+PopTail (Boolean annotate)
 {
        if(appData.icsActive) return FALSE; // only in local mode
        if(!storedGames) return FALSE; // sanity
@@ -17015,7 +17152,7 @@ PopTail(Boolean annotate)
 }
 
 void
-CleanupTail()
+CleanupTail ()
 {      // remove all shelved variations
        int i;
        for(i=0; i<storedGames; i++) {
@@ -17032,7 +17169,7 @@ CleanupTail()
 }
 
 void
-LoadVariation(int index, char *text)
+LoadVariation (int index, char *text)
 {       // [HGM] vari: shelve previous line and load new variation, parsed from text around text[index]
        char *p = text, *start = NULL, *end = NULL, wait = NULLCHAR;
        int level = 0, move;