Subversion Repositories Games.Chess Giants

Rev

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

  1. /*
  2. This Software is distributed with the following X11 License,
  3. sometimes also known as MIT license.
  4.  
  5. Copyright (c) 2010 Miguel A. Ballicora
  6.  
  7.  Permission is hereby granted, free of charge, to any person
  8.  obtaining a copy of this software and associated documentation
  9.  files (the "Software"), to deal in the Software without
  10.  restriction, including without limitation the rights to use,
  11.  copy, modify, merge, publish, distribute, sublicense, and/or sell
  12.  copies of the Software, and to permit persons to whom the
  13.  Software is furnished to do so, subject to the following
  14.  conditions:
  15.  
  16.  The above copyright notice and this permission notice shall be
  17.  included in all copies or substantial portions of the Software.
  18.  
  19.  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  20.  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  21.  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  22.  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  23.  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  24.  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25.  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  26.  OTHER DEALINGS IN THE SOFTWARE.
  27. */
  28.  
  29.  
  30. /* NBBOTF will remove the internal bitbase on the fly */
  31. #ifdef NBBOTF
  32.         #ifdef WDL_PROBE
  33.                 #undef WDL_PROBE
  34.         #endif
  35. #else
  36.         #define WDL_PROBE
  37. #endif
  38.  
  39. /*-- Intended to be modified to make public --> Supporting functions the TB generator ---------------------*/
  40.  
  41. #ifdef GTB_SHARE
  42. #define SHARED_forbuilding
  43. #endif
  44.  
  45. /*---------------------------------------------------------------------------------------------------------*/
  46. #include <stdlib.h>
  47. #include <stdio.h>
  48. #include <string.h>
  49.  
  50. #include "gtb-probe.h"
  51.  
  52. #if defined(SHARED_forbuilding)
  53.         #include "gtb-prob2.h"
  54. #else
  55.         #define mySHARED static
  56.         typedef unsigned char                   SQ_CONTENT;
  57.         typedef unsigned int                    SQUARE;
  58. #endif
  59.  
  60. #include "sysport.h"
  61. #include "gtb-att.h"
  62. #include "gtb-types.h"
  63.  
  64. /*---------------------------------------------------------------------------------------------------------*/
  65. /*#include "posit_t.h"*/
  66.  
  67. #define MAX_LISTSIZE 17
  68. #if 0
  69. typedef unsigned                sq_t;
  70. typedef unsigned char   pc_t;
  71. typedef uint32_t                mv_t;
  72. #endif
  73.  
  74. struct posit {
  75.         sq_t                    ws[MAX_LISTSIZE];
  76.         sq_t                    bs[MAX_LISTSIZE];
  77.         pc_t                    wp[MAX_LISTSIZE];
  78.         pc_t                    bp[MAX_LISTSIZE];
  79.         sq_t                    ep;
  80.         unsigned int    stm;
  81.         unsigned int    cas;
  82. };
  83. typedef struct  posit posit_t;
  84.  
  85. #if 0
  86. typedef long int                tbkey_t;
  87. #endif
  88.  
  89. /*---------------------------------------------------------------------------------------------------------*/
  90. /*#include "bool_t.h"*/
  91.  
  92. #if !defined(H_BOOL)
  93. typedef int                                             bool_t;
  94. #endif
  95.  
  96. #if !defined(TRUE)
  97. #define TRUE ((bool_t)1)
  98. #endif
  99.  
  100. #if !defined(FALSE)
  101. #define FALSE ((bool_t)0)
  102. #endif
  103.  
  104. /*--------- private if external building code is not present ----------------------------------------------*/
  105.  
  106. #if !defined(SHARED_forbuilding)
  107.  
  108. #define MAX_EGKEYS 145
  109. #define SLOTSIZE 1
  110. #define NOINDEX ((index_t)(-1))
  111.  
  112. #if 0
  113. typedef unsigned short int      dtm_t;
  114. typedef size_t                          index_t;
  115. /*typedef int                           index_t;*/
  116. #endif
  117.  
  118. enum Loading_status {
  119.                                 STATUS_ABSENT           = 0,
  120.                                 STATUS_STATICRAM        = 1,
  121.                                 STATUS_MALLOC           = 2,
  122.                                 STATUS_FILE             = 3,
  123.                                 STATUS_REJECT           = 4
  124. };
  125.  
  126. struct endgamekey {
  127.         int             id;
  128.         const char *str;
  129.         index_t         maxindex;
  130.         index_t         slice_n;
  131.         void            (*itopc) (index_t, SQUARE *, SQUARE *);
  132.         bool_t          (*pctoi) (const SQUARE *, const SQUARE *, index_t *);
  133.         dtm_t *         egt_w;
  134.         dtm_t *         egt_b;
  135.         FILE *          fd;
  136.         int             status;
  137.         int                     pathn;
  138. };
  139. #endif
  140.  
  141. /*----------------------------------------------------------------------------------------------------------*/
  142.  
  143. /* array for better moves */
  144. #ifdef GTB_SHARE
  145. mySHARED int            bettarr [2] [8] [8];
  146. #endif
  147.  
  148. /*------------ ENUMS ----------------------------------------------------------*/
  149.  
  150. enum Mask_values {
  151.                                         RESMASK  = tb_RESMASK,
  152.                                         INFOMASK = tb_INFOMASK,
  153.                                         PLYSHIFT = tb_PLYSHIFT
  154. };
  155.  
  156. enum Info_values {
  157.                                         iDRAW    = tb_DRAW,
  158.                                         iWMATE   = tb_WMATE,
  159.                                         iBMATE   = tb_BMATE,
  160.                                         iFORBID  = tb_FORBID,
  161.  
  162.                                         iDRAWt   = tb_DRAW  |4,
  163.                                         iWMATEt  = tb_WMATE |4,
  164.                                         iBMATEt  = tb_BMATE |4,
  165.                                         iUNKNOWN = tb_UNKNOWN,
  166.  
  167.                                         iUNKNBIT = (1<<2)
  168. };
  169.  
  170. /*-------------------------- inherited from a previous maindef.h -----------*/
  171.  
  172. #define WHITES (1u<<6)
  173. #define BLACKS (1u<<7)
  174.  
  175. #define NOPIECE 0u
  176. #define PAWN    1u
  177. #define KNIGHT  2u
  178. #define BISHOP  3u
  179. #define ROOK    4u
  180. #define QUEEN   5u
  181. #define KING    6u
  182.  
  183. #define WH 0
  184. #define BL 1
  185. #define Opp(x) ((x)^1)
  186. #define wK (KING   | WHITES)
  187.  
  188. /*-------------------
  189.        SQUARES
  190.   -------------------*/
  191.  
  192. /* from 1-63 different squares posibles   */
  193.  
  194. /*squares*/
  195. enum SQUARES {
  196.         A1,B1,C1,D1,E1,F1,G1,H1,
  197.         A2,B2,C2,D2,E2,F2,G2,H2,
  198.         A3,B3,C3,D3,E3,F3,G3,H3,
  199.         A4,B4,C4,D4,E4,F4,G4,H4,
  200.         A5,B5,C5,D5,E5,F5,G5,H5,
  201.         A6,B6,C6,D6,E6,F6,G6,H6,
  202.         A7,B7,C7,D7,E7,F7,G7,H7,
  203.         A8,B8,C8,D8,E8,F8,G8,H8,
  204.         NOSQUARE,
  205.         ERRSQUARE = 128
  206. };
  207.  
  208. /*------------------- end of inherited from a previous maindef.h -----------*/
  209.  
  210. #if !defined(NDEBUG)
  211. #define NDEBUG
  212. #endif
  213. #ifdef DEBUG
  214. #undef NDEBUG
  215. #endif
  216. #include "assert.h"
  217.  
  218. /*------------------- general DEFINES--------------------------- -----------*/
  219.  
  220. #define gtbNOSIDE       ((unsigned)-1)
  221. #define gtbNOINDEX      ((index_t)-1)
  222.  
  223. /*************************************************\
  224. |
  225. |                               COMPRESSION SCHEMES
  226. |
  227. \*************************************************/
  228.  
  229. #include "gtb-dec.h"
  230.  
  231. static const char *const Extension[] = {
  232.                                                          ".gtb.cp0"
  233.                                                         ,".gtb.cp1"
  234.                                                         ,".gtb.cp2"
  235.                                                         ,".gtb.cp3"
  236.                                                         ,".gtb.cp4"
  237.                                                         ,".gtb.cp5"
  238.                                                         ,".gtb.cp6"
  239.                                                         ,".gtb.cp7"
  240.                                                         ,".gtb.cp8"
  241.                                                         ,".gtb.cp9"
  242. };
  243.  
  244. /*************************************************\
  245. |
  246. |                                       MOVES
  247. |
  248. \*************************************************/
  249.  
  250. enum move_kind {
  251.                 NORMAL_MOVE = 0,
  252.                 CASTLE_MOVE,
  253.                 PASSNT_MOVE,
  254.                 PROMOT_MOVE
  255. };
  256.  
  257. enum move_content {
  258.                 NOMOVE = 0
  259. };
  260.  
  261. #define MV_TYPE(mv)   ( (BYTE)       ((mv) >>6 & 3 )      )
  262. #define MV_TO(mv)     ( (SQUARE)     ((mv) >>8 & 63)      )
  263. #define MV_PT(mv)     ( (SQ_CONTENT) ((mv) >>(3+16) &7  ) )
  264. #define MV_TK(mv)     ( (SQ_CONTENT) ((mv) >>(6+16) &7  ) )
  265. #define MV_FROM(mv)   ( (SQUARE)     ((mv)     & 63)      )
  266.  
  267. /*
  268. |   move,type,color,piece,from,to,taken,promoted
  269. *------------------------------------------------------------------*/
  270.  
  271. #define MV_BUILD(mv,ty,co,pc,fr,to,tk,pm) (                        \
  272.     (mv)    =  (fr)     | (to)<< 8      | (ty)<<  6     | (co)<<8  \
  273.             |  (pc)<<16 | (pm)<< (3+16) | (tk)<< (6+16)            \
  274. )
  275.  
  276. #define MV_ADD_TOTK(mv,to,tk) (          \
  277.      mv     |= (uint32_t)(to) << 8       \
  278.             |  (uint32_t)(tk) << (6+16)  \
  279. )
  280.  
  281. #define map88(x)    (   (x) + ((x)&070)        )
  282. #define unmap88(x)  ( ( (x) + ((x)& 07) ) >> 1 )
  283.  
  284. /*************************************************\
  285. |
  286. |                               STATIC VARIABLES
  287. |
  288. \*************************************************/
  289.  
  290. static int GTB_scheme = 4;
  291.  
  292. /*************************************************\
  293. |
  294. |       needed for
  295. |       PRE LOAD CACHE AND DEPENDENT FUNCTIONS
  296. |
  297. \*************************************************/
  298.  
  299. #define EGTB_MAXBLOCKSIZE 65536
  300.  
  301. static int GTB_MAXOPEN = 4;
  302.  
  303. static bool_t                   Uncompressed = TRUE;
  304. static unsigned int             zipinfo_init (void);
  305. static void                     zipinfo_done (void);
  306.  
  307. enum Flip_flags {
  308.                 WE_FLAG = 1, NS_FLAG = 2,  NW_SE_FLAG = 4
  309. }; /* used in flipt */
  310.  
  311. struct filesopen {
  312.                 int n;
  313.                 tbkey_t *key;
  314. };
  315.  
  316. /* STATIC GLOBALS */
  317.  
  318. static struct filesopen fd = {0, NULL};
  319.  
  320. static bool_t                   TB_INITIALIZED = FALSE;
  321. static bool_t                   DTM_CACHE_INITIALIZED = FALSE;
  322.  
  323. static int                              WDL_FRACTION = 64;
  324. static int                              WDL_FRACTION_MAX = 128;
  325.  
  326. static size_t                   DTM_cache_size = 0;
  327. static size_t                   WDL_cache_size = 0;
  328.  
  329. static unsigned int             TB_AVAILABILITY = 0;
  330.  
  331. /* LOCKS */
  332. static mythread_mutex_t Egtb_lock;
  333.  
  334.  
  335. /****************************************************************************\
  336.  *
  337.  *
  338.  *                      DEBUGGING or PRINTING ZONE
  339.  *
  340.  *
  341.  ****************************************************************************/
  342.  
  343. #if 0
  344. #define FOLLOW_EGTB
  345. #ifndef DEBUG
  346. #define DEBUG
  347. #endif
  348. #endif
  349.  
  350. #define validsq(x) ((x) >= A1 && (x) <= H8)
  351.  
  352. #if defined(DEBUG)
  353. static void     print_pos (const sq_t *ws, const sq_t *bs, const pc_t *wp, const pc_t *bp);
  354. #endif
  355.  
  356. #if defined(DEBUG) || defined(FOLLOW_EGTB)
  357. static void     output_state (unsigned stm, const SQUARE *wSQ, const SQUARE *bSQ,
  358.                                                                 const SQ_CONTENT *wPC, const SQ_CONTENT *bPC);
  359. static const char *Square_str[64] = {
  360.         "a1","b1","c1","d1","e1","f1","g1","h1",
  361.         "a2","b2","c2","d2","e2","f2","g2","h2",
  362.         "a3","b3","c3","d3","e3","f3","g3","h3",
  363.         "a4","b4","c4","d4","e4","f4","g4","h4",
  364.         "a5","b5","c5","d5","e5","f5","g5","h5",
  365.         "a6","b6","c6","d6","e6","f6","g6","h6",
  366.         "a7","b7","c7","d7","e7","f7","g7","h7",
  367.         "a8","b8","c8","d8","e8","f8","g8","h8"
  368. };
  369. static const char *P_str[] = {
  370.         "--", "P", "N", "B", "R", "Q", "K"
  371. };
  372. #endif
  373.  
  374. #ifdef FOLLOW_EGTB
  375.         #define STAB
  376.         #define STABCONDITION 1 /*(stm == BL && whiteSQ[0]==H1 && whiteSQ[1]==D1 && whiteSQ[2]==D3 && blackSQ[0]==C2 )*/
  377.         static bool_t GLOB_REPORT = TRUE;
  378. #endif
  379.  
  380. #if defined(FOLLOW_EGTB)
  381. static const char *Info_str[8] = {
  382.         " Draw", " Wmate", " Bmate", "Illegal",
  383.         "~Draw", "~Wmate", "~Bmate", "Unknown"
  384. };
  385. #endif
  386.  
  387. static void             list_index (void);
  388. static void     fatal_error(void) {
  389.     exit(EXIT_FAILURE);
  390. }
  391.  
  392. #ifdef STAB
  393.         #define FOLLOW_LU(x,y)  {if (GLOB_REPORT) printf ("************** %s: %lu\n", (x), (long unsigned)(y));}
  394. #else
  395.         #define FOLLOW_LU(x,y)
  396. #endif
  397.  
  398. #ifdef STAB
  399.         #define FOLLOW_LULU(x,y,z)  {if (GLOB_REPORT) printf ("************** %s: %lu, %lu\n", (x), (long unsigned)(y), (long unsigned)(z));}
  400. #else
  401.         #define FOLLOW_LULU(x,y,z)
  402. #endif
  403.  
  404. #ifdef STAB
  405.         #define FOLLOW_label(x) {if (GLOB_REPORT) printf ("************** %s\n", (x));}
  406. #else
  407.         #define FOLLOW_label(x)
  408. #endif
  409.  
  410. #ifdef STAB
  411.         #define FOLLOW_DTM(msg,dtm)  {if (GLOB_REPORT) printf ("************** %s: %lu, info:%s, plies:%lu \n"\
  412.         , (msg), (long unsigned)(dtm), (Info_str[(dtm)&INFOMASK]), (long unsigned)((dtm)>>PLYSHIFT)\
  413.         );}
  414. #else
  415.         #define FOLLOW_DTM(msg,dtm)
  416. #endif
  417.  
  418.  
  419. /*--------------------------------*\
  420. |
  421. |
  422. |               INDEXING FUNCTIONS
  423. |
  424. |
  425. *---------------------------------*/
  426.  
  427. #define IDX_set_empty(x) {x=0;x--;}
  428. #define IDX_is_empty(x) (0==(1+(x)))
  429.  
  430. #define NO_KKINDEX NOINDEX
  431. #define MAX_KKINDEX 462
  432. #define MAX_PPINDEX 576
  433. #define MAX_PpINDEX (24 * 48)
  434. /*1128*/
  435. #define MAX_AAINDEX ((63-62) + (62 * (127-62)/2) - 1 + 1)
  436. #define MAX_AAAINDEX (64*21*31)
  437. #define MAX_PP48_INDEX (1128)
  438. /* (24*23*22/6) + 24 * (24*23/2) */
  439. #define MAX_PPP48_INDEX 8648
  440.  
  441. /* VARIABLES */
  442.  
  443. static index_t                  kkidx [64] [64];
  444. static index_t                  ppidx [24] [48];
  445. static index_t                  pp48_idx[48][48];
  446. static index_t                  ppp48_idx[48][48][48];
  447.  
  448. static sq_t                             wksq [MAX_KKINDEX];
  449. static sq_t                             bksq [MAX_KKINDEX];
  450. static sq_t                             pp48_sq_x[MAX_PP48_INDEX];
  451. static sq_t                             pp48_sq_y[MAX_PP48_INDEX];
  452.  
  453. static index_t                  pp_hi24 [MAX_PPINDEX]; /* was unsigned int */
  454. static index_t                  pp_lo48 [MAX_PPINDEX];
  455. static unsigned int     flipt [64] [64];
  456. static index_t                  aaidx [64] [64]; /* was unsigned int */
  457. static unsigned char    aabase [MAX_AAINDEX];
  458.  
  459. static uint8_t                  ppp48_sq_x[MAX_PPP48_INDEX];
  460. static uint8_t                  ppp48_sq_y[MAX_PPP48_INDEX];
  461. static uint8_t                  ppp48_sq_z[MAX_PPP48_INDEX];
  462.  
  463. /* FUNCTIONS */
  464.  
  465. static void     init_indexing (int verbosity);
  466. static void     norm_kkindex (SQUARE x, SQUARE y, /*@out@*/ SQUARE *pi, /*@out@*/ SQUARE *pj);
  467. static void     pp_putanchorfirst (SQUARE a, SQUARE b, /*@out@*/ SQUARE *out_anchor, /*@out@*/ SQUARE *out_loosen);
  468.  
  469. static index_t  wsq_to_pidx24 (SQUARE pawn);
  470. static index_t  wsq_to_pidx48 (SQUARE pawn);
  471. static SQUARE   pidx24_to_wsq (index_t a);
  472. static SQUARE   pidx48_to_wsq (index_t a);
  473.  
  474. static SQUARE   flipWE                  (SQUARE x) { return x ^  07;}
  475. static SQUARE   flipNS                  (SQUARE x) { return x ^ 070;}
  476. static SQUARE   flipNW_SE               (SQUARE x) { return ((x&7)<<3) | (x>>3);}
  477. static SQUARE   getcol                  (SQUARE x) { return x &  7;}
  478. static SQUARE   getrow                  (SQUARE x) { return x >> 3;}
  479. static bool_t   in_queenside    (sq_t x)   { return 0 == (x & (1<<2));}
  480.  
  481. /* 1:0 */
  482. static void     kxk_indextopc   (index_t i, SQUARE *pw, SQUARE *pb);
  483.  
  484. /* 2:0 */
  485. static void     kabk_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);
  486. static void     kakb_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);
  487. static void             kaak_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);
  488.  
  489. /* 2:1 */
  490. static void     kabkc_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  491. static void             kaakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  492.  
  493. /* 3:0 */
  494. static void     kabck_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  495. static void             kaabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  496. static void             kaaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  497. static void             kabbk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  498.  
  499. /* one pawn */
  500. static void     kpk_indextopc   (index_t i, SQUARE *pw, SQUARE *pb);
  501.  
  502. /* 1:1 one pawn */
  503. static void     kakp_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);
  504.  
  505. /* 2:0 one pawn */
  506. static void     kapk_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);
  507.  
  508. /* 2:0 two pawns */
  509. static void     kppk_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);
  510.  
  511. /*  2:1 one pawn */
  512. static void             kapkb_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  513. static void             kabkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  514. static void             kaakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  515.  
  516. /*  2:1 + 3:0 two pawns */
  517. static void             kppka_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  518. static void             kappk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  519. static void             kapkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  520.  
  521. /*  3:0 one pawn */
  522. static void             kabpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  523. static void             kaapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  524.  
  525. /*  three pawns */
  526. static void             kpppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  527. static void             kppkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  528.  
  529. /* 1:1 two pawns */
  530. static void     kpkp_indextopc  (index_t i, SQUARE *pw, SQUARE *pb);
  531.  
  532. /* corresponding pc to index */
  533. static bool_t   kxk_pctoindex   (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  534. static bool_t   kabk_pctoindex  (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  535. static bool_t   kakb_pctoindex  (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  536. static bool_t   kpk_pctoindex   (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  537. static bool_t   kakp_pctoindex  (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  538. static bool_t   kapk_pctoindex  (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  539. static bool_t   kppk_pctoindex  (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  540. static bool_t   kaak_pctoindex  (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  541. static bool_t   kabkc_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  542.  
  543. static bool_t   kaakb_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);/**/
  544.  
  545. static bool_t   kabck_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  546. static bool_t   kaabk_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);/**/
  547. static bool_t   kaaak_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  548. static bool_t   kabbk_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);/**/
  549. static bool_t   kapkb_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  550. static bool_t   kabkp_pctoindex (const SQUARE *pw, const SQUARE *pb, /*@out@*/ index_t *out);
  551. static bool_t   kaakp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
  552. static bool_t   kppka_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out);
  553. static bool_t   kappk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
  554. static bool_t   kapkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
  555. static bool_t   kabpk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
  556. static bool_t   kaapk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
  557. static bool_t   kppkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
  558. static bool_t   kpppk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out);
  559. static bool_t   kpkp_pctoindex  (const SQUARE *pw,     const SQUARE *pb, /*@out@*/ index_t *out);
  560.  
  561. /* testing functions */
  562. static bool_t   test_kppk  (void);
  563. static bool_t   test_kaakb (void);
  564. static bool_t   test_kaabk (void);
  565. static bool_t   test_kaaak (void);
  566. static bool_t   test_kabbk (void);
  567. static bool_t   test_kapkb (void);
  568. static bool_t   test_kabkp (void);
  569. static bool_t   test_kppka (void);
  570. static bool_t   test_kappk (void);
  571. static bool_t   test_kapkp (void);
  572. static bool_t   test_kabpk (void);
  573. static bool_t   test_kaapk (void);
  574. static bool_t   test_kaakp (void);
  575. static bool_t   test_kppkp (void);
  576. static bool_t   test_kpppk (void);
  577.  
  578. static unsigned flip_type (SQUARE x, SQUARE y);
  579. static index_t  init_kkidx (void);
  580. static index_t  init_ppidx (void);
  581. static void     init_flipt (void);
  582. static index_t  init_aaidx (void);
  583. static index_t  init_aaa   (void);
  584. static index_t  init_pp48_idx (void);
  585. static index_t  init_ppp48_idx (void);
  586.  
  587. enum TB_INDEXES
  588.          {       MAX_KXK        = MAX_KKINDEX*64
  589.                 ,MAX_kabk       = MAX_KKINDEX*64*64
  590.                 ,MAX_kakb       = MAX_KKINDEX*64*64
  591.                 ,MAX_kpk        = 24*64*64
  592.                 ,MAX_kakp       = 24*64*64*64
  593.                 ,MAX_kapk       = 24*64*64*64
  594.                 ,MAX_kppk       = MAX_PPINDEX*64*64
  595.                 ,MAX_kpkp       = MAX_PpINDEX*64*64
  596.                 ,MAX_kaak       = MAX_KKINDEX*MAX_AAINDEX
  597.                 ,MAX_kabkc      = MAX_KKINDEX*64*64*64
  598.                 ,MAX_kabck      = MAX_KKINDEX*64*64*64
  599.                 ,MAX_kaakb      = MAX_KKINDEX*MAX_AAINDEX*64
  600.                 ,MAX_kaabk      = MAX_KKINDEX*MAX_AAINDEX*64
  601.                 ,MAX_kabbk  = MAX_KKINDEX*MAX_AAINDEX*64
  602.                 ,MAX_kaaak      = MAX_KKINDEX*MAX_AAAINDEX
  603.                 ,MAX_kapkb  = 24*64*64*64*64
  604.                 ,MAX_kabkp  = 24*64*64*64*64
  605.                 ,MAX_kabpk  = 24*64*64*64*64
  606.                 ,MAX_kppka  = MAX_kppk*64
  607.                 ,MAX_kappk  = MAX_kppk*64
  608.                 ,MAX_kapkp  = MAX_kpkp*64
  609.                 ,MAX_kaapk  = 24*MAX_AAINDEX*64*64
  610.                 ,MAX_kaakp  = 24*MAX_AAINDEX*64*64
  611.                 ,MAX_kppkp  = 24*MAX_PP48_INDEX*64*64
  612.                 ,MAX_kpppk  = MAX_PPP48_INDEX*64*64
  613. };
  614.  
  615. #if defined(SHARED_forbuilding)
  616. extern index_t
  617. biggest_memory_needed (void) {
  618.     return MAX_kabkc;
  619. }
  620. #endif
  621.  
  622. /*--------------------------------*\
  623. |
  624. |
  625. |               CACHE PROTOTYPES
  626. |
  627. |
  628. *---------------------------------*/
  629.  
  630. #if !defined(SHARED_forbuilding)
  631. mySHARED bool_t         get_dtm (tbkey_t key, unsigned side, index_t idx, dtm_t *out, bool_t probe_hard);
  632. #endif
  633.  
  634. static bool_t           get_dtm_from_cache (tbkey_t key, unsigned side, index_t idx, dtm_t *out);
  635.  
  636.  
  637. /*--------------------------------*\
  638. |
  639. |
  640. |                       INIT
  641. |
  642. |
  643. *---------------------------------*/
  644.  
  645. static bool_t   fd_init (struct filesopen *pfd);
  646. static void             fd_done (struct filesopen *pfd);
  647.  
  648. static void             RAM_egtbfree (void);
  649.  
  650. /*--------------------------------------------------------------------------*/
  651. #if !defined(SHARED_forbuilding)
  652. mySHARED void                   egtb_freemem (int i);
  653. #endif
  654.  
  655. mySHARED struct endgamekey egkey[] = {
  656.  
  657. {0, "kqk",  MAX_KXK,  1, kxk_indextopc,  kxk_pctoindex,  NULL ,  NULL   ,NULL ,0, 0 },
  658. {1, "krk",  MAX_KXK,  1, kxk_indextopc,  kxk_pctoindex,  NULL ,  NULL   ,NULL ,0, 0 },
  659. {2, "kbk",  MAX_KXK,  1, kxk_indextopc,  kxk_pctoindex,  NULL ,  NULL   ,NULL ,0, 0 },
  660. {3, "knk",  MAX_KXK,  1, kxk_indextopc,  kxk_pctoindex,  NULL ,  NULL   ,NULL ,0, 0 },
  661. {4, "kpk",  MAX_kpk,  24,kpk_indextopc,  kpk_pctoindex,  NULL ,  NULL   ,NULL ,0, 0 },
  662.         /* 4 pieces */
  663. {5, "kqkq", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  664. {6, "kqkr", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  665. {7, "kqkb", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  666. {8, "kqkn", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  667.  
  668. {9, "krkr", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  669. {10,"krkb", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  670. {11,"krkn", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  671.  
  672. {12,"kbkb", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  673. {13,"kbkn", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  674.  
  675. {14,"knkn", MAX_kakb, 1, kakb_indextopc, kakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  676.         /**/
  677. {15,"kqqk", MAX_kaak, 1, kaak_indextopc, kaak_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  678. {16,"kqrk", MAX_kabk, 1, kabk_indextopc, kabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  679. {17,"kqbk", MAX_kabk, 1, kabk_indextopc, kabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  680. {18,"kqnk", MAX_kabk, 1, kabk_indextopc, kabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  681.  
  682. {19,"krrk", MAX_kaak, 1, kaak_indextopc, kaak_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  683. {20,"krbk", MAX_kabk, 1, kabk_indextopc, kabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  684. {21,"krnk", MAX_kabk, 1, kabk_indextopc, kabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  685.  
  686. {22,"kbbk", MAX_kaak, 1, kaak_indextopc, kaak_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  687. {23,"kbnk", MAX_kabk, 1, kabk_indextopc, kabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  688.  
  689. {24,"knnk", MAX_kaak, 1, kaak_indextopc, kaak_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  690.         /**/
  691.         /**/
  692. {25,"kqkp", MAX_kakp, 24,kakp_indextopc, kakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  693. {26,"krkp", MAX_kakp, 24,kakp_indextopc, kakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  694. {27,"kbkp", MAX_kakp, 24,kakp_indextopc, kakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  695. {28,"knkp", MAX_kakp, 24,kakp_indextopc, kakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  696.         /**/
  697. {29,"kqpk", MAX_kapk, 24,kapk_indextopc, kapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  698. {30,"krpk", MAX_kapk, 24,kapk_indextopc, kapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  699. {31,"kbpk", MAX_kapk, 24,kapk_indextopc, kapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  700. {32,"knpk", MAX_kapk, 24,kapk_indextopc, kapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  701.         /**/
  702. {33,"kppk", MAX_kppk, MAX_PPINDEX ,kppk_indextopc, kppk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  703.         /**/
  704. {34,"kpkp", MAX_kpkp, MAX_PpINDEX ,kpkp_indextopc, kpkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  705.         /**/
  706.         /**/
  707.         /* 5 pieces */
  708. { 35,"kqqqk", MAX_kaaak, 1, kaaak_indextopc, kaaak_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  709. { 36,"kqqrk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  710. { 37,"kqqbk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  711. { 38,"kqqnk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  712. { 39,"kqrrk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  713. { 40,"kqrbk", MAX_kabck, 1, kabck_indextopc, kabck_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  714. { 41,"kqrnk", MAX_kabck, 1, kabck_indextopc, kabck_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  715. { 42,"kqbbk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  716. { 43,"kqbnk", MAX_kabck, 1, kabck_indextopc, kabck_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  717. { 44,"kqnnk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  718. { 45,"krrrk", MAX_kaaak, 1, kaaak_indextopc, kaaak_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  719. { 46,"krrbk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  720. { 47,"krrnk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  721. { 48,"krbbk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  722. { 49,"krbnk", MAX_kabck, 1, kabck_indextopc, kabck_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  723. { 50,"krnnk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  724. { 51,"kbbbk", MAX_kaaak, 1, kaaak_indextopc, kaaak_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  725. { 52,"kbbnk", MAX_kaabk, 1, kaabk_indextopc, kaabk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  726. { 53,"kbnnk", MAX_kabbk, 1, kabbk_indextopc, kabbk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  727. { 54,"knnnk", MAX_kaaak, 1, kaaak_indextopc, kaaak_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  728. { 55,"kqqkq", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  729. { 56,"kqqkr", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  730. { 57,"kqqkb", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  731. { 58,"kqqkn", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  732. { 59,"kqrkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  733. { 60,"kqrkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  734. { 61,"kqrkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  735. { 62,"kqrkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  736. { 63,"kqbkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  737. { 64,"kqbkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  738. { 65,"kqbkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  739. { 66,"kqbkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  740. { 67,"kqnkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  741. { 68,"kqnkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  742. { 69,"kqnkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  743. { 70,"kqnkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  744. { 71,"krrkq", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  745. { 72,"krrkr", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  746. { 73,"krrkb", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  747. { 74,"krrkn", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  748. { 75,"krbkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  749. { 76,"krbkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  750. { 77,"krbkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  751. { 78,"krbkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  752. { 79,"krnkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  753. { 80,"krnkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  754. { 81,"krnkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  755. { 82,"krnkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  756. { 83,"kbbkq", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  757. { 84,"kbbkr", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  758. { 85,"kbbkb", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  759. { 86,"kbbkn", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  760. { 87,"kbnkq", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  761. { 88,"kbnkr", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  762. { 89,"kbnkb", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  763. { 90,"kbnkn", MAX_kabkc, 1, kabkc_indextopc, kabkc_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  764. { 91,"knnkq", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  765. { 92,"knnkr", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  766. { 93,"knnkb", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  767. { 94,"knnkn", MAX_kaakb, 1, kaakb_indextopc, kaakb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  768.  
  769. { 95,"kqqpk", MAX_kaapk, 24, kaapk_indextopc, kaapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  770. { 96,"kqrpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  771. { 97,"kqbpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  772. { 98,"kqnpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  773. { 99,"krrpk", MAX_kaapk, 24, kaapk_indextopc, kaapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  774. {100,"krbpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  775. {101,"krnpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  776. {102,"kbbpk", MAX_kaapk, 24, kaapk_indextopc, kaapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  777. {103,"kbnpk", MAX_kabpk, 24, kabpk_indextopc, kabpk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  778. {104,"knnpk", MAX_kaapk, 24, kaapk_indextopc, kaapk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  779.  
  780. {105,"kqppk", MAX_kappk, MAX_PPINDEX, kappk_indextopc, kappk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  781. {106,"krppk", MAX_kappk, MAX_PPINDEX, kappk_indextopc, kappk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  782. {107,"kbppk", MAX_kappk, MAX_PPINDEX, kappk_indextopc, kappk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  783. {108,"knppk", MAX_kappk, MAX_PPINDEX, kappk_indextopc, kappk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  784.  
  785. {109,"kqpkq", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  786. {110,"kqpkr", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  787. {111,"kqpkb", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  788. {112,"kqpkn", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  789. {113,"krpkq", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  790. {114,"krpkr", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  791. {115,"krpkb", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  792. {116,"krpkn", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  793. {117,"kbpkq", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  794. {118,"kbpkr", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  795. {119,"kbpkb", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  796. {120,"kbpkn", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  797. {121,"knpkq", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  798. {122,"knpkr", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  799. {123,"knpkb", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  800. {124,"knpkn", MAX_kapkb, 24, kapkb_indextopc, kapkb_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  801.  
  802. {125,"kppkq", MAX_kppka, MAX_PPINDEX, kppka_indextopc, kppka_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  803. {126,"kppkr", MAX_kppka, MAX_PPINDEX, kppka_indextopc, kppka_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  804. {127,"kppkb", MAX_kppka, MAX_PPINDEX, kppka_indextopc, kppka_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  805. {128,"kppkn", MAX_kppka, MAX_PPINDEX, kppka_indextopc, kppka_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  806.  
  807. {129,"kqqkp", MAX_kaakp, 24, kaakp_indextopc, kaakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  808. {130,"kqrkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  809. {131,"kqbkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  810. {132,"kqnkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  811. {133,"krrkp", MAX_kaakp, 24, kaakp_indextopc, kaakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  812. {134,"krbkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  813. {135,"krnkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  814. {136,"kbbkp", MAX_kaakp, 24, kaakp_indextopc, kaakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  815. {137,"kbnkp", MAX_kabkp, 24, kabkp_indextopc, kabkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  816. {138,"knnkp", MAX_kaakp, 24, kaakp_indextopc, kaakp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  817.  
  818. {139,"kqpkp", MAX_kapkp, MAX_PpINDEX, kapkp_indextopc, kapkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  819. {140,"krpkp", MAX_kapkp, MAX_PpINDEX, kapkp_indextopc, kapkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  820. {141,"kbpkp", MAX_kapkp, MAX_PpINDEX, kapkp_indextopc, kapkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  821. {142,"knpkp", MAX_kapkp, MAX_PpINDEX, kapkp_indextopc, kapkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  822.  
  823. {143,"kppkp", MAX_kppkp, 24*MAX_PP48_INDEX, kppkp_indextopc, kppkp_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  824. {144,"kpppk", MAX_kpppk, MAX_PPP48_INDEX, kpppk_indextopc, kpppk_pctoindex, NULL ,  NULL   ,NULL ,0, 0 },
  825.  
  826. {MAX_EGKEYS, NULL,  0,        1, NULL,           NULL,           NULL,   NULL   ,NULL ,0 ,0}
  827.  
  828. };
  829.  
  830. #define EGKEY_HASH_SIZE 512
  831. static tbkey_t egkey_hash[EGKEY_HASH_SIZE];
  832.  
  833. static size_t
  834. str_hash_func_1 (const char * str)
  835. {
  836.         size_t h = 5381;
  837.         int c;
  838.         while ((c = *str++))
  839.                 h = h * 31 + c;
  840.         return h;
  841. }
  842.  
  843. static size_t
  844. str_hash_func_2 (const char * str)
  845. {
  846.         size_t h = 0;
  847.         int c;
  848.         while ((c = *str++))
  849.                 h = h * 65599 + c;
  850.         return 2 * h + 1;
  851. }
  852.  
  853. static void
  854. init_egkey_hash (void)
  855. {
  856.         size_t h1, h2;
  857.         int i;
  858.  
  859.         for (i = 0; i < EGKEY_HASH_SIZE; i++)
  860.                 egkey_hash[i] = -1;
  861.  
  862.         for (i = 0; i < MAX_EGKEYS; i++) {
  863.                 h1 = str_hash_func_1 (egkey[i].str) & (EGKEY_HASH_SIZE - 1);
  864.                 h2 = str_hash_func_2 (egkey[i].str);
  865.                 while (egkey_hash[h1] >= 0)
  866.                         h1 = (h1 + h2) & (EGKEY_HASH_SIZE - 1);
  867.                 egkey_hash[h1] = egkey[i].id;
  868.         }
  869. }
  870.  
  871.  
  872. static int eg_was_open[MAX_EGKEYS];
  873.  
  874. static uint64_t Bytes_read = 0;
  875.  
  876. /****************************************************************************\
  877. |
  878. |
  879. |                                               PATH MANAGEMENT ZONE
  880. |
  881. |
  882. \****************************************************************************/
  883.  
  884. #define MAXPATHLEN tb_MAXPATHLEN
  885. #define MAX_GTBPATHS 10
  886.  
  887. static int                      Gtbpath_end_index = 0;
  888. static const char **    Gtbpath = NULL;
  889.  
  890. /*---------------- EXTERNAL PATH MANAGEMENT --------------------------------*/
  891.  
  892. extern const char *tbpaths_getmain (void) {     return Gtbpath[0];}
  893.  
  894. extern const char **
  895. tbpaths_init(void)
  896. {
  897.         const char **newps;
  898.         newps = (const char **) malloc (sizeof (char *));
  899.         if (newps != NULL) {
  900.                 newps[0] = NULL;
  901.         }
  902.         return newps;
  903. }
  904.  
  905. static const char **
  906. tbpaths_add_single(const char **ps, const char *newpath)
  907. {
  908.         size_t counter;
  909.         const char **newps;
  910.         size_t i, psize;
  911.         char *ppath;
  912.  
  913.         if (NULL == ps)
  914.                 return NULL;
  915.  
  916.         psize = strlen(newpath) + 1;
  917.         ppath = (char *) malloc (psize * sizeof (char));
  918.         if (NULL == ppath)
  919.                 return ps; /* failed to incorporate a new path */
  920.         for (i = 0; i < psize; i++) ppath[i] = newpath[i];
  921.  
  922.         for (counter = 0; ps[counter] != NULL; counter++)
  923.                 ;
  924.  
  925.         /* cast to deal with const poisoning */
  926.         newps = (const char **) realloc ((char **)ps, sizeof(char *) * (counter+2));
  927.         if (newps != NULL) {
  928.                 newps [counter] = ppath;
  929.                 newps [counter+1] = NULL;
  930.         }
  931.         return newps;
  932. }
  933.  
  934.  
  935. extern const char **
  936. tbpaths_add(const char **ps, const char *newpath)
  937. {
  938.         size_t i, psize;
  939.         char *mpath;
  940.  
  941.         if (NULL == ps)
  942.                 return NULL;
  943.  
  944.         psize = strlen(newpath) + 1;
  945.         mpath = (char *) malloc (psize * sizeof (char));
  946.         if (NULL == mpath) {
  947.                 return ps; /* failed to incorporate a new path */
  948.         }
  949.         for (i = 0; i < psize; i++) mpath[i] = newpath[i];
  950.  
  951.         for (i = 0; i < psize; i++) {
  952.                 if(';' == mpath[i])
  953.                         mpath[i] = '\0';
  954.         }
  955.  
  956.         for (i = 0;;) {
  957.                 while (i < psize && mpath[i] == '\0') i++;
  958.                 if (i >= psize) break;
  959.                 ps = tbpaths_add_single (ps, &mpath[i]);
  960.                 while (i < psize && mpath[i] != '\0') i++;
  961.         }
  962.  
  963.         free(mpath);
  964.         return ps;
  965. }
  966.  
  967.  
  968. extern const char **
  969. tbpaths_done(const char **ps)
  970. {
  971.         int counter;
  972.         void *q;
  973.  
  974.         if (ps != NULL) {
  975.                 for (counter = 0; ps[counter] != NULL; counter++) {
  976.                         /* cast to deal with const poisoning */
  977.                         void *p = (void *) ps[counter];
  978.                         free(p);
  979.                 }
  980.                 /* cast to deal with const poisoning */
  981.                 q = (void *) ps;
  982.                 free(q);
  983.         }
  984.         return NULL;
  985. }
  986.  
  987. /*---------------- PATH INITIALIZATION ROUTINES ----------------------------*/
  988.  
  989. static void path_system_reset(void) {Gtbpath_end_index = 0;}
  990.  
  991. static bool_t
  992. path_system_init (const char **path)
  993. {
  994.         size_t i;
  995.         size_t sz;
  996.         const char *x;
  997.         bool_t ok = TRUE;
  998.         path_system_reset();
  999.  
  1000.         if (path == NULL) {
  1001.                 return FALSE;
  1002.         }
  1003.  
  1004.         /* calculate needed size for Gtbpath */
  1005.         i = 0;
  1006.         do {
  1007.                 x = path[i++];
  1008.         } while (x != NULL);
  1009.         sz = i; /* sz includes the NULL */
  1010.  
  1011.  
  1012.         Gtbpath = (const char **) malloc (sz * sizeof(char *));
  1013.  
  1014.         if (Gtbpath) {
  1015.  
  1016.                 ok = TRUE;
  1017.                 /* point to the same strings provided */
  1018.                 Gtbpath_end_index = 0;
  1019.                 for (i = 0; i < sz; i++) {
  1020.                         Gtbpath[i] = path[i];
  1021.                         Gtbpath_end_index++;
  1022.                 }
  1023.  
  1024.         } else {
  1025.                 ok = FALSE;
  1026.         }
  1027.         return ok;
  1028.  
  1029. }
  1030.  
  1031. static void
  1032. path_system_done (void)
  1033. {
  1034.         /* before we free Gtbpath, we have to deal with the
  1035.         "const poisoning" and cast it. free() does not accept
  1036.         const pointers */
  1037.         char ** p = (char **) Gtbpath;
  1038.         /* clean up */
  1039.         if (p != NULL)
  1040.                 free(p);
  1041.         return;
  1042. }
  1043.  
  1044.  
  1045. /****************************************************************************\
  1046.  *
  1047.  *
  1048.  *                                              General Initialization Zone
  1049.  *
  1050.  *
  1051.  ****************************************************************************/
  1052.  
  1053.  
  1054. #ifdef WDL_PROBE
  1055. static size_t           wdl_cache_init (size_t cache_mem);
  1056. static void             wdl_cache_flush (void);
  1057.  
  1058. static void                     wdl_cache_reset_counters (void);
  1059. static void                     wdl_cache_done (void);
  1060.  
  1061. static bool_t           get_WDL_from_cache (tbkey_t key, unsigned side, index_t idx, unsigned int *out);
  1062. static bool_t           wdl_preload_cache (tbkey_t key, unsigned side, index_t idx);
  1063. #endif
  1064.  
  1065. #ifdef GTB_SHARE
  1066. static void     init_bettarr (void);
  1067. #endif
  1068.  
  1069. static void     eg_was_open_reset(void)
  1070. {
  1071.         int i;
  1072.         for (i = 0; i < MAX_EGKEYS; i++) {
  1073.                 eg_was_open[i] = 0;
  1074.         }
  1075. }
  1076.  
  1077. static long unsigned int eg_was_open_count(void)
  1078. {
  1079.         long int i, x;
  1080.         for (i = 0, x = 0; i < MAX_EGKEYS; i++) {
  1081.                 x += eg_was_open[i];
  1082.         }
  1083.         return (long unsigned) x;
  1084. }
  1085.  
  1086.  
  1087. enum  Sizes {INISIZE = 4096};
  1088. static char ini_str[INISIZE];
  1089. static void sjoin_s(char *s, size_t size, const char *tail, size_t max) {strncat_s(s, size, tail, max - strlen(s) - 1);} // Pierre-Marie Baty -- safer version
  1090.  
  1091. char *
  1092. tb_init (int verbosity, int decoding_sch, const char **paths)
  1093. {
  1094.         unsigned int zi;
  1095.         int paths_ok;
  1096.         char *ret_str;
  1097.         char localstr[256];
  1098.  
  1099.         assert(!TB_INITIALIZED);
  1100.  
  1101.         init_egkey_hash ();
  1102.  
  1103.         if (verbosity) {
  1104.                 ini_str[0] = '\0';
  1105.                 ret_str = ini_str;
  1106.         } else {
  1107.                 ret_str = NULL;
  1108.         }
  1109.  
  1110.         paths_ok = path_system_init (paths);
  1111.  
  1112.         if (paths_ok && verbosity) {
  1113.                 int g;
  1114.                 assert(Gtbpath!=NULL);
  1115.                 sjoin_s(ini_str,sizeof(ini_str),"\nGTB PATHS\n",INISIZE); // Pierre-Marie Baty -- using a more secure version of this function
  1116.                 for (g = 0; Gtbpath[g] != NULL; g++) {
  1117.                         const char *p = Gtbpath[g];
  1118.                         if (0 == g) {
  1119.                                 sprintf_s (localstr, sizeof(localstr),"  main: %s\n", p); // Pierre-Marie Baty -- using sprintf_s() instead of sprintf
  1120.                         } else {
  1121.                                 sprintf_s (localstr, sizeof(localstr),"    #%d: %s\n", g, p); // Pierre-Marie Baty -- using sprintf_s() instead of sprintf
  1122.                         }
  1123.          sjoin_s(ini_str,sizeof(ini_str),localstr,INISIZE); // Pierre-Marie Baty -- using a more secure version of this function
  1124.                 }
  1125.         }
  1126.  
  1127.         if (!paths_ok && verbosity) {
  1128.                 sjoin_s (ini_str,sizeof(ini_str),"\nGTB PATHS not initialized\n",INISIZE); // Pierre-Marie Baty -- using a more secure version of this function
  1129.         }
  1130.  
  1131.         if (!reach_was_initialized())
  1132.                 reach_init();
  1133.  
  1134.         attack_maps_init (); /* external initialization */
  1135.  
  1136.         init_indexing(0 /* no verbosity */);
  1137.  
  1138.         #ifdef GTB_SHARE
  1139.         init_bettarr();
  1140.         #endif
  1141.  
  1142.         if (!fd_init (&fd) && verbosity) {
  1143.                 sjoin_s (ini_str,sizeof(ini_str),"  File Open Memory initialization = **FAILED**\n",INISIZE); // Pierre-Marie Baty -- using a more secure version of this function
  1144.                 return ret_str;
  1145.         }
  1146.  
  1147.         GTB_scheme = decoding_sch;
  1148.         Uncompressed = GTB_scheme == 0;
  1149.  
  1150.         if (GTB_scheme == 0) {
  1151.                 Uncompressed = TRUE;
  1152.         }
  1153.  
  1154.         set_decoding_scheme(GTB_scheme);
  1155.  
  1156.         if (verbosity) {
  1157.                 sjoin_s (ini_str,sizeof(ini_str),"\nGTB initialization\n",INISIZE); // Pierre-Marie Baty -- using a more secure version of this function
  1158.       sprintf_s (localstr, sizeof (localstr), "  Compression  Scheme = %d\n", GTB_scheme); // Pierre-Marie Baty -- using sprintf_s() instead of sprintf
  1159.                 sjoin_s (ini_str,sizeof(ini_str),localstr,INISIZE); // Pierre-Marie Baty -- using a more secure version of this function
  1160.         }
  1161.  
  1162.         zi = zipinfo_init();
  1163.  
  1164.         TB_AVAILABILITY = zi;
  1165.  
  1166.         if (verbosity) {
  1167.                 if (0 == zi) {
  1168.                         sjoin_s (ini_str,sizeof(ini_str),"  Compression Indexes = **FAILED**\n",INISIZE); // Pierre-Marie Baty -- using a more secure version of this function
  1169.                 } else {
  1170.                         int n, bit;
  1171.  
  1172.                         n = 3; bit = 1;
  1173.                         if (zi&(1u<<bit))
  1174.             sprintf_s (localstr, sizeof (localstr), "  Compression Indexes (%d-pc) = PASSED\n",n); // Pierre-Marie Baty -- using sprintf_s() instead of sprintf
  1175.                         else
  1176.             sprintf_s (localstr, sizeof (localstr), "  Compression Indexes (%d-pc) = **FAILED**\n",n); // Pierre-Marie Baty -- using sprintf_s() instead of sprintf
  1177.                         sjoin_s (ini_str,sizeof(ini_str),localstr,INISIZE); // Pierre-Marie Baty -- using a more secure version of this function
  1178.  
  1179.                         n = 4; bit = 3;
  1180.                         if (zi&(1u<<bit))
  1181.             sprintf_s (localstr, sizeof (localstr), "  Compression Indexes (%d-pc) = PASSED\n",n); // Pierre-Marie Baty -- using sprintf_s() instead of sprintf
  1182.                         else
  1183.             sprintf_s (localstr, sizeof (localstr), "  Compression Indexes (%d-pc) = **FAILED**\n",n); // Pierre-Marie Baty -- using sprintf_s() instead of sprintf
  1184.                         sjoin_s (ini_str,sizeof(ini_str),localstr,INISIZE); // Pierre-Marie Baty -- using a more secure version of this function
  1185.  
  1186.                         n = 5; bit = 5;
  1187.                         if (zi&(1u<<bit))
  1188.             sprintf_s (localstr, sizeof (localstr), "  Compression Indexes (%d-pc) = PASSED\n",n); // Pierre-Marie Baty -- using sprintf_s() instead of sprintf
  1189.                         else
  1190.                                 sprintf_s (localstr, sizeof(localstr),"  Compression Indexes (%d-pc) = **FAILED**\n",n); // Pierre-Marie Baty -- using sprintf_s() instead of sprintf
  1191.                         sjoin_s (ini_str,sizeof(ini_str),localstr,INISIZE); // Pierre-Marie Baty -- using a more secure version of this function
  1192.                 }
  1193.                 sjoin_s (ini_str,sizeof(ini_str),"\n",INISIZE); // Pierre-Marie Baty -- using a more secure version of this function
  1194.         }
  1195.  
  1196.         eg_was_open_reset();
  1197.         Bytes_read = 0;
  1198.  
  1199.         mythread_mutex_init (&Egtb_lock);
  1200.  
  1201.         TB_INITIALIZED = TRUE;
  1202.  
  1203.         return ret_str;
  1204. }
  1205.  
  1206. extern unsigned int
  1207. tb_availability(void)
  1208. {
  1209.         return TB_AVAILABILITY;
  1210. }
  1211.  
  1212. extern bool_t
  1213. tb_is_initialized (void)
  1214. {
  1215.         return TB_INITIALIZED;
  1216. }
  1217.  
  1218. extern void
  1219. tb_done (void)
  1220. {
  1221.         assert(TB_INITIALIZED);
  1222.         fd_done (&fd);
  1223.         RAM_egtbfree();
  1224.         zipinfo_done();
  1225.         path_system_done();
  1226.         mythread_mutex_destroy (&Egtb_lock);
  1227.         TB_INITIALIZED = FALSE;
  1228.  
  1229.         /*
  1230.                 HERE, I should be free() the ini_str, but in
  1231.                 the current implementation, it is static
  1232.                 rather than dynamic.
  1233.         */
  1234.         return;
  1235. }
  1236.  
  1237. char *
  1238. tb_restart(int verbosity, int decoding_sch, const char **paths)
  1239. {
  1240.         if (tb_is_initialized()) {
  1241.                 tb_done();
  1242.         }
  1243.         return tb_init(verbosity, decoding_sch, paths);
  1244. }
  1245.  
  1246. /* whenever the program exits should release this memory */
  1247. static void
  1248. RAM_egtbfree (void)
  1249. {
  1250.         int i;
  1251.         for (i = 0; egkey[i].str != NULL; i++) {
  1252.                 egtb_freemem (i);
  1253.         }
  1254. }
  1255.  
  1256. /*--------------------------------------------------------------------------*/
  1257.  
  1258. #ifdef GTB_SHARE
  1259. static void
  1260. init_bettarr (void)
  1261. {
  1262. /*
  1263.                 iDRAW  = 0, iWMATE  = 1, iBMATE  = 2, iFORBID  = 3,
  1264.                 iDRAWt = 4, iWMATEt = 5, iBMATEt = 6, iUNKNOWN = 7
  1265.  */
  1266.  
  1267.         int temp[] = {
  1268.         /*White*/
  1269.         /*iDRAW   vs*/
  1270.                 1, 2, 1, 1,     2, 2, 2, 2,
  1271.         /*iWMATE  vs*/
  1272.                 1, 3, 1, 1,     1, 1, 1, 1,
  1273.         /*iBMATE  vs*/
  1274.                 2, 2, 4, 1,     2, 2, 2, 2,
  1275.         /*iFORBID vs*/
  1276.                 2, 2, 2, 2,     2, 2, 2, 2,
  1277.  
  1278.         /*iDRAWt  vs*/
  1279.                 1, 2, 1, 1,     2, 2, 1, 2,
  1280.         /*iWMATEt vs*/
  1281.                 1, 2, 1, 1,     1, 3, 1, 1,
  1282.         /*iBMATEt vs*/
  1283.                 1, 2, 1, 1,     2, 2, 4, 2,
  1284.         /*iUNKNOWN  */
  1285.                 1, 2, 1, 1,     1, 2, 1, 2,
  1286.  
  1287.         /*Black*/
  1288.         /*iDRAW   vs*/
  1289.                 1, 1, 2, 1,     2, 2, 2, 2,
  1290.         /*iWMATE  vs*/
  1291.                 2, 4, 2, 1,     2, 2, 2, 2,
  1292.         /*iBMATE  vs*/
  1293.                 1, 1, 3, 1,     1, 1, 1, 1,
  1294.         /*iFORBID vs*/
  1295.                 2, 2, 2, 2,     2, 2, 2, 2,
  1296.  
  1297.         /*iDRAWt  vs*/
  1298.                 1, 1, 2, 1,     2, 1, 2, 2,
  1299.         /*iWMATEt vs*/
  1300.                 1, 1, 2, 1,     2, 4, 2, 2,
  1301.         /*iBMATEt vs*/
  1302.                 1, 1, 2, 1,     1, 1, 3, 1,
  1303.         /*iUNKNOWN  */
  1304.                 1, 1, 2, 1,     1, 1, 2, 2
  1305.         };
  1306.  
  1307.         int i, j, k, z;
  1308.  
  1309.         /* reset */
  1310.         z = 0;
  1311.         for (i = 0; i < 2; i++)
  1312.                 for (j = 0; j < 8; j++)
  1313.                         for (k = 0; k < 8; k++)
  1314.                                 bettarr [i][j][k] = temp[z++];
  1315.  
  1316.         return;
  1317. }
  1318. #endif
  1319.  
  1320. /*
  1321. |
  1322. |       Own File Descriptors
  1323. |
  1324. \*---------------------------------------------------------------------------*/
  1325.  
  1326. static bool_t
  1327. fd_init (struct filesopen *pfd)
  1328. {
  1329.         tbkey_t *p;
  1330.     int i, allowed;
  1331.  
  1332.         pfd->n = 0;
  1333.  
  1334.         allowed = mysys_fopen_max() - 5 /*stdin,stdout,sterr,stdlog,book*/;
  1335.         if (allowed < 4)
  1336.                 GTB_MAXOPEN = 4;
  1337.         if (allowed > 32)
  1338.                 GTB_MAXOPEN = 32;
  1339.  
  1340.         p =     (tbkey_t *) malloc(sizeof(tbkey_t)*(size_t)GTB_MAXOPEN);
  1341.  
  1342.         if (p != NULL) {
  1343.                 for (i = 0; i < GTB_MAXOPEN; i++) {
  1344.                         p[i] = -1;
  1345.                 }
  1346.                 pfd->key = p;
  1347.                 return TRUE;
  1348.         } else {
  1349.                 return FALSE;
  1350.         }
  1351. }
  1352.  
  1353. static void
  1354. fd_done (struct filesopen *pfd)
  1355. {
  1356.     int i;
  1357.         tbkey_t closingkey;
  1358.         FILE *finp;
  1359.  
  1360.         assert(pfd != NULL);
  1361.  
  1362.         for (i = 0; i < pfd->n; i++) {
  1363.                 closingkey = pfd->key[i];
  1364.                 finp = egkey [closingkey].fd;
  1365.                 fclose (finp);
  1366.                 egkey[closingkey].fd = NULL;
  1367.                 pfd->key[i] = -1;
  1368.         }
  1369.         pfd->n = 0;
  1370.         free(pfd->key);
  1371. }
  1372.  
  1373. /****************************************************************************\
  1374. |
  1375. |
  1376. |                                                               PROBE ZONE
  1377. |
  1378. |
  1379. \****************************************************************************/
  1380.  
  1381. #if !defined(SHARED_forbuilding)
  1382.  
  1383. /* shared with building routines */
  1384. mySHARED void                   list_sq_copy    (const SQUARE *a, SQUARE *b);
  1385. mySHARED void                   list_pc_copy    (const SQ_CONTENT *a, SQ_CONTENT *b);
  1386. mySHARED dtm_t                  inv_dtm                 (dtm_t x);
  1387. mySHARED bool_t                 egtb_get_id     (SQ_CONTENT *w, SQ_CONTENT *b, tbkey_t *id);
  1388. mySHARED void                   list_sq_flipNS  (SQUARE *s);
  1389. mySHARED dtm_t                  adjust_up               (dtm_t dist);
  1390. mySHARED dtm_t                  bestx                   (unsigned stm, dtm_t a, dtm_t b);
  1391. mySHARED void                   sortlists               (SQUARE *ws, SQ_CONTENT *wp);
  1392.  
  1393. mySHARED /*@NULL@*/     FILE * fd_openit(tbkey_t key);
  1394.  
  1395. mySHARED dtm_t                  dtm_unpack      (unsigned stm, unsigned char packed);
  1396. mySHARED void                   unpackdist      (dtm_t d, unsigned int *res, unsigned int *ply);
  1397. mySHARED dtm_t                  packdist        (unsigned int inf, unsigned int ply);
  1398.  
  1399. mySHARED bool_t                 fread_entry_packed      (FILE *dest, unsigned side, dtm_t *px);
  1400. mySHARED bool_t                 fpark_entry_packed  (FILE *finp, unsigned side, index_t max, index_t idx);
  1401. #endif
  1402.  
  1403. /* use only with probe */
  1404. static bool_t                   egtb_get_dtm    (tbkey_t k, unsigned stm, const SQUARE *wS, const SQUARE *bS, bool_t probe_hard, dtm_t *dtm);
  1405. static void                             removepiece (SQUARE *ys, SQ_CONTENT *yp, int j);
  1406. static bool_t                   egtb_filepeek (tbkey_t key, unsigned side, index_t idx, dtm_t *out_dtm);
  1407.  
  1408.  
  1409. /*prototype*/
  1410. #ifdef WDL_PROBE
  1411. static bool_t
  1412. tb_probe_wdl
  1413.                         (unsigned stm,
  1414.                          const SQUARE *inp_wSQ,
  1415.                          const SQUARE *inp_bSQ,
  1416.                          const SQ_CONTENT *inp_wPC,
  1417.                          const SQ_CONTENT *inp_bPC,
  1418.                          bool_t probingtype,
  1419.                          /*@out@*/ unsigned *res);
  1420. #endif
  1421.  
  1422. static bool_t
  1423. tb_probe_       (unsigned stm,
  1424.                          SQUARE epsq,
  1425.                          const SQUARE *inp_wSQ,
  1426.                          const SQUARE *inp_bSQ,
  1427.                          const SQ_CONTENT *inp_wPC,
  1428.                          const SQ_CONTENT *inp_bPC,
  1429.                          bool_t probingtype,
  1430.                          /*@out@*/ unsigned *res,
  1431.                          /*@out@*/ unsigned *ply);
  1432.  
  1433.  
  1434. extern bool_t
  1435. tb_probe_soft
  1436.                         (unsigned stm,
  1437.                          SQUARE epsq,
  1438.                          unsigned castles,
  1439.                          const SQUARE *inp_wSQ,
  1440.                          const SQUARE *inp_bSQ,
  1441.                          const SQ_CONTENT *inp_wPC,
  1442.                          const SQ_CONTENT *inp_bPC,
  1443.                          /*@out@*/ unsigned *res,
  1444.                          /*@out@*/ unsigned *ply)
  1445. {
  1446.         if (castles != 0)
  1447.                 return FALSE;
  1448.         return tb_probe_ (stm, epsq, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, FALSE, res, ply);
  1449. }
  1450.  
  1451. extern bool_t
  1452. tb_probe_hard
  1453.                         (unsigned stm,
  1454.                          SQUARE epsq,
  1455.                          unsigned castles,
  1456.                          const SQUARE *inp_wSQ,
  1457.                          const SQUARE *inp_bSQ,
  1458.                          const SQ_CONTENT *inp_wPC,
  1459.                          const SQ_CONTENT *inp_bPC,
  1460.                          /*@out@*/ unsigned *res,
  1461.                          /*@out@*/ unsigned *ply)
  1462. {
  1463.         if (castles != 0)
  1464.                 return FALSE;
  1465.         return tb_probe_ (stm, epsq, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, TRUE, res, ply);
  1466. }
  1467.  
  1468. extern bool_t
  1469. tb_probe_WDL_soft
  1470.                         (unsigned stm,
  1471.                          SQUARE epsq,
  1472.                          unsigned castles,
  1473.                          const SQUARE *inp_wSQ,
  1474.                          const SQUARE *inp_bSQ,
  1475.                          const SQ_CONTENT *inp_wPC,
  1476.                          const SQ_CONTENT *inp_bPC,
  1477.                          /*@out@*/ unsigned *res)
  1478. {
  1479.         unsigned ply_n;
  1480.         unsigned *ply = &ply_n;
  1481.         if (castles != 0)
  1482.                 return FALSE;
  1483.         if (epsq != NOSQUARE)
  1484.                 return tb_probe_ (stm, epsq, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, FALSE, res, ply);
  1485.  
  1486.         /* probe bitbase like, assuming no en passant */
  1487.         #ifdef WDL_PROBE
  1488.         return tb_probe_wdl    (stm, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, FALSE, res);
  1489.         #else
  1490.         return tb_probe_ (stm, epsq, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, FALSE, res, ply);
  1491.         #endif
  1492. }
  1493.  
  1494. extern bool_t
  1495. tb_probe_WDL_hard
  1496.                         (unsigned stm,
  1497.                          SQUARE epsq,
  1498.                          unsigned castles,
  1499.                          const SQUARE *inp_wSQ,
  1500.                          const SQUARE *inp_bSQ,
  1501.                          const SQ_CONTENT *inp_wPC,
  1502.                          const SQ_CONTENT *inp_bPC,
  1503.                          /*@out@*/ unsigned *res)
  1504. {
  1505.         unsigned ply_n;
  1506.         unsigned *ply = &ply_n;
  1507.         if (castles != 0)
  1508.                 return FALSE;
  1509.         if (epsq != NOSQUARE)
  1510.                 return tb_probe_ (stm, epsq, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, TRUE, res, ply);
  1511.  
  1512.         /* probe bitbase like, assuming no en passant */
  1513.         #ifdef WDL_PROBE
  1514.         return tb_probe_wdl    (stm, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, TRUE, res);
  1515.         #else
  1516.         return tb_probe_ (stm, epsq, inp_wSQ, inp_bSQ, inp_wPC, inp_bPC, TRUE, res, ply);
  1517.         #endif
  1518. }
  1519.  
  1520.  
  1521. static bool_t
  1522. tb_probe_       (unsigned stm,
  1523.                          SQUARE epsq,
  1524.                          const SQUARE *inp_wSQ,
  1525.                          const SQUARE *inp_bSQ,
  1526.                          const SQ_CONTENT *inp_wPC,
  1527.                          const SQ_CONTENT *inp_bPC,
  1528.                          bool_t probingtype,
  1529.                          /*@out@*/ unsigned *res,
  1530.                          /*@out@*/ unsigned *ply)
  1531. {
  1532.         int i = 0, j = 0;
  1533.         tbkey_t id = -1;
  1534.         dtm_t dtm = 0;
  1535.  
  1536.         SQUARE          storage_ws [MAX_LISTSIZE], storage_bs [MAX_LISTSIZE];
  1537.         SQ_CONTENT  storage_wp [MAX_LISTSIZE], storage_bp [MAX_LISTSIZE];
  1538.  
  1539.         SQUARE     *ws = storage_ws;
  1540.         SQUARE     *bs = storage_bs;
  1541.         SQ_CONTENT *wp = storage_wp;
  1542.         SQ_CONTENT *bp = storage_bp;
  1543.  
  1544.         SQUARE     *xs;
  1545.         SQUARE     *ys;
  1546.         SQ_CONTENT *xp;
  1547.         SQ_CONTENT *yp;
  1548.  
  1549.         SQUARE          tmp_ws [MAX_LISTSIZE], tmp_bs [MAX_LISTSIZE];
  1550.         SQ_CONTENT  tmp_wp [MAX_LISTSIZE], tmp_bp [MAX_LISTSIZE];
  1551.  
  1552.         SQUARE *temps;
  1553.         bool_t straight = FALSE;
  1554.  
  1555.         SQUARE capturer_a, capturer_b, xed = NOSQUARE;
  1556.  
  1557.         unsigned int plies;
  1558.         unsigned int inf;
  1559.  
  1560.         bool_t  okdtm  = TRUE;
  1561.         bool_t  okcall = TRUE;
  1562.  
  1563.         /************************************/
  1564.  
  1565.         assert (stm == WH || stm == BL);
  1566.         /*assert (inp_wPC[0] == KING && inp_bPC[0] == KING );*/
  1567.         assert ((epsq >> 3) == 2 || (epsq >> 3) == 5 || epsq == NOSQUARE);
  1568.  
  1569.         /* VALID ONLY FOR KK!! */
  1570.         if (inp_wPC[1] == NOPIECE && inp_bPC[1] == NOPIECE) {
  1571.                 index_t dummy_i;
  1572.                 bool_t b = kxk_pctoindex (inp_wSQ, inp_bSQ, &dummy_i);
  1573.                 *res = b? iDRAW: iFORBID;
  1574.                 *ply = 0;
  1575.                 return TRUE;
  1576.         }
  1577.  
  1578.         /* copy input */
  1579.         list_pc_copy (inp_wPC, wp);
  1580.         list_pc_copy (inp_bPC, bp);
  1581.         list_sq_copy (inp_wSQ, ws);
  1582.         list_sq_copy (inp_bSQ, bs);
  1583.  
  1584.         sortlists (ws, wp);
  1585.         sortlists (bs, bp);
  1586.  
  1587.         FOLLOW_label("EGTB_PROBE")
  1588.  
  1589.         if (egtb_get_id (wp, bp, &id)) {
  1590.                 FOLLOW_LU("got ID",id)
  1591.                 straight = TRUE;
  1592.         } else if (egtb_get_id (bp, wp, &id)) {
  1593.                 FOLLOW_LU("rev ID",id)
  1594.                 straight = FALSE;
  1595.                 list_sq_flipNS (ws);
  1596.                 list_sq_flipNS (bs);
  1597.         temps = ws;
  1598.         ws = bs;
  1599.         bs = temps;
  1600.                 stm = Opp(stm);
  1601.                 if (epsq != NOSQUARE) epsq ^= 070;                              /* added */
  1602.                 {SQ_CONTENT *tempp = wp; wp = bp; bp = tempp;}  /* added */
  1603.         } else {
  1604.                 #if defined(DEBUG)
  1605.                 printf("did not get id...\n");
  1606.                 output_state (stm, ws, bs, wp, bp);
  1607.                 #endif
  1608.                 unpackdist (iFORBID, res, ply);
  1609.                 return FALSE;
  1610.         }
  1611.  
  1612.         /* store position... */
  1613.         list_pc_copy (wp, tmp_wp);
  1614.         list_pc_copy (bp, tmp_bp);
  1615.         list_sq_copy (ws, tmp_ws);
  1616.         list_sq_copy (bs, tmp_bs);
  1617.  
  1618.         /* x will be stm and y will be stw */
  1619.         if (stm == WH) {
  1620.         xs = ws;
  1621.         xp = wp;
  1622.         ys = bs;
  1623.         yp = bp;
  1624.     } else {
  1625.         xs = bs;
  1626.         xp = bp;
  1627.         ys = ws;
  1628.         yp = wp;
  1629.         }
  1630.  
  1631.         okdtm = egtb_get_dtm (id, stm, ws, bs, probingtype, &dtm);
  1632.  
  1633.         FOLLOW_LU("dtmok?",okdtm)
  1634.         FOLLOW_DTM("dtm", dtm)
  1635.  
  1636.         if (okdtm) {
  1637.  
  1638.                 capturer_a = NOSQUARE;
  1639.                 capturer_b = NOSQUARE;
  1640.  
  1641.                 if (epsq != NOSQUARE) {
  1642.                         /* captured pawn, trick: from epsquare to captured */
  1643.                         xed = epsq ^ (1<<3);
  1644.  
  1645.                         /* find index captured (j) */
  1646.                         for (j = 0; ys[j] != NOSQUARE; j++) {
  1647.                                 if (ys[j] == xed) break;
  1648.                         }
  1649.  
  1650.                         /* try first possible ep capture */
  1651.                         if (0 == (0x88 & (map88(xed) + 1)))
  1652.                                 capturer_a = xed + 1;
  1653.                         /* try second possible ep capture */
  1654.                         if (0 == (0x88 & (map88(xed) - 1)))
  1655.                                 capturer_b = xed - 1;
  1656.  
  1657.                         if (ys[j] == xed) {
  1658.  
  1659.                                 /* find capturers (i) */
  1660.                                 for (i = 0; xs[i] != NOSQUARE && okcall; i++) {
  1661.  
  1662.                                         if (xp[i]==PAWN && (xs[i]==capturer_a || xs[i]==capturer_b)) {
  1663.                                                 dtm_t epscore = iFORBID;
  1664.  
  1665.                                                 /* execute capture */
  1666.                                                 xs[i] = epsq;
  1667.                                                 removepiece (ys, yp, j);
  1668.  
  1669.                                                 okcall = tb_probe_ (Opp(stm), NOSQUARE, ws, bs, wp, bp, probingtype, &inf, &plies);
  1670.  
  1671.                                                 if (okcall) {
  1672.                                                         epscore = packdist (inf, plies);
  1673.                                                         epscore = adjust_up (epscore);
  1674.  
  1675.                                                         /* chooses to ep or not */
  1676.                                                         dtm = bestx (stm, epscore, dtm);
  1677.                                                 }
  1678.  
  1679.                                                 /* restore position */
  1680.                                                 list_pc_copy (tmp_wp, wp);
  1681.                                                 list_pc_copy (tmp_bp, bp);
  1682.  
  1683.                                                 list_sq_copy (tmp_ws, ws);
  1684.                                                 list_sq_copy (tmp_bs, bs);
  1685.                                         }
  1686.                                 }
  1687.                         }
  1688.                 } /* ep */
  1689.  
  1690.                 if (straight) {
  1691.                         unpackdist (dtm, res, ply);
  1692.                 } else {
  1693.                         unpackdist (inv_dtm (dtm), res, ply);
  1694.                 }
  1695.         }
  1696.  
  1697.         if (!okdtm || !okcall) {
  1698.                 unpackdist (iFORBID, res, ply);
  1699.         }
  1700.  
  1701.         return okdtm && okcall;
  1702. }
  1703.  
  1704. #ifdef _MSC_VER
  1705. /* to silence warning for sprintf usage */
  1706. #pragma warning(disable:4996)
  1707. #endif
  1708.  
  1709. static bool_t
  1710. egtb_filepeek (tbkey_t key, unsigned side, index_t idx, dtm_t *out_dtm)
  1711. {
  1712.         FILE *finp;
  1713.  
  1714. #define USE_FD
  1715.  
  1716.         #if !defined(USE_FD)
  1717.         char buf[1024];
  1718.         char *filename = buf;
  1719.         #endif
  1720.  
  1721.         bool_t ok;
  1722.     dtm_t x=0;
  1723.         index_t maxindex  = egkey[key].maxindex;
  1724.  
  1725.  
  1726.  
  1727.         assert (Uncompressed);
  1728.         assert (side == WH || side == BL);
  1729.         assert (out_dtm != NULL);
  1730.         assert (idx >= 0);
  1731.         assert (key < MAX_EGKEYS);
  1732.  
  1733.  
  1734.         #if defined(USE_FD)
  1735.                 if (NULL == (finp = egkey[key].fd) ) {
  1736.                         if (NULL == (finp = fd_openit (key))) {
  1737.                                 return FALSE;
  1738.                         }
  1739.                 }
  1740.         #else
  1741.                 sprintf (buf, "%s.gtb", egkey[key].str);
  1742.                 if (NULL == (finp = fopen (filename, "rb"))) {
  1743.                         return FALSE;
  1744.                 }
  1745.         #endif
  1746.  
  1747.         ok = fpark_entry_packed (finp, side, maxindex, idx);
  1748.         ok = ok && fread_entry_packed (finp, side, &x);
  1749.  
  1750.         if (ok) {
  1751.                 *out_dtm = x;
  1752.         } else
  1753.                 *out_dtm = iFORBID;
  1754.  
  1755.         #if !defined(USE_FD)
  1756.         fclose (finp);
  1757.         #endif
  1758.  
  1759.         return ok;
  1760. }
  1761.  
  1762. /* will get defined later */
  1763. static bool_t                   dtm_cache_is_on (void);
  1764.  
  1765. static bool_t
  1766. egtb_get_dtm (tbkey_t k, unsigned stm, const SQUARE *wS, const SQUARE *bS, bool_t probe_hard_flag, dtm_t *dtm)
  1767. {
  1768.         bool_t idxavail;
  1769.         index_t idx;
  1770.         dtm_t *tab[2];
  1771.         bool_t (*pc2idx) (const SQUARE *, const SQUARE *, index_t *);
  1772.  
  1773.         FOLLOW_label("egtb_get_dtm --> starts")
  1774.  
  1775.         if (egkey[k].status == STATUS_MALLOC || egkey[k].status == STATUS_STATICRAM) {
  1776.  
  1777.                 tab[WH] = egkey[k].egt_w;
  1778.                 tab[BL] = egkey[k].egt_b;
  1779.                 pc2idx  = egkey[k].pctoi;
  1780.  
  1781.                 idxavail = pc2idx (wS, bS, &idx);
  1782.  
  1783.                 FOLLOW_LU("indexavail (RAM)",idxavail)
  1784.  
  1785.                 if (idxavail) {
  1786.                         *dtm = tab[stm][idx];
  1787.                 } else {
  1788.                         *dtm = iFORBID;
  1789.                 }
  1790.  
  1791.                 return TRUE;
  1792.  
  1793.         } else if (egkey[k].status == STATUS_ABSENT) {
  1794.  
  1795.                 pc2idx   = egkey[k].pctoi;
  1796.                 idxavail = pc2idx (wS, bS, &idx);
  1797.  
  1798.                 FOLLOW_LU("indexavail (HD)",idxavail)
  1799.  
  1800.                 if (idxavail) {
  1801.                         bool_t success;
  1802.  
  1803.                         /*
  1804.                         |               LOCK
  1805.                         *-------------------------------*/
  1806.                         mythread_mutex_lock (&Egtb_lock);
  1807.  
  1808.                         if (dtm_cache_is_on()) {
  1809.  
  1810.                                 success = get_dtm       (k, stm, idx, dtm, probe_hard_flag);
  1811.  
  1812.                                 FOLLOW_LU("get_dtm (succ)",success)
  1813.                                 FOLLOW_LU("get_dtm (dtm )",*dtm)
  1814.  
  1815.                                         #if defined(DEBUG)
  1816.                                         if (Uncompressed) {
  1817.                                                 dtm_t   dtm_temp;
  1818.                                                 bool_t  ok;
  1819.                                                 bool_t  success2;
  1820.  
  1821.                                                 assert (decoding_scheme() == 0 && GTB_scheme == 0);
  1822.  
  1823.                                                 success2 = egtb_filepeek (k, stm, idx, &dtm_temp);
  1824.                                                 ok =  (success == success2) && (!success || *dtm == dtm_temp);
  1825.                                                 if (!ok) {
  1826.                                                         printf ("\nERROR\nsuccess1=%d sucess2=%d\n"
  1827.                                                                         "k=%d stm=%u idx=%d dtm_peek=%d dtm_cache=%d\n",
  1828.                                                                         success, success2, k, stm, idx, dtm_temp, *dtm);
  1829.                                                         fatal_error();
  1830.                                                 }
  1831.                                         }
  1832.                                         #endif
  1833.  
  1834.                         } else {
  1835.                                 assert(Uncompressed);
  1836.                                 if (probe_hard_flag && Uncompressed)
  1837.                                         success = egtb_filepeek (k, stm, idx, dtm);
  1838.                                 else
  1839.                                         success = FALSE;
  1840.                         }
  1841.  
  1842.                         mythread_mutex_unlock (&Egtb_lock);
  1843.                         /*------------------------------*\
  1844.                         |               UNLOCK
  1845.                         */
  1846.  
  1847.  
  1848.                         if (success) {
  1849.                                 return TRUE;
  1850.                         } else {
  1851.                                 if (probe_hard_flag) /* after probing hard and failing, no chance to succeed later */
  1852.                                         egkey[k].status = STATUS_REJECT;
  1853.                                 *dtm = iUNKNOWN;
  1854.                                 return FALSE;
  1855.                         }
  1856.  
  1857.                 } else {
  1858.                         *dtm = iFORBID;
  1859.                         return  TRUE;
  1860.                 }
  1861.  
  1862.         } else if (egkey[k].status == STATUS_REJECT) {
  1863.  
  1864.                 FOLLOW_label("STATUS_REJECT")
  1865.  
  1866.                 *dtm = iFORBID;
  1867.                 return  FALSE;
  1868.         } else {
  1869.  
  1870.                 FOLLOW_label("STATUS_WRONG!")
  1871.  
  1872.                 assert(0);
  1873.                 *dtm = iFORBID;
  1874.                 return  FALSE;
  1875.         }
  1876.  
  1877. }
  1878.  
  1879. static void
  1880. removepiece (SQUARE *ys, SQ_CONTENT *yp, int j)
  1881. {
  1882.     int k;
  1883.         for (k = j; ys[k] != NOSQUARE; k++) {
  1884.                 ys[k] = ys[k+1];
  1885.                 yp[k] = yp[k+1];
  1886.         }
  1887. }
  1888.  
  1889. /*
  1890. |
  1891. |       mySHARED by probe and build
  1892. |
  1893. \*----------------------------------------------------*/
  1894.  
  1895. mySHARED /*@NULL@*/ FILE *
  1896. fd_openit (tbkey_t key)
  1897. {
  1898.         int                     i;
  1899.         tbkey_t                 closingkey;
  1900.         FILE *                  finp = NULL;
  1901.         char                    buf[4096];
  1902.         char *                  filename = buf;
  1903.         int                     start;
  1904.         int                             end;
  1905.         int                             pth;
  1906.         const char *    extension;
  1907.  
  1908.         assert (0 <= key && key < MAX_EGKEYS);
  1909.         assert (0 <= fd.n && fd.n <= GTB_MAXOPEN);
  1910.  
  1911.         /* test if I reach limit of files open */
  1912.         if (fd.n == GTB_MAXOPEN) {
  1913.  
  1914.                 /* fclose the last accessed, first in the list */
  1915.                 closingkey = fd.key[0];
  1916.                 finp = egkey [closingkey].fd;
  1917.                 assert (finp != NULL);
  1918.                 fclose (finp);
  1919.                 egkey[closingkey].fd = NULL;
  1920.                 finp = NULL;
  1921.  
  1922.                 for (i = 1; i < fd.n; i++) {
  1923.                         fd.key[i-1] = fd.key[i];
  1924.                 }
  1925.                 fd.key[--fd.n] = -1;
  1926.         }
  1927.  
  1928.         assert (fd.n < GTB_MAXOPEN);
  1929.  
  1930.         /* set proper extensions to the File */
  1931.         if (Uncompressed) {
  1932.                 assert (decoding_scheme() == 0 && GTB_scheme == 0);
  1933.                 extension = ".gtb";
  1934.         } else {
  1935.                 extension = Extension[decoding_scheme()];
  1936.         }
  1937.  
  1938.         /* Scan folders to find the File*/
  1939.         finp = NULL;
  1940.  
  1941.         start = egkey[key].pathn;
  1942.         end   = Gtbpath_end_index;
  1943.  
  1944. /*@@
  1945. printf ("start: %d\n",start);
  1946. printf ("===================Gtbpath[0]=%s\n",Gtbpath[0]);
  1947. */
  1948.         for (pth = start; NULL == finp && pth < end && Gtbpath[pth] != NULL; pth++) {
  1949.                 const char *path = Gtbpath[pth];
  1950.                 size_t pl = strlen(path);
  1951. /*@@
  1952. printf ("path: %s\n",path);
  1953. */
  1954.                 if (pl == 0) {
  1955.                                 sprintf (buf, "%s%s%s", path, egkey[key].str, extension);
  1956.                 } else {
  1957.                         if (isfoldersep( path[pl-1] )) {
  1958.                                 sprintf (buf, "%s%s%s", path, egkey[key].str, extension);
  1959.                         } else {
  1960.                                 sprintf (buf, "%s%s%s%s", path, FOLDERSEP, egkey[key].str, extension);
  1961.                         }
  1962.                 }
  1963. /*printf ("try to open %s   --> ",filename);*/
  1964.                 /* Finally found the file? */
  1965.                 finp = fopen (filename, "rb");
  1966. /*printf ("%d\n",finp != NULL);*/
  1967.         }
  1968.  
  1969.         /* File was found and opened */
  1970.         if (NULL != finp) {
  1971.                 fd.key [fd.n++] = key;
  1972.                 egkey[key].fd = finp;
  1973.                 egkey[key].pathn = pth; /* remember succesful path */
  1974.                 eg_was_open[key] = 1;
  1975.                 return finp;
  1976.         }
  1977.  
  1978.         start = 0;
  1979.         end   = egkey[key].pathn;
  1980.         for (pth = start; NULL == finp && pth < end && Gtbpath[pth] != NULL; pth++) {
  1981.                 const char *path = Gtbpath[pth];
  1982.                 size_t pl = strlen(path);
  1983.  
  1984.                 if (pl == 0) {
  1985.                                 sprintf (buf, "%s%s%s", path, egkey[key].str, extension);
  1986.                 } else {
  1987.                         if (isfoldersep( path[pl-1] )) {
  1988.                                 sprintf (buf, "%s%s%s", path, egkey[key].str, extension);
  1989.                         } else {
  1990.                                 sprintf (buf, "%s%s%s%s", path, FOLDERSEP, egkey[key].str, extension);
  1991.                         }
  1992.                 }
  1993. /*printf ("try to open %s   --> ",filename);*/
  1994.                 /* Finally found the file? */
  1995.                 finp = fopen (filename, "rb");
  1996. /*printf ("%d\n",finp != NULL);*/
  1997.         }
  1998.  
  1999.  
  2000.         /* File was found and opened */
  2001.         if (NULL != finp) {
  2002.                 fd.key [fd.n++] = key;
  2003.                 egkey[key].fd = finp;
  2004.                 egkey[key].pathn = pth; /* remember succesful path */
  2005.                 eg_was_open[key] = 1;
  2006.         }
  2007.  
  2008.         return finp;
  2009. }
  2010.  
  2011. #ifdef _MSC_VER
  2012. /* to silence warning for sprintf usage */
  2013. #pragma warning(default:4996)
  2014. #endif
  2015.  
  2016. mySHARED void
  2017. sortlists (SQUARE *ws, SQ_CONTENT *wp)
  2018. {
  2019.         int i, j;
  2020.         SQUARE ts;
  2021.         SQ_CONTENT tp;
  2022.         /* input is sorted */
  2023.         for (i = 0; wp[i] != NOPIECE; i++) {
  2024.                 for (j = (i+1); wp[j] != NOPIECE; j++) {
  2025.                         if (wp[j] > wp[i]) {
  2026.                                 tp = wp[i]; wp[i] = wp[j]; wp[j] = tp;
  2027.                                 ts = ws[i]; ws[i] = ws[j]; ws[j] = ts;
  2028.                         }
  2029.                 }
  2030.         }
  2031. }
  2032.  
  2033. mySHARED void
  2034. list_sq_copy (const SQUARE *a, SQUARE *b)
  2035. {
  2036.         while (NOSQUARE != (*b++ = *a++))
  2037.                 ;
  2038. }
  2039.  
  2040. mySHARED void
  2041. list_pc_copy (const SQ_CONTENT *a, SQ_CONTENT *b)
  2042. {
  2043.         while (NOPIECE != (*b++ = *a++))
  2044.                 ;
  2045. }
  2046.  
  2047. mySHARED dtm_t
  2048. inv_dtm (dtm_t x)
  2049. {
  2050.         unsigned mat;
  2051.         assert ( (x & iUNKNBIT) == 0);
  2052.  
  2053.         if (x == iDRAW || x == iFORBID)
  2054.                 return x;
  2055.  
  2056.         mat = (unsigned)x & 3u;
  2057.         if (mat == iWMATE)
  2058.                 mat = iBMATE;
  2059.         else
  2060.                 mat = iWMATE;
  2061.  
  2062.         x = (dtm_t) (((unsigned)x & ~3u) | mat);
  2063.  
  2064.         return x;
  2065. }
  2066.  
  2067. static const char pctoch[] = {'-','p','n','b','r','q','k'};
  2068.  
  2069. mySHARED bool_t
  2070. egtb_get_id (SQ_CONTENT *w, SQ_CONTENT *b, tbkey_t *id)
  2071. {
  2072.  
  2073.         char pcstr[2*MAX_LISTSIZE];
  2074.         SQ_CONTENT *s;
  2075.         char *t;
  2076.         bool_t found;
  2077.         tbkey_t i;
  2078.         static tbkey_t cache_i = 0;
  2079.         size_t h1, h2;
  2080.  
  2081.         assert (PAWN == 1 && KNIGHT == 2 && BISHOP == 3 && ROOK == 4 && QUEEN == 5 && KING == 6);
  2082.  
  2083.         t = pcstr;
  2084.  
  2085.         s = w;
  2086.         while (NOPIECE != *s)
  2087.                 *t++ = pctoch[*s++];
  2088.         s = b;
  2089.         while (NOPIECE != *s)
  2090.                 *t++ = pctoch[*s++];
  2091.  
  2092.         *t = '\0';
  2093.  
  2094.         found = (0 == strcmp(pcstr, egkey[cache_i].str));
  2095.         if (found) {
  2096.                 *id = cache_i;
  2097.                 return found;
  2098.         }
  2099.  
  2100.         h1 = str_hash_func_1 (pcstr) & (EGKEY_HASH_SIZE - 1);
  2101.         h2 = str_hash_func_2 (pcstr);
  2102.         while (1) {
  2103.                 i = egkey_hash[h1];
  2104.                 if (i < 0)
  2105.                         break;
  2106.                 found = (0 == strcmp(pcstr, egkey[i].str));
  2107.                 if (found)
  2108.                         break;
  2109.                 h1 = (h1 + h2) & (EGKEY_HASH_SIZE - 1);
  2110.         }
  2111.         if (found) {
  2112.                 cache_i = *id = i;
  2113.         }
  2114.  
  2115.         return found;
  2116. }
  2117.  
  2118. mySHARED void
  2119. list_sq_flipNS (SQUARE *s)
  2120. {
  2121.         while (*s != NOSQUARE) {
  2122.                 *s ^= 070;
  2123.                 s++;
  2124.         }
  2125. }
  2126.  
  2127. mySHARED void
  2128. unpackdist (dtm_t d, unsigned int *res, unsigned int *ply)
  2129. {
  2130.         *ply = (unsigned int)d >> PLYSHIFT;
  2131.         *res = d & INFOMASK;
  2132. }
  2133.  
  2134. mySHARED dtm_t
  2135. packdist (unsigned int inf, unsigned int ply)
  2136. {
  2137.         assert (inf <= INFOMASK);
  2138.         return (dtm_t) (inf | ply << PLYSHIFT);
  2139. }
  2140.  
  2141. mySHARED dtm_t
  2142. adjust_up (dtm_t dist)
  2143. {
  2144.         #if 0
  2145.         static const dtm_t adding[] = {
  2146.                 0, 1<<PLYSHIFT, 1<<PLYSHIFT, 0,
  2147.                 0, 1<<PLYSHIFT, 1<<PLYSHIFT, 0
  2148.         };
  2149.         dist += adding [dist&INFOMASK];
  2150.         return dist;
  2151.         #else
  2152.         unsigned udist = (unsigned) dist;
  2153.         switch (udist & INFOMASK) {
  2154.                 case iWMATE:
  2155.                 case iWMATEt:
  2156.                 case iBMATE:
  2157.                 case iBMATEt:
  2158.                         udist += (1u << PLYSHIFT);
  2159.                         break;
  2160.                 default:
  2161.                         break;
  2162.         }
  2163.         return (dtm_t) udist;
  2164.         #endif
  2165. }
  2166.  
  2167.  
  2168. mySHARED dtm_t
  2169. bestx (unsigned stm, dtm_t a, dtm_t b)
  2170. {
  2171.         unsigned int key;
  2172.         static const unsigned int
  2173.         comparison [4] [4] = {
  2174.                                 /*draw, wmate, bmate, forbid*/
  2175.         /* draw  */ {0, 3, 0, 0},
  2176.         /* wmate */ {0, 1, 0, 0},
  2177.         /* bmate */ {3, 3, 2, 0},
  2178.         /* forbid*/ {3, 3, 3, 0}
  2179.  
  2180.         /* 0 = selectfirst   */
  2181.         /* 1 = selectlowest  */
  2182.         /* 2 = selecthighest */
  2183.         /* 3 = selectsecond  */
  2184.         };
  2185.  
  2186.         static const unsigned int xorkey [2] = {0, 3};
  2187.         dtm_t retu[4];
  2188.         dtm_t ret = iFORBID;
  2189.  
  2190.         assert (stm == WH || stm == BL);
  2191.         assert ((a & iUNKNBIT) == 0 && (b & iUNKNBIT) == 0 );
  2192.  
  2193.         if (a == iFORBID)
  2194.                 return b;
  2195.         if (b == iFORBID)
  2196.                 return a;
  2197.  
  2198.         retu[0] = a; /* first parameter */
  2199.         retu[1] = a; /* the lowest by default */
  2200.         retu[2] = b; /* highest by default */
  2201.         retu[3] = b; /* second parameter */
  2202.         if (b < a) {
  2203.                 retu[1] = b;
  2204.                 retu[2] = a;
  2205.         }
  2206.  
  2207.         key = comparison [a&3] [b&3] ^ xorkey[stm];
  2208.         ret = retu [key];
  2209.  
  2210.         return ret;
  2211. }
  2212.  
  2213.  
  2214. /*--------------------------------------------------------------------------*\
  2215.  |                                                              PACKING ZONE
  2216.  *--------------------------------------------------------------------------*/
  2217.  
  2218. inline
  2219. mySHARED dtm_t
  2220. dtm_unpack (unsigned stm, unsigned char packed)
  2221. {
  2222.         unsigned int info, plies, prefx, store, moves;
  2223.         dtm_t ret;
  2224.         unsigned int p = packed;
  2225.  
  2226.         if (iDRAW == p || iFORBID == p) {
  2227.                 return (dtm_t) p;
  2228.         }
  2229.  
  2230.         info  = (unsigned int) p & 3;
  2231.         store = (unsigned int) p >> 2;
  2232.  
  2233.         if (WH == stm) {
  2234.                 switch (info) {
  2235.                         case iWMATE:
  2236.                                                 moves = store + 1;
  2237.                                                 plies = moves * 2 - 1;
  2238.                                                 prefx = info;
  2239.                                                 break;
  2240.  
  2241.                         case iBMATE:
  2242.                                                 moves = store;
  2243.                                                 plies = moves * 2;
  2244.                                                 prefx = info;
  2245.                                                 break;
  2246.  
  2247.                         case iDRAW:
  2248.                                                 moves = store + 1 + 63;
  2249.                                                 plies = moves * 2 - 1;
  2250.                                                 prefx = iWMATE;
  2251.                                                 break;
  2252.  
  2253.                         case iFORBID:
  2254.  
  2255.                                                 moves = store + 63;
  2256.                                                 plies = moves * 2;
  2257.                                                 prefx = iBMATE;
  2258.                                                 break;
  2259.                         default:
  2260.             plies = 0;
  2261.             prefx = 0;
  2262.             assert(0);
  2263.                                                 break;
  2264.  
  2265.                 }
  2266.                 ret = (dtm_t) (prefx | (plies << 3));
  2267.         } else {
  2268.                 switch (info) {
  2269.                         case iBMATE:
  2270.                                                 moves = store + 1;
  2271.                                                 plies = moves * 2 - 1;
  2272.                                                 prefx = info;
  2273.                                                 break;
  2274.  
  2275.                         case iWMATE:
  2276.                                                 moves = store;
  2277.                                                 plies = moves * 2;
  2278.                                                 prefx = info;
  2279.                                                 break;
  2280.  
  2281.                         case iDRAW:
  2282.  
  2283.                                                 if (store == 63) {
  2284.                                                 /*      exception: no position in the 5-man
  2285.                                                         TBs needs to store 63 for iBMATE
  2286.                                                         it is then used to indicate iWMATE
  2287.                                                         when just overflows */
  2288.                                                         store++;
  2289.  
  2290.                                                         moves = store + 63;
  2291.                                                         plies = moves * 2;
  2292.                                                         prefx = iWMATE;
  2293.  
  2294.                                                         break;
  2295.                                                 }
  2296.  
  2297.                                                 moves = store + 1 + 63;
  2298.                                                 plies = moves * 2 - 1;
  2299.                                                 prefx = iBMATE;
  2300.                                                 break;
  2301.  
  2302.                         case iFORBID:
  2303.  
  2304.                                                 moves = store + 63;
  2305.                                                 plies = moves * 2;
  2306.                                                 prefx = iWMATE;
  2307.                                                 break;
  2308.                         default:
  2309.             plies = 0;
  2310.             prefx = 0;
  2311.             assert(0);
  2312.                                                 break;
  2313.  
  2314.                 }
  2315.                 ret = (dtm_t) (prefx | (plies << 3));
  2316.         }
  2317.         return ret;
  2318. }
  2319.  
  2320.  
  2321. /*
  2322. static bool_t fwrite_entry_packed (FILE *dest, unsigned side, dtm_t x);
  2323. */
  2324.  
  2325.  
  2326. mySHARED bool_t
  2327. fread_entry_packed (FILE *finp, unsigned side, dtm_t *px)
  2328. {
  2329.         unsigned char p[SLOTSIZE];
  2330.         bool_t ok = (SLOTSIZE == fread (p, sizeof(unsigned char), SLOTSIZE, finp));
  2331.         if (ok) {
  2332.                 *px = dtm_unpack (side, p[0]);
  2333.         }
  2334.         return ok;
  2335. }
  2336.  
  2337.  
  2338. mySHARED bool_t
  2339. fpark_entry_packed  (FILE *finp, unsigned side, index_t max, index_t idx)
  2340. {
  2341.         bool_t ok;
  2342.         index_t i;
  2343.         long int fseek_i;
  2344.         index_t sz = (index_t) sizeof(unsigned char);
  2345.  
  2346.         assert (side == WH || side == BL);
  2347.         assert (finp != NULL);
  2348.         assert (idx >= 0);
  2349.         i = ((index_t)side * max + idx) * sz;
  2350.         fseek_i = (long int) i;
  2351.         assert (fseek_i >= 0);
  2352.         ok = (0 == fseek (finp, fseek_i, SEEK_SET));
  2353.         return ok;
  2354. }
  2355.  
  2356. /*----------------------------------------------------*\
  2357. |
  2358. |       shared by probe and build
  2359. |
  2360. \*/
  2361.  
  2362. static size_t
  2363. hash_func_1 (tbkey_t key, unsigned side, index_t offset)
  2364. {
  2365.         size_t h = offset | (key << 1) | side;
  2366.         h = ((h >> 16) ^ h) * 0x45d9f3b;
  2367.         h = ((h >> 16) ^ h) * 0x45d9f3b;
  2368.         h = ((h >> 16) ^ h);
  2369.         return h;
  2370. }
  2371.  
  2372. static size_t
  2373. hash_func_2 (tbkey_t key, unsigned side, index_t offset)
  2374. {
  2375.         size_t h = offset | (key << 1) | side;
  2376.         h = ((h >> 16) ^ h) * 0x3335b369;
  2377.         h = ((h >> 16) ^ h) * 0x3335b369;
  2378.         h = ((h >> 16) ^ h);
  2379.         return h * 2 + 1;
  2380. }
  2381.  
  2382. /*---------------------------------------------------------------------*\
  2383. |                       WDL CACHE Implementation  ZONE
  2384. \*---------------------------------------------------------------------*/
  2385.  
  2386. #define WDL_entries_per_unit 4
  2387. #define WDL_entry_mask     3
  2388. static size_t           WDL_units_per_block = 0;
  2389.  
  2390. static bool_t           WDL_CACHE_INITIALIZED = FALSE;
  2391.  
  2392. typedef unsigned char unit_t; /* block unit */
  2393.  
  2394. typedef struct wdl_block        wdl_block_t;
  2395.  
  2396. struct wdl_block {
  2397.         tbkey_t                 key;
  2398.         unsigned                side;
  2399.         index_t                 offset;
  2400.         unit_t                  *p_arr;
  2401.         wdl_block_t             *prev;
  2402.         wdl_block_t             *next;
  2403. };
  2404.  
  2405. struct WDL_CACHE {
  2406.         /* defined at init */
  2407.         bool_t                  cached;
  2408.         size_t                  max_blocks;
  2409.         size_t                  entries_per_block;
  2410.         unit_t           *      buffer;
  2411.  
  2412.         /* flushables */
  2413.         wdl_block_t     *       top;
  2414.         wdl_block_t *   bot;
  2415.         size_t                  n;
  2416.         wdl_block_t *   blocks; /* was entry */
  2417.  
  2418.         /* fast lookup in LRU list */
  2419.         wdl_block_t**   hash_table;
  2420.         size_t                  ht_size;
  2421.         size_t                  ht_used;
  2422.  
  2423.         /* counters */
  2424.         uint64_t                hard;
  2425.         uint64_t                soft;
  2426.         uint64_t                hardmisses;
  2427.         uint64_t                hits;
  2428.         uint64_t                softmisses;
  2429.         uint64_t                comparisons;
  2430. };
  2431.  
  2432. struct WDL_CACHE        wdl_cache = {FALSE,0,0,NULL,
  2433.                                                                  NULL,NULL,0,NULL,
  2434.                                                                  0,0,0,0,0,0};
  2435.  
  2436.  
  2437. /*---------------------------------------------------------------------*\
  2438. |                       DTM CACHE Implementation  ZONE
  2439. \*---------------------------------------------------------------------*/
  2440.  
  2441. struct dtm_block;
  2442.  
  2443. typedef struct dtm_block dtm_block_t;
  2444.  
  2445. struct dtm_block {
  2446.         tbkey_t                 key;
  2447.         unsigned                side;
  2448.         index_t                 offset;
  2449.         dtm_t                   *p_arr;
  2450.         dtm_block_t             *prev;
  2451.         dtm_block_t             *next;
  2452. };
  2453.  
  2454. struct cache_table {
  2455.         /* defined at init */
  2456.         bool_t                  cached;
  2457.         size_t                  max_blocks;
  2458.         size_t                  entries_per_block;
  2459.         dtm_t *                 buffer;
  2460.  
  2461.         /* flushables */
  2462.         dtm_block_t     *       top;
  2463.         dtm_block_t *   bot;
  2464.         size_t                  n;
  2465.         dtm_block_t *   entry;
  2466.  
  2467.         /* fast lookup in LRU list */
  2468.         dtm_block_t**   hash_table;
  2469.         size_t                  ht_size;
  2470.         size_t                  ht_used;
  2471.  
  2472.         /* counters */
  2473.         uint64_t                hard;
  2474.         uint64_t                soft;
  2475.         uint64_t                hardmisses;
  2476.         uint64_t                hits;
  2477.         uint64_t                softmisses;
  2478.         unsigned long   comparisons;
  2479. };
  2480.  
  2481. struct cache_table      dtm_cache = {FALSE,0,0,NULL,
  2482.                                                                 NULL,NULL,0,NULL,
  2483.                                                                 0,0,0,0,0,0};
  2484.  
  2485. struct general_counters {
  2486.         /* counters */
  2487.         uint64_t                hits;
  2488.         uint64_t                miss;
  2489. };
  2490.  
  2491. static struct general_counters Drive = {0,0};
  2492.  
  2493.  
  2494. static void             split_index (size_t entries_per_block, index_t i, index_t *o, index_t *r);
  2495. static dtm_block_t *point_block_to_replace (void);
  2496. static bool_t           preload_cache (tbkey_t key, unsigned side, index_t idx);
  2497. static void                     movetotop (dtm_block_t *t);
  2498.  
  2499. /*--cache prototypes--------------------------------------------------------*/
  2500.  
  2501. /*- WDL --------------------------------------------------------------------*/
  2502. #ifdef WDL_PROBE
  2503. static unsigned int             wdl_extract (unit_t *uarr, index_t x);
  2504. static wdl_block_t *    wdl_point_block_to_replace (void);
  2505. static void                             wdl_movetotop (wdl_block_t *t);
  2506.  
  2507. #if 0
  2508. static bool_t                   wdl_cache_init (size_t cache_mem);
  2509. static void                             wdl_cache_flush (void);
  2510. static bool_t                   get_WDL (tbkey_t key, unsigned side, index_t idx, unsigned int *info_out, bool_t probe_hard_flag);
  2511. #endif
  2512.  
  2513. static bool_t                   wdl_cache_is_on (void);
  2514. static void                             wdl_cache_reset_counters (void);
  2515. static void                             wdl_cache_done (void);
  2516.  
  2517. static wdl_block_t *    wdl_point_block_to_replace (void);
  2518. static bool_t                   get_WDL_from_cache (tbkey_t key, unsigned side, index_t idx, unsigned int *out);
  2519. static void                             wdl_movetotop (wdl_block_t *t);
  2520. static bool_t                   wdl_preload_cache (tbkey_t key, unsigned side, index_t idx);
  2521. #endif
  2522. /*--------------------------------------------------------------------------*/
  2523. /*- DTM --------------------------------------------------------------------*/
  2524. static bool_t                   dtm_cache_is_on (void);
  2525. static void                             dtm_cache_reset_counters (void);
  2526. static void                             dtm_cache_done (void);
  2527.  
  2528. static size_t                   dtm_cache_init (size_t cache_mem);
  2529. static void                             dtm_cache_flush (void);
  2530. /*--------------------------------------------------------------------------*/
  2531.  
  2532. static bool_t
  2533. dtm_cache_is_on (void)
  2534. {
  2535.         return dtm_cache.cached;
  2536. }
  2537.  
  2538. static void
  2539. dtm_cache_reset_counters (void)
  2540. {
  2541.         dtm_cache.hard = 0;
  2542.         dtm_cache.soft = 0;
  2543.         dtm_cache.hardmisses = 0;
  2544.         dtm_cache.hits = 0;
  2545.         dtm_cache.softmisses = 0;
  2546.         dtm_cache.comparisons = 0;
  2547.         return;
  2548. }
  2549.  
  2550.  
  2551. static size_t
  2552. dtm_cache_init (size_t cache_mem)
  2553. {
  2554.         unsigned int    i;
  2555.         dtm_block_t     *p;
  2556.         size_t                  entries_per_block;
  2557.         size_t                  max_blocks;
  2558.         size_t                  block_mem;
  2559.  
  2560.         if (DTM_CACHE_INITIALIZED)
  2561.                 dtm_cache_done();
  2562.  
  2563.         entries_per_block       = 16 * 1024;  /* fixed, needed for the compression schemes */
  2564.  
  2565.         block_mem                       = entries_per_block * sizeof(dtm_t);
  2566.  
  2567.         max_blocks                      = cache_mem / block_mem;
  2568.         if (!Uncompressed && 1 > max_blocks)
  2569.                 max_blocks = 1;
  2570.         cache_mem                       = max_blocks * block_mem;
  2571.  
  2572.  
  2573.         dtm_cache_reset_counters ();
  2574.  
  2575.         dtm_cache.entries_per_block     = entries_per_block;
  2576.         dtm_cache.max_blocks            = max_blocks;
  2577.         dtm_cache.cached                        = TRUE;
  2578.         dtm_cache.top                           = NULL;
  2579.         dtm_cache.bot                           = NULL;
  2580.         dtm_cache.n                             = 0;
  2581.  
  2582.         if (0 == cache_mem || NULL == (dtm_cache.buffer = (dtm_t *)  malloc (cache_mem))) {
  2583.                 dtm_cache.cached = FALSE;
  2584.                 dtm_cache.buffer = NULL;
  2585.                 dtm_cache.entry = NULL;
  2586.                 return 0;
  2587.         }
  2588.  
  2589.         if (0 == max_blocks|| NULL == (dtm_cache.entry  = (dtm_block_t *) malloc (max_blocks * sizeof(dtm_block_t)))) {
  2590.                 dtm_cache.cached = FALSE;
  2591.                 dtm_cache.entry = NULL;
  2592.                 free (dtm_cache.buffer);
  2593.                 dtm_cache.buffer = NULL;
  2594.                 return 0;
  2595.         }
  2596.  
  2597.         for (i = 0; i < max_blocks; i++) {
  2598.                 p = &dtm_cache.entry[i];
  2599.                 p->key          = -1;
  2600.                 p->side         = gtbNOSIDE;
  2601.                 p->offset       = gtbNOINDEX;
  2602.                 p->p_arr        = dtm_cache.buffer + i * entries_per_block;
  2603.                 p->prev         = NULL;
  2604.                 p->next         = NULL;
  2605.         }
  2606.  
  2607.         dtm_cache.ht_size = 1;
  2608.         while (dtm_cache.ht_size < max_blocks * 4)
  2609.                 dtm_cache.ht_size *= 2;
  2610.         dtm_cache.ht_used = 0;
  2611.         dtm_cache.hash_table = (dtm_block_t**) malloc (dtm_cache.ht_size * sizeof(dtm_block_t*));;
  2612.         if (dtm_cache.hash_table == NULL) {
  2613.                 dtm_cache.cached = FALSE;
  2614.                 free (dtm_cache.entry);
  2615.                 dtm_cache.entry = NULL;
  2616.                 free (dtm_cache.buffer);
  2617.                 dtm_cache.buffer = NULL;
  2618.                 return 0;
  2619.         }
  2620.  
  2621.         for (i = 0; i < dtm_cache.ht_size; i++) {
  2622.                 dtm_cache.hash_table[i] = NULL;
  2623.         }
  2624.  
  2625.         DTM_CACHE_INITIALIZED = TRUE;
  2626.  
  2627.         return cache_mem;
  2628. }
  2629.  
  2630.  
  2631. static void
  2632. dtm_cache_done (void)
  2633. {
  2634.         assert(DTM_CACHE_INITIALIZED);
  2635.  
  2636.         dtm_cache.cached = FALSE;
  2637.         dtm_cache.hard = 0;
  2638.         dtm_cache.soft = 0;
  2639.         dtm_cache.hardmisses = 0;
  2640.         dtm_cache.hits = 0;
  2641.         dtm_cache.softmisses = 0;
  2642.         dtm_cache.comparisons = 0;
  2643.         dtm_cache.max_blocks = 0;
  2644.         dtm_cache.entries_per_block = 0;
  2645.  
  2646.         dtm_cache.top = NULL;
  2647.         dtm_cache.bot = NULL;
  2648.         dtm_cache.n = 0;
  2649.  
  2650.         if (dtm_cache.buffer != NULL)
  2651.                 free (dtm_cache.buffer);
  2652.         dtm_cache.buffer = NULL;
  2653.  
  2654.         if (dtm_cache.entry != NULL)
  2655.                 free (dtm_cache.entry);
  2656.         dtm_cache.entry = NULL;
  2657.  
  2658.         if (dtm_cache.hash_table != NULL)
  2659.                 free (dtm_cache.hash_table);
  2660.         dtm_cache.hash_table = NULL;
  2661.  
  2662.         DTM_CACHE_INITIALIZED = FALSE;
  2663.  
  2664.         return;
  2665. }
  2666.  
  2667. static void
  2668. dtm_cache_flush (void)
  2669. {
  2670.         unsigned int    i;
  2671.         dtm_block_t     *p;
  2672.         size_t entries_per_block = dtm_cache.entries_per_block;
  2673.         size_t max_blocks = dtm_cache.max_blocks;
  2674.  
  2675.         dtm_cache.top                           = NULL;
  2676.         dtm_cache.bot                           = NULL;
  2677.         dtm_cache.n                             = 0;
  2678.  
  2679.         for (i = 0; i < max_blocks; i++) {
  2680.                 p = &dtm_cache.entry[i];
  2681.                 p->key          = -1;
  2682.                 p->side         = gtbNOSIDE;
  2683.                 p->offset       = gtbNOINDEX;
  2684.                 p->p_arr        = dtm_cache.buffer + i * entries_per_block;
  2685.                 p->prev         = NULL;
  2686.                 p->next         = NULL;
  2687.         }
  2688.         dtm_cache_reset_counters ();
  2689.         return;
  2690. }
  2691.  
  2692.  
  2693. /*---- end tbcache zone ----------------------------------------------------------------------*/
  2694.  
  2695. extern bool_t
  2696. tbcache_is_on (void)
  2697. {
  2698.         return dtm_cache_is_on() || wdl_cache_is_on();
  2699. }
  2700.  
  2701.  
  2702. /* STATISTICS OUTPUT */
  2703.  
  2704. extern void
  2705. tbstats_get (struct TB_STATS *x)
  2706. {
  2707.         long unsigned mask = 0xfffffffflu;
  2708.         uint64_t memory_hits, total_hits;
  2709.  
  2710.  
  2711.         /*
  2712.         |       WDL CACHE
  2713.         \*---------------------------------------------------*/
  2714.  
  2715.         x->wdl_easy_hits[0] = (long unsigned)(wdl_cache.hits & mask);
  2716.         x->wdl_easy_hits[1] = (long unsigned)(wdl_cache.hits >> 32);
  2717.  
  2718.         x->wdl_hard_prob[0] = (long unsigned)(wdl_cache.hard & mask);
  2719.         x->wdl_hard_prob[1] = (long unsigned)(wdl_cache.hard >> 32);
  2720.  
  2721.         x->wdl_soft_prob[0] = (long unsigned)(wdl_cache.soft & mask);
  2722.         x->wdl_soft_prob[1] = (long unsigned)(wdl_cache.soft >> 32);
  2723.  
  2724.         x->wdl_cachesize    = WDL_cache_size;
  2725.  
  2726.         /* occupancy */
  2727.         x->wdl_occupancy = wdl_cache.max_blocks==0? 0:(double)100.0*(double)wdl_cache.n/(double)wdl_cache.max_blocks;
  2728.  
  2729.         /*
  2730.         |       DTM CACHE
  2731.         \*---------------------------------------------------*/
  2732.  
  2733.         x->dtm_easy_hits[0] = (long unsigned)(dtm_cache.hits & mask);
  2734.         x->dtm_easy_hits[1] = (long unsigned)(dtm_cache.hits >> 32);
  2735.  
  2736.         x->dtm_hard_prob[0] = (long unsigned)(dtm_cache.hard & mask);
  2737.         x->dtm_hard_prob[1] = (long unsigned)(dtm_cache.hard >> 32);
  2738.  
  2739.         x->dtm_soft_prob[0] = (long unsigned)(dtm_cache.soft & mask);
  2740.         x->dtm_soft_prob[1] = (long unsigned)(dtm_cache.soft >> 32);
  2741.  
  2742.         x->dtm_cachesize    = DTM_cache_size;
  2743.  
  2744.         /* occupancy */
  2745.         x->dtm_occupancy = dtm_cache.max_blocks==0? 0:(double)100.0*(double)dtm_cache.n/(double)dtm_cache.max_blocks;
  2746.  
  2747.         /*
  2748.         |       GENERAL
  2749.         \*---------------------------------------------------*/
  2750.  
  2751.         /* memory */
  2752.         memory_hits = wdl_cache.hits + dtm_cache.hits;
  2753.         x->memory_hits[0] = (long unsigned)(memory_hits & mask);
  2754.         x->memory_hits[1] = (long unsigned)(memory_hits >> 32);
  2755.  
  2756.         /* hard drive */
  2757.         x->drive_hits[0] = (long unsigned)(Drive.hits & mask);
  2758.         x->drive_hits[1] = (long unsigned)(Drive.hits >> 32);
  2759.  
  2760.         x->drive_miss[0] = (long unsigned)(Drive.miss & mask);
  2761.         x->drive_miss[1] = (long unsigned)(Drive.miss >> 32);
  2762.  
  2763.         x->bytes_read[0] = (long unsigned)(Bytes_read & mask);
  2764.         x->bytes_read[1] = (long unsigned)(Bytes_read >> 32);
  2765.  
  2766.         x->files_opened = eg_was_open_count();
  2767.  
  2768.         /* total */
  2769.         total_hits = memory_hits + Drive.hits;
  2770.         x->total_hits[0] = (long unsigned)(total_hits & mask);
  2771.         x->total_hits[1] = (long unsigned)(total_hits >> 32);
  2772.  
  2773.         /* efficiency */
  2774.         { uint64_t denominator = memory_hits + Drive.hits + Drive.miss;
  2775.         x->memory_efficiency = 0==denominator? 0: 100.0 * (double)(memory_hits) / (double)(denominator);
  2776.         }
  2777. }
  2778.  
  2779.  
  2780. extern bool_t
  2781. tbcache_init (size_t cache_mem, int wdl_fraction)
  2782. {
  2783.         assert (wdl_fraction <= WDL_FRACTION_MAX && wdl_fraction >= 0);
  2784.  
  2785.         /* defensive against input */
  2786.         if (wdl_fraction > WDL_FRACTION_MAX) wdl_fraction = WDL_FRACTION_MAX;
  2787.         if (wdl_fraction <                0) wdl_fraction = 0;
  2788.         WDL_FRACTION = wdl_fraction;
  2789.  
  2790.         DTM_cache_size = (cache_mem/(size_t)WDL_FRACTION_MAX)*(size_t)(WDL_FRACTION_MAX-WDL_FRACTION);
  2791.         WDL_cache_size = (cache_mem/(size_t)WDL_FRACTION_MAX)*(size_t)                                  WDL_FRACTION ;
  2792.  
  2793.         #ifdef WDL_PROBE
  2794.         /* returns the actual memory allocated */
  2795.         DTM_cache_size = dtm_cache_init (DTM_cache_size);
  2796.         WDL_cache_size = wdl_cache_init (WDL_cache_size);
  2797.         #else
  2798.         /* returns the actual memory allocated */
  2799.         DTM_cache_size = dtm_cache_init (DTM_cache_size);
  2800.         #endif
  2801.         tbstats_reset ();
  2802.         return TRUE;
  2803. }
  2804.  
  2805. extern bool_t
  2806. tbcache_restart (size_t cache_mem, int wdl_fraction)
  2807. {
  2808.         return tbcache_init (cache_mem, wdl_fraction);
  2809. }
  2810.  
  2811. extern void
  2812. tbcache_done (void)
  2813. {
  2814.         dtm_cache_done();
  2815.         #ifdef WDL_PROBE
  2816.         wdl_cache_done();
  2817.         #endif
  2818.         tbstats_reset ();
  2819.         return;
  2820. }
  2821.  
  2822. extern void
  2823. tbcache_flush (void)
  2824. {
  2825.         dtm_cache_flush();
  2826.         #ifdef WDL_PROBE
  2827.         wdl_cache_flush();
  2828.         #endif
  2829.         tbstats_reset ();
  2830.         return;
  2831. }
  2832.  
  2833. extern void
  2834. tbstats_reset (void)
  2835. {
  2836.         dtm_cache_reset_counters ();
  2837.         #ifdef WDL_PROBE
  2838.         wdl_cache_reset_counters ();
  2839.         #endif
  2840.         eg_was_open_reset();
  2841.         Drive.hits = 0;
  2842.         Drive.miss = 0;
  2843.         return;
  2844. }
  2845.  
  2846. static void dtm_hash_insert (dtm_block_t * e);
  2847.  
  2848. static void
  2849. dtm_hash_rebuild (void)
  2850. {
  2851.         dtm_block_t     * p;
  2852.         size_t i;
  2853.  
  2854.         for (i = 0; i < dtm_cache.ht_size; i++)
  2855.                 dtm_cache.hash_table[i] = NULL;
  2856.         dtm_cache.ht_used = 0;
  2857.  
  2858.         for (p = dtm_cache.top; p != NULL; p = p->prev)
  2859.                 dtm_hash_insert (p);
  2860. }
  2861.  
  2862. static void
  2863. dtm_hash_insert (dtm_block_t * e)
  2864. {
  2865.         size_t h1, h2;
  2866.  
  2867.         if (dtm_cache.ht_used > dtm_cache.ht_size * 3 / 4)
  2868.                 dtm_hash_rebuild();
  2869.  
  2870.     h1 = hash_func_1 (e->key, e->side, e->offset) & (dtm_cache.ht_size - 1);
  2871.     h2 = hash_func_2 (e->key, e->side, e->offset);
  2872.     while (dtm_cache.hash_table[h1])
  2873.         h1 = (h1 + h2) & (dtm_cache.ht_size - 1);
  2874.     dtm_cache.hash_table[h1] = e;
  2875.     dtm_cache.ht_used++;
  2876. }
  2877.  
  2878. static dtm_block_t      *
  2879. dtm_cache_pointblock (tbkey_t key, unsigned side, index_t idx)
  2880. {
  2881.         index_t                 offset;
  2882.         index_t                 remainder;
  2883.         dtm_block_t     *       p;
  2884.         dtm_block_t     *       ret;
  2885.         size_t                  h1, h2;
  2886.  
  2887.         if (!dtm_cache_is_on())
  2888.                 return NULL;
  2889.  
  2890.         split_index (dtm_cache.entries_per_block, idx, &offset, &remainder);
  2891.  
  2892.         ret   = NULL;
  2893.  
  2894.         h1 = hash_func_1 (key, side, offset) & (dtm_cache.ht_size - 1);
  2895.         h2 = hash_func_2 (key, side, offset);
  2896.         while (1) {
  2897.                 p = dtm_cache.hash_table[h1];
  2898.                 if (!p)
  2899.                         break;
  2900.  
  2901.                 dtm_cache.comparisons++;
  2902.  
  2903.                 if (key == p->key && side == p->side && offset  == p->offset) {
  2904.                         ret = p;
  2905.                         break;
  2906.                 }
  2907.  
  2908.                 h1 = (h1 + h2) & (dtm_cache.ht_size - 1);
  2909.         }
  2910.  
  2911.         FOLLOW_LU("point_to_dtm_block ok?",(ret!=NULL))
  2912.  
  2913.         return ret;
  2914. }
  2915.  
  2916. /****************************************************************************\
  2917. |
  2918. |
  2919. |                       WRAPPERS for ENCODING/DECODING FUNCTIONS ZONE
  2920. |
  2921. |
  2922. \****************************************************************************/
  2923.  
  2924. #include "gtb-dec.h"
  2925.  
  2926. /*
  2927. |
  2928. |       PRE LOAD CACHE AND DEPENDENT FUNCTIONS
  2929. |
  2930. \*--------------------------------------------------------------------------*/
  2931.  
  2932. struct ZIPINFO {
  2933.         index_t         extraoffset;
  2934.         index_t         totalblocks;
  2935.         index_t *       blockindex;
  2936. };
  2937.  
  2938. struct ZIPINFO Zipinfo[MAX_EGKEYS];
  2939.  
  2940. static index_t  egtb_block_getnumber            (tbkey_t key, unsigned side, index_t idx);
  2941. static index_t  egtb_block_getsize                      (tbkey_t key, index_t idx);
  2942. static index_t  egtb_block_getsize_zipped       (tbkey_t key, index_t block );
  2943. static  bool_t  egtb_block_park                         (tbkey_t key, index_t block);
  2944. static  bool_t  egtb_block_read                         (tbkey_t key, index_t len, unsigned char *buffer);
  2945. static  bool_t  egtb_block_decode                       (tbkey_t key, index_t z, unsigned char *bz, index_t n, unsigned char *bp);
  2946. static  bool_t  egtb_block_unpack                       (unsigned side, index_t n, const unsigned char *bp, dtm_t *out);
  2947. static  bool_t  egtb_file_beready                       (tbkey_t key);
  2948. static  bool_t  egtb_loadindexes                        (tbkey_t key);
  2949. static index_t  egtb_block_uncompressed_to_index (tbkey_t key, index_t b);
  2950. static  bool_t  fread32                                         (FILE *f, unsigned long int *y);
  2951.  
  2952.  
  2953. static unsigned int
  2954. zipinfo_init (void)
  2955. {
  2956.         int i, start, end;
  2957.         unsigned ret;
  2958.         bool_t ok, complet[8] = {0,0,0,0,0,0,0,0};
  2959.         bool_t pa, partial[8] = {0,0,0,0,0,0,0,0};
  2960.         unsigned int z;
  2961.         int x, j;
  2962.  
  2963.         /* reset all values */
  2964.         for (i = 0; i < MAX_EGKEYS; i++) {
  2965.                 Zipinfo[i].blockindex = NULL;
  2966.                 Zipinfo[i].extraoffset = 0;
  2967.                 Zipinfo[i].totalblocks = 0;
  2968.         }
  2969.  
  2970.         /* load all values */
  2971.         start = 0;
  2972.         end   = 5;
  2973.         x         = 3;
  2974.         for (i = start, ok = TRUE, pa = FALSE; i < end; i++) {
  2975.                 ok = NULL != fd_openit(i);
  2976.                 pa = pa || ok;
  2977.                 ok = ok && egtb_loadindexes (i);
  2978.         }
  2979.         complet[x] = ok;
  2980.         partial[x] = pa;
  2981.  
  2982.         start = 5;
  2983.         end   = 35;
  2984.         x         = 4;
  2985.         for (i = start, ok = TRUE, pa = FALSE; i < end; i++) {
  2986.                 ok = NULL != fd_openit(i);
  2987.                 pa = pa || ok;
  2988.                 ok = ok && egtb_loadindexes (i);
  2989.         }
  2990.         complet[x] = ok;
  2991.         partial[x] = pa;
  2992.  
  2993.         start = 35;
  2994.         end   = MAX_EGKEYS;
  2995.         x         = 5;
  2996.         for (i = start, ok = TRUE, pa = FALSE; i < end; i++) {
  2997.                 ok = NULL != fd_openit(i);
  2998.                 pa = pa || ok;
  2999.                 ok = ok && egtb_loadindexes (i);
  3000.         }
  3001.         complet[x] = ok;
  3002.         partial[x] = pa;
  3003.  
  3004.  
  3005.         for (j = 0, z = 0, x = 3; x < 8; x++) {
  3006.                 if (partial[x]) z |= 1u << j;
  3007.                 j++;
  3008.                 if (complet[x]) z |= 1u << j;
  3009.                 j++;
  3010.         }
  3011.  
  3012.         ret = z;
  3013.  
  3014.         return ret;
  3015. }
  3016.  
  3017. static void
  3018. zipinfo_done (void)
  3019. {
  3020.         int i;
  3021.         bool_t ok;
  3022.         for (i = 0, ok = TRUE; ok && i < MAX_EGKEYS; i++) {
  3023.                 if (Zipinfo[i].blockindex != NULL) {
  3024.                         free(Zipinfo[i].blockindex);
  3025.                         Zipinfo[i].blockindex = NULL;
  3026.                         Zipinfo[i].extraoffset = 0;
  3027.                         Zipinfo[i].totalblocks = 0;
  3028.                 }
  3029.         }
  3030.         return;
  3031. }
  3032.  
  3033. static size_t
  3034. zipinfo_memory_allocated (void)
  3035. {
  3036.         int i;
  3037.         index_t accum_blocks = 0;
  3038.         for (i = 0; i < MAX_EGKEYS; i++) {
  3039.                 if (Zipinfo[i].blockindex != NULL) {
  3040.                         accum_blocks += Zipinfo[i].totalblocks;
  3041.                 }
  3042.         }
  3043.         return (size_t)accum_blocks * sizeof(index_t);
  3044. }
  3045.  
  3046. extern size_t
  3047. tb_indexmemory (void)
  3048. {
  3049.         return zipinfo_memory_allocated ();
  3050. }
  3051.  
  3052. static bool_t
  3053. fread32 (FILE *f, unsigned long int *y)
  3054. {
  3055.         enum SIZE {SZ = 4};
  3056.         int i;
  3057.         unsigned long int x;
  3058.         unsigned char p[SZ];
  3059.         bool_t ok;
  3060.  
  3061.         ok = (SZ == fread (p, sizeof(unsigned char), SZ, f));
  3062.  
  3063.         if (ok) {
  3064.                 for (x = 0, i = 0; i < SZ; i++) {
  3065.                         x |= (unsigned long int)p[i] << (i*8);
  3066.                 }
  3067.                 *y = x;
  3068.         }
  3069.         return ok;
  3070. }
  3071.  
  3072. static bool_t
  3073. egtb_loadindexes (tbkey_t key)
  3074. {
  3075.  
  3076.         unsigned long int blocksize = 1;
  3077.         unsigned long int tailblocksize1 = 0;
  3078.         unsigned long int tailblocksize2 = 0;
  3079.     unsigned long int offset=0;
  3080.         unsigned long int dummy;
  3081.         unsigned long int i;
  3082.         unsigned long int blocks;
  3083.         unsigned long int n_idx;
  3084.         unsigned long int idx = 0;
  3085.         index_t *p;
  3086.  
  3087.         bool_t ok;
  3088.  
  3089.         FILE *f;
  3090.  
  3091.         if (Uncompressed) {
  3092.                 assert (decoding_scheme() == 0 && GTB_scheme == 0);
  3093.                 return TRUE; /* no need to load indexes */
  3094.         }
  3095.         if (Zipinfo[key].blockindex != NULL)
  3096.                 return TRUE; /* indexes must have been loaded already */
  3097.  
  3098.         if (NULL == (f = egkey[key].fd))
  3099.                 return FALSE; /* file was no open */
  3100.  
  3101.         /* Get Reserved bytes, blocksize, offset */
  3102.         ok = (0 == fseek (f, 0, SEEK_SET)) &&
  3103.         fread32 (f, &dummy) &&
  3104.         fread32 (f, &dummy) &&
  3105.         fread32 (f, &blocksize) &&
  3106.         fread32 (f, &dummy) &&
  3107.         fread32 (f, &tailblocksize1) &&
  3108.         fread32 (f, &dummy) &&
  3109.         fread32 (f, &tailblocksize2) &&
  3110.         fread32 (f, &dummy) &&
  3111.         fread32 (f, &offset) &&
  3112.         fread32 (f, &dummy);
  3113.  
  3114.         blocks = (offset - 40)/4 -1;
  3115.         n_idx = blocks + 1;
  3116.  
  3117.         p = NULL;
  3118.  
  3119.         ok = ok && NULL != (p = (index_t *)malloc (n_idx * sizeof(index_t)));
  3120.  
  3121.         /* Input of Indexes */
  3122.         for (i = 0; ok && i < n_idx; i++) {
  3123.                 ok = fread32 (f, &idx);
  3124.                 p[i] = (index_t)idx; /* reads a 32 bit int, and converts it to index_t */ assert (sizeof(index_t) >= 4);
  3125.         }
  3126.  
  3127.         if (ok) {
  3128.                 Zipinfo[key].extraoffset = 0;
  3129.                 assert (n_idx <= MAXINDEX_T);
  3130.                 Zipinfo[key].totalblocks = (index_t) n_idx;
  3131.                 Zipinfo[key].blockindex  = p;
  3132.         }
  3133.  
  3134.         if (!ok && p != NULL) {
  3135.                 free(p);
  3136.         }
  3137.  
  3138.         return ok;
  3139. }
  3140.  
  3141. static index_t
  3142. egtb_block_uncompressed_to_index (tbkey_t key, index_t b)
  3143. {
  3144.         index_t max;
  3145.         index_t blocks_per_side;
  3146.         index_t idx;
  3147.  
  3148.         max = egkey[key].maxindex;
  3149.         blocks_per_side = 1 + (max-1) / (index_t)dtm_cache.entries_per_block;
  3150.  
  3151.         if (b < blocks_per_side) {
  3152.                 idx = 0;
  3153.         } else {
  3154.                 b -= blocks_per_side;
  3155.                 idx = max;
  3156.         }
  3157.         idx += b * (index_t)dtm_cache.entries_per_block;
  3158.         return idx;
  3159. }
  3160.  
  3161.  
  3162. static index_t
  3163. egtb_block_getnumber (tbkey_t key, unsigned side, index_t idx)
  3164. {
  3165.         index_t blocks_per_side;
  3166.         index_t block_in_side;
  3167.         index_t max = egkey[key].maxindex;
  3168.  
  3169.         blocks_per_side = 1 + (max-1) / (index_t)dtm_cache.entries_per_block;
  3170.         block_in_side   = idx         / (index_t)dtm_cache.entries_per_block;
  3171.  
  3172.         return (index_t)side * blocks_per_side + block_in_side; /* block */
  3173. }
  3174.  
  3175.  
  3176. static index_t
  3177. egtb_block_getsize (tbkey_t key, index_t idx)
  3178. {
  3179.         index_t blocksz = (index_t) dtm_cache.entries_per_block;
  3180.         index_t maxindex  = egkey[key].maxindex;
  3181.         index_t block, offset, x;
  3182.  
  3183.         assert (dtm_cache.entries_per_block <= MAXINDEX_T);
  3184.         assert (0 <= idx && idx < maxindex);
  3185.         assert (key < MAX_EGKEYS);
  3186.  
  3187.         block = idx / blocksz;
  3188.         offset = block * blocksz;
  3189.  
  3190.         /*
  3191.         |       adjust block size in case that this is the last block
  3192.         |       and is shorter than "blocksz"
  3193.         */
  3194.         if ( (offset + blocksz) > maxindex)
  3195.                 x = maxindex - offset; /* last block size */
  3196.         else
  3197.                 x = blocksz; /* size of a normal block */
  3198.  
  3199.         return x;
  3200. }
  3201.  
  3202. static index_t
  3203. egtb_block_getsize_zipped (tbkey_t key, index_t block )
  3204. {
  3205.         index_t i, j;
  3206.         assert (Zipinfo[key].blockindex != NULL);
  3207.         i = Zipinfo[key].blockindex[block];
  3208.         j = Zipinfo[key].blockindex[block+1];
  3209.         return j - i;
  3210. }
  3211.  
  3212.  
  3213. static bool_t
  3214. egtb_file_beready (tbkey_t key)
  3215. {
  3216.         bool_t success;
  3217.         assert (key < MAX_EGKEYS);
  3218.         success =       (NULL != egkey[key].fd) ||
  3219.                                 (NULL != fd_openit(key) && egtb_loadindexes (key));
  3220.         return success;
  3221. }
  3222.  
  3223.  
  3224. static bool_t
  3225. egtb_block_park  (tbkey_t key, index_t block)
  3226. {
  3227.         index_t i;
  3228.         long fseek_i;
  3229.         assert (egkey[key].fd != NULL);
  3230.  
  3231.         if (Uncompressed) {
  3232.                 assert (decoding_scheme() == 0 && GTB_scheme == 0);
  3233.                 i = egtb_block_uncompressed_to_index (key, block);
  3234.         } else {
  3235.                 assert (Zipinfo[key].blockindex != NULL);
  3236.                 i  = Zipinfo[key].blockindex[block];
  3237.                 i += Zipinfo[key].extraoffset;
  3238.         }
  3239.  
  3240.         fseek_i = (long) i;
  3241.         assert (fseek_i >= 0);
  3242.         return 0 == fseek (egkey[key].fd, fseek_i, SEEK_SET);
  3243. }
  3244.  
  3245.  
  3246. static bool_t
  3247. egtb_block_read (tbkey_t key, index_t len, unsigned char *buffer)
  3248. {
  3249.         assert (egkey[key].fd != NULL);
  3250.         assert (sizeof(size_t) >= sizeof(len));
  3251.         return ((size_t)len == fread (buffer, sizeof (unsigned char), (size_t)len, egkey[key].fd));
  3252. }
  3253.  
  3254. tbkey_t TB_PROBE_indexing_dummy;
  3255.  
  3256. static bool_t
  3257. egtb_block_decode (tbkey_t key, index_t z, unsigned char *bz, index_t n, unsigned char *bp)
  3258. /* bz:buffer zipped to bp:buffer packed */
  3259. {
  3260.         size_t zz = (size_t) z;
  3261.         size_t nn = (size_t) n;
  3262.         TB_PROBE_indexing_dummy = key; /* to silence compiler */
  3263.         assert (sizeof(size_t) >= sizeof(n));
  3264.         assert (sizeof(size_t) >= sizeof(z));
  3265.         return decode (zz-1, bz+1, nn, bp);
  3266. }
  3267.  
  3268. static bool_t
  3269. egtb_block_unpack (unsigned side, index_t n, const unsigned char *bp, dtm_t *out)
  3270. /* bp:buffer packed to out:distance to mate buffer */
  3271. {
  3272.     index_t i;
  3273.     if (WH == side) {
  3274.         for (i = 0; i < n; i++) {
  3275.             *out++ = dtm_unpack (WH, bp[i]);
  3276.         }
  3277.     } else {
  3278.         for (i = 0; i < n; i++) {
  3279.             *out++ = dtm_unpack (BL, bp[i]);
  3280.         }
  3281.     }
  3282.         return TRUE;
  3283. }
  3284.  
  3285. static bool_t
  3286. preload_cache (tbkey_t key, unsigned side, index_t idx)
  3287. /* output to the least used block of the cache */
  3288. {
  3289.         dtm_block_t     *pblock;
  3290.         dtm_t                   *p;
  3291.         bool_t                  ok;
  3292.     unsigned char    Buffer_zipped [EGTB_MAXBLOCKSIZE];
  3293.     unsigned char    Buffer_packed [EGTB_MAXBLOCKSIZE];
  3294.  
  3295.         FOLLOW_label("preload_cache starts")
  3296.  
  3297.         if (idx >= egkey[key].maxindex) {
  3298.                 FOLLOW_LULU("Wrong index", __LINE__, idx)
  3299.                 return FALSE;
  3300.         }
  3301.  
  3302.         /* find aged blocked in cache */
  3303.         pblock = point_block_to_replace();
  3304.  
  3305.         if (NULL == pblock)
  3306.                 return FALSE;
  3307.  
  3308.         p = pblock->p_arr;
  3309.  
  3310.         if (Uncompressed) {
  3311.  
  3312.                 index_t block = egtb_block_getnumber (key, side, idx);
  3313.                 index_t n     = egtb_block_getsize   (key, idx);
  3314.  
  3315.                 ok =       egtb_file_beready (key)
  3316.                                 && egtb_block_park   (key, block)
  3317.                                 && egtb_block_read   (key, n, Buffer_packed)
  3318.                                 && egtb_block_unpack (side, n, Buffer_packed, p);
  3319.  
  3320.                 FOLLOW_LULU("preload_cache", __LINE__, ok)
  3321.  
  3322.                 assert (decoding_scheme() == 0 && GTB_scheme == 0);
  3323.  
  3324.                 if (ok) { Bytes_read = Bytes_read + (uint64_t) n; }
  3325.  
  3326.         } else {
  3327.  
  3328.         index_t block = 0;
  3329.                 index_t n = 0;
  3330.                 index_t z = 0;
  3331.  
  3332.                 ok =       egtb_file_beready (key);
  3333.  
  3334.                 FOLLOW_LULU("preload_cache", __LINE__, ok)
  3335.  
  3336.                 if (ok) {
  3337.                         block = egtb_block_getnumber (key, side, idx);
  3338.                         n     = egtb_block_getsize   (key, idx);
  3339.                         z     = egtb_block_getsize_zipped (key, block);
  3340.                 }
  3341.  
  3342.                 ok =       ok
  3343.                                 && egtb_block_park   (key, block);
  3344.                 FOLLOW_LULU("preload_cache", __LINE__, ok)
  3345.  
  3346.                 ok =       ok
  3347.                                 && egtb_block_read   (key, z, Buffer_zipped);
  3348.                 FOLLOW_LULU("preload_cache", __LINE__, ok)
  3349.  
  3350.         mythread_mutex_unlock (&Egtb_lock);
  3351.  
  3352.                 ok =       ok
  3353.                                 && egtb_block_decode (key, z, Buffer_zipped, n, Buffer_packed);
  3354.                 FOLLOW_LULU("preload_cache", __LINE__, ok)
  3355.  
  3356.         mythread_mutex_lock (&Egtb_lock);
  3357.             pblock = point_block_to_replace();
  3358.             p = pblock->p_arr;
  3359.  
  3360.                 ok =       ok
  3361.                                 && egtb_block_unpack (side, n, Buffer_packed, p);
  3362.                 FOLLOW_LULU("preload_cache", __LINE__, ok)
  3363.  
  3364.                 if (ok) { Bytes_read = Bytes_read + (uint64_t) z; }
  3365.         }
  3366.  
  3367.         if (ok) {
  3368.  
  3369.                 index_t                 offset;
  3370.                 index_t                 remainder;
  3371.                 split_index (dtm_cache.entries_per_block, idx, &offset, &remainder);
  3372.  
  3373.                 pblock->key    = key;
  3374.                 pblock->side   = side;
  3375.                 pblock->offset = offset;
  3376.                 dtm_hash_insert (pblock);
  3377.         } else {
  3378.                 /* make it unusable */
  3379.                 pblock->key    = -1;
  3380.                 pblock->side   = gtbNOSIDE;
  3381.                 pblock->offset = gtbNOINDEX;
  3382.         }
  3383.  
  3384.         FOLLOW_LU("preload_cache?", ok)
  3385.  
  3386.         return ok;
  3387. }
  3388.  
  3389. /****************************************************************************\
  3390. |
  3391. |
  3392. |                                               MEMORY ALLOCATION ZONE
  3393. |
  3394. |
  3395. \****************************************************************************/
  3396.  
  3397.  
  3398. mySHARED void
  3399. egtb_freemem (int i)
  3400. {
  3401.         if (egkey[i].status == STATUS_MALLOC) {
  3402.                 assert (egkey[i].egt_w != NULL);
  3403.                 assert (egkey[i].egt_b != NULL);
  3404.                 free (egkey[i].egt_w);
  3405.                 free (egkey[i].egt_b);
  3406.                 egkey[i].egt_w = NULL;
  3407.                 egkey[i].egt_b = NULL;
  3408.         }
  3409.         egkey[i].status = STATUS_ABSENT;
  3410. }
  3411.  
  3412. /***************************************************************************/
  3413.  
  3414. mySHARED bool_t
  3415. get_dtm (tbkey_t key, unsigned side, index_t idx, dtm_t *out, bool_t probe_hard_flag)
  3416. {
  3417.         bool_t found;
  3418.  
  3419.         if (probe_hard_flag) {
  3420.                 dtm_cache.hard++;
  3421.         } else {
  3422.                 dtm_cache.soft++;
  3423.         }
  3424.  
  3425.         if (get_dtm_from_cache (key, side, idx, out)) {
  3426.                 dtm_cache.hits++;
  3427.                 found = TRUE;
  3428.         } else if (probe_hard_flag) {
  3429.                 dtm_cache.hardmisses++;
  3430.                 found = preload_cache (key, side, idx) &&
  3431.                                 get_dtm_from_cache (key, side, idx, out);
  3432.  
  3433.                 if (found) {
  3434.                         Drive.hits++;
  3435.                 } else {
  3436.                         Drive.miss++;
  3437.                 }
  3438.  
  3439.  
  3440.         } else {
  3441.                 dtm_cache.softmisses++;
  3442.                 found = FALSE;
  3443.         }
  3444.         return found;
  3445. }
  3446.  
  3447.  
  3448. static bool_t
  3449. get_dtm_from_cache (tbkey_t key, unsigned side, index_t idx, dtm_t *out)
  3450. {
  3451.         index_t         offset;
  3452.         index_t         remainder;
  3453.         bool_t          found;
  3454.         dtm_block_t     *p;
  3455.  
  3456.         if (!dtm_cache_is_on())
  3457.                 return FALSE;
  3458.  
  3459.         split_index (dtm_cache.entries_per_block, idx, &offset, &remainder);
  3460.  
  3461.         found = NULL != (p = dtm_cache_pointblock (key, side, idx));
  3462.  
  3463.         if (found) {
  3464.                 *out = p->p_arr[remainder];
  3465.                 movetotop(p);
  3466.         }
  3467.  
  3468.         FOLLOW_LU("get_dtm_from_cache ok?",found)
  3469.  
  3470.         return found;
  3471. }
  3472.  
  3473.  
  3474. static void
  3475. split_index (size_t entries_per_block, index_t i, index_t *o, index_t *r)
  3476. {
  3477.         index_t n;
  3478.         n  = i / (index_t) entries_per_block;
  3479.         *o = n * (index_t) entries_per_block;
  3480.         *r = i - *o;
  3481.         return;
  3482. }
  3483.  
  3484.  
  3485. static dtm_block_t *
  3486. point_block_to_replace (void)
  3487. {
  3488.         dtm_block_t *p, *t, *s;
  3489.  
  3490.         assert (0 == dtm_cache.n || dtm_cache.top != NULL);
  3491.         assert (0 == dtm_cache.n || dtm_cache.bot != NULL);
  3492.         assert (0 == dtm_cache.n || dtm_cache.bot->prev == NULL);
  3493.         assert (0 == dtm_cache.n || dtm_cache.top->next == NULL);
  3494.  
  3495.         /* no cache is being used */
  3496.         if (dtm_cache.max_blocks == 0)
  3497.                 return NULL;
  3498.  
  3499.         if (dtm_cache.n > 0 && -1 == dtm_cache.top->key) {
  3500.  
  3501.                 /* top entry is unusable, should be the one to replace*/
  3502.                 p = dtm_cache.top;
  3503.  
  3504.         } else
  3505.         if (dtm_cache.n == 0) {
  3506.  
  3507.                 assert (NULL != dtm_cache.entry);
  3508.                 p = &dtm_cache.entry[dtm_cache.n++];
  3509.                 dtm_cache.top = p;
  3510.                 dtm_cache.bot = p;
  3511.  
  3512.                 assert (NULL != p);
  3513.                 p->prev = NULL;
  3514.                 p->next = NULL;
  3515.  
  3516.         } else
  3517.         if (dtm_cache.n < dtm_cache.max_blocks) { /* add */
  3518.  
  3519.                 assert (NULL != dtm_cache.entry);
  3520.                 s = dtm_cache.top;
  3521.                 p = &dtm_cache.entry[dtm_cache.n++];
  3522.                 dtm_cache.top = p;
  3523.  
  3524.                 assert (NULL != p && NULL != s);
  3525.                 s->next = p;
  3526.                 p->prev = s;
  3527.                 p->next = NULL;
  3528.  
  3529.         } else if (1 < dtm_cache.max_blocks) { /* replace*/
  3530.  
  3531.                 assert (NULL != dtm_cache.bot && NULL != dtm_cache.top);
  3532.                 t = dtm_cache.bot;
  3533.                 s = dtm_cache.top;
  3534.  
  3535.                 dtm_cache.bot = t->next;
  3536.                 dtm_cache.top = t;
  3537.  
  3538.                 s->next = t;
  3539.                 t->prev = s;
  3540.  
  3541.                 assert (dtm_cache.top);
  3542.                 dtm_cache.top->next = NULL;
  3543.  
  3544.                 assert (dtm_cache.bot);
  3545.                 dtm_cache.bot->prev = NULL;
  3546.  
  3547.                 p = t;
  3548.  
  3549.         } else {
  3550.  
  3551.                 assert (1 == dtm_cache.max_blocks);
  3552.                 p =     dtm_cache.top;
  3553.                 assert (p == dtm_cache.bot && p == dtm_cache.entry);
  3554.         }
  3555.  
  3556.         /* make the information content unusable, it will be replaced */
  3557.         p->key    = -1;
  3558.         p->side   = gtbNOSIDE;
  3559.         p->offset = gtbNOINDEX;
  3560.  
  3561.         return p;
  3562. }
  3563.  
  3564. static void
  3565. movetotop (dtm_block_t *t)
  3566. {
  3567.         dtm_block_t *s, *nx, *pv;
  3568.  
  3569.         assert (t != NULL);
  3570.  
  3571.         if (t->next == NULL) /* at the top already */
  3572.                 return;
  3573.  
  3574.         /* detach */
  3575.         pv = t->prev;
  3576.         nx = t->next;
  3577.  
  3578.         if (pv == NULL)  /* at the bottom */
  3579.                 dtm_cache.bot = nx;
  3580.         else
  3581.                 pv->next = nx;
  3582.  
  3583.         if (nx == NULL) /* at the top */
  3584.                 dtm_cache.top = pv;
  3585.         else
  3586.                 nx->prev = pv;
  3587.  
  3588.         /* relocate */
  3589.         s = dtm_cache.top;
  3590.         assert (s != NULL);
  3591.         if (s == NULL)
  3592.                 dtm_cache.bot = t;
  3593.         else
  3594.                 s->next = t;
  3595.  
  3596.         t->next = NULL;
  3597.         t->prev = s;
  3598.         dtm_cache.top = t;
  3599.  
  3600.         return;
  3601. }
  3602.  
  3603. /****************************************************************************\
  3604.  *
  3605.  *
  3606.  *                                                              INDEXING ZONE
  3607.  *
  3608.  *
  3609.  ****************************************************************************/
  3610.  
  3611. static void
  3612. init_indexing (int verbosity)
  3613. {
  3614.         index_t a,b,c,d,e,f;
  3615.  
  3616.         init_flipt ();
  3617.  
  3618.         a = init_kkidx     () ;
  3619.         b = init_ppidx     () ;
  3620.         c = init_aaidx     () ;
  3621.         d = init_aaa       () ;
  3622.         e = init_pp48_idx  () ;
  3623.         f = init_ppp48_idx () ;
  3624.  
  3625.         if (verbosity) {
  3626.                 printf ("\nGTB supporting tables, Initialization\n");
  3627.                 printf ("  Max    kk idx: %8d\n", (int)a );
  3628.                 printf ("  Max    pp idx: %8d\n", (int)b );
  3629.                 printf ("  Max    aa idx: %8d\n", (int)c );
  3630.                 printf ("  Max   aaa idx: %8d\n", (int)d );
  3631.                 printf ("  Max  pp48 idx: %8d\n", (int)e );
  3632.                 printf ("  Max ppp48 idx: %8d\n", (int)f );
  3633.         }
  3634.  
  3635.         if (!reach_was_initialized())
  3636.                 reach_init();
  3637.  
  3638.         /* testing used only in development stage */
  3639.  
  3640. #ifdef _MSC_VER
  3641. #pragma warning(disable:4127)
  3642. #endif
  3643.  
  3644.         if (0) {
  3645.                 list_index ();
  3646.                 printf ("\nTEST indexing functions\n");
  3647.  
  3648.                 test_kaakb ();
  3649.                 test_kaabk ();
  3650.                 test_kaaak ();
  3651.                 test_kabbk ();
  3652.  
  3653.                 test_kapkb ();
  3654.                 test_kabkp ();
  3655.  
  3656.                 test_kppka ();
  3657.  
  3658.                 test_kapkp ();
  3659.                 test_kabpk();
  3660.                 test_kaapk ();
  3661.  
  3662.                 test_kappk ();
  3663.                 test_kaakp ();
  3664.                 test_kppk ();
  3665.                 test_kppkp ();
  3666.                 test_kpppk ();
  3667.         }
  3668.  
  3669. #ifdef _MSC_VER
  3670. #pragma warning(default:4127)
  3671. #endif
  3672.  
  3673.         return;
  3674. }
  3675.  
  3676.  
  3677. static index_t
  3678. init_kkidx (void)
  3679. /* modifies kkidx[][], wksq[], bksq[] */
  3680. {
  3681.         index_t idx;
  3682.         SQUARE x, y, i, j;
  3683.  
  3684.         /* default is noindex */
  3685.         for (x = 0; x < 64; x++) {
  3686.                 for (y = 0; y < 64; y++) {
  3687.                         IDX_set_empty(kkidx [x][y]);
  3688.                 }
  3689.         }
  3690.  
  3691.         idx = 0;
  3692.         for (x = 0; x < 64; x++) {
  3693.                 for (y = 0; y < 64; y++) {
  3694.  
  3695.                         /* is x,y illegal? continue */
  3696.                         if (possible_attack (x, y, wK) || x == y)
  3697.                                 continue;
  3698.  
  3699.                         /* normalize */
  3700.                         /*i <-- x; j <-- y */
  3701.                         norm_kkindex (x, y, &i, &j);
  3702.  
  3703.                         if (IDX_is_empty(kkidx [i][j])) { /* still empty */
  3704.                                 kkidx [i][j] = idx;
  3705.                                 kkidx [x][y] = idx;
  3706.                                 bksq [idx] = i;
  3707.                                 wksq [idx] = j;
  3708.                                 idx++;
  3709.                         }
  3710.                 }
  3711.         }
  3712.  
  3713.         assert (idx == MAX_KKINDEX);
  3714.  
  3715.         return idx;
  3716. }
  3717.  
  3718.  
  3719. static index_t
  3720. init_aaidx (void)
  3721. /* modifies aabase[], aaidx[][] */
  3722. {
  3723.         index_t idx;
  3724.         SQUARE x, y;
  3725.  
  3726.         /* default is noindex */
  3727.         for (x = 0; x < 64; x++) {
  3728.                 for (y = 0; y < 64; y++) {
  3729.                         IDX_set_empty(aaidx [x][y]);
  3730.                 }
  3731.         }
  3732.  
  3733.         for (idx = 0; idx < MAX_AAINDEX; idx++)
  3734.                 aabase [idx] = 0;
  3735.  
  3736.         idx = 0;
  3737.         for (x = 0; x < 64; x++) {
  3738.                 for (y = x + 1; y < 64; y++) {
  3739.  
  3740.                         assert (idx == (int)((y - x) + x * (127-x)/2 - 1) );
  3741.  
  3742.                         if (IDX_is_empty(aaidx [x][y])) { /* still empty */
  3743.                                 aaidx [x] [y] = idx;
  3744.                                 aaidx [y] [x] = idx;
  3745.                                 aabase [idx] = (unsigned char) x;
  3746.                                 idx++;
  3747.                         } else {
  3748.                                 assert (aaidx [x] [y] == idx);
  3749.                                 assert (aabase [idx] == x);
  3750.                         }
  3751.  
  3752.  
  3753.                 }
  3754.         }
  3755.  
  3756.         assert (idx == MAX_AAINDEX);
  3757.  
  3758.         return idx;
  3759. }
  3760.  
  3761.  
  3762. static index_t
  3763. init_ppidx (void)
  3764. /* modifies ppidx[][], pp_hi24[], pp_lo48[] */
  3765. {
  3766.         index_t i, j;
  3767.         index_t idx = 0;
  3768.         SQUARE a, b;
  3769.  
  3770.         /* default is noindex */
  3771.         for (i = 0; i < 24; i++) {
  3772.                 for (j = 0; j < 48; j++) {
  3773.                         IDX_set_empty(ppidx [i][j]);
  3774.                 }
  3775.         }
  3776.  
  3777.         for (idx = 0; idx < MAX_PPINDEX; idx++) {
  3778.                 IDX_set_empty(pp_hi24 [idx]);
  3779.                 IDX_set_empty(pp_lo48 [idx]);
  3780.         }
  3781.  
  3782.         idx = 0;
  3783.         for (a = H7; a >= A2; a--) {
  3784.  
  3785.                 if ((a & 07) < 4) /* square in the queen side */
  3786.                         continue;
  3787.  
  3788.                 for (b = a - 1; b >= A2; b--) {
  3789.  
  3790.                         SQUARE anchor, loosen;
  3791.  
  3792.                         pp_putanchorfirst (a, b, &anchor, &loosen);
  3793.  
  3794.                         if ((anchor & 07) > 3) { /* square in the king side */
  3795.                                 anchor = flipWE(anchor);
  3796.                                 loosen = flipWE(loosen);
  3797.                         }
  3798.  
  3799.                         i = wsq_to_pidx24 (anchor);
  3800.                         j = wsq_to_pidx48 (loosen);
  3801.  
  3802.                         if (IDX_is_empty(ppidx [i] [j])) {
  3803.  
  3804.                 ppidx [i] [j] = idx;
  3805.                 assert (idx < MAX_PPINDEX);
  3806.                 pp_hi24 [idx] = i;
  3807.                 assert (i < 24);
  3808.                 pp_lo48 [idx] = j;
  3809.                 assert (j < 48);
  3810.                                 idx++;
  3811.                         }
  3812.  
  3813.                 }
  3814.         }
  3815.         assert (idx == MAX_PPINDEX);
  3816.         return idx;
  3817. }
  3818.  
  3819. static void
  3820. init_flipt (void)
  3821. {
  3822.         unsigned int i, j;
  3823.         for (i = 0; i < 64; i++) {
  3824.                 for (j = 0; j < 64; j++) {
  3825.                         flipt [i] [j] = flip_type (i, j);
  3826.                 }
  3827.         }
  3828. }
  3829.  
  3830. /*--- NORMALIZE -------*/
  3831.  
  3832. static void
  3833. norm_kkindex (SQUARE x, SQUARE y, /*@out@*/ SQUARE *pi, /*@out@*/ SQUARE *pj)
  3834. {
  3835.         unsigned int rowx, rowy, colx, coly;
  3836.  
  3837.         assert (x < 64);
  3838.         assert (y < 64);
  3839.  
  3840.         if (getcol(x) > 3) {
  3841.                 x = flipWE (x); /* x = x ^ 07  */
  3842.                 y = flipWE (y);
  3843.         }
  3844.         if (getrow(x) > 3)  {
  3845.                 x = flipNS (x); /* x = x ^ 070  */
  3846.                 y = flipNS (y);
  3847.         }
  3848.         rowx = getrow(x);
  3849.         colx = getcol(x);
  3850.         if ( rowx > colx ) {
  3851.                 x = flipNW_SE (x); /* x = ((x&7)<<3) | (x>>3) */
  3852.                 y = flipNW_SE (y);
  3853.         }
  3854.         rowy = getrow(y);
  3855.         coly = getcol(y);
  3856.         if ( rowx == colx && rowy > coly) {
  3857.                 x = flipNW_SE (x);
  3858.                 y = flipNW_SE (y);
  3859.         }
  3860.  
  3861.         *pi = x;
  3862.         *pj = y;
  3863. }
  3864.  
  3865. static unsigned int
  3866. flip_type (SQUARE x, SQUARE y)
  3867. {
  3868.         unsigned int rowx, rowy, colx, coly;
  3869.         unsigned int ret = 0;
  3870.  
  3871.         assert (x < 64);
  3872.         assert (y < 64);
  3873.  
  3874.  
  3875.         if (getcol(x) > 3) {
  3876.                 x = flipWE (x); /* x = x ^ 07  */
  3877.                 y = flipWE (y);
  3878.                 ret |= 1;
  3879.         }
  3880.         if (getrow(x) > 3)  {
  3881.                 x = flipNS (x); /* x = x ^ 070  */
  3882.                 y = flipNS (y);
  3883.                 ret |= 2;
  3884.         }
  3885.         rowx = getrow(x);
  3886.         colx = getcol(x);
  3887.         if ( rowx > colx ) {
  3888.                 x = flipNW_SE (x); /* x = ((x&7)<<3) | (x>>3) */
  3889.                 y = flipNW_SE (y);
  3890.                 ret |= 4;
  3891.         }
  3892.         rowy = getrow(y);
  3893.         coly = getcol(y);
  3894.         if ( rowx == colx && rowy > coly) {
  3895.                 x = flipNW_SE (x);
  3896.                 y = flipNW_SE (y);
  3897.                 ret |= 4;
  3898.         }
  3899.         return ret;
  3900. }
  3901.  
  3902.  
  3903. static void
  3904. pp_putanchorfirst (SQUARE a, SQUARE b, /*@out@*/ SQUARE *out_anchor, /*@out@*/ SQUARE *out_loosen)
  3905. {
  3906.         unsigned int anchor, loosen;
  3907.  
  3908.         unsigned int row_b, row_a;
  3909.         row_b = b & 070;
  3910.         row_a = a & 070;
  3911.  
  3912.         /* default */
  3913.         anchor = a;
  3914.         loosen = b;
  3915.         if (row_b > row_a) {
  3916.                 anchor = b;
  3917.                 loosen = a;
  3918.         }
  3919.         else
  3920.         if (row_b == row_a) {
  3921.                 unsigned int x, col, inv, hi_a, hi_b;
  3922.                 x = a;
  3923.                 col = x & 07;
  3924.                 inv = col ^ 07;
  3925.                 x = (1u<<col) | (1u<<inv);
  3926.                 x &= (x-1);
  3927.                 hi_a = x;
  3928.  
  3929.                 x = b;
  3930.                 col = x & 07;
  3931.                 inv = col ^ 07;
  3932.                 x = (1u<<col) | (1u<<inv);
  3933.                 x &= (x-1);
  3934.                 hi_b = x;
  3935.  
  3936.                 if (hi_b > hi_a) {
  3937.                         anchor = b;
  3938.                         loosen = a;
  3939.                 }
  3940.  
  3941.                 if (hi_b < hi_a) {
  3942.                         anchor = a;
  3943.                         loosen = b;
  3944.                 }
  3945.  
  3946.                 if (hi_b == hi_a) {
  3947.                         if (a < b) {
  3948.                                 anchor = a;
  3949.                                 loosen = b;
  3950.                         } else {
  3951.                                 anchor = b;
  3952.                                 loosen = a;
  3953.                         }
  3954.                 }
  3955.         }
  3956.  
  3957.         *out_anchor = anchor;
  3958.         *out_loosen = loosen;
  3959.         return;
  3960. }
  3961.  
  3962.  
  3963. static index_t
  3964. wsq_to_pidx24 (SQUARE pawn)
  3965. {
  3966.         unsigned int idx24;
  3967.         SQUARE sq = pawn;
  3968.  
  3969.         /* input can be only queen side, pawn valid */
  3970.         assert (A2 <= pawn && pawn < A8);
  3971.         assert ((pawn & 07) < 4);
  3972.  
  3973.         sq ^= 070; /* flipNS*/
  3974.         sq -= 8;   /* down one row*/
  3975.         idx24 = (sq+(sq&3)) >> 1;
  3976.         assert (idx24 < 24);
  3977.         return (index_t) idx24;
  3978. }
  3979.  
  3980. static index_t
  3981. wsq_to_pidx48 (SQUARE pawn)
  3982. {
  3983.         unsigned int idx48;
  3984.         SQUARE sq = pawn;
  3985.  
  3986.         /* input can be both queen or king side, pawn valid square  */
  3987.         assert (A2 <= pawn && pawn < A8);
  3988.  
  3989.         sq ^= 070; /* flipNS*/
  3990.         sq -= 8;   /* down one row*/
  3991.         idx48 = sq;
  3992.         assert (idx48 < 48);
  3993.         return (index_t)idx48;
  3994. }
  3995.  
  3996. static SQUARE
  3997. pidx24_to_wsq (index_t a)
  3998. {
  3999.         enum  {B11100  = 7u << 2};
  4000.         unsigned int x = (unsigned int) a;      /* x is pslice */
  4001.         assert (a < 24);
  4002.  
  4003.         x += x & B11100; /* get upper part and double it */
  4004.         x += 8;          /* add extra row  */
  4005.         x ^= 070;        /* flip NS */
  4006.         return (SQUARE) x;
  4007. }
  4008.  
  4009. static SQUARE
  4010. pidx48_to_wsq (index_t a)
  4011. {
  4012.         unsigned int x;
  4013.         assert (a < 48);
  4014.         /* x is pslice */
  4015.         x = (unsigned int)a;
  4016.         x += 8;          /* add extra row  */
  4017.         x ^= 070;        /* flip NS */
  4018.         return x;
  4019. }
  4020.  
  4021.  
  4022. static void
  4023. kxk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  4024. {
  4025.         enum  {BLOCK_A = 64};
  4026.  
  4027.         index_t a = i / BLOCK_A;
  4028.         index_t b = i - a * BLOCK_A;
  4029.  
  4030.         pw[0] = wksq [a];
  4031.         pb[0] = bksq [a];
  4032.         pw[1] = (SQUARE) b;
  4033.         pw[2] = NOSQUARE;
  4034.         pb[1] = NOSQUARE;
  4035.  
  4036.         assert (kxk_pctoindex (pw, pb, &a) && a == i);
  4037.  
  4038.         return;
  4039. }
  4040.  
  4041. static bool_t
  4042. kxk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
  4043. {
  4044.         enum  {BLOCK_A = 64};
  4045.         SQUARE *p;
  4046.         SQUARE ws[32], bs[32];
  4047.         index_t ki;
  4048.         int i;
  4049.  
  4050.         unsigned int ft;
  4051.  
  4052.         ft = flip_type (inp_pb[0],inp_pw[0]);
  4053.  
  4054.         assert (ft < 8);
  4055.  
  4056.  
  4057.         for (i = 0; inp_pw[i] != NOSQUARE; i++) {
  4058.                 ws[i] = inp_pw[i];
  4059.         }
  4060.         ws[i] = NOSQUARE;
  4061.         for (i = 0; inp_pb[i] != NOSQUARE; i++) {
  4062.                 bs[i] = inp_pb[i];
  4063.         }
  4064.         bs[i] = NOSQUARE;
  4065.  
  4066.         if ((ft & 1) != 0) {
  4067.                 for (p = ws; *p != NOSQUARE; p++)
  4068.                                 *p = flipWE (*p);
  4069.                 for (p = bs; *p != NOSQUARE; p++)
  4070.                                 *p = flipWE (*p);
  4071.         }
  4072.  
  4073.         if ((ft & 2) != 0) {
  4074.                 for (p = ws; *p != NOSQUARE; p++)
  4075.                                 *p = flipNS (*p);
  4076.                 for (p = bs; *p != NOSQUARE; p++)
  4077.                                 *p = flipNS (*p);
  4078.         }
  4079.  
  4080.         if ((ft & 4) != 0) {
  4081.                 for (p = ws; *p != NOSQUARE; p++)
  4082.                                 *p = flipNW_SE (*p);
  4083.                 for (p = bs; *p != NOSQUARE; p++)
  4084.                                 *p = flipNW_SE (*p);
  4085.         }
  4086.  
  4087.         ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
  4088.  
  4089.         if (IDX_is_empty(ki)) {
  4090.                 *out = NOINDEX;
  4091.                 return FALSE;
  4092.         }
  4093.         *out = ki * BLOCK_A + (index_t) ws[1];
  4094.         return TRUE;
  4095.  
  4096. }
  4097.  
  4098.  
  4099. static void
  4100. kabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  4101. {
  4102.         enum  {BLOCK_A = 64*64, BLOCK_B = 64};
  4103.         index_t a, b, c, r;
  4104.  
  4105.         r = i;
  4106.         a  = r / BLOCK_A;
  4107.         r -= a * BLOCK_A;
  4108.         b  = r / BLOCK_B;
  4109.         r -= b * BLOCK_B;
  4110.         c  = r;
  4111.  
  4112.         pw[0] = wksq [a];
  4113.         pb[0] = bksq [a];
  4114.  
  4115.         pw[1] = (SQUARE) b;
  4116.         pw[2] = (SQUARE) c;
  4117.         pw[3] = NOSQUARE;
  4118.  
  4119.         pb[1] = NOSQUARE;
  4120.  
  4121.         assert (kabk_pctoindex (pw, pb, &a) && a == i);
  4122.  
  4123.         return;
  4124. }
  4125.  
  4126.  
  4127. static bool_t
  4128. kabk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
  4129. {
  4130.         enum  {BLOCK_A = 64*64, BLOCK_B = 64};
  4131.         SQUARE *p;
  4132.         SQUARE ws[32], bs[32];
  4133.         index_t ki;
  4134.         int i;
  4135.  
  4136.         unsigned int ft;
  4137.  
  4138.         ft = flip_type (inp_pb[0],inp_pw[0]);
  4139.  
  4140.         assert (ft < 8);
  4141.  
  4142.         for (i = 0; inp_pw[i] != NOSQUARE; i++) {
  4143.                 ws[i] = inp_pw[i];
  4144.         }
  4145.         ws[i] = NOSQUARE;
  4146.         for (i = 0; inp_pb[i] != NOSQUARE; i++) {
  4147.                 bs[i] = inp_pb[i];
  4148.         }
  4149.         bs[i] = NOSQUARE;
  4150.  
  4151.         if ((ft & 1) != 0) {
  4152.                 for (p = ws; *p != NOSQUARE; p++)
  4153.                                 *p = flipWE (*p);
  4154.                 for (p = bs; *p != NOSQUARE; p++)
  4155.                                 *p = flipWE (*p);
  4156.         }
  4157.  
  4158.         if ((ft & 2) != 0) {
  4159.                 for (p = ws; *p != NOSQUARE; p++)
  4160.                                 *p = flipNS (*p);
  4161.                 for (p = bs; *p != NOSQUARE; p++)
  4162.                                 *p = flipNS (*p);
  4163.         }
  4164.  
  4165.         if ((ft & 4) != 0) {
  4166.                 for (p = ws; *p != NOSQUARE; p++)
  4167.                                 *p = flipNW_SE (*p);
  4168.                 for (p = bs; *p != NOSQUARE; p++)
  4169.                                 *p = flipNW_SE (*p);
  4170.         }
  4171.  
  4172.         ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
  4173.  
  4174.         if (IDX_is_empty(ki)) {
  4175.                 *out = NOINDEX;
  4176.                 return FALSE;
  4177.         }
  4178.         *out = ki * BLOCK_A + (index_t)ws[1] * BLOCK_B + (index_t)ws[2];
  4179.         return TRUE;
  4180.  
  4181. }
  4182.  
  4183.  
  4184. static void
  4185. kabkc_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  4186. {
  4187.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  4188.         index_t a, b, c, d, r;
  4189.  
  4190.         r = i;
  4191.         a  = r / BLOCK_A;
  4192.         r -= a * BLOCK_A;
  4193.         b  = r / BLOCK_B;
  4194.         r -= b * BLOCK_B;
  4195.         c  = r / BLOCK_C;
  4196.         r -= c * BLOCK_C;
  4197.         d  = r;
  4198.  
  4199.         pw[0] = wksq [a];
  4200.         pb[0] = bksq [a];
  4201.  
  4202.         pw[1] = (SQUARE) b;
  4203.         pw[2] = (SQUARE) c;
  4204.         pw[3] = NOSQUARE;
  4205.  
  4206.         pb[1] = (SQUARE) d;
  4207.         pb[2] = NOSQUARE;
  4208.  
  4209.         assert (kabkc_pctoindex (pw, pb, &a) && a == i);
  4210.  
  4211.         return;
  4212. }
  4213.  
  4214.  
  4215. static bool_t
  4216. kabkc_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
  4217. {
  4218.         enum  {N_WHITE = 3, N_BLACK = 2};
  4219.  
  4220.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  4221.         SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
  4222.         index_t ki;
  4223.         int i;
  4224.         unsigned int ft;
  4225.  
  4226.         #if 0
  4227.                 ft = flip_type (inp_pb[0], inp_pw[0]);
  4228.         #else
  4229.                 ft = flipt [inp_pb[0]] [inp_pw[0]];
  4230.         #endif
  4231.  
  4232.         assert (ft < 8);
  4233.  
  4234.         for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE;
  4235.         for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE;
  4236.  
  4237.         if ((ft & WE_FLAG) != 0) {
  4238.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
  4239.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
  4240.         }
  4241.  
  4242.         if ((ft & NS_FLAG) != 0) {
  4243.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
  4244.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
  4245.         }
  4246.  
  4247.         if ((ft & NW_SE_FLAG) != 0) {
  4248.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
  4249.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
  4250.         }
  4251.  
  4252.  
  4253.         ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
  4254.  
  4255.         if (IDX_is_empty(ki)) {
  4256.                 *out = NOINDEX;
  4257.                 return FALSE;
  4258.         }
  4259.         *out = ki * BLOCK_A + (index_t)ws[1] * BLOCK_B + (index_t)ws[2] * BLOCK_C + (index_t)bs[1];
  4260.         return TRUE;
  4261.  
  4262. }
  4263.  
  4264. /* ABC/ ***/
  4265.  
  4266. extern void
  4267. kabck_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  4268. {
  4269.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  4270.         index_t a, b, c, d, r;
  4271.  
  4272.         r = i;
  4273.         a  = r / BLOCK_A;
  4274.         r -= a * BLOCK_A;
  4275.         b  = r / BLOCK_B;
  4276.         r -= b * BLOCK_B;
  4277.         c  = r / BLOCK_C;
  4278.         r -= c * BLOCK_C;
  4279.         d  = r;
  4280.  
  4281.         pw[0] = wksq [a];
  4282.         pb[0] = bksq [a];
  4283.  
  4284.         pw[1] = (SQUARE) b;
  4285.         pw[2] = (SQUARE) c;
  4286.         pw[3] = (SQUARE) d;
  4287.         pw[4] = NOSQUARE;
  4288.  
  4289.         pb[1] = NOSQUARE;
  4290.  
  4291.         assert (kabck_pctoindex (pw, pb, &a) && a == i);
  4292.  
  4293.         return;
  4294. }
  4295.  
  4296.  
  4297. extern bool_t
  4298. kabck_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
  4299. {
  4300.         enum  {N_WHITE = 4, N_BLACK = 1};
  4301.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  4302.  
  4303.         SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
  4304.         index_t ki;
  4305.         int i;
  4306.         unsigned int ft;
  4307.  
  4308.         ft = flipt [inp_pb[0]] [inp_pw[0]];
  4309.  
  4310.         assert (ft < 8);
  4311.  
  4312.         for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE;
  4313.         for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE;
  4314.  
  4315.         if ((ft & WE_FLAG) != 0) {
  4316.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
  4317.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
  4318.         }
  4319.  
  4320.         if ((ft & NS_FLAG) != 0) {
  4321.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
  4322.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
  4323.         }
  4324.  
  4325.         if ((ft & NW_SE_FLAG) != 0) {
  4326.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
  4327.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
  4328.         }
  4329.  
  4330.  
  4331.         ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
  4332.  
  4333.         if (IDX_is_empty(ki)) {
  4334.                 *out = NOINDEX;
  4335.                 return FALSE;
  4336.         }
  4337.         *out = ki * BLOCK_A + (index_t)ws[1] * BLOCK_B + (index_t)ws[2] * BLOCK_C + (index_t)ws[3];
  4338.         return TRUE;
  4339.  
  4340. }
  4341.  
  4342.  
  4343. static void
  4344. kakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  4345. {
  4346.         enum  {BLOCK_A = 64*64, BLOCK_B = 64};
  4347.         index_t a, b, c, r;
  4348.  
  4349.         r = i;
  4350.         a  = r / BLOCK_A;
  4351.         r -= a * BLOCK_A;
  4352.         b  = r / BLOCK_B;
  4353.         r -= b * BLOCK_B;
  4354.         c  = r;
  4355.  
  4356.         pw[0] = wksq [a];
  4357.         pb[0] = bksq [a];
  4358.  
  4359.         pw[1] = (SQUARE) b;
  4360.         pw[2] = NOSQUARE;
  4361.  
  4362.         pb[1] = (SQUARE) c;
  4363.         pb[2] = NOSQUARE;
  4364.  
  4365.         assert (kakb_pctoindex (pw, pb, &a) && a == i);
  4366.  
  4367.         return;
  4368. }
  4369.  
  4370.  
  4371. static bool_t
  4372. kakb_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
  4373. {
  4374.         enum  {BLOCK_A = 64*64, BLOCK_B = 64};
  4375.         SQUARE ws[32], bs[32];
  4376.         index_t ki;
  4377.         unsigned int ft;
  4378.  
  4379.         #if 0
  4380.                 ft = flip_type (inp_pb[0], inp_pw[0]);
  4381.         #else
  4382.                 ft = flipt [inp_pb[0]] [inp_pw[0]];
  4383.         #endif
  4384.  
  4385.         assert (ft < 8);
  4386.  
  4387.         ws[0] = inp_pw[0];
  4388.         ws[1] = inp_pw[1];
  4389.         ws[2] = NOSQUARE;
  4390.  
  4391.         bs[0] = inp_pb[0];
  4392.         bs[1] = inp_pb[1];
  4393.         bs[2] = NOSQUARE;
  4394.  
  4395.         if ((ft & 1) != 0) {
  4396.                 ws[0] = flipWE (ws[0]);
  4397.                 ws[1] = flipWE (ws[1]);
  4398.                 bs[0] = flipWE (bs[0]);
  4399.                 bs[1] = flipWE (bs[1]);
  4400.         }
  4401.  
  4402.         if ((ft & 2) != 0) {
  4403.                 ws[0] = flipNS (ws[0]);
  4404.                 ws[1] = flipNS (ws[1]);
  4405.                 bs[0] = flipNS (bs[0]);
  4406.                 bs[1] = flipNS (bs[1]);
  4407.         }
  4408.  
  4409.         if ((ft & 4) != 0) {
  4410.                 ws[0] = flipNW_SE (ws[0]);
  4411.                 ws[1] = flipNW_SE (ws[1]);
  4412.                 bs[0] = flipNW_SE (bs[0]);
  4413.                 bs[1] = flipNW_SE (bs[1]);
  4414.         }
  4415.  
  4416.         ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
  4417.  
  4418.         if (IDX_is_empty(ki)) {
  4419.                 *out = NOINDEX;
  4420.                 return FALSE;
  4421.         }
  4422.         *out = ki * BLOCK_A + (index_t)ws[1] * BLOCK_B + (index_t)bs[1];
  4423.         return TRUE;
  4424.  
  4425. }
  4426.  
  4427. /********************** KAAKB *************************************/
  4428.  
  4429. static bool_t   test_kaakb (void);
  4430. static bool_t   kaakb_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  4431. static void             kaakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  4432.  
  4433. static bool_t
  4434. test_kaakb (void)
  4435. {
  4436.  
  4437.         enum  {MAXPC = 16+1};
  4438.         char            str[] = "kaakb";
  4439.         SQUARE          a, b, c, d, e;
  4440.         SQUARE          pw[MAXPC], pb[MAXPC];
  4441.         SQUARE          px[MAXPC], py[MAXPC];
  4442.  
  4443.         index_t         i, j;
  4444.         bool_t          err = FALSE;
  4445.  
  4446.         printf ("%8s ", str);
  4447.  
  4448.         for (a = 0; a < 64; a++) {
  4449.                 for (b = 0; b < 64; b++) {
  4450.                 for (c = 0; c < 64; c++) {
  4451.                 for (d = 0; d < 64; d++) {
  4452.                 for (e = 0; e < 64; e++) {
  4453.  
  4454.                         pw[0] = a;
  4455.                         pw[1] = b;
  4456.                         pw[2] = c;
  4457.                         pw[3] = NOSQUARE;
  4458.  
  4459.                         pb[0] = d;
  4460.                         pb[1] = e;
  4461.                         pb[2] = NOSQUARE;
  4462.  
  4463.                         if (kaakb_pctoindex (pw, pb, &i)) {
  4464.                                                         kaakb_indextopc (i, px, py);
  4465.                                                         kaakb_pctoindex (px, py, &j);
  4466.                                                         if (i != j) {
  4467.                                                                 err = TRUE;
  4468.                                                         }
  4469.                                                         assert (i == j);
  4470.                         }
  4471.  
  4472.                 }
  4473.                 }
  4474.                 }
  4475.                 }
  4476.  
  4477.         if ((a&1)==0) {
  4478.             printf(".");
  4479.             fflush(stdout);
  4480.         }
  4481.         }
  4482.  
  4483.         if (err)
  4484.                 printf ("> %s NOT passed\n", str);
  4485.         else
  4486.                 printf ("> %s PASSED\n", str);
  4487.         return !err;
  4488. }
  4489.  
  4490. static void
  4491. kaakb_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  4492. {
  4493.         enum  {
  4494.                         BLOCK_B = 64,
  4495.                         BLOCK_A = BLOCK_B * MAX_AAINDEX
  4496.                 };
  4497.         index_t a, b, c, r, x, y;
  4498.  
  4499.         r = i;
  4500.         a  = r / BLOCK_A;
  4501.         r -= a * BLOCK_A;
  4502.  
  4503.         b  = r / BLOCK_B;
  4504.         r -= b * BLOCK_B;
  4505.  
  4506.         c  = r;
  4507.  
  4508.         assert (i == (a * BLOCK_A + b * BLOCK_B + c));
  4509.  
  4510.         pw[0] = wksq [a];
  4511.         pb[0] = bksq [a];
  4512.  
  4513.         x = aabase [b];
  4514.         y = (b + 1) + x - (x * (127-x)/2);
  4515.  
  4516.         pw[1] = (SQUARE) x;
  4517.         pw[2] = (SQUARE) y;
  4518.         pw[3] = NOSQUARE;
  4519.  
  4520.         pb[1] = (SQUARE) c;
  4521.         pb[2] = NOSQUARE;
  4522.  
  4523.         assert (kaakb_pctoindex (pw, pb, &a) && a == i);
  4524.  
  4525.         return;
  4526. }
  4527.  
  4528. static bool_t
  4529. kaakb_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out)
  4530. {
  4531.         enum  {N_WHITE = 3, N_BLACK = 2};
  4532.         enum  {
  4533.                         BLOCK_B = 64,
  4534.                         BLOCK_A = BLOCK_B * MAX_AAINDEX
  4535.                 };
  4536.         SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
  4537.         index_t ki, ai;
  4538.         unsigned int ft;
  4539.         int i;
  4540.  
  4541.         ft = flipt [inp_pb[0]] [inp_pw[0]];
  4542.  
  4543.         assert (ft < 8);
  4544.  
  4545.         for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE;
  4546.         for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE;
  4547.  
  4548.         if ((ft & WE_FLAG) != 0) {
  4549.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
  4550.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
  4551.         }
  4552.  
  4553.         if ((ft & NS_FLAG) != 0) {
  4554.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
  4555.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
  4556.         }
  4557.  
  4558.         if ((ft & NW_SE_FLAG) != 0) {
  4559.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
  4560.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
  4561.         }
  4562.  
  4563.         ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
  4564.         ai = aaidx [ws[1]] [ws[2]];
  4565.  
  4566.         if (IDX_is_empty(ki) || IDX_is_empty(ai)) {
  4567.                 *out = NOINDEX;
  4568.                 return FALSE;
  4569.         }
  4570.         *out = ki * BLOCK_A + ai * BLOCK_B + (index_t)bs[1];
  4571.         return TRUE;
  4572. }
  4573.  
  4574. /****************** End KAAKB *************************************/
  4575.  
  4576. /********************** KAAB/K ************************************/
  4577.  
  4578. static bool_t   test_kaabk (void);
  4579. static bool_t   kaabk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  4580. static void             kaabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  4581.  
  4582. static bool_t
  4583. test_kaabk (void)
  4584. {
  4585.  
  4586.         enum  {MAXPC = 16+1};
  4587.         char            str[] = "kaabk";
  4588.         SQUARE          a, b, c, d, e;
  4589.         SQUARE          pw[MAXPC], pb[MAXPC];
  4590.         SQUARE          px[MAXPC], py[MAXPC];
  4591.  
  4592.         index_t         i, j;
  4593.         bool_t          err = FALSE;
  4594.  
  4595.         printf ("%8s ", str);
  4596.  
  4597.         for (a = 0; a < 64; a++) {
  4598.                 for (b = 0; b < 64; b++) {
  4599.                 for (c = 0; c < 64; c++) {
  4600.                 for (d = 0; d < 64; d++) {
  4601.                 for (e = 0; e < 64; e++) {
  4602.  
  4603.                         pw[0] = a;
  4604.                         pw[1] = b;
  4605.                         pw[2] = c;
  4606.                         pw[3] = d;
  4607.                         pw[4] = NOSQUARE;
  4608.  
  4609.                         pb[0] = e;
  4610.                         pb[1] = NOSQUARE;
  4611.  
  4612.                         if (kaabk_pctoindex (pw, pb, &i)) {
  4613.                                                         kaabk_indextopc (i, px, py);
  4614.                                                         kaabk_pctoindex (px, py, &j);
  4615.                                                         if (i != j) {
  4616.                                                                 err = TRUE;
  4617.                                                         }
  4618.                                                         assert (i == j);
  4619.                         }
  4620.  
  4621.                 }
  4622.                 }
  4623.                 }
  4624.                 }
  4625.  
  4626.         if ((a&1)==0) {
  4627.             printf(".");
  4628.             fflush(stdout);
  4629.         }
  4630.         }
  4631.  
  4632.         if (err)
  4633.                 printf ("> %s NOT passed\n", str);
  4634.         else
  4635.                 printf ("> %s PASSED\n", str);
  4636.         return !err;
  4637. }
  4638.  
  4639. static void
  4640. kaabk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  4641. {
  4642.         enum  {
  4643.                         BLOCK_B = 64,
  4644.                         BLOCK_A = BLOCK_B * MAX_AAINDEX
  4645.                 };
  4646.         index_t a, b, c, r, x, y;
  4647.  
  4648.         r = i;
  4649.         a  = r / BLOCK_A;
  4650.         r -= a * BLOCK_A;
  4651.  
  4652.         b  = r / BLOCK_B;
  4653.         r -= b * BLOCK_B;
  4654.  
  4655.         c  = r;
  4656.  
  4657.         assert (i == (a * BLOCK_A + b * BLOCK_B + c));
  4658.  
  4659.         pw[0] = wksq [a];
  4660.         pb[0] = bksq [a];
  4661.  
  4662.         x = aabase [b];
  4663.         y = (b + 1) + x - (x * (127-x)/2);
  4664.  
  4665.         pw[1] = (SQUARE) x;
  4666.         pw[2] = (SQUARE) y;
  4667.         pw[3] = (SQUARE) c;
  4668.         pw[4] = NOSQUARE;
  4669.  
  4670.         pb[1] = NOSQUARE;
  4671.  
  4672.         assert (kaabk_pctoindex (pw, pb, &a) && a == i);
  4673.  
  4674.         return;
  4675. }
  4676.  
  4677. static bool_t
  4678. kaabk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out)
  4679. {
  4680.         enum  {N_WHITE = 4, N_BLACK = 1};
  4681.         enum  {
  4682.                         BLOCK_B = 64,
  4683.                         BLOCK_A = BLOCK_B * MAX_AAINDEX
  4684.                 };
  4685.         SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
  4686.         index_t ki, ai;
  4687.         unsigned int ft;
  4688.         int i;
  4689.  
  4690.         ft = flipt [inp_pb[0]] [inp_pw[0]];
  4691.  
  4692.         assert (ft < 8);
  4693.  
  4694.         for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE;
  4695.         for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE;
  4696.  
  4697.         if ((ft & WE_FLAG) != 0) {
  4698.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
  4699.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
  4700.         }
  4701.  
  4702.         if ((ft & NS_FLAG) != 0) {
  4703.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
  4704.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
  4705.         }
  4706.  
  4707.         if ((ft & NW_SE_FLAG) != 0) {
  4708.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
  4709.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
  4710.         }
  4711.  
  4712.         ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
  4713.         ai = aaidx [ws[1]] [ws[2]];
  4714.  
  4715.         if (IDX_is_empty(ki) || IDX_is_empty(ai)) {
  4716.                 *out = NOINDEX;
  4717.                 return FALSE;
  4718.         }
  4719.         *out = ki * BLOCK_A + ai * BLOCK_B + (index_t)ws[3];
  4720.         return TRUE;
  4721. }
  4722.  
  4723. /****************** End KAAB/K *************************************/
  4724.  
  4725. /********************** KABB/K ************************************/
  4726.  
  4727. static bool_t   test_kabbk (void);
  4728. static bool_t   kabbk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  4729. static void             kabbk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  4730.  
  4731. static bool_t
  4732. test_kabbk (void)
  4733. {
  4734.  
  4735.         enum  {MAXPC = 16+1};
  4736.         char            str[] = "kabbk";
  4737.         SQUARE          a, b, c, d, e;
  4738.         SQUARE          pw[MAXPC], pb[MAXPC];
  4739.         SQUARE          px[MAXPC], py[MAXPC];
  4740.  
  4741.         index_t         i, j;
  4742.         bool_t          err = FALSE;
  4743.  
  4744.         printf ("%8s ", str);
  4745.  
  4746.         for (a = 0; a < 64; a++) {
  4747.                 for (b = 0; b < 64; b++) {
  4748.                 for (c = 0; c < 64; c++) {
  4749.                 for (d = 0; d < 64; d++) {
  4750.                 for (e = 0; e < 64; e++) {
  4751.  
  4752.                         pw[0] = a;
  4753.                         pw[1] = b;
  4754.                         pw[2] = c;
  4755.                         pw[3] = d;
  4756.                         pw[4] = NOSQUARE;
  4757.  
  4758.                         pb[0] = e;
  4759.                         pb[1] = NOSQUARE;
  4760.  
  4761.                         if (kabbk_pctoindex (pw, pb, &i)) {
  4762.                                                         kabbk_indextopc (i, px, py);
  4763.                                                         kabbk_pctoindex (px, py, &j);
  4764.                                                         if (i != j) {
  4765.                                                                 err = TRUE;
  4766.                                                         }
  4767.                                                         assert (i == j);
  4768.                         }
  4769.  
  4770.                 }
  4771.                 }
  4772.                 }
  4773.                 }
  4774.  
  4775.         if ((a&1)==0) {
  4776.             printf(".");
  4777.             fflush(stdout);
  4778.         }
  4779.         }
  4780.  
  4781.         if (err)
  4782.                 printf ("> %s NOT passed\n", str);
  4783.         else
  4784.                 printf ("> %s PASSED\n", str);
  4785.         return !err;
  4786. }
  4787.  
  4788. static void
  4789. kabbk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  4790. {
  4791.         enum  {
  4792.                         BLOCK_B = 64,
  4793.                         BLOCK_A = BLOCK_B * MAX_AAINDEX
  4794.                 };
  4795.         index_t a, b, c, r, x, y;
  4796.  
  4797.         r = i;
  4798.         a  = r / BLOCK_A;
  4799.         r -= a * BLOCK_A;
  4800.  
  4801.         b  = r / BLOCK_B;
  4802.         r -= b * BLOCK_B;
  4803.  
  4804.         c  = r;
  4805.  
  4806.         assert (i == (a * BLOCK_A + b * BLOCK_B + c));
  4807.  
  4808.         pw[0] = wksq [a];
  4809.         pb[0] = bksq [a];
  4810.  
  4811.         x = aabase [b];
  4812.         y = (b + 1) + x - (x * (127-x)/2);
  4813.  
  4814.         pw[1] = (SQUARE) c;
  4815.         pw[2] = (SQUARE) x;
  4816.         pw[3] = (SQUARE) y;
  4817.         pw[4] = NOSQUARE;
  4818.  
  4819.         pb[1] = NOSQUARE;
  4820.  
  4821.         assert (kabbk_pctoindex (pw, pb, &a) && a == i);
  4822.  
  4823.         return;
  4824. }
  4825.  
  4826. static bool_t
  4827. kabbk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, /*@out@*/ index_t *out)
  4828. {
  4829.         enum  {N_WHITE = 4, N_BLACK = 1};
  4830.         enum  {
  4831.                         BLOCK_B = 64,
  4832.                         BLOCK_A = BLOCK_B * MAX_AAINDEX
  4833.                 };
  4834.         SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
  4835.         index_t ki, ai;
  4836.         unsigned int ft;
  4837.         int i;
  4838.  
  4839.         ft = flipt [inp_pb[0]] [inp_pw[0]];
  4840.  
  4841.         assert (ft < 8);
  4842.  
  4843.         for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE;
  4844.         for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE;
  4845.  
  4846.         if ((ft & WE_FLAG) != 0) {
  4847.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
  4848.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
  4849.         }
  4850.  
  4851.         if ((ft & NS_FLAG) != 0) {
  4852.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
  4853.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
  4854.         }
  4855.  
  4856.         if ((ft & NW_SE_FLAG) != 0) {
  4857.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
  4858.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
  4859.         }
  4860.  
  4861.         ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
  4862.         ai = aaidx [ws[2]] [ws[3]];
  4863.  
  4864.         if (IDX_is_empty(ki) || IDX_is_empty(ai)) {
  4865.                 *out = NOINDEX;
  4866.                 return FALSE;
  4867.         }
  4868.         *out = ki * BLOCK_A + ai * BLOCK_B + (index_t)ws[1];
  4869.         return TRUE;
  4870. }
  4871.  
  4872. /********************** End KABB/K *************************************/
  4873.  
  4874. /********************** init KAAA/K ************************************/
  4875.  
  4876. static index_t
  4877. aaa_getsubi (sq_t x, sq_t y, sq_t z);
  4878.  
  4879. static sq_t             aaa_xyz [MAX_AAAINDEX] [3];
  4880. static index_t          aaa_base [64];
  4881.  
  4882. static index_t
  4883. init_aaa (void)
  4884. /* modifies aaa_base[], aaa_xyz[][] */
  4885. {
  4886.         index_t comb [64];
  4887.         index_t accum;
  4888.         index_t a;
  4889.  
  4890.         index_t idx;
  4891.         SQUARE x, y, z;
  4892.  
  4893.         /* getting aaa_base */
  4894.         comb [0] = 0;
  4895.         for (a = 1; a < 64; a++) {
  4896.                 comb [a] = a * (a-1) / 2;
  4897.         }
  4898.  
  4899.         accum = 0;
  4900.         aaa_base [0] = accum;
  4901.         for (a = 0; a < (64-1); a++) {
  4902.                 accum += comb[a];
  4903.                 aaa_base [a+1] = accum;
  4904.         }
  4905.  
  4906.         assert ((accum + comb[63]) == MAX_AAAINDEX);
  4907.         /* end getting aaa_base */
  4908.  
  4909.  
  4910.         /* initialize aaa_xyz [][] */
  4911.         for (idx = 0; idx < MAX_AAAINDEX; idx++) {
  4912.                 IDX_set_empty (aaa_xyz[idx][0]);
  4913.                 IDX_set_empty (aaa_xyz[idx][1]);
  4914.                 IDX_set_empty (aaa_xyz[idx][2]);
  4915.         }
  4916.  
  4917.         idx = 0;
  4918.         for (z = 0; z < 64; z++) {
  4919.                 for (y = 0; y < z; y++) {
  4920.                         for (x = 0; x < y; x++) {
  4921.  
  4922.                                 assert (idx == aaa_getsubi (x, y, z));
  4923.  
  4924.                                 aaa_xyz [idx] [0] = x;
  4925.                                 aaa_xyz [idx] [1] = y;
  4926.                                 aaa_xyz [idx] [2] = z;
  4927.  
  4928.                                 idx++;
  4929.                         }
  4930.                 }
  4931.         }
  4932.  
  4933.         assert (idx == MAX_AAAINDEX);
  4934.  
  4935.         return idx;
  4936. }
  4937.  
  4938.  
  4939. static index_t
  4940. aaa_getsubi (sq_t x, sq_t y, sq_t z)
  4941. /* uses aaa_base */
  4942. {
  4943.         index_t calc_idx, base;
  4944.  
  4945.         assert (x < 64 && y < 64 && z < 64);
  4946.         assert (x < y && y < z);
  4947.  
  4948.         base = aaa_base[z];
  4949.         calc_idx = (index_t)x + ((index_t)y - 1) * (index_t)y / 2 + base;
  4950.  
  4951.         return calc_idx;
  4952. }
  4953.  
  4954. /********************** KAAA/K ************************************/
  4955.  
  4956. static bool_t   test_kaaak (void);
  4957. static bool_t   kaaak_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  4958. static void             kaaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  4959.  
  4960. static bool_t
  4961. test_kaaak (void)
  4962. {
  4963.  
  4964.         enum  {MAXPC = 16+1};
  4965.         char            str[] = "kaaak";
  4966.         SQUARE          a, b, c, d, e;
  4967.         SQUARE          pw[MAXPC], pb[MAXPC];
  4968.         SQUARE          px[MAXPC], py[MAXPC];
  4969.  
  4970.         index_t         i, j;
  4971.         bool_t          err = FALSE;
  4972.  
  4973.         printf ("%8s ", str);
  4974.  
  4975.         for (a = 0; a < 64; a++) {
  4976.                 for (b = 0; b < 64; b++) {
  4977.                 for (c = 0; c < 64; c++) {
  4978.                 for (d = 0; d < 64; d++) {
  4979.                 for (e = 0; e < 64; e++) {
  4980.  
  4981.                         pw[0] = a;
  4982.                         pw[1] = b;
  4983.                         pw[2] = c;
  4984.                         pw[3] = d;
  4985.                         pw[4] = NOSQUARE;
  4986.  
  4987.                         pb[0] = e;
  4988.                         pb[1] = NOSQUARE;
  4989.  
  4990.                         if (kaaak_pctoindex (pw, pb, &i)) {
  4991.                                                         kaaak_indextopc (i, px, py);
  4992.                                                         kaaak_pctoindex (px, py, &j);
  4993.                                                         if (i != j) {
  4994.                                                                 err = TRUE;
  4995.                                                         }
  4996.                                                         assert (i == j);
  4997.                         }
  4998.  
  4999.                 }
  5000.                 }
  5001.                 }
  5002.                 }
  5003.  
  5004.         if ((a&1)==0) {
  5005.             printf(".");
  5006.             fflush(stdout);
  5007.         }
  5008.         }
  5009.  
  5010.         if (err)
  5011.                 printf ("> %s NOT passed\n", str);
  5012.         else
  5013.                 printf ("> %s PASSED\n", str);
  5014.         return !err;
  5015. }
  5016.  
  5017. static void
  5018. kaaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  5019. {
  5020.         enum  {
  5021.                         BLOCK_A = MAX_AAAINDEX
  5022.                 };
  5023.         index_t a, b, r;
  5024.  
  5025.         r = i;
  5026.         a  = r / BLOCK_A;
  5027.         r -= a * BLOCK_A;
  5028.  
  5029.         b  = r;
  5030.  
  5031.         assert (i == (a * BLOCK_A + b));
  5032.         assert (b < BLOCK_A);
  5033.  
  5034.         pw[0] = wksq [a];
  5035.         pb[0] = bksq [a];
  5036.  
  5037.         pw[1] = aaa_xyz [b] [0];
  5038.         pw[2] = aaa_xyz [b] [1];
  5039.         pw[3] = aaa_xyz [b] [2];
  5040.         pw[4] = NOSQUARE;
  5041.  
  5042.         pb[1] = NOSQUARE;
  5043.  
  5044.         assert (kaaak_pctoindex (pw, pb, &a) && a == i);
  5045.  
  5046.         return;
  5047. }
  5048.  
  5049. static bool_t
  5050. kaaak_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
  5051. {
  5052.         enum  {N_WHITE = 4, N_BLACK = 1};
  5053.         enum  {
  5054.                         BLOCK_A = MAX_AAAINDEX
  5055.                 };
  5056.         SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
  5057.         index_t ki, ai;
  5058.         unsigned int ft;
  5059.         int i;
  5060.  
  5061.         ft = flipt [inp_pb[0]] [inp_pw[0]];
  5062.  
  5063.         assert (ft < 8);
  5064.  
  5065.         for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i]; ws[N_WHITE] = NOSQUARE;
  5066.         for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i]; bs[N_BLACK] = NOSQUARE;
  5067.  
  5068.         if ((ft & WE_FLAG) != 0) {
  5069.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
  5070.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
  5071.         }
  5072.  
  5073.         if ((ft & NS_FLAG) != 0) {
  5074.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
  5075.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
  5076.         }
  5077.  
  5078.         if ((ft & NW_SE_FLAG) != 0) {
  5079.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
  5080.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
  5081.         }
  5082.  
  5083.  
  5084.         {
  5085.                 SQUARE tmp;
  5086.                 if (ws[2] < ws[1]) {
  5087.             tmp = ws[1];
  5088.             ws[1] = ws[2];
  5089.             ws[2] = tmp;
  5090.                 }
  5091.                 if (ws[3] < ws[2]) {
  5092.             tmp = ws[2];
  5093.             ws[2] = ws[3];
  5094.             ws[3] = tmp;
  5095.                 }
  5096.                 if (ws[2] < ws[1]) {
  5097.             tmp = ws[1];
  5098.             ws[1] = ws[2];
  5099.             ws[2] = tmp;
  5100.                 }
  5101.         }
  5102.  
  5103.         ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
  5104.  
  5105. /*128 == (128 & (((ws[1]^ws[2])-1) | ((ws[1]^ws[3])-1) | ((ws[2]^ws[3])-1)) */
  5106.  
  5107.         if (ws[1] == ws[2] || ws[1] == ws[3] || ws[2] == ws[3]) {
  5108.                 *out = NOINDEX;
  5109.                 return FALSE;
  5110.         }
  5111.  
  5112.         ai = aaa_getsubi ( ws[1], ws[2], ws[3] );
  5113.  
  5114.         if (IDX_is_empty(ki) || IDX_is_empty(ai)) {
  5115.                 *out = NOINDEX;
  5116.                 return FALSE;
  5117.         }
  5118.         *out = ki * BLOCK_A + ai;
  5119.         return TRUE;
  5120. }
  5121.  
  5122. /****************** End KAAB/K *************************************/
  5123.  
  5124. /**********************  KAP/KB ************************************/
  5125.  
  5126. static bool_t   test_kapkb (void);
  5127. static bool_t   kapkb_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  5128. static void     kapkb_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  5129.  
  5130. static bool_t
  5131. test_kapkb (void)
  5132. {
  5133.  
  5134.         enum            {MAXPC = 16+1};
  5135.         char            str[] = "kapkb";
  5136.         SQUARE          a, b, c, d, e;
  5137.         SQUARE          pw[MAXPC], pb[MAXPC];
  5138.         SQUARE          px[MAXPC], py[MAXPC];
  5139.  
  5140.         index_t         i, j;
  5141.         bool_t          err = FALSE;
  5142.  
  5143.         printf ("%8s ", str);
  5144.  
  5145.         for (a = 0; a < 64; a++) {
  5146.                 for (b = 0; b < 64; b++) {
  5147.                 for (c = 0; c < 64; c++) {
  5148.                 for (d = 0; d < 64; d++) {
  5149.                 for (e = 0; e < 64; e++) {
  5150.  
  5151.                         if (c <= H1 || c >= A8)
  5152.                                 continue;
  5153.  
  5154.                         pw[0] = a;
  5155.                         pw[1] = b;
  5156.                         pw[2] = c;
  5157.                         pw[3] = NOSQUARE;
  5158.  
  5159.                         pb[0] = e;
  5160.                         pb[1] = d;
  5161.                         pb[2] = NOSQUARE;
  5162.  
  5163.                         if (kapkb_pctoindex (pw, pb, &i)) {
  5164.                                                         kapkb_indextopc (i, px, py);
  5165.                                                         kapkb_pctoindex (px, py, &j);
  5166.                                                         if (i != j) {
  5167.                                                                 err = TRUE;
  5168.                                                         }
  5169.                                                         assert (i == j);
  5170.                         }
  5171.  
  5172.                 }
  5173.                 }
  5174.                 }
  5175.                 }
  5176.  
  5177.         if ((a&1)==0) {
  5178.             printf(".");
  5179.             fflush(stdout);
  5180.         }
  5181.         }
  5182.  
  5183.         if (err)
  5184.                 printf ("> %s NOT passed\n", str);
  5185.         else
  5186.                 printf ("> %s PASSED\n", str);
  5187.         return !err;
  5188. }
  5189.  
  5190. static void
  5191. kapkb_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  5192. {
  5193.         /*---------------------------------------------------------*
  5194.                 inverse work to make sure that the following is valid
  5195.                 index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d * BLOCK_D + e;
  5196.         *----------------------------------------------------------*/
  5197.         enum  {B11100  = 7u << 2};
  5198.         enum  {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64};
  5199.         index_t a, b, c, d, e, r;
  5200.         index_t x;
  5201.  
  5202.         r = i;
  5203.         a  = r / BLOCK_A;
  5204.         r -= a * BLOCK_A;
  5205.         b  = r / BLOCK_B;
  5206.         r -= b * BLOCK_B;
  5207.         c  = r / BLOCK_C;
  5208.         r -= c * BLOCK_C;
  5209.         d  = r / BLOCK_D;
  5210.         r -= d * BLOCK_D;
  5211.         e  = r;
  5212.  
  5213.         /* x is pslice */
  5214.         x = a;
  5215.         x += x & B11100; /* get upper part and double it */
  5216.         x += 8;          /* add extra row  */
  5217.         x ^= 070;        /* flip NS */
  5218.  
  5219.         pw[0] = (SQUARE) b;
  5220.         pb[0] = (SQUARE) c;
  5221.         pw[1] = (SQUARE) d;
  5222.         pw[2] = (SQUARE) x;
  5223.         pw[3] = NOSQUARE;
  5224.         pb[1] = (SQUARE) e;
  5225.         pb[2] = NOSQUARE;
  5226.  
  5227.         assert (kapkb_pctoindex (pw, pb, &a) && a == i);
  5228.  
  5229.         return;
  5230. }
  5231.  
  5232.  
  5233. static bool_t
  5234. kapkb_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  5235. {
  5236.         enum  {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64};
  5237.         index_t pslice;
  5238.         SQUARE sq;
  5239.         SQUARE pawn = pw[2];
  5240.         SQUARE wa   = pw[1];
  5241.         SQUARE wk   = pw[0];
  5242.         SQUARE bk   = pb[0];
  5243.         SQUARE ba   = pb[1];
  5244.  
  5245.         assert (A2 <= pawn && pawn < A8);
  5246.  
  5247.         if (  !(A2 <= pawn && pawn < A8)) {
  5248.                 *out = NOINDEX;
  5249.                 return FALSE;
  5250.         }
  5251.  
  5252.         if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  5253.                 pawn = flipWE (pawn);
  5254.                 wk   = flipWE (wk);
  5255.                 bk   = flipWE (bk);
  5256.                 wa   = flipWE (wa);
  5257.                 ba   = flipWE (ba);
  5258.         }
  5259.  
  5260.         sq = pawn;
  5261.         sq ^= 070; /* flipNS*/
  5262.         sq -= 8;   /* down one row*/
  5263.         pslice = (index_t) ((sq+(sq&3)) >> 1);
  5264.  
  5265.         *out = pslice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk * BLOCK_C + (index_t)wa * BLOCK_D + (index_t)ba;
  5266.  
  5267.         return TRUE;
  5268. }
  5269. /********************** end KAP/KB ************************************/
  5270.  
  5271. /*************************  KAB/KP ************************************/
  5272.  
  5273. static bool_t   test_kabkp (void);
  5274. static bool_t   kabkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  5275. static void     kabkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  5276.  
  5277. static bool_t
  5278. test_kabkp (void)
  5279. {
  5280.  
  5281.         enum            {MAXPC = 16+1};
  5282.         char            str[] = "kabkp";
  5283.         SQUARE          a, b, c, d, e;
  5284.         SQUARE          pw[MAXPC], pb[MAXPC];
  5285.         SQUARE          px[MAXPC], py[MAXPC];
  5286.  
  5287.         index_t         i, j;
  5288.         bool_t          err = FALSE;
  5289.  
  5290.         printf ("%8s ", str);
  5291.  
  5292.         for (a = 0; a < 64; a++) {
  5293.                 for (b = 0; b < 64; b++) {
  5294.                 for (c = 0; c < 64; c++) {
  5295.                 for (d = 0; d < 64; d++) {
  5296.                 for (e = 0; e < 64; e++) {
  5297.  
  5298.                         if (d <= H1 || d >= A8)
  5299.                                 continue;
  5300.  
  5301.                         pw[0] = a;
  5302.                         pw[1] = b;
  5303.                         pw[2] = c;
  5304.                         pw[3] = NOSQUARE;
  5305.  
  5306.                         pb[0] = e;
  5307.                         pb[1] = d;
  5308.                         pb[2] = NOSQUARE;
  5309.  
  5310.                         if (kabkp_pctoindex (pw, pb, &i)) {
  5311.                                                         kabkp_indextopc (i, px, py);
  5312.                                                         kabkp_pctoindex (px, py, &j);
  5313.                                                         if (i != j) {
  5314.                                                                 err = TRUE;
  5315.                                                         }
  5316.                                                         assert (i == j);
  5317.                         }
  5318.  
  5319.                 }
  5320.                 }
  5321.                 }
  5322.                 }
  5323.  
  5324.         if ((a&1)==0) {
  5325.             printf(".");
  5326.             fflush(stdout);
  5327.         }
  5328.         }
  5329.  
  5330.         if (err)
  5331.                 printf ("> %s NOT passed\n", str);
  5332.         else
  5333.                 printf ("> %s PASSED\n", str);
  5334.         return !err;
  5335. }
  5336.  
  5337. static void
  5338. kabkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  5339. {
  5340.         /*---------------------------------------------------------*
  5341.                 inverse work to make sure that the following is valid
  5342.                 index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d * BLOCK_D + e;
  5343.         *----------------------------------------------------------*/
  5344.         enum  {B11100  = 7u << 2};
  5345.         enum  {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64};
  5346.         index_t a, b, c, d, e, r;
  5347.         index_t x;
  5348.  
  5349.         r = i;
  5350.         a  = r / BLOCK_A;
  5351.         r -= a * BLOCK_A;
  5352.         b  = r / BLOCK_B;
  5353.         r -= b * BLOCK_B;
  5354.         c  = r / BLOCK_C;
  5355.         r -= c * BLOCK_C;
  5356.         d  = r / BLOCK_D;
  5357.         r -= d * BLOCK_D;
  5358.         e  = r;
  5359.  
  5360.         /* x is pslice */
  5361.         x = a;
  5362.         x += x & B11100; /* get upper part and double it */
  5363.         x += 8;          /* add extra row  */
  5364.         /*x ^= 070;*/        /* do not flip NS */
  5365.  
  5366.         pw[0] = (SQUARE) b;
  5367.         pb[0] = (SQUARE) c;
  5368.         pw[1] = (SQUARE) d;
  5369.         pw[2] = (SQUARE) e;
  5370.         pw[3] = NOSQUARE;
  5371.         pb[1] = (SQUARE) x;
  5372.         pb[2] = NOSQUARE;
  5373.  
  5374.         assert (kabkp_pctoindex (pw, pb, &a) && a == i);
  5375.  
  5376.         return;
  5377. }
  5378.  
  5379.  
  5380. static bool_t
  5381. kabkp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  5382. {
  5383.         enum  {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64};
  5384.         index_t pslice;
  5385.         SQUARE sq;
  5386.         SQUARE pawn = pb[1];
  5387.         SQUARE wa   = pw[1];
  5388.         SQUARE wk   = pw[0];
  5389.         SQUARE bk   = pb[0];
  5390.         SQUARE wb   = pw[2];
  5391.  
  5392.         assert (A2 <= pawn && pawn < A8);
  5393.  
  5394.         if (  !(A2 <= pawn && pawn < A8)) {
  5395.                 *out = NOINDEX;
  5396.                 return FALSE;
  5397.         }
  5398.  
  5399.         if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  5400.                 pawn = flipWE (pawn);
  5401.                 wk   = flipWE (wk);
  5402.                 bk   = flipWE (bk);
  5403.                 wa   = flipWE (wa);
  5404.                 wb   = flipWE (wb);
  5405.         }
  5406.  
  5407.         sq = pawn;
  5408.         /*sq ^= 070;*/ /* do not flipNS*/
  5409.         sq -= 8;   /* down one row*/
  5410.         pslice = (index_t) ((sq+(sq&3)) >> 1);
  5411.  
  5412.         *out = pslice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk * BLOCK_C + (index_t)wa * BLOCK_D + (index_t)wb;
  5413.  
  5414.         return TRUE;
  5415. }
  5416. /********************** end KAB/KP ************************************/
  5417.  
  5418.  
  5419. static void
  5420. kpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  5421. {
  5422.         /*---------------------------------------------------------*
  5423.                 inverse work to make sure that the following is valid
  5424.                 index = a * BLOCK_A + b * BLOCK_B + c;
  5425.         *----------------------------------------------------------*/
  5426.         enum  {B11100  = 7u << 2};
  5427.         enum  {BLOCK_A = 64*64, BLOCK_B = 64};
  5428.         index_t a, b, c, r;
  5429.         index_t x;
  5430.  
  5431.         r = i;
  5432.         a  = r / BLOCK_A;
  5433.         r -= a * BLOCK_A;
  5434.         b  = r / BLOCK_B;
  5435.         r -= b * BLOCK_B;
  5436.         c  = r;
  5437.  
  5438.         /* x is pslice */
  5439.         x = a;
  5440.         x += x & B11100; /* get upper part and double it */
  5441.         x += 8;          /* add extra row  */
  5442.         x ^= 070;        /* flip NS */
  5443.  
  5444.         pw[1] = (SQUARE) x;
  5445.         pw[0] = (SQUARE) b;
  5446.         pb[0] = (SQUARE) c;
  5447.  
  5448.         pw[2] = NOSQUARE;
  5449.         pb[1] = NOSQUARE;
  5450.  
  5451.         assert (kpk_pctoindex (pw, pb, &a) && a == i);
  5452.  
  5453.         return;
  5454. }
  5455.  
  5456.  
  5457. static bool_t
  5458. kpk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  5459. {
  5460.         enum  {BLOCK_A = 64*64, BLOCK_B = 64};
  5461.         index_t pslice;
  5462.         SQUARE sq;
  5463.         SQUARE pawn = pw[1];
  5464.         SQUARE wk   = pw[0];
  5465.         SQUARE bk   = pb[0];
  5466.  
  5467.         #ifdef DEBUG
  5468.         if (  !(A2 <= pawn && pawn < A8)) {
  5469.                 SQ_CONTENT wp[MAX_LISTSIZE], bp[MAX_LISTSIZE];
  5470.         bp [0] = wp[0] = KING;
  5471.         wp[1] = PAWN;
  5472.         wp[2] = bp[1] = NOPIECE;
  5473.                 output_state (0, pw, pb, wp, bp);
  5474.         }
  5475.         #endif
  5476.  
  5477.         assert (A2 <= pawn && pawn < A8);
  5478.  
  5479.         if (  !(A2 <= pawn && pawn < A8)) {
  5480.                 *out = NOINDEX;
  5481.                 return FALSE;
  5482.         }
  5483.  
  5484.         if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  5485.                 pawn = flipWE (pawn);
  5486.                 wk   = flipWE (wk);
  5487.                 bk   = flipWE (bk);
  5488.         }
  5489.  
  5490.         sq = pawn;
  5491.         sq ^= 070; /* flipNS*/
  5492.         sq -= 8;   /* down one row*/
  5493.         pslice = (index_t) ((sq+(sq&3)) >> 1);
  5494.  
  5495.         *out = pslice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk;
  5496.  
  5497.         return TRUE;
  5498. }
  5499.  
  5500.  
  5501. /**********************  KPP/K ************************************/
  5502.  
  5503. static bool_t   test_kppk (void);
  5504. static bool_t   kppk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  5505. static void             kppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  5506.  
  5507. static bool_t
  5508. test_kppk (void)
  5509. {
  5510.  
  5511.         enum            {MAXPC = 16+1};
  5512.         char            str[] = "kppk";
  5513.         SQUARE          a, b, c, d;
  5514.         SQUARE          pw[MAXPC], pb[MAXPC];
  5515.         SQUARE          px[MAXPC], py[MAXPC];
  5516.  
  5517.         index_t         i, j;
  5518.         bool_t          err = FALSE;
  5519.  
  5520.         printf ("%8s ", str);
  5521.  
  5522.         for (b = 0; b < 64; b++) {
  5523.                 for (c = 0; c < 64; c++) {
  5524.                         sq_t anchor1, anchor2, loosen1, loosen2;
  5525.                         if (c <= H1 || c >= A8)
  5526.                                 continue;
  5527.                         if (b <= H1 || b >= A8)
  5528.                                 continue;
  5529.  
  5530.                         pp_putanchorfirst (b, c, &anchor1, &loosen1);
  5531.                         pp_putanchorfirst (c, b, &anchor2, &loosen2);
  5532.                         if (!(anchor1 == anchor2 && loosen1 == loosen2)) {
  5533.                                 printf ("Output depends on input in pp_outanchorfirst()\n input:%u, %u\n",(unsigned)b,(unsigned)c);
  5534.                                 fatal_error();
  5535.                         }
  5536.                 }
  5537.         }
  5538.  
  5539.  
  5540.         for (a = 0; a < 64; a++) {
  5541.                 for (b = 0; b < 64; b++) {
  5542.                 for (c = 0; c < 64; c++) {
  5543.                 for (d = 0; d < 64; d++) {
  5544.  
  5545.  
  5546.                         if (c <= H1 || c >= A8)
  5547.                                 continue;
  5548.                         if (b <= H1 || b >= A8)
  5549.                                 continue;
  5550.  
  5551.  
  5552.                         pw[0] = a;
  5553.                         pw[1] = b;
  5554.                         pw[2] = c;
  5555.                         pw[3] = NOSQUARE;
  5556.  
  5557.                         pb[0] = d;
  5558.                         pb[1] = NOSQUARE;
  5559.  
  5560.                         if (kppk_pctoindex (pw, pb, &i)) {
  5561.                                                         kppk_indextopc (i, px, py);
  5562.                                                         kppk_pctoindex (px, py, &j);
  5563.                                                         if (i != j) {
  5564.                                                                 err = TRUE;
  5565.                                                         }
  5566.                                                         assert (i == j);
  5567.                         }
  5568.  
  5569.  
  5570.                 }
  5571.                 }
  5572.                 }
  5573.  
  5574.         if ((a&1)==0) {
  5575.             printf(".");
  5576.             fflush(stdout);
  5577.         }
  5578.         }
  5579.  
  5580.         if (err)
  5581.                 printf ("> %s NOT passed\n", str);
  5582.         else
  5583.                 printf ("> %s PASSED\n", str);
  5584.         return !err;
  5585. }
  5586.  
  5587. static void
  5588. kppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  5589. {
  5590.         /*---------------------------------------------------------*
  5591.                 inverse work to make sure that the following is valid
  5592.                 index = a * BLOCK_A + b * BLOCK_B + c;
  5593.         *----------------------------------------------------------*/
  5594.         enum  {B11100  = 7u << 2};
  5595.         enum  {BLOCK_A = 64*64, BLOCK_B = 64};
  5596.         index_t a, b, c, r;
  5597.         index_t m, n;
  5598.  
  5599.         r = i;
  5600.         a  = r / BLOCK_A;
  5601.         r -= a * BLOCK_A;
  5602.         b  = r / BLOCK_B;
  5603.         r -= b * BLOCK_B;
  5604.         c  = r;
  5605.  
  5606.         m = pp_hi24 [a];
  5607.         n = pp_lo48 [a];
  5608.  
  5609.         pw[0] = (SQUARE) b;
  5610.         pb[0] = (SQUARE) c;
  5611.         pb[1] = NOSQUARE;
  5612.  
  5613.         pw[1] = pidx24_to_wsq (m);
  5614.         pw[2] = pidx48_to_wsq (n);
  5615.  
  5616.         pw[3] = NOSQUARE;
  5617.  
  5618.  
  5619.         assert (A2 <= pw[1] && pw[1] < A8);
  5620.         assert (A2 <= pw[2] && pw[2] < A8);
  5621.  
  5622. #ifdef DEBUG
  5623.         if (!(kppk_pctoindex (pw, pb, &a) && a == i)) {
  5624.                 pc_t wp[] = {KING, PAWN, PAWN, NOPIECE};
  5625.                 pc_t bp[] = {KING, NOPIECE};
  5626.                 printf("Indexes not matching: input:%d, output:%d\n", i, a);
  5627.                 print_pos (pw, pb, wp, bp);
  5628.         }
  5629. #endif
  5630.  
  5631.         assert (kppk_pctoindex (pw, pb, &a) && a == i);
  5632.  
  5633.         return;
  5634. }
  5635.  
  5636.  
  5637. static bool_t
  5638. kppk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  5639. {
  5640.         enum  {BLOCK_A = 64*64, BLOCK_B = 64};
  5641.         index_t pp_slice;
  5642.         SQUARE anchor, loosen;
  5643.  
  5644.         SQUARE wk     = pw[0];
  5645.         SQUARE pawn_a = pw[1];
  5646.         SQUARE pawn_b = pw[2];
  5647.         SQUARE bk     = pb[0];
  5648.         index_t i, j;
  5649.  
  5650.         #ifdef DEBUG
  5651.         if (!(A2 <= pawn_a && pawn_a < A8)) {
  5652.                 printf ("\n\nsquare of pawn_a: %s\n", Square_str[pawn_a]);
  5653.                 printf(" wk %s\n p1 %s\n p2 %s\n bk %s\n"
  5654.                         , Square_str[wk]
  5655.                         , Square_str[pawn_a]
  5656.                         , Square_str[pawn_b]
  5657.                         , Square_str[bk]
  5658.                         );
  5659.         }
  5660.         #endif
  5661.  
  5662.         assert (A2 <= pawn_a && pawn_a < A8);
  5663.         assert (A2 <= pawn_b && pawn_b < A8);
  5664.  
  5665.         pp_putanchorfirst (pawn_a, pawn_b, &anchor, &loosen);
  5666.  
  5667.         if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  5668.                 anchor = flipWE (anchor);
  5669.                 loosen = flipWE (loosen);
  5670.                 wk     = flipWE (wk);
  5671.                 bk     = flipWE (bk);
  5672.         }
  5673.  
  5674.         i = wsq_to_pidx24 (anchor);
  5675.         j = wsq_to_pidx48 (loosen);
  5676.  
  5677.         pp_slice = ppidx [i] [j];
  5678.  
  5679.         if (IDX_is_empty(pp_slice)) {
  5680.                 *out = NOINDEX;
  5681.                 return FALSE;
  5682.         }
  5683.  
  5684.         assert (pp_slice < MAX_PPINDEX );
  5685.  
  5686.         *out = pp_slice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk;
  5687.  
  5688.         return TRUE;
  5689. }
  5690. /****************** end  KPP/K ************************************/
  5691.  
  5692. static void
  5693. kakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  5694. {
  5695.         /*---------------------------------------------------------*
  5696.                 inverse work to make sure that the following is valid
  5697.                 index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d;
  5698.         *----------------------------------------------------------*/
  5699.         enum  {B11100  = 7u << 2};
  5700.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  5701.         index_t a, b, c, d, r;
  5702.         index_t x;
  5703.  
  5704.         r = i;
  5705.         a  = r / BLOCK_A;
  5706.         r -= a * BLOCK_A;
  5707.         b  = r / BLOCK_B;
  5708.         r -= b * BLOCK_B;
  5709.         c  = r / BLOCK_C;
  5710.         r -= c * BLOCK_C;
  5711.         d  = r;
  5712.  
  5713.         /* x is pslice */
  5714.         x = a;
  5715.         x += x & B11100; /* get upper part and double it */
  5716.         x += 8;          /* add extra row  */
  5717. /*      x ^= 070;   */     /* flip NS */
  5718.  
  5719.         pw[0] = (SQUARE) b;
  5720.         pb[0] = (SQUARE) c;
  5721.         pw[1] = (SQUARE) d;
  5722.         pb[1] = (SQUARE) x;
  5723.         pw[2] = NOSQUARE;
  5724.         pb[2] = NOSQUARE;
  5725.  
  5726.         assert (kakp_pctoindex (pw, pb, &a) && a == i);
  5727.  
  5728.         return;
  5729. }
  5730.  
  5731.  
  5732. static bool_t
  5733. kakp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  5734. {
  5735.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  5736.         index_t pslice;
  5737.         SQUARE sq;
  5738.         SQUARE pawn = pb[1];
  5739.         SQUARE wa   = pw[1];
  5740.         SQUARE wk   = pw[0];
  5741.         SQUARE bk   = pb[0];
  5742.  
  5743.         assert (A2 <= pawn && pawn < A8);
  5744.  
  5745.         if (  !(A2 <= pawn && pawn < A8)) {
  5746.                 *out = NOINDEX;
  5747.                 return FALSE;
  5748.         }
  5749.  
  5750.         if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  5751.                 pawn = flipWE (pawn);
  5752.                 wk   = flipWE (wk);
  5753.                 bk   = flipWE (bk);
  5754.                 wa   = flipWE (wa);
  5755.         }
  5756.  
  5757.         sq = pawn;
  5758.         /*sq ^= 070;*/ /* flipNS*/
  5759.         sq -= 8;   /* down one row*/
  5760.         pslice = (index_t) ((sq+(sq&3)) >> 1);
  5761.  
  5762.         *out = pslice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk * BLOCK_C + (index_t)wa;
  5763.  
  5764.         return TRUE;
  5765. }
  5766.  
  5767.  
  5768. static void
  5769. kapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  5770. {
  5771.         /*---------------------------------------------------------*
  5772.                 inverse work to make sure that the following is valid
  5773.                 index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d;
  5774.         *----------------------------------------------------------*/
  5775.         enum  {B11100  = 7u << 2};
  5776.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  5777.         index_t a, b, c, d, r;
  5778.         index_t x;
  5779.  
  5780.         r = i;
  5781.         a  = r / BLOCK_A;
  5782.         r -= a * BLOCK_A;
  5783.         b  = r / BLOCK_B;
  5784.         r -= b * BLOCK_B;
  5785.         c  = r / BLOCK_C;
  5786.         r -= c * BLOCK_C;
  5787.         d  = r;
  5788.  
  5789.         /* x is pslice */
  5790.         x = a;
  5791.         x += x & B11100; /* get upper part and double it */
  5792.         x += 8;          /* add extra row  */
  5793.         x ^= 070;        /* flip NS */
  5794.  
  5795.         pw[0] = (SQUARE) b;
  5796.         pb[0] = (SQUARE) c;
  5797.         pw[1] = (SQUARE) d;
  5798.         pw[2] = (SQUARE) x;
  5799.         pw[3] = NOSQUARE;
  5800.         pb[1] = NOSQUARE;
  5801.  
  5802.         assert (kapk_pctoindex (pw, pb, &a) && a == i);
  5803.  
  5804.         return;
  5805. }
  5806.  
  5807.  
  5808. static bool_t
  5809. kapk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  5810. {
  5811.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  5812.         index_t pslice;
  5813.         SQUARE sq;
  5814.         SQUARE pawn = pw[2];
  5815.         SQUARE wa   = pw[1];
  5816.         SQUARE wk   = pw[0];
  5817.         SQUARE bk   = pb[0];
  5818.  
  5819.         assert (A2 <= pawn && pawn < A8);
  5820.  
  5821.         if (  !(A2 <= pawn && pawn < A8)) {
  5822.                 *out = NOINDEX;
  5823.                 return FALSE;
  5824.         }
  5825.  
  5826.         if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  5827.                 pawn = flipWE (pawn);
  5828.                 wk   = flipWE (wk);
  5829.                 bk   = flipWE (bk);
  5830.                 wa   = flipWE (wa);
  5831.         }
  5832.  
  5833.         sq = pawn;
  5834.         sq ^= 070; /* flipNS*/
  5835.         sq -= 8;   /* down one row*/
  5836.         pslice = (index_t) ((sq+(sq&3)) >> 1);
  5837.  
  5838.         *out = pslice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk * BLOCK_C + (index_t)wa;
  5839.  
  5840.         return TRUE;
  5841. }
  5842.  
  5843.  
  5844. static void
  5845. kaak_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  5846. {
  5847.         enum  {BLOCK_A = MAX_AAINDEX};
  5848.         index_t a, b, r, x, y;
  5849.  
  5850.         r = i;
  5851.         a  = r / BLOCK_A;
  5852.         r -= a * BLOCK_A;
  5853.         b  = r;
  5854.  
  5855.         assert (i == (a * BLOCK_A + b));
  5856.  
  5857.         pw[0] = wksq [a];
  5858.         pb[0] = bksq [a];
  5859.  
  5860.         x = aabase [b];
  5861.         y = (b + 1) + x - (x * (127-x)/2);
  5862.  
  5863.         pw[1] = (SQUARE) x;
  5864.         pw[2] = (SQUARE) y;
  5865.         pw[3] = NOSQUARE;
  5866.  
  5867.         pb[1] = NOSQUARE;
  5868.  
  5869.         assert (kaak_pctoindex (pw, pb, &a) && a == i);
  5870.  
  5871.         return;
  5872. }
  5873.  
  5874.  
  5875. static bool_t
  5876. kaak_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out)
  5877. {
  5878.         enum  {N_WHITE = 3, N_BLACK = 1};
  5879.         enum  {BLOCK_A = MAX_AAINDEX};
  5880.         SQUARE ws[MAX_LISTSIZE], bs[MAX_LISTSIZE];
  5881.         index_t ki, ai;
  5882.         unsigned int ft;
  5883.         SQUARE i;
  5884.  
  5885.         ft = flipt [inp_pb[0]] [inp_pw[0]];
  5886.  
  5887.         assert (ft < 8);
  5888.  
  5889.     for (i = 0; i < N_WHITE; i++) ws[i] = inp_pw[i];
  5890.     ws[N_WHITE] = NOSQUARE;
  5891.     for (i = 0; i < N_BLACK; i++) bs[i] = inp_pb[i];
  5892.     bs[N_BLACK] = NOSQUARE;
  5893.  
  5894.         if ((ft & WE_FLAG) != 0) {
  5895.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipWE (ws[i]);
  5896.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipWE (bs[i]);
  5897.         }
  5898.  
  5899.         if ((ft & NS_FLAG) != 0) {
  5900.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNS (ws[i]);
  5901.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNS (bs[i]);
  5902.         }
  5903.  
  5904.         if ((ft & NW_SE_FLAG) != 0) {
  5905.                 for (i = 0; i < N_WHITE; i++) ws[i] = flipNW_SE (ws[i]);
  5906.                 for (i = 0; i < N_BLACK; i++) bs[i] = flipNW_SE (bs[i]);
  5907.         }
  5908.  
  5909.         ki = kkidx [bs[0]] [ws[0]]; /* kkidx [black king] [white king] */
  5910.         ai = (index_t) aaidx [ws[1]] [ws[2]];
  5911.  
  5912.         if (IDX_is_empty(ki) || IDX_is_empty(ai)) {
  5913.                 *out = NOINDEX;
  5914.                 return FALSE;
  5915.         }
  5916.         *out = ki * BLOCK_A + ai;
  5917.         return TRUE;
  5918. }
  5919.  
  5920. /**********************  KPP/KA ************************************/
  5921.  
  5922. static bool_t   test_kppka (void);
  5923. static bool_t   kppka_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  5924. static void             kppka_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  5925.  
  5926. static bool_t
  5927. test_kppka (void)
  5928. {
  5929.  
  5930.         enum            {MAXPC = 16+1};
  5931.         char            str[] = "kppka";
  5932.         SQUARE          a, b, c, d, e;
  5933.         SQUARE          pw[MAXPC], pb[MAXPC];
  5934.         SQUARE          px[MAXPC], py[MAXPC];
  5935.  
  5936.         index_t         i, j;
  5937.         bool_t          err = FALSE;
  5938.  
  5939.         printf ("%8s ", str);
  5940.  
  5941.         for (a = 0; a < 64; a++) {
  5942.                 for (b = 0; b < 64; b++) {
  5943.                 for (c = 0; c < 64; c++) {
  5944.                 for (d = 0; d < 64; d++) {
  5945.                 for (e = 0; e < 64; e++) {
  5946.  
  5947.                         if (c <= H1 || c >= A8)
  5948.                                 continue;
  5949.                         if (b <= H1 || b >= A8)
  5950.                                 continue;
  5951.  
  5952.  
  5953.                         pw[0] = a;
  5954.                         pw[1] = b;
  5955.                         pw[2] = c;
  5956.                         pw[3] = NOSQUARE;
  5957.  
  5958.                         pb[0] = e;
  5959.                         pb[1] = d;
  5960.                         pb[2] = NOSQUARE;
  5961.  
  5962.                         if (kppka_pctoindex (pw, pb, &i)) {
  5963.                                                         kppka_indextopc (i, px, py);
  5964.                                                         kppka_pctoindex (px, py, &j);
  5965.                                                         if (i != j) {
  5966.                                                                 err = TRUE;
  5967.                                                         }
  5968.                                                         assert (i == j);
  5969.                         }
  5970.  
  5971.                 }
  5972.                 }
  5973.                 }
  5974.                 }
  5975.  
  5976.         if ((a&1)==0) {
  5977.             printf(".");
  5978.             fflush(stdout);
  5979.         }
  5980.         }
  5981.  
  5982.         if (err)
  5983.                 printf ("> %s NOT passed\n", str);
  5984.         else
  5985.                 printf ("> %s PASSED\n", str);
  5986.         return !err;
  5987. }
  5988.  
  5989.  
  5990. static void
  5991. kppka_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  5992. {
  5993.         /*---------------------------------------------------------*
  5994.                 inverse work to make sure that the following is valid
  5995.                 index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d;
  5996.         *----------------------------------------------------------*/
  5997.  
  5998.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  5999.         index_t a, b, c, d, r;
  6000.         index_t m, n;
  6001.  
  6002.         r = i;
  6003.         a  = r / BLOCK_A;
  6004.         r -= a * BLOCK_A;
  6005.         b  = r / BLOCK_B;
  6006.         r -= b * BLOCK_B;
  6007.         c  = r / BLOCK_C;
  6008.         r -= c * BLOCK_C;
  6009.         d  = r;
  6010.  
  6011.         m = pp_hi24 [a];
  6012.         n = pp_lo48 [a];
  6013.  
  6014.         pw[0] = (SQUARE) b;
  6015.         pw[1] = pidx24_to_wsq (m);
  6016.         pw[2] = pidx48_to_wsq (n);
  6017.         pw[3] = NOSQUARE;
  6018.  
  6019.         pb[0] = (SQUARE) c;
  6020.         pb[1] = (SQUARE) d;
  6021.         pb[2] = NOSQUARE;
  6022.  
  6023.  
  6024.         assert (A2 <= pw[1] && pw[1] < A8);
  6025.         assert (A2 <= pw[2] && pw[2] < A8);
  6026.         assert (kppka_pctoindex (pw, pb, &a) && a == i);
  6027.  
  6028.         return;
  6029. }
  6030.  
  6031.  
  6032. static bool_t
  6033. kppka_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  6034. {
  6035.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  6036.         index_t pp_slice;
  6037.         index_t i, j;
  6038.  
  6039.         SQUARE anchor, loosen;
  6040.  
  6041.         SQUARE wk     = pw[0];
  6042.         SQUARE pawn_a = pw[1];
  6043.         SQUARE pawn_b = pw[2];
  6044.         SQUARE bk     = pb[0];
  6045.         SQUARE ba         = pb[1];
  6046.  
  6047.  
  6048.         assert (A2 <= pawn_a && pawn_a < A8);
  6049.         assert (A2 <= pawn_b && pawn_b < A8);
  6050.  
  6051.         pp_putanchorfirst (pawn_a, pawn_b, &anchor, &loosen);
  6052.  
  6053.         if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  6054.                 anchor = flipWE (anchor);
  6055.                 loosen = flipWE (loosen);
  6056.                 wk     = flipWE (wk);
  6057.                 bk     = flipWE (bk);
  6058.                 ba         = flipWE (ba);
  6059.         }
  6060.  
  6061.         i = wsq_to_pidx24 (anchor);
  6062.         j = wsq_to_pidx48 (loosen);
  6063.  
  6064.         pp_slice = ppidx [i] [j];
  6065.  
  6066.         if (IDX_is_empty(pp_slice)) {
  6067.                 *out = NOINDEX;
  6068.                 return FALSE;
  6069.         }
  6070.  
  6071.         assert (pp_slice < MAX_PPINDEX );
  6072.  
  6073.         *out = pp_slice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B  + (index_t)bk * (index_t)BLOCK_C + (index_t)ba;
  6074.  
  6075.         return TRUE;
  6076. }
  6077.  
  6078. /********************** end KPP/KA ************************************/
  6079.  
  6080. /**********************  KAPP/K ************************************/
  6081.  
  6082. static bool_t   test_kappk (void);
  6083. static bool_t   kappk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  6084. static void             kappk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  6085.  
  6086. static bool_t
  6087. test_kappk (void)
  6088. {
  6089.  
  6090.         enum            {MAXPC = 16+1};
  6091.         char            str[] = "kappk";
  6092.         SQUARE          a, b, c, d, e;
  6093.         SQUARE          pw[MAXPC], pb[MAXPC];
  6094.         SQUARE          px[MAXPC], py[MAXPC];
  6095.  
  6096.         index_t         i, j;
  6097.         bool_t          err = FALSE;
  6098.  
  6099.         printf ("%8s ", str);
  6100.  
  6101.         for (a = 0; a < 64; a++) {
  6102.                 for (b = 0; b < 64; b++) {
  6103.                 for (c = 0; c < 64; c++) {
  6104.                 for (d = 0; d < 64; d++) {
  6105.                 for (e = 0; e < 64; e++) {
  6106.  
  6107.                         if (c <= H1 || c >= A8)
  6108.                                 continue;
  6109.                         if (b <= H1 || b >= A8)
  6110.                                 continue;
  6111.  
  6112.  
  6113.                         pw[0] = a;
  6114.                         pw[1] = d;
  6115.                         pw[2] = b;
  6116.                         pw[3] = c;
  6117.                         pw[4] = NOSQUARE;
  6118.  
  6119.                         pb[0] = e;
  6120.                         pb[1] = NOSQUARE;
  6121.  
  6122.                         if (kappk_pctoindex (pw, pb, &i)) {
  6123.                                                         kappk_indextopc (i, px, py);
  6124.                                                         kappk_pctoindex (px, py, &j);
  6125.                                                         if (i != j) {
  6126.                                                                 err = TRUE;
  6127.                                                         }
  6128.                                                         assert (i == j);
  6129.                         }
  6130.  
  6131.                 }
  6132.                 }
  6133.                 }
  6134.                 }
  6135.  
  6136.         if ((a&1)==0) {
  6137.             printf(".");
  6138.             fflush(stdout);
  6139.         }
  6140.         }
  6141.  
  6142.         if (err)
  6143.                 printf ("> %s NOT passed\n", str);
  6144.         else
  6145.                 printf ("> %s PASSED\n", str);
  6146.         return !err;
  6147. }
  6148.  
  6149.  
  6150. static void
  6151. kappk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  6152. {
  6153.         /*---------------------------------------------------------*
  6154.                 inverse work to make sure that the following is valid
  6155.                 index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d;
  6156.         *----------------------------------------------------------*/
  6157.  
  6158.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  6159.         index_t a, b, c, d, r;
  6160.         index_t m, n;
  6161.  
  6162.         r = i;
  6163.         a  = r / BLOCK_A;
  6164.         r -= a * BLOCK_A;
  6165.         b  = r / BLOCK_B;
  6166.         r -= b * BLOCK_B;
  6167.         c  = r / BLOCK_C;
  6168.         r -= c * BLOCK_C;
  6169.         d  = r;
  6170.  
  6171.         m = pp_hi24 [a];
  6172.         n = pp_lo48 [a];
  6173.  
  6174.         pw[0] = (SQUARE) b;
  6175.         pw[1] = (SQUARE) d;
  6176.         pw[2] = pidx24_to_wsq (m);
  6177.         pw[3] = pidx48_to_wsq (n);
  6178.         pw[4] = NOSQUARE;
  6179.  
  6180.         pb[0] = (SQUARE) c;
  6181.         pb[1] = NOSQUARE;
  6182.  
  6183.  
  6184.         assert (A2 <= pw[3] && pw[3] < A8);
  6185.         assert (A2 <= pw[2] && pw[2] < A8);
  6186.         assert (kappk_pctoindex (pw, pb, &a) && a == i);
  6187.  
  6188.         return;
  6189. }
  6190.  
  6191.  
  6192. static bool_t
  6193. kappk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  6194. {
  6195.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  6196.         index_t pp_slice;
  6197.         SQUARE anchor, loosen;
  6198.  
  6199.         SQUARE wk     = pw[0];
  6200.         SQUARE wa         = pw[1];
  6201.         SQUARE pawn_a = pw[2];
  6202.         SQUARE pawn_b = pw[3];
  6203.         SQUARE bk     = pb[0];
  6204.  
  6205.         index_t i, j;
  6206.  
  6207.         assert (A2 <= pawn_a && pawn_a < A8);
  6208.         assert (A2 <= pawn_b && pawn_b < A8);
  6209.  
  6210.         pp_putanchorfirst (pawn_a, pawn_b, &anchor, &loosen);
  6211.  
  6212.         if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  6213.                 anchor = flipWE (anchor);
  6214.                 loosen = flipWE (loosen);
  6215.                 wk     = flipWE (wk);
  6216.                 bk     = flipWE (bk);
  6217.                 wa         = flipWE (wa);
  6218.         }
  6219.  
  6220.         i = wsq_to_pidx24 (anchor);
  6221.         j = wsq_to_pidx48 (loosen);
  6222.  
  6223.         pp_slice = ppidx [i] [j];
  6224.  
  6225.         if (IDX_is_empty(pp_slice)) {
  6226.                 *out = NOINDEX;
  6227.                 return FALSE;
  6228.         }
  6229.  
  6230.         assert (pp_slice < MAX_PPINDEX );
  6231.  
  6232.         *out = pp_slice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B  + (index_t)bk * (index_t)BLOCK_C + (index_t)wa;
  6233.  
  6234.         return TRUE;
  6235. }
  6236.  
  6237. /********************** end KAPP/K ************************************/
  6238.  
  6239. /**********************  KAPP/K ************************************/
  6240.  
  6241. static bool_t   test_kapkp (void);
  6242. static bool_t   kapkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  6243. static void             kapkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  6244.  
  6245. static bool_t
  6246. test_kapkp (void)
  6247. {
  6248.  
  6249.         enum            {MAXPC = 16+1};
  6250.         char            str[] = "kapkp";
  6251.         SQUARE          a, b, c, d, e;
  6252.         SQUARE          pw[MAXPC], pb[MAXPC];
  6253.         SQUARE          px[MAXPC], py[MAXPC];
  6254.  
  6255.         index_t         i, j;
  6256.         bool_t          err = FALSE;
  6257.  
  6258.         printf ("%8s ", str);
  6259.  
  6260.         for (a = 0; a < 64; a++) {
  6261.                 for (b = 0; b < 64; b++) {
  6262.                 for (c = 0; c < 64; c++) {
  6263.                 for (d = 0; d < 64; d++) {
  6264.                 for (e = 0; e < 64; e++) {
  6265.  
  6266.                         if (c <= H1 || c >= A8)
  6267.                                 continue;
  6268.                         if (b <= H1 || b >= A8)
  6269.                                 continue;
  6270.  
  6271.  
  6272.                         pw[0] = a;
  6273.                         pw[1] = d;
  6274.                         pw[2] = b;
  6275.                         pw[3] = NOSQUARE;
  6276.  
  6277.                         pb[0] = e;
  6278.                         pb[1] = c;
  6279.                         pb[2] = NOSQUARE;
  6280.  
  6281.                         if (kapkp_pctoindex (pw, pb, &i)) {
  6282.                                                         kapkp_indextopc (i, px, py);
  6283.                                                         kapkp_pctoindex (px, py, &j);
  6284.                                                         if (i != j) {
  6285.                                                                 err = TRUE;
  6286.                                                         }
  6287.                                                         assert (i == j);
  6288.                         }
  6289.  
  6290.                 }
  6291.                 }
  6292.                 }
  6293.                 }
  6294.  
  6295.         if ((a&1)==0) {
  6296.             printf(".");
  6297.             fflush(stdout);
  6298.         }
  6299.         }
  6300.  
  6301.         if (err)
  6302.                 printf ("> %s NOT passed\n", str);
  6303.         else
  6304.                 printf ("> %s PASSED\n", str);
  6305.         return !err;
  6306. }
  6307.  
  6308.  
  6309. static bool_t
  6310. kapkp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  6311. {
  6312.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  6313.         index_t pp_slice;
  6314.         SQUARE anchor, loosen;
  6315.  
  6316.         SQUARE wk     = pw[0];
  6317.         SQUARE wa         = pw[1];
  6318.         SQUARE pawn_a = pw[2];
  6319.         SQUARE bk     = pb[0];
  6320.         SQUARE pawn_b = pb[1];
  6321.         index_t m, n;
  6322.  
  6323.         assert (A2 <= pawn_a && pawn_a < A8);
  6324.         assert (A2 <= pawn_b && pawn_b < A8);
  6325.         assert (pw[3] == NOSQUARE && pb[2] == NOSQUARE);
  6326.  
  6327.         anchor = pawn_a;
  6328.         loosen = pawn_b;
  6329.  
  6330.         if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  6331.                 anchor = flipWE (anchor);
  6332.                 loosen = flipWE (loosen);
  6333.                 wk     = flipWE (wk);
  6334.                 bk     = flipWE (bk);
  6335.                 wa         = flipWE (wa);
  6336.         }
  6337.  
  6338.         m = wsq_to_pidx24 (anchor);
  6339.         n = (index_t)loosen - 8;
  6340.  
  6341.         pp_slice = m * 48 + n;
  6342.  
  6343.         if (IDX_is_empty(pp_slice)) {
  6344.                 *out = NOINDEX;
  6345.                 return FALSE;
  6346.         }
  6347.  
  6348.         assert (pp_slice < (64*MAX_PpINDEX) );
  6349.  
  6350.         *out = pp_slice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B  + (index_t)bk * (index_t)BLOCK_C + (index_t)wa;
  6351.  
  6352.         return TRUE;
  6353. }
  6354.  
  6355. static void
  6356. kapkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  6357. {
  6358.         /*---------------------------------------------------------*
  6359.                 inverse work to make sure that the following is valid
  6360.                 index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d;
  6361.         *----------------------------------------------------------*/
  6362.         enum  {BLOCK_A = 64*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  6363.         enum  {block_m = 48};
  6364.         index_t a, b, c, d, r;
  6365.         index_t m, n;
  6366.         SQUARE sq_m, sq_n;
  6367.  
  6368.         r = i;
  6369.         a  = r / BLOCK_A;
  6370.         r -= a * BLOCK_A;
  6371.         b  = r / BLOCK_B;
  6372.         r -= b * BLOCK_B;
  6373.         c  = r / BLOCK_C;
  6374.         r -= c * BLOCK_C;
  6375.         d  = r;
  6376.  
  6377.         /* unpack a, which is pslice, into m and n */
  6378.         r = a;
  6379.         m  = r / block_m;
  6380.         r -= m * block_m;
  6381.         n  = r ;
  6382.  
  6383.         sq_m = pidx24_to_wsq (m);
  6384.         sq_n = (SQUARE) n + 8;
  6385.  
  6386.         pw[0] = (SQUARE) b;
  6387.         pb[0] = (SQUARE) c;
  6388.         pw[1] = (SQUARE) d;
  6389.         pw[2] = sq_m;
  6390.         pb[1] = sq_n;
  6391.         pw[3] = NOSQUARE;
  6392.         pb[2] = NOSQUARE;
  6393.  
  6394.         assert (A2 <= sq_m && sq_m < A8);
  6395.         assert (A2 <= sq_n && sq_n < A8);
  6396.         assert (kapkp_pctoindex (pw, pb, &a) && a == i);
  6397.  
  6398.         return;
  6399. }
  6400.  
  6401. /********************** end KAP/KP ************************************/
  6402.  
  6403. /**********************  KABP/K ************************************/
  6404.  
  6405. static bool_t   test_kabpk (void);
  6406. static bool_t   kabpk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  6407. static void             kabpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  6408.  
  6409. static bool_t
  6410. test_kabpk (void)
  6411. {
  6412.  
  6413.         enum            {MAXPC = 16+1};
  6414.         char            str[] = "kabpk";
  6415.         SQUARE          a, b, c, d, e;
  6416.         SQUARE          pw[MAXPC], pb[MAXPC];
  6417.         SQUARE          px[MAXPC], py[MAXPC];
  6418.  
  6419.         index_t         i, j;
  6420.         bool_t          err = FALSE;
  6421.  
  6422.         printf ("%8s ", str);
  6423.  
  6424.         for (a = 0; a < 64; a++) {
  6425.                 for (b = 0; b < 64; b++) {
  6426.                 for (c = 0; c < 64; c++) {
  6427.                 for (d = 0; d < 64; d++) {
  6428.                 for (e = 0; e < 64; e++) {
  6429.  
  6430.                         if (d <= H1 || d >= A8)
  6431.                                 continue;
  6432.  
  6433.                         pw[0] = a;
  6434.                         pw[1] = b;
  6435.                         pw[2] = c;
  6436.                         pw[3] = d;
  6437.                         pw[4] = NOSQUARE;
  6438.  
  6439.                         pb[0] = e;
  6440.                         pb[1] = NOSQUARE;
  6441.  
  6442.                         if (kabpk_pctoindex (pw, pb, &i)) {
  6443.                                                         kabpk_indextopc (i, px, py);
  6444.                                                         kabpk_pctoindex (px, py, &j);
  6445.                                                         if (i != j) {
  6446.                                                                 err = TRUE;
  6447.                                                         }
  6448.                                                         assert (i == j);
  6449.                         }
  6450.  
  6451.                 }
  6452.                 }
  6453.                 }
  6454.                 }
  6455.  
  6456.         if ((a&1)==0) {
  6457.             printf(".");
  6458.             fflush(stdout);
  6459.         }
  6460.         }
  6461.  
  6462.         if (err)
  6463.                 printf ("> %s NOT passed\n", str);
  6464.         else
  6465.                 printf ("> %s PASSED\n", str);
  6466.         return !err;
  6467. }
  6468.  
  6469.  
  6470. static void
  6471. kabpk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  6472. {
  6473.  
  6474.         /*---------------------------------------------------------*
  6475.                 inverse work to make sure that the following is valid
  6476.                 index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d * BLOCK_D + e;
  6477.         *----------------------------------------------------------*/
  6478.         enum  {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64};
  6479.         index_t a, b, c, d, e, r;
  6480.         SQUARE x;
  6481.  
  6482.         r = i;
  6483.         a  = r / BLOCK_A;
  6484.         r -= a * BLOCK_A;
  6485.         b  = r / BLOCK_B;
  6486.         r -= b * BLOCK_B;
  6487.         c  = r / BLOCK_C;
  6488.         r -= c * BLOCK_C;
  6489.         d  = r / BLOCK_D;
  6490.         r -= d * BLOCK_D;
  6491.         e  = r;
  6492.  
  6493.         x = pidx24_to_wsq(a);
  6494.  
  6495.         pw[0] = (SQUARE) b;
  6496.         pw[1] = (SQUARE) d;
  6497.         pw[2] = (SQUARE) e;
  6498.         pw[3] = x;
  6499.         pw[4] = NOSQUARE;
  6500.  
  6501.         pb[0] = (SQUARE) c;
  6502.         pb[1] = NOSQUARE;
  6503.  
  6504.         assert (kabpk_pctoindex (pw, pb, &a) && a == i);
  6505.  
  6506.         return;
  6507. }
  6508.  
  6509.  
  6510. static bool_t
  6511. kabpk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  6512. {
  6513.         enum  {BLOCK_A = 64*64*64*64, BLOCK_B = 64*64*64, BLOCK_C = 64*64, BLOCK_D = 64};
  6514.         index_t pslice;
  6515.  
  6516.         SQUARE wk   = pw[0];
  6517.         SQUARE wa   = pw[1];
  6518.         SQUARE wb   = pw[2];
  6519.         SQUARE pawn = pw[3];
  6520.         SQUARE bk   = pb[0];
  6521.  
  6522.         assert (A2 <= pawn && pawn < A8);
  6523.  
  6524.         if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  6525.                 pawn = flipWE (pawn);
  6526.                 wk   = flipWE (wk);
  6527.                 bk   = flipWE (bk);
  6528.                 wa   = flipWE (wa);
  6529.                 wb   = flipWE (wb);
  6530.         }
  6531.  
  6532.         pslice = wsq_to_pidx24 (pawn);
  6533.  
  6534.         *out = pslice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B  + (index_t)bk * (index_t)BLOCK_C + (index_t)wa * (index_t)BLOCK_D + (index_t)wb;
  6535.  
  6536.         return TRUE;
  6537. }
  6538.  
  6539. /********************** end KABP/K ************************************/
  6540.  
  6541. /**********************  KAAP/K ************************************/
  6542.  
  6543. static bool_t   test_kaapk (void);
  6544. static bool_t   kaapk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  6545. static void             kaapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  6546.  
  6547. static bool_t
  6548. test_kaapk (void)
  6549. {
  6550.  
  6551.         enum            {MAXPC = 16+1};
  6552.         char            str[] = "kaapk";
  6553.         SQUARE          a, b, c, d, e;
  6554.         SQUARE          pw[MAXPC], pb[MAXPC];
  6555.         SQUARE          px[MAXPC], py[MAXPC];
  6556.  
  6557.         index_t         i, j;
  6558.         bool_t          err = FALSE;
  6559.  
  6560.         printf ("%8s ", str);
  6561.  
  6562.         for (a = 0; a < 64; a++) {
  6563.                 for (b = 0; b < 64; b++) {
  6564.                 for (c = 0; c < 64; c++) {
  6565.                 for (d = 0; d < 64; d++) {
  6566.                 for (e = 0; e < 64; e++) {
  6567.  
  6568.                         if (d <= H1 || d >= A8)
  6569.                                 continue;
  6570.  
  6571.                         pw[0] = a;
  6572.                         pw[1] = b;
  6573.                         pw[2] = c;
  6574.                         pw[3] = d;
  6575.                         pw[4] = NOSQUARE;
  6576.  
  6577.                         pb[0] = e;
  6578.                         pb[1] = NOSQUARE;
  6579.  
  6580.                         if (kaapk_pctoindex (pw, pb, &i)) {
  6581.                                                         kaapk_indextopc (i, px, py);
  6582.                                                         kaapk_pctoindex (px, py, &j);
  6583.                                                         if (i != j) {
  6584.                                                                 err = TRUE;
  6585.                                                         }
  6586.                                                         assert (i == j);
  6587.                         }
  6588.  
  6589.                 }
  6590.                 }
  6591.                 }
  6592.                 }
  6593.  
  6594.         if ((a&1)==0) {
  6595.             printf(".");
  6596.             fflush(stdout);
  6597.         }
  6598.         }
  6599.  
  6600.         if (err)
  6601.                 printf ("> %s NOT passed\n", str);
  6602.         else
  6603.                 printf ("> %s PASSED\n", str);
  6604.         return !err;
  6605. }
  6606.  
  6607.  
  6608. static void
  6609. kaapk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  6610. {
  6611.         /*---------------------------------------------------------*
  6612.                 inverse work to make sure that the following is valid
  6613.                 index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d;
  6614.         *----------------------------------------------------------*/
  6615.         enum    {BLOCK_C = MAX_AAINDEX
  6616.                         ,BLOCK_B = 64*BLOCK_C
  6617.                         ,BLOCK_A = 64*BLOCK_B
  6618.         };
  6619.         index_t a, b, c, d, r;
  6620.         index_t x, y, z;
  6621.  
  6622.         assert (i >= 0);
  6623.  
  6624.         r = i;
  6625.         a  = r / BLOCK_A;
  6626.         r -= a * BLOCK_A;
  6627.         b  = r / BLOCK_B;
  6628.         r -= b * BLOCK_B;
  6629.         c  = r / BLOCK_C;
  6630.         r -= c * BLOCK_C;
  6631.         d  = r;
  6632.  
  6633.         z = (index_t) pidx24_to_wsq(a);
  6634.  
  6635.         /* split d into x, y*/
  6636.         x = aabase [d];
  6637.         y = (d + 1) + x - (x * (127-x)/2);
  6638.  
  6639.         assert (aaidx[x][y] == aaidx[y][x]);
  6640.         assert (aaidx[x][y] == d);
  6641.  
  6642.  
  6643.         pw[0] = (SQUARE) b;
  6644.         pw[1] = (SQUARE) x;
  6645.         pw[2] = (SQUARE) y;
  6646.         pw[3] = (SQUARE) z;
  6647.         pw[4] = NOSQUARE;
  6648.  
  6649.         pb[0] = (SQUARE) c;
  6650.         pb[1] = NOSQUARE;
  6651.  
  6652.         assert (kaapk_pctoindex (pw, pb, &a) && a == i);
  6653.  
  6654.         return;
  6655. }
  6656.  
  6657.  
  6658. static bool_t
  6659. kaapk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  6660. {
  6661.         enum    {BLOCK_C = MAX_AAINDEX
  6662.                         ,BLOCK_B = 64*BLOCK_C
  6663.                         ,BLOCK_A = 64*BLOCK_B
  6664.         };
  6665.         index_t aa_combo, pslice;
  6666.  
  6667.         SQUARE wk   = pw[0];
  6668.         SQUARE wa   = pw[1];
  6669.         SQUARE wa2  = pw[2];
  6670.         SQUARE pawn = pw[3];
  6671.         SQUARE bk   = pb[0];
  6672.  
  6673.         assert (A2 <= pawn && pawn < A8);
  6674.  
  6675.         if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  6676.                 pawn = flipWE (pawn);
  6677.                 wk   = flipWE (wk);
  6678.                 bk   = flipWE (bk);
  6679.                 wa   = flipWE (wa);
  6680.                 wa2  = flipWE (wa2);
  6681.         }
  6682.  
  6683.         pslice = wsq_to_pidx24 (pawn);
  6684.  
  6685.         aa_combo = (index_t) aaidx [wa] [wa2];
  6686.  
  6687.         if (IDX_is_empty(aa_combo)) {
  6688.                 *out = NOINDEX;
  6689.                 return FALSE;
  6690.         }
  6691.  
  6692.         *out = pslice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B  + (index_t)bk * (index_t)BLOCK_C + aa_combo;
  6693.  
  6694.         assert (*out >= 0);
  6695.  
  6696.         return TRUE;
  6697. }
  6698.  
  6699. /********************** end KAAP/K ************************************/
  6700.  
  6701. /**********************  KAA/KP ************************************/
  6702.  
  6703. static bool_t   test_kaakp (void);
  6704. static bool_t   kaakp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  6705. static void             kaakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  6706.  
  6707. static bool_t
  6708. test_kaakp (void)
  6709. {
  6710.  
  6711.         enum            {MAXPC = 16+1};
  6712.         char            str[] = "kaakp";
  6713.         SQUARE          a, b, c, d, e;
  6714.         SQUARE          pw[MAXPC], pb[MAXPC];
  6715.         SQUARE          px[MAXPC], py[MAXPC];
  6716.  
  6717.         index_t         i, j;
  6718.         bool_t          err = FALSE;
  6719.  
  6720.         printf ("%8s ", str);
  6721.  
  6722.         for (a = 0; a < 64; a++) {
  6723.                 for (b = 0; b < 64; b++) {
  6724.                 for (c = 0; c < 64; c++) {
  6725.                 for (d = 0; d < 64; d++) {
  6726.                 for (e = 0; e < 64; e++) {
  6727.  
  6728.                         if (d <= H1 || d >= A8)
  6729.                                 continue;
  6730.  
  6731.                         pw[0] = a;
  6732.                         pw[1] = b;
  6733.                         pw[2] = c;
  6734.                         pw[3] = NOSQUARE;
  6735.  
  6736.                         pb[0] = e;
  6737.                         pb[1] = d;
  6738.                         pb[2] = NOSQUARE;
  6739.  
  6740.                         if (kaakp_pctoindex (pw, pb, &i)) {
  6741.                                                         kaakp_indextopc (i, px, py);
  6742.                                                         kaakp_pctoindex (px, py, &j);
  6743.                                                         if (i != j) {
  6744.                                                                 err = TRUE;
  6745.                                                         }
  6746.                                                         assert (i == j);
  6747.                         }
  6748.  
  6749.                 }
  6750.                 }
  6751.                 }
  6752.                 }
  6753.  
  6754.         if ((a&1)==0) {
  6755.             printf(".");
  6756.             fflush(stdout);
  6757.         }
  6758.         }
  6759.  
  6760.         if (err)
  6761.                 printf ("> %s NOT passed\n", str);
  6762.         else
  6763.                 printf ("> %s PASSED\n", str);
  6764.         return !err;
  6765. }
  6766.  
  6767.  
  6768. static void
  6769. kaakp_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  6770. {
  6771.         /*---------------------------------------------------------*
  6772.                 inverse work to make sure that the following is valid
  6773.                 index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d;
  6774.         *----------------------------------------------------------*/
  6775.         enum    {BLOCK_C = MAX_AAINDEX
  6776.                         ,BLOCK_B = 64*BLOCK_C
  6777.                         ,BLOCK_A = 64*BLOCK_B
  6778.         };
  6779.         index_t a, b, c, d, r;
  6780.         index_t x, y, z;
  6781.         SQUARE zq;
  6782.  
  6783.         assert (i >= 0);
  6784.  
  6785.         r = i;
  6786.         a  = r / BLOCK_A;
  6787.         r -= a * BLOCK_A;
  6788.         b  = r / BLOCK_B;
  6789.         r -= b * BLOCK_B;
  6790.         c  = r / BLOCK_C;
  6791.         r -= c * BLOCK_C;
  6792.         d  = r;
  6793.  
  6794.         zq = pidx24_to_wsq(a);
  6795.         z  = (index_t)flipNS(zq);
  6796.  
  6797.  
  6798.         /* split d into x, y*/
  6799.         x = aabase [d];
  6800.         y = (d + 1) + x - (x * (127-x)/2);
  6801.  
  6802.         assert (aaidx[x][y] == aaidx[y][x]);
  6803.         assert (aaidx[x][y] == d);
  6804.  
  6805.  
  6806.         pw[0] = (SQUARE)b;
  6807.         pw[1] = (SQUARE)x;
  6808.         pw[2] = (SQUARE)y;
  6809.         pw[3] = NOSQUARE;
  6810.  
  6811.         pb[0] = (SQUARE)c;
  6812.         pb[1] = (SQUARE)z;
  6813.         pb[2] = NOSQUARE;
  6814.  
  6815.         assert (kaakp_pctoindex (pw, pb, &a) && a == i);
  6816.  
  6817.         return;
  6818. }
  6819.  
  6820.  
  6821. static bool_t
  6822. kaakp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  6823. {
  6824.         enum    {BLOCK_C = MAX_AAINDEX
  6825.                         ,BLOCK_B = 64*BLOCK_C
  6826.                         ,BLOCK_A = 64*BLOCK_B
  6827.         };
  6828.         index_t aa_combo, pslice;
  6829.  
  6830.         SQUARE wk   = pw[0];
  6831.         SQUARE wa   = pw[1];
  6832.         SQUARE wa2  = pw[2];
  6833.         SQUARE bk   = pb[0];
  6834.         SQUARE pawn = pb[1];
  6835.  
  6836.         assert (A2 <= pawn && pawn < A8);
  6837.  
  6838.         if ((pawn & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  6839.                 pawn = flipWE (pawn);
  6840.                 wk   = flipWE (wk);
  6841.                 bk   = flipWE (bk);
  6842.                 wa   = flipWE (wa);
  6843.                 wa2  = flipWE (wa2);
  6844.         }
  6845.  
  6846.         pawn = flipNS(pawn);
  6847.         pslice = wsq_to_pidx24 (pawn);
  6848.  
  6849.         aa_combo = (index_t)aaidx [wa] [wa2];
  6850.  
  6851.         if (IDX_is_empty(aa_combo)) {
  6852.                 *out = NOINDEX;
  6853.                 return FALSE;
  6854.         }
  6855.  
  6856.         *out = pslice * (index_t)BLOCK_A + (index_t)wk * (index_t)BLOCK_B  + (index_t)bk * (index_t)BLOCK_C + aa_combo;
  6857.  
  6858.         assert (*out >= 0);
  6859.  
  6860.         return TRUE;
  6861. }
  6862.  
  6863. /********************** end KAA/KP ************************************/
  6864.  
  6865. /**********************  KPP/KP ************************************/
  6866. /*
  6867. index_t         pp48_idx[48][48];
  6868. sq_t            pp48_sq_x[MAX_PP48_INDEX];
  6869. sq_t            pp48_sq_y[MAX_PP48_INDEX];
  6870. */
  6871. static bool_t   test_kppkp (void);
  6872. static bool_t   kppkp_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  6873. static void             kppkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  6874.  
  6875. static sq_t map24_b   (sq_t s);
  6876. static sq_t unmap24_b (index_t i);
  6877.  
  6878. static index_t
  6879. init_pp48_idx (void)
  6880. /* modifies pp48_idx[][], pp48_sq_x[], pp48_sq_y[] */
  6881. {
  6882.         enum  {MAX_I = 48, MAX_J = 48};
  6883.         SQUARE i, j;
  6884.         index_t idx = 0;
  6885.         SQUARE a, b;
  6886.  
  6887.         /* default is noindex */
  6888.         for (i = 0; i < MAX_I; i++) {
  6889.                 for (j = 0; j < MAX_J; j++) {
  6890.                         IDX_set_empty (pp48_idx [i][j]);
  6891.                 }
  6892.         }
  6893.  
  6894.         for (idx = 0; idx < MAX_PP48_INDEX; idx++) {
  6895.                 pp48_sq_x [idx] = NOSQUARE;
  6896.                 pp48_sq_y [idx] = NOSQUARE;
  6897.         }
  6898.  
  6899.         idx = 0;
  6900.         for (a = H7; a >= A2; a--) {
  6901.  
  6902.                 for (b = a - 1; b >= A2; b--) {
  6903.  
  6904.                         i = flipWE( flipNS (a) ) - 8;
  6905.                         j = flipWE( flipNS (b) ) - 8;
  6906.  
  6907.                         if (IDX_is_empty(pp48_idx [i] [j])) {
  6908.  
  6909.                                 pp48_idx  [i][j]= idx;  assert (idx < MAX_PP48_INDEX);
  6910.                                 pp48_idx  [j][i]= idx;
  6911.                                 pp48_sq_x [idx] = i;    assert (i < MAX_I);
  6912.                                 pp48_sq_y [idx] = j;    assert (j < MAX_J);
  6913.                                 idx++;
  6914.                         }
  6915.                 }
  6916.         }
  6917.         assert (idx == MAX_PP48_INDEX);
  6918.         return idx;
  6919. }
  6920.  
  6921.  
  6922.  
  6923. static bool_t
  6924. test_kppkp (void)
  6925. {
  6926.  
  6927.         enum            {MAXPC = 16+1};
  6928.         char            str[] = "kppkp";
  6929.         SQUARE          a, b, c, d, e;
  6930.         SQUARE          pw[MAXPC], pb[MAXPC];
  6931.         SQUARE          px[MAXPC], py[MAXPC];
  6932.  
  6933.         index_t         i, j;
  6934.         bool_t          err = FALSE;
  6935.  
  6936.         printf ("%8s ", str);
  6937.  
  6938.         for (a = 0; a < 64; a++) {
  6939.                 for (b = 0; b < 64; b++) {
  6940.                 for (c = 0; c < 64; c++) {
  6941.                 for (d = 0; d < 64; d++) {
  6942.                 for (e = 0; e < 64; e++) {
  6943.  
  6944.                         if (c <= H1 || c >= A8)
  6945.                                 continue;
  6946.                         if (b <= H1 || b >= A8)
  6947.                                 continue;
  6948.                         if (d <= H1 || d >= A8)
  6949.                                 continue;
  6950.  
  6951.                         pw[0] = a;
  6952.                         pw[1] = b;
  6953.                         pw[2] = c;
  6954.                         pw[3] = NOSQUARE;
  6955.  
  6956.                         pb[0] = e;
  6957.                         pb[1] = d;
  6958.                         pb[2] = NOSQUARE;
  6959.  
  6960.                         if (kppkp_pctoindex (pw, pb, &i)) {
  6961.                                                         kppkp_indextopc (i, px, py);
  6962.                                                         kppkp_pctoindex (px, py, &j);
  6963.                                                         if (i != j) {
  6964.                                                                 err = TRUE;
  6965.                                                         }
  6966.                                                         assert (i == j);
  6967.                         }
  6968.  
  6969.                 }
  6970.                 }
  6971.                 }
  6972.                 }
  6973.  
  6974.         if ((a&1)==0) {
  6975.             printf(".");
  6976.             fflush(stdout);
  6977.         }
  6978.         }
  6979.  
  6980.         if (err)
  6981.                 printf ("> %s NOT passed\n", str);
  6982.         else
  6983.                 printf ("> %s PASSED\n", str);
  6984.         return !err;
  6985. }
  6986.  
  6987.  
  6988. static void
  6989. kppkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  6990. {
  6991.         /*---------------------------------------------------------*
  6992.                 inverse work to make sure that the following is valid
  6993.                 index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d;
  6994.         *----------------------------------------------------------*/
  6995.  
  6996.         enum  {BLOCK_A = MAX_PP48_INDEX*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  6997.         index_t a, b, c, d, r;
  6998.         SQUARE m, n;
  6999.  
  7000.         r = i;
  7001.         a  = r / BLOCK_A;
  7002.         r -= a * BLOCK_A;
  7003.         b  = r / BLOCK_B;
  7004.         r -= b * BLOCK_B;
  7005.         c  = r / BLOCK_C;
  7006.         r -= c * BLOCK_C;
  7007.         d  = r;
  7008.  
  7009.         m = pp48_sq_x [b];
  7010.         n = pp48_sq_y [b];
  7011.  
  7012.         pw[0] = (SQUARE)c;
  7013.         pw[1] = flipWE(flipNS(m+8));
  7014.         pw[2] = flipWE(flipNS(n+8));
  7015.         pw[3] = NOSQUARE;
  7016.  
  7017.         pb[0] = (SQUARE)d;
  7018.         pb[1] = (SQUARE)unmap24_b (a);
  7019.         pb[2] = NOSQUARE;
  7020.  
  7021.  
  7022.         assert (A2 <= pw[1] && pw[1] < A8);
  7023.         assert (A2 <= pw[2] && pw[2] < A8);
  7024.         assert (A2 <= pb[1] && pb[1] < A8);
  7025.         assert (kppkp_pctoindex (pw, pb, &a) && a == i);
  7026.  
  7027.         return;
  7028. }
  7029.  
  7030.  
  7031. static bool_t
  7032. kppkp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  7033. {
  7034.         enum  {BLOCK_A = MAX_PP48_INDEX*64*64, BLOCK_B = 64*64, BLOCK_C = 64};
  7035.         index_t pp48_slice;
  7036.  
  7037.         SQUARE wk     = pw[0];
  7038.         SQUARE pawn_a = pw[1];
  7039.         SQUARE pawn_b = pw[2];
  7040.         SQUARE bk     = pb[0];
  7041.         SQUARE pawn_c = pb[1];
  7042.         SQUARE i, j, k;
  7043.  
  7044.         assert (A2 <= pawn_a && pawn_a < A8);
  7045.         assert (A2 <= pawn_b && pawn_b < A8);
  7046.         assert (A2 <= pawn_c && pawn_c < A8);
  7047.  
  7048.         if ((pawn_c & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  7049.                 wk     = flipWE (wk);
  7050.                 pawn_a = flipWE (pawn_a);
  7051.                 pawn_b = flipWE (pawn_b);
  7052.                 bk     = flipWE (bk);
  7053.                 pawn_c = flipWE (pawn_c);
  7054.         }
  7055.  
  7056.         i = flipWE( flipNS (pawn_a) ) - 8;
  7057.         j = flipWE( flipNS (pawn_b) ) - 8;
  7058.         k = map24_b (pawn_c); /* black pawn, so low indexes mean more advanced 0 == A2 */
  7059.  
  7060.         pp48_slice = pp48_idx [i] [j];
  7061.  
  7062.         if (IDX_is_empty(pp48_slice)) {
  7063.                 *out = NOINDEX;
  7064.                 return FALSE;
  7065.         }
  7066.  
  7067.         assert (pp48_slice < MAX_PP48_INDEX );
  7068.  
  7069.         *out = (index_t)k * (index_t)BLOCK_A + pp48_slice * (index_t)BLOCK_B + (index_t)wk * (index_t)BLOCK_C  + (index_t)bk;
  7070.  
  7071.         return TRUE;
  7072. }
  7073.  
  7074. static sq_t
  7075. map24_b (sq_t s)
  7076. {
  7077.         s -= 8;
  7078.         return ((s&3)+s)>>1;
  7079. }
  7080.  
  7081. static sq_t
  7082. unmap24_b (index_t i)
  7083. {
  7084.         return (sq_t) ((i&(4+8+16)) + i + 8);
  7085. }
  7086.  
  7087. /********************** end KPP/KP ************************************/
  7088.  
  7089. /**********************  KPPP/K ************************************/
  7090.  
  7091. static const sq_t itosq[48] = {
  7092.         H7,G7,F7,E7,
  7093.         H6,G6,F6,E6,
  7094.         H5,G5,F5,E5,
  7095.         H4,G4,F4,E4,
  7096.         H3,G3,F3,E3,
  7097.         H2,G2,F2,E2,
  7098.         D7,C7,B7,A7,
  7099.         D6,C6,B6,A6,
  7100.         D5,C5,B5,A5,
  7101.         D4,C4,B4,A4,
  7102.         D3,C3,B3,A3,
  7103.         D2,C2,B2,A2
  7104. };
  7105.  
  7106. static bool_t   test_kpppk (void);
  7107. static bool_t   kpppk_pctoindex (const SQUARE *inp_pw, const SQUARE *inp_pb, index_t *out);
  7108. static void             kpppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb);
  7109.  
  7110. static index_t
  7111. init_ppp48_idx (void)
  7112. /* modifies ppp48_idx[][], ppp48_sq_x[], ppp48_sq_y[], ppp48_sq_z[] */
  7113. {
  7114.         enum  {MAX_I = 48, MAX_J = 48, MAX_K = 48};
  7115.         SQUARE i, j, k;
  7116.         index_t idx = 0;
  7117.         SQUARE a, b, c;
  7118.         int x, y, z;
  7119.  
  7120.         /* default is noindex */
  7121.         for (i = 0; i < MAX_I; i++) {
  7122.                 for (j = 0; j < MAX_J; j++) {
  7123.                         for (k = 0; k < MAX_K; k++) {
  7124.                                 IDX_set_empty(ppp48_idx [i][j][k]);
  7125.                         }
  7126.                 }
  7127.         }
  7128.  
  7129.         for (idx = 0; idx < MAX_PPP48_INDEX; idx++) {
  7130.                 ppp48_sq_x [idx] = (uint8_t)NOSQUARE;
  7131.                 ppp48_sq_y [idx] = (uint8_t)NOSQUARE;
  7132.                 ppp48_sq_z [idx] = (uint8_t)NOSQUARE;
  7133.         }
  7134.  
  7135.         idx = 0;
  7136.         for (x = 0; x < 48; x++) {
  7137.                 for (y = x+1; y < 48; y++) {
  7138.                         for (z = y+1; z < 48; z++) {
  7139.  
  7140.                                 a = itosq [x];
  7141.                                 b = itosq [y];
  7142.                                 c = itosq [z];
  7143.  
  7144.                                 if (!in_queenside(b) || !in_queenside(c))
  7145.                                                 continue;
  7146.  
  7147.                                 i = a - 8;
  7148.                                 j = b - 8;
  7149.                                 k = c - 8;
  7150.  
  7151.                                 if (IDX_is_empty(ppp48_idx [i] [j] [k])) {
  7152.  
  7153.                                         ppp48_idx  [i][j][k] = idx;
  7154.                                         ppp48_idx  [i][k][j] = idx;
  7155.                                         ppp48_idx  [j][i][k] = idx;
  7156.                                         ppp48_idx  [j][k][i] = idx;
  7157.                                         ppp48_idx  [k][i][j] = idx;
  7158.                                         ppp48_idx  [k][j][i] = idx;
  7159.                                         ppp48_sq_x [idx] = (uint8_t) i;         assert (i < MAX_I);
  7160.                                         ppp48_sq_y [idx] = (uint8_t) j;         assert (j < MAX_J);
  7161.                                         ppp48_sq_z [idx] = (uint8_t) k;         assert (k < MAX_K);
  7162.                                         idx++;
  7163.                                 }
  7164.                         }
  7165.                 }
  7166.         }
  7167.  
  7168. /*      assert (idx == MAX_PPP48_INDEX);*/
  7169.         return idx;
  7170. }
  7171.  
  7172. static bool_t
  7173. test_kpppk (void)
  7174. {
  7175.  
  7176.         enum            {MAXPC = 16+1};
  7177.         char            str[] = "kpppk";
  7178.         SQUARE          a, b, c, d, e;
  7179.         SQUARE          pw[MAXPC], pb[MAXPC];
  7180.         SQUARE          px[MAXPC], py[MAXPC];
  7181.  
  7182.         index_t         i, j;
  7183.         bool_t          err = FALSE;
  7184.  
  7185.         printf ("%8s ", str);
  7186.  
  7187.         for (a = 0; a < 64; a++) {
  7188.                 for (b = 0; b < 64; b++) {
  7189.                 for (c = 0; c < 64; c++) {
  7190.                 for (d = 0; d < 64; d++) {
  7191.                 for (e = 0; e < 64; e++) {
  7192.  
  7193.                         if (c <= H1 || c >= A8)
  7194.                                 continue;
  7195.                         if (b <= H1 || b >= A8)
  7196.                                 continue;
  7197.                         if (d <= H1 || d >= A8)
  7198.                                 continue;
  7199.  
  7200.                         pw[0] = a;
  7201.                         pw[1] = b;
  7202.                         pw[2] = c;
  7203.                         pw[3] = d;
  7204.                         pw[4] = NOSQUARE;
  7205.  
  7206.                         pb[0] = e;
  7207.                         pb[1] = NOSQUARE;
  7208.  
  7209.                         if (kpppk_pctoindex (pw, pb, &i)) {
  7210.                                                         kpppk_indextopc (i, px, py);
  7211.                                                         kpppk_pctoindex (px, py, &j);
  7212.                                                         if (i != j) {
  7213.                                                                 err = TRUE;
  7214.                                                         }
  7215.                                                         assert (i == j);
  7216.                         }
  7217.  
  7218.                 }
  7219.                 }
  7220.                 }
  7221.                 }
  7222.  
  7223.         if ((a&1)==0) {
  7224.             printf(".");
  7225.             fflush(stdout);
  7226.         }
  7227.         }
  7228.  
  7229.         if (err)
  7230.                 printf ("> %s NOT passed\n", str);
  7231.         else
  7232.                 printf ("> %s PASSED\n", str);
  7233.         return !err;
  7234. }
  7235.  
  7236.  
  7237. static void
  7238. kpppk_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  7239. {
  7240.         /*---------------------------------------------------------*
  7241.                 inverse work to make sure that the following is valid
  7242.                 index = a * BLOCK_A + b * BLOCK_B + c * BLOCK_C + d;
  7243.         *----------------------------------------------------------*/
  7244.  
  7245.         enum  {BLOCK_A = 64*64, BLOCK_B = 64};
  7246.         index_t a, b, c, r;
  7247.         SQUARE m, n, o;
  7248.  
  7249.         r  = i;
  7250.         a  = r / BLOCK_A;
  7251.         r -= a * BLOCK_A;
  7252.         b  = r / BLOCK_B;
  7253.         r -= b * BLOCK_B;
  7254.         c  = r;
  7255.  
  7256.         m = ppp48_sq_x [a];
  7257.         n = ppp48_sq_y [a];
  7258.         o = ppp48_sq_z [a];
  7259.  
  7260.  
  7261.         pw[0] = (SQUARE)b;
  7262.         pw[1] = m + 8;
  7263.         pw[2] = n + 8;
  7264.         pw[3] = o + 8;
  7265.         pw[4] = NOSQUARE;
  7266.  
  7267.         pb[0] = (SQUARE)c;
  7268.         pb[1] = NOSQUARE;
  7269.  
  7270.  
  7271.         assert (A2 <= pw[1] && pw[1] < A8);
  7272.         assert (A2 <= pw[2] && pw[2] < A8);
  7273.         assert (A2 <= pw[3] && pw[3] < A8);
  7274.         assert (kpppk_pctoindex (pw, pb, &a) && a == i);
  7275.  
  7276.         return;
  7277. }
  7278.  
  7279.  
  7280. static bool_t
  7281. kpppk_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  7282. {
  7283.         enum  {BLOCK_A = 64*64, BLOCK_B = 64};
  7284.         index_t ppp48_slice;
  7285.  
  7286.         SQUARE wk     = pw[0];
  7287.         SQUARE pawn_a = pw[1];
  7288.         SQUARE pawn_b = pw[2];
  7289.         SQUARE pawn_c = pw[3];
  7290.  
  7291.         SQUARE bk     = pb[0];
  7292.  
  7293.         SQUARE i, j, k;
  7294.  
  7295.         assert (A2 <= pawn_a && pawn_a < A8);
  7296.         assert (A2 <= pawn_b && pawn_b < A8);
  7297.         assert (A2 <= pawn_c && pawn_c < A8);
  7298.  
  7299.         i = pawn_a - 8;
  7300.         j = pawn_b - 8;
  7301.         k = pawn_c - 8;
  7302.  
  7303.         ppp48_slice = ppp48_idx [i] [j] [k];
  7304.  
  7305.         if (IDX_is_empty(ppp48_slice)) {
  7306.                 wk     = flipWE (wk);
  7307.                 pawn_a = flipWE (pawn_a);
  7308.                 pawn_b = flipWE (pawn_b);
  7309.                 pawn_c = flipWE (pawn_c);
  7310.                 bk     = flipWE (bk);
  7311.         }
  7312.  
  7313.         i = pawn_a - 8;
  7314.         j = pawn_b - 8;
  7315.         k = pawn_c - 8;
  7316.  
  7317.         ppp48_slice = ppp48_idx [i] [j] [k];
  7318.  
  7319.         if (IDX_is_empty(ppp48_slice)) {
  7320.                 *out = NOINDEX;
  7321.                 return FALSE;
  7322.         }
  7323.  
  7324.         assert (ppp48_slice < MAX_PPP48_INDEX );
  7325.  
  7326.         *out = (index_t)ppp48_slice * BLOCK_A + (index_t)wk * BLOCK_B  + (index_t)bk;
  7327.  
  7328.         return TRUE;
  7329. }
  7330.  
  7331.  
  7332. /********************** end KPPP/K ************************************/
  7333.  
  7334.  
  7335. static bool_t
  7336. kpkp_pctoindex (const SQUARE *pw, const SQUARE *pb, index_t *out)
  7337. {
  7338.         enum  {BLOCK_A = 64*64, BLOCK_B = 64};
  7339.         SQUARE pp_slice;
  7340.         SQUARE anchor, loosen;
  7341.  
  7342.         SQUARE wk     = pw[0];
  7343.         SQUARE bk     = pb[0];
  7344.         SQUARE pawn_a = pw[1];
  7345.         SQUARE pawn_b = pb[1];
  7346.  
  7347.         SQUARE m, n;
  7348.  
  7349.         #ifdef DEBUG
  7350.         if (!(A2 <= pawn_a && pawn_a < A8)) {
  7351.                 printf ("\n\nsquare of pawn_a: %s\n", Square_str[pawn_a]);
  7352.                 printf(" wk %s\n p1 %s\n p2 %s\n bk %s\n"
  7353.                         , Square_str[wk]
  7354.                         , Square_str[pawn_a]
  7355.                         , Square_str[pawn_b]
  7356.                         , Square_str[bk]
  7357.                         );
  7358.         }
  7359.         #endif
  7360.  
  7361.         assert (A2 <= pawn_a && pawn_a < A8);
  7362.         assert (A2 <= pawn_b && pawn_b < A8);
  7363.         assert (pw[2] == NOSQUARE && pb[2] == NOSQUARE);
  7364.  
  7365.         /*pp_putanchorfirst (pawn_a, pawn_b, &anchor, &loosen);*/
  7366.         anchor = pawn_a;
  7367.         loosen = pawn_b;
  7368.  
  7369.         if ((anchor & 07) > 3) { /* column is more than 3. e.g. = e,f,g, or h */
  7370.                 anchor = flipWE (anchor);
  7371.                 loosen = flipWE (loosen);
  7372.                 wk     = flipWE (wk);
  7373.                 bk     = flipWE (bk);
  7374.         }
  7375.  
  7376.         m = (SQUARE)wsq_to_pidx24 (anchor);
  7377.         n = loosen - 8;
  7378.  
  7379.         pp_slice = m * 48 + n;
  7380.  
  7381.         if (IDX_is_empty(pp_slice)) {
  7382.                 *out = NOINDEX;
  7383.                 return FALSE;
  7384.         }
  7385.  
  7386.         assert (pp_slice < MAX_PpINDEX );
  7387.  
  7388.         *out = (index_t) (pp_slice * BLOCK_A + wk * BLOCK_B  + bk);
  7389.  
  7390.         return TRUE;
  7391. }
  7392.  
  7393.  
  7394. static void
  7395. kpkp_indextopc (index_t i, SQUARE *pw, SQUARE *pb)
  7396. {
  7397.         /*---------------------------------------------------------*
  7398.                 inverse work to make sure that the following is valid
  7399.                 index = a * BLOCK_A + b * BLOCK_B + c;
  7400.         *----------------------------------------------------------*/
  7401.         enum  {B11100  = 7u << 2};
  7402.         enum  {BLOCK_A = 64*64, BLOCK_B = 64};
  7403.         enum  {block_m = 48};
  7404.         index_t a, b, c, r;
  7405.         index_t m, n;
  7406.         SQUARE sq_m, sq_n;
  7407.  
  7408.         r = i;
  7409.         a  = r / BLOCK_A;
  7410.         r -= a * BLOCK_A;
  7411.         b  = r / BLOCK_B;
  7412.         r -= b * BLOCK_B;
  7413.         c  = r;
  7414.  
  7415.         /* unpack a, which is pslice, into m and n */
  7416.         r = a;
  7417.         m  = r / block_m;
  7418.         r -= m * block_m;
  7419.         n  = r ;
  7420.  
  7421.         sq_m  = pidx24_to_wsq (m);
  7422.         sq_n  = (SQUARE)n + 8;
  7423.  
  7424.         pw[0] = (SQUARE)b;
  7425.         pb[0] = (SQUARE)c;
  7426.         pw[1] = sq_m;
  7427.         pb[1] = sq_n;
  7428.         pw[2] = NOSQUARE;
  7429.         pb[2] = NOSQUARE;
  7430.  
  7431.         assert (A2 <= pw[1] && pw[1] < A8);
  7432.         assert (A2 <= pb[1] && pb[1] < A8);
  7433.  
  7434.         return;
  7435. }
  7436.  
  7437.  
  7438. /****************************************************************************\
  7439.  *
  7440.  *
  7441.  *                                                              DEBUG ZONE
  7442.  *
  7443.  *
  7444.  ****************************************************************************/
  7445.  
  7446. #if defined(DEBUG)
  7447. static void
  7448. print_pos (const sq_t *ws, const sq_t *bs, const pc_t *wp, const pc_t *bp)
  7449. {
  7450.         int i;
  7451.         printf ("White: ");
  7452.         for (i = 0; ws[i] != NOSQUARE; i++) {
  7453.                 printf ("%s%s ", P_str[wp[i]], Square_str[ws[i]]);
  7454.         }
  7455.         printf ("\nBlack: ");
  7456.         for (i = 0; bs[i] != NOSQUARE; i++) {
  7457.                 printf ("%s%s ", P_str[bp[i]], Square_str[bs[i]]);
  7458.         }
  7459.         printf ("\n");
  7460. }
  7461. #endif
  7462.  
  7463. #if defined(DEBUG) || defined(FOLLOW_EGTB)
  7464. static void
  7465. output_state (unsigned stm, const SQUARE *wSQ, const SQUARE *bSQ,
  7466.                                                                 const SQ_CONTENT *wPC, const SQ_CONTENT *bPC)
  7467. {
  7468.         int i;
  7469.         assert (stm == WH || stm == BL);
  7470.  
  7471.         printf("\n%s to move\n", stm==WH?"White":"Black");
  7472.         printf("W: ");
  7473.         for (i = 0; wSQ[i] != NOSQUARE; i++) {
  7474.                 printf("%s%s ", P_str[wPC[i]], Square_str[wSQ[i]]);
  7475.         }
  7476.         printf("\n");
  7477.         printf("B: ");
  7478.         for (i = 0; bSQ[i] != NOSQUARE; i++) {
  7479.                 printf("%s%s ", P_str[bPC[i]], Square_str[bSQ[i]]);
  7480.         }
  7481.         printf("\n\n");
  7482. }
  7483. #endif
  7484.  
  7485. static void
  7486. list_index (void)
  7487. {
  7488.         enum  {START_GTB = 0, END_GTB = (MAX_EGKEYS)};
  7489.         int i;
  7490.         index_t accum = 0;
  7491.         printf ("\nIndex for each GTB\n");
  7492.                 printf ("%3s: %7s  %7s   %7s   %7s\n" , "i", "TB", "RAM-slice", "RAM-max", "HD-cumulative");
  7493.         for (i = START_GTB; i < END_GTB; i++) {
  7494.                 index_t indiv_k  = egkey[i].maxindex * (index_t)sizeof(dtm_t) * 2/1024;
  7495.                 accum += indiv_k;
  7496.                 printf ("%3d: %7s %8luk %8luk %8luM\n", i, egkey[i].str, (long unsigned)(indiv_k/egkey[i].slice_n),
  7497.                                                                                                         (long unsigned)indiv_k, (long unsigned)accum/1024/2);
  7498.         }
  7499.         printf ("\n");
  7500.         return;
  7501. }
  7502.  
  7503. /**************************************************************************************************************
  7504.  
  7505.  NEW_WDL
  7506.  
  7507. **************************************************************************************************************/
  7508.  
  7509. /*---------------------------------------------------------------------*\
  7510. |                       WDL CACHE Implementation  ZONE
  7511. \*---------------------------------------------------------------------*/
  7512.  
  7513. /*
  7514. |                       WDL CACHE Statics
  7515. \*---------------------------------------------------------------------*/
  7516.  
  7517. /*--------------------------------------------------------------------------*/
  7518. static unsigned int             wdl_extract (unit_t *uarr, index_t x);
  7519. static wdl_block_t *    wdl_point_block_to_replace (void);
  7520. static void                             wdl_movetotop (wdl_block_t *t);
  7521.  
  7522. #if 0
  7523. static bool_t                   wdl_cache_init (size_t cache_mem);
  7524. static void                             wdl_cache_flush (void);
  7525. static bool_t                   get_WDL (tbkey_t key, unsigned side, index_t idx, unsigned int *info_out, bool_t probe_hard_flag);
  7526. #endif
  7527.  
  7528. static bool_t                   wdl_cache_is_on (void);
  7529. static void                             wdl_cache_reset_counters (void);
  7530. static void                             wdl_cache_done (void);
  7531.  
  7532. static wdl_block_t *    wdl_point_block_to_replace (void);
  7533. static bool_t                   get_WDL_from_cache (tbkey_t key, unsigned side, index_t idx, unsigned int *out);
  7534. static void                             wdl_movetotop (wdl_block_t *t);
  7535. static bool_t                   wdl_preload_cache (tbkey_t key, unsigned side, index_t idx);
  7536.  
  7537. /*--------------------------------------------------------------------------*/
  7538.  
  7539. /*---------------------------------------------------------------------*\
  7540. |                       WDL CACHE Maintainance
  7541. \*---------------------------------------------------------------------*/
  7542.  
  7543.  
  7544. static size_t
  7545. wdl_cache_init (size_t cache_mem)
  7546. {
  7547.         unsigned int    i;
  7548.         wdl_block_t     *p;
  7549.         size_t                  entries_per_block;
  7550.         size_t                  max_blocks;
  7551.         size_t                  block_mem;
  7552.  
  7553.         if (WDL_CACHE_INITIALIZED)
  7554.                 wdl_cache_done();
  7555.  
  7556.         entries_per_block       = 16 * 1024;  /* fixed, needed for the compression schemes */
  7557.  
  7558.         WDL_units_per_block     = entries_per_block / WDL_entries_per_unit;
  7559.         block_mem                       = WDL_units_per_block * sizeof(unit_t);
  7560.  
  7561.         max_blocks                      = cache_mem / block_mem;
  7562.         cache_mem                       = max_blocks * block_mem;
  7563.  
  7564.  
  7565.         wdl_cache_reset_counters ();
  7566.  
  7567.         wdl_cache.entries_per_block = entries_per_block;
  7568.         wdl_cache.max_blocks            = max_blocks;
  7569.         wdl_cache.cached                        = TRUE;
  7570.         wdl_cache.top                           = NULL;
  7571.         wdl_cache.bot                           = NULL;
  7572.         wdl_cache.n                             = 0;
  7573.  
  7574.         if (0 == cache_mem || NULL == (wdl_cache.buffer = (unit_t *) malloc (cache_mem))) {
  7575.                 wdl_cache.cached = FALSE;
  7576.                 return 0;
  7577.         }
  7578.  
  7579.         if (0 == max_blocks|| NULL == (wdl_cache.blocks = (wdl_block_t *) malloc (max_blocks * sizeof(wdl_block_t)))) {
  7580.                 wdl_cache.cached = FALSE;
  7581.                 free (wdl_cache.buffer);
  7582.                 return 0;
  7583.         }
  7584.  
  7585.         for (i = 0; i < max_blocks; i++) {
  7586.                 p = &wdl_cache.blocks[i];
  7587.                 p->key          = -1;
  7588.                 p->side         = gtbNOSIDE;
  7589.                 p->offset       = gtbNOINDEX;
  7590.                 p->p_arr        = wdl_cache.buffer + i * WDL_units_per_block;
  7591.                 p->prev         = NULL;
  7592.                 p->next         = NULL;
  7593.         }
  7594.  
  7595.         wdl_cache.ht_size = 1;
  7596.         while (wdl_cache.ht_size < max_blocks * 4)
  7597.                 wdl_cache.ht_size *= 2;
  7598.         wdl_cache.ht_used = 0;
  7599.         wdl_cache.hash_table = (wdl_block_t**) malloc (wdl_cache.ht_size * sizeof(wdl_block_t*));;
  7600.         if (wdl_cache.hash_table == NULL) {
  7601.                 wdl_cache.cached = FALSE;
  7602.                 free (wdl_cache.blocks);
  7603.                 wdl_cache.blocks = NULL;
  7604.                 free (wdl_cache.buffer);
  7605.                 wdl_cache.buffer = NULL;
  7606.                 return 0;
  7607.         }
  7608.  
  7609.         for (i = 0; i < wdl_cache.ht_size; i++) {
  7610.                 wdl_cache.hash_table[i] = NULL;
  7611.         }
  7612.  
  7613.         WDL_CACHE_INITIALIZED = TRUE;
  7614.  
  7615.         return cache_mem;
  7616. }
  7617.  
  7618.  
  7619. static void
  7620. wdl_cache_done (void)
  7621. {
  7622.         assert(WDL_CACHE_INITIALIZED);
  7623.  
  7624.         wdl_cache.cached = FALSE;
  7625.         wdl_cache.hard = 0;
  7626.         wdl_cache.soft = 0;
  7627.         wdl_cache.hardmisses = 0;
  7628.         wdl_cache.hits = 0;
  7629.         wdl_cache.softmisses = 0;
  7630.         wdl_cache.comparisons = 0;
  7631.         wdl_cache.max_blocks = 0;
  7632.         wdl_cache.entries_per_block = 0;
  7633.  
  7634.         wdl_cache.top = NULL;
  7635.         wdl_cache.bot = NULL;
  7636.         wdl_cache.n = 0;
  7637.  
  7638.         if (wdl_cache.buffer != NULL)
  7639.                 free (wdl_cache.buffer);
  7640.         wdl_cache.buffer = NULL;
  7641.  
  7642.         if (wdl_cache.blocks != NULL)
  7643.                 free (wdl_cache.blocks);
  7644.         wdl_cache.blocks = NULL;
  7645.  
  7646.         if (wdl_cache.hash_table != NULL)
  7647.                 free (wdl_cache.hash_table);
  7648.         wdl_cache.hash_table = NULL;
  7649.  
  7650.         WDL_CACHE_INITIALIZED = FALSE;
  7651.         return;
  7652. }
  7653.  
  7654.  
  7655. static void
  7656. wdl_cache_flush (void)
  7657. {
  7658.         unsigned int    i;
  7659.         wdl_block_t     *p;
  7660.         size_t max_blocks = wdl_cache.max_blocks;
  7661.  
  7662.         wdl_cache.top                           = NULL;
  7663.         wdl_cache.bot                           = NULL;
  7664.         wdl_cache.n                             = 0;
  7665.  
  7666.         for (i = 0; i < max_blocks; i++) {
  7667.                 p = &wdl_cache.blocks[i];
  7668.                 p->key          = -1;
  7669.                 p->side         = gtbNOSIDE;
  7670.                 p->offset       = gtbNOINDEX;
  7671.                 p->p_arr        = wdl_cache.buffer + i * WDL_units_per_block;
  7672.                 p->prev         = NULL;
  7673.                 p->next         = NULL;
  7674.         }
  7675.  
  7676.         wdl_cache_reset_counters  ();
  7677.  
  7678.         return;
  7679. }
  7680.  
  7681.  
  7682. static void
  7683. wdl_cache_reset_counters (void)
  7684. {
  7685.         wdl_cache.hard = 0;
  7686.         wdl_cache.soft = 0;
  7687.         wdl_cache.hardmisses = 0;
  7688.         wdl_cache.hits = 0;
  7689.         wdl_cache.softmisses = 0;
  7690.         wdl_cache.comparisons = 0;
  7691.         return;
  7692. }
  7693.  
  7694.  
  7695. static bool_t
  7696. wdl_cache_is_on (void)
  7697. {
  7698.         return wdl_cache.cached;
  7699. }
  7700.  
  7701. /****************************************************************************\
  7702. |                                               Replacement
  7703. \****************************************************************************/
  7704.  
  7705. static wdl_block_t *
  7706. wdl_point_block_to_replace (void)
  7707. {
  7708.         wdl_block_t *p, *t, *s;
  7709.  
  7710.         assert (0 == wdl_cache.n || wdl_cache.top != NULL);
  7711.         assert (0 == wdl_cache.n || wdl_cache.bot != NULL);
  7712.         assert (0 == wdl_cache.n || wdl_cache.bot->prev == NULL);
  7713.         assert (0 == wdl_cache.n || wdl_cache.top->next == NULL);
  7714.  
  7715.         if (wdl_cache.n > 0 && -1 == wdl_cache.top->key) {
  7716.  
  7717.                 /* top blocks is unusable, should be the one to replace*/
  7718.                 p = wdl_cache.top;
  7719.  
  7720.         } else
  7721.         if (wdl_cache.n == 0) {
  7722.  
  7723.                 p = &wdl_cache.blocks[wdl_cache.n++];
  7724.                 wdl_cache.top = p;
  7725.                 wdl_cache.bot = p;
  7726.  
  7727.                 p->prev = NULL;
  7728.                 p->next = NULL;
  7729.  
  7730.         } else
  7731.         if (wdl_cache.n < wdl_cache.max_blocks) { /* add */
  7732.  
  7733.                 s = wdl_cache.top;
  7734.                 p = &wdl_cache.blocks[wdl_cache.n++];
  7735.                 wdl_cache.top = p;
  7736.  
  7737.                 s->next = p;
  7738.                 p->prev = s;
  7739.                 p->next = NULL;
  7740.  
  7741.         } else {                       /* replace*/
  7742.  
  7743.                 t = wdl_cache.bot;
  7744.                 s = wdl_cache.top;
  7745.                 wdl_cache.bot = t->next;
  7746.                 wdl_cache.top = t;
  7747.  
  7748.                 s->next = t;
  7749.                 t->prev = s;
  7750.                 wdl_cache.top->next = NULL;
  7751.                 wdl_cache.bot->prev = NULL;
  7752.  
  7753.                 p = t;
  7754.         }
  7755.  
  7756.         /* make the information content unusable, it will be replaced */
  7757.         p->key    = -1;
  7758.         p->side   = gtbNOSIDE;
  7759.         p->offset = gtbNOINDEX;
  7760.  
  7761.         return p;
  7762. }
  7763.  
  7764. /****************************************************************************\
  7765. |
  7766. |                                               NEW PROBING ZONE
  7767. |
  7768. \****************************************************************************/
  7769.  
  7770. static unsigned int     wdl_extract (unit_t *uarr, index_t x);
  7771. static bool_t           get_WDL_from_cache (tbkey_t key, unsigned side, index_t idx, unsigned int *info_out);
  7772. static unsigned         dtm2WDL(dtm_t dtm);
  7773. static void                     wdl_movetotop (wdl_block_t *t);
  7774. static bool_t           wdl_preload_cache (tbkey_t key, unsigned side, index_t idx);
  7775. static void                     dtm_block_2_wdl_block(dtm_block_t *g, wdl_block_t *w, size_t n);
  7776.  
  7777. static bool_t
  7778. get_WDL (tbkey_t key, unsigned side, index_t idx, unsigned int *info_out, bool_t probe_hard_flag)
  7779. {
  7780.         dtm_t dtm;
  7781.         bool_t found;
  7782.  
  7783.         found = get_WDL_from_cache (key, side, idx, info_out);
  7784.  
  7785.         if (found) {
  7786.                 wdl_cache.hits++;
  7787.         } else {
  7788.                 /* may probe soft */
  7789.                 found = get_dtm (key, side, idx, &dtm, probe_hard_flag);
  7790.                 if (found) {
  7791.                         *info_out = dtm2WDL(dtm);
  7792.                         /* move cache info from dtm_cache to WDL_cache */
  7793.                         if (wdl_cache_is_on())
  7794.                                 wdl_preload_cache (key, side, idx);
  7795.                 }
  7796.         }
  7797.  
  7798.         if (probe_hard_flag) {
  7799.                 wdl_cache.hard++;
  7800.                 if (!found) {
  7801.                         wdl_cache.hardmisses++;
  7802.                 }
  7803.         } else {
  7804.                 wdl_cache.soft++;
  7805.                 if (!found) {
  7806.                         wdl_cache.softmisses++;
  7807.                 }
  7808.         }
  7809.  
  7810.         return found;
  7811. }
  7812.  
  7813. static void wdl_hash_insert (wdl_block_t * e);
  7814.  
  7815. static void
  7816. wdl_hash_rebuild (void)
  7817. {
  7818.         wdl_block_t     * p;
  7819.         size_t i;
  7820.  
  7821.         for (i = 0; i < wdl_cache.ht_size; i++)
  7822.                 wdl_cache.hash_table[i] = NULL;
  7823.         wdl_cache.ht_used = 0;
  7824.  
  7825.         for (p = wdl_cache.top; p != NULL; p = p->prev)
  7826.                 wdl_hash_insert (p);
  7827. }
  7828.  
  7829. static void
  7830. wdl_hash_insert (wdl_block_t * e)
  7831. {
  7832.         size_t h1, h2;
  7833.  
  7834.         if (wdl_cache.ht_used > wdl_cache.ht_size * 3 / 4)
  7835.                 wdl_hash_rebuild();
  7836.  
  7837.     h1 = hash_func_1 (e->key, e->side, e->offset) & (wdl_cache.ht_size - 1);
  7838.     h2 = hash_func_2 (e->key, e->side, e->offset);
  7839.     while (wdl_cache.hash_table[h1])
  7840.         h1 = (h1 + h2) & (wdl_cache.ht_size - 1);
  7841.     wdl_cache.hash_table[h1] = e;
  7842.     wdl_cache.ht_used++;
  7843. }
  7844.  
  7845. static bool_t
  7846. get_WDL_from_cache (tbkey_t key, unsigned side, index_t idx, unsigned int *out)
  7847. {
  7848.         index_t         offset;
  7849.         index_t         remainder;
  7850.         wdl_block_t     *p;
  7851.         wdl_block_t     *ret;
  7852.         size_t          h1, h2;
  7853.  
  7854.         if (!wdl_cache_is_on())
  7855.                 return FALSE;
  7856.  
  7857.         split_index (wdl_cache.entries_per_block, idx, &offset, &remainder);
  7858.  
  7859.         ret = NULL;
  7860.  
  7861.         h1 = hash_func_1 (key, side, offset) & (wdl_cache.ht_size - 1);
  7862.         h2 = hash_func_2 (key, side, offset);
  7863.         while (1) {
  7864.                 p = wdl_cache.hash_table[h1];
  7865.                 if (!p)
  7866.                         break;
  7867.  
  7868.                 wdl_cache.comparisons++;
  7869.  
  7870.                 if (key == p->key && side == p->side && offset  == p->offset) {
  7871.                         ret = p;
  7872.                         break;
  7873.                 }
  7874.  
  7875.                 h1 = (h1 + h2) & (wdl_cache.ht_size - 1);
  7876.         }
  7877.  
  7878.         if (ret != NULL) {
  7879.                 *out = wdl_extract (ret->p_arr, remainder);
  7880.                 wdl_movetotop(ret);
  7881.         }
  7882.  
  7883.         FOLLOW_LU("get_wdl_from_cache ok?",(ret != NULL))
  7884.  
  7885.         return ret != NULL;
  7886. }
  7887.  
  7888. static unsigned int
  7889. wdl_extract (unit_t *uarr, index_t x)
  7890. {
  7891.         index_t width = 2;
  7892.         index_t nu = x/WDL_entries_per_unit;
  7893.         index_t y  = x - (nu * WDL_entries_per_unit);
  7894.         return (uarr[nu] >> (y*width)) & WDL_entry_mask;
  7895. }
  7896.  
  7897. static void
  7898. wdl_movetotop (wdl_block_t *t)
  7899. {
  7900.         wdl_block_t *s, *nx, *pv;
  7901.  
  7902.         assert (t != NULL);
  7903.  
  7904.         if (t->next == NULL) /* at the top already */
  7905.                 return;
  7906.  
  7907.         /* detach */
  7908.         pv = t->prev;
  7909.         nx = t->next;
  7910.  
  7911.         if (pv == NULL)  /* at the bottom */
  7912.                 wdl_cache.bot = nx;
  7913.         else
  7914.                 pv->next = nx;
  7915.  
  7916.         if (nx == NULL) /* at the top */
  7917.                 wdl_cache.top = pv;
  7918.         else
  7919.                 nx->prev = pv;
  7920.  
  7921.         /* relocate */
  7922.         s = wdl_cache.top;
  7923.         assert (s != NULL);
  7924.         if (s == NULL)
  7925.                 wdl_cache.bot = t;
  7926.         else
  7927.                 s->next = t;
  7928.  
  7929.         t->next = NULL;
  7930.         t->prev = s;
  7931.         wdl_cache.top = t;
  7932.  
  7933.         return;
  7934. }
  7935.  
  7936. /****************************************************************************************************/
  7937.  
  7938. static bool_t
  7939. wdl_preload_cache (tbkey_t key, unsigned side, index_t idx)
  7940. /* output to the least used block of the cache */
  7941. {
  7942.         dtm_block_t             *dtm_block;
  7943.         wdl_block_t     *to_modify;
  7944.         bool_t                  ok;
  7945.  
  7946.         FOLLOW_label("wdl preload_cache starts")
  7947.  
  7948.         if (idx >= egkey[key].maxindex) {
  7949.                 FOLLOW_LULU("Wrong index", __LINE__, idx)
  7950.                 return FALSE;
  7951.         }
  7952.  
  7953.         /* find fresh block in dtm cache */
  7954.         dtm_block = dtm_cache_pointblock (key, side, idx);
  7955.  
  7956.         /* find aged blocked in wdl cache */
  7957.         to_modify = wdl_point_block_to_replace ();
  7958.  
  7959.         ok = !(NULL == dtm_block || NULL == to_modify);
  7960.  
  7961.         if (!ok)
  7962.                 return FALSE;
  7963.  
  7964.         /* transform and move a block */
  7965.         dtm_block_2_wdl_block(dtm_block, to_modify, dtm_cache.entries_per_block);
  7966.  
  7967.         if (ok) {
  7968.                 index_t                 offset;
  7969.                 index_t                 remainder;
  7970.                 split_index (wdl_cache.entries_per_block, idx, &offset, &remainder);
  7971.  
  7972.                 to_modify->key    = key;
  7973.                 to_modify->side   = side;
  7974.                 to_modify->offset = offset;
  7975.                 wdl_hash_insert (to_modify);
  7976.         } else {
  7977.                 /* make it unusable */
  7978.                 to_modify->key    = -1;
  7979.                 to_modify->side   = gtbNOSIDE;
  7980.                 to_modify->offset = gtbNOINDEX;
  7981.         }
  7982.  
  7983.         FOLLOW_LU("wdl preload_cache?", ok)
  7984.  
  7985.         return ok;
  7986. }
  7987.  
  7988. /****************************************************************************************************/
  7989.  
  7990. static void
  7991. dtm_block_2_wdl_block(dtm_block_t *g, wdl_block_t *w, size_t n)
  7992. {
  7993.         int width = 2;
  7994.         int shifting;
  7995.         size_t i;
  7996.         int j;
  7997.         unsigned int x ,y;
  7998.          dtm_t *s = g->p_arr;
  7999.         unit_t *d = w->p_arr;
  8000.  
  8001.         for (i = 0, y = 0; i < n; i++) {
  8002.                 j =  i & 3; /* modulo WDL_entries_per_unit */
  8003.                 x = dtm2WDL(s[i]);
  8004.                 shifting = j * width;
  8005.                 y |= (x << shifting);
  8006.  
  8007.                 if (j == 3) {
  8008.                         d[i/WDL_entries_per_unit] = (unit_t) y;
  8009.                         y = 0;
  8010.                 }
  8011.         }
  8012.  
  8013.         if (0 != (n & 3)) { /* not multiple of 4 */
  8014.                 d[(n-1)/WDL_entries_per_unit] = (unit_t) y; /* save the rest     */
  8015.                 y = 0;
  8016.         }
  8017.  
  8018.         return;
  8019. }
  8020.  
  8021. static unsigned
  8022. dtm2WDL(dtm_t dtm)
  8023. {
  8024.         return (unsigned) dtm & 3;
  8025. }
  8026.  
  8027.  
  8028. /**************************/
  8029. #ifdef WDL_PROBE
  8030.  
  8031. static unsigned int     inv_wdl(unsigned w);
  8032. static bool_t   egtb_get_wdl (tbkey_t k, unsigned stm, const SQUARE *wS, const SQUARE *bS, bool_t probe_hard_flag, unsigned int *wdl);
  8033.  
  8034. static bool_t
  8035. tb_probe_wdl
  8036.                         (unsigned stm,
  8037.                          const SQUARE *inp_wSQ,
  8038.                          const SQUARE *inp_bSQ,
  8039.                          const SQ_CONTENT *inp_wPC,
  8040.                          const SQ_CONTENT *inp_bPC,
  8041.                          bool_t probingtype,
  8042.                          /*@out@*/ unsigned *res)
  8043. {
  8044.         tbkey_t id = -1;
  8045.         unsigned int wdl = iUNKNOWN;
  8046.  
  8047.         SQUARE          storage_ws [MAX_LISTSIZE], storage_bs [MAX_LISTSIZE];
  8048.         SQ_CONTENT  storage_wp [MAX_LISTSIZE], storage_bp [MAX_LISTSIZE];
  8049.  
  8050.         SQUARE     *ws = storage_ws;
  8051.         SQUARE     *bs = storage_bs;
  8052.         SQ_CONTENT *wp = storage_wp;
  8053.         SQ_CONTENT *bp = storage_bp;
  8054.         SQUARE          tmp_ws [MAX_LISTSIZE], tmp_bs [MAX_LISTSIZE];
  8055.         SQ_CONTENT  tmp_wp [MAX_LISTSIZE], tmp_bp [MAX_LISTSIZE];
  8056.  
  8057.         SQUARE *temps;
  8058.         bool_t straight = FALSE;
  8059.  
  8060.         bool_t  okcall  = TRUE;
  8061.         unsigned ply_;
  8062.         unsigned *ply = &ply_;
  8063.  
  8064.         /************************************/
  8065.  
  8066.         assert (stm == WH || stm == BL);
  8067.  
  8068.         /* VALID ONLY FOR KK!! */
  8069.         if (inp_wPC[1] == NOPIECE && inp_bPC[1] == NOPIECE) {
  8070.                 index_t dummy_i;
  8071.                 bool_t b = kxk_pctoindex (inp_wSQ, inp_bSQ, &dummy_i);
  8072.                 *res = b? iDRAW: iFORBID;
  8073.                 *ply = 0;
  8074.                 return TRUE;
  8075.         }
  8076.  
  8077.         /* copy input */
  8078.         list_pc_copy (inp_wPC, wp);
  8079.         list_pc_copy (inp_bPC, bp);
  8080.         list_sq_copy (inp_wSQ, ws);
  8081.         list_sq_copy (inp_bSQ, bs);
  8082.  
  8083.         sortlists (ws, wp);
  8084.         sortlists (bs, bp);
  8085.  
  8086.         FOLLOW_label("EGTB_PROBE")
  8087.  
  8088.         if (egtb_get_id (wp, bp, &id)) {
  8089.                 FOLLOW_LU("got ID",id)
  8090.                 straight = TRUE;
  8091.         } else if (egtb_get_id (bp, wp, &id)) {
  8092.                 FOLLOW_LU("rev ID",id)
  8093.                 straight = FALSE;
  8094.                 list_sq_flipNS (ws);
  8095.                 list_sq_flipNS (bs);
  8096.         temps = ws;
  8097.         ws = bs;
  8098.         bs = temps;
  8099.                 stm = Opp(stm);
  8100.                 /* no enpassant in this fuction, so no adjustment */
  8101.                 {SQ_CONTENT *tempp = wp; wp = bp; bp = tempp;}  /* added */
  8102.         } else {
  8103.                 #if defined(DEBUG)
  8104.                 printf("did not get id...\n");
  8105.                 output_state (stm, ws, bs, wp, bp);
  8106.                 #endif
  8107.                 unpackdist (iFORBID, res, ply);
  8108.                 return FALSE;
  8109.         }
  8110.  
  8111.         /* store position... */
  8112.         list_pc_copy (wp, tmp_wp);
  8113.         list_pc_copy (bp, tmp_bp);
  8114.         list_sq_copy (ws, tmp_ws);
  8115.         list_sq_copy (bs, tmp_bs);
  8116.  
  8117.         /* x will be stm and y will be stw */
  8118. /*
  8119.         if (stm == WH) {
  8120.         xs = ws;
  8121.         xp = wp;
  8122.         ys = bs;
  8123.         yp = bp;
  8124.     } else {
  8125.         xs = bs;
  8126.         xp = bp;
  8127.         ys = ws;
  8128.         yp = wp;
  8129.         }
  8130. */
  8131.         okcall = egtb_get_wdl (id, stm, ws, bs, probingtype, &wdl);
  8132.  
  8133.         FOLLOW_LU("dtmok?",okcall)
  8134.         FOLLOW_DTM("wdl", wdl)
  8135.  
  8136.         if (okcall) {
  8137.  
  8138.                 /*assert(epsq == NOSQUARE); */
  8139.  
  8140.                 if (straight) {
  8141.                         *res = wdl;
  8142.                 } else {
  8143.                         *res = inv_wdl (wdl);
  8144.                 }
  8145.         } else {
  8146.                         unpackdist (iFORBID, res, ply);
  8147.         }
  8148.  
  8149.         return okcall;
  8150. }
  8151.  
  8152. static unsigned int
  8153. inv_wdl(unsigned w)
  8154. {
  8155.         unsigned r = tb_UNKNOWN;
  8156.         switch (w) {
  8157.                 case tb_DRAW:    r = tb_DRAW;    break;
  8158.                 case tb_WMATE:   r = tb_BMATE;   break;
  8159.                 case tb_BMATE:   r = tb_WMATE;   break;
  8160.                 case tb_FORBID:  r = tb_FORBID;  break;
  8161.                 case tb_UNKNOWN: r = tb_UNKNOWN; break;
  8162.                 default:         r = tb_UNKNOWN; break;
  8163.         }
  8164.         return r;
  8165. }
  8166.  
  8167. static bool_t
  8168. egtb_get_wdl (tbkey_t k, unsigned stm, const SQUARE *wS, const SQUARE *bS, bool_t probe_hard_flag, unsigned int *wdl)
  8169. {
  8170.         bool_t idxavail;
  8171.         index_t idx;
  8172.         dtm_t *tab[2];
  8173.         bool_t (*pc2idx) (const SQUARE *, const SQUARE *, index_t *);
  8174.  
  8175.         FOLLOW_label("egtb_get_wdl --> starts")
  8176.  
  8177.         if (egkey[k].status == STATUS_MALLOC || egkey[k].status == STATUS_STATICRAM) {
  8178.  
  8179.                 tab[WH] = egkey[k].egt_w;
  8180.                 tab[BL] = egkey[k].egt_b;
  8181.                 pc2idx  = egkey[k].pctoi;
  8182.  
  8183.                 idxavail = pc2idx (wS, bS, &idx);
  8184.  
  8185.                 FOLLOW_LU("indexavail (RAM)",idxavail)
  8186.  
  8187.                 if (idxavail) {
  8188.                         *wdl = dtm2WDL(tab[stm][idx]);
  8189.                 } else {
  8190.                         *wdl = dtm2WDL(iFORBID);
  8191.                 }
  8192.  
  8193.                 return FALSE;
  8194.  
  8195.         } else if (egkey[k].status == STATUS_ABSENT) {
  8196.  
  8197.                 pc2idx   = egkey[k].pctoi;
  8198.                 idxavail = pc2idx (wS, bS, &idx);
  8199.  
  8200.                 FOLLOW_LU("indexavail (HD)",idxavail)
  8201.  
  8202.                 if (idxavail) {
  8203.                         bool_t success;
  8204.  
  8205.                         /*
  8206.                         |               LOCK
  8207.                         *-------------------------------*/
  8208.                         mythread_mutex_lock (&Egtb_lock);
  8209.  
  8210.                         success = get_WDL (k, stm, idx, wdl, probe_hard_flag);
  8211.                         FOLLOW_LU("get_wld (succ)",success)
  8212.                         FOLLOW_LU("get_wld (wdl )",*wdl)
  8213.  
  8214.                         /* this may not be needed */
  8215.                         if (!success) {
  8216.                                 dtm_t dtm;
  8217.                                 unsigned res, ply;
  8218.                                 if (probe_hard_flag && Uncompressed) {
  8219.                                         assert(Uncompressed);
  8220.                                         success = egtb_filepeek (k, stm, idx, &dtm);
  8221.                                         unpackdist (dtm, &res, &ply);
  8222.                                         *wdl = res;
  8223.                                 }
  8224.                                 else
  8225.                                         success = FALSE;
  8226.                         }
  8227.  
  8228.                         mythread_mutex_unlock (&Egtb_lock);
  8229.                         /*------------------------------*\
  8230.                         |               UNLOCK
  8231.                         */
  8232.  
  8233.                         if (success) {
  8234.                                 return TRUE;
  8235.                         } else {
  8236.                                 if (probe_hard_flag) /* after probing hard and failing, no chance to succeed later */
  8237.                                         egkey[k].status = STATUS_REJECT;
  8238.                                 *wdl = dtm2WDL(iUNKNOWN);
  8239.                                 return FALSE;
  8240.                         }
  8241.  
  8242.                 } else {
  8243.                         *wdl = dtm2WDL(iFORBID);
  8244.                         return  TRUE;
  8245.                 }
  8246.         } else if (egkey[k].status == STATUS_REJECT) {
  8247.                 FOLLOW_label("STATUS_REJECT")
  8248.                 *wdl = dtm2WDL(iFORBID);
  8249.                 return  FALSE;
  8250.         } else {
  8251.                 FOLLOW_label("STATUS_WRONG!")
  8252.                 assert(0);
  8253.                 *wdl = dtm2WDL(iFORBID);
  8254.                 return  FALSE;
  8255.         }
  8256.  
  8257. }
  8258. #endif
  8259.  
  8260.  
  8261.  
  8262.