stellarUCI Chess engine written in C++20 |
git clone git://git.dimitrijedobrota.com/stellar.git |
Log | Files | Refs | README | LICENSE | |
rook.hpp (4504B)
1 #ifndef STELLAR_ATTACK_ROOK_H 2 #define STELLAR_ATTACK_ROOK_H 3 4 #include "bit.hpp" 5 #include "bitboard.hpp" 6 #include "slider.hpp" 7 #include "square.hpp" 8 #include "utils.hpp" 9 10 #include <array> 11 12 namespace attack { 13 namespace rook { 14 15 inline constexpr const int relevant_bits[64] = { 16 // clang-format off 17 12, 11, 11, 11, 11, 11, 11, 12, 18 11, 10, 10, 10, 10, 10, 10, 11, 19 11, 10, 10, 10, 10, 10, 10, 11, 20 11, 10, 10, 10, 10, 10, 10, 11, 21 11, 10, 10, 10, 10, 10, 10, 11, 22 11, 10, 10, 10, 10, 10, 10, 11, 23 11, 10, 10, 10, 10, 10, 10, 11, 24 12, 11, 11, 11, 11, 11, 11, 12, 25 // clang-format on 26 }; 27 28 inline constexpr const U64 rook_magic_numbers[64] = { 29 C64(0x8a80104000800020), C64(0x140002000100040), C64(0x2801880a0017001), C64(0x100081001000420), 30 C64(0x200020010080420), C64(0x3001c0002010008), C64(0x8480008002000100), C64(0x2080088004402900), 31 C64(0x800098204000), C64(0x2024401000200040), C64(0x100802000801000), C64(0x120800800801000), 32 C64(0x208808088000400), C64(0x2802200800400), C64(0x2200800100020080), C64(0x801000060821100), 33 C64(0x80044006422000), C64(0x100808020004000), C64(0x12108a0010204200), C64(0x140848010000802), 34 C64(0x481828014002800), C64(0x8094004002004100), C64(0x4010040010010802), C64(0x20008806104), 35 C64(0x100400080208000), C64(0x2040002120081000), C64(0x21200680100081), C64(0x20100080080080), 36 C64(0x2000a00200410), C64(0x20080800400), C64(0x80088400100102), C64(0x80004600042881), 37 C64(0x4040008040800020), C64(0x440003000200801), C64(0x4200011004500), C64(0x188020010100100), 38 C64(0x14800401802800), C64(0x2080040080800200), C64(0x124080204001001), C64(0x200046502000484), 39 C64(0x480400080088020), C64(0x1000422010034000), C64(0x30200100110040), C64(0x100021010009), 40 C64(0x2002080100110004), C64(0x202008004008002), C64(0x20020004010100), C64(0x2048440040820001), 41 C64(0x101002200408200), C64(0x40802000401080), C64(0x4008142004410100), C64(0x2060820c0120200), 42 C64(0x1001004080100), C64(0x20c020080040080), C64(0x2935610830022400), C64(0x44440041009200), 43 C64(0x280001040802101), C64(0x2100190040002085), C64(0x80c0084100102001), C64(0x4024081001000421), 44 C64(0x20030a0244872), C64(0x12001008414402), C64(0x2006104900a0804), C64(0x1004081002402), 45 }; 46 47 inline constexpr const bitboard::direction_f dir[4] = {bitboard::westOne, bitboard::soutOne, 48 bitboard::eastOne, bitboard::nortOne}; 49 50 inline constexpr U32 hash(const U64 key, const square::Square square) { 51 uint8_t square_i = to_underlying(square); 52 return (key * rook_magic_numbers[square_i]) >> (64 - relevant_bits[square_i]); 53 } 54 55 inline constexpr U64 mask_fly(const square::Square square, U64 block) { 56 uint8_t square_i = to_underlying(square); 57 int tr = square_i / 8, tf = square_i % 8; 58 int len[4] = {tf, tr, 7 - tf, 7 - tr}; 59 60 return slider::mask(square, block, dir, len); 61 } 62 63 inline constexpr const std::array<U64, 64> masks = []() constexpr -> std::array<U64, 64> { 64 std::array<U64, 64> masks; 65 for (uint8_t square = 0; square < 64; square++) { 66 const int tr = square / 8, tf = square % 8; 67 const int len[4] = {tf - 1, tr - 1, 6 - tf, 6 - tr}; 68 69 masks[square] = slider::mask(static_cast<square::Square>(square), C64(0), dir, len); 70 } 71 return masks; 72 }(); 73 74 inline constexpr U64 mask(const square::Square square) { return masks[to_underlying(square)]; } 75 76 using attack_array = std::array<std::array<U64, 4096>, 64>; 77 inline constexpr const attack_array attacks = []() constexpr -> attack_array { 78 attack_array attacks = {{{0}}}; 79 for (uint8_t square = 0; square < 64; square++) { 80 square::Square Square = static_cast<square::Square>(square); 81 U64 attack_mask = mask(Square); 82 uint8_t relevant_bits = bit::count(attack_mask); 83 U64 occupancy_indices = C64(1) << relevant_bits; 84 85 for (U64 idx = 0; idx < occupancy_indices; idx++) { 86 U64 occupancy = slider::occupancy(idx, relevant_bits, attack_mask); 87 U32 magic_index = hash(occupancy, Square); 88 attacks[square][magic_index] = mask_fly(Square, occupancy); 89 } 90 } 91 return attacks; 92 }(); 93 94 inline constexpr U64 attack(const square::Square square, U64 occupancy) { 95 occupancy &= mask(square); 96 occupancy = hash(occupancy, square); 97 return attacks[to_underlying(square)][occupancy]; 98 } 99 100 } // namespace rook 101 } // namespace attack 102 103 #endif