gnugo-devel
[Top][All Lists]
Advanced

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

[gnugo-devel] mixed patch


From: Gunnar Farneback
Subject: [gnugo-devel] mixed patch
Date: Thu, 11 Apr 2002 21:34:25 +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 mostly deals with aftermath scoring, but includes a few
other fixes as well.

- aftermath revisions
- combination of --score aftermath and -o options more useful
- dead function opponent_not_passing() removed from genmove.c
- init_influence() and new_value_territory() revised
- sgftree_printboard() made global
- bugfix in owl_hotspots()
- valuation of attack threats revised to allow more ko threats
- bugfix in estimate_strategical_value()
- solid string connection bonus revised to also favor cuts of opponent
- play_gtp() starts with boardsize of board loaded with -l instead of
  always 19 
- tuning
- owl tuning
- no warning by default for FF[1] sgf game records

The tuning and owl tuning are very conservative. The influence
revisions solve some scoring mistakes and may improve the endgame
slightly in general. The changed valuation of attack threats reenables
ko threats which are tactically unsafe if the opponent answers the
threat, which by mistake had been disabled.

The regression delta is relatively large but fairly balanced. I've
checked the failures and they are all acceptable.

/Gunnar

Index: engine/aftermath.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/aftermath.c,v
retrieving revision 1.25
diff -u -r1.25 aftermath.c
--- engine/aftermath.c  7 Apr 2002 19:29:03 -0000       1.25
+++ engine/aftermath.c  11 Apr 2002 19:08:21 -0000
@@ -27,6 +27,8 @@
 #include <string.h>
 #include "liberty.h"
 
+SGFTree *aftermath_sgftree;
+
 /* Generate a move to definitely settle the position after the game
  * has been finished. The purpose of this is to robustly determine
  * life and death status and to distinguish between life in seki and
@@ -76,6 +78,18 @@
  * the inner liberties, but one of them lets O live. Thus we have to
  * check carefully for blunders at this step.
  *
+ * Update: Step 0 is only safe against blunders if care is taken not
+ *         to get into a shortage of liberties.
+ *         Step 5 also has some risks. Consider this position:
+ *
+ *         |XXXXX.
+ *         |OOOOXX
+ *         |..O.OX
+ *         |OX*OOX
+ *         +------
+ *
+ *         Playing at * allows X to make seki.
+ *
  * IMPORTANT RESTRICTION:
  * Before calling this function it is mandatory to call genmove() or
  * genmove_conservative(). For this function to be meaningful, the
@@ -232,10 +246,13 @@
     
     for (k = 0; k < 4; k++) {
       int dir = delta[k];
+      int right = delta[(k+1)%4];
       if (!ON_BOARD(pos - dir)
          && board[pos + dir] == color
+         && board[pos + dir + right] == other
+         && board[pos + dir - right] == other
          && (libs > countlib(pos + dir)
-             || (libs >= 4
+             || (libs > 4
                  && libs == countlib(pos + dir)))
          && (DRAGON2(pos + dir).safety == INVINCIBLE
              || DRAGON2(pos + dir).safety == STRONGLY_ALIVE)) {
@@ -592,6 +609,7 @@
        score[move] = 0;
       else {
        *aftermath_move = move;
+       DEBUG(DEBUG_AFTERMATH, "Splitting eyespace at %1m\n", move);
        return 1;
       }
     }
@@ -602,11 +620,13 @@
    * dragons, carefully checking against mistakes.
    */
   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
-    int bb;
+    int move;
+    int target;
+    int cc = NO_MOVE;
     int self_atari_ok = 0;
     if (board[pos] != EMPTY || distance[pos] != -1)
       continue;
-    move = NO_MOVE;
+    target = NO_MOVE;
     for (k = 0; k < 4; k++) {
       int pos2 = pos + delta[k];
       if (!ON_BOARD(pos2))
@@ -616,18 +636,18 @@
          && (do_capture_dead_stones 
              || worm[pos2].unconditional_status != DEAD)
          && DRAGON2(pos2).safety != INESSENTIAL) {
-       move = pos2;
+       target = pos2;
        break;
       }
     }
