version 1.4.34b
[polyglot.git] / uci.c
diff --git a/uci.c b/uci.c
index 21c36e9..f8537e2 100644 (file)
--- a/uci.c
+++ b/uci.c
@@ -36,7 +36,7 @@ const char * thread_options[]={
   "number of threads",        // toga\r
   "number threads",           // Deep Learning Toga\r
   "threads",                  // glaurung, zappa, cyclone, grapefruit,\r
-                              // Deep Shredder, Deep Junior\r
+                              // Deep Shredder, Deep Junior, bright\r
   "core threads",             // HIARCS\r
   "max cpus",                 // rybka\r
   "cpus",                     // Deep Sjeng, Fruit2.3.5\r
@@ -61,33 +61,21 @@ static int  mate_score     (int dist);
 // uci_set_threads()\r
 \r
 void uci_set_threads(uci_t * uci, int n) {\r
-    const char **thread_options_copy = thread_options;\r
-    const char *thread_option;\r
     ASSERT(n>=1);\r
-    while((thread_option = *(thread_options_copy++))){\r
-        uci_send_option(uci,thread_option,"%d",n); // checks also for existence\r
+    const char *thread_option=uci_thread_option(uci);\r
+    if(thread_option){\r
+        uci_send_option(uci,thread_option,"%d",n);\r
     }\r
 }\r
 \r
-// uci_thread_option_exists()\r
-\r
-bool uci_thread_option_exist(uci_t * uci) {\r
-    const char **thread_options_copy = thread_options;\r
-    const char *thread_option;\r
-    while((thread_option = *(thread_options_copy++))){\r
-        if(uci_option_exist(uci,thread_option)) return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
 \r
 const char * uci_thread_option(uci_t * uci){\r
-    const char **thread_options_copy = thread_options;\r
+    const char **p = thread_options;\r
     const char *thread_option;\r
-    int i;\r
-    while((thread_option = *(thread_options_copy++))){\r
-        i=uci_get_option(uci,thread_option);\r
-        if(i>=0){\r
-            return Uci->option[i].name;\r
+    option_t *opt;\r
+    while((thread_option = *(p++))){\r
+        if((opt=option_find(uci->option,thread_option))){\r
+            return opt->name;\r
             break;\r
         }\r
     }\r
@@ -100,8 +88,7 @@ static bool uci_is_ok(const uci_t * uci) {
 \r
    if (uci == NULL) return FALSE;\r
    if (uci->engine == NULL) return FALSE;\r
-   if (uci->option_nb < 0 || uci->option_nb >= OptionNb) return FALSE;\r
-\r
+   if (!option_is_ok(uci->option)) return FALSE;\r
    return TRUE;\r
 }\r
 \r
@@ -123,7 +110,7 @@ void uci_open(uci_t * uci, engine_t * engine) {
    my_string_set(&uci->name,"<empty>");\r
    uci->author = NULL;\r
    my_string_set(&uci->author,"<empty>");\r
-   uci->option_nb = 0;\r
+   option_init(uci->option);\r
 \r
    uci->ready_nb = 0;\r
    uci->searching = 0;\r
@@ -146,22 +133,13 @@ void uci_open(uci_t * uci, engine_t * engine) {
 \r
 void uci_close(uci_t * uci) {\r
 \r
-   int i;\r
-   option_t * opt;\r
-\r
    ASSERT(uci_is_ok(uci));\r
    engine_close(uci->engine);\r
    uci->engine = NULL;\r
    my_string_clear(&uci->name);\r
    my_string_clear(&uci->author);\r
 \r
-   for (i = 0; i < uci->option_nb; i++) {\r
-      opt = &uci->option[i];\r
-      my_string_clear(&opt->name);\r
-      my_string_clear(&opt->default_);\r
-   }\r
-\r
-   uci->option_nb = 0;\r
+   option_clear(uci->option);\r
 }\r
 \r
 // uci_clear()\r
@@ -267,39 +245,18 @@ void uci_send_ucinewgame(uci_t * uci) {
 \r
    ASSERT(uci!=NULL);\r
 \r
-   if (option_get_int("UCIVersion") >= 2) {\r
+   if (option_get_int(Option,"UCIVersion") >= 2) {\r
       engine_send(uci->engine,"ucinewgame");\r
    }\r
 }\r
 \r
-// uci_option_exist()\r
-\r
-bool uci_option_exist(uci_t * uci, const char option[]) {\r
-\r
-   int i;\r
-   option_t * opt;\r
-\r
-   ASSERT(uci_is_ok(uci));\r
-   ASSERT(option!=NULL);\r
-\r
-   // scan options\r
-\r
-   for (i = 0; i < uci->option_nb; i++) {\r
-      opt = &uci->option[i];\r
-      if (my_string_case_equal(opt->name,option)) return TRUE;\r
-   }\r
-\r
-   return FALSE;\r
-}\r
-\r
 // uci_send_option()\r
 \r
-void uci_send_option(uci_t * uci, const char option[], const char format[], ...) {\r
+bool uci_send_option(uci_t * uci, const char option[], const char format[], ...) {\r
 \r
-   va_list arg_list;\r
-   char value[StringSize];\r
-   int i;\r
+   char value[FormatBufferSize];\r
    option_t * opt;\r
+   bool found=FALSE;\r
 \r
    ASSERT(uci_is_ok(uci));\r
    ASSERT(option!=NULL);\r
@@ -307,24 +264,27 @@ void uci_send_option(uci_t * uci, const char option[], const char format[], ...)
 \r
    // format\r
 \r
-   va_start(arg_list,format);\r
-   vsprintf(value,format,arg_list);\r
-   va_end(arg_list);\r
+   CONSTRUCT_ARG_STRING(format,value);\r
 \r
    if (UseDebug) my_log("POLYGLOT OPTION %s VALUE %s\n",option,value);\r
 \r
-   // scan options\r
-\r
-   for (i = 0; i < uci->option_nb; i++) {\r
-\r
-      opt = &uci->option[i];\r
-\r
-      if (my_string_case_equal(opt->name,option) && !my_string_equal(opt->default_,value)) {\r
-         engine_send(uci->engine,"setoption name %s value %s",opt->name,value);\r
-         my_string_set(&opt->default_,value);\r
-         break;\r
-      }\r
+   opt=option_find(uci->option,option);\r
+   if(opt){\r
+       found=TRUE;\r
+       if(!my_string_case_equal(opt->type,"button")){\r
+           if(!my_string_equal(opt->value,value)){\r
+               engine_send(uci->engine,"setoption name %s value %s",\r
+                           opt->name,value);\r
+               my_string_set(&opt->value,value);\r
+           }else{\r
+               my_log("POLYGLOT Not sending option \"%s\" since it "\r
+                      "already has the correct value.\n",opt->name);\r
+           }\r
+       }else{\r
+           engine_send(uci->engine,"setoption name %s",opt->name);\r
+       }\r
    }\r
+   return found;\r
 }\r
 \r
 // uci_parse()\r
@@ -387,9 +347,9 @@ int uci_parse(uci_t * uci, const char string[]) {
 \r
          // search information\r
 \r
-         if (uci->searching && uci->pending_nb == 1) { // current search\r
-            event = parse_info(uci,argument);\r
-         }\r
+              if (uci->searching && uci->pending_nb == 1) { // current search\r
+                  event = parse_info(uci,argument);\r
+               }\r
 \r
       } else if (my_string_equal(command,"option")) {\r
 \r
@@ -444,12 +404,19 @@ static int parse_bestmove(uci_t * uci, const char string[]) {
    // bestmove\r
 \r
    if (!parse_get_string(parse,argument,StringSize)) {\r
-      my_fatal("parse_bestmove(): missing argument\n");\r
+       return EVENT_ILLEGAL_MOVE;\r
+//      my_fatal("parse_bestmove(): missing argument\n");\r
    }\r
 \r
    uci->best_move = move_from_can(argument,uci->board);\r
-   if (uci->best_move == MoveNone) my_fatal("parse_bestmove(): not a move \"%s\"\n",argument);\r
+   if (uci->best_move == MoveNone) {\r
+       return EVENT_ILLEGAL_MOVE;\r
+//       my_fatal("parse_bestmove(): not a move \"%s\"\n",argument);\r
+   }\r
 \r
+   if(!move_is_legal(uci->best_move,uci->board)){\r
+       return EVENT_ILLEGAL_MOVE;\r
+   }\r
    ASSERT(uci->best_move!=MoveNone);\r
    ASSERT(move_is_legal(uci->best_move,uci->board));\r
 \r
@@ -544,6 +511,8 @@ static int parse_info(uci_t * uci, const char string[]) {
    int multipvline=0;\r
    sint64 ln;\r
 \r
+\r
+   \r
    ASSERT(uci_is_ok(uci));\r
    ASSERT(string!=NULL);\r
 \r
@@ -691,12 +660,15 @@ static int parse_info(uci_t * uci, const char string[]) {
 \r
          if (n >= 0) uci->sel_depth = n;\r
 \r
-      } else if (my_string_equal(option,"string")) {\r
-                 if(!strncmp(argument,"DrawOffer",9))\r
+      } else  if (my_string_equal(option,"string")) {\r
+                 if(my_string_case_equal(argument,"DrawOffer")){\r
                          event |= EVENT_DRAW;\r
-                 if(!strncmp(argument,"Resign",6))\r
+          }else if(my_string_case_equal(argument,"Resign")){\r
                          event |= EVENT_RESIGN;\r
-\r
+          }else{\r
+              strcpy(uci->info,argument);\r
+              event|=EVENT_INFO;\r
+          }\r
          // TODO: argument to EOS\r
 \r
          ASSERT(!my_string_empty(argument));\r
@@ -720,6 +692,12 @@ 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
+             // by a "WorkAround" option.\r
+         strcpy(uci->info,option);\r
+         strcat(uci->info," ");\r
+         strcat(uci->info,argument);\r
+         event|=EVENT_INFO;\r
       }\r
    }\r
 \r
@@ -738,55 +716,11 @@ static int parse_info(uci_t * uci, const char string[]) {
    return event;\r
 }\r
 \r
-int uci_get_option(uci_t * uci, const char * name){\r
-    int i;\r
-    for(i=0;i<Uci->option_nb;i++){\r
-        if(my_string_case_equal(Uci->option[i].name,name)){\r
-            return i;\r
-        }\r
-    }\r
-    return -1;\r
-}\r
-\r
-\r
-\r
-// uci_set_option()\r
-\r
-void uci_set_option(uci_t * uci,\r
-                    const char * name,\r
-                    const char * default_,\r
-                    const char * type,\r
-                    const char * max,\r
-                    const char * min,\r
-                    int var_nb,\r
-                    const char * var[]){\r
-    int i,j;\r
-    for(i=0;i<Uci->option_nb;i++){\r
-        if(my_string_equal(Uci->option[i].name,name)){\r
-            break;\r
-       }\r
-   }\r
-   if(i<OptionNb){\r
-       my_string_set(&(Uci->option[i].name),name);\r
-       my_string_set(&(Uci->option[i].default_),default_);\r
-       my_string_set(&(Uci->option[i].type),type);\r
-       my_string_set(&(Uci->option[i].min),min);\r
-       my_string_set(&(Uci->option[i].max),max);\r
-       Uci->option[i].var_nb=var_nb;\r
-       for(j=0;j<var_nb;j++){\r
-           my_string_set(&(Uci->option[i].var[j]),var[j]);\r
-       }\r
-       if(i==Uci->option_nb){\r
-           Uci->option_nb++;\r
-       }\r
-   }\r
-}\r
-\r
 // parse_option()\r
 \r
 static void parse_option(uci_t * uci, const char string[]) {\r
 \r
-   option_t * opt;\r
+   option_t opt[1];\r
    parse_t parse[1];\r
    char command[StringSize];\r
    char option[StringSize];\r
@@ -799,32 +733,16 @@ static void parse_option(uci_t * uci, const char string[]) {
 \r
    strcpy(command,"option");\r
 \r
-   if (uci->option_nb >= OptionNb) return;\r
-\r
-   opt = &uci->option[uci->option_nb];\r
-   uci->option_nb++;\r
-\r
-   opt->value=NULL;\r
+   memset(opt,0,sizeof(option_t));\r
+   \r
    my_string_set(&opt->value,"<empty>");\r
-   opt->mode=0;\r
-\r
-   opt->name = NULL;\r
    my_string_set(&opt->name,"<empty>");\r
-\r
-   \r
-   opt->default_ = NULL;\r
    my_string_set(&opt->default_,"<empty>");\r
-\r
-   opt->max = NULL;\r
    my_string_set(&opt->max,"<empty>");\r
-\r
-   opt->min = NULL;\r
    my_string_set(&opt->min,"<empty>");\r
-\r
-   opt->type = NULL;\r
    my_string_set(&opt->type,"<empty>");\r
-\r
    opt->var_nb=0;\r
+   opt->mode=0;\r
    \r
    parse_open(parse,string);\r
    parse_add_keyword(parse,"default");\r
@@ -887,6 +805,8 @@ static void parse_option(uci_t * uci, const char string[]) {
    }\r
 \r
    parse_close(parse);\r
+   option_insert(uci->option,opt);\r
+   option_free(opt);\r
 \r
    if (UseDebug) my_log("POLYGLOT option name \"%s\" default \"%s\"\n",opt->name,opt->default_);\r
 }\r
@@ -966,9 +886,9 @@ static int mate_score(int dist) {
 \r
    if (FALSE) {\r
    } else if (dist > 0) {\r
-      return +option_get_int("MateScore") - (+dist) * 2 + 1;\r
+       return +option_get_int(Option,"MateScore") - (+dist) * 2 + 1;\r
    } else if (dist < 0) {\r
-      return -option_get_int("MateScore") + (-dist) * 2;\r
+       return -option_get_int(Option,"MateScore") + (-dist) * 2;\r
    }\r
 \r
    return 0;\r