stellar

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

board.hpp (7893B)


      1 #ifndef STELLAR_BOARD_H
      2 #define STELLAR_BOARD_H
      3 
      4 #include "attack.hpp"
      5 #include "bit.hpp"
      6 #include "piece.hpp"
      7 #include "utils.hpp"
      8 #include "zobrist.hpp"
      9 
     10 #include <iostream>
     11 #include <string>
     12 
     13 #define start_position "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 "
     14 
     15 class Board {
     16   public:
     17     enum Castle : uint8_t {
     18         WK = 1,
     19         WQ = 2,
     20         BK = 4,
     21         BQ = 8
     22     };
     23 
     24     Board() = default;
     25     Board(const std::string &fen);
     26 
     27     friend std::ostream &operator<<(std::ostream &os, const Board &board);
     28 
     29     /* Getters */
     30 
     31     [[nodiscard]] inline constexpr U64 get_hash() const { return hash; }
     32     [[nodiscard]] inline constexpr Color get_side() const { return side; }
     33     [[nodiscard]] inline constexpr uint8_t get_castle() const { return castle; }
     34     [[nodiscard]] inline constexpr Square get_enpassant() const { return enpassant; }
     35     [[nodiscard]] inline constexpr U64 get_hash_pawn() const { return hash_pawn; }
     36 
     37     [[nodiscard]] inline constexpr U64 get_bitboard_color(Color side) const;
     38     [[nodiscard]] inline constexpr U64 get_bitboard_occupancy() const;
     39 
     40     [[nodiscard]] inline constexpr U64 get_bitboard_piece(Type piece) const;
     41     [[nodiscard]] inline constexpr U64 get_bitboard_piece(Type piece, Color color) const;
     42 
     43     [[nodiscard]] inline constexpr U64 get_bitboard_piece_attacks(Type piece, Color color, Square from) const;
     44     [[nodiscard]] inline constexpr U64 get_bitboard_piece_moves(Type piece, Color color, Square from) const;
     45     [[nodiscard]] inline constexpr U64 get_bitboard_square_land(Square land, Type piece, Color side) const;
     46 
     47     [[nodiscard]] inline constexpr Color get_square_piece_color(Square square) const;
     48     [[nodiscard]] inline constexpr Type get_square_piece_type(Square square) const;
     49 
     50     /* Setters */
     51 
     52     inline constexpr void xor_hash(U64 op);
     53     inline constexpr void xor_hash_pawn(U32 op);
     54 
     55     inline void switch_side();
     56     inline void and_castle(uint8_t right);
     57     inline void set_enpassant(Square target);
     58 
     59     inline constexpr void pop_bitboard_color(Color color, Square square);
     60     inline constexpr void set_bitboard_color(Color color, Square square);
     61 
     62     inline constexpr void pop_bitboard_piece(Type type, Square square);
     63     inline constexpr void set_bitboard_piece(Type type, Square square);
     64 
     65     inline constexpr void pop_piece(Type type, Color side, Square square);
     66     inline constexpr void set_piece(Type type, Color side, Square square);
     67 
     68     /* Queries */
     69 
     70     [[nodiscard]] inline constexpr bool is_square_attacked(Square square, Color side) const;
     71     [[nodiscard]] inline constexpr bool is_square_occupied(Square square) const;
     72     [[nodiscard]] inline constexpr bool is_piece_attack_square(Type type, Color color, Square source,
     73                                                                Square target) const;
     74     [[nodiscard]] inline constexpr bool is_check() const;
     75 
     76   private:
     77     U64 colors[2] = {0};
     78     U64 pieces[6] = {0};
     79     U64 hash = 0;
     80     U32 hash_pawn = 0;
     81     Color side = WHITE;
     82     Square enpassant = Square::no_sq;
     83     uint8_t castle = 0;
     84 };
     85 
     86 constexpr U64 Board::get_bitboard_color(Color side) const { return colors[side]; }
     87 constexpr U64 Board::get_bitboard_occupancy() const { return colors[WHITE] | colors[BLACK]; }
     88 constexpr U64 Board::get_bitboard_piece(Type piece) const { return pieces[piece]; }
     89 
     90 constexpr U64 Board::get_bitboard_piece(Type piece, Color color) const {
     91     return pieces[piece] & colors[color];
     92 }
     93 
     94 constexpr U64 Board::get_bitboard_piece_attacks(Type type, Color color, Square from) const {
     95     if (type == PAWN) return attack::attack_pawn(color, from);
     96     return attack::attack(type, from, get_bitboard_occupancy());
     97 }
     98 
     99 constexpr U64 Board::get_bitboard_piece_moves(Type type, Color color, Square square) const {
    100     return get_bitboard_piece_attacks(type, color, square) & ~get_bitboard_color(color);
    101 }
    102 
    103 constexpr U64 Board::get_bitboard_square_land(Square land, Type piece, Color side) const {
    104 
    105     return get_bitboard_piece_attacks(piece, other(side), land) & get_bitboard_piece(piece, side);
    106 }
    107 
    108 constexpr Color Board::get_square_piece_color(Square square) const {
    109     if (bit::get(colors[WHITE], square)) return WHITE;
    110     if (bit::get(colors[BLACK], square)) return BLACK;
    111     return COLOR_NB;
    112 }
    113 
    114 constexpr Type Board::get_square_piece_type(Square square) const {
    115     for (Type type = PAWN; type <= KING; ++type) {
    116         if (bit::get(pieces[type], square)) return type;
    117     }
    118     return Type::NO_TYPE;
    119 }
    120 
    121 /* Setters */
    122 
    123 constexpr void Board::xor_hash(U64 op) { hash ^= op; }
    124 constexpr void Board::xor_hash_pawn(U32 op) { hash_pawn ^= op; }
    125 
    126 void Board::and_castle(uint8_t right) {
    127     hash ^= zobrist::key_castle(castle);
    128     castle &= right;
    129     hash ^= zobrist::key_castle(castle);
    130 }
    131 
    132 void Board::switch_side() {
    133     side = other(side);
    134     hash ^= zobrist::key_side();
    135 }
    136 
    137 void Board::set_enpassant(Square target) {
    138     if (enpassant != Square::no_sq) hash ^= zobrist::key_enpassant(enpassant);
    139     if (target != Square::no_sq) hash ^= zobrist::key_enpassant(target);
    140     enpassant = target;
    141 }
    142 
    143 constexpr void Board::pop_bitboard_color(Color color, Square square) { bit::pop(colors[color], square); }
    144 constexpr void Board::set_bitboard_color(Color color, Square square) { bit::set(colors[color], square); }
    145 constexpr void Board::pop_bitboard_piece(Type type, Square square) { bit::pop(pieces[type], square); }
    146 constexpr void Board::set_bitboard_piece(Type type, Square square) { bit::set(pieces[type], square); }
    147 
    148 constexpr void Board::pop_piece(Type type, Color side, Square square) {
    149     pop_bitboard_color(side, square);
    150     pop_bitboard_piece(type, square);
    151 }
    152 
    153 constexpr void Board::set_piece(Type type, Color side, Square square) {
    154     set_bitboard_color(side, square);
    155     set_bitboard_piece(type, square);
    156 }
    157 
    158 /* Queries */
    159 
    160 constexpr bool Board::is_square_occupied(Square square) const {
    161     return bit::get(get_bitboard_occupancy(), square);
    162 }
    163 
    164 constexpr bool Board::is_square_attacked(Square square, Color side) const {
    165     const Color side_other = other(side);
    166 
    167     for (Type type = PAWN; type <= KING; ++type) {
    168         if (get_bitboard_piece_attacks(type, side_other, square) & get_bitboard_piece(type, side)) {
    169             return true;
    170         }
    171     }
    172 
    173     return false;
    174 }
    175 
    176 constexpr bool Board::is_piece_attack_square(Type type, Color color, Square source, Square target) const {
    177     return get_bitboard_piece_attacks(type, color, source) & (C64(1) << target);
    178 }
    179 
    180 constexpr bool Board::is_check() const {
    181     U64 king = pieces[Type::KING] & colors[side];
    182     Color side_other = (side == BLACK) ? WHITE : BLACK;
    183     auto square = static_cast<Square>(bit::lsb_index(king));
    184     return is_square_attacked(square, side_other);
    185 }
    186 
    187 U64 zobrist::hash(const Board &board) {
    188     U64 key_final = C64(0);
    189     uint8_t square = 0;
    190 
    191     for (Type type = PAWN; type <= KING; ++type) {
    192         U64 bitboard_white = board.get_bitboard_piece(type, WHITE);
    193         bitboard_for_each_bit(square, bitboard_white) { key_final ^= keys_piece[WHITE][type][square]; }
    194 
    195         U64 bitboard_black = board.get_bitboard_piece(type, BLACK);
    196         bitboard_for_each_bit(square, bitboard_black) { key_final ^= keys_piece[BLACK][type][square]; }
    197     }
    198 
    199     key_final ^= keys_castle[board.get_castle()];
    200 
    201     if (board.get_side() == BLACK) key_final ^= keys_side;
    202     if (board.get_enpassant() != Square::no_sq) key_final ^= keys_enpassant[board.get_enpassant()];
    203 
    204     return key_final;
    205 }
    206 
    207 U32 zobrist::hash_pawn(const Board &board) {
    208     U32 key_final = C32(0);
    209     uint8_t square = 0;
    210 
    211     U64 bitboard_white = board.get_bitboard_piece(PAWN, WHITE);
    212     bitboard_for_each_bit(square, bitboard_white) { key_final ^= keys_pawn[WHITE][square]; }
    213 
    214     U64 bitboard_black = board.get_bitboard_piece(PAWN, BLACK);
    215     bitboard_for_each_bit(square, bitboard_black) { key_final ^= keys_pawn[BLACK][square]; }
    216 
    217     return key_final;
    218 }
    219 
    220 #endif