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