289 lines
5.9 KiB
C
289 lines
5.9 KiB
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 - either 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. *
|
||
|
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <assert.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#include "sgftree.h"
|
||
|
|
||
|
/*
|
||
|
* Return the integer X move.
|
||
|
*/
|
||
|
|
||
|
int
|
||
|
get_moveX(SGFProperty *property, int boardsize)
|
||
|
{
|
||
|
int i;
|
||
|
if (strlen(property->value) < 2)
|
||
|
return -1;
|
||
|
|
||
|
i = toupper((int) property->value[1]) - 'A';
|
||
|
if (i >= boardsize)
|
||
|
return -1;
|
||
|
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Return the integer Y move.
|
||
|
*/
|
||
|
|
||
|
int
|
||
|
get_moveY(SGFProperty *property, int boardsize)
|
||
|
{
|
||
|
int j;
|
||
|
if (strlen(property->value) < 2)
|
||
|
return -1;
|
||
|
|
||
|
j = toupper((int) property->value[0]) - 'A';
|
||
|
if (j >= boardsize)
|
||
|
return -1;
|
||
|
|
||
|
return j;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Fills (*i, *j) from the property value, in GNU Go co-ords.
|
||
|
* Note that GNU Go uses different conventions from sgf for
|
||
|
* co-ordinates been called.
|
||
|
*
|
||
|
* Returns 1 for a move, 0 for a pass.
|
||
|
*/
|
||
|
|
||
|
int
|
||
|
get_moveXY(SGFProperty *property, int *i, int *j, int boardsize)
|
||
|
{
|
||
|
*i = get_moveX(property, boardsize);
|
||
|
*j = get_moveY(property, boardsize);
|
||
|
|
||
|
if (*i == -1 && *j == -1)
|
||
|
return 0;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Debugging function to print properties as they are traversed.
|
||
|
*/
|
||
|
|
||
|
int
|
||
|
show_sgf_properties(SGFNode *node)
|
||
|
{
|
||
|
SGFProperty *sgf_prop;
|
||
|
int propcount;
|
||
|
|
||
|
propcount = 0;
|
||
|
|
||
|
printf("P: ");
|
||
|
if (!node->props) {
|
||
|
printf("None\n");
|
||
|
return propcount;
|
||
|
}
|
||
|
else {
|
||
|
sgf_prop = node->props;
|
||
|
while (sgf_prop) {
|
||
|
printf("%c%c ", sgf_prop->name & 0x00FF, (sgf_prop->name & 0xFF00)>>8);
|
||
|
sgf_prop = sgf_prop->next;
|
||
|
propcount++;
|
||
|
}
|
||
|
|
||
|
printf("(%d) ", propcount);
|
||
|
if (node->next)
|
||
|
printf("n");
|
||
|
if (node->child)
|
||
|
printf("c");
|
||
|
printf("\n");
|
||
|
}
|
||
|
|
||
|
return propcount;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Recursively traverse each node showing all properties.
|
||
|
*/
|
||
|
|
||
|
int
|
||
|
show_sgf_tree(SGFNode *node)
|
||
|
{
|
||
|
int n = 0; /* number of nodes */
|
||
|
|
||
|
n++;
|
||
|
show_sgf_properties(node);
|
||
|
|
||
|
/* must search depth first- siblings are equal! */
|
||
|
if (node->child)
|
||
|
n += show_sgf_tree(node->child);
|
||
|
|
||
|
if (node->next)
|
||
|
n += show_sgf_tree(node->next);
|
||
|
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Determine if a node has a mark property in it.
|
||
|
*/
|
||
|
|
||
|
int
|
||
|
is_markup_node(SGFNode *node)
|
||
|
{
|
||
|
SGFProperty *sgf_prop;
|
||
|
|
||
|
/* If the node has no properties, there's nothing to do.
|
||
|
This should have been checked by the caller, but it can't hurt. */
|
||
|
if (!node->props)
|
||
|
return 0;
|
||
|
|
||
|
sgf_prop = node->props;
|
||
|
while (sgf_prop) {
|
||
|
switch (sgf_prop->name) {
|
||
|
case SGFCR:
|
||
|
case SGFSQ: /* Square */
|
||
|
case SGFTR: /* Triangle */
|
||
|
case SGFMA: /* Mark */
|
||
|
case SGFBM: /* bad move */
|
||
|
case SGFDO: /* doubtful move */
|
||
|
case SGFIT: /* interesting move */
|
||
|
case SGFTE: /* good move */
|
||
|
return 1;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
sgf_prop = sgf_prop->next;
|
||
|
}
|
||
|
|
||
|
/* No markup property found. */
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Determine if the node has a move in it.
|
||
|
*/
|
||
|
|
||
|
int
|
||
|
is_move_node(SGFNode *node)
|
||
|
{
|
||
|
SGFProperty *sgf_prop;
|
||
|
|
||
|
/* If the node has no properties, there's nothing to do.
|
||
|
This should have been checked by the caller, but it can't hurt. */
|
||
|
if (!node->props)
|
||
|
return 0;
|
||
|
|
||
|
sgf_prop = node->props;
|
||
|
while (sgf_prop) {
|
||
|
switch (sgf_prop->name) {
|
||
|
case SGFB:
|
||
|
case SGFW:
|
||
|
return 1;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
sgf_prop = sgf_prop->next;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Determine if the node has a pass move in it.
|
||
|
*/
|
||
|
|
||
|
int
|
||
|
is_pass_node(SGFNode *node, int boardsize)
|
||
|
{
|
||
|
SGFProperty *sgf_prop;
|
||
|
int i, j;
|
||
|
|
||
|
/* If the node has no properties, there's nothing to do.
|
||
|
This should have been checked by the caller, but it can't hurt. */
|
||
|
if (!node->props)
|
||
|
return 0;
|
||
|
|
||
|
sgf_prop = node->props;
|
||
|
while (sgf_prop) {
|
||
|
switch (sgf_prop->name) {
|
||
|
case SGFB:
|
||
|
case SGFW:
|
||
|
return !get_moveXY(sgf_prop, &i, &j, boardsize);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
sgf_prop = sgf_prop->next;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Determine whose move is in the node.
|
||
|
*/
|
||
|
|
||
|
int
|
||
|
find_move(SGFNode *node)
|
||
|
{
|
||
|
SGFProperty *sgf_prop;
|
||
|
|
||
|
/* If the node has no properties, there's nothing to do.
|
||
|
This should have been checked by the caller, but it can't hurt. */
|
||
|
if (!node->props)
|
||
|
return 0;
|
||
|
|
||
|
sgf_prop = node->props;
|
||
|
while (sgf_prop) {
|
||
|
switch (sgf_prop->name) {
|
||
|
case SGFB:
|
||
|
return BLACK;
|
||
|
break;
|
||
|
case SGFW:
|
||
|
return WHITE;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
sgf_prop = sgf_prop->next;
|
||
|
}
|
||
|
|
||
|
return EMPTY;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Local Variables:
|
||
|
* tab-width: 8
|
||
|
* c-basic-offset: 2
|
||
|
* End:
|
||
|
*/
|