stellar

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

commit 66c57a8231fc90d5e7a02763af8b5388968b3836
parent ef1ae825fa1a9d9fd748e925715d7f0ec8177786
author Dimitrije Dobrota <mail@dimitrijedobrota.com>
date Sun, 13 Aug 2023 19:35:34 +0200

Don't use std::function for sorting

Diffstat:
M CMakeLists.txt | + -
M src/engine/engine.cpp | +++++++++++++++++++++++++++++++++++++++++++++ -------------------------------------
M src/include/board.hpp | + -
M src/include/move.hpp | ++ --
M src/include/movelist.hpp | ++ ------
M src/include/random.hpp | + -
M src/include/zobrist.hpp | ---
M src/move/move.cpp | + -
M src/move/movelist.cpp | ++ -
M src/perft/perft.cpp | ++ --

10 files changed, 61 insertions(+), 59 deletions(-)


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

@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project( Stellar
VERSION 0.0.19
VERSION 0.0.20
DESCRIPTION "Chess engine written in C" HOMEPAGE_URL https://git.dimitrijedobrota.com/stellar.git LANGUAGES C CXX

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

@@ -25,9 +25,47 @@ Move pv_table[MAX_PLY][MAX_PLY]; Move killer[2][MAX_PLY]; U32 history[16][64]; int pv_length[MAX_PLY];
int follow_pv;
long nodes;
int ply;
bool follow_pv;
U64 nodes;
U32 ply;
Move move_list_best_move;
U32 inline move_list_score(Move move) {
const piece::Type type = move.piece().type;
if (move.is_capture()) return piece::score(type, move.piece_capture().type) + 10000;
if (killer[0][ply] == move) return 9000;
if (killer[1][ply] == move) return 8000;
return history[to_underlying(type)][to_underlying(move.target())];
}
void move_list_sort(MoveList &list, bool check_best = true) {
for (auto &[move, score] : list)
score = move_list_score(move);
bool best = false;
if (check_best) {
for (auto &[move, score] : list) {
if (move == move_list_best_move) {
score = 30000;
best = true;
break;
}
}
}
if (!best && ply && follow_pv) {
follow_pv = false;
for (auto &[move, score] : list) {
if (move == pv_table[0][ply]) {
score = 20000;
follow_pv = true;
break;
}
}
}
sort(list.begin(), list.end());
}
int evaluate(const Board &board) { Color side = board.get_side();

@@ -96,25 +134,10 @@ int quiescence(int alpha, int beta) { if (score > alpha) alpha = score; Board copy;
bool pv_flag = false;
const auto score_move = [&pv_flag](Move move) -> U32 {
if (ply && follow_pv) {
follow_pv = 0;
if (pv_table[0][ply] == move) {
pv_flag = true;
return 20000;
}
}
const piece::Type type = move.piece().type;
if (move.is_capture()) return piece::score(type, move.piece_capture().type) + 10000;
if (killer[0][ply] == move) return 9000;
if (killer[1][ply] == move) return 8000;
return history[to_underlying(type)][to_underlying(move.target())];
};
follow_pv = pv_flag;
for (const auto [move, _] : MoveList(board, score_move)) {
MoveList list(board);
move_list_sort(list, false);
for (const auto [move, _] : list) {
if (!stats_move_make(copy, move, 1)) continue; score = -quiescence(-beta, -alpha); stats_move_unmake(copy);

@@ -201,27 +224,13 @@ int negamax(int alpha, int beta, int depth, bool null) { if (depth < 4 && abs(alpha) < MATE_SCORE && staticEval + margin[depth] <= alpha) futility = 1; }
bool pv_flag = false;
const auto score_move = [&bestMove, &pv_flag](Move move) -> U32 {
if (move == bestMove) return 30000;
if (ply && follow_pv) {
follow_pv = 0;
if (pv_table[0][ply] == move) {
pv_flag = true;
return 20000;
}
}
const piece::Type type = move.piece().type;
if (move.is_capture()) return piece::score(type, move.piece_capture().type) + 10000;
if (killer[0][ply] == move) return 9000;
if (killer[1][ply] == move) return 8000;
return history[to_underlying(type)][to_underlying(move.target())];
};
follow_pv = pv_flag;
int legal_moves = 0; int searched = 0;
for (const auto [move, _] : MoveList(board, score_move)) {
move_list_best_move = bestMove;
MoveList list(board);
move_list_sort(list);
for (const auto [move, _] : list) {
if (!stats_move_make(copy, move, 0)) continue; legal_moves++;

@@ -475,7 +484,6 @@ Board *Instruction_parse(Instruction *self) { } void uci_loop(void) {
Board board;
Instruction *instruction; char input[200000];

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

@@ -17,7 +17,7 @@ class Board { BQ = 8 };
Board() {}
Board() = default;
Board(const std::string &fen); friend std::ostream &operator<<(std::ostream &os, const Board &board);

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

@@ -9,7 +9,7 @@ #include <vector> struct Move {
Move(){};
Move() = default;
Move(Square source, Square target, const piece::Piece *piece, const piece::Piece *capture, const piece::Piece *promote, bool dbl, bool enpassant, bool castle)

@@ -35,7 +35,7 @@ struct Move { bool make(Board &board, bool attack_only) const;
friend std::ostream &operator<<(std::ostream &os, const Move &Move);
friend std::ostream &operator<<(std::ostream &os, Move move);
private: void piece_remove(Board &board, const piece::Piece &piece, Square square) const;

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

@@ -11,7 +11,6 @@ class MoveList { public:
typedef std::function<U32(const Move &)> score_f;
struct MoveListE { Move move; U32 score;

@@ -23,10 +22,9 @@ class MoveList { using list_t = std::vector<MoveListE>; public:
MoveList(const Board &board, score_f score = nullptr) : list(), score_move(score) {
MoveList(const Board &board) : list() {
list.reserve(256); generate(board);
sort(list.begin(), list.end());
} auto size() const { return list.size(); }

@@ -48,15 +46,13 @@ class MoveList { const_iterator cend() const { return list.cend(); } private:
void push_back(const MoveListE &&mle) { list.push_back(mle); }
void push_back(const Move &&move) { push_back({move, score_move ? score_move(move) : 0}); }
void push_back(const Move &&move) { list.push_back({move, 0}); }
void generate(const Board &board); void clear() { list.clear(); } list_t list;
score_f score_move;
}; #endif

diff --git a/ src/include/random.hpp b/ src/include/random.hpp

@@ -5,7 +5,7 @@ class Random { public:
constexpr Random(void) {}
constexpr Random(void) = default;
constexpr Random(U64 seed) : state(seed) {} constexpr U64 operator()(void) { return get_U64(); }

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

@@ -14,11 +14,8 @@ class Zobrist { Zobrist() = delete; static inline constexpr U64 key_side(void) { return keys_side; }
static inline constexpr U64 key_castle(int exp) { return keys_castle[exp]; }
static inline constexpr U64 key_enpassant(Square square) { return keys_enpassant[to_underlying(square)]; }
static inline constexpr U64 key_piece(const piece::Piece &piece, Square square) { return keys_piece[piece.index][to_underlying(square)]; }

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

@@ -91,7 +91,7 @@ bool Move::make(Board &board, bool attack_only) const { } }
std::ostream &operator<<(std::ostream &os, const Move &move) {
std::ostream &operator<<(std::ostream &os, Move move) {
os << square_to_coordinates(move.source()) << " "; os << square_to_coordinates(move.target()) << " "; os << move.piece().code << " ";

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

@@ -1,4 +1,5 @@ #include "movelist.hpp"
#include <iomanip>
#define pawn_canPromote(color, source) \ ((color == Color::WHITE && source >= Square::a7 && source <= Square::h7) || \

@@ -112,7 +113,7 @@ void MoveList::generate(const Board &board) { } std::ostream &operator<<(std::ostream &os, const MoveList &list) {
os << "Size: " << list.list.size();
os << "Size: " << std::dec << list.size() << "\n";
for (const auto &moveE : list.list) { os << moveE.score << ": " << moveE.move << "\n"; }

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

@@ -16,7 +16,7 @@ class Perft { public: typedef std::counting_semaphore<THREAD_MAX> semaphore_t; Perft(semaphore_t &sem) : sem(sem) {}
void operator()(const Board &board_start, const Move &move, int depth) {
void operator()(const Board &board_start, Move move, int depth) {
sem.acquire(); Board board = board_start; if (move.make(board, 0)) {

@@ -67,7 +67,7 @@ class Perft { score(copy, move); } }
void score(const Board &board, const Move &move) {
void score(const Board &board, Move move) {
local.node++; #ifdef USE_FULL_COUNT if (board.is_check()) local.check++;