gnugo-devel
[Top][All Lists]
Advanced

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

[gnugo-devel] arend_1_23.4: experimental influence


From: Arend Bayer
Subject: [gnugo-devel] arend_1_23.4: experimental influence
Date: Sun, 27 Jan 2002 13:54:26 +0100 (CET)

In --experimental-influence mode:
- followup value computed in influence.c
- new_value_territroy revised
- new handling for intrusion patterns
- support for standard/experimental influence specific patterns

I think this stage of my influence experiments might be a good moment
to do a resync with CVS, and to give a report what I have been doing.
Biggest changes are 1. and 3.:

1. The influence module now computes a separate territorial followup
  value. It does so by using the intrusion influence sources
  (B patterns -- they are usually only used for the opponent's stones)
  that relate to INFLUENCE_CAPTURED_SAVED stones (i.e. move played and
  rescued stones). This is fast and does not hurt much (the contributions
  are rather small due to 2.).
2. As for not to overvalue followup values too much, the total sum of all
  intrusion sources "originating from a stone" may not be bigger than
  the strength of the stone itself. (This rule is also used in
  initial_influence/move_influence etc. It has some smoothening effects
  there as well.)
3. As new_value_territory tended to overvalue center moves, I revised it
  in the following way: As a first guess, the same formula (with some
  correction) is applied. Then every point gets the minimum of the
  values of itself and its neighbors as final value. (Maybe this can be
  seen as an analogue to an erosion step in Bouzy's algorithm?) This had
  a huge effect, and now the territory value makes a lot more sense.
  (Maybe I will have to look for s.th. in between, though.)
  This also makes a couple of NonTerritory patterns unneccessary. Of course,
  to tune this, some barriers have to be moved a little. But the important
  part is to make center territory as small as it really is.
4. I have currently disable the "Enhance" patterns and instead work with
  a lower DEFAULT_ATTENUATION. The reason is that I find it a bit
  difficult to get a comprehensive list of patterns there. This is a
  try only.
5. Finally, yet another pattern class (now we've run out of bitmap
  places!). Y patterns only get used in experimental influence mode,
  FY patterns in standard influence only. I want to use this, of course,
  for influence specific patterns, but also to experimentally turn off some
  patterns that should be unnecessary with good territory valuation (fixed
  values in LE15 and similar).

I hope I have consistently added comments to indicate the experimental
influence specific parts in the code, so that others are annoyed as
little as possible by the experimental stuff.

The current regression breakage is likely to be very bad. First I probably have
to tweak with the barriers a little bit as mentioned above. More important
might be that part 1. doesn't make sense for intrusions that can be
stopped in sente (e.g. the 2nd line hane). Here I will try to distinguish
the applicable patterns.

Once I've done those things, I would already be mildly optimistic about
the effects on playing strength from what I've seen so far -- but of
course, I am biased :-)

Arend



Index: engine/influence.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/influence.c,v
retrieving revision 1.29
diff -u -r1.29 influence.c
--- engine/influence.c  20 Jan 2002 15:08:06 -0000      1.29
+++ engine/influence.c  27 Jan 2002 11:57:29 -0000
@@ -30,9 +30,9 @@
 #include "liberty.h"
 #include "influence.h"
 #include "patterns.h"
+#include "gg_utils.h"
 
 static void value_territory(struct influence_data *q);
-static void new_value_territory(struct influence_data *q);
 static void add_influence_source(int pos, int color, float strength,
                                  float attenuation,
                                  struct influence_data *q);
@@ -44,6 +44,16 @@
                                    const char *format, int draw_stones,
                                    int mark_epsilon);
 static void print_influence_areas(struct influence_data *q);
+ 
+/* The following functions are used with experimental_influence is set. */
+static void new_value_territory(struct influence_data *q);
+static void enter_intrusion_source(int source_pos, int strength_pos,
+                                   float strength, float attenuation,
+                                   struct influence_data *q);
+static void add_marked_intrusions(struct influence_data *q, int color);
+static void print_influence_territory(struct influence_data *q,
+                                      const char *info_string);
+ 
 
 /* Influence computed for the initial position, i.e. before making
  * some move.
@@ -53,6 +63,7 @@
 
 /* Influence computed after some move has been made. */
 static struct influence_data move_influence;
+static struct influence_data followup_influence;
 
 /* Coordinates for the move influence was last computed for. */
 static int influence_movei = -1;
@@ -67,6 +78,7 @@
 
 /* Cache of delta_territory_values. */
 static float delta_territory_cache[BOARDMAX];
