stellar

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

commit4e698dee2fb03a902881aa74a33092053a82612e
parent24b08195dc653f124987c1973d70760d0f688e50
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateFri, 1 Dec 2023 22:58:17 +0000

Modernize the codebase using clang-tidy

Diffstat:
MCMakeLists.txt|+-
Msrc/arena/arena.cpp|+++---
Msrc/arena/engine.cpp|++++----
Msrc/arena/engine.hpp|++++++------
Msrc/arena/game.cpp|++--
Msrc/arena/game.hpp|++++++++--------
Msrc/attack/attack.hpp|+-
Msrc/board/board.cpp|+++++-----
Msrc/board/board.hpp|++++++++++++++++++++++++++++++------------------------------
Msrc/board/zobrist.hpp|++++----
Msrc/engine/engine.cpp|+++++++++++++++-----------
Msrc/engine/evaluate.cpp|+++++++++---------
Msrc/engine/uci.cpp|+-
Msrc/engine/uci.hpp|++--
Msrc/move/move.cpp|++++----
Msrc/move/move.hpp|+++++++++++++-------------
Msrc/move/movelist.cpp|+++++++++++++++++++++++++-------------------------
Msrc/move/movelist.hpp|+++---
Msrc/perft/perft.cpp|+++++---
Msrc/utils/repetition.hpp|++++----
Msrc/utils/timer.hpp|+++---

21 files changed, 148 insertions(+), 142 deletions(-)


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

@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

