gnugo-devel
[Top][All Lists]
Advanced

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

[gnugo-devel] arend_3_4.4: strategic evaluation


From: Arend Bayer
Subject: [gnugo-devel] arend_3_4.4: strategic evaluation
Date: Mon, 17 Jun 2002 18:57:31 +0200 (CEST)

 - segment_regions also computes territorial value of regions if available
 - new in dragon2 array: post owl moyo size, its terr. value, dragon weakness
 - strategic dragon evaluation rewritten, setting dragon2[].weakness
 - moved interpolate to gg_interpolate in gg_utils.c

So here is the strategy patch I already mentioned. What is new is that we
now use the post owl influence computation to estimate a dragon's weakness.
This has the advantage that we can use the territorial value of the moyo
instead of just using its size. Of course a moyo of size 8 that is pure
territory is more useful than a moyo of size 10 that is expected to yield 3
points of territory.

This means I needed to do a few modifications to examine_position().

Apart from that, the patch is mostly just smoothening out the rules used
in dragon_safety in value_moves.c into continuos valuations. To do this,
I found linear interpolation to be a good compromise between fine tuning
possibilities and robust behaviour.

The breakage of CVS+arend_3_4.4 is appr. 28 PASSes and 9 FAILs.

There certainly can be done further tuning on this patch. Some issues are:
 - perhaps introduce capping of effective dragon size
 - look at behaviour together with --experimental-semeai/connections and
   --owl-threats

Also, show_dragons() doesn't report the new dragon fields yet.

Arend


Index: engine/dragon.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/dragon.c,v
retrieving revision 1.66
diff -u -r1.66 dragon.c
--- engine/dragon.c     15 Jun 2002 21:39:19 -0000      1.66
+++ engine/dragon.c     17 Jun 2002 16:53:45 -0000
@@ -47,6 +47,7 @@
 #include <ctype.h>

 #include "liberty.h"
+#include "gg_utils.h"

 static void initialize_supplementary_dragon_data(void);
 static void find_neighbor_dragons(void);
@@ -57,7 +58,8 @@
 static int compute_dragon_status(int pos);
 static void dragon_eye(int pos, struct eye_data[BOARDMAX]);
 static int compute_escape(int pos, int dragon_status_known);
-static void compute_surrounding_moyo_sizes(int opposite);
+static void compute_surrounding_moyo_sizes(int opposite,
+                                          int dragon_status_known);

 static int dragon2_initialized;
 static int lively_white_dragons;
@@ -320,15 +322,15 @@

   /* Compute the surrounding moyo sizes. */
   for (d = 0; d < number_of_dragons; d++)
-    dragon2[d].moyo = 2 * BOARDMAX;
+    dragon2[d].moyo_size_pre_owl = 2 * BOARDMAX;
   /* Set moyo sizes according to initial_influence. */
-  compute_surrounding_moyo_sizes(0);
+  compute_surrounding_moyo_sizes(0, 0);
   /* Set moyo sizes according to initial_opposite_influence if
    * this yields smaller results.
    */
-  compute_surrounding_moyo_sizes(1);
+  compute_surrounding_moyo_sizes(1, 0);
   time_report(2, "  time to compute moyo sizes", NO_MOVE, 1.0);