+static float followup_territory_cache[BOARDMAX];
 
 /* If set, print influence map when computing this move. Purely for
  * debugging.
@@ -158,7 +170,10 @@
     attenuation = q->white_attenuation[m][n];
   else
     attenuation = q->black_attenuation[m][n];
-  diagonal_attenuation = attenuation * DIAGONAL_DAMPING;
+  if (experimental_influence)
+    diagonal_attenuation = attenuation * EXP_DIAGONAL_DAMPING;
+  else
+    diagonal_attenuation = attenuation * DIAGONAL_DAMPING;
 
   if (color == WHITE)
     permeability_array = q->white_permeability;
@@ -350,13 +365,21 @@
   
   if (q != &escape_influence) {
     q->color_to_move = color;
-    attenuation = DEFAULT_ATTENUATION;
+    if (experimental_influence)
+      attenuation = EXP_DEFAULT_ATTENUATION;
+    else
+      attenuation = DEFAULT_ATTENUATION;
   }
   else {
     q->color_to_move = EMPTY;
-    attenuation = 2 * DEFAULT_ATTENUATION;
+    if (experimental_influence)
+      attenuation = 2 * EXP_DEFAULT_ATTENUATION;
+    else
+      attenuation = 2 * DEFAULT_ATTENUATION;
   }
   
+  q->intrusion_counter = 0;
+  
   for (i = 0; i < board_size; i++)
     for (j = 0; j < board_size; j++) {
       int pos = POS(i, j);
@@ -464,6 +487,99 @@
   }
 }
 
+/* Experimental influence: Adds an intrusion as an entry in the list
+ * q->intrusions.
+ */
+static void
+enter_intrusion_source(int source_pos, int strength_pos,
+                       float strength, float attenuation,
+                       struct influence_data *q)
+{
+  gg_assert(q->intrusion_counter < MAX_INTRUSIONS);
+  q->intrusions[q->intrusion_counter].source_pos = source_pos;
+  q->intrusions[q->intrusion_counter].strength_pos = strength_pos;
+  q->intrusions[q->intrusion_counter].strength = strength;
+  q->intrusions[q->intrusion_counter].attenuation = attenuation;
+  q->intrusion_counter++;
+}
+
+/* Experimental influence: Comparision of intrusions datas, to sort them. */
+static int
+compare_intrusions(const void *p1, const void *p2)
+{
+  const struct intrusion_data *intr1 = p1;
+  const struct intrusion_data *intr2 = p2;
+  if (intr1->source_pos - intr2->source_pos != 0) {
+    return (intr1->source_pos - intr2->source_pos);
+  }
+  else if (intr1->strength_pos - intr2->strength_pos != 0) {
+    return (intr1->strength_pos - intr2->strength_pos);
+  }
+  else if (intr1->strength > intr2->strength) {
+    return 1;
+  }
+  else
+    return -1;
+}
+
+/* Experimental influence: This function goes through the list of 
+ * intrusion sources, and adds the intrusion as influence sources for color. 
+ * The strength is corrected so that each stone's intrusions sources
+ * can have total strength of at most the strength of the stone.
+ */
+static void
+add_marked_intrusions(struct influence_data *q, int color)
+{
+  int i, j;
+  int source_pos;
+  float strength_sum;
+  float correction;
+  float source_strength;
+  gg_sort(q->intrusions, q->intrusion_counter, sizeof(q->intrusions[0]),
+          compare_intrusions);
+
+  /* Go through all intrusion sources. */
+  for (i = 0; i < q->intrusion_counter; i = j) {
+    strength_sum = 0.0;
+    source_pos = q->intrusions[i].source_pos;
+    if (color == BLACK) {
+      source_strength = q->black_strength[I(source_pos)][J(source_pos)];
+    }
+    else {
+      source_strength = q->white_strength[I(source_pos)][J(source_pos)];
+    }
+
+    /* First loop: Determine correction factor. */
+    for (j = i; (j < q->intrusion_counter)
+                 && (q->intrusions[j].source_pos == source_pos); j++) {
+      /* Of identical strength positions, only take strongest value. */
+      if (j == i
+          || q->intrusions[j].strength_pos != q->intrusions[j-1].strength_pos)
+        strength_sum += q->intrusions[j].strength;
+    }
+    if (strength_sum > source_strength)
+      correction = (source_strength / strength_sum);
+    else
+      correction = 1.0;
+
+    /* Second loop: Add influence sources. */
+    for (j = i; (j < q->intrusion_counter)
+                 && (q->intrusions[j].source_pos == source_pos); j++) {
+      /* Of identical strenght positions, only take strongest value. */
+      if (j == i || q->intrusions[j].strength_pos
+                    != q->intrusions[j-1].strength_pos) {
+        add_influence_source(q->intrusions[j].strength_pos, color,
+                             correction * q->intrusions[j].strength,
+                             q->intrusions[j].attenuation, q);
+        DEBUG(DEBUG_INFLUENCE,
+              "Adding intrusion for %1m at %1m, value %f (correction %f)\n",
+              source_pos, q->intrusions[j].strength_pos,
+              correction * q->intrusions[j].strength, correction);
+      }
+    }
+  }
+}
+
 /* Callback for the matched patterns in influence.db and barriers.db.
  * The pattern classes used here are:
  * A - Barrier pattern, where O plays first and X tries to block influence.
@@ -485,8 +601,20 @@
 {
   int ti, tj;
   int k;
+  int saved_pos;
   struct influence_data *q = data;
   
+  /* Patterns marked FY get ignored in experimental influence,
+   * those marked Y in standard influence.
+   */
+  if (pattern->class & CLASS_Y) 
+    if (((pattern->class & CLASS_F) && (experimental_influence))
+        || (!(pattern->class & CLASS_F) && !(experimental_influence)))
+    return;
+  /* We currently ignore enhancement patterns in experimental influence. */
+  if ((pattern->class & CLASS_E) && (experimental_influence))
+    return;
+
   /* Loop through pattern elements to see if an A or D pattern
    * can possibly have any effect. If not we can skip evaluating
    * constraint and/or helper. */
