gnugo-devel
[Top][All Lists]
Advanced

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

[gnugo-devel] pattern reimplementation


From: Paul Pogonyshev
Subject: [gnugo-devel] pattern reimplementation
Date: Sat, 28 Feb 2004 01:10:40 +0200
User-agent: KMail/1.6.50

This patch makes pattern attributes (value, shape, followup etc.)
to be stored in separate lists, not in the `pattern' structure
itself.  There are three main reasonings behind this change:

- It allows adding of many new attributes without blowing the
  `pattern' structure up.

- It frees up flag bits in `class' field, which is already
  overflown actually:

#define CLASS_N 0x01000000   /* antisuji move (do _not_ play) */
...
#define VALUE_MINVAL       0x01000000 /* pattern has a minimum value */

  The patch retires VALUE_* flags.

- Maybe most important, it allows storing several attributes of
  the same type for a single pattern.  Not useful currently, but
  I have plans for using this feature.

In any case, I consider this approach more flexible.  It does
complicate the code that uses pattern attributes (currently, only
`shape.c'), but not significantly.  BTW, I cleaned `shape.c' by moving
common code from shapes_callback() and joseki_callback() to a new
function named handle_joseki_patterns().

Now about my plans.  I have started (basically with this patch)
implementing a new extension to Owl.  It is a sort of run-time threat
combinator which, given a set of matched threat patterns, would be
able to generate owl move reasons like "double threat to create an
eye" or "threatens to capture D6 and to escape" or "secures an eye and
threatens another (i.e. secures the eye in sente)".  I believe that
when implemented, it will make Owl reading significantly more
efficient.

This doesn't mean that current (fixed-value) patterns will get
retired.  Rather, I think co-existence of current patterns (for many
things that cannot be explained in double/multiple threat/goal terms)
and new "combinable" patterns might make Owl much better at life and
death than now.

Threats/goals will be stored as pattern attribute with two fields:
type and target (that's why the currently unused `offset' field).
Knowing targets is important because having matched two patterns that
inform about threat to create an eye at say C2 and C4 is not the same
as having matched two patterns which both say about a threat to create
an eye at C2.

I'm regressing the patch now.  So far there are no node counter
changes (and of course, no result changes).

Paul



Index: engine/shapes.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/shapes.c,v
retrieving revision 1.50
diff -u -p -r1.50 shapes.c
--- engine/shapes.c     24 Jan 2004 04:04:56 -0000      1.50
+++ engine/shapes.c     27 Feb 2004 21:21:50 -0000
@@ -39,10 +39,161 @@
 #define t_VALUE 16.0
 
 
+/* Take care of joseki patterns. */
+static void
+handle_joseki_patterns(struct pattern_attribute *attributes,
+                      unsigned int class, int move,
+                      int my_dragons[MAX_DRAGONS_PER_PATTERN],
+                      int my_ndragons,
+                      int your_dragons[MAX_DRAGONS_PER_PATTERN],
+                      int your_ndragons)
+{
+  struct pattern_attribute *attribute;
+
+  /* Pattern class J, joseki standard move. Add expand territory and
+   * moyo, and require the value at least J_value.
+   */
+  if (class & CLASS_J) {
+    TRACE("...joseki standard move\n");
+    add_expand_territory_move(move);
+    TRACE("...expands territory\n");
+    add_expand_moyo_move(move);
+    TRACE("...expands moyo\n");
+    set_minimum_move_value(move, J_VALUE);
+    TRACE("... minimum move value %f\n", J_VALUE);
+  }
+
+  /* Class `j' and `t' patterns are treated similarly. */
+  if (class & (CLASS_j | CLASS_t)) {
+    float min_value;
+    float shape_value = 0.0;
+
+    if (class & CLASS_j) {
+      min_value = j_VALUE;
+      TRACE("...less urgent joseki move\n");
+      add_expand_territory_move(move);
+      TRACE("...expands territory\n");
+      add_expand_moyo_move(move);
+      TRACE("...expands moyo\n");
+    }
+    else {
+      min_value = t_VALUE;
+      TRACE("...minor joseki move\n");
+    }
+
+    /* Board size modification. */
+    min_value *= board_size / 19.0;
+
+    for (attribute = attributes; attribute->type != LAST_ATTRIBUTE;
+        attribute++) {
+      if (attribute->type == SHAPE) {
+       shape_value = attribute->value;
+       min_value *= (1 + 0.01 * shape_value);
+       break;
+      }
+    }
+
+    if ((board_size >= 17) && (class & CLASS_F)) {
+      /* Otherwise, `j' and `t' patterns not of CLASS_F would get
+       * preferred in value_move_reasons().
+       */
+      min_value *= 1.005;
+
+      set_maximum_move_value(move, min_value);
+      scale_randomness(move, 5.0);
+      TRACE("...move value %f (shape %f)\n", min_value, shape_value);
+    }
+    else
+      TRACE("...minimum move value %f (shape %f)\n", min_value, shape_value);
+
+    set_minimum_move_value(move, min_value);
+  }
+
+  /* Pattern class U, very urgent joseki move. Add strategical defense
+   * and attack, plus a shape bonus of 15 and a minimum value of 40.
+   */
+  if (class & CLASS_U) {
+    int k;
+
+    TRACE("...joseki urgent move\n");
+    for (k = 0; k < my_ndragons; k++) {
+      add_strategical_defense_move(move, my_dragons[k]);
+      TRACE("...strategical defense of %1m\n", my_dragons[k]);
+    }
+    for (k = 0; k < your_ndragons; k++) {
+      add_strategical_attack_move(move, your_dragons[k]);
+      TRACE("...strategical attack on %1m\n", your_dragons[k]);
+    }
+    add_shape_value(move, 15);
+    TRACE("...shape value 15\n");
+    set_minimum_move_value(move, U_VALUE);
+    TRACE("...(min) move value %f\n", U_VALUE);
+  }
+
+  /* Pattern class T, joseki trick move. For the moment we never play
+   * these.
+   */
+  if (class & CLASS_T) {
+    TRACE("...joseki trick move\n");
+    add_antisuji_move(move);
+    TRACE("...antisuji\n");
+  }
+
+  for (attribute = attributes; attribute->type != LAST_ATTRIBUTE;
+       attribute++) {
+    switch (attribute->type) {
+    case MIN_VALUE:
+      set_minimum_move_value(move, attribute->value);
+      TRACE("...(min) move value %f\n", attribute->value);
+      break;
+
+    case MAX_VALUE:
+      set_maximum_move_value(move, attribute->value);
+      TRACE("...max move value %f\n", attribute->value);
+      break;
+
+    case MIN_TERRITORY:
+      set_minimum_territorial_value(move, attribute->value);
+      TRACE("...(min) territorial value %f\n", attribute->value);
+      break;
+
+    case MAX_TERRITORY:
+      set_maximum_territorial_value(move, attribute->value);
+      TRACE("...max territorial value %f\n", attribute->value);
+      break;
+
+    case SHAPE:
+      /* For class `j' and `t' patterns shape value has been counted
+       * already.
+       */
+      if (!(class & (CLASS_j | CLASS_t))) {
+       add_shape_value(move, attribute->value);
+       TRACE("...shape value %f\n", attribute->value);
+      }
+
+      break;
+
+    case FOLLOWUP:
+      add_followup_value(move, attribute->value);
+      TRACE("...followup value %f\n", attribute->value);
+      break;
+
+    case REVERSE_FOLLOWUP:
+      add_reverse_followup_value(move, attribute->value);
+      TRACE("...reverse followup value %f\n", attribute->value);
+      break;
+
+    default:
+      /* Must not happen. */
+      gg_assert(0);
+    }
+  }
+}
+
+
 /* 
  * This callback is invoked for each matched pattern.
  */