-
+
   /* Determine status: ALIVE, DEAD, CRITICAL or UNKNOWN */
   for (str = BOARDMIN; str < BOARDMAX; str++)
     if (ON_BOARD(str)) {
@@ -370,9 +372,9 @@

       /* Some dragons can be ignored but be extra careful with big dragons. */
       if (DRAGON2(str).escape_route > 25
-         || DRAGON2(str).moyo > 20
-         || (DRAGON2(str).moyo > 10
-             && DRAGON2(str).moyo > dragon[str].size)) {
+         || DRAGON2(str).moyo_size_pre_owl > 20
+         || (DRAGON2(str).moyo_size_pre_owl > 10
+             && DRAGON2(str).moyo_size_pre_owl > dragon[str].size)) {
        dragon[str].owl_status = UNCHECKED;
        dragon[str].owl_attack_point  = NO_MOVE;
        dragon[str].owl_defense_point = NO_MOVE;
@@ -499,9 +501,9 @@
        && dragon[str].origin == str) {
       /* Some dragons can be ignored but be extra careful with big dragons. */
       if (DRAGON2(str).escape_route > 25
-         || DRAGON2(str).moyo > 20
-         || (DRAGON2(str).moyo > 10
-             && DRAGON2(str).moyo > dragon[str].size)) {
+         || DRAGON2(str).moyo_size_pre_owl > 20
+         || (DRAGON2(str).moyo_size_pre_owl > 10
+             && DRAGON2(str).moyo_size_pre_owl > dragon[str].size)) {
        dragon[str].owl_threat_status = UNCHECKED;
        dragon[str].owl_second_attack_point  = NO_MOVE;
        dragon[str].owl_second_defense_point = NO_MOVE;
@@ -573,13 +575,13 @@
       dragon2[d].safety = CRITICAL;
     else if (dragon[origin].owl_status == UNCHECKED
             && true_genus < 4
-            && dragon2[d].moyo <= 10)
+            && dragon2[d].moyo_size_pre_owl <= 10)
       dragon2[d].safety = WEAK;
     else if (dragon_invincible(origin))
       dragon2[d].safety = INVINCIBLE;
-    else if (true_genus >= 6 || dragon2[d].moyo > 20)
+    else if (true_genus >= 6 || dragon2[d].moyo_size_pre_owl > 20)
       dragon2[d].safety = STRONGLY_ALIVE;
-    else if ((2 * true_genus + dragon2[d].moyo
+    else if ((2 * true_genus + dragon2[d].moyo_size_pre_owl
              + 2 * (dragon2[d].lunch != NO_MOVE) < 8
              && dragon2[d].escape_route < 10)
             || (dragon[origin].owl_threat_status == CAN_THREATEN_ATTACK)) {
@@ -743,7 +745,9 @@
   for (d = 0; d < number_of_dragons; d++) {
     dragon2[d].neighbors            = 0;
     dragon2[d].hostile_neighbors    = 0;
-    dragon2[d].moyo                 = -1;
+    dragon2[d].moyo_size_pre_owl    = -1;
+    dragon2[d].moyo_size_post_owl   = -1;
+    dragon2[d].moyo_territorial_value  = 0.0;
     dragon2[d].safety               = -1;
     dragon2[d].escape_route         = 0;
     dragon2[d].genus                = 0;
@@ -1163,7 +1167,7 @@
              d2->escape_route,
              snames[dd->status],
              snames[dd->matcher_status],
-             d2->moyo,
+             d2->moyo_size_pre_owl,
              safety_names[d2->safety]);
       gprintf(", owl status %s\n", snames[dd->owl_status]);
       if (dd->owl_status == CRITICAL) {
@@ -1333,7 +1337,7 @@
   if (lunch == NO_MOVE || worm[lunch].cutstone < 2) {
     if (true_genus < 3
        && DRAGON2(pos).escape_route == 0
-       && DRAGON2(pos).moyo < 5)
+       && DRAGON2(pos).moyo_size_pre_owl < 5)
       return DEAD;

     if (true_genus == 3
@@ -1578,7 +1582,8 @@
        if (dragon[ii].status == ALIVE)
          escape_value[ii] = 6;
        else if (dragon[ii].status == UNKNOWN
-                && (DRAGON2(ii).escape_route > 5 || DRAGON2(ii).moyo > 5))
+                && (DRAGON2(ii).escape_route > 5
+                    || DRAGON2(ii).moyo_size_pre_owl  > 5))
          escape_value[ii] = 4;
       }
       else {
@@ -1596,9 +1601,11 @@
  * Sum up the surrounding moyo sizes for each dragon. Write this into
  * dragon2[].moyo if it is smaller than the current entry. If (opposite)
  * is true, we use initial_opposite_influence, otherwise initial_influence.
+ * If dragons_known is false, then .moyo_size_pre_owl is set, otherwise
+ * .moyo_size_post_owl and .moyo_territorial_value.
  */
 static void
-compute_surrounding_moyo_sizes(int opposite)
+compute_surrounding_moyo_sizes(int opposite, int dragon_status_known)
 {
   int pos;
   int d;
@@ -1610,6 +1617,7 @@
   memset(mx, 0, sizeof(mx));
   for (d = 0; d < number_of_dragons; d++) {
     int this_moyo_size = 0;
+    float this_moyo_value = 0.0;
     for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
       int moyo_number = moyos.segmentation[pos];
       if (moyo_number == 0
@@ -1621,15 +1629,140 @@
       if (mx[moyo_number] != d + 1) {
         mx[moyo_number] = d + 1;
         this_moyo_size += moyos.size[moyo_number];
+       this_moyo_value += moyos.territorial_value[moyo_number];
       }
     }

-    if (this_moyo_size < dragon2[d].moyo)
-      dragon2[d].moyo = this_moyo_size;
+    if (!dragon_status_known) {
+      if (this_moyo_size < dragon2[d].moyo_size_pre_owl) {
+       dragon2[d].moyo_size_pre_owl = this_moyo_size;
+      }
+    }
+    else
+      if (this_moyo_size < dragon2[d].moyo_size_post_owl) {
+       dragon2[d].moyo_size_post_owl = this_moyo_size;
+       dragon2[d].moyo_territorial_value = this_moyo_value;
+      }
   }
 }


+struct interpolation_data moyo_value2weakness =
+  { 5, 0.0, 15.0, {1.0, 0.65, 0.3, 0.15, 0.05, 0.0}};
+struct interpolation_data escape_route2weakness =
+  { 5, 0.0, 25.0, {1.0, 0.6, 0.3, 0.1, 0.05, 0.0}};
+struct interpolation_data genus2weakness =
+  { 6, 0.0, 3.0, {1.0, 0.95, 0.8, 0.5, 0.2, 0.1, 0.0}};
+
+/* This function tries to guess a coefficient measuring the weakness of
+ * a dragon. This coefficient * the effective size of the dragon can be
+ * used to award a strategic penalty for weak dragons.
+ */
+static float
+compute_dragon_weakness_value(int d)
+{
+  float true_genus = ((float) dragon2[d].genus)
+                    + 0.5 * ((float) dragon2[d].heyes
+                             + (dragon2[d].lunch != NO_MOVE ? 1.0 : 0.0));
+  int origin = dragon2[d].origin;
+  float escape_route = (float) dragon2[d].escape_route;
+  int dragon_safety = dragon2[d].safety;
+  int i,j;
+
+  float weakness_value[3];
+  float weakness;
+
+  if (dragon_safety == INVINCIBLE|| dragon_safety == INESSENTIAL)
+    return 0.0;
+  if (dragon_safety == TACTICALLY_DEAD)
+    return 1.0;
+
+  if (dragon_safety == DEAD)
+    return 1.0;
+
+  if (dragon_safety == CRITICAL)
+    return 0.9;
+
+  /* Possible ingredients for the computation:
+   *   '+' means currently used, '-' means not (yet?) used
+   * - pre-owl moyo_size
+   * + post-owl moyo_size and its territory value!
+   * + escape factor
+   * + number of eyes
+   *   - minus number of vital attack moves?
+   * + from owl:
+   *   + attack certain?
+   *   - number of owl nodes
+   *   - maybe reading shadow?
+   *   + threat to attack?
+   * - possible connections to neighbour dragons
+   */
+
+  weakness_value[0] = gg_interpolate(&moyo_value2weakness,
+                                    dragon2[d].moyo_territorial_value);
+  weakness_value[1] = gg_interpolate(&escape_route2weakness,
+                                    escape_route);
+  weakness_value[2] = gg_interpolate(&genus2weakness, true_genus);
+
+  DEBUG(DEBUG_DRAGONS, "Computing weakness of dragon at %1m:\n", origin);
+  DEBUG(DEBUG_DRAGONS, "  moyo value %f -> %f, escape %f -> %f, eyes %f -> 
%f,",
+       dragon2[d].moyo_territorial_value, weakness_value[0],
+       escape_route, weakness_value[1], true_genus, weakness_value[2]);
+
+  for (i = 0; i < 3; i++)
+    for (j = i + 1; j < 3; j++)
+      if (weakness_value[j] < weakness_value[i]) {
+       float tmp = weakness_value[i];
+       weakness_value[i] = weakness_value[j];
+       weakness_value[j] = tmp;
+      }
+
+  /* The overall weakness is mostly, but not completely determined by the
+   * best value found so far:
+   */
+  weakness = gg_min(0.7 * weakness_value[0] + 0.3 * weakness_value[1],
+                    1.3 * weakness_value[0]);
+
+  /* Now corrections due to (uncertain) owl results resp. owl threats. */
+  if (!dragon[origin].owl_attack_certain)
+    weakness += gg_min(0.25 * (1.0 - weakness), 0.25 * weakness);
+  if (!dragon[origin].owl_defense_certain)
+    weakness += gg_min(0.25 * (1.0 - weakness), 0.25 * weakness);
+  if (dragon[origin].owl_threat_status == CAN_THREATEN_ATTACK)
+    weakness += 0.15 * (1.0 - weakness);
+
+  if (weakness < 0.0)
+    weakness = 0.0;
+  if (weakness > 1.0)
+    weakness = 1.0;
+
+  DEBUG(DEBUG_DRAGONS, " result: %f.\n", weakness);
+
+  return weakness;
+}
+
+/* This function has to be called _after_ the owl analysis and the
+ * subsequent re-run of the influence code.
+ */
+void
+compute_refined_dragon_weaknesses()
+{
+  int d;
+
+  /* Compute the surrounding moyo sizes. */
+  for (d = 0; d < number_of_dragons; d++)
+    dragon2[d].moyo_size_post_owl = 2 * BOARDMAX;
+  /* Set moyo sizes according to initial_influence. */
+  compute_surrounding_moyo_sizes(0, 1);
+  /* Set moyo sizes according to initial_opposite_influence if
+   * this yields smaller results.
+   */
+  compute_surrounding_moyo_sizes(1, 1);
+
+  for (d = 0; d < number_of_dragons; d++)
+    dragon2[d].weakness = compute_dragon_weakness_value(d);
+}
+
 /*
  * Test whether two dragons are the same. Used by autohelpers and elsewhere.
  */
@@ -1743,43 +1876,46 @@
     return;
   }

-  gfprintf(outfile,"color                   %s\n", 
color_to_string(dragon[pos].color));
-  gfprintf(outfile,"origin                  %1m\n", dragon[pos].origin);
-  gfprintf(outfile,"size                    %d\n", dragon[pos].size);
-  gfprintf(outfile,"effective_size          %f\n", dragon[pos].effective_size);
-  gfprintf(outfile,"heyes                   %d\n", DRAGON2(pos).heyes);
-  gfprintf(outfile,"heye                    %1m\n", DRAGON2(pos).heye);
-  gfprintf(outfile,"genus                   %d\n", DRAGON2(pos).genus);
-  gfprintf(outfile,"escape_route            %d\n", DRAGON2(pos).escape_route);
-  gfprintf(outfile,"lunch                   %1m\n", DRAGON2(pos).lunch);
+  gfprintf(outfile,"color                   %s\n", color_to_string(d->color));
+  gfprintf(outfile,"origin                  %1m\n", d->origin);
+  gfprintf(outfile,"size                    %d\n", d->size);
+  gfprintf(outfile,"effective_size          %f\n", d->effective_size);
+  gfprintf(outfile,"heyes                   %d\n", d2->heyes);
+  gfprintf(outfile,"heye                    %1m\n", d2->heye);
+  gfprintf(outfile,"genus                   %d\n", d2->genus);
+  gfprintf(outfile,"escape_route            %d\n", d2->escape_route);
+  gfprintf(outfile,"lunch                   %1m\n", d2->lunch);
   gfprintf(outfile,"status                  %s\n",
-            status_to_string(dragon[pos].status));
+          status_to_string(d->status));
   gfprintf(outfile,"owl_status              %s\n",
-            status_to_string(dragon[pos].owl_status));
+          status_to_string(d->owl_status));
   gfprintf(outfile,"matcher_status          %s\n",
-            status_to_string(dragon[pos].matcher_status));
+          status_to_string(d->matcher_status));
   gfprintf(outfile,"owl_threat_status       %s\n",
-            status_to_string(dragon[pos].owl_threat_status));
-  gfprintf(outfile,"owl_attack              %1m\n", 
dragon[pos].owl_attack_point);
+          status_to_string(d->owl_threat_status));
+  gfprintf(outfile,"owl_attack              %1m\n", d->owl_attack_point);
   gfprintf(outfile,"owl_attack_certain      %s\n",
-            (dragon[pos].owl_attack_certain) ? "YES" : "NO");
-  gfprintf(outfile,"owl_2nd_attack          %1m\n", 
dragon[pos].owl_second_attack_point);
-  gfprintf(outfile,"owl_defend              %1m\n", 
dragon[pos].owl_defense_point);
+          (d->owl_attack_certain) ? "YES" : "NO");
+  gfprintf(outfile,"owl_2nd_attack          %1m\n", 
d->owl_second_attack_point);
+  gfprintf(outfile,"owl_defend              %1m\n", d->owl_defense_point);
   gfprintf(outfile,"owl_defense_certain     %s\n",
-            (dragon[pos].owl_defense_certain) ? "YES" : "NO");
-  gfprintf(outfile,"owl_2nd_defend          %1m\n", 
dragon[pos].owl_second_defense_point);
-  gfprintf(outfile,"semeai                  %d\n", DRAGON2(pos).semeai);
+          (d->owl_defense_certain) ? "YES" : "NO");
+  gfprintf(outfile,"owl_2nd_defend          %1m\n",
+           d->owl_second_defense_point);
+  gfprintf(outfile,"semeai                  %d\n", d2->semeai);
   gfprintf(outfile,"semeai_margin_of_safety %d\n",
-         DRAGON2(pos).semeai_margin_of_safety);
+          d2->semeai_margin_of_safety);
   gfprintf(outfile,"neighbors               ");
