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
apply_UCI3_heuristics(option_t * opt)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
uci_set_threads(uci_t * uci,int n)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
uci_thread_option(uci_t * uci)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
uci_is_ok(const uci_t * uci)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
uci_open(uci_t * uci,engine_t * engine)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
uci_close(uci_t * uci)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
uci_clear(uci_t * uci)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
uci_send_isready(uci_t * uci)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
uci_send_isready_sync(uci_t * uci)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
uci_send_stop(uci_t * uci)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
uci_send_stop_sync(uci_t * uci)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
uci_send_ucinewgame(uci_t * uci)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
uci_send_option(uci_t * uci,const char option[],const char format[],...)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
uci_parse(uci_t * uci,const char string[])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
parse_bestmove(uci_t * uci,const char string[])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
parse_id(uci_t * uci,const char string[])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
parse_info(uci_t * uci,const char string[])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
parse_option(uci_t * uci,const char string[])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
parse_score(uci_t * uci,const char string[])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
mate_score(int dist)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
962