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