--- /dev/null
+\r
+// epd.c\r
+\r
+// includes\r
+\r
+#include <errno.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "board.h"\r
+#include "engine.h"\r
+#include "epd.h"\r
+#include "fen.h"\r
+#include "line.h"\r
+#include "main.h"\r
+#include "move.h"\r
+#include "move_legal.h"\r
+#include "option.h"\r
+#include "parse.h"\r
+#include "san.h"\r
+#include "uci.h"\r
+#include "util.h"\r
+\r
+// constants\r
+\r
+static const bool UseDebug = FALSE;\r
+static const bool UseTrace = FALSE;\r
+\r
+static const int StringSize = 4096;\r
+\r
+// variables\r
+\r
+static int MinDepth;\r
+static int MaxDepth;\r
+\r
+static double MaxTime;\r
+static double MinTime;\r
+\r
+static int DepthDelta;\r
+\r
+static int FirstMove;\r
+static int FirstDepth;\r
+static int FirstSelDepth;\r
+static int FirstScore;\r
+static double FirstTime;\r
+static uint64 FirstNodeNb;\r
+static move_t FirstPV[LineSize];\r
+\r
+static int LastMove;\r
+static int LastDepth;\r
+static int LastSelDepth;\r
+static int LastScore;\r
+static double LastTime;\r
+static uint64 LastNodeNb;\r
+static move_t LastPV[LineSize];\r
+\r
+static my_timer_t Timer[1];\r
+\r
+// prototypes\r
+\r
+static void epd_test_file (const char file_name[]);\r
+\r
+static bool is_solution (int move, const board_t * board, const char bm[], const char am[]);\r
+static bool string_contain (const char string[], const char substring[]);\r
+\r
+static bool engine_step ();\r
+\r
+// functions\r
+\r
+// epd_test()\r
+\r
+void epd_test(int argc, char * argv[]) {\r
+\r
+ int i;\r
+ const char * epd_file;\r
+\r
+ epd_file = NULL;\r
+ my_string_set(&epd_file,"wac.epd");\r
+\r
+ MinDepth = 8;\r
+ MaxDepth = 63;\r
+\r
+ MinTime = 1.0;\r
+ MaxTime = 5.0;\r
+\r
+ DepthDelta = 3;\r
+\r
+ for (i = 1; i < argc; i++) {\r
+\r
+ if (FALSE) {\r
+\r
+ } else if (my_string_equal(argv[i],"epd-test")) {\r
+\r
+ // skip\r
+\r
+ } else if (my_string_equal(argv[i],"-epd")) {\r
+\r
+ i++;\r
+ if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
+\r
+ my_string_set(&epd_file,argv[i]);\r
+\r
+ } else if (my_string_equal(argv[i],"-min-depth")) {\r
+\r
+ i++;\r
+ if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
+\r
+ MinDepth = atoi(argv[i]);\r
+\r
+ } else if (my_string_equal(argv[i],"-max-depth")) {\r
+\r
+ i++;\r
+ if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
+\r
+ MaxDepth = atoi(argv[i]);\r
+\r
+ } else if (my_string_equal(argv[i],"-min-time")) {\r
+\r
+ i++;\r
+ if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
+\r
+ MinTime = atof(argv[i]);\r
+\r
+ } else if (my_string_equal(argv[i],"-max-time")) {\r
+\r
+ i++;\r
+ if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
+\r
+ MaxTime = atof(argv[i]);\r
+\r
+ } else if (my_string_equal(argv[i],"-depth-delta")) {\r
+\r
+ i++;\r
+ if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
+\r
+ DepthDelta = atoi(argv[i]);\r
+\r
+ } else {\r
+\r
+ my_fatal("epd_test(): unknown option \"%s\"\n",argv[i]);\r
+ }\r
+ }\r
+\r
+ if(MinTime>MaxTime){\r
+ MaxTime=MinTime;\r
+ }\r
+ \r
+ epd_test_file(epd_file);\r
+}\r
+\r
+// epd_test_file()\r
+\r
+static void epd_test_file(const char file_name[]) {\r
+\r
+ FILE * file;\r
+ int hit, tot;\r
+ char epd[StringSize];\r
+ char am[StringSize], bm[StringSize], id[StringSize];\r
+ board_t board[1];\r
+ char string[StringSize];\r
+ int move;\r
+ char pv_string[StringSize];\r
+ bool correct;\r
+ double depth_tot, time_tot, node_tot;\r
+ int line=0;\r
+\r
+ ASSERT(file_name!=NULL);\r
+\r
+ // init\r
+\r
+ file = fopen(file_name,"r");\r
+ if (file == NULL) my_fatal("epd_test_file(): can't open file \"%s\": %s\n",file_name,strerror(errno));\r
+\r
+ hit = 0;\r
+ tot = 0;\r
+\r
+ depth_tot = 0.0;\r
+ time_tot = 0.0;\r
+ node_tot = 0.0;\r
+\r
+ printf("\nEngineName=%s\n",option_get_string("EngineName"));\r
+\r
+ printf("\n[Search parameters: MaxDepth=%d MaxTime=%.1f DepthDelta=%d MinDepth=%d MinTime=%.1f]\n\n",MaxDepth,MaxTime,DepthDelta,MinDepth,MinTime);\r
+\r
+ // loop\r
+\r
+ while (my_file_read_line(file,epd,StringSize)) {\r
+ line++;\r
+ if(my_string_whitespace(epd)) continue;\r
+ if (UseTrace) printf("%s\n",epd);\r
+\r
+ if (!epd_get_op(epd,"am",am,StringSize)) strcpy(am,"");\r
+ if (!epd_get_op(epd,"bm",bm,StringSize)) strcpy(bm,"");\r
+ if (!epd_get_op(epd,"id",id,StringSize)) strcpy(id,"");\r
+\r
+ if (my_string_empty(am) && my_string_empty(bm)) {\r
+ my_fatal("epd_test(): no am or bm field at line %d\n",line);\r
+ }\r
+\r
+ // init\r
+\r
+ uci_send_ucinewgame(Uci);\r
+ uci_send_isready_sync(Uci);\r
+\r
+ ASSERT(!Uci->searching);\r
+\r
+ // position\r
+ if (!board_from_fen(board,epd)) ASSERT(FALSE);\r
+ if (!board_to_fen(board,string,StringSize)) ASSERT(FALSE);\r
+\r
+ engine_send(Engine,"position fen %s");\r
+\r
+ // search\r
+\r
+ my_timer_start(Timer); // also resets\r
+ \r
+ // which ones of the next two alternatives is best?\r
+ engine_send(Engine,"go movetime %.0f depth %d",MaxTime*1000.0,MaxDepth);\r
+ //engine_send(Engine,"go infinite");\r
+\r
+ // engine data\r
+\r
+ board_copy(Uci->board,board);\r
+\r
+ uci_clear(Uci);\r
+ Uci->searching = TRUE;\r
+ Uci->pending_nb++;\r
+\r
+ FirstMove = MoveNone;\r
+ FirstDepth = 0;\r
+ FirstSelDepth = 0;\r
+ FirstScore = 0;\r
+ FirstTime = 0.0;\r
+ FirstNodeNb = 0;\r
+ line_clear(FirstPV);\r
+\r
+ LastMove = MoveNone;\r
+ LastDepth = 0;\r
+ LastSelDepth = 0;\r
+ LastScore = 0;\r
+ LastTime = 0.0;\r
+ LastNodeNb = 0;\r
+ line_clear(LastPV);\r
+\r
+ // parse engine output\r
+\r
+ while (!engine_eof(Engine) && engine_step()) {\r
+ bool stop=FALSE;\r
+\r
+ // stop search?\r
+// printf("Uci->time=%.2f time=%.2f\n",Uci->time,my_timer_elapsed_real(Timer));\r
+ if (Uci->depth > MaxDepth){\r
+ my_log("POLYGLOT Maximum depth %d reached\n",MaxDepth);\r
+ stop=TRUE;\r
+ }else if(my_timer_elapsed_real(Timer) >= MaxTime){\r
+ my_log("POLYGLOT Maximum search time %.2fs reached\n",MaxTime);\r
+ stop=TRUE;\r
+ }else if(Uci->depth - FirstDepth >= DepthDelta){\r
+ if(Uci->depth > MinDepth){\r
+ if(Uci->time >= MinTime){\r
+ if(is_solution(FirstMove,board,bm,am)){\r
+ my_log("POLYGLOT Solution found\n",MaxTime);\r
+ stop=TRUE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if(stop){\r
+ my_log("POLYGLOT Stopping engine\n");\r
+ engine_send(Engine,"stop");\r
+ break;\r
+ }\r
+ }\r
+ \r
+ move = FirstMove;\r
+ correct = is_solution(move,board,bm,am);\r
+\r
+ if (correct) hit++;\r
+ tot++;\r
+\r
+ if (correct) {\r
+ depth_tot += ((double)FirstDepth);\r
+ time_tot += FirstTime;\r
+ node_tot += ((double)((sint64)FirstNodeNb));\r
+ }\r
+\r
+ printf("%2d: %-15s %s %4d",tot,id,correct?"OK":"--",hit);\r
+\r
+ if (!line_to_san(LastPV,Uci->board,pv_string,StringSize)) ASSERT(FALSE);\r
+ 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
+ }\r
+\r
+ printf("\nscore=%d/%d",hit,tot);\r
+\r
+ if (hit != 0) {\r
+\r
+ depth_tot /= ((double)hit);\r
+ time_tot /= ((double)hit);\r
+ node_tot /= ((double)hit);\r
+\r
+ printf(" [averages on correct positions: depth=%.1f time=%.2f nodes=%.0f]",depth_tot,time_tot,node_tot);\r
+ }\r
+\r
+ printf("\n");\r
+\r
+ fclose(file);\r
+ quit();\r
+}\r
+\r
+// is_solution()\r
+\r
+static bool is_solution(int move, const board_t * board, const char bm[], const char am[]) {\r
+\r
+ char move_string[256];\r
+ bool correct;\r
+\r
+ ASSERT(move!=MoveNone);\r
+ ASSERT(bm!=NULL);\r
+ ASSERT(am!=NULL);\r
+\r
+ if (!move_is_legal(move,board)) {\r
+ board_disp(board);\r
+ move_disp(move,board);\r
+ printf("\n\n");\r
+ }\r
+\r
+ ASSERT(move_is_legal(move,board));\r
+\r
+ if (!move_to_san(move,board,move_string,256)) ASSERT(FALSE);\r
+\r
+ correct = FALSE;\r
+ if (!my_string_empty(bm)) {\r
+ correct = string_contain(bm,move_string);\r
+ } else if (!my_string_empty(am)) {\r
+ correct = !string_contain(am,move_string);\r
+ } else {\r
+ ASSERT(FALSE);\r
+ }\r
+\r
+ return correct;\r
+}\r
+\r
+// epd_get_op()\r
+\r
+bool epd_get_op(const char record[], const char opcode[], char string[], int size) {\r
+\r
+ char op[256];\r
+ int len;\r
+ const char *p_start, *p_end;\r
+\r
+ ASSERT(record!=NULL);\r
+ ASSERT(opcode!=NULL);\r
+ ASSERT(string!=NULL);\r
+ ASSERT(size>0);\r
+\r
+ // find the opcode\r
+\r
+ sprintf(op," %s ",opcode); \r
+\r
+ p_start = strstr(record,op);\r
+ if (p_start == NULL){\r
+ sprintf(op,";%s ",opcode); \r
+ p_start = strstr(record,op);\r
+ if (p_start == NULL){\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ // skip the opcode\r
+\r
+ p_start += strlen(op);\r
+\r
+ // find the end\r
+ p_end = strchr(p_start,';');\r
+ if (p_end == NULL) return FALSE;\r
+\r
+ // calculate the length\r
+\r
+ len = p_end - p_start;\r
+ if (size < len+1) my_fatal("epd_get_op(): size < len+1\n");\r
+\r
+ strncpy(string,p_start,len);\r
+ string[len] = '\0';\r
+\r
+ return TRUE;\r
+}\r
+\r
+// string_contain()\r
+\r
+static bool string_contain(const char string[], const char substring[]) {\r
+\r
+ char new_string[StringSize], *p;\r
+\r
+ strcpy(new_string,string); // HACK\r
+\r
+ for (p = strtok(new_string," "); p != NULL; p = strtok(NULL," ")) {\r
+ if (my_string_equal(p,substring)) return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+// engine_step()\r
+\r
+static bool engine_step() {\r
+\r
+ char string[StringSize];\r
+ int event;\r
+\r
+ engine_get(Engine,string);\r
+ event = uci_parse(Uci,string);\r
+\r
+ if ((event & EVENT_MOVE) != 0) {\r
+\r
+ return FALSE;\r
+ }\r
+\r
+ if ((event & EVENT_PV) != 0) {\r
+\r
+ LastMove = Uci->best_pv[0];\r
+ LastDepth = Uci->best_depth;\r
+ LastSelDepth = Uci->best_sel_depth;\r
+ LastScore = Uci->best_score;\r
+ LastTime = Uci->time;\r
+ LastNodeNb = Uci->node_nb;\r
+ line_copy(LastPV,Uci->best_pv);\r
+\r
+ if (LastMove != FirstMove) {\r
+ FirstMove = LastMove;\r
+ FirstDepth = LastDepth;\r
+ FirstSelDepth = LastSelDepth;\r
+ FirstScore = LastScore;\r
+ FirstTime = LastTime;\r
+ FirstNodeNb = LastNodeNb;\r
+ line_copy(FirstPV,LastPV);\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+// end of epd.cpp\r
+\r