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