X-Git-Url: http://winboard.nl/cgi-bin?p=uci2wb.git;a=blobdiff_plain;f=UCI2WB.c;h=ff5ec8cdfb142053da5a38a346c25fb35b47d3d9;hp=c075731fd01b4cf87d80ddc08d0eee70e4cb3ff5;hb=7bd5b32b970229a4a9cc23ca2e8849e30c6d9823;hpb=19d15a4533382e6c7ff78165279151bef8209aee diff --git a/UCI2WB.c b/UCI2WB.c index c075731..ff5ec8c 100644 --- a/UCI2WB.c +++ b/UCI2WB.c @@ -1,6 +1,15 @@ -/************************* UCI2WB by H.G.Muller ****************************/ - -#define VERSION "1.9" +/****************************************************************************/ +/* UCI2WB by H.G.Muller */ +/* */ +/* UCI2WB is an adapter to run engines that communicate in various dialects */ +/* of the Universal Chess Interface in a GUI that supports XBoard protocol */ +/* (CECP). It supports UCI (when used for Xiangqi: the 'Cyclone dialect'), */ +/* as well as USI and UCCI when used with the flags -s or -x, respectively. */ +/* This version of UCI2WB is released under the GNU General Public License, */ +/* of which you should have received a copy together with this file. */ +/****************************************************************************/ + +#define VERSION "2.1" #include #include @@ -30,11 +39,15 @@ #define NONE 2 #define ANALYZE 3 -char move[2000][10], checkOptions[8192], iniPos[256], hashOpt[20], pause, pondering, ponder, post, hasHash, c, sc='c', *suffix, *variants; -int mps, tc, inc, sTime, depth, myTime, hisTime, stm, computer = NONE, memory, oldMem=0, cores, moveNr, lastDepth, lastScore, startTime, debug; -int statDepth, statScore, statNodes, statTime, currNr, size, collect, nr, sm, inex, on[500]; char currMove[20], moveMap[500][10]; // for analyze mode +char move[2000][10], checkOptions[8192], iniPos[256], hashOpt[20], pause, pondering, suspended, ponder, post, hasHash, c, sc='c', suffix[81], *variants; +int mps, tc, inc, sTime, depth, myTime, hisTime, stm, computer = NONE, memory, oldMem=0, cores, moveNr, lastDepth, lastScore, startTime, debug, flob; +int statDepth, statScore, statNodes, statTime, currNr, size, collect, nr, sm, inex, on[500], frc, byo = -1; +char currMove[20], moveMap[500][10], /* for analyze mode */ canPonder[20], threadOpt[20]; +char board[100]; // XQ board for UCCI +char *nameWord = "name ", *valueWord = "value ", *wTime = "w", *bTime = "b", *wInc = "winc", *bInc = "binc", newGame; // keywords that differ in UCCI +int unit = 1, drawOffer; -FILE *toE, *fromE; +FILE *toE, *fromE, *fromF; int pid; #ifdef WIN32 @@ -77,18 +90,69 @@ Sync (int action) } void +FromFEN(char *fen) +{ int i=0; + while(*fen) { + char c = *fen++; + if(c >= 'A') board[i++] = c; else + if(c == '/') i++; else + if(c == ' ') break; else + while(c-- > '0' && i < 99) board[i++] = 0; + if(i >= 99) break; + } +} + +char * +ToFEN(int stm) +{ + int i, n=0; static char fen[200]; char *p = fen; + for(i=0; i<99; i++) { + char c = board[i]; + if(c >= 'A') { if(n) *p++ = '0' + n; n = 0; *p++ = c; } else n ++; + if(i%10 == 8) { if(n) *p++ = '0' + n; n = -1; *p++ = '/'; } + } + sprintf(p-1, " %c - - 0 1", stm); + return fen; +} + +int +Sqr(char *m, int j) +{ + int n = m[j] - 'a' + 10*('9' - m[j+1]); + if(n < 0) n = 0; else if(n > 99) n = 99; return n; +} + +int +Play(int nr) +{ + int i, last = -1; + FromFEN(iniPos + 4); // in XQ iniPos always has just "fen " prefix + for(i=0; i0)); // byoyomi time + if(sc == 'x') black = 1; else drawOffer = 0;// in UCCI 'black' refers to us and 'white' to opponent + if(!x && drawOffer) ponder = " draw", drawOffer = 0; //pass draw offer only when not pondering + fprintf(toE, "\ngo%s %stime %d %stime %d", ponder, bTime, (black ? myTime : hisTime) - t, wTime, (!black ? myTime : hisTime) - t); + DPRINT( "\n# go%s %stime %d %stime %d", ponder, bTime, (black ? myTime : hisTime) - t, wTime, (!black ? myTime : hisTime) - t); if(sTime > 0) { fprintf(toE, " movetime %d", sTime); DPRINT(" movetime %d", sTime); } else if(mps) { fprintf(toE, " movestogo %d", mps*(nr/(2*mps)+1)-nr/2); DPRINT(" movestogo %d", mps*(nr/(2*mps)+1)-nr/2); } - if(inc && !suffix) { fprintf(toE, " winc %d binc %d", inc, inc); DPRINT(" winc %d binc %d", inc, inc); } + if(flob || byo >= 0) sprintf(suffix, " byoyomi %d", t); // for engines running purely on byoyomi + if(inc && !*suffix) { fprintf(toE, " %s %d %s %d", wInc, inc, bInc, inc); DPRINT(" %s %d %s %d", wInc, inc, bInc, inc); } if(depth > 0) { fprintf(toE, " depth %d", depth); DPRINT(" depth %d", depth); } - if(suffix) { fprintf(toE, suffix, inc); DPRINT(suffix, inc); } - fprintf(toE, "%s\n", ponder); - DPRINT("%s\n", ponder); + if(*suffix) { fprintf(toE, suffix, inc); DPRINT(suffix, inc); } + fprintf(toE, "\n"); DPRINT("\n"); } void @@ -103,10 +167,25 @@ StopPonder(int pondering) void LoadPos(int moveNr) { - int j; - fprintf(toE, "%s moves", iniPos); - DPRINT( "# %s moves", iniPos); - for(j=0; j 0) fprintf(toE, "setoption name UCI_Chess960 value true\n"); } } else if(!strcmp(command, "undo") && (i=1) || !strcmp(command, "remove") && (i=2)) { if(pondering || computer == ANALYZE) StopPonder(1); @@ -377,22 +492,33 @@ GUI2Engine() if(!(sm & 2)) goto nomove; // no moves enabled; continue current search if(computer == ANALYZE) StopPonder(1); // abort old analysis } + else if(!strcmp(command, "pause")) { + if(computer == stm) myTime -= GetTickCount() - startTime; + suspended = 1 + pondering; // remember if we were pondering, and stop search ignoring bestmove + StopPonder(pondering || computer == stm); + } + else if(!strcmp(command, "resume")) { + if(suspended == 2) StartPonder(); // restart interrupted ponder search + suspended = 0; // causes thinking to start in normal way if on move or analyzing + } else if(!strcmp(command, "xboard")) ; else if(!strcmp(command, "analyze"))computer = ANALYZE, collect = 1, sm = 0; else if(!strcmp(command, "exit")) computer = NONE, StopPonder(1); else if(!strcmp(command, "force")) computer = NONE, StopPonder(pondering); else if(!strcmp(command, "go")) computer = stm; - else if(!strcmp(command, "time")) sscanf(line+4, "%d", &myTime), myTime *= 10; - else if(!strcmp(command, "otim")) sscanf(line+4, "%d", &hisTime), hisTime *= 10; + else if(!strcmp(command, "time")) sscanf(line+4, "%d", &myTime), myTime = (10*myTime)/unit; + else if(!strcmp(command, "otim")) sscanf(line+4, "%d", &hisTime), hisTime = (10*hisTime)/unit; else if(!strcmp(command, "post")) post = 1; else if(!strcmp(command, "nopost")) post = 0; - else if(!strcmp(command, "easy")) ponder = 0; - else if(!strcmp(command, "hard")) ponder = 1; - else if(!strcmp(command, "ping")) pause = 1, fprintf(toE, "isready\n"), fflush(toE), Sync(PAUSE), printf("pong %s", line+5); + else if(!strcmp(command, "easy") && !!*canPonder) ponder = 0, StopPonder(pondering), fprintf(toE, "setoption %s%s %sfalse\n", nameWord, canPonder, valueWord); + else if(!strcmp(command, "hard") && !!*canPonder) ponder = 1, fprintf(toE, "setoption %s%s %strue\n", nameWord, canPonder, valueWord), StartPonder(); + else if(!strcmp(command, "ping")) { /* static int done; if(!done) pause = 1, fprintf(toE, "isready\n"), fflush(toE), printf("# send isready\n"), fflush(stdout), Sync(PAUSE); done = 1;*/ printf("po%s", line+2); } else if(!strcmp(command, "memory")) sscanf(line, "memory %d", &memory); - else if(!strcmp(command, "cores")) sscanf(line, "cores %d", &cores); + else if(!strcmp(command, "cores")&& !!*threadOpt) sscanf(line, "cores %d", &cores), fprintf(toE, "setoption %s%s %s%d\n", nameWord, threadOpt, valueWord, cores); else if(!strcmp(command, "sd")) sscanf(line, "sd %d", &depth); - else if(!strcmp(command, "st")) sscanf(line, "st %d", &sTime), sTime = 1000*sTime - 30, inc = 0; + else if(!strcmp(command, "st")) sscanf(line, "st %d", &sTime), sTime = 1000*sTime - 30, inc = 0, sTime /= unit; + else if(!strcmp(command, "offer")) drawOffer = 1; + else if(!strcmp(command, "result")) { if(sc == 's') fprintf(toE, "gameover %s\n", line[8] == '/' ? "draw" : (line[7] == '0') == mySide ? "win" : "lose"); } else if(!strcmp(command, "quit")) fprintf(toE, "quit\n"), fflush(toE), exit(0); } } @@ -492,7 +618,11 @@ main(int argc, char **argv) if(argc > 1 && argv[1][0] == '-') { sc = argv[1][1]; argc--; argv++; } if(argc < 2) { printf("usage is: U%cI2WB [debug] [-s] []\n", sc-32); exit(-1); } if(argc > 2) dir = argv[2]; - if(argc > 3) suffix = argv[3]; + if(argc > 3) strncpy(suffix, argv[3], 80); + + if(sc == 'x') nameWord = valueWord = bTime = "", wTime = "opp", bInc = "increment", wInc = "oppincrement", unit = 1000; // switch to UCCI keywords + else if(sc == 'f' ) frc = -1, sc = 'c'; // UCI for unannounced Chess960 + else if(sc == 'n') sc = 'c'; // UCI for normal Chess // spawn engine proc if(StartEngine(argv[1], dir) != NO_ERROR) { perror(argv[1]), exit(-1); } @@ -503,7 +633,7 @@ main(int argc, char **argv) #ifdef WIN32 CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) Engine2GUI, (LPVOID) NULL, 0, &thread_id); #else - { pthread_t t; signal(SIGINT, SIG_IGN); pthread_create(&t, NULL, Engine2GUI, NULL); } + { pthread_t t; signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); pthread_create(&t, NULL, Engine2GUI, NULL); } #endif // handle GUI->engine traffic in original thread