-    if (move == NO_MOVE)
+    if (target == NO_MOVE)
       continue;
     
-    /* At this point, (m, n) is a move that potentially may capture
-     * a dead opponent string at (move).
+    /* At this point, (pos) is a move that potentially may capture
+     * a dead opponent string at (target).
      */
     
-    if (!trymove(pos, color, "aftermath-A", move, EMPTY, NO_MOVE))
+    if (!trymove(pos, color, "aftermath-A", target, EMPTY, NO_MOVE))
       continue;
     
     /* It is frequently necessary to sacrifice own stones in order
@@ -652,21 +672,19 @@
      * |.O.OX
      * +-----
      */
+
+    self_atari_ok = 1;
+    for (k = 0; k < 4; k++) {
+      if (board[pos + delta[k]] == color
+         && DRAGON2(pos + delta[k]).safety != INESSENTIAL) {
+       self_atari_ok = 0;
+       cc = pos + delta[k];
+       break;
+      }
+    }
     
-    if ((board[SOUTH(pos)] == color
-        && DRAGON2(SOUTH(pos)).safety != INESSENTIAL)
-       || (board[WEST(pos)] == color
-           && DRAGON2(WEST(pos)).safety != INESSENTIAL)
-       || (board[NORTH(pos)] == color
-           && DRAGON2(NORTH(pos)).safety != INESSENTIAL)
-       || (board[EAST(pos)] == color
-           && DRAGON2(EAST(pos)).safety != INESSENTIAL))
-      self_atari_ok = 0;
-    else
-      self_atari_ok = 1;
-    
-    /* Copy the potential move to (bb). */
-    bb = pos;
+    /* Copy the potential move to (move). */
+    move = pos;
     
     /* If the move is a self atari, but that isn't okay, try to
      * recursively find a backfilling move which later makes the
@@ -676,19 +694,19 @@
       while (countlib(pos) == 1) {
        int lib;
        findlib(pos, 1, &lib);
-       bb = lib;
-       if (!trymove(bb, color, "aftermath-B", move, EMPTY, NO_MOVE))
+       move = lib;
+       if (!trymove(move, color, "aftermath-B", target, EMPTY, NO_MOVE))
          break;
       }
       
       if (countlib(pos) == 1)
-       bb = NO_MOVE;
+       move = NO_MOVE;
     }
 
     while (stackp > 0)
       popgo();
     
-    if (bb == NO_MOVE)
+    if (move == NO_MOVE)
       continue;
       
     /* Make sure that the potential move really isn't a self
@@ -696,14 +714,27 @@
      * could happen (because the backfilling moves happened to
      * capture some stones).
      */
-    if (!self_atari_ok && is_self_atari(bb, color))
+    if (!self_atari_ok && is_self_atari(move, color))
       continue;
     
     /* Consult the owl code to determine whether the considered move
      * really is effective. Blunders should be detected here.
      */
-    if (owl_does_attack(bb, move) == WIN) {
-      *aftermath_move = bb;
+    if (owl_does_attack(move, target) == WIN) {
+      /* If we have an adjacent own dragon, which is not inessential,
+       * verify that it remains safe.
+       */
+      if (cc != NO_MOVE && !owl_does_defend(move, cc))
+       continue;
+
+      /* If we don't allow self atari, also call confirm safety to
+       * avoid setting up combination attacks.
+       */
+      if (!self_atari_ok && !confirm_safety(move, color, 0, NULL, NULL, NULL))
+       continue;
+         
+      *aftermath_move = move;
+      DEBUG(DEBUG_AFTERMATH, "Filling opponent liberty at %1m\n", move);
       return 1;
     }
   }
@@ -736,6 +767,8 @@
        && worm[pos].attack_codes[0] != 0
        && !is_illegal_ko_capture(worm[pos].attack_points[0], color)) {
       *aftermath_move = worm[pos].attack_points[0];
+      DEBUG(DEBUG_AFTERMATH, "Tactically attack %1m at %1m\n",
+           pos, *aftermath_move);
       return 1;
     }
   }
@@ -849,12 +882,19 @@
     int reading_nodes = get_reading_node_counter();
     int owl_nodes = get_owl_node_counter();
     int move_val = reduced_genmove(&move, color_to_play);
