gnugo-devel
[Top][All Lists]
Advanced

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

[gnugo-devel] defend both, attack either, worms[], dragons[]


From: Arend Bayer
Subject: [gnugo-devel] defend both, attack either, worms[], dragons[]
Date: Tue, 10 Dec 2002 09:57:59 +0100 (CET)

My experiments with revising the influence interface revealed some problems
with "attack either" and "defend both" move reasons. I think the only way
we will ever get their valuations right is by strictly using the
following definition:

1. Both "attack either" and "defend both" must concern two tactically stable
  worms.
2. "attack either" means opponent cannot defend both worms at a time but could
  if we don't play.
3. "defend both" means opponent could play a move after which we cannot
  defend both (but we could defend each of them, of course -- otherwise the
  worms wouldn't be stable).

This patch enforces the first rule by a discard_rule in move_reasons.c.
It gives one PASS at nngs:820.

When writing the patch, I first caused a bug by forgetting for about
the zillionth time whether a "worm" variable was pointing to an entry
in worms[], or whether it had already been "dereferenced" to point to
a location on the board.

Hence I finally decided to kill both the worms[] and the dragons[] array,
together with find_worm() and find_dragon(). They seem to be a relict
from 2D-board times to me.

(Well I see that this also gives some consistency with regards to the
way connections, EITHER_MOVE data etc. is stored, but unless someone
can convince of a good reason why this consistency is necessary I would
really love to get rid of them.)

Arend


Index: engine/move_reasons.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/move_reasons.c,v
retrieving revision 1.103
diff -u -p -r1.103 move_reasons.c
--- engine/move_reasons.c       6 Dec 2002 17:35:41 -0000       1.103
+++ engine/move_reasons.c       10 Dec 2002 03:15:57 -0000
@@ -38,14 +38,6 @@ struct move_data move[BOARDMAX];
 struct move_reason move_reasons[MAX_MOVE_REASONS];
 int next_reason;

-/* Worms */
-int worms[MAX_WORMS];
-int next_worm;
-
-/* Dragons */
-int dragons[MAX_DRAGONS];
-int next_dragon;
-
 /* Connections */
 int conn_worm1[MAX_CONNECTIONS];
 int conn_worm2[MAX_CONNECTIONS];
@@ -90,8 +82,6 @@ clear_move_reasons(void)
   int ii;
   int k;
   next_reason = 0;
-  next_worm = 0;
-  next_dragon = 0;
   next_connection = 0;
   next_either = 0;
   next_all = 0;
@@ -137,46 +127,6 @@ clear_move_reasons(void)
     }
 }

-/*
- * Find the index of a worm in the list of worms. If necessary,
- * add a new entry. (str) must point to the origin of the worm.
- */
-int
-find_worm(int str)
-{
-  int k;
-
-  ASSERT_ON_BOARD1(str);
-  for (k = 0; k < next_worm; k++)
-    if (worms[k] == str)
-      return k;
-
-  /* Add a new entry. */
-  gg_assert(next_worm < MAX_WORMS);
-  worms[next_worm] = str;
-  next_worm++;
-  return next_worm - 1;
-}
-
-/*
- * Find the index of a dragon in the list of dragons. If necessary,
- * add a new entry. (str) must point to the origin of the dragon.
- */
-int
-find_dragon(int str)
-{
-  int k;
-  ASSERT_ON_BOARD1(str);
-  for (k = 0; k < next_dragon; k++)
-    if (dragons[k] == str)
-      return k;
-
-  /* Add a new entry. */
-  gg_assert(next_dragon < MAX_DRAGONS);
-  dragons[next_dragon] = str;
-  next_dragon++;
-  return next_dragon - 1;
-}

 /*
  * Find the index of a connection in the list of connections.
@@ -324,7 +274,8 @@ get_pos(int reason, int what)
   case ATTACK_MOVE_BAD_KO:
   case DEFEND_MOVE_GOOD_KO:
   case DEFEND_MOVE_BAD_KO:
-    return worms[what];
+    return what;
+
   case SEMEAI_MOVE:
   case SEMEAI_THREAT:
   case VITAL_EYE_MOVE:
@@ -341,16 +292,20 @@ get_pos(int reason, int what)
   case OWL_ATTACK_MOVE_BAD_KO:
   case OWL_DEFEND_MOVE_GOOD_KO:
   case OWL_DEFEND_MOVE_BAD_KO:
-    return dragons[what];
+    return what;
+
   case EITHER_MOVE:
     /* FIXME: What should we return here? */
-    return worms[either_data[what].what1];
+    return either_data[what].what1;
+
   case ALL_MOVE:
     /* FIXME: What should we return here? */
-    return worms[all_data[what].what1];
+    return all_data[what].what1;
+
   case CONNECT_MOVE:
   case CUT_MOVE:
-    return dragons[conn_worm1[what]];
+    return conn_worm1[what];
+
   case ANTISUJI_MOVE:
   case EXPAND_TERRITORY_MOVE:
   case EXPAND_MOYO_MOVE:
@@ -358,14 +313,17 @@ get_pos(int reason, int what)
   case MY_ATARI_ATARI_MOVE:
   case YOUR_ATARI_ATARI_MOVE:
     return NO_MOVE;
+
   case OWL_ATTACK_MOVE_GAIN:
   case OWL_DEFEND_MOVE_LOSS:
     /* FIXME: What should we return here? */
-    return dragons[either_data[what].what1];
+    return either_data[what].what1;
+
+  default:
+    /* We should never get here: */
+    gg_assert(0);
+    return 0; /* To keep gcc happy. */
   }
-  /* We should never get here: */
-  gg_assert(1>2);
-  return 0; /* To keep gcc happy. */
 }

 /*
@@ -377,8 +335,8 @@ void
 add_lunch(int eater, int food)
 {
   int k;
-  int dragon1 = find_dragon(dragon[eater].origin);
-  int worm1   = find_worm(worm[food].origin);
+  int dragon1 = dragon[eater].origin;
+  int worm1   = worm[food].origin;
   ASSERT_ON_BOARD1(eater);
   ASSERT_ON_BOARD1(food);

@@ -402,8 +360,8 @@ void
 remove_lunch(int eater, int food)
 {
   int k;
-  int dragon1 = find_dragon(dragon[eater].origin);
-  int worm1   = find_worm(worm[food].origin);
+  int dragon1 = dragon[eater].origin;
+  int worm1   = worm[food].origin;
   ASSERT_ON_BOARD1(eater);
   ASSERT_ON_BOARD1(food);

@@ -531,6 +489,8 @@ move_reason_known(int pos, int type, int
 int
 attack_move_reason_known(int pos, int what)
 {
+  ASSERT1(IS_STONE(board[what]), what);
+  what = worm[what].origin;
   if (move_reason_known(pos, ATTACK_MOVE, what))
     return WIN;
   if (move_reason_known(pos, ATTACK_MOVE_GOOD_KO, what))
@@ -547,6 +507,8 @@ attack_move_reason_known(int pos, int wh
 int
 defense_move_reason_known(int pos, int what)
 {
+  ASSERT1(IS_STONE(board[what]), what);
+  what = worm[what].origin;
   if (move_reason_known(pos, DEFEND_MOVE, what))
     return WIN;
   if (move_reason_known(pos, DEFEND_MOVE_GOOD_KO, what))
@@ -562,10 +524,9 @@ defense_move_reason_known(int pos, int w
 static int
 tactical_move_vs_whole_dragon_known(int pos, int what)
 {
-  int aa = dragons[what];
-  return ((worm[aa].size == dragon[aa].size)
-         && (attack_move_reason_known(pos, find_worm(aa))
-             || defense_move_reason_known(pos, find_worm(aa))));
+  return ((worm[what].size == dragon[what].size)
+         && (attack_move_reason_known(pos, what)
+             || defense_move_reason_known(pos, what)));
 }

 /*
@@ -618,24 +579,24 @@ owl_move_reason_known(int pos, int what)
 static int
 owl_move_vs_worm_known(int pos, int what)
 {
-  return owl_move_reason_known(pos, find_dragon(dragon[worms[what]].origin));
+  return owl_move_reason_known(pos, dragon[what].origin);
 }

-/* Check whether a worm listed in worms[] is inessential */
+/* Check whether a worm is inessential */
 static int
 concerns_inessential_worm(int pos, int what)
 {
   UNUSED(pos);
-  return DRAGON2(worms[what]).safety == INESSENTIAL
-        || worm[worms[what]].inessential;
+  return DRAGON2(what).safety == INESSENTIAL
+        || worm[what].inessential;
 }