-  for (k = 0; k < DRAGON2(pos).neighbors; k++)
-    gfprintf(outfile,"%1m ", DRAGON(DRAGON2(pos).adjacent[k]).origin);
+  for (k = 0; k < d2->neighbors; k++)
+    gfprintf(outfile,"%1m ", DRAGON(d2->adjacent[k]).origin);
   gfprintf(outfile,"\nhostile neighbors       %d\n", d2->hostile_neighbors);
-  gfprintf(outfile,"moyo                    %d\n", DRAGON2(pos).moyo);
+  gfprintf(outfile,"moyo size pre owl       %d\n", d2->moyo_size_pre_owl);
+  gfprintf(outfile,"moyo size post owl      %d\n", d2->moyo_size_post_owl);
+  gfprintf(outfile,"moyo territorial value  %f\n", d2->moyo_territorial_value);
   gfprintf(outfile,"safety                  %s\n",
-         safety_to_string(DRAGON2(pos).safety));
+          safety_to_string(d2->safety));
+  gfprintf(outfile,"weakness estimate       %f\n", d2->weakness);
   gfprintf(outfile,"strings                 ");
-
   for (ii = BOARDMIN; ii < BOARDMAX; ii++)
     if (ON_BOARD(ii)
        && worm[ii].origin == ii
Index: engine/genmove.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/genmove.c,v
retrieving revision 1.41
diff -u -r1.41 genmove.c
--- engine/genmove.c    6 May 2002 14:27:31 -0000       1.41
+++ engine/genmove.c    17 Jun 2002 16:53:48 -0000
@@ -49,6 +49,7 @@
 static int dragons_examined_without_owl = -1;
 static int dragons_examined = -1;
 static int initial_influence2_examined = -1;
+static int dragons_refinedly_examined = -1;

 static int revise_semeai(int color);
 static int revise_thrashing_dragon(int color, float advantage);
@@ -81,6 +82,7 @@
   dragons_examined_without_owl = -1;
   dragons_examined = -1;
   initial_influence2_examined = -1;
+  dragons_refinedly_examined = -1;

   /* Prepare our table of move reasons. */
   clear_move_reasons();
@@ -165,15 +167,24 @@

   verbose = save_verbose;

-  if (printworms)
-    show_dragons();
-
-  if (NEEDS_UPDATE(initial_influence2_examined))
+  if (NEEDS_UPDATE(initial_influence2_examined)) {
     compute_initial_influence(color, 1);
+  }
   if (how_much == EXAMINE_INITIAL_INFLUENCE2) {
     gg_assert(test_gray_border() < 0);
     return;
   }
+
+  if (NEEDS_UPDATE(dragons_refinedly_examined)) {
+    compute_refined_dragon_weaknesses();
+  }
+  if (how_much == FULL_EXAMINE_DRAGONS) {
+    gg_assert(test_gray_border() < 0);
+    return;
+  }
+
+  if (printworms)
+    show_dragons();
 }