@@ -560,6 +688,8 @@
          if ((color == WHITE && q->white_strength[x][y] == 0.0)
              || (color == BLACK && q->black_strength[x][y] == 0.0))
            return; /* Match failed. */
+          else
+            saved_pos = POS(x, y);
        }
        
        if ((pattern->class & (CLASS_A | CLASS_t))
@@ -680,14 +810,65 @@
       
       /* Low intensity influence source for the color in turn to move. */
       if (pattern->class & CLASS_B) {
-        add_influence_source(POS(x, y), color,
-                            pattern->value, DEFAULT_ATTENUATION, q);
+        if (experimental_influence)
+          enter_intrusion_source(saved_pos, POS(x, y), pattern->value,
+                                EXP_DEFAULT_ATTENUATION, q);
+        else
+          add_influence_source(POS(x, y), color,
+                              pattern->value, DEFAULT_ATTENUATION, q);
        DEBUG(DEBUG_INFLUENCE, "  intrusion at %m\n", x, y);
       }
     }
   }
 }
 
+/* Callback for matched barriers patterns in followup influence.
+ * This adds a influence source of color O at !-marked points if any
+ * of the O-stones in the pattern is marked INFLUENCE_SAVED_STONES.
+ */
+static void
+followup_influence_callback(int m, int n, int color, struct pattern *pattern,
+                            int ll, void *data)
+{
+  int k;
+  int saved_stone = NO_MOVE;
+  struct influence_data *q = data;
+  UNUSED(color);
+ 
+  if (!pattern->class & CLASS_B)
+    return;
+
+  /* First loop: We check whether a saved stone is involved. */
+  for (k = 0; k < pattern->patlen; ++k) /* match each point */
+    if (pattern->patn[k].att == ATT_O) {
+      /* transform pattern real coordinate */
+      int x, y;
+      TRANSFORM(pattern->patn[k].x, pattern->patn[k].y, &x, &y, ll);
+      x += m;
+      y += n;
+      if (q->w[x][y] == MARKED)
+        saved_stone = POS(x,y);
+    }
+
+  if (saved_stone == NO_MOVE)
+    return;
+
+  for (k = 0; k < pattern->patlen; ++k)  /* match each point */
+    if (pattern->patn[k].att == ATT_not) {
+      /* transform pattern real coordinate */
+      int x, y;
+      TRANSFORM(pattern->patn[k].x, pattern->patn[k].y, &x, &y, ll);
+      x += m;
+      y += n;
+
+      /* Low intensity influence source for the color in turn to move. */
+      enter_intrusion_source(saved_stone, POS(x, y), pattern->value,
+                            EXP_DEFAULT_ATTENUATION, &followup_influence);
+      DEBUG(DEBUG_INFLUENCE, "  followup for %m: intrusion at %m\n",
+            m, n, x, y);
+    }
+}
+
 /* Called from actions for t patterns. Marks (pos) as not being
  * territory for (color).
  */
@@ -713,6 +894,9 @@
   if (color != EMPTY)
     matchpat(influence_callback, color, &barrierspat_db, q, NULL);
 
+  if (experimental_influence)
+    add_marked_intrusions(q, color);
+
   /* When color == EMPTY, we introduce a weaker kind of barriers
    * manually instead of searching for patterns.
    */
@@ -795,7 +979,7 @@
     find_influence_patterns(q, color);
   else
     find_influence_patterns(q, EMPTY);
