When in check, complain with the requested move.
[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 <curses.h>
46 #include "gnushogi.h"
47
48 char mvstr[4][6];
49 char *InPtr;
50 int InBackground = false;
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             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
302             if (NOT_CURSES)
303             {
304                 /* Illegal move in check */
305                 printf(CP[77], s);
306                 printf("\n");
307             }
308             else
309             {
310                 /* Illegal move in check */
311                 sprintf(buffer, CP[77], s);
312                 ShowMessage(buffer);
313             }
314
315             return false;
316         }
317         else
318         {
319             if (iop == VERIFY_AND_TRY_MODE)
320                 return true;
321
322             UpdateDisplay(xnode.f, xnode.t, 0, (short) xnode.flags);
323             GameList[GameCnt].depth = GameList[GameCnt].score = 0;
324             GameList[GameCnt].nodes = 0;
325             ElapsedTime(COMPUTE_AND_INIT_MODE);
326             GameList[GameCnt].time = (short) (et + 50)/100;
327             GameList[GameCnt].flags |= local_flags;
328
329             if (TCflag)
330             {
331                 TimeControl.clock[opponent] -= et;
332                 timeopp[oppptr] = et;
333                 --TimeControl.moves[opponent];
334             }
335
336             *mv = (xnode.f << 8) | xnode.t;
337             algbr(xnode.f, xnode.t, false);
338
339             /* in force mode, check for mate conditions */
340             if (flag.force)
341             {
342                 if (IsCheckmate(opponent ^ 1, -1, -1))
343                 {
344                     char buf[20];
345
346                     sprintf(buf, "%s mates!\n", ColorStr[opponent]);
347                     ShowMessage(buf);
348                     flag.mate = true;
349                 }
350             }
351
352             return true;
353         }
354     }
355
356     if (NOT_CURSES)
357     {
358         /* Illegal move */
359         printf (CP[75], s);
360     }
361     else /* Curses. */
362     {
363         /* Illegal move */
364         sprintf(buffer, CP[76], s);
365         ShowMessage(buffer);
366     }
367
368     if (!barebones && (cnt > 1))
369     {
370         sprintf(buffer, CP[32], s);
371         ShowMessage(buffer);
372     }
373
374     return false;
375 }
376
377
378
379 static int
380 parser(char *f, int side, short *fpiece)
381 {
382     int c1, r1, c2, r2;
383     short i, p = false;
384
385     if (*f == '+')
386         f++, p = true;
387
388     for (i = 1, *fpiece = no_piece; i < NO_PIECES; i++)
389     {
390         if (f[0] == pxx[i] || f[0] == qxx[i])
391         {
392             *fpiece = (p ? promoted[i] : unpromoted[i]);
393             break;
394         }
395     }
396
397     if (f[1] == '*' || f[1] == '\'')
398     {
399         c2 = COL_NAME(f[2]);
400         r2 = ROW_NAME(f[3]);
401
402         return ((NO_SQUARES + *fpiece) << 8) | locn(r2, c2);
403     }
404     else
405     {
406         c1 = COL_NAME(f[1]);
407         r1 = ROW_NAME(f[2]);
408         c2 = COL_NAME(f[3]);
409         r2 = ROW_NAME(f[4]);
410         p = (f[5] == '+') ? 0x80 : 0;
411
412         return (locn(r1, c1) << 8) | locn(r2, c2) | p;
413     }
414 }
415
416
417 void
418 skip()
419 {
420     while (*InPtr != ' ')
421         InPtr++;
422
423     while (*InPtr == ' ')
424         InPtr++;
425 }
426
427
428
429 void
430 skipb()
431 {
432     while (*InPtr == ' ')
433         InPtr++;
434 }
435
436
437
438 void
439 GetGame(void)
440 {
441     FILE *fd;
442     char fname[256], *p;
443     int c, i, j;
444     short sq;
445     short side, isp;
446
447     if (savefile[0]) {
448         strcpy(fname, savefile);
449     } else {
450         /* Enter file name */
451         ShowMessage(CP[63]);
452         RequestInputString(fname, sizeof(fname)-1);
453     }
454
455     /* shogi.000 */
456     if (fname[0] == '\0')
457         strcpy(fname, CP[137]);
458
459     if ((fd = fopen(fname, "r")) != NULL)
460     {
461         NewGame();
462         fgets(fname, 256, fd);
463         computer = opponent = black;
464         InPtr = fname;
465         skip();
466
467         if (*InPtr == 'c')
468             computer = white;
469         else
470             opponent = white;
471
472         /* FIXME: write a skipn() function so that we can get
473          * 3 skips by doing skipn(3) */
474         skip();
475         skip();
476         skip();
477         Game50 = atoi(InPtr);
478         skip();
479         flag.force = (*InPtr == 'f');
480         fgets(fname, 256, fd); /* empty */
481         fgets(fname, 256, fd);
482         InPtr = &fname[11];
483         skipb();
484         TCflag = atoi(InPtr);
485         skip();
486         InPtr += 14;
487         skipb();
488         OperatorTime = atoi(InPtr);
489         fgets(fname, 256, fd);
490         InPtr = &fname[11];
491         skipb();
492         TimeControl.clock[black] = atol(InPtr);
493         skip();
494         skip();
495         TimeControl.moves[black] = atoi(InPtr);
496         fgets(fname, 256, fd);
497         InPtr = &fname[11];
498         skipb();
499         TimeControl.clock[white] = atol(InPtr);
500         skip();
501         skip();
502         TimeControl.moves[white] = atoi(InPtr);
503         fgets(fname, 256, fd); /* empty */
504
505         for (i = NO_ROWS - 1; i > -1; i--)
506         {
507             fgets(fname, 256, fd);
508             p = &fname[2];
509             InPtr = &fname[23];
510
511             for (j = 0; j < NO_COLS; j++)
512             {
513                 sq = i * NO_COLS + j;
514                 isp = (*p == '+');
515                 p++;
516
517                 if (*p == '-')
518                 {
519                     board[sq] = no_piece;
520                     color[sq] = neutral;
521                 }
522                 else
523                 {
524                     for (c = 0; c < NO_PIECES; c++)
525                     {
526                         if (*p == pxx[c])
527                         {
528                             if (isp)
529                                 board[sq] = promoted[c];
530                             else
531                                 board[sq] = unpromoted[c];
532
533                             color[sq] = white;
534                         }
535                     }
536
537                     for (c = 0; c < NO_PIECES; c++)
538                     {
539                         if (*p == qxx[c])
540                         {
541                             if (isp)
542                                 board[sq] = promoted[c];
543                             else
544                                 board[sq] = unpromoted[c];
545
546                             color[sq] = black;
547                         }
548                     }
549                 }
550
551                 p++;
552                 Mvboard[sq] = atoi(InPtr);
553                 skip();
554             }
555         }
556
557         fgets(fname, 256, fd);  /* empty */
558         fgets(fname, 256, fd);  /* 9 8 7 ... */
559         fgets(fname, 256, fd);  /* empty */
560         fgets(fname, 256, fd);  /* p l n ... */
561         ClearCaptured();
562
563         for (side = 0; side <= 1; side++)
564         {
565             fgets(fname, 256, fd);
566             InPtr = fname;
567             skip();
568             skipb();
569             Captured[side][pawn] = atoi(InPtr);
570             skip();
571             Captured[side][lance] = atoi(InPtr);
572             skip();
573             Captured[side][knight] = atoi(InPtr);
574             skip();
575             Captured[side][silver] = atoi(InPtr);
576             skip();
577             Captured[side][gold] = atoi(InPtr);
578             skip();
579             Captured[side][bishop] = atoi(InPtr);
580             skip();
581             Captured[side][rook] = atoi(InPtr);
582             skip();
583             Captured[side][king] = atoi(InPtr);
584         }
585
586         GameCnt = 0;
587         flag.regularstart = true;
588         Book = BOOKFAIL;
589         fgets(fname, 256, fd); /* empty */
590         fgets(fname, 256, fd);   /*  move score ... */
591
592         while (fgets(fname, 256, fd))
593         {
594             struct GameRec  *g;
595             int side = computer;
596
597             side = side ^ 1;
598             ++GameCnt;
599             InPtr = fname;
600             skipb();
601             g = &GameList[GameCnt];
602             g->gmove = parser(InPtr, side, &g->fpiece);
603             skip();
604             g->score = atoi(InPtr);
605             skip();
606             g->depth = atoi(InPtr);
607             skip();
608             g->nodes = atol(InPtr);
609             skip();
610             g->time = atol(InPtr);
611             skip();
612             g->flags = c = atoi(InPtr);
613             skip();
614             g->hashkey = strtol(InPtr, (char **) NULL, 16);
615             skip();
616             g->hashbd = strtol(InPtr, (char **) NULL, 16);
617
618             if (c & capture)
619             {
620                 short i, piece;
621
622                 skip();
623
624                 for (piece = no_piece, i = 0; i < NO_PIECES; i++)
625                 {
626                     if (pxx[i] == *InPtr)
627                     {
628                         piece = i;
629                         break;
630                     }
631                 }
632
633                 skip();
634                 g->color = ((*InPtr == CP[119][0]) ? white : black);
635                 skip();
636                 g->piece = (*InPtr == '+'
637                             ? promoted[piece]
638                             : unpromoted[piece]);
639             }
640             else
641             {
642                 g->color = neutral;
643                 g->piece = no_piece;
644             }
645         }
646
647         if (TimeControl.clock[black] > 0)
648             TCflag = true;
649
650         fclose(fd);
651     }
652
653     ZeroRPT();
654     InitializeStats();
655     UpdateDisplay(0, 0, 1, 0);
656     Sdepth = 0;
657     hint = 0;
658 }
659
660
661
662 void
663 SaveGame(void)
664 {
665     FILE *fd;
666     char fname[256];
667     short sq, i, c, f, t;
668     char p;
669     short side, piece;
670     char empty[2] = "\n";
671
672     if (savefile[0]) {
673         strcpy(fname, savefile);
674     } else {
675         /* Enter file name */
676         ShowMessage(CP[63]);
677         RequestInputString(fname, sizeof(fname)-1);
678     }
679
680     if (fname[0] == '\0')        /* shogi.000 */
681         strcpy(fname, CP[137]);
682
683     if ((fd = fopen(fname, "w")) != NULL)
684     {
685         char *b, *w;
686         b = w = CP[74];
687
688         if (computer == white)
689             w = CP[141];
690
691         if (computer == black)
692             b = CP[141];
693
694         fprintf(fd, CP[37], w, b, Game50,
695                 flag.force ? "force" : "");
696         fputs(empty, fd);
697         fprintf(fd, CP[111], TCflag, OperatorTime);
698         fprintf(fd, CP[117],
699                 TimeControl.clock[black], TimeControl.moves[black],
700                 TimeControl.clock[white], TimeControl.moves[white]);
701         fputs(empty, fd);
702
703         for (i = NO_ROWS - 1; i > -1; i--)
704         {
705             fprintf(fd, "%c ", ROW_NAME(i));
706
707             for (c = 0; c < NO_COLS; c++)
708             {
709                 sq = i * NO_COLS + c;
710                 piece = board[sq];
711                 p = is_promoted[piece] ? '+' : ' ';
712                 fprintf(fd, "%c", p);
713
714                 switch(color[sq])
715                 {
716                 case white:
717                     p = pxx[piece];
718                     break;
719
720                 case black:
721                     p = qxx[piece];
722                     break;
723
724                 default:
725                     p = '-';
726                 }
727
728                 fprintf(fd, "%c", p);
729             }
730
731             fprintf(fd, "  ");
732
733             for (f = i * NO_COLS; f < i * NO_COLS + NO_ROWS; f++)
734                 fprintf(fd, " %d", Mvboard[f]);
735
736             fprintf(fd, "\n");
737         }
738
739         fputs(empty, fd);
740         fprintf(fd, "   9 8 7 6 5 4 3 2 1\n");    /* FIXME */
741         fputs(empty, fd);
742         fprintf(fd, "   p  l  n  s  g  b  r  k\n");
743
744         for (side = 0; side <= 1; side++)
745         {
746             fprintf(fd, "%c", (side == black) ? 'B' : 'W');
747             fprintf(fd, " %2d", Captured[side][pawn]);
748             fprintf(fd, " %2d", Captured[side][lance]);
749             fprintf(fd, " %2d", Captured[side][knight]);
750             fprintf(fd, " %2d", Captured[side][silver]);
751             fprintf(fd, " %2d", Captured[side][gold]);
752             fprintf(fd, " %2d", Captured[side][bishop]);
753             fprintf(fd, " %2d", Captured[side][rook]);
754             fprintf(fd, " %2d", Captured[side][king]);
755             fprintf(fd, "\n");
756         }
757
758         fputs(empty, fd);
759         fputs(CP[126], fd);
760
761         for (i = 1; i <= GameCnt; i++)
762         {
763             struct GameRec  *g = &GameList[i];
764
765             f = g->gmove >> 8;
766             t = (g->gmove & 0xFF);
767             algbr(f, t, g->flags);
768
769             fprintf(fd, "%c%c%-5s %6d %5d %7ld %6ld %5d  0x%08lx 0x%08lx",
770                     ((f > NO_SQUARES)
771                      ? ' '
772                      : (is_promoted[g->fpiece] ? '+' : ' ')),
773                     pxx[g->fpiece],
774                     ((f > NO_SQUARES) ? &mvstr[0][1] : mvstr[0]),
775                     g->score, g->depth,
776                     g->nodes, g->time, g->flags,
777                     g->hashkey, g->hashbd);
778
779             if (g->piece != no_piece)
780             {
781                 fprintf(fd, "  %c %s %c\n",
782                         pxx[g->piece], ColorStr[g->color],
783                         (is_promoted[g->piece] ? '+' : ' '));
784             }
785             else
786             {
787                 fprintf(fd, "\n");
788             }
789         }
790
791         fclose(fd);
792
793         /* Game saved */
794         ShowMessage(CP[70]);
795     }
796     else
797     {
798         /* ShowMessage("Could not open file"); */
799         ShowMessage(CP[48]);
800     }
801 }
802
803
804
805 /*
806  * GetXGame, SaveXGame and BookGame used to only be defined if
807  * xshogi wasn't defined -- wonder why?
808  */
809
810 void
811 GetXGame(void)
812 {
813     FILE *fd;
814     char fname[256], *p;
815     int c, i, j;
816     short sq;
817     short side, isp;
818
819     /* Enter file name */
820     ShowMessage(CP[63]);
821     RequestInputString(fname, sizeof(fname)-1);
822
823     if (fname[0] == '\0') /* XSHOGI.position.read */
824         strcpy(fname, CP[205]);
825
826     if ((fd = fopen(fname, "r")) != NULL)
827     {
828         NewGame();
829         flag.regularstart = false;
830         Book = false;
831
832         /* xshogi position file ... */
833         fgets(fname, 256, fd);
834
835 #ifdef notdef
836         fname[6] = '\0';
837
838         if (strcmp(fname, CP[206]))
839             return;
840 #endif
841
842         /* -- empty line -- */
843         fgets(fname, 256, fd);
844         /* -- empty line -- */
845         fgets(fname, 256, fd);
846
847         for (i = NO_ROWS - 1; i > -1; i--)
848         {
849             fgets(fname, 256, fd);
850             p = fname;
851
852             for (j = 0; j < NO_COLS; j++)
853             {
854                 sq = i * NO_COLS + j;
855                 isp = (*p == '+');
856                 p++;
857
858                 if (*p == '.')
859                 {
860                     board[sq] = no_piece;
861                     color[sq] = neutral;
862                 }
863                 else
864                 {
865                     for (c = 0; c < NO_PIECES; c++)
866                     {
867                         if (*p == qxx[c])
868                         {
869                             if (isp)
870                                 board[sq] = promoted[c];
871                             else
872                                 board[sq] = unpromoted[c];
873
874                             color[sq] = white;
875                         }
876                     }
877
878                     for (c = 0; c < NO_PIECES; c++)
879                     {
880                         if (*p == pxx[c])
881                         {
882                             if (isp)
883                                 board[sq] = promoted[c];
884                             else
885                                 board[sq] = unpromoted[c];
886
887                             color[sq] = black;
888                         }
889                     }
890                 }
891
892                 p++;
893             }
894         }
895
896         ClearCaptured();
897
898         for (side = 0; side <= 1; side++)
899         {
900             fgets(fname, 256, fd);
901             InPtr = fname;
902             Captured[side][pawn]   = atoi(InPtr);
903             skip();
904             Captured[side][lance]  = atoi(InPtr);
905             skip();
906             Captured[side][knight] = atoi(InPtr);
907             skip();
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     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     /* Enter file name */
948     ShowMessage(CP[63]);
949     RequestInputString(fname, sizeof(fname)-1);
950
951     if (fname[0] == '\0') /* XSHOGI.position.read */
952         strcpy(fname, CP[205]);
953
954     if ((fd = fopen(fname, "w")) != NULL)
955     {
956         /* xshogi position file ... */
957         fputs("# xshogi position file -- \n", fd);
958         /* -- empty line -- */
959         fputs("\n", fd);
960         /* -- empty line -- */
961         fputs("\n", fd);
962
963         for (i = NO_ROWS - 1; i > -1; i--)
964         {
965             p = fname;
966
967             for (j = 0; j < NO_COLS; j++)
968             {
969                 sq = i * NO_COLS + j;
970                 piece = board[sq];
971                 isp = is_promoted[piece];
972                 *p = (isp ? '+' : ' ');
973                 p++;
974
975                 if (piece == no_piece)
976                     *p = '.';
977                 else if (color[sq] == white)
978                     *p = qxx[piece];
979                 else
980                     *p = pxx[piece];
981
982                 p++;
983             }
984
985             *p++ = '\n';
986             *p++ = '\0';
987             fputs(fname, fd);
988         }
989
990         for (side = 0; side <= 1; side++)
991         {
992             sprintf(fname, "%d %d %d %d %d %d %d %d\n",
993                     Captured[side][pawn],
994                     Captured[side][lance],
995                     Captured[side][knight],
996                     Captured[side][silver],
997                     Captured[side][gold],
998                     Captured[side][bishop],
999                     Captured[side][rook],
1000                     Captured[side][king]);
1001
1002             fputs(fname, fd);
1003         }
1004
1005         if (computer == black)
1006             fputs("white to play\n", fd);
1007         else
1008             fputs("black to play\n", fd);
1009
1010         fclose(fd);
1011     }
1012 }
1013
1014
1015 void
1016 BookSave(void)
1017 {
1018     FILE *fd;
1019     char fname[256], sflags[4];
1020     short i, j, f, t;
1021
1022     if (savefile[0]) {
1023         strcpy(fname, savefile);
1024     } else {
1025         /* Enter file name */
1026         ShowMessage(CP[63]);
1027         RequestInputString(fname, sizeof(fname)-1);
1028     }
1029
1030     if (fname[0] == '\0')
1031         return;
1032
1033     if ((fd = fopen(fname, "a")) != NULL)
1034     {
1035         fprintf(fd, "#\n");
1036
1037         for (i = 1; i <= GameCnt; i++)
1038         {
1039             struct GameRec  *g = &GameList[i];
1040             char mvnr[20], mvs[20];
1041
1042             if (i % 2)
1043                 sprintf(mvnr, "%d.", (i + 1)/2);
1044             else
1045                 strcpy(mvnr, "");
1046
1047             f = g->gmove >> 8;
1048             t = (g->gmove & 0xFF);
1049             algbr(f, t, g->flags);
1050             j = 0;
1051
1052             /* determine move quality string */
1053             if (g->flags & goodmove)
1054                 sflags[j++] = '!';
1055
1056             if (g->flags & badmove)
1057                 sflags[j++] = '?';
1058
1059 #ifdef EASY_OPENINGS
1060             if (g->flags & difficult)
1061                 sflags[j++] = '~';
1062 #endif
1063
1064             sflags[j] = '\0';
1065
1066             /* determine move string */
1067             if (f > NO_SQUARES)
1068             {
1069                 sprintf(mvs, "%s%s ", &mvstr[0][1], sflags);
1070             }
1071             else
1072             {
1073                 sprintf(mvs, "%c%c%c%c%c%s%s ",
1074                         mvstr[0][0], mvstr[0][1],
1075                         (g->flags & capture) ? 'x' : '-',
1076                         mvstr[0][2], mvstr[0][3],
1077                         (mvstr[0][4] == '+') ? "+" : "",
1078                         sflags);
1079             }
1080
1081             fprintf(fd, "%s%s%c%s",
1082                     mvnr,
1083                     (f > NO_SQUARES
1084                      ? ""
1085                      : (is_promoted[g->fpiece] ? "+" : "")),
1086                     pxx[g->fpiece],
1087                     mvs);
1088
1089             if ((i % 10) == 0)
1090                 fprintf(fd, "\n");
1091         }
1092
1093         if ((i % 10) != 1)
1094             fprintf(fd, "\n");
1095
1096         fclose(fd);
1097
1098         /* Game saved */
1099         ShowMessage(CP[70]);
1100     }
1101     else
1102     {
1103         /* ShowMessage("Could not open file"); */
1104         ShowMessage(CP[48]);
1105     }
1106 }
1107
1108
1109
1110 void
1111 ListGame(void)
1112 {
1113     FILE *fd;
1114     short i, f, t;
1115     time_t when;
1116     char fname[256], dbuf[256];
1117
1118     if (listfile[0])
1119     {
1120         strcpy(fname, listfile);
1121     }
1122     else
1123     {
1124         time(&when);
1125         strncpy(dbuf, ctime(&when), 20);
1126         dbuf[7]  = '\0';
1127         dbuf[10] = '\0';
1128         dbuf[13] = '\0';
1129         dbuf[16] = '\0';
1130         dbuf[19] = '\0';
1131
1132         /* use format "CLp16.Jan01-020304B" when patchlevel is 16,
1133            date is Jan 1
1134            time is 02:03:04
1135            program played white */
1136
1137         sprintf(fname, "CLp%s.%s%s-%s%s%s%c",
1138                 patchlevel, dbuf + 4, dbuf + 8, dbuf + 11, dbuf + 14,
1139                 dbuf + 17, ColorStr[computer][0]);
1140
1141         /* replace space padding with 0 */
1142         for (i = 0; fname[i] != '\0'; i++)
1143         {
1144             if (fname[i] == ' ')
1145                 fname[i] = '0';
1146         }
1147     }
1148
1149     fd = fopen(fname, "w");
1150
1151     if (!fd)
1152     {
1153         printf(CP[219], fname);
1154         exit(1);
1155     }
1156
1157     /* fprintf(fd, "gnushogi game %d\n", u); */
1158     fprintf(fd, CP[161], version, patchlevel);
1159     fputs(CP[10], fd);
1160     fputs(CP[11], 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, CP[54], DRAW);
1208
1209         if (DRAW == CP[101])
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     ShowSidetoMove();
1317     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, rate, 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     rate = (((et) ? ((cnt * 100) / et) : 0));
1429
1430 #ifdef DYNAMIC_ZNODES
1431     if (rate > 0)
1432         znodes = rate;
1433 #endif
1434
1435     if (NOT_CURSES)
1436         printf(CP[91], cnt, rate);
1437     else
1438         ShowNodeCnt(cnt);
1439 }
1440
1441
1442
1443 void
1444 TestPSpeed(short(*f) (short side), unsigned j)
1445 {
1446     short i;
1447     long cnt, rate, t1, t2;
1448 #ifdef HAVE_GETTIMEOFDAY
1449     struct timeval tv;
1450 #endif
1451
1452 #ifdef HAVE_GETTIMEOFDAY
1453     gettimeofday(&tv, NULL);
1454     t1 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1455 #else
1456     t1 = time(0);
1457 #endif
1458
1459     for (i = 0; i < j; i++)
1460         (void) f(opponent);
1461
1462 #ifdef HAVE_GETTIMEOFDAY
1463     gettimeofday(&tv, NULL);
1464     t2 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1465 #else
1466     t2 = time(0);
1467 #endif
1468
1469     cnt = j;
1470
1471     if (t2 - t1)
1472         et = (t2 - t1);
1473     else
1474         et = 1;
1475
1476     rate = (et) ? ((cnt * 100) / et) : 0;
1477
1478     /* printf("Nodes= %ld Nodes/sec= %ld\n", cnt, rate); */
1479
1480     if (NOT_CURSES)
1481         printf(CP[91], cnt, rate);
1482     else
1483         ShowNodeCnt(cnt);
1484 }
1485
1486
1487
1488 void
1489 SetOppTime(char *s)
1490 {
1491     char *time;
1492     int m, t, sec;
1493
1494     sec = 0;
1495     time = &s[strlen(CP[228])];
1496     t = (int)strtol(time, &time, 10);
1497
1498     if (*time == ':')
1499     {
1500         time++;
1501         sec = (int)strtol(time, &time, 10);
1502     }
1503
1504     m = (int)strtol(time, &time, 10);
1505
1506     if (t)
1507         TimeControl.clock[opponent] = t;
1508
1509     if (m)
1510         TimeControl.moves[opponent] = m;
1511
1512     ElapsedTime(COMPUTE_AND_INIT_MODE);
1513
1514     if (XSHOGI)
1515     {
1516         /* just to inform xshogi about availability of otime command */
1517         printf("otime %d %d\n", t, m);
1518     }
1519 }
1520
1521
1522
1523 void
1524 SetMachineTime(char *s)
1525 {
1526     char *time;
1527     int m, t, sec;
1528
1529     time = &s[strlen(CP[197])];
1530     sec = 0;
1531     t = (int)strtol(time, &time, 10);
1532
1533     if (*time == ':')
1534     {
1535         time++;
1536         sec = (int)strtol(time, &time, 10);
1537     }
1538
1539     m = (int)strtol(time, &time, 10);
1540
1541     if (t)
1542         TimeControl.clock[computer] = t;
1543
1544     if (m)
1545         TimeControl.moves[computer] = m;
1546
1547     ElapsedTime(COMPUTE_AND_INIT_MODE);
1548
1549     if (XSHOGI)
1550     {
1551         /* just to inform xshogi about availability of time command */
1552         printf("time %d %d\n", t, m);
1553     }
1554 }
1555
1556
1557
1558
1559
1560 /* FIXME!  This is truly the function from hell! */
1561
1562 /*
1563  * Process the user's command. If easy mode is OFF (the computer is thinking
1564  * on opponents time) and the program is out of book, then make the 'hint'
1565  * move on the board and call SelectMove() to find a response. The user
1566  * terminates the search by entering ^C (quit siqnal) before entering a
1567  * command. If the opponent does not make the hint move, then set Sdepth to
1568  * zero.
1569  */
1570
1571 void
1572 InputCommand(char *command)
1573 {
1574     int eof = 0;
1575     short have_shown_prompt = false;
1576     short ok, done, is_move = false;
1577     unsigned short mv;
1578     char s[80], sx[80];
1579
1580     ok = flag.quit = done = false;
1581     player = opponent;
1582
1583 #if ttblsz
1584     if (TTadd > ttbllimit)
1585         ZeroTTable();
1586 #endif
1587
1588     if ((hint > 0) && !flag.easy && !flag.force)
1589     {
1590         /*
1591          * A hint move for the player is available.  Compute a move for the
1592          * opponent in background mode assuming that the hint move will be
1593          * selected by the player.
1594          */
1595
1596         ft = time0; /* Save reference time for the player. */
1597         fflush(stdout);
1598         algbr((short) hint >> 8, (short) hint & 0xff, false);
1599         strcpy(s, mvstr[0]);
1600
1601 #if !defined NOPOST
1602         if (flag.post)
1603             GiveHint();
1604 #endif
1605
1606         /* do the hint move */
1607         if (VerifyMove(s, VERIFY_AND_TRY_MODE, &mv))
1608         {
1609             Sdepth = 0;
1610
1611 #ifdef QUIETBACKGROUND
1612             if (NOT_CURSES)
1613             {
1614                 PromptForMove();
1615             }
1616             else
1617             {
1618                 ShowSidetoMove();
1619                 ShowPrompt();
1620             }
1621
1622             have_shown_prompt = true;
1623 #endif /* QUIETBACKGROUND */
1624
1625             /* Start computing a move until the search is interrupted. */
1626
1627 #ifdef INTERRUPT_TEST
1628             itime0 = 0;
1629 #endif
1630
1631             /* would love to put null move in here */
1632             /* after we make the hint move make a 2 ply search
1633              * with both plys our moves */
1634             /* think on opponents time */
1635             SelectMove(computer, BACKGROUND_MODE);
1636
1637 #ifdef INTERRUPT_TEST
1638             ElapsedTime(COMPUTE_INTERRUPT_MODE);
1639
1640             if (itime0 == 0)
1641             {
1642                 printf("searching not terminated by interrupt!\n");
1643             }
1644             else
1645             {
1646                 printf("elapsed time from interrupt to "
1647                        "terminating search: %ld\n", it);
1648             }
1649 #endif
1650
1651             /* undo the hint and carry on */
1652             VerifyMove(s, UNMAKE_MODE, &mv);
1653             Sdepth = 0;
1654         }
1655
1656         time0 = ft; /* Restore reference time for the player. */
1657     }
1658
1659     while(!(ok || flag.quit || done))
1660     {
1661         player = opponent;
1662
1663 #ifdef QUIETBACKGROUND
1664         if (!have_shown_prompt)
1665         {
1666 #endif /* QUIETBACKGROUND */
1667
1668             if (NOT_CURSES)
1669             {
1670                 PromptForMove();
1671             }
1672             else
1673             {
1674                 ShowSidetoMove();
1675                 ShowPrompt();
1676             }
1677
1678 #ifdef QUIETBACKGROUND
1679         }
1680
1681         have_shown_prompt = false;
1682 #endif /* QUIETBACKGROUND */
1683
1684         if (command == NULL)
1685         {
1686             if (NOT_CURSES)
1687             {
1688                 s[0] = sx[0] = '\0';
1689
1690                 while(!eof && !sx[0])
1691                     eof = (fgets(sx, 80, stdin) == NULL);
1692             }
1693             else
1694             {
1695                 fflush(stdout);
1696                 eof = (getstr(sx) == ERR);
1697             }
1698         }
1699         else
1700         {
1701             strcpy(sx, command);
1702             done = true;
1703         }
1704
1705         sscanf(sx, "%s", s);
1706
1707         if (eof)
1708             ExitShogi();
1709
1710         if (s[0] == '\0')
1711             continue;
1712
1713         if (strcmp(s, CP[131]) == 0)   /* bd -- display board */
1714         {
1715             /* FIXME: Hack alert! */
1716             short old_xshogi = XSHOGI;
1717
1718             if (old_xshogi)
1719                 display_type = DISPLAY_RAW;
1720
1721             ClearScreen();
1722             UpdateDisplay(0, 0, 1, 0);
1723
1724             if (old_xshogi)
1725                 display_type = DISPLAY_X;
1726         }
1727         else if (strcmp(s, "post") == 0)
1728         {
1729             flag.post = !flag.post;
1730         }
1731         else if (strcmp(s, CP[129]) == 0)
1732         {
1733             /* noop */ ; /* alg */
1734         }
1735         else if ((strcmp(s, CP[180]) == 0)
1736                  || (strcmp(s, CP[216]) == 0))  /* quit exit */
1737         {
1738             flag.quit = true;
1739         }
1740 #if !defined NOPOST
1741         else if (strcmp(s, CP[178]) == 0)  /* post */
1742         {
1743             flag.post = !flag.post;
1744         }
1745 #endif
1746         else if ((strcmp(s, CP[191]) == 0)
1747                  || (strcmp(s, CP[154]) == 0))  /* set edit */
1748         {
1749             EditBoard();
1750         }
1751         else if (NOT_CURSES && (strcmp(s, CP[190]) == 0))  /* setup */
1752         {
1753             SetupBoard();
1754         }
1755         else if (strcmp(s, CP[156]) == 0)  /* first */
1756         {
1757             ok = true;
1758         }
1759         else if (strcmp(s, CP[162]) == 0)  /* go */
1760         {
1761             ok = true;
1762             flag.force = false;
1763
1764             if (computer == black)
1765             {
1766                 computer = white;
1767                 opponent = black;
1768             }
1769             else
1770             {
1771                 computer = black;
1772                 opponent = white;
1773             }
1774         }
1775         else if (strcmp(s, CP[166]) == 0)  /* help */
1776         {
1777             help();
1778         }
1779         else if (strcmp(s, CP[221]) == 0)  /* material */
1780         {
1781             flag.material = !flag.material;
1782         }
1783         else if (strcmp(s, CP[157]) == 0)  /* force */
1784         {
1785             if (XSHOGI)
1786             {
1787                 flag.force = true;
1788                 flag.bothsides = false;
1789             }
1790             else
1791             {
1792                 flag.force = !flag.force;
1793                 flag.bothsides = false;
1794             }
1795         }
1796         else if (strcmp(s, CP[134]) == 0)  /* book */
1797         {
1798             Book = Book ? 0 : BOOKFAIL;
1799         }
1800         else if (strcmp(s, CP[172]) == 0)  /* new */
1801         {
1802             NewGame();
1803             UpdateDisplay(0, 0, 1, 0);
1804         }
1805         else if (strcmp(s, CP[171]) == 0)  /* list */
1806         {
1807             ListGame();
1808         }
1809         else if ((strcmp(s, CP[169]) == 0)
1810                  || (strcmp(s, CP[217]) == 0))  /* level clock */
1811         {
1812             SelectLevel(sx);
1813         }
1814         else if (strcmp(s, CP[165]) == 0)  /* hash */
1815         {
1816             flag.hash = !flag.hash;
1817         }
1818         else if (strcmp(s, CP[227]) == 0)  /* gamein */
1819         {
1820             flag.gamein = !flag.gamein;
1821         }
1822         else if (strcmp(s, CP[226]) == 0)  /* beep */
1823         {
1824             flag.beep = !flag.beep;
1825         }
1826         else if (strcmp(s, CP[197]) == 0)  /* time */
1827         {
1828             SetMachineTime(sx);
1829         }
1830         else if (strcmp(s, CP[228]) == 0)  /* otime */
1831         {
1832             SetOppTime(sx);
1833         }
1834         else if (strcmp(s, CP[33]) == 0)   /* Awindow */
1835         {
1836             ChangeAlphaWindow();
1837         }
1838         else if (strcmp(s, CP[39]) == 0)   /* Bwindow */
1839         {
1840             ChangeBetaWindow();
1841         }
1842         else if (strcmp(s, CP[183]) == 0)  /* rcptr */
1843         {
1844             flag.rcptr = !flag.rcptr;
1845         }
1846         else if (strcmp(s, CP[168]) == 0)  /* hint */
1847         {
1848             GiveHint();
1849         }
1850         else if (strcmp(s, CP[135]) == 0)  /* both */
1851         {
1852             flag.bothsides = !flag.bothsides;
1853             flag.force = false;
1854             Sdepth = 0;
1855             ElapsedTime(COMPUTE_AND_INIT_MODE);
1856             SelectMove(opponent, FOREGROUND_MODE);
1857             ok = true;
1858         }
1859         else if (strcmp(s, CP[185]) == 0)  /* reverse */
1860         {
1861             flag.reverse = !flag.reverse;
1862             ClearScreen();
1863             UpdateDisplay(0, 0, 1, 0);
1864         }
1865         else if (strcmp(s, CP[195]) == 0)  /* switch */
1866         {
1867             computer = computer ^ 1;
1868             opponent = opponent ^ 1;
1869             xwndw = (computer == black) ? WXWNDW : BXWNDW;
1870             flag.force = false;
1871             Sdepth = 0;
1872             ok = true;
1873         }
1874         else if (strcmp(s, CP[203]) == 0)  /* black */
1875         {
1876             computer = white;
1877             opponent = black;
1878             xwndw = WXWNDW;
1879             flag.force = false;
1880             Sdepth = 0;
1881
1882             /*
1883              * ok = true; don't automatically start with black command
1884              */
1885         }
1886         else if (strcmp(s, CP[133]) == 0)  /* white */
1887         {
1888             computer = black;
1889             opponent = white;
1890             xwndw = BXWNDW;
1891             flag.force = false;
1892             Sdepth = 0;
1893
1894             /*
1895              * ok = true; don't automatically start with white command
1896              */
1897         }
1898         else if (strcmp(s, CP[201]) == 0 && GameCnt > 0)   /* undo */
1899         {
1900             Undo();
1901         }
1902         else if (strcmp(s, CP[184]) == 0 && GameCnt > 1)   /* remove */
1903         {
1904             Undo();
1905             Undo();
1906         }
1907         /* CHECKME: are these next three correct? */
1908         else if (!XSHOGI && strcmp(s, CP[207]) == 0)  /* xget */
1909         {
1910             GetXGame();
1911         }
1912         else if (!XSHOGI && strcmp(s, "xsave") == 0)        /* xsave */
1913         {
1914             SaveXGame();
1915         }
1916         else if (!XSHOGI && strcmp(s, "bsave") == 0)        /* bsave */
1917         {
1918             BookSave();
1919         }
1920 #ifdef EASY_OPENINGS
1921         else if ((strcmp(s, "?") == 0)
1922                  || (strcmp(s, "!") == 0)
1923                  || (strcmp(s, "~") == 0))
1924 #else
1925         else if ((strcmp(s, "?") == 0)
1926                  || (strcmp(s, "!") == 0))
1927 #endif
1928         {
1929             FlagMove(*s);
1930         }
1931         else if (strcmp(s, CP[160]) == 0)    /* get */
1932         {
1933             GetGame();
1934         }
1935         else if (strcmp(s, CP[189]) == 0)    /* save */
1936         {
1937             SaveGame();
1938         }
1939         else if (strcmp(s, CP[151]) == 0)    /* depth */
1940         {
1941             ChangeSearchDepth();
1942         }
1943         else if (strcmp(s, CP[164]) == 0)    /* hashdepth */
1944         {
1945             ChangeHashDepth();
1946         }
1947         else if (strcmp(s, CP[182]) == 0)    /* random */
1948         {
1949             dither = DITHER;
1950         }
1951         else if (strcmp(s, CP[229]) == 0)    /* hard */
1952         {
1953             flag.easy = false;
1954         }
1955         else if (strcmp(s, CP[152]) == 0)    /* easy */
1956         {
1957             flag.easy = !flag.easy;
1958         }
1959         else if (strcmp(s, CP[230]) == 0)    /* tsume */
1960         {
1961             flag.tsume = !flag.tsume;
1962         }
1963         else if (strcmp(s, CP[143]) == 0)    /* contempt */
1964         {
1965             SetContempt();
1966         }
1967         else if (strcmp(s, CP[209]) == 0)    /* xwndw */
1968         {
1969             ChangeXwindow();
1970         }
1971         else if (strcmp(s, CP[186]) == 0)    /* rv */
1972         {
1973             flag.rv = !flag.rv;
1974             UpdateDisplay(0, 0, 1, 0);
1975         }
1976         else if (strcmp(s, CP[145]) == 0)    /* coords */
1977         {
1978             flag.coords = !flag.coords;
1979             UpdateDisplay(0, 0, 1, 0);
1980         }
1981         else if (strcmp(s, CP[193]) == 0)    /* stars */
1982         {
1983             flag.stars = !flag.stars;
1984             UpdateDisplay(0, 0, 1, 0);
1985         }
1986         else if (!XSHOGI && strcmp(s, CP[5]) == 0)          /* moves */
1987         {
1988             short temp;
1989
1990 #if MAXDEPTH > 3
1991             if (GameCnt > 0)
1992             {
1993                 extern unsigned short PrVar[MAXDEPTH];
1994
1995                 SwagHt = (GameList[GameCnt].gmove == PrVar[1])
1996                     ? PrVar[2] : 0;
1997             }
1998             else
1999 #endif
2000                 SwagHt = 0;
2001
2002             ShowMessage(CP[108]);  /* test movelist */
2003             temp = generate_move_flags;
2004             generate_move_flags = true;
2005             TestSpeed(MoveList, 1);
2006             generate_move_flags = temp;
2007             ShowMessage(CP[107]);  /* test capturelist */
2008             TestSpeed(CaptureList, 1);
2009             ShowMessage(CP[85]);   /* test score position */
2010             ExaminePosition(opponent);
2011             TestPSpeed(ScorePosition, 1);
2012         }
2013         else if (!XSHOGI && strcmp(s, CP[196]) == 0)    /* test */
2014         {
2015 #ifdef SLOW_CPU
2016             ShowMessage(CP[108]); /* test movelist */
2017             TestSpeed(MoveList, 2000);
2018             ShowMessage(CP[107]); /* test capturelist */
2019             TestSpeed(CaptureList, 3000);
2020             ShowMessage(CP[85]); /* test score position */
2021             ExaminePosition(opponent);
2022             TestPSpeed(ScorePosition, 1500);
2023 #else
2024             ShowMessage(CP[108]); /* test movelist */
2025             TestSpeed(MoveList, 20000);
2026             ShowMessage(CP[107]); /* test capturelist */
2027             TestSpeed(CaptureList, 30000);
2028             ShowMessage(CP[85]); /* test score position */
2029             ExaminePosition(opponent);
2030             TestPSpeed(ScorePosition, 15000);
2031 #endif
2032         }
2033         else if (!XSHOGI && strcmp(s, CP[179]) == 0) /* p */
2034         {
2035             ShowPostnValues();
2036         }
2037         else if (!XSHOGI && strcmp(s, CP[148]) == 0)    /* debug */
2038         {
2039             DoDebug();
2040         }
2041         else
2042         {
2043             if (flag.mate)
2044             {
2045                 ok = true;
2046             }
2047             else if ((ok = VerifyMove(s, VERIFY_AND_MAKE_MODE, &mv)))
2048             {
2049                 /* check for repetition */
2050                 short rpt = repetition();
2051
2052                 if (rpt >= 3)
2053                 {
2054                     DRAW = CP[101];
2055                     ShowMessage(DRAW);
2056                     GameList[GameCnt].flags |= draw;
2057
2058                         flag.mate = true;
2059                 }
2060                 else
2061                 {
2062                     is_move = true;
2063                 }
2064             }
2065
2066             Sdepth = 0;
2067         }
2068     }
2069
2070     ElapsedTime(COMPUTE_AND_INIT_MODE);
2071
2072     if (flag.force)
2073     {
2074         computer = opponent;
2075         opponent = computer ^ 1;
2076     }
2077
2078     if (XSHOGI)
2079     {
2080         /* add remaining time in milliseconds for xshogi */
2081         if (is_move)
2082         {
2083             printf("%d. %s %ld\n",
2084                    ++mycnt2, s, TimeControl.clock[player] * 10);
2085         }
2086
2087 #ifdef notdef /* optional pass best line to frontend with move */
2088 #  if !defined NOPOST
2089
2090         if (flag.post && !flag.mate)
2091         {
2092             int i;
2093
2094             printf(" %6d ", MSCORE);
2095
2096             for (i = 1; MV[i] > 0; i++)
2097             {
2098                 algbr((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false);
2099                 printf("%5s ", mvstr[0]);
2100             }
2101         }
2102 #  endif
2103         printf("\n");
2104 #endif
2105     }
2106 }
2107
2108
2109
2110
2111 void
2112 SetTimeControl(void)
2113 {
2114     if (TCflag)
2115     {
2116         TimeControl.moves[black] = TimeControl.moves[white] = TCmoves;
2117         TimeControl.clock[black] += 6000L * TCminutes + TCseconds * 100;
2118         TimeControl.clock[white] += 6000L * TCminutes + TCseconds * 100;
2119     }
2120     else
2121     {
2122         TimeControl.moves[black] = TimeControl.moves[white] = 0;
2123         TimeControl.clock[black] = TimeControl.clock[white] = 0;
2124     }
2125
2126     flag.onemove = (TCmoves == 1);
2127     et = 0;
2128     ElapsedTime(COMPUTE_AND_INIT_MODE);
2129 }
2130