-    if (move_val < 0)
+    if (move_val < 0) {
+      int save_verbose = verbose;
+      if (verbose > 0)
+       verbose--;
       move_val = aftermath_genmove(&move, color_to_play,
                                   (color_to_play == WHITE ?
                                    a->white_control : a->black_control),
                                   0);
+      verbose = save_verbose;
+    }
     play_move(move, color_to_play);
+    if (aftermath_sgftree)
+      sgftreeAddPlay(aftermath_sgftree, NULL, color_to_play, I(move), J(move));
     moves++;
     DEBUG(DEBUG_AFTERMATH, "%d %C move %1m (nodes %d, %d  total %d, %d)\n",
          movenum, color_to_play, move, get_owl_node_counter() - owl_nodes,
@@ -962,9 +1002,10 @@
 }
 
 float
-aftermath_compute_score(int color, float komi)
+aftermath_compute_score(int color, float komi, SGFTree *tree)
 {
   struct aftermath_data *a = &aftermath;
+  aftermath_sgftree = tree;
   play_aftermath(color);
   if (chinese_rules)
     return (a->white_area
@@ -988,6 +1029,7 @@
 aftermath_final_status(int color, int pos)
 {
   ASSERT_ON_BOARD1(pos);
+  aftermath_sgftree = NULL;
   play_aftermath(color);
   return aftermath.final_status[pos];
 }
Index: engine/genmove.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/genmove.c,v
retrieving revision 1.36
diff -u -r1.36 genmove.c
--- engine/genmove.c    7 Apr 2002 15:27:35 -0000       1.36
+++ engine/genmove.c    11 Apr 2002 19:08:21 -0000
@@ -49,9 +49,7 @@
 static int dragons_examined_without_owl = -1;
 static int dragons_examined = -1;
 static int initial_influence2_examined = -1;
-#if 0
-static int opponent_not_passing(int color, int score);
-#endif
+
 static int revise_semeai(int color);
 static int revise_thrashing_dragon(int color, float advantage);
 
@@ -293,33 +291,6 @@
   return retval;
 }
 
-
-#if 0
-
-/* If we're way ahead, and opponent has not been passing when we
- * think there are not even dame left, let's start playing aftermath
- * moves, too.  This funtion returns 1 if we should play an aftermath
- * or capturing move.
- * See, disaster in games/nngs/gnugo-3.1.22-heeroy-200201252006.sgf
- * See also TurboGo in the 2001 European Congress (Dublin), where GNU
- *   Go took some really unnecessary risks in passing over & over.
- *   http://www.britgo.org/results/computer/egc01/tg-gg.sgf
- */
-static int
-opponent_not_passing(int color, int score)
-{
-  /* Feel free to pass if we're losing. */
-  if ((color == BLACK && score > 0)
-      || (color == WHITE && score < 0))
-    return 0;
-
-  /*FIXME: re-implement... My initial approach caused many
-   * failures in filllib.tst - tm */
-  return 0;
- /*(last_moves[0] != NO_MOVE*/
-}
-
-#endif
 
 /* 
  * Perform the actual move generation. 
Index: engine/gnugo.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/gnugo.h,v
retrieving revision 1.50
diff -u -r1.50 gnugo.h
--- engine/gnugo.h      7 Apr 2002 15:09:51 -0000       1.50
+++ engine/gnugo.h      11 Apr 2002 19:08:22 -0000
@@ -442,7 +442,7 @@
 int genmove_conservative(int *i, int *j, int color);
 
 /* Play through the aftermath. */
-float aftermath_compute_score(int color, float komi);
+float aftermath_compute_score(int color, float komi, SGFTree *tree);
 int aftermath_final_status(int color, int pos);
 
 /* Basic information gathering. */
Index: engine/influence.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/influence.c,v
retrieving revision 1.52
diff -u -r1.52 influence.c
--- engine/influence.c  7 Apr 2002 14:49:57 -0000       1.52
+++ engine/influence.c  11 Apr 2002 19:08:23 -0000
@@ -44,7 +44,8 @@
 static void print_influence_areas(struct influence_data *q);
  
 /* The following functions are used with experimental_influence is set. */
-static void new_value_territory(struct influence_data *q);
+static void new_value_territory(struct influence_data *q,
+                               int m, int n, int color);
 static void enter_intrusion_source(int source_pos, int strength_pos,
                                    float strength, float attenuation,
                                    struct influence_data *q);
@@ -410,6 +411,7 @@
                    || (dragons_known
                        && dragon[pos].id != -1
                        && (DRAGON2(pos).safety == DEAD
+                           || DRAGON2(pos).safety == TACTICALLY_DEAD
                            || (DRAGON2(pos).safety == CRITICAL
                                && board[pos] == OTHER_COLOR(color))))))) {
          if (q->p[i][j] == WHITE)
@@ -422,6 +424,7 @@
                 || !dragons_known
                 || dragon[pos].id == -1
                 || (DRAGON2(pos).safety != DEAD
+                    && DRAGON2(pos).safety != TACTICALLY_DEAD
                     && DRAGON2(pos).safety != CRITICAL)
                 || (DRAGON2(pos).safety == CRITICAL
                     && board[pos] == color)) {
@@ -445,6 +448,7 @@
            && (DRAGON2(pos).safety == INESSENTIAL
                || (worm[pos].inessential
                    && ((DRAGON2(pos).safety != DEAD
+                        && DRAGON2(pos).safety != TACTICALLY_DEAD
                         && DRAGON2(pos).safety != CRITICAL)
                        || (DRAGON2(pos).safety == CRITICAL
                            && board[pos] == color)))) 
@@ -1266,7 +1270,7 @@
   { 5, (float) 0.0, 1.0, {0.0, 0.25, 0.45, 0.65, 0.85, 1.0}};
 
 static void
-new_value_territory(struct influence_data *q)
+new_value_territory(struct influence_data *q, int m, int n, int color)
 {
   int i, j;
   int dist_i, dist_j;
@@ -1378,6 +1382,16 @@
          q->territory_value[i][j] -= 1.0;
       }
     }
