stellar

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

rook.cpp (3885B)


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