Index: engine/gnugo.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/gnugo.h,v
retrieving revision 1.57
diff -u -r1.57 gnugo.h
--- engine/gnugo.h      22 May 2002 19:22:25 -0000      1.57
+++ engine/gnugo.h      17 Jun 2002 16:53:51 -0000
@@ -373,6 +373,7 @@
 #define EXAMINE_DRAGONS             4
 #define EXAMINE_OWL_REASONS         5
 #define EXAMINE_INITIAL_INFLUENCE2  6
+#define FULL_EXAMINE_DRAGONS        7

 #define EXAMINE_ALL                 99

@@ -449,6 +450,7 @@

 /* dragon.c */
 void make_dragons(int color, int stop_before_owl, int save_verbose);
+void compute_refined_dragon_weaknesses(void);
 void initialize_dragon_data(void);
 void show_dragons(void);
 int dragon_status(int pos);
Index: engine/influence.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/influence.c,v
retrieving revision 1.56
diff -u -r1.56 influence.c
--- engine/influence.c  29 May 2002 09:26:49 -0000      1.56
+++ engine/influence.c  17 Jun 2002 16:54:00 -0000
@@ -1084,6 +1084,9 @@
       if (q->black_strength[i][j] > 0.0)
        accumulate_influence(q, i, j, BLACK);
     }
