Index: engine/owl.c
===================================================================
--- engine/owl.c	(revision 2369)
+++ engine/owl.c	(working copy)
@@ -81,6 +81,7 @@
 
   signed char escape_values[BOARDMAX];
   int color;
+  int origin;
 
   struct eye_data my_eye[BOARDMAX];
   /* array of half-eye data for use during owl reading */
@@ -97,6 +98,8 @@
 
   signed char safe_move_cache[BOARDMAX];
 
+  int escape_moves; /* Number of escape moves. */
+  
   /* This is used to organize the owl stack. */
   struct local_owl_data *restore_from;
 };
@@ -172,10 +175,15 @@
 void dump_pattern_list(struct matched_patterns_list_data *list);
 
 
-static int do_owl_attack(int str, int *move, int *wormid,
-			 struct local_owl_data *owl, int escape);
-static int do_owl_defend(int str, int *move, int *wormid,
-			 struct local_owl_data *owl, int escape);
+static int owl_attack_trymove(int mpos, struct local_owl_data **owl,
+			      struct owl_move_data *move, int *ko_move,
+			      int savecode);
+static int owl_defend_trymove(int mpos, struct local_owl_data **owl,
+			      struct owl_move_data *move, int *ko_move,
+			      int savecode);
+static void owl_popgo(struct local_owl_data **owl);
+static int do_owl_attack(struct local_owl_data *owl, int *move, int *wormid);
+static int do_owl_defend(struct local_owl_data *owl, int *move, int *wormid);
 static void owl_shapes(struct matched_patterns_list_data *list,
                        struct owl_move_data moves[MAX_MOVES], int color,
 		       struct local_owl_data *owl, struct pattern_db *type);
@@ -248,16 +256,14 @@
 			struct local_owl_data *owl);
 static void eat_lunch_escape_bonus(int lunch, int *min, int *probable,
 				   int *max, struct local_owl_data *owl);
-static int select_new_goal_origin(int origin, struct local_owl_data *owl);
+static int select_new_goal_origin(struct local_owl_data *owl);
 static void compute_owl_escape_values(struct local_owl_data *owl);
 static int owl_escape_route(struct local_owl_data *owl);
