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