+
+  if (q->is_territorial_influence)
+    value_territory(q, m, n, color);
   segment_influence(q);

   if (((q == &initial_influence || q == &initial_opposite_influence)
@@ -1211,34 +1214,6 @@
   return EMPTY;
 }

-#define MAX_INTERPOLATION_STEPS 20
-struct interpolation_data
-{
-  int sections;
-  float range_lowerbound;
-  float range_upperbound;
-  float values[MAX_INTERPOLATION_STEPS + 1];
-};
-
-static float
-interpolate(struct interpolation_data *f, float x)
-{
-  int i;
-  float ratio;
-  float diff;
-  if (x < f->range_lowerbound)
-    return f->values[0];
-  else if (x > f->range_upperbound)
-    return f->values[f->sections];
-  else {
-    ratio = ((float) f->sections) * (x - f->range_lowerbound)
-              /(f->range_upperbound - f->range_lowerbound);
-    i = ratio;
-    diff = ratio - ((float)i);
-    return ((1-diff)*f->values[i] + diff* f->values[i+1]);
-  }
-}
-
 /* This curve determines how much influence is needed at least to claim
  * an intersection as territory, in dependence of the "center value".
  * (In the center, more effort is needed to get territory!)
@@ -1295,8 +1270,8 @@
          dist_j = gg_min(4, dist_j);
        central = (float) 2 * gg_min(dist_i, dist_j) + dist_i + dist_j;
         ratio = gg_max(q->black_influence[i][j], q->white_influence[i][j])
-                / interpolate(&min_infl_for_territory, central);
-        first_guess[i][j] *= interpolate(&territory_correction, ratio);
+                / gg_interpolate(&min_infl_for_territory, central);
+        first_guess[i][j] *= gg_interpolate(&territory_correction, ratio);

        /* Dead stone, upgrade to territory. Notice that this is not
          * the point for a prisoner, which is added later. Instead
@@ -1382,11 +1357,12 @@
    * 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;
+  if (ON_BOARD2(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;
+  }
 }


@@ -1409,6 +1385,7 @@
          * the rest of the region.
         */
        int size = 0;
+       float terr_val = 0.0;
        int queue_start = 0;
        int queue_end = 1;
        int color = region_owner(q, m, n);
@@ -1421,8 +1398,11 @@
          int j = q->queuej[queue_start];
          int k;
          queue_start++;
-         if (q->p[i][j] != color)
+         if (q->p[i][j] != color) {
            size++;
+           if (q->is_territorial_influence)
+             terr_val += gg_abs(q->territory_value[i][j]);
+         }
          segmentation[i][j] = q->number_of_regions;
          for (k = 0; k < 4; k++) {
            int di = deltai[k];
@@ -1442,6 +1422,7 @@
        else
          q->region_type[q->number_of_regions] = BLACK_REGION | type;
        q->region_size[q->number_of_regions] = size;
+       q->region_territorial_value[q->number_of_regions] = terr_val;
        if (0)
          gprintf("Region %d of type %d (color %s) at %m. Size %d\n",
                  q->number_of_regions, q->region_type[q->number_of_regions],
@@ -1550,6 +1531,8 @@
   /* Export size and owner info. */
   for (i = min_moyo_id; i <= max_moyo_id; i++) {
     moyos->size[i - min_moyo_id + 1] = q->region_size[i];
+    moyos->territorial_value[i - min_moyo_id + 1]
+        = q->region_territorial_value[i];
     if (q->region_type[i] & BLACK_REGION)
       moyos->owner[i - min_moyo_id + 1] = BLACK;
     else
@@ -1586,7 +1569,6 @@
   compute_influence(&initial_influence, OTHER_COLOR(color), -1, -1,
                    NULL, NULL);
   if (dragons_known) {
-    value_territory(&initial_influence, -1, -1, EMPTY);
     if ((printmoyo & PRINTMOYO_VALUE_TERRITORY)
        && (printmoyo & PRINTMOYO_INITIAL_INFLUENCE))
       print_influence_territory(&initial_influence,
@@ -1695,6 +1677,7 @@
              > move_influence.white_strength[i][j]))
         accumulate_influence(&followup_influence, i, j, color);

+  value_territory(&followup_influence, m, n, color);
 }

 /* Let color play at (m, n) and compute the influence after this move,
@@ -1720,9 +1703,6 @@
     compute_followup_influence(m, n, color, saved_stones);
     decrease_depth_values();
     popgo();
-
-    value_territory(&move_influence, m, n, color);
-    value_territory(&followup_influence, m, n, color);

     if (m == debug_influence_i
        && n == debug_influence_j && m >= 0) {
Index: engine/influence.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/influence.h,v
retrieving revision 1.11
diff -u -r1.11 influence.h
--- engine/influence.h  29 May 2002 09:26:49 -0000      1.11
+++ engine/influence.h  17 Jun 2002 16:54:01 -0000
@@ -104,6 +104,7 @@
   int area_segmentation[MAX_BOARD][MAX_BOARD];
   int region_type[MAX_REGIONS];
   int region_size[MAX_REGIONS];
+  float region_territorial_value[MAX_REGIONS];
   int number_of_regions;

   int dragons_known;  /* True if this is a post-owl influence computation. */
Index: engine/liberty.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/liberty.h,v
retrieving revision 1.104
diff -u -r1.104 liberty.h
--- engine/liberty.h    15 Jun 2002 21:39:19 -0000      1.104
+++ engine/liberty.h    17 Jun 2002 16:54:05 -0000
@@ -524,6 +524,7 @@
   int segmentation[BOARDMAX]; /* Numbers the moyos. */
   int size[MAX_MOYOS];
   int owner[MAX_MOYOS];
+  float territorial_value[MAX_MOYOS];
 };

 /* Influence functions. */
@@ -758,8 +759,11 @@
   int adjacent[MAX_NEIGHBOR_DRAGONS]; /* adjacent dragons                    */
   int neighbors;                      /* number of adjacent dragons          */
   int hostile_neighbors;              /* neighbors of opposite color         */
-  int moyo;                           /* size of surrounding influence moyo  */
+  int moyo_size_pre_owl;              /* size of surrounding influence moyo  */
+  int moyo_size_post_owl;             /* size of surrounding influence moyo, */
+  float moyo_territorial_value;       /* ...and its territorial value */
   int safety;                         /* a more detailed status estimate     */
+  float weakness; /* A new (3.3.x) continuos estimate of the dragon's safety */
   int escape_route; /* a measurement of likelihood of escape                 */
   int genus;    /* the number of eyes (approximately)                        */
   int heyes;    /* the number of half eyes                                   */
Index: engine/owl.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/owl.c,v
retrieving revision 1.91
diff -u -r1.91 owl.c
--- engine/owl.c        3 Jun 2002 15:00:59 -0000       1.91
+++ engine/owl.c        17 Jun 2002 16:54:24 -0000
@@ -4364,7 +4364,8 @@
        if (dragon[pos].status == ALIVE)
          owl->escape_values[pos] = 6;
        else if (dragon[pos].status == UNKNOWN
-                && (DRAGON2(pos).escape_route > 5 || DRAGON2(pos).moyo > 5))
+                && (DRAGON2(pos).escape_route > 5
+                    || DRAGON2(pos).moyo_size_pre_owl > 5))
          owl->escape_values[pos] = 4;
       }
       DEBUG(DEBUG_ESCAPE, "%o%d", owl->escape_values[pos]);
