1 #ifndef PACHI_PATTERN3_H
2 #define PACHI_PATTERN3_H
4 /* Fast matching of simple 3x3 patterns. */
8 /* (Note that this is completely independent from the general pattern
9 * matching infrastructure in pattern.[ch]. This is fast and simple.) */
14 /* hash3_t pattern: ignore middle point, 2 bits per intersection (color)
15 * plus 1 bit per each direct neighbor => 8*2 + 4 bits. Bitmap point order:
19 /* Value bit 0: black pattern; bit 1: white pattern */
21 /* XXX: See <board.h> for hash3_t typedef. */
29 /* In case of a collision, following hash entries are
30 * used. value==0 indicates an unoccupied hash entry. */
31 /* The hash indices are zobrist hashes based on p3hashes. */
32 #define pattern3_hash_bits 19
33 #define pattern3_hash_size (1 << pattern3_hash_bits)
34 #define pattern3_hash_mask (pattern3_hash_size - 1)
35 struct pattern2p hash
[pattern3_hash_size
];
38 /* Zobrist hashes for the various 3x3 points. */
39 /* [point][is_atari][color] */
40 hash_t p3hashes
[8][2][S_MAX
];
42 /* Source pattern encoding:
43 * X: black; O: white; .: empty; #: edge
44 * x: !black; o: !white; ?: any
46 * |/=: black in atari/anything but black in atari
48 * Y/y: black notin atari; Q/q: white notin atari
50 * extra X: pattern valid only for one side;
51 * middle point ignored. */
53 void pattern3s_init(struct pattern3s
*p
, char src
[][11], int src_n
);
55 /* Compute pattern3 hash at local position. */
56 static hash3_t
pattern3_hash(struct board
*b
, coord_t c
);
58 /* Check if we match any 3x3 pattern centered on given move. */
59 static bool pattern3_move_here(struct pattern3s
*p
, struct board
*b
, struct move
*m
);
61 /* Generate all transpositions of given pattern, stored in an
62 * hash3_t[8] array. */
63 void pattern3_transpose(hash3_t pat
, hash3_t (*transp
)[8]);
65 /* Reverse pattern to opposite color assignment. */
66 static hash3_t
pattern3_reverse(hash3_t pat
);
70 pattern3_hash(struct board
*b
, coord_t c
)
73 int x
= coord_x(c
, b
), y
= coord_y(c
, b
);
75 pat
|= (board_atxy(b
, x
- 1, y
- 1) << 14)
76 | (board_atxy(b
, x
, y
- 1) << 12)
77 | (board_atxy(b
, x
+ 1, y
- 1) << 10);
78 pat
|= (board_atxy(b
, x
- 1, y
) << 8)
79 | (board_atxy(b
, x
+ 1, y
) << 6);
80 pat
|= (board_atxy(b
, x
- 1, y
+ 1) << 4)
81 | (board_atxy(b
, x
, y
+ 1) << 2)
82 | (board_atxy(b
, x
+ 1, y
+ 1));
84 #define atari_atxy(b, x, y) (group_atxy(b, x, y) && board_group_info(b, group_atxy(b, x, y)).libs == 1)
85 pat
|= (atari_atxy(b
, x
, y
- 1) << 19);
86 pat
|= (atari_atxy(b
, x
- 1, y
) << 18)
87 | (atari_atxy(b
, x
+ 1, y
) << 17);
88 pat
|= (atari_atxy(b
, x
, y
+ 1) << 16);
93 static inline __attribute__((const)) hash_t
94 hash3_to_hash(hash3_t pat
)
97 static const int ataribits
[8] = { -1, 0, -1, 1, 2, -1, 3, -1 };
98 for (int i
= 0; i
< 8; i
++) {
99 h
^= p3hashes
[i
][ataribits
[i
] >= 0 ? (pat
>> (16 + ataribits
[i
])) & 1 : 0][(pat
>> (i
*2)) & 3];
105 pattern3_move_here(struct pattern3s
*p
, struct board
*b
, struct move
*m
)
108 hash3_t pat
= b
->pat3
[m
->coord
];
110 hash3_t pat
= pattern3_hash(b
, m
->coord
);
112 hash_t h
= hash3_to_hash(pat
);
113 while (p
->hash
[h
& pattern3_hash_mask
].pattern
!= pat
114 && p
->hash
[h
& pattern3_hash_mask
].value
!= 0)
116 return (p
->hash
[h
& pattern3_hash_mask
].value
& m
->color
);
119 static inline hash3_t
120 pattern3_reverse(hash3_t pat
)
122 /* Reverse color assignment - achieved by swapping odd and even bits */
123 return ((pat
>> 1) & 0x5555) | ((pat
& 0x5555) << 1) | (pat
& 0xf0000);