Add forgotten files 1.4.70b
[polyglot.git] / epd.cpp
1 \r
2 // epd.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 "board.h"\r
12 #include "engine.h"\r
13 #include "epd.h"\r
14 #include "fen.h"\r
15 #include "line.h"\r
16 #include "main.h"\r
17 #include "move.h"\r
18 #include "move_legal.h"\r
19 #include "option.h"\r
20 #include "parse.h"\r
21 #include "san.h"\r
22 #include "uci.h"\r
23 #include "util.h"\r
24 \r
25 // constants\r
26 \r
27 static const bool UseDebug = false;\r
28 static const bool UseTrace = false;\r
29 \r
30 static const int StringSize = 4096;\r
31 \r
32 // variables\r
33 \r
34 static int MinDepth;\r
35 static int MaxDepth;\r
36 \r
37 static double MaxTime;\r
38 static double MinTime;\r
39 \r
40 static int DepthDelta;\r
41 \r
42 static int FirstMove;\r
43 static int FirstDepth;\r
44 static int FirstSelDepth;\r
45 static int FirstScore;\r
46 static double FirstTime;\r
47 static uint64 FirstNodeNb;\r
48 static move_t FirstPV[LineSize];\r
49 \r
50 static int LastMove;\r
51 static int LastDepth;\r
52 static int LastSelDepth;\r
53 static int LastScore;\r
54 static double LastTime;\r
55 static uint64 LastNodeNb;\r
56 static move_t LastPV[LineSize];\r
57 \r
58 static my_timer_t Timer[1];\r
59 \r
60 // prototypes\r
61 \r
62 static void epd_test_file  (const char file_name[]);\r
63 \r
64 static bool is_solution    (int move, const board_t * board, const char bm[], const char am[]);\r
65 static bool string_contain (const char string[], const char substring[]);\r
66 \r
67 static bool engine_step    ();\r
68 \r
69 // functions\r
70 \r
71 // epd_test()\r
72 \r
73 void epd_test(int argc, char * argv[]) {\r
74 \r
75    int i;\r
76    const char * epd_file;\r
77 \r
78    epd_file = NULL;\r
79    my_string_set(&epd_file,"wac.epd");\r
80 \r
81    MinDepth = 8;\r
82    MaxDepth = 63;\r
83 \r
84    MinTime = 1.0;\r
85    MaxTime = 5.0;\r
86 \r
87    DepthDelta = 3;\r
88 \r
89    for (i = 1; i < argc; i++) {\r
90 \r
91       if (false) {\r
92 \r
93       } else if (my_string_equal(argv[i],"epd-test")) {\r
94 \r
95          // skip\r
96 \r
97       } else if (my_string_equal(argv[i],"-epd")) {\r
98 \r
99          i++;\r
100          if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
101 \r
102          my_string_set(&epd_file,argv[i]);\r
103 \r
104       } else if (my_string_equal(argv[i],"-min-depth")) {\r
105 \r
106          i++;\r
107          if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
108 \r
109          MinDepth = atoi(argv[i]);\r
110 \r
111       } else if (my_string_equal(argv[i],"-max-depth")) {\r
112 \r
113          i++;\r
114          if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
115 \r
116          MaxDepth = atoi(argv[i]);\r
117 \r
118       } else if (my_string_equal(argv[i],"-min-time")) {\r
119 \r
120          i++;\r
121          if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
122 \r
123          MinTime = atof(argv[i]);\r
124 \r
125       } else if (my_string_equal(argv[i],"-max-time")) {\r
126 \r
127          i++;\r
128          if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
129 \r
130          MaxTime = atof(argv[i]);\r
131 \r
132       } else if (my_string_equal(argv[i],"-depth-delta")) {\r
133 \r
134          i++;\r
135          if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
136 \r
137          DepthDelta = atoi(argv[i]);\r
138 \r
139       } else {\r
140 \r
141          my_fatal("epd_test(): unknown option \"%s\"\n",argv[i]);\r
142       }\r
143    }\r
144 \r
145    if(MinTime>MaxTime){\r
146        MaxTime=MinTime;\r
147    }\r
148   \r
149    epd_test_file(epd_file);\r
150 }\r
151 \r
152 // epd_test_file()\r
153 \r
154 static void epd_test_file(const char file_name[]) {\r
155 \r
156    FILE * file;\r
157    int hit, tot;\r
158    char epd[StringSize];\r
159    char am[StringSize], bm[StringSize], id[StringSize];\r
160    board_t board[1];\r
161    char string[StringSize];\r
162    int move;\r
163    char pv_string[StringSize];\r
164    bool correct;\r
165    double depth_tot, time_tot, node_tot;\r
166    int line=0;\r
167 \r
168    ASSERT(file_name!=NULL);\r
169 \r
170    // init\r
171 \r
172    file = fopen(file_name,"r");\r
173    if (file == NULL) my_fatal("epd_test_file(): can't open file \"%s\": %s\n",file_name,strerror(errno));\r
174 \r
175    hit = 0;\r
176    tot = 0;\r
177 \r
178    depth_tot = 0.0;\r
179    time_tot = 0.0;\r
180    node_tot = 0.0;\r
181 \r
182    printf("\nEngineName=%s\n",option_get_string("EngineName"));\r
183 \r
184    printf("\n[Search parameters: MaxDepth=%d   MaxTime=%.1f   DepthDelta=%d   MinDepth=%d   MinTime=%.1f]\n\n",MaxDepth,MaxTime,DepthDelta,MinDepth,MinTime);\r
185 \r
186    // loop\r
187 \r
188    while (my_file_read_line(file,epd,StringSize)) {\r
189        line++;\r
190        if(my_string_whitespace(epd)) continue;\r
191       if (UseTrace) printf("%s\n",epd);\r
192 \r
193       if (!epd_get_op(epd,"am",am,StringSize)) strcpy(am,"");\r
194       if (!epd_get_op(epd,"bm",bm,StringSize)) strcpy(bm,"");\r
195       if (!epd_get_op(epd,"id",id,StringSize)) strcpy(id,"");\r
196 \r
197       if (my_string_empty(am) && my_string_empty(bm)) {\r
198           my_fatal("epd_test(): no am or bm field at line %d\n",line);\r
199       }\r
200 \r
201       // init\r
202 \r
203       uci_send_ucinewgame(Uci);\r
204       uci_send_isready_sync(Uci);\r
205 \r
206       ASSERT(!Uci->searching);\r
207 \r
208       // position\r
209       if (!board_from_fen(board,epd)) ASSERT(false);\r
210       if (!board_to_fen(board,string,StringSize)) ASSERT(false);\r
211 \r
212       engine_send(Engine,"position fen %s",string);\r
213 \r
214       // search\r
215 \r
216       my_timer_start(Timer); // also resets\r
217       \r
218       // which ones of the next two alternatives is best?\r
219       engine_send(Engine,"go movetime %.0f depth %d",MaxTime*1000.0,MaxDepth);\r
220       //engine_send(Engine,"go infinite");\r
221 \r
222       // engine data\r
223 \r
224       board_copy(Uci->board,board);\r
225 \r
226       uci_clear(Uci);\r
227       Uci->searching = true;\r
228       Uci->pending_nb++;\r
229 \r
230       FirstMove = MoveNone;\r
231       FirstDepth = 0;\r
232       FirstSelDepth = 0;\r
233       FirstScore = 0;\r
234       FirstTime = 0.0;\r
235       FirstNodeNb = 0;\r
236       line_clear(FirstPV);\r
237 \r
238       LastMove = MoveNone;\r
239       LastDepth = 0;\r
240       LastSelDepth = 0;\r
241       LastScore = 0;\r
242       LastTime = 0.0;\r
243       LastNodeNb = 0;\r
244       line_clear(LastPV);\r
245 \r
246       // parse engine output\r
247 \r
248       while (!engine_eof(Engine) && engine_step()) {\r
249           bool stop=false;\r
250 \r
251          // stop search?\r
252 //          printf("Uci->time=%.2f time=%.2f\n",Uci->time,my_timer_elapsed_real(Timer));\r
253           if (Uci->depth > MaxDepth){\r
254               my_log("POLYGLOT Maximum depth %d reached\n",MaxDepth);\r
255               stop=true;\r
256           }else if(my_timer_elapsed_real(Timer) >= MaxTime){\r
257               my_log("POLYGLOT Maximum search time %.2fs reached\n",MaxTime);\r
258               stop=true;\r
259           }else if(Uci->depth - FirstDepth >= DepthDelta){\r
260               if(Uci->depth > MinDepth){\r
261                   if(Uci->time >= MinTime){\r
262                       if(is_solution(FirstMove,board,bm,am)){\r
263                           my_log("POLYGLOT Solution found\n",MaxTime);\r
264                           stop=true;\r
265                       }\r
266                   }\r
267               }\r
268           }\r
269           if(stop){\r
270               my_log("POLYGLOT Stopping engine\n");\r
271               engine_send(Engine,"stop");\r
272               break;\r
273           }\r
274       }\r
275       \r
276       move = FirstMove;\r
277       correct = is_solution(move,board,bm,am);\r
278 \r
279       if (correct) hit++;\r
280       tot++;\r
281 \r
282       if (correct) {\r
283          depth_tot += double(FirstDepth);\r
284          time_tot += FirstTime;\r
285          node_tot += double(sint64(FirstNodeNb));\r
286       }\r
287 \r
288       printf("%2d: %-15s %s %4d",tot,id,correct?"OK":"--",hit);\r
289 \r
290       if (!line_to_san(LastPV,Uci->board,pv_string,StringSize)) ASSERT(false);\r
291       printf(" score=%+6.2f    pv [D=%2d, T=%7.2fs, N=%6dk] =%s\n",double(LastScore)/100.0,FirstDepth,FirstTime,(int)FirstNodeNb/1000,pv_string);\r
292    }\r
293 \r
294    printf("\nscore=%d/%d",hit,tot);\r
295 \r
296    if (hit != 0) {\r
297 \r
298       depth_tot /= double(hit);\r
299       time_tot /= double(hit);\r
300       node_tot /= double(hit);\r
301 \r
302       printf(" [averages on correct positions: depth=%.1f time=%.2f nodes=%.0f]",depth_tot,time_tot,node_tot);\r
303    }\r
304 \r
305    printf("\n");\r
306 \r
307    fclose(file);\r
308    quit();\r
309 }\r
310 \r
311 // is_solution()\r
312 \r
313 static bool is_solution(int move, const board_t * board, const char bm[], const char am[]) {\r
314 \r
315    char move_string[256];\r
316    bool correct;\r
317 \r
318    ASSERT(move!=MoveNone);\r
319    ASSERT(bm!=NULL);\r
320    ASSERT(am!=NULL);\r
321 \r
322    if (!move_is_legal(move,board)) {\r
323       board_disp(board);\r
324       move_disp(move,board);\r
325       printf("\n\n");\r
326    }\r
327 \r
328    ASSERT(move_is_legal(move,board));\r
329 \r
330    if (!move_to_san(move,board,move_string,256)) ASSERT(false);\r
331 \r
332    correct = false;\r
333    if (!my_string_empty(bm)) {\r
334       correct = string_contain(bm,move_string);\r
335    } else if (!my_string_empty(am)) {\r
336       correct = !string_contain(am,move_string);\r
337    } else {\r
338       ASSERT(false);\r
339    }\r
340 \r
341    return correct;\r
342 }\r
343 \r
344 // epd_get_op()\r
345 \r
346 bool epd_get_op(const char record[], const char opcode[], char string[], int size) {\r
347 \r
348    char op[256];\r
349    int len;\r
350    const char *p_start, *p_end;\r
351 \r
352    ASSERT(record!=NULL);\r
353    ASSERT(opcode!=NULL);\r
354    ASSERT(string!=NULL);\r
355    ASSERT(size>0);\r
356 \r
357    // find the opcode\r
358 \r
359    sprintf(op," %s ",opcode); \r
360 \r
361    p_start = strstr(record,op);\r
362    if (p_start == NULL){\r
363           sprintf(op,";%s ",opcode); \r
364           p_start = strstr(record,op);\r
365           if (p_start == NULL){\r
366               return false;\r
367           }\r
368    }\r
369 \r
370    // skip the opcode\r
371 \r
372    p_start += strlen(op);\r
373 \r
374    // find the end\r
375    p_end = strchr(p_start,';');\r
376    if (p_end == NULL) return false;\r
377 \r
378    // calculate the length\r
379 \r
380    len = p_end - p_start;\r
381    if (size < len+1) my_fatal("epd_get_op(): size < len+1\n");\r
382 \r
383    strncpy(string,p_start,len);\r
384    string[len] = '\0';\r
385 \r
386    return true;\r
387 }\r
388 \r
389 // string_contain()\r
390 \r
391 static bool string_contain(const char string[], const char substring[]) {\r
392 \r
393    char new_string[StringSize], *p;\r
394 \r
395    strcpy(new_string,string); // HACK\r
396 \r
397    for (p = strtok(new_string," "); p != NULL; p = strtok(NULL," ")) {\r
398       if (my_string_equal(p,substring)) return true;\r
399    }\r
400 \r
401    return false;\r
402 }\r
403 \r
404 // engine_step()\r
405 \r
406 static bool engine_step() {\r
407 \r
408    char string[StringSize];\r
409    int event;\r
410 \r
411    engine_get(Engine,string,StringSize);\r
412    event = uci_parse(Uci,string);\r
413 \r
414    if ((event & EVENT_MOVE) != 0) {\r
415 \r
416       return false;\r
417    }\r
418 \r
419    if ((event & EVENT_PV) != 0) {\r
420 \r
421       LastMove = Uci->best_pv[0];\r
422       LastDepth = Uci->best_depth;\r
423       LastSelDepth = Uci->best_sel_depth;\r
424       LastScore = Uci->best_score;\r
425       LastTime = Uci->time;\r
426       LastNodeNb = Uci->node_nb;\r
427       line_copy(LastPV,Uci->best_pv);\r
428 \r
429       if (LastMove != FirstMove) {\r
430          FirstMove = LastMove;\r
431          FirstDepth = LastDepth;\r
432          FirstSelDepth = LastSelDepth;\r
433          FirstScore = LastScore;\r
434          FirstTime = LastTime;\r
435          FirstNodeNb = LastNodeNb;\r
436          line_copy(FirstPV,LastPV);\r
437       }\r
438    }\r
439 \r
440    return true;\r
441 }\r
442 \r
443 // end of epd.cpp\r
444 \r