Index: engine/sgfdecide.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/sgfdecide.c,v
retrieving revision 1.34
diff -u -r1.34 sgfdecide.c
--- engine/sgfdecide.c  15 Jun 2002 21:39:19 -0000      1.34
+++ engine/sgfdecide.c  17 Jun 2002 16:54:27 -0000
@@ -295,7 +295,7 @@
     return ;
   }
   reset_engine();
-  silent_examine_position(board[pos], EXAMINE_DRAGONS);
+  silent_examine_position(board[pos], FULL_EXAMINE_DRAGONS);

   gprintf("Dragon at %1m:\n", pos);
   report_dragon(stderr, pos);
Index: engine/value_moves.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/value_moves.c,v
retrieving revision 1.40
diff -u -r1.40 value_moves.c
--- engine/value_moves.c        12 Jun 2002 15:35:06 -0000      1.40
+++ engine/value_moves.c        17 Jun 2002 16:54:38 -0000
@@ -771,7 +771,8 @@


 /*
- * An attempt to estimate the safety of a dragon.
+ * Returns the pre-computed weakness of a dragon, with corrections
+ * according to ignore_dead_draggons.
  *
  * FIXME: Important to test more exactly how effective a strategical
  *        attack or defense of a weak dragon is. This can be done by
@@ -782,18 +783,6 @@
  *        rather where it's called.
  */

