My Project
board.c
Go to the documentation of this file.
1
19#include "board.h"
20
21#include "bit.h"
22#include "hash.h"
23#include "move.h"
24#include "settings.h"
25#include "util.h"
26
27#include <ctype.h>
28#include <stdlib.h>
29#include <assert.h>
30
31
32#if MOVE_GENERATOR == MOVE_GENERATOR_CARRY
33 #ifdef HAS_CPU_64
34 #include "flip_carry_64.c"
36 #else
37 #include "flip_carry_32.c"
39 #endif
40#elif MOVE_GENERATOR == MOVE_GENERATOR_SSE
41 #include "flip_sse.c"
43#elif MOVE_GENERATOR == MOVE_GENERATOR_BITSCAN
44 #include "flip_bitscan.c"
46#elif MOVE_GENERATOR == MOVE_GENERATOR_ROXANE
47 #include "flip_roxane.c"
49#else // MOVE_GENERATOR == MOVE_GENERATOR_KINDERGARTEN
50 #include "flip_kindergarten.c"
52#endif
53
54
56static unsigned char edge_stability[256][256];
57
59static const unsigned long long A1_A8[256] = {
60 0x0000000000000000ULL, 0x0000000000000001ULL, 0x0000000000000100ULL, 0x0000000000000101ULL, 0x0000000000010000ULL, 0x0000000000010001ULL, 0x0000000000010100ULL, 0x0000000000010101ULL,
61 0x0000000001000000ULL, 0x0000000001000001ULL, 0x0000000001000100ULL, 0x0000000001000101ULL, 0x0000000001010000ULL, 0x0000000001010001ULL, 0x0000000001010100ULL, 0x0000000001010101ULL,
62 0x0000000100000000ULL, 0x0000000100000001ULL, 0x0000000100000100ULL, 0x0000000100000101ULL, 0x0000000100010000ULL, 0x0000000100010001ULL, 0x0000000100010100ULL, 0x0000000100010101ULL,
63 0x0000000101000000ULL, 0x0000000101000001ULL, 0x0000000101000100ULL, 0x0000000101000101ULL, 0x0000000101010000ULL, 0x0000000101010001ULL, 0x0000000101010100ULL, 0x0000000101010101ULL,
64 0x0000010000000000ULL, 0x0000010000000001ULL, 0x0000010000000100ULL, 0x0000010000000101ULL, 0x0000010000010000ULL, 0x0000010000010001ULL, 0x0000010000010100ULL, 0x0000010000010101ULL,
65 0x0000010001000000ULL, 0x0000010001000001ULL, 0x0000010001000100ULL, 0x0000010001000101ULL, 0x0000010001010000ULL, 0x0000010001010001ULL, 0x0000010001010100ULL, 0x0000010001010101ULL,
66 0x0000010100000000ULL, 0x0000010100000001ULL, 0x0000010100000100ULL, 0x0000010100000101ULL, 0x0000010100010000ULL, 0x0000010100010001ULL, 0x0000010100010100ULL, 0x0000010100010101ULL,
67 0x0000010101000000ULL, 0x0000010101000001ULL, 0x0000010101000100ULL, 0x0000010101000101ULL, 0x0000010101010000ULL, 0x0000010101010001ULL, 0x0000010101010100ULL, 0x0000010101010101ULL,
68 0x0001000000000000ULL, 0x0001000000000001ULL, 0x0001000000000100ULL, 0x0001000000000101ULL, 0x0001000000010000ULL, 0x0001000000010001ULL, 0x0001000000010100ULL, 0x0001000000010101ULL,
69 0x0001000001000000ULL, 0x0001000001000001ULL, 0x0001000001000100ULL, 0x0001000001000101ULL, 0x0001000001010000ULL, 0x0001000001010001ULL, 0x0001000001010100ULL, 0x0001000001010101ULL,
70 0x0001000100000000ULL, 0x0001000100000001ULL, 0x0001000100000100ULL, 0x0001000100000101ULL, 0x0001000100010000ULL, 0x0001000100010001ULL, 0x0001000100010100ULL, 0x0001000100010101ULL,
71 0x0001000101000000ULL, 0x0001000101000001ULL, 0x0001000101000100ULL, 0x0001000101000101ULL, 0x0001000101010000ULL, 0x0001000101010001ULL, 0x0001000101010100ULL, 0x0001000101010101ULL,
72 0x0001010000000000ULL, 0x0001010000000001ULL, 0x0001010000000100ULL, 0x0001010000000101ULL, 0x0001010000010000ULL, 0x0001010000010001ULL, 0x0001010000010100ULL, 0x0001010000010101ULL,
73 0x0001010001000000ULL, 0x0001010001000001ULL, 0x0001010001000100ULL, 0x0001010001000101ULL, 0x0001010001010000ULL, 0x0001010001010001ULL, 0x0001010001010100ULL, 0x0001010001010101ULL,
74 0x0001010100000000ULL, 0x0001010100000001ULL, 0x0001010100000100ULL, 0x0001010100000101ULL, 0x0001010100010000ULL, 0x0001010100010001ULL, 0x0001010100010100ULL, 0x0001010100010101ULL,
75 0x0001010101000000ULL, 0x0001010101000001ULL, 0x0001010101000100ULL, 0x0001010101000101ULL, 0x0001010101010000ULL, 0x0001010101010001ULL, 0x0001010101010100ULL, 0x0001010101010101ULL,
76 0x0100000000000000ULL, 0x0100000000000001ULL, 0x0100000000000100ULL, 0x0100000000000101ULL, 0x0100000000010000ULL, 0x0100000000010001ULL, 0x0100000000010100ULL, 0x0100000000010101ULL,
77 0x0100000001000000ULL, 0x0100000001000001ULL, 0x0100000001000100ULL, 0x0100000001000101ULL, 0x0100000001010000ULL, 0x0100000001010001ULL, 0x0100000001010100ULL, 0x0100000001010101ULL,
78 0x0100000100000000ULL, 0x0100000100000001ULL, 0x0100000100000100ULL, 0x0100000100000101ULL, 0x0100000100010000ULL, 0x0100000100010001ULL, 0x0100000100010100ULL, 0x0100000100010101ULL,
79 0x0100000101000000ULL, 0x0100000101000001ULL, 0x0100000101000100ULL, 0x0100000101000101ULL, 0x0100000101010000ULL, 0x0100000101010001ULL, 0x0100000101010100ULL, 0x0100000101010101ULL,
80 0x0100010000000000ULL, 0x0100010000000001ULL, 0x0100010000000100ULL, 0x0100010000000101ULL, 0x0100010000010000ULL, 0x0100010000010001ULL, 0x0100010000010100ULL, 0x0100010000010101ULL,
81 0x0100010001000000ULL, 0x0100010001000001ULL, 0x0100010001000100ULL, 0x0100010001000101ULL, 0x0100010001010000ULL, 0x0100010001010001ULL, 0x0100010001010100ULL, 0x0100010001010101ULL,
82 0x0100010100000000ULL, 0x0100010100000001ULL, 0x0100010100000100ULL, 0x0100010100000101ULL, 0x0100010100010000ULL, 0x0100010100010001ULL, 0x0100010100010100ULL, 0x0100010100010101ULL,
83 0x0100010101000000ULL, 0x0100010101000001ULL, 0x0100010101000100ULL, 0x0100010101000101ULL, 0x0100010101010000ULL, 0x0100010101010001ULL, 0x0100010101010100ULL, 0x0100010101010101ULL,
84 0x0101000000000000ULL, 0x0101000000000001ULL, 0x0101000000000100ULL, 0x0101000000000101ULL, 0x0101000000010000ULL, 0x0101000000010001ULL, 0x0101000000010100ULL, 0x0101000000010101ULL,
85 0x0101000001000000ULL, 0x0101000001000001ULL, 0x0101000001000100ULL, 0x0101000001000101ULL, 0x0101000001010000ULL, 0x0101000001010001ULL, 0x0101000001010100ULL, 0x0101000001010101ULL,
86 0x0101000100000000ULL, 0x0101000100000001ULL, 0x0101000100000100ULL, 0x0101000100000101ULL, 0x0101000100010000ULL, 0x0101000100010001ULL, 0x0101000100010100ULL, 0x0101000100010101ULL,
87 0x0101000101000000ULL, 0x0101000101000001ULL, 0x0101000101000100ULL, 0x0101000101000101ULL, 0x0101000101010000ULL, 0x0101000101010001ULL, 0x0101000101010100ULL, 0x0101000101010101ULL,
88 0x0101010000000000ULL, 0x0101010000000001ULL, 0x0101010000000100ULL, 0x0101010000000101ULL, 0x0101010000010000ULL, 0x0101010000010001ULL, 0x0101010000010100ULL, 0x0101010000010101ULL,
89 0x0101010001000000ULL, 0x0101010001000001ULL, 0x0101010001000100ULL, 0x0101010001000101ULL, 0x0101010001010000ULL, 0x0101010001010001ULL, 0x0101010001010100ULL, 0x0101010001010101ULL,
90 0x0101010100000000ULL, 0x0101010100000001ULL, 0x0101010100000100ULL, 0x0101010100000101ULL, 0x0101010100010000ULL, 0x0101010100010001ULL, 0x0101010100010100ULL, 0x0101010100010101ULL,
91 0x0101010101000000ULL, 0x0101010101000001ULL, 0x0101010101000100ULL, 0x0101010101000101ULL, 0x0101010101010000ULL, 0x0101010101010001ULL, 0x0101010101010100ULL, 0x0101010101010101ULL,
92};
93
95static const unsigned long long H1_H8[256] = {
96 0x0000000000000000ULL, 0x0000000000000080ULL, 0x0000000000008000ULL, 0x0000000000008080ULL, 0x0000000000800000ULL, 0x0000000000800080ULL, 0x0000000000808000ULL, 0x0000000000808080ULL,
97 0x0000000080000000ULL, 0x0000000080000080ULL, 0x0000000080008000ULL, 0x0000000080008080ULL, 0x0000000080800000ULL, 0x0000000080800080ULL, 0x0000000080808000ULL, 0x0000000080808080ULL,
98 0x0000008000000000ULL, 0x0000008000000080ULL, 0x0000008000008000ULL, 0x0000008000008080ULL, 0x0000008000800000ULL, 0x0000008000800080ULL, 0x0000008000808000ULL, 0x0000008000808080ULL,
99 0x0000008080000000ULL, 0x0000008080000080ULL, 0x0000008080008000ULL, 0x0000008080008080ULL, 0x0000008080800000ULL, 0x0000008080800080ULL, 0x0000008080808000ULL, 0x0000008080808080ULL,
100 0x0000800000000000ULL, 0x0000800000000080ULL, 0x0000800000008000ULL, 0x0000800000008080ULL, 0x0000800000800000ULL, 0x0000800000800080ULL, 0x0000800000808000ULL, 0x0000800000808080ULL,
101 0x0000800080000000ULL, 0x0000800080000080ULL, 0x0000800080008000ULL, 0x0000800080008080ULL, 0x0000800080800000ULL, 0x0000800080800080ULL, 0x0000800080808000ULL, 0x0000800080808080ULL,
102 0x0000808000000000ULL, 0x0000808000000080ULL, 0x0000808000008000ULL, 0x0000808000008080ULL, 0x0000808000800000ULL, 0x0000808000800080ULL, 0x0000808000808000ULL, 0x0000808000808080ULL,
103 0x0000808080000000ULL, 0x0000808080000080ULL, 0x0000808080008000ULL, 0x0000808080008080ULL, 0x0000808080800000ULL, 0x0000808080800080ULL, 0x0000808080808000ULL, 0x0000808080808080ULL,
104 0x0080000000000000ULL, 0x0080000000000080ULL, 0x0080000000008000ULL, 0x0080000000008080ULL, 0x0080000000800000ULL, 0x0080000000800080ULL, 0x0080000000808000ULL, 0x0080000000808080ULL,
105 0x0080000080000000ULL, 0x0080000080000080ULL, 0x0080000080008000ULL, 0x0080000080008080ULL, 0x0080000080800000ULL, 0x0080000080800080ULL, 0x0080000080808000ULL, 0x0080000080808080ULL,
106 0x0080008000000000ULL, 0x0080008000000080ULL, 0x0080008000008000ULL, 0x0080008000008080ULL, 0x0080008000800000ULL, 0x0080008000800080ULL, 0x0080008000808000ULL, 0x0080008000808080ULL,
107 0x0080008080000000ULL, 0x0080008080000080ULL, 0x0080008080008000ULL, 0x0080008080008080ULL, 0x0080008080800000ULL, 0x0080008080800080ULL, 0x0080008080808000ULL, 0x0080008080808080ULL,
108 0x0080800000000000ULL, 0x0080800000000080ULL, 0x0080800000008000ULL, 0x0080800000008080ULL, 0x0080800000800000ULL, 0x0080800000800080ULL, 0x0080800000808000ULL, 0x0080800000808080ULL,
109 0x0080800080000000ULL, 0x0080800080000080ULL, 0x0080800080008000ULL, 0x0080800080008080ULL, 0x0080800080800000ULL, 0x0080800080800080ULL, 0x0080800080808000ULL, 0x0080800080808080ULL,
110 0x0080808000000000ULL, 0x0080808000000080ULL, 0x0080808000008000ULL, 0x0080808000008080ULL, 0x0080808000800000ULL, 0x0080808000800080ULL, 0x0080808000808000ULL, 0x0080808000808080ULL,
111 0x0080808080000000ULL, 0x0080808080000080ULL, 0x0080808080008000ULL, 0x0080808080008080ULL, 0x0080808080800000ULL, 0x0080808080800080ULL, 0x0080808080808000ULL, 0x0080808080808080ULL,
112 0x8000000000000000ULL, 0x8000000000000080ULL, 0x8000000000008000ULL, 0x8000000000008080ULL, 0x8000000000800000ULL, 0x8000000000800080ULL, 0x8000000000808000ULL, 0x8000000000808080ULL,
113 0x8000000080000000ULL, 0x8000000080000080ULL, 0x8000000080008000ULL, 0x8000000080008080ULL, 0x8000000080800000ULL, 0x8000000080800080ULL, 0x8000000080808000ULL, 0x8000000080808080ULL,
114 0x8000008000000000ULL, 0x8000008000000080ULL, 0x8000008000008000ULL, 0x8000008000008080ULL, 0x8000008000800000ULL, 0x8000008000800080ULL, 0x8000008000808000ULL, 0x8000008000808080ULL,
115 0x8000008080000000ULL, 0x8000008080000080ULL, 0x8000008080008000ULL, 0x8000008080008080ULL, 0x8000008080800000ULL, 0x8000008080800080ULL, 0x8000008080808000ULL, 0x8000008080808080ULL,
116 0x8000800000000000ULL, 0x8000800000000080ULL, 0x8000800000008000ULL, 0x8000800000008080ULL, 0x8000800000800000ULL, 0x8000800000800080ULL, 0x8000800000808000ULL, 0x8000800000808080ULL,
117 0x8000800080000000ULL, 0x8000800080000080ULL, 0x8000800080008000ULL, 0x8000800080008080ULL, 0x8000800080800000ULL, 0x8000800080800080ULL, 0x8000800080808000ULL, 0x8000800080808080ULL,
118 0x8000808000000000ULL, 0x8000808000000080ULL, 0x8000808000008000ULL, 0x8000808000008080ULL, 0x8000808000800000ULL, 0x8000808000800080ULL, 0x8000808000808000ULL, 0x8000808000808080ULL,
119 0x8000808080000000ULL, 0x8000808080000080ULL, 0x8000808080008000ULL, 0x8000808080008080ULL, 0x8000808080800000ULL, 0x8000808080800080ULL, 0x8000808080808000ULL, 0x8000808080808080ULL,
120 0x8080000000000000ULL, 0x8080000000000080ULL, 0x8080000000008000ULL, 0x8080000000008080ULL, 0x8080000000800000ULL, 0x8080000000800080ULL, 0x8080000000808000ULL, 0x8080000000808080ULL,
121 0x8080000080000000ULL, 0x8080000080000080ULL, 0x8080000080008000ULL, 0x8080000080008080ULL, 0x8080000080800000ULL, 0x8080000080800080ULL, 0x8080000080808000ULL, 0x8080000080808080ULL,
122 0x8080008000000000ULL, 0x8080008000000080ULL, 0x8080008000008000ULL, 0x8080008000008080ULL, 0x8080008000800000ULL, 0x8080008000800080ULL, 0x8080008000808000ULL, 0x8080008000808080ULL,
123 0x8080008080000000ULL, 0x8080008080000080ULL, 0x8080008080008000ULL, 0x8080008080008080ULL, 0x8080008080800000ULL, 0x8080008080800080ULL, 0x8080008080808000ULL, 0x8080008080808080ULL,
124 0x8080800000000000ULL, 0x8080800000000080ULL, 0x8080800000008000ULL, 0x8080800000008080ULL, 0x8080800000800000ULL, 0x8080800000800080ULL, 0x8080800000808000ULL, 0x8080800000808080ULL,
125 0x8080800080000000ULL, 0x8080800080000080ULL, 0x8080800080008000ULL, 0x8080800080008080ULL, 0x8080800080800000ULL, 0x8080800080800080ULL, 0x8080800080808000ULL, 0x8080800080808080ULL,
126 0x8080808000000000ULL, 0x8080808000000080ULL, 0x8080808000008000ULL, 0x8080808000008080ULL, 0x8080808000800000ULL, 0x8080808000800080ULL, 0x8080808000808000ULL, 0x8080808000808080ULL,
127 0x8080808080000000ULL, 0x8080808080000080ULL, 0x8080808080008000ULL, 0x8080808080008080ULL, 0x8080808080800000ULL, 0x8080808080800080ULL, 0x8080808080808000ULL, 0x8080808080808080ULL,
128};
129
138{
139 const unsigned long long tmp = board->player;
140 board->player = board->opponent;
141 board->opponent = tmp;
142}
143
154int board_set(Board *board, const char *string)
155{
156 int i;
157 const char *s = string;
158
159 board->player = board->opponent = 0;
160 for (i = A1; i <= H8; ++i) {
161 if (*s == '\0') break;
162 switch (tolower(*s)) {
163 case 'b':
164 case 'x':
165 case '*':
166 board->player |= x_to_bit(i);
167 break;
168 case 'o':
169 case 'w':
170 board->opponent |= x_to_bit(i);
171 break;
172 case '-':
173 case '.':
174 break;
175 default:
176 i--;
177 break;
178 }
179 ++s;
180 }
181 board_check(board);
182
183 for (;*s != '\0'; ++s) {
184 switch (tolower(*s)) {
185 case 'b':
186 case 'x':
187 case '*':
188 return BLACK;
189 case 'o':
190 case 'w':
191 board_swap_players(board);
192 return WHITE;
193 default:
194 break;
195 }
196 }
197
198 warn("board_set: bad string input\n");
199 return EMPTY;
200}
201
212int board_from_FEN(Board *board, const char *string)
213{
214 int i;
215 const char *s;
216
217 board->player = board->opponent = 0;
218 i = A8;
219 for (s = parse_skip_spaces(string); *s && *s != ' '; ++s) {
220 if (isdigit(*s)) {
221 i += (*s - '0');
222 } else if (*s == '/') {
223 if (i & 7) return EMPTY;
224 i -= 16;
225 } else if (*s == 'p') {
226 board->player |= x_to_bit(i);
227 ++i;
228 } else if (*s == 'P') {
229 board->opponent |= x_to_bit(i);
230 ++i;
231 } else {
232 return EMPTY;
233 }
234 }
235
236 s = parse_skip_spaces(s);
237 if (*s == 'b') {
238 return BLACK;
239 } else if (*s == 'w') {
240 board_swap_players(board);
241 return WHITE;
242 }
243
244 return EMPTY;
245}
246
247
258int board_from_obj(Board *board, const Board *obj, const int turn)
259{
260 board->player = obj->player;
261 board->opponent = obj->opponent;
262 board_check(board);
263 switch (turn) {
264 case BLACK:
265 return BLACK;
266 case WHITE:
267 board_swap_players(board);
268 return WHITE;
269 default:
270 break;
271 }
272 return EMPTY;
273}
274
280void board_init(Board *board)
281{
282 board->player = 0x0000000810000000ULL; // BLACK
283 board->opponent = 0x0000001008000000ULL; // WHITE
284}
285
291void board_check(const Board *board)
292{
293#ifndef NDEBUG
294 if (board->player & board->opponent) {
295 error("Two discs on the same square?\n");
296 board_print(board, BLACK, stderr);
297 bitboard_write(board->player, stderr);
298 bitboard_write(board->opponent, stderr);
299 abort();
300 }
301
302 // empty center ?
303 if (((board->player|board->opponent) & 0x0000001818000000ULL) != 0x0000001818000000ULL) {
304 error("Empty center?\n");
305 board_print(board, BLACK, stderr);
306 }
307#else
308 (void) board;
309#endif // NDEBUG
310}
311
319int board_compare(const Board *b1, const Board *b2)
320{
321 if (b1->player > b2->player) return 1;
322 else if (b1->player < b2->player) return -1;
323 else if (b1->opponent > b2->opponent) return 1;
324 else if (b1->opponent < b2->opponent) return -1;
325 else return 0;
326}
327
335bool board_equal(const Board *b1, const Board *b2)
336{
337 return (b1->player == b2->player && b1->opponent == b2->opponent);
338}
339
347void board_symetry(const Board *board, const int s, Board *sym)
348{
349 register unsigned long long player = board->player;
350 register unsigned long long opponent = board->opponent;
351
352 if (s & 1) {
353 player = horizontal_mirror(player);
354 opponent = horizontal_mirror(opponent);
355 }
356 if (s & 2) {
357 player = vertical_mirror(player);
358 opponent = vertical_mirror(opponent);
359 }
360 if (s & 4) {
361 player = transpose(player);
362 opponent = transpose(opponent);
363 }
364
365 sym->player = player;
366 sym->opponent = opponent;
367
368 board_check(sym);
369}
370
379int board_unique(const Board *board, Board *unique)
380{
381 Board sym;
382 int i, s = 0;
383
384 assert(board != unique);
385
386 *unique = *board;
387 for (i = 1; i < 8; ++i) {
388 board_symetry(board, i, &sym);
389 if (board_compare(&sym, unique) < 0) {
390 *unique = sym;
391 s = i;
392 }
393 }
394
395 board_check(unique);
396 return s;
397}
398
406void board_rand(Board *board, int n_ply, Random *r)
407{
408 Move move[1];
409 unsigned long long moves;
410 int ply;
411
412 board_init(board);
413 for (ply = 0; ply < n_ply; ply++) {
414 moves = get_moves(board->player, board->opponent);
415 if (!moves) {
416 board_pass(board);
417 moves = get_moves(board->player, board->opponent);
418 if (!moves) {
419 break;
420 }
421 }
422 board_get_move(board, get_rand_bit(moves, r), move);
423 board_update(board, move);
424 }
425}
426
427
438unsigned long long board_get_move(const Board *board, const int x, Move *move)
439{
440 move->flipped = flip[x](board->player, board->opponent);
441 move->x = x;
442 return move->flipped;
443}
444
452bool board_check_move(const Board *board, Move *move)
453{
454 if (move->x == PASS) return !can_move(board->player, board->opponent);
455 else if ((x_to_bit(move->x) & ~(board->player|board->opponent)) == 0) return false;
456 else if (move->flipped != flip[move->x](board->player, board->opponent)) return false;
457 else return true;
458}
459
469void board_update(Board *board, const Move *move)
470{
471 board->player ^= (move->flipped | x_to_bit(move->x));
472 board->opponent ^= move->flipped;
473 board_swap_players(board);
474
475 board_check(board);
476}
477
487void board_restore(Board *board, const Move *move)
488{
489 board_swap_players(board);
490 board->player ^= (move->flipped | x_to_bit(move->x));
491 board->opponent ^= move->flipped;
492
493 board_check(board);
494}
495
503void board_pass(Board *board)
504{
505 board_swap_players(board);
506 board_check(board);
507}
508
517unsigned long long board_next(const Board *board, const int x, Board *next)
518{
519 const unsigned long long flipped = flip[x](board->player, board->opponent);
520 const unsigned long long player = board->opponent ^ flipped;
521
522 next->opponent = board->player ^ (flipped | x_to_bit(x));
523 next->player = player;
524
525 return flipped;
526}
527
538unsigned long long board_pass_next(const Board *board, const int x, Board *next)
539{
540 const unsigned long long flipped = flip[x](board->opponent, board->player);
541
542 next->opponent = board->opponent ^ (flipped | x_to_bit(x));
543 next->player = board->player ^ flipped;
544
545 return flipped;
546}
547
561static inline unsigned long long get_some_moves(const unsigned long long P, const unsigned long long mask, const int dir)
562{
563
564#if PARALLEL_PREFIX & 1
565 // 1-stage Parallel Prefix (intermediate between kogge stone & sequential)
566 // 6 << + 6 >> + 7 | + 10 &
567 register unsigned long long flip_l, flip_r;
568 register unsigned long long mask_l, mask_r;
569 const int dir2 = dir + dir;
570
571 flip_l = mask & (P << dir); flip_r = mask & (P >> dir);
572 flip_l |= mask & (flip_l << dir); flip_r |= mask & (flip_r >> dir);
573 mask_l = mask & (mask << dir); mask_r = mask & (mask >> dir);
574 flip_l |= mask_l & (flip_l << dir2); flip_r |= mask_r & (flip_r >> dir2);
575 flip_l |= mask_l & (flip_l << dir2); flip_r |= mask_r & (flip_r >> dir2);
576
577 return (flip_l << dir) | (flip_r >> dir);
578
579#elif KOGGE_STONE & 1
580 // kogge-stone algorithm
581 // 6 << + 6 >> + 12 & + 7 |
582 // + better instruction independency
583 register unsigned long long flip_l, flip_r;
584 register unsigned long long mask_l, mask_r;
585 const int dir2 = dir << 1;
586 const int dir4 = dir << 2;
587
588 flip_l = P | (mask & (P << dir)); flip_r = P | (mask & (P >> dir));
589 mask_l = mask & (mask << dir); mask_r = mask & (mask >> dir);
590 flip_l |= mask_l & (flip_l << dir2); flip_r |= mask_r & (flip_r >> dir2);
591 mask_l &= (mask_l << dir2); mask_r &= (mask_r >> dir2);
592 flip_l |= mask_l & (flip_l << dir4); flip_r |= mask_r & (flip_r >> dir4);
593
594 return ((flip_l & mask) << dir) | ((flip_r & mask) >> dir);
595
596#else
597 // sequential algorithm
598 // 7 << + 7 >> + 6 & + 12 |
599 register unsigned long long flip;
600
601 flip = (((P << dir) | (P >> dir)) & mask);
602 flip |= (((flip << dir) | (flip >> dir)) & mask);
603 flip |= (((flip << dir) | (flip >> dir)) & mask);
604 flip |= (((flip << dir) | (flip >> dir)) & mask);
605 flip |= (((flip << dir) | (flip >> dir)) & mask);
606 flip |= (((flip << dir) | (flip >> dir)) & mask);
607 return (flip << dir) | (flip >> dir);
608
609#endif
610}
611
621DLL_API unsigned long long get_moves(const unsigned long long P, const unsigned long long O)
622{
623#if defined(USE_GAS_MMX)
624 /* mm7: P, mm6: O */
625 const unsigned long long mask_7e = 0x7e7e7e7e7e7e7e7eULL;
626
627 __asm__ volatile(
628 "movl %3, %%esi\n\t" "movq %1, %%mm7\n\t"
629 "movl %4, %%edi\n\t" "movq %2, %%mm6\n\t"
630 /* shift=+1 */ /* shift=+8 */
631 "movl %%esi, %%eax\n\t" "movq %%mm7, %%mm0\n\t"
632 "movq %5, %%mm5\n\t"
633 "shrl $1, %%eax\n\t" "psrlq $8, %%mm0\n\t"
634 "andl $2122219134, %%edi\n\t" "pand %%mm6, %%mm5\n\t"
635 "andl %%edi, %%eax\n\t" "pand %%mm6, %%mm0\n\t" /* 0 m7&o6 m6&o5 .. m1&o0 */
636 "movl %%eax, %%edx\n\t" "movq %%mm0, %%mm1\n\t"
637 "shrl $1, %%eax\n\t" "psrlq $8, %%mm0\n\t"
638 "movl %%edi, %%ecx\n\t" "movq %%mm6, %%mm3\n\t"
639 "andl %%edi, %%eax\n\t" "pand %%mm6, %%mm0\n\t" /* 0 0 m7&o6&o5 .. m2&o1&o0 */
640 "shrl $1, %%ecx\n\t" "psrlq $8, %%mm3\n\t"
641 "orl %%edx, %%eax\n\t" "por %%mm1, %%mm0\n\t" /* 0 m7&o6 (m6&o5)|(m7&o6&o5) .. (m1&o0) */
642 "andl %%edi, %%ecx\n\t" "pand %%mm6, %%mm3\n\t" /* 0 o7&o6 o6&o5 o5&o4 o4&o3 .. */
643 "movl %%eax, %%edx\n\t" "movq %%mm0, %%mm4\n\t"
644 "shrl $2, %%eax\n\t" "psrlq $16, %%mm0\n\t"
645 "andl %%ecx, %%eax\n\t" "pand %%mm3, %%mm0\n\t" /* 0 0 0 m7&o6&o5&o4 (m6&o5&o4&o3)|(m7&o6&o5&o4&o3) .. */
646 "orl %%eax, %%edx\n\t" "por %%mm0, %%mm4\n\t"
647 "shrl $2, %%eax\n\t" "psrlq $16, %%mm0\n\t"
648 "andl %%ecx, %%eax\n\t" "pand %%mm3, %%mm0\n\t" /* 0 0 0 0 0 m7&o6&..&o2 (m6&o5&..&o1)|(m7&o6&..&o1) .. */
649 "orl %%edx, %%eax\n\t" "por %%mm0, %%mm4\n\t"
650 "shrl $1, %%eax\n\t" "psrlq $8, %%mm4\n\t" /* result of +8 */
651 /* shift=-1 */ /* shift=-8 */
652 "movq %%mm7, %%mm0\n\t"
653 "addl %%esi, %%esi\n\t" "psllq $8, %%mm0\n\t"
654 "andl %%edi, %%esi\n\t" "pand %%mm6, %%mm0\n\t"
655 "movl %%esi, %%edx\n\t" "movq %%mm0, %%mm1\n\t"
656 "addl %%esi, %%esi\n\t" "psllq $8, %%mm0\n\t"
657 "andl %%edi, %%esi\n\t" "pand %%mm6, %%mm0\n\t"
658 "orl %%esi, %%edx\n\t" "por %%mm1, %%mm0\n\t"
659 "addl %%ecx, %%ecx\n\t" "psllq $8, %%mm3\n\t"
660 "movq %%mm0, %%mm1\n\t"
661 "leal (,%%edx,4), %%esi\n\t" "psllq $16, %%mm0\n\t"
662 "andl %%ecx, %%esi\n\t" "pand %%mm3, %%mm0\n\t"
663 "orl %%esi, %%edx\n\t" "por %%mm0, %%mm1\n\t"
664 "shll $2, %%esi\n\t" "psllq $16, %%mm0\n\t"
665 "andl %%ecx, %%esi\n\t" "pand %%mm3, %%mm0\n\t"
666 "orl %%edx, %%esi\n\t" "por %%mm1, %%mm0\n\t"
667 "addl %%esi, %%esi\n\t" "psllq $8, %%mm0\n\t"
668 "orl %%eax, %%esi\n\t" "por %%mm0, %%mm4\n\t"
669 /* Serialize */ /* shift=+7 */
670 "movq %%mm7, %%mm0\n\t"
671 "movd %%esi, %%mm1\n\t"
672 "psrlq $7, %%mm0\n\t"
673 "psllq $32, %%mm1\n\t"
674 "pand %%mm5, %%mm0\n\t"
675 "por %%mm1, %%mm4\n\t"
676 "movq %%mm0, %%mm1\n\t"
677 "psrlq $7, %%mm0\n\t"
678 "pand %%mm5, %%mm0\n\t"
679 "movq %%mm5, %%mm3\n\t"
680 "por %%mm1, %%mm0\n\t"
681 "psrlq $7, %%mm3\n\t"
682 "movq %%mm0, %%mm1\n\t"
683 "pand %%mm5, %%mm3\n\t"
684 "psrlq $14, %%mm0\n\t"
685 "pand %%mm3, %%mm0\n\t"
686 "movl %1, %%esi\n\t" "por %%mm0, %%mm1\n\t"
687 "movl %2, %%edi\n\t" "psrlq $14, %%mm0\n\t"
688 "andl $2122219134, %%edi\n\t" "pand %%mm3, %%mm0\n\t"
689 "movl %%edi, %%ecx\n\t" "por %%mm1, %%mm0\n\t"
690 "shrl $1, %%ecx\n\t" "psrlq $7, %%mm0\n\t"
691 "andl %%edi, %%ecx\n\t" "por %%mm0, %%mm4\n\t"
692 /* shift=+1 */ /* shift=-7 */
693 "movl %%esi, %%eax\n\t" "movq %%mm7, %%mm0\n\t"
694 "shrl $1, %%eax\n\t" "psllq $7, %%mm0\n\t"
695 "andl %%edi, %%eax\n\t" "pand %%mm5, %%mm0\n\t"
696 "movl %%eax, %%edx\n\t" "movq %%mm0, %%mm1\n\t"
697 "shrl $1, %%eax\n\t" "psllq $7, %%mm0\n\t"
698 "andl %%edi, %%eax\n\t" "pand %%mm5, %%mm0\n\t"
699 "orl %%edx, %%eax\n\t" "por %%mm1, %%mm0\n\t"
700 "psllq $7, %%mm3\n\t"
701 "movl %%eax, %%edx\n\t" "movq %%mm0, %%mm1\n\t"
702 "shrl $2, %%eax\n\t" "psllq $14, %%mm0\n\t"
703 "andl %%ecx, %%eax\n\t" "pand %%mm3, %%mm0\n\t"
704 "orl %%eax, %%edx\n\t" "por %%mm0, %%mm1\n\t"
705 "shrl $2, %%eax\n\t" "psllq $14, %%mm0\n\t"
706 "andl %%ecx, %%eax\n\t" "pand %%mm3, %%mm0\n\t"
707 "orl %%edx, %%eax\n\t" "por %%mm1, %%mm0\n\t"
708 "shrl $1, %%eax\n\t" "psllq $7, %%mm0\n\t"
709 "por %%mm0, %%mm4\n\t"
710 /* shift=-1 */ /* shift=+9 */
711 "movq %%mm7, %%mm0\n\t"
712 "addl %%esi, %%esi\n\t" "psrlq $9, %%mm0\n\t"
713 "andl %%edi, %%esi\n\t" "pand %%mm5, %%mm0\n\t"
714 "movl %%esi, %%edx\n\t" "movq %%mm0, %%mm1\n\t"
715 "addl %%esi, %%esi\n\t" "psrlq $9, %%mm0\n\t"
716 "andl %%edi, %%esi\n\t" "pand %%mm5, %%mm0\n\t"
717 "movq %%mm5, %%mm3\n\t"
718 "orl %%esi, %%edx\n\t" "por %%mm1, %%mm0\n\t"
719 "psrlq $9, %%mm3\n\t"
720 "movq %%mm0, %%mm1\n\t"
721 "addl %%ecx, %%ecx\n\t" "pand %%mm5, %%mm3\n\t"
722 "leal (,%%edx,4), %%esi\n\t" "psrlq $18, %%mm0\n\t"
723 "andl %%ecx, %%esi\n\t" "pand %%mm3, %%mm0\n\t"
724 "orl %%esi, %%edx\n\t" "por %%mm0, %%mm1\n\t"
725 "shll $2, %%esi\n\t" "psrlq $18, %%mm0\n\t"
726 "andl %%ecx, %%esi\n\t" "pand %%mm3, %%mm0\n\t"
727 "orl %%edx, %%esi\n\t" "por %%mm1, %%mm0\n\t"
728 "addl %%esi, %%esi\n\t" "psrlq $9, %%mm0\n\t"
729 "orl %%eax, %%esi\n\t" "por %%mm0, %%mm4\n\t"
730 /* Serialize */ /* shift=-9 */
731 "movq %%mm7, %%mm0\n\t"
732 "movd %%esi, %%mm1\n\t"
733 "psllq $9, %%mm0\n\t"
734 "por %%mm1, %%mm4\n\t"
735 "pand %%mm5, %%mm0\n\t"
736 "movq %%mm0, %%mm1\n\t"
737 "psllq $9, %%mm0\n\t"
738 "pand %%mm5, %%mm0\n\t"
739 "por %%mm1, %%mm0\n\t"
740 "psllq $9, %%mm3\n\t"
741 "movq %%mm0, %%mm1\n\t"
742 "psllq $18, %%mm0\n\t"
743 "pand %%mm3, %%mm0\n\t"
744 "por %%mm0, %%mm1\n\t"
745 "psllq $18, %%mm0\n\t"
746 "pand %%mm3, %%mm0\n\t"
747 "por %%mm1, %%mm0\n\t"
748 "psllq $9, %%mm0\n\t"
749 "por %%mm0, %%mm4\n\t"
750 /* mm4 is the pseudo-feasible moves at this point. */
751 /* Let mm7 be the feasible moves, i.e., mm4 restricted to empty squares. */
752 "por %%mm6, %%mm7\n\t"
753 "pandn %%mm4, %%mm7\n\t"
754 "movq %%mm7, %0\n\t"
755 "emms" /* Reset the FP/MMX unit. */
756 : "=g" (moves) : "m" (P), "m" (O), "g" (P >> 32), "g" (O >> 32), "m" (mask_7e) : "eax", "edx", "ecx", "esi", "edi" );
757
758#else
759 const unsigned long long mask = O & 0x7E7E7E7E7E7E7E7Eull;
760
761 return (get_some_moves(P, mask, 1) // horizontal
762 | get_some_moves(P, O, 8) // vertical
763 | get_some_moves(P, mask, 7) // diagonals
764 | get_some_moves(P, mask, 9))
765 & ~(P|O); // mask with empties
766
767#endif
768}
769
779unsigned long long get_moves_6x6(const unsigned long long P, const unsigned long long O)
780{
781 const unsigned long long E = (~(P|O) & 0x007E7E7E7E7E7E00ull); // empties
782
783 return ((get_some_moves(P, O & 0x003C3C3C3C3C3C00ull, 1) // horizontal
784 | get_some_moves(P, O & 0x00007E7E7E7E0000ull, 8) // vertical
785 | get_some_moves(P, O & 0x00003C3C3C3C0000ull, 7) // diagonals
786 | get_some_moves(P, O & 0x00003C3C3C3C0000ull, 9))
787 & E); // mask with empties
788}
789
797DLL_API bool can_move(const unsigned long long P, const unsigned long long O)
798{
799 const unsigned long long E = ~(P|O); // empties
800
801 return (get_some_moves(P, O & 0x007E7E7E7E7E7E00ull, 7) & E) // diagonals
802 || (get_some_moves(P, O & 0x007E7E7E7E7E7E00ull, 9) & E)
803 || (get_some_moves(P, O & 0x7E7E7E7E7E7E7E7Eull, 1) & E) // horizontal
804 || (get_some_moves(P, O & 0x00FFFFFFFFFFFF00ull, 8) & E); // vertical
805}
806
814bool can_move_6x6(const unsigned long long P, const unsigned long long O)
815{
816 const unsigned long long E = (~(P|O) & 0x007E7E7E7E7E7E00ull); // empties
817
818 return (get_some_moves(P, O & 0x00003C3C3C3C0000ull, 7) & E) // diagonals
819 || (get_some_moves(P, O & 0x00003C3C3C3C0000ull, 9) & E)
820 || (get_some_moves(P, O & 0x003C3C3C3C3C3C00ull, 1) & E) // horizontal
821 || (get_some_moves(P, O & 0x00007E7E7E7E0000ull, 8) & E); // vertical
822}
823
833int get_mobility(const unsigned long long P, const unsigned long long O)
834{
835 return bit_count(get_moves(P, O));
836}
837
838int get_weighted_mobility(const unsigned long long P, const unsigned long long O)
839{
840 return bit_weighted_count(get_moves(P, O));
841}
842
850static inline unsigned long long get_some_potential_moves(const unsigned long long P, const int dir)
851{
852 return (P << dir | P >> dir);
853}
854
864static unsigned long long get_potential_moves(const unsigned long long P, const unsigned long long O)
865{
866 return (get_some_potential_moves(O & 0x7E7E7E7E7E7E7E7Eull, 1) // horizontal
867 | get_some_potential_moves(O & 0x00FFFFFFFFFFFF00ull, 8) // vertical
868 | get_some_potential_moves(O & 0x007E7E7E7E7E7E00ull, 7) // diagonals
869 | get_some_potential_moves(O & 0x007E7E7E7E7E7E00ull, 9))
870 & ~(P|O); // mask with empties
871}
872
882int get_potential_mobility(const unsigned long long P, const unsigned long long O)
883{
885}
886
896static int find_edge_stable(const int old_P, const int old_O, int stable)
897{
898 register int P, O, x, y;
899 const int E = ~(old_P | old_O); // empties
900
901 stable &= old_P; // mask stable squares with remaining player squares.
902 if (!stable || E == 0) return stable;
903
904 for (x = 0; x < 8; ++x) {
905 if (E & x_to_bit(x)) { //is x an empty square ?
906 O = old_O;
907 P = old_P | x_to_bit(x); // player plays on it
908 if (x > 1) { // flip left discs
909 for (y = x - 1; y > 0 && (O & x_to_bit(y)); --y) ;
910 if (P & x_to_bit(y)) {
911 for (y = x - 1; y > 0 && (O & x_to_bit(y)); --y) {
912 O ^= x_to_bit(y); P ^= x_to_bit(y);
913 }
914 }
915 }
916 if (x < 6) { // flip right discs
917 for (y = x + 1; y < 8 && (O & x_to_bit(y)); ++y) ;
918 if (P & x_to_bit(y)) {
919 for (y = x + 1; y < 8 && (O & x_to_bit(y)); ++y) {
920 O ^= x_to_bit(y); P ^= x_to_bit(y);
921 }
922 }
923 }
924 stable = find_edge_stable(P, O, stable); // next move
925 if (!stable) return stable;
926
927 P = old_P;
928 O = old_O | x_to_bit(x); // opponent plays on it
929 if (x > 1) {
930 for (y = x - 1; y > 0 && (P & x_to_bit(y)); --y) ;
931 if (O & x_to_bit(y)) {
932 for (y = x - 1; y > 0 && (P & x_to_bit(y)); --y) {
933 O ^= x_to_bit(y); P ^= x_to_bit(y);
934 }
935 }
936 }
937 if (x < 6) {
938 for (y = x + 1; y < 8 && (P & x_to_bit(y)); ++y) ;
939 if (O & x_to_bit(y)) {
940 for (y = x + 1; y < 8 && (P & x_to_bit(y)); ++y) {
941 O ^= x_to_bit(y); P ^= x_to_bit(y);
942 }
943 }
944 }
945 stable = find_edge_stable(P, O, stable); // next move
946 if (!stable) return stable;
947 }
948 }
949
950 return stable;
951}
952
957{
958 int P, O;
959
960 for (P = 0; P < 256; ++P)
961 for (O = 0; O < 256; ++O) {
962 if (P & O) { // illegal positions
963 edge_stability[P][O] = 0;
964 } else {
966 }
967 }
968}
969
977static inline unsigned long long get_full_lines(const unsigned long long line, const int dir)
978{
979#if KOGGE_STONE & 2
980
981 // kogge-stone algorithm
982 // 5 << + 5 >> + 7 & + 10 |
983 // + better instruction independency
984 register unsigned long long full_l, full_r, edge_l, edge_r;
985 const unsigned long long edge = 0xff818181818181ffULL;
986 const int dir2 = dir << 1;
987 const int dir4 = dir << 2;
988
989 full_l = line & (edge | (line >> dir)); full_r = line & (edge | (line << dir));
990 edge_l = edge | (edge >> dir); edge_r = edge | (edge << dir);
991 full_l &= edge_l | (full_l >> dir2); full_r &= edge_r | (full_r << dir2);
992 edge_l |= edge_l >> dir2; edge_r |= edge_r << dir2;
993 full_l &= edge_l | (full_l >> dir4); full_r &= edge_r | (full_r << dir4);
994
995 return full_r & full_l;
996
997#elif PARALLEL_PREFIX & 2
998
999 // 1-stage Parallel Prefix (intermediate between kogge stone & sequential)
1000 // 5 << + 5 >> + 7 & + 10 |
1001 register unsigned long long full_l, full_r;
1002 register unsigned long long edge_l, edge_r;
1003 const unsigned long long edge = 0xff818181818181ffULL;
1004 const int dir2 = dir + dir;
1005
1006 full_l = edge | (line << dir); full_r = edge | (line >> dir);
1007 full_l &= edge | (full_l << dir); full_r &= edge | (full_r >> dir);
1008 edge_l = edge | (edge << dir); edge_r = edge | (edge >> dir);
1009 full_l &= edge_l | (full_l << dir2); full_r &= edge_r | (full_r >> dir2);
1010 full_l &= edge_l | (full_l << dir2); full_r &= edge_r | (full_r >> dir2);
1011
1012 return full_l & full_r;
1013
1014#else
1015
1016 // sequential algorithm
1017 // 6 << + 6 >> + 12 & + 5 |
1018 register unsigned long long full;
1019 const unsigned long long edge = line & 0xff818181818181ffULL;
1020
1021 full = (line & (((line >> dir) & (line << dir)) | edge));
1022 full &= (((full >> dir) & (full << dir)) | edge);
1023 full &= (((full >> dir) & (full << dir)) | edge);
1024 full &= (((full >> dir) & (full << dir)) | edge);
1025 full &= (((full >> dir) & (full << dir)) | edge);
1026
1027 return ((full >> dir) & (full << dir));
1028
1029#endif
1030}
1031
1032
1033#ifdef __X86_64__
1034#define packA1A8(X) ((((X) & 0x0101010101010101ULL) * 0x0102040810204080ULL) >> 56)
1035#define packH1H8(X) ((((X) & 0x8080808080808080ULL) * 0x0002040810204081ULL) >> 56)
1036#else
1037#define packA1A8(X) (((((unsigned int)(X) & 0x01010101u) + (((unsigned int)((X) >> 32) & 0x01010101u) << 4)) * 0x01020408u) >> 24)
1038#define packH1H8(X) (((((unsigned int)((X) >> 32) & 0x80808080u) + (((unsigned int)(X) & 0x80808080u) >> 4)) * 0x00204081u) >> 24)
1039#endif
1040
1049static inline unsigned long long get_stable_edge(const unsigned long long P, const unsigned long long O)
1050{
1051 // compute the exact stable edges (from precomputed tables)
1052 return edge_stability[P & 0xff][O & 0xff]
1053 | ((unsigned long long)edge_stability[P >> 56][O >> 56]) << 56
1056}
1057
1067int get_stability(const unsigned long long P, const unsigned long long O)
1068{
1069 const unsigned long long disc = (P | O);
1070 const unsigned long long central_mask = (P & 0x007e7e7e7e7e7e00ULL);
1071 const unsigned long long full_h = get_full_lines(disc, 1);
1072 const unsigned long long full_v = get_full_lines(disc, 8);
1073 const unsigned long long full_d7 = get_full_lines(disc, 7);
1074 const unsigned long long full_d9 = get_full_lines(disc, 9);
1075 register unsigned long long stable_h, stable_v, stable_d7, stable_d9, stable, new_stable;
1076
1077 // compute the exact stable edges (from precomputed tables)
1078 new_stable = get_stable_edge(P, O);
1079
1080 // add full lines
1081 new_stable |= (full_h & full_v & full_d7 & full_d9 & central_mask);
1082
1083 // now compute the other stable discs (ie discs touching another stable disc in each flipping direction).
1084 stable = 0;
1085 while (new_stable & ~stable) {
1086 stable |= new_stable;
1087 stable_h = ((stable >> 1) | (stable << 1) | full_h);
1088 stable_v = ((stable >> 8) | (stable << 8) | full_v);
1089 stable_d7 = ((stable >> 7) | (stable << 7) | full_d7);
1090 stable_d9 = ((stable >> 9) | (stable << 9) | full_d9);
1091 new_stable = (stable_h & stable_v & stable_d7 & stable_d9 & central_mask);
1092 }
1093
1094 return bit_count(stable);
1095}
1096
1106int get_edge_stability(const unsigned long long P, const unsigned long long O)
1107{
1108 return bit_count(get_stable_edge(P, O));
1109}
1110
1122int get_corner_stability(const unsigned long long P)
1123{
1124 const unsigned long long stable = ((((0x0100000000000001ULL & P) << 1) | ((0x8000000000000080ULL & P) >> 1) | ((0x0000000000000081ULL & P) << 8) | ((0x8100000000000000ULL & P) >> 8) | 0x8100000000000081ULL) & P);
1125 return bit_count(stable);
1126}
1127
1134unsigned long long board_get_hash_code(const Board *board)
1135{
1136 unsigned long long h1, h2;
1137 const unsigned char *p = (const unsigned char*)board;
1138
1139 h1 = hash_rank[0][p[0]];
1140 h2 = hash_rank[1][p[1]];
1141 h1 ^= hash_rank[2][p[2]];
1142 h2 ^= hash_rank[3][p[3]];
1143 h1 ^= hash_rank[4][p[4]];
1144 h2 ^= hash_rank[5][p[5]];
1145 h1 ^= hash_rank[6][p[6]];
1146 h2 ^= hash_rank[7][p[7]];
1147 h1 ^= hash_rank[8][p[8]];
1148 h2 ^= hash_rank[9][p[9]];
1149 h1 ^= hash_rank[10][p[10]];
1150 h2 ^= hash_rank[11][p[11]];
1151 h1 ^= hash_rank[12][p[12]];
1152 h2 ^= hash_rank[13][p[13]];
1153 h1 ^= hash_rank[14][p[14]];
1154 h2 ^= hash_rank[15][p[15]];
1155
1156 return h1 ^ h2;
1157}
1158
1168int board_get_square_color(const Board *board, const int x)
1169{
1170 return 2 - 2 * ((board->player >> x) & 1) - ((board->opponent >> x) & 1);
1171}
1172
1180bool board_is_occupied(const Board *board, const int x)
1181{
1182 return (board->player | board->opponent) & x_to_bit(x);
1183}
1184
1191bool board_is_pass(const Board *board)
1192{
1193 return can_move(board->player, board->opponent) == false &&
1194 can_move(board->opponent, board->player) == true;
1195}
1196
1203bool board_is_game_over(const Board *board)
1204{
1205 return can_move(board->player, board->opponent) == false &&
1206 can_move(board->opponent, board->player) == false;
1207}
1208
1209
1217{
1218 return bit_count(~(board->player | board->opponent));
1219}
1220
1230void board_print(const Board *board, const int player, FILE *f)
1231{
1232 int i, j, square, x;
1233 const char *color = "?*O-." + 1;
1234 unsigned long long moves = get_moves(board->player, board->opponent);
1235
1236 fputs(" A B C D E F G H\n", f);
1237 for (i = 0; i < 8; ++i) {
1238 fputc(i + '1', f);
1239 fputc(' ', f);
1240 for (j = 0; j < 8; ++j) {
1241 x = i * 8 + j;
1242 if (player == BLACK) square = 2 - ((board->opponent >> x) & 1) - 2 * ((board->player >> x) & 1);
1243 else square = 2 - ((board->player >> x) & 1) - 2 * ((board->opponent >> x) & 1);
1244 if (square == EMPTY && (moves & x_to_bit(x))) ++square;
1245 fputc(color[square], f);
1246 fputc(' ', f);
1247 }
1248 fputc(i + '1', f);
1249 if (i == 1)
1250 fprintf(f, " %c to move", color[player]);
1251 else if (i == 3)
1252 fprintf(f, " %c: discs = %2d moves = %2d",
1253 color[player], bit_count(board->player), get_mobility(board->player, board->opponent));
1254 else if (i == 4)
1255 fprintf(f, " %c: discs = %2d moves = %2d",
1256 color[!player], bit_count(board->opponent), get_mobility(board->opponent, board->player));
1257 else if (i == 5)
1258 fprintf(f, " empties = %2d ply = %2d",
1259 64 - bit_count(board->opponent|board->player), bit_count(board->opponent|board->player) - 3);
1260 fputc('\n', f);
1261 }
1262 fputs(" A B C D E F G H\n", f);
1263}
1264
1272char* board_to_string(const Board *board, const int player, char *s)
1273{
1274 int square, x;
1275 const char *color = "XO-?";
1276
1277 for (x = 0; x < 64; ++x) {
1278 if (player == BLACK) square = 2 - ((board->opponent >> x) & 1) - 2 * ((board->player >> x) & 1);
1279 else square = 2 - ((board->player >> x) & 1) - 2 * ((board->opponent >> x) & 1);
1280 s[x] = color[square];
1281 }
1282 s[64] = ' ';
1283 s[65] = color[player];
1284 s[66] = '\0';
1285 return s;
1286}
1287
1297void board_print_FEN(const Board *board, const int player, FILE *f)
1298{
1299 char s[256];
1300 fputs(board_to_FEN(board, player, s), f);
1301}
1302
1312char* board_to_FEN(const Board *board, const int player, char *string)
1313{
1314 int square, x, r, c;
1315 const char *piece = "pP-?";
1316 const char *color = "bw";
1317 int n_empties = 0;
1318 char *s = string;
1319 static char local_string[128];
1320
1321 if (s == NULL) s = string = local_string;
1322
1323 for (r = 7; r >= 0; --r)
1324 for (c = 0; c < 8; ++c) {
1325 if (c == 0 && r < 7) {
1326 if (n_empties) {
1327 *s++ = n_empties + '0';
1328 n_empties = 0;
1329 }
1330 *s++ = '/';
1331 }
1332 x = 8 * r + c;
1333 if (player == BLACK) square = 2 - ((board->opponent >> x) & 1) - 2 * ((board->player >> x) & 1);
1334 else square = 2 - ((board->player >> x) & 1) - 2 * ((board->opponent >> x) & 1);
1335
1336 if (square == EMPTY) {
1337 ++n_empties;
1338 } else {
1339 if (n_empties) {
1340 *s++ = n_empties + '0';
1341 n_empties = 0;
1342 }
1343 *s++ = piece[square];
1344 }
1345 }
1346 if (n_empties) {
1347 *s++ = n_empties + '0';
1348 n_empties = 0;
1349 }
1350 *s++ = ' ';
1351 *s++ = color[player];
1352 *s++ = ' '; *s++ = '-'; *s++ = ' '; *s++ = '-';
1353 *s++ = ' '; *s++ = '0'; *s++ = ' '; *s++ = '1'; *s = '\0';
1354
1355 return string;
1356}
1357
DLL_API int bit_count(unsigned long long b)
Count the number of bits set to one in an unsigned long long.
Definition bit.c:72
void bitboard_write(const unsigned long long b, FILE *f)
Print an unsigned long long as a board.
Definition bit.c:435
unsigned long long transpose(unsigned long long b)
Transpose the unsigned long long (symetry % A1-H8 diagonal).
Definition bit.c:345
int get_rand_bit(unsigned long long b, Random *r)
Get a random set bit index.
Definition bit.c:415
unsigned long long horizontal_mirror(unsigned long long b)
Mirror the unsigned long long (exchange the line 1 - 8, 2 - 7, 3 - 6 & 4 - 5).
Definition bit.c:377
unsigned long long vertical_mirror(unsigned long long b)
Mirror the unsigned long long (exchange the lines A - H, B - G, C - F & D - E.).
Definition bit.c:364
int bit_weighted_count(const unsigned long long v)
count the number of discs, counting the corners twice.
Definition bit.c:143
#define DLL_API
Definition bit.h:19
#define x_to_bit(x)
Definition bit.h:43
bool board_check_move(const Board *board, Move *move)
Check if a move is legal.
Definition board.c:452
void board_print_FEN(const Board *board, const int player, FILE *f)
print using FEN description.
Definition board.c:1297
#define packH1H8(X)
Definition board.c:1038
unsigned long long board_get_hash_code(const Board *board)
Compute a hash code.
Definition board.c:1134
void board_restore(Board *board, const Move *move)
Restore a board.
Definition board.c:487
bool board_is_game_over(const Board *board)
Check if the game is over.
Definition board.c:1203
unsigned long long board_pass_next(const Board *board, const int x, Board *next)
Compute a board resulting of an opponent move played on a previous board.
Definition board.c:538
void board_print(const Board *board, const int player, FILE *f)
Print out the board.
Definition board.c:1230
static unsigned long long get_potential_moves(const unsigned long long P, const unsigned long long O)
Get potential moves.
Definition board.c:864
void board_update(Board *board, const Move *move)
Update a board.
Definition board.c:469
static unsigned long long get_stable_edge(const unsigned long long P, const unsigned long long O)
Get stable edge.
Definition board.c:1049
static unsigned char edge_stability[256][256]
Definition board.c:56
int board_count_empties(const Board *board)
Check if the game is over.
Definition board.c:1216
int get_potential_mobility(const unsigned long long P, const unsigned long long O)
Get potential mobility.
Definition board.c:882
unsigned long long board_get_move(const Board *board, const int x, Move *move)
Compute a move.
Definition board.c:438
unsigned long long get_moves_6x6(const unsigned long long P, const unsigned long long O)
Get legal moves on a 6x6 board.
Definition board.c:779
char * board_to_FEN(const Board *board, const int player, char *string)
print to FEN description.
Definition board.c:1312
static int find_edge_stable(const int old_P, const int old_O, int stable)
search stable edge patterns.
Definition board.c:896
int board_compare(const Board *b1, const Board *b2)
Compare two board.
Definition board.c:319
int get_corner_stability(const unsigned long long P)
Estimate corner stability.
Definition board.c:1122
void board_swap_players(Board *board)
Swap players.
Definition board.c:137
static unsigned long long get_some_moves(const unsigned long long P, const unsigned long long mask, const int dir)
Get a part of the moves.
Definition board.c:561
int board_from_obj(Board *board, const Board *obj, const int turn)
Set a board from a Board object.
Definition board.c:258
int get_stability(const unsigned long long P, const unsigned long long O)
Estimate the stability.
Definition board.c:1067
int board_unique(const Board *board, Board *unique)
unique board
Definition board.c:379
void edge_stability_init(void)
Initialize the edge stability tables.
Definition board.c:956
int board_get_square_color(const Board *board, const int x)
Get square color.
Definition board.c:1168
void board_init(Board *board)
Set a board to the starting position.
Definition board.c:280
char * board_to_string(const Board *board, const int player, char *s)
convert the to a compact string.
Definition board.c:1272
int get_mobility(const unsigned long long P, const unsigned long long O)
Count legal moves.
Definition board.c:833
int get_edge_stability(const unsigned long long P, const unsigned long long O)
Estimate the stability of edges.
Definition board.c:1106
static const unsigned long long A1_A8[256]
Definition board.c:59
#define packA1A8(X)
Definition board.c:1037
bool board_is_pass(const Board *board)
Check if current player should pass.
Definition board.c:1191
bool can_move_6x6(const unsigned long long P, const unsigned long long O)
Check if a player can move.
Definition board.c:814
void board_check(const Board *board)
Check board consistency.
Definition board.c:291
static unsigned long long get_some_potential_moves(const unsigned long long P, const int dir)
Get some potential moves.
Definition board.c:850
bool board_equal(const Board *b1, const Board *b2)
Compare two board for equality.
Definition board.c:335
DLL_API unsigned long long get_moves(const unsigned long long P, const unsigned long long O)
Get legal moves.
Definition board.c:621
int get_weighted_mobility(const unsigned long long P, const unsigned long long O)
Definition board.c:838
static unsigned long long get_full_lines(const unsigned long long line, const int dir)
Get full lines.
Definition board.c:977
DLL_API bool can_move(const unsigned long long P, const unsigned long long O)
Check if a player can move.
Definition board.c:797
unsigned long long board_next(const Board *board, const int x, Board *next)
Compute a board resulting of a move played on a previous board.
Definition board.c:517
int board_set(Board *board, const char *string)
Set a board from a string description.
Definition board.c:154
void board_pass(Board *board)
Passing move.
Definition board.c:503
bool board_is_occupied(const Board *board, const int x)
Check if a square is occupied.
Definition board.c:1180
static const unsigned long long H1_H8[256]
Definition board.c:95
void board_rand(Board *board, int n_ply, Random *r)
Get a random board by playing random moves.
Definition board.c:406
void board_symetry(const Board *board, const int s, Board *sym)
symetric board
Definition board.c:347
int board_from_FEN(Board *board, const char *string)
Set a board from a string description.
Definition board.c:212
unsigned long long(* flip[BOARD_SIZE+2])(const unsigned long long, const unsigned long long)
Definition flip_bitscan.c:1912
@ PASS
Definition const.h:37
@ A1
Definition const.h:29
@ H8
Definition const.h:36
@ A8
Definition const.h:36
@ WHITE
Definition const.h:43
@ EMPTY
Definition const.h:44
@ BLACK
Definition const.h:42
uint64 P(uint64 mask, const uint64 flat)
Definition generate_flip.c:176
unsigned long long hash_rank[16][256]
Definition hash-lock-free.c:41
Definition board.h:26
unsigned long long player
Definition board.h:27
unsigned long long opponent
Definition board.h:27
Definition move.h:20
unsigned long long flipped
Definition move.h:21
int x
Definition move.h:22
Definition util.h:87
char * parse_skip_spaces(const char *string)
Skip spaces.
Definition util.c:514
Miscellaneous utilities header.
#define error(...)
Display an error message as "ERROR : filename : funcname : line number : ...".
Definition util.h:361
#define warn(...)
Display a warning message as "WARNING : ... ".
Definition util.h:373