home *** CD-ROM | disk | FTP | other *** search
/ The Best of Select: Games 3 / cd.iso / os2 / pmgnuchs / book.c < prev    next >
Text File  |  1994-04-20  |  16KB  |  638 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. //  Project:    OS/2 PM Port of GNU CHESS 4.0 (PmChess)
  8. //
  9. //  Version:    1994-4-17
  10. //
  11. //   Porter:    Revised and ported to OS/2 2.1 by Yibing Fan
  12. //
  13. //   System:    OS2 2.1 using emx0.8g 
  14. //
  15.  * This file is part of GNU CHESS.
  16.  *
  17.  * GNU Chess is free software; you can redistribute it and/or modify it under
  18.  * the terms of the GNU General Public License as published by the Free
  19.  * Software Foundation; either version 2, or (at your option) any later
  20.  * version.
  21.  *
  22.  * GNU Chess is distributed in the hope that it will be useful, but WITHOUT ANY
  23.  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  24.  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  25.  * details.
  26.  *
  27.  * You should have received a copy of the GNU General Public License along with
  28.  * GNU Chess; see the file COPYING.  If not, write to the Free Software
  29.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  30.  */
  31. #define INCL_DOS
  32. #define INCL_PM
  33. #include <os2.h>
  34. #include "gnuchess.h"
  35. #include "ataks.h"
  36. #include <unistd.h>
  37. #include <io.h>
  38. #include <fcntl.h>
  39. extern int UseBook;
  40. unsigned booksize = BOOKSIZE;
  41. unsigned int BKTBLSIZE;
  42. unsigned long BOOKMASK;
  43. unsigned bookcount = 0;
  44. unsigned bookpocket = BOOKPOCKET;
  45. static struct bookentry
  46. {
  47.     unsigned long bookkey;
  48.     unsigned long bookbd;
  49.     unsigned short bmove;
  50.     unsigned short hint;
  51.     unsigned short count;
  52.     unsigned short flags;
  53. } *OBEND;
  54. struct bookentry *OpenBook = NULL;
  55. static struct bookentry **BookTable;
  56.  
  57. unsigned short bookmaxply = BOOKMAXPLY;
  58.  
  59. char *bookfile = NULL;
  60. char *binbookfile = BINBOOK;
  61.  
  62. int GotBook = false;
  63. static char bmvstr[4][6];
  64. unsigned long bhashbd, bhashkey;
  65.  
  66. #define pxx " PNBRQK"
  67. #define qxx " pnbrqk"
  68.  
  69.  
  70. void
  71. Balgbr (short int f, short int t, short int flag)
  72.  
  73.  
  74.      /*
  75.       * Generate move strings in different formats.
  76.       */
  77.  
  78. {
  79.     int m3p;
  80.     bmvstr[0][0] = bmvstr[1][0] = bmvstr[2][0] = bmvstr[3][0] = '\0';
  81.  
  82.     if (f != t)
  83.       {
  84.       /* algebraic notation */
  85.       bmvstr[0][0] = cxx[column (f)];
  86.       bmvstr[0][1] = rxx[row (f)];
  87.       bmvstr[0][2] = cxx[column (t)];
  88.       bmvstr[0][3] = rxx[row (t)];
  89.       bmvstr[0][4] = bmvstr[3][0] = '\0';
  90.       if (((bmvstr[1][0] = pxx[board[f]]) == 'P') || (flag & promote))
  91.         {
  92.         if (bmvstr[0][0] == bmvstr[0][2])    /* pawn did not eat */
  93.           {
  94.               bmvstr[2][0] = bmvstr[1][0] = bmvstr[0][2];    /* to column */
  95.               bmvstr[2][1] = bmvstr[1][1] = bmvstr[0][3];    /* to row */
  96.               m3p = 2;
  97.           }
  98.         else
  99.             /* pawn ate */
  100.           {
  101.               bmvstr[2][0] = bmvstr[1][0] = bmvstr[0][0];    /* column */
  102.               bmvstr[2][1] = bmvstr[1][1] = bmvstr[0][2];    /* to column */
  103.               bmvstr[2][2] = bmvstr[0][3];
  104.               m3p = 3;    /* to row */
  105.           }
  106.         if (flag & promote)
  107.           {
  108.               bmvstr[0][4] = bmvstr[1][2] = bmvstr[2][m3p] = qxx[flag & pmask];
  109.               bmvstr[0][5] = bmvstr[1][3] = bmvstr[2][m3p + 1] = bmvstr[3][0] = '\0';
  110.           }
  111.         else
  112.             bmvstr[2][m3p] = bmvstr[1][2] = '\0';
  113.         }
  114.       else
  115.           /* not a pawn */
  116.         {
  117.         bmvstr[2][0] = bmvstr[1][0];
  118.         bmvstr[2][1] = bmvstr[0][1];
  119.         bmvstr[2][2] = bmvstr[1][1] = bmvstr[0][2];    /* to column */
  120.         bmvstr[2][3] = bmvstr[1][2] = bmvstr[0][3];    /* to row */
  121.         bmvstr[2][4] = bmvstr[1][3] = '\0';
  122.         strcpy (bmvstr[3], bmvstr[2]);
  123.         bmvstr[3][1] = bmvstr[0][0];
  124.         if (flag & cstlmask)
  125.           {
  126.               if (t > f)
  127.             {
  128.                 strcpy (bmvstr[1], bmvstr[0]);
  129.                 strcpy (bmvstr[0], CP[5]);
  130.                 strcpy (bmvstr[2], CP[7]);
  131.             }
  132.               else
  133.             {
  134.                 strcpy (bmvstr[1], bmvstr[0]);
  135.                 strcpy (bmvstr[0], CP[6]);
  136.                 strcpy (bmvstr[2], CP[8]);
  137.             }
  138.           }
  139.         }
  140.       }
  141.     else
  142.     bmvstr[0][0] = bmvstr[1][0] = bmvstr[2][0] = bmvstr[3][0] = '\0';
  143. }
  144.  
  145. #ifndef QUIETBOOKGEN
  146. void
  147. bkdisplay (s, cnt, moveno)
  148.      char *s;
  149.      int cnt;
  150.      int moveno;
  151. {
  152.     static short pnt;
  153.     struct leaf *node;
  154.     int r, c, l;
  155.  
  156.     pnt = TrPnt[2];
  157.     printf ("matches = %d\n", cnt);
  158.     printf ("inout move is :%s:move number %d side %s\n", s, moveno / 2 + 1, (moveno & 1) ? "white" : "black");
  159. #ifndef SEMIQUIETBOOKGEN
  160.     printf ("legal moves are \n");
  161.     while (pnt < TrPnt[3])
  162.       {
  163.       node = &Tree[pnt++];
  164.       Balgbr (node->f, node->t, (short) node->flags);
  165.       printf ("%s %s %s %s\n", bmvstr[0], bmvstr[1], bmvstr[2], bmvstr[3]);
  166.       }
  167.     printf ("\n current board is\n");
  168.     for (r = 7; r >= 0; r--)
  169.       {
  170.       for (c = 0; c <= 7; c++)
  171.         {
  172.         l = locn (r, c);
  173.         if (color[l] == neutral)
  174.             printf (" -");
  175.         else if (color[l] == white)
  176.             printf (" %c", qxx[board[l]]);
  177.         else
  178.             printf (" %c", pxx[board[l]]);
  179.         }
  180.       printf ("\n");
  181.       }
  182.     printf ("\n\n");
  183. #endif
  184. }
  185.  
  186. #endif
  187.  
  188. int
  189. BVerifyMove (char *s, short unsigned int *mv, int moveno)
  190.  
  191.      /*
  192.       * Compare the string 's' to the list of legal moves available for the
  193.       * opponent. If a match is found, make the move on the board.
  194.       */
  195.  
  196. {
  197.     static short pnt, tempb, tempc, tempsf, tempst, cnt;
  198.     static struct leaf xnode;
  199.     struct leaf *node;
  200.  
  201.     *mv = 0;
  202.     cnt = 0;
  203.     MoveList (opponent, 2);
  204.     pnt = TrPnt[2];
  205.     while (pnt < TrPnt[3])
  206.       {
  207.       node = &Tree[pnt++];
  208.       Balgbr (node->f, node->t, (short) node->flags);
  209.       if (strcmp (s, bmvstr[0]) == 0 || strcmp (s, bmvstr[1]) == 0 ||
  210.           strcmp (s, bmvstr[2]) == 0 || strcmp (s, bmvstr[3]) == 0)
  211.         {
  212.         cnt++;
  213.         xnode = *node;
  214.         }
  215.       }
  216.     if (cnt == 1)
  217.       {
  218.       MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  219.       if (SqAtakd (PieceList[opponent][0], computer))
  220.         {
  221.         UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  222.         /* Illegal move in check */
  223. #ifndef QUIETBOOKGEN
  224.         printf (CP[77]);
  225.         printf ("\n");
  226.         bkdisplay (s, cnt, moveno);
  227. #endif
  228.         return (false);
  229.         }
  230.       else
  231.         {
  232.         *mv = (xnode.f << 8) | xnode.t;
  233.         Balgbr (xnode.f, xnode.t, false);
  234.         return (true);
  235.         }
  236.       }
  237.     /* Illegal move */
  238. #ifndef QUIETBOOKGEN
  239.     printf (CP[75], s);
  240.     bkdisplay (s, cnt, moveno);
  241. #endif
  242.     return (false);
  243. }
  244.  
  245. void
  246. RESET (void)
  247.  
  248.      /*
  249.       * Reset the board and other variables to start a new game.
  250.       */
  251.  
  252. {
  253.     short int l;
  254.  
  255.     flag.illegal = flag.mate = flag.post = flag.quit = flag.reverse = flag.bothsides = flag.onemove = flag.force = false;
  256.     flag.material = flag.coords = flag.hash = flag.easy = flag.rcptr = true;
  257.     flag.beep = true;
  258.     flag.stars = flag.shade = flag.back = flag.musttimeout = false;
  259.     flag.gamein = false;
  260.     GenCnt = epsquare = 0;
  261.     GameCnt = 0;
  262.     Developed[white] = Developed[black] = false;
  263.     castld[white] = castld[black] = false;
  264.     PawnThreat[0] = CptrFlag[0] = false;
  265.     opponent = white;
  266.     computer = black;
  267.     for (l = 0; l < 64; l++)
  268.       {
  269.       board[l] = Stboard[l];
  270.       color[l] = Stcolor[l];
  271.       Mvboard[l] = 0;
  272.       }
  273.     InitializeStats ();
  274. /*    hashbd = hashkey = 0;*/
  275. }
  276.  
  277. int
  278. Vparse (FILE * fd, unsigned short *mv, short int side, char *opening, int moveno)
  279. {
  280.     register int c, i;
  281.     char s[128];
  282.     char *p;
  283.  
  284.     while (true)
  285.       {
  286.  
  287.       while ((c = getc (fd)) == ' ' || c == '\n');
  288.       if (c == '\r')
  289.           continue;
  290.       i = 0;
  291.       if (c == '!')
  292.         {            /* comment */
  293.         p = opening;
  294.         do
  295.           {
  296.               *p++ = c;
  297.               c = getc (fd);
  298.               if (c == '\r')
  299.               continue;
  300.               /* goes to end of line */
  301.               if (c == '\n')
  302.             {
  303.                 *p = '\0';
  304.                 return 0;
  305.               } if (c == EOF)
  306.               return -1;
  307.           }
  308.         while (true);
  309.         }
  310.       /* is it a move number or analysis ( in [ ] ) */
  311.       /* number cannot start with a 0 because of 0-0 */
  312.       else if (!isalpha (c) && c != '0')
  313.         {
  314.         int nonspace = false;
  315.  
  316.         /* analysis */
  317.         if (c == '[')
  318.           {
  319.               /* scan to ] */
  320.               while ((c = getc (fd)) != ']')
  321.             {
  322.                 if (c == EOF)
  323.                 return -1;
  324.             } continue;
  325.           }
  326.         while (true)
  327.           {
  328.               c = getc (fd);
  329.               if (c == '\r')
  330.               continue;
  331.               if (c == '\n')
  332.               return 0;
  333.               if (c == EOF)
  334.             {
  335.                 return -1;
  336.             }
  337.               /* stop at first nonspace a ... is space */
  338.               /* must be nonspace because of 0-0 */
  339.               if (nonspace)
  340.             {
  341.                 if (c != '.' && c != ' ')
  342.                 break;
  343.             }
  344.               if (c == '.')
  345.             {
  346.                 nonspace = true;
  347.             }
  348.               /* stop if alpha must be move */
  349.               else if (isalpha (c))
  350.               break;
  351.           }
  352.         }
  353.       s[0] = (char) c;
  354.       while ((c = getc (fd)) != '?' && c != '+' && c != ' ' && c != '\n' && c != '\t' && c != EOF)
  355.         {
  356.         if (c == '\r')
  357.             continue;
  358.         if (c != 'x')
  359.             s[++i] = c;
  360.         }
  361.       s[++i] = '\0';
  362.  
  363.       if (c == EOF)
  364.           return (-1);
  365.       if (s[0] == '!' || s[0] == ';')
  366.         {
  367.         while (c != '\n' && c != EOF)
  368.             c = getc (fd);
  369.         if (c == EOF)
  370.             return -1;
  371.         else
  372.             return (0);
  373.         }
  374.       if ((strcmp (s, "o-o-o") == 0) || (strcmp (s, "OOO") == 0) || (strcmp (s, "O-O-O") == 0) || (strcmp (s, "0-0-0") == 0))
  375.         {
  376.         if (side == black)
  377.             strcpy (s, "e8c8");
  378.         else
  379.             strcpy (s, "e1c1");
  380.         }
  381.       else if ((strcmp ("o-o", s) == 0) || (strcmp (s, "OO") == 0) || (strcmp (s, "O-O") == 0) || (strcmp (s, "0-0") == 0))
  382.         {
  383.         if (side == black)
  384.             strcpy (s, "e8g8");
  385.         else
  386.             strcpy (s, "e1g1");
  387.         }
  388.       else if (strcmp (s, "draw") == 0)
  389.           continue;
  390.       else if (strcmp (s, "1-0") == 0)
  391.           continue;
  392.       else if (strcmp (s, "0-1") == 0)
  393.           continue;
  394.       if (isupper (s[i - 1]))
  395.           s[i - 1] = tolower (s[i - 1]);
  396.  
  397.       bhashkey = hashkey;
  398.       bhashbd = hashbd;
  399.  
  400.       i = BVerifyMove (s, mv, i);
  401.       if (c == '?')
  402.         {            /* Bad move, not for the program to play */
  403.         *mv |= BADMOVE;    /* Flag it ! */
  404.         c = getc (fd);
  405.         }
  406.       else if (c == '+' || c == '\r')
  407.           c = getc (fd);
  408.       if (!i)
  409.         {
  410.         printf ("%s \n", opening);
  411.         /* flush to start of next */
  412.         while ((c = getc (fd)) != '!' && c != EOF);
  413.         if (c == EOF)
  414.             return -1;
  415.         else
  416.           {
  417.               ungetc (c, fd);
  418.               return i;
  419.           }
  420.         }
  421.       return (i);
  422.       }
  423. }
  424.  
  425. struct gdxadmin
  426. {
  427.     unsigned int bookcount;
  428.     unsigned int booksize;
  429.     unsigned long maxoffset;
  430. } ADMIN, B;
  431.  
  432. struct gdxdata
  433. {
  434.     unsigned long hashbd;
  435.     unsigned short hashkey;
  436.     unsigned short bmove;
  437.     unsigned short hint;
  438.     unsigned short count;
  439. } DATA;
  440.  
  441. #define lts(x) (((x>>16)&0xfffe)|side)
  442. unsigned long currentoffset;
  443. int gfd;
  444.  
  445. void
  446. GetOpenings (HWND hWnd)
  447.  
  448.      /*
  449.       * Read in the Opening Book file and parse the algebraic notation for a move
  450.       * into an unsigned integer format indicating the from and to square. Create
  451.       * a linked list of opening lines of play, with entry->next pointing to the
  452.       * next line and entry->move pointing to a chunk of memory containing the
  453.       * moves. More Opening lines of up to 100 half moves may be added to
  454.       * gnuchess.book. But now its a hashed table by position which yields a move
  455.       * or moves for each position. It no longer knows about openings per say only
  456.       * positions and recommended moves in those positions.
  457.       */
  458. {
  459.     register short int i;
  460.     char opening[256];
  461.     char msg[256];
  462.     int mustwrite = false;
  463.     unsigned short xside, doit, side;
  464.     short int c;
  465.     unsigned short mv;
  466.     unsigned short ix;
  467.     unsigned int x;
  468.     unsigned int games = 0;
  469.  
  470.     FILE *fd;
  471.     if (binbookfile != NULL)
  472.       {
  473.       /* open book as writer */
  474.       gfd = open (binbookfile, O_RDONLY | O_BINARY);
  475.       if (gfd >= 0)
  476.         {
  477.         read (gfd, &ADMIN, sizeof (struct gdxadmin));
  478.         B.bookcount = ADMIN.bookcount;
  479.         B.booksize = ADMIN.booksize;
  480.         B.maxoffset = ADMIN.maxoffset;
  481.                 if (B.booksize && !(B.maxoffset == ((unsigned long) (B.booksize - 1) * sizeof (struct gdxdata) + sizeof (struct gdxadmin))))
  482.           {
  483.               printf ("bad format %s\n", binbookfile);
  484.               exit (1);
  485.           }
  486.  
  487.         }
  488.       else
  489.         {
  490.         B.bookcount = 0;
  491.         B.booksize = booksize;
  492.  
  493.         }
  494.  
  495.       sprintf (msg, CP[213], B.bookcount, B.booksize);
  496.       ShowMessage (hWnd, msg);
  497.       }
  498.     /* set every thing back to start game */
  499.           if (UseBook) {
  500.           Book = BOOKFAIL;
  501.           } else {
  502.           Book = 0;
  503.           } /* endif */
  504.     RESET ();
  505.     /* now get ready to play */
  506.     if (!B.bookcount)
  507.       {
  508.       ShowMessage (hWnd, "CP[212]");
  509.       Book = 0;
  510.       }
  511. }
  512.  
  513.  
  514. int
  515. OpeningBook (unsigned short *hint, short int side)
  516.  
  517.      /*
  518.       * Go thru each of the opening lines of play and check for a match with the
  519.       * current game listing. If a match occurs, generate a random number. If this
  520.       * number is the largest generated so far then the next move in this line
  521.       * becomes the current "candidate". After all lines are checked, the
  522.       * candidate move is put at the top of the Tree[] array and will be played by
  523.       * the program. Note that the program does not handle book transpositions.
  524.       */
  525.  
  526. {
  527.     unsigned short r, m;
  528.     int possibles = TrPnt[2] - TrPnt[1];
  529.  
  530.     gsrand ((unsigned int) time ((long *) 0));
  531.     m = 0;
  532.  
  533.     /*
  534.      * find all the moves for this position  - count them and get their
  535.      * total count
  536.      */
  537.     {
  538.     register unsigned short i, x;
  539.     register unsigned short rec = 0;
  540.     register unsigned short summ = 0;
  541.     register unsigned short h = 0, b = 0;
  542.     struct gdxdata OBB[128];
  543.     if (B.bookcount == 0)
  544.       {
  545.           Book = 0;
  546.           return false;
  547.       }
  548.         currentoffset = (unsigned long) (hashkey % B.booksize) * sizeof (struct gdxdata) + sizeof (struct gdxadmin);
  549.     x = 0;
  550.     lseek (gfd, currentoffset, SEEK_SET);
  551.     while (true)
  552.       {
  553.           if (read (gfd, &OBB[x], sizeof (struct gdxdata)) == 0) break;
  554.           if (OBB[x].bmove == 0) break;
  555.  
  556.  
  557.           if (OBB[x].hashkey == (unsigned short)(lts(hashkey)) && OBB[x].hashbd == hashbd)
  558.         {
  559.             x++;if(OBB[x-1].bmove & LASTMOVE) break;
  560.         }
  561.         currentoffset += sizeof (struct gdxdata); 
  562.           if (currentoffset > B.maxoffset){
  563.           lseek (gfd, sizeof (struct gdxadmin), SEEK_SET);
  564.           currentoffset = sizeof (struct gdxadmin); 
  565.         }
  566.  
  567.       }
  568.     if (x == 0)
  569.       {
  570.           Book = 0;
  571.           return false;
  572.       }
  573.     for (i = 0; i < x; i++)
  574.       {
  575.           if ((m = OBB[i].bmove) & BADMOVE)
  576.         {
  577.             m ^= BADMOVE;
  578.             /* is the move is in the MoveList */
  579.             for (b = TrPnt[1]; b < (unsigned) TrPnt[2]; b++)
  580.               {
  581.               if (((Tree[b].f << 8) | Tree[b].t) == m)
  582.                 {
  583.  
  584.                 if (--possibles)
  585.                     Tree[b].score = DONTUSE;
  586.                 break;
  587.                 }
  588.               }
  589.         }
  590.           else summ += OBB[i].count;
  591.       }
  592.     if (summ == 0)
  593.           {
  594.               Book = 0;
  595.               return false;
  596.           }
  597.  
  598.     r = (urand () % summ);
  599.     for (i = 0; i < x; i++)
  600.         if (!(OBB[i].bmove & BADMOVE) ){
  601.             if( r < OBB[i].count)
  602.                 {
  603.                 rec = i;
  604.                 break;
  605.                 }
  606.               else
  607.               r -= OBB[i].count;
  608.         } 
  609.  
  610.     h = ((OBB[rec].hint) & 0x3f3f);
  611.     m = ((OBB[rec].bmove) & 0x3f3f);
  612.     /* make sure the move is in the MoveList */
  613.     for (b = TrPnt[1]; b < (unsigned) TrPnt[2]; b++)
  614.       {
  615.           if (((Tree[b].f << 8) | Tree[b].t) == m)
  616.         {
  617.             Tree[b].flags |= book;
  618.             Tree[b].score = 0;
  619.             break;
  620.         }
  621.       }
  622.     /* Make sure its the best */
  623.  
  624.     pick (TrPnt[1], TrPnt[2] - 1);
  625.     if (Tree[TrPnt[1]].score)
  626.       {
  627.           /* no! */
  628.           Book = 0;
  629.           return false;
  630.       }
  631.     /* ok pick up the hint and go */
  632.     *hint = h;
  633.     return true;
  634.     }
  635.     Book = 0;
  636.     return false;
  637. }
  638.