+++ /dev/null
-/*
- * 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;
-}
-
-
-