Ticket #162: worm_data_v2.diff

File worm_data_v2.diff, 24.9 KB (added by draqo, 3 years ago)

propagate_worm2 correction - previous ver was working because function was called only with origin of worm as str

Line 
1diff -N -r -u -X .ignore gnugo-copy/engine/aftermath.c gnugo/engine/aftermath.c
2--- gnugo-copy/engine/aftermath.c       2006-12-30 21:28:34.734375000 +0100
3+++ gnugo/engine/aftermath.c    2007-01-09 17:42:34.171875000 +0100
4@@ -2,7 +2,7 @@
5  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
6  * http://www.gnu.org/software/gnugo/ for more information.          *
7  *                                                                   *
8- * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 and 2006       *
9+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *
10  * by the Free Software Foundation.                                  *
11  *                                                                   *
12  * This program is free software; you can redistribute it and/or     *
13@@ -501,7 +501,7 @@
14          safety = INVINCIBLE;
15       
16        if (k < 4) {
17-         int apos = worm[pos2].origin;
18+         int apos = find_origin(pos2);
19          int count_lib = countlib(apos);
20         
21          if (!mx[apos]) {
22diff -N -r -u -X .ignore gnugo-copy/engine/combination.c gnugo/engine/combination.c
23--- gnugo-copy/engine/combination.c     2006-12-30 21:37:10.375000000 +0100
24+++ gnugo/engine/combination.c  2007-01-22 23:43:35.468750000 +0100
25@@ -572,8 +572,8 @@
26    */
27   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
28     if (board[pos] == other
29-       && worm[pos].origin == pos
30-       && worm[pos].liberties == 2
31+       && find_origin(pos) == pos
32+       && countlib(pos) == 2
33        && aa_status[pos] == ALIVE) {
34       int libs[2];
35       findlib(pos, 2, libs);
36@@ -587,7 +587,7 @@
37       if (!owl_substantial(pos)) {
38        int pos2;
39        for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++)
40-         if (ON_BOARD(pos2) && is_worm_origin(pos2, pos))
41+         if (board[pos2] == other && find_origin(pos2) == pos)
42            aa_status[pos2] = INSUBSTANTIAL;
43       }
44     }
45@@ -597,7 +597,7 @@
46     gprintf("compute_aa_status() for %C\n", color);
47     gprintf("aa_status: (ALIVE worms not listed)\n");
48     for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
49-      if (board[pos] == other && is_worm_origin(pos, pos)) {
50+      if (board[pos] == other && find_origin(pos) == pos) {
51        const char *status = "UNKNOWN (shouldn't happen)";
52        if (aa_status[pos] == DEAD)
53          status = "DEAD";
54diff -N -r -u -X .ignore gnugo-copy/engine/dragon.c gnugo/engine/dragon.c
55--- gnugo-copy/engine/dragon.c  2006-12-30 21:37:50.796875000 +0100
56+++ gnugo/engine/dragon.c       2007-01-19 02:15:33.369402300 +0100
57@@ -2,7 +2,7 @@
58  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
59  * http://www.gnu.org/software/gnugo/ for more information.          *
60  *                                                                   *
61- * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 and 2006       *
62+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *
63  * by the Free Software Foundation.                                  *
64  *                                                                   *
65  * This program is free software; you can redistribute it and/or     *
66@@ -571,7 +571,7 @@
67    */
68 
69   for (str = BOARDMIN; str < BOARDMAX; str++)
70-    if (ON_BOARD(str)) {
71+    if (IS_STONE(board[str])) {
72       if (is_worm_origin(str, str)
73          && worm[str].attack_codes[0] != 0
74          && worm[str].defense_codes[0] != 0
75diff -N -r -u -X .ignore gnugo-copy/engine/liberty.h gnugo/engine/liberty.h
76--- gnugo-copy/engine/liberty.h 2007-01-22 21:58:43.859375000 +0100
77+++ gnugo/engine/liberty.h      2007-01-09 17:42:34.343750000 +0100
78@@ -797,6 +797,7 @@
79 
80 #define MAX_TACTICAL_POINTS 10
81 
82+/* all this data is valid only, when stackp==0 */
83 struct worm_data {
84   int color;         /* its color */
85   int size;          /* its cardinality */
86diff -N -r -u -X .ignore gnugo-copy/engine/move_reasons.c gnugo/engine/move_reasons.c
87--- gnugo-copy/engine/move_reasons.c    2007-01-22 18:13:22.015625000 +0100
88+++ gnugo/engine/move_reasons.c 2007-01-22 16:52:39.750000000 +0100
89@@ -2,7 +2,7 @@
90  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
91  * http://www.gnu.org/software/gnugo/ for more information.          *
92  *                                                                   *
93- * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 and 2006       *
94+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *
95  * by the Free Software Foundation.                                  *
96  *                                                                   *
97  * This program is free software; you can redistribute it and/or     *
98@@ -463,8 +463,13 @@
99 int
100 attack_move_reason_known(int pos, int what)
101 {
102-  ASSERT1(IS_STONE(board[what]), what);
103-  what = worm[what].origin;
104+  if (what > 0) {
105+    ASSERT_ON_BOARD1(what);
106+    ASSERT1(IS_STONE(board[what]), what);
107+    ASSERT1(board[what] == worm[what].color, what);
108+    what = worm[what].origin;
109+  }
110+
111   if (move_reason_known(pos, ATTACK_MOVE, what))
112     return WIN;
113   if (move_reason_known(pos, ATTACK_MOVE_GOOD_KO, what))
114@@ -481,8 +486,13 @@
115 int
116 defense_move_reason_known(int pos, int what)
117 {
118-  ASSERT1(IS_STONE(board[what]), what);
119-  what = worm[what].origin;
120+  if (what > 0) {
121+    ASSERT_ON_BOARD1(what);
122+    ASSERT1(IS_STONE(board[what]), what);
123+    ASSERT1(board[what] == worm[what].color, what);
124+    what = worm[what].origin;
125+  }
126+
127   if (move_reason_known(pos, DEFEND_MOVE, what))
128     return WIN;
129   if (move_reason_known(pos, DEFEND_MOVE_GOOD_KO, what))
130@@ -510,6 +520,13 @@
131 int
132 owl_attack_move_reason_known(int pos, int what)
133 {
134+  if (what > 0) {
135+    ASSERT_ON_BOARD1(what);
136+    ASSERT1(IS_STONE(board[what]), what);
137+    ASSERT1(board[what] == dragon[what].color, what);
138+    what = dragon[what].origin;
139+  }
140+
141   if (move_reason_known(pos, OWL_ATTACK_MOVE, what))
142     return WIN;
143   if (move_reason_known(pos, OWL_ATTACK_MOVE_GOOD_KO, what))
144@@ -526,6 +543,13 @@
145 int
146 owl_defense_move_reason_known(int pos, int what)
147 {
148+  if (what > 0) {
149+    ASSERT_ON_BOARD1(what);
150+    ASSERT1(IS_STONE(board[what]), what);
151+    ASSERT1(board[what] == dragon[what].color, what);
152+    what = dragon[what].origin;
153+  }
154+
155   if (move_reason_known(pos, OWL_DEFEND_MOVE, what))
156     return WIN;
157   if (move_reason_known(pos, OWL_DEFEND_MOVE_GOOD_KO, what))
158@@ -553,13 +577,16 @@
159 static int
160 owl_move_vs_worm_known(int pos, int what)
161 {
162-  return owl_move_reason_known(pos, dragon[what].origin);
163+  return owl_move_reason_known(pos, what);
164 }
165 
166 int
167 semeai_move_reason_known(int pos, int what)
168 {
169-  return move_reason_known(pos, SEMEAI_MOVE, what);
170+  ASSERT_ON_BOARD1(what);
171+  ASSERT1(IS_STONE(board[what]), what);
172+  ASSERT1(board[what] == dragon[what].color, what);
173+  return move_reason_known(pos, SEMEAI_MOVE, dragon[what].origin);
174 }
175 
176 /* Check whether a worm is inessential */
177@@ -637,6 +664,8 @@
178 add_attack_move(int pos, int ww, int code)
179 {
180   ASSERT_ON_BOARD1(ww);
181+  ASSERT1(IS_STONE(board[ww]), ww);
182+  ASSERT1(board[ww] == worm[ww].color, ww);
183   ww = worm[ww].origin;
184 
185   if (code == WIN)
186@@ -655,6 +684,8 @@
187 add_defense_move(int pos, int ww, int code)
188 {
189   ASSERT_ON_BOARD1(ww);
190+  ASSERT1(IS_STONE(board[ww]), ww);
191+  ASSERT1(board[ww] == worm[ww].color, ww);
192   ww = worm[ww].origin;
193 
194   if (code == WIN)
195@@ -673,8 +704,11 @@
196 add_attack_threat_move(int pos, int ww, int code)
197 {
198   UNUSED(code);
199
200+
201   ASSERT_ON_BOARD1(ww);
202+  ASSERT1(IS_STONE(board[ww]), ww);
203+  ASSERT1(board[ww] == worm[ww].color, ww);
204
205   add_move_reason(pos, ATTACK_THREAT, worm[ww].origin);
206 }
207 
208@@ -684,6 +718,9 @@
209 remove_attack_threat_move(int pos, int ww)
210 {
211   ASSERT_ON_BOARD1(ww);
212+  ASSERT1(IS_STONE(board[ww]), ww);
213+  ASSERT1(board[ww] == worm[ww].color, ww);
214+
215   remove_move_reason(pos, ATTACK_THREAT, worm[ww].origin);
216 }
217 
218@@ -697,6 +734,9 @@
219   UNUSED(code);
220 
221   ASSERT_ON_BOARD1(ww);
222+  ASSERT1(IS_STONE(board[ww]), ww);
223+  ASSERT1(board[ww] == worm[ww].color, ww);
224+
225   add_move_reason(pos, DEFEND_THREAT, worm[ww].origin);
226 }
227 
228@@ -787,8 +827,7 @@
229 
230 /*
231  * Add to the reasons for the move at (pos) that it connects the
232- * dragons at (dr1) and (dr2). Require that the dragons are
233- * distinct.
234+ * worms at (w1) and (w2).
235  */
236 void
237 add_connection_move(int pos, int w1, int w2)
238@@ -796,7 +835,11 @@
239   int connection;
240 
241   ASSERT_ON_BOARD1(w1);
242+  ASSERT1(IS_STONE(board[w1]), w1);
243+  ASSERT1(board[w1] == worm[w1].color, w1);
244   ASSERT_ON_BOARD1(w2);
245+  ASSERT1(IS_STONE(board[w2]), w2);
246+  ASSERT1(board[w2] == worm[w2].color, w2);
247   ASSERT1(worm[w1].color == worm[w2].color, w1);
248   if (worm[w1].origin == worm[w2].origin)
249     return;
250@@ -807,8 +850,7 @@
251 
252 /*
253  * Add to the reasons for the move at (pos) that it cuts the
254- * dragons at (dr1) and (dr2). Require that the dragons are
255- * distinct.
256+ * worms at (w1) and (w2).
257  */
258 void
259 add_cut_move(int pos, int w1, int w2)
260@@ -816,10 +858,15 @@
261   int connection;
262 
263   ASSERT_ON_BOARD1(w1);
264+  ASSERT1(IS_STONE(board[w1]), w1);
265+  ASSERT1(board[w1] == worm[w1].color, w1);
266   ASSERT_ON_BOARD1(w2);
267+  ASSERT1(IS_STONE(board[w2]), w2);
268+  ASSERT1(board[w2] == worm[w2].color, w2);
269   ASSERT1(worm[w1].color == worm[w2].color, w1);
270   if (worm[w1].origin == worm[w2].origin)
271     return;
272
273   connection = find_connection(worm[w1].origin, worm[w2].origin);
274   
275   /*
276@@ -857,6 +904,8 @@
277 add_semeai_move(int pos, int dr)
278 {
279   ASSERT_ON_BOARD1(dr);
280+  ASSERT1(IS_STONE(board[dr]), dr);
281+  ASSERT1(board[dr] == dragon[dr].color, dr);
282   add_move_reason(pos, SEMEAI_MOVE, dragon[dr].origin);
283 }
284 
285@@ -867,14 +916,19 @@
286 static void
287 add_potential_semeai_move(int pos, int type, int dr1, int dr2)
288 {
289-  ASSERT1(ON_BOARD(dr1), pos);
290-  ASSERT1(ON_BOARD(dr2), pos);
291+  ASSERT_ON_BOARD1(dr1);
292+  ASSERT1(IS_STONE(board[dr1]), dr1);
293+  ASSERT1(board[dr1] == dragon[dr1].color, dr1);
294+  ASSERT_ON_BOARD1(dr2);
295+  ASSERT1(IS_STONE(board[dr2]), dr2);
296+  ASSERT1(board[dr2] == dragon[dr2].color, dr2);
297+
298   if (next_semeai >= MAX_POTENTIAL_SEMEAI)
299     DEBUG(DEBUG_MOVE_REASONS,
300          "Potential semeai move at %1m dropped as list was full\n", pos);
301   else {
302-    semeai_target1[next_semeai] = dr1;
303-    semeai_target2[next_semeai] = dr2;
304+    semeai_target1[next_semeai] = dragon[dr1].origin;
305+    semeai_target2[next_semeai] = dragon[dr2].origin;
306     add_move_reason(pos, type, next_semeai);
307     next_semeai++;
308   }
309@@ -887,6 +941,12 @@
310 void
311 add_potential_semeai_attack(int pos, int dr1, int dr2)
312 {
313+  ASSERT_ON_BOARD1(dr1);
314+  ASSERT1(IS_STONE(board[dr1]), dr1);
315+  ASSERT1(board[dr1] == dragon[dr1].color, dr1);
316+  ASSERT_ON_BOARD1(dr2);
317+  ASSERT1(IS_STONE(board[dr2]), dr2);
318+  ASSERT1(board[dr2] == dragon[dr2].color, dr2);
319   add_potential_semeai_move(pos, POTENTIAL_SEMEAI_ATTACK, dr1, dr2);
320 }
321 
322@@ -897,6 +957,12 @@
323 void
324 add_potential_semeai_defense(int pos, int dr1, int dr2)
325 {
326+  ASSERT_ON_BOARD1(dr1);
327+  ASSERT1(IS_STONE(board[dr1]), dr1);
328+  ASSERT1(board[dr1] == dragon[dr1].color, dr1);
329+  ASSERT_ON_BOARD1(dr2);
330+  ASSERT1(IS_STONE(board[dr2]), dr2);
331+  ASSERT1(board[dr2] == dragon[dr2].color, dr2);
332   add_potential_semeai_move(pos, POTENTIAL_SEMEAI_DEFENSE, dr1, dr2);
333 }
334 
335@@ -911,6 +977,8 @@
336 add_semeai_threat(int pos, int dr)
337 {
338   ASSERT_ON_BOARD1(dr);
339+  ASSERT1(IS_STONE(board[dr]), dr);
340+  ASSERT1(board[dr] == dragon[dr].color, dr);
341   add_move_reason(pos, SEMEAI_THREAT, dragon[dr].origin);
342 }
343 
344@@ -949,6 +1017,8 @@
345   switch (reason1) {
346   case ATTACK_STRING:
347     {
348+      ASSERT1(IS_STONE(board[target1]), target1);
349+      ASSERT1(board[target1] == worm[target1].color, target1);
350       what1 = worm[target1].origin;
351 
352       /* If this string is already attacked, and with no defense, then
353@@ -966,6 +1036,8 @@
354   switch (reason2) {
355   case ATTACK_STRING:
356     {
357+      ASSERT1(IS_STONE(board[target2]), target2);
358+      ASSERT1(board[target2] == worm[target2].color, target2);
359       what2 = worm[target2].origin;
360 
361       /* If this string is already attacked, and with no defense, then
362@@ -1019,6 +1091,8 @@
363 
364   switch (reason1) {
365   case DEFEND_STRING:
366+    ASSERT1(IS_STONE(board[target1]), target1);
367+    ASSERT1(board[target1] == worm[target1].color, target1);
368     what1 = worm[target1].origin;
369     break;
370 
371@@ -1028,6 +1102,8 @@
372 
373   switch (reason2) {
374   case DEFEND_STRING:
375+    ASSERT1(IS_STONE(board[target2]), target2);
376+    ASSERT1(board[target2] == worm[target2].color, target2);
377     what2 = worm[target2].origin;
378     break;
379 
380@@ -1043,10 +1119,17 @@
381 void
382 add_loss_move(int pos, int target1, int target2)
383 {
384-  int what1 = dragon[target1].origin;
385-  int what2 = worm[target2].origin;
386-  int index = find_pair_data(what1, what2);
387-  ASSERT1(target2 != NO_MOVE, pos);
388+  int index;
389+
390+  ASSERT_ON_BOARD1(target1);
391+  ASSERT1(IS_STONE(board[target1]), target1);
392+  ASSERT1(board[target1] == dragon[target1].color, target1);
393+  ASSERT_ON_BOARD1(target2);
394+  ASSERT1(IS_STONE(board[target2]), target2);
395+  ASSERT1(board[target2] == worm[target2].color, target2);
396+
397+  index = find_pair_data(dragon[target1].origin,
398+                        worm[target2].origin);
399   add_move_reason(pos, OWL_DEFEND_MOVE_LOSS, index);
400 }
401 
402@@ -1121,9 +1204,10 @@
403 void
404 add_strategical_attack_move(int pos, int dr)
405 {
406-  dr = dragon[dr].origin;
407   ASSERT_ON_BOARD1(dr);
408-  add_move_reason(pos, STRATEGIC_ATTACK_MOVE, dr);
409+  ASSERT1(IS_STONE(board[dr]), dr);
410+  ASSERT1(board[dr] == dragon[dr].color, dr);
411+  add_move_reason(pos, STRATEGIC_ATTACK_MOVE, dragon[dr].origin);
412 }
413 
414 /*
415@@ -1133,9 +1217,10 @@
416 void
417 add_strategical_defense_move(int pos, int dr)
418 {
419-  dr = dragon[dr].origin;
420   ASSERT_ON_BOARD1(dr);
421-  add_move_reason(pos, STRATEGIC_DEFEND_MOVE, dr);
422+  ASSERT1(IS_STONE(board[dr]), dr);
423+  ASSERT1(board[dr] == dragon[dr].color, dr);
424+  add_move_reason(pos, STRATEGIC_DEFEND_MOVE, dragon[dr].origin);
425 }
426 
427 /*
428@@ -1145,9 +1230,11 @@
429 void
430 add_owl_attack_move(int pos, int dr, int kworm, int code)
431 {
432+  ASSERT_ON_BOARD1(dr);
433+  ASSERT1(IS_STONE(board[dr]), dr);
434+  ASSERT1(board[dr] == dragon[dr].color, dr);
435   dr = dragon[dr].origin;
436 
437-  ASSERT_ON_BOARD1(dr);
438   if (code == WIN)
439     add_move_reason(pos, OWL_ATTACK_MOVE, dr);
440   else if (code == KO_A)
441@@ -1156,6 +1243,8 @@
442     add_move_reason(pos, OWL_ATTACK_MOVE_BAD_KO, dr);
443   else if (code == GAIN) {
444     ASSERT_ON_BOARD1(kworm);
445+    ASSERT1(IS_STONE(board[kworm]), kworm);
446+    ASSERT1(board[kworm] == worm[kworm].color, kworm);
447     add_move_reason(pos, OWL_ATTACK_MOVE_GAIN, find_pair_data(dr, kworm));
448   }
449 }
450@@ -1167,9 +1256,11 @@
451 void
452 add_owl_defense_move(int pos, int dr, int code)
453 {
454+  ASSERT_ON_BOARD1(dr);
455+  ASSERT1(IS_STONE(board[dr]), dr);
456+  ASSERT1(board[dr] == dragon[dr].color, dr);
457   dr = dragon[dr].origin;
458 
459-  ASSERT_ON_BOARD1(dr);
460   if (code == WIN)
461     add_move_reason(pos, OWL_DEFEND_MOVE, dr);
462   else if (code == KO_A)
463@@ -1188,9 +1279,9 @@
464 add_owl_attack_threat_move(int pos, int dr, int code)
465 {
466   UNUSED(code);
467-  dr = dragon[dr].origin;
468
469   ASSERT_ON_BOARD1(dr);
470+  ASSERT1(IS_STONE(board[dr]), dr);
471+  ASSERT1(board[dr] == dragon[dr].color, dr);
472   add_move_reason(pos, OWL_ATTACK_THREAT, dragon[dr].origin);
473   add_worthwhile_threat_move(pos);
474 }
475@@ -1202,8 +1293,9 @@
476 void
477 add_owl_uncertain_defense_move(int pos, int dr)
478 {
479-  dr = dragon[dr].origin;
480   ASSERT_ON_BOARD1(dr);
481+  ASSERT1(IS_STONE(board[dr]), dr);
482+  ASSERT1(board[dr] == dragon[dr].color, dr);
483   add_move_reason(pos, UNCERTAIN_OWL_DEFENSE, dragon[dr].origin);
484 }
485 
486@@ -1214,8 +1306,9 @@
487 void
488 add_owl_uncertain_attack_move(int pos, int dr)
489 {
490-  dr = dragon[dr].origin;
491   ASSERT_ON_BOARD1(dr);
492+  ASSERT1(IS_STONE(board[dr]), dr);
493+  ASSERT1(board[dr] == dragon[dr].color, dr);
494   add_move_reason(pos, UNCERTAIN_OWL_ATTACK, dragon[dr].origin);
495 }
496 
497@@ -1229,9 +1322,9 @@
498 add_owl_defense_threat_move(int pos, int dr, int code)
499 {
500   UNUSED(code);
501-  dr = dragon[dr].origin;
502-
503   ASSERT_ON_BOARD1(dr);
504+  ASSERT1(IS_STONE(board[dr]), dr);
505+  ASSERT1(board[dr] == dragon[dr].color, dr);
506   add_move_reason(pos, OWL_DEFEND_THREAT, dragon[dr].origin);
507   add_worthwhile_threat_move(pos);
508 }
509@@ -1269,6 +1362,8 @@
510 add_owl_prevent_threat_move(int pos, int dr)
511 {
512   ASSERT_ON_BOARD1(dr);
513+  ASSERT1(IS_STONE(board[dr]), dr);
514+  ASSERT1(board[dr] == dragon[dr].color, dr);
515   add_move_reason(pos, OWL_PREVENT_THREAT, dragon[dr].origin);
516 }
517 
518@@ -1418,7 +1513,7 @@
519      * move is unsafe.
520      */
521     if (move_reasons[r].type == DEFEND_MOVE)
522-      mark_string(worm[what].origin, saved, 1);
523+      mark_string(what, saved, 1);
524     else if (move_reasons[r].type == OWL_DEFEND_MOVE_LOSS) {
525       int origin = dragon[what].origin;
526       int kworm = worm[what].origin;
527@@ -1426,7 +1521,7 @@
528       for (ii = BOARDMIN; ii < BOARDMAX; ii++)
529        if (IS_STONE(board[ii]) && dragon[ii].origin == origin
530            && worm[ii].origin != kworm)
531-         mark_string(worm[ii].origin, saved, 1);
532+         mark_string(ii, saved, 1);
533     }
534   }   
535 }
536@@ -1990,7 +2085,8 @@
537   int k;
538   ASSERT_ON_BOARD1(move);
539   ASSERT_ON_BOARD1(target);
540-  ASSERT1(IS_STONE(worm[target].color), move);
541+  ASSERT1(IS_STONE(board[target]), target);
542+  ASSERT1(board[target] == worm[target].color, target);
543 
544   target = worm[target].origin;
545   for (k = 0; k < MAX_ATTACK_THREATS; k++) {
546@@ -2011,7 +2107,8 @@
547   int k;
548   ASSERT_ON_BOARD1(move);
549   ASSERT_ON_BOARD1(target);
550-  ASSERT1(IS_STONE(worm[target].color), move);
551+  ASSERT1(IS_STONE(board[target]), target);
552+  ASSERT1(board[target] == worm[target].color, target);
553 
554   target = worm[target].origin;
555   for (k = 0; k < MAX_ATTACK_THREATS; k++) {
556diff -N -r -u -X .ignore gnugo-copy/engine/owl.c gnugo/engine/owl.c
557--- gnugo-copy/engine/owl.c     2007-01-22 22:01:07.640625000 +0100
558+++ gnugo/engine/owl.c  2007-01-22 23:48:10.703125000 +0100
559@@ -454,7 +454,7 @@
560   if (verbose > 0)
561     verbose--;
562   for (str = BOARDMIN; str < BOARDMAX; str++)
563-    if (ON_BOARD(str) && ms[str] && worm[str].origin == str) {
564+    if (ON_BOARD(str) && ms[str] && find_origin(str) == str) {
565       int adj;
566       int adjs[MAXCHAIN];
567       int k;
568@@ -1954,7 +1954,7 @@
569       }
570       if (saveworm != MAX_GOAL_WORMS && size >= 3) {
571        acode = GAIN;
572-       findlib(worm[owl_goal_worm[saveworm]].origin, 1, &mpos);
573+       findlib(owl_goal_worm[saveworm], 1, &mpos);
574        /* ASSERT1( ... */
575       }
576     }
577@@ -4633,10 +4633,14 @@
578   int color = board[apos];
579   
580   ASSERT1(bpos == NO_MOVE || board[bpos] == color, bpos);
581+  apos = find_origin(apos);
582+  if (bpos != NO_MOVE)
583+    bpos = find_origin(bpos);
584 
585   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
586     if (ON_BOARD(pos)) {
587-      if (is_same_worm(pos, apos) || is_same_worm(pos, bpos))
588+      if (IS_STONE(board[pos])
589+         && (find_origin(pos) == apos || find_origin(pos) == bpos))
590        owl->goal[pos] = 1;
591       else
592        owl->goal[pos] = 0;
593@@ -6916,8 +6920,8 @@
594        continue;
595 
596       for (ii = BOARDMIN; ii < BOARDMAX && w < MAX_GOAL_WORMS; ii++)
597-       if (ON_BOARD(ii) && board[ii] && worm[ii].origin == ii
598-           && worm[ii].size >= 3 && dragon[ii].id == d)
599+       if (IS_STONE(board[ii]) && find_origin(ii) == ii
600+           && countstones(ii) >= 3 && dragon[ii].id == d)
601          goal_worm[w++] = ii;
602     }
603   }
604diff -N -r -u -X .ignore gnugo-copy/engine/utils.c gnugo/engine/utils.c
605--- gnugo-copy/engine/utils.c   2006-11-12 17:01:14.000000000 +0100
606+++ gnugo/engine/utils.c        2007-01-22 23:49:31.468750000 +0100
607@@ -2,7 +2,7 @@
608  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
609  * http://www.gnu.org/software/gnugo/ for more information.          *
610  *                                                                   *
611- * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 and 2006       *
612+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *
613  * by the Free Software Foundation.                                  *
614  *                                                                   *
615  * This program is free software; you can redistribute it and/or     *
616@@ -1075,7 +1075,7 @@
617      */
618     if (board[bpos] != color)
619       continue;
620-    if (liberties <= worm[bpos].liberties
621+    if (liberties <= countlib(bpos)
622        && liberties <= 4)
623       trouble = 1;
624     else
625@@ -1137,10 +1137,12 @@
626            int kworm = move + delta[l];
627            if (board[kworm] == color) {
628              *return_value += 2.0 * worm[kworm].effective_size;
629-             if (safe_stones)
630+             if (safe_stones) {
631+               kworm = find_origin(kworm);
632                for (ii = BOARDMIN; ii < BOARDMAX; ii++)
633-                 if (ON_BOARD(ii) && worm[ii].origin == worm[kworm].origin)
634+                 if (IS_STONE(board[ii]) && find_origin(ii) == kworm)
635                    safe_stones[ii] = 0;
636+             }
637            }
638          }
639        }
640@@ -1148,7 +1150,8 @@
641          *return_value += 2.0 * worm[kworm].effective_size;
642          if (safe_stones)
643            for (ii = BOARDMIN; ii < BOARDMAX; ii++)
644-             if (ON_BOARD(ii) && worm[ii].origin == worm[kworm].origin)
645+             if (IS_STONE(board[ii])
646+                 && find_origin(ii) == find_origin(kworm))
647                safe_stones[ii] = 0;
648        }
649       }
650@@ -1182,7 +1185,7 @@
651   
652   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
653     if (!IS_STONE(board[pos])
654-       || worm[pos].origin != pos
655+       || find_origin(pos) != pos
656        || pos == move)
657       continue;
658     
659@@ -1217,11 +1220,12 @@
660       *return_value += worm[pos].effective_size;
661       if (safe_stones) /* Can't use mark_string. */
662        for (ii = BOARDMIN; ii < BOARDMAX; ii++)
663-         if (worm[ii].origin == worm[pos].origin)
664+         if (IS_STONE(board[ii])
665+             && find_origin(ii) == find_origin(pos))
666            safe_stones[ii] = 0;
667     }
668     else if (board[pos] == other
669-            && worm[pos].origin == pos
670+            && find_origin(pos) == pos
671             && worm[pos].attack_codes[0] != 0
672             && worm[pos].defense_codes[0] == 0
673             && find_defense(pos, NULL)) {
674diff -N -r -u -X .ignore gnugo-copy/engine/value_moves.c gnugo/engine/value_moves.c
675--- gnugo-copy/engine/value_moves.c     2007-01-27 18:25:37.734375000 +0100
676+++ gnugo/engine/value_moves.c  2007-01-27 18:22:50.796875000 +0100
677@@ -2,7 +2,7 @@
678  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
679  * http://www.gnu.org/software/gnugo/ for more information.          *
680  *                                                                   *
681- * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 and 2006       *
682+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 and 2007 *
683  * by the Free Software Foundation.                                  *
684  *                                                                   *
685  * This program is free software; you can redistribute it and/or     *
686@@ -839,6 +839,8 @@
687       if (r < 0)
688        break;
689       
690+       gg_assert(stackp==0);
691+
692       if (move_reasons[r].type == ATTACK_MOVE
693          || move_reasons[r].type == DEFEND_MOVE) {
694        int attack_move;
695@@ -1749,7 +1751,7 @@
696        continue;
697       
698       if (ON_BOARD(pos2)
699-         && worm[pos2].color == color
700+         && board[pos2] == color
701          && dragon[pos2].status != DEAD
702          && !disconnect(pos, pos2, NULL)) {
703        result = 1;
704@@ -2003,8 +2005,8 @@
705         * FIXME: This is somewhat halfhearted since only one defense
706         * move is tested.
707         */
708-       if (!is_known_good_attack_threat(pos, aa)
709-           && board[aa] != EMPTY
710+       if (board[aa] != EMPTY
711+           && !is_known_good_attack_threat(pos, aa)
712            && (move[pos].move_safety == 1
713                || adjacent_to_nondead_stone(pos, color)
714                || owl_defense_move_reason_known(pos, -1))
715diff -N -r -u -X .ignore gnugo-copy/engine/worm.c gnugo/engine/worm.c
716--- gnugo-copy/engine/worm.c    2007-01-27 18:12:25.015625000 +0100
717+++ gnugo/engine/worm.c 2007-01-27 18:09:35.546875000 +0100
718@@ -285,7 +285,7 @@
719         */
720        for (str = BOARDMIN; str < BOARDMAX; str++) {
721          if (!IS_STONE(board[str])
722-             || !is_worm_origin(str, str))
723+             || find_origin(str) != str)
724            continue;
725         
726          /* If the worm is of the opposite color to the move,
727@@ -489,6 +489,8 @@
728    * opponent's eye space.
729    */
730 
731+  gg_assert(stackp == 0);
732+
733   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
734     if (IS_STONE(board[pos])
735        && worm[pos].origin == pos
736@@ -998,7 +1000,7 @@
737       continue;
738     for (k = 0; k < 8; k++) {
739       int apos = pos + delta[k];
740-      if (ON_BOARD(apos) && is_same_worm(apos, str)) {
741+      if (IS_STONE(board[apos]) && is_same_worm(apos, str)) {
742        if (worm[pos].attack_codes[0] != 0 && !is_ko_point(pos)) {
743          /*
744           * If several adjacent lunches are found, we pick the
745@@ -1033,6 +1035,7 @@
746 int
747 is_same_worm(int w1, int w2)
748 {
749+  gg_assert(stackp==0);
750   return worm[w1].origin == worm[w2].origin;
751 }
752 
753@@ -1044,6 +1047,7 @@
754 int
755 is_worm_origin(int w, int pos)
756 {
757+  gg_assert(stackp==0);
758   return worm[w].origin == pos;
759 }
760 
761@@ -1221,12 +1225,13 @@
762 propagate_worm2(int str)
763 {
764   int pos;
765+  int origin;
766   ASSERT_ON_BOARD1(str);
767   ASSERT1(IS_STONE(worm[str].color), str);
768 
769+  origin = worm[str].origin;
770   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
771-    if (board[pos] == board[str] && is_same_worm(pos, str)
772-       && pos != str)
773+    if (worm[pos].origin == origin && pos != str)
774       worm[pos] = worm[str];
775 }
776 
777@@ -1241,11 +1246,8 @@
778   int k;
779   
780   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
781-    if (!ON_BOARD(pos) || board[pos] == EMPTY)
782-      continue;
783-
784-    if (!is_worm_origin(pos, pos))
785-      continue;
786+    if (!IS_STONE(board[pos]) || !is_worm_origin(pos, pos))
787+       continue;
788 
789     if (board[pos] == OTHER_COLOR(color)) {
790       for (k = 0; k < MAX_TACTICAL_POINTS; k++) {
791@@ -1564,6 +1566,8 @@
792   int k;
793   UNUSED(data);
794 
795+  gg_assert(stackp==0);
796+
797   move = AFFINE_TRANSFORM(pattern->move_offset, ll, anchor);
798 
799   /* If the pattern has a constraint, call the autohelper to see
800@@ -1652,6 +1656,8 @@
801   int k;
802   UNUSED(data);
803 
804+  gg_assert(stackp==0);
805+
806   move = AFFINE_TRANSFORM(pattern->move_offset, ll, anchor);
807   
808   /* If the pattern has a constraint, call the autohelper to see