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 - either version 3 * | |
11 | * or (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 <stdio.h> | |
25 | #include <stdlib.h> | |
26 | #include <string.h> | |
27 | #include <assert.h> | |
28 | #include <ctype.h> | |
29 | ||
30 | #include "sgftree.h" | |
31 | ||
32 | /* | |
33 | * Return the integer X move. | |
34 | */ | |
35 | ||
36 | int | |
37 | get_moveX(SGFProperty *property, int boardsize) | |
38 | { | |
39 | int i; | |
40 | if (strlen(property->value) < 2) | |
41 | return -1; | |
42 | ||
43 | i = toupper((int) property->value[1]) - 'A'; | |
44 | if (i >= boardsize) | |
45 | return -1; | |
46 | ||
47 | return i; | |
48 | } | |
49 | ||
50 | /* | |
51 | * Return the integer Y move. | |
52 | */ | |
53 | ||
54 | int | |
55 | get_moveY(SGFProperty *property, int boardsize) | |
56 | { | |
57 | int j; | |
58 | if (strlen(property->value) < 2) | |
59 | return -1; | |
60 | ||
61 | j = toupper((int) property->value[0]) - 'A'; | |
62 | if (j >= boardsize) | |
63 | return -1; | |
64 | ||
65 | return j; | |
66 | } | |
67 | ||
68 | ||
69 | /* Fills (*i, *j) from the property value, in GNU Go co-ords. | |
70 | * Note that GNU Go uses different conventions from sgf for | |
71 | * co-ordinates been called. | |
72 | * | |
73 | * Returns 1 for a move, 0 for a pass. | |
74 | */ | |
75 | ||
76 | int | |
77 | get_moveXY(SGFProperty *property, int *i, int *j, int boardsize) | |
78 | { | |
79 | *i = get_moveX(property, boardsize); | |
80 | *j = get_moveY(property, boardsize); | |
81 | ||
82 | if (*i == -1 && *j == -1) | |
83 | return 0; | |
84 | ||
85 | return 1; | |
86 | } | |
87 | ||
88 | ||
89 | /* | |
90 | * Debugging function to print properties as they are traversed. | |
91 | */ | |
92 | ||
93 | int | |
94 | show_sgf_properties(SGFNode *node) | |
95 | { | |
96 | SGFProperty *sgf_prop; | |
97 | int propcount; | |
98 | ||
99 | propcount = 0; | |
100 | ||
101 | printf("P: "); | |
102 | if (!node->props) { | |
103 | printf("None\n"); | |
104 | return propcount; | |
105 | } | |
106 | else { | |
107 | sgf_prop = node->props; | |
108 | while (sgf_prop) { | |
109 | printf("%c%c ", sgf_prop->name & 0x00FF, (sgf_prop->name & 0xFF00)>>8); | |
110 | sgf_prop = sgf_prop->next; | |
111 | propcount++; | |
112 | } | |
113 | ||
114 | printf("(%d) ", propcount); | |
115 | if (node->next) | |
116 | printf("n"); | |
117 | if (node->child) | |
118 | printf("c"); | |
119 | printf("\n"); | |
120 | } | |
121 | ||
122 | return propcount; | |
123 | } | |
124 | ||
125 | ||
126 | /* | |
127 | * Recursively traverse each node showing all properties. | |
128 | */ | |
129 | ||
130 | int | |
131 | show_sgf_tree(SGFNode *node) | |
132 | { | |
133 | int n = 0; /* number of nodes */ | |
134 | ||
135 | n++; | |
136 | show_sgf_properties(node); | |
137 | ||
138 | /* must search depth first- siblings are equal! */ | |
139 | if (node->child) | |
140 | n += show_sgf_tree(node->child); | |
141 | ||
142 | if (node->next) | |
143 | n += show_sgf_tree(node->next); | |
144 | ||
145 | return n; | |
146 | } | |
147 | ||
148 | ||
149 | /* | |
150 | * Determine if a node has a mark property in it. | |
151 | */ | |
152 | ||
153 | int | |
154 | is_markup_node(SGFNode *node) | |
155 | { | |
156 | SGFProperty *sgf_prop; | |
157 | ||
158 | /* If the node has no properties, there's nothing to do. | |
159 | This should have been checked by the caller, but it can't hurt. */ | |
160 | if (!node->props) | |
161 | return 0; | |
162 | ||
163 | sgf_prop = node->props; | |
164 | while (sgf_prop) { | |
165 | switch (sgf_prop->name) { | |
166 | case SGFCR: | |
167 | case SGFSQ: /* Square */ | |
168 | case SGFTR: /* Triangle */ | |
169 | case SGFMA: /* Mark */ | |
170 | case SGFBM: /* bad move */ | |
171 | case SGFDO: /* doubtful move */ | |
172 | case SGFIT: /* interesting move */ | |
173 | case SGFTE: /* good move */ | |
174 | return 1; | |
175 | break; | |
176 | default: | |
177 | break; | |
178 | } | |
179 | sgf_prop = sgf_prop->next; | |
180 | } | |
181 | ||
182 | /* No markup property found. */ | |
183 | return 0; | |
184 | } | |
185 | ||
186 | ||
187 | /* | |
188 | * Determine if the node has a move in it. | |
189 | */ | |
190 | ||
191 | int | |
192 | is_move_node(SGFNode *node) | |
193 | { | |
194 | SGFProperty *sgf_prop; | |
195 | ||
196 | /* If the node has no properties, there's nothing to do. | |
197 | This should have been checked by the caller, but it can't hurt. */ | |
198 | if (!node->props) | |
199 | return 0; | |
200 | ||
201 | sgf_prop = node->props; | |
202 | while (sgf_prop) { | |
203 | switch (sgf_prop->name) { | |
204 | case SGFB: | |
205 | case SGFW: | |
206 | return 1; | |
207 | break; | |
208 | default: | |
209 | break; | |
210 | } | |
211 | sgf_prop = sgf_prop->next; | |
212 | } | |
213 | ||
214 | return 0; | |
215 | } | |
216 | ||
217 | ||
218 | /* | |
219 | * Determine if the node has a pass move in it. | |
220 | */ | |
221 | ||
222 | int | |
223 | is_pass_node(SGFNode *node, int boardsize) | |
224 | { | |
225 | SGFProperty *sgf_prop; | |
226 | int i, j; | |
227 | ||
228 | /* If the node has no properties, there's nothing to do. | |
229 | This should have been checked by the caller, but it can't hurt. */ | |
230 | if (!node->props) | |
231 | return 0; | |
232 | ||
233 | sgf_prop = node->props; | |
234 | while (sgf_prop) { | |
235 | switch (sgf_prop->name) { | |
236 | case SGFB: | |
237 | case SGFW: | |
238 | return !get_moveXY(sgf_prop, &i, &j, boardsize); | |
239 | break; | |
240 | default: | |
241 | break; | |
242 | } | |
243 | sgf_prop = sgf_prop->next; | |
244 | } | |
245 | ||
246 | return 0; | |
247 | } | |
248 | ||
249 | ||
250 | /* | |
251 | * Determine whose move is in the node. | |
252 | */ | |
253 | ||
254 | int | |
255 | find_move(SGFNode *node) | |
256 | { | |
257 | SGFProperty *sgf_prop; | |
258 | ||
259 | /* If the node has no properties, there's nothing to do. | |
260 | This should have been checked by the caller, but it can't hurt. */ | |
261 | if (!node->props) | |
262 | return 0; | |
263 | ||
264 | sgf_prop = node->props; | |
265 | while (sgf_prop) { | |
266 | switch (sgf_prop->name) { | |
267 | case SGFB: | |
268 | return BLACK; | |
269 | break; | |
270 | case SGFW: | |
271 | return WHITE; | |
272 | break; | |
273 | default: | |
274 | break; | |
275 | } | |
276 | sgf_prop = sgf_prop->next; | |
277 | } | |
278 | ||
279 | return EMPTY; | |
280 | } | |
281 | ||
282 | ||
283 | /* | |
284 | * Local Variables: | |
285 | * tab-width: 8 | |
286 | * c-basic-offset: 2 | |
287 | * End: | |
288 | */ |