-/* Check whether a dragon listed in dragons[] is inessential */
+/* Check whether a dragon is inessential */
 static int
 concerns_inessential_dragon(int pos, int what)
 {
   UNUSED(pos);
-  return DRAGON2(dragons[what]).safety == INESSENTIAL;
+  return DRAGON2(what).safety == INESSENTIAL;
 }

 static int
@@ -645,27 +606,35 @@ move_is_marked_unsafe(int pos, int what)
   return !move[pos].move_safety;
 }

+
+/* (what) points to two worms listed in either_data. Returns true if
+ * this is a "attack either" move reason, and one of the worms attackable.
+ * FIXME: Ko?
+ */
 static int
-either_move_redundant(int pos, int what)
+either_worm_attackable(int pos, int what)
 {
-  return ((either_data[what].reason1 == ATTACK_STRING
-          && attack_move_reason_known(pos, either_data[what].what1))
-         || (either_data[what].reason2 == ATTACK_STRING
-             && attack_move_reason_known(pos, either_data[what].what2)));
+  UNUSED(pos);
+  return (either_data[what].reason1 == ATTACK_STRING
+         && either_data[what].reason2 == ATTACK_STRING
+          && (worm[either_data[what].what1].attack_codes[0] != 0
+              || worm[either_data[what].what2].attack_codes[0] != 0));
 }

-#if 0
-
+/* (what) points to two worms via all_data. Returns true if this is
+ * a "defend both" move reason, and one of the worms is attackable.
+ * FIXME: Ko?
+ */
 static int
-all_move_redundant(int pos, int what)
+one_of_both_attackable(int pos, int what)
 {
-  return ((all_data[what].reason1 == DEFEND_STRING
-          && defense_move_reason_known(pos, all_data[what].what1))
-         || (all_data[what].reason2 == DEFEND_STRING
-             && defense_move_reason_known(pos, all_data[what].what2)));
+  UNUSED(pos);
+  return (either_data[what].reason1 == DEFEND_STRING
+         && either_data[what].reason2 == DEFEND_STRING
+         && (worm[all_data[what].what1].attack_codes[0] != 0
+              || worm[all_data[what].what2].attack_codes[0] != 0));
 }

-#endif

 /* ---------------------------------------------------------------- */

@@ -677,15 +646,15 @@ all_move_redundant(int pos, int what)
 void
 add_attack_move(int pos, int ww, int code)
 {
-  int worm_number = find_worm(worm[ww].origin);
+  ww = worm[ww].origin;

   ASSERT_ON_BOARD1(ww);
   if (code == WIN)
-    add_move_reason(pos, ATTACK_MOVE, worm_number);
+    add_move_reason(pos, ATTACK_MOVE, ww);
   else if (code == KO_A)
-    add_move_reason(pos, ATTACK_MOVE_GOOD_KO, worm_number);
+    add_move_reason(pos, ATTACK_MOVE_GOOD_KO, ww);
   else if (code == KO_B)
-    add_move_reason(pos, ATTACK_MOVE_BAD_KO, worm_number);
+    add_move_reason(pos, ATTACK_MOVE_BAD_KO, ww);
 }

 /*
@@ -695,15 +664,15 @@ add_attack_move(int pos, int ww, int cod
 void
 add_defense_move(int pos, int ww, int code)
 {
-  int worm_number = find_worm(worm[ww].origin);
+  ww = worm[ww].origin;

   ASSERT_ON_BOARD1(ww);
   if (code == WIN)
-    add_move_reason(pos, DEFEND_MOVE, worm_number);
+    add_move_reason(pos, DEFEND_MOVE, ww);
   else if (code == KO_A)
-    add_move_reason(pos, DEFEND_MOVE_GOOD_KO, worm_number);
+    add_move_reason(pos, DEFEND_MOVE_GOOD_KO, ww);
   else if (code == KO_B)
-    add_move_reason(pos, DEFEND_MOVE_BAD_KO, worm_number);
+    add_move_reason(pos, DEFEND_MOVE_BAD_KO, ww);
 }

 /*
@@ -713,11 +682,10 @@ add_defense_move(int pos, int ww, int co
 void
 add_attack_threat_move(int pos, int ww, int code)
 {
-  int worm_number = find_worm(worm[ww].origin);
   UNUSED(code);

   ASSERT_ON_BOARD1(ww);
-  add_move_reason(pos, ATTACK_THREAT, worm_number);
+  add_move_reason(pos, ATTACK_THREAT, worm[ww].origin);
 }

 /* Remove an attack threat move reason. */
@@ -725,10 +693,8 @@ add_attack_threat_move(int pos, int ww,
 void
 remove_attack_threat_move(int pos, int ww)
 {
-  int worm_number = find_worm(worm[ww].origin);
-
   ASSERT_ON_BOARD1(ww);
-  remove_move_reason(pos, ATTACK_THREAT, worm_number);
+  remove_move_reason(pos, ATTACK_THREAT, worm[ww].origin);
 }

 /*
@@ -738,11 +704,10 @@ remove_attack_threat_move(int pos, int w
 void
 add_defense_threat_move(int pos, int ww, int code)
 {
-  int worm_number = find_worm(worm[ww].origin);
   UNUSED(code);

   ASSERT_ON_BOARD1(ww);
-  add_move_reason(pos, DEFEND_THREAT, worm_number);
+  add_move_reason(pos, DEFEND_THREAT, worm[ww].origin);
 }


@@ -762,7 +727,7 @@ get_attack_threats(int pos, int max_stri
       break;

     if (move_reasons[r].type == ATTACK_THREAT)
-      strings[num_strings++] = worms[move_reasons[r].what];
+      strings[num_strings++] = move_reasons[r].what;

     if (num_strings == max_strings)
       break;
@@ -787,7 +752,7 @@ get_defense_threats(int pos, int max_str
       break;

     if (move_reasons[r].type == DEFEND_THREAT)
-      strings[num_strings++] = worms[move_reasons[r].what];
+      strings[num_strings++] = move_reasons[r].what;

     if (num_strings == max_strings)
       break;
@@ -820,10 +785,9 @@ get_biggest_owl_target(int pos)
     case OWL_DEFEND_MOVE_BAD_KO:
     case OWL_DEFEND_THREAT:
     case OWL_PREVENT_THREAT:
-      if (dragon[dragons[move_reasons[r].what]].effective_size
-          > target_size) {
+      if (dragon[move_reasons[r].what].effective_size > target_size) {
         biggest_target = move_reasons[r].what;
-        target_size = dragon[dragons[move_reasons[r].what]].effective_size;
+        target_size = dragon[move_reasons[r].what].effective_size;
       }
       break;
     }
@@ -839,24 +803,16 @@ get_biggest_owl_target(int pos)
 void
 add_connection_move(int pos, int w1, int w2)
 {
-  int worm1 = find_worm(worm[w1].origin);
-  int worm2 = find_worm(worm[w2].origin);
   int connection;

   ASSERT_ON_BOARD1(w1);
   ASSERT_ON_BOARD1(w2);
   gg_assert(worm[w1].color == worm[w2].color);
-  if (worm1 == worm2)
+  if (worm[w1].origin == worm[w2].origin)
     return;

-  connection = find_connection(worm1, worm2);
+  connection = find_connection(worm[w1].origin, worm[w2].origin);
   add_move_reason(pos, CONNECT_MOVE, connection);
-
-  /* We do this only for the side effect of being sure that the
-   * corresponding dragon gets into the list of dragons.
-   */
-  (void) find_dragon(dragon[w1].origin);
-  (void) find_dragon(dragon[w2].origin);
 }

 /*
@@ -867,16 +823,14 @@ add_connection_move(int pos, int w1, int
 void
 add_cut_move(int pos, int w1, int w2)
 {
-  int worm1 = find_worm(worm[w1].origin);
-  int worm2 = find_worm(worm[w2].origin);
   int connection;

   ASSERT_ON_BOARD1(w1);
   ASSERT_ON_BOARD1(w2);
   gg_assert(worm[w1].color == worm[w2].color);
-  if (worm1 == worm2)
+  if (worm[w1].origin == worm[w2].origin)
     return;
-  connection = find_connection(worm1, worm2);
+  connection = find_connection(worm[w1].origin, worm[w2].origin);

   /*
    * Ignore the cut or connection if either (w1) or (w2)
@@ -888,11 +842,6 @@ add_cut_move(int pos, int w1, int w2)

   add_move_reason(pos, CUT_MOVE, connection);

-  /* We do this only for the side effect of being sure that the
-   * corresponding dragon gets into the list of dragons.
-   */
-  (void) find_dragon(dragon[w1].origin);
-  (void) find_dragon(dragon[w2].origin);
 }

 /*
@@ -917,10 +866,9 @@ add_antisuji_move(int pos)
 void
 add_semeai_move(int pos, int dr)
 {
-  int the_dragon = find_dragon(dragon[dr].origin);
-
+
   ASSERT_ON_BOARD1(dr);
-  add_move_reason(pos, SEMEAI_MOVE, the_dragon);
+  add_move_reason(pos, SEMEAI_MOVE, dragon[dr].origin);
 }

 /*
@@ -933,10 +881,8 @@ add_semeai_move(int pos, int dr)
 void
 add_semeai_threat(int pos, int dr)
 {
-  int the_dragon = find_dragon(dragon[dr].origin);
-
   ASSERT_ON_BOARD1(dr);
-  add_move_reason(pos, SEMEAI_THREAT, the_dragon);
+  add_move_reason(pos, SEMEAI_THREAT, dragon[dr].origin);
 }

 /*
@@ -991,7 +937,7 @@ add_either_move(int pos, int reason1, in
   switch (reason1) {
   case ATTACK_STRING:
     {
-      what1 = find_worm(worm[target1].origin);
+      what1 = worm[target1].origin;

       /* If this string is already attacked, and with no defense, then
        * there is no additional value of this move reason. */