+
+  /* Final correction. Never count the last played move as territory
+   * for the color playing it. Ideally this should never happen, but
+   * currently we need this workaround.
+   */
+  ASSERT2(color == EMPTY || ON_BOARD2(m, n), m, n);
+  if (color == BLACK && q->territory_value[m][n] < 0.0)
+    q->territory_value[m][n] = 0.0;
+  else if (color == WHITE && q->territory_value[m][n] > 0.0)
+    q->territory_value[m][n] = 0.0;
 }
 
 /* Give territorial value to each vertex.
@@ -1652,7 +1666,7 @@
                    dragons_known, NULL, NULL);
   if (dragons_known) {
     if (experimental_influence)
-      new_value_territory(&initial_influence);
+      new_value_territory(&initial_influence, -1, -1, EMPTY);
     else
       value_territory(&initial_influence);
     if ((printmoyo & PRINTMOYO_VALUE_TERRITORY)
@@ -1789,12 +1803,15 @@
       compute_followup_influence(m, n, color, saved_stones);
     decrease_depth_values();
     popgo();
+
     if (experimental_influence) {
-      new_value_territory(&move_influence);
-      new_value_territory(&followup_influence);
+      new_value_territory(&move_influence, m, n, color);
+      new_value_territory(&followup_influence, m, n, color);
     }
     else
       value_territory(&move_influence);
+
+
     if (m == debug_influence_i
        && n == debug_influence_j && m >= 0) {
       if (printmoyo & PRINTMOYO_VALUE_TERRITORY)
Index: engine/liberty.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/liberty.h,v
retrieving revision 1.94
diff -u -r1.94 liberty.h
--- engine/liberty.h    30 Mar 2002 20:29:22 -0000      1.94
+++ engine/liberty.h    11 Apr 2002 19:08:24 -0000
@@ -568,6 +568,7 @@
 int sgffile_write_line(const char *line, ...);
 void sgffile_dragon_status(int i, int j, int status);
 void goaldump(char goal[BOARDMAX]);
+void sgftree_printboard(struct SGFTree_t *tree);
 void begin_sgftreedump(struct SGFTree_t *tree);
 void end_sgftreedump(const char *filename);
 
Index: engine/owl.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/owl.c,v
retrieving revision 1.80
diff -u -r1.80 owl.c
--- engine/owl.c        7 Apr 2002 16:57:16 -0000       1.80
+++ engine/owl.c        11 Apr 2002 19:08:28 -0000
@@ -801,7 +801,8 @@
            if (countlib(origin) < 3 && attack(origin, &upos)) {
              *resulta = ALIVE;
              *resultb = DEAD;
-             if (move) *move = upos;
+             if (move)
+               *move = upos;
              sgf_dumptree = save_sgf_dumptree;
              count_variations = save_count_variations;
              SGFTRACE2(upos, ALIVE, "tactical win found");
@@ -4978,6 +4979,7 @@
       break;
     case OWL_DOES_DEFEND:
     case OWL_DOES_ATTACK:
+    case OWL_CONFIRM_SAFETY:
       mark_dragon_hotspot_values(values, entry->bpos,
                                 contribution, entry->board);
       break;
Index: engine/sgffile.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/sgffile.c,v
retrieving revision 1.15
diff -u -r1.15 sgffile.c
--- engine/sgffile.c    31 Mar 2002 20:46:47 -0000      1.15
+++ engine/sgffile.c    11 Apr 2002 19:08:28 -0000
@@ -367,8 +367,6 @@
  * ================================================================ */
 
 
