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