X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=gnushogi%2Fcommondsp.c;h=4c6dfa42a90782d39588d7d7e77b84b9081e24bc;hb=21a60b5aae737b538480c4d8beee575b3d9a8e35;hp=9556f63905d109f446e2dd82c8511e7711b08bf8;hpb=dec345dc3b77affb98207d7387093dbdee39c08b;p=gnushogi.git diff --git a/gnushogi/commondsp.c b/gnushogi/commondsp.c index 9556f63..4c6dfa4 100644 --- a/gnushogi/commondsp.c +++ b/gnushogi/commondsp.c @@ -285,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]) { @@ -1482,6 +1483,122 @@ SetMachineTime(char *time) } } +/* + * 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! */ @@ -1493,15 +1610,16 @@ SetMachineTime(char *time) * the hint move, then set Sdepth to zero. */ -void -InputCommand(char *command) +int +InputCommand(char *command, int root) { #ifdef QUIETBACKGROUND short have_shown_prompt = false; #endif short ok, done, is_move = false; unsigned short mv; - char s[80], sx[80]; + char s[200], sx[200], s2[200]; + static char backlog[200], ponderString[20]; ok = flag.quit = done = false; player = opponent; @@ -1511,7 +1629,7 @@ InputCommand(char *command) ZeroTTable(); #endif - if ((hint > 0) && !flag.easy && !flag.force) + while ((hint > 0) && !flag.easy && !flag.force && !command && !backlog[0] && root) { /* * A hint move for the player is available. Compute a move for the @@ -1522,13 +1640,13 @@ 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 (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; @@ -1563,19 +1681,34 @@ InputCommand(char *command) } #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)) { player = opponent; - if (flag.analyze) { + if (flag.analyze && !command && !backlog[0] && root) { SelectMove(opponent, BACKGROUND_MODE); } @@ -1592,19 +1725,45 @@ InputCommand(char *command) have_shown_prompt = false; #endif /* QUIETBACKGROUND */ + if (!command && backlog[0]) command = backlog; /* pick up backlogged command */ + if (command == NULL) { int eof = dsp->GetString(sx); if (eof) dsp->ExitShogi(); } else { strcpy(sx, command); - done = true; + backlog[0]= '\0'; /* make sure no backlog is left */ + command = NULL; } /* 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 */ + return true; /* and order search abort */ + } + if (strcmp(s, "bd") == 0) /* bd -- display board */ { /* FIXME: Hack alert! */ @@ -1652,6 +1811,10 @@ InputCommand(char *command) } 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", @@ -1667,10 +1830,16 @@ InputCommand(char *command) "shogi" #endif ); - printf("debug=1 setboard=0 sigint=0 done=1\n"); + printf("debug=1 setboard=1 sigint=0 memory=1 usermove=1 done=1\n"); } else if (strcmp(s, ".") == 0) - { // ignore for now + { // 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) { @@ -1695,6 +1864,17 @@ InputCommand(char *command) { ok = true; } +#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; @@ -1741,6 +1921,10 @@ InputCommand(char *command) NewGame(); dsp->UpdateDisplay(0, 0, 1, 0); } + else if (strcmp(s, "setboard") == 0) + { + ReadFEN(sx + 9); + } else if (strcmp(s, "list") == 0) { ListGame(); @@ -1904,6 +2088,14 @@ InputCommand(char *command) { flag.easy = !flag.easy; } + 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; @@ -1988,6 +2180,9 @@ InputCommand(char *command) } else { + if (strcmp(s, "usermove") == 0) + sscanf(sx + 9, "%s", s); + if (flag.mate) { ok = true; @@ -2032,4 +2227,6 @@ InputCommand(char *command) ++mycnt2, s, TimeControl.clock[player] * 10); } } + + return true; }