Rev 108 | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 33 | pmbaty | 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 |  */ | ||
| 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 |   } | ||
| 154 | pmbaty | 52 | while (FOREVER) { | 
| 33 | pmbaty | 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; | ||
| 108 | pmbaty | 65 | strcpy(buff, buffer); | 
| 66 | nargs = ReadParse(buffer, args, " \t;"); | ||
| 33 | pmbaty | 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; | ||
| 108 | pmbaty | 91 | tree->pawn_score.key = 0; | 
| 33 | pmbaty | 92 | root_wtm = game_wtm; | 
| 93 | s1 = Evaluate(tree, 0, game_wtm, -99999, 99999); | ||
| 108 | pmbaty | 94 | strcpy(buffer, "flop"); | 
| 95 | Option(tree); | ||
| 33 | pmbaty | 96 | tree->pawn_score.key = 0; | 
| 108 | pmbaty | 97 | root_wtm = game_wtm; | 
| 33 | pmbaty | 98 | s2 = Evaluate(tree, 0, game_wtm, -99999, 99999); | 
| 108 | pmbaty | 99 | strcpy(buffer, "flip"); | 
| 100 | Option(tree); | ||
| 33 | pmbaty | 101 | tree->pawn_score.key = 0; | 
| 108 | pmbaty | 102 | root_wtm = game_wtm; | 
| 33 | pmbaty | 103 | s3 = Evaluate(tree, 0, game_wtm, -99999, 99999); | 
| 108 | pmbaty | 104 | strcpy(buffer, "flop"); | 
| 105 | Option(tree); | ||
| 33 | pmbaty | 106 | tree->pawn_score.key = 0; | 
| 108 | pmbaty | 107 | root_wtm = game_wtm; | 
| 33 | pmbaty | 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) { | ||
| 108 | pmbaty | 121 | strcpy(buffer, "flip"); | 
| 122 | Option(tree); | ||
| 33 | pmbaty | 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 | } |