- void init_pseudo_attacks() {
- Square s;
- for(s = SQ_A1; s <= SQ_H8; s++) {
- BishopPseudoAttacks[s] = bishop_attacks_bb(s, EmptyBoardBB);
- RookPseudoAttacks[s] = rook_attacks_bb(s, EmptyBoardBB);
- QueenPseudoAttacks[s] = queen_attacks_bb(s, EmptyBoardBB);
- }
- }
-
-#if defined(USE_COMPACT_ROOK_ATTACKS)
- void init_file_and_rank_attacks() {
- int i, j, k, l, m, s;
- Bitboard b1, b2;
- for(i = 0; i < 64; i++) {
-
- for(m = 0; m <= 1; m++) {
- b1 = 0ULL;
- for(j = 0; j < 6; j++) if(i & (1<<j)) b1 |= (1ULL << ((j+1)*(1+m*7)));
- for(j = 0; j < 8; j++) {
- b2 = 0ULL;
- for(k = 0, s = 1; k < 2; k++, s *= -1) {
- for(l = j+s; l >= 0 && l <= 7; l += s) {
- b2 |= (m? RankBB[l] : FileBB[l]);
- if(b1 & (1ULL << (l*(1+m*7)))) break;
+ // init_magics() computes all rook and bishop attacks at startup. Magic
+ // bitboards are used to look up attacks of sliding pieces. As a reference see
+ // chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we
+ // use the so called "fancy" approach.
+
+ void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[],
+ Bitboard masks[], unsigned shifts[], Square deltas[], Fn index) {
+
+ int MagicBoosters[][8] = { { 3191, 2184, 1310, 3618, 2091, 1308, 2452, 3996 },
+ { 1059, 3608, 605, 3234, 3326, 38, 2029, 3043 } };
+ RKISS rk;
+ Bitboard occupancy[4096], reference[4096], edges, b;
+ int i, size, booster;
+
+ // attacks[s] is a pointer to the beginning of the attacks table for square 's'
+ attacks[SQ_A1] = table;
+
+ for (Square s = SQ_A1; s <= SQ_H8; s++)
+ {
+ // Board edges are not considered in the relevant occupancies
+ edges = ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s));
+
+ // Given a square 's', the mask is the bitboard of sliding attacks from
+ // 's' computed on an empty board. The index must be big enough to contain
+ // all the attacks for each possible subset of the mask and so is 2 power
+ // the number of 1s of the mask. Hence we deduce the size of the shift to
+ // apply to the 64 or 32 bits word to get the index.
+ masks[s] = sliding_attack(deltas, s, 0) & ~edges;
+ shifts[s] = (Is64Bit ? 64 : 32) - popcount<Max15>(masks[s]);
+
+ // Use Carry-Rippler trick to enumerate all subsets of masks[s] and
+ // store the corresponding sliding attack bitboard in reference[].
+ b = size = 0;
+ do {
+ occupancy[size] = b;
+ reference[size++] = sliding_attack(deltas, s, b);
+ b = (b - masks[s]) & masks[s];
+ } while (b);
+
+ // Set the offset for the table of the next square. We have individual
+ // table sizes for each square with "Fancy Magic Bitboards".
+ if (s < SQ_H8)
+ attacks[s + 1] = attacks[s] + size;
+
+ booster = MagicBoosters[Is64Bit][rank_of(s)];
+
+ // Find a magic for square 's' picking up an (almost) random number
+ // until we find the one that passes the verification test.
+ do {
+ magics[s] = pick_random(masks[s], rk, booster);
+ memset(attacks[s], 0, size * sizeof(Bitboard));
+
+ // A good magic must map every possible occupancy to an index that
+ // looks up the correct sliding attack in the attacks[s] database.
+ // Note that we build up the database for square 's' as a side
+ // effect of verifying the magic.
+ for (i = 0; i < size; i++)
+ {
+ Bitboard& attack = attacks[s][index(s, occupancy[i])];
+
+ if (attack && attack != reference[i])
+ break;
+
+ attack = reference[i];