gnugo-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnugo-devel] doc and scoring patch


From: Gunnar Farneback
Subject: [gnugo-devel] doc and scoring patch
Date: Thu, 05 Jun 2003 01:14:16 +0200
User-agent: EMH/1.14.1 SEMI/1.14.3 (Ushinoya) FLIM/1.14.2 (Yagi-Nishiguchi) APEL/10.3 Emacs/20.7 (sparc-sun-solaris2.7) (with unibyte mode)

This patch includes some minor doc revisions. It also cleans up
load_and_score_sgf_file() and revises it to agree with the revised
docs. :-)

- doc revisions
- load_and_score_sgf_file() revised

/Gunnar

Index: doc/analyze.texi
===================================================================
RCS file: /cvsroot/gnugo/gnugo/doc/analyze.texi,v
retrieving revision 1.8
diff -u -r1.8 analyze.texi
--- doc/analyze.texi    1 Apr 2002 01:42:44 -0000       1.8
+++ doc/analyze.texi    4 Jun 2003 13:43:22 -0000
@@ -208,60 +208,10 @@
 @section Scoring the game
 @cindex scoring
 
-GNU Go can score the game. If done at the last move, this is usually
-accurate unless there is a seki. Normally GNU Go will report its
-opinion about the score at the end of the game, but if you want this
-information about a game stored in a file, use the @option{--score}
-option.
-
address@hidden
-gnugo --score last -l filename
address@hidden example
-
address@hidden
-loads the sgf file to the end of the file and estimates the winner after the
-last stored move by estimating the territory.
-
address@hidden
-gnugo --score end -l filename
address@hidden example
-
address@hidden
-loads the sgf file and GNU Go continues to play after the last stored
-move by itself up to the very end.  Then the winner is determined by
-estimating the territory.
-
address@hidden
-gnugo --score aftermath -l filename
address@hidden example
-
address@hidden
-loads the sgf file and GNU Go continues to play after the last stored
-move by itself up to the very end. Then the winner is determined by
-the most accurate algorithm available. Slower but more accurate than
address@hidden end}.
-
address@hidden
-gnugo --score L10 -l filename
address@hidden example
-
address@hidden
-loads the sgf file until a stone is placed on L10. Now the winner will
-be estimated as with @command{gnugo --score last}.
-
-Any of these commands may be combined with @option{--chinese-rules}
-if you want to use Chinese (area) counting.
-
address@hidden
-gnugo --score 100 -l filename
address@hidden example
-
address@hidden
-loads the sgf file until move number 100. Now the winner will be estimated
-as with @command{gnugo --score last}.
-
-If the option @option{-o @var{outputfilename}} is provided, the results
-will also be written as comment at the end of the output file.
+GNU Go can score the game. Normally GNU Go will report its opinion about
+the score at the end of the game, but if you want this information about
+a game stored in a file, use the @option{--score} option (@pxref{Invoking
+GNU Go}).
 
 @node  Colored Display,  , Scoring, Analyzing
 @comment  node-name,  next,  previous,  up
@@ -269,7 +219,7 @@
 @cindex colored display
 
 Various colored displays of the board may be obtained in a color
address@hidden or @command{rxvt} window. Xterm will only work if xterm is not
address@hidden or @command{rxvt} window. Xterm will only work if xterm is
 compiled with color support. If the colors are not displayed on your xterm,
 try @command{rxvt}.  You may also use the Linux console. The colored display
 will work best if the background color is black; if this is not the case you
Index: doc/eyes.texi
===================================================================
RCS file: /cvsroot/gnugo/gnugo/doc/eyes.texi,v
retrieving revision 1.5
diff -u -r1.5 eyes.texi
--- doc/eyes.texi       26 Dec 2002 04:33:48 -0000      1.5
+++ doc/eyes.texi       4 Jun 2003 13:43:24 -0000
@@ -1,9 +1,5 @@
 The purpose of this Chapter is to describe the algorithm used in
-GNU Go 3.0 to determine eyes. There are actually two alternative
-algorithms: the graph-based algorithm in @file{optics.c}, and
-the algorithm based on reading in @file{life.c}. The life
-code is slower than the graph based algorithm, but sometimes more 
-accurate. You can enable it by using the option @option{--life}.
+GNU Go to determine eyes.
 
 @menu
 * Local Games::                 Local games
Index: doc/influence.texi
===================================================================
RCS file: /cvsroot/gnugo/gnugo/doc/influence.texi,v
retrieving revision 1.14
diff -u -r1.14 influence.texi
--- doc/influence.texi  3 Jun 2003 14:36:24 -0000       1.14
+++ doc/influence.texi  4 Jun 2003 13:43:29 -0000
@@ -985,7 +985,7 @@
 second time. Tactically captured worms are taken into account both
 times. 
 @end quotation
address@hidden @option{--debuginfluence @var{location}}
address@hidden @option{--debug-influence @var{location}}
 @quotation
 Show influence diagrams after the move at the given location. An
 important limitation of this option is that it's only effective for