-static void do_owl_analyze_semeai(int apos, int bpos, 
-				  struct local_owl_data *owla,
+static void do_owl_analyze_semeai(struct local_owl_data *owla,
 				  struct local_owl_data *owlb,
 				  int *resulta, int *resultb,
 				  int *move, int pass, int owl_phase);
-static int semeai_trymove_and_recurse(int apos, int bpos,
-				      struct local_owl_data *owla,
+static int semeai_trymove_and_recurse(struct local_owl_data *owla,
 				      struct local_owl_data *owlb,
 				      int owl_phase,
 				      int move, int color, int ko_allowed,
@@ -519,7 +525,8 @@
   else {
     reduced_init_owl(&owla, 1);
     reduced_init_owl(&owlb, 0);
-    local_owl_node_counter = 0;
+    owla->origin = apos;
+    owlb->origin = bpos;
     owl_mark_worm(apos, NO_MOVE, owla);
     owl_mark_worm(bpos, NO_MOVE, owlb);
   }
@@ -569,11 +576,10 @@
     prefer_ko = EMPTY;
   
   if (move == PASS_MOVE)
-    do_owl_analyze_semeai(apos, bpos, owla, owlb,
-			  resulta, resultb, semeai_move, 0, owl);
+    do_owl_analyze_semeai(owla, owlb, resulta, resultb, semeai_move, 0, owl);
   else {
-    semeai_trymove_and_recurse(bpos, apos, owlb, owla, owl,
-			       move, color, 1, 0, "mandatory move",
+    semeai_trymove_and_recurse(owlb, owla, owl, move, color, 1, 0,
+			       "mandatory move",
 			       SAME_DRAGON_MAYBE_CONNECTED, NULL, NO_MOVE,
 			       semeai_move, resultb, resulta);
     *resulta = REVERSE_RESULT(*resulta);
@@ -619,12 +625,13 @@
  */
 
 static void
-do_owl_analyze_semeai(int apos, int bpos, 
-		      struct local_owl_data *owla,
+do_owl_analyze_semeai(struct local_owl_data *owla,
 		      struct local_owl_data *owlb,
 		      int *resulta, int *resultb,
 		      int *move, int pass, int owl_phase)
 {
+  int apos = owla->origin;
+  int bpos = owlb->origin;
   int color = board[apos];
   int other = OTHER_COLOR(color);
 #if 0
@@ -1114,8 +1121,7 @@
     /* Try playing the move at mpos and call ourselves recursively to
      * determine the result obtained by this move.
      */
-    if (semeai_trymove_and_recurse(apos, bpos, owla, owlb,
-				   owl_phase, mpos, color,
+    if (semeai_trymove_and_recurse(owla, owlb, owl_phase, mpos, color,
 				   best_resulta == 0 || best_resultb == 0,
 				   moves[k].value, moves[k].name,
 				   moves[k].same_dragon, moves[k].pattern_data,
@@ -1239,8 +1245,7 @@
     }
     else {
     /* No working move was found, but opponent hasn't passed. Then we pass. */
-      do_owl_analyze_semeai(bpos, apos, owlb, owla,
-			    resultb, resulta, NULL, 1, owl_phase);
+      do_owl_analyze_semeai(owlb, owla, resultb, resulta, NULL, 1, owl_phase);
       *resulta = REVERSE_RESULT(*resulta);
       *resultb = REVERSE_RESULT(*resultb);
       TRACE("No move found\n");
@@ -1266,7 +1271,7 @@
  * move.
  */
 static int
-semeai_trymove_and_recurse(int apos, int bpos, struct local_owl_data *owla,
+semeai_trymove_and_recurse(struct local_owl_data *owla,
 			   struct local_owl_data *owlb,
 			   int owl_phase,
 			   int move, int color, int ko_allowed,
@@ -1276,6 +1281,8 @@
 			   int lunch, int *semeai_move,
 			   int *this_resulta, int *this_resultb)
 {
+  int apos = owla->origin;
+  int bpos = owlb->origin;
   int ko_move = 0;
   
   gg_assert(this_resulta != NULL && this_resultb != NULL);
@@ -1317,12 +1324,11 @@
     /* FIXME: Are all owl_data fields and relevant static
      * variables properly set up for a call to do_owl_attack()?
      */
-    *this_resulta = REVERSE_RESULT(do_owl_attack(apos, semeai_move, NULL, owla, 0));
+    *this_resulta = REVERSE_RESULT(do_owl_attack(owla, semeai_move, NULL));
     *this_resultb = *this_resulta;
   }
   else {
-    do_owl_analyze_semeai(bpos, apos, owlb, owla,
-			  this_resultb, this_resulta, semeai_move,
+    do_owl_analyze_semeai(owlb, owla, this_resultb, this_resulta, semeai_move,
 			  0, owl_phase);
     *this_resulta = REVERSE_RESULT(*this_resulta);
     *this_resultb = REVERSE_RESULT(*this_resultb);
@@ -1754,88 +1760,91 @@
 }
 
 
-/* Returns true if a move can be found to attack the dragon
- * at (target), in which case (*attack_point) is the recommended move.
- * (attack_point) can be a null pointer if only the result is needed.
- *
- * The array goal marks the extent of the dragon. This must
- * be maintained during reading. Call this function only when
- * stackp==0; otherwise you can call do_owl_attack but you must
- * set up the goal and boundary arrays by hand first.
- *
- * Returns KO_A or KO_B if the position is ko:
- *
- * - Returns KO_A if the attack prevails provided attacker is willing to
- *   ignore any ko threat (the attacker makes the first ko capture).
- *
- * - Returns KO_B if attack succeeds provided attacker has a ko threat
- *   which must be answered (the defender makes the first ko capture).
- *
- * If GNU Go is compiled with `configure --enable-experimental-owl-ext'
- * then a return codes of GAIN is also possible.
- *
- * - Returns GAIN if the attack fails but another worm of the
- *   opponent's is captured in during the failed attack. The location
- *   of the killed worm is returned through the *kworm field.
- *
- * */
-
-int
-owl_attack(int target, int *attack_point, int *certain, int *kworm)
+/* Play an attacking move in owl reading.
+ * In addition to playing the move this involves pushing the owl data
+ * and then updating the owl information.
+ */
+static int
+owl_attack_trymove(int mpos, struct local_owl_data **owl,
+		   struct owl_move_data *move, int *ko_move, int savecode)
 {
-  int result;
-  struct local_owl_data *owl;
-  int reading_nodes_when_called = get_reading_node_counter();
-  double start = 0.0;
-  int tactical_nodes;
-  int move = NO_MOVE;
-  int wpos = NO_MOVE;
-  int wid = MAX_GOAL_WORMS;
-
-  result_certain = 1;
-  if (worm[target].unconditional_status == DEAD) {
-    if (attack_point)
-      *attack_point = NO_MOVE;
-    if (kworm)
-      *kworm = NO_MOVE;
-    if (certain)
-      *certain = 1;
-    return 1;
+  int other = OTHER_COLOR((*owl)->color);
+  /* Try to make the move. */
+  if (!komaster_trymove(mpos, other, move->name, (*owl)->origin,
+			ko_move, savecode == 0))
+    return 0;
+  
+  /* We have now made a move. Analyze the new position. */
+  push_owl(owl);
+  
+  TRACE("Trying %C %1m. Escape = %d. Current stack: ",
+	other, mpos, (*owl)->escape_moves);
+  if (verbose)
+    dump_stack();
+  
+  owl_update_boundary_marks(mpos, *owl);
+  
+  /* If the origin of the dragon has been captured, we look
+   * for another string which was part of the original dragon,
+   * marked when stackp==0, which has not been captured. If no
+   * such string is found, owl_attack declares victory.
+   */
+  if (!IS_STONE(board[(*owl)->origin]))
+    (*owl)->origin = select_new_goal_origin(*owl);
+  
+  /* Test whether the move cut the goal dragon apart. */
+  if (move->cuts[0] != NO_MOVE && (*owl)->origin != NO_MOVE) {
+    owl_test_cuts((*owl)->goal, (*owl)->color, move->cuts);
+    if (!(*owl)->goal[(*owl)->origin])
+      (*owl)->origin = select_new_goal_origin(*owl);
   }
+  mark_goal_in_sgf((*owl)->goal);
 
-  if (search_persistent_owl_cache(OWL_ATTACK, target, 0, 0, &result,
-				  attack_point, kworm, certain))
-    return result;
+  return 1;
+}
 
-  if (debug & DEBUG_OWL_PERFORMANCE)
-    start = gg_cputime();
+
+/* Play a defending move in owl reading.
+ * In addition to playing the move this involves pushing the owl data
+ * and then updating the owl information.
+ */
+static int
+owl_defend_trymove(int mpos, struct local_owl_data **owl,
+		   struct owl_move_data *move, int *ko_move, int savecode)
+{
+  /* Try to make the move. */
+  if (!komaster_trymove(mpos, (*owl)->color, move->name, (*owl)->origin,
+			ko_move, savecode == 0))
+    return 0;
   
-  TRACE("owl_attack %1m\n", target);
-  init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
-  owl_make_domains(owl, NULL);
-  prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
-		    kworm, 1);
-  result = do_owl_attack(target, &move, &wid, owl, 0);
-  finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
-  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
+  /* We have now made a move. Analyze the new position. */
+  push_owl(owl);
+  
+  TRACE("Trying %C %1m. Escape = %d. Current stack: ",
+	(*owl)->color, mpos, (*owl)->escape_moves);
+  if (verbose)
+    dump_stack();
+  
+  if (move->escape)
+    (*owl)->escape_moves++;
+  
+  /* Add the stone just played to the goal dragon, unless the
+   * pattern explicitly asked for not doing this.
+   */
+  owl_update_goal(mpos, move->same_dragon, move->lunch, *owl, 0,
+		  move->pattern_data);
+  mark_goal_in_sgf((*owl)->goal);
 
-  DEBUG(DEBUG_OWL_PERFORMANCE,
-    "owl_attack %1m, result %d %1m (%d, %d nodes, %f seconds)\n",
-    target, result, move, local_owl_node_counter,
-    tactical_nodes, gg_cputime() - start);
+  return 1;
+}
 
-  store_persistent_owl_cache(OWL_ATTACK, target, 0, 0,
-			     result, move, wpos,
-			     result_certain, tactical_nodes,
-			     owl->goal, board[target]);
-  if (attack_point)
-    *attack_point = move;
-  if (kworm)
-    *kworm = wpos;
-  if (certain)
-    *certain = result_certain;
 
-  return result;
+/* Undo an owl reading move. */
+static void
+owl_popgo(struct local_owl_data **owl)
+{
+  pop_owl(owl);
+  popgo();
 }
 
 
@@ -1844,10 +1853,9 @@
  */
 
 static int
-do_owl_attack(int str, int *move, int *wormid,
-	      struct local_owl_data *owl, int escape)
+do_owl_attack(struct local_owl_data *owl, int *move, int *wormid)
 {
-  int color = board[str];
+  int color = board[owl->origin];
   int other = OTHER_COLOR(color);
   struct owl_move_data vital_moves[MAX_MOVES];
   struct owl_move_data shape_moves[MAX_MOVES];
@@ -1870,13 +1878,13 @@
   int value2;
   int this_variation_number = count_variations - 1;
   
-  SETUP_TRACE_INFO("owl_attack", str);
+  SETUP_TRACE_INFO("owl_attack", owl->origin);
 
   shape_patterns.initialized = 0;
 
-  str = find_origin(str);
+  owl->origin = find_origin(owl->origin);
 
-  if (tt_get(&ttable, OWL_ATTACK, str, NO_MOVE, depth - stackp, NULL, 
+  if (tt_get(&ttable, OWL_ATTACK, owl->origin, NO_MOVE, depth - stackp, NULL, 
 	     &value1, &value2, &xpos) == 2) {
 
     TRACE_CACHED_RESULT(value1, xpos);
@@ -1903,10 +1911,10 @@
   }
 
 
-  /* If reading goes to deep or we run out of nodes, we assume life. */
+  /* If reading goes too deep or we run out of nodes, we assume life. */
   if (reading_limit_reached(&live_reason, this_variation_number)) {
     SGFTRACE(0, 0, live_reason);
-    READ_RETURN(OWL_ATTACK, str, depth - stackp, move, 0, 0);
+    READ_RETURN(OWL_ATTACK, owl->origin, depth - stackp, move, 0, 0);
   }
 
   memset(mw, 0, sizeof(mw));
@@ -1948,12 +1956,12 @@
     SGFTRACE(0, acode, live_reason);
     TRACE("%oVariation %d: ALIVE (%s)\n", this_variation_number, live_reason);
     if (acode == 0) {
-      READ_RETURN(OWL_ATTACK, str, depth - stackp, move, 0, 0);
+      READ_RETURN(OWL_ATTACK, owl->origin, depth - stackp, move, 0, 0);
     }
     else {
       if (wormid)
 	*wormid = saveworm;
-      READ_RETURN2(OWL_ATTACK, str, depth - stackp,
+      READ_RETURN2(OWL_ATTACK, owl->origin, depth - stackp,
 		   move, mpos, acode, saveworm);
     }
   }
@@ -2018,7 +2026,7 @@
 
 	sgf_dumptree = NULL;
 	count_variations = 0;
-	result = attack(str, &apos);
+	result = attack(owl->origin, &apos);
 	if (result == WIN
 	    || (result != 0 && (min_eyes(&probable_eyes) >= 2
 				|| pass == 5))) {
@@ -2036,14 +2044,14 @@
     case 4:
       if (number_tried_moves == 0) {
 	int dpos;
-	int dcode = do_owl_defend(str, &dpos, NULL, owl, escape);
+	int dcode = do_owl_defend(owl, &dpos, NULL);
 	/* No defense, we won. */
 	if (dcode == 0) {
 	  TRACE("%oVariation %d: DEAD (no defense)\n",
 		this_variation_number);
 	  SGFTRACE(0, WIN, "no defense");
 	  close_pattern_list(other, &shape_patterns);
-	  READ_RETURN(OWL_ATTACK, str, depth - stackp, move, 0, WIN);
+	  READ_RETURN(OWL_ATTACK, owl->origin, depth - stackp, move, 0, WIN);
 	}
 	else if (dpos != NO_MOVE) {
 	  /* The dragon could be defended by one more move. Try to
@@ -2098,7 +2106,7 @@
       TRACE("%oVariation %d: ALIVE (escaped)\n", this_variation_number);
       SGFTRACE(0, 0, "escaped");
       close_pattern_list(other, &shape_patterns);
-      READ_RETURN0(OWL_ATTACK, str, depth - stackp);
+      READ_RETURN0(OWL_ATTACK, owl->origin, depth - stackp);
     }
 #endif
 
@@ -2112,7 +2120,6 @@
     for (k = 0; k < MAX_MOVES; k++) {
       int mpos;
       int ko_move = -1;
-      int origin = NO_MOVE;
       int captured;
       int wid = MAX_GOAL_WORMS;
       int dcode;
@@ -2144,58 +2151,33 @@
       /* Have we already tested this move? */
       if (mw[mpos])
 	continue;
+      else
+	mw[mpos] = 1;
 
       captured = (color == WHITE ? white_captured : black_captured);
 
-      /* Try to make the move. */
-      if (!komaster_trymove(mpos, other, moves[k].name, str,
-			    &ko_move, savecode == 0))
+      /* Play the move, push the owl data, and update the owl
+       * strucures after the move.
+       */
+      if (!owl_attack_trymove(mpos, &owl, &moves[k], &ko_move, savecode))
 	continue;
-
+      
       captured = (color == WHITE ? white_captured : black_captured) - captured;
-
-      TRACE("Trying %C %1m. Escape = %d. Current stack: ",
-	    other, mpos, escape);
-      if (verbose)
-	dump_stack();
-
-      /* We have now made a move. Analyze the new position. */
-      push_owl(&owl);
-      mw[mpos] = 1;
+      
       number_tried_moves++;
-      owl_update_boundary_marks(mpos, owl);
-      
-      /* If the origin of the dragon has been captured, we look
-       * for another string which was part of the original dragon,
-       * marked when stackp==0, which has not been captured. If no
-       * such string is found, owl_attack declares victory.
-       */
-      if (IS_STONE(board[str]))
-	origin = str;
-      else
-	origin = select_new_goal_origin(NO_MOVE, owl);
-
-      /* Test whether the move cut the goal dragon apart. */
-      if (moves[k].cuts[0] != NO_MOVE && origin != NO_MOVE) {
-	owl_test_cuts(owl->goal, owl->color, moves[k].cuts);
-	if (!owl->goal[origin])
-	  origin = select_new_goal_origin(origin, owl);
+      if (owl->origin == NO_MOVE)
+	dcode = 0;
+      else {
+	dcode = do_owl_defend(owl, NULL, &wid);
       }
-      mark_goal_in_sgf(owl->goal);
 
-      if (origin == NO_MOVE)
-	dcode = 0;
-      else
-	dcode = do_owl_defend(origin, NULL, &wid, owl, escape);
-
       if (!ko_move) {
 	if (dcode == 0) {
-	  pop_owl(&owl);
-	  popgo();
+	  owl_popgo(&owl);
   	  if (sgf_dumptree) {
 	    const char *wintxt;
 	    char winstr[192];
-	    if (origin == NO_MOVE)
+	    if (owl->origin == NO_MOVE)
 	      wintxt = "all original stones captured";
 	    else
 	      wintxt = "attack effective";
@@ -2204,7 +2186,8 @@
 	    SGFTRACE(mpos, WIN, winstr);
 	  }
           close_pattern_list(other, &shape_patterns);
-	  READ_RETURN(OWL_ATTACK, str, depth - stackp, move, mpos, WIN);
+	  READ_RETURN(OWL_ATTACK, owl->origin, depth - stackp,
+		      move, mpos, WIN);
 	}
 	else if (experimental_owl_ext && dcode == LOSS) {
 	  if (saveworm == MAX_GOAL_WORMS
@@ -2270,9 +2253,7 @@
 	  number_tried_moves--;
 	}
       }
-    
-      pop_owl(&owl);
-      popgo();
+      owl_popgo(&owl);
     }
   }
 
@@ -2283,12 +2264,13 @@
       SGFTRACE(savemove, savecode, "attack effective (gain) - E");
       if (wormid)
 	*wormid = saveworm;
-      READ_RETURN2(OWL_ATTACK, str, depth - stackp,
+      READ_RETURN2(OWL_ATTACK, owl->origin, depth - stackp,
 		   move, savemove, savecode, saveworm);
     }
     else {
       SGFTRACE(savemove, savecode, "attack effective (ko) - E");
-      READ_RETURN(OWL_ATTACK, str, depth - stackp, move, savemove, savecode);
+      READ_RETURN(OWL_ATTACK, owl->origin, depth - stackp,
+		  move, savemove, savecode);
     }
   }
 
@@ -2299,204 +2281,16 @@
     SGFTRACE(0, 0, winstr);
   }
   
-  READ_RETURN0(OWL_ATTACK, str, depth - stackp);
+  READ_RETURN0(OWL_ATTACK, owl->origin, depth - stackp);
 }
 
 
-/* Returns true if the dragon at (target) can be captured given
- * two moves in a row. The first two moves to capture the
- * dragon are given as (*attack1) and (*attack2).
- */
+/* Static function containing the main recursive code for owl_defend. */
 
-int
-owl_threaten_attack(int target, int *attack1, int *attack2)
-{
-  struct owl_move_data moves[MAX_MOVES];
-  int k;
-  int other = OTHER_COLOR(board[target]);
-  struct local_owl_data *owl;
-  int result = 0;
-  int reading_nodes_when_called = get_reading_node_counter();
-  signed char saved_boundary[BOARDMAX];
-  double start = 0.0;
-  int tactical_nodes;
-  int move = 0;
-  int move2 = 0;
-  struct matched_patterns_list_data shape_patterns;
-
-  shape_patterns.initialized = 0;
-  result_certain = 1;
-  if (search_persistent_owl_cache(OWL_THREATEN_ATTACK, target, 0, 0,
-				  &result, attack1, attack2, NULL))
-    return result;
-
-  if (debug & DEBUG_OWL_PERFORMANCE)
-    start = gg_cputime();
-  
-  gg_assert(stackp == 0);
-  TRACE("owl_threaten_attack %1m\n", target);
-  init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
-  memcpy(saved_boundary, owl->boundary, sizeof(saved_boundary));
-  owl_make_domains(owl, NULL);
-  owl_shapes(&shape_patterns, moves, other, owl, &owl_attackpat_db);
-  for (k = 0; k < MAX_MOVES; k++) {
-    current_owl_data = owl;
-    if (!get_next_move_from_list(&shape_patterns, other, moves, 1, owl))
-      break;
-    else {
-      int mpos = moves[k].pos;
-
-      if (mpos != NO_MOVE && moves[k].value > 0)
-	if (trymove(mpos, other, moves[k].name, target)) {
-	  int pos;
-	  int origin = NO_MOVE;
-	  owl->lunches_are_current = 0;
-	  owl_update_boundary_marks(mpos, owl);
-	  
-	  /* If the origin of the dragon has been captured, we look
-	   * for another string which was part of the original dragon,
-	   * marked when stackp==0, which has not been captured. If no
-	   * such string is found, owl_attack declares victory.
-	   */
-	  
-	  if (board[target] == EMPTY) {
-	    for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
-	      if (IS_STONE(board[pos]) && owl->goal[pos] == 1) {
-		origin = find_origin(pos);
-		break;
-	      }
-	    }
-	    
-	    if (origin == NO_MOVE
-		|| do_owl_attack(origin, NULL, NULL, owl, 0)) {
-	      /* probably this can't happen */
-	      popgo();
-	      gg_assert(stackp == 0);
-	      result = 1;
-	      break;
-	    }
-	  }
-	  else if (do_owl_attack(target, &move2, NULL, owl, 0) == WIN) {
-	    move = moves[k].pos;
-	    popgo();
-	    gg_assert(stackp == 0);
-	    result = 1;
-	    break;
-	  }
-	  popgo();
-	  memcpy(owl->boundary, saved_boundary, sizeof(saved_boundary));
-	}
-    }
-  }
-  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
-  gg_assert(stackp == 0);
-
-  DEBUG(DEBUG_OWL_PERFORMANCE,
-    "owl_threaten_attack %1m %1m %1m, result %d (%d, %d nodes, %f seconds)\n",
-    target, move, move2, result, local_owl_node_counter,
-    tactical_nodes, gg_cputime() - start);
-
-  store_persistent_owl_cache(OWL_THREATEN_ATTACK, target, 0, 0,
-			     result, move, move2, 0,
-			     tactical_nodes, owl->goal, board[target]);
-
-  if (attack1)
-    *attack1 = move;
-  if (attack2)
-    *attack2 = move2;
-
-  close_pattern_list(other, &shape_patterns);
-  return result;
-}
-
-
-/* Returns true if a move can be found to defend the dragon
- * at (target), in which case (*defense_point) is the recommended move.
- * (defense_point) can be a null pointer if the result is not needed.
- *
- * The array goal marks the extent of the dragon. This must
- * be maintained during reading. Call this function only when
- * stackp==0; otherwise you can call do_owl_attack but you must
- * set up the goal and boundary arrays by hand first.
- *
- * Returns KO_A or KO_B if the position is ko:
- *
- * - Returns KO_A if the defendse succeeds provided the defender is willing to
- *   ignore any ko threat (the defender makes the first ko capture).
- * - Returns KO_B if the defense succeeds provided the defender has a ko threat
- *   which must be answered (the attacker makes the first ko capture).
- *
- * If GNU Go is compiled with `configure --enable-experimental-owl-ext'
- * then a return codes of GAIN is also possible.
- *
- * - Returns LOSS if the defense succeeds but another worm of the
- *   defender's is captured in during the defense. The location
- *   of the killed worm is returned through the *kworm field.
- *
- * The array goal marks the extent of the dragon. This must
- * be maintained during reading.  
- */
-
-int
-owl_defend(int target, int *defense_point, int *certain, int *kworm)
-{
-  int result;
-  static struct local_owl_data *owl;
-  int reading_nodes_when_called = get_reading_node_counter();
-  double start = 0.0;
-  int tactical_nodes;
-  int move = NO_MOVE;
-  int wpos = NO_MOVE;
-  int wid = MAX_GOAL_WORMS;
-
-  result_certain = 1;
-  if (worm[target].unconditional_status == DEAD)
-    return 0;
-
-  if (search_persistent_owl_cache(OWL_DEFEND, target, 0, 0, &result, 
-				  defense_point, kworm, certain))
-    return result;
-
-  if (debug & DEBUG_OWL_PERFORMANCE)
-    start = gg_cputime();
-
-  TRACE("owl_defend %1m\n", target);
-  init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
-  owl_make_domains(owl, NULL);
-  prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
-		    kworm, 1);
-  result = do_owl_defend(target, &move, &wid, owl, 0);
-  finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
-  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
-
-  DEBUG(DEBUG_OWL_PERFORMANCE,
-    "owl_defend %1m, result %d %1m (%d, %d nodes, %f seconds)\n",
-	    target, result, move, local_owl_node_counter,
-	    tactical_nodes, gg_cputime() - start);
-
-  store_persistent_owl_cache(OWL_DEFEND, target, 0, 0, result, move, wpos,
-			     result_certain, tactical_nodes, owl->goal,
-			     board[target]);
-
-  if (defense_point)
-    *defense_point = move;
-  if (kworm)
-    *kworm = wpos;
-  if (certain)
-    *certain = result_certain;
-  
-  return result;
-}
-
-
-/* Static function containing the main recursive code for owl_defend.
- */
-
 static int
-do_owl_defend(int str, int *move, int *wormid, struct local_owl_data *owl,
-	      int escape)
+do_owl_defend(struct local_owl_data *owl, int *move, int *wormid)
 {
-  int color = board[str];
+  int color = board[owl->origin];
   struct owl_move_data shape_moves[MAX_MOVES];
   struct owl_move_data vital_moves[MAX_MOVES];
   struct owl_move_data *moves;
@@ -2519,13 +2313,13 @@
   int value2;
   int this_variation_number = count_variations - 1;
 
-  SETUP_TRACE_INFO("owl_defend", str);
+  SETUP_TRACE_INFO("owl_defend", owl->origin);
 
   shape_patterns.initialized = 0;
   
-  str = find_origin(str);
+  owl->origin = find_origin(owl->origin);
 
-  if (tt_get(&ttable, OWL_DEFEND, str, NO_MOVE, depth - stackp, NULL, 
+  if (tt_get(&ttable, OWL_DEFEND, owl->origin, NO_MOVE, depth - stackp, NULL, 
 	     &value1, &value2, &xpos) == 2) {
     
     TRACE_CACHED_RESULT(value1, xpos);
@@ -2566,13 +2360,13 @@
      */
     TRACE("%oVariation %d: ALIVE (escaped)\n", this_variation_number);
     SGFTRACE(0, WIN, "escaped");
-    READ_RETURN(OWL_DEFEND, str, depth - stackp, move, 0, WIN);
+    READ_RETURN(OWL_DEFEND, owl->origin, depth - stackp, move, 0, WIN);
   }
 
   /* If reading goes to deep or we run out of nodes, we assume life. */
   if (reading_limit_reached(&live_reason, this_variation_number)) {
     SGFTRACE(0, WIN, live_reason);
-    READ_RETURN(OWL_DEFEND, str, depth - stackp, move, 0, WIN);
+    READ_RETURN(OWL_DEFEND, owl->origin, depth - stackp, move, 0, WIN);
   }
 
   memset(mw, 0, sizeof(mw));
@@ -2582,14 +2376,14 @@
   current_owl_data = owl;
   memset(owl->safe_move_cache, 0, sizeof(owl->safe_move_cache));
 
-  /* First see whether we might already be alife. */
-  if (escape < MAX_ESCAPE) {
+  /* First see whether we might already be alive. */
+  if (owl->escape_moves < MAX_ESCAPE) {
     if (owl_estimate_life(owl, NULL, vital_moves, &live_reason, 0,
 	  		  &probable_eyes, &eyemin, &eyemax)) {
       SGFTRACE(0, WIN, live_reason);
       TRACE("%oVariation %d: ALIVE (%s)\n",
 	    this_variation_number, live_reason);
-      READ_RETURN(OWL_DEFEND, str, depth - stackp, move, 0, WIN);
+      READ_RETURN(OWL_DEFEND, owl->origin, depth - stackp, move, 0, WIN);
     }
   }
   else {
@@ -2677,10 +2471,11 @@
 
 	  sgf_dumptree = NULL;
 	  count_variations = 0;
-	  if (attack_and_defend(str, NULL, NULL, NULL, &dpos)
+	  if (attack_and_defend(owl->origin, NULL, NULL, NULL, &dpos)
 	      && (approxlib(dpos, color, 2, NULL) > 1
 		  || does_capture_something(dpos, color))) {
-	    TRACE("Found tactical defense for %1m at %1m.\n", str, dpos);
+	    TRACE("Found tactical defense for %1m at %1m.\n",
+		  owl->origin, dpos);
 	    set_single_owl_move(shape_moves, dpos, "tactical_defense");
 	    moves = shape_moves;
 	  }
@@ -2699,7 +2494,6 @@
     for (k = 0; k < MAX_MOVES; k++) {
       int mpos;
       int ko_move = -1;
-      int new_escape;
       int wid = MAX_GOAL_WORMS;
       
       /* Consider only the highest scoring move if we're deeper than
@@ -2729,38 +2523,20 @@
       /* Have we already tested this move? */
       if (mw[mpos])
 	continue;
+      else
+	mw[mpos] = 1;
+
+      /* Play the move, push the owl data, and update the owl
+       * strucures after the move.
+       */
+      if (!owl_defend_trymove(mpos, &owl, &moves[k], &ko_move, savecode))
+	continue;
       
-      /* Try to make the move. */
-      if (!komaster_trymove(mpos, color, moves[k].name, str,
-			    &ko_move, savecode == 0))
-	continue;
-
-      new_escape = escape;
-      if (moves[k].escape)
-	new_escape++;
-
-      TRACE("Trying %C %1m. Escape = %d. Current stack: ",
-	    color, mpos, escape);
-      if (verbose)
-	dump_stack();
-
-      /* We have now made a move. Analyze the new position. */
-      push_owl(&owl);
-      mw[mpos] = 1;
       number_tried_moves++;
-
-      /* Add the stone just played to the goal dragon, unless the
-       * pattern explicitly asked for not doing this.
-       */
-      owl_update_goal(mpos, moves[k].same_dragon, moves[k].lunch, owl, 0,
-		      moves[k].pattern_data);
-      mark_goal_in_sgf(owl->goal);
-
       if (!ko_move) {
-	int acode = do_owl_attack(str, NULL, &wid, owl, new_escape);
+	int acode = do_owl_attack(owl, NULL, &wid);
 	if (!acode) {
-	  pop_owl(&owl);
-	  popgo();
+	  owl_popgo(&owl);
 	  if (sgf_dumptree) {
 	    char winstr[192];
 	    sprintf(winstr, "defense effective)\n  (%d variations",   
@@ -2768,22 +2544,22 @@
 	    SGFTRACE(mpos, WIN, winstr);
 	  }
 	  close_pattern_list(color, &shape_patterns);
-	  READ_RETURN(OWL_DEFEND, str, depth - stackp, move, mpos, WIN);
+	  READ_RETURN(OWL_DEFEND, owl->origin, depth - stackp,
+		      move, mpos, WIN);
 	}
 	if (acode == GAIN)
 	  saveworm = wid;
 	UPDATE_SAVED_KO_RESULT(savecode, savemove, acode, mpos);
       }
       else {
-	if (do_owl_attack(str, NULL, NULL, owl, new_escape) != WIN) {
+	if (do_owl_attack(owl, NULL, NULL) != WIN) {
 	  savemove = mpos;
 	  savecode = KO_B;
 	}
       }
       
       /* Undo the tested move. */
-      pop_owl(&owl);
-      popgo();
+      owl_popgo(&owl);
     }
   }
 
@@ -2794,18 +2570,19 @@
       SGFTRACE(savemove, savecode, "defense effective (loss) - B");
       if (wormid)
 	*wormid = saveworm;
-      READ_RETURN2(OWL_DEFEND, str, depth - stackp,
+      READ_RETURN2(OWL_DEFEND, owl->origin, depth - stackp,
 		   move, savemove, savecode, saveworm);
     }
     else {
       SGFTRACE(savemove, savecode, "defense effective (ko) - B");
-      READ_RETURN(OWL_DEFEND, str, depth - stackp, move, savemove, savecode);
+      READ_RETURN(OWL_DEFEND, owl->origin, depth - stackp,
+		  move, savemove, savecode);
     }
   }
 
   if (number_tried_moves == 0 && min_eyes(&probable_eyes) >= 2) {
     SGFTRACE(0, WIN, "genus probably >= 2");
-    READ_RETURN(OWL_DEFEND, str, depth - stackp, move, 0, WIN);
+    READ_RETURN(OWL_DEFEND, owl->origin, depth - stackp, move, 0, WIN);
   }
   
 
@@ -2817,10 +2594,281 @@
     SGFTRACE(0, 0, winstr);
   }
 
-  READ_RETURN0(OWL_DEFEND, str, depth - stackp);
+  READ_RETURN0(OWL_DEFEND, owl->origin, depth - stackp);
 }
 
 
+/* Returns true if a move can be found to attack the dragon
+ * at (target), in which case (*attack_point) is the recommended move.
+ * (attack_point) can be a null pointer if only the result is needed.
+ *
+ * The array goal marks the extent of the dragon. This must
+ * be maintained during reading. Call this function only when
+ * stackp==0; otherwise you can call do_owl_attack but you must
+ * set up the goal and boundary arrays by hand first.
+ *
+ * Returns KO_A or KO_B if the position is ko:
+ *
+ * - Returns KO_A if the attack prevails provided attacker is willing to
+ *   ignore any ko threat (the attacker makes the first ko capture).
+ *
+ * - Returns KO_B if attack succeeds provided attacker has a ko threat
+ *   which must be answered (the defender makes the first ko capture).
+ *
+ * If GNU Go is compiled with `configure --enable-experimental-owl-ext'
+ * then a return codes of GAIN is also possible.
+ *
+ * - Returns GAIN if the attack fails but another worm of the
+ *   opponent's is captured in during the failed attack. The location
+ *   of the killed worm is returned through the *kworm field.
+ *
+ */
+
+int
+owl_attack(int target, int *attack_point, int *certain, int *kworm)
+{
+  int result;
+  struct local_owl_data *owl;
+  int reading_nodes_when_called = get_reading_node_counter();
+  double start = 0.0;
+  int tactical_nodes;
+  int move = NO_MOVE;
+  int wpos = NO_MOVE;
+  int wid = MAX_GOAL_WORMS;
+
+  result_certain = 1;
+  if (worm[target].unconditional_status == DEAD) {
+    if (attack_point)
+      *attack_point = NO_MOVE;
+    if (kworm)
+      *kworm = NO_MOVE;
+    if (certain)
+      *certain = 1;
+    return 1;
+  }
+
+  if (search_persistent_owl_cache(OWL_ATTACK, target, 0, 0, &result,
+				  attack_point, kworm, certain))
+    return result;
+
+  if (debug & DEBUG_OWL_PERFORMANCE)
+    start = gg_cputime();
+  
+  TRACE("owl_attack %1m\n", target);
+  init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
+  owl_make_domains(owl, NULL);
+  prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
+		    kworm, 1);
+  result = do_owl_attack(owl, &move, &wid);
+  finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
+  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
+
+  DEBUG(DEBUG_OWL_PERFORMANCE,
+	"owl_attack %1m, result %d %1m (%d, %d nodes, %f seconds)\n",
+	target, result, move, local_owl_node_counter,
+	tactical_nodes, gg_cputime() - start);
+
+  store_persistent_owl_cache(OWL_ATTACK, target, 0, 0,
+			     result, move, wpos,
+			     result_certain, tactical_nodes,
+			     owl->goal, board[target]);
+  if (attack_point)
+    *attack_point = move;
+  if (kworm)
+    *kworm = wpos;
+  if (certain)
+    *certain = result_certain;
+
+  return result;
+}
+
+
+/* Returns true if a move can be found to defend the dragon
+ * at (target), in which case (*defense_point) is the recommended move.
+ * (defense_point) can be a null pointer if the result is not needed.
+ *
+ * The array goal marks the extent of the dragon. This must
+ * be maintained during reading. Call this function only when
+ * stackp==0; otherwise you can call do_owl_attack but you must
+ * set up the goal and boundary arrays by hand first.
+ *
+ * Returns KO_A or KO_B if the position is ko:
+ *
+ * - Returns KO_A if the defendse succeeds provided the defender is willing to
+ *   ignore any ko threat (the defender makes the first ko capture).
+ * - Returns KO_B if the defense succeeds provided the defender has a ko threat
+ *   which must be answered (the attacker makes the first ko capture).
+ *
+ * If GNU Go is compiled with `configure --enable-experimental-owl-ext'
+ * then a return codes of GAIN is also possible.
+ *
+ * - Returns LOSS if the defense succeeds but another worm of the
+ *   defender's is captured in during the defense. The location
+ *   of the killed worm is returned through the *kworm field.
+ *
+ * The array goal marks the extent of the dragon. This must
+ * be maintained during reading.  
+ */
+
+int
+owl_defend(int target, int *defense_point, int *certain, int *kworm)
+{
+  int result;
+  static struct local_owl_data *owl;
+  int reading_nodes_when_called = get_reading_node_counter();
+  double start = 0.0;
+  int tactical_nodes;
+  int move = NO_MOVE;
+  int wpos = NO_MOVE;
+  int wid = MAX_GOAL_WORMS;
+
+  result_certain = 1;
+  if (worm[target].unconditional_status == DEAD)
+    return 0;
+
+  if (search_persistent_owl_cache(OWL_DEFEND, target, 0, 0, &result, 
+				  defense_point, kworm, certain))
+    return result;
+
+  if (debug & DEBUG_OWL_PERFORMANCE)
+    start = gg_cputime();
+
+  TRACE("owl_defend %1m\n", target);
+  init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
+  owl_make_domains(owl, NULL);
+  prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
+		    kworm, 1);
+  result = do_owl_defend(owl, &move, &wid);
+  finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
+  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
+
+  DEBUG(DEBUG_OWL_PERFORMANCE,
+	"owl_defend %1m, result %d %1m (%d, %d nodes, %f seconds)\n",
+	target, result, move, local_owl_node_counter,
+	tactical_nodes, gg_cputime() - start);
+
+  store_persistent_owl_cache(OWL_DEFEND, target, 0, 0, result, move, wpos,
+			     result_certain, tactical_nodes, owl->goal,
+			     board[target]);
+
+  if (defense_point)
+    *defense_point = move;
+  if (kworm)
+    *kworm = wpos;
+  if (certain)
+    *certain = result_certain;
+  
+  return result;
+}
+
+
+/* Returns true if the dragon at (target) can be captured given
+ * two moves in a row. The first two moves to capture the
+ * dragon are given as (*attack1) and (*attack2).
+ */
+
+int
+owl_threaten_attack(int target, int *attack1, int *attack2)
+{
+  struct owl_move_data moves[MAX_MOVES];
+  int k;
+  int other = OTHER_COLOR(board[target]);
+  struct local_owl_data *owl;
+  int result = 0;
+  int reading_nodes_when_called = get_reading_node_counter();
+  signed char saved_boundary[BOARDMAX];
+  double start = 0.0;
+  int tactical_nodes;
+  int move = 0;
+  int move2 = 0;
+  struct matched_patterns_list_data shape_patterns;
+
+  shape_patterns.initialized = 0;
+  result_certain = 1;
+  if (search_persistent_owl_cache(OWL_THREATEN_ATTACK, target, 0, 0,
+				  &result, attack1, attack2, NULL))
+    return result;
+
+  if (debug & DEBUG_OWL_PERFORMANCE)
+    start = gg_cputime();
+  
+  gg_assert(stackp == 0);
+  TRACE("owl_threaten_attack %1m\n", target);
+  init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
+  memcpy(saved_boundary, owl->boundary, sizeof(saved_boundary));
+  owl_make_domains(owl, NULL);
+  owl_shapes(&shape_patterns, moves, other, owl, &owl_attackpat_db);
+  for (k = 0; k < MAX_MOVES; k++) {
+    current_owl_data = owl;
+    if (!get_next_move_from_list(&shape_patterns, other, moves, 1, owl))
+      break;
+    else {
+      int mpos = moves[k].pos;
+
+      if (mpos != NO_MOVE && moves[k].value > 0)
+	if (trymove(mpos, other, moves[k].name, target)) {
+	  int pos;
+	  int origin = NO_MOVE;
+	  owl->lunches_are_current = 0;
+	  owl_update_boundary_marks(mpos, owl);
+	  
+	  /* If the origin of the dragon has been captured, we look
+	   * for another string which was part of the original dragon,
+	   * marked when stackp==0, which has not been captured. If no
+	   * such string is found, owl_attack declares victory.
+	   */
+	  
+	  if (board[target] == EMPTY) {
+	    for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
+	      if (IS_STONE(board[pos]) && owl->goal[pos] == 1) {
+		origin = find_origin(pos);
+		break;
+	      }
+	    }
+	    owl->origin = origin;
+	    
+	    if (origin == NO_MOVE || do_owl_attack(owl, NULL, NULL)) {
+	      /* probably this can't happen */
+	      popgo();
+	      gg_assert(stackp == 0);
+	      result = 1;
+	      break;
+	    }
+	  }
+	  else if (do_owl_attack(owl, &move2, NULL) == WIN) {
+	    move = moves[k].pos;
+	    popgo();
+	    gg_assert(stackp == 0);
+	    result = 1;
+	    break;
+	  }
+	  popgo();
+	  memcpy(owl->boundary, saved_boundary, sizeof(saved_boundary));
+	}
+    }
+  }
+  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
+  gg_assert(stackp == 0);
+
+  DEBUG(DEBUG_OWL_PERFORMANCE,
+    "owl_threaten_attack %1m %1m %1m, result %d (%d, %d nodes, %f seconds)\n",
+    target, move, move2, result, local_owl_node_counter,
+    tactical_nodes, gg_cputime() - start);
+
+  store_persistent_owl_cache(OWL_THREATEN_ATTACK, target, 0, 0,
+			     result, move, move2, 0,
+			     tactical_nodes, owl->goal, board[target]);
+
+  if (attack1)
+    *attack1 = move;
+  if (attack2)
+    *attack2 = move2;
+
+  close_pattern_list(other, &shape_patterns);
+  return result;
+}
+
+
 /* Returns true if the dragon at (target) can be defended given
  * two moves in a row. The first two moves to defend the
  * dragon are given as (*defend1) and (*defend2).
@@ -2870,7 +2918,7 @@
 	  owl->lunches_are_current = 0;
 	  owl_update_goal(moves[k].pos, moves[k].same_dragon,
 	      		  moves[k].lunch, owl, 0, moves[k].pattern_data);
-	  if (do_owl_defend(target, &move2, NULL, owl, 0) == WIN) {
+	  if (do_owl_defend(owl, &move2, NULL) == WIN) {
 	    move = moves[k].pos;
 	    popgo();
 	    /* Don't return the second move if occupied before trymove */
@@ -2907,7 +2955,438 @@
 }
 
 
+/* Use the owl code to determine whether the attack move at (move) of
+ * the dragon (target) is effective, i.e. whether it kills the stones.
+ *
+ * Should be called only when stackp==0.
+ */
 
+int
+owl_does_attack(int move, int target, int *kworm)
+{
+  int color = board[target];
+  int other = OTHER_COLOR(color);
+  int result = 0;
+  struct local_owl_data *owl;
+  int reading_nodes_when_called = get_reading_node_counter();
+  int tactical_nodes;
+  int origin;
+  int dcode;
+  int wpos = NO_MOVE;
+  int wid = MAX_GOAL_WORMS;
+  double start = 0.0;
+
+  if (debug & DEBUG_OWL_PERFORMANCE)
+    start = gg_cputime();
+
+  if (worm[target].unconditional_status == ALIVE)
+    return 0;
+
+  origin = dragon[target].origin;
+  TRACE("owl_does_attack %1m %1m(%1m)\n", move, target, origin);
+
+  if (search_persistent_owl_cache(OWL_DOES_ATTACK, move, target, 0,
+				  &result, kworm, NULL, NULL))
+    return result;
+
+  /* FIXME: We want to do this after the trymove(), but currently
+   * owl_mark_dragon() may crash if the trymove() happens to remove
+   * some stones of the goal dragon from the board.
+   */
+#if 1
+  init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
+#endif
+
+  if (trymove(move, other, "owl_does_attack", target)) {
+    /* Check if a compatible owl_defend() is cached. */
+    if (search_persistent_owl_cache(OWL_DEFEND, origin, 0, 0,
+				    &result, NULL, kworm, NULL)) {
+      popgo();
+      return REVERSE_RESULT(result);
+    }
+
+#if 0
+    local_owl_node_counter = 0;
+    owl->lunches_are_current = 0;
+    owl_mark_dragon(target, NO_MOVE, owl);
+#endif
+    owl_update_boundary_marks(move, owl);
+#if 0
+    compute_owl_escape_values(owl);
+#endif
+    /* FIXME: Should also check if part of the dragon was captured,
+     *        like do_owl_attack() does.
+     */
+    if (board[target] == EMPTY)
+      dcode = 0;
+    else {
+      prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
+	                 kworm, 0);
+      dcode = do_owl_defend(owl, NULL, &wid);
+      finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
+    }
+    result = REVERSE_RESULT(dcode);
+    owl->lunches_are_current = 0;
+    popgo();
+  }
+  else
+    return 0;  /* Don't cache anything in this case. */
+
+  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
+
+  DEBUG(DEBUG_OWL_PERFORMANCE,
+	"owl_does_attack %1m %1m(%1m), result %d (%d, %d nodes, %f seconds)\n",
+	move, target, origin, result, local_owl_node_counter,
+	tactical_nodes, gg_cputime() - start);
+
+  store_persistent_owl_cache(OWL_DOES_ATTACK, move, target, 0,
+			     result, wpos, 0, 0,
+			     tactical_nodes, owl->goal, board[target]);
+
+  if (kworm)
+    *kworm = wpos;
+  return result;
+}
+
+
+/* Use the owl code to determine whether the move at (move) makes
+ * the dragon at (target) owl safe. This is used to test whether
+ * tactical defenses are strategically viable and whether a vital eye
+ * point does kill an owl critical dragon. 
+ *
+ * Should be called only when stackp==0.
+ */
+
+int
+owl_does_defend(int move, int target, int *kworm)
+{
+  int color = board[target];
+  int result = 0;
+  struct local_owl_data *owl;
+  int reading_nodes_when_called = get_reading_node_counter();
+  int tactical_nodes;
+  int origin;
+  int acode;
+  int wpos = NO_MOVE;
+  int wid = MAX_GOAL_WORMS;
+  double start = 0.0;
+
+  if (debug & DEBUG_OWL_PERFORMANCE)
+    start = gg_cputime();
+
+  if (worm[target].unconditional_status == DEAD)
+    return 0;
+
+  origin = dragon[target].origin;
+  TRACE("owl_does_defend %1m %1m(%1m)\n", move, target, origin);
+
+  if (search_persistent_owl_cache(OWL_DOES_DEFEND, move, target, 0,
+				  &result, kworm, NULL, NULL))
+    return result;
+
+  if (trymove(move, color, "owl_does_defend", target)) {
+    /* Check if a compatible owl_attack() is cached. */
+    if (search_persistent_owl_cache(OWL_ATTACK, origin, 0, 0,
+				    &result, NULL, kworm, NULL)) {
+      popgo();
+      return REVERSE_RESULT(result);
+    }
+    
+    /*
+     * FIXME: (move) will be added to the goal dragon although we
+     * do not know whether it is really connected.
+     */
+    init_owl(&owl, target, NO_MOVE, move, 1, NULL);
+    prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
+		      kworm, 0);
+    acode = do_owl_attack(owl, NULL, &wid);
+    finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
+    result = REVERSE_RESULT(acode);
+    popgo();
+  }
+  else
+    return 0;  /* Don't cache anything in this case. */
+
+  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
+
+  DEBUG(DEBUG_OWL_PERFORMANCE,
+	"owl_does_defend %1m %1m(%1m), result %d (%d, %d nodes, %f seconds)\n",
+	move, target, origin, result, local_owl_node_counter,
+	tactical_nodes, gg_cputime() - start);
+
+  store_persistent_owl_cache(OWL_DOES_DEFEND, move, target, 0,
+			     result, wpos, 0, 0,
+			     tactical_nodes, owl->goal, board[target]);
+
+  if (kworm)
+    *kworm = wpos;
+  return result;
+}
+
+
+/* Use the owl code to determine whether the dragon at (target) is owl
+ * safe after an own move at (move). This is used to detect
+ * blunders. In case the dragon is not safe, it also tries to find a
+ * defense point making (target) safe in a later move.
+ *
+ * Should be called only when stackp==0.
+ */
+
+int
+owl_confirm_safety(int move, int target, int *defense_point, int *kworm)
+{
+  int color = board[target];
+  int result = 0;
+  struct local_owl_data *owl;
+  int reading_nodes_when_called = get_reading_node_counter();
+  int tactical_nodes;
+  int origin;
+  int defense = 0;
+  double start = 0.0;
+  int acode;
+  int wpos = NO_MOVE;
+  int wid = MAX_GOAL_WORMS;
+
+  if (debug & DEBUG_OWL_PERFORMANCE)
+    start = gg_cputime();
+
+  if (worm[target].unconditional_status == DEAD)
+    return 0;
+
+  origin = dragon[target].origin;
+  TRACE("owl_confirm_safety %1m %1m(%1m)\n", move, target, origin);
+
+  if (search_persistent_owl_cache(OWL_CONFIRM_SAFETY, move, target, 0,
+				  &result, defense_point, kworm, NULL))
+    return result;
+
+  if (trymove(move, color, "owl_confirm_safety", target)) {
+    /* Check if a compatible owl_attack() is cached. */
+    if (search_persistent_owl_cache(OWL_ATTACK, origin, 0, 0,
+				    &result, defense_point, kworm, NULL)) {
+      popgo();
+      if (result == 0)
+	return WIN;
+      else if (result == GAIN)
+	return LOSS;
+      else
+	return 0;
+    }
+    
+    init_owl(&owl, target, NO_MOVE, move, 1, NULL);
+    prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
+		      kworm, 0);
+    acode = do_owl_attack(owl, &defense, &wid);
+    finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
+    if (acode == 0)
+      result = WIN;
+    else if (acode == GAIN)
+      result = LOSS;
+    popgo();
+  }
+  else
+    return 0;  /* Don't cache anything in this case. */
+
+  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
+
+  DEBUG(DEBUG_OWL_PERFORMANCE,
+	"owl_confirm_safety %1m %1m(%1m), result %d %1m (%d, %d nodes, %f seconds)\n",
+	move, target, origin, result, defense,
+	local_owl_node_counter, tactical_nodes,
+	gg_cputime() - start);
+
+  store_persistent_owl_cache(OWL_CONFIRM_SAFETY, move, target, 0,
+			     result, defense, wpos, 0,
+			     tactical_nodes, owl->goal, board[target]);
+
+  if (defense_point)
+    *defense_point = defense;
+  if (kworm)
+    *kworm = wpos;
+
+  return result;
+}
+
+
+/* Use the owl code to determine whether connecting the two dragons
+ * (target1) and (target2) by playing at (move) results in a living
+ * dragon. Should be called only when stackp==0.
+ */
+
+int
+owl_connection_defends(int move, int target1, int target2)
+{
+  int color = board[target1];
+  int result = 0;
+  int reading_nodes_when_called = get_reading_node_counter();
+  int tactical_nodes;
+  double start = 0.0;
+  struct local_owl_data *owl;
+
+  if (debug & DEBUG_OWL_PERFORMANCE)
+    start = gg_cputime();
+
+  ASSERT1(board[target2] == color, target2);
+  TRACE("owl_connection_defends %1m %1m %1m\n", move, target1, target2);
+
+  if (worm[target1].unconditional_status == DEAD)
+    return 0;
+  if (worm[target2].unconditional_status == DEAD)
+    return 0;
+
+  if (search_persistent_owl_cache(OWL_CONNECTION_DEFENDS, move, target1,
+				  target2, &result, NULL, NULL, NULL))
+    return result;
+
+  init_owl(&owl, target1, target2, NO_MOVE, 1, NULL);
+
+  if (trymove(move, color, "owl_connection_defends", target1)) {
+    owl_update_goal(move, SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE, owl, 0, NULL);
+    owl->origin = move;
+    if (!do_owl_attack(owl, NULL, NULL))
+      result = WIN;
+    owl->lunches_are_current = 0;
+    popgo();
+  }
+  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
+  
+  DEBUG(DEBUG_OWL_PERFORMANCE,
+	"owl_conn_defends %1m %1m %1m, result %d (%d, %d nodes, %f seconds)\n",
+	move, target1, target2, result, local_owl_node_counter,
+	tactical_nodes, gg_cputime() - start);
+
+  store_persistent_owl_cache(OWL_CONNECTION_DEFENDS, move, target1, target2,
+			     result, 0, 0, 0, tactical_nodes,
+			     owl->goal, color);
+
+  return result;
+}
+
+
+/* This function, called when stackp==0, returns true if capturing
+ * the string at (str) results in a live group.
+ */
+
+#define MAX_SUBSTANTIAL_LIBS 10
+
+int
+owl_substantial(int str)
+{
+  int k;
+  int libs[MAX_SUBSTANTIAL_LIBS + 1];
+  int liberties = findlib(str, MAX_SUBSTANTIAL_LIBS+1, libs);
+  int reading_nodes_when_called = get_reading_node_counter();
+  int tactical_nodes;
+  int result;
+  double start = 0.0;
+  struct local_owl_data *owl;
+  int num_moves = 0;
+
+  if (debug & DEBUG_OWL_PERFORMANCE)
+    start = gg_cputime();
+
+  /* FIXME: We want to use the full init_owl here too (cf. similar
+   * remark below).
+   */
+  reduced_init_owl(&owl, 1);
+
+  owl->color = OTHER_COLOR(board[str]);
+
+  /* Big strings are always substantial since the biggest nakade is
+   * six stones. (There are probably rare exceptions to this
+   * rule, but they are unlikely to come up in a game.)
+   */
+  if (countstones(str) > 6)
+    return 1;
+  
+  if (liberties > MAX_SUBSTANTIAL_LIBS)
+    return 0;
+
+  memset(owl->goal, 0, sizeof(owl->goal));
+  /* Mark the neighbors of the string. If one is found which is alive, return
+   * true. */
+  {
+    int adjs[MAXCHAIN];
+    int adj;
+
+    adj = chainlinks(str, adjs);
+    for (k = 0; k < adj; k++) {
+      if (dragon[adjs[k]].status == ALIVE)
+	return 1;
+      mark_dragon(adjs[k], owl->goal, 1);
+    }
+  }
+
+  /* We must check the cache while stackp == 0, but we wait until the
+   * trivial tests have been done.
+   */
+  if (search_persistent_owl_cache(OWL_SUBSTANTIAL, str, 0, 0,
+				  &result, NULL, NULL, NULL))
+    return result;
+
+  /* fill all the liberties */
+  for (k = 0; k < liberties; k++) {
+    if (trymove(libs[k], owl->color, NULL, 0)) {
+      if (get_level() >= 8)
+	increase_depth_values();
+      owl->goal[libs[k]] = 1;
+      num_moves++;
+    }
+    else {
+      /* if we can't fill, try swapping with the next liberty */
+      if (k < liberties-1
+	  && trymove(libs[k+1], owl->color, NULL, 0)) {
+	if (get_level() >= 8)
+	  increase_depth_values();
+	owl->goal[libs[k+1]] = 1;
+	libs[k+1] = libs[k];
+	num_moves++;
+      }
+      else {
+	/* Can't fill the liberties. Give up! */
+	while (num_moves-- > 0) {
+	  if (get_level() >= 8)
+	    decrease_depth_values();
+	  popgo();
+	}
+	return 0;
+      }
+    }
+  }
+  /* FIXME: We would want to use init_owl() here too, but it doesn't
+   * fit very well with the construction of the goal array above.
+   */
+  memcpy(owl->cumulative_goal, owl->goal, BOARDMAX);
+  compute_owl_escape_values(owl);
+  owl_mark_boundary(owl);
+  owl->lunches_are_current = 0;
+  owl->escape_moves = 0;
+  owl->origin = libs[0];
+
+  if (do_owl_attack(owl, NULL, NULL))
+    result = 0;
+  else
+    result = 1;
+  while (num_moves-- > 0) {
+    if (get_level() >= 8)
+      decrease_depth_values();
+    popgo();
+  }
+
+  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
+  DEBUG(DEBUG_OWL_PERFORMANCE,
+	"owl_substantial %1m, result %d (%d, %d nodes, %f seconds)\n",
+	str, result, local_owl_node_counter,
+	tactical_nodes, gg_cputime() - start);
+
+  store_persistent_owl_cache(OWL_SUBSTANTIAL, str, 0, 0, result, 0, 0, 0,
+			     tactical_nodes, owl->goal, owl->color);
+
+  return result;
+}
+
+
+
 /*
  * This function calls owl_determine_life() to get an eye estimate,
  * and matchpat() for vital attack moves, and decides according to
@@ -5319,313 +5798,6 @@
   }
 }
 
-/* Use the owl code to determine whether the move at (move) makes
- * the dragon at (target) owl safe. This is used to test whether
- * tactical defenses are strategically viable and whether a vital eye
- * point does kill an owl critical dragon. 
- *
- * Should be called only when stackp==0.
- */
-
-int
-owl_does_defend(int move, int target, int *kworm)
-{
-  int color = board[target];
-  int result = 0;
-  struct local_owl_data *owl;
-  int reading_nodes_when_called = get_reading_node_counter();
-  int tactical_nodes;
-  int origin;
-  int acode;
-  int wpos = NO_MOVE;
-  int wid = MAX_GOAL_WORMS;
-  double start = 0.0;
-
-  if (debug & DEBUG_OWL_PERFORMANCE)
-    start = gg_cputime();
-
-  if (worm[target].unconditional_status == DEAD)
-    return 0;
-
-  origin = dragon[target].origin;
-  TRACE("owl_does_defend %1m %1m(%1m)\n", move, target, origin);
-
-  if (search_persistent_owl_cache(OWL_DOES_DEFEND, move, target, 0,
-				  &result, kworm, NULL, NULL))
-    return result;
-
-  if (trymove(move, color, "owl_does_defend", target)) {
-    /* Check if a compatible owl_attack() is cached. */
-    if (search_persistent_owl_cache(OWL_ATTACK, origin, 0, 0,
-				    &result, NULL, kworm, NULL)) {
-      popgo();
-      return REVERSE_RESULT(result);
-    }
-    
-    /*
-     * FIXME: (move) will be added to the goal dragon although we
-     * do not know whether it is really connected.
-     */
-    init_owl(&owl, target, NO_MOVE, move, 1, NULL);
-    prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
-		      kworm, 0);
-    acode = do_owl_attack(target, NULL, &wid, owl, 0);
-    finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
-    result = REVERSE_RESULT(acode);
-    popgo();
-  }
-  else
-    return 0;  /* Don't cache anything in this case. */
-
-  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
-
-  DEBUG(DEBUG_OWL_PERFORMANCE,
-	"owl_does_defend %1m %1m(%1m), result %d (%d, %d nodes, %f seconds)\n",
-	move, target, origin, result, local_owl_node_counter,
-	tactical_nodes, gg_cputime() - start);
-
-  store_persistent_owl_cache(OWL_DOES_DEFEND, move, target, 0,
-			     result, wpos, 0, 0,
-			     tactical_nodes, owl->goal, board[target]);
-
-  if (kworm)
-    *kworm = wpos;
-  return result;
-}
-
-
-/* Use the owl code to determine whether the dragon at (target) is owl
- * safe after an own move at (move). This is used to detect
- * blunders. In case the dragon is not safe, it also tries to find a
- * defense point making (target) safe in a later move.
- *
- * Should be called only when stackp==0.
- */
-
-int
-owl_confirm_safety(int move, int target, int *defense_point, int *kworm)
-{
-  int color = board[target];
-  int result = 0;
-  struct local_owl_data *owl;
-  int reading_nodes_when_called = get_reading_node_counter();
-  int tactical_nodes;
-  int origin;
-  int defense = 0;
-  double start = 0.0;
-  int acode;
-  int wpos = NO_MOVE;
-  int wid = MAX_GOAL_WORMS;
-
-  if (debug & DEBUG_OWL_PERFORMANCE)
-    start = gg_cputime();
-
-  if (worm[target].unconditional_status == DEAD)
-    return 0;
-
-  origin = dragon[target].origin;
-  TRACE("owl_confirm_safety %1m %1m(%1m)\n", move, target, origin);
-
-  if (search_persistent_owl_cache(OWL_CONFIRM_SAFETY, move, target, 0,
-				  &result, defense_point, kworm, NULL))
-    return result;
-
-  if (trymove(move, color, "owl_confirm_safety", target)) {
-    /* Check if a compatible owl_attack() is cached. */
-    if (search_persistent_owl_cache(OWL_ATTACK, origin, 0, 0,
-				    &result, defense_point, kworm, NULL)) {
-      popgo();
-      if (result == 0)
-	return WIN;
-      else if (result == GAIN)
-	return LOSS;
-      else
-	return 0;
-    }
-    
-    init_owl(&owl, target, NO_MOVE, move, 1, NULL);
-    prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
-		      kworm, 0);
-    acode = do_owl_attack(target, &defense, &wid, owl, 0);
-    finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
-    if (acode == 0)
-      result = WIN;
-    else if (acode == GAIN)
-      result = LOSS;
-    popgo();
-  }
-  else
-    return 0;  /* Don't cache anything in this case. */
-
-  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
-
-  DEBUG(DEBUG_OWL_PERFORMANCE,
-	"owl_confirm_safety %1m %1m(%1m), result %d %1m (%d, %d nodes, %f seconds)\n",
-	move, target, origin, result, defense,
-	local_owl_node_counter, tactical_nodes,
-	gg_cputime() - start);
-
-  store_persistent_owl_cache(OWL_CONFIRM_SAFETY, move, target, 0,
-			     result, defense, wpos, 0,
-			     tactical_nodes, owl->goal, board[target]);
-
-  if (defense_point)
-    *defense_point = defense;
-  if (kworm)
-    *kworm = wpos;
-
-  return result;
-}
-
-
-/* Use the owl code to determine whether the attack move at (move) of
- * the dragon (target) is effective, i.e. whether it kills the stones.
- *
- * Should be called only when stackp==0.
- */
-
-int
-owl_does_attack(int move, int target, int *kworm)
-{
-  int color = board[target];
-  int other = OTHER_COLOR(color);
-  int result = 0;
-  struct local_owl_data *owl;
-  int reading_nodes_when_called = get_reading_node_counter();
-  int tactical_nodes;
-  int origin;
-  int dcode;
-  int wpos = NO_MOVE;
-  int wid = MAX_GOAL_WORMS;
-  double start = 0.0;
-
-  if (debug & DEBUG_OWL_PERFORMANCE)
-    start = gg_cputime();
-
-  if (worm[target].unconditional_status == ALIVE)
-    return 0;
-
-  origin = dragon[target].origin;
-  TRACE("owl_does_attack %1m %1m(%1m)\n", move, target, origin);
-
-  if (search_persistent_owl_cache(OWL_DOES_ATTACK, move, target, 0,
-				  &result, kworm, NULL, NULL))
-    return result;
-
-  /* FIXME: We want to do this after the trymove(), but currently
-   * owl_mark_dragon() may crash if the trymove() happens to remove
-   * some stones of the goal dragon from the board.
-   */
-#if 1
-  init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
-#endif
-
-  if (trymove(move, other, "owl_does_attack", target)) {
-    /* Check if a compatible owl_defend() is cached. */
-    if (search_persistent_owl_cache(OWL_DEFEND, origin, 0, 0,
-				    &result, NULL, kworm, NULL)) {
-      popgo();
-      return REVERSE_RESULT(result);
-    }
-
-#if 0
-    local_owl_node_counter = 0;
-    owl->lunches_are_current = 0;
-    owl_mark_dragon(target, NO_MOVE, owl);
-#endif
-    owl_update_boundary_marks(move, owl);
-#if 0
-    compute_owl_escape_values(owl);
-#endif
-    /* FIXME: Should also check if part of the dragon was captured,
-     *        like do_owl_attack() does.
-     */
-    if (board[target] == EMPTY)
-      dcode = 0;
-    else {
-      prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
-	                 kworm, 0);
-      dcode = do_owl_defend(target, NULL, &wid, owl, 0);
-      finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
-    }
-    result = REVERSE_RESULT(dcode);
-    owl->lunches_are_current = 0;
-    popgo();
-  }
-  else
-    return 0;  /* Don't cache anything in this case. */
-
-  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
-
-  DEBUG(DEBUG_OWL_PERFORMANCE,
-	"owl_does_attack %1m %1m(%1m), result %d (%d, %d nodes, %f seconds)\n",
-	move, target, origin, result, local_owl_node_counter,
-	tactical_nodes, gg_cputime() - start);
-
-  store_persistent_owl_cache(OWL_DOES_ATTACK, move, target, 0,
-			     result, wpos, 0, 0,
-			     tactical_nodes, owl->goal, board[target]);
-
-  if (kworm)
-    *kworm = wpos;
-  return result;
-}
-
-
-/* Use the owl code to determine whether connecting the two dragons
- * (target1) and (target2) by playing at (move) results in a living
- * dragon. Should be called only when stackp==0.
- */
-
-int
-owl_connection_defends(int move, int target1, int target2)
-{
-  int color = board[target1];
-  int result = 0;
-  int reading_nodes_when_called = get_reading_node_counter();
-  int tactical_nodes;
-  double start = 0.0;
-  struct local_owl_data *owl;
-
-  if (debug & DEBUG_OWL_PERFORMANCE)
-    start = gg_cputime();
-
-  ASSERT1(board[target2] == color, target2);
-  TRACE("owl_connection_defends %1m %1m %1m\n", move, target1, target2);
-
-  if (worm[target1].unconditional_status == DEAD)
-    return 0;
-  if (worm[target2].unconditional_status == DEAD)
-    return 0;
-
-  if (search_persistent_owl_cache(OWL_CONNECTION_DEFENDS, move, target1,
-				  target2, &result, NULL, NULL, NULL))
-    return result;
-
-  init_owl(&owl, target1, target2, NO_MOVE, 1, NULL);
-
-  if (trymove(move, color, "owl_connection_defends", target1)) {
-    owl_update_goal(move, SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE, owl, 0, NULL);
-    if (!do_owl_attack(move, NULL, NULL, owl, 0))
-      result = WIN;
-    owl->lunches_are_current = 0;
-    popgo();
-  }
-  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
-  
-  DEBUG(DEBUG_OWL_PERFORMANCE,
-	"owl_conn_defends %1m %1m %1m, result %d (%d, %d nodes, %f seconds)\n",
-	move, target1, target2, result, local_owl_node_counter,
-	tactical_nodes, gg_cputime() - start);
-
-  store_persistent_owl_cache(OWL_CONNECTION_DEFENDS, move, target1, target2,
-			     result, 0, 0, 0, tactical_nodes,
-			     owl->goal, color);
-
-  return result;
-}
-
-
 /* This function attempts to make a list of dead strings
  * which may be relevant to the life of the goal dragon.
  * Such strings are called owl lunches. They are ignored
@@ -6104,129 +6276,6 @@
 }
   
 
-/* This function, called when stackp==0, returns true if capturing
- * the string at (str) results in a live group.
- */
-
-#define MAX_SUBSTANTIAL_LIBS 10
-
-int
-owl_substantial(int str)
-{
-  int k;
-  int libs[MAX_SUBSTANTIAL_LIBS + 1];
-  int liberties = findlib(str, MAX_SUBSTANTIAL_LIBS+1, libs);
-  int reading_nodes_when_called = get_reading_node_counter();
-  int tactical_nodes;
-  int result;
-  double start = 0.0;
-  struct local_owl_data *owl;
-  int num_moves = 0;
-
-  if (debug & DEBUG_OWL_PERFORMANCE)
-    start = gg_cputime();
-
-  /* FIXME: We want to use the full init_owl here too (cf. similar
-   * remark below).
-   */
-  reduced_init_owl(&owl, 1);
-
-  owl->color = OTHER_COLOR(board[str]);
-  local_owl_node_counter = 0;
-
-  /* Big strings are always substantial since the biggest nakade is
-   * six stones. (There are probably rare exceptions to this
-   * rule, but they are unlikely to come up in a game.)
-   */
-  if (countstones(str) > 6)
-    return 1;
-  
-  if (liberties > MAX_SUBSTANTIAL_LIBS)
-    return 0;
-
-  memset(owl->goal, 0, sizeof(owl->goal));
-  /* Mark the neighbors of the string. If one is found which is alive, return
-   * true. */
-  {
-    int adjs[MAXCHAIN];
-    int adj;
-
-    adj = chainlinks(str, adjs);
-    for (k = 0; k < adj; k++) {
-      if (dragon[adjs[k]].status == ALIVE)
-	return 1;
-      mark_dragon(adjs[k], owl->goal, 1);
-    }
-  }
-
-  /* We must check the cache while stackp == 0, but we wait until the
-   * trivial tests have been done.
-   */
-  if (search_persistent_owl_cache(OWL_SUBSTANTIAL, str, 0, 0,
-				  &result, NULL, NULL, NULL))
-    return result;
-
-  /* fill all the liberties */
-  for (k = 0; k < liberties; k++) {
-    if (trymove(libs[k], owl->color, NULL, 0)) {
-      if (get_level() >= 8)
-	increase_depth_values();
-      owl->goal[libs[k]] = 1;
-      num_moves++;
-    }
-    else {
-      /* if we can't fill, try swapping with the next liberty */
-      if (k < liberties-1
-	  && trymove(libs[k+1], owl->color, NULL, 0)) {
-	if (get_level() >= 8)
-	  increase_depth_values();
-	owl->goal[libs[k+1]] = 1;
-	libs[k+1] = libs[k];
-	num_moves++;
-      }
-      else {
-	/* Can't fill the liberties. Give up! */
-	while (num_moves-- > 0) {
-	  if (get_level() >= 8)
-	    decrease_depth_values();
-	  popgo();
-	}
-	return 0;
-      }
-    }
-  }
-  /* FIXME: We would want to use init_owl() here too, but it doesn't
-   * fit very well with the construction of the goal array above.
-   */
-  memcpy(owl->cumulative_goal, owl->goal, BOARDMAX);
-  compute_owl_escape_values(owl);
-  owl_mark_boundary(owl);
-  owl->lunches_are_current = 0;
-
-  if (do_owl_attack(libs[0], NULL, NULL, owl, 0))
-    result = 0;
-  else
-    result = 1;
-  while (num_moves-- > 0) {
-    if (get_level() >= 8)
-      decrease_depth_values();
-    popgo();
-  }
-
-  tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
-  DEBUG(DEBUG_OWL_PERFORMANCE,
-	"owl_substantial %1m, result %d (%d, %d nodes, %f seconds)\n",
-	str, result, local_owl_node_counter,
-	tactical_nodes, gg_cputime() - start);
-
-  store_persistent_owl_cache(OWL_SUBSTANTIAL, str, 0, 0, result, 0, 0, 0,
-			     tactical_nodes, owl->goal, owl->color);
-
-  return result;
-}
-
-
-
 /* Returns true if and only if (i, j) is a 1-2 vertex, i.e. next to a
  * corner.
  */
@@ -6445,9 +6494,12 @@
  * goal. Used in do_owl_attack()
  */
 static int
-select_new_goal_origin(int origin, struct local_owl_data *owl)
+select_new_goal_origin(struct local_owl_data *owl)
 {
   int pos;
+  int origin = NO_MOVE;
+  if (IS_STONE(board[owl->origin]))
+    origin = owl->origin;
   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
     if (board[pos] == owl->color && owl->goal[pos] == 1)
       return find_origin(pos);
@@ -6748,6 +6800,8 @@
 static void
 reduced_init_owl(struct local_owl_data **owl, int at_bottom_of_stack)
 {
+  local_owl_node_counter = 0;
+
   if (at_bottom_of_stack)
     owl_stack_pointer = 0;
   else
@@ -6769,8 +6823,9 @@
 {
   reduced_init_owl(owl, at_bottom_of_stack);
 
-  local_owl_node_counter = 0;
+  (*owl)->origin = target1;
   (*owl)->lunches_are_current = 0;
+  (*owl)->escape_moves = 0;
   owl_mark_dragon(target1, target2, *owl, new_dragons);
   if (move != NO_MOVE)
     owl_update_goal(move, SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE, *owl, 0, NULL);
@@ -6812,8 +6867,10 @@
   memcpy(new_owl->escape_values, (*owl)->escape_values,
 	 sizeof(new_owl->escape_values));
   new_owl->color = (*owl)->color;
+  new_owl->origin = (*owl)->origin;
 
   new_owl->lunches_are_current = 0;
+  new_owl->escape_moves = (*owl)->escape_moves;
 
   /* Needed for stack organization. Since there may be one or two sets
    * of owl data active at we don't know whether to restore from the
