diff --git a/.gitignore b/.gitignore index f7998acd..d5283b27 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# net file +nn.net + # Prerequisites *.d diff --git a/src/bench.cpp b/src/bench.cpp index 98557234..7717aa6a 100644 --- a/src/bench.cpp +++ b/src/bench.cpp @@ -66,7 +66,7 @@ const char* benchmarkfens[52] = { void StartBench(int depth) { // init all UciOptions uciOptions; - ThreadData* td(new ThreadData()); + ThreadData* td = &mainTD; uint64_t totalNodes = 0; InitTT(64); InitNewGame(td); @@ -75,13 +75,12 @@ void StartBench(int depth) { ParseFen(benchmarkfens[positions], &td->pos); std::cout << "\nPosition: " << positions + 1 << " fen: " << benchmarkfens[positions] << std::endl; RootSearch(depth, td, &uciOptions); - totalNodes += td->info.nodes; + totalNodes += td->nodes; } auto end = std::chrono::steady_clock::now(); auto totalTime = std::chrono::duration_cast(end - start).count(); std::cout << "\n"; std::cout << totalNodes << " nodes " << signed(totalNodes / (totalTime + 1) * 1000) << " nps" << std::endl; - delete td; } void BenchInference() { diff --git a/src/init.cpp b/src/init.cpp index 285df964..52550189 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -218,7 +218,6 @@ void InitNewGame(ThreadData* td) { // Extract data structures from ThreadData Position* pos = &td->pos; SearchData* sd = &td->sd; - SearchInfo* info = &td->info; CleanHistories(sd); @@ -232,11 +231,10 @@ void InitNewGame(ThreadData* td) { std::memset(sd->counterMoves, NOMOVE, sizeof(sd->counterMoves)); - // Reset plies and search info - info->starttime = GetTimeMs(); - info->stopped = 0; - info->nodes = 0; - info->seldepth = 0; + // Reset plies and search info + info.starttime = GetTimeMs(); + setStop(false); + info.seldepth = 0; // Clear TT ClearTT(); diff --git a/src/io.cpp b/src/io.cpp index e6d263b8..c31d8ebe 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -165,27 +165,27 @@ std::string Pick_color(int score) { } // Prints the uci output -void PrintUciOutput(const int score, const int depth, const ThreadData* td, const UciOptions* options) { +void PrintUciOutput(const int score, const int depth, const UciOptions* options) { // We are benching the engine and we don't care about the output if (tryhardmode) return; // This handles the basic console output - long time = GetTimeMs() - td->info.starttime; - uint64_t nodes = td->info.nodes + GetTotalNodes(); + long time = GetTimeMs() - info.starttime; + uint64_t nodes = mainTD.nodes + GetTotalNodes(); uint64_t nps = nodes / (time + !time) * 1000; if (print_uci) { if (score > -MATE_SCORE && score < -MATE_FOUND) - std::cout << "info score mate " << -(score + MATE_SCORE) / 2 << " depth " << depth << " seldepth " << td->info.seldepth << " multipv " << options->MultiPV << " nodes " << nodes << - " nps " << nps << " time " << GetTimeMs() - td->info.starttime << " pv "; + std::cout << "info score mate " << -(score + MATE_SCORE) / 2 << " depth " << depth << " seldepth " << info.seldepth << " multipv " << options->MultiPV << " nodes " << nodes << + " nps " << nps << " time " << GetTimeMs() - info.starttime << " pv "; else if (score > MATE_FOUND && score < MATE_SCORE) - std::cout << "info score mate " << (MATE_SCORE - score) / 2 + 1 << " depth " << depth << " seldepth " << td->info.seldepth << " multipv " << options->MultiPV << " nodes " << nodes << - " nps " << nps << " time " << GetTimeMs() - td->info.starttime << " pv "; + std::cout << "info score mate " << (MATE_SCORE - score) / 2 + 1 << " depth " << depth << " seldepth " << info.seldepth << " multipv " << options->MultiPV << " nodes " << nodes << + " nps " << nps << " time " << GetTimeMs() - info.starttime << " pv "; else - std::cout << "info score cp " << score << " depth " << depth << " seldepth " << td->info.seldepth << " multipv " << options->MultiPV << " nodes " << nodes << - " nps " << nps << " hashfull "<< GetHashfull() << " time " << GetTimeMs() - td->info.starttime << " pv "; + std::cout << "info score cp " << score << " depth " << depth << " seldepth " << info.seldepth << " multipv " << options->MultiPV << " nodes " << nodes << + " nps " << nps << " hashfull "<< GetHashfull() << " time " << GetTimeMs() - info.starttime << " pv "; // loop over the moves within a PV line for (int count = 0; count < std::max(pvTable.pvLength[0], 1); count++) { @@ -262,7 +262,7 @@ void PrintUciOutput(const int score, const int depth, const ThreadData* td, cons // Pretty print search info std::cout << std::setw(3) << depth << "/"; - std::cout << std::left << std::setw(3) << td->info.seldepth; + std::cout << std::left << std::setw(3) << info.seldepth; std::cout << std::right << std::setw(8) << time_string; std::cout << std::right << std::setw(10) << node_string; @@ -279,4 +279,4 @@ void PrintUciOutput(const int score, const int depth, const ThreadData* td, cons // print new line std::cout << std::endl; } -} +} \ No newline at end of file diff --git a/src/io.h b/src/io.h index cea4e26e..4cc83701 100644 --- a/src/io.h +++ b/src/io.h @@ -23,4 +23,4 @@ void PrintMoveList(const MoveList* list); [[nodiscard]] char* FormatMove(const Move move); -void PrintUciOutput(const int score, const int depth, const ThreadData* td, const UciOptions* options); +void PrintUciOutput(const int score, const int depth, const UciOptions* options); diff --git a/src/position.cpp b/src/position.cpp index ac67c881..bace0c89 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -9,6 +9,7 @@ #include "magic.h" #include "init.h" #include "cuckoo.h" +#include "search.h" NNUE nnue = NNUE(); @@ -27,17 +28,16 @@ void ResetBoard(Position* pos) { pos->state.plyFromNull = 0; } -void ResetInfo(SearchInfo* info) { - info->depth = 0; - info->nodes = 0; - info->starttime = 0; - info->stoptimeOpt = 0; - info->stoptimeMax = 0; - info->movestogo = -1; - info->stopped = false; - info->timeset = false; - info->movetimeset = false; - info->nodeset = false; +void ResetInfo() { + info.depth = 0; + info.starttime = 0; + info.stoptimeOpt = 0; + info.stoptimeMax = 0; + info.movestogo = -1; + info.timeset = false; + info.movetimeset = false; + info.nodeset = false; + setStop(false); } // Generates zobrist key from scratch @@ -522,4 +522,4 @@ bool hasGameCycle(Position* pos, int ply) { } } return false; -} +} \ No newline at end of file diff --git a/src/position.h b/src/position.h index b08a85bf..5fe26e29 100644 --- a/src/position.h +++ b/src/position.h @@ -191,7 +191,7 @@ void ParseFen(const std::string& command, Position* pos); // Parse a string of moves in coordinate format and plays them void parse_moves(const std::string& moves, Position* pos); -void ResetInfo(SearchInfo* info); +void ResetInfo(); // Retrieve a generic piece (useful when we don't know what type of piece we are dealing with [[nodiscard]] Bitboard GetPieceBB(const Position* pos, const int piecetype); diff --git a/src/search.cpp b/src/search.cpp index f270e8b5..e670b7cb 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include "bitboard.h" #include "move.h" #include "search.h" @@ -80,23 +79,19 @@ bool IsDraw(Position* pos) { // ClearForSearch handles the cleaning of the post and the info parameters to start search from a clean state void ClearForSearch(ThreadData* td) { - // Extract data structures from ThreadData - SearchInfo* info = &td->info; - - // Reset plies and search info - info->starttime = GetTimeMs(); - info->nodes = 0; - info->seldepth = 0; + td->nodes = 0; // Main thread clears pvTable, nodeSpentTable, and unpauses any eventual search thread if (td->id == 0) { + // Reset plies and search info + info.starttime = GetTimeMs(); + info.seldepth = 0; // Clean the Pv array std::memset(&pvTable, 0, sizeof(pvTable)); // Clean the node table std::memset(nodeSpentTable, 0, sizeof(nodeSpentTable)); - for (auto& helper_thread : threads_data) - helper_thread.info.stopped = false; + setStop(false); } } @@ -211,7 +206,6 @@ void RootSearch(int depth, ThreadData* td, UciOptions* options) { // Init thread_data objects for (size_t i = 0; i < threads_data.size(); i++) { - threads_data[i].info = td->info; threads_data[i].pos = td->pos; } @@ -252,7 +246,7 @@ void SearchPosition(int startDepth, int finalDepth, ThreadData* td, UciOptions* averageScore = averageScore == SCORE_NONE ? score : (averageScore + score) / 2; // If we stop (not at an exact depth) we print a final info string - printFinalInfoString = td->info.stopped; + printFinalInfoString = stop(); // Only the main thread handles time related tasks if (td->id == 0) { @@ -275,30 +269,30 @@ void SearchPosition(int startDepth, int finalDepth, ThreadData* td, UciOptions* // use the previous search to adjust some of the time management parameters, do not scale movetime time controls if ( td->RootDepth > 7 - && td->info.timeset) { - ScaleTm(td, bestMoveStabilityFactor, evalStabilityFactor); + && info.timeset) { + ScaleTm(bestMoveStabilityFactor, evalStabilityFactor); } // check if we just cleared a depth and more than OptTime passed, or we used more than the give nodes - if (StopEarly(&td->info) || NodesOver(&td->info)) + if (StopEarly() || NodesOver()) // Stop main-thread search - td->info.stopped = true; + setStop(true); } // Print a final info string if we have to if (td->id == 0 && printFinalInfoString) - PrintUciOutput(prevScore, currentDepth - 1, td, options); + PrintUciOutput(prevScore, currentDepth - 1, options); // stop calculating and return best move so far - if (td->info.stopped) + if (stop()) break; // If it's the main thread print the uci output if (td->id == 0) - PrintUciOutput(score, currentDepth, td, options); + PrintUciOutput(score, currentDepth, options); // Seldepth should only be related to the current ID loop - td->info.seldepth = 0; + info.seldepth = 0; prevScore = score; } } @@ -337,14 +331,14 @@ int AspirationWindowSearch(int prev_eval, int depth, ThreadData* td) { score = Negamax(alpha, beta, depth, false, td, ss); // Check if more than Maxtime passed and we have to stop - if (td->id == 0 && TimeOver(&td->info)) { + if (td->id == 0 && TimeOver()) { StopHelperThreads(); - td->info.stopped = true; + setStop(true); break; } // Stop calculating and return best move so far - if (td->info.stopped) break; + if (stop()) break; // We fell outside the window, so try again with a bigger window, since we failed low we can adjust beta to decrease the total window size if (score <= alpha) { @@ -372,7 +366,6 @@ int Negamax(int alpha, int beta, int depth, const bool cutNode, ThreadData* td, // Extract data structures from ThreadData Position* pos = &td->pos; SearchData* sd = &td->sd; - SearchInfo* info = &td->info; const bool mainT = td->id == 0; // Initialize the node @@ -390,8 +383,8 @@ int Negamax(int alpha, int beta, int depth, const bool cutNode, ThreadData* td, pvTable.pvLength[ss->ply] = ss->ply; // Check for the highest depth reached in search to report it to the cli - if (ss->ply > info->seldepth) - info->seldepth = ss->ply; + if (ss->ply > info.seldepth) + info.seldepth = ss->ply; // Check for early return conditions if (!rootNode) { @@ -417,9 +410,9 @@ int Negamax(int alpha, int beta, int depth, const bool cutNode, ThreadData* td, return Quiescence(alpha, beta, td, ss); // check if more than Maxtime passed and we have to stop - if (mainT && TimeOver(&td->info)) { + if (mainT && TimeOver()) { StopHelperThreads(); - td->info.stopped = true; + setStop(true); return 0; } @@ -596,7 +589,7 @@ int Negamax(int alpha, int beta, int depth, const bool cutNode, ThreadData* td, ss->contHistEntry = &sd->contHist[PieceTo(move)]; // increment nodes count - info->nodes++; + td->nodes++; // Play the move MakeMove(move, pos); @@ -731,8 +724,8 @@ int Negamax(int alpha, int beta, int depth, const bool cutNode, ThreadData* td, AddMove(move, isQuiet ? &quietMoves : &noisyMoves); // increment nodes count - info->nodes++; - const uint64_t nodesBeforeSearch = info->nodes; + td->nodes++; + const uint64_t nodesBeforeSearch = td->nodes; // Conditions to consider LMR. Calculate how much we should reduce the search depth. if (totalMoves > 1 && depth >= 3 && (isQuiet || !ttPv)) { @@ -809,9 +802,9 @@ int Negamax(int alpha, int beta, int depth, const bool cutNode, ThreadData* td, // take move back UnmakeMove(move, pos); if (mainT && rootNode) - nodeSpentTable[FromTo(move)] += info->nodes - nodesBeforeSearch; + nodeSpentTable[FromTo(move)] += td->nodes - nodesBeforeSearch; - if (info->stopped) + if (stop()) return 0; // If the score of the current move is the best we've found until now @@ -882,7 +875,6 @@ template int Quiescence(int alpha, int beta, ThreadData* td, SearchStack* ss) { Position* pos = &td->pos; SearchData* sd = &td->sd; - SearchInfo* info = &td->info; const bool inCheck = pos->getCheckers(); // tte is an TT entry, it will store the values fetched from the TT TTEntry tte; @@ -890,9 +882,9 @@ int Quiescence(int alpha, int beta, ThreadData* td, SearchStack* ss) { int rawEval; // check if more than Maxtime passed and we have to stop - if (td->id == 0 && TimeOver(&td->info)) { + if (td->id == 0 && TimeOver()) { StopHelperThreads(); - td->info.stopped = true; + setStop(true); return 0; } @@ -991,14 +983,14 @@ int Quiescence(int alpha, int beta, ThreadData* td, SearchStack* ss) { // Play the move MakeMove(move, pos); // increment nodes count - info->nodes++; + td->nodes++; // Call Quiescence search recursively const int score = -Quiescence(-beta, -alpha, td, ss + 1); // take move back UnmakeMove(move, pos); - if (info->stopped) + if (stop()) return 0; // If the score of the current move is the best we've found until now @@ -1030,4 +1022,4 @@ int Quiescence(int alpha, int beta, ThreadData* td, SearchStack* ss) { StoreTTEntry(pos->posKey, MoveToTT(bestmove), ScoreToTT(bestScore, ss->ply), rawEval, bound, 0, pvNode, ttPv); return bestScore; -} +} \ No newline at end of file diff --git a/src/search.h b/src/search.h index 2aec1227..a1b9d7fc 100644 --- a/src/search.h +++ b/src/search.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "history.h" #include "position.h" @@ -36,16 +37,29 @@ struct PvTable { inline PvTable pvTable; inline uint64_t nodeSpentTable[64 * 64]; +inline SearchInfo info; +inline std::atomic stopped = false; + +inline bool stop(){ + return stopped.load(std::memory_order_relaxed); +} + +inline void setStop(bool s){ + stopped.store(s, std::memory_order_relaxed); +} + // a collection of all the data a thread needs to conduct a search struct ThreadData { int id = 0; Position pos; SearchData sd; - SearchInfo info; int RootDepth; int nmpPlies; + u64 nodes; }; +inline ThreadData mainTD; + // ClearForSearch handles the cleaning of the thread data from a clean state void ClearForSearch(ThreadData* td); diff --git a/src/threads.h b/src/threads.h index fdc3da35..e78b6442 100644 --- a/src/threads.h +++ b/src/threads.h @@ -17,16 +17,14 @@ inline std::vector threads_data; [[nodiscard]] inline uint64_t GetTotalNodes() { uint64_t nodes = 0ULL; for (const auto& td : threads_data) { - nodes += td.info.nodes; + nodes += td.nodes; } return nodes; } inline void StopHelperThreads() { // Stop helper threads - for (auto& td : threads_data) { - td.info.stopped = true; - } + setStop(true); for (auto& th : threads) { if (th.joinable()) @@ -34,4 +32,4 @@ inline void StopHelperThreads() { } threads.clear(); -} +} \ No newline at end of file diff --git a/src/time_manager.cpp b/src/time_manager.cpp index 77b73782..1b6646d3 100644 --- a/src/time_manager.cpp +++ b/src/time_manager.cpp @@ -5,33 +5,33 @@ #include "misc.h" // Calculate how much time to spend on searching a move -void Optimum(SearchInfo* info, int time, int inc) { +void Optimum(int time, int inc) { // If ccrl sent us a negative time just assume we have a workable amount of time to search for a move if (time < 0) time = 1000; // Reserve some time overhead to avoid timing out in the engine-gui communication process const int safety_overhead = std::min(300, time / 2); time -= safety_overhead; // if we received a movetime command we need to spend exactly that amount of time on the move, so we don't scale - if (info->movetimeset) { - info->stoptimeMax = info->starttime + time; - info->stoptimeOpt = info->starttime + time; + if (info.movetimeset) { + info.stoptimeMax = info.starttime + time; + info.stoptimeOpt = info.starttime + time; } // else If we received a movestogo parameter we use total_time/movestogo - else if (info->timeset && info->movestogo != -1) { + else if (info.timeset && info.movestogo != -1) { // Divide the time you have left for how many moves you have to play - const auto basetime = time / info->movestogo; + const auto basetime = time / info.movestogo; // Never use more than 76% of the total time left for a single move const auto maxtimeBound = 0.76 * time; // optime is the time we use to stop if we just cleared a depth const auto optime = std::min(0.76 * basetime, maxtimeBound); // maxtime is the absolute maximum time we can spend on a search (unless it is bigger than the bound) const auto maxtime = std::min(3.04 * basetime, maxtimeBound); - info->stoptimeMax = info->starttime + maxtime; - info->stoptimeBaseOpt = optime; - info->stoptimeOpt = info->starttime + info->stoptimeBaseOpt; + info.stoptimeMax = info.starttime + maxtime; + info.stoptimeBaseOpt = optime; + info.stoptimeOpt = info.starttime + info.stoptimeBaseOpt; } // else if we received wtime/btime we calculate an over and upper bound for the time usage based on fixed coefficients - else if (info->timeset) { + else if (info.timeset) { int basetime = time * 0.054 + inc * 0.85; // Never use more than 76% of the total time left for a single move const auto maxtimeBound = 0.76 * time; @@ -39,39 +39,38 @@ void Optimum(SearchInfo* info, int time, int inc) { const auto optime = std::min(0.76 * basetime, maxtimeBound); // maxtime is the absolute maximum time we can spend on a search (unless it is bigger than the bound) const auto maxtime = std::min(3.04 * basetime, maxtimeBound); - info->stoptimeMax = info->starttime + maxtime; - info->stoptimeBaseOpt = optime; - info->stoptimeOpt = info->starttime + info->stoptimeBaseOpt; + info.stoptimeMax = info.starttime + maxtime; + info.stoptimeBaseOpt = optime; + info.stoptimeOpt = info.starttime + info.stoptimeBaseOpt; } } -bool StopEarly(const SearchInfo* info) { +bool StopEarly() { // check if we used all the nodes/movetime we had or if we used more than our lowerbound of time - return (info->timeset || info->movetimeset) && GetTimeMs() > info->stoptimeOpt; + return (info.timeset || info.movetimeset) && GetTimeMs() > info.stoptimeOpt; } -void ScaleTm(ThreadData* td, const int bestMoveStabilityFactor, const int evalStabilityFactor) { +void ScaleTm(const int bestMoveStabilityFactor, const int evalStabilityFactor) { constexpr double bestmoveScale[5] = {2.43, 1.35, 1.09, 0.88, 0.68}; constexpr double evalScale[5] = {1.25, 1.15, 1.00, 0.94, 0.88}; const int bestmove = GetBestMove(); // Calculate how many nodes were spent on checking the best move - const double bestMoveNodesFraction = static_cast(nodeSpentTable[FromTo(bestmove)]) / static_cast(td->info.nodes); + const double bestMoveNodesFraction = static_cast(nodeSpentTable[FromTo(bestmove)]) / static_cast(mainTD.nodes); const double nodeScalingFactor = (1.52 - bestMoveNodesFraction) * 1.74; const double bestMoveScalingFactor = bestmoveScale[bestMoveStabilityFactor]; const double evalScalingFactor = evalScale[evalStabilityFactor]; // Scale the search time based on how many nodes we spent and how the best move changed - td->info.stoptimeOpt = std::min(td->info.starttime + td->info.stoptimeBaseOpt * nodeScalingFactor * bestMoveScalingFactor * evalScalingFactor, td->info.stoptimeMax); + info.stoptimeOpt = std::min(info.starttime + info.stoptimeBaseOpt * nodeScalingFactor * bestMoveScalingFactor * evalScalingFactor, info.stoptimeMax); } -bool NodesOver(const SearchInfo* info) { +bool NodesOver() { // check if we used all the nodes/movetime we had or if we used more than our lowerbound of time - return info->nodeset && info->nodes >= info->nodeslimit; + return info.nodeset && mainTD.nodes >= info.nodeslimit; } -bool TimeOver(const SearchInfo* info) { - // check if more than Maxtime passed and we have to stop +bool TimeOver() { return NodesOver(info) || ((info->timeset || info->movetimeset) && ((info->nodes & 1023) == 1023) && GetTimeMs() > info->stoptimeMax); -} +} \ No newline at end of file diff --git a/src/time_manager.h b/src/time_manager.h index f1683e57..5f5fecec 100644 --- a/src/time_manager.h +++ b/src/time_manager.h @@ -3,8 +3,8 @@ struct SearchInfo; struct ThreadData; -void Optimum(SearchInfo* info, int time, int inc); -[[nodiscard]] bool StopEarly(const SearchInfo* info); -[[nodiscard]] bool TimeOver(const SearchInfo* info); -[[nodiscard]] bool NodesOver(const SearchInfo* info); -void ScaleTm(ThreadData* td, const int bestMoveStabilityFactor, const int evalStabilityFactor); +void Optimum(int time, int inc); +[[nodiscard]] bool StopEarly(); +[[nodiscard]] bool TimeOver(); +[[nodiscard]] bool NodesOver(); +void ScaleTm(const int bestMoveStabilityFactor, const int evalStabilityFactor); \ No newline at end of file diff --git a/src/types.h b/src/types.h index 5645858c..6bd77488 100644 --- a/src/types.h +++ b/src/types.h @@ -21,6 +21,8 @@ using ZobristKey = uint64_t; using Move = uint32_t; using PackedMove = uint16_t; +using u64 = uint64_t; + constexpr Move NOMOVE = 0; constexpr int MAXPLY = 256; constexpr int MAXDEPTH = MAXPLY; diff --git a/src/uci.cpp b/src/uci.cpp index 249b760f..e1c4ae40 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -105,8 +105,8 @@ void ParsePosition(const std::string& command, Position* pos) { } // parse UCI "go" command, returns true if we have to search afterwards and false otherwise -bool ParseGo(const std::string& line, SearchInfo* info, Position* pos) { - ResetInfo(info); +bool ParseGo(const std::string& line, Position* pos) { + ResetInfo(); int depth = -1, movetime = -1; int movestogo; int time = -1, inc = 0; @@ -135,23 +135,23 @@ bool ParseGo(const std::string& line, SearchInfo* info, Position* pos) { if (tokens.at(i) == "wtime" && pos->side == WHITE) { time = std::stoi(tokens[i + 1]); - info->timeset = true; + info.timeset = true; } if (tokens.at(i) == "btime" && pos->side == BLACK) { time = std::stoi(tokens[i + 1]); - info->timeset = true; + info.timeset = true; } if (tokens.at(i) == "movestogo") { movestogo = std::stoi(tokens[i + 1]); if (movestogo > 0) - info->movestogo = movestogo; + info.movestogo = movestogo; } - if (tokens.at(i) == "movetime") { + if (tokens.at(i) == "movetime") { movetime = std::stoi(tokens[i + 1]); time = movetime; - info->movetimeset = true; + info.movetimeset = true; } if (tokens.at(i) == "depth") { @@ -159,27 +159,27 @@ bool ParseGo(const std::string& line, SearchInfo* info, Position* pos) { } if (tokens.at(i) == "nodes") { - info->nodeset = true; - info->nodeslimit = std::stoi(tokens[i + 1]); + info.nodeset = true; + info.nodeslimit = std::stoi(tokens[i + 1]); } } - info->starttime = GetTimeMs(); - info->depth = depth; + info.starttime = GetTimeMs(); + info.depth = depth; // calculate time allocation for the move - Optimum(info, time, inc); + Optimum(time, inc); if (depth == -1) { - info->depth = MAXDEPTH; + info.depth = MAXDEPTH; } std::cout << "info "; std::cout << "time: " << time << " "; - std::cout << "start: " << info->starttime << " "; - std::cout << "stopOpt: " << info->stoptimeOpt << " "; - std::cout << "stopMax: " << info->stoptimeMax << " "; - std::cout << "depth: " << info->depth << " "; - std::cout << "timeset: " << info->timeset << " "; - std::cout << "nodeset: " << info->nodeset << std::endl; + std::cout << "start: " << info.starttime << " "; + std::cout << "stopOpt: " << info.stoptimeOpt << " "; + std::cout << "stopMax: " << info.stoptimeMax << " "; + std::cout << "depth: " << info.depth << " "; + std::cout << "timeset: " << info.timeset << " "; + std::cout << "nodeset: " << info.nodeset << std::endl; return true; } @@ -204,7 +204,8 @@ void UciLoop(int argc, char** argv) { bool parsed_position = false; UciOptions uciOptions; - ThreadData* td(new ThreadData()); + + ThreadData* td = &mainTD; std::thread main_thread; state threads_state = Idle; // print engine info @@ -255,11 +256,11 @@ void UciLoop(int argc, char** argv) { ParsePosition("position startpos", &td->pos); } // call parse go function - bool search = ParseGo(input, &td->info, &td->pos); + bool search = ParseGo(input, &td->pos); // Start search in a separate thread if (search) { threads_state = Search; - main_thread = std::thread(RootSearch, td->info.depth, td, &uciOptions); + main_thread = std::thread(RootSearch, info.depth, &mainTD, &uciOptions); } } @@ -303,8 +304,8 @@ void UciLoop(int argc, char** argv) { // Stop helper threads StopHelperThreads(); // stop main thread search - td->info.stopped = true; - } + setStop(true); + } threads_state = Idle; } @@ -314,14 +315,13 @@ void UciLoop(int argc, char** argv) { // Stop helper threads StopHelperThreads(); // stop main thread search - td->info.stopped = true; + setStop(true); } threads_state = Idle; // Join previous search thread if it exists if (main_thread.joinable()) main_thread.join(); - // free thread data - delete td; + // quit from the chess engine program execution break; } @@ -383,4 +383,4 @@ void UciLoop(int argc, char** argv) { } else std::cout << "Unknown command: " << input << std::endl; } -} +} \ No newline at end of file diff --git a/src/uci.h b/src/uci.h index 368b265f..7954ad4b 100644 --- a/src/uci.h +++ b/src/uci.h @@ -8,9 +8,9 @@ struct Position; struct SearchInfo; struct UciOptions { - uint64_t Hash = 16; static constexpr int MultiPV = 1; int Threads = 1; + uint64_t Hash = 16; }; // Internal flag to decide if to pretty or ugly print search results @@ -23,7 +23,7 @@ inline bool tryhardmode = false; void ParsePosition(const std::string& command, Position* pos); // parse UCI "go" command -[[nodiscard]] bool ParseGo(const std::string& line, SearchInfo* info, Position* pos); +[[nodiscard]] bool ParseGo(const std::string& line, Position* pos); // main UCI loop void UciLoop(int argc, char** argv);