book.dat: Remove, it turns out it is GPLv3 while Pachi is GPLv2
[pachi/derm.git] / fbook.c
blobda08db85c6ac962731ce735d0a42a34f8c926525
1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
6 #include "board.h"
7 #include "debug.h"
8 #include "fbook.h"
9 #include "random.h"
12 static coord_t
13 coord_transform(struct board *b, coord_t coord, int i)
15 #define HASH_VMIRROR 1
16 #define HASH_HMIRROR 2
17 #define HASH_XYFLIP 4
18 if (i & HASH_VMIRROR) {
19 coord = coord_xy(b, coord_x(coord, b), board_size(b) - 1 - coord_y(coord, b));
21 if (i & HASH_HMIRROR) {
22 coord = coord_xy(b, board_size(b) - 1 - coord_x(coord, b), coord_y(coord, b));
24 if (i & HASH_XYFLIP) {
25 coord = coord_xy(b, coord_y(coord, b), coord_x(coord, b));
27 return coord;
31 struct fbook *
32 fbook_init(char *filename, struct board *b)
34 FILE *f = fopen(filename, "r");
35 if (!f) {
36 perror(filename);
37 return NULL;
40 struct fbook *fbook = calloc(1, sizeof(*fbook));
41 fbook->bsize = board_size(b);
42 fbook->handicap = b->handicap;
43 for (int i = 0; i < 1<<fbook_hash_bits; i++)
44 fbook->moves[i] = pass;
46 if (DEBUGL(1))
47 fprintf(stderr, "Loading opening fbook %s...\n", filename);
49 /* Scratch board where we lay out the sequence;
50 * one for each transposition. */
51 struct board *bs[8];
52 for (int i = 0; i < 8; i++) {
53 bs[i] = board_init(NULL);
54 board_resize(bs[i], fbook->bsize - 2);
57 char linebuf[1024];
58 while (fgets(linebuf, sizeof(linebuf), f)) {
59 char *line = linebuf;
60 linebuf[strlen(linebuf) - 1] = 0; // chop
62 /* Format of line is:
63 * BSIZE COORD COORD COORD... | COORD
64 * We descend up to |, then add the new node
65 * with value minimax(1000), forcing UCT to
66 * always pick that node immediately. */
67 int bsize = strtol(line, &line, 10);
68 if (bsize != fbook->bsize - 2)
69 continue;
70 while (isspace(*line)) line++;
72 for (int i = 0; i < 8; i++) {
73 board_clear(bs[i]);
74 bs[i]->last_move.color = S_WHITE;
77 while (*line != '|') {
78 coord_t *c = str2coord(line, fbook->bsize);
80 for (int i = 0; i < 8; i++) {
81 coord_t coord = coord_transform(b, *c, i);
82 struct move m = { .coord = coord, .color = stone_other(bs[i]->last_move.color) };
83 int ret = board_play(bs[i], &m);
84 assert(ret >= 0);
87 coord_done(c);
88 while (!isspace(*line)) line++;
89 while (isspace(*line)) line++;
92 line++;
93 while (isspace(*line)) line++;
95 /* In case of multiple candidates, pick one with
96 * exponentially decreasing likelihood. */
97 while (strchr(line, ' ') && fast_random(2)) {
98 line = strchr(line, ' ');
99 while (isspace(*line)) line++;
100 // fprintf(stderr, "<%s> skip to %s\n", linebuf, line);
103 coord_t *c = str2coord(line, fbook->bsize);
104 for (int i = 0; i < 8; i++) {
105 coord_t coord = coord_transform(b, *c, i);
106 #if 0
107 char conflict = is_pass(fbook->moves[bs[i]->hash & fbook_hash_mask]) ? '+' : 'C';
108 if (conflict == 'C')
109 for (int j = 0; j < i; j++)
110 if (bs[i]->hash == bs[j]->hash)
111 conflict = '+';
112 if (conflict == 'C') {
113 hash_t hi = bs[i]->hash;
114 while (!is_pass(fbook->moves[hi & fbook_hash_mask]) && fbook->hashes[hi & fbook_hash_mask] != bs[i]->hash)
115 hi++;
116 if (fbook->hashes[hi & fbook_hash_mask] == bs[i]->hash)
117 hi = 'c';
119 fprintf(stderr, "%c %"PRIhash":%"PRIhash" (<%d> %s)\n", conflict,
120 bs[i]->hash & fbook_hash_mask, bs[i]->hash, i, linebuf);
121 #endif
122 hash_t hi = bs[i]->hash;
123 while (!is_pass(fbook->moves[hi & fbook_hash_mask]) && fbook->hashes[hi & fbook_hash_mask] != bs[i]->hash)
124 hi++;
125 fbook->moves[hi & fbook_hash_mask] = coord;
126 fbook->hashes[hi & fbook_hash_mask] = bs[i]->hash;
128 coord_done(c);
131 for (int i = 0; i < 8; i++) {
132 board_done(bs[i]);
135 fclose(f);
137 return fbook;
140 void fbook_done(struct fbook *fbook)
142 free(fbook);