Updated README: Equal sign not required with `--mode` flag.
[sgk-go] / engine / showbord.c
CommitLineData
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. */
53static unsigned char dragon_num[BOARDMAX];
54
55static int next_white; /* next worm number to allocate */
56static 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 */
72static 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
78static 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. */
100void
101start_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 */
112void
113draw_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. */
141void
142draw_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. */
148void
149end_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
168static void
169showchar(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
265void
266showboard(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
318static const char *status_names[] = {
319 DRAGON_STATUS_NAMES
320};
321
322/* Convert a status value to a string. */
323const char *
324status_to_string(enum dragon_status status)
325{
326 return status_names[(int) status];
327}
328
329
330/* Convert a read result to a string */
331const char *
332result_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. */
352int
353DEBUG_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 */