-static float safety_values[10] = {
-/* DEAD        */  0.0,
-/* ALIVE       */  0.9,
-/* CRITICAL    */  0.1,
-/* INESSENTIAL */  1.0,   /* Yes, 1.0. We simply don't worry about it. */
-/* TACT. DEAD  */  0.0,
-/* WEAK        */  0.4,
-/* WEAK ALIVE  */  0.6,
-/* SEKI        */  0.8,
-/* STR. ALIVE  */  1.0,
-/* INVINCIBLE  */  1.0};
-
 static float
 dragon_safety(int dr, int ignore_dead_dragons)
 {
@@ -812,28 +801,7 @@
   if (doing_scoring && dragon_safety == ALIVE)
     return 1.0;

-  /* More detailed guesses for WEAK and WEAKLY_ALIVE dragons. */
-  if (dragon_safety == WEAK || dragon_safety == WEAKLY_ALIVE) {
-    int escape = DRAGON2(dr).escape_route;
-    int moyo = DRAGON2(dr).moyo;
-    /* If escape <= 5 and moyo <= 10, the dragon won't be WEAK, since
-     * the owl code has been run.
-     */
-    if (escape < 10 && moyo < 5)
-      return 0.1;
-    else if (escape < 15 && moyo < 5)
-      return 0.2;
-    else if (escape < 10 && moyo < 10)
-      return 0.3;
-    else if (escape < 5 && moyo < 15)
-      return 0.4;
-    else if (escape < 15 && moyo < 15)
-      return 0.7;
-    else
-      return 0.9;
-  }
-
-  return safety_values[dragon_safety];
+  return (1.0 - DRAGON2(dr).weakness);
 }

 /*
@@ -935,7 +903,7 @@
    * assume it doesn't help dragon a to connect to b.
    */
   if (safety2 == CRITICAL && true_genus2 == 0
-      && DRAGON2(dragonb).moyo == 0)
+      && DRAGON2(dragonb).moyo_size_pre_owl == 0)
     return 0.0;


