stellar

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 21:35:34 +0200

Don't use std::function for sorting

Diffstat:
MCMakeLists.txt | 2+-
Msrc/engine/engine.cpp | 90+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/include/board.hpp | 2+-
Msrc/include/move.hpp | 4++--
Msrc/include/movelist.hpp | 8++------
Msrc/include/random.hpp | 2+-
Msrc/include/zobrist.hpp | 3---
Msrc/move/move.cpp | 2+-
Msrc/move/movelist.cpp | 3++-
Msrc/perft/perft.cpp | 4++--
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++;