Index: doc/overview.texi
===================================================================
RCS file: /cvsroot/gnugo/gnugo/doc/overview.texi,v
retrieving revision 1.10
diff -u -r1.10 overview.texi
--- doc/overview.texi   17 May 2002 20:56:30 -0000      1.10
+++ doc/overview.texi   4 Jun 2003 13:43:31 -0000
@@ -604,14 +604,6 @@
 Header file for the engine. The name ``liberty'' connotes
 freedom (@pxref{Copying}).
 @end quotation
address@hidden @file{life.c}
address@hidden
-The code in this file contains an alternative approach to
-life and death based on reading instead of the static approach
-in @file{optics.c}. This code is experimental. It is reasonably
-accurate but too slow. It is activated when gnugo is invoked
-with the @option{--life} option.
address@hidden quotation
 @item @file{matchpat.c}
 @quotation
 This file contains the pattern matcher @code{matchpat()}, which looks for
@@ -634,7 +626,7 @@
 This file does life and death reading. The paradigm is that moves
 are played by both players trying to expand and shrink the eyespace
 until a static configuration is reached where it can be analyzed
-by the code in @file{optics.c} or @file{life.c}.
+by the code in @file{optics.c}.
 @end quotation
 @item @file{printutils.c}
 @quotation
Index: doc/reading.texi
===================================================================
RCS file: /cvsroot/gnugo/gnugo/doc/reading.texi,v
retrieving revision 1.11
diff -u -r1.11 reading.texi
--- doc/reading.texi    3 Jun 2003 14:36:24 -0000       1.11
+++ doc/reading.texi    4 Jun 2003 13:43:35 -0000
@@ -958,7 +958,7 @@
 examining the variation file produced by the command:
 
 @example
-gnugo -l ko5.sgf --quiet --decidestring L1 -o vars.sgf
+gnugo -l ko5.sgf --quiet --decide-string L1 -o vars.sgf
 @end example
 
 The correct resolution is that H1 attacks L1 unconditionally while K2
Index: doc/using.texi
===================================================================
RCS file: /cvsroot/gnugo/gnugo/doc/using.texi,v
retrieving revision 1.13
diff -u -r1.13 using.texi
--- doc/using.texi      12 Jan 2003 19:44:21 -0000      1.13
+++ doc/using.texi      4 Jun 2003 13:43:38 -0000
@@ -274,7 +274,7 @@
 Load the named SGF file. GNU Go will generate a move for
 the player who is about to move. If you want to override this
 and generate a move for the other player you may add the
-option @option{color @var{<color>}} where @var{<color>} is
+option @option{--color @var{<color>}} where @var{<color>} is
 @code{black} or @code{white}.
 @end quotation
 @item @option{--orientation @var{n}}
@@ -309,7 +309,7 @@
 @end quotation
 @end itemize
 
address@hidden Other general options:
address@hidden Other general options
 @itemize
 @item @option{-M}, @option{--cache-size @var{megs}} 
 @quotation
@@ -333,7 +333,8 @@
 Use Chinese rules. This means that the Chinese or Area Counting is
 followed. It may affect the score of the game by one point in even
 games, more if there is a handicap (since in Chinese Counting the
-handicap stones count for Black).
+handicap stones count for Black) or if either player passes during the
+game.
 @end quotation
 @item @option{--japanese-rules} 
 @quotation
@@ -421,7 +422,7 @@
 depth (default 13), GNU Go still tries to attack strings with only
 3 liberties, but only tries one move at each node.
 @end quotation
address@hidden @option{--aa_depth @var{depth}}
address@hidden @option{--aa-depth @var{depth}}
 @quotation
 The reading function @code{atari_atari} looks for combinations beginning
 with a series of ataris, and culminating with some string having an
@@ -456,7 +457,7 @@
 @end quotation
 @end itemize
 
address@hidden Ascii Mode Options
address@hidden Ascii mode options
 @cindex ascii mode
 @itemize
 @item @option{--color @var{color}}
@@ -469,7 +470,7 @@
 @end quotation
 @end itemize
 
address@hidden Development options:
address@hidden Development options
 
 @itemize
 @item @option{--replay @var{color}} 
@@ -510,7 +511,7 @@
 @quotation
 Use rxvt, xterm or Linux Console. (@pxref{Colored Display})
 @end quotation
address@hidden @option{-E}, @option{printeyes}: colored display of eye spaces
address@hidden @option{-E}, @option{--printeyes}: colored display of eye spaces
 @quotation
 Use rxvt, xterm or Linux Console. (@pxref{Colored Display})
 @end quotation
@@ -652,37 +653,43 @@
 @end quotation
 @item @option{--score @var{method}}
 @quotation
