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