-
+  
   for (i = 0; i < board_size; i++)
     for (j = 0; j < board_size; j++) {
       if (q->white_strength[i][j] > 0.0)
@@ -929,19 +1113,58 @@
   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 = f->sections * ((x - f->range_lowerbound)
+                       /(f->range_upperbound - f->range_lowerbound));
+    i = ratio;
+    diff = ratio - ((float)i);
+    return (diff*f->values[i] + (1-diff)* f->values[i+1]);
+  }
+}
+
+struct interpolation_data territory_correction = 
+  { 5, (float) 0.0, 15.0, {0.0, 0.3, 0.55, 0.75, 0.9, 1.0}};
+
 static void
 new_value_territory(struct influence_data *q)
 {
   int i, j;
+  float first_guess[MAX_BOARD][MAX_BOARD];
+  int k;
+
+  /* First loop: guess territory directly from influence. */
   for (i = 0; i < board_size; i++)
     for (j = 0; j < board_size; j++) {
-      q->territory_value[i][j] = 0.0;
+      first_guess[i][j] = 0.0;
 
       if (q->p[i][j] == EMPTY
          || (q->black_strength[i][j] == 0 && q->white_strength[i][j] == 0)) {
         float diff = ( q->white_influence[i][j] - q->black_influence[i][j] )
                     /( q->white_influence[i][j] + q->black_influence[i][j] );
-        q->territory_value[i][j] = diff * diff * diff;
+        first_guess[i][j] = diff * diff * diff;
+        first_guess[i][j] *= interpolate(&territory_correction,
+                                         gg_max(q->black_influence[i][j],
+                                                q->white_influence[i][j]));
+
        /* Dead stone, upgrade to territory. Notice that this is not
          * the point for a prisoner, which is added later. Instead
          * this is to make sure that the vertex is not regarded as
@@ -949,10 +1172,45 @@
          * degradation below may over-rule this decision.
         */
        if (BOARD(i, j) == BLACK)
-         q->territory_value[i][j] = 1.0;
+         first_guess[i][j] = 1.0;
        else if (BOARD(i, j) == WHITE)
-         q->territory_value[i][j] = -1.0;
+         first_guess[i][j] = -1.0;
+      }
+      q->territory_value[i][j] = first_guess[i][j];
+    }
+
+  /* Second loop: Correct according to neighbour vertices, then look for
+   * non-territory patterns and add prisoners.
+   */
+  for (i = 0; i < board_size; i++)
+    for (j = 0; j < board_size; j++) {
+      if (q->p[i][j] == EMPTY) {
+        for (k = 0; k < 4; k++) {
+          if (!ON_BOARD2(i+deltai[k],j+deltaj[k]))
+            continue;
+          if (q->territory_value[i][j] > 0.0) {
+            /* White territory. */
+            if (q->p[i+deltai[k]][j+deltaj[k]] != WHITE)
+              q->territory_value[i][j]
+                = gg_max(0, gg_min(q->territory_value[i][j],
+                                   first_guess[i+deltai[k]][j+deltaj[k]]));
+          }
+          else {
+            /* Black territory. */
+            if (q->p[i+deltai[k]][j+deltaj[k]] != BLACK)
+              q->territory_value[i][j]
+                = gg_min(0, gg_max(q->territory_value[i][j],
+                                   first_guess[i+deltai[k]][j+deltaj[k]]));
+          }
+        }
+      }
+    }
 
+  /* Third loop: Nonterritory patterns, points for prisoners. */
+  for (i = 0; i < board_size; i++)
+    for (j = 0; j < board_size; j++) {
+      if (q->p[i][j] == EMPTY
+         || (q->black_strength[i][j] == 0 && q->white_strength[i][j] == 0)) {
        /* If marked as non-territory for the color currently owning
          * it, reset the territory value.
         */
@@ -1230,6 +1488,11 @@
     new_value_territory(&initial_influence);
   else
     value_territory(&initial_influence);
+  if ((printmoyo & PRINTMOYO_VALUE_TERRITORY)
+      && (printmoyo & PRINTMOYO_INITIAL_INFLUENCE))
+    print_influence_territory(&initial_influence,
+                              "territory (initial influence):\n");
+
   compute_influence(&initial_opposite_influence, color, -1, -1,
                    dragons_known, NULL, NULL);
   /* Invalidate information in move_influence. */
@@ -1238,8 +1501,10 @@
   influence_color = EMPTY;
   /* Clear delta_territory cache. */
   for (i = 0; i < board_size; i++)
-    for (j = 0; j < board_size; j++)
+    for (j = 0; j < board_size; j++) {
       delta_territory_cache[POS(i, j)] = NOT_COMPUTED;
+      followup_territory_cache[POS(i, j)] = NOT_COMPUTED;
+    }
 }
 
 /* Redo the segmentation of the initial influence. */
@@ -1250,6 +1515,68 @@
   segment_influence(&initial_opposite_influence);
 }
 
+/* Experimental influence: Compute a followup influence for the move at
+ * (m, n). Compute the territorial followup value.
+ */
+static void
+compute_followup_influence(int m, int n, int color,
+                           char saved_stones[BOARDMAX])
+{
+  int i, j;
+  memcpy(&followup_influence, &move_influence, sizeof(move_influence));
+ 
+  /* We mark the saved stones in the q->w array. */
+  for (i = 0; i < board_size; i++)
+    for (j = 0; j < board_size; j++) {
+      if (saved_stones[POS(i,j)]) 
+        followup_influence.w[i][j] = MARKED;
+      else
+        followup_influence.w[i][j] = UNMARKED;
+    }
+
+  /* Match B patterns for saved stones. */
+  matchpat(followup_influence_callback, color, &barrierspat_db, 
+           &followup_influence, NULL);
+ 
+  /* Clean the q->w array. */
+  for (i = 0; i < board_size; i++)
+    for (j = 0; j < board_size; j++)
+      followup_influence.w[i][j] = UNMARKED;
+  
+  /* It may happen that we have a low intensity influence source at a
+   * blocked intersection (due to an intrusion). Reset the
+   * permeability at this point.
+   */
+  for (i = 0; i < board_size; i++)
+    for (j = 0; j < board_size; j++) {
+      if (followup_influence.p[i][j] == EMPTY
+          && followup_influence.white_strength[i][j] > 0.0
+         && followup_influence.white_permeability[i][j] != 1.0) {
+       DEBUG(DEBUG_INFLUENCE, "  black block removed from %m\n", i, j);
+       followup_influence.white_permeability[i][j] = 1.0;
+      }
+      if (followup_influence.p[i][j] == EMPTY
+          && followup_influence.black_strength[i][j] > 0.0
+         && followup_influence.black_permeability[i][j] != 1.0) {
+       DEBUG(DEBUG_INFLUENCE, "  white block removed from %m\n", i, j);
+       followup_influence.black_permeability[i][j] = 1.0;
+      }
+    }
+  
+  /* Spread influence for new influence sources. */
+  add_marked_intrusions(&followup_influence, color);
+  for (i = 0; i < board_size; i++)
+    for (j = 0; j < board_size; j++)
+      if ((color == BLACK
+          && followup_influence.black_strength[i][j]
+             > move_influence.black_strength[i][j])
+          || (color == WHITE
+          && followup_influence.white_strength[i][j]
+             > move_influence.white_strength[i][j]))
+        accumulate_influence(&followup_influence, i, j, color);
+
+}
+
 /* Let color play at (m, n) and compute the influence after this move,
  * assuming that the other color is in turn to move next.
  */
@@ -1267,12 +1594,26 @@
     increase_depth_values();
     compute_influence(&move_influence, OTHER_COLOR(color), m, n, 1,
                      NULL, saved_stones);
+    if (experimental_influence)
+      compute_followup_influence(m, n, color, saved_stones);
     decrease_depth_values();
     popgo();
-    if (experimental_influence)
+    if (experimental_influence) {
       new_value_territory(&move_influence);
+      new_value_territory(&followup_influence);
+    }
     else
       value_territory(&move_influence);
+    if (m == (board_size - 19) + debug_influence_i
+         && n == debug_influence_j && m >= 0) {
+      print_influence_territory(&move_influence, "territory (after move):\n");
+      if (experimental_influence) {
+        print_influence(&followup_influence, "followup influence");
+        if (printmoyo & PRINTMOYO_VALUE_TERRITORY)
+          print_influence_territory(&followup_influence,
+                                    "territory (followup):\n");
+      }
+    }
   }
   else {
     gprintf("Computing influence for illegal move %m (move number %d)\n",
@@ -1318,10 +1659,10 @@
   if (0 && (debug & DEBUG_ESCAPE) && verbose > 0) {
     print_numeric_influence(&escape_influence,
                            escape_influence.white_influence,
-                           "%3.0f", 1, 1);
+                           "%3.0f", 3, 1);
     print_numeric_influence(&escape_influence,
                            escape_influence.black_influence,
-                           "%3.0f", 1, 1);
+                           "%3.0f", 3, 1);
   }    
 }
 
