Pattern FEAT_BORDER: Implement
[pachi.git] / pattern.c
blob19ff1eea75c0dc3a15d0d97971bf646b02cbd532
1 #include <assert.h>
2 #include <ctype.h>
3 #include <inttypes.h>
4 #include <stdio.h>
5 #include <stdlib.h>
7 #include "board.h"
8 #include "debug.h"
9 #include "pattern.h"
10 #include "tactics.h"
13 static const char *fnames[] = {
14 [FEAT_SPATIAL] = "s",
15 [FEAT_PASS] = "pass",
16 [FEAT_CAPTURE] = "capture",
17 [FEAT_AESCAPE] = "atariescape",
18 [FEAT_SELFATARI] = "selfatari",
19 [FEAT_ATARI] = "atari",
20 [FEAT_BORDER] = "border",
21 [FEAT_LDIST] = "ldist",
22 [FEAT_LLDIST] = "lldist",
23 [FEAT_MCOWNER] = "mcowner",
26 char *
27 feature2str(char *str, struct feature *f)
29 return str + sprintf(str + strlen(str), "%s:%"PRIx64, fnames[f->id], f->payload);
32 char *
33 str2feature(char *str, struct feature *f)
35 while (isspace(*str)) str++;
37 int flen = strcspn(str, ":");
38 for (int i = 0; i < sizeof(fnames)/sizeof(fnames[0]); i++)
39 if (strlen(fnames[i]) == flen && strncmp(fnames[i], str, flen)) {
40 f->id = i;
41 goto found;
43 fprintf(stderr, "invalid featurespec: %s\n", str);
44 exit(EXIT_FAILURE);
46 found:
47 str += flen + 1;
48 f->payload = strtoull(str, &str, 10);
49 return str;
53 void
54 pattern_get(struct pattern *p, struct board *b, struct move *m)
56 p->n = 0;
57 struct feature *f = &p->f[0];
59 /* TODO: We should match pretty much all of these features
60 * incrementally. */
62 /* FEAT_SPATIAL */
63 /* TODO */
65 /* FEAT_PASS */
66 if (is_pass(m->coord)) {
67 f->id = FEAT_PASS; f->payload = 0;
68 f->payload |= (b->moves > 0 && is_pass(b->last_move.coord)) << PF_PASS_LASTPASS;
69 f++, p->n++;
72 /* FEAT_CAPTURE */
74 foreach_neighbor(b, m->coord, {
75 if (board_at(b, c) != stone_other(m->color))
76 continue;
77 group_t g = group_at(b, c);
78 if (!g || board_group_info(b, g).libs != 1)
79 continue;
81 /* Capture! */
82 f->id = FEAT_CAPTURE; f->payload = 0;
84 f->payload |= is_ladder(b, m->coord, g, true, true) << PF_CAPTURE_LADDER;
85 /* TODO: is_ladder() is too conservative in some
86 * very obvious situations, look at complete.gtp. */
88 /* TODO: PF_CAPTURE_RECAPTURE */
90 foreach_in_group(b, g) {
91 foreach_neighbor(b, c, {
92 assert(board_at(b, c) != S_NONE || c == m->coord);
93 if (board_at(b, c) != m->color)
94 continue;
95 group_t g = group_at(b, c);
96 if (!g || board_group_info(b, g).libs != 1)
97 continue;
98 /* A neighboring group of ours is in atari. */
99 f->payload |= 1 << PF_CAPTURE_ATARIDEF;
101 } foreach_in_group_end;
103 if (group_is_onestone(b, g)
104 && neighbor_count_at(b, m->coord, stone_other(m->color))
105 + neighbor_count_at(b, m->coord, S_OFFBOARD) == 4)
106 f->payload |= 1 << PF_CAPTURE_KO;
108 (f++, p->n++);
113 /* FEAT_AESCAPE */
115 foreach_neighbor(b, m->coord, {
116 if (board_at(b, c) != m->color)
117 continue;
118 group_t g = group_at(b, c);
119 if (!g || board_group_info(b, g).libs != 1)
120 continue;
122 /* In atari! */
123 f->id = FEAT_AESCAPE; f->payload = 0;
125 f->payload |= is_ladder(b, m->coord, g, true, true) << PF_AESCAPE_LADDER;
126 /* TODO: is_ladder() is too conservative in some
127 * very obvious situations, look at complete.gtp. */
129 (f++, p->n++);
134 /* FEAT_SELFATARI */
135 if (is_bad_selfatari(b, m->color, m->coord)) {
136 f->id = FEAT_SELFATARI;
137 /* TODO: Dumb selfatari detection. */
138 f->payload = 1 << PF_SELFATARI_SMART;
141 /* FEAT_ATARI */
143 foreach_neighbor(b, m->coord, {
144 if (board_at(b, c) != stone_other(m->color))
145 continue;
146 group_t g = group_at(b, c);
147 if (!g || board_group_info(b, g).libs != 2)
148 continue;
150 /* Can atari! */
151 f->id = FEAT_ATARI; f->payload = 0;
153 f->payload |= is_ladder(b, m->coord, g, true, true) << PF_ATARI_LADDER;
154 /* TODO: is_ladder() is too conservative in some
155 * very obvious situations, look at complete.gtp. */
157 if (!is_pass(b->ko.coord))
158 f->payload |= 1 << PF_CAPTURE_KO;
160 (f++, p->n++);
164 /* FEAT_BORDER */
165 int bdist = coord_edge_distance(m->coord, b);
166 if (bdist <= 4) { /* TODO: Configurable threshold. */
167 f->id = FEAT_BORDER;
168 f->payload = bdist;
169 (f++, p->n++);
172 /* FEAT_LDIST */
174 /* FEAT_LLDIST */
176 /* FEAT_MCOWNER */
179 char *
180 pattern2str(char *str, struct pattern *p)
182 strcat(str++, "(");
183 for (int i = 0; i < p->n; i++) {
184 if (i > 0) strcat(str++, " ");
185 str = feature2str(str, &p->f[i]);
187 strcat(str++, ")");
188 return str;