gnugo-devel
[Top][All Lists]
Advanced

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

[gnugo-devel] semeai patch


From: Gunnar Farneback
Subject: [gnugo-devel] semeai patch
Date: Fri, 28 Nov 2003 17:22:04 +0100
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 improves the semeai code to better handle the case where
one small dragon, possibly a single string, is enclosed within a
bigger dragon. It also introduces a new function
find_moves_to_make_seki(), which tries to turn the potential territory
of an already alive group into seki. The latter is done by identifying
tactically critical strings enclosed inside a dragon which is not
obviously alive anyway, then calling owl_analyze_semeai_after_move()
to determine whether the tactically defending move suffices to get a
seki. Naturally this does not cover all cases where seki can be
achieved so there's room for further improvements.

In many of the standard corner positions which can be turned into
seki, one or both players have the option to instead choose a ko for
life and death of both. Exactly who benefits from this depends on a
number of factors like ko threat situation and overall score. A
reasonable general rule is however that if one player only risks a few
points in the ko while the other stands to lose much more, the first
player would be happy with the ko. This patch introduces that
assumption in the semeai code.

Additionally it makes some minor tweaks, a bit of tuning, and fixes a
troublesome off-by-one error.

- if one dragon is considerably smaller than the other in a semeai,
  prefer to get ko over seki
- in a semeai, consider also the eyespaces including opponent semeai
  worms in order to detect a definite lack of eyespace and to find
  certain vital moves
- off-by-one error in loops over semeai_worms[] corrected
- don't allow "safe" common liberties to depend on ko
- new static function find_moves_to_make_seki() in semeai.c
- do semeai analysis for all pairs of critical/dead dragons except
  when one is inessential, other exceptional cases removed
- owl tuning
- tuning
- revised test cases

Regression results, relative to (almost) current CVS:

blunder:26      FAIL D19 [!D19|F17]
nicklas3:401    PASS A5 [A5]
trevorc:1000    PASS N9 [N9|M11]
strategy3:135   PASS M13 [M12|N13|M13]
strategy3:141   FAIL J3 [C7]
semeai:51       PASS 1 0 A19 [1 0 (A19|E11)]
semeai:61       PASS 1 0 A15 [1 0 A15]
semeai:62       PASS 1 1 A17 [1 1 A17]
semeai:65       PASS 0 0 PASS [0 0 PASS]   
semeai:66       PASS 1 1 PASS [1 1 (PASS|N13)]
semeai:68       PASS 1 1 A5 [1 1 (PASS|A5|B5|C3|D3)]
strategy4:155   PASS D18 [D18]
strategy4:162   PASS O7 [O7|Q7|N7]
strategy4:192   FAIL K3 [A15]
nngs3:700       FAIL P7 [Q2]
strategy5:282   PASS O13 [O13]
ninestones:660  PASS P1 [P1]
tactics1:106    FAIL B8 [F8|F6]
gunnar:42       PASS B19 [B19]
gifu03:2        PASS R1 [R1]
gifu03:302      FAIL N17 [C1|B6]
seki:103        PASS B1 [B1]
seki:105        PASS C1 [C1]
seki:110        PASS B1 [B1]
seki:111        PASS C2 [C2]
seki:203        PASS A2 [A2|B1]
seki:205        PASS C1 [C1|C2]
seki:301        PASS B2 [B2]
seki:302        PASS B2 [B2]
seki:305        PASS C2 [C2]
seki:407        PASS C2 [C2|E1]
seki:412        PASS D1 [D1]
seki:503        PASS C1 [C1]
seki:801        PASS B2 [B2]
seki:802        PASS B2 [B2]
seki:803        PASS C2 [C2]
seki:805        PASS A2 [A2]
seki:808        PASS C2 [C2]
seki:810        PASS A3 [A3]
seki:901        PASS B2 [B2]
seki:902        PASS B2 [B2]
seki:903        PASS C1 [C2|C1]
seki:904        PASS B3 [B3]
seki:910        PASS A1 [A1|A2]
seki:912        PASS C1 [C1]

Comments on the failures:

blunder:26
Possibly a real failure, needs further investigation.

strategy3:141
Semeai reading mistake. The patch only causes the reading to be done,
which is reasonable.

