Split off BOARD_SPATPROB; board.spatprob is not interesting for us so far
[pachi.git] / patternprob.c
blob4d00ceeeda2af9d71ca30b8d16dc671caf0783ba
1 #define DEBUG
2 #include <assert.h>
3 #include <ctype.h>
4 #include <stdio.h>
5 #include <stdlib.h>
7 #include "board.h"
8 #include "debug.h"
9 #include "pattern.h"
10 #include "patternsp.h"
11 #include "patternprob.h"
14 /* We try to avoid needlessly reloading probability dictionary
15 * since it may take rather long time. */
16 static struct pattern_pdict *cached_dict;
18 struct pattern_pdict *
19 pattern_pdict_init(char *filename, struct pattern_config *pc)
21 if (cached_dict) {
22 cached_dict->pc = pc;
23 return cached_dict;
26 if (!filename)
27 filename = "patterns.prob";
28 FILE *f = fopen(filename, "r");
29 if (!f) {
30 if (DEBUGL(1))
31 fprintf(stderr, "No pattern probtable, will not use learned patterns.\n");
32 return NULL;
35 struct pattern_pdict *dict = calloc2(1, sizeof(*dict));
36 dict->pc = pc;
37 dict->table = calloc2(pc->spat_dict->nspatials + 1, sizeof(*dict->table));
39 char *sphcachehit = calloc2(pc->spat_dict->nspatials, 1);
40 hash_t (*sphcache)[PTH__ROTATIONS] = malloc(pc->spat_dict->nspatials * sizeof(sphcache[0]));
42 int i = 0;
43 char sbuf[1024];
44 while (fgets(sbuf, sizeof(sbuf), f)) {
45 struct pattern_prob *pb = calloc2(1, sizeof(*pb));
46 int c, o;
48 char *buf = sbuf;
49 if (buf[0] == '#') continue;
50 while (isspace(*buf)) buf++;
51 while (!isspace(*buf)) buf++; // we recompute the probability
52 while (isspace(*buf)) buf++;
53 c = strtol(buf, &buf, 10);
54 while (isspace(*buf)) buf++;
55 o = strtol(buf, &buf, 10);
56 pb->prob = (floating_t) c / o;
57 while (isspace(*buf)) buf++;
58 str2pattern(buf, &pb->p);
60 uint32_t spi = pattern2spatial(dict, &pb->p);
61 pb->next = dict->table[spi];
62 dict->table[spi] = pb;
64 /* Some spatials may not have been loaded if they correspond
65 * to a radius larger than supported. */
66 if (pc->spat_dict->spatials[spi].dist > 0) {
67 /* We rehash spatials in the order of loaded patterns. This way
68 * we make sure that the most popular patterns will be hashed
69 * last and therefore take priority. */
70 if (!sphcachehit[spi]) {
71 sphcachehit[spi] = 1;
72 for (unsigned int r = 0; r < PTH__ROTATIONS; r++)
73 sphcache[spi][r] = spatial_hash(r, &pc->spat_dict->spatials[spi]);
75 for (unsigned int r = 0; r < PTH__ROTATIONS; r++)
76 spatial_dict_addh(pc->spat_dict, sphcache[spi][r], spi);
79 i++;
82 free(sphcache);
83 free(sphcachehit);
84 if (DEBUGL(3))
85 spatial_dict_hashstats(pc->spat_dict);
87 fclose(f);
88 if (DEBUGL(1))
89 fprintf(stderr, "Loaded %d pattern-probability pairs.\n", i);
90 cached_dict = dict;
91 return dict;
94 floating_t
95 pattern_rate_some_moves(struct pattern_setup *pat,
96 struct board *b, enum stone color,
97 coord_t *coords, int coord_n,
98 struct pattern *pats, floating_t *probs)
100 floating_t total = 0;
101 for (int f = 0; f < coord_n; f++) {
102 probs[f] = NAN;
104 struct move mo = { .coord = coords[f], .color = color };
105 if (is_pass(mo.coord))
106 continue;
107 if (!board_is_valid_move(b, &mo))
108 continue;
110 if (!pats) {
111 #ifdef BOARD_SPATPROB
112 probs[f] = b->spatprob[coords[f]][color - 1];
113 #endif
114 if (isnan(probs[f])) {
115 struct pattern tmppat;
116 pattern_match(&pat->pc, pat->ps, &tmppat, b, &mo);
117 probs[f] = pattern_prob(pat->pd, &tmppat);
118 #ifdef BOARD_SPATPROB
119 b->spatprob[coords[f]][color - 1] = probs[f];
120 #endif
122 } else {
123 pattern_match(&pat->pc, pat->ps, &pats[f], b, &mo);
124 probs[f] = pattern_prob(pat->pd, &pats[f]);
127 if (!isnan(probs[f]))
128 total += probs[f];
130 return total;
133 floating_t
134 pattern_rate_moves(struct pattern_setup *pat,
135 struct board *b, enum stone color,
136 struct pattern *pats, floating_t *probs)
138 return pattern_rate_some_moves(pat, b, color, b->f, b->flen, pats, probs);