probdist_pick(): Debug print
[pachi.git] / pattern.h
blob83cd9080a71661596ce6be3e111e582d43d45b70
1 #ifndef ZZGO_PATTERN_H
2 #define ZZGO_PATTERN_H
4 /* Matching of multi-featured patterns. */
6 #include "board.h"
7 #include "move.h"
9 /* When someone says "pattern", you imagine a configuration of stones in given
10 * area (e.g. as matched very efficiently by pattern3 in case of 3x3 area).
11 * However, we use a richer definition of pattern, where this is merely one
12 * pattern _feature_. Another features may be is-a-selfatari, is-a-capture,
13 * number of liberties, distance from last move, etc. */
15 /* Each feature is represented by its id and an optional 32-bit payload;
16 * when matching, discrete (id,payload) pairs are considered. */
18 /* This is heavily influenced by (Coulom, 2007), of course. */
19 /* TODO: Try completely separate ko / no-ko features. */
21 /* See the HACKING file for another description of the pattern matcher and
22 * instructions on how to harvest and inspect patterns. */
24 /* If you add a payload bit for a feature, don't forget to update the value
25 * in feature_info. */
26 enum feature_id {
27 /* Implemented: */
29 /* This is a pass. */
30 /* Payload: [bit0] Last move was also pass? */
31 #define PF_PASS_LASTPASS 0
32 FEAT_PASS,
34 /* Simple capture move. */
35 /* Payload: [bit0] Capturing laddered group? */
36 #define PF_CAPTURE_LADDER 0
37 /* [bit1] Re-capturing last move? */
38 #define PF_CAPTURE_RECAPTURE 1 /* TODO */
39 /* [bit2] Enables our atari group get more libs? */
40 #define PF_CAPTURE_ATARIDEF 2
41 /* [bit3] Capturing ko? */
42 #define PF_CAPTURE_KO 3
43 FEAT_CAPTURE,
45 /* Atari escape (extension). */
46 /* Payload: [bit0] Escaping with laddered group? */
47 #define PF_AESCAPE_LADDER 0
48 FEAT_AESCAPE,
50 /* Self-atari move. */
51 /* Payload: [bit0] Also using our complex definition? */
52 #define PF_SELFATARI_SMART 0 /* TODO: Non-smart */
53 FEAT_SELFATARI,
55 /* Atari move. */
56 /* Payload: [bit0] The atari'd group gets laddered? */
57 #define PF_ATARI_LADDER 0
58 /* [bit1] Playing ko? */
59 #define PF_ATARI_KO 1
60 FEAT_ATARI,
62 /* Border distance. */
63 /* Payload: The distance - "line number". Only up to 4. */
64 FEAT_BORDER,
66 /* Last move distance. */
67 /* Payload: The distance - gridcular metric. */
68 FEAT_LDIST,
70 /* Next-to-last move distance. */
71 /* Payload: The distance - gridcular metric. */
72 FEAT_LLDIST,
74 /* Spatial configuration of stones in certain board area,
75 * with black to play. */
76 /* Payload: [bits 31-24] Pattern radius (gridcular) */
77 #define PF_SPATIAL_RADIUS 24
78 /* [other bits] Index in the spatial_dict. */
79 #define PF_SPATIAL_INDEX 0
80 FEAT_SPATIAL,
83 /* Unimplemented - TODO: */
85 /* Monte-carlo owner. */
86 /* Payload: #of playouts owning this point at the final
87 * position, scaled to 0..15 (lowest 4 bits). */
88 FEAT_MCOWNER,
90 FEAT_MAX
93 struct feature {
94 enum feature_id id;
95 uint32_t payload;
98 struct pattern {
99 /* Pattern (matched) is set of features. */
100 int n;
101 #define FEATURES 32
102 struct feature f[FEATURES];
105 struct spatial_dict;
106 struct pattern_config {
107 /* FEAT_SPATIAL: Generate patterns only for these sizes (gridcular). */
108 int spat_min, spat_max;
109 /* FEAT_BORDER: Generate features only up to this board distance. */
110 int bdist_max;
111 /* FEAT_LDIST, FEAT_LLDIST: Generate features only for these move
112 * distances. */
113 int ldist_min, ldist_max;
114 /* FEAT_MCOWNER: Generate feature after this number of simulations. */
115 int mcsims;
117 /* The spatial patterns dictionary, used by FEAT_SPATIAL. */
118 struct spatial_dict *spat_dict;
120 extern struct pattern_config DEFAULT_PATTERN_CONFIG;
122 /* The pattern_spec[] specifies which features to tests for;
123 * highest bit controls whether to test for the feature at all,
124 * then for bitmap features (except FEAT_SPATIAL) the rest
125 * of the bits controls various PF tests; for non-bitmap
126 * features, you will need to tweak the patternconfig to
127 * fine-tune them. */
128 typedef uint32_t pattern_spec[FEAT_MAX];
129 extern pattern_spec PATTERN_SPEC_MATCHALL;
132 /* Append feature to string. */
133 char *feature2str(char *str, struct feature *f);
134 /* Convert string to feature, return pointer after the featurespec. */
135 char *str2feature(char *str, struct feature *f);
137 /* Append pattern as feature spec string. */
138 char *pattern2str(char *str, struct pattern *p);
140 /* Initialize p and fill it with features matched by the
141 * given board move. */
142 void pattern_match(struct pattern_config *pc, pattern_spec ps, struct pattern *p, struct board *b, struct move *m);
145 /* Comparative strengths of all feature-payload pairs (initialized to 1 for
146 * unspecified pairs). */
147 struct features_gamma {
148 /* Indexed by feature and payload; each feature array is allocated for
149 * all possible payloads to fit in. */
150 float *gamma[FEAT_MAX];
151 struct pattern_config *pc;
154 /* Initializes gamma values, pre-loading existing records from
155 * default filename, falling back to gamma==1 for unspecified values. */
156 struct features_gamma *features_gamma_init(struct pattern_config *pc);
158 /* Look up gamma of given feature, or set one if gamma is not NULL. */
159 float feature_gamma(struct features_gamma *fg, struct feature *f, float *gamma);
162 /* Spatial pattern dictionary. */
164 /* For each encountered configuration of stones, we keep it "spelled out"
165 * in these records, index them and refer just the indices in the feature
166 * payloads. This achieves several things:
167 * * We can handle patterns of arbitrary length.
168 * * We can recognize isomorphous configurations (color reversions,
169 * rotations) within the dataset.
170 * * We can visualise patterns corresponding to chosen features.
172 * Thus, it goes like this:
174 * +----------------+ +----------------+
175 * | struct pattern | - | struct feature |
176 * +----------------+ | payload id |
177 * +----------------+
178 * | FEAT_SPATIAL
180 * | ,--<--.
181 * | | |
182 * +-----------------------------------------+
183 * | struct spatial_dict spatials[] hash[] |
184 * +-----------------------------------------+
186 * +----------------+
187 * | struct spatial |
188 * +----------------+
191 /* Maximum spatial pattern diameter. */
192 #define MAX_PATTERN_DIST 21
193 /* Maximum number of points in spatial pattern (upper bound).
194 * TODO: Better upper bound to save more data. */
195 #define MAX_PATTERN_AREA (MAX_PATTERN_DIST*MAX_PATTERN_DIST)
197 /* Record for single stone configuration. */
198 struct spatial {
199 /* Gridcular radius of matched pattern. */
200 uint16_t dist;
201 /* The points; each point is two bits, corresponding
202 * to {enum stone}. Points are ordered in gridcular-defined
203 * spiral from middle to the edge; the dictionary file has
204 * a comment describing the ordering at the top. */
205 char points[MAX_PATTERN_AREA / 4];
206 #define spatial_point_at(s, i) (((s).points[(i) / 4] >> (((i) % 4) * 2)) & 3)
209 /* Collection of stone configurations, with two ways of lookup:
210 * (i) by index (ii) by hash of the configuration. */
211 struct spatial_dict {
212 /* Indexed base store */
213 int nspatials; /* Number of records. */
214 struct spatial *spatials; /* Actual records. */
216 /* Hashed access; all isomorphous configurations
217 * are also hashed */
218 #define spatial_hash_bits 24 // ~64mib array
219 #define spatial_hash_mask ((1 << spatial_hash_bits) - 1)
220 /* Maps to spatials[] indices. The hash function
221 * used is zobrist hashing with fixed values. */
222 uint32_t hash[1 << spatial_hash_bits];
223 /* Auxiliary collision counter, for statistics. */
224 int collisions;
226 /* Backing store for appending patterns. */
227 FILE *f;
230 /* Initializes spatial dictionary, pre-loading existing records from
231 * default filename if exists. If will_append is true, it will open
232 * the file for appending. */
233 struct spatial_dict *spatial_dict_init(bool will_append);
235 /* Compute hash of given pattern, starting at specified offset. */
236 hash_t spatial_hash(int rotation, struct spatial *s, int ofs);
238 /* Lookup specified spatial pattern in the dictionary; return index
239 * of the pattern. If the pattern is not found, 0 will be returned. */
240 int spatial_dict_get(struct spatial_dict *dict, struct spatial *s, hash_t h);
242 /* Store specified spatial pattern (both in dictionary and the underlying
243 * file storage) if it is not known yet. Returns pattern id. */
244 int spatial_dict_put(struct spatial_dict *dict, struct spatial *s, hash_t);
246 #endif