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