From: H.G.Muller Date: Thu, 12 Apr 2018 12:56:54 +0000 (+0200) Subject: Implement playing by node count X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=b0e46015bac4d0bf05e2f89336d0c6c836ef0322;p=crazywa.git Implement playing by node count The CECP 'nps' command is supported, to allow conversion of the clock times to a node budget. A new routine for reaing the CPU time that has been used had to be added for this. ReadClock() got a second parameter for indicating whether the time is requested for printing (CPU time) or for timing (nodes). --- diff --git a/dropper.c b/dropper.c index d0a5ad5..ee8bc83 100644 --- a/dropper.c +++ b/dropper.c @@ -11,7 +11,7 @@ #ifdef WIN32 # include -# define CPUtime 1000.*clock +# define CPUtime (1000./CLOCKS_PER_SEC)*clock int Input() { // checks for waiting input in pipe static int init; static HANDLE inp; DWORD cnt; @@ -30,6 +30,14 @@ gettimeofday(&t, NULL); return t.tv_sec*1000 + t.tv_usec/1000; } + double CPUtime() + { // get CPU time used by process, converted to 'MILLICLOCKS' + struct tms cpuTimes; + static int cps = 0; static double ms_per_clk; + if(!cps) cps = sysconf(_SC_CLK_TCK), ms_per_clk = 1000./cps; + times(&cpuTimes); + return (cpuTimes.tms_utime + cpuTimes.tms_stime) * ms_per_clk; + } int Input() { int cnt; @@ -69,13 +77,13 @@ typedef long long int Key; int ply, nodeCount, forceMove, choice, rootMove, lastGameMove, rootScore, abortFlag, postThinking=1; // some frequently used data -int maxDepth=MAXPLY-2, timeControl=3000, mps=40, inc, timePerMove, timeLeft=1000; // TC parameters -int rootFirst, rootCurrent, rootLast, rootPly, margin; +int maxDepth=MAXPLY-2, timeControl=3000, mps=40, inc, timePerMove, timeLeft=1000, nodeRate=-1; // TC parameters +int rootFirst, rootCurrent, rootLast, rootPly, rootScore, margin; #define H_LOWER 1 #define H_UPPER 2 -int ReadClock (int start); +int ReadClock (int start, int print); char *MoveToText (int move); int TimeIsUp (int mode); @@ -1514,8 +1522,8 @@ printf("%d:%d:%d %2d. %08x %c%d%c%d %6d %6d %6d\n",ply,depth,iterDepth,curMove,m tail = pvPtr; pvPtr = pvStart; *pvPtr++ = moveStack[curMove]; // alpha < score < beta: move starts new PV while(*pvPtr++ = *tail++); // copy PV of daughter node behind it (including 0 sentinel) if(ply == 0) { // in root we print this PV - int xbScore = (score > INF-100 ? 100000 + INF - score : score < 100-INF ? -100000 - score - INF : score); - printf("%d %d %d %d", iterDepth, xbScore, ReadClock(0)/10, nodeCount); + rootScore = (score > INF-100 ? 100000 + INF - score : score < 100-INF ? -100000 - score - INF : score); + printf("%d %d %d %d", iterDepth, rootScore, ReadClock(0, 1)/10, nodeCount); for(tail=pvStart; *tail; tail++) printf(" %s", MoveToText(*tail)); printf("\n"); fflush(stdout); ff->move = moveStack[bestNr]; @@ -1605,7 +1613,7 @@ TimeIsUp (int mode) int t, targetTime, panicTime; if(Input() && DoCommand(1)) return 1; // abort if command waiting that cannot be handled during search if(engineSide == ANALYZE) return 0; // no timing on analyze or ponder - t = ReadClock(0); + t = ReadClock(0, 0); if(timePerMove >= 0) { // fixed time per move targetTime = panicTime = 10*timeLeft - 30; } else if(mps) { // classical TC @@ -1754,11 +1762,12 @@ int resign; // engine-defined option int contemptFactor; // likewise int -ReadClock (int start) +ReadClock (int start, int print) { - static int startTime; - int t = GetTickCount(); - if(start) startTime = t; + static int startTime; int t; + if(nodeRate > 0 && !start && !print) return nodeCount*1000LL/nodeRate; + t = (nodeRate >= 0 ? (int)(CPUtime()) : GetTickCount()); + if(start) startTime = t, nodeCount = 0; return t - startTime; // msec } @@ -1860,7 +1869,7 @@ printf("# command: %s\n", inBuf); if(!strcmp(command, "nopost")) { postThinking = OFF;return 0; } if(!strcmp(command, "random")) { randomize = ON; return 0; } if(!strcmp(command, ".")) { // periodic update request; - printf("stat01: %d %d %d %d %d %s\n", ReadClock(0)/10, nodeCount, rootPly, + printf("stat01: %d %d %d %d %d %s\n", ReadClock(0, 1)/10, nodeCount, rootPly, rootLast - rootCurrent + 1, rootLast - rootFirst, MoveToText(moveStack[rootCurrent])); fflush(stdout); return 0; } @@ -1887,7 +1896,8 @@ printf("# command: %s\n", inBuf); return 1; } if(!strcmp(command, "protover")){ - printf("feature ping=1 setboard=1 colors=0 usermove=1 memory=1 debug=1 reuse=0 sigint=0 sigterm=0 exclude=1 myname=\"CrazyWa " VERSION "\"\n"); + printf("feature ping=1 setboard=1 colors=0 usermove=1 memory=1 debug=1 reuse=0 sigint=0 sigterm=0 " + "exclude=1 nps=1 myname=\"CrazyWa " VERSION "\"\n"); printf("feature variants=\"crazyhouse,shogi,minishogi,judkinshogi,torishogi,euroshogi,crazywa,kyotoshogi," "5x5+4_shogi,5x5+5_shogi,6x6+6_shogi,7x7+6_shogi,11x17+16_chu\"\n"); printf("feature option=\"Resign -check 0\"\n"); // example of an engine-defined option @@ -1902,10 +1912,11 @@ printf("# command: %s\n", inBuf); } if(!strcmp(command, "sd")) { sscanf(inBuf+2, "%d", &maxDepth); return 1; } if(!strcmp(command, "st")) { sscanf(inBuf+2, "%d", &timePerMove); return 1; } + if(!strcmp(command, "nps")) { sscanf(inBuf+4, "%d", &nodeRate); return 1; } if(!strcmp(command, "memory")) { if(SetMemorySize(atoi(inBuf+7))) printf("tellusererror Not enough memory\n"), exit(-1); return 1; } if(!strcmp(command, "ping")) { printf("pong%s", inBuf+4); return 1; } // if(!strcmp(command, "")) { sscanf(inBuf, " %d", &); return 1; } - if(!strcmp(command, "new")) { engineSide = BLACK; stm = WHITE; maxDepth = MAXPLY-2; randomize = OFF; + if(!strcmp(command, "new")) { engineSide = BLACK; stm = WHITE; maxDepth = MAXPLY-2; randomize = OFF; nodeRate = -1; moveNr = 0; ranKey = GetTickCount() | 0x1001; MapClear(0); return 1; } if(!strcmp(command, "variant")) { GameInit(inBuf + 8); Setup(startPos); return 1; } if(!strcmp(command, "setboard")){ engineSide = NONE; stm = Setup(inBuf+9); MapClear(0); return 1; } @@ -1956,10 +1967,11 @@ main () if(stm == engineSide) { // if it is the engine's turn to move, set it thinking, and let it move {int i;for(i=0; i<=hashMask+3; i++) /*if(hashTable[i].score != hashTable[i].lim)*/ hashTable[i].lock = 0;} - nodeCount = forceMove = undoInfo.move = abortFlag = 0; ReadClock(1); + forceMove = undoInfo.move = abortFlag = 0; ReadClock(1, 0); for(i=0;i<1<<16;i++) history[i] = 0; //>>= 1; for(i=0;i<1<<17;i++) mateKillers[i] = 0; score = Search(stm^COLOR, -INF, INF, &undoInfo, maxDepth, 0, maxDepth); + if(nodeRate >= 0) printf("%d %d %d %d \n", rootPly, rootScore, ReadClock(0, 1)/10, nodeCount); // make sure total time is printed if(!undoInfo.move) { // no move, game apparently ended engineSide = NONE; // so stop playing @@ -1974,7 +1986,7 @@ main () // now it is not our turn (anymore) if(engineSide == ANALYZE) { // in analysis, we always ponder the position - nodeCount = forceMove = undoInfo.move = abortFlag = 0; ReadClock(1); + forceMove = undoInfo.move = abortFlag = 0; ReadClock(1, 0); Search(stm^COLOR, -INF, INF, &undoInfo, maxDepth, 0, maxDepth); } #if 0