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