@@ -1358,14 +1699,24 @@
 
 /* Compute the difference in territory made by a move by color at (pos).
  * This also includes the changes in moyo and area.
+ * In experimental-influence mode, followup_value must not be a NULL
+ * pointer, and the followup_value will be returned there.
  */
 float
-influence_delta_territory(int pos, int color, char saved_stones[BOARDMAX])
+influence_delta_territory(int pos, int color, char saved_stones[BOARDMAX],
+                          float *followup_value)
 {
   int i, j;
   float delta = 0.0;
-  if (delta_territory_cache[pos] != NOT_COMPUTED)
+  float followup_delta = 0.0;
+  if (delta_territory_cache[pos] != NOT_COMPUTED) {
+    if (experimental_influence) {
+      gg_assert(followup_territory_cache[pos] != NOT_COMPUTED);
+      gg_assert(followup_value != NULL);
+      *followup_value = followup_territory_cache[pos];
+    }
     return delta_territory_cache[pos];
+  }
   if (0)
     gprintf("influence_delta_territory for %1m %s = ", pos,
            color_to_string(color));
@@ -1375,23 +1726,34 @@
     for (j = 0; j < board_size; j++) {
       float new_value = move_influence.territory_value[i][j];
       float old_value = initial_influence.territory_value[i][j];
+      float followup_value = 0.0;
+      if (experimental_influence)
+        followup_value = followup_influence.territory_value[i][j];
       /* Negate values if we are black. */
       if (color == BLACK) {
        new_value = -new_value;
        old_value = -old_value;
+        if (experimental_influence)
+          followup_value = -followup_value;
       }
       
-      if (( new_value - old_value > 0.01)
-          || ( old_value - new_value > 0.01)) {
+      if (( new_value - old_value > 0.02)
+          || ( old_value - new_value > 0.02)) 
        DEBUG(DEBUG_TERRITORY, "  %1m:   - %m territory change %f (%f -> %f)\n",
                pos, i, j, new_value - old_value, old_value, new_value);
-       delta += new_value - old_value;
-      }
+      delta += new_value - old_value;
+      if (experimental_influence)
+        followup_delta += followup_value - new_value;
     }
   
   if (0)
     gprintf("%f\n", delta);
   delta_territory_cache[pos] = delta;
+  if (experimental_influence) {
+    gg_assert(followup_value != NULL);
+    followup_territory_cache[pos] = followup_delta;
+    *followup_value = followup_delta;
+  }
   
   return delta;
 }
