Subversion Repositories Games.Chess Giants

Rev

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
}