From: Fabian Fichter Date: Wed, 11 Mar 2020 22:44:50 +0000 (+0100) Subject: Communicate clock times in bughouse X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=5bccf6c0abbe9bb7e67f5b83b26ea6f286352972;p=fairystockfish.git Communicate clock times in bughouse Consider clock times of partner board in time management (#64). --- diff --git a/src/partner.cpp b/src/partner.cpp index 77ef9da..5b7c583 100644 --- a/src/partner.cpp +++ b/src/partner.cpp @@ -27,16 +27,20 @@ PartnerHandler Partner; // Global object void PartnerHandler::reset() { - sitRequested = partnerDead = weDead = false; + fast = sitRequested = partnerDead = weDead = false; + time = opptime = 0; } +template void PartnerHandler::ptell(const std::string& message) { - sync_cout << "tellics ptell " << message << sync_endl; + if (p == ALL_PARTNERS || (p == FAIRY && isFairy) || (p == HUMAN && !isFairy)) + sync_cout << "tellics ptell " << message << sync_endl; } void PartnerHandler::parse_partner(std::istringstream& is) { std::string token; if (is >> token) + // handshake to identify Fairy-Stockfish ptell("partner Fairy-Stockfish is an engine. Ask it 'help' for supported commands."); else isFairy = false; @@ -47,45 +51,54 @@ void PartnerHandler::parse_ptell(std::istringstream& is, const Position& pos) { is >> token; if (token == "partner") { + // handshake to identify Fairy-Stockfish if (is >> token && token == "Fairy-Stockfish") isFairy = true; } else if (token == "help") { if (!(is >> token)) - ptell("I listen to the commands help, sit, go, and move. Ptell 'help sit', etc. for details."); + { + ptell("I listen to the commands help, sit, go, move, fast, slow, dead, x, time, and otim."); + ptell("Tell 'help sit', etc. for details."); + } else if (token == "sit") - ptell("After receiving 'sit', I stop moving. Also see 'go'."); + ptell("After receiving 'sit', I stop moving. Also see 'go'."); else if (token == "go") - ptell("After receiving 'go', I will no longer sit."); + ptell("After receiving 'go', I will no longer sit."); else if (token == "move") { - ptell("After receiving 'move', I will move immediately." ); - ptell("If you specify a valid move, e.g., 'move e2e4', I will play it."); + ptell("After receiving 'move', I will move immediately." ); + ptell("If you specify a valid move, e.g., 'move e2e4', I will play it."); + } + else if (token == "fast") + ptell("After receiving 'go', I will play fast."); + else if (token == "slow") + ptell("After receiving 'slow', I will play at normal speed."); + else if (token == "dead") + ptell("After receiving 'dead', I assume you are dead and I play fast."); + else if (token == "x") + ptell("After receiving 'x', I assume I can play normally again."); + else if (token == "time") + { + ptell("'time' together with your time in centiseconds allows me to consider your time."); + ptell("E.g., 'time 1000' for 10 seconds."); } + else if (token == "otim") + ptell("'otim' together with your opponent's time in centiseconds allows me to consider his time."); } else if (!pos.two_boards()) return; else if (token == "sit") { sitRequested = true; - ptell("I sit, tell me 'go' to continue"); + ptell("I sit, tell me 'go' to continue"); } else if (token == "go") { sitRequested = false; Threads.stop = true; } - else if (token == "dead") - { - partnerDead = true; - ptell("I will play fast"); - } - else if (token == "x") - { - partnerDead = false; - ptell("I will play normally again"); - } else if (token == "move") { if (is >> token) @@ -95,9 +108,43 @@ void PartnerHandler::parse_ptell(std::istringstream& is, const Position& pos) { if (move && !Threads.abort.exchange(true)) moveRequested = move; else - ptell("sorry, not possible"); + ptell("sorry, not possible"); } else Threads.stop = true; } + else if (token == "fast") + { + fast = true; + ptell("I play fast, tell me 'slow' to play normally again"); + } + else if (token == "slow") + { + fast = false; + ptell("I play at normal speed again."); + } + else if (token == "dead") + { + partnerDead = true; + ptell("I play fast, tell me 'x' if you are no longer dead."); + } + else if (token == "x") + { + partnerDead = false; + ptell("I play normally again"); + } + else if (token == "time") + { + int value; + time = (is >> value) ? value : 0; + } + else if (token == "otim") + { + int value; + opptime = (is >> value) ? value : 0; + } } + +template void PartnerHandler::ptell(const std::string&); +template void PartnerHandler::ptell(const std::string&); +template void PartnerHandler::ptell(const std::string&); diff --git a/src/partner.h b/src/partner.h index 47fbc7d..c63c06c 100644 --- a/src/partner.h +++ b/src/partner.h @@ -27,14 +27,22 @@ /// PartnerHandler manages the communication with the partner /// in games played on two boards, such as bughouse. +enum PartnerType { + HUMAN, + FAIRY, + ALL_PARTNERS +}; + struct PartnerHandler { void reset(); + template void ptell(const std::string& message); void parse_partner(std::istringstream& is); void parse_ptell(std::istringstream& is, const Position& pos); std::atomic isFairy; - std::atomic sitRequested, partnerDead, weDead; + std::atomic fast, sitRequested, partnerDead, weDead; + std::atomic time, opptime; Move moveRequested; }; diff --git a/src/search.cpp b/src/search.cpp index 86d9828..013b1ca 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -258,8 +258,12 @@ void MainThread::search() { Thread::search(); // Let's start searching! } - if (rootPos.two_boards() && !Threads.abort) + if (rootPos.two_boards() && !Threads.abort && Options["Protocol"] == "xboard") { + if (Limits.time[us]) + Partner.ptell("time " + std::to_string(Limits.time[us] / 10)); + if (Limits.time[~us]) + Partner.ptell("otim " + std::to_string(Limits.time[~us] / 10)); if (!Partner.weDead && this->rootMoves[0].score <= VALUE_MATED_IN_MAX_PLY) { Partner.ptell("dead"); diff --git a/src/timeman.cpp b/src/timeman.cpp index b63d000..a434502 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -120,6 +120,15 @@ void TimeManagement::init(const Position& pos, Search::LimitsType& limits, Color + limits.inc[us] * (hypMTG - 1) - moveOverhead * (2 + std::min(hypMTG, 40)); + // Adjust time management for four-player variants + if (pos.two_boards()) + { + if (Partner.partnerDead && Partner.opptime) + hypMyTime -= Partner.opptime * 10; + else if (Partner.fast || Partner.partnerDead) + hypMyTime /= 4; + } + hypMyTime = std::max(hypMyTime, TimePoint(0)); TimePoint t1 = minThinkingTime + remaining(pos, hypMyTime, hypMTG, ply, slowMover); @@ -129,9 +138,6 @@ void TimeManagement::init(const Position& pos, Search::LimitsType& limits, Color maximumTime = std::min(t2, maximumTime); } - if (pos.two_boards() && Partner.partnerDead) - optimumTime /= 4; - if (Options["Ponder"]) optimumTime += optimumTime / 4; }