X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=gnushogi%2Fcommondsp.c;h=2d4fed577ec9bde7876c1d286caa66cce646b6f0;hb=da2a684903fc7a96d47b43dc2feeecde53bd1aa6;hp=785b72e986a8e846f1a3ac0b2c7358bbec5e8b15;hpb=7f6340bb48dec4e1e091fcf551af50bd3cfdcd2e;p=gnushogi.git diff --git a/gnushogi/commondsp.c b/gnushogi/commondsp.c index 785b72e..2d4fed5 100644 --- a/gnushogi/commondsp.c +++ b/gnushogi/commondsp.c @@ -4,11 +4,15 @@ * Common display routines for GNU Shogi. * * ---------------------------------------------------------------------- - * - * Copyright (c) 2012 Free Software Foundation + * Copyright (c) 1993, 1994, 1995 Matthias Mutz + * Copyright (c) 1999 Michael Vanier and the Free Software Foundation + * Copyright (c) 2008, 2013, 2014 Yann Dirson and the Free Software Foundation * * GNU SHOGI is based on GNU CHESS * + * Copyright (c) 1988, 1989, 1990 John Stanback + * Copyright (c) 1992 Free Software Foundation + * * This file is part of GNU SHOGI. * * GNU Shogi is free software; you can redistribute it and/or modify it @@ -28,6 +32,10 @@ * */ +/* request *snprintf prototypes */ +#define _POSIX_C_SOURCE 200112L +#include + #if defined HAVE_GETTIMEOFDAY #include #endif @@ -39,13 +47,14 @@ #include #include -#include #include "gnushogi.h" char mvstr[4][6]; -char *InPtr; -int InBackground = false; +int mycnt1, mycnt2; +static char *InPtr; +struct display *dsp = &raw_display; +short xboard = false; #if defined(BOOKTEST) @@ -86,20 +95,20 @@ movealgbr(short m, char *s) s++; *s = '*'; s++; - *s = cxx[column(t)]; + *s = COL_NAME(column(t)); s++; - *s = rxx[row(t)]; + *s = ROW_NAME(row(t)); s++; } else { - *s = cxx[column(f)]; + *s = COL_NAME(column(f)); s++; - *s = rxx[row(f)]; + *s = ROW_NAME(row(f)); s++; - *s = cxx[column(t)]; + *s = COL_NAME(column(t)); s++; - *s = rxx[row(t)]; + *s = ROW_NAME(row(t)); s++; if (flag & promote) @@ -121,8 +130,6 @@ movealgbr(short m, char *s) #endif /* BOOKTEST */ - - /* * Generate move strings in different formats. * @@ -132,7 +139,10 @@ movealgbr(short m, char *s) * - NO_SQUARES <= f NO_SQUARES + 2*NO_PIECES dropped piece modulo NO_PIECES * - t & 0x7f target square * - t & 0x80 promotion flag - * - flag FIXME: must be zero ? + * - flag + * - if flag & dropmask, piece type encoded in flag & pmask + * + * FIXME: that makes 2 ways to specify drops and promotions, why ? * * OUTPUT: * - GLOBAL mvstr @@ -161,12 +171,8 @@ algbr(short f, short t, short flag) if ((f == t) && ((f != 0) || (t != 0))) { - if (!barebones) - { - if (NOT_CURSES) - printf("error in algbr: FROM=TO=%d, flag=0x%4x\n", t, flag); - else - printw("error in algbr: FROM=TO=%d, flag=0x%4x\n", t, flag); + if (!XSHOGI) { + dsp->Printf("error in algbr: FROM=TO=%d, flag=0x%4x\n", t, flag); } mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0'; @@ -176,9 +182,9 @@ algbr(short f, short t, short flag) short piece = flag & pmask; mvstr[0][0] = pxx[piece]; - mvstr[0][1] = '*'; - mvstr[0][2] = cxx[column(t)]; - mvstr[0][3] = rxx[row(t)]; + mvstr[0][1] = xboard ? '@' : '*'; + mvstr[0][2] = COL_NAME(column(t)); + mvstr[0][3] = ROW_NAME(row(t)); mvstr[0][4] = '\0'; strcpy(mvstr[1], mvstr[0]); strcpy(mvstr[2], mvstr[0]); @@ -186,20 +192,27 @@ algbr(short f, short t, short flag) } else if ((f != 0) || (t != 0)) { - /* algebraic notation */ - mvstr[0][0] = cxx[column(f)]; - mvstr[0][1] = rxx[row(f)]; - mvstr[0][2] = cxx[column(t)]; - mvstr[0][3] = rxx[row(t)]; - mvstr[0][4] = mvstr[3][0] = '\0'; + /* pure coordinates notation */ + mvstr[0][0] = COL_NAME(column(f)); + mvstr[0][1] = ROW_NAME(row(f)); + mvstr[0][2] = COL_NAME(column(t)); + mvstr[0][3] = ROW_NAME(row(t)); + mvstr[0][4] = '\0'; + + /* algebraic notation without disambiguation */ mvstr[1][0] = pxx[board[f]]; + mvstr[1][1] = mvstr[0][2]; /* to column */ + mvstr[1][2] = mvstr[0][3]; /* to row */ + mvstr[1][3] = '\0'; + /* algebraic notation with row disambiguation */ mvstr[2][0] = mvstr[1][0]; mvstr[2][1] = mvstr[0][1]; + mvstr[2][2] = mvstr[0][2]; /* to column */ + mvstr[2][3] = mvstr[0][3]; /* to row */ + mvstr[2][4] = '\0'; - mvstr[2][2] = mvstr[1][1] = mvstr[0][2]; /* to column */ - mvstr[2][3] = mvstr[1][2] = mvstr[0][3]; /* to row */ - mvstr[2][4] = mvstr[1][3] = '\0'; + /* algebraic notation with column disambiguation */ strcpy(mvstr[3], mvstr[2]); mvstr[3][1] = mvstr[0][0]; @@ -218,7 +231,6 @@ algbr(short f, short t, short flag) } - /* * Compare the string 's' to the list of legal moves available for the * opponent. If a match is found, make the move on the board. @@ -273,6 +285,7 @@ VerifyMove(char *s, VerifyMove_mode iop, unsigned short *mv) MoveList(opponent, 2, -1, true); generate_move_flags = false; pnt = TrPnt[2]; + if(s[4] == '=') s[4] = '\0'; /* deferral is implied */ while (pnt < TrPnt[3]) { @@ -299,20 +312,7 @@ VerifyMove(char *s, VerifyMove_mode iop, unsigned short *mv) if (SqAttacked(PieceList[opponent][0], computer, &blocked)) { UnmakeMove(opponent, &xnode, &tempb, &tempc, &tempsf, &tempst); - - if (NOT_CURSES) - { - /* Illegal move in check */ - printf(CP[77], mvstr[0]); - printf("\n"); - } - else - { - /* Illegal move in check */ - sprintf(buffer, CP[77], s); - ShowMessage(buffer); - } - + dsp->AlwaysShowMessage("Illegal move (in check): %s", s); return false; } else @@ -320,7 +320,7 @@ VerifyMove(char *s, VerifyMove_mode iop, unsigned short *mv) if (iop == VERIFY_AND_TRY_MODE) return true; - UpdateDisplay(xnode.f, xnode.t, 0, (short) xnode.flags); + dsp->UpdateDisplay(xnode.f, xnode.t, 0, (short) xnode.flags); GameList[GameCnt].depth = GameList[GameCnt].score = 0; GameList[GameCnt].nodes = 0; ElapsedTime(COMPUTE_AND_INIT_MODE); @@ -345,7 +345,7 @@ VerifyMove(char *s, VerifyMove_mode iop, unsigned short *mv) char buf[20]; sprintf(buf, "%s mates!\n", ColorStr[opponent]); - ShowMessage(buf); + dsp->ShowMessage(buf); flag.mate = true; } } @@ -354,31 +354,20 @@ VerifyMove(char *s, VerifyMove_mode iop, unsigned short *mv) } } - if (NOT_CURSES) - { - /* Illegal move */ - printf (CP[75], s); - } - else /* Curses. */ - { - /* Illegal move */ - sprintf(buffer, CP[76], s); - ShowMessage(buffer); - } + dsp->AlwaysShowMessage("Illegal move (no match): %s", s); - if (!barebones && (cnt > 1)) + if (!XSHOGI && (cnt > 1)) { - sprintf(buffer, CP[32], s); - ShowMessage(buffer); + sprintf(buffer, "Ambiguous Move %s!", s); + dsp->ShowMessage(buffer); } return false; } - static int -parser(char *f, int side, short *fpiece) +parser(char *f, short *fpiece) { int c1, r1, c2, r2; short i, p = false; @@ -397,17 +386,17 @@ parser(char *f, int side, short *fpiece) if (f[1] == '*' || f[1] == '\'') { - c2 = COL_NAME(f[2]); - r2 = ROW_NAME(f[3]); + c2 = COL_NUM(f[2]); + r2 = ROW_NUM(f[3]); return ((NO_SQUARES + *fpiece) << 8) | locn(r2, c2); } else { - c1 = COL_NAME(f[1]); - r1 = ROW_NAME(f[2]); - c2 = COL_NAME(f[3]); - r2 = ROW_NAME(f[4]); + c1 = COL_NUM(f[1]); + r1 = ROW_NUM(f[2]); + c2 = COL_NUM(f[3]); + r2 = ROW_NUM(f[4]); p = (f[5] == '+') ? 0x80 : 0; return (locn(r1, c1) << 8) | locn(r2, c2) | p; @@ -426,7 +415,6 @@ skip() } - void skipb() { @@ -435,8 +423,25 @@ skipb() } +void RequestInputString(char* buffer, unsigned bufsize) +{ + static char fmt[10]; + int ret = snprintf(fmt, sizeof(fmt), "%%%us", bufsize); + if (ret < 0 ) { + perror("RequestInputString snprintf"); + exit(1); + } + if (ret >= sizeof(fmt)) { + fprintf(stderr, + "Insufficient format-buffer size in %s for bufsize=%u\n", + __FUNCTION__, bufsize); + exit(1); + } + dsp->doRequestInputString(fmt, buffer); +} -void + +static void GetGame(void) { FILE *fd; @@ -445,29 +450,15 @@ GetGame(void) short sq; short side, isp; - if (savefile[0]) - { + if (savefile[0]) { strcpy(fname, savefile); - } - else - { - /* Enter file name */ - ShowMessage(CP[63]); - - if (NOT_CURSES) - { - scanf("%s", fname); - } - else - { - fflush(stdout); - scanw("%s", fname); - } + } else { + dsp->ShowMessage("Enter file name: "); + RequestInputString(fname, sizeof(fname)-1); } - /* shogi.000 */ if (fname[0] == '\0') - strcpy(fname, CP[137]); + strcpy(fname, "shogi.000"); if ((fd = fopen(fname, "r")) != NULL) { @@ -581,10 +572,12 @@ GetGame(void) skipb(); Captured[side][pawn] = atoi(InPtr); skip(); +#ifndef MINISHOGI Captured[side][lance] = atoi(InPtr); skip(); Captured[side][knight] = atoi(InPtr); skip(); +#endif Captured[side][silver] = atoi(InPtr); skip(); Captured[side][gold] = atoi(InPtr); @@ -612,7 +605,7 @@ GetGame(void) InPtr = fname; skipb(); g = &GameList[GameCnt]; - g->gmove = parser(InPtr, side, &g->fpiece); + g->gmove = parser(InPtr, &g->fpiece); skip(); g->score = atoi(InPtr); skip(); @@ -644,7 +637,7 @@ GetGame(void) } skip(); - g->color = ((*InPtr == CP[119][0]) ? white : black); + g->color = ((*InPtr == 'W') ? white : black); skip(); g->piece = (*InPtr == '+' ? promoted[piece] @@ -665,14 +658,13 @@ GetGame(void) ZeroRPT(); InitializeStats(); - UpdateDisplay(0, 0, 1, 0); + dsp->UpdateDisplay(0, 0, 1, 0); Sdepth = 0; hint = 0; } - -void +static void SaveGame(void) { FILE *fd; @@ -682,45 +674,32 @@ SaveGame(void) short side, piece; char empty[2] = "\n"; - if (savefile[0]) - { + if (savefile[0]) { strcpy(fname, savefile); - } - else - { - /* Enter file name */ - ShowMessage(CP[63]); - - if (NOT_CURSES) - { - scanf("%s", fname); - } - else - { - fflush(stdout); - scanw("%s", fname); - } + } else { + dsp->ShowMessage("Enter file name: "); + RequestInputString(fname, sizeof(fname)-1); } - if (fname[0] == '\0') /* shogi.000 */ - strcpy(fname, CP[137]); + if (fname[0] == '\0') + strcpy(fname, "shogi.000"); if ((fd = fopen(fname, "w")) != NULL) { char *b, *w; - b = w = CP[74]; + b = w = "Human "; if (computer == white) - w = CP[141]; + w = "computer"; if (computer == black) - b = CP[141]; + b = "computer"; - fprintf(fd, CP[37], w, b, Game50, + fprintf(fd, "White %s Black %s %d %s\n", w, b, Game50, flag.force ? "force" : ""); fputs(empty, fd); - fprintf(fd, CP[111], TCflag, OperatorTime); - fprintf(fd, CP[117], + fprintf(fd, "TimeControl %d Operator Time %d\n", TCflag, OperatorTime); + fprintf(fd, "Black Clock %ld Moves %d\nWhite Clock %ld Moves %d\n", TimeControl.clock[black], TimeControl.moves[black], TimeControl.clock[white], TimeControl.moves[white]); fputs(empty, fd); @@ -762,16 +741,24 @@ SaveGame(void) } fputs(empty, fd); - fprintf(fd, " 9 8 7 6 5 4 3 2 1\n"); /* FIXME */ +#ifndef MINISHOGI + fprintf(fd, " 9 8 7 6 5 4 3 2 1\n"); fputs(empty, fd); fprintf(fd, " p l n s g b r k\n"); +#else + fprintf(fd, " 5 4 3 2 1\n"); + fputs(empty, fd); + fprintf(fd, " p s g b r k\n"); +#endif for (side = 0; side <= 1; side++) { fprintf(fd, "%c", (side == black) ? 'B' : 'W'); fprintf(fd, " %2d", Captured[side][pawn]); +#ifndef MINISHOGI fprintf(fd, " %2d", Captured[side][lance]); fprintf(fd, " %2d", Captured[side][knight]); +#endif fprintf(fd, " %2d", Captured[side][silver]); fprintf(fd, " %2d", Captured[side][gold]); fprintf(fd, " %2d", Captured[side][bishop]); @@ -781,7 +768,7 @@ SaveGame(void) } fputs(empty, fd); - fputs(CP[126], fd); + fputs(" move score depth nodes time flags capture\n", fd); for (i = 1; i <= GameCnt; i++) { @@ -815,24 +802,21 @@ SaveGame(void) fclose(fd); - /* Game saved */ - ShowMessage(CP[70]); + dsp->ShowMessage("Game saved"); } else { - /* ShowMessage("Could not open file"); */ - ShowMessage(CP[48]); + dsp->ShowMessage("Could not open file"); } } - /* * GetXGame, SaveXGame and BookGame used to only be defined if * xshogi wasn't defined -- wonder why? */ -void +static void GetXGame(void) { FILE *fd; @@ -841,21 +825,11 @@ GetXGame(void) short sq; short side, isp; - /* Enter file name */ - ShowMessage(CP[63]); + dsp->ShowMessage("Enter file name: "); + RequestInputString(fname, sizeof(fname)-1); - if (NOT_CURSES) - { - scanf("%s", fname); - } - else - { - fflush(stdout); - scanw("%s", fname); - } - - if (fname[0] == '\0') /* XSHOGI.position.read */ - strcpy(fname, CP[205]); + if (fname[0] == '\0') + strcpy(fname, "xshogi.position.read"); if ((fd = fopen(fname, "r")) != NULL) { @@ -869,7 +843,7 @@ GetXGame(void) #ifdef notdef fname[6] = '\0'; - if (strcmp(fname, CP[206])) + if (strcmp(fname, "xshogi")) return; #endif @@ -935,10 +909,12 @@ GetXGame(void) InPtr = fname; Captured[side][pawn] = atoi(InPtr); skip(); +#ifndef MINISHOGI Captured[side][lance] = atoi(InPtr); skip(); Captured[side][knight] = atoi(InPtr); skip(); +#endif Captured[side][silver] = atoi(InPtr); skip(); Captured[side][gold] = atoi(InPtr); @@ -963,13 +939,13 @@ GetXGame(void) Game50 = 1; ZeroRPT(); InitializeStats(); - UpdateDisplay(0, 0, 1, 0); + dsp->UpdateDisplay(0, 0, 1, 0); Sdepth = 0; hint = 0; } -void +static void SaveXGame(void) { FILE *fd; @@ -978,29 +954,16 @@ SaveXGame(void) short sq, piece; short side, isp; - /* Enter file name */ - ShowMessage(CP[63]); - - if (NOT_CURSES) - { - scanf("%s", fname); - } - else - { - fflush(stdout); - scanw("%s", fname); - } + dsp->ShowMessage("Enter file name: "); + RequestInputString(fname, sizeof(fname)-1); - if (fname[0] == '\0') /* XSHOGI.position.read */ - strcpy(fname, CP[205]); + if (fname[0] == '\0') + strcpy(fname, "xshogi.position.read"); if ((fd = fopen(fname, "w")) != NULL) { - /* xshogi position file ... */ fputs("# xshogi position file -- \n", fd); - /* -- empty line -- */ fputs("\n", fd); - /* -- empty line -- */ fputs("\n", fd); for (i = NO_ROWS - 1; i > -1; i--) @@ -1032,10 +995,17 @@ SaveXGame(void) for (side = 0; side <= 1; side++) { - sprintf(fname, "%d %d %d %d %d %d %d %d\n", + sprintf(fname, +#ifndef MINISHOGI + "%d %d %d %d %d %d %d %d\n", +#else + "%d %d %d %d %d %d\n", +#endif Captured[side][pawn], +#ifndef MINISHOGI Captured[side][lance], Captured[side][knight], +#endif Captured[side][silver], Captured[side][gold], Captured[side][bishop], @@ -1055,35 +1025,25 @@ SaveXGame(void) } -void +static void BookSave(void) { FILE *fd; char fname[256], sflags[4]; short i, j, f, t; - if (savefile[0]) - { + if (savefile[0]) { strcpy(fname, savefile); - } - else - { + } else { /* Enter file name */ - ShowMessage(CP[63]); - - if (NOT_CURSES) - { - scanf("%s", fname); - } - else - { - fflush(stdout); - scanw("%s", fname); - } + dsp->ShowMessage("Enter file name: "); + RequestInputString(fname, sizeof(fname)-1); } - if (fname[0] == '\0') + if (fname[0] == '\0') { + dsp->AlwaysShowMessage("aborting book save"); return; + } if ((fd = fopen(fname, "a")) != NULL) { @@ -1150,18 +1110,15 @@ BookSave(void) fclose(fd); - /* Game saved */ - ShowMessage(CP[70]); + dsp->ShowMessage("Game saved"); } else { - /* ShowMessage("Could not open file"); */ - ShowMessage(CP[48]); + dsp->ShowMessage("Could not open file"); } } - void ListGame(void) { @@ -1184,13 +1141,13 @@ ListGame(void) dbuf[16] = '\0'; dbuf[19] = '\0'; - /* use format "CLp16.Jan01-020304B" when patchlevel is 16, + /* use format "CL.Jan01-020304B" when date is Jan 1 time is 02:03:04 program played white */ - sprintf(fname, "CLp%s.%s%s-%s%s%s%c", - patchlevel, dbuf + 4, dbuf + 8, dbuf + 11, dbuf + 14, + sprintf(fname, "CL.%s%s-%s%s%s%c", + dbuf + 4, dbuf + 8, dbuf + 11, dbuf + 14, dbuf + 17, ColorStr[computer][0]); /* replace space padding with 0 */ @@ -1205,14 +1162,13 @@ ListGame(void) if (!fd) { - printf(CP[219], fname); + printf("Open failure for file: %s", fname); exit(1); } - /* fprintf(fd, "gnushogi game %d\n", u); */ - fprintf(fd, CP[161], version, patchlevel); - fputs(CP[10], fd); - fputs(CP[11], fd); + fprintf(fd, "gnushogi %s game\n", PACKAGE_VERSION); + fputs(" score depth nodes time ", fd); + fputs(" score depth nodes time\n", fd); for (i = 1; i <= GameCnt; i++) { @@ -1259,9 +1215,9 @@ ListGame(void) if (GameList[GameCnt].flags & draw) { - fprintf(fd, CP[54], DRAW); + fprintf(fd, "Draw %s\n", DRAW); - if (DRAW == CP[101]) + if (DRAW == DRAW_REPETITION) { short j; @@ -1290,8 +1246,7 @@ ListGame(void) } - -void +static void FlagMove(char c) { switch(c) @@ -1313,13 +1268,11 @@ FlagMove(char c) } - - /* * Undo the most recent half-move. */ -void +static void Undo(void) { short f, t; @@ -1368,69 +1321,15 @@ Undo(void) flag.mate = false; Sdepth = 0; player = player ^ 1; - ShowSidetoMove(); - UpdateDisplay(0, 0, 1, 0); + dsp->ShowSidetoMove(); + dsp->UpdateDisplay(0, 0, 1, 0); if (flag.regularstart) Book = false; } - -void -FlagString(unsigned short flags, char *s) -{ - short l, piece; - *s = '\0'; - - if (flags & promote) - strcat(s, " promote"); - - if (flags & dropmask) - strcat(s, " drop:"); - - if ((piece = (flags & pmask))) - { - l = strlen(s); - - if (is_promoted[piece]) - s[l++] = '+'; - - s[l++] = pxx[piece]; - s[l] = '\0'; - } - - if (flags & capture) - strcat(s, " capture"); - - if (flags & exact) - strcat(s, " exact"); - - if (flags & tesuji) - strcat(s, " tesuji"); - - if (flags & check) - strcat(s, " check"); - - if (flags & draw) - strcat(s, " draw"); - - if (flags & stupid) - strcat(s, " stupid"); - - if (flags & questionable) - strcat(s, " questionable"); - - if (flags & kingattack) - strcat(s, " kingattack"); - - if (flags & book) - strcat(s, " book"); -} - - - -void +static void TestSpeed(void(*f)(short side, short ply, short in_check, short blockable), unsigned j) @@ -1440,7 +1339,7 @@ TestSpeed(void(*f)(short side, short ply, #endif unsigned i; - long cnt, rate, t1, t2; + long cnt, t1, t2; #ifdef HAVE_GETTIMEOFDAY struct timeval tv; @@ -1480,26 +1379,15 @@ TestSpeed(void(*f)(short side, short ply, else et = 1; - rate = (((et) ? ((cnt * 100) / et) : 0)); - -#ifdef DYNAMIC_ZNODES - if (rate > 0) - znodes = rate; -#endif - - if (NOT_CURSES) - printf(CP[91], cnt, rate); - else - ShowNodeCnt(cnt); + dsp->ShowNodeCnt(cnt); } - -void +static void TestPSpeed(short(*f) (short side), unsigned j) { - short i; - long cnt, rate, t1, t2; + unsigned i; + long cnt, t1, t2; #ifdef HAVE_GETTIMEOFDAY struct timeval tv; #endif @@ -1528,32 +1416,22 @@ TestPSpeed(short(*f) (short side), unsigned j) else et = 1; - rate = (et) ? ((cnt * 100) / et) : 0; - - /* printf("Nodes= %ld Nodes/sec= %ld\n", cnt, rate); */ - - if (NOT_CURSES) - printf(CP[91], cnt, rate); - else - ShowNodeCnt(cnt); + dsp->ShowNodeCnt(cnt); } - -void -SetOppTime(char *s) +static void +SetOppTime(char *time) { - char *time; - int m, t, sec; + int m, t; - sec = 0; - time = &s[strlen(CP[228])]; t = (int)strtol(time, &time, 10); if (*time == ':') { time++; - sec = (int)strtol(time, &time, 10); + /* FIXME: sec is parsed but ignored */ + (void)strtol(time, &time, 10); } m = (int)strtol(time, &time, 10); @@ -1574,21 +1452,18 @@ SetOppTime(char *s) } - -void -SetMachineTime(char *s) +static void +SetMachineTime(char *time) { - char *time; - int m, t, sec; + int m, t; - time = &s[strlen(CP[197])]; - sec = 0; t = (int)strtol(time, &time, 10); if (*time == ':') { time++; - sec = (int)strtol(time, &time, 10); + /* FIXME: sec is parsed but ignored */ + (void)strtol(time, &time, 10); } m = (int)strtol(time, &time, 10); @@ -1608,40 +1483,141 @@ SetMachineTime(char *s) } } +/* + * Set up a board position. Pieces are entered by typing the piece followed + * by the location. For example, Nf3 will place a knight on square f3. + */ +static void +ReadFEN(char *fen) +{ + short a = white, r, c, sq, i, error = 0; + char s[80]; + + flag.regularstart = true; + Book = BOOKFAIL; + + for (sq = 0; sq < NO_SQUARES; sq++) + { + board[sq] = no_piece; + color[sq] = neutral; + } + + ClearCaptured(); + + /* read board */ + r = NO_ROWS-1; c = 0; + while(*fen) + { + if (isdigit(*fen)) + { + c += *fen++ - '0'; /* assumes single digit! */ + } + else if (*fen == '/') + { /* next rank */ + if (c != NO_COLS) error++; + c = 0; fen++; + if (--r < 0) break; + } + else + { + int promo = 0, found = 0; + if (*fen == '+') + { + promo++; fen++; + } + + if (!isalpha(*fen)) break; + + for (i = no_piece; i <= king; i++) + { + if ((*fen == pxx[i]) || (*fen == qxx[i])) + { + sq = locn(r, c); + color[sq] = (islower(*fen) ? white : black); + if (promo) + board[sq] = promoted[i]; + else + board[sq] = i; + + found = 1; + break; + } + } + + if (!found) error++; + c++; fen++; + } + } + if(r || c != NO_COLS) error++; + + while (*fen == ' ') fen++; + + /* read holdings */ + if(!strncmp(fen, "[-]", 3)) fen += 3; /* empty holdings */ + else if(*fen == '[') + { + fen++; + while(isalpha(*fen)) + { + int found = 0; + for (i = pawn; i <= king; i++) + { + if ((*fen == pxx[i]) || (*fen == qxx[i])) + { + Captured[islower(*fen) ? white : black][i]++; + found = 1; + break; + } + } + if (!found) error++; + fen++; + } + if(*fen == ']') fen++; else error++; + } + + while (*fen == ' ') fen++; + if (*fen == 'w') + a = black; + else if (*fen == 'b') + a = white; + else + error++; + if (error) printf("tellusererror bad FEN\n"); + for (sq = 0; sq < NO_SQUARES; sq++) + Mvboard[sq] = ((board[sq] != Stboard[sq]) ? 10 : 0); + + computer = otherside[a]; + opponent = a; + flag.force = true; + GameCnt = 0; + Game50 = 1; + ZeroRPT(); + Sdepth = 0; + InitializeStats(); +} -/* FIXME! This is truly the function from hell! */ /* * Process the user's command. If easy mode is OFF (the computer is thinking * on opponents time) and the program is out of book, then make the 'hint' * move on the board and call SelectMove() to find a response. The user - * terminates the search by entering ^C (quit siqnal) before entering a - * command. If the opponent does not make the hint move, then set Sdepth to - * zero. + * terminates the search by entering a command. If the opponent does not make + * the hint move, then set Sdepth to zero. */ +static char ponderString[20]; + void -InputCommand(char *command) +PonderOnHintMove(void) { - int eof = 0; +#ifdef QUIETBACKGROUND short have_shown_prompt = false; - short ok, done, is_move = false; - unsigned short mv; - char s[80], sx[80]; - - ok = flag.quit = done = false; - player = opponent; - -#if ttblsz - if (TTadd > ttbllimit) - ZeroTTable(); #endif + unsigned short mv; - if ((hint > 0) && !flag.easy && !flag.force) - { /* * A hint move for the player is available. Compute a move for the * opponent in background mode assuming that the hint move will be @@ -1651,29 +1627,18 @@ InputCommand(char *command) 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 !defined NOPOST if (flag.post) - GiveHint(); -#endif + dsp->GiveHint(); /* do the hint move */ - if (VerifyMove(s, VERIFY_AND_TRY_MODE, &mv)) + if (VerifyMove(ponderString, VERIFY_AND_TRY_MODE, &mv)) { Sdepth = 0; #ifdef QUIETBACKGROUND - if (NOT_CURSES) - { - PromptForMove(); - } - else - { - ShowSidetoMove(); - ShowPrompt(); - } - + dsp->ShowPrompt(); have_shown_prompt = true; #endif /* QUIETBACKGROUND */ @@ -1703,69 +1668,38 @@ InputCommand(char *command) } #endif - /* undo the hint and carry on */ - VerifyMove(s, UNMAKE_MODE, &mv); - Sdepth = 0; - } - - time0 = ft; /* Restore reference time for the player. */ - } - - while(!(ok || flag.quit || done)) - { - player = opponent; - -#ifdef QUIETBACKGROUND - if (!have_shown_prompt) - { -#endif /* QUIETBACKGROUND */ - - if (NOT_CURSES) - { - PromptForMove(); - } - else - { - ShowSidetoMove(); - ShowPrompt(); - } - -#ifdef QUIETBACKGROUND - } - - have_shown_prompt = false; -#endif /* QUIETBACKGROUND */ - - if (command == NULL) - { - if (NOT_CURSES) - { - s[0] = sx[0] = '\0'; - - while(!sx[0]) - (void)fgets(sx, 80, stdin); + if (strcmp(ponderString, "hit")) + { /* undo the hint and carry on */ + VerifyMove(ponderString, UNMAKE_MODE, &mv); } else - { - fflush(stdout); - eof = (getstr(sx) == ERR); + { /* 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 */ + + RenewTimeControl(computer, 0); /* add time for next session */ } - } - else - { - strcpy(sx, command); - done = true; + Sdepth = 0; } - sscanf(sx, "%s", s); - - if (eof) - ExitShogi(); + time0 = ft; /* Restore reference time for the player. */ + ponderString[0] = '\0'; +} - if (s[0] == '\0') - continue; +/* + * Recognize the command s from input line sx, and perform the action it specifies. + * Returns whether the command could cause it to be out turn to move. + */ +int +ParseAndExecuteCommand(char *s, char *sx) +{ + short ok; + unsigned short mv; - if (strcmp(s, CP[131]) == 0) /* bd -- display board */ + if (strcmp(s, "bd") == 0) /* bd -- display board */ { /* FIXME: Hack alert! */ short old_xshogi = XSHOGI; @@ -1773,45 +1707,110 @@ InputCommand(char *command) if (old_xshogi) display_type = DISPLAY_RAW; - ClearScreen(); - UpdateDisplay(0, 0, 1, 0); + dsp->ClearScreen(); + dsp->UpdateDisplay(0, 0, 1, 0); if (old_xshogi) display_type = DISPLAY_X; } else if (strcmp(s, "post") == 0) { - flag.post = !flag.post; + flag.post = (xboard ? 1 : !flag.post); } - else if (strcmp(s, CP[129]) == 0) + else if (strcmp(s, "nopost") == 0) { - /* noop */ ; /* alg */ + flag.post = 0; + } +#ifdef MINISHOGI + else if (strcmp(s, "variant") == 0) + { /* only variant we play is minishogi */ + printf("setup (P.BR.S...G.+.++.+Kp.br.s...g.+.++.+k) 5x5+5_shogi rbsgk/4p/5/P4/KGSBR [-] w 0 1\n"); } - else if ((strcmp(s, CP[180]) == 0) - || (strcmp(s, CP[216]) == 0)) /* quit exit */ +#endif + else if (strcmp(s, "alg") == 0 || + strcmp(s, "accepted") == 0 || strcmp(s, "rejected") == 0 || + strcmp(s, "variant") == 0 || strcmp(s, "computer") == 0) + { + /* noop */ ; + } + else if ((strcmp(s, "quit") == 0) || + (strcmp(s, "exit") == 0) && !xboard) { flag.quit = true; } -#if !defined NOPOST - else if (strcmp(s, CP[178]) == 0) /* post */ + else if (strcmp(s, "xboard") == 0) { - flag.post = !flag.post; + xboard = true; + strcpy(ColorStr[0], "White"); + strcpy(ColorStr[1], "Black"); } + else if (strcmp(s, "protover") == 0) + { + printf("feature option=\"tsume -check 0\"\n"); + printf("feature option=\"contempt -spin %d -1000 1000\"\n", contempt); + printf("feature option=\"Hash-file search depth -spin %d 0 100\"\n", HashDepth); + printf("feature option=\"Hash-file move number -spin %d 0 100\"\n", HashMoveLimit); + printf("feature myname=\"GNU %s %s\" ", +#ifdef MINISHOGI + "MiniShogi", +#else + "Shogi", #endif - else if ((strcmp(s, CP[191]) == 0) - || (strcmp(s, CP[154]) == 0)) /* set edit */ + PACKAGE_VERSION + ); + printf("variants=\"%s\" ", +#ifdef MINISHOGI + "5x5+5_shogi,minishogi" +#else + "shogi" +#endif + ); + printf("debug=1 setboard=1 sigint=0 memory=1 usermove=1 done=1\n"); + } + else if (strcmp(s, ".") == 0) + { // periodic update request of analysis info: send stat01 info + ElapsedTime(2); + algbr((short)(currentMove >> 8), (short)(currentMove & 0xFF), 0); + printf("stat01: %4ld %8ld %2d %2d %2d %s\n", + et, NodeCnt, Sdepth, movesLeft, TrPnt[2]-TrPnt[1], mvstr[0]); + fflush(stdout); + if (!root) return false; /* signal no abort needed */ + } + else if (strcmp(s, "exit") == 0) { - EditBoard(); + flag.analyze = false; + flag.force = true; } - else if (NOT_CURSES && (strcmp(s, CP[190]) == 0)) /* setup */ + else if (strcmp(s, "analyze") == 0) { - SetupBoard(); + flag.analyze = true; + flag.force = true; } - else if (strcmp(s, CP[156]) == 0) /* first */ + else if ((strcmp(s, "set") == 0) || + (strcmp(s, "edit") == 0)) + { + dsp->EditBoard(); + } + else if (strcmp(s, "setup") == 0) + { + dsp->SetupBoard(); + } + else if (strcmp(s, "first") == 0) { ok = true; } - else if (strcmp(s, CP[162]) == 0) /* go */ +#if ttblsz + else if (strcmp(s, "memory") == 0) + { + unsigned int mem, size, t = 1; + sscanf(sx, "memory %d", &mem); + if(mem > 2048) mem = 2048; /* prevent integer overflow for > 2GB hash */ + size = (mem << 20) / sizeof(struct hashentry) - rehash; + while(t <= size/4) t <<= 1; + AllocateTT(t); + } +#endif + else if (strcmp(s, "go") == 0) { ok = true; flag.force = false; @@ -1827,15 +1826,15 @@ InputCommand(char *command) opponent = white; } } - else if (strcmp(s, CP[166]) == 0) /* help */ + else if (strcmp(s, "help") == 0) { - help(); + dsp->help(); } - else if (strcmp(s, CP[221]) == 0) /* material */ + else if (strcmp(s, "material") == 0) { flag.material = !flag.material; } - else if (strcmp(s, CP[157]) == 0) /* force */ + else if (strcmp(s, "force") == 0) { if (XSHOGI) { @@ -1848,61 +1847,69 @@ InputCommand(char *command) flag.bothsides = false; } } - else if (strcmp(s, CP[134]) == 0) /* book */ + else if (strcmp(s, "book") == 0) { Book = Book ? 0 : BOOKFAIL; } - else if (strcmp(s, CP[172]) == 0) /* new */ + else if (strcmp(s, "new") == 0) { NewGame(); - UpdateDisplay(0, 0, 1, 0); + dsp->UpdateDisplay(0, 0, 1, 0); } - else if (strcmp(s, CP[171]) == 0) /* list */ + else if (strcmp(s, "setboard") == 0) + { + ReadFEN(sx + 9); + } + else if (strcmp(s, "list") == 0) { ListGame(); } - else if ((strcmp(s, CP[169]) == 0) - || (strcmp(s, CP[217]) == 0)) /* level clock */ + else if (strcmp(s, "level") == 0) + { + dsp->SelectLevel(sx + strlen("level")); + } + else if (strcmp(s, "clock") == 0) { - SelectLevel(sx); + dsp->SelectLevel(sx + strlen("clock")); } - else if (strcmp(s, CP[165]) == 0) /* hash */ + else if (strcmp(s, "hash") == 0) { flag.hash = !flag.hash; } - else if (strcmp(s, CP[227]) == 0) /* gamein */ + else if (strcmp(s, "gamein") == 0) { flag.gamein = !flag.gamein; } - else if (strcmp(s, CP[226]) == 0) /* beep */ + else if (strcmp(s, "beep") == 0) { flag.beep = !flag.beep; } - else if (strcmp(s, CP[197]) == 0) /* time */ + else if (strcmp(s, "time") == 0) { - SetMachineTime(sx); + SetMachineTime(sx + strlen("time")); } - else if (strcmp(s, CP[228]) == 0) /* otime */ + else if ((strcmp(s, "otime") == 0) || + (xboard && (strcmp(s, "otim")) == 0)) { - SetOppTime(sx); + SetOppTime(sx + strlen("otime")); } - else if (strcmp(s, CP[33]) == 0) /* Awindow */ + else if (strcmp(s, "Awindow") == 0) { - ChangeAlphaWindow(); + dsp->ChangeAlphaWindow(); } - else if (strcmp(s, CP[39]) == 0) /* Bwindow */ + else if (strcmp(s, "Bwindow") == 0) { - ChangeBetaWindow(); + dsp->ChangeBetaWindow(); } - else if (strcmp(s, CP[183]) == 0) /* rcptr */ + else if (strcmp(s, "rcptr") == 0) { flag.rcptr = !flag.rcptr; } - else if (strcmp(s, CP[168]) == 0) /* hint */ + else if (strcmp(s, "hint") == 0) { - GiveHint(); + dsp->GiveHint(); } - else if (strcmp(s, CP[135]) == 0) /* both */ + else if (strcmp(s, "both") == 0) { flag.bothsides = !flag.bothsides; flag.force = false; @@ -1911,13 +1918,13 @@ InputCommand(char *command) SelectMove(opponent, FOREGROUND_MODE); ok = true; } - else if (strcmp(s, CP[185]) == 0) /* reverse */ + else if (strcmp(s, "reverse") == 0) { flag.reverse = !flag.reverse; - ClearScreen(); - UpdateDisplay(0, 0, 1, 0); + dsp->ClearScreen(); + dsp->UpdateDisplay(0, 0, 1, 0); } - else if (strcmp(s, CP[195]) == 0) /* switch */ + else if (strcmp(s, "switch") == 0) { computer = computer ^ 1; opponent = opponent ^ 1; @@ -1925,8 +1932,9 @@ InputCommand(char *command) flag.force = false; Sdepth = 0; ok = true; + dsp->UpdateDisplay(0, 0, 1, 0); } - else if (strcmp(s, CP[203]) == 0) /* black */ + else if (xboard ? strcmp(s, "white") == 0 : strcmp(s, "black") == 0) { computer = white; opponent = black; @@ -1938,7 +1946,7 @@ InputCommand(char *command) * ok = true; don't automatically start with black command */ } - else if (strcmp(s, CP[133]) == 0) /* white */ + else if (xboard ? strcmp(s, "black") == 0 : strcmp(s, "white") == 0) { computer = black; opponent = white; @@ -1950,95 +1958,107 @@ InputCommand(char *command) * ok = true; don't automatically start with white command */ } - else if (strcmp(s, CP[201]) == 0 && GameCnt > 0) /* undo */ + else if (strcmp(s, "undo") == 0 && GameCnt > 0) { Undo(); } - else if (strcmp(s, CP[184]) == 0 && GameCnt > 1) /* remove */ + else if (strcmp(s, "remove") == 0 && GameCnt > 1) { Undo(); Undo(); } /* CHECKME: are these next three correct? */ - else if (!XSHOGI && strcmp(s, CP[207]) == 0) /* xget */ + else if (!XSHOGI && strcmp(s, "xget") == 0) { GetXGame(); } - else if (!XSHOGI && strcmp(s, "xsave") == 0) /* xsave */ + else if (!XSHOGI && strcmp(s, "xsave") == 0) { SaveXGame(); } - else if (!XSHOGI && strcmp(s, "bsave") == 0) /* bsave */ + else if (!XSHOGI && strcmp(s, "bsave") == 0) { BookSave(); } #ifdef EASY_OPENINGS - else if ((strcmp(s, "?") == 0) - || (strcmp(s, "!") == 0) - || (strcmp(s, "~") == 0)) + else if ((strcmp(s, "?") == 0) || + (strcmp(s, "!") == 0) || + (strcmp(s, "~") == 0)) #else - else if ((strcmp(s, "?") == 0) - || (strcmp(s, "!") == 0)) + else if ((strcmp(s, "?") == 0) || + (strcmp(s, "!") == 0)) #endif { FlagMove(*s); } - else if (strcmp(s, CP[160]) == 0) /* get */ + else if (strcmp(s, "get") == 0) { GetGame(); } - else if (strcmp(s, CP[189]) == 0) /* save */ + else if (strcmp(s, "save") == 0) { SaveGame(); } - else if (strcmp(s, CP[151]) == 0) /* depth */ + else if (strcmp(s, "depth") == 0) + { + dsp->ChangeSearchDepth(sx + strlen("depth")); + } + else if (strcmp(s, "sd") == 0) { - ChangeSearchDepth(); + dsp->ChangeSearchDepth(sx + strlen("sd")); } - else if (strcmp(s, CP[164]) == 0) /* hashdepth */ + else if (strcmp(s, "hashdepth") == 0) { - ChangeHashDepth(); + dsp->ChangeHashDepth(); } - else if (strcmp(s, CP[182]) == 0) /* random */ + else if (strcmp(s, "random") == 0) { dither = DITHER; } - else if (strcmp(s, CP[229]) == 0) /* hard */ + else if (strcmp(s, "hard") == 0) { flag.easy = false; } - else if (strcmp(s, CP[152]) == 0) /* easy */ + else if (strcmp(s, "easy") == 0) { flag.easy = !flag.easy; } - else if (strcmp(s, CP[230]) == 0) /* tsume */ + else if (strcmp(s, "option") == 0) + { + sscanf(sx, "option tsume=%hd", &flag.tsume) || + sscanf(sx, "option hash=%hd", &flag.hash) || + sscanf(sx, "option Hash-file search depth=%hd", &HashDepth) || + sscanf(sx, "option Hash-file move number=%hd", &HashMoveLimit) || + sscanf(sx, "option contempt=%hd", &contempt); + } + else if (strcmp(s, "tsume") == 0) { flag.tsume = !flag.tsume; } - else if (strcmp(s, CP[143]) == 0) /* contempt */ + else if (strcmp(s, "contempt") == 0) { - SetContempt(); + dsp->SetContempt(); } - else if (strcmp(s, CP[209]) == 0) /* xwndw */ + else if (strcmp(s, "xwndw") == 0) { - ChangeXwindow(); + dsp->ChangeXwindow(); } - else if (strcmp(s, CP[186]) == 0) /* rv */ + else if (strcmp(s, "rv") == 0) { flag.rv = !flag.rv; - UpdateDisplay(0, 0, 1, 0); + dsp->UpdateDisplay(0, 0, 1, 0); } - else if (strcmp(s, CP[145]) == 0) /* coords */ + else if (strcmp(s, "coords") == 0) { flag.coords = !flag.coords; - UpdateDisplay(0, 0, 1, 0); + dsp->UpdateDisplay(0, 0, 1, 0); } - else if (strcmp(s, CP[193]) == 0) /* stars */ + else if (strcmp(s, "stars") == 0) { flag.stars = !flag.stars; - UpdateDisplay(0, 0, 1, 0); + dsp->UpdateDisplay(0, 0, 1, 0); } - else if (!XSHOGI && strcmp(s, CP[5]) == 0) /* moves */ + else if (!XSHOGI && strcmp(s, "moves") == 0) { short temp; @@ -2054,47 +2074,50 @@ InputCommand(char *command) #endif SwagHt = 0; - ShowMessage(CP[108]); /* test movelist */ + dsp->ShowMessage("Testing MoveList Speed"); temp = generate_move_flags; generate_move_flags = true; TestSpeed(MoveList, 1); generate_move_flags = temp; - ShowMessage(CP[107]); /* test capturelist */ + dsp->ShowMessage("Testing CaptureList Speed"); TestSpeed(CaptureList, 1); - ShowMessage(CP[85]); /* test score position */ + dsp->ShowMessage("Testing Eval Speed"); ExaminePosition(opponent); TestPSpeed(ScorePosition, 1); } - else if (!XSHOGI && strcmp(s, CP[196]) == 0) /* test */ + else if (!XSHOGI && strcmp(s, "test") == 0) { #ifdef SLOW_CPU - ShowMessage(CP[108]); /* test movelist */ + dsp->ShowMessage("Testing MoveList Speed"); TestSpeed(MoveList, 2000); - ShowMessage(CP[107]); /* test capturelist */ + dsp->ShowMessage("Testing CaptureList Speed"); TestSpeed(CaptureList, 3000); - ShowMessage(CP[85]); /* test score position */ + dsp->ShowMessage("Testing Eval Speed"); ExaminePosition(opponent); TestPSpeed(ScorePosition, 1500); #else - ShowMessage(CP[108]); /* test movelist */ + dsp->ShowMessage("Testing MoveList Speed"); TestSpeed(MoveList, 20000); - ShowMessage(CP[107]); /* test capturelist */ + dsp->ShowMessage("Testing CaptureList Speed"); TestSpeed(CaptureList, 30000); - ShowMessage(CP[85]); /* test score position */ + dsp->ShowMessage("Testing Eval Speed"); ExaminePosition(opponent); TestPSpeed(ScorePosition, 15000); #endif } - else if (!XSHOGI && strcmp(s, CP[179]) == 0) /* p */ + else if (!XSHOGI && strcmp(s, "p") == 0) { - ShowPostnValues(); + dsp->ShowPostnValues(); } - else if (!XSHOGI && strcmp(s, CP[148]) == 0) /* debug */ + else if (!XSHOGI && strcmp(s, "debug") == 0) { - DoDebug(); + dsp->DoDebug(); } else { + if (strcmp(s, "usermove") == 0) + sscanf(sx + 9, "%s", s); + if (flag.mate) { ok = true; @@ -2106,82 +2129,140 @@ InputCommand(char *command) if (rpt >= 3) { - DRAW = CP[101]; - ShowMessage(DRAW); + DRAW = DRAW_REPETITION; + dsp->ShowMessage(DRAW); GameList[GameCnt].flags |= draw; flag.mate = true; } - else + else if (XSHOGI) { - is_move = true; - } + /* add remaining time in milliseconds for xshogi */ + printf("%d. %s %ld\n", + ++mycnt2, s, TimeControl.clock[player] * 10); + } } Sdepth = 0; } - } - ElapsedTime(COMPUTE_AND_INIT_MODE); + return ok; +} - if (flag.force) +/* + * Read commands from input, and execute them, until it becomes our turn to move. + * When called during a background search (root = false) it just backlogs the + * input command without executing it, and returns immediately. Unless the command + * was the move on which the search was pondering. In that case we turn the ongoing + * search into a foreground search. To judge this, it is also necessary to process + * the 'time' and 'otim' commands that preceed the move. The '.' command is also + * always processed, to prevent it from aborting an analysis search. + * The time spent waiting for input can be filled with background searches for + * pondering or analysis. (In !root mode input is guaranteed to be pending already!) + */ +int +InputCommand(int root) +{ +#ifdef QUIETBACKGROUND + short have_shown_prompt = false; +#endif + short ok; + char s[200], sx[200], s2[200]; + static char backlog[200]; + + ok = flag.quit = false; + player = opponent; + +#if ttblsz + /* CHECKME: should this also be done in the following while loop? */ + if (TTadd > ttbllimit) + ZeroTTable(); +#endif + + while ((hint > 0) && !flag.easy && !flag.force && !backlog[0] && root) { - computer = opponent; - opponent = computer ^ 1; + /* + * A hint move for the player is available. Compute a move for the + * opponent in background mode assuming that the hint move will be + * selected by the player. + * Terminate this search on input, which will then be saved in backlog[]. + * Unless the input was the hint move ('ponder hit'). Then that move will + * be played (after the search times out) in addition to the hint. There + * will then be no backlog, and we start pondering on the new hint move. + */ + + PonderOnHintMove(); } - if (XSHOGI) - { - /* add remaining time in milliseconds for xshogi */ - if (is_move) - { - printf("%d. %s %ld\n", - ++mycnt2, s, TimeControl.clock[player] * 10); - } + while(!(ok || flag.quit)) + { /* process input commands until our it becomes our turn to move */ + player = opponent; -#ifdef notdef /* optional pass best line to frontend with move */ -# if !defined NOPOST + /* in analysis mode we do a background search while waiting for input */ + if (flag.analyze && !backlog[0] && root) { + SelectMove(opponent, BACKGROUND_MODE); + } - if (flag.post && !flag.mate) +#ifdef QUIETBACKGROUND + if (!have_shown_prompt) { - int i; +#endif /* QUIETBACKGROUND */ - printf(" %6d ", MSCORE); + dsp->ShowPrompt(); - for (i = 1; MV[i] > 0; i++) - { - algbr((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false); - printf("%5s ", mvstr[0]); - } +#ifdef QUIETBACKGROUND } -# endif - printf("\n"); -#endif - } - signal(SIGUSR1, TerminateSearch); -} + have_shown_prompt = false; +#endif /* QUIETBACKGROUND */ + if (!backlog[0]) { /* read new input line */ + int eof = dsp->GetString(sx); + if (eof) + dsp->ExitShogi(); + } else { /* or use backlogged input line */ + strcpy(sx, backlog); + backlog[0]= '\0'; /* make sure no backlog is left */ + } + /* extract first word */ + 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; + if (--TimeControl.moves[opponent] == 0) + TimeControl.moves[opponent] = TCmoves; /* assumes uni-TC! */ + } + SetResponseTime(computer); + strcpy(ponderString, "hit"); + return false; /* no search abort */ + } -void -SetTimeControl(void) -{ - if (TCflag) - { - TimeControl.moves[black] = TimeControl.moves[white] = TCmoves; - TimeControl.clock[black] += 6000L * TCminutes + TCseconds * 100; - TimeControl.clock[white] += 6000L * TCminutes + TCseconds * 100; + 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 */ + return true; /* and order search abort */ + } + + ok = ParseAndExecuteCommand(s, sx); /* returns whether turn changed */ } - else + + ElapsedTime(COMPUTE_AND_INIT_MODE); + + /* kludge alert: change the side we play to prevent starting a search */ + if (flag.force) { - TimeControl.moves[black] = TimeControl.moves[white] = 0; - TimeControl.clock[black] = TimeControl.clock[white] = 0; + computer = opponent; + opponent = computer ^ 1; } - flag.onemove = (TCmoves == 1); - et = 0; - ElapsedTime(COMPUTE_AND_INIT_MODE); + return true; } -