home *** CD-ROM | disk | FTP | other *** search
/ Más de 2,500 Juegos / CD1.iso / ZIPDAT / 0153 / 0153.ZIP / SRC / BOOK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-08  |  34.9 KB  |  1,330 lines

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