gnugo-devel
[Top][All Lists]
Advanced

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

Re: [gnugo-devel] Eye pattern 304


From: Paul Pogonyshev
Subject: Re: [gnugo-devel] Eye pattern 304
Date: Mon, 5 May 2003 23:45:28 -0400
User-agent: KMail/1.5.9

here is the patch rediffed with comments in.

Paul


Index: engine/liberty.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/liberty.h,v
retrieving revision 1.167
diff -u -p -r1.167 liberty.h
--- engine/liberty.h    4 May 2003 11:20:00 -0000       1.167
+++ engine/liberty.h    5 May 2003 20:35:03 -0000
@@ -51,9 +51,10 @@ extern Hash_data    hashdata;
 /* ================================================================ */
 
 
-#define FALSE_EYE          1
-#define HALF_EYE           2
-#define INHIBIT_CONNECTION 4
+#define FALSE_EYE              1
+#define HALF_EYE               2
+#define INHIBIT_CONNECTION     4
+#define INESSENTIAL_MARGINAL   8
 
 
 /* A string with n stones can have at most 2(n+1) liberties. From this
Index: engine/optics.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/optics.c,v
retrieving revision 1.73
diff -u -p -r1.73 optics.c
--- engine/optics.c     4 May 2003 11:20:00 -0000       1.73
+++ engine/optics.c     5 May 2003 20:35:10 -0000
@@ -1123,48 +1123,49 @@ recognize_eye(int pos, int *attack_point
   if (eye[pos].msize > MAXEYE)
     return 0;
 
-  /* Create list of eye vertices */
+  /* Create list of eye vertices. Ignore inessential marginals. */
   for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++) {
-    if (!ON_BOARD(pos2))
+    if (!ON_BOARD(pos2)
+       || eye[pos2].origin != pos
+       || (heye[pos2].type & INESSENTIAL_MARGINAL))
       continue;
-    if (eye[pos2].origin == pos) {
-      vpos[eye_size] = pos2;
-      marginal[eye_size] = eye[pos2].marginal;
+
+    vpos[eye_size] = pos2;
+    marginal[eye_size] = eye[pos2].marginal;
+    if (marginal[eye_size])
+      num_marginals++;
+    neighbors[eye_size] = eye[pos2].neighbors;
+    if (0) {
       if (marginal[eye_size])
-       num_marginals++;
-      neighbors[eye_size] = eye[pos2].neighbors;
-      if (0) {
-       if (marginal[eye_size])
-         TRACE("(%1m)", vpos[eye_size]);
-       else
-         TRACE(" %1m ", vpos[eye_size]);
-       TRACE("\n");
-      }
-      
-      if (is_corner_vertex(pos2))
-       edge[eye_size] = 2;
-      else if (is_edge_vertex(pos2))
-       edge[eye_size] = 1;
-      else 
-       edge[eye_size] = 0;
-      
-      if (is_halfeye(heye, pos2)) {
-       neighbors[eye_size]++;      /* Increase neighbors of half eye. */
-       eye_size++;
-       /* Use a virtual marginal vertex for mapping purposes. We set it
-        * to be at NO_MOVE so it won't accidentally count as a
-        * neighbor for another vertex. Note that the half eye precedes
-        * the virtual marginal vertex in the list.
-        */
-       vpos[eye_size] = NO_MOVE;
-       marginal[eye_size] = 1;
-       num_marginals++;
-       edge[eye_size] = 0;
-       neighbors[eye_size] = 1;
-      }
-      
+       TRACE("(%1m)", vpos[eye_size]);
+      else
+       TRACE(" %1m ", vpos[eye_size]);
+      TRACE("\n");
+    }
+
+    if (is_corner_vertex(pos2))
+      edge[eye_size] = 2;
+    else if (is_edge_vertex(pos2))
+      edge[eye_size] = 1;
+    else 
+      edge[eye_size] = 0;
+
+    if (is_halfeye(heye, pos2)) {
+      neighbors[eye_size]++;      /* Increase neighbors of half eye. */
       eye_size++;
+      /* Use a virtual marginal vertex for mapping purposes. We set it
+       * to be at NO_MOVE so it won't accidentally count as a
+       * neighbor for another vertex. Note that the half eye precedes
+       * the virtual marginal vertex in the list.
+       */
+      vpos[eye_size] = NO_MOVE;
+      marginal[eye_size] = 1;
+      num_marginals++;
+      edge[eye_size] = 0;
+      neighbors[eye_size] = 1;
     }
+
+    eye_size++;
   }
   
   /* We attempt to construct a map from the graph to the eyespace
@@ -1488,25 +1489,50 @@ next_map(int *q, int map[MAXEYE])
 }     
 
 
-/* add_false_eye() turns a proper eyespace into a margin. */
-
+/* add_false_eye() turns a proper eyespace into a margin. It also turns
+ * neighbor marginals into inessential when some conditions are met.
+ * Consider this example:
+ *
+ *   ...O.
+ *   XXXOX
+ *   X....
+ *
+ * When the topological algorithm does its job, the eye is turned from
+ * '..!' to '.!!'. Since we prohibit such eyespaces, the easiest way to
+ * work it around is to ignore the right marginal vertex at graph matching
+ * stage. We mark it as "inessential" here and recognize_eye() ignores
+ * such marginals.
+ */
 void
 add_false_eye(int pos, struct eye_data eye[BOARDMAX],
              struct half_eye_data heye[BOARDMAX])
 {
   int k;
+  int detach_neighbor_marginals;
   ASSERT1(heye[pos].type == FALSE_EYE, pos);
   DEBUG(DEBUG_EYES, "false eye found at %1m\n", pos);
 
   if (eye[pos].color == GRAY || eye[pos].marginal != 0)
     return;
-  
+
   eye[pos].marginal = 1;
   eye[eye[pos].origin].msize++;
-  for (k = 0; k < 4; k++)
-    if (ON_BOARD(pos + delta[k])
-       && eye[pos + delta[k]].origin == eye[pos].origin)
-      eye[pos + delta[k]].marginal_neighbors++;
+  detach_neighbor_marginals = (eye[pos].neighbors > 1 && is_edge_vertex(pos));
+
+  for (k = 0; k < 4; k++) {
+    int neighbor = pos + delta[k];
+    if (ON_BOARD(neighbor) && eye[neighbor].origin == eye[pos].origin) {
+      eye[neighbor].marginal_neighbors++;
+      if (detach_neighbor_marginals
+         && eye[neighbor].marginal
+         && eye[neighbor].neighbors == 1) {
+       heye[neighbor].type |= INESSENTIAL_MARGINAL;
+       eye[pos].neighbors--;
+       eye[pos].marginal_neighbors--;
+      }
+    }
+  }
+
   propagate_eye(eye[pos].origin, eye);
 }
 
@@ -1589,8 +1615,12 @@ find_half_and_false_eyes(int color, stru
     
     /* skip every vertex which can't be a false or half eye */
     if (eye[pos].color != eye_color
-        || eye[pos].marginal
-        || eye[pos].neighbors > 1)
+       || eye[pos].marginal
+#if 0
+       || (eye[pos].neighbors > 1 && !is_edge_vertex(pos)))
+#else
+       || eye[pos].neighbors > 1)
+#endif
       continue;
     
     sum = topological_eye(pos, color, eye, heye);
