stellar

UCI Chess engine written in C++20
git clone git://git.dimitrijedobrota.com/stellar.git
Log | Files | Refs | README | LICENSE |

bishop.hpp (4613B)


1 #ifndef STELLAR_ATTACK_BISHOP_H 2 #define STELLAR_ATTACK_BISHOP_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 bishop { 14 15 inline constexpr const U64 bishop_magic_numbers[64] = { 16 C64(0x40040844404084), C64(0x2004208a004208), C64(0x10190041080202), C64(0x108060845042010), 17 C64(0x581104180800210), C64(0x2112080446200010), C64(0x1080820820060210), C64(0x3c0808410220200), 18 C64(0x4050404440404), C64(0x21001420088), C64(0x24d0080801082102), C64(0x1020a0a020400), 19 C64(0x40308200402), C64(0x4011002100800), C64(0x401484104104005), C64(0x801010402020200), 20 C64(0x400210c3880100), C64(0x404022024108200), C64(0x810018200204102), C64(0x4002801a02003), 21 C64(0x85040820080400), C64(0x810102c808880400), C64(0xe900410884800), C64(0x8002020480840102), 22 C64(0x220200865090201), C64(0x2010100a02021202), C64(0x152048408022401), C64(0x20080002081110), 23 C64(0x4001001021004000), C64(0x800040400a011002), C64(0xe4004081011002), C64(0x1c004001012080), 24 C64(0x8004200962a00220), C64(0x8422100208500202), C64(0x2000402200300c08), C64(0x8646020080080080), 25 C64(0x80020a0200100808), C64(0x2010004880111000), C64(0x623000a080011400), C64(0x42008c0340209202), 26 C64(0x209188240001000), C64(0x400408a884001800), C64(0x110400a6080400), C64(0x1840060a44020800), 27 C64(0x90080104000041), C64(0x201011000808101), C64(0x1a2208080504f080), C64(0x8012020600211212), 28 C64(0x500861011240000), C64(0x180806108200800), C64(0x4000020e01040044), C64(0x300000261044000a), 29 C64(0x802241102020002), C64(0x20906061210001), C64(0x5a84841004010310), C64(0x4010801011c04), 30 C64(0xa010109502200), C64(0x4a02012000), C64(0x500201010098b028), C64(0x8040002811040900), 31 C64(0x28000010020204), C64(0x6000020202d0240), C64(0x8918844842082200), C64(0x4010011029020020), 32 }; 33 34 static inline constexpr const int relevant_bits[64] = { 35 // clang-format off 36 6, 5, 5, 5, 5, 5, 5, 6, 37 5, 5, 5, 5, 5, 5, 5, 5, 38 5, 5, 7, 7, 7, 7, 5, 5, 39 5, 5, 7, 9, 9, 7, 5, 5, 40 5, 5, 7, 9, 9, 7, 5, 5, 41 5, 5, 7, 7, 7, 7, 5, 5, 42 5, 5, 5, 5, 5, 5, 5, 5, 43 6, 5, 5, 5, 5, 5, 5, 6, 44 // clang-format on 45 }; 46 47 inline constexpr const bitboard::direction_f dir[4] = {bitboard::noEaOne, bitboard::noWeOne, 48 bitboard::soEaOne, bitboard::soWeOne}; 49 50 inline constexpr U32 hash(const U64 key, const square::Square square) { 51 uint8_t square_i = to_underlying(square); 52 return (key * bishop_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] = {std::min(7 - tf, 7 - tr), std::min(tf, 7 - tr), std::min(7 - tf, tr), std::min(tf, 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 int tr = square / 8, tf = square % 8; 67 int len[4] = {std::min(7 - tf, 7 - tr) - 1, std::min(tf, 7 - tr) - 1, std::min(7 - tf, tr) - 1, 68 std::min(tf, tr) - 1}; 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 bishop 101 } // namespace attack 102 103 #endif