1 /*
2 Sjeng - a chess variants playing program
3 Copyright (C) 2001 Gian-Carlo Pascutto and Nubie
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 File: segtb.c
20 Purpose: suicide endgame tablebases
21
22 */
23
24 #include <limits.h>
25 #include "sjeng.h"
26 #include "extvars.h"
27 #include "protos.h"
28 #include "squares.h"
29
30 #define FILE(x) ((x) & 7)
31 #define RANK(x) ((x) >> 3)
32
33 #define TWO_PIECE_SIZE 4096
34 #define TWO_PIECE_HASH(x,y,z) (((((x) << 5) | (y)) << 6) | (z))
35 #define TWO_PIECE_FILE "stb/2pieces.bin"
36
37 #define THREE_PIECE_SIZE (64*TWO_PIECE_SIZE)
38 #define THREE_PIECE_HASH(x,y,z,w) (((((((x) << 5) | (y)) << 6) | (z)) << 6) | (w))
39 #define THREE_PIECE_FILE "stb/xxx.bin"
40
41 #define TABLE_KEY(x,y,z) (((((x) << 3) | (y)) << 3) | (z))
42
43 #define IO_BUFSIZE 4096
44 #define CACHE_SIZE 8
45
46 int upscale[64] = {
47 A1,B1,C1,D1,E1,F1,G1,H1,
48 A2,B2,C2,D2,E2,F2,G2,H2,
49 A3,B3,C3,D3,E3,F3,G3,H3,
50 A4,B4,C4,D4,E4,F4,G4,H4,
51 A5,B5,C5,D5,E5,F5,G5,H5,
52 A6,B6,C6,D6,E6,F6,G6,H6,
53 A7,B7,C7,D7,E7,F7,G7,H7,
54 A8,B8,C8,D8,E8,F8,G8,H8
55 };
56
57 int vertical_flip[64] = {
58 7, 6, 5, 4, 3, 2, 1, 0,
59 15, 14, 13, 12, 11, 10, 9, 8,
60 23, 22, 21, 20, 19, 18, 17, 16,
61 31, 30, 29, 28, 27, 26, 25, 24,
62 39, 38, 37, 36, 35, 34, 33, 32,
63 47, 46, 45, 44, 43, 42, 41, 40,
64 55, 54, 53, 52, 51, 50, 49, 48,
65 63, 62, 61, 60, 59, 58, 57, 56
66 };
67
68 /* angrim : this is 63-x, no need to lookup */
69
70 int rotate[64] = {
71 63, 62, 61, 60, 59, 58, 57, 56,
72 55, 54, 53, 52, 51, 50, 49, 48,
73 47, 46, 45, 44, 43, 42, 41, 40,
74 39, 38, 37, 36, 35, 34, 33, 32,
75 31, 30, 29, 28, 27, 26, 25, 24,
76 23, 22, 21, 20, 19, 18, 17, 16,
77 15, 14, 13, 12, 11, 10, 9, 8,
78 7, 6, 5, 4, 3, 2, 1, 0
79 };
80
81 int white_addr[64] = {
82 0, 1, 2, 3, -1, -1, -1, -1,
83 4, 5, 6, 7, -1, -1, -1, -1,
84 8, 9, 10, 11, -1, -1, -1, -1,
85 12, 13, 14, 15, -1, -1, -1, -1,
86 16, 17, 18, 19, -1, -1, -1, -1,
87 20, 21, 22, 23, -1, -1, -1, -1,
88 24, 25, 26, 27, -1, -1, -1, -1,
89 28, 29, 30, 31, -1, -1, -1, -1
90 };
91
92 int section_map[6][6] = {
93 { 0, 1, 2, 3, 4, 5 },
94 { -1, 6, 7, 8, 9, 10 },
95 { -1, -1, 11, 12, 13, 14 },
96 { -1, -1, -1, 15, 16, 17 },
97 { -1, -1, -1, -1, 18, 19 },
98 { -1, -1, -1, -1, -1, 20 }
99 };
100
101
102 int section_trans[] = {666, 0, 0, 1, 1, 5, 5, 3, 3, 4, 4, 2, 2, 6};
103 char xpiece_char[] = {'F','P','P','N','N','K','K','R','R','Q','Q','B','B','E' };
104
105 typedef struct
106 {
107 int table_key;
108 int last_access;
109 } cache_data;
110
111 signed char *two_piece_data;
112 signed char *three_piece_data;
113 signed char *temp_table; /* used when generating new tables */
114
115 int cache_counter;
116 cache_data table_cache[CACHE_SIZE];
117 int temp_key;
118
119 int SEGTB;
120
valid_2piece(int w,int b,int w_man,int b_man)121 int valid_2piece(int w, int b, int w_man, int b_man)
122 {
123 /* white piece on the wrong half-board? */
124
125 if(white_addr[w] == -1)
126 return 0;
127
128 /* pieces on the same square? */
129 if(w == b)
130 return 0;
131
132 if(w_man == wpawn || w_man == bpawn)
133 if(w < 8 || w > 55)
134 return 0;
135
136 if(b_man == bpawn || b_man == wpawn)
137 if(b < 8 || b > 55)
138 return 0;
139
140 return 1;
141 }
142
143
valid_3piece(int w,int b1,int b2,int w_man,int b1_man,int b2_man)144 int valid_3piece(int w, int b1, int b2, int w_man, int b1_man, int b2_man)
145 {
146 /* white piece on the wrong half-board? */
147 if(white_addr[w] == -1)
148 return 0;
149
150 /* pieces on the same square? */
151 if(w == b1)
152 return 0;
153
154 if(w == b2)
155 return 0;
156
157 if(b1 == b2)
158 return 0;
159
160 /* pawn on a bad rank? */
161 if(w_man == wpawn || w_man == bpawn)
162 if(w < 8 || w > 55)
163 return 0;
164
165 if(b1_man == bpawn || b1_man == wpawn)
166 if(b1 < 8 || b1 > 55)
167 return 0;
168
169 if(b2_man == bpawn || b2_man == wpawn)
170 if(b2 < 8 || b2 > 55)
171 return 0;
172
173 return 1;
174 }
175
check_result()176 int check_result()
177 {
178 int p, xp, res;
179 int wp = 0, bp = 0;
180 int a, j, i;
181 move_s moves[MOVE_BUFF];
182 int num_moves;
183
184 for (j = 1, a = 1; (a <= piece_count); j++)
185 {
186 i = pieces[j];
187
188 if (!i)
189 continue;
190 else
191 a++;
192
193 switch (board[i])
194 {
195 case wpawn:
196 case wbishop:
197 case wrook:
198 case wking:
199 case wqueen:
200 case wknight: wp++; break;
201 case bpawn:
202 case bbishop:
203 case brook:
204 case bking:
205 case bqueen:
206 case bknight: bp++; break;
207 }
208 }
209
210 if (!(wp) && (bp))
211 {
212 if (white_to_move)
213 {
214 return -127;
215 }
216 else
217 {
218 return 126;
219 }
220 }
221 else if ((!bp) && (wp))
222 {
223 if (white_to_move)
224 {
225 return 126;
226 }
227 else
228 {
229 return -127;
230 }
231 }
232
233
234 gen(&moves[0]);
235 num_moves = numb_moves;
236
237 if(!num_moves)
238 {
239 if (white_to_move)
240 {
241 p = wp;
242 xp = bp;
243 }
244 else
245 {
246 p = bp;
247 xp = wp;
248 }
249
250 if(p < xp) return -127;
251 else if(xp < p) return 126; /* can't really happen */
252 else return 0;
253
254 }
255
256 res = egtb(white_to_move);
257
258 if(res > -10 && res < 10 && res)
259 printf("Warning: near zero values!\n");
260
261 if(res > 0)
262 return -res+1;
263 else if(res < 0 && res > -128)
264 return -res-1;
265
266 return res;
267 }
268
gen_2piece(int w_man,int b_man,signed char * table)269 void gen_2piece(int w_man, int b_man, signed char *table)
270 {
271 int i, w, b, t, addr;
272 signed char best, res;
273 int f, unknown;
274 move_s moves[MOVE_BUFF];
275 int num_moves;
276
277 ply = 1;
278 reset_board();
279
280 /* initialise the table */
281 memset(table, -128, TWO_PIECE_SIZE);
282
283 if (!(w_man & 1)) w_man--;
284 if (b_man & 1) b_man++;
285
286 do
287 {
288 f = FALSE;
289
290 for(t = 0; t < 2; t++)
291 {
292 white_to_move = t;
293
294 for(w = 0; w < 64; w++)
295 {
296 for(b = 0; b < 64; b++)
297 {
298 if(!valid_2piece(w, b, w_man, b_man)) continue;
299
300 addr = TWO_PIECE_HASH(t, white_addr[w], b);
301 if(table[addr] != -128) continue;
302
303 board[upscale[w]] = w_man;
304 board[upscale[b]] = b_man;
305 pieces[1] = upscale[w];
306 pieces[2] = upscale[b];
307 squares[upscale[w]] = 1;
308 squares[upscale[b]] = 2;
309 piece_count = 2;
310 ep_square = 0;
311
312 gen(&moves[0]);
313 num_moves = numb_moves;
314
315 if(num_moves == 0)
316 {
317 if (table[addr] != 0) f = TRUE;
318 table[addr] = 0;
319 }
320 else
321 {
322 best = -128;
323 unknown = FALSE;
324
325 for(i = 0; i < num_moves; i++)
326 {
327 make(&moves[0], i);
328 res = (signed char) check_result();
329 unmake(&moves[0], i);
330
331
332 if(res == -128)
333 {
334 unknown = TRUE;
335 continue;
336 }
337
338 if(res > best) best = res;
339 }
340
341 if(best > 0 || (best < 0 && !unknown))
342 {
343 if (table[addr] != best) f = TRUE;
344 table[addr] = best;
345 }
346 }
347
348 board[upscale[w]] = npiece;
349 board[upscale[b]] = npiece;
350 squares[upscale[w]] = 0;
351 squares[upscale[b]] = 0;
352 pieces[1] = 0;
353 pieces[2] = 0;
354
355 }
356 }
357 }
358 printf(".");
359 }
360 while(f);
361
362 printf("\n");
363
364 for(i = 0; i < TWO_PIECE_SIZE; i++)
365 if(table[i] == -128) table[i] = 0;
366
367 }
368
369
gen_3piece(int w_man,int b1_man,int b2_man,signed char * table)370 void gen_3piece(int w_man, int b1_man, int b2_man, signed char *table)
371 {
372 int i, w, b1, b2, t, addr;
373 signed char best, res;
374 int f, unknown;
375 move_s moves[MOVE_BUFF];
376 int num_moves;
377
378 ply = 1;
379 reset_board();
380
381 /* initialise the table */
382 memset(table, -128, THREE_PIECE_SIZE);
383
384 /* normalize colors if needed */
385 if (!(w_man & 1)) w_man--;
386 if (b1_man & 1) b1_man++;
387 if (b2_man & 1) b2_man++;
388
389 do
390 {
391 f = FALSE;
392
393 for(t = 0; t < 2; t++)
394 {
395 white_to_move = t;
396
397 for(w = 0; w < 64; w++)
398 {
399 for(b1 = 0; b1 < 64; b1++)
400 {
401 for(b2 = 0; b2 < 64; b2++)
402 {
403
404 if(!valid_3piece(w, b1, b2, w_man, b1_man, b2_man)) continue;
405
406 addr = THREE_PIECE_HASH(t, white_addr[w], b1, b2);
407 // if(table[addr] != -128) continue;
408
409 board[upscale[w]] = w_man;
410 board[upscale[b1]] = b1_man;
411 board[upscale[b2]] = b2_man;
412 piece_count = 3;
413 pieces[1] = upscale[w];
414 pieces[2] = upscale[b1];
415 pieces[3] = upscale[b2];
416 squares[upscale[w]] = 1;
417 squares[upscale[b1]] = 2;
418 squares[upscale[b2]] = 3;
419 ep_square = 0;
420
421 gen(&moves[0]);
422 num_moves = numb_moves;
423
424 if(!num_moves)
425 {
426 if (table[addr] != (white_to_move ? 126 : -127))
427 f = TRUE;
428 table[addr] = (white_to_move ? 126 : -127);
429 }
430 else
431 {
432 best = -128;
433 unknown = FALSE;
434
435 for(i = 0; i < num_moves; i++)
436 {
437 make(&moves[0], i);
438 res = (signed char) check_result();
439 unmake(&moves[0], i);
440
441 if(res == -128)
442 {
443 unknown = TRUE;
444 continue;
445 }
446
447 if(res > best) best = res;
448 }
449
450 if(best > 0 || (best < 0 && !unknown))
451 {
452 if (table[addr] != best) f = TRUE;
453 table[addr] = best;
454 }
455 }
456
457 board[upscale[w]] = npiece;
458 board[upscale[b1]] = npiece;
459 board[upscale[b2]] = npiece;
460 squares[upscale[w]] = 0;
461 squares[upscale[b1]] = 0;
462 squares[upscale[b2]] = 0;
463 pieces[1] = 0;
464 pieces[2] = 0;
465 pieces[3] = 0;
466 }
467 }
468 }
469 }
470 printf(".");
471 }
472 while(f);
473
474 printf("\n");
475
476 for(i = 0; i < THREE_PIECE_SIZE; i++)
477 if(table[i] == -128) table[i] = 0;
478
479 }
480
save_2piece()481 int save_2piece()
482 {
483 int i, j;
484 FILE *f;
485 signed char *table;
486
487 if(!(f = fopen(TWO_PIECE_FILE, "w"))) return 0;
488
489 for(i = 0; i < 21; i++)
490 {
491 table = two_piece_data + i * TWO_PIECE_SIZE;
492 for(j = 0 ; j < TWO_PIECE_SIZE; j++)
493 {
494 fputc(table[j], f);
495 }
496 }
497
498 fclose(f);
499 return 1;
500 }
501
502
save_3piece(int w1_man,int b1_man,int b2_man,signed char * t)503 int save_3piece(int w1_man, int b1_man, int b2_man, signed char *t)
504 {
505 FILE *f;
506 signed char fname[13];
507 signed char *buf;
508 int i;
509
510 /* generate the filename */
511
512 strcpy(fname, THREE_PIECE_FILE);
513 fname[4] = xpiece_char[w1_man];
514 fname[5] = xpiece_char[b1_man];
515 fname[6] = xpiece_char[b2_man];
516
517 if(!(f = fopen(fname,"w"))) return 0;
518
519 for(i = 0; i < THREE_PIECE_SIZE; i += IO_BUFSIZE)
520 {
521 buf = t + i;
522
523 if(!fwrite(buf, IO_BUFSIZE, 1, f))
524 {
525 printf("Error writing %s\n",fname);
526 fclose(f);
527 return 0;
528 }
529 }
530
531 fclose(f);
532 return 1;
533 }
534
535
gen_all_tables()536 void gen_all_tables()
537 {
538 int w_man, b1_man, b2_man;
539 signed char *base_addr;
540
541 printf("Two-piece tables:\n");
542
543 /* first generate pawnless tables */
544 for(w_man = wknight; w_man <= wbishop; w_man += 2)
545 {
546 for(b1_man = bknight; b1_man <= bbishop; b1_man += 2)
547 {
548 if(section_map[section_trans[w_man]][section_trans[b1_man]] == -1) continue;
549
550 printf("Generating %c vs %c ",
551 xpiece_char[w_man], xpiece_char[b1_man]);
552
553 base_addr = two_piece_data
554 + (section_map[section_trans[w_man]][section_trans[b1_man]] * TWO_PIECE_SIZE);
555
556 gen_2piece(w_man, b1_man, base_addr);
557 }
558 }
559
560 /* pawns are the tricky ones that can be promoted,
561 that's why we need the other tables to exist */
562 w_man = wpawn;
563 for(b1_man = bknight; b1_man <= bbishop; b1_man += 2)
564 {
565 if(section_map[section_trans[w_man]][section_trans[b1_man]] == -1) continue;
566 printf("Generating %c vs %c ",
567 xpiece_char[w_man], xpiece_char[b1_man]);
568
569 base_addr = two_piece_data
570 + (section_map[section_trans[w_man]][section_trans[b1_man]] * TWO_PIECE_SIZE);
571
572 gen_2piece(w_man, b1_man, base_addr);
573 }
574
575 /* finally, pawn vs pawn */
576 printf("Generating %c vs %c ",
577 xpiece_char[wpawn], xpiece_char[bpawn]);
578
579 base_addr = two_piece_data
580 + (section_map[section_trans[wpawn]][section_trans[bpawn]]*TWO_PIECE_SIZE);
581
582 gen_2piece(wpawn, bpawn, base_addr);
583
584 if(save_2piece())
585 printf("Saved two-piece tables in %s\n", TWO_PIECE_FILE);
586
587 /* now, start doing pawnless three-piece tables */
588
589 temp_table = malloc(THREE_PIECE_SIZE);
590
591 if(!temp_table) return;
592
593 for(w_man = wknight; w_man <= wbishop; w_man += 2)
594 for(b1_man = bknight; b1_man <= bbishop ; b1_man += 2)
595 for(b2_man = bknight; b2_man <= bbishop; b2_man += 2)
596 {
597 if(section_map[section_trans[b1_man]][section_trans[b2_man]] == -1) continue;
598
599 printf("Generating %c vs %c+%c ", xpiece_char[w_man],
600 xpiece_char[b1_man], xpiece_char[b2_man]);
601
602 temp_key = TABLE_KEY(section_trans[w_man],
603 section_trans[b1_man],
604 section_trans[b2_man]);
605 gen_3piece(w_man, b1_man, b2_man, temp_table);
606 save_3piece(w_man, b1_man, b2_man, temp_table);
607 }
608
609
610 /* white piece is a pawn */
611
612 w_man = wpawn;
613 for(b1_man = bknight; b1_man <= bbishop; b1_man += 2)
614 for(b2_man = bknight; b2_man <= bbishop; b2_man += 2)
615 {
616 if(section_map[section_trans[b1_man]][section_trans[b2_man]] == -1) continue;
617
618 printf("Generating %c vs %c+%c ", xpiece_char[w_man],
619 xpiece_char[b1_man], xpiece_char[b2_man]);
620
621 temp_key = TABLE_KEY(section_trans[w_man],
622 section_trans[b1_man],
623 section_trans[b2_man]);
624 gen_3piece(w_man, b1_man, b2_man, temp_table);
625 save_3piece(w_man, b1_man, b2_man, temp_table);
626 }
627
628 /* one black piece is a pawn */
629
630 for(w_man = wknight; w_man <= wbishop; w_man += 2)
631 {
632 b1_man = bpawn;
633
634 for(b2_man = wknight; b2_man <= bbishop; b2_man += 2)
635 {
636 printf("Generating %c vs %c+%c ", xpiece_char[w_man],
637 xpiece_char[b1_man], xpiece_char[b2_man]);
638
639 temp_key = TABLE_KEY(section_trans[w_man],
640 section_trans[b1_man],
641 section_trans[b2_man]);
642 gen_3piece(w_man, b1_man, b2_man, temp_table);
643 save_3piece(w_man, b1_man, b2_man, temp_table);
644 }
645 }
646
647 w_man = wpawn;
648 b1_man = bpawn;
649 for(b2_man = bknight; b2_man <= bbishop; b2_man += 2)
650 {
651 printf("Generating %c vs %c+%c ", xpiece_char[w_man],
652 xpiece_char[b1_man], xpiece_char[b2_man]);
653
654 temp_key = TABLE_KEY(section_trans[w_man],
655 section_trans[b1_man],
656 section_trans[b2_man]);
657 gen_3piece(w_man, b1_man, b2_man, temp_table);
658 save_3piece(w_man, b1_man, b2_man, temp_table);
659 }
660
661 /* both black pieces are pawns */
662
663 for(w_man = wknight; w_man <= wbishop; w_man += 2)
664 {
665 b1_man = bpawn;
666 b2_man = bpawn;
667
668 printf("Generating %c vs %c+%c ", xpiece_char[w_man],
669 xpiece_char[b1_man], xpiece_char[b2_man]);
670
671 temp_key = TABLE_KEY(section_trans[w_man],
672 section_trans[b1_man],
673 section_trans[b2_man]);
674 gen_3piece(w_man, b1_man, b2_man, temp_table);
675 save_3piece(w_man, b1_man, b2_man, temp_table);
676 }
677
678 /* three pawns */
679
680 w_man = wpawn;
681 b1_man = bpawn;
682 b2_man = bpawn;
683
684 printf("Generating %c vs %c+%c ", xpiece_char[w_man],
685 xpiece_char[b1_man], xpiece_char[b2_man]);
686
687 temp_key = TABLE_KEY(section_trans[w_man],
688 section_trans[b1_man],
689 section_trans[b2_man]);
690 gen_3piece(w_man, b1_man, b2_man, temp_table);
691 save_3piece(w_man, b1_man, b2_man, temp_table);
692
693
694 printf("\nAll done.\n");
695 free(temp_table);
696
697 reset_board();
698 }
699
700
free_egtb()701 void free_egtb()
702 {
703 free(two_piece_data);
704 free(three_piece_data);
705 }
706
707
init_segtb()708 int init_segtb()
709 {
710 int i;
711
712 two_piece_data = malloc(21 * TWO_PIECE_SIZE);
713 three_piece_data = malloc(CACHE_SIZE * THREE_PIECE_SIZE);
714
715 if(!two_piece_data || !three_piece_data)
716 {
717 return FALSE;
718 }
719
720 if(!load_2piece())
721 {
722 return FALSE;
723 }
724
725 for(i = 0; i < CACHE_SIZE; i++)
726 {
727 table_cache[i].table_key = -1;
728 table_cache[i].last_access = 0;
729 }
730
731 cache_counter = 0;
732 temp_key = -1;
733
734 printf("Two-piece suicide endgame tables preloaded (using %d kB of memory)\n",
735 (21 * TWO_PIECE_SIZE) / 1024);
736 printf("Three-piece suicide endgame table cache %d kB\n",
737 (CACHE_SIZE * THREE_PIECE_SIZE) / 1024);
738
739 return TRUE;
740 }
741
742
egtb(int s)743 int egtb(int s)
744 {
745 int w1_man, w2_man, b1_man, b2_man;
746 int w1, w2, b1, b2;
747 int w_count = 0, b_count = 0;
748 int i, t, temp, junk, bpc;
749 signed char *table;
750
751 /* first figure out what kind of position we have */
752
753 for(i = 0; i < 64; i++)
754 {
755 bpc = board[upscale[i]];
756
757 if (bpc == npiece) continue;
758
759 if(bpc & 1)
760 {
761 if(!w_count)
762 {
763 w1_man = bpc;
764 w1 = i;
765 }
766 else
767 {
768 w2_man = bpc;
769 w2 = i;
770 }
771 w_count++;
772 }
773 else
774 {
775 if(!b_count)
776 {
777 b1_man = bpc;
778 b1 = i;
779 }
780 else
781 {
782 b2_man = bpc;
783 b2 = i;
784 }
785 b_count++;
786 }
787 }
788
789 /* two pieces? */
790
791 if(w_count == 1 && b_count == 1) {
792
793 if(section_map[section_trans[w1_man]][section_trans[b1_man]] == -1)
794 {
795 temp = b1_man;
796 b1_man = w1_man;
797 w1_man = temp;
798
799 temp = b1;
800
801 /* angrim: can do this without branch */
802
803 if(w1_man == wpawn || w1_man == bpawn)
804 {
805 /* pawn color was changed, we need to
806 rotate the board 180 degrees */
807 b1 = rotate[w1];
808 w1 = rotate[temp];
809 }
810 else
811 {
812 b1 = w1;
813 w1 = temp;
814 }
815
816 s ^= 1;
817 }
818
819 table = two_piece_data
820 + (section_map[section_trans[w1_man]][section_trans[b1_man]] * TWO_PIECE_SIZE);
821
822 /* flip the board if necessary */
823 if(white_addr[w1] == -1)
824 {
825 w1 = vertical_flip[w1];
826 b1 = vertical_flip[b1];
827 }
828
829 return (int)table[TWO_PIECE_HASH(s, white_addr[w1], b1)];
830
831
832 }
833 else if((w_count == 1 && b_count == 2) ||
834 (w_count == 2 && b_count == 1))
835 { /* three pieces */
836
837 if(w_count > 1)
838 { /* need to switch sides */
839
840 b2_man = w2_man;
841 temp = w1_man;
842 w1_man = b1_man;
843 b1_man = temp;
844
845 temp = w1;
846
847 if(w1_man == wpawn || w1_man == bpawn ||
848 b1_man == bpawn || b1_man == wpawn ||
849 b2_man == bpawn || b2_man == wpawn)
850 {
851 /* pawn color was changed, we need to
852 rotate the board 180 degrees */
853 b2 = rotate[w2];
854 w1 = rotate[b1];
855 b1 = rotate[temp];
856 }
857 else
858 {
859 b2 = w2;
860 w1 = b1;
861 b1 = temp;
862 }
863
864 s ^= 1;
865 }
866
867 /* swap black pieces if necessary */
868
869 if(section_map[section_trans[b1_man]][section_trans[b2_man]] == -1)
870 {
871
872 temp = b1_man;
873 b1_man = b2_man;
874 b2_man = temp;
875
876 temp = b1;
877 b1 = b2;
878 b2 = temp;
879 }
880
881 /* do the vertical flip */
882
883 if(white_addr[w1] == -1)
884 {
885 w1 = vertical_flip[w1];
886 b1 = vertical_flip[b1];
887 b2 = vertical_flip[b2];
888 }
889
890
891 /* finally, find the table we need either
892 from memory or disk and return the value */
893
894 t = TABLE_KEY(section_trans[w1_man],
895 section_trans[b1_man],
896 section_trans[b2_man]);
897
898 if(temp_key == t) /* maybe we're generating a table */
899 table = temp_table;
900 else
901 {
902 /* check the cache */
903
904 temp = INT_MAX;
905 cache_counter++;
906
907 for(i = 0; i < CACHE_SIZE; i++)
908 {
909 if(table_cache[i].table_key == t)
910 {
911 table = three_piece_data + (i * THREE_PIECE_SIZE);
912 table_cache[i].last_access = cache_counter;
913 return (int) table[THREE_PIECE_HASH(s, white_addr[w1], b1, b2)];
914 }
915 else if(table_cache[i].last_access < temp)
916 {
917 temp = table_cache[i].last_access;
918 junk = i;
919 }
920 }
921 /* the table was not in the cache, we'll load
922 it into the least recently accessed slot */
923
924 table = three_piece_data + (junk * THREE_PIECE_SIZE);
925
926 if(!load_3piece(w1_man, b1_man, b2_man, table))
927 {
928 //printf("Loading error\n");
929 table_cache[junk].table_key = -1;
930 return (-128);
931 }
932 table_cache[junk].table_key = t;
933 table_cache[junk].last_access = cache_counter;
934 }
935
936 return (int) table[THREE_PIECE_HASH(s, white_addr[w1], b1, b2)];
937
938 }
939 else
940 return (-128); /* position not in the tables */
941
942 }
943
load_2piece()944 int load_2piece()
945 {
946 int i,j;
947 FILE *f;
948 signed char *table;
949
950 if(!(f = fopen(TWO_PIECE_FILE, "r"))) return 0;
951
952 for(i = 0; i < 21; i++)
953 {
954 table = two_piece_data + i * TWO_PIECE_SIZE;
955
956 for(j = 0; j < TWO_PIECE_SIZE; j++)
957 table[j] = (signed char) fgetc(f);
958 }
959
960 fclose(f);
961 return 1;
962 }
963
load_3piece(int w1_man,int b1_man,int b2_man,signed char * t)964 int load_3piece(int w1_man, int b1_man, int b2_man, signed char *t)
965 {
966 FILE *f;
967 signed char fname[13];
968 signed char *buf;
969 int i;
970
971 /* generate the filename */
972
973 strcpy(fname, THREE_PIECE_FILE);
974 fname[4]= xpiece_char[w1_man];
975 fname[5]= xpiece_char[b1_man];
976 fname[6]= xpiece_char[b2_man];
977
978 if(!(f = fopen(fname,"r"))) return 0;
979
980 for(i = 0; i < THREE_PIECE_SIZE; i += IO_BUFSIZE)
981 {
982 buf = t + i;
983 if(!fread(buf, IO_BUFSIZE, 1, f)) {
984 printf("Error reading %s\n",fname);
985 fclose(f);
986 return 0;
987 }
988 }
989
990 fclose(f);
991 return 1;
992 }
993
994
995