-static void sgftree_printboard(SGFTree *tree);
-
 /*
  * begin_sgftreedump begins storing all moves considered by
  * trymove and tryko in an sgf tree in memory.
@@ -413,7 +411,7 @@
  * sgftree_printboard adds the current board position to the tree.
  */
 
-static void
+void
 sgftree_printboard(SGFTree *tree)
 {
   int i, j;
Index: engine/value_moves.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/value_moves.c,v
retrieving revision 1.26
diff -u -r1.26 value_moves.c
--- engine/value_moves.c        7 Apr 2002 14:48:33 -0000       1.26
+++ engine/value_moves.c        11 Apr 2002 19:08:31 -0000
@@ -28,7 +28,6 @@
 
 #include "liberty.h"
 #include "gg_utils.h"
-#include "random.h"
 #include "move_reasons.h"
 
 
@@ -1311,7 +1310,8 @@
        * of each type.
        *
        * No followup value is awarded if the defense move is a threat
-       * back on our move because we're likely to end in gote then.
+       * back on our move because we're likely to end in gote then,
+       * unless the move is unsafe anyway and played as a ko threat.
        *
        * FIXME: It might be possible that parts of the dragon
        *        can be cut in the process of capturing the (aa)
@@ -1347,12 +1347,15 @@
          num_adj = chainlinks(aa, adjs);
 
        /* No followup value if string can be defended with threat
-         * against our move.
+         * against our move. An exception to this is when our move
+         * isn't safe anyway and we play this only for the followup
+         * value, typically as a ko threat.
         *
         * FIXME: This is somewhat halfhearted since only one defense
         * move is tested.
         */
        if (board[aa] != EMPTY
+           && move[pos].move_safety == 1
            && find_defense(aa, &defense_move) == WIN
            && defense_move != NO_MOVE) {
          if (trymove(defense_move, other,
@@ -1366,7 +1369,7 @@
            popgo();
          }
        }
-       
+
        for (s = 0; s < num_adj; s++) {
          int adj = adjs[s];
 
@@ -1381,6 +1384,22 @@
              && 2*worm[adj].effective_size > adjustment_down)
            adjustment_down = 2*worm[adj].effective_size;
        }
+
+       popgo();
+
+       /* No followup if the string is not substantial. */
+       {
+         int save_verbose = verbose;
+         if (verbose > 0)
+           verbose --;
+         if (move[pos].move_safety == 0
+             && !owl_substantial(aa)) {
+           verbose = save_verbose;
+           break;
+         }
+         verbose = save_verbose;
+       }
+       
        adjusted_value += adjustment_up;
        adjusted_value -= adjustment_down;
        if (adjusted_value > 0.0) {
@@ -1389,7 +1408,6 @@
          TRACE("%1m:   %f (followup) - threatens to capture %1m\n",
                pos, adjusted_value, aa);
        }
-       popgo();
       }
       break;
 
