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