stellar

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

commit2f3a26c1d985412b453547ebd5c01190e378684e
parentfcde3f48c51361419b4d2f43652dd622e50660b7
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateWed, 13 Mar 2024 19:54:46 +0000

Beter enum handling, get rid of to_underlying()

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