Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
99 pmbaty 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