Version 0.8
[hachu.git] / hachu.c
diff --git a/hachu.c b/hachu.c
index 79c5b75..4e3ea5d 100644 (file)
--- a/hachu.c
+++ b/hachu.c
@@ -11,7 +11,7 @@
 // promotions by pieces with Lion power stepping in & out the zone in same turn\r
 // promotion on capture\r
 \r
-#define VERSION "0.7beta"\r
+#define VERSION "0.8beta"\r
 \r
 #define PATH level==0 || path[0] == 0xc4028 &&  (level==1 /*|| path[1] == 0x75967 && (level == 2 || path[2] == 0x3400b && (level == 3))*/)\r
 //define PATH 0\r
@@ -230,6 +230,7 @@ PieceDesc ddPieces[] = {
   {"WB", "FT", 1, { 2,X,X,X,2,X,X,X } }, // Water Buffalo\r
   {"RB", "FR", 1, { X,X,X,X,0,X,X,X } }, // Rushing Bird\r
   {"SB", "",   1, { X,X,2,2,2,2,2,X } }, // Standard Bearer\r
+\r
   {"FH", "FK", 1, { 1,2,1,0,1,0,1,2 } }, // Flying Horse\r
   {"NK", "SB", 1, { 1,1,1,1,1,1,1,1 } }, // Neighbor King\r
   {"BM", "MW", 1, { 0,1,1,1,0,1,1,1 } }, // Blind Monkey\r
@@ -1500,7 +1501,6 @@ GenCapts(int sqr, int victimValue)
                    NewCapture(x, SPECIAL + 8*(i-1&7) + (i+1&7) + victimValue - SORTKEY(attacker), p[attacker].promoFlag);\r
                  v = kStep[i+1];\r
                  if((board[x+v] & TYPE) == xstm && board[x+v] > board[sqr])\r
-\r
                    NewCapture(x, SPECIAL + 8*(i+1&7) + (i-1&7) + victimValue - SORTKEY(attacker), p[attacker].promoFlag);\r
                }\r
              } else { // primary victim on first ring\r
@@ -1600,7 +1600,7 @@ Search (int alpha, int beta, int difEval, int depth, int oldPromo, int promoSupp
 #ifdef HASH\r
   Move hashMove; int index, nr, hit;\r
 #endif\r
-if(PATH) /*pboard(board),pmap(attacks, BLACK),*/printf("search(%d) {%d,%d} eval=%d, stm=%d\n",depth,alpha,beta,difEval,stm),fflush(stdout);\r
+if(PATH) /*pboard(board),pmap(attacks, BLACK),*/printf("search(%d) {%d,%d} eval=%d, stm=%d (flag=%d)\n",depth,alpha,beta,difEval,stm,abortFlag),fflush(stdout);\r
   xstm = stm ^ WHITE;\r
 //printf("map made\n");fflush(stdout);\r
   // KING CAPTURE\r
@@ -1807,7 +1807,7 @@ printf("# abort (%d) @ %d\n", abortFlag, level);
         goto leave;\r
       }\r
 #if 1\r
-if(PATH) printf("%d:%2d:%d %3d %6x %-10s %6d %6d\n", level, depth, iterDep, curMove, moveStack[curMove], MoveToText(moveStack[curMove], 0), score, bestScore);\r
+if(PATH) printf("%d:%2d:%d %3d %6x %-10s %6d %6d  (%d)\n", level, depth, iterDep, curMove, moveStack[curMove], MoveToText(moveStack[curMove], 0), score, bestScore, GetTickCount());\r
 \r
       // ALPHA-BETA STUFF\r
       if(score > bestScore) {\r
@@ -1857,7 +1857,6 @@ if(PATH) printf("%d:%2d:%d %3d %6x %-10s %6d %6d\n", level, depth, iterDep, curM
        printf("\n");\r
         fflush(stdout);\r
       }\r
-printf("# s=%d t=%d 1=%d 3=%d f=%d\n",startTime,GetTickCount(),tlim1,tlim3,abortFlag);\r
       if(!(abortFlag & 1) && GetTickCount() - startTime > tlim1) break; // do not start iteration we can (most likely) not finish\r
     }\r
     replyDep = iterDep;\r
@@ -1879,7 +1878,7 @@ leave:
   pvPtr = myPV; // pop PV\r
   retMove = bestMoveNr ? moveStack[bestMoveNr] : 0;\r
   retDep = resDep + 1;\r
-if(PATH) printf("return %d: %d %d\n", depth, bestScore, curEval);\r
+if(PATH) printf("return %d: %d %d (t=%d s=%d lim=%d)\n", depth, bestScore, curEval, GetTickCount(), startTime, tlim1),fflush(stdout);\r
   return bestScore + (bestScore < curEval);\r
 }\r
 \r
@@ -2246,31 +2245,28 @@ SetSearchTimes (int timeLeft)
   tlim1 = 0.2*targetTime;\r
   tlim2 = 1.9*targetTime;\r
   tlim3 = 5*timeLeft / (movesLeft + 4.1);\r
+printf("# limits %d, %d, %d mode = %d\n", tlim1, tlim2, tlim3, abortFlag);\r
 }\r
 \r
 int\r
 SearchBestMove (MOVE *move, MOVE *ponderMove)\r
 {\r
   int score;\r
+printf("# SearchBestMove\n");\r
   startTime = GetTickCount();\r
   nodes = 0;\r
+printf("# s=%d\n", startTime);fflush(stdout);\r
 MapFromScratch(attacks);\r
   retMove = INVALID; repCnt = 0;\r
   score = Search(-INF-1, INF+1, rootEval, maxDepth, sup1, sup2);\r
   *move = retMove;\r
   *ponderMove = pv[1];\r
+printf("# best=%s\n", MoveToText(pv[0],0));\r
+printf("# ponder=%s\n", MoveToText(pv[1],0));\r
   return score;\r
 }\r
 \r
 \r
