Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
33 pmbaty 1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <string.h>
4
#include <ctype.h>
5
#if defined(_WIN32)
6
#include <windows.h>
7
#endif
8
 
9
#define NEW
10
#define T41_INCLUDE
11
#define T42_INCLUDE
12
#define T33_INCLUDE
108 pmbaty 13
#define T_INDEX64
33 pmbaty 14
#define  XX  127
15
 
16
#if defined (T_INDEX64) && defined (_MSC_VER)
17
typedef unsigned __int64 INDEX;
18
#elif defined (T_INDEX64)
19
typedef unsigned long long INDEX;
20
#else
21
typedef unsigned long INDEX;
22
#endif
23
 
24
typedef unsigned int square;
25
 
26
typedef int color;
27
 
28
#define  x_colorWhite    0
29
#define  x_colorBlack    1
30
#define  x_colorNeutral  2
31
 
32
typedef int piece;
33
 
34
#define  x_pieceNone     0
35
#define  x_piecePawn     1
36
#define  x_pieceKnight   2
37
#define  x_pieceBishop   3
38
#define  x_pieceRook     4
39
#define  x_pieceQueen    5
40
#define  x_pieceKing     6
41
 
42
/*
43
   Macro that fetches positions of pieces
44
 */
45
 
46
#define  C_PIECES  3    /* Maximum # of pieces of one color OTB */
47
 
48
#define  SqFindKing(psq)       (psq[C_PIECES*(x_pieceKing-1)])
49
#define  SqFindOne(psq, pi)    (psq[C_PIECES*(pi-1)])
50
#define  SqFindFirst(psq, pi)  (psq[C_PIECES*(pi-1)])
51
#define  SqFindSecond(psq, pi) (psq[C_PIECES*(pi-1)+1])
52
#define  SqFindThird(psq, pi)  (psq[C_PIECES*(pi-1)+2])
53
 
54
#include "lock.h"
55
 
56
/*
57
   All defined, now include probing code
58
 */
59
 
60
/* -------------------------------------------------------------------- */
61
/*                                                                      */
62
/*              Probe chess endgame database ("tablebase")              */
63
/*                                                                      */
64
/*               Copyright (c) 1998--2001 Eugene Nalimov                */
65
/*                                                                      */
66
/* The code listed below should not be used in any product (software or */
67
/* hardware,  commercial or not,  and so on) without written permission */
68
/* from the author.                                                     */
69
/*                                                                      */
70
/* -------------------------------------------------------------------- */
71
 
72
#if defined (_WIN32) || defined(_WIN64)
73
#  include <windows.h>
74
#endif
75
 
76
#include <string.h>
77
#include <stdlib.h>
78
#include <stdio.h>
79
#if !defined (DEBUG) && !defined(NDEBUG)
80
#  define   NDEBUG
81
#endif
82
#include <assert.h>
83
 
84
static  lock_t  lockLRU;
85
 
86
// Declarations
87
 
88
typedef unsigned    char BYTE;
89
typedef unsigned    long ULONG;
90
typedef signed      char tb_t;
91
 
92
#if !defined (COLOR_DECLARED)
93
typedef int color;
94
#  define   x_colorWhite    0
95
#  define   x_colorBlack    1
96
#  define   x_colorNeutral  2
97
#  define COLOR_DECLARED
98
#endif
99
 
100
#if !defined (PIECES_DECLARED)
101
typedef int piece;
102
#  define   x_pieceNone     0
103
#  define   x_piecePawn     1
104
#  define   x_pieceKnight   2
105
#  define   x_pieceBishop   3
106
#  define   x_pieceRook     4
107
#  define   x_pieceQueen    5
108
#  define   x_pieceKing     6
109
#  define PIECES_DECLARED
110
#endif
111
 
112
#if !defined (SqFind2)
113
#  define   SqFind2(psq,pi1,sq1,pi2,sq2)    sq1=SqFindFirst(psq,pi1);sq2=SqFindFirst(psq,pi2);
114
#endif
115
 
116
// Machine and compiler-specific declarations
117
 
118
#if defined (_MSC_VER)
119
 
108 pmbaty 120
#  undef    TB_CDECL
121
#  define   TB_CDECL    __cdecl
122
#  define   TB_FASTCALL __fastcall
33 pmbaty 123
#  if _MSC_VER >= 1200
124
#    define INLINE      __forceinline
125
#  endif
126
 
127
#else
128
 
108 pmbaty 129
#  define   TB_CDECL
33 pmbaty 130
#  define   TB_FASTCALL
131
 
132
#endif
133
 
134
#if !defined (INLINE)
135
#  define   INLINE  inline
136
#endif
137
 
138
// Printf formats
139
 
140
#if defined (T_INDEX64) && defined (_MSC_VER)
141
#   define HEX_INDEX_FORMAT "%016I64X"
142
#   define DEC_INDEX_FORMAT "%I64u"
143
#elif defined (T_INDEX64)
144
#   define HEX_INDEX_FORMAT "%016llX"
145
#   define DEC_INDEX_FORMAT "%llu"
146
#else
147
#   define HEX_INDEX_FORMAT "%08X"
148
#   define DEC_INDEX_FORMAT "%lu"
149
#endif
150
 
151
// Directory delimiter
152
 
153
#if defined (_WIN32) || defined(_WIN64)
154
#   define DELIMITER   "\\"
155
#elif defined (__MWERKS__)
156
#   define DELIMITER   ":"
157
#else
158
#   define DELIMITER   "/"
159
#endif
160
 
161
 
162
// Some constants from SJE program
163
 
164
#define pageL 256
165
 
166
/* tablebase byte entry semispan length */
167
 
168
#define tbbe_ssL ((pageL - 4) / 2)
169
 
170
/* tablebase signed byte entry values */
171
 
172
#define bev_broken  (tbbe_ssL + 1)  /* illegal or busted */
173
 
174
#define bev_mi1     tbbe_ssL        /* mate in 1 move */
175
#define bev_mimin   1               /* mate in 126 moves */
176
 
177
#define bev_draw    0               /* draw */
178
 
179
#define bev_limax   (-1)            /* mated in 125 moves */
180
#define bev_li0     (-tbbe_ssL)     /* mated in 0 moves */
181
 
182
#define bev_limaxx  (-tbbe_ssL - 1) /* mated in 126 moves */
183
#define bev_miminx  (-tbbe_ssL - 2) /* mate in 127 moves */
184
 
185
// Some constants for 16-bit tables
186
 
187
#define L_pageL 65536
188
 
189
/* tablebase short entry semispan length */
190
 
191
#define L_tbbe_ssL ((L_pageL - 4) / 2)
192
 
193
/* tablebase signed short entry values */
194
 
195
#define L_bev_broken  (L_tbbe_ssL + 1)      /* illegal or busted */
196
 
197
#define L_bev_mi1     L_tbbe_ssL            /* mate in 1 move */
198
#define L_bev_mimin   1                     /* mate in 32766 moves */
199
 
200
#define L_bev_draw    0                     /* draw */
201
 
202
#define L_bev_limax   (-1)                  /* mated in 32765 moves */
203
#define L_bev_li0     (-L_tbbe_ssL)         /* mated in 0 moves */
204
 
205
#define L_bev_limaxx    (-L_tbbe_ssL - 1)   /* mated in 32766 moves */
206
#define L_bev_miminx    (-L_tbbe_ssL - 2)   /* mate in 32767 moves */
207
 
208
// Convertion from 8-bit to 16-bit score
209
// UNDONE: Maybe implement via lookup table?
210
 
211
#define S_to_L(tbt)\
212
    (\
213
     (0 == tbt) ? 0:\
214
     (tbt > 0) ? (bev_broken != tbt ? tbt + 32640 : L_bev_broken):\
215
     (tbt >= bev_li0) ? tbt - 32640:\
216
     (bev_limaxx == tbt) ? -32640:\
217
     /*bev_miminx == tbt*/  32640\
218
    )
219
 
220
// Constants
221
 
222
#define i8  ((unsigned) 8)
223
#define i14 ((unsigned) 14)
224
#define i42 ((unsigned) 42)
225
#define i43 ((unsigned) 43)
226
#define i44 ((unsigned) 44)
227
#define i45 ((unsigned) 45)
228
#define i46 ((unsigned) 46)
229
#define i47 ((unsigned) 47)
230
#define i48 ((unsigned) 48)
231
#define i57 ((unsigned) 57)
232
#define i58 ((unsigned) 58)
233
#define i59 ((unsigned) 59)
234
#define i60 ((unsigned) 60)
235
#define i61 ((unsigned) 61)
236
#define i62 ((unsigned) 62)
237
#define i63 ((unsigned) 63)
238
#define i64 ((unsigned) 64)
239
 
240
#define x_row_1 0
241
#define x_row_2 1
242
#define x_row_3 2
243
#define x_row_4 3
244
#define x_row_5 4
245
#define x_row_6 5
246
#define x_row_7 6
247
#define x_row_8 7
248
 
249
#define x_column_a 0
250
#define x_column_b 1
251
#define x_column_c 2
252
#define x_column_d 3
253
#define x_column_e 4
254
#define x_column_f 5
255
#define x_column_g 6
256
#define x_column_h 7
257
 
258
/* reflection macros */
259
 
260
#define reflect_x(sq) ((sq) ^ 0x38)
261
#define reflect_y(sq) ((sq) ^ 0x07)
262
#define reflect_xy(sq) rgsqReflectXY[sq]
263
 
264
static const square rgsqReflectXY [] =
265
{
266
  0,  8, 16, 24, 32, 40, 48, 56,
267
  1,  9, 17, 25, 33, 41, 49, 57,
268
  2, 10, 18, 26, 34, 42, 50, 58,
269
  3, 11, 19, 27, 35, 43, 51, 59,
270
  4, 12, 20, 28, 36, 44, 52, 60,
271
  5, 13, 21, 29, 37, 45, 53, 61,
272
  6, 14, 22, 30, 38, 46, 54, 62,
273
  7, 15, 23, 31, 39, 47, 55, 63,
274
};
275
 
276
static const square rgsqReflectMaskY [] =
277
{
278
 0, 0, 0, 0, 7, 7, 7, 7,
279
 0, 0, 0, 0, 7, 7, 7, 7,
280
 0, 0, 0, 0, 7, 7, 7, 7,
281
 0, 0, 0, 0, 7, 7, 7, 7,
282
 0, 0, 0, 0, 7, 7, 7, 7,
283
 0, 0, 0, 0, 7, 7, 7, 7,
284
 0, 0, 0, 0, 7, 7, 7, 7,
285
 0, 0, 0, 0, 7, 7, 7, 7,
286
};
287
 
288
static const square rgsqReflectMaskYandX [] =
289
{
290
 0, 0, 0, 0, 7, 7, 7, 7,
291
 0, 0, 0, 0, 7, 7, 7, 7,
292
 0, 0, 0, 0, 7, 7, 7, 7,
293
 0, 0, 0, 0, 7, 7, 7, 7,
294
 0x38, 0x38, 0x38, 0x38, 0x38+7, 0x38+7, 0x38+7, 0x38+7,
295
 0x38, 0x38, 0x38, 0x38, 0x38+7, 0x38+7, 0x38+7, 0x38+7,
296
 0x38, 0x38, 0x38, 0x38, 0x38+7, 0x38+7, 0x38+7, 0x38+7,
297
 0x38, 0x38, 0x38, 0x38, 0x38+7, 0x38+7, 0x38+7, 0x38+7,
298
};
299
 
300
static const square rgsqReflectInvertMask[] = { 0, 0x38 };
301
 
302
/* useful macros */
303
 
304
#define TbRow(sq)               ((sq) >> 3)
305
#define TbColumn(sq)            ((sq) & 7)
306
 
307
#if defined (NEW)
308
#  define   PchExt(side) ((x_colorWhite == side) ? ".nbw" : ".nbb")
309
#else
310
#  define   PchExt(side) ((x_colorWhite == side) ? ".tbw" : ".tbb")
311
#endif
312
 
313
// Verbose levels
314
 
315
static bool     fPrint = false;     // Print some technical statistics
316
static bool     fVerbose = false;   // Print additional information
317
 
318
// Malloc that checks for out-of-memory condition
319
 
320
static size_t   cbAllocated;
321
static int      cOpenFilesAttempts;
322
static int      cOpenFilesSuceed;
323
 
324
static void* PvMalloc
325
    (
326
    size_t cb
327
    )
328
    {
329
    void    *pv;
330
 
331
    pv = malloc (cb);
332
    if (NULL == pv)
333
        {
334
        printf ("*** Cannot allocate %lu bytes of memory\n", cb);
335
        exit (1);
336
        }
337
    cbAllocated += cb;
338
    return pv;
339
    }
340
 
341
#if defined (NEW)   // New index schema ----------------------------------------
342
 
343
// 'Invalid' value have to be large, so index
344
// of invalid position will be very large, too.
345
 
346
#define INF 4000
347
 
348
// Enumeration: valid positions with 2 kings on board; white king restricted to
349
// a1-d1-d4 triangle; also, if it's at a1-d4 half-diagonal, then black king
350
// must be in a1-h1-h8 triangle// Enumeration: all valid positions with 2 kings on board when white king
351
 
352
353
#define IndTriKings(sqk1,sqk2)  ((unsigned) rgsTriKings[sqk1*64+sqk2])
354
#define IndHalfKings(sqk1,sqk2) ((unsigned) rgsHalfKings[sqk1*64+sqk2])
355
356
static const bool rgfTriangle[64] =
357
{
358
     true,  true,  true,  true,  false, false, false, false,
359
     false, true,  true,  true,  false, false, false, false,
360
     false, false, true,  true,  false, false, false, false,
361
     false, false, false, true,  false, false, false, false,
362
     false, false, false, false, false, false, false, false,
363
     false, false, false, false, false, false, false, false,
364
     false, false, false, false, false, false, false, false,
365
     false, false, false, false, false, false, false, false,
366
};
367
368
static const bool rgfNotDiagonal[64] =
369
{
370
     false, true,  true,  true,  true,  true,  true,  true,
371
     true,  false, true,  true,  true,  true,  true,  true,
372
     true,  true,  false, true,  true,  true,  true,  true,
373
     true,  true,  true,  false, true,  true,  true,  true,
374
     true,  true,  true,  true,  false, true,  true,  true,
375
     true,  true,  true,  true,  true,  false, true,  true,
376
     true,  true,  true,  true,  true,  true,  false, true,
377
     true,  true,  true,  true,  true,  true,  true,  false,
378
};
379
380
static const bool rgfInLargeTriangle[64] =
381
{
382
     true,  true,  true,  true,  true,  true,  true,  true,
383
     false, true,  true,  true,  true,  true,  true,  true,
384
     false, false, true,  true,  true,  true,  true,  true,
385
     false, false, false, true,  true,  true,  true,  true,
386
     false, false, false, false, true,  true,  true,  true,
387
     false, false, false, false, false, true,  true,  true,
388
     false, false, false, false, false, false, true,  true,
389
     false, false, false, false, false, false, false, true,
390
};
391
392
#define FInTriangle(sqwk,sqbk)  (rgfTriangle[sqwk] & (rgfNotDiagonal[sqwk]|rgfInLargeTriangle[sqbk]))
393
394
// Sort pieces
395
396
#define SORT(sq1,sq2)   if (sq1>sq2) { square sqTmp; sqTmp=sq1; sq1=sq2; sq2=sqTmp; }
397
398
// Exclude occupied squares
399
400
#define EXCLUDE1(sq,sq1)                         (sq-(sq>sq1))
401
#define EXCLUDE2(sq,sq1,sq2)                     (sq-((sq>sq1)+(sq>sq2)))
402
#define EXCLUDE3(sq,sq1,sq2,sq3)                 (sq-((sq>sq1)+(sq>sq2)+(sq>sq3)))
403
#define EXCLUDE4(sq,sq1,sq2,sq3,sq4)             (sq-((sq>sq1)+(sq>sq2)+(sq>sq3)+(sq>sq4)))
404
#define EXCLUDE5(sq,sq1,sq2,sq3,sq4,sq5)         (sq-((sq>sq1)+(sq>sq2)+(sq>sq3)+(sq>sq4)+(sq>sq5)))
405
#define EXCLUDE6(sq,sq1,sq2,sq3,sq4,sq5,sq6)     (sq-((sq>sq1)+(sq>sq2)+(sq>sq3)+(sq>sq4)+(sq>sq5)+(sq>sq6)))
406
#define EXCLUDE7(sq,sq1,sq2,sq3,sq4,sq5,sq6,sq7) (sq-((sq>sq1)+(sq>sq2)+(sq>sq3)+(sq>sq4)+(sq>sq5)+(sq>sq6)+(sq>sq7)))
407
408
#if !defined(SWAP)
409
#define SWAP(sq1, sq2)  {square sq_tmp = sq2; sq2 = sq1; sq1 = sq_tmp;}
410
#endif
411
412
// Calculate index - a lot of functions...
413
414
// Enumeration tables
415
416
static BYTE     *rgprgsqPiece[6];   // Enumeration for each piece (0 - black pawn)
417
                                    // For each position of the King, all legal squares
418
                                    // of the opposite piece enumerated
419
static BYTE     rgcLegal[6][64];    // # of enumerated positions for each piece and each
420
                                    // location of enemy king
421
422
// Enumerations - indexed by [piece] and [kings enumeration].
423
// In each table for each [piece] and [king enumeration] we store # of preceeding positions.
424
425
static ULONG    *rgprgulSinglePawnless[6];
426
static ULONG    *rgprgulPairPawnless[6][6];
427
#if defined (T41_INCLUDE) || defined (T42_INCLUDE)
428
  static ULONG  *rgprgulTriplePawnless[6][6][6];
429
#endif
430
static ULONG    *rgprgulSinglePawnPresent[6];
431
static ULONG    *rgprgulPairPawnPresent[6][6];
432
#if defined (T41_INCLUDE) || defined (T42_INCLUDE)
433
  static ULONG  *rgprgulTriplePawnPresent[6][6][6];
434
#endif
435
436
// Total # of enumerated positions
437
438
static ULONG    rgcSinglePawnPresent[6];
439
static ULONG    rgcSinglePawnless[6];
440
static ULONG    rgcPairPawnPresent[6][6];
441
static ULONG    rgcPairPawnless[6][6];
442
#if defined (T41_INCLUDE) || defined (T42_INCLUDE)
443
  static ULONG  rgcTriplePawnPresent[6][6][6];
444
  static ULONG  rgcTriplePawnless[6][6][6];
445
#endif
446
447
// Infinities. Have to be larger than any legal enumeration yet small enough
448
// so there will be no overflow when combining them with remaining pieces.
449
450
#define INF_SINGLE  (110000)
451
#define INF_PAIR    (6500000)
452
#define INF_TRIPLE  (500000000)
453
454
// Initialize squares and counters table for one piece.
455
// Piece can be x_pieceNone - that means 'pawn of the wrong color', e.g. KPK BTM.
456
457
static void VInitSquaresTable
458
    (
459
    piece   pi,
460
    BYTE    *prgsqPiece,
461
    BYTE    *prgcLegal
462
    )
463
    {
464
    int sqLo, sqHi;
465
466
    memset (prgsqPiece, -1, 64*64);
467
    sqLo = 0;
468
    sqHi = 64;
469
    if (pi <= x_piecePawn)
470
        {
471
        sqLo = 8;
472
        sqHi = 56;
473
        }
474
    for (int sqKing = 0; sqKing < 64; sqKing ++)
475
        {
476
        int iPiece;
477
478
        iPiece = 0;
479
        for (int sq = sqLo; sq < sqHi; sq ++)
480
            {
481
            if (sq == sqKing)
482
                continue;
483
            switch (pi)
484
                {
485
            case x_piecePawn:
486
                if (
487
                    (0 != TbColumn (sq) && sqKing == sq+7) ||
488
                    (7 != TbColumn (sq) && sqKing == sq+9)
489
                   )
490
                   continue;
491
                break;
492
            case x_pieceKnight:
493
                if (
494
                    (TbRow (sq) >= 2 && TbColumn (sq) >= 1 && sqKing == sq-17) ||
495
                    (TbRow (sq) >= 2 && TbColumn (sq) <= 6 && sqKing == sq-15) ||
496
                    (TbRow (sq) >= 1 && TbColumn (sq) >= 2 && sqKing == sq-10) ||
497
                    (TbRow (sq) >= 1 && TbColumn (sq) <= 5 && sqKing == sq-6) ||
498
                    (TbRow (sq) <= 6 && TbColumn (sq) >= 2 && sqKing == sq+6) ||
499
                    (TbRow (sq) <= 6 && TbColumn (sq) <= 5 && sqKing == sq+10) ||
500
                    (TbRow (sq) <= 5 && TbColumn (sq) >= 1 && sqKing == sq+15) ||
501
                    (TbRow (sq) <= 5 && TbColumn (sq) <= 6 && sqKing == sq+17)
502
                   )
503
                    continue;
504
                break;
505
            case x_pieceBishop:
506
                if (
507
                    (0 != TbRow (sq) && 0 != TbColumn (sq) && sqKing == sq-9) ||
508
                    (0 != TbRow (sq) && 7 != TbColumn (sq) && sqKing == sq-7) ||
509
                    (7 != TbRow (sq) && 0 != TbColumn (sq) && sqKing == sq+7) ||
510
                    (7 != TbRow (sq) && 7 != TbColumn (sq) && sqKing == sq+9)
511
                   )
512
                    continue;
513
                break;
514
            case x_pieceRook:
515
                if (
516
                    (0 != TbColumn (sq) && sqKing == sq-1) ||
517
                    (7 != TbColumn (sq) && sqKing == sq+1) ||
518
                    (0 != TbRow (sq) && sqKing == sq-8) ||
519
                    (7 != TbRow (sq) && sqKing == sq+8)
520
                   )
521
                    continue;
522
                break;
523
            case x_pieceQueen:
524
                if (
525
                    (0 != TbColumn (sq) && sqKing == sq-1) ||
526
                    (7 != TbColumn (sq) && sqKing == sq+1) ||
527
                    (0 != TbRow (sq) && sqKing == sq-8) ||
528
                    (7 != TbRow (sq) && sqKing == sq+8) ||
529
                    (0 != TbRow (sq) && 0 != TbColumn (sq) && sqKing == sq-9) ||
530
                    (0 != TbRow (sq) && 7 != TbColumn (sq) && sqKing == sq-7) ||
531
                    (7 != TbRow (sq) && 0 != TbColumn (sq) && sqKing == sq+7) ||
532
                    (7 != TbRow (sq) && 7 != TbColumn (sq) && sqKing == sq+9)
533
                   )
534
                    continue;
535
                break;
536
                }
537
            prgsqPiece[sqKing*64+sq] = (BYTE) iPiece;
538
            iPiece ++;
539
            }
540
        prgcLegal[sqKing] = (BYTE) iPiece;
541
        }
542
    }
543
544
// Initialize enumeration table for single piece
545
546
static void VInitSingle
547
    (
548
    ULONG       *prgIndex,
549
    const short *prgsKings,
550
    const BYTE  *prgcLegal,
551
    const BYTE  *prgsqPiece,
552
    ULONG       *pcEnumeration
553
    )
554
    {
555
    ULONG iIndex;
556
557
    iIndex = 0;
558
    for (int sqKing1 = 0; sqKing1 < 64; sqKing1 ++)
559
        for (int sqKing2 = 0; sqKing2 < 64; sqKing2 ++)
560
            {
561
            if (INF != prgsKings[sqKing1*64+sqKing2])
562
                {
563
                prgIndex[prgsKings[sqKing1*64+sqKing2]] = iIndex;
564
                iIndex += prgcLegal[sqKing2] - ((BYTE) -1 != prgsqPiece[sqKing2*64+sqKing1]);
565
                }
566
            }
567
    *pcEnumeration = iIndex;
568
    }
569
570
// Initialize enumeration table for pair of pieces
571
572
static void VInitPair
573
    (
574
    ULONG       *prgIndex,
575
    const short *prgsKings,
576
    const BYTE  *prgcLegal1,
577
    const BYTE  *prgsqPiece1,
578
    const BYTE  *prgcLegal2,
579
    const BYTE  *prgsqPiece2,
580
    ULONG       *pcEnumeration
581
    )
582
    {
583
    ULONG iIndex;
584
    ULONG cPositions1, cPositions2;
585
586
    iIndex = 0;
587
    for (int sqKing1 = 0; sqKing1 < 64; sqKing1 ++)
588
        for (int sqKing2 = 0; sqKing2 < 64; sqKing2 ++)
589
            {
590
            if (INF != prgsKings[sqKing1*64+sqKing2])
591
                {
592
                prgIndex[prgsKings[sqKing1*64+sqKing2]] = iIndex;
593
                cPositions1 = prgcLegal1[sqKing2] - ((BYTE) -1 != prgsqPiece1[sqKing2*64+sqKing1]);
594
                if (prgcLegal1 == prgcLegal2)
595
                    iIndex += cPositions1*(cPositions1-1)/2;
596
                else
597
                    {
598
                    cPositions2 = prgcLegal2[sqKing2] - ((BYTE) -1 != prgsqPiece2[sqKing2*64+sqKing1]);
599
                    iIndex += cPositions1*cPositions2;
600
                    }
601
                }
602
            }
603
    *pcEnumeration = iIndex;
604
    }
605
606
#if defined (T41_INCLUDE) || defined (T42_INCLUDE)
607
608
// Initialize enumeration table for triple piece
609
610
static void VInitTriple
611
 
612
    ULONG       *prgIndex,
613
    const short *prgsKings,
614
 
615
    const BYTE  *prgsqPiece1,
616
    const BYTE  *prgcLegal2,
617
    const BYTE  *prgsqPiece2,
618
    const BYTE  *prgcLegal3,
619
    const BYTE  *prgsqPiece3,
620
    ULONG       *pcEnumeration
621
    )
622
    {
623
    ULONG iIndex;
624
    ULONG cPositions1, cPositions2, cPositions3;
625
626
    iIndex = 0;
627
    for (int sqKing1 = 0; sqKing1 < 64; sqKing1 ++)
628
        for (int sqKing2 = 0; sqKing2 < 64; sqKing2 ++)
629
            {
630
            if (INF != prgsKings[sqKing1*64+sqKing2])
631
                {
632
                prgIndex[prgsKings[sqKing1*64+sqKing2]] = iIndex;
633
                cPositions1 = prgcLegal1[sqKing2] - ((BYTE) -1 != prgsqPiece1[sqKing2*64+sqKing1]);
634
                if (prgcLegal1 == prgcLegal2 && prgcLegal2 == prgcLegal3)
635
                    iIndex += cPositions1*(cPositions1-1)*(cPositions1-2)/6;
636
                else if (prgcLegal1 == prgcLegal2)
637
                    {
638
                    cPositions3 = prgcLegal3[sqKing2] - ((BYTE) -1 != prgsqPiece3[sqKing2*64+sqKing1]);
639
                    iIndex += cPositions1*(cPositions1-1)/2*cPositions3;
640
                    }
641
                else if (prgcLegal2 == prgcLegal3)
642
                    {
643
                    cPositions2 = prgcLegal2[sqKing2] - ((BYTE) -1 != prgsqPiece2[sqKing2*64+sqKing1]);
644
                    iIndex += cPositions1*cPositions2*(cPositions2-1)/2;
645
                    }
646
                else
647
                    {
648
                    cPositions2 = prgcLegal2[sqKing2] - ((BYTE) -1 != prgsqPiece2[sqKing2*64+sqKing1]);
649
                    cPositions3 = prgcLegal3[sqKing2] - ((BYTE) -1 != prgsqPiece3[sqKing2*64+sqKing1]);
650
                    iIndex += cPositions1*cPositions2*cPositions3;
651
                    }
652
                }
653
            }
654
    *pcEnumeration = iIndex;
655
    }
656
657
#endif
658
659
// Initialize all Enumeration tables
660
661
static bool fEnumerationInitted = false;
662
663
static void VInitEnumerations (void)
664
    {
665
    piece   pi1;
666
    piece   pi2;
667
#if defined (T41_INCLUDE) || defined (T42_INCLUDE)
668
    piece   pi3;
669
#endif
670
671
    if (fEnumerationInitted)
672
        return;
673
    fEnumerationInitted = true;
674
    // Initialize square tables
675
    for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
676
        {
677
        rgprgsqPiece[pi1] = (BYTE *) PvMalloc (64*64);
678
        VInitSquaresTable (pi1, rgprgsqPiece[pi1], rgcLegal[pi1]);
679
        }
680
681
    for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
682
        {
683
        // Initialize enumeration tables for single piece
684
        rgprgulSinglePawnPresent[pi1] = (ULONG *) PvMalloc (1806*sizeof (ULONG));
685
        VInitSingle (rgprgulSinglePawnPresent[pi1], rgsHalfKings,
686
                     rgcLegal[pi1], rgprgsqPiece[pi1], &rgcSinglePawnPresent[pi1]);
687
        if (pi1 > x_piecePawn)
688
            {
689
            rgprgulSinglePawnless[pi1] = (ULONG *) PvMalloc (462*sizeof (ULONG));
690
            VInitSingle (rgprgulSinglePawnless[pi1], rgsTriKings,
691
                         rgcLegal[pi1], rgprgsqPiece[pi1], &rgcSinglePawnless[pi1]);
692
            }
693
        // Initialize enumeration tables for pair of pieces
694
        for (pi2 = (x_pieceNone == pi1 ? x_pieceNone : x_piecePawn); pi2 <= pi1; pi2 = (piece) (pi2 + 1))
695
            {
696
            rgprgulPairPawnPresent[pi1][pi2] = (ULONG *) PvMalloc (1806*sizeof (ULONG));
697
            VInitPair (rgprgulPairPawnPresent[pi1][pi2], rgsHalfKings,
698
                       rgcLegal[pi1], rgprgsqPiece[pi1], rgcLegal[pi2], rgprgsqPiece[pi2],
699
                       &rgcPairPawnPresent[pi1][pi2]);
700
            if (pi1 > x_piecePawn && pi2 > x_piecePawn)
701
                {
702
                rgprgulPairPawnless[pi1][pi2] = (ULONG *) PvMalloc (462*sizeof (ULONG));
703
                VInitPair (rgprgulPairPawnless[pi1][pi2], rgsTriKings,
704
                           rgcLegal[pi1], rgprgsqPiece[pi1], rgcLegal[pi2], rgprgsqPiece[pi2],
705
                           &rgcPairPawnless[pi1][pi2]);
706
                }
707
#if defined (T41_INCLUDE) || defined (T42_INCLUDE)
708
            // Initialize enumeration tables for three pieces
709
            for (pi3 = (x_pieceNone == pi1 ? x_pieceNone : x_piecePawn); pi3 <= pi2; pi3 = (piece) (pi3 + 1))
710
                {
711
                if (pi1 <= x_piecePawn || pi2 <= x_piecePawn || pi3 <= x_piecePawn)
712
                    {
713
                    rgprgulTriplePawnPresent[pi1][pi2][pi3] = (ULONG *) PvMalloc (1806*sizeof (ULONG));
714
                    VInitTriple (rgprgulTriplePawnPresent[pi1][pi2][pi3], rgsHalfKings,
715
                                 rgcLegal[pi1], rgprgsqPiece[pi1],
716
                                 rgcLegal[pi2], rgprgsqPiece[pi2],
717
                                 rgcLegal[pi3], rgprgsqPiece[pi3],
718
                                 &rgcTriplePawnPresent[pi1][pi2][pi3]);
719
                    }
720
                else
721
                    {
722
                    rgprgulTriplePawnless[pi1][pi2][pi3] = (ULONG *) PvMalloc (462*sizeof (ULONG));
723
                    VInitTriple (rgprgulTriplePawnless[pi1][pi2][pi3], rgsTriKings,
724
                        rgcLegal[pi1], rgprgsqPiece[pi1],
725
                        rgcLegal[pi2], rgprgsqPiece[pi2],
726
                        rgcLegal[pi3], rgprgsqPiece[pi3],
727
                        &rgcTriplePawnless[pi1][pi2][pi3]);
728
#if defined (T42_INCLUDE)
729
                    rgprgulTriplePawnPresent[pi1][pi2][pi3] = (ULONG *) PvMalloc (1806*sizeof (ULONG));
730
                    VInitTriple (rgprgulTriplePawnPresent[pi1][pi2][pi3], rgsHalfKings,
731
                                 rgcLegal[pi1], rgprgsqPiece[pi1],
732
                                 rgcLegal[pi2], rgprgsqPiece[pi2],
733
                                 rgcLegal[pi3], rgprgsqPiece[pi3],
734
                                 &rgcTriplePawnPresent[pi1][pi2][pi3]);
735
#endif
736
                    }
737
                }
738
#endif
739
            }
740
        }
741
742
    // All done!
743
    if (fPrint)
744
        {
745
        for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
746
            printf ("%c - %lud enumerated positions\n", "pPNBRQ"[pi1], rgcSinglePawnPresent[pi1]);
747
        for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
748
            {
749
            if (0 != rgcSinglePawnless[pi1])
750
                printf ("pawnless %c - %lud enumerated positions\n", "pPNBRQ"[pi1], rgcSinglePawnless[pi1]);
751
            }
752
        for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
753
            for (pi2 = x_pieceNone; pi2 <= pi1; pi2 = (piece) (pi2 + 1))
754
                {
755
                if (0 != rgcPairPawnPresent[pi1][pi2])
756
                    printf ("%c%c - %lu enumerated positions\n", "pPNBRQ"[pi1], "pPNBRQ"[pi2],
757
                            rgcPairPawnPresent[pi1][pi2]);
758
                }
759
        for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
760
            for (pi2 = x_pieceNone; pi2 <= pi1; pi2 = (piece) (pi2 + 1))
761
                {
762
                if (0 != rgcPairPawnless[pi1][pi2])
763
                    printf ("pawnless %c%c - %lu enumerated positions\n", "pPNBRQ"[pi1], "pPNBRQ"[pi2],
764
                            rgcPairPawnless[pi1][pi2]);
765
                }
766
#if defined (T41_INCLUDE) || defined (T42_INCLUDE)
767
        for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
768
            for (pi2 = x_pieceNone; pi2 <= pi1; pi2 = (piece) (pi2 + 1))
769
                for (pi3 = x_pieceNone; pi3 <= pi2; pi3 = (piece) (pi3 + 1))
770
                    {
771
                    if (0 != rgcTriplePawnPresent[pi1][pi2][pi3])
772
                        printf ("%c%c%c - %lu enumerated positions\n",
773
                                "pPNBRQ"[pi1], "pPNBRQ"[pi2], "pPNBRQ"[pi3],
774
                                rgcTriplePawnPresent[pi1][pi2][pi3]);
775
                    }
776
        for (pi1 = x_pieceNone; pi1 <= x_pieceQueen; pi1 = (piece) (pi1 + 1))
777
            for (pi2 = x_pieceNone; pi2 <= pi1; pi2 = (piece) (pi2 + 1))
778
                for (pi3 = x_pieceNone; pi3 <= pi2; pi3 = (piece) (pi3 + 1))
779
                    {
780
                    if (0 != rgcTriplePawnless[pi1][pi2][pi3])
781
                        printf ("pawnless %c%c%c - %lu enumerated positions\n",
782
                                "pPNBRQ"[pi1], "pPNBRQ"[pi2], "pPNBRQ"[pi3],
783
                                rgcTriplePawnless[pi1][pi2][pi3]);
784
                    }
785
#endif
786
        printf ("\nAllocated %luk\n\n", (cbAllocated + 1023)/1024);
787
        }
788
    }
789
790
// Return enumeration of 2 kings and single piece
791
792
template <int piw1, bool fPawns, bool fInvert> class TEnumerate1
793
    {
794
public:
795
    static INLINE unsigned TB_FASTCALL Index
796
        (
797
        square  sqwk,
798
        square  sqw1,
799
        square  sqbk
800
        )
801
        {
802
        unsigned ind;
803
        ULONG    ulKings;
804
805
        // For black pawn invert the board
806
        if (piw1 <= x_piecePawn && fInvert)
807
            {
808
            sqwk = reflect_x(sqwk);
809
            sqw1 = reflect_x(sqw1);
810
            sqbk = reflect_x(sqbk);
811
            }
812
       
813
        // Get enumerated square
814
        ind = rgprgsqPiece[piw1][sqbk*64+sqw1];
815
#if defined (ILLEGAL_POSSIBLE)
816
        if ((BYTE) -1 == ind)
817
            return INF_SINGLE;
818
#endif
819
        // Get enumerated position of both kings
820
        if (fPawns)
821
            ulKings = rgsHalfKings[sqwk*64+sqbk];   // 0..1805
822
        else
823
            ulKings = rgsTriKings[sqwk*64+sqbk];    // 0..461
824
#if defined (ILLEGAL_POSSIBLE)
825
        if (INF == ulKings)
826
            return INF_SINGLE;
827
#endif
828
        // Can we remove one extra square?
829
        if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
830
            ind -= (sqw1 > sqwk);
831
        // Add enumerated square to the # of the preceeding positions
832
        return ind + (fPawns ? rgprgulSinglePawnPresent[piw1][ulKings] : rgprgulSinglePawnless[piw1][ulKings]);
833
        }
834
    };
835
836
// Return enumeration of 2 kings and 2 pieces
837
838
template <int piw1, int piw2, bool fPawns, bool fInvert> class TEnumerate2
839
    {
840
public:
841
    static INLINE unsigned TB_FASTCALL Index
842
        (
843
        square  sqwk,
844
        square  sqw1,
845
        square  sqw2,
846
        square  sqbk
847
        )
848
        {
849
        unsigned ind1, ind2, cInd2;
850
        ULONG    ulKings;
851
852
        // For black pawn invert the board
853
        if (piw2 <= x_piecePawn && fInvert)
854
            {
855
            sqwk = reflect_x(sqwk);
856
            sqw1 = reflect_x(sqw1);
857
            sqw2 = reflect_x(sqw2);
858
            sqbk = reflect_x(sqbk);
859
            }
860
       
861
        // Get enumerated squares for both pieces
862
        if (piw1 == piw2)
863
            SORT (sqw1, sqw2);
864
        ind1 = rgprgsqPiece[piw1][sqbk*64+sqw1];
865
        ind2 = rgprgsqPiece[piw2][sqbk*64+sqw2];
866
#if defined (ILLEGAL_POSSIBLE)
867
        if ((BYTE) -1 == ind1 || (BYTE) -1 == ind2)
868
            return INF_PAIR;
869
#endif
870
        // Get enumerated position of both kings
871
        if (fPawns)
872
            ulKings = rgsHalfKings[sqwk*64+sqbk];   // 0..1805
873
        else
874
 
875
#if defined (ILLEGAL_POSSIBLE)
876
 
877
            return INF_PAIR;
878
#endif
879
 
880
            {
881
            // Can we remove one extra square?
882
            if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
883
                {
884
                ind1 -= (sqw1 > sqwk);
885
                ind2 -= (sqw2 > sqwk);
886
                }
887
            // Add enumerated squares to the # of the preceeding positions
888
            return  ind2*(ind2-1)/2 + ind1 +
889
                    (fPawns ? rgprgulPairPawnPresent[piw1][piw2][ulKings] : rgprgulPairPawnless[piw1][piw2][ulKings]);
890
            }
891
 
892
            {
893
            // Can we remove WK square from 1st piece Enumeration?
894
            if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
895
                ind1 -= (sqw1 > sqwk);
896
            // Get # of enumerated positions of 2nd piece
897
            cInd2 = rgcLegal[piw2][sqbk];
898
            // Can we remove WK square from 2nd piece Enumeration?
899
            if ((piw2>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw2][sqbk*64+sqwk]))
900
                {
901
                cInd2 --;
902
                ind2 -= (sqw2 > sqwk);
903
 
904
            // Add enumerated square to the # of the preceeding positions
905
            return cInd2*ind1 + ind2 + (fPawns ? rgprgulPairPawnPresent[piw1][piw2][ulKings] : rgprgulPairPawnless[piw1][piw2][ulKings]);
906
            }
907
        }
908
    };