project(
Stellar
VERSION 9.0.4
VERSION 1.1.1
DESCRIPTION "Chess engine written in C++"
HOMEPAGE_URL https://git.dimitrijedobrota.com/stellar.git
LANGUAGES CXX

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

@@ -65,10 +65,10 @@ void usage(const char *program) {

}
int main(int argc, char *argv[]) {
char *engine1 = NULL, *engine2 = NULL;
char *engine1 = nullptr, *engine2 = nullptr;
Match::Settings settings1, settings2;
char c;
char c = 0;
while ((c = getopt(argc, argv, "hE:e:D:d:T:t:I:i:G:g:N:")) != -1) {
switch (c) {
case 'E': engine1 = optarg; break;

@@ -93,7 +93,7 @@ int main(int argc, char *argv[]) {

std::vector<std::string> positions;
for (int i = optind; i < argc; i++)
positions.push_back(!strcmp(argv[i], "-") ? start_position : argv[i]);
positions.emplace_back(!strcmp(argv[i], "-") ? start_position : argv[i]);
Arena arena(engine1, engine2);
arena(positions, settings1, settings2);

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

@@ -44,7 +44,7 @@ Engine::Engine(const char *file) : file(file) {

Engine::~Engine() {
send("quit");
waitpid(engine_pid, NULL, 0);
waitpid(engine_pid, nullptr, 0);
// kill(engine_pid, SIGKILL);
if (close(fd_to[1]) < 0) logger::error("close");

@@ -68,7 +68,7 @@ void Engine::send(std::string &&command) {

logger::log(std::format("Engine {}: TO {}: {}", id, name.size() ? name : file, command), logger::Info);
}
std::string Engine::receive(void) {
std::string Engine::receive() {
int size = 0;
while (true) {

@@ -104,7 +104,7 @@ std::string Engine::receive(void) {

}
}
[[noreturn]] void Engine::start_engine(void) {
[[noreturn]] void Engine::start_engine() {
if (close(fd_to[1]) < 0 || close(fd_from[0])) {
logger::error("close");
throw std::runtime_error("close failed");

@@ -115,7 +115,7 @@ std::string Engine::receive(void) {

throw std::runtime_error("dup2 failed");
}
execl(file, file, (char *)NULL);
execl(file, file, (char *)nullptr);
logger::error("execl");
throw std::runtime_error("execl failed");
}

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

@@ -11,22 +11,22 @@ class Engine {

~Engine();
const std::string &get_name(void) const { return name; }
const std::string &get_author(void) const { return author; }
[[nodiscard]] const std::string &get_name() const { return name; }
[[nodiscard]] const std::string &get_author() const { return author; }
void send(std::string &&command);
std::string receive(void);
std::string receive();
private:
[[noreturn]] void start_engine(void);
[[noreturn]] void start_engine();
const char *file = nullptr;
int fd_to[2], fd_from[2];
int fd_to[2]{}, fd_from[2]{};
pid_t engine_pid;
std::string name, author;
char rb[1000];
char rb[1000]{};
int rb_size = 0;
std::queue<std::string> q;

diff --git a/src/arena/game.cpp b/src/arena/game.cpp

@@ -16,7 +16,7 @@ Game::Game(const uint16_t match_id, const std::string white, const std::string b

logger::log(std::format("Game {}: started", id), logger::Debug);
}
const std::string Game::get_moves(void) const {
const std::string Game::get_moves() const {
std::string res;
if (list.size()) res += (std::string)list[0];
for (int i = 1; i < list.size(); i++)

@@ -43,7 +43,7 @@ const std::string Game::to_san(const Board &board, const Move move) {

if (bit::count(potential) > 1) {
int file[9] = {0}, rank[9] = {0};
uint8_t square_i;
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));
file[crd[0] & 0x3]++;

diff --git a/src/arena/game.hpp b/src/arena/game.hpp

@@ -18,14 +18,14 @@ class Game {

void play(const Move move) { list.push(move); }
const std::string get_moves(void) const;
const std::string &get_white(void) const { return white; }
const std::string &get_black(void) const { return black; }
const Terminate get_terminate(void) const { return terminate; }
const bool is_win_white(void) const { return !draw && winner == color::WHITE; }
const bool is_win_black(void) const { return !draw && winner == color::BLACK; }
const bool is_draw(void) const { return draw; }
[[nodiscard]] const std::string get_moves() const;
[[nodiscard]] const std::string &get_white() const { return white; }
[[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_draw() const { return draw; }
void set_terminate(const Terminate terminate) { this->terminate = terminate; }
void set_winner(const color::Color winner) { this->winner = winner; }

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

@@ -15,7 +15,7 @@

namespace attack {
typedef U64 (*attack_f)(const square::Square square, U64 occupancy);
using attack_f = U64 (*)(const square::Square, U64);
}

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

@@ -1,7 +1,7 @@

#include <ctype.h>
#include <cctype>
#include <exception>
#include <stdio.h>
#include <string.h>
#include <cstdio>
#include <cstring>
#include "board.hpp"
#include "piece.hpp"

@@ -12,7 +12,7 @@

/* Getters */
Board::Board(const std::string &fen) {
int file = 0, rank = 7, i;
int file = 0, rank = 7, i = 0;
for (i = 0; fen[i] != ' '; i++) {
if (isalpha(fen[i])) {
const piece::Piece &piece = piece::get_from_code(fen[i]);

@@ -58,7 +58,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 << " ";
square::Square square = static_cast<square::Square>((7 - rank) * 8 + file);
auto square = static_cast<square::Square>((7 - rank) * 8 + file);
const piece::Piece *piece = board.get_square_piece(square);
os << (piece ? piece->code : '.') << " ";
}

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

@@ -29,32 +29,32 @@ class Board {

/* Getters */
inline constexpr U64 get_hash(void) const;
inline constexpr color::Color get_side(void) const;
inline constexpr uint8_t get_castle(void) const;
inline constexpr square::Square get_enpassant(void) const;
[[nodiscard]] inline constexpr U64 get_hash() const;
[[nodiscard]] inline constexpr color::Color get_side() const;
[[nodiscard]] inline constexpr uint8_t get_castle() const;
[[nodiscard]] inline constexpr square::Square get_enpassant() const;
inline constexpr U64 get_bitboard_color(color::Color side) const;
inline constexpr U64 get_bitboard_occupancy(void) const;
[[nodiscard]] inline constexpr U64 get_bitboard_color(color::Color side) const;
[[nodiscard]] inline constexpr U64 get_bitboard_occupancy() const;
inline constexpr U64 get_bitboard_piece(piece::Type piece) const;
inline constexpr U64 get_bitboard_piece(piece::Type piece, color::Color color) 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;
inline constexpr U64 get_bitboard_piece_attacks(piece::Type piece, color::Color color,
[[nodiscard]] inline constexpr U64 get_bitboard_piece_attacks(piece::Type piece, color::Color color,
square::Square from) const;
inline constexpr U64 get_bitboard_piece_moves(piece::Type piece, color::Color color,
[[nodiscard]] inline constexpr U64 get_bitboard_piece_moves(piece::Type piece, color::Color color,
square::Square from) const;
inline constexpr U64 get_bitboard_square_land(square::Square land, piece::Type piece,
[[nodiscard]] inline constexpr U64 get_bitboard_square_land(square::Square land, piece::Type piece,
color::Color side) const;
inline constexpr color::Color get_square_piece_color(square::Square square) const;
inline constexpr piece::Type get_square_piece_type(square::Square square) const;
inline constexpr const piece::Piece *get_square_piece(square::Square square) 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;
/* Setters */
inline constexpr void xor_hash(U64 op);
inline constexpr void switch_side(void);
inline constexpr void switch_side();
inline constexpr void and_castle(uint8_t right);
inline constexpr void set_enpassant(square::Square target);

@@ -69,11 +69,11 @@ class Board {

/* Queries */
inline constexpr bool is_square_attacked(square::Square square, color::Color side) const;
inline constexpr bool is_square_occupied(square::Square square) const;
inline constexpr bool is_piece_attack_square(piece::Type type, color::Color color, square::Square source,
[[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;
inline constexpr bool is_check(void) const;
[[nodiscard]] inline constexpr bool is_check() const;
private:
U64 colors[2] = {0};

@@ -84,14 +84,14 @@ class Board {

uint8_t castle = 0;
};
constexpr color::Color Board::get_side(void) const { return side; }
constexpr U64 Board::get_hash(void) const { return hash; }
constexpr uint8_t Board::get_castle(void) const { return castle; }
constexpr square::Square Board::get_enpassant(void) const { return enpassant; }
constexpr color::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 U64 Board::get_bitboard_color(color::Color side) const { return colors[to_underlying(side)]; }
constexpr U64 Board::get_bitboard_occupancy(void) const {
constexpr U64 Board::get_bitboard_occupancy() const {
return colors[to_underlying(color::WHITE)] | colors[to_underlying(color::BLACK)];
}

@@ -147,7 +147,7 @@ constexpr void Board::and_castle(uint8_t right) {

hash ^= Zobrist::key_castle(castle);
}
constexpr void Board::switch_side(void) {
constexpr void Board::switch_side() {
side = color::other(side);
hash ^= Zobrist::key_side();
}

@@ -195,11 +195,11 @@ constexpr bool Board::is_square_attacked(square::Square square, color::Color sid

for (piece::Type type : piece::TypeIter()) {
if (get_bitboard_piece_attacks(type, side_other, square) & get_bitboard_piece(type, side)) {
return 1;
return true;
}
}
return 0;
return false;
}
constexpr bool Board::is_piece_attack_square(piece::Type type, color::Color color, square::Square source,

@@ -207,16 +207,16 @@ constexpr bool Board::is_piece_attack_square(piece::Type type, color::Color colo

return get_bitboard_piece_attacks(type, color, source) & (C64(1) << to_underlying(target));
}
constexpr bool Board::is_check(void) const {
constexpr bool Board::is_check() const {
U64 king = pieces[to_underlying(piece::Type::KING)] & colors[to_underlying(side)];
color::Color side_other = (side == color::BLACK) ? color::WHITE : color::BLACK;
square::Square square = static_cast<square::Square>(bit::lsb_index(king));
auto square = static_cast<square::Square>(bit::lsb_index(king));
return is_square_attacked(square, side_other);
}
U64 Zobrist::hash(const Board &board) {
U64 key_final = C64(0);
uint8_t square;
uint8_t square = 0;
for (piece::Type type : piece::TypeIter()) {
int piece_white_index = piece::get_index(type, color::WHITE);

diff --git a/src/board/zobrist.hpp b/src/board/zobrist.hpp

@@ -14,7 +14,7 @@ class Zobrist {

Zobrist() = delete;
static inline U64 hash(const Board &board);
static inline constexpr U64 key_side(void) { return keys_side; }
static inline constexpr U64 key_side() { return keys_side; }
static inline constexpr U64 key_castle(int exp) { return keys_castle[exp]; }
static inline constexpr U64 key_enpassant(square::Square square) {
return keys_enpassant[to_underlying(square)];

@@ -24,7 +24,7 @@ class Zobrist {

}
private:
typedef std::array<std::array<U64, 64>, 12> key_piece_array;
using key_piece_array = std::array<std::array<U64, 64>, 12>;
static inline constexpr const key_piece_array keys_piece = []() constexpr -> key_piece_array {
key_piece_array key_piece;
Random gen(C64(1804289383));

@@ -39,7 +39,7 @@ class Zobrist {

return key_piece;
}();
typedef std::array<U64, 64> key_enpassant_array;
using key_enpassant_array = std::array<U64, 64>;
static inline constexpr const key_enpassant_array keys_enpassant = []() constexpr -> key_enpassant_array {
key_enpassant_array key_enpassant;
Random gen(C32(337245213));

@@ -49,7 +49,7 @@ class Zobrist {

return key_enpassant;
}();
typedef std::array<U64, 16> key_castle_array;
using key_castle_array = std::array<U64, 16>;
static inline constexpr const key_castle_array keys_castle = []() constexpr -> key_castle_array {
key_castle_array key_castle;
Random gen(C32(3642040919));

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

@@ -1,8 +1,8 @@

#include <algorithm>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "attack.hpp"
#include "board.hpp"

@@ -16,11 +16,15 @@

#include "uci.hpp"
#include "utils.hpp"
#define FULL_DEPTH 4
#define REDUCTION_LIMIT 3
#define REDUCTION_MOVE 2
enum {
FULL_DEPTH = 4,
REDUCTION_LIMIT = 3,
REDUCTION_MOVE = 2
};
#define WINDOW 50
enum {
WINDOW = 50
};
namespace engine {

@@ -41,7 +45,7 @@ class TTable {

public:
static inline constexpr const int16_t unknown = 32500;
TTable() {}
TTable() = default;
TTable(U64 size) : table(size, {0}) {}
void clear() { table.clear(); };

@@ -424,7 +428,7 @@ Move search_position(const uci::Settings &settingsr) {

uint8_t max_depth = settings->depth ? settings->depth : MAX_PLY;
for (uint8_t depth = 1; depth <= max_depth; depth++) {
lastBest = pvtable.best();
follow_pv = 1;
follow_pv = true;
int16_t score = negamax(alpha, beta, depth, true);
uci::communicate(settings);

@@ -468,7 +472,7 @@ Move search_position(const uci::Settings &settingsr) {

}
} // namespace engine
int main(void) {
int main() {
uci::loop();
return 0;
}

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

@@ -10,7 +10,7 @@

namespace evaluate {
typedef std::array<U64, 8> mask_fr_array;
using mask_fr_array = std::array<U64, 8>;
inline constexpr const mask_fr_array mask_rank = []() constexpr -> mask_fr_array {
mask_fr_array mask_rank;
U64 mask = 0xFF;

@@ -45,11 +45,11 @@ inline constexpr const mask_fr_array mask_isolated = []() constexpr -> mask_fr_a

return mask_isolated;
}();
typedef std::array<std::array<U64, 64>, 2> mask_passed_array;
using mask_passed_array = std::array<std::array<U64, 64>, 2>;
inline constexpr const mask_passed_array mask_passed = []() constexpr -> mask_passed_array {
mask_passed_array mask_passed;
U64 maskW, maskB;
U64 maskW = 0, maskB = 0;
for (uint8_t file = 0; file < 8; file++) {
maskW = maskB = mask_file[file] | mask_isolated[file];
for (uint8_t rank = 0; rank < 8; rank++) {

@@ -96,7 +96,7 @@ 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 square::Square square = static_cast<square::Square>(square_i);
const auto square = static_cast<square::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);

@@ -117,21 +117,21 @@ 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 square::Square square = static_cast<square::Square>(square_i);
const auto square = static_cast<square::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 square::Square square = static_cast<square::Square>(square_i);
const auto square = static_cast<square::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 square::Square square = static_cast<square::Square>(square_i);
const auto square = static_cast<square::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);

@@ -143,14 +143,14 @@ int16_t score_position_side(const Board &board, const color::Color side, const u

bitboard = board.get_bitboard_piece(QUEEN, side);
bitboard_for_each_bit(square_i, bitboard) {
const square::Square square = static_cast<square::Square>(square_i);
const auto square = static_cast<square::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 square::Square square = static_cast<square::Square>(square_i);
const auto square = static_cast<square::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);

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

@@ -35,7 +35,7 @@ inline bool parse_move(const Board &board, Move &move, const std::string &move_s

return false;
}
void loop(void) {
void loop() {
static Settings settings;
static std::string line, command;
static Move move;

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

@@ -29,8 +29,8 @@ struct Settings {

mutable bool stopped = false;
};
void loop(void);
uint32_t get_time_ms(void);
void loop();
uint32_t get_time_ms();
void communicate(const uci::Settings *settings);
} // namespace uci

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

@@ -40,7 +40,7 @@ bool Move::make(Board &board) const {

const color::Color color = board.get_side(), colorOther = color::other(color);
const square::Square source = this->source(), target = this->target();
const square::Square ntarget =
const auto ntarget =
static_cast<square::Square>(to_underlying(this->target()) + (color == color::Color::WHITE ? -8 : +8));
const piece::Type piece = board.get_square_piece_type(source);

@@ -88,12 +88,12 @@ bool Move::make(Board &board) const {

if (!board.is_check()) {
board.switch_side();
return 1;
return true;
}
return 0;
return false;
}
void Move::print(void) const {
void Move::print() const {
std::cout << square::to_coordinates(source()) << " ";
std::cout << square::to_coordinates(target()) << " ";
std::cout << (is_promote() ? piece::get_code(promoted()) : '.') << " ";

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

@@ -35,29 +35,29 @@ struct Move {

return a.source_i == b.source_i && a.target_i == b.target_i && a.flags_i == b.flags_i;
}
square::Square source(void) const { return static_cast<square::Square>(source_i); }
square::Square target(void) const { return static_cast<square::Square>(target_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); }
bool is_capture(void) const { return flags_i != PQUIET && (flags_i & CAPTURE); }
bool is_promote(void) const { return flags_i & 0x8; }
[[nodiscard]] bool is_capture() const { return flags_i != PQUIET && (flags_i & CAPTURE); }
[[nodiscard]] bool is_promote() const { return flags_i & 0x8; }
bool is_double(void) const { return flags_i == DOUBLE; }
bool is_repeatable(void) const { return flags_i == QUIET; }
bool is_quiet(void) const { return flags_i == QUIET || flags_i == PQUIET; }
[[nodiscard]] bool is_double() const { return flags_i == DOUBLE; }
[[nodiscard]] bool is_repeatable() const { return flags_i == QUIET; }
[[nodiscard]] bool is_quiet() const { return flags_i == QUIET || flags_i == PQUIET; }
bool is_castle(void) const { return flags_i == CASTLEK || flags_i == CASTLEQ; }
bool is_castle_king(void) const { return flags_i == CASTLEK; }
bool is_castle_queen(void) const { return flags_i == CASTLEQ; }
[[nodiscard]] bool is_castle() const { return flags_i == CASTLEK || flags_i == CASTLEQ; }
[[nodiscard]] bool is_castle_king() const { return flags_i == CASTLEK; }
[[nodiscard]] bool is_castle_queen() const { return flags_i == CASTLEQ; }
bool is_enpassant(void) const { return flags_i == ENPASSANT; }
[[nodiscard]] bool is_enpassant() const { return flags_i == ENPASSANT; }
const piece::Type promoted(void) const { return static_cast<piece::Type>((flags_i & 0x3) + 1); }
[[nodiscard]] const piece::Type promoted() const { return static_cast<piece::Type>((flags_i & 0x3) + 1); }
bool make(Board &board) const;
operator std::string() const;
friend std::ostream &operator<<(std::ostream &os, Move move);
void print(void) const;
void print() const;
private:
inline void piece_remove(Board &board, piece::Type type, color::Color color, square::Square square) const;

diff --git a/src/move/movelist.cpp b/src/move/movelist.cpp

@@ -14,7 +14,7 @@

using piece::Type::PAWN;
void MoveList::generate(const Board &board, bool attacks_only) {
uint8_t src_i, tgt_i;
uint8_t src_i = 0, tgt_i = 0;
const color::Color color = board.get_side(), colorOther = color::other(color);

@@ -23,21 +23,21 @@ void MoveList::generate(const Board &board, bool attacks_only) {

U64 bitboard = board.get_bitboard_piece(PAWN, color);
bitboard_for_each_bit(src_i, bitboard) {
const square::Square src = static_cast<square::Square>(src_i);
const square::Square tgt = static_cast<square::Square>(tgt_i = src_i + add);
const auto src = static_cast<square::Square>(src_i);
const auto tgt = static_cast<square::Square>(tgt_i = src_i + add);
if (!attacks_only && !board.is_square_occupied(tgt)) {
if (pawn_canPromote(color, src)) {
list.push_back({src, tgt, Move::PKNIGHT});
list.push_back({src, tgt, Move::PBISHOP});
list.push_back({src, tgt, Move::PROOK});
list.push_back({src, tgt, Move::PQUEEN});
list.emplace_back(src, tgt, Move::PKNIGHT);
list.emplace_back(src, tgt, Move::PBISHOP);
list.emplace_back(src, tgt, Move::PROOK);
list.emplace_back(src, tgt, Move::PQUEEN);
} else {
list.push_back({src, tgt, Move::PQUIET});
list.emplace_back(src, tgt, Move::PQUIET);
// two ahead
const square::Square tgt = static_cast<square::Square>(tgt_i + add);
const auto tgt = static_cast<square::Square>(tgt_i + add);
if (pawn_onStart(color, src) && !board.is_square_occupied(tgt))
list.push_back({src, tgt, Move::DOUBLE});
list.emplace_back(src, tgt, Move::DOUBLE);
}
}

@@ -45,36 +45,36 @@ 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 square::Square tgt = static_cast<square::Square>(tgt_i);
const auto tgt = static_cast<square::Square>(tgt_i);
if (pawn_canPromote(color, src)) {
list.push_back({src, tgt, Move::PCKNIGHT});
list.push_back({src, tgt, Move::PCBISHOP});
list.push_back({src, tgt, Move::PCROOK});
list.push_back({src, tgt, Move::PCQUEEN});
list.emplace_back(src, tgt, Move::PCKNIGHT);
list.emplace_back(src, tgt, Move::PCBISHOP);
list.emplace_back(src, tgt, Move::PCROOK);
list.emplace_back(src, tgt, Move::PCQUEEN);
} else {
list.push_back({src, tgt, Move::CAPTURE});
list.emplace_back(src, tgt, Move::CAPTURE);
}
}
// en passant
const square::Square enpassant = board.get_enpassant();
if (enpassant != square::no_sq && board.is_piece_attack_square(PAWN, color, src, enpassant))
list.push_back({src, enpassant, Move::ENPASSANT});
list.emplace_back(src, enpassant, Move::ENPASSANT);
}
// All piece move
for (const piece::Type type : ++piece::TypeIter()) {
U64 bitboard = board.get_bitboard_piece(type, color);
bitboard_for_each_bit(src_i, bitboard) {
const square::Square src = static_cast<square::Square>(src_i);
const auto src = static_cast<square::Square>(src_i);
U64 attack = board.get_bitboard_piece_moves(type, color, src);
bitboard_for_each_bit(tgt_i, attack) {
const square::Square tgt = static_cast<square::Square>(tgt_i);
const auto tgt = static_cast<square::Square>(tgt_i);
if (board.is_square_occupied(tgt)) {
list.push_back({src, tgt, Move::CAPTURE});
list.emplace_back(src, tgt, Move::CAPTURE);
} else {
if (attacks_only) continue;
list.push_back({src, tgt, Move::QUIET});
list.emplace_back(src, tgt, Move::QUIET);
}
}
}

@@ -88,14 +88,14 @@ void MoveList::generate(const Board &board, bool attacks_only) {

if (board.get_castle() & to_underlying(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.push_back({square::e1, square::g1, Move::CASTLEK});
list.emplace_back(square::e1, square::g1, Move::CASTLEK);
}
if (board.get_castle() & to_underlying(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.push_back({square::e1, square::c1, Move::CASTLEQ});
list.emplace_back(square::e1, square::c1, Move::CASTLEQ);
}
}
} else {

@@ -103,14 +103,14 @@ void MoveList::generate(const Board &board, bool attacks_only) {

if (board.get_castle() & to_underlying(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.push_back({square::Square::e8, square::Square::g8, Move::CASTLEK});
list.emplace_back(square::Square::e8, square::Square::g8, Move::CASTLEK);
}
if (board.get_castle() & to_underlying(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.push_back({square::e8, square::c8, Move::CASTLEQ});
list.emplace_back(square::e8, square::c8, Move::CASTLEQ);
}
}
}

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

@@ -21,15 +21,15 @@ class MoveList {

if (!legal) return;
int size = 0;
for (int i = 0; i < list.size(); i++) {
for (const auto& move : list) {
Board copy = board;
if (list[i].make(copy)) list[size++] = list[i];
if (move.make(copy)) list[size++] = move;
}
list.resize(size);
}
void clear() { list.clear(); }
int size() const { return list.size(); }
[[nodiscard]] int size() const { return list.size(); }
const Move operator[](size_t idx) const { return list[idx]; }
Move &operator[](size_t idx) { return list[idx]; }

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

@@ -10,11 +10,13 @@

// FEN debug positions
#define tricky_position "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1 "
#define THREAD_MAX 64
enum {
THREAD_MAX = 64
};
class Perft {
public:
typedef std::counting_semaphore<THREAD_MAX> semaphore_t;
using semaphore_t = std::counting_semaphore<THREAD_MAX>;
Perft(semaphore_t &sem) : sem(sem) {}
void operator()(const Board &board_start, Move move, int depth) {
Board board = board_start;

@@ -130,7 +132,7 @@ void usage(const char *program) {

}
int main(int argc, char *argv[]) {
int c, depth = 1, thread_num = 1;
int c = 0, depth = 1, thread_num = 1;
std::string s(start_position);
const char *fen = s.data();
while ((c = getopt(argc, argv, "ht:f:d:")) != -1) {

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

@@ -7,7 +7,7 @@ class Table {

public:
Table() = default;
bool is_repetition(const U64 hash) const {
[[nodiscard]] bool is_repetition(const U64 hash) const {
for (int i = repetitions.size() - 1; i >= 0; i--) {
if (repetitions[i] == hash) return true;
if (repetitions[i] == hashNull) return false;

@@ -15,9 +15,9 @@ class Table {

return false;
}
void pop(void) { repetitions.pop_back(); }
void clear(void) { repetitions.clear(); }
void push_null(void) { repetitions.push_back(hashNull); }
void pop() { repetitions.pop_back(); }
void clear() { repetitions.clear(); }
void push_null() { repetitions.push_back(hashNull); }
void push_hash(U64 hash) { repetitions.push_back(hash); }
friend std::ostream &operator<<(std::ostream &os, const Table &rtable) {

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

@@ -5,9 +5,9 @@

namespace timer {
inline uint32_t get_ms(void) {
struct timeval time;
gettimeofday(&time, NULL);
inline uint32_t get_ms() {
struct timeval time{};
gettimeofday(&time, nullptr);
return time.tv_sec * 1000 + time.tv_usec / 1000;
}