Index: engine/owl.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/owl.c,v
retrieving revision 1.156
diff -u -p -r1.156 owl.c
--- engine/owl.c        4 May 2003 11:39:48 -0000       1.156
+++ engine/owl.c        5 May 2003 20:35:22 -0000
@@ -4479,18 +4479,19 @@ owl_find_lunches(struct local_owl_data *
 }
 
 
-/* Try to improve the move to attack a lunch. Essentially we try to
- * avoid unsafe moves when there are less risky ways to attack.
+/* Try to improve the move to attack a lunch. Essentially we try to avoid
+ * unsafe moves when there are less risky ways to attack.
  *
- * This function also improves lunch attack point in this special case:
+ * This function also improves lunch attack point in a special case when
+ * we capture a one- or two-stone lunch on the first line. If we eat it
+ * with a first line move, there is a huge risk we'll end up with a false
+ * eye. Therefore, we move the attack to the second line when it works.
  *
- * |.XXX       In this case it is better to play A2 rather than A1 since
- * |XXOO       it saves an eye in the corner. We replace attack point if
- * |XO..       three conditions are satisfied:
- * |.O.O         a) lunch is a single stone
- * |.XO.         b) it's attack point is a corner point
- * +----         c) it has no neighbors in atari
+ *   .*OO      .*OOO       .*OOOO
+ *   .,XO      .,X.O       .,XX.O
+ *   ----      -----       ------
  *
+ * In all these position the attack point is moved from ',' to '*'.
  */
 static int
 improve_lunch_attack(int lunch, int attack_point)
@@ -4501,19 +4502,28 @@ improve_lunch_attack(int lunch, int atta
   int adj[MAXCHAIN];
 
   if (safe_move(attack_point, color)) {
-    if (countstones(lunch) == 1 && is_corner_vertex(attack_point)
-       && chainlinks2(lunch, adj, 1) == 0) {
-      for (k = 0; k < 4; k++) {
-       int apos = attack_point + delta[k];
+    if (is_edge_vertex(lunch)
+       && is_edge_vertex(attack_point)
+       && neighbor_of_string(attack_point, lunch)) {
+      int stones = countstones(lunch);
+      int libs[2];
 
-       if (board[apos] == EMPTY) {
-         if (safe_move(apos, color))
-           return apos;
-         break;
+      if (stones == 1
+         || (stones == 2
+             && findlib(lunch, 2, libs) == 2
+             && is_edge_vertex(libs[0])
+             && is_edge_vertex(libs[1]))) {
+       for (k = 0; k < 4; k++) {
+         int apos = attack_point + delta[k];
+         if (!ON_BOARD(attack_point - delta[k]) && board[apos] == EMPTY) {
+           if (does_attack(apos, lunch) && safe_move(apos, color))
+             return apos;
+           break;
+         }
        }
       }
     }
-  
+
     return attack_point;
   }
 
Index: patterns/owl_defendpats.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/owl_defendpats.db,v
retrieving revision 1.92
diff -u -p -r1.92 owl_defendpats.db
--- patterns/owl_defendpats.db  2 May 2003 15:04:59 -0000       1.92
+++ patterns/owl_defendpats.db  5 May 2003 20:35:33 -0000
@@ -824,20 +824,21 @@ xx...X.        slide (usually inferior t
 :8,-,value(70)
 
 
-Pattern D219
-# tm Modified (3.1.17)
-
-OO*        capture edge stone to maybe make eye
-.X.
----
-
-:8,-,value(50)
-
-OO*
-aA.
----
-
-;does_attack(*,A) && !obvious_false_oeye(a)
+# pp Removed (3.3.20). This job is now done by improve_lunch_attack().
+#Pattern D219
+## tm Modified (3.1.17)
+#
+#OO*        capture edge stone to maybe make eye
+#.X.
+#---
+#
+#:8,-,value(50)
+#
+#OO*
+#aA.
+#---
+#
+#;does_attack(*,A) && !obvious_false_oeye(a)
 
 
 Pattern D220




reply via email to

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