version 1.4.56b
[polyglot.git] / uci.c
diff --git a/uci.c b/uci.c
index f8537e2..65d4d2a 100644 (file)
--- a/uci.c
+++ b/uci.c
@@ -10,6 +10,7 @@
 \r
 #include "board.h"\r
 #include "engine.h"\r
+#include "gui.h"\r
 #include "move.h"\r
 #include "move_do.h"\r
 #include "move_legal.h"\r
 #include "line.h"\r
 #include "uci.h"\r
 \r
+\r
 // constants\r
 \r
 static const bool UseDebug = FALSE;\r
 \r
-static const int StringSize = 4096;\r
+#define StringSize ((int)4096)\r
 \r
 // variables\r
 \r
@@ -58,11 +60,34 @@ static int  mate_score     (int dist);
 \r
 // functions\r
 \r
+\r
+// uci_adapt_UCI3()\r
+\r
+static void apply_UCI3_heuristics(option_t *opt){\r
+  if(option_get_int(Option,"UCIVersion")>2){\r
+    return;\r
+  }\r
+  if(!my_string_equal(opt->type,"string")){\r
+    return;\r
+  }\r
+  if(!strncmp(opt->name,"UCI_",4)){\r
+    return;\r
+  }\r
+  if(my_string_case_contains(opt->name,"file")){\r
+    my_string_set(&opt->type,"file");\r
+    return;\r
+  }\r
+  if(my_string_case_contains(opt->name,"path")){\r
+    my_string_set(&opt->type,"path");\r
+    return;\r
+  }\r
+}\r
+\r
 // uci_set_threads()\r
 \r
 void uci_set_threads(uci_t * uci, int n) {\r
-    ASSERT(n>=1);\r
     const char *thread_option=uci_thread_option(uci);\r
+    ASSERT(n>=1);\r
     if(thread_option){\r
         uci_send_option(uci,thread_option,"%d",n);\r
     }\r
@@ -125,6 +150,11 @@ void uci_open(uci_t * uci, engine_t * engine) {
 \r
    do {\r
       engine_get(uci->engine,string);\r
+      // Handle the case that the engine is really a WB engine somewhat gracefully.\r
+      if((strstr(string,"Illegal") || strstr(string,"Error"))\r
+         &&strstr(string,"uci")){\r
+          my_fatal("uci_open(): Not an UCI engine.\n");\r
+      }\r
       event = uci_parse(uci,string);\r
    } while (!engine_eof(Engine) && (event & EVENT_UCI) == 0);\r
 }\r
@@ -162,8 +192,8 @@ void uci_clear(uci_t * uci) {
    uci->best_depth = 0;\r
    uci->best_sel_depth = 0;\r
    line_clear(uci->best_pv);\r
-\r
-   uci->node_nb = 0;\r
+// make the default 1 instead of 0 so that info lines can be recognized by their node number 0\r
+   uci->node_nb = 1;\r
    uci->time = 0.0;\r
    uci->speed = 0.0;\r
    uci->cpu = 0.0;\r
@@ -173,6 +203,8 @@ void uci_clear(uci_t * uci) {
    uci->root_move = MoveNone;\r
    uci->root_move_pos = 0;\r
    uci->root_move_nb = board_mobility(uci->board);\r
+\r
+   uci->multipvSP=0;\r
 }\r
 \r
 // uci_send_isready()\r
@@ -271,7 +303,7 @@ bool uci_send_option(uci_t * uci, const char option[], const char format[], ...)
    opt=option_find(uci->option,option);\r
    if(opt){\r
        found=TRUE;\r
-       if(!my_string_case_equal(opt->type,"button")){\r
+       if(!IS_BUTTON(opt->type)){\r
            if(!my_string_equal(opt->value,value)){\r
                engine_send(uci->engine,"setoption name %s value %s",\r
                            opt->name,value);\r
@@ -308,7 +340,7 @@ int uci_parse(uci_t * uci, const char string[]) {
    parse_open(parse,string);\r
 \r
    if (parse_get_word(parse,command,StringSize)) {\r
-\r
+       \r
       parse_get_string(parse,argument,StringSize);\r
       if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" ARGUMENT \"%s\"\n",command,argument);\r
 \r
@@ -610,7 +642,7 @@ static int parse_info(uci_t * uci, const char string[]) {
          ASSERT(!my_string_empty(argument));\r
 \r
          n = atoi(argument);\r
-                if(Uci->multipv_mode) multipvline=n;\r
+        multipvline=n;\r
         \r
          ASSERT(n>=1);\r
 \r
@@ -666,7 +698,8 @@ static int parse_info(uci_t * uci, const char string[]) {
           }else if(my_string_case_equal(argument,"Resign")){\r
                          event |= EVENT_RESIGN;\r
           }else{\r
-              strcpy(uci->info,argument);\r
+              snprintf(uci->info,sizeof(uci->info),"%s",argument);\r
+              uci->info[sizeof(uci->info)-1]='\0';\r
               event|=EVENT_INFO;\r
           }\r
          // TODO: argument to EOS\r
@@ -692,27 +725,53 @@ static int parse_info(uci_t * uci, const char string[]) {
       } else {\r
 \r
          my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
-             // this is for buggy engines; it should probably be protected\r
+             // This should probably be protected\r
              // by a "WorkAround" option.\r
-         strcpy(uci->info,option);\r
-         strcat(uci->info," ");\r
-         strcat(uci->info,argument);\r
+         snprintf(uci->info,sizeof(uci->info),"%s %s",option,argument);\r
+         uci->info[sizeof(uci->info)-1]='\0';\r
          event|=EVENT_INFO;\r
       }\r
    }\r
 \r
    parse_close(parse);\r
 \r
-   // update display\r
-   //lousy uci,filter out lower depth multipv lines that have been repeated from the engine \r
-   if(multipvline>1 && uci->depth<uci->best_depth) event &= ~EVENT_PV;\r
+\r
+   // code by HGM\r
    if ((event & EVENT_PV) != 0) {\r
       uci->best_score = uci->score; \r
-         uci->best_depth = uci->depth;\r
-         if(multipvline==1)uci->depth=-1; //HACK ,clears the engine outpout window,see send_pv in adapter.cpp \r
       uci->best_sel_depth = uci->sel_depth;\r
       line_copy(uci->best_pv,uci->pv);\r
    }\r
+   if(uci->depth < uci->best_depth){\r
+     // ignore lines of lower depth\r
+     event &= ~EVENT_PV;\r
+   } else {\r
+     if(uci->depth > uci->best_depth) {\r
+       // clear stack when we start new depth\r
+       uci->multipvSP = 0; \r
+     }\r
+     uci->best_depth = uci->depth;\r
+     if(multipvline >= 1) {\r
+       int i;\r
+       for(i=0; i<uci->multipvSP; i++) {\r
+        if(uci->score == uci->multipvScore[i] && uci->pv[0] == uci->multipvMove[i]) {\r
+          event &= ~EVENT_PV; // ignore duplicates\r
+        }\r
+       }\r
+       if(event & EVENT_PV){\r
+        // line is new, try to add to stack\r
+        if(uci->multipvSP<MultiPVStackSize){\r
+          uci->multipvMove[uci->multipvSP] = uci->pv[0];\r
+          uci->multipvScore[uci->multipvSP] = uci->score;\r
+          uci->multipvSP++;\r
+        }else{\r
+          my_fatal("parse_info(): multipv stack overflow.");\r
+        }\r
+       }\r
+     }\r
+   }\r
+\r
+\r
    return event;\r
 }\r
 \r
@@ -805,6 +864,8 @@ static void parse_option(uci_t * uci, const char string[]) {
    }\r
 \r
    parse_close(parse);\r
+\r
+   apply_UCI3_heuristics(opt);\r
    option_insert(uci->option,opt);\r
    option_free(opt);\r
 \r