stellar

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

commit 9f2c299a72ac90aa9d2a927666375cc5b6d527b3
parent edfb2f6999e4cc1e8215e10736850b48a12d424b
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Wed, 13 Mar 2024 21:41:22 +0000

Merge square and color into utils out of namespace

Diffstat:
MCMakeLists.txt | 2+-
Msrc/arena/engine.cpp | 1-
Msrc/arena/game.cpp | 19++++++++++---------
Msrc/arena/game.hpp | 8++++----
Msrc/arena/match.cpp | 40++++++++++++++++++++--------------------
Msrc/arena/match.hpp | 2+-
Msrc/attack/attack.hpp | 5++---
Msrc/attack/bishop.cpp | 10+++++-----
Msrc/attack/bishop.hpp | 5++---
Msrc/attack/king.hpp | 7+++----
Msrc/attack/knight.hpp | 7+++----
Msrc/attack/pawn.hpp | 16++++++----------
Msrc/attack/queen.hpp | 2+-
Msrc/attack/rook.cpp | 10+++++-----
Msrc/attack/rook.hpp | 3+--
Msrc/attack/slider.hpp | 3+--
Msrc/bitboard/bitboard.cpp | 12++++++++++++
Msrc/bitboard/bitboard.hpp | 4+++-
Msrc/board/board.cpp | 17+++++++----------
Msrc/board/board.hpp | 143+++++++++++++++++++++++++++++++++++--------------------------------------------
Msrc/board/zobrist.hpp | 8++++----
Msrc/engine/engine.cpp | 2+-
Msrc/engine/evaluate.cpp | 27+++++++++++++--------------
Msrc/engine/score.hpp | 5++---
Msrc/engine/uci.cpp | 11+++++------
Msrc/engine/uci.hpp | 1+
Msrc/move/move.cpp | 37++++++++++++++++---------------------
Msrc/move/move.hpp | 14++++++--------
Msrc/move/movelist.cpp | 65+++++++++++++++++++++++++++++++----------------------------------
Msrc/move/movelist.hpp | 2+-
Msrc/perft/perft.cpp | 5++---
Msrc/piece/piece.hpp | 38++++++++++++++++++--------------------
Dsrc/utils/color.hpp | 20--------------------
Msrc/utils/repetition.hpp | 5+++++
Dsrc/utils/square.hpp | 61-------------------------------------------------------------
Msrc/utils/utils.hpp | 48++++++++++++++++++++++++++++++++++++++++++++++--
Asrc/utils/utils_ui.hpp | 35+++++++++++++++++++++++++++++++++++
37 files changed, 336 insertions(+), 364 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project( Stellar - VERSION 1.3.3 + VERSION 1.3.4 DESCRIPTION "Chess engine written in C++" HOMEPAGE_URL https://git.dimitrijedobrota.com/stellar.git LANGUAGES CXX diff --git a/src/arena/engine.cpp b/src/arena/engine.cpp @@ -13,7 +13,6 @@ Engine::Pipes::Pipes() { } } - void Engine::Pipes::close() { if (::close(fd[0]) < 0 || ::close(fd[1])) { logger::error("close"); diff --git a/src/arena/game.cpp b/src/arena/game.cpp @@ -3,6 +3,7 @@ #include "board.hpp" #include "logger.hpp" #include "timer.hpp" +#include "utils_ui.hpp" #include <format> @@ -45,12 +46,12 @@ const std::string Game::to_san(const Board &board, const Move move) { int file[9] = {0}, rank[9] = {0}; uint8_t square_i = 0; bitboard_for_each_bit(square_i, potential) { - const std::string crd = square::to_coordinates(static_cast<square::Square>(square_i)); + const std::string crd = to_coordinates(static_cast<Square>(square_i)); file[crd[0] & 0x3]++; rank[crd[1] & 0x3]++; } - const std::string crd = square::to_coordinates(move.source()); + const std::string crd = to_coordinates(move.source()); if (file[crd[0] & 0x3] == 1) res += crd[0]; else if (rank[crd[1] & 0x3] == 1) res += crd[1]; @@ -58,13 +59,13 @@ const std::string Game::to_san(const Board &board, const Move move) { res += crd; } - res += piece::get_code(piece, color::WHITE); + res += piece::get_code(piece, WHITE); if (target != piece::NONE) res += "x"; - res += square::to_coordinates(move.target()); + res += to_coordinates(move.target()); } else { - if (target != piece::NONE) res += std::format("{}x", square::to_coordinates(move.source())[0]); - res += square::to_coordinates(move.target()); - if (move.is_promote()) res += piece::get_code(move.promoted(), color::WHITE); + if (target != piece::NONE) res += std::format("{}x", to_coordinates(move.source())[0]); + res += to_coordinates(move.target()); + if (move.is_promote()) res += piece::get_code(move.promoted(), WHITE); if (move.is_enpassant()) res += " e.p."; } @@ -94,8 +95,8 @@ std::ostream &operator<<(std::ostream &os, const Game &game) { if (!game.list.size()) return os; Board board(game.fen); - const color::Color side = board.get_side(); - if (side == color::BLACK) os << std::format("1. ... "); + const Color side = board.get_side(); + if (side == BLACK) os << std::format("1. ... "); for (int i = 0; i < game.list.size(); i++) { 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]); diff --git a/src/arena/game.hpp b/src/arena/game.hpp @@ -23,12 +23,12 @@ class Game { [[nodiscard]] const std::string &get_black() const { return black; } [[nodiscard]] const Terminate get_terminate() const { return terminate; } - [[nodiscard]] const bool is_win_white() const { return !draw && winner == color::WHITE; } - [[nodiscard]] const bool is_win_black() const { return !draw && winner == color::BLACK; } + [[nodiscard]] const bool is_win_white() const { return !draw && winner == WHITE; } + [[nodiscard]] const bool is_win_black() const { return !draw && winner == BLACK; } [[nodiscard]] const bool is_draw() const { return draw; } void set_terminate(const Terminate terminate) { this->terminate = terminate; } - void set_winner(const color::Color winner) { this->winner = winner; } + void set_winner(const Color winner) { this->winner = winner; } void set_draw(const bool draw) { this->draw = draw; } static void set_san(bool san) { Game::san = san; } @@ -47,7 +47,7 @@ class Game { MoveList list; bool draw = false; - color::Color winner; + Color winner; Terminate terminate = Terminate::Deatch; static bool san; diff --git a/src/arena/match.cpp b/src/arena/match.cpp @@ -2,6 +2,7 @@ #include "logger.hpp" #include "repetition.hpp" #include "timer.hpp" +#include "utils_ui.hpp" uint16_t Match::id_t = 0; Match::~Match() { logger::log(std::format("Match {}: destroyed", id), logger::Debug); } @@ -23,11 +24,11 @@ Game Match::play(Settings swhite, Settings sblack, const std::string fen = Game: engines[0]->send("ucinewgame"); engines[1]->send("ucinewgame"); - color::Color turn = board.get_side(); + Color turn = board.get_side(); while (true) { const MoveList list = MoveList(board, false, true); if (!list.size()) { - game.set_winner(color::other(turn)); + game.set_winner(other(turn)); break; } @@ -45,15 +46,14 @@ Game Match::play(Settings swhite, Settings sblack, const std::string fen = Game: std::string move_str = response.substr(9); if ((move = parse_move(list, move_str)) == Move() || !move.make(board)) { - logger::log( - std::format("Match {}: {} illegal {}", id, color::to_string(turn), (std::string)move)); + logger::log(std::format("Match {}: {} illegal {}", id, to_string(turn), (std::string)move)); game.set_terminate(Game::Illegal); - game.set_winner(color::other(turn)); + game.set_winner(other(turn)); break; } if (rtable.is_repetition(board.get_hash())) { - logger::log(std::format("Match {}: {} repetition", id, color::to_string(turn))); + logger::log(std::format("Match {}: {} repetition", id, to_string(turn))); game.set_terminate(Game::Repetition); game.set_draw(true); break; @@ -64,21 +64,21 @@ Game Match::play(Settings swhite, Settings sblack, const std::string fen = Game: game.play(move); uint64_t time_passed = timer::get_ms() - time_start; - if (turn == color::WHITE ? swhite.time <= time_passed : sblack.time <= time_passed) { - logger::log(std::format("Match {}: {} timeout", id, color::to_string(turn))); + if (turn == WHITE ? swhite.time <= time_passed : sblack.time <= time_passed) { + logger::log(std::format("Match {}: {} timeout", id, to_string(turn))); game.set_terminate(Game::Timeout); - game.set_winner(color::other(turn)); + game.set_winner(other(turn)); break; } - if (turn == color::WHITE && !swhite.depth) swhite.time -= time_passed; - if (turn == color::BLACK && !sblack.depth) sblack.time -= time_passed; + if (turn == WHITE && !swhite.depth) swhite.time -= time_passed; + if (turn == BLACK && !sblack.depth) sblack.time -= time_passed; - turn = color::other(turn); + turn = other(turn); } if (!game.is_draw()) { - logger::log(std::format("Match {}: winner is {}", id, color::to_string(turn))); + logger::log(std::format("Match {}: winner is {}", id, to_string(turn))); } else { logger::log(std::format("Match {}: ended in a draw", id)); } @@ -87,19 +87,19 @@ Game Match::play(Settings swhite, Settings sblack, const std::string fen = Game: return game; } -std::string Match::get_go(Settings &swhite, Settings &sblack, color::Color side) { +std::string Match::get_go(Settings &swhite, Settings &sblack, Color side) { std::string go = "go"; - if (side == color::WHITE && swhite.depth) go += " depth " + std::to_string(swhite.depth); + if (side == WHITE && swhite.depth) go += " depth " + std::to_string(swhite.depth); else { - if (side == color::WHITE && swhite.togo) go += " movestogo " + std::to_string(swhite.togo); + if (side == WHITE && swhite.togo) go += " movestogo " + std::to_string(swhite.togo); if (!sblack.depth && swhite.time) go += " wtime " + std::to_string(swhite.time); if (swhite.inc) go += " winc " + std::to_string(swhite.inc); if (swhite.movetime) go += " movetime " + std::to_string(swhite.movetime); } - if (side == color::BLACK && sblack.depth) go += " depth " + std::to_string(sblack.depth); + if (side == BLACK && sblack.depth) go += " depth " + std::to_string(sblack.depth); else { - if (side == color::BLACK && sblack.togo) go += " movestogo " + std::to_string(sblack.togo); + if (side == BLACK && sblack.togo) go += " movestogo " + std::to_string(sblack.togo); if (!swhite.depth && sblack.time) go += " btime " + std::to_string(sblack.time); if (sblack.inc) go += " binc " + std::to_string(sblack.inc); if (swhite.movetime) go += " movetime " + std::to_string(sblack.movetime); @@ -108,8 +108,8 @@ std::string Match::get_go(Settings &swhite, Settings &sblack, color::Color side) } Move Match::parse_move(const MoveList list, const std::string &move_string) { - const square::Square source = square::from_coordinates(move_string.substr(0, 2)); - const square::Square target = square::from_coordinates(move_string.substr(2, 2)); + const Square source = from_coordinates(move_string.substr(0, 2)); + const Square target = from_coordinates(move_string.substr(2, 2)); for (int i = 0; i < list.size(); i++) { const Move crnt = list[i]; diff --git a/src/arena/match.hpp b/src/arena/match.hpp @@ -17,7 +17,7 @@ class Match { Game play(Settings swhite, Settings sblack, const std::string fen); private: - static std::string get_go(Settings &swhite, Settings &sblack, color::Color side); + static std::string get_go(Settings &swhite, Settings &sblack, Color side); static Move parse_move(const MoveList list, const std::string &move_string); std::array<Engine *, 2> engines; diff --git a/src/attack/attack.hpp b/src/attack/attack.hpp @@ -1,7 +1,6 @@ #ifndef STELLAR_ATTACK_H #define STELLAR_ATTACK_H -#include "square.hpp" #include "utils.hpp" #include "bishop.hpp" @@ -17,11 +16,11 @@ namespace attack { void init(void); -inline constexpr const U64 attack_pawn(const color::Color color, const square::Square from) { +inline constexpr const U64 attack_pawn(const Color color, const Square from) { return attack::pawn::attack(color, from); } -inline constexpr const U64 attack(const piece::Type type, const square::Square from, const U64 occupancy) { +inline constexpr const U64 attack(const piece::Type type, const Square from, const U64 occupancy) { switch (type) { case piece::QUEEN: return attack::queen::attack(from, occupancy); case piece::ROOK: return attack::rook::attack(from, occupancy); diff --git a/src/attack/bishop.cpp b/src/attack/bishop.cpp @@ -44,11 +44,11 @@ static inline constexpr const int relevant_bits[64] = { inline constexpr const bitboard::direction_f dir[4] = {bitboard::noEaOne, bitboard::noWeOne, bitboard::soEaOne, bitboard::soWeOne}; -inline constexpr U32 hash(const U64 key, const square::Square square) { +inline constexpr U32 hash(const U64 key, const Square square) { return (key * bishop_magic_numbers[square]) >> (64 - relevant_bits[square]); } -inline constexpr U64 mask_fly(const square::Square square, U64 block) { +inline constexpr U64 mask_fly(const Square square, U64 block) { 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)}; @@ -59,14 +59,14 @@ std::array<U64, 64> mask = {{0}}; std::array<std::array<U64, 4098>, 64> attacks = {{{0}}}; void init(void) { - for (square::Square square = square::a1; square <= square::h8; ++square) { + for (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}; mask[square] = attack::slider::mask(square, C64(0), dir, len); } - for (square::Square square = square::a1; square <= square::h8; ++square) { + for (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; @@ -79,7 +79,7 @@ void init(void) { } } -U64 attack(const square::Square square, U64 occupancy) { +U64 attack(const Square square, U64 occupancy) { occupancy &= mask[square]; occupancy = hash(occupancy, square); return attacks[square][occupancy]; diff --git a/src/attack/bishop.hpp b/src/attack/bishop.hpp @@ -1,16 +1,15 @@ #ifndef STELLAR_BISHOP_H #define STELLAR_BISHOP_H -#include "square.hpp" #include "utils.hpp" namespace attack { namespace bishop { void init(void); -U64 attack(const square::Square square, U64 occupancy); +U64 attack(const Square square, U64 occupancy); -} +} // namespace bishop } // namespace attack #endif diff --git a/src/attack/king.hpp b/src/attack/king.hpp @@ -3,7 +3,6 @@ #include "bit.hpp" #include "bitboard.hpp" -#include "square.hpp" #include "utils.hpp" #include <array> @@ -11,7 +10,7 @@ namespace attack { namespace king { -static constexpr U64 mask(const square::Square square) { +static constexpr U64 mask(const Square square) { U64 bitboard = C64(0), attacks = C64(0); bit::set(bitboard, square); @@ -28,14 +27,14 @@ typedef std::array<U64, 64> attack_array; const attack_array attacks = []() -> attack_array { std::array<U64, 64> attacks; - for (square::Square square = square::a1; square <= square::h8; ++square) { + for (Square square = Square::a1; square <= Square::h8; ++square) { attacks[square] = mask(square); } return attacks; }(); -inline constexpr U64 attack(const square::Square square) { return attacks[square]; } +inline constexpr U64 attack(const Square square) { return attacks[square]; } } // namespace king } // namespace attack diff --git a/src/attack/knight.hpp b/src/attack/knight.hpp @@ -3,7 +3,6 @@ #include "bit.hpp" #include "bitboard.hpp" -#include "square.hpp" #include "utils.hpp" #include <array> @@ -11,7 +10,7 @@ namespace attack { namespace knight { -static constexpr U64 mask(const square::Square square) { +static constexpr U64 mask(const Square square) { U64 bitboard = C64(0), attacks = C64(0), tmp; bit::set(bitboard, square); @@ -31,14 +30,14 @@ typedef std::array<U64, 64> attack_array; const attack_array attacks = []() -> attack_array { std::array<U64, 64> attacks; - for (square::Square square = square::a1; square <= square::h8; ++square) { + for (Square square = Square::a1; square <= Square::h8; ++square) { attacks[square] = mask(square); } return attacks; }(); -inline constexpr U64 attack(const square::Square square) { return attacks[square]; } +inline constexpr U64 attack(const Square square) { return attacks[square]; } } // namespace knight } // namespace attack diff --git a/src/attack/pawn.hpp b/src/attack/pawn.hpp @@ -3,8 +3,6 @@ #include "bit.hpp" #include "bitboard.hpp" -#include "color.hpp" -#include "square.hpp" #include "utils.hpp" #include <array> @@ -12,14 +10,14 @@ namespace attack { namespace pawn { -static constexpr U64 mask_white(const square::Square square) { +static constexpr U64 mask_white(const Square square) { U64 bitboard = C64(0); bit::set(bitboard, square); return bitboard::noWeOne(bitboard) | bitboard::noEaOne(bitboard); } -static constexpr U64 mask_black(const square::Square square) { +static constexpr U64 mask_black(const Square square) { U64 bitboard = C64(0); bit::set(bitboard, square); @@ -30,17 +28,15 @@ typedef std::array<std::array<U64, 64>, 2> attack_array; const auto attacks = []() { attack_array attacks; - for (square::Square square = square::a1; square <= square::h8; ++square) { - attacks[color::WHITE][square] = mask_white(square); - attacks[color::BLACK][square] = mask_black(square); + for (Square square = Square::a1; square <= Square::h8; ++square) { + attacks[WHITE][square] = mask_white(square); + attacks[BLACK][square] = mask_black(square); } return attacks; }(); -inline constexpr U64 attack(color::Color color, square::Square square) { - return attacks[color][square]; -} +inline constexpr U64 attack(Color color, Square square) { return attacks[color][square]; } } // namespace pawn } // namespace attack diff --git a/src/attack/queen.hpp b/src/attack/queen.hpp @@ -7,7 +7,7 @@ namespace attack { namespace queen { -inline U64 attack(const square::Square square, U64 occupancy) { +inline U64 attack(const Square square, U64 occupancy) { return rook::attack(square, occupancy) | bishop::attack(square, occupancy); } diff --git a/src/attack/rook.cpp b/src/attack/rook.cpp @@ -43,11 +43,11 @@ inline constexpr const U64 rook_magic_numbers[64] = { inline constexpr const bitboard::direction_f dir[4] = {bitboard::westOne, bitboard::soutOne, bitboard::eastOne, bitboard::nortOne}; -inline constexpr U32 hash(const U64 key, const square::Square square) { +inline constexpr U32 hash(const U64 key, const Square square) { return (key * rook_magic_numbers[square]) >> (64 - relevant_bits[square]); } -inline constexpr U64 mask_fly(const square::Square square, U64 block) { +inline constexpr U64 mask_fly(const Square square, U64 block) { int tr = square / 8, tf = square % 8; int len[4] = {tf, tr, 7 - tf, 7 - tr}; @@ -58,14 +58,14 @@ std::array<U64, 64> mask = {{0}}; std::array<std::array<U64, 4096>, 64> attacks = {{{0}}}; void init(void) { - for (square::Square square = square::a1; square <= square::h8; ++square) { + for (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}; mask[square] = attack::slider::mask(square, C64(0), dir, len); } - for (square::Square square = square::a1; square <= square::h8; ++square) { + for (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; @@ -78,7 +78,7 @@ void init(void) { } } -U64 attack(const square::Square square, U64 occupancy) { +U64 attack(const Square square, U64 occupancy) { occupancy &= mask[square]; occupancy = hash(occupancy, square); return attacks[square][occupancy]; diff --git a/src/attack/rook.hpp b/src/attack/rook.hpp @@ -1,14 +1,13 @@ #ifndef STELLAR_ATTACK_ROOK_H #define STELLAR_ATTACK_ROOK_H -#include "square.hpp" #include "utils.hpp" namespace attack { namespace rook { void init(void); -U64 attack(const square::Square square, U64 occupancy); +U64 attack(const Square square, U64 occupancy); } // namespace rook } // namespace attack diff --git a/src/attack/slider.hpp b/src/attack/slider.hpp @@ -3,7 +3,6 @@ #include "bit.hpp" #include "bitboard.hpp" -#include "square.hpp" #include "utils.hpp" namespace attack { @@ -22,7 +21,7 @@ inline constexpr U64 occupancy(U64 index, uint8_t bits_in_mask, U64 attack_mask) return occupancy; } -inline constexpr U64 mask(const square::Square square, U64 block, const bitboard::direction_f dir[4], +inline constexpr U64 mask(const Square square, U64 block, const bitboard::direction_f dir[4], const int len[4]) { U64 bitboard = C64(0), attacks = C64(0); bit::set(bitboard, square); diff --git a/src/bitboard/bitboard.cpp b/src/bitboard/bitboard.cpp @@ -1,10 +1,22 @@ #include "bitboard.hpp" #include "bit.hpp" +#include "piece.hpp" #include <iostream> namespace bitboard { +/* +void init() { +for (Square s1 = Square::a1; s1 <= Square::h8; ++s1) { + for (Square s2 = Square::a1; s2 <= Square::h8; ++s2) { + line[s1][s2] |= + (piece::get_attack(piece::BISHOP, s1, 0) & piece::get_attack(piece::BISHOP, s2, 0)) | s1 | s2; + } +} +} +*/ + void print(U64 bitboard) { for (int rank = 0; rank < 8; rank++) { for (int file = 0; file < 8; file++) { diff --git a/src/bitboard/bitboard.hpp b/src/bitboard/bitboard.hpp @@ -1,11 +1,11 @@ #ifndef STELLAR_BITBOARD_H #define STELLAR_BITBOARD_H -#include "square.hpp" #include "utils.hpp" namespace bitboard { +void init(void); void print(U64 bitboard); inline constexpr const U64 notAFile = C64(0xfefefefefefefefe); @@ -21,6 +21,8 @@ inline constexpr U64 soWeOne(U64 b) { return (b & notAFile) >> 9; } inline constexpr U64 noEaOne(U64 b) { return (b & notHFile) << 9; } inline constexpr U64 noWeOne(U64 b) { return (b & notAFile) << 7; } +extern U64 line[Square::no_sq][Square::no_sq]; + } // namespace bitboard #endif diff --git a/src/board/board.cpp b/src/board/board.cpp @@ -5,8 +5,7 @@ #include "board.hpp" #include "piece.hpp" -#include "square.hpp" -#include "utils.hpp" +#include "utils_ui.hpp" #include "zobrist.hpp" /* Init arrays for Zobris hashing */ @@ -21,7 +20,7 @@ Board::Board(const std::string &fen) { for (i = 0; fen[i] != ' '; i++) { if (isalpha(fen[i])) { const piece::Piece &piece = piece::get_from_code(fen[i]); - set_piece(piece.type, piece.color, static_cast<square::Square>(rank * 8 + file)); + set_piece(piece.type, piece.color, static_cast<Square>(rank * 8 + file)); file++; } else if (isdigit(fen[i])) { file += fen[i] - '0'; @@ -34,9 +33,7 @@ Board::Board(const std::string &fen) { } } - side = fen[++i] == 'w' ? color::WHITE - : fen[i] == 'b' ? color::BLACK - : throw std::runtime_error("Invalid player char"); + side = fen[++i] == 'w' ? WHITE : fen[i] == 'b' ? BLACK : throw std::runtime_error("Invalid player char"); for (i += 2; fen[i] != ' '; i++) { if (fen[i] == 'K') castle |= Castle::WK; @@ -53,7 +50,7 @@ Board::Board(const std::string &fen) { throw std::runtime_error("Invalid castle rights"); } - enpassant = fen[++i] != '-' ? square::from_coordinates(fen.substr(i, 2)) : square::no_sq; + enpassant = fen[++i] != '-' ? from_coordinates(fen.substr(i, 2)) : Square::no_sq; hash = zobrist::hash(*this); } @@ -62,7 +59,7 @@ std::ostream &operator<<(std::ostream &os, const Board &board) { for (int rank = 0; rank < 8; rank++) { for (int file = 0; file < 8; file++) { if (!file) os << 8 - rank << " "; - auto square = static_cast<square::Square>((7 - rank) * 8 + file); + auto square = static_cast<Square>((7 - rank) * 8 + file); const piece::Piece *piece = board.get_square_piece(square); os << (piece ? piece->code : '.') << " "; } @@ -70,8 +67,8 @@ std::ostream &operator<<(std::ostream &os, const Board &board) { } os << " A B C D E F G H\n"; os << " Side: "; - os << ((board.side == color::WHITE) ? "white" : "black") << "\n"; - os << "Enpassant: " << square::to_coordinates(board.enpassant) << "\n"; + os << ((board.side == WHITE) ? "white" : "black") << "\n"; + os << "Enpassant: " << to_coordinates(board.enpassant) << "\n"; os << " Castle:"; os << ((board.castle & Board::Castle::WK) ? 'K' : '-'); os << ((board.castle & Board::Castle::WQ) ? 'Q' : '-'); diff --git a/src/board/board.hpp b/src/board/board.hpp @@ -3,9 +3,7 @@ #include "attack.hpp" #include "bit.hpp" -#include "color.hpp" #include "piece.hpp" -#include "square.hpp" #include "utils.hpp" #include "zobrist.hpp" @@ -31,105 +29,101 @@ class Board { /* Getters */ [[nodiscard]] inline constexpr U64 get_hash() const; - [[nodiscard]] inline constexpr color::Color get_side() const; + [[nodiscard]] inline constexpr Color get_side() const; [[nodiscard]] inline constexpr uint8_t get_castle() const; - [[nodiscard]] inline constexpr square::Square get_enpassant() const; + [[nodiscard]] inline constexpr Square get_enpassant() const; - [[nodiscard]] inline constexpr U64 get_bitboard_color(color::Color side) const; + [[nodiscard]] inline constexpr U64 get_bitboard_color(Color side) const; [[nodiscard]] inline constexpr U64 get_bitboard_occupancy() const; [[nodiscard]] inline constexpr U64 get_bitboard_piece(piece::Type piece) const; - [[nodiscard]] inline constexpr U64 get_bitboard_piece(piece::Type piece, color::Color color) const; + [[nodiscard]] inline constexpr U64 get_bitboard_piece(piece::Type piece, Color color) const; - [[nodiscard]] inline constexpr U64 get_bitboard_piece_attacks(piece::Type piece, color::Color color, - square::Square from) const; - [[nodiscard]] inline constexpr U64 get_bitboard_piece_moves(piece::Type piece, color::Color color, - square::Square from) const; - [[nodiscard]] inline constexpr U64 get_bitboard_square_land(square::Square land, piece::Type piece, - color::Color side) const; + [[nodiscard]] inline constexpr U64 get_bitboard_piece_attacks(piece::Type piece, Color color, + Square from) const; + [[nodiscard]] inline constexpr U64 get_bitboard_piece_moves(piece::Type piece, Color color, + Square from) const; + [[nodiscard]] inline constexpr U64 get_bitboard_square_land(Square land, piece::Type piece, + Color side) const; - [[nodiscard]] inline constexpr color::Color get_square_piece_color(square::Square square) const; - [[nodiscard]] inline constexpr piece::Type get_square_piece_type(square::Square square) const; - [[nodiscard]] inline constexpr const piece::Piece *get_square_piece(square::Square square) const; + [[nodiscard]] inline constexpr Color get_square_piece_color(Square square) const; + [[nodiscard]] inline constexpr piece::Type get_square_piece_type(Square square) const; + [[nodiscard]] inline constexpr const piece::Piece *get_square_piece(Square square) const; /* Setters */ inline constexpr void xor_hash(U64 op); inline constexpr void switch_side(); inline constexpr void and_castle(uint8_t right); - inline constexpr void set_enpassant(square::Square target); + inline constexpr void set_enpassant(Square target); - inline constexpr void pop_bitboard_color(color::Color color, square::Square square); - inline constexpr void set_bitboard_color(color::Color color, square::Square square); + inline constexpr void pop_bitboard_color(Color color, Square square); + inline constexpr void set_bitboard_color(Color color, Square square); - inline constexpr void pop_bitboard_piece(piece::Type type, square::Square square); - inline constexpr void set_bitboard_piece(piece::Type type, square::Square square); + inline constexpr void pop_bitboard_piece(piece::Type type, Square square); + inline constexpr void set_bitboard_piece(piece::Type type, Square square); - inline constexpr void pop_piece(piece::Type type, color::Color side, square::Square square); - inline constexpr void set_piece(piece::Type type, color::Color side, square::Square square); + inline constexpr void pop_piece(piece::Type type, Color side, Square square); + inline constexpr void set_piece(piece::Type type, Color side, Square square); /* Queries */ - [[nodiscard]] inline constexpr bool is_square_attacked(square::Square square, color::Color side) const; - [[nodiscard]] inline constexpr bool is_square_occupied(square::Square square) const; - [[nodiscard]] inline constexpr bool is_piece_attack_square(piece::Type type, color::Color color, - square::Square source, - square::Square target) const; + [[nodiscard]] inline constexpr bool is_square_attacked(Square square, Color side) const; + [[nodiscard]] inline constexpr bool is_square_occupied(Square square) const; + [[nodiscard]] inline constexpr bool is_piece_attack_square(piece::Type type, Color color, Square source, + Square target) const; [[nodiscard]] inline constexpr bool is_check() const; private: U64 colors[2] = {0}; U64 pieces[6] = {0}; U64 hash = 0; - color::Color side = color::WHITE; - square::Square enpassant = square::Square::no_sq; + Color side = WHITE; + Square enpassant = Square::no_sq; uint8_t castle = 0; }; -constexpr color::Color Board::get_side() const { return side; } +constexpr Color Board::get_side() const { return side; } 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 Square Board::get_enpassant() const { return enpassant; } -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_color(Color side) const { return colors[side]; } +constexpr U64 Board::get_bitboard_occupancy() const { return colors[WHITE] | colors[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 { +constexpr U64 Board::get_bitboard_piece(piece::Type piece, Color color) const { return pieces[piece] & colors[color]; } -constexpr U64 Board::get_bitboard_piece_attacks(piece::Type type, color::Color color, - square::Square from) const { +constexpr U64 Board::get_bitboard_piece_attacks(piece::Type type, Color color, Square from) const { if (type == piece::PAWN) return attack::attack_pawn(color, from); return attack::attack(type, from, get_bitboard_occupancy()); } -constexpr U64 Board::get_bitboard_piece_moves(piece::Type type, color::Color color, - square::Square square) const { +constexpr U64 Board::get_bitboard_piece_moves(piece::Type type, Color color, Square square) const { return get_bitboard_piece_attacks(type, color, square) & ~get_bitboard_color(color); } -constexpr U64 Board::get_bitboard_square_land(square::Square land, piece::Type piece, - color::Color side) const { +constexpr U64 Board::get_bitboard_square_land(Square land, piece::Type piece, Color side) const { - return get_bitboard_piece_attacks(piece, color::other(side), land) & get_bitboard_piece(piece, side); + return get_bitboard_piece_attacks(piece, other(side), land) & get_bitboard_piece(piece, side); } -constexpr color::Color Board::get_square_piece_color(square::Square square) const { - if (bit::get(colors[color::WHITE], square)) return color::WHITE; - if (bit::get(colors[color::BLACK], square)) return color::BLACK; +constexpr Color Board::get_square_piece_color(Square square) const { + if (bit::get(colors[WHITE], square)) return WHITE; + if (bit::get(colors[BLACK], square)) return BLACK; throw std::exception(); } -constexpr piece::Type Board::get_square_piece_type(square::Square square) const { +constexpr piece::Type Board::get_square_piece_type(Square square) const { for (piece::Type type = piece::PAWN; type <= piece::KING; ++type) { if (bit::get(pieces[type], square)) return type; } return piece::Type::NONE; } -constexpr const piece::Piece *Board::get_square_piece(square::Square square) const { +constexpr const piece::Piece *Board::get_square_piece(Square square) const { try { return &piece::get(get_square_piece_type(square), get_square_piece_color(square)); } catch (std::exception &e) { @@ -147,50 +141,39 @@ constexpr void Board::and_castle(uint8_t right) { } constexpr void Board::switch_side() { - side = color::other(side); + side = other(side); hash ^= zobrist::key_side(); } -constexpr void Board::set_enpassant(square::Square target) { - if (enpassant != square::Square::no_sq) hash ^= zobrist::key_enpassant(enpassant); - if (target != square::Square::no_sq) hash ^= zobrist::key_enpassant(target); +constexpr void Board::set_enpassant(Square target) { + if (enpassant != Square::no_sq) hash ^= zobrist::key_enpassant(enpassant); + if (target != Square::no_sq) hash ^= zobrist::key_enpassant(target); enpassant = target; } -constexpr void Board::pop_bitboard_color(color::Color color, square::Square square) { - bit::pop(colors[color], square); -} - -constexpr void Board::set_bitboard_color(color::Color color, square::Square square) { - bit::set(colors[color], square); -} - -constexpr void Board::pop_bitboard_piece(piece::Type type, square::Square square) { - bit::pop(pieces[type], square); -} - -constexpr void Board::set_bitboard_piece(piece::Type type, square::Square square) { - bit::set(pieces[type], square); -} +constexpr void Board::pop_bitboard_color(Color color, Square square) { bit::pop(colors[color], square); } +constexpr void Board::set_bitboard_color(Color color, Square square) { bit::set(colors[color], square); } +constexpr void Board::pop_bitboard_piece(piece::Type type, Square square) { bit::pop(pieces[type], square); } +constexpr void Board::set_bitboard_piece(piece::Type type, Square square) { bit::set(pieces[type], square); } -constexpr void Board::pop_piece(piece::Type type, color::Color side, square::Square square) { +constexpr void Board::pop_piece(piece::Type type, Color side, Square square) { pop_bitboard_color(side, square); pop_bitboard_piece(type, square); } -constexpr void Board::set_piece(piece::Type type, color::Color side, square::Square square) { +constexpr void Board::set_piece(piece::Type type, Color side, Square square) { set_bitboard_color(side, square); set_bitboard_piece(type, square); } /* Queries */ -constexpr bool Board::is_square_occupied(square::Square square) const { +constexpr bool Board::is_square_occupied(Square square) const { 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); +constexpr bool Board::is_square_attacked(Square square, Color side) const { + const Color side_other = other(side); for (piece::Type type = piece::PAWN; type <= piece::KING; ++type) { if (get_bitboard_piece_attacks(type, side_other, square) & get_bitboard_piece(type, side)) { @@ -201,15 +184,15 @@ constexpr bool Board::is_square_attacked(square::Square square, color::Color sid return false; } -constexpr bool Board::is_piece_attack_square(piece::Type type, color::Color color, square::Square source, - square::Square target) const { +constexpr bool Board::is_piece_attack_square(piece::Type type, Color color, Square source, + Square target) const { return get_bitboard_piece_attacks(type, color, source) & (C64(1) << target); } constexpr bool Board::is_check() const { 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)); + Color side_other = (side == BLACK) ? WHITE : BLACK; + auto square = static_cast<Square>(bit::lsb_index(king)); return is_square_attacked(square, side_other); } @@ -218,19 +201,19 @@ U64 zobrist::hash(const Board &board) { uint8_t square = 0; 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); + int piece_white_index = piece::get_index(type, WHITE); + U64 bitboard_white = board.get_bitboard_piece(type, WHITE); bitboard_for_each_bit(square, bitboard_white) { key_final ^= keys_piece[piece_white_index][square]; } - int piece_black_index = piece::get_index(type, color::BLACK); - U64 bitboard_black = board.get_bitboard_piece(type, color::BLACK); + int piece_black_index = piece::get_index(type, BLACK); + U64 bitboard_black = board.get_bitboard_piece(type, BLACK); bitboard_for_each_bit(square, bitboard_black) { key_final ^= keys_piece[piece_black_index][square]; } } 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[board.get_enpassant()]; + if (board.get_side() == BLACK) key_final ^= keys_side; + if (board.get_enpassant() != 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 @@ -20,8 +20,8 @@ const U64 keys_side = Random(C32(1699391443))(); inline void init() { Random gen1(C64(1804289383)); 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; + int piece_index_white = piece::get(type, Color::WHITE).index; + int piece_index_black = piece::get(type, Color::BLACK).index; for (int square = 0; square < 64; square++) { keys_piece[piece_index_white][square] = gen1(); keys_piece[piece_index_black][square] = gen1(); @@ -42,8 +42,8 @@ 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[square]; } -inline constexpr U64 key_piece(piece::Type type, color::Color color, square::Square square) { +inline constexpr U64 key_enpassant(Square square) { return keys_enpassant[square]; } +inline constexpr U64 key_piece(piece::Type type, Color color, Square square) { return keys_piece[piece::get_index(type, color)][square]; } diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp @@ -194,7 +194,7 @@ int stats_move_make(Board &copy, const Move move) { void stats_move_make_pruning(Board &copy) { copy = board; board.switch_side(); - board.set_enpassant(square::no_sq); + board.set_enpassant(Square::no_sq); ply++; } diff --git a/src/engine/evaluate.cpp b/src/engine/evaluate.cpp @@ -3,7 +3,6 @@ #include "bitboard.hpp" #include "piece.hpp" #include "score.hpp" -#include "square.hpp" #include "utils.hpp" #include <array> @@ -83,7 +82,7 @@ uint16_t score_game_phase(const Board &board) { return total; } -int16_t score_position_side(const Board &board, const color::Color side, const uint16_t phase_score) { +int16_t score_position_side(const Board &board, const Color side, const uint16_t phase_score) { U64 bitboard; int16_t total = 0, opening = 0, endgame = 0; @@ -95,12 +94,12 @@ int16_t score_position_side(const Board &board, const color::Color side, const u bitboard = board.get_bitboard_piece(PAWN, side); bitboard_for_each_bit(square_i, bitboard) { - const auto square = static_cast<square::Square>(square_i); + const auto square = static_cast<Square>(square_i); opening += score::get(PAWN, side, square, OPENING) + score::get(PAWN, OPENING); endgame += score::get(PAWN, side, square, ENDGAME) + score::get(PAWN, ENDGAME); // check isolated, doubled and passed pawns - const uint8_t file = square::file(square), rank = square::rank(square); + const uint8_t file = get_file(square), rank = get_rank(square); if (!(mask_isolated[file] & pawnsS)) { opening -= score::pawn_isolated_opening; endgame -= score::pawn_isolated_endgame; @@ -116,45 +115,45 @@ int16_t score_position_side(const Board &board, const color::Color side, const u bitboard = board.get_bitboard_piece(KNIGHT, side); bitboard_for_each_bit(square_i, bitboard) { - const auto square = static_cast<square::Square>(square_i); + const auto square = static_cast<Square>(square_i); opening += score::get(KNIGHT, side, square, OPENING) + score::get(KNIGHT, OPENING); endgame += score::get(KNIGHT, side, square, ENDGAME) + score::get(KNIGHT, ENDGAME); } bitboard = board.get_bitboard_piece(BISHOP, side); bitboard_for_each_bit(square_i, bitboard) { - const auto square = static_cast<square::Square>(square_i); + const auto square = static_cast<Square>(square_i); opening += score::get(BISHOP, side, square, OPENING) + score::get(BISHOP, OPENING); endgame += score::get(BISHOP, side, square, ENDGAME) + score::get(BISHOP, ENDGAME); } bitboard = board.get_bitboard_piece(ROOK, side); bitboard_for_each_bit(square_i, bitboard) { - const auto square = static_cast<square::Square>(square_i); + const auto square = static_cast<Square>(square_i); opening += score::get(ROOK, side, square, OPENING) + score::get(ROOK, OPENING); endgame += score::get(ROOK, side, square, ENDGAME) + score::get(ROOK, ENDGAME); // rook on open and semi-open files - const uint8_t file = square::file(square); + const uint8_t file = get_file(square); if (!(pawns & mask_file[file])) total += score::file_open; if (!(pawnsS & mask_file[file])) total += score::file_open_semi; } bitboard = board.get_bitboard_piece(QUEEN, side); bitboard_for_each_bit(square_i, bitboard) { - const auto square = static_cast<square::Square>(square_i); + const auto square = static_cast<Square>(square_i); opening += score::get(QUEEN, side, square, OPENING) + score::get(QUEEN, OPENING); endgame += score::get(QUEEN, side, square, ENDGAME) + score::get(QUEEN, ENDGAME); } bitboard = board.get_bitboard_piece(KING, side); bitboard_for_each_bit(square_i, bitboard) { - const auto square = static_cast<square::Square>(square_i); + const auto square = static_cast<Square>(square_i); opening += score::get(KING, side, square, OPENING) + score::get(KING, OPENING); endgame += score::get(KING, side, square, ENDGAME) + score::get(KING, ENDGAME); // king on open and semi-open files - const uint8_t file = square::file(square); + const uint8_t file = get_file(square); if (!(pawns & mask_file[file])) total -= score::file_open; if (!(pawnsS & mask_file[file])) total -= score::file_open_semi; } @@ -167,9 +166,9 @@ int16_t score_position_side(const Board &board, const color::Color side, const u int16_t score_position(const Board &board) { const uint16_t phase_score = score_game_phase(board); - const int16_t score = score_position_side(board, color::WHITE, phase_score) - - score_position_side(board, color::BLACK, phase_score); - return board.get_side() == color::WHITE ? score : -score; + const int16_t score = + score_position_side(board, WHITE, phase_score) - score_position_side(board, BLACK, phase_score); + return board.get_side() == WHITE ? score : -score; } } // namespace evaluate diff --git a/src/engine/score.hpp b/src/engine/score.hpp @@ -150,9 +150,8 @@ inline constexpr int16_t get(const piece::Type piece, const Phase phase = OPENIN return value[phase][piece]; } -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); +inline constexpr int16_t get(piece::Type piece, Color color, Square square, Phase phase = ENDGAME) { + if (color != WHITE) square = get_mirror(square); return position[phase][piece][square]; } diff --git a/src/engine/uci.cpp b/src/engine/uci.cpp @@ -18,8 +18,8 @@ void communicate(const uci::Settings *settings) { } inline bool parse_move(const Board &board, Move &move, const std::string &move_string) { - const square::Square source = square::from_coordinates(move_string.substr(0, 2)); - const square::Square target = square::from_coordinates(move_string.substr(2, 2)); + const Square source = from_coordinates(move_string.substr(0, 2)); + const Square target = from_coordinates(move_string.substr(2, 2)); const MoveList list(board); for (int i = 0; i < list.size(); i++) { @@ -85,8 +85,7 @@ void loop() { uint16_t winc = 0, binc = 0, movestogo = 60; while (iss >> command) { - if (command == "wtime") - iss >> wtime; + if (command == "wtime") iss >> wtime; else if (command == "btime") iss >> btime; else if (command == "winc") @@ -116,13 +115,13 @@ void loop() { } settings.starttime = timer::get_ms(); - uint64_t time = (board.get_side() == color::WHITE) ? wtime : btime; + uint64_t time = (board.get_side() == WHITE) ? wtime : btime; if (movetime != 0) { time = movetime; movestogo = 1; } else if (time != 0) { - uint16_t inc = (board.get_side() == color::WHITE) ? winc : binc; + uint16_t inc = (board.get_side() == WHITE) ? winc : binc; time /= movestogo; time -= 50; settings.stoptime = settings.starttime + time + inc; diff --git a/src/engine/uci.hpp b/src/engine/uci.hpp @@ -6,6 +6,7 @@ #include "movelist.hpp" #include "score.hpp" #include "utils.hpp" +#include "utils_ui.hpp" namespace uci { diff --git a/src/move/move.cpp b/src/move/move.cpp @@ -1,21 +1,21 @@ #include "move.hpp" #include "utils.hpp" +#include "utils_ui.hpp" #include <algorithm> #include <iomanip> -void Move::piece_remove(Board &board, piece::Type type, color::Color color, square::Square square) const { +void Move::piece_remove(Board &board, piece::Type type, Color color, Square square) const { board.pop_piece(type, color, square); board.xor_hash(zobrist::key_piece(type, color, square)); } -void Move::piece_set(Board &board, piece::Type type, color::Color color, square::Square square) const { +void Move::piece_set(Board &board, piece::Type type, Color color, Square square) const { board.set_piece(type, color, square); board.xor_hash(zobrist::key_piece(type, color, square)); } -void Move::piece_move(Board &board, piece::Type type, color::Color color, square::Square source, - square::Square target) const { +void Move::piece_move(Board &board, piece::Type type, Color color, Square source, Square target) const { piece_remove(board, type, color, source); piece_set(board, type, color, target); } @@ -37,11 +37,10 @@ bool Move::make(Board &board) const { // clang-format on }; - const color::Color color = board.get_side(), colorOther = color::other(color); - const square::Square source = this->source(), target = this->target(); + const Color color = board.get_side(), colorOther = other(color); + const Square source = this->source(), target = this->target(); - const auto ntarget = - static_cast<square::Square>(this->target() + (color == color::Color::WHITE ? -8 : +8)); + const auto ntarget = static_cast<Square>(this->target() + (color == Color::WHITE ? -8 : +8)); const piece::Type piece = board.get_square_piece_type(source); @@ -67,19 +66,15 @@ bool Move::make(Board &board) const { } } - board.set_enpassant(is_double() ? ntarget : square::Square::no_sq); + board.set_enpassant(is_double() ? ntarget : Square::no_sq); if (is_castle()) { - if (color == color::Color::WHITE) { - if (is_castle_king()) - piece_move(board, ROOK, color::Color::WHITE, square::Square::h1, square::Square::f1); - if (is_castle_queen()) - piece_move(board, ROOK, color::Color::WHITE, square::Square::a1, square::Square::d1); + if (color == Color::WHITE) { + if (is_castle_king()) piece_move(board, ROOK, Color::WHITE, Square::h1, Square::f1); + if (is_castle_queen()) piece_move(board, ROOK, Color::WHITE, Square::a1, Square::d1); } else { - if (is_castle_king()) - piece_move(board, ROOK, color::Color::BLACK, square::Square::h8, square::Square::f8); - if (is_castle_queen()) - piece_move(board, ROOK, color::Color::BLACK, square::Square::a8, square::Square::d8); + if (is_castle_king()) piece_move(board, ROOK, Color::BLACK, Square::h8, Square::f8); + if (is_castle_queen()) piece_move(board, ROOK, Color::BLACK, Square::a8, Square::d8); } } @@ -93,8 +88,8 @@ bool Move::make(Board &board) const { } void Move::print() const { - std::cout << square::to_coordinates(source()) << " "; - std::cout << square::to_coordinates(target()) << " "; + std::cout << to_coordinates(source()) << " "; + std::cout << to_coordinates(target()) << " "; std::cout << (is_promote() ? piece::get_code(promoted()) : '.') << " "; std::cout << is_double() << " "; std::cout << is_enpassant() << " "; @@ -102,7 +97,7 @@ void Move::print() const { } Move::operator std::string() const { - std::string res = square::to_coordinates(source()) + square::to_coordinates(target()); + std::string res = to_coordinates(source()) + to_coordinates(target()); if (is_promote()) res += piece::get_code(promoted()); return res; } diff --git a/src/move/move.hpp b/src/move/move.hpp @@ -28,15 +28,14 @@ struct Move { }; Move() : source_i(0), target_i(0), flags_i(0) {} - Move(square::Square source, square::Square target, Flag flags) - : source_i(source), target_i(target), flags_i(flags) {} + Move(Square source, Square target, Flag 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; } - [[nodiscard]] square::Square source() const { return static_cast<square::Square>(source_i); } - [[nodiscard]] square::Square target() const { return static_cast<square::Square>(target_i); } + [[nodiscard]] Square source() const { return static_cast<Square>(source_i); } + [[nodiscard]] Square target() const { return static_cast<Square>(target_i); } [[nodiscard]] bool is_capture() const { return flags_i != PQUIET && (flags_i & CAPTURE); } [[nodiscard]] bool is_promote() const { return flags_i & 0x8; } @@ -60,10 +59,9 @@ struct Move { void print() const; private: - inline void piece_remove(Board &board, piece::Type type, color::Color color, square::Square square) const; - inline void piece_set(Board &board, piece::Type type, color::Color color, square::Square square) const; - inline void piece_move(Board &board, piece::Type type, color::Color color, square::Square source, - square::Square target) const; + inline void piece_remove(Board &board, piece::Type type, Color color, Square square) const; + inline void piece_set(Board &board, piece::Type type, Color color, Square square) const; + inline void piece_move(Board &board, piece::Type type, Color color, Square source, Square target) const; unsigned source_i : 6; unsigned target_i : 6; diff --git a/src/move/movelist.cpp b/src/move/movelist.cpp @@ -1,30 +1,29 @@ #include "movelist.hpp" -#include "color.hpp" #include "piece.hpp" #include <iomanip> #define pawn_canPromote(color, source) \ - ((color == color::WHITE && source >= square::a7 && source <= square::h7) || \ - (color == color::BLACK && source >= square::a2 && source <= square::h2)) + ((color == WHITE && source >= Square::a7 && source <= Square::h7) || \ + (color == BLACK && source >= Square::a2 && source <= Square::h2)) #define pawn_onStart(color, source) \ - ((color == color::BLACK && source >= square::a7 && source <= square::h7) || \ - (color == color::WHITE && source >= square::a2 && source <= square::h2)) + ((color == BLACK && source >= Square::a7 && source <= Square::h7) || \ + (color == WHITE && source >= Square::a2 && source <= Square::h2)) using piece::Type::PAWN; void MoveList::generate(const Board &board, bool attacks_only) { uint8_t src_i = 0, tgt_i = 0; - const color::Color color = board.get_side(), colorOther = color::other(color); + const Color color = board.get_side(), colorOther = other(color); // pawn moves - const int add = (color == color::WHITE) ? +8 : -8; + const int add = (color == WHITE) ? +8 : -8; U64 bitboard = board.get_bitboard_piece(PAWN, color); bitboard_for_each_bit(src_i, bitboard) { - const auto src = static_cast<square::Square>(src_i); - const auto tgt = static_cast<square::Square>(tgt_i = src_i + add); + const auto src = static_cast<Square>(src_i); + const auto tgt = static_cast<Square>(tgt_i = src_i + add); if (!attacks_only && !board.is_square_occupied(tgt)) { if (pawn_canPromote(color, src)) { list.emplace_back(src, tgt, Move::PKNIGHT); @@ -35,7 +34,7 @@ void MoveList::generate(const Board &board, bool attacks_only) { list.emplace_back(src, tgt, Move::PQUIET); // two ahead - const auto tgt = static_cast<square::Square>(tgt_i + add); + const auto tgt = static_cast<Square>(tgt_i + add); if (pawn_onStart(color, src) && !board.is_square_occupied(tgt)) list.emplace_back(src, tgt, Move::DOUBLE); } @@ -45,7 +44,7 @@ void MoveList::generate(const Board &board, bool attacks_only) { U64 attack = board.get_bitboard_piece_attacks(PAWN, color, src) & board.get_bitboard_color(colorOther); bitboard_for_each_bit(tgt_i, attack) { - const auto tgt = static_cast<square::Square>(tgt_i); + const auto tgt = static_cast<Square>(tgt_i); if (pawn_canPromote(color, src)) { list.emplace_back(src, tgt, Move::PCKNIGHT); list.emplace_back(src, tgt, Move::PCBISHOP); @@ -57,8 +56,8 @@ void MoveList::generate(const Board &board, bool attacks_only) { } // en passant - const square::Square enpassant = board.get_enpassant(); - if (enpassant != square::no_sq && board.is_piece_attack_square(PAWN, color, src, enpassant)) + const Square enpassant = board.get_enpassant(); + if (enpassant != Square::no_sq && board.is_piece_attack_square(PAWN, color, src, enpassant)) list.emplace_back(src, enpassant, Move::ENPASSANT); } @@ -66,10 +65,10 @@ void MoveList::generate(const Board &board, bool attacks_only) { 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); + const auto src = static_cast<Square>(src_i); U64 attack = board.get_bitboard_piece_moves(type, color, src); bitboard_for_each_bit(tgt_i, attack) { - const auto tgt = static_cast<square::Square>(tgt_i); + const auto tgt = static_cast<Square>(tgt_i); if (board.is_square_occupied(tgt)) { list.emplace_back(src, tgt, Move::CAPTURE); } else { @@ -83,34 +82,32 @@ void MoveList::generate(const Board &board, bool attacks_only) { if (attacks_only) return; // Castling - if (color == color::WHITE) { - if (!board.is_square_attacked(square::e1, color::BLACK)) { + if (color == WHITE) { + if (!board.is_square_attacked(Square::e1, BLACK)) { 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.is_square_occupied(Square::f1) && !board.is_square_occupied(Square::g1) && + !board.is_square_attacked(Square::f1, BLACK)) + list.emplace_back(Square::e1, Square::g1, Move::CASTLEK); } 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) && - !board.is_square_attacked(square::c1, color::BLACK)) - list.emplace_back(square::e1, square::c1, Move::CASTLEQ); + 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, BLACK) && + !board.is_square_attacked(Square::c1, BLACK)) + list.emplace_back(Square::e1, Square::c1, Move::CASTLEQ); } } } else { - if (!board.is_square_attacked(square::e8, color::WHITE)) { + if (!board.is_square_attacked(Square::e8, WHITE)) { 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.is_square_occupied(Square::f8) && !board.is_square_occupied(Square::g8) && + !board.is_square_attacked(Square::f8, WHITE)) + list.emplace_back(Square::e8, Square::g8, Move::CASTLEK); } 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) && - !board.is_square_attacked(square::c8, color::WHITE)) - list.emplace_back(square::e8, square::c8, Move::CASTLEQ); + 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, WHITE) && + !board.is_square_attacked(Square::c8, WHITE)) + list.emplace_back(Square::e8, Square::c8, Move::CASTLEQ); } } } diff --git a/src/move/movelist.hpp b/src/move/movelist.hpp @@ -21,7 +21,7 @@ class MoveList { if (!legal) return; int size = 0; - for (const auto& move : list) { + for (const auto &move : list) { Board copy = board; if (move.make(copy)) list[size++] = move; } diff --git a/src/perft/perft.cpp b/src/perft/perft.cpp @@ -12,7 +12,7 @@ #define tricky_position "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1 " enum { -THREAD_MAX = 64 + THREAD_MAX = 64 }; class Perft { @@ -68,8 +68,7 @@ class Perft { Board copy = board; if (!list[i].make(copy)) continue; // debug(board, list[i], copy); - if (depth != 1) - test(copy, depth - 1); + if (depth != 1) test(copy, depth - 1); else score(copy, list[i]); } diff --git a/src/piece/piece.hpp b/src/piece/piece.hpp @@ -1,10 +1,10 @@ #ifndef STELLAR_PIECE_H #define STELLAR_PIECE_H -#include "color.hpp" #include "utils.hpp" #include <cctype> +#include <exception> namespace piece { @@ -23,42 +23,40 @@ ENABLE_INCR_OPERATORS_ON(Type) struct Piece { const uint8_t index; const Type type; - const color::Color color; + const Color color; const char code; }; inline constexpr const Piece table[2][6] = { // clang-format off { - { .index = 0, .type = PAWN, .color = color::WHITE, .code = 'P' }, - { .index = 1, .type = KNIGHT, .color = color::WHITE, .code = 'N' }, - { .index = 2, .type = BISHOP, .color = color::WHITE, .code = 'B' }, - { .index = 3, .type = ROOK, .color = color::WHITE, .code = 'R' }, - { .index = 4, .type = QUEEN, .color = color::WHITE, .code = 'Q' }, - { .index = 5, .type = KING, .color = color::WHITE, .code = 'K' }, + { .index = 0, .type = PAWN, .color = WHITE, .code = 'P' }, + { .index = 1, .type = KNIGHT, .color = WHITE, .code = 'N' }, + { .index = 2, .type = BISHOP, .color = WHITE, .code = 'B' }, + { .index = 3, .type = ROOK, .color = WHITE, .code = 'R' }, + { .index = 4, .type = QUEEN, .color = WHITE, .code = 'Q' }, + { .index = 5, .type = KING, .color = WHITE, .code = 'K' }, }, { - { .index = 6, .type = PAWN, .color = color::BLACK, .code = 'p' }, - { .index = 7, .type = KNIGHT, .color = color::BLACK, .code = 'n' }, - { .index = 8, .type = BISHOP, .color = color::BLACK, .code = 'b' }, - { .index = 9, .type = ROOK, .color = color::BLACK, .code = 'r' }, - {.index = 10, .type = QUEEN, .color = color::BLACK, .code = 'q' }, - {.index = 11, .type = KING, .color = color::BLACK, .code = 'k' }, + { .index = 6, .type = PAWN, .color = BLACK, .code = 'p' }, + { .index = 7, .type = KNIGHT, .color = BLACK, .code = 'n' }, + { .index = 8, .type = BISHOP, .color = BLACK, .code = 'b' }, + { .index = 9, .type = ROOK, .color = BLACK, .code = 'r' }, + {.index = 10, .type = QUEEN, .color = BLACK, .code = 'q' }, + {.index = 11, .type = KING, .color = BLACK, .code = 'k' }, }, // clang-format on }; -inline constexpr const Piece &get(const Type type, const color::Color color) { return table[color][type]; } +inline constexpr const Piece &get(const Type type, const Color color) { return table[color][type]; } -inline constexpr const char get_code(const Type type, const color::Color color = color::BLACK) { +inline constexpr const char get_code(const Type type, const Color color = BLACK) { return get(type, color).code; } -inline constexpr const U64 get_index(const Type type, const color::Color color) { - return get(type, color).index; -} +inline constexpr const U64 get_index(const Type type, const Color color) { return get(type, color).index; } inline constexpr const Piece &get_from_code(const char code) { - color::Color color = isupper(code) ? color::WHITE : color::BLACK; + Color color = isupper(code) ? WHITE : BLACK; for (Type type = PAWN; type <= KING; ++type) { const Piece &piece = get(type, color); diff --git a/src/utils/color.hpp b/src/utils/color.hpp @@ -1,20 +0,0 @@ -#ifndef STELLAR_COLOR_H -#define STELLAR_COLOR_H - -#include <string> - -namespace color { - -enum Color { - WHITE = 0, - BLACK -}; - -inline constexpr const Color other(const Color color) { return color == WHITE ? BLACK : WHITE; } -inline constexpr const std::string to_string(const Color color) { - return std::string(color == WHITE ? "white" : "black"); -} - -} // namespace color - -#endif diff --git a/src/utils/repetition.hpp b/src/utils/repetition.hpp @@ -1,6 +1,11 @@ #ifndef STELLAR_REPETITION_H #define STELLAR_REPETITION_H +#include <iostream> +#include <vector> + +#include "utils.hpp" + namespace repetition { class Table { diff --git a/src/utils/square.hpp b/src/utils/square.hpp @@ -1,61 +0,0 @@ -#ifndef STELLAR_SQUARE_H -#define STELLAR_SQUARE_H - -#include "utils.hpp" -#include <string> - -namespace square { - -enum Square : int { - // clang-format off - a1, b1, c1, d1, e1, f1, g1, h1, - a2, b2, c2, d2, e2, f2, g2, h2, - a3, b3, c3, d3, e3, f3, g3, h3, - a4, b4, c4, d4, e4, f4, g4, h4, - a5, b5, c5, d5, e5, f5, g5, h5, - a6, b6, c6, d6, e6, f6, g6, h6, - a7, b7, c7, d7, e7, f7, g7, h7, - a8, b8, c8, d8, e8, f8, g8, h8, no_sq - // clang-format on -}; - -ENABLE_INCR_OPERATORS_ON(Square) - -inline constexpr const Square mirror_array[]{ - // clang-format off - a8, b8, c8, d8, e8, f8, g8, h8, - a7, b7, c7, d7, e7, f7, g7, h7, - a6, b6, c6, d6, e6, f6, g6, h6, - a5, b5, c5, d5, e5, f5, g5, h5, - a4, b4, c4, d4, e4, f4, g4, h4, - a3, b3, c3, d3, e3, f3, g3, h3, - a2, b2, c2, d2, e2, f2, g2, h2, - a1, b1, c1, d1, e1, f1, g1, h1, no_sq - // clang-format on -}; - -inline constexpr const char *coordinates_array[] = { - // clang-format off - "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", - "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", - "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3", - "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4", - "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5", - "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6", - "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7", - "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8", " " - // clang-format on -}; - -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[square]; } - -inline const Square from_coordinates(const std::string &cord) { - return static_cast<Square>((cord[1] - '1') * 8 + (cord[0] - 'a')); -} - -} // namespace square - -#endif diff --git a/src/utils/utils.hpp b/src/utils/utils.hpp @@ -1,5 +1,5 @@ -#ifndef STELLAR_UTILS_CPP_H -#define STELLAR_UTILS_CPP_H +#ifndef STELLAR_UTILS_HPP +#define STELLAR_UTILS_HPP #include <cstdint> @@ -13,4 +13,48 @@ typedef uint32_t U32; inline T &operator++(T &d) { return d = T(int(d) + 1); } \ inline T &operator--(T &d) { return d = T(int(d) - 1); } +/* Color */ + +enum Color { + WHITE, + BLACK, + COLOR_NB = 2 +}; + +inline constexpr const Color other(const Color color) { return color == WHITE ? BLACK : WHITE; } + +/* Square */ + +enum Square : int { + // clang-format off + a1, b1, c1, d1, e1, f1, g1, h1, + a2, b2, c2, d2, e2, f2, g2, h2, + a3, b3, c3, d3, e3, f3, g3, h3, + a4, b4, c4, d4, e4, f4, g4, h4, + a5, b5, c5, d5, e5, f5, g5, h5, + a6, b6, c6, d6, e6, f6, g6, h6, + a7, b7, c7, d7, e7, f7, g7, h7, + a8, b8, c8, d8, e8, f8, g8, h8, no_sq + // clang-format on +}; + +ENABLE_INCR_OPERATORS_ON(Square) + +constexpr const Square mirror_array[]{ + // clang-format off + a8, b8, c8, d8, e8, f8, g8, h8, + a7, b7, c7, d7, e7, f7, g7, h7, + a6, b6, c6, d6, e6, f6, g6, h6, + a5, b5, c5, d5, e5, f5, g5, h5, + a4, b4, c4, d4, e4, f4, g4, h4, + a3, b3, c3, d3, e3, f3, g3, h3, + a2, b2, c2, d2, e2, f2, g2, h2, + a1, b1, c1, d1, e1, f1, g1, h1, no_sq + // clang-format on +}; + +constexpr uint8_t get_file(const Square square) { return square & 0x07; } +constexpr uint8_t get_rank(const Square square) { return square >> 3; } +constexpr Square get_mirror(const Square square) { return mirror_array[square]; } + #endif diff --git a/src/utils/utils_ui.hpp b/src/utils/utils_ui.hpp @@ -0,0 +1,35 @@ +#ifndef STELLAR_UTILS_UI_HPP +#define STELLAR_UTILS_UI_HPP + +#include <string> + +#include "utils.hpp" + +/* Color */ + +constexpr const std::string to_string(const Color color) { + return std::string(color == WHITE ? "white" : "black"); +} + +/* Square */ + +constexpr const char *coordinates_array[] = { + // clang-format off + "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", + "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", + "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3", + "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4", + "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5", + "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6", + "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7", + "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8", " " + // clang-format on +}; + +constexpr const std::string to_coordinates(const Square square) { return coordinates_array[square]; } + +constexpr Square from_coordinates(const std::string &cord) { + return static_cast<Square>((cord[1] - '1') * 8 + (cord[0] - 'a')); +} + +#endif