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