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