909
910
#if defined (T41_INCLUDE) || defined (T42_INCLUDE)
911
912
// Return enumeration of 2 kings and 3 pieces
913
914
template <int piw1, int piw2, int piw3, bool fPawns, bool fInvert> class TEnumerate3
915
 
916
public:
917
 
918
        (
919
 
920
        square  sqw1,
921
 
922
        square  sqw3,
923
 
924
        )
925
        {
926
        unsigned ind1, ind2, ind3, cInd1, cInd2, cInd3;
927
        ULONG    ulKings;
928
929
        // For black pawn invert the board
930
        if (piw3 <= x_piecePawn && fInvert)
931
 
932
            sqwk = reflect_x(sqwk);
933
            sqw1 = reflect_x(sqw1);
934
            sqw2 = reflect_x(sqw2);
935
 
936
            sqbk = reflect_x(sqbk);
937
 
938
       
939
 
940
        if (piw1 == piw2 && piw1 == piw3)
941
            {
942
            SORT (sqw1, sqw2);
943
            SORT (sqw2, sqw3);
944
            SORT (sqw1, sqw2);
945
 
946
        else if (piw1 == piw2)
947
            {
948
 
949
            }
950
        else if (piw2 == piw3)
951
            {
952
            SORT (sqw2, sqw3);
953
            }
954
        ind1 = rgprgsqPiece[piw1][sqbk*64+sqw1];
955
        ind2 = rgprgsqPiece[piw2][sqbk*64+sqw2];
956
        ind3 = rgprgsqPiece[piw3][sqbk*64+sqw3];
957
#if defined (ILLEGAL_POSSIBLE)
958
        if ((BYTE) -1 == ind1 || (BYTE) -1 == ind2 || (BYTE) -1 == ind3)
959
 
960
#endif
961
 
962
        if (fPawns)
963
            ulKings = rgsHalfKings[sqwk*64+sqbk];   // 0..1805
964
        else
965
            ulKings = rgsTriKings[sqwk*64+sqbk];    // 0..461
966
#if defined (ILLEGAL_POSSIBLE)
967
        if (INF == ulKings)
968
            return INF_TRIPLE;
969
#endif
970
 
971
            {
972
            // Can we remove one extra square?
973
 
974
                {
975
                ind1 -= (sqw1 > sqwk);
976
                ind2 -= (sqw2 > sqwk);
977
 
978
                }
979
            // Add enumerated squares to the # of the preceeding positions
980
 
981
                    (fPawns ? rgprgulTriplePawnPresent[piw1][piw2][piw3][ulKings] :
982
                              rgprgulTriplePawnless[piw1][piw2][piw3][ulKings]);
983
            }
984
        else if (piw1 == piw2)
985
            {
986
            // Can we remove one extra square?
987
            if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
988
                {
989
 
990
                ind2 -= (sqw2 > sqwk);
991
                }
992
            // Get # of enumerated positions of 3rd piece
993
            cInd3 = rgcLegal[piw3][sqbk];
994
            // Can we remove WK square from 3rd piece Enumeration?
995
            if ((piw3>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw3][sqbk*64+sqwk]))
996
                {
997
                cInd3 --;
998
                ind3 -= (sqw3 > sqwk);
999
                }
1000
            // Add enumerated squares to the # of the preceeding positions
1001
 
1002
                    (fPawns ? rgprgulTriplePawnPresent[piw1][piw2][piw3][ulKings] :
1003
                              rgprgulTriplePawnless[piw1][piw2][piw3][ulKings]);
1004
            }
1005
        else if (piw2 == piw3)
1006
            {
1007
            // Can we remove one extra square?
1008
            if ((piw2>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw2][sqbk*64+sqwk]))
1009
                {
1010
                ind2 -= (sqw2 > sqwk);
1011
                ind3 -= (sqw3 > sqwk);
1012
                }
1013
            // Get # of enumerated positions of 1st piece
1014
            cInd1 = rgcLegal[piw1][sqbk];
1015
            // Can we remove WK square from 3rd piece Enumeration?
1016
            if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
1017
                {
1018
                cInd1 --;
1019
                ind1 -= (sqw1 > sqwk);
1020
                }
1021
            // Add enumerated squares to the # of the preceeding positions
1022
            return  (ind3*(ind3-1)/2 + ind2)*cInd1 + ind1 +
1023
                    (fPawns ? rgprgulTriplePawnPresent[piw1][piw2][piw3][ulKings] :
1024
                              rgprgulTriplePawnless[piw1][piw2][piw3][ulKings]);
1025
            }
1026
        else
1027
            {
1028
            // Can we remove WK square from 1st piece Enumeration?
1029
            if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
1030
                ind1 -= (sqw1 > sqwk);
1031
            // Get # of enumerated positions of 2nd piece
1032
            cInd2 = rgcLegal[piw2][sqbk];
1033
            // Can we remove WK square from 2nd piece Enumeration?
1034
            if ((piw2>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw2][sqbk*64+sqwk]))
1035
                {
1036
                cInd2 --;
1037
                ind2 -= (sqw2 > sqwk);
1038
                }
1039
            // Get # of enumerated positions of 3rd piece
1040
            cInd3 = rgcLegal[piw3][sqbk];
1041
            // Can we remove WK square from 3rd piece Enumeration?
1042
            if ((piw3>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw3][sqbk*64+sqwk]))
1043
                {
1044
                cInd3 --;
1045
                ind3 -= (sqw3 > sqwk);
1046
                }
1047
            // Add enumerated square to the # of the preceeding positions
1048
            return  cInd3*(cInd2*ind1 + ind2) + ind3 +
1049
                    (fPawns ? rgprgulTriplePawnPresent[piw1][piw2][piw3][ulKings] :
1050
                              rgprgulTriplePawnless[piw1][piw2][piw3][ulKings]);
1051
            }
1052
        }
1053
    };
1054
1055
#endif
1056
1057
// Enumerate en passant captures
1058
1059
static INLINE unsigned TB_FASTCALL IndEnPassant11W
1060
    (
1061
    square  sqw,
1062
    square  sqb,
1063
    square  sqEnP
1064
    )
1065
    {
1066
    assert (sqb+8 == sqEnP);
1067
 
1068
        // Capture to the left
1069
 
1070
    else
1071
        {
1072
        // Capture to the right
1073
        assert (sqw+9 == sqEnP);
1074
        return  (sqw&7)+7;
1075
        }
1076
    }
1077
1078
static INLINE unsigned TB_FASTCALL IndEnPassant11B
1079
    (
1080
 
1081
    square  sqb,
1082
    square  sqEnP
1083
    )
1084
    {
1085
    assert (sqw-8 == sqEnP);
1086
    if (sqb-9 == sqEnP)
1087
        // Capture to the left
1088
        return (sqb&7)-1;
1089
    else
1090
        {
1091
        // Capture to the right
1092
        assert (sqb-7 == sqEnP);
1093
 
1094
        }
1095
 
1096
1097
static INLINE unsigned TB_FASTCALL IndEnPassant21W
1098
    (
1099
    square  sqw1,
1100
    square  sqw2,
1101
    square  sqb,
1102
    square  sqEnP
1103
    )
1104
    {
1105
    assert (sqb+8 == sqEnP);
1106
    SORT (sqw1, sqw2);
1107
    if (sqw1+7 == sqEnP && 0 != TbColumn(sqw1))
1108
        // Capture to the left
1109
 
1110
    else if (sqw1+9 == sqEnP && 7 != TbColumn(sqw1))
1111
        // Capture to the right
1112
        return (sqw1&7)+7+(EXCLUDE3(sqw2,sqb,sqEnP,sqEnP+8)-i8-1)*i14;
1113
    else if (sqw2+7 == sqEnP && 0 != TbColumn(sqw2))
1114
        // Capture to the left
1115
        return (sqw2&7)-1+(EXCLUDE3(sqw1,sqb,sqEnP,sqEnP+8)-i8)*i14;
1116
    else
1117
        {
1118
        // Capture to the right
1119
        assert (sqw2+9 == sqEnP && 7 != TbColumn(sqw2));
1120
        return (sqw2&7)+7+(EXCLUDE3(sqw1,sqb,sqEnP,sqEnP+8)-i8)*i14;
1121
        }
1122
    }
1123
1124
static INLINE unsigned TB_FASTCALL IndEnPassant21B
1125
    (
1126
    square  sqw1,
1127
    square  sqw2,
1128
    square  sqb,
1129
 
1130
    )
1131
 
1132
    assert (sqw1 < sqw2);   // Must be already sorted
1133
 
1134
        // Capture to the left
1135
        if (sqw1-8 == sqEnP)
1136
            return (sqb&7)-1+(EXCLUDE3(sqw2,sqb,sqEnP,sqEnP-8)-i8-1)*i14;
1137
        else
1138
            {
1139
            assert (sqw2-8 == sqEnP);
1140
            return (sqb&7)-1+(EXCLUDE3(sqw1,sqb,sqEnP,sqEnP-8)-i8)*i14;
1141
            }
1142
    else
1143
        {
1144
        // Capture to the right
1145
        assert (sqb-7 == sqEnP && 7 != TbColumn(sqb));
1146
        if (sqw1-8 == sqEnP)
1147
            return (sqb&7)+7+(EXCLUDE3(sqw2,sqb,sqEnP,sqEnP-8)-i8-1)*i14;
1148
        else
1149
 
1150
            assert (sqw2-8 == sqEnP);
1151
            return (sqb&7)+7+(EXCLUDE3(sqw1,sqb,sqEnP,sqEnP-8)-i8)*i14;
1152
            }
1153
        }
1154
    }
1155
1156
static INLINE unsigned TB_FASTCALL IndEnPassant12W
1157
    (
1158
    square  sqw,
1159
    square  sqb1,
1160
    square  sqb2,
1161
    square  sqEnP
1162
    )
1163
{
1164
    if(sqb2+8 == sqEnP)
1165
        SWAP(sqb1, sqb2);
1166
1167
    assert(sqb1+8 == sqEnP);
1168
1169
    if (sqw+7 == sqEnP && 0 != TbColumn(sqw))
1170
        // Capture to the left
1171
        return TbColumn(sqw)-1+(EXCLUDE4(sqb2,sqb1,sqw,sqEnP,sqEnP+8)-i8)*i14;
1172
1173
    assert(sqw+9 == sqEnP && 7 != TbColumn(sqw));
1174
1175
    // Capture to the right
1176
    return TbColumn(sqw)+7 + (EXCLUDE4(sqb2,sqb1,sqw,sqEnP,sqEnP+8)-i8)*i14;
1177
}
1178
1179
static INLINE unsigned TB_FASTCALL IndEnPassant12B
1180
 
1181
    square  sqw,
1182
 
1183
    square  sqb2,
1184
 
1185
    )
1186
 
1187
    assert(sqw-8 == sqEnP);
1188
1189
    SORT(sqb1, sqb2);
1190
1191
    if(sqb1-9 == sqEnP && 0 != TbColumn(sqb1))
1192
        // Capture to the left
1193
        return TbColumn(sqb1) - 1 + (sqb2-i8-4)*i14;
1194
 
1195
        // Capture to the right
1196
        return TbColumn(sqb1) + 7 + (sqb2-i8-4)*i14;
1197
    else if(sqb2-9 == sqEnP && 0 != TbColumn(sqb2))
1198
        // Capture to the left
1199
        return TbColumn(sqb2) - 1 + (EXCLUDE2(sqb1,sqEnP,sqEnP-8)-i8)*i14;
1200
1201
    // Capture to the right
1202
    assert(sqb2-7 == sqEnP && 7 != TbColumn(sqb2));
1203
    return TbColumn(sqb2) + 7 + (EXCLUDE2(sqb1,sqEnP,sqEnP-8)-i8)*i14;
1204
 
1205
1206
static INLINE unsigned TB_FASTCALL IndEnPassant22W
1207
    (
1208
    square  sqw1,
1209
    square  sqw2,
1210
    square  sqb1,
1211
    square  sqb2,
1212
    square  sqEnP
1213
    )
1214
{
1215
    square sqEmptyEnP = sqEnP + 8;
1216
1217
    if(sqb2+8== sqEnP)
1218
       SWAP(sqb1, sqb2);
1219
1220
    assert(sqb1+8 == sqEnP);
1221
1222
    SORT(sqw1, sqw2);
1223
1224
    if (sqw1+7 == sqEnP && 0 != TbColumn(sqw1))
1225
            // Capture to the left
1226
        return TbColumn(sqw1)-1+
1227
           (EXCLUDE2(sqw2,sqEnP,sqEmptyEnP)-i8-2)*i14+
1228
           (EXCLUDE5(sqb2,sqb1,sqw1,sqw2,sqEnP,sqEmptyEnP)-i8)*(i14*i44);
1229
    else if (sqw1+9 == sqEnP && 7 != TbColumn(sqw1))
1230
            // Capture to the right
1231
        return TbColumn(sqw1)+7+
1232
           (EXCLUDE2(sqw2,sqEnP,sqEmptyEnP)-i8-2)*i14+
1233
           (EXCLUDE5(sqb2,sqb1,sqw1,sqw2,sqEnP,sqEmptyEnP)-i8)*(i14*i44);
1234
    else if (sqw2+7 == sqEnP && 0 != TbColumn(sqw2))
1235
            // Capture to the left
1236
        return TbColumn(sqw2)-1+
1237
           (sqw1-i8)*i14+
1238
           (EXCLUDE5(sqb2,sqb1,sqw1,sqw2,sqEnP,sqEmptyEnP)-i8)*(i14*i44);
1239
1240
    // Capture to the right
1241
    assert(sqw2+9 == sqEnP && 7 != TbColumn(sqw2));
1242
    return TbColumn(sqw2)+7+
1243
           (sqw1-i8)*i14+
1244
       (EXCLUDE5(sqb2,sqb1,sqw1,sqw2,sqEnP,sqEmptyEnP)-i8)*(i14*i44);
1245
}
1246
1247
static INLINE unsigned TB_FASTCALL IndEnPassant22B
1248
    (
1249
    square  sqw1,
1250
    square  sqw2,
1251
    square  sqb1,
1252
    square  sqb2,
1253
    square  sqEnP
1254
    )
1255
{
1256
    square sqEmptyEnP = sqEnP - 8;
1257
1258
    if(sqw2-8 == sqEnP)
1259
       SWAP(sqw1, sqw2);
1260
1261
    assert(sqw1-8 == sqEnP);
1262
1263
    SORT(sqb1, sqb2);
1264
1265
 
1266
        // Capture to the left
1267
        return TbColumn(sqb1)-1+
1268
           (sqb2-i8-4)*i14+
1269
           (EXCLUDE5(sqw2,sqw1,sqb1,sqb2,sqEnP,sqEmptyEnP)-i8)*(i14*i44);
1270
    else if (sqb1-7 == sqEnP && 7 != TbColumn(sqb1))
1271
        // Capture to the right
1272
        return TbColumn(sqb1)+7+
1273
           (sqb2-i8-4)*i14+
1274
           (EXCLUDE5(sqw2,sqw1,sqb1,sqb2,sqEnP,sqEmptyEnP)-i8)*(i14*i44);
1275
    else if (sqb2-9 == sqEnP && 0 != TbColumn(sqb2))
1276
        // Capture to the left
1277
        return TbColumn(sqb2)-1+
1278
           (EXCLUDE2(sqb1,sqEnP,sqEmptyEnP)-i8)*i14+
1279
           (EXCLUDE5(sqw2,sqw1,sqb1,sqb2,sqEnP,sqEmptyEnP)-i8)*(i14*i44);
1280
1281
    // Capture to the right
1282
    assert(sqb2-7 == sqEnP && 7 != TbColumn(sqb2));
1283
    return TbColumn(sqb2)+7+
1284
           (EXCLUDE2(sqb1,sqEnP,sqEmptyEnP)-i8)*i14+
1285
       (EXCLUDE5(sqw2,sqw1,sqb1,sqb2,sqEnP,sqEmptyEnP)-i8)*(i14*i44);
1286
}
1287
1288
static INLINE unsigned TB_FASTCALL IndEnPassant31W
1289
    (
1290
    square  sqw1,
1291
    square  sqw2,
1292
    square  sqw3,
1293
    square  sqb,
1294
    square  sqEnP
1295
    )
1296
{
1297
    square sqEmptyEnP = sqEnP + 8;
1298
1299
    assert(sqb + 8 == sqEnP);
1300
1301
    SORT (sqw1, sqw2);
1302
    SORT (sqw2, sqw3);
1303
    SORT (sqw1, sqw2);
1304
1305
    if (sqw1+7 == sqEnP && 0 != TbColumn(sqw1)) {
1306
        // Capture to the left
1307
        sqw3 = EXCLUDE2(sqw3,sqEnP,sqEmptyEnP)-i8-2;
1308
        return TbColumn(sqw1)-1+
1309
               (EXCLUDE2(sqw2,sqEnP,sqEmptyEnP)-i8-2)*i14+
1310
               (sqw3*(sqw3-1)/2)*i14;
1311
        }
1312
    else if (sqw1+9 == sqEnP && 7 != TbColumn(sqw1)) {
1313
 
1314
        sqw3 = EXCLUDE2(sqw3,sqEnP,sqEmptyEnP)-i8-2;
1315
 
1316
               (EXCLUDE2(sqw2,sqEnP,sqEmptyEnP)-i8-2)*i14+
1317
               (sqw3*(sqw3-1)/2)*i14;
1318
    }
1319
    else if (sqw2+7 == sqEnP && 0 != TbColumn(sqw2)) {
1320
        // Capture to the left
1321
        sqw3 = EXCLUDE2(sqw3,sqEnP,sqEmptyEnP)-i8-2;
1322
        return TbColumn(sqw2)-1+
1323
               (sqw1-i8)*i14+
1324
               (sqw3*(sqw3-1)/2)*i14;
1325
    }
1326
    else if (sqw2+9 == sqEnP && 7 != TbColumn(sqw2)) {
1327
        // Capture to the right
1328
 
1329
        return TbColumn(sqw2)+7+
1330
               (sqw1-i8)*i14+
1331
               (sqw3*(sqw3-1)/2)*i14;
1332
    }
1333
    else if (sqw3+7 == sqEnP && 0 != TbColumn(sqw3)) {
1334
        // Capture to the left
1335
        sqw2 = sqw2-i8;
1336
 
1337
               (sqw1-i8)*i14+
1338
               (sqw2*(sqw2-1)/2)*i14;
1339
    }
1340
    else {
1341
        // Capture to the right
1342
        sqw2 = sqw2-i8;
1343
        return TbColumn(sqw3)+7+
1344
               (sqw1-i8)*i14+
1345
               (sqw2*(sqw2-1)/2)*i14;
1346
    }
1347
}
1348
1349
static INLINE unsigned TB_FASTCALL IndEnPassant31B
1350
    (
1351
    square  sqw1,
1352
    square  sqw2,
1353
    square  sqw3,
1354
    square  sqb,
1355
    square  sqEnP
1356
    )
1357
{
1358
    square sqEmptyEnP = sqEnP - 8;
1359
 
1360
    if(sqw2 - 8 == sqEnP)
1361
 
1362
    if(sqw3 - 8 == sqEnP)
1363
        SWAP(sqw1, sqw3);
1364
1365
    assert(sqw1 - 8 == sqEnP);
1366
1367
    SORT(sqw2, sqw3);
1368
1369
    if(sqb - 9 == sqEnP && 0 != TbColumn(sqb)) {
1370
        sqw3 = EXCLUDE4(sqw3,sqw1,sqb,sqEnP,sqEmptyEnP)-i8;
1371
        return TbColumn(sqb)-1+
1372
        (EXCLUDE4(sqw2,sqw1,sqb,sqEnP,sqEmptyEnP)-i8)*i14+
1373
        (sqw3*(sqw3-1)/2)*i14;
1374
    }
1375
 
1376
        assert(sqb - 7 == sqEnP && 7 != TbColumn(sqb));
1377
        sqw3 = EXCLUDE4(sqw3,sqw1,sqb,sqEnP,sqEmptyEnP)-i8;
1378
        return TbColumn(sqb)+7+
1379
            (EXCLUDE4(sqw2,sqw1,sqb,sqEnP,sqEmptyEnP)-i8)*i14+
1380
        (sqw3*(sqw3-1)/2)*i14;
1381
    }
1382
}
1383
1384
 
1385
1386
template <int piw1> class T21
1387
    {
1388
public:
1389
    static INDEX TB_FASTCALL IndCalcW
1390
        (
1391
        square  *psqW,
1392
        square  *psqB,
1393
        square  sqEnP,
1394
        int     fInvert
1395
        )
1396
        {
1397
        square sqwk, sqw1, sqbk, sqMask;
1398
1399
        sqwk = SqFindKing (psqW);
1400
        sqw1 = SqFindOne  (psqW, piw1);
1401
        sqbk = SqFindKing (psqB);
1402
1403
        if (x_piecePawn == piw1)
1404
            sqMask = rgsqReflectMaskY [sqwk] ^ rgsqReflectInvertMask [fInvert];
1405
        else
1406
            sqMask = rgsqReflectMaskYandX [sqwk];
1407
        sqwk ^= sqMask;
1408
        sqbk ^= sqMask;
1409
        sqw1 ^= sqMask;
1410
1411
        if (x_piecePawn != piw1)
1412
            {
1413
            // No pawn
1414
            if (! FInTriangle (sqwk, sqbk))
1415
                {
1416
                sqwk = reflect_xy(sqwk);
1417
                sqbk = reflect_xy(sqbk);
1418
                sqw1 = reflect_xy(sqw1);
1419
                };
1420
            }
1421
        return TEnumerate1<piw1,x_piecePawn==piw1 ? true : false,false>::Index(sqwk,sqw1,sqbk);
1422
        }
1423
1424
    static INDEX TB_FASTCALL IndCalcB
1425
        (
1426
        square  *psqW,
1427
        square  *psqB,
1428
        square  sqEnP,
1429
        int     fInvert
1430
        )
1431
        {
1432
        square sqwk, sqw1, sqbk, sqMask;
1433
 
1434
        sqwk = SqFindKing (psqW);
1435
 
1436
        sqbk = SqFindKing (psqB);
1437
 
1438
        if (x_piecePawn == piw1)
1439
            sqMask = rgsqReflectMaskY [sqbk] ^ rgsqReflectInvertMask [fInvert];
1440
        else
1441
            sqMask = rgsqReflectMaskYandX [sqbk];
1442
        sqwk ^= sqMask;
1443
        sqbk ^= sqMask;
1444
        sqw1 ^= sqMask;
1445
1446
        if (x_piecePawn == piw1)
1447
            return TEnumerate1<x_pieceNone,true,true>::Index(sqbk,sqw1,sqwk);
1448
        else
1449
            {
1450
            // No pawn
1451
            if (! FInTriangle (sqbk, sqwk))
1452
 
1453
                sqwk = reflect_xy(sqwk);
1454
                sqbk = reflect_xy(sqbk);
1455
                sqw1 = reflect_xy(sqw1);
1456
                };
1457
            return IndTriKings(sqbk,sqwk)*i62 + EXCLUDE2(sqw1,sqwk,sqbk);
1458
            }
1459
        }
1460
    };
1461
1462
 
1463
    {
1464
public:
1465
    static INDEX TB_FASTCALL IndCalcW
1466
        (
1467
        square  *psqW,
1468
        square  *psqB,
1469
        square  sqEnP,
1470
        int     fInvert
1471
        )
1472
        {
1473
        square sqwk, sqw1, sqbk, sqb1, sqMask;
1474
1475
        sqwk = SqFindKing (psqW);
1476
        sqw1 = SqFindOne  (psqW, piw1);
1477
        sqbk = SqFindKing (psqB);
1478
        sqb1 = SqFindOne  (psqB, pib1);
1479
1480
        if (x_piecePawn == pib1)
1481
            sqMask = rgsqReflectMaskY [sqwk] ^ rgsqReflectInvertMask [fInvert];
1482
        else
1483
            sqMask = rgsqReflectMaskYandX [sqwk];
1484
        sqwk ^= sqMask;
1485
        sqbk ^= sqMask;
1486
        sqw1 ^= sqMask;
1487
        sqb1 ^= sqMask;
1488
1489
        if (x_piecePawn == pib1)
1490
            {
1491
            // There are pawns on the board
1492
            if (x_piecePawn == piw1)
1493
                {
1494
                // One white and one black pawn
1495
                if (XX == sqEnP)
1496
                    return  TEnumerate1<x_piecePawn,true,false>::Index(sqwk,sqw1,sqbk)*i47 +
1497
                            EXCLUDE1(sqb1,sqw1)-i8; // 47
1498
                else
1499
                    return  rgcSinglePawnPresent[x_piecePawn]*i47 +
1500
                            IndHalfKings(sqwk,sqbk)*i14 +
1501
                            IndEnPassant11W (sqw1, sqb1, sqEnP ^ sqMask);
1502
                }
1503
            else
1504
                // Only black pawn
1505
                return  TEnumerate1<piw1,true,false>::Index(sqwk,sqw1,sqbk)*i48 + sqb1-i8;
1506
            }
1507
        else
1508
            {
1509
            // No pawns at all
1510
            if (!FInTriangle (sqwk, sqbk))
1511
                {
1512
                sqwk = reflect_xy(sqwk);
1513
                sqbk = reflect_xy(sqbk);
1514
                sqw1 = reflect_xy(sqw1);
1515
                sqb1 = reflect_xy(sqb1);
1516
                };
1517
            return  TEnumerate1<piw1,false,false>::Index(sqwk,sqw1,sqbk)*i61 +
1518
                    EXCLUDE3(sqb1,sqwk,sqbk,sqw1);  // 61
1519
            }
1520
        }
1521
1522
    static INDEX TB_FASTCALL IndCalcB
1523
        (
1524
        square  *psqW,
1525
        square  *psqB,
1526
        square  sqEnP,
1527
        int     fInvert
1528
        )
1529
        {
1530
        square sqwk, sqw1, sqbk, sqb1, sqMask;
1531
1532
        sqwk = SqFindKing (psqW);
1533
        sqw1 = SqFindOne  (psqW, piw1);
1534
        sqbk = SqFindKing (psqB);
1535
        sqb1 = SqFindOne  (psqB, pib1);
1536
1537
        if (x_piecePawn == pib1)
1538
            sqMask = rgsqReflectMaskY [sqbk] ^ rgsqReflectInvertMask [fInvert];
1539
        else
1540
            sqMask = rgsqReflectMaskYandX [sqbk];
1541
        sqwk ^= sqMask;
1542
        sqbk ^= sqMask;
1543
        sqw1 ^= sqMask;
1544
        sqb1 ^= sqMask;
1545
1546
        if (x_piecePawn == pib1)
1547
            {
1548
            // There are pawns on the board
1549
            if (x_piecePawn == piw1)
1550
                {
1551
                // One white and one black pawn
1552
                if (XX == sqEnP)
1553
                    return  TEnumerate1<x_piecePawn,true,true>::Index(sqbk,sqb1,sqwk)*i47 +
1554
                            EXCLUDE1(sqw1,sqb1)-i8; // 47
1555
                else
1556
                    return  rgcSinglePawnPresent[x_piecePawn]*i47 +
1557
                            IndHalfKings(sqbk,sqwk)*i14 +
1558
                            IndEnPassant11B (sqw1, sqb1, sqEnP ^ sqMask);
1559
                }
1560
            }
1561
        else
1562
            {
1563
            // No pawns at all
1564
            if (!FInTriangle (sqbk, sqwk))
1565
                {
1566
                sqwk = reflect_xy(sqwk);
1567
                sqbk = reflect_xy(sqbk);
1568
                sqw1 = reflect_xy(sqw1);
1569
                sqb1 = reflect_xy(sqb1);
1570
                };
1571
            }
1572
        return  (x_piecePawn == pib1 ?  TEnumerate1<pib1,true,true>::Index(sqbk,sqb1,sqwk) :
1573
                                        TEnumerate1<pib1,false,false>::Index(sqbk,sqb1,sqwk))*i61 +
1574
                EXCLUDE3(sqw1,sqwk,sqbk,sqb1);  // 61
1575
        }
1576
    };
1577
1578
 
1579
    {
1580
 
1581
    static INDEX TB_FASTCALL IndCalcW
1582
 
1583
        square  *psqW,
1584
        square  *psqB,
1585
        square  sqEnP,
1586
        int     fInvert
1587
        )
1588
        {
1589
        square sqwk, sqw1, sqw2, sqbk, sqMask;
1590
1591
        sqwk = SqFindKing (psqW);
1592
        if (piw1 == piw2)
1593
            {
1594
            sqw1 = SqFindFirst  (psqW, piw1);
1595
            sqw2 = SqFindSecond (psqW, piw2);
1596
            }
1597
        else
1598
            {
1599
            SqFind2 (psqW, piw1, sqw1, piw2, sqw2);
1600
            }
1601
 
1602
1603
        if (x_piecePawn == piw2)
1604
            sqMask = rgsqReflectMaskY [sqwk] ^ rgsqReflectInvertMask [fInvert];
1605
        else
1606
            sqMask = rgsqReflectMaskYandX [sqwk];
1607
        sqwk ^= sqMask;
1608
        sqbk ^= sqMask;
1609
        sqw1 ^= sqMask;
1610
        sqw2 ^= sqMask;
1611
1612
        if (x_piecePawn != piw2)
1613
            {
1614
            // There are no pawns on the board
1615
            if (!FInTriangle (sqwk, sqbk))
1616
                {
1617
                sqwk = reflect_xy(sqwk);
1618
                sqw1 = reflect_xy(sqw1);
1619
                sqw2 = reflect_xy(sqw2);
1620
 
1621
                };
1622
            }
1623
        return TEnumerate2<piw1, piw2, x_piecePawn==piw2 ? true : false, false>::Index(sqwk, sqw1, sqw2, sqbk);
1624
        }
1625
1626
    static INDEX TB_FASTCALL IndCalcB
1627
        (
1628
        square  *psqW,
1629
        square  *psqB,
1630
        square  sqEnP,
1631
        int     fInvert
1632
        )
1633
        {
1634
        square sqwk, sqw1, sqw2, sqbk, sqMask;
1635
1636
        sqwk = SqFindKing (psqW);
1637
        if (piw1 == piw2)
1638
            {
1639
            sqw1 = SqFindFirst (psqW, piw1);
1640
            sqw2 = SqFindSecond (psqW, piw2);
1641
            }
1642
        else
1643
            {
1644
            SqFind2 (psqW, piw1, sqw1, piw2, sqw2);
1645
            }
1646
        sqbk = SqFindKing (psqB);
1647
 
1648
        if (x_piecePawn == piw2)
1649
            sqMask = rgsqReflectMaskY [sqbk] ^ rgsqReflectInvertMask [fInvert];
1650
        else
1651
            sqMask = rgsqReflectMaskYandX [sqbk];
1652
        sqwk ^= sqMask;
1653
        sqbk ^= sqMask;
1654
        sqw1 ^= sqMask;
1655
        sqw2 ^= sqMask;
1656
1657
        if (x_piecePawn == piw2)
1658
            {
1659
            // There are pawns on the board
1660
            if (x_piecePawn == piw1)
1661
                // Two white pawns
1662
                return  TEnumerate2<x_pieceNone,x_pieceNone,true,true>::Index(sqbk,sqw1,sqw2,sqwk);
1663
            else
1664
                // Only one white pawn
1665
                return  TEnumerate1<x_pieceNone,true,true>::Index(sqbk,sqw2,sqwk)*i61 +
1666
                        EXCLUDE3(sqw1,sqwk,sqbk,sqw2);  // 61
1667
            }
1668
        else
1669
            {
1670
            // No pawns
1671
            if (!FInTriangle (sqbk, sqwk))
1672
                {
1673
                sqwk = reflect_xy(sqwk);
1674
                sqw1 = reflect_xy(sqw1);
1675
                sqw2 = reflect_xy(sqw2);
1676
                sqbk = reflect_xy(sqbk);
1677
                };
1678
            if (piw1 == piw2)
1679
 
1680
                SORT (sqw1, sqw2);
1681
                sqw2 = EXCLUDE2(sqw2,sqwk,sqbk);                    // 62
1682
                return  IndTriKings(sqbk,sqwk)*(i62*i61/2) +
1683
                        sqw2*(sqw2-1)/2+EXCLUDE2(sqw1,sqwk,sqbk);   // 62*61/2
1684
                }
1685
            else
1686
                return  IndTriKings(sqbk,sqwk)*(i62*i61) +
1687
                        EXCLUDE2(sqw1,sqwk,sqbk)*i61 +  // 62
1688
                        EXCLUDE3(sqw2,sqwk,sqbk,sqw1);  // 61
1689
            }
1690
 
1691
    };
1692
 
