diff -N -r -u -X .ignore gnugo-copy/engine/aftermath.c gnugo/engine/aftermath.c
--- gnugo-copy/engine/aftermath.c	2006-12-30 21:28:34.734375000 +0100
+++ gnugo/engine/aftermath.c	2007-01-09 17:42:34.171875000 +0100
@@ -2,7 +2,7 @@
  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
  * http://www.gnu.org/software/gnugo/ for more information.          *
  *                                                                   *
- * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 and 2006       *
+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *
  * by the Free Software Foundation.                                  *
  *                                                                   *
  * This program is free software; you can redistribute it and/or     *
@@ -501,7 +501,7 @@
 	  safety = INVINCIBLE;
 	
 	if (k < 4) {
-	  int apos = worm[pos2].origin;
+	  int apos = find_origin(pos2);
 	  int count_lib = countlib(apos);
 	  
 	  if (!mx[apos]) {
diff -N -r -u -X .ignore gnugo-copy/engine/combination.c gnugo/engine/combination.c
--- gnugo-copy/engine/combination.c	2006-12-30 21:37:10.375000000 +0100
+++ gnugo/engine/combination.c	2007-01-22 23:43:35.468750000 +0100
@@ -572,8 +572,8 @@
    */
   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
     if (board[pos] == other
-	&& worm[pos].origin == pos
-	&& worm[pos].liberties == 2
+	&& find_origin(pos) == pos
+	&& countlib(pos) == 2
 	&& aa_status[pos] == ALIVE) {
       int libs[2];
       findlib(pos, 2, libs);
@@ -587,7 +587,7 @@
       if (!owl_substantial(pos)) {
 	int pos2;
 	for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++)
-	  if (ON_BOARD(pos2) && is_worm_origin(pos2, pos))
+	  if (IS_STONE(board[pos2]) && is_worm_origin(pos2, pos))
 	    aa_status[pos2] = INSUBSTANTIAL;
       }
     }
diff -N -r -u -X .ignore gnugo-copy/engine/dragon.c gnugo/engine/dragon.c
--- gnugo-copy/engine/dragon.c	2006-12-30 21:37:50.796875000 +0100
+++ gnugo/engine/dragon.c	2007-01-19 02:15:33.369402300 +0100
@@ -2,7 +2,7 @@
  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
  * http://www.gnu.org/software/gnugo/ for more information.          *
  *                                                                   *
- * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 and 2006       *
+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *
  * by the Free Software Foundation.                                  *
  *                                                                   *
  * This program is free software; you can redistribute it and/or     *
@@ -442,8 +442,8 @@
     if (ON_BOARD(str)) {
       int food;
 
-      if (worm[str].origin != str
-	  || board[str] == EMPTY
+      if (board[str] == EMPTY
+	  || find_origin(str) != str
 	  || worm[str].lunch == NO_MOVE)
 	continue;
 
@@ -571,7 +571,7 @@
    */
 
   for (str = BOARDMIN; str < BOARDMAX; str++)
-    if (ON_BOARD(str)) {
+    if (IS_STONE(board[str])) {
       if (is_worm_origin(str, str)
 	  && worm[str].attack_codes[0] != 0
 	  && worm[str].defense_codes[0] != 0
diff -N -r -u -X .ignore gnugo-copy/engine/liberty.h gnugo/engine/liberty.h
--- gnugo-copy/engine/liberty.h	2007-01-22 21:58:43.859375000 +0100
+++ gnugo/engine/liberty.h	2007-01-09 17:42:34.343750000 +0100
@@ -797,6 +797,7 @@
 
 #define MAX_TACTICAL_POINTS 10
 
+/* all this data is valid only, when stackp==0 */
 struct worm_data {
   int color;         /* its color */
   int size;          /* its cardinality */
diff -N -r -u -X .ignore gnugo-copy/engine/move_reasons.c gnugo/engine/move_reasons.c
--- gnugo-copy/engine/move_reasons.c	2007-01-22 18:13:22.015625000 +0100
+++ gnugo/engine/move_reasons.c	2007-01-22 16:52:39.750000000 +0100
@@ -2,7 +2,7 @@
  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
  * http://www.gnu.org/software/gnugo/ for more information.          *
  *                                                                   *
- * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 and 2006       *
+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *
  * by the Free Software Foundation.                                  *
  *                                                                   *
  * This program is free software; you can redistribute it and/or     *
@@ -463,8 +463,13 @@
 int
 attack_move_reason_known(int pos, int what)
 {
-  ASSERT1(IS_STONE(board[what]), what);
-  what = worm[what].origin;
+  if (what > 0) {
+    ASSERT_ON_BOARD1(what);
+    ASSERT1(IS_STONE(board[what]), what);
+    ASSERT1(board[what] == worm[what].color, 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))
@@ -481,8 +486,13 @@
 int
 defense_move_reason_known(int pos, int what)
 {
-  ASSERT1(IS_STONE(board[what]), what);
-  what = worm[what].origin;
+  if (what > 0) {
+    ASSERT_ON_BOARD1(what);
+    ASSERT1(IS_STONE(board[what]), what);
+    ASSERT1(board[what] == worm[what].color, 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))
@@ -510,6 +520,13 @@
 int
 owl_attack_move_reason_known(int pos, int what)
 {
+  if (what > 0) {
+    ASSERT_ON_BOARD1(what);
+    ASSERT1(IS_STONE(board[what]), what);
+    ASSERT1(board[what] == dragon[what].color, what);
+    what = dragon[what].origin;
+  }
+
   if (move_reason_known(pos, OWL_ATTACK_MOVE, what))
     return WIN;
   if (move_reason_known(pos, OWL_ATTACK_MOVE_GOOD_KO, what))
@@ -526,6 +543,13 @@
 int
 owl_defense_move_reason_known(int pos, int what)
 {
+  if (what > 0) {
+    ASSERT_ON_BOARD1(what);
+    ASSERT1(IS_STONE(board[what]), what);
+    ASSERT1(board[what] == dragon[what].color, what);
+    what = dragon[what].origin;
+  }
+
   if (move_reason_known(pos, OWL_DEFEND_MOVE, what))
     return WIN;
   if (move_reason_known(pos, OWL_DEFEND_MOVE_GOOD_KO, what))
@@ -553,13 +577,16 @@
 static int
 owl_move_vs_worm_known(int pos, int what)
 {
-  return owl_move_reason_known(pos, dragon[what].origin);
+  return owl_move_reason_known(pos, what);
 }
 
 int
 semeai_move_reason_known(int pos, int what)
 {
-  return move_reason_known(pos, SEMEAI_MOVE, what);
+  ASSERT_ON_BOARD1(what);
+  ASSERT1(IS_STONE(board[what]), what);
+  ASSERT1(board[what] == dragon[what].color, what);
+  return move_reason_known(pos, SEMEAI_MOVE, dragon[what].origin);
 }
 
 /* Check whether a worm is inessential */
@@ -637,6 +664,8 @@
 add_attack_move(int pos, int ww, int code)
 {
   ASSERT_ON_BOARD1(ww);
+  ASSERT1(IS_STONE(board[ww]), ww);
+  ASSERT1(board[ww] == worm[ww].color, ww);
   ww = worm[ww].origin;
 
   if (code == WIN)
@@ -655,6 +684,8 @@
 add_defense_move(int pos, int ww, int code)
 {
   ASSERT_ON_BOARD1(ww);
+  ASSERT1(IS_STONE(board[ww]), ww);
+  ASSERT1(board[ww] == worm[ww].color, ww);
   ww = worm[ww].origin;
 
   if (code == WIN)
@@ -673,8 +704,11 @@
 add_attack_threat_move(int pos, int ww, int code)
 {
   UNUSED(code);
-  
+
   ASSERT_ON_BOARD1(ww);
+  ASSERT1(IS_STONE(board[ww]), ww);
+  ASSERT1(board[ww] == worm[ww].color, ww);
+  
   add_move_reason(pos, ATTACK_THREAT, worm[ww].origin);
 }
 
@@ -684,6 +718,9 @@
 remove_attack_threat_move(int pos, int ww)
 {
   ASSERT_ON_BOARD1(ww);
+  ASSERT1(IS_STONE(board[ww]), ww);
+  ASSERT1(board[ww] == worm[ww].color, ww);
+
   remove_move_reason(pos, ATTACK_THREAT, worm[ww].origin);
 }
 
@@ -697,6 +734,9 @@
   UNUSED(code);
 
   ASSERT_ON_BOARD1(ww);
+  ASSERT1(IS_STONE(board[ww]), ww);
+  ASSERT1(board[ww] == worm[ww].color, ww);
+
   add_move_reason(pos, DEFEND_THREAT, worm[ww].origin);
 }
 
@@ -787,8 +827,7 @@
 
 /*
  * Add to the reasons for the move at (pos) that it connects the
- * dragons at (dr1) and (dr2). Require that the dragons are
- * distinct.
+ * worms at (w1) and (w2).
  */
 void
 add_connection_move(int pos, int w1, int w2)
@@ -796,7 +835,11 @@
   int connection;
 
   ASSERT_ON_BOARD1(w1);
+  ASSERT1(IS_STONE(board[w1]), w1);
+  ASSERT1(board[w1] == worm[w1].color, w1);
   ASSERT_ON_BOARD1(w2);
+  ASSERT1(IS_STONE(board[w2]), w2);
+  ASSERT1(board[w2] == worm[w2].color, w2);
   ASSERT1(worm[w1].color == worm[w2].color, w1);
   if (worm[w1].origin == worm[w2].origin)
     return;
@@ -807,8 +850,7 @@
 
 /*
  * Add to the reasons for the move at (pos) that it cuts the
- * dragons at (dr1) and (dr2). Require that the dragons are
- * distinct.
+ * worms at (w1) and (w2).
  */
 void
 add_cut_move(int pos, int w1, int w2)
@@ -816,10 +858,15 @@
   int connection;
 
   ASSERT_ON_BOARD1(w1);
+  ASSERT1(IS_STONE(board[w1]), w1);
+  ASSERT1(board[w1] == worm[w1].color, w1);
   ASSERT_ON_BOARD1(w2);
+  ASSERT1(IS_STONE(board[w2]), w2);
+  ASSERT1(board[w2] == worm[w2].color, w2);
   ASSERT1(worm[w1].color == worm[w2].color, w1);
   if (worm[w1].origin == worm[w2].origin)
     return;
+  
   connection = find_connection(worm[w1].origin, worm[w2].origin);
   
   /*
@@ -857,6 +904,8 @@
 add_semeai_move(int pos, int dr)
 {
   ASSERT_ON_BOARD1(dr);
+  ASSERT1(IS_STONE(board[dr]), dr);
+  ASSERT1(board[dr] == dragon[dr].color, dr);
   add_move_reason(pos, SEMEAI_MOVE, dragon[dr].origin);
 }
 
@@ -867,14 +916,19 @@
 static void
 add_potential_semeai_move(int pos, int type, int dr1, int dr2)
 {
-  ASSERT1(ON_BOARD(dr1), pos);
-  ASSERT1(ON_BOARD(dr2), pos);
+  ASSERT_ON_BOARD1(dr1);
+  ASSERT1(IS_STONE(board[dr1]), dr1);
+  ASSERT1(board[dr1] == dragon[dr1].color, dr1);
+  ASSERT_ON_BOARD1(dr2);
+  ASSERT1(IS_STONE(board[dr2]), dr2);
+  ASSERT1(board[dr2] == dragon[dr2].color, dr2);
+
   if (next_semeai >= MAX_POTENTIAL_SEMEAI)
     DEBUG(DEBUG_MOVE_REASONS,
 	  "Potential semeai move at %1m dropped as list was full\n", pos);
   else {
-    semeai_target1[next_semeai] = dr1;
-    semeai_target2[next_semeai] = dr2;
+    semeai_target1[next_semeai] = dragon[dr1].origin;
+    semeai_target2[next_semeai] = dragon[dr2].origin;
     add_move_reason(pos, type, next_semeai);
     next_semeai++;
   }
@@ -887,6 +941,12 @@
 void
 add_potential_semeai_attack(int pos, int dr1, int dr2)
 {
+  ASSERT_ON_BOARD1(dr1);
+  ASSERT1(IS_STONE(board[dr1]), dr1);
+  ASSERT1(board[dr1] == dragon[dr1].color, dr1);
+  ASSERT_ON_BOARD1(dr2);
+  ASSERT1(IS_STONE(board[dr2]), dr2);
+  ASSERT1(board[dr2] == dragon[dr2].color, dr2);
   add_potential_semeai_move(pos, POTENTIAL_SEMEAI_ATTACK, dr1, dr2);
 }
 
@@ -897,6 +957,12 @@
 void
 add_potential_semeai_defense(int pos, int dr1, int dr2)
 {
+  ASSERT_ON_BOARD1(dr1);
+  ASSERT1(IS_STONE(board[dr1]), dr1);
+  ASSERT1(board[dr1] == dragon[dr1].color, dr1);
+  ASSERT_ON_BOARD1(dr2);
+  ASSERT1(IS_STONE(board[dr2]), dr2);
+  ASSERT1(board[dr2] == dragon[dr2].color, dr2);
   add_potential_semeai_move(pos, POTENTIAL_SEMEAI_DEFENSE, dr1, dr2);
 }
 
@@ -911,6 +977,8 @@
 add_semeai_threat(int pos, int dr)
 {
   ASSERT_ON_BOARD1(dr);
+  ASSERT1(IS_STONE(board[dr]), dr);
+  ASSERT1(board[dr] == dragon[dr].color, dr);
   add_move_reason(pos, SEMEAI_THREAT, dragon[dr].origin);
 }
 
@@ -949,6 +1017,8 @@
   switch (reason1) {
   case ATTACK_STRING:
     {
+      ASSERT1(IS_STONE(board[target1]), target1);
+      ASSERT1(board[target1] == worm[target1].color, target1);
       what1 = worm[target1].origin;
 
       /* If this string is already attacked, and with no defense, then
@@ -966,6 +1036,8 @@
   switch (reason2) {
   case ATTACK_STRING:
     {
+      ASSERT1(IS_STONE(board[target2]), target2);
+      ASSERT1(board[target2] == worm[target2].color, target2);
       what2 = worm[target2].origin;
 
       /* If this string is already attacked, and with no defense, then
@@ -1019,6 +1091,8 @@
 
   switch (reason1) {
   case DEFEND_STRING:
+    ASSERT1(IS_STONE(board[target1]), target1);
+    ASSERT1(board[target1] == worm[target1].color, target1);
     what1 = worm[target1].origin;
     break;
 
@@ -1028,6 +1102,8 @@
 
   switch (reason2) {
   case DEFEND_STRING:
+    ASSERT1(IS_STONE(board[target2]), target2);
+    ASSERT1(board[target2] == worm[target2].color, target2);
     what2 = worm[target2].origin;
     break;
 
@@ -1043,10 +1119,17 @@
 void
 add_loss_move(int pos, int target1, int target2)
 {
-  int what1 = dragon[target1].origin;
-  int what2 = worm[target2].origin;
-  int index = find_pair_data(what1, what2);
-  ASSERT1(target2 != NO_MOVE, pos);
+  int index;
+
+  ASSERT_ON_BOARD1(target1);
+  ASSERT1(IS_STONE(board[target1]), target1);
+  ASSERT1(board[target1] == dragon[target1].color, target1);
+  ASSERT_ON_BOARD1(target2);
+  ASSERT1(IS_STONE(board[target2]), target2);
+  ASSERT1(board[target2] == worm[target2].color, target2);
+
+  index = find_pair_data(dragon[target1].origin,
+			 worm[target2].origin);
   add_move_reason(pos, OWL_DEFEND_MOVE_LOSS, index);
 }
 
@@ -1121,9 +1204,10 @@
 void
 add_strategical_attack_move(int pos, int dr)
 {
-  dr = dragon[dr].origin;
   ASSERT_ON_BOARD1(dr);
-  add_move_reason(pos, STRATEGIC_ATTACK_MOVE, dr);
+  ASSERT1(IS_STONE(board[dr]), dr);
+  ASSERT1(board[dr] == dragon[dr].color, dr);
+  add_move_reason(pos, STRATEGIC_ATTACK_MOVE, dragon[dr].origin);
 }
 
 /*
@@ -1133,9 +1217,10 @@
 void
 add_strategical_defense_move(int pos, int dr)
 {
-  dr = dragon[dr].origin;
   ASSERT_ON_BOARD1(dr);
-  add_move_reason(pos, STRATEGIC_DEFEND_MOVE, dr);
+  ASSERT1(IS_STONE(board[dr]), dr);
+  ASSERT1(board[dr] == dragon[dr].color, dr);
+  add_move_reason(pos, STRATEGIC_DEFEND_MOVE, dragon[dr].origin);
 }
 
 /*
@@ -1145,9 +1230,11 @@
 void
 add_owl_attack_move(int pos, int dr, int kworm, int code)
 {
+  ASSERT_ON_BOARD1(dr);
+  ASSERT1(IS_STONE(board[dr]), dr);
+  ASSERT1(board[dr] == dragon[dr].color, dr);
   dr = dragon[dr].origin;
 
-  ASSERT_ON_BOARD1(dr);
   if (code == WIN)
     add_move_reason(pos, OWL_ATTACK_MOVE, dr);
   else if (code == KO_A)
@@ -1156,6 +1243,8 @@
     add_move_reason(pos, OWL_ATTACK_MOVE_BAD_KO, dr);
   else if (code == GAIN) {
     ASSERT_ON_BOARD1(kworm);
+    ASSERT1(IS_STONE(board[kworm]), kworm);
+    ASSERT1(board[kworm] == worm[kworm].color, kworm);
     add_move_reason(pos, OWL_ATTACK_MOVE_GAIN, find_pair_data(dr, kworm));
   }
 }
@@ -1167,9 +1256,11 @@
 void
 add_owl_defense_move(int pos, int dr, int code)
 {
+  ASSERT_ON_BOARD1(dr);
+  ASSERT1(IS_STONE(board[dr]), dr);
+  ASSERT1(board[dr] == dragon[dr].color, dr);
   dr = dragon[dr].origin;
 
-  ASSERT_ON_BOARD1(dr);
   if (code == WIN)
     add_move_reason(pos, OWL_DEFEND_MOVE, dr);
   else if (code == KO_A)
@@ -1188,9 +1279,9 @@
 add_owl_attack_threat_move(int pos, int dr, int code)
 {
   UNUSED(code);
-  dr = dragon[dr].origin;
-  
   ASSERT_ON_BOARD1(dr);
+  ASSERT1(IS_STONE(board[dr]), dr);
+  ASSERT1(board[dr] == dragon[dr].color, dr);
   add_move_reason(pos, OWL_ATTACK_THREAT, dragon[dr].origin);
   add_worthwhile_threat_move(pos);
 }
@@ -1202,8 +1293,9 @@
 void
 add_owl_uncertain_defense_move(int pos, int dr)
 {
-  dr = dragon[dr].origin;
   ASSERT_ON_BOARD1(dr);
+  ASSERT1(IS_STONE(board[dr]), dr);
+  ASSERT1(board[dr] == dragon[dr].color, dr);
   add_move_reason(pos, UNCERTAIN_OWL_DEFENSE, dragon[dr].origin);
 }
 
@@ -1214,8 +1306,9 @@
 void
 add_owl_uncertain_attack_move(int pos, int dr)
 {
-  dr = dragon[dr].origin;
   ASSERT_ON_BOARD1(dr);
+  ASSERT1(IS_STONE(board[dr]), dr);
+  ASSERT1(board[dr] == dragon[dr].color, dr);
   add_move_reason(pos, UNCERTAIN_OWL_ATTACK, dragon[dr].origin);
 }
 
@@ -1229,9 +1322,9 @@
 add_owl_defense_threat_move(int pos, int dr, int code)
 {
   UNUSED(code);
-  dr = dragon[dr].origin;
-
   ASSERT_ON_BOARD1(dr);
+  ASSERT1(IS_STONE(board[dr]), dr);
+  ASSERT1(board[dr] == dragon[dr].color, dr);
   add_move_reason(pos, OWL_DEFEND_THREAT, dragon[dr].origin);
   add_worthwhile_threat_move(pos);
 }
@@ -1269,6 +1362,8 @@
 add_owl_prevent_threat_move(int pos, int dr)
 {
   ASSERT_ON_BOARD1(dr);
+  ASSERT1(IS_STONE(board[dr]), dr);
+  ASSERT1(board[dr] == dragon[dr].color, dr);
   add_move_reason(pos, OWL_PREVENT_THREAT, dragon[dr].origin);
 }
 
@@ -1418,7 +1513,7 @@
      * move is unsafe.
      */
     if (move_reasons[r].type == DEFEND_MOVE)
-      mark_string(worm[what].origin, saved, 1);
+      mark_string(what, saved, 1);
     else if (move_reasons[r].type == OWL_DEFEND_MOVE_LOSS) {
       int origin = dragon[what].origin;
       int kworm = worm[what].origin;
@@ -1426,7 +1521,7 @@
       for (ii = BOARDMIN; ii < BOARDMAX; ii++)
 	if (IS_STONE(board[ii]) && dragon[ii].origin == origin
 	    && worm[ii].origin != kworm)
-	  mark_string(worm[ii].origin, saved, 1);
+	  mark_string(ii, saved, 1);
     }
   }    
 }
@@ -1990,7 +2085,8 @@
   int k;
   ASSERT_ON_BOARD1(move);
   ASSERT_ON_BOARD1(target);
-  ASSERT1(IS_STONE(worm[target].color), move);
+  ASSERT1(IS_STONE(board[target]), target);
+  ASSERT1(board[target] == worm[target].color, target);
 
   target = worm[target].origin;
   for (k = 0; k < MAX_ATTACK_THREATS; k++) {
@@ -2011,7 +2107,8 @@
   int k;
   ASSERT_ON_BOARD1(move);
   ASSERT_ON_BOARD1(target);
-  ASSERT1(IS_STONE(worm[target].color), move);
+  ASSERT1(IS_STONE(board[target]), target);
+  ASSERT1(board[target] == worm[target].color, target);
 
   target = worm[target].origin;
   for (k = 0; k < MAX_ATTACK_THREATS; k++) {
diff -N -r -u -X .ignore gnugo-copy/engine/owl.c gnugo/engine/owl.c
--- gnugo-copy/engine/owl.c	2007-01-22 22:01:07.640625000 +0100
+++ gnugo/engine/owl.c	2007-01-22 23:48:10.703125000 +0100
@@ -454,7 +454,7 @@
   if (verbose > 0)
     verbose--;
   for (str = BOARDMIN; str < BOARDMAX; str++) 
-    if (ON_BOARD(str) && ms[str] && worm[str].origin == str) {
+    if (ON_BOARD(str) && ms[str] && find_origin(str) == str) {
       int adj;
       int adjs[MAXCHAIN];
       int k;
@@ -1947,14 +1947,14 @@
 	if (board[worm_goal] == EMPTY
 	    || countlib(worm_goal) > 1)
 	  continue;
-	if (worm[worm_goal].size > size) {
+	if (countstones(worm_goal) > size) {
 	  saveworm = k;
-	  size = worm[worm_goal].size;
+	  size = countstones(worm_goal);
 	}
       }
       if (saveworm != MAX_GOAL_WORMS && size >= 3) {
 	acode = GAIN;
-	findlib(worm[owl_goal_worm[saveworm]].origin, 1, &mpos);
+	findlib(find_origin(owl_goal_worm[saveworm]), 1, &mpos);
 	/* ASSERT1( ... */
       }
     }
@@ -4636,7 +4636,8 @@
 
   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
     if (ON_BOARD(pos)) {
-      if (is_same_worm(pos, apos) || is_same_worm(pos, bpos))
+      if (IS_STONE(board[pos])
+	  && (is_same_worm(pos, apos) || is_same_worm(pos, bpos)))
 	owl->goal[pos] = 1;
       else
 	owl->goal[pos] = 0;
@@ -6916,8 +6917,8 @@
 	continue;
 
       for (ii = BOARDMIN; ii < BOARDMAX && w < MAX_GOAL_WORMS; ii++)
-	if (ON_BOARD(ii) && board[ii] && worm[ii].origin == ii
-	    && worm[ii].size >= 3 && dragon[ii].id == d)
+	if (IS_STONE(board[ii]) && find_origin(ii) == ii
+	    && countstones(ii) >= 3 && dragon[ii].id == d)
 	  goal_worm[w++] = ii;
     }
   }
diff -N -r -u -X .ignore gnugo-copy/engine/utils.c gnugo/engine/utils.c
--- gnugo-copy/engine/utils.c	2006-11-12 17:01:14.000000000 +0100
+++ gnugo/engine/utils.c	2007-01-22 23:49:31.468750000 +0100
@@ -2,7 +2,7 @@
  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
  * http://www.gnu.org/software/gnugo/ for more information.          *
  *                                                                   *
- * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 and 2006       *
+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *
  * by the Free Software Foundation.                                  *
  *                                                                   *
  * This program is free software; you can redistribute it and/or     *
@@ -1075,7 +1075,7 @@
      */
     if (board[bpos] != color)
       continue;
-    if (liberties <= worm[bpos].liberties
+    if (liberties <= countlib(bpos)
 	&& liberties <= 4)
       trouble = 1;
     else
@@ -1139,7 +1139,7 @@
 	      *return_value += 2.0 * worm[kworm].effective_size;
 	      if (safe_stones)
 		for (ii = BOARDMIN; ii < BOARDMAX; ii++)
-		  if (ON_BOARD(ii) && worm[ii].origin == worm[kworm].origin)
+		  if (IS_STONE(board[ii]) && is_same_worm(ii, kworm))
 		    safe_stones[ii] = 0;
 	    }
 	  }
@@ -1148,7 +1148,7 @@
 	  *return_value += 2.0 * worm[kworm].effective_size;
 	  if (safe_stones)
 	    for (ii = BOARDMIN; ii < BOARDMAX; ii++)
-	      if (ON_BOARD(ii) && worm[ii].origin == worm[kworm].origin)
+	      if (IS_STONE(board[ii]) && is_same_worm(ii, kworm))
 		safe_stones[ii] = 0;
 	}
       }
@@ -1182,7 +1182,7 @@
   
   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
     if (!IS_STONE(board[pos])
-	|| worm[pos].origin != pos
+	|| find_origin(pos) != pos
 	|| pos == move)
       continue;
     
@@ -1217,11 +1217,11 @@
       *return_value += worm[pos].effective_size;
       if (safe_stones) /* Can't use mark_string. */
 	for (ii = BOARDMIN; ii < BOARDMAX; ii++)
-	  if (worm[ii].origin == worm[pos].origin)
+	  if (IS_STONE(board[ii]) && is_same_worm(ii, pos))
 	    safe_stones[ii] = 0;
     }
     else if (board[pos] == other
-	     && worm[pos].origin == pos
+	     && find_origin(pos) == pos
 	     && worm[pos].attack_codes[0] != 0
 	     && worm[pos].defense_codes[0] == 0
 	     && find_defense(pos, NULL)) {
diff -N -r -u -X .ignore gnugo-copy/engine/value_moves.c gnugo/engine/value_moves.c
--- gnugo-copy/engine/value_moves.c	2007-01-22 18:13:11.000000000 +0100
+++ gnugo/engine/value_moves.c	2007-01-09 17:42:34.562500000 +0100
@@ -2,7 +2,7 @@
  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
  * http://www.gnu.org/software/gnugo/ for more information.          *
  *                                                                   *
- * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 and 2006       *
+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *
  * by the Free Software Foundation.                                  *
  *                                                                   *
  * This program is free software; you can redistribute it and/or     *
@@ -150,7 +150,7 @@
   /* Identify the unstable worms and store them in a list. */
   for (ii = BOARDMIN; ii < BOARDMAX; ii++) {
     if (IS_STONE(board[ii])
-	&& worm[ii].origin == ii
+	&& find_origin(ii) == ii
 	&& worm[ii].attack_codes[0] != 0
 	&& worm[ii].defense_codes[0] != 0) {
       unstable_worms[N] = ii;
@@ -944,7 +944,7 @@
 	 * dragons.
 	 */
 	if (!attack_move) {
-	  int strategically_valuable = (worm[aa].size > 3);
+	  int strategically_valuable = (countstones(aa) > 3);
 	  signed char neighbor_dragons[BOARDMAX];
 
 	  memset(neighbor_dragons, 0, sizeof(neighbor_dragons));
@@ -1748,7 +1748,7 @@
 	continue;
       
       if (ON_BOARD(pos2)
-	  && worm[pos2].color == color
+	  && board[pos2] == color
 	  && dragon[pos2].status != DEAD
 	  && !disconnect(pos, pos2, NULL)) {
 	result = 1;
@@ -2002,8 +2002,8 @@
 	 * FIXME: This is somewhat halfhearted since only one defense
 	 * move is tested.
 	 */
-	if (!is_known_good_attack_threat(pos, aa)
-	    && board[aa] != EMPTY
+	if (board[aa] != EMPTY
+	    && !is_known_good_attack_threat(pos, aa)
 	    && (move[pos].move_safety == 1
 		|| adjacent_to_nondead_stone(pos, color)
 		|| owl_defense_move_reason_known(pos, -1))
diff -N -r -u -X .ignore gnugo-copy/engine/worm.c gnugo/engine/worm.c
--- gnugo-copy/engine/worm.c	2007-01-22 17:19:37.531250000 +0100
+++ gnugo/engine/worm.c	2007-01-22 17:21:29.859375000 +0100
@@ -190,8 +190,8 @@
 	continue;
       
       for (k = 0; k < 4; k++) {
-	if (!ON_BOARD(pos2 + delta[k])
-	    || worm[pos2 + delta[k]].origin != pos)
+	if (!IS_STONE(board[pos2 + delta[k]])
+	    || find_origin(pos2 + delta[k]) != pos)
 	  continue;
 	
 	ASSERT1(board[pos2 + delta[k]] == board[pos], pos);
@@ -200,9 +200,9 @@
 	 * store it into (w1), otherwise store it into (w2).
 	 */
 	if (w1 == NO_MOVE)
-	  w1 = worm[pos2].origin;
+	  w1 = find_origin(pos2);
 	else if (!is_same_worm(pos2, w1))
-	  w2 = worm[pos2].origin;
+	  w2 = find_origin(pos2);
       }
     }
     
@@ -285,7 +285,7 @@
 	 */
 	for (str = BOARDMIN; str < BOARDMAX; str++) {
 	  if (!IS_STONE(board[str])
-	      || !is_worm_origin(str, str))
+	      || find_origin(str) != str)
 	    continue;
 	  
 	  /* If the worm is of the opposite color to the move,
@@ -491,7 +491,7 @@
 
   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
     if (IS_STONE(board[pos])
-	&& worm[pos].origin == pos
+	&& find_origin(pos) == pos
 	&& worm[pos].genus == 0
 	&& worm[pos].liberties2 == 0
 	&& !worm[pos].cutstone
@@ -995,7 +995,7 @@
       continue;
     for (k = 0; k < 8; k++) {
       int apos = pos + delta[k];
-      if (ON_BOARD(apos) && is_same_worm(apos, str)) {
+      if (IS_STONE(board[apos]) && is_same_worm(apos, str)) {
 	if (worm[pos].attack_codes[0] != 0 && !is_ko_point(pos)) {
 	  /*
 	   * If several adjacent lunches are found, we pick the 
@@ -1030,7 +1030,7 @@
 int
 is_same_worm(int w1, int w2)
 {
-  return worm[w1].origin == worm[w2].origin;
+  return same_string(w1, w2);
 }
 
 
@@ -1041,7 +1041,7 @@
 int
 is_worm_origin(int w, int pos)
 {
-  return worm[w].origin == pos;
+  return find_origin(w) == pos;
 }
 
 
@@ -1222,7 +1222,7 @@
   ASSERT1(IS_STONE(worm[str].color), str);
 
   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
-    if (board[pos] == board[str] && is_same_worm(pos, str)
+    if (board[pos] == board[str] && worm[pos].origin == worm[str].origin
 	&& pos != str)
       worm[pos] = worm[str];
 }
@@ -1238,11 +1238,8 @@
   int k;
   
   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
-    if (!ON_BOARD(pos) || board[pos] == EMPTY)
-      continue;
-
-    if (!is_worm_origin(pos, pos))
-      continue;
+    if (!IS_STONE(board[pos]) || !is_worm_origin(pos, pos))
+       continue;
 
     if (board[pos] == OTHER_COLOR(color)) {
       for (k = 0; k < MAX_TACTICAL_POINTS; k++) {
@@ -1589,7 +1586,7 @@
       /* transform pattern real coordinate */
       int pos = AFFINE_TRANSFORM(pattern->patn[k].offset, ll, anchor);
 
-      int str = worm[pos].origin;
+      int str = find_origin(pos);
 
       /* A string with 5 liberties or more is considered tactically alive. */
       if (countlib(str) > 4)
@@ -1676,7 +1673,7 @@
     if (pattern->patn[k].att == ATT_O) {
       /* transform pattern real coordinate */
       int pos = AFFINE_TRANSFORM(pattern->patn[k].offset, ll, anchor);
-      int str = worm[pos].origin;
+      int str = find_origin(pos);
 
       if (worm[str].attack_codes[0] == 0
 	  || defense_move_known(move, str))
@@ -1711,7 +1708,7 @@
   memset(safe_stones, 0, BOARDMAX * sizeof(signed char));
   for (ii = BOARDMIN; ii < BOARDMAX; ii++) // TICKET #155
     if (IS_STONE(board[ii])
-	&& worm[ii].origin == ii) {
+	&& find_origin(ii) == ii) {
       if (worm[ii].attack_codes[0] == 0
 	  || (board[ii] == color
 	      && worm[ii].defense_codes[0] != 0))
diff -N -r -u -X .ignore gnugo-copy/patterns/helpers.c gnugo/patterns/helpers.c
--- gnugo-copy/patterns/helpers.c	2006-11-12 17:34:22.000000000 +0100
+++ gnugo/patterns/helpers.c	2007-01-22 23:51:32.343750000 +0100
@@ -2,7 +2,7 @@
  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
  * http://www.gnu.org/software/gnugo/ for more information.          *
  *                                                                   *
- * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 and 2006       *
+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *
  * by the Free Software Foundation.                                  *
  *                                                                   *
  * This program is free software; you can redistribute it and/or     *
@@ -678,7 +678,8 @@
 		  move, worma, wormb);
       }
       else if (!defend_both(worma, wormb))
-        add_either_move(move, ATTACK_STRING, worma, ATTACK_STRING, wormb);
+        add_either_move(move, ATTACK_STRING, find_origin(worma),
+			ATTACK_STRING, find_origin(wormb));
       else {
 	if (0)
 	  gprintf("%1m: Rej. attack_either_move for %1m & %1m (doesn't work)\n",
