4 * Common display routines for GNU Shogi.
6 * ----------------------------------------------------------------------
7 * Copyright (c) 1993, 1994, 1995 Matthias Mutz
8 * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
9 * Copyright (c) 2008, 2013, 2014 Yann Dirson and the Free Software Foundation
11 * GNU SHOGI is based on GNU CHESS
13 * Copyright (c) 1988, 1989, 1990 John Stanback
14 * Copyright (c) 1992 Free Software Foundation
16 * This file is part of GNU SHOGI.
18 * GNU Shogi is free software; you can redistribute it and/or modify it
19 * under the terms of the GNU General Public License as published by the
20 * Free Software Foundation; either version 3 of the License,
21 * or (at your option) any later version.
23 * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
24 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
28 * You should have received a copy of the GNU General Public License along
29 * with GNU Shogi; see the file COPYING. If not, see
30 * <http://www.gnu.org/licenses/>.
31 * ----------------------------------------------------------------------
35 /* request *snprintf prototypes */
36 #define _POSIX_C_SOURCE 200112L
39 #if defined HAVE_GETTIMEOFDAY
46 #include <sys/param.h>
47 #include <sys/types.h>
54 int InBackground = false;
55 struct display *dsp = &raw_display;
61 movealgbr(short m, char *s)
64 short piece = 0, flag = 0;
77 piece = f - NO_SQUARES;
79 if (piece > NO_PIECES)
82 flag = (dropmask | piece);
129 #endif /* BOOKTEST */
133 * Generate move strings in different formats.
136 * - f piece to be moved
137 * - 0 < f < NO_SQUARES source square
138 * - NO_SQUARES <= f NO_SQUARES + 2*NO_PIECES dropped piece modulo NO_PIECES
139 * - t & 0x7f target square
140 * - t & 0x80 promotion flag
141 * - flag FIXME: must be zero ?
148 algbr(short f, short t, short flag)
154 piece = f - NO_SQUARES;
156 if (f > (NO_SQUARES + NO_PIECES))
159 flag = (dropmask | piece);
168 if ((f == t) && ((f != 0) || (t != 0)))
171 dsp->Printf("error in algbr: FROM=TO=%d, flag=0x%4x\n", t, flag);
174 mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
176 else if ((flag & dropmask) != 0)
178 short piece = flag & pmask;
180 mvstr[0][0] = pxx[piece];
182 mvstr[0][2] = cxx[column(t)];
183 mvstr[0][3] = rxx[row(t)];
185 strcpy(mvstr[1], mvstr[0]);
186 strcpy(mvstr[2], mvstr[0]);
187 strcpy(mvstr[3], mvstr[0]);
189 else if ((f != 0) || (t != 0))
191 /* algebraic notation */
192 mvstr[0][0] = cxx[column(f)];
193 mvstr[0][1] = rxx[row(f)];
194 mvstr[0][2] = cxx[column(t)];
195 mvstr[0][3] = rxx[row(t)];
196 mvstr[0][4] = mvstr[3][0] = '\0';
197 mvstr[1][0] = pxx[board[f]];
199 mvstr[2][0] = mvstr[1][0];
200 mvstr[2][1] = mvstr[0][1];
202 mvstr[2][2] = mvstr[1][1] = mvstr[0][2]; /* to column */
203 mvstr[2][3] = mvstr[1][2] = mvstr[0][3]; /* to row */
204 mvstr[2][4] = mvstr[1][3] = '\0';
205 strcpy(mvstr[3], mvstr[2]);
206 mvstr[3][1] = mvstr[0][0];
210 strcat(mvstr[0], "+");
211 strcat(mvstr[1], "+");
212 strcat(mvstr[2], "+");
213 strcat(mvstr[3], "+");
218 mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
224 * Compare the string 's' to the list of legal moves available for the
225 * opponent. If a match is found, make the move on the board.
229 VerifyMove(char *s, VerifyMove_mode iop, unsigned short *mv)
231 static short pnt, tempb, tempc, tempsf, tempst, cnt;
232 static struct leaf xnode;
234 short i, l, local_flags;
237 /* check and remove quality flags */
238 for (i = local_flags = 0, l = strlen(s); i < l; i++)
243 local_flags |= badmove;
248 local_flags |= goodmove;
254 local_flags |= difficult;
263 if (iop == UNMAKE_MODE)
265 UnmakeMove(opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
271 if (iop == VERIFY_AND_MAKE_MODE)
272 generate_move_flags = true;
274 MoveList(opponent, 2, -1, true);
275 generate_move_flags = false;
278 while (pnt < TrPnt[3])
281 algbr(node->f, node->t, (short) node->flags);
283 if ((strcmp(s, mvstr[0]) == 0)
284 || (strcmp(s, mvstr[1]) == 0)
285 || (strcmp(s, mvstr[2]) == 0)
286 || (strcmp(s, mvstr[3]) == 0))
293 if ((cnt == 1) && (xnode.score > DONTUSE))
297 MakeMove(opponent, &xnode, &tempb, &tempc,
298 &tempsf, &tempst, &INCscore);
300 if (SqAttacked(PieceList[opponent][0], computer, &blocked))
302 UnmakeMove(opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
303 dsp->AlwaysShowMessage("Illegal move (in check) %s", s);
308 if (iop == VERIFY_AND_TRY_MODE)
311 dsp->UpdateDisplay(xnode.f, xnode.t, 0, (short) xnode.flags);
312 GameList[GameCnt].depth = GameList[GameCnt].score = 0;
313 GameList[GameCnt].nodes = 0;
314 ElapsedTime(COMPUTE_AND_INIT_MODE);
315 GameList[GameCnt].time = (short) (et + 50)/100;
316 GameList[GameCnt].flags |= local_flags;
320 TimeControl.clock[opponent] -= et;
321 timeopp[oppptr] = et;
322 --TimeControl.moves[opponent];
325 *mv = (xnode.f << 8) | xnode.t;
326 algbr(xnode.f, xnode.t, false);
328 /* in force mode, check for mate conditions */
331 if (IsCheckmate(opponent ^ 1, -1, -1))
335 sprintf(buf, "%s mates!\n", ColorStr[opponent]);
336 dsp->ShowMessage(buf);
345 dsp->AlwaysShowMessage("Illegal move (no match) %s", s);
347 if (!barebones && (cnt > 1))
349 sprintf(buffer, "Ambiguous Move %s!", s);
350 dsp->ShowMessage(buffer);
358 parser(char *f, short *fpiece)
366 for (i = 1, *fpiece = no_piece; i < NO_PIECES; i++)
368 if (f[0] == pxx[i] || f[0] == qxx[i])
370 *fpiece = (p ? promoted[i] : unpromoted[i]);
375 if (f[1] == '*' || f[1] == '\'')
380 return ((NO_SQUARES + *fpiece) << 8) | locn(r2, c2);
388 p = (f[5] == '+') ? 0x80 : 0;
390 return (locn(r1, c1) << 8) | locn(r2, c2) | p;
398 while (*InPtr != ' ')
401 while (*InPtr == ' ')
409 while (*InPtr == ' ')
414 void RequestInputString(char* buffer, unsigned bufsize)
417 int ret = snprintf(fmt, sizeof(fmt), "%%%us", bufsize);
419 perror("RequestInputString snprintf");
422 if (ret >= sizeof(fmt)) {
424 "Insufficient format-buffer size in %s for bufsize=%u\n",
425 __FUNCTION__, bufsize);
428 dsp->doRequestInputString(fmt, buffer);
442 strcpy(fname, savefile);
444 dsp->ShowMessage("Enter file name: ");
445 RequestInputString(fname, sizeof(fname)-1);
448 if (fname[0] == '\0')
449 strcpy(fname, "shogi.000");
451 if ((fd = fopen(fname, "r")) != NULL)
454 fgets(fname, 256, fd);
455 computer = opponent = black;
464 /* FIXME: write a skipn() function so that we can get
465 * 3 skips by doing skipn(3) */
469 Game50 = atoi(InPtr);
471 flag.force = (*InPtr == 'f');
472 fgets(fname, 256, fd); /* empty */
473 fgets(fname, 256, fd);
476 TCflag = atoi(InPtr);
480 OperatorTime = atoi(InPtr);
481 fgets(fname, 256, fd);
484 TimeControl.clock[black] = atol(InPtr);
487 TimeControl.moves[black] = atoi(InPtr);
488 fgets(fname, 256, fd);
491 TimeControl.clock[white] = atol(InPtr);
494 TimeControl.moves[white] = atoi(InPtr);
495 fgets(fname, 256, fd); /* empty */
497 for (i = NO_ROWS - 1; i > -1; i--)
499 fgets(fname, 256, fd);
503 for (j = 0; j < NO_COLS; j++)
505 sq = i * NO_COLS + j;
511 board[sq] = no_piece;
516 for (c = 0; c < NO_PIECES; c++)
521 board[sq] = promoted[c];
523 board[sq] = unpromoted[c];
529 for (c = 0; c < NO_PIECES; c++)
534 board[sq] = promoted[c];
536 board[sq] = unpromoted[c];
544 Mvboard[sq] = atoi(InPtr);
549 fgets(fname, 256, fd); /* empty */
550 fgets(fname, 256, fd); /* 9 8 7 ... */
551 fgets(fname, 256, fd); /* empty */
552 fgets(fname, 256, fd); /* p l n ... */
555 for (side = 0; side <= 1; side++)
557 fgets(fname, 256, fd);
561 Captured[side][pawn] = atoi(InPtr);
564 Captured[side][lance] = atoi(InPtr);
566 Captured[side][knight] = atoi(InPtr);
569 Captured[side][silver] = atoi(InPtr);
571 Captured[side][gold] = atoi(InPtr);
573 Captured[side][bishop] = atoi(InPtr);
575 Captured[side][rook] = atoi(InPtr);
577 Captured[side][king] = atoi(InPtr);
581 flag.regularstart = true;
583 fgets(fname, 256, fd); /* empty */
584 fgets(fname, 256, fd); /* move score ... */
586 while (fgets(fname, 256, fd))
595 g = &GameList[GameCnt];
596 g->gmove = parser(InPtr, &g->fpiece);
598 g->score = atoi(InPtr);
600 g->depth = atoi(InPtr);
602 g->nodes = atol(InPtr);
604 g->time = atol(InPtr);
606 g->flags = c = atoi(InPtr);
608 g->hashkey = strtol(InPtr, (char **) NULL, 16);
610 g->hashbd = strtol(InPtr, (char **) NULL, 16);
618 for (piece = no_piece, i = 0; i < NO_PIECES; i++)
620 if (pxx[i] == *InPtr)
628 g->color = ((*InPtr == 'W') ? white : black);
630 g->piece = (*InPtr == '+'
632 : unpromoted[piece]);
641 if (TimeControl.clock[black] > 0)
649 dsp->UpdateDisplay(0, 0, 1, 0);
660 short sq, i, c, f, t;
663 char empty[2] = "\n";
666 strcpy(fname, savefile);
668 dsp->ShowMessage("Enter file name: ");
669 RequestInputString(fname, sizeof(fname)-1);
672 if (fname[0] == '\0')
673 strcpy(fname, "shogi.000");
675 if ((fd = fopen(fname, "w")) != NULL)
680 if (computer == white)
683 if (computer == black)
686 fprintf(fd, "White %s Black %s %d %s\n", w, b, Game50,
687 flag.force ? "force" : "");
689 fprintf(fd, "TimeControl %d Operator Time %d\n", TCflag, OperatorTime);
690 fprintf(fd, "Black Clock %ld Moves %d\nWhite Clock %ld Moves %d\n",
691 TimeControl.clock[black], TimeControl.moves[black],
692 TimeControl.clock[white], TimeControl.moves[white]);
695 for (i = NO_ROWS - 1; i > -1; i--)
697 fprintf(fd, "%c ", ROW_NAME(i));
699 for (c = 0; c < NO_COLS; c++)
701 sq = i * NO_COLS + c;
703 p = is_promoted[piece] ? '+' : ' ';
704 fprintf(fd, "%c", p);
720 fprintf(fd, "%c", p);
725 for (f = i * NO_COLS; f < i * NO_COLS + NO_ROWS; f++)
726 fprintf(fd, " %d", Mvboard[f]);
733 fprintf(fd, " 9 8 7 6 5 4 3 2 1\n");
735 fprintf(fd, " p l n s g b r k\n");
737 fprintf(fd, " 5 4 3 2 1\n");
739 fprintf(fd, " p s g b r k\n");
742 for (side = 0; side <= 1; side++)
744 fprintf(fd, "%c", (side == black) ? 'B' : 'W');
745 fprintf(fd, " %2d", Captured[side][pawn]);
747 fprintf(fd, " %2d", Captured[side][lance]);
748 fprintf(fd, " %2d", Captured[side][knight]);
750 fprintf(fd, " %2d", Captured[side][silver]);
751 fprintf(fd, " %2d", Captured[side][gold]);
752 fprintf(fd, " %2d", Captured[side][bishop]);
753 fprintf(fd, " %2d", Captured[side][rook]);
754 fprintf(fd, " %2d", Captured[side][king]);
759 fputs(" move score depth nodes time flags capture\n", fd);
761 for (i = 1; i <= GameCnt; i++)
763 struct GameRec *g = &GameList[i];
766 t = (g->gmove & 0xFF);
767 algbr(f, t, g->flags);
769 fprintf(fd, "%c%c%-5s %6d %5d %7ld %6ld %5d 0x%08lx 0x%08lx",
772 : (is_promoted[g->fpiece] ? '+' : ' ')),
774 ((f > NO_SQUARES) ? &mvstr[0][1] : mvstr[0]),
776 g->nodes, g->time, g->flags,
777 g->hashkey, g->hashbd);
779 if (g->piece != no_piece)
781 fprintf(fd, " %c %s %c\n",
782 pxx[g->piece], ColorStr[g->color],
783 (is_promoted[g->piece] ? '+' : ' '));
793 dsp->ShowMessage("Game saved");
797 dsp->ShowMessage("Could not open file");
803 * GetXGame, SaveXGame and BookGame used to only be defined if
804 * xshogi wasn't defined -- wonder why?
816 dsp->ShowMessage("Enter file name: ");
817 RequestInputString(fname, sizeof(fname)-1);
819 if (fname[0] == '\0')
820 strcpy(fname, "xshogi.position.read");
822 if ((fd = fopen(fname, "r")) != NULL)
825 flag.regularstart = false;
828 /* xshogi position file ... */
829 fgets(fname, 256, fd);
834 if (strcmp(fname, "xshogi"))
838 /* -- empty line -- */
839 fgets(fname, 256, fd);
840 /* -- empty line -- */
841 fgets(fname, 256, fd);
843 for (i = NO_ROWS - 1; i > -1; i--)
845 fgets(fname, 256, fd);
848 for (j = 0; j < NO_COLS; j++)
850 sq = i * NO_COLS + j;
856 board[sq] = no_piece;
861 for (c = 0; c < NO_PIECES; c++)
866 board[sq] = promoted[c];
868 board[sq] = unpromoted[c];
874 for (c = 0; c < NO_PIECES; c++)
879 board[sq] = promoted[c];
881 board[sq] = unpromoted[c];
894 for (side = 0; side <= 1; side++)
896 fgets(fname, 256, fd);
898 Captured[side][pawn] = atoi(InPtr);
901 Captured[side][lance] = atoi(InPtr);
903 Captured[side][knight] = atoi(InPtr);
906 Captured[side][silver] = atoi(InPtr);
908 Captured[side][gold] = atoi(InPtr);
910 Captured[side][bishop] = atoi(InPtr);
912 Captured[side][rook] = atoi(InPtr);
914 Captured[side][king] = atoi(InPtr);
917 if (fgets(fname, 256, fd) != NULL && strncmp(fname, "white", 5) == 0)
930 dsp->UpdateDisplay(0, 0, 1, 0);
945 dsp->ShowMessage("Enter file name: ");
946 RequestInputString(fname, sizeof(fname)-1);
948 if (fname[0] == '\0')
949 strcpy(fname, "xshogi.position.read");
951 if ((fd = fopen(fname, "w")) != NULL)
953 fputs("# xshogi position file -- \n", fd);
957 for (i = NO_ROWS - 1; i > -1; i--)
961 for (j = 0; j < NO_COLS; j++)
963 sq = i * NO_COLS + j;
965 isp = is_promoted[piece];
966 *p = (isp ? '+' : ' ');
969 if (piece == no_piece)
971 else if (color[sq] == white)
984 for (side = 0; side <= 1; side++)
988 "%d %d %d %d %d %d %d %d\n",
990 "%d %d %d %d %d %d\n",
992 Captured[side][pawn],
994 Captured[side][lance],
995 Captured[side][knight],
997 Captured[side][silver],
998 Captured[side][gold],
999 Captured[side][bishop],
1000 Captured[side][rook],
1001 Captured[side][king]);
1006 if (computer == black)
1007 fputs("white to play\n", fd);
1009 fputs("black to play\n", fd);
1020 char fname[256], sflags[4];
1024 strcpy(fname, savefile);
1026 /* Enter file name */
1027 dsp->ShowMessage("Enter file name: ");
1028 RequestInputString(fname, sizeof(fname)-1);
1031 if (fname[0] == '\0')
1034 if ((fd = fopen(fname, "a")) != NULL)
1038 for (i = 1; i <= GameCnt; i++)
1040 struct GameRec *g = &GameList[i];
1041 char mvnr[20], mvs[20];
1044 sprintf(mvnr, "%d.", (i + 1)/2);
1049 t = (g->gmove & 0xFF);
1050 algbr(f, t, g->flags);
1053 /* determine move quality string */
1054 if (g->flags & goodmove)
1057 if (g->flags & badmove)
1060 #ifdef EASY_OPENINGS
1061 if (g->flags & difficult)
1067 /* determine move string */
1070 sprintf(mvs, "%s%s ", &mvstr[0][1], sflags);
1074 sprintf(mvs, "%c%c%c%c%c%s%s ",
1075 mvstr[0][0], mvstr[0][1],
1076 (g->flags & capture) ? 'x' : '-',
1077 mvstr[0][2], mvstr[0][3],
1078 (mvstr[0][4] == '+') ? "+" : "",
1082 fprintf(fd, "%s%s%c%s",
1086 : (is_promoted[g->fpiece] ? "+" : "")),
1099 dsp->ShowMessage("Game saved");
1103 dsp->ShowMessage("Could not open file");
1114 char fname[256], dbuf[256];
1118 strcpy(fname, listfile);
1123 strncpy(dbuf, ctime(&when), 20);
1130 /* use format "CL.Jan01-020304B" when
1133 program played white */
1135 sprintf(fname, "CL.%s%s-%s%s%s%c",
1136 dbuf + 4, dbuf + 8, dbuf + 11, dbuf + 14,
1137 dbuf + 17, ColorStr[computer][0]);
1139 /* replace space padding with 0 */
1140 for (i = 0; fname[i] != '\0'; i++)
1142 if (fname[i] == ' ')
1147 fd = fopen(fname, "w");
1151 printf("Open failure for file: %s", fname);
1155 fprintf(fd, "gnushogi %s game\n", PACKAGE_VERSION);
1156 fputs(" score depth nodes time ", fd);
1157 fputs(" score depth nodes time\n", fd);
1159 for (i = 1; i <= GameCnt; i++)
1161 f = GameList[i].gmove >> 8;
1162 t = (GameList[i].gmove & 0xFF);
1163 algbr(f, t, GameList[i].flags);
1165 if (GameList[i].flags & book)
1167 fprintf(fd, "%c%c%-5s %5d Book%7ld %5ld",
1170 : (is_promoted[GameList[i].fpiece] ? '+' : ' ')),
1171 pxx[GameList[i].fpiece],
1173 ? &mvstr[0][1] : mvstr[0]),
1180 fprintf(fd, "%c%c%-5s %5d %2d %7ld %5ld",
1183 : (is_promoted[GameList[i].fpiece] ? '+' : ' ')),
1184 pxx[GameList[i].fpiece],
1185 (f > NO_SQUARES ? &mvstr[0][1] : mvstr[0]),
1186 GameList[i].score, GameList[i].depth,
1187 GameList[i].nodes, GameList[i].time);
1200 fprintf(fd, "\n\n");
1202 if (GameList[GameCnt].flags & draw)
1204 fprintf(fd, "Draw %s\n", DRAW);
1206 if (DRAW == DRAW_REPETITION)
1210 fprintf(fd, "repetition by positions ");
1212 for (j = GameCnt - 1; j >= Game50; j -= 2)
1214 if (GameList[j].hashkey == hashkey &&
1215 GameList[j].hashbd == hashbd)
1216 fprintf(fd, "%d ", j);
1222 else if (GameList[GameCnt].score == -(SCORE_LIMIT + 999))
1224 fprintf(fd, "%s\n", ColorStr[player ]);
1226 else if (GameList[GameCnt].score == (SCORE_LIMIT + 998))
1228 fprintf(fd, "%s\n", ColorStr[player ^ 1]);
1241 GameList[GameCnt].flags |= badmove;
1245 GameList[GameCnt].flags |= goodmove;
1248 #ifdef EASY_OPENINGS
1250 GameList[GameCnt].flags |= difficult;
1258 * Undo the most recent half-move.
1266 f = GameList[GameCnt].gmove >> 8;
1267 t = GameList[GameCnt].gmove & 0x7F;
1271 /* the move was a drop */
1272 Captured[color[t]][board[t]]++;
1273 board[t] = no_piece;
1279 if (GameList[GameCnt].flags & promote)
1280 board[f] = unpromoted[board[t]];
1282 board[f] = board[t];
1284 color[f] = color[t];
1285 board[t] = GameList[GameCnt].piece;
1286 color[t] = GameList[GameCnt].color;
1288 if (board[t] != no_piece)
1289 Captured[color[f]][unpromoted[board[t]]]--;
1291 if (color[t] != neutral)
1299 if (TCflag && (TCmoves > 1))
1300 ++TimeControl.moves[color[f]];
1302 hashkey = GameList[GameCnt].hashkey;
1303 hashbd = GameList[GameCnt].hashbd;
1305 computer = computer ^ 1;
1306 opponent = opponent ^ 1;
1309 player = player ^ 1;
1310 dsp->ShowSidetoMove();
1311 dsp->UpdateDisplay(0, 0, 1, 0);
1313 if (flag.regularstart)
1319 FlagString(unsigned short flags, char *s)
1324 if (flags & promote)
1325 strcat(s, " promote");
1327 if (flags & dropmask)
1328 strcat(s, " drop:");
1330 if ((piece = (flags & pmask)))
1334 if (is_promoted[piece])
1337 s[l++] = pxx[piece];
1341 if (flags & capture)
1342 strcat(s, " capture");
1345 strcat(s, " exact");
1348 strcat(s, " tesuji");
1351 strcat(s, " check");
1357 strcat(s, " stupid");
1359 if (flags & questionable)
1360 strcat(s, " questionable");
1362 if (flags & kingattack)
1363 strcat(s, " kingattack");
1371 TestSpeed(void(*f)(short side, short ply,
1372 short in_check, short blockable),
1382 #ifdef HAVE_GETTIMEOFDAY
1386 #ifdef HAVE_GETTIMEOFDAY
1387 gettimeofday(&tv, NULL);
1388 t1 = (tv.tv_sec*100 + (tv.tv_usec/10000));
1393 for (i = 0; i < j; i++)
1395 f(opponent, 2, -1, true);
1398 for (jj = TrPnt[2]; i < TrPnt[3]; jj++)
1400 if (!pick(jj, TrPnt[3] - 1))
1406 #ifdef HAVE_GETTIMEOFDAY
1407 gettimeofday(&tv, NULL);
1408 t2 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1413 cnt = j * (TrPnt[3] - TrPnt[2]);
1420 dsp->ShowNodeCnt(cnt);
1425 TestPSpeed(short(*f) (short side), unsigned j)
1429 #ifdef HAVE_GETTIMEOFDAY
1433 #ifdef HAVE_GETTIMEOFDAY
1434 gettimeofday(&tv, NULL);
1435 t1 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1440 for (i = 0; i < j; i++)
1443 #ifdef HAVE_GETTIMEOFDAY
1444 gettimeofday(&tv, NULL);
1445 t2 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1457 dsp->ShowNodeCnt(cnt);
1462 SetOppTime(char *time)
1467 t = (int)strtol(time, &time, 10);
1472 /* FIXME: sec is parsed but ignored */
1473 sec = (int)strtol(time, &time, 10);
1476 m = (int)strtol(time, &time, 10);
1479 TimeControl.clock[opponent] = t;
1482 TimeControl.moves[opponent] = m;
1484 ElapsedTime(COMPUTE_AND_INIT_MODE);
1488 /* just to inform xshogi about availability of otime command */
1489 printf("otime %d %d\n", t, m);
1495 SetMachineTime(char *time)
1500 t = (int)strtol(time, &time, 10);
1505 /* FIXME: sec is parsed but ignored */
1506 sec = (int)strtol(time, &time, 10);
1509 m = (int)strtol(time, &time, 10);
1512 TimeControl.clock[computer] = t;
1515 TimeControl.moves[computer] = m;
1517 ElapsedTime(COMPUTE_AND_INIT_MODE);
1521 /* just to inform xshogi about availability of time command */
1522 printf("time %d %d\n", t, m);
1527 /* FIXME! This is truly the function from hell! */
1530 * Process the user's command. If easy mode is OFF (the computer is thinking
1531 * on opponents time) and the program is out of book, then make the 'hint'
1532 * move on the board and call SelectMove() to find a response. The user
1533 * terminates the search by entering a command. If the opponent does not make
1534 * the hint move, then set Sdepth to zero.
1538 InputCommand(char *command)
1540 short have_shown_prompt = false;
1541 short ok, done, is_move = false;
1545 ok = flag.quit = done = false;
1549 if (TTadd > ttbllimit)
1553 if ((hint > 0) && !flag.easy && !flag.force)
1556 * A hint move for the player is available. Compute a move for the
1557 * opponent in background mode assuming that the hint move will be
1558 * selected by the player.
1561 ft = time0; /* Save reference time for the player. */
1563 algbr((short) hint >> 8, (short) hint & 0xff, false);
1564 strcpy(s, mvstr[0]);
1569 /* do the hint move */
1570 if (VerifyMove(s, VERIFY_AND_TRY_MODE, &mv))
1574 #ifdef QUIETBACKGROUND
1576 have_shown_prompt = true;
1577 #endif /* QUIETBACKGROUND */
1579 /* Start computing a move until the search is interrupted. */
1581 #ifdef INTERRUPT_TEST
1585 /* would love to put null move in here */
1586 /* after we make the hint move make a 2 ply search
1587 * with both plys our moves */
1588 /* think on opponents time */
1589 SelectMove(computer, BACKGROUND_MODE);
1591 #ifdef INTERRUPT_TEST
1592 ElapsedTime(COMPUTE_INTERRUPT_MODE);
1596 printf("searching not terminated by interrupt!\n");
1600 printf("elapsed time from interrupt to "
1601 "terminating search: %ld\n", it);
1605 /* undo the hint and carry on */
1606 VerifyMove(s, UNMAKE_MODE, &mv);
1610 time0 = ft; /* Restore reference time for the player. */
1613 while(!(ok || flag.quit || done))
1617 #ifdef QUIETBACKGROUND
1618 if (!have_shown_prompt)
1620 #endif /* QUIETBACKGROUND */
1624 #ifdef QUIETBACKGROUND
1627 have_shown_prompt = false;
1628 #endif /* QUIETBACKGROUND */
1630 if (command == NULL) {
1631 int eof = dsp->GetString(sx);
1635 strcpy(sx, command);
1639 /* extract first word */
1640 if (sscanf(sx, "%s", s) < 1)
1643 if (strcmp(s, "bd") == 0) /* bd -- display board */
1645 /* FIXME: Hack alert! */
1646 short old_xshogi = XSHOGI;
1649 display_type = DISPLAY_RAW;
1652 dsp->UpdateDisplay(0, 0, 1, 0);
1655 display_type = DISPLAY_X;
1657 else if (strcmp(s, "post") == 0)
1659 flag.post = !flag.post;
1661 else if (strcmp(s, "alg") == 0)
1665 else if ((strcmp(s, "quit") == 0)
1666 || (strcmp(s, "exit") == 0))
1670 else if ((strcmp(s, "set") == 0)
1671 || (strcmp(s, "edit") == 0))
1675 else if (strcmp(s, "setup") == 0)
1679 else if (strcmp(s, "first") == 0)
1683 else if (strcmp(s, "go") == 0)
1688 if (computer == black)
1699 else if (strcmp(s, "help") == 0)
1703 else if (strcmp(s, "material") == 0)
1705 flag.material = !flag.material;
1707 else if (strcmp(s, "force") == 0)
1712 flag.bothsides = false;
1716 flag.force = !flag.force;
1717 flag.bothsides = false;
1720 else if (strcmp(s, "book") == 0)
1722 Book = Book ? 0 : BOOKFAIL;
1724 else if (strcmp(s, "new") == 0)
1727 dsp->UpdateDisplay(0, 0, 1, 0);
1729 else if (strcmp(s, "list") == 0)
1733 else if (strcmp(s, "level") == 0)
1735 dsp->SelectLevel(sx + strlen("level"));
1737 else if (strcmp(s, "clock") == 0)
1739 dsp->SelectLevel(sx + strlen("clock"));
1741 else if (strcmp(s, "hash") == 0)
1743 flag.hash = !flag.hash;
1745 else if (strcmp(s, "gamein") == 0)
1747 flag.gamein = !flag.gamein;
1749 else if (strcmp(s, "beep") == 0)
1751 flag.beep = !flag.beep;
1753 else if (strcmp(s, "time") == 0)
1755 SetMachineTime(sx + strlen("time"));
1757 else if (strcmp(s, "otime") == 0)
1759 SetOppTime(sx + strlen("otime"));
1761 else if (strcmp(s, "Awindow") == 0)
1763 dsp->ChangeAlphaWindow();
1765 else if (strcmp(s, "Bwindow") == 0)
1767 dsp->ChangeBetaWindow();
1769 else if (strcmp(s, "rcptr") == 0)
1771 flag.rcptr = !flag.rcptr;
1773 else if (strcmp(s, "hint") == 0)
1777 else if (strcmp(s, "both") == 0)
1779 flag.bothsides = !flag.bothsides;
1782 ElapsedTime(COMPUTE_AND_INIT_MODE);
1783 SelectMove(opponent, FOREGROUND_MODE);
1786 else if (strcmp(s, "reverse") == 0)
1788 flag.reverse = !flag.reverse;
1790 dsp->UpdateDisplay(0, 0, 1, 0);
1792 else if (strcmp(s, "switch") == 0)
1794 computer = computer ^ 1;
1795 opponent = opponent ^ 1;
1796 xwndw = (computer == black) ? WXWNDW : BXWNDW;
1801 else if (strcmp(s, "black") == 0)
1810 * ok = true; don't automatically start with black command
1813 else if (strcmp(s, "white") == 0)
1822 * ok = true; don't automatically start with white command
1825 else if (strcmp(s, "undo") == 0 && GameCnt > 0)
1829 else if (strcmp(s, "remove") == 0 && GameCnt > 1)
1834 /* CHECKME: are these next three correct? */
1835 else if (!XSHOGI && strcmp(s, "xget") == 0)
1839 else if (!XSHOGI && strcmp(s, "xsave") == 0)
1843 else if (!XSHOGI && strcmp(s, "bsave") == 0)
1847 #ifdef EASY_OPENINGS
1848 else if ((strcmp(s, "?") == 0)
1849 || (strcmp(s, "!") == 0)
1850 || (strcmp(s, "~") == 0))
1852 else if ((strcmp(s, "?") == 0)
1853 || (strcmp(s, "!") == 0))
1858 else if (strcmp(s, "get") == 0)
1862 else if (strcmp(s, "save") == 0)
1866 else if (strcmp(s, "depth") == 0)
1868 dsp->ChangeSearchDepth(sx + strlen("depth"));
1870 else if (strcmp(s, "sd") == 0)
1872 dsp->ChangeSearchDepth(sx + strlen("sd"));
1874 else if (strcmp(s, "hashdepth") == 0)
1876 dsp->ChangeHashDepth();
1878 else if (strcmp(s, "random") == 0)
1882 else if (strcmp(s, "hard") == 0)
1886 else if (strcmp(s, "easy") == 0)
1888 flag.easy = !flag.easy;
1890 else if (strcmp(s, "tsume") == 0)
1892 flag.tsume = !flag.tsume;
1894 else if (strcmp(s, "contempt") == 0)
1898 else if (strcmp(s, "xwndw") == 0)
1900 dsp->ChangeXwindow();
1902 else if (strcmp(s, "rv") == 0)
1905 dsp->UpdateDisplay(0, 0, 1, 0);
1907 else if (strcmp(s, "coords") == 0)
1909 flag.coords = !flag.coords;
1910 dsp->UpdateDisplay(0, 0, 1, 0);
1912 else if (strcmp(s, "stars") == 0)
1914 flag.stars = !flag.stars;
1915 dsp->UpdateDisplay(0, 0, 1, 0);
1917 else if (!XSHOGI && strcmp(s, "moves") == 0)
1924 extern unsigned short PrVar[MAXDEPTH];
1926 SwagHt = (GameList[GameCnt].gmove == PrVar[1])
1933 dsp->ShowMessage("Testing MoveList Speed");
1934 temp = generate_move_flags;
1935 generate_move_flags = true;
1936 TestSpeed(MoveList, 1);
1937 generate_move_flags = temp;
1938 dsp->ShowMessage("Testing CaptureList Speed");
1939 TestSpeed(CaptureList, 1);
1940 dsp->ShowMessage("Testing Eval Speed");
1941 ExaminePosition(opponent);
1942 TestPSpeed(ScorePosition, 1);
1944 else if (!XSHOGI && strcmp(s, "test") == 0)
1947 dsp->ShowMessage("Testing MoveList Speed");
1948 TestSpeed(MoveList, 2000);
1949 dsp->ShowMessage("Testing CaptureList Speed");
1950 TestSpeed(CaptureList, 3000);
1951 dsp->ShowMessage("Testing Eval Speed");
1952 ExaminePosition(opponent);
1953 TestPSpeed(ScorePosition, 1500);
1955 dsp->ShowMessage("Testing MoveList Speed");
1956 TestSpeed(MoveList, 20000);
1957 dsp->ShowMessage("Testing CaptureList Speed");
1958 TestSpeed(CaptureList, 30000);
1959 dsp->ShowMessage("Testing Eval Speed");
1960 ExaminePosition(opponent);
1961 TestPSpeed(ScorePosition, 15000);
1964 else if (!XSHOGI && strcmp(s, "p") == 0)
1966 dsp->ShowPostnValues();
1968 else if (!XSHOGI && strcmp(s, "debug") == 0)
1978 else if ((ok = VerifyMove(s, VERIFY_AND_MAKE_MODE, &mv)))
1980 /* check for repetition */
1981 short rpt = repetition();
1985 DRAW = DRAW_REPETITION;
1986 dsp->ShowMessage(DRAW);
1987 GameList[GameCnt].flags |= draw;
2001 ElapsedTime(COMPUTE_AND_INIT_MODE);
2005 computer = opponent;
2006 opponent = computer ^ 1;
2011 /* add remaining time in milliseconds for xshogi */
2014 printf("%d. %s %ld\n",
2015 ++mycnt2, s, TimeControl.clock[player] * 10);
2018 #ifdef notdef /* optional pass best line to frontend with move */
2019 if (flag.post && !flag.mate)
2023 printf(" %6d ", MSCORE);
2025 for (i = 1; MV[i] > 0; i++)
2027 algbr((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false);
2028 printf("%5s ", mvstr[0]);
2038 SetTimeControl(void)
2042 TimeControl.moves[black] = TimeControl.moves[white] = TCmoves;
2043 TimeControl.clock[black] += 6000L * TCminutes + TCseconds * 100;
2044 TimeControl.clock[white] += 6000L * TCminutes + TCseconds * 100;
2048 TimeControl.moves[black] = TimeControl.moves[white] = 0;
2049 TimeControl.clock[black] = TimeControl.clock[white] = 0;
2052 flag.onemove = (TCmoves == 1);
2054 ElapsedTime(COMPUTE_AND_INIT_MODE);