Cute Chess 0.1
tbcore.c
1/*
2 Copyright (c) 2011-2015 Ronald de Man
3 This file may be redistributed and/or modified without restrictions.
4
5 tbcore.c contains engine-independent routines of the tablebase probing code.
6 This file should not need to much adaptation to add tablebase probing to
7 a particular engine, provided the engine is written in C or C++.
8*/
9
10#include <stdio.h>
11#ifndef TB_NO_STDINT
12#include <stdint.h>
13#endif
14#include <stdlib.h>
15#include <string.h>
16#include <sys/stat.h>
17#include <fcntl.h>
18#ifndef _WIN32
19#include <unistd.h>
20#include <sys/mman.h>
21#endif
22#include "tbcore.h"
23
24#if !defined(DECOMP64) && defined(_LP64)
25// use 64-bit decompression if OS is 64-bit
26// (appears not to work so commented out for now)
27//#define DECOMP64
28#endif
29
30#define TBMAX_PIECE 254
31#define TBMAX_PAWN 256
32#define HSHMAX 5
33
34// for variants where kings can connect and/or captured
35// #define CONNECTED_KINGS
36
37#define Swap(a,b) {int tmp=a;a=b;b=tmp;}
38
39#define TB_PAWN 1
40#define TB_KNIGHT 2
41#define TB_BISHOP 3
42#define TB_ROOK 4
43#define TB_QUEEN 5
44#define TB_KING 6
45
46#define TB_WPAWN TB_PAWN
47#define TB_BPAWN (TB_PAWN | 8)
48
49#ifdef TB_HAVE_THREADS
50static LOCK_T TB_MUTEX;
51#endif
52
53#ifdef TB_CUSTOM_BSWAP32
54#define internal_bswap32(x) TB_CUSTOM_BSWAP32(x)
55#elif defined(_MSC_VER)
56#define internal_bswap32(x) _byteswap_ulong(x)
57#else
58#define internal_bswap32(x) __builtin_bswap32(x)
59#endif
60
61#ifdef TB_CUSTOM_BSWAP64
62#define internal_bswap64(x) TB_CUSTOM_BSWAP64(x)
63#elif defined(_MSC_VER)
64#define internal_bswap64(x) _byteswap_uint64(x)
65#else
66#define internal_bswap64(x) __builtin_bswap64(x)
67#endif
68
69static int initialized = 0;
70static int num_paths = 0;
71static char *path_string = NULL;
72static char **paths = NULL;
73
74static int TBnum_piece, TBnum_pawn;
75static struct TBEntry_piece TB_piece[TBMAX_PIECE];
76static struct TBEntry_pawn TB_pawn[TBMAX_PAWN];
77
78static struct TBHashEntry TB_hash[1 << TBHASHBITS][HSHMAX];
79
80#define DTZ_ENTRIES 64
81
82static struct DTZTableEntry DTZ_table[DTZ_ENTRIES];
83
84static void init_indices(void);
85static uint64_t calc_key_from_pcs(int *pcs, int mirror);
86static void free_wdl_entry(struct TBEntry *entry);
87static void free_dtz_entry(struct TBEntry *entry);
88
89/* A replacement for strncpy().
90 Uses NUL termination even when the string has to be truncated. */
91static size_t safe_strncpy(char *dst, const char *src, size_t size)
92{
93 char *dstptr = dst;
94 size_t tocopy = size;
95 const char *srcptr = src;
96
97 if (tocopy && --tocopy) {
98 do {
99 if (!(*dstptr++ = *srcptr++))
100 break;
101 } while (--tocopy);
102 }
103 if (!tocopy) {
104 if (size) *dstptr = 0;
105 while (*srcptr++);
106 }
107
108 return (srcptr - src - 1);
109}
110
111/* A replacement for strncat().
112 <size> is the size of <dst>, not space left. */
113static size_t safe_strncat(char *dst, const char *src, size_t size)
114{
115 char *dstptr = dst;
116 size_t dstlen;
117 size_t tocopy = size;
118 const char *srcptr = src;
119
120 while (tocopy-- && *dstptr)
121 dstptr++;
122 dstlen = dstptr - dst;
123 if (!(tocopy = size - dstlen))
124 return (dstlen + strlen(src));
125 while (*srcptr) {
126 if (tocopy != 1) {
127 *dstptr++ = *srcptr;
128 tocopy--;
129 }
130 srcptr++;
131 }
132 *dstptr = 0;
133
134 return (dstlen + (srcptr - src));
135}
136
137static FD open_tb(const char *str, const char *suffix)
138{
139 int i;
140 FD fd;
141 char file[256];
142
143 for (i = 0; i < num_paths; i++) {
144 safe_strncpy(file, paths[i], 256);
145#ifndef _WIN32
146 safe_strncat(file, "/", 256);
147#else
148 safe_strncat(file, "\\", 256);
149#endif
150 safe_strncat(file, str, 256);
151 safe_strncat(file, suffix, 256);
152#ifndef _WIN32
153 fd = open(file, O_RDONLY);
154#else
155 fd = CreateFileA(file, GENERIC_READ, FILE_SHARE_READ, NULL,
156 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
157#endif
158 if (fd != FD_ERR) return fd;
159 }
160 return FD_ERR;
161}
162
163static void close_tb(FD fd)
164{
165#ifndef _WIN32
166 close(fd);
167#else
168 CloseHandle(fd);
169#endif
170}
171
172static char *map_file(const char *name, const char *suffix, uint64 *mapping)
173{
174 FD fd = open_tb(name, suffix);
175 if (fd == FD_ERR)
176 return NULL;
177#ifndef _WIN32
178 struct stat statbuf;
179 if (fstat(fd, &statbuf) == -1) {
180 printf("Could not get file status\n");
181 close_tb(fd);
182 return NULL;
183 }
184 *mapping = statbuf.st_size;
185 char *data = (char *)mmap(NULL, statbuf.st_size, PROT_READ,
186 MAP_SHARED, fd, 0);
187 if (data == (char *)(-1)) {
188 printf("Could not mmap() %s.\n", name);
189 exit(1);
190 }
191#else
192 DWORD size_low, size_high;
193 size_low = GetFileSize(fd, &size_high);
194// *size = ((uint64)size_high) << 32 | ((uint64)size_low);
195 HANDLE map = CreateFileMapping(fd, NULL, PAGE_READONLY, size_high, size_low,
196 NULL);
197 if (map == NULL) {
198 printf("CreateFileMapping() failed.\n");
199 exit(1);
200 }
201 *mapping = (uint64)map;
202 char *data = (char *)MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
203 if (data == NULL) {
204 printf("MapViewOfFile() failed, name = %s%s, error = %lu.\n", name, suffix, GetLastError());
205 exit(1);
206 }
207#endif
208 close_tb(fd);
209 return data;
210}
211
212#ifndef _WIN32
213static void unmap_file(char *data, uint64 size)
214{
215 if (!data) return;
216 munmap(data, size);
217}
218#else
219static void unmap_file(char *data, uint64 mapping)
220{
221 if (!data) return;
222 UnmapViewOfFile(data);
223 CloseHandle((HANDLE)mapping);
224}
225#endif
226
227static void add_to_hash(struct TBEntry *ptr, uint64 key)
228{
229 int i, hshidx;
230 hshidx = key >> (64 - TBHASHBITS);
231 i = 0;
232 while (i < HSHMAX && TB_hash[hshidx][i].ptr)
233 i++;
234 if (i == HSHMAX) {
235 printf("HSHMAX too low!\n");
236 exit(1);
237 } else {
238 TB_hash[hshidx][i].key = key;
239 TB_hash[hshidx][i].ptr = ptr;
240 }
241}
242
243static char pchr[] = {'K', 'Q', 'R', 'B', 'N', 'P'};
244
245static void init_tb(char *str)
246{
247 FD fd;
248 struct TBEntry *entry;
249 int i, j, pcs[16];
250 uint64 key, key2;
251 int color;
252 char *s;
253
254 fd = open_tb(str, WDLSUFFIX);
255 if (fd == FD_ERR) return;
256 close_tb(fd);
257
258 for (i = 0; i < 16; i++)
259 pcs[i] = 0;
260 color = 0;
261 for (s = str; *s; s++)
262 switch (*s) {
263 case 'P':
264 pcs[TB_PAWN | color]++;
265 break;
266 case 'N':
267 pcs[TB_KNIGHT | color]++;
268 break;
269 case 'B':
270 pcs[TB_BISHOP | color]++;
271 break;
272 case 'R':
273 pcs[TB_ROOK | color]++;
274 break;
275 case 'Q':
276 pcs[TB_QUEEN | color]++;
277 break;
278 case 'K':
279 pcs[TB_KING | color]++;
280 break;
281 case 'v':
282 color = 0x08;
283 break;
284 }
285 key = calc_key_from_pcs(pcs, 0);
286 key2 = calc_key_from_pcs(pcs, 1);
287 if (pcs[TB_WPAWN] + pcs[TB_BPAWN] == 0) {
288 if (TBnum_piece == TBMAX_PIECE) {
289 printf("TBMAX_PIECE limit too low!\n");
290 exit(1);
291 }
292 entry = (struct TBEntry *)&TB_piece[TBnum_piece++];
293 } else {
294 if (TBnum_pawn == TBMAX_PAWN) {
295 printf("TBMAX_PAWN limit too low!\n");
296 exit(1);
297 }
298 entry = (struct TBEntry *)&TB_pawn[TBnum_pawn++];
299 }
300 entry->key = key;
301 entry->ready = 0;
302 entry->num = 0;
303 for (i = 0; i < 16; i++)
304 entry->num += pcs[i];
305 entry->symmetric = (key == key2);
306 entry->has_pawns = (pcs[TB_WPAWN] + pcs[TB_BPAWN] > 0);
307 if (entry->num > TB_LARGEST)
308 TB_LARGEST = entry->num;
309
310 if (entry->has_pawns) {
311 struct TBEntry_pawn *ptr = (struct TBEntry_pawn *)entry;
312 ptr->pawns[0] = pcs[TB_WPAWN];
313 ptr->pawns[1] = pcs[TB_BPAWN];
314 if (pcs[TB_BPAWN] > 0
315 && (pcs[TB_WPAWN] == 0 || pcs[TB_BPAWN] < pcs[TB_WPAWN])) {
316 ptr->pawns[0] = pcs[TB_BPAWN];
317 ptr->pawns[1] = pcs[TB_WPAWN];
318 }
319 } else {
320 struct TBEntry_piece *ptr = (struct TBEntry_piece *)entry;
321 for (i = 0, j = 0; i < 16; i++)
322 if (pcs[i] == 1) j++;
323 if (j >= 3) ptr->enc_type = 0;
324 else if (j == 2) ptr->enc_type = 2;
325 else { /* only for suicide */
326 j = 16;
327 for (i = 0; i < 16; i++) {
328 if (pcs[i] < j && pcs[i] > 1) j = pcs[i];
329 ptr->enc_type = 1 + j;
330 }
331 }
332 }
333 add_to_hash(entry, key);
334 if (key2 != key) add_to_hash(entry, key2);
335}
336
337void init_tablebases(const char *path)
338{
339 char str[16];
340 int i, j, k, l;
341
342 if (initialized) {
343 free(path_string);
344 free(paths);
345 struct TBEntry *entry;
346 for (i = 0; i < TBnum_piece; i++) {
347 entry = (struct TBEntry *)&TB_piece[i];
348 free_wdl_entry(entry);
349 }
350 for (i = 0; i < TBnum_pawn; i++) {
351 entry = (struct TBEntry *)&TB_pawn[i];
352 free_wdl_entry(entry);
353 }
354 for (i = 0; i < DTZ_ENTRIES; i++)
355 if (DTZ_table[i].entry)
356 free_dtz_entry(DTZ_table[i].entry);
357 } else {
358 init_indices();
359 initialized = 1;
360 }
361
362 const char *p = path;
363 if (strlen(p) == 0 || !strcmp(p, "<empty>")) return;
364 const size_t len = strlen(p) + 1;
365 path_string = (char *)malloc(len);
366 safe_strncpy(path_string, p, len);
367 num_paths = 0;
368 for (i = 0;; i++) {
369 if (path_string[i] != SEP_CHAR)
370 num_paths++;
371 while (path_string[i] && path_string[i] != SEP_CHAR)
372 i++;
373 if (!path_string[i]) break;
374 path_string[i] = 0;
375 }
376 paths = (char **)malloc(num_paths * sizeof(char *));
377 for (i = j = 0; i < num_paths; i++) {
378 while (!path_string[j]) j++;
379 paths[i] = &path_string[j];
380 while (path_string[j]) j++;
381 }
382
383 LOCK_INIT(TB_MUTEX);
384
385 TBnum_piece = TBnum_pawn = 0;
386 TB_LARGEST = 0;
387
388 for (i = 0; i < (1 << TBHASHBITS); i++)
389 for (j = 0; j < HSHMAX; j++) {
390 TB_hash[i][j].key = 0ULL;
391 TB_hash[i][j].ptr = NULL;
392 }
393
394 for (i = 0; i < DTZ_ENTRIES; i++)
395 DTZ_table[i].entry = NULL;
396
397 for (i = 1; i < 6; i++) {
398 snprintf(str, 16, "K%cvK", pchr[i]);
399 init_tb(str);
400 }
401
402 for (i = 1; i < 6; i++)
403 for (j = i; j < 6; j++) {
404 snprintf(str, 16, "K%cvK%c", pchr[i], pchr[j]);
405 init_tb(str);
406 }
407
408 for (i = 1; i < 6; i++)
409 for (j = i; j < 6; j++) {
410 snprintf(str, 16, "K%c%cvK", pchr[i], pchr[j]);
411 init_tb(str);
412 }
413
414 for (i = 1; i < 6; i++)
415 for (j = i; j < 6; j++)
416 for (k = 1; k < 6; k++) {
417 snprintf(str, 16, "K%c%cvK%c", pchr[i], pchr[j], pchr[k]);
418 init_tb(str);
419 }
420
421 for (i = 1; i < 6; i++)
422 for (j = i; j < 6; j++)
423 for (k = j; k < 6; k++) {
424 snprintf(str, 16, "K%c%c%cvK", pchr[i], pchr[j], pchr[k]);
425 init_tb(str);
426 }
427
428 for (i = 1; i < 6; i++)
429 for (j = i; j < 6; j++)
430 for (k = i; k < 6; k++)
431 for (l = (i == k) ? j : k; l < 6; l++) {
432 snprintf(str, 16, "K%c%cvK%c%c", pchr[i], pchr[j], pchr[k], pchr[l]);
433 init_tb(str);
434 }
435
436 for (i = 1; i < 6; i++)
437 for (j = i; j < 6; j++)
438 for (k = j; k < 6; k++)
439 for (l = 1; l < 6; l++) {
440 snprintf(str, 16, "K%c%c%cvK%c", pchr[i], pchr[j], pchr[k], pchr[l]);
441 init_tb(str);
442 }
443
444 for (i = 1; i < 6; i++)
445 for (j = i; j < 6; j++)
446 for (k = j; k < 6; k++)
447 for (l = k; l < 6; l++) {
448 snprintf(str, 16, "K%c%c%c%cvK", pchr[i], pchr[j], pchr[k], pchr[l]);
449 init_tb(str);
450 }
451
452// printf("Found %d tablebases.\n", TBnum_piece + TBnum_pawn);
453}
454
455static const char offdiag[] = {
456 0,-1,-1,-1,-1,-1,-1,-1,
457 1, 0,-1,-1,-1,-1,-1,-1,
458 1, 1, 0,-1,-1,-1,-1,-1,
459 1, 1, 1, 0,-1,-1,-1,-1,
460 1, 1, 1, 1, 0,-1,-1,-1,
461 1, 1, 1, 1, 1, 0,-1,-1,
462 1, 1, 1, 1, 1, 1, 0,-1,
463 1, 1, 1, 1, 1, 1, 1, 0
464};
465
466static const ubyte triangle[] = {
467 6, 0, 1, 2, 2, 1, 0, 6,
468 0, 7, 3, 4, 4, 3, 7, 0,
469 1, 3, 8, 5, 5, 8, 3, 1,
470 2, 4, 5, 9, 9, 5, 4, 2,
471 2, 4, 5, 9, 9, 5, 4, 2,
472 1, 3, 8, 5, 5, 8, 3, 1,
473 0, 7, 3, 4, 4, 3, 7, 0,
474 6, 0, 1, 2, 2, 1, 0, 6
475};
476
477static const ubyte invtriangle[] = {
478 1, 2, 3, 10, 11, 19, 0, 9, 18, 27
479};
480
481static const ubyte invdiag[] = {
482 0, 9, 18, 27, 36, 45, 54, 63,
483 7, 14, 21, 28, 35, 42, 49, 56
484};
485
486static const ubyte flipdiag[] = {
487 0, 8, 16, 24, 32, 40, 48, 56,
488 1, 9, 17, 25, 33, 41, 49, 57,
489 2, 10, 18, 26, 34, 42, 50, 58,
490 3, 11, 19, 27, 35, 43, 51, 59,
491 4, 12, 20, 28, 36, 44, 52, 60,
492 5, 13, 21, 29, 37, 45, 53, 61,
493 6, 14, 22, 30, 38, 46, 54, 62,
494 7, 15, 23, 31, 39, 47, 55, 63
495};
496
497static const ubyte lower[] = {
498 28, 0, 1, 2, 3, 4, 5, 6,
499 0, 29, 7, 8, 9, 10, 11, 12,
500 1, 7, 30, 13, 14, 15, 16, 17,
501 2, 8, 13, 31, 18, 19, 20, 21,
502 3, 9, 14, 18, 32, 22, 23, 24,
503 4, 10, 15, 19, 22, 33, 25, 26,
504 5, 11, 16, 20, 23, 25, 34, 27,
505 6, 12, 17, 21, 24, 26, 27, 35
506};
507
508static const ubyte diag[] = {
509 0, 0, 0, 0, 0, 0, 0, 8,
510 0, 1, 0, 0, 0, 0, 9, 0,
511 0, 0, 2, 0, 0, 10, 0, 0,
512 0, 0, 0, 3, 11, 0, 0, 0,
513 0, 0, 0, 12, 4, 0, 0, 0,
514 0, 0, 13, 0, 0, 5, 0, 0,
515 0, 14, 0, 0, 0, 0, 6, 0,
516 15, 0, 0, 0, 0, 0, 0, 7
517};
518
519static const ubyte flap[] = {
520 0, 0, 0, 0, 0, 0, 0, 0,
521 0, 6, 12, 18, 18, 12, 6, 0,
522 1, 7, 13, 19, 19, 13, 7, 1,
523 2, 8, 14, 20, 20, 14, 8, 2,
524 3, 9, 15, 21, 21, 15, 9, 3,
525 4, 10, 16, 22, 22, 16, 10, 4,
526 5, 11, 17, 23, 23, 17, 11, 5,
527 0, 0, 0, 0, 0, 0, 0, 0
528};
529
530static const ubyte ptwist[] = {
531 0, 0, 0, 0, 0, 0, 0, 0,
532 47, 35, 23, 11, 10, 22, 34, 46,
533 45, 33, 21, 9, 8, 20, 32, 44,
534 43, 31, 19, 7, 6, 18, 30, 42,
535 41, 29, 17, 5, 4, 16, 28, 40,
536 39, 27, 15, 3, 2, 14, 26, 38,
537 37, 25, 13, 1, 0, 12, 24, 36,
538 0, 0, 0, 0, 0, 0, 0, 0
539};
540
541static const ubyte invflap[] = {
542 8, 16, 24, 32, 40, 48,
543 9, 17, 25, 33, 41, 49,
544 10, 18, 26, 34, 42, 50,
545 11, 19, 27, 35, 43, 51
546};
547
548static const ubyte invptwist[] = {
549 52, 51, 44, 43, 36, 35, 28, 27, 20, 19, 12, 11,
550 53, 50, 45, 42, 37, 34, 29, 26, 21, 18, 13, 10,
551 54, 49, 46, 41, 38, 33, 30, 25, 22, 17, 14, 9,
552 55, 48, 47, 40, 39, 32, 31, 24, 23, 16, 15, 8
553};
554
555static const ubyte file_to_file[] = {
556 0, 1, 2, 3, 3, 2, 1, 0
557};
558
559#ifndef CONNECTED_KINGS
560static const short KK_idx[10][64] = {
561 { -1, -1, -1, 0, 1, 2, 3, 4,
562 -1, -1, -1, 5, 6, 7, 8, 9,
563 10, 11, 12, 13, 14, 15, 16, 17,
564 18, 19, 20, 21, 22, 23, 24, 25,
565 26, 27, 28, 29, 30, 31, 32, 33,
566 34, 35, 36, 37, 38, 39, 40, 41,
567 42, 43, 44, 45, 46, 47, 48, 49,
568 50, 51, 52, 53, 54, 55, 56, 57 },
569 { 58, -1, -1, -1, 59, 60, 61, 62,
570 63, -1, -1, -1, 64, 65, 66, 67,
571 68, 69, 70, 71, 72, 73, 74, 75,
572 76, 77, 78, 79, 80, 81, 82, 83,
573 84, 85, 86, 87, 88, 89, 90, 91,
574 92, 93, 94, 95, 96, 97, 98, 99,
575 100,101,102,103,104,105,106,107,
576 108,109,110,111,112,113,114,115},
577 {116,117, -1, -1, -1,118,119,120,
578 121,122, -1, -1, -1,123,124,125,
579 126,127,128,129,130,131,132,133,
580 134,135,136,137,138,139,140,141,
581 142,143,144,145,146,147,148,149,
582 150,151,152,153,154,155,156,157,
583 158,159,160,161,162,163,164,165,
584 166,167,168,169,170,171,172,173 },
585 {174, -1, -1, -1,175,176,177,178,
586 179, -1, -1, -1,180,181,182,183,
587 184, -1, -1, -1,185,186,187,188,
588 189,190,191,192,193,194,195,196,
589 197,198,199,200,201,202,203,204,
590 205,206,207,208,209,210,211,212,
591 213,214,215,216,217,218,219,220,
592 221,222,223,224,225,226,227,228 },
593 {229,230, -1, -1, -1,231,232,233,
594 234,235, -1, -1, -1,236,237,238,
595 239,240, -1, -1, -1,241,242,243,
596 244,245,246,247,248,249,250,251,
597 252,253,254,255,256,257,258,259,
598 260,261,262,263,264,265,266,267,
599 268,269,270,271,272,273,274,275,
600 276,277,278,279,280,281,282,283 },
601 {284,285,286,287,288,289,290,291,
602 292,293, -1, -1, -1,294,295,296,
603 297,298, -1, -1, -1,299,300,301,
604 302,303, -1, -1, -1,304,305,306,
605 307,308,309,310,311,312,313,314,
606 315,316,317,318,319,320,321,322,
607 323,324,325,326,327,328,329,330,
608 331,332,333,334,335,336,337,338 },
609 { -1, -1,339,340,341,342,343,344,
610 -1, -1,345,346,347,348,349,350,
611 -1, -1,441,351,352,353,354,355,
612 -1, -1, -1,442,356,357,358,359,
613 -1, -1, -1, -1,443,360,361,362,
614 -1, -1, -1, -1, -1,444,363,364,
615 -1, -1, -1, -1, -1, -1,445,365,
616 -1, -1, -1, -1, -1, -1, -1,446 },
617 { -1, -1, -1,366,367,368,369,370,
618 -1, -1, -1,371,372,373,374,375,
619 -1, -1, -1,376,377,378,379,380,
620 -1, -1, -1,447,381,382,383,384,
621 -1, -1, -1, -1,448,385,386,387,
622 -1, -1, -1, -1, -1,449,388,389,
623 -1, -1, -1, -1, -1, -1,450,390,
624 -1, -1, -1, -1, -1, -1, -1,451 },
625 {452,391,392,393,394,395,396,397,
626 -1, -1, -1, -1,398,399,400,401,
627 -1, -1, -1, -1,402,403,404,405,
628 -1, -1, -1, -1,406,407,408,409,
629 -1, -1, -1, -1,453,410,411,412,
630 -1, -1, -1, -1, -1,454,413,414,
631 -1, -1, -1, -1, -1, -1,455,415,
632 -1, -1, -1, -1, -1, -1, -1,456 },
633 {457,416,417,418,419,420,421,422,
634 -1,458,423,424,425,426,427,428,
635 -1, -1, -1, -1, -1,429,430,431,
636 -1, -1, -1, -1, -1,432,433,434,
637 -1, -1, -1, -1, -1,435,436,437,
638 -1, -1, -1, -1, -1,459,438,439,
639 -1, -1, -1, -1, -1, -1,460,440,
640 -1, -1, -1, -1, -1, -1, -1,461 }
641};
642#else
643static const short PP_idx[10][64] = {
644 { 0, -1, 1, 2, 3, 4, 5, 6,
645 7, 8, 9, 10, 11, 12, 13, 14,
646 15, 16, 17, 18, 19, 20, 21, 22,
647 23, 24, 25, 26, 27, 28, 29, 30,
648 31, 32, 33, 34, 35, 36, 37, 38,
649 39, 40, 41, 42, 43, 44, 45, 46,
650 -1, 47, 48, 49, 50, 51, 52, 53,
651 54, 55, 56, 57, 58, 59, 60, 61 },
652 { 62, -1, -1, 63, 64, 65, -1, 66,
653 -1, 67, 68, 69, 70, 71, 72, -1,
654 73, 74, 75, 76, 77, 78, 79, 80,
655 81, 82, 83, 84, 85, 86, 87, 88,
656 89, 90, 91, 92, 93, 94, 95, 96,
657 -1, 97, 98, 99,100,101,102,103,
658 -1,104,105,106,107,108,109, -1,
659 110, -1,111,112,113,114, -1,115 },
660 {116, -1, -1, -1,117, -1, -1,118,
661 -1,119,120,121,122,123,124, -1,
662 -1,125,126,127,128,129,130, -1,
663 131,132,133,134,135,136,137,138,
664 -1,139,140,141,142,143,144,145,
665 -1,146,147,148,149,150,151, -1,
666 -1,152,153,154,155,156,157, -1,
667 158, -1, -1,159,160, -1, -1,161 },
668 {162, -1, -1, -1, -1, -1, -1,163,
669 -1,164, -1,165,166,167,168, -1,
670 -1,169,170,171,172,173,174, -1,
671 -1,175,176,177,178,179,180, -1,
672 -1,181,182,183,184,185,186, -1,
673 -1, -1,187,188,189,190,191, -1,
674 -1,192,193,194,195,196,197, -1,
675 198, -1, -1, -1, -1, -1, -1,199 },
676 {200, -1, -1, -1, -1, -1, -1,201,
677 -1,202, -1, -1,203, -1,204, -1,
678 -1, -1,205,206,207,208, -1, -1,
679 -1,209,210,211,212,213,214, -1,
680 -1, -1,215,216,217,218,219, -1,
681 -1, -1,220,221,222,223, -1, -1,
682 -1,224, -1,225,226, -1,227, -1,
683 228, -1, -1, -1, -1, -1, -1,229 },
684 {230, -1, -1, -1, -1, -1, -1,231,
685 -1,232, -1, -1, -1, -1,233, -1,
686 -1, -1,234, -1,235,236, -1, -1,
687 -1, -1,237,238,239,240, -1, -1,
688 -1, -1, -1,241,242,243, -1, -1,
689 -1, -1,244,245,246,247, -1, -1,
690 -1,248, -1, -1, -1, -1,249, -1,
691 250, -1, -1, -1, -1, -1, -1,251 },
692 { -1, -1, -1, -1, -1, -1, -1,259,
693 -1,252, -1, -1, -1, -1,260, -1,
694 -1, -1,253, -1, -1,261, -1, -1,
695 -1, -1, -1,254,262, -1, -1, -1,
696 -1, -1, -1, -1,255, -1, -1, -1,
697 -1, -1, -1, -1, -1,256, -1, -1,
698 -1, -1, -1, -1, -1, -1,257, -1,
699 -1, -1, -1, -1, -1, -1, -1,258 },
700 { -1, -1, -1, -1, -1, -1, -1, -1,
701 -1, -1, -1, -1, -1, -1,268, -1,
702 -1, -1,263, -1, -1,269, -1, -1,
703 -1, -1, -1,264,270, -1, -1, -1,
704 -1, -1, -1, -1,265, -1, -1, -1,
705 -1, -1, -1, -1, -1,266, -1, -1,
706 -1, -1, -1, -1, -1, -1,267, -1,
707 -1, -1, -1, -1, -1, -1, -1, -1 },
708 { -1, -1, -1, -1, -1, -1, -1, -1,
709 -1, -1, -1, -1, -1, -1, -1, -1,
710 -1, -1, -1, -1, -1,274, -1, -1,
711 -1, -1, -1,271,275, -1, -1, -1,
712 -1, -1, -1, -1,272, -1, -1, -1,
713 -1, -1, -1, -1, -1,273, -1, -1,
714 -1, -1, -1, -1, -1, -1, -1, -1,
715 -1, -1, -1, -1, -1, -1, -1, -1 },
716 { -1, -1, -1, -1, -1, -1, -1, -1,
717 -1, -1, -1, -1, -1, -1, -1, -1,
718 -1, -1, -1, -1, -1, -1, -1, -1,
719 -1, -1, -1, -1,277, -1, -1, -1,
720 -1, -1, -1, -1,276, -1, -1, -1,
721 -1, -1, -1, -1, -1, -1, -1, -1,
722 -1, -1, -1, -1, -1, -1, -1, -1,
723 -1, -1, -1, -1, -1, -1, -1, -1 }
724};
725
726static const ubyte test45[] = {
727 0, 0, 0, 0, 0, 0, 0, 0,
728 0, 0, 0, 0, 0, 0, 0, 0,
729 0, 0, 0, 0, 0, 0, 0, 0,
730 0, 0, 0, 0, 0, 0, 0, 0,
731 1, 1, 1, 0, 0, 0, 0, 0,
732 1, 1, 0, 0, 0, 0, 0, 0,
733 1, 0, 0, 0, 0, 0, 0, 0,
734 0, 0, 0, 0, 0, 0, 0, 0
735};
736
737static const ubyte mtwist[] = {
738 15, 63, 55, 47, 40, 48, 56, 12,
739 62, 11, 39, 31, 24, 32, 8, 57,
740 54, 38, 7, 23, 16, 4, 33, 49,
741 46, 30, 22, 3, 0, 17, 25, 41,
742 45, 29, 21, 2, 1, 18, 26, 42,
743 53, 37, 6, 20, 19, 5, 34, 50,
744 61, 10, 36, 28, 27, 35, 9, 58,
745 14, 60, 52, 44, 43, 51, 59, 13
746};
747#endif
748
749static int binomial[5][64];
750static int pawnidx[5][24];
751static int pfactor[5][4];
752#ifdef CONNECTED_KINGS
753static int multidx[5][10];
754static int mfactor[5];
755#endif
756
757static void init_indices(void)
758{
759 int i, j, k;
760
761// binomial[k-1][n] = Bin(n, k)
762 for (i = 0; i < 5; i++)
763 for (j = 0; j < 64; j++) {
764 int f = j;
765 int l = 1;
766 for (k = 1; k <= i; k++) {
767 f *= (j - k);
768 l *= (k + 1);
769 }
770 binomial[i][j] = f / l;
771 }
772
773 for (i = 0; i < 5; i++) {
774 int s = 0;
775 for (j = 0; j < 6; j++) {
776 pawnidx[i][j] = s;
777 s += (i == 0) ? 1 : binomial[i - 1][ptwist[invflap[j]]];
778 }
779 pfactor[i][0] = s;
780 s = 0;
781 for (; j < 12; j++) {
782 pawnidx[i][j] = s;
783 s += (i == 0) ? 1 : binomial[i - 1][ptwist[invflap[j]]];
784 }
785 pfactor[i][1] = s;
786 s = 0;
787 for (; j < 18; j++) {
788 pawnidx[i][j] = s;
789 s += (i == 0) ? 1 : binomial[i - 1][ptwist[invflap[j]]];
790 }
791 pfactor[i][2] = s;
792 s = 0;
793 for (; j < 24; j++) {
794 pawnidx[i][j] = s;
795 s += (i == 0) ? 1 : binomial[i - 1][ptwist[invflap[j]]];
796 }
797 pfactor[i][3] = s;
798 }
799
800#ifdef CONNECTED_KINGS
801 for (i = 0; i < 5; i++) {
802 int s = 0;
803 for (j = 0; j < 10; j++) {
804 multidx[i][j] = s;
805 s += (i == 0) ? 1 : binomial[i - 1][mtwist[invtriangle[j]]];
806 }
807 mfactor[i] = s;
808 }
809#endif
810}
811
812#ifndef CONNECTED_KINGS
813static uint64 encode_piece(struct TBEntry_piece *ptr, ubyte *norm, int *pos, int *factor)
814{
815 uint64 idx;
816 int i, j, k, m, l, p;
817 int n = ptr->num;
818
819 if (pos[0] & 0x04) {
820 for (i = 0; i < n; i++)
821 pos[i] ^= 0x07;
822 }
823 if (pos[0] & 0x20) {
824 for (i = 0; i < n; i++)
825 pos[i] ^= 0x38;
826 }
827
828 for (i = 0; i < n; i++)
829 if (offdiag[pos[i]]) break;
830 if (i < (ptr->enc_type == 0 ? 3 : 2) && offdiag[pos[i]] > 0)
831 for (i = 0; i < n; i++)
832 pos[i] = flipdiag[pos[i]];
833
834 switch (ptr->enc_type) {
835
836 case 0: /* 111 */
837 i = (pos[1] > pos[0]);
838 j = (pos[2] > pos[0]) + (pos[2] > pos[1]);
839
840 if (offdiag[pos[0]])
841 idx = triangle[pos[0]] * 63*62 + (pos[1] - i) * 62 + (pos[2] - j);
842 else if (offdiag[pos[1]])
843 idx = 6*63*62 + diag[pos[0]] * 28*62 + lower[pos[1]] * 62 + pos[2] - j;
844 else if (offdiag[pos[2]])
845 idx = 6*63*62 + 4*28*62 + (diag[pos[0]]) * 7*28 + (diag[pos[1]] - i) * 28 + lower[pos[2]];
846 else
847 idx = 6*63*62 + 4*28*62 + 4*7*28 + (diag[pos[0]] * 7*6) + (diag[pos[1]] - i) * 6 + (diag[pos[2]] - j);
848 i = 3;
849 break;
850
851 case 1: /* K3 */
852 j = (pos[2] > pos[0]) + (pos[2] > pos[1]);
853
854 idx = KK_idx[triangle[pos[0]]][pos[1]];
855 if (idx < 441)
856 idx = idx + 441 * (pos[2] - j);
857 else {
858 idx = 441*62 + (idx - 441) + 21 * lower[pos[2]];
859 if (!offdiag[pos[2]])
860 idx -= j * 21;
861 }
862 i = 3;
863 break;
864
865 default: /* K2 */
866 idx = KK_idx[triangle[pos[0]]][pos[1]];
867 i = 2;
868 break;
869 }
870 idx *= factor[0];
871
872 for (; i < n;) {
873 int t = norm[i];
874 for (j = i; j < i + t; j++)
875 for (k = j + 1; k < i + t; k++)
876 if (pos[j] > pos[k]) Swap(pos[j], pos[k]);
877 int s = 0;
878 for (m = i; m < i + t; m++) {
879 p = pos[m];
880 for (l = 0, j = 0; l < i; l++)
881 j += (p > pos[l]);
882 s += binomial[m - i][p - j];
883 }
884 idx += ((uint64)s) * ((uint64)factor[i]);
885 i += t;
886 }
887
888 return idx;
889}
890#else
891static uint64 encode_piece(struct TBEntry_piece *ptr, ubyte *norm, int *pos, int *factor)
892{
893 uint64 idx;
894 int i, j, k, m, l, p;
895 int n = ptr->num;
896
897 if (ptr->enc_type < 3) {
898 if (pos[0] & 0x04) {
899 for (i = 0; i < n; i++)
900 pos[i] ^= 0x07;
901 }
902 if (pos[0] & 0x20) {
903 for (i = 0; i < n; i++)
904 pos[i] ^= 0x38;
905 }
906
907 for (i = 0; i < n; i++)
908 if (offdiag[pos[i]]) break;
909 if (i < (ptr->enc_type == 0 ? 3 : 2) && offdiag[pos[i]] > 0)
910 for (i = 0; i < n; i++)
911 pos[i] = flipdiag[pos[i]];
912
913 switch (ptr->enc_type) {
914
915 case 0: /* 111 */
916 i = (pos[1] > pos[0]);
917 j = (pos[2] > pos[0]) + (pos[2] > pos[1]);
918
919 if (offdiag[pos[0]])
920 idx = triangle[pos[0]] * 63*62 + (pos[1] - i) * 62 + (pos[2] - j);
921 else if (offdiag[pos[1]])
922 idx = 6*63*62 + diag[pos[0]] * 28*62 + lower[pos[1]] * 62 + pos[2] - j;
923 else if (offdiag[pos[2]])
924 idx = 6*63*62 + 4*28*62 + (diag[pos[0]]) * 7*28 + (diag[pos[1]] - i) * 28 + lower[pos[2]];
925 else
926 idx = 6*63*62 + 4*28*62 + 4*7*28 + (diag[pos[0]] * 7*6) + (diag[pos[1]] - i) * 6 + (diag[pos[2]] - j);
927 i = 3;
928 break;
929
930 case 2: /* 11 */
931 i = (pos[1] > pos[0]);
932
933 if (offdiag[pos[0]])
934 idx = triangle[pos[0]] * 63 + (pos[1] - i);
935 else if (offdiag[pos[1]])
936 idx = 6*63 + diag[pos[0]] * 28 + lower[pos[1]];
937 else
938 idx = 6*63 + 4*28 + (diag[pos[0]]) * 7 + (diag[pos[1]] - i);
939 i = 2;
940 break;
941
942 }
943 } else if (ptr->enc_type == 3) { /* 2, e.g. KKvK */
944 if (triangle[pos[0]] > triangle[pos[1]])
945 Swap(pos[0], pos[1]);
946 if (pos[0] & 0x04)
947 for (i = 0; i < n; i++)
948 pos[i] ^= 0x07;
949 if (pos[0] & 0x20)
950 for (i = 0; i < n; i++)
951 pos[i] ^= 0x38;
952 if (offdiag[pos[0]] > 0 || (offdiag[pos[0]] == 0 && offdiag[pos[1]] > 0))
953 for (i = 0; i < n; i++)
954 pos[i] = flipdiag[pos[i]];
955 if (test45[pos[1]] && triangle[pos[0]] == triangle[pos[1]]) {
956 Swap(pos[0], pos[1]);
957 for (i = 0; i < n; i++)
958 pos[i] = flipdiag[pos[i] ^ 0x38];
959 }
960 idx = PP_idx[triangle[pos[0]]][pos[1]];
961 i = 2;
962 } else { /* 3 and higher, e.g. KKKvK and KKKKvK */
963 for (i = 1; i < norm[0]; i++)
964 if (triangle[pos[0]] > triangle[pos[i]])
965 Swap(pos[0], pos[i]);
966 if (pos[0] & 0x04)
967 for (i = 0; i < n; i++)
968 pos[i] ^= 0x07;
969 if (pos[0] & 0x20)
970 for (i = 0; i < n; i++)
971 pos[i] ^= 0x38;
972 if (offdiag[pos[0]] > 0)
973 for (i = 0; i < n; i++)
974 pos[i] = flipdiag[pos[i]];
975 for (i = 1; i < norm[0]; i++)
976 for (j = i + 1; j < norm[0]; j++)
977 if (mtwist[pos[i]] > mtwist[pos[j]])
978 Swap(pos[i], pos[j]);
979
980 idx = multidx[norm[0] - 1][triangle[pos[0]]];
981 for (i = 1; i < norm[0]; i++)
982 idx += binomial[i - 1][mtwist[pos[i]]];
983 }
984 idx *= factor[0];
985
986 for (; i < n;) {
987 int t = norm[i];
988 for (j = i; j < i + t; j++)
989 for (k = j + 1; k < i + t; k++)
990 if (pos[j] > pos[k]) Swap(pos[j], pos[k]);
991 int s = 0;
992 for (m = i; m < i + t; m++) {
993 p = pos[m];
994 for (l = 0, j = 0; l < i; l++)
995 j += (p > pos[l]);
996 s += binomial[m - i][p - j];
997 }
998 idx += ((uint64)s) * ((uint64)factor[i]);
999 i += t;
1000 }
1001
1002 return idx;
1003}
1004#endif
1005
1006// determine file of leftmost pawn and sort pawns
1007static int pawn_file(struct TBEntry_pawn *ptr, int *pos)
1008{
1009 int i;
1010
1011 for (i = 1; i < ptr->pawns[0]; i++)
1012 if (flap[pos[0]] > flap[pos[i]])
1013 Swap(pos[0], pos[i]);
1014
1015 return file_to_file[pos[0] & 0x07];
1016}
1017
1018static uint64 encode_pawn(struct TBEntry_pawn *ptr, ubyte *norm, int *pos, int *factor)
1019{
1020 uint64 idx;
1021 int i, j, k, m, s, t;
1022 int n = ptr->num;
1023
1024 if (pos[0] & 0x04)
1025 for (i = 0; i < n; i++)
1026 pos[i] ^= 0x07;
1027
1028 for (i = 1; i < ptr->pawns[0]; i++)
1029 for (j = i + 1; j < ptr->pawns[0]; j++)
1030 if (ptwist[pos[i]] < ptwist[pos[j]])
1031 Swap(pos[i], pos[j]);
1032
1033 t = ptr->pawns[0] - 1;
1034 idx = pawnidx[t][flap[pos[0]]];
1035 for (i = t; i > 0; i--)
1036 idx += binomial[t - i][ptwist[pos[i]]];
1037 idx *= factor[0];
1038
1039// remaining pawns
1040 i = ptr->pawns[0];
1041 t = i + ptr->pawns[1];
1042 if (t > i) {
1043 for (j = i; j < t; j++)
1044 for (k = j + 1; k < t; k++)
1045 if (pos[j] > pos[k]) Swap(pos[j], pos[k]);
1046 s = 0;
1047 for (m = i; m < t; m++) {
1048 int p = pos[m];
1049 for (k = 0, j = 0; k < i; k++)
1050 j += (p > pos[k]);
1051 s += binomial[m - i][p - j - 8];
1052 }
1053 idx += ((uint64)s) * ((uint64)factor[i]);
1054 i = t;
1055 }
1056
1057 for (; i < n;) {
1058 t = norm[i];
1059 for (j = i; j < i + t; j++)
1060 for (k = j + 1; k < i + t; k++)
1061 if (pos[j] > pos[k]) Swap(pos[j], pos[k]);
1062 s = 0;
1063 for (m = i; m < i + t; m++) {
1064 int p = pos[m];
1065 for (k = 0, j = 0; k < i; k++)
1066 j += (p > pos[k]);
1067 s += binomial[m - i][p - j];
1068 }
1069 idx += ((uint64)s) * ((uint64)factor[i]);
1070 i += t;
1071 }
1072
1073 return idx;
1074}
1075
1076static ubyte decompress_pairs(struct PairsData *d, uint64 index);
1077
1078// place k like pieces on n squares
1079static int subfactor(int k, int n)
1080{
1081 int i, f, l;
1082
1083 f = n;
1084 l = 1;
1085 for (i = 1; i < k; i++) {
1086 f *= n - i;
1087 l *= i + 1;
1088 }
1089
1090 return f / l;
1091}
1092
1093static uint64 calc_factors_piece(int *factor, int num, int order, ubyte *norm, ubyte enc_type)
1094{
1095 int i, k, n;
1096 uint64 f;
1097#ifndef CONNECTED_KINGS
1098 static int pivfac[] = { 31332, 28056, 462 };
1099#else
1100 static int pivfac[] = { 31332, 0, 518, 278 };
1101#endif
1102
1103 n = 64 - norm[0];
1104
1105 f = 1;
1106 for (i = norm[0], k = 0; i < num || k == order; k++) {
1107 if (k == order) {
1108 factor[0] = (int)f;
1109#ifndef CONNECTED_KINGS
1110 f *= pivfac[enc_type];
1111#else
1112 if (enc_type < 4)
1113 f *= pivfac[enc_type];
1114 else
1115 f *= mfactor[enc_type - 2];
1116#endif
1117 } else {
1118 factor[i] = (int)f;
1119 f *= subfactor(norm[i], n);
1120 n -= norm[i];
1121 i += norm[i];
1122 }
1123 }
1124
1125 return f;
1126}
1127
1128static uint64 calc_factors_pawn(int *factor, int num, int order, int order2, ubyte *norm, int file)
1129{
1130 int i, k, n;
1131 uint64 f;
1132
1133 i = norm[0];
1134 if (order2 < 0x0f) i += norm[i];
1135 n = 64 - i;
1136
1137 f = 1;
1138 for (k = 0; i < num || k == order || k == order2; k++) {
1139 if (k == order) {
1140 factor[0] = (int)f;
1141 f *= pfactor[norm[0] - 1][file];
1142 } else if (k == order2) {
1143 factor[norm[0]] = (int)f;
1144 f *= subfactor(norm[norm[0]], 48 - norm[0]);
1145 } else {
1146 factor[i] = (int)f;
1147 f *= subfactor(norm[i], n);
1148 n -= norm[i];
1149 i += norm[i];
1150 }
1151 }
1152
1153 return f;
1154}
1155
1156static void set_norm_piece(struct TBEntry_piece *ptr, ubyte *norm, ubyte *pieces)
1157{
1158 int i, j;
1159
1160 for (i = 0; i < ptr->num; i++)
1161 norm[i] = 0;
1162
1163 switch (ptr->enc_type) {
1164 case 0:
1165 norm[0] = 3;
1166 break;
1167 case 2:
1168 norm[0] = 2;
1169 break;
1170 default:
1171 norm[0] = ptr->enc_type - 1;
1172 break;
1173 }
1174
1175 for (i = norm[0]; i < ptr->num; i += norm[i])
1176 for (j = i; j < ptr->num && pieces[j] == pieces[i]; j++)
1177 norm[i]++;
1178}
1179
1180static void set_norm_pawn(struct TBEntry_pawn *ptr, ubyte *norm, ubyte *pieces)
1181{
1182 int i, j;
1183
1184 for (i = 0; i < ptr->num; i++)
1185 norm[i] = 0;
1186
1187 norm[0] = ptr->pawns[0];
1188 if (ptr->pawns[1]) norm[ptr->pawns[0]] = ptr->pawns[1];
1189
1190 for (i = ptr->pawns[0] + ptr->pawns[1]; i < ptr->num; i += norm[i])
1191 for (j = i; j < ptr->num && pieces[j] == pieces[i]; j++)
1192 norm[i]++;
1193}
1194
1195static void setup_pieces_piece(struct TBEntry_piece *ptr, unsigned char *data, uint64 *tb_size)
1196{
1197 int i;
1198 int order;
1199
1200 for (i = 0; i < ptr->num; i++)
1201 ptr->pieces[0][i] = data[i + 1] & 0x0f;
1202 order = data[0] & 0x0f;
1203 set_norm_piece(ptr, ptr->norm[0], ptr->pieces[0]);
1204 tb_size[0] = calc_factors_piece(ptr->factor[0], ptr->num, order, ptr->norm[0], ptr->enc_type);
1205
1206 for (i = 0; i < ptr->num; i++)
1207 ptr->pieces[1][i] = data[i + 1] >> 4;
1208 order = data[0] >> 4;
1209 set_norm_piece(ptr, ptr->norm[1], ptr->pieces[1]);
1210 tb_size[1] = calc_factors_piece(ptr->factor[1], ptr->num, order, ptr->norm[1], ptr->enc_type);
1211}
1212
1213static void setup_pieces_piece_dtz(struct DTZEntry_piece *ptr, unsigned char *data, uint64 *tb_size)
1214{
1215 int i;
1216 int order;
1217
1218 for (i = 0; i < ptr->num; i++)
1219 ptr->pieces[i] = data[i + 1] & 0x0f;
1220 order = data[0] & 0x0f;
1221 set_norm_piece((struct TBEntry_piece *)ptr, ptr->norm, ptr->pieces);
1222 tb_size[0] = calc_factors_piece(ptr->factor, ptr->num, order, ptr->norm, ptr->enc_type);
1223}
1224
1225static void setup_pieces_pawn(struct TBEntry_pawn *ptr, unsigned char *data, uint64 *tb_size, int f)
1226{
1227 int i, j;
1228 int order, order2;
1229
1230 j = 1 + (ptr->pawns[1] > 0);
1231 order = data[0] & 0x0f;
1232 order2 = ptr->pawns[1] ? (data[1] & 0x0f) : 0x0f;
1233 for (i = 0; i < ptr->num; i++)
1234 ptr->file[f].pieces[0][i] = data[i + j] & 0x0f;
1235 set_norm_pawn(ptr, ptr->file[f].norm[0], ptr->file[f].pieces[0]);
1236 tb_size[0] = calc_factors_pawn(ptr->file[f].factor[0], ptr->num, order, order2, ptr->file[f].norm[0], f);
1237
1238 order = data[0] >> 4;
1239 order2 = ptr->pawns[1] ? (data[1] >> 4) : 0x0f;
1240 for (i = 0; i < ptr->num; i++)
1241 ptr->file[f].pieces[1][i] = data[i + j] >> 4;
1242 set_norm_pawn(ptr, ptr->file[f].norm[1], ptr->file[f].pieces[1]);
1243 tb_size[1] = calc_factors_pawn(ptr->file[f].factor[1], ptr->num, order, order2, ptr->file[f].norm[1], f);
1244}
1245
1246static void setup_pieces_pawn_dtz(struct DTZEntry_pawn *ptr, unsigned char *data, uint64 *tb_size, int f)
1247{
1248 int i, j;
1249 int order, order2;
1250
1251 j = 1 + (ptr->pawns[1] > 0);
1252 order = data[0] & 0x0f;
1253 order2 = ptr->pawns[1] ? (data[1] & 0x0f) : 0x0f;
1254 for (i = 0; i < ptr->num; i++)
1255 ptr->file[f].pieces[i] = data[i + j] & 0x0f;
1256 set_norm_pawn((struct TBEntry_pawn *)ptr, ptr->file[f].norm, ptr->file[f].pieces);
1257 tb_size[0] = calc_factors_pawn(ptr->file[f].factor, ptr->num, order, order2, ptr->file[f].norm, f);
1258}
1259
1260static void calc_symlen(struct PairsData *d, int s, char *tmp)
1261{
1262 int s1, s2;
1263
1264 int w = *(int *)(d->sympat + 3 * s);
1265 s2 = (w >> 12) & 0x0fff;
1266 if (s2 == 0x0fff)
1267 d->symlen[s] = 0;
1268 else {
1269 s1 = w & 0x0fff;
1270 if (!tmp[s1]) calc_symlen(d, s1, tmp);
1271 if (!tmp[s2]) calc_symlen(d, s2, tmp);
1272 d->symlen[s] = d->symlen[s1] + d->symlen[s2] + 1;
1273 }
1274 tmp[s] = 1;
1275}
1276
1277static struct PairsData *setup_pairs(unsigned char *data, uint64 tb_size, uint64 *size, unsigned char **next, ubyte *flags, int wdl)
1278{
1279 struct PairsData *d;
1280 int i;
1281
1282 *flags = data[0];
1283 if (data[0] & 0x80) {
1284 d = (struct PairsData *)malloc(sizeof(struct PairsData));
1285 d->idxbits = 0;
1286 if (wdl)
1287 d->min_len = data[1];
1288 else
1289 d->min_len = 0;
1290 *next = data + 2;
1291 size[0] = size[1] = size[2] = 0;
1292 return d;
1293 }
1294
1295 int blocksize = data[1];
1296 int idxbits = data[2];
1297 int real_num_blocks = *(uint32 *)(&data[4]);
1298 int num_blocks = real_num_blocks + *(ubyte *)(&data[3]);
1299 int max_len = data[8];
1300 int min_len = data[9];
1301 int h = max_len - min_len + 1;
1302 int num_syms = *(ushort *)(&data[10 + 2 * h]);
1303 d = (struct PairsData *)malloc(sizeof(struct PairsData) + (h - 1) * sizeof(base_t) + num_syms);
1304 d->blocksize = blocksize;
1305 d->idxbits = idxbits;
1306 d->offset = (ushort *)(&data[10]);
1307 d->symlen = ((ubyte *)d) + sizeof(struct PairsData) + (h - 1) * sizeof(base_t);
1308 d->sympat = &data[12 + 2 * h];
1309 d->min_len = min_len;
1310 *next = &data[12 + 2 * h + 3 * num_syms + (num_syms & 1)];
1311
1312 int num_indices = (int)((tb_size + (1ULL << idxbits) - 1) >> idxbits);
1313 size[0] = 6ULL * num_indices;
1314 size[1] = 2ULL * num_blocks;
1315 size[2] = (1ULL << blocksize) * real_num_blocks;
1316
1317 // char tmp[num_syms];
1318 char tmp[4096];
1319 for (i = 0; i < num_syms; i++)
1320 tmp[i] = 0;
1321 for (i = 0; i < num_syms; i++)
1322 if (!tmp[i])
1323 calc_symlen(d, i, tmp);
1324
1325 d->base[h - 1] = 0;
1326 for (i = h - 2; i >= 0; i--)
1327 d->base[i] = (d->base[i + 1] + d->offset[i] - d->offset[i + 1]) / 2;
1328#ifdef DECOMP64
1329 for (i = 0; i < h; i++)
1330 d->base[i] <<= 64 - (min_len + i);
1331#else
1332 for (i = 0; i < h; i++)
1333 d->base[i] <<= 32 - (min_len + i);
1334#endif
1335
1336 d->offset -= d->min_len;
1337
1338 return d;
1339}
1340
1341static int init_table_wdl(struct TBEntry *entry, char *str)
1342{
1343 ubyte *next;
1344 int f, s;
1345 uint64 tb_size[8];
1346 uint64 size[8 * 3];
1347 ubyte flags;
1348
1349 // first mmap the table into memory
1350 entry->data = map_file(str, WDLSUFFIX, &entry->mapping);
1351 if (!entry->data) {
1352 printf("Could not find %s" WDLSUFFIX "\n", str);
1353 return 0;
1354 }
1355
1356 ubyte *data = (ubyte *)entry->data;
1357 if (((uint32 *)data)[0] != WDL_MAGIC) {
1358 printf("Corrupted table.\n");
1359 unmap_file(entry->data, entry->mapping);
1360 entry->data = 0;
1361 return 0;
1362 }
1363
1364 int split = data[4] & 0x01;
1365 int files = data[4] & 0x02 ? 4 : 1;
1366
1367 data += 5;
1368
1369 if (!entry->has_pawns) {
1370 struct TBEntry_piece *ptr = (struct TBEntry_piece *)entry;
1371 setup_pieces_piece(ptr, data, &tb_size[0]);
1372 data += ptr->num + 1;
1373 data += ((uintptr_t)data) & 0x01;
1374
1375 ptr->precomp[0] = setup_pairs(data, tb_size[0], &size[0], &next, &flags, 1);
1376 data = next;
1377 if (split) {
1378 ptr->precomp[1] = setup_pairs(data, tb_size[1], &size[3], &next, &flags, 1);
1379 data = next;
1380 } else
1381 ptr->precomp[1] = NULL;
1382
1383 ptr->precomp[0]->indextable = (char *)data;
1384 data += size[0];
1385 if (split) {
1386 ptr->precomp[1]->indextable = (char *)data;
1387 data += size[3];
1388 }
1389
1390 ptr->precomp[0]->sizetable = (ushort *)data;
1391 data += size[1];
1392 if (split) {
1393 ptr->precomp[1]->sizetable = (ushort *)data;
1394 data += size[4];
1395 }
1396
1397 data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
1398 ptr->precomp[0]->data = data;
1399 data += size[2];
1400 if (split) {
1401 data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
1402 ptr->precomp[1]->data = data;
1403 }
1404 } else {
1405 struct TBEntry_pawn *ptr = (struct TBEntry_pawn *)entry;
1406 s = 1 + (ptr->pawns[1] > 0);
1407 for (f = 0; f < 4; f++) {
1408 setup_pieces_pawn((struct TBEntry_pawn *)ptr, data, &tb_size[2 * f], f);
1409 data += ptr->num + s;
1410 }
1411 data += ((uintptr_t)data) & 0x01;
1412
1413 for (f = 0; f < files; f++) {
1414 ptr->file[f].precomp[0] = setup_pairs(data, tb_size[2 * f], &size[6 * f], &next, &flags, 1);
1415 data = next;
1416 if (split) {
1417 ptr->file[f].precomp[1] = setup_pairs(data, tb_size[2 * f + 1], &size[6 * f + 3], &next, &flags, 1);
1418 data = next;
1419 } else
1420 ptr->file[f].precomp[1] = NULL;
1421 }
1422
1423 for (f = 0; f < files; f++) {
1424 ptr->file[f].precomp[0]->indextable = (char *)data;
1425 data += size[6 * f];
1426 if (split) {
1427 ptr->file[f].precomp[1]->indextable = (char *)data;
1428 data += size[6 * f + 3];
1429 }
1430 }
1431
1432 for (f = 0; f < files; f++) {
1433 ptr->file[f].precomp[0]->sizetable = (ushort *)data;
1434 data += size[6 * f + 1];
1435 if (split) {
1436 ptr->file[f].precomp[1]->sizetable = (ushort *)data;
1437 data += size[6 * f + 4];
1438 }
1439 }
1440
1441 for (f = 0; f < files; f++) {
1442 data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
1443 ptr->file[f].precomp[0]->data = data;
1444 data += size[6 * f + 2];
1445 if (split) {
1446 data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
1447 ptr->file[f].precomp[1]->data = data;
1448 data += size[6 * f + 5];
1449 }
1450 }
1451 }
1452
1453 return 1;
1454}
1455
1456static int init_table_dtz(struct TBEntry *entry)
1457{
1458 ubyte *data = (ubyte *)entry->data;
1459 ubyte *next;
1460 int f, s;
1461 uint64 tb_size[4];
1462 uint64 size[4 * 3];
1463
1464 if (!data)
1465 return 0;
1466
1467 if (((uint32 *)data)[0] != DTZ_MAGIC) {
1468 printf("Corrupted table.\n");
1469 return 0;
1470 }
1471
1472 int files = data[4] & 0x02 ? 4 : 1;
1473
1474 data += 5;
1475
1476 if (!entry->has_pawns) {
1477 struct DTZEntry_piece *ptr = (struct DTZEntry_piece *)entry;
1478 setup_pieces_piece_dtz(ptr, data, &tb_size[0]);
1479 data += ptr->num + 1;
1480 data += ((uintptr_t)data) & 0x01;
1481
1482 ptr->precomp = setup_pairs(data, tb_size[0], &size[0], &next, &(ptr->flags), 0);
1483 data = next;
1484
1485 ptr->map = data;
1486 if (ptr->flags & 2) {
1487 int i;
1488 for (i = 0; i < 4; i++) {
1489 ptr->map_idx[i] = (ushort)(data + 1 - ptr->map);
1490 data += 1 + data[0];
1491 }
1492 data += ((uintptr_t)data) & 0x01;
1493 }
1494
1495 ptr->precomp->indextable = (char *)data;
1496 data += size[0];
1497
1498 ptr->precomp->sizetable = (ushort *)data;
1499 data += size[1];
1500
1501 data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
1502 ptr->precomp->data = data;
1503 data += size[2];
1504 } else {
1505 struct DTZEntry_pawn *ptr = (struct DTZEntry_pawn *)entry;
1506 s = 1 + (ptr->pawns[1] > 0);
1507 for (f = 0; f < 4; f++) {
1508 setup_pieces_pawn_dtz(ptr, data, &tb_size[f], f);
1509 data += ptr->num + s;
1510 }
1511 data += ((uintptr_t)data) & 0x01;
1512
1513 for (f = 0; f < files; f++) {
1514 ptr->file[f].precomp = setup_pairs(data, tb_size[f], &size[3 * f], &next, &(ptr->flags[f]), 0);
1515 data = next;
1516 }
1517
1518 ptr->map = data;
1519 for (f = 0; f < files; f++) {
1520 if (ptr->flags[f] & 2) {
1521 int i;
1522 for (i = 0; i < 4; i++) {
1523 ptr->map_idx[f][i] = (ushort)(data + 1 - ptr->map);
1524 data += 1 + data[0];
1525 }
1526 }
1527 }
1528 data += ((uintptr_t)data) & 0x01;
1529
1530 for (f = 0; f < files; f++) {
1531 ptr->file[f].precomp->indextable = (char *)data;
1532 data += size[3 * f];
1533 }
1534
1535 for (f = 0; f < files; f++) {
1536 ptr->file[f].precomp->sizetable = (ushort *)data;
1537 data += size[3 * f + 1];
1538 }
1539
1540 for (f = 0; f < files; f++) {
1541 data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
1542 ptr->file[f].precomp->data = data;
1543 data += size[3 * f + 2];
1544 }
1545 }
1546
1547 return 1;
1548}
1549
1550static ubyte decompress_pairs(struct PairsData *d, uint64 idx)
1551{
1552 if (!d->idxbits)
1553 return d->min_len;
1554
1555 uint32 mainidx = (uint32)(idx >> d->idxbits);
1556 int litidx = (idx & (((uint64)1 << d->idxbits) - 1)) - ((uint64)1 << (d->idxbits - 1));
1557 uint32 block = *(uint32 *)(d->indextable + 6 * mainidx);
1558 litidx += *(ushort *)(d->indextable + 6 * mainidx + 4);
1559 if (litidx < 0) {
1560 do {
1561 litidx += d->sizetable[--block] + 1;
1562 } while (litidx < 0);
1563 } else {
1564 while (litidx > d->sizetable[block])
1565 litidx -= d->sizetable[block++] + 1;
1566 }
1567
1568 uint32 *ptr = (uint32 *)(d->data + (block << d->blocksize));
1569
1570 int m = d->min_len;
1571 ushort *offset = d->offset;
1572 base_t *base = d->base - m;
1573 ubyte *symlen = d->symlen;
1574 int sym, bitcnt;
1575
1576#ifdef DECOMP64
1577 uint64 code = internal_bswap64(*((uint64 *)ptr));
1578 ptr += 2;
1579 bitcnt = 0; // number of "empty bits" in code
1580 for (;;) {
1581 int l = m;
1582 while (code < base[l]) l++;
1583 sym = offset[l] + ((code - base[l]) >> (64 - l));
1584 if (litidx < (int)symlen[sym] + 1) break;
1585 litidx -= (int)symlen[sym] + 1;
1586 code <<= l;
1587 bitcnt += l;
1588 if (bitcnt >= 32) {
1589 bitcnt -= 32;
1590 uint32 data = *ptr++;
1591 code |= ((uint64)(internal_bswap32(data))) << bitcnt;
1592 }
1593 }
1594#else
1595 uint32 next = 0;
1596 uint32 data = *ptr++;
1597 uint32 code = internal_bswap32(data);
1598 bitcnt = 0; // number of bits in next
1599 for (;;) {
1600 int l = m;
1601 while (code < base[l]) l++;
1602 sym = offset[l] + ((code - base[l]) >> (32 - l));
1603 if (litidx < (int)symlen[sym] + 1) break;
1604 litidx -= (int)symlen[sym] + 1;
1605 code <<= l;
1606 if (bitcnt < l) {
1607 if (bitcnt) {
1608 code |= (next >> (32 - l));
1609 l -= bitcnt;
1610 }
1611 data = *ptr++;
1612 next = internal_bswap32(data);
1613 bitcnt = 32;
1614 }
1615 code |= (next >> (32 - l));
1616 next <<= l;
1617 bitcnt -= l;
1618 }
1619#endif
1620
1621 ubyte *sympat = d->sympat;
1622 while (symlen[sym] != 0) {
1623 int w = *(int *)(sympat + 3 * sym);
1624 int s1 = w & 0x0fff;
1625 if (litidx < (int)symlen[s1] + 1)
1626 sym = s1;
1627 else {
1628 litidx -= (int)symlen[s1] + 1;
1629 sym = (w >> 12) & 0x0fff;
1630 }
1631 }
1632
1633 return *(sympat + 3 * sym);
1634}
1635
1636void load_dtz_table(char *str, uint64 key1, uint64 key2)
1637{
1638 int i;
1639 struct TBEntry *ptr, *ptr3;
1640 struct TBHashEntry *ptr2;
1641
1642 DTZ_table[0].key1 = key1;
1643 DTZ_table[0].key2 = key2;
1644 DTZ_table[0].entry = NULL;
1645
1646 // find corresponding WDL entry
1647 ptr2 = TB_hash[key1 >> (64 - TBHASHBITS)];
1648 for (i = 0; i < HSHMAX; i++)
1649 if (ptr2[i].key == key1) break;
1650 if (i == HSHMAX) return;
1651 ptr = ptr2[i].ptr;
1652
1653 ptr3 = (struct TBEntry *)malloc(ptr->has_pawns
1654 ? sizeof(struct DTZEntry_pawn)
1655 : sizeof(struct DTZEntry_piece));
1656
1657 ptr3->data = map_file(str, DTZSUFFIX, &ptr3->mapping);
1658 ptr3->key = ptr->key;
1659 ptr3->num = ptr->num;
1660 ptr3->symmetric = ptr->symmetric;
1661 ptr3->has_pawns = ptr->has_pawns;
1662 if (ptr3->has_pawns) {
1663 struct DTZEntry_pawn *entry = (struct DTZEntry_pawn *)ptr3;
1664 entry->pawns[0] = ((struct TBEntry_pawn *)ptr)->pawns[0];
1665 entry->pawns[1] = ((struct TBEntry_pawn *)ptr)->pawns[1];
1666 } else {
1667 struct DTZEntry_piece *entry = (struct DTZEntry_piece *)ptr3;
1668 entry->enc_type = ((struct TBEntry_piece *)ptr)->enc_type;
1669 }
1670 if (!init_table_dtz(ptr3))
1671 free(ptr3);
1672 else
1673 DTZ_table[0].entry = ptr3;
1674}
1675
1676static void free_wdl_entry(struct TBEntry *entry)
1677{
1678 unmap_file(entry->data, entry->mapping);
1679 if (!entry->has_pawns) {
1680 struct TBEntry_piece *ptr = (struct TBEntry_piece *)entry;
1681 free(ptr->precomp[0]);
1682 if (ptr->precomp[1])
1683 free(ptr->precomp[1]);
1684 } else {
1685 struct TBEntry_pawn *ptr = (struct TBEntry_pawn *)entry;
1686 int f;
1687 for (f = 0; f < 4; f++) {
1688 free(ptr->file[f].precomp[0]);
1689 if (ptr->file[f].precomp[1])
1690 free(ptr->file[f].precomp[1]);
1691 }
1692 }
1693}
1694
1695static void free_dtz_entry(struct TBEntry *entry)
1696{
1697 unmap_file(entry->data, entry->mapping);
1698 if (!entry->has_pawns) {
1699 struct DTZEntry_piece *ptr = (struct DTZEntry_piece *)entry;
1700 free(ptr->precomp);
1701 } else {
1702 struct DTZEntry_pawn *ptr = (struct DTZEntry_pawn *)entry;
1703 int f;
1704 for (f = 0; f < 4; f++)
1705 free(ptr->file[f].precomp);
1706 }
1707 free(entry);
1708}
1709
1710static int wdl_to_map[5] = { 1, 3, 0, 2, 0 };
1711static ubyte pa_flags[5] = { 8, 0, 0, 0, 4 };
1712
Definition tbcore.h:141
Definition tbcore.h:123
Definition tbcore.h:166
Definition tbcore.h:63
Definition tbcore.h:106
Definition tbcore.h:91
Definition tbcore.h:76
Definition tbcore.h:161