Beispiel #1
0
hex_t
hex_load_sgf (hex_format_t format, char * filename)
{
  hex_t hex;
  char * size_str;
  SGFNode * root;
  SGFNode * node;
  if ((root = readsgffile (filename)) == NULL)
    return NULL;
  if (! sgfGetCharProperty (root, "SZ", &size_str))
    return NULL;
  hex = hex_new (atoi (size_str));
  for (node = root->child; node != NULL; node = node->child)
    {
      uint i, x;
      char * move;
      char * prop_name;

      /* Swap isn't supported yet */
      switch (format)
        {
        case HEX_AUTO:
          if (sgfGetCharProperty (node, "W ", &move))
            format = HEX_LG_SGF;
          else if (sgfGetCharProperty (node, "B ", &move))
            format = HEX_SGF;
          else
            return NULL;
          break;
        case HEX_SGF:
          sgfGetCharProperty (node, hex_get_player (hex) == 1 ? "B " : "W ", &move);
          if (! (strcmp ("swap-sides", move) || strcmp ("swap-pieces", move)))
            return NULL;
          if (! strcmp ("resign", move))
            goto end;
          break;
        case HEX_LG_SGF:
          sgfGetCharProperty (node, hex_get_player (hex) == 1 ? "W " : "B ", &move);
          if (! strcmp ("swap", move))
            return NULL;
          if (! strcmp ("resign", move))
            goto end;
          break;
        default:
          return NULL;
        }

      errno = 0;
      i = hex_decode_sgf_pos (move[0]);
      if (errno || i >= hex->size)
        return NULL;

      if (format == HEX_SGF)
        x = atoi (move+1);
      else if (format == HEX_LG_SGF)
        x = hex_decode_sgf_pos (move[1]);
      if (errno || x >= hex->size)
        return NULL;

      hex_move (hex, i, hex->size-x-1);
    }
 end:
  sgfFreeNode (root);
  return hex;
}
Beispiel #2
0
void
play_replay(SGFTree *tree, int color_to_replay)
{
  char *tmpc = NULL;
  float replay_score = 0.0;
  float total_score = 0.0;

  SGFNode *node = tree->root;

  /* Board size and komi are already set up correctly since the game
   * has already been loaded before this function is called. Now we
   * only have to clear the board before starting over.
   */
  clear_board();
 
  if (!quiet) {
    printf("Board Size:   %d\n", board_size);
    if (sgfGetCharProperty(node, "HA", &tmpc))
      printf("Handicap:     %s\n", tmpc);
    printf("Komi:         %.1f\n", komi);
    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);
    if (sgfGetCharProperty(node, "RE", &tmpc))
      printf("Result:       %s\n", tmpc);
  }

  /*
   * 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, &replay_score, &total_score);
    sgffile_output(tree);
    node = node->child;
  }

  if (!quiet)
    printf("Global score: %.2f / %.2f\n", replay_score, total_score);

  if (showtime) {
    gprintf("SLOWEST MOVE: %d at %1m ", slowest_movenum, slowest_move);
    fprintf(stderr, "(%.2f seconds)\n", slowest_time);
    fprintf(stderr, "AVERAGE TIME: %.2f seconds per move\n",
	    total_time / movenum);
    fprintf(stderr, "TOTAL TIME: %.2f seconds\n",
	    total_time);
  }
}
void 
load_and_score_sgf_file(SGFTree *tree, Gameinfo *gameinfo, 
			const char *scoringmode)
{
  int i, j, move_val;
  float result;
  char *tempc = NULL;
  char dummy;
  char text[250];
  char winner;
  int next;
  int pass = 0;
  SGFTree score_tree;
  
  sgftree_clear(&score_tree);
  sgftreeCreateHeaderNode(&score_tree, board_size, komi);
  sgffile_printboard(&score_tree);
  
  next = gameinfo->to_move;
  doing_scoring = 1;
  reset_engine();
  
  if (!strcmp(scoringmode, "finish") || !strcmp(scoringmode, "aftermath")) {
    do {
      move_val = genmove_conservative(&i, &j, next);
      if (move_val >= 0) {
	pass = 0;
	gprintf("%d %s move %m\n", movenum,
		next == WHITE ? "white (O)" : "black (X)", i, j);
      }
      else {
	++pass;
	gprintf("%d %s move : PASS!\n", movenum, 
		next == WHITE ? "white (O)" : "black (X)");
      }
      play_move(POS(i, j), next);
      sgffile_add_debuginfo(score_tree.lastnode, move_val);
      sgftreeAddPlay(&score_tree, next, i, j);
      sgffile_output(&score_tree);
      next = OTHER_COLOR(next);
    } while (movenum <= 10000 && pass < 2);

    if (pass >= 2) {
      /* Calculate the score */
      if (!strcmp(scoringmode, "aftermath"))
	score = aftermath_compute_score(next, komi, &score_tree);
      else
	score = gnugo_estimate_score(&lower_bound, &upper_bound);

      if (score < 0.0) {
	sprintf(text, "Black wins by %1.1f points\n", -score);
	winner = 'B';
      }
      else if (score > 0.0) {
	sprintf(text, "White wins by %1.1f points\n", score);
	winner = 'W';
      }
      else {
	sprintf(text, "Jigo\n");
	winner = '0';
      }
      fputs(text, stdout);
      sgftreeAddComment(&score_tree, text);
      if (sgfGetCharProperty(tree->root, "RE", &tempc)) {
	if (sscanf(tempc, "%1c%f", &dummy, &result) == 2) {
	  fprintf(stdout, "Result from file: %1.1f\n", result);
	  fputs("GNU Go result and result from file are ", stdout);
	  if (result == fabs(score) && winner == dummy)
	    fputs("identical\n", stdout);
	  else
	    fputs("different\n", stdout);
	      
	}
	else {
	  if (tempc[2] == 'R') {
	    fprintf(stdout, "Result from file: Resign\n");
	    fputs("GNU Go result and result from file are ", stdout);
	    if (tempc[0] == winner)
	      fputs("identical\n", stdout);
	    else
	      fputs("different\n", stdout);
	  }
	}
      }
      sgfWriteResult(score_tree.root, score, 1);
      sgffile_output(&score_tree);
    }
  }
  doing_scoring = 0;

  if (strcmp(scoringmode, "aftermath")) {
    /* Before we call estimate_score() we must make sure that the dragon
     * status is computed. Therefore the call to examine_position().
     */
    examine_position(next, EXAMINE_ALL);
    score = estimate_score(NULL, NULL);

    fprintf(stdout, "\n%s seems to win by %1.1f points\n",
      score < 0 ? "B" : "W",
      score < 0 ? -score : score);
  }
}
Beispiel #4
0
void 
load_and_score_sgf_file(SGFTree *tree, Gameinfo *gameinfo, 
			const char *scoringmode)
{
  int move;
  float move_value;
  char *tempc = NULL;
  char text[250];
  char winner;
  int next;
  int pass = 0;
  int method;
  float score;
  SGFTree local_tree;
  SGFTree *score_tree = tree;
  
  /* Default scoring method is ESTIMATE since it's fastest. */
  method = ESTIMATE;
  if (strcmp(scoringmode, "finish") == 0)
    method = FINISH;
  else if (strcmp(scoringmode, "aftermath") == 0)
    method = AFTERMATH;

  /* For aftermath scoring we compress the previous moves to a static
   * board position in the output sgf. This helps a lot when debugging
   * scoring mistakes. We don't do this for the finish method,
   * however, since users may be better served by having GNU Go's
   * selfplay added to the original game record.
   */
  if (method == AFTERMATH) {
    sgftree_clear(&local_tree);
    /* Modify komi to compensate for captured stones. We start at a
     * setup position and since there is no standard sgf property to
     * tell the number of captured stones, a modified komi is the best
     * available solution.
     */
    sgftreeCreateHeaderNode(&local_tree, board_size,
			    komi + black_captured - white_captured, handicap);
    sgffile_printboard(&local_tree);
    sgfAddProperty(local_tree.lastnode, "PL",
		   gameinfo->to_move == WHITE ? "W" : "B");
    score_tree = &local_tree;
  }
  
  next = gameinfo->to_move;
  reset_engine();
  
  /* Complete the game by selfplay for the finish and aftermath methods. */
  if (method != ESTIMATE) {
    doing_scoring = 1;
    while (pass < 2) {
      move = genmove_conservative(next, &move_value);
      if (move != PASS_MOVE) {
	pass = 0;
	gprintf("%d %s move %1m\n", movenum,
		next == WHITE ? "white (O)" : "black (X)", move);
      }
      else {
	pass++;
	gprintf("%d %s move PASS\n", movenum, 
		next == WHITE ? "white (O)" : "black (X)");
      }
      play_move(move, next);
      sgffile_add_debuginfo(score_tree->lastnode, move_value);
      sgftreeAddPlay(score_tree, next, I(move), J(move));
      sgffile_output(score_tree);
      next = OTHER_COLOR(next);
    }
    doing_scoring = 0;
  }
  
  /* Calculate the score. */
  if (method == AFTERMATH)
    score = aftermath_compute_score(next, score_tree);
  else
    score = gnugo_estimate_score(NULL, NULL);
  
  if (score < 0.0) {
    sprintf(text, "Black wins by %1.1f points\n", -score);
    winner = 'B';
  }
  else if (score > 0.0) {
    sprintf(text, "White wins by %1.1f points\n", score);
    winner = 'W';
  }
  else {
    sprintf(text, "Jigo\n");
    winner = '0';
  }
  fputs(text, stdout);
  sgftreeAddComment(score_tree, text);

  /* For the finish and aftermath methods we compare the score with
   * what's stored in the game record.
   *
   * FIXME: No comparison is made if the stored result was 0. Wins by
   *        time or forfeit are not handled either.
   *
   * FIXME: Does anybody actually care about this information? Just
   *        removing this piece of code is a tempting alternative.
   */
  if (method != ESTIMATE && sgfGetCharProperty(tree->root, "RE", &tempc)) {
    char dummy;
    float result;
    if (sscanf(tempc, "%1c%f", &dummy, &result) == 2) {
      fprintf(stdout, "Result from file: %c+%1.1f\n", dummy, result);
      fputs("GNU Go result and result from file are ", stdout);
      if (result == fabs(score) && winner == dummy)
	fputs("identical\n", stdout);
      else
	fputs("different\n", stdout);
      
    }
    else {
      if (tempc[2] == 'R') {
	fprintf(stdout, "Result from file: Resign\n");
	fputs("GNU Go result and result from file are ", stdout);
	if (tempc[0] == winner)
	  fputs("identical\n", stdout);
	else
	  fputs("different\n", stdout);
      }
    }
  }

  if (method != ESTIMATE)
    sgfWriteResult(score_tree->root, score, 1);
  
  sgffile_output(score_tree);
}