Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

  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. // restricted to left half of the board// Useful macro and enumeration tables
  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.     const BYTE  *prgcLegal1,
  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.             ulKings = rgsTriKings[sqwk*64+sqbk];    // 0..461
  888. #if defined (ILLEGAL_POSSIBLE)
  889.         if (INF == ulKings)
  890.             return INF_PAIR;
  891. #endif
  892.         if (piw1 == piw2)
  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.         else
  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.     static INLINE unsigned TB_FASTCALL Index
  931.         (
  932.         square  sqwk,
  933.         square  sqw1,
  934.         square  sqw2,
  935.         square  sqw3,
  936.         square  sqbk
  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.             sqw3 = reflect_x(sqw3);
  949.             sqbk = reflect_x(sqbk);
  950.             }
  951.        
  952.         // Get enumerated squares for all pieces
  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.             SORT (sqw1, sqw2);
  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.             return INF_TRIPLE;
  973. #endif
  974.         // Get enumerated position of both kings
  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.         if (piw1 == piw2 && piw2 == piw3)
  984.             {
  985.             // Can we remove one extra square?
  986.             if ((piw1>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw1][sqbk*64+sqwk]))
  987.                 {
  988.                 ind1 -= (sqw1 > sqwk);
  989.                 ind2 -= (sqw2 > sqwk);
  990.                 ind3 -= (sqw3 > sqwk);
  991.                 }
  992.             // Add enumerated squares to the # of the preceeding positions
  993.             return  ind3*(ind3-1)*(ind3-2)/6 + ind2*(ind2-1)/2 + ind1 +
  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.                 ind1 -= (sqw1 > sqwk);
  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.             return  (ind2*(ind2-1)/2 + ind1)*cInd3 + ind3 +
  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.                 ind3 -= (sqw3 > sqwk);
  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.             // Get # of enumerated positions of 2nd piece
  1045.             cInd2 = rgcLegal[piw2][sqbk];
  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.             cInd3 = rgcLegal[piw3][sqbk];
  1054.             // Can we remove WK square from 3rd piece Enumeration?
  1055.             if ((piw3>x_pieceKnight) || ((BYTE)-1 != rgprgsqPiece[piw3][sqbk*64+sqwk]))
  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.                     (fPawns ? rgprgulTriplePawnPresent[piw1][piw2][piw3][ulKings] :
  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.     if (sqw+7 == sqEnP)
  1081.         // Capture to the left
  1082.         return  (sqw&7)-1;
  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.     square  sqw,
  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.         return (sqb&7)+7;
  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.         return (sqw1&7)-1+(EXCLUDE3(sqw2,sqb,sqEnP,sqEnP+8)-i8-1)*i14;
  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.     square  sqEnP
  1143.     )
  1144.     {
  1145.     assert (sqw1 < sqw2);   // Must be already sorted
  1146.     if (sqb-9 == sqEnP && 0 != TbColumn(sqb))
  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.     square  sqb1,
  1196.     square  sqb2,
  1197.     square  sqEnP
  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.     else if(sqb1-7 == sqEnP && 7 != TbColumn(sqb1))
  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.     if (sqb1-9 == sqEnP && 0 != TbColumn(sqb1))
  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.         // Capture to the right
  1327.         sqw3 = EXCLUDE2(sqw3,sqEnP,sqEmptyEnP)-i8-2;
  1328.         return TbColumn(sqw1)+7+
  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.         sqw3 = EXCLUDE2(sqw3,sqEnP,sqEmptyEnP)-i8-2;
  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.         return TbColumn(sqw3)-1+
  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.         SWAP(sqw1, sqw2);
  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.     else {
  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. // Index calculation functions for different endgame classes
  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.         sqw1 = SqFindOne  (psqW, piw1);
  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. template <int piw1, int pib1> class T22
  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. template <int piw1, int piw2> class T31
  1592.     {
  1593. public:
  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.         sqbk = SqFindKing (psqB);
  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.                 sqbk = reflect_xy(sqbk);
  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.     static INDEX TB_FASTCALL IndCalcW
  1710.         (
  1711.         square  *psqW,
  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.         else
  1726.             {
  1727.             SqFind2 (psqW, piw1, sqw1, piw2, sqw2);
  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.         sqbk ^= sqMask;
  1738.         sqw1 ^= sqMask;
  1739.         sqw2 ^= sqMask;
  1740.         sqb1 ^= sqMask;
  1741.  
  1742.         if (x_piecePawn == piw2 || x_piecePawn == pib1)
  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.                                     Index(sqwk,sqw1,sqw2,sqbk)*i46+
  1754.                                 EXCLUDE2(sqb1,sqw1,sqw2)-i8;    // 46
  1755.                     else
  1756.                         // En passant capture
  1757.                         return  rgcPairPawnPresent[x_piecePawn][x_piecePawn]*i46 +
  1758.                                 IndHalfKings(sqwk,sqbk)*(i14*i44) +
  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.                     return  TEnumerate2<piw1,piw2,true,false>::
  1777.                                 Index(sqwk,sqw1,sqw2,sqbk)*i48 +
  1778.                             sqb1-i8;    // 48
  1779.                 }
  1780.             }
  1781.         else
  1782.             {
  1783.             // No pawns
  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.                     Index(sqwk,sqw1,sqw2,sqbk)*i60 +
  1795.                 EXCLUDE4(sqb1,sqwk,sqbk,sqw1,sqw2); // 60
  1796.         }
  1797.  
  1798.     static INDEX TB_FASTCALL IndCalcB
  1799.         (
  1800.         square  *psqW,
  1801.         square  *psqB,
  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.             sqMask = rgsqReflectMaskYandX [sqbk];
  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.                 if (x_piecePawn == piw1 && x_piecePawn == piw2)
  1838.                     {
  1839.                     // All 3 pieces are pawns
  1840.                     SORT (sqw1, sqw2);
  1841.                     if (XX == sqEnP)
  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.                                 Index(sqbk,sqb1,sqwk)*(i61*i60) +
  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.                     SORT (sqw1, sqw2);
  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.                     // Only one white pawn
  1904.                     return  TEnumerate1<pib1,true,true>::
  1905.                                 Index(sqbk,sqb1,sqwk)*(i60*i48) +
  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. #if defined (T41_INCLUDE)
  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.         square  *psqB,
  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.             sqw3 = SqFindFirst (psqW, piw3);
  1975.             }
  1976.         sqbk = SqFindKing (psqB);
  1977.  
  1978.         if (x_piecePawn == piw3)
  1979.             sqMask = rgsqReflectMaskY [sqwk] ^ rgsqReflectInvertMask [fInvert];
  1980.         else
  1981.             sqMask = rgsqReflectMaskYandX [sqwk];
  1982.         sqwk ^= sqMask;
  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.         square sqwk, sqw1, sqw2, sqw3, sqbk, sqMask;
  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.         else if (piw2 == piw3)
  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.                         EXCLUDE4(sqw1,sqwk,sqbk,sqw2,sqw3); // 60
  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.             else
  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.                 sqw3 = reflect_xy(sqw3);
  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.                         sqw3*(sqw3-1)/2+EXCLUDE3(sqw2,sqwk,sqbk,sqw1);  // 61*60/2
  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. #if defined (ILLEGAL_POSSIBLE)
  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.             return (INDEX) -1;\
  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.         square   sqwk, sqw1, sqw2, sqbk, sqb1, sqb2, sqMask;
  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.         else
  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.                     else {
  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.                     uInd = rgcPairPawnPresent[x_piecePawn][x_piecePawn];
  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.                     CHECK_INF_SINGLE(uInd);
  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.         square  sqEnP,
  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.             sqw2 = SqFindSecond (psqW, piw2);
  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.         sqb1 ^= sqMask;
  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.                          (INDEX) (uInd +
  2463.                           EXCLUDE4(sqw1,sqbk,sqwk,sqb1,sqb2)*i59 +
  2464.                            EXCLUDE5(sqw2,sqbk,sqwk,sqb1,sqb2,sqw1));
  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.         square sqwk, sqw1, sqw2, sqw3, sqbk, sqb1, sqMask;
  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.         sqb1 = SqFindOne  (psqB, pib1);
  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.         sqw3 ^= sqMask;
  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.                                 IndHalfKings(sqwk,sqbk)*(i14*i44*i43/2) +
  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.                                 Index(sqwk,sqw1,sqw2,sqw3,sqbk);
  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.         sqw1 = SqFindFirst (psqW, piw1);
  2651.         if (piw1 == piw2 && piw2 == piw3)
  2652.             {
  2653.             sqw2 = SqFindSecond (psqW, piw2);
  2654.             sqw3 = SqFindThird (psqW, piw3);
  2655.             }
  2656.         else if (piw1 == piw2)
  2657.             {
  2658.             sqw2 = SqFindSecond (psqW, piw2);
  2659.             sqw3 = SqFindFirst (psqW, piw3);
  2660.             }
  2661.         else if (piw2 == piw3)
  2662.             {
  2663.             sqw2 = SqFindFirst (psqW, piw2);
  2664.             sqw3 = SqFindSecond (psqW, piw3);
  2665.             }
  2666.         else
  2667.             {
  2668.             sqw2 = SqFindFirst (psqW, piw2);
  2669.             sqw3 = SqFindFirst (psqW, piw3);
  2670.             }
  2671.         sqbk = SqFindKing (psqB);
  2672.         sqb1 = SqFindOne  (psqB, pib1);
  2673.  
  2674.         if (x_piecePawn == piw3 || x_piecePawn == pib1)
  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.             if (x_piecePawn == pib1)
  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.                                 sqw2*(sqw2-1)/2 +
  2706.                                 EXCLUDE1(sqw1,sqb1)-i8; // 47*46*45/6
  2707.                         }
  2708.                     else
  2709.                         // En passant capture
  2710.                         return  rgcSinglePawnPresent[x_piecePawn]*(i47*i46*i45/6) +
  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.                     SORT (sqw2, sqw3);
  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.                             uInd = rgcSinglePawnPresent[x_piecePawn];
  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.                                      EXCLUDE7(sqw2,sqwk,sqbk,sqw1,sqw3,sqb1,sqEnP,sqEnP-8)*i14 +        // 57
  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.                         sqw2 = EXCLUDE3(sqw2,sqwk,sqbk,sqb1);               // 61
  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.                     SORT (sqw1, sqw2);
  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.                 else if (piw1 == piw2)
  2869.                     {
  2870.                     // One white pawn, 2 identical white pieces
  2871.                     SORT (sqw1, sqw2);
  2872.                     sqw1 = EXCLUDE4(sqw1,sqwk,sqbk,sqb1,sqw3);
  2873.                     sqw2 = EXCLUDE4(sqw2,sqwk,sqbk,sqb1,sqw3);
  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.                     // One white pawn, 2 different white pieces
  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.         sq2 = reflect_x(sq2);
  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.         sq2 = reflect_xy(sq2);
  3007.         };
  3008.  
  3009.     index =
  3010.         sq0 +
  3011.         sq1 * i64 +
  3012.         sptriv [sq2] * i64 * i64;
  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.     INDEX index;
  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.     if (TbRow(sq4) > TbColumn(sq4))
  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.     square sq3,
  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.         sq3 = reflect_y(sq3);
  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.             return CalcIndex5A (sq0, sq1, sq2, sq3, sq4);
  3470.         }
  3471.     };
  3472.  
  3473. #endif
  3474.  
  3475. #endif  //----------------------------------------------------------------------
  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. #define tbid_knkn    8
  3488. #define tbid_kbkp    9
  3489. #define tbid_kbkn   10
  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. #define tbid_knpk   22
  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. #define tbid_kqnk   32
  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. #define tbid_kppkr  39
  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. #define tbid_knnkp  46
  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. #define tbid_kbpkb  53
  3533. #define tbid_kbpkr  54
  3534. #define tbid_kbpkq  55
  3535. #define tbid_kbnkp  56
  3536. #define tbid_kbnkn  57
  3537. #define tbid_kbnkb  58
  3538. #define tbid_kbnkr  59
  3539. #define tbid_kbnkq  60
  3540. #define tbid_kbbkp  61
  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. #define tbid_krnkp  71
  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. #define tbid_krbkb  78
  3558. #define tbid_krbkr  79
  3559. #define tbid_krbkq  80
  3560. #define tbid_krrkp  81
  3561. #define tbid_krrkn  82
  3562. #define tbid_krrkb  83
  3563. #define tbid_krrkr  84
  3564. #define tbid_krrkq  85
  3565. #define tbid_kqpkp  86
  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. #define tbid_kqbkn  97
  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. #define tbid_kqrkq 105
  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. #  define tbid_kpppk    111
  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. #  define tbid_kbbnk    119
  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. #  define tbid_krbnk    125
  3607. #  define tbid_krbbk    126
  3608. #  define tbid_krrpk    127
  3609. #  define tbid_krrnk    128
  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. #  define tbid_kqrbk    139
  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. #  endif
  3635. #  define tbid_knnknn   (BASE_33 + 1)
  3636. #  define tbid_kbnknn   (BASE_33 + 2)
  3637. #  define tbid_kbbknn   (BASE_33 + 3)
  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. #  define tbid_krrkrb   (BASE_33 + 14)
  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. #  define tbid_kqrknn   (BASE_33 + 22)
  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. #  define tbid_kqqkrn   (BASE_33 + 28)
  3663. #  define tbid_kqqkrb   (BASE_33 + 29)
  3664. #  define tbid_kqqkrr   (BASE_33 + 30)
  3665. #  define tbid_kqqkqn   (BASE_33 + 31)
  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. #    define tbid_krbkbn (BASE_33 + 42)
  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. #    define tbid_kqrkbn (BASE_33 + 51)
  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. #    define tbid_knnknp (BASE_33 + 60)
  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. #    define tbid_kbbknp (BASE_33 + 69)
  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. #    define tbid_krpkbb (BASE_33 + 76)
  3712. #    define tbid_krpkrp (BASE_33 + 77)
  3713. #    define tbid_krnkpp (BASE_33 + 78)
  3714. #    define tbid_krnknp (BASE_33 + 79)
  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. #    define tbid_kqpknp (BASE_33 + 91)
  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. #    define tbid_kqpkqp (BASE_33 + 100)
  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. #    define tbid_kqbknp (BASE_33 + 107)
  3743. #    define tbid_kqbkbp (BASE_33 + 108)
  3744. #    define tbid_kqbkrp (BASE_33 + 109)
  3745. #    define tbid_kqbkqp (BASE_33 + 110)
  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. #  else
  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. #else
  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. #  define tbid_kbbnkn   (BASE_42 + 3)
  3774. #  define tbid_kbbbkn   (BASE_42 + 4)
  3775. #  define tbid_krnnkn   (BASE_42 + 5)
  3776. #  define tbid_krbbkn   (BASE_42 + 6)
  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. #  define tbid_kbnnkb   (BASE_42 + 18)
  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. #  define tbid_kqbbkb   (BASE_42 + 27)
  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. #  define tbid_kbnnkr   (BASE_42 + 34)
  3805. #  define tbid_kbbnkr   (BASE_42 + 35)
  3806. #  define tbid_kbbbkr   (BASE_42 + 36)
  3807. #  define tbid_krnnkr   (BASE_42 + 37)
  3808. #  define tbid_krbbkr   (BASE_42 + 38)
  3809. #  define tbid_krrnkr   (BASE_42 + 39)
  3810. #  define tbid_krrbkr   (BASE_42 + 40)
  3811. #  define tbid_krrrkr   (BASE_42 + 41)
  3812. #  define tbid_kqnnkr   (BASE_42 + 42)
  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. #  define tbid_krrnkq   (BASE_42 + 55)
  3826. #  define tbid_krrbkq   (BASE_42 + 56)
  3827. #  define tbid_krrrkq   (BASE_42 + 57)
  3828. #  define tbid_kqnnkq   (BASE_42 + 58)
  3829. #  define tbid_kqbbkq   (BASE_42 + 59)
  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. #    define tbid_krbnkr (BASE_42 + 73)
  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. #    define tbid_kbppkp (BASE_42 + 85)
  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. #    define tbid_kbbbkp (BASE_42 + 90)
  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. #    define tbid_kqbbkp (BASE_42 + 106)
  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. #    define tbid_kbppkn (BASE_42 + 119)
  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. #    define tbid_kqnpkn (BASE_42 + 127)
  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. #    define tbid_kqbpkb (BASE_42 + 143)
  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. #    define tbid_kqppkr (BASE_42 + 156)
  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. #    define tbid_kbnpkq (BASE_42 + 165)
  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. #else
  3958. #  define cTb   (BASE_42 + 1)
  3959. #endif
  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. /*extern "C" int TB_CRC_CHECK = 0; */
  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. #endif
  3997.  
  3998. struct CTbCache;
  3999.  
  4000. typedef struct      // Hungarian: tbcb
  4001.     {
  4002. #if (CPUS > 1)
  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.     TB (kbnkr, false, false, false, (T32<B, N, R>::IndCalcW), (T32<B, N, R>::IndCalcB),  93037200,  98951760)
  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.     TB (kqbkn, false, false, false, (T32<Q, B, N>::IndCalcW), (T32<Q, B, N>::IndCalcB),  90750420,  96192120)
  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.     TB (krnkbp, false, true,  true,  (T33<R, N, B, P>::IndCalcW), (T33<R, N, B, P>::IndCalcB),  17032882752, 17052633120)
  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.     TB (krrkpp, false, true,  false, (T33<R, R, P, P>::IndCalcW), (T33<R, R, P, P>::IndCalcB),   3428678952,  3197807670)
  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.     TB (kqqnkr, false, false, false, (T42<Q, Q, N, R>::IndCalcW), (T42<Q, Q, N, R>::IndCalcB), 2350606433, 2919076920)
  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.     TB (krbpkb, false, false, true,  (T42<R, B, P, B>::IndCalcW), (T42<R, B, P, B>::IndCalcB), 16637490240, 18096480000)
  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.     TB (kqqpkb, false, false, true,  (T42<Q, Q, P, B>::IndCalcW), (T42<Q, Q, P, B>::IndCalcB),  7297961576,  9048240000)
  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.     TB (kbbpkr, false, true,  true,  (T42<B, B, P, R>::IndCalcW), (T42<B, B, P, R>::IndCalcB),  8243187360,  8978912640)
  4485.     TB (krppkr, false, false, true,  (T42<R, P, P, R>::IndCalcW), (T42<R, P, P, R>::IndCalcB),  6239761412,  7033481568)
  4486.     TB (krnpkr, false, false, true,  (T42<R, N, P, R>::IndCalcW), (T42<R, N, P, R>::IndCalcB), 16057066825, 17957825280)
  4487.     TB (krbpkr, false, false, true,  (T42<R, B, P, R>::IndCalcW), (T42<R, B, P, R>::IndCalcB), 16637490240, 17957825280)
  4488.     TB (krrpkr, false, false, true,  (T42<R, R, P, R>::IndCalcW), (T42<R, R, P, R>::IndCalcB),  8112305064,  8978912640)
  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.     TB (kqrpkr, false, false, true,  (T42<Q, R, P, R>::IndCalcW), (T42<Q, R, P, R>::IndCalcB), 15660230819, 17957825280)
  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.     TB (krppkq, false, true,  true,  (T42<R, P, P, Q>::IndCalcW), (T42<R, P, P, Q>::IndCalcB),  6239761412,  6669309024)
  4501.     TB (krnpkq, false, true,  true,  (T42<R, N, P, Q>::IndCalcW), (T42<R, N, P, Q>::IndCalcB), 16057066825, 17028023040)
  4502.     TB (krbpkq, false, true,  true,  (T42<R, B, P, Q>::IndCalcW), (T42<R, B, P, Q>::IndCalcB), 16637490240, 17028023040)
  4503.     TB (krrpkq, false, true,  true,  (T42<R, R, P, Q>::IndCalcW), (T42<R, R, P, Q>::IndCalcB),  8112305064,  8514011520)
  4504.     TB (kqppkq, false, true,  true,  (T42<Q, P, P, Q>::IndCalcW), (T42<Q, P, P, Q>::IndCalcB),  5920486098,  6669309024)
  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. #endif
  4512.     };
  4513.  
  4514. #undef  P
  4515. #undef  N
  4516. #undef  B
  4517. #undef  R
  4518. #undef  Q
  4519.  
  4520. //  Helper structure
  4521. //  Used to classify on-board position
  4522.  
  4523. union CUTbReference     // Hungarian: utbr
  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. static CUTbReference rgutbReference [MAX_NON_KINGS + 2];
  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.             break;
  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.             pi = x_pieceQueen;
  4564.             break;
  4565.         default:
  4566.             assert (0);
  4567.             }
  4568.         piCounters [pi-1] ++;
  4569.         pch ++;
  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.         goto not_found;
  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.     putbr = rgutbReference;
  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.     hFile = CreateFile ((STRING_PTR) (szName), GENERIC_READ, FILE_SHARE_READ,
  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.     char    *pszName;
  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.     for (int iExtent = 0; iExtent < MAX_EXTENTS; iExtent ++)
  5054.         {
  5055.         if (NULL != rgtbdDesc[iTb].m_rgpdiDecodeInfo[side][iExtent])
  5056.             return false;
  5057.         }
  5058.     if (NULL != rgtbdDesc[iTb].m_rgpbRead[side])
  5059.         return true;
  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. #endif
  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.     // All done
  5114.     rgtbdDesc[iTb].m_rgpbRead[side] = pb;
  5115.     return true;
  5116.     }
  5117.  
  5118. #if defined (_WIN32) || defined(_WIN64)
  5119.  
  5120. // Map whole file into memory
  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. int FMapTableToMemory
  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.     if (rgtbdDesc[iTb].m_fSymmetric)
  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.     char *pszName;
  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.         return false;
  5197.     pszName = rgtbdDesc[iTb].m_rgpchFileName[side][0];
  5198.     if (NULL != rgtbdDesc[iTb].m_rgpbRead[side])
  5199.         {
  5200.         VUnmapFile (rgtbdDesc[iTb].m_rgpbRead[side], hFile, hFileMapping);
  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.     int      iTb,
  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.     // Head of the cache bucket LRU list
  5230.     Lock (ptbd->m_prgtbcbBuckets[side][iDirectory].m_lock);
  5231.     ptbcTbFirst = ptbd->m_prgtbcbBuckets[side][iDirectory].m_ptbcFirst;
  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.                 ptbc->m_ptbcPrev->m_ptbcNext = ptbc->m_ptbcNext;
  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.                 ptbcHead->m_ptbcPrev = ptbc;
  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.                 ptbc->m_ptbcTbNext = ptbcTbFirst;
  5265.                 ptbcTbFirst->m_ptbcTbPrev = ptbc;
  5266.                 ptbd->m_prgtbcbBuckets[side][iDirectory].m_ptbcFirst = ptbc;
  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.     // First, find cache entry we can use
  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.         int      iTailTb;
  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.             // To avoid deadlocks, have to first acquire cache buckets lock,
  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.             ptbcTail->m_ptbcNext = NULL;
  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.             ptbc->m_ptbcTbPrev->m_ptbcTbNext = ptbc->m_ptbcTbNext;
  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.     // Now read it from the disk
  5359.     FILE    *fp;
  5360.     size_t  cb;
  5361.  
  5362.     // First, check: is necessary file opened?
  5363.     // As files are not thread-safe, lock file
  5364.     Lock (ptbd->m_rglockFiles[side]);
  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.         iPhysicalChunk = indChunk;
  5374.         }
  5375.     fp = ptbd->m_rgfpFiles[side][iExtent];
  5376.     if (NULL == fp)
  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.                 Lock (ptbd->m_rglockFiles[side]);
  5389.                 // Theoretically, it's possible that other threads opened a lot of
  5390.                 // files in the interval between VTbCloseFiles() and Lock(). If
  5391.                 // so, we'll fail - I don't like to have one more global lock
  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.                 // combination.
  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.         int  iResult;
  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.                 goto ERROR_LABEL;
  5437.                 }
  5438.             do
  5439.                 {
  5440.                 iResult = fseek (fp, 0x40000000, SEEK_CUR);
  5441.                 if (iResult)
  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.             iResult = fseek (fp, lPos, SEEK_CUR);
  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. #endif
  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.         Lock (lockDecode);
  5497.         pBlock = rgpdbDecodeBlocks;
  5498.         while (NULL == *pBlock)
  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. #if (CPUS > 1)
  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.         ptbcTail = ptbc;
  5546.     else
  5547.         ptbcHead->m_ptbcPrev = ptbc;
  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.     // All done
  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. ERROR_LABEL_2:
  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.     CTbDesc *ptbd;
  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.     color   side,
  5629.     INDEX   indOffset
  5630.     )
  5631.     {
  5632.     int tbtScore;
  5633.     CTbDesc *ptbd;
  5634.  
  5635.     assert (iTb > 0 && iTb < cTb);
  5636.     ptbd = & rgtbdDesc[iTb];
  5637.     if (ptbd->m_fSymmetric)
  5638.         side = x_colorWhite;
  5639.  
  5640.     // Entire file read/mapped to memory?
  5641.     if (NULL != ptbd->m_rgpbRead[side])
  5642.         {
  5643. #if defined (KPPKP_16BIT)
  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.         if (!ptbd->m_f16bit)
  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. #endif
  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.         int iHi;
  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.     if (FOutOfBound (iTb, side, indOffset))
  5703.         return -32639;
  5704.     tbtScore = TbtProbeTable (iTb, side, (unsigned) TB_CHUNK (indOffset), (unsigned) TB_OFFSET (indOffset));
  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.     cbOk1 = rgtbdDesc[iTb].m_rgcbLength[side];
  5750.     cbOk2 = cbOk1;
  5751. #if defined (T_INDEX64)
  5752.     if (rgtbdDesc[iTb].m_fSplit)
  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. //  decode_block    *block;
  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.         char szRoot[5];
  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.                 szRoot[4] = 0;
  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.     //printf (">>> Opening %s\n", rgchTbName);
  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.         cOpenFilesAttempts ++;
  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.             ((int)(cb = rgtbdDesc[iTb].m_rgcbLength[side])) < 0 ||
  5876.             cb != (unsigned) cb)
  5877.             {
  5878.             // Do not check the length for too large files
  5879.             cb = rgtbdDesc[iTb].m_rgcbLength[side];
  5880.             }
  5881.         else
  5882.             {
  5883.             if (0 != fseek (fp, 0L, SEEK_END))
  5884.                 {
  5885.                 printf ("*** Seek in %s failed\n", rgchTbName);
  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.         if (0 != iResult)
  5941.             {
  5942.             printf ("*** Unable to read %s - ", rgchTbName);
  5943.             switch (iResult & 0xFF)
  5944.                 {
  5945.             case COMP_ERR_READ:
  5946.                 printf ("read error\n");
  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.                 LockInit (prgtbcbBuckets[i].m_lock);
  6016. #endif
  6017.             rgtbdDesc[iTb].m_prgtbcbBuckets[side] = prgtbcbBuckets;
  6018.             if (fVerbose)
  6019.                 printf ("%s registered\n", pchCopy);
  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.     return false;
  6035.     }
  6036.  
  6037. int FCheckExistance
  6038.     (
  6039.     char    *pszPath,
  6040.     int     iTb,
  6041.     color   side
  6042.     )
  6043.     {
  6044.     int  fFound;
  6045.     int  cExtents;
  6046.     INDEX cBytes;
  6047.  
  6048.     if (rgtbdDesc[iTb].m_fSplit)
  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.         if (!FCheckExtentExistance (pszPath, iTb, side, iExtent))
  6061.             break;
  6062.         fFound = true;
  6063.         }
  6064.     return fFound;
  6065.     }
  6066.  
  6067. extern "C" int IInitializeTb
  6068.     (
  6069.     char *pszPath
  6070.     )
  6071.     {
  6072.     char    szTemp[1024];
  6073.     color   sd;
  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.     memset (rgfAccessed, 0, sizeof(rgfAccessed));
  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.     // Init all locks
  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.     // Create empty TB search table
  6103.     VCreateEmptyTbTable ();
  6104.     // Free memory from TB table
  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. #if (CPUS > 1)
  6114.                 for (i = 0; i < TB_DIRECTORY_SIZE; i ++)
  6115.                     LockFree (prgtbcbBuckets[i].m_lock);
  6116. #endif
  6117.                 free (prgtbcbBuckets);
  6118.                 rgtbdDesc[iTb].m_prgtbcbBuckets[sd] = NULL;
  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.                     rgtbdDesc[iTb].m_rgpchFileName[sd][iExtent] = NULL;
  6126.                     }
  6127.                 if (NULL != rgtbdDesc[iTb].m_rgpdiDecodeInfo[sd][iExtent])
  6128.                     {
  6129.                     free (rgtbdDesc[iTb].m_rgpdiDecodeInfo[sd][iExtent]);
  6130.                     rgtbdDesc[iTb].m_rgpdiDecodeInfo[sd][iExtent] = NULL;
  6131.                     }
  6132.                 }
  6133.             }
  6134.         }
  6135.     // Free compressed blocks
  6136.     for (i = 0; i < CPUS; i ++)
  6137.         {
  6138.         if (NULL != rgpdbDecodeBlocks[i])
  6139.             {
  6140.             free (rgpdbDecodeBlocks[i]);
  6141.             rgpdbDecodeBlocks[i] = NULL;
  6142.             }
  6143.         }
  6144.  
  6145.     if(pszPath == NULL)
  6146.         return 0;
  6147.  
  6148.     // Search for existing TBs
  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.             szTemp[i] = pszPath[i];
  6159.             }
  6160.         szTemp[i] = '\0';
  6161.         for (iTb = 1; iTb < cTb; iTb ++)
  6162.             {
  6163.             if (FCheckExistance (szTemp, iTb, x_colorWhite))
  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.     if (fVerbose)
  6201.         printf ("Tried to open %d files. Opened %d files.\n",
  6202.                 cOpenFilesAttempts, cOpenFilesSuceed);
  6203.     // All done!
  6204. #if defined T33_INCLUDE
  6205.     if (iMaxTb >= tbid_knnknn)
  6206.         return 6;
  6207. #elif defined (T42_INCLUDE)
  6208.     if (iMaxTb >= tbid_knnnkn)
  6209.         return 6;
  6210. #endif
  6211.     if (iMaxTb >= tbid_kppkp)
  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.