From a83e12aca9f45c3dc2657feeed6b2d88040219d8 Mon Sep 17 00:00:00 2001 From: H.G.Muller Date: Thu, 14 Jan 2016 16:49:34 +0100 Subject: [PATCH] Fix spurious undo at game start For ping-supporting engines the logic in handling unexpected moves is completely changed. Such moves can occur when an engine think is interrupted by a 'force' command, which in many engines is only processed after the think completes naturally with a move, and could cross such a move anyway in engines that would abort the search promptly. If the 'force' is the result of the user switching to EditGame mode, such a move should be undone, if it occurs at game end or start, the moves can be ignored, as the following 'new' will erase all memory of them. So in EditGameEvent, if the engine was thinking, a flag is set to indicate its upcoming move should be undone, and ping is sent after 'force'. The 'pong' response would arrive after the move (if any), and clears the flag. In all other cases of ping imbalance, incoming moves are ignored. While waiting for a pong after EditGameEvent the user interface is frozen, and a message is displayed to keep the user quiet. --- backend.c | 42 ++++++++++++++++++++++++++++-------------- 1 files changed, 28 insertions(+), 14 deletions(-) diff --git a/backend.c b/backend.c index 233fb8d..174b2a2 100644 --- a/backend.c +++ b/backend.c @@ -8551,7 +8551,7 @@ DeferredBookMove (void) static int savedWhitePlayer, savedBlackPlayer, pairingReceived; static ChessProgramState *stalledEngine; -static char stashedInputMove[MSG_SIZ]; +static char stashedInputMove[MSG_SIZ], abortEngineThink; void HandleMachineMove (char *message, ChessProgramState *cps) @@ -8634,24 +8634,27 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h return; } + if(cps->usePing) { + /* This method is only useful on engines that support ping */ + if(abortEngineThink) { + if (appData.debugMode) { + fprintf(debugFP, "Undoing move from aborted think of %s\n", cps->which); + } + SendToProgram("undo\n", cps); + return; + } + if (cps->lastPing != cps->lastPong) { - if (gameMode == BeginningOfGame) { /* Extra move from before last new; ignore */ if (appData.debugMode) { fprintf(debugFP, "Ignoring extra move from %s\n", cps->which); } - } else { - if (appData.debugMode) { - fprintf(debugFP, "Undoing extra move from %s, gameMode %d\n", - cps->which, gameMode); - } - - SendToProgram("undo\n", cps); - } return; } + } else { + switch (gameMode) { case BeginningOfGame: /* Extra move from before last reset; ignore */ @@ -8697,6 +8700,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } return; } + } if(cps->alphaRank) AlphaRank(machineMove, 4); @@ -9115,6 +9119,11 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } initPing = -1; } + if(cps->lastPing == cps->lastPong && abortEngineThink) { + abortEngineThink = FALSE; + DisplayMessage("", ""); + ThawUI(); + } return; } if(!strncmp(message, "highlight ", 10)) { @@ -14974,10 +14983,15 @@ EditGameEvent () case MachinePlaysBlack: case BeginningOfGame: SendToProgram("force\n", &first); - if (first.usePing) { // [HGM] always send ping when we might interrupt machine thinking - char buf[MSG_SIZ]; - snprintf(buf, MSG_SIZ, "ping %d\n", initPing = ++first.lastPing); - SendToProgram(buf, &first); + if(gameMode == (forwardMostMove & 1 ? MachinePlaysBlack : MachinePlaysWhite)) { // engine is thinking + if (first.usePing) { // [HGM] always send ping when we might interrupt machine thinking + char buf[MSG_SIZ]; + abortEngineThink = TRUE; + snprintf(buf, MSG_SIZ, "ping %d\n", initPing = ++first.lastPing); + SendToProgram(buf, &first); + DisplayMessage("Aborting engine think", ""); + FreezeUI(); + } } SetUserThinkingEnables(); break; -- 1.7.0.4