stellarUCI 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++;