version 1.4.45b
[polyglot.git] / main.c
1 \r
2 // main.c\r
3 \r
4 // includes\r
5 \r
6 #include <errno.h>\r
7 #include <stdio.h>\r
8 #include <stdlib.h>\r
9 #include <string.h>\r
10 #include <time.h>\r
11 \r
12 #include "attack.h"\r
13 #include "board.h"\r
14 #include "book.h"\r
15 #include "book_make.h"\r
16 #include "book_merge.h"\r
17 #include "engine.h"\r
18 #include "epd.h"\r
19 #include "fen.h"\r
20 #include "gui.h"\r
21 #include "hash.h"\r
22 #include "list.h"\r
23 #include "main.h"\r
24 #include "mainloop.h"\r
25 #include "move.h"\r
26 #include "move_gen.h"\r
27 #include "option.h"\r
28 #include "piece.h"\r
29 #include "search.h"\r
30 #include "square.h"\r
31 #include "uci.h"\r
32 #include "util.h"\r
33 #include "xboard2uci.h"\r
34 #include "uci2uci.h"\r
35 #include "ini.h"\r
36 #include "util.h"\r
37 \r
38 \r
39 // constants\r
40 \r
41 \r
42 static const char * const Version = "1.4.45b";\r
43 static const char * const HelpMessage = "\\r
44 SYNTAX\n\\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
52 ";\r
53 \r
54 static const int SearchDepth = 63;\r
55 static const double SearchTime = 3600.0;\r
56 static const int StringSize = 4096;\r
57 \r
58 static const char * const IniIntro=\r
59               "; This ini file is used internally by PolyGlot\n"\r
60               "; to remember the settings for the UCI engine\n"\r
61               "; whose name is \"%s\".\n"\r
62               "\n"\r
63               "; The values for these settings would be typicallly\n"\r
64               "; obtained from the engine settings dialog\n"\r
65               "; in WinBoard/xboard 4.4.0 and higher.\n"\r
66               "\n" \r
67               "; It is allowed to manually edit this file\n"\r
68               "; and you may safely delete it as well.\n"\r
69               "\n";\r
70 \r
71 // variables\r
72 \r
73 static bool Init;\r
74 \r
75 // prototypes\r
76 \r
77 static void init_book ();\r
78 static void stop_search  ();\r
79 \r
80 // functions\r
81 \r
82 // arg_shift_left()\r
83 \r
84 static void arg_shift_left(char **argv, int index){\r
85     int i;\r
86     for(i=index; argv[i]!=NULL; i++){\r
87         argv[i]=argv[i+1];\r
88     }\r
89 }\r
90 \r
91 // write_ini()\r
92 \r
93 static void write_ini(const char *filename,\r
94                       option_list_t *pg_options,\r
95                       option_list_t *uci_options){\r
96     option_t *opt;\r
97     char tmp[StringSize];\r
98     FILE *f;\r
99     time_t t=time(NULL);\r
100     f=fopen(filename,"w");\r
101     if(!f){\r
102       // alas this does nothing....\r
103       gui_send(GUI,"tellusererror write_ini(): %s: %s.",filename,strerror(errno));\r
104       // but at least we log the error\r
105       my_log("POLYGLOT write_ini(): %s: %s.\n",filename,strerror(errno));\r
106       return;\r
107     }\r
108     fprintf(f,"; %s\n",ctime(&t));\r
109     fprintf(f,IniIntro,option_get_string(Option,"EngineName"));\r
110     fprintf(f,"[PolyGlot]\n");\r
111     fprintf(f,"EngineName=%s\n",\r
112             option_get_string(Option,"EngineName"));\r
113     fprintf(f,"EngineCommand=%s\n",\r
114             option_get_string(Option,"EngineCommand"));\r
115     fprintf(f,"EngineDir=%s\n",\r
116             option_get_string(Option,"EngineDir"));\r
117     option_start_iter(pg_options);\r
118     while((opt=option_next(pg_options))){\r
119         if(!my_string_equal(opt->value,opt->default_)&&\r
120            !IS_BUTTON(opt) &&\r
121            (opt->mode & XBOARD)){\r
122             snprintf(tmp,sizeof(tmp),"%s=%s\n",opt->name,opt->value);\r
123             tmp[sizeof(tmp)-1]='\0';\r
124             fprintf(f,"%s",tmp);\r
125         }\r
126     }\r
127     fprintf(f,"[Engine]\n");\r
128     option_start_iter(uci_options);\r
129     while((opt=option_next(uci_options))){\r
130         if(!my_string_equal(opt->value,opt->default_)&&\r
131            !IS_BUTTON(opt)){\r
132             snprintf(tmp,sizeof(tmp),"%s=%s\n",opt->name,opt->value);\r
133             tmp[sizeof(tmp)-1]='\0';\r
134             fprintf(f,"%s",tmp);\r
135         }\r
136     }\r
137     fclose(f);\r
138 }\r
139 \r
140 // write_ini_ex()\r
141 \r
142 static void write_ini_ex(const char *filename,\r
143                          ini_t *ini){\r
144     ini_entry_t *entry;\r
145     char tmp[StringSize];\r
146     FILE *f;\r
147     time_t t=time(NULL);\r
148     f=fopen(filename,"w");\r
149     if(!f){\r
150       // alas this does nothing....\r
151       gui_send(GUI,"tellusererror write_ini(): %s: %s.",filename,strerror(errno));\r
152       // but at least we log the error\r
153       my_log("POLYGLOT write_ini(): %s: %s.\n",filename,strerror(errno));\r
154       return;\r
155     }\r
156     fprintf(f,"; %s\n",ctime(&t));\r
157     fprintf(f,IniIntro,option_get_string(Option,"EngineName"));\r
158     fprintf(f,"[PolyGlot]\n");\r
159     fprintf(f,"EngineName=%s\n",\r
160             option_get_string(Option,"EngineName"));\r
161     fprintf(f,"EngineCommand=%s\n",\r
162             option_get_string(Option,"EngineCommand"));\r
163     fprintf(f,"EngineDir=%s\n",\r
164             option_get_string(Option,"EngineDir"));\r
165     ini_start_iter(ini);\r
166     while((entry=ini_next(ini))){\r
167       if(my_string_case_equal(entry->section,"polyglot")){\r
168         snprintf(tmp,sizeof(tmp),"%s=%s\n",\r
169                  entry->name,\r
170                  entry->value);\r
171         tmp[sizeof(tmp)-1]='\0';\r
172         fprintf(f,"%s",tmp);\r
173       }\r
174     }\r
175     fprintf(f,"[Engine]\n");\r
176     ini_start_iter(ini);\r
177     while((entry=ini_next(ini))){\r
178       if(my_string_case_equal(entry->section,"engine")){\r
179         snprintf(tmp,sizeof(tmp),"%s=%s\n",\r
180                  entry->name,\r
181                  entry->value);\r
182         tmp[sizeof(tmp)-1]='\0';\r
183         fprintf(f,"%s",tmp);\r
184       }\r
185     }\r
186     fclose(f);\r
187 }\r
188 \r
189 \r
190 // main()\r
191 \r
192 int main(int argc, char * argv[]) {\r
193     ini_t ini[1],ini_save[1];\r
194     ini_entry_t *entry;\r
195     char *arg;\r
196     int arg_index;\r
197     bool NoIni, Persist;\r
198     char persist_path[StringSize];\r
199  \r
200     if(!DEBUG){\r
201         printf("PolyGlot %s by Fabien Letouzey.\n",Version);\r
202     }else{\r
203         printf("PolyGlot %s by Fabien Letouzey (debug build).\n",Version);\r
204     }\r
205 \r
206     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
207         printf("%s\n",HelpMessage);\r
208         return EXIT_SUCCESS;\r
209     }\r
210 \r
211    // init\r
212 \r
213     Init = FALSE;\r
214 \r
215     util_init();\r
216     option_init_pg();\r
217     \r
218     square_init();\r
219     piece_init();\r
220     attack_init();\r
221     \r
222     hash_init();\r
223 \r
224     my_random_init();\r
225 \r
226     ini_init(ini);\r
227     ini_init(ini_save);\r
228 \r
229         // book utilities\r
230     \r
231     if (argc >= 2 && my_string_equal(argv[1],"make-book")) {\r
232         book_make(argc,argv);\r
233         return EXIT_SUCCESS;\r
234     }\r
235     \r
236     if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {\r
237         book_merge(argc,argv);\r
238         return EXIT_SUCCESS;\r
239     }\r
240 \r
241     if (argc >= 2 && my_string_equal(argv[1],"dump-book")) {\r
242         book_dump(argc,argv);\r
243         return EXIT_SUCCESS;\r
244     }\r
245     \r
246     if (argc >= 2 && my_string_equal(argv[1],"info-book")) {\r
247         book_info(argc,argv);\r
248         return EXIT_SUCCESS;\r
249     }\r
250 \r
251         // perft\r
252     \r
253     if (argc >= 2 && my_string_equal(argv[1],"perft")) {\r
254         do_perft(argc,argv);\r
255         return EXIT_SUCCESS;\r
256     }\r
257 \r
258         // TODO: If logging is enabled on the command line turn it on NOW\r
259         // and do not allow it to be overridden later. \r
260     \r
261         // What is the config file? This is very hacky right now.\r
262 \r
263         // Do we want a config file at all?\r
264 \r
265     arg_index=0;\r
266     NoIni=FALSE;\r
267     while((arg=argv[arg_index++])){\r
268         if(my_string_equal(arg,"-noini")){\r
269             NoIni=TRUE;\r
270             break;\r
271         }\r
272     }\r
273     arg_shift_left(argv,arg_index-1);\r
274     if(NoIni){\r
275         option_set(Option,"OptionFile","<empty>");\r
276     }\r
277 \r
278         // Ok see if first argument looks like config file\r
279     \r
280     if(argv[1] && !my_string_equal(argv[1],"epd-test") && !(argv[1][0]=='-')){\r
281                 // first argument must be  config file\r
282         if(!NoIni){\r
283             option_set(Option,"OptionFile",argv[1]);\r
284         }else{\r
285                 // ignore\r
286         }\r
287         arg_shift_left(argv,1);\r
288     }else{\r
289             // Config file is the default.\r
290             // This has already been set above or in "option_init_pg()"\r
291     }\r
292     \r
293 \r
294         // if we use a config file: load it!\r
295     \r
296     if(!my_string_equal(option_get_string(Option,"OptionFile"),"<empty>")){\r
297         if(ini_parse(ini,option_get_string(Option,"OptionFile"))){\r
298             my_fatal("main(): Can't open file \"%s\": %s\n",\r
299                    option_get_string(Option,"OptionFile"),\r
300                    strerror(errno));\r
301         }\r
302     }\r
303         // remind the reader of what options are in effect\r
304 \r
305     my_log("POLYGLOG Options from ini file\n");\r
306     ini_disp(ini);\r
307 \r
308         // extract PG options\r
309     \r
310     ini_start_iter(ini);\r
311     while((entry=ini_next(ini))){\r
312         if(my_string_case_equal(entry->section,"polyglot")){\r
313             option_set(Option,entry->name,entry->value);\r
314             option_set_default(Option,entry->name,entry->value);\r
315         }\r
316     }\r
317 \r
318         // start logging if required\r
319     \r
320     if (option_get_bool(Option,"Log")) {\r
321         my_log_open(option_get_string(Option,"LogFile"));\r
322     }\r
323 \r
324         // log welcome stuff\r
325     \r
326     if(!DEBUG){\r
327         my_log("PolyGlot %s by Fabien Letouzey\n",Version);\r
328     }else{\r
329         my_log("PolyGlot %s by Fabien Letouzey (debug build)\n",Version);\r
330     }    \r
331     my_log("POLYGLOT *** START ***\n");\r
332     my_log("POLYGLOT INI file \"%s\"\n",option_get_string(Option,"OptionFile"));\r
333 \r
334         // open book (presumably this should go else where)\r
335     \r
336     init_book();\r
337 \r
338         // scavenge command line for options necessary to start the engine\r
339     \r
340     arg_index=1;\r
341     while((arg=argv[arg_index])){\r
342         if(my_string_equal(arg,"-ec") && argv[arg_index+1]){\r
343             option_set(Option,"EngineCommand",argv[arg_index+1]);\r
344             arg_shift_left(argv,arg_index);\r
345             arg_shift_left(argv,arg_index);\r
346             continue;\r
347         }\r
348         if(my_string_equal(arg,"-ed") && argv[arg_index+1]){\r
349             option_set(Option,"EngineDir",argv[arg_index+1]);\r
350             arg_shift_left(argv,arg_index);\r
351             arg_shift_left(argv,arg_index);\r
352             continue;\r
353         }\r
354         if(my_string_equal(arg,"-en") && argv[arg_index+1]){\r
355             option_set(Option,"EngineName",argv[arg_index+1]);\r
356             arg_shift_left(argv,arg_index);\r
357             arg_shift_left(argv,arg_index);\r
358             continue;\r
359         }\r
360         arg_index++;\r
361     }\r
362 \r
363         // start engine\r
364     \r
365     engine_open(Engine);\r
366     if(!engine_active(Engine)){\r
367         my_fatal("Could not start \"%s\"\n",option_get(Option,"EngineCommand"));\r
368     }\r
369 \r
370         // switch to UCI mode if necessary\r
371     \r
372     if (option_get_bool(Option,"UCI")) {\r
373         my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
374     }\r
375 \r
376         // initialize uci parsing and send uci command. \r
377         // Parse options and wait for uciok\r
378     \r
379     uci_open(Uci,Engine);\r
380 \r
381         // get engine name from engine if not supplied in config file\r
382     \r
383     if (my_string_equal(option_get_string(Option,"EngineName"),"<empty>")) {\r
384         option_set(Option,"EngineName",Uci->name);\r
385     }\r
386 \r
387         // what is the name of the persist file?\r
388 \r
389     if(my_string_equal(option_get_string(Option,"PersistFile"),"<empty>")){\r
390         char tmp[StringSize];\r
391         snprintf(tmp,sizeof(tmp),"%s.ini",\r
392                  option_get_string(Option,"EngineName"));\r
393         tmp[sizeof(tmp)-1]='\0';\r
394         option_set(Option,"PersistFile",tmp);\r
395     }\r
396 \r
397     // Load the persist file\r
398 \r
399     my_path_join(persist_path,\r
400                  option_get_string(Option,"PersistDir"),\r
401                  option_get_string(Option,"PersistFile"));\r
402 \r
403     my_log("POLYGLOT PersistFile=%s\n",persist_path);   \r
404     if(ini_parse(ini_save,persist_path)){\r
405       my_log("POLYGLOT Unable to open PersistFile\n"); \r
406     }\r
407 \r
408     // Do we want to use the persist file?\r
409 \r
410     entry=ini_find(ini_save,"polyglot","Persist");\r
411     if(!entry){\r
412       Persist=option_get_bool(Option,"Persist");\r
413     }else{\r
414       Persist=(my_string_case_equal(entry->value,"false") || \r
415                my_string_equal(entry->value,"0"))?FALSE:TRUE;\r
416     }\r
417 \r
418     // if "Persist" now happens to be false, forget about the\r
419     // persist file    \r
420 \r
421     if(!Persist){\r
422       my_log("POLYGLOT Ignoring PersistFile");\r
423       ini_clear(ini_save);\r
424     }\r
425 \r
426     option_set(Option,"Persist",Persist?"true":"false");\r
427 \r
428     // parse the command line and merge remaining options\r
429 \r
430     arg_index=1;\r
431     while((arg=argv[arg_index])){\r
432         if(my_string_equal(arg,"-log")){\r
433             ini_insert_ex(ini_save,"PolyGlot","Log","true");\r
434             arg_shift_left(argv,arg_index);\r
435             continue;\r
436         }\r
437         if(my_string_equal(arg,"-lf") && argv[arg_index+1]){\r
438             ini_insert_ex(ini_save,"PolyGlot","LogFile",argv[arg_index+1]);\r
439             arg_shift_left(argv,arg_index);\r
440             arg_shift_left(argv,arg_index);\r
441             continue;\r
442         }\r
443         if(my_string_equal(arg,"-hash") && argv[arg_index+1]){\r
444             ini_insert_ex(ini_save,"Engine","Hash",argv[arg_index+1]);\r
445             arg_shift_left(argv,arg_index);\r
446             arg_shift_left(argv,arg_index);\r
447             continue;\r
448         }\r
449         if(my_string_equal(arg,"-bk") && argv[arg_index+1]){\r
450             ini_insert_ex(ini_save,"PolyGlot","Book","true");\r
451             ini_insert_ex(ini_save,"PolyGlot","BookFile",argv[arg_index+1]);\r
452             arg_shift_left(argv,arg_index);\r
453             arg_shift_left(argv,arg_index);\r
454             continue;\r
455         }\r
456         if((my_string_equal(arg,"-pg")||my_string_equal(arg,"-uci")) &&\r
457            argv[arg_index]){\r
458             int ret;\r
459             char section[StringSize];\r
460             char name[StringSize];\r
461             char value[StringSize];\r
462             ret=ini_line_parse(argv[arg_index++],section,name,value);\r
463             if(ret==NAME_VALUE){\r
464                 if(my_string_equal(arg,"-pg")){\r
465                     ini_insert_ex(ini_save,"PolyGlot",name,value);\r
466                 }else{\r
467                     ini_insert_ex(ini_save,"Engine",name,value);\r
468                 }\r
469             }\r
470             arg_shift_left(argv,arg_index);\r
471             arg_shift_left(argv,arg_index);\r
472             continue;\r
473         }\r
474         arg_index++;\r
475     }\r
476 \r
477         // remind the reader once again about options\r
478 \r
479     my_log("POLYGLOG Options from PersistFile and command line\n");\r
480     ini_disp(ini_save);\r
481 \r
482         // Extract PG options; this time do not set the default.\r
483         // polyglot_set_option() performs the necessary actions such\r
484         // as opening the log file/opening book etcetera.\r
485         // Ignore EngineName, EngineCommand and EngineDir\r
486         // as these are really meant as comments.\r
487     \r
488     ini_start_iter(ini_save);\r
489     while((entry=ini_next(ini_save))){\r
490         if(my_string_case_equal(entry->section,"polyglot")){\r
491             if(my_string_case_equal(entry->value,"EngineName")) \r
492                continue;\r
493             if(my_string_case_equal(entry->value,"EngineCommand")) \r
494                continue;\r
495             if(my_string_case_equal(entry->value,"EngineDir")) \r
496                continue;\r
497             polyglot_set_option(entry->name,entry->value);\r
498         }\r
499     }\r
500 \r
501         // done initializing\r
502     \r
503     Init = TRUE;\r
504     \r
505         // collect engine options from config file(s) and send to engine\r
506     \r
507     ini_start_iter(ini);\r
508     while((entry=ini_next(ini))){\r
509         if(my_string_case_equal(entry->section,"engine")){\r
510                 // also updates value in Uci->option\r
511             uci_send_option(Uci,entry->name,"%s",entry->value);\r
512                 // since this comes from the ini file, also update default\r
513             option_set_default(Uci->option,entry->name,entry->value);\r
514                 // this is inherited, it probably does not work correctly\r
515            if(my_string_case_equal(entry->name,"MultiPV") &&\r
516               atoi(entry->value)>1){\r
517                Uci->multipv_mode=TRUE;\r
518            }\r
519         }\r
520     }\r
521     ini_start_iter(ini_save);\r
522     while((entry=ini_next(ini_save))){\r
523         if(my_string_case_equal(entry->section,"engine")){\r
524                 // also updates value in Uci->option\r
525             uci_send_option(Uci,entry->name,"%s",entry->value);\r
526                 // this is inherited, it probably does not work correctly\r
527             if(my_string_case_equal(entry->name,"MultiPV") &&\r
528                atoi(entry->value)>1){\r
529                 Uci->multipv_mode=TRUE;\r
530             }\r
531         }\r
532     }\r
533    \r
534     \r
535         // EPD test\r
536     \r
537     if (argv[1] && my_string_equal(argv[1],"epd-test")){\r
538         argc=0;\r
539         while((arg=argv[argc++]));\r
540         epd_test(argc-1,argv);\r
541         return EXIT_SUCCESS;\r
542     }\r
543     \r
544         // Anything that hasn't been parsed yet is a syntax error\r
545 \r
546     if(argv[1]){\r
547         my_fatal("main(): Unknown option: %s\n",argv[1]);\r
548     }\r
549 \r
550 \r
551     gui_init(GUI);\r
552     mainloop();\r
553     return EXIT_SUCCESS; \r
554 }\r
555 \r
556 // polyglot_set_option()\r
557 \r
558 void polyglot_set_option(const char *name, const char *value){ // this must be cleaned up!\r
559     option_t *opt;\r
560     my_log("POLYGLOT Setting PolyGlot option %s=\"%s\"\n",name,value);\r
561     if(my_string_case_equal(name,"Defaults")){\r
562       option_start_iter(Uci->option);\r
563       while((opt=option_next(Uci->option))){\r
564         if(!IS_BUTTON(opt)){\r
565         // also sets opt->value\r
566           uci_send_option(Uci,opt->name,opt->default_);\r
567         }\r
568       }\r
569       option_start_iter(Option);\r
570       while((opt=option_next(Option))){\r
571         if(!IS_BUTTON(opt)){\r
572           polyglot_set_option(opt->name,opt->default_);\r
573         }\r
574       }\r
575       xboard2uci_send_options();\r
576     }\r
577     option_set(Option,name,value);\r
578     if(option_get_bool(Option,"Book")&&(my_string_case_equal(name,"BookFile")||my_string_case_equal(name,"Book"))){\r
579         my_log("POLYGLOT *** SETTING BOOK ***\n");\r
580         my_log("POLYGLOT BOOK \"%s\"\n",option_get_string(Option,"BookFile"));\r
581         book_close();\r
582         book_clear();\r
583         book_open(option_get_string(Option,"BookFile"));\r
584         if(!book_is_open()){\r
585             my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string(Option,"BookFile"));\r
586         }\r
587     }else if(option_get_bool(Option,"Log")&&(my_string_case_equal(name,"LogFile") ||my_string_case_equal(name,"Log"))){\r
588         my_log("POLYGLOT *** SWITCHING LOGFILE ***\n");\r
589         my_log("POLYGLOT LOGFILE \"%s\"\n",option_get_string(Option,"LogFile"));\r
590         my_log_close();\r
591         my_log_open(option_get_string(Option,"LogFile"));\r
592     }else if(option_get_bool(Option,"UseNice") &&(my_string_case_equal(name,"NiceValue")||my_string_case_equal(name,"UseNice"))){\r
593         my_log("POLYGLOT Adjust Engine Piority\n");\r
594         engine_set_nice_value(Engine,atoi(option_get_string(Option,"NiceValue")));\r
595     }else if(my_string_case_equal(name,"Book") && !option_get_bool(Option,"Book")){\r
596         book_close();\r
597         book_clear();\r
598     }else if(my_string_case_equal(name,"UseNice") && !option_get_bool(Option,"UseNice")){\r
599         my_log("POLYGLOT Adjust Engine Piority\n");\r
600         engine_set_nice_value(Engine,0);\r
601     }else if(my_string_case_equal(name,"Log") && !option_get_bool(Option,"Log")){\r
602         my_log("POLYGLOT QUIT LOGGING\n");\r
603         my_log_close();\r
604     }\r
605 }\r
606 \r
607 \r
608 // init_book()\r
609 \r
610 static void init_book(){\r
611     book_clear();\r
612     if (option_get_bool(Option,"Book")){\r
613         my_log("POLYGLOT *** SETTING BOOK ***\n");\r
614         my_log("POLYGLOT BOOK \"%s\"\n",option_get_string(Option,"BookFile"));\r
615         book_open(option_get_string(Option,"BookFile"));\r
616         if(!book_is_open()){\r
617             my_log("POLYGLOT Unable to open book \"%s\"\n",\r
618                    option_get_string(Option,"BookFile"));\r
619         }\r
620     }\r
621 }\r
622 \r
623 \r
624 // quit()\r
625 \r
626 void quit() {\r
627 \r
628     ini_t empty[1];\r
629     char persist_path[StringSize];\r
630     int ret;\r
631 \r
632     ini_init(empty);\r
633 \r
634     my_log("POLYGLOT *** QUIT ***\n");\r
635     \r
636     if (Init) {\r
637         \r
638         stop_search();\r
639         engine_send(Engine,"quit");\r
640         my_log("POLYGLOT Closing engine\n");\r
641         engine_close(Engine);\r
642         \r
643     }\r
644     ret=my_mkdir(option_get(Option,"PersistDir"));\r
645     if(ret){\r
646       my_log("POLYGLOT quit(): %s: %s\n",option_get(Option,"PersistDir"),strerror(errno));\r
647     }\r
648     // PersistFile can be named "<empty>" in case of a crash before the\r
649     // engine is started. \r
650     if(!my_string_case_equal(option_get(Option,"PersistFile"),\r
651                              "<empty>")){\r
652       my_path_join(persist_path,\r
653                  option_get(Option,"PersistDir"),\r
654                  option_get(Option,"PersistFile"));\r
655       if(option_get_bool(Option,"Persist")){\r
656         write_ini(persist_path,\r
657                   Option,Uci->option);\r
658       }else if(!my_string_case_equal(option_get_default(Option,"Persist"),\r
659                                      option_get_string(Option,"Persist"))){\r
660         // Hack\r
661         ini_insert_ex(empty,"PolyGlot","Persist","false");\r
662         write_ini_ex(persist_path,empty);\r
663       }else{\r
664         write_ini_ex(persist_path,empty);\r
665       }\r
666       my_log("POLYGLOT Calling exit\n");\r
667     }\r
668     exit(EXIT_SUCCESS);\r
669 }\r
670 \r
671 // stop_search()\r
672 \r
673 static void stop_search() {\r
674     \r
675     if (Init && Uci->searching) {\r
676         \r
677         ASSERT(Uci->searching);\r
678         ASSERT(Uci->pending_nb>=1);\r
679         \r
680         my_log("POLYGLOT STOP SEARCH\n");\r
681         \r
682         if (option_get_bool(Option,"SyncStop")) {\r
683             uci_send_stop_sync(Uci);\r
684         } else {\r
685             uci_send_stop(Uci);\r
686         }\r
687     }\r
688 }\r
689 \r
690 \r
691 // end of main.cpp\r
692 \r