18 #include "move_legal.h"
\r
27 static const bool UseDebug = false;
\r
28 static const bool UseTrace = false;
\r
30 static const int StringSize = 4096;
\r
34 static int MinDepth;
\r
35 static int MaxDepth;
\r
37 static double MaxTime;
\r
38 static double MinTime;
\r
40 static int DepthDelta;
\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
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
60 static void epd_test_file (const char file_name[]);
\r
62 static bool is_solution (int move, const board_t * board, const char bm[], const char am[]);
\r
63 static bool string_contain (const char string[], const char substring[]);
\r
65 static bool engine_step ();
\r
71 void epd_test(int argc, char * argv[]) {
\r
74 const char * epd_file;
\r
77 my_string_set(&epd_file,"wac.epd");
\r
87 for (i = 1; i < argc; i++) {
\r
91 } else if (my_string_equal(argv[i],"epd-test")) {
\r
95 } else if (my_string_equal(argv[i],"-epd")) {
\r
98 if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");
\r
100 my_string_set(&epd_file,argv[i]);
\r
102 } else if (my_string_equal(argv[i],"-min-depth")) {
\r
105 if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");
\r
107 MinDepth = atoi(argv[i]);
\r
109 } else if (my_string_equal(argv[i],"-max-depth")) {
\r
112 if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");
\r
114 MaxDepth = atoi(argv[i]);
\r
116 } else if (my_string_equal(argv[i],"-min-time")) {
\r
119 if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");
\r
121 MinTime = atof(argv[i]);
\r
123 } else if (my_string_equal(argv[i],"-max-time")) {
\r
126 if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");
\r
128 MaxTime = atof(argv[i]);
\r
130 } else if (my_string_equal(argv[i],"-depth-delta")) {
\r
133 if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");
\r
135 DepthDelta = atoi(argv[i]);
\r
139 my_fatal("epd_test(): unknown option \"%s\"\n",argv[i]);
\r
143 if(MinTime>MaxTime){
\r
147 epd_test_file(epd_file);
\r
152 static void epd_test_file(const char file_name[]) {
\r
156 char epd[StringSize];
\r
157 char am[StringSize], bm[StringSize], id[StringSize];
\r
159 char string[StringSize];
\r
161 char pv_string[StringSize];
\r
163 double depth_tot, time_tot, node_tot;
\r
166 ASSERT(file_name!=NULL);
\r
170 file = fopen(file_name,"r");
\r
171 if (file == NULL) my_fatal("epd_test_file(): can't open file \"%s\": %s\n",file_name,strerror(errno));
\r
180 printf("\nEngineName=%s\n",option_get_string("EngineName"));
\r
182 printf("\n[Search parameters: MaxDepth=%d MaxTime=%.1f DepthDelta=%d MinDepth=%d MinTime=%.1f]\n\n",MaxDepth,MaxTime,DepthDelta,MinDepth,MinTime);
\r
186 while (my_file_read_line(file,epd,StringSize)) {
\r
188 if(my_string_whitespace(epd)) continue;
\r
189 if (UseTrace) printf("%s\n",epd);
\r
191 if (!epd_get_op(epd,"am",am,StringSize)) strcpy(am,"");
\r
192 if (!epd_get_op(epd,"bm",bm,StringSize)) strcpy(bm,"");
\r
193 if (!epd_get_op(epd,"id",id,StringSize)) strcpy(id,"");
\r
195 if (my_string_empty(am) && my_string_empty(bm)) {
\r
196 my_fatal("epd_test(): no am or bm field at line %d\n",line);
\r
201 uci_send_ucinewgame(Uci);
\r
202 uci_send_isready_sync(Uci);
\r
204 ASSERT(!Uci->searching);
\r
207 if (!board_from_fen(board,epd)) ASSERT(false);
\r
208 if (!board_to_fen(board,string,StringSize)) ASSERT(false);
\r
210 engine_send(Engine,"position fen %s",string);
\r
214 // which ones of the next two alternatives is best?
\r
215 engine_send(Engine,"go movetime %.0f depth %d",MaxTime*1000.0,MaxDepth);
\r
216 //engine_send(Engine,"go infinite");
\r
220 board_copy(Uci->board,board);
\r
223 Uci->searching = true;
\r
226 FirstMove = MoveNone;
\r
232 line_clear(FirstPV);
\r
234 LastMove = MoveNone;
\r
240 line_clear(LastPV);
\r
242 // parse engine output
\r
244 while (engine_step()) {
\r
248 if (Uci->depth > MaxDepth){
\r
249 my_log("POLYGLOT Maximum depth %d reached\n",MaxDepth);
\r
251 }else if(Uci->time >= MaxTime){
\r
252 my_log("POLYGLOT Maximum search time %.2fs reached\n",MaxTime);
\r
254 }else if(Uci->depth - FirstDepth >= DepthDelta){
\r
255 my_log("POLYGLOT DepthDelta (=%d) reached\n",DepthDelta);
\r
256 if(Uci->depth > MinDepth){
\r
257 my_log("POLYGLOT Minimum depth %d reached\n",MinDepth);
\r
258 if(Uci->time >= MinTime){
\r
259 my_log("POLYGLOT Minimum search time %.2fs reached\n",MinTime);
\r
260 if(is_solution(FirstMove,board,bm,am)){
\r
261 my_log("POLYGLOT Solution is correct\n");
\r
264 my_log("POLYGLOT Solution is not correct\n");
\r
270 my_log("POLYGLOT Stopping engine\n");
\r
271 engine_send(Engine,"stop");
\r
277 correct = is_solution(move,board,bm,am);
\r
279 if (correct) hit++;
\r
283 depth_tot += double(FirstDepth);
\r
284 time_tot += FirstTime;
\r
285 node_tot += double(FirstNodeNb);
\r
288 printf("%2d: %-15s %s %4d",tot,id,correct?"OK":"--",hit);
\r
290 if (!line_to_san(LastPV,Uci->board,pv_string,StringSize)) ASSERT(false);
\r
291 printf(" [at: depth=%2d time=%6.2f nodes="S64_FORMAT"] score=%+6.2f pv=%s\n",FirstDepth,FirstTime,FirstNodeNb,double(LastScore)/100.0,pv_string);
\r
294 printf("\nscore=%d/%d",hit,tot);
\r
298 depth_tot /= double(hit);
\r
299 time_tot /= double(hit);
\r
300 node_tot /= double(hit);
\r
302 printf(" [averages on correct positions: depth=%.1f time=%.2f nodes=%.0f]",depth_tot,time_tot,node_tot);
\r
313 static bool is_solution(int move, const board_t * board, const char bm[], const char am[]) {
\r
315 char move_string[256];
\r
318 ASSERT(move!=MoveNone);
\r
322 if (!move_is_legal(move,board)) {
\r
324 move_disp(move,board);
\r
328 ASSERT(move_is_legal(move,board));
\r
330 if (!move_to_san(move,board,move_string,256)) ASSERT(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
346 bool epd_get_op(const char record[], const char opcode[], char string[], int size) {
\r
350 const char *p_start, *p_end;
\r
352 ASSERT(record!=NULL);
\r
353 ASSERT(opcode!=NULL);
\r
354 ASSERT(string!=NULL);
\r
359 sprintf(op," %s ",opcode);
\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
372 p_start += strlen(op);
\r
375 p_end = strchr(p_start,';');
\r
376 if (p_end == NULL) return false;
\r
378 // calculate the length
\r
380 len = p_end - p_start;
\r
381 if (size < len+1) my_fatal("epd_get_op(): size < len+1\n");
\r
383 strncpy(string,p_start,len);
\r
384 string[len] = '\0';
\r
389 // string_contain()
\r
391 static bool string_contain(const char string[], const char substring[]) {
\r
393 char new_string[StringSize], *p;
\r
395 strcpy(new_string,string); // HACK
\r
397 for (p = strtok(new_string," "); p != NULL; p = strtok(NULL," ")) {
\r
398 if (my_string_equal(p,substring)) return true;
\r
406 static bool engine_step() {
\r
408 char string[StringSize];
\r
411 engine_get(Engine,string,StringSize);
\r
412 event = uci_parse(Uci,string);
\r
414 if ((event & EVENT_MOVE) != 0) {
\r
419 if ((event & EVENT_PV) != 0) {
\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
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