328 lines
6.5 KiB
C
328 lines
6.5 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 - 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 <assert.h>
|
||
|
|
||
|
#include "gg_utils.h"
|
||
|
#include "sgftree.h"
|
||
|
|
||
|
void
|
||
|
sgftree_clear(SGFTree *tree)
|
||
|
{
|
||
|
tree->root = NULL;
|
||
|
tree->lastnode = NULL;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
sgftree_readfile(SGFTree *tree, const char *infilename)
|
||
|
{
|
||
|
SGFNode *savetree = tree->root;
|
||
|
|
||
|
tree->root = readsgffile(infilename);
|
||
|
if (tree->root == NULL) {
|
||
|
tree->root = savetree;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
sgfFreeNode(savetree);
|
||
|
tree->lastnode = NULL;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Go back one node in the tree. If lastnode is NULL, go to the last
|
||
|
* node (the one in main variant which has no children).
|
||
|
*/
|
||
|
|
||
|
int
|
||
|
sgftreeBack(SGFTree *tree)
|
||
|
{
|
||
|
if (tree->lastnode) {
|
||
|
if (tree->lastnode->parent)
|
||
|
tree->lastnode = tree->lastnode->parent;
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
else
|
||
|
while (sgftreeForward(tree))
|
||
|
;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Go forward one node in the tree. If lastnode is NULL, go to the
|
||
|
* tree root.
|
||
|
*/
|
||
|
|
||
|
int
|
||
|
sgftreeForward(SGFTree *tree)
|
||
|
{
|
||
|
if (tree->lastnode) {
|
||
|
if (tree->lastnode->child)
|
||
|
tree->lastnode = tree->lastnode->child;
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
else
|
||
|
tree->lastnode = tree->root;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* ================================================================ */
|
||
|
/* High level functions */
|
||
|
/* ================================================================ */
|
||
|
|
||
|
/*
|
||
|
* Returns the node to modify. Use lastnode if available, otherwise
|
||
|
* follow the main variation to the current end of the game.
|
||
|
*/
|
||
|
|
||
|
SGFNode *
|
||
|
sgftreeNodeCheck(SGFTree *tree)
|
||
|
{
|
||
|
SGFNode *node = NULL;
|
||
|
assert(tree->root);
|
||
|
|
||
|
if (tree->lastnode)
|
||
|
node = tree->lastnode;
|
||
|
else {
|
||
|
node = tree->root;
|
||
|
while (node->child)
|
||
|
node = node->child;
|
||
|
}
|
||
|
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Add a stone to the current or the given node.
|
||
|
* Return the node where the stone was added.
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeAddStone(SGFTree *tree, int color, int movex, int movey)
|
||
|
{
|
||
|
SGFNode *node = sgftreeNodeCheck(tree);
|
||
|
sgfAddStone(node, color, movex, movey);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Add a move to the gametree.
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeAddPlay(SGFTree *tree, int color, int movex, int movey)
|
||
|
{
|
||
|
SGFNode *node = sgftreeNodeCheck(tree);
|
||
|
tree->lastnode = sgfAddPlay(node, color, movex, movey);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Add a move to the gametree. New variations are added after the old
|
||
|
* ones rather than before.
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeAddPlayLast(SGFTree *tree, int color, int movex, int movey)
|
||
|
{
|
||
|
SGFNode *node = sgftreeNodeCheck(tree);
|
||
|
tree->lastnode = sgfAddPlayLast(node, color, movex, movey);
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
sgftreeCreateHeaderNode(SGFTree *tree, int boardsize, float komi, int handicap)
|
||
|
{
|
||
|
SGFNode *root = sgfNewNode();
|
||
|
|
||
|
sgfAddPropertyInt(root, "SZ", boardsize);
|
||
|
sgfAddPropertyFloat(root, "KM", komi);
|
||
|
sgfAddPropertyInt(root, "HA", handicap);
|
||
|
tree->root = root;
|
||
|
tree->lastnode = root;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Add a comment to a gametree.
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeAddComment(SGFTree *tree, const char *comment)
|
||
|
{
|
||
|
SGFNode *node;
|
||
|
assert(tree && tree->root);
|
||
|
|
||
|
node = sgftreeNodeCheck(tree);
|
||
|
sgfAddComment(node, comment);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Place text on the board at position (i, j).
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeBoardText(SGFTree *tree, int i, int j, const char *text)
|
||
|
{
|
||
|
SGFNode *node;
|
||
|
assert(tree->root);
|
||
|
|
||
|
node = sgftreeNodeCheck(tree);
|
||
|
sgfBoardText(node, i, j, text);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Place a character on the board at position (i, j).
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeBoardChar(SGFTree *tree, int i, int j, char c)
|
||
|
{
|
||
|
SGFNode *node;
|
||
|
assert(tree->root);
|
||
|
|
||
|
node = sgftreeNodeCheck(tree);
|
||
|
sgfBoardChar(node, i, j, c);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Place a number on the board at position (i, j).
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeBoardNumber(SGFTree *tree, int i, int j, int number)
|
||
|
{
|
||
|
SGFNode *node = sgftreeNodeCheck(tree);
|
||
|
sgfBoardNumber(node, i, j, number);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Place a circle mark on the board at position (i, j).
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeTriangle(SGFTree *tree, int i, int j)
|
||
|
{
|
||
|
SGFNode *node = sgftreeNodeCheck(tree);
|
||
|
sgfTriangle(node, i, j);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Place a circle mark on the board at position (i, j).
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeCircle(SGFTree *tree, int i, int j)
|
||
|
{
|
||
|
SGFNode *node = sgftreeNodeCheck(tree);
|
||
|
sgfCircle(node, i, j);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Place a square mark on the board at position (i, j).
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeSquare(SGFTree *tree, int i, int j)
|
||
|
{
|
||
|
SGFNode *node = sgftreeNodeCheck(tree);
|
||
|
sgfSquare(node, i, j);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Place a (square) mark on the board at position (i, j).
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeMark(SGFTree *tree, int i, int j)
|
||
|
{
|
||
|
SGFNode *node = sgftreeNodeCheck(tree);
|
||
|
sgfMark(node, i, j);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Start a new variant.
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeStartVariant(SGFTree *tree)
|
||
|
{
|
||
|
SGFNode *node = sgftreeNodeCheck(tree);
|
||
|
tree->lastnode = sgfStartVariant(node);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Start a new variant as first child.
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeStartVariantFirst(SGFTree *tree)
|
||
|
{
|
||
|
SGFNode *node = sgftreeNodeCheck(tree);
|
||
|
tree->lastnode = sgfStartVariantFirst(node);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Write result of the game to the game tree.
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
sgftreeWriteResult(SGFTree *tree, float score, int overwrite)
|
||
|
{
|
||
|
assert(tree->root);
|
||
|
|
||
|
sgfWriteResult(tree->root, score, overwrite);
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
sgftreeSetLastNode(SGFTree *tree, SGFNode *last_node)
|
||
|
{
|
||
|
tree->lastnode = last_node;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Local Variables:
|
||
|
* tab-width: 8
|
||
|
* c-basic-offset: 2
|
||
|
* End:
|
||
|
*/
|
||
|
|