1 #include <stddef.h>
2 #include <math.h>
3 #include "chess.h"
4 #include "data.h"
5 #if defined(UNIX)
6 #  include <unistd.h>
7 #  include <sys/types.h>
8 #else
9 #  include <fcntl.h> /* needed for definition of "_O_BINARY" */
10 #endif
11 /*
12  *******************************************************************************
13  *                                                                             *
14  *   Initialize() performs routine initialization before anything else is      *
15  *   attempted.  It uses a group of service routines to initialize various     *
16  *   data structures that are needed before the engine can do anything at all. *
17  *                                                                             *
18  *******************************************************************************
19  */
Initialize()20 void Initialize() {
21   TREE *tree;
22   int j, v, major, id;
23 #if defined(UNIX)
24   int i, node;
25 #endif
26 
27   tree = block[0];
28   for (j = 1; j <= MAX_BLOCKS; j++)
29     block[j] = NULL;
30   InitializeMasks();
31   InitializeMagic();
32   InitializeSMP();
33   InitializeAttackBoards();
34   InitializePawnMasks();
35   InitializeChessBoard(tree);
36   InitializeKillers();
37 #if !defined(UNIX)
38   _fmode = _O_BINARY; /* set file mode binary to avoid text translation */
39 #endif
40 #if defined(EPD)
41   EGInit();
42 #endif
43   tree->last[0] = tree->move_list;
44   tree->last[1] = tree->move_list;
45   sprintf(log_filename, "%s/book.bin", book_path);
46   book_file = fopen(log_filename, "rb+");
47   if (!book_file) {
48     book_file = fopen(log_filename, "rb");
49     if (!book_file) {
50       Print(2048, "unable to open book file [%s/book.bin].\n", book_path);
51       Print(32, "book is disabled\n");
52     } else {
53       Print(2048, "unable to open book file [%s/book.bin] for \"write\".\n",
54           book_path);
55       Print(32, "learning is disabled\n");
56     }
57   }
58   sprintf(log_filename, "%s/books.bin", book_path);
59   normal_bs_file = fopen(log_filename, "rb");
60   books_file = normal_bs_file;
61   if (!normal_bs_file)
62     Print(32, "unable to open book file [%s/books.bin].\n", book_path);
63   sprintf(log_filename, "%s/bookc.bin", book_path);
64   computer_bs_file = fopen(log_filename, "rb");
65   if (computer_bs_file)
66     Print(32, "found computer opening book file [%s/bookc.bin].\n",
67         book_path);
68   if (book_file) {
69     int maj_min;
70     fseek(book_file, - (long) sizeof(int), SEEK_END);
71     v = fread(&maj_min, 4, 1, book_file);
72     if (v <= 0)
73       perror("Initialize() fread error: ");
74     major = BookIn32((unsigned char *) &maj_min);
75     major = major >> 16;
76     if (major < 23) {
77       Print(4095, "\nERROR!  book.bin not made by version 23.0 or later\n");
78       fclose(book_file);
79       fclose(books_file);
80       book_file = 0;
81       books_file = 0;
82     }
83   }
84   id = InitializeGetLogID();
85   sprintf(log_filename, "%s/log.%03d", log_path, id);
86   sprintf(history_filename, "%s/game.%03d", log_path, id);
87   log_file = fopen(log_filename, "w");
88   history_file = fopen(history_filename, "w+");
89   if (!history_file) {
90     printf("ERROR, unable to open game history file, exiting\n");
91     CraftyExit(1);
92   }
93   AlignedMalloc((void *) &hash_table, 64,
94       sizeof(HASH_ENTRY) * hash_table_size);
95   AlignedMalloc((void *) &hash_path, 64,
96       sizeof(HPATH_ENTRY) * hash_path_size);
97   AlignedMalloc((void *) &pawn_hash_table, 64,
98       sizeof(PAWN_HASH_ENTRY) * pawn_hash_table_size);
99   if (!hash_table) {
100     Print(2048,
101         "AlignedMalloc() failed, not enough memory (primary trans/ref table).\n");
102     hash_table_size = 0;
103     hash_table = 0;
104   }
105   if (!pawn_hash_table) {
106     Print(2048,
107         "AlignedMalloc() failed, not enough memory (pawn hash table).\n");
108     pawn_hash_table_size = 0;
109     pawn_hash_table = 0;
110   }
111 /*
112  ************************************************************
113  *                                                          *
114  *  Now for some NUMA stuff.  We need to allocate the local *
115  *  memory for each processor, but we can't touch it here   *
116  *  or it will be faulted in and be allocated on the        *
117  *  current CPU, which is not where it should be located    *
118  *  for optimal NUMA performance.  ThreadInit() will do the *
119  *  actual initialization after each new process is created *
120  *  so that the pages of local memory will be faulted in on *
121  *  the correct processor and use local node memory for     *
122  *  optimal performance.                                    *
123  *                                                          *
124  *  If we are using CPU affinity, we need to set this up    *
125  *  for thread 0 BEFORE we initialize the split blocks so   *
126  *  that they will page fault in on the correct NUMA node.  *
127  *                                                          *
128  ************************************************************
129  */
130 #if (CPUS > 1)
131   ThreadAffinity(smp_affinity);
132 #  if !defined(UNIX)
133   ThreadMalloc((int) 0);
134 #  else
135   for (i = 0; i < CPUS; i++) {
136     for (j = 0; j < 64; j++) {
137       AlignedMalloc((void **) &block[i * 64 + j + 1], 2048,
138           (size_t) sizeof(TREE));
139     }
140   }
141   for (i = 1; i < 64; i++) {
142     memset((char *) block[i], 0, sizeof(TREE));
143     LockInit(block[i]->lock);
144   }
145   for (node = 1; node < CPUS; node++) {
146     ThreadAffinity(node);
147     for (i = 0; i < 64; i++) {
148       memset((char *) block[node * 64 + i], 0, sizeof(TREE));
149       LockInit(block[node * 64 + i]->lock);
150     }
151   }
152   ThreadAffinity(0);
153 #  endif
154 #endif
155   thread[0].blocks = 0xffffffffffffffffull;
156   initialized_threads++;
157   InitializeHashTables(1);
158   InitializeKingSafety();
159   InitializeLMP();
160   InitializeLMR();
161 }
162 
163 /*
164  *******************************************************************************
165  *                                                                             *
166  *   InitializeAttackBoards() is used to initialize the basic bitboards that   *
167  *   deal with what squares a piece attacks.                                   *
168  *                                                                             *
169  *******************************************************************************
170  */
InitializeAttackBoards(void)171 void InitializeAttackBoards(void) {
172   int i, j, d, s, t, frank, ffile, trank, tfile;
173   int sq, lastsq;
174   static const int knightsq[8] = { -17, -15, -10, -6, 6, 10, 15, 17 };
175   static const int bishopsq[4] = { -9, -7, 7, 9 };
176   static const int rooksq[4] = { -8, -1, 1, 8 };
177   uint64_t sqs;
178 
179 /*
180  initialize pawn attack boards
181  */
182   for (i = 0; i < 64; i++) {
183     pawn_attacks[white][i] = 0;
184     if (i < 56)
185       for (j = 2; j < 4; j++) {
186         sq = i + bishopsq[j];
187         if (Abs(Rank(sq) - Rank(i)) == 1 && Abs(File(sq) - File(i)) == 1 &&
188             sq < 64 && sq > -1)
189           pawn_attacks[white][i] =
190               pawn_attacks[white][i] | (uint64_t) 1 << sq;
191       }
192     pawn_attacks[black][i] = 0;
193     if (i > 7)
194       for (j = 0; j < 2; j++) {
195         sq = i + bishopsq[j];
196         if (Abs(Rank(sq) - Rank(i)) == 1 && Abs(File(sq) - File(i)) == 1 &&
197             sq < 64 && sq > -1)
198           pawn_attacks[black][i] =
199               pawn_attacks[black][i] | (uint64_t) 1 << sq;
200       }
201   }
202 /*
203  initialize knight attack board
204  */
205   for (i = 0; i < 64; i++) {
206     knight_attacks[i] = 0;
207     frank = Rank(i);
208     ffile = File(i);
209     for (j = 0; j < 8; j++) {
210       sq = i + knightsq[j];
211       if (sq < 0 || sq > 63)
212         continue;
213       trank = Rank(sq);
214       tfile = File(sq);
215       if (Abs(frank - trank) > 2 || Abs(ffile - tfile) > 2)
216         continue;
217       knight_attacks[i] = knight_attacks[i] | (uint64_t) 1 << sq;
218     }
219   }
220 /*
221  initialize bishop/queen attack boards and masks
222  */
223   for (i = 0; i < 64; i++) {
224     for (j = 0; j < 4; j++) {
225       sq = i;
226       lastsq = sq;
227       sq = sq + bishopsq[j];
228       while (Abs(Rank(sq) - Rank(lastsq)) == 1 &&
229           Abs(File(sq) - File(lastsq)) == 1 && sq < 64 && sq > -1) {
230         if (bishopsq[j] == 7)
231           plus7dir[i] = plus7dir[i] | (uint64_t) 1 << sq;
232         else if (bishopsq[j] == 9)
233           plus9dir[i] = plus9dir[i] | (uint64_t) 1 << sq;
234         else if (bishopsq[j] == -7)
235           minus7dir[i] = minus7dir[i] | (uint64_t) 1 << sq;
236         else
237           minus9dir[i] = minus9dir[i] | (uint64_t) 1 << sq;
238         lastsq = sq;
239         sq = sq + bishopsq[j];
240       }
241     }
242   }
243   plus1dir[64] = 0;
244   plus7dir[64] = 0;
245   plus8dir[64] = 0;
246   plus9dir[64] = 0;
247   minus1dir[64] = 0;
248   minus7dir[64] = 0;
249   minus8dir[64] = 0;
250   minus9dir[64] = 0;
251 /*
252  initialize rook/queen attack boards
253  */
254   for (i = 0; i < 64; i++) {
255     for (j = 0; j < 4; j++) {
256       sq = i;
257       lastsq = sq;
258       sq = sq + rooksq[j];
259       while (((Abs(Rank(sq) - Rank(lastsq)) == 1 &&
260                   Abs(File(sq) - File(lastsq)) == 0)
261               || (Abs(Rank(sq) - Rank(lastsq)) == 0 &&
262                   Abs(File(sq) - File(lastsq)) == 1)) && sq < 64 && sq > -1) {
263         if (rooksq[j] == 1)
264           plus1dir[i] = plus1dir[i] | (uint64_t) 1 << sq;
265         else if (rooksq[j] == 8)
266           plus8dir[i] = plus8dir[i] | (uint64_t) 1 << sq;
267         else if (rooksq[j] == -1)
268           minus1dir[i] = minus1dir[i] | (uint64_t) 1 << sq;
269         else
270           minus8dir[i] = minus8dir[i] | (uint64_t) 1 << sq;
271         lastsq = sq;
272         sq = sq + rooksq[j];
273       }
274     }
275   }
276 /*
277  initialize bishop attack board
278  */
279   for (i = 0; i < 64; i++) {
280     bishop_attacks[i] =
281         plus9dir[i] | minus9dir[i] | plus7dir[i] | minus7dir[i];
282   }
283 /*
284  initialize rook attack board
285  */
286   for (i = 0; i < 64; i++) {
287     rook_attacks[i] = file_mask[File(i)] | rank_mask[Rank(i)];
288   }
289 /*
290  initialize king attack board
291  */
292   for (i = 0; i < 64; i++) {
293     king_attacks[i] = 0;
294     for (j = 0; j < 64; j++) {
295       if (Distance(i, j) == 1)
296         king_attacks[i] = king_attacks[i] | SetMask(j);
297     }
298   }
299 /*
300  directions[sq1][sq2] gives the "move direction" to move from
301  sq1 to sq2.  intervening[sq1][sq2] gives a bit vector that indicates
302  which squares must be unoccupied in order for <sq1> to attack <sq2>,
303  assuming a sliding piece is involved.  To use this, you simply have
304  to Or(intervening[sq1][sq2],occupied_squares) and if the result is
305  "0" then a sliding piece on sq1 would attack sq2 and vice-versa.
306  */
307   for (i = 0; i < 64; i++) {
308     for (j = 0; j < 64; j++)
309       intervening[i][j] = 0;
310     sqs = plus1dir[i];
311     while (sqs) {
312       j = LSB(sqs);
313       directions[i][j] = 1;
314       intervening[i][j] = plus1dir[i] ^ plus1dir[j - 1];
315       sqs &= sqs - 1;
316     }
317     sqs = plus7dir[i];
318     while (sqs) {
319       j = LSB(sqs);
320       directions[i][j] = 7;
321       intervening[i][j] = plus7dir[i] ^ plus7dir[j - 7];
322       sqs &= sqs - 1;
323     }
324     sqs = plus8dir[i];
325     while (sqs) {
326       j = LSB(sqs);
327       directions[i][j] = 8;
328       intervening[i][j] = plus8dir[i] ^ plus8dir[j - 8];
329       sqs &= sqs - 1;
330     }
331     sqs = plus9dir[i];
332     while (sqs) {
333       j = LSB(sqs);
334       directions[i][j] = 9;
335       intervening[i][j] = plus9dir[i] ^ plus9dir[j - 9];
336       sqs &= sqs - 1;
337     }
338     sqs = minus1dir[i];
339     while (sqs) {
340       j = LSB(sqs);
341       directions[i][j] = -1;
342       intervening[i][j] = minus1dir[i] ^ minus1dir[j + 1];
343       sqs &= sqs - 1;
344     }
345     sqs = minus7dir[i];
346     while (sqs) {
347       j = LSB(sqs);
348       directions[i][j] = -7;
349       intervening[i][j] = minus7dir[i] ^ minus7dir[j + 7];
350       sqs &= sqs - 1;
351     }
352     sqs = minus8dir[i];
353     while (sqs) {
354       j = LSB(sqs);
355       directions[i][j] = -8;
356       intervening[i][j] = minus8dir[i] ^ minus8dir[j + 8];
357       sqs &= sqs - 1;
358     }
359     sqs = minus9dir[i];
360     while (sqs) {
361       j = LSB(sqs);
362       directions[i][j] = -9;
363       intervening[i][j] = minus9dir[i] ^ minus9dir[j + 9];
364       sqs &= sqs - 1;
365     }
366   }
367 /*
368   distance_ring[square][distance] has a ring of 1's around "square" with a
369   distance of "distance".  IE for e4, we have a ring of adjacent squares
370   [e4][1], the next ring (2 squares away) for [e4][2], etc.  In this code,
371   s = square being set up, d = distance from square to "ring" and t = target
372   square that is on the ring if distance is correct.
373  */
374   for (s = 0; s < 64; s++) {
375     distance_ring[s][0] = SetMask(s);
376     for (d = 1; d < 8; d++) {
377       distance_ring[s][d] = 0;
378       for (t = 0; t < 64; t++)
379         if (Distance(s, t) == d)
380           distance_ring[s][d] |= SetMask(t);
381     }
382   }
383 }
384 
385 /*
386  *******************************************************************************
387  *                                                                             *
388  *   InitializeMagic() initializes the magic number tables used in the new     *
389  *   magic move generation algorithm.  We also initialize a set of parallel    *
390  *   tables that contain mobility scores for each possible set of magic attack *
391  *   vectors, which saves significant time in the evaluation, since it is done *
392  *   here before the game actually starts.                                     *
393  *                                                                             *
394  *******************************************************************************
395  */
InitializeMagic(void)396 void InitializeMagic(void) {
397   int i, j, m;
398   int initmagicmoves_bitpos64_database[64] = {
399     63, 0, 58, 1, 59, 47, 53, 2,
400     60, 39, 48, 27, 54, 33, 42, 3,
401     61, 51, 37, 40, 49, 18, 28, 20,
402     55, 30, 34, 11, 43, 14, 22, 4,
403     62, 57, 46, 52, 38, 26, 32, 41,
404     50, 36, 17, 19, 29, 10, 13, 21,
405     56, 45, 25, 31, 35, 16, 9, 12,
406     44, 24, 15, 8, 23, 7, 6, 5
407   };
408 /*
409  Bishop attacks and mobility
410  */
411   for (i = 0; i < 64; i++) {
412     int squares[64];
413     int numsquares = 0;
414     uint64_t temp = magic_bishop_mask[i];
415 
416     while (temp) {
417       uint64_t abit = temp & -temp;
418 
419       squares[numsquares++] =
420           initmagicmoves_bitpos64_database[(abit *
421               0x07EDD5E59A4E28C2ull) >> 58];
422       temp ^= abit;
423     }
424     for (temp = 0; temp < (uint64_t) 1 << numsquares; temp++) {
425       uint64_t moves;
426       uint64_t tempoccupied =
427           InitializeMagicOccupied(squares, numsquares, temp);
428       moves = InitializeMagicBishop(i, tempoccupied);
429       *(magic_bishop_indices[i] +
430           (tempoccupied * magic_bishop[i] >> magic_bishop_shift[i])) = moves;
431       moves |= SetMask(i);
432       m = -lower_b;
433       for (j = 0; j < 4; j++)
434         m += PopCnt(moves & mobility_mask_b[j]) * mobility_score_b[j];
435       if (m < 0)
436         m *= 2;
437       *(magic_bishop_mobility_indices[i] +
438           (tempoccupied * magic_bishop[i] >> magic_bishop_shift[i])) = m;
439     }
440   }
441 /*
442  Rook attacks and mobility
443  */
444   for (i = 0; i < 64; i++) {
445     int squares[64];
446     int numsquares = 0;
447     uint64_t temp = magic_rook_mask[i];
448 
449     while (temp) {
450       uint64_t abit = temp & -temp;
451 
452       squares[numsquares++] =
453           initmagicmoves_bitpos64_database[(abit *
454               0x07EDD5E59A4E28C2ull) >> 58];
455       temp ^= abit;
456     }
457     for (temp = 0; temp < (uint64_t) 1 << numsquares; temp++) {
458       uint64_t tempoccupied =
459           InitializeMagicOccupied(squares, numsquares, temp);
460       uint64_t moves = InitializeMagicRook(i, tempoccupied);
461       *(magic_rook_indices[i] +
462           (tempoccupied * magic_rook[i] >> magic_rook_shift[i])) = moves;
463       moves |= SetMask(i);
464       m = -1;
465       for (j = 0; j < 4; j++)
466         m += PopCnt(moves & mobility_mask_r[j]) * mobility_score_r[j];
467       *(magic_rook_mobility_indices[i] +
468           (tempoccupied * magic_rook[i] >> magic_rook_shift[i])) =
469           mob_curve_r[m];
470     }
471   }
472 }
473 
474 /*
475  *******************************************************************************
476  *                                                                             *
477  *   InitializeMagicBishop() does the bishop-specific initialization for a     *
478  *   particular square on the board.                                           *
479  *                                                                             *
480  *******************************************************************************
481  */
InitializeMagicBishop(int square,uint64_t occupied)482 uint64_t InitializeMagicBishop(int square, uint64_t occupied) {
483   uint64_t ret = 0;
484   uint64_t abit;
485   uint64_t abit2;
486   uint64_t rowbits = (uint64_t) 0xFF << 8 * (square / 8);
487 
488   abit = (uint64_t) 1 << square;
489   abit2 = abit;
490   do {
491     abit <<= 8 - 1;
492     abit2 >>= 1;
493     if (abit2 & rowbits)
494       ret |= abit;
495     else
496       break;
497   } while (abit && !(abit & occupied));
498   abit = (uint64_t) 1 << square;
499   abit2 = abit;
500   do {
501     abit <<= 8 + 1;
502     abit2 <<= 1;
503     if (abit2 & rowbits)
504       ret |= abit;
505     else
506       break;
507   } while (abit && !(abit & occupied));
508   abit = (uint64_t) 1 << square;
509   abit2 = abit;
510   do {
511     abit >>= 8 - 1;
512     abit2 <<= 1;
513     if (abit2 & rowbits)
514       ret |= abit;
515     else
516       break;
517   } while (abit && !(abit & occupied));
518   abit = (uint64_t) 1 << square;
519   abit2 = abit;
520   do {
521     abit >>= 8 + 1;
522     abit2 >>= 1;
523     if (abit2 & rowbits)
524       ret |= abit;
525     else
526       break;
527   } while (abit && !(abit & occupied));
528   return ret;
529 }
530 
531 /*
532  *******************************************************************************
533  *                                                                             *
534  *   InitializeMagicOccupied() generates a specific occupied-square bitboard   *
535  *   needed during initialization.                                             *
536  *                                                                             *
537  *******************************************************************************
538  */
InitializeMagicOccupied(int * squares,int numSquares,uint64_t linoccupied)539 uint64_t InitializeMagicOccupied(int *squares, int numSquares,
540     uint64_t linoccupied) {
541   int i;
542   uint64_t ret = 0;
543 
544   for (i = 0; i < numSquares; i++)
545     if (linoccupied & (uint64_t) 1 << i)
546       ret |= (uint64_t) 1 << squares[i];
547   return ret;
548 }
549 
550 /*
551  *******************************************************************************
552  *                                                                             *
553  *   InitializeMagicRook() does the rook-specific initialization for a         *
554  *   particular square on the board.                                           *
555  *                                                                             *
556  *******************************************************************************
557  */
InitializeMagicRook(int square,uint64_t occupied)558 uint64_t InitializeMagicRook(int square, uint64_t occupied) {
559   uint64_t ret = 0;
560   uint64_t abit;
561   uint64_t rowbits = (uint64_t) 0xFF << 8 * (square / 8);
562 
563   abit = (uint64_t) 1 << square;
564   do {
565     abit <<= 8;
566     ret |= abit;
567   } while (abit && !(abit & occupied));
568   abit = (uint64_t) 1 << square;
569   do {
570     abit >>= 8;
571     ret |= abit;
572   } while (abit && !(abit & occupied));
573   abit = (uint64_t) 1 << square;
574   do {
575     abit <<= 1;
576     if (abit & rowbits)
577       ret |= abit;
578     else
579       break;
580   } while (!(abit & occupied));
581   abit = (uint64_t) 1 << square;
582   do {
583     abit >>= 1;
584     if (abit & rowbits)
585       ret |= abit;
586     else
587       break;
588   } while (!(abit & occupied));
589   return ret;
590 }
591 
592 /*
593  *******************************************************************************
594  *                                                                             *
595  *   InitializeChessBoard() initializes the chess board to the normal starting *
596  *   position.  It then calls SetChessBitboards() to correctly set the usual   *
597  *   occupied-square bitboards to correspond to the starting position.         *
598  *                                                                             *
599  *******************************************************************************
600  */
InitializeChessBoard(TREE * tree)601 void InitializeChessBoard(TREE * tree) {
602   int i;
603 
604   if (strlen(initial_position)) {
605     int nargs;
606 
607     nargs = ReadParse(initial_position, args, " \t;");
608     SetBoard(tree, nargs, args, 1);
609   } else {
610     for (i = 0; i < 64; i++)
611       PcOnSq(i) = empty;
612     game_wtm = 1;
613 /*
614  place pawns
615  */
616     for (i = 0; i < 8; i++) {
617       PcOnSq(i + 8) = pawn;
618       PcOnSq(i + 48) = -pawn;
619     }
620 /*
621  place knights
622  */
623     PcOnSq(B1) = knight;
624     PcOnSq(G1) = knight;
625     PcOnSq(B8) = -knight;
626     PcOnSq(G8) = -knight;
627 /*
628  place bishops
629  */
630     PcOnSq(C1) = bishop;
631     PcOnSq(F1) = bishop;
632     PcOnSq(C8) = -bishop;
633     PcOnSq(F8) = -bishop;
634 /*
635  place rooks
636  */
637     PcOnSq(A1) = rook;
638     PcOnSq(H1) = rook;
639     PcOnSq(A8) = -rook;
640     PcOnSq(H8) = -rook;
641 /*
642  place queens
643  */
644     PcOnSq(D1) = queen;
645     PcOnSq(D8) = -queen;
646 /*
647  place kings
648  */
649     PcOnSq(E1) = king;
650     PcOnSq(E8) = -king;
651 /*
652  initialize castling status so all castling is legal.
653  */
654     Castle(0, black) = 3;
655     Castle(0, white) = 3;
656 /*
657  initialize enpassant status.
658  */
659     EnPassant(0) = 0;
660 /*
661  now, set the bit-boards.
662  */
663     SetChessBitBoards(tree);
664   }
665 /*
666  initialize 50 move counter and repetition list/index.
667  */
668   Reversible(0) = 0;
669   rep_index = 0;
670   tree->rep_list[0] = HashKey;
671 }
672 
673 /*
674  *******************************************************************************
675  *                                                                             *
676  *   SetChessBitBoards() is used to set the occupied-square bitboards so that  *
677  *   they agree with the current real chessboard.                              *
678  *                                                                             *
679  *******************************************************************************
680  */
SetChessBitBoards(TREE * tree)681 void SetChessBitBoards(TREE * tree) {
682   int side, piece, square;
683 
684   HashKey = 0;
685   PawnHashKey = 0;
686   Material = 0;
687   for (side = black; side <= white; side++)
688     for (piece = empty; piece <= king; piece++)
689       Pieces(side, piece) = 0;
690   for (square = 0; square < 64; square++) {
691     if (!PcOnSq(square))
692       continue;
693     piece = PcOnSq(square);
694     side = (piece > 0) ? 1 : 0;
695     Pieces(side, Abs(piece)) |= SetMask(square);
696     Occupied(side) |= SetMask(square);
697     Hash(side, Abs(piece), square);
698     if (Abs(piece) == pawn)
699       HashP(side, square);
700     Material += PieceValues(side, Abs(piece));
701   }
702   if (Pieces(white, king))
703     KingSQ(white) = LSB(Pieces(white, king));
704   if (Pieces(black, king))
705     KingSQ(black) = LSB(Pieces(black, king));
706   if (EnPassant(0))
707     HashEP(EnPassant(0));
708   if (!(Castle(0, white) & 1))
709     HashCastle(0, white);
710   if (!(Castle(0, white) & 2))
711     HashCastle(1, white);
712   if (!(Castle(0, black) & 1))
713     HashCastle(0, black);
714   if (!(Castle(0, black) & 2))
715     HashCastle(1, black);
716 /*
717  initialize black/white piece counts.
718  */
719   for (side = black; side <= white; side++)
720     for (piece = pawn; piece <= king; piece++)
721       TotalPieces(side, piece) = PopCnt(Pieces(side, piece));
722   for (side = black; side <= white; side++) {
723     TotalPieces(side, occupied) = 0;
724     for (piece = knight; piece < king; piece++)
725       TotalPieces(side, occupied) +=
726           PopCnt(Pieces(side, piece)) * p_vals[piece];
727   }
728   TotalAllPieces = PopCnt(OccupiedSquares);
729   rep_index = 0;
730   tree->rep_list[0] = HashKey;
731 }
732 
733 /*
734  *******************************************************************************
735  *                                                                             *
736  *   InitializeGetLogID() is used to determine the nnn (in log.nnn) to use for *
737  *   the current game.  It is typically the ID of the last log + 1, but we do  *
738  *   not know what that is if we just started the engine.  We simply look thru *
739  *   existing log files in the current directory and use the next un-used name *
740  *   in sequence.                                                              *
741  *                                                                             *
742  *******************************************************************************
743  */
InitializeGetLogID(void)744 int InitializeGetLogID(void) {
745   int t, total_files = 0;
746 #if defined(UNIX)
747   struct stat *fileinfo = malloc(sizeof(struct stat));
748 #endif
749 
750   for (; total_files < 300; log_id++) {
751     sprintf(log_filename, "%s/log.%03d", log_path, log_id);
752     sprintf(history_filename, "%s/game.%03d", log_path, log_id);
753     log_file = fopen(log_filename, "r");
754     if (!log_file)
755       break;
756     fclose(log_file);
757     total_files++;
758   }
759 #if defined(UNIX)
760 /*  a kludge to work around an xboard 4.2.3 problem.  It sends two "quit"
761    commands, which causes every other log.nnn file to be empty.  this code
762    looks for a very small log.nnn file as the last one, and if it is small,
763    then we simply overwrite it to solve this problem temporarily.  this will
764    be removed when the nexto xboard version comes out to fix this extra quit
765    problem.                                                                  */
766   {
767     char tfn[128];
768     FILE *tlog;
769 
770     sprintf(tfn, "%s/log.%03d", log_path, log_id - 1);
771     tlog = fopen(tfn, "r+");
772     if (tlog) {
773       fstat(fileno(tlog), fileinfo);
774       if (fileinfo->st_size < 2000)
775         log_id--;
776     }
777   }
778 #endif
779   t = log_id++;
780   return t;
781 }
782 
783 /*
784  *******************************************************************************
785  *                                                                             *
786  *   InitializeHashTables() is used to clear all hash entries completely, so   *
787  *   that no old information remains to interefere with a new game or test     *
788  *   position.                                                                 *
789  *                                                                             *
790  *   Whenever any hash table size is changed, they are initialized by calling  *
791  *   this procedure to make sure that in the case of NUMA hardware, the trick  *
792  *   explained below is always executed.                                       *
793  *                                                                             *
794  *   This code uses the NUMA fix when using MT threads.  It clears size / MT   *
795  *   bytes per cpu, after pinning the current thread to the correct cpu, so    *
796  *   that the data will fault in to the correct NUMA node.  If the size is not *
797  *   perfectly divisible by MT (max threads) it clears the final piece at the  *
798  *   end of each loop.                                                         *
799  *                                                                             *
800  *   Note that if no size has changed, (fault_in = 0) then we skip the NUMA    *
801  *   stuff and just clear the tables, period.                                  *
802  *                                                                             *
803  *******************************************************************************
804  */
InitializeHashTables(int fault_in)805 void InitializeHashTables(int fault_in) {
806   uint64_t mem_per_node;
807   int node;
808 
809   transposition_age = 0;
810   if (fault_in && smp_numa) {
811 /*
812  ************************************************************
813  *                                                          *
814  *  First, initialize the primary transposition/refutation  *
815  *  (hash) table, using the NUMA trick to place part of     *
816  *  the trans/ref on each node of the NUMA system.          *
817  *                                                          *
818  ************************************************************
819  */
820     mem_per_node =
821         hash_table_size * sizeof(HASH_ENTRY) / Max(smp_max_threads, 1);
822     for (node = 0; node < smp_max_threads; node++) {
823       ThreadAffinity(node);
824       memset((char *) hash_table + node * mem_per_node, 0, mem_per_node);
825     }
826     ThreadAffinity(0);
827     if (mem_per_node * Max(smp_max_threads,
828             1) < hash_table_size * sizeof(HASH_ENTRY))
829       memset((char *) hash_table + smp_max_threads * mem_per_node, 0,
830           hash_table_size * sizeof(HASH_ENTRY) -
831           mem_per_node * smp_max_threads);
832 /*
833  ************************************************************
834  *                                                          *
835  *  Second, initialize the primary hash path table, using   *
836  *  the NUMA trick to place part of the hash path table on  *
837  *  each node of the NUMA system.                           *
838  *                                                          *
839  ************************************************************
840  */
841     mem_per_node =
842         hash_path_size * sizeof(HPATH_ENTRY) / Max(smp_max_threads, 1);
843     for (node = 0; node < smp_max_threads; node++) {
844       ThreadAffinity(node);
845       memset((char *) hash_path + node * mem_per_node, 0, mem_per_node);
846     }
847     ThreadAffinity(0);
848     if (mem_per_node * Max(smp_max_threads,
849             1) < hash_path_size * sizeof(HPATH_ENTRY))
850       memset((char *) hash_path + smp_max_threads * mem_per_node, 0,
851           hash_path_size * sizeof(HPATH_ENTRY) -
852           mem_per_node * smp_max_threads);
853 /*
854  ************************************************************
855  *                                                          *
856  *  Finally, initialize the primary pawn hash table, using  *
857  *  the NUMA trick to place part of the pawn hash table on  *
858  *  each node of the NUMA system.                           *
859  *                                                          *
860  ************************************************************
861  */
862     mem_per_node =
863         pawn_hash_table_size * sizeof(PAWN_HASH_ENTRY) / Max(smp_max_threads,
864         1);
865     for (node = 0; node < smp_max_threads; node++) {
866       ThreadAffinity(node);
867       memset((char *) pawn_hash_table + node * mem_per_node, 0, mem_per_node);
868     }
869     ThreadAffinity(0);
870     if (mem_per_node * Max(smp_max_threads,
871             1) < pawn_hash_table_size * sizeof(PAWN_HASH_ENTRY))
872       memset((char *) pawn_hash_table + smp_max_threads * mem_per_node, 0,
873           pawn_hash_table_size * sizeof(PAWN_HASH_ENTRY) -
874           mem_per_node * smp_max_threads);
875 /*
876  ************************************************************
877  *                                                          *
878  *  Before we return, we need to re-pin this thread to the  *
879  *  correct processor.                                      *
880  *                                                          *
881  ************************************************************
882  */
883     ThreadAffinity(smp_affinity);
884   } else {
885 /*
886  ************************************************************
887  *                                                          *
888  *  Otherwise we only need to use memset() to clear the     *
889  *  tables since they have already been faulted in to the   *
890  *  correct NUMA node.                                      *
891  *                                                          *
892  ************************************************************
893  */
894     memset((char *) hash_table, 0, hash_table_size * sizeof(HASH_ENTRY));
895     memset((char *) hash_path, 0, hash_path_size * sizeof(HPATH_ENTRY));
896     memset((char *) pawn_hash_table, 0,
897         pawn_hash_table_size * sizeof(PAWN_HASH_ENTRY));
898   }
899 }
900 
901 /*
902  *******************************************************************************
903  *                                                                             *
904  *   InitializeKillers() is used to zero the killer moves so that old killers  *
905  *   don't screw up ordering while processing test suites.  Ditto for history  *
906  *   counters.                                                                 *
907  *                                                                             *
908  *******************************************************************************
909  */
InitializeKillers(void)910 void InitializeKillers(void) {
911   int i;
912 
913   for (i = 0; i < MAXPLY; i++) {
914     block[0]->killers[i].move1 = 0;
915     block[0]->killers[i].move2 = 0;
916   }
917   for (i = 0; i < 1024; i++)
918     history[i] = 1024;
919 }
920 
921 /*
922  *******************************************************************************
923  *                                                                             *
924  *   InitializeMasks() is used to initialize the various bitboard masks that   *
925  *   are used throughout Crafty.                                               *
926  *                                                                             *
927  *******************************************************************************
928  */
InitializeMasks(void)929 void InitializeMasks(void) {
930   int i, j;
931 
932 /*
933  masks to set/clear a bit on a specific square
934  */
935   for (i = 0; i < 64; i++) {
936     ClearMask(i) = ~((uint64_t) 1 << i);
937     SetMask(i) = (uint64_t) 1 << i;
938   }
939   ClearMask(BAD_SQUARE) = 0;
940   SetMask(BAD_SQUARE) = 0;
941 /*
942  masks to select bits on a specific rank or file
943  */
944   rank_mask[0] = (uint64_t) 255;
945   for (i = 1; i < 8; i++)
946     rank_mask[i] = rank_mask[i - 1] << 8;
947   file_mask[FILEA] = (uint64_t) 1;
948   for (i = 1; i < 8; i++)
949     file_mask[FILEA] = file_mask[FILEA] | file_mask[FILEA] << 8;
950   for (i = 1; i < 8; i++)
951     file_mask[i] = file_mask[i - 1] << 1;
952 /*
953  masks to determine if a pawn has nearby neighbors or not.
954  */
955 #if !defined(INLINEASM)
956   msb[0] = 64;
957   lsb[0] = 16;
958   for (i = 1; i < 65536; i++) {
959     lsb[i] = 16;
960     for (j = 0; j < 16; j++)
961       if (i & (1 << j)) {
962         msb[i] = j;
963         if (lsb[i] == 16)
964           lsb[i] = j;
965       }
966   }
967 #endif
968   msb_8bit[0] = 8;
969   lsb_8bit[0] = 8;
970   pop_cnt_8bit[0] = 0;
971   for (i = 1; i < 256; i++) {
972     pop_cnt_8bit[i] = 0;
973     for (j = 0; j < 8; j++)
974       if (i & (1 << j))
975         pop_cnt_8bit[i]++;
976     lsb_8bit[i] = 8;
977     for (j = 0; j < 8; j++) {
978       if (i & (1 << j)) {
979         msb_8bit[i] = j;
980         if (lsb_8bit[i] == 8)
981           lsb_8bit[i] = j;
982       }
983     }
984   }
985 }
986 
987 /*
988  *******************************************************************************
989  *                                                                             *
990  *   InitializePawnMasks() is used to initialize the various bitboard masks    *
991  *   that are used in pawn evaluation.                                         *
992  *                                                                             *
993  *******************************************************************************
994  */
InitializePawnMasks(void)995 void InitializePawnMasks(void) {
996   int i, j;
997 
998 /*
999  initialize isolated pawn masks, which are nothing more than 1's on
1000  the files adjacent to the pawn file.
1001  */
1002   for (i = 0; i < 64; i++) {
1003     if (!File(i))
1004       mask_pawn_isolated[i] = file_mask[File(i) + 1];
1005     else if (File(i) == 7)
1006       mask_pawn_isolated[i] = file_mask[File(i) - 1];
1007     else
1008       mask_pawn_isolated[i] = file_mask[File(i) - 1] | file_mask[File(i) + 1];
1009   }
1010 /*
1011  initialize passed pawn masks, which are nothing more than 1's on
1012  the pawn's file and the adjacent files, but only on ranks that are
1013  in "front" of the pawn.
1014  */
1015   for (i = 0; i < 64; i++) {
1016     if (!File(i)) {
1017       mask_passed[white][i] = plus8dir[i] | plus8dir[i + 1];
1018       mask_passed[black][i] = minus8dir[i] | minus8dir[i + 1];
1019     } else if (File(i) == 7) {
1020       mask_passed[white][i] = plus8dir[i - 1] | plus8dir[i];
1021       mask_passed[black][i] = minus8dir[i - 1] | minus8dir[i];
1022     } else {
1023       mask_passed[white][i] = plus8dir[i - 1] | plus8dir[i] | plus8dir[i + 1];
1024       mask_passed[black][i] =
1025           minus8dir[i - 1] | minus8dir[i] | minus8dir[i + 1];
1026     }
1027   }
1028 /*
1029  masks to determine if a pawn has supporting contact with friendly pawns.
1030  */
1031   for (i = 8; i < 56; i++) {
1032     if (File(i) > 0 && File(i) < 7) {
1033       mask_pawn_connected[white][i] =
1034           SetMask(i - 1) | SetMask(i + 1) | SetMask(i - 9) | SetMask(i - 7);
1035       mask_pawn_connected[black][i] =
1036           SetMask(i - 1) | SetMask(i + 1) | SetMask(i + 9) | SetMask(i + 7);
1037     } else if (File(i) == 0) {
1038       mask_pawn_connected[white][i] = SetMask(i + 1) | SetMask(i - 7);
1039       mask_pawn_connected[black][i] = SetMask(i + 1) | SetMask(i + 9);
1040     } else if (File(i) == 7) {
1041       mask_pawn_connected[white][i] = SetMask(i - 1) | SetMask(i - 9);
1042       mask_pawn_connected[black][i] = SetMask(i - 1) | SetMask(i + 7);
1043     }
1044   }
1045 /*
1046  these masks are used to determine if the other side has any pawns
1047  that can attack [square].
1048  */
1049   for (i = 8; i < 56; i++) {
1050     if (!File(i)) {
1051       mask_pattacks[white][i] = minus8dir[i + 1];
1052       mask_pattacks[black][i] = plus8dir[i + 1];
1053     } else if (File(i) == 7) {
1054       mask_pattacks[white][i] = minus8dir[i - 1];
1055       mask_pattacks[black][i] = plus8dir[i - 1];
1056     } else {
1057       mask_pattacks[white][i] = minus8dir[i - 1] | minus8dir[i + 1];
1058       mask_pattacks[black][i] = plus8dir[i + 1] | plus8dir[i - 1];
1059     }
1060   }
1061 /*
1062  enpassant pawns are on either file adjacent to the current file, and
1063  on the same rank.
1064  */
1065   for (i = 0; i < 64; i++)
1066     mask_eptest[i] = 0;
1067   for (i = 25; i < 31; i++)
1068     mask_eptest[i] = SetMask(i - 1) | SetMask(i + 1);
1069   for (i = 33; i < 39; i++)
1070     mask_eptest[i] = SetMask(i - 1) | SetMask(i + 1);
1071   mask_eptest[A4] = SetMask(B4);
1072   mask_eptest[H4] = SetMask(G4);
1073   mask_eptest[A5] = SetMask(B5);
1074   mask_eptest[H5] = SetMask(G5);
1075 /*
1076  Initialize masks used to evaluate pawn races.  These masks are
1077  used to determine if the opposing king is in a position to stop a
1078  passed pawn from racing down and queening.  The data is organized
1079  as pawn_race[side][onmove][square], where side is black or white,
1080  and onmove indicates which side is to move for proper tempo
1081  evaluation.
1082  */
1083   for (i = 0; i < 64; i++) {
1084     pawn_race[white][white][i] = 0;
1085     pawn_race[white][black][i] = 0;
1086     pawn_race[black][white][i] = 0;
1087     pawn_race[black][black][i] = 0;
1088   }
1089   for (j = 8; j < 56; j++) {
1090     for (i = 0; i < 64; i++) {
1091 /* white pawn, wtm */
1092       if (j < 16) {
1093         if (KingPawnSquare(j + 8, i, File(j) + 56, 1))
1094           pawn_race[white][white][j] |= SetMask(i);
1095       } else {
1096         if (KingPawnSquare(j, i, File(j) + 56, 1))
1097           pawn_race[white][white][j] |= SetMask(i);
1098       }
1099 /* white pawn, btm */
1100       if (j < 16) {
1101         if (KingPawnSquare(j + 8, i, File(j) + 56, 0))
1102           pawn_race[white][black][j] |= SetMask(i);
1103       } else {
1104         if (KingPawnSquare(j, i, File(j) + 56, 0))
1105           pawn_race[white][black][j] |= SetMask(i);
1106       }
1107 /* black pawn, wtm */
1108       if (j > 47) {
1109         if (KingPawnSquare(j - 8, i, File(j), 0))
1110           pawn_race[black][white][j] |= SetMask(i);
1111       } else {
1112         if (KingPawnSquare(j, i, File(j), 0))
1113           pawn_race[black][white][j] |= SetMask(i);
1114       }
1115 /* black pawn, btm */
1116       if (j > 47) {
1117         if (KingPawnSquare(j - 8, i, File(j), 1))
1118           pawn_race[black][black][j] |= SetMask(i);
1119       } else {
1120         if (KingPawnSquare(j, i, File(j), 1))
1121           pawn_race[black][black][j] |= SetMask(i);
1122       }
1123     }
1124   }
1125 }
1126 
1127 /*
1128  *******************************************************************************
1129  *                                                                             *
1130  *   InitializeLMP() is used to initialize the LMP thresholds used to decide   *
1131  *   when to stop searching additional branches near the tips of the tree.     *
1132  *                                                                             *
1133  *******************************************************************************
1134  */
InitializeLMP()1135 void InitializeLMP() {
1136   int i;
1137 
1138   for (i = 0; i < LMP_depth; i++)
1139     LMP[i] = LMP_base + pow(i + .5, LMP_scale);
1140 }
1141 
1142 /*
1143  *******************************************************************************
1144  *                                                                             *
1145  *   InitializeLMR() is used to initialize the reduction matrix used to set    *
1146  *   the reduction value for LMR for each move searched.  It is indexed by     *
1147  *   depth remaining and # moves searched.                                     *
1148  *                                                                             *
1149  *******************************************************************************
1150  */
InitializeLMR()1151 void InitializeLMR() {
1152   int d, m;
1153 
1154   for (d = 0; d < 32; d++)
1155     for (m = 0; m < 64; m++)
1156       LMR[d][m] = 0;
1157   for (d = 3; d < 32; d++)
1158     for (m = 1; m < 64; m++) {
1159       LMR[d][m] =
1160           Max(Min(log(d * LMR_db) * log(m * LMR_mb) / LMR_s, LMR_max),
1161           LMR_min);
1162       LMR[d][m] = Min(LMR[d][m], Max(d - 1 - LMR_rdepth, 0));
1163     }
1164 }
1165 
1166 /*
1167  *******************************************************************************
1168  *                                                                             *
1169  *   InitlializeSMP() is used to initialize the pthread lock variables.        *
1170  *                                                                             *
1171  *******************************************************************************
1172  */
InitializeSMP(void)1173 void InitializeSMP(void) {
1174   LockInit(lock_smp);
1175   LockInit(lock_io);
1176   LockInit(block[0]->lock);
1177 #if defined(UNIX) && (CPUS > 1)
1178   pthread_attr_init(&attributes);
1179   pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
1180 #endif
1181 }
1182