14 #include "move_legal.h"
\r
31 static FILE * BookFile;
\r
32 static int BookSize;
\r
36 static int find_pos (uint64 key);
\r
38 static void read_entry (entry_t * entry, int n);
\r
39 static void write_entry (const entry_t * entry, int n);
\r
41 static uint64 read_integer (FILE * file, int size);
\r
42 static void write_integer (FILE * file, int size, uint64 n);
\r
54 bool book_is_open(){
\r
55 return BookFile!=NULL;
\r
60 void book_open(const char file_name[]) {
\r
62 ASSERT(file_name!=NULL);
\r
63 if(option_get_bool(Option,"BookLearn")){
\r
64 BookFile = fopen(file_name,"rb+");
\r
66 BookFile = fopen(file_name,"rb");
\r
69 // if (BookFile == NULL) my_fatal("book_open(): can't open file \"%s\": %s\n",file_name,strerror(errno));
\r
70 if (BookFile == NULL) return;
\r
72 if (fseek(BookFile,0,SEEK_END) == -1) {
\r
73 my_fatal("book_open(): fseek(): %s\n",strerror(errno));
\r
76 BookSize = ftell(BookFile) / 16;
\r
77 // if (BookSize == 0) my_fatal("book_open(): empty file\n");
\r
78 if (BookSize == 0) {
\r
88 if(BookFile==NULL) return;
\r
90 if (fclose(BookFile) == EOF) {
\r
91 my_fatal("book_close(): fclose(): %s\n",strerror(errno));
\r
97 bool is_in_book(const board_t * board) {
\r
102 if(BookFile==NULL) return FALSE;
\r
104 ASSERT(board!=NULL);
\r
106 for (pos = find_pos(board->key); pos < BookSize; pos++) {
\r
107 read_entry(entry,pos);
\r
108 if (entry->key == board->key) return TRUE;
\r
116 int book_move(const board_t * board, bool random) {
\r
127 if(BookFile==NULL) return MoveNone;
\r
129 ASSERT(board!=NULL);
\r
130 ASSERT(random==TRUE||random==FALSE);
\r
136 book_moves(list,board);
\r
138 best_move = MoveNone;
\r
140 for(i=0; i<list_size(list); i++){
\r
142 move = list->move[i];
\r
143 score = list->value[i];
\r
145 if (move != MoveNone &&
\r
146 move_is_legal(move,board) &&
\r
147 score/10>option_get_int(Option,"BookTreshold")) {
\r
154 best_score += score;
\r
155 if (my_random_int(best_score) < score) best_move = move;
\r
157 if (score > best_score) {
\r
159 best_score = score;
\r
174 void book_moves(list_t * list, const board_t * board) {
\r
182 char move_string[256];
\r
184 ASSERT(board!=NULL);
\r
185 ASSERT(list!=NULL);
\r
187 if(BookFile==NULL) return;
\r
193 first_pos = find_pos(board->key);
\r
199 for (pos = first_pos; pos < BookSize; pos++) {
\r
201 read_entry(entry,pos);
\r
202 if (entry->key != board->key) break;
\r
204 sum += entry->count;
\r
209 for (pos = first_pos; pos < BookSize; pos++) {
\r
211 read_entry(entry,pos);
\r
212 if (entry->key != board->key) break;
\r
214 move = entry->move;
\r
215 score = (entry->count*10000)/sum; // 32 bit safe!
\r
217 if (score > 0 && move != MoveNone && move_is_legal(move,board)) {
\r
218 list_add_ex(list,move,score);
\r
227 void book_disp(const board_t * board) {
\r
229 char move_string[256];
\r
233 ASSERT(board!=NULL);
\r
235 if(BookFile==NULL) return;
\r
237 book_moves(list,board);
\r
239 for(i=0; i<list_size(list); i++){
\r
240 move_to_san(list->move[i],board,move_string,256);
\r
241 printf(" %6s %5.2f%%\n",move_string,list->value[i]/100.0);
\r
245 // book_learn_move()
\r
247 void book_learn_move(const board_t * board, int move, int result) {
\r
252 if(BookFile==NULL) return;
\r
254 ASSERT(board!=NULL);
\r
255 ASSERT(move_is_ok(move));
\r
256 ASSERT(result>=-1&&result<=+1);
\r
258 ASSERT(move_is_legal(move,board));
\r
260 for (pos = find_pos(board->key); pos < BookSize; pos++) {
\r
262 read_entry(entry,pos);
\r
263 if (entry->key != board->key) break;
\r
265 if (entry->move == move) {
\r
268 entry->sum += result+1;
\r
270 write_entry(entry,pos);
\r
279 void book_flush() {
\r
281 if(BookFile==NULL) return;
\r
283 if (fflush(BookFile) == EOF) {
\r
284 my_fatal("book_flush(): fflush(): %s\n",strerror(errno));
\r
290 static int find_pos(uint64 key) {
\r
292 int left, right, mid;
\r
295 // binary search (finds the leftmost entry)
\r
298 right = BookSize-1;
\r
300 ASSERT(left<=right);
\r
302 while (left < right) {
\r
304 mid = (left + right) / 2;
\r
305 ASSERT(mid>=left&&mid<right);
\r
307 read_entry(entry,mid);
\r
309 if (key <= entry->key) {
\r
316 ASSERT(left==right);
\r
318 read_entry(entry,left);
\r
320 return (entry->key == key) ? left : BookSize;
\r
325 static void read_entry(entry_t * entry, int n) {
\r
327 ASSERT(entry!=NULL);
\r
328 ASSERT(n>=0&&n<BookSize);
\r
330 if (fseek(BookFile,n*16,SEEK_SET) == -1) {
\r
331 my_fatal("read_entry(): fseek(): %s\n",strerror(errno));
\r
334 entry->key = read_integer(BookFile,8);
\r
335 entry->move = read_integer(BookFile,2);
\r
336 entry->count = read_integer(BookFile,2);
\r
337 entry->n = read_integer(BookFile,2);
\r
338 entry->sum = read_integer(BookFile,2);
\r
343 static void write_entry(const entry_t * entry, int n) {
\r
345 ASSERT(entry!=NULL);
\r
346 ASSERT(n>=0&&n<BookSize);
\r
348 if (fseek(BookFile,n*16,SEEK_SET) == -1) {
\r
349 my_fatal("write_entry(): fseek(): %s\n",strerror(errno));
\r
352 write_integer(BookFile,8,entry->key);
\r
353 write_integer(BookFile,2,entry->move);
\r
354 write_integer(BookFile,2,entry->count);
\r
355 write_integer(BookFile,2,entry->n);
\r
356 write_integer(BookFile,2,entry->sum);
\r
361 static uint64 read_integer(FILE * file, int size) {
\r
367 ASSERT(file!=NULL);
\r
368 ASSERT(size>0&&size<=8);
\r
372 for (i = 0; i < size; i++) {
\r
378 my_fatal("read_integer(): fgetc(): EOF reached\n");
\r
380 my_fatal("read_integer(): fgetc(): %s\n",strerror(errno));
\r
384 ASSERT(b>=0&&b<256);
\r
393 static void write_integer(FILE * file, int size, uint64 n) {
\r
398 ASSERT(file!=NULL);
\r
399 ASSERT(size>0&&size<=8);
\r
400 ASSERT(size==8||n>>(size*8)==0);
\r
402 for (i = size-1; i >= 0; i--) {
\r
404 b = (n >> (i*8)) & 0xFF;
\r
405 ASSERT(b>=0&&b<256);
\r
407 if (fputc(b,file) == EOF) {
\r
408 my_fatal("write_integer(): fputc(): %s\n",strerror(errno));
\r