@@ -1008,7 +954,7 @@ add_either_move(int pos, int reason1, in
   switch (reason2) {
   case ATTACK_STRING:
     {
-      what2 = find_worm(worm[target2].origin);
+      what2 = worm[target2].origin;

       /* If this string is already attacked, and with no defense, then
        * there is no additional value of this move reason. */
@@ -1061,7 +1007,7 @@ add_all_move(int pos, int reason1, int t

   switch (reason1) {
   case DEFEND_STRING:
-    what1 = find_worm(worm[target1].origin);
+    what1 = worm[target1].origin;
     break;

   default:
@@ -1070,7 +1016,7 @@ add_all_move(int pos, int reason1, int t

   switch (reason2) {
   case DEFEND_STRING:
-    what2 = find_worm(worm[target2].origin);
+    what2 = worm[target2].origin;
     break;

   default:
@@ -1085,8 +1031,8 @@ add_all_move(int pos, int reason1, int t
 void
 add_gain_move(int pos, int target1, int target2)
 {
-  int what1 = find_dragon(dragon[target1].origin);
-  int what2 = find_worm(worm[target2].origin);
+  int what1 = dragon[target1].origin;
+  int what2 = worm[target2].origin;
   int index = find_pair_data(what1, what2);
   ASSERT1(target2 != NO_MOVE, pos);
   add_move_reason(pos, OWL_ATTACK_MOVE_GAIN, index);
@@ -1095,8 +1041,8 @@ add_gain_move(int pos, int target1, int
 void
 add_loss_move(int pos, int target1, int target2)
 {
-  int what1 = find_dragon(dragon[target1].origin);
-  int what2 = find_worm(worm[target2].origin);
+  int what1 = dragon[target1].origin;
+  int what2 = worm[target2].origin;
   int index = find_pair_data(what1, what2);
   ASSERT1(target2 != NO_MOVE, pos);
   add_move_reason(pos, OWL_DEFEND_MOVE_LOSS, index);
@@ -1173,10 +1119,9 @@ add_worthwhile_threat_move(int pos)
 void
 add_strategical_attack_move(int pos, int dr)
 {
-  int dragon1 = find_dragon(dragon[dr].origin);
-
+  dr = dragon[dr].origin;
   ASSERT_ON_BOARD1(dr);
-  add_move_reason(pos, STRATEGIC_ATTACK_MOVE, dragon1);
+  add_move_reason(pos, STRATEGIC_ATTACK_MOVE, dr);
 }

 /*
@@ -1186,10 +1131,9 @@ add_strategical_attack_move(int pos, int
 void
 add_strategical_defense_move(int pos, int dr)
 {
-  int dragon1 = find_dragon(dragon[dr].origin);
-
+  dr = dragon[dr].origin;
   ASSERT_ON_BOARD1(dr);
-  add_move_reason(pos, STRATEGIC_DEFEND_MOVE, dragon1);
+  add_move_reason(pos, STRATEGIC_DEFEND_MOVE, dr);
 }

 /*
@@ -1199,15 +1143,15 @@ add_strategical_defense_move(int pos, in
 void
 add_owl_attack_move(int pos, int dr, int code)
 {
-  int dragon1 = find_dragon(dragon[dr].origin);
+  dr = dragon[dr].origin;

   ASSERT_ON_BOARD1(dr);
   if (code == WIN)
-    add_move_reason(pos, OWL_ATTACK_MOVE, dragon1);
+    add_move_reason(pos, OWL_ATTACK_MOVE, dr);
   else if (code == KO_A)
-    add_move_reason(pos, OWL_ATTACK_MOVE_GOOD_KO, dragon1);
+    add_move_reason(pos, OWL_ATTACK_MOVE_GOOD_KO, dr);
   else if (code == KO_B)
-    add_move_reason(pos, OWL_ATTACK_MOVE_BAD_KO, dragon1);
+    add_move_reason(pos, OWL_ATTACK_MOVE_BAD_KO, dr);
 }

 /*
@@ -1217,15 +1161,15 @@ add_owl_attack_move(int pos, int dr, int
 void
 add_owl_defense_move(int pos, int dr, int code)
 {
-  int dragon1 = find_dragon(dragon[dr].origin);
+  dr = dragon[dr].origin;

   ASSERT_ON_BOARD1(dr);
   if (code == WIN)
-    add_move_reason(pos, OWL_DEFEND_MOVE, dragon1);
+    add_move_reason(pos, OWL_DEFEND_MOVE, dr);
   else if (code == KO_A)
-    add_move_reason(pos, OWL_DEFEND_MOVE_GOOD_KO, dragon1);
+    add_move_reason(pos, OWL_DEFEND_MOVE_GOOD_KO, dr);
   else if (code == KO_B)
-    add_move_reason(pos, OWL_DEFEND_MOVE_BAD_KO, dragon1);
+    add_move_reason(pos, OWL_DEFEND_MOVE_BAD_KO, dr);
 }

 /*
@@ -1237,11 +1181,11 @@ add_owl_defense_move(int pos, int dr, in
 void
 add_owl_attack_threat_move(int pos, int dr, int code)
 {
-  int dragon1 = find_dragon(dragon[dr].origin);
   UNUSED(code);
+  dr = dragon[dr].origin;

   ASSERT_ON_BOARD1(dr);
-  add_move_reason(pos, OWL_ATTACK_THREAT, dragon1);
+  add_move_reason(pos, OWL_ATTACK_THREAT, dragon[dr].origin);
   add_worthwhile_threat_move(pos);
 }

@@ -1252,10 +1196,9 @@ add_owl_attack_threat_move(int pos, int
 void
 add_owl_uncertain_defense_move(int pos, int dr)
 {
-  int dragon1 = find_dragon(dragon[dr].origin);
-
+  dr = dragon[dr].origin;
   ASSERT_ON_BOARD1(dr);
-  add_move_reason(pos, UNCERTAIN_OWL_DEFENSE, dragon1);
+  add_move_reason(pos, UNCERTAIN_OWL_DEFENSE, dragon[dr].origin);
 }

 /* The owl code found the opponent dragon alive, or the friendly
@@ -1265,10 +1208,9 @@ add_owl_uncertain_defense_move(int pos,
 void
 add_owl_uncertain_attack_move(int pos, int dr)
 {
-  int dragon1 = find_dragon(dragon[dr].origin);
-
+  dr = dragon[dr].origin;
   ASSERT_ON_BOARD1(dr);
-  add_move_reason(pos, UNCERTAIN_OWL_ATTACK, dragon1);
+  add_move_reason(pos, UNCERTAIN_OWL_ATTACK, dragon[dr].origin);
 }

 /*
@@ -1280,11 +1222,11 @@ add_owl_uncertain_attack_move(int pos, i
 void
 add_owl_defense_threat_move(int pos, int dr, int code)
 {
-  int dragon1 = find_dragon(dragon[dr].origin);
   UNUSED(code);
+  dr = dragon[dr].origin;

   ASSERT_ON_BOARD1(dr);
-  add_move_reason(pos, OWL_DEFEND_THREAT, dragon1);
+  add_move_reason(pos, OWL_DEFEND_THREAT, dragon[dr].origin);
   add_worthwhile_threat_move(pos);
 }

@@ -1320,10 +1262,8 @@ add_your_atari_atari_move(int pos, int s
 void
 add_owl_prevent_threat_move(int pos, int dr)
 {
-  int dragon1 = find_dragon(dragon[dr].origin);
-
   ASSERT_ON_BOARD1(dr);
-  add_move_reason(pos, OWL_PREVENT_THREAT, dragon1);
+  add_move_reason(pos, OWL_PREVENT_THREAT, dragon[dr].origin);
 }

 /*
@@ -1472,10 +1412,10 @@ get_saved_worms(int pos, char saved[BOAR
      * move is unsafe.
      */
     if (move_reasons[r].type == DEFEND_MOVE)
-      mark_string(worm[worms[what]].origin, saved, 1);
+      mark_string(worm[what].origin, saved, 1);
     else if (move_reasons[r].type == OWL_DEFEND_MOVE_LOSS) {
-      int origin = dragon[worms[what]].origin;
-      int kworm = worm[worms[what]].origin;
+      int origin = dragon[what].origin;
+      int kworm = worm[what].origin;
       int ii;
       for (ii = BOARDMIN; ii < BOARDMAX; ii++)
        if (IS_STONE(board[ii]) && dragon[ii].origin == origin
@@ -1560,7 +1500,7 @@ mark_changed_dragon(int pos, int color,
       else {
        int worm_is_safe = 0;
        if (worm[ii].attack_codes[0] == NO_MOVE
-           || defense_move_reason_known(pos, find_worm(ii)))
+           || defense_move_reason_known(pos, ii))
          worm_is_safe = 1;
        else if (trymove(pos, color, "mark-changed-dragon", ii,
                         EMPTY, NO_MOVE)) {
@@ -1605,11 +1545,10 @@ get_saved_dragons(int pos, char saved[BO
      * move is unsafe.
      */
     if (move_reasons[r].type == OWL_DEFEND_MOVE) {
-      int origin = dragon[dragons[what]].origin;
       int ii;
-      for (ii = BOARDMIN; ii < BOARDMAX; ii++)
-       if (IS_STONE(board[ii]) && dragon[ii].origin == origin)
-         saved[ii] = 1;
+      for (ii = first_worm_in_dragon(what); ii != NO_MOVE;
+          ii = next_worm_in_dragon(ii))
+       mark_string(ii, saved, 1);
     }
   }
 }
@@ -1686,37 +1625,37 @@ list_move_reasons(int color)

        switch (move_reasons[r].type) {
        case ATTACK_MOVE:
-         aa = worms[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m attacks %1m%s\n", pos, aa,
                  (worm[aa].defense_codes[0] == 0) ? " (defenseless)" : "");
          break;
        case ATTACK_MOVE_GOOD_KO:
-         aa = worms[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m attacks %1m%s with good ko\n", pos, aa,
                  (worm[aa].defense_codes[0] == 0) ? " (defenseless)" : "");
          break;
        case ATTACK_MOVE_BAD_KO:
-         aa = worms[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m attacks %1m%s with bad ko\n", pos, aa,
                  (worm[aa].defense_codes[0] == 0) ? " (defenseless)" : "");
          break;

        case DEFEND_MOVE:
-         aa = worms[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m defends %1m\n", pos, aa);
          break;
        case DEFEND_MOVE_GOOD_KO:
-         aa = worms[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m defends %1m with good ko\n", pos, aa);
          break;
        case DEFEND_MOVE_BAD_KO:
-         aa = worms[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m defends %1m with bad ko\n", pos, aa);
          break;

        case ATTACK_THREAT:
        case DEFEND_THREAT:
-         aa = worms[move_reasons[r].what];
+         aa = move_reasons[r].what;

          if (move_reasons[r].type == ATTACK_THREAT)
            gprintf("Move at %1m threatens to attack %1m\n", pos, aa);
@@ -1725,7 +1664,7 @@ list_move_reasons(int color)
          break;

        case UNCERTAIN_OWL_DEFENSE:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;
          if (board[aa] == color)
            gprintf("%1m found alive but not certainly, %1m defends it again\n",
                    aa, pos);
@@ -1738,12 +1677,10 @@ list_move_reasons(int color)
        case CUT_MOVE:
          worm1 = conn_worm1[move_reasons[r].what];
          worm2 = conn_worm2[move_reasons[r].what];
-         aa = worms[worm1];
-         bb = worms[worm2];
          if (move_reasons[r].type == CONNECT_MOVE)
-           gprintf("Move at %1m connects %1m and %1m\n", pos, aa, bb);
+           gprintf("Move at %1m connects %1m and %1m\n", pos, worm1, worm2);
          else
-           gprintf("Move at %1m cuts %1m and %1m\n", pos, aa, bb);
+           gprintf("Move at %1m cuts %1m and %1m\n", pos, worm1, worm2);
          break;

        case ANTISUJI_MOVE:
@@ -1751,12 +1688,12 @@ list_move_reasons(int color)
          break;

        case SEMEAI_MOVE:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m wins semeai for %1m\n", pos, aa);
          break;

        case SEMEAI_THREAT:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m threatens to win semeai for %1m\n", pos, aa);
          break;

@@ -1774,11 +1711,9 @@ list_move_reasons(int color)
          reason2 = either_data[move_reasons[r].what].reason2;
          worm1 = either_data[move_reasons[r].what].what1;
          worm2 = either_data[move_reasons[r].what].what2;
-         aa = worms[worm1];
-         bb = worms[worm2];
          gprintf("Move at %1m either %s %1m or %s %1m\n", pos,
-                 reason1 == ATTACK_STRING ? "attacks" : "defends", aa,
-                 reason2 == ATTACK_STRING ? "attacks" : "defends", bb);
+                 reason1 == ATTACK_STRING ? "attacks" : "defends", worm1,
+                 reason2 == ATTACK_STRING ? "attacks" : "defends", worm2);
          break;

        case ALL_MOVE:
@@ -1786,61 +1721,59 @@ list_move_reasons(int color)
          reason2 = all_data[move_reasons[r].what].reason2;
          worm1 = all_data[move_reasons[r].what].what1;
          worm2 = all_data[move_reasons[r].what].what2;
-         aa = worms[worm1];
-         bb = worms[worm2];
          gprintf("Move at %1m both %s %1m and %s %1m\n", pos,
-                 reason1 == ATTACK_STRING ? "attacks" : "defends", aa,
-                 reason2 == ATTACK_STRING ? "attacks" : "defends", bb);
+                 reason1 == ATTACK_STRING ? "attacks" : "defends", worm1,
+                 reason2 == ATTACK_STRING ? "attacks" : "defends", worm2);
          break;

        case OWL_ATTACK_MOVE:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m owl-attacks %1m\n", pos, aa);
          break;
        case OWL_ATTACK_MOVE_GOOD_KO:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m owl-attacks %1m with good ko\n", pos, aa);
          break;
        case OWL_ATTACK_MOVE_BAD_KO:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m owl-attacks %1m with bad ko\n", pos, aa);
          break;
        case OWL_ATTACK_MOVE_GAIN:
-         aa = dragons[either_data[move_reasons[r].what].what1];
-         bb = worms[either_data[move_reasons[r].what].what2];
+         aa = either_data[move_reasons[r].what].what1;
+         bb = either_data[move_reasons[r].what].what2;
          gprintf("Move at %1m owl-attacks %1m (captures %1m)\n", pos, aa, bb);
          break;

        case OWL_DEFEND_MOVE:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m owl-defends %1m\n", pos, aa);
          break;
        case OWL_DEFEND_MOVE_GOOD_KO:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m owl-defends %1m with good ko\n", pos, aa);
          break;
        case OWL_DEFEND_MOVE_BAD_KO:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m owl-defends %1m with bad ko\n", pos, aa);
          break;
        case OWL_DEFEND_MOVE_LOSS:
-         aa = dragons[either_data[move_reasons[r].what].what1];
-         bb = worms[either_data[move_reasons[r].what].what2];
+         aa = either_data[move_reasons[r].what].what1;
+         bb = either_data[move_reasons[r].what].what2;
          gprintf("Move at %1m owl-defends %1m (loses %1m)\n", pos, aa, bb);
          break;

        case OWL_ATTACK_THREAT:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m owl-threatens to attack %1m\n", pos, aa);
          break;

        case OWL_DEFEND_THREAT:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m owl-threatens to defend %1m\n", pos, aa);
          break;

        case OWL_PREVENT_THREAT:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;
          gprintf("Move at %1m owl-prevents a threat to attack or defend %1m\n",
                  pos, aa);
          break;
@@ -1859,7 +1792,7 @@ list_move_reasons(int color)

        case STRATEGIC_ATTACK_MOVE:
        case STRATEGIC_DEFEND_MOVE:
-         aa = dragons[move_reasons[r].what];
+         aa = move_reasons[r].what;

          if (move_reasons[r].type == STRATEGIC_ATTACK_MOVE)
            gprintf("Move at %1m strategically attacks %1m\n", pos, aa);
@@ -1889,6 +1822,8 @@ list_move_reasons(int color)
  * flags to be set, trace message }
  * The condition must be of type discard_condition_fn_ptr, that is a pointer
  * to a function with parameters (pos, what).
+ *
+ * FIXME: Add handling of ALL and EITHER moves for inessential worms.
  */

 static struct discard_rule discard_rules[] =
@@ -1906,12 +1841,11 @@ static struct discard_rule discard_rules
     tactical_move_vs_whole_dragon_known, REDUNDANT,
     "  %1m: 0.0 - (threat to) win semai involving %1m (tactical move as 
well)\n"},
   { { EITHER_MOVE, -1 },
-    either_move_redundant, REDUNDANT,
-    "  %1m: 0.0 - either move is redundant at %1m (direct att./def. as 
well)\n"},
-  /* FIXME: Add handling of ALL_MOVE: All single attacks/defenses should
-   *        be removed when there is also a corresponding ALL_MOVE.
-   */
-  /* FIXME: Add handling of ALL and EITHER moves for inessential worms. */
+    either_worm_attackable, REDUNDANT,
+    "  %1m: 0.0 - 'attack either' is redundant at %1m (direct att./def. as 
well)\n"},
+  { { ALL_MOVE, -1 },
+    one_of_both_attackable, REDUNDANT,
+    "  %1m: 0.0 - 'defend both' is redundant at %1m (direct att./def. as 
well)\n"},
   { { ATTACK_MOVE, ATTACK_MOVE_GOOD_KO,
       ATTACK_MOVE_BAD_KO, ATTACK_THREAT,
       DEFEND_MOVE, DEFEND_MOVE_GOOD_KO,
Index: engine/move_reasons.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/move_reasons.h,v
retrieving revision 1.28
diff -u -p -r1.28 move_reasons.h
--- engine/move_reasons.h       6 Dec 2002 17:35:42 -0000       1.28
+++ engine/move_reasons.h       10 Dec 2002 03:15:58 -0000
@@ -145,14 +145,6 @@ extern struct move_data move[BOARDMAX];
 extern struct move_reason move_reasons[MAX_MOVE_REASONS];
 extern int next_reason;

-/* Worms */
-extern int worms[MAX_WORMS];
-extern int next_worm;
-
-/* Dragons */
-extern int dragons[MAX_DRAGONS];
-extern int next_dragon;
-
 /* Connections */
 extern int conn_worm1[MAX_CONNECTIONS];
 extern int conn_worm2[MAX_CONNECTIONS];
Index: engine/value_moves.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/value_moves.c,v
retrieving revision 1.70
diff -u -p -r1.70 value_moves.c
--- engine/value_moves.c        6 Dec 2002 18:28:38 -0000       1.70
+++ engine/value_moves.c        10 Dec 2002 03:16:10 -0000
@@ -143,7 +143,7 @@ find_more_attack_and_defense_moves(int c
          && worm[ii].origin == ii
          && worm[ii].attack_codes[0] != 0
          && worm[ii].defense_codes[0] != 0) {
-       unstable_worms[N] = find_worm(ii);
+       unstable_worms[N] = ii;
        N++;
       }
     }
@@ -183,7 +183,7 @@ find_more_attack_and_defense_moves(int c
       if (trymove(ii, color, "find_more_attack_and_defense_moves",
                  NO_MOVE, EMPTY, NO_MOVE)) {
        for (k = 0; k < N; k++) {
-         int aa = worms[unstable_worms[k]];
+         int aa = unstable_worms[k];

          /* string of our color, see if there still is an attack,
           * unless we already know the move works as defense move.
@@ -303,17 +303,17 @@ find_more_owl_attack_and_defense_moves(i
       what = move_reasons[r].what;
       if (move_reasons[r].type == STRATEGIC_ATTACK_MOVE
          || move_reasons[r].type == STRATEGIC_DEFEND_MOVE)
-       dd1 = dragons[what];
+       dd1 = what;
       else if (move_reasons[r].type == ATTACK_MOVE
               || move_reasons[r].type == ATTACK_MOVE_GOOD_KO
               || move_reasons[r].type == ATTACK_MOVE_BAD_KO
               || move_reasons[r].type == DEFEND_MOVE
               || move_reasons[r].type == DEFEND_MOVE_GOOD_KO
               || move_reasons[r].type == DEFEND_MOVE_BAD_KO)
-       dd1 = worms[what];
+       dd1 = what;
       else if (move_reasons[r].type == VITAL_EYE_MOVE) {
-       int ee = eyes[move_reasons[r].what];
-       int ecolor = eyecolor[move_reasons[r].what];
+       int ee = eyes[what];
+       int ecolor = eyecolor[what];

        if (ecolor == WHITE)
          find_eye_dragons(ee, white_eye, WHITE, &dd1, 1);
@@ -324,10 +324,10 @@ find_more_owl_attack_and_defense_moves(i
          continue;
       }
       else if (move_reasons[r].type == CONNECT_MOVE) {
-       int worm1 = conn_worm1[move_reasons[r].what];
-       int worm2 = conn_worm2[move_reasons[r].what];
-       dd1 = dragon[worms[worm1]].origin;
-       dd2 = dragon[worms[worm2]].origin;
+       int worm1 = conn_worm1[what];
+       int worm2 = conn_worm2[what];
+       dd1 = dragon[worm1].origin;
+       dd2 = dragon[worm2].origin;
        if (dd1 == dd2)
          dd2 = NO_MOVE;
       }
@@ -356,7 +356,7 @@ find_more_owl_attack_and_defense_moves(i
             || move_reasons[r].type == ATTACK_MOVE_BAD_KO
             || (move_reasons[r].type == VITAL_EYE_MOVE
                 && board[dd] == OTHER_COLOR(color)))
-           && !owl_attack_move_reason_known(pos, find_dragon(dd))) {
+           && !owl_attack_move_reason_known(pos, dd)) {
          int kworm = NO_MOVE;
          int acode = owl_does_attack(pos, dd, &kworm);
          if (acode >= dragon[dd].owl_attack_code) {
@@ -375,7 +375,7 @@ find_more_owl_attack_and_defense_moves(i
             || move_reasons[r].type == DEFEND_MOVE_BAD_KO
             || (move_reasons[r].type == VITAL_EYE_MOVE
                 && board[dd] == color))
-           && !owl_defense_move_reason_known(pos, find_dragon(dd))) {
+           && !owl_defense_move_reason_known(pos, dd)) {
          int kworm = NO_MOVE;
          /* FIXME: Better use owl_connection_defend() for CONNECT_MOVE ? */
          int dcode = owl_does_defend(pos, dd, &kworm);
@@ -413,7 +413,7 @@ find_more_owl_attack_and_defense_moves(i
              || move_reasons[r].type == OWL_DEFEND_MOVE
              || move_reasons[r].type == OWL_DEFEND_MOVE_GOOD_KO
              || move_reasons[r].type == OWL_DEFEND_MOVE_BAD_KO) {
-           dd = dragons[move_reasons[r].what];
+           dd = move_reasons[r].what;
            if (are_neighbor_dragons(dd, pos)) {
              worth_trying = 1;
              break;
@@ -426,7 +426,7 @@ find_more_owl_attack_and_defense_moves(i

        if (worth_trying) {
          if (board[pos] == color
-             && !owl_defense_move_reason_known(pos2, find_dragon(pos))) {
+             && !owl_defense_move_reason_known(pos2, pos)) {
            int kworm = NO_MOVE;
            int dcode = owl_does_defend(pos2, pos, &kworm);
            if (dcode >= dragon[pos].owl_defense_code) {
@@ -438,7 +438,7 @@ find_more_owl_attack_and_defense_moves(i

          }
          else if (board[pos] != color
-                  && !owl_attack_move_reason_known(pos2, find_dragon(pos))) {
+                  && !owl_attack_move_reason_known(pos2, pos)) {
            int kworm = NO_MOVE;
            int acode = owl_does_attack(pos2, pos, &kworm);
            if (acode >= dragon[pos].owl_attack_code) {
@@ -508,7 +508,7 @@ induce_secondary_move_reasons(int color)
        int color_to_move;
        int num_adj, adjs[MAXCHAIN];

-       aa = worms[move_reasons[r].what];
+       aa = move_reasons[r].what;

        if (move_reasons[r].type == ATTACK_MOVE) {
          attack_move = 1;
@@ -596,7 +596,7 @@ induce_secondary_move_reasons(int color)
        }
       }
       else if (move_reasons[r].type == OWL_ATTACK_MOVE) {
-       aa = dragons[move_reasons[r].what];
+       aa = move_reasons[r].what;
        for (i = 0; i < DRAGON2(aa).neighbors; i++) {
          int bb = dragon2[DRAGON2(aa).adjacent[i]].origin;
          if (dragon[bb].color == color && worm[bb].attack_codes[0] == 0)
@@ -605,8 +605,8 @@ induce_secondary_move_reasons(int color)
       }
       else if (move_reasons[r].type == CONNECT_MOVE
              && cut_possible(pos, OTHER_COLOR(color))) {
-       int worm1 = worms[conn_worm1[move_reasons[r].what]];
-       int worm2 = worms[conn_worm2[move_reasons[r].what]];
+       int worm1 = conn_worm1[move_reasons[r].what];
+       int worm2 = conn_worm2[move_reasons[r].what];
        int pos2;
        for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++)
          if (ON_BOARD(pos2) && board[pos2] == EMPTY
@@ -705,15 +705,15 @@ examine_move_safety(int color)
          if (type == ATTACK_MOVE
              || type == ATTACK_MOVE_GOOD_KO
              || type == ATTACK_MOVE_BAD_KO) {
-           aa = worms[what];
+           aa = what;
            size = worm[aa].effective_size;
          }
          else if (type == OWL_ATTACK_MOVE_GAIN) {
-           aa = worms[either_data[what].what2];
+           aa = either_data[what].what2;
            size = worm[aa].effective_size;
          }
          else {
-           aa = dragons[what];
+           aa = what;
            size = dragon[aa].effective_size;
          }

@@ -834,7 +834,7 @@ examine_move_safety(int color)
       case DEFEND_MOVE_GOOD_KO:
       case DEFEND_MOVE_BAD_KO:
        {
-         int aa = worms[what];
+         int aa = what;

          if (dragon[aa].status == ALIVE)
            /* It would be better if this never happened, but it does
@@ -855,8 +855,8 @@ examine_move_safety(int color)
         {
          int worm1 = conn_worm1[move_reasons[r].what];
          int worm2 = conn_worm2[move_reasons[r].what];
-         int aa = dragon[worms[worm1]].origin;
-         int bb = dragon[worms[worm2]].origin;
+         int aa = dragon[worm1].origin;
+         int bb = dragon[worm2].origin;

          if (aa == bb)
            continue;
@@ -999,12 +999,10 @@ connection_value(int dragona, int dragon
    * FIXME: Shouldn't it be sufficient to check this for dragon a?
    */
   if (doing_scoring && terr_val < 0.0) {
-    if ((safetya == WEAKLY_ALIVE
-        || safetya == ALIVE
+    if ((safetya == ALIVE
         || safetya == STRONGLY_ALIVE
         || safetya == INVINCIBLE)
-       && (safetyb == WEAKLY_ALIVE
-           || safetyb == ALIVE
+       && (safetyb == ALIVE
            || safetyb == STRONGLY_ALIVE
            || safetyb == INVINCIBLE))
       return 0.0;
@@ -1187,7 +1185,7 @@ strategic_penalty(int pos, int color)

   for (k = 0; k < MAX_REASONS; k++) {
     int r = move[pos].reason[k];
-    if (r == -1)
+    if (r < 0)
       break;
     /* We assume that invasion moves can only have the move reasons listed
      * below.
@@ -1209,7 +1207,7 @@ strategic_penalty(int pos, int color)
      */
     case DEFEND_MOVE:
       {
-       int target = worms[move_reasons[r].what];
+       int target = move_reasons[r].what;
        if (dragon[target].size > 1)
          return 0.0;
        continue;
@@ -1220,7 +1218,7 @@ strategic_penalty(int pos, int color)
      */
     case OWL_DEFEND_MOVE:
       {
-       int target = dragons[move_reasons[r].what];
+       int target = move_reasons[r].what;
        int has_strong_neighbor = 0;
        int has_weak_neighbor = 0;
        int i;
@@ -1252,7 +1250,9 @@ strategic_penalty(int pos, int color)
              has_strong_neighbor = 1;
              break;
            case ALIVE:
-             continue;
+             if (DRAGON2(target + delta[i]).weakness > 0.4)
+               has_weak_neighbor = 1;
+             break;
            default:
              has_weak_neighbor = 1;
            }
@@ -1332,7 +1332,7 @@ estimate_territorial_value(int pos, int
     case ATTACK_MOVE:
     case ATTACK_MOVE_GOOD_KO:
     case ATTACK_MOVE_BAD_KO:
-      aa = worms[move_reasons[r].what];
+      aa = move_reasons[r].what;

       gg_assert(board[aa] != color);

@@ -1385,7 +1385,7 @@ estimate_territorial_value(int pos, int
     case DEFEND_MOVE:
     case DEFEND_MOVE_GOOD_KO:
     case DEFEND_MOVE_BAD_KO:
-      aa = worms[move_reasons[r].what];
+      aa = move_reasons[r].what;

       gg_assert(board[aa] == color);

@@ -1433,8 +1433,8 @@ estimate_territorial_value(int pos, int
        * combination with bad ko it still has a positive net impact.
        */
       if (dragon[aa].owl_status == CRITICAL
-         && (owl_defense_move_reason_known(pos, find_dragon(aa))
-             < defense_move_reason_known(pos, find_worm(aa)))) {
+         && (owl_defense_move_reason_known(pos, aa)
+             < defense_move_reason_known(pos, aa))) {
        this_value = 0.45 * (2 * worm[aa].effective_size);
        TRACE("  %1m: -%f - suspected ineffective defense of worm %1m\n",
              pos, this_value, aa);
@@ -1445,7 +1445,7 @@ estimate_territorial_value(int pos, int
       break;

     case ATTACK_THREAT:
-      aa = worms[move_reasons[r].what];
+      aa = move_reasons[r].what;

       /* Make sure this is a threat to attack opponent stones. */
       ASSERT1(board[aa] == other, aa);
@@ -1569,7 +1569,7 @@ estimate_territorial_value(int pos, int
       break;

     case DEFEND_THREAT:
-      aa = worms[move_reasons[r].what];
+      aa = move_reasons[r].what;

       /* Make sure this is a threat to defend our stones. */
       ASSERT1(board[aa] == color, aa);
@@ -1624,7 +1624,7 @@ estimate_territorial_value(int pos, int
       break;

     case SEMEAI_MOVE:
-      aa = dragons[move_reasons[r].what];
+      aa = move_reasons[r].what;

       this_value = 2 * dragon[aa].effective_size;
       TRACE("  %1m: %f - semeai involving %1m\n", pos, this_value, aa);
@@ -1632,7 +1632,7 @@ estimate_territorial_value(int pos, int
       break;

     case SEMEAI_THREAT:
-      aa = dragons[move_reasons[r].what];
+      aa = move_reasons[r].what;

       /* threaten to win the semeai as a ko threat */
       add_followup_value(pos, 2 * dragon[aa].effective_size);
@@ -1658,11 +1658,11 @@ estimate_territorial_value(int pos, int

       if (move_reasons[r].type == OWL_ATTACK_MOVE_GAIN
          || move_reasons[r].type == OWL_DEFEND_MOVE_LOSS) {
-        aa = dragons[either_data[move_reasons[r].what].what1];
-        bb = worms[either_data[move_reasons[r].what].what2];
+        aa = either_data[move_reasons[r].what].what1;
+        bb = either_data[move_reasons[r].what].what2;
       }
       else {
-       aa = dragons[move_reasons[r].what];
+       aa = move_reasons[r].what;
        bb = NO_MOVE;
       }

@@ -1726,7 +1726,7 @@ estimate_territorial_value(int pos, int
           || move_reasons[r].type == OWL_ATTACK_MOVE_BAD_KO)
          && dragon[aa].size == worm[aa].size
          && worm[aa].attack_codes[0] == WIN
-         && attack_move_reason_known(pos, find_worm(aa)) != WIN) {
+         && attack_move_reason_known(pos, aa) != WIN) {
        this_value = 0.05 * (2 * worm[aa].effective_size);
        TRACE("  %1m: -%f - suspected ineffective owl attack of worm %1m\n",
              pos, this_value, aa);
@@ -1737,7 +1737,7 @@ estimate_territorial_value(int pos, int
       break;

     case OWL_ATTACK_THREAT:
-      aa = dragons[move_reasons[r].what];
+      aa = move_reasons[r].what;

       if (dragon[aa].status == DEAD) {
        DEBUG(DEBUG_MOVE_REASONS,
@@ -1766,7 +1766,7 @@ estimate_territorial_value(int pos, int
          if (dragon[adj].color == color
              && dragon[adj].status == CRITICAL
              && dragon2[d].safety != INESSENTIAL
-             && !owl_defense_move_reason_known(pos, find_dragon(adj)))
+             && !owl_defense_move_reason_known(pos, adj))
            value = 0.0;
        }

@@ -1779,7 +1779,7 @@ estimate_territorial_value(int pos, int
       break;

     case OWL_DEFEND_THREAT:
-      aa = dragons[move_reasons[r].what];
+      aa = move_reasons[r].what;

       add_followup_value(pos, 2 * dragon[aa].effective_size);
       TRACE("  %1m: %f (followup) - threatens to owl defend %1m\n",
@@ -1789,7 +1789,7 @@ estimate_territorial_value(int pos, int
     case OWL_PREVENT_THREAT:
       /* A move attacking a dragon whose defense can be threatened.
        */
-      aa = dragons[move_reasons[r].what];
+      aa = move_reasons[r].what;

       /* If the opponent just added a stone to a dead dragon, then
        * attack it. If we are ahead, add a safety move here, at most
@@ -1912,25 +1912,19 @@ estimate_strategical_value(int pos, int
   int l;
   int aa = NO_MOVE;
   int bb = NO_MOVE;
+  int a_id;
+  int b_id;
   float aa_value = 0.0;
   float bb_value = 0.0;
-  int d1 = -1;
-  int d2 = -1;
-  int worm1 = -1;
-  int worm2 = -1;

   float this_value = 0.0;
   float tot_value = 0.0;

   /* Strategical value of connecting or cutting dragons. */
-  static float dragon_value[MAX_DRAGONS];
+  float *dragon_value = malloc(sizeof(float) * number_of_dragons);
+  gg_assert(dragon_value);

-  /* This loop used to be up to next_dragon, but that is not safe
-   * because while doing the computations below, next_dragon might
-   * increase (through calls to find_dragon()). Thus we could then
-   * reference improperly initialized memory.
-   */
-  for (k = 0; k < MAX_DRAGONS; k++)
+  for (k = 0; k < number_of_dragons; k++)
     dragon_value[k] = 0.0;

   for (k = 0; k < MAX_REASONS; k++) {
@@ -1948,8 +1942,7 @@ estimate_strategical_value(int pos, int
       case DEFEND_MOVE:
       case DEFEND_MOVE_GOOD_KO:
       case DEFEND_MOVE_BAD_KO:
-       worm1 = move_reasons[r].what;
-       aa = worms[worm1];
+       aa = move_reasons[r].what;

        /* Defenseless stone */
        if (worm[aa].defense_codes[0] == 0)
@@ -1989,9 +1982,9 @@ estimate_strategical_value(int pos, int

        /* Can't use k in this loop too. */
        for (l = 0; l < next_lunch; l++)
-         if (lunch_worm[l] == worm1) {
-           d1 = lunch_dragon[l];
-           bb = dragons[d1];
+         if (lunch_worm[l] == aa) {
+           bb = lunch_dragon[l];
+           b_id = dragon[bb].id;

            /* FIXME: This value cannot be computed without some measurement
             * of how the actual move affects the dragon.  The dragon safety
@@ -2008,8 +2001,8 @@ estimate_strategical_value(int pos, int
             */
            if (dragon[bb].status != DEAD
                && dragon[bb].size == worm[bb].size
-               && (attack_move_reason_known(pos, find_worm(bb))
-                   || defense_move_reason_known(pos, find_worm(bb))))
+               && (attack_move_reason_known(pos, bb)
+                   || defense_move_reason_known(pos, bb)))
              this_value = 0.0;

            /* If this dragon can be tactically attacked and the move
@@ -2026,17 +2019,16 @@ estimate_strategical_value(int pos, int
             */
            if (doing_scoring
                && move[pos].territorial_value < 0.0
-               && (DRAGON2(bb).safety == WEAKLY_ALIVE
-                   || DRAGON2(bb).safety == ALIVE
+               && (DRAGON2(bb).safety == ALIVE
                    || DRAGON2(bb).safety == STRONGLY_ALIVE
                    || DRAGON2(bb).safety == INVINCIBLE))
              this_value = 0.0;

-           if (this_value > dragon_value[d1]) {
+           if (this_value > dragon_value[b_id]) {
              DEBUG(DEBUG_MOVE_REASONS,
                    "  %1m:   %f - %1m attacked/defended\n",
                    pos, this_value, bb);
-             dragon_value[d1] = this_value;
+             dragon_value[b_id] = this_value;
            }
          }

@@ -2051,10 +2043,8 @@ estimate_strategical_value(int pos, int
        /* FIXME: We need a policy if a move has several EITHER_MOVE
         * reasons. Most likely not all of them can be achieved.
         */
-       worm1 = either_data[move_reasons[r].what].what1;
-       worm2 = either_data[move_reasons[r].what].what2;
-       aa = worms[worm1];
-       bb = worms[worm2];
+       aa = either_data[move_reasons[r].what].what1;
+       bb = either_data[move_reasons[r].what].what2;

        /* If both worms are dead, this move reason has no value. */
        if (dragon[aa].status == DEAD
@@ -2081,10 +2071,8 @@ estimate_strategical_value(int pos, int

       case ALL_MOVE:
        /* FIXME: Generalize this to more types of threats. */
-       worm1 = all_data[move_reasons[r].what].what1;
-       worm2 = all_data[move_reasons[r].what].what2;
-       aa = worms[worm1];
-       bb = worms[worm2];
+       aa = all_data[move_reasons[r].what].what1;
+       bb = all_data[move_reasons[r].what].what2;

        /* If both worms are dead, this move reason has no value. */
        if (dragon[aa].status == DEAD
@@ -2122,10 +2110,8 @@ estimate_strategical_value(int pos, int

        if (!doing_scoring) {
          int cc;
-         worm1 = conn_worm1[move_reasons[r].what];
-         worm2 = conn_worm2[move_reasons[r].what];
-         aa = dragon[worms[worm1]].origin;
-         bb = dragon[worms[worm2]].origin;
+         aa = dragon[conn_worm1[move_reasons[r].what]].origin;
+         bb = dragon[conn_worm2[move_reasons[r].what]].origin;
          cc = get_last_opponent_move(color);

          if (cc != NO_MOVE
@@ -2140,9 +2126,8 @@ estimate_strategical_value(int pos, int
            else
              this_value = 1.7 * dragon[cc].effective_size;

-           d1 = find_dragon(cc);
-           if (this_value > dragon_value[d1]) {
-             dragon_value[d1] = this_value;
+           if (this_value > dragon_value[dragon[cc].id]) {
+             dragon_value[dragon[cc].id] = this_value;
              DEBUG(DEBUG_MOVE_REASONS,
                    "  %1m:   %f - connect %1m and %1m to attack thrashing 
dragon %1m\n",
                    pos, this_value, aa, bb, cc);
@@ -2157,16 +2142,14 @@ estimate_strategical_value(int pos, int
        if (doing_scoring && !move[pos].move_safety)
          break;

-       worm1 = conn_worm1[move_reasons[r].what];
-       worm2 = conn_worm2[move_reasons[r].what];
-       aa = dragon[worms[worm1]].origin;
-       bb = dragon[worms[worm2]].origin;
+       aa = dragon[conn_worm1[move_reasons[r].what]].origin;
+       bb = dragon[conn_worm2[move_reasons[r].what]].origin;

        if (aa == bb)
          continue;

-       d1 = find_dragon(aa);
-       d2 = find_dragon(bb);
+       a_id = dragon[aa].id;
+       b_id = dragon[bb].id;

        /* If we are ahead by more than 20, value connections more strongly */
        if ((color == WHITE && score > 20.0)
@@ -2174,8 +2157,8 @@ estimate_strategical_value(int pos, int
          this_value = connection_value(aa, bb, pos, gg_abs(score));
        else
          this_value = connection_value(aa, bb, pos, 0);
-       if (this_value > dragon_value[d1]) {
-         dragon_value[d1] = this_value;
+       if (this_value > dragon_value[a_id]) {
+         dragon_value[a_id] = this_value;
           DEBUG(DEBUG_MOVE_REASONS,
                "  %1m:   %f - %1m cut/connect strategic value\n",
                pos, this_value, aa);
@@ -2187,8 +2170,8 @@ estimate_strategical_value(int pos, int
          this_value = connection_value(bb, aa, pos, gg_abs(score));
        else
          this_value = connection_value(bb, aa, pos, 0);
-       if (this_value > dragon_value[d2]) {
-         dragon_value[d2] = this_value;
+       if (this_value > dragon_value[b_id]) {
+         dragon_value[b_id] = this_value;
           DEBUG(DEBUG_MOVE_REASONS,
                "  %1m:   %f - %1m cut/connect strategic value\n",
                pos, this_value, bb);
@@ -2231,8 +2214,8 @@ estimate_strategical_value(int pos, int
         * we don't care about it, since otherwise we would count the
         * points twice.
         */
-       if (owl_defense_move_reason_known(pos, find_dragon(bb))
-           || owl_attack_move_reason_known(pos, find_dragon(bb))) {
+       if (owl_defense_move_reason_known(pos, bb)
+           || owl_attack_move_reason_known(pos, bb)) {
          DEBUG(DEBUG_MOVE_REASONS,
                "    %1m: 0.0 - vital for %1m: owl attack/defense as well\n",
                pos, bb);
@@ -2260,8 +2243,8 @@ estimate_strategical_value(int pos, int
         *
         * FIXME: Improve the implementation.
         */
-       d1 = move_reasons[r].what;
-       aa = dragons[d1];
+       aa = move_reasons[r].what;
+       a_id = dragon[aa].id;

        /* FIXME: This value cannot be computed without some
         * measurement of how the actual move affects the dragon. The
@@ -2291,13 +2274,13 @@ estimate_strategical_value(int pos, int
            if (dragon[adj].color == color
                && dragon[adj].status == CRITICAL
                && dragon2[d].safety != INESSENTIAL
-               && !owl_defense_move_reason_known(pos, find_dragon(adj)))
+               && !owl_defense_move_reason_known(pos, adj))
              this_value = 0.0;
          }
        }

-       if (this_value > dragon_value[d1]) {
-         dragon_value[d1] = this_value;
+       if (this_value > dragon_value[a_id]) {
+         dragon_value[a_id] = this_value;
           DEBUG(DEBUG_MOVE_REASONS,
                "  %1m:   %f - %1m strategic attack/defend\n",
                pos, this_value, aa);
@@ -2306,8 +2289,8 @@ estimate_strategical_value(int pos, int
        break;

       case UNCERTAIN_OWL_DEFENSE:
-       d1 = move_reasons[r].what;
-       aa = dragons[d1];
+       aa = move_reasons[r].what;
+       a_id = dragon[aa].id;

        /* If there is an adjacent dragon which is critical we should
         * skip this type of move reason, since attacking or defending
@@ -2333,8 +2316,8 @@ estimate_strategical_value(int pos, int
        else
          this_value = gg_min(2*dragon[aa].effective_size, gg_abs(0.65*score));

-       if (this_value > dragon_value[d1]) {
-         dragon_value[d1] = this_value;
+       if (this_value > dragon_value[a_id]) {
+         dragon_value[a_id] = this_value;
          DEBUG(DEBUG_MOVE_REASONS,
                "  %1m:   %f - %1m uncertain owl defense bonus\n",
                pos, this_value, aa);
@@ -2344,17 +2327,17 @@ estimate_strategical_value(int pos, int
     }
   }

-  for (k = 0; k < next_dragon; k++) {
+  for (k = 0; k < number_of_dragons; k++) {
     if (dragon_value[k] == 0.0)
       continue;

-    aa = dragons[k];
+    aa = dragon2[k].origin;

     /* If this dragon is critical but not attacked/defended by this
      * move, we ignore the strategic effect.
      */
     if (dragon[aa].status == CRITICAL
-       && !owl_move_reason_known(pos, k)) {
+       && !owl_move_reason_known(pos, aa)) {
       DEBUG(DEBUG_MOVE_REASONS, "  %1m: 0.0 - disregarding strategic effect on 
%1m (critical dragon)\n",
            pos, aa);
       continue;
@@ -2367,8 +2350,8 @@ estimate_strategical_value(int pos, int
      */
     if (dragon[aa].status != DEAD
        && dragon[aa].size == worm[aa].size
-       && (attack_move_reason_known(pos, find_worm(aa))
-           || defense_move_reason_known(pos, find_worm(aa)))) {
+       && (attack_move_reason_known(pos, aa)
+           || defense_move_reason_known(pos, aa))) {
       TRACE("  %1m:   %f - %1m strategic value already counted - A.\n",
            pos, dragon_value[k], aa);
       continue;
@@ -2377,18 +2360,17 @@ estimate_strategical_value(int pos, int
      * in a semeai, we have likewise already counted the points as
      * territorial value.
      */
-    if (owl_attack_move_reason_known(pos, k)
-       || owl_defense_move_reason_known(pos, k)
-       || move_reason_known(pos, SEMEAI_MOVE, k)) {
+    if (owl_attack_move_reason_known(pos, aa)
+       || owl_defense_move_reason_known(pos, aa)
+       || move_reason_known(pos, SEMEAI_MOVE, aa)) {
       /* But if the strategical value was larger than the territorial
        * value (e.g. because connecting to strong dragon) we award the
        * excess value as a bonus.
        */
       float excess_value = (dragon_value[k] -
-                           2 * dragon[dragons[k]].effective_size);
+                           2 * dragon[aa].effective_size);
       if (excess_value > 0.0) {
-       TRACE("  %1m: %f - strategic bonus for %1m\n",
-             pos, excess_value, dragons[k]);
+       TRACE("  %1m: %f - strategic bonus for %1m\n", pos, excess_value, aa);
        tot_value += excess_value;
       }
       else {
@@ -2400,9 +2382,11 @@ estimate_strategical_value(int pos, int
     }

     TRACE("  %1m: %f - strategic effect on %1m\n",
-         pos, dragon_value[k], dragons[k]);
+         pos, dragon_value[k], aa);
     tot_value += dragon_value[k];
   }
+
+  free(dragon_value);

   /* Finally, subtract penalty for invasion type moves. */
   this_value = strategic_penalty(pos, color);
@@ -2810,9 +2794,9 @@ reevaluate_ko_threats(int ko_move, int c
         switch (move_reasons[r].type) {
         case ATTACK_THREAT:
         case DEFEND_THREAT:
-          if (worm[worms[move_reasons[r].what]].effective_size
+          if (worm[move_reasons[r].what].effective_size
               > threat_size) {
-            threat_size = worm[worms[move_reasons[r].what]].effective_size;
+            threat_size = worm[move_reasons[r].what].effective_size;
             type = move_reasons[r].type;
             what = move_reasons[r].what;
           }
@@ -2820,9 +2804,9 @@ reevaluate_ko_threats(int ko_move, int c
         case OWL_ATTACK_THREAT:
         case OWL_DEFEND_THREAT:
         case SEMEAI_THREAT:
-          if (dragon[dragons[move_reasons[r].what]].effective_size
+          if (dragon[move_reasons[r].what].effective_size
               > threat_size) {
-            threat_size = dragon[dragons[move_reasons[r].what]]\
+            threat_size = dragon[move_reasons[r].what]\
                           .effective_size;
             type = move_reasons[r].type;
             what = move_reasons[r].what;
@@ -2853,11 +2837,11 @@ reevaluate_ko_threats(int ko_move, int c
                         "reevaluate_ko_threats", ko_move, EMPTY, NO_MOVE)) {
               switch (type) {
               case ATTACK_THREAT:
-                threat_does_work = attack(worms[what], NULL);
+                threat_does_work = attack(what, NULL);
                 break;
               case DEFEND_THREAT:
-                threat_does_work = (board[worms[what]] != EMPTY
-                                    && find_defense(worms[what], NULL));
+                threat_does_work = (board[what] != EMPTY
+                                    && find_defense(what, NULL));
                 break;
               case OWL_ATTACK_THREAT:
               case OWL_DEFEND_THREAT:




reply via email to

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