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