stellar

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

commit 8bfcd0ddad32537cc686a87dc8200626e7be81d5
parent 9f2c299a72ac90aa9d2a927666375cc5b6d527b3
author Dimitrije Dobrota <mail@dimitrijedobrota.com>
date Wed, 13 Mar 2024 21:48:55 +0000

Move Type enum to utils

Diffstat:
M CMakeLists.txt | + -
M src/arena/game.cpp | +++++ -----
M src/attack/attack.hpp | ++++++ ------
M src/bitboard/bitboard.cpp | -----------
M src/bitboard/bitboard.hpp | ---
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/utils.hpp | ++++++++++++++

15 files changed, 79 insertions(+), 104 deletions(-)


diff --git a/ CMakeLists.txt b/ CMakeLists.txt

@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project( Stellar
VERSION 1.3.4
VERSION 1.3.5
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

@@ -35,11 +35,11 @@ const std::string Game::to_san(const Board &board, const Move move) { if (move.is_castle_king()) return "O-O"; if (move.is_castle_queen()) return "O-O-O";
const piece::Type piece = board.get_square_piece_type(move.source());
const piece::Type target = board.get_square_piece_type(move.target());
const Type piece = board.get_square_piece_type(move.source());
const Type target = board.get_square_piece_type(move.target());
std::string res;
if (piece != piece::PAWN) {
if (piece != PAWN) {
U64 potential = board.get_bitboard_square_land(move.target(), piece, board.get_side()); if (bit::count(potential) > 1) {

@@ -60,10 +60,10 @@ const std::string Game::to_san(const Board &board, const Move move) { } res += piece::get_code(piece, WHITE);
if (target != piece::NONE) res += "x";
if (target != Type::NONE) res += "x";
res += to_coordinates(move.target()); } else {
if (target != piece::NONE) res += std::format("{}x", to_coordinates(move.source())[0]);
if (target != Type::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.";

diff --git a/ src/attack/attack.hpp b/ src/attack/attack.hpp

@@ -20,13 +20,13 @@ 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 from, const U64 occupancy) {
inline constexpr const U64 attack(const 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);
case piece::BISHOP: return attack::bishop::attack(from, occupancy);
case piece::KING: return attack::king::attack(from);
case piece::KNIGHT: return attack::knight::attack(from);
case QUEEN: return attack::queen::attack(from, occupancy);
case ROOK: return attack::rook::attack(from, occupancy);
case BISHOP: return attack::bishop::attack(from, occupancy);
case KING: return attack::king::attack(from);
case KNIGHT: return attack::knight::attack(from);
default: return 0; } }

diff --git a/ src/bitboard/bitboard.cpp b/ src/bitboard/bitboard.cpp

@@ -6,17 +6,6 @@ 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

@@ -5,7 +5,6 @@ namespace bitboard {
void init(void);
void print(U64 bitboard); inline constexpr const U64 notAFile = C64(0xfefefefefefefefe);

@@ -21,8 +20,6 @@ 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.hpp b/ src/board/board.hpp

@@ -36,18 +36,15 @@ class Board { [[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) const;
[[nodiscard]] inline constexpr U64 get_bitboard_piece(Type piece) const;
[[nodiscard]] inline constexpr U64 get_bitboard_piece(Type piece, Color color) 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 U64 get_bitboard_piece_attacks(Type piece, Color color, Square from) const;
[[nodiscard]] inline constexpr U64 get_bitboard_piece_moves(Type piece, Color color, Square from) const;
[[nodiscard]] inline constexpr U64 get_bitboard_square_land(Square land, Type piece, Color side) 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 Type get_square_piece_type(Square square) const;
[[nodiscard]] inline constexpr const piece::Piece *get_square_piece(Square square) const; /* Setters */

@@ -60,17 +57,17 @@ class Board { 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);
inline constexpr void set_bitboard_piece(piece::Type type, Square square);
inline constexpr void pop_bitboard_piece(Type type, Square square);
inline constexpr void set_bitboard_piece(Type type, 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);
inline constexpr void pop_piece(Type type, Color side, Square square);
inline constexpr void set_piece(Type type, Color side, Square square);
/* Queries */ [[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,
[[nodiscard]] inline constexpr bool is_piece_attack_square(Type type, Color color, Square source,
Square target) const; [[nodiscard]] inline constexpr bool is_check() const;

@@ -90,22 +87,22 @@ constexpr Square Board::get_enpassant() const { return enpassant; } 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(Type piece) const { return pieces[piece]; }
constexpr U64 Board::get_bitboard_piece(piece::Type piece, Color color) const {
constexpr U64 Board::get_bitboard_piece(Type piece, Color color) const {
return pieces[piece] & colors[color]; }
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);
constexpr U64 Board::get_bitboard_piece_attacks(Type type, Color color, Square from) const {
if (type == 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, Square square) const {
constexpr U64 Board::get_bitboard_piece_moves(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 land, piece::Type piece, Color side) const {
constexpr U64 Board::get_bitboard_square_land(Square land, Type piece, Color side) const {
return get_bitboard_piece_attacks(piece, other(side), land) & get_bitboard_piece(piece, side); }

@@ -116,11 +113,11 @@ constexpr Color Board::get_square_piece_color(Square square) const { throw std::exception(); }
constexpr piece::Type Board::get_square_piece_type(Square square) const {
for (piece::Type type = piece::PAWN; type <= piece::KING; ++type) {
constexpr Type Board::get_square_piece_type(Square square) const {
for (Type type = PAWN; type <= KING; ++type) {
if (bit::get(pieces[type], square)) return type; }
return piece::Type::NONE;
return Type::NONE;
} constexpr const piece::Piece *Board::get_square_piece(Square square) const {

@@ -153,15 +150,15 @@ constexpr void Board::set_enpassant(Square target) { 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_bitboard_piece(Type type, Square square) { bit::pop(pieces[type], square); }
constexpr void Board::set_bitboard_piece(Type type, Square square) { bit::set(pieces[type], square); }
constexpr void Board::pop_piece(piece::Type type, Color side, Square square) {
constexpr void Board::pop_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 side, Square square) {
constexpr void Board::set_piece(Type type, Color side, Square square) {
set_bitboard_color(side, square); set_bitboard_piece(type, square); }

@@ -175,7 +172,7 @@ constexpr bool Board::is_square_occupied(Square square) const { 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) {
for (Type type = PAWN; type <= KING; ++type) {
if (get_bitboard_piece_attacks(type, side_other, square) & get_bitboard_piece(type, side)) { return true; }

@@ -184,13 +181,12 @@ constexpr bool Board::is_square_attacked(Square square, Color side) const { return false; }
constexpr bool Board::is_piece_attack_square(piece::Type type, Color color, Square source,
Square target) const {
constexpr bool Board::is_piece_attack_square(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];
U64 king = pieces[Type::KING] & colors[side];
Color side_other = (side == BLACK) ? WHITE : BLACK; auto square = static_cast<Square>(bit::lsb_index(king)); return is_square_attacked(square, side_other);

@@ -200,7 +196,7 @@ U64 zobrist::hash(const Board &board) { U64 key_final = C64(0); uint8_t square = 0;
for (piece::Type type = piece::PAWN; type <= piece::KING; ++type) {
for (Type type = PAWN; type <= KING; ++type) {
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]; }

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::PAWN; type <= piece::KING; ++type) {
for (Type type = PAWN; type <= KING; ++type) {
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++) {

@@ -43,7 +43,7 @@ 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) { return keys_enpassant[square]; }
inline constexpr U64 key_piece(piece::Type type, Color color, Square square) {
inline constexpr U64 key_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

@@ -132,9 +132,9 @@ U32 inline move_score(const Move move) { // clang-format on };
const piece::Type type = board.get_square_piece_type(move.source());
const Type type = board.get_square_piece_type(move.source());
if (move.is_capture()) {
const piece::Type captured = board.get_square_piece_type(move.target());
const Type captured = board.get_square_piece_type(move.target());
return capture[type][captured] + 10000; } if (killer[0][ply] == move) return 9000;

@@ -279,7 +279,7 @@ int16_t negamax(int16_t alpha, int16_t beta, uint8_t depth, bool null) { // if (ply > MAX_PLY - 1) return evaluate::score_position(board); if (!pv_node && !isCheck) {
static constexpr const U32 score_pawn = score::get(piece::Type::PAWN);
static constexpr const U32 score_pawn = score::get(PAWN);
int16_t staticEval = evaluate::score_position(board); // evaluation pruning

@@ -316,9 +316,9 @@ int16_t negamax(int16_t alpha, int16_t beta, uint8_t depth, bool null) { // futility pruning condition static constexpr const int16_t margin[] = { 0,
score::get(piece::Type::PAWN),
score::get(piece::Type::KNIGHT),
score::get(piece::Type::ROOK),
score::get(PAWN),
score::get(KNIGHT),
score::get(ROOK),
}; if (depth < 4 && abs(alpha) < MATE_SCORE && staticEval + margin[depth] <= alpha) futility = 1; }

@@ -367,7 +367,7 @@ int16_t negamax(int16_t alpha, int16_t beta, uint8_t depth, bool null) { if (settings->stopped) return 0; if (score > alpha) { if (!move.is_capture()) {
const piece::Type piece = board.get_square_piece_type(move.source());
const Type piece = board.get_square_piece_type(move.source());
history[piece::get_index(piece, board.get_side())][move.target()] += depth; }

diff --git a/ src/engine/evaluate.cpp b/ src/engine/evaluate.cpp

@@ -63,20 +63,13 @@ inline constexpr const mask_passed_array mask_passed = []() constexpr -> mask_pa return mask_passed; }();
using piece::Type::BISHOP;
using piece::Type::KING;
using piece::Type::KNIGHT;
using piece::Type::PAWN;
using piece::Type::QUEEN;
using piece::Type::ROOK;
using score::Phase::ENDGAME; using score::Phase::OPENING; uint16_t score_game_phase(const Board &board) { int16_t total = 0; for (int type_i = KNIGHT; type_i < KING; type_i++) {
const piece::Type type = static_cast<piece::Type>(type_i);
const Type type = static_cast<Type>(type_i);
total += bit::count(board.get_bitboard_piece(type)) * score::get(type); } return total;

diff --git a/ src/engine/score.hpp b/ src/engine/score.hpp

@@ -146,11 +146,9 @@ enum Phase { ENDGAME, };
inline constexpr int16_t get(const piece::Type piece, const Phase phase = OPENING) {
return value[phase][piece];
}
inline constexpr int16_t get(const Type piece, const Phase phase = OPENING) { return value[phase][piece]; }
inline constexpr int16_t get(piece::Type piece, Color color, Square square, Phase phase = ENDGAME) {
inline constexpr int16_t get(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/move/move.cpp b/ src/move/move.cpp

@@ -5,23 +5,23 @@ #include <algorithm> #include <iomanip>
void Move::piece_remove(Board &board, piece::Type type, Color color, Square square) const {
void Move::piece_remove(Board &board, 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, Square square) const {
void Move::piece_set(Board &board, 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, Square source, Square target) const {
void Move::piece_move(Board &board, Type type, Color color, Square source, Square target) const {
piece_remove(board, type, color, source); piece_set(board, type, color, target); }
using piece::Type::PAWN;
using piece::Type::ROOK;
using Type::PAWN;
using Type::ROOK;
bool Move::make(Board &board) const { static constexpr const int castling_rights[64] = {

@@ -42,7 +42,7 @@ bool Move::make(Board &board) const { const auto ntarget = static_cast<Square>(this->target() + (color == Color::WHITE ? -8 : +8));
const piece::Type piece = board.get_square_piece_type(source);
const Type piece = board.get_square_piece_type(source);
if (!is_capture()) { if (is_promote()) {

@@ -52,7 +52,7 @@ bool Move::make(Board &board) const { piece_move(board, piece, color, source, target); } } else {
const piece::Type captured = board.get_square_piece_type(target);
const Type captured = board.get_square_piece_type(target);
if (is_enpassant()) { piece_move(board, piece, color, source, target); piece_remove(board, PAWN, colorOther, ntarget);

diff --git a/ src/move/move.hpp b/ src/move/move.hpp

@@ -50,7 +50,7 @@ struct Move { [[nodiscard]] bool is_enpassant() const { return flags_i == ENPASSANT; }
[[nodiscard]] const piece::Type promoted() const { return static_cast<piece::Type>((flags_i & 0x3) + 1); }
[[nodiscard]] const Type promoted() const { return static_cast<Type>((flags_i & 0x3) + 1); }
bool make(Board &board) const;

@@ -59,9 +59,9 @@ struct Move { void print() const; private:
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;
inline void piece_remove(Board &board, Type type, Color color, Square square) const;
inline void piece_set(Board &board, Type type, Color color, Square square) const;
inline void piece_move(Board &board, 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

@@ -10,7 +10,7 @@ ((color == BLACK && source >= Square::a7 && source <= Square::h7) || \ (color == WHITE && source >= Square::a2 && source <= Square::h2))
using piece::Type::PAWN;
using Type::PAWN;
void MoveList::generate(const Board &board, bool attacks_only) { uint8_t src_i = 0, tgt_i = 0;

@@ -62,7 +62,7 @@ void MoveList::generate(const Board &board, bool attacks_only) { } // All piece move
for (piece::Type type = piece::KNIGHT; type <= piece::KING; ++type) {
for (Type type = KNIGHT; type <= KING; ++type) {
U64 bitboard = board.get_bitboard_piece(type, color); bitboard_for_each_bit(src_i, bitboard) { const auto src = static_cast<Square>(src_i);

diff --git a/ src/piece/piece.hpp b/ src/piece/piece.hpp

@@ -8,18 +8,6 @@ namespace piece {
enum Type {
PAWN = 0,
KNIGHT,
BISHOP,
ROOK,
QUEEN,
KING,
NONE = 7,
};
ENABLE_INCR_OPERATORS_ON(Type)
struct Piece { const uint8_t index; const Type type;

diff --git a/ src/utils/utils.hpp b/ src/utils/utils.hpp

@@ -57,4 +57,18 @@ 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]; }
/* piece */
enum Type {
PAWN = 0,
KNIGHT,
BISHOP,
ROOK,
QUEEN,
KING,
NONE = 7,
};
ENABLE_INCR_OPERATORS_ON(Type)
#endif