a5a3b422ad2162f957120c5bc288d27607954dbe
[gnushogi.git] / gnushogi / commondsp.c
1 /*
2  * FILE: commondsp.c
3  *
4  *     Common display routines for GNU Shogi.
5  *
6  * ----------------------------------------------------------------------
7  * Copyright (c) 1993, 1994, 1995 Matthias Mutz
8  * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
9  *
10  * GNU SHOGI is based on GNU CHESS
11  *
12  * Copyright (c) 1988, 1989, 1990 John Stanback
13  * Copyright (c) 1992 Free Software Foundation
14  *
15  * This file is part of GNU SHOGI.
16  *
17  * GNU Shogi is free software; you can redistribute it and/or modify it
18  * under the terms of the GNU General Public License as published by the
19  * Free Software Foundation; either version 3 of the License,
20  * or (at your option) any later version.
21  *
22  * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
23  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
24  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25  * for more details.
26  *
27  * You should have received a copy of the GNU General Public License along
28  * with GNU Shogi; see the file COPYING. If not, see
29  * <http://www.gnu.org/licenses/>.
30  * ----------------------------------------------------------------------
31  *
32  */
33
34 #if defined HAVE_GETTIMEOFDAY
35 #include <sys/time.h>
36 #endif
37
38 #include <ctype.h>
39 #include <signal.h>
40
41 #include <sys/param.h>
42 #include <sys/types.h>
43 #include <sys/file.h>
44
45 #include "gnushogi.h"
46
47 char mvstr[4][6];
48 char *InPtr;
49 int InBackground = false;
50 struct display *dsp = &raw_display;
51
52
53 #if defined(BOOKTEST)
54
55 void
56 movealgbr(short m, char *s)
57 {
58     unsigned int f, t;
59     short piece = 0, flag = 0;
60
61     if (m == 0)
62     {
63         strcpy(s, "none");
64         return;
65     }
66
67     f = (m >> 8) & 0x7f;
68     t = m & 0xff;
69
70     if (f > NO_SQUARES)
71     {
72         piece = f - NO_SQUARES;
73
74         if (piece > NO_PIECES)
75             piece -= NO_PIECES;
76
77         flag = (dropmask | piece);
78     }
79
80     if (t & 0x80)
81     {
82         flag |= promote;
83         t &= 0x7f;
84     }
85
86     if (flag & dropmask)
87     {
88         *s = pxx[piece];
89         s++;
90         *s = '*';
91         s++;
92         *s = cxx[column(t)];
93         s++;
94         *s = rxx[row(t)];
95         s++;
96     }
97     else
98     {
99         *s = cxx[column(f)];
100         s++;
101         *s = rxx[row(f)];
102         s++;
103         *s = cxx[column(t)];
104         s++;
105         *s = rxx[row(t)];
106         s++;
107
108         if (flag & promote)
109         {
110             *s = '+';
111             s++;
112         }
113     }
114
115     if (m & 0x8000)
116     {
117         *s = '?';
118         s++;
119     }
120
121     *s = '\0';
122 }
123
124 #endif /* BOOKTEST */
125
126
127
128
129 /*
130  * Generate move strings in different formats.
131  *
132  * INPUT:
133  * - f                                  piece to be moved
134  *   - 0 < f < NO_SQUARES                               source square
135  *   - NO_SQUARES <= f NO_SQUARES + 2*NO_PIECES         dropped piece modulo NO_PIECES
136  * - t & 0x7f                           target square
137  * - t & 0x80                           promotion flag
138  * - flag                               FIXME: must be zero ?
139  *
140  * OUTPUT:
141  * - GLOBAL mvstr
142  */
143
144 void
145 algbr(short f, short t, short flag)
146 {
147     if (f > NO_SQUARES)
148     {
149         short piece;
150
151         piece = f - NO_SQUARES;
152
153         if (f > (NO_SQUARES + NO_PIECES))
154             piece -= NO_PIECES;
155
156         flag = (dropmask | piece);
157     }
158
159     if ((t & 0x80) != 0)
160     {
161         flag |= promote;
162         t &= 0x7f;
163     }
164
165     if ((f == t) && ((f != 0) || (t != 0)))
166     {
167         if (!barebones) {
168             dsp->Printf("error in algbr: FROM=TO=%d, flag=0x%4x\n", t, flag);
169         }
170
171         mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
172     }
173     else if ((flag & dropmask) != 0)
174     {
175         short piece = flag & pmask;
176
177         mvstr[0][0] = pxx[piece];
178         mvstr[0][1] = '*';
179         mvstr[0][2] = cxx[column(t)];
180         mvstr[0][3] = rxx[row(t)];
181         mvstr[0][4] = '\0';
182         strcpy(mvstr[1], mvstr[0]);
183         strcpy(mvstr[2], mvstr[0]);
184         strcpy(mvstr[3], mvstr[0]);
185     }
186     else if ((f != 0) || (t != 0))
187     {
188         /* algebraic notation */
189         mvstr[0][0] = cxx[column(f)];
190         mvstr[0][1] = rxx[row(f)];
191         mvstr[0][2] = cxx[column(t)];
192         mvstr[0][3] = rxx[row(t)];
193         mvstr[0][4] = mvstr[3][0] = '\0';
194         mvstr[1][0] = pxx[board[f]];
195
196         mvstr[2][0] = mvstr[1][0];
197         mvstr[2][1] = mvstr[0][1];
198
199         mvstr[2][2] = mvstr[1][1] = mvstr[0][2];    /* to column */
200         mvstr[2][3] = mvstr[1][2] = mvstr[0][3];    /* to row */
201         mvstr[2][4] = mvstr[1][3] = '\0';
202         strcpy(mvstr[3], mvstr[2]);
203         mvstr[3][1] = mvstr[0][0];
204
205         if (flag & promote)
206         {
207             strcat(mvstr[0], "+");
208             strcat(mvstr[1], "+");
209             strcat(mvstr[2], "+");
210             strcat(mvstr[3], "+");
211         }
212     }
213     else
214     {
215         mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
216     }
217 }
218
219
220
221 /*
222  * Compare the string 's' to the list of legal moves available for the
223  * opponent. If a match is found, make the move on the board.
224  */
225
226 int
227 VerifyMove(char *s, VerifyMove_mode iop, unsigned short *mv)
228 {
229     static short pnt, tempb, tempc, tempsf, tempst, cnt;
230     static struct leaf xnode;
231     struct leaf  *node;
232     short i, l, local_flags;
233     char buffer[60];
234
235     /* check and remove quality flags */
236     for (i = local_flags = 0, l = strlen(s); i < l; i++)
237     {
238         switch(s[i])
239         {
240         case '?':
241             local_flags |= badmove;
242             s[i] = '\0';
243             break;
244
245         case '!':
246             local_flags |= goodmove;
247             s[i] = '\0';
248             break;
249
250 #ifdef EASY_OPENINGS
251         case '~':
252             local_flags |= difficult;
253             s[i] = '\0';
254             break;
255 #endif
256         }
257     }
258
259     *mv = 0;
260
261     if (iop == UNMAKE_MODE)
262     {
263         UnmakeMove(opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
264         return false;
265     }
266
267     cnt = 0;
268
269     if (iop == VERIFY_AND_MAKE_MODE)
270         generate_move_flags = true;
271
272     MoveList(opponent, 2, -1, true);
273     generate_move_flags = false;
274     pnt = TrPnt[2];
275
276     while (pnt < TrPnt[3])
277     {
278         node = &Tree[pnt++];
279         algbr(node->f, node->t, (short) node->flags);
280
281         if ((strcmp(s, mvstr[0]) == 0)
282             || (strcmp(s, mvstr[1]) == 0)
283             || (strcmp(s, mvstr[2]) == 0)
284             || (strcmp(s, mvstr[3]) == 0))
285         {
286             cnt++;
287             xnode = *node;
288         }
289     }
290
291     if ((cnt == 1) && (xnode.score > DONTUSE))
292     {
293         short blocked;
294
295         MakeMove(opponent, &xnode, &tempb, &tempc,
296                  &tempsf, &tempst, &INCscore);
297
298         if (SqAttacked(PieceList[opponent][0], computer, &blocked))
299         {
300             UnmakeMove(opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
301             dsp->AlwaysShowMessage("Illegal move (in check) %s", s);
302             return false;
303         }
304         else
305         {
306             if (iop == VERIFY_AND_TRY_MODE)
307                 return true;
308
309             dsp->UpdateDisplay(xnode.f, xnode.t, 0, (short) xnode.flags);
310             GameList[GameCnt].depth = GameList[GameCnt].score = 0;
311             GameList[GameCnt].nodes = 0;
312             ElapsedTime(COMPUTE_AND_INIT_MODE);
313             GameList[GameCnt].time = (short) (et + 50)/100;
314             GameList[GameCnt].flags |= local_flags;
315
316             if (TCflag)
317             {
318                 TimeControl.clock[opponent] -= et;
319                 timeopp[oppptr] = et;
320                 --TimeControl.moves[opponent];
321             }
322
323             *mv = (xnode.f << 8) | xnode.t;
324             algbr(xnode.f, xnode.t, false);
325
326             /* in force mode, check for mate conditions */
327             if (flag.force)
328             {
329                 if (IsCheckmate(opponent ^ 1, -1, -1))
330                 {
331                     char buf[20];
332
333                     sprintf(buf, "%s mates!\n", ColorStr[opponent]);
334                     dsp->ShowMessage(buf);
335                     flag.mate = true;
336                 }
337             }
338
339             return true;
340         }
341     }
342
343     dsp->AlwaysShowMessage("Illegal move (no match) %s", s);
344
345     if (!barebones && (cnt > 1))
346     {
347         sprintf(buffer, "Ambiguous Move %s!", s);
348         dsp->ShowMessage(buffer);
349     }
350
351     return false;
352 }
353
354
355
356 static int
357 parser(char *f, int side, short *fpiece)
358 {
359     int c1, r1, c2, r2;
360     short i, p = false;
361
362     if (*f == '+')
363         f++, p = true;
364
365     for (i = 1, *fpiece = no_piece; i < NO_PIECES; i++)
366     {
367         if (f[0] == pxx[i] || f[0] == qxx[i])
368         {
369             *fpiece = (p ? promoted[i] : unpromoted[i]);
370             break;
371         }
372     }
373
374     if (f[1] == '*' || f[1] == '\'')
375     {
376         c2 = COL_NAME(f[2]);
377         r2 = ROW_NAME(f[3]);
378
379         return ((NO_SQUARES + *fpiece) << 8) | locn(r2, c2);
380     }
381     else
382     {
383         c1 = COL_NAME(f[1]);
384         r1 = ROW_NAME(f[2]);
385         c2 = COL_NAME(f[3]);
386         r2 = ROW_NAME(f[4]);
387         p = (f[5] == '+') ? 0x80 : 0;
388
389         return (locn(r1, c1) << 8) | locn(r2, c2) | p;
390     }
391 }
392
393
394 void
395 skip()
396 {
397     while (*InPtr != ' ')
398         InPtr++;
399
400     while (*InPtr == ' ')
401         InPtr++;
402 }
403
404
405
406 void
407 skipb()
408 {
409     while (*InPtr == ' ')
410         InPtr++;
411 }
412
413
414 void RequestInputString(char* buffer, unsigned bufsize)
415 {
416     static char fmt[10];
417     int ret = snprintf(fmt, sizeof(fmt), "%%%us", bufsize);
418     if (ret < 0 ) {
419         perror("RequestInputString snprintf");
420         exit(1);
421     }
422     if (ret >= sizeof(fmt)) {
423         fprintf(stderr,
424                 "Insufficient format-buffer size in %s for bufsize=%u\n",
425                 __FUNCTION__, bufsize);
426         exit(1);
427     }
428     dsp->doRequestInputString(fmt, buffer);
429 }
430
431
432 void
433 GetGame(void)
434 {
435     FILE *fd;
436     char fname[256], *p;
437     int c, i, j;
438     short sq;
439     short side, isp;
440
441     if (savefile[0]) {
442         strcpy(fname, savefile);
443     } else {
444         dsp->ShowMessage("Enter file name: ");
445         RequestInputString(fname, sizeof(fname)-1);
446     }
447
448     if (fname[0] == '\0')
449         strcpy(fname, "shogi.000");
450
451     if ((fd = fopen(fname, "r")) != NULL)
452     {
453         NewGame();
454         fgets(fname, 256, fd);
455         computer = opponent = black;
456         InPtr = fname;
457         skip();
458
459         if (*InPtr == 'c')
460             computer = white;
461         else
462             opponent = white;
463
464         /* FIXME: write a skipn() function so that we can get
465          * 3 skips by doing skipn(3) */
466         skip();
467         skip();
468         skip();
469         Game50 = atoi(InPtr);
470         skip();
471         flag.force = (*InPtr == 'f');
472         fgets(fname, 256, fd); /* empty */
473         fgets(fname, 256, fd);
474         InPtr = &fname[11];
475         skipb();
476         TCflag = atoi(InPtr);
477         skip();
478         InPtr += 14;
479         skipb();
480         OperatorTime = atoi(InPtr);
481         fgets(fname, 256, fd);
482         InPtr = &fname[11];
483         skipb();
484         TimeControl.clock[black] = atol(InPtr);
485         skip();
486         skip();
487         TimeControl.moves[black] = atoi(InPtr);
488         fgets(fname, 256, fd);
489         InPtr = &fname[11];
490         skipb();
491         TimeControl.clock[white] = atol(InPtr);
492         skip();
493         skip();
494         TimeControl.moves[white] = atoi(InPtr);
495         fgets(fname, 256, fd); /* empty */
496
497         for (i = NO_ROWS - 1; i > -1; i--)
498         {
499             fgets(fname, 256, fd);
500             p = &fname[2];
501             InPtr = &fname[23];
502
503             for (j = 0; j < NO_COLS; j++)
504             {
505                 sq = i * NO_COLS + j;
506                 isp = (*p == '+');
507                 p++;
508
509                 if (*p == '-')
510                 {
511                     board[sq] = no_piece;
512                     color[sq] = neutral;
513                 }
514                 else
515                 {
516                     for (c = 0; c < NO_PIECES; c++)
517                     {
518                         if (*p == pxx[c])
519                         {
520                             if (isp)
521                                 board[sq] = promoted[c];
522                             else
523                                 board[sq] = unpromoted[c];
524
525                             color[sq] = white;
526                         }
527                     }
528
529                     for (c = 0; c < NO_PIECES; c++)
530                     {
531                         if (*p == qxx[c])
532                         {
533                             if (isp)
534                                 board[sq] = promoted[c];
535                             else
536                                 board[sq] = unpromoted[c];
537
538                             color[sq] = black;
539                         }
540                     }
541                 }
542
543                 p++;
544                 Mvboard[sq] = atoi(InPtr);
545                 skip();
546             }
547         }
548
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 ... */
553         ClearCaptured();
554
555         for (side = 0; side <= 1; side++)
556         {
557             fgets(fname, 256, fd);
558             InPtr = fname;
559             skip();
560             skipb();
561             Captured[side][pawn] = atoi(InPtr);
562             skip();
563 #ifndef MINISHOGI
564             Captured[side][lance] = atoi(InPtr);
565             skip();
566             Captured[side][knight] = atoi(InPtr);
567             skip();
568 #endif
569             Captured[side][silver] = atoi(InPtr);
570             skip();
571             Captured[side][gold] = atoi(InPtr);
572             skip();
573             Captured[side][bishop] = atoi(InPtr);
574             skip();
575             Captured[side][rook] = atoi(InPtr);
576             skip();
577             Captured[side][king] = atoi(InPtr);
578         }
579
580         GameCnt = 0;
581         flag.regularstart = true;
582         Book = BOOKFAIL;
583         fgets(fname, 256, fd); /* empty */
584         fgets(fname, 256, fd);   /*  move score ... */
585
586         while (fgets(fname, 256, fd))
587         {
588             struct GameRec  *g;
589             int side = computer;
590
591             side = side ^ 1;
592             ++GameCnt;
593             InPtr = fname;
594             skipb();
595             g = &GameList[GameCnt];
596             g->gmove = parser(InPtr, side, &g->fpiece);
597             skip();
598             g->score = atoi(InPtr);
599             skip();
600             g->depth = atoi(InPtr);
601             skip();
602             g->nodes = atol(InPtr);
603             skip();
604             g->time = atol(InPtr);
605             skip();
606             g->flags = c = atoi(InPtr);
607             skip();
608             g->hashkey = strtol(InPtr, (char **) NULL, 16);
609             skip();
610             g->hashbd = strtol(InPtr, (char **) NULL, 16);
611
612             if (c & capture)
613             {
614                 short i, piece;
615
616                 skip();
617
618                 for (piece = no_piece, i = 0; i < NO_PIECES; i++)
619                 {
620                     if (pxx[i] == *InPtr)
621                     {
622                         piece = i;
623                         break;
624                     }
625                 }
626
627                 skip();
628                 g->color = ((*InPtr == 'W') ? white : black);
629                 skip();
630                 g->piece = (*InPtr == '+'
631                             ? promoted[piece]
632                             : unpromoted[piece]);
633             }
634             else
635             {
636                 g->color = neutral;
637                 g->piece = no_piece;
638             }
639         }
640
641         if (TimeControl.clock[black] > 0)
642             TCflag = true;
643
644         fclose(fd);
645     }
646
647     ZeroRPT();
648     InitializeStats();
649     dsp->UpdateDisplay(0, 0, 1, 0);
650     Sdepth = 0;
651     hint = 0;
652 }
653
654
655
656 void
657 SaveGame(void)
658 {
659     FILE *fd;
660     char fname[256];
661     short sq, i, c, f, t;
662     char p;
663     short side, piece;
664     char empty[2] = "\n";
665
666     if (savefile[0]) {
667         strcpy(fname, savefile);
668     } else {
669         dsp->ShowMessage("Enter file name: ");
670         RequestInputString(fname, sizeof(fname)-1);
671     }
672
673     if (fname[0] == '\0')
674         strcpy(fname, "shogi.000");
675
676     if ((fd = fopen(fname, "w")) != NULL)
677     {
678         char *b, *w;
679         b = w = "Human   ";
680
681         if (computer == white)
682             w = "computer";
683
684         if (computer == black)
685             b = "computer";
686
687         fprintf(fd, "White %s Black %s %d %s\n", w, b, Game50,
688                 flag.force ? "force" : "");
689         fputs(empty, fd);
690         fprintf(fd, "TimeControl %d Operator Time %d\n", TCflag, OperatorTime);
691         fprintf(fd, "Black Clock %ld Moves %d\nWhite Clock %ld Moves %d\n",
692                 TimeControl.clock[black], TimeControl.moves[black],
693                 TimeControl.clock[white], TimeControl.moves[white]);
694         fputs(empty, fd);
695
696         for (i = NO_ROWS - 1; i > -1; i--)
697         {
698             fprintf(fd, "%c ", ROW_NAME(i));
699
700             for (c = 0; c < NO_COLS; c++)
701             {
702                 sq = i * NO_COLS + c;
703                 piece = board[sq];
704                 p = is_promoted[piece] ? '+' : ' ';
705                 fprintf(fd, "%c", p);
706
707                 switch(color[sq])
708                 {
709                 case white:
710                     p = pxx[piece];
711                     break;
712
713                 case black:
714                     p = qxx[piece];
715                     break;
716
717                 default:
718                     p = '-';
719                 }
720
721                 fprintf(fd, "%c", p);
722             }
723
724             fprintf(fd, "  ");
725
726             for (f = i * NO_COLS; f < i * NO_COLS + NO_ROWS; f++)
727                 fprintf(fd, " %d", Mvboard[f]);
728
729             fprintf(fd, "\n");
730         }
731
732         fputs(empty, fd);
733 #ifndef MINISHOGI
734         fprintf(fd, "   9 8 7 6 5 4 3 2 1\n");
735         fputs(empty, fd);
736         fprintf(fd, "   p  l  n  s  g  b  r  k\n");
737 #else
738         fprintf(fd, "   5 4 3 2 1\n");
739         fputs(empty, fd);
740         fprintf(fd, "   p  s  g  b  r  k\n");
741 #endif
742
743         for (side = 0; side <= 1; side++)
744         {
745             fprintf(fd, "%c", (side == black) ? 'B' : 'W');
746             fprintf(fd, " %2d", Captured[side][pawn]);
747 #ifndef MINISHOGI
748             fprintf(fd, " %2d", Captured[side][lance]);
749             fprintf(fd, " %2d", Captured[side][knight]);
750 #endif
751             fprintf(fd, " %2d", Captured[side][silver]);
752             fprintf(fd, " %2d", Captured[side][gold]);
753             fprintf(fd, " %2d", Captured[side][bishop]);
754             fprintf(fd, " %2d", Captured[side][rook]);
755             fprintf(fd, " %2d", Captured[side][king]);
756             fprintf(fd, "\n");
757         }
758
759         fputs(empty, fd);
760         fputs("  move   score depth   nodes   time flags                         capture\n", fd);
761
762         for (i = 1; i <= GameCnt; i++)
763         {
764             struct GameRec  *g = &GameList[i];
765
766             f = g->gmove >> 8;
767             t = (g->gmove & 0xFF);
768             algbr(f, t, g->flags);
769
770             fprintf(fd, "%c%c%-5s %6d %5d %7ld %6ld %5d  0x%08lx 0x%08lx",
771                     ((f > NO_SQUARES)
772                      ? ' '
773                      : (is_promoted[g->fpiece] ? '+' : ' ')),
774                     pxx[g->fpiece],
775                     ((f > NO_SQUARES) ? &mvstr[0][1] : mvstr[0]),
776                     g->score, g->depth,
777                     g->nodes, g->time, g->flags,
778                     g->hashkey, g->hashbd);
779
780             if (g->piece != no_piece)
781             {
782                 fprintf(fd, "  %c %s %c\n",
783                         pxx[g->piece], ColorStr[g->color],
784                         (is_promoted[g->piece] ? '+' : ' '));
785             }
786             else
787             {
788                 fprintf(fd, "\n");
789             }
790         }
791
792         fclose(fd);
793
794         dsp->ShowMessage("Game saved");
795     }
796     else
797     {
798         dsp->ShowMessage("Could not open file");
799     }
800 }
801
802
803
804 /*
805  * GetXGame, SaveXGame and BookGame used to only be defined if
806  * xshogi wasn't defined -- wonder why?
807  */
808
809 void
810 GetXGame(void)
811 {
812     FILE *fd;
813     char fname[256], *p;
814     int c, i, j;
815     short sq;
816     short side, isp;
817
818     dsp->ShowMessage("Enter file name: ");
819     RequestInputString(fname, sizeof(fname)-1);
820
821     if (fname[0] == '\0')
822         strcpy(fname, "xshogi.position.read");
823
824     if ((fd = fopen(fname, "r")) != NULL)
825     {
826         NewGame();
827         flag.regularstart = false;
828         Book = false;
829
830         /* xshogi position file ... */
831         fgets(fname, 256, fd);
832
833 #ifdef notdef
834         fname[6] = '\0';
835
836         if (strcmp(fname, "xshogi"))
837             return;
838 #endif
839
840         /* -- empty line -- */
841         fgets(fname, 256, fd);
842         /* -- empty line -- */
843         fgets(fname, 256, fd);
844
845         for (i = NO_ROWS - 1; i > -1; i--)
846         {
847             fgets(fname, 256, fd);
848             p = fname;
849
850             for (j = 0; j < NO_COLS; j++)
851             {
852                 sq = i * NO_COLS + j;
853                 isp = (*p == '+');
854                 p++;
855
856                 if (*p == '.')
857                 {
858                     board[sq] = no_piece;
859                     color[sq] = neutral;
860                 }
861                 else
862                 {
863                     for (c = 0; c < NO_PIECES; c++)
864                     {
865                         if (*p == qxx[c])
866                         {
867                             if (isp)
868                                 board[sq] = promoted[c];
869                             else
870                                 board[sq] = unpromoted[c];
871
872                             color[sq] = white;
873                         }
874                     }
875
876                     for (c = 0; c < NO_PIECES; c++)
877                     {
878                         if (*p == pxx[c])
879                         {
880                             if (isp)
881                                 board[sq] = promoted[c];
882                             else
883                                 board[sq] = unpromoted[c];
884
885                             color[sq] = black;
886                         }
887                     }
888                 }
889
890                 p++;
891             }
892         }
893
894         ClearCaptured();
895
896         for (side = 0; side <= 1; side++)
897         {
898             fgets(fname, 256, fd);
899             InPtr = fname;
900             Captured[side][pawn]   = atoi(InPtr);
901             skip();
902 #ifndef MINISHOGI
903             Captured[side][lance]  = atoi(InPtr);
904             skip();
905             Captured[side][knight] = atoi(InPtr);
906             skip();
907 #endif
908             Captured[side][silver] = atoi(InPtr);
909             skip();
910             Captured[side][gold]   = atoi(InPtr);
911             skip();
912             Captured[side][bishop] = atoi(InPtr);
913             skip();
914             Captured[side][rook]   = atoi(InPtr);
915             skip();
916             Captured[side][king]   = atoi(InPtr);
917         }
918
919         if (fgets(fname, 256, fd) != NULL && strncmp(fname, "white", 5) == 0)
920         {
921             computer = black;
922             opponent = white;
923             xwndw = BXWNDW;
924         }
925
926         fclose(fd);
927     }
928
929     Game50 = 1;
930     ZeroRPT();
931     InitializeStats();
932     dsp->UpdateDisplay(0, 0, 1, 0);
933     Sdepth = 0;
934     hint = 0;
935 }
936
937
938 void
939 SaveXGame(void)
940 {
941     FILE *fd;
942     char fname[256], *p;
943     int i, j;
944     short sq, piece;
945     short side, isp;
946
947     dsp->ShowMessage("Enter file name: ");
948     RequestInputString(fname, sizeof(fname)-1);
949
950     if (fname[0] == '\0')
951         strcpy(fname, "xshogi.position.read");
952
953     if ((fd = fopen(fname, "w")) != NULL)
954     {
955         fputs("# xshogi position file -- \n", fd);
956         fputs("\n", fd);
957         fputs("\n", fd);
958
959         for (i = NO_ROWS - 1; i > -1; i--)
960         {
961             p = fname;
962
963             for (j = 0; j < NO_COLS; j++)
964             {
965                 sq = i * NO_COLS + j;
966                 piece = board[sq];
967                 isp = is_promoted[piece];
968                 *p = (isp ? '+' : ' ');
969                 p++;
970
971                 if (piece == no_piece)
972                     *p = '.';
973                 else if (color[sq] == white)
974                     *p = qxx[piece];
975                 else
976                     *p = pxx[piece];
977
978                 p++;
979             }
980
981             *p++ = '\n';
982             *p++ = '\0';
983             fputs(fname, fd);
984         }
985
986         for (side = 0; side <= 1; side++)
987         {
988             sprintf(fname,
989 #ifndef MINISHOGI
990                     "%d %d %d %d %d %d %d %d\n",
991 #else
992                     "%d %d %d %d %d %d\n",
993 #endif
994                     Captured[side][pawn],
995 #ifndef MINISHOGI
996                     Captured[side][lance],
997                     Captured[side][knight],
998 #endif
999                     Captured[side][silver],
1000                     Captured[side][gold],
1001                     Captured[side][bishop],
1002                     Captured[side][rook],
1003                     Captured[side][king]);
1004
1005             fputs(fname, fd);
1006         }
1007
1008         if (computer == black)
1009             fputs("white to play\n", fd);
1010         else
1011             fputs("black to play\n", fd);
1012
1013         fclose(fd);
1014     }
1015 }
1016
1017
1018 void
1019 BookSave(void)
1020 {
1021     FILE *fd;
1022     char fname[256], sflags[4];
1023     short i, j, f, t;
1024
1025     if (savefile[0]) {
1026         strcpy(fname, savefile);
1027     } else {
1028         /* Enter file name */
1029         dsp->ShowMessage("Enter file name: ");
1030         RequestInputString(fname, sizeof(fname)-1);
1031     }
1032
1033     if (fname[0] == '\0')
1034         return;
1035
1036     if ((fd = fopen(fname, "a")) != NULL)
1037     {
1038         fprintf(fd, "#\n");
1039
1040         for (i = 1; i <= GameCnt; i++)
1041         {
1042             struct GameRec  *g = &GameList[i];
1043             char mvnr[20], mvs[20];
1044
1045             if (i % 2)
1046                 sprintf(mvnr, "%d.", (i + 1)/2);
1047             else
1048                 strcpy(mvnr, "");
1049
1050             f = g->gmove >> 8;
1051             t = (g->gmove & 0xFF);
1052             algbr(f, t, g->flags);
1053             j = 0;
1054
1055             /* determine move quality string */
1056             if (g->flags & goodmove)
1057                 sflags[j++] = '!';
1058
1059             if (g->flags & badmove)
1060                 sflags[j++] = '?';
1061
1062 #ifdef EASY_OPENINGS
1063             if (g->flags & difficult)
1064                 sflags[j++] = '~';
1065 #endif
1066
1067             sflags[j] = '\0';
1068
1069             /* determine move string */
1070             if (f > NO_SQUARES)
1071             {
1072                 sprintf(mvs, "%s%s ", &mvstr[0][1], sflags);
1073             }
1074             else
1075             {
1076                 sprintf(mvs, "%c%c%c%c%c%s%s ",
1077                         mvstr[0][0], mvstr[0][1],
1078                         (g->flags & capture) ? 'x' : '-',
1079                         mvstr[0][2], mvstr[0][3],
1080                         (mvstr[0][4] == '+') ? "+" : "",
1081                         sflags);
1082             }
1083
1084             fprintf(fd, "%s%s%c%s",
1085                     mvnr,
1086                     (f > NO_SQUARES
1087                      ? ""
1088                      : (is_promoted[g->fpiece] ? "+" : "")),
1089                     pxx[g->fpiece],
1090                     mvs);
1091
1092             if ((i % 10) == 0)
1093                 fprintf(fd, "\n");
1094         }
1095
1096         if ((i % 10) != 1)
1097             fprintf(fd, "\n");
1098
1099         fclose(fd);
1100
1101         dsp->ShowMessage("Game saved");
1102     }
1103     else
1104     {
1105         dsp->ShowMessage("Could not open file");
1106     }
1107 }
1108
1109
1110
1111 void
1112 ListGame(void)
1113 {
1114     FILE *fd;
1115     short i, f, t;
1116     time_t when;
1117     char fname[256], dbuf[256];
1118
1119     if (listfile[0])
1120     {
1121         strcpy(fname, listfile);
1122     }
1123     else
1124     {
1125         time(&when);
1126         strncpy(dbuf, ctime(&when), 20);
1127         dbuf[7]  = '\0';
1128         dbuf[10] = '\0';
1129         dbuf[13] = '\0';
1130         dbuf[16] = '\0';
1131         dbuf[19] = '\0';
1132
1133         /* use format "CL.Jan01-020304B" when
1134            date is Jan 1
1135            time is 02:03:04
1136            program played white */
1137
1138         sprintf(fname, "CL.%s%s-%s%s%s%c",
1139                 dbuf + 4, dbuf + 8, dbuf + 11, dbuf + 14,
1140                 dbuf + 17, ColorStr[computer][0]);
1141
1142         /* replace space padding with 0 */
1143         for (i = 0; fname[i] != '\0'; i++)
1144         {
1145             if (fname[i] == ' ')
1146                 fname[i] = '0';
1147         }
1148     }
1149
1150     fd = fopen(fname, "w");
1151
1152     if (!fd)
1153     {
1154         printf("Open failure for file: %s", fname);
1155         exit(1);
1156     }
1157
1158     fprintf(fd, "gnushogi %s game\n", PACKAGE_VERSION);
1159     fputs("         score  depth   nodes  time         ", fd);
1160     fputs("         score  depth   nodes  time\n", fd);
1161
1162     for (i = 1; i <= GameCnt; i++)
1163     {
1164         f = GameList[i].gmove >> 8;
1165         t = (GameList[i].gmove & 0xFF);
1166         algbr(f, t, GameList[i].flags);
1167
1168         if (GameList[i].flags & book)
1169         {
1170             fprintf(fd, "%c%c%-5s  %5d    Book%7ld %5ld",
1171                     ((f > NO_SQUARES)
1172                      ? ' '
1173                      : (is_promoted[GameList[i].fpiece] ? '+' : ' ')),
1174                     pxx[GameList[i].fpiece],
1175                     ((f > NO_SQUARES)
1176                      ? &mvstr[0][1] : mvstr[0]),
1177                     GameList[i].score,
1178                     GameList[i].nodes,
1179                     GameList[i].time);
1180         }
1181         else
1182         {
1183             fprintf(fd, "%c%c%-5s  %5d     %2d %7ld %5ld",
1184                     (f > NO_SQUARES
1185                      ? ' '
1186                      : (is_promoted[GameList[i].fpiece] ? '+' : ' ')),
1187                     pxx[GameList[i].fpiece],
1188                     (f > NO_SQUARES ? &mvstr[0][1] : mvstr[0]),
1189                     GameList[i].score, GameList[i].depth,
1190                     GameList[i].nodes, GameList[i].time);
1191         }
1192
1193         if ((i % 2) == 0)
1194         {
1195             fprintf(fd, "\n");
1196         }
1197         else
1198         {
1199             fprintf(fd, "         ");
1200         }
1201     }
1202
1203     fprintf(fd, "\n\n");
1204
1205     if (GameList[GameCnt].flags & draw)
1206     {
1207         fprintf(fd, "Draw %s\n", DRAW);
1208
1209         if (DRAW == DRAW_REPETITION)
1210         {
1211             short j;
1212
1213             fprintf(fd, "repetition by positions ");
1214
1215             for (j = GameCnt - 1; j >= Game50; j -= 2)
1216             {
1217                 if (GameList[j].hashkey == hashkey &&
1218                     GameList[j].hashbd == hashbd)
1219                     fprintf(fd, "%d ", j);
1220             }
1221
1222             fprintf(fd, "\n");
1223         }
1224     }
1225     else if (GameList[GameCnt].score == -(SCORE_LIMIT + 999))
1226     {
1227         fprintf(fd, "%s\n", ColorStr[player ]);
1228     }
1229     else if (GameList[GameCnt].score == (SCORE_LIMIT + 998))
1230     {
1231         fprintf(fd, "%s\n", ColorStr[player ^ 1]);
1232     }
1233
1234     fclose(fd);
1235 }
1236
1237
1238
1239 void
1240 FlagMove(char c)
1241 {
1242     switch(c)
1243     {
1244     case '?' :
1245         GameList[GameCnt].flags |= badmove;
1246         break;
1247
1248     case '!' :
1249         GameList[GameCnt].flags |= goodmove;
1250         break;
1251
1252 #ifdef EASY_OPENINGS
1253     case '~' :
1254         GameList[GameCnt].flags |= difficult;
1255         break;
1256 #endif
1257     }
1258 }
1259
1260
1261
1262
1263 /*
1264  * Undo the most recent half-move.
1265  */
1266
1267 void
1268 Undo(void)
1269 {
1270     short f, t;
1271
1272     f = GameList[GameCnt].gmove >> 8;
1273     t = GameList[GameCnt].gmove & 0x7F;
1274
1275     if (f > NO_SQUARES)
1276     {
1277         /* the move was a drop */
1278         Captured[color[t]][board[t]]++;
1279         board[t] = no_piece;
1280         color[t] = neutral;
1281         Mvboard[t]--;
1282     }
1283     else
1284     {
1285         if (GameList[GameCnt].flags & promote)
1286             board[f] = unpromoted[board[t]];
1287         else
1288             board[f] = board[t];
1289
1290         color[f] = color[t];
1291         board[t] = GameList[GameCnt].piece;
1292         color[t] = GameList[GameCnt].color;
1293
1294         if (board[t] != no_piece)
1295             Captured[color[f]][unpromoted[board[t]]]--;
1296
1297         if (color[t] != neutral)
1298             Mvboard[t]--;
1299
1300         Mvboard[f]--;
1301     }
1302
1303     InitializeStats();
1304
1305     if (TCflag && (TCmoves > 1))
1306         ++TimeControl.moves[color[f]];
1307
1308     hashkey = GameList[GameCnt].hashkey;
1309     hashbd = GameList[GameCnt].hashbd;
1310     GameCnt--;
1311     computer = computer ^ 1;
1312     opponent = opponent ^ 1;
1313     flag.mate = false;
1314     Sdepth = 0;
1315     player = player ^ 1;
1316     dsp->ShowSidetoMove();
1317     dsp->UpdateDisplay(0, 0, 1, 0);
1318
1319     if (flag.regularstart)
1320         Book = false;
1321 }
1322
1323
1324
1325 void
1326 FlagString(unsigned short flags, char *s)
1327 {
1328     short l, piece;
1329     *s = '\0';
1330
1331     if (flags & promote)
1332         strcat(s, " promote");
1333
1334     if (flags & dropmask)
1335         strcat(s, " drop:");
1336
1337     if ((piece = (flags & pmask)))
1338     {
1339         l = strlen(s);
1340
1341         if (is_promoted[piece])
1342             s[l++] = '+';
1343
1344         s[l++] = pxx[piece];
1345         s[l] = '\0';
1346     }
1347
1348     if (flags & capture)
1349         strcat(s, " capture");
1350
1351     if (flags & exact)
1352         strcat(s, " exact");
1353
1354     if (flags & tesuji)
1355         strcat(s, " tesuji");
1356
1357     if (flags & check)
1358         strcat(s, " check");
1359
1360     if (flags & draw)
1361         strcat(s, " draw");
1362
1363     if (flags & stupid)
1364         strcat(s, " stupid");
1365
1366     if (flags & questionable)
1367         strcat(s, " questionable");
1368
1369     if (flags & kingattack)
1370         strcat(s, " kingattack");
1371
1372     if (flags & book)
1373         strcat(s, " book");
1374 }
1375
1376
1377
1378 void
1379 TestSpeed(void(*f)(short side, short ply,
1380                    short in_check, short blockable),
1381           unsigned j)
1382 {
1383 #ifdef test
1384     unsigned jj;
1385 #endif
1386
1387     unsigned i;
1388     long cnt, t1, t2;
1389
1390 #ifdef HAVE_GETTIMEOFDAY
1391     struct timeval tv;
1392 #endif
1393
1394 #ifdef HAVE_GETTIMEOFDAY
1395     gettimeofday(&tv, NULL);
1396     t1 = (tv.tv_sec*100 + (tv.tv_usec/10000));
1397 #else
1398     t1 = time(0);
1399 #endif
1400
1401     for (i = 0; i < j; i++)
1402     {
1403         f(opponent, 2, -1, true);
1404
1405 #ifdef test
1406         for (jj = TrPnt[2]; i < TrPnt[3]; jj++)
1407         {
1408             if (!pick(jj, TrPnt[3] - 1))
1409                 break;
1410         }
1411 #endif
1412     }
1413
1414 #ifdef HAVE_GETTIMEOFDAY
1415     gettimeofday(&tv, NULL);
1416     t2 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1417 #else
1418     t2 = time(0);
1419 #endif
1420
1421     cnt = j * (TrPnt[3] - TrPnt[2]);
1422
1423     if (t2 - t1)
1424         et = (t2 - t1);
1425     else
1426         et = 1;
1427
1428     dsp->ShowNodeCnt(cnt);
1429 }
1430
1431
1432
1433 void
1434 TestPSpeed(short(*f) (short side), unsigned j)
1435 {
1436     short i;
1437     long cnt, t1, t2;
1438 #ifdef HAVE_GETTIMEOFDAY
1439     struct timeval tv;
1440 #endif
1441
1442 #ifdef HAVE_GETTIMEOFDAY
1443     gettimeofday(&tv, NULL);
1444     t1 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1445 #else
1446     t1 = time(0);
1447 #endif
1448
1449     for (i = 0; i < j; i++)
1450         (void) f(opponent);
1451
1452 #ifdef HAVE_GETTIMEOFDAY
1453     gettimeofday(&tv, NULL);
1454     t2 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1455 #else
1456     t2 = time(0);
1457 #endif
1458
1459     cnt = j;
1460
1461     if (t2 - t1)
1462         et = (t2 - t1);
1463     else
1464         et = 1;
1465
1466     dsp->ShowNodeCnt(cnt);
1467 }
1468
1469
1470
1471 void
1472 SetOppTime(char *s)
1473 {
1474     char *time;
1475     int m, t, sec;
1476
1477     sec = 0;
1478     time = &s[strlen("otime")];
1479     t = (int)strtol(time, &time, 10);
1480
1481     if (*time == ':')
1482     {
1483         time++;
1484         sec = (int)strtol(time, &time, 10);
1485     }
1486
1487     m = (int)strtol(time, &time, 10);
1488
1489     if (t)
1490         TimeControl.clock[opponent] = t;
1491
1492     if (m)
1493         TimeControl.moves[opponent] = m;
1494
1495     ElapsedTime(COMPUTE_AND_INIT_MODE);
1496
1497     if (XSHOGI)
1498     {
1499         /* just to inform xshogi about availability of otime command */
1500         printf("otime %d %d\n", t, m);
1501     }
1502 }
1503
1504
1505
1506 void
1507 SetMachineTime(char *s)
1508 {
1509     char *time;
1510     int m, t, sec;
1511
1512     time = &s[strlen("time")];
1513     sec = 0;
1514     t = (int)strtol(time, &time, 10);
1515
1516     if (*time == ':')
1517     {
1518         time++;
1519         sec = (int)strtol(time, &time, 10);
1520     }
1521
1522     m = (int)strtol(time, &time, 10);
1523
1524     if (t)
1525         TimeControl.clock[computer] = t;
1526
1527     if (m)
1528         TimeControl.moves[computer] = m;
1529
1530     ElapsedTime(COMPUTE_AND_INIT_MODE);
1531
1532     if (XSHOGI)
1533     {
1534         /* just to inform xshogi about availability of time command */
1535         printf("time %d %d\n", t, m);
1536     }
1537 }
1538
1539
1540
1541
1542
1543 /* FIXME!  This is truly the function from hell! */
1544
1545 /*
1546  * Process the user's command. If easy mode is OFF (the computer is thinking
1547  * on opponents time) and the program is out of book, then make the 'hint'
1548  * move on the board and call SelectMove() to find a response. The user
1549  * terminates the search by entering ^C (quit siqnal) before entering a
1550  * command. If the opponent does not make the hint move, then set Sdepth to
1551  * zero.
1552  */
1553
1554 void
1555 InputCommand(char *command)
1556 {
1557     int eof = 0;
1558     short have_shown_prompt = false;
1559     short ok, done, is_move = false;
1560     unsigned short mv;
1561     char s[80], sx[80];
1562
1563     ok = flag.quit = done = false;
1564     player = opponent;
1565
1566 #if ttblsz
1567     if (TTadd > ttbllimit)
1568         ZeroTTable();
1569 #endif
1570
1571     if ((hint > 0) && !flag.easy && !flag.force)
1572     {
1573         /*
1574          * A hint move for the player is available.  Compute a move for the
1575          * opponent in background mode assuming that the hint move will be
1576          * selected by the player.
1577          */
1578
1579         ft = time0; /* Save reference time for the player. */
1580         fflush(stdout);
1581         algbr((short) hint >> 8, (short) hint & 0xff, false);
1582         strcpy(s, mvstr[0]);
1583
1584 #if !defined NOPOST
1585         if (flag.post)
1586             dsp->GiveHint();
1587 #endif
1588
1589         /* do the hint move */
1590         if (VerifyMove(s, VERIFY_AND_TRY_MODE, &mv))
1591         {
1592             Sdepth = 0;
1593
1594 #ifdef QUIETBACKGROUND
1595             dsp->ShowPrompt();
1596             have_shown_prompt = true;
1597 #endif /* QUIETBACKGROUND */
1598
1599             /* Start computing a move until the search is interrupted. */
1600
1601 #ifdef INTERRUPT_TEST
1602             itime0 = 0;
1603 #endif
1604
1605             /* would love to put null move in here */
1606             /* after we make the hint move make a 2 ply search
1607              * with both plys our moves */
1608             /* think on opponents time */
1609             SelectMove(computer, BACKGROUND_MODE);
1610
1611 #ifdef INTERRUPT_TEST
1612             ElapsedTime(COMPUTE_INTERRUPT_MODE);
1613
1614             if (itime0 == 0)
1615             {
1616                 printf("searching not terminated by interrupt!\n");
1617             }
1618             else
1619             {
1620                 printf("elapsed time from interrupt to "
1621                        "terminating search: %ld\n", it);
1622             }
1623 #endif
1624
1625             /* undo the hint and carry on */
1626             VerifyMove(s, UNMAKE_MODE, &mv);
1627             Sdepth = 0;
1628         }
1629
1630         time0 = ft; /* Restore reference time for the player. */
1631     }
1632
1633     while(!(ok || flag.quit || done))
1634     {
1635         player = opponent;
1636
1637 #ifdef QUIETBACKGROUND
1638         if (!have_shown_prompt)
1639         {
1640 #endif /* QUIETBACKGROUND */
1641
1642             dsp->ShowPrompt();
1643
1644 #ifdef QUIETBACKGROUND
1645         }
1646
1647         have_shown_prompt = false;
1648 #endif /* QUIETBACKGROUND */
1649
1650         if (command == NULL) {
1651             if (NOT_CURSES)
1652                 s[0] = '\0';
1653
1654             eof = dsp->GetString(sx);
1655         } else {
1656             strcpy(sx, command);
1657             done = true;
1658         }
1659
1660         sscanf(sx, "%s", s);
1661
1662         if (eof)
1663             dsp->ExitShogi();
1664
1665         if (s[0] == '\0')
1666             continue;
1667
1668         if (strcmp(s, "bd") == 0)   /* bd -- display board */
1669         {
1670             /* FIXME: Hack alert! */
1671             short old_xshogi = XSHOGI;
1672
1673             if (old_xshogi)
1674                 display_type = DISPLAY_RAW;
1675
1676             dsp->ClearScreen();
1677             dsp->UpdateDisplay(0, 0, 1, 0);
1678
1679             if (old_xshogi)
1680                 display_type = DISPLAY_X;
1681         }
1682         else if (strcmp(s, "post") == 0)
1683         {
1684             flag.post = !flag.post;
1685         }
1686         else if (strcmp(s, "alg") == 0)
1687         {
1688             /* noop */ ; /* alg */
1689         }
1690         else if ((strcmp(s, "quit") == 0)
1691                  || (strcmp(s, "exit") == 0))
1692         {
1693             flag.quit = true;
1694         }
1695 #if !defined NOPOST
1696         else if (strcmp(s, "post") == 0)
1697         {
1698             flag.post = !flag.post;
1699         }
1700 #endif
1701         else if ((strcmp(s, "set") == 0)
1702                  || (strcmp(s, "edit") == 0))
1703         {
1704             dsp->EditBoard();
1705         }
1706         else if ((strcmp(s, "setup") == 0))
1707         {
1708             dsp->SetupBoard();
1709         }
1710         else if (strcmp(s, "first") == 0)
1711         {
1712             ok = true;
1713         }
1714         else if (strcmp(s, "go") == 0)
1715         {
1716             ok = true;
1717             flag.force = false;
1718
1719             if (computer == black)
1720             {
1721                 computer = white;
1722                 opponent = black;
1723             }
1724             else
1725             {
1726                 computer = black;
1727                 opponent = white;
1728             }
1729         }
1730         else if (strcmp(s, "help") == 0)
1731         {
1732             dsp->help();
1733         }
1734         else if (strcmp(s, "material") == 0)
1735         {
1736             flag.material = !flag.material;
1737         }
1738         else if (strcmp(s, "force") == 0)
1739         {
1740             if (XSHOGI)
1741             {
1742                 flag.force = true;
1743                 flag.bothsides = false;
1744             }
1745             else
1746             {
1747                 flag.force = !flag.force;
1748                 flag.bothsides = false;
1749             }
1750         }
1751         else if (strcmp(s, "book") == 0)
1752         {
1753             Book = Book ? 0 : BOOKFAIL;
1754         }
1755         else if (strcmp(s, "new") == 0)
1756         {
1757             NewGame();
1758             dsp->UpdateDisplay(0, 0, 1, 0);
1759         }
1760         else if (strcmp(s, "list") == 0)
1761         {
1762             ListGame();
1763         }
1764         else if ((strcmp(s, "level") == 0)
1765                  || (strcmp(s, "clock") == 0))
1766         {
1767             dsp->SelectLevel(sx);
1768         }
1769         else if (strcmp(s, "hash") == 0)
1770         {
1771             flag.hash = !flag.hash;
1772         }
1773         else if (strcmp(s, "gamein") == 0)
1774         {
1775             flag.gamein = !flag.gamein;
1776         }
1777         else if (strcmp(s, "beep") == 0)
1778         {
1779             flag.beep = !flag.beep;
1780         }
1781         else if (strcmp(s, "time") == 0)
1782         {
1783             SetMachineTime(sx);
1784         }
1785         else if (strcmp(s, "otime") == 0)
1786         {
1787             SetOppTime(sx);
1788         }
1789         else if (strcmp(s, "Awindow") == 0)
1790         {
1791             dsp->ChangeAlphaWindow();
1792         }
1793         else if (strcmp(s, "Bwindow") == 0)
1794         {
1795             dsp->ChangeBetaWindow();
1796         }
1797         else if (strcmp(s, "rcptr") == 0)
1798         {
1799             flag.rcptr = !flag.rcptr;
1800         }
1801         else if (strcmp(s, "hint") == 0)
1802         {
1803             dsp->GiveHint();
1804         }
1805         else if (strcmp(s, "both") == 0)
1806         {
1807             flag.bothsides = !flag.bothsides;
1808             flag.force = false;
1809             Sdepth = 0;
1810             ElapsedTime(COMPUTE_AND_INIT_MODE);
1811             SelectMove(opponent, FOREGROUND_MODE);
1812             ok = true;
1813         }
1814         else if (strcmp(s, "reverse") == 0)
1815         {
1816             flag.reverse = !flag.reverse;
1817             dsp->ClearScreen();
1818             dsp->UpdateDisplay(0, 0, 1, 0);
1819         }
1820         else if (strcmp(s, "switch") == 0)
1821         {
1822             computer = computer ^ 1;
1823             opponent = opponent ^ 1;
1824             xwndw = (computer == black) ? WXWNDW : BXWNDW;
1825             flag.force = false;
1826             Sdepth = 0;
1827             ok = true;
1828         }
1829         else if (strcmp(s, "black") == 0)
1830         {
1831             computer = white;
1832             opponent = black;
1833             xwndw = WXWNDW;
1834             flag.force = false;
1835             Sdepth = 0;
1836
1837             /*
1838              * ok = true; don't automatically start with black command
1839              */
1840         }
1841         else if (strcmp(s, "white") == 0)
1842         {
1843             computer = black;
1844             opponent = white;
1845             xwndw = BXWNDW;
1846             flag.force = false;
1847             Sdepth = 0;
1848
1849             /*
1850              * ok = true; don't automatically start with white command
1851              */
1852         }
1853         else if (strcmp(s, "undo") == 0 && GameCnt > 0)
1854         {
1855             Undo();
1856         }
1857         else if (strcmp(s, "remove") == 0 && GameCnt > 1)
1858         {
1859             Undo();
1860             Undo();
1861         }
1862         /* CHECKME: are these next three correct? */
1863         else if (!XSHOGI && strcmp(s, "xget") == 0)
1864         {
1865             GetXGame();
1866         }
1867         else if (!XSHOGI && strcmp(s, "xsave") == 0)
1868         {
1869             SaveXGame();
1870         }
1871         else if (!XSHOGI && strcmp(s, "bsave") == 0)
1872         {
1873             BookSave();
1874         }
1875 #ifdef EASY_OPENINGS
1876         else if ((strcmp(s, "?") == 0)
1877                  || (strcmp(s, "!") == 0)
1878                  || (strcmp(s, "~") == 0))
1879 #else
1880         else if ((strcmp(s, "?") == 0)
1881                  || (strcmp(s, "!") == 0))
1882 #endif
1883         {
1884             FlagMove(*s);
1885         }
1886         else if (strcmp(s, "get") == 0)
1887         {
1888             GetGame();
1889         }
1890         else if (strcmp(s, "save") == 0)
1891         {
1892             SaveGame();
1893         }
1894         else if (strcmp(s, "depth") == 0)
1895         {
1896             dsp->ChangeSearchDepth();
1897         }
1898         else if (strcmp(s, "hashdepth") == 0)
1899         {
1900             dsp->ChangeHashDepth();
1901         }
1902         else if (strcmp(s, "random") == 0)
1903         {
1904             dither = DITHER;
1905         }
1906         else if (strcmp(s, "hard") == 0)
1907         {
1908             flag.easy = false;
1909         }
1910         else if (strcmp(s, "easy") == 0)
1911         {
1912             flag.easy = !flag.easy;
1913         }
1914         else if (strcmp(s, "tsume") == 0)
1915         {
1916             flag.tsume = !flag.tsume;
1917         }
1918         else if (strcmp(s, "contempt") == 0)
1919         {
1920             dsp->SetContempt();
1921         }
1922         else if (strcmp(s, "xwndw") == 0)
1923         {
1924             dsp->ChangeXwindow();
1925         }
1926         else if (strcmp(s, "rv") == 0)
1927         {
1928             flag.rv = !flag.rv;
1929             dsp->UpdateDisplay(0, 0, 1, 0);
1930         }
1931         else if (strcmp(s, "coords") == 0)
1932         {
1933             flag.coords = !flag.coords;
1934             dsp->UpdateDisplay(0, 0, 1, 0);
1935         }
1936         else if (strcmp(s, "stars") == 0)
1937         {
1938             flag.stars = !flag.stars;
1939             dsp->UpdateDisplay(0, 0, 1, 0);
1940         }
1941         else if (!XSHOGI && strcmp(s, "moves") == 0)
1942         {
1943             short temp;
1944
1945 #if MAXDEPTH > 3
1946             if (GameCnt > 0)
1947             {
1948                 extern unsigned short PrVar[MAXDEPTH];
1949
1950                 SwagHt = (GameList[GameCnt].gmove == PrVar[1])
1951                     ? PrVar[2] : 0;
1952             }
1953             else
1954 #endif
1955                 SwagHt = 0;
1956
1957             dsp->ShowMessage("Testing MoveList Speed");
1958             temp = generate_move_flags;
1959             generate_move_flags = true;
1960             TestSpeed(MoveList, 1);
1961             generate_move_flags = temp;
1962             dsp->ShowMessage("Testing CaptureList Speed");
1963             TestSpeed(CaptureList, 1);
1964             dsp->ShowMessage("Testing Eval Speed");
1965             ExaminePosition(opponent);
1966             TestPSpeed(ScorePosition, 1);
1967         }
1968         else if (!XSHOGI && strcmp(s, "test") == 0)
1969         {
1970 #ifdef SLOW_CPU
1971             dsp->ShowMessage("Testing MoveList Speed");
1972             TestSpeed(MoveList, 2000);
1973             dsp->ShowMessage("Testing CaptureList Speed");
1974             TestSpeed(CaptureList, 3000);
1975             dsp->ShowMessage("Testing Eval Speed");
1976             ExaminePosition(opponent);
1977             TestPSpeed(ScorePosition, 1500);
1978 #else
1979             dsp->ShowMessage("Testing MoveList Speed");
1980             TestSpeed(MoveList, 20000);
1981             dsp->ShowMessage("Testing CaptureList Speed");
1982             TestSpeed(CaptureList, 30000);
1983             dsp->ShowMessage("Testing Eval Speed");
1984             ExaminePosition(opponent);
1985             TestPSpeed(ScorePosition, 15000);
1986 #endif
1987         }
1988         else if (!XSHOGI && strcmp(s, "p") == 0)
1989         {
1990             dsp->ShowPostnValues();
1991         }
1992         else if (!XSHOGI && strcmp(s, "debug") == 0)
1993         {
1994             dsp->DoDebug();
1995         }
1996         else
1997         {
1998             if (flag.mate)
1999             {
2000                 ok = true;
2001             }
2002             else if ((ok = VerifyMove(s, VERIFY_AND_MAKE_MODE, &mv)))
2003             {
2004                 /* check for repetition */
2005                 short rpt = repetition();
2006
2007                 if (rpt >= 3)
2008                 {
2009                     DRAW = DRAW_REPETITION;
2010                     dsp->ShowMessage(DRAW);
2011                     GameList[GameCnt].flags |= draw;
2012
2013                         flag.mate = true;
2014                 }
2015                 else
2016                 {
2017                     is_move = true;
2018                 }
2019             }
2020
2021             Sdepth = 0;
2022         }
2023     }
2024
2025     ElapsedTime(COMPUTE_AND_INIT_MODE);
2026
2027     if (flag.force)
2028     {
2029         computer = opponent;
2030         opponent = computer ^ 1;
2031     }
2032
2033     if (XSHOGI)
2034     {
2035         /* add remaining time in milliseconds for xshogi */
2036         if (is_move)
2037         {
2038             printf("%d. %s %ld\n",
2039                    ++mycnt2, s, TimeControl.clock[player] * 10);
2040         }
2041
2042 #ifdef notdef /* optional pass best line to frontend with move */
2043 #  if !defined NOPOST
2044
2045         if (flag.post && !flag.mate)
2046         {
2047             int i;
2048
2049             printf(" %6d ", MSCORE);
2050
2051             for (i = 1; MV[i] > 0; i++)
2052             {
2053                 algbr((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false);
2054                 printf("%5s ", mvstr[0]);
2055             }
2056         }
2057 #  endif
2058         printf("\n");
2059 #endif
2060     }
2061 }
2062
2063
2064
2065
2066 void
2067 SetTimeControl(void)
2068 {
2069     if (TCflag)
2070     {
2071         TimeControl.moves[black] = TimeControl.moves[white] = TCmoves;
2072         TimeControl.clock[black] += 6000L * TCminutes + TCseconds * 100;
2073         TimeControl.clock[white] += 6000L * TCminutes + TCseconds * 100;
2074     }
2075     else
2076     {
2077         TimeControl.moves[black] = TimeControl.moves[white] = 0;
2078         TimeControl.clock[black] = TimeControl.clock[white] = 0;
2079     }
2080
2081     flag.onemove = (TCmoves == 1);
2082     et = 0;
2083     ElapsedTime(COMPUTE_AND_INIT_MODE);
2084 }