1 #ifndef WINCE
2 
3 #include <string.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #if !defined (DEBUG) && !defined(EBUG)
7 #define	NDEBUG 1
8 #endif
9 #include <assert.h>
10 
11 #if defined (_WIN32)
12 #include <windows.h>
13 #endif
14 
15 
16 // SMP stuff
17 
18 #if defined (SMP)
19 static	lock_t	LockLRU;
20 #else
21 #define	LockInit(x)
22 #define Lock(x)
23 #define UnLock(x)
24 #endif
25 
26 // Declarations
27 
28 typedef unsigned	char BYTE;
29 typedef unsigned	long ULONG;
30 typedef	signed		char tb_t;
31 
32 #if !defined (COLOR_DECLARED)
33 typedef	int	color;
34 #define	x_colorWhite	0
35 #define	x_colorBlack	1
36 #define	x_colorNeutral	2
37 #define COLOR_DECLARED
38 #endif
39 
40 #if !defined (PIECES_DECLARED)
41 typedef	int	piece;
42 #define	x_pieceNone		0
43 #define	x_piecePawn		1
44 #define	x_pieceKnight	2
45 #define	x_pieceBishop	3
46 #define	x_pieceRook		4
47 #define	x_pieceQueen	5
48 #define	x_pieceKing		6
49 #define PIECES_DECLARED
50 #endif
51 
52 #if !defined (SqFind2)
53 #define	SqFind2(psq,pi1,sq1,pi2,sq2)	sq1=SqFindFirst(psq,pi1);sq2=SqFindFirst(psq,pi2);
54 #endif
55 
56 // Machine and compiler-specific declarations
57 
58 #if defined (_MSC_VER)
59 
60 #undef	TB_CDECL
61 #define	TB_CDECL	__cdecl
62 #define	TB_FASTCALL	__fastcall
63 #if _MSC_VER >= 1200
64 #define	INLINE		__forceinline
65 #endif
66 
67 #else
68 
69 #define	TB_CDECL
70 #define	TB_FASTCALL
71 
72 #endif
73 
74 #if !defined (INLINE)
75 #define	INLINE	inline
76 #endif
77 
78 // Some constants from SJE program
79 
80 #define pageL 256
81 
82 /* tablebase byte entry semispan length */
83 
84 #define tbbe_ssL ((pageL - 4) / 2)
85 
86 /* tablebase signed byte entry values */
87 
88 #define bev_broken  (tbbe_ssL + 1)  /* illegal or busted */
89 
90 #define bev_mi1     tbbe_ssL        /* mate in 1 move */
91 #define bev_mimin   1               /* mate in 126 moves */
92 
93 #define bev_draw    0               /* draw */
94 
95 #define bev_limax   (-1)            /* mated in 125 moves */
96 #define bev_li0     (-tbbe_ssL)     /* mated in 0 moves */
97 
98 #define	bev_limaxx	(-tbbe_ssL - 1)	/* mated in 126 moves */
99 #define	bev_miminx	(-tbbe_ssL - 2)	/* mate in 127 moves */
100 
101 // Some constants for 16-bit tables
102 
103 #define L_pageL 65536
104 
105 /* tablebase short entry semispan length */
106 
107 #define L_tbbe_ssL ((L_pageL - 4) / 2)
108 
109 /* tablebase signed short entry values */
110 
111 #define L_bev_broken  (L_tbbe_ssL + 1)		/* illegal or busted */
112 
113 #define L_bev_mi1     L_tbbe_ssL			/* mate in 1 move */
114 #define L_bev_mimin   1						/* mate in 32766 moves */
115 
116 #define L_bev_draw    0						/* draw */
117 
118 #define L_bev_limax   (-1)					/* mated in 32765 moves */
119 #define L_bev_li0     (-L_tbbe_ssL)			/* mated in 0 moves */
120 
121 #define	L_bev_limaxx	(-L_tbbe_ssL - 1)	/* mated in 32766 moves */
122 #define	L_bev_miminx	(-L_tbbe_ssL - 2)	/* mate in 32767 moves */
123 
124 // Conversion from 8-bit to 16-bit score
125 // UNDONE: Maybe implement via lookup table?
126 
127 #define	S_to_L(tbt)\
128 	(\
129 	 (0 == tbt) ? 0:\
130 	 (tbt > 0) ? (bev_broken != tbt ? tbt + 32640 : L_bev_broken):\
131 	 (tbt >= bev_li0) ? tbt - 32640:\
132 	 (bev_limaxx == tbt) ? -32640:\
133 	 /*bev_miminx == tbt*/  32640\
134 	)
135 
136 // Constants
137 
138 #define	i8	((INDEX) 8)
139 #define	i14	((INDEX) 14)
140 #define	i44	((INDEX) 44)
141 #define	i46	((INDEX) 46)
142 #define	i47	((INDEX) 47)
143 #define	i48	((INDEX) 48)
144 #define	i58	((INDEX) 58)
145 #define	i60	((INDEX) 60)
146 #define	i61	((INDEX) 61)
147 #define	i62	((INDEX) 62)
148 #define	i63	((INDEX) 63)
149 #define	i64	((INDEX) 64)
150 
151 #define x_row_1 0
152 #define x_row_2 1
153 #define x_row_3 2
154 #define x_row_4 3
155 #define x_row_5 4
156 #define x_row_6 5
157 #define x_row_7 6
158 #define x_row_8 7
159 
160 #define x_column_a 0
161 #define x_column_b 1
162 #define x_column_c 2
163 #define x_column_d 3
164 #define x_column_e 4
165 #define x_column_f 5
166 #define x_column_g 6
167 #define x_column_h 7
168 
169 /* reflection macros */
170 
171 #define reflect_x(sq) ((sq) ^ 0x38)
172 #define reflect_y(sq) ((sq) ^ 0x07)
173 #define reflect_xy(sq) rgsqReflectXY[sq]
174 
175 static const square rgsqReflectXY [] =
176 {
177   0,  8, 16, 24, 32, 40, 48, 56,
178   1,  9, 17, 25, 33, 41, 49, 57,
179   2, 10, 18, 26, 34, 42, 50, 58,
180   3, 11, 19, 27, 35, 43, 51, 59,
181   4, 12, 20, 28, 36, 44, 52, 60,
182   5, 13, 21, 29, 37, 45, 53, 61,
183   6, 14, 22, 30, 38, 46, 54, 62,
184   7, 15, 23, 31, 39, 47, 55, 63,
185 };
186 
187 static const square rgsqReflectMaskY [] =
188 {
189  0, 0, 0, 0, 7, 7, 7, 7,
190  0, 0, 0, 0, 7, 7, 7, 7,
191  0, 0, 0, 0, 7, 7, 7, 7,
192  0, 0, 0, 0, 7, 7, 7, 7,
193  0, 0, 0, 0, 7, 7, 7, 7,
194  0, 0, 0, 0, 7, 7, 7, 7,
195  0, 0, 0, 0, 7, 7, 7, 7,
196  0, 0, 0, 0, 7, 7, 7, 7,
197 };
198 
199 static const square rgsqReflectMaskYandX [] =
200 {
201  0, 0, 0, 0, 7, 7, 7, 7,
202  0, 0, 0, 0, 7, 7, 7, 7,
203  0, 0, 0, 0, 7, 7, 7, 7,
204  0, 0, 0, 0, 7, 7, 7, 7,
205  0x38, 0x38, 0x38, 0x38, 0x38+7, 0x38+7, 0x38+7, 0x38+7,
206  0x38, 0x38, 0x38, 0x38, 0x38+7, 0x38+7, 0x38+7, 0x38+7,
207  0x38, 0x38, 0x38, 0x38, 0x38+7, 0x38+7, 0x38+7, 0x38+7,
208  0x38, 0x38, 0x38, 0x38, 0x38+7, 0x38+7, 0x38+7, 0x38+7,
209 };
210 
211 static const square rgsqReflectInvertMask[] = { 0, 0x38 };
212 
213 /* useful macros */
214 
215 #define	TbRow(sq)				((sq) >> 3)
216 #define	TbColumn(sq)			((sq) & 7)
217 
218 #if defined (NEW)
219 #define	PchExt(side) ((x_colorWhite == side) ? ".nbw" : ".nbb")
220 #else
221 #define	PchExt(side) ((x_colorWhite == side) ? ".tbw" : ".tbb")
222 #endif
223 
224 // Verbose levels
225 
226 static bool		fPrint = false;		// Print some technical statistics
227 static bool		fVerbose = false;	// Print additional information
228 
229 // Malloc that checks for out-of-memory condition
230 
231 static unsigned long cbAllocated;
232 
PvMalloc(unsigned long cb)233 static void* PvMalloc
234 	(
235 	unsigned long cb
236 	)
237 	{
238 	void	*pv;
239 
240 #ifdef WINCE
241   pv = my_Tcl_Alloc (cb);
242 #else
243   pv = malloc (cb);
244 #endif
245 	if (NULL == pv)
246 		{
247 		printf("*** Cannot allocate %lu bytes of memory\n", cb);
248 		exit (1);
249 		}
250 	cbAllocated += cb;
251 	return pv;
252 	}
253 
254 #if defined (NEW)	// New index schema ----------------------------------------
255 
256 // 'Invalid' value have to be large, so index
257 // of invalid position will be very large, too.
258 
259 #define	INF	4000
260 
261 // Enumeration: valid positions with 2 kings on board; white king restricted to
262 // a1-d1-d4 triangle; also, if it's at a1-d4 half-diagonal, then black king
263 // must be in a1-h1-h8 triangle
264 
265 static const short rgsTriKings [64 * 64] =
266 {
267  INF, INF,   0,   1,   2,   3,   4,   5, INF, INF,   6,   7,   8,   9,  10,  11,
268  INF, INF,  12,  13,  14,  15,  16,  17, INF, INF, INF,  18,  19,  20,  21,  22,
269  INF, INF, INF, INF,  23,  24,  25,  26, INF, INF, INF, INF, INF,  27,  28,  29,
270  INF, INF, INF, INF, INF, INF,  30,  31, INF, INF, INF, INF, INF, INF, INF,  32,
271  INF, INF, INF,  33,  34,  35,  36,  37, INF, INF, INF,  38,  39,  40,  41,  42,
272   43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,
273   59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,
274   75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
275   91, INF, INF, INF,  92,  93,  94,  95,  96, INF, INF, INF,  97,  98,  99, 100,
276  101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
277  117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
278  133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
279  149, 150, INF, INF, INF, 151, 152, 153, 154, 155, INF, INF, INF, 156, 157, 158,
280  159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
281  175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
282  191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
283  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
284  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
285  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
286  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
287  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
288  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
289  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
290  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
291  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
292  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
293  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
294  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
295  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
296  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
297  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
298  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
299  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
300  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
301  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
302  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
303  INF, INF, INF, 207, 208, 209, 210, 211, INF, INF, INF, 212, 213, 214, 215, 216,
304  INF, INF, INF, 217, 218, 219, 220, 221, INF, INF, INF, 222, 223, 224, 225, 226,
305  INF, INF, INF, INF, 227, 228, 229, 230, INF, INF, INF, INF, INF, 231, 232, 233,
306  INF, INF, INF, INF, INF, INF, 234, 235, INF, INF, INF, INF, INF, INF, INF, 236,
307  237, INF, INF, INF, 238, 239, 240, 241, 242, INF, INF, INF, 243, 244, 245, 246,
308  247, INF, INF, INF, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
309  260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
310  276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
311  292, 293, INF, INF, INF, 294, 295, 296, 297, 298, INF, INF, INF, 299, 300, 301,
312  302, 303, INF, INF, INF, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
313  315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330,
314  331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346,
315  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
316  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
317  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
318  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
319  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
320  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
321  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
322  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
323  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
324  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
325  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
326  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
327  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
328  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
329  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
330  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
331  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
332  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
333  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
334  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
335  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
336  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
337  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
338  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
339  347, 348, 349, 350, 351, 352, 353, 354, INF, INF, INF, INF, 355, 356, 357, 358,
340  INF, INF, INF, INF, 359, 360, 361, 362, INF, INF, INF, INF, 363, 364, 365, 366,
341  INF, INF, INF, INF, 367, 368, 369, 370, INF, INF, INF, INF, INF, 371, 372, 373,
342  INF, INF, INF, INF, INF, INF, 374, 375, INF, INF, INF, INF, INF, INF, INF, 376,
343  377, 378, 379, 380, 381, 382, 383, 384, 385, 386, INF, INF, INF, 387, 388, 389,
344  390, 391, INF, INF, INF, 392, 393, 394, 395, 396, INF, INF, INF, 397, 398, 399,
345  400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415,
346  416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431,
347  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
348  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
349  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
350  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
351  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
352  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
353  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
354  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
355  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
356  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
357  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
358  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
359  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
360  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
361  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
362  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
363  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
364  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
365  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
366  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
367  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
368  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
369  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
370  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
371  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
372  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
373  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
374  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
375  432, 433, 434, 435, 436, 437, 438, 439, INF, 440, 441, 442, 443, 444, 445, 446,
376  INF, INF, INF, INF, INF, 447, 448, 449, INF, INF, INF, INF, INF, 450, 451, 452,
377  INF, INF, INF, INF, INF, 453, 454, 455, INF, INF, INF, INF, INF, 456, 457, 458,
378  INF, INF, INF, INF, INF, INF, 459, 460, INF, INF, INF, INF, INF, INF, INF, 461,
379  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
380  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
381  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
382  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
383  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
384  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
385  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
386  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
387  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
388  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
389  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
390  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
391  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
392  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
393  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
394  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
395  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
396  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
397  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
398  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
399  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
400  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
401  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
402  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
403  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
404  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
405  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
406  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
407  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
408  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
409  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
410  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
411  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
412  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
413  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
414  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
415  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
416  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
417  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
418  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
419  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
420  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
421  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
422  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
423  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
424  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
425  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
426  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
427  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
428  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
429  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
430  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
431  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
432  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
433  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
434  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
435  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
436  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
437  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
438  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
439  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
440  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
441  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
442  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
443  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
444  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
445  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
446  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
447  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
448  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
449  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
450  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
451  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
452  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
453  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
454  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
455  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
456  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
457  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
458  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
459  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
460  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
461  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
462  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
463  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
464  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
465  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
466  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
467  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
468  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
469  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
470  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
471  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
472  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
473  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
474  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
475  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
476  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
477  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
478  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
479  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
480  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
481  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
482  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
483  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
484  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
485  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
486  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
487  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
488  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
489  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
490  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
491  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
492  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
493  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
494  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
495  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
496  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
497  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
498  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
499  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
500  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
501  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
502  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
503  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
504  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
505  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
506  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
507  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
508  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
509  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
510  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
511  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
512  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
513  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
514  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
515  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
516  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
517  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
518  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
519  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
520  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
521  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
522  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
523 };
524 
525 // Enumeration: all valid positions with 2 kings on board when white king
526 // restricted to left half of the board
527 
528 static const short rgsHalfKings [64 * 64] =
529 {
530  INF, INF,   0,   1,   2,   3,   4,   5, INF, INF,   6,   7,   8,   9,  10,  11,
531   12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,
532   28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,
533   44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
534  INF, INF, INF,  60,  61,  62,  63,  64, INF, INF, INF,  65,  66,  67,  68,  69,
535   70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,
536   86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99, 100, 101,
537  102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
538  118, INF, INF, INF, 119, 120, 121, 122, 123, INF, INF, INF, 124, 125, 126, 127,
539  128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
540  144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
541  160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
542  176, 177, INF, INF, INF, 178, 179, 180, 181, 182, INF, INF, INF, 183, 184, 185,
543  186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
544  202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217,
545  218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
546  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
547  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
548  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
549  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
550  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
551  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
552  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
553  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
554  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
555  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
556  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
557  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
558  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
559  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
560  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
561  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
562  INF, INF, 234, 235, 236, 237, 238, 239, INF, INF, 240, 241, 242, 243, 244, 245,
563  INF, INF, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
564  260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
565  276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
566  INF, INF, INF, 292, 293, 294, 295, 296, INF, INF, INF, 297, 298, 299, 300, 301,
567  INF, INF, INF, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
568  315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330,
569  331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346,
570  347, INF, INF, INF, 348, 349, 350, 351, 352, INF, INF, INF, 353, 354, 355, 356,
571  357, INF, INF, INF, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369,
572  370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385,
573  386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401,
574  402, 403, INF, INF, INF, 404, 405, 406, 407, 408, INF, INF, INF, 409, 410, 411,
575  412, 413, INF, INF, INF, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424,
576  425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440,
577  441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456,
578  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
579  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
580  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
581  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
582  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
583  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
584  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
585  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
586  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
587  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
588  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
589  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
590  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
591  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
592  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
593  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
594  457, 458, 459, 460, 461, 462, 463, 464, INF, INF, 465, 466, 467, 468, 469, 470,
595  INF, INF, 471, 472, 473, 474, 475, 476, INF, INF, 477, 478, 479, 480, 481, 482,
596  483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498,
597  499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514,
598  515, 516, 517, 518, 519, 520, 521, 522, INF, INF, INF, 523, 524, 525, 526, 527,
599  INF, INF, INF, 528, 529, 530, 531, 532, INF, INF, INF, 533, 534, 535, 536, 537,
600  538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553,
601  554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569,
602  570, 571, 572, 573, 574, 575, 576, 577, 578, INF, INF, INF, 579, 580, 581, 582,
603  583, INF, INF, INF, 584, 585, 586, 587, 588, INF, INF, INF, 589, 590, 591, 592,
604  593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608,
605  609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624,
606  625, 626, 627, 628, 629, 630, 631, 632, 633, 634, INF, INF, INF, 635, 636, 637,
607  638, 639, INF, INF, INF, 640, 641, 642, 643, 644, INF, INF, INF, 645, 646, 647,
608  648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663,
609  664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679,
610  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
611  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
612  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
613  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
614  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
615  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
616  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
617  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
618  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
619  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
620  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
621  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
622  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
623  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
624  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
625  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
626  680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695,
627  INF, INF, 696, 697, 698, 699, 700, 701, INF, INF, 702, 703, 704, 705, 706, 707,
628  INF, INF, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721,
629  722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737,
630  738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753,
631  INF, INF, INF, 754, 755, 756, 757, 758, INF, INF, INF, 759, 760, 761, 762, 763,
632  INF, INF, INF, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776,
633  777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792,
634  793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808,
635  809, INF, INF, INF, 810, 811, 812, 813, 814, INF, INF, INF, 815, 816, 817, 818,
636  819, INF, INF, INF, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831,
637  832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847,
638  848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863,
639  864, 865, INF, INF, INF, 866, 867, 868, 869, 870, INF, INF, INF, 871, 872, 873,
640  874, 875, INF, INF, INF, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886,
641  887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902,
642  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
643  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
644  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
645  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
646  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
647  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
648  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
649  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
650  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
651  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
652  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
653  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
654  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
655  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
656  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
657  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
658  903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918,
659  919, 920, 921, 922, 923, 924, 925, 926, INF, INF, 927, 928, 929, 930, 931, 932,
660  INF, INF, 933, 934, 935, 936, 937, 938, INF, INF, 939, 940, 941, 942, 943, 944,
661  945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960,
662  961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976,
663  977, 978, 979, 980, 981, 982, 983, 984, INF, INF, INF, 985, 986, 987, 988, 989,
664  INF, INF, INF, 990, 991, 992, 993, 994, INF, INF, INF, 995, 996, 997, 998, 999,
665 1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,
666 1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,
667 1032,1033,1034,1035,1036,1037,1038,1039,1040, INF, INF, INF,1041,1042,1043,1044,
668 1045, INF, INF, INF,1046,1047,1048,1049,1050, INF, INF, INF,1051,1052,1053,1054,
669 1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,
670 1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,
671 1087,1088,1089,1090,1091,1092,1093,1094,1095,1096, INF, INF, INF,1097,1098,1099,
672 1100,1101, INF, INF, INF,1102,1103,1104,1105,1106, INF, INF, INF,1107,1108,1109,
673 1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,
674  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
675  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
676  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
677  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
678  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
679  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
680  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
681  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
682  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
683  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
684  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
685  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
686  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
687  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
688  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
689  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
690 1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,
691 1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,
692  INF, INF,1158,1159,1160,1161,1162,1163, INF, INF,1164,1165,1166,1167,1168,1169,
693  INF, INF,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,
694 1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,
695 1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,
696  INF, INF, INF,1216,1217,1218,1219,1220, INF, INF, INF,1221,1222,1223,1224,1225,
697  INF, INF, INF,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,
698 1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,
699 1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,
700 1271, INF, INF, INF,1272,1273,1274,1275,1276, INF, INF, INF,1277,1278,1279,1280,
701 1281, INF, INF, INF,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,
702 1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,
703 1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,
704 1326,1327, INF, INF, INF,1328,1329,1330,1331,1332, INF, INF, INF,1333,1334,1335,
705 1336,1337, INF, INF, INF,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,
706  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
707  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
708  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
709  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
710  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
711  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
712  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
713  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
714  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
715  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
716  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
717  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
718  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
719  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
720  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
721  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
722 1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,
723 1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,
724 1381,1382,1383,1384,1385,1386,1387,1388, INF, INF,1389,1390,1391,1392,1393,1394,
725  INF, INF,1395,1396,1397,1398,1399,1400, INF, INF,1401,1402,1403,1404,1405,1406,
726 1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,
727 1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,
728 1439,1440,1441,1442,1443,1444,1445,1446, INF, INF, INF,1447,1448,1449,1450,1451,
729  INF, INF, INF,1452,1453,1454,1455,1456, INF, INF, INF,1457,1458,1459,1460,1461,
730 1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,
731 1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,
732 1494,1495,1496,1497,1498,1499,1500,1501,1502, INF, INF, INF,1503,1504,1505,1506,
733 1507, INF, INF, INF,1508,1509,1510,1511,1512, INF, INF, INF,1513,1514,1515,1516,
734 1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,
735 1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,
736 1549,1550,1551,1552,1553,1554,1555,1556,1557,1558, INF, INF, INF,1559,1560,1561,
737 1562,1563, INF, INF, INF,1564,1565,1566,1567,1568, INF, INF, INF,1569,1570,1571,
738  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
739  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
740  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
741  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
742  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
743  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
744  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
745  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
746  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
747  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
748  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
749  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
750  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
751  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
752  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
753  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
754 1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,
755 1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,
756 1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,
757  INF, INF,1620,1621,1622,1623,1624,1625, INF, INF,1626,1627,1628,1629,1630,1631,
758 1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,
759 1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,
760 1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,
761  INF, INF, INF,1680,1681,1682,1683,1684, INF, INF, INF,1685,1686,1687,1688,1689,
762 1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,
763 1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,
764 1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,
765 1738, INF, INF, INF,1739,1740,1741,1742,1743, INF, INF, INF,1744,1745,1746,1747,
766 1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,
767 1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,
768 1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,
769 1796,1797, INF, INF, INF,1798,1799,1800,1801,1802, INF, INF, INF,1803,1804,1805,
770  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
771  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
772  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
773  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
774  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
775  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
776  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
777  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
778  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
779  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
780  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
781  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
782  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
783  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
784  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
785  INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF,
786 };
787 
788 // Useful macro and enumeration tables
789 
790 #define	IndTriKings(sqk1,sqk2)	((INDEX) rgsTriKings[sqk1*64+sqk2])
791 #define	IndHalfKings(sqk1,sqk2)	((INDEX) rgsHalfKings[sqk1*64+sqk2])
792 
793 static const bool rgfTriangle[64] =
794 {
795 	 true,  true,  true,  true,  false, false, false, false,
796 	 false, true,  true,  true,  false, false, false, false,
797 	 false, false, true,  true,  false, false, false, false,
798 	 false, false, false, true,  false, false, false, false,
799 	 false, false, false, false, false, false, false, false,
800 	 false, false, false, false, false, false, false, false,
801 	 false, false, false, false, false, false, false, false,
802 	 false, false, false, false, false, false, false, false,
803 };
804 
805 static const bool rgfNotDiagonal[64] =
806 {
807 	 false, true,  true,  true,  true,  true,  true,  true,
808 	 true,  false, true,  true,  true,  true,  true,  true,
809 	 true,  true,  false, true,  true,  true,  true,  true,
810 	 true,  true,  true,  false, true,  true,  true,  true,
811 	 true,  true,  true,  true,  false, true,  true,  true,
812 	 true,  true,  true,  true,  true,  false, true,  true,
813 	 true,  true,  true,  true,  true,  true,  false, true,
814 	 true,  true,  true,  true,  true,  true,  true,  false,
815 };
816 
817 static const bool rgfInLargeTriangle[64] =
818 {
819 	 true,  true,  true,  true,  true,  true,  true,  true,
820 	 false, true,  true,  true,  true,  true,  true,  true,
821 	 false, false, true,  true,  true,  true,  true,  true,
822 	 false, false, false, true,  true,  true,  true,  true,
823 	 false, false, false, false, true,  true,  true,  true,
824 	 false, false, false, false, false, true,  true,  true,
825 	 false, false, false, false, false, false, true,  true,
826 	 false, false, false, false, false, false, false, true,
827 };
828 
829 #define	FInTriangle(sqwk,sqbk)	(rgfTriangle[sqwk] & (rgfNotDiagonal[sqwk]|rgfInLargeTriangle[sqbk]))
830 
831 // Sort pieces
832 
833 #define	SORT(sq1,sq2)	if (sq1>sq2) { square sqTmp; sqTmp=sq1; sq1=sq2; sq2=sqTmp; }
834 
835 // Exclude occupied squares
836 
837 #define	EXCLUDE1(sq,sq1)						(sq-(sq>sq1))
838 #define	EXCLUDE2(sq,sq1,sq2)					(sq-((sq>sq1)+(sq>sq2)))
839 #define	EXCLUDE3(sq,sq1,sq2,sq3)				(sq-((sq>sq1)+(sq>sq2)+(sq>sq3)))
840 #define	EXCLUDE4(sq,sq1,sq2,sq3,sq4)			(sq-((sq>sq1)+(sq>sq2)+(sq>sq3)+(sq>sq4)))
841 #define	EXCLUDE6(sq,sq1,sq2,sq3,sq4,sq5,sq6)	(sq-((sq>sq1)+(sq>sq2)+(sq>sq3)+(sq>sq4)+(sq>sq5)+(sq>sq6)))
842 
843 // Calculate index - a lot of functions...
844 
845 // Enumeration tables
846 
847 static BYTE		*rgprgsqPiece[6];	// Enumeration for each piece (0 - black pawn)
848 									// For each position of the King, all legal squares
849 									// of the opposite piece enumerated
850 static BYTE		rgcLegal[6][64];	// # of enumerated positions for each piece and each
851 									// location of enemy king
852 
853 // Enumerations - indexed by [piece] and [kings enumeration].
854 // In each table for each [piece] and [king enumeration] we store # of preceding positions.
855 
856 static ULONG	*rgprgulSinglePawnless[6];
857 static ULONG	*rgprgulPairPawnless[6][6];
858 #if defined (T41_INCLUDE)
859 static ULONG	*rgprgulTriplePawnless[6][6][6];
860 #endif
861 static ULONG	*rgprgulSinglePawnPresent[6];
862 static ULONG	*rgprgulPairPawnPresent[6][6];
863 #if defined (T41_INCLUDE)
864 static ULONG	*rgprgulTriplePawnPresent[6][6][6];
865 #endif
866 
867 // Total # of enumerated positions
868 
869 static ULONG	rgcSinglePawnPresent[6];
870 static ULONG	rgcSinglePawnless[6];
871 static ULONG	rgcPairPawnPresent[6][6];
872 static ULONG	rgcPairPawnless[6][6];
873 #if defined (T41_INCLUDE)
874 static ULONG	rgcTriplePawnPresent[6][6][6];
875 static ULONG	rgcTriplePawnless[6][6][6];
876 #endif
877 
878 // Infinities. Have to be larger than any legal enumeration yet small enough
879 // so there will be no overflow when combining them with remaining pieces.
880 
881 #define	INF_SINGLE	(110000)
882 #define	INF_PAIR	(6500000)
883 #define	INF_TRIPLE	(300000000)
884 
885 // Initialize squares and counters table for one piece.
886 // Piece can be x_pieceNone - that means 'pawn of the wrong color', e.g. KPK BTM.
887 
VInitSquaresTable(piece pi,BYTE * prgsqPiece,BYTE * prgcLegal)888 static void VInitSquaresTable
889 	(
890 	piece	pi,
891 	BYTE	*prgsqPiece,
892 	BYTE	*prgcLegal
893 	)
894 	{
895 	int	sqLo, sqHi;
896 
897 	memset (prgsqPiece, -1, 64*64);
898 	sqLo = 0;
899 	sqHi = 64;
900 	if (pi <= x_piecePawn)
901 		{
902 		sqLo = 8;
903 		sqHi = 56;
904 		}
905 	for (int sqKing = 0; sqKing < 64; sqKing ++)
906 		{
907 		int	iPiece;
908 
909 		iPiece = 0;
910 		for (int sq = sqLo; sq < sqHi; sq ++)
911 			{
912 			if (sq == sqKing)
913 				continue;
914 			switch (pi)
915 				{
916 			case x_piecePawn:
917 				if (
918 					( 0 != TbColumn (sq) && sqKing == sq+7 ) ||
919 					( 7 != TbColumn (sq) && sqKing == sq+9 )
920 				   )
921 				   continue;
922 				break;
923 			case x_pieceKnight:
924 				if (
925 					( TbRow (sq) >= 2 && TbColumn (sq) >= 1 && sqKing == sq-17 ) ||
926 					( TbRow (sq) >= 2 && TbColumn (sq) <= 6 && sqKing == sq-15 ) ||
927 					( TbRow (sq) >= 1 && TbColumn (sq) >= 2 && sqKing == sq-10 ) ||
928 					( TbRow (sq) >= 1 && TbColumn (sq) <= 5 && sqKing == sq-6 ) ||
929 					( TbRow (sq) <= 6 && TbColumn (sq) >= 2 && sqKing == sq+6 ) ||
930 					( TbRow (sq) <= 6 && TbColumn (sq) <= 5 && sqKing == sq+10 ) ||
931 					( TbRow (sq) <= 5 && TbColumn (sq) >= 1 && sqKing == sq+15 ) ||
932 					( TbRow (sq) <= 5 && TbColumn (sq) <= 6 && sqKing == sq+17 )
933 				   )
934 					continue;
935 				break;
936 			case x_pieceBishop:
937 				if (
938 					( 0 != TbRow (sq) && 0 != TbColumn (sq) && sqKing == sq-9 ) ||
939 					( 0 != TbRow (sq) && 7 != TbColumn (sq) && sqKing == sq-7 ) ||
940 					( 7 != TbRow (sq) && 0 != TbColumn (sq) && sqKing == sq+7 ) ||
941 					( 7 != TbRow (sq) && 7 != TbColumn (sq) && sqKing == sq+9 )
942 				   )
943 					continue;
944 				break;
945 			case x_pieceRook:
946 				if (
947 					( 0 != TbColumn (sq) && sqKing == sq-1 ) ||
948 					( 7 != TbColumn (sq) && sqKing == sq+1 ) ||
949 					( 0 != TbRow (sq) && sqKing == sq-8 ) ||
950 					( 7 != TbRow (sq) && sqKing == sq+8 )
951 				   )
952 					continue;
953 				break;
954 			case x_pieceQueen:
955 				if (
956 					( 0 != TbColumn (sq) && sqKing == sq-1 ) ||
957 					( 7 != TbColumn (sq) && sqKing == sq+1 ) ||
958 					( 0 != TbRow (sq) && sqKing == sq-8 ) ||
959 					( 7 != TbRow (sq) && sqKing == sq+8 ) ||
960 					( 0 != TbRow (sq) && 0 != TbColumn (sq) && sqKing == sq-9 ) ||
961 					( 0 != TbRow (sq) && 7 != TbColumn (sq) && sqKing == sq-7 ) ||
962 					( 7 != TbRow (sq) && 0 != TbColumn (sq) && sqKing == sq+7 ) ||
963 					( 7 != TbRow (sq) && 7 != TbColumn (sq) && sqKing == sq+9 )
964 				   )
965 					continue;
966 				break;
967 				}
968 			prgsqPiece[sqKing*64+sq] = (BYTE) iPiece;
969 			iPiece ++;
970 			}
971 		prgcLegal[sqKing] = (BYTE) iPiece;
972 		}
973 	}
974 
975 // Initialize enumeration table for single piece
976 
VInitSingle(ULONG * prgIndex,const short * prgsKings,const BYTE * prgcLegal,const BYTE * prgsqPiece,ULONG * pcEnumeration)977 static void VInitSingle
978 	(
979 	ULONG		*prgIndex,
980 	const short	*prgsKings,
981 	const BYTE	*prgcLegal,
982 	const BYTE	*prgsqPiece,
983 	ULONG		*pcEnumeration
984 	)
985 	{
986 	ULONG iIndex;
987 
988 	iIndex = 0;
989 	for (int sqKing1 = 0; sqKing1 < 64; sqKing1 ++)
990 		for (int sqKing2 = 0; sqKing2 < 64; sqKing2 ++)
991 			{
992 			if (INF != prgsKings[sqKing1*64+sqKing2])
993 				{
994 				prgIndex[prgsKings[sqKing1*64+sqKing2]] = iIndex;
995 				iIndex += prgcLegal[sqKing2] - ((BYTE) -1 != prgsqPiece[sqKing2*64+sqKing1]);
996 				}
997 			}
998 	*pcEnumeration = iIndex;
999 	}
1000 
1001 // Initialize enumeration table for pair of pieces
1002 
VInitPair(ULONG * prgIndex,const short * prgsKings,const BYTE * prgcLegal1,const BYTE * prgsqPiece1,const BYTE * prgcLegal2,const BYTE * prgsqPiece2,ULONG * pcEnumeration)1003 static void VInitPair
1004 	(
1005 	ULONG		*prgIndex,
1006 	const short	*prgsKings,
1007 	const BYTE	*prgcLegal1,
1008 	const BYTE	*prgsqPiece1,
1009 	const BYTE	*prgcLegal2,
1010 	const BYTE	*prgsqPiece2,
1011 	ULONG		*pcEnumeration
1012 	)
1013 	{
1014 	ULONG iIndex;
1015 	ULONG cPositions1, cPositions2;
1016 
1017 	iIndex = 0;
1018 	for (int sqKing1 = 0; sqKing1 < 64; sqKing1 ++)
1019 		for (int sqKing2 = 0; sqKing2 < 64; sqKing2 ++)
1020 			{
1021 			if (INF != prgsKings[sqKing1*64+sqKing2])
1022 				{
1023 				prgIndex[prgsKings[sqKing1*64+sqKing2]] = iIndex;
1024 				cPositions1 = prgcLegal1[sqKing2] - ((BYTE) -1 != prgsqPiece1[sqKing2*64+sqKing1]);
1025 				if (prgcLegal1 == prgcLegal2)
1026 					iIndex += cPositions1*(cPositions1-1)/2;
1027 				else
1028 					{
1029 					cPositions2 = prgcLegal2[sqKing2] - ((BYTE) -1 != prgsqPiece2[sqKing2*64+sqKing1]);
1030 					iIndex += cPositions1*cPositions2;
1031 					}
1032 				}
1033 			}
1034 	*pcEnumeration = iIndex;
1035 	}
1036 
1037 #if defined (T41_INCLUDE)
1038 
1039 // Initialize enumeration table for triple piece
1040 
VInitTriple(ULONG * prgIndex,const short * prgsKings,const BYTE * prgcLegal1,const BYTE * prgsqPiece1,const BYTE * prgcLegal2,const BYTE * prgsqPiece2,const BYTE * prgcLegal3,const BYTE * prgsqPiece3,ULONG * pcEnumeration)1041 static void VInitTriple
1042 	(
1043 	ULONG		*prgIndex,
1044 	const short	*prgsKings,
1045 	const BYTE	*prgcLegal1,
1046 	const BYTE	*prgsqPiece1,
1047 	const BYTE	*prgcLegal2,
1048 	const BYTE	*prgsqPiece2,
1049 	const BYTE	*prgcLegal3,
1050 	const BYTE	*prgsqPiece3,
1051 	ULONG		*pcEnumeration
1052 	)
1053 	{
1054 	ULONG iIndex;
1055 	ULONG cPositions1, cPositions2, cPositions3;
1056 
1057 	iIndex = 0;
1058 	for (int sqKing1 = 0; sqKing1 < 64; sqKing1 ++)
1059 		for (int sqKing2 = 0; sqKing2 < 64; sqKing2 ++)
1060 			{
1061 			if (INF != prgsKings[sqKing1*64+sqKing2])
1062 				{
1063 				prgIndex[prgsKings[sqKing1*64+sqKing2]] = iIndex;
1064 				cPositions1 = prgcLegal1[sqKing2] - ((BYTE) -1 != prgsqPiece1[sqKing2*64+sqKing1]);
1065 				if (prgcLegal1 == prgcLegal2 && prgcLegal2 == prgcLegal3)
1066 					iIndex += cPositions1*(cPositions1-1)*(cPositions1-2)/6;
1067 				else if (prgcLegal1 == prgcLegal2)
1068 					{
1069 					cPositions3 = prgcLegal3[sqKing2] - ((BYTE) -1 != prgsqPiece3[sqKing2*64+sqKing1]);
1070 					iIndex += cPositions1*(cPositions1-1)/2*cPositions3;
1071 					}
1072 				else if (prgcLegal2 == prgcLegal3)
1073 					{
1074 					cPositions2 = prgcLegal2[sqKing2] - ((BYTE) -1 != prgsqPiece2[sqKing2*64+sqKing1]);
1075 					iIndex += cPositions1*cPositions2*(cPositions2-1)/2;
1076 					}
1077 				else
1078 					{
1079 					cPositions2 = prgcLegal2[sqKing2] - ((BYTE) -1 != prgsqPiece2[sqKing2*64+sqKing1]);
1080 					cPositions3 = prgcLegal3[sqKing2] - ((BYTE) -1 != prgsqPiece3[sqKing2*64+sqKing1]);
1081 					iIndex += cPositions1*cPositions2*cPositions3;
1082 					}
1083 				}
1084 			}
1085 	*pcEnumeration = iIndex;
1086 	}
1087 
1088 #endif
1089 
1090 // Initialize all enumeration tables
1091 
1092 static bool fEnumerationInitted = false;
1093 
VInitEnumerations(void)1094 static void VInitEnumerations (void)
1095 	{
1096 	piece	pi1;
1097 	piece	pi2;
1098 #if defined (T41_INCLUDE)
1099 	piece	pi3;
1100 #endif
1101 
1102 	if (fEnumerationInitted)
1103 		return;
1104 	fEnumerationInitted = true;
1105 	// Initialize square tables
1106 	for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
1107 		{
1108 		rgprgsqPiece[pi1] = (BYTE *) PvMalloc (64*64);
1109 		VInitSquaresTable (pi1, rgprgsqPiece[pi1], rgcLegal[pi1]);
1110 		}
1111 
1112 	for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
1113 		{
1114 		// Initialize enumeration tables for single piece
1115 		rgprgulSinglePawnPresent[pi1] = (ULONG *) PvMalloc (1806*sizeof (ULONG));
1116 		VInitSingle (rgprgulSinglePawnPresent[pi1], rgsHalfKings,
1117 					 rgcLegal[pi1], rgprgsqPiece[pi1], &rgcSinglePawnPresent[pi1]);
1118 		if (pi1 > x_piecePawn)
1119 			{
1120 			rgprgulSinglePawnless[pi1] = (ULONG *) PvMalloc (462*sizeof (ULONG));
1121 			VInitSingle (rgprgulSinglePawnless[pi1], rgsTriKings,
1122 						 rgcLegal[pi1], rgprgsqPiece[pi1], &rgcSinglePawnless[pi1]);
1123 			}
1124 		// Initialize enumeration tables for pair of pieces
1125 		for (pi2 = (x_pieceNone == pi1 ? x_pieceNone : x_piecePawn); pi2 <= pi1; pi2 = (piece) (pi2 + 1))
1126 			{
1127 			rgprgulPairPawnPresent[pi1][pi2] = (ULONG *) PvMalloc (1806*sizeof (ULONG));
1128 			VInitPair (rgprgulPairPawnPresent[pi1][pi2], rgsHalfKings,
1129 					   rgcLegal[pi1], rgprgsqPiece[pi1], rgcLegal[pi2], rgprgsqPiece[pi2],
1130 					   &rgcPairPawnPresent[pi1][pi2]);
1131 			if (pi1 > x_piecePawn && pi2 > x_piecePawn)
1132 				{
1133 				rgprgulPairPawnless[pi1][pi2] = (ULONG *) PvMalloc (462*sizeof (ULONG));
1134 				VInitPair (rgprgulPairPawnless[pi1][pi2], rgsTriKings,
1135 						   rgcLegal[pi1], rgprgsqPiece[pi1], rgcLegal[pi2], rgprgsqPiece[pi2],
1136 						   &rgcPairPawnless[pi1][pi2]);
1137 				}
1138 #if defined (T41_INCLUDE)
1139 			// Initialize enumeration tables for three pieces
1140 			for (pi3 = (x_pieceNone == pi1 ? x_pieceNone : x_piecePawn); pi3 <= pi2; pi3 = (piece) (pi3 + 1))
1141 				{
1142 				if (pi1 <= x_piecePawn || pi2 <= x_piecePawn || pi3 <= x_piecePawn)
1143 					{
1144 					rgprgulTriplePawnPresent[pi1][pi2][pi3] = (ULONG *) PvMalloc (1806*sizeof (ULONG));
1145 					VInitTriple (rgprgulTriplePawnPresent[pi1][pi2][pi3], rgsHalfKings,
1146 								 rgcLegal[pi1], rgprgsqPiece[pi1],
1147 								 rgcLegal[pi2], rgprgsqPiece[pi2],
1148 								 rgcLegal[pi3], rgprgsqPiece[pi3],
1149 								 &rgcTriplePawnPresent[pi1][pi2][pi3]);
1150 					}
1151 				else
1152 					{
1153 					rgprgulTriplePawnless[pi1][pi2][pi3] = (ULONG *) PvMalloc (462*sizeof (ULONG));
1154 					VInitTriple (rgprgulTriplePawnless[pi1][pi2][pi3], rgsTriKings,
1155 						rgcLegal[pi1], rgprgsqPiece[pi1],
1156 						rgcLegal[pi2], rgprgsqPiece[pi2],
1157 						rgcLegal[pi3], rgprgsqPiece[pi3],
1158 						&rgcTriplePawnless[pi1][pi2][pi3]);
1159 					}
1160 				}
1161 #endif
1162 			}
1163 		}
1164 
1165 	// All done!
1166 	if (fPrint)
1167 		{
1168 		for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
1169 			printf ("%c - %ld enumerated positions\n", "pPNBRQ"[pi1], rgcSinglePawnPresent[pi1]);
1170 		for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
1171 			{
1172 			if (0 != rgcSinglePawnless[pi1])
1173 				printf ("pawnless %c - %ld enumerated positions\n", "pPNBRQ"[pi1], rgcSinglePawnless[pi1]);
1174 			}
1175 		for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
1176 			for (pi2 = x_pieceNone; pi2 <= pi1; pi2 = (piece) (pi2 + 1))
1177 				{
1178 				if (0 != rgcPairPawnPresent[pi1][pi2])
1179 					printf ("%c%c - %ld enumerated positions\n", "pPNBRQ"[pi1], "pPNBRQ"[pi2],
1180 							rgcPairPawnPresent[pi1][pi2]);
1181 				}
1182 		for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
1183 			for (pi2 = x_pieceNone; pi2 <= pi1; pi2 = (piece) (pi2 + 1))
1184 				{
1185 				if (0 != rgcPairPawnless[pi1][pi2])
1186 					printf ("pawnless %c%c - %ld enumerated positions\n", "pPNBRQ"[pi1], "pPNBRQ"[pi2],
1187 							rgcPairPawnless[pi1][pi2]);
1188 				}
1189 #if defined (T41_INCLUDE)
1190 		for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
1191 			for (pi2 = x_pieceNone; pi2 <= pi1; pi2 = (piece) (pi2 + 1))
1192 				for (pi3 = x_pieceNone; pi3 <= pi2; pi3 = (piece) (pi3 + 1))
1193 					{
1194 					if (0 != rgcTriplePawnPresent[pi1][pi2][pi3])
1195 						printf ("%c%c%c - %ld enumerated positions\n",
1196 								"pPNBRQ"[pi1], "pPNBRQ"[pi2], "pPNBRQ"[pi3],
1197 								rgcTriplePawnPresent[pi1][pi2][pi3]);
1198 					}
1199 		for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
1200 			for (pi2 = x_pieceNone; pi2 <= pi1; pi2 = (piece) (pi2 + 1))
1201 				for (pi3 = x_pieceNone; pi3 <= pi2; pi3 = (piece) (pi3 + 1))
1202 					{
1203 					if (0 != rgcTriplePawnless[pi1][pi2][pi3])
1204 						printf ("pawnless %c%c%c - %ld enumerated positions\n",
1205 								"pPNBRQ"[pi1], "pPNBRQ"[pi2], "pPNBRQ"[pi3],
1206 								rgcTriplePawnless[pi1][pi2][pi3]);
1207 					}
1208 #endif
1209 		printf ("\nAllocated %luk\n\n", (cbAllocated + 1023)/1024);
1210 		}
1211 	}
1212 
1213 // Return enumeration of 2 kings and single piece
1214 
1215 template <int piw1, bool fPawns, bool fInvert> class TEnumerate1
1216 	{
1217 public:
Index(square sqwk,square sqw1,square sqbk)1218 	static INLINE INDEX TB_FASTCALL Index
1219 		(
1220 		square	sqwk,
1221 		square	sqw1,
1222 		square	sqbk
1223 		)
1224 		{
1225 		INDEX	ind;
1226 		ULONG	ulKings;
1227 
1228 		// For black pawn invert the board
1229 		if (piw1 <= x_piecePawn && fInvert)
1230 			{
1231 			sqwk = reflect_x(sqwk);
1232 			sqw1 = reflect_x(sqw1);
1233 			sqbk = reflect_x(sqbk);
1234 			}
1235 
1236 		// Get enumerated square
1237 		ind = rgprgsqPiece[piw1][sqbk*64+sqw1];
1238 #if defined (ILLEGAL_POSSIBLE)
1239 		if ((BYTE) -1 == ind)
1240 			return INF_SINGLE;
1241 #endif
1242 		// Get enumerated position of both kings
1243 		if (fPawns)
1244 			ulKings = rgsHalfKings[sqwk*64+sqbk];	// 0..1805
1245 		else
1246 			ulKings = rgsTriKings[sqwk*64+sqbk];	// 0..461
1247 #if defined (ILLEGAL_POSSIBLE)
1248 		if (INF == ulKings)
1249 			return INF_SINGLE;
1250 #endif
1251 		// Can we remove one extra square?
1252 		if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
1253 			ind -= (sqw1 > sqwk);
1254 		// Add enumerated square to the # of the preceding positions
1255 		return ind + (fPawns ? rgprgulSinglePawnPresent[piw1][ulKings] : rgprgulSinglePawnless[piw1][ulKings]);
1256 		}
1257 	};
1258 
1259 // Return enumeration of 2 kings and 2 pieces
1260 
1261 template <int piw1, int piw2, bool fPawns, bool fInvert> class TEnumerate2
1262 	{
1263 public:
Index(square sqwk,square sqw1,square sqw2,square sqbk)1264 	static INLINE INDEX TB_FASTCALL Index
1265 		(
1266 		square	sqwk,
1267 		square	sqw1,
1268 		square	sqw2,
1269 		square	sqbk
1270 		)
1271 		{
1272 		INDEX	ind1, ind2, cInd2;
1273 		ULONG	ulKings;
1274 
1275 		// For black pawn invert the board
1276 		if (piw2 <= x_piecePawn && fInvert)
1277 			{
1278 			sqwk = reflect_x(sqwk);
1279 			sqw1 = reflect_x(sqw1);
1280 			sqw2 = reflect_x(sqw2);
1281 			sqbk = reflect_x(sqbk);
1282 			}
1283 
1284 		// Get enumerated squares for both pieces
1285 		if (piw1 == piw2)
1286 			SORT (sqw1, sqw2);
1287 		ind1 = rgprgsqPiece[piw1][sqbk*64+sqw1];
1288 		ind2 = rgprgsqPiece[piw2][sqbk*64+sqw2];
1289 #if defined (ILLEGAL_POSSIBLE)
1290 		if ((BYTE) -1 == ind1 || (BYTE) -1 == ind2)
1291 			return INF_PAIR;
1292 #endif
1293 		// Get enumerated position of both kings
1294 		if (fPawns)
1295 			ulKings = rgsHalfKings[sqwk*64+sqbk];	// 0..1805
1296 		else
1297 			ulKings = rgsTriKings[sqwk*64+sqbk];	// 0..461
1298 #if defined (ILLEGAL_POSSIBLE)
1299 		if (INF == ulKings)
1300 			return INF_PAIR;
1301 #endif
1302 		if (piw1 == piw2)
1303 			{
1304 			// Can we remove one extra square?
1305 			if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
1306 				{
1307 				ind1 -= (sqw1 > sqwk);
1308 				ind2 -= (sqw2 > sqwk);
1309 				}
1310 			// Add enumerated squares to the # of the preceding positions
1311 			return	ind2*(ind2-1)/2 + ind1 +
1312 					(fPawns ? rgprgulPairPawnPresent[piw1][piw2][ulKings] : rgprgulPairPawnless[piw1][piw2][ulKings]);
1313 			}
1314 		else
1315 			{
1316 			// Can we remove WK square from 1st piece enumeration?
1317 			if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
1318 				ind1 -= (sqw1 > sqwk);
1319 			// Get # of enumerated positions of 2nd piece
1320 			cInd2 = rgcLegal[piw2][sqbk];
1321 			// Can we remove WK square from 2nd piece enumeration?
1322 			if ((piw2>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw2][sqbk*64+sqwk]))
1323 				{
1324 				cInd2 --;
1325 				ind2 -= (sqw2 > sqwk);
1326 				}
1327 			// Add enumerated square to the # of the preceding positions
1328 			return cInd2*ind1 + ind2 + (fPawns ? rgprgulPairPawnPresent[piw1][piw2][ulKings] : rgprgulPairPawnless[piw1][piw2][ulKings]);
1329 			}
1330 		}
1331 	};
1332 
1333 #if defined (T41_INCLUDE)
1334 
1335 // Return enumeration of 2 kings and 3 pieces
1336 
1337 template <int piw1, int piw2, int piw3, bool fPawns, bool fInvert> class TEnumerate3
1338 	{
1339 public:
Index(square sqwk,square sqw1,square sqw2,square sqw3,square sqbk)1340 	static INLINE INDEX TB_FASTCALL Index
1341 		(
1342 		square	sqwk,
1343 		square	sqw1,
1344 		square	sqw2,
1345 		square	sqw3,
1346 		square	sqbk
1347 		)
1348 		{
1349 		INDEX	ind1, ind2, ind3, cInd1, cInd2, cInd3;
1350 		ULONG	ulKings;
1351 
1352 		// For black pawn invert the board
1353 		if (piw3 <= x_piecePawn && fInvert)
1354 			{
1355 			sqwk = reflect_x(sqwk);
1356 			sqw1 = reflect_x(sqw1);
1357 			sqw2 = reflect_x(sqw2);
1358 			sqw3 = reflect_x(sqw3);
1359 			sqbk = reflect_x(sqbk);
1360 			}
1361 
1362 		// Get enumerated squares for all pieces
1363 		if (piw1 == piw2 && piw1 == piw3)
1364 			{
1365 			SORT (sqw1, sqw2);
1366 			SORT (sqw2, sqw3);
1367 			SORT (sqw1, sqw2);
1368 			}
1369 		else if (piw1 == piw2)
1370 			{
1371 			SORT (sqw1, sqw2);
1372 			}
1373 		else if (piw2 == piw3)
1374 			{
1375 			SORT (sqw2, sqw3);
1376 			}
1377 		ind1 = rgprgsqPiece[piw1][sqbk*64+sqw1];
1378 		ind2 = rgprgsqPiece[piw2][sqbk*64+sqw2];
1379 		ind3 = rgprgsqPiece[piw3][sqbk*64+sqw3];
1380 #if defined (ILLEGAL_POSSIBLE)
1381 		if ((BYTE) -1 == ind1 || (BYTE) -1 == ind2 || (BYTE) -1 == ind3)
1382 			return INF_TRIPLE;
1383 #endif
1384 		// Get enumerated position of both kings
1385 		if (fPawns)
1386 			ulKings = rgsHalfKings[sqwk*64+sqbk];	// 0..1805
1387 		else
1388 			ulKings = rgsTriKings[sqwk*64+sqbk];	// 0..461
1389 #if defined (ILLEGAL_POSSIBLE)
1390 		if (INF == ulKings)
1391 			return INF_TRIPLE;
1392 #endif
1393 		if (piw1 == piw2 && piw2 == piw3)
1394 			{
1395 			// Can we remove one extra square?
1396 			if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
1397 				{
1398 				ind1 -= (sqw1 > sqwk);
1399 				ind2 -= (sqw2 > sqwk);
1400 				ind3 -= (sqw3 > sqwk);
1401 				}
1402 			// Add enumerated squares to the # of the preceding positions
1403 			return	ind3*(ind3-1)*(ind3-2)/6 + ind2*(ind2-1)/2 + ind1 +
1404 					(fPawns ? rgprgulTriplePawnPresent[piw1][piw2][piw3][ulKings] :
1405 							  rgprgulTriplePawnless[piw1][piw2][piw3][ulKings]);
1406 			}
1407 		else if (piw1 == piw2)
1408 			{
1409 			// Can we remove one extra square?
1410 			if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
1411 				{
1412 				ind1 -= (sqw1 > sqwk);
1413 				ind2 -= (sqw2 > sqwk);
1414 				}
1415 			// Get # of enumerated positions of 3rd piece
1416 			cInd3 = rgcLegal[piw3][sqbk];
1417 			// Can we remove WK square from 3rd piece enumeration?
1418 			if ((piw3>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw3][sqbk*64+sqwk]))
1419 				{
1420 				cInd3 --;
1421 				ind3 -= (sqw3 > sqwk);
1422 				}
1423 			// Add enumerated squares to the # of the preceding positions
1424 			return	(ind2*(ind2-1)/2 + ind1)*cInd3 + ind3 +
1425 					(fPawns ? rgprgulTriplePawnPresent[piw1][piw2][piw3][ulKings] :
1426 							  rgprgulTriplePawnless[piw1][piw2][piw3][ulKings]);
1427 			}
1428 		else if (piw2 == piw3)
1429 			{
1430 			// Can we remove one extra square?
1431 			if ((piw2>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw2][sqbk*64+sqwk]))
1432 				{
1433 				ind2 -= (sqw2 > sqwk);
1434 				ind3 -= (sqw3 > sqwk);
1435 				}
1436 			// Get # of enumerated positions of 1st piece
1437 			cInd1 = rgcLegal[piw1][sqbk];
1438 			// Can we remove WK square from 3rd piece enumeration?
1439 			if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
1440 				{
1441 				cInd1 --;
1442 				ind1 -= (sqw1 > sqwk);
1443 				}
1444 			// Add enumerated squares to the # of the preceding positions
1445 			return	(ind3*(ind3-1)/2 + ind2)*cInd1 + ind1 +
1446 					(fPawns ? rgprgulTriplePawnPresent[piw1][piw2][piw3][ulKings] :
1447 							  rgprgulTriplePawnless[piw1][piw2][piw3][ulKings]);
1448 			}
1449 		else
1450 			{
1451 			// Can we remove WK square from 1st piece enumeration?
1452 			if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
1453 				ind1 -= (sqw1 > sqwk);
1454 			// Get # of enumerated positions of 2nd piece
1455 			cInd2 = rgcLegal[piw2][sqbk];
1456 			// Can we remove WK square from 2nd piece enumeration?
1457 			if ((piw2>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw2][sqbk*64+sqwk]))
1458 				{
1459 				cInd2 --;
1460 				ind2 -= (sqw2 > sqwk);
1461 				}
1462 			// Get # of enumerated positions of 3rd piece
1463 			cInd3 = rgcLegal[piw3][sqbk];
1464 			// Can we remove WK square from 3rd piece enumeration?
1465 			if ((piw3>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw3][sqbk*64+sqwk]))
1466 				{
1467 				cInd3 --;
1468 				ind3 -= (sqw3 > sqwk);
1469 				}
1470 			// Add enumerated square to the # of the preceding positions
1471 			return	cInd3*(cInd2*ind1 + ind2) + ind3 +
1472 					(fPawns ? rgprgulTriplePawnPresent[piw1][piw2][piw3][ulKings] :
1473 							  rgprgulTriplePawnless[piw1][piw2][piw3][ulKings]);
1474 			}
1475 		}
1476 	};
1477 
1478 #endif
1479 
1480 // Enumerate en passant captures
1481 
IndEnPassant11W(square sqw,square sqb,square sqEnP)1482 static INLINE INDEX TB_FASTCALL IndEnPassant11W
1483 	(
1484 	square	sqw,
1485 	square	sqb,
1486 	square	sqEnP
1487 	)
1488 	{
1489 	assert (sqb+8 == sqEnP);
1490 	if (sqw+7 == sqEnP)
1491 		// Capture to the left
1492 		return	(sqw&7)-1;
1493 	else
1494 		{
1495 		// Capture to the right
1496 		assert (sqw+9 == sqEnP);
1497 		return	(sqw&7)+7;
1498 		}
1499 	}
1500 
IndEnPassant11B(square sqw,square sqb,square sqEnP)1501 static INLINE INDEX TB_FASTCALL IndEnPassant11B
1502 	(
1503 	square	sqw,
1504 	square	sqb,
1505 	square	sqEnP
1506 	)
1507 	{
1508 	assert (sqw-8 == sqEnP);
1509 	if (sqb-9 == sqEnP)
1510 		// Capture to the left
1511 		return (sqb&7)-1;
1512 	else
1513 		{
1514 		// Capture to the right
1515 		assert (sqb-7 == sqEnP);
1516 		return (sqb&7)+7;
1517 		}
1518 	}
1519 
IndEnPassant21W(square sqw1,square sqw2,square sqb,square sqEnP)1520 static INLINE INDEX TB_FASTCALL IndEnPassant21W
1521 	(
1522 	square	sqw1,
1523 	square	sqw2,
1524 	square	sqb,
1525 	square	sqEnP
1526 	)
1527 	{
1528 	assert (sqb+8 == sqEnP);
1529 	SORT (sqw1, sqw2);
1530 	if (sqw1+7 == sqEnP && 0 != TbColumn(sqw1))
1531 		// Capture to the left
1532 		return (sqw1&7)-1+(EXCLUDE3(sqw2,sqb,sqEnP,sqEnP+8)-i8-1)*i14;
1533 	else if (sqw1+9 == sqEnP && 7 != TbColumn(sqw1))
1534 		// Capture to the right
1535 		return (sqw1&7)+7+(EXCLUDE3(sqw2,sqb,sqEnP,sqEnP+8)-i8-1)*i14;
1536 	else if (sqw2+7 == sqEnP && 0 != TbColumn(sqw2))
1537 		// Capture to the left
1538 		return (sqw2&7)-1+(EXCLUDE3(sqw1,sqb,sqEnP,sqEnP+8)-i8)*i14;
1539 	else
1540 		{
1541 		// Capture to the right
1542 		assert (sqw2+9 == sqEnP && 7 != TbColumn(sqw2));
1543 		return (sqw2&7)+7+(EXCLUDE3(sqw1,sqb,sqEnP,sqEnP+8)-i8)*i14;
1544 		}
1545 	}
1546 
IndEnPassant21B(square sqw1,square sqw2,square sqb,square sqEnP)1547 static INLINE INDEX TB_FASTCALL IndEnPassant21B
1548 	(
1549 	square	sqw1,
1550 	square	sqw2,
1551 	square	sqb,
1552 	square	sqEnP
1553 	)
1554 	{
1555 	assert (sqw1 < sqw2);	// Must be already sorted
1556 	if (sqb-9 == sqEnP && 0 != TbColumn(sqb))
1557 		// Capture to the left
1558 		if (sqw1-8 == sqEnP)
1559 			return (sqb&7)-1+(EXCLUDE3(sqw2,sqb,sqEnP,sqEnP-8)-i8-1)*i14;
1560 		else
1561 			{
1562 			assert (sqw2-8 == sqEnP);
1563 			return (sqb&7)-1+(EXCLUDE3(sqw1,sqb,sqEnP,sqEnP-8)-i8)*i14;
1564 			}
1565 	else
1566 		{
1567 		// Capture to the right
1568 		assert (sqb-7 == sqEnP && 7 != TbColumn(sqb));
1569 		if (sqw1-8 == sqEnP)
1570 			return (sqb&7)+7+(EXCLUDE3(sqw2,sqb,sqEnP,sqEnP-8)-i8-1)*i14;
1571 		else
1572 			{
1573 			assert (sqw2-8 == sqEnP);
1574 			return (sqb&7)+7+(EXCLUDE3(sqw1,sqb,sqEnP,sqEnP-8)-i8)*i14;
1575 			}
1576 		}
1577 	}
1578 
1579 // Index calculation functions for different endgame classes
1580 
1581 template <int piw1> class T21
1582 	{
1583 public:
IndCalcW(square * psqW,square * psqB,square sqEnP,int fInvert)1584 	static INDEX TB_FASTCALL IndCalcW
1585 		(
1586 		square	*psqW,
1587 		square	*psqB,
1588 		square	sqEnP,
1589 		int		fInvert
1590 		)
1591 		{
1592 		square sqwk, sqw1, sqbk, sqMask;
1593 
1594 		sqwk = SqFindKing (psqW);
1595 		sqw1 = SqFindOne  (psqW, piw1);
1596 		sqbk = SqFindKing (psqB);
1597 
1598 		if (x_piecePawn == piw1)
1599 			sqMask = rgsqReflectMaskY [sqwk] ^ rgsqReflectInvertMask [fInvert];
1600 		else
1601 			sqMask = rgsqReflectMaskYandX [sqwk];
1602 		sqwk ^= sqMask;
1603 		sqbk ^= sqMask;
1604 		sqw1 ^= sqMask;
1605 
1606 		if (x_piecePawn != piw1)
1607 			{
1608 			// No pawn
1609 			if (! FInTriangle (sqwk, sqbk))
1610 				{
1611 				sqwk = reflect_xy(sqwk);
1612 				sqbk = reflect_xy(sqbk);
1613 				sqw1 = reflect_xy(sqw1);
1614 				};
1615 			}
1616 		return TEnumerate1<piw1,x_piecePawn==piw1 ? true : false,false>::Index(sqwk,sqw1,sqbk);
1617 		}
1618 
IndCalcB(square * psqW,square * psqB,square sqEnP,int fInvert)1619 	static INDEX TB_FASTCALL IndCalcB
1620 		(
1621 		square	*psqW,
1622 		square	*psqB,
1623 		square	sqEnP,
1624 		int		fInvert
1625 		)
1626 		{
1627 		square sqwk, sqw1, sqbk, sqMask;
1628 
1629 		sqwk = SqFindKing (psqW);
1630 		sqw1 = SqFindOne  (psqW, piw1);
1631 		sqbk = SqFindKing (psqB);
1632 
1633 		if (x_piecePawn == piw1)
1634 			sqMask = rgsqReflectMaskY [sqbk] ^ rgsqReflectInvertMask [fInvert];
1635 		else
1636 			sqMask = rgsqReflectMaskYandX [sqbk];
1637 		sqwk ^= sqMask;
1638 		sqbk ^= sqMask;
1639 		sqw1 ^= sqMask;
1640 
1641 		if (x_piecePawn == piw1)
1642 			return TEnumerate1<x_pieceNone,true,true>::Index(sqbk,sqw1,sqwk);
1643 		else
1644 			{
1645 			// No pawn
1646 			if (! FInTriangle (sqbk, sqwk))
1647 				{
1648 				sqwk = reflect_xy(sqwk);
1649 				sqbk = reflect_xy(sqbk);
1650 				sqw1 = reflect_xy(sqw1);
1651 				};
1652 			return IndTriKings(sqbk,sqwk)*i62 + EXCLUDE2(sqw1,sqwk,sqbk);
1653 			}
1654 		}
1655 	};
1656 
1657 template <int piw1, int pib1> class T22
1658 	{
1659 public:
IndCalcW(square * psqW,square * psqB,square sqEnP,int fInvert)1660 	static INDEX TB_FASTCALL IndCalcW
1661 		(
1662 		square	*psqW,
1663 		square	*psqB,
1664 		square	sqEnP,
1665 		int		fInvert
1666 		)
1667 		{
1668 		square sqwk, sqw1, sqbk, sqb1, sqMask;
1669 
1670 		sqwk = SqFindKing (psqW);
1671 		sqw1 = SqFindOne  (psqW, piw1);
1672 		sqbk = SqFindKing (psqB);
1673 		sqb1 = SqFindOne  (psqB, pib1);
1674 
1675 		if (x_piecePawn == pib1)
1676 			sqMask = rgsqReflectMaskY [sqwk] ^ rgsqReflectInvertMask [fInvert];
1677 		else
1678 			sqMask = rgsqReflectMaskYandX [sqwk];
1679 		sqwk ^= sqMask;
1680 		sqbk ^= sqMask;
1681 		sqw1 ^= sqMask;
1682 		sqb1 ^= sqMask;
1683 
1684 		if (x_piecePawn == pib1)
1685 			{
1686 			// There are pawns on the board
1687 			if (x_piecePawn == piw1)
1688 				{
1689 				// One white and one black pawn
1690 				if (XX == sqEnP)
1691 					return	TEnumerate1<x_piecePawn,true,false>::Index(sqwk,sqw1,sqbk)*i47 +
1692 							EXCLUDE1(sqb1,sqw1)-i8;	// 47
1693 				else
1694 					return	rgcSinglePawnPresent[x_piecePawn]*i47 +
1695 							IndHalfKings(sqwk,sqbk)*i14 +
1696 							IndEnPassant11W (sqw1, sqb1, sqEnP ^ sqMask);
1697 				}
1698 			else
1699 				// Only black pawn
1700 				return	TEnumerate1<piw1,true,false>::Index(sqwk,sqw1,sqbk)*i48 + sqb1-i8;
1701 			}
1702 		else
1703 			{
1704 			// No pawns at all
1705 			if (!FInTriangle (sqwk, sqbk))
1706 				{
1707 				sqwk = reflect_xy(sqwk);
1708 				sqbk = reflect_xy(sqbk);
1709 				sqw1 = reflect_xy(sqw1);
1710 				sqb1 = reflect_xy(sqb1);
1711 				};
1712 			return	TEnumerate1<piw1,false,false>::Index(sqwk,sqw1,sqbk)*i61 +
1713 					EXCLUDE3(sqb1,sqwk,sqbk,sqw1);	// 61
1714 			}
1715 		}
1716 
IndCalcB(square * psqW,square * psqB,square sqEnP,int fInvert)1717 	static INDEX TB_FASTCALL IndCalcB
1718 		(
1719 		square	*psqW,
1720 		square	*psqB,
1721 		square	sqEnP,
1722 		int		fInvert
1723 		)
1724 		{
1725 		square sqwk, sqw1, sqbk, sqb1, sqMask;
1726 
1727 		sqwk = SqFindKing (psqW);
1728 		sqw1 = SqFindOne  (psqW, piw1);
1729 		sqbk = SqFindKing (psqB);
1730 		sqb1 = SqFindOne  (psqB, pib1);
1731 
1732 		if (x_piecePawn == pib1)
1733 			sqMask = rgsqReflectMaskY [sqbk] ^ rgsqReflectInvertMask [fInvert];
1734 		else
1735 			sqMask = rgsqReflectMaskYandX [sqbk];
1736 		sqwk ^= sqMask;
1737 		sqbk ^= sqMask;
1738 		sqw1 ^= sqMask;
1739 		sqb1 ^= sqMask;
1740 
1741 		if (x_piecePawn == pib1)
1742 			{
1743 			// There are pawns on the board
1744 			if (x_piecePawn == piw1)
1745 				{
1746 				// One white and one black pawn
1747 				if (XX == sqEnP)
1748 					return	TEnumerate1<x_piecePawn,true,true>::Index(sqbk,sqb1,sqwk)*i47 +
1749 							EXCLUDE1(sqw1,sqb1)-i8;	// 47
1750 				else
1751 					return	rgcSinglePawnPresent[x_piecePawn]*i47 +
1752 							IndHalfKings(sqbk,sqwk)*i14 +
1753 							IndEnPassant11B (sqw1, sqb1, sqEnP ^ sqMask);
1754 				}
1755 			}
1756 		else
1757 			{
1758 			// No pawns at all
1759 			if (!FInTriangle (sqbk, sqwk))
1760 				{
1761 				sqwk = reflect_xy(sqwk);
1762 				sqbk = reflect_xy(sqbk);
1763 				sqw1 = reflect_xy(sqw1);
1764 				sqb1 = reflect_xy(sqb1);
1765 				};
1766 			}
1767 		return	(x_piecePawn == pib1 ?	TEnumerate1<pib1,true,true>::Index(sqbk,sqb1,sqwk) :
1768 										TEnumerate1<pib1,false,false>::Index(sqbk,sqb1,sqwk))*i61 +
1769 				EXCLUDE3(sqw1,sqwk,sqbk,sqb1);	// 61
1770 		}
1771 	};
1772 
1773 template <int piw1, int piw2> class T31
1774 	{
1775 public:
IndCalcW(square * psqW,square * psqB,square sqEnP,int fInvert)1776 	static INDEX TB_FASTCALL IndCalcW
1777 		(
1778 		square	*psqW,
1779 		square	*psqB,
1780 		square	sqEnP,
1781 		int		fInvert
1782 		)
1783 		{
1784 		square sqwk, sqw1, sqw2, sqbk, sqMask;
1785 
1786 		sqwk = SqFindKing (psqW);
1787 		if (piw1 == piw2)
1788 			{
1789 			sqw1 = SqFindFirst  (psqW, piw1);
1790 			sqw2 = SqFindSecond (psqW, piw2);
1791 			}
1792 		else
1793 			{
1794 			SqFind2 (psqW, piw1, sqw1, piw2, sqw2);
1795 			}
1796 		sqbk = SqFindKing (psqB);
1797 
1798 		if (x_piecePawn == piw2)
1799 			sqMask = rgsqReflectMaskY [sqwk] ^ rgsqReflectInvertMask [fInvert];
1800 		else
1801 			sqMask = rgsqReflectMaskYandX [sqwk];
1802 		sqwk ^= sqMask;
1803 		sqbk ^= sqMask;
1804 		sqw1 ^= sqMask;
1805 		sqw2 ^= sqMask;
1806 
1807 		if (x_piecePawn != piw2)
1808 			{
1809 			// There are no pawns on the board
1810 			if (!FInTriangle (sqwk, sqbk))
1811 				{
1812 				sqwk = reflect_xy(sqwk);
1813 				sqw1 = reflect_xy(sqw1);
1814 				sqw2 = reflect_xy(sqw2);
1815 				sqbk = reflect_xy(sqbk);
1816 				};
1817 			}
1818 		return TEnumerate2<piw1, piw2, x_piecePawn==piw2 ? true : false, false>::Index(sqwk, sqw1, sqw2, sqbk);
1819 		}
1820 
IndCalcB(square * psqW,square * psqB,square sqEnP,int fInvert)1821 	static INDEX TB_FASTCALL IndCalcB
1822 		(
1823 		square	*psqW,
1824 		square	*psqB,
1825 		square	sqEnP,
1826 		int		fInvert
1827 		)
1828 		{
1829 		square sqwk, sqw1, sqw2, sqbk, sqMask;
1830 
1831 		sqwk = SqFindKing (psqW);
1832 		if (piw1 == piw2)
1833 			{
1834 			sqw1 = SqFindFirst (psqW, piw1);
1835 			sqw2 = SqFindSecond (psqW, piw2);
1836 			}
1837 		else
1838 			{
1839 			SqFind2 (psqW, piw1, sqw1, piw2, sqw2);
1840 			}
1841 		sqbk = SqFindKing (psqB);
1842 
1843 		if (x_piecePawn == piw2)
1844 			sqMask = rgsqReflectMaskY [sqbk] ^ rgsqReflectInvertMask [fInvert];
1845 		else
1846 			sqMask = rgsqReflectMaskYandX [sqbk];
1847 		sqwk ^= sqMask;
1848 		sqbk ^= sqMask;
1849 		sqw1 ^= sqMask;
1850 		sqw2 ^= sqMask;
1851 
1852 		if (x_piecePawn == piw2)
1853 			{
1854 			// There are pawns on the board
1855 			if (x_piecePawn == piw1)
1856 				// Two white pawns
1857 				return	TEnumerate2<x_pieceNone,x_pieceNone,true,true>::Index(sqbk,sqw1,sqw2,sqwk);
1858 			else
1859 				// Only one white pawn
1860 				return	TEnumerate1<x_pieceNone,true,true>::Index(sqbk,sqw2,sqwk)*i61 +
1861 						EXCLUDE3(sqw1,sqwk,sqbk,sqw2);	// 61
1862 			}
1863 		else
1864 			{
1865 			// No pawns
1866 			if (!FInTriangle (sqbk, sqwk))
1867 				{
1868 				sqwk = reflect_xy(sqwk);
1869 				sqw1 = reflect_xy(sqw1);
1870 				sqw2 = reflect_xy(sqw2);
1871 				sqbk = reflect_xy(sqbk);
1872 				};
1873 			if (piw1 == piw2)
1874 				{
1875 				SORT (sqw1, sqw2);
1876 				sqw2 = EXCLUDE2(sqw2,sqwk,sqbk);					// 62
1877 				return	IndTriKings(sqbk,sqwk)*(i62*i61/2) +
1878 						sqw2*(sqw2-1)/2+EXCLUDE2(sqw1,sqwk,sqbk);	// 62*61/2
1879 				}
1880 			else
1881 				return	IndTriKings(sqbk,sqwk)*(i62*i61) +
1882 						EXCLUDE2(sqw1,sqwk,sqbk)*i61 +	// 62
1883 						EXCLUDE3(sqw2,sqwk,sqbk,sqw1);	// 61
1884 			}
1885 		}
1886 	};
1887 
1888 template <int piw1, int piw2, int pib1> class T32
1889 	{
1890 public:
IndCalcW(square * psqW,square * psqB,square sqEnP,int fInvert)1891 	static INDEX TB_FASTCALL IndCalcW
1892 		(
1893 		square	*psqW,
1894 		square	*psqB,
1895 		square	sqEnP,
1896 		int		fInvert
1897 		)
1898 		{
1899 		square sqwk, sqw1, sqw2, sqbk, sqb1, sqMask;
1900 
1901 		sqwk = SqFindKing (psqW);
1902 		if (piw1 == piw2)
1903 			{
1904 			sqw1 = SqFindFirst  (psqW, piw1);
1905 			sqw2 = SqFindSecond (psqW, piw2);
1906 			}
1907 		else
1908 			{
1909 			SqFind2 (psqW, piw1, sqw1, piw2, sqw2);
1910 			}
1911 		sqbk = SqFindKing (psqB);
1912 		sqb1 = SqFindOne  (psqB, pib1);
1913 
1914 		if (x_piecePawn == piw2 || x_piecePawn == pib1)
1915 			sqMask = rgsqReflectMaskY [sqwk] ^ rgsqReflectInvertMask [fInvert];
1916 		else
1917 			sqMask = rgsqReflectMaskYandX [sqwk];
1918 		sqwk ^= sqMask;
1919 		sqbk ^= sqMask;
1920 		sqw1 ^= sqMask;
1921 		sqw2 ^= sqMask;
1922 		sqb1 ^= sqMask;
1923 
1924 		if (x_piecePawn == piw2 || x_piecePawn == pib1)
1925 			{
1926 			// There are pawns on the board
1927 			if (x_piecePawn == pib1)
1928 				{
1929 				// Black pawn
1930 				if (x_piecePawn == piw1 && x_piecePawn == piw2)
1931 					{
1932 					// All 3 pieces are pawns
1933 					if (XX == sqEnP)
1934 						return	TEnumerate2<x_piecePawn,x_piecePawn,true,false>::
1935 									Index(sqwk,sqw1,sqw2,sqbk)*i46+
1936 								EXCLUDE2(sqb1,sqw1,sqw2)-i8;	// 46
1937 					else
1938 						// En passant capture
1939 						return	rgcPairPawnPresent[x_piecePawn][x_piecePawn]*i46 +
1940 								IndHalfKings(sqwk,sqbk)*(i14*i44) +
1941 								IndEnPassant21W (sqw1, sqw2, sqb1, sqEnP ^ sqMask);
1942 					}
1943 				else if (x_piecePawn == piw2)
1944 					{
1945 					// One white pawn, one black pawn
1946 					if (XX == sqEnP)
1947 						return	TEnumerate2<piw1,x_piecePawn,true,false>::
1948 									Index(sqwk,sqw1,sqw2,sqbk)*i47 +
1949 								EXCLUDE1(sqb1,sqw2)-i8;	// 47
1950 					else
1951 						// En passant capture
1952 						return	rgcPairPawnPresent[piw1][x_piecePawn]*i47 +
1953 								TEnumerate1<piw1,true,false>::Index(sqwk,sqw1,sqbk)*i14 +
1954 								IndEnPassant11W (sqw2, sqb1, sqEnP ^ sqMask);
1955 					}
1956 				else
1957 					// Only black pawn
1958 					return	TEnumerate2<piw1,piw2,true,false>::
1959 								Index(sqwk,sqw1,sqw2,sqbk)*i48 +
1960 							sqb1-i8;	// 48
1961 				}
1962 			}
1963 		else
1964 			{
1965 			// No pawns
1966 			if (!FInTriangle (sqwk, sqbk))
1967 				{
1968 				sqwk = reflect_xy(sqwk);
1969 				sqw1 = reflect_xy(sqw1);
1970 				sqw2 = reflect_xy(sqw2);
1971 				sqbk = reflect_xy(sqbk);
1972 				sqb1 = reflect_xy(sqb1);
1973 				};
1974 			}
1975 		return	TEnumerate2<piw1,piw2,(x_piecePawn==piw2||x_piecePawn==pib1) ? true : false,false>::
1976 					Index(sqwk,sqw1,sqw2,sqbk)*i60 +
1977 				EXCLUDE4(sqb1,sqwk,sqbk,sqw1,sqw2);	// 60
1978 		}
1979 
IndCalcB(square * psqW,square * psqB,square sqEnP,int fInvert)1980 	static INDEX TB_FASTCALL IndCalcB
1981 		(
1982 		square	*psqW,
1983 		square	*psqB,
1984 		square	sqEnP,
1985 		int		fInvert
1986 		)
1987 		{
1988 		square sqwk, sqw1, sqw2, sqbk, sqb1, sqMask;
1989 
1990 		sqwk = SqFindKing (psqW);
1991 		if (piw1 == piw2)
1992 			{
1993 			sqw1 = SqFindFirst  (psqW, piw1);
1994 			sqw2 = SqFindSecond (psqW, piw2);
1995 			}
1996 		else
1997 			{
1998 			SqFind2 (psqW, piw1, sqw1, piw2, sqw2);
1999 			}
2000 		sqbk = SqFindKing (psqB);
2001 		sqb1 = SqFindOne  (psqB, pib1);
2002 
2003 		if (x_piecePawn == piw2 || x_piecePawn == pib1)
2004 			sqMask = rgsqReflectMaskY [sqbk] ^ rgsqReflectInvertMask [fInvert];
2005 		else
2006 			sqMask = rgsqReflectMaskYandX [sqbk];
2007 		sqwk ^= sqMask;
2008 		sqbk ^= sqMask;
2009 		sqw1 ^= sqMask;
2010 		sqw2 ^= sqMask;
2011 		sqb1 ^= sqMask;
2012 
2013 		if (x_piecePawn == piw2 || x_piecePawn == pib1)
2014 			{
2015 			// There are pawns on the board
2016 			if (x_piecePawn == pib1)
2017 				{
2018 				// Black pawn
2019 				if (x_piecePawn == piw1 && x_piecePawn == piw2)
2020 					{
2021 					// All 3 pieces are pawns
2022 					SORT (sqw1, sqw2);
2023 					if (XX == sqEnP)
2024 						{
2025 						sqw2 = EXCLUDE1(sqw2,sqb1)-i8;					// 47
2026 						return	TEnumerate1<x_piecePawn,true,true>::
2027 									Index(sqbk,sqb1,sqwk)*(i47*i46/2) +
2028 								sqw2*(sqw2-1)/2+EXCLUDE1(sqw1,sqb1)-i8;	// 47*46/2
2029 						}
2030 					else
2031 						// En passant capture
2032 						return	rgcSinglePawnPresent[x_piecePawn]*(i47*i46/2) +
2033 								IndHalfKings(sqbk,sqwk)*(i44*i14) +
2034 								IndEnPassant21B (sqw1, sqw2, sqb1, sqEnP ^ sqMask);
2035 					}
2036 				else if (x_piecePawn == piw2)
2037 					{
2038 					// One white pawn, one black pawn
2039 					if (XX == sqEnP)
2040 						return	TEnumerate1<x_piecePawn,true,true>::
2041 									Index(sqbk,sqb1,sqwk)*(i60*i47) +
2042 								EXCLUDE4(sqw1,sqwk,sqbk,sqw2,sqb1)*i47 +	// 60
2043 								EXCLUDE1(sqw2,sqb1)-i8;						// 47
2044 					else
2045 						{
2046 						// En passant capture
2047 						sqEnP ^= sqMask;
2048 						return	rgcSinglePawnPresent[x_piecePawn]*(i60*i47) +
2049 								IndHalfKings(sqbk,sqwk)*(i58*i14) +
2050 								EXCLUDE6(sqw1,sqwk,sqbk,sqw2,sqb1,sqEnP,sqEnP-8)*i14 +	// 58
2051 								IndEnPassant11B (sqw2, sqb1, sqEnP);
2052 						}
2053 					}
2054 				else
2055 					{
2056 					// Only black pawn
2057 					if (piw1 == piw2)
2058 						{
2059 						// 2 identical white pieces
2060 						SORT (sqw1, sqw2);
2061 						sqw2 = EXCLUDE3(sqw2,sqwk,sqbk,sqb1);						// 61
2062 						return	TEnumerate1<x_piecePawn,true,true>::
2063 									Index(sqbk,sqb1,sqwk)*(i61*i60/2) +
2064 								sqw2*(sqw2-1)/2 + EXCLUDE3(sqw1,sqwk,sqbk,sqb1);	// 61*60/2
2065 						}
2066 					return	TEnumerate1<x_piecePawn,true,true>::
2067 								Index(sqbk,sqb1,sqwk)*(i61*i60) +
2068 							EXCLUDE3(sqw1,sqwk,sqbk,sqb1)*i60 +	// 61
2069 							EXCLUDE4(sqw2,sqwk,sqbk,sqw1,sqb1);	// 60
2070 					}
2071 				}
2072 			else
2073 				{
2074 				// No black pawn
2075 				if (x_piecePawn == piw1)
2076 					{
2077 					// Only 2 white pawns
2078 					SORT (sqw1, sqw2);
2079 					sqw2 -= i8;
2080 					return	TEnumerate1<pib1,true,true>::
2081 								Index(sqbk,sqb1,sqwk)*(i48*47/2) +
2082 							sqw2*(sqw2-1)/2+sqw1-i8;			// 48*47/2
2083 					}
2084 				else
2085 					// Only one white pawn
2086 					return	TEnumerate1<pib1,true,true>::
2087 								Index(sqbk,sqb1,sqwk)*(i60*i48) +
2088 							EXCLUDE4(sqw1,sqwk,sqbk,sqw2,sqb1)*i48 +	// 60
2089 							sqw2-i8;									// 48
2090 				}
2091 			}
2092 		else
2093 			{
2094 			// No pawns
2095 			if (!FInTriangle (sqbk, sqwk))
2096 				{
2097 				sqwk = reflect_xy(sqwk);
2098 				sqw1 = reflect_xy(sqw1);
2099 				sqw2 = reflect_xy(sqw2);
2100 				sqbk = reflect_xy(sqbk);
2101 				sqb1 = reflect_xy(sqb1);
2102 				};
2103 			if (piw1 == piw2)
2104 				{
2105 				// 2 identical white pieces
2106 				SORT (sqw1, sqw2);
2107 				sqw2 = EXCLUDE3(sqw2,sqwk,sqbk,sqb1);					// 61
2108 				return	TEnumerate1<pib1,false,false>::
2109 							Index(sqbk,sqb1,sqwk)*(i61*i60/2) +
2110 						sqw2*(sqw2-1)/2+EXCLUDE3(sqw1,sqwk,sqbk,sqb1);	// 61*60/2
2111 				}
2112 			else
2113 				return	TEnumerate1<pib1,false,false>::
2114 							Index(sqbk,sqb1,sqwk)*(i61*i60) +
2115 						EXCLUDE3(sqw1,sqwk,sqbk,sqb1)*i60 +	// 61
2116 						EXCLUDE4(sqw2,sqwk,sqbk,sqw1,sqb1);	// 60
2117 			}
2118 		}
2119 	};
2120 
2121 #if defined (T41_INCLUDE)
2122 
2123 template <int piw1, int piw2, int piw3> class T41
2124 	{
2125 public:
IndCalcW(square * psqW,square * psqB,square sqEnP,int fInvert)2126 	static INDEX TB_FASTCALL IndCalcW
2127 		(
2128 		square	*psqW,
2129 		square	*psqB,
2130 		square	sqEnP,
2131 		int		fInvert
2132 		)
2133 		{
2134 		square sqwk, sqw1, sqw2, sqw3, sqbk, sqMask;
2135 
2136 		sqwk = SqFindKing (psqW);
2137 		sqw1 = SqFindFirst (psqW, piw1);
2138 		if (piw1 == piw2 && piw2 == piw3)
2139 			{
2140 			sqw2 = SqFindSecond (psqW, piw2);
2141 			sqw3 = SqFindThird (psqW, piw3);
2142 			}
2143 		else if (piw1 == piw2)
2144 			{
2145 			sqw2 = SqFindSecond (psqW, piw2);
2146 			sqw3 = SqFindFirst (psqW, piw3);
2147 			}
2148 		else if (piw2 == piw3)
2149 			{
2150 			sqw2 = SqFindFirst (psqW, piw2);
2151 			sqw3 = SqFindSecond (psqW, piw3);
2152 			}
2153 		else
2154 			{
2155 			sqw2 = SqFindFirst (psqW, piw2);
2156 			sqw3 = SqFindFirst (psqW, piw3);
2157 			}
2158 		sqbk = SqFindKing (psqB);
2159 
2160 		if (x_piecePawn == piw3)
2161 			sqMask = rgsqReflectMaskY [sqwk] ^ rgsqReflectInvertMask [fInvert];
2162 		else
2163 			sqMask = rgsqReflectMaskYandX [sqwk];
2164 		sqwk ^= sqMask;
2165 		sqbk ^= sqMask;
2166 		sqw1 ^= sqMask;
2167 		sqw2 ^= sqMask;
2168 		sqw3 ^= sqMask;
2169 
2170 		if (x_piecePawn != piw3)
2171 			{
2172 			// No pawns
2173 			if (!FInTriangle (sqwk, sqbk))
2174 				{
2175 				sqwk = reflect_xy(sqwk);
2176 				sqw1 = reflect_xy(sqw1);
2177 				sqw2 = reflect_xy(sqw2);
2178 				sqw3 = reflect_xy(sqw3);
2179 				sqbk = reflect_xy(sqbk);
2180 				};
2181 			}
2182 		return	TEnumerate3<piw1,piw2,piw3,x_piecePawn == piw3,false>::Index(sqwk,sqw1,sqw2,sqw3,sqbk);
2183 		}
2184 
IndCalcB(square * psqW,square * psqB,square sqEnP,int fInvert)2185 	static INDEX TB_FASTCALL IndCalcB
2186 		(
2187 		square	*psqW,
2188 		square	*psqB,
2189 		square	sqEnP,
2190 		int		fInvert
2191 		)
2192 		{
2193 		square sqwk, sqw1, sqw2, sqw3, sqbk, sqMask;
2194 
2195 		sqwk = SqFindKing (psqW);
2196 		sqw1 = SqFindFirst (psqW, piw1);
2197 		if (piw1 == piw2 && piw2 == piw3)
2198 			{
2199 			sqw2 = SqFindSecond (psqW, piw2);
2200 			sqw3 = SqFindThird (psqW, piw3);
2201 			}
2202 		else if (piw1 == piw2)
2203 			{
2204 			sqw2 = SqFindSecond (psqW, piw2);
2205 			sqw3 = SqFindFirst (psqW, piw3);
2206 			}
2207 		else if (piw2 == piw3)
2208 			{
2209 			sqw2 = SqFindFirst (psqW, piw2);
2210 			sqw3 = SqFindSecond (psqW, piw3);
2211 			}
2212 		else
2213 			{
2214 			sqw2 = SqFindFirst (psqW, piw2);
2215 			sqw3 = SqFindFirst (psqW, piw3);
2216 			}
2217 		sqbk = SqFindKing (psqB);
2218 
2219 		if (x_piecePawn == piw3)
2220 			sqMask = rgsqReflectMaskY [sqbk] ^ rgsqReflectInvertMask [fInvert];
2221 		else
2222 			sqMask = rgsqReflectMaskYandX [sqbk];
2223 		sqwk ^= sqMask;
2224 		sqbk ^= sqMask;
2225 		sqw1 ^= sqMask;
2226 		sqw2 ^= sqMask;
2227 		sqw3 ^= sqMask;
2228 
2229 		if (x_piecePawn == piw3)
2230 			{
2231 			// There are pawns on the board
2232 			if (x_piecePawn == piw1)
2233 				// 3 white pawns
2234 				return	TEnumerate3<x_pieceNone,x_pieceNone,x_pieceNone,true,true>::
2235 							Index(sqbk,sqw1,sqw2,sqw3,sqwk);
2236 			else if (x_piecePawn == piw2)
2237 				// 2 white pawns
2238 				return	TEnumerate2<x_pieceNone,x_pieceNone,true,true>::
2239 							Index(sqbk,sqw2,sqw3,sqwk)*i60 +
2240 						EXCLUDE4(sqw1,sqwk,sqbk,sqw2,sqw3);	// 60
2241 			else if (piw1 == piw2)
2242 				{
2243 				// 1 pawn, 2 pieces equal
2244 				SORT (sqw1, sqw2);
2245 				sqw2 = EXCLUDE3(sqw2,sqwk,sqbk,sqw3);					// 61
2246 				return	TEnumerate1<x_pieceNone,true,true>::
2247 							Index(sqbk,sqw3,sqwk)*(i61*i60/2) +
2248 						sqw2*(sqw2-1)/2+EXCLUDE3(sqw1,sqwk,sqbk,sqw3);	// 61*60/2
2249 				}
2250 			else
2251 				// Only one white pawn
2252 				return	TEnumerate1<x_pieceNone,true,true>::Index(sqbk,sqw3,sqwk)*i61*i60 +
2253 						EXCLUDE3(sqw1,sqwk,sqbk,sqw3)*i60 +	// 61
2254 						EXCLUDE4(sqw2,sqwk,sqbk,sqw1,sqw3);	// 60
2255 			}
2256 		else
2257 			{
2258 			// No pawns
2259 			if (!FInTriangle (sqbk, sqwk))
2260 				{
2261 				sqwk = reflect_xy(sqwk);
2262 				sqw1 = reflect_xy(sqw1);
2263 				sqw2 = reflect_xy(sqw2);
2264 				sqw3 = reflect_xy(sqw3);
2265 				sqbk = reflect_xy(sqbk);
2266 				};
2267 			if (piw1 == piw2 && piw2 == piw3)
2268 				{
2269 				// All 3 pieces equal
2270 				SORT (sqw1, sqw2);
2271 				SORT (sqw2, sqw3);
2272 				SORT (sqw1, sqw2);
2273 				sqw3 = EXCLUDE2(sqw3,sqwk,sqbk);	// 62
2274 				sqw2 = EXCLUDE2(sqw2,sqwk,sqbk);
2275 				return	IndTriKings(sqbk,sqwk)*(i62*i61*i60/6) +
2276 						sqw3*(sqw3-1)*(sqw3-2)/6+
2277 						sqw2*(sqw2-1)/2+
2278 						EXCLUDE2(sqw1,sqwk,sqbk);	// 62*61*60/6
2279 				}
2280 			else if (piw1 == piw2)
2281 				{
2282 				// 2 major pieces equal
2283 				SORT (sqw1, sqw2);
2284 				sqw2 = EXCLUDE3(sqw2,sqwk,sqbk,sqw3);							// 61
2285 				return	IndTriKings(sqbk,sqwk)*(i61*i60/2*i62) +
2286 						(sqw2*(sqw2-1)/2+EXCLUDE3(sqw1,sqwk,sqbk,sqw3))*i62 +	// 61*60/2
2287 						EXCLUDE2(sqw3,sqwk,sqbk);								// 62
2288 				}
2289 			else if (piw2 == piw3)
2290 				{
2291 				// 2 minor pieces equal
2292 				SORT (sqw2, sqw3);
2293 				sqw3 = EXCLUDE3(sqw3,sqwk,sqbk,sqw1);					// 61
2294 				return	IndTriKings(sqbk,sqwk)*(i62*i61*i60/2) +
2295 						EXCLUDE2(sqw1,sqwk,sqbk)*(i61*i60/2) +			// 62
2296 						sqw3*(sqw3-1)/2+EXCLUDE3(sqw2,sqwk,sqbk,sqw1);	// 61*60/2
2297 				}
2298 			else
2299 				return	IndTriKings(sqbk,sqwk)*(i62*i61*i60) +
2300 						EXCLUDE2(sqw1,sqwk,sqbk)*(i61*i60) +	// 62
2301 						EXCLUDE3(sqw2,sqwk,sqbk,sqw1)*i60 +		// 61
2302 						EXCLUDE4(sqw3,sqwk,sqbk,sqw1,sqw2);		// 60
2303 			}
2304 		}
2305 	};
2306 
2307 #endif	// T41
2308 
2309 #else	// Old SJE schema ------------------------------------------------------
2310 
2311 /* scanning pattern: triangle encoding */
2312 
2313 static const INDEX sptriv[] =
2314 	{
2315 	 0,  1,  2,  3, -1, -1, -1, -1,
2316 	-1,  4,  5,  6, -1, -1, -1, -1,
2317 	-1, -1,  7,  8, -1, -1, -1, -1,
2318 	-1, -1, -1,  9, -1, -1, -1, -1,
2319 	-1, -1, -1, -1, -1, -1, -1, -1,
2320 	-1, -1, -1, -1, -1, -1, -1, -1,
2321 	-1, -1, -1, -1, -1, -1, -1, -1,
2322 	-1, -1, -1, -1, -1, -1, -1, -1,
2323 	};
2324 
2325 /* scanning pattern: queenside flank encoding */
2326 
2327 static const INDEX spqsfv[] =
2328 	{
2329 	 0,  1,  2,  3, -1, -1, -1, -1,
2330 	 4,  5,  6,  7, -1, -1, -1, -1,
2331 	 8,  9, 10, 11, -1, -1, -1, -1,
2332 	12, 13, 14, 15, -1, -1, -1, -1,
2333 	16, 17, 18, 19, -1, -1, -1, -1,
2334 	20, 21, 22, 23, -1, -1, -1, -1,
2335 	24, 25, 26, 27, -1, -1, -1, -1,
2336 	28, 29, 30, 31, -1, -1, -1, -1,
2337 	};
2338 
2339 /*--> CalcIndex3A: calculate index, mode 3A */
CalcIndex3A(square sq0,square sq1,square sq2)2340 INLINE INDEX CalcIndex3A
2341 	(
2342 	square sq0,
2343 	square sq1,
2344 	square sq2
2345 	)
2346 	{
2347 	INDEX index;
2348 
2349 	if (TbRow(sq2) > x_row_4)
2350 		{
2351 		sq0 = reflect_x(sq0);
2352 		sq1 = reflect_x(sq1);
2353 		sq2 = reflect_x(sq2);
2354 		};
2355 
2356 	if (TbColumn(sq2) > x_column_d)
2357 		{
2358 		sq0 = reflect_y(sq0);
2359 		sq1 = reflect_y(sq1);
2360 		sq2 = reflect_y(sq2);
2361 		};
2362 
2363 	if (TbRow(sq2) > TbColumn(sq2))
2364 		{
2365 		sq0 = reflect_xy(sq0);
2366 		sq1 = reflect_xy(sq1);
2367 		sq2 = reflect_xy(sq2);
2368 		};
2369 
2370 	index =
2371 		sq0 +
2372 		sq1 * i64 +
2373 		sptriv [sq2] * i64 * i64;
2374 
2375 	return (index);
2376 	}
2377 
2378 /*--> CalcIndex3B: calculate index, mode 3B */
CalcIndex3B(square sq0,square sq1,square sq2)2379 INLINE INDEX CalcIndex3B
2380 	(
2381 	square sq0,
2382 	square sq1,
2383 	square sq2
2384 	)
2385 	{
2386 	INDEX index;
2387 
2388 	if (TbColumn(sq1) > x_column_d)
2389 		{
2390 		sq0 = reflect_y(sq0);
2391 		sq1 = reflect_y(sq1);
2392 		sq2 = reflect_y(sq2);
2393 		};
2394 
2395 	index =
2396 		sq0 +
2397 		spqsfv [sq1] * i64 +
2398 		sq2 * (i64 / 2) * i64;
2399 
2400 	return (index);
2401 	}
2402 
2403 /*--> CalcIndex4A: calculate index, mode 4A */
CalcIndex4A(square sq0,square sq1,square sq2,square sq3)2404 INLINE INDEX CalcIndex4A
2405 	(
2406 	square sq0,
2407 	square sq1,
2408 	square sq2,
2409 	square sq3
2410 	)
2411 	{
2412 	INDEX index;
2413 
2414 	if (TbRow(sq3) > x_row_4)
2415 		{
2416 		sq0 = reflect_x(sq0);
2417 		sq1 = reflect_x(sq1);
2418 		sq2 = reflect_x(sq2);
2419 		sq3 = reflect_x(sq3);
2420 		};
2421 
2422 	if (TbColumn(sq3) > x_column_d)
2423 		{
2424 		sq0 = reflect_y(sq0);
2425 		sq1 = reflect_y(sq1);
2426 		sq2 = reflect_y(sq2);
2427 		sq3 = reflect_y(sq3);
2428 		};
2429 
2430 	if (TbRow(sq3) > TbColumn(sq3))
2431 		{
2432 		sq0 = reflect_xy(sq0);
2433 		sq1 = reflect_xy(sq1);
2434 		sq2 = reflect_xy(sq2);
2435 		sq3 = reflect_xy(sq3);
2436 		};
2437 
2438 	index =
2439 		sq0 +
2440 		sq1 * i64 +
2441 		sq2 * i64 * i64 +
2442 		sptriv [sq3] * i64 * i64 * i64;
2443 
2444 	return (index);
2445 	}
2446 
2447 /*--> CalcIndex4B: calculate index, mode 4B */
CalcIndex4B(square sq0,square sq1,square sq2,square sq3)2448 INLINE INDEX CalcIndex4B
2449 	(
2450 	square sq0,
2451 	square sq1,
2452 	square sq2,
2453 	square sq3
2454 	)
2455 	{
2456 	INDEX index;
2457 
2458 	if (TbColumn(sq3) > x_column_d)
2459 		{
2460 		sq0 = reflect_y(sq0);
2461 		sq1 = reflect_y(sq1);
2462 		sq2 = reflect_y(sq2);
2463 		sq3 = reflect_y(sq3);
2464 		};
2465 
2466 	index =
2467 		sq0 +
2468 		sq1 * i64 +
2469 		sq2 * i64 * i64 +
2470 		spqsfv [sq3] * i64 * i64 * i64;
2471 
2472 	return (index);
2473 	}
2474 
2475 /*--> CalcIndex4C: calculate index, mode 4C */
CalcIndex4C(square sq0,square sq1,square sq2,square sq3)2476 INLINE INDEX CalcIndex4C
2477 	(
2478 	square sq0,
2479 	square sq1,
2480 	square sq2,
2481 	square sq3
2482 	)
2483 	{
2484 	INDEX index;
2485 
2486 	if (TbColumn(sq2) > x_column_d)
2487 		{
2488 		sq0 = reflect_y(sq0);
2489 		sq1 = reflect_y(sq1);
2490 		sq2 = reflect_y(sq2);
2491 		sq3 = reflect_y(sq3);
2492 		};
2493 
2494 	index =
2495 		sq0 +
2496 		sq1 * i64 +
2497 		spqsfv [sq2] * i64 * i64 +
2498 		sq3 * (i64 / 2) * i64 * i64;
2499 
2500 	return (index);
2501 	}
2502 
2503 /*--> CalcIndex5A: calculate index, mode 5A */
CalcIndex5A(square sq0,square sq1,square sq2,square sq3,square sq4)2504 INLINE INDEX CalcIndex5A
2505 	(
2506 	square sq0,
2507 	square sq1,
2508 	square sq2,
2509 	square sq3,
2510 	square sq4
2511 	)
2512 	{
2513 	INDEX index;
2514 
2515 	if (TbRow(sq4) > x_row_4)
2516 		{
2517 		sq0 = reflect_x(sq0);
2518 		sq1 = reflect_x(sq1);
2519 		sq2 = reflect_x(sq2);
2520 		sq3 = reflect_x(sq3);
2521 		sq4 = reflect_x(sq4);
2522 		};
2523 
2524 	if (TbColumn(sq4) > x_column_d)
2525 		{
2526 		sq0 = reflect_y(sq0);
2527 		sq1 = reflect_y(sq1);
2528 		sq2 = reflect_y(sq2);
2529 		sq3 = reflect_y(sq3);
2530 		sq4 = reflect_y(sq4);
2531 		};
2532 
2533 	if (TbRow(sq4) > TbColumn(sq4))
2534 		{
2535 		sq0 = reflect_xy(sq0);
2536 		sq1 = reflect_xy(sq1);
2537 		sq2 = reflect_xy(sq2);
2538 		sq3 = reflect_xy(sq3);
2539 		sq4 = reflect_xy(sq4);
2540 		};
2541 
2542 	index =
2543 		sq0 +
2544 		sq1 * i64 +
2545 		sq2 * i64 * i64 +
2546 		sq3 * i64 * i64 * i64 +
2547 		sptriv [sq4] * i64 * i64 * i64 * i64;
2548 
2549 	return (index);
2550 	}
2551 
2552 /*--> CalcIndex5B: calculate index, mode 5B */
CalcIndex5B(square sq0,square sq1,square sq2,square sq3,square sq4)2553 INLINE INDEX CalcIndex5B
2554 	(
2555 	square sq0,
2556 	square sq1,
2557 	square sq2,
2558 	square sq3,
2559 	square sq4
2560 	)
2561 	{
2562 	INDEX index;
2563 
2564 	if (TbColumn(sq4) > x_column_d)
2565 		{
2566 		sq0 = reflect_y(sq0);
2567 		sq1 = reflect_y(sq1);
2568 		sq2 = reflect_y(sq2);
2569 		sq3 = reflect_y(sq3);
2570 		sq4 = reflect_y(sq4);
2571 		};
2572 
2573 	index =
2574 		sq0 +
2575 		sq1 * i64 +
2576 		sq2 * i64 * i64 +
2577 		sq3 * i64 * i64 * i64 +
2578 		spqsfv [sq4] * i64 * i64 * i64 * i64;
2579 
2580 	return (index);
2581 	}
2582 
2583 /*--> CalcIndex5C: calculate index, mode 5C */
CalcIndex5C(square sq0,square sq1,square sq2,square sq3,square sq4)2584 INLINE INDEX CalcIndex5C
2585 	(
2586 	square sq0,
2587 	square sq1,
2588 	square sq2,
2589 	square sq3,
2590 	square sq4
2591 	)
2592 	{
2593 	INDEX index;
2594 
2595 	if (TbColumn(sq3) > x_column_d)
2596 		{
2597 		sq0 = reflect_y(sq0);
2598 		sq1 = reflect_y(sq1);
2599 		sq2 = reflect_y(sq2);
2600 		sq3 = reflect_y(sq3);
2601 		sq4 = reflect_y(sq4);
2602 		};
2603 
2604 	index =
2605 		sq0 +
2606 		sq1 * i64 +
2607 		sq2 * i64 * i64 +
2608 		spqsfv [sq3] * i64 * i64 * i64 +
2609 		sq4 * (i64 / 2) * i64 * i64 * i64;
2610 
2611 	return (index);
2612 	}
2613 
2614 /*--> CalcIndex5D: calculate index, mode 5D */
CalcIndex5D(square sq0,square sq1,square sq2,square sq3,square sq4)2615 INLINE INDEX CalcIndex5D
2616 	(
2617 	square sq0,
2618 	square sq1,
2619 	square sq2,
2620 	square sq3,
2621 	square sq4
2622 	)
2623 	{
2624 	INDEX index;
2625 
2626 	if (TbColumn(sq2) > x_column_d)
2627 		{
2628 		sq0 = reflect_y(sq0);
2629 		sq1 = reflect_y(sq1);
2630 		sq2 = reflect_y(sq2);
2631 		sq3 = reflect_y(sq3);
2632 		sq4 = reflect_y(sq4);
2633 		};
2634 
2635 	index =
2636 		sq0 +
2637 		sq1 * i64 +
2638 		spqsfv [sq2] * i64 * i64 +
2639 		sq3 * (i64 / 2) * i64 * i64 +
2640 		sq4 * (i64 / 2) * i64 * i64 * i64;
2641 
2642 	return (index);
2643 	}
2644 
2645 // Calculate index - a lot of functions...
2646 
2647 #define	IndCalcW	IndCalc
2648 #define	IndCalcB	IndCalc
2649 
2650 template <int pi> class T21
2651 	{
2652 public:
IndCalc(square * psqW,square * psqB,square sqEnP,int fInvert)2653 	static INDEX TB_FASTCALL IndCalc
2654 		(
2655 		square	*psqW,
2656 		square	*psqB,
2657 		square	sqEnP,
2658 		int		fInvert
2659 		)
2660 		{
2661 		square sq0, sq1, sq2;
2662 
2663 		sq0 = SqFindKing (psqW);
2664 		sq1 = SqFindOne  (psqW, pi);
2665 		sq2 = SqFindKing (psqB);
2666 
2667 		if (x_piecePawn == pi)
2668 			{
2669 			if (fInvert)
2670 				{
2671 				sq0 = reflect_x (sq0);
2672 				sq1 = reflect_x (sq1);
2673 				sq2 = reflect_x (sq2);
2674 				}
2675 			return CalcIndex3B (sq0, sq1, sq2);
2676 			}
2677 		else
2678 			return CalcIndex3A (sq0, sq1, sq2);
2679 		}
2680 	};
2681 
2682 template <int pi1, int pi2> class T22
2683 	{
2684 public:
IndCalc(square * psqW,square * psqB,square sqEnP,int fInvert)2685 	static INDEX TB_FASTCALL IndCalc
2686 		(
2687 		square	*psqW,
2688 		square	*psqB,
2689 		square	sqEnP,
2690 		int		fInvert
2691 		)
2692 		{
2693 		square sq0, sq1, sq2, sq3;
2694 
2695 		sq0 = SqFindKing (psqW);
2696 		sq1 = SqFindOne  (psqW, pi1);
2697 		sq2 = SqFindKing (psqB);
2698 		sq3 = SqFindOne  (psqB, pi2);
2699 
2700 		if (x_piecePawn == pi1 || x_piecePawn == pi2)
2701 			{
2702 			if (fInvert)
2703 				{
2704 				sq0 = reflect_x (sq0);
2705 				sq1 = reflect_x (sq1);
2706 				sq2 = reflect_x (sq2);
2707 				sq3 = reflect_x (sq3);
2708 				}
2709 			return CalcIndex4B (sq0, sq1, sq2, sq3);
2710 			}
2711 		else
2712 			return CalcIndex4A (sq0, sq1, sq2, sq3);
2713 		}
2714 	};
2715 
2716 template <int pi1, int pi2> class T31
2717 	{
2718 public:
IndCalc(square * psqW,square * psqB,square sqEnP,int fInvert)2719 	static INDEX TB_FASTCALL IndCalc
2720 		(
2721 		square	*psqW,
2722 		square	*psqB,
2723 		square	sqEnP,
2724 		int		fInvert
2725 		)
2726 		{
2727 		square sq0, sq1, sq2, sq3;
2728 
2729 		sq0 = SqFindKing (psqW);
2730 		sq1 = SqFindFirst (psqW, pi1);
2731 		if (pi1 == pi2)
2732 			sq2 = SqFindSecond (psqW, pi2);
2733 		else
2734 			sq2 = SqFindFirst (psqW, pi2);
2735 		sq3 = SqFindKing (psqB);
2736 
2737 		if (x_piecePawn == pi1 || x_piecePawn == pi2)
2738 			{
2739 			if (fInvert)
2740 				{
2741 				sq0 = reflect_x (sq0);
2742 				sq1 = reflect_x (sq1);
2743 				sq2 = reflect_x (sq2);
2744 				sq3 = reflect_x (sq3);
2745 				}
2746 			return CalcIndex4C (sq0, sq1, sq2, sq3);
2747 			}
2748 		else
2749 			return CalcIndex4A (sq0, sq1, sq2, sq3);
2750 		}
2751 	};
2752 
2753 template <int pi1, int pi2, int pi3> class T32
2754 	{
2755 public:
IndCalc(square * psqW,square * psqB,square sqEnP,int fInvert)2756 	static INDEX TB_FASTCALL IndCalc
2757 		(
2758 		square	*psqW,
2759 		square	*psqB,
2760 		square	sqEnP,
2761 		int		fInvert
2762 		)
2763 		{
2764 		square sq0, sq1, sq2, sq3, sq4;
2765 
2766 		sq0 = SqFindKing (psqW);
2767 		sq1 = SqFindFirst (psqW, pi1);
2768 		if (pi1 == pi2)
2769 			sq2 = SqFindSecond (psqW, pi2);
2770 		else
2771 			sq2 = SqFindFirst (psqW, pi2);
2772 		sq3 = SqFindKing (psqB);
2773 		sq4 = SqFindOne  (psqB, pi3);
2774 
2775 		if (x_piecePawn == pi1 || x_piecePawn == pi2 || x_piecePawn == pi3)
2776 			{
2777 			if (fInvert)
2778 				{
2779 				sq0 = reflect_x (sq0);
2780 				sq1 = reflect_x (sq1);
2781 				sq2 = reflect_x (sq2);
2782 				sq3 = reflect_x (sq3);
2783 				sq4 = reflect_x (sq4);
2784 				}
2785 			if (x_piecePawn == pi3)
2786 				return CalcIndex5B (sq0, sq1, sq2, sq3, sq4);
2787 			else
2788 				return CalcIndex5D (sq0, sq1, sq2, sq3, sq4);
2789 			}
2790 		else
2791 			return CalcIndex5A (sq0, sq1, sq2, sq3, sq4);
2792 		}
2793 	};
2794 
2795 #if defined (T41_INCLUDE)
2796 
2797 template <int pi1, int pi2, int pi3> class T41
2798 	{
2799 public:
IndCalc(square * psqW,square * psqB,square sqEnP,int fInvert)2800 	static INDEX TB_FASTCALL IndCalc
2801 		(
2802 		square	*psqW,
2803 		square	*psqB,
2804 		square	sqEnP,
2805 		int		fInvert
2806 		)
2807 		{
2808 		square sq0, sq1, sq2, sq3, sq4;
2809 
2810 		sq0 = SqFindKing (psqW);
2811 		sq1 = SqFindFirst (psqW, pi1);
2812 		sq2 = SqFindFirst (psqW, pi2);
2813 		sq3 = SqFindFirst (psqW, pi3);
2814 		sq4 = SqFindKing (psqB);
2815 
2816 		if (x_piecePawn == pi1 || x_piecePawn == pi2 || x_piecePawn == pi3)
2817 			{
2818 			// There are pawns on the board
2819 			if (fInvert)
2820 				{
2821 				sq0 = reflect_x (sq0);
2822 				sq1 = reflect_x (sq1);
2823 				sq2 = reflect_x (sq2);
2824 				sq3 = reflect_x (sq3);
2825 				sq4 = reflect_x (sq4);
2826 				}
2827 			return CalcIndex5C (sq0, sq1, sq2, sq3, sq4);
2828 			}
2829 		else	// No pawns
2830 			return CalcIndex5A (sq0, sq1, sq2, sq3, sq4);
2831 		}
2832 	};
2833 
2834 #endif
2835 
2836 #endif	//----------------------------------------------------------------------
2837 
2838 // All tablebase enumerated
2839 
2840 #if defined (T41_INCLUDE)
2841 #define cTb			146
2842 #else
2843 #define cTb			111
2844 #endif
2845 
2846 #define tbid_kk      0
2847 #define tbid_kpk     1
2848 #define tbid_knk     2
2849 #define tbid_kbk     3
2850 #define tbid_krk     4
2851 #define tbid_kqk     5
2852 #define tbid_kpkp    6
2853 #define tbid_knkp    7
2854 #define tbid_knkn    8
2855 #define tbid_kbkp    9
2856 #define tbid_kbkn   10
2857 #define tbid_kbkb   11
2858 #define tbid_krkp   12
2859 #define tbid_krkn   13
2860 #define tbid_krkb   14
2861 #define tbid_krkr   15
2862 #define tbid_kqkp   16
2863 #define tbid_kqkn   17
2864 #define tbid_kqkb   18
2865 #define tbid_kqkr   19
2866 #define tbid_kqkq   20
2867 #define tbid_kppk   21
2868 #define tbid_knpk   22
2869 #define tbid_knnk   23
2870 #define tbid_kbpk   24
2871 #define tbid_kbnk   25
2872 #define tbid_kbbk   26
2873 #define tbid_krpk   27
2874 #define tbid_krnk   28
2875 #define tbid_krbk   29
2876 #define tbid_krrk   30
2877 #define tbid_kqpk   31
2878 #define tbid_kqnk   32
2879 #define tbid_kqbk   33
2880 #define tbid_kqrk   34
2881 #define tbid_kqqk   35
2882 #define tbid_kppkp  36
2883 #define tbid_kppkn  37
2884 #define tbid_kppkb  38
2885 #define tbid_kppkr  39
2886 #define tbid_kppkq  40
2887 #define tbid_knpkp  41
2888 #define tbid_knpkn  42
2889 #define tbid_knpkb  43
2890 #define tbid_knpkr  44
2891 #define tbid_knpkq  45
2892 #define tbid_knnkp  46
2893 #define tbid_knnkn  47
2894 #define tbid_knnkb  48
2895 #define tbid_knnkr  49
2896 #define tbid_knnkq  50
2897 #define tbid_kbpkp  51
2898 #define tbid_kbpkn  52
2899 #define tbid_kbpkb  53
2900 #define tbid_kbpkr  54
2901 #define tbid_kbpkq  55
2902 #define tbid_kbnkp  56
2903 #define tbid_kbnkn  57
2904 #define tbid_kbnkb  58
2905 #define tbid_kbnkr  59
2906 #define tbid_kbnkq  60
2907 #define tbid_kbbkp  61
2908 #define tbid_kbbkn  62
2909 #define tbid_kbbkb  63
2910 #define tbid_kbbkr  64
2911 #define tbid_kbbkq  65
2912 #define tbid_krpkp  66
2913 #define tbid_krpkn  67
2914 #define tbid_krpkb  68
2915 #define tbid_krpkr  69
2916 #define tbid_krpkq  70
2917 #define tbid_krnkp  71
2918 #define tbid_krnkn  72
2919 #define tbid_krnkb  73
2920 #define tbid_krnkr  74
2921 #define tbid_krnkq  75
2922 #define tbid_krbkp  76
2923 #define tbid_krbkn  77
2924 #define tbid_krbkb  78
2925 #define tbid_krbkr  79
2926 #define tbid_krbkq  80
2927 #define tbid_krrkp  81
2928 #define tbid_krrkn  82
2929 #define tbid_krrkb  83
2930 #define tbid_krrkr  84
2931 #define tbid_krrkq  85
2932 #define tbid_kqpkp  86
2933 #define tbid_kqpkn  87
2934 #define tbid_kqpkb  88
2935 #define tbid_kqpkr  89
2936 #define tbid_kqpkq  90
2937 #define tbid_kqnkp  91
2938 #define tbid_kqnkn  92
2939 #define tbid_kqnkb  93
2940 #define tbid_kqnkr  94
2941 #define tbid_kqnkq  95
2942 #define tbid_kqbkp  96
2943 #define tbid_kqbkn  97
2944 #define tbid_kqbkb  98
2945 #define tbid_kqbkr  99
2946 #define tbid_kqbkq 100
2947 #define tbid_kqrkp 101
2948 #define tbid_kqrkn 102
2949 #define tbid_kqrkb 103
2950 #define tbid_kqrkr 104
2951 #define tbid_kqrkq 105
2952 #define tbid_kqqkp 106
2953 #define tbid_kqqkn 107
2954 #define tbid_kqqkb 108
2955 #define tbid_kqqkr 109
2956 #define tbid_kqqkq 110
2957 
2958 #if defined (T41_INCLUDE)
2959 #define tbid_kpppk 111
2960 #define tbid_knppk 112
2961 #define tbid_knnpk 113
2962 #define tbid_knnnk 114
2963 #define tbid_kbppk 115
2964 #define tbid_kbnpk 116
2965 #define tbid_kbnnk 117
2966 #define tbid_kbbpk 118
2967 #define tbid_kbbnk 119
2968 #define tbid_kbbbk 120
2969 #define tbid_krppk 121
2970 #define tbid_krnpk 122
2971 #define tbid_krnnk 123
2972 #define tbid_krbpk 124
2973 #define tbid_krbnk 125
2974 #define tbid_krbbk 126
2975 #define tbid_krrpk 127
2976 #define tbid_krrnk 128
2977 #define tbid_krrbk 129
2978 #define tbid_krrrk 130
2979 #define tbid_kqppk 131
2980 #define tbid_kqnpk 132
2981 #define tbid_kqnnk 133
2982 #define tbid_kqbpk 134
2983 #define tbid_kqbnk 135
2984 #define tbid_kqbbk 136
2985 #define tbid_kqrpk 137
2986 #define tbid_kqrnk 138
2987 #define tbid_kqrbk 139
2988 #define tbid_kqrrk 140
2989 #define tbid_kqqpk 141
2990 #define tbid_kqqnk 142
2991 #define tbid_kqqbk 143
2992 #define tbid_kqqrk 144
2993 #define tbid_kqqqk 145
2994 #endif
2995 
2996 // Compression
2997 
2998 #include "tbdecode.c"
2999 
3000 #if !defined (CPUS)
3001 #define	CPUS	1
3002 #endif
3003 
3004 #if defined (SMP)
3005 static	lock_t	LockDecode;
3006 #endif
3007 extern "C" { int TB_CRC_CHECK = 0; }
3008 static int cCompressed = 0;
3009 static decode_block *rgpdbDecodeBlocks[CPUS];
3010 
3011 // Information about tablebases
3012 
3013 #define	MAX_TOTAL_PIECES		5	/* Maximum # of pieces on the board */
3014 #define	MAX_NON_KINGS			(MAX_TOTAL_PIECES - 2)
3015 
3016 #if !defined (TB_DIRECTORY_SIZE)
3017 #define	TB_DIRECTORY_SIZE		32	/* # of cache buckets */
3018 #endif
3019 
3020 typedef INDEX (TB_FASTCALL * PfnCalcIndex) (square *psqW, square *psqB,
3021 										 square sqEnP, int fInverse);
3022 struct CTbCache;
3023 
3024 typedef struct		// Hungarian: tbcb
3025 	{
3026 #if defined (SMP)
3027 	lock_t				m_lock;			// Lock on this cache bucket list
3028 #endif
3029 	volatile CTbCache  *m_ptbcFirst;	// Cached file chunks in LRU order
3030 	}
3031 	CTbCacheBucket;
3032 
3033 typedef struct		// Hungarian: tbd
3034 	{
3035 	int				m_iTbId;
3036 	PfnCalcIndex	m_rgpfnCalcIndex[2];
3037 	char			m_rgchName[MAX_TOTAL_PIECES+1];
3038 	INDEX			m_rgcbLength[2];
3039 	char			*m_rgpchFileName[2];
3040 #if defined (SMP)
3041 	lock_t			m_rglockFiles[2];
3042 #endif
3043 	FILE			*m_rgfpFiles[2];
3044 	decode_info		*m_rgpdiDecodeInfo[2];
3045 	CTbCacheBucket	*m_prgtbcbBuckets[2];	// Cached file chunks in LRU order
3046 	BYTE			*m_rgpbRead[2];
3047 	}
3048 	CTbDesc;
3049 
3050 #define	TB(name, funW, funB, cbW, cbB)	{ tbid_##name, { funW, funB }, #name, { cbW, cbB } },
3051 
3052 #define	P	x_piecePawn
3053 #define	N	x_pieceKnight
3054 #define	B	x_pieceBishop
3055 #define	R	x_pieceRook
3056 #define	Q	x_pieceQueen
3057 
3058 CTbDesc	rgtbdDesc[cTb] =
3059 	{
3060 	TB (kk, NULL, NULL, 0, 0)
3061 	TB (kpk, (T21<P>::IndCalcW), (T21<P>::IndCalcB), 81664, 84012)
3062 	TB (knk, (T21<N>::IndCalcW), (T21<N>::IndCalcB), 26282, 28644)
3063 	TB (kbk, (T21<B>::IndCalcW), (T21<B>::IndCalcB), 27243, 28644)
3064 	TB (krk, (T21<R>::IndCalcW), (T21<R>::IndCalcB), 27030, 28644)
3065 	TB (kqk, (T21<Q>::IndCalcW), (T21<Q>::IndCalcB), 25629, 28644)
3066 
3067 	TB (kpkp, (T22<P, P>::IndCalcW), (T22<P, P>::IndCalcB), 3863492, 3863492)
3068 	TB (knkp, (T22<N, P>::IndCalcW), (T22<N, P>::IndCalcB), 4931904, 4981504)
3069 	TB (knkn, (T22<N, N>::IndCalcW), (T22<N, N>::IndCalcB), 1603202, 1603202)
3070 	TB (kbkp, (T22<B, P>::IndCalcW), (T22<B, P>::IndCalcB), 5112000, 4981504)
3071 	TB (kbkn, (T22<B, N>::IndCalcW), (T22<B, N>::IndCalcB), 1661823, 1603202)
3072 	TB (kbkb, (T22<B, B>::IndCalcW), (T22<B, B>::IndCalcB), 1661823, 1661823)
3073 	TB (krkp, (T22<R, P>::IndCalcW), (T22<R, P>::IndCalcB), 5072736, 4981504)
3074 	TB (krkn, (T22<R, N>::IndCalcW), (T22<R, N>::IndCalcB), 1649196, 1603202)
3075 	TB (krkb, (T22<R, B>::IndCalcW), (T22<R, B>::IndCalcB), 1649196, 1661823)
3076 	TB (krkr, (T22<R, R>::IndCalcW), (T22<R, R>::IndCalcB), 1649196, 1649196)
3077 	TB (kqkp, (T22<Q, P>::IndCalcW), (T22<Q, P>::IndCalcB), 4810080, 4981504)
3078 	TB (kqkn, (T22<Q, N>::IndCalcW), (T22<Q, N>::IndCalcB), 1563735, 1603202)
3079 	TB (kqkb, (T22<Q, B>::IndCalcW), (T22<Q, B>::IndCalcB), 1563735, 1661823)
3080 	TB (kqkr, (T22<Q, R>::IndCalcW), (T22<Q, R>::IndCalcB), 1563735, 1649196)
3081 	TB (kqkq, (T22<Q, Q>::IndCalcW), (T22<Q, Q>::IndCalcB), 1563735, 1563735)
3082 	TB (kppk, (T31<P, P>::IndCalcW), (T31<P, P>::IndCalcB), 1806671, 1912372)
3083 	TB (knpk, (T31<N, P>::IndCalcW), (T31<N, P>::IndCalcB), 4648581, 5124732)
3084 	TB (knnk, (T31<N, N>::IndCalcW), (T31<N, N>::IndCalcB),  735304,  873642)
3085 	TB (kbpk, (T31<B, P>::IndCalcW), (T31<B, P>::IndCalcB), 4817128, 5124732)
3086 	TB (kbnk, (T31<B, N>::IndCalcW), (T31<B, N>::IndCalcB), 1550620, 1747284)
3087 	TB (kbbk, (T31<B, B>::IndCalcW), (T31<B, B>::IndCalcB),  789885,  873642)
3088 	TB (krpk, (T31<R, P>::IndCalcW), (T31<R, P>::IndCalcB), 4779530, 5124732)
3089 	TB (krnk, (T31<R, N>::IndCalcW), (T31<R, N>::IndCalcB), 1538479, 1747284)
3090 	TB (krbk, (T31<R, B>::IndCalcW), (T31<R, B>::IndCalcB), 1594560, 1747284)
3091 	TB (krrk, (T31<R, R>::IndCalcW), (T31<R, R>::IndCalcB),  777300,  873642)
3092 	TB (kqpk, (T31<Q, P>::IndCalcW), (T31<Q, P>::IndCalcB), 4533490, 5124732)
3093 	TB (kqnk, (T31<Q, N>::IndCalcW), (T31<Q, N>::IndCalcB), 1459616, 1747284)
3094 	TB (kqbk, (T31<Q, B>::IndCalcW), (T31<Q, B>::IndCalcB), 1512507, 1747284)
3095 	TB (kqrk, (T31<Q, R>::IndCalcW), (T31<Q, R>::IndCalcB), 1500276, 1747284)
3096 	TB (kqqk, (T31<Q, Q>::IndCalcW), (T31<Q, Q>::IndCalcB),  698739,  873642)
3097 
3098 #if !defined (KPPKP_16BIT)
3099 	TB (kppkp, (T32<P, P, P>::IndCalcW), (T32<P, P, P>::IndCalcB),  84219361,  89391280)
3100 #else
3101 	TB (kppkp, (T32<P, P, P>::IndCalcW), (T32<P, P, P>::IndCalcB), 2*84219361, 2*89391280)
3102 #endif
3103 	TB (kppkn, (T32<P, P, N>::IndCalcW), (T32<P, P, N>::IndCalcB), 108400260, 115899744)
3104 	TB (kppkb, (T32<P, P, B>::IndCalcW), (T32<P, P, B>::IndCalcB), 108400260, 120132000)
3105 	TB (kppkr, (T32<P, P, R>::IndCalcW), (T32<P, P, R>::IndCalcB), 108400260, 119209296)
3106 	TB (kppkq, (T32<P, P, Q>::IndCalcW), (T32<P, P, Q>::IndCalcB), 108400260, 113036880)
3107 	TB (knpkp, (T32<N, P, P>::IndCalcW), (T32<N, P, P>::IndCalcB), 219921779, 231758952)
3108 	TB (knpkn, (T32<N, P, N>::IndCalcW), (T32<N, P, N>::IndCalcB), 278914860, 295914240)
3109 	TB (knpkb, (T32<N, P, B>::IndCalcW), (T32<N, P, B>::IndCalcB), 278914860, 306720000)
3110 	TB (knpkr, (T32<N, P, R>::IndCalcW), (T32<N, P, R>::IndCalcB), 278914860, 304369920)
3111 	TB (knpkq, (T32<N, P, Q>::IndCalcW), (T32<N, P, Q>::IndCalcB), 278914860, 288610560)
3112 	TB (knnkp, (T32<N, N, P>::IndCalcW), (T32<N, N, P>::IndCalcB), 137991648, 149445120)
3113 	TB (knnkn, (T32<N, N, N>::IndCalcW), (T32<N, N, N>::IndCalcB),  44118240,  48096060)
3114 	TB (knnkb, (T32<N, N, B>::IndCalcW), (T32<N, N, B>::IndCalcB),  44118240,  49854690)
3115 	TB (knnkr, (T32<N, N, R>::IndCalcW), (T32<N, N, R>::IndCalcB),  44118240,  49475880)
3116 	TB (knnkq, (T32<N, N, Q>::IndCalcW), (T32<N, N, Q>::IndCalcB),  44118240,  46912050)
3117 	TB (kbpkp, (T32<B, P, P>::IndCalcW), (T32<B, P, P>::IndCalcB), 227896016, 231758952)
3118 	TB (kbpkn, (T32<B, P, N>::IndCalcW), (T32<B, P, N>::IndCalcB), 289027680, 295914240)
3119 	TB (kbpkb, (T32<B, P, B>::IndCalcW), (T32<B, P, B>::IndCalcB), 289027680, 306720000)
3120 	TB (kbpkr, (T32<B, P, R>::IndCalcW), (T32<B, P, R>::IndCalcB), 289027680, 304369920)
3121 	TB (kbpkq, (T32<B, P, Q>::IndCalcW), (T32<B, P, Q>::IndCalcB), 289027680, 288610560)
3122 	TB (kbnkp, (T32<B, N, P>::IndCalcW), (T32<B, N, P>::IndCalcB), 290989584, 298890240)
3123 	TB (kbnkn, (T32<B, N, N>::IndCalcW), (T32<B, N, N>::IndCalcB),  93037200,  96192120)
3124 	TB (kbnkb, (T32<B, N, B>::IndCalcW), (T32<B, N, B>::IndCalcB),  93037200,  99709380)
3125 	TB (kbnkr, (T32<B, N, R>::IndCalcW), (T32<B, N, R>::IndCalcB),  93037200,  98951760)
3126 	TB (kbnkq, (T32<B, N, Q>::IndCalcW), (T32<B, N, Q>::IndCalcB),  93037200,  93824100)
3127 	TB (kbbkp, (T32<B, B, P>::IndCalcW), (T32<B, B, P>::IndCalcB), 148223520, 149445120)
3128 	TB (kbbkn, (T32<B, B, N>::IndCalcW), (T32<B, B, N>::IndCalcB),  47393100,  48096060)
3129 	TB (kbbkb, (T32<B, B, B>::IndCalcW), (T32<B, B, B>::IndCalcB),  47393100,  49854690)
3130 	TB (kbbkr, (T32<B, B, R>::IndCalcW), (T32<B, B, R>::IndCalcB),  47393100,  49475880)
3131 	TB (kbbkq, (T32<B, B, Q>::IndCalcW), (T32<B, B, Q>::IndCalcB),  47393100,  46912050)
3132 	TB (krpkp, (T32<R, P, P>::IndCalcW), (T32<R, P, P>::IndCalcB), 226121876, 231758952)
3133 	TB (krpkn, (T32<R, P, N>::IndCalcW), (T32<R, P, N>::IndCalcB), 286777440, 295914240)
3134 	TB (krpkb, (T32<R, P, B>::IndCalcW), (T32<R, P, B>::IndCalcB), 286777440, 306720000)
3135 	TB (krpkr, (T32<R, P, R>::IndCalcW), (T32<R, P, R>::IndCalcB), 286777440, 304369920)
3136 	TB (krpkq, (T32<R, P, Q>::IndCalcW), (T32<R, P, Q>::IndCalcB), 286777440, 288610560)
3137 	TB (krnkp, (T32<R, N, P>::IndCalcW), (T32<R, N, P>::IndCalcB), 288692928, 298890240)
3138 	TB (krnkn, (T32<R, N, N>::IndCalcW), (T32<R, N, N>::IndCalcB),  92308740,  96192120)
3139 	TB (krnkb, (T32<R, N, B>::IndCalcW), (T32<R, N, B>::IndCalcB),  92308740,  99709380)
3140 	TB (krnkr, (T32<R, N, R>::IndCalcW), (T32<R, N, R>::IndCalcB),  92308740,  98951760)
3141 	TB (krnkq, (T32<R, N, Q>::IndCalcW), (T32<R, N, Q>::IndCalcB),  92308740,  93824100)
3142 	TB (krbkp, (T32<R, B, P>::IndCalcW), (T32<R, B, P>::IndCalcB), 299203200, 298890240)
3143 	TB (krbkn, (T32<R, B, N>::IndCalcW), (T32<R, B, N>::IndCalcB),  95673600,  96192120)
3144 	TB (krbkb, (T32<R, B, B>::IndCalcW), (T32<R, B, B>::IndCalcB),  95673600,  99709380)
3145 	TB (krbkr, (T32<R, B, R>::IndCalcW), (T32<R, B, R>::IndCalcB),  95673600,  98951760)
3146 	TB (krbkq, (T32<R, B, Q>::IndCalcW), (T32<R, B, Q>::IndCalcB),  95673600,  93824100)
3147 	TB (krrkp, (T32<R, R, P>::IndCalcW), (T32<R, R, P>::IndCalcB), 145901232, 149445120)
3148 	TB (krrkn, (T32<R, R, N>::IndCalcW), (T32<R, R, N>::IndCalcB),  46658340,  48096060)
3149 	TB (krrkb, (T32<R, R, B>::IndCalcW), (T32<R, R, B>::IndCalcB),  46658340,  49854690)
3150 	TB (krrkr, (T32<R, R, R>::IndCalcW), (T32<R, R, R>::IndCalcB),  46658340,  49475880)
3151 	TB (krrkq, (T32<R, R, Q>::IndCalcW), (T32<R, R, Q>::IndCalcB),  46658340,  46912050)
3152 	TB (kqpkp, (T32<Q, P, P>::IndCalcW), (T32<Q, P, P>::IndCalcB), 214481388, 231758952)
3153 	TB (kqpkn, (T32<Q, P, N>::IndCalcW), (T32<Q, P, N>::IndCalcB), 272015040, 295914240)
3154 	TB (kqpkb, (T32<Q, P, B>::IndCalcW), (T32<Q, P, B>::IndCalcB), 272015040, 306720000)
3155 	TB (kqpkr, (T32<Q, P, R>::IndCalcW), (T32<Q, P, R>::IndCalcB), 272015040, 304369920)
3156 	TB (kqpkq, (T32<Q, P, Q>::IndCalcW), (T32<Q, P, Q>::IndCalcB), 272015040, 288610560)
3157 	TB (kqnkp, (T32<Q, N, P>::IndCalcW), (T32<Q, N, P>::IndCalcB), 273904512, 298890240)
3158 	TB (kqnkn, (T32<Q, N, N>::IndCalcW), (T32<Q, N, N>::IndCalcB),  87576960,  96192120)
3159 	TB (kqnkb, (T32<Q, N, B>::IndCalcW), (T32<Q, N, B>::IndCalcB),  87576960,  99709380)
3160 	TB (kqnkr, (T32<Q, N, R>::IndCalcW), (T32<Q, N, R>::IndCalcB),  87576960,  98951760)
3161 	TB (kqnkq, (T32<Q, N, Q>::IndCalcW), (T32<Q, N, Q>::IndCalcB),  87576960,  93824100)
3162 	TB (kqbkp, (T32<Q, B, P>::IndCalcW), (T32<Q, B, P>::IndCalcB), 283818240, 298890240)
3163 	TB (kqbkn, (T32<Q, B, N>::IndCalcW), (T32<Q, B, N>::IndCalcB),  90750420,  96192120)
3164 	TB (kqbkb, (T32<Q, B, B>::IndCalcW), (T32<Q, B, B>::IndCalcB),  90750420,  99709380)
3165 	TB (kqbkr, (T32<Q, B, R>::IndCalcW), (T32<Q, B, R>::IndCalcB),  90750420,  98951760)
3166 	TB (kqbkq, (T32<Q, B, Q>::IndCalcW), (T32<Q, B, Q>::IndCalcB),  90750420,  93824100)
3167 	TB (kqrkp, (T32<Q, R, P>::IndCalcW), (T32<Q, R, P>::IndCalcB), 281568240, 298890240)
3168 	TB (kqrkn, (T32<Q, R, N>::IndCalcW), (T32<Q, R, N>::IndCalcB),  90038460,  96192120)
3169 	TB (kqrkb, (T32<Q, R, B>::IndCalcW), (T32<Q, R, B>::IndCalcB),  90038460,  99709380)
3170 	TB (kqrkr, (T32<Q, R, R>::IndCalcW), (T32<Q, R, R>::IndCalcB),  90038460,  98951760)
3171 	TB (kqrkq, (T32<Q, R, Q>::IndCalcW), (T32<Q, R, Q>::IndCalcB),  90038460,  93824100)
3172 	TB (kqqkp, (T32<Q, Q, P>::IndCalcW), (T32<Q, Q, P>::IndCalcB), 131170128, 149445120)
3173 	TB (kqqkn, (T32<Q, Q, N>::IndCalcW), (T32<Q, Q, N>::IndCalcB),  41944320,  48096060)
3174 	TB (kqqkb, (T32<Q, Q, B>::IndCalcW), (T32<Q, Q, B>::IndCalcB),  41944320,  49854690)
3175 	TB (kqqkr, (T32<Q, Q, R>::IndCalcW), (T32<Q, Q, R>::IndCalcB),  41944320,  49475880)
3176 	TB (kqqkq, (T32<Q, Q, Q>::IndCalcW), (T32<Q, Q, Q>::IndCalcB),  41944320,  46912050)
3177 
3178 #if defined (T41_INCLUDE)
3179 	TB (kpppk, (T41<P, P, P>::IndCalcW), (T41<P, P, P>::IndCalcB),  26061704,  28388716)
3180 	TB (knppk, (T41<N, P, P>::IndCalcW), (T41<N, P, P>::IndCalcB), 102898651, 114742320)
3181 	TB (knnpk, (T41<N, N, P>::IndCalcW), (T41<N, N, P>::IndCalcB), 130135501, 153741960)
3182 	TB (knnnk, (T41<N, N, N>::IndCalcW), (T41<N, N, N>::IndCalcB),  13486227,  17472840)
3183 	TB (kbppk, (T41<B, P, P>::IndCalcW), (T41<B, P, P>::IndCalcB), 106602156, 114742320)
3184 	TB (kbnpk, (T41<B, N, P>::IndCalcW), (T41<B, N, P>::IndCalcB), 274352939, 307483920)
3185 	TB (kbnnk, (T41<B, N, N>::IndCalcW), (T41<B, N, N>::IndCalcB),  43406294, 52418520)
3186 	TB (kbbpk, (T41<B, B, P>::IndCalcW), (T41<B, B, P>::IndCalcB), 139715040, 153741960)
3187 	TB (kbbnk, (T41<B, B, N>::IndCalcW), (T41<B, B, N>::IndCalcB),  44983618,  52418520)
3188 	TB (kbbbk, (T41<B, B, B>::IndCalcW), (T41<B, B, B>::IndCalcB),  15010230,  17472840)
3189 	TB (krppk, (T41<R, P, P>::IndCalcW), (T41<R, P, P>::IndCalcB), 105758666, 114742320)
3190 	TB (krnpk, (T41<R, N, P>::IndCalcW), (T41<R, N, P>::IndCalcB), 272153675, 307483920)
3191 	TB (krnnk, (T41<R, N, N>::IndCalcW), (T41<R, N, N>::IndCalcB),  43056198,  52418520)
3192 	TB (krbpk, (T41<R, B, P>::IndCalcW), (T41<R, B, P>::IndCalcB), 281991360, 307483920)
3193 	TB (krbnk, (T41<R, B, N>::IndCalcW), (T41<R, B, N>::IndCalcB),  90787358, 104837040)
3194 	TB (krbbk, (T41<R, B, B>::IndCalcW), (T41<R, B, B>::IndCalcB),  46242089,  52418520)
3195 	TB (krrpk, (T41<R, R, P>::IndCalcW), (T41<R, R, P>::IndCalcB), 137491197, 153741960)
3196 	TB (krrnk, (T41<R, R, N>::IndCalcW), (T41<R, R, N>::IndCalcB),  44265261,  52418520)
3197 	TB (krrbk, (T41<R, R, B>::IndCalcW), (T41<R, R, B>::IndCalcB),  45873720,  52418520)
3198 	TB (krrrk, (T41<R, R, R>::IndCalcW), (T41<R, R, R>::IndCalcB),  14644690,  17472840)
3199 	TB (kqppk, (T41<Q, P, P>::IndCalcW), (T41<Q, P, P>::IndCalcB), 100347220, 114742320)
3200 	TB (kqnpk, (T41<Q, N, P>::IndCalcW), (T41<Q, N, P>::IndCalcB), 258294639, 307483920)
3201 	TB (kqnnk, (T41<Q, N, N>::IndCalcW), (T41<Q, N, N>::IndCalcB),  40873646,  52418520)
3202 	TB (kqbpk, (T41<Q, B, P>::IndCalcW), (T41<Q, B, P>::IndCalcB), 267576632, 307483920)
3203 	TB (kqbnk, (T41<Q, B, N>::IndCalcW), (T41<Q, B, N>::IndCalcB),  86166717, 104837040)
3204 	TB (kqbbk, (T41<Q, B, B>::IndCalcW), (T41<Q, B, B>::IndCalcB),  43879679,  52418520)
3205 	TB (kqrpk, (T41<Q, R, P>::IndCalcW), (T41<Q, R, P>::IndCalcB), 265421907, 307483920)
3206 	TB (kqrnk, (T41<Q, R, N>::IndCalcW), (T41<Q, R, N>::IndCalcB),  85470603, 104837040)
3207 	TB (kqrbk, (T41<Q, R, B>::IndCalcW), (T41<Q, R, B>::IndCalcB),  88557959, 104837040)
3208 	TB (kqrrk, (T41<Q, R, R>::IndCalcW), (T41<Q, R, R>::IndCalcB),  43157690,  52418520)
3209 	TB (kqqpk, (T41<Q, Q, P>::IndCalcW), (T41<Q, Q, P>::IndCalcB), 123688859, 153741960)
3210 	TB (kqqnk, (T41<Q, Q, N>::IndCalcW), (T41<Q, Q, N>::IndCalcB),  39840787,  52418520)
3211 	TB (kqqbk, (T41<Q, Q, B>::IndCalcW), (T41<Q, Q, B>::IndCalcB),  41270973,  52418520)
3212 	TB (kqqrk, (T41<Q, Q, R>::IndCalcW), (T41<Q, Q, R>::IndCalcB),  40916820,  52418520)
3213 	TB (kqqqk, (T41<Q, Q, Q>::IndCalcW), (T41<Q, Q, Q>::IndCalcB),  12479974,  17472840)
3214 #endif
3215 	};
3216 
3217 #undef	P
3218 #undef	N
3219 #undef	B
3220 #undef	R
3221 #undef	Q
3222 
3223 //	Helper structure
3224 //	Used to classify on-board position
3225 
3226 union CUTbReference		// Hungarian: utbr
3227 	{
3228 	int				m_iDesc;			// Negative if have to inverse
3229 	int				m_cPieces;
3230 	CUTbReference	*m_utbReference;
3231 	};
3232 
3233 //	Root of the search tree
3234 
3235 static CUTbReference rgutbReference [MAX_NON_KINGS + 2];
3236 
3237 // Convert TB name (e.g. KQKR) into set of counters
3238 
PchSetHalfCounters(int * piCounters,const char * pch)3239 static const char *PchSetHalfCounters
3240 	(
3241 	int			*piCounters,
3242 	const char	*pch
3243 	)
3244 	{
3245 	memset (piCounters, 0, 5 * sizeof (int));
3246 	while ('\0' != *pch && 'k' != *pch)
3247 		{
3248 		piece pi;
3249 
3250 		pi = x_piecePawn;	// To make compiler happy
3251 		switch (*pch)
3252 			{
3253 		case 'p':
3254 			pi = x_piecePawn;
3255 			break;
3256 		case 'n':
3257 			pi = x_pieceKnight;
3258 			break;
3259 		case 'b':
3260 			pi = x_pieceBishop;
3261 			break;
3262 		case 'r':
3263 			pi = x_pieceRook;
3264 			break;
3265 		case 'q':
3266 			pi = x_pieceQueen;
3267 			break;
3268 		default:
3269 			assert (0);
3270 			}
3271 		piCounters [pi-1] ++;
3272 		pch ++;
3273 		}
3274 		return pch;
3275 	};
3276 
VSetCounters(int * piCounters,const char * pch)3277 static void VSetCounters
3278 	(
3279 	int			*piCounters,
3280 	const char	*pch
3281 	)
3282 	{
3283 	assert ('k' == *pch);
3284 	pch = PchSetHalfCounters (piCounters, pch+1);
3285 	assert ('k' == *pch);
3286 	pch = PchSetHalfCounters (piCounters+5, pch+1);
3287 	assert ('\0' == *pch);
3288 	}
3289 
3290 //	Following functions return TB index
3291 //	They differ by input arguments
3292 
IDescFindFromCounters(int * piCount)3293 extern "C" int IDescFindFromCounters
3294 	(
3295 	int	*piCount
3296 	)
3297 	{
3298 	CUTbReference *putbr = rgutbReference;
3299 
3300 	if (piCount[0] > putbr->m_cPieces)
3301 		goto not_found;
3302 	putbr = putbr[1 + piCount[0]].m_utbReference;
3303 	if (piCount[1] > putbr->m_cPieces)
3304 		goto not_found;
3305 	putbr = putbr[1 + piCount[1]].m_utbReference;
3306 	if (piCount[2] > putbr->m_cPieces)
3307 		goto not_found;
3308 	putbr = putbr[1 + piCount[2]].m_utbReference;
3309 	if (piCount[3] > putbr->m_cPieces)
3310 		goto not_found;
3311 	putbr = putbr[1 + piCount[3]].m_utbReference;
3312 	if (piCount[4] > putbr->m_cPieces)
3313 		goto not_found;
3314 	putbr = putbr[1 + piCount[4]].m_utbReference;
3315 	if (piCount[5] > putbr->m_cPieces)
3316 		goto not_found;
3317 	putbr = putbr[1 + piCount[5]].m_utbReference;
3318 	if (piCount[6] > putbr->m_cPieces)
3319 		goto not_found;
3320 	putbr = putbr[1 + piCount[6]].m_utbReference;
3321 	if (piCount[7] > putbr->m_cPieces)
3322 		goto not_found;
3323 	putbr = putbr[1 + piCount[7]].m_utbReference;
3324 	if (piCount[8] > putbr->m_cPieces)
3325 		goto not_found;
3326 	putbr = putbr[1 + piCount[8]].m_utbReference;
3327 	if (piCount[9] <= putbr->m_cPieces)
3328 		return putbr[1 + piCount[9]].m_iDesc;
3329 not_found:
3330 	return 0;
3331 	}
3332 
IDescFind(square * p_piW,square * p_piB,int cWhite,int cBlack)3333 int	IDescFind
3334 	(
3335 	square	*p_piW,	// IN | Pointer to array of white pieces (king excluded)
3336 	square	*p_piB,	// IN | Pointer to array of black pieces (king excluded)
3337 	int		cWhite,	// IN | Counter of white pieces (king excluded)
3338 	int		cBlack	// IN | Counter of black pieces (king excluded)
3339 	)
3340 	{
3341 	int	rgiCount[10];
3342 
3343 	// Set pieces counters
3344 	rgiCount[0] =
3345 	rgiCount[1] =
3346 	rgiCount[2] =
3347 	rgiCount[3] =
3348 	rgiCount[4] =
3349 	rgiCount[5] =
3350 	rgiCount[6] =
3351 	rgiCount[7] =
3352 	rgiCount[8] =
3353 	rgiCount[9] = 0;
3354 	while (cWhite)
3355 		{
3356 		rgiCount[(*p_piW)-1] ++;
3357 		p_piW ++;
3358 		cWhite --;
3359 		}
3360 	while (cBlack)
3361 		{
3362 		rgiCount[5-1+(*p_piB)] ++;
3363 		p_piB ++;
3364 		cBlack --;
3365 		}
3366 	return IDescFindFromCounters (rgiCount);
3367 	}
3368 
IDescFindByName(char * pchName)3369 int	IDescFindByName
3370 	(
3371 	char	*pchName
3372 	)
3373 	{
3374 	int	rgiCount[10];
3375 
3376 	VSetCounters (rgiCount, pchName);
3377 	return IDescFindFromCounters (rgiCount);
3378 	}
3379 
3380 //-----------------------------------------------------------------------------
3381 //
3382 //	Function used during initialization
3383 
3384 //	Set of functions to create search table
3385 
PutbrCreateSubtable(int cPieces,int iDepth)3386 static CUTbReference *PutbrCreateSubtable
3387 	(
3388 	int	cPieces,	//	IN | # of pieces remaining on board
3389 	int	iDepth		//	IN | Recursion depth (# of piece classes left)
3390 	)
3391 	{
3392 	CUTbReference *putbr;
3393 
3394 	putbr = (CUTbReference *) PvMalloc ((cPieces + 2) * sizeof (CUTbReference));
3395 	putbr[0].m_cPieces = cPieces;
3396 	if (0 == iDepth)
3397 		{
3398 		for (int i = 0; i <= cPieces; i ++)
3399 			putbr[i+1].m_iDesc = 0;
3400 		}
3401 	else
3402 		{
3403 		for (int i = 0; i <= cPieces; i ++)
3404 			putbr[i+1].m_utbReference = PutbrCreateSubtable (cPieces-i, iDepth-1);
3405 		}
3406 	return putbr;
3407 	}
3408 
3409 static bool fTbTableCreated = false;
3410 
VCreateEmptyTbTable(void)3411 static void VCreateEmptyTbTable (void)
3412 	{
3413 	if (fTbTableCreated)
3414 		return;
3415 	fTbTableCreated = true;
3416 	rgutbReference[0].m_cPieces = MAX_NON_KINGS;
3417 	for (int i = 0; i <= MAX_NON_KINGS; i ++)
3418 		rgutbReference[i+1].m_utbReference = PutbrCreateSubtable (MAX_NON_KINGS - i, 8);
3419 	}
3420 
3421 // Insert TB (e.g. KQKR) into search table
3422 
FRegisterHalf(int iTb,int * piCount)3423 static bool FRegisterHalf
3424 	(
3425 	int		iTb,
3426 	int		*piCount
3427 	)
3428 	{
3429 	CUTbReference	*putbr;
3430 
3431 	putbr = rgutbReference;
3432 	for (int i = 0; i < 9; i ++)
3433 		{
3434 		if (piCount[i] > putbr->m_cPieces)
3435 			return false;
3436 		putbr = putbr[1 + piCount[i]].m_utbReference;
3437 		}
3438 	if (piCount[9] > putbr->m_cPieces)
3439 		return false;
3440 	putbr[1 + piCount[9]].m_iDesc = iTb;
3441 	return true;
3442 	}
3443 
3444 // Insert TB (both, e.g. KQKR and KRKQ) into search table
3445 
FRegisterTb(CTbDesc * ptbDesc)3446 static bool FRegisterTb
3447 	(
3448 	CTbDesc	*ptbDesc
3449 	)
3450 	{
3451 	int		rgiCount[10];
3452 	bool	fInserted;
3453 
3454 	VSetCounters (rgiCount, ptbDesc->m_rgchName);
3455 	fInserted = FRegisterHalf (ptbDesc->m_iTbId, rgiCount);
3456 	if (fInserted)
3457 		{
3458 		for (int i = 0; i < 5; i ++)
3459 			{
3460 			int	iTemp;
3461 
3462 			iTemp = rgiCount[i];
3463 			rgiCount[i] = rgiCount[i+5];
3464 			rgiCount[i+5] = iTemp;
3465 			}
3466 		fInserted = FRegisterHalf (-ptbDesc->m_iTbId, rgiCount);
3467 		assert (fInserted);
3468 		}
3469 	return fInserted;
3470 	}
3471 
3472 // File mapping - Win32 code only
3473 
3474 #if defined (_WIN32)
3475 
PbMapFileForRead(char * szName,HANDLE * phFile,HANDLE * phFileMapping)3476 static BYTE * PbMapFileForRead
3477 	(
3478 	char	*szName,
3479 	HANDLE	*phFile,
3480 	HANDLE	*phFileMapping
3481 	)
3482 	{
3483 	HANDLE	hFile;
3484 	HANDLE	hFileMapping;
3485 	LPVOID	lpFileBase;
3486 
3487 	hFile = CreateFile (szName, GENERIC_READ, FILE_SHARE_READ,
3488 						NULL, OPEN_EXISTING,
3489 						FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
3490 	if (INVALID_HANDLE_VALUE == hFile)
3491 		{
3492 		printf("*** Couldn't open file %s with CreateFile()\n", szName);
3493 		exit (1);
3494 		}
3495 	hFileMapping = CreateFileMapping (hFile, NULL, PAGE_READONLY, 0, 0, NULL);
3496 	if (0 == hFileMapping)
3497 		{
3498 		CloseHandle (hFile);
3499 		printf ("*** Couldn't open file %s mapping with CreateFileMapping()\n", szName);
3500 		exit (1);
3501 		}
3502 	lpFileBase = MapViewOfFile (hFileMapping, FILE_MAP_READ, 0, 0, 0);
3503 	if (0 == lpFileBase)
3504 		{
3505 		CloseHandle (hFileMapping);
3506 		CloseHandle (hFile);
3507 		printf ("*** Couldn't map view of file %s with MapViewOfFile()\n", szName);
3508 		exit (1);
3509 		}
3510 	if (NULL != phFile)
3511 		*phFile = hFile;
3512 	if (NULL != phFileMapping)
3513 		*phFileMapping = hFileMapping;
3514 	return (BYTE*) lpFileBase;
3515 	}
3516 
VUnmapFile(BYTE * pbFileBase,HANDLE hFile,HANDLE hFileMapping)3517 static void	VUnmapFile
3518 	(
3519 	BYTE	*pbFileBase,
3520 	HANDLE	hFile,
3521 	HANDLE	hFileMapping
3522 	)
3523 	{
3524 	BOOL fFailed;
3525 
3526 	fFailed = (0 == UnmapViewOfFile (pbFileBase)) |
3527 			  (0 == CloseHandle (hFileMapping)) |
3528 			  (0 == CloseHandle (hFile));
3529 	if (fFailed)
3530 		{
3531 		printf ("*** Couldn't unmap file\n");
3532 		exit (1);
3533 		}
3534 	}
3535 
3536 #endif
3537 
3538 //-----------------------------------------------------------------------------
3539 //
3540 //	TB caching
3541 
3542 #if !defined (TB_CB_CACHE_CHUNK)
3543 #define	TB_CB_CACHE_CHUNK			8192 /* Must be power of 2 */
3544 #define	LOG2_TB_CB_CACHE_CHUNK		13
3545 #endif
3546 
3547 #define	TB_DIRECTORY_ENTRY(index)	(((index) >> LOG2_TB_CB_CACHE_CHUNK) % TB_DIRECTORY_SIZE)
3548 
3549 struct CTbCache			//Hungarian: tbc
3550 	{
3551 	volatile	int			m_iTb;
3552 	volatile	color		m_color;
3553 				INDEX		m_indStart;
3554 	volatile	CTbCache	*m_ptbcNext;	// Next element in double-linked general LRU list
3555 	volatile	CTbCache	*m_ptbcPrev;	// Previous element in double-linked general LRU list
3556 	volatile	CTbCache	*m_ptbcTbNext;	// Next element in double-linked cache bucket LRU list
3557 	volatile	CTbCache	*m_ptbcTbPrev;	// Previous element in double-linked cache bucket LRU list
3558 				BYTE		*m_pbData;
3559 	};
3560 
3561 static CTbCache	*ptbcTbCache;	// Cache memory
3562 static ULONG	ctbcTbCache;	// Cache size (in entries)
3563 
3564 static volatile CTbCache	*ptbcHead;		// Head of that list
3565 static volatile CTbCache	*ptbcTail;		// Last element in that list
3566 static volatile CTbCache	*ptbcFree;		// First free cache header
3567 
VTbCloseFile(int iTb,color side)3568 static INLINE void VTbCloseFile
3569 	(
3570 	int		iTb,
3571 	color	side
3572 	)
3573 	{
3574 	if (NULL != rgtbdDesc[iTb].m_rgfpFiles[side])
3575 		{
3576 		Lock (rgtbdDesc[iTb].m_rglockFiles[side]);
3577 		fclose (rgtbdDesc[iTb].m_rgfpFiles[side]);
3578 		rgtbdDesc[iTb].m_rgfpFiles[side] = NULL;
3579 		UnLock (rgtbdDesc[iTb].m_rglockFiles[side]);
3580 		}
3581 	}
3582 
VTbCloseFiles(void)3583 extern "C" void VTbCloseFiles (void)
3584 	{
3585 	// Initialized?
3586 	if (0 == ctbcTbCache)
3587 		return;
3588 
3589 	// Walk through TB cache and close all opened files
3590 	for (int iTb = 1; iTb < cTb; iTb ++)
3591 		{
3592 		VTbCloseFile (iTb, x_colorWhite);
3593 		VTbCloseFile (iTb, x_colorBlack);
3594 		}
3595 	}
3596 
VTbClearCache(void)3597 void VTbClearCache (void)
3598 	{
3599 	CTbCache *ptbc;
3600 	BYTE *pb;
3601 	ULONG i;
3602 
3603 	// Initialized?
3604 	if (0 == ctbcTbCache)
3605 		return;
3606 	VTbCloseFiles();
3607 
3608 	// Initialize all lists
3609 	pb = (BYTE *) & ptbcTbCache [ctbcTbCache];
3610 	for (i = 0, ptbc = ptbcTbCache; i < ctbcTbCache; i ++, ptbc ++)
3611 		{
3612 		ptbc->m_pbData = pb + i*(TB_CB_CACHE_CHUNK+32+4);
3613 		ptbc->m_ptbcTbPrev =
3614 		ptbc->m_ptbcTbNext =
3615 		ptbc->m_ptbcPrev = NULL;
3616 		ptbc->m_ptbcNext = (ptbc + 1);
3617 		}
3618 	ptbc[-1].m_ptbcNext = NULL;
3619 
3620 	// Clear references from TBs
3621 	for (int iTb = 1; iTb < cTb; iTb ++)
3622 		{
3623 		if (NULL != rgtbdDesc[iTb].m_prgtbcbBuckets[x_colorWhite])
3624 			memset (rgtbdDesc[iTb].m_prgtbcbBuckets[x_colorWhite], 0,
3625 					TB_DIRECTORY_SIZE * sizeof (CTbCacheBucket));
3626 		if (NULL != rgtbdDesc[iTb].m_prgtbcbBuckets[x_colorBlack])
3627 			memset (rgtbdDesc[iTb].m_prgtbcbBuckets[x_colorBlack], 0,
3628 					TB_DIRECTORY_SIZE * sizeof (CTbCacheBucket));
3629 		}
3630 
3631 	// Set globals
3632 	ptbcHead = ptbcTail = NULL;
3633 	ptbcFree = ptbcTbCache;
3634 	}
3635 
FTbSetCacheSize(void * pv,ULONG cbSize)3636 extern "C" int FTbSetCacheSize
3637 	(
3638 	void	*pv,
3639 	ULONG	cbSize
3640 	)
3641 	{
3642 	VTbCloseFiles();
3643 	ctbcTbCache = 0;
3644 	ptbcHead = NULL;
3645 	if (cbSize < sizeof (CTbCache))
3646 		return false;
3647 	ptbcTbCache = (CTbCache*) pv;
3648 	ctbcTbCache = cbSize / (sizeof (CTbCache) + TB_CB_CACHE_CHUNK+32+4);
3649 	VTbClearCache();
3650 	return true;
3651 	}
3652 
3653 // Table registered
3654 
3655 #define	FRegistered(iTb, side)	(NULL != rgtbdDesc[iTb].m_rgpchFileName[side])
FRegisteredFun(int iTb,color side)3656 extern "C" int FRegisteredFun
3657 	(
3658 	int		iTb,
3659 	color	side
3660 	)
3661 	{
3662 	return FRegistered (iTb, side);
3663 	}
3664 
3665 // Return function that calculates the necessary index:
3666 
3667 #define PfnIndCalc(iTb, side)	(rgtbdDesc[iTb].m_rgpfnCalcIndex[side])
PfnIndCalcFun(int iTb,color side)3668 extern "C" PfnCalcIndex PfnIndCalcFun
3669 	(
3670 	int		iTb,
3671 	color	side
3672 	)
3673 	{
3674 	return PfnIndCalc (iTb, side);
3675 	}
3676 
3677 
3678 #if defined (_WIN32)
3679 
3680 // Map whole file into memory
3681 
FMapTableToMemory(int iTb,color side)3682 extern "C" int FMapTableToMemory
3683 	(
3684 	int		iTb,	// IN | Tablebase
3685 	color	side	// IN | Side to move
3686 	)
3687 	{
3688 	char *pszName;
3689 
3690 	if (!FRegistered (iTb, side))
3691 		return false;
3692 	if (NULL != rgtbdDesc[iTb].m_rgpdiDecodeInfo[side])
3693 		return false;
3694 	pszName = rgtbdDesc[iTb].m_rgpchFileName[side];
3695 	if (NULL == rgtbdDesc[iTb].m_rgpbRead[side])
3696 		{
3697 		rgtbdDesc[iTb].m_rgpbRead[side] = PbMapFileForRead (pszName, NULL, NULL);
3698 		if (fVerbose)
3699 			printf ("%s mapped\n", pszName);
3700 		}
3701 	return true;
3702 	}
3703 
3704 // Map whole file into memory
3705 
FMapTableToMemory(int iTb,color side,HANDLE * phFile,HANDLE * phFileMapping)3706 int FMapTableToMemory
3707 	(
3708 	int		iTb,			// IN  | Tablebase
3709 	color	side,			// IN  | Side to move
3710 	HANDLE	*phFile,		// OUT | File handle will be written here
3711 	HANDLE	*phFileMapping	// OUT | File mapping handle will be written here
3712 	)
3713 	{
3714 	char *pszName;
3715 
3716 	if (!FRegistered (iTb, side))
3717 		return false;
3718 	pszName = rgtbdDesc[iTb].m_rgpchFileName[side];
3719 	if (NULL == rgtbdDesc[iTb].m_rgpbRead[side])
3720 		{
3721 		rgtbdDesc[iTb].m_rgpbRead[side] = PbMapFileForRead (pszName, phFile, phFileMapping);
3722 		if (fVerbose)
3723 			printf ("%s mapped\n", pszName);
3724 		}
3725 	return true;
3726 	}
3727 
3728 // Unmap whole file from memory
3729 
FUnMapTableFromMemory(int iTb,color side,HANDLE hFile,HANDLE hFileMapping)3730 int FUnMapTableFromMemory
3731 	(
3732 	int		iTb,			// IN | Tablebase
3733 	color	side,			// IN | Side to move
3734 	HANDLE	hFile,			// IN | File handle will be written here
3735 	HANDLE	hFileMapping	// IN | File mapping handle will be written here
3736 	)
3737 	{
3738 	char *pszName;
3739 
3740 	if (!FRegistered (iTb, side))
3741 		return false;
3742 	pszName = rgtbdDesc[iTb].m_rgpchFileName[side];
3743 	if (NULL != rgtbdDesc[iTb].m_rgpbRead[side])
3744 		{
3745 		VUnmapFile (rgtbdDesc[iTb].m_rgpbRead[side], hFile, hFileMapping);
3746 		rgtbdDesc[iTb].m_rgpbRead[side] = NULL;
3747 		if (fVerbose)
3748 			printf ("%s unmapped\n", pszName);
3749 		}
3750 	return true;
3751 	}
3752 
3753 #endif
3754 
3755 // Probe TB
3756 
TbtProbeTable(int iTb,color side,INDEX indOffset)3757 static int	TB_FASTCALL TbtProbeTable
3758 	(
3759 	int		iTb,
3760 	color	side,
3761 	INDEX	indOffset
3762 	)
3763 	{
3764 	CTbDesc	*ptbd;
3765 	int		iDirectory;
3766 	volatile CTbCache	*ptbc;
3767 	volatile CTbCache	*ptbcTbFirst;
3768 
3769 	assert (iTb > 0 && iTb < cTb);
3770 	ptbd = & rgtbdDesc[iTb];
3771 
3772 #if defined (NEW)
3773 	// If we know TB size, it's better for offset be smaller
3774 	assert (!FRegistered (iTb, side) || indOffset < ptbd->m_rgcbLength[side]);
3775 #endif
3776 
3777 	// Entire file read/mapped to memory?
3778 	if (NULL != ptbd->m_rgpbRead[side])
3779 		return (tb_t) ptbd->m_rgpbRead[side][indOffset];
3780 
3781 	// Cache initialized? TB registered?
3782 	if (0 == ctbcTbCache || NULL == ptbd->m_prgtbcbBuckets[side])
3783 		return bev_broken;
3784 
3785 	// Calculate cache bucket
3786 	iDirectory = TB_DIRECTORY_ENTRY (indOffset);
3787 
3788 	// Head of the cache bucket LRU list
3789 	Lock (ptbd->m_prgtbcbBuckets[side][iDirectory].m_lock);
3790 	ptbcTbFirst = ptbd->m_prgtbcbBuckets[side][iDirectory].m_ptbcFirst;
3791 
3792 	// First, search entry in the cache
3793 	for (ptbc = ptbcTbFirst; NULL != ptbc; ptbc = ptbc->m_ptbcTbNext)
3794 		{
3795 		if ((indOffset >= ptbc->m_indStart) && (indOffset < ptbc->m_indStart + TB_CB_CACHE_CHUNK))
3796 			{
3797 			// Found - move cache entry to the head of the general LRU list
3798 			Lock (lockLRU);
3799 			if (ptbc != ptbcHead)
3800 				{
3801 				// Remove it from its current position
3802 				ptbc->m_ptbcPrev->m_ptbcNext = ptbc->m_ptbcNext;
3803 				if (NULL == ptbc->m_ptbcNext)
3804 					ptbcTail = ptbc->m_ptbcPrev;
3805 				else
3806 					ptbc->m_ptbcNext->m_ptbcPrev = ptbc->m_ptbcPrev;
3807 				// Insert it at the head
3808 				ptbc->m_ptbcPrev = NULL;
3809 				ptbc->m_ptbcNext = ptbcHead;
3810 				ptbcHead->m_ptbcPrev = ptbc;
3811 				ptbcHead = ptbc;
3812 				}
3813 			UnLock (lockLRU);
3814 			// Move cache entry to the head of the cache bucket LRU list
3815 			if (ptbc != ptbcTbFirst)
3816 				{
3817 				// Remove it from list
3818 				ptbc->m_ptbcTbPrev->m_ptbcTbNext = ptbc->m_ptbcTbNext;
3819 				if (NULL != ptbc->m_ptbcTbNext)
3820 					ptbc->m_ptbcTbNext->m_ptbcTbPrev = ptbc->m_ptbcTbPrev;
3821 				// Insert it at head
3822 				ptbc->m_ptbcTbPrev = NULL;
3823 				ptbc->m_ptbcTbNext = ptbcTbFirst;
3824 				ptbcTbFirst->m_ptbcTbPrev = ptbc;
3825 				ptbd->m_prgtbcbBuckets[side][iDirectory].m_ptbcFirst = ptbc;
3826 				}
3827 			int	tb;
3828 
3829 			tb = (tb_t) (ptbc->m_pbData[(ULONG)(indOffset-ptbc->m_indStart)]);
3830 			UnLock (ptbd->m_prgtbcbBuckets[side][iDirectory].m_lock);
3831 			return tb;
3832 			}
3833 		}
3834 	// Not in the cache - have to read it from disk.
3835 	// I decided to write simple code - so sometimes it's possible that
3836 	// 2 threads will simultaneously read exactly the same chunk into 2
3837 	// different cache entries. In that case, all subsequent cache probes
3838 	// will hit the first cache entry, so the second one will 'drift' to
3839 	// the end of general LRU list and will be reused.
3840 
3841 	// Unlock cache bucket, so other threads can continue execution
3842 	UnLock (ptbd->m_prgtbcbBuckets[side][iDirectory].m_lock);
3843 	// First, find cache entry we can use
3844 	Lock (lockLRU);
3845 	// Get it either from a free list, or reuse last element of the LRU list
3846 	if (NULL != ptbcFree)
3847 		{
3848 		ptbc = ptbcFree;
3849 		ptbcFree = ptbc->m_ptbcNext;
3850 		UnLock (lockLRU);
3851 		}
3852 	else
3853 		{
3854 		int		iTailDirectory;
3855 		int		iTailTb;
3856 		color	colorTail;
3857 
3858 		assert (NULL != ptbcTail);
3859 #if defined (SMP)
3860 		// "Optimistic" model - assuming that there is low content
3861 		// (not hundreds of threads)
3862 		for (;;)
3863 			{
3864 			ptbc = ptbcTail;
3865 			iTailTb = ptbc->m_iTb;
3866 			iTailDirectory = TB_DIRECTORY_ENTRY (ptbc->m_indStart);
3867 			colorTail = ptbc->m_color;
3868 			// To avoid deadlocks, have to first acquire cache buckets lock,
3869 			// and only then general LRU lock. So, free general LRU lock and
3870 			// acquire 2 locks in a proper order.
3871 			UnLock (lockLRU);
3872 			Lock (rgtbdDesc[iTailTb].m_prgtbcbBuckets[colorTail][iTailDirectory].m_lock);
3873 			Lock (lockLRU);
3874 			// Have structures been modified while we re-acquired locks?
3875 			// (to be more precise, it's Ok, if structures were modified,
3876 			// but cache entry again become the last element of the list,
3877 			// and TB, color, and cache bucket did not changed, so we locked
3878 			// proper locks).
3879 			if (ptbc == ptbcTail && ptbc->m_iTb == iTailTb &&
3880 				ptbc->m_color == colorTail &&
3881 				TB_DIRECTORY_ENTRY (ptbc->m_indStart) == iTailDirectory)
3882 				break;
3883 			// Sorry - try once again...
3884 			UnLock (rgtbdDesc[iTailTb].m_prgtbcbBuckets[colorTail][iTailDirectory].m_lock);
3885 			}
3886 #else
3887 		ptbc = ptbcTail;
3888 		iTailTb = ptbc->m_iTb;
3889 		iTailDirectory = TB_DIRECTORY_ENTRY (ptbc->m_indStart);
3890 		colorTail = ptbc->m_color;
3891 #endif
3892 
3893 		// Remove cache entry from the general LRU list
3894 		ptbcTail = ptbc->m_ptbcPrev;
3895 		if (NULL == ptbcTail)
3896 			ptbcHead = NULL;
3897 		else
3898 			ptbcTail->m_ptbcNext = NULL;
3899 		UnLock (lockLRU);
3900 
3901 		// Remove it from cache bucket list
3902 		if (NULL != ptbc->m_ptbcTbNext)
3903 			ptbc->m_ptbcTbNext->m_ptbcTbPrev = ptbc->m_ptbcTbPrev;
3904 		if (NULL == ptbc->m_ptbcTbPrev)
3905 			rgtbdDesc[iTailTb].m_prgtbcbBuckets[colorTail][iTailDirectory].m_ptbcFirst = ptbc->m_ptbcTbNext;
3906 		else
3907 			ptbc->m_ptbcTbPrev->m_ptbcTbNext = ptbc->m_ptbcTbNext;
3908 		UnLock (rgtbdDesc[iTailTb].m_prgtbcbBuckets[colorTail][iTailDirectory].m_lock);
3909 		}
3910 
3911 	// Ok, now we have "orphan" cache entry - it's excluded from all lists,
3912 	// so other threads will never touch it.
3913 	ptbc->m_iTb = iTb;
3914 	ptbc->m_color = side;
3915 	ptbc->m_indStart = indOffset / (INDEX) (TB_CB_CACHE_CHUNK) * TB_CB_CACHE_CHUNK;
3916 
3917 	// Now read it from the disk
3918 	FILE	*fp;
3919 	size_t	cb;
3920 
3921 	// First, check: is necessary file opened?
3922 	// As files are not thread-safe, lock file
3923 	Lock (ptbd->m_rglockFiles[side]);
3924 	fp = ptbd->m_rgfpFiles[side];
3925 	if (NULL == fp)
3926 		{
3927 		// Not - try to open it
3928 		fp = fopen (ptbd->m_rgpchFileName[side], "rb");
3929 		if (NULL == fp)
3930 			{
3931 			// Failed. Close all the opened files and retry
3932 			UnLock (ptbd->m_rglockFiles[side]);
3933 			VTbCloseFiles ();
3934 			Lock (ptbd->m_rglockFiles[side]);
3935 			// Theoretically, it's possible that other threads opened a lot of
3936 			// files in the interval between VTbCloseFiles() and Lock(). If
3937 			// so, we'll fail - I don't like to have one more global lock
3938 			// especially for file open, at least not in first version.
3939 			// Problem can happen only on systems with small limit of
3940 			// simultaneously open files and high number of threads - unlikely
3941 			// combination.
3942 			fp = ptbd->m_rgfpFiles[side];
3943 			if (NULL == fp)
3944 				{
3945 				fp = fopen (ptbd->m_rgpchFileName[side], "rb");
3946 				if (NULL == fp)
3947 					goto ERROR_LABEL;
3948 				}
3949 			}
3950 		ptbd->m_rgfpFiles[side] = fp;
3951 		}
3952 
3953 	// File opened. Now seek and read necessary chunk
3954 	if (NULL == ptbd->m_rgpdiDecodeInfo[side])
3955 		{
3956 		// Read uncompressed file
3957 		if (fseek (fp, (long) ptbc->m_indStart, SEEK_SET))
3958 			goto ERROR_LABEL;
3959 		cb = fread (ptbc->m_pbData, 1, TB_CB_CACHE_CHUNK, fp);
3960 		if (cb != TB_CB_CACHE_CHUNK && ferror (fp))
3961 			goto ERROR_LABEL;
3962 		assert (cb > (indOffset-ptbc->m_indStart));
3963 		UnLock (ptbd->m_rglockFiles[side]);
3964 		}
3965 	else
3966 		{
3967 		// Read compressed file
3968 		int	fWasError;
3969 		decode_block	*block;
3970 		decode_info		*info = ptbd->m_rgpdiDecodeInfo[side];
3971 
3972 #if defined (SMP)
3973 		// Find free decode block
3974 		decode_block	**pBlock;
3975 
3976 		Lock (lockDecode);
3977 		pBlock = rgpdbDecodeBlocks;
3978 		while (NULL == *pBlock)
3979 			pBlock ++;
3980 		block = *pBlock;
3981 		*pBlock = NULL;
3982 		UnLock (lockDecode);
3983 #else
3984 		block = rgpdbDecodeBlocks[0];
3985 #endif
3986 
3987 		// Initialize decode block and read chunk
3988 		fWasError = 0 != comp_init_block (block, TB_CB_CACHE_CHUNK, ptbc->m_pbData) ||
3989 					0 != comp_read_block (block, info, fp, indOffset / TB_CB_CACHE_CHUNK);
3990 
3991 		// Release lock on file, so other threads can proceed with that file
3992 		UnLock (ptbd->m_rglockFiles[side]);
3993 
3994 		// Decompress chunk
3995 		if (!fWasError)
3996 			fWasError |= (0 != comp_decode_and_check_crc (block, info, block->orig.size, TB_CRC_CHECK));
3997 
3998 		// Release block
3999 #if defined (SMP)
4000 		Lock (lockDecode);
4001 		*pBlock = block;
4002 		UnLock (lockDecode);
4003 #endif
4004 
4005 		// Read Ok?
4006 		if (fWasError)
4007 			goto ERROR_LABEL_2;
4008 		}
4009 
4010 	// Read - now acquire locks and insert cache entry in both lists
4011 	Lock (ptbd->m_prgtbcbBuckets[side][iDirectory].m_lock);
4012 	Lock (lockLRU);
4013 
4014 	// Insert cache entry into general LRU list
4015 	ptbc->m_ptbcPrev = NULL;
4016 	ptbc->m_ptbcNext = ptbcHead;
4017 	if (NULL == ptbcHead)
4018 		ptbcTail = ptbc;
4019 	else
4020 		ptbcHead->m_ptbcPrev = ptbc;
4021 	ptbcHead = ptbc;
4022 
4023 	// Insert cache entry into cache bucket LRU list
4024 	ptbc->m_ptbcTbPrev = NULL;
4025 	ptbc->m_ptbcTbNext = ptbd->m_prgtbcbBuckets[side][iDirectory].m_ptbcFirst;
4026 	if (NULL != ptbc->m_ptbcTbNext)
4027 		ptbc->m_ptbcTbNext->m_ptbcTbPrev = ptbc;
4028 	ptbd->m_prgtbcbBuckets[side][iDirectory].m_ptbcFirst = ptbc;
4029 
4030 	// All done
4031 	int tb;
4032 
4033 	tb = (tb_t) (ptbc->m_pbData[(ULONG)(indOffset-ptbc->m_indStart)]);
4034 	// Release locks
4035 	UnLock (ptbd->m_prgtbcbBuckets[side][iDirectory].m_lock);
4036 	UnLock (lockLRU);
4037 	return tb;
4038 
4039 	// I/O error. Here I don't want to halt the program, because that can
4040 	// happen in the middle of the important game. Just return failure.
4041 ERROR_LABEL:
4042 	UnLock (ptbd->m_rglockFiles[side]);
4043 ERROR_LABEL_2:
4044 	Lock (lockLRU);
4045 	ptbd->m_rgpchFileName[side] = NULL;
4046 	ptbc->m_ptbcNext = ptbcFree;
4047 	ptbcFree = ptbc;
4048 	UnLock (lockLRU);
4049 	return bev_broken;
4050 	}
4051 
4052 // 16-bit version (recommended)
4053 
L_TbtProbeTable(int iTb,color side,INDEX indOffset)4054 extern "C" int TB_FASTCALL L_TbtProbeTable
4055 	(
4056 	int		iTb,
4057 	color	side,
4058 	INDEX	indOffset
4059 	)
4060 	{
4061 	int	tbtScore;
4062 
4063 #if !defined (KPPKP_16BIT)
4064 	if (tbid_kppkp == iTb && x_colorBlack == side &&
4065 		(indOffset == 0x0362BC7C || indOffset == 0x0362DE44 || indOffset == 0x03637648 ||
4066 		 indOffset == 0x03639810 || indOffset == 0x038D4F29 || indOffset == 0x040A2CAB ||
4067 		 indOffset == 0x043C778C))
4068 		return -32639;
4069 	tbtScore = TbtProbeTable (iTb, side, indOffset);
4070 	tbtScore = S_to_L (tbtScore);
4071 #else
4072 	if (tbid_kppkp != iTb)
4073 		{
4074 		// All tables but kppkp are 8-bit tables
4075 		tbtScore = TbtProbeTable (iTb, side, indOffset);
4076 		tbtScore = S_to_L (tbtScore);
4077 		}
4078 	else
4079 		{
4080 		// Special handling of kppkp - it's 16-bit table
4081 		// Inefficient, but very simple, code
4082 		int	iLo;
4083 		int	iHi;
4084 
4085 		indOffset *= 2;
4086 		iLo = TbtProbeTable (iTb, side, indOffset);
4087 		iHi = TbtProbeTable (iTb, side, indOffset+1);
4088 		tbtScore = (bev_broken == iHi) ? L_bev_broken : (iHi << 8) + (iLo & 0xFF);
4089 		}
4090 #endif
4091 	return tbtScore;
4092 	}
4093 
4094 //-----------------------------------------------------------------------------
4095 //
4096 //	Global initialization
4097 
FCheckExistence(char * pszPath,int iTb,color side)4098 int FCheckExistence
4099 	(
4100 	char	*pszPath,
4101 	int		iTb,
4102 	color	side
4103 	)
4104 	{
4105 	FILE			*fp;
4106 	char			*pchCopy;
4107 	const char		*pchExt = PchExt (side);
4108 	char			rgchTbName[256];
4109 	CTbCacheBucket	*prgtbcbBuckets;
4110 	INDEX			cb;
4111 	decode_info		*comp_info = NULL;
4112 
4113 	if (FRegistered (iTb, side) || NULL != rgtbdDesc[iTb].m_rgpbRead[side])
4114 		return true;
4115 
4116 	strcpy (rgchTbName, pszPath);
4117 	if (0 != pszPath[0])
4118 		{
4119 #if defined (_WIN32)
4120 		strcat (rgchTbName, "\\");
4121 #elif defined (__MWERKS__)
4122 		strcat (rgchTbName, ":");
4123 #else
4124 		strcat (rgchTbName, "/");
4125 #endif
4126 		}
4127 	strcat (rgchTbName, rgtbdDesc[iTb].m_rgchName);
4128 	strcat (rgchTbName, pchExt);
4129 	fp = fopen (rgchTbName, "rb");
4130 #if !defined (NEW) && !defined (_WIN32)
4131 	// For case-sensitive systems, have to try once more
4132 	if (NULL == fp)
4133 		{
4134 		for (int i = strchr(rgchTbName,'.')-rgchTbName-1; i>=0 && isalpha(rgchTbName[i]); i--)
4135 			rgchTbName[i] = toupper (rgchTbName[i]);
4136 		fp = fopen (rgchTbName, "rb");
4137 		}
4138 #endif
4139 	if (NULL != fp)
4140 		{
4141 		// Found uncompressed table
4142 		if (0 != fseek (fp, 0L, SEEK_END))
4143 			{
4144 			printf ("*** Seek in %s failed\n", rgchTbName);
4145 			exit (1);
4146 			}
4147 		cb = (INDEX) ftell (fp);
4148 #if defined (NEW)
4149 		if (0 != rgtbdDesc[iTb].m_rgcbLength[side] && cb != rgtbdDesc[iTb].m_rgcbLength[side])
4150 			{
4151 			printf ("*** %s corrupted\n", rgchTbName);
4152 			exit (1);
4153 			}
4154 #endif
4155 		}
4156 	else
4157 		{
4158 		// Check for compressed table.
4159 		// First, check for kxykz.nb?.emd
4160 		strcat (rgchTbName, ".emd");
4161 		fp = fopen (rgchTbName, "rb");
4162 		if (NULL == fp)
4163 			{
4164 			// Check for kxykznb?.emd (8+3 format)
4165 			int	cch;
4166 
4167 			cch = strlen (rgchTbName);
4168 			memmove (rgchTbName+cch-8, rgchTbName+cch-7, 8);
4169 			fp = fopen (rgchTbName, "rb");
4170 			if (NULL == fp)
4171 				return false;
4172 			}
4173 		cCompressed ++;
4174 		int iResult = comp_open_file (&comp_info, fp, TB_CRC_CHECK);
4175 		if (0 != iResult)
4176 			{
4177 			printf ("*** Unable to read %s - ", rgchTbName);
4178 			switch (iResult & 0xFF)
4179 				{
4180 			case COMP_ERR_READ:
4181 				printf ("read error\n");
4182 				break;
4183 			case COMP_ERR_NOMEM:
4184 				printf ("out of memory\n");
4185 				break;
4186 			case COMP_ERR_BROKEN:
4187 				printf ("file broken\n");
4188 				break;
4189 			default:
4190 				printf ("error %d\n", iResult);
4191 				break;
4192 				}
4193 			exit (1);
4194 			}
4195 		if (comp_info->block_size != TB_CB_CACHE_CHUNK)
4196 			{
4197 			printf ("*** %s: Unsupported block size %d\n", rgchTbName, comp_info->block_size);
4198 			exit (1);
4199 			}
4200 		cb = comp_info->block_size*(comp_info->n_blk-1) + comp_info->last_block_size;
4201 #if defined (NEW)
4202 		if (0 != rgtbdDesc[iTb].m_rgcbLength[side] && cb != rgtbdDesc[iTb].m_rgcbLength[side])
4203 			{
4204 			printf ("*** %s corrupted\n", rgchTbName);
4205 			exit (1);
4206 			}
4207 #endif
4208 		}
4209 	rgtbdDesc[iTb].m_rgcbLength[side] = cb;
4210 	fclose (fp);
4211 	if (FRegisterTb (& (rgtbdDesc[iTb])))
4212 		{
4213 		pchCopy = (char*) PvMalloc (strlen(rgchTbName)+1);
4214 		strcpy (pchCopy, rgchTbName);
4215 		rgtbdDesc[iTb].m_rgpchFileName[side] = pchCopy;
4216 		prgtbcbBuckets = (CTbCacheBucket*) PvMalloc (TB_DIRECTORY_SIZE*sizeof(CTbCacheBucket));
4217 		memset (prgtbcbBuckets, 0, TB_DIRECTORY_SIZE*sizeof(CTbCacheBucket));
4218 #if defined (SMP)
4219 		for (int i = 0; i < TB_DIRECTORY_SIZE; i ++)
4220 			LockInit (prgtbcbBuckets[i].m_lock);
4221 #endif
4222 		rgtbdDesc[iTb].m_prgtbcbBuckets[side] = prgtbcbBuckets;
4223 		rgtbdDesc[iTb].m_rgpdiDecodeInfo[side] = comp_info;
4224 		if (fVerbose)
4225 			printf ("%s registered\n", pchCopy);
4226 		return true;
4227 		}
4228 	else
4229 		{
4230 		printf ("*** Unable to register %s\n", rgchTbName);
4231 		exit (1);
4232 		}
4233 	return false;
4234 	}
4235 
IInitializeTb(char * pszPath)4236 extern "C" int IInitializeTb
4237 	(
4238 	char *pszPath
4239 	)
4240 	{
4241 	char	szTemp[1024];
4242 	color	sd;
4243 	int		iTb, iMaxTb, i;
4244 
4245 	cbAllocated = cbEGTBCompBytes = 0;
4246 	// If there are open files, close those
4247 	VTbCloseFiles ();
4248 #if defined (SMP)
4249 	// Init all locks
4250 	LockInit (lockLRU);
4251 	LockInit (LockDecode);
4252 	for (iTb = 1; iTb < cTb; iTb ++)
4253 		{
4254 		LockInit (rgtbdDesc[iTb].m_rglockFiles[x_colorWhite]);
4255 		LockInit (rgtbdDesc[iTb].m_rglockFiles[x_colorBlack]);
4256 		}
4257 #endif
4258 #if defined (NEW)
4259 	// Create enumeration tables
4260 	VInitEnumerations ();
4261 #endif
4262 	// Create empty TB search table
4263 	VCreateEmptyTbTable ();
4264 	// Free memory from TB table
4265 	for (iTb = 1; iTb < cTb; iTb ++)
4266 		{
4267 		for (sd = x_colorWhite; sd <= x_colorBlack; sd = (color) (sd + 1))
4268 			{
4269 			if (NULL != rgtbdDesc[iTb].m_prgtbcbBuckets[sd] &&
4270 				NULL == rgtbdDesc[iTb].m_rgpbRead[sd])
4271 				{
4272 #ifdef WINCE
4273 				my_Tcl_Free ((char*)rgtbdDesc[iTb].m_prgtbcbBuckets[sd]);
4274 #else
4275         free (rgtbdDesc[iTb].m_prgtbcbBuckets[sd]);
4276 #endif
4277 				rgtbdDesc[iTb].m_prgtbcbBuckets[sd] = NULL;
4278 				}
4279 			if (NULL != rgtbdDesc[iTb].m_rgpchFileName[sd])
4280 				{
4281 #ifdef WINCE
4282         my_Tcl_Free ((char*)rgtbdDesc[iTb].m_rgpchFileName[sd]);
4283 #else
4284         free (rgtbdDesc[iTb].m_rgpchFileName[sd]);
4285 #endif
4286 				rgtbdDesc[iTb].m_rgpchFileName[sd] = NULL;
4287 				}
4288 			if (NULL != rgtbdDesc[iTb].m_rgpdiDecodeInfo[sd])
4289 				{
4290 #ifdef WINCE
4291         my_Tcl_Free ((char*)rgtbdDesc[iTb].m_rgpdiDecodeInfo[sd]);
4292 #else
4293         free (rgtbdDesc[iTb].m_rgpdiDecodeInfo[sd]);
4294 #endif
4295 				rgtbdDesc[iTb].m_rgpdiDecodeInfo[sd] = NULL;
4296 				}
4297 			}
4298 		}
4299 	// Free compressed blocks
4300 	for (i = 0; i < CPUS; i ++)
4301 		{
4302 		if (NULL != rgpdbDecodeBlocks[i])
4303 			{
4304 #ifdef WINCE
4305       my_Tcl_Free ((char*)rgpdbDecodeBlocks[i]);
4306 #else
4307       free (rgpdbDecodeBlocks[i]);
4308 #endif
4309 			rgpdbDecodeBlocks[i] = NULL;
4310 			}
4311 		}
4312 	// Search for existing TBs
4313 	iMaxTb = 0;
4314 	for (;;)
4315 		{
4316 		for (i = 0; pszPath[i] != '\0' && pszPath[i] != ',' && pszPath[i] != ';'
4317 #if !defined (_WIN32) && !defined (__MWERKS__)
4318 			 && pszPath[i] != ':'
4319 #endif
4320 			 ; i ++)
4321 			{
4322 			szTemp[i] = pszPath[i];
4323 			}
4324 		szTemp[i] = '\0';
4325 		for (iTb = 1; iTb < cTb; iTb ++)
4326 			{
4327 			if (FCheckExistence (szTemp, iTb, x_colorWhite))
4328 				{
4329 				if (iTb > iMaxTb)
4330 					iMaxTb = iTb;
4331 				}
4332 			if (FCheckExistence (szTemp, iTb, x_colorBlack))
4333 				{
4334 				if (iTb > iMaxTb)
4335 					iMaxTb = iTb;
4336 				}
4337 			}
4338 		pszPath += i;
4339 		if ('\0' == *pszPath)
4340 			break;
4341 		pszPath ++;
4342 		}
4343 
4344 	// If there were compressed files, have to allocate buffer(s)
4345 	if (0 != cCompressed)
4346 		{
4347 		for (i = 0; i < CPUS; i ++)
4348 			{
4349 			int iResult = comp_alloc_block (&rgpdbDecodeBlocks[i], TB_CB_CACHE_CHUNK);
4350 			if (0 != iResult)
4351 				{
4352 				printf ("*** Cannot allocate decode block: error code %d\n", iResult);
4353 				exit (1);
4354 				}
4355 			}
4356 		if (fVerbose)
4357 			printf ("Allocated %dKb for decompression tables, indices, and buffers.\n",
4358 					(cbEGTBCompBytes+1023)/1024);
4359 		}
4360 
4361 	// All done!
4362 	if (iMaxTb >= tbid_kppkp)
4363 		return 5;
4364 	else if (iMaxTb >= tbid_kpkp)
4365 		return 4;
4366 	else if (iMaxTb >= tbid_kpk)
4367 		return 3;
4368 	return 0;
4369 	}
4370 
4371 #endif
4372