-void\r
-PonderUntilInput (int stm)\r
-{\r
-MapFromScratch(attacks);\r
-  repCnt = 0; abortFlag = -1;\r
-  Search(-INF-1, INF+1, rootEval, maxDepth, sup1, sup2);\r
-}\r
\r
     int TakeBack(int n)\r
     { // reset the game and then replay it to the desired point\r
       int last, stm;\r
@@ -2306,6 +2302,17 @@ printf("# in (mode = %d,%d): %s\n", root, abortFlag, command);
         if(!strcmp(command, "put"))     { ReadSquare(inBuf+4, &lastPut); continue; }  // ditto\r
         if(!strcmp(command, "."))       { inBuf[0] = 0; return; } // ignore for now\r
         if(!strcmp(command, "lift"))    { inBuf[0] = 0; Highlight(inBuf+5); return; } // treat here\r
+        if(!root && !strcmp(command, "usermove")) {\r
+printf("# move = %s#ponder = %s", inBuf+9, ponderMoveText);\r
+          abortFlag = !!strcmp(inBuf+9, ponderMoveText);\r
+          if(!abortFlag) { // ponder hit, continue as time-based search\r
+printf("# ponder hit\n");\r
+            SetSearchTimes(10*timeLeft + GetTickCount() - startTime); // add time we already have been pondering to total\r
+            if(lastRootIter > tlim1) abortFlag = 2; // abort instantly if we are in iteration we should not have started\r
+            inBuf[0] = 0; ponderMove = INVALID;\r
+            return;\r
+          }\r
+        }\r
         abortFlag = 1;\r
         return;\r
       }\r
@@ -2328,7 +2335,6 @@ printf("# in (mode = %d,%d): %s\n", root, abortFlag, command);
       int i, score, curVarNr;\r
 \r
   Init(V_CHU); // Chu\r
-      listEnd = 1;\r
 \r
       while(1) { // infinite loop\r
 \r
@@ -2336,14 +2342,21 @@ printf("# in (mode = %d,%d): %s\n", root, abortFlag, command);
         *inBuf = 0;\r
 \r
         if(listEnd == 0) ListMoves();   // always maintain a list of legal moves in root position\r
-\r
-        abortFlag = 0;\r
-        if(stm == engineSide) {         // if it is the engine's turn to move, set it thinking, and let it move\r
-     \r
+        abortFlag = -(ponder && WHITE+BLACK-stm == engineSide && moveNr); // pondering and opponent on move\r
+        if(stm == engineSide || abortFlag && ponderMove) {      // if it is the engine's turn to move, set it thinking, and let it move\r
+printf("# start search: stm=%d engine=%d (flag=%d)\n", stm, engineSide, abortFlag);\r
+          if(abortFlag) {\r
+            stm = MakeMove2(stm, ponderMove);                           // for pondering, play speculative move\r
+            gameMove[moveNr++] = ponderMove;                            // remember in game\r
+            sprintf(ponderMoveText, "%s\n", MoveToText(ponderMove, 0)); // for detecting ponder hits\r
+printf("# ponder move = %s", ponderMoveText);\r
+          } else SetSearchTimes(10*timeLeft);                           // for thinking, schedule end time\r
 pboard(board);\r
-          SetSearchTimes(10*timeLeft);\r
           score = SearchBestMove(&move, &ponderMove);\r
-\r
+          if(abortFlag == 1) { // ponder search was interrupted (and no hit)\r
+            UnMake2(INVALID); moveNr--; stm ^= WHITE;    // take ponder move back if we made one\r
+            abortFlag = 0;\r
+          } else\r
           if(move == INVALID) {         // game apparently ended\r
             int kcapt = 0, xstm = stm ^ WHITE, king, k = p[king=royal[xstm]].pos;\r
             if( k != ABSENT) { // test if King capture possible\r
@@ -2366,24 +2379,15 @@ pboard(board);
             gameMove[moveNr++] = move;   // remember game\r
             printf("move %s\n", MoveToText(move, 1));\r
             listEnd = 0;\r
-            continue;\r
+            continue;                    // go check if we should ponder\r
           }\r
-        }\r
-\r
-        fflush(stdout); // make sure everything is printed before we do something that might take time\r
-\r
-        // now it is not our turn (anymore)\r
-        if(engineSide == ANALYZE) {       // in analysis, we always ponder the position\r
-            PonderUntilInput(stm);\r
         } else\r
-        if(engineSide != NONE && ponder == ON && moveNr != 0) { // ponder while waiting for input\r
-          if(ponderMove == INVALID) {     // if we have no move to ponder on, ponder the position\r
-            PonderUntilInput(stm);\r
-          } else {\r
-            int newStm = MakeMove2(stm, ponderMove);\r
-            PonderUntilInput(newStm);\r
-            UnMake2(ponderMove);\r
-          }\r
+        if(engineSide == ANALYZE || abortFlag) { // in analysis, we always ponder the position\r
+            Move dummy;\r
+            *ponderMoveText = 0; // forces miss on any move\r
+            abortFlag = -1;      // set pondering\r
+            SearchBestMove(&dummy, &dummy);\r
+            abortFlag = 0;       //\r
         }\r
 \r
         fflush(stdout);         // make sure everything is printed before we do something that might take time\r