@@ -1552,13 +1914,6 @@
   compute_initial_influence(color, dragons_known);
   print_influence(&initial_influence, (dragons_known ? "dragons_known"
                                       : "dragons_unknown"));
-  if ((printmoyo & PRINTMOYO_VALUE_TERRITORY)
-       && dragons_known) {
-    fprintf(stderr, "territory valuation (initial influence):\n");
-    print_numeric_influence(&initial_influence,
-                            initial_influence.territory_value,
-                            "%1.2f", 4, 0);
-  }
 
   print_influence(&initial_opposite_influence,
                  dragons_known ? "dragons_known, opposite color"
@@ -1575,12 +1930,6 @@
   compute_move_influence(I(pos), J(pos), color, saved_stones);
   print_influence(&move_influence, "after move, dragons known");
 
-  if (printmoyo & PRINTMOYO_VALUE_TERRITORY) {
-    fprintf(stderr, "territory valuation (after move):\n");
-    print_numeric_influence(&initial_influence,
-                            initial_influence.territory_value,
-                            "%1.2f", 4, 0);
-  }
 }
 
 /* Print influence for debugging purposes. */
@@ -1608,22 +1957,28 @@
   if (printmoyo & PRINTMOYO_STRENGTH) {
     /* Print the strength values. */
     fprintf(stderr, "white strength:\n");
-    print_numeric_influence(q, q->white_strength, "%3.0f", 0, 1);
+    if (experimental_influence)
+      print_numeric_influence(q, q->white_strength, "%5.1f", 0, 0);
+    else
+      print_numeric_influence(q, q->white_strength, "%3.0f", 0, 1);
     fprintf(stderr, "black strength:\n");
-    print_numeric_influence(q, q->black_strength, "%3.0f", 0, 1);
+    if (experimental_influence)
+      print_numeric_influence(q, q->black_strength, "%5.1f", 0, 0);
+    else
+      print_numeric_influence(q, q->black_strength, "%3.0f", 0, 1);
   }
 
   if (printmoyo & PRINTMOYO_NUMERIC_INFLUENCE) {
     /* Print the white influence values. */
     fprintf(stderr, "white influence (%s):\n", info_string);
     if (experimental_influence)
-      print_numeric_influence(q, q->white_influence, "%3.2f", 6, 0);
+      print_numeric_influence(q, q->white_influence, "%5.1f", 5, 0);
     else
       print_numeric_influence(q, q->white_influence, "%3.0f", 3, 1);
     /* Print the black influence values. */
     fprintf(stderr, "black influence (%s):\n", info_string);
     if (experimental_influence)
-      print_numeric_influence(q, q->black_influence, "%3.2f", 6, 1);
+      print_numeric_influence(q, q->black_influence, "%5.1f", 5, 0);
     else
       print_numeric_influence(q, q->black_influence, "%3.0f", 3, 1);
   }
@@ -1632,9 +1987,21 @@
     fprintf(stderr, "influence regions (%s):\n", info_string);
     print_influence_areas(q);
   }
+}
 
+/* Print the numerical territory valuation. */
+static void
+print_influence_territory(struct influence_data *q, const char *info_string)
+{
+  fprintf(stderr, info_string);
+  print_numeric_influence(q, q->territory_value, "%5.2f", 5, 0);
 }
 
+
+char black_stone[8][10] = { "X", " X", "  X", "  X ", "  X  ", "   X  ",
+                         "   X   ", "    X   "};
+char white_stone[8][10] = { "O", " O", "  O", "  O ", "  O  ", "   O  ",
+                         "   O   ", "    O   "};
 /* Print numeric influence values.
  * If draw_stones is not zero, then it denotes the lenght (in characters)
  * of the numeric output fields.
@@ -1647,17 +2014,12 @@
                        int mark_epsilon)
 {
   int i, j;
-  char spaces[10] = "";
-  if (draw_stones) {
-    for (i = 0; i < draw_stones; i++)
-      strcat(spaces, " ");
-  }
   for (i = 0; i < board_size; i++) {
     for (j = 0; j < board_size; j++) {
       if (draw_stones && q->p[i][j] == WHITE)
-       fprintf(stderr, "  O ");
+       fprintf(stderr, white_stone[draw_stones]);
       else if (draw_stones && q->p[i][j] == BLACK)
-       fprintf(stderr, "  X ");
+       fprintf(stderr, black_stone[draw_stones]);
       else {
        if (mark_epsilon && values[i][j] > 0.0 && values[i][j] < 1.0)
          fprintf(stderr, "eps");
Index: engine/influence.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/influence.h,v
retrieving revision 1.5
diff -u -r1.5 influence.h
--- engine/influence.h  14 Nov 2001 19:16:28 -0000      1.5
+++ engine/influence.h  27 Jan 2002 11:57:29 -0000
@@ -32,9 +32,11 @@
 
 /* default attenuation coefficient. */
 #define DEFAULT_ATTENUATION 3.0
