3x3 patterns: Include atari information for direct neighbors
[pachi/derm.git] / pattern3.c
blobcf68fd0fa626c114c0bb40e2371854d24867c660
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"
11 static void
12 pattern_record(struct pattern3s *p, char *str, hash3_t pat, int fixed_color)
14 hash3_t hpat = pat;
15 while (p->hash[hpat & pattern3_hash_mask].pattern != pat
16 && p->hash[hpat & pattern3_hash_mask].value != 0)
17 hpat++;
18 p->hash[hpat & pattern3_hash_mask].pattern = pat;
19 p->hash[hpat & pattern3_hash_mask].value = fixed_color ? fixed_color : 3;
20 //fprintf(stderr, "[%s] %04x %d\n", str, pat, fixed_color);
23 static int
24 pat_vmirror(hash3_t pat)
26 /* V mirror pattern; reverse order of 3-2-3 color chunks and
27 * 1-2-1 atari chunks */
28 return ((pat & 0xfc00) >> 10) | (pat & 0x03c0) | ((pat & 0x003f) << 10)
29 | ((pat & 0x80000) >> 3) | (pat & 0x60000) | ((pat & 0x10000) << 3);
32 static int
33 pat_hmirror(hash3_t pat)
35 /* H mirror pattern; reverse order of 2-bit values within the chunks,
36 * and the 2-bit middle atari chunk. */
37 #define rev3(p) ((p >> 4) | (p & 0xc) | ((p & 0x3) << 4))
38 #define rev2(p) ((p >> 2) | ((p & 0x3) << 2))
39 return (rev3((pat & 0xfc00) >> 10) << 10)
40 | (rev2((pat & 0x03c0) >> 6) << 6)
41 | rev3((pat & 0x003f))
42 | ((pat & 0x20000) << 1)
43 | ((pat & 0x40000) >> 1)
44 | (pat & 0x90000);
45 #undef rev3
46 #undef rev2
49 static int
50 pat_90rot(hash3_t pat)
52 /* Rotate by 90 degrees:
53 * 5 6 7 3 7 4 2 2
54 * 3 4 1 2 -> 6 1 -> 3 0
55 * 0 1 2 0 5 3 0 1 */
56 /* I'm too lazy to optimize this :) */
58 int p2 = 0;
60 /* Stone info */
61 int vals[8];
62 for (int i = 0; i < 8; i++)
63 vals[i] = (pat >> (i * 2)) & 0x3;
64 int vals2[8];
65 vals2[0] = vals[5]; vals2[1] = vals[3]; vals2[2] = vals[0];
66 vals2[3] = vals[6]; vals2[4] = vals[1];
67 vals2[5] = vals[7]; vals2[6] = vals[4]; vals2[7] = vals[2];
68 for (int i = 0; i < 8; i++)
69 p2 |= vals2[i] << (i * 2);
71 /* Atari info */
72 int avals[4];
73 for (int i = 0; i < 4; i++)
74 vals[i] = (pat >> (16 + i)) & 0x1;
75 int avals2[4];
76 avals2[3] = avals[2];
77 avals2[1] = avals[3]; avals2[2] = avals[0];
78 avals2[0] = avals[1];
79 for (int i = 0; i < 4; i++)
80 p2 |= avals2[i] << (16 + i);
82 return p2;
85 void
86 pattern3_transpose(hash3_t pat, hash3_t (*transp)[8])
88 int i = 0;
89 (*transp)[i++] = pat;
90 (*transp)[i++] = pat_vmirror(pat);
91 (*transp)[i++] = pat_hmirror(pat);
92 (*transp)[i++] = pat_vmirror(pat_hmirror(pat));
93 (*transp)[i++] = pat_90rot(pat);
94 (*transp)[i++] = pat_90rot(pat_vmirror(pat));
95 (*transp)[i++] = pat_90rot(pat_hmirror(pat));
96 (*transp)[i++] = pat_90rot(pat_vmirror(pat_hmirror(pat)));
99 static void
100 pattern_gen(struct pattern3s *p, hash3_t pat, char *src, int srclen, int fixed_color)
102 for (; srclen > 0; src++, srclen--) {
103 if (srclen == 5)
104 continue;
105 static const int ataribits[] = { -1, 0, -1, 1, 2, -1, 3, -1 };
106 int patofs = (srclen > 5 ? srclen - 1 : srclen) - 1;
107 switch (*src) {
108 /* Wildcards. */
109 case '?':
110 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
111 *src = 'X'; pattern_gen(p, pat, src, srclen, fixed_color);
112 *src = 'O'; pattern_gen(p, pat, src, srclen, fixed_color);
113 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
114 *src = '?'; // for future recursions
115 return;
116 case 'x':
117 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
118 *src = 'O'; pattern_gen(p, pat, src, srclen, fixed_color);
119 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
120 *src = 'x'; // for future recursions
121 return;
122 case 'o':
123 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
124 *src = 'X'; pattern_gen(p, pat, src, srclen, fixed_color);
125 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
126 *src = 'o'; // for future recursions
127 return;
129 case 'X':
130 *src = 'Y'; pattern_gen(p, pat, src, srclen, fixed_color);
131 if (ataribits[patofs] >= 0)
132 *src = '|'; pattern_gen(p, pat, src, srclen, fixed_color);
133 *src = 'X'; // for future recursions
134 return;
135 case 'O':
136 *src = 'Q'; pattern_gen(p, pat, src, srclen, fixed_color);
137 if (ataribits[patofs] >= 0)
138 *src = '@'; pattern_gen(p, pat, src, srclen, fixed_color);
139 *src = 'O'; // for future recursions
140 return;
142 case 'y':
143 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
144 *src = '|'; pattern_gen(p, pat, src, srclen, fixed_color);
145 *src = 'O'; pattern_gen(p, pat, src, srclen, fixed_color);
146 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
147 *src = 'y'; // for future recursions
148 return;
149 case 'q':
150 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
151 *src = '@'; pattern_gen(p, pat, src, srclen, fixed_color);
152 *src = 'X'; pattern_gen(p, pat, src, srclen, fixed_color);
153 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
154 *src = 'q'; // for future recursions
155 return;
157 case '=':
158 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
159 *src = 'Y'; pattern_gen(p, pat, src, srclen, fixed_color);
160 *src = 'O'; pattern_gen(p, pat, src, srclen, fixed_color);
161 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
162 *src = '='; // for future recursions
163 return;
164 case '0':
165 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
166 *src = 'Q'; pattern_gen(p, pat, src, srclen, fixed_color);
167 *src = 'X'; pattern_gen(p, pat, src, srclen, fixed_color);
168 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
169 *src = '0'; // for future recursions
170 return;
172 /* Atoms. */
173 case '.': /* 0 */ break;
174 case 'Y': pat |= S_BLACK << (patofs * 2); break;
175 case 'Q': pat |= S_WHITE << (patofs * 2); break;
176 case '|': assert(ataribits[patofs] >= 0);
177 pat |= (S_BLACK << (patofs * 2)) | (1 << (16 + ataribits[patofs]));
178 break;
179 case '@': assert(ataribits[patofs] >= 0);
180 pat |= (S_WHITE << (patofs * 2)) | (1 << (16 + ataribits[patofs]));
181 break;
182 case '#': pat |= S_OFFBOARD << (patofs * 2); break;
186 /* Original pattern, all transpositions and rotations */
187 hash3_t transp[8];
188 pattern3_transpose(pat, &transp);
189 for (int i = 0; i < 8; i++) {
190 /* Original color assignment */
191 pattern_record(p, src - 9, transp[i], fixed_color);
192 /* Reverse color assignment */
193 if (fixed_color)
194 fixed_color = 2 - (fixed_color == 2);
195 pattern_record(p, src - 9, pattern3_reverse(transp[i]), fixed_color);
199 static void
200 patterns_gen(struct pattern3s *p, char src[][11], int src_n)
202 for (int i = 0; i < src_n; i++) {
203 //printf("<%s>\n", src[i]);
204 int fixed_color = 0;
205 switch (src[i][9]) {
206 case 'X': fixed_color = S_BLACK; break;
207 case 'O': fixed_color = S_WHITE; break;
209 //fprintf(stderr, "** %s **\n", src[i]);
210 pattern_gen(p, 0, src[i], 9, fixed_color);
214 static bool
215 patterns_load(char src[][11], int src_n, char *filename)
217 FILE *f = fopen("moggy.patterns", "r");
218 if (!f) return false;
220 int i;
221 for (i = 0; i < src_n; i++) {
222 char line[32];
223 if (!fgets(line, sizeof(line), f))
224 goto error;
225 int l = strlen(line);
226 if (l != 10 + (line[l - 1] == '\n'))
227 goto error;
228 memcpy(src[i], line, 10);
230 fprintf(stderr, "moggy.patterns: %d patterns loaded\n", i);
231 fclose(f);
232 return true;
233 error:
234 fprintf(stderr, "Error loading moggy.patterns.\n");
235 fclose(f);
236 return false;
239 void
240 pattern3s_init(struct pattern3s *p, char src[][11], int src_n)
242 char nsrc[src_n][11];
244 if (!patterns_load(nsrc, src_n, "moggy.patterns")) {
245 /* Use default pattern set. */
246 for (int i = 0; i < src_n; i++)
247 strcpy(nsrc[i], src[i]);
250 patterns_gen(p, nsrc, src_n);