home *** CD-ROM | disk | FTP | other *** search
/ Dream 44 / Amiga_Dream_44.iso / RiscPc / jeux / ArcBoard004.arc / !GNUChessX / src / c / book < prev    next >
Text File  |  1996-01-10  |  30KB  |  1,295 lines

  1. /*
  2.  * book.c - C source for GNU CHESS
  3.  *
  4.  * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software
  5.  * Foundation
  6.  *
  7.  * This file is part of GNU CHESS.
  8.  *
  9.  * GNU Chess is free software; you can redistribute it and/or modify it under
  10.  * the terms of the GNU General Public License as published by the Free
  11.  * Software Foundation; either version 2, or (at your option) any later
  12.  * version.
  13.  *
  14.  * GNU Chess is distributed in the hope that it will be useful, but WITHOUT ANY
  15.  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  16.  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  17.  * details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License along with
  20.  * GNU Chess; see the file COPYING.  If not, write to the Free Software
  21.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23.  
  24. /* Dec 95 SPD added FBOOK define to allow buffered book io */
  25.  
  26. #include "gnuchess.h"
  27. #include "ttable.h"        /* uses hashbd, hashkey */
  28. #include "ataks.h"
  29. #if !defined(AMIGADOS) && !defined(Think_C) && !defined(WIN32) && !defined(__arm__)
  30. #include <unistd.h>
  31. #endif
  32. #ifdef Think_C
  33. #include <unix.h>
  34. #endif
  35. #ifdef GENIT
  36. FILE *GEN;
  37. int GENline = 0;
  38. int GENmove = 0;
  39. CHAR gs0[12], gs1[12], gs2[12], gs3[12], GENITs[12];
  40. #endif
  41. #ifdef MSDOS
  42. #include <io.h>
  43. #endif
  44. #if !defined MSDOS && !defined(Think_C) && !defined(__arm__)
  45. #define O_BINARY 0
  46. #endif
  47. #ifndef FBOOK
  48. #include <fcntl.h>
  49. #endif
  50. static unsigned long booksize = BOOKSIZE;
  51. static unsigned long int BKTBLSIZE;
  52. static unsigned long BOOKMASK;
  53. static unsigned long bookcount = 0;
  54. static unsigned long bookline = 0;
  55. static unsigned bookpocket = BOOKPOCKET;
  56. static UTSHORT bookmaxply = BOOKMAXPLY;
  57.  
  58. #ifdef ECO
  59. #include <sys/types.h>
  60. #include <sys/stat.h>
  61. #endif
  62.  
  63. CHAR *bookfile = NULL;
  64. CHAR *binbookfile = BINBOOK;
  65.  
  66. static int GotBook = false;
  67. static unsigned long bhashbd, bhashkey;
  68.  
  69. #ifdef FBOOK
  70. #define close(x) fclose(x)
  71. #define read(a,b,c) fread(b,c,1,a)
  72. #include <errno.h>
  73. #define write(a,b,c) if (fwrite(b,c,1,a) != 1) printf("Write failed %d line %d\n",errno,__LINE__)
  74. #define lseek fseek
  75. #define FHAND FILE *
  76. static inline int fhandok(FHAND fred)
  77. {
  78.         return fred != NULL;
  79. }
  80. #else
  81. #define FHAND int
  82. static inline int fhandok(FHAND fred)
  83. {
  84.         return fred >= 0;
  85. }
  86. #endif
  87.  
  88. #ifdef GENIT
  89. GENITchk (gs)
  90.      CHAR *gs;
  91. {
  92.     int gcnt, gpnt;
  93.     struct leaf *node = NULL;
  94.     gcnt = 0;
  95.     gpnt = TrPnt[2];
  96.     while (gpnt < TrPnt[3])
  97.       {
  98.       node = &Tree[gpnt++];
  99.       algbr (node->f, node->t, (SHORT) node->flags);
  100.       if (strcmp (gs, mvstr[0]) == 0 || strcmp (gs, mvstr[1]) == 0 ||
  101.           strcmp (gs, mvstr[2]) == 0 || strcmp (gs, mvstr[3]) == 0
  102.           || strcmp (gs, mvstr[4]) == 0)
  103.         {
  104.         gcnt++;
  105.         }
  106.       }
  107.     return gcnt;
  108. }
  109. #endif
  110.  
  111. #ifndef QUIETBOOKGEN
  112. void
  113. bkdisplay (s, cnt, moveno)
  114.      CHAR *s;
  115.      int cnt;
  116.      int moveno;
  117. {
  118.     static SHORT pnt;
  119. #ifndef SEMIQUIETBOOKGEN
  120.     struct leaf *node;
  121.     int r, c, l;
  122. #endif
  123.  
  124.     pnt = TrPnt[2];
  125.     printf ("matches = %d\n", cnt);
  126.     printf ("inout move is :%s:move number %d side %s\n", s, moveno / 2 + 1, !(moveno & 1) ? "white" : "black");
  127. #ifndef SEMIQUIETBOOKGEN
  128.     printf ("legal moves are \n");
  129.     while (pnt < TrPnt[3])
  130.       {
  131.       node = &Tree[pnt++];
  132.       algbr (node->f, node->t, (SHORT) node->flags);
  133.       printf ("%s %s %s %s %s\n", mvstr[0], mvstr[1], mvstr[2], mvstr[3], mvstr[4]);
  134.       }
  135.     printf ("\n current board is\n");
  136.     for (r = 7; r >= 0; r--)
  137.       {
  138.       for (c = 0; c <= 7; c++)
  139.         {
  140.         l = locn (r, c);
  141.         if (color[l] == neutral)
  142.             printf (" -");
  143.         else if (color[l] == white)
  144.             printf (" %c", qxx[board[l]]);
  145.         else
  146.             printf (" %c", pxx[board[l]]);
  147.         }
  148.       printf ("\n");
  149.       }
  150.     printf ("\n\n");
  151. #endif
  152. }
  153.  
  154. #endif
  155.  
  156. int
  157. BVerifyMove (CHAR * s, UTSHORT * mv, int moveno)
  158.  
  159.      /*
  160.       * Compare the string 's' to the list of legal moves available for the
  161.       * opponent. If a match is found, make the move on the board.
  162.       */
  163.  
  164. {
  165.     static SHORT pnt, tempb, tempc, tempsf, tempst, cnt;
  166.     static struct leaf xnode;
  167.     struct leaf *node;
  168.  
  169.     *mv = 0;
  170.     cnt = 0;
  171.     VMoveList (opponent, 2);
  172.     pnt = TrPnt[2];
  173.     while (pnt < TrPnt[3])
  174.       {
  175.       node = &Tree[pnt++];
  176.       algbr (node->f, node->t, (SHORT) node->flags);
  177.       if (strcmp (s, mvstr[0]) == 0 || strcmp (s, mvstr[1]) == 0 ||
  178.           strcmp (s, mvstr[2]) == 0 || strcmp (s, mvstr[3]) == 0 || strcmp (s, mvstr[4]) == 0)
  179.         {
  180.         cnt++;
  181.         xnode = *node;
  182.         }
  183.       }
  184.     if (cnt == 1)
  185.       {
  186. #ifdef GENIT
  187.  
  188.       algbr (xnode.f, xnode.t, (SHORT) xnode.flags);
  189.       strcpy (gs0, mvstr[0]);
  190.       strcpy (gs1, mvstr[1]);
  191.       strcpy (gs2, mvstr[2]);
  192.       strcpy (gs3, mvstr[3]);
  193.       if (GENITchk (gs1) == 1)
  194.           strcpy (GENITs, gs1);
  195.       else if (GENITchk (gs2) == 1)
  196.           strcpy (GENITs, gs2);
  197.       else if (GENITchk (gs2) == 1)
  198.           strcpy (GENITs, gs1);
  199.       else
  200.           strcpy (GENITs, gs0);
  201.       if (strcmp ("e8g8", GENITs) == 0 || strcmp ("e1g1", GENITs) == 0)
  202.           strcpy (GENITs, "o-o");
  203.       else if (strcmp ("e8c8", GENITs) == 0 || strcmp ("e1c1", GENITs) == 0)
  204.           strcpy (GENITs, "o-o-o");
  205. #endif
  206.       MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  207.       if (SqAtakd (PieceList[opponent][0], computer))
  208.         {
  209.         UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  210.         /* Illegal move in check */
  211. #ifndef QUIETBOOKGEN
  212.         printf (CP[77]);
  213.         printf ("\n");
  214.         bkdisplay (s, cnt, moveno);
  215. #endif
  216.         return (false);
  217.         }
  218.       else
  219.         {
  220.         *mv = (xnode.f << 8) | xnode.t;
  221.         algbr (xnode.f, xnode.t, false);
  222.         if (board[xnode.t] == pawn)
  223.           {
  224.               if (xnode.t - xnode.f == 16)
  225.               epsquare = xnode.f + 8;
  226.               else if (xnode.f - xnode.t == 16)
  227.               epsquare = xnode.f - 8;
  228.           }
  229.         else
  230.             epsquare = -1;
  231.  
  232.         return (true);
  233.         }
  234.       }
  235.     /* Illegal move */
  236. #ifndef QUIETBOOKGEN
  237.     printf (CP[75], s);
  238.     bkdisplay (s, cnt, moveno);
  239. #endif
  240.     return (false);
  241. }
  242.  
  243. void
  244. RESET (void)
  245.  
  246.      /*
  247.       * Reset the board and other variables to start a new game.
  248.       */
  249.  
  250. {
  251.     SHORT l;
  252.  
  253.     flag.illegal = flag.mate = flag.post = flag.quit = flag.reverse = flag.bothsides = flag.onemove = flag.force = false;
  254.     flag.material = flag.coords = flag.hash = flag.easy = flag.rcptr = true;
  255.     flag.stars = flag.shade = flag.back = flag.musttimeout = false;
  256. #ifdef CHESSTOOL
  257.     flag.beep = false;
  258. #else
  259.     flag.beep = true;
  260. #endif
  261. #ifdef CLIENT
  262.     flag.gamein = true;
  263.     flag.post = true;
  264. #else
  265.     flag.gamein = false;
  266. #endif
  267.     GenCnt = epsquare = 0;
  268.     GameCnt = 0;
  269.     Developed[white] = Developed[black] = false;
  270.     castld[white] = castld[black] = false;
  271.     PawnThreat[0] = CptrFlag[0] = false;
  272.     opponent = white;
  273.     computer = black;
  274.     for (l = 0; l < 64; l++)
  275.       {
  276.       board[l] = Stboard[l];
  277.       color[l] = Stcolor[l];
  278.       Mvboard[l] = 0;
  279.       }
  280.     InitializeStats ();
  281. }
  282.  
  283. int
  284. gnc (FILE * fd)
  285. {
  286.     int c;
  287.     c = getc (fd);
  288.     if (c == '(')
  289.       {
  290. #ifdef GENIT
  291.       fputc (GEN, c);
  292. #endif
  293.       do
  294.         {
  295.         c = getc (fd);
  296. #ifdef GENIT
  297.         fputc (GEN, c);
  298. #endif
  299.         if (c == ')')
  300.           {
  301.               c = getc (fd);
  302.               break;
  303.           }
  304.         if (c == EOF)
  305.             break;
  306.         }
  307.       while (true);
  308.       }
  309.     else if (c == '{')
  310.       {
  311. #ifdef GENIT
  312.       fputc (GEN, c);
  313. #endif
  314.       do
  315.         {
  316.         c = getc (fd);
  317. #ifdef GENIT
  318.         fputc (GEN, c);
  319. #endif
  320.         if (c == '}')
  321.           {
  322.               c = getc (fd);
  323.               break;
  324.           }
  325.         if (c == EOF)
  326.             break;
  327.         }
  328.       while (true);
  329.       }
  330.     return c;
  331. }
  332.  
  333.  
  334. int
  335. Vparse (FILE * fd, UTSHORT * mv, SHORT side, CHAR * opening, int moveno)
  336. {
  337.     register int c, i;
  338.     CHAR s[1024];
  339.     CHAR *p;
  340.  
  341.     while (true)
  342.       {
  343.  
  344.       while ((c = gnc (fd)) == ' ' || c == '\n');
  345.       if (c == '\r')
  346.           continue;
  347.       i = 0;
  348.       if (c == '#' || c == '[' || c == '%')
  349.         {            /* comment */
  350. #ifdef GENIT
  351.         pcurr =
  352. #endif
  353.             p = opening;
  354.         do
  355.           {
  356.               *p++ = c;
  357.               c = gnc (fd);
  358.               if (c == '\r')
  359.               continue;
  360.               /* goes to end of line */
  361.               if (c == '\n')
  362.             {
  363.                 /* does the comment continue */
  364.                 if (opening[0] == '[')
  365.                   {
  366.                   if ((c = getc (fd)) == '[')
  367.                     {
  368. #ifdef GENIT
  369.                     *p = '\0';
  370.                     fprintf (GEN, "%s\n", pcurr);
  371.                     pcurr = p;
  372. #endif
  373.                     continue;
  374.                     }
  375.                   else
  376.                       ungetc (c, fd);
  377.                   }
  378.                 *p = '\0';
  379. #ifdef GENIT
  380.                 GENline = 0;
  381.                 fprintf (GEN, "%s\n", opening);
  382.                 GENmove = 0;
  383. #endif
  384.                 return 0;
  385.             }
  386.               if (c == EOF)
  387.               return -1;
  388.           }
  389.         while (true);
  390.         }
  391.       /* is it a move number or analysis ( in [ ] or in { } ) */
  392.       /* number cannot start with a 0 because of 0-0 */
  393.       else if (!isalpha (c) && c != '0')
  394.         {
  395.         int nlxx = false;
  396.         int nonspace = false;
  397.  
  398.         while (true)
  399.           {
  400.               c = gnc (fd);
  401.               if (nlxx)
  402.               if (c == '#' || c == '[' || c == '%')
  403.                 {
  404.                 ungetc (c, fd);
  405.                 return 0;
  406.                 }
  407.               if (c == '\r')
  408.               continue;
  409.               if (c == '\n')
  410.             {
  411.                 nlxx = true;
  412.                 continue;
  413.             }
  414.               else
  415.               nlxx = false;
  416.               if (c == EOF)
  417.             {
  418.                 return -1;
  419.             }
  420.               /* stop at first nonspace a ... is space */
  421.               /* must be nonspace because of 0-0 */
  422.               if (nonspace)
  423.             {
  424.                 if (c != '.' && c != ' ')
  425.                 break;
  426.             }
  427.               if (c == '.')
  428.             {
  429.                 nonspace = true;
  430.             }
  431.               /* stop if alpha must be move */
  432.               else if (isalpha (c))
  433.               break;
  434.           }
  435.         }
  436.       s[0] = (CHAR) c;
  437.  
  438.       while ((c = gnc (fd)) != '\n' && c != ' ' && c != '\t' && c != EOF)
  439.         {
  440.         if (isupper (c))
  441.           {
  442.               if (c != 'O')
  443.             {
  444.                 ungetc (c, fd);
  445.                 c = ' ';
  446.                 break;
  447.             }
  448.           }
  449.         if (c == '\r')
  450.             continue;
  451.         if (c == '?')
  452.             break;
  453.         if (c == '!')
  454.             continue;
  455.         if (c == '+')
  456.             continue;
  457.         if (c == '#')
  458.             continue;
  459.         if (c == '%')
  460.             continue;
  461.         if (c == '=')
  462.           {
  463.               c = gnc (fd);
  464.               c = tolower (c);
  465.           }
  466.         if (c != 'x')
  467.             s[++i] = c;
  468.         }
  469.       s[++i] = '\0';
  470.  
  471.       if (c == EOF)
  472.           return (-1);
  473.       if (s[0] == '!' || s[0] == ';')
  474.         {
  475.         while (c != '\n' && c != EOF)
  476.             c = gnc (fd);
  477.         if (c == EOF)
  478.             return -1;
  479.         else
  480.             return (0);
  481.         }
  482.       if ((strcmp (s, "o-o-o") == 0) || (strcmp (s, "OOO") == 0) || (strcmp (s, "O-O-O") == 0) || (strcmp (s, "0-0-0") == 0))
  483.         {
  484.         if (side == black)
  485.             strcpy (s, "e8c8");
  486.         else
  487.             strcpy (s, "e1c1");
  488.         }
  489.       else if ((strcmp ("o-o", s) == 0) || (strcmp (s, "OO") == 0) || (strcmp (s, "O-O") == 0) || (strcmp (s, "0-0") == 0))
  490.         {
  491.         if (side == black)
  492.             strcpy (s, "e8g8");
  493.         else
  494.             strcpy (s, "e1g1");
  495.         }
  496.       else if (strcmp (s, "draw") == 0)
  497.           continue;
  498.       else if (strcmp (s, "Draw") == 0)
  499.           continue;
  500.       else if (strcmp (s, "1-0") == 0)
  501.           continue;
  502.       else if (strcmp (s, "0-1") == 0)
  503.           continue;
  504.       else if (strcmp (s, "2-1/2") == 0)
  505.           continue;
  506.       if (isupper (s[i - 1]))
  507.           s[i - 1] = tolower (s[i - 1]);
  508.  
  509.       bhashkey = hashkey;
  510.       bhashbd = hashbd;
  511.  
  512.       i = BVerifyMove (s, mv, moveno);
  513.       if (c == '?')
  514.         {            /* Bad move, not for the program to play */
  515.         *mv |= BADMOVE;    /* Flag it ! */
  516.         c = getc (fd);
  517.         }
  518.       else if (c == '+' || c == '\r')
  519.           c = gnc (fd);
  520.       if (!i)
  521.         {
  522.         printf ("%s \n", opening);
  523.         /* flush to start of next */
  524.         while ((c = gnc (fd)) != '[' && c != EOF && c != '#');
  525.         if (c == EOF)
  526.             return -1;
  527.         else
  528.           {
  529.               ungetc (c, fd);
  530.               return i;
  531.           }
  532.         }
  533. #ifdef GENIT
  534.       if (GENline++ > 15)
  535.         {
  536.         GENline = 1;
  537.         fprintf (GEN, "\n");
  538.         }
  539.       if ((GENmove / 2) * 2 == GENmove)
  540.           fprintf ("%d. ", (GENmove / 2) + 1);
  541.       if (c == '?')
  542.           fprintf (GEN, "%s? ", GENITs);
  543.       else
  544.           fprintf (GEN, "%s ", GENITs);
  545.       if (!(GENline & 1))
  546.           fprintf (GEN, " ");
  547.       GENmove++;
  548. #endif
  549.       return (i);
  550.       }
  551. }
  552.  
  553.  
  554. /*===================================== GDX =======================================*/
  555.  
  556. struct gdxadmin
  557. {
  558.     unsigned long bkcount;
  559.     unsigned long bksize;
  560.     unsigned long maxoffset;
  561. }
  562. adminStr, bStr;
  563.  
  564. struct gdxdata
  565.   {
  566.       unsigned long hashbd;
  567.       utshort hashkey;
  568.       utshort bmove;
  569.       utshort hint;
  570.       utshort count;
  571.   }
  572. dataStr;
  573.  
  574. #ifdef LONG64
  575. #define lts(x) (utshort)(((x>>48)&0xfffe)|side)
  576. #else
  577. #define lts(x) (utshort)(((x>>16)&0xfffe)|side)
  578. #endif
  579. unsigned long currentoffset;
  580. FHAND gfd;
  581.  
  582. void
  583. GetOpenings (void)
  584.  
  585.      /*
  586.       * If a text file of opening chess plays (the Opening Book) is available: 
  587.       * Read in the Opening Book file and parse the algebraic notation for a move
  588.       * into an unsigned integer format indicating the from and to square. Create
  589.       * or update a binary hash file with the recomended move/moves for each 
  590.       * position.  
  591.       * The binary hash file is opened with readonly access durring the game.
  592.       */
  593. {
  594.     register SHORT i;
  595.     CHAR opening[1024];
  596.     CHAR msg[1024];
  597.     int mustwrite = false;
  598.     UTSHORT xside, doit, side;
  599.     SHORT c;
  600.     UTSHORT mv;
  601.     UTSHORT ix;
  602.     unsigned long x;
  603.     unsigned long games = 0;
  604.  
  605.     FILE *fd;
  606.  
  607.     if ((fd = fopen (bookfile, "r")) == NULL)
  608.     fd = fopen ("gnuchess.book", "r");
  609. #ifdef GENIT
  610.     if ((GEN = fopen ("GEN", "w")) == NULL)
  611.       {
  612.       printf ("GEN FAIL\n");
  613.       exit (1);
  614.       }
  615. #endif
  616.     if (fd != NULL)
  617.       {
  618.       /* yes add to book */
  619.       /* open book as writer */
  620. #ifdef FBOOK
  621.         gfd = fopen(binbookfile, "rb");
  622. #else
  623.       gfd = open (binbookfile, O_RDONLY | O_BINARY);
  624. #endif
  625.       if (fhandok(gfd))
  626.         {
  627.         if (sizeof (struct gdxadmin) == read (gfd, &adminStr, sizeof (struct gdxadmin)))
  628.           {
  629.               bStr.bkcount = adminStr.bkcount;
  630.               bStr.bksize = adminStr.bksize;
  631.               bStr.maxoffset = adminStr.maxoffset;
  632.               if (bStr.bksize && !(bStr.maxoffset == ((unsigned long) (bStr.bksize - 1) * sizeof (struct gdxdata) + sizeof (struct gdxadmin))))
  633.             {
  634.                 printf ("bad format %s\n", binbookfile);
  635.                 exit (1);
  636.             }
  637.           }
  638.         else
  639.           {
  640.               printf ("bad format %s\n", binbookfile);
  641.               exit (1);
  642.           }
  643.         close (gfd);   
  644. #ifdef FBOOK
  645.         gfd = fopen(binbookfile, "r+b");
  646. #else
  647.         gfd = open (binbookfile, O_RDWR | O_BINARY);
  648. #endif
  649.         }
  650.       else
  651.         {
  652. #ifdef FBOOK
  653.         gfd = fopen(binbookfile, "wb");
  654. #else
  655. #ifdef Think_C
  656.         gfd = open (binbookfile, O_RDWR | O_CREAT | O_BINARY);
  657. #else
  658.         gfd = open (binbookfile, O_RDWR | O_CREAT | O_BINARY, 0644);
  659. #endif      
  660. #endif
  661.         adminStr.bkcount = bStr.bkcount = 0;
  662.         adminStr.bksize = bStr.bksize = booksize;
  663.         bStr.maxoffset = adminStr.maxoffset = (unsigned long) (booksize - 1) * sizeof (struct gdxdata) + sizeof (struct gdxadmin);
  664.         dataStr.hashbd = 0;
  665.         dataStr.hashkey = 0;
  666.         dataStr.bmove = 0;
  667.         dataStr.hint = 0;
  668.         dataStr.count = 0;
  669.         write (gfd, &adminStr, sizeof (struct gdxadmin));
  670.         printf ("creating bookfile %s  %ld %ld\n", binbookfile, bStr.maxoffset, bStr.bksize);
  671.         for (x = 0; x < bStr.bksize; x++)
  672.           {
  673.               write (gfd, &dataStr, sizeof (struct gdxdata));
  674.           }
  675.  
  676.  
  677.         }
  678.       if (fhandok(gfd))
  679.         {
  680.  
  681.  
  682.         /* setvbuf(fd,buffr,_IOFBF,2048); */
  683.         side = white;
  684.         xside = black;
  685.         InitializeStats ();
  686.         i = 0;
  687.  
  688.         while ((c = Vparse (fd, &mv, side, opening, i)) >= 0)
  689.           {
  690.               if (c == 1)
  691.             {
  692.  
  693.                 /*
  694.                  * if not first move of an opening and first
  695.                  * time we have seen it save next move as
  696.                  * hint
  697.                  */
  698.                 i++;
  699.                 if (i < bookmaxply + 2)
  700.                   {
  701.                   if (i > 1)
  702.                     {
  703.                     dataStr.hint = mv & 0x3f3f;
  704.                     }
  705.                   if (i < bookmaxply + 1)
  706.                     {
  707.                     doit = true;
  708.  
  709.                     /*
  710.                      * see if this position and
  711.                      * move already exist from
  712.                      * some other opening
  713.                      */
  714.  
  715.                     /*
  716.                      * is this ethical, to offer
  717.                      * the bad move as a
  718.                      * hint?????
  719.                      */
  720.                     ix = 0;
  721.                     if (mustwrite)
  722.                       {
  723.                           lseek (gfd, currentoffset, SEEK_SET);
  724.                           write (gfd, &dataStr, sizeof (struct gdxdata));
  725.                           mustwrite = false;
  726.                       }
  727.                     doit = true;
  728.                     currentoffset = (unsigned long) (bhashkey % bStr.bksize) * sizeof (struct gdxdata) + sizeof (struct gdxadmin);
  729.                     while (true)
  730.                       {
  731.  
  732.                           lseek (gfd, currentoffset, SEEK_SET);
  733.                           if ((read (gfd, &dataStr, sizeof (struct gdxdata)) == 0))
  734.                             break;
  735.  
  736.                           if (dataStr.bmove == 0)
  737.                           break;
  738.                           if (dataStr.hashkey == (utshort) (lts (bhashkey)) && dataStr.hashbd == bhashbd)
  739.                         {
  740.  
  741.                             if ((dataStr.bmove & (~(LASTMOVE | BADMOVE))) == (mv & ~BADMOVE))
  742.                               {
  743.                               dataStr.count++;
  744.                               if (mv & BADMOVE)
  745.                                   dataStr.bmove |= BADMOVE;
  746.                               /*
  747.                                * yes so just bump count - count is
  748.                                * used to choose opening move in
  749.                                * proportion to its presence in the book
  750.                                */
  751.                               doit = false;
  752.                               mustwrite = true;
  753.                               break;
  754.                               }
  755.                             else if (dataStr.bmove & LASTMOVE)
  756.                               {
  757.                               dataStr.bmove &= (~LASTMOVE);
  758.                               lseek (gfd, currentoffset, SEEK_SET);
  759.                               write (gfd, &dataStr, sizeof (struct gdxdata));
  760.                               }
  761.                         }
  762.                           currentoffset += sizeof (struct gdxdata);
  763.                           if (currentoffset > bStr.maxoffset)
  764.                           currentoffset = sizeof (struct gdxadmin);
  765.                       }
  766.  
  767.                     /*
  768.                      * doesn`t exist so add it to
  769.                      * the book
  770.                      */
  771.                     if (!mustwrite)
  772.                       {
  773.                           bStr.bkcount++;
  774. #if !defined CHESSTOOL && !defined XBOARD
  775.                           if (bStr.bkcount % 1000 == 0)
  776.                           printf ("%ld rec %ld openings processed\n", bStr.bkcount, games);
  777. #endif
  778.                           /* initialize a record */
  779.                           dataStr.hashbd = bhashbd;
  780.                           dataStr.hashkey = (utshort) (lts (bhashkey));
  781.                           dataStr.bmove = mv | LASTMOVE;
  782.                           dataStr.count = 1;
  783.                           dataStr.hint = 0;
  784.  
  785.                           mustwrite = true;
  786.                       }
  787.                     }
  788.                   }
  789.                 computer = opponent;
  790.                 opponent = computer ^ 1;
  791.  
  792.                 xside = side;
  793.                 side = side ^ 1;
  794.             }
  795.               else if (i > 0)
  796.             {
  797.                 /* reset for next opening */
  798.                 games++;
  799.                 if (mustwrite)
  800.                   {
  801.                   lseek (gfd, currentoffset, SEEK_SET);
  802.                   write (gfd, &dataStr, sizeof (struct gdxdata));
  803.                   mustwrite = false;
  804.                   }
  805.                 RESET ();
  806.                 i = 0;
  807.                 side = white;
  808.                 xside = black;
  809.  
  810.             }
  811.           }
  812.         if (mustwrite)
  813.           {
  814.               lseek (gfd, currentoffset, SEEK_SET);
  815.               write (gfd, &dataStr, sizeof (struct gdxdata));
  816.               mustwrite = false;
  817.           }
  818.         fclose (fd);
  819.         /* write admin rec with counts */
  820.         adminStr.bkcount = bStr.bkcount;
  821.         currentoffset = 0;
  822. #ifdef FBOOK
  823.        rewind(gfd);
  824. #else
  825.         lseek (gfd, currentoffset, SEEK_SET);
  826. #endif
  827.         write (gfd, &adminStr, sizeof (struct gdxadmin));
  828.  
  829.         close (gfd);
  830.         }
  831.       }
  832.     if (binbookfile != NULL)
  833.       {
  834.       /* open book as reader */
  835. #ifdef FBOOK
  836.         gfd = fopen(binbookfile, "rb");
  837. #else
  838.       gfd = open (binbookfile, O_RDONLY | O_BINARY);
  839. #endif
  840.       if (fhandok(gfd))
  841.         {
  842.         read (gfd, &adminStr, sizeof (struct gdxadmin));
  843.         bStr.bkcount = adminStr.bkcount;
  844.         bStr.bksize = adminStr.bksize;
  845.         bStr.maxoffset = adminStr.maxoffset;
  846.         if (bStr.bksize && !(bStr.maxoffset == ((unsigned long) (bStr.bksize - 1) * sizeof (struct gdxdata) + sizeof (struct gdxadmin))))
  847.           {
  848.               printf ("bad format %s\n", binbookfile);
  849.               exit (1);
  850.           }
  851.  
  852.         }
  853.       else
  854.         {
  855.         bStr.bkcount = 0;
  856.         bStr.bksize = booksize;
  857.  
  858.         }
  859.  
  860. #if !defined CHESSTOOL && !defined XBOARD
  861.       sprintf (msg, CP[213], bStr.bkcount, bStr.bksize);
  862.       ShowMessage (msg);
  863. #endif
  864.       }
  865.     /* set every thing back to start game */
  866.     Book = BOOKFAIL;
  867.     RESET ();
  868.     /* now get ready to play */
  869.     if (!bStr.bkcount)
  870.       {
  871. #if !defined CHESSTOOL && !defined XBOARD
  872.       ShowMessage (CP[212]);
  873. #endif
  874.       Book = 0;
  875.       }
  876. }
  877.  
  878.  
  879. int
  880. OpeningBook (SHORT * hint, SHORT side)
  881.  
  882.      /*
  883.       * Go thru each of the opening lines of play and check for a match with the
  884.       * current game listing. If a match occurs, generate a random number. If this
  885.       * number is the largest generated so far then the next move in this line
  886.       * becomes the current "candidate". After all lines are checked, the
  887.       * candidate move is put at the top of the Tree[] array and will be played by
  888.       * the program. Note that the program does not handle book transpositions.
  889.       */
  890.  
  891. {
  892.     UTSHORT r, m;
  893.     int possibles = TrPnt[2] - TrPnt[1];
  894.     register UTSHORT i, x;
  895.     register UTSHORT rec = 0;
  896.     register UTSHORT summ = 0;
  897.     register UTSHORT h = 0, b = 0;
  898.     struct gdxdata OBB[128];
  899.  
  900.     gsrand ((unsigned int) time ((long *) 0));
  901.     m = 0;
  902.  
  903.     /*
  904.      * find all the moves for this position  - count them and get their
  905.      * total count
  906.      */
  907.     if (bStr.bkcount == 0)
  908.       {
  909.     Book--;
  910.     return false;
  911.       }
  912.     currentoffset = (unsigned long) (hashkey % bStr.bksize) * sizeof (struct gdxdata) + sizeof (struct gdxadmin);
  913.     x = 0;
  914.     lseek (gfd, currentoffset, SEEK_SET);
  915.     while (true)
  916.       {
  917.         if (read (gfd, &OBB[x], sizeof (struct gdxdata)) == 0)
  918.         break;
  919.         if (OBB[x].bmove == 0)
  920.         break;
  921.  
  922.         if (OBB[x].hashkey == (utshort) (lts (hashkey)) && OBB[x].hashbd == hashbd)
  923.       {
  924.         x++;
  925.         if (OBB[x - 1].bmove & LASTMOVE)
  926.         break;
  927.       }
  928.     currentoffset += sizeof (struct gdxdata);
  929.     if (currentoffset > bStr.maxoffset)
  930.       {
  931.         lseek (gfd, sizeof (struct gdxadmin), SEEK_SET);
  932.         currentoffset = sizeof (struct gdxadmin);
  933.       }
  934.  
  935.       }
  936.     if (x == 0)
  937.       {
  938.         Book--;
  939.         return false;
  940.       }
  941. #ifdef DEBUG33
  942.       {
  943.         int loop = true;
  944.         while (loop)
  945.       {
  946.         loop = false;
  947.         for (i = 1; i < x; i++)
  948.           {
  949.         struct gdxdata tmp;
  950.         if (OBB[i].count > OBB[i - 1].count)
  951.           {
  952.             loop = true;
  953.             tmp = OBB[i - 1];
  954.             OBB[i - 1] = OBB[i];
  955.             OBB[i] = tmp;
  956.           }
  957.           }
  958.       }
  959.       }
  960.     for (i = 0; i < x; i++)
  961.       {
  962.         algbr ((OBB[i].bmove >> 8) & 0x3f, (OBB[i].bmove) & 0x3f, 0);
  963.         printf (" %s ", mvstr[0], OBB[i].count);
  964.         algbr ((OBB[i].hint >> 8) & 0x3f, (OBB[i].hint) & 0x3f, 0);
  965.         printf ("%s %c %d\n", mvstr[0], (OBB[i].bmove & BADMOVE) ? '*' : ' ', OBB[i].count);
  966.       }
  967. #endif
  968.     for (i = 0; i < x; i++)
  969.       {
  970.         if ((m = OBB[i].bmove) & BADMOVE)
  971.       {
  972.         m &= 0x3f3f;
  973.         /* is the move is in the MoveList */
  974.         for (b = TrPnt[1]; b < (unsigned) TrPnt[2]; b++)
  975.           {
  976.           if (((Tree[b].f << 8) | Tree[b].t) == m)
  977.           {
  978.             if (--possibles)
  979.                 Tree[b].score = DONTUSE;
  980.             pick (TrPnt[1], TrPnt[2] - 1);
  981.             break;
  982.           }
  983.           }
  984.       }
  985.     else
  986.       summ += OBB[i].count;
  987.       }
  988.     if (summ == 0)
  989.       {
  990.         Book--;
  991.         return false;
  992.       }
  993.  
  994.     r = (urand () % summ);
  995. #ifdef DEBUG33
  996.     printf ("rand is %d, sum is %d\n", r, summ);
  997. #endif
  998.     for (i = 0; i < x; i++)
  999.     if (!(OBB[i].bmove & BADMOVE))
  1000.       {
  1001.         if (r < OBB[i].count)
  1002.       {
  1003.         rec = i;
  1004.         break;
  1005.       }
  1006.     else
  1007.         r -= OBB[i].count;
  1008. #ifdef DEBUG33
  1009.     printf ("rand is %d, sum is %d\n", r, summ);
  1010. #endif
  1011.  
  1012.       }
  1013.  
  1014.     h = ((OBB[rec].hint) & 0x3f3f);
  1015.     m = ((OBB[rec].bmove) & 0x3f3f);
  1016.     /* make sure the move is in the MoveList */
  1017.     for (b = TrPnt[1]; b < (unsigned) TrPnt[2]; b++)
  1018.       {
  1019.         if (((Tree[b].f << 8) | Tree[b].t) == m)
  1020.       {
  1021.         Tree[b].flags |= book;
  1022.         Tree[b].score = 0;
  1023.         break;
  1024.       }
  1025.       }
  1026.     /* Make sure its the best */
  1027.  
  1028.     pick (TrPnt[1], TrPnt[2] - 1);
  1029.     if (Tree[TrPnt[1]].score)
  1030.       {
  1031.         /* no! */
  1032.         Book--;
  1033.         return false;
  1034.       }
  1035.     /* ok pick up the hint and go */
  1036.     *hint = h;
  1037.     return true;
  1038. }
  1039.  
  1040. void
  1041. LOpeningBook (SHORT side)
  1042.  
  1043.      /*
  1044.       * Go thru each of the opening lines of play and check for a match with the
  1045.       * current game listing. If a match occurs, generate a random number. If this
  1046.       * number is the largest generated so far then the next move in this line
  1047.       * becomes the current "candidate". After all lines are checked, the
  1048.       * candidate move is put at the top of the Tree[] array and will be played by
  1049.       * the program. Note that the program does not handle book transpositions.
  1050.       */
  1051.  
  1052. {
  1053.     char Lmove[12], Lhint[12];
  1054.     /*
  1055.      * find all the moves for this position  - count them and get their
  1056.      * total count
  1057.      */
  1058.     struct gdxdata OBB[128];
  1059.     SHORT x;
  1060.     if (bStr.bkcount == 0)
  1061.       {
  1062.       return;
  1063.       }
  1064.     Ldisplay1 ();
  1065.     currentoffset = (unsigned long) (hashkey % bStr.bksize) * sizeof (struct gdxdata) + sizeof (struct gdxadmin);
  1066.     x = 0;
  1067.     lseek (gfd, currentoffset, SEEK_SET);
  1068.     while (true)
  1069.       {
  1070.       if (read (gfd, &OBB[x], sizeof (struct gdxdata)) == 0)
  1071.             return;
  1072.       if (OBB[x].bmove == 0)
  1073.           return;
  1074.  
  1075.  
  1076.       if (OBB[x].hashkey == (utshort) (lts (hashkey)) && OBB[x].hashbd == hashbd)
  1077.         {
  1078.         algbr ((OBB[x].bmove >> 8) & 0x3f, (OBB[x].bmove) & 0x3f, 0);
  1079.         strcpy (Lmove, mvstr[1]);
  1080.         if (OBB[x].bmove & BADMOVE)
  1081.             strcat (Lmove, "?");
  1082.         algbr ((OBB[x].hint >> 8) & 0x3f, (OBB[x].hint) & 0x3f, 0);
  1083.         strcpy (Lhint, mvstr[1]);
  1084.         Ldisplay (Lmove, Lhint, OBB[x].count);
  1085.         if (OBB[x++].bmove & LASTMOVE)
  1086.             break;
  1087.         }
  1088.       currentoffset += sizeof (struct gdxdata);
  1089.       if (currentoffset > bStr.maxoffset)
  1090.         {
  1091.         lseek (gfd, sizeof (struct gdxadmin), SEEK_SET);
  1092.         currentoffset = sizeof (struct gdxadmin);
  1093.         }
  1094.  
  1095.       }
  1096.     Ldisplay2 ();
  1097.     return;
  1098. }
  1099.  
  1100. #ifdef IGNUAN
  1101. int
  1102. GOpeningBook (SHORT * hint, SHORT side, CHAR * mv)
  1103.  
  1104.      /*
  1105.       * Go thru each of the opening lines of play and check for a match with the
  1106.       * current game listing. If a match occurs, generate a random number. If this
  1107.       * number is the largest generated so far then the next move in this line
  1108.       * becomes the current "candidate". After all lines are checked, the
  1109.       * candidate move is put at the top of the Tree[] array and will be played by
  1110.       * the program. Note that the program does not handle book transpositions.
  1111.       */
  1112.  
  1113. {
  1114.     char Lmove[12], Lhint[12];
  1115.     /*
  1116.      * find all the moves for this position  - count them and get their
  1117.      * total count
  1118.      */
  1119.     struct gdxdata OBB[128];
  1120.     SHORT x;
  1121.     if (bStr.bkcount == 0)
  1122.       {
  1123.       return false;
  1124.       }
  1125.     currentoffset = (unsigned long) (hashkey % bStr.bksize) * sizeof (struct gdxdata) + sizeof (struct gdxadmin);
  1126.     x = 0;
  1127.     lseek (gfd, currentoffset, SEEK_SET);
  1128.     while (true)
  1129.       {
  1130.       if (read (gfd, &OBB[x], sizeof (struct gdxdata)) == 0)
  1131.             return false;
  1132.       if (OBB[x].bmove == 0)
  1133.           return false;
  1134.  
  1135.  
  1136.       if (OBB[x].hashkey == (utshort) (lts (hashkey)) && OBB[x].hashbd == hashbd)
  1137.         {
  1138.         algbr ((OBB[x].bmove >> 8) & 0x3f, (OBB[x].bmove) & 0x3f, 0);
  1139.         if ((strcmp (mvstr[0], mv) == 0) ||
  1140.             strcmp (mvstr[1], mv) == 0 ||
  1141.             strcmp (mvstr[2], mv) == 0 ||
  1142.             strcmp (mvstr[3], mv) == 0 ||
  1143.             strcmp (mvstr[4], mv) == 0)
  1144.             return true;
  1145.         if (OBB[x++].bmove & LASTMOVE)
  1146.             return false;
  1147.         }
  1148.       currentoffset += sizeof (struct gdxdata);
  1149.       if (currentoffset > bStr.maxoffset)
  1150.         {
  1151.         lseek (gfd, sizeof (struct gdxadmin), SEEK_SET);
  1152.         currentoffset = sizeof (struct gdxadmin);
  1153.         }
  1154.  
  1155.       }
  1156.     return false;
  1157. }
  1158. #endif
  1159.  
  1160. #ifdef ECO
  1161. #ifdef LONG64
  1162. #define rts(x) (unsigned long)(((x)&(~1))|(side))
  1163. #else
  1164. #define rts(x) (unsigned long)(((x)&(~1))|(side))
  1165. #endif
  1166. extern SHORT ecomove;
  1167. int efd = 0;
  1168. FILE *Efd;
  1169. unsigned int efdsize = 0;
  1170. void
  1171. EOpeningBook (SHORT side)
  1172. {
  1173.     char E[256];
  1174.     struct gdxecodata
  1175.       {
  1176.       unsigned long hashbd;
  1177.       unsigned long hashkey;
  1178.       unsigned int ecoptr;
  1179.       utshort cntr;
  1180.       };
  1181.     SHORT ECOmove = ecomove;
  1182.  
  1183.     /*
  1184.      * find all the moves for this position  - count them and get their
  1185.      * total count
  1186.      */
  1187.     struct gdxecodata OBB;
  1188.     SHORT x, k;
  1189.     int h = 0;
  1190.     int l = 0;
  1191.     unsigned int ecocur;
  1192.     k = 0;
  1193.     if (efd == 0)
  1194.       {
  1195.       struct stat buf;
  1196.       efd = open (BINECO, O_RDONLY | O_BINARY);
  1197.       if (efd < 0)
  1198.         {
  1199.         perror ("BINECO \n");
  1200.         return;
  1201.         }
  1202.       stat (BINECO, &buf);
  1203.       efdsize = buf.st_size / sizeof (struct gdxecodata);
  1204.       Efd = fopen (PGNECO, "r");
  1205.       if (Efd == (FILE *) NULL)
  1206.         {
  1207.         perror ("PGNECO \n");
  1208.         return;
  1209.         }
  1210.       }
  1211.     Ldisplay3 ();
  1212.     while (ECOmove > 0)
  1213.       {
  1214.       h = efdsize;
  1215.       l = 0;
  1216.       ecocur = (h + l) / 2;
  1217.       x = 0;
  1218.  
  1219.       while (true)
  1220.         {
  1221.         SHORT ecofirst;
  1222.         currentoffset = ecocur * sizeof (struct gdxecodata);
  1223.         if (lseek (efd, currentoffset, SEEK_SET) < 0)
  1224.           {
  1225.               perror ("seek error\n");
  1226.               exit (0);
  1227.           }
  1228.         if (read (efd, &OBB, sizeof (struct gdxecodata)) == 0) break;
  1229.         if (OBbStr.hashbd == GameList[ECOmove].hashbd && OBbStr.hashkey == (unsigned long) (rts (GameList[ECOmove].hashkey))
  1230.             && OBbStr.cntr == 0)
  1231.           {
  1232.               /* got it */
  1233.               printf ("After %d plys:\n", ECOmove);
  1234.               ecofirst = true;
  1235.               while (true)
  1236.             {
  1237.                 if (!ecofirst) { if (read (efd, &OBB, sizeof (struct gdxecodata)) == 0) break; }
  1238.                 else ecofirst = false;
  1239.                 if (OBbStr.hashbd != GameList[ECOmove].hashbd) break;
  1240.                 if (OBbStr.hashkey != (unsigned long) (rts (GameList[ECOmove].hashkey))) continue;
  1241.                 if (fseek (Efd, (long) OBbStr.ecoptr, SEEK_SET) < 0)
  1242.                   { perror ("Eseek PGNECO"); exit (1); }
  1243.                 if (fgets (E, sizeof (E), Efd) <= (char *) NULL)
  1244.                   { perror ("fget "); exit (1); }
  1245.                 Ldisplay4 (E);
  1246.                 k++;
  1247.                 if (fgets (E, sizeof (E), Efd) <= (char *) NULL)
  1248.                   { perror ("fget "); exit (1); }
  1249.                 k += 2;
  1250.                 while (E[0] != '[')
  1251.                   {
  1252.                   Ldisplay4 (E);
  1253.                   k++;
  1254.                   if (fgets (E, sizeof (E), Efd) <= (char *) NULL)
  1255.                     { perror ("fget "); exit (1); }
  1256.                   }
  1257.                 Ldisplay4 ("\n");
  1258.                 k++;
  1259.  
  1260.                 if (k++ > 32){
  1261.                 if (getchar () == 'q')
  1262.                   { k = 999; break; }
  1263.                 else
  1264.                     k = 1;}
  1265.             }
  1266.           }
  1267.         else if (OBbStr.hashbd > GameList[ECOmove].hashbd
  1268.              || (OBbStr.hashbd == GameList[ECOmove].hashbd
  1269.                  && OBbStr.hashkey > (unsigned long) (rts (GameList[ECOmove].hashkey))
  1270.                  && OBbStr.cntr > 0)
  1271.              || (OBbStr.hashbd == GameList[ECOmove].hashbd
  1272.                  && OBbStr.hashkey == (unsigned long) (rts (GameList[ECOmove].hashkey))
  1273.                  && OBbStr.cntr > 0))
  1274.           {        /* high */
  1275.               h = ecocur;
  1276.           }
  1277.         else
  1278.           {        /* low */
  1279.               l = ecocur;
  1280.           }
  1281.         if ((h == l) || (h - l) == 1)
  1282.             break;
  1283.         ecocur = (h + l) / 2;
  1284.  
  1285.         if (k > 0)
  1286.             break;
  1287.         }
  1288.       if (k > 0)
  1289.           break;
  1290.       ECOmove--;
  1291.       }
  1292.     Ldisplay2 ();
  1293. }
  1294. #endif
  1295.