+#define EXP_DEFAULT_ATTENUATION 2.1
 
 /* Extra damping coefficient for spreading influence diagonally. */
 #define DIAGONAL_DAMPING 2.0
+#define EXP_DIAGONAL_DAMPING 1.5
 
 /* Default strength of the influence from a stone. May be lowered if
  * it is unsafe.
@@ -76,6 +78,16 @@
  */ 
 #define MAX_REGIONS (3*MAX_BOARD*MAX_BOARD + 1)
 
+#define MAX_INTRUSIONS (MAX_BOARD * MAX_BOARD)
+
+struct intrusion_data
+{
+  int source_pos;      /* Stone from which intrusion originates.*/
+  int strength_pos;     /* Position of the intrusion influence soure. */
+  float strength;
+  float attenuation;
+};
+
 struct influence_data
 {
   float white_influence[MAX_BOARD][MAX_BOARD]; /* Accumulated influence. */
@@ -103,6 +115,9 @@
   float w[MAX_BOARD][MAX_BOARD];         /* Working area. */
   int queuei[MAX_BOARD * MAX_BOARD];     /* Points receiving influence. */
   int queuej[MAX_BOARD * MAX_BOARD];
+
+  int intrusion_counter;
+  struct intrusion_data intrusions[MAX_INTRUSIONS];
 };
 
 /* Typedef for pointer to either of the functions whose_territory(),
Index: engine/liberty.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/liberty.h,v
retrieving revision 1.71
diff -u -r1.71 liberty.h
--- engine/liberty.h    22 Jan 2002 14:57:04 -0000      1.71
+++ engine/liberty.h    27 Jan 2002 11:57:34 -0000
@@ -483,7 +483,8 @@
 void compute_initial_influence(int color, int dragons_known);
 void resegment_initial_influence(void);
 float influence_delta_territory(int pos, int color,
-                               char saved_stones[BOARDMAX]);
+                               char saved_stones[BOARDMAX],
+                                float *followup_value);
 int influence_territory_color(int pos);
 int influence_moyo_color(int pos);
 int influence_moyo_color_opposite(int pos);
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 11:57:35 -0000
@@ -105,6 +105,8 @@
   int numneg_shape;        /* Number of negative contributions to shape */
 
   float followup_value;    /* Value of followup move (our sente). */