-
 static void
 shapes_callback(int anchor, int color, struct pattern *pattern, int ll,
                void *data)
@@ -202,7 +353,8 @@ shapes_callback(int anchor, int color, s
   if (!pattern->helper
       && !allpats
       && !(pattern->autohelper_flag & HAVE_ACTION)
-      && !(class & (CLASS_MOVE_REASONS | CLASS_MOVE_VALUES)))
+      && !(class & CLASS_MOVE_REASONS)
+      && pattern->attributes->type == LAST_ATTRIBUTE)
     return;
   
   /* For sacrifice patterns, the survival of the stone to be played is
@@ -355,160 +507,21 @@ shapes_callback(int anchor, int color, s
     }
   }
 
-  /* Pattern class J, joseki standard move. Add expand territory and
-   * moyo, and require the value at least J_value.
-   */
-  if (class & CLASS_J) {
-    TRACE("...joseki standard move\n");
-    add_expand_territory_move(move);
-    TRACE("...expands territory\n");
-    add_expand_moyo_move(move);
-    TRACE("...expands moyo\n");
-    set_minimum_move_value(move, J_VALUE);
-    TRACE("... minimum move value %f\n", J_VALUE);
-  }
-
-  /* Pattern class j, less urgent joseki move. Add expand territory and
-   * moyo, set a minimum value of j_VALUE. If it is a fuseki pattern, set also
-   * the maximum value to j_VALUE.
-   */
-  if (class & CLASS_j) {
-    float min_value = j_VALUE;
-    TRACE("...less urgent joseki move\n");
-    add_expand_territory_move(move);
-    TRACE("...expands territory\n");
-    add_expand_moyo_move(move);
-    TRACE("...expands moyo\n");
-
-    /* Board size modification. */
-    min_value *= board_size / 19.0;
-    
-    if (class & VALUE_SHAPE) {
-      min_value *= (1 + 0.01 * pattern->shape);
-      class &= ~VALUE_SHAPE;
-    };
-
-    if ((board_size >= 17) && (class & CLASS_F)) {
-      min_value *= 1.005; /* Otherwise, j patterns not of CLASS_F would */
-                          /* get preferred in value_move_reasons */
-      set_maximum_move_value(move, min_value);
-      scale_randomness(move, 5.);
-      TRACE("...move value %f (shape %f)\n", min_value, pattern->shape);
-    }
-    else 
-      TRACE("...minimum move value %f (shape %f)\n",
-            min_value, pattern->shape);
-    set_minimum_move_value(move, min_value);
-  }
-
-  /* Pattern class t, minor joseki move (tenuki OK).
-   * Set the (min-)value at t_value
-   */
-  if (class & CLASS_t) {
-    float min_value = t_VALUE;
-    TRACE("...minor joseki move\n");
-    
-    /* Board size modification. */
-    min_value *= board_size / 19.0;
-    
-    if (class & VALUE_SHAPE) {
-      min_value *= (1 + 0.01 * pattern->shape);
-      class &= ~VALUE_SHAPE;
-    };
-    
-    if ((board_size >= 17) && (class & CLASS_F)) {
-      min_value *= 1.005; /* Otherwise, j patterns not of CLASS_F would */
-                          /* get preferred in value_move_reasons */
-      set_maximum_move_value(move, min_value);
-      scale_randomness(move, 5.);
-      TRACE("...move value %f (shape %f)\n", min_value, pattern->shape);
-    }
-    else
-      TRACE("...minimum move value %f (shape %f)\n",
-            min_value, pattern->shape);
-    set_minimum_move_value(move, min_value);
-  }
-
-  /* Pattern class U, very urgent joseki move. Add strategical defense
-   * and attack, plus a shape bonus of 15 and a minimum value of 40.
-   */
-  if (class & CLASS_U) {
-    TRACE("...joseki urgent move\n");
-    for (k = 0; k < my_ndragons; k++) {
-      add_strategical_defense_move(move, my_dragons[k]);
-      TRACE("...strategical defense of %1m\n", my_dragons[k]);
-    }
-    for (k = 0; k < your_ndragons; k++) {
-      add_strategical_attack_move(move, your_dragons[k]);
-      TRACE("...strategical attack on %1m\n", your_dragons[k]);
-    }
-    add_shape_value(move, 15);
-    TRACE("...shape value 15\n");
-    set_minimum_move_value(move, U_VALUE);
-    TRACE("...(min) move value %f\n", U_VALUE);
-  }
-
-  /* Pattern class T, joseki trick move. For the moment we never play
-   * these.
-   */
-  if (class & CLASS_T) {
-    TRACE("...joseki trick move\n");
-    add_antisuji_move(move);
-    TRACE("...antisuji\n");
-  }
-
   /* Pattern class W, worthwhile threat move. */
   if (class & CLASS_W) {
     TRACE("...worthwhile threat move\n");
     add_worthwhile_threat_move(move);
   }
 
