Initial commit of GNU Go v3.8.
[sgk-go] / patterns / mkeyes.c
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* This is GNU Go, a Go program. Contact gnugo@gnu.org, or see *
* http://www.gnu.org/software/gnugo/ for more information. *
* *
* Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008 and 2009 by the Free Software Foundation. *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation - version 3 or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License in file COPYING for more details. *
* *
* You should have received a copy of the GNU General Public *
* License along with this program; if not, write to the Free *
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02111, USA. *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Compile the eye database. This produces eyes.c. */
/* see also eyes.db, eyes.h and engine/optics.c */
#define MAXLINE 80
#define MAXDIMEN 20
#define MAXSIZE 20
#define MAXPATNO 800
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "eyes.h"
int
main(void)
{
char line[MAXLINE];
int patno = 0;
int p;
char vertex[MAXDIMEN][MAXDIMEN];
signed char marginal[MAXDIMEN][MAXDIMEN];
signed char edge[MAXDIMEN][MAXDIMEN];
unsigned char flags[MAXDIMEN][MAXDIMEN];
int neighbors[MAXSIZE];
int k, l, h;
int m = 0, n = 0;
int vi[MAXSIZE];
int vj[MAXSIZE];
int eye_number[MAXPATNO];
int esize[MAXPATNO];
int msize[MAXPATNO];
int value_a[MAXPATNO];
int value_b[MAXPATNO];
int value_c[MAXPATNO];
int value_d[MAXPATNO];
int ends[MAXPATNO];
int two_neighbors[MAXPATNO];
int three_neighbors[MAXPATNO];
int num_attacks = 0;
int num_defenses = 0;
int debug = 0;
int fatal_errors = 0;
printf("\
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\\\n\
* This is GNU Go, a Go program. Contact gnugo@gnu.org, or see *\n\
* http://www.gnu.org/software/gnugo/ for more information. *\n\
* *\n\
* Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *\n\
* by the Free Software Foundation. *\n\
* *\n\
* This program is free software; you can redistribute it and/or *\n\
* modify it under the terms of the GNU General Public License as *\n\
* published by the Free Software Foundation - version 3 *\n\
* or (at your option) any later version *\n\
* *\n\
* This program is distributed in the hope that it will be useful, *\n\
* but WITHOUT ANY WARRANTY; without even the implied warranty of *\n\
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *\n\
* GNU General Public License in file COPYING for more details. *\n\
* *\n\
* You should have received a copy of the GNU General Public *\n\
* License along with this program; if not, write to the Free *\n\
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *\n\
* Boston, MA 02111, USA. *\n\
\\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n");
printf("/* This file is automatically generated by mkeyes. Do not\n");
printf(" * edit it directly. Instead, edit the eye shape database.\n");
printf(" */\n\n");
printf("#include <stdio.h> /* for NULL */\n");
printf("#include \"eyes.h\"\n\n");
memset(ends, 0, sizeof(ends));
memset(two_neighbors, 0, sizeof(two_neighbors));
memset(three_neighbors, 0, sizeof(three_neighbors));
memset(esize, 0, sizeof(esize));
while (fgets(line, MAXLINE, stdin) && !fatal_errors) {
int last = strlen(line) - 1;
if (line[last] != '\n') {
fprintf(stderr, "mkeyes: line truncated: %s\n", line);
return 1;
}
/* remove trailing whitespace */
for (last--; last >= 0 && isspace((int) line[last]); last--) {
line[last] = '\n';
line[last+1] = '\0';
}
/* New pattern. */
if (sscanf(line, "Pattern %d", &p)) {
eye_number[patno] = p;
if (patno > 0 && eye_number[patno] <= eye_number[patno-1]) {
fprintf(stderr, "mkeyes: Pattern %d out of sequence\n",
eye_number[patno]);
return 1;
}
if (debug)
fprintf(stderr, "parsing pattern %d\n", eye_number[patno]);
memset(vertex, 0, sizeof(vertex));
memset(marginal, 0, sizeof(marginal));
memset(edge, 0, sizeof(edge));
memset(flags, 0, sizeof(flags));
m = 0;
esize[patno] = 0;
msize[patno] = 0;
num_attacks = 0;
num_defenses = 0;
continue;
}
/* Empty line or comment line, skip. */
if (strncmp("#", line, 1) == 0 || strncmp("\n", line, 1) == 0)
continue;
if (strncmp(":", line, 1) != 0) {
/* diagram line. */
for (n = 0; n < MAXDIMEN && strncmp("\n", line + n, 1); n++) {
/* space, harmless CR, or corner symbol */
if (line[n] == ' ' || line[n] == '\r' || line[n] == '+')
continue;
/* vertical edge */
if (line[n] == '|') {
if (n == 0)
edge[m][n+1]++;
else
edge[m][n-1]++;
continue;
}
/* horizontal edge */
if (line[n] == '-') {
if (m == 0)
edge[m+1][n]++;
else
edge[m-1][n]++;
continue;
}
/* All other symbols. */
vi[esize[patno]] = m;
vj[esize[patno]] = n;
vertex[m][n] = line[n];
if (debug)
fprintf(stderr, "%c", line[n]);
switch (line[n])
{
case '.':
marginal[m][n] = 0;
flags[m][n] = CAN_BE_EMPTY;
break;
case '!':
msize[patno]++;
marginal[m][n] = 1;
flags[m][n] = CAN_BE_EMPTY;
break;
case '@':
msize[patno]++;
marginal[m][n] = 1;
flags[m][n] = CAN_BE_EMPTY | EYE_DEFENSE_POINT | EYE_ATTACK_POINT;
num_attacks++;
num_defenses++;
break;
case '$':
msize[patno]++;
marginal[m][n] = 1;
flags[m][n] = CAN_CONTAIN_STONE;
break;
case '(':
msize[patno]++;
marginal[m][n] = 1;
flags[m][n] = CAN_BE_EMPTY | EYE_ATTACK_POINT;
num_attacks++;
break;
case ')':
msize[patno]++;
marginal[m][n] = 1;
flags[m][n] = CAN_BE_EMPTY | EYE_DEFENSE_POINT;
num_defenses++;
break;
case 'x':
marginal[m][n] = 0;
flags[m][n] = CAN_BE_EMPTY | CAN_CONTAIN_STONE;
break;
case '*':
marginal[m][n] = 0;
flags[m][n] = CAN_BE_EMPTY | EYE_ATTACK_POINT | EYE_DEFENSE_POINT;
num_attacks++;
num_defenses++;
break;
case '<':
marginal[m][n] = 0;
flags[m][n] = CAN_BE_EMPTY | EYE_ATTACK_POINT;
num_attacks++;
break;
case '>':
marginal[m][n] = 0;
flags[m][n] = CAN_BE_EMPTY | EYE_DEFENSE_POINT;
num_defenses++;
break;
case 'X':
marginal[m][n] = 0;
flags[m][n] = CAN_CONTAIN_STONE;
break;
default:
fprintf(stderr,
"mkeyes: invalid character %c in pattern %d\n",
line[n], eye_number[patno]);
fatal_errors++;
break;
}
esize[patno]++;
}
m++;
if (debug)
fprintf(stderr, "\n");
}
else {
/* Colon line. */
sscanf(line, ":%1d%1d%1d%1d", &value_a[patno], &value_b[patno],
&value_c[patno], &value_d[patno]);
if (debug)
fprintf(stderr, "value=%d%d%d%d\n", value_a[patno], value_b[patno],
value_c[patno], value_d[patno]);
if (value_b[patno] != value_c[patno]) {
if (num_attacks == 0 || num_defenses == 0) {
fprintf(stderr,
"mkeyes: missing attack or defense point in pattern %d\n",
eye_number[patno]);
fatal_errors++;
}
}
if (value_b[patno] == value_c[patno]) {
if (num_attacks > 0 || num_defenses > 0) {
fprintf(stderr,
"mkeyes: attack or defense point in settled pattern %d\n",
eye_number[patno]);
fatal_errors++;
}
}
printf("static struct eye_vertex eye%d[] = {\n", eye_number[patno]);
for (l = 0; l < esize[patno]; l++) {
int ni[4];
int nj[4];
int nb[4];
int mx[MAXDIMEN][MAXDIMEN];
int count = 0;
int i = vi[l];
int j = vj[l];
memset(mx, -1, sizeof(mx));
neighbors[l] = 0;
for (h = 0; h < 4; h++) {
ni[h] = -1;
nj[h] = -1;
nb[h] = -1;
}
mx[i][j] = 0;
if (i > 0 && vertex[i-1][j]) {
ni[neighbors[l]] = i-1;
nj[neighbors[l]] = j;
neighbors[l]++;
count++;
mx[i-1][j] = l;
}
if (i < MAXDIMEN-1 && vertex[i+1][j]) {
ni[neighbors[l]] = i+1;
nj[neighbors[l]] = j;
neighbors[l]++;
count++;
mx[i+1][j] = l;
}
if (j > 0 && vertex[i][j-1]) {
ni[neighbors[l]] = i;
nj[neighbors[l]] = j-1;
neighbors[l]++;
mx[i][j-1] = l;
}
if (j < MAXDIMEN-1 && vertex[i][j+1]) {
ni[neighbors[l]] = i;
nj[neighbors[l]] = j+1;
neighbors[l]++;
mx[i][j+1] = l;
}
if (neighbors[l] == 1)
ends[patno]++;
else if (neighbors[l] == 2)
two_neighbors[patno]++;
else if (neighbors[l] == 3)
three_neighbors[patno]++;
for (h = 0; h < esize[patno]; h++) {
for (k = 0; k < 4; k++)
if (ni[k] != -1 && vi[h] == ni[k] && vj[h] == nj[k])
nb[k] = h;
}
printf(" {%d, %d, %2d, %d, {%2d, %2d, %2d, %2d}}",
marginal[i][j], (int) edge[i][j], (int) flags[i][j],
neighbors[l], nb[0], nb[1], nb[2], nb[3]);
if (l < esize[patno]-1)
printf(",\n");
else
printf("\n};\n\n");
}
patno++;
if (patno >= MAXPATNO) {
fprintf(stderr,
"mkeyes: Too many eye patterns. Increase MAXPATNO in mkeyes.c\n");
fatal_errors++;
}
}
}
printf("\nstruct eye_graph graphs[] = {\n");
for (l = 0; l < patno; l++) {
printf(" {eye%d, %d, %d, %d, %d, %d, %d, {%d, %d, %d, %d}}",
eye_number[l], eye_number[l], esize[l], msize[l], ends[l],
two_neighbors[l], three_neighbors[l],
value_a[l], value_b[l], value_c[l], value_d[l]);
if (l < patno-1)
printf(",\n");
else
printf(",\n {NULL, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}}\n};\n");
}
if (fatal_errors) {
printf("\n\n#error in eye database. Rebuild.\n\n");
}
return fatal_errors;
}
/*
* Local Variables:
* tab-width: 8
* c-basic-offset: 2
* End:
*/