version 1.4.53b
[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.53b";\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 // variables\r
59 \r
60 static bool Init;\r
61 \r
62 // prototypes\r
63 \r
64 static void stop_search  ();\r
65 \r
66 // functions\r
67 \r
68 // arg_shift_left()\r
69 \r
70 static void arg_shift_left(char **argv, int index){\r
71     int i;\r
72     for(i=index; argv[i]!=NULL; i++){\r
73         argv[i]=argv[i+1];\r
74     }\r
75 }\r
76 \r
77 // parse_args()\r
78 \r
79 static void parse_args(ini_t *ini, char **argv){\r
80     int arg_index;\r
81     char *arg;\r
82     arg_index=0;\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
88             continue;\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
93             continue;\r
94         }\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
99             continue;\r
100         }\r
101         if(my_string_equal(arg,"-log") &&\r
102            argv[arg_index+1] &&\r
103            IS_BOOL(argv[arg_index+1])){\r
104             ini_insert_ex(ini,\r
105                           "PolyGlot",\r
106                           "Log",\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
110             continue;\r
111         }\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
116             continue;\r
117         }\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
122                              "OnlyWbOptions",\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
126                continue;\r
127         }\r
128         if((my_string_equal(arg,"-pg")||my_string_equal(arg,"-uci")) &&\r
129            argv[arg_index+1]){\r
130             int ret;\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
138                 }else{\r
139                     ini_insert_ex(ini,"Engine",name,value);\r
140                 }\r
141             }\r
142             arg_shift_left(argv,arg_index);\r
143             arg_shift_left(argv,arg_index);\r
144             continue;\r
145         }\r
146         arg_index++;\r
147     }\r
148 }\r
149 \r
150 \r
151 // make_ini()\r
152 \r
153 static void make_ini(ini_t *ini){\r
154     option_t *opt;\r
155     ini_insert_ex(ini,"polyglot",\r
156                   "EngineCommand",\r
157                   option_get(Option,"EngineCommand"));\r
158     ini_insert_ex(ini,"polyglot",\r
159                   "EngineDir",\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
167         {\r
168             ini_insert_ex(ini,"polyglot",opt->name,opt->value);\r
169         }\r
170     }\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
179         }\r
180     }\r
181 }\r
182 \r
183 \r
184 // write_ini()\r
185 \r
186 static void write_ini(const char *filename,\r
187                          ini_t *ini){\r
188     const char *quote;\r
189     ini_entry_t *entry;\r
190     char tmp[StringSize];\r
191     FILE *f;\r
192     time_t t=time(NULL);\r
193     f=fopen(filename,"w");\r
194     if(!f){\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
197       return;\r
198     }\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
205               quote="\"";\r
206           }else{\r
207               quote="";\r
208           }\r
209           snprintf(tmp,sizeof(tmp),"%s=%s%s%s\n",\r
210                    entry->name,\r
211                    quote,\r
212                    entry->value,\r
213                    quote);\r
214         tmp[sizeof(tmp)-1]='\0';\r
215         fprintf(f,"%s",tmp);\r
216       }\r
217     }\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
223                 quote="\"";\r
224             }else{\r
225                 quote="";\r
226             }\r
227             snprintf(tmp,sizeof(tmp),"%s=%s%s%s\n",\r
228                      entry->name,\r
229                      quote,\r
230                      entry->value,\r
231                      quote);\r
232         tmp[sizeof(tmp)-1]='\0';\r
233         fprintf(f,"%s",tmp);\r
234       }\r
235     }\r
236     fclose(f);\r
237 }\r
238 \r
239 // welcome_message()\r
240 \r
241 void welcome_message(char *buf){\r
242     if(!DEBUG){\r
243         sprintf(buf,\r
244                 "PolyGlot %s by Fabien Letouzey.\n",\r
245                 Version);\r
246     }else{\r
247         sprintf(buf,\r
248                 "PolyGlot %s by Fabien Letouzey (debug build).\n",\r
249                 Version);\r
250     }\r
251 }\r
252 \r
253 int wb_select(){\r
254     option_t *opt;\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
260         }\r
261     }\r
262 }\r
263 \r
264 // main()\r
265 \r
266 int main(int argc, char * argv[]) {\r
267     ini_t ini[1], ini_command[1];\r
268     ini_entry_t *entry;\r
269     char *arg;\r
270     int arg_index;\r
271     bool NoIni;\r
272     option_t *opt;\r
273     char welcome[StringSize];\r
274 \r
275 \r
276     welcome_message(welcome);\r
277  \r
278     printf("%s",welcome);\r
279 \r
280 \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
284     }\r
285 \r
286    // init\r
287 \r
288     Init = FALSE;\r
289 \r
290     util_init();\r
291     option_init_pg();\r
292     \r
293     square_init();\r
294     piece_init();\r
295     attack_init();\r
296     \r
297     hash_init();\r
298 \r
299     my_random_init();\r
300 \r
301     ini_init(ini);\r
302     ini_init(ini_command);\r
303 \r
304         // book utilities: do not touch these\r
305     \r
306     if (argc >= 2 && my_string_equal(argv[1],"make-book")) {\r
307         book_make(argc,argv);\r
308         return EXIT_SUCCESS;\r
309     }\r
310     \r
311     if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {\r
312         book_merge(argc,argv);\r
313         return EXIT_SUCCESS;\r
314     }\r
315 \r
316     if (argc >= 2 && my_string_equal(argv[1],"dump-book")) {\r
317         book_dump(argc,argv);\r
318         return EXIT_SUCCESS;\r
319     }\r
320     \r
321     if (argc >= 2 && my_string_equal(argv[1],"info-book")) {\r
322         book_info(argc,argv);\r
323         return EXIT_SUCCESS;\r
324     }\r
325 \r
326         // perft\r
327     \r
328     if (argc >= 2 && my_string_equal(argv[1],"perft")) {\r
329         do_perft(argc,argv);\r
330         return EXIT_SUCCESS;\r
331     }\r
332     \r
333         // What is the config file? This is very hacky right now.\r
334 \r
335         // Do we want a config file at all?\r
336 \r
337     arg_index=0;\r
338     NoIni=FALSE;\r
339     while((arg=argv[arg_index++])){\r
340         if(my_string_equal(arg,"-noini")){\r
341             NoIni=TRUE;\r
342             break;\r
343         }\r
344     }\r
345     arg_shift_left(argv,arg_index-1);\r
346     parse_args(ini_command,argv+1);\r
347     if(NoIni){\r
348         option_set(Option,"SettingsFile","<empty>");\r
349     }\r
350 \r
351         // Ok see if first argument looks like config file\r
352     \r
353     if(argv[1] && !my_string_equal(argv[1],"epd-test") && !(argv[1][0]=='-')){\r
354                 // first argument must be  config file\r
355         if(!NoIni){\r
356             option_set(Option,"SettingsFile",argv[1]);\r
357         }else{\r
358                 // ignore\r
359         }\r
360         arg_shift_left(argv,1);\r
361     }else{\r
362             // Config file is the default.\r
363             // This has already been set above or in "option_init_pg()"\r
364     }\r
365 \r
366 \r
367 \r
368         // if we use a config file: load it!\r
369     \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
374                    strerror(errno));\r
375         }\r
376     }\r
377 \r
378         // Extract some important options\r
379 \r
380     if((entry=ini_find(ini,"polyglot","EngineCommand"))){\r
381         option_set(Option,entry->name,entry->value);\r
382     }\r
383     if((entry=ini_find(ini,"polyglot","EngineDir"))){\r
384         option_set(Option,entry->name,entry->value);\r
385     }\r
386     if((entry=ini_find(ini,"polyglot","EngineName"))){\r
387         option_set(Option,entry->name,entry->value);\r
388     }\r
389     if((entry=ini_find(ini,"polyglot","Log"))){\r
390         polyglot_set_option(entry->name,entry->value);\r
391     }\r
392     if((entry=ini_find(ini,"polyglot","LogFile"))){\r
393         polyglot_set_option(entry->name,entry->value);\r
394     }\r
395     \r
396         // Concession to WB 4.4.0\r
397         // Treat "polyglot_1st.ini" and "polyglot_2nd.ini" specially\r
398 \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
404         }\r
405     }\r
406 \r
407         // Look at command line for logging option. It is important\r
408         // to start logging as soon as possible.\r
409 \r
410      if((entry=ini_find(ini_command,"PolyGlot","Log"))){\r
411          option_set(Option,entry->name,entry->value);\r
412     }\r
413     if((entry=ini_find(ini_command,"PolyGlot","LogFile"))){\r
414         option_set(Option,entry->name,entry->value);\r
415     }\r
416     \r
417        // start logging if required\r
418     \r
419     if (option_get_bool(Option,"Log")) {\r
420         my_log_open(option_get_string(Option,"LogFile"));\r
421     }\r
422 \r
423         // log welcome stuff\r
424     \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
429     }\r
430 \r
431 \r
432         // scavenge command line for options necessary to start the engine\r
433 \r
434 \r
435     if((entry=ini_find(ini_command,"PolyGlot","EngineCommand"))){\r
436         option_set(Option,entry->name,entry->value);\r
437     }\r
438     if((entry=ini_find(ini_command,"PolyGlot","EngineDir"))){\r
439         option_set(Option,entry->name,entry->value);\r
440     }\r
441     if((entry=ini_find(ini_command,"PolyGlot","EngineName"))){\r
442         option_set(Option,entry->name,entry->value);\r
443     }\r
444 \r
445         // start engine\r
446     \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
450     }\r
451 \r
452         // switch to UCI mode if necessary\r
453     \r
454     if (option_get_bool(Option,"UCI")) {\r
455         my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
456     }\r
457 \r
458         // initialize uci parsing and send uci command. \r
459         // Parse options and wait for uciok\r
460     \r
461     uci_open(Uci,Engine);\r
462 \r
463     option_set_default(Option,"EngineName",Uci->name);\r
464 \r
465         // get engine name from engine if not supplied in config file or on\r
466         // the command line\r
467 \r
468     if (my_string_equal(option_get_string(Option,"EngineName"),"<empty>")) {\r
469         option_set(Option,"EngineName",Uci->name);\r
470     }\r
471 \r
472 \r
473         // In the case we have been invoked with NoIni or StandardIni\r
474         // we still have to load a config file.\r
475 \r
476     if(my_string_equal(option_get_string(Option,"SettingsFile"),"<empty>")){\r
477 \r
478             //  construct the name of the ConfigFile from the EngineName\r
479         \r
480         char tmp[StringSize];\r
481         char option_file[StringSize];\r
482         int i;\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
487             if(tmp[i]==' '){\r
488                 tmp[i]='_';\r
489             }\r
490         }\r
491         my_path_join(option_file,\r
492                      option_get_string(Option,"SettingsDir"),\r
493                      tmp);\r
494     // Load the config file\r
495         option_set(Option,"SettingsFile",option_file);\r
496 \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
501         }\r
502     }\r
503 \r
504 \r
505     // Parse the command line and merge remaining options.\r
506 \r
507     ini_start_iter(ini_command);\r
508     while((entry=ini_next(ini_command))){\r
509         ini_insert(ini,entry);\r
510     }\r
511 \r
512         // Remind the reader about the options that are now in effect.\r
513 \r
514     my_log("POLYGLOG OPTIONS \n");\r
515     ini_disp(ini);\r
516 \r
517             // extract PG options\r
518     \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
525             }\r
526         }\r
527     }\r
528 \r
529         // Cater to our biggest customer:-)\r
530     \r
531     if(option_get_bool(Option,"OnlyWbOptions")){\r
532         wb_select();\r
533     }\r
534 \r
535         // done initializing\r
536     \r
537     Init = TRUE;\r
538     \r
539         // collect engine options from config file(s) and send to engine\r
540     \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
546         }\r
547     }\r
548 \r
549     \r
550     \r
551         // EPD test\r
552     \r
553     if (argv[1] && my_string_equal(argv[1],"epd-test")){\r
554         argc=0;\r
555         while((arg=argv[argc++]));\r
556         epd_test(argc-1,argv);\r
557         return EXIT_SUCCESS;\r
558     }\r
559     \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
563 \r
564     argc=1;\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
568         }\r
569     }\r
570 \r
571     gui_init(GUI);\r
572     mainloop();\r
573     return EXIT_SUCCESS; \r
574 }\r
575 \r
576 // polyglot_set_option()\r
577 \r
578 void polyglot_set_option(const char *name, const char *value){ // this must be cleaned up!\r
579     ini_t ini[1];\r
580     int ret;\r
581     ini_init(ini);\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
585         if(ret){\r
586             my_log("POLYGLOT polyglot_set_option(): %s: %s\n",\r
587                    option_get(Option,"SettingsDir"),\r
588                    strerror(errno));\r
589         }\r
590         make_ini(ini);\r
591         write_ini(option_get(Option,"SettingsFile"),ini);\r
592         return;\r
593     }\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
597 //               name);\r
598 //        return;\r
599 //    }\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
604         book_close();\r
605         book_clear();\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
609         }\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
613         my_log_close();\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
619         book_close();\r
620         book_clear();\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
626         my_log_close();\r
627     }\r
628 }\r
629 \r
630 \r
631 \r
632 // quit()\r
633 \r
634 void quit() {\r
635 \r
636     my_log("POLYGLOT *** QUIT ***\n");\r
637     \r
638     if (Init) {\r
639         \r
640         stop_search();\r
641         engine_send(Engine,"quit");\r
642         my_log("POLYGLOT Closing engine\n");\r
643         engine_close(Engine);\r
644         \r
645     }\r
646         my_log("POLYGLOT Calling exit\n");\r
647     exit(EXIT_SUCCESS);\r
648 }\r
649 \r
650 // stop_search()\r
651 \r
652 static void stop_search() {\r
653     \r
654     if (Init && Uci->searching) {\r
655         \r
656         ASSERT(Uci->searching);\r
657         ASSERT(Uci->pending_nb>=1);\r
658         \r
659         my_log("POLYGLOT STOP SEARCH\n");\r
660         \r
661         if (option_get_bool(Option,"SyncStop")) {\r
662             uci_send_stop_sync(Uci);\r
663         } else {\r
664             uci_send_stop(Uci);\r
665         }\r
666     }\r
667 }\r
668 \r
669 \r
670 // end of main.c\r
671 \r