foreach_neighbor(): Iterate in-line, row-row-row
[pachi/json.git] / pattern3.c
blob19c322ad665cad7acdaa2edd36e884718cfb3173
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 chunks */
27 return ((pat & 0xfc00) >> 10) | (pat & 0x03c0) | ((pat & 0x003f) << 10);
30 static int
31 pat_hmirror(hash3_t pat)
33 /* H mirror pattern; reverse order of 2-bit values within the chunks */
34 #define rev3(p) ((p >> 4) | (p & 0xc) | ((p & 0x3) << 4))
35 #define rev2(p) ((p >> 2) | ((p & 0x3) << 2))
36 return (rev3((pat & 0xfc00) >> 10) << 10)
37 | (rev2((pat & 0x03c0) >> 6) << 6)
38 | rev3((pat & 0x003f));
39 #undef rev3
40 #undef rev2
43 static int
44 pat_90rot(hash3_t pat)
46 /* Rotate by 90 degrees:
47 * 5 6 7 7 4 2
48 * 3 4 -> 6 1
49 * 0 1 2 5 3 0 */
50 /* I'm too lazy to optimize this :) */
51 int vals[8];
52 for (int i = 0; i < 8; i++)
53 vals[i] = (pat >> (i * 2)) & 0x3;
54 int vals2[8];
55 vals2[0] = vals[5]; vals2[1] = vals[3]; vals2[2] = vals[0];
56 vals2[3] = vals[6]; vals2[4] = vals[1];
57 vals2[5] = vals[7]; vals2[6] = vals[4]; vals2[7] = vals[2];
58 int p2 = 0;
59 for (int i = 0; i < 8; i++)
60 p2 |= vals2[i] << (i * 2);
61 return p2;
64 void
65 pattern3_transpose(hash3_t pat, hash3_t (*transp)[8])
67 int i = 0;
68 (*transp)[i++] = pat;
69 (*transp)[i++] = pat_vmirror(pat);
70 (*transp)[i++] = pat_hmirror(pat);
71 (*transp)[i++] = pat_vmirror(pat_hmirror(pat));
72 (*transp)[i++] = pat_90rot(pat);
73 (*transp)[i++] = pat_90rot(pat_vmirror(pat));
74 (*transp)[i++] = pat_90rot(pat_hmirror(pat));
75 (*transp)[i++] = pat_90rot(pat_vmirror(pat_hmirror(pat)));
78 static void
79 pattern_gen(struct pattern3s *p, hash3_t pat, char *src, int srclen, int fixed_color)
81 for (; srclen > 0; src++, srclen--) {
82 if (srclen == 5)
83 continue;
84 int patofs = (srclen > 5 ? srclen - 1 : srclen) - 1;
85 switch (*src) {
86 case '?':
87 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
88 *src = 'X'; pattern_gen(p, pat, src, srclen, fixed_color);
89 *src = 'O'; pattern_gen(p, pat, src, srclen, fixed_color);
90 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
91 *src = '?'; // for future recursions
92 return;
93 case 'x':
94 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
95 *src = 'O'; pattern_gen(p, pat, src, srclen, fixed_color);
96 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
97 *src = 'x'; // for future recursions
98 return;
99 case 'o':
100 *src = '.'; pattern_gen(p, pat, src, srclen, fixed_color);
101 *src = 'X'; pattern_gen(p, pat, src, srclen, fixed_color);
102 *src = '#'; pattern_gen(p, pat, src, srclen, fixed_color);
103 *src = 'o'; // for future recursions
104 return;
105 case '.': /* 0 */ break;
106 case 'X': pat |= S_BLACK << (patofs * 2); break;
107 case 'O': pat |= S_WHITE << (patofs * 2); break;
108 case '#': pat |= S_OFFBOARD << (patofs * 2); break;
112 /* Original pattern, all transpositions and rotations */
113 hash3_t transp[8];
114 pattern3_transpose(pat, &transp);
115 for (int i = 0; i < 8; i++) {
116 /* Original color assignment */
117 pattern_record(p, src - 9, transp[i], fixed_color);
118 /* Reverse color assignment */
119 if (fixed_color)
120 fixed_color = 2 - (fixed_color == 2);
121 pattern_record(p, src - 9, pattern3_reverse(transp[i]), fixed_color);
125 static void
126 patterns_gen(struct pattern3s *p, char src[][11], int src_n)
128 for (int i = 0; i < src_n; i++) {
129 //printf("<%s>\n", src[i]);
130 int fixed_color = 0;
131 switch (src[i][9]) {
132 case 'X': fixed_color = S_BLACK; break;
133 case 'O': fixed_color = S_WHITE; break;
135 //fprintf(stderr, "** %s **\n", src[i]);
136 pattern_gen(p, 0, src[i], 9, fixed_color);
140 static bool
141 patterns_load(char src[][11], int src_n, char *filename)
143 FILE *f = fopen("moggy.patterns", "r");
144 if (!f) return false;
146 int i;
147 for (i = 0; i < src_n; i++) {
148 char line[32];
149 if (!fgets(line, sizeof(line), f))
150 goto error;
151 int l = strlen(line);
152 if (l != 10 + (line[l - 1] == '\n'))
153 goto error;
154 memcpy(src[i], line, 10);
156 fprintf(stderr, "moggy.patterns: %d patterns loaded\n", i);
157 fclose(f);
158 return true;
159 error:
160 fprintf(stderr, "Error loading moggy.patterns.\n");
161 fclose(f);
162 return false;
165 void
166 pattern3s_init(struct pattern3s *p, char src[][11], int src_n)
168 char nsrc[src_n][11];
170 if (!patterns_load(nsrc, src_n, "moggy.patterns")) {
171 /* Use default pattern set. */
172 for (int i = 0; i < src_n; i++)
173 strcpy(nsrc[i], src[i]);
176 patterns_gen(p, nsrc, src_n);