13 coord_transform(struct board
*b
, coord_t coord
, int i
)
15 #define HASH_VMIRROR 1
16 #define HASH_HMIRROR 2
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
));
32 fbook_init(char *filename
, struct board
*b
)
34 FILE *f
= fopen(filename
, "r");
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
;
47 fprintf(stderr
, "Loading opening fbook %s...\n", filename
);
49 /* Scratch board where we lay out the sequence;
50 * one for each transposition. */
52 for (int i
= 0; i
< 8; i
++) {
53 bs
[i
] = board_init(NULL
);
54 board_resize(bs
[i
], fbook
->bsize
- 2);
58 while (fgets(linebuf
, sizeof(linebuf
), f
)) {
60 linebuf
[strlen(linebuf
) - 1] = 0; // chop
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)
70 while (isspace(*line
)) line
++;
72 for (int i
= 0; i
< 8; 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
);
88 while (!isspace(*line
)) line
++;
89 while (isspace(*line
)) 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
);
107 char conflict
= is_pass(fbook
->moves
[bs
[i
]->hash
& fbook_hash_mask
]) ? '+' : 'C';
109 for (int j
= 0; j
< i
; j
++)
110 if (bs
[i
]->hash
== bs
[j
]->hash
)
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
)
116 if (fbook
->hashes
[hi
& fbook_hash_mask
] == bs
[i
]->hash
)
119 fprintf(stderr
, "%c %"PRIhash
":%"PRIhash
" (<%d> %s)\n", conflict
,
120 bs
[i
]->hash
& fbook_hash_mask
, bs
[i
]->hash
, i
, linebuf
);
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
)
125 fbook
->moves
[hi
& fbook_hash_mask
] = coord
;
126 fbook
->hashes
[hi
& fbook_hash_mask
] = bs
[i
]->hash
;
131 for (int i
= 0; i
< 8; i
++) {
140 void fbook_done(struct fbook
*fbook
)