ce6c235859c6fd83a0d1e508bfa20146be585cbf
[polyglot.git] / main.cpp
1 \r
2 // main.cpp\r
3 \r
4 // includes\r
5 \r
6 #include <cerrno>\r
7 #include <csignal>\r
8 #include <cstdio>\r
9 #include <cstdlib>\r
10 #include <cstring>\r
11 \r
12 #ifdef _WIN32\r
13   #include <windows.h>\r
14 #else\r
15   #include <unistd.h>\r
16 #endif\r
17 \r
18 #include "adapter.h"\r
19 #include "attack.h"\r
20 #include "board.h"\r
21 #include "book.h"\r
22 #include "book_make.h"\r
23 #include "book_merge.h"\r
24 #include "engine.h"\r
25 #include "epd.h"\r
26 #include "fen.h"\r
27 #include "gui.h"\r
28 #include "hash.h"\r
29 #include "list.h"\r
30 #include "main.h"\r
31 #include "move.h"\r
32 #include "move_gen.h"\r
33 #include "option.h"\r
34 #include "piece.h"\r
35 #include "search.h"\r
36 #include "square.h"\r
37 #include "uci.h"\r
38 #include "util.h"\r
39 // constants\r
40 \r
41 \r
42 static const char * const Version = "1.4W10UCIb16";\r
43 static const char * const HelpMessage = "\\r
44 SYNTAX\n\\r
45 polyglot [configfile]\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 [configfile] epd-test [-epd inputfile] [-min-depth depth] [-max-depth depth] [-max-time time] [-depth-delta delta]\n\\r
49 polyglot perft [-fen fen] [-max-depth depth]\\r
50 ";\r
51 \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 // variables\r
58 static bool Init;\r
59 // prototypes\r
60 \r
61 static void parse_option ();\r
62 static void init_book ();\r
63 static bool parse_line   (char line[], char * * name_ptr, char * * value_ptr);\r
64 static void stop_search  ();\r
65 static void sig_quit(int);\r
66 \r
67 // functions\r
68 \r
69 // main()\r
70 \r
71 int main(int argc, char * argv[]) {\r
72 \r
73 //   board_t board[1];\r
74 \r
75     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
76         printf("%s\n",HelpMessage);\r
77         return EXIT_SUCCESS;\r
78     }\r
79    // init\r
80 \r
81    Init = false;\r
82 \r
83    signal(SIGINT,sig_quit);\r
84 \r
85 #ifdef _WIN32\r
86       signal(SIGTERM,SIG_IGN);\r
87 #ifdef SIGPIPE\r
88       signal(SIGPIPE,SIG_IGN);\r
89 #endif\r
90 #endif\r
91 \r
92    util_init();\r
93    printf("PolyGlot %s by Fabien Letouzey\n",Version);\r
94 \r
95    option_init();\r
96 \r
97    square_init();\r
98    piece_init();\r
99    attack_init();\r
100 \r
101    hash_init();\r
102 \r
103    my_random_init();\r
104 \r
105    // build book\r
106 \r
107    if (argc >= 2 && my_string_equal(argv[1],"make-book")) {\r
108       book_make(argc,argv);\r
109       return EXIT_SUCCESS;\r
110    }\r
111 \r
112    if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {\r
113       book_merge(argc,argv);\r
114       return EXIT_SUCCESS;\r
115    }\r
116 \r
117    if (argc >= 2 && my_string_equal(argv[1],"perft")) {\r
118       do_perft(argc,argv);\r
119       return EXIT_SUCCESS;\r
120    }\r
121 \r
122    if (argc >= 3 && my_string_equal(argv[1],"-ec")) {\r
123        option_set("EngineCommand",argv[2]);\r
124        Init=true;\r
125        engine_open(Engine);\r
126        gui_init(GUI);\r
127        uci_open(Uci,Engine);\r
128        if (my_string_equal(option_get_string("EngineName"),"<empty>")) {\r
129             option_set("EngineName",Uci->name);\r
130        }\r
131        adapter_loop();\r
132        return EXIT_SUCCESS; // we don't get here\r
133    }\r
134 \r
135    // read options\r
136 \r
137    if (argc == 2) option_set("OptionFile",argv[1]); // HACK for compatibility\r
138 \r
139    parse_option(); // HACK: also launches the engine\r
140 \r
141    // EPD test\r
142 \r
143    if (argc >= 2 && my_string_equal(argv[1],"epd-test")){\r
144        epd_test(argc,argv);\r
145        return EXIT_SUCCESS;\r
146    }else if(argc >= 3 && my_string_equal(argv[2],"epd-test")){\r
147        epd_test(argc-1,argv+1);\r
148        return EXIT_SUCCESS;\r
149    }\r
150    \r
151    init_book();\r
152    // adapter\r
153    \r
154    gui_init(GUI);\r
155    adapter_loop();\r
156    return EXIT_SUCCESS;  // we never get here....\r
157 }\r
158 \r
159 // polyglot_set_option\r
160 \r
161 void polyglot_set_option(char *name, char *value){ // this must be cleaned up!\r
162     option_set(name,value);\r
163     if(option_get_bool("Book")&&(my_string_case_equal(name,"BookFile")||my_string_case_equal(name,"Book"))){\r
164         my_log("POLYGLOT *** SETTING BOOK ***\n");\r
165         my_log("POLYGLOT BOOK \"%s\"\n",option_get_string("BookFile"));\r
166         book_close();\r
167         book_clear();\r
168         book_open(option_get_string("BookFile"));\r
169         if(!book_is_open()){\r
170             my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string("BookFile"));\r
171         }\r
172     }else if(option_get_bool("Log")&&(my_string_case_equal(name,"LogFile") ||my_string_case_equal(name,"Log"))){\r
173         my_log("POLYGLOT *** SETTING LOGFILE ***\n");\r
174         my_log("POLYGLOT LOGFILE \"%s\"\n",option_get_string("LogFile"));\r
175         my_log_close();\r
176         my_log_open(option_get_string("LogFile"));\r
177     }else if(option_get_bool("UseNice") &&(my_string_case_equal(name,"NiceValue")||my_string_case_equal(name,"UseNice"))){\r
178         my_log("POLYGLOT Adjust Engine Piority\n");\r
179         engine_set_nice_value(Engine,atoi(option_get_string("NiceValue")));\r
180     }else if(my_string_case_equal(name,"Book") && !option_get_bool("Book")){\r
181         book_close();\r
182         book_clear();\r
183     }else if(my_string_case_equal(name,"UseNice") && !option_get_bool("UseNice")){\r
184         my_log("POLYGLOT Adjust Engine Piority\n");\r
185         engine_set_nice_value(Engine,0);\r
186     }else if(my_string_case_equal(name,"Log") && !option_get_bool("Log")){\r
187         my_log("POLYGLOT QUIT LOGGING\n");\r
188         my_log_close();\r
189     }\r
190 }\r
191 \r
192 \r
193 // init_book()\r
194 \r
195 static void init_book(){\r
196     const char *empty_var[]={};\r
197     book_clear();\r
198     if (option_get_bool("Book")){\r
199         my_log("POLYGLOT *** SETTING BOOK ***\n");\r
200         my_log("POLYGLOT BOOK \"%s\"\n",option_get_string("BookFile"));\r
201         book_open(option_get_string("BookFile"));\r
202         if(!book_is_open()){\r
203             my_log("POLYGLOT Unable to open book \"%s\"\n",\r
204                    option_get_string("BookFile"));\r
205         }\r
206     }\r
207 }\r
208 \r
209 // parse_option()\r
210 \r
211 static void parse_option() {\r
212 \r
213    const char * file_name;\r
214    FILE * file;\r
215    char line[256];\r
216    char * name, * value;\r
217     file_name = option_get_string("OptionFile");\r
218 \r
219    file = fopen(file_name,"r");\r
220    if (file == NULL) {\r
221        my_fatal("Can't open file \"%s\": %s\n",file_name,strerror(errno));\r
222    }\r
223 \r
224    // PolyGlot options (assumed first)\r
225 \r
226    while (true) {\r
227 \r
228       if (!my_file_read_line(file,line,256)) {\r
229          my_fatal("parse_option(): missing [Engine] section\n");\r
230       }\r
231 \r
232       if(line[0]=='#') continue;\r
233 \r
234       if (my_string_case_equal(line,"[engine]")) break;\r
235 \r
236       if (parse_line(line,&name,&value)) {\r
237           option_set(name,value);\r
238           option_set_default(name,value);\r
239       }\r
240    }\r
241 \r
242    if (option_get_bool("Log")) {\r
243       my_log_open(option_get_string("LogFile"));\r
244    }\r
245 \r
246    my_log("POLYGLOT *** START ***\n");\r
247    my_log("POLYGLOT INI file \"%s\"\n",file_name);\r
248    engine_open(Engine);\r
249    if (option_get_bool("UCI")) {\r
250        my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
251    }\r
252 \r
253  \r
254    Init = true;\r
255    uci_open(Uci,Engine);\r
256    while (my_file_read_line(file,line,256)) {\r
257        if (line[0] == '[') my_fatal("parse_option(): unknown section %s\n",line);\r
258        if (line[0]=='#') continue;\r
259        \r
260        if (parse_line(line,&name,&value)) {\r
261            uci_send_option(Uci,name,"%s",value);\r
262                //to get a decent display in winboard_x we need to now if an engine really is doing multipv analysis\r
263                // "multipv 1" in the pv is meaningless,f.i. toga sends that all the time\r
264                //therefore check if MultiPV is set to a decent value in the polyglot ini file\r
265            if(my_string_case_equal(name,"MultiPV") && atoi(value)>1)  Uci->multipv_mode=true;\r
266        }\r
267    }\r
268    if (my_string_equal(option_get_string("EngineName"),"<empty>")) {\r
269            option_set("EngineName",Uci->name);\r
270    }\r
271 \r
272    fclose(file);\r
273 }\r
274 \r
275 // parse_line()\r
276 \r
277 static bool parse_line(char line[], char * * name_ptr, char * * value_ptr) {\r
278 \r
279    char * ptr;\r
280    char * name, * value;\r
281 \r
282    ASSERT(line!=NULL);\r
283    ASSERT(name_ptr!=NULL);\r
284    ASSERT(value_ptr!=NULL);\r
285 \r
286    // remove comments\r
287 \r
288    ptr = strchr(line,';');\r
289    if (ptr != NULL) *ptr = '\0';\r
290 \r
291    ptr = strchr(line,'#');\r
292    if (ptr != NULL) *ptr = '\0';\r
293 \r
294    // split at '='\r
295 \r
296    ptr = strchr(line,'=');\r
297    if (ptr == NULL) return false;\r
298 \r
299    name = line;\r
300    value = ptr+1;\r
301 \r
302    // cleanup name\r
303 \r
304    while (*name == ' ') name++; // remove leading spaces\r
305 \r
306    while (ptr > name && ptr[-1] == ' ') ptr--; // remove trailing spaces\r
307    *ptr = '\0';\r
308 \r
309    if (*name == '\0') return false;\r
310 \r
311    // cleanup value\r
312 \r
313    ptr = &value[strlen(value)]; // pointer to string terminator\r
314 \r
315    while (*value == ' ') value++; // remove leading spaces\r
316 \r
317    while (ptr > value && ptr[-1] == ' ') ptr--; // remove trailing spaces\r
318    *ptr = '\0';\r
319 \r
320    if (*value == '\0') return false;\r
321 \r
322    // end\r
323 \r
324    *name_ptr = name;\r
325    *value_ptr = value;\r
326 \r
327    return true;\r
328 }\r
329 \r
330 static void sig_quit(int dummy){\r
331     my_log("POLYGLOT *** SIGINT Received ***\n");\r
332     quit();\r
333 }\r
334 \r
335 \r
336 // quit()\r
337 \r
338 void quit() {\r
339 \r
340    char string[StringSize];\r
341 \r
342    my_log("POLYGLOT *** QUIT ***\n");\r
343 \r
344    if (Init) {\r
345 \r
346       stop_search();\r
347       engine_send(Engine,"quit");\r
348 \r
349       // wait for the engine to quit\r
350       while (true) {\r
351          engine_get(Engine,string,StringSize); // HACK: calls exit() on receiving EOF\r
352       }\r
353    }\r
354    exit(EXIT_SUCCESS);\r
355 }\r
356 \r
357 // stop_search()\r
358 \r
359 static void stop_search() {\r
360 \r
361    if (Init && Uci->searching) {\r
362 \r
363       ASSERT(Uci->searching);\r
364       ASSERT(Uci->pending_nb>=1);\r
365 \r
366       my_log("POLYGLOT STOP SEARCH\n");\r
367 \r
368 /*\r
369       engine_send(Engine,"stop");\r
370       Uci->searching = false;\r
371 */\r
372 \r
373       if (option_get_bool("SyncStop")) {\r
374          uci_send_stop_sync(Uci);\r
375       } else {\r
376          uci_send_stop(Uci);\r
377       }\r
378    }\r
379 }\r
380 \r
381 // end of main.cpp\r
382 \r