Ticket #116: gunnar_7_10.1b.diff

File gunnar_7_10.1b.diff, 24.8 kB (added by gunnar, 3 years ago)

bugfixes and more a patterns

  • engine/owl.c

    RCS file: /cvsroot/gnugo/gnugo/engine/owl.c,v
    retrieving revision 1.247
    diff -u -r1.247 owl.c
     
    118118 
    119119#define MAX_CUTS 5 
    120120 
     121enum same_dragon_value { 
     122  SAME_DRAGON_NOT_CONNECTED, 
     123  SAME_DRAGON_MAYBE_CONNECTED, 
     124  SAME_DRAGON_CONNECTED, 
     125  SAME_DRAGON_ALL_CONNECTED 
     126}; 
     127 
     128struct matched_pattern_data; 
     129 
    121130struct owl_move_data { 
    122131  int pos;          /* move coordinate */ 
    123132  int value;        /* value */ 
    124133  const char *name; /* name of the pattern suggesting the move */ 
    125   int same_dragon;  /* whether the move extends the dragon or not */ 
     134  /* whether the move extends the dragon or not */ 
     135  enum same_dragon_value same_dragon; 
    126136  int lunch;        /* Position of a lunch, if applicable.*/ 
    127137  int escape;       /* true if an escape pattern is matched */ 
    128138  int defense_pos;  /* defense coordinate for vital owl attack patterns. */ 
    129139  int cuts[MAX_CUTS]; /* strings of the goal that might get cut off */ 
     140  /* pointer to pattern data, used for SAME_DRAGON_ALL_CONNECTED */ 
     141  struct matched_pattern_data *pattern_data; 
    130142}; 
    131143 
    132144#define USE_BDIST 1 
     
    187199                                struct pattern *pattern_db, 
    188200                                int ll, void *data); 
    189201static void owl_add_move(struct owl_move_data *moves, int move, int value, 
    190                          const char *reason, int same_dragon, int lunch, 
    191                          int escape, int defense_pos, int max_moves); 
     202                         const char *reason, 
     203                         enum same_dragon_value same_dragon, int lunch, 
     204                         int escape, int defense_pos, int max_moves, 
     205                         struct matched_pattern_data *pattern_data); 
    192206static void owl_determine_life(struct local_owl_data *owl, 
    193207                               struct local_owl_data *second_owl, 
    194208                               int does_attack, 
     
    216230static void owl_mark_worm(int apos, int bpos, 
    217231                          struct local_owl_data *owl); 
    218232static void owl_mark_boundary(struct local_owl_data *owl); 
    219 static void owl_update_goal(int pos, int same_dragon, int lunch, 
    220                             struct local_owl_data *owl, int semeai_call); 
     233static void owl_update_goal(int pos, enum same_dragon_value same_dragon, 
     234                            int lunch, struct local_owl_data *owl, 
     235                            int semeai_call, 
     236                            struct matched_pattern_data *pattern_data); 
    221237static void owl_test_cuts(signed char goal[BOARDMAX], int color, 
    222238                          int cuts[MAX_CUTS]); 
    223239static void componentdump(const signed char component[BOARDMAX]); 
     
    246262                                      int owl_phase, 
    247263                                      int move, int color, int ko_allowed, 
    248264                                      int move_value, const char *move_name, 
    249                                       int same_dragon, int lunch, 
    250                                       int *semeai_move, 
     265                                      enum same_dragon_value same_dragon, 
     266                                      struct matched_pattern_data *pattern_data, 
     267                                      int lunch, int *semeai_move, 
    251268                                      int *this_resulta, int *this_resultb); 
    252269static void semeai_add_sgf_comment(int value, int owl_phase); 
    253270static int semeai_trust_tactical_attack(int str); 
     
    556573                          resulta, resultb, semeai_move, 0, owl); 
    557574  else { 
    558575    semeai_trymove_and_recurse(bpos, apos, owlb, owla, owl, 
    559                                move, color, 1, 0, "mandatory move", 1, NO_MOVE, 
     576                               move, color, 1, 0, "mandatory move", 
     577                               SAME_DRAGON_MAYBE_CONNECTED, NULL, NO_MOVE, 
    560578                               semeai_move, resultb, resulta); 
    561579    *resulta = REVERSE_RESULT(*resulta); 
    562580    *resultb = REVERSE_RESULT(*resultb); 
     
    703721    moves[k].pos = 0; 
    704722    moves[k].value = -1; 
    705723    moves[k].name = NULL; 
    706     moves[k].same_dragon = 2; 
     724    moves[k].same_dragon = SAME_DRAGON_CONNECTED; 
    707725    moves[k].lunch = NO_MOVE; 
    708726    clear_cut_list(moves[k].cuts); 
    709727  } 
     
    742760        else if (acode != 0 
    743761                 && find_defense(semeai_worms[sworm], NULL)) { 
    744762          critical_semeai_worms[sworm] = 1; 
    745           owl_add_move(moves, upos, 105, "attack semeai worm", 1, 
    746                        NO_MOVE, 0, NO_MOVE, MAX_SEMEAI_MOVES); 
     763          owl_add_move(moves, upos, 105, "attack semeai worm", 
     764                       SAME_DRAGON_MAYBE_CONNECTED, 
     765                       NO_MOVE, 0, NO_MOVE, MAX_SEMEAI_MOVES, NULL); 
    747766          TRACE("Added %1m %d (-1)\n", upos, 105); 
    748767        } 
    749768        else if (acode == WIN 
    750769                 && important_semeai_worms[sworm]) { 
    751           owl_add_move(moves, upos, 100, "attack semeai worm", 1, 
    752                        NO_MOVE, 0, NO_MOVE, MAX_SEMEAI_MOVES); 
     770          owl_add_move(moves, upos, 100, "attack semeai worm", 
     771                       SAME_DRAGON_MAYBE_CONNECTED, 
     772                       NO_MOVE, 0, NO_MOVE, MAX_SEMEAI_MOVES, NULL); 
    753773          TRACE("Added %1m %d (-1)\n", upos, 100); 
    754774        } 
    755775      } 
     
    767787        if (attack(semeai_worms[sworm], NULL) 
    768788            && find_defense(semeai_worms[sworm], &upos)) { 
    769789          critical_semeai_worms[sworm] = 1; 
    770           owl_add_move(moves, upos, 85, "defend semeai worm", 1, NO_MOVE, 
    771                        0, NO_MOVE, MAX_SEMEAI_MOVES); 
     790          owl_add_move(moves, upos, 85, "defend semeai worm", 
     791                       SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE, 
     792                       0, NO_MOVE, MAX_SEMEAI_MOVES, NULL); 
    772793          TRACE("Added %1m %d (0)\n", upos, 85); 
    773794        } 
    774795      } 
     
    10061027                                     owla, owlb, 50, 
    10071028                                     critical_semeai_worms); 
    10081029      owl_add_move(moves, outside_liberty.pos, move_value, 
    1009                    "safe outside liberty", 0, NO_MOVE, 0, NO_MOVE, 
    1010                    MAX_SEMEAI_MOVES); 
     1030                   "safe outside liberty", SAME_DRAGON_NOT_CONNECTED, 
     1031                   NO_MOVE, 0, NO_MOVE, MAX_SEMEAI_MOVES, NULL); 
    10111032      riskless_move_found = 1; 
    10121033      TRACE("Added %1m %d (5)\n", outside_liberty.pos, move_value); 
    10131034    } 
     
    10161037                                     owla, owlb, 50, 
    10171038                                     critical_semeai_worms); 
    10181039      owl_add_move(moves, backfill_outside_liberty.pos, move_value, 
    1019                    "backfilling move", 0, NO_MOVE, 0, 
    1020                    NO_MOVE, MAX_SEMEAI_MOVES); 
     1040                   "backfilling move", SAME_DRAGON_NOT_CONNECTED, NO_MOVE, 0, 
     1041                   NO_MOVE, MAX_SEMEAI_MOVES, NULL); 
    10211042      riskless_move_found = 1; 
    10221043      TRACE("Added %1m %d (6)\n", backfill_outside_liberty.pos, move_value); 
    10231044    } 
     
    10271048                                     owla, owlb, 10, 
    10281049                                     critical_semeai_worms); 
    10291050      owl_add_move(moves, common_liberty.pos, move_value, 
    1030                    "safe common liberty", 1, NO_MOVE, 0, 
    1031                    NO_MOVE, MAX_SEMEAI_MOVES); 
     1051                   "safe common liberty", SAME_DRAGON_MAYBE_CONNECTED, 
     1052                   NO_MOVE, 0, NO_MOVE, MAX_SEMEAI_MOVES, NULL); 
    10321053      if (semeai_is_riskless_move(common_liberty.pos, owla)) 
    10331054        riskless_move_found = 1; 
    10341055      TRACE("Added %1m %d (7)\n", common_liberty.pos, move_value); 
     
    10381059                                     owla, owlb, 10, 
    10391060                                     critical_semeai_worms); 
    10401061      owl_add_move(moves, backfill_common_liberty.pos, move_value, 
    1041                    "backfilling move", 0, NO_MOVE, 0, 
    1042                    NO_MOVE, MAX_SEMEAI_MOVES); 
     1062                   "backfilling move", SAME_DRAGON_NOT_CONNECTED, NO_MOVE, 0, 
     1063                   NO_MOVE, MAX_SEMEAI_MOVES, NULL); 
    10431064      if (semeai_is_riskless_move(backfill_common_liberty.pos, owla)) 
    10441065        riskless_move_found = 1; 
    10451066      TRACE("Added %1m %d (6)\n", backfill_common_liberty.pos, move_value); 
     
    10541075      int move = semeai_propose_eyespace_filling_move(owla, owlb); 
    10551076 
    10561077      if (move) { 
    1057         owl_add_move(moves, move, 70, "eyespace filling", 0, NO_MOVE, 
    1058                      0, NO_MOVE, MAX_SEMEAI_MOVES); 
     1078        owl_add_move(moves, move, 70, "eyespace filling", 
     1079                     SAME_DRAGON_NOT_CONNECTED, NO_MOVE, 
     1080                     0, NO_MOVE, MAX_SEMEAI_MOVES, NULL); 
    10591081      } 
    10601082    } 
    10611083 
     
    10971119                                   owl_phase, mpos, color, 
    10981120                                   best_resulta == 0 || best_resultb == 0, 
    10991121                                   moves[k].value, moves[k].name, 
    1100                                    moves[k].same_dragon, moves[k].lunch, 
    1101                                    NULL, &this_resulta, &this_resultb)) { 
     1122                                   moves[k].same_dragon, moves[k].pattern_data, 
     1123                                   moves[k].lunch, NULL, 
     1124                                   &this_resulta, &this_resultb)) { 
    11021125      tested_moves++; 
    11031126      if (this_resultb == WIN && this_resulta == WIN) { 
    11041127        /* Ideal result, no need to try any more moves. */ 
     
    12491272                           int owl_phase, 
    12501273                           int move, int color, int ko_allowed, 
    12511274                           int move_value, const char *move_name, 
    1252                            int same_dragon, int lunch, int *semeai_move, 
     1275                           enum same_dragon_value same_dragon, 
     1276                           struct matched_pattern_data *pattern_data, 
     1277                           int lunch, int *semeai_move, 
    12531278                           int *this_resulta, int *this_resultb) 
    12541279{ 
    12551280  int ko_move = 0; 
     
    12751300  push_owl(&owlb); 
    12761301 
    12771302  if (owla->color == color) { 
    1278     owl_update_goal(move, same_dragon, lunch, owla, 1); 
     1303    owl_update_goal(move, same_dragon, lunch, owla, 1, pattern_data); 
    12791304    owl_update_boundary_marks(move, owlb); 
    12801305  } 
    12811306  else { 
    1282     owl_update_goal(move, same_dragon, lunch, owlb, 1); 
     1307    owl_update_goal(move, same_dragon, lunch, owlb, 1, pattern_data); 
    12831308    owl_update_boundary_marks(move, owla); 
    12841309  } 
    12851310  mark_goal_in_sgf(owla->goal); 
     
    14181443{ 
    14191444  int move; 
    14201445  int move_value; 
    1421   int same_dragon; 
     1446  enum same_dragon_value same_dragon; 
     1447  struct matched_pattern_data *pattern_data = NULL; 
    14221448  int k; 
    14231449   
    14241450  for (k = 0; k < MAX_MOVES-1; k++) { 
     
    14441470    if (guess_same_dragon) { 
    14451471      if (liberty_of_goal(move, owla) 
    14461472          || second_liberty_of_goal(move, owla)) 
    1447         same_dragon = 1; 
     1473        same_dragon = SAME_DRAGON_MAYBE_CONNECTED; 
    14481474      else 
    1449         same_dragon = 0; 
     1475        same_dragon = SAME_DRAGON_NOT_CONNECTED; 
    14501476    } 
    1451     else 
     1477    else { 
    14521478      same_dragon = owl_moves[k].same_dragon; 
     1479      pattern_data = owl_moves[k].pattern_data; 
     1480    } 
    14531481 
    14541482    mw[move] = 1; 
    14551483    move_value = (semeai_move_value(move, owla, owlb, owl_moves[k].value, 
     
    14571485                  + value_bonus); 
    14581486    owl_add_move(semeai_moves, move, move_value, owl_moves[k].name,  
    14591487                 same_dragon, NO_MOVE, owl_moves[k].escape, 
    1460                  NO_MOVE, MAX_SEMEAI_MOVES); 
     1488                 NO_MOVE, MAX_SEMEAI_MOVES, pattern_data); 
    14611489    TRACE("Added %1m %d\n", move, move_value); 
    14621490  } 
    14631491} 
     
    17031731    moves[k].pos = NO_MOVE; 
    17041732    moves[k].value = -1; 
    17051733    moves[k].name = NULL; 
    1706     moves[k].same_dragon = 2; 
     1734    moves[k].same_dragon = SAME_DRAGON_CONNECTED; 
    17071735    moves[k].escape = 0; 
    17081736    moves[k].lunch = NO_MOVE; 
     1737    moves[k].pattern_data = NULL; 
    17091738    clear_cut_list(moves[k].cuts); 
    17101739  } 
    17111740} 
     
    17141743set_single_owl_move(struct owl_move_data moves[MAX_MOVES], 
    17151744                    int pos, const char *name) 
    17161745{ 
    1717   moves[0].pos         = pos; 
    1718   moves[0].value       = 25; 
    1719   moves[0].name        = name; 
    1720   moves[0].same_dragon = 1; 
    1721   moves[0].escape      = 0; 
    1722   moves[0].lunch       = NO_MOVE; 
     1746  moves[0].pos          = pos; 
     1747  moves[0].value        = 25; 
     1748  moves[0].name         = name; 
     1749  moves[0].same_dragon  = SAME_DRAGON_MAYBE_CONNECTED; 
     1750  moves[0].escape       = 0; 
     1751  moves[0].lunch        = NO_MOVE; 
     1752  moves[0].pattern_data = NULL; 
    17231753  clear_cut_list(moves[0].cuts); 
    1724   moves[1].value       = 0; 
     1754  moves[1].value        = 0; 
    17251755} 
    17261756 
    17271757 
     
    27162746      /* Add the stone just played to the goal dragon, unless the 
    27172747       * pattern explicitly asked for not doing this. 
    27182748       */ 
    2719       owl_update_goal(mpos, moves[k].same_dragon, moves[k].lunch, owl, 0); 
     2749      owl_update_goal(mpos, moves[k].same_dragon, moves[k].lunch, owl, 0, 
     2750                      moves[k].pattern_data); 
    27202751      mark_goal_in_sgf(owl->goal); 
    27212752 
    27222753      if (!ko_move) { 
     
    28322863        if (trymove(moves[k].pos, color, moves[k].name, target)) { 
    28332864          owl->lunches_are_current = 0; 
    28342865          owl_update_goal(moves[k].pos, moves[k].same_dragon, 
    2835                           moves[k].lunch, owl, 0); 
     2866                          moves[k].lunch, owl, 0, moves[k].pattern_data); 
    28362867          if (do_owl_defend(target, &move2, NULL, owl, 0) == WIN) { 
    28372868            move = moves[k].pos; 
    28382869            popgo(); 
     
    29472978     * Let's try to defend against it. 
    29482979     */ 
    29492980    owl_add_move(vital_moves, dummy_moves[0].defense_pos, 
    2950                  dummy_moves[0].value, dummy_moves[0].name, 2, NO_MOVE, 
    2951                  0, NO_MOVE, MAX_MOVES); 
     2981                 dummy_moves[0].value, dummy_moves[0].name, 
     2982                 SAME_DRAGON_CONNECTED, NO_MOVE, 0, NO_MOVE, MAX_MOVES, NULL); 
    29522983  } 
    29532984 
    29542985  return 0; 
     
    31613192                  attack_point); 
    31623193 
    31633194          if (attack_point != NO_MOVE) { 
    3164             owl_add_move(moves, attack_point, value, reason, 1, NO_MOVE, 
    3165                          0, NO_MOVE, MAX_MOVES); 
     3195            owl_add_move(moves, attack_point, value, reason, 
     3196                         SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE, 
     3197                         0, NO_MOVE, MAX_MOVES, NULL); 
    31663198            vital_values[attack_point] = value; 
    31673199            eyes_attack_points[num_eyes] = attack_point; 
    31683200          } 
     
    32163248                  defense_point); 
    32173249 
    32183250          if (defense_point != NO_MOVE) { 
    3219             owl_add_move(moves, defense_point, value, reason, 1, NO_MOVE, 
    3220                          0, NO_MOVE, MAX_MOVES); 
     3251            owl_add_move(moves, defense_point, value, reason, 
     3252                         SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE, 
     3253                         0, NO_MOVE, MAX_MOVES, NULL); 
    32213254            vital_values[defense_point] = value; 
    32223255          } 
    32233256        } 
     
    32913324                owl->lunch[lunch], defense_point, value, 
    32923325                lunch_probable, lunch_max); 
    32933326          owl_add_move(moves, defense_point, value, 
    3294                        "save lunch", 1, NO_MOVE, 0, NO_MOVE, MAX_MOVES); 
     3327                       "save lunch", SAME_DRAGON_MAYBE_CONNECTED, 
     3328                       NO_MOVE, 0, NO_MOVE, MAX_MOVES, NULL); 
    32953329        } 
    32963330        else { 
    32973331          attack_point = improve_lunch_attack(owl->lunch[lunch], 
     
    33073341          if (owl->lunch_attack_code[lunch] ==  WIN 
    33083342              || is_illegal_ko_capture(attack_point, owl->color)) 
    33093343            owl_add_move(moves, attack_point, value, "eat lunch", 
    3310                          1, owl->lunch[lunch], 0, NO_MOVE, MAX_MOVES); 
     3344                         SAME_DRAGON_MAYBE_CONNECTED, owl->lunch[lunch], 
     3345                         0, NO_MOVE, MAX_MOVES, NULL); 
    33113346          else 
    33123347            owl_add_move(moves, attack_point, value, "eat lunch", 
    3313                          1, NO_MOVE, 0, NO_MOVE, MAX_MOVES); 
     3348                         SAME_DRAGON_MAYBE_CONNECTED, NO_MOVE, 0, NO_MOVE, 
     3349                         MAX_MOVES, NULL); 
    33143350          num_lunches++; 
    33153351          eyevalue_list[num_eyes++] = e; 
    33163352        } 
     
    41624198 
    41634199  while (list->heap_num_patterns > 0) { 
    41644200    int k; 
     4201    struct matched_pattern_data *pattern_data; 
    41654202    struct pattern *pattern; 
    41664203    int move; 
    41674204    int value; 
     
    41734210    if (list->pattern_heap[0]->value < cutoff) 
    41744211      break; 
    41754212 
     4213    pattern_data = list->pattern_heap[0]; 
    41764214    pattern = list->pattern_heap[0]->pattern; 
    41774215    move    = list->pattern_heap[0]->move; 
    41784216    value   = list->pattern_heap[0]->value; 
     
    42404278        } 
    42414279 
    42424280        if (pattern->class & CLASS_B) 
    4243           moves[k].same_dragon = 0; 
    4244         else if (pattern->class & CLASS_b) { 
     4281          moves[k].same_dragon = SAME_DRAGON_NOT_CONNECTED; 
     4282        else if (pattern->class & CLASS_a) { 
     4283          moves[k].same_dragon = SAME_DRAGON_ALL_CONNECTED; 
     4284          moves[k].pattern_data = pattern_data; 
     4285        } 
     4286        else if (!(pattern->class & CLASS_b)) 
     4287          moves[k].same_dragon = SAME_DRAGON_CONNECTED; 
     4288        else { 
    42454289          int i; 
    4246           int same_dragon = 1; 
     4290          enum same_dragon_value same_dragon = SAME_DRAGON_MAYBE_CONNECTED; 
    42474291 
    42484292          /* If we do not yet know whether the move belongs to the 
    42494293           * same dragon, we see whether another pattern can clarify. 
    42504294           */ 
    42514295          for (i = 0; i < list->heap_num_patterns; i++) { 
    4252             struct matched_pattern_data *pattern_data = list->pattern_heap[i]; 
     4296            pattern_data = list->pattern_heap[i]; 
    42534297 
    42544298            if (pattern_data->pattern 
    42554299                && pattern_data->move == move 
     
    42604304                TRACE("Additionally pattern %s found at %1m\n", 
    42614305                      pattern_data->pattern->name, move); 
    42624306                if (pattern_data->pattern->class & CLASS_B) 
    4263                   same_dragon = 0; 
     4307                  same_dragon = SAME_DRAGON_NOT_CONNECTED; 
     4308                else if (pattern_data->pattern->class & CLASS_a) { 
     4309                  same_dragon = SAME_DRAGON_ALL_CONNECTED; 
     4310                  moves[k].pattern_data = pattern_data; 
     4311                } 
    42644312                else 
    4265                   same_dragon = 2; 
     4313                  same_dragon = SAME_DRAGON_CONNECTED; 
    42664314 
    42674315                break; 
    42684316              } 
     
    42714319 
    42724320          moves[k].same_dragon = same_dragon; 
    42734321        } 
    4274         else 
    4275           moves[k].same_dragon = 2; 
    42764322      } 
    42774323      else { 
    42784324        moves[k].name = "Pattern combination"; 
     
    42874333         *        chain didn't match, this will not work at all. 
    42884334         */ 
    42894335        if (pattern && pattern->class & CLASS_B) 
    4290           moves[k].same_dragon = 0; 
     4336          moves[k].same_dragon = SAME_DRAGON_NOT_CONNECTED; 
     4337        else if (pattern && pattern->class & CLASS_a) { 
     4338          moves[k].same_dragon = SAME_DRAGON_ALL_CONNECTED; 
     4339          moves[k].pattern_data = list->pattern_heap[0]; 
     4340        } 
    42914341        else 
    4292           moves[k].same_dragon = 2; 
     4342          moves[k].same_dragon = SAME_DRAGON_CONNECTED; 
    42934343      } 
    42944344 
    42954345      if (pattern && pattern->class & CLASS_E) 
     
    43384388  int tval;  /* trial move and its value */ 
    43394389  int move; 
    43404390  struct owl_move_data *moves = data; /* considered moves passed as data */ 
    4341   int same_dragon = 1; 
     4391  enum same_dragon_value same_dragon = SAME_DRAGON_MAYBE_CONNECTED; 
    43424392  int escape = 0; 
    43434393  int defense_pos; 
    43444394 
     
    43954445  TRACE("Pattern %s found at %1m with value %d\n", pattern->name, move, tval); 
    43964446 
    43974447  if (pattern->class & CLASS_B) 
    4398     same_dragon = 0; 
     4448    same_dragon = SAME_DRAGON_NOT_CONNECTED; 
    43994449  else if (pattern->class & CLASS_b) 
    4400     same_dragon = 1; 
     4450    same_dragon = SAME_DRAGON_MAYBE_CONNECTED; 
     4451  else if (pattern->class & CLASS_a) { 
     4452    same_dragon = SAME_DRAGON_ALL_CONNECTED; 
     4453    /* FIXME: Currently this code is only used with vital attack 
     4454     * moves, so there is no use for the "a" classification. If it 
     4455     * would be needed in the future it's necessary to set up a struct 
     4456     * matched_pattern_data here to be passed to owl_add_move(). This 
     4457     * is not all that simple with respect to memory management 
     4458     * however. Notice that a local variable in this function would go 
     4459     * out of scope too early. 
     4460     */ 
     4461    gg_assert(0); 
     4462  } 
    44014463  else 
    4402     same_dragon = 2; 
     4464    same_dragon = SAME_DRAGON_CONNECTED; 
    44034465 
    44044466  if (pattern->class & CLASS_E) 
    44054467    escape = 1; 
     
    44164478  } 
    44174479   
    44184480  owl_add_move(moves, move, tval, pattern->name, same_dragon, NO_MOVE, 
    4419                escape, defense_pos, MAX_MOVES); 
     4481               escape, defense_pos, MAX_MOVES, NULL); 
    44204482} 
    44214483 
    44224484 
     
    44244486 
    44254487static void 
    44264488owl_add_move(struct owl_move_data *moves, int move, int value, 
    4427              const char *reason, int same_dragon, int lunch, 
    4428              int escape, int defense_pos, int max_moves) 
     4489             const char *reason, enum same_dragon_value same_dragon, int lunch, 
     4490             int escape, int defense_pos, int max_moves, 
     4491             struct matched_pattern_data *pattern_data) 
    44294492{ 
    44304493  int k; 
    44314494 
     
    44434506    if (moves[k].value == -1) 
    44444507      break; 
    44454508    if (moves[k].pos == move) { 
    4446       if (same_dragon > moves[k].same_dragon) 
     4509      if (same_dragon > moves[k].same_dragon) { 
    44474510        moves[k].same_dragon = same_dragon; 
     4511        moves[k].pattern_data = pattern_data; 
     4512      } 
    44484513      if (!moves[k].escape) 
    44494514        escape = 0; 
    44504515      break; 
     
    44714536         * dragon under consideration. 
    44724537         */ 
    44734538        moves[k].same_dragon = same_dragon; 
     4539        moves[k].pattern_data = pattern_data; 
    44744540        moves[k].lunch = lunch; 
    44754541        moves[k].escape = escape; 
    44764542        moves[k].defense_pos = defense_pos; 
     
    46614727} 
    46624728 
    46634729/* Add the stone just played to the goal dragon if same_dragon is 
    4664  * 2. We also add all stones belonging to the same generalized string 
    4665  * to the goal. If same_dragon is 1, we only add the stones if at 
    4666  * least one stone of the generalized string already was part of the 
    4667  * goal. If same_dragon is 0, we don't add any stones at all. 
     4730 * SAME_DRAGON_CONNECTED. We also add all stones belonging to the same 
     4731 * generalized string to the goal. If same_dragon is 
     4732 * SAME_DRAGON_MAYBE_CONNECTED, we only add the stones if at least one 
     4733 * stone of the generalized string already was part of the goal. If 
     4734 * same_dragon is SAME_DRAGON_NOT_CONNECTED, we don't add any stones 
     4735 * at all. 
     4736 * 
     4737 * The SAME_DRAGON_ALL_CONNECTED case is like SAME_DRAGON_CONNECTED 
     4738 * but additionally all other own stones in the pattern suggesting the 
     4739 * move are also added to the goal. 
    46684740 */ 
    46694741static void 
    4670 owl_update_goal(int pos, int same_dragon, int lunch, 
    4671                 struct local_owl_data *owl, int semeai_call) 
     4742owl_update_goal(int pos, enum same_dragon_value same_dragon, int lunch, 
     4743                struct local_owl_data *owl, int semeai_call, 
     4744                struct matched_pattern_data *pattern_data) 
    46724745{ 
    46734746  int stones[MAX_BOARD * MAX_BOARD]; 
    46744747  int num_stones; 
     
    46824755  sgf_dumptree = NULL; 
    46834756  count_variations = 0; 
    46844757   
    4685   if (same_dragon == 0) 
     4758  if (same_dragon == SAME_DRAGON_NOT_CONNECTED) 
    46864759    num_stones = findstones(pos, MAX_BOARD*MAX_BOARD, stones); 
    46874760  else if (semeai_call) 
    46884761    find_superstring_conservative(pos, &num_stones, stones); 
     
    46964769  /* If same_dragon field is 1, only add if the played stone 
    46974770   * clearly is in contact with the goal dragon. 
    46984771   */ 
    4699   if (same_dragon <= 1) { 
     4772  if (same_dragon <= SAME_DRAGON_MAYBE_CONNECTED) { 
    47004773    do_add = 0; 
    47014774    for (k = 0; k < num_stones; k++) 
    47024775      if (owl->goal[stones[k]] != 0) { 
     
    47294802      } 
    47304803  } 
    47314804 
     4805  /* Now we handle the SAME_DRAGON_ALL_CONNECTED case. The move has 
     4806   * already been added to the goal above, so it remains to find all 
     4807   * other friendly stones in the pattern and add them too. We do that 
     4808   * by a recursive call to this function in SAME_DRAGON_CONNECTED mode. 
     4809   * This is maybe not the most elegant technique, however. 
     4810   */ 
     4811  if (same_dragon == SAME_DRAGON_ALL_CONNECTED) { 
     4812    gg_assert(pattern_data != NULL); 
     4813    for (k = 0; k < pattern_data->pattern->patlen; k++) { 
     4814      int pos2; 
     4815       
     4816      /* all the following stuff (currently) applies only at occupied cells */ 
     4817      if (pattern_data->pattern->patn[k].att != ATT_O) 
     4818        continue; 
     4819       
     4820      /* transform pattern real coordinate */ 
     4821      pos2 = AFFINE_TRANSFORM(pattern_data->pattern->patn[k].offset, 
     4822                              pattern_data->ll, pattern_data->anchor); 
     4823 
     4824      if (!owl->goal[pos2]) 
     4825        owl_update_goal(pos2, SAME_DRAGON_CONNECTED, NO_MOVE, owl, semeai_call, 
     4826                        pattern_data); 
     4827    } 
     4828  } 
     4829 
    47324830  if (1 && verbose) 
    47334831    goaldump(owl->goal); 
    47344832} 
     
    55015599  init_owl(&owl, target1, target2, NO_MOVE, 1, NULL); 
    55025600 
    55035601  if (trymo