stellar

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

commit362cc43b8bc8a4e5519238dc587ddd0b8eb30ee2
parent478983d07da27cc277fef32f73a65f5de5631f1a
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateMon, 28 Aug 2023 22:23:48 +0200

Basic time control

Diffstat:
MCMakeLists.txt|+-
Msrc/engine/engine.cpp|+++++++++++++++++++++++----
Msrc/engine/uci.cpp|+++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msrc/engine/uci.hpp|+++++++++-------

4 files changed, 88 insertions(+), 25 deletions(-)


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

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

project(
Stellar
VERSION 0.0.24
VERSION 0.0.25
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

@@ -76,6 +76,7 @@ class TTable {

std::vector<Hashe> table;
};
const uci::Settings *settings = nullptr;
Board board;
TTable ttable;
Move pv_table[MAX_PLY][MAX_PLY];

@@ -184,6 +185,10 @@ void stats_pv_store(Move move) {

}
int quiescence(int16_t alpha, int16_t beta) {
if ((nodes & 2047) == 0) {
uci::communicate(settings);
if (settings->stopped) return 0;
}
pv_length[ply] = ply;
nodes++;

@@ -207,6 +212,8 @@ int quiescence(int16_t alpha, int16_t beta) {

stats_pv_store(list[idx]);
if (score >= beta) return beta;
}
if (settings->stopped) return 0;
}
return alpha;

@@ -219,6 +226,10 @@ int negamax(int16_t alpha, int16_t beta, uint8_t depth, bool null) {

Move bestMove;
Board copy;
if ((nodes & 2047) == 0) {
uci::communicate(settings);
if (settings->stopped) return 0;
}
pv_length[ply] = ply;
int score = ttable.read(board, ply, &bestMove, alpha, beta, depth);

@@ -251,6 +262,8 @@ int negamax(int16_t alpha, int16_t beta, uint8_t depth, bool null) {

if (staticEval - marginEval >= beta) return staticEval - marginEval;
}
if (settings->stopped) return 0;
if (null) {
// null move pruning
if (ply && depth > 2 && staticEval >= beta) {

@@ -326,6 +339,7 @@ int negamax(int16_t alpha, int16_t beta, uint8_t depth, bool null) {

stats_move_unmake(copy);
searched++;
if (settings->stopped) return 0;
if (score > alpha) {
if (!move.is_capture()) {
const piece::Type piece = board.get_square_piece_type(move.source());

@@ -361,22 +375,27 @@ int negamax(int16_t alpha, int16_t beta, uint8_t depth, bool null) {

return alpha;
}
void search_position(const uci::Settings &setting) {
void search_position(const uci::Settings &settingsr) {
int16_t alpha = -SCORE_INFINITY, beta = SCORE_INFINITY;
settings = &settingsr;
if (setting.newgame) {
if (settings->newgame) {
ttable = TTable(C64(0x400000));
}
ply = 0;
nodes = 0;
board = setting.board;
board = settings->board;
settings->stopped = false;
memset(killer, 0x00, sizeof(killer));
memset(history, 0x00, sizeof(history));
memset(pv_table, 0x00, sizeof(pv_table));
memset(pv_length, 0x00, sizeof(pv_length));
for (uint8_t depth_crnt = 1; depth_crnt <= setting.depth;) {
for (uint8_t depth_crnt = 1; depth_crnt <= settings->depth;) {
uci::communicate(settings);
if (settings->stopped) break;
follow_pv = 1;
int score = negamax(alpha, beta, depth_crnt, true);

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

@@ -1,18 +1,39 @@

#include <iostream>
#include <limits>
#include <sstream>
#include <string>
#include <sys/time.h>
#include "engine.hpp"
#include "stellar_version.hpp"
#include "uci.hpp"
namespace uci {
uint32_t get_time_ms(void) {
struct timeval time;
gettimeofday(&time, NULL);
return time.tv_sec * 1000 + time.tv_usec / 1000;
}
void move_print(const Board &board, Move move) {
std::cout << square_to_coordinates(move.source()) << square_to_coordinates(move.target());
if (move.is_promote()) std::cout << piece::get_code(move.promoted(), board.get_side());
}
void communicate(const uci::Settings *settings) {
if (!settings->infinite && uci::get_time_ms() > settings->stoptime) settings->stopped = true;
/*
if (std::cin.peek() == EOF || std::cin.peek() == '\n') {
std::cin.clear();
return;
}
std::string command;
std::cin >> command;
if (command == "stop" || command == "quit") settings->stopped = true;
*/
}
inline bool parse_move(const Board &board, Move &move, const std::string &move_string) {
Square source = square_from_coordinates(move_string.substr(0, 2));
Square target = square_from_coordinates(move_string.substr(2, 2));

@@ -64,27 +85,30 @@ void loop(void) {

}
iss >> command;
while (iss >> command) {
if (parse_move(settings.board, move, command))
move.make(settings.board);
else
break;
if (!parse_move(settings.board, move, command)) break;
move.make(settings.board);
}
} else if (command == "go") {
uint32_t wtime = 0, btime = 0, movetime = 0;
uint16_t winc = 0, binc = 0, movestogo = 30;
while (iss >> command) {
if (command == "wtime")
iss >> settings.wtime;
iss >> wtime;
else if (command == "btime")
iss >> settings.btime;
iss >> btime;
else if (command == "winc")
iss >> settings.winc;
iss >> winc;
else if (command == "binc")
iss >> settings.binc;
iss >> binc;
else if (command == "depth")
iss >> settings.depth;
else if (command == "nodes")
iss >> settings.nodes;
else if (command == "movetime")
iss >> settings.movetime;
iss >> movetime;
else if (command == "movestogo")
iss >> movestogo;
else if (command == "ponder")
settings.ponder = true;
else if (command == "mate")

@@ -93,13 +117,31 @@ void loop(void) {

settings.infinite = true;
else if (command == "searchmoves") {
while (iss >> command) {
if (parse_move(settings.board, move, command))
settings.searchmoves.push(move);
else
break;
if (!parse_move(settings.board, move, command)) break;
settings.searchmoves.push(move);
}
}
}
settings.starttime = get_time_ms();
uint32_t time = (settings.board.get_side() == Color::WHITE) ? wtime : btime;
if (movetime != 0) {
time = movetime;
movestogo = 1;
}
if (time != 0) {
uint16_t inc = (settings.board.get_side() == Color::WHITE) ? winc : binc;
time /= movestogo;
time -= 50;
settings.stoptime = settings.starttime += time + inc;
settings.infinite = false;
}
if (!time) settings.infinite = true;
// std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
engine::search_position(settings);
settings.newgame = false;
}

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

@@ -11,22 +11,24 @@ namespace uci {

struct Settings {
MoveList searchmoves;
Board board;
uint32_t wtime = 0;
uint32_t btime = 0;
uint32_t movetime = 0;
uint32_t starttime;
uint32_t stoptime;
uint16_t depth = 64;
uint32_t nodes = 0;
uint16_t depth = 0;
uint16_t winc = 0;
uint16_t binc = 0;
bool ponder = false;
bool debug = false;
bool mate = false;
bool infinite = false;
bool infinite = true;
bool newgame = true;
mutable bool stopped = false;
};
void loop(void);
void move_print(const Board &board, Move move);
void communicate(const uci::Settings *settings);
uint32_t get_time_ms(void);
} // namespace uci