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