strategy4:192
Not a real failure. The status of the upper left corner is now
correctly understood and valued about right. Is A15 really the biggest
move on the board, by the way?

nngs3:700
Valuation problem. The semeai understanding has improved.

tactics1:106
Same kind of problem as strategy3:141.

gifu03:302
Semeai reading mistake.

/Gunnar

Index: engine/owl.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/owl.c,v
retrieving revision 1.183
diff -u -r1.183 owl.c
--- engine/owl.c        13 Nov 2003 22:48:41 -0000      1.183
+++ engine/owl.c        28 Nov 2003 10:22:10 -0000
@@ -288,6 +288,21 @@
 static int semeai_worms[MAX_SEMEAI_WORMS];
 static int important_semeai_worms[MAX_SEMEAI_WORMS];
 
+/* Whether one color prefers to get a ko over a seki. */
+static int prefer_ko;
+
+/* Usually it's a bad idea to include the opponent worms involved in
+ * the semeai in the eyespace. For some purposes (determining a
+ * definite lack of eyespace, finding certain vital moves), however,
+ * we want to do that anyway. Then set this variable to 1 before
+ * calling owl_estimate_life() and reset it afterwards.
+ *
+ * FIXME: We should implement a nicer mechanism to propagate this
+ *        information to owl_lively(), where it's used.
+ */
+static int include_semeai_worms_in_eyespace = 0;
+
+
 /* Called when (apos) and (bpos) point to adjacent dragons
  * of the opposite color, both with matcher_status DEAD or
  * CRITICAL, analyzes the semeai, assuming that the player
@@ -397,6 +412,25 @@
 
   result_certain = 1;
 
+  /* In some semeai situations one or both players have the option to
+   * choose between seki and ko for the life and death of both. In
+   * general this choice depends on the ko threat situation, the
+   * overall score, and the strategical effects on surrounding
+   * dragons, but we don't try to correctly estimate this. Instead we
+   * make the reasonable assumption that if one dragon is
+   * substantially smaller than the other dragon, ko is to be
+   * preferred for the smaller dragon and seki for the larger dragon.
+   *
+   * prefer_ko can be either WHITE, BLACK, or EMPTY and tells which
+   * color, if any, prefers to get ko.
+   */
+  if (dragon[apos].size <= 5 && dragon[bpos].size > 3 * dragon[apos].size)
+    prefer_ko = board[apos];
+  else if (dragon[bpos].size <= 5 && dragon[apos].size > 3 * dragon[bpos].size)
+    prefer_ko = board[bpos];
+  else
+    prefer_ko = EMPTY;
+  
   if (move == PASS_MOVE)
     do_owl_analyze_semeai(apos, bpos, owla, owlb, EMPTY, NO_MOVE,
                          resulta, resultb, semeai_move, 0, owl);
@@ -537,7 +571,7 @@
     int upos;
     int sworm;
 
