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