30 static constexpr int MAX_OCCUPANCIES = 4096;
35 constexpr uint64_t rand64() {
36 s ^= s >> 12, s ^= s << 25, s ^= s >> 27;
37 return s * 2685821657736338717LL;
41 constexpr PRNG(uint64_t seed) : s(seed) { assert(seed); }
49 constexpr T sparse_rand() {
50 return T(rand64() & rand64() & rand64());
56 case PieceType::ROOK: {
58 ((Bitboard::rankBB(Rank::R1) | Bitboard::rankBB(Rank::R8)) &
~Bitboard::rankBB(square.rank())) |
59 ((Bitboard::fileBB(File::FA) | Bitboard::fileBB(File::FH)) & ~Bitboard::fileBB(square.file()));
60 return slidingAttacksBB(PieceType::ROOK, square, Bitboard::zero()) & ~edges;
62 case PieceType::BISHOP: {
63 Bitboard edges = (Bitboard::rankBB(Rank::R1) | Bitboard::rankBB(Rank::R8) | Bitboard::fileBB(File::FA) |
64 Bitboard::fileBB(File::FH));
65 return slidingAttacksBB(PieceType::BISHOP, square, Bitboard::zero()) & ~edges;
68 return Bitboard::zero();
75 constexpr std::array<Direction, 4> rookDirections = {Direction::N, Direction::S, Direction::E, Direction::W};
76 constexpr std::array<Direction, 4> bishopDirections = {Direction::NE, Direction::NW, Direction::SE,
79 const auto& directions = (pieceType == PieceType::BISHOP) ? bishopDirections : rookDirections;
82 Square currentSquare = square;
85 Bitboard destination = Bitboard::destinationBB(currentSquare, direction);
86 if (destination == Bitboard::zero())
break;
88 attacks |= destination;
89 currentSquare = currentSquare + direction;
91 if ((destination & occupancy) != Bitboard::zero()) {
101 static auto generateMagics() {
102 std::array<
Magic, Square::number()> rookMagics{};
103 std::array<
Magic, Square::number()> bishopMagics{};
104 std::array<Bitboard, TOTAL_ATTACKS_SIZE> attacks{};
107 constexpr std::array<std::array<int, 8>, 2> seeds = {{{8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020},
108 {728, 10316, 55013, 32803, 12281, 15100, 16645, 255}}};
110 size_t attacksOffset = 0;
112 for (
auto square : Square::all()) {
113 Magic& magic = rookMagics[square];
114 magic.premask = premask(PieceType::ROOK, square);
115 magic.shift = Square::number() - popCount(magic.premask);
116 magic.attacksOffset = attacksOffset;
118 std::array<Bitboard, MAX_OCCUPANCIES> occupancies{};
119 std::array<Bitboard, MAX_OCCUPANCIES> reference{};
120 std::array<int, MAX_OCCUPANCIES> epoch{};
128 occupancies[size] = b;
129 reference[size] = slidingAttacksBB(PieceType::ROOK, square, b);
131 b = (b - magic.premask) & magic.premask;
132 }
while (b != Bitboard::zero());
134 PRNG rng(
static_cast<uint64_t
>(seeds[0][square.rank()]));
136 for (
size_t i = 0; i < size;) {
137 for (magic.magic = Bitboard::zero(); popCount((magic.magic * magic.premask) >> 56) < 6;) {
138 magic.magic = rng.sparse_rand<
Bitboard>();
140 for (++cnt, i = 0; i < size; ++i) {
141 size_t idx = magic.index(occupancies[i]);
142 if (epoch[idx] < cnt) {
144 attacks[attacksOffset + idx] = reference[i];
145 }
else if (attacks[attacksOffset + idx] != reference[i]) {
151 attacksOffset += (1ULL << popCount(magic.premask));
154 for (
auto square : Square::all()) {
155 Magic& magic = bishopMagics[square];
156 magic.premask = premask(PieceType::BISHOP, square);
157 magic.shift = Square::number() - popCount(magic.premask);
158 magic.attacksOffset = attacksOffset;
160 std::array<Bitboard, MAX_OCCUPANCIES> occupancies{};
161 std::array<Bitboard, MAX_OCCUPANCIES> reference{};
162 std::array<int, MAX_OCCUPANCIES> epoch{};
169 occupancies[size] = b;
170 reference[size] = slidingAttacksBB(PieceType::BISHOP, square, b);
172 b = (b - magic.premask) & magic.premask;
173 }
while (b != Bitboard::zero());
175 PRNG rng(
static_cast<uint64_t
>(seeds[1][square.rank()]));
177 for (
size_t i = 0; i < size;) {
178 for (magic.magic = Bitboard::zero(); popCount((magic.magic * magic.premask) >> 56) < 6;) {
179 magic.magic = rng.sparse_rand<
Bitboard>();
182 for (++cnt, i = 0; i < size; ++i) {
183 size_t idx = magic.index(occupancies[i]);
184 if (epoch[idx] < cnt) {
186 attacks[attacksOffset + idx] = reference[i];
187 }
else if (attacks[attacksOffset + idx] != reference[i]) {
193 attacksOffset += (1ULL << popCount(magic.premask));
196 return std::make_tuple(rookMagics, bishopMagics, attacks);