/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* 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. *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Convert joseki from sgf format to patterns.db format. */
Usage : joseki prefix filename\n\
/* We don't want to play moves on edges of board which might have been
* cropped, since there might appear an accidential capture.
#define SAFE_ON_BOARD(i, j) ((i) >= 0 && (j) >= 0\
&& (i) < MAX_BOARD - 1 && (j) < MAX_BOARD - 1)
/* Identify the type of joseki move.
* FIXME: We might want the relax the requirement that this info comes
* as the very first character.
identify_move_type(char *text
)
/* Copy the lines starting with a certain character to stdout. */
write_selected_lines(char *text
, char start_char
)
/* Is there any line starting with a certain character? */
selected_line_exists(char *text
, char start_char
)
/* Write the main diagram or the constraint diagram. In the former
* case, pass a NULL pointer for labels.
write_diagram(int movei
, int movej
, int color
, int marki
, int markj
,
char labels
[MAX_BOARD
][MAX_BOARD
])
for (i
= -1; i
<= marki
; i
++) {
for (j
= markj
; j
>= 0; j
--) {
else if (labels
&& labels
[i
][j
])
printf("%c", labels
[i
][j
]);
else if (i
== movei
&& j
== movej
)
else if (BOARD(i
, j
) == color
)
else if (BOARD(i
, j
) == OTHER_COLOR(color
))
/* Write the colon line of the pattern. */
write_colon_line(int move_type
, char symmetry
, char *text
)
/* Locate a possible colon line in the sgf file comment. */
printf(":%c,sF", symmetry
);
/* A little trick to guess whether the supplied colon line in the
* sgf file begins with a classification.
&& (!strchr(p
, ',') || strchr(p
, ',') > strchr(p
, '(')))
while (*p
!= 0 && *p
!= '\n')
/* Check if the board and labels are symmetric. */
board_is_symmetric(int n
, char labels
[MAX_BOARD
][MAX_BOARD
])
for (i
= 0; i
<= n
; i
++) {
for (j
= 0; j
< i
; j
++) {
if (BOARD(i
, j
) != BOARD(j
, i
)
|| (labels
&& labels
[i
][j
] != labels
[j
][i
]))
/* Write a pattern to stdout. */
make_pattern(int movei
, int movej
, int color
,
int marki
, int markj
, int multiple_marks
,
char labels
[MAX_BOARD
][MAX_BOARD
], char *text
,
static int pattern_number
= 0;
move_type
= identify_move_type(text
);
printf("Pattern %s%d\n", prefix
, pattern_number
);
write_selected_lines(text
, '#');
/* Write the main diagram. */
write_diagram(movei
, movej
, color
, marki
, markj
, NULL
);
/* Write the colon line. */
if (movei
== movej
&& marki
== markj
&& board_is_symmetric(marki
, labels
))
write_colon_line(move_type
, symmetry
, text
);
/* Write the constraint diagram if there are any labels, a
* constraint line, or an action line.
|| selected_line_exists(text
, ';')
|| selected_line_exists(text
, '>')) {
write_diagram(movei
, movej
, color
, marki
, markj
, labels
);
/* Write constraint and action lines. */
write_selected_lines(text
, ';');
write_selected_lines(text
, '>');
/* Basic sanity checking. We do this at the end to simplify debugging. */
fprintf(stderr
, "Warning: Multiple square marks in pattern %s%d\n",
if (is_suicide(POS(movei
, movej
), color
)) {
fprintf(stderr
, "Error: Illegal move in pattern %s%d\n",
/* Analyze the node properties in order to make a pattern. Then make
* recursive calls for child node and siblings.
analyze_node(SGFNode
*node
, const char *prefix
)
char labels
[MAX_BOARD
][MAX_BOARD
];
/* Clear the labels array. */
memset(labels
, 0, MAX_BOARD
* MAX_BOARD
);
/* Check the node properties for a move, a square mark, labels, and
for (prop
= node
->props
; prop
; prop
= prop
->next
) {
get_moveXY(prop
, &marki
, &markj
, boardsize
);
markj
= boardsize
- 1 - markj
;
case SGFW
: /* White move */
get_moveXY(prop
, &movei
, &movej
, boardsize
);
movej
= boardsize
- 1 - movej
;
case SGFB
: /* Black move */
get_moveXY(prop
, &movei
, &movej
, boardsize
);
movej
= boardsize
- 1 - movej
;
case SGFLB
: /* Label, with value like "mh:A" */
get_moveXY(prop
, &i
, &j
, boardsize
);
gg_assert(prop
->value
[2] == ':');
labels
[i
][j
] = prop
->value
[3];
/* If we have a move and a square mark, produce a pattern. */
if (SAFE_ON_BOARD(movei
, movej
) && ON_BOARD2(marki
, markj
))
make_pattern(movei
, movej
, color
, marki
, markj
, multiple_marks
,
(label_found
? labels
: NULL
), comment
, prefix
);
/* Traverse child, if any. */
if (SAFE_ON_BOARD(movei
, movej
))
tryko(POS(movei
, movej
), color
, NULL
);
analyze_node(node
->child
, prefix
);
if (SAFE_ON_BOARD(movei
, movej
))
/* Traverse sibling, if any. */
analyze_node(node
->next
, prefix
);
main(int argc
, char *argv
[])
/* Check number of arguments. */
/* Read the sgf file into a tree in memory. */
sgf
= readsgffile(filename
);
fprintf(stderr
, "%s: Couldn't open sgf file %s.\n", argv
[0], filename
);
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\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\
# Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, #\n\
# 2008 and 2009 by the Free Software Foundation. #\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 or #\n\
# (at your option) any later version. #\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\
# 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\
# This file is automatically generated by joseki. Do not edit #\n\
# it directly. Instead, edit the corresponding sgf file. #\n\
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\n\
printf("attribute_map general\n\n");
/* Call the engine to setup and clear the board. */
/* Determine board size of the file. */
if (!sgfGetIntProperty(sgf
, "SZ", &boardsize
)) {
fprintf(stderr
, "joseki: error: can't determine file board size\n");
/* Walk through the tree and make patterns. */
analyze_node(sgf
, prefix
);