/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * 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 and 2004 * * 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 2 * * * * 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., 59 Temple Place - Suite 330, * * Boston, MA 02111, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gnugo.h" #include #include #include #include #include "interface.h" #include "sgftree.h" #include "gg_utils.h" #include "liberty.h" static void replay_node(SGFNode *node, int color_to_test); static float replay_score; static float total_score; /* --------------------------------------------------------------*/ /* replay a game */ /* --------------------------------------------------------------*/ void play_replay(Gameinfo *gameinfo, int color_to_replay) { int tmpi; float tmpf; char *tmpc = NULL; SGFTree tree = gameinfo->game_record; SGFNode *node = tree.root; /* Get the board size. */ if (!sgfGetIntProperty(node, "SZ", &tmpi)) { fprintf(stderr, "Couldn't find the size (SZ) attribute!\n"); exit(EXIT_FAILURE); } gnugo_clear_board(tmpi); /* Get the komi. */ if (sgfGetFloatProperty(node, "KM", &tmpf)) komi = tmpf; if (!quiet) { if (sgfGetCharProperty(node, "RU", &tmpc)) printf("Ruleset: %s\n", tmpc); if (sgfGetCharProperty(node, "GN", &tmpc)) printf("Game Name: %s\n", tmpc); if (sgfGetCharProperty(node, "DT", &tmpc)) printf("Game Date: %s\n", tmpc); if (sgfGetCharProperty(node, "GC", &tmpc)) printf("Game Comment: %s\n", tmpc); if (sgfGetCharProperty(node, "US", &tmpc)) printf("Game User: %s\n", tmpc); if (sgfGetCharProperty(node, "PB", &tmpc)) printf("Black Player: %s\n", tmpc); if (sgfGetCharProperty(node, "PW", &tmpc)) printf("White Player: %s\n", tmpc); gameinfo_print(gameinfo); replay_score = 0.0; total_score = 0.0; } /* * Now actually run through the file. This is the interesting part. * We need to traverse the SGF tree, and every time we encounter a node * we need to check what move GNU Go would make, and see if it is OK. */ while (node) { replay_node(node, color_to_replay); sgffile_output(&tree); node = node->child; } if (!quiet) { printf("\nGlobal score: %.2f / %.2f", replay_score, total_score); } if (showtime) { gprintf("\nSLOWEST MOVE: %d at %1m ", slowest_movenum, slowest_move); fprintf(stderr, "(%.2f seconds)\n", slowest_time); fprintf(stderr, "\nAVERAGE TIME: %.2f seconds per move\n", total_time / movenum); fprintf(stderr, "\nTOTAL TIME: %.2f seconds\n", total_time); } } /* * Handle this node. */ static void replay_node(SGFNode *node, int color_to_replay) { SGFProperty *sgf_prop; /* iterate over properties of the node */ SGFProperty *move_prop = NULL; /* remember if we see a move property */ int color; /* color of move to be made at this node. */ int boardsize = gnugo_get_boardsize(); int m, n; /* Move from file. */ int i, j; /* Move generated by GNU Go. */ char buf[127]; /* Handle any AB / AW properties, and note presence * of move properties. */ for (sgf_prop = node->props; sgf_prop; sgf_prop = sgf_prop->next) { switch (sgf_prop->name) { case SGFAB: /* add black */ gnugo_add_stone(get_moveX(sgf_prop, boardsize), get_moveY(sgf_prop, boardsize), BLACK); break; case SGFAW: /* add white */ gnugo_add_stone(get_moveX(sgf_prop, boardsize), get_moveY(sgf_prop, boardsize), WHITE); break; case SGFB: case SGFW: move_prop = sgf_prop; /* remember it for later */ break; } } /* Only generate moves at move nodes. */ if (!move_prop) return; m = get_moveX(move_prop, boardsize); n = get_moveY(move_prop, boardsize); color = (move_prop->name == SGFW) ? WHITE : BLACK; if (color == color_to_replay || color_to_replay == GRAY) { /* Get a move from the engine for color. */ float move_val = gnugo_genmove(&i, &j, color); /* Now report on how well the computer generated the move. */ if (i != m || j != n || !quiet) { mprintf("Move %d (%C): ", movenum + 1, color); if (move_val < 0.0 && !gnugo_is_pass(i, j)) printf("GNU Go resigns "); else { mprintf("GNU Go plays %m ", i, j); if (!gnugo_is_pass(i, j)) printf("(%.2f) ", potential_moves[i][j]); } mprintf("- Game move %m ", m, n); if (!gnugo_is_pass(m, n) && potential_moves[m][n] > 0.0) printf("(%.2f) ", potential_moves[m][n]); printf("\n"); if (!quiet) { replay_score += (potential_moves[i][j] - potential_moves[m][n]); total_score += potential_moves[i][j]; } } if (i != m || j != n) { if (move_val < 0.0 && !gnugo_is_pass(i, j)) gg_snprintf(buf, 127, "GNU Go resigns - Game move %s (%.2f)", location_to_string(POS(m, n)), gnugo_is_pass(m, n) && potential_moves[m][n] < 0.0 ? 0 : potential_moves[m][n]); else { gg_snprintf(buf, 127, "GNU Go plays %s (%.2f) - Game move %s (%.2f)", location_to_string(POS(i, j)), gnugo_is_pass(i, j) ? 0 : potential_moves[i][j], location_to_string(POS(m, n)), gnugo_is_pass(m, n) && potential_moves[m][n] < 0.0 ? 0 : potential_moves[m][n]); sgfCircle(node, i, j); } } else gg_snprintf(buf, 127, "GNU Go plays the same move %s (%.2f)", location_to_string(POS(i, j)), gnugo_is_pass(i, j) ? 0 : potential_moves[i][j]); sgfAddComment(node, buf); sgffile_add_debuginfo(node, 0); } /* Finally, do play the move from the file. */ gnugo_play_move(m, n, color); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */