gnugo-devel
[Top][All Lists]
Advanced

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

[gnugo-devel] (finally) arend_1_23.1: ko threats check


From: Arend Bayer
Subject: [gnugo-devel] (finally) arend_1_23.1: ko threats check
Date: Sun, 27 Jan 2002 14:39:08 +0100 (CET)

- reevaluate_ko_threats now makes checks
- pattern removed

I've spent a lot of time this week trying to figure out whether there 
is a good way of dealing with the FAILs caused by --owl-threats. (Locally,
this is patch arend_1_23.h :-) ) I wasn't successful there, and so I
only submit a small patch with some probably uncontroversial changes
(although reevaluate ko threats definitely needs some more intelligent
handling of owl threats; I only took care of tactical threats).

The mode --owl-threats has two consequences (unless I missed s.th.):
It adds followup values for owl_attack threats, and it changes dragon
safety values. I tried to tweak with both of these evaluations (the first
one often has overlaps with strategic attacks, the second is a bit coarse
as a criterion). But all the changes I tried in dragon.c and
dragon_safety (in move_reasons.c) did not really produce a net gain.
However, both problems might be treated better with a more intelligent
evaluation of strategic effects of moves on dragons, which is on the
to-do-list as I understand.

Although I am not disagreeing with the decision to turn off --owl-threats
as default, I may point out that there are some quite urgent moves
missed in this mode, and which are really directly related to the
missing knowledge of OWL_ATTACK_THREATs; 13x3:37 is a typical example,
and there were a few (maybe 2 or 3) others in the regression; as usually
only bad moves make it into the regression test suites, I would expect a
little more in "real life" (where as in other situations the followup
values/change dragon safeties just shuffle a less-than-perfect valuation
a bit, sometimes producing better and sometimes worse moves).

So it might be worth trying to find a way to produce this useful
information at less time cost.

Arend


Index: engine/move_reasons.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/move_reasons.c,v
retrieving revision 1.64
diff -u -r1.64 move_reasons.c
--- engine/move_reasons.c       22 Jan 2002 14:57:04 -0000      1.64
+++ engine/move_reasons.c       27 Jan 2002 13:20:48 -0000
@@ -781,6 +781,40 @@
   return num_strings;
 }
 
+/* Report the biggest dragon that is owl-affected (possibily with ko)
+ * by a move at (pos).
+ */
+int
+get_biggest_owl_target(int pos)
+{
+  int k;
+  int biggest_target = -1;
+  float target_size = 0.0;
+  for (k = 0; k < MAX_REASONS; k++) {
+    int r = move[pos].reason[k];
+    if (r < 0)
+      break;
+
+    switch (move_reasons[r].type) {
+    case OWL_ATTACK_MOVE:
+    case OWL_ATTACK_MOVE_GOOD_KO:
+    case OWL_ATTACK_MOVE_BAD_KO:
+    case OWL_ATTACK_THREAT:
+    case OWL_DEFEND_MOVE:
+    case OWL_DEFEND_MOVE_GOOD_KO:
+    case OWL_DEFEND_MOVE_BAD_KO:
+    case OWL_DEFEND_THREAT:
+    case OWL_PREVENT_THREAT:
+      if (dragon[dragons[move_reasons[r].what]].effective_size
+          > target_size) {
+        biggest_target = move_reasons[r].what;
+        target_size = dragon[dragons[move_reasons[r].what]].effective_size;
+      }
+    }
+  }
+  return biggest_target;
+}
+
 /*
  * Add to the reasons for the move at (pos) that it connects the
  * dragons at (dr1) and (dr2). Require that the dragons are
Index: engine/move_reasons.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/move_reasons.h,v
retrieving revision 1.13
diff -u -r1.13 move_reasons.h
--- engine/move_reasons.h       22 Jan 2002 14:57:04 -0000      1.13
+++ engine/move_reasons.h       27 Jan 2002 13:20:49 -0000
@@ -198,6 +198,7 @@
 int  defense_move_reason_known(int pos, int what);
 int  owl_attack_move_reason_known(int pos, int what);
 int  owl_defense_move_reason_known(int pos, int what);
+int  get_biggest_owl_target(int pos);
 int  is_antisuji_move(int pos);
 
 int  move_connects_strings(int pos, int color);
Index: engine/value_moves.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/value_moves.c,v
retrieving revision 1.8
diff -u -r1.8 value_moves.c
--- engine/value_moves.c        25 Jan 2002 07:36:54 -0000      1.8
+++ engine/value_moves.c        27 Jan 2002 13:21:00 -0000
@@ -2331,22 +2331,123 @@
  * the opponent fills in the ko (or resolves it in another way.)
  */
 static void
-reevaluate_ko_threats(void)
+reevaluate_ko_threats(int ko_move, int color)
 {
+  int ko_stone;
+  int opp_ko_move;
   int m, n;
   int pos;
+  int k;
+  int type, what;
+  int threat_does_work = 0;
+  int ko_move_target;
+  float threat_size;
 
+  ko_move_target = get_biggest_owl_target(ko_move);
+  
+  /* Find the ko stone. */
+  for (k = 0; k <= 3; k++) {
+    ko_stone = ko_move + delta[k];
+    if (ON_BOARD(ko_stone) && countlib(ko_stone))
+      break;
+  }
+  
   TRACE("Reevaluating ko threats.\n");
   for (m = 0; m < board_size; m++)
     for (n = 0; n < board_size; n++) {
       pos = POS(m, n);
-
-      if (move[pos].additional_ko_value > 0.0) {
+      if (pos == ko_move)
+        continue;
+      if (move[pos].additional_ko_value <= 0.0) 
+        continue;
+
+      /* Otherwise we look for the biggest threat, and then check whether
+       * it still works after ko has been resolved.
+       */
+      threat_size = 0.0;
+      type = -1;
+      what = -1;
+      for (k = 0; k < MAX_REASONS; k++) {
+        int r = move[pos].reason[k];
+        if (r < 0)
+          break;
+        if (! (move_reasons[r].type & THREAT_BIT))
+          continue;
+        switch (move_reasons[r].type) {
+        case ATTACK_THREAT:
+        case DEFEND_THREAT:
+          if (worm[worms[move_reasons[r].what]].effective_size
+              > threat_size) {
+            threat_size = worm[worms[move_reasons[r].what]].effective_size;
+            type = move_reasons[r].type;
+            what = move_reasons[r].what;
+          }
+          break;
+        case OWL_ATTACK_THREAT:
+        case OWL_DEFEND_THREAT:   
+        case SEMEAI_THREAT:
+          if (dragon[dragons[move_reasons[r].what]].effective_size
+              > threat_size) {
+            threat_size = dragon[dragons[move_reasons[r].what]]\
+                          .effective_size;
+            type = move_reasons[r].type;
+            what = move_reasons[r].what;
+          }
+          break;
+        default:
+          /* This means probably someone has introduced a new threat type
+           * without adding the corresponding case above.
+           */
+          gg_assert(0);
+          break;
+        }
+      } 
+      /* If there is no threat recorded, the followup value is probably
+       * contributed by a pattern. We can do nothing but accept this value.
+       * (although this does cause problems).
+       */
+      if (type == -1)
+        threat_does_work = 1;
+      else
+        if (trymove(pos, color, "reevaluate_ko_threats", ko_move,
+                    EMPTY, ko_move)) {
+          if (!find_defense(ko_stone, &opp_ko_move))
+            threat_does_work = 1;
+          else {
+            if (trymove(opp_ko_move, OTHER_COLOR(color),
+                        "reevaluate_ko_threats", ko_move, EMPTY, NO_MOVE)) {
+              switch (type) {
+              case ATTACK_THREAT:
+                threat_does_work = attack(worms[what], NULL);
+                break;
+              case DEFEND_THREAT:
+                threat_does_work = (board[worms[what]] != EMPTY
+                                    && find_defense(worms[what], NULL));
+                break;
+              case OWL_ATTACK_THREAT:
+              case OWL_DEFEND_THREAT:
+                /* Should we call do_owl_attack/defense here?
+                 * Maybe too expensive? For the moment we just assume
+                 * that the attack does not work if it concerns the
+                 * same dragon as ko_move. (Can this really happen?)
+                 */
+                threat_does_work = (ko_move_target != what);
+              }
+              popgo();
+            }
+          }
+          popgo();
+        }
+ 
+      if (threat_does_work) {
        TRACE("%1m: %f + %f = %f\n", pos, move[pos].value,
              move[pos].additional_ko_value,
              move[pos].value + move[pos].additional_ko_value);
        move[pos].value += move[pos].additional_ko_value;
       }
+      else
+        DEBUG(DEBUG_MOVE_REASONS,
+              "%1m: no additional ko value (threat does not work as ko 
threat)\n", pos);
     }
 }
 
@@ -2491,7 +2592,7 @@
      */
     if (bestval > 0.0 && is_illegal_ko_capture(best_move, color)) {
       TRACE("Move at %1m would be an illegal ko capture.\n", best_move);
-      reevaluate_ko_threats();
+      reevaluate_ko_threats(best_move, color);
       redistribute_points();
       time_report(2, "  reevaluate_ko_threats", NO_MOVE, 1.0);
       ko_values_have_been_added = 1;
Index: patterns/patterns.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/patterns.db,v
retrieving revision 1.49
diff -u -r1.49 patterns.db
--- patterns/patterns.db        23 Jan 2002 19:12:36 -0000      1.49
+++ patterns/patterns.db        27 Jan 2002 13:21:17 -0000
@@ -12939,27 +12939,28 @@
 #
 ######################################################################
 
-
-Pattern Reinforce101
-#FIXME: This should at least be contingent on being ahead.
-#  see trevorc:1170
-
-oO?      Eliminate aji
-.*X
-...
-...
----
-
-:8,O,value(5)
-
-oO?
-.*A
-...
-...
----
-
-; has_aji(A)
-
+# ab: I think this is well treated by our "attack dragon XX, although
+# it seems dead, as we are ahead"-policy.
+# Pattern Reinforce101
+# #FIXME: This should at least be contingent on being ahead.
+# #  see trevorc:1170
+# 
+# oO?      Eliminate aji
+# .*X
+# ...
+# ...
+# ---
+# 
+# :8,O,value(5)
+# 
+# oO?
+# .*A
+# ...
+# ...
+# ---
+# 
+# ; has_aji(A)
+# 
 
 Pattern Reinforce102
 # This pattern should be contingent on being clearly ahead.




reply via email to

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