-    for (sworm = 0; sworm <= s_worms; sworm++) {
+    for (sworm = 0; sworm < s_worms; sworm++) {
       critical_semeai_worms[sworm] = 0;
       if (board[semeai_worms[sworm]] == other) {
        int acode = attack(semeai_worms[sworm], &upos);
@@ -565,7 +599,7 @@
      * threatened, try to save it.
      */
 
-    for (sworm = 0; sworm <= s_worms; sworm++)
+    for (sworm = 0; sworm < s_worms; sworm++)
       if (board[semeai_worms[sworm]] == color
          && attack(semeai_worms[sworm], NULL)
          && find_defense(semeai_worms[sworm], &upos)) {
@@ -712,6 +746,23 @@
                              critical_semeai_worms);
     }
 
+    /* If no moves were found so far, also check the eyespaces when
+     * opponent semeai worms are allowed to be included for vital
+     * moves.
+     */
+    if (moves[0].pos == NO_MOVE) {
+      include_semeai_worms_in_eyespace = 1;
+      if (!owl_estimate_life(owlb, owla, vital_offensive_moves,
+                            &live_reasonb, komaster, 1, &probable_eyes_b,
+                            &eyemin_b, &eyemax_b))
+       semeai_review_owl_moves(vital_offensive_moves, owla, owlb, color,
+                               &safe_outside_liberty_found,
+                               &safe_common_liberty_found,
+                               mw, moves, 1, 30,
+                               critical_semeai_worms);
+      include_semeai_worms_in_eyespace = 0;
+    }
+
     if (level < 8) {
       /* If no owl moves were found on two consecutive moves,
        * turn off the owl phase.
@@ -758,7 +809,7 @@
          }
          else {
            /* common liberty */
-           if (safe_move(pos, color)) {
+           if (safe_move(pos, color) == WIN) {
              safe_common_liberty_found = 1;
              common_liberty.pos = pos;
            }
@@ -866,16 +917,19 @@
        close_pattern_list(color, &shape_offensive_patterns);
        READ_RETURN_SEMEAI(read_result, move, mpos, WIN, WIN);
       }
-      /* We consider our own safety most important and attacking the
-       * opponent as a secondary aim. This means that we prefer seki
-       * over a ko for life and death.
-       *
-       * FIXME: If our dragon is considerably smaller than the
-       * opponent dragon, we should probably prefer ko over seki.
+      /* When there is a choice between ko and seki, the prefer_ko
+       * variable decides policy. Thus if prefer_ko == color we
+       * consider attacking the opponent more important than defending
+       * our dragon, and vise versa otherwise.
        */
-      else if (this_resulta > best_resulta
-              || (this_resulta == best_resulta
-                  && this_resultb > best_resultb)) {
+      else if ((prefer_ko != color
+               && (this_resulta > best_resulta
+                   || (this_resulta == best_resulta
+                       && this_resultb > best_resultb)))
+              || (prefer_ko == color
+                  && (this_resultb > best_resultb
+                      || (this_resultb == best_resultb
+                          && this_resulta > best_resulta)))) {
        best_resulta = this_resulta;
        best_resultb = this_resultb;
        best_move = mpos;
@@ -898,6 +952,38 @@
     READ_RETURN_SEMEAI(read_result, move, PASS_MOVE, 0, 0);
   }
 
+  /* If we can't find a move and we look dead even if including the
+   * opponent stones in our eyespace, we have lost.
+   */
+  if (tested_moves == 0) {
+    const char *live_reasona;
+    struct eyevalue probable_eyes_a;
+    int eyemin_a;
+    int eyemax_a;
+    int sworm;
+    for (sworm = 0; sworm < s_worms; sworm++) {
+      if (board[semeai_worms[sworm]] == other) {
+       if (important_semeai_worms[sworm])
+         break;
+      }
+    }
+    
+    if (sworm == s_worms) {
+      include_semeai_worms_in_eyespace = 1;
+      if (!owl_estimate_life(owla, owlb, vital_defensive_moves,
+                            &live_reasona, komaster, 0, &probable_eyes_a,
+                            &eyemin_a, &eyemax_a)) {
+       include_semeai_worms_in_eyespace = 0;
+       *resulta = 0;
+       *resultb = 0;
+       *move = PASS_MOVE;
+       SGFTRACE_SEMEAI(PASS_MOVE, 0, 0, "You live, I die - 2");
+       READ_RETURN_SEMEAI(read_result, move, PASS_MOVE, 0, 0);
+      }
+      include_semeai_worms_in_eyespace = 0;
+    }
+  }
+
   /* If we can't find a move and opponent passed, it's seki */
   if (tested_moves == 0 && pass == 1) {
     *resulta = WIN;
@@ -1174,7 +1260,7 @@
     }
 
     increase_depth_values();
-    for (k = 0; k <= s_worms; k++) {
+    for (k = 0; k < s_worms; k++) {
       if (!critical_semeai_worms[k])
        continue;
       if (board[semeai_worms[k]] == color
@@ -2500,6 +2586,7 @@
   memset(found_matches, 0, sizeof(found_matches));
 
   if (level >= 8) {
+    memset(owl->safe_move_cache, 0, sizeof(owl->safe_move_cache));
     if (!does_attack) {
       clear_owl_move_data(dummy_moves);
       matchpat(owl_shapes_callback, other,
@@ -4895,6 +4982,10 @@
    * other dragon and can't be saved is not lively.
    */
   if (other_owl_data) {
+
+    if (include_semeai_worms_in_eyespace && other_owl_data->goal[pos])
+      return 0;
+    
     if (other_owl_data->goal[pos] && !semeai_trust_tactical_attack(pos))
       return 1;
     /* FIXME: Shouldn't we check other_owl_data->inessential[origin] here? */
Index: engine/semeai.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/semeai.c,v
retrieving revision 1.64
diff -u -r1.64 semeai.c
--- engine/semeai.c     19 Nov 2003 07:53:49 -0000      1.64
+++ engine/semeai.c     28 Nov 2003 10:22:10 -0000
@@ -29,6 +29,7 @@
 
 #define INFINITY 1000
 
+static void find_moves_to_make_seki(void);
 static void update_status(int dr, enum dragon_status new_status, 
                          enum dragon_status new_safety);
 
@@ -83,25 +84,8 @@
          || (dragon[bpos].status != DEAD
              && dragon[bpos].status != CRITICAL))
        continue;
+
       
-      /* A dragon consisting of a single worm which is tactically dead or
-       * critical and having just one neighbor should be ignored, since
-       * the owl code is more reliable than the semeai code in such cases.
-       * We do allow these cases if the worm has 4 liberties and can be
-       * defended.
-       */
-      
-      if (dragon[apos].size == worm[apos].size
-         && worm[apos].attack_codes[0]
-         && (worm[apos].liberties < 4
-             || worm[apos].defense_codes[0] == 0))
-       continue;
-      
-      if (dragon[bpos].size == worm[bpos].size
-         && worm[bpos].attack_codes[0]
-         && (worm[bpos].liberties < 4
-             || worm[bpos].defense_codes[0] == 0))
-       continue;
       /* Ignore inessential worms or dragons */
       
       if (worm[apos].inessential 
@@ -110,10 +94,6 @@
          || DRAGON2(bpos).safety == INESSENTIAL)
        continue;
 
-      /* If either dragon is a single stone, this is best left
-       * to the owl code */
-      if (dragon[apos].size == 1 || dragon[bpos].size == 1)
-       continue;
 
       /* The array semeai_results_first[d1][d2] will contain the status
        * of d1 after the d1 d2 semeai, giving d1 the first move.
@@ -225,6 +205,80 @@
       }
       else if (best_attack == 0 && attack_certain)
        update_status(DRAGON(d1).origin, ALIVE, ALIVE);
+    }
+  }
+  find_moves_to_make_seki();
+}
+
+/* Find moves turning supposed territory into seki. This is not
+ * detected above since it either involves an ALIVE dragon adjacent to
+ * a CRITICAL dragon, or an ALIVE dragon whose eyespace can be invaded
+ * and turned into a seki.
+ *
+ * Currently we only search for tactically critical strings with
+ * dragon status dead, which are neighbors of only one opponent
+ * dragon, which is alive. Through semeai analysis we then determine
+ * whether such a string can in fact live in seki. Relevant testcases
+ * include gunnar:42 and gifu03:2.
+ */
+static void
+find_moves_to_make_seki()
+{
+  int str;
+  int defend_move;
+  int resulta, resultb;
+  
+  for (str = BOARDMIN; str < BOARDMAX; str++) {
+    if (IS_STONE(board[str]) && is_worm_origin(str, str)
+       && attack_and_defend(str, NULL, NULL, NULL, &defend_move)
+       && dragon[str].status == DEAD
+       && DRAGON2(str).hostile_neighbors == 1) {
+      int k;
+      int color = board[str];
+      int opponent;
+      int certain;
+      
+      for (k = 0; k < DRAGON2(str).neighbors; k++) {
+       opponent = dragon2[DRAGON2(str).adjacent[k]].origin;
+       if (board[opponent] != color)
+         break;
+      }
+
+      if (dragon[opponent].status != ALIVE)
+       continue;
+      
+      /* FIXME: These heuristics are not very precise. What we really
+       * want to check is whether str is inside the eyespace of the
+       * opponent, for an interpretation of eyespace that includes
+       * lunches, while it doesn't already have more than one eye
+       * elsewhere.
+       */
+      if (DRAGON2(opponent).moyo_size > 10
+         || min_eyes(&DRAGON2(opponent).genus) > 1)
+       continue;
+
+      owl_analyze_semeai_after_move(defend_move, color, opponent, str,
+                                   &resulta, &resultb, NULL, 1, &certain);
+
+      /* Do not trust uncertain results. In fact it should only take a
+       * few nodes to determine the semeai result, if it is a proper
+       * potential seki position.
+       */
+      if (resultb != WIN && certain) {
+       int d = dragon[str].id;
+       DEBUG(DEBUG_SEMEAI, "Move to make seki at %1m (%1m vs %1m)\n",
+             defend_move, str, opponent);
+       dragon2[d].semeai = 1;
+       update_status(str, CRITICAL, CRITICAL);
+       dragon2[d].semeai_defense_point = defend_move;
+       dragon2[d].semeai_defense_certain = certain;
+       /* FIXME: The assumption that the attack move coincides with
+         * the defense move is somewhat optimistic.
+        */
+       dragon2[d].semeai_attack_point = defend_move;
+       dragon2[d].semeai_attack_certain = certain;
+       dragon2[d].semeai_target = opponent;
+      }
     }
   }
 }
Index: patterns/owl_attackpats.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/owl_attackpats.db,v
retrieving revision 1.99
diff -u -r1.99 owl_attackpats.db
--- patterns/owl_attackpats.db  19 Nov 2003 07:53:49 -0000      1.99
+++ patterns/owl_attackpats.db  28 Nov 2003 10:22:11 -0000
@@ -1913,6 +1913,24 @@
 :8,s,value(45)
 
 
+Pattern A503b
+# gf New pattern. (3.5.3)
+
+?XXX        atari to eliminate eye or make ko
+Y.O.
+X.X*
+----
+
+:8,s,value(32)
+
+?XXX
+Y.O.
+X.X*
+----
+
+;olib(*)>1
+
+
 Pattern A504
 
 Y*           cut off one stone
@@ -3127,15 +3145,46 @@
 :8,s,value(36)
 
 
-# Pattern A906
-# # gf We don't need two copies of this pattern. Removed one. (3.1.14)
-# 
-# |O.X        try to form nakade
-# |XOX
-# |*..
-# +---
-# 
-# :8,s,value(35)
+Pattern A906a
+# gf New pattern. (3.5.3)
+# See seki:303.
+
+|X???
+|.YX?
+|XO.X         try to make ko
+|*.O.
++----
+
+:8,s,value(32)
+
+|Xa??
+|.YX?
+|XO.X
+|*.O.
++----
+
+;!o_somewhere(a) || !defend(a)
+
+
+Pattern A906b
+# gf New pattern. (3.5.3)
+# See seki:303.
+
+|X???
+|.YX?
+|.OXX         try to make ko
+|*.O.
++----
+
+:8,s,value(32)
+
+|Xa??
+|.YX?
+|.OXX
+|*.O.
++----
+
+;!o_somewhere(a) || !defend(a)
 
 
 Pattern A907
@@ -4579,6 +4628,24 @@
 ;owl_escape_value(A)>0 && !xplay_disconnect(*,A,B) && !oplay_connect(*,A,B)
 
 
+Pattern A1136
+# gf New pattern. (3.5.3)
+
+?Y?
+O*O
+..?
+?X?
+
+:8,-,value(75)
+
+?B?
+O*O
+..?
+?A?
+
+;owl_escape_value(A)>0 && !xplay_disconnect(*,A,B) && !oplay_connect(*,A,B)
+
+
 #########################################################
 #                                                       #
 #       Kill or threaten a worm of the dragon           #
@@ -4752,6 +4819,24 @@
 +----
 
 :8,s,value(50)
+
+
+Pattern A1303c
+# gf New pattern. (3.5.3)
+
+|..X?         variation
+|XOYo
+|.*.?
++----
+
+:8,s,value(85)
+
+|..X?
+|XaYo
+|.*.?
++----
+
+;defend(a) != WIN
 
 
 Pattern A1304
Index: patterns/owl_defendpats.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/owl_defendpats.db,v
retrieving revision 1.108
diff -u -r1.108 owl_defendpats.db
--- patterns/owl_defendpats.db  19 Nov 2003 07:53:49 -0000      1.108
+++ patterns/owl_defendpats.db  28 Nov 2003 10:22:13 -0000
@@ -2607,6 +2607,18 @@
 :8,-,value(40)
 
 
+Pattern D644
+# gf New pattern. (3.5.3)
+# See seki:111.
+
+oOOo   make one definite eye
+.*.O
+X..O
+----
+
+:8,-,value(30)
+
+
 #########################################################
 #                                                       #
 #            Make eyeshape in the center                #
@@ -3677,6 +3689,19 @@
 +----
 
 ;does_attack(*,A) && xplay_attack(b,*,c,A)
+
+
+Pattern D840
+# gf New pattern. (3.5.3)
+# See seki:203.
+
+|OO??
+|.*O?
+|XXOO         make seki
+|.O.O
++----
+
+:8,-,value(25)
 
 
 #########################################################
Index: patterns/patterns.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/patterns.db,v
retrieving revision 1.119
diff -u -r1.119 patterns.db
--- patterns/patterns.db        19 Nov 2003 07:53:49 -0000      1.119
+++ patterns/patterns.db        28 Nov 2003 10:22:16 -0000
@@ -13630,8 +13630,8 @@
 
 
 Pattern S6c
-# Back out from a potential and horribly complex ko for the
-# life of the entire corner. This moves secures a seki.
+# Eliminate a potential 1000-year ko for the life of the entire
+# corner. This moves secures a seki.
 
 |OO??
 |.OOO
@@ -13668,6 +13668,223 @@
 +----
 
 ;lib(a)==4 && seki_helper(a)
+
+
+Pattern S8
+# gf New pattern. (3.5.3)
+# 7 points gote seki. See seki:301.
+
+|XX???
+|.XXX?
+|.*.XX
+|....X
++-----
+
+:8,sXe,terri(7)
+
+|AA???
+|.AAA?
+|.*.AA
+|....A
++-----
+
+;lib(A)==4 && seki_helper(A)
+
+
+Pattern S9
+# gf New pattern. (3.5.3)
+# 7 points seki. Compare S8. See seki:302
+
+|OO???
+|.OOO?
+|.*.OO
+|....O
++-----
+
+:8,sXe,terri(7)
+
+|aa???
+|.aaa?
+|.*.aa
+|....a
++-----
+
+;lib(a)==4 && seki_helper(a)
+
+
+Pattern S10
+# gf New pattern. (3.5.3)
+# 8 points (mostly) sente seki. See seki:801.
+
+|XXX??
+|..XX?
+|.*.XX
+|....X
++-----
+
+:8,sXe,terri(8),followup(16)
+
+|AAA??
+|..AA?
+|.*.AA
+|....A
++-----
+
+;lib(A)==4 && seki_helper(A)
+
+
+Pattern S10b
+# gf New pattern. (3.5.3)
+# Best way to secure seki. See seki:803.
+
+|OOO??
+|..OO?
+|.X*OO
+|....O
++-----
+
+:8,sXe,terri(8),reverse_followup(16)
+
+|aaa??
+|..aa?
+|bX*aa
+|....a
++-----
+
+;lib(a)==4 && seki_helper(a)
+
+>replace(b,*);
+
+
+Pattern S10c
+# gf New pattern. (3.5.3)
+# Make seki in sente, not gote. See seki:808.
+
+|XXX??
+|..XX?
+|.O*XX
+|..X.X
++-----
+
+:8,sXe,terri(8),followup(16)
+
+|AAA??
+|..AA?
+|bO*AA
+|.cX.A
++-----
+
+;lib(A)==4 && seki_helper(A)
+
+>replace(b,*);
+>replace(c,*);
+
+
+Pattern S10d
+# gf New pattern. (3.5.3)
+# Make seki in sente, not gote. See seki:810.
+# Only replace pattern here. The seki_helper doesn't apply and the
+# semeai code should find either a or * if there's a chance to make seki.
+
+|XXX??
+|*.XX?
+|.OOXX
+|.XX.X
++-----
+
+:8,sX
+
+|XXX??
+|*.XX?
+|aOOXX
+|.XX.X
++-----
+
+>replace(a,*);
+
+
+Pattern S11
+# gf New pattern. (3.5.3)
+# 8 points (mostly) reverse sente seki. Compare S10. See seki:802.
+
+|OOO??
+|..OO?
+|.*.OO
+|....O
++-----
+
+:8,sXe,terri(8),reverse_followup(16)
+
+|aaa??
+|..aa?
+|.*.aa
+|....a
++-----
+
+;lib(a)==4 && seki_helper(a)
+
+
+Pattern S12
+# gf New pattern. (3.5.3)
+# 9 points gote seki. See seki:901.
+
+|XXXX?
+|...X?
+|.*.XX
+|....X
++-----
+
+:8,sXe,terri(9)
+
+|AAAA?
+|...A?
+|.*.AA
+|....A
++-----
+
+;lib(A)==5 && seki_helper(A)
+
+
+Pattern S13
+# gf New pattern. (3.5.3)
+# 9 points seki. Compare S12. See seki:902.
+
+|OOOO?
+|...O?
+|.*.OO
+|....O
++-----
+
+:8,sXe,terri(9)
+
+|aaaa?
+|...a?
+|.*.aa
+|....a
++-----
+
+;lib(a)==5 && seki_helper(a)
+
+
+Pattern S14b
+# gf New pattern. (3.5.3)
+# Make sente seki. See seki:905.
+
+|OOOO?
+|.X.O?
+|.XOOO
+|..*.O
++-----
+
+:8,sX
+
+|OOOO?
+|.X.O?
+|.XOOO
+|.a*.O
++-----
+
+> replace(a,*);
 
 
 ######################################################################
Index: regression/ld_owl.tst
===================================================================
RCS file: /cvsroot/gnugo/gnugo/regression/ld_owl.tst,v
retrieving revision 1.32
diff -u -r1.32 ld_owl.tst
--- regression/ld_owl.tst       24 Aug 2003 21:28:40 -0000      1.32
+++ regression/ld_owl.tst       28 Nov 2003 10:22:17 -0000
@@ -134,6 +134,7 @@
 51 dragon_status R3
 #? [critical S1 (R1|S1|T5|T4|T3|S2|S3|T1)]
 # B1 is a better defense than D1 because the latter only lives by double ko.
+# FIXME: D1 and A5 only attack with ko since black can reply at A2.
 52 dragon_status C4
 #? [critical (D1|A5) (B1|D1|B2)]
 
Index: regression/seki.tst
===================================================================
RCS file: /cvsroot/gnugo/gnugo/regression/seki.tst,v
retrieving revision 1.1
diff -u -r1.1 seki.tst
--- regression/seki.tst 17 Nov 2003 10:32:49 -0000      1.1
+++ regression/seki.tst 28 Nov 2003 10:22:18 -0000
@@ -239,9 +239,10 @@
 loadsgf games/seki08.sgf
 401 reg_genmove white
 #? [B1]
-# Most moves secure territory but C1 and C2 are most natural.
+# Most moves secure territory but C1 and C2 are most natural. We also
+# allow B1.
 402 reg_genmove black
-#? [C1|C2]
+#? [C1|C2|B1]
 
 # C1 and C2 both secure seki, but C1 is one prisoner better.
 # B2 leaves white the option to make ko.
@@ -404,16 +405,18 @@
 902 reg_genmove black
 #? [B2]
 
-# Black probably have more moves to make seki but C2 looks most natural.
+# Black probably have more moves to make seki but C2 looks most
+# natural. C1 is also good enough
 play white B2
 903 reg_genmove black
-#? [C2]
+#? [C2|C1]
 
 play black C2
 904 reg_genmove white
 #? [B3]
 
-# B1 gives ko or seki in gote.
+# B1 gives ko or seki in gote. Tenuki also leaves a seki but compared
+# to C1 the latter is 1 point double sente.
 play white B3
 905 reg_genmove black
 #? [C1]
@@ -432,6 +435,7 @@
 908 reg_genmove white
 #? [A2]
 
+# 1 point double sente, just like 907.
 undo
 909 reg_genmove white
 #? [A3]
Index: regression/strategy4.tst
===================================================================
RCS file: /cvsroot/gnugo/gnugo/regression/strategy4.tst,v
retrieving revision 1.72
diff -u -r1.72 strategy4.tst
--- regression/strategy4.tst    5 Nov 2003 19:05:19 -0000       1.72
+++ regression/strategy4.tst    28 Nov 2003 10:22:18 -0000
@@ -216,6 +216,9 @@
 191 reg_genmove black
 #? [C12]
 
+# A15 captures the white corner stones but does not have much
+# strategical value. The black stones are safe anyway. Thus A15 is
+# worth about 19 points. Other moves may well be larger.
 loadsgf games/pooo.sgf 74
 192 reg_genmove black
 #? [A15]




reply via email to

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