Ticket #148: worm4.patch

File worm4.patch, 10.5 kB (added by draqo, 18 months ago)

upgraded threat finding (+ small cleanup) - fix2.patch from ticket #163 is needed to don't change regression

  • engine/reading.c

    diff -N -r -u -X .ignore gnugo-copy/engine/reading.c gnugo/engine/reading.c
    old new  
    484484 * is a frontend to the attack() and find_defense() functions, which 
    485485 * guarantees a consistent result. If a string cannot be attacked, 0 
    486486 * is returned and acode is 0. If a string can be attacked and 
    487  * defended, WIN is returned, acode and dcode are both non-zero, and 
     487 * defended, 1 is returned, acode and dcode are both non-zero, and 
    488488 * (attack_point), (defense_point) both point to vertices on the board.  
    489489 * If a string can be attacked but not defended, 0 is again returned,  
    490490 * acode is non-zero, dcode is 0, and (attack_point) points to a vertex  
     
    507507  int dpos = NO_MOVE; 
    508508 
    509509  acode = attack(str, &apos); 
    510   if (acode != 0) 
     510  if (acode) 
    511511    dcode = find_defense(str, &dpos); 
    512512 
    513513  ASSERT1(!(acode != 0 && dcode == WIN && dpos == NO_MOVE), str); 
     
    521521  if (defense_point) 
    522522    *defense_point = dpos; 
    523523 
    524   return acode != 0 && dcode != 0; 
     524  return acode && dcode; 
    525525} 
    526526 
    527527 
     
    10211021 
    10221022 
    10231023/* Return up to max_threats threats to capture the string at str. 
    1024  * If the string is directly attackable the number of threats 
    1025  * is reported to be 0. 
     1024 * The function should be called only when the string is not directly 
     1025 * attackable. 
    10261026 * 
    10271027 * NOTE:  You can call attack_threats with moves[] and codes[]  
    10281028 *        already partly filled in. So if you want to get the 
    10291029 *        threats from scratch, you have to set them to 0 
    10301030 *        yourself. 
    1031  * 
    1032  * FIXME: Shall we report upgrades, like we can capture in ko but 
    1033  *        have a threat to capture unconditionally? 
    10341031 */ 
    10351032 
    10361033int 
    10371034attack_threats(int str, int max_points, int moves[], int codes[]) 
    10381035{ 
    10391036  int other; 
    1040   int num_threats; 
    10411037  int liberties; 
    10421038  int libs[MAXLIBS]; 
    1043   int num_adj; 
     1039  int *cur_lib, *last_lib; 
    10441040  int adjs[MAXCHAIN]; 
    1045   int k; 
    1046   int l; 
     1041  int *cur_adj, *last_adj; 
    10471042  int r; 
    10481043  int discard; 
     1044  int aa, bb; 
     1045  int acode; 
     1046  const int *cur_delta; 
    10491047 
    10501048  ASSERT1(IS_STONE(board[str]), str); 
     1049  ASSERT1(!attack(str, NULL), str); 
    10511050 
    1052   /* Only handle strings with no way to capture immediately. 
    1053    * For now, we treat ko the same as unconditionally. */ 
    1054   if (attack(str, NULL) != 0) 
    1055     return 0; 
     1051  other = OTHER_COLOR(board[str]); 
     1052  liberties = findlib(str, MAXLIBS, libs); 
    10561053 
    10571054  /* This test would seem to be unnecessary since we only threaten 
    10581055   * strings with attack_code == 0, but it turns out that single 
     
    10611058   * 
    10621059   * The test against 6 liberties is just an optimization. 
    10631060   */ 
    1064   other = OTHER_COLOR(board[str]); 
    1065   liberties = findlib(str, MAXLIBS, libs); 
    1066   if (liberties > 1 && liberties < 6) { 
    1067     for (k = 0; k < liberties; k++) { 
    1068       int aa = libs[k]; 
     1061  if (liberties == 1) 
     1062    change_tactical_point(str, libs[0], WIN, moves, codes, 
     1063                          worm[str].discarded_att_threats); 
     1064  else if (liberties < 6) { 
     1065    cur_lib = libs; 
     1066    last_lib = cur_lib + liberties; 
     1067 
     1068    for (; cur_lib < last_lib; cur_lib++) { 
     1069      aa = *cur_lib; 
    10691070 
    10701071      /* Try to threaten on the liberty. */ 
    10711072      if (trymove(aa, other, "attack_threats-A", str)) { 
    1072        int acode = attack(str, NULL); 
    1073        if (acode != 0) 
     1073       acode = attack(str, NULL); 
     1074       if (acode) 
    10741075         change_tactical_point(str, aa, acode, moves, codes, 
    10751076                               worm[str].discarded_att_threats); 
    10761077       popgo(); 
    10771078      } 
    10781079 
    10791080      /* Try to threaten on second order liberties. */ 
    1080       for (l = 0; l < 4; l++) { 
    1081        int bb = libs[k] + delta[l]; 
     1081      for (cur_delta = delta; cur_delta < last_delta_4; cur_delta++) { 
     1082       bb = aa + *cur_delta; 
    10821083 
    1083        if (!ON_BOARD(bb) 
    1084            || IS_STONE(board[bb]) 
     1084       if (board[bb] 
    10851085           || attack_threat_move_known(bb, str) 
    10861086           || discarded_move_known(bb, MAX_TACTICAL_POINTS, 
    10871087                                   worm[str].discarded_att_threats) 
     
    10911091       discard = 1; 
    10921092 
    10931093       if (trymove(bb, other, "attack_threats-B", str)) { 
    1094          int acode = attack(str, NULL); 
    1095          if (acode != 0) { 
     1094         acode = attack(str, NULL); 
     1095         if (acode) { 
    10961096           change_tactical_point(str, bb, acode, moves, codes, 
    10971097                                 worm[str].discarded_att_threats); 
    10981098           discard = 0; 
     
    11081108  } 
    11091109 
    11101110  /* Threaten to attack by saving weak neighbors. */ 
    1111   num_adj = chainlinks(str, adjs); 
    1112   for (k = 0; k < num_adj; k++) { 
    1113     int bb; 
    1114     int acode; 
     1111  cur_adj = adjs; 
     1112  last_adj = cur_adj + chainlinks(str, adjs); 
     1113  for (; cur_adj < last_adj; cur_adj++) { 
    11151114    int dcode; 
    11161115 
    1117     attack_and_defend(adjs[k], &acode, NULL, &dcode, NULL); 
    1118     if (acode == 0 || dcode == 0) 
     1116    if (!attack_and_defend(*cur_adj, &acode, NULL, &dcode, NULL)) 
    11191117      continue; 
    11201118 
    11211119    /* Step through all defense points. */ 
    11221120    for (r = 0; r < max_points; r++) { 
    1123       if (worm[adjs[k]].defense_codes[r] == 0) 
     1121      if (!worm[*cur_adj].defense_codes[r]) 
    11241122        break; 
    1125       bb = worm[adjs[k]].defense_points[r]; 
     1123      bb = worm[*cur_adj].defense_points[r]; 
     1124 
     1125      if (attack_threat_move_known(bb, str) 
     1126          || discarded_move_known(bb, MAX_TACTICAL_POINTS, 
     1127                                  worm[str].discarded_att_threats)) 
     1128        continue; 
     1129 
     1130      discard = 1; 
    11261131 
    11271132      /* Test the move and see if it is a threat. */ 
    11281133      if (trymove(bb, other, "attack_threats-C", str)) { 
    1129         if (board[str] == EMPTY) 
     1134        if (!board[str]) 
    11301135          acode = WIN; 
    11311136        else 
    11321137          acode = attack(str, NULL); 
    1133         if (acode != 0) 
     1138        if (acode) { 
    11341139          change_tactical_point(str, bb, acode, moves, codes, 
    11351140                                worm[str].discarded_att_threats); 
     1141          discard = 0; 
     1142        } 
    11361143        popgo(); 
    11371144      } 
     1145 
     1146      if (discard) 
     1147        movelist_change_discarded(bb, MAX_TACTICAL_POINTS, 
     1148                                  worm[str].discarded_att_threats); 
    11381149    } 
    11391150  } 
    11401151 
    11411152  /* Return actual number of threats found regardless of attack code. */ 
    1142   for (num_threats = 0; num_threats < max_points; num_threats++) 
    1143     if (codes[num_threats] == 0) 
     1153  for (r = 0; r < max_points; r++) 
     1154    if (!codes[r]) 
    11441155      break; 
    1145   return num_threats; 
     1156  return r; 
    11461157} 
    11471158 
    11481159 
  • engine/worm.c

    diff -N -r -u -X .ignore gnugo-copy/engine/worm.c gnugo/engine/worm.c
    old new  
    822822         */ 
    823823        if (!send_two_return_one(pos, other) 
    824824            && trymove(pos, other, "make_worms", str)) { 
    825           if (board[str] == EMPTY || attack(str, NULL)) { 
    826             if (board[str] == EMPTY) 
     825          if (!board[str] || attack(str, NULL)) { 
     826            if (!board[str]) 
    827827              dcode = 0; 
    828828            else 
    829829              dcode = find_defense(str, NULL); 
     
    863863{ 
    864864  int str; 
    865865  static int libs[MAXLIBS]; 
    866   int liberties; 
    867    
    868   int k; 
    869   int l; 
     866  int *cur_lib, *last_lib; 
     867  int aa, bb; 
    870868  int color; 
    871869  int discard; 
     870  int dcode, worm_dcode; 
     871  const int *cur_delta; 
    872872   
    873873  for (str = BOARDMIN; str < BOARDMAX; str++) { 
    874     color = board[str]; 
    875     if (!IS_STONE(color) || !is_worm_origin(str, str)) 
     874    if (!IS_STONE(board[str]) || !is_worm_origin(str, str)) 
    876875      continue; 
    877876 
     877    color = board[str]; 
     878 
    878879    /* 1. Start with finding attack threats. */ 
    879880    /* Only try those worms that have no attack. */ 
    880     if (worm[str].attack_codes[0] == 0) { 
     881    if (!worm[str].attack_codes[0]) { 
    881882      attack_threats(str, MAX_TACTICAL_POINTS, 
    882883                     worm[str].attack_threat_points, 
    883884                     worm[str].attack_threat_codes); 
    884 #if 0 
    885       /* Threaten to attack by saving weak neighbors. */ 
    886       num_adj = chainlinks(str, adjs); 
    887       for (k = 0; k < num_adj; k++) { 
    888         if (worm[adjs[k]].attack_codes[0] != 0 
    889             && worm[adjs[k]].defense_codes[0] != 0) 
    890           for (r = 0; r < MAX_TACTICAL_POINTS; r++) { 
    891             int bb; 
    892              
    893             if (worm[adjs[k]].defense_codes[r] == 0) 
    894               break; 
    895             bb = worm[adjs[k]].defense_points[r]; 
    896             if (trymove(bb, other, "threaten attack", str, 
    897                         EMPTY, NO_MOVE)) { 
    898               int acode; 
    899               if (board[str] == EMPTY) 
    900                 acode = WIN; 
    901               else 
    902                 acode = attack(str, NULL); 
    903               if (acode != 0) 
    904                 change_attack_threat(str, bb, acode); 
    905               popgo(); 
    906             } 
    907           } 
    908       } 
    909 #endif 
     885 
    910886      /* FIXME: Try other moves also (patterns?). */ 
    911887    } 
    912888     
    913889    /* 2. Continue with finding defense threats. */ 
    914890    /* Only try those worms that have an attack. */ 
    915     if (worm[str].attack_codes[0] != 0 
    916         && worm[str].defense_codes[0] == 0) { 
     891    else { 
     892      worm_dcode = worm[str].defense_codes[0]; 
    917893 
    918       liberties = findlib(str, MAXLIBS, libs); 
     894      cur_lib = libs; 
     895      last_lib = cur_lib + findlib(str, MAXLIBS, libs); 
    919896       
    920       for (k = 0; k < liberties; k++) { 
    921         int aa = libs[k]; 
     897      for (; cur_lib < last_lib; cur_lib++) { 
     898        aa = *cur_lib; 
     899 
     900        discard = 1; 
    922901         
    923902        /* Try to threaten on the liberty. */ 
    924903        if (trymove(aa, color, "threaten defense", NO_MOVE)) { 
    925           if (attack(str, NULL) == WIN) { 
    926             int dcode = find_defense(str, NULL); 
    927             if (dcode != 0) 
    928               change_defense_threat(str, aa, dcode); 
     904          dcode = find_defense(str, NULL); 
     905          if (dcode > worm_dcode) { 
     906            change_defense_threat(str, aa, dcode); 
     907            discard = 0; 
    929908          } 
    930909          popgo(); 
    931910        } 
     911 
     912        if (discard) 
     913          movelist_change_discarded(aa, MAX_TACTICAL_POINTS, 
     914                                    worm[str].discarded_def_threats); 
    932915         
    933916        /* Try to threaten on second order liberties. */ 
    934         for (l = 0; l < 4; l++) { 
    935           int bb = libs[k] + delta[l]; 
     917        for (cur_delta = delta; cur_delta < last_delta_4; cur_delta++) { 
     918          bb = aa + *cur_delta; 
    936919           
    937           if (!ON_BOARD(bb) 
    938               || IS_STONE(board[bb]) 
     920          if (board[bb] 
    939921              || defense_threat_move_known(bb, str) 
    940922              || discarded_move_known(bb, MAX_TACTICAL_POINTS, 
    941923                                      worm[str].discarded_def_threats) 
     
    945927          discard = 1; 
    946928           
    947929          if (trymove(bb, color, "threaten defense", str)) { 
    948             if (attack(str, NULL) == WIN) { 
    949               int dcode = find_defense(str, NULL); 
    950               if (dcode != 0) { 
    951                 change_defense_threat(str, bb, dcode); 
    952                 discard = 0; 
    953               } 
     930            dcode = find_defense(str, NULL); 
     931            if (dcode > worm_dcode) { 
     932              change_defense_threat(str, bb, dcode); 
     933              discard = 0; 
    954934            } 
    955935            popgo(); 
    956936          } 
     
    961941        } 
    962942      } 
    963943       
    964       /* It might be interesting to look for defense threats by 
     944      /* FIXME: It might be interesting to look for defense threats by 
    965945       * attacking weak neighbors, similar to threatening attack by 
    966946       * defending a weak neighbor. However, in this case it seems 
    967947       * probable that if there is such an attack, it's a real 
  • regression/nngs.tst

    diff -N -r -u -X .ignore gnugo-copy/regression/nngs.tst gnugo/regression/nngs.tst
    old new  
    993993#CATEGORY=OWL_TUNING 
    994994loadsgf games/nngs/LordOfPi-gnugo-3.1.20-200201202014.sgf 36 
    9959952060 reg_genmove black 
    996 #? [C4|C1|F1] 
     996#? [C4]