@@ -1704,7 +1722,12 @@
   /* Strategical value of connecting or cutting dragons. */
   static float dragon_value[MAX_DRAGONS];
 
-  for (k = 0; k < next_dragon; k++)
+  /* This loop used to be up to next_dragon, but that is not safe
+   * because while doing the computations below, next_dragon might
+   * increase (through calls to find_dragon()). Thus we could then
+   * reference improperly initialized memory.
+   */
+  for (k = 0; k < MAX_DRAGONS; k++)
     dragon_value[k] = 0.0;
   
   for (k = 0; k < MAX_REASONS; k++) {
@@ -2276,8 +2299,11 @@
       }
     }
 
-    /* Add a special shape bonus for moves which connect strings. */
-    c = move_connects_strings(pos, color);
+    /* Add a special shape bonus for moves which connect own strings
+     * or cut opponent strings.
+     */
+    c = (move_connects_strings(pos, color)
+        + move_connects_strings(pos, OTHER_COLOR(color)));
     if (c > 0) {
       float shape_factor2 = pow(1.02, (float) c) - 1;
       float base_value = gg_max(gg_min(tot_value, 5.0), 1.0);
Index: interface/play_gtp.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/interface/play_gtp.c,v
retrieving revision 1.70
diff -u -r1.70 play_gtp.c
--- interface/play_gtp.c        7 Apr 2002 17:00:31 -0000       1.70
+++ interface/play_gtp.c        11 Apr 2002 19:08:33 -0000
@@ -248,8 +248,7 @@
 #endif
 
   /* Inform the GTP utility functions about the board size. */
-  board_size = 19;
-  gtp_internal_set_boardsize(19);
+  gtp_internal_set_boardsize(board_size);
   gtp_orientation = gtp_initial_orientation;
   gtp_set_vertex_transform_hooks(rotate_on_input, rotate_on_output);
   
@@ -1336,7 +1335,7 @@
   silent_examine_position(BOARD(i, j), EXAMINE_DRAGONS_WITHOUT_OWL);
   /* to get the variations into the sgf file, clear the reading cache */
   if (sgf_dumptree)
-      reading_cache_clear();
+    reading_cache_clear();
 
   owl_analyze_semeai(dragona, dragonb, &resulta, &resultb, &move, 0);
   gtp_printid(id, GTP_SUCCESS);
@@ -1900,7 +1899,7 @@
     next = OTHER_COLOR(next);
   } while (pass < 2 && moves < board_size * board_size);
 
