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 |