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