+  float infl_followup_value;  /* Followup value of move as reported by
+                                 experimental influence. */
   float reverse_followup_value;        /* Value of opponents followup move
                                   (reverse sente). */
   float secondary_value;   /* Secondary move value. */
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 11:57:45 -0000
@@ -1523,7 +1523,11 @@
   
   /* tm added move_safety check (3.1.22) (see trevorc:880) */
   if (does_block && move[pos].move_safety) {
-    this_value = influence_delta_territory(pos, color, saved_stones);
+    if (experimental_influence)
+      this_value = influence_delta_territory(pos, color, saved_stones,
+                                             &move[pos].infl_followup_value);
+    else
+      this_value = influence_delta_territory(pos, color, saved_stones, NULL);
     if (this_value != 0.0)
       TRACE("  %1m: %f - change in territory\n", pos, this_value);
     else
@@ -2081,6 +2085,15 @@
 
   if (tot_value > 0.0) {
     int c;
+    float followup_value;
+    if (experimental_influence) {
+      followup_value = move[pos].followup_value
+                       + move[pos].infl_followup_value;
+      TRACE("  %1m:   %f - total followup value, added %f as territorial 
followup\n",
+            pos, followup_value, move[pos].infl_followup_value);
+    }
+    else
+      followup_value = move[pos].followup_value;
     
     /* In the endgame, there are a few situations where the value can
      * be 0 points + followup.  But we want to take the intersections first
@@ -2096,10 +2109,10 @@
       /* We adjust the value according to followup and reverse followup
        * values.
        */
-      contribution = gg_min(gg_min(0.5 * move[pos].followup_value
+      contribution = gg_min(gg_min(0.5 * followup_value
                                   + 0.5 * move[pos].reverse_followup_value,
                                   1.0 * tot_value
-                                  + move[pos].followup_value),
+                                  + followup_value),
                            1.1 * tot_value
                            + move[pos].reverse_followup_value);
       tot_value += contribution;
@@ -2113,7 +2126,7 @@
       
       if (contribution != 0.0) {
        TRACE("  %1m: %f - added due to followup (%f) and reverse followup 
values (%f)\n",
-              pos, contribution, move[pos].followup_value,
+              pos, contribution, followup_value,
               move[pos].reverse_followup_value);
       }
 
@@ -2122,7 +2135,7 @@
        * additional contribution for later access.
        */
       move[pos].additional_ko_value =
-       move[pos].followup_value 
+       followup_value 
        + move[pos].reverse_followup_value 
        - (tot_value - old_tot_value);
 
Index: patterns/barriers.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/barriers.db,v
retrieving revision 1.21
diff -u -r1.21 barriers.db
--- patterns/barriers.db        23 Jan 2002 19:12:36 -0000      1.21
+++ patterns/barriers.db        27 Jan 2002 11:57:47 -0000
@@ -24,20 +24,20 @@
 #
 #  ? - don't care
 #  . - empty
-#  O - color of dragon looking for escape
+#  O - color to move
 #  X - opposite color of O
 #  o - O or empty
 #  x - X or empty
 #  , - point which influence can't pass through
 #
 #
-# Two different classes of patterns are used here.
+# Four different classes of patterns are used here.
 #
-#  C - Territorial connection, stopping opponent influence from
-#      passing through.
-#  E - Enhance influence. By convention, the influence is enhanced
-#      in the eastwards direction. The value of the pattern decides
-#      the level of influence enhancement.
+#  A - Patterns stopping O influence
+#  D - Patterns stopping X influence
+#  B - Intrusions (where O can intrude into X'x territory)
+#  t - Nonterritory patterns indicating points where one color cannot
+#      get territory
 
 Pattern Barrier1
 
@@ -927,13 +927,13 @@
 :8,B,value(30)
 
 
-Pattern Intrusion7
+Pattern Intrusion7a
 
 OX.
 .!!
 X.x
 
-:8,B,value(30)
+:8,BFY,value(30)
 
 OA.
 .!!
@@ -942,6 +942,21 @@
 ;lib(A)==2
 
 
+Pattern Intrusion7b
+
+OX
+!!
+
+
+:8,BY,value(30)
+
+OA
+ba
+
+
+;oplay_attack_either(a,b,A,b);
+
+
 Pattern Intrusion8
 # ab 3.1.22 revised constraint (see territory valuation in 13x13:2)
 
@@ -1535,6 +1550,25 @@
 -----
 
 ;lib(a)>2
+
+Pattern Intrusion48
+# ab New pattern. (3.1.23)
+
+?X.
+...
+O.!
+..X
+
+:8,B,value(30)
+
+
+# .X.
+# fce
+# Oba
+# .dX
+# 
+# ;oplay_attack(a,b,c,d,e,f,f)
+
 
 
 Pattern Nonterritory1
Index: patterns/influence.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/influence.db,v
retrieving revision 1.6
diff -u -r1.6 influence.db
--- patterns/influence.db       23 Jan 2002 19:12:36 -0000      1.6
+++ patterns/influence.db       27 Jan 2002 11:57:50 -0000
@@ -33,9 +33,8 @@
 #
 # Two different classes of patterns are used here.
 #
-#  C - Territorial connection, stopping opponent influence from
-#      passing through.
 #  E - Enhance influence.
+#  I - Invasion points.
 
 Pattern Enhance1
 
Index: patterns/mkpat.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/mkpat.c,v
retrieving revision 1.46
diff -u -r1.46 mkpat.c
--- patterns/mkpat.c    25 Jan 2002 21:14:56 -0000      1.46
+++ patterns/mkpat.c    27 Jan 2002 11:57:57 -0000
@@ -946,6 +946,7 @@
          case 'U': pattern[patno].class |= CLASS_U; break;
          case 'W': pattern[patno].class |= CLASS_W; break;
          case 'F': pattern[patno].class |= CLASS_F; break;
+         case 'Y': pattern[patno].class |= CLASS_Y; break;
          case '-': break;
          default:
            if (!isgraph((int) *p))
Index: patterns/patterns.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/patterns.h,v
retrieving revision 1.17
diff -u -r1.17 patterns.h
--- patterns/patterns.h 8 Jan 2002 22:32:55 -0000       1.17
+++ patterns/patterns.h 27 Jan 2002 11:57:59 -0000
@@ -157,7 +157,12 @@
 #define CLASS_U 0x100000 /* very urgent joseki move */
 #define CLASS_T 0x200000 /* joseki trick move */
 #define CLASS_W 0x400000 /* worthwhile threat move */
-#define CLASS_F 0x800000 /* a fuseki pattern */
+#define CLASS_F 0x800000 /* for joseki moves: a fuseki pattern; for CLASS_Y
+                          * patterns: pattern only for standard influence
+                          * FIXME: This is ugly. */
+#define CLASS_Y 0x80000000 /* a pattern that should only be matched for 
+                            * either standard or experimental influence
+                            * (CLASS_F indicating which one). */
 
 /* Collection of the classes inducing move reasons. */
 #define CLASS_MOVE_REASONS (CLASS_C | CLASS_B | CLASS_b | \




reply via email to

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