Index: interface/play_gtp.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/interface/play_gtp.c,v
retrieving revision 1.77
diff -u -r1.77 play_gtp.c
--- interface/play_gtp.c        15 Jun 2002 21:39:19 -0000      1.77
+++ interface/play_gtp.c        17 Jun 2002 16:54:47 -0000
@@ -2624,7 +2624,7 @@
   if (stackp > 0)
     return gtp_failure(id, "dragon data unavailable when stackp > 0");

-  examine_position(EMPTY, EXAMINE_DRAGONS);
+  examine_position(EMPTY, FULL_EXAMINE_DRAGONS);

   gtp_printid(id, GTP_SUCCESS);

Index: utils/gg_utils.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/utils/gg_utils.c,v
retrieving revision 1.25
diff -u -r1.25 gg_utils.c
--- utils/gg_utils.c    18 Apr 2002 21:21:31 -0000      1.25
+++ utils/gg_utils.c    17 Jun 2002 16:54:50 -0000
@@ -395,6 +395,27 @@
   } while (gap > 1 || swap_made);
 }

+/* Linearly interpoloate f(x) from the data given in interpolation_data. */
+float
+gg_interpolate(struct interpolation_data *f, float x)
+{
+  int i;
+  float ratio;
+  float diff;
+  if (x < f->range_lowerbound)
+    return f->values[0];
+  else if (x > f->range_upperbound)
+    return f->values[f->sections];
+  else {
+    ratio = ((float) f->sections) * (x - f->range_lowerbound)
+              /(f->range_upperbound - f->range_lowerbound);
+    i = (int) ratio;
+    diff = ratio - ((float)i);
+     /* printf(stderr, "Floating point Ratio: %f, integer: %d, diff %f", 
ratio, i, diff); */
+    return ((1-diff)*f->values[i] + diff* f->values[i+1]);
+  }
+}
+

 /* Reorientation of point (i, j) into (*ri, *rj) */
 void
Index: utils/gg_utils.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/utils/gg_utils.h,v
retrieving revision 1.10
diff -u -r1.10 gg_utils.h
--- utils/gg_utils.h    18 Apr 2002 21:21:31 -0000      1.10
+++ utils/gg_utils.h    17 Jun 2002 16:54:50 -0000
@@ -67,6 +67,16 @@
 void gg_sort(void *base, size_t nel, size_t width,
             int (*compar)(const void *, const void *));

+#define MAX_INTERPOLATION_STEPS 20
+struct interpolation_data
+{
+  int sections;
+  float range_lowerbound;
+  float range_upperbound;
+  float values[MAX_INTERPOLATION_STEPS + 1];
+};
+
+float gg_interpolate(struct interpolation_data *f, float x);

 const char *gg_version(void);





reply via email to

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