Commit | Line | Data |
---|---|---|
7eeb782e AT |
1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ |
2 | * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see * | |
3 | * http://www.gnu.org/software/gnugo/ for more information. * | |
4 | * * | |
5 | * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * | |
6 | * 2008 and 2009 by the Free Software Foundation. * | |
7 | * * | |
8 | * This program is free software; you can redistribute it and/or * | |
9 | * modify it under the terms of the GNU General Public License as * | |
10 | * published by the Free Software Foundation - version 3 or * | |
11 | * (at your option) any later version. * | |
12 | * * | |
13 | * This program is distributed in the hope that it will be useful, * | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
16 | * GNU General Public License in file COPYING for more details. * | |
17 | * * | |
18 | * You should have received a copy of the GNU General Public * | |
19 | * License along with this program; if not, write to the Free * | |
20 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * | |
21 | * Boston, MA 02111, USA. * | |
22 | \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
23 | ||
24 | #include "gnugo.h" | |
25 | ||
c150f57c | 26 | #include <ctype.h> |
7eeb782e AT |
27 | #include <stdio.h> |
28 | #include <stdlib.h> | |
29 | #include <string.h> | |
7eeb782e | 30 | |
7eeb782e | 31 | #include "gg_utils.h" |
c150f57c | 32 | #include "interface.h" |
7eeb782e | 33 | #include "liberty.h" |
c150f57c | 34 | #include "sgftree.h" |
7eeb782e | 35 | |
c150f57c AT |
36 | static void replay_node(SGFNode* node, int color_to_test, float* replay_score, |
37 | float* total_score); | |
7eeb782e AT |
38 | |
39 | /* --------------------------------------------------------------*/ | |
40 | /* replay a game */ | |
41 | /* --------------------------------------------------------------*/ | |
42 | ||
c150f57c | 43 | void play_replay(SGFTree* tree, int color_to_replay) |
7eeb782e | 44 | { |
c150f57c AT |
45 | char* tmpc = NULL; |
46 | float replay_score = 0.0; | |
47 | float total_score = 0.0; | |
7eeb782e | 48 | |
c150f57c | 49 | SGFNode* node = tree->root; |
7eeb782e | 50 | |
c150f57c | 51 | /* Board size and komi are already set up correctly since the game |
7eeb782e AT |
52 | * has already been loaded before this function is called. Now we |
53 | * only have to clear the board before starting over. | |
54 | */ | |
c150f57c AT |
55 | clear_board(); |
56 | ||
57 | if (!quiet) { | |
58 | printf("Board Size: %d\n", board_size); | |
59 | if (sgfGetCharProperty(node, "HA", &tmpc)) | |
60 | printf("Handicap: %s\n", tmpc); | |
61 | printf("Komi: %.1f\n", komi); | |
62 | if (sgfGetCharProperty(node, "RU", &tmpc)) | |
63 | printf("Ruleset: %s\n", tmpc); | |
64 | if (sgfGetCharProperty(node, "GN", &tmpc)) | |
65 | printf("Game Name: %s\n", tmpc); | |
66 | if (sgfGetCharProperty(node, "DT", &tmpc)) | |
67 | printf("Game Date: %s\n", tmpc); | |
68 | if (sgfGetCharProperty(node, "GC", &tmpc)) | |
69 | printf("Game Comment: %s\n", tmpc); | |
70 | if (sgfGetCharProperty(node, "US", &tmpc)) | |
71 | printf("Game User: %s\n", tmpc); | |
72 | if (sgfGetCharProperty(node, "PB", &tmpc)) | |
73 | printf("Black Player: %s\n", tmpc); | |
74 | if (sgfGetCharProperty(node, "PW", &tmpc)) | |
75 | printf("White Player: %s\n", tmpc); | |
76 | if (sgfGetCharProperty(node, "RE", &tmpc)) | |
77 | printf("Result: %s\n", tmpc); | |
78 | } | |
79 | ||
80 | /* | |
7eeb782e AT |
81 | * Now actually run through the file. This is the interesting part. |
82 | * We need to traverse the SGF tree, and every time we encounter a node | |
83 | * we need to check what move GNU Go would make, and see if it is OK. | |
84 | */ | |
c150f57c AT |
85 | while (node) { |
86 | replay_node(node, color_to_replay, &replay_score, &total_score); | |
87 | sgffile_output(tree); | |
88 | node = node->child; | |
89 | } | |
7eeb782e | 90 | |
c150f57c AT |
91 | if (!quiet) |
92 | printf("Global score: %.2f / %.2f\n", replay_score, total_score); | |
93 | ||
94 | if (showtime) { | |
95 | gprintf("SLOWEST MOVE: %d at %1m ", slowest_movenum, slowest_move); | |
96 | fprintf(stderr, "(%.2f seconds)\n", slowest_time); | |
97 | fprintf(stderr, "AVERAGE TIME: %.2f seconds per move\n", | |
98 | total_time / movenum); | |
99 | fprintf(stderr, "TOTAL TIME: %.2f seconds\n", | |
100 | total_time); | |
101 | } | |
102 | } | |
7eeb782e AT |
103 | |
104 | #define BUFSIZE 128 | |
105 | ||
106 | /* | |
107 | * Handle this node. | |
108 | */ | |
109 | ||
110 | static void | |
c150f57c AT |
111 | replay_node(SGFNode* node, int color_to_replay, float* replay_score, |
112 | float* total_score) | |
7eeb782e | 113 | { |
c150f57c AT |
114 | SGFProperty* sgf_prop; /* iterate over properties of the node */ |
115 | SGFProperty* move_prop = NULL; /* remember if we see a move property */ | |
116 | int color; /* color of move to be made at this node. */ | |
117 | ||
118 | int old_move; /* The move played in the file. */ | |
119 | int new_move; /* The move generated by GNU Go. */ | |
7eeb782e | 120 | |
c150f57c | 121 | char buf[BUFSIZE]; |
7eeb782e | 122 | |
c150f57c | 123 | /* Handle any AB / AW properties, and note presence |
7eeb782e AT |
124 | * of move properties. |
125 | */ | |
126 | ||
c150f57c AT |
127 | for (sgf_prop = node->props; sgf_prop; sgf_prop = sgf_prop->next) { |
128 | switch (sgf_prop->name) { | |
129 | case SGFAB: | |
130 | /* add black */ | |
131 | add_stone(get_sgfmove(sgf_prop), BLACK); | |
132 | break; | |
133 | case SGFAW: | |
134 | /* add white */ | |
135 | add_stone(get_sgfmove(sgf_prop), WHITE); | |
136 | break; | |
137 | case SGFB: | |
138 | case SGFW: | |
139 | move_prop = sgf_prop; /* remember it for later */ | |
140 | break; | |
141 | } | |
7eeb782e | 142 | } |
c150f57c AT |
143 | |
144 | /* Only generate moves at move nodes. */ | |
145 | if (!move_prop) | |
146 | return; | |
147 | ||
148 | old_move = get_sgfmove(move_prop); | |
149 | color = (move_prop->name == SGFW) ? WHITE : BLACK; | |
150 | ||
151 | if (color == color_to_replay || color_to_replay == GRAY) { | |
152 | float new_move_value = 0.0; | |
153 | float old_move_value = 0.0; | |
154 | ||
155 | /* Get a move from the engine for color. */ | |
156 | int resign; | |
157 | new_move = genmove(color, NULL, &resign); | |
158 | ||
159 | /* Pick up the relevant values from the potential_moves[] array. */ | |
160 | if (new_move != PASS_MOVE) | |
161 | new_move_value = potential_moves[new_move]; | |
162 | if (old_move != PASS_MOVE) | |
163 | old_move_value = potential_moves[old_move]; | |
164 | ||
165 | /* Now report on how well the computer generated the move. */ | |
166 | if (new_move != old_move || !quiet) { | |
167 | mprintf("Move %d (%C): ", movenum + 1, color); | |
168 | ||
169 | if (resign) | |
170 | printf("GNU Go resigns "); | |
171 | else { | |
172 | mprintf("GNU Go plays %1m ", new_move); | |
173 | if (new_move != PASS_MOVE) | |
174 | printf("(%.2f) ", new_move_value); | |
175 | } | |
176 | ||
177 | mprintf("- Game move %1m ", old_move); | |
178 | if (new_move != PASS_MOVE && old_move_value > 0.0) | |
179 | printf("(%.2f) ", old_move_value); | |
180 | printf("\n"); | |
181 | ||
182 | *replay_score += new_move_value - old_move_value; | |
183 | *total_score += new_move_value; | |
184 | } | |
185 | ||
186 | if (new_move != old_move) { | |
187 | if (resign) | |
188 | gg_snprintf(buf, BUFSIZE, "GNU Go resigns - Game move %s (%.2f)", | |
189 | location_to_string(old_move), old_move_value); | |
190 | else { | |
191 | gg_snprintf(buf, BUFSIZE, | |
192 | "GNU Go plays %s (%.2f) - Game move %s (%.2f)", | |
193 | location_to_string(new_move), new_move_value, | |
194 | location_to_string(old_move), old_move_value); | |
195 | if (new_move != PASS_MOVE) | |
196 | sgfCircle(node, I(new_move), J(new_move)); | |
197 | } | |
198 | } else | |
199 | gg_snprintf(buf, BUFSIZE, "GNU Go plays the same move %s (%.2f)", | |
200 | location_to_string(new_move), new_move_value); | |
201 | ||
202 | sgfAddComment(node, buf); | |
203 | sgffile_add_debuginfo(node, 0.0); | |
7eeb782e | 204 | } |
7eeb782e | 205 | |
c150f57c AT |
206 | /* Finally, do play the move from the file. */ |
207 | play_move(old_move, color); | |
208 | } | |
7eeb782e AT |
209 | |
210 | /* | |
211 | * Local Variables: | |
c150f57c AT |
212 | * tab-width: 4 |
213 | * c-basic-offset: 4 | |
7eeb782e AT |
214 | * End: |
215 | */ |