version 1.4.30b
[polyglot.git] / uci.c
diff --git a/uci.c b/uci.c
new file mode 100644 (file)
index 0000000..21c36e9
--- /dev/null
+++ b/uci.c
@@ -0,0 +1,978 @@
+\r
+// uci.c\r
+\r
+// includes\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "board.h"\r
+#include "engine.h"\r
+#include "move.h"\r
+#include "move_do.h"\r
+#include "move_legal.h"\r
+#include "option.h"\r
+#include "parse.h"\r
+#include "line.h"\r
+#include "uci.h"\r
+\r
+// constants\r
+\r
+static const bool UseDebug = FALSE;\r
+\r
+static const int StringSize = 4096;\r
+\r
+// variables\r
+\r
+uci_t Uci[1];\r
+\r
+// Hopefully the following confusion is temporary\r
+// Normally we should check for the engine name but this is a hack anyway\r
+// Some of there where provided by Marc Lacrosse\r
+\r
+const char * thread_options[]={\r
+  "number of threads",        // toga\r
+  "number threads",           // Deep Learning Toga\r
+  "threads",                  // glaurung, zappa, cyclone, grapefruit,\r
+                              // Deep Shredder, Deep Junior\r
+  "core threads",             // HIARCS\r
+  "max cpus",                 // rybka\r
+  "cpus",                     // Deep Sjeng, Fruit2.3.5\r
+  "maxthreads",               // Naum \r
+  NULL\r
+};\r
+\r
+// prototypes\r
+\r
+static bool uci_is_ok      (const uci_t * uci);\r
+\r
+static int  parse_bestmove (uci_t * uci, const char string[]);\r
+static void parse_id       (uci_t * uci, const char string[]);\r
+static int  parse_info     (uci_t * uci, const char string[]);\r
+static void parse_option   (uci_t * uci, const char string[]);\r
+static void parse_score    (uci_t * uci, const char string[]);\r
+\r
+static int  mate_score     (int dist);\r
+\r
+// functions\r
+\r
+// 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
+    }\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 *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
+            break;\r
+        }\r
+    }\r
+    return NULL;\r
+}\r
+\r
+// uci_is_ok()\r
+\r
+static bool uci_is_ok(const uci_t * uci) {\r
+\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
+   return TRUE;\r
+}\r
+\r
+// uci_open()\r
+\r
+void uci_open(uci_t * uci, engine_t * engine) {\r
+\r
+   char string[StringSize];\r
+   int event;\r
+\r
+   ASSERT(uci!=NULL);\r
+   ASSERT(engine!=NULL);\r
+\r
+   // init\r
+\r
+   uci->engine = engine;\r
+\r
+   uci->name = NULL;\r
+   my_string_set(&uci->name,"<empty>");\r
+   uci->author = NULL;\r
+   my_string_set(&uci->author,"<empty>");\r
+   uci->option_nb = 0;\r
+\r
+   uci->ready_nb = 0;\r
+   uci->searching = 0;\r
+   uci->pending_nb = 0;\r
+   uci->multipv_mode = FALSE;\r
+   board_start(uci->board);\r
+   uci_clear(uci);\r
+\r
+   // send "uci" and wait for "uciok"\r
+\r
+   engine_send(uci->engine,"uci");\r
+\r
+   do {\r
+      engine_get(uci->engine,string);\r
+      event = uci_parse(uci,string);\r
+   } while (!engine_eof(Engine) && (event & EVENT_UCI) == 0);\r
+}\r
+\r
+// uci_close()\r
+\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
+}\r
+\r
+// uci_clear()\r
+\r
+void uci_clear(uci_t * uci) {\r
+\r
+   ASSERT(uci_is_ok(uci));\r
+\r
+   ASSERT(!uci->searching);\r
+\r
+   uci->best_move = MoveNone;\r
+   uci->ponder_move = MoveNone;\r
+\r
+   uci->score = 0;\r
+   uci->depth = 0;\r
+   uci->sel_depth = 0;\r
+   line_clear(uci->pv);\r
+\r
+   uci->best_score = 0;\r
+   uci->best_depth = 0;\r
+   uci->best_sel_depth = 0;\r
+   line_clear(uci->best_pv);\r
+\r
+   uci->node_nb = 0;\r
+   uci->time = 0.0;\r
+   uci->speed = 0.0;\r
+   uci->cpu = 0.0;\r
+   uci->hash = 0.0;\r
+   line_clear(uci->current_line);\r
+\r
+   uci->root_move = MoveNone;\r
+   uci->root_move_pos = 0;\r
+   uci->root_move_nb = board_mobility(uci->board);\r
+}\r
+\r
+// uci_send_isready()\r
+\r
+void uci_send_isready(uci_t * uci) {\r
+\r
+   ASSERT(uci!=NULL);\r
+\r
+   engine_send(uci->engine,"isready");\r
+   uci->ready_nb++;\r
+}\r
+\r
+// uci_send_isready_sync()\r
+\r
+void uci_send_isready_sync(uci_t * uci) {\r
+\r
+   char string[StringSize];\r
+   int event;\r
+\r
+   ASSERT(uci_is_ok(uci));\r
+\r
+   // send "isready" and wait for "readyok"\r
+\r
+   uci_send_isready(uci);\r
+\r
+   do {\r
+      engine_get(uci->engine,string);\r
+      event = uci_parse(uci,string);\r
+   } while (!engine_eof(Engine) && (event & EVENT_READY) == 0);\r
+}\r
+\r
+// uci_send_stop()\r
+\r
+void uci_send_stop(uci_t * uci) {\r
+\r
+   ASSERT(uci_is_ok(uci));\r
+\r
+   ASSERT(uci->searching);\r
+   ASSERT(uci->pending_nb>=1);\r
+\r
+   engine_send(Engine,"stop");\r
+   uci->searching = FALSE;\r
+}\r
+\r
+// uci_send_stop_sync()\r
+\r
+void uci_send_stop_sync(uci_t * uci) {\r
+\r
+   char string[StringSize];\r
+   int event;\r
+\r
+   ASSERT(uci_is_ok(uci));\r
+\r
+   ASSERT(uci->searching);\r
+   ASSERT(uci->pending_nb>=1);\r
+\r
+   // send "stop" and wait for "bestmove"\r
+\r
+   uci_send_stop(uci);\r
+\r
+   do {\r
+      engine_get(uci->engine,string);\r
+      event = uci_parse(uci,string);\r
+   } while (!engine_eof(Engine) && (event & EVENT_STOP) == 0);\r
+}\r
+\r
+// uci_send_ucinewgame()\r
+\r
+void uci_send_ucinewgame(uci_t * uci) {\r
+\r
+   ASSERT(uci!=NULL);\r
+\r
+   if (option_get_int("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
+\r
+   va_list arg_list;\r
+   char value[StringSize];\r
+   int i;\r
+   option_t * opt;\r
+\r
+   ASSERT(uci_is_ok(uci));\r
+   ASSERT(option!=NULL);\r
+   ASSERT(format!=NULL);\r
+\r
+   // format\r
+\r
+   va_start(arg_list,format);\r
+   vsprintf(value,format,arg_list);\r
+   va_end(arg_list);\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
+   }\r
+}\r
+\r
+// uci_parse()\r
+\r
+int uci_parse(uci_t * uci, const char string[]) {\r
+\r
+   int event;\r
+   parse_t parse[1];\r
+   char command[StringSize];\r
+   char argument[StringSize];\r
+\r
+   ASSERT(uci_is_ok(uci));\r
+   ASSERT(string!=NULL);\r
+\r
+   // init\r
+\r
+   event = EVENT_NONE;\r
+\r
+   // parse\r
+\r
+   parse_open(parse,string);\r
+\r
+   if (parse_get_word(parse,command,StringSize)) {\r
+\r
+      parse_get_string(parse,argument,StringSize);\r
+      if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" ARGUMENT \"%s\"\n",command,argument);\r
+\r
+      if (FALSE) {\r
+\r
+      } else if (my_string_equal(command,"bestmove")) {\r
+\r
+         // search end\r
+\r
+         ASSERT(uci->pending_nb>0);\r
+\r
+         if (uci->searching && uci->pending_nb == 1) {\r
+\r
+            // current search\r
+\r
+            uci->searching = FALSE;\r
+            uci->pending_nb--;\r
+\r
+            event = parse_bestmove(uci,argument); // updates uci->best_move and uci->ponder_move\r
+\r
+         } else {\r
+\r
+            // obsolete search\r
+\r
+            if (uci->pending_nb > 0) {\r
+               uci->pending_nb--;\r
+               if (uci->pending_nb == 0) event = EVENT_STOP;\r
+            }\r
+         }\r
+\r
+      } else if (my_string_equal(command,"id")) {\r
+\r
+         parse_id(uci,argument);\r
+\r
+      } else if (my_string_equal(command,"info")) {\r
+\r
+         // search information\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
+         parse_option(uci,argument);\r
+\r
+      } else if (my_string_equal(command,"readyok")) {\r
+\r
+         // engine is ready\r
+\r
+         ASSERT(uci->ready_nb>0);\r
+\r
+         if (uci->ready_nb > 0) {\r
+            uci->ready_nb--;\r
+            if (uci->ready_nb == 0) event = EVENT_READY;\r
+         }\r
+\r
+      } else if (my_string_equal(command,"uciok")) {\r
+\r
+         event = EVENT_UCI;\r
+\r
+      } else {\r
+\r
+         if (UseDebug) my_log("POLYGLOT unknown command \"%s\"\n",command);\r
+      }\r
+   }\r
+\r
+   parse_close(parse);\r
+\r
+   return event;\r
+}\r
+\r
+// parse_bestmove()\r
+\r
+static int parse_bestmove(uci_t * uci, const char string[]) {\r
+\r
+   parse_t parse[1];\r
+   char command[StringSize];\r
+   char option[StringSize];\r
+   char argument[StringSize];\r
+   board_t board[1];\r
+\r
+   ASSERT(uci_is_ok(uci));\r
+   ASSERT(string!=NULL);\r
+\r
+   // init\r
+\r
+   strcpy(command,"bestmove");\r
+\r
+   parse_open(parse,string);\r
+   parse_add_keyword(parse,"ponder");\r
+\r
+   // bestmove\r
+\r
+   if (!parse_get_string(parse,argument,StringSize)) {\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
+\r
+   ASSERT(uci->best_move!=MoveNone);\r
+   ASSERT(move_is_legal(uci->best_move,uci->board));\r
+\r
+   // loop\r
+\r
+   while (parse_get_word(parse,option,StringSize)) {\r
+\r
+      parse_get_string(parse,argument,StringSize);\r
+\r
+      if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
+\r
+      if (FALSE) {\r
+\r
+      } else if (my_string_equal(option,"ponder")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         board_copy(board,uci->board);\r
+         move_do(board,uci->best_move);\r
+\r
+         uci->ponder_move = move_from_can(argument,board);\r
+         // if (uci->ponder_move == MoveNone) my_fatal("parse_bestmove(): not a move \"%s\"\n",argument);\r
+\r
+         ASSERT(uci->ponder_move!=MoveNone);\r
+         ASSERT(move_is_legal(uci->ponder_move,board));\r
+\r
+      } else {\r
+\r
+         my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
+      }\r
+   }\r
+\r
+   parse_close(parse);\r
+\r
+   return EVENT_MOVE;\r
+}\r
+\r
+// parse_id()\r
+\r
+static void parse_id(uci_t * uci, const char string[]) {\r
+\r
+   parse_t parse[1];\r
+   char command[StringSize];\r
+   char option[StringSize];\r
+   char argument[StringSize];\r
+\r
+   ASSERT(uci!=NULL);\r
+   ASSERT(string!=NULL);\r
+\r
+   // init\r
+\r
+   strcpy(command,"id");\r
+\r
+   parse_open(parse,string);\r
+   parse_add_keyword(parse,"author");\r
+   parse_add_keyword(parse,"name");\r
+\r
+   // loop\r
+\r
+   while (parse_get_word(parse,option,StringSize)) {\r
+\r
+      parse_get_string(parse,argument,StringSize);\r
+      if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
+\r
+      if (FALSE) {\r
+      } else if (my_string_equal(option,"author")) {\r
+         ASSERT(!my_string_empty(argument));\r
+         my_string_set(&uci->author,argument);\r
+      } else if (my_string_equal(option,"name")) {\r
+         ASSERT(!my_string_empty(argument));\r
+         my_string_set(&uci->name,argument);\r
+      } else {\r
+         my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
+      }\r
+   }\r
+\r
+   parse_close(parse);\r
+\r
+   if (UseDebug) my_log("POLYGLOT engine name \"%s\" author \"%s\"\n",uci->name,uci->author);\r
+}\r
+\r
+// parse_info()\r
+\r
+static int parse_info(uci_t * uci, const char string[]) {\r
+\r
+   int event;\r
+   parse_t parse[1];\r
+   char command[StringSize];\r
+   char option[StringSize];\r
+   char argument[StringSize];\r
+   int n;\r
+   int multipvline=0;\r
+   sint64 ln;\r
+\r
+   ASSERT(uci_is_ok(uci));\r
+   ASSERT(string!=NULL);\r
+\r
+   // init\r
+\r
+   event = EVENT_NONE;\r
+\r
+   strcpy(command,"info");\r
+\r
+   parse_open(parse,string);\r
+   parse_add_keyword(parse,"cpuload");\r
+   parse_add_keyword(parse,"currline");\r
+   parse_add_keyword(parse,"currmove");\r
+   parse_add_keyword(parse,"currmovenumber");\r
+   parse_add_keyword(parse,"depth");\r
+   parse_add_keyword(parse,"hashfull");\r
+   parse_add_keyword(parse,"multipv");\r
+   parse_add_keyword(parse,"nodes");\r
+   parse_add_keyword(parse,"nps");\r
+   parse_add_keyword(parse,"pv");\r
+   parse_add_keyword(parse,"refutation");\r
+   parse_add_keyword(parse,"score");\r
+   parse_add_keyword(parse,"seldepth");\r
+   parse_add_keyword(parse,"string");\r
+   parse_add_keyword(parse,"tbhits");\r
+   parse_add_keyword(parse,"time");\r
+\r
+   // loop\r
+\r
+   while (parse_get_word(parse,option,StringSize)) {\r
+\r
+      parse_get_string(parse,argument,StringSize);\r
+\r
+      if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
+\r
+      if (FALSE) {\r
+\r
+      } else if (my_string_equal(option,"cpuload")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         n = atoi(argument);\r
+         ASSERT(n>=0);\r
+\r
+         if (n >= 0) uci->cpu = ((double)n) / 1000.0;\r
+\r
+      } else if (my_string_equal(option,"currline")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         line_from_can(uci->current_line,uci->board,argument,LineSize);\r
+\r
+      } else if (my_string_equal(option,"currmove")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         uci->root_move = move_from_can(argument,uci->board);\r
+         ASSERT(uci->root_move!=MoveNone);\r
+\r
+      } else if (my_string_equal(option,"currmovenumber")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         n = atoi(argument);\r
+         ASSERT(n>=1&&n<=uci->root_move_nb);\r
+\r
+         if (n >= 1 && n <= uci->root_move_nb) {\r
+            uci->root_move_pos = n - 1;\r
+            ASSERT(uci->root_move_pos>=0&&uci->root_move_pos<uci->root_move_nb);\r
+         }\r
+\r
+      } else if (my_string_equal(option,"depth")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         n = atoi(argument);\r
+         ASSERT(n>=1);\r
+\r
+         if (n >= 0) {\r
+            if (n > uci->depth) event |= EVENT_DEPTH;\r
+            uci->depth = n;\r
+         }\r
+\r
+      } else if (my_string_equal(option,"hashfull")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         n = atoi(argument);\r
+         ASSERT(n>=0);\r
+\r
+         if (n >= 0) uci->hash = ((double)n) / 1000.0;\r
+\r
+      } else if (my_string_equal(option,"multipv")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         n = atoi(argument);\r
+                if(Uci->multipv_mode) multipvline=n;\r
+        \r
+         ASSERT(n>=1);\r
+\r
+      } else if (my_string_equal(option,"nodes")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         ln = my_atoll(argument);\r
+         ASSERT(ln>=0);\r
+\r
+         if (ln >= 0) uci->node_nb = ln;\r
+\r
+      } else if (my_string_equal(option,"nps")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         n = atoi(argument);\r
+         ASSERT(n>=0);\r
+\r
+         if (n >= 0) uci->speed = ((double)n);\r
+\r
+      } else if (my_string_equal(option,"pv")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         line_from_can(uci->pv,uci->board,argument,LineSize);\r
+         event |= EVENT_PV;\r
+\r
+      } else if (my_string_equal(option,"refutation")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         line_from_can(uci->pv,uci->board,argument,LineSize);\r
+\r
+      } else if (my_string_equal(option,"score")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         parse_score(uci,argument);\r
+\r
+      } else if (my_string_equal(option,"seldepth")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         n = atoi(argument);\r
+         ASSERT(n>=0);\r
+\r
+         if (n >= 0) uci->sel_depth = n;\r
+\r
+      } else if (my_string_equal(option,"string")) {\r
+                 if(!strncmp(argument,"DrawOffer",9))\r
+                         event |= EVENT_DRAW;\r
+                 if(!strncmp(argument,"Resign",6))\r
+                         event |= EVENT_RESIGN;\r
+\r
+         // TODO: argument to EOS\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+      } else if (my_string_equal(option,"tbhits")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         ln = my_atoll(argument);\r
+         ASSERT(ln>=0);\r
+\r
+      } else if (my_string_equal(option,"time")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         n = atoi(argument);\r
+         ASSERT(n>=0);\r
+\r
+         if (n >= 0) uci->time = ((double)n) / 1000.0;\r
+\r
+      } else {\r
+\r
+         my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\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
+   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
+   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
+   parse_t parse[1];\r
+   char command[StringSize];\r
+   char option[StringSize];\r
+   char argument[StringSize];\r
+\r
+   ASSERT(uci!=NULL);\r
+   ASSERT(string!=NULL);\r
+\r
+   // init\r
+\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
+   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
+   \r
+   parse_open(parse,string);\r
+   parse_add_keyword(parse,"default");\r
+   parse_add_keyword(parse,"max");\r
+   parse_add_keyword(parse,"min");\r
+   parse_add_keyword(parse,"name");\r
+   parse_add_keyword(parse,"type");\r
+   parse_add_keyword(parse,"var");\r
+\r
+   // loop\r
+\r
+   while (parse_get_word(parse,option,StringSize)) {\r
+      parse_get_string(parse,argument,StringSize);\r
+      if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
+\r
+      if (FALSE) {\r
+\r
+      } else if (my_string_equal(option,"default")) {\r
+\r
+         // ASSERT(!my_string_empty(argument)); // HACK for Pepito\r
+\r
+         if (!my_string_empty(argument)) {\r
+            my_string_set(&opt->default_,argument);\r
+            my_string_set(&opt->value,argument);\r
+         }\r
+\r
+      } else if (my_string_equal(option,"max")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+         my_string_set(&opt->max,argument);\r
+\r
+      } else if (my_string_equal(option,"min")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+         my_string_set(&opt->min,argument);\r
+\r
+      } else if (my_string_equal(option,"name")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         if (!my_string_empty(argument)) {\r
+            my_string_set(&opt->name,argument);\r
+         }\r
+\r
+      } else if (my_string_equal(option,"type")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+         my_string_set(&opt->type,argument);\r
+\r
+      } else if (my_string_equal(option,"var")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+         my_string_set(&opt->var[opt->var_nb++],argument);\r
+         if(opt->var_nb==VarNb) break;\r
+\r
+      } else {\r
+\r
+         my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
+      }\r
+   }\r
+\r
+   parse_close(parse);\r
+\r
+   if (UseDebug) my_log("POLYGLOT option name \"%s\" default \"%s\"\n",opt->name,opt->default_);\r
+}\r
+\r
+// parse_score()\r
+\r
+static void parse_score(uci_t * uci, const char string[]) {\r
+\r
+   parse_t parse[1];\r
+   char command[StringSize];\r
+   char option[StringSize];\r
+   char argument[StringSize];\r
+   int n;\r
+\r
+   ASSERT(uci_is_ok(uci));\r
+   ASSERT(string!=NULL);\r
+\r
+   // init\r
+\r
+   strcpy(command,"score");\r
+\r
+   parse_open(parse,string);\r
+   parse_add_keyword(parse,"cp");\r
+   parse_add_keyword(parse,"lowerbound");\r
+   parse_add_keyword(parse,"mate");\r
+   parse_add_keyword(parse,"upperbound");\r
+\r
+   // loop\r
+\r
+   while (parse_get_word(parse,option,StringSize)) {\r
+\r
+      parse_get_string(parse,argument,StringSize);\r
+\r
+      if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
+\r
+      if (FALSE) {\r
+\r
+      } else if (my_string_equal(option,"cp")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         n = atoi(argument);\r
+\r
+         uci->score = n;\r
+\r
+      } else if (my_string_equal(option,"lowerbound")) {\r
+\r
+         ASSERT(my_string_empty(argument));\r
+\r
+      } else if (my_string_equal(option,"mate")) {\r
+\r
+         ASSERT(!my_string_empty(argument));\r
+\r
+         n = atoi(argument);\r
+         ASSERT(n!=0);\r
+\r
+         uci->score = mate_score(n);\r
+\r
+      } else if (my_string_equal(option,"upperbound")) {\r
+\r
+         ASSERT(my_string_empty(argument));\r
+\r
+      } else {\r
+\r
+         my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
+      }\r
+   }\r
+\r
+   parse_close(parse);\r
+}\r
+\r
+// mate_score()\r
+\r
+static int mate_score(int dist) {\r
+\r
+   ASSERT(dist!=0);\r
+\r
+   if (FALSE) {\r
+   } else if (dist > 0) {\r
+      return +option_get_int("MateScore") - (+dist) * 2 + 1;\r
+   } else if (dist < 0) {\r
+      return -option_get_int("MateScore") + (-dist) * 2;\r
+   }\r
+\r
+   return 0;\r
+}\r
+\r
+// end of uci.cpp\r
+\r