14 #include "book_make.h"
\r
15 #include "book_merge.h"
\r
23 #include "mainloop.h"
\r
25 #include "move_gen.h"
\r
32 #include "xboard2uci.h"
\r
33 #include "uci2uci.h"
\r
39 static const char * const Version = "1.4.41b";
\r
40 static const char * const HelpMessage = "\
\r
42 * polyglot [configfile] [-noini] [-ec engine] [-ed enginedirectory] [-en enginename] [-log] [-lf logfile] [-hash value] [-bk book] [-pg <name>=<value>]* [-uci <name>=<value>]*\n\
\r
43 * polyglot make-book [-pgn inputfile] [-bin outputfile] [-max-ply ply] [-min-game games] [-min-score score] [-only-white] [-only-black] [-uniform]\n\
\r
44 * polyglot merge-book -in1 inputfile1 -in2 inputfile2 [-out outputfile]\n\
\r
45 * polyglot info-book [-bin inputfile] [-exact]\n\
\r
46 * polyglot dump-book [-bin inputfile] -color color [-out outputfile]\n\
\r
47 * polyglot [configfile] epd-test [engineoptions] [-epd inputfile] [-min-depth depth] [-max-depth depth] [-min-time time] [-max-time time] [-depth-delta delta]\n\
\r
48 * polyglot perft [-fen fen] [-max-depth depth]\
\r
51 static const int SearchDepth = 63;
\r
52 static const double SearchTime = 3600.0;
\r
53 static const int StringSize = 4096;
\r
61 static void init_book ();
\r
62 static void stop_search ();
\r
68 void arg_shift_left(char **argv, int index){
\r
70 for(i=index; argv[i]!=NULL; i++){
\r
76 void write_ini(const char *filename,
\r
77 option_list_t *pg_options,
\r
78 option_list_t *uci_options){
\r
80 char tmp[StringSize];
\r
82 f=fopen(filename,"w");
\r
84 my_fatal("ini_create_pg(): Cannot open %s for writing.\n",filename);
\r
86 fprintf(f,"; You may edit this file to set options for the\n"
\r
87 "; UCI engine whose PolyGlot name is %s.\n"
\r
88 "; You may also safely delete this file\n"
\r
89 "; to restore the default options.\n",
\r
90 option_get_string(Option,"EngineName"));
\r
91 fprintf(f,"[PolyGlot]\n");
\r
92 option_start_iter(pg_options);
\r
93 while((opt=option_next(pg_options))){
\r
94 if(!my_string_case_equal(opt->type,"button") && (opt->mode & XBOARD)){
\r
95 snprintf(tmp,sizeof(tmp),"%s=%s\n",opt->name,opt->value);
\r
96 tmp[sizeof(tmp)-1]='\0';
\r
97 fprintf(f,"%s",tmp);
\r
100 fprintf(f,"[Engine]\n");
\r
101 option_start_iter(uci_options);
\r
102 while((opt=option_next(uci_options))){
\r
103 if(!my_string_case_equal(opt->type,"button")){
\r
104 snprintf(tmp,sizeof(tmp),"%s=%s\n",opt->name,opt->value);
\r
105 tmp[sizeof(tmp)-1]='\0';
\r
106 fprintf(f,"%s",tmp);
\r
115 int main(int argc, char * argv[]) {
\r
117 ini_entry_t *entry;
\r
123 printf("PolyGlot %s by Fabien Letouzey.\n",Version);
\r
125 printf("PolyGlot %s by Fabien Letouzey (debug build).\n",Version);
\r
128 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
129 printf("%s\n",HelpMessage);
\r
130 return EXIT_SUCCESS;
\r
150 if (argc >= 2 && my_string_equal(argv[1],"make-book")) {
\r
151 book_make(argc,argv);
\r
152 return EXIT_SUCCESS;
\r
155 if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {
\r
156 book_merge(argc,argv);
\r
157 return EXIT_SUCCESS;
\r
160 if (argc >= 2 && my_string_equal(argv[1],"dump-book")) {
\r
161 book_dump(argc,argv);
\r
162 return EXIT_SUCCESS;
\r
165 if (argc >= 2 && my_string_equal(argv[1],"info-book")) {
\r
166 book_info(argc,argv);
\r
167 return EXIT_SUCCESS;
\r
172 if (argc >= 2 && my_string_equal(argv[1],"perft")) {
\r
173 do_perft(argc,argv);
\r
174 return EXIT_SUCCESS;
\r
177 // what is the config file? This is very hacky right now?
\r
179 // Do we want a config file at all?
\r
183 while((arg=argv[arg_index++])){
\r
184 if(my_string_equal(arg,"-noini")){
\r
189 arg_shift_left(argv,arg_index-1);
\r
191 option_set(Option,"OptionFile","<empty>");
\r
194 // Ok see if first argument looks like config file
\r
196 if(argv[1] && !my_string_equal(argv[1],"epd-test") && !(argv[1][0]=='-')){
\r
197 // first argument must be config file
\r
199 option_set(Option,"OptionFile",argv[1]);
\r
203 arg_shift_left(argv,1);
\r
205 // Config file is the default.
\r
206 // This has already been set above or in "option_init_pg"
\r
211 // if we use a config file: load it!
\r
213 if(!my_string_equal(option_get_string(Option,"OptionFile"),"<empty>")){
\r
214 if(ini_parse(ini,option_get_string(Option,"OptionFile"))){
\r
215 my_fatal("main(): Can't open file \"%s\": %s\n",
\r
216 option_get_string(Option,"OptionFile"),
\r
221 // parse the command line and merge options
\r
224 while((arg=argv[arg_index])){
\r
227 // printf("arg_index=%d\n",arg_index);
\r
228 // while((arg1=argv[i++])){
\r
229 // printf("arg=%s ",arg1);
\r
232 if(my_string_equal(arg,"-ec") && argv[arg_index+1]){
\r
233 ini_insert_ex(ini,"PolyGlot","EngineCommand",argv[arg_index+1]);
\r
234 arg_shift_left(argv,arg_index);
\r
235 arg_shift_left(argv,arg_index);
\r
238 if(my_string_equal(arg,"-ed") && argv[arg_index+1]){
\r
239 ini_insert_ex(ini,"PolyGlot","EngineDir",argv[arg_index+1]);
\r
240 arg_shift_left(argv,arg_index);
\r
241 arg_shift_left(argv,arg_index);
\r
244 if(my_string_equal(arg,"-en") && argv[arg_index+1]){
\r
245 ini_insert_ex(ini,"PolyGlot","EngineName",argv[arg_index+1]);
\r
246 arg_shift_left(argv,arg_index);
\r
247 arg_shift_left(argv,arg_index);
\r
250 if(my_string_equal(arg,"-log")){
\r
251 ini_insert_ex(ini,"PolyGlot","Log","true");
\r
252 arg_shift_left(argv,arg_index);
\r
255 if(my_string_equal(arg,"-lf") && argv[arg_index+1]){
\r
256 ini_insert_ex(ini,"PolyGlot","LogFile",argv[arg_index+1]);
\r
257 arg_shift_left(argv,arg_index);
\r
258 arg_shift_left(argv,arg_index);
\r
261 if(my_string_equal(arg,"-hash") && argv[arg_index+1]){
\r
262 ini_insert_ex(ini,"Engine","Hash",argv[arg_index+1]);
\r
263 arg_shift_left(argv,arg_index);
\r
264 arg_shift_left(argv,arg_index);
\r
267 if(my_string_equal(arg,"-bk") && argv[arg_index+1]){
\r
268 ini_insert_ex(ini,"PolyGlot","Book","true");
\r
269 ini_insert_ex(ini,"PolyGlot","BookFile",argv[arg_index+1]);
\r
270 arg_shift_left(argv,arg_index);
\r
271 arg_shift_left(argv,arg_index);
\r
274 if((my_string_equal(arg,"-pg")||my_string_equal(arg,"-uci")) &&
\r
277 char section[StringSize];
\r
278 char name[StringSize];
\r
279 char value[StringSize];
\r
280 ret=ini_line_parse(argv[arg_index++],section,name,value);
\r
281 if(ret==NAME_VALUE){
\r
282 if(my_string_equal(arg,"-pg")){
\r
283 ini_insert_ex(ini,"PolyGlot",name,value);
\r
285 ini_insert_ex(ini,"Engine",name,value);
\r
288 arg_shift_left(argv,arg_index);
\r
289 arg_shift_left(argv,arg_index);
\r
295 // extract PG options
\r
296 // this sets both the default and the value
\r
298 option_from_ini(Option,ini,"polyglot");
\r
300 // start logging if required
\r
302 if (option_get_bool(Option,"Log")) {
\r
303 my_log_open(option_get_string(Option,"LogFile"));
\r
306 // log welcome stuff
\r
309 my_log("PolyGlot %s by Fabien Letouzey\n",Version);
\r
311 my_log("PolyGlot %s by Fabien Letouzey (debug build)\n",Version);
\r
313 my_log("POLYGLOT *** START ***\n");
\r
314 my_log("POLYGLOT INI file \"%s\"\n",option_get_string(Option,"OptionFile"));
\r
318 engine_open(Engine);
\r
319 if(!engine_active(Engine)){
\r
320 my_fatal("Could not start \"%s\"\n",option_get(Option,"EngineCommand"));
\r
323 // switch to UCI mode if necessary
\r
325 if (option_get_bool(Option,"UCI")) {
\r
326 my_log("POLYGLOT *** Switching to UCI mode ***\n");
\r
329 // initialize uci parsing and send uci command. Parse options and wait
\r
332 uci_open(Uci,Engine);
\r
334 // get engine name from engine if not supplied in config file
\r
336 if (my_string_equal(option_get_string(Option,"EngineName"),"<empty>")) {
\r
337 option_set(Option,"EngineName",Uci->name);
\r
340 // if there is a save file: load it!
\r
342 if(my_string_equal(option_get_string(Option,"SaveFile"),"<empty>")){
\r
343 char tmp[StringSize];
\r
344 snprintf(tmp,sizeof(tmp),"PG_%s.ini",
\r
345 option_get_string(Option,"EngineName"));
\r
346 tmp[sizeof(tmp)-1]='\0';
\r
347 option_set(Option,"SaveFile",tmp);
\r
349 if(option_get_bool(Option,"SaveSettingsOnExit")){
\r
350 my_log("POLYGLOT SaveFile=%s\n",option_get_string(Option,"SaveFile"));
\r
351 if(ini_parse(ini,option_get_string(Option,"SaveFile"))){
\r
352 my_log("POLYGLOT Unable to open SaveFile\n");
\r
355 // start if it was enabled in the SaveFile
\r
358 if (option_get_bool(Option,"Log")) {
\r
359 my_log_open(option_get_string(Option,"LogFile"));
\r
361 // remind the user of the options that are now in effect
\r
367 // done initializing
\r
371 // collect engine options from config file(s) and send to engine
\r
373 ini_start_iter(ini);
\r
374 while((entry=ini_next(ini))){
\r
375 if(my_string_case_equal(entry->section,"engine")){
\r
376 // also updates value in Uci->option
\r
377 uci_send_option(Uci,entry->name,"%s",entry->value);
\r
378 // since this comes from the ini file, also update default
\r
379 option_set_default(Uci->option,entry->name,entry->value);
\r
380 //to get a decent display in winboard_x we need to now if an engine really is doing multipv analysis
\r
381 // "multipv 1" in the pv is meaningless,f.i. toga sends that all the time
\r
382 //therefore check if MultiPV is set to a decent value in the polyglot ini file
\r
383 if(my_string_case_equal(entry->name,"MultiPV") &&
\r
384 atoi(entry->value)>1){
\r
385 Uci->multipv_mode=TRUE;
\r
393 if (argv[1] && my_string_equal(argv[1],"epd-test")){
\r
395 while((arg=argv[argc++]));
\r
396 epd_test(argc-1,argv);
\r
397 return EXIT_SUCCESS;
\r
400 // Anything that hasn't been parsed yet is a syntax error
\r
403 my_fatal("main(): Unknown option: %s\n",argv[1]);
\r
410 return EXIT_SUCCESS;
\r
413 // polyglot_set_option
\r
415 void polyglot_set_option(char *name, char *value){ // this must be cleaned up!
\r
416 option_set(Option,name,value);
\r
417 if(option_get_bool(Option,"Book")&&(my_string_case_equal(name,"BookFile")||my_string_case_equal(name,"Book"))){
\r
418 my_log("POLYGLOT *** SETTING BOOK ***\n");
\r
419 my_log("POLYGLOT BOOK \"%s\"\n",option_get_string(Option,"BookFile"));
\r
422 book_open(option_get_string(Option,"BookFile"));
\r
423 if(!book_is_open()){
\r
424 my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string(Option,"BookFile"));
\r
426 }else if(option_get_bool(Option,"Log")&&(my_string_case_equal(name,"LogFile") ||my_string_case_equal(name,"Log"))){
\r
427 my_log("POLYGLOT *** SETTING LOGFILE ***\n");
\r
428 my_log("POLYGLOT LOGFILE \"%s\"\n",option_get_string(Option,"LogFile"));
\r
430 my_log_open(option_get_string(Option,"LogFile"));
\r
431 }else if(option_get_bool(Option,"UseNice") &&(my_string_case_equal(name,"NiceValue")||my_string_case_equal(name,"UseNice"))){
\r
432 my_log("POLYGLOT Adjust Engine Piority\n");
\r
433 engine_set_nice_value(Engine,atoi(option_get_string(Option,"NiceValue")));
\r
434 }else if(my_string_case_equal(name,"Book") && !option_get_bool(Option,"Book")){
\r
437 }else if(my_string_case_equal(name,"UseNice") && !option_get_bool(Option,"UseNice")){
\r
438 my_log("POLYGLOT Adjust Engine Piority\n");
\r
439 engine_set_nice_value(Engine,0);
\r
440 }else if(my_string_case_equal(name,"Log") && !option_get_bool(Option,"Log")){
\r
441 my_log("POLYGLOT QUIT LOGGING\n");
\r
449 static void init_book(){
\r
451 if (option_get_bool(Option,"Book")){
\r
452 my_log("POLYGLOT *** SETTING BOOK ***\n");
\r
453 my_log("POLYGLOT BOOK \"%s\"\n",option_get_string(Option,"BookFile"));
\r
454 book_open(option_get_string(Option,"BookFile"));
\r
455 if(!book_is_open()){
\r
456 my_log("POLYGLOT Unable to open book \"%s\"\n",
\r
457 option_get_string(Option,"BookFile"));
\r
467 my_log("POLYGLOT *** QUIT ***\n");
\r
472 engine_send(Engine,"quit");
\r
473 my_log("POLYGLOT Closing engine\n");
\r
474 engine_close(Engine);
\r
477 if(option_get_bool(Option,"SaveSettingsOnExit")){
\r
478 write_ini(option_get_string(Option,"SaveFile"),Option,Uci->option);
\r
480 my_log("POLYGLOT Calling exit\n");
\r
481 exit(EXIT_SUCCESS);
\r
486 static void stop_search() {
\r
488 if (Init && Uci->searching) {
\r
490 ASSERT(Uci->searching);
\r
491 ASSERT(Uci->pending_nb>=1);
\r
493 my_log("POLYGLOT STOP SEARCH\n");
\r
495 if (option_get_bool(Option,"SyncStop")) {
\r
496 uci_send_stop_sync(Uci);
\r
498 uci_send_stop(Uci);
\r