Xboard: declare "Use hash-file" option to allow disabling hash-file.
[gnushogi.git] / gnushogi / commondsp.c
blobff45ed844bdfc2d8eb509910ec9c5ce790f656af
1 /*
2 * FILE: commondsp.c
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
26 * for more details.
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
38 #include "gnushogi.h"
40 #include <stdio.h>
42 #if defined HAVE_GETTIMEOFDAY
43 #include <sys/time.h>
44 #endif
46 #include <ctype.h>
47 #include <signal.h>
49 #include <sys/param.h>
50 #include <sys/types.h>
51 #include <sys/file.h>
53 char mvstr[4][6];
54 int mycnt1, mycnt2;
55 static char *InPtr;
56 struct display *dsp = &raw_display;
58 short xboard = false;
60 #if defined(BOOKTEST)
62 void
63 movealgbr(short m, char *s)
65 unsigned int f, t;
66 short piece = 0, flag = 0;
68 if (m == 0)
70 strcpy(s, "none");
71 return;
74 f = (m >> 8) & 0x7f;
75 t = m & 0xff;
77 if (f > NO_SQUARES)
79 piece = f - NO_SQUARES;
81 if (piece > NO_PIECES)
82 piece -= NO_PIECES;
84 flag = (dropmask | piece);
87 if (t & 0x80)
89 flag |= promote;
90 t &= 0x7f;
93 if (flag & dropmask)
95 *s = pxx[piece];
96 s++;
97 *s = '*';
98 s++;
99 *s = COL_NAME(column(t));
100 s++;
101 *s = ROW_NAME(row(t));
102 s++;
104 else
106 *s = COL_NAME(column(f));
107 s++;
108 *s = ROW_NAME(row(f));
109 s++;
110 *s = COL_NAME(column(t));
111 s++;
112 *s = ROW_NAME(row(t));
113 s++;
115 if (flag & promote)
117 *s = '+';
118 s++;
122 if (m & 0x8000)
124 *s = '?';
125 s++;
128 *s = '\0';
131 #endif /* BOOKTEST */
135 * Generate move strings in different formats.
137 * INPUT:
138 * - f piece to be moved
139 * - 0 < f < NO_SQUARES source square
140 * - NO_SQUARES <= f NO_SQUARES + 2*NO_PIECES dropped piece modulo NO_PIECES
141 * - t & 0x7f target square
142 * - t & 0x80 promotion flag
143 * - flag
144 * - if flag & dropmask, piece type encoded in flag & pmask
146 * FIXME: that makes 2 ways to specify drops and promotions, why ?
148 * OUTPUT:
149 * - GLOBAL mvstr
152 void
153 algbr(short f, short t, short flags)
155 if (f > NO_SQUARES)
157 short piece;
159 piece = f - NO_SQUARES;
161 if (f > (NO_SQUARES + NO_PIECES))
162 piece -= NO_PIECES;
164 flags = (dropmask | piece);
167 if ((t & 0x80) != 0)
169 flags |= promote;
170 t &= 0x7f;
173 if ((f == t) && ((f != 0) || (t != 0)))
175 if (!XSHOGI) {
176 dsp->Printf("error in algbr: FROM=TO=%d, flags=0x%4x\n", t, flags);
179 mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
181 else if ((flags & dropmask) != 0)
183 short piece = flags & pmask;
185 mvstr[0][0] = pxx[piece];
186 mvstr[0][1] = xboard ? '@' : '*';
187 mvstr[0][2] = COL_NAME(column(t));
188 mvstr[0][3] = ROW_NAME(row(t));
189 mvstr[0][4] = '\0';
190 strcpy(mvstr[1], mvstr[0]);
191 strcpy(mvstr[2], mvstr[0]);
192 strcpy(mvstr[3], mvstr[0]);
194 else if ((f != 0) || (t != 0))
196 /* pure coordinates notation */
197 mvstr[0][0] = COL_NAME(column(f));
198 mvstr[0][1] = ROW_NAME(row(f));
199 mvstr[0][2] = COL_NAME(column(t));
200 mvstr[0][3] = ROW_NAME(row(t));
201 mvstr[0][4] = '\0';
203 /* algebraic notation without disambiguation */
204 mvstr[1][0] = pxx[board[f]];
205 mvstr[1][1] = mvstr[0][2]; /* to column */
206 mvstr[1][2] = mvstr[0][3]; /* to row */
207 mvstr[1][3] = '\0';
209 /* algebraic notation with row disambiguation */
210 mvstr[2][0] = mvstr[1][0];
211 mvstr[2][1] = mvstr[0][1];
212 mvstr[2][2] = mvstr[0][2]; /* to column */
213 mvstr[2][3] = mvstr[0][3]; /* to row */
214 mvstr[2][4] = '\0';
216 /* algebraic notation with column disambiguation */
217 strcpy(mvstr[3], mvstr[2]);
218 mvstr[3][1] = mvstr[0][0];
220 if (flags & promote)
222 strcat(mvstr[0], "+");
223 strcat(mvstr[1], "+");
224 strcat(mvstr[2], "+");
225 strcat(mvstr[3], "+");
228 else
230 mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
236 * Compare the string 's' to the list of legal moves available for the
237 * opponent. If a match is found, make the move on the board.
241 VerifyMove(char *s, VerifyMove_mode iop, unsigned short *mv)
243 static short pnt, tempb, tempc, tempsf, tempst, cnt;
244 static struct leaf xnode;
245 struct leaf *node;
246 short i, l, local_flags;
247 char buffer[60];
249 /* check and remove quality flags */
250 for (i = local_flags = 0, l = strlen(s); i < l; i++)
252 switch(s[i])
254 case '?':
255 local_flags |= badmove;
256 s[i] = '\0';
257 break;
259 case '!':
260 local_flags |= goodmove;
261 s[i] = '\0';
262 break;
264 #ifdef EASY_OPENINGS
265 case '~':
266 local_flags |= difficult;
267 s[i] = '\0';
268 break;
269 #endif
273 *mv = 0;
275 if (iop == UNMAKE_MODE)
277 UnmakeMove(opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
278 return false;
281 cnt = 0;
283 if (iop == VERIFY_AND_MAKE_MODE)
284 generate_move_flags = true;
286 MoveList(opponent, 2, -1, true);
287 generate_move_flags = false;
288 pnt = TrPnt[2];
289 if(s[4] == '=') s[4] = '\0'; /* deferral is implied */
291 while (pnt < TrPnt[3])
293 node = &Tree[pnt++];
294 algbr(node->f, node->t, (short) node->flags);
296 if ((strcmp(s, mvstr[0]) == 0)
297 || (strcmp(s, mvstr[1]) == 0)
298 || (strcmp(s, mvstr[2]) == 0)
299 || (strcmp(s, mvstr[3]) == 0))
301 cnt++;
302 xnode = *node;
306 if ((cnt == 1) && (xnode.score > DONTUSE))
308 short blocked;
310 MakeMove(opponent, &xnode, &tempb, &tempc,
311 &tempsf, &tempst, &INCscore);
313 if (SqAttacked(PieceList[opponent][0], computer, &blocked))
315 UnmakeMove(opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
316 dsp->AlwaysShowMessage("Illegal move (in check): %s", s);
317 return false;
319 else
321 if (iop == VERIFY_AND_TRY_MODE)
322 return true;
324 dsp->UpdateDisplay(xnode.f, xnode.t, 0, (short) xnode.flags);
325 GameList[GameCnt].depth = GameList[GameCnt].score = 0;
326 GameList[GameCnt].nodes = 0;
327 ElapsedTime(COMPUTE_AND_INIT_MODE);
328 GameList[GameCnt].time = (short) (et + 50)/100;
329 GameList[GameCnt].flags |= local_flags;
331 if (TCflag)
333 TimeControl.clock[opponent] -= et;
334 timeopp[oppptr] = et;
335 --TimeControl.moves[opponent];
338 *mv = (xnode.f << 8) | xnode.t;
339 algbr(xnode.f, xnode.t, 0);
341 /* in force mode, check for mate conditions */
342 if (flag.force)
344 if (IsCheckmate(opponent ^ 1, -1, -1))
346 char buf[20];
348 sprintf(buf, "%s mates!\n", ColorStr[opponent]);
349 dsp->ShowMessage(buf);
350 flag.mate = true;
354 return true;
358 dsp->AlwaysShowMessage("Illegal move (no match): %s", s);
360 if (!XSHOGI && (cnt > 1))
362 sprintf(buffer, "Ambiguous Move %s!", s);
363 dsp->ShowMessage(buffer);
366 return false;
370 static int
371 parser(char *f, short *fpiece)
373 int c1, r1, c2, r2;
374 short i, p = false;
376 if (*f == '+')
377 f++, p = true;
379 for (i = 1, *fpiece = no_piece; i < NO_PIECES; i++)
381 if (f[0] == pxx[i] || f[0] == qxx[i])
383 *fpiece = (p ? promoted[i] : unpromoted[i]);
384 break;
388 if (f[1] == '*' || f[1] == '\'')
390 c2 = COL_NUM(f[2]);
391 r2 = ROW_NUM(f[3]);
393 return ((NO_SQUARES + *fpiece) << 8) | locn(r2, c2);
395 else
397 c1 = COL_NUM(f[1]);
398 r1 = ROW_NUM(f[2]);
399 c2 = COL_NUM(f[3]);
400 r2 = ROW_NUM(f[4]);
401 p = (f[5] == '+') ? 0x80 : 0;
403 return (locn(r1, c1) << 8) | locn(r2, c2) | p;
408 void
409 skip()
411 while (*InPtr != ' ')
412 InPtr++;
414 while (*InPtr == ' ')
415 InPtr++;
419 void
420 skipb()
422 while (*InPtr == ' ')
423 InPtr++;
427 void RequestInputString(char* buffer, unsigned bufsize)
429 static char fmt[10];
430 int ret = snprintf(fmt, sizeof(fmt), "%%%us", bufsize);
431 if (ret < 0 ) {
432 perror("RequestInputString snprintf");
433 exit(1);
435 if (ret >= sizeof(fmt)) {
436 fprintf(stderr,
437 "Insufficient format-buffer size in %s for bufsize=%u\n",
438 __FUNCTION__, bufsize);
439 exit(1);
441 dsp->doRequestInputString(fmt, buffer);
445 static void
446 GetGame(void)
448 FILE *fd;
449 char fname[256], *p;
450 int c, i, j;
451 short sq;
452 short side, isp;
454 if (savefile[0]) {
455 strcpy(fname, savefile);
456 } else {
457 dsp->ShowMessage("Enter file name: ");
458 RequestInputString(fname, sizeof(fname)-1);
461 if (fname[0] == '\0')
462 strcpy(fname, "shogi.000");
464 if ((fd = fopen(fname, "r")) != NULL)
466 NewGame();
467 fgets(fname, 256, fd);
468 computer = opponent = black;
469 InPtr = fname;
470 skip();
472 if (*InPtr == 'c')
473 computer = white;
474 else
475 opponent = white;
477 /* FIXME: write a skipn() function so that we can get
478 * 3 skips by doing skipn(3) */
479 skip();
480 skip();
481 skip();
482 Game50 = atoi(InPtr);
483 skip();
484 flag.force = (*InPtr == 'f');
485 fgets(fname, 256, fd); /* empty */
486 fgets(fname, 256, fd);
487 InPtr = &fname[11];
488 skipb();
489 TCflag = atoi(InPtr);
490 skip();
491 InPtr += 14;
492 skipb();
493 OperatorTime = atoi(InPtr);
494 fgets(fname, 256, fd);
495 InPtr = &fname[11];
496 skipb();
497 TimeControl.clock[black] = atol(InPtr);
498 skip();
499 skip();
500 TimeControl.moves[black] = atoi(InPtr);
501 fgets(fname, 256, fd);
502 InPtr = &fname[11];
503 skipb();
504 TimeControl.clock[white] = atol(InPtr);
505 skip();
506 skip();
507 TimeControl.moves[white] = atoi(InPtr);
508 fgets(fname, 256, fd); /* empty */
510 for (i = NO_ROWS - 1; i > -1; i--)
512 fgets(fname, 256, fd);
513 p = &fname[2];
514 InPtr = &fname[23];
516 for (j = 0; j < NO_COLS; j++)
518 sq = i * NO_COLS + j;
519 isp = (*p == '+');
520 p++;
522 if (*p == '-')
524 board[sq] = no_piece;
525 color[sq] = neutral;
527 else
529 for (c = 0; c < NO_PIECES; c++)
531 if (*p == pxx[c])
533 if (isp)
534 board[sq] = promoted[c];
535 else
536 board[sq] = unpromoted[c];
538 color[sq] = white;
542 for (c = 0; c < NO_PIECES; c++)
544 if (*p == qxx[c])
546 if (isp)
547 board[sq] = promoted[c];
548 else
549 board[sq] = unpromoted[c];
551 color[sq] = black;
556 p++;
557 Mvboard[sq] = atoi(InPtr);
558 skip();
562 fgets(fname, 256, fd); /* empty */
563 fgets(fname, 256, fd); /* 9 8 7 ... */
564 fgets(fname, 256, fd); /* empty */
565 fgets(fname, 256, fd); /* p l n ... */
566 ClearCaptured();
568 for (side = 0; side <= 1; side++)
570 fgets(fname, 256, fd);
571 InPtr = fname;
572 skip();
573 skipb();
574 Captured[side][pawn] = atoi(InPtr);
575 skip();
576 #ifndef MINISHOGI
577 Captured[side][lance] = atoi(InPtr);
578 skip();
579 Captured[side][knight] = atoi(InPtr);
580 skip();
581 #endif
582 Captured[side][silver] = atoi(InPtr);
583 skip();
584 Captured[side][gold] = atoi(InPtr);
585 skip();
586 Captured[side][bishop] = atoi(InPtr);
587 skip();
588 Captured[side][rook] = atoi(InPtr);
589 skip();
590 Captured[side][king] = atoi(InPtr);
593 GameCnt = 0;
594 flag.regularstart = true;
595 Book = BOOKFAIL;
596 fgets(fname, 256, fd); /* empty */
597 fgets(fname, 256, fd); /* move score ... */
599 while (fgets(fname, 256, fd))
601 struct GameRec *g;
602 int side = computer;
604 side = side ^ 1;
605 ++GameCnt;
606 InPtr = fname;
607 skipb();
608 g = &GameList[GameCnt];
609 g->gmove = parser(InPtr, &g->fpiece);
610 skip();
611 g->score = atoi(InPtr);
612 skip();
613 g->depth = atoi(InPtr);
614 skip();
615 g->nodes = atol(InPtr);
616 skip();
617 g->time = atol(InPtr);
618 skip();
619 g->flags = c = atoi(InPtr);
620 skip();
621 g->hashkey = strtol(InPtr, (char **) NULL, 16);
622 skip();
623 g->hashbd = strtol(InPtr, (char **) NULL, 16);
625 if (c & capture)
627 short i, piece;
629 skip();
631 for (piece = no_piece, i = 0; i < NO_PIECES; i++)
633 if (pxx[i] == *InPtr)
635 piece = i;
636 break;
640 skip();
641 g->color = ((*InPtr == 'W') ? white : black);
642 skip();
643 g->piece = (*InPtr == '+'
644 ? promoted[piece]
645 : unpromoted[piece]);
647 else
649 g->color = neutral;
650 g->piece = no_piece;
654 if (TimeControl.clock[black] > 0)
655 TCflag = true;
657 fclose(fd);
660 ZeroRPT();
661 InitializeStats();
662 dsp->UpdateDisplay(0, 0, 1, 0);
663 Sdepth = 0;
664 hint = 0;
668 static void
669 SaveGame(void)
671 FILE *fd;
672 char fname[256];
673 short sq, i, c, f, t;
674 char p;
675 short side, piece;
676 char empty[2] = "\n";
678 if (savefile[0]) {
679 strcpy(fname, savefile);
680 } else {
681 dsp->ShowMessage("Enter file name: ");
682 RequestInputString(fname, sizeof(fname)-1);
685 if (fname[0] == '\0')
686 strcpy(fname, "shogi.000");
688 if ((fd = fopen(fname, "w")) != NULL)
690 char *b, *w;
691 b = w = "Human ";
693 if (computer == white)
694 w = "computer";
696 if (computer == black)
697 b = "computer";
699 fprintf(fd, "White %s Black %s %d %s\n", w, b, Game50,
700 flag.force ? "force" : "");
701 fputs(empty, fd);
702 fprintf(fd, "TimeControl %d Operator Time %d\n", TCflag, OperatorTime);
703 fprintf(fd, "Black Clock %ld Moves %d\nWhite Clock %ld Moves %d\n",
704 TimeControl.clock[black], TimeControl.moves[black],
705 TimeControl.clock[white], TimeControl.moves[white]);
706 fputs(empty, fd);
708 for (i = NO_ROWS - 1; i > -1; i--)
710 fprintf(fd, "%c ", ROW_NAME(i));
712 for (c = 0; c < NO_COLS; c++)
714 sq = i * NO_COLS + c;
715 piece = board[sq];
716 p = is_promoted[piece] ? '+' : ' ';
717 fprintf(fd, "%c", p);
719 switch(color[sq])
721 case white:
722 p = pxx[piece];
723 break;
725 case black:
726 p = qxx[piece];
727 break;
729 default:
730 p = '-';
733 fprintf(fd, "%c", p);
736 fprintf(fd, " ");
738 for (f = i * NO_COLS; f < i * NO_COLS + NO_ROWS; f++)
739 fprintf(fd, " %d", Mvboard[f]);
741 fprintf(fd, "\n");
744 fputs(empty, fd);
745 #ifndef MINISHOGI
746 fprintf(fd, " 9 8 7 6 5 4 3 2 1\n");
747 fputs(empty, fd);
748 fprintf(fd, " p l n s g b r k\n");
749 #else
750 fprintf(fd, " 5 4 3 2 1\n");
751 fputs(empty, fd);
752 fprintf(fd, " p s g b r k\n");
753 #endif
755 for (side = 0; side <= 1; side++)
757 fprintf(fd, "%c", (side == black) ? 'B' : 'W');
758 fprintf(fd, " %2d", Captured[side][pawn]);
759 #ifndef MINISHOGI
760 fprintf(fd, " %2d", Captured[side][lance]);
761 fprintf(fd, " %2d", Captured[side][knight]);
762 #endif
763 fprintf(fd, " %2d", Captured[side][silver]);
764 fprintf(fd, " %2d", Captured[side][gold]);
765 fprintf(fd, " %2d", Captured[side][bishop]);
766 fprintf(fd, " %2d", Captured[side][rook]);
767 fprintf(fd, " %2d", Captured[side][king]);
768 fprintf(fd, "\n");
771 fputs(empty, fd);
772 fputs(" move score depth nodes time flags capture\n", fd);
774 for (i = 1; i <= GameCnt; i++)
776 struct GameRec *g = &GameList[i];
778 f = g->gmove >> 8;
779 t = (g->gmove & 0xFF);
780 algbr(f, t, g->flags);
782 fprintf(fd, "%c%c%-5s %6d %5d %7ld %6ld %5d 0x%08lx 0x%08lx",
783 ((f > NO_SQUARES)
784 ? ' '
785 : (is_promoted[g->fpiece] ? '+' : ' ')),
786 pxx[g->fpiece],
787 ((f > NO_SQUARES) ? &mvstr[0][1] : mvstr[0]),
788 g->score, g->depth,
789 g->nodes, g->time, g->flags,
790 g->hashkey, g->hashbd);
792 if (g->piece != no_piece)
794 fprintf(fd, " %c %s %c\n",
795 pxx[g->piece], ColorStr[g->color],
796 (is_promoted[g->piece] ? '+' : ' '));
798 else
800 fprintf(fd, "\n");
804 fclose(fd);
806 dsp->ShowMessage("Game saved");
808 else
810 dsp->ShowMessage("Could not open file");
816 * GetXGame, SaveXGame and BookGame used to only be defined if
817 * xshogi wasn't defined -- wonder why?
820 static void
821 GetXGame(void)
823 FILE *fd;
824 char fname[256], *p;
825 int c, i, j;
826 short sq;
827 short side, isp;
829 dsp->ShowMessage("Enter file name: ");
830 RequestInputString(fname, sizeof(fname)-1);
832 if (fname[0] == '\0')
833 strcpy(fname, "xshogi.position.read");
835 if ((fd = fopen(fname, "r")) != NULL)
837 NewGame();
838 flag.regularstart = false;
839 Book = false;
841 /* xshogi position file ... */
842 fgets(fname, 256, fd);
844 #ifdef notdef
845 fname[6] = '\0';
847 if (strcmp(fname, "xshogi"))
848 return;
849 #endif
851 /* -- empty line -- */
852 fgets(fname, 256, fd);
853 /* -- empty line -- */
854 fgets(fname, 256, fd);
856 for (i = NO_ROWS - 1; i > -1; i--)
858 fgets(fname, 256, fd);
859 p = fname;
861 for (j = 0; j < NO_COLS; j++)
863 sq = i * NO_COLS + j;
864 isp = (*p == '+');
865 p++;
867 if (*p == '.')
869 board[sq] = no_piece;
870 color[sq] = neutral;
872 else
874 for (c = 0; c < NO_PIECES; c++)
876 if (*p == qxx[c])
878 if (isp)
879 board[sq] = promoted[c];
880 else
881 board[sq] = unpromoted[c];
883 color[sq] = white;
887 for (c = 0; c < NO_PIECES; c++)
889 if (*p == pxx[c])
891 if (isp)
892 board[sq] = promoted[c];
893 else
894 board[sq] = unpromoted[c];
896 color[sq] = black;
901 p++;
905 ClearCaptured();
907 for (side = 0; side <= 1; side++)
909 fgets(fname, 256, fd);
910 InPtr = fname;
911 Captured[side][pawn] = atoi(InPtr);
912 skip();
913 #ifndef MINISHOGI
914 Captured[side][lance] = atoi(InPtr);
915 skip();
916 Captured[side][knight] = atoi(InPtr);
917 skip();
918 #endif
919 Captured[side][silver] = atoi(InPtr);
920 skip();
921 Captured[side][gold] = atoi(InPtr);
922 skip();
923 Captured[side][bishop] = atoi(InPtr);
924 skip();
925 Captured[side][rook] = atoi(InPtr);
926 skip();
927 Captured[side][king] = atoi(InPtr);
930 if (fgets(fname, 256, fd) != NULL && strncmp(fname, "white", 5) == 0)
932 computer = black;
933 opponent = white;
934 xwndw = BXWNDW;
937 fclose(fd);
940 Game50 = 1;
941 ZeroRPT();
942 InitializeStats();
943 dsp->UpdateDisplay(0, 0, 1, 0);
944 Sdepth = 0;
945 hint = 0;
949 static void
950 SaveXGame(void)
952 FILE *fd;
953 char fname[256], *p;
954 int i, j;
955 short sq, piece;
956 short side, isp;
958 dsp->ShowMessage("Enter file name: ");
959 RequestInputString(fname, sizeof(fname)-1);
961 if (fname[0] == '\0')
962 strcpy(fname, "xshogi.position.read");
964 if ((fd = fopen(fname, "w")) != NULL)
966 fputs("# xshogi position file -- \n", fd);
967 fputs("\n", fd);
968 fputs("\n", fd);
970 for (i = NO_ROWS - 1; i > -1; i--)
972 p = fname;
974 for (j = 0; j < NO_COLS; j++)
976 sq = i * NO_COLS + j;
977 piece = board[sq];
978 isp = is_promoted[piece];
979 *p = (isp ? '+' : ' ');
980 p++;
982 if (piece == no_piece)
983 *p = '.';
984 else if (color[sq] == white)
985 *p = qxx[piece];
986 else
987 *p = pxx[piece];
989 p++;
992 *p++ = '\n';
993 *p++ = '\0';
994 fputs(fname, fd);
997 for (side = 0; side <= 1; side++)
999 sprintf(fname,
1000 #ifndef MINISHOGI
1001 "%d %d %d %d %d %d %d %d\n",
1002 #else
1003 "%d %d %d %d %d %d\n",
1004 #endif
1005 Captured[side][pawn],
1006 #ifndef MINISHOGI
1007 Captured[side][lance],
1008 Captured[side][knight],
1009 #endif
1010 Captured[side][silver],
1011 Captured[side][gold],
1012 Captured[side][bishop],
1013 Captured[side][rook],
1014 Captured[side][king]);
1016 fputs(fname, fd);
1019 if (computer == black)
1020 fputs("white to play\n", fd);
1021 else
1022 fputs("black to play\n", fd);
1024 fclose(fd);
1029 static void
1030 BookSave(void)
1032 FILE *fd;
1033 char fname[256], sflags[4];
1034 short i, j, f, t;
1036 if (savefile[0]) {
1037 strcpy(fname, savefile);
1038 } else {
1039 /* Enter file name */
1040 dsp->ShowMessage("Enter file name: ");
1041 RequestInputString(fname, sizeof(fname)-1);
1044 if (fname[0] == '\0') {
1045 dsp->AlwaysShowMessage("aborting book save");
1046 return;
1049 if ((fd = fopen(fname, "a")) != NULL)
1051 fprintf(fd, "#\n");
1053 for (i = 1; i <= GameCnt; i++)
1055 struct GameRec *g = &GameList[i];
1056 char mvnr[20], mvs[20];
1058 if (i % 2)
1059 sprintf(mvnr, "%d.", (i + 1)/2);
1060 else
1061 strcpy(mvnr, "");
1063 f = g->gmove >> 8;
1064 t = (g->gmove & 0xFF);
1065 algbr(f, t, g->flags);
1066 j = 0;
1068 /* determine move quality string */
1069 if (g->flags & goodmove)
1070 sflags[j++] = '!';
1072 if (g->flags & badmove)
1073 sflags[j++] = '?';
1075 #ifdef EASY_OPENINGS
1076 if (g->flags & difficult)
1077 sflags[j++] = '~';
1078 #endif
1080 sflags[j] = '\0';
1082 /* determine move string */
1083 if (f > NO_SQUARES)
1085 sprintf(mvs, "%s%s ", &mvstr[0][1], sflags);
1087 else
1089 sprintf(mvs, "%c%c%c%c%c%s%s ",
1090 mvstr[0][0], mvstr[0][1],
1091 (g->flags & capture) ? 'x' : '-',
1092 mvstr[0][2], mvstr[0][3],
1093 (mvstr[0][4] == '+') ? "+" : "",
1094 sflags);
1097 fprintf(fd, "%s%s%c%s",
1098 mvnr,
1099 (f > NO_SQUARES
1100 ? ""
1101 : (is_promoted[g->fpiece] ? "+" : "")),
1102 pxx[g->fpiece],
1103 mvs);
1105 if ((i % 10) == 0)
1106 fprintf(fd, "\n");
1109 if ((i % 10) != 1)
1110 fprintf(fd, "\n");
1112 fclose(fd);
1114 dsp->ShowMessage("Game saved");
1116 else
1118 dsp->ShowMessage("Could not open file");
1123 void
1124 ListGame(void)
1126 FILE *fd;
1127 short i, f, t;
1128 time_t when;
1129 char fname[256], dbuf[256];
1131 if (listfile[0])
1133 strcpy(fname, listfile);
1135 else
1137 time(&when);
1138 strncpy(dbuf, ctime(&when), 20);
1139 dbuf[7] = '\0';
1140 dbuf[10] = '\0';
1141 dbuf[13] = '\0';
1142 dbuf[16] = '\0';
1143 dbuf[19] = '\0';
1145 /* use format "CL.Jan01-020304B" when
1146 date is Jan 1
1147 time is 02:03:04
1148 program played white */
1150 sprintf(fname, "CL.%s%s-%s%s%s%c",
1151 dbuf + 4, dbuf + 8, dbuf + 11, dbuf + 14,
1152 dbuf + 17, ColorStr[computer][0]);
1154 /* replace space padding with 0 */
1155 for (i = 0; fname[i] != '\0'; i++)
1157 if (fname[i] == ' ')
1158 fname[i] = '0';
1162 fd = fopen(fname, "w");
1164 if (!fd)
1166 printf("Open failure for file: %s", fname);
1167 exit(1);
1170 fprintf(fd, "gnushogi %s game\n", PACKAGE_VERSION);
1171 fputs(" score depth nodes time ", fd);
1172 fputs(" score depth nodes time\n", fd);
1174 for (i = 1; i <= GameCnt; i++)
1176 f = GameList[i].gmove >> 8;
1177 t = (GameList[i].gmove & 0xFF);
1178 algbr(f, t, GameList[i].flags);
1180 if (GameList[i].flags & book)
1182 fprintf(fd, "%c%c%-5s %5d Book%7ld %5ld",
1183 ((f > NO_SQUARES)
1184 ? ' '
1185 : (is_promoted[GameList[i].fpiece] ? '+' : ' ')),
1186 pxx[GameList[i].fpiece],
1187 ((f > NO_SQUARES)
1188 ? &mvstr[0][1] : mvstr[0]),
1189 GameList[i].score,
1190 GameList[i].nodes,
1191 GameList[i].time);
1193 else
1195 fprintf(fd, "%c%c%-5s %5d %2d %7ld %5ld",
1196 (f > NO_SQUARES
1197 ? ' '
1198 : (is_promoted[GameList[i].fpiece] ? '+' : ' ')),
1199 pxx[GameList[i].fpiece],
1200 (f > NO_SQUARES ? &mvstr[0][1] : mvstr[0]),
1201 GameList[i].score, GameList[i].depth,
1202 GameList[i].nodes, GameList[i].time);
1205 if ((i % 2) == 0)
1207 fprintf(fd, "\n");
1209 else
1211 fprintf(fd, " ");
1215 fprintf(fd, "\n\n");
1217 if (GameList[GameCnt].flags & draw)
1219 fprintf(fd, "Draw %s\n", DRAW);
1221 if (DRAW == DRAW_REPETITION)
1223 short j;
1225 fprintf(fd, "repetition by positions ");
1227 for (j = GameCnt - 1; j >= Game50; j -= 2)
1229 if (GameList[j].hashkey == hashkey &&
1230 GameList[j].hashbd == hashbd)
1231 fprintf(fd, "%d ", j);
1234 fprintf(fd, "\n");
1237 else if (GameList[GameCnt].score == -(SCORE_LIMIT + 999))
1239 fprintf(fd, "%s\n", ColorStr[player ]);
1241 else if (GameList[GameCnt].score == (SCORE_LIMIT + 998))
1243 fprintf(fd, "%s\n", ColorStr[player ^ 1]);
1246 fclose(fd);
1250 static void
1251 FlagMove(char c)
1253 switch(c)
1255 case '?' :
1256 GameList[GameCnt].flags |= badmove;
1257 break;
1259 case '!' :
1260 GameList[GameCnt].flags |= goodmove;
1261 break;
1263 #ifdef EASY_OPENINGS
1264 case '~' :
1265 GameList[GameCnt].flags |= difficult;
1266 break;
1267 #endif
1273 * Undo the most recent half-move.
1276 static void
1277 Undo(void)
1279 short f, t;
1281 f = GameList[GameCnt].gmove >> 8;
1282 t = GameList[GameCnt].gmove & 0x7F;
1284 if (f > NO_SQUARES)
1286 /* the move was a drop */
1287 Captured[color[t]][board[t]]++;
1288 board[t] = no_piece;
1289 color[t] = neutral;
1290 Mvboard[t]--;
1292 else
1294 if (GameList[GameCnt].flags & promote)
1295 board[f] = unpromoted[board[t]];
1296 else
1297 board[f] = board[t];
1299 color[f] = color[t];
1300 board[t] = GameList[GameCnt].piece;
1301 color[t] = GameList[GameCnt].color;
1303 if (board[t] != no_piece)
1304 Captured[color[f]][unpromoted[board[t]]]--;
1306 if (color[t] != neutral)
1307 Mvboard[t]--;
1309 Mvboard[f]--;
1312 InitializeStats();
1314 if (TCflag && (TCmoves > 1))
1315 ++TimeControl.moves[color[f]];
1317 hashkey = GameList[GameCnt].hashkey;
1318 hashbd = GameList[GameCnt].hashbd;
1319 GameCnt--;
1320 computer = computer ^ 1;
1321 opponent = opponent ^ 1;
1322 flag.mate = false;
1323 Sdepth = 0;
1324 player = player ^ 1;
1325 dsp->ShowSidetoMove();
1326 dsp->UpdateDisplay(0, 0, 1, 0);
1328 if (flag.regularstart)
1329 Book = false;
1333 static void
1334 TestSpeed(void(*f)(short side, short ply,
1335 short in_check, short blockable),
1336 unsigned j)
1338 #ifdef test
1339 unsigned jj;
1340 #endif
1342 unsigned i;
1343 long cnt, t1, t2;
1345 #ifdef HAVE_GETTIMEOFDAY
1346 struct timeval tv;
1347 #endif
1349 #ifdef HAVE_GETTIMEOFDAY
1350 gettimeofday(&tv, NULL);
1351 t1 = (tv.tv_sec*100 + (tv.tv_usec/10000));
1352 #else
1353 t1 = time(0);
1354 #endif
1356 for (i = 0; i < j; i++)
1358 f(opponent, 2, -1, true);
1360 #ifdef test
1361 for (jj = TrPnt[2]; i < TrPnt[3]; jj++)
1363 if (!pick(jj, TrPnt[3] - 1))
1364 break;
1366 #endif
1369 #ifdef HAVE_GETTIMEOFDAY
1370 gettimeofday(&tv, NULL);
1371 t2 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1372 #else
1373 t2 = time(0);
1374 #endif
1376 cnt = j * (TrPnt[3] - TrPnt[2]);
1378 if (t2 - t1)
1379 et = (t2 - t1);
1380 else
1381 et = 1;
1383 dsp->ShowNodeCnt(cnt);
1387 static void
1388 TestPSpeed(short(*f) (short side), unsigned j)
1390 unsigned i;
1391 long cnt, t1, t2;
1392 #ifdef HAVE_GETTIMEOFDAY
1393 struct timeval tv;
1394 #endif
1396 #ifdef HAVE_GETTIMEOFDAY
1397 gettimeofday(&tv, NULL);
1398 t1 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1399 #else
1400 t1 = time(0);
1401 #endif
1403 for (i = 0; i < j; i++)
1404 (void) f(opponent);
1406 #ifdef HAVE_GETTIMEOFDAY
1407 gettimeofday(&tv, NULL);
1408 t2 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1409 #else
1410 t2 = time(0);
1411 #endif
1413 cnt = j;
1415 if (t2 - t1)
1416 et = (t2 - t1);
1417 else
1418 et = 1;
1420 dsp->ShowNodeCnt(cnt);
1424 static void
1425 SetOppTime(char *time)
1427 int m, t;
1429 t = (int)strtol(time, &time, 10);
1431 if (*time == ':')
1433 time++;
1434 /* FIXME: sec is parsed but ignored */
1435 (void)strtol(time, &time, 10);
1438 m = (int)strtol(time, &time, 10);
1440 if (t)
1441 TimeControl.clock[opponent] = t;
1443 if (m)
1444 TimeControl.moves[opponent] = m;
1446 ElapsedTime(COMPUTE_AND_INIT_MODE);
1448 if (XSHOGI)
1450 /* just to inform xshogi about availability of otime command */
1451 printf("otime %d %d\n", t, m);
1456 static void
1457 SetMachineTime(char *time)
1459 int m, t;
1461 t = (int)strtol(time, &time, 10);
1463 if (*time == ':')
1465 time++;
1466 /* FIXME: sec is parsed but ignored */
1467 (void)strtol(time, &time, 10);
1470 m = (int)strtol(time, &time, 10);
1472 if (t)
1473 TimeControl.clock[computer] = t;
1475 if (m)
1476 TimeControl.moves[computer] = m;
1478 ElapsedTime(COMPUTE_AND_INIT_MODE);
1480 if (XSHOGI)
1482 /* just to inform xshogi about availability of time command */
1483 printf("time %d %d\n", t, m);
1488 /* FIXME! This is truly the function from hell! */
1491 * Process the user's command. If easy mode is OFF (the computer is thinking
1492 * on opponents time) and the program is out of book, then make the 'hint'
1493 * move on the board and call SelectMove() to find a response. The user
1494 * terminates the search by entering a command. If the opponent does not make
1495 * the hint move, then set Sdepth to zero.
1498 void
1499 InputCommand(char *command)
1501 #ifdef QUIETBACKGROUND
1502 short have_shown_prompt = false;
1503 #endif
1504 short ok, done, is_move = false;
1505 unsigned short mv;
1506 char s[80], sx[80];
1508 ok = flag.quit = done = false;
1509 player = opponent;
1511 #if ttblsz
1512 if (TTadd > ttbllimit)
1513 ZeroTTable();
1514 #endif
1516 if ((hint > 0) && !flag.easy && !flag.force)
1519 * A hint move for the player is available. Compute a move for the
1520 * opponent in background mode assuming that the hint move will be
1521 * selected by the player.
1524 ft = time0; /* Save reference time for the player. */
1525 fflush(stdout);
1526 algbr((short) hint >> 8, (short) hint & 0xff, 0);
1527 strcpy(s, mvstr[0]);
1529 if (flag.post)
1530 dsp->GiveHint();
1532 /* do the hint move */
1533 if (VerifyMove(s, VERIFY_AND_TRY_MODE, &mv))
1535 Sdepth = 0;
1537 #ifdef QUIETBACKGROUND
1538 dsp->ShowPrompt();
1539 have_shown_prompt = true;
1540 #endif /* QUIETBACKGROUND */
1542 /* Start computing a move until the search is interrupted. */
1544 #ifdef INTERRUPT_TEST
1545 itime0 = 0;
1546 #endif
1548 /* would love to put null move in here */
1549 /* after we make the hint move make a 2 ply search
1550 * with both plys our moves */
1551 /* think on opponents time */
1552 SelectMove(computer, BACKGROUND_MODE);
1554 #ifdef INTERRUPT_TEST
1555 ElapsedTime(COMPUTE_INTERRUPT_MODE);
1557 if (itime0 == 0)
1559 printf("searching not terminated by interrupt!\n");
1561 else
1563 printf("elapsed time from interrupt to "
1564 "terminating search: %ld\n", it);
1566 #endif
1568 /* undo the hint and carry on */
1569 VerifyMove(s, UNMAKE_MODE, &mv);
1570 Sdepth = 0;
1573 time0 = ft; /* Restore reference time for the player. */
1576 while(!(ok || flag.quit || done))
1578 player = opponent;
1580 #ifdef QUIETBACKGROUND
1581 if (!have_shown_prompt)
1583 #endif /* QUIETBACKGROUND */
1585 dsp->ShowPrompt();
1587 #ifdef QUIETBACKGROUND
1590 have_shown_prompt = false;
1591 #endif /* QUIETBACKGROUND */
1593 if (command == NULL) {
1594 int eof = dsp->GetString(sx);
1595 if (eof)
1596 dsp->ExitShogi();
1597 } else {
1598 strcpy(sx, command);
1599 done = true;
1602 /* extract first word */
1603 if (sscanf(sx, "%s", s) < 1)
1604 continue;
1606 if (strcmp(s, "bd") == 0) /* bd -- display board */
1608 /* FIXME: Hack alert! */
1609 short old_xshogi = XSHOGI;
1611 if (old_xshogi)
1612 display_type = DISPLAY_RAW;
1614 dsp->ClearScreen();
1615 dsp->UpdateDisplay(0, 0, 1, 0);
1617 if (old_xshogi)
1618 display_type = DISPLAY_X;
1620 else if (strcmp(s, "post") == 0)
1622 flag.post = (xboard ? 1 : !flag.post);
1624 else if (strcmp(s, "nopost") == 0)
1626 flag.post = 0;
1628 #ifdef MINISHOGI
1629 else if (strcmp(s, "variant") == 0)
1630 { /* only variant we play is minishogi */
1631 printf("setup (P.BR.S...G.+.++.+Kp.br.s...g.+.++.+k) 5x5+5_shogi rbsgk/4p/5/P4/KGSBR [-] w 0 1\n");
1633 #endif
1634 else if (strcmp(s, "alg") == 0 ||
1635 strcmp(s, "accepted") == 0 || strcmp(s, "rejected") == 0 ||
1636 strcmp(s, "variant") == 0 || strcmp(s, "computer") == 0)
1638 /* noop */ ;
1640 else if ((strcmp(s, "quit") == 0) ||
1641 (strcmp(s, "exit") == 0))
1643 flag.quit = true;
1645 else if (strcmp(s, "xboard") == 0)
1647 if (!xboard) {
1648 /* xboard calls Sente "White" */
1649 const char *tmp = ColorStr[0];
1650 ColorStr[0] = ColorStr[1];
1651 ColorStr[1] = tmp;
1652 xboard = true;
1655 else if (strcmp(s, "protover") == 0)
1657 printf("feature option=\"tsume -check 0\"\n");
1658 printf("feature option=\"Use hash-file -check %d\"\n", !!flag.hash);
1659 printf("feature option=\"contempt -spin %d -1000 1000\"\n", contempt);
1660 printf("feature option=\"Hash-file search depth -spin %d 0 100\"\n", HashDepth);
1661 printf("feature option=\"Hash-file move number -spin %d 0 100\"\n", HashMoveLimit);
1662 printf("feature myname=\"GNU %s %s\" ",
1663 #ifdef MINISHOGI
1664 "MiniShogi",
1665 #else
1666 "Shogi",
1667 #endif
1668 PACKAGE_VERSION
1670 printf("variants=\"%s\" ",
1671 #ifdef MINISHOGI
1672 "5x5+5_shogi,minishogi"
1673 #else
1674 "shogi"
1675 #endif
1677 printf("debug=1 setboard=0 sigint=0 usermove=1 done=1\n");
1679 else if ((strcmp(s, "set") == 0) ||
1680 (strcmp(s, "edit") == 0))
1682 dsp->EditBoard();
1684 else if (strcmp(s, "setup") == 0)
1686 dsp->SetupBoard();
1688 else if (strcmp(s, "first") == 0)
1690 ok = true;
1692 else if (strcmp(s, "go") == 0)
1694 ok = true;
1695 flag.force = false;
1697 if (computer == black)
1699 computer = white;
1700 opponent = black;
1702 else
1704 computer = black;
1705 opponent = white;
1708 else if (strcmp(s, "help") == 0)
1710 dsp->help();
1712 else if (strcmp(s, "material") == 0)
1714 flag.material = !flag.material;
1716 else if (strcmp(s, "force") == 0)
1718 if (XSHOGI)
1720 flag.force = true;
1721 flag.bothsides = false;
1723 else
1725 flag.force = !flag.force;
1726 flag.bothsides = false;
1729 else if (strcmp(s, "book") == 0)
1731 Book = Book ? 0 : BOOKFAIL;
1733 else if (strcmp(s, "new") == 0)
1735 NewGame();
1736 dsp->UpdateDisplay(0, 0, 1, 0);
1738 else if (strcmp(s, "list") == 0)
1740 ListGame();
1742 else if (strcmp(s, "level") == 0)
1744 dsp->SelectLevel(sx + strlen("level"));
1746 else if (strcmp(s, "clock") == 0)
1748 dsp->SelectLevel(sx + strlen("clock"));
1750 else if (strcmp(s, "hash") == 0)
1752 flag.hash = !flag.hash;
1754 else if (strcmp(s, "gamein") == 0)
1756 flag.gamein = !flag.gamein;
1758 else if (strcmp(s, "beep") == 0)
1760 flag.beep = !flag.beep;
1762 else if (strcmp(s, "time") == 0)
1764 SetMachineTime(sx + strlen("time"));
1766 else if ((strcmp(s, "otime") == 0) ||
1767 (xboard && (strcmp(s, "otim")) == 0))
1769 SetOppTime(sx + strlen("otime"));
1771 else if (strcmp(s, "Awindow") == 0)
1773 dsp->ChangeAlphaWindow();
1775 else if (strcmp(s, "Bwindow") == 0)
1777 dsp->ChangeBetaWindow();
1779 else if (strcmp(s, "rcptr") == 0)
1781 flag.rcptr = !flag.rcptr;
1783 else if (strcmp(s, "hint") == 0)
1785 dsp->GiveHint();
1787 else if (strcmp(s, "both") == 0)
1789 flag.bothsides = !flag.bothsides;
1790 flag.force = false;
1791 Sdepth = 0;
1792 ElapsedTime(COMPUTE_AND_INIT_MODE);
1793 SelectMove(opponent, FOREGROUND_MODE);
1794 ok = true;
1796 else if (strcmp(s, "reverse") == 0)
1798 flag.reverse = !flag.reverse;
1799 dsp->ClearScreen();
1800 dsp->UpdateDisplay(0, 0, 1, 0);
1802 else if (strcmp(s, "switch") == 0)
1804 computer = computer ^ 1;
1805 opponent = opponent ^ 1;
1806 xwndw = (computer == black) ? WXWNDW : BXWNDW;
1807 flag.force = false;
1808 Sdepth = 0;
1809 ok = true;
1810 dsp->UpdateDisplay(0, 0, 1, 0);
1812 else if (xboard ? strcmp(s, "white") == 0 : strcmp(s, "black") == 0)
1814 computer = white;
1815 opponent = black;
1816 xwndw = WXWNDW;
1817 flag.force = false;
1818 Sdepth = 0;
1821 * ok = true; don't automatically start with black command
1824 else if (xboard ? strcmp(s, "black") == 0 : strcmp(s, "white") == 0)
1826 computer = black;
1827 opponent = white;
1828 xwndw = BXWNDW;
1829 flag.force = false;
1830 Sdepth = 0;
1833 * ok = true; don't automatically start with white command
1836 else if (strcmp(s, "undo") == 0 && GameCnt > 0)
1838 Undo();
1840 else if (strcmp(s, "remove") == 0 && GameCnt > 1)
1842 Undo();
1843 Undo();
1845 /* CHECKME: are these next three correct? */
1846 else if (!XSHOGI && strcmp(s, "xget") == 0)
1848 GetXGame();
1850 else if (!XSHOGI && strcmp(s, "xsave") == 0)
1852 SaveXGame();
1854 else if (!XSHOGI && strcmp(s, "bsave") == 0)
1856 BookSave();
1858 #ifdef EASY_OPENINGS
1859 else if ((strcmp(s, "?") == 0) ||
1860 (strcmp(s, "!") == 0) ||
1861 (strcmp(s, "~") == 0))
1862 #else
1863 else if ((strcmp(s, "?") == 0) ||
1864 (strcmp(s, "!") == 0))
1865 #endif
1867 FlagMove(*s);
1869 else if (strcmp(s, "get") == 0)
1871 GetGame();
1873 else if (strcmp(s, "save") == 0)
1875 SaveGame();
1877 else if (strcmp(s, "depth") == 0)
1879 dsp->ChangeSearchDepth(sx + strlen("depth"));
1881 else if (strcmp(s, "sd") == 0)
1883 dsp->ChangeSearchDepth(sx + strlen("sd"));
1885 else if (strcmp(s, "hashdepth") == 0)
1887 dsp->ChangeHashDepth();
1889 else if (strcmp(s, "random") == 0)
1891 dither = DITHER;
1893 else if (strcmp(s, "hard") == 0)
1895 flag.easy = false;
1897 else if (strcmp(s, "easy") == 0)
1899 flag.easy = !flag.easy;
1901 else if (strcmp(s, "option") == 0)
1903 do {
1904 if (sscanf(sx, "option tsume=%hd", &flag.tsume) == 1)
1905 break;
1906 if (sscanf(sx, "option Use hash-file=%hd", &flag.hash) == 1)
1907 break;
1908 if (sscanf(sx, "option Hash-file search depth=%hd", &HashDepth) == 1)
1909 break;
1910 if (sscanf(sx, "option Hash-file move number=%hd", &HashMoveLimit) == 1)
1911 break;
1912 if (sscanf(sx, "option contempt=%hd", &contempt) == 1)
1913 break;
1914 dsp->AlwaysShowMessage("Unknown '%s'", sx);
1915 } while(0);
1917 else if (strcmp(s, "tsume") == 0)
1919 flag.tsume = !flag.tsume;
1921 else if (strcmp(s, "contempt") == 0)
1923 dsp->SetContempt();
1925 else if (strcmp(s, "xwndw") == 0)
1927 dsp->ChangeXwindow();
1929 else if (strcmp(s, "rv") == 0)
1931 flag.rv = !flag.rv;
1932 dsp->UpdateDisplay(0, 0, 1, 0);
1934 else if (strcmp(s, "coords") == 0)
1936 flag.coords = !flag.coords;
1937 dsp->UpdateDisplay(0, 0, 1, 0);
1939 else if (strcmp(s, "stars") == 0)
1941 flag.stars = !flag.stars;
1942 dsp->UpdateDisplay(0, 0, 1, 0);
1944 else if (!XSHOGI && strcmp(s, "moves") == 0)
1946 short temp;
1948 #if MAXDEPTH > 3
1949 if (GameCnt > 0)
1951 extern unsigned short PrVar[MAXDEPTH];
1953 SwagHt = (GameList[GameCnt].gmove == PrVar[1])
1954 ? PrVar[2] : 0;
1956 else
1957 #endif
1958 SwagHt = 0;
1960 dsp->ShowMessage("Testing MoveList Speed");
1961 temp = generate_move_flags;
1962 generate_move_flags = true;
1963 TestSpeed(MoveList, 1);
1964 generate_move_flags = temp;
1965 dsp->ShowMessage("Testing CaptureList Speed");
1966 TestSpeed(CaptureList, 1);
1967 dsp->ShowMessage("Testing Eval Speed");
1968 ExaminePosition(opponent);
1969 TestPSpeed(ScorePosition, 1);
1971 else if (!XSHOGI && strcmp(s, "test") == 0)
1973 #ifdef SLOW_CPU
1974 dsp->ShowMessage("Testing MoveList Speed");
1975 TestSpeed(MoveList, 2000);
1976 dsp->ShowMessage("Testing CaptureList Speed");
1977 TestSpeed(CaptureList, 3000);
1978 dsp->ShowMessage("Testing Eval Speed");
1979 ExaminePosition(opponent);
1980 TestPSpeed(ScorePosition, 1500);
1981 #else
1982 dsp->ShowMessage("Testing MoveList Speed");
1983 TestSpeed(MoveList, 20000);
1984 dsp->ShowMessage("Testing CaptureList Speed");
1985 TestSpeed(CaptureList, 30000);
1986 dsp->ShowMessage("Testing Eval Speed");
1987 ExaminePosition(opponent);
1988 TestPSpeed(ScorePosition, 15000);
1989 #endif
1991 else if (!XSHOGI && strcmp(s, "p") == 0)
1993 dsp->ShowPostnValues();
1995 else if (!XSHOGI && strcmp(s, "debug") == 0)
1997 dsp->DoDebug();
1999 else
2001 if (strcmp(s, "usermove") == 0 && sx[8] == ' ')
2002 sscanf(sx + 9, "%s", s);
2004 if (flag.mate)
2006 ok = true;
2008 else if ((ok = VerifyMove(s, VERIFY_AND_MAKE_MODE, &mv)))
2010 /* check for repetition */
2011 short rpt = repetition();
2013 if (rpt >= 3)
2015 DRAW = DRAW_REPETITION;
2016 dsp->ShowMessage(DRAW);
2017 GameList[GameCnt].flags |= draw;
2019 flag.mate = true;
2021 else
2023 is_move = true;
2027 Sdepth = 0;
2031 ElapsedTime(COMPUTE_AND_INIT_MODE);
2033 if (flag.force)
2035 computer = opponent;
2036 opponent = computer ^ 1;
2039 if (XSHOGI)
2041 /* add remaining time in milliseconds for xshogi */
2042 if (is_move)
2044 printf("%d. %s %ld\n",
2045 ++mycnt2, s, TimeControl.clock[player] * 10);