commit 66c57a8231fc90d5e7a02763af8b5388968b3836
parent ef1ae825fa1a9d9fd748e925715d7f0ec8177786
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Sun, 13 Aug 2023 21:35:34 +0200
Don't use std::function for sorting
Diffstat:
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++;