Add some book-control options
[xboard.git] / book.c
diff --git a/book.c b/book.c
index 82d4a45..2c1a06a 100644 (file)
--- a/book.c
+++ b/book.c
@@ -30,6 +30,9 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include <math.h>
 
 #include "common.h"
 #include "backend.h"
@@ -63,8 +66,6 @@ entry_t entry_none = {
 };
 
 char *promote_pieces=" nbrqac=";
-extern char castlingRights[][BOARD_SIZE];
-extern char epStatus[];
 
 uint64 Random64[781] = {
    U64(0x9D39247E33776D41), U64(0x2AF7398005AAA5C7), U64(0x44DB015024623547), U64(0x9C15F73E62A76AE2),
@@ -273,8 +274,7 @@ uint64 *RandomTurn      =Random64+780;
 
 uint64 hash(int moveNr)
 {
-    char c;
-    int p, r, f, i, p_enc, squareNr, pieceGroup;
+    int r, f, p_enc, squareNr, pieceGroup;
     uint64 key=0, Zobrist;
 
     for(f=BOARD_LEFT; f<BOARD_RGHT; f++){
@@ -311,16 +311,16 @@ uint64 hash(int moveNr)
     }
     // Holdings not implemented yet!
 
-    if(castlingRights[moveNr][2] >= 0) {
-       if(castlingRights[moveNr][0] >= 0) key^=RandomCastle[0];
-       if(castlingRights[moveNr][1] >= 0) key^=RandomCastle[1];
+    if(boards[moveNr][CASTLING][2] != NoRights) {
+       if(boards[moveNr][CASTLING][0] != NoRights) key^=RandomCastle[0];
+       if(boards[moveNr][CASTLING][1] != NoRights) key^=RandomCastle[1];
     }
-    if(castlingRights[moveNr][5] >= 0) {
-       if(castlingRights[moveNr][3] >= 0) key^=RandomCastle[2];
-       if(castlingRights[moveNr][4] >= 0) key^=RandomCastle[3];
+    if(boards[moveNr][CASTLING][5] != NoRights) {
+       if(boards[moveNr][CASTLING][3] != NoRights) key^=RandomCastle[2];
+       if(boards[moveNr][CASTLING][4] != NoRights) key^=RandomCastle[3];
     }
 
-    f = epStatus[moveNr];
+    f = boards[moveNr][EP_STATUS];
     if(f >= 0 && f < 8){
         if(!WhiteOnMove(moveNr)){
            // the test for neighboring Pawns might not be needed, 
@@ -467,7 +467,7 @@ char *ProbeBook(int moveNr, char *book)
     static char move_s[6];
     int total_weight;
 
-    if(book == NULL) return NULL; 
+    if(book == NULL || moveNr >= 2*appData.bookDepth) return NULL; 
 //    if(gameInfo.variant != VariantNormal) return NULL; // Zobrist scheme only works for normal Chess, so far
     f=fopen(book,"rb");
     if(!f){
@@ -480,7 +480,10 @@ char *ProbeBook(int moveNr, char *book)
     if(appData.debugMode) fprintf(debugFP, "book key = %08x%08x\n", (unsigned int)(key>>32), (unsigned int)key);
 
     offset=find_key(f, key, &entry);
-    if(entry.key != key) return NULL;
+    if(entry.key != key) {
+         fclose(f);
+         return NULL;
+    }
     entries[0] = entry;
     count=1;
     fseek(f, 16*(offset+1), SEEK_SET);
@@ -495,12 +498,21 @@ char *ProbeBook(int moveNr, char *book)
         if(count == MOVE_BUF) break;
         entries[count++] = entry;
     }
+    if(appData.bookStrength != 50) { // transform weights
+        double power, maxWeight = 0.0;
+        if(appData.bookStrength) power = (100.-appData.bookStrength)/appData.bookStrength;
+        for(i=0; i<count; i++) if(entries[i].weight > maxWeight) maxWeight = entries[i].weight;
+        for(i=0; i<count; i++){
+            double weight = entries[i].weight / maxWeight;
+             if(weight > 0)
+                entries[i].weight = appData.bookStrength || weight == 1.0 ? 1e4*exp(power * log(weight)) + 0.5 : 0.0;
+        }
+    }
     total_weight = 0;
     for(i=0; i<count; i++){
         total_weight += entries[i].weight;
     }
-    srandom( time(0) );
-    j = (random() & 0x7FFF) * total_weight >> 15; // create random < total_weight
+    j = (random() & 0xFFF) * total_weight >> 12; // create random < total_weight
     total_weight = 0;
     for(i=0; i<count; i++){
         total_weight += entries[i].weight;
@@ -510,5 +522,6 @@ char *ProbeBook(int moveNr, char *book)
     move_to_string(move_s, entries[i].move);
     if(appData.debugMode) fprintf(debugFP, "book move field = %d\n", entries[i].move);
 
+    fclose(f);
     return move_s;
 }