1 /* main.cpp
2
3 GNU Chess protocol adapter
4
5 Copyright (C) 2001-2015 Free Software Foundation, Inc.
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21
22 // main.cpp
23
24 // includes
25
26 #include <pthread.h>
27 #include <cerrno>
28 #include <csignal>
29 #include <cstdio>
30 #include <cstdlib>
31 #include <cstring>
32
33 #include "adapter.h"
34 #include "attack.h"
35 #include "board.h"
36 #include "book.h"
37 #include "book_make.h"
38 #include "book_merge.h"
39 #include "engine.h"
40 #include "epd.h"
41 #include "fen.h"
42 #include "hash.h"
43 #include "list.h"
44 #include "main.h"
45 #include "move.h"
46 #include "move_gen.h"
47 #include "option.h"
48 #include "piece.h"
49 #include "search.h"
50 #include "square.h"
51 #include "uci.h"
52 #include "util.h"
53
54 namespace adapter {
55
56 // constants
57
58 static const char * const Version = "1.4";
59
60 static const bool BlockSignal = false; // true on Windows
61
62 static const int SearchDepth = 63;
63 static const double SearchTime = 3600.0;
64
65 static const int StringSize = 4096;
66
67 // variables
68
69 static bool Init;
70 extern unsigned int HashSize;
71 pthread_mutex_t adapter_init_mutex;
72 pthread_cond_t adapter_init_cond;
73
74 // prototypes
75
76 static void parse_option ();
77 static bool parse_line (char line[], char * * name_ptr, char * * value_ptr);
78
79 static void stop_search ();
80
81 // functions
82
83 // main()
84
main_adapter(int argc,char * argv[])85 int main_adapter(int argc, char * argv[]) {
86
87 // init
88
89 Init = false;
90
91 if (BlockSignal) {
92 signal(SIGINT,SIG_IGN);
93 signal(SIGTERM,SIG_IGN);
94 signal(SIGPIPE,SIG_IGN);
95 }
96
97 util_init();
98
99 option_init();
100
101 square_init();
102 piece_init();
103 attack_init();
104
105 hash_init();
106
107 my_random_init();
108
109 // build book
110
111 if (argc >= 2 && my_string_equal(argv[1],"make-book")) {
112 book_make(argc,argv);
113 return EXIT_SUCCESS;
114 }
115
116 if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {
117 book_merge(argc,argv);
118 return EXIT_SUCCESS;
119 }
120
121 // read options
122
123 if (argc == 2) option_set("OptionFile",argv[1]); // HACK for compatibility
124
125 parse_option(); // HACK: also launches the engine
126
127 // EPD test
128
129 if (argc >= 2 && my_string_equal(argv[1],"epd-test")) {
130 epd_test(argc,argv);
131 return EXIT_SUCCESS;
132 }
133
134 // opening book
135
136 book_clear();
137 if (option_get_bool("Book")) {
138 int mode = BookReadOnly;
139 if (option_get_bool("BookLearn")) {
140 mode = BookReadWrite;
141 }
142 book_open(option_get_string("BookFile"),mode);
143 }
144
145 // flag adapter initialized
146 pthread_mutex_lock( &adapter_init_mutex );
147 pthread_cond_signal( &adapter_init_cond );
148 pthread_mutex_unlock( &adapter_init_mutex );
149
150 // adapter
151 adapter_loop();
152
153 engine_send(Engine,"quit");
154 engine_close(Engine);
155
156 return EXIT_SUCCESS;
157 }
158
159 // parse_option()
160
parse_option()161 static void parse_option() {
162
163 const char * file_name;
164 FILE * file;
165 char line[256];
166 char * name, * value;
167
168 file_name = option_get_string("OptionFile");
169
170 file = fopen(file_name,"r");
171 if (file == NULL) my_fatal( "Can't open file \"%s\": %s - using defaults\n",file_name,strerror(errno));
172
173 // PolyGlot options (assumed first)
174
175 if ( file != NULL ) {
176 while (true) {
177
178 if (!my_file_read_line(file,line,256)) {
179 my_fatal("parse_option(): missing [Engine] section\n");
180 }
181
182 if (my_string_case_equal(line,"[engine]")) break;
183
184 if (parse_line(line,&name,&value)) option_set(name,value);
185 }
186 }
187
188 if (option_get_bool("Log")) {
189 my_log_open(option_get_string("LogFile"));
190 }
191
192 my_log("POLYGLOT *** START ***\n");
193 my_log("POLYGLOT INI file \"%s\"\n",file_name);
194
195 // engine options (assumed second and last)
196
197 engine_open(Engine);
198 Init = true; // engine has been launched
199 uci_open(Uci,Engine);
200
201 if ( file != NULL ) {
202 while (my_file_read_line(file,line,256)) {
203
204 if (line[0] == '[') my_fatal("parse_option(): unknown section %s\n",line);
205
206 if (parse_line(line,&name,&value)) {
207 if ( strcmp(name,"Hash") == 0 ) {
208 sscanf( value, "%d", &HashSize );
209 }
210 uci_send_option(Uci,name,"%s",value);
211 }
212 }
213 }
214
215 uci_send_isready(Uci);
216
217 if ( file != NULL ) {
218 fclose(file);
219 }
220
221 if (my_string_equal(option_get_string("EngineName"),"<empty>")) {
222 option_set("EngineName",Uci->name);
223 }
224 }
225
226 // parse_line()
227
parse_line(char line[],char ** name_ptr,char ** value_ptr)228 static bool parse_line(char line[], char * * name_ptr, char * * value_ptr) {
229
230 char * ptr;
231 char * name, * value;
232
233 ASSERT(line!=NULL);
234 ASSERT(name_ptr!=NULL);
235 ASSERT(value_ptr!=NULL);
236
237 // remove comments
238
239 ptr = strchr(line,';');
240 if (ptr != NULL) *ptr = '\0';
241
242 ptr = strchr(line,'#');
243 if (ptr != NULL) *ptr = '\0';
244
245 // split at '='
246
247 ptr = strchr(line,'=');
248 if (ptr == NULL) return false;
249
250 name = line;
251 value = ptr+1;
252
253 // cleanup name
254
255 while (*name == ' ') name++; // remove leading spaces
256
257 while (ptr > name && ptr[-1] == ' ') ptr--; // remove trailing spaces
258 *ptr = '\0';
259
260 if (*name == '\0') return false;
261
262 // cleanup value
263
264 ptr = &value[strlen(value)]; // pointer to string terminator
265
266 while (*value == ' ') value++; // remove leading spaces
267
268 while (ptr > value && ptr[-1] == ' ') ptr--; // remove trailing spaces
269 *ptr = '\0';
270
271 if (*value == '\0') return false;
272
273 // end
274
275 *name_ptr = name;
276 *value_ptr = value;
277
278 return true;
279 }
280
281 // quit()
282
quit()283 void quit() {
284
285 char string[StringSize];
286
287 my_log("POLYGLOT *** QUIT ***\n");
288
289 if (Init) {
290
291 stop_search();
292 engine_send(Engine,"quit");
293
294 pthread_exit(NULL);
295
296 // wait for the engine to quit
297
298 while (true) {
299 engine_get(Engine,string,StringSize); // HACK: calls exit() on receiving EOF
300 }
301
302 uci_close(Uci);
303 }
304
305 //exit(EXIT_SUCCESS);
306 }
307
308 // stop_search()
309
stop_search()310 static void stop_search() {
311
312 if (Init && Uci->searching) {
313
314 ASSERT(Uci->searching);
315 ASSERT(Uci->pending_nb>=1);
316
317 my_log("POLYGLOT STOP SEARCH\n");
318
319 /*
320 engine_send(Engine,"stop");
321 Uci->searching = false;
322 */
323
324 if (option_get_bool("SyncStop")) {
325 uci_send_stop_sync(Uci);
326 } else {
327 uci_send_stop(Uci);
328 }
329 }
330 }
331
332 } // namespace adapter
333
334 // end of main.cpp
335