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:
M CMakeLists.txt | + -
M src/arena/game.cpp | ++ --
M src/arena/logger.hpp | + -
M src/arena/match.cpp | + -
M src/attack/bishop.cpp | +++++++++++ ----------------
M src/attack/king.hpp | +++++++ ------
M src/attack/knight.hpp | +++++++ ------
M src/attack/pawnb.hpp | +++++++ ------
M src/attack/pawnw.hpp | +++++++ ------
M src/attack/rook.cpp | +++++++++++ ----------------
M src/attack/slider.hpp | + -
M src/board/board.cpp | ++++++++ --------
M src/board/board.hpp | +++++++++++++++++++ ------------------------
M src/board/zobrist.hpp | +++ ---
M src/engine/engine.cpp | +++ ---
M src/engine/evaluate.cpp | + --
M src/engine/score.hpp | ++++++ -----
M src/move/move.cpp | ++ ---
M src/move/move.hpp | + -
M src/move/movelist.cpp | +++++ -----
M src/piece/piece.hpp | +++ --
M src/utils/bitboard.cpp | ++
M src/utils/bitboard.hpp | +
M src/utils/square.hpp | +++++ --------
M src/utils/utils.hpp | +++ --------------------------

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