-  final_score = aftermath_compute_score(next, komi);
+  final_score = aftermath_compute_score(next, komi, NULL);
   for (i = 0; i < board_size; i++)
     for (j = 0; j < board_size; j++) {
       final_status[i][j] = aftermath_final_status(next, POS(i, j));
Index: interface/play_solo.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/interface/play_solo.c,v
retrieving revision 1.11
diff -u -r1.11 play_solo.c
--- interface/play_solo.c       7 Mar 2002 05:35:28 -0000       1.11
+++ interface/play_solo.c       11 Apr 2002 19:08:33 -0000
@@ -152,11 +152,11 @@
     genmove(&i, &j, next);
     
     if (is_pass(POS(i, j))) {
-      gprintf("%s move: PASS!\n", next == WHITE ? "white (o)" : "black (X)");
+      gprintf("%s move: PASS!\n", next == WHITE ? "white (O)" : "black (X)");
       sgffile_move_made(i, j, next, 0);
     }
     else {
-      gprintf("%s move %m\n", next == WHITE ? "white (o)" : "black (X)",
+      gprintf("%s move %m\n", next == WHITE ? "white (O)" : "black (X)",
              i, j);
       gnugo_play_move(i, j, next);
       sgffile_move_made(i, j, next, 0);
@@ -178,7 +178,7 @@
 load_and_score_sgf_file(SGFTree *tree, Gameinfo *gameinfo, 
                        const char *scoringmode)
 {
-  int i, j, move_val, pass;
+  int i, j, move_val;
   int until;
   float result;
   char *tempc = NULL;
@@ -186,11 +186,18 @@
   char text[250];
   char winner;
   int next;
-  pass = 0;
-
-  assert(tree);
+  int pass = 0;
+  SGFTree score_tree;
+  SGFNode *node;
+  
+  sgftree_clear(&score_tree);
+  node = sgftreeCreateHeaderNode(&score_tree, board_size, komi);
+  sgftreeSetLastNode(&score_tree, node);
+  sgftree_printboard(&score_tree);
+  
   sgffile_write_gameinfo(gameinfo, "load and score");
   next = gameinfo->to_move;
+  sgffile_printboard(next);
   doing_scoring = 1;
   
   if (!strcmp(scoringmode, "finish") || !strcmp(scoringmode, "aftermath")) {
@@ -200,23 +207,24 @@
       if (move_val >= 0) {
        pass = 0;
        gprintf("%d %s move %m\n", movenum,
-               next == WHITE ? "white (o)" : "black (X)", i, j);
+               next == WHITE ? "white (O)" : "black (X)", i, j);
       }
       else {
        ++pass;
        gprintf("%d %s move : PASS!\n", movenum, 
-               next == WHITE ? "white (o)" : "black (X)");
+               next == WHITE ? "white (O)" : "black (X)");
       }
       play_move(POS(i, j), next);
       sgffile_move_made(i, j, next, move_val);
-      sgftreeAddPlay(tree, 0, next, i, j);
+      sgftreeAddPlay(&score_tree, NULL, next, i, j);
       next = OTHER_COLOR(next);
     } while (movenum <= until && pass < 2);
 
     if (pass >= 2) {
+      node = score_tree.lastnode;
       /* Calculate the score */
       if (!strcmp(scoringmode, "aftermath"))
-       score = aftermath_compute_score(next, komi);
+       score = aftermath_compute_score(next, komi, &score_tree);
       else
        score = gnugo_estimate_score(&lower_bound, &upper_bound);
 
@@ -233,7 +241,7 @@
        winner = '0';
       }
       fputs(text, stdout);
-      sgfAddComment(tree->lastnode, text);
+      sgfAddComment(node, text);
       sgffile_write_comment(text);
       if (sgfGetCharProperty(tree->root, "RE", &tempc)) {
        if (sscanf(tempc, "%1c%f", &dummy, &result) == 2) {
@@ -256,13 +264,16 @@
          }
        }
       }
-      sgfWriteResult(tree->root, score, 1);
+      sgfWriteResult(score_tree.root, score, 1);
     }
   }
   doing_scoring = 0;
 
