gnugo-devel
[Top][All Lists]
Advanced

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

[gnugo-devel] vital owl defense


From: Arend Bayer
Subject: [gnugo-devel] vital owl defense
Date: Sat, 16 Nov 2002 20:44:09 +0100 (CET)

While there are matching vital owl attack patterns, we make it harder
for do_owl_defend to claim life (and hence cut the search).

However, the moves themselves are discarded. This is changed by this
patch. If owl_estimate_life() would estimate the dragon to be alive
without this rule, it inserts the top scoring vital attack move into
the vital_moves list as a defense against the vital owl attack.

As sometimes the right defense could be somewhere else than the attack
move, this can be indicated in the pattern by a '!'. However, this
does not seem necessary for many patterns.

This reduces owl nodes for nngs.tst by ~2% and probably gets exactly
one PASS for the whole regression test suite (a good one).

Arend


Index: engine/owl.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/owl.c,v
retrieving revision 1.121
diff -u -p -r1.121 owl.c
--- engine/owl.c        15 Nov 2002 19:39:45 -0000      1.121
+++ engine/owl.c        16 Nov 2002 19:39:49 -0000
@@ -111,6 +111,7 @@ struct owl_move_data {
   const char *name; /* name of the pattern suggesting the move */
   int same_dragon;  /* whether the move extends the dragon or not */
   int escape;       /* true if an escape pattern is matched */
+  int defense_pos;  /* defense coordinate for vital owl attack patterns. */
 };

 struct matched_pattern_data {
@@ -153,7 +154,8 @@ static void owl_shapes_callback(int m, i
                                struct pattern *pattern_db,
                                int ll, void *data);
 static void owl_add_move(struct owl_move_data *moves, int move, int value,
-                        const char *reason, int same_dragon, int escape);
+                        const char *reason, int same_dragon, int escape,
+                        int defense_pos);
 static void owl_determine_life(struct local_owl_data *owl,
                               struct local_owl_data *second_owl,
                               int komaster, int does_attack,
@@ -632,7 +634,7 @@ do_owl_analyze_semeai(int apos, int bpos
       owl_add_move(moves, vital_defensive_moves[k].pos,
                   move_value, "vital defensive move",
                   vital_defensive_moves[k].same_dragon,
-                  vital_defensive_moves[k].escape);
+                  vital_defensive_moves[k].escape, NO_MOVE);
     }
     for (k = 0;
         k < MAX_SEMEAI_MOVES && vital_offensive_moves[k].pos != NO_MOVE;
@@ -662,7 +664,7 @@ do_owl_analyze_semeai(int apos, int bpos
       owl_add_move(moves, vital_offensive_moves[k].pos,
                   move_value, vital_offensive_moves[k].name,
                   same_dragon,
-                  vital_offensive_moves[k].escape);
+                  vital_offensive_moves[k].escape, NO_MOVE);
     }
     for (k = 0;
         k < MAX_SEMEAI_MOVES && shape_defensive_moves[k].pos != NO_MOVE;
@@ -689,7 +691,7 @@ do_owl_analyze_semeai(int apos, int bpos
                   move_value,
                   shape_defensive_moves[k].name,
                   shape_defensive_moves[k].same_dragon,
-                  shape_defensive_moves[k].escape);
+                  shape_defensive_moves[k].escape, NO_MOVE);
     }
     for (k = 0;
         k < MAX_SEMEAI_MOVES && shape_offensive_moves[k].pos != NO_MOVE;
@@ -720,7 +722,7 @@ do_owl_analyze_semeai(int apos, int bpos
                   move_value,
                   shape_offensive_moves[k].name,
                   same_dragon,
-                  shape_offensive_moves[k].escape);
+                  shape_offensive_moves[k].escape, NO_MOVE);
     }
     /* If no owl moves were found, turn off the owl phase */
     if (moves[0].pos == 0)
@@ -810,20 +812,20 @@ do_owl_analyze_semeai(int apos, int bpos
     move_value = semeai_move_value(outside_liberty.pos,
                                   owla, owlb, 50);
     owl_add_move(moves, outside_liberty.pos, move_value,
-                "safe outside liberty", 0, 0);
+                "safe outside liberty", 0, 0, NO_MOVE);
   }
   else if (backfilling_move_found && backfilling_move.pos != NO_MOVE) {
     move_value = semeai_move_value(backfilling_move.pos,
                                   owla, owlb, 50);
     owl_add_move(moves, backfilling_move.pos, move_value,
-                "backfilling move", 0, 0);
+                "backfilling move", 0, 0, NO_MOVE);
   }
   else if (safe_common_liberty_found
           && common_liberty.pos != NO_MOVE) {
     move_value = semeai_move_value(common_liberty.pos,
                                   owla, owlb, 10);
     owl_add_move(moves, common_liberty.pos, move_value,
-                "safe common liberty", 1, 0);
+                "safe common liberty", 1, 0, NO_MOVE);
   }
   /* Now we are ready to try moves. Turn on the sgf output ... */
   sgf_dumptree = save_sgf_dumptree;
