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 | /* 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 | |
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 | */ |