Convert more stuff from #ifdef to dspwrappers: GetString.
[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 "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             if (NOT_CURSES)
1572             {
1573                 PromptForMove();
1574             }
1575             else
1576             {
1577                 ShowSidetoMove();
1578                 ShowPrompt();
1579             }
1580
1581             have_shown_prompt = true;
1582 #endif /* QUIETBACKGROUND */
1583
1584             /* Start computing a move until the search is interrupted. */
1585
1586 #ifdef INTERRUPT_TEST
1587             itime0 = 0;
1588 #endif
1589
1590             /* would love to put null move in here */
1591             /* after we make the hint move make a 2 ply search
1592              * with both plys our moves */
1593             /* think on opponents time */
1594             SelectMove(computer, BACKGROUND_MODE);
1595
1596 #ifdef INTERRUPT_TEST
1597             ElapsedTime(COMPUTE_INTERRUPT_MODE);
1598
1599             if (itime0 == 0)
1600             {
1601                 printf("searching not terminated by interrupt!\n");
1602             }
1603             else
1604             {
1605                 printf("elapsed time from interrupt to "
1606                        "terminating search: %ld\n", it);
1607             }
1608 #endif
1609
1610             /* undo the hint and carry on */
1611             VerifyMove(s, UNMAKE_MODE, &mv);
1612             Sdepth = 0;
1613         }
1614
1615         time0 = ft; /* Restore reference time for the player. */
1616     }
1617
1618     while(!(ok || flag.quit || done))
1619     {
1620         player = opponent;
1621
1622 #ifdef QUIETBACKGROUND
1623         if (!have_shown_prompt)
1624         {
1625 #endif /* QUIETBACKGROUND */
1626
1627             if (NOT_CURSES)
1628             {
1629                 PromptForMove();
1630             }
1631             else
1632             {
1633                 ShowSidetoMove();
1634                 ShowPrompt();
1635             }
1636
1637 #ifdef QUIETBACKGROUND
1638         }
1639
1640         have_shown_prompt = false;
1641 #endif /* QUIETBACKGROUND */
1642
1643         if (command == NULL) {
1644             if (NOT_CURSES)
1645                 s[0] = '\0';
1646
1647             eof = GetString(sx);
1648         } else {
1649             strcpy(sx, command);
1650             done = true;
1651         }
1652
1653         sscanf(sx, "%s", s);
1654
1655         if (eof)
1656             ExitShogi();
1657
1658         if (s[0] == '\0')
1659             continue;
1660
1661         if (strcmp(s, CP[131]) == 0)   /* bd -- display board */
1662         {
1663             /* FIXME: Hack alert! */
1664             short old_xshogi = XSHOGI;
1665
1666             if (old_xshogi)
1667                 display_type = DISPLAY_RAW;
1668
1669             ClearScreen();
1670             UpdateDisplay(0, 0, 1, 0);
1671
1672             if (old_xshogi)
1673                 display_type = DISPLAY_X;
1674         }
1675         else if (strcmp(s, "post") == 0)
1676         {
1677             flag.post = !flag.post;
1678         }
1679         else if (strcmp(s, CP[129]) == 0)
1680         {
1681             /* noop */ ; /* alg */
1682         }
1683         else if ((strcmp(s, CP[180]) == 0)
1684                  || (strcmp(s, CP[216]) == 0))  /* quit exit */
1685         {
1686             flag.quit = true;
1687         }
1688 #if !defined NOPOST
1689         else if (strcmp(s, CP[178]) == 0)  /* post */
1690         {
1691             flag.post = !flag.post;
1692         }
1693 #endif
1694         else if ((strcmp(s, CP[191]) == 0)
1695                  || (strcmp(s, CP[154]) == 0))  /* set edit */
1696         {
1697             EditBoard();
1698         }
1699         else if (NOT_CURSES && (strcmp(s, CP[190]) == 0))  /* setup */
1700         {
1701             SetupBoard();
1702         }
1703         else if (strcmp(s, CP[156]) == 0)  /* first */
1704         {
1705             ok = true;
1706         }
1707         else if (strcmp(s, CP[162]) == 0)  /* go */
1708         {
1709             ok = true;
1710             flag.force = false;
1711
1712             if (computer == black)
1713             {
1714                 computer = white;
1715                 opponent = black;
1716             }
1717             else
1718             {
1719                 computer = black;
1720                 opponent = white;
1721             }
1722         }
1723         else if (strcmp(s, CP[166]) == 0)  /* help */
1724         {
1725             help();
1726         }
1727         else if (strcmp(s, CP[221]) == 0)  /* material */
1728         {
1729             flag.material = !flag.material;
1730         }
1731         else if (strcmp(s, CP[157]) == 0)  /* force */
1732         {
1733             if (XSHOGI)
1734             {
1735                 flag.force = true;
1736                 flag.bothsides = false;
1737             }
1738             else
1739             {
1740                 flag.force = !flag.force;
1741                 flag.bothsides = false;
1742             }
1743         }
1744         else if (strcmp(s, CP[134]) == 0)  /* book */
1745         {
1746             Book = Book ? 0 : BOOKFAIL;
1747         }
1748         else if (strcmp(s, CP[172]) == 0)  /* new */
1749         {
1750             NewGame();
1751             UpdateDisplay(0, 0, 1, 0);
1752         }
1753         else if (strcmp(s, CP[171]) == 0)  /* list */
1754         {
1755             ListGame();
1756         }
1757         else if ((strcmp(s, CP[169]) == 0)
1758                  || (strcmp(s, CP[217]) == 0))  /* level clock */
1759         {
1760             SelectLevel(sx);
1761         }
1762         else if (strcmp(s, CP[165]) == 0)  /* hash */
1763         {
1764             flag.hash = !flag.hash;
1765         }
1766         else if (strcmp(s, CP[227]) == 0)  /* gamein */
1767         {
1768             flag.gamein = !flag.gamein;
1769         }
1770         else if (strcmp(s, CP[226]) == 0)  /* beep */
1771         {
1772             flag.beep = !flag.beep;
1773         }
1774         else if (strcmp(s, CP[197]) == 0)  /* time */
1775         {
1776             SetMachineTime(sx);
1777         }
1778         else if (strcmp(s, CP[228]) == 0)  /* otime */
1779         {
1780             SetOppTime(sx);
1781         }
1782         else if (strcmp(s, CP[33]) == 0)   /* Awindow */
1783         {
1784             ChangeAlphaWindow();
1785         }
1786         else if (strcmp(s, CP[39]) == 0)   /* Bwindow */
1787         {
1788             ChangeBetaWindow();
1789         }
1790         else if (strcmp(s, CP[183]) == 0)  /* rcptr */
1791         {
1792             flag.rcptr = !flag.rcptr;
1793         }
1794         else if (strcmp(s, CP[168]) == 0)  /* hint */
1795         {
1796             GiveHint();
1797         }
1798         else if (strcmp(s, CP[135]) == 0)  /* both */
1799         {
1800             flag.bothsides = !flag.bothsides;
1801             flag.force = false;
1802             Sdepth = 0;
1803             ElapsedTime(COMPUTE_AND_INIT_MODE);
1804             SelectMove(opponent, FOREGROUND_MODE);
1805             ok = true;
1806         }
1807         else if (strcmp(s, CP[185]) == 0)  /* reverse */
1808         {
1809             flag.reverse = !flag.reverse;
1810             ClearScreen();
1811             UpdateDisplay(0, 0, 1, 0);
1812         }
1813         else if (strcmp(s, CP[195]) == 0)  /* switch */
1814         {
1815             computer = computer ^ 1;
1816             opponent = opponent ^ 1;
1817             xwndw = (computer == black) ? WXWNDW : BXWNDW;
1818             flag.force = false;
1819             Sdepth = 0;
1820             ok = true;
1821         }
1822         else if (strcmp(s, CP[203]) == 0)  /* black */
1823         {
1824             computer = white;
1825             opponent = black;
1826             xwndw = WXWNDW;
1827             flag.force = false;
1828             Sdepth = 0;
1829
1830             /*
1831              * ok = true; don't automatically start with black command
1832              */
1833         }
1834         else if (strcmp(s, CP[133]) == 0)  /* white */
1835         {
1836             computer = black;
1837             opponent = white;
1838             xwndw = BXWNDW;
1839             flag.force = false;
1840             Sdepth = 0;
1841
1842             /*
1843              * ok = true; don't automatically start with white command
1844              */
1845         }
1846         else if (strcmp(s, CP[201]) == 0 && GameCnt > 0)   /* undo */
1847         {
1848             Undo();
1849         }
1850         else if (strcmp(s, CP[184]) == 0 && GameCnt > 1)   /* remove */
1851         {
1852             Undo();
1853             Undo();
1854         }
1855         /* CHECKME: are these next three correct? */
1856         else if (!XSHOGI && strcmp(s, CP[207]) == 0)  /* xget */
1857         {
1858             GetXGame();
1859         }
1860         else if (!XSHOGI && strcmp(s, "xsave") == 0)        /* xsave */
1861         {
1862             SaveXGame();
1863         }
1864         else if (!XSHOGI && strcmp(s, "bsave") == 0)        /* bsave */
1865         {
1866             BookSave();
1867         }
1868 #ifdef EASY_OPENINGS
1869         else if ((strcmp(s, "?") == 0)
1870                  || (strcmp(s, "!") == 0)
1871                  || (strcmp(s, "~") == 0))
1872 #else
1873         else if ((strcmp(s, "?") == 0)
1874                  || (strcmp(s, "!") == 0))
1875 #endif
1876         {
1877             FlagMove(*s);
1878         }
1879         else if (strcmp(s, CP[160]) == 0)    /* get */
1880         {
1881             GetGame();
1882         }
1883         else if (strcmp(s, CP[189]) == 0)    /* save */
1884         {
1885             SaveGame();
1886         }
1887         else if (strcmp(s, CP[151]) == 0)    /* depth */
1888         {
1889             ChangeSearchDepth();
1890         }
1891         else if (strcmp(s, CP[164]) == 0)    /* hashdepth */
1892         {
1893             ChangeHashDepth();
1894         }
1895         else if (strcmp(s, CP[182]) == 0)    /* random */
1896         {
1897             dither = DITHER;
1898         }
1899         else if (strcmp(s, CP[229]) == 0)    /* hard */
1900         {
1901             flag.easy = false;
1902         }
1903         else if (strcmp(s, CP[152]) == 0)    /* easy */
1904         {
1905             flag.easy = !flag.easy;
1906         }
1907         else if (strcmp(s, CP[230]) == 0)    /* tsume */
1908         {
1909             flag.tsume = !flag.tsume;
1910         }
1911         else if (strcmp(s, CP[143]) == 0)    /* contempt */
1912         {
1913             SetContempt();
1914         }
1915         else if (strcmp(s, CP[209]) == 0)    /* xwndw */
1916         {
1917             ChangeXwindow();
1918         }
1919         else if (strcmp(s, CP[186]) == 0)    /* rv */
1920         {
1921             flag.rv = !flag.rv;
1922             UpdateDisplay(0, 0, 1, 0);
1923         }
1924         else if (strcmp(s, CP[145]) == 0)    /* coords */
1925         {
1926             flag.coords = !flag.coords;
1927             UpdateDisplay(0, 0, 1, 0);
1928         }
1929         else if (strcmp(s, CP[193]) == 0)    /* stars */
1930         {
1931             flag.stars = !flag.stars;
1932             UpdateDisplay(0, 0, 1, 0);
1933         }
1934         else if (!XSHOGI && strcmp(s, CP[5]) == 0)          /* moves */
1935         {
1936             short temp;
1937
1938 #if MAXDEPTH > 3
1939             if (GameCnt > 0)
1940             {
1941                 extern unsigned short PrVar[MAXDEPTH];
1942
1943                 SwagHt = (GameList[GameCnt].gmove == PrVar[1])
1944                     ? PrVar[2] : 0;
1945             }
1946             else
1947 #endif
1948                 SwagHt = 0;
1949
1950             ShowMessage(CP[108]);  /* test movelist */
1951             temp = generate_move_flags;
1952             generate_move_flags = true;
1953             TestSpeed(MoveList, 1);
1954             generate_move_flags = temp;
1955             ShowMessage(CP[107]);  /* test capturelist */
1956             TestSpeed(CaptureList, 1);
1957             ShowMessage(CP[85]);   /* test score position */
1958             ExaminePosition(opponent);
1959             TestPSpeed(ScorePosition, 1);
1960         }
1961         else if (!XSHOGI && strcmp(s, CP[196]) == 0)    /* test */
1962         {
1963 #ifdef SLOW_CPU
1964             ShowMessage(CP[108]); /* test movelist */
1965             TestSpeed(MoveList, 2000);
1966             ShowMessage(CP[107]); /* test capturelist */
1967             TestSpeed(CaptureList, 3000);
1968             ShowMessage(CP[85]); /* test score position */
1969             ExaminePosition(opponent);
1970             TestPSpeed(ScorePosition, 1500);
1971 #else
1972             ShowMessage(CP[108]); /* test movelist */
1973             TestSpeed(MoveList, 20000);
1974             ShowMessage(CP[107]); /* test capturelist */
1975             TestSpeed(CaptureList, 30000);
1976             ShowMessage(CP[85]); /* test score position */
1977             ExaminePosition(opponent);
1978             TestPSpeed(ScorePosition, 15000);
1979 #endif
1980         }
1981         else if (!XSHOGI && strcmp(s, CP[179]) == 0) /* p */
1982         {
1983             ShowPostnValues();
1984         }
1985         else if (!XSHOGI && strcmp(s, CP[148]) == 0)    /* debug */
1986         {
1987             DoDebug();
1988         }
1989         else
1990         {
1991             if (flag.mate)
1992             {
1993                 ok = true;
1994             }
1995             else if ((ok = VerifyMove(s, VERIFY_AND_MAKE_MODE, &mv)))
1996             {
1997                 /* check for repetition */
1998                 short rpt = repetition();
1999
2000                 if (rpt >= 3)
2001                 {
2002                     DRAW = CP[101];
2003                     ShowMessage(DRAW);
2004                     GameList[GameCnt].flags |= draw;
2005
2006                         flag.mate = true;
2007                 }
2008                 else
2009                 {
2010                     is_move = true;
2011                 }
2012             }
2013
2014             Sdepth = 0;
2015         }
2016     }
2017
2018     ElapsedTime(COMPUTE_AND_INIT_MODE);
2019
2020     if (flag.force)
2021     {
2022         computer = opponent;
2023         opponent = computer ^ 1;
2024     }
2025
2026     if (XSHOGI)
2027     {
2028         /* add remaining time in milliseconds for xshogi */
2029         if (is_move)
2030         {
2031             printf("%d. %s %ld\n",
2032                    ++mycnt2, s, TimeControl.clock[player] * 10);
2033         }
2034
2035 #ifdef notdef /* optional pass best line to frontend with move */
2036 #  if !defined NOPOST
2037
2038         if (flag.post && !flag.mate)
2039         {
2040             int i;
2041
2042             printf(" %6d ", MSCORE);
2043
2044             for (i = 1; MV[i] > 0; i++)
2045             {
2046                 algbr((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false);
2047                 printf("%5s ", mvstr[0]);
2048             }
2049         }
2050 #  endif
2051         printf("\n");
2052 #endif
2053     }
2054 }
2055
2056
2057
2058
2059 void
2060 SetTimeControl(void)
2061 {
2062     if (TCflag)
2063     {
2064         TimeControl.moves[black] = TimeControl.moves[white] = TCmoves;
2065         TimeControl.clock[black] += 6000L * TCminutes + TCseconds * 100;
2066         TimeControl.clock[white] += 6000L * TCminutes + TCseconds * 100;
2067     }
2068     else
2069     {
2070         TimeControl.moves[black] = TimeControl.moves[white] = 0;
2071         TimeControl.clock[black] = TimeControl.clock[white] = 0;
2072     }
2073
2074     flag.onemove = (TCmoves == 1);
2075     et = 0;
2076     ElapsedTime(COMPUTE_AND_INIT_MODE);
2077 }
2078