Add forgotten files 1.4.70b
[polyglot.git] / book.c
diff --git a/book.c b/book.c
index 73fb2d2..6a7b167 100644 (file)
--- a/book.c
+++ b/book.c
-\r
-// book.c\r
-\r
-// includes\r
-\r
-#include <errno.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#include "board.h"\r
-#include "book.h"\r
-#include "move.h"\r
-#include "move_legal.h"\r
-#include "san.h"\r
-#include "util.h"\r
-#include "option.h"\r
-\r
-// types\r
-\r
-typedef struct {\r
-   uint64 key;\r
-   uint16 move;\r
-   uint16 count;\r
-   uint16 n;\r
-   uint16 sum;\r
-} entry_t;\r
-\r
-// variables\r
-\r
-static FILE * BookFile;\r
-static int BookSize;\r
-\r
-// prototypes\r
-\r
-static int    find_pos      (uint64 key);\r
-\r
-static void   read_entry    (entry_t * entry, int n);\r
-static void   write_entry   (const entry_t * entry, int n);\r
-\r
-static uint64 read_integer  (FILE * file, int size);\r
-static void   write_integer (FILE * file, int size, uint64 n);\r
-\r
-// functions\r
-\r
-// book_clear()\r
-\r
-void book_clear() {\r
-\r
-   BookFile = NULL;\r
-   BookSize = 0;\r
-}\r
-\r
-bool book_is_open(){\r
-    return BookFile!=NULL;\r
-}\r
-\r
-// book_open()\r
-\r
-void book_open(const char file_name[]) {\r
-\r
-   ASSERT(file_name!=NULL);\r
-   if(option_get_bool("BookLearn")){\r
-       BookFile = fopen(file_name,"rb+");\r
-   }else{\r
-       BookFile = fopen(file_name,"rb");\r
-   }\r
-      \r
-//   if (BookFile == NULL) my_fatal("book_open(): can't open file \"%s\": %s\n",file_name,strerror(errno));\r
-   if (BookFile == NULL)  return; \r
-\r
-   if (fseek(BookFile,0,SEEK_END) == -1) {\r
-      my_fatal("book_open(): fseek(): %s\n",strerror(errno));\r
-   }\r
-\r
-   BookSize = ftell(BookFile) / 16;\r
-//   if (BookSize == 0) my_fatal("book_open(): empty file\n");\r
-   if (BookSize == 0) {\r
-      book_close();\r
-      book_clear(); \r
-   };\r
-}\r
-\r
-// book_close()\r
-\r
-void book_close() {\r
-\r
-   if(BookFile==NULL) return;\r
-\r
-   if (fclose(BookFile) == EOF) {\r
-      my_fatal("book_close(): fclose(): %s\n",strerror(errno));\r
-   }\r
-}\r
-\r
-// is_in_book()\r
-\r
-bool is_in_book(const board_t * board) {\r
-\r
-   int pos;\r
-   entry_t entry[1];\r
-\r
-   if(BookFile==NULL) return FALSE;\r
-\r
-   ASSERT(board!=NULL);\r
-\r
-   for (pos = find_pos(board->key); pos < BookSize; pos++) {\r
-      read_entry(entry,pos);\r
-      if (entry->key == board->key) return TRUE;\r
-   }\r
-\r
-   return FALSE;\r
-}\r
-\r
-// book_move()\r
-\r
-int book_move(const board_t * board, bool random) {\r
-\r
-   int best_move;\r
-   int best_score;\r
-   int pos;\r
-   entry_t entry[1];\r
-   int move;\r
-   int score;\r
-\r
-   if(BookFile==NULL) return MoveNone;\r
-\r
-   ASSERT(board!=NULL);\r
-   ASSERT(random==TRUE||random==FALSE);\r
-\r
-\r
-   best_move = MoveNone;\r
-   best_score = 0;\r
-   for (pos = find_pos(board->key); pos < BookSize; pos++) {\r
-\r
-      read_entry(entry,pos);\r
-      if (entry->key != board->key) break;\r
-\r
-      move = entry->move;\r
-      score = entry->count;\r
-\r
-      if (move != MoveNone && move_is_legal(move,board)) {\r
-\r
-         // pick this move?\r
-\r
-         ASSERT(score>0);\r
-\r
-         if (random) {\r
-            best_score += score;\r
-            if (my_random_int(best_score) < score) best_move = move;\r
-         } else {\r
-            if (score > best_score) {\r
-               best_move = move;\r
-               best_score = score;\r
-            }\r
-         }\r
-\r
-      } else {\r
-\r
-         ASSERT(FALSE);\r
-      }\r
-   }\r
-\r
-   return best_move;\r
-}\r
-\r
-// book_disp()\r
-\r
-void book_disp(const board_t * board) {\r
-\r
-   int first_pos;\r
-   int sum;\r
-   int pos;\r
-   entry_t entry[1];\r
-   int move;\r
-   int score;\r
-   char move_string[256];\r
-\r
-   ASSERT(board!=NULL);\r
-\r
-   if(BookFile==NULL) return; \r
-\r
-   first_pos = find_pos(board->key);\r
-\r
-   // sum\r
-\r
-   sum = 0;\r
-\r
-   for (pos = first_pos; pos < BookSize; pos++) {\r
-\r
-      read_entry(entry,pos);\r
-      if (entry->key != board->key) break;\r
-\r
-      sum += entry->count;\r
-   }\r
-\r
-   // disp\r
-\r
-   for (pos = first_pos; pos < BookSize; pos++) {\r
-\r
-      read_entry(entry,pos);\r
-      if (entry->key != board->key) break;\r
-\r
-      move = entry->move;\r
-      score = entry->count;\r
-\r
-      if (score > 0 && move != MoveNone && move_is_legal(move,board)) {\r
-         move_to_san(move,board,move_string,256);\r
-         printf(" %s (%.0f%%)\n",move_string,((double)score)/((double)sum)*100.0);\r
-      }\r
-   }\r
-\r
-   printf("\n");\r
-}\r
-\r
-// book_learn_move()\r
-\r
-void book_learn_move(const board_t * board, int move, int result) {\r
-\r
-   int pos;\r
-   entry_t entry[1];\r
-\r
-   if(BookFile==NULL) return;\r
-\r
-   ASSERT(board!=NULL);\r
-   ASSERT(move_is_ok(move));\r
-   ASSERT(result>=-1&&result<=+1);\r
-\r
-   ASSERT(move_is_legal(move,board));\r
-\r
-   for (pos = find_pos(board->key); pos < BookSize; pos++) {\r
-\r
-      read_entry(entry,pos);\r
-      if (entry->key != board->key) break;\r
-\r
-      if (entry->move == move) {\r
-\r
-         entry->n++;\r
-         entry->sum += result+1;\r
-\r
-         write_entry(entry,pos);\r
-\r
-         break;\r
-      }\r
-   }\r
-}\r
-\r
-// book_flush()\r
-\r
-void book_flush() {\r
-\r
-   if(BookFile==NULL) return;\r
-\r
-   if (fflush(BookFile) == EOF) {\r
-      my_fatal("book_flush(): fflush(): %s\n",strerror(errno));\r
-   }\r
-}\r
-\r
-// find_pos()\r
-\r
-static int find_pos(uint64 key) {\r
-\r
-   int left, right, mid;\r
-   entry_t entry[1];\r
-\r
-   // binary search (finds the leftmost entry)\r
-\r
-   left = 0;\r
-   right = BookSize-1;\r
-\r
-   ASSERT(left<=right);\r
-\r
-   while (left < right) {\r
-\r
-      mid = (left + right) / 2;\r
-      ASSERT(mid>=left&&mid<right);\r
-\r
-      read_entry(entry,mid);\r
-\r
-      if (key <= entry->key) {\r
-         right = mid;\r
-      } else {\r
-         left = mid+1;\r
-      }\r
-   }\r
-\r
-   ASSERT(left==right);\r
-\r
-   read_entry(entry,left);\r
-\r
-   return (entry->key == key) ? left : BookSize;\r
-}\r
-\r
-// read_entry()\r
-\r
-static void read_entry(entry_t * entry, int n) {\r
-\r
-   ASSERT(entry!=NULL);\r
-   ASSERT(n>=0&&n<BookSize);\r
-\r
-   if (fseek(BookFile,n*16,SEEK_SET) == -1) {\r
-      my_fatal("read_entry(): fseek(): %s\n",strerror(errno));\r
-   }\r
-\r
-   entry->key   = read_integer(BookFile,8);\r
-   entry->move  = read_integer(BookFile,2);\r
-   entry->count = read_integer(BookFile,2);\r
-   entry->n     = read_integer(BookFile,2);\r
-   entry->sum   = read_integer(BookFile,2);\r
-}\r
-\r
-// write_entry()\r
-\r
-static void write_entry(const entry_t * entry, int n) {\r
-\r
-   ASSERT(entry!=NULL);\r
-   ASSERT(n>=0&&n<BookSize);\r
-\r
-   if (fseek(BookFile,n*16,SEEK_SET) == -1) {\r
-      my_fatal("write_entry(): fseek(): %s\n",strerror(errno));\r
-   }\r
-\r
-   write_integer(BookFile,8,entry->key);\r
-   write_integer(BookFile,2,entry->move);\r
-   write_integer(BookFile,2,entry->count);\r
-   write_integer(BookFile,2,entry->n);\r
-   write_integer(BookFile,2,entry->sum);\r
-}\r
-\r
-// read_integer()\r
-\r
-static uint64 read_integer(FILE * file, int size) {\r
-\r
-   uint64 n;\r
-   int i;\r
-   int b;\r
-\r
-   ASSERT(file!=NULL);\r
-   ASSERT(size>0&&size<=8);\r
-\r
-   n = 0;\r
-\r
-   for (i = 0; i < size; i++) {\r
-\r
-      b = fgetc(file);\r
-\r
-      if (b == EOF) {\r
-         if (feof(file)) {\r
-            my_fatal("read_integer(): fgetc(): EOF reached\n");\r
-         } else { // error\r
-            my_fatal("read_integer(): fgetc(): %s\n",strerror(errno));\r
-         }\r
-      }\r
-\r
-      ASSERT(b>=0&&b<256);\r
-      n = (n << 8) | b;\r
-   }\r
-\r
-   return n;\r
-}\r
-\r
-// write_integer()\r
-\r
-static void write_integer(FILE * file, int size, uint64 n) {\r
-\r
-   int i;\r
-   int b;\r
-\r
-   ASSERT(file!=NULL);\r
-   ASSERT(size>0&&size<=8);\r
-   ASSERT(size==8||n>>(size*8)==0);\r
-\r
-   for (i = size-1; i >= 0; i--) {\r
-\r
-      b = (n >> (i*8)) & 0xFF;\r
-      ASSERT(b>=0&&b<256);\r
-\r
-      if (fputc(b,file) == EOF) {\r
-         my_fatal("write_integer(): fputc(): %s\n",strerror(errno));\r
-      }\r
-   }\r
-}\r
-\r
-// end of book.cpp\r
-\r
+
+// book.c
+
+// includes
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "board.h"
+#include "book.h"
+#include "move.h"
+#include "move_legal.h"
+#include "san.h"
+#include "util.h"
+#include "option.h"
+
+// types
+
+typedef struct {
+   uint64 key;
+   uint16 move;
+   uint16 count;
+   uint16 n;
+   uint16 sum;
+} entry_t;
+
+// variables
+
+static FILE * BookFile;
+static int BookSize;
+
+// prototypes
+
+static int    find_pos      (uint64 key);
+
+static void   read_entry    (entry_t * entry, int n);
+static void   write_entry   (const entry_t * entry, int n);
+
+static uint64 read_integer  (FILE * file, int size);
+static void   write_integer (FILE * file, int size, uint64 n);
+
+// functions
+
+// book_clear()
+
+void book_clear() {
+
+   BookFile = NULL;
+   BookSize = 0;
+}
+
+bool book_is_open(){
+    return BookFile!=NULL;
+}
+
+// book_open()
+
+void book_open(const char file_name[]) {
+
+   ASSERT(file_name!=NULL);
+   if(FALSE && option_get_bool(Option,"BookLearn")){
+       BookFile = fopen(file_name,"rb+");
+   }else{
+       BookFile = fopen(file_name,"rb");
+   }
+      
+//   if (BookFile == NULL) my_fatal("book_open(): can't open file \"%s\": %s\n",file_name,strerror(errno));
+   if (BookFile == NULL)  return; 
+
+   if (fseek(BookFile,0,SEEK_END) == -1) {
+      my_fatal("book_open(): fseek(): %s\n",strerror(errno));
+   }
+
+   BookSize = ftell(BookFile) / 16;
+//   if (BookSize == 0) my_fatal("book_open(): empty file\n");
+   if (BookSize == 0) {
+      book_close();
+      book_clear(); 
+   };
+}
+
+// book_close()
+
+void book_close() {
+
+   if(BookFile==NULL) return;
+
+   if (fclose(BookFile) == EOF) {
+      my_fatal("book_close(): fclose(): %s\n",strerror(errno));
+   }
+}
+
+// is_in_book()
+
+bool is_in_book(const board_t * board) {
+
+   int pos;
+   entry_t entry[1];
+
+   if(BookFile==NULL) return FALSE;
+
+   ASSERT(board!=NULL);
+
+   for (pos = find_pos(board->key); pos < BookSize; pos++) {
+      read_entry(entry,pos);
+      if (entry->key == board->key) return TRUE;
+   }
+
+   return FALSE;
+}
+
+// book_move()
+
+int book_move(const board_t * board, bool random) {
+
+   int best_move;
+   int best_score;
+   int pos;
+   entry_t entry[1];
+   int move;
+   int score;
+   list_t list[1];
+   int i;
+
+   if(BookFile==NULL) return MoveNone;
+
+   ASSERT(board!=NULL);
+   ASSERT(random==TRUE||random==FALSE);
+
+   // init
+   
+   list_clear(list);
+
+   book_moves(list,board);
+
+   best_move = MoveNone;
+   best_score = 0;
+   for(i=0; i<list_size(list); i++){
+
+      move = list->move[i];
+      score = list->value[i];
+
+      if (move != MoveNone &&
+          move_is_legal(move,board) &&
+          score>10*option_get_int(Option,"BookTreshold")) {
+
+         // pick this move?
+
+         ASSERT(score>0);
+
+         if (random) {
+            best_score += score;
+            if (my_random_int(best_score) < score) best_move = move;
+         } else {
+            if (score > best_score) {
+               best_move = move;
+               best_score = score;
+            }
+         }
+
+      } else {
+
+         ASSERT(FALSE);
+      }
+   }
+
+   return best_move;
+}
+
+// book_moves()
+
+void book_moves(list_t * list, const board_t * board) {
+
+   int first_pos;
+   int sum;
+   int pos;
+   entry_t entry[1];
+   int move;
+   int score;
+   char move_string[256];
+
+   ASSERT(board!=NULL);
+   ASSERT(list!=NULL);
+
+   if(BookFile==NULL) return;
+
+   // null keys are reserved for the header
+   if(board->key==U64(0x0)) return;
+   
+
+
+
+   // init
+
+   list_clear(list);
+
+   first_pos = find_pos(board->key);
+
+   // sum
+
+   sum = 0;
+
+   for (pos = first_pos; pos < BookSize; pos++) {
+
+      read_entry(entry,pos);
+      if (entry->key != board->key) break;
+
+      sum += entry->count;
+   }
+
+   // disp
+
+   for (pos = first_pos; pos < BookSize; pos++) {
+
+      read_entry(entry,pos);
+      if (entry->key != board->key) break;
+
+      move = entry->move;
+      score = (((uint32)entry->count)*((uint32)10000))/sum;  // 32 bit safe!
+
+      if (move != MoveNone && move_is_legal(move,board)) {
+              list_add_ex(list,move,score);
+      }
+   }
+
+}
+
+
+// book_disp()
+
+void book_disp(const board_t * board) {
+
+   char move_string[256];
+   list_t list[1];
+   int i;
+   int treshold=option_get_int(Option,"BookTreshold");
+
+   ASSERT(board!=NULL);
+
+   if(BookFile==NULL) return;
+
+   book_moves(list,board);
+   
+   for(i=0; i<list_size(list); i++){
+       move_to_san(list->move[i],board,move_string,256);
+       if(list->value[i]>10*treshold){
+           printf(" %6s %5.2f%%\n",move_string,list->value[i]/100.0);
+       }else{
+           printf(" %6s %5.2f%% (below treshold %4.2f%%)\n",
+                  move_string,list->value[i]/100.0,treshold/10.0);
+       }
+   }
+   // this is necessary by the xboard protocol
+   printf("\n");
+}
+
+// book_learn_move()
+
+void book_learn_move(const board_t * board, int move, int result) {
+
+   int pos;
+   entry_t entry[1];
+
+   if(BookFile==NULL) return;
+
+   ASSERT(board!=NULL);
+   ASSERT(move_is_ok(move));
+   ASSERT(result>=-1&&result<=+1);
+
+   ASSERT(move_is_legal(move,board));
+
+   for (pos = find_pos(board->key); pos < BookSize; pos++) {
+
+      read_entry(entry,pos);
+      if (entry->key != board->key) break;
+
+      if (entry->move == move) {
+
+         entry->n++;
+         entry->sum += result+1;
+
+         write_entry(entry,pos);
+
+         break;
+      }
+   }
+}
+
+// book_flush()
+
+void book_flush() {
+
+   if(BookFile==NULL) return;
+
+   if (fflush(BookFile) == EOF) {
+      my_fatal("book_flush(): fflush(): %s\n",strerror(errno));
+   }
+}
+
+// find_pos()
+
+static int find_pos(uint64 key) {
+
+   int left, right, mid;
+   entry_t entry[1];
+
+   // binary search (finds the leftmost entry)
+
+   left = 0;
+   right = BookSize-1;
+
+   ASSERT(left<=right);
+
+   while (left < right) {
+
+      mid = (left + right) / 2;
+      ASSERT(mid>=left&&mid<right);
+
+      read_entry(entry,mid);
+
+      if (key <= entry->key) {
+         right = mid;
+      } else {
+         left = mid+1;
+      }
+   }
+
+   ASSERT(left==right);
+
+   read_entry(entry,left);
+
+   return (entry->key == key) ? left : BookSize;
+}
+
+// read_entry()
+
+static void read_entry(entry_t * entry, int n) {
+
+   ASSERT(entry!=NULL);
+   ASSERT(n>=0&&n<BookSize);
+
+   if (fseek(BookFile,n*16,SEEK_SET) == -1) {
+      my_fatal("read_entry(): fseek(): %s\n",strerror(errno));
+   }
+
+   entry->key   = read_integer(BookFile,8);
+   entry->move  = read_integer(BookFile,2);
+   entry->count = read_integer(BookFile,2);
+   entry->n     = read_integer(BookFile,2);
+   entry->sum   = read_integer(BookFile,2);
+}
+
+// write_entry()
+
+static void write_entry(const entry_t * entry, int n) {
+
+   ASSERT(entry!=NULL);
+   ASSERT(n>=0&&n<BookSize);
+
+   if (fseek(BookFile,n*16,SEEK_SET) == -1) {
+      my_fatal("write_entry(): fseek(): %s\n",strerror(errno));
+   }
+
+   write_integer(BookFile,8,entry->key);
+   write_integer(BookFile,2,entry->move);
+   write_integer(BookFile,2,entry->count);
+   write_integer(BookFile,2,entry->n);
+   write_integer(BookFile,2,entry->sum);
+}
+
+// read_integer()
+
+static uint64 read_integer(FILE * file, int size) {
+
+   uint64 n;
+   int i;
+   int b;
+
+   ASSERT(file!=NULL);
+   ASSERT(size>0&&size<=8);
+
+   n = 0;
+
+   for (i = 0; i < size; i++) {
+
+      b = fgetc(file);
+
+      if (b == EOF) {
+         if (feof(file)) {
+            my_fatal("read_integer(): fgetc(): EOF reached\n");
+         } else { // error
+            my_fatal("read_integer(): fgetc(): %s\n",strerror(errno));
+         }
+      }
+
+      ASSERT(b>=0&&b<256);
+      n = (n << 8) | b;
+   }
+
+   return n;
+}
+
+// write_integer()
+
+static void write_integer(FILE * file, int size, uint64 n) {
+
+   int i;
+   int b;
+
+   ASSERT(file!=NULL);
+   ASSERT(size>0&&size<=8);
+   ASSERT(size==8||n>>(size*8)==0);
+
+   for (i = size-1; i >= 0; i--) {
+
+      b = (n >> (i*8)) & 0xFF;
+      ASSERT(b>=0&&b<256);
+
+      if (fputc(b,file) == EOF) {
+         my_fatal("write_integer(): fputc(): %s\n",strerror(errno));
+      }
+   }
+}
+
+// end of book.cpp
+