commit 362cc43b8bc8a4e5519238dc587ddd0b8eb30ee2
parent 478983d07da27cc277fef32f73a65f5de5631f1a
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Tue, 29 Aug 2023 00:23:48 +0200
Basic time control
Diffstat:
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