version 1.4.35b
[polyglot.git] / uci.c
1 \r
2 // uci.c\r
3 \r
4 // includes\r
5 \r
6 #include <stdarg.h>\r
7 #include <stdio.h>\r
8 #include <stdlib.h>\r
9 #include <string.h>\r
10 \r
11 #include "board.h"\r
12 #include "engine.h"\r
13 #include "move.h"\r
14 #include "move_do.h"\r
15 #include "move_legal.h"\r
16 #include "option.h"\r
17 #include "parse.h"\r
18 #include "line.h"\r
19 #include "uci.h"\r
20 \r
21 // constants\r
22 \r
23 static const bool UseDebug = FALSE;\r
24 \r
25 static const int StringSize = 4096;\r
26 \r
27 // variables\r
28 \r
29 uci_t Uci[1];\r
30 \r
31 // Hopefully the following confusion is temporary\r
32 // Normally we should check for the engine name but this is a hack anyway\r
33 // Some of there where provided by Marc Lacrosse\r
34 \r
35 const char * thread_options[]={\r
36   "number of threads",        // toga\r
37   "number threads",           // Deep Learning Toga\r
38   "threads",                  // glaurung, zappa, cyclone, grapefruit,\r
39                               // Deep Shredder, Deep Junior, bright\r
40   "core threads",             // HIARCS\r
41   "max cpus",                 // rybka\r
42   "cpus",                     // Deep Sjeng, Fruit2.3.5\r
43   "maxthreads",               // Naum \r
44   NULL\r
45 };\r
46 \r
47 // prototypes\r
48 \r
49 static bool uci_is_ok      (const uci_t * uci);\r
50 \r
51 static int  parse_bestmove (uci_t * uci, const char string[]);\r
52 static void parse_id       (uci_t * uci, const char string[]);\r
53 static int  parse_info     (uci_t * uci, const char string[]);\r
54 static void parse_option   (uci_t * uci, const char string[]);\r
55 static void parse_score    (uci_t * uci, const char string[]);\r
56 \r
57 static int  mate_score     (int dist);\r
58 \r
59 // functions\r
60 \r
61 // uci_set_threads()\r
62 \r
63 void uci_set_threads(uci_t * uci, int n) {\r
64     ASSERT(n>=1);\r
65     const char *thread_option=uci_thread_option(uci);\r
66     if(thread_option){\r
67         uci_send_option(uci,thread_option,"%d",n);\r
68     }\r
69 }\r
70 \r
71 \r
72 const char * uci_thread_option(uci_t * uci){\r
73     const char **p = thread_options;\r
74     const char *thread_option;\r
75     option_t *opt;\r
76     while((thread_option = *(p++))){\r
77         if((opt=option_find(uci->option,thread_option))){\r
78             return opt->name;\r
79             break;\r
80         }\r
81     }\r
82     return NULL;\r
83 }\r
84 \r
85 // uci_is_ok()\r
86 \r
87 static bool uci_is_ok(const uci_t * uci) {\r
88 \r
89    if (uci == NULL) return FALSE;\r
90    if (uci->engine == NULL) return FALSE;\r
91    if (!option_is_ok(uci->option)) return FALSE;\r
92    return TRUE;\r
93 }\r
94 \r
95 // uci_open()\r
96 \r
97 void uci_open(uci_t * uci, engine_t * engine) {\r
98 \r
99    char string[StringSize];\r
100    int event;\r
101 \r
102    ASSERT(uci!=NULL);\r
103    ASSERT(engine!=NULL);\r
104 \r
105    // init\r
106 \r
107    uci->engine = engine;\r
108 \r
109    uci->name = NULL;\r
110    my_string_set(&uci->name,"<empty>");\r
111    uci->author = NULL;\r
112    my_string_set(&uci->author,"<empty>");\r
113    option_init(uci->option);\r
114 \r
115    uci->ready_nb = 0;\r
116    uci->searching = 0;\r
117    uci->pending_nb = 0;\r
118    uci->multipv_mode = FALSE;\r
119    board_start(uci->board);\r
120    uci_clear(uci);\r
121 \r
122    // send "uci" and wait for "uciok"\r
123 \r
124    engine_send(uci->engine,"uci");\r
125 \r
126    do {\r
127       engine_get(uci->engine,string);\r
128       event = uci_parse(uci,string);\r
129    } while (!engine_eof(Engine) && (event & EVENT_UCI) == 0);\r
130 }\r
131 \r
132 // uci_close()\r
133 \r
134 void uci_close(uci_t * uci) {\r
135 \r
136    ASSERT(uci_is_ok(uci));\r
137    engine_close(uci->engine);\r
138    uci->engine = NULL;\r
139    my_string_clear(&uci->name);\r
140    my_string_clear(&uci->author);\r
141 \r
142    option_clear(uci->option);\r
143 }\r
144 \r
145 // uci_clear()\r
146 \r
147 void uci_clear(uci_t * uci) {\r
148 \r
149    ASSERT(uci_is_ok(uci));\r
150 \r
151    ASSERT(!uci->searching);\r
152 \r
153    uci->best_move = MoveNone;\r
154    uci->ponder_move = MoveNone;\r
155 \r
156    uci->score = 0;\r
157    uci->depth = 0;\r
158    uci->sel_depth = 0;\r
159    line_clear(uci->pv);\r
160 \r
161    uci->best_score = 0;\r
162    uci->best_depth = 0;\r
163    uci->best_sel_depth = 0;\r
164    line_clear(uci->best_pv);\r
165 \r
166    uci->node_nb = 0;\r
167    uci->time = 0.0;\r
168    uci->speed = 0.0;\r
169    uci->cpu = 0.0;\r
170    uci->hash = 0.0;\r
171    line_clear(uci->current_line);\r
172 \r
173    uci->root_move = MoveNone;\r
174    uci->root_move_pos = 0;\r
175    uci->root_move_nb = board_mobility(uci->board);\r
176 }\r
177 \r
178 // uci_send_isready()\r
179 \r
180 void uci_send_isready(uci_t * uci) {\r
181 \r
182    ASSERT(uci!=NULL);\r
183 \r
184    engine_send(uci->engine,"isready");\r
185    uci->ready_nb++;\r
186 }\r
187 \r
188 // uci_send_isready_sync()\r
189 \r
190 void uci_send_isready_sync(uci_t * uci) {\r
191 \r
192    char string[StringSize];\r
193    int event;\r
194 \r
195    ASSERT(uci_is_ok(uci));\r
196 \r
197    // send "isready" and wait for "readyok"\r
198 \r
199    uci_send_isready(uci);\r
200 \r
201    do {\r
202       engine_get(uci->engine,string);\r
203       event = uci_parse(uci,string);\r
204    } while (!engine_eof(Engine) && (event & EVENT_READY) == 0);\r
205 }\r
206 \r
207 // uci_send_stop()\r
208 \r
209 void uci_send_stop(uci_t * uci) {\r
210 \r
211    ASSERT(uci_is_ok(uci));\r
212 \r
213    ASSERT(uci->searching);\r
214    ASSERT(uci->pending_nb>=1);\r
215 \r
216    engine_send(Engine,"stop");\r
217    uci->searching = FALSE;\r
218 }\r
219 \r
220 // uci_send_stop_sync()\r
221 \r
222 void uci_send_stop_sync(uci_t * uci) {\r
223 \r
224    char string[StringSize];\r
225    int event;\r
226 \r
227    ASSERT(uci_is_ok(uci));\r
228 \r
229    ASSERT(uci->searching);\r
230    ASSERT(uci->pending_nb>=1);\r
231 \r
232    // send "stop" and wait for "bestmove"\r
233 \r
234    uci_send_stop(uci);\r
235 \r
236    do {\r
237       engine_get(uci->engine,string);\r
238       event = uci_parse(uci,string);\r
239    } while (!engine_eof(Engine) && (event & EVENT_STOP) == 0);\r
240 }\r
241 \r
242 // uci_send_ucinewgame()\r
243 \r
244 void uci_send_ucinewgame(uci_t * uci) {\r
245 \r
246    ASSERT(uci!=NULL);\r
247 \r
248    if (option_get_int(Option,"UCIVersion") >= 2) {\r
249       engine_send(uci->engine,"ucinewgame");\r
250    }\r
251 }\r
252 \r
253 // uci_send_option()\r
254 \r
255 bool uci_send_option(uci_t * uci, const char option[], const char format[], ...) {\r
256 \r
257    char value[FormatBufferSize];\r
258    option_t * opt;\r
259    bool found=FALSE;\r
260 \r
261    ASSERT(uci_is_ok(uci));\r
262    ASSERT(option!=NULL);\r
263    ASSERT(format!=NULL);\r
264 \r
265    // format\r
266 \r
267    CONSTRUCT_ARG_STRING(format,value);\r
268 \r
269    if (UseDebug) my_log("POLYGLOT OPTION %s VALUE %s\n",option,value);\r
270 \r
271    opt=option_find(uci->option,option);\r
272    if(opt){\r
273        found=TRUE;\r
274        if(!my_string_case_equal(opt->type,"button")){\r
275            if(!my_string_equal(opt->value,value)){\r
276                engine_send(uci->engine,"setoption name %s value %s",\r
277                            opt->name,value);\r
278                my_string_set(&opt->value,value);\r
279            }else{\r
280                my_log("POLYGLOT Not sending option \"%s\" since it "\r
281                       "already has the correct value.\n",opt->name);\r
282            }\r
283        }else{\r
284            engine_send(uci->engine,"setoption name %s",opt->name);\r
285        }\r
286    }\r
287    return found;\r
288 }\r
289 \r
290 // uci_parse()\r
291 \r
292 int uci_parse(uci_t * uci, const char string[]) {\r
293 \r
294    int event;\r
295    parse_t parse[1];\r
296    char command[StringSize];\r
297    char argument[StringSize];\r
298 \r
299    ASSERT(uci_is_ok(uci));\r
300    ASSERT(string!=NULL);\r
301 \r
302    // init\r
303 \r
304    event = EVENT_NONE;\r
305 \r
306    // parse\r
307 \r
308    parse_open(parse,string);\r
309 \r
310    if (parse_get_word(parse,command,StringSize)) {\r
311 \r
312       parse_get_string(parse,argument,StringSize);\r
313       if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" ARGUMENT \"%s\"\n",command,argument);\r
314 \r
315       if (FALSE) {\r
316 \r
317       } else if (my_string_equal(command,"bestmove")) {\r
318 \r
319          // search end\r
320 \r
321          ASSERT(uci->pending_nb>0);\r
322 \r
323          if (uci->searching && uci->pending_nb == 1) {\r
324 \r
325             // current search\r
326 \r
327             uci->searching = FALSE;\r
328             uci->pending_nb--;\r
329 \r
330             event = parse_bestmove(uci,argument); // updates uci->best_move and uci->ponder_move\r
331 \r
332          } else {\r
333 \r
334             // obsolete search\r
335 \r
336             if (uci->pending_nb > 0) {\r
337                uci->pending_nb--;\r
338                if (uci->pending_nb == 0) event = EVENT_STOP;\r
339             }\r
340          }\r
341 \r
342       } else if (my_string_equal(command,"id")) {\r
343 \r
344          parse_id(uci,argument);\r
345 \r
346       } else if (my_string_equal(command,"info")) {\r
347 \r
348          // search information\r
349 \r
350               if (uci->searching && uci->pending_nb == 1) { // current search\r
351                   event = parse_info(uci,argument);\r
352                }\r
353 \r
354       } else if (my_string_equal(command,"option")) {\r
355 \r
356          parse_option(uci,argument);\r
357 \r
358       } else if (my_string_equal(command,"readyok")) {\r
359 \r
360          // engine is ready\r
361 \r
362          ASSERT(uci->ready_nb>0);\r
363 \r
364          if (uci->ready_nb > 0) {\r
365             uci->ready_nb--;\r
366             if (uci->ready_nb == 0) event = EVENT_READY;\r
367          }\r
368 \r
369       } else if (my_string_equal(command,"uciok")) {\r
370 \r
371          event = EVENT_UCI;\r
372 \r
373       } else {\r
374 \r
375          if (UseDebug) my_log("POLYGLOT unknown command \"%s\"\n",command);\r
376       }\r
377    }\r
378 \r
379    parse_close(parse);\r
380 \r
381    return event;\r
382 }\r
383 \r
384 // parse_bestmove()\r
385 \r
386 static int parse_bestmove(uci_t * uci, const char string[]) {\r
387 \r
388    parse_t parse[1];\r
389    char command[StringSize];\r
390    char option[StringSize];\r
391    char argument[StringSize];\r
392    board_t board[1];\r
393 \r
394    ASSERT(uci_is_ok(uci));\r
395    ASSERT(string!=NULL);\r
396 \r
397    // init\r
398 \r
399    strcpy(command,"bestmove");\r
400 \r
401    parse_open(parse,string);\r
402    parse_add_keyword(parse,"ponder");\r
403 \r
404    // bestmove\r
405 \r
406    if (!parse_get_string(parse,argument,StringSize)) {\r
407        return EVENT_ILLEGAL_MOVE;\r
408 //      my_fatal("parse_bestmove(): missing argument\n");\r
409    }\r
410 \r
411    uci->best_move = move_from_can(argument,uci->board);\r
412    if (uci->best_move == MoveNone) {\r
413        return EVENT_ILLEGAL_MOVE;\r
414 //       my_fatal("parse_bestmove(): not a move \"%s\"\n",argument);\r
415    }\r
416 \r
417    if(!move_is_legal(uci->best_move,uci->board)){\r
418        return EVENT_ILLEGAL_MOVE;\r
419    }\r
420    ASSERT(uci->best_move!=MoveNone);\r
421    ASSERT(move_is_legal(uci->best_move,uci->board));\r
422 \r
423    // loop\r
424 \r
425    while (parse_get_word(parse,option,StringSize)) {\r
426 \r
427       parse_get_string(parse,argument,StringSize);\r
428 \r
429       if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
430 \r
431       if (FALSE) {\r
432 \r
433       } else if (my_string_equal(option,"ponder")) {\r
434 \r
435          ASSERT(!my_string_empty(argument));\r
436 \r
437          board_copy(board,uci->board);\r
438          move_do(board,uci->best_move);\r
439 \r
440          uci->ponder_move = move_from_can(argument,board);\r
441          // if (uci->ponder_move == MoveNone) my_fatal("parse_bestmove(): not a move \"%s\"\n",argument);\r
442 \r
443          ASSERT(uci->ponder_move!=MoveNone);\r
444          ASSERT(move_is_legal(uci->ponder_move,board));\r
445 \r
446       } else {\r
447 \r
448          my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
449       }\r
450    }\r
451 \r
452    parse_close(parse);\r
453 \r
454    return EVENT_MOVE;\r
455 }\r
456 \r
457 // parse_id()\r
458 \r
459 static void parse_id(uci_t * uci, const char string[]) {\r
460 \r
461    parse_t parse[1];\r
462    char command[StringSize];\r
463    char option[StringSize];\r
464    char argument[StringSize];\r
465 \r
466    ASSERT(uci!=NULL);\r
467    ASSERT(string!=NULL);\r
468 \r
469    // init\r
470 \r
471    strcpy(command,"id");\r
472 \r
473    parse_open(parse,string);\r
474    parse_add_keyword(parse,"author");\r
475    parse_add_keyword(parse,"name");\r
476 \r
477    // loop\r
478 \r
479    while (parse_get_word(parse,option,StringSize)) {\r
480 \r
481       parse_get_string(parse,argument,StringSize);\r
482       if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
483 \r
484       if (FALSE) {\r
485       } else if (my_string_equal(option,"author")) {\r
486          ASSERT(!my_string_empty(argument));\r
487          my_string_set(&uci->author,argument);\r
488       } else if (my_string_equal(option,"name")) {\r
489          ASSERT(!my_string_empty(argument));\r
490          my_string_set(&uci->name,argument);\r
491       } else {\r
492          my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
493       }\r
494    }\r
495 \r
496    parse_close(parse);\r
497 \r
498    if (UseDebug) my_log("POLYGLOT engine name \"%s\" author \"%s\"\n",uci->name,uci->author);\r
499 }\r
500 \r
501 // parse_info()\r
502 \r
503 static int parse_info(uci_t * uci, const char string[]) {\r
504 \r
505    int event;\r
506    parse_t parse[1];\r
507    char command[StringSize];\r
508    char option[StringSize];\r
509    char argument[StringSize];\r
510    int n;\r
511    int multipvline=0;\r
512    sint64 ln;\r
513 \r
514 \r
515    \r
516    ASSERT(uci_is_ok(uci));\r
517    ASSERT(string!=NULL);\r
518 \r
519    // init\r
520 \r
521    event = EVENT_NONE;\r
522 \r
523    strcpy(command,"info");\r
524 \r
525    parse_open(parse,string);\r
526    parse_add_keyword(parse,"cpuload");\r
527    parse_add_keyword(parse,"currline");\r
528    parse_add_keyword(parse,"currmove");\r
529    parse_add_keyword(parse,"currmovenumber");\r
530    parse_add_keyword(parse,"depth");\r
531    parse_add_keyword(parse,"hashfull");\r
532    parse_add_keyword(parse,"multipv");\r
533    parse_add_keyword(parse,"nodes");\r
534    parse_add_keyword(parse,"nps");\r
535    parse_add_keyword(parse,"pv");\r
536    parse_add_keyword(parse,"refutation");\r
537    parse_add_keyword(parse,"score");\r
538    parse_add_keyword(parse,"seldepth");\r
539    parse_add_keyword(parse,"string");\r
540    parse_add_keyword(parse,"tbhits");\r
541    parse_add_keyword(parse,"time");\r
542 \r
543    // loop\r
544 \r
545    while (parse_get_word(parse,option,StringSize)) {\r
546 \r
547       parse_get_string(parse,argument,StringSize);\r
548 \r
549       if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
550 \r
551       if (FALSE) {\r
552 \r
553       } else if (my_string_equal(option,"cpuload")) {\r
554 \r
555          ASSERT(!my_string_empty(argument));\r
556 \r
557          n = atoi(argument);\r
558          ASSERT(n>=0);\r
559 \r
560          if (n >= 0) uci->cpu = ((double)n) / 1000.0;\r
561 \r
562       } else if (my_string_equal(option,"currline")) {\r
563 \r
564          ASSERT(!my_string_empty(argument));\r
565 \r
566          line_from_can(uci->current_line,uci->board,argument,LineSize);\r
567 \r
568       } else if (my_string_equal(option,"currmove")) {\r
569 \r
570          ASSERT(!my_string_empty(argument));\r
571 \r
572          uci->root_move = move_from_can(argument,uci->board);\r
573          ASSERT(uci->root_move!=MoveNone);\r
574 \r
575       } else if (my_string_equal(option,"currmovenumber")) {\r
576 \r
577          ASSERT(!my_string_empty(argument));\r
578 \r
579          n = atoi(argument);\r
580          ASSERT(n>=1&&n<=uci->root_move_nb);\r
581 \r
582          if (n >= 1 && n <= uci->root_move_nb) {\r
583             uci->root_move_pos = n - 1;\r
584             ASSERT(uci->root_move_pos>=0&&uci->root_move_pos<uci->root_move_nb);\r
585          }\r
586 \r
587       } else if (my_string_equal(option,"depth")) {\r
588 \r
589          ASSERT(!my_string_empty(argument));\r
590 \r
591          n = atoi(argument);\r
592          ASSERT(n>=1);\r
593 \r
594          if (n >= 0) {\r
595             if (n > uci->depth) event |= EVENT_DEPTH;\r
596             uci->depth = n;\r
597          }\r
598 \r
599       } else if (my_string_equal(option,"hashfull")) {\r
600 \r
601          ASSERT(!my_string_empty(argument));\r
602 \r
603          n = atoi(argument);\r
604          ASSERT(n>=0);\r
605 \r
606          if (n >= 0) uci->hash = ((double)n) / 1000.0;\r
607 \r
608       } else if (my_string_equal(option,"multipv")) {\r
609 \r
610          ASSERT(!my_string_empty(argument));\r
611 \r
612          n = atoi(argument);\r
613                  if(Uci->multipv_mode) multipvline=n;\r
614         \r
615          ASSERT(n>=1);\r
616 \r
617       } else if (my_string_equal(option,"nodes")) {\r
618 \r
619          ASSERT(!my_string_empty(argument));\r
620 \r
621          ln = my_atoll(argument);\r
622          ASSERT(ln>=0);\r
623 \r
624          if (ln >= 0) uci->node_nb = ln;\r
625 \r
626       } else if (my_string_equal(option,"nps")) {\r
627 \r
628          ASSERT(!my_string_empty(argument));\r
629 \r
630          n = atoi(argument);\r
631          ASSERT(n>=0);\r
632 \r
633          if (n >= 0) uci->speed = ((double)n);\r
634 \r
635       } else if (my_string_equal(option,"pv")) {\r
636 \r
637          ASSERT(!my_string_empty(argument));\r
638 \r
639          line_from_can(uci->pv,uci->board,argument,LineSize);\r
640          event |= EVENT_PV;\r
641 \r
642       } else if (my_string_equal(option,"refutation")) {\r
643 \r
644          ASSERT(!my_string_empty(argument));\r
645 \r
646          line_from_can(uci->pv,uci->board,argument,LineSize);\r
647 \r
648       } else if (my_string_equal(option,"score")) {\r
649 \r
650          ASSERT(!my_string_empty(argument));\r
651 \r
652          parse_score(uci,argument);\r
653 \r
654       } else if (my_string_equal(option,"seldepth")) {\r
655 \r
656          ASSERT(!my_string_empty(argument));\r
657 \r
658          n = atoi(argument);\r
659          ASSERT(n>=0);\r
660 \r
661          if (n >= 0) uci->sel_depth = n;\r
662 \r
663       } else  if (my_string_equal(option,"string")) {\r
664                   if(my_string_case_equal(argument,"DrawOffer")){\r
665                           event |= EVENT_DRAW;\r
666           }else if(my_string_case_equal(argument,"Resign")){\r
667                           event |= EVENT_RESIGN;\r
668           }else{\r
669               strcpy(uci->info,argument);\r
670               event|=EVENT_INFO;\r
671           }\r
672          // TODO: argument to EOS\r
673 \r
674          ASSERT(!my_string_empty(argument));\r
675 \r
676       } else if (my_string_equal(option,"tbhits")) {\r
677 \r
678          ASSERT(!my_string_empty(argument));\r
679 \r
680          ln = my_atoll(argument);\r
681          ASSERT(ln>=0);\r
682 \r
683       } else if (my_string_equal(option,"time")) {\r
684 \r
685          ASSERT(!my_string_empty(argument));\r
686 \r
687          n = atoi(argument);\r
688          ASSERT(n>=0);\r
689 \r
690          if (n >= 0) uci->time = ((double)n) / 1000.0;\r
691 \r
692       } else {\r
693 \r
694          my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
695              // this is for buggy engines; it should probably be protected\r
696              // by a "WorkAround" option.\r
697          strcpy(uci->info,option);\r
698          strcat(uci->info," ");\r
699          strcat(uci->info,argument);\r
700          event|=EVENT_INFO;\r
701       }\r
702    }\r
703 \r
704    parse_close(parse);\r
705 \r
706    // update display\r
707    //lousy uci,filter out lower depth multipv lines that have been repeated from the engine \r
708    if(multipvline>1 && uci->depth<uci->best_depth) event &= ~EVENT_PV;\r
709    if ((event & EVENT_PV) != 0) {\r
710       uci->best_score = uci->score; \r
711           uci->best_depth = uci->depth;\r
712           if(multipvline==1)uci->depth=-1; //HACK ,clears the engine outpout window,see send_pv in adapter.cpp \r
713       uci->best_sel_depth = uci->sel_depth;\r
714       line_copy(uci->best_pv,uci->pv);\r
715    }\r
716    return event;\r
717 }\r
718 \r
719 // parse_option()\r
720 \r
721 static void parse_option(uci_t * uci, const char string[]) {\r
722 \r
723    option_t opt[1];\r
724    parse_t parse[1];\r
725    char command[StringSize];\r
726    char option[StringSize];\r
727    char argument[StringSize];\r
728 \r
729    ASSERT(uci!=NULL);\r
730    ASSERT(string!=NULL);\r
731 \r
732    // init\r
733 \r
734    strcpy(command,"option");\r
735 \r
736    memset(opt,0,sizeof(option_t));\r
737    \r
738    my_string_set(&opt->value,"<empty>");\r
739    my_string_set(&opt->name,"<empty>");\r
740    my_string_set(&opt->default_,"<empty>");\r
741    my_string_set(&opt->max,"<empty>");\r
742    my_string_set(&opt->min,"<empty>");\r
743    my_string_set(&opt->type,"<empty>");\r
744    opt->var_nb=0;\r
745    opt->mode=0;\r
746    \r
747    parse_open(parse,string);\r
748    parse_add_keyword(parse,"default");\r
749    parse_add_keyword(parse,"max");\r
750    parse_add_keyword(parse,"min");\r
751    parse_add_keyword(parse,"name");\r
752    parse_add_keyword(parse,"type");\r
753    parse_add_keyword(parse,"var");\r
754 \r
755    // loop\r
756 \r
757    while (parse_get_word(parse,option,StringSize)) {\r
758       parse_get_string(parse,argument,StringSize);\r
759       if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
760 \r
761       if (FALSE) {\r
762 \r
763       } else if (my_string_equal(option,"default")) {\r
764 \r
765          // ASSERT(!my_string_empty(argument)); // HACK for Pepito\r
766 \r
767          if (!my_string_empty(argument)) {\r
768             my_string_set(&opt->default_,argument);\r
769             my_string_set(&opt->value,argument);\r
770          }\r
771 \r
772       } else if (my_string_equal(option,"max")) {\r
773 \r
774          ASSERT(!my_string_empty(argument));\r
775          my_string_set(&opt->max,argument);\r
776 \r
777       } else if (my_string_equal(option,"min")) {\r
778 \r
779          ASSERT(!my_string_empty(argument));\r
780          my_string_set(&opt->min,argument);\r
781 \r
782       } else if (my_string_equal(option,"name")) {\r
783 \r
784          ASSERT(!my_string_empty(argument));\r
785 \r
786          if (!my_string_empty(argument)) {\r
787             my_string_set(&opt->name,argument);\r
788          }\r
789 \r
790       } else if (my_string_equal(option,"type")) {\r
791 \r
792          ASSERT(!my_string_empty(argument));\r
793          my_string_set(&opt->type,argument);\r
794 \r
795       } else if (my_string_equal(option,"var")) {\r
796 \r
797          ASSERT(!my_string_empty(argument));\r
798          my_string_set(&opt->var[opt->var_nb++],argument);\r
799          if(opt->var_nb==VarNb) break;\r
800 \r
801       } else {\r
802 \r
803          my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
804       }\r
805    }\r
806 \r
807    parse_close(parse);\r
808    option_insert(uci->option,opt);\r
809    option_free(opt);\r
810 \r
811    if (UseDebug) my_log("POLYGLOT option name \"%s\" default \"%s\"\n",opt->name,opt->default_);\r
812 }\r
813 \r
814 // parse_score()\r
815 \r
816 static void parse_score(uci_t * uci, const char string[]) {\r
817 \r
818    parse_t parse[1];\r
819    char command[StringSize];\r
820    char option[StringSize];\r
821    char argument[StringSize];\r
822    int n;\r
823 \r
824    ASSERT(uci_is_ok(uci));\r
825    ASSERT(string!=NULL);\r
826 \r
827    // init\r
828 \r
829    strcpy(command,"score");\r
830 \r
831    parse_open(parse,string);\r
832    parse_add_keyword(parse,"cp");\r
833    parse_add_keyword(parse,"lowerbound");\r
834    parse_add_keyword(parse,"mate");\r
835    parse_add_keyword(parse,"upperbound");\r
836 \r
837    // loop\r
838 \r
839    while (parse_get_word(parse,option,StringSize)) {\r
840 \r
841       parse_get_string(parse,argument,StringSize);\r
842 \r
843       if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
844 \r
845       if (FALSE) {\r
846 \r
847       } else if (my_string_equal(option,"cp")) {\r
848 \r
849          ASSERT(!my_string_empty(argument));\r
850 \r
851          n = atoi(argument);\r
852 \r
853          uci->score = n;\r
854 \r
855       } else if (my_string_equal(option,"lowerbound")) {\r
856 \r
857          ASSERT(my_string_empty(argument));\r
858 \r
859       } else if (my_string_equal(option,"mate")) {\r
860 \r
861          ASSERT(!my_string_empty(argument));\r
862 \r
863          n = atoi(argument);\r
864          ASSERT(n!=0);\r
865 \r
866          uci->score = mate_score(n);\r
867 \r
868       } else if (my_string_equal(option,"upperbound")) {\r
869 \r
870          ASSERT(my_string_empty(argument));\r
871 \r
872       } else {\r
873 \r
874          my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
875       }\r
876    }\r
877 \r
878    parse_close(parse);\r
879 }\r
880 \r
881 // mate_score()\r
882 \r
883 static int mate_score(int dist) {\r
884 \r
885    ASSERT(dist!=0);\r
886 \r
887    if (FALSE) {\r
888    } else if (dist > 0) {\r
889        return +option_get_int(Option,"MateScore") - (+dist) * 2 + 1;\r
890    } else if (dist < 0) {\r
891        return -option_get_int(Option,"MateScore") + (-dist) * 2;\r
892    }\r
893 \r
894    return 0;\r
895 }\r
896 \r
897 // end of uci.cpp\r
898 \r