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);
28 /* V mirror pattern; reverse order of 3-2-3 chunks */
29 return ((pat
& 0xfc00) >> 10) | (pat
& 0x03c0) | ((pat
& 0x003f) << 10);
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));
48 /* Rotate by 90 degrees:
52 /* I'm too lazy to optimize this :) */
54 for (int i
= 0; i
< 8; i
++)
55 vals
[i
] = (pat
>> (i
* 2)) & 0x3;
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];
61 for (int i
= 0; i
< 8; i
++)
62 p2
|= vals2
[i
] << (i
* 2);
67 pattern_gen(struct pattern3s
*p
, int pat
, char *src
, int srclen
, int fixed_color
)
69 for (; srclen
> 0; src
++, srclen
--) {
72 int patofs
= (srclen
> 5 ? srclen
- 1 : srclen
) - 1;
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
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
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
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
);
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]);
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
);
127 patterns_load(char src
[][11], int src_n
, char *filename
)
129 FILE *f
= fopen("moggy.patterns", "r");
130 if (!f
) return false;
133 for (i
= 0; i
< src_n
; i
++) {
135 if (!fgets(line
, sizeof(line
), f
))
137 int l
= strlen(line
);
138 if (l
!= 10 + (line
[l
- 1] == '\n'))
140 memcpy(src
[i
], line
, 10);
142 fprintf(stderr
, "moggy.patterns: %d patterns loaded\n", i
);
146 fprintf(stderr
, "Error loading moggy.patterns.\n");
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
170 test_pattern3_here(struct pattern3s
*p
, struct board
*b
, struct move
*m
)
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
);