diff --git a/cpp/command/gtp.cpp b/cpp/command/gtp.cpp index 26391e2a8..29a58a977 100644 --- a/cpp/command/gtp.cpp +++ b/cpp/command/gtp.cpp @@ -364,8 +364,13 @@ struct GTPEngine { double desiredDynamicPDAForWhite; std::unique_ptr patternBonusTable; + double delayMoveScale; + double delayMoveMax; + Player perspective; + Rand gtpRand; + double genmoveTimeSum; //Positions during this game when genmove was called std::vector genmoveSamples; @@ -377,6 +382,7 @@ struct GTPEngine { bool assumeMultiBlackHandicap, bool prevtEncore, bool autoPattern, double dynamicPDACapPerOppLead, bool staticPDAPrecedence, double normAvoidRepeatedPatternUtility, double hcapAvoidRepeatedPatternUtility, + double delayScale, double delayMax, Player persp, int pvLen, std::unique_ptr&& pbTable ) @@ -406,6 +412,8 @@ struct GTPEngine { lastSearchFactor(1.0), desiredDynamicPDAForWhite(0.0), patternBonusTable(std::move(pbTable)), + delayMoveScale(delayScale), + delayMoveMax(delayMax), perspective(persp), genmoveTimeSum(0.0), genmoveSamples() @@ -1043,6 +1051,21 @@ struct GTPEngine { return; } + SearchNode* rootNode = bot->getSearch()->rootNode; + if(rootNode != NULL && delayMoveScale > 0.0 && delayMoveMax > 0.0) { + const NNOutput* humanOutput = rootNode->getHumanOutput(); + const float* policyProbs = humanOutput != NULL ? humanOutput->getPolicyProbsMaybeNoised() : NULL; + int pos = bot->getSearch()->getPos(moveLoc); + if(policyProbs != NULL) { + double prob = std::max(0.0,(double)policyProbs[pos]); + double meanWait = 0.5 * delayMoveScale / (prob + 0.10); + double waitTime = gtpRand.nextGamma(2.0) * meanWait / 2.0; + waitTime = std::min(waitTime,delayMoveMax); + waitTime = std::max(waitTime,0.0001); + std::this_thread::sleep_for(std::chrono::duration(waitTime)); + } + } + ReportedSearchValues values; double winLossValue; double lead; @@ -1856,6 +1879,8 @@ int MainCmds::gtp(const vector& args) { const double normalAvoidRepeatedPatternUtility = initialGenmoveParams.avoidRepeatedPatternUtility; const double handicapAvoidRepeatedPatternUtility = cfg.contains("avoidRepeatedPatternUtility") ? initialGenmoveParams.avoidRepeatedPatternUtility : 0.005; + const double delayMoveScale = cfg.contains("delayMoveScale") ? cfg.getDouble("delayMoveScale",0.0,10000.0) : 0.0; + const double delayMoveMax = cfg.contains("delayMoveMax") ? cfg.getDouble("delayMoveMax",0.0,1000000.0) : 1000000.0; int defaultBoardXSize = -1; int defaultBoardYSize = -1; @@ -1897,6 +1922,7 @@ int MainCmds::gtp(const vector& args) { dynamicPlayoutDoublingAdvantageCapPerOppLead, staticPDATakesPrecedence, normalAvoidRepeatedPatternUtility, handicapAvoidRepeatedPatternUtility, + delayMoveScale,delayMoveMax, perspective,analysisPVLen, std::move(patternBonusTable) ); diff --git a/cpp/configs/gtp_human5k_example.cfg b/cpp/configs/gtp_human5k_example.cfg index 7075952f7..9183cb57d 100644 --- a/cpp/configs/gtp_human5k_example.cfg +++ b/cpp/configs/gtp_human5k_example.cfg @@ -41,6 +41,11 @@ maxVisits = 40 numSearchThreads = 1 lagBuffer = 1.0 +# Rough scale in seconds to ranomly delay moving, so as not to respond instantly. +# Some moves will delay longer, some moves will delay a little less. +delayMoveScale = 2.0 +delayMoveMax = 10.0 + # =========================================================================== # HUMAN SL PARAMETERS # ===========================================================================