1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
2  * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
3  * http://www.gnu.org/software/gnugo/ for more information.          *
4  *                                                                   *
5  * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,   *
6  * 2008 and 2009 by the Free Software Foundation.                    *
7  *                                                                   *
8  * This program is free software; you can redistribute it and/or     *
9  * modify it under the terms of the GNU General Public License as    *
10  * published by the Free Software Foundation - version 3 or          *
11  * (at your option) any later version.                               *
12  *                                                                   *
13  * This program is distributed in the hope that it will be useful,   *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     *
16  * GNU General Public License in file COPYING for more details.      *
17  *                                                                   *
18  * You should have received a copy of the GNU General Public         *
19  * License along with this program; if not, write to the Free        *
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,       *
21  * Boston, MA 02111, USA.                                            *
22 \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
23 
24 /*
25  * The code in this file implements "Optics With Limit-negotiation (OWL)."
26  *
27  * The life and death code in optics.c, works reasonably well as long as the
28  * position is in a *terminal position*, which we define to be one where there
29  * are no moves left which can expand the eye space, or limit it. In
30  * situations where the dragon is surrounded, yet has room to thrash around a
31  * bit making eyes, a simple application of the graph-based analysis will not
32  * work. Instead, a bit of reading is needed to reach a terminal position.
33  * The defender tries to expand his eyespace, the attacker to limit it, and
34  * when neither finds an effective move, the position is evaluated. We call
35  * this type of life and death reading *Optics With Limit-negotiation* (OWL).
36  *
37  *                             (|__|)
38  *                            (@)(@))
39  *                            |:v:: |
40  *                           (       )
41  *                            \|   |/
42  *                            =#===#=
43  *                            /___/
44  *
45  *                The owl is noted for its keen vision
46  *                       and (purported) wisdom.
47  */
48 
49 #include "gnugo.h"
50 
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include "liberty.h"
55 #include "readconnect.h"
56 #include "patterns.h"
57 #include "cache.h"
58 #include "sgftree.h"
59 #include "gg_utils.h"
60 
61 #define MAX_MOVES 3           /* maximum number of branches at each node */
62 #define MAX_SEMEAI_MOVES 6    /* semeai branch factor */
63 #define MAX_SEMEAI_DEPTH 100  /* Don't read below this depth */
64 #define MAX_LUNCHES 10
65 #define MAX_GOAL_WORMS 15  /* maximum number of worms in a dragon to be */
66                            /*   cataloged.  NOTE: Must fit in value2 in hashnode! */
67 #define MAX_ESCAPE 3  /* After this many escape moves, owl_determine_life is */
68                       /*    not called                                       */
69 
70 struct local_owl_data {
71   signed char goal[BOARDMAX];
72   signed char boundary[BOARDMAX];
73   /* Same as goal, except never anything is removed from it. */
74   signed char cumulative_goal[BOARDMAX];
75 
76   /* FIXME: neighbors[] and escape_values[] are never recomputed.
77    *	    Consider moving these arrays from stack to a static or
78    *	    dynamic variable so it is not copied around in
79    *	    do_push_owl().  Be aware of semeai code though.
80    */
81   signed char neighbors[BOARDMAX];
82 
83   signed char escape_values[BOARDMAX];
84   int color;
85 
86   struct eye_data my_eye[BOARDMAX];
87   /* array of half-eye data for use during owl reading */
88   struct half_eye_data half_eye[BOARDMAX];
89 
90   int lunch[MAX_LUNCHES];
91   int lunch_attack_code[MAX_LUNCHES];
92   int lunch_attack_point[MAX_LUNCHES];
93   int lunch_defend_code[MAX_LUNCHES];
94   int lunch_defense_point[MAX_LUNCHES];
95   signed char inessential[BOARDMAX];
96 
97   int lunches_are_current; /* If true, owl lunch data is current */
98 
99   signed char safe_move_cache[BOARDMAX];
100 
101   /* This is used to organize the owl stack. */
102   struct local_owl_data *restore_from;
103 };
104 
105 
106 static int result_certain;
107 
108 /* Statistics. */
109 static int local_owl_node_counter;
110 /* Node limitation. */
111 static int global_owl_node_counter = 0;
112 
113 static struct local_owl_data *current_owl_data;
114 static struct local_owl_data *other_owl_data;
115 
116 static int goal_worms_computed = 0;
117 static int owl_goal_worm[MAX_GOAL_WORMS];
118 
119 
120 #define MAX_CUTS 5
121 
122 enum same_dragon_value {
123   SAME_DRAGON_NOT_CONNECTED,
124   SAME_DRAGON_MAYBE_CONNECTED,
125   SAME_DRAGON_CONNECTED,
126   SAME_DRAGON_ALL_CONNECTED
127 };
128 
129 struct matched_pattern_data;
130 
131 struct owl_move_data {
132   int pos;          /* move coordinate */
133   int value;        /* value */
134   const char *name; /* name of the pattern suggesting the move */
135   /* whether the move extends the dragon or not */
136   enum same_dragon_value same_dragon;
137   int lunch;	    /* Position of a lunch, if applicable.*/
138   int escape;       /* true if an escape pattern is matched */
139   int defense_pos;  /* defense coordinate for vital owl attack patterns. */
140   int cuts[MAX_CUTS]; /* strings of the goal that might get cut off */
141   /* pointer to pattern data, used for SAME_DRAGON_ALL_CONNECTED */
142   struct matched_pattern_data *pattern_data;
143 };
144 
145 #define USE_BDIST 1
146 
147 struct matched_pattern_data {
148   int move;
149   int value;
150   int ll;
151   int anchor;
152 #if USE_BDIST
153   int bdist;
154 #endif
155   struct pattern *pattern;
156 
157   /* To link combinable patterns in chains. */
158   int next_pattern_index;
159 };
160 
161 struct matched_patterns_list_data {
162   int initialized;
163   int counter; 		/* Number of patterns in the list. */
164   int used;		/* How many patterns have already been used?*/
165   int list_size;
166   struct matched_pattern_data *pattern_list;
167   int first_pattern_index[BOARDMAX];
168 
169   int heap_num_patterns;
170   struct matched_pattern_data **pattern_heap;
171 };
172 
173 void dump_pattern_list(struct matched_patterns_list_data *list);
174 
175 
176 static int do_owl_attack(int str, int *move, int *wormid,
177 			 struct local_owl_data *owl, int escape);
178 static int do_owl_defend(int str, int *move, int *wormid,
179 			 struct local_owl_data *owl, int escape);
180 static void owl_shapes(struct matched_patterns_list_data *list,
181                        struct owl_move_data moves[MAX_MOVES], int color,
182 		       struct local_owl_data *owl, struct pattern_db *type);
183 static void collect_owl_shapes_callbacks(int anchor, int color,
184 	  			         struct pattern *pattern_db,
185 				         int ll, void *data);
186 
187 static void pattern_list_prepare(struct matched_patterns_list_data *list);
188 static void pattern_list_build_heap(struct matched_patterns_list_data *list);
189 static void pattern_list_pop_heap_once(struct matched_patterns_list_data *list);
190 static void pattern_list_sink_heap_top_element(struct matched_patterns_list_data
191 					       *list);
192 
193 static int get_next_move_from_list(struct matched_patterns_list_data *list,
194                                    int color, struct owl_move_data *moves,
195 				   int cutoff, struct local_owl_data *owl);
196 static void init_pattern_list(struct matched_patterns_list_data *list);
197 static void close_pattern_list(int color,
198 			       struct matched_patterns_list_data *list);
199 static void owl_shapes_callback(int anchor, int color,
200 				struct pattern *pattern_db,
201 				int ll, void *data);
202 static void owl_add_move(struct owl_move_data *moves, int move, int value,
203 			 const char *reason,
204 			 enum same_dragon_value same_dragon, int lunch,
205 			 int escape, int defense_pos, int max_moves,
206 			 struct matched_pattern_data *pattern_data);
207 static void owl_determine_life(struct local_owl_data *owl,
208 			       struct local_owl_data *second_owl,
209 			       int does_attack,
210 			       struct owl_move_data *moves,
211 			       struct eyevalue *probable_eyes,
212 			       int *eyemin, int *eyemax);
213 static void owl_find_relevant_eyespaces(struct local_owl_data *owl,
214 					int mw[BOARDMAX], int mz[BOARDMAX]);
215 static int owl_estimate_life(struct local_owl_data *owl,
216 			     struct local_owl_data *second_owl,
217     		  	     struct owl_move_data vital_moves[MAX_MOVES],
218 		  	     const char **live_reason,
219 			     int does_attack,
220 		  	     struct eyevalue *probable_eyes,
221 			     int *eyemin, int *eyemax);
222 static int modify_stupid_eye_vital_point(struct local_owl_data *owl,
223 					 int *vital_point,
224 					 int is_attack_point);
225 static int modify_eyefilling_move(int *move, int color);
226 static int estimate_lunch_half_eye_bonus(int lunch,
227 			struct half_eye_data half_eye[BOARDMAX]);
228 static void owl_mark_dragon(int apos, int bpos,
229 			    struct local_owl_data *owl,
230 			    int new_dragons[BOARDMAX]);
231 static void owl_mark_worm(int apos, int bpos,
232 			  struct local_owl_data *owl);
233 static void owl_mark_boundary(struct local_owl_data *owl);
234 static void owl_update_goal(int pos, enum same_dragon_value same_dragon,
235 			    int lunch, struct local_owl_data *owl,
236 			    int semeai_call,
237 			    struct matched_pattern_data *pattern_data);
238 static void owl_test_cuts(signed char goal[BOARDMAX], int color,
239 		          int cuts[MAX_CUTS]);
240 static void componentdump(const signed char component[BOARDMAX]);
241 static void owl_update_boundary_marks(int pos, struct local_owl_data *owl);
242 static void owl_find_lunches(struct local_owl_data *owl);
243 static int improve_lunch_attack(int lunch, int attack_point);
244 static int improve_lunch_defense(int lunch, int defense_point);
245 static void owl_make_domains(struct local_owl_data *owla,
246 			     struct local_owl_data *owlb);
247 static int owl_safe_move(int move, int color);
248 static void sniff_lunch(int lunch, int *min, int *probable, int *max,
249 			struct local_owl_data *owl);
250 static void eat_lunch_escape_bonus(int lunch, int *min, int *probable,
251 				   int *max, struct local_owl_data *owl);
252 static int select_new_goal_origin(int origin, struct local_owl_data *owl);
253 static void compute_owl_escape_values(struct local_owl_data *owl);
254 static int owl_escape_route(struct local_owl_data *owl);
255 static void do_owl_analyze_semeai(int apos, int bpos,
256 				  struct local_owl_data *owla,
257 				  struct local_owl_data *owlb,
258 				  int *resulta, int *resultb,
259 				  int *move, int pass, int owl_phase);
260 static int semeai_trymove_and_recurse(int apos, int bpos,
261 				      struct local_owl_data *owla,
262 				      struct local_owl_data *owlb,
263 				      int owl_phase,
264 				      int move, int color, int ko_allowed,
265 				      int move_value, const char *move_name,
266 				      enum same_dragon_value same_dragon,
267 				      struct matched_pattern_data *pattern_data,
268 				      int lunch, int *semeai_move,
269 				      int *this_resulta, int *this_resultb);
270 static void semeai_add_sgf_comment(int value, int owl_phase);
271 static int semeai_trust_tactical_attack(int str);
272 static int semeai_propose_eyespace_filling_move(struct local_owl_data *owla,
273 						struct local_owl_data *owlb);
274 static void semeai_review_owl_moves(struct owl_move_data owl_moves[MAX_MOVES],
275 				    struct local_owl_data *owla,
276 				    struct local_owl_data *owlb, int color,
277 				    int *safe_outside_liberty_found,
278 				    int *safe_common_liberty_found,
279 				    int *riskless_move_found,
280 				    signed char mw[BOARDMAX],
281 				    struct owl_move_data semeai_moves[MAX_SEMEAI_MOVES],
282 				    int guess_same_dragon, int value_bonus,
283 				    int *critical_semeai_worms);
284 static int semeai_move_value(int move, struct local_owl_data *owla,
285 			     struct local_owl_data *owlb, int raw_value,
286 			     int *critical_semeai_worms);
287 static int semeai_is_riskless_move(int move, struct local_owl_data *owla);
288 static void remove_eye_filling_moves(struct local_owl_data *our_owl,
289 				     struct owl_move_data *moves);
290 static int find_semeai_backfilling_move(int worm, int liberty);
291 static int liberty_of_goal(int pos, struct local_owl_data *owl);
292 static int second_liberty_of_goal(int pos, struct local_owl_data *owl);
293 static int matches_found;
294 static signed char found_matches[BOARDMAX];
295 
296 static void reduced_init_owl(struct local_owl_data **owl,
297     			     int at_bottom_of_stack);
298 static void init_owl(struct local_owl_data **owl, int target1, int target2,
299 		     int move, int use_stack, int new_dragons[BOARDMAX]);
300 
301 static struct local_owl_data *owl_stack[2 * MAXSTACK];
302 static int owl_stack_size = 0;
303 static int owl_stack_pointer = 0;
304 static void check_owl_stack_size(void);
305 static void push_owl(struct local_owl_data **owl);
306 static void do_push_owl(struct local_owl_data **owl);
307 static void pop_owl(struct local_owl_data **owl);
308 
309 #if 0
310 static int catalog_goal(struct local_owl_data *owl,
311     			int goal_worm[MAX_GOAL_WORMS]);
312 #endif
313 
314 static int list_goal_worms(struct local_owl_data *owl,
315     			   int goal_worm[MAX_GOAL_WORMS]);
316 
317 /* FIXME: taken from move_reasons.h */
318 #define MAX_DRAGONS       2 * MAX_BOARD * MAX_BOARD / 3
319 
320 static int dragon_goal_worms[MAX_DRAGONS][MAX_GOAL_WORMS];
321 
322 static void
323 prepare_goal_list(int str, struct local_owl_data *owl,
324 		  int list[MAX_GOAL_WORMS], int *flag, int *kworm,
325 		  int do_list);
326 static void
327 finish_goal_list(int *flag, int *wpos, int list[MAX_GOAL_WORMS], int index);
328 
329 
330 /* Semeai worms are worms whose capture wins the semeai. */
331 
332 #define MAX_SEMEAI_WORMS 20
333 static int s_worms = 0;
334 static int semeai_worms[MAX_SEMEAI_WORMS];
335 static int important_semeai_worms[MAX_SEMEAI_WORMS];
336 
337 /* Whether one color prefers to get a ko over a seki. */
338 static int prefer_ko;
339 
340 /* Usually it's a bad idea to include the opponent worms involved in
341  * the semeai in the eyespace. For some purposes (determining a
342  * definite lack of eyespace, finding certain vital moves), however,
343  * we want to do that anyway. Then set this variable to 1 before
344  * calling owl_estimate_life() and reset it afterwards.
345  *
346  * FIXME: We should implement a nicer mechanism to propagate this
347  *        information to owl_lively(), where it's used.
348  */
349 static int include_semeai_worms_in_eyespace = 0;
350 
351 
352 
353 static void
clear_cut_list(int cuts[MAX_CUTS])354 clear_cut_list(int cuts[MAX_CUTS])
355 {
356   int i;
357   for (i = 0; i < MAX_CUTS; i++)
358     cuts[i] = NO_MOVE;
359 }
360 
361 
362 
363 /* Called when (apos) and (bpos) point to adjacent dragons
364  * of the opposite color, both with matcher_status DEAD or
365  * CRITICAL, analyzes the semeai, assuming that the player
366  * of the (apos) dragon moves first. The results returned
367  * by *resulta and *resultb are the results of the defense
368  * of the apos dragon and the attack of the bpos dragon,
369  * respectively. Thus if these results are 1 and 0,
370  * respectively, the usual meaning is that a move by the
371  * apos player produces seki.
372  *
373  * owl determines whether owl moves are being generated
374  * or simple liberty filling is taking place.
375  *
376  */
377 
378 void
owl_analyze_semeai(int apos,int bpos,int * resulta,int * resultb,int * semeai_move,int owl,int * semeai_result_certain)379 owl_analyze_semeai(int apos, int bpos, int *resulta, int *resultb,
380 		   int *semeai_move, int owl, int *semeai_result_certain)
381 {
382   owl_analyze_semeai_after_move(PASS_MOVE, EMPTY, apos, bpos, resulta, resultb,
383 				semeai_move, owl, semeai_result_certain, 0);
384 }
385 
386 /* Same as the function above with the addition that an arbitrary move
387  * may be made before the analysis is performed.
388  */
389 void
owl_analyze_semeai_after_move(int move,int color,int apos,int bpos,int * resulta,int * resultb,int * semeai_move,int owl,int * semeai_result_certain,int recompute_dragons)390 owl_analyze_semeai_after_move(int move, int color, int apos, int bpos,
391 			      int *resulta, int *resultb, int *semeai_move,
392 			      int owl, int *semeai_result_certain,
393 			      int recompute_dragons)
394 {
395   signed char ms[BOARDMAX];
396   int w1, w2;
397   int str;
398   SGFTree *save_sgf_dumptree = sgf_dumptree;
399   int save_verbose = verbose;
400   int dummy_resulta;
401   int dummy_resultb;
402   int dummy_semeai_move;
403   double start = 0.0;
404   int reading_nodes_when_called = get_reading_node_counter();
405   int nodes_used;
406   int new_dragons[BOARDMAX];
407 
408   struct local_owl_data *owla;
409   struct local_owl_data *owlb;
410   Hash_data goal_hash;
411 
412   if (!resulta)
413     resulta = &dummy_resulta;
414   if (!resultb)
415     resultb = &dummy_resultb;
416   if (!semeai_move)
417     semeai_move = &dummy_semeai_move;
418 
419   if (debug & DEBUG_OWL_PERFORMANCE)
420     start = gg_cputime();
421 
422   if (recompute_dragons) {
423     if (tryko(move, color, "Recompute dragons for semeai.")) {
424       compute_new_dragons(new_dragons);
425       popgo();
426     }
427     else
428       recompute_dragons = 0;
429   }
430 
431 
432   /* Look for owl substantial worms of either dragon adjoining
433    * the other dragon. Capturing such a worm wins the semeai.
434    * These are the semeai_worms. This code must come before
435    * the owl_init() calls because the owl_substantial
436    *
437    * FIXME: The sentence above is unfinished.
438    */
439   s_worms = 0;
440   memset(ms, 0, sizeof(ms));
441   for (w1 = first_worm_in_dragon(apos);
442        w1 != NO_MOVE;
443        w1 = next_worm_in_dragon(w1)) {
444     for (w2 = first_worm_in_dragon(bpos);
445 	 w2 != NO_MOVE;
446 	 w2 = next_worm_in_dragon(w2)) {
447       if (adjacent_strings(w1, w2) || have_common_lib(w1, w2, NULL)) {
448 	mark_string(w1, ms, 1);
449 	mark_string(w2, ms, 1);
450       }
451     }
452   }
453 
454 
455 
456   sgf_dumptree = NULL;
457   if (verbose > 0)
458     verbose--;
459   for (str = BOARDMIN; str < BOARDMAX; str++)
460     if (ON_BOARD(str) && ms[str] && worm[str].origin == str) {
461       int adj;
462       int adjs[MAXCHAIN];
463       int k;
464       int adjacent_to_outside = 0;
465 
466       /* Is the string adjacent to a living dragon outside the semeai?
467        * In that case it's important to attack/defend it for the life
468        * of the opponent.
469        *
470        * FIXME: Checking crude_status here isn't quite appropriate but
471        * owl_status is not always computed and status itself is unsafe
472        * since it might change before later calls to this code, e.g.
473        * when checking for blunders.
474        *
475        * Not checking for aliveness at all gives problems in e.g.
476        * ld_owl:302 where S19 is a separate dragon and R19 should not
477        * be considered critically important. What we really would like
478        * to determine is whether it's outside the semeai, however.
479        */
480       adj = chainlinks(str, adjs);
481       for (k = 0; k < adj; k++) {
482 	if (!is_same_dragon(adjs[k], apos)
483 	    && !is_same_dragon(adjs[k], bpos)
484 	    && dragon[adjs[k]].crude_status == ALIVE)
485 	  adjacent_to_outside = 1;
486       }
487 
488       if ((adjacent_to_outside || countstones(str) > 6)
489 	  && s_worms < MAX_SEMEAI_WORMS) {
490 	important_semeai_worms[s_worms] = 1;
491 	semeai_worms[s_worms++] = str;
492 	DEBUG(DEBUG_SEMEAI, "important semeai worm: %1m\n", str);
493       }
494       else if (owl_substantial(str) && s_worms < MAX_SEMEAI_WORMS) {
495 	important_semeai_worms[s_worms] = 0;
496 	semeai_worms[s_worms++] = str;
497 	DEBUG(DEBUG_SEMEAI, "semeai worm: %1m\n", str);
498       }
499     }
500   verbose = save_verbose;
501   sgf_dumptree = save_sgf_dumptree;
502 
503   ASSERT1(board[apos] == OTHER_COLOR(board[bpos]), apos);
504   count_variations = 1;
505   if (move == PASS_MOVE)
506     DEBUG(DEBUG_SEMEAI, "owl_analyze_semeai: %1m vs. %1m\n", apos, bpos);
507   else
508     DEBUG(DEBUG_SEMEAI, "owl_analyze_semeai_after_move %C %1m: %1m vs. %1m\n",
509 	  color, move, apos, bpos);
510 
511   if (owl) {
512     if (recompute_dragons) {
513       init_owl(&owla, apos, NO_MOVE, NO_MOVE, 1, new_dragons);
514       init_owl(&owlb, bpos, NO_MOVE, NO_MOVE, 0, new_dragons);
515     }
516     else {
517       init_owl(&owla, apos, NO_MOVE, NO_MOVE, 1, NULL);
518       init_owl(&owlb, bpos, NO_MOVE, NO_MOVE, 0, NULL);
519     }
520     owl_make_domains(owla, owlb);
521   }
522   else {
523     reduced_init_owl(&owla, 1);
524     reduced_init_owl(&owlb, 0);
525     local_owl_node_counter = 0;
526     owl_mark_worm(apos, NO_MOVE, owla);
527     owl_mark_worm(bpos, NO_MOVE, owlb);
528   }
529 
530   result_certain = 1;
531 
532   {
533     Hash_data temp = goal_to_hashvalue(owla->goal);
534     goal_hash = goal_to_hashvalue(owlb->goal);
535     hashdata_xor(goal_hash, temp);
536   }
537   if (owl
538       && search_persistent_semeai_cache(ANALYZE_SEMEAI,
539 					apos, bpos, move, color, &goal_hash,
540 					resulta, resultb, semeai_move,
541 					semeai_result_certain)) {
542     if (move == PASS_MOVE) {
543       DEBUG(DEBUG_OWL_PERFORMANCE,
544 	    "analyze_semeai %1m vs. %1m, result %d %d %1m (cached)\n",
545 	    apos, bpos, *resulta, *resultb, *semeai_move);
546     }
547     else {
548       DEBUG(DEBUG_OWL_PERFORMANCE,
549 	    "analyze_semeai_after_move %C %1m: %1m vs. %1m, result %d %d %1m (cached)\n",
550 	    color, move, apos, bpos, *resulta, *resultb, *semeai_move);
551     }
552     return;
553   }
554 
555   /* In some semeai situations one or both players have the option to
556    * choose between seki and ko for the life and death of both. In
557    * general this choice depends on the ko threat situation, the
558    * overall score, and the strategical effects on surrounding
559    * dragons, but we don't try to correctly estimate this. Instead we
560    * make the reasonable assumption that if one dragon is
561    * substantially smaller than the other dragon, ko is to be
562    * preferred for the smaller dragon and seki for the larger dragon.
563    *
564    * prefer_ko can be either WHITE, BLACK, or EMPTY and tells which
565    * color, if any, prefers to get ko.
566    */
567   if (dragon[apos].size <= 5 && dragon[bpos].size > 3 * dragon[apos].size)
568     prefer_ko = board[apos];
569   else if (dragon[bpos].size <= 5 && dragon[apos].size > 3 * dragon[bpos].size)
570     prefer_ko = board[bpos];
571   else
572     prefer_ko = EMPTY;
573 
574   if (move == PASS_MOVE)
575     do_owl_analyze_semeai(apos, bpos, owla, owlb,
576 			  resulta, resultb, semeai_move, 0, owl);
577   else {
578     semeai_trymove_and_recurse(bpos, apos, owlb, owla, owl,
579 			       move, color, 1, 0, "mandatory move",
580 			       SAME_DRAGON_MAYBE_CONNECTED, NULL, NO_MOVE,
581 			       semeai_move, resultb, resulta);
582     *resulta = REVERSE_RESULT(*resulta);
583     *resultb = REVERSE_RESULT(*resultb);
584   }
585 
586   nodes_used = get_reading_node_counter() - reading_nodes_when_called;
587   if (move == PASS_MOVE) {
588     DEBUG(DEBUG_OWL_PERFORMANCE,
589 	  "analyze_semeai %1m vs. %1m, result %d %d %1m (%d, %d nodes, %f seconds)\n",
590 	  apos, bpos, *resulta, *resultb, *semeai_move, local_owl_node_counter,
591 	  nodes_used, gg_cputime() - start);
592   }
593   else {
594     DEBUG(DEBUG_OWL_PERFORMANCE,
595 	  "analyze_semeai_after_move %C %1m: %1m vs. %1m, result %d %d %1m (%d, %d nodes, %f seconds)\n",
596 	  color, move, apos, bpos, *resulta, *resultb, *semeai_move,
597 	  local_owl_node_counter,
598 	  nodes_used, gg_cputime() - start);
599   }
600 
601   if (semeai_result_certain)
602     *semeai_result_certain = result_certain;
603 
604   if (owl)
605     store_persistent_semeai_cache(ANALYZE_SEMEAI, apos, bpos, move, color,
606 				  &goal_hash,
607 				  *resulta, *resultb, *semeai_move,
608 				  result_certain, nodes_used,
609 				  owla->goal, owlb->goal);
610 }
611 
612 
613 
614 /* It is assumed that the 'a' player moves first, and
615  * determines the best result for both players. The
616  * parameter "pass" is 1 if the opponent's last move is
617  * pass. In this case, if no move is found but the genus
618  * is less than 2, then the position is declared seki.
619  *
620  * If a move is needed to get this result, then (*move) is
621  * the location, otherwise this field returns PASS.
622  */
623 
624 static void
do_owl_analyze_semeai(int apos,int bpos,struct local_owl_data * owla,struct local_owl_data * owlb,int * resulta,int * resultb,int * move,int pass,int owl_phase)625 do_owl_analyze_semeai(int apos, int bpos,
626 		      struct local_owl_data *owla,
627 		      struct local_owl_data *owlb,
628 		      int *resulta, int *resultb,
629 		      int *move, int pass, int owl_phase)
630 {
631   int color = board[apos];
632   int other = OTHER_COLOR(color);
633 #if 0
634   int wormsa, wormsb;
635   int goal_wormsa[MAX_GOAL_WORMS], goal_wormsb[MAX_GOAL_WORMS];
636 #endif
637   struct owl_move_data vital_defensive_moves[MAX_MOVES];
638   struct owl_move_data vital_offensive_moves[MAX_MOVES];
639   struct owl_move_data shape_defensive_moves[MAX_MOVES];
640   struct owl_move_data shape_offensive_moves[MAX_MOVES];
641   struct matched_patterns_list_data shape_offensive_patterns;
642   struct matched_patterns_list_data shape_defensive_patterns;
643   struct owl_move_data moves[MAX_SEMEAI_MOVES];
644   struct owl_move_data outside_liberty;
645   struct owl_move_data common_liberty;
646   struct owl_move_data backfill_outside_liberty;
647   struct owl_move_data backfill_common_liberty;
648   int safe_outside_liberty_found = 0;
649   int safe_common_liberty_found = 0;
650   int riskless_move_found = 0;
651   signed char mw[BOARDMAX];
652   int k;
653   SGFTree *save_sgf_dumptree = sgf_dumptree;
654   int save_count_variations = count_variations;
655   int move_value;
656   int best_resulta = 0;
657   int best_resultb = 0;
658   int best_move = 0;
659   const char *best_move_name = NULL;
660   int this_resulta = -1;
661   int this_resultb = -1;
662   int xpos;
663   int value1;
664   int value2;
665   int this_variation_number = count_variations - 1;
666   int you_look_alive = 0;
667   int I_look_alive = 0;
668   int dummy_move;
669   int tested_moves;
670   int critical_semeai_worms[MAX_SEMEAI_WORMS];
671   int sworm;
672   int we_might_be_inessential;
673   struct eyevalue probable_eyes_a;
674   struct eyevalue probable_eyes_b;
675   struct eyevalue dummy_eyes;
676   int I_have_more_eyes;
677 
678   SETUP_TRACE_INFO2("do_owl_analyze_semeai", apos, bpos);
679 
680   if (!move)
681     move = &dummy_move;
682 
683   ASSERT1(board[apos] == owla->color, apos);
684   ASSERT1(board[bpos] == owlb->color, bpos);
685 
686   apos = find_origin(apos);
687   bpos = find_origin(bpos);
688 
689   if (stackp <= semeai_branch_depth
690       && owl_phase
691       && tt_get(&ttable, SEMEAI, apos, bpos, depth - stackp, NULL,
692 		&value1, &value2, &xpos) == 2) {
693     TRACE_CACHED_RESULT2(value1, value2, xpos);
694     *move = xpos;
695 
696     *resulta = value1;
697     *resultb = value2;
698 
699     TRACE("%oVariation %d: %1m %1m %s %s %1m (cached) ",
700 	  this_variation_number, apos, bpos,
701 	  result_to_string(*resulta),
702 	  result_to_string(*resultb),
703 	  *move);
704     SGFTRACE_SEMEAI(xpos, *resulta, *resultb, "cached");
705     return;
706   }
707 
708   global_owl_node_counter++;
709   local_owl_node_counter++;
710 
711   shape_offensive_patterns.initialized = 0;
712   shape_defensive_patterns.initialized = 0;
713 
714 #if 0
715   wormsa = catalog_goal(owla, goal_wormsa);
716   wormsb = catalog_goal(owlb, goal_wormsb);
717 #endif
718 
719   outside_liberty.pos = NO_MOVE;
720   common_liberty.pos = NO_MOVE;
721   backfill_outside_liberty.pos = NO_MOVE;
722   backfill_common_liberty.pos = NO_MOVE;
723   for (k = 0; k < MAX_SEMEAI_MOVES; k++) {
724     moves[k].pos = 0;
725     moves[k].value = -1;
726     moves[k].name = NULL;
727     moves[k].same_dragon = SAME_DRAGON_CONNECTED;
728     moves[k].lunch = NO_MOVE;
729     clear_cut_list(moves[k].cuts);
730   }
731   ASSERT1(other == board[bpos], bpos);
732   memset(mw, 0, sizeof(mw));
733 
734   /* Turn off the sgf file and variation counting. */
735   sgf_dumptree = NULL;
736   count_variations = 0;
737 
738   /* Look for a tactical attack. We seek a semeai worm of owlb which
739    * can be attacked. If such exists and is considered critical, we
740    * declare victory. If it's not considered critical we add the
741    * attacking move as a high priority move to try.
742    */
743 
744   {
745     int upos;
746 
747     for (sworm = 0; sworm < s_worms; sworm++) {
748       critical_semeai_worms[sworm] = 0;
749       if (board[semeai_worms[sworm]] == other) {
750 	int acode = attack(semeai_worms[sworm], &upos);
751 	if (acode == WIN
752 	    && semeai_trust_tactical_attack(semeai_worms[sworm])
753 	    && important_semeai_worms[sworm]) {
754 	  *resulta = WIN;
755 	  *resultb = WIN;
756 	  *move = upos;
757 	  sgf_dumptree = save_sgf_dumptree;
758 	  count_variations = save_count_variations;
759 	  SGFTRACE_SEMEAI(upos, WIN, WIN, "tactical win found");
760 	  READ_RETURN_SEMEAI(SEMEAI, apos, bpos, depth - stackp,
761 			     move, upos, WIN, WIN);
762 	}
763 	else if (acode != 0
764 		 && find_defense(semeai_worms[sworm], NULL)) {
765 	  critical_semeai_worms[sworm] = 1;
766 	  owl_add_move(moves, upos, 105, "attack semeai worm",
767 		       SAME_DRAGON_MAYBE_CONNECTED,
768 		       NO_MOVE, 0, NO_MOVE, MAX_SEMEAI_MOVES, NULL);
769 	  TRACE("Added %1m %d (-1)\n", upos, 105);
770 	}
771 	else if (acode == WIN
772 		 && important_semeai_worms[sworm]) {
773 	  owl_add_move(moves, upos, 100, "attack semeai worm",
774 		       SAME_DRAGON_MAYBE_CONNECTED,
775 		       NO_MOVE, 0, NO_MOVE, MAX_SEMEAI_MOVES, NULL);
776 	  TRACE("Added %1m %d (-1)\n", upos, 100);
777 	}
778       }
779     }
780     /* Look for a tactical rescue. If a semeai worm of owla is tactically
781      * threatened, try to save it.
782      */
783 
784     we_might_be_inessential = 1;
785     for (sworm = 0; sworm < s_worms; sworm++)
786       if (board[semeai_worms[sworm]] == color) {
787 	if (important_semeai_worms[sworm])
788 	  we_might_be_inessential = 0;
789 
790 	if (attack(semeai_worms[sworm], NULL)
791 	    && find_defense(semeai_worms[sworm], &upos)) {
792 	  critical_semeai_worms[sworm] = 1;
793 	  owl_add_move(moves, upos, 85, "defend semeai worm",
794 		       SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE,
795 	      	       0, NO_MOVE, MAX_SEMEAI_MOVES, NULL);
796 	  TRACE("Added %1m %d (0)\n", upos, 85);
797 	}
798       }
799   }
800 
801   /* We generate the candidate moves. During the early stages of
802    * the semeai, there may be moves to expand or shrink the
803    * eyespaces of the two dragons. During the later stages, the
804    * picture is simplified and reading the semeai is a matter
805    * of filling liberties until one of the dragons may be removed,
806    * or a seki results. The first stage we call the owl phase.
807    */
808   if (!owl_phase) {
809     set_eyevalue(&probable_eyes_a, 0, 0, 0, 0);
810     set_eyevalue(&probable_eyes_b, 0, 0, 0, 0);
811     I_have_more_eyes = 0;
812   }
813   else {
814     /* First the vital moves. These include moves to attack or
815      * defend the eyespace (e.g. nakade, or hane to reduce the
816      * number of eyes) or moves to capture a lunch.
817      */
818     int eyemin_a;
819     int eyemin_b;
820     int eyemax_a;
821     int eyemax_b;
822     const char *live_reasona;
823     const char *live_reasonb;
824 
825     /* We do not wish for any string of the 'b' dragon to be
826      * counted as a lunch of the 'a' dragon since owl_determine_life
827      * can give a wrong result in the case of a semeai. So we eliminate
828      * such lunches.
829      */
830 
831     owl_find_lunches(owla);
832     owl_find_lunches(owlb);
833     for (k = 0; k < MAX_LUNCHES; k++) {
834       if (owla->lunch[k] != NO_MOVE
835 	  && owlb->goal[owla->lunch[k]]) {
836 	owla->lunch[k] = NO_MOVE;
837       }
838     }
839 #if 1
840     for (k = 0; k < MAX_LUNCHES; k++) {
841       if (owlb->lunch[k] != NO_MOVE
842 	  && owla->goal[owlb->lunch[k]]) {
843 	owlb->lunch[k] = NO_MOVE;
844       }
845     }
846 #endif
847 
848     if (owl_estimate_life(owla, owlb, vital_defensive_moves,
849 			  &live_reasona, 0, &probable_eyes_a,
850 			  &eyemin_a, &eyemax_a))
851       I_look_alive = 1;
852     else if (stackp > 2 && owl_escape_route(owla) >= 5) {
853       live_reasona = "escaped";
854       I_look_alive = 1;
855     }
856 
857     if (owl_estimate_life(owlb, owla, vital_offensive_moves,
858 			  &live_reasonb, 1, &probable_eyes_b,
859 			  &eyemin_b, &eyemax_b))
860       you_look_alive = 1;
861     else if (stackp > 2 && owl_escape_route(owlb) >= 5) {
862       live_reasonb = "escaped";
863       you_look_alive = 1;
864     }
865 
866     if (verbose) {
867       gprintf("probable_eyes_a: %s eyemin: %d eyemax: %d",
868 	      eyevalue_to_string(&probable_eyes_a), eyemin_a, eyemax_a);
869       if (I_look_alive)
870 	gprintf("%o I look alive (%s)", live_reasona);
871       gprintf("%o\n");
872       gprintf("probable_eyes_b: %s eyemin: %d eyemax: %d",
873 	      eyevalue_to_string(&probable_eyes_b), eyemin_b, eyemax_b);
874       if (you_look_alive)
875 	gprintf("%o you look alive(%s)", live_reasonb);
876       gprintf("%o\n");
877     }
878 
879     /* Stop here if both look certain to live. */
880     if (I_look_alive && you_look_alive) {
881       *resulta = WIN;
882       *resultb = 0;
883       *move = PASS_MOVE;
884       sgf_dumptree = save_sgf_dumptree;
885       count_variations = save_count_variations;
886       TRACE("Both live\n");
887       SGFTRACE_SEMEAI(PASS_MOVE, WIN, 0, "Both live");
888       READ_RETURN_SEMEAI(SEMEAI, apos, bpos, depth - stackp,
889 			 move, PASS_MOVE, WIN, 0);
890     }
891 
892     /* Next the shape moves. */
893     if (!I_look_alive) {
894       owl_shapes(&shape_defensive_patterns, shape_defensive_moves, color,
895 		 owla, &owl_defendpat_db);
896       for (k = 0; k < MAX_MOVES-1; k++)
897 	if (!get_next_move_from_list(&shape_defensive_patterns, color,
898 				     shape_defensive_moves, 1, owla))
899 	  break;
900     }
901     else
902       shape_defensive_moves[0].pos = NO_MOVE;
903 
904     if (!you_look_alive) {
905       owl_shapes(&shape_offensive_patterns, shape_offensive_moves, color,
906 		 owlb, &owl_attackpat_db);
907       for (k = 0; k < MAX_MOVES-1; k++)
908 	if (!get_next_move_from_list(&shape_offensive_patterns, color,
909 				     shape_offensive_moves, 1, owlb))
910 	  break;
911     }
912     else
913       shape_offensive_moves[0].pos = NO_MOVE;
914 
915     /* Filter out moves, which fill our eye (and not split it). */
916     if (eyemax_a > 0) {
917       remove_eye_filling_moves(owla, vital_defensive_moves);
918       remove_eye_filling_moves(owla, vital_offensive_moves);
919       remove_eye_filling_moves(owla, shape_defensive_moves);
920       remove_eye_filling_moves(owla, shape_offensive_moves);
921     }
922 
923     /* Now we review the moves already considered, while collecting
924      * them into a single list.
925      */
926 
927     if (!I_look_alive) {
928       semeai_review_owl_moves(vital_defensive_moves, owla, owlb, color,
929 			      &safe_outside_liberty_found,
930 			      &safe_common_liberty_found,
931 			      &riskless_move_found,
932 			      mw, moves, 0, 30,
933 			      critical_semeai_worms);
934 
935       semeai_review_owl_moves(shape_defensive_moves, owla, owlb, color,
936 			      &safe_outside_liberty_found,
937 			      &safe_common_liberty_found,
938 			      &riskless_move_found,
939 			      mw, moves, 0, 0,
940 			      critical_semeai_worms);
941     }
942 
943     if (!you_look_alive) {
944       semeai_review_owl_moves(vital_offensive_moves, owla, owlb, color,
945 			      &safe_outside_liberty_found,
946 			      &safe_common_liberty_found,
947 			      &riskless_move_found,
948 			      mw, moves, 1, 30,
949 			      critical_semeai_worms);
950 
951       semeai_review_owl_moves(shape_offensive_moves, owla, owlb, color,
952 			      &safe_outside_liberty_found,
953 			      &safe_common_liberty_found,
954 			      &riskless_move_found,
955 			      mw, moves, 1, 0,
956 			      critical_semeai_worms);
957     }
958 
959     /* If no moves were found so far, also check the eyespaces when
960      * opponent semeai worms are allowed to be included for vital
961      * moves.
962      */
963     if (moves[0].pos == NO_MOVE || we_might_be_inessential) {
964       include_semeai_worms_in_eyespace = 1;
965       if (!owl_estimate_life(owlb, owla, vital_offensive_moves,
966 			     &live_reasonb, 1, &dummy_eyes,
967 			     &eyemin_b, &eyemax_b))
968 	semeai_review_owl_moves(vital_offensive_moves, owla, owlb, color,
969 				&safe_outside_liberty_found,
970 				&safe_common_liberty_found,
971 				&riskless_move_found,
972 				mw, moves, 1, 30,
973 				critical_semeai_worms);
974       include_semeai_worms_in_eyespace = 0;
975     }
976 
977     if (eyemin_a == eyemax_a)
978       /* We have stable number of eyes, so we can try to reduce
979        * opponent eyes.
980        */
981       I_have_more_eyes = (eyemin_a > min_eyes(&probable_eyes_b));
982     else {
983       if (min_eyes(&probable_eyes_a) == max_eyes(&probable_eyes_a))
984         /* If we can't increase our number of eyes, we try to reduce
985 	 * opponent eyes.
986 	 */
987         I_have_more_eyes = (max_eyes(&probable_eyes_a) > min_eyes(&probable_eyes_b));
988       else
989         /* If we can increase our number of eyes, we do it and let
990 	 * opponent to increase his.
991 	 */
992         I_have_more_eyes = (max_eyes(&probable_eyes_a) > max_eyes(&probable_eyes_b));
993     }
994 
995     if (get_level() < 8) {
996       /* If no owl moves were found on two consecutive moves,
997        * turn off the owl phase.
998        */
999       if (moves[0].pos == NO_MOVE) {
1000 	if (owl_phase == 1)
1001 	  owl_phase = 2;
1002 	else if (owl_phase == 2)
1003 	  owl_phase = 0;
1004       }
1005       else
1006 	owl_phase = 1;
1007     }
1008   }
1009 
1010   if (1 && verbose) {
1011     showboard(0);
1012     goaldump(owla->goal);
1013     goaldump(owlb->goal);
1014   }
1015 
1016   /* Now we look for a move to fill a liberty. This is only
1017    * interesting if the opponent doesn't already have two eyes.
1018    * If we have more eyes, always check for a backfilling move.
1019    */
1020   if (!you_look_alive
1021       && !safe_outside_liberty_found
1022       && (moves[0].value < 110 || I_have_more_eyes)) {
1023     int pos;
1024     for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
1025       if (!ON_BOARD(pos))
1026 	continue;
1027 
1028       if (board[pos] == EMPTY && !mw[pos]) {
1029 	if (liberty_of_goal(pos, owlb)) {
1030 	  if (!liberty_of_goal(pos, owla)) {
1031 	    /* outside liberty */
1032 	    if (safe_move(pos, color) == WIN) {
1033 	      safe_outside_liberty_found = 1;
1034 	      outside_liberty.pos = pos;
1035 	      break;
1036 	    }
1037 	    else if (backfill_outside_liberty.pos == NO_MOVE)
1038 	      backfill_outside_liberty.pos = find_semeai_backfilling_move(bpos,
1039 									  pos);
1040 	  }
1041 	  else {
1042 	    /* common liberty */
1043 	    if (safe_move(pos, color) == WIN) {
1044 	      safe_common_liberty_found = 1;
1045 	      common_liberty.pos = pos;
1046 	    }
1047 	    else if (backfill_common_liberty.pos == NO_MOVE)
1048 	      backfill_common_liberty.pos = find_semeai_backfilling_move(bpos,
1049 									 pos);
1050 	  }
1051 	}
1052       }
1053     }
1054   }
1055 
1056   /* Add the best liberty filling move available. We first want to
1057    * play outer liberties, second backfilling moves required before
1058    * filling an outer liberty. If no such moves are available we try
1059    * to fill a mutual liberty or play a corresponding backfilling
1060    * move.
1061    */
1062   if (!you_look_alive) {
1063     if (safe_outside_liberty_found
1064 	&& outside_liberty.pos != NO_MOVE) {
1065       move_value = semeai_move_value(outside_liberty.pos,
1066 				     owla, owlb, 50,
1067 				     critical_semeai_worms);
1068       owl_add_move(moves, outside_liberty.pos, move_value,
1069 		   "safe outside liberty", SAME_DRAGON_NOT_CONNECTED,
1070 		   NO_MOVE, 0, NO_MOVE, MAX_SEMEAI_MOVES, NULL);
1071       riskless_move_found = 1;
1072       TRACE("Added %1m %d (5)\n", outside_liberty.pos, move_value);
1073     }
1074     else if (backfill_outside_liberty.pos != NO_MOVE) {
1075       move_value = semeai_move_value(backfill_outside_liberty.pos,
1076 				     owla, owlb, 50,
1077 				     critical_semeai_worms);
1078       owl_add_move(moves, backfill_outside_liberty.pos, move_value,
1079 		   "backfilling move", SAME_DRAGON_NOT_CONNECTED, NO_MOVE, 0,
1080 		   NO_MOVE, MAX_SEMEAI_MOVES, NULL);
1081       riskless_move_found = 1;
1082       TRACE("Added %1m %d (6)\n", backfill_outside_liberty.pos, move_value);
1083     }
1084     else if (safe_common_liberty_found
1085 	     && common_liberty.pos != NO_MOVE) {
1086       move_value = semeai_move_value(common_liberty.pos,
1087 				     owla, owlb, 10,
1088 				     critical_semeai_worms);
1089       owl_add_move(moves, common_liberty.pos, move_value,
1090 		   "safe common liberty", SAME_DRAGON_MAYBE_CONNECTED,
1091 		   NO_MOVE, 0, NO_MOVE, MAX_SEMEAI_MOVES, NULL);
1092       if (semeai_is_riskless_move(common_liberty.pos, owla))
1093 	riskless_move_found = 1;
1094       TRACE("Added %1m %d (7)\n", common_liberty.pos, move_value);
1095     }
1096     else if (backfill_common_liberty.pos != NO_MOVE) {
1097       move_value = semeai_move_value(backfill_common_liberty.pos,
1098 				     owla, owlb, 10,
1099 				     critical_semeai_worms);
1100       owl_add_move(moves, backfill_common_liberty.pos, move_value,
1101 		   "backfilling move", SAME_DRAGON_NOT_CONNECTED, NO_MOVE, 0,
1102 		   NO_MOVE, MAX_SEMEAI_MOVES, NULL);
1103       if (semeai_is_riskless_move(backfill_common_liberty.pos, owla))
1104 	riskless_move_found = 1;
1105       TRACE("Added %1m %d (6)\n", backfill_common_liberty.pos, move_value);
1106     }
1107   }
1108 
1109   if (moves[0].pos == NO_MOVE) {
1110     /* If no move has been found yet, see if we can fill opponent's
1111      * eye (i.e. put more stones in "bulky five" shape).
1112      */
1113     if (min_eyes(&probable_eyes_b) == 1) {
1114       int move = semeai_propose_eyespace_filling_move(owla, owlb);
1115 
1116       if (move) {
1117 	owl_add_move(moves, move, 70, "eyespace filling",
1118 		     SAME_DRAGON_NOT_CONNECTED, NO_MOVE,
1119 	    	     0, NO_MOVE, MAX_SEMEAI_MOVES, NULL);
1120       }
1121     }
1122 
1123     if (moves[0].pos == NO_MOVE)
1124       TRACE("No move found\n");
1125   }
1126 
1127   /* Now we are ready to try moves. Turn on the sgf output ... */
1128   sgf_dumptree = save_sgf_dumptree;
1129   count_variations = save_count_variations;
1130   tested_moves = 0;
1131   for (k = 0; k < MAX_SEMEAI_MOVES; k++) {
1132     int mpos = moves[k].pos;
1133     if (mpos == NO_MOVE)
1134       break;
1135 
1136     if (moves[k].value == 0)
1137       continue;
1138 
1139     /* Do not try too many moves. */
1140     if (tested_moves > 2
1141 	|| (stackp > semeai_branch_depth2 && tested_moves > 1)
1142 	|| (stackp > semeai_branch_depth && tested_moves > 0)) {
1143       /* If allpats, try and pop to get the move in the sgf record. */
1144       if (!allpats)
1145 	break;
1146       else if (trymove(mpos, color, moves[k].name, apos)) {
1147 	semeai_add_sgf_comment(moves[k].value, owl_phase);
1148 	popgo();
1149       }
1150       continue;
1151     }
1152 
1153     if (count_variations >= semeai_node_limit
1154 	|| stackp >= MAX_SEMEAI_DEPTH)
1155       continue;
1156 
1157     /* Try playing the move at mpos and call ourselves recursively to
1158      * determine the result obtained by this move.
1159      */
1160     if (semeai_trymove_and_recurse(apos, bpos, owla, owlb,
1161 				   owl_phase, mpos, color,
1162 				   best_resulta == 0 || best_resultb == 0,
1163 				   moves[k].value, moves[k].name,
1164 				   moves[k].same_dragon, moves[k].pattern_data,
1165 				   moves[k].lunch, NULL,
1166 				   &this_resulta, &this_resultb)) {
1167       tested_moves++;
1168       if (this_resultb == WIN && this_resulta == WIN) {
1169 	/* Ideal result, no need to try any more moves. */
1170 	*resulta = WIN;
1171 	*resultb = WIN;
1172 	*move = mpos;
1173 	TRACE("After %1m I (%C) am alive, you are dead\n", mpos, color);
1174 	SGFTRACE_SEMEAI(mpos, WIN, WIN, moves[k].name);
1175 	close_pattern_list(color, &shape_defensive_patterns);
1176 	close_pattern_list(color, &shape_offensive_patterns);
1177 	READ_RETURN_SEMEAI(SEMEAI, apos, bpos, depth - stackp,
1178 			   move, mpos, WIN, WIN);
1179       }
1180       /* When there is a choice between ko and seki, the prefer_ko
1181        * variable decides policy. Thus if prefer_ko == color we
1182        * consider attacking the opponent more important than defending
1183        * our dragon, and vise versa otherwise.
1184        */
1185       else if ((prefer_ko != color
1186 		&& (this_resulta > best_resulta
1187 		    || (this_resulta == best_resulta
1188 			&& this_resultb > best_resultb)))
1189 	       || (prefer_ko == color
1190 		   && (this_resultb > best_resultb
1191 		       || (this_resultb == best_resultb
1192 			   && this_resulta > best_resulta)))) {
1193 	best_resulta = this_resulta;
1194 	best_resultb = this_resultb;
1195 	best_move = mpos;
1196 	best_move_name = moves[k].name;
1197       }
1198     }
1199   }
1200 
1201   close_pattern_list(color, &shape_defensive_patterns);
1202   close_pattern_list(color, &shape_offensive_patterns);
1203 
1204   /* If we can't find a move and the opponent looks alive, we have
1205    * lost.
1206    */
1207   if (best_resulta == 0 && best_resultb == 0 && you_look_alive) {
1208     *resulta = 0;
1209     *resultb = 0;
1210     *move = PASS_MOVE;
1211     SGFTRACE_SEMEAI(PASS_MOVE, 0, 0, "You live, I die");
1212     READ_RETURN_SEMEAI(SEMEAI, apos, bpos, depth - stackp,
1213 		       move, PASS_MOVE, 0, 0);
1214   }
1215 
1216   /* If we didn't find a working move and we look dead even if including the
1217    * opponent stones in our eyespace, we have lost.
1218    */
1219   if (best_resulta == 0 && best_resultb == 0
1220       && !riskless_move_found) {
1221     const char *live_reasona;
1222     int eyemin_a;
1223     int eyemax_a;
1224     for (sworm = 0; sworm < s_worms; sworm++) {
1225       if (board[semeai_worms[sworm]] == other) {
1226 	if (important_semeai_worms[sworm])
1227 	  break;
1228       }
1229     }
1230 
1231     if (sworm == s_worms) {
1232       include_semeai_worms_in_eyespace = 1;
1233       if (!owl_estimate_life(owla, owlb, vital_defensive_moves,
1234 			     &live_reasona, 0, &dummy_eyes,
1235 			     &eyemin_a, &eyemax_a)
1236 	  && eyemax_a < 2) {
1237 	include_semeai_worms_in_eyespace = 0;
1238 	*resulta = 0;
1239 	*resultb = 0;
1240 	*move = PASS_MOVE;
1241 	SGFTRACE_SEMEAI(PASS_MOVE, 0, 0, "You live, I die - 2");
1242 	READ_RETURN_SEMEAI(SEMEAI, apos, bpos, depth - stackp,
1243 			   move, PASS_MOVE, 0, 0);
1244       }
1245       include_semeai_worms_in_eyespace = 0;
1246     }
1247   }
1248 
1249   /* If we can't find a useful move and opponent passed, it's seki, unless
1250    * one dragon has more eyes than the other.
1251    */
1252   if (best_resulta == 0 && best_resultb == 0
1253       && !riskless_move_found) {
1254     if (pass) {
1255       if (max_eyes(&probable_eyes_a) < min_eyes(&probable_eyes_b)) {
1256 	*resulta = 0;
1257 	*resultb = 0;
1258 	*move = PASS_MOVE;
1259 	TRACE("You have more eyes.\n");
1260 	SGFTRACE_SEMEAI(PASS_MOVE, 0, 0, "You have more eyes");
1261 	READ_RETURN_SEMEAI(SEMEAI, apos, bpos, depth - stackp,
1262 			   move, PASS_MOVE, 0, 0);
1263       }
1264       else if (max_eyes(&probable_eyes_b) < min_eyes(&probable_eyes_a)) {
1265 	*resulta = WIN;
1266 	*resultb = WIN;
1267 	*move = PASS_MOVE;
1268 	TRACE("I have more eyes\n");
1269 	SGFTRACE_SEMEAI(PASS_MOVE, WIN, WIN, "I have more eyes");
1270 	READ_RETURN_SEMEAI(SEMEAI, apos, bpos, depth - stackp,
1271 			   move, PASS_MOVE, WIN, WIN);
1272       }
1273       else {
1274 	*resulta = WIN;
1275 	*resultb = 0;
1276 	*move = PASS_MOVE;
1277 	TRACE("Seki\n");
1278 	SGFTRACE_SEMEAI(PASS_MOVE, WIN, 0, "Seki");
1279 	READ_RETURN_SEMEAI(SEMEAI, apos, bpos, depth - stackp,
1280 			   move, PASS_MOVE, WIN, 0);
1281       }
1282     }
1283     else {
1284     /* No working move was found, but opponent hasn't passed. Then we pass. */
1285       do_owl_analyze_semeai(bpos, apos, owlb, owla,
1286 			    resultb, resulta, NULL, 1, owl_phase);
1287       *resulta = REVERSE_RESULT(*resulta);
1288       *resultb = REVERSE_RESULT(*resultb);
1289       TRACE("No move found\n");
1290       SGFTRACE_SEMEAI(PASS_MOVE, *resulta, *resultb, "No move found");
1291       *move = PASS_MOVE;
1292       READ_RETURN_SEMEAI(SEMEAI, apos, bpos, depth - stackp,
1293 			 move, PASS_MOVE, *resulta, *resultb);
1294     }
1295   }
1296 
1297   /* There are a few selected cases where we should try to see if it
1298    * would be better to pass rather than playing any move in the semeai.
1299    *
1300    * A first simple example is the case of positions where there is nothing
1301    * left to play but common liberties. In case the above analysis concluded
1302    * the result is seki and if the best (and only) move happens to be a
1303    * common liberty, we attempt to pass, so that the engine considers tenuki
1304    * as a viable option in case it actually is.
1305    *
1306    * Another example is related to "disturbing" kos.
1307    *
1308    * .OOOOOOOO.  In this position (similar to semeai:130), X has just taken
1309    * OOXXXXXXOO  the ko on the left. The semeai code finds the ko recapture
1310    * OX.XXOOXXO  as the only attacking move and concludes the result is KO_B.
1311    * OOXX.OO.XO
1312    * ----------
1313    *
1314    * In such cases too, we try to pass to see if it doesn't actually yield
1315    * a better result.
1316    *
1317    * FIXME: there might be more cases where passing would be valuable.
1318    */
1319   if (!pass && k == 1) {
1320     if ((best_resulta == WIN && best_resultb == 0
1321 	 && best_move != NO_MOVE
1322 	 && best_move == common_liberty.pos)
1323 	|| (best_resulta == KO_B && best_resultb == KO_B
1324 	    && is_ko(best_move, owla->color, NULL))) {
1325       do_owl_analyze_semeai(bpos, apos, owlb, owla, &this_resultb,
1326 			    &this_resulta, NULL, 1, owl_phase);
1327       if (REVERSE_RESULT(this_resulta) >= best_resulta
1328 	  && REVERSE_RESULT(this_resultb) >= best_resultb) {
1329 	best_move = PASS_MOVE;
1330 	best_resulta = REVERSE_RESULT(this_resulta);
1331 	best_resultb = REVERSE_RESULT(this_resultb);
1332 	best_move_name = "Pass";
1333       }
1334     }
1335   }
1336 
1337   *resulta = best_resulta;
1338   *resultb = best_resultb;
1339   if (best_resulta == 0)
1340     best_move = PASS_MOVE;
1341   *move = best_move;
1342   SGFTRACE_SEMEAI(best_move, best_resulta, best_resultb, best_move_name);
1343   READ_RETURN_SEMEAI(SEMEAI, apos, bpos, depth - stackp,
1344 		     move, best_move, best_resulta, best_resultb);
1345 }
1346 
1347 /* Play a move, update goal and boundaries appropriately, and call
1348  * do_owl_analyze_semeai() recursively to determine the result of this
1349  * move.
1350  */
1351 static int
semeai_trymove_and_recurse(int apos,int bpos,struct local_owl_data * owla,struct local_owl_data * owlb,int owl_phase,int move,int color,int ko_allowed,int move_value,const char * move_name,enum same_dragon_value same_dragon,struct matched_pattern_data * pattern_data,int lunch,int * semeai_move,int * this_resulta,int * this_resultb)1352 semeai_trymove_and_recurse(int apos, int bpos, struct local_owl_data *owla,
1353 			   struct local_owl_data *owlb,
1354 			   int owl_phase,
1355 			   int move, int color, int ko_allowed,
1356 			   int move_value, const char *move_name,
1357 			   enum same_dragon_value same_dragon,
1358 			   struct matched_pattern_data *pattern_data,
1359 			   int lunch, int *semeai_move,
1360 			   int *this_resulta, int *this_resultb)
1361 {
1362   int ko_move = 0;
1363 
1364   gg_assert(this_resulta != NULL && this_resultb != NULL);
1365   *this_resulta = 0;
1366   *this_resultb = 0;
1367 
1368   if (!komaster_trymove(move, color, move_name, apos, &ko_move, ko_allowed)) {
1369     int kpos;
1370     if (is_ko(move, color, &kpos)) {
1371       /* Move was not allowed because of komaster. We want to check
1372        * if this situation is double ko and when it is, we won semeai.
1373        */
1374       int libs[MAX_LIBERTIES];
1375       int n;
1376       int nlib;
1377       int sworm;
1378       int worm_color;
1379       int other = OTHER_COLOR(color);
1380 
1381       for (sworm = 0; sworm < s_worms; sworm++) {
1382 	worm_color = board[semeai_worms[sworm]];
1383 	if (worm_color == color) {
1384 	  /* We only check up to MAX_LIBERTIES, due to performance
1385 	   * reasons. When we have more liberties we have some outside
1386 	   * liberties to fill and these moves will be tried later
1387 	   * (and double ko situation will be found).
1388 	   */
1389 	  nlib = findlib(semeai_worms[sworm], MAX_LIBERTIES, libs);
1390 	  if (nlib > MAX_LIBERTIES)
1391 	    return 0;
1392 
1393 	  for (n = 0; n < nlib; n++)
1394 	    if (is_ko(libs[n], other, NULL)) {
1395 	      /* Check if situation is not a nested ko capture. */
1396 	      if (DIAGONAL_NEIGHBORS(libs[n], kpos))
1397 	        return 0;
1398 
1399 	      /* Our dragon has double ko, but we have to check if
1400 	       * opponent dragon doesn't have outside liberties or
1401 	       * double ko.
1402 	       */
1403 	      *this_resulta = WIN;
1404 	      *this_resultb = WIN;
1405 	    }
1406 	}
1407 	else if (worm_color == other) {
1408 	  if (countlib(semeai_worms[sworm]) > 2)
1409 	    /* In double ko situation the opponent can have only a
1410 	     * single eye and a ko outside liberty to be sure that we
1411 	     * will always win double ko.
1412 	     */
1413 	    return 0;
1414 	}
1415       }
1416       if (*this_resulta == WIN)
1417 	return 1;
1418     }
1419 
1420     return 0;
1421   }
1422 
1423   semeai_add_sgf_comment(move_value, owl_phase);
1424   TRACE("Trying %C %1m. Current stack: ", color, move);
1425   if (verbose) {
1426     dump_stack();
1427     goaldump(owla->goal);
1428     gprintf("\n");
1429     goaldump(owlb->goal);
1430     gprintf("\n");
1431   }
1432   TRACE("%s, value %d, same_dragon %d\n", move_name, move_value, same_dragon);
1433 
1434   push_owl(&owla);
1435   push_owl(&owlb);
1436 
1437   if (owla->color == color) {
1438     owl_update_goal(move, same_dragon, lunch, owla, 1, pattern_data);
1439     owl_update_boundary_marks(move, owlb);
1440   }
1441   else {
1442     owl_update_goal(move, same_dragon, lunch, owlb, 1, pattern_data);
1443     owl_update_boundary_marks(move, owla);
1444   }
1445   mark_goal_in_sgf(owla->goal);
1446   mark_goal_in_sgf(owlb->goal);
1447 
1448   /* Do a recursive call to read the semeai after the move we just
1449    * tried. If dragon b was captured by the move, call
1450    * do_owl_attack() to see whether it sufficed for us to live.
1451    */
1452   if (board[bpos] == EMPTY) {
1453     /* FIXME: Are all owl_data fields and relevant static
1454      * variables properly set up for a call to do_owl_attack()?
1455      */
1456     *this_resulta = REVERSE_RESULT(do_owl_attack(apos, semeai_move, NULL, owla, 0));
1457     *this_resultb = *this_resulta;
1458   }
1459   else {
1460     do_owl_analyze_semeai(bpos, apos, owlb, owla,
1461 			  this_resultb, this_resulta, semeai_move,
1462 			  0, owl_phase);
1463     *this_resulta = REVERSE_RESULT(*this_resulta);
1464     *this_resultb = REVERSE_RESULT(*this_resultb);
1465   }
1466 
1467   pop_owl(&owlb);
1468   pop_owl(&owla);
1469 
1470   popgo();
1471 
1472   /* Does success require ko? */
1473   if (ko_move) {
1474     if (*this_resulta != 0)
1475       *this_resulta = KO_B;
1476     if (*this_resultb != 0)
1477       *this_resultb = KO_B;
1478   }
1479 
1480   if (count_variations >= semeai_node_limit) {
1481     TRACE("Out of nodes, claiming win.\n");
1482     result_certain = 0;
1483     *this_resulta = WIN;
1484     *this_resultb = WIN;
1485   }
1486   return 1;
1487 }
1488 
1489 /* Add details in sgf file about move value and whether owl_phase is active. */
1490 static void
semeai_add_sgf_comment(int value,int owl_phase)1491 semeai_add_sgf_comment(int value, int owl_phase)
1492 {
1493   char buf[100];
1494 
1495   if (!sgf_dumptree)
1496     return;
1497 
1498   if (owl_phase)
1499     gg_snprintf(buf, 100, "value %d, owl_phase", value);
1500   else
1501     gg_snprintf(buf, 100, "value %d", value);
1502   sgftreeAddComment(sgf_dumptree, buf);
1503 }
1504 
1505 
1506 /* In semeai situations tactical attacks often cannot be trusted. This
1507  * in particular holds for strings with three or more liberties. Two
1508  * liberties can usually be trusted, but if neither liberty can be
1509  * played immediately, the need for backfilling moves gives an
1510  * effective liberty count of more than two, again making the attack
1511  * untrustworthy.
1512  *
1513  * This function decides whether an attack should be trusted. It does
1514  * not check whether there actually is an attack, though.
1515  */
1516 static int
semeai_trust_tactical_attack(int str)1517 semeai_trust_tactical_attack(int str)
1518 {
1519   int liberties;
1520   int libs[3];
1521   int other = OTHER_COLOR(board[str]);
1522 
1523   liberties = findlib(str, 3, libs);
1524   if (liberties > 2)
1525     return 0;
1526 
1527   if (liberties < 2)
1528     return 1;
1529 
1530   if (!is_self_atari(libs[0], other)
1531       || !is_self_atari(libs[1], other))
1532     return 1;
1533 
1534   return 0;
1535 }
1536 
1537 
1538 /* A move is deemed riskless (i.e., doesn't kill ourself in a seki situation)
1539  * if it doesn't decrease the liberty count of any goal string of our
1540  * dragon.
1541  */
1542 static int
semeai_is_riskless_move(int move,struct local_owl_data * owla)1543 semeai_is_riskless_move(int move, struct local_owl_data *owla)
1544 {
1545   int k;
1546   int liberties = accuratelib(move, owla->color, MAXLIBS, NULL);
1547   if (!liberty_of_goal(move, owla))
1548     return 1;
1549   for (k = 0; k < 4; k++) {
1550     int pos = move + delta[k];
1551     if (board[pos] == owla->color
1552 	&& owla->goal[pos]
1553 	&& countlib(pos) > liberties)
1554       return 0;
1555   }
1556   return 1;
1557 }
1558 
1559 
1560 /* Review the moves in owl_moves[] and add them into semeai_moves[].
1561  * This is used to merge multiple sets of owl moves into one move
1562  * list, while revising the values for use in semeai reading.
1563  *
1564  * We also record whether the moves include an outer or common liberty
1565  * in the semeai.
1566  */
1567 static void
semeai_review_owl_moves(struct owl_move_data owl_moves[MAX_MOVES],struct local_owl_data * owla,struct local_owl_data * owlb,int color,int * safe_outside_liberty_found,int * safe_common_liberty_found,int * riskless_move_found,signed char mw[BOARDMAX],struct owl_move_data semeai_moves[MAX_SEMEAI_MOVES],int guess_same_dragon,int value_bonus,int * critical_semeai_worms)1568 semeai_review_owl_moves(struct owl_move_data owl_moves[MAX_MOVES],
1569 			struct local_owl_data *owla,
1570 			struct local_owl_data *owlb, int color,
1571 			int *safe_outside_liberty_found,
1572 			int *safe_common_liberty_found,
1573 			int *riskless_move_found,
1574 			signed char mw[BOARDMAX],
1575 			struct owl_move_data semeai_moves[MAX_SEMEAI_MOVES],
1576 			int guess_same_dragon, int value_bonus,
1577 			int *critical_semeai_worms)
1578 {
1579   int move;
1580   int move_value;
1581   enum same_dragon_value same_dragon;
1582   struct matched_pattern_data *pattern_data = NULL;
1583   int k;
1584 
1585   for (k = 0; k < MAX_MOVES-1; k++) {
1586     move = owl_moves[k].pos;
1587     if (move == NO_MOVE)
1588       break;
1589 
1590     if (owl_moves[k].value == 0)
1591       continue;
1592 
1593     /* Does the move fill a liberty in the semeai? */
1594     if (liberty_of_goal(move, owlb)
1595 	&& safe_move(move, color)) {
1596       if (!liberty_of_goal(move, owla))
1597 	*safe_outside_liberty_found = 1;
1598       else
1599 	*safe_common_liberty_found = 1;
1600     }
1601     if (is_legal(move, color) && !is_ko(move, color, NULL)
1602 	&& semeai_is_riskless_move(move, owla))
1603       *riskless_move_found = 1;
1604 
1605     /* For some types of owl moves we don't have same_dragon
1606      * information recorded and need to guess.
1607      */
1608     if (guess_same_dragon) {
1609       if (liberty_of_goal(move, owla)
1610 	  || second_liberty_of_goal(move, owla))
1611 	same_dragon = SAME_DRAGON_MAYBE_CONNECTED;
1612       else
1613 	same_dragon = SAME_DRAGON_NOT_CONNECTED;
1614     }
1615     else {
1616       same_dragon = owl_moves[k].same_dragon;
1617       pattern_data = owl_moves[k].pattern_data;
1618     }
1619 
1620     mw[move] = 1;
1621     move_value = (semeai_move_value(move, owla, owlb, owl_moves[k].value,
1622 				    critical_semeai_worms)
1623 		  + value_bonus);
1624     owl_add_move(semeai_moves, move, move_value, owl_moves[k].name,
1625 		 same_dragon, NO_MOVE, owl_moves[k].escape,
1626 		 NO_MOVE, MAX_SEMEAI_MOVES, pattern_data);
1627     TRACE("Added %1m %d\n", move, move_value);
1628   }
1629 }
1630 
1631 
1632 /* Propose an eyespace filling move.  Such a move can, for instance,
1633  * add a stone to opponent's "bulky five" shape.  We of course choose
1634  * a move that doesn't allow opponent to turn his dead eyeshape into a
1635  * two eyes eyeshape.  E.g. in this position, the function will
1636  * propose the move at '*', not at the '.':
1637  *
1638  *	 XXX
1639  *	XXOX
1640  *	XOOX
1641  *	X.*X
1642  *	----
1643  */
1644 static int
semeai_propose_eyespace_filling_move(struct local_owl_data * owla,struct local_owl_data * owlb)1645 semeai_propose_eyespace_filling_move(struct local_owl_data *owla,
1646 				     struct local_owl_data *owlb)
1647 {
1648   int color = OTHER_COLOR(owlb->color);
1649   int pos;
1650   int mw[BOARDMAX];
1651   int mz[BOARDMAX];
1652 
1653   owl_find_relevant_eyespaces(owlb, mw, mz);
1654 
1655   /* Never try to fill opponent's eyes which contain our dragon.  This
1656    * is nothing else than suicide.
1657    */
1658   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
1659     if (ON_BOARD(pos) && owla->goal[pos])
1660       mw[owlb->my_eye[pos].origin] = 0;
1661   }
1662 
1663   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
1664     if (board[pos] == EMPTY) {
1665       int origin = owlb->my_eye[pos].origin;
1666 
1667       if (mw[origin] > 1
1668 	  && min_eyes(&owlb->my_eye[origin].value) == 1) {
1669 	int good_move = 0;
1670 
1671 	if (trymove(pos, color, "eyespace_filling", NO_MOVE)) {
1672 	  struct eyevalue new_value;
1673 	  int dummy_attack;
1674 	  int dummy_defense;
1675 
1676 	  compute_eyes(origin, &new_value, &dummy_attack, &dummy_defense,
1677 		       owlb->my_eye, owlb->half_eye, 0);
1678 	  if (max_eyes(&new_value) <= 1)
1679 	    good_move = 1;
1680 
1681 	  popgo();
1682 	}
1683 
1684 	if (good_move)
1685 	  return pos;
1686       }
1687     }
1688   }
1689 
1690   return NO_MOVE;
1691 }
1692 
1693 
1694 /* Try to estimate the value of a semeai move. This has two
1695  * components. The first is the change in the total number of
1696  * liberties for strings involved in the semeai. The second is a bonus
1697  * for attacks and defenses of critical semeai worms.
1698  */
1699 
1700 static int
semeai_move_value(int move,struct local_owl_data * owla,struct local_owl_data * owlb,int raw_value,int * critical_semeai_worms)1701 semeai_move_value(int move, struct local_owl_data *owla,
1702 		  struct local_owl_data *owlb,
1703 		  int raw_value, int *critical_semeai_worms)
1704 {
1705   int pos;
1706   int net = 0;
1707   int color = owla->color;
1708   int save_verbose = verbose;
1709   int k;
1710   int bonus = 0;
1711 
1712   ASSERT1(board[move] == EMPTY, move);
1713   verbose = 0;
1714   if (safe_move(move, color)) {
1715     for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
1716       if (IS_STONE(board[pos])
1717 	  && pos == find_origin(pos)) {
1718 	int count_lib = -1;
1719 	if (owla->goal[pos]) {
1720 	  count_lib = countlib(pos);
1721 	  net -= 75 * count_lib;
1722 	}
1723 	if (owlb->goal[pos]) {
1724 	  if (count_lib < 0)
1725 	    count_lib = countlib(pos);
1726 	  net += 100 * count_lib;
1727 	}
1728       }
1729     }
1730     if (!trymove(move, color, NULL, 0)) {
1731       verbose = save_verbose;
1732       return 0;
1733     }
1734     for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
1735       if (IS_STONE(board[pos])
1736 	  && pos == find_origin(pos)) {
1737 	int count_lib = -1;
1738 	if (owla->goal[pos]
1739 	    || (pos == move && liberty_of_goal(move, owla))) {
1740 	  count_lib = countlib(pos);
1741 	  net += 75 * count_lib;
1742 	}
1743 	if (owlb->goal[pos]) {
1744 	  if (count_lib < 0)
1745 	    count_lib = countlib(pos);
1746 	  net -= 100 * count_lib;
1747 	}
1748       }
1749     }
1750 
1751     increase_depth_values();
1752     for (k = 0; k < s_worms; k++) {
1753       if (!critical_semeai_worms[k])
1754 	continue;
1755       if (board[semeai_worms[k]] == color
1756 	  && !attack(semeai_worms[k], NULL))
1757 	bonus += 50;
1758       else if (board[semeai_worms[k]] == OTHER_COLOR(color)
1759 	       && !find_defense(semeai_worms[k], NULL))
1760 	bonus += 50;
1761     }
1762     decrease_depth_values();
1763 
1764     popgo();
1765   }
1766 
1767   verbose = save_verbose;
1768 
1769   if (net < 0)
1770     net = 0;
1771 
1772   net /= 25;
1773   net *= 3;
1774 
1775   return raw_value + net + bonus;
1776 }
1777 
1778 
1779 /* Remove all moves from the list that would fill our own eye. */
1780 static void
remove_eye_filling_moves(struct local_owl_data * our_owl,struct owl_move_data * moves)1781 remove_eye_filling_moves(struct local_owl_data *our_owl,
1782 			 struct owl_move_data *moves)
1783 {
1784   int k;
1785   int color = our_owl->color;
1786 
1787   for (k = 0; k < MAX_MOVES; k++) {
1788     if (moves[k].pos == NO_MOVE)
1789       break;
1790     else {
1791       struct eye_data *eye = &our_owl->my_eye[moves[k].pos];
1792 
1793       /* If esize==1 this eye must not be a real eye (at least one
1794        * worm is capturable, otherwise this move would not be
1795        * proposed).
1796        */
1797       if (eye->color == color && eye->msize == 0 && eye->neighbors <= 1
1798 	  && eye->esize != 1
1799 	  && our_owl->half_eye[moves[k].pos].type != HALF_EYE
1800 	  && !has_neighbor(moves[k].pos, OTHER_COLOR(color)))
1801 	moves[k].value = 0;
1802     }
1803   }
1804 }
1805 
1806 /* Is the vertex at pos adjacent to an element of the owl goal? */
1807 static int
liberty_of_goal(int pos,struct local_owl_data * owl)1808 liberty_of_goal(int pos, struct local_owl_data *owl)
1809 {
1810   int k;
1811   for (k = 0; k < 4; k++)
1812     if (IS_STONE(board[pos + delta[k]]) && owl->goal[pos + delta[k]])
1813       return 1;
1814 
1815   return 0;
1816 }
1817 
1818 /* Is the vertex at pos a second liberty of the owl goal? */
1819 static int
second_liberty_of_goal(int pos,struct local_owl_data * owl)1820 second_liberty_of_goal(int pos, struct local_owl_data *owl)
1821 {
1822   int k;
1823   for (k = 0; k < 4; k++)
1824     if (board[pos + delta[k]] == EMPTY && liberty_of_goal(pos + delta[k], owl))
1825       return 1;
1826 
1827   return 0;
1828 }
1829 
1830 
1831 /* 'liberty' is a liberty of 'worm' which we would like to fill.
1832  * However it is not safe to play there, so we look for a
1833  * backfilling move. For example in this situation:
1834  *
1835  *   ------+
1836  *   O.OaXc|
1837  *   OOOOOX|
1838  *   XXXXXb|
1839  *   ......|
1840  *
1841  * If 'worm' is the O string and 'liberty' is 'a', the
1842  * function returns 'b'. To fill at 'a', X must first
1843  * fill 'b' and 'c' and it is better to fill at 'b' first
1844  * since that will sometimes leave fewer or smaller ko threats.
1845  *
1846  * Returns NO_MOVE if no move is found.
1847  */
1848 
1849 static int
find_semeai_backfilling_move(int worm,int liberty)1850 find_semeai_backfilling_move(int worm, int liberty)
1851 {
1852   int color = board[worm];
1853   int other = OTHER_COLOR(color);
1854   int result = NO_MOVE;
1855 
1856   if (safe_move(liberty, other) == WIN)
1857     return liberty;
1858   if (is_self_atari(liberty, other)) {
1859     int fill;
1860     if (approxlib(liberty, other, 1, &fill) > 0
1861 	&& trymove(fill, other, "find_semeai_backfilling_move", worm)) {
1862       if (safe_move(liberty, other))
1863 	result = fill;
1864       else if (board[worm] != EMPTY)
1865 	result = find_semeai_backfilling_move(worm, liberty);
1866       popgo();
1867     }
1868   }
1869   if (ON_BOARD(result) && safe_move(result, other))
1870     return result;
1871   else
1872     return NO_MOVE;
1873 }
1874 
1875 /* Some helper function for do_owl_attack/defend. */
1876 
1877 static int
reading_limit_reached(const char ** live_reason,int this_variation_number)1878 reading_limit_reached(const char **live_reason, int this_variation_number)
1879 {
1880   /* If (stackp > owl_reading_depth), interpret deep reading
1881    * conservatively as escape.
1882    */
1883   if (stackp > owl_reading_depth) {
1884     TRACE("%oVariation %d: ALIVE (maximum reading depth reached)\n",
1885 	  this_variation_number);
1886     *live_reason = "max reading depth reached";
1887     return 1;
1888   }
1889   /* If the owl node limit has been reached, assume the dragon has
1890    * managed to escape.
1891    */
1892   if (local_owl_node_counter >= owl_node_limit) {
1893     result_certain = 0;
1894     TRACE("%oVariation %d: ALIVE (owl node limit reached)\n",
1895 	  this_variation_number);
1896     *live_reason = "owl node limit reached";
1897     return 1;
1898   }
1899   return 0;
1900 }
1901 
1902 static void
clear_owl_move_data(struct owl_move_data moves[MAX_MOVES])1903 clear_owl_move_data(struct owl_move_data moves[MAX_MOVES])
1904 {
1905   int k;
1906   for (k = 0; k < MAX_MOVES; k++) {
1907     moves[k].pos = NO_MOVE;
1908     moves[k].value = -1;
1909     moves[k].name = NULL;
1910     moves[k].same_dragon = SAME_DRAGON_CONNECTED;
1911     moves[k].escape = 0;
1912     moves[k].lunch = NO_MOVE;
1913     moves[k].pattern_data = NULL;
1914     clear_cut_list(moves[k].cuts);
1915   }
1916 }
1917 
1918 static void
set_single_owl_move(struct owl_move_data moves[MAX_MOVES],int pos,const char * name)1919 set_single_owl_move(struct owl_move_data moves[MAX_MOVES],
1920     		    int pos, const char *name)
1921 {
1922   moves[0].pos          = pos;
1923   moves[0].value        = 25;
1924   moves[0].name         = name;
1925   moves[0].same_dragon  = SAME_DRAGON_MAYBE_CONNECTED;
1926   moves[0].escape       = 0;
1927   moves[0].lunch        = NO_MOVE;
1928   moves[0].pattern_data = NULL;
1929   clear_cut_list(moves[0].cuts);
1930   moves[1].value        = 0;
1931 }
1932 
1933 
1934 /* Returns true if a move can be found to attack the dragon
1935  * at (target), in which case (*attack_point) is the recommended move.
1936  * (attack_point) can be a null pointer if only the result is needed.
1937  *
1938  * The array goal marks the extent of the dragon. This must
1939  * be maintained during reading. Call this function only when
1940  * stackp==0; otherwise you can call do_owl_attack but you must
1941  * set up the goal and boundary arrays by hand first.
1942  *
1943  * Returns KO_A or KO_B if the position is ko:
1944  *
1945  * - Returns KO_A if the attack prevails provided attacker is willing to
1946  *   ignore any ko threat (the attacker makes the first ko capture).
1947  *
1948  * - Returns KO_B if attack succeeds provided attacker has a ko threat
1949  *   which must be answered (the defender makes the first ko capture).
1950  *
1951  * If GNU Go is compiled with `configure --enable-experimental-owl-ext'
1952  * then a return codes of GAIN is also possible.
1953  *
1954  * - Returns GAIN if the attack fails but another worm of the
1955  *   opponent's is captured in during the failed attack. The location
1956  *   of the killed worm is returned through the *kworm field.
1957  *
1958  * */
1959 
1960 int
owl_attack(int target,int * attack_point,int * certain,int * kworm)1961 owl_attack(int target, int *attack_point, int *certain, int *kworm)
1962 {
1963   int result;
1964   struct local_owl_data *owl;
1965   int reading_nodes_when_called = get_reading_node_counter();
1966   double start = 0.0;
1967   int tactical_nodes;
1968   int move = NO_MOVE;
1969   int wpos = NO_MOVE;
1970   int wid = MAX_GOAL_WORMS;
1971 
1972   result_certain = 1;
1973   if (worm[target].unconditional_status == DEAD) {
1974     if (attack_point)
1975       *attack_point = NO_MOVE;
1976     if (kworm)
1977       *kworm = NO_MOVE;
1978     if (certain)
1979       *certain = 1;
1980     return 1;
1981   }
1982 
1983   if (search_persistent_owl_cache(OWL_ATTACK, target, 0, 0, &result,
1984 				  attack_point, kworm, certain))
1985     return result;
1986 
1987   if (debug & DEBUG_OWL_PERFORMANCE)
1988     start = gg_cputime();
1989 
1990   TRACE("owl_attack %1m\n", target);
1991   init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
1992   owl_make_domains(owl, NULL);
1993   prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
1994 		    kworm, 1);
1995   result = do_owl_attack(target, &move, &wid, owl, 0);
1996   finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
1997   tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
1998 
1999   DEBUG(DEBUG_OWL_PERFORMANCE,
2000     "owl_attack %1m, result %d %1m (%d, %d nodes, %f seconds)\n",
2001     target, result, move, local_owl_node_counter,
2002     tactical_nodes, gg_cputime() - start);
2003 
2004   store_persistent_owl_cache(OWL_ATTACK, target, 0, 0,
2005 			     result, move, wpos,
2006 			     result_certain, tactical_nodes,
2007 			     owl->goal, board[target]);
2008   if (attack_point)
2009     *attack_point = move;
2010   if (kworm)
2011     *kworm = wpos;
2012   if (certain)
2013     *certain = result_certain;
2014 
2015   return result;
2016 }
2017 
2018 
2019 /* Static function containing the main recursive code for
2020  * owl_attack.
2021  */
2022 
2023 static int
do_owl_attack(int str,int * move,int * wormid,struct local_owl_data * owl,int escape)2024 do_owl_attack(int str, int *move, int *wormid,
2025 	      struct local_owl_data *owl, int escape)
2026 {
2027   int color = board[str];
2028   int other = OTHER_COLOR(color);
2029   struct owl_move_data vital_moves[MAX_MOVES];
2030   struct owl_move_data shape_moves[MAX_MOVES];
2031   struct owl_move_data *moves;
2032   struct matched_patterns_list_data shape_patterns;
2033   signed char mw[BOARDMAX];
2034   int number_tried_moves = 0;
2035   int pass;
2036   int k;
2037   int savemove = 0;
2038   int saveworm = MAX_GOAL_WORMS;
2039   int savecode = 0;
2040   int eyemin = -1;               /* Lower bound on the number of eyes. */
2041   int eyemax = -1;               /* Upper bound on the number of eyes. */
2042   struct eyevalue probable_eyes; /* Best guess of eyevalue. */
2043   const char *live_reason;
2044   int move_cutoff;
2045   int xpos;
2046   int value1;
2047   int value2;
2048   int this_variation_number = count_variations - 1;
2049 
2050   SETUP_TRACE_INFO("owl_attack", str);
2051 
2052   shape_patterns.initialized = 0;
2053 
2054   str = find_origin(str);
2055 
2056   if (tt_get(&ttable, OWL_ATTACK, str, NO_MOVE, depth - stackp, NULL,
2057 	     &value1, &value2, &xpos) == 2) {
2058 
2059     TRACE_CACHED_RESULT(value1, xpos);
2060     if (move)
2061       *move = xpos;
2062 
2063     if (value1 == GAIN) {
2064       if (wormid) {
2065 	if (goal_worms_computed)
2066 	  *wormid = value2;
2067 	else
2068 	  *wormid = MAX_GOAL_WORMS;
2069       }
2070     }
2071 
2072     if (value1 == WIN)
2073       TRACE("%oVariation %d: DEAD (cached)\n", this_variation_number);
2074     else
2075       TRACE("%oVariation %d: ALIVE (cached)\n", this_variation_number);
2076 
2077     SGFTRACE(xpos, value1, "cached");
2078 
2079     return value1;
2080   }
2081 
2082 
2083   /* If reading goes to deep or we run out of nodes, we assume life. */
2084   if (reading_limit_reached(&live_reason, this_variation_number)) {
2085     SGFTRACE(0, 0, live_reason);
2086     READ_RETURN(OWL_ATTACK, str, depth - stackp, move, 0, 0);
2087   }
2088 
2089   memset(mw, 0, sizeof(mw));
2090   global_owl_node_counter++;
2091   local_owl_node_counter++;
2092 
2093   current_owl_data = owl;
2094   memset(owl->safe_move_cache, 0, sizeof(owl->safe_move_cache));
2095 
2096   /* First see whether there is any chance to kill. */
2097   if (owl_estimate_life(owl, NULL, vital_moves, &live_reason, 1,
2098 			&probable_eyes, &eyemin, &eyemax)) {
2099     /*
2100      * We need to check here if there's a worm under atari. If yes,
2101      * locate it and report a (gote) GAIN.
2102      */
2103     int acode = 0;
2104     int mpos = NO_MOVE;
2105     if (experimental_owl_ext && goal_worms_computed) {
2106       int size = 0;
2107       saveworm = MAX_GOAL_WORMS;
2108       for (k = 0; k < MAX_GOAL_WORMS; k++) {
2109 	if (owl_goal_worm[k] == NO_MOVE)
2110 	  break;
2111 	if (board[owl_goal_worm[k]] == EMPTY
2112 	    || countlib(owl_goal_worm[k]) > 1)
2113 	  continue;
2114 	if (worm[owl_goal_worm[k]].size > size) {
2115 	  saveworm = k;
2116 	  size = worm[owl_goal_worm[k]].size;
2117 	}
2118       }
2119       if (saveworm != MAX_GOAL_WORMS && size >= 3) {
2120 	acode = GAIN;
2121 	findlib(worm[owl_goal_worm[saveworm]].origin, 1, &mpos);
2122 	/* ASSERT1( ... */
2123       }
2124     }
2125     SGFTRACE(0, acode, live_reason);
2126     TRACE("%oVariation %d: ALIVE (%s)\n", this_variation_number, live_reason);
2127     if (acode == 0) {
2128       READ_RETURN(OWL_ATTACK, str, depth - stackp, move, 0, 0);
2129     }
2130     else {
2131       if (wormid)
2132 	*wormid = saveworm;
2133       READ_RETURN2(OWL_ATTACK, str, depth - stackp,
2134 		   move, mpos, acode, saveworm);
2135     }
2136   }
2137 
2138   /* We try moves in five passes.
2139    *                                stackp==0   stackp>0
2140    * 0. Vital moves in the interval  [70..]      [45..]
2141    * 1. Shape moves
2142    * 2. Vital moves in the interval  [..69]      [..44]
2143    * 3. Tactical attack moves (except certain kos)
2144    * 4. Moves found by the defender
2145    * 5. Tactical ko attack moves which were not tried in pass 3
2146    */
2147   for (pass = 0; pass < 6; pass++) {
2148     moves = NULL;
2149     move_cutoff = 1;
2150 
2151     current_owl_data = owl;
2152     /* Get the shape moves if we are in the right pass. */
2153     switch (pass) {
2154     case 1:
2155       if (stackp > owl_branch_depth && number_tried_moves > 0)
2156 	continue;
2157 
2158       owl_shapes(&shape_patterns, shape_moves, other, owl, &owl_attackpat_db);
2159       moves = shape_moves;
2160       break;
2161 
2162     case 0:
2163     case 2:
2164       if (stackp > owl_branch_depth && number_tried_moves > 0)
2165 	continue;
2166 
2167       moves = vital_moves;
2168       if (pass == 0 || stackp > owl_distrust_depth) {
2169 	if (stackp == 0)
2170 	  move_cutoff = 70;
2171 	else
2172 	  move_cutoff = 45;
2173       }
2174       if (eyemax < 2 && stackp > 2)
2175 	move_cutoff = 99; /* Effectively disable vital moves. */
2176       break;
2177 
2178     case 3:
2179     case 5:
2180       {
2181 	/* Look for a tactical attack. This is primarily intended for
2182 	 * the case where the whole dragon is a single string, therefore
2183 	 * we only look at the string at the "origin".
2184 	 *
2185 	 * We must be wary with attacks giving ko. Unless the dragon
2186 	 * otherwise looks alive, this may turn a dead dragon into one
2187 	 * which can live by ko. Such moves will be tried anyway in
2188 	 * pass 5. Notice though that we can only reach there if an owl
2189 	 * defense was found in pass 4.
2190 	 */
2191 	int apos;
2192 	int result;
2193 	SGFTree *save_sgf_dumptree = sgf_dumptree;
2194 	int save_count_variations = count_variations;
2195 
2196 	sgf_dumptree = NULL;
2197 	count_variations = 0;
2198 	result = attack(str, &apos);
2199 	if (result == WIN
2200 	    || (result != 0 && (min_eyes(&probable_eyes) >= 2
2201 				|| pass == 5))) {
2202 	  set_single_owl_move(shape_moves, apos, "tactical attack");
2203 	  moves = shape_moves;
2204 	}
2205 	sgf_dumptree = save_sgf_dumptree;
2206 	count_variations = save_count_variations;
2207       }
2208       break;
2209 
2210     /* If we found no move in the first four passes we ask the defender
2211      * for a move suggestion.
2212      */
2213     case 4:
2214       if (number_tried_moves == 0) {
2215 	int dpos;
2216 	int dcode = do_owl_defend(str, &dpos, NULL, owl, escape);
2217 	/* No defense, we won. */
2218 	if (dcode == 0) {
2219 	  TRACE("%oVariation %d: DEAD (no defense)\n",
2220 		this_variation_number);
2221 	  SGFTRACE(0, WIN, "no defense");
2222 	  close_pattern_list(other, &shape_patterns);
2223 	  READ_RETURN(OWL_ATTACK, str, depth - stackp, move, 0, WIN);
2224 	}
2225 	else if (dpos != NO_MOVE) {
2226 	  /* The dragon could be defended by one more move. Try to
2227 	   * attack with this move.
2228 	   *
2229 	   * If the move is suicide for us, try to find a backfilling
2230 	   * move to play instead. Do this also if the move is a
2231 	   * send-two-return-one sacrifice.
2232 	   */
2233 	  const char *name = "defense move";
2234 	  SGFTree *save_sgf_dumptree = sgf_dumptree;
2235 	  int save_count_variations = count_variations;
2236 
2237 	  sgf_dumptree = NULL;
2238 	  count_variations = 0;
2239 
2240 	  if (is_suicide(dpos, other) || send_two_return_one(dpos, other)) {
2241 	    int dpos2;
2242 	    for (k = 0; k < 4; k++) {
2243 	      if (board[dpos + delta[k]] == other
2244 		  && find_defense(dpos + delta[k], &dpos2)) {
2245 		dpos = dpos2;
2246 		name = "defense move (backfill)";
2247 		break;
2248 	      }
2249 	    }
2250 	  }
2251 
2252 	  sgf_dumptree = save_sgf_dumptree;
2253 	  count_variations = save_count_variations;
2254 
2255 	  if (dpos != NO_MOVE) {
2256 	    set_single_owl_move(shape_moves, dpos, name);
2257 	    moves = shape_moves;
2258 	  }
2259 	}
2260       }
2261       break;
2262     } /* switch (pass) */
2263 
2264 
2265     /* FIXME: This block probably should reappear somewhere in this
2266      * function.
2267      */
2268 #if 0
2269     /* First test whether the dragon has escaped. */
2270     if (owl_escape_route(owl) >= 5) {
2271       /* FIXME: We probably should make distinction in the returned
2272        * result whether the dragon lives by making two eyes or by
2273        * escaping.
2274        */
2275       TRACE("%oVariation %d: ALIVE (escaped)\n", this_variation_number);
2276       SGFTRACE(0, 0, "escaped");
2277       close_pattern_list(other, &shape_patterns);
2278       READ_RETURN0(OWL_ATTACK, str, depth - stackp);
2279     }
2280 #endif
2281 
2282     if (!moves)
2283       continue;
2284 
2285     /* For the up to MAX_MOVES best moves with value equal to
2286      * move_cutoff or higher, try to attack the dragon and see if it
2287      * can then be defended.
2288      */
2289     for (k = 0; k < MAX_MOVES; k++) {
2290       int mpos;
2291       int ko_move = -1;
2292       int origin = NO_MOVE;
2293       int captured;
2294       int wid = MAX_GOAL_WORMS;
2295       int dcode;
2296 
2297       /* Consider only the highest scoring move if we're deeper than
2298        * owl_branch_depth.
2299        *
2300        * FIXME: To behave as intended, k should be replaced by
2301        *        number_tried_moves.
2302        */
2303       if (stackp > owl_branch_depth && k > 0)
2304 	break;
2305 
2306       current_owl_data = owl;
2307 
2308       /* Shape moves are selected on demand. */
2309       if (pass == 1) {
2310         if (!get_next_move_from_list(&shape_patterns, other,
2311 	                             shape_moves, move_cutoff, owl))
2312           break;
2313       }
2314       else
2315 	if (moves[k].value < move_cutoff)
2316 	  break;
2317 
2318       mpos = moves[k].pos;
2319       ASSERT_ON_BOARD1(mpos);
2320 
2321       /* Have we already tested this move? */
2322       if (mw[mpos])
2323 	continue;
2324 
2325       captured = (color == WHITE ? white_captured : black_captured);
2326 
2327       /* Try to make the move. */
2328       if (!komaster_trymove(mpos, other, moves[k].name, str,
2329 			    &ko_move, savecode == 0))
2330 	continue;
2331 
2332       captured = (color == WHITE ? white_captured : black_captured) - captured;
2333 
2334       TRACE("Trying %C %1m. Escape = %d. Current stack: ",
2335 	    other, mpos, escape);
2336       if (verbose)
2337 	dump_stack();
2338 
2339       /* We have now made a move. Analyze the new position. */
2340       push_owl(&owl);
2341       mw[mpos] = 1;
2342       number_tried_moves++;
2343       owl_update_boundary_marks(mpos, owl);
2344 
2345       /* If the origin of the dragon has been captured, we look
2346        * for another string which was part of the original dragon,
2347        * marked when stackp==0, which has not been captured. If no
2348        * such string is found, owl_attack declares victory.
2349        */
2350       if (IS_STONE(board[str]))
2351 	origin = str;
2352       else
2353 	origin = select_new_goal_origin(NO_MOVE, owl);
2354 
2355       /* Test whether the move cut the goal dragon apart. */
2356       if (moves[k].cuts[0] != NO_MOVE && origin != NO_MOVE) {
2357 	owl_test_cuts(owl->goal, owl->color, moves[k].cuts);
2358 	if (!owl->goal[origin])
2359 	  origin = select_new_goal_origin(origin, owl);
2360       }
2361       mark_goal_in_sgf(owl->goal);
2362 
2363       if (origin == NO_MOVE)
2364 	dcode = 0;
2365       else
2366 	dcode = do_owl_defend(origin, NULL, &wid, owl, escape);
2367 
2368       if (!ko_move) {
2369 	if (dcode == 0) {
2370 	  pop_owl(&owl);
2371 	  popgo();
2372   	  if (sgf_dumptree) {
2373 	    const char *wintxt;
2374 	    char winstr[192];
2375 	    if (origin == NO_MOVE)
2376 	      wintxt = "all original stones captured";
2377 	    else
2378 	      wintxt = "attack effective";
2379 	    sprintf(winstr, "%s)\n  (%d variations", wintxt,
2380 	  		    count_variations - this_variation_number);
2381 	    SGFTRACE(mpos, WIN, winstr);
2382 	  }
2383           close_pattern_list(other, &shape_patterns);
2384 	  READ_RETURN(OWL_ATTACK, str, depth - stackp, move, mpos, WIN);
2385 	}
2386 	else if (experimental_owl_ext && dcode == LOSS) {
2387 	  if (saveworm == MAX_GOAL_WORMS
2388 	      || worm[owl_goal_worm[wid]].size
2389 		 > worm[owl_goal_worm[saveworm]].size)
2390 	    saveworm = wid;
2391 	}
2392 	/* The conditions here are set so that this code doesn't get
2393 	 * triggered when the capture is immediate (the tactical
2394 	 * reading code should take care of these).
2395 	 */
2396 	else if (experimental_owl_ext && goal_worms_computed
2397 #if 0
2398 		 && stackp > 1
2399 #endif
2400 		 && captured >= 3) {
2401 	  int w = MAX_GOAL_WORMS;
2402 	  int size = 0;
2403 	  int l;
2404 	  /* locate the biggest captured worm */
2405 	  for (l = 0; l < MAX_GOAL_WORMS; l++) {
2406 	    if (owl_goal_worm[l] == NO_MOVE)
2407 	      break;
2408 	    if (board[owl_goal_worm[l]] == EMPTY)
2409 	      if (size == 0 || worm[owl_goal_worm[l]].size > size) {
2410 		w = l;
2411 		size = worm[owl_goal_worm[l]].size;
2412 	      }
2413 	  }
2414 	  if (w != MAX_GOAL_WORMS) {
2415 	    if (GAIN > savecode) {
2416   	      /* if new result better, just update */
2417 	      dcode = LOSS;
2418 	      saveworm = w;
2419 	    }
2420 	    else if (GAIN == savecode) {
2421 	      /* bigger ? */
2422 	      int wpos = owl_goal_worm[saveworm];
2423 	      if (size > worm[wpos].size)
2424   		saveworm = w;
2425 	    }
2426 	  }
2427 	}
2428 	UPDATE_SAVED_KO_RESULT(savecode, savemove, dcode, mpos);
2429       }
2430       else { /* ko_move */
2431 	if (dcode != WIN) {
2432 	  if (mpos == 0) {
2433 	    SGFTRACE(mpos, KO_B, "all original stones captured with ko");
2434 	  }
2435 	  else {
2436 	    SGFTRACE(mpos, KO_B, "attack effective - ko");
2437 	  }
2438 	  /* We already know the savecode was previously 0. */
2439 	  savemove = mpos;
2440 	  savecode = KO_B;
2441 
2442 	  /* It's possible that the defender has no defense even if we
2443            * give up the ko. In order to force a test of this,
2444            * assuming this was our only move, we decrease the number
2445            * of tried moves counter, disregarding this move.
2446 	   */
2447 	  number_tried_moves--;
2448 	}
2449       }
2450 
2451       pop_owl(&owl);
2452       popgo();
2453     }
2454   }
2455 
2456   close_pattern_list(other, &shape_patterns);
2457 
2458   if (savecode) {
2459     if (savecode == GAIN) {
2460       SGFTRACE(savemove, savecode, "attack effective (gain) - E");
2461       if (wormid)
2462 	*wormid = saveworm;
2463       READ_RETURN2(OWL_ATTACK, str, depth - stackp,
2464 		   move, savemove, savecode, saveworm);
2465     }
2466     else {
2467       SGFTRACE(savemove, savecode, "attack effective (ko) - E");
2468       READ_RETURN(OWL_ATTACK, str, depth - stackp, move, savemove, savecode);
2469     }
2470   }
2471 
2472   if (sgf_dumptree) {
2473     char winstr[128];
2474     sprintf(winstr, "attack failed)\n  (%d variations",
2475 	  	    count_variations - this_variation_number);
2476     SGFTRACE(0, 0, winstr);
2477   }
2478 
2479   READ_RETURN0(OWL_ATTACK, str, depth - stackp);
2480 }
2481 
2482 
2483 /* Returns true if the dragon at (target) can be captured given
2484  * two moves in a row. The first two moves to capture the
2485  * dragon are given as (*attack1) and (*attack2).
2486  */
2487 
2488 int
owl_threaten_attack(int target,int * attack1,int * attack2)2489 owl_threaten_attack(int target, int *attack1, int *attack2)
2490 {
2491   struct owl_move_data moves[MAX_MOVES];
2492   int k;
2493   int other = OTHER_COLOR(board[target]);
2494   struct local_owl_data *owl;
2495   int result = 0;
2496   int reading_nodes_when_called = get_reading_node_counter();
2497   signed char saved_boundary[BOARDMAX];
2498   double start = 0.0;
2499   int tactical_nodes;
2500   int move = 0;
2501   int move2 = 0;
2502   struct matched_patterns_list_data shape_patterns;
2503 
2504   shape_patterns.initialized = 0;
2505   result_certain = 1;
2506   if (search_persistent_owl_cache(OWL_THREATEN_ATTACK, target, 0, 0,
2507 				  &result, attack1, attack2, NULL))
2508     return result;
2509 
2510   if (debug & DEBUG_OWL_PERFORMANCE)
2511     start = gg_cputime();
2512 
2513   gg_assert(stackp == 0);
2514   TRACE("owl_threaten_attack %1m\n", target);
2515   init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
2516   memcpy(saved_boundary, owl->boundary, sizeof(saved_boundary));
2517   owl_make_domains(owl, NULL);
2518   owl_shapes(&shape_patterns, moves, other, owl, &owl_attackpat_db);
2519   for (k = 0; k < MAX_MOVES; k++) {
2520     current_owl_data = owl;
2521     if (!get_next_move_from_list(&shape_patterns, other, moves, 1, owl))
2522       break;
2523     else {
2524       int mpos = moves[k].pos;
2525 
2526       if (mpos != NO_MOVE && moves[k].value > 0)
2527 	if (trymove(mpos, other, moves[k].name, target)) {
2528 	  int pos;
2529 	  int origin = NO_MOVE;
2530 	  owl->lunches_are_current = 0;
2531 	  owl_update_boundary_marks(mpos, owl);
2532 
2533 	  /* If the origin of the dragon has been captured, we look
2534 	   * for another string which was part of the original dragon,
2535 	   * marked when stackp==0, which has not been captured. If no
2536 	   * such string is found, owl_attack declares victory.
2537 	   */
2538 
2539 	  if (board[target] == EMPTY) {
2540 	    for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
2541 	      if (IS_STONE(board[pos]) && owl->goal[pos] == 1) {
2542 		origin = find_origin(pos);
2543 		break;
2544 	      }
2545 	    }
2546 
2547 	    if (origin == NO_MOVE
2548 		|| do_owl_attack(origin, NULL, NULL, owl, 0)) {
2549 	      /* probably this can't happen */
2550 	      popgo();
2551 	      gg_assert(stackp == 0);
2552 	      result = 1;
2553 	      break;
2554 	    }
2555 	  }
2556 	  else if (do_owl_attack(target, &move2, NULL, owl, 0) == WIN) {
2557 	    move = moves[k].pos;
2558 	    popgo();
2559 	    gg_assert(stackp == 0);
2560 	    result = 1;
2561 	    break;
2562 	  }
2563 	  popgo();
2564 	  memcpy(owl->boundary, saved_boundary, sizeof(saved_boundary));
2565 	}
2566     }
2567   }
2568   tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
2569   gg_assert(stackp == 0);
2570 
2571   DEBUG(DEBUG_OWL_PERFORMANCE,
2572     "owl_threaten_attack %1m %1m %1m, result %d (%d, %d nodes, %f seconds)\n",
2573     target, move, move2, result, local_owl_node_counter,
2574     tactical_nodes, gg_cputime() - start);
2575 
2576   store_persistent_owl_cache(OWL_THREATEN_ATTACK, target, 0, 0,
2577 			     result, move, move2, 0,
2578 			     tactical_nodes, owl->goal, board[target]);
2579 
2580   if (attack1)
2581     *attack1 = move;
2582   if (attack2)
2583     *attack2 = move2;
2584 
2585   close_pattern_list(other, &shape_patterns);
2586   return result;
2587 }
2588 
2589 
2590 /* Returns true if a move can be found to defend the dragon
2591  * at (target), in which case (*defense_point) is the recommended move.
2592  * (defense_point) can be a null pointer if the result is not needed.
2593  *
2594  * The array goal marks the extent of the dragon. This must
2595  * be maintained during reading. Call this function only when
2596  * stackp==0; otherwise you can call do_owl_attack but you must
2597  * set up the goal and boundary arrays by hand first.
2598  *
2599  * Returns KO_A or KO_B if the position is ko:
2600  *
2601  * - Returns KO_A if the defendse succeeds provided the defender is willing to
2602  *   ignore any ko threat (the defender makes the first ko capture).
2603  * - Returns KO_B if the defense succeeds provided the defender has a ko threat
2604  *   which must be answered (the attacker makes the first ko capture).
2605  *
2606  * If GNU Go is compiled with `configure --enable-experimental-owl-ext'
2607  * then a return codes of GAIN is also possible.
2608  *
2609  * - Returns LOSS if the defense succeeds but another worm of the
2610  *   defender's is captured in during the defense. The location
2611  *   of the killed worm is returned through the *kworm field.
2612  *
2613  * The array goal marks the extent of the dragon. This must
2614  * be maintained during reading.
2615  */
2616 
2617 int
owl_defend(int target,int * defense_point,int * certain,int * kworm)2618 owl_defend(int target, int *defense_point, int *certain, int *kworm)
2619 {
2620   int result;
2621   static struct local_owl_data *owl;
2622   int reading_nodes_when_called = get_reading_node_counter();
2623   double start = 0.0;
2624   int tactical_nodes;
2625   int move = NO_MOVE;
2626   int wpos = NO_MOVE;
2627   int wid = MAX_GOAL_WORMS;
2628 
2629   result_certain = 1;
2630   if (worm[target].unconditional_status == DEAD)
2631     return 0;
2632 
2633   if (search_persistent_owl_cache(OWL_DEFEND, target, 0, 0, &result,
2634 				  defense_point, kworm, certain))
2635     return result;
2636 
2637   if (debug & DEBUG_OWL_PERFORMANCE)
2638     start = gg_cputime();
2639 
2640   TRACE("owl_defend %1m\n", target);
2641   init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
2642   owl_make_domains(owl, NULL);
2643   prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
2644 		    kworm, 1);
2645   result = do_owl_defend(target, &move, &wid, owl, 0);
2646   finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
2647   tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
2648 
2649   DEBUG(DEBUG_OWL_PERFORMANCE,
2650     "owl_defend %1m, result %d %1m (%d, %d nodes, %f seconds)\n",
2651 	    target, result, move, local_owl_node_counter,
2652 	    tactical_nodes, gg_cputime() - start);
2653 
2654   store_persistent_owl_cache(OWL_DEFEND, target, 0, 0, result, move, wpos,
2655 			     result_certain, tactical_nodes, owl->goal,
2656 			     board[target]);
2657 
2658   if (defense_point)
2659     *defense_point = move;
2660   if (kworm)
2661     *kworm = wpos;
2662   if (certain)
2663     *certain = result_certain;
2664 
2665   return result;
2666 }
2667 
2668 
2669 /* Static function containing the main recursive code for owl_defend.
2670  */
2671 
2672 static int
do_owl_defend(int str,int * move,int * wormid,struct local_owl_data * owl,int escape)2673 do_owl_defend(int str, int *move, int *wormid, struct local_owl_data *owl,
2674 	      int escape)
2675 {
2676   int color = board[str];
2677   struct owl_move_data shape_moves[MAX_MOVES];
2678   struct owl_move_data vital_moves[MAX_MOVES];
2679   struct owl_move_data *moves;
2680   struct matched_patterns_list_data shape_patterns;
2681   signed char mw[BOARDMAX];
2682   int number_tried_moves = 0;
2683   int pass;
2684   int k;
2685   int savemove = 0;
2686   int saveworm = MAX_GOAL_WORMS;
2687   int savecode = 0;
2688   int eyemin = -1;               /* Lower bound on the number of eyes. */
2689   int eyemax = -1;               /* Upper bound on the number of eyes. */
2690   struct eyevalue probable_eyes; /* Best guess of eyevalue. */
2691   int escape_route;
2692   const char *live_reason;
2693   int move_cutoff;
2694   int xpos;
2695   int value1;
2696   int value2;
2697   int this_variation_number = count_variations - 1;
2698 
2699   SETUP_TRACE_INFO("owl_defend", str);
2700 
2701   shape_patterns.initialized = 0;
2702 
2703   str = find_origin(str);
2704 
2705   if (tt_get(&ttable, OWL_DEFEND, str, NO_MOVE, depth - stackp, NULL,
2706 	     &value1, &value2, &xpos) == 2) {
2707 
2708     TRACE_CACHED_RESULT(value1, xpos);
2709     if (move)
2710       *move = xpos;
2711 
2712     if (value1 == LOSS) {
2713       if (wormid) {
2714 	if (goal_worms_computed)
2715 	  *wormid = value2;
2716 	else
2717 	  *wormid = MAX_GOAL_WORMS;
2718       }
2719     }
2720 
2721     if (value1 == WIN || value1 == LOSS)
2722       TRACE("%oVariation %d: ALIVE (cached)\n", this_variation_number);
2723     else
2724       TRACE("%oVariation %d: DEAD (cached)\n", this_variation_number);
2725 
2726     SGFTRACE(xpos, value1, "cached");
2727 
2728     return value1;
2729   }
2730 
2731   /* In order to get a defense move even if we seem to already have
2732    * escaped and to reduce the impact of overestimated escape
2733    * possibilities, we don't declare escape victory on the first move.
2734    *
2735    * FIXME: Should introduce a new owl depth value rather than having
2736    *        this hardwired value.
2737    */
2738   escape_route = owl_escape_route(owl);
2739   if (stackp > 2 && escape_route >= 5) {
2740     /* FIXME: We probably should make distinction in the returned
2741      * result whether the dragon lives by making two eyes or by
2742      * escaping.
2743      */
2744     TRACE("%oVariation %d: ALIVE (escaped)\n", this_variation_number);
2745     SGFTRACE(0, WIN, "escaped");
2746     READ_RETURN(OWL_DEFEND, str, depth - stackp, move, 0, WIN);
2747   }
2748 
2749   /* If reading goes to deep or we run out of nodes, we assume life. */
2750   if (reading_limit_reached(&live_reason, this_variation_number)) {
2751     SGFTRACE(0, WIN, live_reason);
2752     READ_RETURN(OWL_DEFEND, str, depth - stackp, move, 0, WIN);
2753   }
2754 
2755   memset(mw, 0, sizeof(mw));
2756   local_owl_node_counter++;
2757   global_owl_node_counter++;
2758 
2759   current_owl_data = owl;
2760   memset(owl->safe_move_cache, 0, sizeof(owl->safe_move_cache));
2761 
2762   /* First see whether we might already be alive. */
2763   if (escape < MAX_ESCAPE) {
2764     if (owl_estimate_life(owl, NULL, vital_moves, &live_reason, 0,
2765 	  		  &probable_eyes, &eyemin, &eyemax)) {
2766       SGFTRACE(0, WIN, live_reason);
2767       TRACE("%oVariation %d: ALIVE (%s)\n",
2768 	    this_variation_number, live_reason);
2769       READ_RETURN(OWL_DEFEND, str, depth - stackp, move, 0, WIN);
2770     }
2771   }
2772   else {
2773     /* In this case we don't recompute eyes. However, to avoid accessing
2774      * partially-random data left on stack, we copy eye data from the
2775      * previous depth level. It should be reasonably close to the actual
2776      * state of eyes.
2777      */
2778     memcpy(owl->my_eye, owl->restore_from->my_eye, sizeof(owl->my_eye));
2779     memcpy(owl->half_eye, owl->restore_from->half_eye, sizeof(owl->half_eye));
2780 
2781     vital_moves[0].pos = 0;
2782     vital_moves[0].value = -1;
2783     set_eyevalue(&probable_eyes, 0, 0, 0, 0);
2784   }
2785 
2786   /* We try moves in four passes.
2787    *                                stackp==0   stackp>0
2788    * 0. Vital moves in the interval  [70..]      [45..]
2789    * 1. Shape moves
2790    * 2. Vital moves in the interval  [..69]      [..44]
2791    * 3. Tactical defense moves
2792    */
2793   for (pass = 0; pass < 4; pass++) {
2794     moves = NULL;
2795     move_cutoff = 1;
2796 
2797     current_owl_data = owl;
2798     switch (pass) {
2799     /* Get the shape moves if we are in the right pass. */
2800     case 1:
2801 
2802       if (stackp > owl_branch_depth && number_tried_moves > 0)
2803 	continue;
2804 
2805       owl_shapes(&shape_patterns, shape_moves, color, owl, &owl_defendpat_db);
2806       moves = shape_moves;
2807       break;
2808 
2809     case 0:
2810     case 2:
2811       if (stackp > owl_branch_depth && number_tried_moves > 0)
2812 	continue;
2813 
2814       moves = vital_moves;
2815       if (pass == 0 || stackp > owl_distrust_depth) {
2816 	if (stackp == 0)
2817 	  move_cutoff = 70;
2818 	else if (eyemin + min_eyes(&probable_eyes) > 3)
2819 	  move_cutoff = 25;
2820 	else if (eyemin + min_eyes(&probable_eyes) >= 3)
2821 	  move_cutoff = 35;
2822 	else
2823 	  move_cutoff = 45;
2824       }
2825       if (eyemax < 2 && stackp > 2)
2826 	move_cutoff = 99; /* Effectively disable vital moves. */
2827       break;
2828 
2829     case 3:
2830       {
2831 	int goalcount = 0;
2832 
2833 	/* If the goal is small, try a tactical defense. */
2834 
2835 	for (k = BOARDMIN; k < BOARDMAX; k++)
2836 	  if (ON_BOARD(k))
2837 	    goalcount += owl->goal[k];
2838 
2839 	if (goalcount < 5) {
2840 
2841 	  /* Look for a tactical defense. This is primarily intended for
2842 	   * the case where the whole dragon is a single string, therefore
2843 	   * we only look at the string at the "origin".
2844 	   *
2845 	   * We only accept clearly effective tactical defenses here,
2846 	   * using a liberty heuristic. The reason for this is problems
2847 	   * with ineffective self ataris which do defend tactically but
2848 	   * have no strategical effect other than wasting owl nodes or
2849 	   * confusing the eye analysis.
2850 	   */
2851 	  int dpos;
2852 	  SGFTree *save_sgf_dumptree = sgf_dumptree;
2853 	  int save_count_variations = count_variations;
2854 
2855 	  sgf_dumptree = NULL;
2856 	  count_variations = 0;
2857 	  if (attack_and_defend(str, NULL, NULL, NULL, &dpos)
2858 	      && (approxlib(dpos, color, 2, NULL) > 1
2859 		  || does_capture_something(dpos, color))) {
2860 	    TRACE("Found tactical defense for %1m at %1m.\n", str, dpos);
2861 	    set_single_owl_move(shape_moves, dpos, "tactical_defense");
2862 	    moves = shape_moves;
2863 	  }
2864 	  sgf_dumptree = save_sgf_dumptree;
2865 	  count_variations = save_count_variations;
2866 	}
2867 	if (!moves)
2868 	  continue;
2869       }
2870     } /* switch (pass) */
2871 
2872     /* For the up to MAX_MOVES best moves with value equal to
2873      * move_cutoff or higher, try to defend the dragon and see if it
2874      * can then be attacked.
2875      */
2876     for (k = 0; k < MAX_MOVES; k++) {
2877       int mpos;
2878       int ko_move = -1;
2879       int new_escape;
2880       int wid = MAX_GOAL_WORMS;
2881 
2882       /* Consider only the highest scoring move if we're deeper than
2883        * owl_branch_depth.
2884        *
2885        * FIXME: To behave as intended, k should be replaced by
2886        *        number_tried_moves.
2887        */
2888       if (stackp > owl_branch_depth && k > 0)
2889 	break;
2890 
2891       current_owl_data = owl;
2892 
2893       if (pass == 1) {
2894         if (!get_next_move_from_list(&shape_patterns, color, shape_moves,
2895 	                             move_cutoff, owl))
2896 	  break;
2897       }
2898       else
2899 	if (moves[k].value < move_cutoff)
2900 	  break;
2901 
2902       mpos = moves[k].pos;
2903       modify_eyefilling_move(&mpos, color);
2904       ASSERT_ON_BOARD1(mpos);
2905 
2906       /* Have we already tested this move? */
2907       if (mw[mpos])
2908 	continue;
2909 
2910       /* Try to make the move. */
2911       if (!komaster_trymove(mpos, color, moves[k].name, str,
2912 			    &ko_move, savecode == 0))
2913 	continue;
2914 
2915       new_escape = escape;
2916       if (moves[k].escape)
2917 	new_escape++;
2918 
2919       TRACE("Trying %C %1m. Escape = %d. Current stack: ",
2920 	    color, mpos, escape);
2921       if (verbose)
2922 	dump_stack();
2923 
2924       /* We have now made a move. Analyze the new position. */
2925       push_owl(&owl);
2926       mw[mpos] = 1;
2927       number_tried_moves++;
2928 
2929       /* Add the stone just played to the goal dragon, unless the
2930        * pattern explicitly asked for not doing this.
2931        */
2932       owl_update_goal(mpos, moves[k].same_dragon, moves[k].lunch, owl, 0,
2933 		      moves[k].pattern_data);
2934       mark_goal_in_sgf(owl->goal);
2935 
2936       if (!ko_move) {
2937 	int acode = do_owl_attack(str, NULL, &wid, owl, new_escape);
2938 	if (!acode) {
2939 	  pop_owl(&owl);
2940 	  popgo();
2941 	  if (sgf_dumptree) {
2942 	    char winstr[192];
2943 	    sprintf(winstr, "defense effective)\n  (%d variations",
2944 	  		    count_variations - this_variation_number);
2945 	    SGFTRACE(mpos, WIN, winstr);
2946 	  }
2947 	  close_pattern_list(color, &shape_patterns);
2948 	  READ_RETURN(OWL_DEFEND, str, depth - stackp, move, mpos, WIN);
2949 	}
2950 	if (acode == GAIN)
2951 	  saveworm = wid;
2952 	UPDATE_SAVED_KO_RESULT(savecode, savemove, acode, mpos);
2953       }
2954       else {
2955 	if (do_owl_attack(str, NULL, NULL, owl, new_escape) != WIN) {
2956 	  savemove = mpos;
2957 	  savecode = KO_B;
2958 	}
2959       }
2960 
2961       /* Undo the tested move. */
2962       pop_owl(&owl);
2963       popgo();
2964     }
2965   }
2966 
2967   close_pattern_list(color, &shape_patterns);
2968 
2969   if (savecode) {
2970     if (savecode == LOSS) {
2971       SGFTRACE(savemove, savecode, "defense effective (loss) - B");
2972       if (wormid)
2973 	*wormid = saveworm;
2974       READ_RETURN2(OWL_DEFEND, str, depth - stackp,
2975 		   move, savemove, savecode, saveworm);
2976     }
2977     else {
2978       SGFTRACE(savemove, savecode, "defense effective (ko) - B");
2979       READ_RETURN(OWL_DEFEND, str, depth - stackp, move, savemove, savecode);
2980     }
2981   }
2982 
2983   if (number_tried_moves == 0 && min_eyes(&probable_eyes) >= 2) {
2984     SGFTRACE(0, WIN, "genus probably >= 2");
2985     READ_RETURN(OWL_DEFEND, str, depth - stackp, move, 0, WIN);
2986   }
2987 
2988 
2989   if (sgf_dumptree) {
2990     char winstr[196];
2991     int print_genus = eyemin == 1 ? 1 : 0;
2992     sprintf(winstr, "defense failed - genus %d)\n  (%d variations",
2993 	  	    print_genus, count_variations - this_variation_number);
2994     SGFTRACE(0, 0, winstr);
2995   }
2996 
2997   READ_RETURN0(OWL_DEFEND, str, depth - stackp);
2998 }
2999 
3000 
3001 /* Returns true if the dragon at (target) can be defended given
3002  * two moves in a row. The first two moves to defend the
3003  * dragon are given as (*defend1) and (*defend2).
3004  */
3005 
3006 int
owl_threaten_defense(int target,int * defend1,int * defend2)3007 owl_threaten_defense(int target, int *defend1, int *defend2)
3008 {
3009   struct owl_move_data moves[MAX_MOVES];
3010   int k;
3011   int color = board[target];
3012   int result = 0;
3013   struct local_owl_data *owl;
3014   int reading_nodes_when_called = get_reading_node_counter();
3015   signed char saved_goal[BOARDMAX];
3016   double start = 0.0;
3017   int tactical_nodes;
3018   int move = 0;
3019   int move2 = 0;
3020   struct matched_patterns_list_data shape_patterns;
3021 
3022   shape_patterns.initialized = 0;
3023 
3024   result_certain = 1;
3025   if (worm[target].unconditional_status == DEAD)
3026     return 0;
3027 
3028   if (search_persistent_owl_cache(OWL_THREATEN_DEFENSE, target, 0, 0,
3029 				  &result, defend1, defend2, NULL))
3030     return result;
3031 
3032   if (debug & DEBUG_OWL_PERFORMANCE)
3033     start = gg_cputime();
3034 
3035   TRACE("owl_threaten_defense %1m\n", target);
3036   init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
3037   memcpy(saved_goal, owl->goal, sizeof(saved_goal));
3038   owl_make_domains(owl, NULL);
3039   owl_shapes(&shape_patterns, moves, color, owl, &owl_defendpat_db);
3040   for (k = 0; k < MAX_MOVES; k++) {
3041     current_owl_data = owl;
3042     if (!get_next_move_from_list(&shape_patterns, color, moves, 1, owl))
3043       break;
3044     else {
3045       if (moves[k].pos != NO_MOVE && moves[k].value > 0)
3046 	if (trymove(moves[k].pos, color, moves[k].name, target)) {
3047 	  owl->lunches_are_current = 0;
3048 	  owl_update_goal(moves[k].pos, moves[k].same_dragon,
3049 	      		  moves[k].lunch, owl, 0, moves[k].pattern_data);
3050 	  if (do_owl_defend(target, &move2, NULL, owl, 0) == WIN) {
3051 	    move = moves[k].pos;
3052 	    popgo();
3053 	    /* Don't return the second move if occupied before trymove */
3054 	    if (move2 != NO_MOVE && IS_STONE(board[move2]))
3055 	      move2 = NO_MOVE;
3056 	    result = WIN;
3057 	    break;
3058 	  }
3059 	  else
3060 	    popgo();
3061 	  memcpy(owl->goal, saved_goal, sizeof(saved_goal));
3062 	}
3063     }
3064   }
3065   tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
3066   gg_assert(stackp == 0);
3067 
3068   DEBUG(DEBUG_OWL_PERFORMANCE,
3069     "owl_threaten_defense %1m %1m %1m, result %d (%d, %d nodes, %f seconds)\n",
3070 	    target, move, move2, result, local_owl_node_counter,
3071 	    tactical_nodes, gg_cputime() - start);
3072 
3073   store_persistent_owl_cache(OWL_THREATEN_DEFENSE, target, 0, 0,
3074 			     result, move, move2, 0,
3075 			     tactical_nodes, owl->goal, board[target]);
3076 
3077   if (defend1)
3078     *defend1 = move;
3079   if (defend2)
3080     *defend2 = move2;
3081 
3082   close_pattern_list(color, &shape_patterns);
3083   return result;
3084 }
3085 
3086 
3087 
3088 /*
3089  * This function calls owl_determine_life() to get an eye estimate,
3090  * and matchpat() for vital attack moves, and decides according to
3091  * various policies (depth-dependant) whether the dragon should thus
3092  * be considered alive.
3093  */
3094 static int
owl_estimate_life(struct local_owl_data * owl,struct local_owl_data * second_owl,struct owl_move_data vital_moves[MAX_MOVES],const char ** live_reason,int does_attack,struct eyevalue * probable_eyes,int * eyemin,int * eyemax)3095 owl_estimate_life(struct local_owl_data *owl,
3096 		  struct local_owl_data *second_owl,
3097     		  struct owl_move_data vital_moves[MAX_MOVES],
3098 		  const char **live_reason, int does_attack,
3099 		  struct eyevalue *probable_eyes, int *eyemin, int *eyemax)
3100 {
3101   SGFTree *save_sgf_dumptree = sgf_dumptree;
3102   int save_count_variations = count_variations;
3103   struct owl_move_data dummy_moves[MAX_MOVES];
3104   int other = OTHER_COLOR(owl->color);
3105 
3106   sgf_dumptree = NULL;
3107   count_variations = 0;
3108 
3109   owl_determine_life(owl, second_owl, does_attack, vital_moves,
3110 		     probable_eyes, eyemin, eyemax);
3111 
3112   matches_found = 0;
3113   memset(found_matches, 0, sizeof(found_matches));
3114 
3115   if (get_level() >= 8) {
3116     memset(owl->safe_move_cache, 0, sizeof(owl->safe_move_cache));
3117     if (!does_attack) {
3118       clear_owl_move_data(dummy_moves);
3119       matchpat(owl_shapes_callback, other,
3120 	       &owl_vital_apat_db, dummy_moves, owl->goal);
3121     }
3122     else if (max_eyes(probable_eyes) >= 2)
3123       matchpat(owl_shapes_callback, other,
3124 	       &owl_vital_apat_db, vital_moves, owl->goal);
3125   }
3126 
3127   if ((debug & DEBUG_EYES) && (debug & DEBUG_OWL))
3128     gprintf("owl: eyemin=%d matches_found=%d\n", *eyemin, matches_found);
3129   if (*eyemin >= matches_found)
3130     *eyemin -= matches_found;
3131   else
3132     *eyemin = 0;
3133 
3134   sgf_dumptree = save_sgf_dumptree;
3135   count_variations = save_count_variations;
3136 
3137   if (*eyemin >= 2
3138       || (*eyemin == 1 && min_eyes(probable_eyes) >= 4)
3139       || (stackp > owl_distrust_depth
3140 	  && min_eyes(probable_eyes) >= 2
3141 	  && !matches_found)) {
3142     if (*eyemin >= 2)
3143       *live_reason = "2 or more secure eyes";
3144     else if (*eyemin == 1 && min_eyes(probable_eyes) >= 4)
3145       *live_reason = "1 secure eye, likely >= 4";
3146     else if (stackp > owl_distrust_depth
3147 	     && min_eyes(probable_eyes) >= 2
3148 	     && !matches_found)
3149       *live_reason = "getting deep, looks lively";
3150     else
3151       gg_assert(0);
3152     return 1;
3153   }
3154 
3155   if (!does_attack
3156       && (*eyemin + matches_found >= 2
3157 	  || (*eyemin + matches_found == 1 && min_eyes(probable_eyes) >= 4)
3158       || (stackp > owl_distrust_depth
3159 	  && min_eyes(probable_eyes) >= 2))) {
3160     /* We are not yet alive only due to owl vital attack patterns matching.
3161      * Let's try to defend against it.
3162      */
3163     owl_add_move(vital_moves, dummy_moves[0].defense_pos,
3164 		 dummy_moves[0].value, dummy_moves[0].name,
3165 		 SAME_DRAGON_CONNECTED, NO_MOVE, 0, NO_MOVE, MAX_MOVES, NULL);
3166   }
3167 
3168   return 0;
3169 }
3170 
3171 
3172 /*
3173  * This function is invoked from do_owl_attack() and do_owl_defend()
3174  * for each node to determine whether the the dragon has sufficient
3175  * eye potential to live. It also generates vital moves to attack or
3176  * defend the eyes. There are two distinct sources for eyes. The first
3177  * is the eyespaces found by make_domains() and evaluated by
3178  * compute_eyes_pessimistic(). The second is the lunches found by
3179  * owl_find_lunches() and evaluated by sniff_lunch().
3180  *
3181  * The best guess of the eye potential is stored as an eyevalue in
3182  * *probable_eyes. This is not entirely reliable though since the
3183  * graph matching techniques in optics.c fail to understand subtleties
3184  * like atari inside the eyespace, cutting points in the wall, and
3185  * shortage of outside liberties. (The patterns in owl_vital_apats.db
3186  * are used to compensate for this. See do_owl_attack() and
3187  * do_owl_defend() for how these are used.) Also the estimates from
3188  * sniff_lunch() are fairly unreliable.
3189  *
3190  * A lower and upper bound on the number of eyes are returned in
3191  * *eyemin and *eyemax. The value of *eyemin must be offset by the
3192  * matches of owl_vital_apats.db. If that number is 2 or larger, we
3193  * should be certain of life.
3194  *
3195  * Vital moves to attack or defend eyes are returned in the moves[]
3196  * array. Also moves to reduce the uncertainty of the eye estimates
3197  * are added to this array, but with smaller move values. The
3198  * parameter does_attack determines whether to generate vital attack
3199  * moves or vital defense moves.
3200  *
3201  * The dragon is specified by the information in the owl struct. The
3202  * color of the dragon is passed in the color parameter.
3203  *
3204  * For use in the semeai code, a second dragon can be provided. Set
3205  * this to NULL when only one dragon is involved.
3206  */
3207 
3208 static void
owl_determine_life(struct local_owl_data * owl,struct local_owl_data * second_owl,int does_attack,struct owl_move_data * moves,struct eyevalue * probable_eyes,int * eyemin,int * eyemax)3209 owl_determine_life(struct local_owl_data *owl,
3210 		   struct local_owl_data *second_owl,
3211 		   int does_attack,
3212 		   struct owl_move_data *moves,
3213 		   struct eyevalue *probable_eyes, int *eyemin, int *eyemax)
3214 {
3215   int color = owl->color;
3216   struct eye_data *eye = owl->my_eye;
3217   int mw[BOARDMAX];  /* mark relevant eye origins */
3218   int mz[BOARDMAX];  /* mark potentially irrelevant eye origins */
3219   int vital_values[BOARDMAX];
3220   int dummy_eyemin = 0;
3221   int dummy_eyemax = 0;
3222   struct eyevalue eyevalue;
3223   struct eyevalue eyevalue_list[BOARDMAX/2];
3224   int eyes_attack_points[BOARDMAX/2];
3225   int pessimistic_min;
3226   int attack_point;
3227   int defense_point;
3228   int pos;
3229   int k;
3230   int lunch;
3231   int num_eyes = 0;
3232   int num_lunches = 0;
3233   int save_debug = debug;
3234   memset(vital_values, 0, sizeof(vital_values));
3235 
3236   if (!eyemin)
3237     eyemin = &dummy_eyemin;
3238   if (!eyemax)
3239     eyemax = &dummy_eyemax;
3240 
3241   *eyemin = 0;
3242   *eyemax = 0;
3243 
3244   /* Turn off eye debugging if we're not also debugging owl. */
3245   if (!(debug & DEBUG_OWL))
3246     debug &= ~DEBUG_EYES;
3247 
3248   clear_owl_move_data(moves);
3249 
3250   if (!owl->lunches_are_current)
3251     owl_find_lunches(owl);
3252 
3253   if (0) {
3254     for (k = 0; k < MAX_LUNCHES; k++)
3255       if (owl->lunch[k] != NO_MOVE)
3256 	gprintf("owl lunch %1m, attack %1m, defend %1m\n",
3257 		owl->lunch[k],
3258 		owl->lunch_attack_point[k],
3259 		owl->lunch_defense_point[k]);
3260   }
3261 
3262   owl_make_domains(owl, second_owl);
3263 
3264   owl_find_relevant_eyespaces(owl, mw, mz);
3265 
3266   /* Reset halfeye data. Set topological eye value to something big. */
3267   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
3268     if (ON_BOARD(pos)) {
3269       owl->half_eye[pos].type = 0;
3270       owl->half_eye[pos].value = 10.0;
3271     }
3272   }
3273 
3274   /* Find topological half eyes and false eyes. */
3275   find_half_and_false_eyes(color, eye, owl->half_eye, mw);
3276 
3277   /* The eyespaces may have been split or changed in other ways by the
3278    * topological analysis, so we need to regenerate them and once more
3279    * determine which ones are relevant.
3280    */
3281   partition_eyespaces(owl->my_eye, owl->color);
3282   owl_find_relevant_eyespaces(owl, mw, mz);
3283 
3284   set_eyevalue(probable_eyes, 0, 0, 0, 0);
3285 
3286   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
3287     if (ON_BOARD(pos) && mw[pos] > 1) {
3288       int value = 0;
3289       const char *reason = "";
3290       compute_eyes_pessimistic(pos, &eyevalue, &pessimistic_min,
3291 			       &attack_point, &defense_point,
3292 			       eye, owl->half_eye);
3293 
3294       /* If the eyespace is more in contact with own stones not in the goal,
3295        * than with ones in the goal, there is a risk that we can be cut off
3296        * from a major part of the eyespace. Thus we can't trust the opinion
3297        * of compute_eyes().
3298        *
3299        * (Obviously this is a quite fuzzy heuristic. With more accurate
3300        * connection analysis in the owl code we could do this more robustly.)
3301        */
3302       if (mw[pos] < mz[pos]
3303 	  || (mw[pos] < 3 * mz[pos] && mz[pos] > 5))
3304 	pessimistic_min = 0;
3305 
3306       /* It appears that this policy is needed no longer. */
3307 #if 0
3308       /* If this eyespace includes an owl inessential string, we must assume
3309        * that the pessimistic min is 0.
3310        */
3311       if (pessimistic_min > 0) {
3312 	for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++) {
3313 	  if (ON_BOARD(pos2)
3314 	      && eye[pos2].origin == pos
3315 	      && owl->inessential[pos2]) {
3316 	    pessimistic_min = 0;
3317 	    break;
3318 	  }
3319 	}
3320       }
3321 #endif
3322 
3323       eyes_attack_points[num_eyes] = NO_MOVE;
3324       eyevalue_list[num_eyes] = eyevalue;
3325       *eyemin += pessimistic_min;
3326 
3327       /* Fill in the value field for use by the owl_eyespace() function. */
3328       eye[pos].value = eyevalue;
3329 
3330       /* This shortcut has been disabled for two reasons:
3331        * 1. Due to the vital attack moves being able to later reduce
3332        * the *eyemin, we can't say that a certain *eyemin is
3333        * sufficient.
3334        * 2. This part of the code is in no way time critical.
3335        */
3336 #if 0
3337       /* Found two certain eyes---look no further. */
3338       if (*eyemin >= 2) {
3339 	debug = save_debug;
3340 	return 2;
3341       }
3342 #endif
3343 
3344       if (eye_move_urgency(&eyevalue)) {
3345 	value = 50;
3346 	if (max_eyes(&eyevalue) - min_eyes(&eyevalue) == 2)
3347 	  value = 70;
3348 	else if (max_eyes(&eyevalue) - pessimistic_min == 2)
3349 	  value = 60;
3350 	reason = "vital move";
3351       }
3352       else if (max_eyes(&eyevalue) != pessimistic_min) {
3353 	if (max_eyes(&eyevalue) - pessimistic_min == 2)
3354 	  value = 40;
3355 	else
3356 	  value = 30;
3357 	reason = "marginal eye space";
3358       }
3359 
3360       if (value > 0) {
3361 	if (does_attack && attack_point != NO_MOVE) {
3362 	  if (vital_values[attack_point] > 0) {
3363 	    value += vital_values[attack_point];
3364 	    if (value > 98)
3365 	      value = 98; /* Higher values may get special interpretation. */
3366 	  }
3367 
3368 	  TRACE("%s at %1m, score %d (eye at %1m, value %s, pessimistic_min %d)\n",
3369 		reason, attack_point, value,
3370 		pos, eyevalue_to_string(&eyevalue), pessimistic_min);
3371 
3372 	  if (eye[attack_point].marginal
3373 	      && modify_stupid_eye_vital_point(owl, &attack_point, 1))
3374 	    TRACE("vital point looked stupid, moved it to %1m\n",
3375 		  attack_point);
3376 
3377 	  if (attack_point != NO_MOVE) {
3378 	    owl_add_move(moves, attack_point, value, reason,
3379 			 SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE,
3380 			 0, NO_MOVE, MAX_MOVES, NULL);
3381 	    vital_values[attack_point] = value;
3382 	    eyes_attack_points[num_eyes] = attack_point;
3383 	  }
3384 	}
3385 
3386 	/* The reason for the last set of tests is that we don't
3387 	 * want to play a self atari in e.g. this position
3388 	 *
3389 	 * |XXX.
3390 	 * |OOX.
3391 	 * |.OX.
3392 	 * |XOXX
3393 	 * |XOOX
3394 	 * |O*OX
3395 	 * +----
3396 	 *
3397 	 * but it's okay in this position
3398 	 *
3399 	 * |XXXXX
3400 	 * |....X
3401 	 * |OOOOX
3402 	 * |.XXOX
3403 	 * |.*XOX
3404 	 * +-----
3405 	 *
3406 	 * In both cases * is the vital point according to the graph
3407 	 * matching. The significant difference is that in the first
3408 	 * case the vital point is adjacent to stones in the goal.
3409 	 */
3410 	else if (!does_attack
3411 		 && defense_point != NO_MOVE
3412 		 && board[defense_point] == EMPTY
3413 		 && (!liberty_of_goal(defense_point, owl)
3414 		     || !is_self_atari(defense_point, color)
3415 		     || is_ko(defense_point, color, NULL)
3416 		     || safe_move(defense_point, color) != 0)) {
3417 	  if (vital_values[defense_point] > 0) {
3418 	    value += vital_values[defense_point];
3419 	    if (value > 98)
3420 	      value = 98; /* Higher values may get special interpretation. */
3421 	  }
3422 
3423 	  TRACE("%s at %1m, score %d (eye at %1m, value %s, pessimistic_min %d)\n",
3424 		reason, defense_point, value, pos,
3425 		eyevalue_to_string(&eyevalue), pessimistic_min);
3426 
3427 	  if ((eye[defense_point].marginal
3428 	       || eye[defense_point].origin != pos)
3429 	      && modify_stupid_eye_vital_point(owl, &defense_point, 0))
3430 	    TRACE("vital point looked stupid, moved it to %1m\n",
3431 		  defense_point);
3432 
3433 	  if (defense_point != NO_MOVE) {
3434 	    owl_add_move(moves, defense_point, value, reason,
3435 			 SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE,
3436 			 0, NO_MOVE, MAX_MOVES, NULL);
3437 	    vital_values[defense_point] = value;
3438 	  }
3439 	}
3440       }
3441       num_eyes++;
3442     }
3443   }
3444 
3445   /* Sniff each lunch for nutritional value. The assumption is that
3446    * capturing the lunch is gote, therefore the number of half eyes
3447    * equals the MINIMUM number of eyes yielded by the resulting eye
3448    * space.
3449    */
3450   {
3451     for (lunch = 0; (lunch < MAX_LUNCHES); lunch++)
3452       if (owl->lunch[lunch] != NO_MOVE
3453 	  && owl->lunch_defense_point[lunch] != NO_MOVE) {
3454 	int value = 0;
3455 	int lunch_min;
3456 	int lunch_probable;
3457 	int lunch_max;
3458 	struct eyevalue e;
3459 	sniff_lunch(owl->lunch[lunch],
3460 		    &lunch_min, &lunch_probable, &lunch_max, owl);
3461 
3462 	set_eyevalue(&e, 0, 0, lunch_probable, lunch_probable);
3463 	*eyemax += lunch_max;
3464 
3465 	if (lunch_probable == 0) {
3466 	  if (countstones(owl->lunch[lunch]) == 1)
3467 	    continue;
3468 	  value = 20;
3469 	}
3470 	else if (lunch_probable == 1 && lunch_max == 1)
3471 	  value = 60 + countstones(owl->lunch[lunch]);
3472 	else if (lunch_probable == 1 && lunch_max == 2)
3473 	  value = 70 + countstones(owl->lunch[lunch]);
3474 	else
3475 	  value = 75 + countstones(owl->lunch[lunch]);
3476 
3477 	if (owl->lunch_attack_code[lunch] != WIN)
3478 	  value -= 10;
3479 
3480 	if (does_attack) {
3481 	  defense_point = improve_lunch_defense(owl->lunch[lunch],
3482 						owl->lunch_defense_point[lunch]);
3483 
3484 	  if (vital_values[defense_point]) {
3485 	    /* The point here is that the move which saves the lunch also
3486 	     * attacks an eye. So this attack move reduces the global eye
3487 	     * potential. The eyes arithmetic for probable_eyes has then
3488 	     * to be adapted accordingly.
3489 	     */
3490 	    int ne;
3491 	    for (ne = 0; ne < num_eyes - num_lunches; ne++)
3492 	      if (eyes_attack_points[ne] == defense_point)
3493 		break;
3494 	    gg_assert(ne < num_eyes - num_lunches);
3495 	    /* merge eye values */
3496 	    add_eyevalues(&eyevalue_list[ne], &e, &eyevalue_list[ne]);
3497 	    /* and adjust */
3498 	    eyevalue_list[ne].a = 0;
3499 	    eyevalue_list[ne].b = 0;
3500 	  }
3501 	  else {
3502 	    num_lunches++;
3503 	    eyevalue_list[num_eyes++] = e;
3504 	  }
3505 
3506 	  TRACE("save lunch at %1m with %1m, score %d, probable eye %d, max eye %d\n",
3507 		owl->lunch[lunch], defense_point, value,
3508 		lunch_probable, lunch_max);
3509 	  owl_add_move(moves, defense_point, value,
3510 	      	       "save lunch", SAME_DRAGON_MAYBE_CONNECTED,
3511 		       NO_MOVE, 0, NO_MOVE, MAX_MOVES, NULL);
3512 	}
3513 	else {
3514 	  attack_point = improve_lunch_attack(owl->lunch[lunch],
3515 					      owl->lunch_attack_point[lunch]);
3516 	  TRACE("eat lunch at %1m with %1m, score %d, probable eye %d, max eye %d\n",
3517 		owl->lunch[lunch], attack_point, value,
3518 		lunch_probable, lunch_max);
3519 	  /* We only remember the lunch for owl_update_goal() if the lunch
3520 	   * cannot be defended with ko after the move.
3521 	   * If we capture the lunch by an illegal ko capture, we become
3522 	   * ko master with this move, and hence the above is true.
3523 	   */
3524 	  if (owl->lunch_attack_code[lunch] ==  WIN
3525 	      || is_illegal_ko_capture(attack_point, owl->color))
3526 	    owl_add_move(moves, attack_point, value, "eat lunch",
3527 			 SAME_DRAGON_MAYBE_CONNECTED, owl->lunch[lunch],
3528 			 0, NO_MOVE, MAX_MOVES, NULL);
3529 	  else
3530 	    owl_add_move(moves, attack_point, value, "eat lunch",
3531 			 SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE, 0, NO_MOVE,
3532 			 MAX_MOVES, NULL);
3533 	  num_lunches++;
3534 	  eyevalue_list[num_eyes++] = e;
3535 	}
3536       }
3537   }
3538 
3539   /* now, totalize the eye potential */
3540   {
3541     int ne;
3542     for (ne = 0; ne < num_eyes - num_lunches; ne++)
3543       add_eyevalues(probable_eyes, &eyevalue_list[ne], probable_eyes);
3544 
3545     *eyemax += max_eyes(probable_eyes);
3546     /* If we have at least two different eyespaces and can create one eye
3547      * in sente, we assume there's a chance to create another one. This is
3548      * needed because optics code don't know about eyespaces influencing
3549      * each other and combination moves (i.e. double threats to create an
3550      * eye).
3551      */
3552     if (num_eyes - num_lunches > 1 && max_eye_threat(probable_eyes) > 1)
3553       *eyemax += 1;
3554 
3555     for (; ne < num_eyes; ne++)
3556       add_eyevalues(probable_eyes, &eyevalue_list[ne], probable_eyes);
3557   }
3558 
3559   debug = save_debug;
3560 }
3561 
3562 
3563 /* The eyespaces we want to evaluate are the ones which
3564  * are adjacent to the dragon (whose stones comprise the
3565  * support of goal) which are not GRAY bordered. These
3566  * are the eyespaces of the dragon. Now we find their
3567  * origins.
3568  *
3569  * It is required that there are at least two distinct connections,
3570  * adjacent or diagonal, between non-marginal eyespace vertices and
3571  * stones of the goal dragon. Otherwise there is a risk that we
3572  * include irrelevant eye spaces.
3573  */
3574 
3575 static void
owl_find_relevant_eyespaces(struct local_owl_data * owl,int mw[BOARDMAX],int mz[BOARDMAX])3576 owl_find_relevant_eyespaces(struct local_owl_data *owl,
3577 			    int mw[BOARDMAX], int mz[BOARDMAX])
3578 {
3579   int pos;
3580   int eye_color;
3581   int k;
3582   struct eye_data *eye = owl->my_eye;
3583 
3584   if (owl->color == WHITE)
3585     eye_color = WHITE;
3586   else
3587     eye_color = BLACK;
3588 
3589   memset(mw, 0, BOARDMAX * sizeof(mw[0]));
3590   memset(mz, 0, BOARDMAX * sizeof(mz[0]));
3591   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
3592     if (board[pos] == owl->color) {
3593       for (k = 0; k < 8; k++) {
3594 	int pos2 = pos + delta[k];
3595 	if (ON_BOARD(pos2)
3596 	    && eye[pos2].color == eye_color
3597 	    && !eye[pos2].marginal) {
3598 	  if (owl->goal[pos])
3599 	    mw[eye[pos2].origin]++;
3600 	  else
3601 	    mz[eye[pos2].origin]++;
3602 	}
3603       }
3604     }
3605   }
3606 }
3607 
3608 /* Case 1.
3609  *
3610  * The optics code occasionally comes up with stupid vital moves, like
3611  * a in this position:
3612  *
3613  * ----+
3614  * O...|
3615  * OX..|
3616  * OX..|
3617  * O.X.|
3618  * .O.a|
3619  * ....|
3620  *
3621  * This function moves such moves to the second line.
3622  *
3623  * Case 2.
3624  *
3625  * In this position the optics code can suggest the empty 1-2 point as
3626  * vital move for the eyespace on the right edge. That is okay for attack
3627  * but obviously not for defense.
3628  *
3629  * ----+
3630  * XO.O|
3631  * XOOX|
3632  * XXO.|
3633  * .XOO|
3634  * .XXX|
3635  *
3636  * Case 3.
3637  *
3638  * Playing into a snapback is usually not an effective way to destroy
3639  * an eye.
3640  *
3641  * XOOO|
3642  * XOXX|
3643  * XXO.|
3644  * .XXO|
3645  * ....|
3646  *
3647  * This function changes the attack point to NO_MOVE (i.e. removes it).
3648  */
3649 static int
modify_stupid_eye_vital_point(struct local_owl_data * owl,int * vital_point,int is_attack_point)3650 modify_stupid_eye_vital_point(struct local_owl_data *owl, int *vital_point,
3651 			      int is_attack_point)
3652 {
3653   int up;
3654   int right;
3655   int k;
3656   int libs[2];
3657 
3658   /* Case 1. */
3659   for (k = 0; k < 4; k++) {
3660     up = delta[k];
3661     if (ON_BOARD(*vital_point - up))
3662       continue;
3663 
3664     if (board[*vital_point + up] != EMPTY)
3665       continue;
3666 
3667     right = delta[(k+1) % 4];
3668 
3669     if (board[*vital_point + right] != EMPTY
3670 	|| board[*vital_point - right] != EMPTY)
3671       continue;
3672 
3673     if (board[*vital_point + 2 * up] != EMPTY
3674 	|| board[*vital_point + up + right] != EMPTY
3675 	|| board[*vital_point + up - right] != EMPTY) {
3676       *vital_point += up;
3677       return 1;
3678     }
3679   }
3680 
3681   /* Case 2. */
3682   if (!is_attack_point) {
3683     if (approxlib(*vital_point, OTHER_COLOR(owl->color), 1, NULL) == 0) {
3684       for (k = 4; k < 8; k++) {
3685 	int pos = *vital_point + delta[k];
3686 	if (board[pos] == OTHER_COLOR(owl->color)
3687 	    && countlib(pos) == 1) {
3688 	  findlib(pos, 1, vital_point);
3689 	  return 1;
3690 	}
3691       }
3692     }
3693   }
3694 
3695   /* Case 3. */
3696   if (is_attack_point
3697       && does_capture_something(*vital_point, OTHER_COLOR(owl->color))
3698       && accuratelib(*vital_point, OTHER_COLOR(owl->color), 2, libs) == 1
3699       && !attack(libs[0], NULL)) {
3700     *vital_point = NO_MOVE;
3701     return 1;
3702   }
3703 
3704   return 0;
3705 }
3706 
3707 
3708 /* The purpose of this function is to avoid moves which needlessly
3709  * fill in an eye. A typical example, from ld_owl:188, is
3710  *
3711  * -----+
3712  * .O.OX|
3713  * XOOXX|
3714  * XXOOX|
3715  * .XXO.|
3716  * ..XOO|
3717  * ..XXX|
3718  *
3719  * where various patterns manage to propose the eye-filling move on
3720  * the top edge instead of capturing the opponent stones and get two
3721  * solid eyes. This function modifies the move accordingly.
3722  */
3723 static int
modify_eyefilling_move(int * move,int color)3724 modify_eyefilling_move(int *move, int color)
3725 {
3726   int k;
3727   int r;
3728   int other = OTHER_COLOR(color);
3729   /* Only do this for a small eye. */
3730   for (k = 0; k < 4; k++)
3731     if (ON_BOARD(*move + delta[k]) && board[*move + delta[k]] != color)
3732       return 0;
3733 
3734   for (r = 4; r < 8; r++)
3735     if (board[*move + delta[r]] == other
3736 	&& countlib(*move + delta[r]) == 1) {
3737       for (k = 0; k < 4; k++)
3738 	if (board[*move + delta[k]] == color
3739 	    && countlib(*move + delta[k]) == 1
3740 	    && !adjacent_strings(*move + delta[r], *move + delta[k]))
3741 	  break;
3742 
3743       if (k == 4) {
3744 	int new_move;
3745 	findlib(*move + delta[r], 1, &new_move);
3746 	TRACE("Changing eyefilling move at %1m to capture at %1m.\n",
3747 	      *move, new_move);
3748 	*move = new_move;
3749 	return 1;
3750       }
3751     }
3752 
3753   return 0;
3754 }
3755 
3756 
3757 /*
3758  * Generates up to max_moves moves, attempting to attack or defend the goal
3759  * dragon. The found moves are put in moves, an array of owl_move_data
3760  * structs, starting in the position 'initial'.  The entries in the array are
3761  * sorted by value with moves[initial] having highest priority. When no more
3762  * moves are available this is indicated by value and coordinates in the array
3763  * being -1.
3764  *
3765  * This function automatically initializes the owl_safe_move cache the
3766  * pattern list. WATCH OUT: This has to be matched with a call to
3767  * close_pattern_list(pattern_list)!!!
3768  *
3769  * Returns 1 if at least one move is found, or 0 if no move is found.
3770  */
3771 
3772 static void
owl_shapes(struct matched_patterns_list_data * pattern_list,struct owl_move_data moves[MAX_MOVES],int color,struct local_owl_data * owl,struct pattern_db * type)3773 owl_shapes(struct matched_patterns_list_data *pattern_list,
3774            struct owl_move_data moves[MAX_MOVES],
3775 	   int color, struct local_owl_data *owl, struct pattern_db *type)
3776 {
3777   SGFTree *save_sgf_dumptree = sgf_dumptree;
3778   int save_count_variations = count_variations;
3779   sgf_dumptree = NULL;
3780   count_variations = 0;
3781 
3782   current_owl_data = owl;
3783 
3784   clear_owl_move_data(moves);
3785 
3786   /* We must reset the owl safe_move_cache before starting the
3787    * pattern matching. The cache is used by owl_shapes_callback().
3788    */
3789   memset(owl->safe_move_cache, 0, sizeof(owl->safe_move_cache));
3790   init_pattern_list(pattern_list);
3791   matchpat(collect_owl_shapes_callbacks, color, type, pattern_list, owl->goal);
3792 
3793   sgf_dumptree = save_sgf_dumptree;
3794   count_variations = save_count_variations;
3795 }
3796 
3797 
3798 /* This function contains all the expensive checks for a matched pattern. */
3799 static int
check_pattern_hard(int move,int color,struct pattern * pattern,int ll)3800 check_pattern_hard(int move, int color, struct pattern *pattern, int ll)
3801 {
3802   int constraint_checked = 0;
3803   int safe_move_checked = 0;
3804 
3805   /* The very first check is whether we can disregard the pattern due
3806    * due to an owl safe_move_cache lookup.
3807    */
3808   if (!(pattern->class & CLASS_s))
3809     if (current_owl_data->safe_move_cache[move]) {
3810       if (current_owl_data->safe_move_cache[move] == 1)
3811         return 0;
3812       else
3813         safe_move_checked = 1;
3814     }
3815 
3816   /* If the constraint is cheap to check, we do this first. */
3817   if ((pattern->autohelper_flag & HAVE_CONSTRAINT)
3818       && pattern->constraint_cost < 0.45) {
3819     if (!pattern->autohelper(ll, move, color, 0))
3820       return 0;
3821     constraint_checked = 1;
3822   }
3823 
3824   /* For sacrifice patterns, the survival of the stone to be played is
3825    * not checked. Otherwise we discard moves which can be captured.
3826    * Illegal ko captures are accepted for ko analysis.
3827    */
3828   if (!(pattern->class & CLASS_s) && !safe_move_checked) {
3829     if (!owl_safe_move(move, color)) {
3830       if (0)
3831 	TRACE("  move at %1m wasn't safe, discarded\n", move);
3832       return 0;
3833     }
3834     if (!is_legal(move, color)) {
3835       if (0)
3836 	TRACE("  move at %1m wasn't legal, discarded\n", move);
3837       return 0;
3838     }
3839   }
3840 
3841   /* For class n patterns, the pattern is contingent on an opponent
3842    * move at * not being captured.
3843    *
3844    * We can't use owl_safe_move() here because we would try the wrong color.
3845    */
3846   if (pattern->class & CLASS_n) {
3847     if (safe_move(move, OTHER_COLOR(color)) == 0) {
3848       if (0)
3849 	TRACE("  opponent can't play safely at %1m, move discarded\n", move);
3850       return 0;
3851     }
3852   }
3853 
3854   /* If the pattern has a constraint, call the autohelper to see
3855    * if the pattern must be rejected.
3856    */
3857   if ((pattern->autohelper_flag & HAVE_CONSTRAINT) && !constraint_checked)
3858     if (!pattern->autohelper(ll, move, color, 0))
3859       return 0;
3860   return 1;
3861 }
3862 
3863 
3864 /* This initializes a pattern list, allocating memory for 200 patterns.
3865  * If more patterns need to be stored, collect_owl_shapes_callbacks will
3866  * dynamically reallocate additional memory.
3867  * The space for list->pattern_list is allocated here.
3868  *
3869  * This function is automatically called from owl_shapes. Every call here
3870  * has to be matched by a call to close_pattern_list below.
3871  */
3872 static void
init_pattern_list(struct matched_patterns_list_data * list)3873 init_pattern_list(struct matched_patterns_list_data *list)
3874 {
3875   gg_assert(!list->initialized);
3876 
3877   list->counter = 0;
3878   list->used = 0;
3879 
3880   list->pattern_list = malloc(200 * sizeof(list->pattern_list[0]));
3881   list->list_size = 200;
3882   gg_assert(list->pattern_list != NULL);
3883   list->pattern_heap = NULL;
3884 
3885   if (0)
3886     gprintf("List at %x has new array at %x\n", list, list->pattern_list);
3887 
3888   list->initialized = 1;
3889 }
3890 
3891 
3892 /* This function has to get called before the memory of *list is freed
3893  * in the calling function.
3894  */
3895 static void
close_pattern_list(int color,struct matched_patterns_list_data * list)3896 close_pattern_list(int color, struct matched_patterns_list_data *list)
3897 {
3898   if (list->initialized) {
3899     if (0)
3900       gprintf("%d patterns matched, %d patterns checked\n", list->counter,
3901 	      list->used);
3902     if (0)
3903       gprintf("Pattern list at %x freed for list at %x\n",
3904 	      list->pattern_list, list);
3905     if (allpats && verbose) {
3906       int i;
3907       int found_one = 0;
3908       SGFTree *save_sgf_dumptree = sgf_dumptree;
3909       int save_count_variations = count_variations;
3910       sgf_dumptree = NULL;
3911       count_variations = 0;
3912 
3913       if (!current_owl_data->lunches_are_current)
3914 	owl_find_lunches(current_owl_data);
3915 
3916       if (!list->pattern_heap)
3917 	pattern_list_build_heap(list);
3918 
3919       for (i = 0; i < list->heap_num_patterns; i++)
3920 	if (check_pattern_hard(list->pattern_heap[i]->move, color,
3921 	     		       list->pattern_heap[i]->pattern,
3922 			       list->pattern_heap[i]->ll)) {
3923 	  if (!found_one) {
3924 	    TRACE("Remaining valid (but unused) patterns at stack: ");
3925 	    dump_stack();
3926 	    found_one = 1;
3927 	  }
3928       	  TRACE("Pattern %s found at %1m with value %d\n",
3929 	        list->pattern_heap[i]->pattern->name,
3930 	        list->pattern_heap[i]->move,
3931 	        (int) list->pattern_heap[i]->pattern->value);
3932 	}
3933 
3934       sgf_dumptree = save_sgf_dumptree;
3935       count_variations = save_count_variations;
3936     }
3937 
3938     free(list->pattern_list);
3939     free(list->pattern_heap);
3940   }
3941   list->counter = -1;
3942 }
3943 
3944 
3945 /* Can be called from gdb for debugging:
3946  * (gdb) set dump_pattern_list(&shape_patterns)
3947  */
3948 void
dump_pattern_list(struct matched_patterns_list_data * list)3949 dump_pattern_list(struct matched_patterns_list_data *list)
3950 {
3951   int i;
3952   struct matched_pattern_data *matched_pattern;
3953   if (!list->initialized)
3954     return;
3955   gprintf("%oList size %d. %d Patterns in list, %d have been used.",
3956 	  list->list_size, list->counter, list->used);
3957   for (i = 0; i < list->counter; i++) {
3958     matched_pattern = &list->pattern_list[i];
3959     gprintf("%o\n  Pattern %s (orient. %d) at %1m, value %f.",
3960 	    matched_pattern->pattern->name, matched_pattern->ll,
3961 	    matched_pattern->move, matched_pattern->pattern->value);
3962     if (matched_pattern->next_pattern_index != -1)
3963       gprintf("%o * ");
3964   }
3965   gprintf("%o\n");
3966 
3967   gprintf("%oCurrent heap ordering: \n");
3968   for (i = 0; i < list->heap_num_patterns; i++) {
3969     matched_pattern = list->pattern_heap[i];
3970     gprintf("%o %s (%1m), %f; ", matched_pattern->pattern->name,
3971 	    matched_pattern->move, matched_pattern->pattern->value);
3972   }
3973   gprintf("\n");
3974 }
3975 
3976 
3977 /* This function stores a found pattern in the list for later evaluation.
3978  * The only processing done is computing the position of the move, and
3979  * forgetting the color.
3980  */
3981 static void
collect_owl_shapes_callbacks(int anchor,int color,struct pattern * pattern,int ll,void * data)3982 collect_owl_shapes_callbacks(int anchor, int color, struct pattern *pattern,
3983                              int ll, void *data)
3984 {
3985   struct matched_patterns_list_data *matched_patterns = data;
3986   struct matched_pattern_data *next_pattern;
3987 
3988   UNUSED(color); /* The calling function has to remember that. */
3989 
3990   if (matched_patterns->counter >= matched_patterns->list_size) {
3991     matched_patterns->list_size += 100;
3992     matched_patterns->pattern_list
3993         = realloc(matched_patterns->pattern_list,
3994 	          matched_patterns->list_size
3995 	          * sizeof(matched_patterns->pattern_list[0]));
3996   }
3997 
3998   next_pattern = &matched_patterns->pattern_list[matched_patterns->counter];
3999   next_pattern->move	= AFFINE_TRANSFORM(pattern->move_offset, ll, anchor);
4000   next_pattern->value	= pattern->value;
4001   next_pattern->ll	= ll;
4002   next_pattern->anchor	= anchor;
4003   next_pattern->pattern	= pattern;
4004   next_pattern->next_pattern_index = -1;
4005 
4006   matched_patterns->counter++;
4007 }
4008 
4009 
4010 #define MAX_STORED_REASONS	4
4011 
4012 static int
valuate_combinable_pattern_chain(struct matched_patterns_list_data * list,int pos)4013 valuate_combinable_pattern_chain(struct matched_patterns_list_data *list,
4014 				 int pos)
4015 {
4016   /* FIXME: This is just a first attempt at pattern combination.
4017    *	    Improve it.  The first idea is to differentiate between
4018    *	    move reason types.  For instance, when there is a secure
4019    *	    eye already, a threat to create another is more severe.
4020    *
4021    *	    This will certainly involve splitting the function into
4022    *	    attack and defense versions.
4023    */
4024 
4025   int pattern_index = list->first_pattern_index[pos];
4026   int num_capture_threats = 0;
4027   int capture_threats[MAX_STORED_REASONS];
4028   int num_eye_threats = 0;
4029   int eye_threats[MAX_STORED_REASONS];
4030   int num_reverse_sente = 0;
4031   int reverse_sente_against[MAX_STORED_REASONS];
4032   int num_move_reasons;
4033   float full_value = 0.0;
4034 
4035   ASSERT1(pattern_index != -1, pos);
4036 
4037   do {
4038     struct matched_pattern_data *pattern_data = (list->pattern_list
4039 						 + pattern_index);
4040     struct pattern_attribute *attribute;
4041 
4042     /* Skip patterns that haven't passed constraint validation. */
4043     if (pattern_data->pattern) {
4044       for (attribute = pattern_data->pattern->attributes;
4045 	   attribute->type != LAST_ATTRIBUTE;
4046 	   attribute++) {
4047 	int k;
4048 	int target = AFFINE_TRANSFORM(attribute->offset, pattern_data->ll,
4049 				      pattern_data->move);
4050 
4051 	switch (attribute->type) {
4052 	case THREATENS_TO_CAPTURE:
4053 	  if (num_capture_threats < MAX_STORED_REASONS) {
4054 	    ASSERT1(IS_STONE(board[target]), target);
4055 	    target = find_origin(target);
4056 
4057 	    for (k = 0; k < num_capture_threats; k++) {
4058 	      if (capture_threats[k] == target)
4059 		break;
4060 	    }
4061 
4062 	    if (k == num_capture_threats) {
4063 	      capture_threats[num_capture_threats++] = target;
4064 	      full_value += pattern_data->pattern->value;
4065 	    }
4066 	  }
4067 
4068 	  break;
4069 
4070 	case THREATENS_EYE:
4071 	  if (num_eye_threats < MAX_STORED_REASONS) {
4072 	    target = current_owl_data->my_eye[target].origin;
4073 
4074 	    for (k = 0; k < num_eye_threats; k++) {
4075 	      if (eye_threats[k] == target)
4076 		break;
4077 	    }
4078 
4079 	    if (k == num_eye_threats) {
4080 	      eye_threats[num_eye_threats++] = target;
4081 	      full_value += pattern_data->pattern->value;
4082 	    }
4083 	  }
4084 
4085 	  break;
4086 
4087 	case REVERSE_SENTE:
4088 	  if (num_reverse_sente < MAX_STORED_REASONS) {
4089 	    ASSERT1(board[target] == EMPTY, target);
4090 
4091 	    for (k = 0; k < num_reverse_sente; k++) {
4092 	      if (reverse_sente_against[k] == target)
4093 		break;
4094 	    }
4095 
4096 	    if (k == num_reverse_sente) {
4097 	      reverse_sente_against[num_reverse_sente++] = target;
4098 	      full_value += pattern_data->pattern->value;
4099 	    }
4100 	  }
4101 
4102 	  break;
4103 
4104 	default:
4105 	  gg_assert(0);
4106 	}
4107       }
4108     }
4109 
4110     pattern_index = pattern_data->next_pattern_index;
4111   } while (pattern_index >= 0);
4112 
4113 
4114   num_move_reasons = num_capture_threats + num_eye_threats + num_reverse_sente;
4115   if (num_move_reasons <= 1) {
4116     /* Not much to combine, eh? */
4117     return 0;
4118   }
4119 
4120   if (num_move_reasons == 2)
4121     return gg_min(gg_normalize_float2int(full_value, 1.0), 75);
4122   if (num_move_reasons == 3)
4123     return gg_min(gg_normalize_float2int(full_value * 0.85, 1.0), 90);
4124   return gg_min(gg_normalize_float2int(full_value * 0.75, 1.0), 99);
4125 }
4126 
4127 
4128 #if USE_BDIST
4129 
4130 /* Compute the squared of the distance of a point on the board to the
4131  * center of the board.
4132  */
4133 static int
bdist(int move)4134 bdist(int move)
4135 {
4136   /* i = 0:              idist = - (board_size - 1)
4137    * i = board_size -1 : idist =    board_size - 1
4138    */
4139   int idist = 2*I(move) - board_size + 1;
4140   int jdist = 2*J(move) - board_size + 1;
4141   return idist*idist + jdist*jdist;
4142 }
4143 
4144 
4145 /* NOTICE : In order to stabilize the regression test results,
4146  * arbitrary parameters like pattern memory address and move position
4147  * have been included in the sorting algorithm.
4148  */
4149 
4150 #define BETTER_PATTERN(a, b)				\
4151   ((a)->value > (b)->value				\
4152    || ((a)->value == (b)->value				\
4153        && ((a)->pattern < (b)->pattern			\
4154 	   || ((a)->pattern == (b)->pattern		\
4155 	       && ((a)->bdist < (b)->bdist		\
4156 		   || ((a)->bdist == (b)->bdist		\
4157 		       && (a)->move < (b)->move))))))
4158 
4159 #else	/* not USE_BDIST */
4160 
4161 #define BETTER_PATTERN(a, b)				\
4162   ((a)->value > (b)->value				\
4163    || ((a)->value == (b)->value				\
4164        && ((a)->pattern < (b)->pattern			\
4165 	   || ((a)->pattern == (b)->pattern		\
4166 	       && (a)->move < (b)->move))))
4167 
4168 #endif	/* not USE_BDIST */
4169 
4170 
4171 static void
pattern_list_prepare(struct matched_patterns_list_data * list)4172 pattern_list_prepare(struct matched_patterns_list_data *list)
4173 {
4174   int k;
4175   int pos;
4176 
4177   list->heap_num_patterns = 0;
4178 
4179   /* This is more than needed in case of (combinable) pattern chains,
4180    * but it is easier to allocate more than to count real number of
4181    * heap elements first.
4182    */
4183   if (list->counter > 0) { /* avoid malloc(0) */
4184     list->pattern_heap = malloc(list->counter * sizeof(*(list->pattern_heap)));
4185     gg_assert(list->pattern_heap != NULL);
4186   }
4187   else {
4188     /* free() has defined behaviour for NULL pointer */
4189     list->pattern_heap = NULL;
4190   }
4191 
4192   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
4193     list->first_pattern_index[pos] = -1;
4194 
4195   for (k = 0; k < list->counter; k++) {
4196     int move = list->pattern_list[k].move;
4197 
4198 #if USE_BDIST
4199     list->pattern_list[k].bdist = bdist(move);
4200 #endif
4201 
4202     /* Allocate heap elements for normal patterns.  Link combinable
4203      * patterns in chains.
4204      */
4205     if (!(list->pattern_list[k].pattern->class & CLASS_c))
4206       list->pattern_heap[list->heap_num_patterns++] = &list->pattern_list[k];
4207     else {
4208       list->pattern_list[k].next_pattern_index = list->first_pattern_index[move];
4209       list->first_pattern_index[move] = k;
4210     }
4211   }
4212 
4213   /* Allocate one heap element for each chain of combinable patterns
4214    * and calculate initial chain values (as if all patterns passed
4215    * constraint validation).
4216    */
4217   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
4218     if (list->first_pattern_index[pos] != -1) {
4219       struct matched_pattern_data *pattern_data
4220 	= &list->pattern_list[list->first_pattern_index[pos]];
4221 
4222       pattern_data->value = valuate_combinable_pattern_chain(list, pos);
4223       list->pattern_heap[list->heap_num_patterns++] = pattern_data;
4224     }
4225   }
4226 
4227   if (list->heap_num_patterns > 0)
4228     pattern_list_build_heap(list);
4229 }
4230 
4231 
4232 /* Fast heap building.  Takes O(n) only. */
4233 static void
pattern_list_build_heap(struct matched_patterns_list_data * list)4234 pattern_list_build_heap(struct matched_patterns_list_data *list)
4235 {
4236   int k;
4237   int limit = list->heap_num_patterns / 2;
4238 
4239   for (k = limit; --k >= 0;) {
4240     int parent;
4241     int child;
4242     struct matched_pattern_data *pattern_data = list->pattern_heap[k];
4243 
4244     for (parent = k; parent < limit; parent = child) {
4245       child = 2 * parent + 1;
4246       if (child + 1 < list->heap_num_patterns
4247 	  && BETTER_PATTERN(list->pattern_heap[child + 1],
4248 			    list->pattern_heap[child]))
4249 	child++;
4250 
4251       if (BETTER_PATTERN(pattern_data, list->pattern_heap[child]))
4252 	break;
4253 
4254       list->pattern_heap[parent] = list->pattern_heap[child];
4255     }
4256 
4257     list->pattern_heap[parent] = pattern_data;
4258   }
4259 }
4260 
4261 
4262 /* Pops patterns list's heap once. */
4263 static void
pattern_list_pop_heap_once(struct matched_patterns_list_data * list)4264 pattern_list_pop_heap_once(struct matched_patterns_list_data *list)
4265 {
4266   int parent;
4267   int child;
4268 
4269   list->heap_num_patterns--;
4270   for (parent = 0; 2 * parent + 1 < list->heap_num_patterns; parent = child) {
4271     child = 2 * parent + 1;
4272     if (BETTER_PATTERN(list->pattern_heap[child + 1],
4273 		       list->pattern_heap[child]))
4274       child++;
4275 
4276     if (BETTER_PATTERN(list->pattern_heap[list->heap_num_patterns],
4277 		       list->pattern_heap[child]))
4278       break;
4279 
4280     list->pattern_heap[parent] = list->pattern_heap[child];
4281   }
4282 
4283   list->pattern_heap[parent] = list->pattern_heap[list->heap_num_patterns];
4284 }
4285 
4286 
4287 /* Sink top element of heap because it got devalued.  This happens
4288  * when a combinable pattern doesn't pass check_pattern_hard() -- it
4289  * is no longer counted and its whole chain's value is reduced.
4290  */
4291 static void
pattern_list_sink_heap_top_element(struct matched_patterns_list_data * list)4292 pattern_list_sink_heap_top_element(struct matched_patterns_list_data *list)
4293 {
4294   int parent;
4295   int child;
4296   struct matched_pattern_data *heap_top_element = list->pattern_heap[0];
4297 
4298   for (parent = 0; 2 * parent + 1 < list->heap_num_patterns; parent = child) {
4299     child = 2 * parent + 1;
4300     if (child + 1 < list->heap_num_patterns
4301 	&& BETTER_PATTERN(list->pattern_heap[child + 1],
4302 			  list->pattern_heap[child]))
4303       child++;
4304 
4305     if (BETTER_PATTERN(heap_top_element,
4306 		       list->pattern_heap[child]))
4307       break;
4308 
4309     list->pattern_heap[parent] = list->pattern_heap[child];
4310   }
4311 
4312   list->pattern_heap[parent] = heap_top_element;
4313 }
4314 
4315 
4316 /* Adds all goal strings in the pattern area to the cuts[] list, if there
4317  * is more than one.
4318  */
4319 static void
generate_cut_list(struct pattern * pattern,int ll,int anchor,int cuts[MAX_CUTS],struct local_owl_data * owl)4320 generate_cut_list(struct pattern *pattern, int ll, int anchor,
4321     		  int cuts[MAX_CUTS], struct local_owl_data *owl)
4322 {
4323   int k;
4324   int num = 0;
4325   signed char mark[BOARDMAX];
4326 
4327   memset(mark, 0, BOARDMAX);
4328   for (k = 0; k < pattern->patlen; k++) {
4329     int pos = AFFINE_TRANSFORM(pattern->patn[k].offset, ll, anchor);
4330     if (!IS_STONE(board[pos]))
4331       continue;
4332     pos = find_origin(pos);
4333     if (!mark[pos] && board[pos] == owl->color && owl->goal[pos]) {
4334       cuts[num++] = pos;
4335       mark[pos] = 1;
4336       if (num == MAX_CUTS)
4337 	return;
4338     }
4339   }
4340   if (num == 1)
4341     cuts[0] = NO_MOVE;
4342   else if ((debug & DEBUG_SPLIT_OWL) && num > 1)
4343     gprintf("Move provokes %d cuts, among them %1m and %1m.\n", num,
4344 	    cuts[0], cuts[1]);
4345 }
4346 
4347 /* This function searches in the previously stored list of matched
4348  * patterns for the highest valued unused patterns that have a valid
4349  * constraint.  It returns the moves at the next empty positions in
4350  * the array moves[].  Empty positions in the moves array are marked
4351  * by having value <= 0.  There must be enough empty positions in the
4352  * list.
4353  *
4354  * If the highest valued pattern found has a value less than cutoff,
4355  * no move is returned.  Returns 1 if a move is found, 0 otherwise.
4356  *
4357  * This function also dispatches constraint validation of combinable
4358  * pattern chains.  Whenever a pattern from a chain fails constraints,
4359  * the chain is reevaluated and most likely drops in value enough to
4360  * let other patterns (or chains) climb to the top of pattern heap.
4361  *
4362  * This function loops until enough moves are found or the end of the
4363  * list is reached.
4364  */
4365 
4366 static int
get_next_move_from_list(struct matched_patterns_list_data * list,int color,struct owl_move_data * moves,int cutoff,struct local_owl_data * owl)4367 get_next_move_from_list(struct matched_patterns_list_data *list, int color,
4368 			struct owl_move_data *moves, int cutoff,
4369 			struct local_owl_data *owl)
4370 {
4371   int move_found = 0;
4372   SGFTree *save_sgf_dumptree = sgf_dumptree;
4373   int save_count_variations = count_variations;
4374 
4375   sgf_dumptree = NULL;
4376   count_variations = 0;
4377 
4378   /* Prepare pattern list if needed. */
4379   if (!list->pattern_heap)
4380     pattern_list_prepare(list);
4381 
4382   while (list->heap_num_patterns > 0) {
4383     int k;
4384     struct matched_pattern_data *pattern_data;
4385     struct pattern *pattern;
4386     int move;
4387     int value;
4388     int ll;
4389     int anchor;
4390     int next_pattern_index;
4391 
4392     /* Peek top element of heap associated with pattern list. */
4393     if (list->pattern_heap[0]->value < cutoff)
4394       break;
4395 
4396     pattern_data = list->pattern_heap[0];
4397     pattern = list->pattern_heap[0]->pattern;
4398     move    = list->pattern_heap[0]->move;
4399     value   = list->pattern_heap[0]->value;
4400     ll      = list->pattern_heap[0]->ll;
4401     anchor  = list->pattern_heap[0]->anchor;
4402     next_pattern_index = list->pattern_heap[0]->next_pattern_index;
4403 
4404     list->used++;
4405 
4406     ASSERT_ON_BOARD1(move);
4407     for (k = 0; k < MAX_MOVES; k++) {
4408       if (moves[k].pos == move || moves[k].value <= 0)
4409 	break;
4410     }
4411 
4412     if (moves[k].pos == move) {
4413       /* No point in testing this pattern/chain.  Throw it out. */
4414       pattern_list_pop_heap_once(list);
4415       continue;
4416     }
4417 
4418     /* There has to be an empty space. */
4419     gg_assert(k < MAX_MOVES);
4420 
4421     /* If a pattern chain was devalued because its last pattern didn't
4422      * pass constraint validation, `pattern' is set NULL (i.e. nothing
4423      * more to test).  Note that devalued chains might still be
4424      * useful, i.e. if 2 of 3 patterns passed check_pattern_hard().
4425      */
4426     if (pattern == NULL
4427 	|| check_pattern_hard(move, color, pattern, ll)) {
4428       if (next_pattern_index == -1) {
4429 	/* Normal pattern or last one in a chain. */
4430 	pattern_list_pop_heap_once(list);
4431       }
4432       else {
4433 	/* We just validated a non-last pattern in a chain.  Since the
4434 	 * chain remains at the same value, we keep the heap structure
4435 	 * untouched.  However, we need to set heap's top to point to
4436 	 * next pattern of the chain.
4437 	 */
4438 	list->pattern_heap[0] = list->pattern_list + next_pattern_index;
4439 	list->pattern_heap[0]->value = value;
4440 	continue;
4441       }
4442 
4443       moves[k].pos = move;
4444       moves[k].value = value;
4445       clear_cut_list(moves[k].cuts);
4446       move_found = 1;
4447 
4448       if (pattern && !(pattern->class & CLASS_c)) {
4449 	moves[k].name = pattern->name;
4450 	TRACE("Pattern %s found at %1m with value %d\n",
4451 	      pattern->name, move, moves[k].value);
4452 
4453 	if (pattern->class & CLASS_C) {
4454 	  /* Cut possible. (Only used in attack patterns). Try to find
4455 	   * goal strings in the pattern area and store them in the cut list
4456 	   * if there is more than one.
4457 	   */
4458 	  DEBUG(DEBUG_SPLIT_OWL,
4459 	      	"Generating cut list for move at %1m.\n", move);
4460 	  generate_cut_list(pattern, ll, anchor, moves[k].cuts, owl);
4461 	}
4462 
4463 	if (pattern->class & CLASS_B)
4464 	  moves[k].same_dragon = SAME_DRAGON_NOT_CONNECTED;
4465 	else if (pattern->class & CLASS_a) {
4466 	  moves[k].same_dragon = SAME_DRAGON_ALL_CONNECTED;
4467 	  moves[k].pattern_data = pattern_data;
4468 	}
4469 	else if (!(pattern->class & CLASS_b))
4470 	  moves[k].same_dragon = SAME_DRAGON_CONNECTED;
4471 	else {
4472 	  int i;
4473 	  enum same_dragon_value same_dragon = SAME_DRAGON_MAYBE_CONNECTED;
4474 
4475 	  /* If we do not yet know whether the move belongs to the
4476 	   * same dragon, we see whether another pattern can clarify.
4477 	   */
4478 	  for (i = 0; i < list->heap_num_patterns; i++) {
4479 	    pattern_data = list->pattern_heap[i];
4480 
4481 	    if (pattern_data->pattern
4482 		&& pattern_data->move == move
4483 		&& ((pattern_data->pattern->class & CLASS_B)
4484 		    || !(pattern_data->pattern->class & CLASS_b))) {
4485 	      if (check_pattern_hard(move, color, pattern_data->pattern,
4486 				     pattern_data->ll)) {
4487 		TRACE("Additionally pattern %s found at %1m\n",
4488 		      pattern_data->pattern->name, move);
4489 		if (pattern_data->pattern->class & CLASS_B)
4490 		  same_dragon = SAME_DRAGON_NOT_CONNECTED;
4491 		else if (pattern_data->pattern->class & CLASS_a) {
4492 		  same_dragon = SAME_DRAGON_ALL_CONNECTED;
4493 		  moves[k].pattern_data = pattern_data;
4494 		}
4495 		else
4496 		  same_dragon = SAME_DRAGON_CONNECTED;
4497 
4498 		break;
4499 	      }
4500 	    }
4501 	  }
4502 
4503 	  moves[k].same_dragon = same_dragon;
4504 	}
4505       }
4506       else {
4507 	moves[k].name = "Pattern combination";
4508 	if (verbose) {
4509 	  /* FIXME: write names of all patterns in chain. */
4510 	}
4511 
4512 	/* FIXME: Add handling of CLASS_b.
4513 	 *
4514 	 * FIXME: It is silently assumed that all patterns in the
4515 	 *	  chain have the same class.  When the last pattern in
4516 	 *	  chain didn't match, this will not work at all.
4517 	 */
4518 	if (pattern && pattern->class & CLASS_B)
4519 	  moves[k].same_dragon = SAME_DRAGON_NOT_CONNECTED;
4520 	else if (pattern && pattern->class & CLASS_a) {
4521 	  moves[k].same_dragon = SAME_DRAGON_ALL_CONNECTED;
4522 	  moves[k].pattern_data = list->pattern_heap[0];
4523 	}
4524 	else
4525 	  moves[k].same_dragon = SAME_DRAGON_CONNECTED;
4526       }
4527 
4528       if (pattern && pattern->class & CLASS_E)
4529 	moves[k].escape = 1;
4530       else
4531 	moves[k].escape = 0;
4532 
4533       break;
4534     }
4535     else {			/* !check_pattern_hard(...) */
4536       if (!(pattern->class & CLASS_c)) {
4537 	/* Just forget about it. */
4538 	pattern_list_pop_heap_once(list);
4539       }
4540       else {
4541 	/* Set this pattern to not matched and advance to next one in
4542 	 * the chain, if any.
4543 	 */
4544 	list->pattern_heap[0]->pattern = NULL;
4545 	if (next_pattern_index != -1)
4546 	  list->pattern_heap[0] = list->pattern_list + next_pattern_index;
4547 
4548 	/* Reevaluate chain and adjust heap structure accordingly. */
4549 	list->pattern_heap[0]->value = valuate_combinable_pattern_chain(list,
4550 									move);
4551 	pattern_list_sink_heap_top_element(list);
4552       }
4553     }
4554   }
4555 
4556   sgf_dumptree = save_sgf_dumptree;
4557   count_variations = save_count_variations;
4558 
4559   return move_found;
4560 }
4561 
4562 
4563 /* This function takes an array of already found moves (passed as
4564  * 'data') and looks for moves to replace these. Only moves near
4565  * the goal dragon are considered.
4566  */
4567 static void
owl_shapes_callback(int anchor,int color,struct pattern * pattern,int ll,void * data)4568 owl_shapes_callback(int anchor, int color, struct pattern *pattern,
4569 		    int ll, void *data)
4570 {
4571   int tval;  /* trial move and its value */
4572   int move;
4573   struct owl_move_data *moves = data; /* considered moves passed as data */
4574   enum same_dragon_value same_dragon = SAME_DRAGON_MAYBE_CONNECTED;
4575   int escape = 0;
4576   int defense_pos;
4577 
4578   /* Pick up the location of the move */
4579   move = AFFINE_TRANSFORM(pattern->move_offset, ll, anchor);
4580 
4581   /* Before we do any expensive reading, check whether this move
4582    * already is known with a higher value or if there are too many
4583    * other moves with higher value.
4584    */
4585   if (!allpats) {
4586     int k;
4587     for (k = 0; k < MAX_MOVES; k++) {
4588       if (moves[k].value == -1)
4589 	break;
4590       if (moves[k].pos == move) {
4591 	if (moves[k].value >= pattern->value)
4592 	  return;
4593 	else
4594 	  break;
4595       }
4596     }
4597     if (k == MAX_MOVES && moves[MAX_MOVES - 1].value >= pattern->value)
4598       return;
4599   }
4600 
4601   if (!check_pattern_hard(move, color, pattern, ll))
4602     return;
4603 
4604   /* and work out the value of this move */
4605   if (pattern->helper) {
4606     /* ask helper function to consider the move */
4607     gg_assert(0);
4608     DEBUG(DEBUG_HELPER, "  asking helper to consider '%s'+%d at %1m\n",
4609 	  pattern->name, ll, move);
4610     tval = pattern->helper(pattern, ll, move, color);
4611 
4612     if (tval > 0) {
4613       DEBUG(DEBUG_HELPER, "helper likes pattern '%s' value %d at %1m\n",
4614 	    pattern->name, tval, move);
4615     }
4616     else {
4617       DEBUG(DEBUG_HELPER, "  helper does not like pattern '%s' at %1m\n",
4618 	    pattern->name, move);
4619       return;  /* pattern matcher does not like it */
4620     }
4621   }
4622   else { /* no helper */
4623     tval = (int) pattern->value;
4624   }
4625 
4626   /* having made it here, we have made it through all the extra checks */
4627 
4628   TRACE("Pattern %s found at %1m with value %d\n", pattern->name, move, tval);
4629 
4630   if (pattern->class & CLASS_B)
4631     same_dragon = SAME_DRAGON_NOT_CONNECTED;
4632   else if (pattern->class & CLASS_b)
4633     same_dragon = SAME_DRAGON_MAYBE_CONNECTED;
4634   else if (pattern->class & CLASS_a) {
4635     same_dragon = SAME_DRAGON_ALL_CONNECTED;
4636     /* FIXME: Currently this code is only used with vital attack
4637      * moves, so there is no use for the "a" classification. If it
4638      * would be needed in the future it's necessary to set up a struct
4639      * matched_pattern_data here to be passed to owl_add_move(). This
4640      * is not all that simple with respect to memory management
4641      * however. Notice that a local variable in this function would go
4642      * out of scope too early.
4643      */
4644     gg_assert(0);
4645   }
4646   else
4647     same_dragon = SAME_DRAGON_CONNECTED;
4648 
4649   if (pattern->class & CLASS_E)
4650     escape = 1;
4651   else
4652     escape = 0;
4653 
4654   /* Finally, check for position of defense move. */
4655   {
4656     int k;
4657     defense_pos = move;
4658     for (k = 0; k < pattern->patlen; k++)
4659       if (pattern->patn[k].att == ATT_not)
4660 	defense_pos = AFFINE_TRANSFORM(pattern->patn[k].offset, ll, anchor);
4661   }
4662 
4663   owl_add_move(moves, move, tval, pattern->name, same_dragon, NO_MOVE,
4664       	       escape, defense_pos, MAX_MOVES, NULL);
4665 }
4666 
4667 
4668 /* Add a move to the list of candidate moves */
4669 
4670 static void
owl_add_move(struct owl_move_data * moves,int move,int value,const char * reason,enum same_dragon_value same_dragon,int lunch,int escape,int defense_pos,int max_moves,struct matched_pattern_data * pattern_data)4671 owl_add_move(struct owl_move_data *moves, int move, int value,
4672 	     const char *reason, enum same_dragon_value same_dragon, int lunch,
4673 	     int escape, int defense_pos, int max_moves,
4674 	     struct matched_pattern_data *pattern_data)
4675 {
4676   int k;
4677 
4678   if (!found_matches[move]) {
4679     found_matches[move] = 1;
4680     matches_found++;
4681   }
4682 
4683   /* Add the new move to the list of already found moves, if the value
4684    * is sufficently large. We keep the list sorted.
4685    *
4686    * First we must see if this move already is in the list.
4687    */
4688   for (k = 0; k < max_moves; k++) {
4689     if (moves[k].value == -1)
4690       break;
4691     if (moves[k].pos == move) {
4692       if (same_dragon > moves[k].same_dragon) {
4693 	moves[k].same_dragon = same_dragon;
4694 	moves[k].pattern_data = pattern_data;
4695       }
4696       if (!moves[k].escape)
4697 	escape = 0;
4698       break;
4699     }
4700   }
4701 
4702   /* Did we already have this move in the list with a higher value? */
4703   if (k < max_moves && moves[k].value >= value)
4704     return;
4705 
4706   /* Insert the move at the right place in the list and adjust other
4707    * entries as needed.
4708    */
4709   for (; k >= 0; k--) {
4710     if (k == 0 || value <= moves[k-1].value) {
4711       /* Can't get higher. Insert the move below this point and quit
4712        * looping.
4713        */
4714       if (k < max_moves) {
4715 	moves[k].pos = move;
4716 	moves[k].value = value;
4717 	moves[k].name = reason;
4718 	/* If B or b class pattern, this move shouldn't be added to the
4719          * dragon under consideration.
4720 	 */
4721 	moves[k].same_dragon = same_dragon;
4722 	moves[k].pattern_data = pattern_data;
4723 	moves[k].lunch = lunch;
4724 	moves[k].escape = escape;
4725 	moves[k].defense_pos = defense_pos;
4726       }
4727       break;
4728     }
4729     /* Shuffle the passed move one step downwards. */
4730     if (k < max_moves)
4731       moves[k] = moves[k-1]; /* struct copy */
4732   }
4733 
4734   /* Assert that the list contains unique moves. */
4735   if (0) {
4736     int l;
4737     for (k = 0; k < max_moves; k++)
4738       for (l = k+1; l < max_moves; l++)
4739 	gg_assert(moves[k].pos == 0
4740 		  || moves[k].pos != moves[l].pos);
4741   }
4742 }
4743 
4744 
4745 /* Marks the dragons at apos and bpos. If only one dragon
4746  * needs marking, bpos should be passed as NO_MOVE.
4747  */
4748 
4749 static void
owl_mark_dragon(int apos,int bpos,struct local_owl_data * owl,int new_dragons[BOARDMAX])4750 owl_mark_dragon(int apos, int bpos, struct local_owl_data *owl,
4751 		int new_dragons[BOARDMAX])
4752 {
4753   int pos;
4754   int color = board[apos];
4755 
4756   ASSERT1(bpos == NO_MOVE || board[bpos] == color, bpos);
4757 
4758   if (new_dragons == NULL) {
4759     for (pos = BOARDMIN; pos < BOARDMAX; pos++)
4760       if (ON_BOARD(pos)) {
4761 	if (is_same_dragon(pos, apos) || is_same_dragon(pos, bpos))
4762 	  owl->goal[pos] = 1;
4763 	else
4764 	  owl->goal[pos] = 0;
4765       }
4766   }
4767   else {
4768     for (pos = BOARDMIN; pos < BOARDMAX; pos++)
4769       if (ON_BOARD(pos)) {
4770 	if (IS_STONE(board[pos])
4771 	    && (new_dragons[pos] == new_dragons[apos]
4772 		|| new_dragons[pos] == new_dragons[bpos]))
4773 	  owl->goal[pos] = 1;
4774 	else
4775 	  owl->goal[pos] = 0;
4776       }
4777   }
4778 
4779   memcpy(owl->cumulative_goal, owl->goal, sizeof(owl->goal));
4780   owl->color = color;
4781   owl_mark_boundary(owl);
4782 }
4783 
4784 
4785 /* Marks the worms at apos and bpos. If only one worm
4786  * needs marking, bpos should be passed as NO_MOVE.
4787  */
4788 
4789 static void
owl_mark_worm(int apos,int bpos,struct local_owl_data * owl)4790 owl_mark_worm(int apos, int bpos, struct local_owl_data *owl)
4791 {
4792   int pos;
4793   int color = board[apos];
4794 
4795   ASSERT1(bpos == NO_MOVE || board[bpos] == color, bpos);
4796 
4797   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
4798     if (ON_BOARD(pos)) {
4799       if (is_same_worm(pos, apos) || is_same_worm(pos, bpos))
4800 	owl->goal[pos] = 1;
4801       else
4802 	owl->goal[pos] = 0;
4803     }
4804 
4805   owl->color = color;
4806 }
4807 
4808 
4809 /* Mark the boundary strings of the dragon. A boundary string is marked 2
4810  * if it adjoins a friendly live dragon, 1 otherwise.
4811  */
4812 
4813 static void
owl_mark_boundary(struct local_owl_data * owl)4814 owl_mark_boundary(struct local_owl_data *owl)
4815 {
4816   int k;
4817   int pos;
4818   int color = owl->color;
4819   int other = OTHER_COLOR(color);
4820 
4821   memset(owl->boundary, 0, sizeof(owl->boundary));
4822   memset(owl->neighbors, 0, sizeof(owl->neighbors));
4823 
4824   /* Find all friendly neighbors of the dragon in goal. */
4825   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
4826     if (board[pos] == color && owl->goal[pos]) {
4827       for (k = 0; k < 4; k++) {
4828 	if (board[pos + delta[k]] == EMPTY
4829 	    && board[pos + 2 * delta[k]] == color
4830 	    && !owl->neighbors[pos + 2 * delta[k]])
4831 	  mark_string(pos + 2 * delta[k], owl->neighbors, 1);
4832       }
4833 
4834       for (; k < 8; k++) {
4835 	int pos2 = pos + delta[k];
4836 
4837 	if (board[pos2] == color
4838 	    && !owl->neighbors[pos2]
4839 	    && (board[SOUTH(gg_min(pos, pos2))] == EMPTY
4840 		|| board[NORTH(gg_max(pos, pos2))] == EMPTY))
4841 	  mark_string(pos2, owl->neighbors, 1);
4842       }
4843     }
4844   }
4845 
4846   /* First find all boundary strings (including those adjacent not to
4847    * the goal dragon, but one of its neighbors).
4848    */
4849   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
4850     if (board[pos] == other && !owl->boundary[pos]) {
4851       for (k = 0; k < 8; k++)
4852 	if (ON_BOARD(pos + delta[k])
4853 	    && (owl->goal[pos + delta[k]] || owl->neighbors[pos + delta[k]])) {
4854 	  mark_string(pos, owl->boundary, 1);
4855 	  break;
4856 	}
4857     }
4858 
4859   /* Upgrade the mark of a boundary string if it adjoins a safe
4860    * friendly dragon.
4861    */
4862   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
4863     if (owl->boundary[pos] == 1) {
4864       for (k = 0; k < 8; k++) {
4865 	int pos2 = pos + delta[k];
4866 	if (board[pos2] == color
4867 	    && !owl->goal[pos2]
4868 	    && !owl->neighbors[pos2]
4869 	    && ((dragon[pos2].crude_status != DEAD && countstones(pos2) > 2)
4870 		|| dragon[pos2].crude_status == ALIVE)) {
4871 	  mark_string(pos, owl->boundary, 2);
4872 	  break;
4873 	}
4874       }
4875     }
4876 
4877   /* During the owl reading, stones farther away may become parts of
4878    * the boundary. We mark those strings neighboring some other
4879    * friendly dragon with boundary value 2 right away, since we have
4880    * no mechanism for detecting this later.
4881    */
4882   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
4883     if (board[pos] == other && owl->boundary[pos] == 0) {
4884       /* If a lunch has been amalgamated into a larger dragon, we
4885        * have to back out now.
4886        *
4887        * Notice that we assume that no stone of the attacking color
4888        * has been placed on the board with trymove() when this
4889        * function is called. Thus we can (mostly) trust the worm data for
4890        * stones of this color.
4891        */
4892       if (worm[pos].attack_codes[0] != 0
4893 	  && worm[pos].size != dragon[pos].size)
4894 	continue;
4895 
4896       /* This can happen if called when stackp > 0 */
4897       if (dragon[pos].id == -1)
4898 	continue;
4899 
4900       for (k = 0; k < DRAGON2(pos).neighbors; k++) {
4901 	int d = DRAGON2(pos).adjacent[k];
4902 	int apos = dragon2[d].origin;
4903 
4904 	if (board[apos] == color && !owl->goal[apos]) {
4905 	  owl->boundary[pos] = 2;
4906 	  break;
4907 	}
4908       }
4909     }
4910 }
4911 
4912 /* Add the stone just played to the goal dragon if same_dragon is
4913  * SAME_DRAGON_CONNECTED. We also add all stones belonging to the same
4914  * generalized string to the goal. If same_dragon is
4915  * SAME_DRAGON_MAYBE_CONNECTED, we only add the stones if at least one
4916  * stone of the generalized string already was part of the goal. If
4917  * same_dragon is SAME_DRAGON_NOT_CONNECTED, we don't add any stones
4918  * at all.
4919  *
4920  * The SAME_DRAGON_ALL_CONNECTED case is like SAME_DRAGON_CONNECTED
4921  * but additionally all other own stones in the pattern suggesting the
4922  * move are also added to the goal.
4923  */
4924 static void
owl_update_goal(int pos,enum same_dragon_value same_dragon,int lunch,struct local_owl_data * owl,int semeai_call,struct matched_pattern_data * pattern_data)4925 owl_update_goal(int pos, enum same_dragon_value same_dragon, int lunch,
4926     		struct local_owl_data *owl, int semeai_call,
4927 		struct matched_pattern_data *pattern_data)
4928 {
4929   int stones[MAX_BOARD * MAX_BOARD];
4930   int num_stones;
4931   int k;
4932   int do_add = 1;
4933   SGFTree *save_sgf_dumptree = sgf_dumptree;
4934   int save_count_variations = count_variations;
4935 
4936 
4937   /* Turn off sgf output during find_superstring(). */
4938   sgf_dumptree = NULL;
4939   count_variations = 0;
4940 
4941   if (same_dragon == SAME_DRAGON_NOT_CONNECTED)
4942     num_stones = findstones(pos, MAX_BOARD * MAX_BOARD, stones);
4943   else if (semeai_call)
4944     find_superstring_conservative(pos, &num_stones, stones);
4945   else
4946     find_superstring(pos, &num_stones, stones);
4947 
4948   /* Turn sgf output back on. */
4949   sgf_dumptree = save_sgf_dumptree;
4950   count_variations = save_count_variations;
4951 
4952   /* If same_dragon field is 1, only add if the played stone
4953    * clearly is in contact with the goal dragon.
4954    */
4955   if (same_dragon <= SAME_DRAGON_MAYBE_CONNECTED) {
4956     do_add = 0;
4957     for (k = 0; k < num_stones; k++)
4958       if (owl->goal[stones[k]] != 0) {
4959 	do_add = 1;
4960 	break;
4961       }
4962   }
4963 
4964   if (do_add)
4965     for (k = 0; k < num_stones; k++) {
4966       if (owl->goal[stones[k]] == 0) {
4967 	if (0)
4968 	  TRACE("Added %1m to goal.\n", stones[k]);
4969 	owl->goal[stones[k]] = 2;
4970 	owl->cumulative_goal[stones[k]] = 1;
4971       }
4972     }
4973 
4974   /* If this move captures a lunch, we add all it's direct neighbours to the
4975    * goal.
4976    */
4977   if (!semeai_call && lunch != NO_MOVE && board[lunch] != EMPTY) {
4978     int adj, adjs[MAXCHAIN];
4979     int k;
4980     adj = chainlinks(lunch, adjs);
4981     for (k = 0; k < adj; k++)
4982       if (!owl->goal[adjs[k]]) {
4983 	mark_string(adjs[k], owl->goal, 2);
4984 	mark_string(adjs[k], owl->cumulative_goal, 2);
4985       }
4986   }
4987 
4988   /* Now we handle the SAME_DRAGON_ALL_CONNECTED case. The move has
4989    * already been added to the goal above, so it remains to find all
4990    * other friendly stones in the pattern and add them too. We do that
4991    * by a recursive call to this function in SAME_DRAGON_CONNECTED mode.
4992    * This is maybe not the most elegant technique, however.
4993    */
4994   if (same_dragon == SAME_DRAGON_ALL_CONNECTED) {
4995     gg_assert(pattern_data != NULL);
4996     for (k = 0; k < pattern_data->pattern->patlen; k++) {
4997       int pos2;
4998 
4999       /* all the following stuff (currently) applies only at occupied cells */
5000       if (pattern_data->pattern->patn[k].att != ATT_O)
5001 	continue;
5002 
5003       /* transform pattern real coordinate */
5004       pos2 = AFFINE_TRANSFORM(pattern_data->pattern->patn[k].offset,
5005 			      pattern_data->ll, pattern_data->anchor);
5006 
5007       if (!owl->goal[pos2])
5008 	owl_update_goal(pos2, SAME_DRAGON_CONNECTED, NO_MOVE, owl, semeai_call,
5009 			pattern_data);
5010     }
5011   }
5012 
5013   if (1 && verbose)
5014     goaldump(owl->goal);
5015 }
5016 
5017 
5018 /* Computes the connected components of a the graph that is given by
5019  * having graph[i][j] = 1 if i and j are connected, and that has size
5020  * graph_size.
5021  *
5022  * This function is generic, but without having the fixed MAX_CUTS
5023  * array size it is ugly to write in ANSI C89 (no variably sized arrays),
5024  * so we leave it here for now.
5025  */
5026 static int
connected_components(signed char graph[MAX_CUTS][MAX_CUTS],int graph_size,signed char component[MAX_CUTS])5027 connected_components(signed char graph[MAX_CUTS][MAX_CUTS], int graph_size,
5028 		     signed char component[MAX_CUTS])
5029 {
5030   int num_components = 0;
5031   int k, j;
5032 
5033   if (graph_size <= 0)
5034     return 0;
5035 
5036   memset(component, -1, MAX_CUTS);
5037   for (;;) {
5038     int found_one;
5039     /* Find unidentified string. */
5040     for (k = 0; k < graph_size; k++)
5041       if (component[k] == -1)
5042 	break;
5043     if (k == graph_size)
5044       break; /* All are identified. */
5045     component[k] = num_components; /* Start new component. */
5046     do { /* Spread new component. */
5047       found_one = 0;
5048       for (j = k+1; j < graph_size; j++)
5049 	if (graph[k][j] && component[j] == -1) {
5050 	  component[j] = num_components;
5051 	  found_one = 1;
5052 	}
5053     } while (found_one);
5054     num_components++;
5055   }
5056   gg_assert(num_components > 0);
5057   return num_components;
5058 }
5059 
5060 /* This functions gets called after a move has been made that threatens
5061  * to cut the owl goal dragon. It cuts the goal if necessary, and sets it
5062  * to the biggest remaining component.
5063  */
5064 static void
owl_test_cuts(signed char goal[BOARDMAX],int color,int cuts[MAX_CUTS])5065 owl_test_cuts(signed char goal[BOARDMAX], int color, int cuts[MAX_CUTS])
5066 {
5067   int k, j;
5068   signed char connected[MAX_CUTS][MAX_CUTS];
5069   /* int connect_move[MAX_CUTS][MAX_CUTS]; */
5070   int num_cuts;
5071   int found_cut = 0;
5072   SGFTree *save_sgf_dumptree = sgf_dumptree;
5073   int save_count_variations = count_variations;
5074 
5075   sgf_dumptree = NULL;
5076   count_variations = 0;
5077 
5078   memset(connected, 1, MAX_CUTS*MAX_CUTS);
5079   if (debug & DEBUG_SPLIT_OWL) {
5080     gprintf("Called for this goal: ");
5081     goaldump(goal);
5082     gprintf("At this position:\n");
5083     showboard(0);
5084   }
5085 
5086   /* Delete captured strings from list. */
5087   for (k = 0; k < MAX_CUTS; k++) {
5088     if (cuts[k] == NO_MOVE)
5089       break;
5090     if (board[cuts[k]] == EMPTY) {
5091       for (j = k + 1; j < MAX_CUTS; j++) {
5092 	if (cuts[j] == NO_MOVE)
5093 	  break;
5094 	cuts[j-1] = cuts[j];
5095       }
5096       cuts[k] = NO_MOVE;
5097       k--;
5098     }
5099   }
5100   num_cuts = k;
5101 
5102   /* Test for each pair of strings in cuts[] whether it can now be
5103    * disconnected.
5104    */
5105   for (k = 0; k < num_cuts; k++) {
5106     ASSERT1(board[cuts[k]] == color, cuts[k]);
5107     for (j = k + 1; j < num_cuts; j++)
5108       if (fast_disconnect(cuts[k], cuts[j], NULL) == WIN) {
5109 	found_cut = 1;
5110 	connected[k][j] = 0;
5111 	connected[j][k] = 0;
5112       }
5113   }
5114 
5115   if (found_cut) {
5116     signed char component[MAX_CUTS];
5117     signed char component2[BOARDMAX];
5118     int component_size[MAX_CUTS];
5119     int num_components;
5120     int biggest_component = -1;
5121     struct connection_data *conn_data;
5122     int c_id;
5123     int pos;
5124 
5125     /* Start by computing the connected components among the strings
5126      * listed in cuts[].
5127      */
5128     num_components = connected_components(connected, num_cuts, component);
5129     if (num_components <= 1) {
5130       sgf_dumptree = save_sgf_dumptree;
5131       count_variations = save_count_variations;
5132       return;
5133     }
5134 
5135     /* Now break up the goal by associating each goal stone to one of
5136      * the connected components.
5137      *
5138      * First we compute the connection distances from each of the
5139      * partial goals we have found.
5140      */
5141     memset(component2, -1, BOARDMAX);
5142     memset(component_size, 0, sizeof(int) * num_components);
5143     conn_data = malloc(sizeof(struct connection_data) * num_components);
5144     for (c_id = 0; c_id < num_components; c_id++) {
5145       signed char this_goal[BOARDMAX];
5146       memset(this_goal, 0, BOARDMAX);
5147 
5148       for (k = 0; k < num_cuts; k++)
5149 	if (component[k] == c_id) {
5150 	  mark_string(cuts[k], this_goal, 1);
5151 	  mark_string(cuts[k], component2, (signed char) c_id);
5152 	}
5153       init_connection_data(color, this_goal, NO_MOVE, FP(3.01),
5154 	  		   conn_data + c_id, 1);
5155       spread_connection_distances(color, conn_data + c_id);
5156     }
5157 
5158     /* Now put each goal string to the component to which it has the
5159      * smallest distance.
5160      */
5161     for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
5162       int closest_dist = HUGE_CONNECTION_DISTANCE;
5163       int closest_component = -1;
5164       if (board[pos] != color || !goal[pos])
5165 	continue;
5166       if (pos != find_origin(pos))
5167 	continue;
5168       for (c_id = 0; c_id < num_components; c_id++) {
5169 	if (conn_data[c_id].distances[pos] < closest_dist) {
5170 	  closest_dist = conn_data[c_id].distances[pos];
5171 	  closest_component = c_id;
5172 	}
5173       }
5174       /* FIXME: What to do if no close component found? */
5175       if (closest_component != -1) {
5176 	mark_string(pos, component2, (signed char) closest_component);
5177 	component_size[closest_component] += countstones(pos);
5178       }
5179     }
5180 
5181     /* Now find the biggest_component. */
5182     {
5183       int biggest_size = 0;
5184       for (c_id = 0; c_id < num_components; c_id++)
5185 	if (component_size[c_id] > biggest_size) {
5186 	  biggest_size = component_size[c_id];
5187 	  biggest_component = c_id;
5188 	}
5189       gg_assert(biggest_component != -1);
5190     }
5191 
5192     /* Now delete everything except the biggest component from the goal. */
5193     for (pos = BOARDMIN; pos < BOARDMAX; pos++)
5194       if (component2[pos] != biggest_component)
5195 	goal[pos] = 0;
5196     if (debug & DEBUG_SPLIT_OWL) {
5197       gprintf("Split dragon. Biggest component is %d (of %d).\n",
5198 	      biggest_component, num_components);
5199       showboard(0);
5200       componentdump(component2);
5201     }
5202     free(conn_data);
5203   }
5204   sgf_dumptree = save_sgf_dumptree;
5205   count_variations = save_count_variations;
5206 }
5207 
5208 /* We update the boundary marks. The boundary mark must be
5209  * constant on each string. It is nonzero if the string
5210  * adjoins the goal dragon, or if the string includes a
5211  * stone played in the course of analysis. If the string
5212  * adjoins a live friendly dragon, the boundary mark is 2.
5213  */
5214 static void
owl_update_boundary_marks(int pos,struct local_owl_data * owl)5215 owl_update_boundary_marks(int pos, struct local_owl_data *owl)
5216 {
5217   signed char boundary_mark = 0;
5218   int k;
5219 
5220   for (k = 0; k < 4; k++) {
5221     int pos2 = pos + delta[k];
5222 
5223     if (ON_BOARD(pos2) && owl->boundary[pos2] > boundary_mark)
5224       boundary_mark = owl->boundary[pos2];
5225 
5226     if (board[pos2] == owl->color
5227 	&& dragon[pos2].color == owl->color
5228 	&& dragon[pos2].status == ALIVE
5229 	&& !owl->goal[pos2]
5230 	&& !owl->neighbors[pos2])
5231       boundary_mark = 2;
5232   }
5233 
5234   mark_string(pos, owl->boundary, boundary_mark);
5235 }
5236 
5237 /* Lists the goal array. For use in GDB:
5238  * (gdb) set goaldump(goal).
5239  */
5240 
5241 void
goaldump(const signed char goal[BOARDMAX])5242 goaldump(const signed char goal[BOARDMAX])
5243 {
5244   int pos;
5245   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
5246     if (ON_BOARD(pos) && goal[pos])
5247       gprintf("%o%1m (%d)  ", pos, (int) goal[pos]);
5248   gprintf("\n");
5249 }
5250 
5251 void
componentdump(const signed char component[BOARDMAX])5252 componentdump(const signed char component[BOARDMAX])
5253 {
5254   int pos;
5255   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
5256     if (ON_BOARD(pos) && component[pos] != -1)
5257       gprintf("%o%1m (%d)  ", pos, (int) component[pos]);
5258   gprintf("\n");
5259 }
5260 
5261 /*
5262  * Owl attack moves are ineffective when the dragon can still live in a
5263  * semeai. This function tests whether an owl attack move has this problem.
5264  * If not, an owl attack move reason is added, otherwise we treat the
5265  * move as a strategic attack.
5266  */
5267 static void
test_owl_attack_move(int pos,int dr,int kworm,int acode)5268 test_owl_attack_move(int pos, int dr, int kworm, int acode)
5269 {
5270   int color = OTHER_COLOR(board[dr]);
5271   if (DRAGON2(dr).semeais == 0
5272       || DRAGON2(dr).semeai_defense_point == NO_MOVE
5273       || (DRAGON2(dr).semeais == 1 && semeai_move_reason_known(pos, dr))
5274       || acode == GAIN) {
5275     add_owl_attack_move(pos, dr, kworm, acode);
5276     DEBUG(DEBUG_OWL, "owl: %1m attacks %1m (%s) at move %d\n",
5277 	  pos, dr, result_to_string(DRAGON2(dr).owl_attack_code),
5278 	  movenum+1);
5279   }
5280   else {
5281     int dr2 = DRAGON2(dr).semeai_defense_target;
5282     int semeai_result, certain;
5283     int save_verbose = verbose;
5284     if (verbose > 0)
5285       verbose--;
5286     owl_analyze_semeai_after_move(pos, color, dr, dr2, &semeai_result,
5287 				  NULL, NULL, 1, &certain, 0);
5288     verbose = save_verbose;
5289     if (certain >= DRAGON2(dr).semeai_defense_certain
5290 	&& (semeai_result >= REVERSE_RESULT(acode))) {
5291       /* Demote the move reasons. */
5292       DEBUG(DEBUG_OWL, "owl: %1m ineffective owl attack on %1m (can live in semeai with %1m)\n", pos, dr, dr2);
5293       add_strategical_attack_move(pos, dr);
5294     }
5295     else {
5296       add_owl_attack_move(pos, dr, kworm, acode);
5297       DEBUG(DEBUG_OWL, "owl: %1m attacks %1m (%s) at move %d\n",
5298 	    pos, dr, result_to_string(DRAGON2(dr).owl_attack_code),
5299 	    movenum+1);
5300     }
5301   }
5302 }
5303 
5304 /* Add owl move reasons. This function should be called once during
5305  * genmove. It has to be called after semeai_move_reasons().
5306  */
5307 
5308 void
owl_reasons(int color)5309 owl_reasons(int color)
5310 {
5311   int pos;
5312 
5313   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
5314     if (!IS_STONE(board[pos])
5315         || dragon[pos].origin != pos)
5316       continue;
5317 
5318     if (dragon[pos].status == CRITICAL
5319 	&& DRAGON2(pos).owl_attack_point != NO_MOVE) {
5320       if (board[pos] == color) {
5321 	if (DRAGON2(pos).owl_defense_point != NO_MOVE) {
5322 	  if (DRAGON2(pos).owl_defense_code == LOSS) {
5323 	    add_loss_move(DRAGON2(pos).owl_defense_point, pos,
5324 			  DRAGON2(pos).owl_defense_kworm);
5325 	    DEBUG(DEBUG_OWL, "owl: %1m defends %1m with loss at move %d\n",
5326 		  DRAGON2(pos).owl_defense_point, pos, movenum+1);
5327 	  }
5328 	  else {
5329 	    add_owl_defense_move(DRAGON2(pos).owl_defense_point, pos,
5330 				 DRAGON2(pos).owl_defense_code);
5331 	    DEBUG(DEBUG_OWL, "owl: %1m defends %1m at move %d\n",
5332 		  DRAGON2(pos).owl_defense_point, pos, movenum+1);
5333 	  }
5334 	}
5335       }
5336       else { /* opponent's dragon */
5337 	/* We don't want to add this move reason if the attacker
5338 	 * dies because the victim only formed a nakade shape.
5339 	 *
5340 	 * FIXME: This code overlaps heavily with some code in
5341 	 *	  examine_move_safety() in move_reasons.c. The caching
5342 	 *	  scheme should minimize the performance hit, but of course
5343 	 *	  it's unfortunate to have the code duplication.
5344 	 */
5345 	int move = DRAGON2(pos).owl_attack_point;
5346 
5347 	/* No worries if we catch something big. */
5348 	if (dragon[pos].effective_size < 8) {
5349 	  /* Look through the neighbors of the victim for dragons of
5350 	   * our color. If we find at least one being thought alive
5351 	   * everything is ok. Otherwise we keep track of the
5352 	   * largest one for further examination.
5353 	   */
5354 	  int largest = 0;
5355 	  int k;
5356 	  int bpos = NO_MOVE;
5357 	  int kworm = NO_MOVE;
5358 	  int safe = 0;
5359 	  for (k = 0; k < DRAGON2(pos).neighbors; k++) {
5360 	    int d = DRAGON2(pos).adjacent[k];
5361 	    if (DRAGON(d).color == color) {
5362 	      if (DRAGON(d).status == ALIVE) {
5363 		safe = 1;
5364 		break;
5365 	      }
5366 	      if (DRAGON(d).size > largest) {
5367 		bpos = dragon2[d].origin;
5368 		largest = DRAGON(d).size;
5369 	      }
5370 	    }
5371 	  }
5372 
5373 	  /* It may occasionally happen that no neighbor of our
5374 	   * color was found. Assume safe in that case.
5375 	   */
5376 	  if (bpos == NO_MOVE)
5377 	    safe = 1;
5378 
5379 	  /* If not yet thought safe, ask the owl code whether the
5380 	   * owl attack defends the (largest) attacker.
5381 	   */
5382 	  if (!safe && owl_does_defend(move, bpos, &kworm) != WIN) {
5383 	    DEBUG(DEBUG_OWL,
5384 		  "owl: %1m attacks %1m at move %d, but the attacker dies.\n",
5385 		  move, pos, movenum+1);
5386 	    DRAGON2(pos).safety = INESSENTIAL;
5387 	    continue;
5388 	  }
5389 	}
5390 
5391 	/* If we've reached this far, it only remains to check the move
5392 	 * against semeai complications. */
5393 	test_owl_attack_move(move, pos, DRAGON2(pos).owl_attack_kworm,
5394 	    		    DRAGON2(pos).owl_attack_code);
5395       }
5396     }
5397     else if (DRAGON2(pos).owl_status == DEAD
5398 	     && DRAGON2(pos).owl_threat_status == CAN_THREATEN_DEFENSE) {
5399       if (board[pos] == color
5400 	  && DRAGON2(pos).owl_defense_point != NO_MOVE) {
5401 	add_owl_defense_threat_move(DRAGON2(pos).owl_defense_point, pos, WIN);
5402 	DEBUG(DEBUG_OWL, "owl: %1m threatens to defend %1m at move %d\n",
5403 	      DRAGON2(pos).owl_defense_point, pos, movenum+1);
5404       }
5405       if (board[pos] == color
5406 	    && DRAGON2(pos).owl_second_defense_point != NO_MOVE
5407 	  && is_legal(DRAGON2(pos).owl_second_defense_point, color)) {
5408 	add_owl_defense_threat_move(DRAGON2(pos).owl_second_defense_point,
5409 				    pos, WIN);
5410 	DEBUG(DEBUG_OWL, "owl: %1m threatens to defend %1m at move %d\n",
5411 	      DRAGON2(pos).owl_second_defense_point, pos, movenum+1);
5412       }
5413 
5414       /* If the opponent can threaten to live, an attacking
5415        * move gets a small value to make sure it's really dead.
5416        */
5417       if (board[pos] == OTHER_COLOR(color)
5418 	  && DRAGON2(pos).owl_threat_status == CAN_THREATEN_DEFENSE
5419 	  && DRAGON2(pos).owl_attack_point != NO_MOVE) {
5420 	add_owl_prevent_threat_move(DRAGON2(pos).owl_attack_point, pos);
5421 	DEBUG(DEBUG_OWL, "owl: %1m prevents a threat against %1m at move %d\n",
5422 	      DRAGON2(pos).owl_attack_point, pos, movenum+1);
5423       }
5424     }
5425     else if (DRAGON2(pos).owl_status == ALIVE) {
5426       if (board[pos] == OTHER_COLOR(color)
5427 	  && DRAGON2(pos).owl_threat_status == CAN_THREATEN_ATTACK) {
5428 	if (DRAGON2(pos).owl_attack_point != NO_MOVE) {
5429 	  add_owl_attack_threat_move(DRAGON2(pos).owl_attack_point, pos, WIN);
5430 	  DEBUG(DEBUG_OWL, "owl: %1m threatens %1m at move %d\n",
5431 		DRAGON2(pos).owl_attack_point, pos, movenum+1);
5432 	}
5433 	if (DRAGON2(pos).owl_second_attack_point != NO_MOVE
5434 	    && is_legal(DRAGON2(pos).owl_second_attack_point, color)) {
5435 	  add_owl_attack_threat_move(DRAGON2(pos).owl_second_attack_point, pos,
5436 				     WIN);
5437 	  DEBUG(DEBUG_OWL, "owl: %1m threatens %1m at move %d\n",
5438 		DRAGON2(pos).owl_second_attack_point, pos, movenum+1);
5439 	}
5440       }
5441       else if (board[pos] == OTHER_COLOR(color)
5442 	       && DRAGON2(pos).owl_attack_point != NO_MOVE
5443 	       && DRAGON2(pos).owl_attack_code == GAIN) {
5444 	add_owl_attack_move(DRAGON2(pos).owl_attack_point, pos,
5445 		            DRAGON2(pos).owl_attack_kworm, GAIN);
5446 	DEBUG(DEBUG_OWL, "owl: %1m attacks %1m with gain at move %d\n",
5447 	      DRAGON2(pos).owl_attack_point, pos, movenum+1);
5448       }
5449       else if (board[pos] == color
5450 	       && DRAGON2(pos).owl_defense_point != NO_MOVE
5451 	       && DRAGON2(pos).owl_defense_code == LOSS) {
5452 	add_loss_move(DRAGON2(pos).owl_defense_point, pos,
5453 		      DRAGON2(pos).owl_defense_kworm);
5454 	DEBUG(DEBUG_OWL, "owl: %1m defends %1m with loss at move %d\n",
5455 	      DRAGON2(pos).owl_defense_point, pos, movenum+1);
5456       }
5457       else if (board[pos] == color
5458 	       && DRAGON2(pos).owl_attack_point != NO_MOVE
5459 	       && DRAGON2(pos).owl_attack_code == GAIN
5460 	       && DRAGON2(pos).owl_defense_code == WIN
5461 	       && DRAGON2(pos).owl_defense_point != NO_MOVE) {
5462 	add_owl_defense_move(DRAGON2(pos).owl_defense_point, pos,
5463 			     DRAGON2(pos).owl_defense_code);
5464 	DEBUG(DEBUG_OWL, "owl: %1m defends %1m against possible loss at move %d\n",
5465 	      DRAGON2(pos).owl_defense_point, pos, movenum+1);
5466 
5467       }
5468       /* The owl code found the friendly dragon alive, but was uncertain,
5469        * and an extra point of defense was found, so this might
5470        * be a good place to play.
5471        */
5472       else if (board[pos] == color
5473 	       && !DRAGON2(pos).owl_attack_certain
5474 	       && DRAGON2(pos).owl_defense_certain
5475 	       && ON_BOARD(DRAGON2(pos).owl_defense_point)) {
5476 	add_owl_uncertain_defense_move(DRAGON2(pos).owl_defense_point, pos);
5477 	DEBUG(DEBUG_OWL,
5478 	      "owl: %1m defends the uncertain dragon at %1m at move %d\n",
5479 	      DRAGON2(pos).owl_defense_point, pos, movenum+1);
5480       }
5481     }
5482 
5483     /* The owl code found the dragon dead, but was uncertain,
5484      * and an extra point of attack was found, so this might
5485      * be a good place to play.
5486      */
5487     else if (DRAGON2(pos).owl_status == DEAD
5488 	     && board[pos] == OTHER_COLOR(color)
5489 	     && !DRAGON2(pos).owl_attack_certain
5490 	     && ON_BOARD(DRAGON2(pos).owl_attack_point)) {
5491       add_owl_uncertain_defense_move(DRAGON2(pos).owl_attack_point, pos);
5492       DEBUG(DEBUG_OWL,
5493 	    "owl: %1m might defend the uncertain dragon at %1m at move %d\n",
5494 	    DRAGON2(pos).owl_attack_point, pos, movenum+1);
5495     }
5496   }
5497 }
5498 
5499 /* Use the owl code to determine whether the move at (move) makes
5500  * the dragon at (target) owl safe. This is used to test whether
5501  * tactical defenses are strategically viable and whether a vital eye
5502  * point does kill an owl critical dragon.
5503  *
5504  * Should be called only when stackp==0.
5505  */
5506 
5507 int
owl_does_defend(int move,int target,int * kworm)5508 owl_does_defend(int move, int target, int *kworm)
5509 {
5510   int color = board[target];
5511   int result = 0;
5512   struct local_owl_data *owl;
5513   int reading_nodes_when_called = get_reading_node_counter();
5514   int tactical_nodes;
5515   int origin;
5516   int acode;
5517   int wpos = NO_MOVE;
5518   int wid = MAX_GOAL_WORMS;
5519   double start = 0.0;
5520 
5521   if (debug & DEBUG_OWL_PERFORMANCE)
5522     start = gg_cputime();
5523 
5524   if (worm[target].unconditional_status == DEAD)
5525     return 0;
5526 
5527   origin = dragon[target].origin;
5528   TRACE("owl_does_defend %1m %1m(%1m)\n", move, target, origin);
5529 
5530   if (search_persistent_owl_cache(OWL_DOES_DEFEND, move, target, 0,
5531 				  &result, kworm, NULL, NULL))
5532     return result;
5533 
5534   if (trymove(move, color, "owl_does_defend", target)) {
5535     /* Check if a compatible owl_attack() is cached. */
5536     if (search_persistent_owl_cache(OWL_ATTACK, origin, 0, 0,
5537 				    &result, NULL, kworm, NULL)) {
5538       popgo();
5539       return REVERSE_RESULT(result);
5540     }
5541 
5542     /*
5543      * FIXME: (move) will be added to the goal dragon although we
5544      * do not know whether it is really connected.
5545      */
5546     init_owl(&owl, target, NO_MOVE, move, 1, NULL);
5547     prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
5548 		      kworm, 0);
5549     acode = do_owl_attack(target, NULL, &wid, owl, 0);
5550     finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
5551     result = REVERSE_RESULT(acode);
5552     popgo();
5553   }
5554   else
5555     return 0;  /* Don't cache anything in this case. */
5556 
5557   tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
5558 
5559   DEBUG(DEBUG_OWL_PERFORMANCE,
5560 	"owl_does_defend %1m %1m(%1m), result %d (%d, %d nodes, %f seconds)\n",
5561 	move, target, origin, result, local_owl_node_counter,
5562 	tactical_nodes, gg_cputime() - start);
5563 
5564   store_persistent_owl_cache(OWL_DOES_DEFEND, move, target, 0,
5565 			     result, wpos, 0, 0,
5566 			     tactical_nodes, owl->goal, board[target]);
5567 
5568   if (kworm)
5569     *kworm = wpos;
5570   return result;
5571 }
5572 
5573 
5574 /* Use the owl code to determine whether the dragon at (target) is owl
5575  * safe after an own move at (move). This is used to detect
5576  * blunders. In case the dragon is not safe, it also tries to find a
5577  * defense point making (target) safe in a later move.
5578  *
5579  * Should be called only when stackp==0.
5580  */
5581 
5582 int
owl_confirm_safety(int move,int target,int * defense_point,int * kworm)5583 owl_confirm_safety(int move, int target, int *defense_point, int *kworm)
5584 {
5585   int color = board[target];
5586   int result = 0;
5587   struct local_owl_data *owl;
5588   int reading_nodes_when_called = get_reading_node_counter();
5589   int tactical_nodes;
5590   int origin;
5591   int defense = 0;
5592   double start = 0.0;
5593   int acode;
5594   int wpos = NO_MOVE;
5595   int wid = MAX_GOAL_WORMS;
5596 
5597   if (debug & DEBUG_OWL_PERFORMANCE)
5598     start = gg_cputime();
5599 
5600   if (worm[target].unconditional_status == DEAD)
5601     return 0;
5602 
5603   origin = dragon[target].origin;
5604   TRACE("owl_confirm_safety %1m %1m(%1m)\n", move, target, origin);
5605 
5606   if (search_persistent_owl_cache(OWL_CONFIRM_SAFETY, move, target, 0,
5607 				  &result, defense_point, kworm, NULL))
5608     return result;
5609 
5610   if (trymove(move, color, "owl_confirm_safety", target)) {
5611     /* Check if a compatible owl_attack() is cached. */
5612     if (search_persistent_owl_cache(OWL_ATTACK, origin, 0, 0,
5613 				    &result, defense_point, kworm, NULL)) {
5614       popgo();
5615       if (result == 0)
5616 	return WIN;
5617       else if (result == GAIN)
5618 	return LOSS;
5619       else
5620 	return 0;
5621     }
5622 
5623     init_owl(&owl, target, NO_MOVE, move, 1, NULL);
5624     prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
5625 		      kworm, 0);
5626     acode = do_owl_attack(target, &defense, &wid, owl, 0);
5627     finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
5628     if (acode == 0)
5629       result = WIN;
5630     else if (acode == GAIN)
5631       result = LOSS;
5632     popgo();
5633   }
5634   else
5635     return 0;  /* Don't cache anything in this case. */
5636 
5637   tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
5638 
5639   DEBUG(DEBUG_OWL_PERFORMANCE,
5640 	"owl_confirm_safety %1m %1m(%1m), result %d %1m (%d, %d nodes, %f seconds)\n",
5641 	move, target, origin, result, defense,
5642 	local_owl_node_counter, tactical_nodes,
5643 	gg_cputime() - start);
5644 
5645   store_persistent_owl_cache(OWL_CONFIRM_SAFETY, move, target, 0,
5646 			     result, defense, wpos, 0,
5647 			     tactical_nodes, owl->goal, board[target]);
5648 
5649   if (defense_point)
5650     *defense_point = defense;
5651   if (kworm)
5652     *kworm = wpos;
5653 
5654   return result;
5655 }
5656 
5657 
5658 /* Use the owl code to determine whether the attack move at (move) of
5659  * the dragon (target) is effective, i.e. whether it kills the stones.
5660  *
5661  * Should be called only when stackp==0.
5662  */
5663 
5664 int
owl_does_attack(int move,int target,int * kworm)5665 owl_does_attack(int move, int target, int *kworm)
5666 {
5667   int color = board[target];
5668   int other = OTHER_COLOR(color);
5669   int result = 0;
5670   struct local_owl_data *owl;
5671   int reading_nodes_when_called = get_reading_node_counter();
5672   int tactical_nodes;
5673   int origin;
5674   int dcode;
5675   int wpos = NO_MOVE;
5676   int wid = MAX_GOAL_WORMS;
5677   double start = 0.0;
5678 
5679   if (debug & DEBUG_OWL_PERFORMANCE)
5680     start = gg_cputime();
5681 
5682   if (worm[target].unconditional_status == ALIVE)
5683     return 0;
5684 
5685   origin = dragon[target].origin;
5686   TRACE("owl_does_attack %1m %1m(%1m)\n", move, target, origin);
5687 
5688   if (search_persistent_owl_cache(OWL_DOES_ATTACK, move, target, 0,
5689 				  &result, kworm, NULL, NULL))
5690     return result;
5691 
5692   /* FIXME: We want to do this after the trymove(), but currently
5693    * owl_mark_dragon() may crash if the trymove() happens to remove
5694    * some stones of the goal dragon from the board.
5695    */
5696 #if 1
5697   init_owl(&owl, target, NO_MOVE, NO_MOVE, 1, NULL);
5698 #endif
5699 
5700   if (trymove(move, other, "owl_does_attack", target)) {
5701     /* Check if a compatible owl_defend() is cached. */
5702     if (search_persistent_owl_cache(OWL_DEFEND, origin, 0, 0,
5703 				    &result, NULL, kworm, NULL)) {
5704       popgo();
5705       return REVERSE_RESULT(result);
5706     }
5707 
5708 #if 0
5709     local_owl_node_counter = 0;
5710     owl->lunches_are_current = 0;
5711     owl_mark_dragon(target, NO_MOVE, owl);
5712 #endif
5713     owl_update_boundary_marks(move, owl);
5714 #if 0
5715     compute_owl_escape_values(owl);
5716 #endif
5717     /* FIXME: Should also check if part of the dragon was captured,
5718      *        like do_owl_attack() does.
5719      */
5720     if (board[target] == EMPTY)
5721       dcode = 0;
5722     else {
5723       prepare_goal_list(target, owl, owl_goal_worm, &goal_worms_computed,
5724 	                 kworm, 0);
5725       dcode = do_owl_defend(target, NULL, &wid, owl, 0);
5726       finish_goal_list(&goal_worms_computed, &wpos, owl_goal_worm, wid);
5727     }
5728     result = REVERSE_RESULT(dcode);
5729     owl->lunches_are_current = 0;
5730     popgo();
5731   }
5732   else
5733     return 0;  /* Don't cache anything in this case. */
5734 
5735   tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
5736 
5737   DEBUG(DEBUG_OWL_PERFORMANCE,
5738 	"owl_does_attack %1m %1m(%1m), result %d (%d, %d nodes, %f seconds)\n",
5739 	move, target, origin, result, local_owl_node_counter,
5740 	tactical_nodes, gg_cputime() - start);
5741 
5742   store_persistent_owl_cache(OWL_DOES_ATTACK, move, target, 0,
5743 			     result, wpos, 0, 0,
5744 			     tactical_nodes, owl->goal, board[target]);
5745 
5746   if (kworm)
5747     *kworm = wpos;
5748   return result;
5749 }
5750 
5751 
5752 /* Use the owl code to determine whether connecting the two dragons
5753  * (target1) and (target2) by playing at (move) results in a living
5754  * dragon. Should be called only when stackp==0.
5755  */
5756 
5757 int
owl_connection_defends(int move,int target1,int target2)5758 owl_connection_defends(int move, int target1, int target2)
5759 {
5760   int color = board[target1];
5761   int result = 0;
5762   int reading_nodes_when_called = get_reading_node_counter();
5763   int tactical_nodes;
5764   double start = 0.0;
5765   struct local_owl_data *owl;
5766 
5767   if (debug & DEBUG_OWL_PERFORMANCE)
5768     start = gg_cputime();
5769 
5770   ASSERT1(board[target2] == color, target2);
5771   TRACE("owl_connection_defends %1m %1m %1m\n", move, target1, target2);
5772 
5773   if (worm[target1].unconditional_status == DEAD)
5774     return 0;
5775   if (worm[target2].unconditional_status == DEAD)
5776     return 0;
5777 
5778   if (search_persistent_owl_cache(OWL_CONNECTION_DEFENDS, move, target1,
5779 				  target2, &result, NULL, NULL, NULL))
5780     return result;
5781 
5782   init_owl(&owl, target1, target2, NO_MOVE, 1, NULL);
5783 
5784   if (trymove(move, color, "owl_connection_defends", target1)) {
5785     owl_update_goal(move, SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE, owl, 0, NULL);
5786     if (!do_owl_attack(move, NULL, NULL, owl, 0))
5787       result = WIN;
5788     owl->lunches_are_current = 0;
5789     popgo();
5790   }
5791   tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
5792 
5793   DEBUG(DEBUG_OWL_PERFORMANCE,
5794 	"owl_conn_defends %1m %1m %1m, result %d (%d, %d nodes, %f seconds)\n",
5795 	move, target1, target2, result, local_owl_node_counter,
5796 	tactical_nodes, gg_cputime() - start);
5797 
5798   store_persistent_owl_cache(OWL_CONNECTION_DEFENDS, move, target1, target2,
5799 			     result, 0, 0, 0, tactical_nodes,
5800 			     owl->goal, color);
5801 
5802   return result;
5803 }
5804 
5805 
5806 /* This function attempts to make a list of dead strings
5807  * which may be relevant to the life of the goal dragon.
5808  * Such strings are called owl lunches. They are ignored
5809  * (treated as invisible) during the running of make_domains.
5810  *
5811  * In certain cases we also need to identify tactically safe strings
5812  * which should be included in the eyespace, e.g. in this position:
5813  *
5814  * -------
5815  * OXXOOXO
5816  * OX.O.XO
5817  * OXX.XXO
5818  * OOXXXOO
5819  * .OOOOO.
5820  *
5821  * The three O stones cannot be captured, but they can't live
5822  * independently without capturing the surrounding stones. We call
5823  * such stones INESSENTIAL and identify them by the condition that for
5824  * each liberty of the corresponding superstring, the following must
5825  * hold:
5826  *
5827  * 1. At least one neighbor of the liberty is the goal dragon.
5828  * 2. No neighbor of the liberty is the same color as the tested string,
5829  *    unless part of the same superstring.
5830  * 3. No neighbor of the liberty of the same color as the goal dragon
5831  *    does not belong to the goal dragon.
5832  * 4. No neighbor of the liberty belonging to the goal dragon can be
5833  *    tactically captured.
5834  *
5835  * There is a weakness with this characterization though, which can be
5836  * seen in this position:
5837  *
5838  * --------
5839  * OX..OOX.
5840  * OX.X.XOO
5841  * OX.XX.O.
5842  * O.XXOOO.
5843  * .OOOO...
5844  *
5845  * The two O stones intruding in X's eyespace cannot be tactically
5846  * captured and their liberties satisfy the requirements above. Still
5847  * it doesn't make any sense to count those stones as
5848  * inessential. Therefore we add another requirement on the stones
5849  * themself:
5850  *
5851  * 5. No neighbor of the stones does not belong to the goal or can be
5852  *    tactically captured.
5853  *
5854  * A second weakness can be noticed in this position:
5855  *
5856  * |OOOO.
5857  * |XXXO.
5858  * |O.XOO
5859  * |OXXXO
5860  * |.O.XO
5861  * +-----
5862  *
5863  * The white stones in the corner should qualify as inessential but
5864  * the corner liberty doesn't satisfy requirement 1. Therefore we add
5865  * an alternative requirement:
5866  *
5867  * 1b. The liberty is a topologically false eye with respect to the
5868  *     goal dragon.
5869  *
5870  * This is not quite good enough though, as shown in this position:
5871  *
5872  * ----------
5873  * OX.X.OO...
5874  * OXX.OOX.O.
5875  * O.XXXXX.O.
5876  * OOOOOOOOO.
5877  *
5878  * The four O stones are regarded as inessential after inclusion of
5879  * rule 1b, which is clearly inappropriate. To solve this problem we
5880  * modify the rule:
5881  *
5882  * 1b'. The liberty is a topologically false eye with respect to the
5883  *      goal dragon and is adjacent to no empty vertex.
5884  */
5885 
5886 static void
owl_find_lunches(struct local_owl_data * owl)5887 owl_find_lunches(struct local_owl_data *owl)
5888 {
5889   int k;
5890   int pos;
5891   int lunches = 0;
5892   int prevlunch;
5893   int lunch;
5894   int acode;
5895   int apos;
5896   int dcode;
5897   int dpos;
5898   int color = owl->color;
5899   int other = OTHER_COLOR(color);
5900   signed char already_checked[BOARDMAX];
5901 
5902   SGFTree *save_sgf_dumptree = sgf_dumptree;
5903   int save_count_variations = count_variations;
5904 
5905   sgf_dumptree = NULL;
5906   count_variations = 0;
5907   for (prevlunch = 0; prevlunch < MAX_LUNCHES; prevlunch++)
5908     owl->lunch[prevlunch] = NO_MOVE;
5909   memset(owl->inessential, 0, sizeof(owl->inessential));
5910 
5911   memset(already_checked, 0, sizeof(already_checked));
5912   for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
5913     if (board[pos] == color && owl->goal[pos]) {
5914       /* Loop over the eight neighbors. */
5915       for (k = 0; k < 8; k++) {
5916 	int pos2 = pos + delta[k];
5917 
5918 	/* If the immediate neighbor is empty, we look two steps away. */
5919 	if (k < 4 && board[pos2] == EMPTY)
5920 	  pos2 += delta[k];
5921 
5922 	if (board[pos2] != other)
5923 	  continue;
5924 
5925 	lunch = find_origin(pos2);
5926 	if (already_checked[lunch])
5927 	  continue;
5928 	already_checked[lunch] = 1;
5929 
5930 	attack_and_defend(lunch, &acode, &apos, &dcode, &dpos);
5931 	if (acode != 0) {
5932 	  owl->lunch[lunches] = lunch;
5933 	  owl->lunch_attack_code[lunches]  = acode;
5934 	  owl->lunch_attack_point[lunches] = apos;
5935 	  owl->lunch_defend_code[lunches]  = dcode;
5936 	  ASSERT1(board[apos] == EMPTY, lunch);
5937 	  if (dcode != 0) {
5938 	    owl->lunch_defense_point[lunches] = dpos;
5939 	    ASSERT1(board[dpos] == EMPTY, lunch);
5940 	  }
5941 	  else
5942 	    owl->lunch_defense_point[lunches] = NO_MOVE;
5943 	  lunches++;
5944 	  if (lunches == MAX_LUNCHES) {
5945 	    sgf_dumptree = save_sgf_dumptree;
5946 	    count_variations = save_count_variations;
5947 	    owl->lunches_are_current = 1;
5948 	    return;
5949 	  }
5950 	}
5951 	else if (!owl->inessential[lunch]) {
5952 	  /* Test for inessentiality. */
5953 	  int adj;
5954 	  int adjs[MAXCHAIN];
5955 	  int num_stones;
5956 	  int stones[MAX_BOARD * MAX_BOARD];
5957 	  int liberties;
5958 	  int libs[MAXLIBS];
5959 	  int r;
5960 	  int essential = 0;
5961 	  int superstring[BOARDMAX];
5962 
5963 	  /* First check the neighbors of the string. */
5964 	  adj = chainlinks(lunch, adjs);
5965 	  for (r = 0; r < adj; r++) {
5966 	    if (!owl->goal[adjs[r]] || attack(adjs[r], NULL) != 0) {
5967 	      essential = 1;
5968 	      break;
5969 	    }
5970 	  }
5971 
5972 	  if (essential)
5973 	    continue;
5974 
5975 	  find_superstring_stones_and_liberties(lunch, &num_stones, stones,
5976 						&liberties, libs, 0);
5977 
5978 	  memset(superstring, 0, sizeof(superstring));
5979 	  for (r = 0; r < num_stones; r++)
5980 	    superstring[stones[r]] = 1;
5981 
5982 	  for (r = 0; r < liberties; r++) {
5983 	    int bpos = libs[r];
5984 	    int goal_found = 0;
5985 	    int s;
5986 
5987 	    for (s = 0; s < 4; s++) {
5988 	      int cpos = bpos + delta[s];
5989 
5990 	      if (!ON_BOARD(cpos))
5991 		continue;
5992 	      if (board[cpos] == color) {
5993 		if (attack(cpos, NULL) != 0) {
5994 		  essential = 1;
5995 		  break;
5996 		}
5997 		else if (owl->goal[cpos])
5998 		  goal_found = 1;
5999 		else {
6000 		  essential = 1;
6001 		  break;
6002 		}
6003 	      }
6004 	      else if (board[cpos] == other
6005 		       && !superstring[cpos]) {
6006 		essential = 1;
6007 		break;
6008 	      }
6009 	    }
6010 	    if (!goal_found) {
6011 	      /* Requirement 1 not satisfied. Test requirement 1b.
6012 	       * N.B. This is a simplified topological eye test.
6013 	       * The simplification may be good, bad, or neutral.
6014 	       */
6015 	      int off_board = 0;
6016 	      int diagonal_goal = 0;
6017 	      for (s = 4; s < 8; s++) {
6018 		if (!ON_BOARD(bpos + delta[s]))
6019 		  off_board++;
6020 		else if (owl->goal[bpos + delta[s]])
6021 		  diagonal_goal++;
6022 	      }
6023 	      if (diagonal_goal + (off_board >= 2) < 2)
6024 		essential = 1;
6025 	      else {
6026 		/* Check that the liberty is adjacent to no empty
6027 		 * vertex, as required by 1b'.
6028 		 */
6029 		for (s = 0; s < 4; s++) {
6030 		  if (board[bpos + delta[s]] == EMPTY) {
6031 		    essential = 1;
6032 		    break;
6033 		  }
6034 		}
6035 	      }
6036 	    }
6037 
6038 	    if (essential)
6039 	      break;
6040 	  }
6041 
6042 	  if (!essential) {
6043 	    TRACE("Inessential string found at %1m.\n", lunch);
6044 	    for (r = 0; r < num_stones; r++)
6045 	      owl->inessential[stones[r]] = 1;
6046 	  }
6047 	}
6048       }
6049     }
6050   }
6051 
6052   owl->lunches_are_current = 1;
6053   sgf_dumptree = save_sgf_dumptree;
6054   count_variations = save_count_variations;
6055 }
6056 
6057 
6058 /* Try to improve the move to attack a lunch. Essentially we try to avoid
6059  * unsafe moves when there are less risky ways to attack.
6060  *
6061  * This function also improves lunch attack point in a special case when
6062  * we capture a one- or two-stone lunch on the first line. If we eat it
6063  * with a first line move, there is a huge risk we'll end up with a false
6064  * eye. Therefore, we move the attack to the second line when it works.
6065  *
6066  *   .*OO	.*OOO	    .*OOOO
6067  *   .,XO	.,X.O	    .,XX.O
6068  *   ----	-----	    ------
6069  *
6070  * In all these position the attack point is moved from ',' to '*'.
6071  */
6072 static int
improve_lunch_attack(int lunch,int attack_point)6073 improve_lunch_attack(int lunch, int attack_point)
6074 {
6075   int color = OTHER_COLOR(board[lunch]);
6076   int defense_point;
6077   int k;
6078 
6079   if (safe_move(attack_point, color)) {
6080     if (is_edge_vertex(lunch)
6081 	&& is_edge_vertex(attack_point)
6082 	&& neighbor_of_string(attack_point, lunch)) {
6083       int stones = countstones(lunch);
6084       int libs[2];
6085 
6086       if (stones == 1
6087 	  || (stones == 2
6088 	      && findlib(lunch, 2, libs) == 2
6089 	      && is_edge_vertex(libs[0])
6090 	      && is_edge_vertex(libs[1]))) {
6091 	for (k = 0; k < 4; k++) {
6092 	  int apos = attack_point + delta[k];
6093 	  if (!ON_BOARD(attack_point - delta[k]) && board[apos] == EMPTY) {
6094 	    if (does_attack(apos, lunch) && safe_move(apos, color))
6095 	      return apos;
6096 	    break;
6097 	  }
6098 	}
6099       }
6100     }
6101 
6102     return attack_point;
6103   }
6104 
6105   for (k = 0; k < 4; k++) {
6106     int pos = attack_point + delta[k];
6107     if (board[pos] == color
6108 	&& attack(pos, NULL)
6109 	&& find_defense(pos, &defense_point)
6110 	&& defense_point != NO_MOVE
6111 	&& does_attack(defense_point, lunch)) {
6112       TRACE("Moved attack of lunch %1m from %1m to %1m.\n",
6113 	    lunch, attack_point, defense_point);
6114       return defense_point;
6115     }
6116   }
6117 
6118   return attack_point;
6119 }
6120 
6121 /* Try to improve the move to defend a lunch.
6122  *
6123  * An example where this is useful is the position below, where the
6124  * defense of A is moved from b to c. This is a possible variation in
6125  * ld_owl:182.
6126  *
6127  * ...X..|      ...X..|
6128  * ...X..|	...Xc.|
6129  * ..XXO.|	..XXOb|
6130  * XXXOOX|	XXXOOA|
6131  * XOOOX.|	XOOOX.|
6132  * .XOX.X|	.XOX.X|
6133  * ------+	------+
6134  */
6135 static int
improve_lunch_defense(int lunch,int defense_point)6136 improve_lunch_defense(int lunch, int defense_point)
6137 {
6138   int color = board[lunch];
6139   int k;
6140 
6141   for (k = 0; k < 4; k++) {
6142     int pos = defense_point + delta[k];
6143     if (board[pos] == OTHER_COLOR(color)
6144 	&& countlib(pos) == 2) {
6145       int libs[2];
6146       int pos2;
6147 
6148       findlib(pos, 2, libs);
6149       if (libs[0] == defense_point)
6150 	pos2 = libs[1];
6151       else
6152 	pos2 = libs[0];
6153 
6154       if (accuratelib(pos2, color, MAXLIBS, NULL)
6155 	  > accuratelib(defense_point, color, MAXLIBS, NULL)
6156 	  && does_defend(pos2, lunch)) {
6157 	TRACE("Moved defense of lunch %1m from %1m to %1m.\n",
6158 	      lunch, defense_point, pos2);
6159 	return pos2;
6160       }
6161     }
6162   }
6163 
6164   return defense_point;
6165 }
6166 
6167 
6168 /* Wrapper for make domains. The second set of owl data is optional.
6169  * Use a null pointer if it is not needed. Otherwise, make_domains
6170  * is run separately for the two owl data, but information about
6171  * tactically dead lunches is used from *both* sources through
6172  * the owl_lively() calls.
6173  */
6174 
6175 static void
owl_make_domains(struct local_owl_data * owla,struct local_owl_data * owlb)6176 owl_make_domains(struct local_owl_data *owla, struct local_owl_data *owlb)
6177 {
6178   /* We need to set this so that owl_lively() can be used. */
6179   struct eye_data *black_eye = NULL;
6180   struct eye_data *white_eye = NULL;
6181 
6182   current_owl_data = owla;
6183   other_owl_data = owlb;
6184 
6185   if (!owla->lunches_are_current)
6186     owl_find_lunches(owla);
6187   if (owla->color == BLACK)
6188     black_eye = owla->my_eye;
6189   else
6190     white_eye = owla->my_eye;
6191 
6192   if (owlb) {
6193     gg_assert(owla->color == OTHER_COLOR(owlb->color));
6194     if (!owlb->lunches_are_current)
6195       owl_find_lunches(owlb);
6196     if (owlb->color == BLACK)
6197       black_eye = owlb->my_eye;
6198     else
6199       white_eye = owlb->my_eye;
6200   }
6201   make_domains(black_eye, white_eye, 1);
6202 }
6203 
6204 /* True unless (pos) is EMPTY or occupied by a lunch for the goal dragon.
6205  * Used during make_domains (see optics.c: lively macro). A ``lively''
6206  * worm is one that might be alive, hence cannot be ignored in
6207  * determining eye spaces.
6208  */
6209 
6210 int
owl_lively(int pos)6211 owl_lively(int pos)
6212 {
6213   int origin;
6214   int lunch;
6215   ASSERT_ON_BOARD1(pos);
6216 
6217   if (board[pos] == EMPTY)
6218     return 0;
6219   origin = find_origin(pos);
6220 
6221   /* When reading a semeai there is a second set of owl data to consider.
6222    * Strings of the second owl are considered lively no matter what,
6223    * since declaring such a string dead prematurely can prevent the
6224    * semeai code from finishing its job.
6225    *
6226    * On the other hand a friendly string which is a lunch of the
6227    * other dragon and can't be saved is not lively.
6228    */
6229   if (other_owl_data) {
6230 
6231     if (include_semeai_worms_in_eyespace && other_owl_data->goal[pos])
6232       return 0;
6233 
6234     if (other_owl_data->goal[pos] && !semeai_trust_tactical_attack(pos))
6235       return 1;
6236     /* FIXME: Shouldn't we check other_owl_data->inessential[origin] here? */
6237     for (lunch = 0; lunch < MAX_LUNCHES; lunch++)
6238       if (other_owl_data->lunch[lunch] == origin
6239 	  && other_owl_data->lunch_defense_point[lunch] == NO_MOVE)
6240 	return 0;
6241   }
6242 
6243   /* Inessential stones are not lively. */
6244   if (current_owl_data->inessential[origin])
6245     return 0;
6246 
6247   /* Lunches that can't be saved are dead, so don't report them as lively. */
6248   for (lunch = 0; lunch < MAX_LUNCHES; lunch++)
6249     if (current_owl_data->lunch[lunch] == origin
6250 	&& current_owl_data->lunch_defense_point[lunch] == NO_MOVE)
6251       return 0;
6252 
6253   return 1;
6254 }
6255 
6256 
6257 /* Caching version of safe_move for the callback. This function has
6258  * its own cache, separate from the global safe move cache. Note that
6259  * since the cache is reset by owl_shapes before starting pattern
6260  * matching, and since (unlike safe_move) this function is always
6261  * called from the same place in owl_shapes_callback, the color will
6262  * be the same each time it is called. So there is no need to have
6263  * separate caches for B and W.
6264  */
6265 
6266 static int
owl_safe_move(int move,int color)6267 owl_safe_move(int move, int color)
6268 {
6269   int acode, safe = 0;
6270 
6271   if (trymove(move, color, "owl_safe_move", 0)) {
6272     acode = attack(move, NULL);
6273     if (acode != WIN)
6274       safe = 1;
6275     else
6276       safe = 0;
6277     popgo();
6278   }
6279   current_owl_data->safe_move_cache[move] = safe+1;
6280   return safe;
6281 }
6282 
6283 
6284 /* This function, called when stackp==0, returns true if capturing
6285  * the string at (str) results in a live group.
6286  */
6287 
6288 #define MAX_SUBSTANTIAL_LIBS 10
6289 
6290 int
owl_substantial(int str)6291 owl_substantial(int str)
6292 {
6293   int k;
6294   int libs[MAX_SUBSTANTIAL_LIBS + 1];
6295   int liberties = findlib(str, MAX_SUBSTANTIAL_LIBS+1, libs);
6296   int reading_nodes_when_called = get_reading_node_counter();
6297   int tactical_nodes;
6298   int result;
6299   double start = 0.0;
6300   struct local_owl_data *owl;
6301   int num_moves = 0;
6302 
6303   if (debug & DEBUG_OWL_PERFORMANCE)
6304     start = gg_cputime();
6305 
6306   /* FIXME: We want to use the full init_owl here too (cf. similar
6307    * remark below).
6308    */
6309   reduced_init_owl(&owl, 1);
6310 
6311   owl->color = OTHER_COLOR(board[str]);
6312   local_owl_node_counter = 0;
6313 
6314   /* Big strings are always substantial since the biggest nakade is
6315    * six stones. (There are probably rare exceptions to this
6316    * rule, but they are unlikely to come up in a game.)
6317    */
6318   if (countstones(str) > 6)
6319     return 1;
6320 
6321   if (liberties > MAX_SUBSTANTIAL_LIBS)
6322     return 0;
6323 
6324   memset(owl->goal, 0, sizeof(owl->goal));
6325   /* Mark the neighbors of the string. If one is found which is alive, return
6326    * true. */
6327   {
6328     int adjs[MAXCHAIN];
6329     int adj;
6330 
6331     adj = chainlinks(str, adjs);
6332     for (k = 0; k < adj; k++) {
6333       if (dragon[adjs[k]].status == ALIVE)
6334 	return 1;
6335       mark_dragon(adjs[k], owl->goal, 1);
6336     }
6337   }
6338 
6339   /* We must check the cache while stackp == 0, but we wait until the
6340    * trivial tests have been done.
6341    */
6342   if (search_persistent_owl_cache(OWL_SUBSTANTIAL, str, 0, 0,
6343 				  &result, NULL, NULL, NULL))
6344     return result;
6345 
6346   /* fill all the liberties */
6347   for (k = 0; k < liberties; k++) {
6348     if (trymove(libs[k], owl->color, NULL, 0)) {
6349       if (get_level() >= 8)
6350 	increase_depth_values();
6351       owl->goal[libs[k]] = 1;
6352       num_moves++;
6353     }
6354     else {
6355       /* if we can't fill, try swapping with the next liberty */
6356       if (k < liberties-1
6357 	  && trymove(libs[k+1], owl->color, NULL, 0)) {
6358 	if (get_level() >= 8)
6359 	  increase_depth_values();
6360 	owl->goal[libs[k+1]] = 1;
6361 	libs[k+1] = libs[k];
6362 	num_moves++;
6363       }
6364       else {
6365 	/* Can't fill the liberties. Give up! */
6366 	while (num_moves-- > 0) {
6367 	  if (get_level() >= 8)
6368 	    decrease_depth_values();
6369 	  popgo();
6370 	}
6371 	return 0;
6372       }
6373     }
6374   }
6375   /* FIXME: We would want to use init_owl() here too, but it doesn't
6376    * fit very well with the construction of the goal array above.
6377    */
6378   memcpy(owl->cumulative_goal, owl->goal, BOARDMAX);
6379   compute_owl_escape_values(owl);
6380   owl_mark_boundary(owl);
6381   owl->lunches_are_current = 0;
6382 
6383   if (do_owl_attack(libs[0], NULL, NULL, owl, 0))
6384     result = 0;
6385   else
6386     result = 1;
6387   while (num_moves-- > 0) {
6388     if (get_level() >= 8)
6389       decrease_depth_values();
6390     popgo();
6391   }
6392 
6393   tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
6394   DEBUG(DEBUG_OWL_PERFORMANCE,
6395 	"owl_substantial %1m, result %d (%d, %d nodes, %f seconds)\n",
6396 	str, result, local_owl_node_counter,
6397 	tactical_nodes, gg_cputime() - start);
6398 
6399   store_persistent_owl_cache(OWL_SUBSTANTIAL, str, 0, 0, result, 0, 0, 0,
6400 			     tactical_nodes, owl->goal, owl->color);
6401 
6402   return result;
6403 }
6404 
6405 
6406 
6407 /* Returns true if and only if (i, j) is a 1-2 vertex, i.e. next to a
6408  * corner.
6409  */
6410 static int
one_two_point(int pos)6411 one_two_point(int pos)
6412 {
6413   int i = I(pos);
6414   int j = J(pos);
6415 
6416   if ((i == 0 || i == board_size-1 || j == 0 || j == board_size-1)
6417       && (i == 1 || i == board_size-2 || j == 1 || j == board_size-2))
6418     return 1;
6419 
6420   return 0;
6421 }
6422 
6423 
6424 
6425 /* Reports the number of eyes gotten by capturing a boundary string.
6426  * This implementation tends to give an optimistic view of the
6427  * chances, so if it tells that the lunch is worthless, it truly
6428  * should be. The converse is not true.
6429  */
6430 
6431 static void
sniff_lunch(int lunch,int * min,int * probable,int * max,struct local_owl_data * owl)6432 sniff_lunch(int lunch, int *min, int *probable, int *max,
6433 	    struct local_owl_data *owl)
6434 {
6435   int other = OTHER_COLOR(board[lunch]);
6436   int libs[MAXLIBS];
6437   int liberties;
6438   int r;
6439 
6440   ASSERT1(IS_STONE(board[lunch]), lunch);
6441 
6442   if (owl->boundary[lunch] == 2) {
6443     *min = 2;
6444     *probable = 2;
6445     *max = 2;
6446     return;
6447   }
6448 
6449   /* Do we believe this capture would help escaping? */
6450   liberties = findlib(lunch, MAXLIBS, libs);
6451   for (r = 0; r < liberties; r++) {
6452     if (owl->escape_values[libs[r]] > 0
6453 	&& !is_self_atari(libs[r], other)) {
6454       int k;
6455       for (k = 0; k < 8; k++)
6456 	if (ON_BOARD(libs[r] + delta[k]) && owl->goal[libs[r] + delta[k]])
6457 	  break;
6458       if (k == 8) {
6459 	*min = 2;
6460 	*probable = 2;
6461 	*max = 2;
6462 	return;
6463       }
6464     }
6465   }
6466 
6467   estimate_lunch_eye_value(lunch, min, probable, max, 1);
6468 
6469   if (*min < 2) {
6470     int bonus = estimate_lunch_half_eye_bonus(lunch, owl->half_eye);
6471     *min += bonus/2;
6472     *probable += bonus;
6473     *max += (bonus + 1)/2;
6474   }
6475 
6476   if (*probable < 2)
6477     eat_lunch_escape_bonus(lunch, min, probable, max, owl);
6478 }
6479 
6480 /* Capturing a lunch can give eyes by turning a false eye into a proper one,
6481  * etc. This function returns the likely increase in half eyes
6482  * by capturing the string at (lunch).
6483  */
6484 static int
estimate_lunch_half_eye_bonus(int lunch,struct half_eye_data half_eye[BOARDMAX])6485 estimate_lunch_half_eye_bonus(int lunch,
6486     			      struct half_eye_data half_eye[BOARDMAX])
6487 {
6488   int stones[10];
6489   int k;
6490   int size = findstones(lunch, 10, stones);
6491   int half_eyes = 0;
6492 
6493   ASSERT1(size < 10, lunch);
6494 
6495   for (k = 0; k < size; k++) {
6496     int stone = stones[k];
6497     int d;
6498     for (d = 4; d < 8; d++) {
6499       int pos = stone + delta[d];
6500       if (ON_BOARD(pos)
6501 	  && (is_halfeye(half_eye, pos) || is_false_eye(half_eye, pos)))
6502 	half_eyes++;
6503     }
6504   }
6505   return half_eyes;
6506 }
6507 
6508 
6509 void
estimate_lunch_eye_value(int lunch,int * min,int * probable,int * max,int appreciate_one_two_lunches)6510 estimate_lunch_eye_value(int lunch, int *min, int *probable, int *max,
6511 			 int appreciate_one_two_lunches)
6512 {
6513   int other = OTHER_COLOR(board[lunch]);
6514   int size = countstones(lunch);
6515 
6516   if (size > 6) {
6517     *min = 2;
6518     *probable = 2;
6519     *max = 2;
6520   }
6521   else if (size > 4) {
6522     *min = 1;
6523     *probable = 2;
6524     *max = 2;
6525   }
6526   else if (size > 2) {
6527     *min = 0;
6528     *probable = 1;
6529     *max = 2;
6530   }
6531   else if (size == 2) {
6532     int stones[2];
6533     findstones(lunch, 2, stones);
6534     /* A lunch on a 1-2 point tends always to be worth contesting. */
6535     if ((obvious_false_eye(stones[0], other)
6536 	|| obvious_false_eye(stones[1], other))
6537 	&& (!appreciate_one_two_lunches
6538 	    || !(one_two_point(stones[0]) || one_two_point(stones[1])))) {
6539       *min = 0;
6540       *probable = 0;
6541       *max = 0;
6542     }
6543     else {
6544       *min = 0;
6545       *probable = 1;
6546       *max = 1;
6547     }
6548   }
6549   else if (size == 1) {
6550     if (!obvious_false_eye(lunch, other)) {
6551       *min = 0;
6552       *probable = 1;
6553       *max = 1;
6554     }
6555     else {
6556       *min = 0;
6557       *probable = 0;
6558       *max = 0;
6559     }
6560   }
6561 }
6562 
6563 /* Gives a bonus for a lunch capture which joins a (or some) friendly
6564  * string(s) to the goal dragon and improves the escape potential at
6565  * the same time. This is indicated in some situations where the owl
6566  * code would stop the analysis because of various cutoffs. See
6567  * do_owl_defend()
6568  *
6569  * The following implementation tries to get a precise idea of the
6570  * escape potential improvement by calling dragon_escape() twice.
6571  */
6572 static void
eat_lunch_escape_bonus(int lunch,int * min,int * probable,int * max,struct local_owl_data * owl)6573 eat_lunch_escape_bonus(int lunch, int *min, int *probable, int *max,
6574 		       struct local_owl_data *owl)
6575 {
6576   int adjacent[MAXCHAIN];
6577   int neighbors;
6578   int adjoins = 0;
6579   int n;
6580   /* Be very careful before touching this value.
6581    * See owl_estimate_life() for details.
6582    */
6583   UNUSED(min);
6584 
6585   /* Don't mess up with kos */
6586   if (is_ko_point(lunch))
6587     return;
6588 
6589   neighbors = chainlinks(lunch, adjacent);
6590   for (n = 0; n < neighbors; n++)
6591     adjoins |= !owl->goal[adjacent[n]];
6592 
6593   if (adjoins) {
6594     int before, after;
6595     before = dragon_escape(owl->goal, owl->color, owl->escape_values);
6596     /* if the escape route is already large enough to be considered
6597      * a WIN by the owl code, then no need for more */
6598     if (before < 5) {
6599       signed char new_goal[BOARDMAX];
6600       memcpy(new_goal, owl->goal, sizeof(new_goal));
6601       for (n = 0; n < neighbors; n++)
6602 	if (!owl->goal[adjacent[n]])
6603 	  mark_string(adjacent[n], new_goal, 2);
6604       after = dragon_escape(new_goal, owl->color, owl->escape_values);
6605 
6606       /* Following is completely ad hoc. Another set of tests might
6607        * very well get better results. */
6608       if (after - before >= 3) {
6609 	if (after >= 8 || (before == 0 && after >= 5)) {
6610 	  *probable = 2;
6611 	  *max = 2;
6612 	}
6613 	else if (*max < 2)
6614 	  (*max)++;
6615       }
6616     }
6617   }
6618 }
6619 
6620 
6621 /* Find a new origin when it has been captured or cut out of the
6622  * goal. Used in do_owl_attack()
6623  */
6624 static int
select_new_goal_origin(int origin,struct local_owl_data * owl)6625 select_new_goal_origin(int origin, struct local_owl_data *owl)
6626 {
6627   int pos;
6628   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
6629     if (board[pos] == owl->color && owl->goal[pos] == 1)
6630       return find_origin(pos);
6631 
6632   return origin;
6633 }
6634 
6635 
6636 /* Retrieve topological eye values stored in the half_eye[] array of
6637  * the current owl data.
6638  *
6639  * FIXME: Sooner or later we'll want this to return a non-rounded
6640  * value. When we change this, we have to review all patterns using
6641  * the autohelper owl_topological_eye().
6642  */
6643 int
owl_topological_eye(int pos,int color)6644 owl_topological_eye(int pos, int color)
6645 {
6646   float value;
6647   UNUSED(color);
6648   value = current_owl_data->half_eye[pos].value;
6649   if (value > 2.0 && value < 4.0)
6650     return 3;
6651   else if (value <= 2.0)
6652     return (int) (value + 0.99); /* Round up. */
6653   else
6654     return (int) value;          /* Round down. */
6655 }
6656 
6657 /* This function returns true if it is judged that the capture of the
6658  * string at (pos) is sufficient to create one eye.
6659  *
6660  * Update: Now it instead returns the max number of eyes.
6661  */
6662 
6663 int
vital_chain(int pos)6664 vital_chain(int pos)
6665 {
6666   int min;
6667   int probable;
6668   int max;
6669   sniff_lunch(pos, &min, &probable, &max, current_owl_data);
6670 
6671   return max;
6672 }
6673 
6674 
6675 static void
compute_owl_escape_values(struct local_owl_data * owl)6676 compute_owl_escape_values(struct local_owl_data *owl)
6677 {
6678   int pos;
6679   int m, n;
6680   signed char safe_stones[BOARDMAX];
6681   SGFTree *save_sgf_dumptree = sgf_dumptree;
6682   int save_count_variations = count_variations;
6683   signed char mx[BOARDMAX];
6684   memset(mx, 0, sizeof(mx));
6685 
6686   sgf_dumptree = NULL;
6687   count_variations = 0;
6688   get_lively_stones(OTHER_COLOR(owl->color), safe_stones);
6689   sgf_dumptree = save_sgf_dumptree;
6690   count_variations = save_count_variations;
6691 
6692   compute_escape_influence(owl->color, safe_stones, NULL, NULL,
6693 			   owl->escape_values);
6694 
6695   DEBUG(DEBUG_ESCAPE, "Owl escape values:\n");
6696   for (m = 0; m < board_size; m++) {
6697     for (n = 0; n < board_size; n++) {
6698       pos = POS(m, n);
6699       if (dragon[pos].color == owl->color && !owl->goal[pos]) {
6700 	if (dragon[pos].crude_status == ALIVE)
6701 	  owl->escape_values[pos] = 6;
6702 	else if (dragon[pos].crude_status == UNKNOWN) {
6703 	  if (DRAGON2(pos).moyo_size > 5)
6704 	    owl->escape_values[pos] = 4;
6705 	  else if (DRAGON2(pos).escape_route > 5) {
6706 	    if (mx[dragon[pos].origin])
6707 	      owl->escape_values[pos] = owl->escape_values[dragon[pos].origin];
6708 	    else {
6709 	      int pos2;
6710 	      signed char escape_values[BOARDMAX];
6711 	      signed char dragon_stones[BOARDMAX];
6712 
6713 	      compute_escape_influence(owl->color, safe_stones, owl->goal,
6714 				       NULL, escape_values);
6715 
6716 	      /* mark_dragon() can't be used here in case a string of
6717 	       * the dragon was captured by the initial move in
6718 	       * owl_does_attack(). Actually it isn't really proper to
6719 	       * use is_same_dragon() at stackp>0 either but it's more
6720 	       * robust at least.
6721 	       */
6722 	      for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++) {
6723 		if (ON_BOARD(pos2))
6724 		  dragon_stones[pos2] = is_same_dragon(pos2, pos);
6725 	      }
6726 
6727 	      if (dragon_escape(dragon_stones, owl->color, escape_values) > 5)
6728 		owl->escape_values[dragon[pos].origin] = 4;
6729 
6730 	      mx[dragon[pos].origin] = 1;
6731 	    }
6732 	  }
6733 	}
6734       }
6735       DEBUG(DEBUG_ESCAPE, "%o%d", owl->escape_values[pos]);
6736     }
6737     DEBUG(DEBUG_ESCAPE, "%o\n");
6738   }
6739 }
6740 
6741 
6742 /* Used by autohelpers. */
6743 int
owl_escape_value(int pos)6744 owl_escape_value(int pos)
6745 {
6746   /* FIXME: Should have a more robust mechanism to avoid
6747    * escaping inwards. Returning a negative value is just a kludge.
6748    */
6749   int k;
6750   ASSERT_ON_BOARD1(pos);
6751   if (current_owl_data->goal[pos])
6752     return -10;
6753 
6754   if (board[pos] == EMPTY)
6755     for (k = 0; k < 8; k++)
6756       if (ON_BOARD(pos + delta[k]) && current_owl_data->goal[pos + delta[k]])
6757 	return -10;
6758 
6759   return current_owl_data->escape_values[pos];
6760 }
6761 
6762 
6763 /* Used by autohelpers. */
6764 int
owl_goal_dragon(int pos)6765 owl_goal_dragon(int pos)
6766 {
6767   return current_owl_data->goal[pos] != 0;
6768 }
6769 
6770 /* Used by autohelpers.
6771  * Returns 1 if (pos) is an eyespace for the color of the dragon currently
6772  * under owl investigation.
6773  */
6774 int
owl_eyespace(int pos)6775 owl_eyespace(int pos)
6776 {
6777   int origin;
6778   ASSERT_ON_BOARD1(pos);
6779 
6780   origin = current_owl_data->my_eye[pos].origin;
6781   return (ON_BOARD(origin)
6782 	  && (current_owl_data->my_eye[origin].color
6783 	      == current_owl_data->color)
6784 	  && max_eyes(&current_owl_data->my_eye[origin].value) > 0);
6785 }
6786 
6787 
6788 /* Used by autohelpers.
6789  * Returns 1 if (pos) is an eyespace for the color of the dragon currently
6790  * under owl investigation, which is possibly worth (at least) 2 eyes.
6791  */
6792 int
owl_big_eyespace(int pos)6793 owl_big_eyespace(int pos)
6794 {
6795   int origin;
6796   ASSERT_ON_BOARD1(pos);
6797 
6798   origin = current_owl_data->my_eye[pos].origin;
6799   return (ON_BOARD(origin)
6800 	  && (current_owl_data->my_eye[origin].color
6801 	      == current_owl_data->color)
6802 	  && max_eyes(&current_owl_data->my_eye[origin].value) >= 2);
6803 }
6804 
6805 
6806 /* Used by autohelpers.
6807  * Returns 1 if (pos) is an eyespace for the color of the dragon currently
6808  * under owl investigation.
6809  */
6810 int
owl_mineye(int pos)6811 owl_mineye(int pos)
6812 {
6813   int origin;
6814   ASSERT_ON_BOARD1(pos);
6815 
6816   origin = current_owl_data->my_eye[pos].origin;
6817   if (!ON_BOARD(origin)
6818       || (current_owl_data->my_eye[origin].color
6819 	  != current_owl_data->color))
6820     return 0;
6821 
6822   return min_eyes(&current_owl_data->my_eye[origin].value);
6823 }
6824 
6825 
6826 /* Used by autohelpers.
6827  * Returns 1 if (pos) is an eyespace for the color of the dragon currently
6828  * under owl investigation.
6829  */
6830 int
owl_maxeye(int pos)6831 owl_maxeye(int pos)
6832 {
6833   int origin;
6834   ASSERT_ON_BOARD1(pos);
6835 
6836   origin = current_owl_data->my_eye[pos].origin;
6837   if (!ON_BOARD(origin)
6838       || (current_owl_data->my_eye[origin].color
6839 	  != current_owl_data->color))
6840     return 0;
6841 
6842   return max_eyes(&current_owl_data->my_eye[origin].value);
6843 }
6844 
6845 
6846 /* Used by autohelpers.
6847  * Returns 1 if (pos) is a non-marginal eyespace for the color of the
6848  * dragon currently under owl investigation.
6849  */
6850 int
owl_proper_eye(int pos)6851 owl_proper_eye(int pos)
6852 {
6853   ASSERT_ON_BOARD1(pos);
6854 
6855   return ((current_owl_data->my_eye[pos].color
6856 	   == current_owl_data->color)
6857 	  && !current_owl_data->my_eye[pos].marginal);
6858 }
6859 
6860 
6861 /* Used by autohelpers.
6862  * Returns the effective size of the eyespace at pos.
6863  */
6864 int
owl_eye_size(int pos)6865 owl_eye_size(int pos)
6866 {
6867   int origin;
6868   ASSERT_ON_BOARD1(pos);
6869 
6870   origin = current_owl_data->my_eye[pos].origin;
6871   return current_owl_data->my_eye[origin].esize
6872 	 - current_owl_data->my_eye[origin].msize;
6873 }
6874 
6875 
6876 /* Used by autohelpers.
6877  * Returns whether str is a lunch.
6878  */
6879 int
owl_lunch(int str)6880 owl_lunch(int str)
6881 {
6882   int k;
6883   int origin;
6884   ASSERT_ON_BOARD1(str);
6885   ASSERT1(current_owl_data->lunches_are_current, str);
6886   origin = find_origin(str);
6887 
6888   for (k = 0; k < MAX_LUNCHES; k++) {
6889     if (current_owl_data->lunch[k] == NO_MOVE)
6890       break;
6891     if (current_owl_data->lunch[k] == origin)
6892       return 1;
6893   }
6894 
6895   return 0;
6896 }
6897 
6898 
6899 /* Used by autohelpers.
6900 
6901  * Returns 1 if (pos) is considered to be a strong dragon. This is
6902  * intended to be used to decide whether connecting to some external
6903  * stones is an easy way to live. The current implementation is fairly
6904  * conservative, requiring that (pos) was part of a dragon with two
6905  * eyes according to the static analysis. This requirement may be
6906  * relaxed considerably in the future.
6907  *
6908  * (pos) must not be part of the goal dragon.
6909  */
6910 int
owl_strong_dragon(int pos)6911 owl_strong_dragon(int pos)
6912 {
6913   ASSERT_ON_BOARD1(pos);
6914   ASSERT1(IS_STONE(board[pos]), pos);
6915 
6916   return (!current_owl_data->goal[pos]
6917 	  && dragon[pos].color == board[pos]
6918 	  && dragon[pos].crude_status == ALIVE);
6919 }
6920 
6921 
6922 static int
owl_escape_route(struct local_owl_data * owl)6923 owl_escape_route(struct local_owl_data *owl)
6924 {
6925   signed char modified_escape[BOARDMAX];
6926   int pos;
6927   memcpy(modified_escape, owl->escape_values, sizeof(modified_escape));
6928   for (pos = BOARDMIN; pos < BOARDMAX; pos++)
6929     if (ON_BOARD(pos) && owl->cumulative_goal[pos])
6930       modified_escape[pos] = 0;
6931   return dragon_escape(owl->goal, owl->color, modified_escape);
6932 }
6933 
6934 
6935 /****************************
6936  * Initialization of owl data
6937  ****************************/
6938 
6939 /* This is a temporary solution. We want to be able to use the full
6940  * init_owl() also in owl_substantial.
6941  */
6942 static void
reduced_init_owl(struct local_owl_data ** owl,int at_bottom_of_stack)6943 reduced_init_owl(struct local_owl_data **owl, int at_bottom_of_stack)
6944 {
6945   if (at_bottom_of_stack)
6946     owl_stack_pointer = 0;
6947   else
6948     owl_stack_pointer++;
6949 
6950   check_owl_stack_size();
6951   *owl = owl_stack[owl_stack_pointer];
6952   VALGRIND_MAKE_WRITABLE(*owl, sizeof(struct local_owl_data));
6953 }
6954 
6955 
6956 /* Initialize owl data. Set at_bottom_of_stack to 1 the first time you
6957  * call init_owl() and to 0 any following time (only relevant if you
6958  * need more than one set of owl data).
6959  */
6960 static void
init_owl(struct local_owl_data ** owl,int target1,int target2,int move,int at_bottom_of_stack,int new_dragons[BOARDMAX])6961 init_owl(struct local_owl_data **owl, int target1, int target2, int move,
6962          int at_bottom_of_stack, int new_dragons[BOARDMAX])
6963 {
6964   reduced_init_owl(owl, at_bottom_of_stack);
6965 
6966   local_owl_node_counter = 0;
6967   (*owl)->lunches_are_current = 0;
6968   owl_mark_dragon(target1, target2, *owl, new_dragons);
6969   if (move != NO_MOVE)
6970     owl_update_goal(move, SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE, *owl, 0, NULL);
6971   compute_owl_escape_values(*owl);
6972 }
6973 
6974 
6975 /***********************
6976  * Storage of owl data
6977  ***********************/
6978 
6979 /* Check the size of the owl stack and extend it if too small. */
6980 static void
check_owl_stack_size(void)6981 check_owl_stack_size(void)
6982 {
6983   while (owl_stack_size <= owl_stack_pointer) {
6984     owl_stack[owl_stack_size] = malloc(sizeof(*owl_stack[0]));
6985     gg_assert(owl_stack[owl_stack_size] != NULL);
6986     owl_stack_size++;
6987   }
6988 }
6989 
6990 /* Push owl data one step upwards in the stack. Gets called from
6991  * push_owl.
6992  */
6993 static void
do_push_owl(struct local_owl_data ** owl)6994 do_push_owl(struct local_owl_data **owl)
6995 {
6996   struct local_owl_data *new_owl = owl_stack[owl_stack_pointer];
6997 
6998   /* Mark all the data in *new_owl as uninitialized. */
6999   VALGRIND_MAKE_WRITABLE(new_owl, sizeof(struct local_owl_data));
7000   /* Copy the owl data. */
7001   memcpy(new_owl->goal, (*owl)->goal, sizeof(new_owl->goal));
7002   memcpy(new_owl->cumulative_goal, (*owl)->cumulative_goal,
7003          sizeof(new_owl->cumulative_goal));
7004   memcpy(new_owl->boundary, (*owl)->boundary, sizeof(new_owl->boundary));
7005   memcpy(new_owl->neighbors, (*owl)->neighbors, sizeof(new_owl->neighbors));
7006   memcpy(new_owl->escape_values, (*owl)->escape_values,
7007 	 sizeof(new_owl->escape_values));
7008   new_owl->color = (*owl)->color;
7009 
7010   new_owl->lunches_are_current = 0;
7011 
7012   /* Needed for stack organization. Since there may be one or two sets
7013    * of owl data active at we don't know whether to restore from the
7014    * previos stack entry or two steps back.
7015    */
7016   new_owl->restore_from = *owl;
7017 
7018   /* Finally move the *owl pointer. */
7019   *owl = new_owl;
7020 }
7021 
7022 
7023 /* Push owl data one step upwards in the stack. The stack is extended
7024  * with dynamically allocated memory if it is too small.
7025  *
7026  * This function no longer may move existing owl data around, so
7027  * existing pointers do not risk becoming invalid.
7028  */
7029 static void
push_owl(struct local_owl_data ** owl)7030 push_owl(struct local_owl_data **owl)
7031 {
7032   owl_stack_pointer++;
7033   check_owl_stack_size();
7034   do_push_owl(owl);
7035 }
7036 
7037 
7038 /* Retrieve owl data from the stack. */
7039 static void
pop_owl(struct local_owl_data ** owl)7040 pop_owl(struct local_owl_data **owl)
7041 {
7042   *owl = (*owl)->restore_from;
7043   owl_stack_pointer--;
7044 }
7045 
7046 
7047 /*
7048  * List worms in order to track captures during owl reading
7049  * (GAIN/LOSS codes)
7050  */
7051 static int
list_goal_worms(struct local_owl_data * owl,int goal_worm[MAX_GOAL_WORMS])7052 list_goal_worms(struct local_owl_data *owl, int goal_worm[MAX_GOAL_WORMS])
7053 {
7054   int pos, k;
7055   int w = 0;
7056 
7057   for (k = 0; k < MAX_GOAL_WORMS; k++)
7058     goal_worm[k] = NO_MOVE;
7059 
7060   for (pos = BOARDMIN; pos < BOARDMAX && w < MAX_GOAL_WORMS; pos++) {
7061     if (ON_BOARD(pos)
7062 	&& board[pos]
7063 	&& owl->goal[pos] == 1) {
7064       int origin = find_origin(pos);
7065       for (k = 0; k < w; k++)
7066 	if (goal_worm[k] == origin)
7067 	  break;
7068       if (k == w)
7069 	goal_worm[w++] = pos;
7070     }
7071   }
7072 
7073   /* experimental: let's try to fill up the array with other neighboring
7074    * opponent worms
7075    */
7076   if (1 && (w > 0) && (w < MAX_GOAL_WORMS)) {
7077     pos = goal_worm[0];
7078     for (k = 0; k < DRAGON2(pos).neighbors && w < MAX_GOAL_WORMS; k++) {
7079       int ii;
7080       int d = DRAGON2(pos).adjacent[k];
7081       if (DRAGON(d).color != owl->color)
7082 	continue;
7083 
7084       for (ii = BOARDMIN; ii < BOARDMAX && w < MAX_GOAL_WORMS; ii++)
7085 	if (ON_BOARD(ii) && board[ii] && worm[ii].origin == ii
7086 	    && worm[ii].size >= 3 && dragon[ii].id == d)
7087 	  goal_worm[w++] = ii;
7088     }
7089   }
7090 
7091   return w;
7092 }
7093 
7094 static void
prepare_goal_list(int str,struct local_owl_data * owl,int list[MAX_GOAL_WORMS],int * flag,int * kworm,int do_list)7095 prepare_goal_list(int str, struct local_owl_data *owl,
7096 		  int list[MAX_GOAL_WORMS], int *flag,
7097 		  int *kworm, int do_list)
7098 {
7099   gg_assert(flag != NULL);
7100 
7101   if (kworm) {
7102     if (do_list)
7103       list_goal_worms(owl, list);
7104     /* N.B. We cannot use sizeof(list) below because a formal array
7105      * parameter implicitly is converted to a pointer and sizeof(list)
7106      * thus equals sizeof(int *), which is not what we want.
7107      */
7108     memcpy(dragon_goal_worms[dragon[str].id], list,
7109 	   sizeof(dragon_goal_worms[dragon[str].id]));
7110     *flag = 1;
7111   }
7112   else
7113     *flag = 0;
7114 }
7115 
7116 static void
finish_goal_list(int * flag,int * wpos,int list[MAX_GOAL_WORMS],int index)7117 finish_goal_list(int *flag, int *wpos, int list[MAX_GOAL_WORMS], int index)
7118 {
7119   gg_assert(flag != NULL);
7120   gg_assert(wpos != NULL);
7121 
7122   *flag = 0;
7123   if (index == MAX_GOAL_WORMS)
7124     *wpos = NO_MOVE;
7125   else
7126     *wpos = list[index];
7127 }
7128 
7129 
7130 /* Returns the number of worms in the goal dragon, and a pointer to each */
7131 
7132 #if 0
7133 static int
7134 catalog_goal(struct local_owl_data *owl, int goal_worm[MAX_GOAL_WORMS])
7135 {
7136   int pos;
7137   int worms = 0;
7138   int k;
7139 
7140   for (k = 0; k < MAX_WORMS; k++)
7141     goal_worm[k] = NO_MOVE;
7142 
7143   for (pos = BOARDMIN; pos < BOARDMAX && worms < MAX_WORMS; pos++)
7144     if (ON_BOARD(pos)
7145 	&& board[pos]
7146 	&& (owl->goal)[pos]) {
7147       int origin = find_origin(pos);
7148       if (pos == origin) {
7149 	if (0) {
7150 	  DEBUG(DEBUG_SEMEAI, "goal worm: %1m\n", pos);
7151 	}
7152 	goal_worm[worms++] = pos;
7153       }
7154     }
7155   return worms;
7156 }
7157 #endif
7158 
7159 /***********************/
7160 
7161 /* Clear statistics. */
7162 void
reset_owl_node_counter()7163 reset_owl_node_counter()
7164 {
7165   global_owl_node_counter = 0;
7166 }
7167 
7168 
7169 /* Retrieve statistics. */
7170 int
get_owl_node_counter()7171 get_owl_node_counter()
7172 {
7173   return global_owl_node_counter;
7174 }
7175 
7176 
7177 /*
7178  * Local Variables:
7179  * tab-width: 8
7180  * c-basic-offset: 2
7181  * End:
7182  */
7183