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 | showbord.c -- Show current go board and playing information | |
26 | -------------------------------------------------------------*/ | |
27 | ||
28 | /* | |
29 | * NOTE : this is no longer intended as the main user interface | |
30 | * as it was in GNU Go 1.2. It is now a debugging aid, showing | |
31 | * the internal state of dragons, and things. But with | |
32 | * color enabled, it should be easy enough to see the state | |
33 | * of play at a glance. | |
34 | * | |
35 | * Note : the dragons must have been calculated before this is called | |
36 | */ | |
37 | ||
38 | #include "gnugo.h" | |
39 | ||
40 | #include <stdio.h> | |
41 | #include <stdlib.h> | |
42 | #include <string.h> | |
43 | ||
44 | #include "liberty.h" | |
45 | #include "gg_utils.h" | |
46 | ||
47 | ||
48 | /* | |
49 | * Stuff to enumerate the dragons | |
50 | */ | |
51 | ||
52 | /* Element at origin of each worm stores allocated worm number. */ | |
53 | static unsigned char dragon_num[BOARDMAX]; | |
54 | ||
55 | static int next_white; /* next worm number to allocate */ | |
56 | static int next_black; | |
57 | ||
58 | /* linux console : | |
59 | * 0=black | |
60 | * 1=red [critical] | |
61 | * 2=green [alive] | |
62 | * 3=yellow/brown [unknown] | |
63 | * 4=blue | |
64 | * 5=magenta | |
65 | * 6=cyan [dead] | |
66 | * 7=white [unchecked] | |
67 | */ | |
68 | ||
69 | /* Both black and white are common background colors and should be | |
70 | * avoided. | |
71 | */ | |
72 | static const int colors[3][5] = { | |
73 | {0, 0, 0, 0, 0}, /*not used */ | |
74 | {6, 2, 1, 3, 5}, /* WHITE : dead, alive, critical, unknown, unchecked */ | |
75 | {6, 2, 1, 3, 5} /* BLACK : dead, alive, critical, unknown, unchecked */ | |
76 | }; | |
77 | ||
78 | static const int domain_colors[4] = {5, 1, 2, 3}; /* gray, black, white, both */ | |
79 | ||
80 | ||
81 | /* The following four functions define an API for drawing boards. The | |
82 | * typical use would be along the following lines: | |
83 | * | |
84 | * start_draw_board(); | |
85 | * for (m = 0; m < board_size; m++) | |
86 | * for (n = 0; n < board_size; n++) { | |
87 | * int color = ...; | |
88 | * int c = ...; | |
89 | * draw_color_char(m, n, c, color); | |
90 | * } | |
91 | * end_draw_board(); | |
92 | * | |
93 | * Coordinate system, hoshi points, and linefeeds are written | |
94 | * automatically by the board drawing functions. The coordinates m, n | |
95 | * must be ordered as in the full loops above. | |
96 | * | |
97 | */ | |
98 | ||
99 | /* Init color and print a line with coordinate letters above the board. */ | |
100 | void | |
101 | start_draw_board() | |
102 | { | |
103 | gg_init_color(); | |
104 | draw_letter_coordinates(stderr); | |
105 | } | |
106 | ||
107 | /* Draw a colored character. If c has the value EMPTY, either a "." or | |
108 | * a "+" is drawn, depending on whether it is a hoshi stone. If this | |
109 | * is the first or last intersection on a line, the coordinate number | |
110 | * is also drawn. | |
111 | */ | |
112 | void | |
113 | draw_color_char(int m, int n, int c, int color) | |
114 | { | |
115 | /* Is this the first column? */ | |
116 | if (n == 0) | |
117 | fprintf(stderr, "\n%2d", board_size - m); | |
118 | ||
119 | /* Do we see a hoshi point? */ | |
120 | if (c == EMPTY) { | |
121 | if (is_hoshi_point(m, n)) | |
122 | c = '+'; | |
123 | else | |
124 | c = '.'; | |
125 | } | |
126 | ||
127 | /* Use fprintf to draw black characters. This way they'll turn out | |
128 | * white on terminals with black background. | |
129 | */ | |
130 | if (color == GG_COLOR_BLACK) | |
131 | fprintf(stderr, " %c", c); | |
132 | else | |
133 | write_color_char(color, c); | |
134 | ||
135 | /* Is this the last column? */ | |
136 | if (n == board_size - 1) | |
137 | fprintf(stderr, " %-2d", board_size - m); | |
138 | } | |
139 | ||
140 | /* Draw a black character as specified above. */ | |
141 | void | |
142 | draw_char(int m, int n, int c) | |
143 | { | |
144 | draw_color_char(m, n, c, GG_COLOR_BLACK); | |
145 | } | |
146 | ||
147 | /* Print a line with coordinate letters under the board. */ | |
148 | void | |
149 | end_draw_board() | |
150 | { | |
151 | fprintf(stderr, "\n"); | |
152 | draw_letter_coordinates(stderr); | |
153 | fprintf(stderr, "\n"); | |
154 | } | |
155 | ||
156 | ||
157 | /* | |
158 | * Write one stone. Use 'empty' if the board is empty ('-' or '+') | |
159 | * We use capital letters A,B,... for black, lower case a,b,... for white. | |
160 | * This allows us to indicate up to 26 dragons uniquely, and more with | |
161 | * low risk of ambiguity. | |
162 | */ | |
163 | ||
164 | /* The variable xo=1 if running gnugo -T, 2 if running gnugo -E, or | |
165 | * 3 if displaying owl_status. | |
166 | */ | |
167 | ||
168 | static void | |
169 | showchar(int i, int j, int empty, int xo) | |
170 | { | |
171 | struct dragon_data *d; /* dragon data at (i, j) */ | |
172 | struct dragon_data2 *d2; | |
173 | int x; | |
174 | ASSERT_ON_BOARD2(i, j); | |
175 | x = BOARD(i, j); | |
176 | d = &(dragon[POS(i, j)]); | |
177 | d2 = &(dragon2[d->id]); | |
178 | ||
179 | if (x == EMPTY) { | |
180 | if (xo != 2) | |
181 | fprintf(stderr, " %c", empty); | |
182 | else { | |
183 | int empty_color; | |
184 | char empty_char; | |
185 | ||
186 | if (black_eye[POS(i, j)].color == BLACK) { | |
187 | if (white_eye[POS(i, j)].color == WHITE) | |
188 | empty_color = domain_colors[3]; | |
189 | else | |
190 | empty_color = domain_colors[1]; | |
191 | ||
192 | if (black_eye[POS(i, j)].marginal) | |
193 | empty_char = '!'; | |
194 | else | |
195 | empty_char = 'x'; | |
196 | } | |
197 | else if (white_eye[POS(i, j)].color == WHITE) { | |
198 | empty_color = domain_colors[2]; | |
199 | if (white_eye[POS(i, j)].marginal) | |
200 | empty_char = '!'; | |
201 | else | |
202 | empty_char = 'o'; | |
203 | } | |
204 | else { | |
205 | empty_color = domain_colors[0]; | |
206 | empty_char = '.'; | |
207 | } | |
208 | ||
209 | write_color_char(empty_color, empty_char); | |
210 | } | |
211 | } | |
212 | else { | |
213 | int w; | |
214 | ||
215 | if (xo == 0 || ! ON_BOARD1(d->origin)) { | |
216 | fprintf(stderr, " %c", BOARD(i, j) == BLACK ? 'X' : 'O'); | |
217 | return; | |
218 | } | |
219 | ||
220 | /* Figure out ascii character for this dragon. This is the | |
221 | * dragon number allocated to the origin of this worm. */ | |
222 | ||
223 | w = dragon_num[d->origin]; | |
224 | if (!w) { | |
225 | /* Not yet allocated - allocate next one. */ | |
226 | /* Count upwards for black, downwards for white to reduce confusion. */ | |
227 | if (BOARD(i, j) == BLACK) | |
228 | w = dragon_num[d->origin] = next_black++; | |
229 | else | |
230 | w = dragon_num[d->origin] = next_white--; | |
231 | } | |
232 | ||
233 | w = w%26 + (BOARD(i, j) == BLACK ? 'A' : 'a'); | |
234 | ||
235 | /* Now draw it. */ | |
236 | if (xo == 1) | |
237 | write_color_char(colors[BOARD(i, j)][d->crude_status], w); | |
238 | else if (xo == 2) { | |
239 | if (BOARD(i, j) == BLACK) | |
240 | write_color_char(domain_colors[1], 'X'); | |
241 | else | |
242 | write_color_char(domain_colors[2], 'O'); | |
243 | } | |
244 | else if (xo == 3) | |
245 | write_color_char(colors[BOARD(i, j)][d2->owl_status], w); | |
246 | else if (xo == 4) | |
247 | write_color_char(colors[BOARD(i, j)][d->status], w); | |
248 | } | |
249 | } | |
250 | ||
251 | ||
252 | ||
253 | ||
254 | /* | |
255 | * Show go board. | |
256 | * | |
257 | * xo=0: black and white XO board for ascii game | |
258 | * xo=1: colored dragon display | |
259 | * xo=2: colored eye display | |
260 | * xo=3: colored owl display | |
261 | * xo=4: colored matcher status display | |
262 | * | |
263 | */ | |
264 | ||
265 | void | |
266 | showboard(int xo) | |
267 | { | |
268 | int i, j, ii; | |
269 | gg_init_color(); | |
270 | ||
271 | /* Set all dragon numbers to 0. */ | |
272 | memset(dragon_num, 0, sizeof(dragon_num)); | |
273 | ||
274 | next_white = (259 - 26); | |
275 | next_black = 26; | |
276 | ||
277 | start_draw_board(); | |
278 | ||
279 | for (i = 0; i < board_size; i++) { | |
280 | ii = board_size - i; | |
281 | fprintf(stderr, "\n%2d", ii); | |
282 | ||
283 | for (j = 0; j < board_size; j++) | |
284 | showchar(i, j, is_hoshi_point(i, j) ? '+' : '.', xo); | |
285 | ||
286 | fprintf(stderr, " %d", ii); | |
287 | ||
288 | if (xo == 0 && ((board_size < 10 && i == board_size-2) | |
289 | || (board_size >= 10 && i == 8))) | |
290 | fprintf(stderr, " WHITE (O) has captured %d stones", black_captured); | |
291 | ||
292 | if (xo == 0 && ((board_size < 10 && i == board_size-1) | |
293 | || (board_size >= 10 && i == 9))) | |
294 | fprintf(stderr, " BLACK (X) has captured %d stones", white_captured); | |
295 | ||
296 | if (xo == 3) { | |
297 | if (i == board_size-5) | |
298 | write_color_string(GG_COLOR_GREEN, " green=alive"); | |
299 | if (i == board_size-4) | |
300 | write_color_string(GG_COLOR_CYAN, " cyan=dead"); | |
301 | if (i == board_size-3) | |
302 | write_color_string(GG_COLOR_RED, " red=critical"); | |
303 | if (i == board_size-2) | |
304 | write_color_string(GG_COLOR_YELLOW, " yellow=unknown"); | |
305 | if (i == board_size-1) | |
306 | write_color_string(GG_COLOR_MAGENTA, " magenta=unchecked"); | |
307 | } | |
308 | } | |
309 | ||
310 | end_draw_board(); | |
311 | } | |
312 | ||
313 | ||
314 | /* Some print utility function that don't really have a better place | |
315 | * in the engine code than here. | |
316 | */ | |
317 | ||
318 | static const char *status_names[] = { | |
319 | DRAGON_STATUS_NAMES | |
320 | }; | |
321 | ||
322 | /* Convert a status value to a string. */ | |
323 | const char * | |
324 | status_to_string(enum dragon_status status) | |
325 | { | |
326 | return status_names[(int) status]; | |
327 | } | |
328 | ||
329 | ||
330 | /* Convert a read result to a string */ | |
331 | const char * | |
332 | result_to_string(int result) | |
333 | { | |
334 | switch (result) { | |
335 | case 0: return "0"; | |
336 | case KO_B: return "KO_B"; | |
337 | case LOSS: return "LOSS"; | |
338 | case GAIN: return "GAIN"; | |
339 | case KO_A: return "KO_A"; | |
340 | case WIN: return "WIN"; | |
341 | ||
342 | default: return "ERROR"; | |
343 | } | |
344 | } | |
345 | ||
346 | ||
347 | #ifndef HAVE_VARIADIC_DEFINE | |
348 | ||
349 | /* See gnugo.h for related TRACE family macro definitions */ | |
350 | ||
351 | /* Always returns 1 to allow use in short-circuit logical expressions. */ | |
352 | int | |
353 | DEBUG_func(int flag, const char *fmt, ...) | |
354 | { | |
355 | if (debug & flag) { | |
356 | va_list ap; | |
357 | va_start(ap, fmt); | |
358 | vgprintf(stderr, fmt, ap); | |
359 | va_end(ap); | |
360 | } | |
361 | ||
362 | return 1; | |
363 | } | |
364 | ||
365 | #endif /*HAVE_VARIADIC_DEFINE*/ | |
366 | ||
367 | ||
368 | ||
369 | /* | |
370 | * Local Variables: | |
371 | * tab-width: 8 | |
372 | * c-basic-offset: 2 | |
373 | * End: | |
374 | */ |