-  /* Minimum move value specified. */
-  if (class & VALUE_MINVAL) {
-    set_minimum_move_value(move, pattern->value);
-    TRACE("...(min) move value %f\n", pattern->value);
-  }
-
-  /* Maximum move value specified. */
-  if (class & VALUE_MAXVAL) {
-    set_maximum_move_value(move, pattern->maxvalue);
-    TRACE("...max move value %f\n", pattern->maxvalue);
-  }
-
-  /* Minimum territorial value specified. */
-  if (class & VALUE_MINTERRITORY) {
-    set_minimum_territorial_value(move, pattern->minterritory);
-    TRACE("...(min) territorial value %f\n", pattern->minterritory);
-  }
-
-  /* Maximum territorial value specified. */
-  if (class & VALUE_MAXTERRITORY) {
-    set_maximum_territorial_value(move, pattern->maxterritory);
-    TRACE("...max territorial value %f\n", pattern->maxterritory);
-  }
-
-  /* Shape value specified. */
-  if (class & VALUE_SHAPE) {
-    add_shape_value(move, pattern->shape);
-    TRACE("...shape value %f\n", pattern->shape);
-  }
-
-  /* Followup value specified. */
-  if (class & VALUE_FOLLOWUP) {
-    add_followup_value(move, pattern->followup);
-    TRACE("...followup value %f\n", pattern->followup);
-  }
-
-  /* Reverse followup value specified. */
-  if (class & VALUE_REV_FOLLOWUP) {
-    add_reverse_followup_value(move, pattern->reverse_followup);
-    TRACE("...reverse followup value %f\n", pattern->reverse_followup);
-  }
+  handle_joseki_patterns(pattern->attributes, class, move,
+                        my_dragons, my_ndragons, your_dragons, your_ndragons);
 }
 
 
