Decrement node_sizes when freeing a node.
[pachi.git] / pattern3.c
blobab2f873386e05ad812ec67872a1c9b6bae0ce36d
1 #include <assert.h>
2 #include <math.h>
3 #include <stdio.h>
4 #include <stdlib.h>
6 #include "board.h"
7 #include "debug.h"
8 #include "pattern3.h"
9 #include "tactics.h"
12 static void
13 pattern_record(char *table, char *str, int pat, int fixed_color)
15 /* Original color assignment */
16 table[pat] = fixed_color ? fixed_color : 3;
17 //fprintf(stderr, "[%s] %04x %d\n", str, pat, fixed_color);
19 /* Reverse color assignment - achieved by swapping odd and even bits */
20 pat = ((pat >> 1) & 0x5555) | ((pat & 0x5555) << 1);
21 table[pat] = fixed_color ? 2 - (fixed_color == 2) : 3;
22 //fprintf(stderr, "[%s] %04x %d\n", str, pat, fixed_color);
25 static int
26 pat_vmirror(int pat)
28 /* V mirror pattern; reverse order of 3-2-3 chunks */
29 return ((pat & 0xfc00) >> 10) | (pat & 0x03c0) | ((pat & 0x003f) << 10);
32 static int
33 pat_hmirror(int pat)
35 /* H mirror pattern; reverse order of 2-bit values within the chunks */
36 #define rev3(p) ((p >> 4) | (p & 0xc) | ((p & 0x3) << 4))
37 #define rev2(p) ((p >> 2) | ((p & 0x3) << 2))
38 return (rev3((pat & 0xfc00) >> 10) << 10)
39 | (rev2((pat & 0x03c0) >> 6) << 6)
40 | rev3((pat & 0x003f));
41 #undef rev3
42 #undef rev2
45 static int
46 pat_90rot(int pat)
48 /* Rotate by 90 degrees:
49 * 5 6 7 7 4 2
50 * 3 4 -> 6 1
51 * 0 1 2 5 3 0 */
52 /* I'm too lazy to optimize this :) */
53 int vals[8];
54 for (int i = 0; i < 8; i++)
55 vals[i] = (pat >> (i * 2)) & 0x3;
56 int vals2[8];
57 vals2[0] = vals[5]; vals2[1] = vals[3]; vals2[2] = vals[0];
58 vals2[3] = vals[6]; vals2[4] = vals[1];
59 vals2[5] = vals[7]; vals2[6] = vals[4]; vals2[7] = vals[2];
60 int p2 = 0;
61 for (int i = 0; i < 8; i++)
62 p2 |= vals2[i] << (i * 2);
63 return p2;
66 static void
67 pattern_gen(struct pattern3s *p, int pat, char *src, int srclen, int fixed_color)
69 for (; srclen > 0; src++, srclen--) {
70 if (srclen == 5)
71 continue;
72 int patofs = (srclen > 5 ? srclen - 1 : srclen) - 1;
73 switch (*src) {
74 case '?':
75 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
76 *src = 'X'; pattern_gen(p, pat, src, srclen, fixed_color);
77 *src = 'O'; pattern_gen(p, pat, src, srclen, fixed_color);
78 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
79 *src = '?'; // for future recursions
80 return;
81 case 'x':
82 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
83 *src = 'O'; pattern_gen(p, pat, src, srclen, fixed_color);
84 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
85 *src = 'x'; // for future recursions
86 return;
87 case 'o':
88 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
89 *src = 'X'; pattern_gen(p, pat, src, srclen, fixed_color);
90 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
91 *src = 'o'; // for future recursions
92 return;
93 case '.': /* 0 */ break;
94 case 'X': pat |= S_BLACK << (patofs * 2); break;
95 case 'O': pat |= S_WHITE << (patofs * 2); break;
96 case '#': pat |= S_OFFBOARD << (patofs * 2); break;
100 /* Original pattern, all transpositions and rotations */
101 pattern_record(p->hash, src - 9, pat, fixed_color);
102 pattern_record(p->hash, src - 9, pat_vmirror(pat), fixed_color);
103 pattern_record(p->hash, src - 9, pat_hmirror(pat), fixed_color);
104 pattern_record(p->hash, src - 9, pat_vmirror(pat_hmirror(pat)), fixed_color);
105 pattern_record(p->hash, src - 9, pat_90rot(pat), fixed_color);
106 pattern_record(p->hash, src - 9, pat_90rot(pat_vmirror(pat)), fixed_color);
107 pattern_record(p->hash, src - 9, pat_90rot(pat_hmirror(pat)), fixed_color);
108 pattern_record(p->hash, src - 9, pat_90rot(pat_vmirror(pat_hmirror(pat))), fixed_color);
111 static void
112 patterns_gen(struct pattern3s *p, char src[][11], int src_n)
114 for (int i = 0; i < src_n; i++) {
115 //printf("<%s>\n", src[i]);
116 int fixed_color = 0;
117 switch (src[i][9]) {
118 case 'X': fixed_color = S_BLACK; break;
119 case 'O': fixed_color = S_WHITE; break;
121 //fprintf(stderr, "** %s **\n", src[i]);
122 pattern_gen(p, 0, src[i], 9, fixed_color);
126 static bool
127 patterns_load(char src[][11], int src_n, char *filename)
129 FILE *f = fopen("moggy.patterns", "r");
130 if (!f) return false;
132 int i;
133 for (i = 0; i < src_n; i++) {
134 char line[32];
135 if (!fgets(line, sizeof(line), f))
136 goto error;
137 int l = strlen(line);
138 if (l != 10 + (line[l - 1] == '\n'))
139 goto error;
140 memcpy(src[i], line, 10);
142 fprintf(stderr, "moggy.patterns: %d patterns loaded\n", i);
143 fclose(f);
144 return true;
145 error:
146 fprintf(stderr, "Error loading moggy.patterns.\n");
147 fclose(f);
148 return false;
151 void
152 pattern3s_init(struct pattern3s *p, char src[][11], int src_n)
154 char nsrc[src_n][11];
156 if (!patterns_load(nsrc, src_n, "moggy.patterns")) {
157 /* Use default pattern set. */
158 for (int i = 0; i < src_n; i++)
159 strcpy(nsrc[i], src[i]);
162 patterns_gen(p, nsrc, src_n);
166 /* Check if we match any pattern centered on given move. */
167 /* TODO: Make use of the incremental spatial matching infrastructure
168 * in board.h? */
169 bool
170 test_pattern3_here(struct pattern3s *p, struct board *b, struct move *m)
172 int pat = 0;
173 int x = coord_x(m->coord, b), y = coord_y(m->coord, b);
174 pat |= (board_atxy(b, x - 1, y - 1) << 14)
175 | (board_atxy(b, x, y - 1) << 12)
176 | (board_atxy(b, x + 1, y - 1) << 10);
177 pat |= (board_atxy(b, x - 1, y) << 8)
178 | (board_atxy(b, x + 1, y) << 6);
179 pat |= (board_atxy(b, x - 1, y + 1) << 4)
180 | (board_atxy(b, x, y + 1) << 2)
181 | (board_atxy(b, x + 1, y + 1));
182 //fprintf(stderr, "(%d,%d) hashtable[%04x] = %d\n", x, y, pat, p->hash[pat]);
183 return (p->hash[pat] & m->color) && !is_bad_selfatari(b, m->color, m->coord);