From: Marco Costalba Date: Wed, 28 Dec 2011 17:27:18 +0000 (+0100) Subject: Add user-defined conversions to UCIOption X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=0759d8f4302d0ad262a2dabca465f1618677aeba Add user-defined conversions to UCIOption Greatly improves the usage. User defined conversions are a novelity for SF, another amazing C++ facility at work ! No functional change. Signed-off-by: Marco Costalba --- diff --git a/src/evaluate.cpp b/src/evaluate.cpp index ab10597b..5e278242 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -412,7 +412,7 @@ void read_evaluation_uci_options(Color us) { // If running in analysis mode, make sure we use symmetrical king safety. We do this // by replacing both Weights[kingDangerUs] and Weights[kingDangerThem] by their average. - if (Options["UCI_AnalyseMode"].value()) + if (Options["UCI_AnalyseMode"]) Weights[kingDangerUs] = Weights[kingDangerThem] = (Weights[kingDangerUs] + Weights[kingDangerThem]) / 2; init_safety(); @@ -1101,8 +1101,8 @@ namespace { Score weight_option(const std::string& mgOpt, const std::string& egOpt, Score internalWeight) { // Scale option value from 100 to 256 - int mg = Options[mgOpt].value() * 256 / 100; - int eg = Options[egOpt].value() * 256 / 100; + int mg = Options[mgOpt] * 256 / 100; + int eg = Options[egOpt] * 256 / 100; return apply_weight(make_score(mg, eg), internalWeight); } diff --git a/src/search.cpp b/src/search.cpp index 636ebd8e..c7bc8d17 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -296,12 +296,12 @@ void Search::think() { || count(SearchMoves.begin(), SearchMoves.end(), ml.move())) RootMoves.push_back(RootMove(ml.move())); - if (Options["OwnBook"].value()) + if (Options["OwnBook"]) { - if (Options["Book File"].value() != book.name()) - book.open(Options["Book File"].value()); + if (book.name() != (string)Options["Book File"]) + book.open(Options["Book File"]); - Move bookMove = book.probe(pos, Options["Best Book Move"].value()); + Move bookMove = book.probe(pos, Options["Best Book Move"]); if ( bookMove != MOVE_NONE && count(RootMoves.begin(), RootMoves.end(), bookMove)) @@ -315,24 +315,24 @@ void Search::think() { read_evaluation_uci_options(pos.side_to_move()); Threads.read_uci_options(); - TT.set_size(Options["Hash"].value()); - if (Options["Clear Hash"].value()) + TT.set_size(Options["Hash"]); + if (Options["Clear Hash"]) { Options["Clear Hash"] = false; TT.clear(); } - UCIMultiPV = Options["MultiPV"].value(); - SkillLevel = Options["Skill Level"].value(); + UCIMultiPV = Options["MultiPV"]; + SkillLevel = Options["Skill Level"]; // Do we have to play with skill handicap? In this case enable MultiPV that // we will use behind the scenes to retrieve a set of possible moves. SkillLevelEnabled = (SkillLevel < 20); MultiPV = (SkillLevelEnabled ? std::max(UCIMultiPV, (size_t)4) : UCIMultiPV); - if (Options["Use Search Log"].value()) + if (Options["Use Search Log"]) { - Log log(Options["Search Log Filename"].value()); + Log log(Options["Search Log Filename"]); log << "\nSearching: " << pos.to_fen() << "\ninfinite: " << Limits.infinite << " ponder: " << Limits.ponder @@ -362,11 +362,11 @@ void Search::think() { Threads.set_timer(0); Threads.set_size(1); - if (Options["Use Search Log"].value()) + if (Options["Use Search Log"]) { int e = elapsed_time(); - Log log(Options["Search Log Filename"].value()); + Log log(Options["Search Log Filename"]); log << "Nodes: " << pos.nodes_searched() << "\nNodes/second: " << (e > 0 ? pos.nodes_searched() * 1000 / e : 0) << "\nBest move: " << move_to_san(pos, RootMoves[0].pv[0]); @@ -512,7 +512,7 @@ namespace { if (SkillLevelEnabled && depth == 1 + SkillLevel) skillBest = do_skill_level(); - if (Options["Use Search Log"].value()) + if (Options["Use Search Log"]) pv_info_to_log(pos, depth, bestValue, elapsed_time(), &RootMoves[0].pv[0]); // Filter out startup noise when monitoring best move stability @@ -1758,7 +1758,7 @@ split_point_start: // At split points actual search starts from here while (m != pv) pos.undo_move(*--m); - Log l(Options["Search Log Filename"].value()); + Log l(Options["Search Log Filename"]); l << s.str() << endl; } diff --git a/src/thread.cpp b/src/thread.cpp index 18e35fb0..5c0ac84b 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -112,11 +112,11 @@ bool Thread::is_available_to(int master) const { void ThreadsManager::read_uci_options() { - maxThreadsPerSplitPoint = Options["Max Threads per Split Point"].value(); - minimumSplitDepth = Options["Min Split Depth"].value() * ONE_PLY; - useSleepingThreads = Options["Use Sleeping Threads"].value(); + maxThreadsPerSplitPoint = Options["Max Threads per Split Point"]; + minimumSplitDepth = Options["Min Split Depth"] * ONE_PLY; + useSleepingThreads = Options["Use Sleeping Threads"]; - set_size(Options["Threads"].value()); + set_size(Options["Threads"]); } diff --git a/src/timeman.cpp b/src/timeman.cpp index 8282f2c6..aece49d5 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -104,10 +104,10 @@ void TimeManager::init(const Search::LimitsType& limits, int currentPly) int hypMTG, hypMyTime, t1, t2; // Read uci parameters - int emergencyMoveHorizon = Options["Emergency Move Horizon"].value(); - int emergencyBaseTime = Options["Emergency Base Time"].value(); - int emergencyMoveTime = Options["Emergency Move Time"].value(); - int minThinkingTime = Options["Minimum Thinking Time"].value(); + int emergencyMoveHorizon = Options["Emergency Move Horizon"]; + int emergencyBaseTime = Options["Emergency Base Time"]; + int emergencyMoveTime = Options["Emergency Move Time"]; + int minThinkingTime = Options["Minimum Thinking Time"]; // Initialize to maximum values but unstablePVExtraTime that is reset unstablePVExtraTime = 0; @@ -132,7 +132,7 @@ void TimeManager::init(const Search::LimitsType& limits, int currentPly) maximumSearchTime = std::min(maximumSearchTime, t2); } - if (Options["Ponder"].value()) + if (Options["Ponder"]) optimumSearchTime += optimumSearchTime / 4; // Make sure that maxSearchTime is not over absoluteMaxSearchTime diff --git a/src/uci.cpp b/src/uci.cpp index c4d01fa1..02a3c30c 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -157,7 +157,7 @@ namespace { else return; - pos.from_fen(fen, Options["UCI_Chess960"].value()); + pos.from_fen(fen, Options["UCI_Chess960"]); // Parse move list (if any) while (is >> token && (m = move_from_uci(pos, token)) != MOVE_NONE) @@ -188,10 +188,14 @@ namespace { while (is >> token) value += string(" ", !value.empty()) + token; - if (Options.count(name)) - Options[name] = (value.empty() ? "true" : value); // UCI buttons don't have "value" - else + if (!Options.count(name)) cout << "No such option: " << name << endl; + + else if (value.empty()) // UCI buttons don't have a value + Options[name] = true; + + else + Options[name] = value; } diff --git a/src/ucioption.h b/src/ucioption.h index b8622e51..f0787132 100644 --- a/src/ucioption.h +++ b/src/ucioption.h @@ -35,10 +35,19 @@ public: UCIOption(bool v, std::string type = "check"); UCIOption(int v, int min, int max); - template T value() const; void operator=(const std::string& v); void operator=(bool v) { *this = std::string(v ? "true" : "false"); } + operator int() const { + assert(type == "check" || type == "button" || type == "spin"); + return (type == "spin" ? atoi(currentValue.c_str()) : currentValue == "true"); + } + + operator std::string() const { + assert(type == "string"); + return currentValue; + } + private: friend std::ostream& operator<<(std::ostream&, const OptionsMap&); @@ -48,29 +57,6 @@ private: }; -/// UCIOption::value() definition and specializations -template -T UCIOption::value() const { - - assert(type == "spin"); - return T(atoi(currentValue.c_str())); -} - -template<> -inline std::string UCIOption::value() const { - - assert(type == "string"); - return currentValue; -} - -template<> -inline bool UCIOption::value() const { - - assert(type == "check" || type == "button"); - return currentValue == "true"; -} - - /// Custom comparator because UCI options should be case insensitive struct CaseInsensitiveLess { bool operator() (const std::string&, const std::string&) const;