Rev 154 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 154 | Rev 169 | ||
|---|---|---|---|
| Line 4... | Line 4... | ||
| 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad |
4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad |
| 5 | Copyright (C) 2015- |
5 | Copyright (C) 2015-2018 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad |
| 6 | 6 | ||
| 7 | Stockfish is free software: you can redistribute it and/or modify |
7 | Stockfish is free software: you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation, either version 3 of the License, or |
9 | the Free Software Foundation, either version 3 of the License, or |
| 10 | (at your option) any later version. |
10 | (at your option) any later version. |
| Line 23... | Line 23... | ||
| 23 | #include "bitboard.h" |
23 | #include "bitboard.h" |
| 24 | #include "misc.h" |
24 | #include "misc.h" |
| 25 | 25 | ||
| 26 | uint8_t PopCnt16[1 << 16]; |
26 | uint8_t PopCnt16[1 << 16]; |
| 27 | int SquareDistance[SQUARE_NB][SQUARE_NB]; |
27 | int SquareDistance[SQUARE_NB][SQUARE_NB]; |
| 28 | - | ||
| 29 | Bitboard RookMasks [SQUARE_NB]; |
- | |
| 30 | Bitboard RookMagics [SQUARE_NB]; |
- | |
| 31 | Bitboard* RookAttacks[SQUARE_NB]; |
- | |
| 32 | unsigned RookShifts [SQUARE_NB]; |
- | |
| 33 | - | ||
| 34 | Bitboard BishopMasks [SQUARE_NB]; |
- | |
| 35 | Bitboard BishopMagics [SQUARE_NB]; |
- | |
| 36 | Bitboard* BishopAttacks[SQUARE_NB]; |
- | |
| 37 | unsigned BishopShifts [SQUARE_NB]; |
- | |
| 38 | 28 | ||
| 39 | Bitboard SquareBB[SQUARE_NB]; |
29 | Bitboard SquareBB[SQUARE_NB]; |
| 40 | Bitboard FileBB[FILE_NB]; |
30 | Bitboard FileBB[FILE_NB]; |
| 41 | Bitboard RankBB[RANK_NB]; |
31 | Bitboard RankBB[RANK_NB]; |
| 42 | Bitboard AdjacentFilesBB[FILE_NB]; |
32 | Bitboard AdjacentFilesBB[FILE_NB]; |
| 43 | Bitboard |
33 | Bitboard ForwardRanksBB[COLOR_NB][RANK_NB]; |
| 44 | Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB]; |
- | |
| 45 | Bitboard BetweenBB[SQUARE_NB][SQUARE_NB]; |
34 | Bitboard BetweenBB[SQUARE_NB][SQUARE_NB]; |
| 46 | Bitboard LineBB[SQUARE_NB][SQUARE_NB]; |
35 | Bitboard LineBB[SQUARE_NB][SQUARE_NB]; |
| 47 | Bitboard DistanceRingBB[SQUARE_NB][8]; |
36 | Bitboard DistanceRingBB[SQUARE_NB][8]; |
| 48 | Bitboard |
37 | Bitboard ForwardFileBB[COLOR_NB][SQUARE_NB]; |
| 49 | Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB]; |
38 | Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB]; |
| 50 | Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB]; |
39 | Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB]; |
| 51 | Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB]; |
40 | Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB]; |
| - | 41 | Bitboard PawnAttacks[COLOR_NB][SQUARE_NB]; |
|
| - | 42 | ||
| - | 43 | Magic RookMagics[SQUARE_NB]; |
|
| - | 44 | Magic BishopMagics[SQUARE_NB]; |
|
| 52 | 45 | ||
| 53 | namespace { |
46 | namespace { |
| 54 | 47 | ||
| 55 | // De Bruijn sequences. See chessprogramming.wikispaces.com/BitScan |
48 | // De Bruijn sequences. See chessprogramming.wikispaces.com/BitScan |
| 56 | const uint64_t DeBruijn64 = 0x3F79D71B4CB0A89ULL; |
49 | const uint64_t DeBruijn64 = 0x3F79D71B4CB0A89ULL; |
| Line 59... | Line 52... | ||
| 59 | int MSBTable[256]; // To implement software msb() |
52 | int MSBTable[256]; // To implement software msb() |
| 60 | Square BSFTable[SQUARE_NB]; // To implement software bitscan |
53 | Square BSFTable[SQUARE_NB]; // To implement software bitscan |
| 61 | Bitboard RookTable[0x19000]; // To store rook attacks |
54 | Bitboard RookTable[0x19000]; // To store rook attacks |
| 62 | Bitboard BishopTable[0x1480]; // To store bishop attacks |
55 | Bitboard BishopTable[0x1480]; // To store bishop attacks |
| 63 | 56 | ||
| 64 | typedef unsigned (Fn)(Square, Bitboard); |
- | |
| 65 | - | ||
| 66 | void init_magics(Bitboard table[], |
57 | void init_magics(Bitboard table[], Magic magics[], Direction directions[]); |
| 67 | Bitboard masks[], unsigned shifts[], Square deltas[], Fn index); |
- | |
| 68 | 58 | ||
| 69 | // bsf_index() returns the index into BSFTable[] to look up the bitscan. Uses |
59 | // bsf_index() returns the index into BSFTable[] to look up the bitscan. Uses |
| 70 | // Matt Taylor's folding for 32 bit case, extended to 64 bit by Kim Walisch. |
60 | // Matt Taylor's folding for 32 bit case, extended to 64 bit by Kim Walisch. |
| 71 | 61 | ||
| 72 | unsigned bsf_index(Bitboard b) { |
62 | unsigned bsf_index(Bitboard b) { |
| Line 171... | Line 161... | ||
| 171 | 161 | ||
| 172 | for (File f = FILE_A; f <= FILE_H; ++f) |
162 | for (File f = FILE_A; f <= FILE_H; ++f) |
| 173 | AdjacentFilesBB[f] = (f > FILE_A ? FileBB[f - 1] : 0) | (f < FILE_H ? FileBB[f + 1] : 0); |
163 | AdjacentFilesBB[f] = (f > FILE_A ? FileBB[f - 1] : 0) | (f < FILE_H ? FileBB[f + 1] : 0); |
| 174 | 164 | ||
| 175 | for (Rank r = RANK_1; r < RANK_8; ++r) |
165 | for (Rank r = RANK_1; r < RANK_8; ++r) |
| 176 |
|
166 | ForwardRanksBB[WHITE][r] = ~(ForwardRanksBB[BLACK][r + 1] = ForwardRanksBB[BLACK][r] | RankBB[r]); |
| 177 | 167 | ||
| 178 | for (Color c = WHITE; c <= BLACK; ++c) |
168 | for (Color c = WHITE; c <= BLACK; ++c) |
| 179 | for (Square s = SQ_A1; s <= SQ_H8; ++s) |
169 | for (Square s = SQ_A1; s <= SQ_H8; ++s) |
| 180 | { |
170 | { |
| 181 |
|
171 | ForwardFileBB [c][s] = ForwardRanksBB[c][rank_of(s)] & FileBB[file_of(s)]; |
| 182 | PawnAttackSpan[c][s] = |
172 | PawnAttackSpan[c][s] = ForwardRanksBB[c][rank_of(s)] & AdjacentFilesBB[file_of(s)]; |
| 183 | PassedPawnMask[c][s] = |
173 | PassedPawnMask[c][s] = ForwardFileBB [c][s] | PawnAttackSpan[c][s]; |
| 184 | } |
174 | } |
| 185 | 175 | ||
| 186 | for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) |
176 | for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) |
| 187 | for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) |
177 | for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) |
| 188 | if (s1 != s2) |
178 | if (s1 != s2) |
| 189 | { |
179 | { |
| 190 | SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2)); |
180 | SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2)); |
| 191 | DistanceRingBB[s1][SquareDistance[s1][s2] - 1] |= s2; |
181 | DistanceRingBB[s1][SquareDistance[s1][s2] - 1] |= s2; |
| 192 | } |
182 | } |
| 193 | 183 | ||
| 194 | int steps[][ |
184 | int steps[][5] = { {}, { 7, 9 }, { 6, 10, 15, 17 }, {}, {}, {}, { 1, 7, 8, 9 } }; |
| 195 | {}, {}, {}, { 9, 7, -7, -9, 8, 1, -1, -8 } }; |
- | |
| 196 | 185 | ||
| 197 | for (Color c = WHITE; c <= BLACK; ++c) |
186 | for (Color c = WHITE; c <= BLACK; ++c) |
| 198 | for (PieceType pt |
187 | for (PieceType pt : { PAWN, KNIGHT, KING }) |
| 199 | for (Square s = SQ_A1; s <= SQ_H8; ++s) |
188 | for (Square s = SQ_A1; s <= SQ_H8; ++s) |
| 200 | for (int i = 0; steps[pt][i]; ++i) |
189 | for (int i = 0; steps[pt][i]; ++i) |
| 201 | { |
190 | { |
| 202 | Square to = s + |
191 | Square to = s + Direction(c == WHITE ? steps[pt][i] : -steps[pt][i]); |
| 203 | 192 | ||
| 204 | if (is_ok(to) && distance(s, to) < 3) |
193 | if (is_ok(to) && distance(s, to) < 3) |
| - | 194 | { |
|
| - | 195 | if (pt == PAWN) |
|
| - | 196 | PawnAttacks[c][s] |= to; |
|
| - | 197 | else |
|
| 205 |
|
198 | PseudoAttacks[pt][s] |= to; |
| - | 199 | } |
|
| 206 | } |
200 | } |
| 207 | 201 | ||
| 208 |
|
202 | Direction RookDirections[] = { NORTH, EAST, SOUTH, WEST }; |
| 209 |
|
203 | Direction BishopDirections[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }; |
| 210 | 204 | ||
| 211 | init_magics(RookTable, |
205 | init_magics(RookTable, RookMagics, RookDirections); |
| 212 | init_magics(BishopTable, |
206 | init_magics(BishopTable, BishopMagics, BishopDirections); |
| 213 | 207 | ||
| 214 | for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) |
208 | for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) |
| 215 | { |
209 | { |
| 216 | PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb<BISHOP>(s1, 0); |
210 | PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb<BISHOP>(s1, 0); |
| 217 | PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0); |
211 | PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0); |
| 218 | 212 | ||
| 219 | for ( |
213 | for (PieceType pt : { BISHOP, ROOK }) |
| 220 | for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) |
214 | for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) |
| 221 | { |
215 | { |
| 222 | if (!(PseudoAttacks[ |
216 | if (!(PseudoAttacks[pt][s1] & s2)) |
| 223 | continue; |
217 | continue; |
| 224 | 218 | ||
| 225 | LineBB[s1][s2] = (attacks_bb( |
219 | LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2; |
| 226 | BetweenBB[s1][s2] = attacks_bb( |
220 | BetweenBB[s1][s2] = attacks_bb(pt, s1, SquareBB[s2]) & attacks_bb(pt, s2, SquareBB[s1]); |
| 227 | } |
221 | } |
| 228 | } |
222 | } |
| 229 | } |
223 | } |
| 230 | 224 | ||
| 231 | 225 | ||
| 232 | namespace { |
226 | namespace { |
| 233 | 227 | ||
| 234 | Bitboard sliding_attack( |
228 | Bitboard sliding_attack(Direction directions[], Square sq, Bitboard occupied) { |
| 235 | 229 | ||
| 236 | Bitboard attack = 0; |
230 | Bitboard attack = 0; |
| 237 | 231 | ||
| 238 | for (int i = 0; i < 4; ++i) |
232 | for (int i = 0; i < 4; ++i) |
| 239 | for (Square s = sq + |
233 | for (Square s = sq + directions[i]; |
| 240 | is_ok(s) && distance(s, s - |
234 | is_ok(s) && distance(s, s - directions[i]) == 1; |
| 241 | s += |
235 | s += directions[i]) |
| 242 | { |
236 | { |
| 243 | attack |= s; |
237 | attack |= s; |
| 244 | 238 | ||
| 245 | if (occupied & s) |
239 | if (occupied & s) |
| 246 | break; |
240 | break; |
| Line 253... | Line 247... | ||
| 253 | // init_magics() computes all rook and bishop attacks at startup. Magic |
247 | // init_magics() computes all rook and bishop attacks at startup. Magic |
| 254 | // bitboards are used to look up attacks of sliding pieces. As a reference see |
248 | // bitboards are used to look up attacks of sliding pieces. As a reference see |
| 255 | // chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we |
249 | // chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we |
| 256 | // use the so called "fancy" approach. |
250 | // use the so called "fancy" approach. |
| 257 | 251 | ||
| 258 | void init_magics(Bitboard table[], |
252 | void init_magics(Bitboard table[], Magic magics[], Direction directions[]) { |
| 259 | Bitboard masks[], unsigned shifts[], Square deltas[], Fn index) { |
- | |
| 260 | 253 | ||
| - | 254 | // Optimal PRNG seeds to pick the correct magics in the shortest time |
|
| 261 | int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 }, |
255 | int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 }, |
| 262 | { 728, 10316, 55013, 32803, 12281, 15100, 16645, 255 } }; |
256 | { 728, 10316, 55013, 32803, 12281, 15100, 16645, 255 } }; |
| 263 | 257 | ||
| 264 | Bitboard occupancy[4096], reference[4096], edges, b; |
258 | Bitboard occupancy[4096], reference[4096], edges, b; |
| 265 | int |
259 | int epoch[4096] = {}, cnt = 0, size = 0; |
| 266 | - | ||
| 267 | // attacks[s] is a pointer to the beginning of the attacks table for square 's' |
- | |
| 268 | attacks[SQ_A1] = table; |
- | |
| 269 | 260 | ||
| 270 | for (Square s = SQ_A1; s <= SQ_H8; ++s) |
261 | for (Square s = SQ_A1; s <= SQ_H8; ++s) |
| 271 | { |
262 | { |
| 272 | // Board edges are not considered in the relevant occupancies |
263 | // Board edges are not considered in the relevant occupancies |
| 273 | edges = ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s)); |
264 | edges = ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s)); |
| Line 275... | Line 266... | ||
| 275 | // Given a square 's', the mask is the bitboard of sliding attacks from |
266 | // Given a square 's', the mask is the bitboard of sliding attacks from |
| 276 | // 's' computed on an empty board. The index must be big enough to contain |
267 | // 's' computed on an empty board. The index must be big enough to contain |
| 277 | // all the attacks for each possible subset of the mask and so is 2 power |
268 | // all the attacks for each possible subset of the mask and so is 2 power |
| 278 | // the number of 1s of the mask. Hence we deduce the size of the shift to |
269 | // the number of 1s of the mask. Hence we deduce the size of the shift to |
| 279 | // apply to the 64 or 32 bits word to get the index. |
270 | // apply to the 64 or 32 bits word to get the index. |
| - | 271 | Magic& m = magics[s]; |
|
| 280 |
|
272 | m.mask = sliding_attack(directions, s, 0) & ~edges; |
| 281 |
|
273 | m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask); |
| - | 274 | ||
| - | 275 | // Set the offset for the attacks table of the square. We have individual |
|
| - | 276 | // table sizes for each square with "Fancy Magic Bitboards". |
|
| - | 277 | m.attacks = s == SQ_A1 ? table : magics[s - 1].attacks + size; |
|
| 282 | 278 | ||
| 283 | // Use Carry-Rippler trick to enumerate all subsets of masks[s] and |
279 | // Use Carry-Rippler trick to enumerate all subsets of masks[s] and |
| 284 | // store the corresponding sliding attack bitboard in reference[]. |
280 | // store the corresponding sliding attack bitboard in reference[]. |
| 285 | b = size = 0; |
281 | b = size = 0; |
| 286 | do { |
282 | do { |
| 287 | occupancy[size] = b; |
283 | occupancy[size] = b; |
| 288 | reference[size] = sliding_attack( |
284 | reference[size] = sliding_attack(directions, s, b); |
| 289 | 285 | ||
| 290 | if (HasPext) |
286 | if (HasPext) |
| 291 | attacks |
287 | m.attacks[pext(b, m.mask)] = reference[size]; |
| 292 | 288 | ||
| 293 | size++; |
289 | size++; |
| 294 | b = (b - |
290 | b = (b - m.mask) & m.mask; |
| 295 | } while (b); |
291 | } while (b); |
| 296 | - | ||
| 297 | // Set the offset for the table of the next square. We have individual |
- | |
| 298 | // table sizes for each square with "Fancy Magic Bitboards". |
- | |
| 299 | if (s < SQ_H8) |
- | |
| 300 | attacks[s + 1] = attacks[s] + size; |
- | |
| 301 | 292 | ||
| 302 | if (HasPext) |
293 | if (HasPext) |
| 303 | continue; |
294 | continue; |
| 304 | 295 | ||
| 305 | PRNG rng(seeds[Is64Bit][rank_of(s)]); |
296 | PRNG rng(seeds[Is64Bit][rank_of(s)]); |
| 306 | 297 | ||
| 307 | // Find a magic for square 's' picking up an (almost) random number |
298 | // Find a magic for square 's' picking up an (almost) random number |
| 308 | // until we find the one that passes the verification test. |
299 | // until we find the one that passes the verification test. |
| 309 |
|
300 | for (int i = 0; i < size; ) |
| 310 |
|
301 | { |
| 311 |
|
302 | for (m.magic = 0; popcount((m.magic * m.mask) >> 56) < 6; ) |
| 312 |
|
303 | m.magic = rng.sparse_rand<Bitboard>(); |
| 313 | 304 | ||
| 314 | // A good magic must map every possible occupancy to an index that |
305 | // A good magic must map every possible occupancy to an index that |
| 315 | // looks up the correct sliding attack in the attacks[s] database. |
306 | // looks up the correct sliding attack in the attacks[s] database. |
| 316 | // Note that we build up the database for square 's' as a side |
307 | // Note that we build up the database for square 's' as a side |
| 317 | // effect of verifying the magic. |
308 | // effect of verifying the magic. Keep track of the attempt count |
| - | 309 | // and save it in epoch[], little speed-up trick to avoid resetting |
|
| - | 310 | // m.attacks[] after every failed attempt. |
|
| 318 | for (++ |
311 | for (++cnt, i = 0; i < size; ++i) |
| 319 | { |
312 | { |
| 320 | unsigned idx = index( |
313 | unsigned idx = m.index(occupancy[i]); |
| 321 | 314 | ||
| 322 | if ( |
315 | if (epoch[idx] < cnt) |
| 323 | { |
316 | { |
| 324 |
|
317 | epoch[idx] = cnt; |
| 325 | attacks |
318 | m.attacks[idx] = reference[i]; |
| 326 | } |
319 | } |
| 327 | else if (attacks |
320 | else if (m.attacks[idx] != reference[i]) |
| 328 | break; |
321 | break; |
| 329 | } |
322 | } |
| 330 | } |
323 | } |
| 331 | } |
324 | } |
| 332 | } |
325 | } |
| 333 | } |
326 | } |