Initial attempt at minishogi.
[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("Illegal move (in check) %s", 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("Illegal move (no match) %s", s);
343
344     if (!barebones && (cnt > 1))
345     {
346         sprintf(buffer, "Ambiguous Move %s!", 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         ShowMessage("Enter file name: ");
427         RequestInputString(fname, sizeof(fname)-1);
428     }
429
430     if (fname[0] == '\0')
431         strcpy(fname, "shogi.000");
432
433     if ((fd = fopen(fname, "r")) != NULL)
434     {
435         NewGame();
436         fgets(fname, 256, fd);
437         computer = opponent = black;
438         InPtr = fname;
439         skip();
440
441         if (*InPtr == 'c')
442             computer = white;
443         else
444             opponent = white;
445
446         /* FIXME: write a skipn() function so that we can get
447          * 3 skips by doing skipn(3) */
448         skip();
449         skip();
450         skip();
451         Game50 = atoi(InPtr);
452         skip();
453         flag.force = (*InPtr == 'f');
454         fgets(fname, 256, fd); /* empty */
455         fgets(fname, 256, fd);
456         InPtr = &fname[11];
457         skipb();
458         TCflag = atoi(InPtr);
459         skip();
460         InPtr += 14;
461         skipb();
462         OperatorTime = atoi(InPtr);
463         fgets(fname, 256, fd);
464         InPtr = &fname[11];
465         skipb();
466         TimeControl.clock[black] = atol(InPtr);
467         skip();
468         skip();
469         TimeControl.moves[black] = atoi(InPtr);
470         fgets(fname, 256, fd);
471         InPtr = &fname[11];
472         skipb();
473         TimeControl.clock[white] = atol(InPtr);
474         skip();
475         skip();
476         TimeControl.moves[white] = atoi(InPtr);
477         fgets(fname, 256, fd); /* empty */
478
479         for (i = NO_ROWS - 1; i > -1; i--)
480         {
481             fgets(fname, 256, fd);
482             p = &fname[2];
483             InPtr = &fname[23];
484
485             for (j = 0; j < NO_COLS; j++)
486             {
487                 sq = i * NO_COLS + j;
488                 isp = (*p == '+');
489                 p++;
490
491                 if (*p == '-')
492                 {
493                     board[sq] = no_piece;
494                     color[sq] = neutral;
495                 }
496                 else
497                 {
498                     for (c = 0; c < NO_PIECES; c++)
499                     {
500                         if (*p == pxx[c])
501                         {
502                             if (isp)
503                                 board[sq] = promoted[c];
504                             else
505                                 board[sq] = unpromoted[c];
506
507                             color[sq] = white;
508                         }
509                     }
510
511                     for (c = 0; c < NO_PIECES; c++)
512                     {
513                         if (*p == qxx[c])
514                         {
515                             if (isp)
516                                 board[sq] = promoted[c];
517                             else
518                                 board[sq] = unpromoted[c];
519
520                             color[sq] = black;
521                         }
522                     }
523                 }
524
525                 p++;
526                 Mvboard[sq] = atoi(InPtr);
527                 skip();
528             }
529         }
530
531         fgets(fname, 256, fd);  /* empty */
532         fgets(fname, 256, fd);  /* 9 8 7 ... */
533         fgets(fname, 256, fd);  /* empty */
534         fgets(fname, 256, fd);  /* p l n ... */
535         ClearCaptured();
536
537         for (side = 0; side <= 1; side++)
538         {
539             fgets(fname, 256, fd);
540             InPtr = fname;
541             skip();
542             skipb();
543             Captured[side][pawn] = atoi(InPtr);
544             skip();
545 #ifndef MINISHOGI
546             Captured[side][lance] = atoi(InPtr);
547             skip();
548             Captured[side][knight] = atoi(InPtr);
549             skip();
550 #endif
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 == 'W') ? 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         ShowMessage("Enter file name: ");
652         RequestInputString(fname, sizeof(fname)-1);
653     }
654
655     if (fname[0] == '\0')
656         strcpy(fname, "shogi.000");
657
658     if ((fd = fopen(fname, "w")) != NULL)
659     {
660         char *b, *w;
661         b = w = "Human   ";
662
663         if (computer == white)
664             w = "computer";
665
666         if (computer == black)
667             b = "computer";
668
669         fprintf(fd, "White %s Black %s %d %s\n", w, b, Game50,
670                 flag.force ? "force" : "");
671         fputs(empty, fd);
672         fprintf(fd, "TimeControl %d Operator Time %d\n", TCflag, OperatorTime);
673         fprintf(fd, "Black Clock %ld Moves %d\nWhite Clock %ld Moves %d\n",
674                 TimeControl.clock[black], TimeControl.moves[black],
675                 TimeControl.clock[white], TimeControl.moves[white]);
676         fputs(empty, fd);
677
678         for (i = NO_ROWS - 1; i > -1; i--)
679         {
680             fprintf(fd, "%c ", ROW_NAME(i));
681
682             for (c = 0; c < NO_COLS; c++)
683             {
684                 sq = i * NO_COLS + c;
685                 piece = board[sq];
686                 p = is_promoted[piece] ? '+' : ' ';
687                 fprintf(fd, "%c", p);
688
689                 switch(color[sq])
690                 {
691                 case white:
692                     p = pxx[piece];
693                     break;
694
695                 case black:
696                     p = qxx[piece];
697                     break;
698
699                 default:
700                     p = '-';
701                 }
702
703                 fprintf(fd, "%c", p);
704             }
705
706             fprintf(fd, "  ");
707
708             for (f = i * NO_COLS; f < i * NO_COLS + NO_ROWS; f++)
709                 fprintf(fd, " %d", Mvboard[f]);
710
711             fprintf(fd, "\n");
712         }
713
714         fputs(empty, fd);
715 #ifndef MINISHOGI
716         fprintf(fd, "   9 8 7 6 5 4 3 2 1\n");
717         fputs(empty, fd);
718         fprintf(fd, "   p  l  n  s  g  b  r  k\n");
719 #else
720         fprintf(fd, "   5 4 3 2 1\n");
721         fputs(empty, fd);
722         fprintf(fd, "   p  s  g  b  r  k\n");
723 #endif
724
725         for (side = 0; side <= 1; side++)
726         {
727             fprintf(fd, "%c", (side == black) ? 'B' : 'W');
728             fprintf(fd, " %2d", Captured[side][pawn]);
729 #ifndef MINISHOGI
730             fprintf(fd, " %2d", Captured[side][lance]);
731             fprintf(fd, " %2d", Captured[side][knight]);
732 #endif
733             fprintf(fd, " %2d", Captured[side][silver]);
734             fprintf(fd, " %2d", Captured[side][gold]);
735             fprintf(fd, " %2d", Captured[side][bishop]);
736             fprintf(fd, " %2d", Captured[side][rook]);
737             fprintf(fd, " %2d", Captured[side][king]);
738             fprintf(fd, "\n");
739         }
740
741         fputs(empty, fd);
742         fputs("  move   score depth   nodes   time flags                         capture\n", fd);
743
744         for (i = 1; i <= GameCnt; i++)
745         {
746             struct GameRec  *g = &GameList[i];
747
748             f = g->gmove >> 8;
749             t = (g->gmove & 0xFF);
750             algbr(f, t, g->flags);
751
752             fprintf(fd, "%c%c%-5s %6d %5d %7ld %6ld %5d  0x%08lx 0x%08lx",
753                     ((f > NO_SQUARES)
754                      ? ' '
755                      : (is_promoted[g->fpiece] ? '+' : ' ')),
756                     pxx[g->fpiece],
757                     ((f > NO_SQUARES) ? &mvstr[0][1] : mvstr[0]),
758                     g->score, g->depth,
759                     g->nodes, g->time, g->flags,
760                     g->hashkey, g->hashbd);
761
762             if (g->piece != no_piece)
763             {
764                 fprintf(fd, "  %c %s %c\n",
765                         pxx[g->piece], ColorStr[g->color],
766                         (is_promoted[g->piece] ? '+' : ' '));
767             }
768             else
769             {
770                 fprintf(fd, "\n");
771             }
772         }
773
774         fclose(fd);
775
776         ShowMessage("Game saved");
777     }
778     else
779     {
780         ShowMessage("Could not open file");
781     }
782 }
783
784
785
786 /*
787  * GetXGame, SaveXGame and BookGame used to only be defined if
788  * xshogi wasn't defined -- wonder why?
789  */
790
791 void
792 GetXGame(void)
793 {
794     FILE *fd;
795     char fname[256], *p;
796     int c, i, j;
797     short sq;
798     short side, isp;
799
800     ShowMessage("Enter file name: ");
801     RequestInputString(fname, sizeof(fname)-1);
802
803     if (fname[0] == '\0')
804         strcpy(fname, "xshogi.position.read");
805
806     if ((fd = fopen(fname, "r")) != NULL)
807     {
808         NewGame();
809         flag.regularstart = false;
810         Book = false;
811
812         /* xshogi position file ... */
813         fgets(fname, 256, fd);
814
815 #ifdef notdef
816         fname[6] = '\0';
817
818         if (strcmp(fname, "xshogi"))
819             return;
820 #endif
821
822         /* -- empty line -- */
823         fgets(fname, 256, fd);
824         /* -- empty line -- */
825         fgets(fname, 256, fd);
826
827         for (i = NO_ROWS - 1; i > -1; i--)
828         {
829             fgets(fname, 256, fd);
830             p = fname;
831
832             for (j = 0; j < NO_COLS; j++)
833             {
834                 sq = i * NO_COLS + j;
835                 isp = (*p == '+');
836                 p++;
837
838                 if (*p == '.')
839                 {
840                     board[sq] = no_piece;
841                     color[sq] = neutral;
842                 }
843                 else
844                 {
845                     for (c = 0; c < NO_PIECES; c++)
846                     {
847                         if (*p == qxx[c])
848                         {
849                             if (isp)
850                                 board[sq] = promoted[c];
851                             else
852                                 board[sq] = unpromoted[c];
853
854                             color[sq] = white;
855                         }
856                     }
857
858                     for (c = 0; c < NO_PIECES; c++)
859                     {
860                         if (*p == pxx[c])
861                         {
862                             if (isp)
863                                 board[sq] = promoted[c];
864                             else
865                                 board[sq] = unpromoted[c];
866
867                             color[sq] = black;
868                         }
869                     }
870                 }
871
872                 p++;
873             }
874         }
875
876         ClearCaptured();
877
878         for (side = 0; side <= 1; side++)
879         {
880             fgets(fname, 256, fd);
881             InPtr = fname;
882             Captured[side][pawn]   = atoi(InPtr);
883             skip();
884 #ifndef MINISHOGI
885             Captured[side][lance]  = atoi(InPtr);
886             skip();
887             Captured[side][knight] = atoi(InPtr);
888             skip();
889 #endif
890             Captured[side][silver] = atoi(InPtr);
891             skip();
892             Captured[side][gold]   = atoi(InPtr);
893             skip();
894             Captured[side][bishop] = atoi(InPtr);
895             skip();
896             Captured[side][rook]   = atoi(InPtr);
897             skip();
898             Captured[side][king]   = atoi(InPtr);
899         }
900
901         if (fgets(fname, 256, fd) != NULL && strncmp(fname, "white", 5) == 0)
902         {
903             computer = black;
904             opponent = white;
905             xwndw = BXWNDW;
906         }
907
908         fclose(fd);
909     }
910
911     Game50 = 1;
912     ZeroRPT();
913     InitializeStats();
914     UpdateDisplay(0, 0, 1, 0);
915     Sdepth = 0;
916     hint = 0;
917 }
918
919
920 void
921 SaveXGame(void)
922 {
923     FILE *fd;
924     char fname[256], *p;
925     int i, j;
926     short sq, piece;
927     short side, isp;
928
929     ShowMessage("Enter file name: ");
930     RequestInputString(fname, sizeof(fname)-1);
931
932     if (fname[0] == '\0')
933         strcpy(fname, "xshogi.position.read");
934
935     if ((fd = fopen(fname, "w")) != NULL)
936     {
937         fputs("# xshogi position file -- \n", fd);
938         fputs("\n", fd);
939         fputs("\n", fd);
940
941         for (i = NO_ROWS - 1; i > -1; i--)
942         {
943             p = fname;
944
945             for (j = 0; j < NO_COLS; j++)
946             {
947                 sq = i * NO_COLS + j;
948                 piece = board[sq];
949                 isp = is_promoted[piece];
950                 *p = (isp ? '+' : ' ');
951                 p++;
952
953                 if (piece == no_piece)
954                     *p = '.';
955                 else if (color[sq] == white)
956                     *p = qxx[piece];
957                 else
958                     *p = pxx[piece];
959
960                 p++;
961             }
962
963             *p++ = '\n';
964             *p++ = '\0';
965             fputs(fname, fd);
966         }
967
968         for (side = 0; side <= 1; side++)
969         {
970             sprintf(fname,
971 #ifndef MINISHOGI
972                     "%d %d %d %d %d %d %d %d\n",
973 #else
974                     "%d %d %d %d %d %d\n",
975 #endif
976                     Captured[side][pawn],
977 #ifndef MINISHOGI
978                     Captured[side][lance],
979                     Captured[side][knight],
980 #endif
981                     Captured[side][silver],
982                     Captured[side][gold],
983                     Captured[side][bishop],
984                     Captured[side][rook],
985                     Captured[side][king]);
986
987             fputs(fname, fd);
988         }
989
990         if (computer == black)
991             fputs("white to play\n", fd);
992         else
993             fputs("black to play\n", fd);
994
995         fclose(fd);
996     }
997 }
998
999
1000 void
1001 BookSave(void)
1002 {
1003     FILE *fd;
1004     char fname[256], sflags[4];
1005     short i, j, f, t;
1006
1007     if (savefile[0]) {
1008         strcpy(fname, savefile);
1009     } else {
1010         /* Enter file name */
1011         ShowMessage("Enter file name: ");
1012         RequestInputString(fname, sizeof(fname)-1);
1013     }
1014
1015     if (fname[0] == '\0')
1016         return;
1017
1018     if ((fd = fopen(fname, "a")) != NULL)
1019     {
1020         fprintf(fd, "#\n");
1021
1022         for (i = 1; i <= GameCnt; i++)
1023         {
1024             struct GameRec  *g = &GameList[i];
1025             char mvnr[20], mvs[20];
1026
1027             if (i % 2)
1028                 sprintf(mvnr, "%d.", (i + 1)/2);
1029             else
1030                 strcpy(mvnr, "");
1031
1032             f = g->gmove >> 8;
1033             t = (g->gmove & 0xFF);
1034             algbr(f, t, g->flags);
1035             j = 0;
1036
1037             /* determine move quality string */
1038             if (g->flags & goodmove)
1039                 sflags[j++] = '!';
1040
1041             if (g->flags & badmove)
1042                 sflags[j++] = '?';
1043
1044 #ifdef EASY_OPENINGS
1045             if (g->flags & difficult)
1046                 sflags[j++] = '~';
1047 #endif
1048
1049             sflags[j] = '\0';
1050
1051             /* determine move string */
1052             if (f > NO_SQUARES)
1053             {
1054                 sprintf(mvs, "%s%s ", &mvstr[0][1], sflags);
1055             }
1056             else
1057             {
1058                 sprintf(mvs, "%c%c%c%c%c%s%s ",
1059                         mvstr[0][0], mvstr[0][1],
1060                         (g->flags & capture) ? 'x' : '-',
1061                         mvstr[0][2], mvstr[0][3],
1062                         (mvstr[0][4] == '+') ? "+" : "",
1063                         sflags);
1064             }
1065
1066             fprintf(fd, "%s%s%c%s",
1067                     mvnr,
1068                     (f > NO_SQUARES
1069                      ? ""
1070                      : (is_promoted[g->fpiece] ? "+" : "")),
1071                     pxx[g->fpiece],
1072                     mvs);
1073
1074             if ((i % 10) == 0)
1075                 fprintf(fd, "\n");
1076         }
1077
1078         if ((i % 10) != 1)
1079             fprintf(fd, "\n");
1080
1081         fclose(fd);
1082
1083         ShowMessage("Game saved");
1084     }
1085     else
1086     {
1087         ShowMessage("Could not open file");
1088     }
1089 }
1090
1091
1092
1093 void
1094 ListGame(void)
1095 {
1096     FILE *fd;
1097     short i, f, t;
1098     time_t when;
1099     char fname[256], dbuf[256];
1100
1101     if (listfile[0])
1102     {
1103         strcpy(fname, listfile);
1104     }
1105     else
1106     {
1107         time(&when);
1108         strncpy(dbuf, ctime(&when), 20);
1109         dbuf[7]  = '\0';
1110         dbuf[10] = '\0';
1111         dbuf[13] = '\0';
1112         dbuf[16] = '\0';
1113         dbuf[19] = '\0';
1114
1115         /* use format "CL.Jan01-020304B" when
1116            date is Jan 1
1117            time is 02:03:04
1118            program played white */
1119
1120         sprintf(fname, "CL.%s%s-%s%s%s%c",
1121                 dbuf + 4, dbuf + 8, dbuf + 11, dbuf + 14,
1122                 dbuf + 17, ColorStr[computer][0]);
1123
1124         /* replace space padding with 0 */
1125         for (i = 0; fname[i] != '\0'; i++)
1126         {
1127             if (fname[i] == ' ')
1128                 fname[i] = '0';
1129         }
1130     }
1131
1132     fd = fopen(fname, "w");
1133
1134     if (!fd)
1135     {
1136         printf("Open failure for file: %s", fname);
1137         exit(1);
1138     }
1139
1140     fprintf(fd, "gnushogi %s game\n", PACKAGE_VERSION);
1141     fputs("         score  depth   nodes  time         ", fd);
1142     fputs("         score  depth   nodes  time\n", fd);
1143
1144     for (i = 1; i <= GameCnt; i++)
1145     {
1146         f = GameList[i].gmove >> 8;
1147         t = (GameList[i].gmove & 0xFF);
1148         algbr(f, t, GameList[i].flags);
1149
1150         if (GameList[i].flags & book)
1151         {
1152             fprintf(fd, "%c%c%-5s  %5d    Book%7ld %5ld",
1153                     ((f > NO_SQUARES)
1154                      ? ' '
1155                      : (is_promoted[GameList[i].fpiece] ? '+' : ' ')),
1156                     pxx[GameList[i].fpiece],
1157                     ((f > NO_SQUARES)
1158                      ? &mvstr[0][1] : mvstr[0]),
1159                     GameList[i].score,
1160                     GameList[i].nodes,
1161                     GameList[i].time);
1162         }
1163         else
1164         {
1165             fprintf(fd, "%c%c%-5s  %5d     %2d %7ld %5ld",
1166                     (f > NO_SQUARES
1167                      ? ' '
1168                      : (is_promoted[GameList[i].fpiece] ? '+' : ' ')),
1169                     pxx[GameList[i].fpiece],
1170                     (f > NO_SQUARES ? &mvstr[0][1] : mvstr[0]),
1171                     GameList[i].score, GameList[i].depth,
1172                     GameList[i].nodes, GameList[i].time);
1173         }
1174
1175         if ((i % 2) == 0)
1176         {
1177             fprintf(fd, "\n");
1178         }
1179         else
1180         {
1181             fprintf(fd, "         ");
1182         }
1183     }
1184
1185     fprintf(fd, "\n\n");
1186
1187     if (GameList[GameCnt].flags & draw)
1188     {
1189         fprintf(fd, "Draw %s\n", DRAW);
1190
1191         if (DRAW == DRAW_REPETITION)
1192         {
1193             short j;
1194
1195             fprintf(fd, "repetition by positions ");
1196
1197             for (j = GameCnt - 1; j >= Game50; j -= 2)
1198             {
1199                 if (GameList[j].hashkey == hashkey &&
1200                     GameList[j].hashbd == hashbd)
1201                     fprintf(fd, "%d ", j);
1202             }
1203
1204             fprintf(fd, "\n");
1205         }
1206     }
1207     else if (GameList[GameCnt].score == -(SCORE_LIMIT + 999))
1208     {
1209         fprintf(fd, "%s\n", ColorStr[player ]);
1210     }
1211     else if (GameList[GameCnt].score == (SCORE_LIMIT + 998))
1212     {
1213         fprintf(fd, "%s\n", ColorStr[player ^ 1]);
1214     }
1215
1216     fclose(fd);
1217 }
1218
1219
1220
1221 void
1222 FlagMove(char c)
1223 {
1224     switch(c)
1225     {
1226     case '?' :
1227         GameList[GameCnt].flags |= badmove;
1228         break;
1229
1230     case '!' :
1231         GameList[GameCnt].flags |= goodmove;
1232         break;
1233
1234 #ifdef EASY_OPENINGS
1235     case '~' :
1236         GameList[GameCnt].flags |= difficult;
1237         break;
1238 #endif
1239     }
1240 }
1241
1242
1243
1244
1245 /*
1246  * Undo the most recent half-move.
1247  */
1248
1249 void
1250 Undo(void)
1251 {
1252     short f, t;
1253
1254     f = GameList[GameCnt].gmove >> 8;
1255     t = GameList[GameCnt].gmove & 0x7F;
1256
1257     if (f > NO_SQUARES)
1258     {
1259         /* the move was a drop */
1260         Captured[color[t]][board[t]]++;
1261         board[t] = no_piece;
1262         color[t] = neutral;
1263         Mvboard[t]--;
1264     }
1265     else
1266     {
1267         if (GameList[GameCnt].flags & promote)
1268             board[f] = unpromoted[board[t]];
1269         else
1270             board[f] = board[t];
1271
1272         color[f] = color[t];
1273         board[t] = GameList[GameCnt].piece;
1274         color[t] = GameList[GameCnt].color;
1275
1276         if (board[t] != no_piece)
1277             Captured[color[f]][unpromoted[board[t]]]--;
1278
1279         if (color[t] != neutral)
1280             Mvboard[t]--;
1281
1282         Mvboard[f]--;
1283     }
1284
1285     InitializeStats();
1286
1287     if (TCflag && (TCmoves > 1))
1288         ++TimeControl.moves[color[f]];
1289
1290     hashkey = GameList[GameCnt].hashkey;
1291     hashbd = GameList[GameCnt].hashbd;
1292     GameCnt--;
1293     computer = computer ^ 1;
1294     opponent = opponent ^ 1;
1295     flag.mate = false;
1296     Sdepth = 0;
1297     player = player ^ 1;
1298     ShowSidetoMove();
1299     UpdateDisplay(0, 0, 1, 0);
1300
1301     if (flag.regularstart)
1302         Book = false;
1303 }
1304
1305
1306
1307 void
1308 FlagString(unsigned short flags, char *s)
1309 {
1310     short l, piece;
1311     *s = '\0';
1312
1313     if (flags & promote)
1314         strcat(s, " promote");
1315
1316     if (flags & dropmask)
1317         strcat(s, " drop:");
1318
1319     if ((piece = (flags & pmask)))
1320     {
1321         l = strlen(s);
1322
1323         if (is_promoted[piece])
1324             s[l++] = '+';
1325
1326         s[l++] = pxx[piece];
1327         s[l] = '\0';
1328     }
1329
1330     if (flags & capture)
1331         strcat(s, " capture");
1332
1333     if (flags & exact)
1334         strcat(s, " exact");
1335
1336     if (flags & tesuji)
1337         strcat(s, " tesuji");
1338
1339     if (flags & check)
1340         strcat(s, " check");
1341
1342     if (flags & draw)
1343         strcat(s, " draw");
1344
1345     if (flags & stupid)
1346         strcat(s, " stupid");
1347
1348     if (flags & questionable)
1349         strcat(s, " questionable");
1350
1351     if (flags & kingattack)
1352         strcat(s, " kingattack");
1353
1354     if (flags & book)
1355         strcat(s, " book");
1356 }
1357
1358
1359
1360 void
1361 TestSpeed(void(*f)(short side, short ply,
1362                    short in_check, short blockable),
1363           unsigned j)
1364 {
1365 #ifdef test
1366     unsigned jj;
1367 #endif
1368
1369     unsigned i;
1370     long cnt, t1, t2;
1371
1372 #ifdef HAVE_GETTIMEOFDAY
1373     struct timeval tv;
1374 #endif
1375
1376 #ifdef HAVE_GETTIMEOFDAY
1377     gettimeofday(&tv, NULL);
1378     t1 = (tv.tv_sec*100 + (tv.tv_usec/10000));
1379 #else
1380     t1 = time(0);
1381 #endif
1382
1383     for (i = 0; i < j; i++)
1384     {
1385         f(opponent, 2, -1, true);
1386
1387 #ifdef test
1388         for (jj = TrPnt[2]; i < TrPnt[3]; jj++)
1389         {
1390             if (!pick(jj, TrPnt[3] - 1))
1391                 break;
1392         }
1393 #endif
1394     }
1395
1396 #ifdef HAVE_GETTIMEOFDAY
1397     gettimeofday(&tv, NULL);
1398     t2 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1399 #else
1400     t2 = time(0);
1401 #endif
1402
1403     cnt = j * (TrPnt[3] - TrPnt[2]);
1404
1405     if (t2 - t1)
1406         et = (t2 - t1);
1407     else
1408         et = 1;
1409
1410     ShowNodeCnt(cnt);
1411 }
1412
1413
1414
1415 void
1416 TestPSpeed(short(*f) (short side), unsigned j)
1417 {
1418     short i;
1419     long cnt, t1, t2;
1420 #ifdef HAVE_GETTIMEOFDAY
1421     struct timeval tv;
1422 #endif
1423
1424 #ifdef HAVE_GETTIMEOFDAY
1425     gettimeofday(&tv, NULL);
1426     t1 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1427 #else
1428     t1 = time(0);
1429 #endif
1430
1431     for (i = 0; i < j; i++)
1432         (void) f(opponent);
1433
1434 #ifdef HAVE_GETTIMEOFDAY
1435     gettimeofday(&tv, NULL);
1436     t2 = (tv.tv_sec * 100 + (tv.tv_usec / 10000));
1437 #else
1438     t2 = time(0);
1439 #endif
1440
1441     cnt = j;
1442
1443     if (t2 - t1)
1444         et = (t2 - t1);
1445     else
1446         et = 1;
1447
1448     ShowNodeCnt(cnt);
1449 }
1450
1451
1452
1453 void
1454 SetOppTime(char *s)
1455 {
1456     char *time;
1457     int m, t, sec;
1458
1459     sec = 0;
1460     time = &s[strlen("otime")];
1461     t = (int)strtol(time, &time, 10);
1462
1463     if (*time == ':')
1464     {
1465         time++;
1466         sec = (int)strtol(time, &time, 10);
1467     }
1468
1469     m = (int)strtol(time, &time, 10);
1470
1471     if (t)
1472         TimeControl.clock[opponent] = t;
1473
1474     if (m)
1475         TimeControl.moves[opponent] = m;
1476
1477     ElapsedTime(COMPUTE_AND_INIT_MODE);
1478
1479     if (XSHOGI)
1480     {
1481         /* just to inform xshogi about availability of otime command */
1482         printf("otime %d %d\n", t, m);
1483     }
1484 }
1485
1486
1487
1488 void
1489 SetMachineTime(char *s)
1490 {
1491     char *time;
1492     int m, t, sec;
1493
1494     time = &s[strlen("time")];
1495     sec = 0;
1496     t = (int)strtol(time, &time, 10);
1497
1498     if (*time == ':')
1499     {
1500         time++;
1501         sec = (int)strtol(time, &time, 10);
1502     }
1503
1504     m = (int)strtol(time, &time, 10);
1505
1506     if (t)
1507         TimeControl.clock[computer] = t;
1508
1509     if (m)
1510         TimeControl.moves[computer] = m;
1511
1512     ElapsedTime(COMPUTE_AND_INIT_MODE);
1513
1514     if (XSHOGI)
1515     {
1516         /* just to inform xshogi about availability of time command */
1517         printf("time %d %d\n", t, m);
1518     }
1519 }
1520
1521
1522
1523
1524
1525 /* FIXME!  This is truly the function from hell! */
1526
1527 /*
1528  * Process the user's command. If easy mode is OFF (the computer is thinking
1529  * on opponents time) and the program is out of book, then make the 'hint'
1530  * move on the board and call SelectMove() to find a response. The user
1531  * terminates the search by entering ^C (quit siqnal) before entering a
1532  * command. If the opponent does not make the hint move, then set Sdepth to
1533  * zero.
1534  */
1535
1536 void
1537 InputCommand(char *command)
1538 {
1539     int eof = 0;
1540     short have_shown_prompt = false;
1541     short ok, done, is_move = false;
1542     unsigned short mv;
1543     char s[80], sx[80];
1544
1545     ok = flag.quit = done = false;
1546     player = opponent;
1547
1548 #if ttblsz
1549     if (TTadd > ttbllimit)
1550         ZeroTTable();
1551 #endif
1552
1553     if ((hint > 0) && !flag.easy && !flag.force)
1554     {
1555         /*
1556          * A hint move for the player is available.  Compute a move for the
1557          * opponent in background mode assuming that the hint move will be
1558          * selected by the player.
1559          */
1560
1561         ft = time0; /* Save reference time for the player. */
1562         fflush(stdout);
1563         algbr((short) hint >> 8, (short) hint & 0xff, false);
1564         strcpy(s, mvstr[0]);
1565
1566 #if !defined NOPOST
1567         if (flag.post)
1568             GiveHint();
1569 #endif
1570
1571         /* do the hint move */
1572         if (VerifyMove(s, VERIFY_AND_TRY_MODE, &mv))
1573         {
1574             Sdepth = 0;
1575
1576 #ifdef QUIETBACKGROUND
1577             ShowPrompt();
1578             have_shown_prompt = true;
1579 #endif /* QUIETBACKGROUND */
1580
1581             /* Start computing a move until the search is interrupted. */
1582
1583 #ifdef INTERRUPT_TEST
1584             itime0 = 0;
1585 #endif
1586
1587             /* would love to put null move in here */
1588             /* after we make the hint move make a 2 ply search
1589              * with both plys our moves */
1590             /* think on opponents time */
1591             SelectMove(computer, BACKGROUND_MODE);
1592
1593 #ifdef INTERRUPT_TEST
1594             ElapsedTime(COMPUTE_INTERRUPT_MODE);
1595
1596             if (itime0 == 0)
1597             {
1598                 printf("searching not terminated by interrupt!\n");
1599             }
1600             else
1601             {
1602                 printf("elapsed time from interrupt to "
1603                        "terminating search: %ld\n", it);
1604             }
1605 #endif
1606
1607             /* undo the hint and carry on */
1608             VerifyMove(s, UNMAKE_MODE, &mv);
1609             Sdepth = 0;
1610         }
1611
1612         time0 = ft; /* Restore reference time for the player. */
1613     }
1614
1615     while(!(ok || flag.quit || done))
1616     {
1617         player = opponent;
1618
1619 #ifdef QUIETBACKGROUND
1620         if (!have_shown_prompt)
1621         {
1622 #endif /* QUIETBACKGROUND */
1623
1624             ShowPrompt();
1625
1626 #ifdef QUIETBACKGROUND
1627         }
1628
1629         have_shown_prompt = false;
1630 #endif /* QUIETBACKGROUND */
1631
1632         if (command == NULL) {
1633             if (NOT_CURSES)
1634                 s[0] = '\0';
1635
1636             eof = GetString(sx);
1637         } else {
1638             strcpy(sx, command);
1639             done = true;
1640         }
1641
1642         sscanf(sx, "%s", s);
1643
1644         if (eof)
1645             ExitShogi();
1646
1647         if (s[0] == '\0')
1648             continue;
1649
1650         if (strcmp(s, "bd") == 0)   /* bd -- display board */
1651         {
1652             /* FIXME: Hack alert! */
1653             short old_xshogi = XSHOGI;
1654
1655             if (old_xshogi)
1656                 display_type = DISPLAY_RAW;
1657
1658             ClearScreen();
1659             UpdateDisplay(0, 0, 1, 0);
1660
1661             if (old_xshogi)
1662                 display_type = DISPLAY_X;
1663         }
1664         else if (strcmp(s, "post") == 0)
1665         {
1666             flag.post = !flag.post;
1667         }
1668         else if (strcmp(s, "alg") == 0)
1669         {
1670             /* noop */ ; /* alg */
1671         }
1672         else if ((strcmp(s, "quit") == 0)
1673                  || (strcmp(s, "exit") == 0))
1674         {
1675             flag.quit = true;
1676         }
1677 #if !defined NOPOST
1678         else if (strcmp(s, "post") == 0)
1679         {
1680             flag.post = !flag.post;
1681         }
1682 #endif
1683         else if ((strcmp(s, "set") == 0)
1684                  || (strcmp(s, "edit") == 0))
1685         {
1686             EditBoard();
1687         }
1688         else if ((strcmp(s, "setup") == 0))
1689         {
1690             SetupBoard();
1691         }
1692         else if (strcmp(s, "first") == 0)
1693         {
1694             ok = true;
1695         }
1696         else if (strcmp(s, "go") == 0)
1697         {
1698             ok = true;
1699             flag.force = false;
1700
1701             if (computer == black)
1702             {
1703                 computer = white;
1704                 opponent = black;
1705             }
1706             else
1707             {
1708                 computer = black;
1709                 opponent = white;
1710             }
1711         }
1712         else if (strcmp(s, "help") == 0)
1713         {
1714             help();
1715         }
1716         else if (strcmp(s, "material") == 0)
1717         {
1718             flag.material = !flag.material;
1719         }
1720         else if (strcmp(s, "force") == 0)
1721         {
1722             if (XSHOGI)
1723             {
1724                 flag.force = true;
1725                 flag.bothsides = false;
1726             }
1727             else
1728             {
1729                 flag.force = !flag.force;
1730                 flag.bothsides = false;
1731             }
1732         }
1733         else if (strcmp(s, "book") == 0)
1734         {
1735             Book = Book ? 0 : BOOKFAIL;
1736         }
1737         else if (strcmp(s, "new") == 0)
1738         {
1739             NewGame();
1740             UpdateDisplay(0, 0, 1, 0);
1741         }
1742         else if (strcmp(s, "list") == 0)
1743         {
1744             ListGame();
1745         }
1746         else if ((strcmp(s, "level") == 0)
1747                  || (strcmp(s, "clock") == 0))
1748         {
1749             SelectLevel(sx);
1750         }
1751         else if (strcmp(s, "hash") == 0)
1752         {
1753             flag.hash = !flag.hash;
1754         }
1755         else if (strcmp(s, "gamein") == 0)
1756         {
1757             flag.gamein = !flag.gamein;
1758         }
1759         else if (strcmp(s, "beep") == 0)
1760         {
1761             flag.beep = !flag.beep;
1762         }
1763         else if (strcmp(s, "time") == 0)
1764         {
1765             SetMachineTime(sx);
1766         }
1767         else if (strcmp(s, "otime") == 0)
1768         {
1769             SetOppTime(sx);
1770         }
1771         else if (strcmp(s, "Awindow") == 0)
1772         {
1773             ChangeAlphaWindow();
1774         }
1775         else if (strcmp(s, "Bwindow") == 0)
1776         {
1777             ChangeBetaWindow();
1778         }
1779         else if (strcmp(s, "rcptr") == 0)
1780         {
1781             flag.rcptr = !flag.rcptr;
1782         }
1783         else if (strcmp(s, "hint") == 0)
1784         {
1785             GiveHint();
1786         }
1787         else if (strcmp(s, "both") == 0)
1788         {
1789             flag.bothsides = !flag.bothsides;
1790             flag.force = false;
1791             Sdepth = 0;
1792             ElapsedTime(COMPUTE_AND_INIT_MODE);
1793             SelectMove(opponent, FOREGROUND_MODE);
1794             ok = true;
1795         }
1796         else if (strcmp(s, "reverse") == 0)
1797         {
1798             flag.reverse = !flag.reverse;
1799             ClearScreen();
1800             UpdateDisplay(0, 0, 1, 0);
1801         }
1802         else if (strcmp(s, "switch") == 0)
1803         {
1804             computer = computer ^ 1;
1805             opponent = opponent ^ 1;
1806             xwndw = (computer == black) ? WXWNDW : BXWNDW;
1807             flag.force = false;
1808             Sdepth = 0;
1809             ok = true;
1810         }
1811         else if (strcmp(s, "black") == 0)
1812         {
1813             computer = white;
1814             opponent = black;
1815             xwndw = WXWNDW;
1816             flag.force = false;
1817             Sdepth = 0;
1818
1819             /*
1820              * ok = true; don't automatically start with black command
1821              */
1822         }
1823         else if (strcmp(s, "white") == 0)
1824         {
1825             computer = black;
1826             opponent = white;
1827             xwndw = BXWNDW;
1828             flag.force = false;
1829             Sdepth = 0;
1830
1831             /*
1832              * ok = true; don't automatically start with white command
1833              */
1834         }
1835         else if (strcmp(s, "undo") == 0 && GameCnt > 0)
1836         {
1837             Undo();
1838         }
1839         else if (strcmp(s, "remove") == 0 && GameCnt > 1)
1840         {
1841             Undo();
1842             Undo();
1843         }
1844         /* CHECKME: are these next three correct? */
1845         else if (!XSHOGI && strcmp(s, "xget") == 0)
1846         {
1847             GetXGame();
1848         }
1849         else if (!XSHOGI && strcmp(s, "xsave") == 0)
1850         {
1851             SaveXGame();
1852         }
1853         else if (!XSHOGI && strcmp(s, "bsave") == 0)
1854         {
1855             BookSave();
1856         }
1857 #ifdef EASY_OPENINGS
1858         else if ((strcmp(s, "?") == 0)
1859                  || (strcmp(s, "!") == 0)
1860                  || (strcmp(s, "~") == 0))
1861 #else
1862         else if ((strcmp(s, "?") == 0)
1863                  || (strcmp(s, "!") == 0))
1864 #endif
1865         {
1866             FlagMove(*s);
1867         }
1868         else if (strcmp(s, "get") == 0)
1869         {
1870             GetGame();
1871         }
1872         else if (strcmp(s, "save") == 0)
1873         {
1874             SaveGame();
1875         }
1876         else if (strcmp(s, "depth") == 0)
1877         {
1878             ChangeSearchDepth();
1879         }
1880         else if (strcmp(s, "hashdepth") == 0)
1881         {
1882             ChangeHashDepth();
1883         }
1884         else if (strcmp(s, "random") == 0)
1885         {
1886             dither = DITHER;
1887         }
1888         else if (strcmp(s, "hard") == 0)
1889         {
1890             flag.easy = false;
1891         }
1892         else if (strcmp(s, "easy") == 0)
1893         {
1894             flag.easy = !flag.easy;
1895         }
1896         else if (strcmp(s, "tsume") == 0)
1897         {
1898             flag.tsume = !flag.tsume;
1899         }
1900         else if (strcmp(s, "contempt") == 0)
1901         {
1902             SetContempt();
1903         }
1904         else if (strcmp(s, "xwndw") == 0)
1905         {
1906             ChangeXwindow();
1907         }
1908         else if (strcmp(s, "rv") == 0)
1909         {
1910             flag.rv = !flag.rv;
1911             UpdateDisplay(0, 0, 1, 0);
1912         }
1913         else if (strcmp(s, "coords") == 0)
1914         {
1915             flag.coords = !flag.coords;
1916             UpdateDisplay(0, 0, 1, 0);
1917         }
1918         else if (strcmp(s, "stars") == 0)
1919         {
1920             flag.stars = !flag.stars;
1921             UpdateDisplay(0, 0, 1, 0);
1922         }
1923         else if (!XSHOGI && strcmp(s, "moves") == 0)
1924         {
1925             short temp;
1926
1927 #if MAXDEPTH > 3
1928             if (GameCnt > 0)
1929             {
1930                 extern unsigned short PrVar[MAXDEPTH];
1931
1932                 SwagHt = (GameList[GameCnt].gmove == PrVar[1])
1933                     ? PrVar[2] : 0;
1934             }
1935             else
1936 #endif
1937                 SwagHt = 0;
1938
1939             ShowMessage("Testing MoveList Speed");
1940             temp = generate_move_flags;
1941             generate_move_flags = true;
1942             TestSpeed(MoveList, 1);
1943             generate_move_flags = temp;
1944             ShowMessage("Testing CaptureList Speed");
1945             TestSpeed(CaptureList, 1);
1946             ShowMessage("Testing Eval Speed");
1947             ExaminePosition(opponent);
1948             TestPSpeed(ScorePosition, 1);
1949         }
1950         else if (!XSHOGI && strcmp(s, "test") == 0)
1951         {
1952 #ifdef SLOW_CPU
1953             ShowMessage("Testing MoveList Speed");
1954             TestSpeed(MoveList, 2000);
1955             ShowMessage("Testing CaptureList Speed");
1956             TestSpeed(CaptureList, 3000);
1957             ShowMessage("Testing Eval Speed");
1958             ExaminePosition(opponent);
1959             TestPSpeed(ScorePosition, 1500);
1960 #else
1961             ShowMessage("Testing MoveList Speed");
1962             TestSpeed(MoveList, 20000);
1963             ShowMessage("Testing CaptureList Speed");
1964             TestSpeed(CaptureList, 30000);
1965             ShowMessage("Testing Eval Speed");
1966             ExaminePosition(opponent);
1967             TestPSpeed(ScorePosition, 15000);
1968 #endif
1969         }
1970         else if (!XSHOGI && strcmp(s, "p") == 0)
1971         {
1972             ShowPostnValues();
1973         }
1974         else if (!XSHOGI && strcmp(s, "debug") == 0)
1975         {
1976             DoDebug();
1977         }
1978         else
1979         {
1980             if (flag.mate)
1981             {
1982                 ok = true;
1983             }
1984             else if ((ok = VerifyMove(s, VERIFY_AND_MAKE_MODE, &mv)))
1985             {
1986                 /* check for repetition */
1987                 short rpt = repetition();
1988
1989                 if (rpt >= 3)
1990                 {
1991                     DRAW = DRAW_REPETITION;
1992                     ShowMessage(DRAW);
1993                     GameList[GameCnt].flags |= draw;
1994
1995                         flag.mate = true;
1996                 }
1997                 else
1998                 {
1999                     is_move = true;
2000                 }
2001             }
2002
2003             Sdepth = 0;
2004         }
2005     }
2006
2007     ElapsedTime(COMPUTE_AND_INIT_MODE);
2008
2009     if (flag.force)
2010     {
2011         computer = opponent;
2012         opponent = computer ^ 1;
2013     }
2014
2015     if (XSHOGI)
2016     {
2017         /* add remaining time in milliseconds for xshogi */
2018         if (is_move)
2019         {
2020             printf("%d. %s %ld\n",
2021                    ++mycnt2, s, TimeControl.clock[player] * 10);
2022         }
2023
2024 #ifdef notdef /* optional pass best line to frontend with move */
2025 #  if !defined NOPOST
2026
2027         if (flag.post && !flag.mate)
2028         {
2029             int i;
2030
2031             printf(" %6d ", MSCORE);
2032
2033             for (i = 1; MV[i] > 0; i++)
2034             {
2035                 algbr((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false);
2036                 printf("%5s ", mvstr[0]);
2037             }
2038         }
2039 #  endif
2040         printf("\n");
2041 #endif
2042     }
2043 }
2044
2045
2046
2047
2048 void
2049 SetTimeControl(void)
2050 {
2051     if (TCflag)
2052     {
2053         TimeControl.moves[black] = TimeControl.moves[white] = TCmoves;
2054         TimeControl.clock[black] += 6000L * TCminutes + TCseconds * 100;
2055         TimeControl.clock[white] += 6000L * TCminutes + TCseconds * 100;
2056     }
2057     else
2058     {
2059         TimeControl.moves[black] = TimeControl.moves[white] = 0;
2060         TimeControl.clock[black] = TimeControl.clock[white] = 0;
2061     }
2062
2063     flag.onemove = (TCmoves == 1);
2064     et = 0;
2065     ElapsedTime(COMPUTE_AND_INIT_MODE);
2066 }
2067