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