forked from pasky/pachi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pattern3.h
131 lines (110 loc) · 3.74 KB
/
pattern3.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#ifndef PACHI_PATTERN3_H
#define PACHI_PATTERN3_H
/* Fast matching of simple 3x3 patterns. */
#include "board.h"
/* (Note that this is completely independent from the general pattern
* matching infrastructure in pattern.[ch]. This is fast and simple.) */
struct board;
struct move;
/* hash3_t pattern: ignore middle point, 2 bits per intersection (color)
* plus 1 bit per each direct neighbor => 8*2 + 4 bits. Bitmap point order:
* 7 6 5 b
* 4 3 a 9
* 2 1 0 8 */
/* Value bit 0: black pattern; bit 1: white pattern */
/* XXX: See <board.h> for hash3_t typedef. */
struct pattern2p {
hash3_t pattern;
unsigned char value;
};
struct pattern3s {
/* In case of a collision, following hash entries are
* used. value==0 indicates an unoccupied hash entry. */
/* The hash indices are zobrist hashes based on p3hashes. */
#define pattern3_hash_bits 19
#define pattern3_hash_size (1 << pattern3_hash_bits)
#define pattern3_hash_mask (pattern3_hash_size - 1)
struct pattern2p hash[pattern3_hash_size];
};
/* Zobrist hashes for the various 3x3 points. */
/* [point][is_atari][color] */
hash_t p3hashes[8][2][S_MAX];
/* Source pattern encoding:
* X: black; O: white; .: empty; #: edge
* x: !black; o: !white; ?: any
*
* |/=: black in atari/anything but black in atari
* @/0: white in atari
* Y/y: black notin atari; Q/q: white notin atari
*
* extra X: pattern valid only for one side;
* middle point ignored. */
void pattern3s_init(struct pattern3s *p, char src[][11], int src_n);
/* Compute pattern3 hash at local position. */
static hash3_t pattern3_hash(struct board *b, coord_t c);
/* Check if we match any 3x3 pattern centered on given move. */
static bool pattern3_move_here(struct pattern3s *p, struct board *b, struct move *m, char *idx);
/* Generate all transpositions of given pattern, stored in an
* hash3_t[8] array. */
void pattern3_transpose(hash3_t pat, hash3_t (*transp)[8]);
/* Reverse pattern to opposite color assignment. */
static hash3_t pattern3_reverse(hash3_t pat);
static inline hash3_t
pattern3_hash(struct board *b, coord_t c)
{
hash3_t pat = 0;
int x = coord_x(c, b), y = coord_y(c, b);
/* Stone info. */
pat |= (board_atxy(b, x - 1, y - 1) << 14)
| (board_atxy(b, x, y - 1) << 12)
| (board_atxy(b, x + 1, y - 1) << 10);
pat |= (board_atxy(b, x - 1, y) << 8)
| (board_atxy(b, x + 1, y) << 6);
pat |= (board_atxy(b, x - 1, y + 1) << 4)
| (board_atxy(b, x, y + 1) << 2)
| (board_atxy(b, x + 1, y + 1));
/* Atari info. */
#define atari_atxy(b, x, y) (group_atxy(b, x, y) && board_group_info(b, group_atxy(b, x, y)).libs == 1)
pat |= (atari_atxy(b, x, y - 1) << 19);
pat |= (atari_atxy(b, x - 1, y) << 18)
| (atari_atxy(b, x + 1, y) << 17);
pat |= (atari_atxy(b, x, y + 1) << 16);
#undef atari_atxy
return pat;
}
static inline __attribute__((const)) hash_t
hash3_to_hash(hash3_t pat)
{
hash_t h = 0;
static const int ataribits[8] = { -1, 0, -1, 1, 2, -1, 3, -1 };
for (int i = 0; i < 8; i++) {
h ^= p3hashes[i][ataribits[i] >= 0 ? (pat >> (16 + ataribits[i])) & 1 : 0][(pat >> (i*2)) & 3];
}
return h;
}
static inline bool
pattern3_move_here(struct pattern3s *p, struct board *b, struct move *m, char *idx)
{
#ifdef BOARD_PAT3
hash3_t pat = b->pat3[m->coord];
#else
hash3_t pat = pattern3_hash(b, m->coord);
#endif
hash_t h = hash3_to_hash(pat);
while (p->hash[h & pattern3_hash_mask].pattern != pat
&& p->hash[h & pattern3_hash_mask].value != 0)
h++;
if (p->hash[h & pattern3_hash_mask].value & m->color) {
*idx = p->hash[h & pattern3_hash_mask].value >> 2;
return true;
} else {
return false;
}
}
static inline hash3_t
pattern3_reverse(hash3_t pat)
{
/* Reverse color assignment - achieved by swapping odd and even bits */
return ((pat >> 1) & 0x5555) | ((pat & 0x5555) << 1) | (pat & 0xf0000);
}
#endif