home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 7
/
FreshFishVol7.bin
/
bbs
/
game
/
uchess-2.89.lha
/
UChess
/
src
/
book.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-29
|
10KB
|
406 lines
/*
* book.c - C source for GNU CHESS
*
* Copyright (c) 1988,1989,1990 John Stanback
* Copyright (c) 1992 Free Software Foundation
*
* This file is part of GNU CHESS.
*
* GNU Chess 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 2, or (at your option)
* any later version.
*
* GNU Chess 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 Chess; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "gnuchess.h"
unsigned int urand (void);
extern char mvstr[8][8];
int __aligned bookcount = 0;
static struct bookentry
{
unsigned long bookkey;
unsigned long bookbd;
unsigned INTSIZE2 bmove;
unsigned INTSIZE2 hint;
unsigned char count;
unsigned char flags;
} __aligned *OpenBook=(struct bookentry *)0L;
static struct bookentry __aligned *BookTable[BKTBLSIZE];
int __aligned whichbookloaded=-1;
void
GetOpenings (op_option)
int op_option;
/*
* 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.
*/
#ifndef BOOK
#define BOOK "/usr/games/lib/gnuchess.book"
#endif /* BOOK */
{
FILE *fd;
REG struct bookentry *OB, *OC;
REG INTSIZE int i, f, t;
char opening[80];
char msg[80];
INTSIZE int xside, doit, c, side;
INTSIZE int rf, rt;
unsigned INTSIZE mv;
#ifndef AMIGA
int bs;
unsigned long ltmp;
#endif
/* allocate space for the book */
if (whichbookloaded == op_option)
return;
if (!OpenBook)
OpenBook = (struct bookentry *) malloc(BOOKSIZE*sizeof(struct bookentry));
if (!OpenBook)
{
ShowMessage("Unable to alloc book");
return;
}
ClearMem(OpenBook,BOOKSIZE*sizeof(struct bookentry));
bookcount = 0;
for (i = 0; i < BKTBLSIZE; i++)
{
BookTable[i] = &OpenBook[BOOKSIZE / BKTBLSIZE * i];
}
for (OB = OpenBook; OB < &OpenBook[BOOKSIZE]; OB++)
OB->count = 0;
if (op_option == white)
{
if ((fd = fopen ("uchess:uchesswhite.book", "r")) == NULL)
{
fd = fopen ("uchess:uchess.book", "r");
op_option = 2;
}
}
else
{
if ((fd = fopen ("uchess:uchessblack.book", "r")) == NULL)
{
fd = fopen ("uchess:uchess.book", "r");
op_option = 2;
}
}
if (fd != NULL)
{
whichbookloaded = -1;
ShowMessage("Loading Book..");
ShowMessage("Please Wait...");
OC = NULL;
/*setvbuf(fd,buffr,_IOFBF,2048);*/
side = white;
xside = black;
hashbd = hashkey = 0;
for (i = 0; i < 64; i++)
{
board[i] = Stboard[i];
color[i] = Stcolor[i];
}
i = 0;
while ((c = parse (fd, &mv, side, opening)) >= 0)
if (c == 1)
{
/*
* if not first move of an opening and first time we have
* seen it save next move as hint
*/
if (i && OB->count == 1)
OB->hint = mv & 0x3f3f;
OC = OB; /* save for end marking */
doit = true;
/*
* see if this position and move already exist from some
* other opening
*/
/* is this ethical, to offer the bad move as a hint????? */
for (OB = BookTable[hashkey & BOOKMASK]; OB->count; OB++)
{
if (OB->bookkey == hashkey
&& OB->bookbd == hashbd
&& (OB->flags & SIDEMASK) == side
&& OB->bmove == mv)
{
/*
* yes so just bump count - count is used to choose
* opening move in proportion to its presence in the
* book
*/
doit = false;
OB->count++;
if (OB->count < 1)
OB->count--;
break;
}
/* Book is hashed into BKTBLSIZE chunks based on hashkey */
if (OB == &OpenBook[BOOKSIZE - 1])
OB = OpenBook;
}
/* doesn`t exist so add it to the book */
if (doit)
{
bookcount++;
OB->bookkey = hashkey;
OB->bookbd = hashbd;
OB->bmove = mv;
OB->hint = 0;
OB->count = 1;
OB->flags = side;
}
/* now update the board and hash values */
/* should really check the moves as we do this, but??? */
f = mv >> 8 & 0x3F;
t = mv & 0x3F;
if (board[t] != no_piece)
{
if (color[t] != xside)
{
algbr (f, t, false);
sprintf (msg, CP[211], i + 1, mvstr, opening);
ShowMessage (msg);
}
UpdateHashbd (xside, board[t], -1, t);
}
if (board[f] == no_piece || color[f] != side)
{
algbr (f, t, false);
sprintf (msg, CP[211], i + 1, mvstr, opening);
ShowMessage (msg);
}
UpdateHashbd (side, board[f], f, t);
board[t] = board[f];
color[t] = color[f];
color[f] = neutral;
board[f] = no_piece;
if ((board[t] == king) && ((mv == BLACKCASTLE) || (mv == WHITECASTLE) || (mv == LONGBLACKCASTLE) || (mv == LONGWHITECASTLE)))
{
if (t > f)
{
rf = f + 3;
rt = t - 1;
}
else
{
rf = f - 4;
rt = t + 1;
}
board[rt] = rook;
color[rt] = side;
board[rf] = no_piece;
color[rf] = neutral;
UpdateHashbd (side, rook, rf, rt);
}
i++;
xside = side;
side = side ^ 1;
}
else if (c == 0 && i > 0)
{
/* Mark last move as end of an opening */
/* might want to terminate? */
OB->flags |= BOOKEND;
if (i > 1)
OC->flags |= BOOKEND;
/* reset for next opening */
side = white;
hashbd = hashkey = 0;
for (i = 0; i < 64; i++)
{
board[i] = Stboard[i];
color[i] = Stcolor[i];
}
i = 0;
}
fclose (fd);
#ifdef BINBOOK
fd = fopen (BINBOOK, "w");
fprintf(fd, "%d\n%d\n", BOOKSIZE, bookcount);
if(0>fwrite(OpenBook, sizeof(struct bookentry), BOOKSIZE, fd))
ShowMessage("fwrite");
fclose (fd);
#endif
#if !defined CHESSTOOL && !defined XBOARD
ShowMessage(" ");
ShowMessage(" ");
ShowMessage(" ");
ShowMessage(" ");
ShowMessage(" ");
if (op_option == white)
ShowMessage("White Book");
else if (op_option == black)
ShowMessage("Black Book");
else
ShowMessage("NOptml Book");
sprintf (msg, CP[213], bookcount, BOOKSIZE);
ShowMessage (msg);
whichbookloaded = op_option;
#endif
/* set every thing back to start game */
Book = BOOKFAIL;
for (i = 0; i < 64; i++)
{
board[i] = Stboard[i];
color[i] = Stcolor[i];
}
}
else
{
#if !defined CHESSTOOL && !defined XBOARD
ShowMessage (CP[212]);
#endif
Book = 0;
}
}
int
OpeningBook (unsigned INTSIZE *hint, INTSIZE 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.
*/
{
INTSIZE pnt;
unsigned INTSIZE m;
unsigned r, cnt, tcnt, ccnt;
REG struct bookentry *OB, *OC;
int possibles = TrPnt[2] - TrPnt[1];
gsrand ((unsigned int) time ((long *) 0));
m = 0;
cnt = 0;
tcnt = 0;
ccnt = 0;
OC = NULL;
/*
* find all the moves for this position - count them and get their total
* count
*/
for (OB = BookTable[hashkey & BOOKMASK]; OB->count; OB++)
{