Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

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