search: fixed a bug in NULL move pruning
[owl.git] / book.c
blob0190c37b68a4d6988b0aee16fea6e96b14bebff0
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * based on Polyglot code
22 #include <errno.h>
23 #include <math.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include "common.h"
28 #include "board.h"
29 #include "engine.h"
30 #include "move.h"
32 struct entry_t {
33 uint64_t key;
34 uint16_t move;
35 uint16_t count;
36 uint16_t n;
37 uint16_t sum;
40 static FILE * book_file;
41 static int book_size;
43 static int find_pos(uint64_t key);
44 static void read_entry(struct entry_t *entry, int n);
45 static uint64_t read_integer(FILE *file, int size);
47 int
48 my_random(int n)
50 double r;
52 r = (double)(rand()) / ((double)(RAND_MAX) + 1.0);
54 return (int)(floor(r * (double)(n)));
57 void
58 book_init(void)
60 book_file = NULL;
61 book_size = 0;
64 void
65 book_open(const char file_name[])
67 book_file = fopen(file_name, "rb");
69 if (book_file != NULL) {
70 if (fseek(book_file, 0, SEEK_END) == -1)
71 fprintf(stderr, "book_open(): fseek(): %s\n", strerror(errno));
73 book_size = ftell(book_file) / 16;
74 if (book_size == -1)
75 fprintf(stderr, "book_open(): ftell(): %s\n", strerror(errno));
76 } else
77 fprintf(stderr, "Unable open book\n");
80 void
81 book_close(void)
83 if (book_file != NULL && fclose(book_file) == EOF)
84 fprintf(stderr, "book_close(): fclose(): %s\n", strerror(errno));
87 int
88 book_move(void)
90 int i, pos, from, to;
91 int move, score;
92 int best_move, best_score;
93 struct entry_t entry[1];
94 struct moves_t moves;
96 if (book_file != NULL && book_size != 0) {
97 /* draw a move according to a fixed probability distribution */
98 best_move = 0;
99 best_score = 0;
101 for (pos = find_pos(brd.hash_key); pos < book_size; pos++) {
102 read_entry(entry, pos);
104 if (entry->key != brd.hash_key)
105 break;
107 move = entry->move;
108 score = entry->count;
110 best_score += score;
111 if (my_random(best_score) < score)
112 best_move = move;
115 if (best_move != 0) {
116 /* convert polyglot move to our format */
117 from = SET_FROM(((best_move >> 9) & 7) * 8 + \
118 ((best_move >> 6) & 7));
119 to = SET_TO(((best_move >> 3) & 7) * 8 + (best_move & 7));
121 if (square64[from] == KING) {
122 if (GET_FROM(from) == E1 && GET_TO(to) == H1)
123 to = SET_TO(G1);
124 else if (GET_FROM(from) == E1 && GET_TO(to) == A1)
125 to = SET_TO(C1);
126 else if (GET_FROM(from) == E8 && GET_TO(to) == H8)
127 to = SET_TO(G8);
128 else if (GET_FROM(from) == E8 && GET_TO(to) == A8)
129 to = SET_TO(C8);
132 gen_moves(&moves);
134 if (!moves.count)
135 return 0;
137 for (i = 0; i < moves.count; i++) {
138 if (!make_move(moves.move[i], TRUE))
139 continue;
140 if ((moves.move[i] & 0xfff) == (from + to))
141 return moves.move[i];
146 return 0;
149 static int
150 find_pos(uint64_t key)
152 int left, right, mid;
153 struct entry_t entry[1];
155 /* binary search (finds the leftmost entry) */
156 left = 0;
157 right = book_size - 1;
159 while (left < right) {
160 mid = (left + right) / 2;
161 read_entry(entry, mid);
163 if (key <= entry->key)
164 right = mid;
165 else
166 left = mid + 1;
168 read_entry(entry, left);
170 return (entry->key == key) ? left : book_size;
173 static void
174 read_entry(struct entry_t *entry, int n)
176 if (fseek(book_file,n*16,SEEK_SET) == -1)
177 fprintf(stderr, "read_entry(): fseek(): %s\n",strerror(errno));
179 entry->key = read_integer(book_file, 8);
180 entry->move = read_integer(book_file, 2);
181 entry->count = read_integer(book_file, 2);
182 entry->n = read_integer(book_file, 2);
183 entry->sum = read_integer(book_file, 2);
186 static uint64_t
187 read_integer(FILE *file, int size)
189 int i, b;
190 uint64_t n;
192 n = 0;
193 for (i = 0; i < size; i++) {
194 b = fgetc(file);
196 if (b == EOF) {
197 if (feof(file))
198 fprintf(stderr, "read_integer(): fgetc(): EOF reached\n");
199 else
200 fprintf(stderr, "read_integer(): fgetc(): %s\n", \
201 strerror(errno));
203 n = (n << 8) | b;
206 return n;