-Requires @option{-l}. @var{method} can be "end", "last", "aftermath" or a move.
-"end" and "aftermath" are appropriate when the game is complete, or nearly
-so, and both try to supply an accurate final score. The other options may
-be used to get an estimate during the middle of the game. Any of these
-options may be combined with @option{--chinese-rule} if you want to
-use Chinese (Area) counting.
+Requires @option{-l} to specify which game to score and @option{-L} if
+you want to score anywhere else than at the end of the game record.
address@hidden can be "estimate", "finish", or "aftermath". "finish" and
+"aftermath" are appropriate when the game is complete, or nearly so, and
+both try to supply an accurate final score. Notice that if the game is
+not already finished it will be played out, which may take quite a long
+time if the game is far from complete. The "estimate" method may be used
+to get a quick estimate during the middle of the game. Any of these
+options may be combined with @option{--chinese-rules} if you want to use
+Chinese (Area) counting.
+
+If the option @option{-o @var{outputfilename}} is provided, the result
+will also be written as a comment in the output file. For the "finish"
+and "aftermath" scoring algorithms, the selfplayed moves completing the
+game are also stored.
+
 @itemize
address@hidden last
address@hidden estimate
 @quotation
-load the sgf file up to the last move, then estimate territory
-using the Bouzy 5/21 algorithm (@pxref{Moyo}).
+Examine the status of all groups on the board, then give a quick
+estimate of the score using the Bouzy 5/21 algorithm (@pxref{Moyo}).
 @end quotation
address@hidden end
address@hidden finish
 @quotation
-finish the game by selfplaying from the end of the file until two passes,
-then estimate territory using the Bouzy 5/21 algorithm (@pxref{Moyo}).
+Finish the game by selfplaying until two passes, then determine the
+status of all stones and estimate territory using the Bouzy 5/21
+algorithm (@pxref{Moyo}).
 @end quotation
 @item aftermath
 @quotation
-finish the game by selfplaying from the end of the file until two passes,
-then estimate territory using the most accurate scoring algorithm available.
-Slower than @option{--score last}, and while these algorithms usually agree,
-if they differ, @option{--score aftermath} is most likely to be correct.
address@hidden quotation
address@hidden move, e.g. @option{--score J17}
address@hidden
-load file until move is reached and estimate territorial balance using
-the Bouzy 5/21 algorithm. The @option{--score end} and 
address@hidden aftermath} options are only useful at or near the
-end of the game, so if you want an estimate of the score in the
-middle, use this method.
+Finish the game by selfplaying until two passes, then accurately
+determine status of all stones by playing out the "aftermath", i.e.
+playing on until all stones except ones involved in seki have become
+either unconditionally (in the strongest sense) alive or unconditionally
+dead (or captured). Slower than @option{--score finish}, and while these
+algorithms usually agree, if they differ, @option{--score aftermath} is
+most likely to be correct.
 @end quotation
 @end itemize
 @end quotation
Index: interface/play_solo.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/interface/play_solo.c,v
retrieving revision 1.26
diff -u -r1.26 play_solo.c
--- interface/play_solo.c       1 May 2003 20:55:27 -0000       1.26
+++ interface/play_solo.c       4 Jun 2003 13:44:27 -0000
@@ -186,38 +186,59 @@
  *             get an accurate score
  */
 
+#define ESTIMATE  0
+#define FINISH    1
+#define AFTERMATH 2
+
 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;
+  int method;
+  SGFTree local_tree;
+  SGFTree *score_tree = tree;
   
-  sgftree_clear(&score_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.
+  /* 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.
    */
-  sgftreeCreateHeaderNode(&score_tree, board_size,
-                         komi + black_captured - white_captured);
-  sgffile_printboard(&score_tree);
-  sgfAddProperty(score_tree.lastnode, "PL",
-                gameinfo->to_move == WHITE ? "W" : "B");  
+  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);
+    sgffile_printboard(&local_tree);
+    sgfAddProperty(local_tree.lastnode, "PL",
+                  gameinfo->to_move == WHITE ? "W" : "B");
+    score_tree = &local_tree;
+  }
   
   next = gameinfo->to_move;
-  doing_scoring = 1;
   reset_engine();
   
-  if (!strcmp(scoringmode, "finish") || !strcmp(scoringmode, "aftermath")) {
-    do {
+  /* Complete the game by selfplay for the finish and aftermath methods. */
+  if (method != ESTIMATE) {
+    doing_scoring = 1;
+    while (pass < 2) {
       move_val = genmove_conservative(&i, &j, next);
       if (move_val >= 0) {
        pass = 0;
@@ -225,76 +246,83 @@
                next == WHITE ? "white (O)" : "black (X)", i, j);
       }
       else {
-       ++pass;
+       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);
+      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(&upper_bound, &lower_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;
   }
-  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().
+  
+  /* Calculate the score. */
+  if (method == AFTERMATH)
+    score = aftermath_compute_score(next, komi, score_tree);
+  else {
+    /* 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);
+    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);
 
-    fprintf(stdout, "\n%s seems to win by %1.1f points\n",
-      score < 0 ? "B" : "W",
-      score < 0 ? -score : score);
+  /* 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 or 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);
 }
 
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]