1693
template <int piw1, int piw2, int pib1> class T32
1694
    {
1695
public:
1696
 
1697
        (
1698
 
1699
        square  *psqB,
1700
        square  sqEnP,
1701
        int     fInvert
1702
 
1703
        {
1704
        square sqwk, sqw1, sqw2, sqbk, sqb1, sqMask;
1705
1706
        sqwk = SqFindKing (psqW);
1707
        if (piw1 == piw2)
1708
            {
1709
            sqw1 = SqFindFirst  (psqW, piw1);
1710
            sqw2 = SqFindSecond (psqW, piw2);
1711
            }
1712
 
1713
            {
1714
 
1715
            }
1716
        sqbk = SqFindKing (psqB);
1717
        sqb1 = SqFindOne  (psqB, pib1);
1718
1719
        if (x_piecePawn == piw2 || x_piecePawn == pib1)
1720
            sqMask = rgsqReflectMaskY [sqwk] ^ rgsqReflectInvertMask [fInvert];
1721
        else
1722
            sqMask = rgsqReflectMaskYandX [sqwk];
1723
        sqwk ^= sqMask;
1724
 
1725
        sqw1 ^= sqMask;
1726
        sqw2 ^= sqMask;
1727
        sqb1 ^= sqMask;
1728
1729
 
1730
            {
1731
            // There are pawns on the board
1732
            if (x_piecePawn == pib1)
1733
                {
1734
                // Black pawn
1735
                if (x_piecePawn == piw1 && x_piecePawn == piw2)
1736
                    {
1737
                    // All 3 pieces are pawns
1738
                    if (XX == sqEnP)
1739
                        return  TEnumerate2<x_piecePawn,x_piecePawn,true,false>::
1740
 
1741
                                EXCLUDE2(sqb1,sqw1,sqw2)-i8;    // 46
1742
                    else
1743
 
1744
                        return  rgcPairPawnPresent[x_piecePawn][x_piecePawn]*i46 +
1745
 
1746
                                IndEnPassant21W (sqw1, sqw2, sqb1, sqEnP ^ sqMask);
1747
 
1748
                else if (x_piecePawn == piw2)
1749
                    {
1750
                    // One white pawn, one black pawn
1751
                    if (XX == sqEnP)
1752
                        return  TEnumerate2<piw1,x_piecePawn,true,false>::
1753
                                    Index(sqwk,sqw1,sqw2,sqbk)*i47 +
1754
                                EXCLUDE1(sqb1,sqw2)-i8; // 47
1755
                    else
1756
                        // En passant capture
1757
                        return  rgcPairPawnPresent[piw1][x_piecePawn]*i47 +
1758
                                TEnumerate1<piw1,true,false>::Index(sqwk,sqw1,sqbk)*i14 +
1759
                                IndEnPassant11W (sqw2, sqb1, sqEnP ^ sqMask);
1760
                    }
1761
                else
1762
                    // Only black pawn
1763
 
1764
                                Index(sqwk,sqw1,sqw2,sqbk)*i48 +
1765
                            sqb1-i8;    // 48
1766
                }
1767
            }
1768
        else
1769
            {
1770
 
1771
            if (!FInTriangle (sqwk, sqbk))
1772
                {
1773
                sqwk = reflect_xy(sqwk);
1774
                sqw1 = reflect_xy(sqw1);
1775
                sqw2 = reflect_xy(sqw2);
1776
                sqbk = reflect_xy(sqbk);
1777
                sqb1 = reflect_xy(sqb1);
1778
                };
1779
            }
1780
        return  TEnumerate2<piw1,piw2,(x_piecePawn==piw2||x_piecePawn==pib1) ? true : false,false>::
1781
 
1782
                EXCLUDE4(sqb1,sqwk,sqbk,sqw1,sqw2); // 60
1783
        }
1784
 
1785
    static INDEX TB_FASTCALL IndCalcB
1786
 
1787
        square  *psqW,
1788
 
1789
        square  sqEnP,
1790
        int     fInvert
1791
        )
1792
        {
1793
        square sqwk, sqw1, sqw2, sqbk, sqb1, sqMask;
1794
1795
        sqwk = SqFindKing (psqW);
1796
        if (piw1 == piw2)
1797
            {
1798
            sqw1 = SqFindFirst  (psqW, piw1);
1799
            sqw2 = SqFindSecond (psqW, piw2);
1800
            }
1801
        else
1802
            {
1803
            SqFind2 (psqW, piw1, sqw1, piw2, sqw2);
1804
 
1805
        sqbk = SqFindKing (psqB);
1806
        sqb1 = SqFindOne  (psqB, pib1);
1807
1808
        if (x_piecePawn == piw2 || x_piecePawn == pib1)
1809
            sqMask = rgsqReflectMaskY [sqbk] ^ rgsqReflectInvertMask [fInvert];
1810
        else
1811
 
1812
        sqwk ^= sqMask;
1813
        sqbk ^= sqMask;
1814
        sqw1 ^= sqMask;
1815
        sqw2 ^= sqMask;
1816
        sqb1 ^= sqMask;
1817
1818
        if (x_piecePawn == piw2 || x_piecePawn == pib1)
1819
            {
1820
            // There are pawns on the board
1821
            if (x_piecePawn == pib1)
1822
 
1823
                // Black pawn
1824
 
1825
                    {
1826
                    // All 3 pieces are pawns
1827
                    SORT (sqw1, sqw2);
1828
 
1829
                        {
1830
                        sqw2 = EXCLUDE1(sqw2,sqb1)-i8;                  // 47
1831
                        return  TEnumerate1<x_piecePawn,true,true>::
1832
                                    Index(sqbk,sqb1,sqwk)*(i47*i46/2) +
1833
                                sqw2*(sqw2-1)/2+EXCLUDE1(sqw1,sqb1)-i8; // 47*46/2
1834
                        }
1835
                    else
1836
                        // En passant capture
1837
                        return  rgcSinglePawnPresent[x_piecePawn]*(i47*i46/2) +
1838
                                IndHalfKings(sqbk,sqwk)*(i44*i14) +
1839
                                IndEnPassant21B (sqw1, sqw2, sqb1, sqEnP ^ sqMask);
1840
                    }
1841
                else if (x_piecePawn == piw2)
1842
                    {
1843
                    // One white pawn, one black pawn
1844
                    if (XX == sqEnP)
1845
                        return  TEnumerate1<x_piecePawn,true,true>::
1846
                                    Index(sqbk,sqb1,sqwk)*(i60*i47) +
1847
                                EXCLUDE4(sqw1,sqwk,sqbk,sqw2,sqb1)*i47 +    // 60
1848
                                EXCLUDE1(sqw2,sqb1)-i8;                     // 47
1849
                    else
1850
                        {
1851
                        // En passant capture
1852
                        sqEnP ^= sqMask;
1853
                        return  rgcSinglePawnPresent[x_piecePawn]*(i60*i47) +
1854
                                IndHalfKings(sqbk,sqwk)*(i58*i14) +
1855
                                EXCLUDE6(sqw1,sqwk,sqbk,sqw2,sqb1,sqEnP,sqEnP-8)*i14 +  // 58
1856
                                IndEnPassant11B (sqw2, sqb1, sqEnP);
1857
                        }
1858
                    }
1859
                else
1860
                    {
1861
                    // Only black pawn
1862
                    if (piw1 == piw2)
1863
                        {
1864
                        // 2 identical white pieces
1865
                        SORT (sqw1, sqw2);
1866
                        sqw2 = EXCLUDE3(sqw2,sqwk,sqbk,sqb1);                       // 61
1867
                        return  TEnumerate1<x_piecePawn,true,true>::
1868
                                    Index(sqbk,sqb1,sqwk)*(i61*i60/2) +
1869
                                sqw2*(sqw2-1)/2 + EXCLUDE3(sqw1,sqwk,sqbk,sqb1);    // 61*60/2
1870
                        }
1871
                    return  TEnumerate1<x_piecePawn,true,true>::
1872
 
1873
                            EXCLUDE3(sqw1,sqwk,sqbk,sqb1)*i60 + // 61
1874
                            EXCLUDE4(sqw2,sqwk,sqbk,sqw1,sqb1); // 60
1875
                    }
1876
                }
1877
            else
1878
                {
1879
                // No black pawn
1880
                if (x_piecePawn == piw1)
1881
                    {
1882
                    // Only 2 white pawns
1883
 
1884
                    sqw2 -= i8;
1885
                    return  TEnumerate1<pib1,true,true>::
1886
                                Index(sqbk,sqb1,sqwk)*(i48*47/2) +
1887
                            sqw2*(sqw2-1)/2+sqw1-i8;            // 48*47/2
1888
 
1889
                else
1890
 
1891
                    return  TEnumerate1<pib1,true,true>::
1892
 
1893
                            EXCLUDE4(sqw1,sqwk,sqbk,sqw2,sqb1)*i48 +    // 60
1894
                            sqw2-i8;                                    // 48
1895
                }
1896
            }
1897
        else
1898
            {
1899
            // No pawns
1900
            if (!FInTriangle (sqbk, sqwk))
1901
                {
1902
                sqwk = reflect_xy(sqwk);
1903
                sqw1 = reflect_xy(sqw1);
1904
                sqw2 = reflect_xy(sqw2);
1905
                sqbk = reflect_xy(sqbk);
1906
                sqb1 = reflect_xy(sqb1);
1907
 
1908
            if (piw1 == piw2)
1909
 
1910
                // 2 identical white pieces
1911
                SORT (sqw1, sqw2);
1912
                sqw2 = EXCLUDE3(sqw2,sqwk,sqbk,sqb1);                   // 61
1913
                return  TEnumerate1<pib1,false,false>::
1914
                            Index(sqbk,sqb1,sqwk)*(i61*i60/2) +
1915
                        sqw2*(sqw2-1)/2+EXCLUDE3(sqw1,sqwk,sqbk,sqb1);  // 61*60/2
1916
                }
1917
            else
1918
                return  TEnumerate1<pib1,false,false>::
1919
                            Index(sqbk,sqb1,sqwk)*(i61*i60) +
1920
                        EXCLUDE3(sqw1,sqwk,sqbk,sqb1)*i60 + // 61
1921
                        EXCLUDE4(sqw2,sqwk,sqbk,sqw1,sqb1); // 60
1922
 
1923
        }
1924
    };
1925
1926
 
1927
1928
template <int piw1, int piw2, int piw3> class T41
1929
    {
1930
public:
1931
    static INDEX TB_FASTCALL IndCalcW
1932
        (
1933
        square  *psqW,
1934
 
1935
        square  sqEnP,
1936
        int     fInvert
1937
        )
1938
        {
1939
        square sqwk, sqw1, sqw2, sqw3, sqbk, sqMask;
1940
1941
        sqwk = SqFindKing (psqW);
1942
        sqw1 = SqFindFirst (psqW, piw1);
1943
        if (piw1 == piw2 && piw2 == piw3)
1944
            {
1945
            sqw2 = SqFindSecond (psqW, piw2);
1946
            sqw3 = SqFindThird (psqW, piw3);
1947
 
1948
        else if (piw1 == piw2)
1949
            {
1950
            sqw2 = SqFindSecond (psqW, piw2);
1951
            sqw3 = SqFindFirst (psqW, piw3);
1952
            }
1953
        else if (piw2 == piw3)
1954
            {
1955
            sqw2 = SqFindFirst (psqW, piw2);
1956
            sqw3 = SqFindSecond (psqW, piw3);
1957
 
1958
        else
1959
            {
1960
            sqw2 = SqFindFirst (psqW, piw2);
1961
 
1962
            }
1963
        sqbk = SqFindKing (psqB);
1964
1965
        if (x_piecePawn == piw3)
1966
            sqMask = rgsqReflectMaskY [sqwk] ^ rgsqReflectInvertMask [fInvert];
1967
        else
1968
            sqMask = rgsqReflectMaskYandX [sqwk];
1969
 
1970
        sqbk ^= sqMask;
1971
        sqw1 ^= sqMask;
1972
        sqw2 ^= sqMask;
1973
        sqw3 ^= sqMask;
1974
1975
        if (x_piecePawn != piw3)
1976
            {
1977
            // No pawns
1978
            if (!FInTriangle (sqwk, sqbk))
1979
                {
1980
                sqwk = reflect_xy(sqwk);
1981
                sqw1 = reflect_xy(sqw1);
1982
                sqw2 = reflect_xy(sqw2);
1983
                sqw3 = reflect_xy(sqw3);
1984
                sqbk = reflect_xy(sqbk);
1985
 
1986
            }
1987
        return  TEnumerate3<piw1,piw2,piw3,x_piecePawn == piw3,false>::Index(sqwk,sqw1,sqw2,sqw3,sqbk);
1988
        }
1989
1990
    static INDEX TB_FASTCALL IndCalcB
1991
        (
1992
        square  *psqW,
1993
        square  *psqB,
1994
        square  sqEnP,
1995
        int     fInvert
1996
        )
1997
        {
1998
 
1999
2000
        sqwk = SqFindKing (psqW);
2001
        sqw1 = SqFindFirst (psqW, piw1);
2002
        if (piw1 == piw2 && piw2 == piw3)
2003
 
2004
            sqw2 = SqFindSecond (psqW, piw2);
2005
            sqw3 = SqFindThird (psqW, piw3);
2006
            }
2007
        else if (piw1 == piw2)
2008
            {
2009
            sqw2 = SqFindSecond (psqW, piw2);
2010
            sqw3 = SqFindFirst (psqW, piw3);
2011
            }
2012
 
2013
            {
2014
            sqw2 = SqFindFirst (psqW, piw2);
2015
            sqw3 = SqFindSecond (psqW, piw3);
2016
            }
2017
        else
2018
            {
2019
            sqw2 = SqFindFirst (psqW, piw2);
2020
            sqw3 = SqFindFirst (psqW, piw3);
2021
            }
2022
        sqbk = SqFindKing (psqB);
2023
2024
        if (x_piecePawn == piw3)
2025
            sqMask = rgsqReflectMaskY [sqbk] ^ rgsqReflectInvertMask [fInvert];
2026
        else
2027
            sqMask = rgsqReflectMaskYandX [sqbk];
2028
        sqwk ^= sqMask;
2029
        sqbk ^= sqMask;
2030
        sqw1 ^= sqMask;
2031
        sqw2 ^= sqMask;
2032
        sqw3 ^= sqMask;
2033
2034
        if (x_piecePawn == piw3)
2035
            {
2036
            // There are pawns on the board
2037
            if (x_piecePawn == piw1)
2038
                // 3 white pawns
2039
                return  TEnumerate3<x_pieceNone,x_pieceNone,x_pieceNone,true,true>::
2040
                            Index(sqbk,sqw1,sqw2,sqw3,sqwk);
2041
            else if (x_piecePawn == piw2)
2042
                // 2 white pawns
2043
                return  TEnumerate2<x_pieceNone,x_pieceNone,true,true>::
2044
                            Index(sqbk,sqw2,sqw3,sqwk)*i60 +
2045
 
2046
            else if (piw1 == piw2)
2047
                {
2048
                // 1 pawn, 2 pieces equal
2049
                SORT (sqw1, sqw2);
2050
                sqw2 = EXCLUDE3(sqw2,sqwk,sqbk,sqw3);                   // 61
2051
                return  TEnumerate1<x_pieceNone,true,true>::
2052
                            Index(sqbk,sqw3,sqwk)*(i61*i60/2) +
2053
                        sqw2*(sqw2-1)/2+EXCLUDE3(sqw1,sqwk,sqbk,sqw3);  // 61*60/2
2054
                }
2055
 
2056
                // Only one white pawn
2057
                return  TEnumerate1<x_pieceNone,true,true>::Index(sqbk,sqw3,sqwk)*i61*i60 +
2058
                        EXCLUDE3(sqw1,sqwk,sqbk,sqw3)*i60 + // 61
2059
                        EXCLUDE4(sqw2,sqwk,sqbk,sqw1,sqw3); // 60
2060
 
2061
        else
2062
            {
2063
            // No pawns
2064
            if (!FInTriangle (sqbk, sqwk))
2065
                {
2066
                sqwk = reflect_xy(sqwk);
2067
                sqw1 = reflect_xy(sqw1);
2068
                sqw2 = reflect_xy(sqw2);
2069
 
2070
                sqbk = reflect_xy(sqbk);
2071
                };
2072
            if (piw1 == piw2 && piw2 == piw3)
2073
                {
2074
                // All 3 pieces equal
2075
                SORT (sqw1, sqw2);
2076
                SORT (sqw2, sqw3);
2077
                SORT (sqw1, sqw2);
2078
                sqw3 = EXCLUDE2(sqw3,sqwk,sqbk);    // 62
2079
                sqw2 = EXCLUDE2(sqw2,sqwk,sqbk);
2080
                return  IndTriKings(sqbk,sqwk)*(i62*i61*i60/6) +
2081
                        sqw3*(sqw3-1)*(sqw3-2)/6+
2082
                        sqw2*(sqw2-1)/2+
2083
                        EXCLUDE2(sqw1,sqwk,sqbk);   // 62*61*60/6
2084
                }
2085
            else if (piw1 == piw2)
2086
                {
2087
                // 2 major pieces equal
2088
                SORT (sqw1, sqw2);
2089
                sqw2 = EXCLUDE3(sqw2,sqwk,sqbk,sqw3);                           // 61
2090
                return  IndTriKings(sqbk,sqwk)*(i61*i60/2*i62) +
2091
                        (sqw2*(sqw2-1)/2+EXCLUDE3(sqw1,sqwk,sqbk,sqw3))*i62 +   // 61*60/2
2092
                        EXCLUDE2(sqw3,sqwk,sqbk);                               // 62
2093
                }
2094
            else if (piw2 == piw3)
2095
                {
2096
                // 2 minor pieces equal
2097
                SORT (sqw2, sqw3);
2098
                sqw3 = EXCLUDE3(sqw3,sqwk,sqbk,sqw1);                   // 61
2099
                return  IndTriKings(sqbk,sqwk)*(i62*i61*i60/2) +
2100
                        EXCLUDE2(sqw1,sqwk,sqbk)*(i61*i60/2) +          // 62
2101
 
2102
                }
2103
            else
2104
                return  IndTriKings(sqbk,sqwk)*(i62*i61*i60) +
2105
                        EXCLUDE2(sqw1,sqwk,sqbk)*(i61*i60) +    // 62
2106
                        EXCLUDE3(sqw2,sqwk,sqbk,sqw1)*i60 +     // 61
2107
                        EXCLUDE4(sqw3,sqwk,sqbk,sqw1,sqw2);     // 60
2108
            }
2109
        }
2110
    };
2111
2112
#endif  // T41
2113
2114
 
2115
2116
#define CHECK_INF_SINGLE(ind)\
2117
        if (INF_SINGLE == ind)\
2118
            return (INDEX) -1;\
2119
2120
#define CHECK_INF_PAIR(ind)\
2121
        if (INF_PAIR == ind)\
2122
            return (INDEX) -1;\
2123
2124
#define CHECK_INF_TRIPLE(ind)\
2125
        if (INF_TRIPLE == ind)\
2126
 
2127
2128
#else
2129
2130
#define CHECK_INF_SINGLE(ind)
2131
#define CHECK_INF_PAIR(ind)
2132
#define CHECK_INF_TRIPLE(ind)
2133
2134
#endif
2135
 
2136
#if defined (T33_INCLUDE)
2137
2138
template <int piw1, int piw2, int pib1, int pib2> class T33
2139
{
2140
public:
2141
    static INDEX TB_FASTCALL IndCalcW
2142
        (
2143
        square  *psqW,
2144
        square  *psqB,
2145
        square  sqEnP,
2146
        int     fInvert
2147
        )
2148
    {
2149
 
2150
        unsigned uInd;
2151
2152
        sqwk = SqFindKing (psqW);
2153
        if (piw1 == piw2) {
2154
            sqw1 = SqFindFirst  (psqW, piw1);
2155
            sqw2 = SqFindSecond (psqW, piw2);
2156
            }
2157
        else {
2158
            SqFind2 (psqW, piw1, sqw1, piw2, sqw2);
2159
 
2160
        sqbk = SqFindKing (psqB);
2161
        if (pib1 == pib2) {
2162
            sqb1 = SqFindFirst  (psqB, pib1);
2163
            sqb2 = SqFindSecond (psqB, pib2);
2164
            }
2165
        else {
2166
            SqFind2 (psqB, pib1, sqb1, pib2, sqb2);
2167
            }
2168
2169
        if(x_piecePawn == piw2 || x_piecePawn == pib2)
2170
            sqMask = rgsqReflectMaskY[sqwk] ^ rgsqReflectInvertMask[fInvert];
2171
 
2172
            sqMask = rgsqReflectMaskYandX[sqwk];
2173
2174
        sqwk ^= sqMask;
2175
        sqbk ^= sqMask;
2176
        sqw1 ^= sqMask;
2177
        sqw2 ^= sqMask;
2178
        sqb1 ^= sqMask;
2179
        sqb2 ^= sqMask;
2180
 
2181
        if(x_piecePawn == piw2 || x_piecePawn == pib2) {
2182
            // There are pawns on the board
2183
            if(XX == sqEnP) {
2184
                // No En Passant possible
2185
                uInd = TEnumerate2<piw1,piw2,true,false>::Index(sqwk,sqw1,sqw2,sqbk);
2186
                CHECK_INF_PAIR(uInd);
2187
                if(x_piecePawn == piw1) {
2188
                    // all 4 pieces are pawns
2189
                    SORT(sqb1, sqb2);
2190
                    sqb2 = EXCLUDE2(sqb2,sqw1,sqw2) - i8;
2191
                    return uInd*(INDEX)(i46*i45/2) +
2192
                           sqb2*(sqb2-1)/2 + EXCLUDE2(sqb1,sqw1,sqw2) - i8;
2193
                }
2194
                else if(x_piecePawn == piw2) {
2195
                    if(x_piecePawn == pib1) {
2196
                        // 1 white, 2 black pawns
2197
                        SORT(sqb1, sqb2);
2198
                        sqb2 = EXCLUDE1(sqb2,sqw2) - i8;
2199
                        return uInd*(INDEX)(i47*i46/2) +
2200
                               sqb2*(sqb2-1)/2 + EXCLUDE1(sqb1,sqw2) - i8;
2201
                    }
2202
                    else if(x_piecePawn == pib2) {
2203
                        // 1 white, 1 black pawn
2204
                        return uInd*(INDEX)(i59*i47) +
2205
                               (EXCLUDE1(sqb2,sqw2)-i8)*i59 +
2206
                               EXCLUDE5(sqb1,sqb2,sqwk,sqw1,sqw2,sqbk);
2207
                    }
2208
                    else if(pib2 == pib1) {
2209
                        // only 1 white pawn, two identical black pieces
2210
                        SORT(sqb1, sqb2);
2211
                        sqb2 = EXCLUDE4(sqb2,sqwk,sqw1,sqw2,sqbk);
2212
                        return uInd*(INDEX)(i60*i59/2) +
2213
                               sqb2*(sqb2-1)/2 +
2214
                               EXCLUDE4(sqb1,sqwk,sqw1,sqw2,sqbk);
2215
                    }
2216
 
2217
                        // only 1 white pawn, two different black pieces
2218
                        return uInd*(INDEX)(i60*i59) +
2219
                               EXCLUDE4(sqb2,sqwk,sqw1,sqw2,sqbk)*i59 +
2220
                               EXCLUDE5(sqb1,sqb2,sqwk,sqw1,sqw2,sqbk);
2221
                    }
2222
                }
2223
                else if(x_piecePawn == pib1) {
2224
                    // no white pawns, two black pawns
2225
                    SORT(sqb1, sqb2);
2226
                    sqb2 -= i8;
2227
                    return uInd*(INDEX)(i48*i47/2) +
2228
                           sqb2*(sqb2-1)/2 + sqb1 - i8;
2229
 
2230
                else {
2231
                    // no white pawns, 1 black pawn
2232
                    return uInd*(INDEX)(i48*i59) +
2233
                           (sqb2 - i8)*i59 +
2234
                           EXCLUDE5(sqb1,sqb2,sqwk,sqw1,sqw2,sqbk);
2235
                }
2236
            }
2237
            else {
2238
                // En Passant possible
2239
                sqEnP ^= sqMask;
2240
                if(x_piecePawn == piw1) {
2241
                    // all 4 pieces are pawns
2242
 
2243
                    return uInd*(INDEX)(i46*i45/2) +
2244
                           IndHalfKings(sqwk,sqbk)*(i14*i44*i43) +
2245
                           IndEnPassant22W(sqw1, sqw2, sqb1, sqb2, sqEnP);
2246
                }
2247
                else {
2248
                    assert(x_piecePawn == piw2);
2249
2250
                    uInd = TEnumerate1<piw1, true, false>::
2251
                           Index(sqwk,sqw1,sqbk);
2252
 
2253
2254
                    if(x_piecePawn == pib1) {
2255
                        // 1 white pawn, 2 black pawns
2256
                        return rgcPairPawnPresent[piw1][x_piecePawn]*((INDEX)(i47*i46/2)) +
2257
                               (uInd*(i14*i44) +
2258
                                IndEnPassant12W(sqw2, sqb1, sqb2, sqEnP));
2259
                    }
2260
                    else {
2261
                        // 1 white pawn, 1 black pawn
2262
                        assert(x_piecePawn == pib2);
2263
                        return rgcPairPawnPresent[piw1][x_piecePawn]*((INDEX)(i47*i59))+
2264
                               (uInd*(i14*i57) +
2265
                                 EXCLUDE7(sqb1,sqb2,sqwk,sqw1,sqw2,sqbk,sqEnP,sqEnP+8)*i14+
2266
                                 IndEnPassant11W(sqw2,sqb2,sqEnP));
2267
                    }
2268
                }
2269
            }
2270
        }
2271
        else {
2272
            // no pawns at all
2273
            if (!FInTriangle (sqwk, sqbk)) {
2274
                sqwk = reflect_xy(sqwk);
2275
                sqw1 = reflect_xy(sqw1);
2276
                sqw2 = reflect_xy(sqw2);
2277
                sqbk = reflect_xy(sqbk);
2278
                sqb1 = reflect_xy(sqb1);
2279
                sqb2 = reflect_xy(sqb2);
2280
                }
2281
2282
            uInd = TEnumerate2<piw1,piw2,false,false>::Index(sqwk,sqw1,sqw2,sqbk);
2283
            CHECK_INF_PAIR(uInd);
2284
            if (pib1 == pib2) {
2285
                SORT (sqb1, sqb2);
2286
                sqb2 = EXCLUDE4(sqb2,sqwk,sqbk,sqw1,sqw2);
2287
                return  uInd*(i60*i59/2) +
2288
                        sqb2*(sqb2-1)/2+
2289
                        EXCLUDE4(sqb1,sqwk,sqbk,sqw1,sqw2);
2290
                }
2291
            else {
2292
                // Divide by 2 to avoid overflow on the 32-bit systems, later
2293
                // add to itself to produce the correct result. Only the final
2294
                // addition have to be done using 64-bit arithmetic.
2295
                uInd *= (i60*i59/2);
2296
                return  ((INDEX) uInd) +
2297
                          (INDEX) (uInd +
2298
                            EXCLUDE4(sqb1,sqwk,sqbk,sqw1,sqw2)*i59 +
2299
                            EXCLUDE5(sqb2,sqwk,sqbk,sqw1,sqw2,sqb1));
2300
                }
2301
            }
2302
    }
2303
2304
    static INDEX TB_FASTCALL IndCalcB
2305
        (
2306
        square  *psqW,
2307
        square  *psqB,
2308
 
2309
        int     fInvert
2310
        )
2311
    {
2312
        square   sqwk, sqw1, sqw2, sqbk, sqb1, sqb2, sqMask;
2313
        unsigned uInd;
2314
2315
        sqwk = SqFindKing (psqW);
2316
        if (piw1 == piw2) {
2317
            sqw1 = SqFindFirst  (psqW, piw1);
2318
 
2319
            }
2320
        else {
2321
            SqFind2 (psqW, piw1, sqw1, piw2, sqw2);
2322
            }
2323
        sqbk = SqFindKing (psqB);
2324
        if (pib1 == pib2) {
2325
            sqb1 = SqFindFirst  (psqB, pib1);
2326
            sqb2 = SqFindSecond (psqB, pib2);
2327
            }
2328
        else {
2329
            SqFind2 (psqB, pib1, sqb1, pib2, sqb2);
2330
            }
2331
 
2332
        if(piw2 == x_piecePawn || pib2 == x_piecePawn)
2333
            sqMask = rgsqReflectMaskY[sqbk] ^ rgsqReflectInvertMask[fInvert];
2334
        else
2335
            sqMask = rgsqReflectMaskYandX[sqbk];
2336
2337
        sqwk ^= sqMask;
2338
        sqw1 ^= sqMask;
2339
        sqw2 ^= sqMask;
2340
        sqbk ^= sqMask;
2341
 
2342
        sqb2 ^= sqMask;
2343
2344
        if(x_piecePawn == piw2 || x_piecePawn == pib2) {
2345
            // There are pawns on the board
2346
            if(XX == sqEnP) {
2347
                // No En Passant possible
2348
                uInd = TEnumerate2<pib1,pib2,true,true>::Index(sqbk,sqb1,sqb2,sqwk);
2349
                CHECK_INF_PAIR(uInd);
2350
                if(x_piecePawn == piw1) {
2351
                    // all 4 pieces are pawns
2352
                    SORT(sqw1, sqw2);
2353
                    sqw2 = EXCLUDE2(sqw2,sqb1,sqb2) - i8;
2354
                    return uInd*(INDEX)(i46*i45/2) +
2355
                           sqw2*(sqw2-1)/2 + EXCLUDE2(sqw1,sqb1,sqw2) - i8;
2356
                }
2357
                else if(x_piecePawn == piw2) {
2358
                    if(x_piecePawn == pib1) {
2359
                        // 1 white, 2 black pawns
2360
                        return uInd*(INDEX)(i46*i59) +
2361
                               (EXCLUDE2(sqw2,sqb1,sqb2)-i8)*i59 +
2362
                               EXCLUDE5(sqw1,sqw2,sqb1,sqb2,sqwk,sqbk);
2363
                    }
2364
                    else if(x_piecePawn == pib2) {
2365
                        // 1 white, 1 black pawn
2366
                        return uInd*(INDEX)(i47*i59) +
2367
                               (EXCLUDE1(sqw2,sqb2)-i8)*i59 +
2368
                               EXCLUDE5(sqw1,sqw2,sqb1,sqb2,sqwk,sqbk);
2369
                    }
2370
                    else {
2371
                        // only 1 white pawn
2372
                        return uInd*(INDEX)(i48*i59) +
2373
                               (sqw2 - i8)*i59 +
2374
                               EXCLUDE5(sqw1,sqw2,sqb1,sqb2,sqwk,sqbk);
2375
                    }
2376
                }
2377
                else if(piw1 == piw2) {
2378
                    // no white pawns, two identical white pieces
2379
                    SORT(sqw1, sqw2);
2380
                    sqw2 = EXCLUDE4(sqw2,sqb1,sqb2,sqwk,sqbk);
2381
                    return uInd*(INDEX)(i60*i59/2) +
2382
                           sqw2*(sqw2-1)/2 +
2383
                           EXCLUDE4(sqw1,sqb1,sqb2,sqwk,sqbk);
2384
                }
2385
                else {
2386
                    // no white pawns, two different white pieces
2387
                    return uInd*(INDEX)(i60*i59) +
2388
                           EXCLUDE4(sqw2,sqb1,sqb2,sqwk,sqbk)*i59 +
2389
                           EXCLUDE5(sqw1,sqw2,sqb1,sqb2,sqwk,sqbk);
2390
                }
2391
            }
2392
            else {
2393
                // En Passant possible
2394
                sqEnP ^= sqMask;
2395
                if(x_piecePawn == piw1) {
2396
                    // all 4 pieces are pawns
2397
                    uInd = rgcPairPawnPresent[x_piecePawn][x_piecePawn];
2398
                    return uInd*(INDEX)(i46*i45/2) +
2399
                           IndHalfKings(sqbk,sqwk)*(i14*i44*i43) +
2400
                           IndEnPassant22B(sqw1, sqw2, sqb1, sqb2, sqEnP);
2401
                }
2402
                else if(x_piecePawn == pib1) {
2403
                    // 1 white, 2 black pawns
2404
                    assert(x_piecePawn == piw2);
2405
                    uInd = rgcPairPawnPresent[x_piecePawn][x_piecePawn];
2406
                    return uInd*(INDEX)(i46*i59) +
2407
                           IndHalfKings(sqbk,sqwk)*(i14*i44*i57) +
2408
                           EXCLUDE7(sqw1,sqw2,sqb1,sqb2,sqbk,sqwk,sqEnP,sqEnP-8)*(i44*i14)+
2409
                           IndEnPassant12B(sqw2, sqb1, sqb2, sqEnP);
2410
                }
2411
                else {
2412
                    // 1 white, 1 black pawn
2413
                    assert(x_piecePawn == piw2 && x_piecePawn == pib2);
2414
                    uInd = TEnumerate1<pib1, true, true>::
2415
                           Index(sqbk,sqb1,sqwk);
2416
                    CHECK_INF_SINGLE(uInd);
2417
                    return rgcPairPawnPresent[pib1][x_piecePawn]*((INDEX)(i47*i59)) +
2418
                           (uInd*(i14*i57) +
2419
                            EXCLUDE7(sqw1,sqw2,sqb1,sqb2,sqwk,sqbk,sqEnP,sqEnP-8)*i14 +
2420
                            IndEnPassant11B(sqw2,sqb2,sqEnP));
2421
                }
2422
            }
2423
        }
2424
        else {
2425
            // no pawns at all
2426
            if (!FInTriangle (sqbk, sqwk)) {
2427
            sqwk = reflect_xy(sqwk);
2428
            sqw1 = reflect_xy(sqw1);
2429
            sqw2 = reflect_xy(sqw2);
2430
            sqbk = reflect_xy(sqbk);
2431
            sqb1 = reflect_xy(sqb1);
2432
            sqb2 = reflect_xy(sqb2);
2433
            }
2434
            uInd = TEnumerate2<pib1,pib2,false,false>::Index(sqbk,sqb1,sqb2,sqwk);
2435
            CHECK_INF_PAIR(uInd);
2436
            if (piw1 == piw2) {
2437
            SORT (sqw1, sqw2);
2438
                sqw2 = EXCLUDE4(sqw2,sqbk,sqwk,sqb1,sqb2);
2439
                return  uInd*(i60*i59/2) +
2440
                    sqw2*(sqw2-1)/2+
2441
                        EXCLUDE4(sqw1,sqbk,sqwk,sqb1,sqb2);
2442
            }
2443
            else {
2444
            // Divide by 2 to avoid overflow on the 32-bit systems, later
2445
            // add to itself to produce the correct result. Only the final
2446
                // addition have to be done using 64-bit arithmetic.
2447
                uInd *= (i60*i59/2);
2448
                return  ((INDEX) uInd) +
2449
 
2450
                          EXCLUDE4(sqw1,sqbk,sqwk,sqb1,sqb2)*i59 +
2451
 
2452
            }
2453
        }
2454
    }
2455
2456
    // IndCalcBF should replace IndCalcB for symmetric endgames
2457
2458
    static INDEX TB_FASTCALL IndCalcBF
2459
        (
2460
        square  *psqW,
2461
        square  *psqB,
2462
        square  sqEnP,
2463
        int fInvert
2464
 
2465
    {
2466
            return IndCalcW(psqB, psqW, sqEnP, !fInvert);
2467
    }
2468
};
2469
2470
#endif  // T33
2471
2472
#if defined (T42_INCLUDE)
2473
2474
// TODO: Add code for the TBs with pawns
2475
2476
template <int piw1, int piw2, int piw3, int pib1> class T42
2477
    {
2478
public:
2479
    static INDEX TB_FASTCALL IndCalcW
2480
        (
2481
        square  *psqW,
2482
        square  *psqB,
2483
        square  sqEnP,
2484
        int     fInvert
2485
        )
2486
        {
2487
        unsigned uInd;
2488
 
2489
2490
        sqwk = SqFindKing (psqW);
2491
        sqw1 = SqFindFirst (psqW, piw1);
2492
        if (piw1 == piw2 && piw2 == piw3)
2493
            {
2494
            sqw2 = SqFindSecond (psqW, piw2);
2495
            sqw3 = SqFindThird (psqW, piw3);
2496
            }
2497
        else if (piw1 == piw2)
2498
 
2499
            sqw2 = SqFindSecond (psqW, piw2);
2500
            sqw3 = SqFindFirst (psqW, piw3);
2501
            }
2502
        else if (piw2 == piw3)
2503
            {
2504
            sqw2 = SqFindFirst (psqW, piw2);
2505
            sqw3 = SqFindSecond (psqW, piw3);
2506
            }
2507
        else
2508
            {
2509
            sqw2 = SqFindFirst (psqW, piw2);
2510
            sqw3 = SqFindFirst (psqW, piw3);
2511
            }
2512
        sqbk = SqFindKing (psqB);
2513
 
2514
2515
        if (x_piecePawn == piw3 || x_piecePawn == pib1)
2516
            sqMask = rgsqReflectMaskY [sqwk] ^ rgsqReflectInvertMask [fInvert];
2517
        else
2518
            sqMask = rgsqReflectMaskYandX [sqwk];
2519
        sqwk ^= sqMask;
2520
        sqbk ^= sqMask;
2521
        sqw1 ^= sqMask;
2522
        sqw2 ^= sqMask;
2523
 
2524
        sqb1 ^= sqMask;
2525
2526
        if (x_piecePawn == piw3 || x_piecePawn == pib1)
2527
            {
2528
            // There are pawns on the board
2529
            if (x_piecePawn == pib1)
2530
                {
2531
                // Black pawn
2532
                if (x_piecePawn == piw1)
2533
                    {
2534
                    // All 4 pieces are pawns
2535
                    if (XX == sqEnP)
2536
                        {
2537
                        uInd = TEnumerate3<x_piecePawn,x_piecePawn,x_piecePawn,true,false>::
2538
                                Index(sqwk,sqw1,sqw2,sqw3,sqbk);
2539
                        CHECK_INF_TRIPLE(uInd);
2540
                        return uInd*i45 + EXCLUDE3(sqb1,sqw1,sqw2,sqw3)-i8; // 45
2541
                        }
2542
                    else
2543
                        {
2544
                        // En passant capture
2545
                        uInd = rgcTriplePawnPresent[x_piecePawn][x_piecePawn][x_piecePawn];
2546
                        return  uInd*i45 +
2547
 
2548
                                IndEnPassant31W (sqw1, sqw2, sqw3, sqb1, sqEnP ^ sqMask);
2549
                        }
2550
                    }
2551
                else if (x_piecePawn == piw2)
2552
                    {
2553
                    // Two white pawns, one black pawn
2554
                    if (XX == sqEnP)
2555
                        {
2556
                        uInd = TEnumerate3<piw1,x_piecePawn,x_piecePawn,true,false>::
2557
 
2558
                        CHECK_INF_TRIPLE(uInd);
2559
                        return uInd*(INDEX)i46 + (EXCLUDE2(sqb1,sqw2,sqw3)-i8);   // 46
2560
                        }
2561
                    else
2562
                        {
2563
                        // En passant capture
2564
                        uInd = TEnumerate1<piw1,true,false>::Index(sqwk,sqw1,sqbk);
2565
                        CHECK_INF_SINGLE(uInd);
2566
                        return  rgcTriplePawnPresent[piw1][x_piecePawn][x_piecePawn]*(INDEX)i46 +
2567
                                (uInd*(i14*i44) + IndEnPassant21W (sqw2, sqw3, sqb1, sqEnP ^ sqMask));
2568
                        }
2569
                    }
2570
                else if (x_piecePawn == piw3)
2571
                    {
2572
                    // One white pawn, one black pawn
2573
                    if (XX == sqEnP)
2574
                        {
2575
                        uInd = TEnumerate3<piw1,piw2,x_piecePawn,true,false>::
2576
                                Index(sqwk,sqw1,sqw2,sqw3,sqbk);
2577
                        CHECK_INF_TRIPLE(uInd);
2578
                        return  uInd*((INDEX)i47) + (EXCLUDE1(sqb1,sqw3)-i8);    // 47
2579
                        }
2580
                    else
2581
                        {
2582
                        // En passant capture
2583
                        uInd = TEnumerate2<piw1,piw2,true,false>::Index(sqwk,sqw1,sqw2,sqbk);
2584
                        CHECK_INF_PAIR(uInd);
2585
                        return  rgcTriplePawnPresent[piw1][piw2][x_piecePawn]*(INDEX)i47 +
2586
                                (uInd*i14 + IndEnPassant11W (sqw3, sqb1, sqEnP ^ sqMask));
2587
                        }
2588
                    }
2589
                else
2590
                    {
2591
                    // Only black pawn
2592
                    uInd = TEnumerate3<piw1,piw2,piw3,true,false>::
2593
                            Index(sqwk,sqw1,sqw2,sqw3,sqbk);
2594
                    CHECK_INF_TRIPLE(uInd);
2595
                    return  (uInd*3)*(INDEX)16 + (sqb1-i8); // 48
2596
                    }
2597
                }
2598
            else
2599
                {
2600
                // No black pawn
2601
                uInd = TEnumerate3<piw1,piw2,piw3,true,false>::
2602
                    Index(sqwk,sqw1,sqw2,sqw3,sqbk);
2603
                CHECK_INF_TRIPLE(uInd);
2604
                return uInd*(INDEX)i59 + EXCLUDE5(sqb1,sqwk,sqbk,sqw1,sqw2,sqw3);    // 59
2605
                }
2606
            }
2607
        else
2608
            {
2609
            // No pawns
2610
            if (!FInTriangle (sqwk, sqbk))
2611
                {
2612
                sqwk = reflect_xy(sqwk);
2613
                sqw1 = reflect_xy(sqw1);
2614
                sqw2 = reflect_xy(sqw2);
2615
                sqw3 = reflect_xy(sqw3);
2616
                sqbk = reflect_xy(sqbk);
2617
                sqb1 = reflect_xy(sqb1);
2618
                };
2619
            uInd = TEnumerate3<piw1,piw2,piw3,false,false>::Index(sqwk,sqw1,sqw2,sqw3,sqbk);
2620
            CHECK_INF_TRIPLE(uInd);
2621
            return uInd*(INDEX)i59 + EXCLUDE5(sqb1,sqwk,sqbk,sqw1,sqw2,sqw3);   // 59
2622
            }
2623
        }
2624
2625
    static INDEX TB_FASTCALL IndCalcB
2626
        (
2627
        square  *psqW,
2628
        square  *psqB,
2629
        square  sqEnP,
2630
        int     fInvert
2631
        )
2632
        {
2633
        unsigned uInd;
2634
        square sqwk, sqw1, sqw2, sqw3, sqbk, sqb1, sqMask, sqTemp;
2635
 
2636
        sqwk = SqFindKing (psqW);
2637
 
2638
        if (piw1 == piw2 && piw2 == piw3)
2639
 
2640
            sqw2 = SqFindSecond (psqW, piw2);
2641
            sqw3 = SqFindThird (psqW, piw3);
2642
            }
2643
 
2644
            {
2645
            sqw2 = SqFindSecond (psqW, piw2);
2646
            sqw3 = SqFindFirst (psqW, piw3);
2647
 
2648
        else if (piw2 == piw3)
2649
            {
2650
            sqw2 = SqFindFirst (psqW, piw2);
2651
 
2652
            }
2653
 
2654
            {
2655
            sqw2 = SqFindFirst (psqW, piw2);
2656
            sqw3 = SqFindFirst (psqW, piw3);
2657
 
2658
        sqbk = SqFindKing (psqB);
2659
 
2660
2661
 
2662
            sqMask = rgsqReflectMaskY [sqbk] ^ rgsqReflectInvertMask [fInvert];
2663
        else
2664
            sqMask = rgsqReflectMaskYandX [sqbk];
2665
        sqwk ^= sqMask;
2666
        sqbk ^= sqMask;
2667
        sqw1 ^= sqMask;
2668
        sqw2 ^= sqMask;
2669
        sqw3 ^= sqMask;
2670
        sqb1 ^= sqMask;
2671
2672
        if (x_piecePawn == piw3 || x_piecePawn == pib1)
2673
            {
2674
            // There are pawns on the board
2675
 
2676
                {
2677
                // Black pawn
2678
                if (x_piecePawn == piw1)
2679
                    {
2680
                    // All 4 pieces are pawns
2681
                    SORT (sqw1, sqw2);
2682
                    SORT (sqw2, sqw3);
2683
                    SORT (sqw1, sqw2);
2684
                    if (XX == sqEnP)
2685
                        {
2686
                        sqw3 = EXCLUDE1(sqw3,sqb1)-i8;                  // 47
2687
                        sqw2 = EXCLUDE1(sqw2,sqb1)-i8;                  // 47
2688
                        uInd = TEnumerate1<x_piecePawn,true,true>::Index(sqbk,sqb1,sqwk);
2689
                        CHECK_INF_SINGLE(uInd);
2690
                        return  uInd*(i47*i46*i45/6) +
2691
                                sqw3*(sqw3-1)*(sqw3-2)/6 +
2692
 
2693
                                EXCLUDE1(sqw1,sqb1)-i8; // 47*46*45/6
2694
                        }
2695
                    else
2696
                        // En passant capture
2697
 
2698
                                IndHalfKings(sqbk,sqwk)*(i44*i43/2*i14) +
2699
                                IndEnPassant31B (sqw1, sqw2, sqw3, sqb1, sqEnP ^ sqMask);
2700
                    }
2701
                else if (x_piecePawn == piw2)
2702
                    {
2703
                    // Two white pawns, one black pawn
2704
 
2705
                    if (XX == sqEnP)
2706
                        {
2707
                        sqTemp = EXCLUDE1(sqw3,sqb1)-i8;                    // 47
2708
                        uInd = TEnumerate1<x_piecePawn,true,true>::
2709
                                    Index(sqbk,sqb1,sqwk);
2710
                        CHECK_INF_SINGLE(uInd);
2711
                        return (uInd*(i59*i47)*(INDEX)(i46/2)) +
2712
                                (EXCLUDE5(sqw1,sqwk,sqbk,sqw2,sqw3,sqb1)*(i47*i46/2) +  // 59
2713
                                 sqTemp*(sqTemp-1)/2 +
2714
                                 EXCLUDE1(sqw2,sqb1)-i8);   // 47*46/2
2715
                        }
2716
                    else
2717
                        {
2718
                        // En passant capture
2719
                        sqEnP ^= sqMask;
2720
                        uInd = rgcSinglePawnPresent[x_piecePawn];
2721
                        return (uInd*(i59*i47))*(INDEX)(i46/2) +
2722
                                (IndHalfKings(sqbk,sqwk)*(i57*i44*i14) +
2723
                                 EXCLUDE7(sqw1,sqwk,sqbk,sqw2,sqw3,sqb1,sqEnP,sqEnP-8)*(i44*i14) +  // 57
2724
                                 IndEnPassant21B (sqw2, sqw3, sqb1, sqEnP));
2725
                        }
2726
                    }
2727
                else if (x_piecePawn == piw3)
2728
                    {
2729
                    // One white pawn, one black pawn
2730
                    if (piw1 == piw2)
2731
                        {
2732
                        // Two identical white pieces
2733
                        SORT (sqw1, sqw2);
2734
                        if (XX == sqEnP)
2735
                            {
2736
                            sqw2 = EXCLUDE4(sqw2,sqwk,sqbk,sqw3,sqb1);
2737
                            sqw1 = EXCLUDE4(sqw1,sqwk,sqbk,sqw3,sqb1);
2738
                            uInd = TEnumerate1<x_piecePawn,true,true>::Index(sqbk,sqb1,sqwk);
2739
                            CHECK_INF_SINGLE(uInd);
2740
                            return  (uInd*(i59*i47))*((INDEX)i60/2) +
2741
                                    ((sqw2*(sqw2-1)/2+sqw1)*i47 +   // 60*59/2
2742
                                     EXCLUDE1(sqw3,sqb1)-i8);           // 47
2743
                            }
2744
                        else
2745
                            {
2746
                            // En passant capture
2747
                            sqEnP ^= sqMask;
2748
                            sqw2 = EXCLUDE6(sqw2,sqwk,sqbk,sqw3,sqb1,sqEnP,sqEnP-8);
2749
                            sqw1 = EXCLUDE6(sqw1,sqwk,sqbk,sqw3,sqb1,sqEnP,sqEnP-8);
2750
                            uInd = rgcSinglePawnPresent[x_piecePawn];
2751
                            return  (uInd*(i59*i47))*((INDEX)i60/2) +
2752
                                    (IndHalfKings(sqbk,sqwk)*(i58*i57/2*i14) +
2753
                                     (sqw2*(sqw2-1)/2+sqw1)*i14 + // 58*57/2
2754
                                     IndEnPassant11B (sqw3, sqb1, sqEnP));
2755
                            }
2756
                        }
2757
                    else
2758
                        {
2759
                        // Two different white pieces
2760
                        if (XX == sqEnP)
2761
                            {
2762
                            uInd = TEnumerate1<x_piecePawn,true,true>::Index(sqbk,sqb1,sqwk);
2763
                            CHECK_INF_SINGLE(uInd);
2764
                            return  (uInd*(i59*i47))*((INDEX)i60) +
2765
                                    (EXCLUDE4(sqw1,sqwk,sqbk,sqw3,sqb1)*i59*i47 +   // 60
2766
                                     EXCLUDE5(sqw2,sqwk,sqbk,sqw1,sqw3,sqb1)*i47 +  // 59
2767
                                     EXCLUDE1(sqw3,sqb1)-i8);                       // 47
2768
                            }
2769
                        else
2770
                            {
2771
                            // En passant capture
2772
                            sqEnP ^= sqMask;
2773
 
2774
                            return  (uInd*(i59*i47))*((INDEX)i60) +
2775
                                    (IndHalfKings(sqbk,sqwk)*(i58*i57*i14) +
2776
                                     EXCLUDE6(sqw1,sqwk,sqbk,sqw3,sqb1,sqEnP,sqEnP-8)*(i57*i14) +   // 58
2777
 
2778
                                     IndEnPassant11B (sqw3, sqb1, sqEnP));
2779
                            }
2780
                        }
2781
                    }
2782
                else
2783
                    {
2784
                    // Only black pawn
2785
                    uInd = TEnumerate1<x_piecePawn,true,true>::Index(sqbk,sqb1,sqwk);
2786
                    CHECK_INF_SINGLE(uInd);
2787
                    if (piw1 == piw3)
2788
                        {
2789
                        // 3 identical white pieces
2790
                        SORT (sqw1, sqw2);
2791
                        SORT (sqw2, sqw3);
2792
                        SORT (sqw1, sqw2);
2793
                        sqw1 = EXCLUDE3(sqw1,sqwk,sqbk,sqb1);                       // 61
2794
                        sqw2 = EXCLUDE3(sqw2,sqwk,sqbk,sqb1);                       // 61
2795
                        sqw3 = EXCLUDE3(sqw3,sqwk,sqbk,sqb1);                       // 61
2796
                        return  uInd*(i61*i60*i59/6) +
2797
                                sqw3*(sqw3-1)*(sqw3-2)/6 + sqw2*(sqw2-1)/2 + sqw1;  // 61*60*59/6
2798
                        }
2799
                    else if (piw1 == piw2)
2800
                        {
2801
                        // 2 identical major white pieces
2802
                        SORT (sqw1, sqw2);
2803
                        sqw3 = EXCLUDE5(sqw3,sqwk,sqbk,sqw1,sqw2,sqb1);
2804
                        sqw1 = EXCLUDE3(sqw1,sqwk,sqbk,sqb1);               // 61
2805
 
2806
                        return  (uInd*(i61*i59))*(INDEX)(i60/2) +
2807
                                ((sqw2*(sqw2-1)/2 + sqw1)*i59 +             // 61*60/2
2808
                                 sqw3);                                     // 59
2809
                        }
2810
                    else if (piw2 == piw3)
2811
                        {
2812
                        // 2 identical minor white pieces
2813
                        SORT (sqw2, sqw3);
2814
                        sqw2 = EXCLUDE4(sqw2,sqwk,sqbk,sqw1,sqb1);              // 60
2815
                        sqw3 = EXCLUDE4(sqw3,sqwk,sqbk,sqw1,sqb1);              // 60
2816
                        return  (uInd*(i61*i59))*(INDEX)(i60/2) +
2817
                                (EXCLUDE3(sqw1,sqwk,sqbk,sqb1)*(i60*i59/2) +    // 61
2818
                                 sqw3*(sqw3-1)/2 + sqw2);                       // 60*59/2
2819
                        }
2820
                    else
2821
                        {
2822
                        // All 3 white pieces are different
2823
                        return  (uInd*(i61*i59))*(INDEX)i60 +
2824
                                (EXCLUDE3(sqw1,sqwk,sqbk,sqb1)*(i60*i59) +  // 61
2825
                                 EXCLUDE4(sqw2,sqwk,sqbk,sqw1,sqb1)*i59 +   // 60
2826
                                 EXCLUDE5(sqw3,sqwk,sqbk,sqw1,sqw2,sqb1));  // 59
2827
 
2828
                    }
2829
                }
2830
            else
2831
                {
2832
                // No black pawn
2833
                uInd = TEnumerate1<pib1,true,true>::Index(sqbk,sqb1,sqwk);
2834
                CHECK_INF_SINGLE(uInd);
2835
                if (x_piecePawn == piw1)
2836
                    {
2837
                    // Only 3 white pawns
2838
 
2839
                    SORT (sqw2, sqw3);
2840
                    SORT (sqw1, sqw2);
2841
                    sqw3 -= i8;
2842
                    sqw2 -= i8;
2843
                    return  uInd*(i48*47*i46/6) +
2844
                            sqw3*(sqw3-1)*(sqw3-2)/6+sqw2*(sqw2-1)/2+sqw1-i8;           // 48*47*46/6
2845
                    }
2846
                else if (x_piecePawn == piw2)
2847
                    {
2848
                    // 2 white pawns, one non-pawn
2849
                    SORT (sqw2, sqw3);
2850
                    sqTemp = sqw3 - i8;
2851
                    return  (uInd*(i59*47))*(INDEX)(i48/2) +
2852
                            (EXCLUDE5(sqw1,sqwk,sqbk,sqb1,sqw2,sqw3)*(i48*i47/2) +
2853
                             sqTemp*(sqTemp-1)/2+sqw2-i8);          // 48*47/2
2854
                    }
2855
 
2856
                    {
2857
                    // One white pawn, 2 identical white pieces
2858
                    SORT (sqw1, sqw2);
2859
                    sqw1 = EXCLUDE4(sqw1,sqwk,sqbk,sqb1,sqw3);
2860
 
2861
                    return  (uInd*(i60*i59/2))*(INDEX)i48 +
2862
                            ((sqw2*(sqw2-1)/2+sqw1)*i48 +   // 60*59/2
2863
                             sqw3-i8);                      // 48
2864
                    }
2865
                else
2866
                    {
2867
 
2868
                    return  (uInd*(i60*i59))*(INDEX)i48 +
2869
                            (EXCLUDE4(sqw1,sqwk,sqbk,sqb1,sqw3)*(i59*i48) + // 60
2870
                             EXCLUDE5(sqw2,sqwk,sqbk,sqb1,sqw1,sqw3)*i48 +  // 59
2871
                             sqw3-i8);                                      // 48
2872
                    }
2873
                }
2874
            }
2875
        else
2876
            {
2877
            // No pawns
2878
            if (!FInTriangle (sqbk, sqwk))
2879
                {
2880
                sqwk = reflect_xy(sqwk);
2881
                sqw1 = reflect_xy(sqw1);
2882
                sqw2 = reflect_xy(sqw2);
2883
                sqw3 = reflect_xy(sqw3);
2884
                sqbk = reflect_xy(sqbk);
2885
                sqb1 = reflect_xy(sqb1);
2886
                };
2887
            uInd = TEnumerate1<pib1,false,false>::Index(sqbk,sqb1,sqwk);
2888
            CHECK_INF_SINGLE(uInd);
2889
            if (piw1 == piw2 && piw2 == piw3)
2890
                {
2891
                // All 3 pieces equal
2892
                SORT (sqw1, sqw2);
2893
                SORT (sqw2, sqw3);
2894
                SORT (sqw1, sqw2);
2895
                sqw3 = EXCLUDE3(sqw3,sqwk,sqbk,sqb1);   // 61
2896
                sqw2 = EXCLUDE3(sqw2,sqwk,sqbk,sqb1);
2897
                return  uInd*(i61*i60*i59/6) +
2898
                        sqw3*(sqw3-1)*(sqw3-2)/6+
2899
                        sqw2*(sqw2-1)/2+
2900
                        EXCLUDE3(sqw1,sqwk,sqbk,sqb1);  // 61*60*59/6
2901
                }
2902
            else if (piw1 == piw2)
2903
                {
2904
                // 2 major pieces equal
2905
                SORT (sqw1, sqw2);
2906
                sqw2 = EXCLUDE4(sqw2,sqwk,sqbk,sqw3,sqb1);                          // 60
2907
                return uInd*(i60*i59/2*i61) +
2908
                        (sqw2*(sqw2-1)/2+EXCLUDE4(sqw1,sqwk,sqbk,sqw3,sqb1))*i61 +  // 60*59/2
2909
                        EXCLUDE3(sqw3,sqwk,sqbk,sqb1);                              // 61
2910
                }
2911
            else if (piw2 == piw3)
2912
                {
2913
                // 2 minor pieces equal
2914
                SORT (sqw2, sqw3);
2915
                sqw3 = EXCLUDE4(sqw3,sqwk,sqbk,sqw1,sqb1);                  // 60
2916
                return uInd*(i61*i60*i59/2) +
2917
                        EXCLUDE3(sqw1,sqwk,sqbk,sqb1)*(i60*i59/2) +         // 62
2918
                        sqw3*(sqw3-1)/2+EXCLUDE4(sqw2,sqwk,sqbk,sqw1,sqb1); // 60*59/2
2919
                }
2920
            else
2921
                {
2922
                uInd *= i61*i60*i59/2;
2923
                return (INDEX) uInd +
2924
                       (INDEX) (uInd +
2925
                                EXCLUDE3(sqw1,sqwk,sqbk,sqb1)*(i60*i59) +   // 61
2926
                                EXCLUDE4(sqw2,sqwk,sqbk,sqw1,sqb1)*i59 +    // 60
2927
                                EXCLUDE5(sqw3,sqwk,sqbk,sqw1,sqw2,sqb1));   // 59
2928
                }
2929
            }
2930
        }
2931
    };
2932
2933
#endif  // T42
2934
2935
#else   // Old SJE schema ------------------------------------------------------
2936
2937
/* scanning pattern: triangle encoding */
2938
2939
static const INDEX sptriv[] =
2940
    {
2941
     0,  1,  2,  3, -1, -1, -1, -1,
2942
    -1,  4,  5,  6, -1, -1, -1, -1,
2943
    -1, -1,  7,  8, -1, -1, -1, -1,
2944
    -1, -1, -1,  9, -1, -1, -1, -1,
2945
    -1, -1, -1, -1, -1, -1, -1, -1,
2946
    -1, -1, -1, -1, -1, -1, -1, -1,
2947
    -1, -1, -1, -1, -1, -1, -1, -1,
2948
    -1, -1, -1, -1, -1, -1, -1, -1,
2949
    };
2950
2951
/* scanning pattern: queenside flank encoding */
2952
2953
static const INDEX spqsfv[] =
2954
    {
2955
     0,  1,  2,  3, -1, -1, -1, -1,
2956
     4,  5,  6,  7, -1, -1, -1, -1,
2957
     8,  9, 10, 11, -1, -1, -1, -1,
2958
    12, 13, 14, 15, -1, -1, -1, -1,
2959
    16, 17, 18, 19, -1, -1, -1, -1,
2960
    20, 21, 22, 23, -1, -1, -1, -1,
2961
    24, 25, 26, 27, -1, -1, -1, -1,
2962
    28, 29, 30, 31, -1, -1, -1, -1,
2963
    };
2964
2965
/*--> CalcIndex3A: calculate index, mode 3A */
2966
INLINE INDEX CalcIndex3A
2967
    (
2968
    square sq0,
2969
    square sq1,
2970
    square sq2
2971
    )
2972
    {
2973
    INDEX index;
2974
2975
    if (TbRow(sq2) > x_row_4)
2976
        {
2977
        sq0 = reflect_x(sq0);
2978
        sq1 = reflect_x(sq1);
2979
 
2980
        };
2981
 
2982
    if (TbColumn(sq2) > x_column_d)
2983
        {
2984
        sq0 = reflect_y(sq0);
2985
        sq1 = reflect_y(sq1);
2986
        sq2 = reflect_y(sq2);
2987
        };
2988
2989
    if (TbRow(sq2) > TbColumn(sq2))
2990
        {
2991
        sq0 = reflect_xy(sq0);
2992
        sq1 = reflect_xy(sq1);
2993
 
2994
        };
2995
 
2996
    index =
2997
 
2998
        sq1 * i64 +
2999
 
3000
3001
    return (index);
3002
    }
3003
3004
/*--> CalcIndex3B: calculate index, mode 3B */
3005
INLINE INDEX CalcIndex3B
3006
    (
3007
    square sq0,
3008
    square sq1,
3009
    square sq2
3010
    )
3011
    {
3012
    INDEX index;
3013
 
3014
    if (TbColumn(sq1) > x_column_d)
3015
        {
3016
        sq0 = reflect_y(sq0);
3017
        sq1 = reflect_y(sq1);
3018
        sq2 = reflect_y(sq2);
3019
        };
3020
3021
    index =
3022
        sq0 +
3023
        spqsfv [sq1] * i64 +
3024
        sq2 * (i64 / 2) * i64;
3025
3026
    return (index);
3027
    }
3028
3029
/*--> CalcIndex4A: calculate index, mode 4A */
3030
INLINE INDEX CalcIndex4A
3031
    (
3032
    square sq0,
3033
    square sq1,
3034
    square sq2,
3035
    square sq3
3036
    )
3037
    {
3038
 
3039
3040
    if (TbRow(sq3) > x_row_4)
3041
        {
3042
        sq0 = reflect_x(sq0);
3043
        sq1 = reflect_x(sq1);
3044
        sq2 = reflect_x(sq2);
3045
        sq3 = reflect_x(sq3);
3046
        };
3047
3048
    if (TbColumn(sq3) > x_column_d)
3049
 
3050
        sq0 = reflect_y(sq0);
3051
        sq1 = reflect_y(sq1);
3052
        sq2 = reflect_y(sq2);
3053
        sq3 = reflect_y(sq3);
3054
        };
3055
3056
    if (TbRow(sq3) > TbColumn(sq3))
3057
        {
3058
        sq0 = reflect_xy(sq0);
3059
        sq1 = reflect_xy(sq1);
3060
        sq2 = reflect_xy(sq2);
3061
        sq3 = reflect_xy(sq3);
3062
        };
3063
3064
    index =
3065
        sq0 +
3066
        sq1 * i64 +
3067
        sq2 * i64 * i64 +
3068
        sptriv [sq3] * i64 * i64 * i64;
3069
3070
    return (index);
3071
    }
3072
3073
/*--> CalcIndex4B: calculate index, mode 4B */
3074
INLINE INDEX CalcIndex4B
3075
    (
3076
    square sq0,
3077
    square sq1,
3078
    square sq2,
3079
    square sq3
3080
    )
3081
    {
3082
    INDEX index;
3083
3084
    if (TbColumn(sq3) > x_column_d)
3085
        {
3086
        sq0 = reflect_y(sq0);
3087
        sq1 = reflect_y(sq1);
3088
        sq2 = reflect_y(sq2);
3089
        sq3 = reflect_y(sq3);
3090
        };
3091
3092
    index =
3093
        sq0 +
3094
        sq1 * i64 +
3095
        sq2 * i64 * i64 +
3096
        spqsfv [sq3] * i64 * i64 * i64;
3097
3098
    return (index);
3099
    }
3100
3101
/*--> CalcIndex4C: calculate index, mode 4C */
3102
INLINE INDEX CalcIndex4C
3103
    (
3104
    square sq0,
3105
    square sq1,
3106
    square sq2,
3107
    square sq3
3108
    )
3109
    {
3110
    INDEX index;
3111
3112
    if (TbColumn(sq2) > x_column_d)
3113
        {
3114
        sq0 = reflect_y(sq0);
3115
        sq1 = reflect_y(sq1);
3116
        sq2 = reflect_y(sq2);
3117
        sq3 = reflect_y(sq3);
3118
        };
3119
3120
    index =
3121
        sq0 +
3122
        sq1 * i64 +
3123
        spqsfv [sq2] * i64 * i64 +
3124
        sq3 * (i64 / 2) * i64 * i64;
3125
3126
    return (index);
3127
    }
3128
3129
/*--> CalcIndex5A: calculate index, mode 5A */
3130
INLINE INDEX CalcIndex5A
3131
    (
3132
    square sq0,
3133
    square sq1,
3134
    square sq2,
3135
    square sq3,
3136
    square sq4
3137
    )
3138
    {
3139
    INDEX index;
3140
3141
    if (TbRow(sq4) > x_row_4)
3142
        {
3143
        sq0 = reflect_x(sq0);
3144
        sq1 = reflect_x(sq1);
3145
        sq2 = reflect_x(sq2);
3146
        sq3 = reflect_x(sq3);
3147
        sq4 = reflect_x(sq4);
3148
 
3149
3150
    if (TbColumn(sq4) > x_column_d)
3151
        {
3152
        sq0 = reflect_y(sq0);
3153
        sq1 = reflect_y(sq1);
3154
        sq2 = reflect_y(sq2);
3155
        sq3 = reflect_y(sq3);
3156
        sq4 = reflect_y(sq4);
3157
        };
3158
3159
 
3160
        {
3161
        sq0 = reflect_xy(sq0);
3162
        sq1 = reflect_xy(sq1);
3163
        sq2 = reflect_xy(sq2);
3164
        sq3 = reflect_xy(sq3);
3165
        sq4 = reflect_xy(sq4);
3166
        };
3167
3168
    index =
3169
        sq0 +
3170
        sq1 * i64 +
3171
        sq2 * i64 * i64 +
3172
        sq3 * i64 * i64 * i64 +
3173
        sptriv [sq4] * i64 * i64 * i64 * i64;
3174
3175
    return (index);
3176
    }
3177
3178
/*--> CalcIndex5B: calculate index, mode 5B */
3179
INLINE INDEX CalcIndex5B
3180
    (
3181
    square sq0,
3182
    square sq1,
3183
    square sq2,
3184
 
3185
    square sq4
3186
    )
3187
    {
3188
    INDEX index;
3189
3190
    if (TbColumn(sq4) > x_column_d)
3191
        {
3192
        sq0 = reflect_y(sq0);
3193
        sq1 = reflect_y(sq1);
3194
        sq2 = reflect_y(sq2);
3195
 
3196
        sq4 = reflect_y(sq4);
3197
        };
3198
3199
    index =
3200
        sq0 +
3201
        sq1 * i64 +
3202
        sq2 * i64 * i64 +
3203
        sq3 * i64 * i64 * i64 +
3204
        spqsfv [sq4] * i64 * i64 * i64 * i64;
3205
3206
    return (index);
3207
    }
3208
3209
/*--> CalcIndex5C: calculate index, mode 5C */
3210
INLINE INDEX CalcIndex5C
3211
    (
3212
    square sq0,
3213
    square sq1,
3214
    square sq2,
3215
    square sq3,
3216
    square sq4
3217
    )
3218
    {
3219
    INDEX index;
3220
3221
    if (TbColumn(sq3) > x_column_d)
3222
        {
3223
        sq0 = reflect_y(sq0);
3224
        sq1 = reflect_y(sq1);
3225
        sq2 = reflect_y(sq2);
3226
        sq3 = reflect_y(sq3);
3227
        sq4 = reflect_y(sq4);
3228
        };
3229
3230
    index =
3231
        sq0 +
3232
        sq1 * i64 +
3233
        sq2 * i64 * i64 +
3234
        spqsfv [sq3] * i64 * i64 * i64 +
3235
        sq4 * (i64 / 2) * i64 * i64 * i64;
3236
3237
    return (index);
3238
    }
3239
3240
/*--> CalcIndex5D: calculate index, mode 5D */
3241
INLINE INDEX CalcIndex5D
3242
    (
3243
    square sq0,
3244
    square sq1,
3245
    square sq2,
3246
    square sq3,
3247
    square sq4
3248
    )
3249
    {
3250
    INDEX index;
3251
3252
    if (TbColumn(sq2) > x_column_d)
3253
        {
3254
        sq0 = reflect_y(sq0);
3255
        sq1 = reflect_y(sq1);
3256
        sq2 = reflect_y(sq2);
3257
        sq3 = reflect_y(sq3);
3258
        sq4 = reflect_y(sq4);
3259
        };
3260
3261
    index =
3262
        sq0 +
3263
        sq1 * i64 +
3264
        spqsfv [sq2] * i64 * i64 +
3265
        sq3 * (i64 / 2) * i64 * i64 +
3266
        sq4 * (i64 / 2) * i64 * i64 * i64;
3267
3268
    return (index);
3269
    }
3270
3271
// Calculate index - a lot of functions...
3272
3273
#define IndCalcW    IndCalc
3274
#define IndCalcB    IndCalc
3275
3276
template <int pi> class T21
3277
    {
3278
public:
3279
    static INDEX TB_FASTCALL IndCalc
3280
        (
3281
        square  *psqW,
3282
        square  *psqB,
3283
        square  sqEnP,
3284
        int     fInvert
3285
        )
3286
        {
3287
        square sq0, sq1, sq2;
3288
3289
        sq0 = SqFindKing (psqW);
3290
        sq1 = SqFindOne  (psqW, pi);
3291
        sq2 = SqFindKing (psqB);
3292
3293
        if (x_piecePawn == pi)
3294
            {
3295
            if (fInvert)
3296
                {
3297
                sq0 = reflect_x (sq0);
3298
                sq1 = reflect_x (sq1);
3299
                sq2 = reflect_x (sq2);
3300
                }
3301
            return CalcIndex3B (sq0, sq1, sq2);
3302
            }
3303
        else
3304
            return CalcIndex3A (sq0, sq1, sq2);
3305
        }
3306
    };
3307
3308
template <int pi1, int pi2> class T22
3309
    {
3310
public:
3311
    static INDEX TB_FASTCALL IndCalc
3312
        (
3313
        square  *psqW,
3314
        square  *psqB,
3315
        square  sqEnP,
3316
        int     fInvert
3317
        )
3318
        {
3319
        square sq0, sq1, sq2, sq3;
3320
3321
        sq0 = SqFindKing (psqW);
3322
        sq1 = SqFindOne  (psqW, pi1);
3323
        sq2 = SqFindKing (psqB);
3324
        sq3 = SqFindOne  (psqB, pi2);
3325
3326
        if (x_piecePawn == pi1 || x_piecePawn == pi2)
3327
            {
3328
            if (fInvert)
3329
                {
3330
                sq0 = reflect_x (sq0);
3331
                sq1 = reflect_x (sq1);
3332
                sq2 = reflect_x (sq2);
3333
                sq3 = reflect_x (sq3);
3334
                }
3335
            return CalcIndex4B (sq0, sq1, sq2, sq3);
3336
            }
3337
        else
3338
            return CalcIndex4A (sq0, sq1, sq2, sq3);
3339
        }
3340
    };
3341
3342
template <int pi1, int pi2> class T31
3343
    {
3344
public:
3345
    static INDEX TB_FASTCALL IndCalc
3346
        (
3347
        square  *psqW,
3348
        square  *psqB,
3349
        square  sqEnP,
3350
        int     fInvert
3351
        )
3352
        {
3353
        square sq0, sq1, sq2, sq3;
3354
3355
        sq0 = SqFindKing (psqW);
3356
        sq1 = SqFindFirst (psqW, pi1);
3357
        if (pi1 == pi2)
3358
            sq2 = SqFindSecond (psqW, pi2);
3359
        else
3360
            sq2 = SqFindFirst (psqW, pi2);
3361
        sq3 = SqFindKing (psqB);
3362
3363
        if (x_piecePawn == pi1 || x_piecePawn == pi2)
3364
            {
3365
            if (fInvert)
3366
                {
3367
                sq0 = reflect_x (sq0);
3368
                sq1 = reflect_x (sq1);
3369
                sq2 = reflect_x (sq2);
3370
                sq3 = reflect_x (sq3);
3371
                }
3372
            return CalcIndex4C (sq0, sq1, sq2, sq3);
3373
            }
3374
        else
3375
            return CalcIndex4A (sq0, sq1, sq2, sq3);
3376
        }
3377
    };
3378
3379
template <int pi1, int pi2, int pi3> class T32
3380
    {
3381
public:
3382
    static INDEX TB_FASTCALL IndCalc
3383
        (
3384
        square  *psqW,
3385
        square  *psqB,
3386
        square  sqEnP,
3387
        int     fInvert
3388
        )
3389
        {
3390
        square sq0, sq1, sq2, sq3, sq4;
3391
3392
        sq0 = SqFindKing (psqW);
3393
        sq1 = SqFindFirst (psqW, pi1);
3394
        if (pi1 == pi2)
3395
            sq2 = SqFindSecond (psqW, pi2);
3396
        else
3397
            sq2 = SqFindFirst (psqW, pi2);
3398
        sq3 = SqFindKing (psqB);
3399
        sq4 = SqFindOne  (psqB, pi3);
3400
3401
        if (x_piecePawn == pi1 || x_piecePawn == pi2 || x_piecePawn == pi3)
3402
            {
3403
            if (fInvert)
3404
                {
3405
                sq0 = reflect_x (sq0);
3406
                sq1 = reflect_x (sq1);
3407
                sq2 = reflect_x (sq2);
3408
                sq3 = reflect_x (sq3);
3409
                sq4 = reflect_x (sq4);
3410
                }
3411
            if (x_piecePawn == pi3)
3412
                return CalcIndex5B (sq0, sq1, sq2, sq3, sq4);
3413
            else
3414
                return CalcIndex5D (sq0, sq1, sq2, sq3, sq4);
3415
            }
3416
        else
3417
            return CalcIndex5A (sq0, sq1, sq2, sq3, sq4);
3418
        }
3419
    };
3420
3421
#if defined (T41_INCLUDE)
3422
3423
template <int pi1, int pi2, int pi3> class T41
3424
    {
3425
public:
3426
    static INDEX TB_FASTCALL IndCalc
3427
        (
3428
        square  *psqW,
3429
        square  *psqB,
3430
        square  sqEnP,
3431
        int     fInvert
3432
        )
3433
        {
3434
        square sq0, sq1, sq2, sq3, sq4;
3435
3436
        sq0 = SqFindKing (psqW);
3437
        sq1 = SqFindFirst (psqW, pi1);
3438
        sq2 = SqFindFirst (psqW, pi2);
3439
        sq3 = SqFindFirst (psqW, pi3);
3440
        sq4 = SqFindKing (psqB);
3441
3442
        if (x_piecePawn == pi1 || x_piecePawn == pi2 || x_piecePawn == pi3)
3443
            {
3444
            // There are pawns on the board
3445
            if (fInvert)
3446
                {
3447
                sq0 = reflect_x (sq0);
3448
                sq1 = reflect_x (sq1);
3449
                sq2 = reflect_x (sq2);
3450
                sq3 = reflect_x (sq3);
3451
                sq4 = reflect_x (sq4);
3452
                }
3453
            return CalcIndex5C (sq0, sq1, sq2, sq3, sq4);
3454
            }
3455
        else    // No pawns
3456
 
3457
        }
3458
 
3459
3460
 
3461
3462
 
3463
3464
// All tablebases enumerated
3465
3466
#define tbid_kk      0
3467
#define tbid_kpk     1
3468
#define tbid_knk     2
3469
#define tbid_kbk     3
3470
#define tbid_krk     4
3471
#define tbid_kqk     5
3472
#define tbid_kpkp    6
3473
#define tbid_knkp    7
3474
 
3475
#define tbid_kbkp    9
3476
 
3477
#define tbid_kbkb   11
3478
#define tbid_krkp   12
3479
#define tbid_krkn   13
3480
#define tbid_krkb   14
3481
#define tbid_krkr   15
3482
#define tbid_kqkp   16
3483
#define tbid_kqkn   17
3484
#define tbid_kqkb   18
3485
#define tbid_kqkr   19
3486
#define tbid_kqkq   20
3487
#define tbid_kppk   21
3488
 
3489
#define tbid_knnk   23
3490
#define tbid_kbpk   24
3491
#define tbid_kbnk   25
3492
#define tbid_kbbk   26
3493
#define tbid_krpk   27
3494
#define tbid_krnk   28
3495
#define tbid_krbk   29
3496
#define tbid_krrk   30
3497
#define tbid_kqpk   31
3498
 
3499
#define tbid_kqbk   33
3500
#define tbid_kqrk   34
3501
#define tbid_kqqk   35
3502
#define tbid_kppkp  36
3503
#define tbid_kppkn  37
3504
#define tbid_kppkb  38
3505
 
3506
#define tbid_kppkq  40
3507
#define tbid_knpkp  41
3508
#define tbid_knpkn  42
3509
#define tbid_knpkb  43
3510
#define tbid_knpkr  44
3511
#define tbid_knpkq  45
3512
 
3513
#define tbid_knnkn  47
3514
#define tbid_knnkb  48
3515
#define tbid_knnkr  49
3516
#define tbid_knnkq  50
3517
#define tbid_kbpkp  51
3518
#define tbid_kbpkn  52
3519
 
3520
#define tbid_kbpkr  54
3521
#define tbid_kbpkq  55
3522
#define tbid_kbnkp  56
3523
#define tbid_kbnkn  57
3524
 
3525
#define tbid_kbnkr  59
3526
#define tbid_kbnkq  60
3527
 
3528
#define tbid_kbbkn  62
3529
#define tbid_kbbkb  63
3530
#define tbid_kbbkr  64
3531
#define tbid_kbbkq  65
3532
#define tbid_krpkp  66
3533
#define tbid_krpkn  67
3534
#define tbid_krpkb  68
3535
#define tbid_krpkr  69
3536
#define tbid_krpkq  70
3537
 
3538
#define tbid_krnkn  72
3539
#define tbid_krnkb  73
3540
#define tbid_krnkr  74
3541
#define tbid_krnkq  75
3542
#define tbid_krbkp  76
3543
#define tbid_krbkn  77
3544
 
3545
#define tbid_krbkr  79
3546
#define tbid_krbkq  80
3547
#define tbid_krrkp  81
3548
#define tbid_krrkn  82
3549
 
3550
#define tbid_krrkr  84
3551
#define tbid_krrkq  85
3552
 
3553
#define tbid_kqpkn  87
3554
#define tbid_kqpkb  88
3555
#define tbid_kqpkr  89
3556
#define tbid_kqpkq  90
3557
#define tbid_kqnkp  91
3558
#define tbid_kqnkn  92
3559
#define tbid_kqnkb  93
3560
#define tbid_kqnkr  94
3561
#define tbid_kqnkq  95
3562
#define tbid_kqbkp  96
3563
 
3564
#define tbid_kqbkb  98
3565
#define tbid_kqbkr  99
3566
#define tbid_kqbkq 100
3567
#define tbid_kqrkp 101
3568
#define tbid_kqrkn 102
3569
#define tbid_kqrkb 103
3570
#define tbid_kqrkr 104
3571
 
3572
#define tbid_kqqkp 106
3573
#define tbid_kqqkn 107
3574
#define tbid_kqqkb 108
3575
#define tbid_kqqkr 109
3576
#define tbid_kqqkq 110
3577
3578
#if defined (T41_INCLUDE)
3579
 
3580
#  define tbid_knppk    112
3581
#  define tbid_knnpk    113
3582
#  define tbid_knnnk    114
3583
#  define tbid_kbppk    115
3584
#  define tbid_kbnpk    116
3585
#  define tbid_kbnnk    117
3586
#  define tbid_kbbpk    118
3587
 
3588
#  define tbid_kbbbk    120
3589
#  define tbid_krppk    121
3590
#  define tbid_krnpk    122
3591
#  define tbid_krnnk    123
3592
#  define tbid_krbpk    124
3593
 
3594
#  define tbid_krbbk    126
3595
#  define tbid_krrpk    127
3596
 
3597
#  define tbid_krrbk    129
3598
#  define tbid_krrrk    130
3599
#  define tbid_kqppk    131
3600
#  define tbid_kqnpk    132
3601
#  define tbid_kqnnk    133
3602
#  define tbid_kqbpk    134
3603
#  define tbid_kqbnk    135
3604
#  define tbid_kqbbk    136
3605
#  define tbid_kqrpk    137
3606
#  define tbid_kqrnk    138
3607
 
3608
#  define tbid_kqrrk    140
3609
#  define tbid_kqqpk    141
3610
#  define tbid_kqqnk    142
3611
#  define tbid_kqqbk    143
3612
#  define tbid_kqqrk    144
3613
#  define tbid_kqqqk    145
3614
#endif
3615
 
3616
#if defined (T33_INCLUDE)
3617
#  if defined (T41_INCLUDE)
3618
#    define BASE_33 145
3619
#  else
3620
#    define BASE_33 110
3621
 
3622
#  define tbid_knnknn   (BASE_33 + 1)
3623
#  define tbid_kbnknn   (BASE_33 + 2)
3624
 
3625
#  define tbid_kbbkbn   (BASE_33 + 4)
3626
#  define tbid_kbbkbb   (BASE_33 + 5)
3627
#  define tbid_krnknn   (BASE_33 + 6)
3628
#  define tbid_krnkbb   (BASE_33 + 7)
3629
#  define tbid_krbknn   (BASE_33 + 8)
3630
#  define tbid_krbkbb   (BASE_33 + 9)
3631
#  define tbid_krrknn   (BASE_33 + 10)
3632
#  define tbid_krrkbn   (BASE_33 + 11)
3633
#  define tbid_krrkbb   (BASE_33 + 12)
3634
#  define tbid_krrkrn   (BASE_33 + 13)
3635
 
3636
#  define tbid_krrkrr   (BASE_33 + 15)
3637
#  define tbid_kqnknn   (BASE_33 + 16)
3638
#  define tbid_kqnkbb   (BASE_33 + 17)
3639
#  define tbid_kqnkrr   (BASE_33 + 18)
3640
#  define tbid_kqbknn   (BASE_33 + 19)
3641
#  define tbid_kqbkbb   (BASE_33 + 20)
3642
#  define tbid_kqbkrr   (BASE_33 + 21)
3643
 
3644
#  define tbid_kqrkbb   (BASE_33 + 23)
3645
#  define tbid_kqrkrr   (BASE_33 + 24)
3646
#  define tbid_kqqknn   (BASE_33 + 25)
3647
#  define tbid_kqqkbn   (BASE_33 + 26)
3648
#  define tbid_kqqkbb   (BASE_33 + 27)
3649
 
3650
#  define tbid_kqqkrb   (BASE_33 + 29)
3651
#  define tbid_kqqkrr   (BASE_33 + 30)
3652
 
3653
#  define tbid_kqqkqb   (BASE_33 + 32)
3654
#  define tbid_kqqkqr   (BASE_33 + 33)
3655
#  define tbid_kqqkqq   (BASE_33 + 34)
3656
#  if defined (T_INDEX64)
3657
#    define tbid_kbnkbn (BASE_33 + 35)
3658
#    define tbid_krnkrn (BASE_33 + 36)
3659
#    define tbid_krbkrb (BASE_33 + 37)
3660
#    define tbid_kqnkqn (BASE_33 + 38)
3661
#    define tbid_kqbkqb (BASE_33 + 39)
3662
#    define tbid_kqrkqr (BASE_33 + 40)
3663
#    define tbid_krnkbn (BASE_33 + 41)
3664
 
3665
#    define tbid_krbkrn (BASE_33 + 43)
3666
#    define tbid_kqnkbn (BASE_33 + 44)
3667
#    define tbid_kqnkrn (BASE_33 + 45)
3668
#    define tbid_kqnkrb (BASE_33 + 46)
3669
#    define tbid_kqbkbn (BASE_33 + 47)
3670
#    define tbid_kqbkrn (BASE_33 + 48)
3671
#    define tbid_kqbkrb (BASE_33 + 49)
3672
#    define tbid_kqbkqn (BASE_33 + 50)
3673
 
3674
#    define tbid_kqrkrn (BASE_33 + 52)
3675
#    define tbid_kqrkrb (BASE_33 + 53)
3676
#    define tbid_kqrkqn (BASE_33 + 54)
3677
#    define tbid_kqrkqb (BASE_33 + 55)
3678
#    define tbid_kppkpp (BASE_33 + 56)
3679
#    define tbid_knpkpp (BASE_33 + 57)
3680
#    define tbid_knpknp (BASE_33 + 58)
3681
#    define tbid_knnkpp (BASE_33 + 59)
3682
 
3683
#    define tbid_kbpkpp (BASE_33 + 61)
3684
#    define tbid_kbpknp (BASE_33 + 62)
3685
#    define tbid_kbpknn (BASE_33 + 63)
3686
#    define tbid_kbpkbp (BASE_33 + 64)
3687
#    define tbid_kbnkpp (BASE_33 + 65)
3688
#    define tbid_kbnknp (BASE_33 + 66)
3689
#    define tbid_kbnkbp (BASE_33 + 67)
3690
#    define tbid_kbbkpp (BASE_33 + 68)
3691
 
3692
#    define tbid_kbbkbp (BASE_33 + 70)
3693
#    define tbid_krpkpp (BASE_33 + 71)
3694
#    define tbid_krpknp (BASE_33 + 72)
3695
#    define tbid_krpknn (BASE_33 + 73)
3696
#    define tbid_krpkbp (BASE_33 + 74)
3697
#    define tbid_krpkbn (BASE_33 + 75)
3698
 
3699
#    define tbid_krpkrp (BASE_33 + 77)
3700
#    define tbid_krnkpp (BASE_33 + 78)
3701
 
3702
#    define tbid_krnkbp (BASE_33 + 80)
3703
#    define tbid_krnkrp (BASE_33 + 81)
3704
#    define tbid_krbkpp (BASE_33 + 82)
3705
#    define tbid_krbknp (BASE_33 + 83)
3706
#    define tbid_krbkbp (BASE_33 + 84)
3707
#    define tbid_krbkrp (BASE_33 + 85)
3708
#    define tbid_krrkpp (BASE_33 + 86)
3709
#    define tbid_krrknp (BASE_33 + 87)
3710
#    define tbid_krrkbp (BASE_33 + 88)
3711
#    define tbid_krrkrp (BASE_33 + 89)
3712
#    define tbid_kqpkpp (BASE_33 + 90)
3713
 
3714
#    define tbid_kqpknn (BASE_33 + 92)
3715
#    define tbid_kqpkbp (BASE_33 + 93)
3716
#    define tbid_kqpkbn (BASE_33 + 94)
3717
#    define tbid_kqpkbb (BASE_33 + 95)
3718
#    define tbid_kqpkrp (BASE_33 + 96)
3719
#    define tbid_kqpkrn (BASE_33 + 97)
3720
#    define tbid_kqpkrb (BASE_33 + 98)
3721
#    define tbid_kqpkrr (BASE_33 + 99)
3722
 
3723
#    define tbid_kqnkpp (BASE_33 + 101)
3724
#    define tbid_kqnknp (BASE_33 + 102)
3725
#    define tbid_kqnkbp (BASE_33 + 103)
3726
#    define tbid_kqnkrp (BASE_33 + 104)
3727
#    define tbid_kqnkqp (BASE_33 + 105)
3728
#    define tbid_kqbkpp (BASE_33 + 106)
3729
 
3730
#    define tbid_kqbkbp (BASE_33 + 108)
3731
#    define tbid_kqbkrp (BASE_33 + 109)
3732
 
3733
#    define tbid_kqrkpp (BASE_33 + 111)
3734
#    define tbid_kqrknp (BASE_33 + 112)
3735
#    define tbid_kqrkbp (BASE_33 + 113)
3736
#    define tbid_kqrkrp (BASE_33 + 114)
3737
#    define tbid_kqrkqp (BASE_33 + 115)
3738
#    define tbid_kqqkpp (BASE_33 + 116)
3739
#    define tbid_kqqknp (BASE_33 + 117)
3740
#    define tbid_kqqkbp (BASE_33 + 118)
3741
#    define tbid_kqqkrp (BASE_33 + 119)
3742
#    define tbid_kqqkqp (BASE_33 + 120)
3743
#    define C33 (tbid_kqqkqp - BASE_33)
3744
 
3745
#    define C33 (tbid_kqqkqq - BASE_33)
3746
#  endif
3747
#else
3748
#  define C33   0
3749
#endif
3750
3751
#if defined (T41_INCLUDE)
3752
#  define BASE_42   (145 + C33)
3753
 
3754
#  define BASE_42   (110 + C33)
3755
#endif
3756
3757
#if defined (T42_INCLUDE)
3758
#  define tbid_knnnkn   (BASE_42 + 1)
3759
#  define tbid_kbnnkn   (BASE_42 + 2)
3760
 
3761
#  define tbid_kbbbkn   (BASE_42 + 4)
3762
#  define tbid_krnnkn   (BASE_42 + 5)
3763
 
3764
#  define tbid_krrnkn   (BASE_42 + 7)
3765
#  define tbid_krrbkn   (BASE_42 + 8)
3766
#  define tbid_krrrkn   (BASE_42 + 9)
3767
#  define tbid_kqnnkn   (BASE_42 + 10)
3768
#  define tbid_kqbbkn   (BASE_42 + 11)
3769
#  define tbid_kqrrkn   (BASE_42 + 12)
3770
#  define tbid_kqqnkn   (BASE_42 + 13)
3771
#  define tbid_kqqbkn   (BASE_42 + 14)
3772
#  define tbid_kqqrkn   (BASE_42 + 15)
3773
#  define tbid_kqqqkn   (BASE_42 + 16)
3774
#  define tbid_knnnkb   (BASE_42 + 17)
3775
 
3776
#  define tbid_kbbnkb   (BASE_42 + 19)
3777
#  define tbid_kbbbkb   (BASE_42 + 20)
3778
#  define tbid_krnnkb   (BASE_42 + 21)
3779
#  define tbid_krbbkb   (BASE_42 + 22)
3780
#  define tbid_krrnkb   (BASE_42 + 23)
3781
#  define tbid_krrbkb   (BASE_42 + 24)
3782
#  define tbid_krrrkb   (BASE_42 + 25)
3783
#  define tbid_kqnnkb   (BASE_42 + 26)
3784
 
3785
#  define tbid_kqrrkb   (BASE_42 + 28)
3786
#  define tbid_kqqnkb   (BASE_42 + 29)
3787
#  define tbid_kqqbkb   (BASE_42 + 30)
3788
#  define tbid_kqqrkb   (BASE_42 + 31)
3789
#  define tbid_kqqqkb   (BASE_42 + 32)
3790
#  define tbid_knnnkr   (BASE_42 + 33)
3791
 
3792
#  define tbid_kbbnkr   (BASE_42 + 35)
3793
#  define tbid_kbbbkr   (BASE_42 + 36)
3794
 
3795
#  define tbid_krbbkr   (BASE_42 + 38)
3796
 
3797
#  define tbid_krrbkr   (BASE_42 + 40)
3798
#  define tbid_krrrkr   (BASE_42 + 41)
3799
 
3800
#  define tbid_kqbbkr   (BASE_42 + 43)
3801
#  define tbid_kqrrkr   (BASE_42 + 44)
3802
#  define tbid_kqqnkr   (BASE_42 + 45)
3803
#  define tbid_kqqbkr   (BASE_42 + 46)
3804
#  define tbid_kqqrkr   (BASE_42 + 47)
3805
#  define tbid_kqqqkr   (BASE_42 + 48)
3806
#  define tbid_knnnkq   (BASE_42 + 49)
3807
#  define tbid_kbnnkq   (BASE_42 + 50)
3808
#  define tbid_kbbnkq   (BASE_42 + 51)
3809
#  define tbid_kbbbkq   (BASE_42 + 52)
3810
#  define tbid_krnnkq   (BASE_42 + 53)
3811
#  define tbid_krbbkq   (BASE_42 + 54)
3812
 
3813
#  define tbid_krrbkq   (BASE_42 + 56)
3814
#  define tbid_krrrkq   (BASE_42 + 57)
3815
#  define tbid_kqnnkq   (BASE_42 + 58)
3816
 
3817
#  define tbid_kqrrkq   (BASE_42 + 60)
3818
#  define tbid_kqqnkq   (BASE_42 + 61)
3819
#  define tbid_kqqbkq   (BASE_42 + 62)
3820
#  define tbid_kqqrkq   (BASE_42 + 63)
3821
#  define tbid_kqqqkq   (BASE_42 + 64)
3822
#  if defined (T_INDEX64)
3823
#    define tbid_krbnkn (BASE_42 + 65)
3824
#    define tbid_kqbnkn (BASE_42 + 66)
3825
#    define tbid_kqrnkn (BASE_42 + 67)
3826
#    define tbid_kqrbkn (BASE_42 + 68)
3827
#    define tbid_krbnkb (BASE_42 + 69)
3828
#    define tbid_kqbnkb (BASE_42 + 70)
3829
#    define tbid_kqrnkb (BASE_42 + 71)
3830
#    define tbid_kqrbkb (BASE_42 + 72)
3831
 
3832
#    define tbid_kqbnkr (BASE_42 + 74)
3833
#    define tbid_kqrnkr (BASE_42 + 75)
3834
#    define tbid_kqrbkr (BASE_42 + 76)
3835
#    define tbid_krbnkq (BASE_42 + 77)
3836
#    define tbid_kqbnkq (BASE_42 + 78)
3837
#    define tbid_kqrnkq (BASE_42 + 79)
3838
#    define tbid_kqrbkq (BASE_42 + 80)
3839
3840
#    define tbid_kpppkp (BASE_42 + 81)
3841
#    define tbid_knppkp (BASE_42 + 82)
3842
#    define tbid_knnpkp (BASE_42 + 83)
3843
#    define tbid_knnnkp (BASE_42 + 84)
3844
 
3845
#    define tbid_kbnpkp (BASE_42 + 86)
3846
#    define tbid_kbnnkp (BASE_42 + 87)
3847
#    define tbid_kbbpkp (BASE_42 + 88)
3848
#    define tbid_kbbnkp (BASE_42 + 89)
3849
 
3850
#    define tbid_krppkp (BASE_42 + 91)
3851
#    define tbid_krnpkp (BASE_42 + 92)
3852
#    define tbid_krnnkp (BASE_42 + 93)
3853
#    define tbid_krbpkp (BASE_42 + 94)
3854
#    define tbid_krbnkp (BASE_42 + 95)
3855
#    define tbid_krbbkp (BASE_42 + 96)
3856
#    define tbid_krrpkp (BASE_42 + 97)
3857
#    define tbid_krrnkp (BASE_42 + 98)
3858
#    define tbid_krrbkp (BASE_42 + 99)
3859
#    define tbid_krrrkp (BASE_42 + 100)
3860
#    define tbid_kqppkp (BASE_42 + 101)
3861
#    define tbid_kqnpkp (BASE_42 + 102)
3862
#    define tbid_kqnnkp (BASE_42 + 103)
3863
#    define tbid_kqbpkp (BASE_42 + 104)
3864
#    define tbid_kqbnkp (BASE_42 + 105)
3865
 
3866
#    define tbid_kqrpkp (BASE_42 + 107)
3867
#    define tbid_kqrnkp (BASE_42 + 108)
3868
#    define tbid_kqrbkp (BASE_42 + 109)
3869
#    define tbid_kqrrkp (BASE_42 + 110)
3870
#    define tbid_kqqpkp (BASE_42 + 111)
3871
#    define tbid_kqqnkp (BASE_42 + 112)
3872
#    define tbid_kqqbkp (BASE_42 + 113)
3873
#    define tbid_kqqrkp (BASE_42 + 114)
3874
#    define tbid_kqqqkp (BASE_42 + 115)
3875
#    define tbid_kpppkn (BASE_42 + 116)
3876
#    define tbid_knppkn (BASE_42 + 117)
3877
#    define tbid_knnpkn (BASE_42 + 118)
3878
 
3879
#    define tbid_kbnpkn (BASE_42 + 120)
3880
#    define tbid_kbbpkn (BASE_42 + 121)
3881
#    define tbid_krppkn (BASE_42 + 122)
3882
#    define tbid_krnpkn (BASE_42 + 123)
3883
#    define tbid_krbpkn (BASE_42 + 124)
3884
#    define tbid_krrpkn (BASE_42 + 125)
3885
#    define tbid_kqppkn (BASE_42 + 126)
3886
 
3887
#    define tbid_kqbpkn (BASE_42 + 128)
3888
#    define tbid_kqrpkn (BASE_42 + 129)
3889
#    define tbid_kqqpkn (BASE_42 + 130)
3890
#    define tbid_kpppkb (BASE_42 + 131)
3891
#    define tbid_knppkb (BASE_42 + 132)
3892
#    define tbid_knnpkb (BASE_42 + 133)
3893
#    define tbid_kbppkb (BASE_42 + 134)
3894
#    define tbid_kbnpkb (BASE_42 + 135)
3895
#    define tbid_kbbpkb (BASE_42 + 136)
3896
#    define tbid_krppkb (BASE_42 + 137)
3897
#    define tbid_krnpkb (BASE_42 + 138)
3898
#    define tbid_krbpkb (BASE_42 + 139)
3899
#    define tbid_krrpkb (BASE_42 + 140)
3900
#    define tbid_kqppkb (BASE_42 + 141)
3901
#    define tbid_kqnpkb (BASE_42 + 142)
3902
 
3903
#    define tbid_kqrpkb (BASE_42 + 144)
3904
#    define tbid_kqqpkb (BASE_42 + 145)
3905
#    define tbid_kpppkr (BASE_42 + 146)
3906
#    define tbid_knppkr (BASE_42 + 147)
3907
#    define tbid_knnpkr (BASE_42 + 148)
3908
#    define tbid_kbppkr (BASE_42 + 149)
3909
#    define tbid_kbnpkr (BASE_42 + 150)
3910
#    define tbid_kbbpkr (BASE_42 + 151)
3911
#    define tbid_krppkr (BASE_42 + 152)
3912
#    define tbid_krnpkr (BASE_42 + 153)
3913
#    define tbid_krbpkr (BASE_42 + 154)
3914
#    define tbid_krrpkr (BASE_42 + 155)
3915
 
3916
#    define tbid_kqnpkr (BASE_42 + 157)
3917
#    define tbid_kqbpkr (BASE_42 + 158)
3918
#    define tbid_kqrpkr (BASE_42 + 159)
3919
#    define tbid_kqqpkr (BASE_42 + 160)
3920
#    define tbid_kpppkq (BASE_42 + 161)
3921
#    define tbid_knppkq (BASE_42 + 162)
3922
#    define tbid_knnpkq (BASE_42 + 163)
3923
#    define tbid_kbppkq (BASE_42 + 164)
3924
 
3925
#    define tbid_kbbpkq (BASE_42 + 166)
3926
#    define tbid_krppkq (BASE_42 + 167)
3927
#    define tbid_krnpkq (BASE_42 + 168)
3928
#    define tbid_krbpkq (BASE_42 + 169)
3929
#    define tbid_krrpkq (BASE_42 + 170)
3930
#    define tbid_kqppkq (BASE_42 + 171)
3931
#    define tbid_kqnpkq (BASE_42 + 172)
3932
#    define tbid_kqbpkq (BASE_42 + 173)
3933
#    define tbid_kqrpkq (BASE_42 + 174)
3934
#    define tbid_kqqpkq (BASE_42 + 175)
3935
3936
#    define C42 175
3937
#  else
3938
#    define C42 64
3939
#  endif
3940
#endif
3941
3942
#if defined (T42_INCLUDE)
3943
#  define cTb   (BASE_42 + C42 + 1)
3944
 
3945
#  define cTb   (BASE_42 + 1)
3946
 
3947
3948
// Compression
3949
3950
#include "tbdecode.h"
3951
3952
#if !defined (CPUS)
3953
#  define   CPUS    1
3954
#endif
3955
3956
#if (CPUS > 1)
3957
  static    lock_t  lockDecode;
3958
#endif
3959
 
3960
int TB_CRC_CHECK = 0;
3961
static int cCompressed = 0;
3962
static decode_block *rgpdbDecodeBlocks[CPUS];
3963
3964
// Information about tablebases
3965
 
3966
#define MAX_EXTENTS                 18  /* Maximum # of 2Gb file extents */
3967
3968
#if defined (T33_INCLUDE) || defined (T42_INCLUDE)
3969
#  define   MAX_TOTAL_PIECES        6   /* Maximum # of pieces on the board */
3970
#else
3971
#  define   MAX_TOTAL_PIECES        5   /* Maximum # of pieces on the board */
3972
#endif
3973
#define MAX_NON_KINGS           (MAX_TOTAL_PIECES - 2)
3974
3975
#if !defined (TB_DIRECTORY_SIZE)
3976
#  define   TB_DIRECTORY_SIZE       32  /* # of cache buckets */
3977
#endif
3978
3979
#if !defined (PFNCALCINDEX_DECLARED)
3980
typedef INDEX (TB_FASTCALL * PfnCalcIndex) (square *psqW, square *psqB,
3981
                                         square sqEnP, int fInverse);
3982
#  define   PFNCALCINDEX_DECLARED
3983
 
3984
3985
 
3986
3987
 
3988
    {
3989
 
3990
    lock_t                       m_lock;            // Lock on this cache bucket list
3991
#endif
3992
    volatile CTbCache * volatile m_ptbcFirst;   // Cached file chunks in LRU order
3993
    }
3994
    CTbCacheBucket;
3995
3996
typedef struct      // Hungarian: tbd
3997
    {
3998
    int             m_iTbId;
3999
    unsigned int    m_fSymmetric:1;
4000
    unsigned int    m_f16bit:1;
4001
    unsigned int    m_fSplit:1;
4002
    PfnCalcIndex    m_rgpfnCalcIndex[2];
4003
    char            m_rgchName[MAX_TOTAL_PIECES+1];
4004
    INDEX           m_rgcbLength[2];
4005
    char            *m_rgpchFileName[2][MAX_EXTENTS];
4006
#if (CPUS > 1)
4007
    lock_t          m_rglockFiles[2];
4008
#endif
4009
    FILE            *m_rgfpFiles[2][MAX_EXTENTS];
4010
    decode_info     *m_rgpdiDecodeInfo[2][MAX_EXTENTS];
4011
    CTbCacheBucket  *m_prgtbcbBuckets[2];   // Cached file chunks in LRU order
4012
    BYTE            *m_rgpbRead[2];
4013
    }
4014
    CTbDesc;
4015
4016
#if defined (T_INDEX64) && defined (_MSC_VER)
4017
#  define   TB(name, fSym, f16bit, fSplit, funW, funB, cbW, cbB)\
4018
                    { tbid_##name, fSym, f16bit, fSplit, { funW, funB }, #name, { cbW##ui64, cbB##ui64 } },
4019
#elif defined (T_INDEX64)
4020
#  define   TB(name, fSym, f16bit, fSplit, funW, funB, cbW, cbB)\
4021
                    { tbid_##name, fSym, f16bit, fSplit, { funW, funB }, #name, { cbW##llu, cbB##llu } },
4022
#else
4023
#  define   TB(name, fSym, f16bit, fSplit, funW, funB, cbW, cbB)\
4024
                    { tbid_##name, fSym, f16bit, fSplit, { funW, funB }, #name, { cbW##u, cbB##u } },
4025
#endif
4026
4027
#define P   x_piecePawn
4028
#define N   x_pieceKnight
4029
#define B   x_pieceBishop
4030
#define R   x_pieceRook
4031
#define Q   x_pieceQueen
4032
4033
CTbDesc rgtbdDesc[cTb] =
4034
    {
4035
    TB (kk, true, false, false, NULL, NULL, 0, 0)
4036
4037
    TB (kpk, false, false, false, (T21<P>::IndCalcW), (T21<P>::IndCalcB), 81664, 84012)
4038
    TB (knk, false, false, false, (T21<N>::IndCalcW), (T21<N>::IndCalcB), 26282, 28644)
4039
    TB (kbk, false, false, false, (T21<B>::IndCalcW), (T21<B>::IndCalcB), 27243, 28644)
4040
    TB (krk, false, false, false, (T21<R>::IndCalcW), (T21<R>::IndCalcB), 27030, 28644)
4041
    TB (kqk, false, false, false, (T21<Q>::IndCalcW), (T21<Q>::IndCalcB), 25629, 28644)
4042
4043
    TB (kpkp, false, false, false, (T22<P, P>::IndCalcW), (T22<P, P>::IndCalcB), 3863492, 3863492)
4044
    TB (knkp, false, false, false, (T22<N, P>::IndCalcW), (T22<N, P>::IndCalcB), 4931904, 4981504)
4045
    TB (knkn, true,  false, false, (T22<N, N>::IndCalcW), (T22<N, N>::IndCalcB), 1603202, 1603202)
4046
    TB (kbkp, false, false, false, (T22<B, P>::IndCalcW), (T22<B, P>::IndCalcB), 5112000, 4981504)
4047
    TB (kbkn, false, false, false, (T22<B, N>::IndCalcW), (T22<B, N>::IndCalcB), 1661823, 1603202)
4048
    TB (kbkb, true,  false, false, (T22<B, B>::IndCalcW), (T22<B, B>::IndCalcB), 1661823, 1661823)
4049
    TB (krkp, false, false, false, (T22<R, P>::IndCalcW), (T22<R, P>::IndCalcB), 5072736, 4981504)
4050
    TB (krkn, false, false, false, (T22<R, N>::IndCalcW), (T22<R, N>::IndCalcB), 1649196, 1603202)
4051
    TB (krkb, false, false, false, (T22<R, B>::IndCalcW), (T22<R, B>::IndCalcB), 1649196, 1661823)
4052
    TB (krkr, true,  false, false, (T22<R, R>::IndCalcW), (T22<R, R>::IndCalcB), 1649196, 1649196)
4053
    TB (kqkp, false, false, false, (T22<Q, P>::IndCalcW), (T22<Q, P>::IndCalcB), 4810080, 4981504)
4054
    TB (kqkn, false, false, false, (T22<Q, N>::IndCalcW), (T22<Q, N>::IndCalcB), 1563735, 1603202)
4055
    TB (kqkb, false, false, false, (T22<Q, B>::IndCalcW), (T22<Q, B>::IndCalcB), 1563735, 1661823)
4056
    TB (kqkr, false, false, false, (T22<Q, R>::IndCalcW), (T22<Q, R>::IndCalcB), 1563735, 1649196)
4057
    TB (kqkq, true,  false, false, (T22<Q, Q>::IndCalcW), (T22<Q, Q>::IndCalcB), 1563735, 1563735)
4058
    TB (kppk, false, false, false, (T31<P, P>::IndCalcW), (T31<P, P>::IndCalcB), 1806671, 1912372)
4059
    TB (knpk, false, false, false, (T31<N, P>::IndCalcW), (T31<N, P>::IndCalcB), 4648581, 5124732)
4060
    TB (knnk, false, false, false, (T31<N, N>::IndCalcW), (T31<N, N>::IndCalcB),  735304,  873642)
4061
    TB (kbpk, false, false, false, (T31<B, P>::IndCalcW), (T31<B, P>::IndCalcB), 4817128, 5124732)
4062
    TB (kbnk, false, false, false, (T31<B, N>::IndCalcW), (T31<B, N>::IndCalcB), 1550620, 1747284)
4063
    TB (kbbk, false, false, false, (T31<B, B>::IndCalcW), (T31<B, B>::IndCalcB),  789885,  873642)
4064
    TB (krpk, false, false, false, (T31<R, P>::IndCalcW), (T31<R, P>::IndCalcB), 4779530, 5124732)
4065
    TB (krnk, false, false, false, (T31<R, N>::IndCalcW), (T31<R, N>::IndCalcB), 1538479, 1747284)
4066
    TB (krbk, false, false, false, (T31<R, B>::IndCalcW), (T31<R, B>::IndCalcB), 1594560, 1747284)
4067
    TB (krrk, false, false, false, (T31<R, R>::IndCalcW), (T31<R, R>::IndCalcB),  777300,  873642)
4068
    TB (kqpk, false, false, false, (T31<Q, P>::IndCalcW), (T31<Q, P>::IndCalcB), 4533490, 5124732)
4069
    TB (kqnk, false, false, false, (T31<Q, N>::IndCalcW), (T31<Q, N>::IndCalcB), 1459616, 1747284)
4070
    TB (kqbk, false, false, false, (T31<Q, B>::IndCalcW), (T31<Q, B>::IndCalcB), 1512507, 1747284)
4071
    TB (kqrk, false, false, false, (T31<Q, R>::IndCalcW), (T31<Q, R>::IndCalcB), 1500276, 1747284)
4072
    TB (kqqk, false, false, false, (T31<Q, Q>::IndCalcW), (T31<Q, Q>::IndCalcB),  698739,  873642)
4073
4074
#if !defined (KPPKP_16BIT)
4075
    TB (kppkp, false, false, false, (T32<P, P, P>::IndCalcW), (T32<P, P, P>::IndCalcB),  84219361,  89391280)
4076
#else
4077
    TB (kppkp, false, true,  false, (T32<P, P, P>::IndCalcW), (T32<P, P, P>::IndCalcB),  84219361,  89391280)
4078
#endif
4079
    TB (kppkn, false, false, false, (T32<P, P, N>::IndCalcW), (T32<P, P, N>::IndCalcB), 108400260, 115899744)
4080
    TB (kppkb, false, false, false, (T32<P, P, B>::IndCalcW), (T32<P, P, B>::IndCalcB), 108400260, 120132000)
4081
    TB (kppkr, false, false, false, (T32<P, P, R>::IndCalcW), (T32<P, P, R>::IndCalcB), 108400260, 119209296)
4082
    TB (kppkq, false, false, false, (T32<P, P, Q>::IndCalcW), (T32<P, P, Q>::IndCalcB), 108400260, 113036880)
4083
    TB (knpkp, false, false, false, (T32<N, P, P>::IndCalcW), (T32<N, P, P>::IndCalcB), 219921779, 231758952)
4084
    TB (knpkn, false, false, false, (T32<N, P, N>::IndCalcW), (T32<N, P, N>::IndCalcB), 278914860, 295914240)
4085
    TB (knpkb, false, false, false, (T32<N, P, B>::IndCalcW), (T32<N, P, B>::IndCalcB), 278914860, 306720000)
4086
    TB (knpkr, false, false, false, (T32<N, P, R>::IndCalcW), (T32<N, P, R>::IndCalcB), 278914860, 304369920)
4087
    TB (knpkq, false, false, false, (T32<N, P, Q>::IndCalcW), (T32<N, P, Q>::IndCalcB), 278914860, 288610560)
4088
    TB (knnkp, false, false, false, (T32<N, N, P>::IndCalcW), (T32<N, N, P>::IndCalcB), 137991648, 149445120)
4089
    TB (knnkn, false, false, false, (T32<N, N, N>::IndCalcW), (T32<N, N, N>::IndCalcB),  44118240,  48096060)
4090
    TB (knnkb, false, false, false, (T32<N, N, B>::IndCalcW), (T32<N, N, B>::IndCalcB),  44118240,  49854690)
4091
    TB (knnkr, false, false, false, (T32<N, N, R>::IndCalcW), (T32<N, N, R>::IndCalcB),  44118240,  49475880)
4092
    TB (knnkq, false, false, false, (T32<N, N, Q>::IndCalcW), (T32<N, N, Q>::IndCalcB),  44118240,  46912050)
4093
    TB (kbpkp, false, false, false, (T32<B, P, P>::IndCalcW), (T32<B, P, P>::IndCalcB), 227896016, 231758952)
4094
    TB (kbpkn, false, false, false, (T32<B, P, N>::IndCalcW), (T32<B, P, N>::IndCalcB), 289027680, 295914240)
4095
    TB (kbpkb, false, false, false, (T32<B, P, B>::IndCalcW), (T32<B, P, B>::IndCalcB), 289027680, 306720000)
4096
    TB (kbpkr, false, false, false, (T32<B, P, R>::IndCalcW), (T32<B, P, R>::IndCalcB), 289027680, 304369920)
4097
    TB (kbpkq, false, false, false, (T32<B, P, Q>::IndCalcW), (T32<B, P, Q>::IndCalcB), 289027680, 288610560)
4098
    TB (kbnkp, false, false, false, (T32<B, N, P>::IndCalcW), (T32<B, N, P>::IndCalcB), 290989584, 298890240)
4099
    TB (kbnkn, false, false, false, (T32<B, N, N>::IndCalcW), (T32<B, N, N>::IndCalcB),  93037200,  96192120)
4100
    TB (kbnkb, false, false, false, (T32<B, N, B>::IndCalcW), (T32<B, N, B>::IndCalcB),  93037200,  99709380)
4101
 
4102
    TB (kbnkq, false, false, false, (T32<B, N, Q>::IndCalcW), (T32<B, N, Q>::IndCalcB),  93037200,  93824100)
4103
    TB (kbbkp, false, false, false, (T32<B, B, P>::IndCalcW), (T32<B, B, P>::IndCalcB), 148223520, 149445120)
4104
    TB (kbbkn, false, false, false, (T32<B, B, N>::IndCalcW), (T32<B, B, N>::IndCalcB),  47393100,  48096060)
4105
    TB (kbbkb, false, false, false, (T32<B, B, B>::IndCalcW), (T32<B, B, B>::IndCalcB),  47393100,  49854690)
4106
    TB (kbbkr, false, false, false, (T32<B, B, R>::IndCalcW), (T32<B, B, R>::IndCalcB),  47393100,  49475880)
4107
    TB (kbbkq, false, false, false, (T32<B, B, Q>::IndCalcW), (T32<B, B, Q>::IndCalcB),  47393100,  46912050)
4108
    TB (krpkp, false, false, false, (T32<R, P, P>::IndCalcW), (T32<R, P, P>::IndCalcB), 226121876, 231758952)
4109
    TB (krpkn, false, false, false, (T32<R, P, N>::IndCalcW), (T32<R, P, N>::IndCalcB), 286777440, 295914240)
4110
    TB (krpkb, false, false, false, (T32<R, P, B>::IndCalcW), (T32<R, P, B>::IndCalcB), 286777440, 306720000)
4111
    TB (krpkr, false, false, false, (T32<R, P, R>::IndCalcW), (T32<R, P, R>::IndCalcB), 286777440, 304369920)
4112
    TB (krpkq, false, false, false, (T32<R, P, Q>::IndCalcW), (T32<R, P, Q>::IndCalcB), 286777440, 288610560)
4113
    TB (krnkp, false, false, false, (T32<R, N, P>::IndCalcW), (T32<R, N, P>::IndCalcB), 288692928, 298890240)
4114
    TB (krnkn, false, false, false, (T32<R, N, N>::IndCalcW), (T32<R, N, N>::IndCalcB),  92308740,  96192120)
4115
    TB (krnkb, false, false, false, (T32<R, N, B>::IndCalcW), (T32<R, N, B>::IndCalcB),  92308740,  99709380)
4116
    TB (krnkr, false, false, false, (T32<R, N, R>::IndCalcW), (T32<R, N, R>::IndCalcB),  92308740,  98951760)
4117
    TB (krnkq, false, false, false, (T32<R, N, Q>::IndCalcW), (T32<R, N, Q>::IndCalcB),  92308740,  93824100)
4118
    TB (krbkp, false, false, false, (T32<R, B, P>::IndCalcW), (T32<R, B, P>::IndCalcB), 299203200, 298890240)
4119
    TB (krbkn, false, false, false, (T32<R, B, N>::IndCalcW), (T32<R, B, N>::IndCalcB),  95673600,  96192120)
4120
    TB (krbkb, false, false, false, (T32<R, B, B>::IndCalcW), (T32<R, B, B>::IndCalcB),  95673600,  99709380)
4121
    TB (krbkr, false, false, false, (T32<R, B, R>::IndCalcW), (T32<R, B, R>::IndCalcB),  95673600,  98951760)
4122
    TB (krbkq, false, false, false, (T32<R, B, Q>::IndCalcW), (T32<R, B, Q>::IndCalcB),  95673600,  93824100)
4123
    TB (krrkp, false, false, false, (T32<R, R, P>::IndCalcW), (T32<R, R, P>::IndCalcB), 145901232, 149445120)
4124
    TB (krrkn, false, false, false, (T32<R, R, N>::IndCalcW), (T32<R, R, N>::IndCalcB),  46658340,  48096060)
4125
    TB (krrkb, false, false, false, (T32<R, R, B>::IndCalcW), (T32<R, R, B>::IndCalcB),  46658340,  49854690)
4126
    TB (krrkr, false, false, false, (T32<R, R, R>::IndCalcW), (T32<R, R, R>::IndCalcB),  46658340,  49475880)
4127
    TB (krrkq, false, false, false, (T32<R, R, Q>::IndCalcW), (T32<R, R, Q>::IndCalcB),  46658340,  46912050)
4128
    TB (kqpkp, false, false, false, (T32<Q, P, P>::IndCalcW), (T32<Q, P, P>::IndCalcB), 214481388, 231758952)
4129
    TB (kqpkn, false, false, false, (T32<Q, P, N>::IndCalcW), (T32<Q, P, N>::IndCalcB), 272015040, 295914240)
4130
    TB (kqpkb, false, false, false, (T32<Q, P, B>::IndCalcW), (T32<Q, P, B>::IndCalcB), 272015040, 306720000)
4131
    TB (kqpkr, false, false, false, (T32<Q, P, R>::IndCalcW), (T32<Q, P, R>::IndCalcB), 272015040, 304369920)
4132
    TB (kqpkq, false, false, false, (T32<Q, P, Q>::IndCalcW), (T32<Q, P, Q>::IndCalcB), 272015040, 288610560)
4133
    TB (kqnkp, false, false, false, (T32<Q, N, P>::IndCalcW), (T32<Q, N, P>::IndCalcB), 273904512, 298890240)
4134
    TB (kqnkn, false, false, false, (T32<Q, N, N>::IndCalcW), (T32<Q, N, N>::IndCalcB),  87576960,  96192120)
4135
    TB (kqnkb, false, false, false, (T32<Q, N, B>::IndCalcW), (T32<Q, N, B>::IndCalcB),  87576960,  99709380)
4136
    TB (kqnkr, false, false, false, (T32<Q, N, R>::IndCalcW), (T32<Q, N, R>::IndCalcB),  87576960,  98951760)
4137
    TB (kqnkq, false, false, false, (T32<Q, N, Q>::IndCalcW), (T32<Q, N, Q>::IndCalcB),  87576960,  93824100)
4138
    TB (kqbkp, false, false, false, (T32<Q, B, P>::IndCalcW), (T32<Q, B, P>::IndCalcB), 283818240, 298890240)
4139
 
4140
    TB (kqbkb, false, false, false, (T32<Q, B, B>::IndCalcW), (T32<Q, B, B>::IndCalcB),  90750420,  99709380)
4141
    TB (kqbkr, false, false, false, (T32<Q, B, R>::IndCalcW), (T32<Q, B, R>::IndCalcB),  90750420,  98951760)
4142
    TB (kqbkq, false, false, false, (T32<Q, B, Q>::IndCalcW), (T32<Q, B, Q>::IndCalcB),  90750420,  93824100)
4143
    TB (kqrkp, false, false, false, (T32<Q, R, P>::IndCalcW), (T32<Q, R, P>::IndCalcB), 281568240, 298890240)
4144
    TB (kqrkn, false, false, false, (T32<Q, R, N>::IndCalcW), (T32<Q, R, N>::IndCalcB),  90038460,  96192120)
4145
    TB (kqrkb, false, false, false, (T32<Q, R, B>::IndCalcW), (T32<Q, R, B>::IndCalcB),  90038460,  99709380)
4146
    TB (kqrkr, false, false, false, (T32<Q, R, R>::IndCalcW), (T32<Q, R, R>::IndCalcB),  90038460,  98951760)
4147
    TB (kqrkq, false, false, false, (T32<Q, R, Q>::IndCalcW), (T32<Q, R, Q>::IndCalcB),  90038460,  93824100)
4148
    TB (kqqkp, false, false, false, (T32<Q, Q, P>::IndCalcW), (T32<Q, Q, P>::IndCalcB), 131170128, 149445120)
4149
    TB (kqqkn, false, false, false, (T32<Q, Q, N>::IndCalcW), (T32<Q, Q, N>::IndCalcB),  41944320,  48096060)
4150
    TB (kqqkb, false, false, false, (T32<Q, Q, B>::IndCalcW), (T32<Q, Q, B>::IndCalcB),  41944320,  49854690)
4151
    TB (kqqkr, false, false, false, (T32<Q, Q, R>::IndCalcW), (T32<Q, Q, R>::IndCalcB),  41944320,  49475880)
4152
    TB (kqqkq, false, false, false, (T32<Q, Q, Q>::IndCalcW), (T32<Q, Q, Q>::IndCalcB),  41944320,  46912050)
4153
4154
#if defined (T41_INCLUDE)
4155
    TB (kpppk, false, false, false, (T41<P, P, P>::IndCalcW), (T41<P, P, P>::IndCalcB),  26061704,  28388716)
4156
    TB (knppk, false, false, false, (T41<N, P, P>::IndCalcW), (T41<N, P, P>::IndCalcB), 102898651, 114742320)
4157
    TB (knnpk, false, false, false, (T41<N, N, P>::IndCalcW), (T41<N, N, P>::IndCalcB), 130135501, 153741960)
4158
    TB (knnnk, false, false, false, (T41<N, N, N>::IndCalcW), (T41<N, N, N>::IndCalcB),  13486227,  17472840)
4159
    TB (kbppk, false, false, false, (T41<B, P, P>::IndCalcW), (T41<B, P, P>::IndCalcB), 106602156, 114742320)
4160
    TB (kbnpk, false, false, false, (T41<B, N, P>::IndCalcW), (T41<B, N, P>::IndCalcB), 274352939, 307483920)
4161
    TB (kbnnk, false, false, false, (T41<B, N, N>::IndCalcW), (T41<B, N, N>::IndCalcB),  43406294, 52418520)
4162
    TB (kbbpk, false, false, false, (T41<B, B, P>::IndCalcW), (T41<B, B, P>::IndCalcB), 139715040, 153741960)
4163
    TB (kbbnk, false, false, false, (T41<B, B, N>::IndCalcW), (T41<B, B, N>::IndCalcB),  44983618,  52418520)
4164
    TB (kbbbk, false, false, false, (T41<B, B, B>::IndCalcW), (T41<B, B, B>::IndCalcB),  15010230,  17472840)
4165
    TB (krppk, false, false, false, (T41<R, P, P>::IndCalcW), (T41<R, P, P>::IndCalcB), 105758666, 114742320)
4166
    TB (krnpk, false, false, false, (T41<R, N, P>::IndCalcW), (T41<R, N, P>::IndCalcB), 272153675, 307483920)
4167
    TB (krnnk, false, false, false, (T41<R, N, N>::IndCalcW), (T41<R, N, N>::IndCalcB),  43056198,  52418520)
4168
    TB (krbpk, false, false, false, (T41<R, B, P>::IndCalcW), (T41<R, B, P>::IndCalcB), 281991360, 307483920)
4169
    TB (krbnk, false, false, false, (T41<R, B, N>::IndCalcW), (T41<R, B, N>::IndCalcB),  90787358, 104837040)
4170
    TB (krbbk, false, false, false, (T41<R, B, B>::IndCalcW), (T41<R, B, B>::IndCalcB),  46242089,  52418520)
4171
    TB (krrpk, false, false, false, (T41<R, R, P>::IndCalcW), (T41<R, R, P>::IndCalcB), 137491197, 153741960)
4172
    TB (krrnk, false, false, false, (T41<R, R, N>::IndCalcW), (T41<R, R, N>::IndCalcB),  44265261,  52418520)
4173
    TB (krrbk, false, false, false, (T41<R, R, B>::IndCalcW), (T41<R, R, B>::IndCalcB),  45873720,  52418520)
4174
    TB (krrrk, false, false, false, (T41<R, R, R>::IndCalcW), (T41<R, R, R>::IndCalcB),  14644690,  17472840)
4175
    TB (kqppk, false, false, false, (T41<Q, P, P>::IndCalcW), (T41<Q, P, P>::IndCalcB), 100347220, 114742320)
4176
    TB (kqnpk, false, false, false, (T41<Q, N, P>::IndCalcW), (T41<Q, N, P>::IndCalcB), 258294639, 307483920)
4177
    TB (kqnnk, false, false, false, (T41<Q, N, N>::IndCalcW), (T41<Q, N, N>::IndCalcB),  40873646,  52418520)
4178
    TB (kqbpk, false, false, false, (T41<Q, B, P>::IndCalcW), (T41<Q, B, P>::IndCalcB), 267576632, 307483920)
4179
    TB (kqbnk, false, false, false, (T41<Q, B, N>::IndCalcW), (T41<Q, B, N>::IndCalcB),  86166717, 104837040)
4180
    TB (kqbbk, false, false, false, (T41<Q, B, B>::IndCalcW), (T41<Q, B, B>::IndCalcB),  43879679,  52418520)
4181
    TB (kqrpk, false, false, false, (T41<Q, R, P>::IndCalcW), (T41<Q, R, P>::IndCalcB), 265421907, 307483920)
4182
    TB (kqrnk, false, false, false, (T41<Q, R, N>::IndCalcW), (T41<Q, R, N>::IndCalcB),  85470603, 104837040)
4183
    TB (kqrbk, false, false, false, (T41<Q, R, B>::IndCalcW), (T41<Q, R, B>::IndCalcB),  88557959, 104837040)
4184
    TB (kqrrk, false, false, false, (T41<Q, R, R>::IndCalcW), (T41<Q, R, R>::IndCalcB),  43157690,  52418520)
4185
    TB (kqqpk, false, false, false, (T41<Q, Q, P>::IndCalcW), (T41<Q, Q, P>::IndCalcB), 123688859, 153741960)
4186
    TB (kqqnk, false, false, false, (T41<Q, Q, N>::IndCalcW), (T41<Q, Q, N>::IndCalcB),  39840787,  52418520)
4187
    TB (kqqbk, false, false, false, (T41<Q, Q, B>::IndCalcW), (T41<Q, Q, B>::IndCalcB),  41270973,  52418520)
4188
    TB (kqqrk, false, false, false, (T41<Q, Q, R>::IndCalcW), (T41<Q, Q, R>::IndCalcB),  40916820,  52418520)
4189
    TB (kqqqk, false, false, false, (T41<Q, Q, Q>::IndCalcW), (T41<Q, Q, Q>::IndCalcB),  12479974,  17472840)
4190
#endif
4191
4192
#if defined (T33_INCLUDE)
4193
    TB (knnknn, true,  false, false, (T33<N, N, N, N>::IndCalcW), (T33<N, N, N, N>::IndCalcB),  1301488080,  1301488080)
4194
    TB (kbnknn, false, false, false, (T33<B, N, N, N>::IndCalcW), (T33<B, N, N, N>::IndCalcB),  2744597400,  2602976160)
4195
    TB (kbbknn, false, false, false, (T33<B, B, N, N>::IndCalcW), (T33<B, B, N, N>::IndCalcB),  1398096450,  1301488080)
4196
    TB (kbbkbn, false, false, false, (T33<B, B, B, N>::IndCalcW), (T33<B, B, B, N>::IndCalcB),  2796192900,  2744597400)
4197
    TB (kbbkbb, true,  false, false, (T33<B, B, B, B>::IndCalcW), (T33<B, B, B, B>::IndCalcB),  1398096450,  1398096450)
4198
    TB (krnknn, false, true,  false, (T33<R, N, N, N>::IndCalcW), (T33<R, N, N, N>::IndCalcB),  2723107830,  2602976160)
4199
    TB (krnkbb, false, true,  false, (T33<R, N, B, B>::IndCalcW), (T33<R, N, B, B>::IndCalcB),  2723107830,  2796192900)
4200
    TB (krbknn, false, true,  false, (T33<R, B, N, N>::IndCalcW), (T33<R, B, N, N>::IndCalcB),  2822371200,  2602976160)
4201
    TB (krbkbb, false, false, false, (T33<R, B, B, B>::IndCalcW), (T33<R, B, B, B>::IndCalcB),  2822371200,  2796192900)
4202
    TB (krrknn, false, false, false, (T33<R, R, N, N>::IndCalcW), (T33<R, R, N, N>::IndCalcB),  1376421030,  1301488080)
4203
    TB (krrkbn, false, false, false, (T33<R, R, B, N>::IndCalcW), (T33<R, R, B, N>::IndCalcB),  2752842060,  2744597400)
4204
    TB (krrkbb, false, false, false, (T33<R, R, B, B>::IndCalcW), (T33<R, R, B, B>::IndCalcB),  1376421030,  1398096450)
4205
    TB (krrkrn, false, false, false, (T33<R, R, R, N>::IndCalcW), (T33<R, R, R, N>::IndCalcB),  2752842060,  2723107830)
4206
    TB (krrkrb, false, false, false, (T33<R, R, R, B>::IndCalcW), (T33<R, R, R, B>::IndCalcB),  2752842060,  2822371200)
4207
    TB (krrkrr, true,  false, false, (T33<R, R, R, R>::IndCalcW), (T33<R, R, R, R>::IndCalcB),  1376421030,  1376421030)
4208
    TB (kqnknn, false, false, false, (T33<Q, N, N, N>::IndCalcW), (T33<Q, N, N, N>::IndCalcB),  2583520320,  2602976160)
4209
    TB (kqnkbb, false, false, false, (T33<Q, N, B, B>::IndCalcW), (T33<Q, N, B, B>::IndCalcB),  2583520320,  2796192900)
4210
    TB (kqnkrr, false, true,  false, (T33<Q, N, R, R>::IndCalcW), (T33<Q, N, R, R>::IndCalcB),  2583520320,  2752842060)
4211
    TB (kqbknn, false, false, false, (T33<Q, B, N, N>::IndCalcW), (T33<Q, B, N, N>::IndCalcB),  2677137390,  2602976160)
4212
    TB (kqbkbb, false, false, false, (T33<Q, B, B, B>::IndCalcW), (T33<Q, B, B, B>::IndCalcB),  2677137390,  2796192900)
4213
    TB (kqbkrr, false, false, false, (T33<Q, B, R, R>::IndCalcW), (T33<Q, B, R, R>::IndCalcB),  2677137390,  2752842060)
4214
    TB (kqrknn, false, false, false, (T33<Q, R, N, N>::IndCalcW), (T33<Q, R, N, N>::IndCalcB),  2656134570,  2602976160)
4215
    TB (kqrkbb, false, false, false, (T33<Q, R, B, B>::IndCalcW), (T33<Q, R, B, B>::IndCalcB),  2656134570,  2796192900)
4216
    TB (kqrkrr, false, false, false, (T33<Q, R, R, R>::IndCalcW), (T33<Q, R, R, R>::IndCalcB),  2656134570,  2752842060)
4217
    TB (kqqknn, false, false, false, (T33<Q, Q, N, N>::IndCalcW), (T33<Q, Q, N, N>::IndCalcB),  1237357440,  1301488080)
4218
    TB (kqqkbn, false, false, false, (T33<Q, Q, B, N>::IndCalcW), (T33<Q, Q, B, N>::IndCalcB),  2474714880,  2744597400)
4219
    TB (kqqkbb, false, false, false, (T33<Q, Q, B, B>::IndCalcW), (T33<Q, Q, B, B>::IndCalcB),  1237357440,  1398096450)
4220
    TB (kqqkrn, false, false, false, (T33<Q, Q, R, N>::IndCalcW), (T33<Q, Q, R, N>::IndCalcB),  2474714880,  2723107830)
4221
    TB (kqqkrb, false, false, false, (T33<Q, Q, R, B>::IndCalcW), (T33<Q, Q, R, B>::IndCalcB),  2474714880,  2822371200)
4222
    TB (kqqkrr, false, false, false, (T33<Q, Q, R, R>::IndCalcW), (T33<Q, Q, R, R>::IndCalcB),  1237357440,  1376421030)
4223
    TB (kqqkqn, false, false, false, (T33<Q, Q, Q, N>::IndCalcW), (T33<Q, Q, Q, N>::IndCalcB),  2474714880,  2583520320)
4224
    TB (kqqkqb, false, false, false, (T33<Q, Q, Q, B>::IndCalcW), (T33<Q, Q, Q, B>::IndCalcB),  2474714880,  2677137390)
4225
    TB (kqqkqr, false, false, false, (T33<Q, Q, Q, R>::IndCalcW), (T33<Q, Q, Q, R>::IndCalcB),  2474714880,  2656134570)
4226
    TB (kqqkqq, true,  false, false, (T33<Q, Q, Q, Q>::IndCalcW), (T33<Q, Q, Q, Q>::IndCalcB),  1237357440,  1237357440)
4227
#if defined (T_INDEX64)
4228
    TB (kbnkbn, true,  false, false, (T33<B, N, B, N>::IndCalcW), (T33<B, N, B, N>::IndCalcB),  5489194800,  5489194800)
4229
    TB (krnkrn, true,  false, false, (T33<R, N, R, N>::IndCalcW), (T33<R, N, R, N>::IndCalcB),  5446215660,  5446215660)
4230
    TB (krbkrb, true,  false, false, (T33<R, B, R, B>::IndCalcW), (T33<R, B, R, B>::IndCalcB),  5644742400,  5644742400)
4231
    TB (kqnkqn, true,  false, false, (T33<Q, N, Q, N>::IndCalcW), (T33<Q, N, Q, N>::IndCalcB),  5167040640,  5167040640)
4232
    TB (kqbkqb, true,  false, false, (T33<Q, B, Q, B>::IndCalcW), (T33<Q, B, Q, B>::IndCalcB),  5354274780,  5354274780)
4233
    TB (kqrkqr, true,  false, false, (T33<Q, R, Q, R>::IndCalcW), (T33<Q, R, Q, R>::IndCalcB),  5312269140,  5312269140)
4234
    TB (krnkbn, false, true,  true,  (T33<R, N, B, N>::IndCalcW), (T33<R, N, B, N>::IndCalcB),  5446215660,  5489194800)
4235
    TB (krbkbn, false, false, true,  (T33<R, B, B, N>::IndCalcW), (T33<R, B, B, N>::IndCalcB),  5644742400,  5489194800)
4236
    TB (krbkrn, false, false, false, (T33<R, B, R, N>::IndCalcW), (T33<R, B, R, N>::IndCalcB),  5644742400,  5446215660)
4237
    TB (kqnkbn, false, false, false, (T33<Q, N, B, N>::IndCalcW), (T33<Q, N, B, N>::IndCalcB),  5167040640,  5489194800)
4238
    TB (kqnkrn, false, false, true,  (T33<Q, N, R, N>::IndCalcW), (T33<Q, N, R, N>::IndCalcB),  5167040640,  5446215660)
4239
    TB (kqnkrb, false, false, true,  (T33<Q, N, R, B>::IndCalcW), (T33<Q, N, R, B>::IndCalcB),  5167040640,  5644742400)
4240
    TB (kqbkbn, false, false, false, (T33<Q, B, B, N>::IndCalcW), (T33<Q, B, B, N>::IndCalcB),  5354274780,  5489194800)
4241
    TB (kqbkrn, false, false, true,  (T33<Q, B, R, N>::IndCalcW), (T33<Q, B, R, N>::IndCalcB),  5354274780,  5446215660)
4242
    TB (kqbkrb, false, false, true,  (T33<Q, B, R, B>::IndCalcW), (T33<Q, B, R, B>::IndCalcB),  5354274780,  5644742400)
4243
    TB (kqbkqn, false, false, false, (T33<Q, B, Q, N>::IndCalcW), (T33<Q, B, Q, N>::IndCalcB),  5354274780,  5167040640)
4244
    TB (kqrkbn, false, false, false, (T33<Q, R, B, N>::IndCalcW), (T33<Q, R, B, N>::IndCalcB),  5312269140,  5489194800)
4245
    TB (kqrkrn, false, false, false, (T33<Q, R, R, N>::IndCalcW), (T33<Q, R, R, N>::IndCalcB),  5312269140,  5446215660)
4246
    TB (kqrkrb, false, false, false, (T33<Q, R, R, B>::IndCalcW), (T33<Q, R, R, B>::IndCalcB),  5312269140,  5644742400)
4247
    TB (kqrkqn, false, false, false, (T33<Q, R, Q, N>::IndCalcW), (T33<Q, R, Q, N>::IndCalcB),  5312269140,  5167040640)
4248
    TB (kqrkqb, false, false, false, (T33<Q, R, Q, B>::IndCalcW), (T33<Q, R, Q, B>::IndCalcB),  5312269140,  5354274780)
4249
4250
    TB (kppkpp, true,  true,  false, (T33<P, P, P, P>::IndCalcW), (T33<P, P, P, P>::IndCalcBF),  1917741812,  1917741812)
4251
    TB (knpkpp, false, true,  true,  (T33<N, P, P, P>::IndCalcW), (T33<N, P, P, P>::IndCalcB),   5088408829,  4966717366)
4252
    TB (knpknp, true,  false, true,  (T33<N, P, N, P>::IndCalcW), (T33<N, P, N, P>::IndCalcBF), 12972508017, 12972508017)
4253
    TB (knnkpp, false, true,  false, (T33<N, N, P, P>::IndCalcW), (T33<N, N, P, P>::IndCalcB),   3242803728,  3197807670)
4254
    TB (knnknp, false, true,  true,  (T33<N, N, N, P>::IndCalcW), (T33<N, N, N, P>::IndCalcB),   8141507232,  8227988370)
4255
    TB (kbpkpp, false, true,  true,  (T33<B, P, P, P>::IndCalcW), (T33<B, P, P, P>::IndCalcB),   5272919368,  4966717366)
4256
    TB (kbpknp, false, true,  true,  (T33<B, P, N, P>::IndCalcW), (T33<B, P, N, P>::IndCalcB),  13442882944, 12972508017)
4257
    TB (kbpknn, false, true,  true,  (T33<B, P, N, N>::IndCalcW), (T33<B, P, N, N>::IndCalcB),   8526316560,  8141507232)
4258
    TB (kbpkbp, true,  false, true,  (T33<B, P, B, P>::IndCalcW), (T33<B, P, B, P>::IndCalcBF), 13442882944, 13442882944)
4259
    TB (kbnkpp, false, true,  true,  (T33<B, N, P, P>::IndCalcW), (T33<B, N, P, P>::IndCalcB),   6838255224,  6395615340)
4260
    TB (kbnknp, false, true,  true,  (T33<B, N, N, P>::IndCalcW), (T33<B, N, N, P>::IndCalcB),  17168385456, 16455976740)
4261
    TB (kbnkbp, false, false, true,  (T33<B, N, B, P>::IndCalcW), (T33<B, N, B, P>::IndCalcB),  17168385456, 17052633120)
4262
    TB (kbbkpp, false, false, false, (T33<B, B, P, P>::IndCalcW), (T33<B, B, P, P>::IndCalcB),   3483252720,  3197807670)
4263
    TB (kbbknp, false, true,  true,  (T33<B, B, N, P>::IndCalcW), (T33<B, B, N, P>::IndCalcB),   8745187680,  8227988370)
4264
    TB (kbbkbp, false, false, true,  (T33<B, B, B, P>::IndCalcW), (T33<B, B, B, P>::IndCalcB),   8745187680,  8526316560)
4265
    TB (krpkpp, false, true,  true,  (T33<R, P, P, P>::IndCalcW), (T33<R, P, P, P>::IndCalcB),   5231873656,  4966717366)
4266
    TB (krpknp, false, true,  true,  (T33<R, P, N, P>::IndCalcW), (T33<R, P, N, P>::IndCalcB),  13338233184, 12972508017)
4267
    TB (krpknn, false, true,  true,  (T33<R, P, N, N>::IndCalcW), (T33<R, P, N, N>::IndCalcB),   8459934480,  8141507232)
4268
    TB (krpkbp, false, true,  true,  (T33<R, P, B, P>::IndCalcW), (T33<R, P, B, P>::IndCalcB),  13338233184, 13442882944)
4269
    TB (krpkbn, false, true,  true,  (T33<R, P, B, N>::IndCalcW), (T33<R, P, B, N>::IndCalcB),  16919868960, 17168385456)
4270
    TB (krpkbb, false, true,  true,  (T33<R, P, B, B>::IndCalcW), (T33<R, P, B, B>::IndCalcB),   8459934480,  8745187680)
4271
    TB (krpkrp, true,  false, true,  (T33<R, P, R, P>::IndCalcW), (T33<R, P, R, P>::IndCalcBF), 13338233184, 13338233184)
4272
    TB (krnkpp, false, true,  true,  (T33<R, N, P, P>::IndCalcW), (T33<R, N, P, P>::IndCalcB),   6784283808,  6395615340)
4273
    TB (krnknp, false, true,  true,  (T33<R, N, N, P>::IndCalcW), (T33<R, N, N, P>::IndCalcB),  17032882752, 16455976740)
4274
 
4275
    TB (krnkrp, false, false, true,  (T33<R, N, R, P>::IndCalcW), (T33<R, N, R, P>::IndCalcB),  17032882752, 16919868906)
4276
    TB (krbkpp, false, true,  true,  (T33<R, B, P, P>::IndCalcW), (T33<R, B, P, P>::IndCalcB),   7031275200,  6395615340)
4277
    TB (krbknp, false, true,  true,  (T33<R, B, N, P>::IndCalcW), (T33<R, B, N, P>::IndCalcB),  17652988800, 16455976740)
4278
    TB (krbkbp, false, false, true,  (T33<R, B, B, P>::IndCalcW), (T33<R, B, B, P>::IndCalcB),  17652988800, 17052633120)
4279
    TB (krbkrp, false, false, true,  (T33<R, B, R, P>::IndCalcW), (T33<R, B, R, P>::IndCalcB),  17652988800, 16919868906)
4280
 
4281
    TB (krrknp, false, true,  true,  (T33<R, R, N, P>::IndCalcW), (T33<R, R, N, P>::IndCalcB),   8608504032,  8227988370)
4282
    TB (krrkbp, false, false, true,  (T33<R, R, B, P>::IndCalcW), (T33<R, R, B, P>::IndCalcB),   8608504032,  8526316560)
4283
    TB (krrkrp, false, false, true,  (T33<R, R, R, P>::IndCalcW), (T33<R, R, R, P>::IndCalcB),   8608504032,  8459934426)
4284
    TB (kqpkpp, false, true,  true,  (T33<Q, P, P, P>::IndCalcW), (T33<Q, P, P, P>::IndCalcB),   4962533664,  4966717366)
4285
    TB (kqpknp, false, false, true,  (T33<Q, P, N, P>::IndCalcW), (T33<Q, P, N, P>::IndCalcB),  12651597608, 12972508017)
4286
    TB (kqpknn, false, false, true,  (T33<Q, P, N, N>::IndCalcW), (T33<Q, P, N, N>::IndCalcB),   8024443680,  8141507232)
4287
    TB (kqpkbp, false, false, true,  (T33<Q, P, B, P>::IndCalcW), (T33<Q, P, B, P>::IndCalcB),  12651597608, 13442882944)
4288
    TB (kqpkbn, false, false, true,  (T33<Q, P, B, N>::IndCalcW), (T33<Q, P, B, N>::IndCalcB),  16048887360, 17168385456)
4289
    TB (kqpkbb, false, false, true,  (T33<Q, P, B, B>::IndCalcW), (T33<Q, P, B, B>::IndCalcB),   8024443680,  8745187680)
4290
    TB (kqpkrp, false, false, true,  (T33<Q, P, R, P>::IndCalcW), (T33<Q, P, R, P>::IndCalcB),  12651597608, 13338233184)
4291
    TB (kqpkrn, false, false, true,  (T33<Q, P, R, N>::IndCalcW), (T33<Q, P, R, N>::IndCalcB),  16048887360, 17032882752)
4292
    TB (kqpkrb, false, true,  true,  (T33<Q, P, R, B>::IndCalcW), (T33<Q, P, R, B>::IndCalcB),  16048887360, 17652988800)
4293
    TB (kqpkrr, false, true,  true,  (T33<Q, P, R, R>::IndCalcW), (T33<Q, P, R, R>::IndCalcB),   8024443680,  8608504032)
4294
    TB (kqpkqp, true,  true,  true,  (T33<Q, P, Q, P>::IndCalcW), (T33<Q, P, Q, P>::IndCalcBF), 12651597608, 12651597608)
4295
    TB (kqnkpp, false, true,  true,  (T33<Q, N, P, P>::IndCalcW), (T33<Q, N, P, P>::IndCalcB),   6436756032,  6395615340)
4296
    TB (kqnknp, false, false, true,  (T33<Q, N, N, P>::IndCalcW), (T33<Q, N, N, P>::IndCalcB),  16160366208, 16455976740)
4297
    TB (kqnkbp, false, false, true,  (T33<Q, N, B, P>::IndCalcW), (T33<Q, N, B, P>::IndCalcB),  16160366208, 17052633120)
4298
    TB (kqnkrp, false, false, true,  (T33<Q, N, R, P>::IndCalcW), (T33<Q, N, R, P>::IndCalcB),  16160366208, 16919868906)
4299
    TB (kqnkqp, false, true,  true,  (T33<Q, N, Q, P>::IndCalcW), (T33<Q, N, Q, P>::IndCalcB),  16160366208, 16048887306)
4300
    TB (kqbkpp, false, false, true,  (T33<Q, B, P, P>::IndCalcW), (T33<Q, B, P, P>::IndCalcB),   6669728640,  6395615340)
4301
    TB (kqbknp, false, false, true,  (T33<Q, B, N, P>::IndCalcW), (T33<Q, B, N, P>::IndCalcB),  16745276160, 16455976740)
4302
    TB (kqbkbp, false, false, true,  (T33<Q, B, B, P>::IndCalcW), (T33<Q, B, B, P>::IndCalcB),  16745276160, 17052633120)
4303
    TB (kqbkrp, false, false, true,  (T33<Q, B, R, P>::IndCalcW), (T33<Q, B, R, P>::IndCalcB),  16745276160, 16919868906)
4304
    TB (kqbkqp, false, true,  true,  (T33<Q, B, Q, P>::IndCalcW), (T33<Q, B, Q, P>::IndCalcB),  16745276160, 16048887306)
4305
    TB (kqrkpp, false, false, true,  (T33<Q, R, P, P>::IndCalcW), (T33<Q, R, P, P>::IndCalcB),   6616853640,  6395615340)
4306
    TB (kqrknp, false, false, true,  (T33<Q, R, N, P>::IndCalcW), (T33<Q, R, N, P>::IndCalcB),  16612871664, 16455976740)
4307
    TB (kqrkbp, false, false, true,  (T33<Q, R, B, P>::IndCalcW), (T33<Q, R, B, P>::IndCalcB),  16612871664, 17052633120)
4308
    TB (kqrkrp, false, false, true,  (T33<Q, R, R, P>::IndCalcW), (T33<Q, R, R, P>::IndCalcB),  16612871664, 16919868906)
4309
    TB (kqrkqp, false, true,  true,  (T33<Q, R, Q, P>::IndCalcW), (T33<Q, R, Q, P>::IndCalcB),  16612871664, 16048887306)
4310
    TB (kqqkpp, false, false, false, (T33<Q, Q, P, P>::IndCalcW), (T33<Q, Q, P, P>::IndCalcB),   3082498008,  3197807670)
4311
    TB (kqqknp, false, false, true,  (T33<Q, Q, N, P>::IndCalcW), (T33<Q, Q, N, P>::IndCalcB),   7739363232,  8227988370)
4312
    TB (kqqkbp, false, false, true,  (T33<Q, Q, B, P>::IndCalcW), (T33<Q, Q, B, P>::IndCalcB),   7739363232,  8526316560)
4313
    TB (kqqkrp, false, false, true,  (T33<Q, Q, R, P>::IndCalcW), (T33<Q, Q, R, P>::IndCalcB),   7739363232,  8459934426)
4314
    TB (kqqkqp, false, false, true,  (T33<Q, Q, Q, P>::IndCalcW), (T33<Q, Q, Q, P>::IndCalcB),   7739363232,  8024443626)
4315
#endif  // T_INDEX64
4316
#endif  // T33_INCLUDE
4317
4318
#if defined (T42_INCLUDE)
4319
    TB (knnnkn, false, false, false, (T42<N, N, N, N>::IndCalcW), (T42<N, N, N, N>::IndCalcB),  795687393,  945889180)
4320
    TB (kbnnkn, false, false, false, (T42<B, N, N, N>::IndCalcW), (T42<B, N, N, N>::IndCalcB), 2560971346, 2837667540)
4321
    TB (kbbnkn, false, false, false, (T42<B, B, N, N>::IndCalcW), (T42<B, B, N, N>::IndCalcB), 2654033462, 2837667540)
4322
    TB (kbbbkn, false, false, false, (T42<B, B, B, N>::IndCalcW), (T42<B, B, B, N>::IndCalcB),  885603570,  945889180)
4323
    TB (krnnkn, false, false, false, (T42<R, N, N, N>::IndCalcW), (T42<R, N, N, N>::IndCalcB), 2540315682, 2837667540)
4324
    TB (krbbkn, false, false, false, (T42<R, B, B, N>::IndCalcW), (T42<R, B, B, N>::IndCalcB), 2728283251, 2837667540)
4325
    TB (krrnkn, false, false, false, (T42<R, R, N, N>::IndCalcW), (T42<R, R, N, N>::IndCalcB), 2611650399, 2837667540)
4326
    TB (krrbkn, false, false, false, (T42<R, R, B, N>::IndCalcW), (T42<R, R, B, N>::IndCalcB), 2706549480, 2837667540)
4327
    TB (krrrkn, false, false, false, (T42<R, R, R, N>::IndCalcW), (T42<R, R, R, N>::IndCalcB),  864592254,  945889180)
4328
    TB (kqnnkn, false, false, false, (T42<Q, N, N, N>::IndCalcW), (T42<Q, N, N, N>::IndCalcB), 2411545114, 2837667540)
4329
    TB (kqbbkn, false, false, false, (T42<Q, B, B, N>::IndCalcW), (T42<Q, B, B, N>::IndCalcB), 2588901061, 2837667540)
4330
    TB (kqrrkn, false, false, false, (T42<Q, R, R, N>::IndCalcW), (T42<Q, R, R, N>::IndCalcB), 2547484064, 2837667540)
4331
    TB (kqqnkn, false, false, false, (T42<Q, Q, N, N>::IndCalcW), (T42<Q, Q, N, N>::IndCalcB), 2350606433, 2837667540)
4332
    TB (kqqbkn, false, false, false, (T42<Q, Q, B, N>::IndCalcW), (T42<Q, Q, B, N>::IndCalcB), 2434987407, 2837667540)
4333
    TB (kqqrkn, false, false, false, (T42<Q, Q, R, N>::IndCalcW), (T42<Q, Q, R, N>::IndCalcB), 2415271436, 2837667540)
4334
    TB (kqqqkn, false, false, false, (T42<Q, Q, Q, N>::IndCalcW), (T42<Q, Q, Q, N>::IndCalcB),  736854363,  945889180)
4335
    TB (knnnkb, false, false, false, (T42<N, N, N, B>::IndCalcW), (T42<N, N, N, B>::IndCalcB),  795687393,  980475570)
4336
    TB (kbnnkb, false, false, false, (T42<B, N, N, B>::IndCalcW), (T42<B, N, N, B>::IndCalcB), 2560971346, 2941426710)
4337
    TB (kbbnkb, false, false, false, (T42<B, B, N, B>::IndCalcW), (T42<B, B, N, B>::IndCalcB), 2654033462, 2941426710)
4338
    TB (kbbbkb, false, false, false, (T42<B, B, B, B>::IndCalcW), (T42<B, B, B, B>::IndCalcB),  885603570,  980475570)
4339
    TB (krnnkb, false, false, false, (T42<R, N, N, B>::IndCalcW), (T42<R, N, N, B>::IndCalcB), 2540315682, 2941426710)
4340
    TB (krbbkb, false, false, false, (T42<R, B, B, B>::IndCalcW), (T42<R, B, B, B>::IndCalcB), 2728283251, 2941426710)
4341
    TB (krrnkb, false, false, false, (T42<R, R, N, B>::IndCalcW), (T42<R, R, N, B>::IndCalcB), 2611650399, 2941426710)
4342
    TB (krrbkb, false, false, false, (T42<R, R, B, B>::IndCalcW), (T42<R, R, B, B>::IndCalcB), 2706549480, 2941426710)
4343
    TB (krrrkb, false, false, false, (T42<R, R, R, B>::IndCalcW), (T42<R, R, R, B>::IndCalcB),  864592254,  980475570)
4344
    TB (kqnnkb, false, false, false, (T42<Q, N, N, B>::IndCalcW), (T42<Q, N, N, B>::IndCalcB), 2411545114, 2941426710)
4345
    TB (kqbbkb, false, false, false, (T42<Q, B, B, B>::IndCalcW), (T42<Q, B, B, B>::IndCalcB), 2588901061, 2941426710)
4346
    TB (kqrrkb, false, false, false, (T42<Q, R, R, B>::IndCalcW), (T42<Q, R, R, B>::IndCalcB), 2547484064, 2941426710)
4347
    TB (kqqnkb, false, false, false, (T42<Q, Q, N, B>::IndCalcW), (T42<Q, Q, N, B>::IndCalcB), 2350606433, 2941426710)
4348
    TB (kqqbkb, false, false, false, (T42<Q, Q, B, B>::IndCalcW), (T42<Q, Q, B, B>::IndCalcB), 2434987407, 2941426710)
4349
    TB (kqqrkb, false, false, false, (T42<Q, Q, R, B>::IndCalcW), (T42<Q, Q, R, B>::IndCalcB), 2415271436, 2941426710)
4350
    TB (kqqqkb, false, false, false, (T42<Q, Q, Q, B>::IndCalcW), (T42<Q, Q, Q, B>::IndCalcB),  736854363,  980475570)
4351
    TB (knnnkr, false, false, false, (T42<N, N, N, R>::IndCalcW), (T42<N, N, N, R>::IndCalcB),  795687393,  973025640)
4352
    TB (kbnnkr, false, false, false, (T42<B, N, N, R>::IndCalcW), (T42<B, N, N, R>::IndCalcB), 2560971346, 2919076920)
4353
    TB (kbbnkr, false, false, false, (T42<B, B, N, R>::IndCalcW), (T42<B, B, N, R>::IndCalcB), 2654033462, 2919076920)
4354
    TB (kbbbkr, false, false, false, (T42<B, B, B, R>::IndCalcW), (T42<B, B, B, R>::IndCalcB),  885603570,  973025640)
4355
    TB (krnnkr, false, false, false, (T42<R, N, N, R>::IndCalcW), (T42<R, N, N, R>::IndCalcB), 2540315682, 2919076920)
4356
    TB (krbbkr, false, false, false, (T42<R, B, B, R>::IndCalcW), (T42<R, B, B, R>::IndCalcB), 2728283251, 2919076920)
4357
    TB (krrnkr, false, false, false, (T42<R, R, N, R>::IndCalcW), (T42<R, R, N, R>::IndCalcB), 2611650399, 2919076920)
4358
    TB (krrbkr, false, false, false, (T42<R, R, B, R>::IndCalcW), (T42<R, R, B, R>::IndCalcB), 2706549480, 2919076920)
4359
    TB (krrrkr, false, false, false, (T42<R, R, R, R>::IndCalcW), (T42<R, R, R, R>::IndCalcB),  864592254,  973025640)
4360
    TB (kqnnkr, false, false, false, (T42<Q, N, N, R>::IndCalcW), (T42<Q, N, N, R>::IndCalcB), 2411545114, 2919076920)
4361
    TB (kqbbkr, false, false, false, (T42<Q, B, B, R>::IndCalcW), (T42<Q, B, B, R>::IndCalcB), 2588901061, 2919076920)
4362
    TB (kqrrkr, false, false, false, (T42<Q, R, R, R>::IndCalcW), (T42<Q, R, R, R>::IndCalcB), 2547484064, 2919076920)
4363
 
4364
    TB (kqqbkr, false, false, false, (T42<Q, Q, B, R>::IndCalcW), (T42<Q, Q, B, R>::IndCalcB), 2434987407, 2919076920)
4365
    TB (kqqrkr, false, false, false, (T42<Q, Q, R, R>::IndCalcW), (T42<Q, Q, R, R>::IndCalcB), 2415271436, 2919076920)
4366
    TB (kqqqkr, false, false, false, (T42<Q, Q, Q, R>::IndCalcW), (T42<Q, Q, Q, R>::IndCalcB),  736854363,  973025640)
4367
    TB (knnnkq, false, false, false, (T42<N, N, N, Q>::IndCalcW), (T42<N, N, N, Q>::IndCalcB),  795687393,  922603650)
4368
    TB (kbnnkq, false, false, false, (T42<B, N, N, Q>::IndCalcW), (T42<B, N, N, Q>::IndCalcB), 2560971346, 2767810950)
4369
    TB (kbbnkq, false, false, false, (T42<B, B, N, Q>::IndCalcW), (T42<B, B, N, Q>::IndCalcB), 2654033462, 2767810950)
4370
    TB (kbbbkq, false, false, false, (T42<B, B, B, Q>::IndCalcW), (T42<B, B, B, Q>::IndCalcB),  885603570,  922603650)
4371
    TB (krnnkq, false, false, false, (T42<R, N, N, Q>::IndCalcW), (T42<R, N, N, Q>::IndCalcB), 2540315682, 2767810950)
4372
    TB (krbbkq, false, false, false, (T42<R, B, B, Q>::IndCalcW), (T42<R, B, B, Q>::IndCalcB), 2728283251, 2767810950)
4373
    TB (krrnkq, false, false, false, (T42<R, R, N, Q>::IndCalcW), (T42<R, R, N, Q>::IndCalcB), 2611650399, 2767810950)
4374
    TB (krrbkq, false, false, false, (T42<R, R, B, Q>::IndCalcW), (T42<R, R, B, Q>::IndCalcB), 2706549480, 2767810950)
4375
    TB (krrrkq, false, false, false, (T42<R, R, R, Q>::IndCalcW), (T42<R, R, R, Q>::IndCalcB),  864592254,  922603650)
4376
    TB (kqnnkq, false, false, false, (T42<Q, N, N, Q>::IndCalcW), (T42<Q, N, N, Q>::IndCalcB), 2411545114, 2767810950)
4377
    TB (kqbbkq, false, false, false, (T42<Q, B, B, Q>::IndCalcW), (T42<Q, B, B, Q>::IndCalcB), 2588901061, 2767810950)
4378
    TB (kqrrkq, false, false, false, (T42<Q, R, R, Q>::IndCalcW), (T42<Q, R, R, Q>::IndCalcB), 2547484064, 2767810950)
4379
    TB (kqqnkq, false, false, false, (T42<Q, Q, N, Q>::IndCalcW), (T42<Q, Q, N, Q>::IndCalcB), 2350606433, 2767810950)
4380
    TB (kqqbkq, false, false, false, (T42<Q, Q, B, Q>::IndCalcW), (T42<Q, Q, B, Q>::IndCalcB), 2434987407, 2767810950)
4381
    TB (kqqrkq, false, false, false, (T42<Q, Q, R, Q>::IndCalcW), (T42<Q, Q, R, Q>::IndCalcB), 2415271436, 2767810950)
4382
    TB (kqqqkq, false, false, false, (T42<Q, Q, Q, Q>::IndCalcW), (T42<Q, Q, Q, Q>::IndCalcB),  736854363,  922603650)
4383
#if defined (T_INDEX64)
4384
    TB (krbnkn, false, false, false, (T42<R, B, N, N>::IndCalcW), (T42<R, B, N, N>::IndCalcB), 5356454122, 5675335080)
4385
    TB (kqbnkn, false, false, false, (T42<Q, B, N, N>::IndCalcW), (T42<Q, B, N, N>::IndCalcB), 5083836303, 5675335080)
4386
    TB (kqrnkn, false, false, false, (T42<Q, R, N, N>::IndCalcW), (T42<Q, R, N, N>::IndCalcB), 5042765577, 5675335080)
4387
    TB (kqrbkn, false, false, false, (T42<Q, R, B, N>::IndCalcW), (T42<Q, R, B, N>::IndCalcB), 5224919581, 5675335080)
4388
    TB (krbnkb, false, false, false, (T42<R, B, N, B>::IndCalcW), (T42<R, B, N, B>::IndCalcB), 5356454122, 5882853420)
4389
    TB (kqbnkb, false, false, false, (T42<Q, B, N, B>::IndCalcW), (T42<Q, B, N, B>::IndCalcB), 5083836303, 5882853420)
4390
    TB (kqrnkb, false, false, false, (T42<Q, R, N, B>::IndCalcW), (T42<Q, R, N, B>::IndCalcB), 5042765577, 5882853420)
4391
    TB (kqrbkb, false, false, false, (T42<Q, R, B, B>::IndCalcW), (T42<Q, R, B, B>::IndCalcB), 5224919581, 5882853420)
4392
    TB (krbnkr, false, false, false, (T42<R, B, N, R>::IndCalcW), (T42<R, B, N, R>::IndCalcB), 5356454122, 5838153840)
4393
    TB (kqbnkr, false, false, false, (T42<Q, B, N, R>::IndCalcW), (T42<Q, B, N, R>::IndCalcB), 5083836303, 5838153840)
4394
    TB (kqrnkr, false, false, false, (T42<Q, R, N, R>::IndCalcW), (T42<Q, R, N, R>::IndCalcB), 5042765577, 5838153840)
4395
    TB (kqrbkr, false, false, false, (T42<Q, R, B, R>::IndCalcW), (T42<Q, R, B, R>::IndCalcB), 5224919581, 5838153840)
4396
    TB (krbnkq, false, false, false, (T42<R, B, N, Q>::IndCalcW), (T42<R, B, N, Q>::IndCalcB), 5356454122, 5535621900)
4397
    TB (kqbnkq, false, false, true,  (T42<Q, B, N, Q>::IndCalcW), (T42<Q, B, N, Q>::IndCalcB), 5083836303, 5535621900)
4398
    TB (kqrnkq, false, false, false, (T42<Q, R, N, Q>::IndCalcW), (T42<Q, R, N, Q>::IndCalcB), 5042765577, 5535621900)
4399
    TB (kqrbkq, false, false, false, (T42<Q, R, B, Q>::IndCalcW), (T42<Q, R, B, Q>::IndCalcB), 5224919581, 5535621900)
4400
4401
    TB (kpppkp, false, true,  false, (T42<P, P, P, P>::IndCalcW), (T42<P, P, P, P>::IndCalcB),  1196695343,  1348100424)
4402
    TB (knppkp, false, true,  true,  (T42<N, P, P, P>::IndCalcW), (T42<N, P, P, P>::IndCalcB),  4796630713,  5271860528)
4403
    TB (knnpkp, false, false, true,  (T42<N, N, P, P>::IndCalcW), (T42<N, N, P, P>::IndCalcB),  6156616111,  6835422612)
4404
    TB (knnnkp, false, false, false, (T42<N, N, N, P>::IndCalcW), (T42<N, N, N, P>::IndCalcB),  2531022144,  2939087360)
4405
    TB (kbppkp, false, true,  true,  (T42<B, P, P, P>::IndCalcW), (T42<B, P, P, P>::IndCalcB),  4969303175,  5271860528)
4406
    TB (kbnpkp, false, true,  true,  (T42<B, N, P, P>::IndCalcW), (T42<B, N, P, P>::IndCalcB), 12979462304, 13670845224)
4407
    TB (kbnnkp, false, false, true,  (T42<B, N, N, P>::IndCalcW), (T42<B, N, N, P>::IndCalcB),  8146120416,  8817262080)
4408
    TB (kbbpkp, false, true,  true,  (T42<B, B, P, P>::IndCalcW), (T42<B, B, P, P>::IndCalcB),  6609838740,  6835422612)
4409
    TB (kbbnkp, false, false, true,  (T42<B, B, N, P>::IndCalcW), (T42<B, B, N, P>::IndCalcB),  8441899104,  8817262080)
4410
    TB (kbbbkp, false, false, false, (T42<B, B, B, P>::IndCalcW), (T42<B, B, B, P>::IndCalcB),  2816801280,  2939087360)
4411
    TB (krppkp, false, true,  true,  (T42<R, P, P, P>::IndCalcW), (T42<R, P, P, P>::IndCalcB),  4929998839,  5271860528)
4412
    TB (krnpkp, false, true,  true,  (T42<R, N, P, P>::IndCalcW), (T42<R, N, P, P>::IndCalcB), 12875424829, 13670845224)
4413
    TB (krnnkp, false, false, true,  (T42<R, N, N, P>::IndCalcW), (T42<R, N, N, P>::IndCalcB),  8079921360,  8817262080)
4414
    TB (krbpkp, false, true,  true,  (T42<R, B, P, P>::IndCalcW), (T42<R, B, P, P>::IndCalcB), 13340861520, 13670845224)
4415
    TB (krbnkp, false, false, true,  (T42<R, B, N, P>::IndCalcW), (T42<R, B, N, P>::IndCalcB), 17036639904, 17634524160)
4416
    TB (krbbkp, false, false, true,  (T42<R, B, B, P>::IndCalcW), (T42<R, B, B, P>::IndCalcB),  8677177872,  8817262080)
4417
    TB (krrpkp, false, true,  true,  (T42<R, R, P, P>::IndCalcW), (T42<R, R, P, P>::IndCalcB),  6504899238,  6835422612)
4418
    TB (krrnkp, false, false, true,  (T42<R, R, N, P>::IndCalcW), (T42<R, R, N, P>::IndCalcB),  8306047872,  8817262080)
4419
    TB (krrbkp, false, false, true,  (T42<R, R, B, P>::IndCalcW), (T42<R, R, B, P>::IndCalcB),  8607504960,  8817262080)
4420
    TB (krrrkp, false, false, false, (T42<R, R, R, P>::IndCalcW), (T42<R, R, R, P>::IndCalcB),  2749283520,  2939087360)
4421
    TB (kqppkp, false, true,  true,  (T42<Q, P, P, P>::IndCalcW), (T42<Q, P, P, P>::IndCalcB),  4677701571,  5271860528)
4422
    TB (kqnpkp, false, true,  true,  (T42<Q, N, P, P>::IndCalcW), (T42<Q, N, P, P>::IndCalcB), 12219736849, 13670845224)
4423
    TB (kqnnkp, false, false, true,  (T42<Q, N, N, P>::IndCalcW), (T42<Q, N, N, P>::IndCalcB),  7670559696,  8817262080)
4424
    TB (kqbpkp, false, true,  true,  (T42<Q, B, P, P>::IndCalcW), (T42<Q, B, P, P>::IndCalcB), 12658882024, 13670845224)
4425
    TB (kqbnkp, false, false, true,  (T42<Q, B, N, P>::IndCalcW), (T42<Q, B, N, P>::IndCalcB), 16170070752, 17634524160)
4426
    TB (kqbbkp, false, false, true,  (T42<Q, B, B, P>::IndCalcW), (T42<Q, B, B, P>::IndCalcB),  8234170512,  8817262080)
4427
    TB (kqrpkp, false, false, true,  (T42<Q, R, P, P>::IndCalcW), (T42<Q, R, P, P>::IndCalcB), 12557225406, 13670845224)
4428
    TB (kqrnkp, false, false, true,  (T42<Q, R, N, P>::IndCalcW), (T42<Q, R, N, P>::IndCalcB), 16038464256, 17634524160)
4429
    TB (kqrbkp, false, false, true,  (T42<Q, R, B, P>::IndCalcW), (T42<Q, R, B, P>::IndCalcB), 16617170832, 17634524160)
4430
    TB (kqrrkp, false, false, true,  (T42<Q, R, R, P>::IndCalcW), (T42<Q, R, R, P>::IndCalcB),  8101097520,  8817262080)
4431
    TB (kqqpkp, false, false, true,  (T42<Q, Q, P, P>::IndCalcW), (T42<Q, Q, P, P>::IndCalcB),  5851888362,  6835422612)
4432
    TB (kqqnkp, false, false, true,  (T42<Q, Q, N, P>::IndCalcW), (T42<Q, Q, N, P>::IndCalcB),  7476276864,  8817262080)
4433
    TB (kqqbkp, false, false, true,  (T42<Q, Q, B, P>::IndCalcW), (T42<Q, Q, B, P>::IndCalcB),  7744392000,  8817262080)
4434
    TB (kqqrkp, false, false, true,  (T42<Q, Q, R, P>::IndCalcW), (T42<Q, Q, R, P>::IndCalcB),  7680886080,  8817262080)
4435
    TB (kqqqkp, false, false, false, (T42<Q, Q, Q, P>::IndCalcW), (T42<Q, Q, Q, P>::IndCalcB),  2343300048,  2939087360)
4436
    TB (kpppkn, false, false, false, (T42<P, P, P, N>::IndCalcW), (T42<P, P, P, N>::IndCalcB),  1537640536,  1777129408)
4437
    TB (knppkn, false, false, true,  (T42<N, P, P, N>::IndCalcW), (T42<N, P, P, N>::IndCalcB),  6071020409,  6838084896)
4438
    TB (knnpkn, false, false, true,  (T42<N, N, P, N>::IndCalcW), (T42<N, N, P, N>::IndCalcB),  7677994559,  8729470080)
4439
    TB (kbppkn, false, false, true,  (T42<B, P, P, N>::IndCalcW), (T42<B, P, P, N>::IndCalcB),  6289527204,  6838084896)
4440
    TB (kbnpkn, false, false, true,  (T42<B, N, P, N>::IndCalcW), (T42<B, N, P, N>::IndCalcB), 16186823401, 17458940160)
4441
    TB (kbbpkn, false, false, true,  (T42<B, B, P, N>::IndCalcW), (T42<B, B, P, N>::IndCalcB),  8243187360,  8729470080)
4442
    TB (krppkn, false, false, true,  (T42<R, P, P, N>::IndCalcW), (T42<R, P, P, N>::IndCalcB),  6239761412,  6838084896)
4443
    TB (krnpkn, false, false, true,  (T42<R, N, P, N>::IndCalcW), (T42<R, N, P, N>::IndCalcB), 16057066825, 17458940160)
4444
    TB (krbpkn, false, false, true,  (T42<R, B, P, N>::IndCalcW), (T42<R, B, P, N>::IndCalcB), 16637490240, 17458940160)
4445
    TB (krrpkn, false, false, true,  (T42<R, R, P, N>::IndCalcW), (T42<R, R, P, N>::IndCalcB),  8112305064,  8729470080)
4446
    TB (kqppkn, false, false, true,  (T42<Q, P, P, N>::IndCalcW), (T42<Q, P, P, N>::IndCalcB),  5920486098,  6838084896)
4447
    TB (kqnpkn, false, false, true,  (T42<Q, N, P, N>::IndCalcW), (T42<Q, N, P, N>::IndCalcB), 15239383701, 17458940160)
4448
    TB (kqbpkn, false, false, true,  (T42<Q, B, P, N>::IndCalcW), (T42<Q, B, P, N>::IndCalcB), 15787021288, 17458940160)
4449
    TB (kqrpkn, false, false, true,  (T42<Q, R, P, N>::IndCalcW), (T42<Q, R, P, N>::IndCalcB), 15660230819, 17458940160)
4450
    TB (kqqpkn, false, false, true,  (T42<Q, Q, P, N>::IndCalcW), (T42<Q, Q, P, N>::IndCalcB),  7297961576,  8729470080)
4451
    TB (kpppkb, false, false, false, (T42<P, P, P, B>::IndCalcW), (T42<P, P, P, B>::IndCalcB),  1537640536,  1842024000)
4452
    TB (knppkb, false, false, true,  (T42<N, P, P, B>::IndCalcW), (T42<N, P, P, B>::IndCalcB),  6071020409,  7087788000)
4453
    TB (knnpkb, false, false, true,  (T42<N, N, P, B>::IndCalcW), (T42<N, N, P, B>::IndCalcB),  7677994559,  9048240000)
4454
    TB (kbppkb, false, false, true,  (T42<B, P, P, B>::IndCalcW), (T42<B, P, P, B>::IndCalcB),  6289527204,  7087788000)
4455
    TB (kbnpkb, false, false, true,  (T42<B, N, P, B>::IndCalcW), (T42<B, N, P, B>::IndCalcB), 16186823401, 18096480000)
4456
    TB (kbbpkb, false, false, true,  (T42<B, B, P, B>::IndCalcW), (T42<B, B, P, B>::IndCalcB),  8243187360,  9048240000)
4457
    TB (krppkb, false, false, true,  (T42<R, P, P, B>::IndCalcW), (T42<R, P, P, B>::IndCalcB),  6239761412,  7087788000)
4458
    TB (krnpkb, false, false, true,  (T42<R, N, P, B>::IndCalcW), (T42<R, N, P, B>::IndCalcB), 16057066825, 18096480000)
4459
 
4460
    TB (krrpkb, false, false, true,  (T42<R, R, P, B>::IndCalcW), (T42<R, R, P, B>::IndCalcB),  8112305064,  9048240000)
4461
    TB (kqppkb, false, false, true,  (T42<Q, P, P, B>::IndCalcW), (T42<Q, P, P, B>::IndCalcB),  5920486098,  7087788000)
4462
    TB (kqnpkb, false, false, true,  (T42<Q, N, P, B>::IndCalcW), (T42<Q, N, P, B>::IndCalcB), 15239383701, 18096480000)
4463
    TB (kqbpkb, false, false, true,  (T42<Q, B, P, B>::IndCalcW), (T42<Q, B, P, B>::IndCalcB), 15787021288, 18096480000)
4464
    TB (kqrpkb, false, false, true,  (T42<Q, R, P, B>::IndCalcW), (T42<Q, R, P, B>::IndCalcB), 15660230819, 18096480000)
4465
 
4466
    TB (kpppkr, false, false, false, (T42<P, P, P, R>::IndCalcW), (T42<P, P, P, R>::IndCalcB),  1537640536,  1827875872)
4467
    TB (knppkr, false, false, true,  (T42<N, P, P, R>::IndCalcW), (T42<N, P, P, R>::IndCalcB),  6071020409,  7033481568)
4468
    TB (knnpkr, false, false, true,  (T42<N, N, P, R>::IndCalcW), (T42<N, N, P, R>::IndCalcB),  7677994559,  8978912640)
4469
    TB (kbppkr, false, true,  true,  (T42<B, P, P, R>::IndCalcW), (T42<B, P, P, R>::IndCalcB),  6289527204,  7033481568)
4470
    TB (kbnpkr, false, true,  true,  (T42<B, N, P, R>::IndCalcW), (T42<B, N, P, R>::IndCalcB), 16186823401, 17957825280)
4471
 
4472
    TB (krppkr, false, false, true,  (T42<R, P, P, R>::IndCalcW), (T42<R, P, P, R>::IndCalcB),  6239761412,  7033481568)
4473
 
4474
    TB (krbpkr, false, false, true,  (T42<R, B, P, R>::IndCalcW), (T42<R, B, P, R>::IndCalcB), 16637490240, 17957825280)
4475
 
4476
    TB (kqppkr, false, false, true,  (T42<Q, P, P, R>::IndCalcW), (T42<Q, P, P, R>::IndCalcB),  5920486098,  7033481568)
4477
    TB (kqnpkr, false, false, true,  (T42<Q, N, P, R>::IndCalcW), (T42<Q, N, P, R>::IndCalcB), 15239383701, 17957825280)
4478
    TB (kqbpkr, false, false, true,  (T42<Q, B, P, R>::IndCalcW), (T42<Q, B, P, R>::IndCalcB), 15787021288, 17957825280)
4479
 
4480
    TB (kqqpkr, false, false, true,  (T42<Q, Q, P, R>::IndCalcW), (T42<Q, Q, P, R>::IndCalcB),  7297961576,  8978912640)
4481
    TB (kpppkq, false, true,  false, (T42<P, P, P, Q>::IndCalcW), (T42<P, P, P, Q>::IndCalcB),  1537640536,  1733232160)
4482
    TB (knppkq, false, true,  true,  (T42<N, P, P, Q>::IndCalcW), (T42<N, P, P, Q>::IndCalcB),  6071020409,  6669309024)
4483
    TB (knnpkq, false, false, true,  (T42<N, N, P, Q>::IndCalcW), (T42<N, N, P, Q>::IndCalcB),  7677994559,  8514011520)
4484
    TB (kbppkq, false, true,  true,  (T42<B, P, P, Q>::IndCalcW), (T42<B, P, P, Q>::IndCalcB),  6289527204,  6669309024)
4485
    TB (kbnpkq, false, true,  true,  (T42<B, N, P, Q>::IndCalcW), (T42<B, N, P, Q>::IndCalcB), 16186823401, 17028023040)
4486
    TB (kbbpkq, false, true,  true,  (T42<B, B, P, Q>::IndCalcW), (T42<B, B, P, Q>::IndCalcB),  8243187360,  8514011520)
4487
 
4488
    TB (krnpkq, false, true,  true,  (T42<R, N, P, Q>::IndCalcW), (T42<R, N, P, Q>::IndCalcB), 16057066825, 17028023040)
4489
 
4490
    TB (krrpkq, false, true,  true,  (T42<R, R, P, Q>::IndCalcW), (T42<R, R, P, Q>::IndCalcB),  8112305064,  8514011520)
4491
 
4492
    TB (kqnpkq, false, true,  true,  (T42<Q, N, P, Q>::IndCalcW), (T42<Q, N, P, Q>::IndCalcB), 15239383701, 17028023040)
4493
    TB (kqbpkq, false, true,  true,  (T42<Q, B, P, Q>::IndCalcW), (T42<Q, B, P, Q>::IndCalcB), 15787021288, 17028023040)
4494
    TB (kqrpkq, false, true,  true,  (T42<Q, R, P, Q>::IndCalcW), (T42<Q, R, P, Q>::IndCalcB), 15660230819, 17028023040)
4495
    TB (kqqpkq, false, false, true,  (T42<Q, Q, P, Q>::IndCalcW), (T42<Q, Q, P, Q>::IndCalcB),  7297961576,  8514011520)
4496
4497
#endif
4498
 
4499
    };
4500
4501
#undef  P
4502
 
4503
#undef  B
4504
#undef  R
4505
#undef  Q
4506
4507
//  Helper structure
4508
 
4509
4510
 
4511
    {
4512
    int             m_iDesc;            // Negative if have to inverse
4513
    int             m_cPieces;
4514
    CUTbReference   *m_utbReference;
4515
    };
4516
4517
//  Root of the search tree
4518
4519
 
4520
4521
// Convert TB name (e.g. KQKR) into set of counters
4522
4523
static const char *PchSetHalfCounters
4524
    (
4525
    int         *piCounters,
4526
    const char  *pch
4527
    )
4528
    {
4529
    memset (piCounters, 0, 5 * sizeof (int));
4530
    while ('\0' != *pch && 'k' != *pch)
4531
        {
4532
        piece pi;
4533
4534
        pi = x_piecePawn;   // To make compiler happy
4535
        switch (*pch)
4536
            {
4537
        case 'p':
4538
            pi = x_piecePawn;
4539
 
4540
        case 'n':
4541
            pi = x_pieceKnight;
4542
            break;
4543
        case 'b':
4544
            pi = x_pieceBishop;
4545
            break;
4546
        case 'r':
4547
            pi = x_pieceRook;
4548
            break;
4549
        case 'q':
4550
 
4551
            break;
4552
        default:
4553
            assert (0);
4554
            }
4555
        piCounters [pi-1] ++;
4556
 
4557
        }
4558
        return pch;
4559
    };
4560
 
4561
static void VSetCounters
4562
    (
4563
    int         *piCounters,
4564
    const char  *pch
4565
    )
4566
 
4567
    assert ('k' == *pch);
4568
    pch = PchSetHalfCounters (piCounters, pch+1);
4569
    assert ('k' == *pch);
4570
    pch = PchSetHalfCounters (piCounters+5, pch+1);
4571
    assert ('\0' == *pch);
4572
    }
4573
4574
//  Following functions return TB index
4575
//  They differ by input arguments
4576
4577
extern "C" int IDescFindFromCounters
4578
    (
4579
    int *piCount
4580
    )
4581
    {
4582
    CUTbReference *putbr = rgutbReference;
4583
4584
    if (piCount[0] > putbr->m_cPieces)
4585
        goto not_found;
4586
    putbr = putbr[1 + piCount[0]].m_utbReference;
4587
    if (piCount[1] > putbr->m_cPieces)
4588
        goto not_found;
4589
    putbr = putbr[1 + piCount[1]].m_utbReference;
4590
    if (piCount[2] > putbr->m_cPieces)
4591
        goto not_found;
4592
    putbr = putbr[1 + piCount[2]].m_utbReference;
4593
    if (piCount[3] > putbr->m_cPieces)
4594
        goto not_found;
4595
    putbr = putbr[1 + piCount[3]].m_utbReference;
4596
    if (piCount[4] > putbr->m_cPieces)
4597
 
4598
    putbr = putbr[1 + piCount[4]].m_utbReference;
4599
    if (piCount[5] > putbr->m_cPieces)
4600
        goto not_found;
4601
    putbr = putbr[1 + piCount[5]].m_utbReference;
4602
    if (piCount[6] > putbr->m_cPieces)
4603
        goto not_found;
4604
    putbr = putbr[1 + piCount[6]].m_utbReference;
4605
    if (piCount[7] > putbr->m_cPieces)
4606
        goto not_found;
4607
    putbr = putbr[1 + piCount[7]].m_utbReference;
4608
    if (piCount[8] > putbr->m_cPieces)
4609
        goto not_found;
4610
    putbr = putbr[1 + piCount[8]].m_utbReference;
4611
    if (piCount[9] <= putbr->m_cPieces)
4612
        return putbr[1 + piCount[9]].m_iDesc;
4613
not_found:
4614
    return 0;
4615
    }
4616
4617
int IDescFind
4618
    (
4619
    square  *p_piW, // IN | Pointer to array of white pieces (king excluded)
4620
    square  *p_piB, // IN | Pointer to array of black pieces (king excluded)
4621
    int     cWhite, // IN | Counter of white pieces (king excluded)
4622
    int     cBlack  // IN | Counter of black pieces (king excluded)
4623
    )
4624
    {
4625
    int rgiCount[10];
4626
4627
    // Set pieces counters
4628
    rgiCount[0] =
4629
    rgiCount[1] =
4630
    rgiCount[2] =
4631
    rgiCount[3] =
4632
    rgiCount[4] =
4633
    rgiCount[5] =
4634
    rgiCount[6] =
4635
    rgiCount[7] =
4636
    rgiCount[8] =
4637
    rgiCount[9] = 0;
4638
    while (cWhite)
4639
        {
4640
        rgiCount[(*p_piW)-1] ++;
4641
        p_piW ++;
4642
        cWhite --;
4643
        }
4644
    while (cBlack)
4645
        {
4646
        rgiCount[5-1+(*p_piB)] ++;
4647
        p_piB ++;
4648
        cBlack --;
4649
        }
4650
    return IDescFindFromCounters (rgiCount);
4651
    }
4652
4653
int IDescFindByName
4654
    (
4655
    char    *pchName
4656
    )
4657
    {
4658
    int rgiCount[10];
4659
4660
    VSetCounters (rgiCount, pchName);
4661
    return IDescFindFromCounters (rgiCount);
4662
    }
4663
4664
//-----------------------------------------------------------------------------
4665
//
4666
//  Function used during initialization
4667
4668
//  Set of functions to create search table
4669
4670
static CUTbReference *PutbrCreateSubtable
4671
    (
4672
    int cPieces,    //  IN | # of pieces ramaining on board
4673
    int iDepth      //  IN | Recursion depth (# of piece classes left)
4674
    )
4675
    {
4676
    CUTbReference *putbr;
4677
 
4678
    putbr = (CUTbReference *) PvMalloc ((cPieces + 2) * sizeof (CUTbReference));
4679
    putbr[0].m_cPieces = cPieces;
4680
    if (0 == iDepth)
4681
        {
4682
        for (int i = 0; i <= cPieces; i ++)
4683
            putbr[i+1].m_iDesc = 0;
4684
        }
4685
    else
4686
        {
4687
        for (int i = 0; i <= cPieces; i ++)
4688
            putbr[i+1].m_utbReference = PutbrCreateSubtable (cPieces-i, iDepth-1);
4689
        }
4690
    return putbr;
4691
    }
4692
4693
static bool fTbTableCreated = false;
4694
4695
static void VCreateEmptyTbTable (void)
4696
    {
4697
    if (fTbTableCreated)
4698
        return;
4699
    fTbTableCreated = true;
4700
    rgutbReference[0].m_cPieces = MAX_NON_KINGS;
4701
    for (int i = 0; i <= MAX_NON_KINGS; i ++)
4702
        rgutbReference[i+1].m_utbReference = PutbrCreateSubtable (MAX_NON_KINGS - i, 8);
4703
    }
4704
4705
// Insert TB (e.g. KQKR) into search table
4706
4707
static bool FRegisterHalf
4708
    (
4709
    int     iTb,
4710
    int     *piCount
4711
    )
4712
    {
4713
    CUTbReference   *putbr;
4714
4715
 
4716
    for (int i = 0; i < 9; i ++)
4717
        {
4718
        if (piCount[i] > putbr->m_cPieces)
4719
            return false;
4720
        putbr = putbr[1 + piCount[i]].m_utbReference;
4721
        }
4722
    if (piCount[9] > putbr->m_cPieces)
4723
        return false;
4724
    putbr[1 + piCount[9]].m_iDesc = iTb;
4725
    return true;
4726
    }
4727
4728
// Insert TB (both, e.g. KQKR and KRKQ) into search table
4729
4730
static bool FRegisterTb
4731
    (
4732
    CTbDesc *ptbDesc
4733
    )
4734
    {
4735
    int     rgiCount[10];
4736
    bool    fInserted;
4737
4738
    VSetCounters (rgiCount, ptbDesc->m_rgchName);
4739
    fInserted = FRegisterHalf (ptbDesc->m_iTbId, rgiCount);
4740
    if (fInserted)
4741
        {
4742
        if (ptbDesc->m_fSymmetric)
4743
            return true;
4744
        for (int i = 0; i < 5; i ++)
4745
            {
4746
            int iTemp;
4747
4748
            iTemp = rgiCount[i];
4749
            rgiCount[i] = rgiCount[i+5];
4750
            rgiCount[i+5] = iTemp;
4751
            }
4752
        fInserted = FRegisterHalf (-ptbDesc->m_iTbId, rgiCount);
4753
        assert (fInserted);
4754
        }
4755
    return fInserted;
4756
    }
4757
4758
// File mapping - Win32 code only
4759
4760
#if defined (_WIN32) || defined(_WIN64)
4761
4762
static BYTE * PbMapFileForRead
4763
    (
4764
    char    *szName,
4765
    HANDLE  *phFile,
4766
    HANDLE  *phFileMapping
4767
    )
4768
    {
4769
    HANDLE  hFile;
4770
    HANDLE  hFileMapping;
4771
    LPVOID  lpFileBase;
4772
4773
 
4774
                        NULL, OPEN_EXISTING,
4775
                        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
4776
    if (INVALID_HANDLE_VALUE == hFile)
4777
        {
4778
        printf("*** Couldn't open file %s with CreateFile()\n", szName);
4779
        exit (1);
4780
        }
4781
    hFileMapping = CreateFileMapping (hFile, NULL, PAGE_READONLY, 0, 0, NULL);
4782
    if (0 == hFileMapping)
4783
        {
4784
        CloseHandle (hFile);
4785
        printf ("*** Couldn't open file %s mapping with CreateFileMapping()\n", szName);
4786
        exit (1);
4787
        }
4788
    lpFileBase = MapViewOfFile (hFileMapping, FILE_MAP_READ, 0, 0, 0);
4789
    if (0 == lpFileBase)
4790
        {
4791
        CloseHandle (hFileMapping);
4792
        CloseHandle (hFile);
4793
        printf ("*** Couldn't map view of file %s with MapViewOfFile()\n", szName);
4794
        exit (1);
4795
        }
4796
    if (NULL != phFile)
4797
        *phFile = hFile;
4798
    if (NULL != phFileMapping)
4799
        *phFileMapping = hFileMapping;
4800
    return (BYTE*) lpFileBase;
4801
    }
4802
4803
static void VUnmapFile
4804
    (
4805
    BYTE    *pbFileBase,
4806
    HANDLE  hFile,
4807
    HANDLE  hFileMapping
4808
    )
4809
    {
4810
    BOOL fFailed;
4811
4812
    fFailed = (0 == UnmapViewOfFile (pbFileBase)) |
4813
              (0 == CloseHandle (hFileMapping)) |
4814
              (0 == CloseHandle (hFile));
4815
    if (fFailed)
4816
        {
4817
        printf ("*** Couldn't unmap file\n");
4818
        exit (1);
4819
        }
4820
    }
4821
4822
#endif
4823
4824
//-----------------------------------------------------------------------------
4825
//
4826
//  TB caching
4827
4828
#if !defined (TB_CB_CACHE_CHUNK)
4829
#define TB_CB_CACHE_CHUNK           8192 /* Must be power of 2 */
4830
#define LOG2_TB_CB_CACHE_CHUNK      13
4831
#endif
4832
4833
#define TB_CHUNK(index)             ((index) >> LOG2_TB_CB_CACHE_CHUNK)
4834
#define TB_OFFSET(index)            ((index) % TB_CB_CACHE_CHUNK)
4835
#define TB_DIRECTORY_ENTRY(chunk)   ((chunk) % TB_DIRECTORY_SIZE)
4836
4837
#define WIDE_TB_CHUNK(index)        ((index) >> (LOG2_TB_CB_CACHE_CHUNK-1))
4838
#define WIDE_TB_OFFSET(index)       ((index) % (TB_CB_CACHE_CHUNK/2))*2
4839
4840
struct CTbCache         //Hungarian: tbc
4841
 
4842
    int volatile                m_iTb;
4843
    color volatile              m_color;
4844
    unsigned volatile           m_indChunk;
4845
    volatile CTbCache *volatile m_ptbcNext;     // Next element in double-linked general LRU list
4846
    volatile CTbCache *volatile m_ptbcPrev;     // Previous element in double-linked general LRU list
4847
    volatile CTbCache *volatile m_ptbcTbNext;   // Next element in double-linked cache bucket LRU list
4848
    volatile CTbCache *volatile m_ptbcTbPrev;   // Previous element in double-linked cache bucket LRU list
4849
    BYTE                        *m_pbData;
4850
    };
4851
4852
static CTbCache *ptbcTbCache;   // Cache memory
4853
static ULONG    ctbcTbCache;    // Cache size (in entries)
4854
4855
static volatile CTbCache * volatile ptbcHead;       // Head of that list
4856
static volatile CTbCache * volatile ptbcTail;       // Last element in that list
4857
static volatile CTbCache * volatile ptbcFree;       // First free cache header
4858
4859
static INLINE void VTbCloseFile
4860
    (
4861
    int     iTb,
4862
    color   side
4863
    )
4864
    {
4865
    for (int iExtent = 0; iExtent < MAX_EXTENTS; iExtent ++) {
4866
        if (NULL != rgtbdDesc[iTb].m_rgfpFiles[side][iExtent])
4867
            {
4868
            Lock (rgtbdDesc[iTb].m_rglockFiles[side]);
4869
            if (NULL != rgtbdDesc[iTb].m_rgfpFiles[side][iExtent])
4870
                {
4871
                fclose (rgtbdDesc[iTb].m_rgfpFiles[side][iExtent]);
4872
                rgtbdDesc[iTb].m_rgfpFiles[side][iExtent] = NULL;
4873
                }
4874
            Unlock (rgtbdDesc[iTb].m_rglockFiles[side]);
4875
            }
4876
        }
4877
    }
4878
4879
extern "C" void VTbCloseFiles (void)
4880
    {
4881
    // Initialized?
4882
    if (0 == ctbcTbCache)
4883
        return;
4884
4885
    // Walk through TB cache and close all opened files
4886
    for (int iTb = 1; iTb < cTb; iTb ++)
4887
        {
4888
        VTbCloseFile (iTb, x_colorWhite);
4889
        VTbCloseFile (iTb, x_colorBlack);
4890
        }
4891
    }
4892
4893
void VTbClearCache (void)
4894
    {
4895
    CTbCacheBucket  *prgtbcbBuckets;
4896
    CTbCache *ptbc;
4897
    BYTE *pb;
4898
    ULONG i;
4899
4900
    // Initialized?
4901
    if (0 == ctbcTbCache)
4902
        return;
4903
    VTbCloseFiles();
4904
   
4905
    // Initialize all lists
4906
    pb = (BYTE *) & ptbcTbCache [ctbcTbCache];
4907
    for (i = 0, ptbc = ptbcTbCache; i < ctbcTbCache; i ++, ptbc ++)
4908
        {
4909
        ptbc->m_pbData = pb + i*(TB_CB_CACHE_CHUNK+32+4);
4910
        ptbc->m_ptbcTbPrev =
4911
        ptbc->m_ptbcTbNext =
4912
        ptbc->m_ptbcPrev = NULL;
4913
        ptbc->m_ptbcNext = (ptbc + 1);
4914
        }
4915
    ptbc[-1].m_ptbcNext = NULL;
4916
4917
    // Clear references from TBs
4918
    for (int iTb = 1; iTb < cTb; iTb ++)
4919
        {
4920
        for (color sd=x_colorWhite; sd <= x_colorBlack; sd ++)
4921
            {
4922
            prgtbcbBuckets = rgtbdDesc[iTb].m_prgtbcbBuckets[sd];
4923
            if (NULL != prgtbcbBuckets)
4924
 
4925
#if (CPUS > 1)
4926
                for (i = 0; i < TB_DIRECTORY_SIZE; i ++)
4927
                    LockFree (prgtbcbBuckets[i].m_lock);
4928
#endif
4929
                memset (prgtbcbBuckets, 0, TB_DIRECTORY_SIZE * sizeof (CTbCacheBucket));
4930
#if (CPUS > 1)
4931
                for (i = 0; i < TB_DIRECTORY_SIZE; i ++)
4932
                    LockInit (prgtbcbBuckets[i].m_lock);
4933
#endif
4934
                }
4935
            }
4936
        }
4937
4938
    // Set globals
4939
    ptbcHead = ptbcTail = NULL;
4940
    ptbcFree = ptbcTbCache;
4941
    }
4942
4943
extern "C" int FTbSetCacheSize
4944
    (
4945
    void    *pv,
4946
    ULONG   cbSize
4947
    )
4948
    {
4949
    VTbCloseFiles();
4950
    ctbcTbCache = 0;
4951
    ptbcHead = NULL;
4952
    if (cbSize < sizeof (CTbCache))
4953
        return false;
4954
    ptbcTbCache = (CTbCache*) pv;
4955
    ctbcTbCache = cbSize / (sizeof (CTbCache) + TB_CB_CACHE_CHUNK+32+4);
4956
    VTbClearCache();
4957
    return true;
4958
    }
4959
4960
// Table registered
4961
4962
INLINE int FRegisteredExtent
4963
    (
4964
    int     iTb,
4965
    color   side,
4966
    int     iExtent
4967
    )
4968
    {
4969
    if (rgtbdDesc[iTb].m_fSymmetric)
4970
        side = x_colorWhite;
4971
    return (NULL != rgtbdDesc[iTb].m_rgpchFileName[side][iExtent]);
4972
    }
4973
4974
INLINE int FRegistered
4975
    (
4976
    int     iTb,
4977
    color   side
4978
    )
4979
    {
4980
    int iExtent, cExtents;
4981
    INDEX cBytes;
4982
4983
    if (rgtbdDesc[iTb].m_fSplit)
4984
        {
4985
        cBytes = rgtbdDesc[iTb].m_rgcbLength[side];
4986
        if (rgtbdDesc[iTb].m_f16bit)
4987
            cBytes *= 2;
4988
        cExtents = (int) (cBytes >> 31) + 1;
4989
        }
4990
    else
4991
        cExtents = 1;
4992
    for (iExtent = 0; iExtent < cExtents; iExtent ++)
4993
        {
4994
        if (FRegisteredExtent (iTb, side, iExtent))
4995
            return true;
4996
        }
4997
    return false;
4998
    }
4999
5000
extern "C" int FRegisteredFun
5001
    (
5002
    int     iTb,
5003
    color   side
5004
    )
5005
    {
5006
    return FRegistered (iTb, side);
5007
    }
5008
5009
// Return function that calculates the necessary index:
5010
5011
#define PfnIndCalc(iTb, side)   (rgtbdDesc[iTb].m_rgpfnCalcIndex[side])
5012
extern "C" PfnCalcIndex PfnIndCalcFun
5013
    (
5014
    int     iTb,
5015
    color   side
5016
    )
5017
    {
5018
    return PfnIndCalc (iTb, side);
5019
    }
5020
 
5021
// Read whole file into memory
5022
5023
extern "C" int FReadTableToMemory
5024
 
5025
    int     iTb,    // IN | Tablebase
5026
    color   side,   // IN | Side to move
5027
    BYTE    *pb     // IN | Either buffer or NULL
5028
    )
5029
    {
5030
 
5031
    INDEX   cb;
5032
    FILE    *fp;
5033
 
5034
    if (rgtbdDesc[iTb].m_fSymmetric)
5035
        side = x_colorWhite;
5036
    if (!FRegistered (iTb, side))
5037
        return false;
5038
    if (rgtbdDesc[iTb].m_fSplit)
5039
        return false;
5040
 
5041
        {
5042
 
5043
            return false;
5044
 
5045
    if (NULL != rgtbdDesc[iTb].m_rgpbRead[side])
5046
 
5047
    pszName = rgtbdDesc[iTb].m_rgpchFileName[side][0];
5048
    fp = fopen (pszName, "rb");
5049
    if (NULL == fp)
5050
        return false;
5051
5052
    // Find database size
5053
#if defined (NEW)
5054
    cb = rgtbdDesc[iTb].m_rgcbLength[side];
5055
    if (0 == cb)
5056
        {
5057
 
5058
        if (0 != fseek (fp, 0L, SEEK_END))
5059
            {
5060
            printf ("*** Seek in %s failed\n", pszName);
5061
            exit (1);
5062
            }
5063
        cb = ftell (fp);
5064
        if (-1 == (int) cb)
5065
            {
5066
            printf ("*** Cannot find length of %s\n", pszName);
5067
            exit (1);
5068
            }
5069
        if (0 != fseek (fp, 0L, SEEK_SET))
5070
            {
5071
            printf ("*** Seek in %s failed\n", pszName);
5072
            exit (1);
5073
            }
5074
#if defined (NEW)
5075
        }
5076
#if defined (T33_INCLUDE) || defined (KPPKP_16BIT)
5077
    else if (rgtbdDesc[iTb].m_f16bit)
5078
        {
5079
        if ((size_t) cb != cb)   // Overflow
5080
            {
5081
            printf ("*** %s too big to read into memory\n", pszName);
5082
            exit (1);
5083
            }
5084
 
5085
#endif
5086
#endif
5087
   
5088
    // If buffer not specified, allocate memory for it
5089
    if (NULL == pb)
5090
        pb = (BYTE*) PvMalloc ((size_t) cb); // Pierre-Marie Baty -- added type cast
5091
5092
    // Read file into memory
5093
    if (cb != (INDEX) fread (pb, 1, (size_t) cb, fp)) // Pierre-Marie Baty -- added type cast
5094
        {
5095
        printf ("*** Read from %s failed\n", pszName);
5096
        exit (1);
5097
 
5098
    fclose (fp);
5099
5100
 
5101
    rgtbdDesc[iTb].m_rgpbRead[side] = pb;
5102
    return true;
5103
    }
5104
5105
#if defined (_WIN32) || defined(_WIN64)
5106
5107
 
5108
5109
extern "C" int FMapTableToMemory
5110
    (
5111
    int     iTb,    // IN | Tablebase
5112
    color   side    // IN | Side to move
5113
    )
5114
    {
5115
    char *pszName;
5116
5117
    if (rgtbdDesc[iTb].m_fSymmetric)
5118
        side = x_colorWhite;
5119
    if (!FRegistered (iTb, side))
5120
        return false;
5121
    if (rgtbdDesc[iTb].m_fSplit)
5122
        return false;
5123
    for (int iExtent = 0; iExtent < MAX_EXTENTS; iExtent ++)
5124
        {
5125
        if (NULL != rgtbdDesc[iTb].m_rgpdiDecodeInfo[side][iExtent])
5126
            return false;
5127
        }
5128
    pszName = rgtbdDesc[iTb].m_rgpchFileName[side][0];
5129
    if (NULL == rgtbdDesc[iTb].m_rgpbRead[side])
5130
        {
5131
        rgtbdDesc[iTb].m_rgpbRead[side] = PbMapFileForRead (pszName, NULL, NULL);
5132
        if (fVerbose)
5133
            printf ("%s mapped\n", pszName);
5134
        }
5135
    return true;
5136
    }
5137
5138
// Map whole file into memory
5139
5140
 
5141
    (
5142
    int     iTb,            // IN  | Tablebase
5143
    color   side,           // IN  | Side to move
5144
    HANDLE  *phFile,        // OUT | File handle will be written here
5145
    HANDLE  *phFileMapping  // OUT | File mapping handle will be written here
5146
    )
5147
    {
5148
    char *pszName;
5149
5150
 
5151
        side = x_colorWhite;
5152
    if (!FRegistered (iTb, side))
5153
        return false;
5154
    if (rgtbdDesc[iTb].m_fSplit)
5155
        return false;
5156
    pszName = rgtbdDesc[iTb].m_rgpchFileName[side][0];
5157
    if (NULL == rgtbdDesc[iTb].m_rgpbRead[side])
5158
        {
5159
        rgtbdDesc[iTb].m_rgpbRead[side] = PbMapFileForRead (pszName, phFile, phFileMapping);
5160
        if (fVerbose)
5161
            printf ("%s mapped\n", pszName);
5162
        }
5163
    return true;
5164
    }
5165
5166
// Unmap whole file from memory
5167
5168
int FUnMapTableFromMemory
5169
    (
5170
    int     iTb,            // IN | Tablebase
5171
    color   side,           // IN | Side to move
5172
    HANDLE  hFile,          // IN | File handle will be written here
5173
    HANDLE  hFileMapping    // IN | File mapping handle will be written here
5174
    )
5175
    {
5176
 
5177
5178
    if (rgtbdDesc[iTb].m_fSymmetric)
5179
        side = x_colorWhite;
5180
    if (!FRegistered (iTb, side))
5181
        return false;
5182
    if (rgtbdDesc[iTb].m_fSplit)
5183
 
5184
    pszName = rgtbdDesc[iTb].m_rgpchFileName[side][0];
5185
    if (NULL != rgtbdDesc[iTb].m_rgpbRead[side])
5186
        {
5187
 
5188
        rgtbdDesc[iTb].m_rgpbRead[side] = NULL;
5189
        if (fVerbose)
5190
            printf ("%s unmapped\n", pszName);
5191
 
5192
    return true;
5193
 
5194
5195
#endif
5196
5197
// Probe TB - lower level (not exportable) function
5198
5199
static int TB_FASTCALL TbtProbeTable
5200
    (
5201
 
5202
    color    side,
5203
    unsigned indChunk,
5204
    unsigned indInChunk
5205
    )
5206
    {
5207
    CTbDesc *ptbd;
5208
    int iDirectory, iExtent, iPhysicalChunk;
5209
    volatile CTbCache * ptbc;
5210
    volatile CTbCache * ptbcTbFirst;
5211
    const char *pszFileName;
5212
5213
    ptbd = & rgtbdDesc[iTb];
5214
    iDirectory = TB_DIRECTORY_ENTRY (indChunk);
5215
5216
 
5217
    Lock (ptbd->m_prgtbcbBuckets[side][iDirectory].m_lock);
5218
 
5219
5220
    // First, search entry in the cache
5221
    for (ptbc = ptbcTbFirst; NULL != ptbc; ptbc = ptbc->m_ptbcTbNext)
5222
        {
5223
        if (indChunk == ptbc->m_indChunk)
5224
            {
5225
            // Found - move cache entry to the head of the general LRU list
5226
            Lock (lockLRU);
5227
            if (ptbc != ptbcHead)
5228
 
5229
                // Remove it from its current position
5230
 
5231
                if (NULL == ptbc->m_ptbcNext)
5232
                    ptbcTail = ptbc->m_ptbcPrev;
5233
                else
5234
                    ptbc->m_ptbcNext->m_ptbcPrev = ptbc->m_ptbcPrev;
5235
                // Insert it at the head
5236
                ptbc->m_ptbcPrev = NULL;
5237
                ptbc->m_ptbcNext = ptbcHead;
5238
 
5239
                ptbcHead = ptbc;
5240
                }
5241
            Unlock (lockLRU);
5242
            // Move cache entry to the head of the cache bucket LRU list
5243
            if (ptbc != ptbcTbFirst)
5244
                {
5245
                // Remove it from list
5246
                ptbc->m_ptbcTbPrev->m_ptbcTbNext = ptbc->m_ptbcTbNext;
5247
                if (NULL != ptbc->m_ptbcTbNext)
5248
                    ptbc->m_ptbcTbNext->m_ptbcTbPrev = ptbc->m_ptbcTbPrev;
5249
                // Insert it at head
5250
                ptbc->m_ptbcTbPrev = NULL;
5251
 
5252
                ptbcTbFirst->m_ptbcTbPrev = ptbc;
5253
 
5254
                }
5255
            int tb;
5256
5257
            tb = (tb_t) (ptbc->m_pbData[(ULONG)indInChunk]);
5258
            Unlock (ptbd->m_prgtbcbBuckets[side][iDirectory].m_lock);
5259
            return tb;
5260
            }
5261
 
5262
    // Not in the cache - have to read it from disk.
5263
    // I decided to write simple code - so sometimes it's possible that
5264
    // 2 threads will simultaneously read exactly the same chunk into 2
5265
    // different cache entries. In that case, all subsequent cache probes
5266
    // will hit the first cache entry, so the second one will 'drift' to
5267
    // the end of general LRU list and will be reused.
5268
5269
    // Unlock cache bucket, so other threads can continue execution
5270
    Unlock (ptbd->m_prgtbcbBuckets[side][iDirectory].m_lock);
5271
 
5272
    Lock (lockLRU);
5273
    // Get it either from a free list, or reuse last element of the LRU list
5274
    if (NULL != ptbcFree)
5275
        {
5276
        ptbc = ptbcFree;
5277
        ptbcFree = ptbc->m_ptbcNext;
5278
        Unlock (lockLRU);
5279
        }
5280
    else
5281
 
5282
        unsigned iTailDirectory;
5283
 
5284
        color    colorTail;
5285
 
5286
        assert (NULL != ptbcTail);
5287
#if (CPUS > 1)
5288
        // "Optimistic" model - assuming that there is low content
5289
        // (not hundreds of threads)
5290
        for (;;)
5291
            {
5292
            ptbc = ptbcTail;
5293
            iTailTb = ptbc->m_iTb;
5294
            iTailDirectory = TB_DIRECTORY_ENTRY (ptbc->m_indChunk);
5295
            colorTail = ptbc->m_color;
5296
 
5297
            // and only then general LRU lock. So, free general LRU lock and
5298
            // acquire 2 locks in a proper order.
5299
            Unlock (lockLRU);
5300
            Lock (rgtbdDesc[iTailTb].m_prgtbcbBuckets[colorTail][iTailDirectory].m_lock);
5301
            Lock (lockLRU);
5302
            // Have structures been modified while we re-acquired locks? 
5303
            // (to be more precise, it's Ok, if structures were modified,
5304
            // but cache entry again become the last element of the list,
5305
            // and TB, color, and cache bucket did not changed, so we locked
5306
            // proper locks).
5307
            if (ptbc == ptbcTail && ptbc->m_iTb == iTailTb &&
5308
                ptbc->m_color == colorTail &&
5309
                TB_DIRECTORY_ENTRY (ptbc->m_indChunk) == iTailDirectory)
5310
                break;
5311
            // Sorry - try once again...
5312
            Unlock (rgtbdDesc[iTailTb].m_prgtbcbBuckets[colorTail][iTailDirectory].m_lock);
5313
            }
5314
#else
5315
        ptbc = ptbcTail;
5316
        iTailTb = ptbc->m_iTb;
5317
        iTailDirectory = TB_DIRECTORY_ENTRY (ptbc->m_indChunk);
5318
        colorTail = ptbc->m_color;
5319
#endif
5320
5321
        // Remove cache entry from the general LRU list
5322
        ptbcTail = ptbc->m_ptbcPrev;
5323
        if (NULL == ptbcTail)
5324
            ptbcHead = NULL;
5325
        else
5326
 
5327
        Unlock (lockLRU);
5328
       
5329
        // Remove it from cache bucket list
5330
        if (NULL != ptbc->m_ptbcTbNext)
5331
            ptbc->m_ptbcTbNext->m_ptbcTbPrev = ptbc->m_ptbcTbPrev;
5332
        if (NULL == ptbc->m_ptbcTbPrev)
5333
            rgtbdDesc[iTailTb].m_prgtbcbBuckets[colorTail][iTailDirectory].m_ptbcFirst = ptbc->m_ptbcTbNext;
5334
        else
5335
 
5336
        Unlock (rgtbdDesc[iTailTb].m_prgtbcbBuckets[colorTail][iTailDirectory].m_lock);
5337
        }
5338
5339
    // Ok, now we have "orphan" cache entry - it's excluded from all lists,
5340
    // so other threads will never touch it.
5341
    ptbc->m_iTb = iTb;
5342
    ptbc->m_color = side;
5343
    ptbc->m_indChunk = indChunk;
5344
5345
 
5346
    FILE    *fp;
5347
 
5348
5349
    // First, check: is necessary file opened?
5350
    // As files are not thread-safe, lock file
5351
 
5352
    if (ptbd->m_fSplit)
5353
        {
5354
        iExtent = indChunk >> (31 - LOG2_TB_CB_CACHE_CHUNK);
5355
        iPhysicalChunk = indChunk - (iExtent << (31 - LOG2_TB_CB_CACHE_CHUNK));
5356
 
5357
    else
5358
        {
5359
        iExtent = 0;
5360
 
5361
        }
5362
    fp = ptbd->m_rgfpFiles[side][iExtent];
5363
 
5364
        {
5365
        // Not - try to open it
5366
        pszFileName = ptbd->m_rgpchFileName[side][iExtent];
5367
        if (NULL != pszFileName)
5368
            {
5369
            fp = fopen (pszFileName, "rb");
5370
            if (NULL == fp)
5371
                {
5372
                // Failed. Close all the opened files and retry
5373
                Unlock (ptbd->m_rglockFiles[side]);
5374
                VTbCloseFiles ();
5375
 
5376
                // Theoretically, it's possible that other threads opened a lot of
5377
                // files in the interval between VTbCloseFiles() and Lock(). If
5378
 
5379
                // especially for file open, at least not in first version.
5380
                // Problem can happen only on systems with small limit of
5381
                // simultaneously open files and high number of threads - unlikely
5382
 
5383
                fp = ptbd->m_rgfpFiles[side][iExtent];
5384
                if (NULL == fp)
5385
                    {
5386
                    fp = fopen (pszFileName, "rb");
5387
                    if (NULL == fp)
5388
                        {
5389
#if defined (STOP_ON_ERROR)
5390
                        printf ("*** Unable to open file %s\n", pszFileName);
5391
                        fflush (stdout);
5392
                        exit(1);
5393
#endif
5394
                        goto ERROR_LABEL;
5395
                        }
5396
                    }
5397
                }
5398
            ptbd->m_rgfpFiles[side][iExtent] = fp;
5399
            }
5400
        else
5401
            goto ERROR_LABEL;
5402
 
5403
5404
    // File opened. Now seek and read necessary chunk
5405
    if (NULL == ptbd->m_rgpdiDecodeInfo[side][iExtent])
5406
        {
5407
        long lPos;
5408
 
5409
5410
        lPos = (long) (iPhysicalChunk*TB_CB_CACHE_CHUNK);
5411
#if defined (T33_INCLUDE) || defined (T42_INCLUDE)
5412
        if (lPos < 0)
5413
            {
5414
            iResult = fseek (fp, 0L, SEEK_SET);
5415
            if (iResult)
5416
 
5417
#if defined (STOP_ON_ERROR)
5418
                printf ("*** Unable to seek file %s offset %08X\n",
5419
                        pszFileName, 0);
5420
                fflush (stdout);
5421
                exit(1);
5422
#endif
5423
 
5424
                }
5425
            do
5426
                {
5427
                iResult = fseek (fp, 0x40000000, SEEK_CUR);
5428
 
5429
                    {
5430
#if defined (STOP_ON_ERROR)
5431
                    printf ("*** Unable to seek file %s offset %08X\n",
5432
                            pszFileName, 0x40000000);
5433
                    fflush (stdout);
5434
                    exit(1);
5435
#endif
5436
                    goto ERROR_LABEL;
5437
                    }
5438
                lPos -= 0x40000000;
5439
                } while (lPos < 0);
5440
 
5441
            }
5442
        else
5443
#endif
5444
            iResult = fseek (fp, lPos, SEEK_SET);
5445
        // Read uncompressed file
5446
        if (iResult)
5447
            {
5448
#if defined (STOP_ON_ERROR)
5449
            printf ("*** Unable to seek file %s offset %08X\n",
5450
                    pszFileName, lPos);
5451
            fflush (stdout);
5452
            exit(1);
5453
#endif
5454
            goto ERROR_LABEL;
5455
            }
5456
        cb = fread (ptbc->m_pbData, 1, TB_CB_CACHE_CHUNK, fp);
5457
        if (cb != TB_CB_CACHE_CHUNK)
5458
            {
5459
            // Could not read TB_CB_CACHE_CHUNK - check for error
5460
            if (ferror (fp) || ((size_t) -1 == cb))
5461
 
5462
#if defined (STOP_ON_ERROR)
5463
                printf ("*** Read error, file %s\n", pszFileName);
5464
                fflush (stdout);
5465
                exit(1);
5466
 
5467
                goto ERROR_LABEL;
5468
                }
5469
            }
5470
        Unlock (ptbd->m_rglockFiles[side]);
5471
        }
5472
    else
5473
        {
5474
        // Read compressed file
5475
        int fWasError;
5476
        decode_block    *block;
5477
        decode_info     *info = ptbd->m_rgpdiDecodeInfo[side][iExtent];
5478
5479
#if (CPUS > 1)
5480
        // Find free decode block
5481
        decode_block    **pBlock;
5482
5483
 
5484
        pBlock = rgpdbDecodeBlocks;
5485
 
5486
            pBlock ++;
5487
        block = *pBlock;
5488
        *pBlock = NULL;
5489
        Unlock (lockDecode);
5490
#else
5491
        block = rgpdbDecodeBlocks[0];
5492
#endif
5493
5494
        // Initialize decode block and read chunk
5495
        fWasError = 0 != comp_init_block (block, TB_CB_CACHE_CHUNK, ptbc->m_pbData) ||
5496
                    0 != comp_read_block (block, info, fp, iPhysicalChunk);
5497
 
5498
        // Release lock on file, so other threads can proceed with that file
5499
        Unlock (ptbd->m_rglockFiles[side]);
5500
5501
        // Decompress chunk
5502
        if (!fWasError)
5503
            fWasError |= (0 != comp_decode_and_check_crc (block, info, block->orig.size, TB_CRC_CHECK));
5504
5505
        // Release block
5506
 
5507
        Lock (lockDecode);
5508
        *pBlock = block;
5509
        Unlock (lockDecode);
5510
#endif
5511
5512
        // Read Ok?
5513
        if (fWasError)
5514
            {
5515
#if defined (STOP_ON_ERROR)
5516
            printf ("*** Decompression error, file %s\n", pszFileName);
5517
            fflush (stdout);
5518
            exit(1);
5519
#endif
5520
            goto ERROR_LABEL_2;
5521
            }
5522
        }
5523
 
5524
    // Read - now acquire locks and insert cache entry in both lists
5525
    Lock (ptbd->m_prgtbcbBuckets[side][iDirectory].m_lock);
5526
    Lock (lockLRU);
5527
5528
    // Insert cache entry into general LRU list
5529
    ptbc->m_ptbcPrev = NULL;
5530
    ptbc->m_ptbcNext = ptbcHead;
5531
    if (NULL == ptbcHead)
5532
 
5533
    else
5534
 
5535
    ptbcHead = ptbc;
5536
5537
    // Insert cache entry into cache bucket LRU list
5538
    ptbc->m_ptbcTbPrev = NULL;
5539
    ptbc->m_ptbcTbNext = ptbd->m_prgtbcbBuckets[side][iDirectory].m_ptbcFirst;
5540
    if (NULL != ptbc->m_ptbcTbNext)
5541
        ptbc->m_ptbcTbNext->m_ptbcTbPrev = ptbc;
5542
    ptbd->m_prgtbcbBuckets[side][iDirectory].m_ptbcFirst = ptbc;
5543
5544
 
5545
    int tb;
5546
 
5547
    tb = (tb_t) (ptbc->m_pbData[indInChunk]);
5548
    // Release locks
5549
    Unlock (ptbd->m_prgtbcbBuckets[side][iDirectory].m_lock);
5550
    Unlock (lockLRU);
5551
    return tb;
5552
5553
    // I/O error. Here I don't want to halt the program, because that can
5554
    // happen in the middle of the important game. Just return failure.
5555
ERROR_LABEL:
5556
    Unlock (ptbd->m_rglockFiles[side]);
5557
 
5558
    Lock (lockLRU);
5559
    ptbd->m_rgpchFileName[side][iExtent] = NULL;
5560
    ptbc->m_ptbcNext = ptbcFree;
5561
    ptbcFree = ptbc;
5562
    Unlock (lockLRU);
5563
    return L_bev_broken;
5564
    }
5565
5566
// Probe TB - upper level function
5567
5568
// 16-bit version (recommended)
5569
5570
#define FOutOfBound(iTb, side, indOffset)\
5571
        (tbid_kppkp == iTb && x_colorBlack == side &&\
5572
         (indOffset == 0x0362BC7C || indOffset == 0x0362DE44 || indOffset == 0x03637648 ||\
5573
          indOffset == 0x03639810 || indOffset == 0x038D4F29 || indOffset == 0x040A2CAB ||\
5574
          indOffset == 0x043C778C))
5575
 
5576
extern "C" int TB_FASTCALL L_TbtProbeTable
5577
    (
5578
    int     iTb,
5579
    color   side,
5580
    INDEX   indOffset
5581
    )
5582
    {
5583
    int tbtScore;
5584
    CTbDesc *ptbd;
5585
5586
    assert (iTb > 0 && iTb < cTb);
5587
    ptbd = & rgtbdDesc[iTb];
5588
    if (ptbd->m_fSymmetric)
5589
        side = x_colorWhite;
5590
5591
    // Entire file read/mapped to memory?
5592
    if (NULL != ptbd->m_rgpbRead[side])
5593
        {
5594
#if defined (KPPKP_16BIT)
5595
        if (!ptbd->m_f16bit)
5596
            {
5597
            tbtScore = (tb_t) ptbd->m_rgpbRead[side][indOffset];
5598
            return S_to_L (tbtScore);
5599
            }
5600
        else
5601
            return (((int) (((signed char) ptbd->m_rgpbRead[side][indOffset*2+1]))) << 8) +
5602
                    ptbd->m_rgpbRead[side][indOffset*2];
5603
#elif defined (T33_INCLUDE)
5604
        if (!ptbd->m_f16bit)
5605
            {
5606
            if (FOutOfBound (iTb, side, indOffset))
5607
                return -32639;
5608
            else
5609
                {
5610
                tbtScore = (tb_t) ptbd->m_rgpbRead[side][indOffset];
5611
 
5612
                }
5613
            }
5614
        else
5615
 
5616
                    ptbd->m_rgpbRead[side][indOffset*2];
5617
#else
5618
        if (FOutOfBound (iTb, side, indOffset))
5619
            return -32639;
5620
        else
5621
            {
5622
            tbtScore = (tb_t) ptbd->m_rgpbRead[side][indOffset];
5623
 
5624
            }
5625
#endif
5626
        }
5627
5628
 
5629
    if (0 == ctbcTbCache || NULL == ptbd->m_prgtbcbBuckets[side])
5630
 
5631
5632
 
5633
    if (ptbd->m_f16bit)
5634
        {
5635
        // Inefficient, but very simple, code
5636
        int iLo;
5637
        int iHi;
5638
       
5639
        iLo = TbtProbeTable (iTb, side, (unsigned) WIDE_TB_CHUNK (indOffset), (unsigned) WIDE_TB_OFFSET (indOffset));
5640
 
5641
        tbtScore = (L_bev_broken == iLo || L_bev_broken == iHi) ? L_bev_broken : ((iHi << 8) + (iLo & 0xFF));
5642
        }
5643
    else
5644
        {
5645
#if !defined (KPPKP_16BIT)
5646
        if (FOutOfBound (iTb, side, indOffset))
5647
            return -32639;
5648
#endif
5649
        tbtScore = TbtProbeTable (iTb, side, (unsigned) TB_CHUNK (indOffset), (unsigned) TB_OFFSET (indOffset));
5650
        tbtScore = L_bev_broken == tbtScore ? L_bev_broken : S_to_L (tbtScore);
5651
        }
5652
#elif !defined (KPPKP_16BIT)
5653
    if (FOutOfBound (iTb, side, indOffset))
5654
        return -32639;
5655
    tbtScore = TbtProbeTable (iTb, side, (unsigned) TB_CHUNK (indOffset), (unsigned) TB_OFFSET (indOffset));
5656
    tbtScore = L_bev_broken == tbtScore ? L_bev_broken : S_to_L (tbtScore);
5657
#else
5658
    if (tbid_kppkp != iTb)
5659
        {
5660
        // All tables but kppkp are 8-bit tables
5661
 
5662
        tbtScore = L_bev_broken == tbtScore ? L_bev_broken : S_to_L (tbtScore);
5663
 
5664
    else
5665
        {
5666
        // Special handling of kppkp - it's 16-bit table
5667
        // Inefficient, but very simple, code
5668
        int iLo;
5669
        int iHi;
5670
       
5671
        iLo = TbtProbeTable (iTb, side, (unsigned) WIDE_TB_CHUNK (indOffset), (unsigned) WIDE_TB_OFFSET (indOffset));
5672
        iHi = TbtProbeTable (iTb, side, (unsigned) WIDE_TB_CHUNK (indOffset), (unsigned) WIDE_TB_OFFSET (indOffset)+1);
5673
 
5674
        }
5675
#endif
5676
    return tbtScore;
5677
    }
5678
5679
//-----------------------------------------------------------------------------
5680
//
5681
//  Global initialization
5682
5683
// TODO: Check size of split tables, too
5684
5685
static void VCheckSize
5686
    (
5687
    int     iTb,
5688
    color   side,
5689
 
5690
    INDEX   cb,
5691
 
5692
    )
5693
    {
5694
#if defined (NEW)
5695
    INDEX   cbOk1, cbOk2;
5696
5697
    if (0 == rgtbdDesc[iTb].m_rgcbLength[side])
5698
        return;
5699
5700
    cbOk1 = rgtbdDesc[iTb].m_rgcbLength[side];
5701
 
5702
#if defined (T_INDEX64)
5703
    if (rgtbdDesc[iTb].m_fSplit)
5704
        {
5705
        cbOk1 = (1uLL << (rgtbdDesc[iTb].m_f16bit ? 30 : 31)); // Pierre-Marie Baty -- added type cast
5706
        cbOk2 = cbOk2 % (1uLL << (rgtbdDesc[iTb].m_f16bit ? 30 : 31)); // Pierre-Marie Baty -- added type cast
5707
        }
5708
#endif
5709
5710
    if (cb != cbOk1 && cb != cbOk2)
5711
        {
5712
        printf ("*** %s corrupted "
5713
                DEC_INDEX_FORMAT " " DEC_INDEX_FORMAT " " DEC_INDEX_FORMAT "\n", // Pierre-Marie Baty -- added spaces for preprocessor
5714
                rgchTbName, cbOk1, cbOk2, cb);
5715
        exit (1);
5716
        }
5717
#endif
5718
 
5719
5720
 
5721
#if defined (_WIN32) || defined (_WIN64)
5722
 
5723
BOOL    rgfAccessed[26];
5724
BOOL    rgfNotReady[26];
5725
#endif
5726
5727
static int FCheckExtentExistance
5728
    (
5729
    char    *pszPath,
5730
    int     iTb,
5731
    color   side,
5732
    int     iExtent
5733
    )
5734
    {
5735
    FILE            *fp;
5736
 
5737
    const char      *pchExt = PchExt (side);
5738
    char            rgchTbName[1024];
5739
 
5740
    CTbCacheBucket  *prgtbcbBuckets;
5741
    INDEX           cb;
5742
    decode_info     *comp_info = NULL;
5743
 
5744
    if (FRegisteredExtent (iTb, side, iExtent) || NULL != rgtbdDesc[iTb].m_rgpbRead[side])
5745
        return true;
5746
5747
#if defined (_WIN32) || defined (_WIN64)
5748
    // Do not repeatedely probe device that is not ready
5749
    // (i.e. unmapped disk or CD-ROM that does not contain the disk).
5750
    if (NULL != pszPath && 0 != pszPath[0] && ':' == pszPath[1])
5751
        {
5752
        int  iDrive;
5753
        char szRoot[5];
5754
        WIN32_FIND_DATA fd;
5755
        HANDLE hResult;
5756
5757
        iDrive = tolower(pszPath[0]) - 'a';
5758
        if (iDrive >= 0 && iDrive < 26)
5759
            {
5760
            if (rgfNotReady[iDrive])
5761
                return false;
5762
            if (!rgfAccessed[iDrive])
5763
                {
5764
                if (iDrivesMap && 0 == (iDrivesMap & (1 << iDrive)))
5765
                    return false;
5766
                szRoot[0] = pszPath[0];
5767
                szRoot[1] = pszPath[1];
5768
                szRoot[2] = '\\';
5769
                szRoot[3] = '*';
5770
                szRoot[4] = 0;
5771
                hResult = FindFirstFile (szRoot, &fd);
5772
                if (INVALID_HANDLE_VALUE == hResult)
5773
                    {
5774
                    if (ERROR_NOT_READY == GetLastError())
5775
                        {
5776
                        rgfNotReady[iDrive] = true;
5777
                        return false;
5778
                        }
5779
                    }
5780
 
5781
                    FindClose (hResult);
5782
                rgfAccessed[iDrive] = true;
5783
                }
5784
            }
5785
        }
5786
#endif
5787
5788
    strcpy (rgchTbName, pszPath);
5789
    if (0 != pszPath[0] && DELIMITER[0] != pszPath[strlen(pszPath)-1])
5790
        strcat (rgchTbName, DELIMITER);
5791
    strcat (rgchTbName, rgtbdDesc[iTb].m_rgchName);
5792
 
5793
        {
5794
        rgchExtent[0] = '.';
5795
        if (iExtent >= 10)
5796
            rgchExtent[1] = (char) (iExtent + 'a' - 10);
5797
        else
5798
            rgchExtent[1] = (char) (iExtent + '0');
5799
        rgchExtent[2] = '\0';
5800
        strcat (rgchTbName, rgchExtent);
5801
        }
5802
    strcat (rgchTbName, pchExt);
5803
    cOpenFilesAttempts ++;
5804
    fp = fopen (rgchTbName, "rb");
5805
    //printf (">>> Opening %s\n", rgchTbName);
5806
    cOpenFilesSuceed += (NULL != fp);
5807
#if !defined (NEW) && !defined (_WIN32) && !defined(_WIN64)
5808
    // For case-sensitive systems, have to try once more
5809
 
5810
        {
5811
        for (int i = strchr(rgchTbName,'.')-rgchTbName-1; i>=0 && isalpha(rgchTbName[i]); i--)
5812
            rgchTbName[i] = toupper (rgchTbName[i]);
5813
        cOpenFilesAttempts ++;
5814
        fp = fopen (rgchTbName, "rb");
5815
        //printf (">>> Opening %s\n", rgchTbName);
5816
        cOpenFilesSuceed += (NULL != fp);
5817
        }
5818
#endif
5819
    if (NULL != fp)
5820
        {
5821
        // Found uncompressed table
5822
        if (rgtbdDesc[iTb].m_f16bit ||
5823
            ((int)(cb = rgtbdDesc[iTb].m_rgcbLength[side])) < 0 ||
5824
            cb != (unsigned) cb)
5825
            {
5826
            // Do not check the length for too large files
5827
            cb = rgtbdDesc[iTb].m_rgcbLength[side];
5828
            }
5829
        else
5830
            {
5831
            if (0 != fseek (fp, 0L, SEEK_END))
5832
                {
5833
                printf ("*** Seek in %s failed\n", rgchTbName);
5834
                exit (1);
5835
                }
5836
            cb = (INDEX) ftell (fp);
5837
            VCheckSize (iTb, side, iExtent, cb, rgchTbName);
5838
            }
5839
        }
5840
    else
5841
        {
5842
        // Check for compressed table.
5843
        // First, check for kxykz.nb?.emd
5844
 
5845
        cOpenFilesAttempts ++;
5846
        fp = fopen (rgchTbName, "rb");
5847
        //printf (">>> Opening %s\n", rgchTbName);
5848
        cOpenFilesSuceed += (NULL != fp);
5849
        if ((NULL == fp) && !rgtbdDesc[iTb].m_fSplit)
5850
            {
5851
            // Check for kxykz_nb?.emd
5852
 
5853
            cOpenFilesAttempts ++;
5854
            fp = fopen (rgchTbName, "rb");
5855
            //printf (">>> Opening %s\n", rgchTbName);
5856
            cOpenFilesSuceed += (NULL != fp);
5857
            }
5858
        if ((NULL == fp) && !rgtbdDesc[iTb].m_fSplit)
5859
            {
5860
            // Check for kxykz_nb?_emd
5861
            rgchTbName [strlen(rgchTbName)-4] = '_';
5862
 
5863
            fp = fopen (rgchTbName, "rb");
5864
            //printf (">>> Opening %s\n", rgchTbName);
5865
            cOpenFilesSuceed += (NULL != fp);
5866
            }
5867
#if defined (T41_INCLUDE)
5868
 
5869
#else
5870
        if ((NULL == fp) && (iTb <= tbid_kqqkq))
5871
#endif
5872
 
5873
            // Check for kxykznb?.emd (8+3 format)
5874
            int cch;
5875
           
5876
            rgchTbName [strlen(rgchTbName)-4] = '.';
5877
            cch = strlen (rgchTbName);
5878
            memmove (rgchTbName+cch-8, rgchTbName+cch-7, 8);
5879
            cOpenFilesAttempts ++;
5880
            fp = fopen (rgchTbName, "rb");
5881
            //printf (">>> Opening %s\n", rgchTbName);
5882
            cOpenFilesSuceed += (NULL != fp);
5883
            }
5884
        if (NULL == fp)
5885
            return false;
5886
        cCompressed ++;
5887
        int iResult = comp_open_file (&comp_info, fp, TB_CRC_CHECK);
5888
        if (0 != iResult)
5889
            {
5890
            printf ("*** Unable to read %s - ", rgchTbName);
5891
            switch (iResult & 0xFF)
5892
                {
5893
            case COMP_ERR_READ:
5894
                printf ("read error\n");
5895
                break;
5896
            case COMP_ERR_NOMEM:
5897
                printf ("out of memory\n");
5898
                break;
5899
            case COMP_ERR_BROKEN:
5900
                printf ("file broken\n");
5901
                break;
5902
            default:
5903
                printf ("error %d\n", iResult);
5904
                break;
5905
                }
5906
            exit (1);
5907
            }
5908
        if (comp_info->block_size != TB_CB_CACHE_CHUNK)
5909
            {
5910
            printf ("*** %s: Unsupported block size %d\n", rgchTbName, comp_info->block_size);
5911
            exit (1);
5912
            }
5913
        if (rgtbdDesc[iTb].m_f16bit)
5914
            {
5915
            cb = ((INDEX)comp_info->block_size/2)*(comp_info->n_blk-1) +
5916
                  (INDEX)comp_info->last_block_size/2;
5917
            VCheckSize (iTb, side, iExtent, cb, rgchTbName);
5918
            }
5919
        else
5920
            {
5921
            cb = ((INDEX)comp_info->block_size)*(comp_info->n_blk-1) +
5922
                 (INDEX)comp_info->last_block_size;
5923
            VCheckSize (iTb, side, iExtent, cb, rgchTbName);
5924
            }
5925
5926
#if 0
5927
 
5928
        if (NULL == block)
5929
            {
5930
            int iResult = comp_alloc_block (&rgpdbDecodeBlocks[0], TB_CB_CACHE_CHUNK);
5931
            if (0 != iResult)
5932
                {
5933
 
5934
                exit (1);
5935
                }
5936
            block = rgpdbDecodeBlocks[0];
5937
            }
5938
        // Initialize decode block and read chunk
5939
        fWasError = 0 != comp_init_block (block, TB_CB_CACHE_CHUNK, rgbBuffer) ||
5940
                    0 != comp_read_block (block, comp_info, fp, TB_CHUNK (cb-1)) ||
5941
                    0 != comp_decode_and_check_crc (block, comp_info, block->orig.size, TB_CRC_CHECK);
5942
        if (fWasError)
5943
            {
5944
            printf ("*** Sanity check on %s failed\n", rgchTbName);
5945
            exit (1);
5946
            }
5947
#endif
5948
        }
5949
5950
    fclose (fp);
5951
    if (FRegisterTb (& (rgtbdDesc[iTb])))
5952
        {
5953
        pchCopy = (char*) PvMalloc (strlen(rgchTbName)+1);
5954
        strcpy (pchCopy, rgchTbName);
5955
        free (rgtbdDesc[iTb].m_rgpchFileName[side][iExtent]);
5956
        rgtbdDesc[iTb].m_rgpchFileName[side][iExtent] = pchCopy;
5957
        if (NULL == rgtbdDesc[iTb].m_prgtbcbBuckets[side])
5958
            {
5959
            prgtbcbBuckets = (CTbCacheBucket*) PvMalloc (TB_DIRECTORY_SIZE*sizeof(CTbCacheBucket));
5960
            memset (prgtbcbBuckets, 0, TB_DIRECTORY_SIZE*sizeof(CTbCacheBucket));
5961
#if (CPUS > 1)
5962
            for (int i = 0; i < TB_DIRECTORY_SIZE; i ++)
5963
                LockInit (prgtbcbBuckets[i].m_lock);
5964
#endif
5965
            rgtbdDesc[iTb].m_prgtbcbBuckets[side] = prgtbcbBuckets;
5966
            if (fVerbose)
5967
                printf ("%s registered\n", pchCopy);
5968
            }
5969
        else
5970
            {
5971
            if (fVerbose)
5972
                printf ("%s found\n", pchCopy);
5973
            }
5974
        rgtbdDesc[iTb].m_rgpdiDecodeInfo[side][iExtent] = comp_info;
5975
        return true;
5976
        }
5977
    else
5978
        {
5979
        printf ("*** Unable to register %s\n", rgchTbName);
5980
        exit (1);
5981
        }
5982
    return false;
5983
    }
5984
5985
int FCheckExistance
5986
    (
5987
    char    *pszPath,
5988
    int     iTb,
5989
    color   side
5990
    )
5991
    {
5992
    int  fFound;
5993
    int  cExtents;
5994
    INDEX cBytes;
5995
5996
    if (rgtbdDesc[iTb].m_fSplit)
5997
        {
5998
        cBytes = rgtbdDesc[iTb].m_rgcbLength[side];
5999
        if (rgtbdDesc[iTb].m_f16bit)
6000
            cBytes *= 2;
6001
        cExtents = (int) (cBytes >> 31) + 1;
6002
 
6003
    else
6004
        cExtents = 1;
6005
    fFound = false;
6006
 
6007
        {
6008
        if (!FCheckExtentExistance (pszPath, iTb, side, iExtent))
6009
            break;
6010
        fFound = true;
6011
        }
6012
    return fFound;
6013
    }
6014
6015
extern "C" int IInitializeTb
6016
    (
6017
 
6018
    )
6019
    {
6020
 
6021
 
6022
    int     iTb, iMaxTb, iExtent, i;
6023
    CTbCacheBucket  *prgtbcbBuckets;
6024
 
6025
#if defined (_WIN32) || defined (_WIN64)
6026
    // For Windows, get bit map of ready devices
6027
    iDrivesMap = GetLogicalDrives();
6028
 
6029
    memset (rgfNotReady, 0, sizeof(rgfNotReady));
6030
#endif
6031
6032
    cOpenFilesAttempts = cOpenFilesSuceed = 0;
6033
    cbAllocated = cbEGTBCompBytes = 0;
6034
    // If there are open files, close those
6035
 
6036
#if (CPUS > 1)
6037
    // Init all locks
6038
    LockInit (lockLRU);
6039
    LockInit (lockDecode);
6040
    for (iTb = 1; iTb < cTb; iTb ++)
6041
        {
6042
        LockInit (rgtbdDesc[iTb].m_rglockFiles[x_colorWhite]);
6043
        LockInit (rgtbdDesc[iTb].m_rglockFiles[x_colorBlack]);
6044
        }
6045
#endif
6046
#if defined (NEW)
6047
 
6048
    VInitEnumerations ();
6049
#endif
6050
    // Create empty TB search table
6051
 
6052
    // Free memory from TB table
6053
    for (iTb = 1; iTb < cTb; iTb ++)
6054
        {
6055
        for (sd = x_colorWhite; sd <= x_colorBlack; sd = (color) (sd + 1))
6056
            {
6057
            if (NULL != rgtbdDesc[iTb].m_prgtbcbBuckets[sd] &&
6058
                NULL == rgtbdDesc[iTb].m_rgpbRead[sd])
6059
                {
6060
 
6061
#if (CPUS > 1)
6062
                for (i = 0; i < TB_DIRECTORY_SIZE; i ++)
6063
                    LockFree (prgtbcbBuckets[i].m_lock);
6064
#endif
6065
                free (prgtbcbBuckets);
6066
                rgtbdDesc[iTb].m_prgtbcbBuckets[sd] = NULL;
6067
 
6068
            for (iExtent = 0; iExtent < MAX_EXTENTS; iExtent ++)
6069
                {
6070
 
6071
                    {
6072
                    free (rgtbdDesc[iTb].m_rgpchFileName[sd][iExtent]);
6073
                    rgtbdDesc[iTb].m_rgpchFileName[sd][iExtent] = NULL;
6074
                    }
6075
                if (NULL != rgtbdDesc[iTb].m_rgpdiDecodeInfo[sd][iExtent])
6076
 
6077
                    free (rgtbdDesc[iTb].m_rgpdiDecodeInfo[sd][iExtent]);
6078
                    rgtbdDesc[iTb].m_rgpdiDecodeInfo[sd][iExtent] = NULL;
6079
                    }
6080
                }
6081
            }
6082
        }
6083
    // Free compressed blocks
6084
    for (i = 0; i < CPUS; i ++)
6085
        {
6086
        if (NULL != rgpdbDecodeBlocks[i])
6087
            {
6088
            free (rgpdbDecodeBlocks[i]);
6089
 
6090
            }
6091
 
6092
6093
 
6094
        return 0;
6095
6096
    // Search for existing TBs
6097
    iMaxTb = 0;
6098
    for (;;)
6099
 
6100
        for (i = 0; pszPath[i] != '\0' && pszPath[i] != ',' && pszPath[i] != ';'
6101
#if !defined (_WIN32) && !defined (__MWERKS__) && !defined(_WIN64)
6102
             && pszPath[i] != ':'
6103
#endif
6104
             ; i ++)
6105
            {
6106
            szTemp[i] = pszPath[i];
6107
            }
6108
        szTemp[i] = '\0';
6109
 
6110
            {
6111
            if (FCheckExistance (szTemp, iTb, x_colorWhite))
6112
                {
6113
                if (iTb > iMaxTb)
6114
 
6115
                }
6116
        if (! rgtbdDesc[iTb].m_fSymmetric && FCheckExistance (szTemp, iTb, x_colorBlack))
6117
                {
6118
                if (iTb > iMaxTb)
6119
                    iMaxTb = iTb;
6120
                }
6121
            }
6122
        pszPath += i;
6123
        if ('\0' == *pszPath)
6124
            break;
6125
        pszPath ++;
6126
        }
6127
   
6128
    // If there were compressed files, have to allocate buffer(s)
6129
    if (0 != cCompressed)
6130
        {
6131
        for (i = 0; i < CPUS; i ++)
6132
            {
6133
            if (NULL == rgpdbDecodeBlocks[i])
6134
                {
6135
                int iResult = comp_alloc_block (&rgpdbDecodeBlocks[i], TB_CB_CACHE_CHUNK);
6136
                if (0 != iResult)
6137
                    {
6138
                    printf ("*** Cannot allocate decode block: error code %d\n", iResult);
6139
                    exit (1);
6140
                    }
6141
                }
6142
            }
6143
        if (fVerbose)
6144
            printf ("Allocated %dKb for decompression tables, indices, and buffers.\n",
6145
                    (cbEGTBCompBytes+1023)/1024);
6146
        }
6147
6148
    if (fVerbose)
6149
        printf ("Tried to open %d files. Opened %d files.\n",
6150
                cOpenFilesAttempts, cOpenFilesSuceed);
6151
 
6152
#if defined T33_INCLUDE
6153
    if (iMaxTb >= tbid_knnknn)
6154
        return 6;
6155
 
6156
    if (iMaxTb >= tbid_knnnkn)
6157
        return 6;
6158
#endif
6159
    if (iMaxTb >= tbid_kppkp)
6160
        return 5;
6161
    if (iMaxTb >= tbid_kpkp)
6162
 
6163
    if (iMaxTb >= tbid_kpk)
6164
        return 3;
6165
    return 0;
6166
    }
6167
 
6168