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 /* Compile the eye database. This produces eyes.c. */
25 
26 /* see also eyes.db, eyes.h and engine/optics.c */
27 
28 
29 #define MAXLINE 80
30 #define MAXDIMEN 20
31 #define MAXSIZE 20
32 #define MAXPATNO 800
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <assert.h>
39 
40 #include "eyes.h"
41 
42 
43 int
main(void)44 main(void)
45 {
46   char line[MAXLINE];
47   int patno = 0;
48   int p;
49   char vertex[MAXDIMEN][MAXDIMEN];
50   signed char marginal[MAXDIMEN][MAXDIMEN];
51   signed char edge[MAXDIMEN][MAXDIMEN];
52   unsigned char flags[MAXDIMEN][MAXDIMEN];
53   int neighbors[MAXSIZE];
54   int k, l, h;
55   int m = 0, n = 0;
56   int vi[MAXSIZE];
57   int vj[MAXSIZE];
58   int eye_number[MAXPATNO];
59   int esize[MAXPATNO];
60   int msize[MAXPATNO];
61   int value_a[MAXPATNO];
62   int value_b[MAXPATNO];
63   int value_c[MAXPATNO];
64   int value_d[MAXPATNO];
65   int ends[MAXPATNO];
66   int two_neighbors[MAXPATNO];
67   int three_neighbors[MAXPATNO];
68   int num_attacks = 0;
69   int num_defenses = 0;
70   int debug = 0;
71   int fatal_errors = 0;
72 
73   printf("\
74 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\\\n\
75  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *\n\
76  * http://www.gnu.org/software/gnugo/ for more information.          *\n\
77  *                                                                   *\n\
78  * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *\n\
79  * by the Free Software Foundation.                                  *\n\
80  *                                                                   *\n\
81  * This program is free software; you can redistribute it and/or     *\n\
82  * modify it under the terms of the GNU General Public License as    *\n\
83  * published by the Free Software Foundation - version 3             *\n\
84  * or (at your option) any later version                             *\n\
85  *                                                                   *\n\
86  * This program is distributed in the hope that it will be useful,   *\n\
87  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *\n\
88  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     *\n\
89  * GNU General Public License in file COPYING for more details.      *\n\
90  *                                                                   *\n\
91  * You should have received a copy of the GNU General Public         *\n\
92  * License along with this program; if not, write to the Free        *\n\
93  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,       *\n\
94  * Boston, MA 02111, USA.                                            *\n\
95 \\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n");
96 
97   printf("/* This file is automatically generated by mkeyes. Do not\n");
98   printf(" * edit it directly. Instead, edit the eye shape database.\n");
99   printf(" */\n\n");
100   printf("#include <stdio.h> /* for NULL */\n");
101   printf("#include \"eyes.h\"\n\n");
102 
103   memset(ends, 0, sizeof(ends));
104   memset(two_neighbors, 0, sizeof(two_neighbors));
105   memset(three_neighbors, 0, sizeof(three_neighbors));
106   memset(esize, 0, sizeof(esize));
107 
108   while (fgets(line, MAXLINE, stdin) && !fatal_errors) {
109     int last = strlen(line) - 1;
110 
111     if (line[last] != '\n') {
112       fprintf(stderr, "mkeyes: line truncated: %s\n", line);
113       return 1;
114     }
115 
116     /* remove trailing whitespace */
117     for (last--; last >= 0 && isspace((int) line[last]); last--) {
118       line[last]   = '\n';
119       line[last+1] = '\0';
120     }
121 
122     /* New pattern. */
123     if (sscanf(line, "Pattern %d", &p)) {
124       eye_number[patno] = p;
125       if (patno > 0 && eye_number[patno] <= eye_number[patno-1]) {
126 	fprintf(stderr, "mkeyes: Pattern %d out of sequence\n",
127 		eye_number[patno]);
128 	return 1;
129       }
130       if (debug)
131 	fprintf(stderr, "parsing pattern %d\n", eye_number[patno]);
132 
133       memset(vertex, 0, sizeof(vertex));
134       memset(marginal, 0, sizeof(marginal));
135       memset(edge, 0, sizeof(edge));
136       memset(flags, 0, sizeof(flags));
137 
138       m = 0;
139       esize[patno] = 0;
140       msize[patno] = 0;
141       num_attacks = 0;
142       num_defenses = 0;
143       continue;
144     }
145 
146     /* Empty line or comment line, skip. */
147     if (strncmp("#", line, 1) == 0 || strncmp("\n", line, 1) == 0)
148       continue;
149 
150     if (strncmp(":", line, 1) != 0) {
151       /* diagram line. */
152       for (n = 0; n < MAXDIMEN && strncmp("\n", line + n, 1); n++) {
153 	/* space, harmless CR, or corner symbol */
154 	if (line[n] == ' ' || line[n] == '\r' || line[n] == '+')
155 	  continue;
156 
157 	/* vertical edge */
158 	if (line[n] == '|') {
159 	  if (n == 0)
160 	    edge[m][n+1]++;
161 	  else
162 	    edge[m][n-1]++;
163 	  continue;
164 	}
165 
166 	/* horizontal edge */
167 	if (line[n] == '-') {
168 	  if (m == 0)
169 	    edge[m+1][n]++;
170 	  else
171 	    edge[m-1][n]++;
172 	  continue;
173 	}
174 
175 	/* All other symbols. */
176 	vi[esize[patno]] = m;
177 	vj[esize[patno]] = n;
178 	vertex[m][n] = line[n];
179 	if (debug)
180 	  fprintf(stderr, "%c", line[n]);
181 	switch (line[n])
182 	{
183 	  case '.':
184 	    marginal[m][n] = 0;
185 	    flags[m][n] = CAN_BE_EMPTY;
186 	    break;
187 
188 	  case '!':
189 	    msize[patno]++;
190 	    marginal[m][n] = 1;
191 	    flags[m][n] = CAN_BE_EMPTY;
192 	    break;
193 
194 	  case '@':
195 	    msize[patno]++;
196 	    marginal[m][n] = 1;
197 	    flags[m][n] = CAN_BE_EMPTY | EYE_DEFENSE_POINT | EYE_ATTACK_POINT;
198 	    num_attacks++;
199 	    num_defenses++;
200 	    break;
201 
202 	  case '$':
203 	    msize[patno]++;
204 	    marginal[m][n] = 1;
205 	    flags[m][n] = CAN_CONTAIN_STONE;
206 	    break;
207 
208 	  case '(':
209 	    msize[patno]++;
210 	    marginal[m][n] = 1;
211 	    flags[m][n] = CAN_BE_EMPTY | EYE_ATTACK_POINT;
212 	    num_attacks++;
213 	    break;
214 
215 	  case ')':
216 	    msize[patno]++;
217 	    marginal[m][n] = 1;
218 	    flags[m][n] = CAN_BE_EMPTY | EYE_DEFENSE_POINT;
219 	    num_defenses++;
220 	    break;
221 
222 	  case 'x':
223 	    marginal[m][n] = 0;
224 	    flags[m][n] = CAN_BE_EMPTY | CAN_CONTAIN_STONE;
225 	    break;
226 
227 	  case '*':
228 	    marginal[m][n] = 0;
229 	    flags[m][n] = CAN_BE_EMPTY | EYE_ATTACK_POINT | EYE_DEFENSE_POINT;
230 	    num_attacks++;
231 	    num_defenses++;
232 	    break;
233 
234 	  case '<':
235 	    marginal[m][n] = 0;
236 	    flags[m][n] = CAN_BE_EMPTY | EYE_ATTACK_POINT;
237 	    num_attacks++;
238 	    break;
239 
240 	  case '>':
241 	    marginal[m][n] = 0;
242 	    flags[m][n] = CAN_BE_EMPTY | EYE_DEFENSE_POINT;
243 	    num_defenses++;
244 	    break;
245 
246 	  case 'X':
247 	    marginal[m][n] = 0;
248 	    flags[m][n] = CAN_CONTAIN_STONE;
249 	    break;
250 
251 	  default:
252 	    fprintf(stderr,
253 		    "mkeyes: invalid character %c in pattern %d\n",
254 		    line[n], eye_number[patno]);
255 	    fatal_errors++;
256 	    break;
257 	}
258 	esize[patno]++;
259       }
260       m++;
261       if (debug)
262 	fprintf(stderr, "\n");
263     }
264     else {
265       /* Colon line. */
266       sscanf(line, ":%1d%1d%1d%1d", &value_a[patno], &value_b[patno],
267 	     &value_c[patno], &value_d[patno]);
268       if (debug)
269 	fprintf(stderr, "value=%d%d%d%d\n", value_a[patno], value_b[patno],
270 		value_c[patno], value_d[patno]);
271 
272       if (value_b[patno] != value_c[patno]) {
273 	if (num_attacks == 0 || num_defenses == 0) {
274 	  fprintf(stderr,
275 		  "mkeyes: missing attack or defense point in pattern %d\n",
276 		  eye_number[patno]);
277 	  fatal_errors++;
278 	}
279       }
280 
281       if (value_b[patno] == value_c[patno]) {
282 	if (num_attacks > 0 || num_defenses > 0) {
283 	  fprintf(stderr,
284 		  "mkeyes: attack or defense point in settled pattern %d\n",
285 		  eye_number[patno]);
286 	  fatal_errors++;
287 	}
288       }
289 
290       printf("static struct eye_vertex eye%d[] = {\n", eye_number[patno]);
291 
292       for (l = 0; l < esize[patno]; l++) {
293 	int ni[4];
294 	int nj[4];
295 	int nb[4];
296 	int mx[MAXDIMEN][MAXDIMEN];
297 	int count = 0;
298 	int i = vi[l];
299 	int j = vj[l];
300 
301 	memset(mx, -1, sizeof(mx));
302 
303 	neighbors[l] = 0;
304 
305 	for (h = 0; h < 4; h++) {
306 	  ni[h] = -1;
307 	  nj[h] = -1;
308 	  nb[h] = -1;
309 	}
310 
311 	mx[i][j] = 0;
312 
313 	if (i > 0 && vertex[i-1][j]) {
314 	  ni[neighbors[l]] = i-1;
315 	  nj[neighbors[l]] = j;
316 	  neighbors[l]++;
317 	  count++;
318 	  mx[i-1][j] = l;
319 	}
320 
321 	if (i < MAXDIMEN-1 && vertex[i+1][j]) {
322 	  ni[neighbors[l]] = i+1;
323 	  nj[neighbors[l]] = j;
324 	  neighbors[l]++;
325 	  count++;
326 	  mx[i+1][j] = l;
327 	}
328 
329 	if (j > 0 && vertex[i][j-1]) {
330 	  ni[neighbors[l]] = i;
331 	  nj[neighbors[l]] = j-1;
332 	  neighbors[l]++;
333 	  mx[i][j-1] = l;
334 	}
335 
336 	if (j < MAXDIMEN-1 && vertex[i][j+1]) {
337 	  ni[neighbors[l]] = i;
338 	  nj[neighbors[l]] = j+1;
339 	  neighbors[l]++;
340 	  mx[i][j+1] = l;
341 	}
342 
343 
344 	if (neighbors[l] == 1)
345 	  ends[patno]++;
346 	else if (neighbors[l] == 2)
347 	  two_neighbors[patno]++;
348 	else if (neighbors[l] == 3)
349 	  three_neighbors[patno]++;
350 
351 	for (h = 0; h < esize[patno]; h++) {
352 
353 	  for (k = 0; k < 4; k++)
354 	    if (ni[k] != -1 && vi[h] == ni[k] && vj[h] == nj[k])
355 	      nb[k] = h;
356 	}
357 
358 
359 	printf("  {%d, %d, %2d, %d, {%2d, %2d, %2d, %2d}}",
360 	       marginal[i][j], (int) edge[i][j], (int) flags[i][j],
361 	       neighbors[l], nb[0], nb[1], nb[2], nb[3]);
362 
363 	if (l < esize[patno]-1)
364 	  printf(",\n");
365 	else
366 	  printf("\n};\n\n");
367       }
368 
369       patno++;
370       if (patno >= MAXPATNO) {
371 	fprintf(stderr,
372 		"mkeyes: Too many eye patterns. Increase MAXPATNO in mkeyes.c\n");
373 	fatal_errors++;
374       }
375     }
376   }
377 
378 
379   printf("\nstruct eye_graph graphs[] = {\n");
380   for (l = 0; l < patno; l++) {
381 
382     printf("  {eye%d, %d, %d, %d, %d, %d, %d, {%d, %d, %d, %d}}",
383 	   eye_number[l], eye_number[l], esize[l], msize[l], ends[l],
384 	   two_neighbors[l], three_neighbors[l],
385 	   value_a[l], value_b[l], value_c[l], value_d[l]);
386     if (l < patno-1)
387       printf(",\n");
388     else
389       printf(",\n  {NULL, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}}\n};\n");
390   }
391 
392   if (fatal_errors) {
393     printf("\n\n#error in eye database.  Rebuild.\n\n");
394   }
395 
396   return fatal_errors;
397 }
398 
399 /*
400  * Local Variables:
401  * tab-width: 8
402  * c-basic-offset: 2
403  * End:
404  */
405