stellar

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

commit 2f3a26c1d985412b453547ebd5c01190e378684e
parent fcde3f48c51361419b4d2f43652dd622e50660b7
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Wed, 13 Mar 2024 19:54:46 +0000

Beter enum handling, get rid of to_underlying()

Diffstat:
MCMakeLists.txt | 2+-
Msrc/arena/game.cpp | 4++--
Msrc/arena/logger.hpp | 2+-
Msrc/arena/match.cpp | 2+-
Msrc/attack/bishop.cpp | 27+++++++++++----------------
Msrc/attack/king.hpp | 13+++++++------
Msrc/attack/knight.hpp | 13+++++++------
Msrc/attack/pawnb.hpp | 13+++++++------
Msrc/attack/pawnw.hpp | 13+++++++------
Msrc/attack/rook.cpp | 27+++++++++++----------------
Msrc/attack/slider.hpp | 2+-
Msrc/board/board.cpp | 16++++++++--------
Msrc/board/board.hpp | 43+++++++++++++++++++------------------------
Msrc/board/zobrist.hpp | 6+++---
Msrc/engine/engine.cpp | 6+++---
Msrc/engine/evaluate.cpp | 3+--
Msrc/engine/score.hpp | 11++++++-----
Msrc/move/move.cpp | 5++---
Msrc/move/move.hpp | 2+-
Msrc/move/movelist.cpp | 10+++++-----
Msrc/piece/piece.hpp | 5+++--
Msrc/utils/bitboard.cpp | 2++
Msrc/utils/bitboard.hpp | 1+
Msrc/utils/square.hpp | 13+++++--------
Msrc/utils/utils.hpp | 29+++--------------------------
25 files changed, 118 insertions(+), 152 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project( Stellar - VERSION 1.3.0 + VERSION 1.3.1 DESCRIPTION "Chess engine written in C++" HOMEPAGE_URL https://git.dimitrijedobrota.com/stellar.git LANGUAGES CXX diff --git a/src/arena/game.cpp b/src/arena/game.cpp @@ -84,7 +84,7 @@ std::ostream &operator<<(std::ostream &os, const Game &game) { os << std::format("\n[White \"{}\"]", game.get_white()); os << std::format("\n[Black \"{}\"]", game.get_black()); os << std::format("\n[Result \"{}-{}\"]", (int)game.is_win_white(), (int)game.is_win_black()); - os << std::format("\n[Termination \"{}\"]", name[to_underlying(game.get_terminate())]); + os << std::format("\n[Termination \"{}\"]", name[game.get_terminate()]); if (game.fen != Game::startPosition) { os << std::format("\n[SetUp \"1\"]"); os << std::format("\n[FEN \"{}\"]", game.fen); @@ -97,7 +97,7 @@ std::ostream &operator<<(std::ostream &os, const Game &game) { const color::Color side = board.get_side(); if (side == color::BLACK) os << std::format("1. ... "); for (int i = 0; i < game.list.size(); i++) { - if (i % 2 == to_underlying(side)) os << std::format("{}. ", i / 2 + 1); + if (i % 2 == side) os << std::format("{}. ", i / 2 + 1); os << std::format("{} ", Game::san ? Game::to_san(board, game.list[i]) : (std::string)game.list[i]); game.list[i].make(board); } diff --git a/src/arena/logger.hpp b/src/arena/logger.hpp @@ -22,7 +22,7 @@ inline void set_level(const Level lvl) { active = lvl; } inline void log(const std::string &message, const Level lvl = Arena) { static const std::string name[] = {"crit", "arena", "debug", "info"}; if (lvl > active) return; - std::cerr << std::format("[ {:>5} ] {}\n", name[to_underlying(lvl)], message); + std::cerr << std::format("[ {:>5} ] {}\n", name[lvl], message); } inline void error(const char *call) { log(std::format("{}, {}", call, std::strerror(errno)), Critical); } diff --git a/src/arena/match.cpp b/src/arena/match.cpp @@ -31,7 +31,7 @@ Game Match::play(Settings swhite, Settings sblack, const std::string fen = Game: break; } - Engine *engine = engines[to_underlying(turn)]; + Engine *engine = engines[turn]; engine->send(std::format("{} moves {}", position, game.get_moves())); engine->send(get_go(swhite, sblack, turn)); diff --git a/src/attack/bishop.cpp b/src/attack/bishop.cpp @@ -45,49 +45,44 @@ inline constexpr const bitboard::direction_f dir[4] = {bitboard::noEaOne, bitboa bitboard::soEaOne, bitboard::soWeOne}; inline constexpr U32 hash(const U64 key, const square::Square square) { - uint8_t square_i = to_underlying(square); - return (key * bishop_magic_numbers[square_i]) >> (64 - relevant_bits[square_i]); + return (key * bishop_magic_numbers[square]) >> (64 - relevant_bits[square]); } inline constexpr U64 mask_fly(const square::Square square, U64 block) { - uint8_t square_i = to_underlying(square); - int tr = square_i / 8, tf = square_i % 8; + int tr = square / 8, tf = square % 8; int len[4] = {std::min(7 - tf, 7 - tr), std::min(tf, 7 - tr), std::min(7 - tf, tr), std::min(tf, tr)}; return attack::slider::mask(square, block, dir, len); } -std::array<U64, 64> masks = {{0}}; -inline U64 mask(const square::Square square) { return masks[to_underlying(square)]; } - +std::array<U64, 64> mask = {{0}}; std::array<std::array<U64, 4098>, 64> attacks = {{{0}}}; void init(void) { - for (uint8_t square = 0; square < 64; square++) { + for (square::Square square = square::a1; square <= square::h8; ++square) { int tr = square / 8, tf = square % 8; int len[4] = {std::min(7 - tf, 7 - tr) - 1, std::min(tf, 7 - tr) - 1, std::min(7 - tf, tr) - 1, std::min(tf, tr) - 1}; - masks[square] = attack::slider::mask(static_cast<square::Square>(square), C64(0), dir, len); + mask[square] = attack::slider::mask(square, C64(0), dir, len); } - for (uint8_t square = 0; square < 64; square++) { - square::Square Square = static_cast<square::Square>(square); - U64 attack_mask = mask(Square); + for (square::Square square = square::a1; square <= square::h8; ++square) { + U64 attack_mask = mask[square]; uint8_t relevant_bits = bit::count(attack_mask); U64 occupancy_indices = C64(1) << relevant_bits; for (U64 idx = 0; idx < occupancy_indices; idx++) { U64 occupancy = attack::slider::occupancy(idx, relevant_bits, attack_mask); - U32 magic_index = hash(occupancy, Square); - attacks[square][magic_index] = mask_fly(Square, occupancy); + U32 magic_index = hash(occupancy, square); + attacks[square][magic_index] = mask_fly(square, occupancy); } } } U64 attack(const square::Square square, U64 occupancy) { - occupancy &= mask(square); + occupancy &= mask[square]; occupancy = hash(occupancy, square); - return attacks[to_underlying(square)][occupancy]; + return attacks[square][occupancy]; } } // namespace bishop diff --git a/src/attack/king.hpp b/src/attack/king.hpp @@ -14,7 +14,7 @@ namespace king { static constexpr U64 mask(const square::Square square) { U64 bitboard = C64(0), attacks = C64(0); - bit::set(bitboard, to_underlying(square)); + bit::set(bitboard, square); attacks |= bitboard::westOne(bitboard) | bitboard::eastOne(bitboard); attacks |= bitboard::soutOne(bitboard) | bitboard::nortOne(bitboard); attacks |= bitboard::soutOne(bitboard) | bitboard::nortOne(bitboard); @@ -27,14 +27,15 @@ static constexpr U64 mask(const square::Square square) { typedef std::array<U64, 64> attack_array; const attack_array attacks = []() -> attack_array { std::array<U64, 64> attacks; - for (uint8_t square = 0; square < 64; square++) - attacks[square] = mask(static_cast<square::Square>(square)); + + for (square::Square square = square::a1; square <= square::h8; ++square) { + attacks[square] = mask(square); + } + return attacks; }(); -inline constexpr U64 attack(const square::Square square, U64 occupancy) { - return attacks[to_underlying(square)]; -} +inline constexpr U64 attack(const square::Square square, U64 occupancy) { return attacks[square]; } } // namespace king } // namespace attack diff --git a/src/attack/knight.hpp b/src/attack/knight.hpp @@ -14,7 +14,7 @@ namespace knight { static constexpr U64 mask(const square::Square square) { U64 bitboard = C64(0), attacks = C64(0), tmp; - bit::set(bitboard, to_underlying(square)); + bit::set(bitboard, square); tmp = bitboard::nortOne(bitboard::nortOne(bitboard)); attacks |= bitboard::westOne(tmp) | bitboard::eastOne(tmp); tmp = bitboard::soutOne(bitboard::soutOne(bitboard)); @@ -30,14 +30,15 @@ static constexpr U64 mask(const square::Square square) { typedef std::array<U64, 64> attack_array; const attack_array attacks = []() -> attack_array { std::array<U64, 64> attacks; - for (uint8_t square = 0; square < 64; square++) - attacks[square] = mask(static_cast<square::Square>(square)); + + for (square::Square square = square::a1; square <= square::h8; ++square) { + attacks[square] = mask(square); + } + return attacks; }(); -inline constexpr U64 attack(const square::Square square, U64 occupancy) { - return attacks[to_underlying(square)]; -} +inline constexpr U64 attack(const square::Square square, U64 occupancy) { return attacks[square]; } } // namespace knight } // namespace attack diff --git a/src/attack/pawnb.hpp b/src/attack/pawnb.hpp @@ -14,21 +14,22 @@ namespace pawnb { static constexpr U64 mask(const square::Square square) { U64 bitboard = C64(0); - bit::set(bitboard, to_underlying(square)); + bit::set(bitboard, square); return bitboard::soWeOne(bitboard) | bitboard::soEaOne(bitboard); } typedef std::array<U64, 64> attack_array; const attack_array attacks = []() -> attack_array { std::array<U64, 64> attacks; - for (uint8_t square = 0; square < 64; square++) - attacks[square] = mask(static_cast<square::Square>(square)); + + for (square::Square square = square::a1; square <= square::h8; ++square) { + attacks[square] = mask(square); + } + return attacks; }(); -inline constexpr U64 attack(const square::Square square, U64 occupancy) { - return attacks[to_underlying(square)]; -} +inline constexpr U64 attack(const square::Square square, U64 occupancy) { return attacks[square]; } } // namespace pawnb }; // namespace attack diff --git a/src/attack/pawnw.hpp b/src/attack/pawnw.hpp @@ -14,21 +14,22 @@ namespace pawnw { static constexpr U64 mask(const square::Square square) { U64 bitboard = C64(0); - bit::set(bitboard, to_underlying(square)); + bit::set(bitboard, square); return bitboard::noWeOne(bitboard) | bitboard::noEaOne(bitboard); } typedef std::array<U64, 64> attack_array; const attack_array attacks = []() -> attack_array { std::array<U64, 64> attacks; - for (uint8_t square = 0; square < 64; square++) - attacks[square] = mask(static_cast<square::Square>(square)); + + for (square::Square square = square::a1; square <= square::h8; ++square) { + attacks[square] = mask(square); + } + return attacks; }(); -inline constexpr U64 attack(const square::Square square, U64 occupancy) { - return attacks[to_underlying(square)]; -} +inline constexpr U64 attack(const square::Square square, U64 occupancy) { return attacks[square]; } } // namespace pawnw } // namespace attack diff --git a/src/attack/rook.cpp b/src/attack/rook.cpp @@ -44,49 +44,44 @@ inline constexpr const bitboard::direction_f dir[4] = {bitboard::westOne, bitboa bitboard::eastOne, bitboard::nortOne}; inline constexpr U32 hash(const U64 key, const square::Square square) { - uint8_t square_i = to_underlying(square); - return (key * rook_magic_numbers[square_i]) >> (64 - relevant_bits[square_i]); + return (key * rook_magic_numbers[square]) >> (64 - relevant_bits[square]); } inline constexpr U64 mask_fly(const square::Square square, U64 block) { - uint8_t square_i = to_underlying(square); - int tr = square_i / 8, tf = square_i % 8; + int tr = square / 8, tf = square % 8; int len[4] = {tf, tr, 7 - tf, 7 - tr}; return attack::slider::mask(square, block, dir, len); } -std::array<U64, 64> masks = {{0}}; -U64 mask(const square::Square square) { return masks[to_underlying(square)]; } - +std::array<U64, 64> mask = {{0}}; std::array<std::array<U64, 4096>, 64> attacks = {{{0}}}; void init(void) { - for (uint8_t square = 0; square < 64; square++) { + for (square::Square square = square::a1; square <= square::h8; ++square) { const int tr = square / 8, tf = square % 8; const int len[4] = {tf - 1, tr - 1, 6 - tf, 6 - tr}; - masks[square] = attack::slider::mask(static_cast<square::Square>(square), C64(0), dir, len); + mask[square] = attack::slider::mask(square, C64(0), dir, len); } - for (uint8_t square = 0; square < 64; square++) { - square::Square Square = static_cast<square::Square>(square); - U64 attack_mask = mask(Square); + for (square::Square square = square::a1; square <= square::h8; ++square) { + U64 attack_mask = mask[square]; uint8_t relevant_bits = bit::count(attack_mask); U64 occupancy_indices = C64(1) << relevant_bits; for (U64 idx = 0; idx < occupancy_indices; idx++) { U64 occupancy = attack::slider::occupancy(idx, relevant_bits, attack_mask); - U32 magic_index = hash(occupancy, Square); - attacks[square][magic_index] = mask_fly(Square, occupancy); + U32 magic_index = hash(occupancy, square); + attacks[square][magic_index] = mask_fly(square, occupancy); } } } U64 attack(const square::Square square, U64 occupancy) { - occupancy &= mask(square); + occupancy &= mask[square]; occupancy = hash(occupancy, square); - return attacks[to_underlying(square)][occupancy]; + return attacks[square][occupancy]; } } // namespace rook diff --git a/src/attack/slider.hpp b/src/attack/slider.hpp @@ -25,7 +25,7 @@ inline constexpr U64 occupancy(U64 index, uint8_t bits_in_mask, U64 attack_mask) inline constexpr U64 mask(const square::Square square, U64 block, const bitboard::direction_f dir[4], const int len[4]) { U64 bitboard = C64(0), attacks = C64(0); - bit::set(bitboard, to_underlying(square)); + bit::set(bitboard, square); for (int i = 0; i < 4; i++) { U64 tmp = bitboard; for (int j = 0; j < len[i]; j++) { diff --git a/src/board/board.cpp b/src/board/board.cpp @@ -39,13 +39,13 @@ Board::Board(const std::string &fen) { : throw std::runtime_error("Invalid player char"); for (i += 2; fen[i] != ' '; i++) { - if (fen[i] == 'K') castle |= to_underlying(Castle::WK); + if (fen[i] == 'K') castle |= Castle::WK; else if (fen[i] == 'Q') - castle |= to_underlying(Castle::WQ); + castle |= Castle::WQ; else if (fen[i] == 'k') - castle |= to_underlying(Castle::BK); + castle |= Castle::BK; else if (fen[i] == 'q') - castle |= to_underlying(Castle::BQ); + castle |= Castle::BQ; else if (fen[i] == '-') { i++; break; @@ -73,10 +73,10 @@ std::ostream &operator<<(std::ostream &os, const Board &board) { os << ((board.side == color::WHITE) ? "white" : "black") << "\n"; os << "Enpassant: " << square::to_coordinates(board.enpassant) << "\n"; os << " Castle:"; - os << ((board.castle & to_underlying(Board::Castle::WK)) ? 'K' : '-'); - os << ((board.castle & to_underlying(Board::Castle::WQ)) ? 'Q' : '-'); - os << ((board.castle & to_underlying(Board::Castle::BK)) ? 'k' : '-'); - os << ((board.castle & to_underlying(Board::Castle::BQ)) ? 'q' : '-'); + os << ((board.castle & Board::Castle::WK) ? 'K' : '-'); + os << ((board.castle & Board::Castle::WQ) ? 'Q' : '-'); + os << ((board.castle & Board::Castle::BK) ? 'k' : '-'); + os << ((board.castle & Board::Castle::BQ) ? 'q' : '-'); os << "\n Hash:" << board.hash << "\n\n"; return os; diff --git a/src/board/board.hpp b/src/board/board.hpp @@ -15,7 +15,7 @@ class Board { public: - enum class Castle : uint8_t { + enum Castle : uint8_t { WK = 1, WQ = 2, BK = 4, @@ -90,16 +90,12 @@ constexpr U64 Board::get_hash() const { return hash; } constexpr uint8_t Board::get_castle() const { return castle; } constexpr square::Square Board::get_enpassant() const { return enpassant; } -constexpr U64 Board::get_bitboard_color(color::Color side) const { return colors[to_underlying(side)]; } - -constexpr U64 Board::get_bitboard_occupancy() const { - return colors[to_underlying(color::WHITE)] | colors[to_underlying(color::BLACK)]; -} - -constexpr U64 Board::get_bitboard_piece(piece::Type piece) const { return pieces[to_underlying(piece)]; } +constexpr U64 Board::get_bitboard_color(color::Color side) const { return colors[side]; } +constexpr U64 Board::get_bitboard_occupancy() const { return colors[color::WHITE] | colors[color::BLACK]; } +constexpr U64 Board::get_bitboard_piece(piece::Type piece) const { return pieces[piece]; } constexpr U64 Board::get_bitboard_piece(piece::Type piece, color::Color color) const { - return pieces[to_underlying(piece)] & colors[to_underlying(color)]; + return pieces[piece] & colors[color]; } constexpr U64 Board::get_bitboard_piece_attacks(piece::Type type, color::Color color, @@ -119,14 +115,14 @@ constexpr U64 Board::get_bitboard_square_land(square::Square land, piece::Type p } constexpr color::Color Board::get_square_piece_color(square::Square square) const { - if (bit::get(colors[to_underlying(color::WHITE)], to_underlying(square))) return color::WHITE; - if (bit::get(colors[to_underlying(color::BLACK)], to_underlying(square))) return color::BLACK; + if (bit::get(colors[color::WHITE], square)) return color::WHITE; + if (bit::get(colors[color::BLACK], square)) return color::BLACK; throw std::exception(); } constexpr piece::Type Board::get_square_piece_type(square::Square square) const { - for (piece::Type type : piece::TypeIter()) { - if (bit::get(pieces[to_underlying(type)], to_underlying(square))) return type; + for (piece::Type type = piece::PAWN; type <= piece::KING; ++type) { + if (bit::get(pieces[type], square)) return type; } return piece::Type::NONE; } @@ -160,19 +156,19 @@ constexpr void Board::set_enpassant(square::Square target) { } constexpr void Board::pop_bitboard_color(color::Color color, square::Square square) { - bit::pop(colors[to_underlying(color)], to_underlying(square)); + bit::pop(colors[color], square); } constexpr void Board::set_bitboard_color(color::Color color, square::Square square) { - bit::set(colors[to_underlying(color)], to_underlying(square)); + bit::set(colors[color], square); } constexpr void Board::pop_bitboard_piece(piece::Type type, square::Square square) { - bit::pop(pieces[to_underlying(type)], to_underlying(square)); + bit::pop(pieces[type], square); } constexpr void Board::set_bitboard_piece(piece::Type type, square::Square square) { - bit::set(pieces[to_underlying(type)], to_underlying(square)); + bit::set(pieces[type], square); } constexpr void Board::pop_piece(piece::Type type, color::Color side, square::Square square) { @@ -188,13 +184,13 @@ constexpr void Board::set_piece(piece::Type type, color::Color side, square::Squ /* Queries */ constexpr bool Board::is_square_occupied(square::Square square) const { - return bit::get(get_bitboard_occupancy(), to_underlying(square)); + return bit::get(get_bitboard_occupancy(), square); } constexpr bool Board::is_square_attacked(square::Square square, color::Color side) const { const color::Color side_other = color::other(side); - for (piece::Type type : piece::TypeIter()) { + for (piece::Type type = piece::PAWN; type <= piece::KING; ++type) { if (get_bitboard_piece_attacks(type, side_other, square) & get_bitboard_piece(type, side)) { return true; } @@ -205,11 +201,11 @@ constexpr bool Board::is_square_attacked(square::Square square, color::Color sid constexpr bool Board::is_piece_attack_square(piece::Type type, color::Color color, square::Square source, square::Square target) const { - return get_bitboard_piece_attacks(type, color, source) & (C64(1) << to_underlying(target)); + return get_bitboard_piece_attacks(type, color, source) & (C64(1) << target); } constexpr bool Board::is_check() const { - U64 king = pieces[to_underlying(piece::Type::KING)] & colors[to_underlying(side)]; + U64 king = pieces[piece::Type::KING] & colors[side]; color::Color side_other = (side == color::BLACK) ? color::WHITE : color::BLACK; auto square = static_cast<square::Square>(bit::lsb_index(king)); return is_square_attacked(square, side_other); @@ -219,7 +215,7 @@ U64 zobrist::hash(const Board &board) { U64 key_final = C64(0); uint8_t square = 0; - for (piece::Type type : piece::TypeIter()) { + for (piece::Type type = piece::PAWN; type <= piece::KING; ++type) { int piece_white_index = piece::get_index(type, color::WHITE); U64 bitboard_white = board.get_bitboard_piece(type, color::WHITE); bitboard_for_each_bit(square, bitboard_white) { key_final ^= keys_piece[piece_white_index][square]; } @@ -232,8 +228,7 @@ U64 zobrist::hash(const Board &board) { key_final ^= keys_castle[board.get_castle()]; if (board.get_side() == color::BLACK) key_final ^= keys_side; - if (board.get_enpassant() != square::Square::no_sq) - key_final ^= keys_enpassant[to_underlying(board.get_enpassant())]; + if (board.get_enpassant() != square::Square::no_sq) key_final ^= keys_enpassant[board.get_enpassant()]; return key_final; } diff --git a/src/board/zobrist.hpp b/src/board/zobrist.hpp @@ -19,7 +19,7 @@ const U64 keys_side = Random(C32(1699391443))(); inline void init() { Random gen1(C64(1804289383)); - for (piece::Type type : piece::TypeIter()) { + for (piece::Type type = piece::PAWN; type <= piece::KING; ++type) { int piece_index_white = piece::get(type, color::Color::WHITE).index; int piece_index_black = piece::get(type, color::Color::BLACK).index; for (int square = 0; square < 64; square++) { @@ -42,9 +42,9 @@ inline void init() { inline U64 hash(const Board &board); inline constexpr U64 key_side() { return keys_side; } inline constexpr U64 key_castle(int exp) { return keys_castle[exp]; } -inline constexpr U64 key_enpassant(square::Square square) { return keys_enpassant[to_underlying(square)]; } +inline constexpr U64 key_enpassant(square::Square square) { return keys_enpassant[square]; } inline constexpr U64 key_piece(piece::Type type, color::Color color, square::Square square) { - return keys_piece[piece::get_index(type, color)][to_underlying(square)]; + return keys_piece[piece::get_index(type, color)][square]; } }; // namespace zobrist diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp @@ -135,11 +135,11 @@ U32 inline move_score(const Move move) { const piece::Type type = board.get_square_piece_type(move.source()); if (move.is_capture()) { const piece::Type captured = board.get_square_piece_type(move.target()); - return capture[to_underlying(type)][to_underlying(captured)] + 10000; + return capture[type][captured] + 10000; } if (killer[0][ply] == move) return 9000; if (killer[1][ply] == move) return 8000; - return history[piece::get_index(type, board.get_side())][to_underlying(move.target())]; + return history[piece::get_index(type, board.get_side())][move.target()]; } void move_list_sort(MoveList &list, std::vector<int> &score, int crnt) { @@ -368,7 +368,7 @@ int16_t negamax(int16_t alpha, int16_t beta, uint8_t depth, bool null) { if (score > alpha) { if (!move.is_capture()) { const piece::Type piece = board.get_square_piece_type(move.source()); - history[piece::get_index(piece, board.get_side())][to_underlying(move.target())] += depth; + history[piece::get_index(piece, board.get_side())][move.target()] += depth; } alpha = score; diff --git a/src/engine/evaluate.cpp b/src/engine/evaluate.cpp @@ -89,7 +89,6 @@ int16_t score_position_side(const Board &board, const color::Color side, const u int16_t total = 0, opening = 0, endgame = 0; int8_t square_i; - const uint8_t side_i = to_underlying(side); const U64 pawns = board.get_bitboard_piece(PAWN); const U64 pawnsS = board.get_bitboard_piece(PAWN, side); const U64 pawnsO = pawns & ~pawnsS; @@ -112,7 +111,7 @@ int16_t score_position_side(const Board &board, const color::Color side, const u endgame -= score::pawn_double_endgame; } - if (!(pawnsO & mask_passed[side_i][square_i])) total += score::pawn_passed[side_i][rank]; + if (!(pawnsO & mask_passed[side][square_i])) total += score::pawn_passed[side][rank]; } bitboard = board.get_bitboard_piece(KNIGHT, side); diff --git a/src/engine/score.hpp b/src/engine/score.hpp @@ -1,6 +1,7 @@ #ifndef STELLAR_SCORE_H #define STELLAR_SCORE_H +#include "piece.hpp" #include "utils.hpp" #define MAX_PLY 64 @@ -146,13 +147,13 @@ enum Phase { }; inline constexpr int16_t get(const piece::Type piece, const Phase phase = OPENING) { - return value[to_underlying(phase)][to_underlying(piece)]; + return value[phase][piece]; } -inline constexpr int16_t get(const piece::Type piece, const color::Color color, const square::Square square, - const Phase phase = ENDGAME) { - uint8_t square_i = to_underlying(color == color::WHITE ? square : square::mirror(square)); - return position[to_underlying(phase)][to_underlying(piece)][square_i]; +inline constexpr int16_t get(piece::Type piece, color::Color color, square::Square square, + Phase phase = ENDGAME) { + if (color != color::WHITE) square = square::mirror(square); + return position[phase][piece][square]; } inline constexpr const uint8_t pawn_double_opening = 5; diff --git a/src/move/move.cpp b/src/move/move.cpp @@ -41,7 +41,7 @@ bool Move::make(Board &board) const { const square::Square source = this->source(), target = this->target(); const auto ntarget = - static_cast<square::Square>(to_underlying(this->target()) + (color == color::Color::WHITE ? -8 : +8)); + static_cast<square::Square>(this->target() + (color == color::Color::WHITE ? -8 : +8)); const piece::Type piece = board.get_square_piece_type(source); @@ -83,8 +83,7 @@ bool Move::make(Board &board) const { } } - board.and_castle(castling_rights[to_underlying(this->source())] & - castling_rights[to_underlying(this->target())]); + board.and_castle(castling_rights[this->source()] & castling_rights[this->target()]); if (!board.is_check()) { board.switch_side(); diff --git a/src/move/move.hpp b/src/move/move.hpp @@ -29,7 +29,7 @@ struct Move { Move() : source_i(0), target_i(0), flags_i(0) {} Move(square::Square source, square::Square target, Flag flags) - : source_i(to_underlying(source)), target_i(to_underlying(target)), flags_i(flags) {} + : source_i(source), target_i(target), flags_i(flags) {} friend bool operator==(const Move a, const Move b) { return a.source_i == b.source_i && a.target_i == b.target_i && a.flags_i == b.flags_i; diff --git a/src/move/movelist.cpp b/src/move/movelist.cpp @@ -63,7 +63,7 @@ void MoveList::generate(const Board &board, bool attacks_only) { } // All piece move - for (const piece::Type type : ++piece::TypeIter()) { + for (piece::Type type = piece::KNIGHT; type <= piece::KING; ++type) { U64 bitboard = board.get_bitboard_piece(type, color); bitboard_for_each_bit(src_i, bitboard) { const auto src = static_cast<square::Square>(src_i); @@ -85,12 +85,12 @@ void MoveList::generate(const Board &board, bool attacks_only) { // Castling if (color == color::WHITE) { if (!board.is_square_attacked(square::e1, color::BLACK)) { - if (board.get_castle() & to_underlying(Board::Castle::WK)) { + if (board.get_castle() & Board::Castle::WK) { if (!board.is_square_occupied(square::f1) && !board.is_square_occupied(square::g1) && !board.is_square_attacked(square::f1, color::BLACK)) list.emplace_back(square::e1, square::g1, Move::CASTLEK); } - if (board.get_castle() & to_underlying(Board::Castle::WQ)) { + if (board.get_castle() & Board::Castle::WQ) { if (!board.is_square_occupied(square::d1) && !board.is_square_occupied(square::c1) && !board.is_square_occupied(square::b1) && !board.is_square_attacked(square::d1, color::BLACK) && @@ -100,12 +100,12 @@ void MoveList::generate(const Board &board, bool attacks_only) { } } else { if (!board.is_square_attacked(square::e8, color::WHITE)) { - if (board.get_castle() & to_underlying(Board::Castle::BK)) { + if (board.get_castle() & Board::Castle::BK) { if (!board.is_square_occupied(square::f8) && !board.is_square_occupied(square::g8) && !board.is_square_attacked(square::f8, color::WHITE)) list.emplace_back(square::Square::e8, square::Square::g8, Move::CASTLEK); } - if (board.get_castle() & to_underlying(Board::Castle::BQ)) { + if (board.get_castle() & Board::Castle::BQ) { if (!board.is_square_occupied(square::d8) && !board.is_square_occupied(square::c8) && !board.is_square_occupied(square::b8) && !board.is_square_attacked(square::d8, color::WHITE) && diff --git a/src/piece/piece.hpp b/src/piece/piece.hpp @@ -18,7 +18,8 @@ enum Type { KING, NONE = 7, }; -typedef Iterator<Type, Type::PAWN, Type::KING> TypeIter; + +ENABLE_INCR_OPERATORS_ON(Type) struct Piece { const uint8_t index; @@ -68,7 +69,7 @@ inline constexpr const U64 get_index(const Type type, const color::Color color) inline constexpr const Piece &get_from_code(const char code) { color::Color color = isupper(code) ? color::WHITE : color::BLACK; - for (Type type : TypeIter()) { + for (Type type = PAWN; type <= KING; ++type) { const Piece &piece = get(type, color); if (piece.code == code) return piece; } diff --git a/src/utils/bitboard.cpp b/src/utils/bitboard.cpp @@ -4,6 +4,7 @@ #include <iostream> namespace bitboard { + void print(U64 bitboard) { for (int rank = 0; rank < 8; rank++) { for (int file = 0; file < 8; file++) { @@ -17,4 +18,5 @@ void print(U64 bitboard) { std::cout << "\n A B C D E F G H\n\n"; std::cout << " Bitboard: " << std::hex << bitboard << std::dec << std::endl; } + } // namespace bitboard diff --git a/src/utils/bitboard.hpp b/src/utils/bitboard.hpp @@ -1,6 +1,7 @@ #ifndef STELLAR_BITBOARD_H #define STELLAR_BITBOARD_H +#include "square.hpp" #include "utils.hpp" namespace bitboard { diff --git a/src/utils/square.hpp b/src/utils/square.hpp @@ -6,7 +6,7 @@ namespace square { -enum Square { +enum Square : int { // clang-format off a1, b1, c1, d1, e1, f1, g1, h1, a2, b2, c2, d2, e2, f2, g2, h2, @@ -19,7 +19,7 @@ enum Square { // clang-format on }; -typedef Iterator<Square, Square::a1, Square::h8> Iter; +ENABLE_INCR_OPERATORS_ON(Square) inline constexpr const Square mirror_array[]{ // clang-format off @@ -47,13 +47,10 @@ inline constexpr const char *coordinates_array[] = { // clang-format on }; -inline constexpr const uint8_t file(const Square square) { return to_underlying(square) & 0x07; } -inline constexpr const uint8_t rank(const Square square) { return to_underlying(square) >> 3; } +inline constexpr const uint8_t file(const Square square) { return square & 0x07; } +inline constexpr const uint8_t rank(const Square square) { return square >> 3; } inline constexpr const Square mirror(const Square square) { return mirror_array[square]; } - -inline constexpr const std::string to_coordinates(const Square square) { - return coordinates_array[to_underlying(square)]; -} +inline constexpr const std::string to_coordinates(const Square square) { return coordinates_array[square]; } inline const Square from_coordinates(const std::string &cord) { return static_cast<Square>((cord[1] - '1') * 8 + (cord[0] - 'a')); diff --git a/src/utils/utils.hpp b/src/utils/utils.hpp @@ -9,31 +9,8 @@ typedef uint64_t U64; typedef uint32_t U32; -#include <type_traits> - -template <typename E> constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept { - return static_cast<typename std::underlying_type<E>::type>(e); -} - -template <typename C, C beginVal, C endVal> class Iterator { - typedef typename std::underlying_type<C>::type val_t; - int val; - - public: - constexpr Iterator(const C &f) : val(static_cast<val_t>(f)) {} - constexpr Iterator() : val(static_cast<val_t>(beginVal)) {} - constexpr Iterator operator++() { - ++val; - return *this; - } - constexpr C operator*() { return static_cast<C>(val); } - constexpr Iterator begin() { return *this; } - constexpr Iterator end() { - // static const Iterator endIter = ++Iterator(endVal); - // return endIter; - return ++Iterator(endVal); - } - constexpr bool operator!=(const Iterator &i) { return val != i.val; } -}; +#define ENABLE_INCR_OPERATORS_ON(T) \ + inline T &operator++(T &d) { return d = T(int(d) + 1); } \ + inline T &operator--(T &d) { return d = T(int(d) - 1); } #endif