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