1 #include "chess.h"
2 #include "data.h"
3 /* last modified 02/26/14 */
4 /*
5  *******************************************************************************
6  *                                                                             *
7  *   EVTest() 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 "evtest <filename>" command to read in *
12  *   the suite of problems from file <filename>.  The format of this file is   *
13  *   as follows:                                                               *
14  *                                                                             *
15  *   <forsythe-string>  This sets the board position using the usual Forsythe  *
16  *   notation (see module SetBoard() for a full explanation explanation of the *
17  *   syntax).                                                                  *
18  *                                                                             *
19  *   After reading this position, the program then calls Evaluate() to produce *
20  *   a positional evaluation, along with any debug output from Evaluate(), and *
21  *   then goes on to the next position.                                        *
22  *                                                                             *
23  *   A common use (with code included below) is to take a position, and then   *
24  *   "flip" it (reverse the board rank by rank changing the color of each      *
25  *   piece as this is done, giving us two positions.  We then take each of     *
26  *   these and mirror them, which reverses them file by file, which now gives  *
27  *   four positions in total.  We run these thru Evaluate() to make sure that  *
28  *   all produce exactly the same score, except for the color change for the   *
29  *   two that changed the piece colors.  This is used to make certain that the *
30  *   evaluation is not asymmetric with respect to the colors, or to the side   *
31  *   of the board, which catches errors that are difficult to spot otherwise.  *
32  *                                                                             *
33  *******************************************************************************
34  */
EVTest(char * filename)35 void EVTest(char *filename) {
36   FILE *test_input;
37   char *eof;
38   char buff[4096];
39   TREE *const tree = block[0];
40 
41 /*
42  ************************************************************
43  *                                                          *
44  *  Read in the position                                    *
45  *                                                          *
46  ************************************************************
47  */
48   if (!(test_input = fopen(filename, "r"))) {
49     printf("file %s does not exist.\n", filename);
50     return;
51   }
52   while (FOREVER) {
53     eof = fgets(buffer, 4096, test_input);
54     if (eof) {
55       char *delim;
56 
57       delim = strchr(buffer, '\n');
58       if (delim)
59         *delim = 0;
60       delim = strchr(buffer, '\r');
61       if (delim)
62         *delim = ' ';
63     } else
64       break;
65     strcpy(buff, buffer);
66     nargs = ReadParse(buffer, args, " \t;");
67     if (!strcmp(args[0], "end"))
68       break;
69 /*
70  ************************************************************
71  *                                                          *
72  *  Now for the asymmetry tests.  We use the built-in       *
73  *  commands "flip" and "flop" to create the four           *
74  *  positions, and call Evaluate() for each.                *
75  *                                                          *
76  ************************************************************
77  */
78     else {
79       int s1, s2, s3, s4, id;
80 
81       for (id = 2; id < nargs; id++)
82         if (!strcmp(args[id], "id"))
83           break;
84       if (id >= nargs)
85         id = 0;
86       SetBoard(tree, nargs, args, 0);
87       Castle(0, white) = 0;
88       Castle(1, white) = 0;
89       Castle(0, black) = 0;
90       Castle(1, black) = 0;
91       tree->pawn_score.key = 0;
92       root_wtm = game_wtm;
93       s1 = Evaluate(tree, 0, game_wtm, -99999, 99999);
94       strcpy(buffer, "flop");
95       Option(tree);
96       tree->pawn_score.key = 0;
97       root_wtm = game_wtm;
98       s2 = Evaluate(tree, 0, game_wtm, -99999, 99999);
99       strcpy(buffer, "flip");
100       Option(tree);
101       tree->pawn_score.key = 0;
102       root_wtm = game_wtm;
103       s3 = Evaluate(tree, 0, game_wtm, -99999, 99999);
104       strcpy(buffer, "flop");
105       Option(tree);
106       tree->pawn_score.key = 0;
107       root_wtm = game_wtm;
108       s4 = Evaluate(tree, 0, game_wtm, -99999, 99999);
109 /*
110  ************************************************************
111  *                                                          *
112  *  If the evaluations (with sign corrected if piece color  *
113  *  was changed) are different, we display the four values  *
114  *  and then display the original board position so that we *
115  *  can debug the cause of the asymmetry.                   *
116  *                                                          *
117  ************************************************************
118  */
119       if (s1 != s2 || s1 != s3 || s1 != s4 || s2 != s3 || s2 != s4 ||
120           s3 != s4) {
121         strcpy(buffer, "flip");
122         Option(tree);
123         printf("FEN = %s\n", buff);
124         DisplayChessBoard(stdout, tree->position);
125         if (id)
126           Print(4095, "id=%s  ", args[id + 1]);
127         Print(4095, "wtm=%d  score=%d  %d (flop)  %d (flip)  %d (flop)\n",
128             game_wtm, s1, s2, s3, s4);
129       }
130     }
131   }
132   input_stream = stdin;
133 }
134