Skip to content

Commit

Permalink
experimental ponder support
Browse files Browse the repository at this point in the history
issues:
* `lift` and other commands during ponder
* stability?
  • Loading branch information
ianfab committed Oct 28, 2020
1 parent 5c48938 commit 17500e6
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 24 deletions.
5 changes: 4 additions & 1 deletion src/search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,14 +301,17 @@ void MainThread::search() {
if (Options["Protocol"] == "xboard")
{
// Send move only when not in analyze mode and not at game end
if (!Options["UCI_AnalyseMode"] && rootMoves[0].pv[0] != MOVE_NONE && !Threads.abort.exchange(true))
if (!Limits.infinite && !ponder && rootMoves[0].pv[0] != MOVE_NONE && !Threads.abort.exchange(true))
{
Move bestMove = bestThread->rootMoves[0].pv[0];
sync_cout << "move " << UCI::move(rootPos, bestMove) << sync_endl;
if (XBoard::stateMachine->moveAfterSearch)
{
XBoard::stateMachine->do_move(bestMove);
XBoard::stateMachine->moveAfterSearch = false;
if (Options["Ponder"] && ( bestThread->rootMoves[0].pv.size() > 1
|| bestThread->rootMoves[0].extract_ponder_from_tt(rootPos)))
XBoard::stateMachine->ponderMove = bestThread->rootMoves[0].pv[1];
}
}
return;
Expand Down
7 changes: 7 additions & 0 deletions src/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "uci.h"
#include "syzygy/tbprobe.h"
#include "tt.h"
#include "xboard.h"

ThreadPool Threads; // Global object

Expand Down Expand Up @@ -109,6 +110,12 @@ void Thread::idle_loop() {
std::unique_lock<std::mutex> lk(mutex);
searching = false;
cv.notify_one(); // Wake up anyone waiting for search finished
// Start ponder search from separate thread to prevent deadlock
if (Threads.size() && this == Threads.main() && XBoard::stateMachine && XBoard::stateMachine->ponderMove)
{
NativeThread t(&XBoard::StateMachine::ponder, XBoard::stateMachine);
t.detach();
}
cv.wait(lk, [&]{ return searching; });

if (exit)
Expand Down
1 change: 1 addition & 0 deletions src/thread_win32_osx.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class NativeThread {
pthread_create(&thread, attr, start_routine<T>, new P(obj, fun));
}
void join() { pthread_join(thread, NULL); }
void detach() { pthread_detach(thread); }
};

#else // Default case: use STL classes
Expand Down
72 changes: 49 additions & 23 deletions src/xboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,31 @@ namespace {
return limits;
}();

} // namespace

namespace XBoard {

StateMachine* stateMachine = nullptr;

// go() starts the search for game play, analysis, or perft.

void go(Position& pos, Search::LimitsType limits, StateListPtr& states) {
void StateMachine::go(Search::LimitsType searchLimits, bool ponder) {

searchLimits.startTime = now(); // As early as possible!

limits.startTime = now(); // As early as possible!
Threads.start_thinking(pos, states, searchLimits, ponder);
}

void StateMachine::ponder() {

Threads.start_thinking(pos, states, limits, false);
do_move(ponderMove);
ponderMove = MOVE_NONE;
go(limits, true);
}

// setboard() is called when engine receives the "setboard" XBoard command.

void setboard(Position& pos, std::deque<Move>& moveList, StateListPtr& states, std::string fen = "") {
void StateMachine::setboard(std::string fen) {

if (fen.empty())
fen = variants.find(Options["UCI_Variant"])->second->startFen;
Expand All @@ -57,12 +70,6 @@ namespace {
pos.set(variants.find(Options["UCI_Variant"])->second, fen, Options["UCI_Chess960"], &states->back(), Threads.main());
}

} // namespace

namespace XBoard {

StateMachine* stateMachine;

// do_move() is called when engine needs to apply a move when using XBoard protocol.

void StateMachine::do_move(Move m) {
Expand Down Expand Up @@ -94,13 +101,32 @@ namespace XBoard {
/// StateMachine::process_command() processes commands of the XBoard protocol.

void StateMachine::process_command(std::string token, std::istringstream& is) {
// TODO: move logic to respective commands?
if (moveAfterSearch && token != "ptell")
{
// try to abort search in bughouse when receiving "holding" command
if (token == "holding")
Threads.abort = true;
Threads.stop = true;
Threads.main()->wait_for_search_finished();
Threads.main()->ponder = false;
}
// TODO: how to deal with other commands during ponder (such as lift -> consider other pos!)?
if (Threads.main()->ponder)
{
assert(moveList.size());
if ((token != "usermove" || is >> token) && token == UCI::move(pos, moveList.back()))
{
Threads.main()->ponder = false;
return;
}
else
{
Threads.stop = true;
Threads.main()->wait_for_search_finished();
undo_move();
Threads.main()->ponder = false;
}
}
if (token == "protover")
{
Expand Down Expand Up @@ -172,7 +198,7 @@ void StateMachine::process_command(std::string token, std::istringstream& is) {
else if (token == "new")
{
Search::clear();
setboard(pos, moveList, states);
setboard();
// play second by default
playColor = ~pos.side_to_move();
Threads.sit = false;
Expand All @@ -182,14 +208,14 @@ void StateMachine::process_command(std::string token, std::istringstream& is) {
{
if (is >> token)
Options["UCI_Variant"] = token;
setboard(pos, moveList, states);
setboard();
}
else if (token == "force")
playColor = COLOR_NB;
else if (token == "go")
{
playColor = pos.side_to_move();
go(pos, limits, states);
go(limits);
moveAfterSearch = true;
}
else if (token == "level" || token == "st" || token == "sd" || token == "time" || token == "otim")
Expand Down Expand Up @@ -254,14 +280,14 @@ void StateMachine::process_command(std::string token, std::istringstream& is) {
do_move(m);
// apply setboard if passing does not lead to a match
if (pos.key() != p.key())
setboard(pos, moveList, states, fen);
setboard(fen);
}
else
setboard(pos, moveList, states, fen);
setboard(fen);
// Winboard sends setboard after passing moves
if (pos.side_to_move() == playColor)
{
go(pos, limits, states);
go(limits);
moveAfterSearch = true;
}
}
Expand Down Expand Up @@ -293,7 +319,7 @@ void StateMachine::process_command(std::string token, std::istringstream& is) {
else if (token == "analyze")
{
Options["UCI_AnalyseMode"] = std::string("true");
go(pos, analysisLimits, states);
go(analysisLimits);
}
else if (token == "exit")
{
Expand All @@ -312,7 +338,7 @@ void StateMachine::process_command(std::string token, std::istringstream& is) {
}
undo_move();
if (Options["UCI_AnalyseMode"])
go(pos, analysisLimits, states);
go(analysisLimits);
}
}
// Bughouse commands
Expand Down Expand Up @@ -354,18 +380,18 @@ void StateMachine::process_command(std::string token, std::istringstream& is) {
std::transform(black_holdings.begin(), black_holdings.end(), black_holdings.begin(), ::tolower);
fen = pos.fen(false, false, 0, white_holdings + black_holdings);
}
setboard(pos, moveList, states, fen);
setboard(fen);
}
// restart search
if (moveAfterSearch)
go(pos, limits, states);
go(limits);
}
// Additional custom non-XBoard commands
else if (token == "perft")
{
Search::LimitsType perft_limits;
is >> perft_limits.perft;
go(pos, perft_limits, states);
go(perft_limits);
}
else if (token == "d")
sync_cout << pos << sync_endl;
Expand All @@ -392,11 +418,11 @@ void StateMachine::process_command(std::string token, std::istringstream& is) {
else
sync_cout << (isMove ? "Illegal move: " : "Error (unknown command): ") << token << sync_endl;
if (Options["UCI_AnalyseMode"])
go(pos, analysisLimits, states);
go(analysisLimits);
else if (pos.side_to_move() == playColor)
{
go(pos, limits, states);
moveAfterSearch = true;
go(limits);
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/xboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,16 @@ class StateMachine {
moveList = std::deque<Move>();
moveAfterSearch = false;
playColor = COLOR_NB;
ponderMove = MOVE_NONE;
}
void go(Search::LimitsType searchLimits, bool ponder = false);
void ponder();
void setboard(std::string fen = "");
void do_move(Move m);
void undo_move();
void process_command(std::string token, std::istringstream& is);
bool moveAfterSearch;
Move ponderMove;

private:
Position& pos;
Expand Down

0 comments on commit 17500e6

Please sign in to comment.