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
46int 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
57int 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
70int 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
81int 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
92int 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
102int section_trans[] = {666, 0, 0, 1, 1, 5, 5, 3, 3, 4, 4, 2, 2, 6};
103char xpiece_char[] = {'F','P','P','N','N','K','K','R','R','Q','Q','B','B','E' };
104
105typedef struct
106{
107  int table_key;
108  int last_access;
109} cache_data;
110
111signed char *two_piece_data;
112signed char *three_piece_data;
113signed char *temp_table; /* used when generating new tables */
114
115int cache_counter;
116cache_data table_cache[CACHE_SIZE];
117int temp_key;
118
119int SEGTB;
120
121int 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
144int 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
176int 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
269void 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
370void 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
481int 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
503int 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
536void 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
701void free_egtb()
702{
703  free(two_piece_data);
704  free(three_piece_data);
705}
706
707
708int 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
743int 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
944int 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
964int 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