version 1.4b27
[polyglot.git] / main.cpp
1 \r
2 // main.cpp\r
3 \r
4 // includes\r
5 \r
6 #include <cerrno>\r
7 #include <cstdio>\r
8 #include <cstdlib>\r
9 #include <cstring>\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.4b27";\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 dumb-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 //   board_t board[1];\r
73 \r
74     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
75         printf("%s\n",HelpMessage);\r
76         return EXIT_SUCCESS;\r
77     }\r
78    // init\r
79 \r
80     Init = false;\r
81 \r
82     util_init();\r
83     printf("PolyGlot %s by Fabien Letouzey\n",Version);\r
84     \r
85     option_init();\r
86     \r
87     square_init();\r
88     piece_init();\r
89     attack_init();\r
90     \r
91     hash_init();\r
92     \r
93     my_random_init();\r
94 \r
95         // build book\r
96     \r
97     if (argc >= 2 && my_string_equal(argv[1],"make-book")) {\r
98         book_make(argc,argv);\r
99         return EXIT_SUCCESS;\r
100     }\r
101     \r
102     if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {\r
103         book_merge(argc,argv);\r
104         return EXIT_SUCCESS;\r
105     }\r
106 \r
107        if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {\r
108       book_merge(argc,argv);\r
109       return EXIT_SUCCESS;\r
110    }\r
111 \r
112    if (argc >= 2 && my_string_equal(argv[1],"dump-book")) {\r
113       book_dump(argc,argv);\r
114       return EXIT_SUCCESS;\r
115    }\r
116 \r
117    if (argc >= 2 && my_string_equal(argv[1],"info-book")) {\r
118       book_info(argc,argv);\r
119       return EXIT_SUCCESS;\r
120    }\r
121     \r
122     if (argc >= 2 && my_string_equal(argv[1],"perft")) {\r
123         do_perft(argc,argv);\r
124         return EXIT_SUCCESS;\r
125     }\r
126     \r
127     if (argc >= 3 && my_string_equal(argv[1],"-ec")) {\r
128         option_set("EngineCommand",argv[2]);\r
129         engine_open(Engine);\r
130         if(!engine_active(Engine)){\r
131             my_fatal("Could not start \"%s\"\n",option_get("EngineCommand"));\r
132         }\r
133         Init=true;\r
134         gui_init(GUI);\r
135         uci_open(Uci,Engine);\r
136         if (my_string_equal(option_get_string("EngineName"),"<empty>")) {\r
137             option_set("EngineName",Uci->name);\r
138         }\r
139         mainloop();\r
140         return EXIT_SUCCESS; \r
141     }\r
142     \r
143         // read options\r
144     \r
145     if (argc == 2) option_set("OptionFile",argv[1]); // HACK for compatibility\r
146 \r
147     parse_option(); // HACK: also launches the engine\r
148     \r
149         // EPD test\r
150     \r
151     if (argc >= 2 && my_string_equal(argv[1],"epd-test")){\r
152         epd_test(argc,argv);\r
153         return EXIT_SUCCESS;\r
154     }else if(argc >= 3 && my_string_equal(argv[2],"epd-test")){\r
155         epd_test(argc-1,argv+1);\r
156         return EXIT_SUCCESS;\r
157     }\r
158     \r
159     if (argc >= 3) my_fatal("Too many arguments\n");\r
160 \r
161 \r
162     init_book();\r
163     gui_init(GUI);\r
164     mainloop();\r
165     return EXIT_SUCCESS; \r
166 }\r
167 \r
168 // polyglot_set_option\r
169 \r
170 void polyglot_set_option(char *name, char *value){ // this must be cleaned up!\r
171     option_set(name,value);\r
172     if(option_get_bool("Book")&&(my_string_case_equal(name,"BookFile")||my_string_case_equal(name,"Book"))){\r
173         my_log("POLYGLOT *** SETTING BOOK ***\n");\r
174         my_log("POLYGLOT BOOK \"%s\"\n",option_get_string("BookFile"));\r
175         book_close();\r
176         book_clear();\r
177         book_open(option_get_string("BookFile"));\r
178         if(!book_is_open()){\r
179             my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string("BookFile"));\r
180         }\r
181     }else if(option_get_bool("Log")&&(my_string_case_equal(name,"LogFile") ||my_string_case_equal(name,"Log"))){\r
182         my_log("POLYGLOT *** SETTING LOGFILE ***\n");\r
183         my_log("POLYGLOT LOGFILE \"%s\"\n",option_get_string("LogFile"));\r
184         my_log_close();\r
185         my_log_open(option_get_string("LogFile"));\r
186     }else if(option_get_bool("UseNice") &&(my_string_case_equal(name,"NiceValue")||my_string_case_equal(name,"UseNice"))){\r
187         my_log("POLYGLOT Adjust Engine Piority\n");\r
188         engine_set_nice_value(Engine,atoi(option_get_string("NiceValue")));\r
189     }else if(my_string_case_equal(name,"Book") && !option_get_bool("Book")){\r
190         book_close();\r
191         book_clear();\r
192     }else if(my_string_case_equal(name,"UseNice") && !option_get_bool("UseNice")){\r
193         my_log("POLYGLOT Adjust Engine Piority\n");\r
194         engine_set_nice_value(Engine,0);\r
195     }else if(my_string_case_equal(name,"Log") && !option_get_bool("Log")){\r
196         my_log("POLYGLOT QUIT LOGGING\n");\r
197         my_log_close();\r
198     }\r
199 }\r
200 \r
201 \r
202 // init_book()\r
203 \r
204 static void init_book(){\r
205     book_clear();\r
206     if (option_get_bool("Book")){\r
207         my_log("POLYGLOT *** SETTING BOOK ***\n");\r
208         my_log("POLYGLOT BOOK \"%s\"\n",option_get_string("BookFile"));\r
209         book_open(option_get_string("BookFile"));\r
210         if(!book_is_open()){\r
211             my_log("POLYGLOT Unable to open book \"%s\"\n",\r
212                    option_get_string("BookFile"));\r
213         }\r
214     }\r
215 }\r
216 \r
217 // parse_option()\r
218 \r
219 static void parse_option() {\r
220 \r
221     const char * file_name;\r
222     FILE * file;\r
223     char line[256];\r
224     char * name, * value;\r
225     file_name = option_get_string("OptionFile");\r
226     \r
227     file = fopen(file_name,"r");\r
228     if (file == NULL) {\r
229         my_fatal("Can't open file \"%s\": %s\n",file_name,strerror(errno));\r
230     }\r
231     \r
232         // PolyGlot options (assumed first)\r
233     \r
234    while (true) {\r
235        \r
236        if (!my_file_read_line(file,line,256)) {\r
237            my_fatal("parse_option(): missing [Engine] section\n");\r
238        }\r
239        \r
240        if (my_string_case_equal(line,"[engine]")) break;\r
241        \r
242        if (parse_line(line,&name,&value)) {\r
243            option_set(name,value);\r
244            option_set_default(name,value);\r
245        }\r
246    }\r
247    \r
248    if (option_get_bool("Log")) {\r
249        my_log_open(option_get_string("LogFile"));\r
250    }\r
251    \r
252    my_log("POLYGLOT *** START ***\n");\r
253    my_log("POLYGLOT INI file \"%s\"\n",file_name);\r
254    engine_open(Engine);\r
255    if(!engine_active(Engine)){\r
256        my_fatal("Could not start \"%s\"\n",option_get("EngineCommand"));\r
257    }\r
258 \r
259    if (option_get_bool("UCI")) {\r
260        my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
261    }\r
262    uci_open(Uci,Engine);\r
263    Init = true;\r
264    while (my_file_read_line(file,line,256)) {\r
265        if (line[0] == '[') my_fatal("parse_option(): unknown section %s\n",line);\r
266        if (parse_line(line,&name,&value)) {\r
267            uci_send_option(Uci,name,"%s",value);\r
268                //to get a decent display in winboard_x we need to now if an engine really is doing multipv analysis\r
269                // "multipv 1" in the pv is meaningless,f.i. toga sends that all the time\r
270                //therefore check if MultiPV is set to a decent value in the polyglot ini file\r
271            if(my_string_case_equal(name,"MultiPV") && atoi(value)>1)  Uci->multipv_mode=true;\r
272        }\r
273    }\r
274    if (my_string_equal(option_get_string("EngineName"),"<empty>")) {\r
275        option_set("EngineName",Uci->name);\r
276    }\r
277    \r
278    fclose(file);\r
279 }\r
280 \r
281 // parse_line()\r
282 \r
283 static bool parse_line(char line[], char * * name_ptr, char * * value_ptr) {\r
284     \r
285     char * ptr;\r
286     char * name, * value;\r
287     \r
288     ASSERT(line!=NULL);\r
289     ASSERT(name_ptr!=NULL);\r
290     ASSERT(value_ptr!=NULL);\r
291     \r
292         // remove comments\r
293     \r
294     ptr = strchr(line,';');\r
295     if (ptr != NULL) *ptr = '\0';\r
296     \r
297     ptr = strchr(line,'#');\r
298     if (ptr != NULL) *ptr = '\0';\r
299     \r
300         // split at '='\r
301     \r
302     ptr = strchr(line,'=');\r
303     if (ptr == NULL) return false;\r
304     \r
305     name = line;\r
306     value = ptr+1;\r
307    \r
308         // cleanup name\r
309     \r
310     while (*name == ' ') name++; // remove leading spaces\r
311     \r
312     while (ptr > name && ptr[-1] == ' ') ptr--; // remove trailing spaces\r
313     *ptr = '\0';\r
314     \r
315     if (*name == '\0') return false;\r
316     \r
317         // cleanup value\r
318     \r
319     ptr = &value[strlen(value)]; // pointer to string terminator\r
320     \r
321     while (*value == ' ') value++; // remove leading spaces\r
322     \r
323     while (ptr > value && ptr[-1] == ' ') ptr--; // remove trailing spaces\r
324     *ptr = '\0';\r
325     \r
326     if (*value == '\0') return false;\r
327    \r
328         // end\r
329     \r
330     *name_ptr = name;\r
331     *value_ptr = value;\r
332     \r
333     return true;\r
334 }\r
335 \r
336 // quit()\r
337 \r
338 void quit() {\r
339 \r
340     my_log("POLYGLOT *** QUIT ***\n");\r
341     \r
342     if (Init) {\r
343         \r
344         stop_search();\r
345         engine_send(Engine,"quit");\r
346         my_log("POLYGLOT Closing engine\n");\r
347         engine_close(Engine);\r
348         \r
349     }\r
350     my_log("POLYGLOT Calling exit\n");\r
351     exit(EXIT_SUCCESS);\r
352 }\r
353 \r
354 // stop_search()\r
355 \r
356 static void stop_search() {\r
357     \r
358     if (Init && Uci->searching) {\r
359         \r
360         ASSERT(Uci->searching);\r
361         ASSERT(Uci->pending_nb>=1);\r
362         \r
363         my_log("POLYGLOT STOP SEARCH\n");\r
364         \r
365         if (option_get_bool("SyncStop")) {\r
366             uci_send_stop_sync(Uci);\r
367         } else {\r
368             uci_send_stop(Uci);\r
369         }\r
370     }\r
371 }\r
372 \r
373 \r
374 // end of main.cpp\r
375 \r