-  if (!strcmp(scoringmode, "aftermath"))
+
+  if (!strcmp(scoringmode, "aftermath")) {
+    writesgf(score_tree.root, gameinfo->outfilename);
     return;
+  }
 
   /* Before we call estimate_score() we must make sure that the dragon
    * status is computed. Therefore the call to examine_position().
Index: patterns/owl_defendpats.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/owl_defendpats.db,v
retrieving revision 1.59
diff -u -r1.59 owl_defendpats.db
--- patterns/owl_defendpats.db  7 Apr 2002 13:22:04 -0000       1.59
+++ patterns/owl_defendpats.db  11 Apr 2002 19:08:35 -0000
@@ -3765,6 +3765,7 @@
 
 Pattern D1006b
 # gf New pattern. (3.1.14)
+# gf Revised constraint. (3.1.32)
 
 OXO            connect underneath
 .*.
@@ -3776,7 +3777,7 @@
 .*.
 ---
 
-;owl_escape_value(a)>0 || owl_escape_value(b)>0
+;(owl_escape_value(a)>0 || owl_escape_value(b)>0) && lib(a)>1 && lib(b)>1
 
 
 Pattern D1007
@@ -5503,6 +5504,7 @@
 
 
 Pattern D1345
+# gf Revised constraint. (3.1.32)
 
 OXO        atari to connect
 .*.
@@ -5512,7 +5514,8 @@
 cDe
 a*b
 
-;lib(D)==2 && (owl_escape_value(c)>0 || owl_escape_value(e)>0)
+;lib(D)==2 && lib(c)>1 && lib(e)>1
+;&& (owl_escape_value(c)>0 || owl_escape_value(e)>0)
 ;&& oplay_attack(*,?,a,b,b)
 
 
Index: patterns/patterns.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/patterns.db,v
retrieving revision 1.68
diff -u -r1.68 patterns.db
--- patterns/patterns.db        7 Apr 2002 13:22:04 -0000       1.68
+++ patterns/patterns.db        11 Apr 2002 19:08:39 -0000
@@ -11121,15 +11121,35 @@
 ; xplay_attack(a,b,c,c) && !oplay_attack(*,a,b,c,c)
 
 
-Pattern CD104
+Pattern CD104a
 # gf Revised constraint.
+# gf Split pattern. We can't have eE classification unless b is alive. (3.1.32)
 
 ...          atari using dead stone
 .*.
 OX.
 XO?
 
-:8,deE,shape(3)
+:8,deE
+
+...
+.*.
+bX.
+XA?
+
+;lib(b)>1 && alive(b) && attack(A) && !defend(A)
+
+
+Pattern CD104b
+# gf Revised constraint.
+# gf Split pattern. We can't have eE classification unless b is alive. (3.1.32)
+
+...          atari using dead stone
+.*.
+OX.
+XO?
+
+:8,d,shape(3)
 
 ...
 .*.
Index: patterns/patterns2.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/patterns2.db,v
retrieving revision 1.34
diff -u -r1.34 patterns2.db
--- patterns/patterns2.db       28 Mar 2002 00:48:31 -0000      1.34
+++ patterns/patterns2.db       11 Apr 2002 19:08:40 -0000
@@ -2533,6 +2533,24 @@
 :8,X,shape(1)
 
 
+Pattern Shape82
+# gf New pattern. (3.1.32) (see trevorb:280)
+
+|XXO        Prefer this as ko threat since it gives a second one
+|.*X
+|.X?
+|.??
+
+:8,Xs,shape(2)
+
+|AAO
+|.*X
+|.X?
+|b??
+
+;!weak(A) && lib(A)==2 && xterri(b)
+
+
 ###########################
 #
 # Followup moves. 
Index: regression/owl.tst
===================================================================
RCS file: /cvsroot/gnugo/gnugo/regression/owl.tst,v
retrieving revision 1.45
diff -u -r1.45 owl.tst
--- regression/owl.tst  18 Mar 2002 03:55:01 -0000      1.45
+++ regression/owl.tst  11 Apr 2002 19:08:40 -0000
@@ -927,7 +927,10 @@
 257 owl_attack J3
 #? [0]*
 
-
+# This is quite trivial, but at least GNU Go 3.1.31 fails it.
+loadsgf games/handtalk11.sgf 157
+258 owl_defend O2
+#? [0]*
 
 ########### end of tests #####################
 
Index: sgf/sgfnode.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/sgf/sgfnode.c,v
retrieving revision 1.13
diff -u -r1.13 sgfnode.c
--- sgf/sgfnode.c       4 Mar 2002 06:49:09 -0000       1.13
+++ sgf/sgfnode.c       11 Apr 2002 19:08:42 -0000
@@ -981,7 +981,7 @@
     if (VERBOSE_WARNINGS)
       fprintf(stderr, "Can not determine SGF spec version (FF)!\n");
   }
-  else if (tmpi < 3 || tmpi > 4)
+  else if ((tmpi < 3 || tmpi > 4) && VERBOSE_WARNINGS)
     fprintf(stderr, "Unsupported SGF spec version: %d\n", tmpi);
 
   return root;
@@ -1035,7 +1035,7 @@
     if (VERBOSE_WARNINGS)
       fprintf(stderr, "Can not determine SGF spec version (FF)!\n");
   }
-  else if (tmpi < 3 || tmpi > 4)
+  else if ((tmpi < 3 || tmpi > 4) && VERBOSE_WARNINGS)
     fprintf(stderr, "Unsupported SGF spec version: %d\n", tmpi);
 
   return root;



reply via email to

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