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 (board[pos2] == other && find_origin(pos2) == pos)
 	    aa_status[pos2] = INSUBSTANTIAL;
       }
     }
@@ -597,7 +597,7 @@
     gprintf("compute_aa_status() for %C\n", color);
     gprintf("aa_status: (ALIVE worms not listed)\n");
     for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
-      if (board[pos] == other && is_worm_origin(pos, pos)) {
+      if (board[pos] == other && find_origin(pos) == pos) {
 	const char *status = "UNKNOWN (shouldn't happen)";
 	if (aa_status[pos] == DEAD)
 	  status = "DEAD";
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     *
@@ -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;
@@ -1954,7 +1954,7 @@
       }
       if (saveworm != MAX_GOAL_WORMS && size >= 3) {
 	acode = GAIN;
-	findlib(worm[owl_goal_worm[saveworm]].origin, 1, &mpos);
+	findlib(owl_goal_worm[saveworm], 1, &mpos);
 	/* ASSERT1( ... */
       }
     }
@@ -4633,10 +4633,14 @@
   int color = board[apos];
   
   ASSERT1(bpos == NO_MOVE || board[bpos] == color, bpos);
+  apos = find_origin(apos);
+  if (bpos != NO_MOVE)
+    bpos = find_origin(bpos);
 
   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])
+	  && (find_origin(pos) == apos || find_origin(pos) == bpos))
 	owl->goal[pos] = 1;
       else
 	owl->goal[pos] = 0;
@@ -6916,8 +6920,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
@@ -1137,10 +1137,12 @@
 	    int kworm = move + delta[l];
 	    if (board[kworm] == color) {
 	      *return_value += 2.0 * worm[kworm].effective_size;
-	      if (safe_stones)
+	      if (safe_stones) {
+		kworm = find_origin(kworm);
 		for (ii = BOARDMIN; ii < BOARDMAX; ii++)
-		  if (ON_BOARD(ii) && worm[ii].origin == worm[kworm].origin)
+		  if (IS_STONE(board[ii]) && find_origin(ii) == kworm)
 		    safe_stones[ii] = 0;
+	      }
 	    }
 	  }
	}
@@ -1148,7 +1150,8 @@
 	  *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])
+		  && find_origin(ii) == find_origin(kworm))
 		safe_stones[ii] = 0;
 	}
       }
@@ -1182,7 +1185,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 +1220,12 @@
       *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])
+	      && find_origin(ii) == find_origin(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-27 18:25:37.734375000 +0100
+++ gnugo/engine/value_moves.c	2007-01-27 18:22:50.796875000 +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     *
@@ -839,6 +839,8 @@
       if (r < 0)
 	break;
       
+	gg_assert(stackp==0);
+
       if (move_reasons[r].type == ATTACK_MOVE
 	  || move_reasons[r].type == DEFEND_MOVE) {
 	int attack_move;
@@ -1749,7 +1751,7 @@
 	continue;
       
       if (ON_BOARD(pos2)
-	  && worm[pos2].color == color
+	  && board[pos2] == color
 	  && dragon[pos2].status != DEAD
 	  && !disconnect(pos, pos2, NULL)) {
 	result = 1;
@@ -2003,8 +2005,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-27 18:12:25.015625000 +0100
+++ gnugo/engine/worm.c	2007-01-27 18:09:35.546875000 +0100
@@ -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,
@@ -489,6 +489,8 @@
    * opponent's eye space.
    */
 
+  gg_assert(stackp == 0);
+
   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
     if (IS_STONE(board[pos])
 	&& worm[pos].origin == pos
@@ -998,7 +1000,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 
@@ -1033,6 +1035,7 @@
 int
 is_same_worm(int w1, int w2)
 {
+  gg_assert(stackp==0);
   return worm[w1].origin == worm[w2].origin;
 }
 
@@ -1044,6 +1047,7 @@
 int
 is_worm_origin(int w, int pos)
 {
+  gg_assert(stackp==0);
   return worm[w].origin == pos;
 }
 
@@ -1221,12 +1225,13 @@
 propagate_worm2(int str)
 {
   int pos;
+  int origin;
   ASSERT_ON_BOARD1(str);
   ASSERT1(IS_STONE(worm[str].color), str);
 
+  origin = worm[str].origin;
   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
-    if (board[pos] == board[str] && is_same_worm(pos, str)
-	&& pos != str)
+    if (worm[pos].origin == origin && pos != str)
       worm[pos] = worm[str];
 }
 
@@ -1241,11 +1246,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++) {
@@ -1564,6 +1566,8 @@
   int k;
   UNUSED(data);
 
+  gg_assert(stackp==0);
+
   move = AFFINE_TRANSFORM(pattern->move_offset, ll, anchor);
 
   /* If the pattern has a constraint, call the autohelper to see
@@ -1652,6 +1656,8 @@
   int k;
   UNUSED(data);
 
+  gg_assert(stackp==0);
+
   move = AFFINE_TRANSFORM(pattern->move_offset, ll, anchor);
   
   /* If the pattern has a constraint, call the autohelper to see
