Subversion Repositories Games.Chess Giants

Rev

Rev 108 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "chess.h"
  2. #include "data.h"
  3. /* last modified 02/26/14 */
  4. /*
  5.  *******************************************************************************
  6.  *                                                                             *
  7.  *   Test() is used to test the program against a suite of test positions to   *
  8.  *   measure its performance on a particular machine, or to evaluate its skill *
  9.  *   after modifying it in some way.                                           *
  10.  *                                                                             *
  11.  *   The test is initiated by using the "test <filename>" command to read in   *
  12.  *   the suite of problems from file <filename>.  The format of this file is   *
  13.  *   as follows:                                                               *
  14.  *                                                                             *
  15.  *   Setboard <forsythe-string>:  This sets the board position using the usual *
  16.  *   forsythe notation (see module SetBoard() in setc for a full ex-           *
  17.  *   planation of the syntax).                                                 *
  18.  *                                                                             *
  19.  *   Solution <move1> <move2> ... <moven>:  this provides a solution move (or  *
  20.  *   set of solution moves if more than one is correct).  If the search finds  *
  21.  *   one of these moves, then the prblem is counted as correct, otherwise it   *
  22.  *   is counted wrong.                                                         *
  23.  *                                                                             *
  24.  *   After reading these two lines, the program then searches to whatever time *
  25.  *   or depth limit has been set, when it reaches the end-of-file condition or *
  26.  *   when it reads a record containing the string "end" it then displays the   *
  27.  *   number correct and the number missed.                                     *
  28.  *                                                                             *
  29.  *   There are two test modules here.  Test() handles the specific Crafty test *
  30.  *   data format (dates back to Cray Blitz days) while TestEPD() handles the   *
  31.  *   EPD-style test positions which is more concise.  Other than the parsing   *
  32.  *   differences, these are identical modules.                                 *
  33.  *                                                                             *
  34.  *******************************************************************************
  35.  */
  36. void Test(char *filename) {
  37.   FILE *test_input;
  38.   int i, move, right = 0, wrong = 0, correct;
  39.   int time = 0, len;
  40.   uint64_t nodes = 0;
  41.   char *eof, *delim;
  42.   float avg_depth = 0.0;
  43.   TREE *const tree = block[0];
  44.  
  45. /*
  46.  ************************************************************
  47.  *                                                          *
  48.  *  Read in the position and then the solutions.  After     *
  49.  *  executing a search to find the best move (according to  *
  50.  *  the program, anyway) compare it against the list of     *
  51.  *  solutions and count it right or wrong.                  *
  52.  *                                                          *
  53.  ************************************************************
  54.  */
  55.   fopen_s (&test_input, filename, "r");
  56.   if (!test_input) {
  57.     printf("file %s does not exist.\n", filename);
  58.     return;
  59.   }
  60.   Print(4095, "\n");
  61.   eof = fgets(buffer, 4096, test_input);
  62.   if (strstr(buffer, "title"));
  63.   else {
  64.     fclose(test_input);
  65.     TestEPD(filename);
  66.     return;
  67.   }
  68.   if (book_file) {
  69.     fclose(book_file);
  70.     book_file = 0;
  71.   }
  72.   if (books_file) {
  73.     fclose(books_file);
  74.     books_file = 0;
  75.   }
  76.   while (1) {
  77.     if (eof) {
  78.       delim = strchr(buffer, '\n');
  79.       if (delim)
  80.         *delim = 0;
  81.       delim = strchr(buffer, '\r');
  82.       if (delim)
  83.         *delim = ' ';
  84.     } else
  85.       break;
  86.     nargs = ReadParse(buffer, args, " ;");
  87.     if (!strcmp(args[0], "end"))
  88.       break;
  89.     else if (!strcmp(args[0], "title")) {
  90.       Print(4095,
  91.           "=============================================="
  92.           "========================\n");
  93.       Print(4095, "! ");
  94.       len = 0;
  95.       for (i = 1; i < nargs; i++) {
  96.         Print(4095, "%s ", args[i]);
  97.         len += strlen(args[i]) + 1;
  98.         if (len > 65)
  99.           break;
  100.       }
  101.       for (i = len; i < 67; i++)
  102.         printf(" ");
  103.       Print(4095, "!\n");
  104.       Print(4095,
  105.           "=============================================="
  106.           "========================\n");
  107.     } else if (strcmp(args[0], "solution")) {
  108.       Option(tree);
  109.     } else {
  110.       number_of_solutions = 0;
  111.       solution_type = 0;
  112.       Print(4095, "solution ");
  113.       for (i = 1; i < nargs; i++) {
  114.         if (args[i][strlen(args[i]) - 1] == '?') {
  115.           solution_type = 1;
  116.           args[i][strlen(args[i]) - 1] = '\0';
  117.         } else if (*(args + i)[strlen(args[i]) - 1] == '!') {
  118.           solution_type = 0;
  119.           args[i][strlen(args[i]) - 1] = '\0';
  120.         }
  121.         move = InputMove(tree, args[i], 0, game_wtm, 0, 0);
  122.         if (move) {
  123.           solutions[number_of_solutions] = move;
  124.           Print(4095, "%d. %s", (number_of_solutions++) + 1, OutputMove(tree,
  125.                   move, 0, game_wtm));
  126.           if (solution_type == 1)
  127.             Print(4095, "? ");
  128.           else
  129.             Print(4095, "  ");
  130.         } else
  131.           DisplayChessBoard(stdout, tree->position);
  132.       }
  133.       Print(4095, "\n");
  134.       InitializeHashTables();
  135.       last_pv.pathd = 0;
  136.       thinking = 1;
  137.       tree->status[1] = tree->status[0];
  138.       (void) Iterate(game_wtm, think, 0);
  139.       thinking = 0;
  140.       nodes += tree->nodes_searched;
  141.       avg_depth += (float) iteration_depth;
  142.       time += (end_time - start_time);
  143.       correct = solution_type;
  144.       for (i = 0; i < number_of_solutions; i++) {
  145.         if (!solution_type) {
  146.           if (solutions[i] == tree->pv[1].path[1])
  147.             correct = 1;
  148.         } else if (solutions[i] == tree->pv[1].path[1])
  149.           correct = 0;
  150.       }
  151.       if (correct) {
  152.         right++;
  153.         Print(4095, "----------------------> solution correct (%d/%d).\n",
  154.             right, right + wrong);
  155.       } else {
  156.         wrong++;
  157.         Print(4095, "----------------------> solution incorrect (%d/%d).\n",
  158.             right, right + wrong);
  159.       }
  160.     }
  161.     eof = fgets(buffer, 4096, test_input);
  162.   }
  163. /*
  164.  ************************************************************
  165.  *                                                          *
  166.  *  Now print the results.                                  *
  167.  *                                                          *
  168.  ************************************************************
  169.  */
  170.   if (right + wrong) {
  171.     Print(4095, "\n\n\n");
  172.     Print(4095, "test results summary:\n\n");
  173.     Print(4095, "total positions searched..........%12d\n", right + wrong);
  174.     Print(4095, "number right......................%12d\n", right);
  175.     Print(4095, "number wrong......................%12d\n", wrong);
  176.     Print(4095, "percentage right..................%12d\n",
  177.         right * 100 / (right + wrong));
  178.     Print(4095, "percentage wrong..................%12d\n",
  179.         wrong * 100 / (right + wrong));
  180.     Print(4095, "total nodes searched..............%12" PRIu64 "\n", nodes);
  181.     Print(4095, "average search depth..............%12.1f\n",
  182.         avg_depth / (right + wrong));
  183.     Print(4095, "nodes per second..................%12" PRIu64 "\n",
  184.         nodes * 100 / Max(time, 1));
  185.     Print(4095, "total time........................%12s\n",
  186.         DisplayTime(time));
  187.   }
  188.   input_stream = stdin;
  189.   early_exit = 99;
  190. }
  191.  
  192. /* last modified 02/26/14 */
  193. /*
  194.  *******************************************************************************
  195.  *                                                                             *
  196.  *   TestEPD() is used to test the program against a suite of test positions   *
  197.  *   to measure its performance on a particular machine, or to evaluate its    *
  198.  *   skill after modifying it in some way.                                     *
  199.  *                                                                             *
  200.  *   The test is initiated by using the "test <filename>" command to read in   *
  201.  *   the suite of problems from file <filename>.  The format of this file is   *
  202.  *   as follows:                                                               *
  203.  *                                                                             *
  204.  *   <forsythe-string>  am/bm move1 move2 etc; title "xxx"                     *
  205.  *                                                                             *
  206.  *   Am means "avoid move" and bm means "best move".  Each test position may   *
  207.  *   have multiple moves to avoid or that are best, but both am and bm may not *
  208.  *   appear on one position.                                                   *
  209.  *                                                                             *
  210.  *   The title is just a comment that is given in the program output to make   *
  211.  *   it easier to match output to specific positions.                          *
  212.  *                                                                             *
  213.  *******************************************************************************
  214.  */
  215. void TestEPD(char *filename) {
  216.   FILE *test_input;
  217.   int i, move, right = 0, wrong = 0, correct;
  218.   int time = 0, len;
  219.   uint64_t nodes = 0;
  220.   char *eof, *mvs, *title;
  221.   float avg_depth = 0.0;
  222.   TREE *const tree = block[0];
  223.  
  224. /*
  225.  ************************************************************
  226.  *                                                          *
  227.  *  Read in the position and then the solutions.  After     *
  228.  *  executing a search to find the best move (according to  *
  229.  *  the program, anyway) compare it against the list of     *
  230.  *  solutions and count it right or wrong.                  *
  231.  *                                                          *
  232.  ************************************************************
  233.  */
  234.   fopen_s(&test_input, filename, "r"); // Pierre-Marie Baty -- use safe version
  235.   if (!test_input) {
  236.     printf("file %s does not exist.\n", filename);
  237.     return;
  238.   }
  239.   if (book_file) {
  240.     fclose(book_file);
  241.     book_file = 0;
  242.   }
  243.   if (books_file) {
  244.     fclose(books_file);
  245.     books_file = 0;
  246.   }
  247.   while (1) {
  248.     eof = fgets(buffer, 4096, test_input);
  249.     if (eof) {
  250.       char *delim;
  251.  
  252.       delim = strchr(buffer, '\n');
  253.       if (delim)
  254.         *delim = 0;
  255.       delim = strchr(buffer, '\r');
  256.       if (delim)
  257.         *delim = ' ';
  258.     } else
  259.       break;
  260.     mvs = strstr(buffer, " bm ");
  261.     if (!mvs)
  262.       mvs = strstr(buffer, " am ");
  263.     if (!mvs)
  264.       Print(4095, "Warning. am/bm field missing, input string follows\n%s\n",
  265.           buffer);
  266.     if (mvs)
  267.       mvs++;
  268.     title = strstr(buffer, "id");
  269.     if (mvs)
  270.       *(mvs - 1) = 0;
  271.     if (title)
  272.       *(title - 1) = 0;
  273.     if (title) {
  274.       title = strchr(title, '\"') + 1;
  275.       if (title) {
  276.         if (strchr(title, '\"')) {
  277.           *strchr(title, '\"') = 0;
  278.         }
  279.       }
  280.       Print(4095,
  281.           "=============================================="
  282.           "========================\n");
  283.       Print(4095, "! ");
  284.       Print(4095, "%s ", title);
  285.       len = 66 - strlen(title);
  286.       for (i = 0; i < len; i++)
  287.         printf(" ");
  288.       Print(4095, "!\n");
  289.       Print(4095,
  290.           "=============================================="
  291.           "========================\n");
  292.     }
  293.     Option(tree);
  294.     if (mvs) {
  295.       nargs = ReadParse(mvs, args, " ;");
  296.       number_of_solutions = 0;
  297.       solution_type = 0;
  298.       if (!strcmp(args[0], "am"))
  299.         solution_type = 1;
  300.       Print(4095, "solution ");
  301.       for (i = 1; i < nargs; i++) {
  302.         if (!strcmp(args[i], "c0"))
  303.           break;
  304.         move = InputMove(tree, args[i], 0, game_wtm, 0, 0);
  305.         if (move) {
  306.           solutions[number_of_solutions] = move;
  307.           Print(4095, "%d. %s", (number_of_solutions++) + 1, OutputMove(tree,
  308.                   move, 0, game_wtm));
  309.           if (solution_type == 1)
  310.             Print(4095, "? ");
  311.           else
  312.             Print(4095, "  ");
  313.         } else
  314.           DisplayChessBoard(stdout, tree->position);
  315.       }
  316.     }
  317.     Print(4095, "\n");
  318.     InitializeHashTables();
  319.     last_pv.pathd = 0;
  320.     thinking = 1;
  321.     tree->status[1] = tree->status[0];
  322.     (void) Iterate(game_wtm, think, 0);
  323.     thinking = 0;
  324.     nodes += tree->nodes_searched;
  325.     avg_depth += (float) iteration_depth;
  326.     time += (end_time - start_time);
  327.     correct = solution_type;
  328.     for (i = 0; i < number_of_solutions; i++) {
  329.       if (!solution_type) {
  330.         if (solutions[i] == tree->pv[1].path[1])
  331.           correct = 1;
  332.       } else if (solutions[i] == tree->pv[1].path[1])
  333.         correct = 0;
  334.     }
  335.     if (correct) {
  336.       right++;
  337.       Print(4095, "----------------------> solution correct (%d/%d).\n",
  338.           right, right + wrong);
  339.     } else {
  340.       wrong++;
  341.       Print(4095, "----------------------> solution incorrect (%d/%d).\n",
  342.           right, right + wrong);
  343.     }
  344.   }
  345. /*
  346.  ************************************************************
  347.  *                                                          *
  348.  *  Now print the results.                                  *
  349.  *                                                          *
  350.  ************************************************************
  351.  */
  352.   if (right + wrong) {
  353.     Print(4095, "\n\n\n");
  354.     Print(4095, "test results summary:\n\n");
  355.     Print(4095, "total positions searched..........%12d\n", right + wrong);
  356.     Print(4095, "number right......................%12d\n", right);
  357.     Print(4095, "number wrong......................%12d\n", wrong);
  358.     Print(4095, "percentage right..................%12d\n",
  359.         right * 100 / (right + wrong));
  360.     Print(4095, "percentage wrong..................%12d\n",
  361.         wrong * 100 / (right + wrong));
  362.     Print(4095, "total nodes searched..............%12" PRIu64 "\n", nodes);
  363.     Print(4095, "average search depth..............%12.1f\n",
  364.         avg_depth / (right + wrong));
  365.     Print(4095, "nodes per second..................%12" PRIu64 "\n",
  366.         nodes * 100 / Max(1, time));
  367.     Print(4095, "total time........................%12s\n",
  368.         DisplayTime(time));
  369.   }
  370.   input_stream = stdin;
  371.   early_exit = 99;
  372. }
  373.