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