From 022d19e51026c387f7e0176766ca6747c1669dca Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Sat, 23 Jan 2010 00:55:13 +0100 Subject: [PATCH] Pattern FEAT_PATTERN3: Introduce, use by default inst. of FEAT_SPATIAL in matchfast --- pattern.c | 35 +++++++++++++++++++++++++++++++++-- pattern.h | 12 +++++++++++- patternscan/patternscan.c | 21 +++++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/pattern.c b/pattern.c index 69de61c..d947fda 100644 --- a/pattern.c +++ b/pattern.c @@ -9,6 +9,7 @@ #include "debug.h" #include "pattern.h" #include "patternsp.h" +#include "pattern3.h" #include "tactics.h" @@ -37,6 +38,7 @@ pattern_spec PATTERN_SPEC_MATCHALL = { [FEAT_LLDIST] = ~0, [FEAT_CONTIGUITY] = 0, [FEAT_SPATIAL] = ~0, + [FEAT_PATTERN3] = 0, [FEAT_MCOWNER] = ~0, }; @@ -51,8 +53,9 @@ pattern_spec PATTERN_SPEC_MATCHFAST = { [FEAT_LDIST] = 0, [FEAT_LLDIST] = 0, [FEAT_CONTIGUITY] = ~0, - [FEAT_SPATIAL] = ~0, - [FEAT_MCOWNER] = ~0, + [FEAT_SPATIAL] = 0, + [FEAT_PATTERN3] = ~0, + [FEAT_MCOWNER] = 0, }; static const struct feature_info { @@ -69,6 +72,7 @@ static const struct feature_info { [FEAT_LLDIST] = { .name = "lldist", .payloads = -1 }, [FEAT_CONTIGUITY] = { .name = "cont", .payloads = 2 }, [FEAT_SPATIAL] = { .name = "s", .payloads = -1 }, + [FEAT_PATTERN3] = { .name = "p", .payloads = 2<<16 }, [FEAT_MCOWNER] = { .name = "mcowner", .payloads = 16 }, }; @@ -431,6 +435,21 @@ pattern_match(struct pattern_config *pc, pattern_spec ps, f = pattern_match_spatial(pc, ps, p, f, b, m); } + if (PS_ANY(PATTERN3) && !is_pass(m->coord)) { +#ifdef BOARD_PAT3 + int pat = b->pat3[m->coord]; +#else + int pat = pattern3_hash(b, m->coord); +#endif + if (m->color == S_WHITE) { + /* We work with the pattern3s as black-to-play. */ + pat = pattern3_reverse(pat); + } + f->id = FEAT_PATTERN3; + f->payload = pat; + (f++, p->n++); + } + /* FEAT_MCOWNER: TODO */ assert(!pc->mcsims); } @@ -463,7 +482,19 @@ features_gamma_load(struct features_gamma *fg, const char *filename) bufp = str2feature(bufp, &f); while (isspace(*bufp)) bufp++; float gamma = strtof(bufp, &bufp); + /* Record feature's gamma. */ feature_gamma(fg, &f, &gamma); + /* In case of 3x3 patterns, record gamma also + * for all rotations and transpositions. */ + if (f.id == FEAT_PATTERN3) { + int transp[8]; + pattern3_transpose(f.payload, &transp); + for (int i = 1; i < 8; i++) { + f.payload = transp[i]; + feature_gamma(fg, &f, &gamma); + } + f.payload = transp[0]; + } } fclose(f); } diff --git a/pattern.h b/pattern.h index 585dc2b..7ad2d4d 100644 --- a/pattern.h +++ b/pattern.h @@ -78,9 +78,19 @@ enum feature_id { /* Spatial configuration of stones in certain board area, * with black to play. */ - /* Payload: [other bits] Index in the spatial_dict. */ + /* Payload: Index in the spatial_dict. */ FEAT_SPATIAL, + /* Spatial configuration of stones in fixed 3x3 square, + * with black to play. */ + /* This is a fast substitution to spatial. */ + /* Payload: Pattern3 hash (see pattern3.h). */ + /* Note that the hash describes only one particular rotation; + * no normalization across rotations and transpositions is done + * during the matching, only color normalization. The patternscan + * and gamma machineries is taking care of the rotations. */ + FEAT_PATTERN3, + /* Unimplemented - TODO: */ diff --git a/patternscan/patternscan.c b/patternscan/patternscan.c index bf3607f..832bbba 100644 --- a/patternscan/patternscan.c +++ b/patternscan/patternscan.c @@ -31,6 +31,7 @@ struct patternscan { /* Book-keeping of spatial occurence count. */ int nscounts; int *scounts; + /* TODO: The same for PATTERN3 occurences. */ }; @@ -112,6 +113,25 @@ mm_pattern(struct patternscan *ps, char *str, struct pattern *p) } +/* FEAT_PATTERN3-matched patterns do not account for rotations + * and transpositions, but we shold emit only pattern hashes + * in "canonical" form that is the same no matter the rotation. + * To achieve this, we use a trick - the canonical form is the + * one recorded in the spatial dictionary! The dictionary is + * already closed on rotation and transposition. */ +void +pattern_p3_normalize(struct patternscan *ps, struct pattern *p) +{ + for (int i = 0; i < p->n; i++) { + if (p->f[i].id != FEAT_PATTERN3) + continue; + /* Normalize the pattern hash across rotation and + * transposition space. */ + p->f[i].payload = pattern3_by_spatial(ps->pc.spat_dict, p->f[i].payload); + } +} + + static void process_pattern(struct patternscan *ps, struct board *b, struct move *m, char **str) { @@ -141,6 +161,7 @@ process_pattern(struct patternscan *ps, struct board *b, struct move *m, char ** if (!ps->no_pattern_match) { struct pattern p; pattern_match(&ps->pc, ps->ps, &p, b, m); + pattern_p3_normalize(ps, &p); *str = ps->mm ? mm_pattern(ps, *str, &p) : pattern2str(*str, &p); } } -- 2.11.4.GIT