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
sgffile_add_debuginfo(SGFNode * node,float value)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
sgffile_output(SGFTree * tree)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
sgffile_begindump(SGFTree * tree)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
sgffile_enddump(const char * filename)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
sgffile_printsgf(int color_to_play,const char * filename)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
sgffile_printboard(SGFTree * tree)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
sgffile_recordboard(SGFNode * node)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
get_sgfmove(SGFProperty * property)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  */
250