Updating to version 1.3, release made by Mike Vanier (mvanier@bbb.caltech.edu).
[gnushogi.git] / src / book.c
diff --git a/src/book.c b/src/book.c
deleted file mode 100644 (file)
index c0c2686..0000000
+++ /dev/null
@@ -1,931 +0,0 @@
-/*
- * book.c - C source for GNU SHOGI
- *
- * Copyright (c) 1993, 1994, 1995 Matthias Mutz
- *
- * GNU SHOGI is based on GNU CHESS
- *
- * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software
- * Foundation
- *
- * This file is part of GNU SHOGI.
- *
- * GNU Shogi is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 1, or (at your option) any later
- * version.
- *
- * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * GNU Shogi; see the file COPYING.  If not, write to the Free Software
- * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "gnushogi.h"
-#ifdef MSDOS
-#include <io.h>
-#endif
-#if !defined MSDOS && !defined THINK_C
-#define O_BINARY 0
-#endif
-#include <fcntl.h>
-#ifdef THINK_C
-#include <unix.h>
-/* #define BOOKTEST */
-#endif
-
-
-#include "book.h"
-
-
-
-unsigned booksize = BOOKSIZE;
-unsigned short bookmaxply = BOOKMAXPLY;
-unsigned bookcount = 0;
-
-#ifdef BOOK
-char *bookfile = BOOK;
-#else
-char *bookfile = NULL;
-#endif
-#ifdef BINBOOK
-char *binbookfile = BINBOOK;
-#else
-char *binbookfile = NULL;
-#endif
-
-
-
-static char bmvstr[3][7];
-
-static ULONG bhashbd;
-static ULONG bhashkey;
-
-
-void
-Balgbr (short int f, short int t, short int flag)
-
-
-     /*
-      * Generate move strings in different formats.
-      */
-
-{
-  short promoted = false;
-
-  if ( (f & 0x80) != 0)
-    {                
-      f &= 0x7f;
-      promoted = true;
-    }
-
-  if ( f > NO_SQUARES ) 
-    { short piece;
-      piece = f - NO_SQUARES;
-      if ( f > (NO_SQUARES+NO_PIECES) )
-        piece -= NO_PIECES;
-      flag = (dropmask | piece); 
-    }
-  if ( (t & 0x80) != 0 )
-    {
-      flag |= promote;
-      t &= 0x7f;
-    }
-  if ( f == t && (f != 0 || t != 0) ) 
-    { 
-#if !defined XSHOGI
-      char buffer[80];
-      sprintf(buffer,"error in algbr: FROM=TO=%d, flag=0x%4x\n",t,flag);
-      ShowMessage(buffer);
-#endif
-      bmvstr[0][0] = bmvstr[1][0] = bmvstr[2][0] = '\0';
-    }
-  else
-  if ( (flag & dropmask) != 0 )
-    {
-      /* bmvstr[0]: P*3c bmvstr[1]: P'3c */ 
-      short piece = flag & pmask;
-      bmvstr[0][0] = pxx[piece];
-      bmvstr[0][1] = '*';
-      bmvstr[0][2] = cxx[column (t)];
-      bmvstr[0][3] = rxx[row (t)];
-      bmvstr[0][4] = bmvstr[2][0] = '\0';
-      strcpy (bmvstr[1], bmvstr[0]);
-      bmvstr[1][1] = '\'';
-    }
-  else
-  if (f != 0 || t != 0)
-    {
-      /* algebraic notation */
-      /* bmvstr[0]: 7g7f bmvstr[1]: (+)P7g7f(+) bmvstr[2]: (+)P7f(+) */
-      bmvstr[0][0] = cxx[column (f)];
-      bmvstr[0][1] = rxx[row (f)];
-      bmvstr[0][2] = cxx[column (t)];
-      bmvstr[0][3] = rxx[row (t)];
-      bmvstr[0][4] = '\0';
-      if (promoted)
-       {
-          bmvstr[1][0] = bmvstr[2][0] = '+';
-          bmvstr[1][1] = bmvstr[2][1] = pxx[board[f]];
-          strcpy(&bmvstr[1][2],&bmvstr[0][0]);
-          strcpy(&bmvstr[2][2],&bmvstr[0][2]);
-       }                                  
-      else
-       {
-          bmvstr[1][0] = bmvstr[2][0] = pxx[board[f]];
-          strcpy(&bmvstr[1][1],&bmvstr[0][0]);
-          strcpy(&bmvstr[2][1],&bmvstr[0][2]);
-       }
-      if (flag & promote)
-        {
-               strcat(bmvstr[0], "+");
-               strcat(bmvstr[1], "+");
-               strcat(bmvstr[2], "+");
-        }
-    }
-  else
-    bmvstr[0][0] = bmvstr[1][0] = bmvstr[2][0] = '\0';
-}
-
-
-
-
-#ifndef QUIETBOOKGEN
-void
-bkdisplay (s, cnt, moveno)
-     char *s;
-     int cnt;
-     int moveno;
-{
-    static short pnt;
-    struct leaf far *node;
-    int r, c, l;
-
-    pnt = TrPnt[2];
-    printf ("matches = %d\n", cnt);
-    printf ("inout move is :%s: move number %d side %s\n", 
-                s, moveno / 2 + 1, (moveno & 1) ? "white" : "black");
-#ifndef SEMIQUIETBOOKGEN
-    printf ("legal moves are \n");
-    while (pnt < TrPnt[3])
-      {
-         node = &Tree[pnt++];
-         if ( is_promoted[board[node->f]] )
-           Balgbr (node->f | 0x80, node->t, (short) node->flags);
-         else
-           Balgbr (node->f, node->t, (short) node->flags);
-         printf ("%s %s %s\n", 
-            bmvstr[0], bmvstr[1], bmvstr[2]);
-      }
-    printf ("\n current board is\n");
-    for (r = (NO_ROWS-1); r >= 0; r--)
-       {
-         for (c = 0; c <= (NO_COLS-1); c++)
-           { char pc;
-             l = locn (r, c);
-             pc = (is_promoted[board[l]] ? '+' : ' ');
-             if (color[l] == neutral)
-               printf (" -");
-             else if (color[l] == black)
-               printf ("%c%c", pc, qxx[board[l]]);
-             else
-               printf ("%c%c", pc, pxx[board[l]]);
-           }
-         printf ("\n");
-       }
-    printf ("\n");
-    {  
-       short color;
-       for (color = black; color <= white; color++)
-         { short piece, c;
-           printf((color==black)?"black ":"white ");
-            for (piece = pawn; piece <= king; piece++)
-             if (c = Captured[color][piece]) 
-               printf("%i%c ",c,pxx[piece]);
-            printf("\n");
-          };
-    }
-#endif /* SEMIQUIETBOOKGEN */
-}
-
-#endif /* QUIETBOOKGEN */
-
-int
-BVerifyMove (char *s, short unsigned int *mv, int moveno)
-
-     /*
-      * Compare the string 's' to the list of legal moves available for the
-      * opponent. If a match is found, make the move on the board.
-      */
-
-{
-    static short pnt, tempb, tempc, tempsf, tempst, cnt;
-    static struct leaf xnode;
-    struct leaf far *node;
-
-    *mv = 0;
-    cnt = 0;
-    MoveList (opponent, 2, -2, true);
-    pnt = TrPnt[2];
-    while (pnt < TrPnt[3])
-      {
-         node = &Tree[pnt++];
-         if ( is_promoted[board[node->f]] )
-           Balgbr (node->f | 0x80, node->t, (short) node->flags);
-         else
-           Balgbr (node->f, node->t, (short) node->flags);
-         if (strcmp (s, bmvstr[0]) == 0 || strcmp (s, bmvstr[1]) == 0 ||
-             strcmp (s, bmvstr[2]) == 0)
-           {
-               cnt++;
-               xnode = *node;
-           }
-      }
-    if (cnt == 1)
-      {   short blockable;
-         MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst, &INCscore);
-         if (SqAtakd (PieceList[opponent][0], computer, &blockable))
-           {
-               UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
-               /* Illegal move in check */
-#if !defined QUIETBOOKGEN
-#ifdef XSHOGI
-               printf ("Illegal move (in check)");
-#else
-               printf (CP[77]);
-#endif
-               printf ("\n");
-               bkdisplay (s, cnt, moveno);
-#endif
-               return (false);
-           }
-         else
-           {
-               *mv = (xnode.f << 8) | xnode.t;
-               if ( is_promoted[board[xnode.t]] )
-                 Balgbr (xnode.f | 0x80, xnode.t, false);
-               else
-                 Balgbr (xnode.f, xnode.t, false);
-               return (true);
-           }
-      }
-    /* Illegal move */
-#if !defined QUIETBOOKGEN
-#ifdef XSHOGI
-    printf ("Illegal move (no match) %s\n", s);
-#else
-    printf (CP[75], s);
-#endif
-    bkdisplay (s, cnt, moveno);
-#endif
-    return (false);
-}
-
-void
-RESET (void)
-
-     /*
-      * Reset the board and other variables to start a new game.
-      */
-
-{
-    short int l;
-
-    flag.illegal = flag.mate = flag.post = flag.quit = flag.reverse = flag.bothsides = flag.onemove = flag.force = false;
-    flag.material = flag.coords = flag.hash = flag.easy = flag.beep = flag.rcptr = true;
-    flag.stars = flag.shade = flag.back = flag.musttimeout = false;
-    flag.gamein = false;
-    GenCnt = 0;
-    GameCnt = 0;
-    CptrFlag[0] = TesujiFlag[0] = false;
-    opponent = black;
-    computer = white;
-    for (l = 0; l < NO_SQUARES; l++)
-      {
-         board[l] = Stboard[l];
-         color[l] = Stcolor[l];
-         Mvboard[l] = 0;
-      }
-    ClearCaptured ();
-    InitializeStats ();
-    hashbd = hashkey = 0; 
-}
-
-static
-int
-Vparse (FILE * fd, USHORT *mv, USHORT *flags, USHORT side, int moveno)
-{
-    int c, i;
-    char s[255];
-
-    *flags = 0;
-
-    while (true)
-      {
-          
-         while ((c = getc (fd)) == ' ' || c == '!' || c == '/' || c == '\n');
-
-         if ( c == '(' ) 
-           {   /* amount of time spent for the last move */
-               while ((c = getc(fd)) != ')' && c != EOF);
-               if ( c == ')' ) 
-                 while ((c = getc (fd)) == ' ' || c == '\n');
-           }
-
-         if (c == '[')
-           {   /* comment for the actual game */
-               while ( (c = getc(fd)) != ']' && c != EOF );
-               if ( c == ']' ) 
-                 while ((c = getc (fd)) == ' ' || c == '\n');
-           }
-          
-         if (c == '\r')
-             continue;
-
-         if (c == '#')
-           {   /* comment */
-               do
-                 {
-                     c = getc (fd);
-                     if (c == '\r')
-                         continue;
-                     /* goes to end of line */
-                     if (c == '\n')
-                       {
-                           return 0;
-                       } 
-                     if (c == EOF)
-                       return -1;
-                 }
-               while (true);
-           }
-
-         s[i = 0] = (char) c;
-
-          while ( c >= '0' && c <= '9' )
-           { 
-             c = getc(fd);
-             s[++i] = (char) c;
-           }
-
-         if ( c == '.' )
-           { 
-             while ((c = getc (fd)) == ' ' || c == '.' || c == '\n');
-             s[i = 0] = (char) c;
-           }     
-
-         while ((c = getc (fd)) != '?' && c != '!' && c != ' ' && c != '(' && c != '\n' && c != '\t' && c != EOF)
-           {
-               if (c == '\r')
-                   continue;
-               if (c != 'x' && c != '-' && c != ',' && c != ';' && c != '=')
-                   s[++i] = (char) c;
-           }
-         s[++i] = '\0';
-
-         if ( c == '(' ) 
-           {
-             while ((c = getc(fd)) != ')' && c != EOF);
-             if ( c == ')' ) 
-               c = getc(fd);
-           }
-
-         if (c == EOF)
-             return (-1);
-
-         if (s[0] == '#')
-           {
-               while (c != '\n' && c != EOF)
-                   c = getc (fd);
-               if (c == EOF)
-                   return -1;
-               else
-                   return (0);
-           }
-
-         if (strcmp (s, "draw") == 0)
-             continue;
-         else if (strcmp (s, "1-0") == 0)
-             continue;
-         else if (strcmp (s, "0-1") == 0)
-             continue;
-         else if (strcmp (s, "Resigns") == 0)
-             continue;
-         else if (strcmp (s, "Resigns.") == 0)
-             continue;
-         else if (strcmp (s, "Sennichite") == 0)
-             continue;
-         else if (strcmp (s, "Sennichite.") == 0)
-             continue;
-         else if (strcmp (s, "Jishogi") == 0)
-             continue;
-         else if (strcmp (s, "Jishogi.") == 0)
-             continue;
-
-          bhashkey = hashkey;
-         bhashbd  = hashbd;
-
-         i = BVerifyMove (s, mv, moveno);
-
-         if (c == '?')
-           {                   /* Bad move, not for the program to play */
-               *flags |= BADMOVE;      /* Flag it ! */
-               while ((c = getc (fd)) == '?' || c == '!' || c == '/');
-           }                      
-#ifdef EASY_OPENINGS
-         else if (c == '~')
-           {                   /* Do not use by computer */
-               *flags |= BADMOVE;      /* Flag it ! */
-               while ((c = getc (fd)) == '?' || c == '!' || c == '/');
-           }            
-#endif
-         else if (c == '!')
-           {                   /* Good move */
-               *flags |= GOODMOVE;     /* Flag it ! */
-               while ((c = getc (fd)) == '?' || c == '!' || c == '/');
-           }
-         else if (c == '\r')
-             c = getc (fd);
-
-         if ( c == '(' ) 
-           while ((c = getc(fd)) != ')' && c != EOF);
-
-         if (!i)
-           {
-               /* flush to start of next */
-               while ((c = getc (fd)) != '#' && c != EOF);
-               if (c == EOF)
-                   return -1;
-               else
-                 {
-                     ungetc (c, fd);
-                     return i;
-                 }
-           }
-
-         return (i);
-      }
-}
-
-
-static struct gdxadmin ADMIN;
-struct gdxadmin B;
-
-static struct gdxdata DATA;
-
-
-
-/* lts(l) returns most significant 16 bits of l */
-
-#ifdef LONG64
-#define lts(x) (USHORT)(((x>>48)&0xfffe)|side)
-#else
-#if defined THINK_C || defined USE_LTSIMP
-static USHORT ltsimp (long x)
-{ USHORT n;
-  n = (((x>>16)&0xfffe));
-#if 0
-  printf("x=0x%lx lts(x)=0x%x\n",x,n);
-#endif
-  return(n);
-}
-#define lts(x) (USHORT)(ltsimp(x) | side)
-#else
-#define lts(x) (USHORT)(((x>>16)&0xfffe) | side)
-#endif
-#endif
-
-
-/* #define HashValue(l) lts(l) */
-#define HashValue(l) (USHORT)(l & 0xffff)
-
-
-static int gfd;
-
-
-static ULONG currentoffset;
-
-
-#define MAXOFFSET(B) ((B.booksize-1)*sizeof_gdxdata + sizeof_gdxadmin)
-
-#define HashOffset(hashkey,B) { \
-  currentoffset = ((ULONG)hashkey % B.booksize)*sizeof_gdxdata + sizeof_gdxadmin; \
-}
-
-#define NextOffset(B) { \
-  currentoffset += sizeof_gdxdata; \
-  if (currentoffset > B.maxoffset) \
-    currentoffset = sizeof_gdxadmin; \
-}
-
-
-
-
-#define WriteAdmin() { \
-  lseek (gfd, 0, 0); \
-  write (gfd, (char *)&ADMIN, sizeof_gdxadmin); \
-}
-
-#define WriteData() { \
-  if ( mustwrite ) { \
-    lseek (gfd, currentoffset, 0); \
-    write (gfd, (char *)&DATA, sizeof_gdxdata); \
-    mustwrite = false; \
-  } \
-}
-
-static int ReadAdmin(void) {
-  lseek (gfd, 0, 0); 
-  return (sizeof_gdxadmin == read (gfd, (char *)&ADMIN, sizeof_gdxadmin));
-}
-
-static int ReadData(struct gdxdata *DATA) {
-  lseek (gfd, currentoffset, 0); 
-  return (sizeof_gdxdata == read (gfd, (char *)DATA, sizeof_gdxdata));
-}
-
-
-void
-GetOpenings (void)
-
-     /*
-      * Read in the Opening Book file and parse the algebraic notation for a move
-      * into an unsigned integer format indicating the from and to square. Create
-      * a linked list of opening lines of play, with entry->next pointing to the
-      * next line and entry->move pointing to a chunk of memory containing the
-      * moves. More Opening lines of up to 100 half moves may be added to
-      gnuchess.book. But now its a hashed table by position which yields a move
-      * or moves for each position. It no longer knows about openings per say only
-      * positions and recommended moves in those positions.
-      */
-{
-    short int i;
-    char opening[80];
-    char msg[80];
-    int mustwrite = false, first;
-    unsigned short xside, side;
-    short int c;
-    USHORT mv, flags; unsigned int x;
-    unsigned int games = 0;
-    LONG collisions = 0;
-
-    FILE *fd;
-
-    if ((fd = fopen (bookfile, "r")) == NULL)
-       fd = fopen ("gnushogi.tbk", "r");
-    if (fd != NULL)
-      {
-         /* yes add to book */
-         /* open book as writer */
-         gfd = open (binbookfile, O_RDONLY | O_BINARY);
-         if (gfd >= 0)
-           {
-               if ( ReadAdmin() ) 
-                 {
-                     B.bookcount = ADMIN.bookcount;
-                     B.booksize = ADMIN.booksize;
-                     B.maxoffset = ADMIN.maxoffset;
-                     if (B.booksize && !(B.maxoffset == MAXOFFSET(B)))
-                       {
-                           printf ("bad format %s\n", binbookfile);
-                           exit (1);
-                       }
-                 }
-               else
-                 {
-                     printf ("bad format %s\n", binbookfile);
-                     exit (1);
-                 }
-               close (gfd);
-                gfd = open (binbookfile, O_RDWR | O_BINARY);
-
-           }
-         else
-           {
-#if defined THINK_C || defined MSDOS
-                gfd = open (binbookfile, O_RDWR | O_CREAT | O_BINARY);
-#else
-                gfd = open (binbookfile, O_RDWR | O_CREAT | O_BINARY, 0644);
-#endif
-               ADMIN.bookcount = B.bookcount = 0;
-               ADMIN.booksize = B.booksize = booksize;
-                B.maxoffset = ADMIN.maxoffset = MAXOFFSET(B);
-               DATA.hashbd = 0;
-               DATA.hashkey = 0;
-               DATA.bmove = 0;
-               DATA.flags = 0;
-               DATA.hint = 0;
-               DATA.count = 0;
-               write (gfd, (char *)&ADMIN, sizeof_gdxadmin);
-               printf ("creating bookfile %s  %ld %d\n", binbookfile, B.maxoffset, B.booksize);
-               for (x = 0; x < B.booksize; x++)
-                 {
-                     write (gfd, (char *)&DATA, sizeof_gdxdata);
-                 }
-
-
-           }
-         if (gfd >= 0)
-           {
-
-
-               /* setvbuf(fd,buffr,_IOFBF,2048); */
-               side = black;
-               xside = white;
-               hashbd = hashkey = 0;
-               i = 0;
-
-               while ((c = Vparse (fd, &mv, &flags, side, i)) >= 0)
-                 {
-                     if (c == 1)
-                        {
-
-                           /*
-                             * if not first move of an opening and first
-                             * time we have seen it save next move as
-                             * hint
-                             */
-                           i++;
-                           if (i < bookmaxply + 2)
-                             {
-                                 if (i > 1 && !(flags & BADMOVE)) {
-                                   DATA.hint = mv;
-                                 }
-                                 if (i < bookmaxply + 1)
-                                   {
-                                       /*
-                                        * see if this position and
-                                        * move already exist from
-                                        * some other opening
-                                        */
-
-                                       WriteData();
-                                        HashOffset(bhashkey,B);
-                                       first = true;
-                                       while (true) {
-                                         if (!ReadData(&DATA)) break; /* corrupted binbook file */
-                                         if (DATA.bmove == 0) break;  /* free entry */
-                                         if (DATA.hashkey == HashValue(bhashkey) && DATA.hashbd == bhashbd) {
-                                           if (DATA.bmove == mv) {
-                                              /*
-                                              * yes so just bump count - count is
-                                              * used to choose opening move in
-                                              * proportion to its presence in the book
-                                              */
-                                             DATA.count++;
-                                             DATA.flags |= flags;
-                                             mustwrite = true;
-                                             break;   
-                                           } else {
-                                             if ( first ) collisions++;
-                                             if (DATA.flags & LASTMOVE) {
-                                               DATA.flags &= (~LASTMOVE);
-                                               mustwrite = true;
-                                               WriteData();
-                                             }
-                                           }
-                                         }
-                                          NextOffset(B);
-                                         first = false;
-                                       }
-
-                                       /*
-                                        * doesn`t exist so add it to
-                                        * the book
-                                        */
-                                       if (!mustwrite)
-                                         {
-                                             B.bookcount++;
-#if !defined XSHOGI
-#if defined THINK_C || defined MSDOS
-                                             if (B.bookcount % 100 == 0)
-#else
-                                             if (B.bookcount % 1000 == 0)
-#endif
-                                                 printf ("%d rec %d openings processed\n", B.bookcount, games);
-#endif
-                                             /* initialize a record */
-                                             DATA.hashbd = bhashbd;
-                                             DATA.hashkey = HashValue(bhashkey);
-                                             DATA.bmove = mv;
-                                             DATA.flags = flags | LASTMOVE;
-                                             DATA.count = 1;
-                                             DATA.hint = 0;
-                                             mustwrite = true;
-                                         }
-                                   }
-                             }
-                           computer = opponent;
-                           opponent = computer ^ 1;
-
-                           xside = side;
-                           side = side ^ 1;
-                       }
-                     else if (i > 0)
-                       {
-                           /* reset for next opening */
-                           games++;
-                           WriteData();
-                           RESET ();
-                           i = 0;
-                           side = black;
-                           xside = white;
-
-                       }
-                 }
-               WriteData();
-               fclose (fd);
-               /* write admin rec with counts */
-               ADMIN.bookcount = B.bookcount;
-               WriteAdmin();
-
-               close (gfd);
-           }
-      }
-    if (binbookfile != NULL)
-      {
-         /* open book as reader */
-         gfd = open (binbookfile, O_RDONLY | O_BINARY);
-         if (gfd >= 0)
-           {
-               if ( ReadAdmin() && (!ADMIN.booksize || ADMIN.maxoffset == MAXOFFSET(ADMIN)) ) 
-                 {
-                   B.bookcount = ADMIN.bookcount;
-                   B.booksize = ADMIN.booksize;
-                   B.maxoffset = ADMIN.maxoffset;
-                 }
-                else
-                 {
-                   printf ("bad format %s\n", binbookfile);
-                   exit (1);
-                 }
-
-           }
-         else
-           {
-               B.bookcount = 0;
-               B.booksize = booksize;
-
-           }
-
-#if !defined XSHOGI
-         sprintf (msg, CP[213], B.bookcount, B.booksize);
-         ShowMessage (msg);
-         /* printf("%ld collisions\n", collisions); */
-#endif
-      }
-    /* set every thing back to start game */
-    Book = BOOKFAIL;
-    RESET ();
-    /* now get ready to play */
-    if (!B.bookcount)
-      {
-#if !defined XSHOGI
-         ShowMessage (CP[212]);
-#endif
-         Book = 0;
-      }
-}
-
-
-int
-OpeningBook (unsigned short *hint, short int side)
-
-     /*
-      * Go thru each of the opening lines of play and check for a match with the
-      * current game listing. If a match occurs, generate a random number. If this
-      * number is the largest generated so far then the next move in this line
-      * becomes the current "candidate". After all lines are checked, the
-      * candidate move is put at the top of the Tree[] array and will be played by
-      * the program. Note that the program does not handle book transpositions.
-      */
-
-{
-    unsigned short r, m;
-    int possibles = TrPnt[2] - TrPnt[1];
-
-    gsrand ((unsigned int) time ((long *) 0));
-    m = 0;
-
-    /*
-     * find all the moves for this position  - count them and get their
-     * total count
-     */
-    {
-       USHORT i, x;
-       USHORT rec = 0;
-       USHORT summ = 0;
-       USHORT h = 0, b = 0;
-       struct gdxdata OBB[128];
-       if (B.bookcount == 0)
-         {
-             Book--;
-             return false;
-         }
-       x = 0;
-        HashOffset(hashkey,B);
-#ifdef BOOKTEST
-        printf("looking for book move, bhashbd = 0x%lx bhashkey = 0x%x\n", (ULONG)hashbd, HashValue(hashkey));
-#endif
-       while (true)
-         {
-             if (!ReadData(&OBB[x])) break;
-             if (OBB[x].bmove == 0) break;
-#ifdef BOOKTEST
-              printf("compare with bhashbd = 0x%lx bhashkey = 0x%x\n", OBB[x].hashbd, OBB[x].hashkey);
-#endif
-             if (OBB[x].hashkey == HashValue(hashkey) && OBB[x].hashbd == (ULONG)hashbd)
-               {
-                   x++;
-                   if (OBB[x-1].flags & LASTMOVE) break;
-               }
-              NextOffset(B);
-         }
-#ifdef BOOKTEST
-        printf("%d book move(s) found.\n",x);
-#endif
-       if (x == 0)
-         {
-             Book--;
-             return false;
-         }
-       for (i = 0; i < x; i++)
-         {
-             if (OBB[i].flags & BADMOVE)
-               {
-                   m = OBB[i].bmove;
-                   /* is the move is in the MoveList */
-                   for (b = TrPnt[1]; b < (unsigned) TrPnt[2]; b++)
-                     {
-                         if (((Tree[b].f << 8) | Tree[b].t) == m)
-                           {
-
-                               if (--possibles)
-                                   Tree[b].score = DONTUSE;
-                               break;
-                           }
-                     }
-               }
-             else 
-               {
-#if defined BOOKTEST
-                 char s[20];
-                 movealgbr(m = OBB[i].bmove,s); 
-                 printf("finding book move: %s\n",s);
-#endif
-                 summ += OBB[i].count;
-               }
-         }
-       if (summ == 0)
-          {
-              Book--;
-              return false;
-          }
-
-       r = (urand () % summ);
-       for (i = 0; i < x; i++)
-           if (!(OBB[i].flags & BADMOVE) ){
-               if( r < OBB[i].count)
-                   {
-                       rec = i;
-                       break;
-                   }
-                 else
-                     r -= OBB[i].count;
-           } 
-
-       h = OBB[rec].hint;
-       m = OBB[rec].bmove;
-       /* make sure the move is in the MoveList */
-       for (b = TrPnt[1]; b < (unsigned) TrPnt[2]; b++)
-         {
-             if (((Tree[b].f << 8) | Tree[b].t) == m)
-               {
-                   Tree[b].flags |= book;
-                   Tree[b].score = 0;
-                   break;
-               }
-         }
-       /* Make sure its the best */
-
-       pick (TrPnt[1], TrPnt[2] - 1);
-       if (Tree[TrPnt[1]].score)
-         {
-             /* no! */
-             Book--;
-             return false;
-         }
-       /* ok pick up the hint and go */
-       *hint = h;
-       return true;
-    }
-    Book--;
-    return false;
-}
-
-
-