Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 112 | pmbaty | 1 | /* |
| 2 | Protector -- a UCI chess engine |
||
| 3 | |||
| 4 | Copyright (C) 2009-2010 Raimund Heid (Raimund_Heid@yahoo.com) |
||
| 5 | |||
| 6 | This program is free software: you can redistribute it and/or modify |
||
| 7 | it under the terms of the GNU General Public License as published by |
||
| 8 | the Free Software Foundation, either version 3 of the License, or |
||
| 9 | (at your option) any later version. |
||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, |
||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 14 | GNU General Public License for more details. |
||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License |
||
| 17 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
| 18 | |||
| 19 | */ |
||
| 20 | |||
| 21 | #include <assert.h> |
||
| 22 | #include <stdio.h> |
||
| 23 | #include <stdlib.h> |
||
| 24 | #include <string.h> |
||
| 25 | #include "test.h" |
||
| 26 | #include "io.h" |
||
| 27 | #include "pgn.h" |
||
| 28 | #include "coordination.h" |
||
| 29 | #include "evaluation.h" |
||
| 30 | |||
| 31 | extern bool resetSharedHashtable; |
||
| 32 | |||
| 33 | static void handleSearchEvent(int eventId, void *var) |
||
| 34 | { |
||
| 35 | Variation *variation = (Variation *) var; |
||
| 36 | long time; |
||
| 37 | char *pvMoves; |
||
| 38 | |||
| 39 | switch (eventId) |
||
| 40 | { |
||
| 41 | case SEARCHEVENT_SEARCH_FINISHED: |
||
| 42 | time = variation->finishTimeProcess - variation->startTimeProcess; |
||
| 43 | |||
| 44 | logReport("%lld nodes in %ld msec\n", getNodeCount(), time); |
||
| 45 | |||
| 46 | if (time > 1000) |
||
| 47 | { |
||
| 48 | logReport("%ld knps\n", getNodeCount() / max(1, time)); |
||
| 49 | } |
||
| 50 | |||
| 51 | break; |
||
| 52 | |||
| 53 | case SEARCHEVENT_PLY_FINISHED: |
||
| 54 | case SEARCHEVENT_NEW_PV: |
||
| 55 | pvMoves = getPrincipalVariation(var); |
||
| 56 | dumpPv(variation->iteration, |
||
| 57 | (getTimestamp() - variation->startTime), pvMoves, |
||
| 58 | variation->pv[0].score, variation->nodes, |
||
| 59 | variation->startPosition.activeColor); |
||
| 60 | free(pvMoves); |
||
| 61 | break; |
||
| 62 | |||
| 63 | default: |
||
| 64 | break; |
||
| 65 | } |
||
| 66 | } |
||
| 67 | |||
| 68 | static bool solveMateProblem(SearchTask * entry) |
||
| 69 | { |
||
| 70 | bool result = TRUE; |
||
| 71 | int i; |
||
| 72 | |||
| 73 | completeTask(entry); |
||
| 74 | |||
| 75 | if (entry->solutions.numberOfMoves != |
||
| 76 | entry->calculatedSolutions.numberOfMoves) |
||
| 77 | { |
||
| 78 | result = FALSE; |
||
| 79 | } |
||
| 80 | |||
| 81 | for (i = 0; i < entry->solutions.numberOfMoves; i++) |
||
| 82 | { |
||
| 83 | if (listContainsMove |
||
| 84 | (&entry->calculatedSolutions, entry->solutions.moves[i]) == FALSE) |
||
| 85 | { |
||
| 86 | result = FALSE; |
||
| 87 | } |
||
| 88 | } |
||
| 89 | |||
| 90 | return result; |
||
| 91 | } |
||
| 92 | |||
| 93 | static bool solveBestMoveProblem(SearchTask * entry) |
||
| 94 | { |
||
| 95 | completeTask(entry); |
||
| 96 | |||
| 97 | return listContainsMove(&entry->solutions, entry->bestMove); |
||
| 98 | } |
||
| 99 | |||
| 100 | static bool dumpEvaluation(SearchTask * entry) |
||
| 101 | { |
||
| 102 | EvaluationBase base; |
||
| 103 | |||
| 104 | prepareSearch(entry->variation); |
||
| 105 | getValue(&entry->variation->startPosition, |
||
| 106 | &base, |
||
| 107 | entry->variation->pawnHashtable, |
||
| 108 | entry->variation->kingsafetyHashtable); |
||
| 109 | |||
| 110 | return TRUE; |
||
| 111 | } |
||
| 112 | |||
| 113 | int processTestsuite(const char *filename) |
||
| 114 | { |
||
| 115 | PGNFile pgnfile; |
||
| 116 | PGNGame *game; |
||
| 117 | SearchTask entry; |
||
| 118 | Gamemove *gamemove; |
||
| 119 | long i; |
||
| 120 | UINT64 overallNodes = 0; |
||
| 121 | const char *fmt = "\nTestsuite '%s': %d/%d solved, %s nodes\n"; |
||
| 122 | char ons[32]; |
||
| 123 | int solved = 0; |
||
| 124 | String notSolved = getEmptyString(); |
||
| 125 | Variation variation; |
||
| 126 | |||
| 127 | if (openPGNFile(&pgnfile, filename) != 0) |
||
| 128 | { |
||
| 129 | return -1; |
||
| 130 | } |
||
| 131 | |||
| 132 | logReport("\nProcessing file '%s' [%ld game(s)]\n", filename, |
||
| 133 | pgnfile.numGames); |
||
| 134 | |||
| 135 | statCount1 = statCount2 = 0; |
||
| 136 | variation.timeTarget = 60 * 1000; |
||
| 137 | variation.timeLimit = 60 * 1000; |
||
| 138 | variation.ponderMode = FALSE; |
||
| 139 | entry.variation = &variation; |
||
| 140 | |||
| 141 | for (i = 1; i <= pgnfile.numGames; i++) |
||
| 142 | { |
||
| 143 | game = getGame(&pgnfile, i); |
||
| 144 | |||
| 145 | if (game == 0) |
||
| 146 | { |
||
| 147 | continue; |
||
| 148 | } |
||
| 149 | |||
| 150 | logReport("\n%ld (%ld): %s-%s\n", i, pgnfile.numGames, |
||
| 151 | game->white, game->black); |
||
| 152 | logPosition(&game->firstMove->position); |
||
| 153 | |||
| 154 | entry.solutions.numberOfMoves = 0; |
||
| 155 | gamemove = game->firstMove; |
||
| 156 | |||
| 157 | while (gamemove != 0) |
||
| 158 | { |
||
| 159 | entry.solutions.moves |
||
| 160 | [entry.solutions.numberOfMoves++] = |
||
| 161 | getPackedMove(gamemove->from, gamemove->to, gamemove->newPiece); |
||
| 162 | |||
| 163 | gamemove = gamemove->alternativeMove; |
||
| 164 | } |
||
| 165 | |||
| 166 | initializeVariation(&variation, game->fen); |
||
| 167 | resetSharedHashtable = TRUE; |
||
| 168 | variation.handleSearchEvent = &handleSearchEvent; |
||
| 169 | |||
| 170 | if (strstr(game->white, "[#") != NULL) |
||
| 171 | { |
||
| 172 | char *tmp = strstr(game->white, "[#"); |
||
| 173 | |||
| 174 | entry.type = TASKTYPE_TEST_MATE_IN_N; |
||
| 175 | entry.numberOfMoves = atoi(tmp + 2); |
||
| 176 | |||
| 177 | if (solveMateProblem(&entry) != FALSE) |
||
| 178 | { |
||
| 179 | solved++; |
||
| 180 | } |
||
| 181 | else |
||
| 182 | { |
||
| 183 | assert(0); |
||
| 184 | } |
||
| 185 | |||
| 186 | overallNodes += entry.nodes; |
||
| 187 | } |
||
| 188 | else |
||
| 189 | { |
||
| 190 | entry.type = TASKTYPE_TEST_BEST_MOVE; |
||
| 191 | entry.numberOfMoves = 0; |
||
| 192 | |||
| 193 | if (commandlineOptions.dumpEvaluation) |
||
| 194 | { |
||
| 195 | dumpEvaluation(&entry); |
||
| 196 | } |
||
| 197 | else |
||
| 198 | { |
||
| 199 | if (solveBestMoveProblem(&entry) != FALSE) |
||
| 200 | { |
||
| 201 | solved++; |
||
| 202 | } |
||
| 203 | else |
||
| 204 | { |
||
| 205 | appendToString(¬Solved, "%d ", i); |
||
| 206 | } |
||
| 207 | |||
| 208 | overallNodes += entry.nodes; |
||
| 209 | } |
||
| 210 | } |
||
| 211 | |||
| 212 | freePgnGame(game); |
||
| 213 | } |
||
| 214 | |||
| 215 | formatLongInteger(overallNodes, ons); |
||
| 216 | logReport(fmt, filename, solved, pgnfile.numGames, ons); |
||
| 217 | logReport("Not solved: %s\n", notSolved.buffer); |
||
| 218 | free(notSolved.buffer); |
||
| 219 | closePGNFile(&pgnfile); |
||
| 220 | |||
| 221 | return 0; |
||
| 222 | } |
||
| 223 | |||
| 224 | /** |
||
| 225 | * Initialize this module. |
||
| 226 | * |
||
| 227 | * @return 0 if no errors occurred. |
||
| 228 | */ |
||
| 229 | int initializeModuleTest(void) |
||
| 230 | { |
||
| 231 | return 0; |
||
| 232 | } |
||
| 233 | |||
| 234 | int testModuleTest() |
||
| 235 | { |
||
| 236 | int result; |
||
| 237 | |||
| 238 | if ((result = processTestsuite("moduletest.pgn")) != 0) |
||
| 239 | { |
||
| 240 | return result; |
||
| 241 | } |
||
| 242 | |||
| 243 | return 0; |
||
| 244 | } |