Async UCI options actions
authorMarco Costalba <mcostalba@gmail.com>
Sun, 4 Mar 2012 16:57:01 +0000 (17:57 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Mon, 5 Mar 2012 18:20:07 +0000 (19:20 +0100)
Introduce 'on change' actions that are triggered as soon as
an UCI option is changed by the GUI. This allows to set hash
size before to start the game, helpful especially on very fast
TC and big TT size.

As a side effect remove the 'button' type option, that now
is managed as a 'check' type.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>

src/main.cpp
src/search.cpp
src/thread.cpp
src/ucioption.cpp
src/ucioption.h

index 5a32ae3..920d948 100644 (file)
@@ -21,6 +21,7 @@
 #include <string>
 
 #include "bitboard.h"
+#include "ucioption.h"
 #include "position.h"
 #include "search.h"
 #include "thread.h"
@@ -38,6 +39,7 @@ int main(int argc, char* argv[]) {
   kpk_bitbase_init();
   Search::init();
   Threads.init();
+  TT.set_size(Options["Hash"]);
 
   cout << engine_info() << endl;
 
index 03df6d7..ea777dc 100644 (file)
@@ -278,14 +278,6 @@ void Search::think() {
 
   // Read UCI options: GUI could change UCI parameters during the game
   read_evaluation_uci_options(pos.side_to_move());
-  Threads.read_uci_options();
-
-  TT.set_size(Options["Hash"]);
-  if (Options["Clear Hash"])
-  {
-      Options["Clear Hash"] = false;
-      TT.clear();
-  }
 
   UCIMultiPV = Options["MultiPV"];
   SkillLevel = Options["Skill Level"];
index 7ffc3df..358ced5 100644 (file)
@@ -216,6 +216,8 @@ void ThreadsManager::set_size(int cnt) {
 
 void ThreadsManager::init() {
 
+  read_uci_options();
+
   cond_init(sleepCond);
   lock_init(splitLock);
 
index c754353..2f4d6f4 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "misc.h"
 #include "thread.h"
+#include "tt.h"
 #include "ucioption.h"
 
 using std::string;
@@ -29,6 +30,12 @@ using std::string;
 OptionsMap Options; // Global object
 
 
+/// 'On change' actions, triggered by an option's change event
+static void on_threads(UCIOption&) { Threads.read_uci_options(); }
+static void on_hash_size(UCIOption& o) { TT.set_size(o); }
+static void on_clear_hash(UCIOption& o) { TT.clear(); o = false; } // UCI button
+
+
 /// Our case insensitive less() function as required by UCI protocol
 static bool ci_less(char c1, char c2) { return tolower(c1) < tolower(c2); }
 
@@ -58,12 +65,12 @@ OptionsMap::OptionsMap() {
   o["Space"]                       = UCIOption(100, 0, 200);
   o["Aggressiveness"]              = UCIOption(100, 0, 200);
   o["Cowardice"]                   = UCIOption(100, 0, 200);
-  o["Min Split Depth"]             = UCIOption(msd, 4, 7);
-  o["Max Threads per Split Point"] = UCIOption(5, 4, 8);
+  o["Min Split Depth"]             = UCIOption(msd, 4, 7, on_threads);
+  o["Max Threads per Split Point"] = UCIOption(5, 4, 8, on_threads);
   o["Threads"]                     = UCIOption(cpus, 1, MAX_THREADS);
-  o["Use Sleeping Threads"]        = UCIOption(true);
-  o["Hash"]                        = UCIOption(32, 4, 8192);
-  o["Clear Hash"]                  = UCIOption(false, "button");
+  o["Use Sleeping Threads"]        = UCIOption(true, on_threads);
+  o["Hash"]                        = UCIOption(32, 4, 8192, on_hash_size);
+  o["Clear Hash"]                  = UCIOption(false, on_clear_hash);
   o["Ponder"]                      = UCIOption(true);
   o["OwnBook"]                     = UCIOption(true);
   o["MultiPV"]                     = UCIOption(1, 1, 500);
@@ -103,13 +110,13 @@ std::ostream& operator<<(std::ostream& os, const OptionsMap& om) {
 
 /// UCIOption class c'tors
 
-UCIOption::UCIOption(const char* v) : type("string"), min(0), max(0), idx(Options.size())
+UCIOption::UCIOption(const char* v, Fn* f) : type("string"), min(0), max(0), idx(Options.size()), on_change_action(f)
 { defaultValue = currentValue = v; }
 
-UCIOption::UCIOption(bool v, string t) : type(t), min(0), max(0), idx(Options.size())
+UCIOption::UCIOption(bool v, Fn* f) : type("check"), min(0), max(0), idx(Options.size()), on_change_action(f)
 { defaultValue = currentValue = (v ? "true" : "false"); }
 
-UCIOption::UCIOption(int v, int minv, int maxv) : type("spin"), min(minv), max(maxv), idx(Options.size())
+UCIOption::UCIOption(int v, int minv, int maxv, Fn* f) : type("spin"), min(minv), max(maxv), idx(Options.size()), on_change_action(f)
 { std::ostringstream ss; ss << v; defaultValue = currentValue = ss.str(); }
 
 
@@ -122,7 +129,12 @@ void UCIOption::operator=(const string& v) {
   assert(!type.empty());
 
   if (   !v.empty()
-      && (type == "check" || type == "button") == (v == "true" || v == "false")
+      && (type == "check") == (v == "true" || v == "false")
       && (type != "spin" || (atoi(v.c_str()) >= min && atoi(v.c_str()) <= max)))
+  {
       currentValue = v;
+
+      if (on_change_action)
+          (*on_change_action)(*this);
+  }
 }
index f80ff86..8150bb0 100644 (file)
@@ -29,11 +29,14 @@ struct OptionsMap;
 
 /// UCIOption class implements an option as defined by UCI protocol
 class UCIOption {
+
+  typedef void (Fn)(UCIOption&);
+
 public:
   UCIOption() {} // Required by std::map::operator[]
-  UCIOption(const char* v);
-  UCIOption(bool v, std::string type = "check");
-  UCIOption(int v, int min, int max);
+  UCIOption(const char* v, Fn* = NULL);
+  UCIOption(bool v, Fn* = NULL);
+  UCIOption(int v, int min, int max, Fn* = NULL);
 
   void operator=(const std::string& v);
   void operator=(bool v) { *this = std::string(v ? "true" : "false"); }
@@ -54,6 +57,7 @@ private:
   std::string defaultValue, currentValue, type;
   int min, max;
   size_t idx;
+  Fn* on_change_action;
 };