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