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