@@ -1868,6 +1870,7 @@ do_owl_defend(int str, int *move, int *w
   int eyemin = -1;               /* Lower bound on the number of eyes. */
   int eyemax = -1;               /* Upper bound on the number of eyes. */
   struct eyevalue probable_eyes; /* Best guess of eyevalue. */
+  int escape_route;
   const char *live_reason;
   int move_cutoff;
   Read_result *read_result = NULL;
@@ -1912,7 +1915,8 @@ do_owl_defend(int str, int *move, int *w
    * FIXME: Should introduce a new owl depth value rather than having
    *        this hardwired value.
    */
-  if (stackp > 2 && owl_escape_route(owl) >= 5) {
+  escape_route = owl_escape_route(owl);
+  if (stackp > 2 && escape_route >= 5) {
     /* FIXME: We probably should make distinction in the returned
      * result whether the dragon lives by making two eyes or by
      * escaping.
@@ -1984,6 +1988,12 @@ do_owl_defend(int str, int *move, int *w
        READ_RETURN(read_result, move, shape_moves[0].pos, WIN);
       }
       moves = shape_moves;
+
+      if (eyemax == 0 && escape_route == 0)
+       move_cutoff = 67;
+      else if (eyemax <= 1 && escape_route <= 2)
+       move_cutoff = 32;
+
       break;

     case 0:
@@ -2325,8 +2335,22 @@ owl_estimate_life(struct local_owl_data
       gg_assert(0);
     return 1;
   }
-  else
-    return 0;
+
+  if (!does_attack
+      && (*eyemin + matches_found >= 2
+         || (*eyemin + matches_found == 1 && min_eyes(probable_eyes) >= 4)
+      || (stackp > owl_distrust_depth
+         && min_eyes(probable_eyes) >= 2))) {
+    /* We are not yet alive only due to owl vital attack patterns matching.
+     * Let's try to defend against it.
+     */
+    owl_add_move(vital_moves, dummy_moves[0].defense_pos,
+                dummy_moves[0].value, dummy_moves[0].name, 2, 0, NO_MOVE);
+  }
+
+
+
+  return 0;
 }


@@ -2577,7 +2601,7 @@ owl_determine_life(struct local_owl_data
              TRACE("vital point looked stupid, moved it to %1m\n",
                    attack_point);

-           owl_add_move(moves, attack_point, value, reason, 1, 0);
+           owl_add_move(moves, attack_point, value, reason, 1, 0, NO_MOVE);
            vital_values[attack_point] = value;
            eyes_attack_points[num_eyes] = attack_point;
          }
@@ -2628,7 +2652,7 @@ owl_determine_life(struct local_owl_data
              TRACE("vital point looked stupid, moved it to %1m\n",
                    defense_point);

-           owl_add_move(moves, defense_point, value, reason, 1, 0);
+           owl_add_move(moves, defense_point, value, reason, 1, 0, NO_MOVE);
            vital_values[defense_point] = value;
          }
        }
@@ -2706,14 +2730,16 @@ owl_determine_life(struct local_owl_data

          TRACE("save lunch at %1m with %1m, score %d\n",
                owl->lunch[lunch], defense_point, value);
-         owl_add_move(moves, defense_point, value, "save lunch", 1, 0);
+         owl_add_move(moves, defense_point, value,
+                      "save lunch", 1, 0, NO_MOVE);
        }
        else {
          attack_point = improve_lunch_attack(owl->lunch[lunch],
                                              owl->lunch_attack_point[lunch]);
          TRACE("eat lunch at %1m with %1m, score %d\n",
                owl->lunch[lunch], attack_point, value);
-         owl_add_move(moves, attack_point, value, "eat lunch", 1, 0);
+         owl_add_move(moves, attack_point, value, "eat lunch",
+                      1, 0, NO_MOVE);
          num_lunch++;
          eyevalue_list[num_eyes++] = e;
        }
@@ -3243,6 +3269,7 @@ owl_shapes_callback(int m, int n, int co
   struct owl_move_data *moves = data; /* considered moves passed as data */
   int same_dragon = 1;
   int escape = 0;
+  int defense_pos;

   /* Pick up the location of the move */
   move = AFFINE_TRANSFORM(pattern->movei, pattern->movej, ll, m, n);
@@ -3307,8 +3334,19 @@ owl_shapes_callback(int m, int n, int co
     escape = 1;
   else
     escape = 0;
+
+  /* Finally, check for position of defense move. */
+  {
+    int k;
+    defense_pos = move;
+    for (k = 0; k < pattern->patlen; k++)
+      if (pattern->patn[k].att == ATT_not)
+       defense_pos = AFFINE_TRANSFORM(pattern->patn[k].x, pattern->patn[k].y,
+                                      ll, m, n);
+  }

-  owl_add_move(moves, move, tval, pattern->name, same_dragon, escape);
+  owl_add_move(moves, move, tval, pattern->name, same_dragon, escape,
+              defense_pos);
 }


@@ -3316,7 +3354,7 @@ owl_shapes_callback(int m, int n, int co

 static void
 owl_add_move(struct owl_move_data *moves, int move, int value,
-            const char *reason, int same_dragon, int escape)
+            const char *reason, int same_dragon, int escape, int defense_pos)
 {
   int k;

@@ -3363,6 +3401,7 @@ owl_add_move(struct owl_move_data *moves
         */
        moves[k].same_dragon = same_dragon;
        moves[k].escape = escape;
+       moves[k].defense_pos = defense_pos;
       }
       break;
     }
Index: patterns/owl_vital_apats.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/owl_vital_apats.db,v
retrieving revision 1.31
diff -u -p -r1.31 owl_vital_apats.db
--- patterns/owl_vital_apats.db 20 Oct 2002 10:43:25 -0000      1.31
+++ patterns/owl_vital_apats.db 16 Nov 2002 19:39:50 -0000
@@ -40,6 +40,7 @@
 #  x     : your piece or empty
 #  o     : my piece or empty
 #  *     : my next move
+#  !    : your defense move against * (if different)
 #  -, |  : edge of board
 #  +     : corner of board
 #
@@ -203,7 +204,7 @@ XOOXXx

 ?XX???
 XaaXXx
-.aX*.x
+!aX*.x
 ------

 ;attack(a) && !defend(a)
@@ -227,7 +228,7 @@ Pattern VA13
 |XX?        take ko to maybe kill
 |*XX
 |XOX
-|O.O
+|O!O
 +---

 :8,s,value(85)
@@ -244,7 +245,7 @@ Pattern VA13
 Pattern VA14

 ?OX         force X to defend inside own eyespace
-OX.
+OX!
 *XO
 ---

@@ -293,7 +294,7 @@ X..?
 Pattern VA17

 xXXOo         exploit shortage of liberties
-.O*XO
+!O*XO
 .X.Xo

 :8,s,value(35)
@@ -307,7 +308,7 @@ aO*XO

 Pattern VA18

-XX.O       throw in to kill an eye
+XX!O       throw in to kill an eye
 .*X?
 XXO?

@@ -445,7 +446,7 @@ Pattern VA26
 # gf New pattern. (3.1.15)

 ??XX?       making nakade is only chance to kill, unless we can capture
-?XO.X       some of the wall
+?XO!X       some of the wall
 X*XOX
 X.OX?
 ?XX??
@@ -509,7 +510,7 @@ Pattern VA29
 # gf New pattern. (3.1.15)

 |XXX?        not two certain eyes
-|.O.X
+|!O.X
 |OX*x
 +----

@@ -519,7 +520,7 @@ Pattern VA29
 Pattern VA30
 # gf New pattern. (3.1.15)

-?XX.         atari to destroy eye
+?XX!         atari to destroy eye
 X.*X
 ?XX?

@@ -538,7 +539,7 @@ Pattern VA31
 ?O.|
 OX.|
 X.X|
-X.*|
+X!*|
 ??.|

 :8,s,value(76)
@@ -548,7 +549,7 @@ Pattern VA32
 # tm New pattern (3.1.15)  (see maeda0:60)

 ?O*|
-OX.|
+OX!|
 X.X|
 XXO|

@@ -560,7 +561,7 @@ Pattern VA33

 ?X|
 XO|
-.O|
+!O|
 *X|

 :8,-,value(76)
@@ -572,7 +573,7 @@ Pattern VA34

 ?X?
 XOX
-.OX
+!OX
 *XO

 :8,-,value(76)
@@ -620,7 +621,7 @@ Pattern VA37

 ?xXO?
 ?X.XO
-O.X.*
+O.X!*
 -----

 :8,-,value(45)
@@ -638,7 +639,7 @@ Pattern VA38
 # See trevora:25

 ??O
-x..           capture a string at the edge of an eyespace
+x!.           capture a string at the edge of an eyespace
 .*X
 ...
 ---
@@ -658,7 +659,7 @@ Pattern VA39
 # tm New Pattern (3.1.16)

 XO*|     atari to kill eye
-.XX|
+!XX|
 XOO|

 :8,s,value(95)
@@ -693,7 +694,7 @@ Pattern VA41

 XXO
 .*X
-..X
+!.X

 :8,s,value(95)

@@ -811,7 +812,7 @@ Pattern VA48

 +----
 |.*..
-|XX.O
+|XX!O

 :8,s,value(75)






reply via email to

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