Continue search on ponder hit
authorH.G.Muller <hgm@hgm-xboard.(none)>
Thu, 6 Mar 2014 16:43:19 +0000 (17:43 +0100)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Thu, 6 Mar 2014 23:11:17 +0000 (00:11 +0100)
The usermove command is now examined during ponder search, commparing
the move with the hint move (stored in a new static variable for the
purpose). If there is a ponder hit, the ponder search, which was started
in BACKGROUND_MODE, is switched to FOREGROUND_MODE, and a ResponseTime
is calculated, so that it will pay attention to the clock, and play
a move once it times out. This is recognized by setting the hint-move
text to "hit", which then suppresses retraction of the hint move.
 The if-statement at the top of InputMove is now turned into a 'while',
so that a move produced after a ponder hit will immediately be followed
by pondering over the next move. A ponder miss (or non-move command)
will terminate this loop, through backlogging the command (as will
a failure to produce a hint move).
 The way the thinking time is calculated after a ponder hit might
have to be revised. For now SetTimeControl is called after a ponder hit
when the computer has zero moves left.

gnushogi/commondsp.c
gnushogi/gnushogi.h
gnushogi/search.c
gnushogi/tcontrl.c

index 1790e5f..4c6dfa4 100644 (file)
@@ -1618,8 +1618,8 @@ InputCommand(char *command, int root)
 #endif
     short ok, done, is_move = false;
     unsigned short mv;
-    char s[200], sx[200];
-    static char backlog[200];
+    char s[200], sx[200], s2[200];
+    static char backlog[200], ponderString[20];
 
     ok = flag.quit = done = false;
     player = opponent;
@@ -1629,7 +1629,7 @@ InputCommand(char *command, int root)
         ZeroTTable();
 #endif
 
-    if ((hint > 0) && !flag.easy && !flag.force && !command && !backlog[0] && root)
+    while ((hint > 0) && !flag.easy && !flag.force && !command && !backlog[0] && root)
     {
         /*
          * A hint move for the player is available.  Compute a move for the
@@ -1640,13 +1640,13 @@ InputCommand(char *command, int root)
         ft = time0; /* Save reference time for the player. */
         fflush(stdout);
         algbr((short) hint >> 8, (short) hint & 0xff, false);
-        strcpy(s, mvstr[0]);
+        strcpy(ponderString, mvstr[0]);
 
         if (flag.post)
             dsp->GiveHint();
 
         /* do the hint move */
-        if (VerifyMove(s, VERIFY_AND_TRY_MODE, &mv))
+        if (VerifyMove(ponderString, VERIFY_AND_TRY_MODE, &mv))
         {
             Sdepth = 0;
 
@@ -1681,12 +1681,27 @@ InputCommand(char *command, int root)
             }
 #endif
 
-            /* undo the hint and carry on */
-            VerifyMove(s, UNMAKE_MODE, &mv);
+            if (strcmp(ponderString, "hit"))
+            {   /* undo the hint and carry on */
+                VerifyMove(ponderString, UNMAKE_MODE, &mv);
+            }
+            else
+            {   /* otherwise SelectMove will have played the computer's reply */ 
+                /* update ponder-move stats, which was skipped in TRY_MODE    */
+                GameList[GameCnt-1].depth = GameList[GameCnt].score = 0;
+                GameList[GameCnt-1].nodes = 0;
+                ElapsedTime(COMPUTE_AND_INIT_MODE);
+                GameList[GameCnt-1].time = (short) (et + 50)/100; /* FIXME: this is wrong */
+
+                if(TCflag && TimeControl.moves[computer] == 0)
+                    SetTimeControl(); /* add time for next session */
+            }
             Sdepth = 0;
         }
 
         time0 = ft; /* Restore reference time for the player. */
+        ponderString[0] = '\0';
+        /* on a ponder miss or other command, loop terminates because of backlog */
     }
 
     while(!(ok || flag.quit || done))
@@ -1723,9 +1738,26 @@ InputCommand(char *command, int root)
         }
 
         /* extract first word */
-        if (sscanf(sx, "%s", s) < 1)
+        if (sscanf(sx, "%s %s", s, s2) < 1)
             continue;
 
+        if (!root && (strcmp(s, "usermove") == 0)
+                  && (strcmp(s2, ponderString) == 0))
+        {   /* ponder hit; switch to normal search  */
+            background = false;
+            hint = 0;
+            if (TCflag)
+            {   /* account opponent time and moves */
+                TimeControl.clock[opponent] -= et;
+                timeopp[oppptr] = et;
+                --TimeControl.moves[opponent];
+                if(TimeControl.moves[computer] == 0) SetTimeControl();
+            }
+            SetResponseTime(computer);
+            strcpy(ponderString, "hit");
+            return false;        /* no search abort */
+        }
+
         if (!root && strcmp(s, ".") && strcmp(s, "time") && strcmp(s, "otim"))
         {   /* during search most commands can only be done after abort */
             strcpy(backlog, sx); /* backlog the command    */
index d40c3ac..fd6b022 100644 (file)
@@ -852,9 +852,7 @@ typedef struct hashval drop_hashcode_array[2][NO_PIECES][NO_SQUARES];
 extern hashcode_array  *hashcode;
 extern drop_hashcode_array  *drop_hashcode;
 
-#ifdef QUIETBACKGROUND
 extern short background;
-#endif /* QUIETBACKGROUND */
 
 #if ttblsz
 extern short use_ttable;
index 7272095..ee7b402 100644 (file)
@@ -403,7 +403,7 @@ SelectMove(short side, SelectMove_mode iop)
     /********************** end of main loop ***************************/
 
     /* background mode */
-    if (iop == BACKGROUND_MODE)
+    if (background) /* originally: if (iop == BACKGROUND_MODE) */
         return;
 
     if (rpt >= 3)
index 2ce4416..539cb7f 100644 (file)
@@ -295,7 +295,7 @@ void SetResponseTime(short side)
         TCcount = MAXTCCOUNTX;
     }
 #endif
-
+printf("# %2d. moves=%d,%d time=%d,%d ResponseTime=%d+%d\n",GameCnt,TimeControl.moves[computer],TimeControl.moves[opponent],TimeControl.clock[computer],TimeControl.clock[opponent],ResponseTime,TCleft);
     assert(TCcount <= MAXTCCOUNTX);
 }