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 | /* | |
25 | * sgffile.c | |
26 | * | |
27 | * This file used to contain functions that create an SGF file on the fly. | |
28 | * | |
29 | * Today it contains supporting code around the more general SGF library | |
30 | * found in the sgf/ directory. | |
31 | */ | |
32 | ||
33 | #include "gnugo.h" | |
34 | ||
35 | #include <stdio.h> | |
36 | #include <stdarg.h> | |
37 | #include <stdlib.h> | |
38 | #include <string.h> | |
39 | ||
40 | #include "liberty.h" | |
41 | #include "sgftree.h" | |
42 | #include "gg_utils.h" | |
43 | ||
44 | /* | |
45 | * Add debug information to a node if user requested it from command | |
46 | * line. | |
47 | */ | |
48 | ||
49 | void | |
50 | sgffile_add_debuginfo(SGFNode *node, float value) | |
51 | { | |
52 | int pos; | |
53 | char comment[24]; | |
54 | ||
55 | if (!outfilename[0]) | |
56 | return; | |
57 | ||
58 | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { | |
59 | if (!ON_BOARD(pos)) | |
60 | continue; | |
61 | ||
62 | if (IS_STONE(board[pos]) && (output_flags & OUTPUT_MARKDRAGONS)) { | |
63 | if (dragon[pos].crude_status == DEAD) | |
64 | sgfLabel(node, "X", I(pos), J(pos)); | |
65 | else if (dragon[pos].crude_status == CRITICAL) | |
66 | sgfLabel(node, "!", I(pos), J(pos)); | |
67 | } | |
68 | ||
69 | if (potential_moves[pos] > 0.0 && (output_flags & OUTPUT_MOVEVALUES)) { | |
70 | if (potential_moves[pos] < 1.0) | |
71 | sgfLabel(node, "<1", I(pos), J(pos)); | |
72 | else | |
73 | sgfLabelInt(node, (int) potential_moves[pos], I(pos), J(pos)); | |
74 | } | |
75 | } | |
76 | ||
77 | if (value > 0.0 && (output_flags & OUTPUT_MOVEVALUES)) { | |
78 | sprintf(comment, "Value of move: %.2f", value); | |
79 | sgfAddComment(node, comment); | |
80 | } | |
81 | } | |
82 | ||
83 | ||
84 | /* | |
85 | * Write sgf tree to output file specified with -o option. | |
86 | * This can safely be done multiple times. | |
87 | */ | |
88 | ||
89 | void | |
90 | sgffile_output(SGFTree *tree) | |
91 | { | |
92 | if (outfilename[0]) | |
93 | writesgf(tree->root, outfilename); | |
94 | } | |
95 | ||
96 | ||
97 | /* ================================================================ | |
98 | * Dumping of information about a position into an sgftree. | |
99 | * Used by sgffile_decideposition, etc. | |
100 | * ================================================================ */ | |
101 | ||
102 | ||
103 | /* | |
104 | * sgffile_begindump begins storing all moves considered by | |
105 | * trymove and tryko in an sgf tree in memory. | |
106 | * | |
107 | * The caller only has to provide an own SGFTree pointer if he wants | |
108 | * to do something more with the tree than writing it to file as done | |
109 | * by sgffile_enddump(). | |
110 | */ | |
111 | ||
112 | void | |
113 | sgffile_begindump(SGFTree *tree) | |
114 | { | |
115 | static SGFTree local_tree; | |
116 | gg_assert(sgf_dumptree == NULL); | |
117 | ||
118 | if (tree == NULL) | |
119 | sgf_dumptree = &local_tree; | |
120 | else | |
121 | sgf_dumptree = tree; | |
122 | ||
123 | sgftree_clear(sgf_dumptree); | |
124 | sgftreeCreateHeaderNode(sgf_dumptree, board_size, komi, handicap); | |
125 | sgffile_printboard(sgf_dumptree); | |
126 | } | |
127 | ||
128 | ||
129 | /* | |
130 | * sgffile_enddump ends the dump and writes the sgf tree to file. | |
131 | */ | |
132 | ||
133 | void | |
134 | sgffile_enddump(const char *filename) | |
135 | { | |
136 | /* Check if we have a valid filename and a tree. */ | |
137 | if (filename && *filename && sgf_dumptree) { | |
138 | if (writesgf(sgf_dumptree->root, filename)) { | |
139 | /* Only delete the tree if writesgf() succeeds. If it doesn't, one | |
140 | * will most likely wish to save into another (writable) file. | |
141 | */ | |
142 | sgfFreeNode(sgf_dumptree->root); | |
143 | sgf_dumptree = NULL; | |
144 | } | |
145 | } | |
146 | } | |
147 | ||
148 | ||
149 | /* | |
150 | * sgffile_printsgf creates an sgf of the current board position | |
151 | * (without any move history). It also adds information about who is | |
152 | * to play and marks illegal moves with the private sgf property IL. | |
153 | */ | |
154 | ||
155 | void | |
156 | sgffile_printsgf(int color_to_play, const char *filename) | |
157 | { | |
158 | SGFTree sgftree; | |
159 | int m, n; | |
160 | char pos[3]; | |
161 | char str[128]; | |
162 | float relative_komi; | |
163 | ||
164 | relative_komi = komi + black_captured - white_captured; | |
165 | ||
166 | sgftree_clear(&sgftree); | |
167 | sgftreeCreateHeaderNode(&sgftree, board_size, relative_komi, handicap); | |
168 | sgf_write_header(sgftree.root, 1, get_random_seed(), relative_komi, | |
169 | handicap, get_level(), chinese_rules); | |
170 | gg_snprintf(str, 128, "GNU Go %s load and print", gg_version()); | |
171 | sgfOverwriteProperty(sgftree.root, "GN", str); | |
172 | ||
173 | sgffile_printboard(&sgftree); | |
174 | ||
175 | if (color_to_play != EMPTY) { | |
176 | sgfAddProperty(sgftree.lastnode, "PL", | |
177 | (color_to_play == WHITE ? "W" : "B")); | |
178 | ||
179 | for (m = 0; m < board_size; ++m) | |
180 | for (n = 0; n < board_size; ++n) | |
181 | if (BOARD(m, n) == EMPTY && !is_legal(POS(m, n), color_to_play)) { | |
182 | gg_snprintf(pos, 3, "%c%c", 'a' + n, 'a' + m); | |
183 | sgfAddProperty(sgftree.lastnode, "IL", pos); | |
184 | } | |
185 | } | |
186 | ||
187 | writesgf(sgftree.root, filename); | |
188 | } | |
189 | ||
190 | ||
191 | /* | |
192 | * sgffile_printboard adds the current board position to the tree. | |
193 | */ | |
194 | ||
195 | void | |
196 | sgffile_printboard(SGFTree *tree) | |
197 | { | |
198 | int i, j; | |
199 | SGFNode *node; | |
200 | ||
201 | gg_assert(tree); | |
202 | node = tree->lastnode; | |
203 | ||
204 | /* Write the white stones to the file. */ | |
205 | for (i = 0; i < board_size; i++) { | |
206 | for (j = 0; j < board_size; j++) { | |
207 | if (BOARD(i, j) == WHITE) | |
208 | sgfAddStone(node, WHITE, i, j); | |
209 | } | |
210 | } | |
211 | ||
212 | /* Write the black stones to the file. */ | |
213 | for (i = 0; i < board_size; i++) { | |
214 | for (j = 0; j < board_size; j++) { | |
215 | if (BOARD(i, j) == BLACK) | |
216 | sgfAddStone(node, BLACK, i, j); | |
217 | } | |
218 | } | |
219 | ||
220 | sgftreeSetLastNode(tree, node); | |
221 | } | |
222 | ||
223 | ||
224 | void | |
225 | sgffile_recordboard(SGFNode *node) | |
226 | { | |
227 | int i, j; | |
228 | ||
229 | if (node) | |
230 | for (i = 0; i < board_size; i++) | |
231 | for (j = 0; j < board_size; j++) | |
232 | if (BOARD(i, j) == BLACK) | |
233 | sgfAddStone(node, BLACK, i, j); | |
234 | } | |
235 | ||
236 | ||
237 | int | |
238 | get_sgfmove(SGFProperty *property) | |
239 | { | |
240 | return POS(get_moveX(property, board_size), get_moveY(property, board_size)); | |
241 | } | |
242 | ||
243 | ||
244 | /* | |
245 | * Local Variables: | |
246 | * tab-width: 8 | |
247 | * c-basic-offset: 2 | |
248 | * End: | |
249 | */ |