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