home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gnuch40.zip / gnuchess-4.0.pl79 / src / gnuan.c < prev    next >
C/C++ Source or Header  |  1999-01-15  |  41KB  |  1,761 lines

  1. /*
  2.  * gnuan.c - Analysis interface for gnuchess.
  3.  * 
  4.  * Copyright (c) 1985-1996 Stuart Cracraft, John Stanback,
  5.  *                         Daryl Baker, Conor McCarthy,
  6.  *                         Mike McGann, Chua Kong Sian
  7.  * Copyright (c) 1985-1996 Free Software Foundation
  8.  * 
  9.  * This file is part of GNU CHESS.
  10.  * 
  11.  * GNU Chess is free software; you can redistribute it and/or modify it under
  12.  * the terms of the GNU General Public License as published by the Free
  13.  * Software Foundation; either version 2, or (at your option) any later
  14.  * version.
  15.  * 
  16.  * GNU Chess is distributed in the hope that it will be useful, but WITHOUT ANY
  17.  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  18.  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  19.  * details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License along with
  22.  * GNU Chess; see the file COPYING.  If not, write to the Free Software
  23.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. /*
  27.  * This is a front end for a chess analysis program.  It takes a file of
  28.  * moves in algebraic notation and creates a file containing each move that
  29.  * was made, the move it would have made, the score it would give itself
  30.  * after making the move it recommended, and the depth it searched for the
  31.  * move.
  32.  * 
  33.  * This is a modification of nondsp.c.  I have cut out code that was not needed
  34.  * for this application such as the help and edit functions.  Most of the
  35.  * modifications were done in InputCommand.
  36.  */
  37.  
  38. /*
  39.  * This file will generate two different analysis programs.  One is meant to
  40.  * be run as a background process inwhich the in and out files are
  41.  * predefined. The other is meant to be run in the foreground where it will
  42.  * prompt you for the name of the file with the game in it, the maximum depth
  43.  * the search should be conducted to and the time limit per move.  It would
  44.  * be nice to be able to give these parameters on the command line, but that
  45.  * would mean changing main which is in the gnuchess.c file.
  46.  * 
  47.  * For each move it will analyse the move until either it has run out of time or
  48.  * it has reached the maximum depth.
  49.  * 
  50.  * To build the version for background processing define BACKGROUND_ANALYSIS
  51.  * either at the top of this file, or in compilation.  The files and depth
  52.  * used are defined below.  They are MAX_DEPTH, MAX_TIME, OUT_FILE, IN_FILE
  53.  * and PROG_FILE.  The PROG_FILE is a file that will be updated as each move
  54.  * is analysed so you can check its progress.  This is only updated when
  55.  * running the BACKGROUND_ANALYSIS version.  In the version where the
  56.  * filename and depth are entered at runtime, the output goes to stdout.
  57.  */
  58.  
  59. #undef BACKGROUND_ANALYSIS
  60.  
  61. #define MAX_DEPTH  MAXDEPTH
  62. #define MAX_MINUTE 0
  63. #define MAX_SECOND 20
  64. #define OUT_FILE   "gnuan.out"
  65. #define IN_FILE    "gnuan.in"
  66. #define PROG_FILE  "gnuan.prog"
  67.  
  68.  
  69. #include <ctype.h>
  70. #include <signal.h>
  71. #include <fcntl.h>
  72. #ifdef MSDOS
  73. #include <dos.h>
  74. /*#include <conio.h>*/
  75. #include <stdlib.h>
  76. #include <string.h>
  77. /*#include <io.h>*/
  78. #else
  79. #include <sys/param.h>
  80. #include <sys/types.h>
  81. #include <sys/file.h>
  82. #ifndef AMIGADOS
  83. #include <sys/ioctl.h>
  84. #endif
  85. void TerminateSearch (int), Die (int);
  86.  
  87. #ifndef __EMX__
  88. #define O_BINARY 0
  89. #endif
  90.  
  91. #endif /* MSDOS */
  92.  
  93. #include "gnuchess.h"
  94. #include "ttable.h"
  95. #include "ataks.h"
  96. #undef rxx
  97. #undef cxx
  98. #undef scanz
  99. #undef printz
  100.  
  101. #define rxx "12345678"
  102. #define cxx "abcdefgh"
  103. #define scanz scanf
  104. #define printz printf
  105. extern SHORT board[64], color[64], Mvboard[64];
  106. extern CHAR *ColorStr[2];
  107. SHORT debuglevel = 0;
  108. int mycnt1, mycnt2;
  109. char mvstr[5][7];
  110.  
  111. static FILE *fpin;
  112. static FILE *fpout;
  113. int samedepth = false;
  114. CHAR *DRAW;
  115. UTSHORT MV[MAXDEPTH+1];
  116. enum
  117.   {
  118.       XBOARD, GNUCHESS, PGN, OTHER
  119.   }
  120. InFileType;
  121. CHAR InBuf[256];
  122.  
  123. #ifdef BACKGROUND_ANALYSIS
  124. static FILE *fpprog;
  125.  
  126. #endif
  127. static CHAR white_actual_move[20];
  128. static CHAR black_actual_move[20];
  129. static CHAR suggest_move[20];
  130. static CHAR suggest_move1[20];
  131. static CHAR suggest_move2[20];
  132. static CHAR suggest_move3[20];
  133.     int total_moves[2];
  134.     int same_moves[2];
  135. static int sdw, sdb;
  136. static int print_score;
  137. int tmpscore;
  138. static int current_depth;
  139. static int current_score;
  140. static int enable_update_display = 0;
  141. static CHAR GNUANmove[400][16];    /* moves for this game strings */
  142. static SHORT GNUANsd[400];    /* search depth for each move */
  143. static SHORT GNUANnext;        /*                               */
  144. static SHORT GNUANhint;        /*                               */
  145. static SHORT GNUANdepth;    /*Search depth override         */
  146. static SHORT GNUANcurrmove;    /* current move within base  */
  147. static SHORT GNUANbasemove;    /* base for curr move set    */
  148. static SHORT GNUANmovecnt;    /* movecnt within base frame        */
  149. static SHORT GNUANnextstop = 0;    /*loop control proceed to this move */
  150. SHORT GNUANtop;            /* # movees in adjlist   */
  151. SHORT GNUANtopLim = 0;            /* # movees in adjlist   */
  152. static unsigned short GNUANadjlist[20];        /*moves to not use       */
  153. static CHAR GNUANinbuf[256];    /* input buffer     */
  154. struct
  155.   {
  156.       SHORT board[64];
  157.       SHORT color[64];
  158.       SHORT mvboard[64];
  159.       SHORT currmove;
  160.       SHORT movecnt;
  161.       SHORT basemove;
  162.       SHORT moveno;
  163.   }
  164. GNUANsave[20];
  165. SHORT GNUANsavedepth;
  166. static enum INenum
  167.   {
  168.       file, keyboard
  169.   }
  170. GNUANinput;
  171. int move_number = 1;
  172.  
  173. #ifdef notdef
  174. GNUANlist (SHORT mv[])
  175. {
  176.     SHORT B[64], C[64];
  177.     SHORT from, to, i;
  178.     SHORT plain = false;
  179.     memcpy (B, board, sizeof (B));
  180.     memcpy (C, color, sizeof (C));
  181.  
  182.     for (i = 1; mv[i] != 0; i++)
  183.       {
  184.       from = mv[i] >> 8;
  185.       to = mv[i] & 0xff;
  186.       algbr (from, to, 0);
  187.       if(plain) fprintf (fpout, "%5s ", mvstr[0]);
  188.       else fprintf (fpout, "%5s ", mvstr[1]);
  189.       if (mv[i] == WHITECASTLE)
  190.         {
  191.         /* castle short */ board[5] = board[7];
  192.         board[7] = no_piece;
  193.         color[5] = color[7];
  194.         color[7] = neutral;
  195.         }
  196.       else if (mv[i] == LONGWHITECASTLE)
  197.         {
  198.         /* castle short */ board[3] = board[0];
  199.         board[0] = no_piece;
  200.         color[3] = color[0];
  201.         color[0] = neutral;
  202.         }
  203.       else if (mv[i] == BLACKCASTLE)
  204.         {
  205.         /* castle short */ board[60] = board[63];
  206.         board[63] = no_piece;
  207.         color[60] = color[63];
  208.         color[63] = neutral;
  209.         }
  210.       else if (mv[i] == LONGBLACKCASTLE)
  211.         {
  212.         /* castle long */ board[59] = board[56];
  213.         board[56] = no_piece;
  214.         color[59] = color[56];
  215.         color[56] = neutral;
  216.         }
  217. /* could it be en-passant or promote */
  218.       else if (board[from] == pawn && color[from] == black)
  219.         {
  220.         if (row (to) == 0)
  221.           {        /* promote */
  222.                  plain = true;
  223.           }
  224.         else if ((row (from) == 3 && row(to) == 2) && 
  225.             ((column(to) == (column(from) -1)) || 
  226.              (column(to) == column(from) +1))
  227.             && board[to] == no_piece
  228.             && board[to + 8] == pawn
  229.             && color[to + 8] == white)
  230.           {        /* possible en-passant */
  231.              board[to+8] = no_piece;
  232.              color[to+8] = neutral;
  233.           }
  234.         }
  235.       else if (board[from] == pawn && color[from] == white)
  236.         {
  237.         if (row (to) == 7)
  238.           {        /* promote */
  239.                  plain=true;
  240.           }
  241.         else if ((row (from) == 4 && row(to) == 5) && 
  242.             ((column(to) == (column(from) -1)) || 
  243.              (column(to) == column(from) +1))
  244.             && board[to] == no_piece
  245.             && board[to - 8] == pawn
  246.             && color[to - 8] == black)
  247.           {        /* possible en-passant */
  248.              board[to+8] = no_piece;
  249.              color[to+8] = neutral;
  250.           }
  251.         }
  252.  
  253.       board[to] = board[from];
  254.       color[to] = color[from];
  255.       board[from] = no_piece;
  256.       color[from] = neutral;
  257.       }
  258.     memcpy (board, B, sizeof (B));
  259.     memcpy (color, C, sizeof (C));
  260.     return(0);
  261. }
  262. #endif
  263.  
  264. void
  265. GNUANadj ()
  266. {
  267.     int i, b;
  268.     for (i = 0; i < GNUANtop; i++)
  269.       {
  270.       for (b = TrPnt[1]; b < (unsigned) TrPnt[2]; b++)
  271.         {
  272.         if (((Tree[b].f << 8) | Tree[b].t) == GNUANadjlist[i])
  273.           {
  274.               Tree[b].score = DONTUSE;
  275.               break;
  276.           }
  277.         }
  278.       }
  279. }
  280. void
  281. Initialize (void)
  282. {
  283.     mycnt1 = mycnt2 = 0;
  284. }
  285.  
  286. void
  287. ExitChess (void)
  288. {
  289.     ListGame ();
  290.     exit (0);
  291. }
  292.  
  293. #ifndef MSDOS            /* never called!!! */
  294. void
  295. Die (int sig)
  296. {
  297.     ExitChess ();
  298. }
  299.  
  300. #endif /* MSDOS */
  301.  
  302. void
  303. TerminateSearch (int sig)
  304. {
  305. #ifdef MSDOS
  306.     sig++;            /* shut up the compiler */
  307. #endif /* MSDOS */
  308.     if (!flag.timeout)
  309.     flag.musttimeout = true;
  310.     flag.bothsides = false;
  311. }
  312.  
  313. void
  314. algbr (SHORT f, SHORT t, SHORT flag)
  315.  
  316.  
  317. /*
  318.  * Generate move strings in different formats.
  319.  */
  320.  
  321. {
  322.     int m3p;
  323.  
  324.     if (f != t)
  325.       {
  326.       /* algebraic notation */
  327.       mvstr[0][0] = cxx[column (f)];
  328.       mvstr[0][1] = rxx[row (f)];
  329.       mvstr[0][2] = cxx[column (t)];
  330.       mvstr[0][3] = rxx[row (t)];
  331.       mvstr[4][0] = mvstr[0][4] = mvstr[3][0] = '\0';
  332.       if (((mvstr[1][0] = pxx[board[f]]) == CP[2][1]) || (flag & promote))
  333.         {
  334.         if (mvstr[0][0] == mvstr[0][2])        /* pawn did not eat */
  335.           {
  336.               mvstr[2][0] = mvstr[1][0] = mvstr[0][2];    /* to column */
  337.               mvstr[2][1] = mvstr[1][1] = mvstr[0][3];    /* to row */
  338.               m3p = 2;
  339.           }
  340.         else
  341.             /* pawn ate */
  342.           {
  343.               mvstr[2][0] = mvstr[1][0] = mvstr[0][0];    /* column */
  344.               mvstr[2][1] = mvstr[1][1] = mvstr[0][2];    /* to column */
  345.               mvstr[2][2] = mvstr[0][3];
  346.               m3p = 3;    /* to row */
  347.           }
  348.         if (flag & promote)
  349.           {
  350.               mvstr[0][4] = mvstr[1][2] = mvstr[2][m3p] = qxx[flag & pmask];
  351.               mvstr[0][5] = mvstr[1][3] = mvstr[2][m3p + 1] = mvstr[3][0] = '\0';
  352. #ifdef CHESSTOOL
  353.               mvstr[3][0] = mvstr[0][0];    /* Allow e7e8 for chesstool */
  354.               mvstr[3][1] = mvstr[0][1];
  355.               mvstr[3][2] = mvstr[0][2];
  356.               mvstr[3][3] = mvstr[0][3];
  357.               mvstr[3][4] = '\0';
  358. #endif
  359.           }
  360.         else
  361.             mvstr[2][m3p] = mvstr[1][2] = '\0';
  362.         }
  363.       else
  364.           /* not a pawn */
  365.         {
  366.         mvstr[2][0] = mvstr[1][0];
  367.         mvstr[2][1] = mvstr[0][1];
  368.         mvstr[2][2] = mvstr[1][1] = mvstr[0][2];    /* to column */
  369.         mvstr[2][3] = mvstr[1][2] = mvstr[0][3];    /* to row */
  370.         mvstr[2][4] = mvstr[1][3] = '\0';
  371.         strcpy (mvstr[3], mvstr[2]);
  372.         mvstr[3][1] = mvstr[0][0];
  373.         mvstr[4][0] = mvstr[1][0];
  374.         strcpy (&mvstr[4][1], mvstr[0]);
  375.         if (flag & cstlmask)
  376.           {
  377.               if (t > f)
  378.             {
  379.                 strcpy (mvstr[1], mvstr[0]);
  380.                 strcpy (mvstr[0], CP[5]);
  381.                 strcpy (mvstr[2], CP[7]);
  382.                 strcpy (mvstr[3], "O-O");
  383.             }
  384.               else
  385.             {
  386.                 strcpy (mvstr[1], mvstr[0]);
  387.                 strcpy (mvstr[0], CP[6]);
  388.                 strcpy (mvstr[2], CP[8]);
  389.                 strcpy (mvstr[3], "O-O-O");
  390.             }
  391.           }
  392.         }
  393.       }
  394.     else
  395.     mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = mvstr[4][0] = '\0';
  396. }
  397.  
  398. int
  399. strxcmp (char *sx, char *sbase)
  400.  
  401. /*
  402.  * Compare strings sx and sbase, but ignore any 'x' characters found in sx.
  403.  * This kludge lets gnuan parse notation with "x" for capture.
  404.  */
  405. {
  406.     for (;;)
  407.       {
  408.       if (*sx == 'x')
  409.           sx++;
  410.       if (*sx == '\0')
  411.         {
  412.         if (*sbase == '\0')
  413.             return 0;
  414.         else
  415.             return -1;
  416.         }
  417.       if (*sx < *sbase)
  418.           return -1;
  419.       else if (*sx > *sbase)
  420.           return 1;
  421.       sx++;
  422.       sbase++;
  423.       }
  424. }
  425.  
  426.  
  427.  
  428. int
  429. VerifyMove (CHAR * s, SHORT iop, UTSHORT * mv)
  430.  
  431. /*
  432.  * Compare the string 's' to the list of legal moves available for the
  433.  * opponent. If a match is found, make the move on the board.
  434.  */
  435.  
  436. {
  437.     static SHORT pnt, tempb, tempc, tempsf, tempst, cnt;
  438.     static struct leaf xnode;
  439.     struct leaf *node;
  440.  
  441.     *mv = 0;
  442.     if (iop == 2)
  443.       {
  444.       UnmakeMove (computer, &xnode, &tempb, &tempc, &tempsf, &tempst);
  445.       return (false);
  446.       }
  447.     cnt = 0;
  448.     MoveList (computer, 2);
  449.     pnt = TrPnt[2];
  450.     while (pnt < TrPnt[3])
  451.       {
  452.       node = &Tree[pnt++];
  453.       algbr (node->f, node->t, (SHORT) node->flags);
  454.       if (strxcmp (s, mvstr[0]) == 0 || strxcmp (s, mvstr[1]) == 0 ||
  455.           strxcmp (s, mvstr[2]) == 0 || strxcmp (s, mvstr[3]) == 0)
  456.         {
  457.         cnt++;
  458.         xnode = *node;
  459.         }
  460.       }
  461.     if (cnt == 1)
  462.       {
  463.       MakeMove (computer, &xnode, &tempb, &tempc, &tempsf, &tempst);
  464.       if (SqAtakd (PieceList[computer][0], opponent))
  465.         {
  466.         UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  467.         printz ("Illegal move\n");
  468.         return (false);
  469.         }
  470.       else
  471.         {
  472.         if (iop == 1)
  473.             return (true);
  474.  
  475.         /*
  476.          * UpdateDisplay (xnode.f, xnode.t, 0, (SHORT) xnode.flags);
  477.          */
  478.         if ((board[xnode.t] == pawn)
  479.             || (xnode.flags & capture)
  480.             || (xnode.flags & cstlmask))
  481.           {
  482.               Game50 = GameCnt;
  483.               ZeroRPT ();
  484.           }
  485.         GameList[GameCnt].depth = GameList[GameCnt].score = 0;
  486.         GameList[GameCnt].nodes = 0;
  487.         ElapsedTime (1);
  488.         GameList[GameCnt].time = (SHORT) et;
  489.         TimeControl.clock[opponent] -= et;
  490.         --TimeControl.moves[opponent];
  491.         *mv = (xnode.f << 8) | xnode.t;
  492.         algbr (xnode.f, xnode.t, false);
  493.         return (true);
  494.         }
  495.       }
  496. #ifdef CHESSTOOL
  497.     printz ("Illegal move\n");
  498. #else
  499.     if (cnt > 1)
  500.     ShowMessage ("Ambiguous Move!");
  501. #endif
  502.     if (cnt == 0)
  503.       {
  504.       pnt = TrPnt[2];
  505.       while (pnt < TrPnt[3])
  506.         {
  507.         node = &Tree[pnt++];
  508.         algbr (node->f, node->t, (SHORT) node->flags);
  509.         printf ("%s -> %s %s %s %s\n", s, mvstr[0], mvstr[1], mvstr[2], mvstr[3]);
  510.         }
  511.       }
  512.     return (false);
  513. }
  514.  
  515. void
  516. help (void)
  517. {
  518. }
  519.  
  520. void
  521. EditBoard (void)
  522.  
  523. /*
  524.  * Set up a board position. Pieces are entered by typing the piece followed
  525.  * by the location. For example, Nf3 will place a knight on square f3.
  526.  */
  527.  
  528. {
  529. }
  530.  
  531. void
  532. SetupBoard (void)
  533.  
  534. /*
  535.  * Compatibility with Unix chess and the nchesstool. Set up a board position.
  536.  * Eight lines of eight characters are used to setup the board. a8-h8 is the
  537.  * first line. Black pieces are  represented  by  uppercase characters.
  538.  */
  539.  
  540. {
  541. }
  542.  
  543. void
  544. ShowDepth (CHAR ch)
  545. {
  546. #ifdef MSDOS
  547.     ch++;            /* shut up the compiler */
  548. #endif /* MSDOS */
  549. }
  550.  
  551. void
  552. ShowLine (UTSHORT * bstline)
  553. {
  554.     register int i;
  555.  
  556.     for (i = 1; bstline[i] > 0; i++)
  557.       {
  558.       if ((i > 1) && (i % 8 == 1))
  559.           printf ("\n                          ");
  560.       algbr ((SHORT) (bstline[i] >> 8), (SHORT) (bstline[i] & 0xFF), false);
  561.       printf ("%5s ", mvstr[0]);
  562.       }
  563.     printf ("\n");
  564. }
  565.  
  566.  
  567. void
  568. ShowResults (SHORT score, UTSHORT * bstline, CHAR ch)
  569. {
  570.     int i;
  571.  
  572.     if (flag.post)
  573.       {
  574.       ElapsedTime (2);
  575.       printf ("%2d%c %6d %4ld %8ld  ", Sdepth, ch, score, et / 100, NodeCnt);
  576.       ShowLine (bstline);
  577.       }
  578.     current_score = score;
  579.     current_depth = Sdepth;
  580.     for (i = 1; bstline[i] > 0; i++)
  581.       {
  582.       MV[i] = bstline[i];
  583.       }
  584.     MV[i] = 0;
  585. }
  586.  
  587. void
  588. SearchStartStuff (SHORT side)
  589. {
  590.     signal (SIGINT, TerminateSearch);
  591. #ifndef MSDOS
  592.     signal (SIGQUIT, TerminateSearch);
  593. #endif /* MSDOS */
  594.     if (flag.post)
  595.       {
  596.       fprintf (stderr, "\nMove# %d    Target= %ld    Clock: %ld\n",
  597.            move_number,
  598.            ResponseTime, TimeControl.clock[side]);
  599.       }
  600. }
  601.  
  602. void
  603. OutputMove (SHORT score)
  604. {
  605.     strcpy (suggest_move, mvstr[0]);
  606.     strcpy (suggest_move1, mvstr[1]);
  607.     strcpy (suggest_move2, mvstr[2]);
  608.     strcpy (suggest_move3, mvstr[3]);
  609.     print_score = current_score;
  610. }
  611.  
  612.  
  613. #ifdef HAVE_GETTIMEOFDAY
  614. #include <sys/time.h>
  615. void
  616. ElapsedTime (SHORT iop)
  617.  
  618.  
  619. /*
  620.  * Determine the time that has passed since the search was started. If the
  621.  * elapsed time exceeds the target (ResponseTime+ExtraTime) then set timeout
  622.  * to true which will terminate the search. iop = 0 calculate et bump ETnodes
  623.  * iop = 1 calculate et set timeout if time exceeded, calculate et
  624.  */
  625.  
  626. {
  627.     struct timeval tv;
  628.  
  629. #ifndef MSDOS
  630.     int nchar;
  631.     extern int errno;
  632.     int i;
  633.  
  634. #ifdef FIONREAD
  635.     if (i = ioctl ((int) 0, FIONREAD, &nchar))
  636.       {
  637.       perror ("FIONREAD");
  638.       fprintf (stderr,
  639.        "You probably have a non-ANSI <ioctl.h>; see README. %d %d %x\n",
  640.            i, errno, FIONREAD);
  641.       exit (1);
  642.       }
  643.     if (nchar)
  644.       {
  645.       if (!flag.timeout)
  646.           flag.back = true;
  647.       flag.bothsides = false;
  648.       }
  649. #endif /* FIONREAD */
  650. #else
  651.     if (kbhit ())
  652.       {
  653.       if (!flag.timeout)
  654.           flag.back = true;
  655.       flag.bothsides = false;
  656.       }
  657. #endif /* MSDOS */
  658.     gettimeofday (&tv, NULL);
  659.     et = (tv.tv_sec * 100 + (tv.tv_usec / 10000)) - time0;
  660.     ETnodes = NodeCnt + ZNODES;
  661.     if (et < 0)
  662.     et = 0;
  663.     if (iop == 1)
  664.       {
  665.       if (et > ResponseTime + ExtraTime && Sdepth > MINDEPTH)
  666.           flag.timeout = true;
  667.       ETnodes = NodeCnt + ZNODES;
  668.       gettimeofday (&tv, NULL);
  669.       time0 = tv.tv_sec * 100 + tv.tv_usec / 10000;
  670.       }
  671. }
  672.  
  673. #else
  674. void
  675. ElapsedTime (SHORT iop)
  676.  
  677.  
  678. /*
  679.  * Determine the time that has passed since the search was started. If the
  680.  * elapsed time exceeds the target (ResponseTime+ExtraTime) then set timeout
  681.  * to true which will terminate the search. iop = 0 calculate et bump ETnodes
  682.  * iop = 1 calculate et set timeout if time exceeded, calculate et
  683.  */
  684.  
  685. {
  686. #ifndef MSDOS
  687.     int nchar;
  688.     extern int errno;
  689.     int i;
  690.  
  691. #ifdef FIONREAD
  692.     if (i = ioctl ((int) 0, FIONREAD, &nchar))
  693.       {
  694.       perror ("FIONREAD");
  695.       fprintf (stderr,
  696.        "You probably have a non-ANSI <ioctl.h>; see README. %d %d %x\n",
  697.            i, errno, FIONREAD);
  698.       exit (1);
  699.       }
  700.     if (nchar)
  701.       {
  702.       if (!flag.timeout)
  703.           flag.back = true;
  704.       flag.bothsides = false;
  705.       }
  706. #endif /* FIONREAD */
  707. #else
  708.     if (kbhit ())
  709.       {
  710.       if (!flag.timeout)
  711.           flag.back = true;
  712.       flag.bothsides = false;
  713.       }
  714. #endif /* MSDOS */
  715.     et = (time ((time_t *) 0) * 100) - time0;
  716.     ETnodes = NodeCnt + ZNODES;
  717.     if (et < 0)
  718.     et = 0;
  719.     if (iop == 1)
  720.       {
  721.       if (et > ResponseTime + ExtraTime && Sdepth > MINDEPTH)
  722.           flag.timeout = true;
  723.       ETnodes = NodeCnt + ZNODES;
  724.       time0 = time ((time_t *) 0) * 100;
  725.       }
  726. }
  727.  
  728. #endif
  729.  
  730. void
  731. SetTimeControl (void)
  732. {
  733.     if (TCflag)
  734.       {
  735.       TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
  736.       TimeControl.clock[white] = TimeControl.clock[black] = 6000L * TCminutes + 100L * TCseconds;
  737.       }
  738.     else
  739.       {
  740.       TimeControl.moves[white] = TimeControl.moves[black] = 0;
  741.       TimeControl.clock[white] = TimeControl.clock[black] = 0;
  742.       MaxResponseTime = 6000L * TCminutes + 100L * TCseconds;
  743.       }
  744.     et = 0;
  745.     ElapsedTime (1);
  746. }
  747.  
  748. void
  749. ClrScreen (void)
  750. {
  751. #ifndef CHESSTOOL
  752.     printz ("\n");
  753. #endif
  754. }
  755.  
  756. void
  757. UpdateDisplay (SHORT f, SHORT t, SHORT redraw, SHORT isspec)
  758. {
  759. #ifndef CHESSTOOL
  760.     SHORT r, c, l;
  761.  
  762.     if (!enable_update_display)
  763.     return;
  764.     if (redraw)
  765.       {
  766.       fprintf (fpout, "\n");
  767.       for (r = 7; r >= 0; r--)
  768.         {
  769.         for (c = 0; c <= 7; c++)
  770.           {
  771.               l = locn (r, c);
  772.               if (color[l] == neutral)
  773.               fprintf (fpout, " -");
  774.               else if (color[l] == white)
  775.               fprintf (fpout, " %c", qxx[board[l]]);
  776.               else
  777.               fprintf (fpout, " %c", pxx[board[l]]);
  778.           }
  779.         fprintf (fpout, "\n");
  780.         }
  781.       fprintf (fpout, "\n");
  782.       }
  783. #endif /* CHESSTOOL */
  784. #ifdef MSDOS
  785.     f++;
  786.     t++;
  787.     isspec++;            /* shut up the compiler */
  788. #endif /* MSDOS */
  789. }
  790.  
  791. void
  792. GetGame (void)
  793. {
  794. }
  795.  
  796. void
  797. SaveGame (void)
  798. {
  799. }
  800.  
  801. void
  802. ListGame (void)
  803. {
  804. }
  805.  
  806. void
  807. Undo (void)
  808.  
  809. /*
  810.  * Undo the most recent half-move.
  811.  */
  812.  
  813. {
  814.     SHORT f, t;
  815.  
  816.     f = GameList[GameCnt].gmove >> 8;
  817.     t = GameList[GameCnt].gmove & 0xFF;
  818.     if (board[t] == king && distance (t, f) > 1)
  819.     (void) castle (GameList[GameCnt].color, f, t, 2);
  820.     else
  821.       {
  822.       /* Check for promotion: */
  823.       if (GameList[GameCnt].flags & promote)
  824.         {
  825.         board[t] = pawn;
  826.         }
  827.       board[f] = board[t];
  828.       color[f] = color[t];
  829.       board[t] = GameList[GameCnt].piece;
  830.       color[t] = GameList[GameCnt].color;
  831.       if (color[t] != neutral)
  832.           Mvboard[t]--;
  833.       Mvboard[f]--;
  834.       }
  835.     if (GameList[GameCnt].flags & epmask)
  836.     EnPassant (otherside[color[f]], f, t, 2);
  837.     else
  838.     InitializeStats ();
  839.     epsquare = GameList[GameCnt].epssq;
  840.     if (TCflag && (TCmoves > 1))
  841.     ++TimeControl.moves[color[f]];
  842.     hashkey = GameList[GameCnt].hashkey;
  843.     hashbd = GameList[GameCnt].hashbd;
  844.     GameCnt--;
  845.     flag.mate = false;
  846.     Sdepth = 0;
  847.  
  848.     /*
  849.      * ShowSidetoMove (); UpdateDisplay (0, 0, 1, 0);
  850.      */
  851.     if (flag.regularstart)
  852.     Book = BOOKFAIL;
  853. }
  854.  
  855. #ifdef notdef
  856. void
  857. Undo (void)
  858.  
  859. /*
  860.  * Undo the most recent half-move.
  861.  */
  862.  
  863. {
  864.     SHORT f, t;
  865.  
  866.     f = GameList[GameCnt].gmove >> 8;
  867.     t = GameList[GameCnt].gmove & 0xFF;
  868.     if (board[t] == king && distance (t, f) > 1)
  869.     (void) castle (GameList[GameCnt].color, f, t, 2);
  870.     else
  871.       {
  872.       /* Check for promotion: */
  873.       if (GameList[GameCnt].flags & promote)
  874.         {
  875.         board[t] = pawn;
  876.         }
  877.       board[f] = board[t];
  878.       color[f] = color[t];
  879.       board[t] = GameList[GameCnt].piece;
  880.       color[t] = GameList[GameCnt].color;
  881.       if (color[t] != neutral)
  882.           Mvboard[t]--;
  883.       Mvboard[f]--;
  884.       }
  885.     if (GameList[GameCnt].flags & epmask)
  886.     EnPassant (color[t], f, t, 2);
  887.     if (TCflag)
  888.     ++TimeControl.moves[color[f]];
  889.     GameCnt--;
  890.     computer = otherside[computer];
  891.     opponent = otherside[opponent];
  892.     flag.mate = false;
  893.     Sdepth = 0;
  894.     InitializeStats ();
  895. }
  896.  
  897. #endif
  898. void
  899. ShowMessage (CHAR * s)
  900. {
  901.     fprintf (stderr, "%s\n", s);
  902. }
  903.  
  904. void
  905. ShowSidetoMove (void)
  906. {
  907. }
  908.  
  909. void
  910. PromptForMove (void)
  911. {
  912. #ifndef CHESSTOOL
  913.     printz ("\nYour move is? ");
  914. #endif /* CHESSTOOL */
  915. }
  916.  
  917.  
  918. void
  919. ShowCurrentMove (SHORT pnt, SHORT f, SHORT t)
  920. {
  921. #ifdef MSDOS
  922.     f++;
  923.     t++;
  924.     pnt++;            /* shut up the compiler */
  925. #endif /* MSDOS */
  926. }
  927.  
  928. void
  929. ChangeAlphaWindow (void)
  930. {
  931.     printz ("window: ");
  932. }
  933.  
  934. void
  935. ChangeBetaWindow (void)
  936. {
  937.     printz ("window: ");
  938. }
  939.  
  940. void
  941. GiveHint (void)
  942. {
  943.     algbr ((SHORT) (hint >> 8), (SHORT) (hint & 0xFF), false);
  944.     fprintf (stderr, "Hint: %s\n", mvstr[0]);
  945. }
  946.  
  947. void
  948. SelectLevel (CHAR * sx)
  949. {
  950. }
  951.  
  952. void
  953. ChangeSearchDepth (void)
  954. {
  955.     printz ("depth= ");
  956.     scanz ("%d", &MaxSearchDepth);
  957. }
  958.  
  959. void
  960. SetContempt (void)
  961. {
  962.     printz ("contempt= ");
  963.     scanz ("%hd", &contempt);
  964. }
  965.  
  966. void
  967. ChangeXwindow (void)
  968. {
  969.     printz ("xwndw= ");
  970.     scanz ("%hd", &xwndw);
  971. }
  972.  
  973. void
  974. TestSpeed (void (*f) (SHORT side, SHORT ply))
  975. {
  976.     SHORT i;
  977.     long cnt, rate, t1, t2;
  978.  
  979.     t1 = time (0);
  980.     for (i = 0; i < 10000; i++)
  981.       {
  982.       f (opponent, 2);
  983.       }
  984.     t2 = time (0);
  985.     cnt = 10000L * (TrPnt[3] - TrPnt[2]);
  986.     rate = cnt / (t2 - t1);
  987.     printz ("Nodes= %ld Nodes/sec= %ld\n", cnt, rate);
  988. }
  989.  
  990. CHAR cbuf[256];
  991. CHAR sdepth[128];
  992. int sdindex;
  993. SHORT GNCmode;
  994. CHAR *GetNextPtr = (CHAR *) NULL;
  995.  
  996. signed char GetNextChar ()
  997. {
  998.     GNCmode = false;
  999.     while (true)
  1000.       {
  1001.       if (GetNextPtr == NULL)
  1002.         {
  1003.         if (fgets (cbuf, sizeof (cbuf), fpin) != NULL)
  1004.           {
  1005.               GetNextPtr = cbuf;
  1006.           }
  1007.         else
  1008.             return -1;
  1009.         }
  1010.       else
  1011.           GetNextPtr++;
  1012.       if (*GetNextPtr == '\n' || *GetNextPtr == '\0')
  1013.         {
  1014.         GetNextPtr = NULL;
  1015.         return ' ';
  1016.         }
  1017.       if (GNCmode)
  1018.           if (*GetNextPtr == '}')
  1019.         {
  1020.             GNCmode = false;
  1021.             continue;
  1022.         }
  1023.           else
  1024.           continue;
  1025.       if (*GetNextPtr == '{')
  1026.         {
  1027.         GNCmode = true;
  1028.         continue;
  1029.         }
  1030.       return (*GetNextPtr);
  1031.  
  1032.       }
  1033. }
  1034. int lastws = true;
  1035. static signed char GNUANc;
  1036. int
  1037. GetNextMove (CHAR * buffer)
  1038. {
  1039.     CHAR *p, *q;
  1040.  
  1041.     sdw = sdb = 0;
  1042.     black_actual_move[0] = '\0';
  1043.     white_actual_move[0] = '\0';
  1044.     if (InFileType == PGN)
  1045.       {
  1046.       lastws = true;
  1047.       while (!isalpha (GNUANc))
  1048.         {
  1049.         if (GNUANc == '0' && lastws)
  1050.             break;
  1051.         if (GNUANc == ' ' || GNUANc == '.')
  1052.             lastws = true;
  1053.         else
  1054.             lastws = false;
  1055.         GNUANc = GetNextChar ();
  1056.         if (GNUANc == -1 && GetNextPtr == NULL)
  1057.             return -1;
  1058.         }
  1059.       q = white_actual_move;
  1060.       while (GNUANc != ' ' && GNUANc != -1)
  1061.         {
  1062.         if (GNUANc != 'x' && GNUANc != '+')
  1063.             *q++ = GNUANc;
  1064.         GNUANc = GetNextChar ();
  1065.         }
  1066.       *q = '\0';
  1067.       lastws = true;
  1068.       while (!isalpha (GNUANc))
  1069.         {
  1070.         if (GNUANc == '0' && lastws)
  1071.             break;
  1072.         if (GNUANc == ' ')
  1073.             lastws = true;
  1074.         else
  1075.             lastws = false;
  1076.         GNUANc = GetNextChar ();
  1077.         if (GetNextPtr == NULL)
  1078.             return 1;
  1079.         }
  1080.       q = black_actual_move;
  1081.       while (GNUANc != ' ' && GNUANc != -1)
  1082.         {
  1083.         if (GNUANc != 'x' && GNUANc != '+')
  1084.             *q++ = GNUANc;
  1085.         GNUANc = GetNextChar ();
  1086.         }
  1087.       *q = '\0';
  1088.       return 2;
  1089.  
  1090.       }
  1091.     if (fgets (cbuf, sizeof (cbuf), fpin) != NULL)
  1092.       {
  1093.       p = cbuf;
  1094.       for (; *p; p++)
  1095.         {
  1096.         if (isalpha (*p))
  1097.           {
  1098.               q = white_actual_move;
  1099.               while (!isspace (*p))
  1100.               *q++ = *p++;
  1101.               *q = '\0';
  1102.               if (strcmp (white_actual_move, "Book") == 0)
  1103.               continue;
  1104.               else
  1105.               break;
  1106.               break;
  1107.           }
  1108.         }
  1109.       if (*p == '\0' && white_actual_move[0] == '\0')
  1110.           return 0;
  1111.       if (InFileType == GNUCHESS)
  1112.         {
  1113.         if (samedepth)
  1114.           {
  1115.               sdindex = 0;
  1116.               while (*p == ' ' || *p == '\n')
  1117.               p++;
  1118.               while (*p != ' ' && *p != '\0')
  1119.               p++;
  1120.               while (*p == ' ' || *p == '\n')
  1121.               p++;
  1122.               while (*p != ' ' && *p != '\n')
  1123.               sdepth[sdindex++] = *p++;
  1124.               sdepth[sdindex] = '\0';
  1125.               if (strcmp (sdepth, "Book") == 0)
  1126.             {
  1127.                 sdw = -99;
  1128.                 for (; *p != ' '; p++);
  1129.             }
  1130.               else
  1131.               sdw = atoi (sdepth);
  1132.           }
  1133.         }
  1134.       for (; *p; p++)
  1135.         {
  1136.         if (isalpha (*p))
  1137.           {
  1138.               q = black_actual_move;
  1139.               while (!isspace (*p))
  1140.               *q++ = *p++;
  1141.               *q = '\0';
  1142.               if (strcmp (black_actual_move, "Book") == 0)
  1143.               continue;
  1144.               else
  1145.               break;
  1146.           }
  1147.         }
  1148.       if (*p == '\0' && black_actual_move[0] == '\0')
  1149.           return 1;
  1150.       if (InFileType == GNUCHESS)
  1151.         {
  1152.         if (samedepth)
  1153.           {
  1154.               sdindex = 0;
  1155.               while (*p == ' ' || *p == '\n')
  1156.               p++;
  1157.               while (*p != ' ' && *p != '\0')
  1158.               p++;
  1159.               while (*p == ' ' || *p == '\n')
  1160.               p++;
  1161.               while (*p != ' ' && *p != '\n')
  1162.               sdepth[sdindex++] = *p++;
  1163.               sdepth[sdindex] = '\0';
  1164.               if (strcmp (sdepth, "Book") == 0)
  1165.             {
  1166.                 sdb = -99;
  1167.                 for (; *p != ' '; p++);
  1168.             }
  1169.               else
  1170.               sdb = atoi (sdepth);
  1171.           }
  1172.         }
  1173.       return 2;
  1174.       }
  1175.     else            /* EOF */
  1176.     return -1;
  1177.  
  1178. }
  1179. UTSHORT mv;
  1180. UTSHORT GNUANmv;
  1181.  
  1182. int DoIt (SHORT computer, CHAR * smove, SHORT inbook, CHAR * s)
  1183. {
  1184.     SHORT dok, i;
  1185.  
  1186.     dok = VerifyMove (smove, 0, &mv);
  1187.     if (!dok)
  1188.       {
  1189.       fprintf (fpout, "\nBad move.  %s  Board position is: \n", s);
  1190.       UpdateDisplay (0, 0, 1, 0);
  1191.       flag.quit = 1;
  1192.       return false;
  1193.       }
  1194.     if (inbook)
  1195.       {
  1196.       if (computer == black)
  1197.           fprintf (fpout, "            %-9s   -     -    book\n", smove);
  1198.       else
  1199.           fprintf (fpout, "%3d   %-9s         -     -    book\n", move_number, smove);
  1200.  
  1201.       fflush (fpout);
  1202.       Sdepth = 0;
  1203.       ft = 0;
  1204.       same_moves[computer]++;
  1205.       }
  1206.     else
  1207.       {
  1208.       CHAR x[8];
  1209.  
  1210.       strcpy (x, smove);
  1211.       if (strcmp (smove, suggest_move) == 0
  1212.           || strcmp (smove, suggest_move1) == 0
  1213.           || strcmp (smove, suggest_move2) == 0
  1214.           || strcmp (smove, suggest_move3) == 0)
  1215.         {
  1216.         same_moves[computer]++;
  1217.         }
  1218.       else
  1219.           strcat (x, "*");
  1220.       if (computer == white)
  1221.         {
  1222.         if (sdw == -99)
  1223.             fprintf (fpout, "%3d   %-9s      %5d   Book ", move_number, x, print_score);
  1224.         else
  1225.             fprintf (fpout, "%3d   %-9s      %5d%5d   ", move_number, x, print_score, current_depth);
  1226.         }
  1227.       else
  1228.         {
  1229.         if (sdb == -99)
  1230.             fprintf (fpout, "            %-9s%5d  Book  ", x, print_score);
  1231.         else
  1232.             fprintf (fpout, "            %-9s%5d%5d   ", x, print_score, current_depth);
  1233.         }
  1234.       for (i = 1; MV[i] > 0; i++)
  1235.         {
  1236. /*        if(i == 1)fprintf (fpout, "%5s ", suggest_move1); */
  1237. /*        else*/ {algbr ((SHORT) (MV[i] >> 8), (SHORT) (MV[i] & 0xFF), false);
  1238.         fprintf (fpout, "%5s ", mvstr[0]);}
  1239.         }
  1240. #ifdef notdef
  1241.       GNUANlist (MV);
  1242. #endif
  1243.       fprintf (fpout, "\n");
  1244.       fflush (fpout);
  1245.       Sdepth = 0;
  1246.       ft = 0;
  1247.       }
  1248.     return true;
  1249. }
  1250.  
  1251. void
  1252. GNUANvarit ()
  1253. {
  1254.     memcpy (&GNUANsave[GNUANsavedepth].board, board, sizeof (board));
  1255.     memcpy (&GNUANsave[GNUANsavedepth].color, color, sizeof (color));
  1256.     memcpy (&GNUANsave[GNUANsavedepth].mvboard, Mvboard, sizeof (Mvboard));
  1257.     GNUANsave[GNUANsavedepth].currmove = GNUANcurrmove;
  1258.     GNUANsave[GNUANsavedepth].basemove = GNUANbasemove;
  1259.     GNUANsave[GNUANsavedepth].movecnt = GNUANmovecnt;
  1260.     GNUANcurrmove = GNUANmovecnt - 1;
  1261.     GNUANbasemove = GNUANmovecnt;
  1262.     GNUANmovecnt = 0;
  1263.     GNUANsave[GNUANsavedepth].moveno = move_number;
  1264.     GNUANsavedepth++;
  1265. }
  1266. void
  1267. GNUANravit ()
  1268. {
  1269.     GNUANsavedepth--;
  1270.     memcpy (board, &GNUANsave[GNUANsavedepth].board, sizeof (board));
  1271.     memcpy (color, &GNUANsave[GNUANsavedepth].color, sizeof (color));
  1272.     memcpy (Mvboard, &GNUANsave[GNUANsavedepth].mvboard, sizeof (Mvboard));
  1273.     GNUANcurrmove = GNUANsave[GNUANsavedepth].currmove;
  1274.     GNUANbasemove = GNUANsave[GNUANsavedepth].basemove;
  1275.     GNUANmovecnt = GNUANsave[GNUANsavedepth].movecnt;
  1276.     move_number = GNUANsave[GNUANsavedepth].moveno;
  1277. }
  1278.  
  1279. int Undid = false;
  1280.  
  1281. void
  1282. InputCommand (void)
  1283.  
  1284. /*
  1285.  * Open the file of moves to analyse.  Go through the file move by move and
  1286.  * do the following for each move.  See what gnuchess would have done in that
  1287.  * position.  Record the move it would have made along with the score it
  1288.  * would have given and the search depth.  Take back its move. Force the move
  1289.  * that was actually made.  Keep track of statistics such as how many moves
  1290.  * agreed.
  1291.  */
  1292.  
  1293. {
  1294.     SHORT ok, inbook;
  1295.     CHAR s[80];
  1296.     int search_depth;
  1297.  
  1298. #if !defined BACKGROUND_ANALYSIS
  1299.     int max_minutes;
  1300.     int max_seconds;
  1301.     CHAR inbuf[256];
  1302. #else
  1303.     CHAR outfilename[255];
  1304.     CHAR progfilename[255];
  1305. #endif
  1306.     CHAR infilename[255];
  1307.     long start_time, end_time;
  1308.     double elapsed_time;
  1309.     float move_percent[2];
  1310.     CHAR GNUANinbuf1[128];
  1311.     CHAR *p, *q;
  1312.     int mr;
  1313.  
  1314.     /* Initialize necessary variables. */
  1315.  
  1316.     flag.quit = false;
  1317.     flag.beep = false;
  1318.     flag.post = true;
  1319.     enable_update_display = 1;
  1320.     ft = 0;
  1321.     Book = false;
  1322.     total_moves[0] = total_moves[1] = 0;
  1323.     same_moves[0] = same_moves[0] = 0;
  1324.  
  1325. #ifdef BACKGROUND_ANALYSIS
  1326.  
  1327.     /*
  1328.      * Set the in files to standard ones for analysis if background
  1329.      * processing selected.
  1330.      */
  1331.  
  1332.     strcpy (infilename, IN_FILE);
  1333.     strcpy (outfilename, OUT_FILE);
  1334.     strcpy (progfilename, PROG_FILE);
  1335.     fpout = fopen (outfilename, "w");
  1336.     if (fpout == NULL)
  1337.       {
  1338.       fprintf (fpout, "This file does not exist : %s\n", outfilename);
  1339.       flag.quit = 1;
  1340.       return;
  1341.       }
  1342.     MaxSearchDepth = search_depth = MAX_DEPTH;
  1343.     TCminutes = MAX_MINUTE;
  1344.     TCseconds = MAX_SECOND;
  1345.  
  1346. #else
  1347.  
  1348.     /* Request information on where the file is and the depth an time. */
  1349.  
  1350.     fpout = stderr;
  1351.     fprintf (fpout, "Input the file with the algebraic moves of the game.\n");
  1352.     fflush (fpout);
  1353.     gets (infilename);
  1354.     fprintf (fpout, "\n");
  1355.     do
  1356.       {
  1357.       fprintf (fpout, "Input the search depth you want to use.  (1 to 29)(- for depth from file)\n");
  1358.       gets (inbuf);
  1359.       search_depth = atoi (inbuf);
  1360.       if (search_depth < 0)
  1361.         {
  1362.         samedepth = true;
  1363.         search_depth = -search_depth;
  1364.         }
  1365.       }
  1366.     while (search_depth < 1 || search_depth > 29);
  1367.     MaxSearchDepth = search_depth;
  1368.  
  1369.     fprintf (fpout, "\n");
  1370.     max_minutes = max_seconds = 0;
  1371.     do
  1372.       {
  1373.       fprintf (fpout, "Input the maximum number of minutes per move you want to use.\n");
  1374.       gets (inbuf);
  1375.       max_minutes = atoi (inbuf);
  1376.       if (max_minutes < 0)
  1377.         {
  1378.         max_seconds = -max_minutes;
  1379.         max_minutes = 0;
  1380.         }
  1381.       }
  1382.     while ((max_minutes + max_seconds) < 1);
  1383.     fprintf (fpout, "Post the search results(y/n).\n");
  1384.     gets (inbuf);
  1385.     if (inbuf[0] == 'y')
  1386.     flag.post = true;
  1387.     else
  1388.     flag.post = false;
  1389.     printf ("\nYou will search to %d half moves\n", search_depth);
  1390.     printf ("\nWith no search taking more than %d:%02d minutes\n", max_minutes, max_seconds);
  1391.     TCminutes = max_minutes;
  1392.     TCseconds = max_seconds;
  1393.  
  1394.     fprintf (fpout, "\n\n");
  1395.  
  1396. #endif
  1397.  
  1398.     fpin = fopen (infilename, "r");
  1399.     if (fpin == NULL)
  1400.       {
  1401.       fprintf (fpout, "This file does not exist : %s\n", infilename);
  1402.       flag.quit = 1;
  1403.       return;
  1404.       }
  1405.     /* lets find out about this file */
  1406.     fgets (InBuf, 256, fpin);
  1407.     InFileType = OTHER;
  1408.     if (!strncmp (InBuf, "xboard", 6) || !strncmp (InBuf, "# xboard", 8))
  1409.       {
  1410.       InFileType = XBOARD;
  1411.       fgets (InBuf, 256, fpin);
  1412.       fgets (InBuf, 256, fpin);
  1413.       }
  1414.     else if (!strncmp (InBuf, "gnuchess", 6))
  1415.       {
  1416.       InFileType = GNUCHESS;
  1417.       fgets (InBuf, 256, fpin);
  1418.       }
  1419.     else if (InBuf[0] == '[')
  1420.       {
  1421.       InFileType = PGN;
  1422.       while (InBuf[0] == '[')
  1423.         {
  1424.         fprintf (fpout, "%s", InBuf);
  1425.         fgets (InBuf, 256, fpin);
  1426.         }
  1427.       fprintf (fpout, "\n");
  1428.       }
  1429.     else
  1430.     rewind (fpin);
  1431.     TCmoves = 1;
  1432.     TCflag = (TCmoves > 1);
  1433.     /* flag.onemove = true; */
  1434.     OperatorTime = 0;
  1435.     SetTimeControl ();
  1436.  
  1437.  
  1438.     fprintf (fpout, "Move White Black      Score Depth     Best Line\n");
  1439.     fprintf (fpout, "------------------------------------------------------------------\n");
  1440.  
  1441. #ifdef BACKGROUND_ANALYSIS
  1442.  
  1443.     /*
  1444.      * Update progress in the progress file if this is running in the
  1445.      * background.
  1446.      */
  1447.  
  1448.     fpprog = fopen (progfilename, "w");
  1449.     fprintf (fpprog, "Done with move #%d.\n", move_number - 1);
  1450.     fclose (fpprog);
  1451.  
  1452. #endif
  1453.     GNUANmovecnt = 0;
  1454.     GNUANbasemove = 0;
  1455.     while ((mr = GetNextMove (s)) > 0)
  1456.       {
  1457.       strcpy (GNUANmove[GNUANmovecnt], white_actual_move);
  1458.       GNUANsd[GNUANmovecnt] = (sdw == -99) ? search_depth : (sdw) ? sdw : search_depth;
  1459.       GNUANmovecnt++;
  1460.         if (mr == 1) break;
  1461.       strcpy (GNUANmove[GNUANmovecnt], black_actual_move);
  1462.       GNUANsd[GNUANmovecnt] = (sdb == -99) ? search_depth : (sdb) ? sdb : search_depth;
  1463.       GNUANmovecnt++;
  1464.       if (!strcmp (white_actual_move, "Black") || !strcmp (white_actual_move, "White") || !strcmp (white_actual_move, "draw"))
  1465.           break;
  1466.       }
  1467.     printf ("Got %d moves\n", GNUANmovecnt);
  1468.  
  1469.     /* all the moves are stored now start */
  1470.     opponent = black;
  1471.     computer = white;
  1472.     GNUANinput = file;
  1473.     GNUANnext = false;
  1474.     GNUANnextstop = GNUANsavedepth = GNUANcurrmove = 0;
  1475.     time (&start_time);
  1476.     Undid = false;
  1477.     while (GNUANcurrmove < (GNUANbasemove + GNUANmovecnt))
  1478.       {
  1479.  
  1480. #ifdef IGNUAN
  1481. /************************************************************************/
  1482.       /* gnuan interactive                                */
  1483. /************************************************************************/
  1484.  
  1485.       /*
  1486.        * Commands: var - initiate a variation - save current another - find
  1487.        * next best move for this position top - always look at the top n
  1488.        * moves comment - copy to output rav - return from variation go get
  1489.        * next move from input
  1490.        */
  1491. /************************************************************************/
  1492. #endif
  1493.       if (GNUANdepth)
  1494.           MaxSearchDepth = GNUANdepth;
  1495.       else
  1496.         {
  1497.         if (GNUANinput == file)
  1498.             MaxSearchDepth = GNUANsd[GNUANcurrmove];
  1499.         else
  1500.             MaxSearchDepth = 4;
  1501.         }
  1502.       if (GNUANnext)
  1503.         {
  1504.         GNUANnext = false;
  1505.         inbook = false;
  1506.         }
  1507.       else
  1508.         {
  1509.         VMoveList (computer, 1);
  1510.         inbook = GOpeningBook (&GNUANhint, computer, GNUANmove[GNUANcurrmove]);
  1511.         }
  1512.  
  1513.       if (!inbook)
  1514.         {
  1515.         flag.force = 0;
  1516.         SelectMove (computer, 1);
  1517.         Undo ();
  1518.         SetTimeControl ();
  1519.         flag.force = 1;
  1520.         }
  1521.       if (GNUANinput == file)
  1522.           ok = DoIt (computer, GNUANmove[GNUANcurrmove], inbook, s);
  1523.       else
  1524.           ok = DoIt (computer, GNUANinbuf, inbook, s);
  1525.       if (!ok)
  1526.         {
  1527.         if (GNUANinput == keyboard)
  1528.             GNUANmovecnt--;
  1529.         GNUANcurrmove--;
  1530.         }
  1531. #ifdef BACKGROUND_ANALYSIS
  1532.  
  1533.       /*
  1534.        * Update progress in the progress file if this is running in the
  1535.        * background.
  1536.        */
  1537.  
  1538.       fpprog = fopen (progfilename, "w");
  1539.       fprintf (fpprog, "Done with move #%d.\n", move_number - 1);
  1540.       fclose (fpprog);
  1541. #else
  1542.  
  1543.       /*
  1544.        * fprintf(stderr, "Done with move #%d.\n", move_number-1);
  1545.        */
  1546.  
  1547. #endif
  1548. #ifdef IGNUAN
  1549.       /* we have done the move now any commands */
  1550.       if(GNUANtopLim){
  1551.         if(GNUANtop < GNUANtopLim){
  1552.              GNUANadjlist[GNUANtop++] = GNUANmv;
  1553.                           GNUANnext = true;
  1554.                           Undo ();
  1555.                           Undid = true;
  1556.             }
  1557.         else GNUANtop = 0;
  1558.         }
  1559.       if (GNUANcurrmove >= GNUANnextstop) GNUANnextstop = 0;
  1560.       if (GNUANnextstop == 0 && (GNUANtopLim == 0 || GNUANtop == 0))
  1561.           while (true)
  1562.         {
  1563.             printf (">");
  1564.             gets (GNUANinbuf1);
  1565.             p = GNUANinbuf1;
  1566.             q = GNUANinbuf;
  1567.             while (true)
  1568.               {
  1569.               while (true)
  1570.                 {
  1571.                 if (*p == ' ')
  1572.                   {
  1573.                       p++;
  1574.                       continue;
  1575.                   }
  1576.                 else
  1577.                     break;
  1578.                 }
  1579.               while (true)
  1580.                 {
  1581.                 if (*p != ' ')
  1582.                   {
  1583.                       if (*p == '\0')
  1584.                     {
  1585.                         break;
  1586.                     }
  1587.                       *q++ = *p++;
  1588.                       continue;
  1589.                   }
  1590.                 else
  1591.                     break;
  1592.                 }
  1593.               if (*p == '\0')
  1594.                   break;
  1595.               else
  1596.                   *q++ = ' ';
  1597.               }
  1598.             *q = '\0';
  1599.             if (strcmp ("var", GNUANinbuf) == 0)
  1600.               {
  1601.               GNUANvarit ();
  1602.               GNUANinput = keyboard;
  1603.               }
  1604.             else if (strcmp ("rav", GNUANinbuf) == 0)
  1605.               {
  1606.               if (GNUANsavedepth == 0)
  1607.                 {
  1608.                 printf ("Error not in Var\n");
  1609.                 continue;
  1610.                 }
  1611.               GNUANravit ();
  1612.               InitializeStats ();
  1613.               GNUANinput = (GNUANsavedepth ? keyboard : file);
  1614.               }
  1615.             else if (strcmp ("next", GNUANinbuf) == 0 || strcmp ("n", GNUANinbuf) == 0)
  1616.               {
  1617.               GNUANadjlist[GNUANtop++] = GNUANmv;
  1618.               GNUANnext = true;
  1619.               Undo ();
  1620.               Undid = true;
  1621.               break;
  1622.               }
  1623.             else if ((strncmp ("depth", GNUANinbuf, 5) == 0))
  1624.               {
  1625.               int i = strtol (&GNUANinbuf[5], NULL, 10);
  1626.               if (i > 0)
  1627.                   GNUANdepth = i;
  1628.               else
  1629.                 {
  1630.                 printf ("Illegal depth %d\n", i);
  1631.                 continue;
  1632.                 }
  1633.               }
  1634.             else if (strcmp ("wn", GNUANinbuf) == 0)
  1635.               {
  1636.               GNUANtop = 0;
  1637.               }
  1638.             else if (strncmp ("d", GNUANinbuf, 2) == 0)
  1639.               {
  1640.               int i = strtol (&GNUANinbuf[2], NULL, 10);
  1641.               if (i > 0)
  1642.                   GNUANdepth = i;
  1643.               else
  1644.                 {
  1645.                 printf ("Illegal depth %d\n", i);
  1646.                 continue;
  1647.                 }
  1648.               }
  1649.             else if (strncmp ("top", GNUANinbuf, 3) == 0)
  1650.               {
  1651.               int i = strtol (&GNUANinbuf[4], NULL, 10);
  1652.               if (i > 1 && i < 6)
  1653.                   GNUANtopLim = i-1;
  1654.               else
  1655.                   printf ("Illegal range for top %d\n", i);
  1656.               }
  1657.             else if (strncmp ("t", GNUANinbuf, 2) == 0)
  1658.               {
  1659.               int i = strtol (&GNUANinbuf[2], NULL, 10);
  1660.               if (i > 0 && i < 99)
  1661.                   GNUANtop = i;
  1662.               else
  1663.                   printf ("Illegal range for top %d\n", i);
  1664.               }
  1665.             else if (strcmp ("bd", GNUANinbuf) == 0)
  1666.               {
  1667.               UpdateDisplay (0, 0, 1, 0);
  1668.               }
  1669.             else if (strcmp ("quit", GNUANinbuf) == 0)
  1670.               {
  1671.               exit (1);
  1672.               }
  1673.             else if (strcmp ("go", GNUANinbuf) == 0 || strcmp ("g", GNUANinbuf) == 0)
  1674.               {
  1675.               if (!GNUANsavedepth)
  1676.                   break;
  1677.               else
  1678.                   printf ("In variation need move or rav\n");
  1679.               }
  1680.             else if (isdigit (GNUANinbuf[0]))
  1681.               {
  1682.               /* means go to move nn */
  1683.               GNUANnextstop = 2 * (strtol (GNUANinbuf, &p, 10) - 1) - 1;
  1684.               if (GNUANnextstop <= GNUANcurrmove)
  1685.                 {
  1686.                 printf ("already past that move\n");
  1687.                 GNUANnextstop = 0;
  1688.                 continue;
  1689.                 }
  1690.               break;
  1691.               }
  1692.             else
  1693.               {        /* none of above must be a move if in a var */
  1694.               if (!GNUANsavedepth)
  1695.                 {
  1696.                 printf ("Illegal input:must be in var to specify move\n");
  1697.                 continue;
  1698.                 }
  1699.               if (strlen (GNUANinbuf) < 2)
  1700.                 {
  1701.                 printf ("Illegal input:%s\n", GNUANinbuf);
  1702.                 continue;
  1703.                 }
  1704.               else
  1705.                 {
  1706.                 strcpy (GNUANmove[GNUANbasemove + GNUANmovecnt], GNUANinbuf);
  1707.                 GNUANmovecnt++;
  1708.                 GNUANinput = keyboard;
  1709.                 break;
  1710.                 }
  1711.               }
  1712.  
  1713.         }
  1714. #endif
  1715.       if (!Undid)
  1716.         {
  1717.         computer ^= 1;
  1718.         opponent ^= 1;
  1719.         GNUANcurrmove++;
  1720.             if (computer == white) move_number++;
  1721.         }
  1722.       Undid = false;
  1723.       }
  1724.  
  1725.     move_percent[white] = ((float) same_moves[white]) * 200 / (float) (GNUANmovecnt + (GNUANmovecnt % 2 ? 1 : 0));
  1726.     move_percent[black] = ((float) same_moves[black]) * 200 / (float) (GNUANmovecnt + (GNUANmovecnt % 2 ? 1 : 0));
  1727.     fprintf (fpout, "\n           White's percentage was %5.2f%%.     Black's percentage was %5.2f%%.\n", move_percent[white], move_percent[black]);
  1728.     time (&end_time);
  1729. #ifdef __EMX__
  1730.     elapsed_time = difftime(end_time, start_time);
  1731. #else
  1732.     elapsed_time = difftime(end_time - start_time);
  1733. #endif
  1734.     fprintf (fpout, "\n           Elapsed time was %ld seconds.\n", elapsed_time);
  1735.     fclose (fpin);
  1736.     fclose (fpout);
  1737.     exit (0);
  1738. }
  1739.  
  1740. void
  1741. Ldisplay1 ()
  1742. {
  1743. };
  1744. void
  1745. Ldisplay2 ()
  1746. {
  1747. };
  1748. void
  1749. Ldisplay ()
  1750. {
  1751. };
  1752. void
  1753. Ldisplay3 ()
  1754. {
  1755. };
  1756. void
  1757. Ldisplay4 ()
  1758. {
  1759. };
  1760. int ecomove;
  1761.