15 #include "book_make.h"
\r
16 #include "book_merge.h"
\r
24 #include "mainloop.h"
\r
26 #include "move_gen.h"
\r
33 #include "xboard2uci.h"
\r
34 #include "uci2uci.h"
\r
42 static const char * const Version = "1.4.53b";
\r
43 static const char * const HelpMessage = "\
\r
45 * polyglot [configfile] [-noini] [-ec engine] [-ed enginedirectory] [-en enginename] [-log] [-lf logfile] [-hash value] [-bk book] [-pg <name>=<value>]* [-uci <name>=<value>]*\n\
\r
46 * polyglot make-book [-pgn inputfile] [-bin outputfile] [-max-ply ply] [-min-game games] [-min-score score] [-only-white] [-only-black] [-uniform]\n\
\r
47 * polyglot merge-book -in1 inputfile1 -in2 inputfile2 [-out outputfile]\n\
\r
48 * polyglot info-book [-bin inputfile] [-exact]\n\
\r
49 * polyglot dump-book [-bin inputfile] -color color [-out outputfile]\n\
\r
50 * polyglot [configfile] epd-test [engineoptions] [-epd inputfile] [-min-depth depth] [-max-depth depth] [-min-time time] [-max-time time] [-depth-delta delta]\n\
\r
51 * polyglot perft [-fen fen] [-max-depth depth]\
\r
54 static const int SearchDepth = 63;
\r
55 static const double SearchTime = 3600.0;
\r
56 static const int StringSize = 4096;
\r
64 static void stop_search ();
\r
70 static void arg_shift_left(char **argv, int index){
\r
72 for(i=index; argv[i]!=NULL; i++){
\r
79 static void parse_args(ini_t *ini, char **argv){
\r
83 while((arg=argv[arg_index])){
\r
84 if(my_string_equal(arg,"-ec") && argv[arg_index+1]){
\r
85 ini_insert_ex(ini,"PolyGlot","EngineCommand",argv[arg_index+1]);
\r
86 arg_shift_left(argv,arg_index);
\r
87 arg_shift_left(argv,arg_index);
\r
89 }if(my_string_equal(arg,"-ed") && argv[arg_index+1]){
\r
90 ini_insert_ex(ini,"PolyGlot","EngineDir",argv[arg_index+1]);
\r
91 arg_shift_left(argv,arg_index);
\r
92 arg_shift_left(argv,arg_index);
\r
95 if(my_string_equal(arg,"-en") && argv[arg_index+1]){
\r
96 ini_insert_ex(ini,"PolyGlot","EngineName",argv[arg_index+1]);
\r
97 arg_shift_left(argv,arg_index);
\r
98 arg_shift_left(argv,arg_index);
\r
101 if(my_string_equal(arg,"-log") &&
\r
102 argv[arg_index+1] &&
\r
103 IS_BOOL(argv[arg_index+1])){
\r
107 TO_BOOL(argv[arg_index+1])?"true":"false");
\r
108 arg_shift_left(argv,arg_index);
\r
109 arg_shift_left(argv,arg_index);
\r
112 if(my_string_equal(arg,"-lf") && argv[arg_index+1]){
\r
113 ini_insert_ex(ini,"PolyGlot","LogFile",argv[arg_index+1]);
\r
114 arg_shift_left(argv,arg_index);
\r
115 arg_shift_left(argv,arg_index);
\r
118 if(my_string_equal(arg,"-wb") &&
\r
119 argv[arg_index+1]&&
\r
120 IS_BOOL(argv[arg_index+1])){
\r
121 ini_insert_ex(ini,"PolyGlot",
\r
123 TO_BOOL(argv[arg_index+1])?"true":"false");
\r
124 arg_shift_left(argv,arg_index);
\r
125 arg_shift_left(argv,arg_index);
\r
128 if((my_string_equal(arg,"-pg")||my_string_equal(arg,"-uci")) &&
\r
129 argv[arg_index+1]){
\r
131 char section[StringSize];
\r
132 char name[StringSize];
\r
133 char value[StringSize];
\r
134 ret=ini_line_parse(argv[arg_index+1],section,name,value);
\r
135 if(ret==NAME_VALUE){
\r
136 if(my_string_equal(arg,"-pg")){
\r
137 ini_insert_ex(ini,"PolyGlot",name,value);
\r
139 ini_insert_ex(ini,"Engine",name,value);
\r
142 arg_shift_left(argv,arg_index);
\r
143 arg_shift_left(argv,arg_index);
\r
153 static void make_ini(ini_t *ini){
\r
155 ini_insert_ex(ini,"polyglot",
\r
157 option_get(Option,"EngineCommand"));
\r
158 ini_insert_ex(ini,"polyglot",
\r
160 option_get(Option,"EngineDir"));
\r
161 option_start_iter(Option);
\r
162 while((opt=option_next(Option))){
\r
163 if(my_string_case_equal(opt->name,"SettingsFile")) continue;
\r
164 if(my_string_case_equal(opt->name,"EngineCommand")) continue;
\r
165 if(my_string_case_equal(opt->name,"EngineDir")) continue;
\r
166 if(!my_string_equal(opt->value,opt->default_)&& !IS_BUTTON(opt->type))
\r
168 ini_insert_ex(ini,"polyglot",opt->name,opt->value);
\r
171 option_start_iter(Uci->option);
\r
172 while((opt=option_next(Uci->option))){
\r
173 if(!strncmp(opt->name,"UCI_",4) &&
\r
174 !my_string_case_equal(opt->name,"UCI_LimitStrength") &&
\r
175 !my_string_case_equal(opt->name,"UCI_Elo"))continue;
\r
176 if(!my_string_equal(opt->value,opt->default_)&&
\r
177 !IS_BUTTON(opt->type)){
\r
178 ini_insert_ex(ini,"engine",opt->name,opt->value);
\r
186 static void write_ini(const char *filename,
\r
189 ini_entry_t *entry;
\r
190 char tmp[StringSize];
\r
192 time_t t=time(NULL);
\r
193 f=fopen(filename,"w");
\r
195 gui_send(GUI,"tellusererror write_ini(): %s: %s.",filename,strerror(errno));
\r
196 my_log("POLYGLOT write_ini(): %s: %s.\n",filename,strerror(errno));
\r
199 fprintf(f,"; Created: %s\n",ctime(&t));
\r
200 fprintf(f,"[PolyGlot]\n");
\r
201 ini_start_iter(ini);
\r
202 while((entry=ini_next(ini))){
\r
203 if(my_string_case_equal(entry->section,"polyglot")){
\r
204 if(strchr(entry->value,';')|| strchr(entry->value,'#')|| strchr(entry->value,'"')){
\r
209 snprintf(tmp,sizeof(tmp),"%s=%s%s%s\n",
\r
214 tmp[sizeof(tmp)-1]='\0';
\r
215 fprintf(f,"%s",tmp);
\r
218 fprintf(f,"[Engine]\n");
\r
219 ini_start_iter(ini);
\r
220 while((entry=ini_next(ini))){
\r
221 if(my_string_case_equal(entry->section,"engine")){
\r
222 if(strchr(entry->value,';')|| strchr(entry->value,'#')|| strchr(entry->value,'"')){
\r
227 snprintf(tmp,sizeof(tmp),"%s=%s%s%s\n",
\r
232 tmp[sizeof(tmp)-1]='\0';
\r
233 fprintf(f,"%s",tmp);
\r
239 // welcome_message()
\r
241 void welcome_message(char *buf){
\r
244 "PolyGlot %s by Fabien Letouzey.\n",
\r
248 "PolyGlot %s by Fabien Letouzey (debug build).\n",
\r
255 option_start_iter(Option);
\r
256 while((opt=option_next(Option))){
\r
257 opt->mode&=~XBOARD;
\r
258 if(opt->mode & XBSEL){
\r
259 opt->mode|=XBOARD;
\r
266 int main(int argc, char * argv[]) {
\r
267 ini_t ini[1], ini_command[1];
\r
268 ini_entry_t *entry;
\r
273 char welcome[StringSize];
\r
276 welcome_message(welcome);
\r
278 printf("%s",welcome);
\r
281 if(argc>=2 && ((my_string_case_equal(argv[1],"help")) || (my_string_case_equal(argv[1],"-help")) || (my_string_case_equal(argv[1],"--help")) || (my_string_case_equal(argv[1],"-h")) || my_string_case_equal(argv[1],"/?"))){
\r
282 printf("%s\n",HelpMessage);
\r
283 return EXIT_SUCCESS;
\r
302 ini_init(ini_command);
\r
304 // book utilities: do not touch these
\r
306 if (argc >= 2 && my_string_equal(argv[1],"make-book")) {
\r
307 book_make(argc,argv);
\r
308 return EXIT_SUCCESS;
\r
311 if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {
\r
312 book_merge(argc,argv);
\r
313 return EXIT_SUCCESS;
\r
316 if (argc >= 2 && my_string_equal(argv[1],"dump-book")) {
\r
317 book_dump(argc,argv);
\r
318 return EXIT_SUCCESS;
\r
321 if (argc >= 2 && my_string_equal(argv[1],"info-book")) {
\r
322 book_info(argc,argv);
\r
323 return EXIT_SUCCESS;
\r
328 if (argc >= 2 && my_string_equal(argv[1],"perft")) {
\r
329 do_perft(argc,argv);
\r
330 return EXIT_SUCCESS;
\r
333 // What is the config file? This is very hacky right now.
\r
335 // Do we want a config file at all?
\r
339 while((arg=argv[arg_index++])){
\r
340 if(my_string_equal(arg,"-noini")){
\r
345 arg_shift_left(argv,arg_index-1);
\r
346 parse_args(ini_command,argv+1);
\r
348 option_set(Option,"SettingsFile","<empty>");
\r
351 // Ok see if first argument looks like config file
\r
353 if(argv[1] && !my_string_equal(argv[1],"epd-test") && !(argv[1][0]=='-')){
\r
354 // first argument must be config file
\r
356 option_set(Option,"SettingsFile",argv[1]);
\r
360 arg_shift_left(argv,1);
\r
362 // Config file is the default.
\r
363 // This has already been set above or in "option_init_pg()"
\r
368 // if we use a config file: load it!
\r
370 if(!my_string_equal(option_get_string(Option,"SettingsFile"),"<empty>")){
\r
371 if(ini_parse(ini,option_get_string(Option,"SettingsFile"))){
\r
372 my_fatal("main(): Can't open file \"%s\": %s\n",
\r
373 option_get_string(Option,"SettingsFile"),
\r
378 // Extract some important options
\r
380 if((entry=ini_find(ini,"polyglot","EngineCommand"))){
\r
381 option_set(Option,entry->name,entry->value);
\r
383 if((entry=ini_find(ini,"polyglot","EngineDir"))){
\r
384 option_set(Option,entry->name,entry->value);
\r
386 if((entry=ini_find(ini,"polyglot","EngineName"))){
\r
387 option_set(Option,entry->name,entry->value);
\r
389 if((entry=ini_find(ini,"polyglot","Log"))){
\r
390 polyglot_set_option(entry->name,entry->value);
\r
392 if((entry=ini_find(ini,"polyglot","LogFile"))){
\r
393 polyglot_set_option(entry->name,entry->value);
\r
396 // Concession to WB 4.4.0
\r
397 // Treat "polyglot_1st.ini" and "polyglot_2nd.ini" specially
\r
399 if(option_get_bool(Option,"WbWorkArounds3")){
\r
400 const char *SettingsFile=option_get(Option,"SettingsFile");
\r
401 if(strstr(SettingsFile,"polyglot_1st.ini")||
\r
402 strstr(SettingsFile,"polyglot_2nd.ini")){
\r
403 option_set(Option,"SettingsFile","<empty>");
\r
407 // Look at command line for logging option. It is important
\r
408 // to start logging as soon as possible.
\r
410 if((entry=ini_find(ini_command,"PolyGlot","Log"))){
\r
411 option_set(Option,entry->name,entry->value);
\r
413 if((entry=ini_find(ini_command,"PolyGlot","LogFile"))){
\r
414 option_set(Option,entry->name,entry->value);
\r
417 // start logging if required
\r
419 if (option_get_bool(Option,"Log")) {
\r
420 my_log_open(option_get_string(Option,"LogFile"));
\r
423 // log welcome stuff
\r
425 my_log("%s",welcome);
\r
426 my_log("POLYGLOT *** START ***\n");
\r
427 if(!my_string_equal(option_get_string(Option,"SettingsFile"),"<empty>")){
\r
428 my_log("POLYGLOT INI file \"%s\"\n",option_get_string(Option,"SettingsFile"));
\r
432 // scavenge command line for options necessary to start the engine
\r
435 if((entry=ini_find(ini_command,"PolyGlot","EngineCommand"))){
\r
436 option_set(Option,entry->name,entry->value);
\r
438 if((entry=ini_find(ini_command,"PolyGlot","EngineDir"))){
\r
439 option_set(Option,entry->name,entry->value);
\r
441 if((entry=ini_find(ini_command,"PolyGlot","EngineName"))){
\r
442 option_set(Option,entry->name,entry->value);
\r
447 engine_open(Engine);
\r
448 if(!engine_active(Engine)){
\r
449 my_fatal("Could not start \"%s\"\n",option_get(Option,"EngineCommand"));
\r
452 // switch to UCI mode if necessary
\r
454 if (option_get_bool(Option,"UCI")) {
\r
455 my_log("POLYGLOT *** Switching to UCI mode ***\n");
\r
458 // initialize uci parsing and send uci command.
\r
459 // Parse options and wait for uciok
\r
461 uci_open(Uci,Engine);
\r
463 option_set_default(Option,"EngineName",Uci->name);
\r
465 // get engine name from engine if not supplied in config file or on
\r
466 // the command line
\r
468 if (my_string_equal(option_get_string(Option,"EngineName"),"<empty>")) {
\r
469 option_set(Option,"EngineName",Uci->name);
\r
473 // In the case we have been invoked with NoIni or StandardIni
\r
474 // we still have to load a config file.
\r
476 if(my_string_equal(option_get_string(Option,"SettingsFile"),"<empty>")){
\r
478 // construct the name of the ConfigFile from the EngineName
\r
480 char tmp[StringSize];
\r
481 char option_file[StringSize];
\r
483 snprintf(tmp,sizeof(tmp),"%s.ini",
\r
484 option_get_string(Option,"EngineName"));
\r
485 tmp[sizeof(tmp)-1]='\0';
\r
486 for(i=0;i<strlen(tmp);i++){
\r
491 my_path_join(option_file,
\r
492 option_get_string(Option,"SettingsDir"),
\r
494 // Load the config file
\r
495 option_set(Option,"SettingsFile",option_file);
\r
497 my_log("POLYGLOT INI file \"%s\"\n",option_get_string(Option,"SettingsFile"));
\r
498 if(ini_parse(ini,option_file)){
\r
499 my_log("POLYGLOT Unable to open %s\n",
\r
500 option_get_string(Option,"SettingsFile"));
\r
505 // Parse the command line and merge remaining options.
\r
507 ini_start_iter(ini_command);
\r
508 while((entry=ini_next(ini_command))){
\r
509 ini_insert(ini,entry);
\r
512 // Remind the reader about the options that are now in effect.
\r
514 my_log("POLYGLOG OPTIONS \n");
\r
517 // extract PG options
\r
519 ini_start_iter(ini);
\r
520 while((entry=ini_next(ini))){
\r
521 if(my_string_case_equal(entry->section,"polyglot")){
\r
522 opt=option_find(Option,entry->name);
\r
523 if(opt && !IS_BUTTON(opt->type)){
\r
524 polyglot_set_option(entry->name,entry->value);
\r
529 // Cater to our biggest customer:-)
\r
531 if(option_get_bool(Option,"OnlyWbOptions")){
\r
535 // done initializing
\r
539 // collect engine options from config file(s) and send to engine
\r
541 ini_start_iter(ini);
\r
542 while((entry=ini_next(ini))){
\r
543 if(my_string_case_equal(entry->section,"engine")){
\r
544 // also updates value in Uci->option
\r
545 uci_send_option(Uci,entry->name,"%s",entry->value);
\r
553 if (argv[1] && my_string_equal(argv[1],"epd-test")){
\r
555 while((arg=argv[argc++]));
\r
556 epd_test(argc-1,argv);
\r
557 return EXIT_SUCCESS;
\r
560 // Anything that hasn't been parsed yet is a syntax error
\r
561 // It seems that XBoard sometimes passes empty strings as arguments
\r
562 // to PolyGlot. We ignore these.
\r
565 while((arg=argv[argc++])){
\r
566 if(!my_string_equal(arg,"")){
\r
567 my_fatal("main(): Option: \"%s\" not found\n",argv[argc-1]);
\r
573 return EXIT_SUCCESS;
\r
576 // polyglot_set_option()
\r
578 void polyglot_set_option(const char *name, const char *value){ // this must be cleaned up!
\r
582 my_log("POLYGLOT Setting PolyGlot option %s=\"%s\"\n",name,value);
\r
583 if(my_string_case_equal(name,"Save")){
\r
584 ret=my_mkdir(option_get(Option,"SettingsDir"));
\r
586 my_log("POLYGLOT polyglot_set_option(): %s: %s\n",
\r
587 option_get(Option,"SettingsDir"),
\r
591 write_ini(option_get(Option,"SettingsFile"),ini);
\r
594 // if(my_string_equal(option_get(Option,name),value)){
\r
595 // my_log("Not setting PolyGlot option \"%s\" "
\r
596 // "since it already as the correct value.\n",
\r
600 option_set(Option,name,value);
\r
601 if(option_get_bool(Option,"Book")&&(my_string_case_equal(name,"BookFile")||my_string_case_equal(name,"Book"))){
\r
602 my_log("POLYGLOT *** SETTING BOOK ***\n");
\r
603 my_log("POLYGLOT BOOK \"%s\"\n",option_get_string(Option,"BookFile"));
\r
606 book_open(option_get_string(Option,"BookFile"));
\r
607 if(!book_is_open()){
\r
608 my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string(Option,"BookFile"));
\r
610 }else if(option_get_bool(Option,"Log")&&(my_string_case_equal(name,"LogFile") ||my_string_case_equal(name,"Log"))){
\r
611 my_log("POLYGLOT *** SWITCHING LOGFILE ***\n");
\r
612 my_log("POLYGLOT NEW LOGFILE \"%s\"\n",option_get_string(Option,"LogFile"));
\r
614 my_log_open(option_get_string(Option,"LogFile"));
\r
615 }else if(option_get_bool(Option,"UseNice") &&(my_string_case_equal(name,"NiceValue")||my_string_case_equal(name,"UseNice"))){
\r
616 my_log("POLYGLOT Adjust Engine Piority\n");
\r
617 engine_set_nice_value(Engine,atoi(option_get_string(Option,"NiceValue")));
\r
618 }else if(my_string_case_equal(name,"Book") && !option_get_bool(Option,"Book")){
\r
621 }else if(my_string_case_equal(name,"UseNice") && !option_get_bool(Option,"UseNice")){
\r
622 my_log("POLYGLOT Adjust Engine Piority\n");
\r
623 engine_set_nice_value(Engine,0);
\r
624 }else if(my_string_case_equal(name,"Log") && !option_get_bool(Option,"Log")){
\r
625 my_log("POLYGLOT QUIT LOGGING\n");
\r
636 my_log("POLYGLOT *** QUIT ***\n");
\r
641 engine_send(Engine,"quit");
\r
642 my_log("POLYGLOT Closing engine\n");
\r
643 engine_close(Engine);
\r
646 my_log("POLYGLOT Calling exit\n");
\r
647 exit(EXIT_SUCCESS);
\r
652 static void stop_search() {
\r
654 if (Init && Uci->searching) {
\r
656 ASSERT(Uci->searching);
\r
657 ASSERT(Uci->pending_nb>=1);
\r
659 my_log("POLYGLOT STOP SEARCH\n");
\r
661 if (option_get_bool(Option,"SyncStop")) {
\r
662 uci_send_stop_sync(Uci);
\r
664 uci_send_stop(Uci);
\r