-/* This callback is invoked for each matched pattern from joseki database.
- * This function is just a copy of relevant parts of shapes_callback().
+/* This callback is invoked for each matched pattern from joseki
+ * database.  This function is just a copy of relevant parts of
+ * shapes_callback().  However, most of the common code resides in
+ * handle_joseki_patterns().
  */
 static void
 joseki_callback(int move, int color, struct corner_pattern *pattern,
@@ -591,117 +604,14 @@ joseki_callback(int move, int color, str
   if (pattern->autohelper_flag & HAVE_ACTION)
     pattern->autohelper(trans, move, color, 1);
 
-  /* Pattern class J, joseki standard move. Add expand territory and
-   * moyo, and require the value at least J_value.
-   */
-  if (class & CLASS_J) {
-    TRACE("...joseki standard move\n");
-    add_expand_territory_move(move);
-    TRACE("...expands territory\n");
-    add_expand_moyo_move(move);
-    TRACE("...expands moyo\n");
-    set_minimum_move_value(move, J_VALUE);
-    TRACE("... minimum move value %f\n", J_VALUE);
-  }
-
-  /* Pattern class j, less urgent joseki move. Add expand territory and
-   * moyo, set a minimum value of j_VALUE. If it is a fuseki pattern, set also
-   * the maximum value to j_VALUE.
-   */
-  if (class & CLASS_j) {
-    float min_value = j_VALUE;
-    TRACE("...less urgent joseki move\n");
-    add_expand_territory_move(move);
-    TRACE("...expands territory\n");
-    add_expand_moyo_move(move);
-    TRACE("...expands moyo\n");
-
-    /* Board size modification. */
-    min_value *= board_size / 19.0;
-
-    if (class & VALUE_SHAPE) {
-      min_value *= (1 + 0.01 * pattern->shape);
-      class &= ~VALUE_SHAPE;
-    };
-
-    if (board_size >= 17) {
-      min_value *= 1.005; /* Otherwise, j patterns not of CLASS_F would */
-                          /* get preferred in value_move_reasons(). */
-      set_maximum_move_value(move, min_value);
-      scale_randomness(move, 5.);
-      TRACE("...move value %f (shape %f)\n", min_value, pattern->shape);
-    }
-    else
-      TRACE("...minimum move value %f (shape %f)\n",
-            min_value, pattern->shape);
-    set_minimum_move_value(move, min_value);
-  }
-
-  /* Pattern class t, minor joseki move (tenuki OK).
-   * Set the (min-)value at t_value
-   */
-  if (class & CLASS_t) {
-    float min_value = t_VALUE;
-    TRACE("...minor joseki move\n");
-
-    /* Board size modification. */
-    min_value *= board_size / 19.0;
-
-    if (class & VALUE_SHAPE) {
-      min_value *= (1 + 0.01 * pattern->shape);
-      class &= ~VALUE_SHAPE;
-    };
-
-    if ((board_size >= 17) && (class & CLASS_F)) {
-      min_value *= 1.005; /* Otherwise, j patterns not of CLASS_F would */
-                          /* get preferred in value_move_reasons */
-      set_maximum_move_value(move, min_value);
-      scale_randomness(move, 5.);
-      TRACE("...move value %f (shape %f)\n", min_value, pattern->shape);
-    }
-    else
-      TRACE("...minimum move value %f (shape %f)\n",
-            min_value, pattern->shape);
-    set_minimum_move_value(move, min_value);
-  }
-
-  /* Pattern class U, very urgent joseki move. Add strategical defense
-   * and attack, plus a shape bonus of 15 and a minimum value of 40.
-   */
-  if (class & CLASS_U) {
-    TRACE("...joseki urgent move\n");
-    for (k = 0; k < my_ndragons; k++) {
-      add_strategical_defense_move(move, my_dragons[k]);
-      TRACE("...strategical defense of %1m\n", my_dragons[k]);
-    }
-    for (k = 0; k < your_ndragons; k++) {
-      add_strategical_attack_move(move, your_dragons[k]);
-      TRACE("...strategical attack on %1m\n", your_dragons[k]);
-    }
-    add_shape_value(move, 15);
-    TRACE("...shape value 15\n");
-    set_minimum_move_value(move, U_VALUE);
-    TRACE("...(min) move value %f\n", U_VALUE);
-  }
-
-  /* Pattern class T, joseki trick move. For the moment we never play these. */
-  if (class & CLASS_T) {
-    TRACE("...joseki trick move\n");
-    add_antisuji_move(move);
-    TRACE("...antisuji\n");
-  }
-
   /* Pattern class N, antisuji move. */
   if (class & CLASS_N) {
     TRACE("...antisuji move\n");
     add_antisuji_move(move);
   }
 
-  /* Shape value specified. */
-  if (class & VALUE_SHAPE) {
-    add_shape_value(move, pattern->shape);
-    TRACE("...shape value %f\n", pattern->shape);
-  }
+  handle_joseki_patterns(pattern->attributes, class, move,
+                        my_dragons, my_ndragons, your_dragons, your_ndragons);
 }
 
 
Index: patterns/aa_attackpats.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/aa_attackpats.db,v
retrieving revision 1.20
diff -u -p -r1.20 aa_attackpats.db
--- patterns/aa_attackpats.db   24 Jan 2004 04:04:56 -0000      1.20
+++ patterns/aa_attackpats.db   27 Feb 2004 21:21:50 -0000
@@ -62,6 +62,8 @@
 #########################################################
 
 
+attribute_map none
+
 goal_elements Xx
 callback_data X
 
Index: patterns/attack.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/attack.db,v
retrieving revision 1.13
diff -u -p -r1.13 attack.db
--- patterns/attack.db  24 Jan 2004 04:04:56 -0000      1.13
+++ patterns/attack.db  27 Feb 2004 21:21:52 -0000
@@ -44,6 +44,8 @@
 ##################################################################
 
 
+attribute_map none
+
 goal_elements none
 callback_data X
 
Index: patterns/barriers.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/barriers.db,v
retrieving revision 1.62
diff -u -p -r1.62 barriers.db
--- patterns/barriers.db        24 Jan 2004 04:04:56 -0000      1.62
+++ patterns/barriers.db        27 Feb 2004 21:21:53 -0000
@@ -55,6 +55,8 @@
 # documentation for explanation and influence.c for details.
 
 
+attribute_map value_only
+
 goal_elements none
 callback_data XO,!
 
Index: patterns/conn.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/conn.db,v
retrieving revision 1.40
diff -u -p -r1.40 conn.db
--- patterns/conn.db    24 Jan 2004 04:04:56 -0000      1.40
+++ patterns/conn.db    27 Feb 2004 21:21:55 -0000
@@ -65,6 +65,8 @@
 ###################################
 
 
+attribute_map none
+
 goal_elements none
 # callback_data is dependent on pattern class in this database
 
Index: patterns/defense.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/defense.db,v
retrieving revision 1.14
diff -u -p -r1.14 defense.db
--- patterns/defense.db 24 Jan 2004 04:04:56 -0000      1.14
+++ patterns/defense.db 27 Feb 2004 21:21:55 -0000
@@ -44,6 +44,8 @@
 ##################################################################
 
 
+attribute_map none
+
 goal_elements none
 callback_data O
 
Index: patterns/endgame.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/endgame.db,v
retrieving revision 1.59
diff -u -p -r1.59 endgame.db
--- patterns/endgame.db 24 Jan 2004 04:04:56 -0000      1.59
+++ patterns/endgame.db 27 Feb 2004 21:21:58 -0000
@@ -102,6 +102,8 @@
 ######################################################################
 
 
+attribute_map general
+
 goal_elements none
 # Several patterns here have a or d class, so we need these elements.
 callback_data XOxo
Index: patterns/extract_fuseki.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/extract_fuseki.c,v
retrieving revision 1.21
diff -u -p -r1.21 extract_fuseki.c
--- patterns/extract_fuseki.c   25 Jan 2004 21:35:37 -0000      1.21
+++ patterns/extract_fuseki.c   27 Feb 2004 21:22:00 -0000
@@ -1204,7 +1204,9 @@ main(int argc, char *argv[])
      */
     generate_patterns();
     fprintf(stderr, "generate OK.\n");
-    
+
+    printf("attribute_map value_only\n\n\n");
+
     /* Write the patterns to stdout in patterns.db format.
      */
     print_patterns();
Index: patterns/fuseki.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/fuseki.db,v
retrieving revision 1.37
diff -u -p -r1.37 fuseki.db
--- patterns/fuseki.db  24 Jan 2004 04:04:56 -0000      1.37
+++ patterns/fuseki.db  27 Feb 2004 21:22:03 -0000
@@ -94,6 +94,8 @@
 ######################################################################
 
 
+attribute_map general
+
 goal_elements none
 callback_data XOxo
 
Index: patterns/fuseki13.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/fuseki13.db,v
retrieving revision 1.8
diff -u -p -r1.8 fuseki13.db
--- patterns/fuseki13.db        24 Jan 2004 04:04:56 -0000      1.8
+++ patterns/fuseki13.db        27 Feb 2004 21:22:24 -0000
@@ -37,6 +37,10 @@
 #
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
+
+attribute_map value_only
+
+
 Pattern Fuseki1
 # 799/1591
 
Index: patterns/fuseki19.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/fuseki19.db,v
retrieving revision 1.11
diff -u -p -r1.11 fuseki19.db
--- patterns/fuseki19.db        24 Jan 2004 04:04:57 -0000      1.11
+++ patterns/fuseki19.db        27 Feb 2004 21:22:41 -0000
@@ -41,6 +41,9 @@
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
 
+attribute_map value_only
+
+
 Pattern Fuseki1
 # 4924/6203
 
Index: patterns/fuseki9.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/fuseki9.db,v
retrieving revision 1.8
diff -u -p -r1.8 fuseki9.db
--- patterns/fuseki9.db 24 Jan 2004 04:04:57 -0000      1.8
+++ patterns/fuseki9.db 27 Feb 2004 21:22:51 -0000
@@ -40,6 +40,10 @@
 #
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
+
+attribute_map value_only
+
+
 Pattern Fuseki1
 # 504/1625
 
Index: patterns/gnugo-db.el
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/gnugo-db.el,v
retrieving revision 1.5
diff -u -p -r1.5 gnugo-db.el
--- patterns/gnugo-db.el        24 Jan 2004 04:04:57 -0000      1.5
+++ patterns/gnugo-db.el        27 Feb 2004 21:22:52 -0000
@@ -51,7 +51,8 @@
 
 (defvar gnugo-db-font-lock-keywords (list "Pattern"
                                          "goal_elements"
-                                         "callback_data"))
+                                         "callback_data"
+                                         "attribute_map"))
 
 
 (defun gnugo-db-mode()
Index: patterns/handicap.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/handicap.db,v
retrieving revision 1.6
diff -u -p -r1.6 handicap.db
--- patterns/handicap.db        24 Jan 2004 04:04:57 -0000      1.6
+++ patterns/handicap.db        27 Feb 2004 21:22:53 -0000
@@ -73,6 +73,8 @@
 #  cutoffs involved, see engine/handicap.c for details.
 
 
+attribute_map value_only
+
 goal_elements none
 callback_data !
 
Index: patterns/influence.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/influence.db,v
retrieving revision 1.12
diff -u -p -r1.12 influence.db
--- patterns/influence.db       24 Jan 2004 04:04:57 -0000      1.12
+++ patterns/influence.db       27 Feb 2004 21:22:53 -0000
@@ -38,6 +38,8 @@
 #  I - Invasion points.
 
 
+attribute_map value_only
+
 goal_elements none
 # callback_data is pattern class dependent for this database
 
Index: patterns/joseki.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/joseki.c,v
retrieving revision 1.21
diff -u -p -r1.21 joseki.c
--- patterns/joseki.c   25 Jan 2004 21:35:37 -0000      1.21
+++ patterns/joseki.c   27 Feb 2004 21:22:54 -0000
@@ -430,6 +430,7 @@ main(int argc, char *argv[])
 "
 
   printf(PREAMBLE);
+  printf("attribute_map general\n\n");
 
   /* Call the engine to setup and clear the board. */
   board_size = MAX_BOARD;
Index: patterns/mkpat.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/mkpat.c,v
retrieving revision 1.131
diff -u -p -r1.131 mkpat.c
--- patterns/mkpat.c    25 Jan 2004 21:35:37 -0000      1.131
+++ patterns/mkpat.c    27 Feb 2004 21:23:03 -0000
@@ -173,6 +173,8 @@ static char constraint_diagram[MAX_BOARD
 static char *prefix;
 static struct pattern pattern[MAXPATNO]; /* accumulate the patterns into here 
*/
 static char pattern_names[MAXPATNO][MAXNAME]; /* with optional names here, */
+static int num_attributes;
+static struct pattern_attribute attributes[MAXPATNO * NUM_ATTRIBUTES];
 static char helper_fn_names[MAXPATNO][MAXNAME]; /* helper fn names here */
 static char autohelper_code[MAXPATNO*300]; /* code for automatically generated 
*/
                                           /* helper functions here */
@@ -196,6 +198,50 @@ static const char *current_file = NULL;
 static int current_line_number = 0;
 
 
+struct attribute_description {
+  const char *input_name;      /* The name used in `.db' files. */
+  enum attribute_type type;
+};
+
+
+static const char *attribute_name[NUM_ATTRIBUTES + 1] = {
+  "MIN_VALUE",
+  "MAX_VALUE",
+  "MIN_TERRITORY",
+  "MAX_TERRITORY",
+  "SHAPE",
+  "FOLLOWUP",
+  "REVERSE_FOLLOWUP",
+  "LAST_ATTRIBUTE"
+};
+
+
+/* Owl-style value stored in pattern itself. */
+#define IN_PATTERN_VALUE       NUM_ATTRIBUTES
+
+struct attribute_description general_attribute_map[] = {
+  { "value",           MIN_VALUE },
+  { "minvalue",                MIN_VALUE },
+  { "maxvalue",                MAX_VALUE },
+  { "terri",           MIN_TERRITORY },
+  { "minterri",                MIN_TERRITORY },
+  { "maxterri",                MAX_TERRITORY },
+  { "shape",           SHAPE },
+  { "followup",                FOLLOWUP },
+  { "followup_value",  FOLLOWUP },
+  { "reverse_followup",        REVERSE_FOLLOWUP },
+  { NULL,              LAST_ATTRIBUTE }
+};
+
+struct attribute_description value_only_attribute_map[] = {
+  { "value",           IN_PATTERN_VALUE },
+  { NULL,              LAST_ATTRIBUTE }
+};
+
+struct attribute_description *attribute_map = NULL;
+static int attributes_needed = 0;
+
+
 /* ================================================================ */
 /*                                                                  */
 /*                Autohelper function definitions                   */
@@ -1092,59 +1138,42 @@ finish_pattern(char *line)
       fatal_errors++;
     }
 
+    pattern[patno].attributes = NULL;
     while (sscanf(p, "%*[, ]%[^,]%n", entry, &n) > 0) {
       p += n;
 
       if (sscanf(entry, "%*[^(](%f)", &v) > 0) {
-       const char *corner_unsupported = NULL;
+       struct attribute_description *description;
 
-       if (strncmp(entry, "value", 5) == 0
-           || strncmp(entry, "minvalue", 8) == 0) {
-         pattern[patno].value = v;
-         pattern[patno].class |= VALUE_MINVAL;
-         corner_unsupported = "value";
-       }
-       else if (strncmp(entry, "maxvalue", 8) == 0) {
-         pattern[patno].maxvalue = v;
-         pattern[patno].class |= VALUE_MAXVAL;
-         corner_unsupported = "maxvalue";
-       }
-       else if (strncmp(entry, "terri", 5) == 0
-                || strncmp(entry, "minterri", 8) == 0) {
-         pattern[patno].minterritory = v;
-         pattern[patno].class |= VALUE_MINTERRITORY;
-         corner_unsupported = "terri";
-       }
-       else if (strncmp(entry, "maxterri", 8) == 0) {
-         pattern[patno].maxterritory = v;
-         pattern[patno].class |= VALUE_MAXTERRITORY;
-         corner_unsupported = "maxterri";
-       }
-       else if (strncmp(entry, "shape", 5) == 0) {
-         pattern[patno].shape = v;
-         pattern[patno].class |= VALUE_SHAPE;
-       }
-       else if (strncmp(entry, "followup", 8) == 0) {
-         pattern[patno].followup = v;
-         pattern[patno].class |= VALUE_FOLLOWUP;
-         corner_unsupported = "followup";
-       }
-       else if (strncmp(entry, "reverse_followup", 16) == 0) {
-         pattern[patno].reverse_followup = v;
-         pattern[patno].class |= VALUE_REV_FOLLOWUP;
-         corner_unsupported = "reverse_followup";
+       if (attribute_map) {
+         for (description = attribute_map; description->input_name;
+              description++) {
+           int length = strlen(description->input_name);
+
+           if (strncmp(entry, description->input_name, length) == 0
+               && entry[length] == '(') {
+             if (description->type != IN_PATTERN_VALUE) {
+               if (!pattern[patno].attributes)
+                 pattern[patno].attributes = attributes + num_attributes;
+
+               attributes[num_attributes].type = description->type;
+               attributes[num_attributes].value = v;
+               num_attributes++;
+             }
+             else
+               pattern[patno].value = v;
+
+             break;
+           }
+         }
        }
-       else {
+
+       if (attribute_map == NULL || description->input_name == NULL) {
          fprintf(stderr, "%s(%d) : error : Unknown value field: %s\n",
-                  current_file, current_line_number, entry);
-          fatal_errors++;
+                 current_file, current_line_number, entry);
+         fatal_errors++;
          break;
        }
-
-       if (database_type == DB_CORNER && corner_unsupported) {
-         fprintf(stderr, "%s(%d) : warning : `%s' is unsupported in corner 
databases\n",
-                 current_file, current_line_number, corner_unsupported);
-       }
       }
       else {
        strncpy(helper_fn_names[patno], entry, 79);
@@ -1152,6 +1181,12 @@ finish_pattern(char *line)
       }
     }
 
+    if (pattern[patno].attributes != NULL) {
+      attributes[num_attributes].type = LAST_ATTRIBUTE;
+      attributes[num_attributes].value = 0.0;
+      num_attributes++;
+    }
+
     for (p2 = class; *p2; p2++) {
       switch (*p2) {
        case 's': pattern[patno].class |= CLASS_s; break;
@@ -2601,7 +2636,35 @@ corner_write_variations(struct corner_va
 }
 
 
-/* sort and write out the patterns */
+static void
+write_attributes(FILE *outfile)
+{
+  int k;
+
+  fprintf(outfile, "static struct pattern_attribute attributes[] = {\n");
+  fprintf(outfile, "#ifdef __GNUC__\n");
+
+  for (k = 0; k < num_attributes; k++) {
+    fprintf(outfile, "  {%s,{.value=%f}}",
+           attribute_name[attributes[k].type], attributes[k].value);
+    if (k != num_attributes - 1)
+      fprintf(outfile, ",\n");
+  }
+
+  fprintf(outfile, "\n#else\n");
+
+  for (k = 0; k < num_attributes; k++) {
+    fprintf(outfile, "  {%s,%f,0}",
+           attribute_name[attributes[k].type], attributes[k].value);
+    if (k != num_attributes - 1)
+      fprintf(outfile, ",\n");
+  }
+
+  fprintf(outfile,"\n#endif\n};\n\n");
+}
+
+
+/* Sort and write out the patterns. */
 static void
 write_patterns(FILE *outfile)
 {
@@ -2634,10 +2697,19 @@ write_patterns(FILE *outfile)
     }
 
     if (database_type == DB_CORNER) {
-      fprintf(outfile, "  {%d,%d,0x%x,\"%s\",%f,%d,",
+      fprintf(outfile, "  {%d,%d,0x%x,\"%s\",",
              second_corner_offset[j], (p->trfno == 4),
-             p->class, pattern_names[j], p->shape,
-             p->autohelper_flag);
+             p->class, pattern_names[j]);
+
+      if (attributes_needed) {
+       fprintf(outfile, "attributes+%d,",
+               p->attributes ? p->attributes - attributes : 0);
+      }
+      else
+       fprintf(outfile, "NULL,");
+
+      fprintf(outfile, "%d,", p->autohelper_flag);
+
       if (p->autohelper)
        fprintf(outfile, "autohelper%s%d}", prefix, j);
       else
@@ -2684,17 +2756,17 @@ write_patterns(FILE *outfile)
     fprintf(outfile, "}\n   ");
 #endif
 
-    fprintf(outfile, ", 0x%x,%f,%f,%f,%f,%f,%f,%f,%d,%s,",
-           p->class,
-           p->value,
-           p->maxvalue,
-           p->minterritory,
-           p->maxterritory,
-           p->shape,
-           p->followup,
-           p->reverse_followup,
-           p->autohelper_flag,
-           helper_fn_names[j]);
+    fprintf(outfile, ", 0x%x,%f,", p->class, p->value);
+
+    if (attributes_needed) {
+      fprintf(outfile, "attributes+%d,",
+             p->attributes ? p->attributes - attributes : 0);
+    }
+    else
+      fprintf(outfile, "NULL,");
+
+    fprintf(outfile, "%d,%s,", p->autohelper_flag, helper_fn_names[j]);
+
     if (p->autohelper)
       fprintf(outfile, "autohelper%s%d", prefix, j);
     else
@@ -2722,10 +2794,9 @@ write_patterns(FILE *outfile)
 #if GRID_OPT
   fprintf(outfile, ",{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}");
 #endif
-  fprintf(outfile, ",0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,NULL,NULL,0,0.0");
+  fprintf(outfile, ",0,0.0,NULL,0,NULL,NULL,0,0.0");
 #if PROFILE_PATTERNS
-  fprintf(outfile, ",0,0");
-  fprintf(outfile, ",0");
+  fprintf(outfile, ",0,0,0");
 #endif
   fprintf(outfile, "}\n};\n");
 }
@@ -2936,6 +3007,9 @@ main(int argc, char *argv[])
   autohelper_code[0] = 0;
   code_pos = autohelper_code;
 
+  num_attributes = 1;
+  attributes[0].type = LAST_ATTRIBUTE;
+
   /* Parse the input file, output pattern elements as as we find them,
    * and store pattern entries for later output.
    *
@@ -2996,6 +3070,8 @@ main(int argc, char *argv[])
        command = 2;
       else if (sscanf(line, "callback_data %s", command_data) == 1)
        command = 3;
+      else if (sscanf(line, "attribute_map %s", command_data) == 1)
+       command = 4;
 
       if (command) {
        char *p = strpbrk(command_data, " \t");
@@ -3050,7 +3126,7 @@ main(int argc, char *argv[])
          state = 1;
          discard_pattern = 0;
        }
-       else {
+       else if (command == 2 || command == 3) {
          int *sort_out = (command == 2 ? nongoal : callback_unneeded);
          int k;
 
@@ -3091,6 +3167,40 @@ main(int argc, char *argv[])
 
          state = 0;
        }
+       else {
+         struct attribute_description *old_map = attribute_map;
+
+         if (strcmp(command_data, "general") == 0) {
+           attribute_map = general_attribute_map;
+           attributes_needed = 1;
+         }
+         else if (strcmp(command_data, "value_only") == 0) {
+           attribute_map = value_only_attribute_map;
+           attributes_needed = 0;
+         }
+         else if (strcmp(command_data, "none") == 0) {
+           attribute_map = NULL;
+           attributes_needed = 0;
+         }
+         else {
+           fprintf(stderr, "%s(%d) : Error : unknown attribute map `%s'",
+                   current_file, current_line_number, command_data);
+           fatal_errors++;
+         }
+
+         if (patno != -1 && attribute_map != old_map) {
+           fprintf(stderr, "%s(%d) : Error : attribute map can only be set 
before the first pattern\n",
+                   current_file, current_line_number);
+           fatal_errors++;
+         }
+
+         if (attributes_needed
+             && (database_type == DB_FULLBOARD || database_type == DB_TREE)) {
+           fprintf(stderr, "%s(%d) : Error : attributes other than `value' are 
not allowed in fullboard and tree databases\n",
+                   current_file, current_line_number);
+           fatal_errors++;
+         }
+       }
       }
       else if (line[0] == '\n' || line[0] == '#') { 
        /* nothing */
@@ -3242,6 +3352,11 @@ main(int argc, char *argv[])
 
     /* Write the autohelper code. */
     fprintf(output_FILE, "%s", autohelper_code);
+
+    if (attributes_needed)
+      write_attributes(output_FILE);
+    else
+      assert(num_attributes == 1);
 
     write_patterns(output_FILE);
 
Index: patterns/oracle.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/oracle.db,v
retrieving revision 1.9
diff -u -p -r1.9 oracle.db
--- patterns/oracle.db  24 Jan 2004 04:04:57 -0000      1.9
+++ patterns/oracle.db  27 Feb 2004 21:23:05 -0000
@@ -28,6 +28,9 @@
 # Nadare joseki variations
 
 
+attribute_map value_only
+
+
 Pattern O1
 
 +-------
Index: patterns/owl_attackpats.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/owl_attackpats.db,v
retrieving revision 1.107
diff -u -p -r1.107 owl_attackpats.db
--- patterns/owl_attackpats.db  4 Feb 2004 16:07:37 -0000       1.107
+++ patterns/owl_attackpats.db  27 Feb 2004 21:23:11 -0000
@@ -83,6 +83,8 @@
 # A16xx Specific edge attacks
 
 
+attribute_map value_only
+
 goal_elements Xx
 callback_data none
 
Index: patterns/owl_defendpats.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/owl_defendpats.db,v
retrieving revision 1.114
diff -u -p -r1.114 owl_defendpats.db
--- patterns/owl_defendpats.db  4 Feb 2004 16:07:37 -0000       1.114
+++ patterns/owl_defendpats.db  27 Feb 2004 21:23:18 -0000
@@ -83,6 +83,8 @@
 # D14xx Ko
 
 
+attribute_map value_only
+
 goal_elements Oo
 callback_data none
 
Index: patterns/owl_vital_apats.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/owl_vital_apats.db,v
retrieving revision 1.46
diff -u -p -r1.46 owl_vital_apats.db
--- patterns/owl_vital_apats.db 28 Jan 2004 12:22:50 -0000      1.46
+++ patterns/owl_vital_apats.db 27 Feb 2004 21:23:19 -0000
@@ -62,6 +62,8 @@
 # 
 
 
+attribute_map value_only
+
 goal_elements Xx
 callback_data !
 
Index: patterns/patterns.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/patterns.db,v
retrieving revision 1.124
diff -u -p -r1.124 patterns.db
--- patterns/patterns.db        24 Jan 2004 04:04:57 -0000      1.124
+++ patterns/patterns.db        27 Feb 2004 21:23:34 -0000
@@ -85,6 +85,8 @@
 #
 
 
+attribute_map general
+
 goal_elements none
 # FIXME: try to make callback_data pattern category specific
 callback_data XOxo
Index: patterns/patterns.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/patterns.h,v
retrieving revision 1.61
diff -u -p -r1.61 patterns.h
--- patterns/patterns.h 24 Jan 2004 04:04:57 -0000      1.61
+++ patterns/patterns.h 27 Feb 2004 21:23:35 -0000
@@ -151,20 +151,6 @@ typedef int (*autohelper_fn_ptr)(int rot
                            CLASS_J | CLASS_j | CLASS_U | CLASS_T | CLASS_t | \
                             CLASS_W | CLASS_c | CLASS_F)
 
-/* Values associated with patterns. Stored together with classes. */
-#define VALUE_MINVAL       0x01000000 /* pattern has a minimum value */
-#define VALUE_MAXVAL       0x02000000 /* pattern has a maximum value */
-#define VALUE_MINTERRITORY 0x04000000 /* pattern has a min territorial value */
-#define VALUE_MAXTERRITORY 0x08000000 /* pattern has a max territorial value */
-#define VALUE_SHAPE        0x10000000 /* pattern has a shape value */
-#define VALUE_FOLLOWUP     0x20000000 /* pattern has a followup value */
-#define VALUE_REV_FOLLOWUP 0x40000000 /* pattern has a reverse followup value 
*/
-
-/* Collection of the classes inducing move values. */
-#define CLASS_MOVE_VALUES (VALUE_MINVAL | VALUE_MAXVAL | VALUE_MINTERRITORY \
-                          | VALUE_MAXTERRITORY | VALUE_SHAPE \
-                          | VALUE_FOLLOWUP | VALUE_REV_FOLLOWUP)
-
 /* directions for applying edge-constraints */
 #define NORTH_EDGE 1
 #define SOUTH_EDGE 2
@@ -195,10 +181,45 @@ typedef struct patval_b {
 } Patval_b;
 
 
+enum attribute_type {
+  MIN_VALUE,
+  MAX_VALUE,
+  MIN_TERRITORY,
+  MAX_TERRITORY,
+  SHAPE,
+  FOLLOWUP,
+  REVERSE_FOLLOWUP,
+  NUM_ATTRIBUTES,
+  LAST_ATTRIBUTE = NUM_ATTRIBUTES
+};
+
+
+#ifdef __GNUC__
+
+struct pattern_attribute {
+  enum attribute_type type;
+
+  /* GCC allows unnamed (and transparent) unions. */
+  union {
+    float value;
+    int offset;
+  };
+};
+
+#else
+
+struct pattern_attribute {
+  enum attribute_type type;
+  float value;
+  int offset;
+};
+
+#endif
+
+
 /*
  * Each pattern as a whole is compiled to an instance of this structure.
  */
-
 struct pattern {
   struct patval *patn;  /* array of elements */
   int patlen;           /* number of elements */
@@ -219,13 +240,14 @@ struct pattern {
 #endif
 
   unsigned int class;   /* classification of pattern */
-  float value;          /* value for pattern, if matched */
-  float maxvalue;
-  float minterritory;
-  float maxterritory;
-  float shape;
-  float followup;
-  float reverse_followup;
+
+  /* Value (owl-style, used for pattern sorting) is not stored as an
+   * attribute, because it is very common.
+   */
+  float value;
+
+  /* Pattern attributes like shape, followup etc. */
+  struct pattern_attribute *attributes;
 
   int autohelper_flag;  /* whether autohelper has constraint and/or action */
   pattern_helper_fn_ptr helper;  /* helper function, or NULL */
@@ -406,7 +428,8 @@ struct corner_pattern {
   unsigned int class;  /* Pattern class. */
   const char *name;    /* Pattern name (optional). */
 
-  float shape;         /* Pattern shape value. */
+  /* Pattern attributes like shape (the only one used currently). */
+  struct pattern_attribute *attributes;
 
   int autohelper_flag; /* Whether autohelper has constraint and/or action. */
   autohelper_fn_ptr autohelper; /* Automatically generated helper (or NULL). */
Index: patterns/patterns2.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/patterns2.db,v
retrieving revision 1.70
diff -u -p -r1.70 patterns2.db
--- patterns/patterns2.db       24 Jan 2004 04:04:57 -0000      1.70
+++ patterns/patterns2.db       27 Feb 2004 21:23:38 -0000
@@ -39,6 +39,8 @@
 ##############################
 
 
+attribute_map general
+
 goal_elements none
 # FIXME: try to make callback_data pattern category specific
 callback_data XOxo
Index: patterns/read_attack.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/read_attack.db,v
retrieving revision 1.12
diff -u -p -r1.12 read_attack.db
--- patterns/read_attack.db     24 Jan 2004 04:04:57 -0000      1.12
+++ patterns/read_attack.db     27 Feb 2004 21:23:39 -0000
@@ -25,6 +25,10 @@
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
 
+# FIXME: Pattern-based reading code is broken.  This makes it even more so.
+attribute_map general
+
+
 # thoughts:
 #  Need some way to specify two patterns, one on this end, one on that end.
 #  Need some better backfill & superstring helpers.
Index: patterns/read_defend.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/read_defend.db,v
retrieving revision 1.7
diff -u -p -r1.7 read_defend.db
--- patterns/read_defend.db     24 Jan 2004 04:04:57 -0000      1.7
+++ patterns/read_defend.db     27 Feb 2004 21:23:39 -0000
@@ -24,6 +24,11 @@
 #
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
+
+# FIXME: Pattern-based reading code is broken.  This makes it even more so.
+attribute_map general
+
+
 ##Pattern RD001
 ##
 ##X*




reply via email to

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