-\r
-// main.c\r
-\r
-// includes\r
-\r
-#include <errno.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <time.h>\r
-\r
-#include "attack.h"\r
-#include "board.h"\r
-#include "book.h"\r
-#include "book_make.h"\r
-#include "book_merge.h"\r
-#include "engine.h"\r
-#include "epd.h"\r
-#include "fen.h"\r
-#include "gui.h"\r
-#include "hash.h"\r
-#include "list.h"\r
-#include "main.h"\r
-#include "mainloop.h"\r
-#include "move.h"\r
-#include "move_gen.h"\r
-#include "option.h"\r
-#include "piece.h"\r
-#include "search.h"\r
-#include "square.h"\r
-#include "uci.h"\r
-#include "util.h"\r
-#include "xboard2uci.h"\r
-#include "uci2uci.h"\r
-#include "ini.h"\r
-#include "util.h"\r
-\r
-\r
-// constants\r
-\r
-\r
-static const char * const Version = "1.4.52b";\r
-static const char * const HelpMessage = "\\r
-SYNTAX\n\\r
-* polyglot [configfile] [-noini] [-ec engine] [-ed enginedirectory] [-en enginename] [-log] [-lf logfile] [-hash value] [-bk book] [-pg <name>=<value>]* [-uci <name>=<value>]*\n\\r
-* polyglot make-book [-pgn inputfile] [-bin outputfile] [-max-ply ply] [-min-game games] [-min-score score] [-only-white] [-only-black] [-uniform]\n\\r
-* polyglot merge-book -in1 inputfile1 -in2 inputfile2 [-out outputfile]\n\\r
-* polyglot info-book [-bin inputfile] [-exact]\n\\r
-* polyglot dump-book [-bin inputfile] -color color [-out outputfile]\n\\r
-* polyglot [configfile] epd-test [engineoptions] [-epd inputfile] [-min-depth depth] [-max-depth depth] [-min-time time] [-max-time time] [-depth-delta delta]\n\\r
-* polyglot perft [-fen fen] [-max-depth depth]\\r
-";\r
-\r
-static const int SearchDepth = 63;\r
-static const double SearchTime = 3600.0;\r
-static const int StringSize = 4096;\r
-\r
-// variables\r
-\r
-static bool Init;\r
-\r
-// prototypes\r
-\r
-static void stop_search ();\r
-\r
-// functions\r
-\r
-// arg_shift_left()\r
-\r
-static void arg_shift_left(char **argv, int index){\r
- int i;\r
- for(i=index; argv[i]!=NULL; i++){\r
- argv[i]=argv[i+1];\r
- }\r
-}\r
-\r
-// parse_args()\r
-\r
-static void parse_args(ini_t *ini, char **argv){\r
- int arg_index;\r
- char *arg;\r
- arg_index=0;\r
- while((arg=argv[arg_index])){\r
- if(my_string_equal(arg,"-ec") && argv[arg_index+1]){\r
- ini_insert_ex(ini,"PolyGlot","EngineCommand",argv[arg_index+1]);\r
- arg_shift_left(argv,arg_index);\r
- arg_shift_left(argv,arg_index);\r
- continue;\r
- }if(my_string_equal(arg,"-ed") && argv[arg_index+1]){\r
- ini_insert_ex(ini,"PolyGlot","EngineDir",argv[arg_index+1]);\r
- arg_shift_left(argv,arg_index);\r
- arg_shift_left(argv,arg_index);\r
- continue;\r
- }\r
- if(my_string_equal(arg,"-en") && argv[arg_index+1]){\r
- ini_insert_ex(ini,"PolyGlot","EngineName",argv[arg_index+1]);\r
- arg_shift_left(argv,arg_index);\r
- arg_shift_left(argv,arg_index);\r
- continue;\r
- }\r
- if(my_string_equal(arg,"-log") &&\r
- argv[arg_index+1] &&\r
- IS_BOOL(argv[arg_index+1])){\r
- ini_insert_ex(ini,\r
- "PolyGlot",\r
- "Log",\r
- TO_BOOL(argv[arg_index+1])?"true":"false");\r
- arg_shift_left(argv,arg_index);\r
- arg_shift_left(argv,arg_index);\r
- continue;\r
- }\r
- if(my_string_equal(arg,"-lf") && argv[arg_index+1]){\r
- ini_insert_ex(ini,"PolyGlot","LogFile",argv[arg_index+1]);\r
- arg_shift_left(argv,arg_index);\r
- arg_shift_left(argv,arg_index);\r
- continue;\r
- }\r
- if(my_string_equal(arg,"-wb") &&\r
- argv[arg_index+1]&&\r
- IS_BOOL(argv[arg_index+1])){\r
- ini_insert_ex(ini,"PolyGlot",\r
- "OnlyWbOptions",\r
- TO_BOOL(argv[arg_index+1])?"true":"false");\r
- arg_shift_left(argv,arg_index);\r
- arg_shift_left(argv,arg_index);\r
- continue;\r
- }\r
- if((my_string_equal(arg,"-pg")||my_string_equal(arg,"-uci")) &&\r
- argv[arg_index+1]){\r
- int ret;\r
- char section[StringSize];\r
- char name[StringSize];\r
- char value[StringSize];\r
- ret=ini_line_parse(argv[arg_index+1],section,name,value);\r
- if(ret==NAME_VALUE){\r
- if(my_string_equal(arg,"-pg")){\r
- ini_insert_ex(ini,"PolyGlot",name,value);\r
- }else{\r
- ini_insert_ex(ini,"Engine",name,value);\r
- }\r
- }\r
- arg_shift_left(argv,arg_index);\r
- arg_shift_left(argv,arg_index);\r
- continue;\r
- }\r
- arg_index++;\r
- }\r
-}\r
-\r
-\r
-// make_ini()\r
-\r
-static void make_ini(ini_t *ini){\r
- option_t *opt;\r
- ini_insert_ex(ini,"polyglot",\r
- "EngineCommand",\r
- option_get(Option,"EngineCommand"));\r
- ini_insert_ex(ini,"polyglot",\r
- "EngineDir",\r
- option_get(Option,"EngineDir"));\r
- option_start_iter(Option);\r
- while((opt=option_next(Option))){\r
- if(my_string_case_equal(opt->name,"SettingsFile")) continue;\r
- if(my_string_case_equal(opt->name,"EngineCommand")) continue;\r
- if(my_string_case_equal(opt->name,"EngineDir")) continue;\r
- if(!my_string_equal(opt->value,opt->default_)&& !IS_BUTTON(opt->type))\r
- {\r
- ini_insert_ex(ini,"polyglot",opt->name,opt->value);\r
- }\r
- }\r
- option_start_iter(Uci->option);\r
- while((opt=option_next(Uci->option))){\r
- if(!strncmp(opt->name,"UCI_",4) &&\r
- !my_string_case_equal(opt->name,"UCI_LimitStrength") &&\r
- !my_string_case_equal(opt->name,"UCI_Elo"))continue;\r
- if(!my_string_equal(opt->value,opt->default_)&&\r
- !IS_BUTTON(opt->type)){\r
- ini_insert_ex(ini,"engine",opt->name,opt->value);\r
- }\r
- }\r
-}\r
-\r
-\r
-// write_ini()\r
-\r
-static void write_ini(const char *filename,\r
- ini_t *ini){\r
- const char *quote;\r
- ini_entry_t *entry;\r
- char tmp[StringSize];\r
- FILE *f;\r
- time_t t=time(NULL);\r
- f=fopen(filename,"w");\r
- if(!f){\r
- gui_send(GUI,"tellusererror write_ini(): %s: %s.",filename,strerror(errno));\r
- my_log("POLYGLOT write_ini(): %s: %s.\n",filename,strerror(errno));\r
- return;\r
- }\r
- fprintf(f,"; Created: %s\n",ctime(&t));\r
- fprintf(f,"[PolyGlot]\n");\r
- ini_start_iter(ini);\r
- while((entry=ini_next(ini))){\r
- if(my_string_case_equal(entry->section,"polyglot")){\r
- if(strchr(entry->value,';')|| strchr(entry->value,'#')|| strchr(entry->value,'"')){\r
- quote="\"";\r
- }else{\r
- quote="";\r
- }\r
- snprintf(tmp,sizeof(tmp),"%s=%s%s%s\n",\r
- entry->name,\r
- quote,\r
- entry->value,\r
- quote);\r
- tmp[sizeof(tmp)-1]='\0';\r
- fprintf(f,"%s",tmp);\r
- }\r
- }\r
- fprintf(f,"[Engine]\n");\r
- ini_start_iter(ini);\r
- while((entry=ini_next(ini))){\r
- if(my_string_case_equal(entry->section,"engine")){\r
- if(strchr(entry->value,';')|| strchr(entry->value,'#')|| strchr(entry->value,'"')){\r
- quote="\"";\r
- }else{\r
- quote="";\r
- }\r
- snprintf(tmp,sizeof(tmp),"%s=%s%s%s\n",\r
- entry->name,\r
- quote,\r
- entry->value,\r
- quote);\r
- tmp[sizeof(tmp)-1]='\0';\r
- fprintf(f,"%s",tmp);\r
- }\r
- }\r
- fclose(f);\r
-}\r
-\r
-// welcome_message()\r
-\r
-void welcome_message(char *buf){\r
- if(!DEBUG){\r
- sprintf(buf,\r
- "PolyGlot %s by Fabien Letouzey.\n",\r
- Version);\r
- }else{\r
- sprintf(buf,\r
- "PolyGlot %s by Fabien Letouzey (debug build).\n",\r
- Version);\r
- }\r
-}\r
-\r
-int wb_select(){\r
- option_t *opt;\r
- option_start_iter(Option);\r
- while((opt=option_next(Option))){\r
- opt->mode&=~XBOARD;\r
- if(opt->mode & XBSEL){\r
- opt->mode|=XBOARD; \r
- }\r
- }\r
-}\r
-\r
-// main()\r
-\r
-int main(int argc, char * argv[]) {\r
- ini_t ini[1], ini_command[1];\r
- ini_entry_t *entry;\r
- char *arg;\r
- int arg_index;\r
- bool NoIni;\r
- option_t *opt;\r
- char welcome[StringSize];\r
-\r
-\r
- welcome_message(welcome);\r
- \r
- printf("%s",welcome);\r
-\r
-\r
- 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
- printf("%s\n",HelpMessage);\r
- return EXIT_SUCCESS;\r
- }\r
-\r
- // init\r
-\r
- Init = FALSE;\r
-\r
- util_init();\r
- option_init_pg();\r
- \r
- square_init();\r
- piece_init();\r
- attack_init();\r
- \r
- hash_init();\r
-\r
- my_random_init();\r
-\r
- ini_init(ini);\r
- ini_init(ini_command);\r
-\r
- // book utilities: do not touch these\r
- \r
- if (argc >= 2 && my_string_equal(argv[1],"make-book")) {\r
- book_make(argc,argv);\r
- return EXIT_SUCCESS;\r
- }\r
- \r
- if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {\r
- book_merge(argc,argv);\r
- return EXIT_SUCCESS;\r
- }\r
-\r
- if (argc >= 2 && my_string_equal(argv[1],"dump-book")) {\r
- book_dump(argc,argv);\r
- return EXIT_SUCCESS;\r
- }\r
- \r
- if (argc >= 2 && my_string_equal(argv[1],"info-book")) {\r
- book_info(argc,argv);\r
- return EXIT_SUCCESS;\r
- }\r
-\r
- // perft\r
- \r
- if (argc >= 2 && my_string_equal(argv[1],"perft")) {\r
- do_perft(argc,argv);\r
- return EXIT_SUCCESS;\r
- }\r
- \r
- // What is the config file? This is very hacky right now.\r
-\r
- // Do we want a config file at all?\r
-\r
- arg_index=0;\r
- NoIni=FALSE;\r
- while((arg=argv[arg_index++])){\r
- if(my_string_equal(arg,"-noini")){\r
- NoIni=TRUE;\r
- break;\r
- }\r
- }\r
- arg_shift_left(argv,arg_index-1);\r
- parse_args(ini_command,argv+1);\r
- if(NoIni){\r
- option_set(Option,"SettingsFile","<empty>");\r
- }\r
-\r
- // Ok see if first argument looks like config file\r
- \r
- if(argv[1] && !my_string_equal(argv[1],"epd-test") && !(argv[1][0]=='-')){\r
- // first argument must be config file\r
- if(!NoIni){\r
- option_set(Option,"SettingsFile",argv[1]);\r
- }else{\r
- // ignore\r
- }\r
- arg_shift_left(argv,1);\r
- }else{\r
- // Config file is the default.\r
- // This has already been set above or in "option_init_pg()"\r
- }\r
-\r
-\r
-\r
- // if we use a config file: load it!\r
- \r
- if(!my_string_equal(option_get_string(Option,"SettingsFile"),"<empty>")){\r
- if(ini_parse(ini,option_get_string(Option,"SettingsFile"))){\r
- my_fatal("main(): Can't open file \"%s\": %s\n",\r
- option_get_string(Option,"SettingsFile"),\r
- strerror(errno));\r
- }\r
- }\r
-\r
- // Extract some important options\r
-\r
- if((entry=ini_find(ini,"polyglot","EngineCommand"))){\r
- option_set(Option,entry->name,entry->value);\r
- }\r
- if((entry=ini_find(ini,"polyglot","EngineDir"))){\r
- option_set(Option,entry->name,entry->value);\r
- }\r
- if((entry=ini_find(ini,"polyglot","EngineName"))){\r
- option_set(Option,entry->name,entry->value);\r
- }\r
- if((entry=ini_find(ini,"polyglot","Log"))){\r
- polyglot_set_option(entry->name,entry->value);\r
- }\r
- if((entry=ini_find(ini,"polyglot","LogFile"))){\r
- polyglot_set_option(entry->name,entry->value);\r
- }\r
- \r
- // Concession to WB 4.4.0\r
- // Treat "polyglot_1st.ini" and "polyglot_2nd.ini" specially\r
-\r
- if(option_get_bool(Option,"WbWorkArounds3")){\r
- const char *SettingsFile=option_get(Option,"SettingsFile");\r
- if(strstr(SettingsFile,"polyglot_1st.ini")||\r
- strstr(SettingsFile,"polyglot_2nd.ini")){\r
- option_set(Option,"SettingsFile","<empty>");\r
- }\r
- }\r
-\r
- // Look at command line for logging option. It is important\r
- // to start logging as soon as possible.\r
-\r
- if((entry=ini_find(ini_command,"PolyGlot","Log"))){\r
- option_set(Option,entry->name,entry->value);\r
- }\r
- if((entry=ini_find(ini_command,"PolyGlot","LogFile"))){\r
- option_set(Option,entry->name,entry->value);\r
- }\r
- \r
- // start logging if required\r
- \r
- if (option_get_bool(Option,"Log")) {\r
- my_log_open(option_get_string(Option,"LogFile"));\r
- }\r
-\r
- // log welcome stuff\r
- \r
- my_log("%s",welcome);\r
- my_log("POLYGLOT *** START ***\n");\r
- if(!my_string_equal(option_get_string(Option,"SettingsFile"),"<empty>")){\r
- my_log("POLYGLOT INI file \"%s\"\n",option_get_string(Option,"SettingsFile"));\r
- }\r
-\r
-\r
- // scavenge command line for options necessary to start the engine\r
-\r
-\r
- if((entry=ini_find(ini_command,"PolyGlot","EngineCommand"))){\r
- option_set(Option,entry->name,entry->value);\r
- }\r
- if((entry=ini_find(ini_command,"PolyGlot","EngineDir"))){\r
- option_set(Option,entry->name,entry->value);\r
- }\r
- if((entry=ini_find(ini_command,"PolyGlot","EngineName"))){\r
- option_set(Option,entry->name,entry->value);\r
- }\r
-\r
- // start engine\r
- \r
- engine_open(Engine);\r
- if(!engine_active(Engine)){\r
- my_fatal("Could not start \"%s\"\n",option_get(Option,"EngineCommand"));\r
- }\r
-\r
- // switch to UCI mode if necessary\r
- \r
- if (option_get_bool(Option,"UCI")) {\r
- my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
- }\r
-\r
- // initialize uci parsing and send uci command. \r
- // Parse options and wait for uciok\r
- \r
- uci_open(Uci,Engine);\r
-\r
- option_set_default(Option,"EngineName",Uci->name);\r
-\r
- // get engine name from engine if not supplied in config file or on\r
- // the command line\r
-\r
- if (my_string_equal(option_get_string(Option,"EngineName"),"<empty>")) {\r
- option_set(Option,"EngineName",Uci->name);\r
- }\r
-\r
-\r
- // In the case we have been invoked with NoIni or StandardIni\r
- // we still have to load a config file.\r
-\r
- if(my_string_equal(option_get_string(Option,"SettingsFile"),"<empty>")){\r
-\r
- // construct the name of the ConfigFile from the EngineName\r
- \r
- char tmp[StringSize];\r
- char option_file[StringSize];\r
- int i;\r
- snprintf(tmp,sizeof(tmp),"%s.ini",\r
- option_get_string(Option,"EngineName"));\r
- tmp[sizeof(tmp)-1]='\0';\r
- for(i=0;i<strlen(tmp);i++){\r
- if(tmp[i]==' '){\r
- tmp[i]='_';\r
- }\r
- }\r
- my_path_join(option_file,\r
- option_get_string(Option,"SettingsDir"),\r
- tmp);\r
- // Load the config file\r
- option_set(Option,"SettingsFile",option_file);\r
-\r
- my_log("POLYGLOT INI file \"%s\"\n",option_get_string(Option,"SettingsFile"));\r
- if(ini_parse(ini,option_file)){\r
- my_log("POLYGLOT Unable to open %s\n",\r
- option_get_string(Option,"SettingsFile")); \r
- }\r
- }\r
-\r
-\r
- // Parse the command line and merge remaining options.\r
-\r
- ini_start_iter(ini_command);\r
- while((entry=ini_next(ini_command))){\r
- ini_insert(ini,entry);\r
- }\r
-\r
- // Remind the reader about the options that are now in effect.\r
-\r
- my_log("POLYGLOG OPTIONS \n");\r
- ini_disp(ini);\r
-\r
- // extract PG options\r
- \r
- ini_start_iter(ini);\r
- while((entry=ini_next(ini))){\r
- if(my_string_case_equal(entry->section,"polyglot")){\r
- opt=option_find(Option,entry->name);\r
- if(opt && !IS_BUTTON(opt->type)){\r
- polyglot_set_option(entry->name,entry->value);\r
- }\r
- }\r
- }\r
-\r
- // Cater to our biggest customer:-)\r
- \r
- if(option_get_bool(Option,"OnlyWbOptions")){\r
- wb_select();\r
- }\r
-\r
- // done initializing\r
- \r
- Init = TRUE;\r
- \r
- // collect engine options from config file(s) and send to engine\r
- \r
- ini_start_iter(ini);\r
- while((entry=ini_next(ini))){\r
- if(my_string_case_equal(entry->section,"engine")){\r
- // also updates value in Uci->option\r
- uci_send_option(Uci,entry->name,"%s",entry->value);\r
- // this is inherited, it probably does not work correctly\r
- if(my_string_case_equal(entry->name,"MultiPV") &&\r
- atoi(entry->value)>1){\r
- Uci->multipv_mode=TRUE;\r
- }\r
- }\r
- }\r
-\r
- \r
- \r
- // EPD test\r
- \r
- if (argv[1] && my_string_equal(argv[1],"epd-test")){\r
- argc=0;\r
- while((arg=argv[argc++]));\r
- epd_test(argc-1,argv);\r
- return EXIT_SUCCESS;\r
- }\r
- \r
- // Anything that hasn't been parsed yet is a syntax error\r
- // It seems that XBoard sometimes passes empty strings as arguments\r
- // to PolyGlot. We ignore these. \r
-\r
- argc=1;\r
- while((arg=argv[argc++])){\r
- if(!my_string_equal(arg,"")){\r
- my_fatal("main(): Option: \"%s\" not found\n",argv[argc-1]);\r
- }\r
- }\r
-\r
- gui_init(GUI);\r
- mainloop();\r
- return EXIT_SUCCESS; \r
-}\r
-\r
-// polyglot_set_option()\r
-\r
-void polyglot_set_option(const char *name, const char *value){ // this must be cleaned up!\r
- ini_t ini[1];\r
- int ret;\r
- ini_init(ini);\r
- my_log("POLYGLOT Setting PolyGlot option %s=\"%s\"\n",name,value);\r
- if(my_string_case_equal(name,"Save")){\r
- ret=my_mkdir(option_get(Option,"SettingsDir"));\r
- if(ret){\r
- my_log("POLYGLOT polyglot_set_option(): %s: %s\n",\r
- option_get(Option,"SettingsDir"),\r
- strerror(errno));\r
- }\r
- make_ini(ini);\r
- write_ini(option_get(Option,"SettingsFile"),ini);\r
- return;\r
- }\r
-// if(my_string_equal(option_get(Option,name),value)){\r
-// my_log("Not setting PolyGlot option \"%s\" "\r
-// "since it already as the correct value.\n",\r
-// name);\r
-// return;\r
-// }\r
- option_set(Option,name,value);\r
- if(option_get_bool(Option,"Book")&&(my_string_case_equal(name,"BookFile")||my_string_case_equal(name,"Book"))){\r
- my_log("POLYGLOT *** SETTING BOOK ***\n");\r
- my_log("POLYGLOT BOOK \"%s\"\n",option_get_string(Option,"BookFile"));\r
- book_close();\r
- book_clear();\r
- book_open(option_get_string(Option,"BookFile"));\r
- if(!book_is_open()){\r
- my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string(Option,"BookFile"));\r
- }\r
- }else if(option_get_bool(Option,"Log")&&(my_string_case_equal(name,"LogFile") ||my_string_case_equal(name,"Log"))){\r
- my_log("POLYGLOT *** SWITCHING LOGFILE ***\n");\r
- my_log("POLYGLOT NEW LOGFILE \"%s\"\n",option_get_string(Option,"LogFile"));\r
- my_log_close();\r
- my_log_open(option_get_string(Option,"LogFile"));\r
- }else if(option_get_bool(Option,"UseNice") &&(my_string_case_equal(name,"NiceValue")||my_string_case_equal(name,"UseNice"))){\r
- my_log("POLYGLOT Adjust Engine Piority\n");\r
- engine_set_nice_value(Engine,atoi(option_get_string(Option,"NiceValue")));\r
- }else if(my_string_case_equal(name,"Book") && !option_get_bool(Option,"Book")){\r
- book_close();\r
- book_clear();\r
- }else if(my_string_case_equal(name,"UseNice") && !option_get_bool(Option,"UseNice")){\r
- my_log("POLYGLOT Adjust Engine Piority\n");\r
- engine_set_nice_value(Engine,0);\r
- }else if(my_string_case_equal(name,"Log") && !option_get_bool(Option,"Log")){\r
- my_log("POLYGLOT QUIT LOGGING\n");\r
- my_log_close();\r
- }\r
-}\r
-\r
-\r
-\r
-// quit()\r
-\r
-void quit() {\r
-\r
- my_log("POLYGLOT *** QUIT ***\n");\r
- \r
- if (Init) {\r
- \r
- stop_search();\r
- engine_send(Engine,"quit");\r
- my_log("POLYGLOT Closing engine\n");\r
- engine_close(Engine);\r
- \r
- }\r
- my_log("POLYGLOT Calling exit\n");\r
- exit(EXIT_SUCCESS);\r
-}\r
-\r
-// stop_search()\r
-\r
-static void stop_search() {\r
- \r
- if (Init && Uci->searching) {\r
- \r
- ASSERT(Uci->searching);\r
- ASSERT(Uci->pending_nb>=1);\r
- \r
- my_log("POLYGLOT STOP SEARCH\n");\r
- \r
- if (option_get_bool(Option,"SyncStop")) {\r
- uci_send_stop_sync(Uci);\r
- } else {\r
- uci_send_stop(Uci);\r
- }\r
- }\r
-}\r
-\r
-\r
-// end of main.c\r
-\r
+
+// main.c
+
+// includes
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "attack.h"
+#include "board.h"
+#include "book.h"
+#include "book_make.h"
+#include "book_merge.h"
+#include "engine.h"
+#include "epd.h"
+#include "fen.h"
+#include "gui.h"
+#include "hash.h"
+#include "list.h"
+#include "main.h"
+#include "mainloop.h"
+#include "move.h"
+#include "move_gen.h"
+#include "option.h"
+#include "piece.h"
+#include "search.h"
+#include "square.h"
+#include "uci.h"
+#include "util.h"
+#include "xboard2uci.h"
+#include "uci2uci.h"
+#include "ini.h"
+#include "util.h"
+
+
+// constants
+
+
+static const char * const Version = "1.4.70b";
+static const char * const HelpMessage = "\
+SYNTAX\n\
+* polyglot [configfile] [-noini] [-ec engine] [-ed enginedirectory] [-en enginename] [-log true/false] [-lf logfile] [-pg <name>=<value>]* [-uci <name>=<value>]*\n\
+* polyglot make-book [-pgn inputfile] [-bin outputfile] [-max-ply ply] [-min-game games] [-min-score score] [-only-white] [-only-black] [-uniform]\n\
+* polyglot merge-book -in1 inputfile1 -in2 inputfile2 [-out outputfile]\n\
+* polyglot info-book [-bin inputfile] [-exact]\n\
+* polyglot dump-book [-bin inputfile] -color color [-out outputfile]\n\
+* polyglot [configfile] epd-test [engineoptions] [-epd inputfile] [-min-depth depth] [-max-depth depth] [-min-time time] [-max-time time] [-depth-delta delta]\n\
+* polyglot perft [-fen fen] [-max-depth depth]\
+";
+
+static const int SearchDepth = 63;
+static const double SearchTime = 3600.0;
+
+// variables
+
+static bool Init;
+
+// prototypes
+
+static void stop_search ();
+
+// functions
+
+// arg_shift_left()
+
+static void arg_shift_left(char **argv, int index){
+ int i;
+ for(i=index; argv[i]!=NULL; i++){
+ argv[i]=argv[i+1];
+ }
+}
+
+// parse_args()
+
+static void parse_args(ini_t *ini, char **argv){
+ int arg_index;
+ char *arg;
+ arg_index=0;
+ while((arg=argv[arg_index])){
+ if(my_string_equal(arg,"-ec") && argv[arg_index+1]){
+ ini_insert_ex(ini,"PolyGlot","EngineCommand",argv[arg_index+1]);
+ arg_shift_left(argv,arg_index);
+ arg_shift_left(argv,arg_index);
+ continue;
+ }if(my_string_equal(arg,"-ed") && argv[arg_index+1]){
+ ini_insert_ex(ini,"PolyGlot","EngineDir",argv[arg_index+1]);
+ arg_shift_left(argv,arg_index);
+ arg_shift_left(argv,arg_index);
+ continue;
+ }
+ if(my_string_equal(arg,"-en") && argv[arg_index+1]){
+ ini_insert_ex(ini,"PolyGlot","EngineName",argv[arg_index+1]);
+ arg_shift_left(argv,arg_index);
+ arg_shift_left(argv,arg_index);
+ continue;
+ }
+ if(my_string_equal(arg,"-log") &&
+ argv[arg_index+1] &&
+ IS_BOOL(argv[arg_index+1])){
+ ini_insert_ex(ini,
+ "PolyGlot",
+ "Log",
+ TO_BOOL(argv[arg_index+1])?"true":"false");
+ arg_shift_left(argv,arg_index);
+ arg_shift_left(argv,arg_index);
+ continue;
+ }
+ if(my_string_equal(arg,"-lf") && argv[arg_index+1]){
+ ini_insert_ex(ini,"PolyGlot","LogFile",argv[arg_index+1]);
+ arg_shift_left(argv,arg_index);
+ arg_shift_left(argv,arg_index);
+ continue;
+ }
+ if(my_string_equal(arg,"-wb") &&
+ argv[arg_index+1]&&
+ IS_BOOL(argv[arg_index+1])){
+ ini_insert_ex(ini,"PolyGlot",
+ "OnlyWbOptions",
+ TO_BOOL(argv[arg_index+1])?"true":"false");
+ arg_shift_left(argv,arg_index);
+ arg_shift_left(argv,arg_index);
+ continue;
+ }
+ if((my_string_equal(arg,"-pg")||my_string_equal(arg,"-uci")) &&
+ argv[arg_index+1]){
+ int ret;
+ char section[StringSize];
+ char name[StringSize];
+ char value[StringSize];
+ ret=ini_line_parse(argv[arg_index+1],section,name,value);
+ if(ret==NAME_VALUE){
+ if(my_string_equal(arg,"-pg")){
+ ini_insert_ex(ini,"PolyGlot",name,value);
+ }else{
+ ini_insert_ex(ini,"Engine",name,value);
+ }
+ }
+ arg_shift_left(argv,arg_index);
+ arg_shift_left(argv,arg_index);
+ continue;
+ }
+ arg_index++;
+ }
+}
+
+
+// make_ini()
+
+static void make_ini(ini_t *ini){
+ option_t *opt;
+ ini_insert_ex(ini,"polyglot",
+ "EngineCommand",
+ option_get(Option,"EngineCommand"));
+ ini_insert_ex(ini,"polyglot",
+ "EngineDir",
+ option_get(Option,"EngineDir"));
+ option_start_iter(Option);
+ while((opt=option_next(Option))){
+ if(my_string_case_equal(opt->name,"SettingsFile")) continue;
+ if(my_string_case_equal(opt->name,"EngineCommand")) continue;
+ if(my_string_case_equal(opt->name,"EngineDir")) continue;
+ if(!my_string_equal(opt->value,opt->default_)&& !IS_BUTTON(opt->type))
+ {
+ ini_insert_ex(ini,"polyglot",opt->name,opt->value);
+ }
+ }
+ option_start_iter(Uci->option);
+ while((opt=option_next(Uci->option))){
+ if(!strncmp(opt->name,"UCI_",4) &&
+ !my_string_case_equal(opt->name,"UCI_LimitStrength") &&
+ !my_string_case_equal(opt->name,"UCI_Elo"))continue;
+ if(!my_string_equal(opt->value,opt->default_)&&
+ !IS_BUTTON(opt->type)){
+ ini_insert_ex(ini,"engine",opt->name,opt->value);
+ }
+ }
+}
+
+
+// write_ini()
+
+static void write_ini(const char *filename,
+ ini_t *ini){
+ // TODO Quote, dequote
+ const char *quote;
+ ini_entry_t *entry;
+ char tmp[StringSize];
+ char tmp1[StringSize];
+ char tmp2[StringSize];
+ FILE *f;
+ time_t t=time(NULL);
+ f=fopen(filename,"w");
+ if(!f){
+ gui_send(GUI,"tellusererror write_ini(): %s: %s.",filename,strerror(errno));
+ my_log("POLYGLOT write_ini(): %s: %s.\n",filename,strerror(errno));
+ return;
+ }
+ fprintf(f,"; Created: %s\n",ctime(&t));
+ fprintf(f,"[PolyGlot]\n");
+ ini_start_iter(ini);
+ while((entry=ini_next(ini))){
+ if(my_string_case_equal(entry->section,"polyglot")){
+ my_quote(tmp1,entry->name,ini_specials);
+ my_quote(tmp2,entry->value,ini_specials);
+ snprintf(tmp,sizeof(tmp),"%s=%s\n",
+ tmp1,
+ tmp2);
+ tmp[sizeof(tmp)-1]='\0';
+ fprintf(f,"%s",tmp);
+ }
+ }
+ fprintf(f,"[Engine]\n");
+ ini_start_iter(ini);
+ while((entry=ini_next(ini))){
+ if(my_string_case_equal(entry->section,"engine")){
+ my_quote(tmp1,entry->name,ini_specials);
+ my_quote(tmp2,entry->value,ini_specials);
+ snprintf(tmp,sizeof(tmp),"%s=%s\n",
+ tmp1,
+ tmp2);
+ tmp[sizeof(tmp)-1]='\0';
+ fprintf(f,"%s",tmp);
+ }
+ }
+ fclose(f);
+}
+
+// welcome_message()
+
+void welcome_message(char *buf){
+ if(!DEBUG){
+ sprintf(buf,
+ "PolyGlot %s by Fabien Letouzey.\n",
+ Version);
+ }else{
+ sprintf(buf,
+ "PolyGlot %s by Fabien Letouzey (debug build).\n",
+ Version);
+ }
+}
+
+int wb_select(){
+ option_t *opt;
+ option_start_iter(Option);
+ while((opt=option_next(Option))){
+ opt->mode&=~XBOARD;
+ if(opt->mode & XBSEL){
+ opt->mode|=XBOARD;
+ }
+ }
+}
+
+// main()
+
+int main(int argc, char * argv[]) {
+ ini_t ini[1], ini_command[1];
+ ini_entry_t *entry;
+ char *arg;
+ int arg_index;
+ bool NoIni;
+ option_t *opt;
+ char welcome[StringSize];
+
+
+ welcome_message(welcome);
+
+ printf("%s",welcome);
+
+
+ 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],"/?"))){
+ printf("%s\n",HelpMessage);
+ return EXIT_SUCCESS;
+ }
+
+ // init
+
+ Init = FALSE;
+
+ gui_init(GUI);
+
+ util_init();
+ option_init_pg();
+
+ square_init();
+ piece_init();
+ attack_init();
+
+ hash_init();
+
+ my_random_init();
+
+ ini_init(ini);
+ ini_init(ini_command);
+
+ // book utilities: do not touch these
+
+ if (argc >= 2 && my_string_equal(argv[1],"make-book")) {
+ book_make(argc,argv);
+ return EXIT_SUCCESS;
+ }
+
+ if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {
+ book_merge(argc,argv);
+ return EXIT_SUCCESS;
+ }
+
+ if (argc >= 2 && my_string_equal(argv[1],"dump-book")) {
+ book_dump(argc,argv);
+ return EXIT_SUCCESS;
+ }
+
+ if (argc >= 2 && my_string_equal(argv[1],"info-book")) {
+ book_info(argc,argv);
+ return EXIT_SUCCESS;
+ }
+
+ // perft
+
+ if (argc >= 2 && my_string_equal(argv[1],"perft")) {
+ do_perft(argc,argv);
+ return EXIT_SUCCESS;
+ }
+
+ // What is the config file? This is very hacky right now.
+
+ // Do we want a config file at all?
+
+ arg_index=0;
+ NoIni=FALSE;
+ while((arg=argv[arg_index++])){
+ if(my_string_equal(arg,"-noini")){
+ NoIni=TRUE;
+ break;
+ }
+ }
+ arg_shift_left(argv,arg_index-1);
+ parse_args(ini_command,argv+1);
+ if(NoIni){
+ option_set(Option,"SettingsFile","<empty>");
+ }
+
+ // Ok see if first argument looks like config file
+
+ if(argv[1] && !my_string_equal(argv[1],"epd-test") && !(argv[1][0]=='-')){
+ // first argument must be config file
+ if(!NoIni){
+ option_set(Option,"SettingsFile",argv[1]);
+ }else{
+ // ignore
+ }
+ arg_shift_left(argv,1);
+ }else{
+ // Config file is the default.
+ // This has already been set above or in "option_init_pg()"
+ }
+
+
+
+ // if we use a config file: load it!
+
+ if(!my_string_equal(option_get_string(Option,"SettingsFile"),"<empty>")){
+ if(ini_parse(ini,option_get_string(Option,"SettingsFile"))){
+ my_fatal("main(): Can't open config file \"%s\": %s\n",
+ option_get_string(Option,"SettingsFile"),
+ strerror(errno));
+ }
+ }
+
+ // Extract some important options
+
+ if((entry=ini_find(ini,"polyglot","EngineCommand"))){
+ option_set(Option,entry->name,entry->value);
+ }
+ if((entry=ini_find(ini,"polyglot","EngineDir"))){
+ option_set(Option,entry->name,entry->value);
+ }
+ if((entry=ini_find(ini,"polyglot","EngineName"))){
+ option_set(Option,entry->name,entry->value);
+ }
+ if((entry=ini_find(ini,"polyglot","Log"))){
+ polyglot_set_option(entry->name,entry->value);
+ }
+ if((entry=ini_find(ini,"polyglot","LogFile"))){
+ polyglot_set_option(entry->name,entry->value);
+ }
+
+ // Concession to WB 4.4.0
+ // Treat "polyglot_1st.ini" and "polyglot_2nd.ini" specially
+
+ if(option_get_bool(Option,"WbWorkArounds3")){
+ const char *SettingsFile=option_get(Option,"SettingsFile");
+ if(strstr(SettingsFile,"polyglot_1st.ini")||
+ strstr(SettingsFile,"polyglot_2nd.ini")){
+ option_set(Option,"SettingsFile","<empty>");
+ }
+ }
+
+ // Look at command line for logging option. It is important
+ // to start logging as soon as possible.
+
+ if((entry=ini_find(ini_command,"PolyGlot","Log"))){
+ option_set(Option,entry->name,entry->value);
+ }
+ if((entry=ini_find(ini_command,"PolyGlot","LogFile"))){
+ option_set(Option,entry->name,entry->value);
+ }
+
+ // start logging if required
+
+ if (option_get_bool(Option,"Log")) {
+ my_log_open(option_get_string(Option,"LogFile"));
+ }
+
+ // log welcome stuff
+
+ my_log("%s",welcome);
+ my_log("POLYGLOT *** START ***\n");
+ if(!my_string_equal(option_get_string(Option,"SettingsFile"),"<empty>")){
+ my_log("POLYGLOT INI file \"%s\"\n",option_get_string(Option,"SettingsFile"));
+ }
+
+
+ // scavenge command line for options necessary to start the engine
+
+
+ if((entry=ini_find(ini_command,"PolyGlot","EngineCommand"))){
+ option_set(Option,entry->name,entry->value);
+ }
+ if((entry=ini_find(ini_command,"PolyGlot","EngineDir"))){
+ option_set(Option,entry->name,entry->value);
+ }
+ if((entry=ini_find(ini_command,"PolyGlot","EngineName"))){
+ option_set(Option,entry->name,entry->value);
+ }
+
+ // Make sure that EngineCommand has been set
+ if(my_string_case_equal(option_get(Option,"EngineCommand"),"<empty>")){
+ my_fatal("main(): EngineCommand not set\n");
+ }
+
+ // start engine
+
+ engine_open(Engine);
+
+ if(!engine_active(Engine)){
+ my_fatal("main(): Could not start \"%s\"\n",option_get(Option,"EngineCommand"));
+ }
+
+ // switch to UCI mode if necessary
+
+ if (option_get_bool(Option,"UCI")) {
+ my_log("POLYGLOT *** Switching to UCI mode ***\n");
+ }
+
+ // initialize uci parsing and send uci command.
+ // Parse options and wait for uciok
+
+ // XXX
+ uci_open(Uci,Engine);
+
+ option_set_default(Option,"EngineName",Uci->name);
+
+ // get engine name from engine if not supplied in config file or on
+ // the command line
+
+ if (my_string_equal(option_get_string(Option,"EngineName"),"<empty>")) {
+ option_set(Option,"EngineName",Uci->name);
+ }
+
+
+ // In the case we have been invoked with NoIni or StandardIni
+ // we still have to load a config file.
+
+ if(my_string_equal(option_get_string(Option,"SettingsFile"),"<empty>")){
+
+ // construct the name of the ConfigFile from the EngineName
+
+ char tmp[StringSize];
+ char option_file[StringSize];
+ int i;
+ snprintf(tmp,sizeof(tmp),"%s.ini",
+ option_get_string(Option,"EngineName"));
+ tmp[sizeof(tmp)-1]='\0';
+ for(i=0;i<strlen(tmp);i++){
+ if(tmp[i]==' '){
+ tmp[i]='_';
+ }
+ }
+ my_path_join(option_file,
+ option_get_string(Option,"SettingsDir"),
+ tmp);
+ // Load the config file
+ option_set(Option,"SettingsFile",option_file);
+
+ my_log("POLYGLOT INI file \"%s\"\n",option_get_string(Option,"SettingsFile"));
+ if(ini_parse(ini,option_file)){
+ my_log("POLYGLOT Unable to open %s\n",
+ option_get_string(Option,"SettingsFile"));
+ }
+ }
+
+
+ // Parse the command line and merge remaining options.
+
+ ini_start_iter(ini_command);
+ while((entry=ini_next(ini_command))){
+ ini_insert(ini,entry);
+ }
+
+ // Remind the reader about the options that are now in effect.
+
+ my_log("POLYGLOG OPTIONS \n");
+ ini_disp(ini);
+
+ // extract PG options
+
+ ini_start_iter(ini);
+ while((entry=ini_next(ini))){
+ if(my_string_case_equal(entry->section,"polyglot")){
+ opt=option_find(Option,entry->name);
+ if(opt && !IS_BUTTON(opt->type)){
+ polyglot_set_option(entry->name,entry->value);
+ }
+ }
+ }
+
+ // Cater to our biggest customer:-)
+
+ if(option_get_bool(Option,"OnlyWbOptions")){
+ wb_select();
+ }
+
+ // done initializing
+
+ Init = TRUE;
+
+ // collect engine options from config file(s) and send to engine
+
+ ini_start_iter(ini);
+ while((entry=ini_next(ini))){
+ if(my_string_case_equal(entry->section,"engine")){
+ // also updates value in Uci->option
+ uci_send_option(Uci,entry->name,"%s",entry->value);
+ }
+ }
+
+
+
+ // EPD test
+
+ if (argv[1] && my_string_equal(argv[1],"epd-test")){
+ argc=0;
+ while((arg=argv[argc++]));
+ epd_test(argc-1,argv);
+ return EXIT_SUCCESS;
+ }
+
+ // Anything that hasn't been parsed yet is a syntax error
+ // It seems that XBoard sometimes passes empty strings as arguments
+ // to PolyGlot. We ignore these.
+
+ argc=1;
+ while((arg=argv[argc++])){
+ if(!my_string_equal(arg,"")){
+ my_fatal("main(): Incorrect use of option: \"%s\"\n",argv[argc-1]);
+ }
+ }
+
+ // gui_init(GUI);
+ mainloop();
+ return EXIT_SUCCESS;
+}
+
+// polyglot_set_option()
+
+void polyglot_set_option(const char *name, const char *value){ // this must be cleaned up!
+ ini_t ini[1];
+ int ret;
+ ini_init(ini);
+ my_log("POLYGLOT Setting PolyGlot option \"%s=%s\"\n",name,value);
+ if(my_string_case_equal(name,"Save")){
+ ret=my_mkdir(option_get(Option,"SettingsDir"));
+ if(ret){
+ my_log("POLYGLOT polyglot_set_option(): %s: %s\n",
+ option_get(Option,"SettingsDir"),
+ strerror(errno));
+ }
+ make_ini(ini);
+ write_ini(option_get(Option,"SettingsFile"),ini);
+ return;
+ }
+// if(my_string_equal(option_get(Option,name),value)){
+// my_log("Not setting PolyGlot option \"%s\" "
+// "since it already as the correct value.\n",
+// name);
+// return;
+// }
+ option_set(Option,name,value);
+ if(option_get_bool(Option,"Book")&&(my_string_case_equal(name,"BookFile")||my_string_case_equal(name,"Book"))){
+ my_log("POLYGLOT *** SETTING BOOK ***\n");
+ my_log("POLYGLOT BOOK \"%s\"\n",option_get_string(Option,"BookFile"));
+ book_close();
+ book_clear();
+ book_open(option_get_string(Option,"BookFile"));
+ if(!book_is_open()){
+ my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string(Option,"BookFile"));
+ }
+ }else if(option_get_bool(Option,"Log")&&(my_string_case_equal(name,"LogFile") ||my_string_case_equal(name,"Log"))){
+ my_log("POLYGLOT *** SWITCHING LOGFILE ***\n");
+ my_log("POLYGLOT NEW LOGFILE \"%s\"\n",option_get_string(Option,"LogFile"));
+ my_log_close();
+ my_log_open(option_get_string(Option,"LogFile"));
+ }else if(option_get_bool(Option,"UseNice") &&(my_string_case_equal(name,"NiceValue")||my_string_case_equal(name,"UseNice"))){
+ my_log("POLYGLOT Adjust Engine Piority\n");
+ engine_set_nice_value(Engine,atoi(option_get_string(Option,"NiceValue")));
+ }else if(my_string_case_equal(name,"Book") && !option_get_bool(Option,"Book")){
+ book_close();
+ book_clear();
+ }else if(my_string_case_equal(name,"UseNice") && !option_get_bool(Option,"UseNice")){
+ my_log("POLYGLOT Adjust Engine Piority\n");
+ engine_set_nice_value(Engine,0);
+ }else if(my_string_case_equal(name,"Log") && !option_get_bool(Option,"Log")){
+ my_log("POLYGLOT QUIT LOGGING\n");
+ my_log_close();
+ }
+}
+
+
+
+// quit()
+
+void quit() {
+ my_log("POLYGLOT *** QUIT ***\n");
+ if (Init && !Engine->pipex->quit_pending) {
+ stop_search();
+ Engine->pipex->quit_pending=TRUE;
+ engine_send(Engine,"quit");
+ engine_close(Engine);
+
+ }
+ my_sleep(200);
+ my_log("POLYGLOT Calling exit\n");
+ exit(EXIT_SUCCESS);
+}
+
+// stop_search()
+
+static void stop_search() {
+
+ if (Init && Uci->searching) {
+
+ ASSERT(Uci->searching);
+ ASSERT(Uci->pending_nb>=1);
+
+ my_log("POLYGLOT STOP SEARCH\n");
+
+ if (option_get_bool(Option,"SyncStop")) {
+ uci_send_stop_sync(Uci);
+ } else {
+ uci_send_stop(Uci);
+ }
+ }
+}
+
+
+// end of main.c
+