Index: engine/globals.c =================================================================== RCS file: /cvsroot/gnugo/gnugo/engine/globals.c,v retrieving revision 1.51 diff -u -r1.51 globals.c --- engine/globals.c 18 Jun 2003 11:01:24 -0000 1.51 +++ engine/globals.c 19 Jun 2003 18:48:43 -0000 @@ -69,6 +69,7 @@ int depth; /* deep reading cut off */ int backfill_depth; /* deep reading cut off */ int backfill2_depth; /* deep reading cut off */ +int break_chain_depth; /* deep reading cut off */ int superstring_depth; /* deep reading cut off */ int fourlib_depth; /* deep reading cut off */ int ko_depth; /* deep reading cut off */ @@ -89,6 +90,7 @@ int mandated_depth; /* deep reading cut off, mandated value */ int mandated_backfill_depth; /* deep reading cut off, mandated value */ int mandated_backfill2_depth; /* deep reading cut off, mandated value */ +int mandated_break_chain_depth; /* deep reading cut off, mandated value */ int mandated_superstring_depth; /* deep reading cut off, mandated value */ int mandated_fourlib_depth; /* deep reading cut off, mandated value */ int mandated_ko_depth; /* deep reading cut off, mandated value */ Index: engine/gnugo.h =================================================================== RCS file: /cvsroot/gnugo/gnugo/engine/gnugo.h,v retrieving revision 1.98 diff -u -r1.98 gnugo.h --- engine/gnugo.h 18 Jun 2003 14:26:58 -0000 1.98 +++ engine/gnugo.h 19 Jun 2003 18:48:44 -0000 @@ -300,6 +300,7 @@ extern int mandated_depth; extern int mandated_backfill_depth; extern int mandated_backfill2_depth; +extern int mandated_break_chain_depth; extern int mandated_superstring_depth; extern int mandated_fourlib_depth; extern int mandated_ko_depth; Index: engine/liberty.h =================================================================== RCS file: /cvsroot/gnugo/gnugo/engine/liberty.h,v retrieving revision 1.182 diff -u -r1.182 liberty.h --- engine/liberty.h 18 Jun 2003 14:26:58 -0000 1.182 +++ engine/liberty.h 19 Jun 2003 18:48:44 -0000 @@ -401,8 +401,8 @@ void modify_depth_values(int n); void increase_depth_values(void); void decrease_depth_values(void); -void set_temporary_depth_values(int d, int b, int f, int k, - int br, int b2, int ss); +void set_temporary_depth_values(int d, int b, int b2, int bc, + int ss, int br, int f, int k); void restore_depth_values(void); int safe_move(int move, int color); @@ -795,6 +795,7 @@ extern int depth; /* deep reading cutoff */ extern int backfill_depth; /* deep reading cutoff */ extern int backfill2_depth; /* deep reading cutoff */ +extern int break_chain_depth; /* deep reading cutoff */ extern int superstring_depth; /* deep reading cutoff */ extern int branch_depth; /* deep reading cutoff */ extern int fourlib_depth; /* deep reading cutoff */ Index: engine/reading.c =================================================================== RCS file: /cvsroot/gnugo/gnugo/engine/reading.c,v retrieving revision 1.114 diff -u -r1.114 reading.c --- engine/reading.c 17 Jun 2003 10:54:47 -0000 1.114 +++ engine/reading.c 19 Jun 2003 18:48:47 -0000 @@ -182,17 +182,21 @@ static void propose_edge_moves(int str, int *libs, int liberties, struct reading_moves *moves, int color); static void break_chain_moves(int str, struct reading_moves *moves); +static void defend_secondary_chain_moves(int str, struct reading_moves *moves, + int min_liberties); static void break_chain2_efficient_moves(int str, struct reading_moves *moves); static void do_find_break_chain2_efficient_moves(int str, int adj, struct reading_moves *moves); static void break_chain2_moves(int str, struct reading_moves *moves, - int require_safe); -static void break_chain2_defense_moves(int str, struct reading_moves *moves); -static void break_chain3_moves(int str, struct reading_moves *moves); + int require_safe, int be_aggressive); +static void break_chain2_defense_moves(int str, struct reading_moves *moves, + int be_aggressive); +static void break_chain3_moves(int str, struct reading_moves *moves, + int be_aggressive); static void superstring_moves(int str, struct reading_moves *moves, int liberty_cap, int does_attack); -static void superstring_breakchain_moves(int str, int liberty_cap, +static void superstring_break_chain_moves(int str, int liberty_cap, struct reading_moves *moves); static void double_atari_chain2_moves(int str, struct reading_moves *moves); @@ -1284,6 +1288,8 @@ int k; int r; int suggest_move = NO_MOVE; + int string_size; + int be_aggressive; SETUP_TRACE_INFO("defend2", str); reading_node_counter++; @@ -1305,13 +1311,18 @@ * 3. Second order liberties moving up from first line to second. * 4. Edge clamps. */ - for (k = 0; k < liberties; k++) { - moves.pos[k] = libs[k]; - moves.score[k] = 0; - moves.message[k] = "liberty"; - } - moves.num = liberties; - + moves.num = 0; + + /* We don't want to play self-atari liberties, unless the string is a + * single stone (in which case it might be a snapback move). Sacrifices + * might be good moves, but not in tactical reading. + */ + string_size = countstones(str); + if (string_size == 1 || !is_self_atari(libs[0], color)) + ADD_CANDIDATE_MOVE(libs[0], 0, moves, "liberty"); + if (string_size == 1 || !is_self_atari(libs[1], color)) + ADD_CANDIDATE_MOVE(libs[1], 0, moves, "liberty"); + break_chain_moves(str, &moves); break_chain2_efficient_moves(str, &moves); propose_edge_moves(str, libs, liberties, &moves, color); @@ -1370,11 +1381,11 @@ * stone, we don't even try. */ if (!is_self_atari(xpos, color) - || has_neighbor(xpos, color)) + && has_neighbor(xpos, color)) ADD_CANDIDATE_MOVE(xpos, 0, moves, "backfill-A"); - } } + liberties2 = approxlib(libs[k], other, 3, libs2); if (liberties2 <= 2) { for (r = 0; r < liberties2; r++) { @@ -1416,9 +1427,13 @@ saved_num_moves = moves.num; - if (stackp <= superstring_depth) { - superstring_breakchain_moves(str, 4, &moves); - } + /* If we haven't found any useful moves in first batches, be more + * aggressive in break_chain[23]_moves(). + */ + be_aggressive = (moves.num == 0); + + if (stackp <= superstring_depth) + superstring_break_chain_moves(str, 4, &moves); /* If nothing else works, we try playing a liberty of the * super_string. @@ -1426,15 +1441,14 @@ if (stackp <= superstring_depth) superstring_moves(str, &moves, 3, 0); - break_chain2_defense_moves(str, &moves); + break_chain2_defense_moves(str, &moves, be_aggressive); - if (stackp <= backfill_depth) { + if (stackp <= backfill_depth) special_rescue5_moves(str, libs, &moves); - } - if (stackp <= backfill2_depth) { - break_chain3_moves(str, &moves); - } + if (stackp <= break_chain_depth + || (be_aggressive && stackp <= backfill_depth)) + break_chain3_moves(str, &moves, be_aggressive); /* Only order and test the new set of moves. */ order_moves(str, &moves, other, read_function_name, saved_num_moves, NO_MOVE); @@ -1633,10 +1647,10 @@ } if (level >= 10 && stackp <= backfill2_depth) - superstring_breakchain_moves(str, 4, &moves); + superstring_break_chain_moves(str, 4, &moves); - if (stackp <= backfill2_depth) - break_chain2_defense_moves(str, &moves); + if (stackp <= break_chain_depth) + break_chain2_defense_moves(str, &moves, 0); if (stackp <= backfill_depth) { special_rescue5_moves(str, libs, &moves); @@ -1679,8 +1693,8 @@ if (level >= 10 && stackp <= backfill2_depth) superstring_moves(str, &moves, 3, 0); - if (stackp <= backfill2_depth) - break_chain3_moves(str, &moves); + if (stackp <= break_chain_depth) + break_chain3_moves(str, &moves, 0); /* Only order and test the new set of moves. */ order_moves(str, &moves, other, read_function_name, saved_num_moves, *move); @@ -1765,7 +1779,7 @@ break_chain2_efficient_moves(str, &moves); if (stackp <= backfill_depth) { - break_chain2_defense_moves(str, &moves); + break_chain2_defense_moves(str, &moves, 0); #if 0 hane_rescue_moves(str, libs, &moves); #endif @@ -3543,7 +3557,7 @@ && approxlib(libs2[1], other, 4, NULL) > 3) continue; break_chain_moves(adjs[r], &moves); - break_chain2_moves(adjs[r], &moves, 1); + break_chain2_moves(adjs[r], &moves, 1, 0); for (k = 0; k < 2; k++) ADD_CANDIDATE_MOVE(libs2[k], 0, moves, "save_boundary-2"); } @@ -4326,6 +4340,38 @@ } +/* defend_secondary_chain_moves() tries to break a chain by defending + * "secondary chain", that is, own strings surrounding a given + * opponent string (which is in turn a chainlink for another own + * string, phew... :). Currently, it only defends own strings in + * atari. + * + * It is required that the defending stone played gets at least + * `min_liberties', or one less if it is adjacent to the opponent + * chainlink. + */ +static void +defend_secondary_chain_moves(int str, struct reading_moves *moves, + int min_liberties) +{ + int r; + int color = OTHER_COLOR(board[str]); + int xpos; + int adj; + int adjs[MAXCHAIN]; + + /* Find links in atari. */ + adj = chainlinks2(str, adjs, 1); + + for (r = 0; r < adj; r++) { + findlib(adjs[r], 1, &xpos); + if (approxlib(xpos, color, min_liberties, NULL) + + neighbor_of_string(xpos, str) >= min_liberties) + ADD_CANDIDATE_MOVE(xpos, 0, *moves, "defend_secondary_chain"); + } +} + + /* * Find moves which immediately capture chain links with 2 * liberties, in the sense that the links cannot escape atari. @@ -4428,48 +4474,45 @@ ADD_CANDIDATE_MOVE(libs[0], 1, *moves, "break_chain2_efficient-C"); } -/* - * (str) points to a group with two liberties. break_chain2_moves - * tries to defend this worm by attacking * a neighbouring worm with + +/* (str) points to a group with two liberties. break_chain2_moves() + * tries to defend this string by attacking a neighbouring string with * two liberties. * This is done by playing on either of its liberties * (if (require_safe) is true these are only used if they are not * self-ataris), taking a neighbour out of atari or by backfilling if * both liberties are self-ataris. */ - static void -break_chain2_moves(int str, struct reading_moves *moves, int require_safe) +break_chain2_moves(int str, struct reading_moves *moves, int require_safe, + int be_aggressive) { int color = board[str]; int other = OTHER_COLOR(color); int r; - int k; - int apos; int adj; int adjs[MAXCHAIN]; - int dummy_adjs[MAXCHAIN]; - int libs[2]; - int unsafe[2]; adj = chainlinks2(str, adjs, 2); - + for (r = 0; r < adj; r++) { - apos = adjs[r]; + int k; + int apos = adjs[r]; + int libs[2]; + int unsafe[2]; + int dummy_adjs[MAXCHAIN]; + + findlib(apos, 2, libs); /* If stackp > backfill_depth, don't bother playing liberties of * 2-liberty strings if those also have at least one neighbor in * atari. This is intended to solve reading:171 and generally reduce * the number of nodes. - * - * FIXME: We may need to still accept these moves if they happen to - * take the ataried string out of atari. */ if (stackp > backfill_depth && chainlinks2(apos, dummy_adjs, 1) > 0) continue; - - findlib(apos, 2, libs); + for (k = 0; k < 2; k++) { unsafe[k] = is_self_atari(libs[k], color); if (!unsafe[k] @@ -4479,17 +4522,26 @@ ADD_CANDIDATE_MOVE(libs[k], 0, *moves, "break_chain2-A"); } - if (stackp <= backfill2_depth || have_common_lib(str, apos, NULL)) { - break_chain_moves(apos, moves); - if (unsafe[0] && unsafe[1]) { + if (stackp <= break_chain_depth + || (be_aggressive && stackp <= backfill_depth)) { + /* If the chain link cannot escape easily, try to defend all adjacent + * friendly stones in atari (if any). + */ + if (approxlib(libs[0], other, 4, NULL) < 4 + && approxlib(libs[1], other, 4, NULL) < 4) + defend_secondary_chain_moves(adjs[r], moves, 2); + } + + if (unsafe[0] && unsafe[1] + && (stackp <= backfill2_depth || have_common_lib(str, apos, NULL))) { + /* Find backfilling moves. */ + for (k = 0; k < 2; k++) { int libs2[3]; - for (k = 0; k < 2; k++) { - if (approxlib(libs[k], other, 3, libs2) == 2) { - int s; - for (s = 0; s < 2; s++) - if (!is_self_atari(libs2[s], color)) - ADD_CANDIDATE_MOVE(libs2[s], 0, *moves, "break_chain2-B"); - } + if (approxlib(libs[k], other, 3, libs2) == 2) { + if (!is_self_atari(libs2[0], color)) + ADD_CANDIDATE_MOVE(libs2[0], 0, *moves, "break_chain2-B"); + if (!is_self_atari(libs2[1], color)) + ADD_CANDIDATE_MOVE(libs2[1], 0, *moves, "break_chain2-B"); } } } @@ -4508,12 +4560,13 @@ */ static void -break_chain2_defense_moves(int str, struct reading_moves *moves) +break_chain2_defense_moves(int str, struct reading_moves *moves, + int be_aggressive) { int saved_num_moves = moves->num; int k; - break_chain2_moves(str, moves, !(stackp <= backfill_depth)); + break_chain2_moves(str, moves, !(stackp <= backfill_depth), be_aggressive); for (k = saved_num_moves; k < moves->num; k++) moves->score[k] = -2; } @@ -4528,7 +4581,7 @@ */ static void -break_chain3_moves(int str, struct reading_moves *moves) +break_chain3_moves(int str, struct reading_moves *moves, int be_aggressive) { int color = board[str]; int other = OTHER_COLOR(color); @@ -4593,8 +4646,11 @@ possible_moves[u++] = libs[k]; } } + + if (stackp <= backfill2_depth + || (be_aggressive && stackp <= backfill_depth)) + defend_secondary_chain_moves(adjs[r], moves, 3); } - for (v = 0; v < u; v++) { /* We do not wish to consider the move if it can be @@ -4604,7 +4660,8 @@ * (This currently only makes a difference at stackp == backfill2_depth.) */ int xpos = possible_moves[v]; - if (stackp < backfill2_depth + if (stackp <= break_chain_depth + || (be_aggressive && stackp <= backfill_depth) || approxlib(xpos, color, 2, NULL) > 1) /* We use a negative initial score here as we prefer to find * direct defense moves. @@ -4613,6 +4670,7 @@ } } + /* This function looks for moves attacking those components * of the surrounding chain of the superstring (see find_superstring * for the definition) which have fewer than liberty_cap liberties, @@ -4620,8 +4678,8 @@ * are tested by break_chain_moves. */ static void -superstring_breakchain_moves(int str, int liberty_cap, - struct reading_moves *moves) +superstring_break_chain_moves(int str, int liberty_cap, + struct reading_moves *moves) { int adj; int adjs[MAXCHAIN]; @@ -4633,7 +4691,7 @@ int liberties = countlib(adjs[k]); if (liberties == 1) { findlib(adjs[k], 1, &apos); - ADD_CANDIDATE_MOVE(apos, 0, *moves, "superstring_breakchain"); + ADD_CANDIDATE_MOVE(apos, 0, *moves, "superstring_break_chain"); } else if (liberties == 2) do_find_break_chain2_efficient_moves(str, adjs[k], moves); @@ -5184,6 +5242,7 @@ moves->message[i] = temp_message; } } + if (0) { gprintf("%oVariation %d:\n", count_variations); Index: engine/utils.c =================================================================== RCS file: /cvsroot/gnugo/gnugo/engine/utils.c,v retrieving revision 1.72 diff -u -r1.72 utils.c --- engine/utils.c 9 Jun 2003 16:19:17 -0000 1.72 +++ engine/utils.c 19 Jun 2003 18:48:48 -0000 @@ -610,6 +610,7 @@ #define BRANCH_DEPTH 13 #define BACKFILL_DEPTH 12 #define BACKFILL2_DEPTH 5 +#define BREAK_CHAIN_DEPTH 7 #define SUPERSTRING_DEPTH 7 #define FOURLIB_DEPTH 7 #define KO_DEPTH 8 @@ -678,10 +679,11 @@ else depth_level = level - 8; - depth = gg_max(6, DEPTH + depth_level); - backfill_depth = gg_max(2, BACKFILL_DEPTH + depth_level); - backfill2_depth = gg_max(1, BACKFILL2_DEPTH + depth_level); - branch_depth = gg_max(3, BRANCH_DEPTH + depth_level); + depth = gg_max(6, DEPTH + depth_level); + branch_depth = gg_max(3, BRANCH_DEPTH + depth_level); + backfill_depth = gg_max(2, BACKFILL_DEPTH + depth_level); + backfill2_depth = gg_max(1, BACKFILL2_DEPTH + depth_level); + break_chain_depth = gg_max(2, BREAK_CHAIN_DEPTH + depth_level); if (level >= 8) owl_distrust_depth = gg_max(1, (2 * OWL_DISTRUST_DEPTH + depth_level) / 2); else @@ -741,14 +743,16 @@ backfill_depth = mandated_backfill_depth; if (mandated_backfill2_depth != -1) backfill2_depth = mandated_backfill2_depth; + if (mandated_break_chain_depth != -1) + break_chain_depth = mandated_break_chain_depth; if (mandated_superstring_depth != -1) superstring_depth = mandated_superstring_depth; + if (mandated_branch_depth != -1) + branch_depth = mandated_branch_depth; if (mandated_fourlib_depth != -1) fourlib_depth = mandated_fourlib_depth; if (mandated_ko_depth != -1) ko_depth = mandated_ko_depth; - if (mandated_branch_depth != -1) - branch_depth = mandated_branch_depth; if (mandated_aa_depth != -1) aa_depth = mandated_aa_depth; if (mandated_owl_distrust_depth != -1) @@ -777,6 +781,7 @@ depth += n; backfill_depth += n; backfill2_depth += n; + break_chain_depth += n; superstring_depth += n; branch_depth += n; fourlib_depth += n; @@ -804,6 +809,7 @@ static int save_depth; static int save_backfill_depth; static int save_backfill2_depth; +static int save_break_chain_depth; static int save_superstring_depth; static int save_branch_depth; static int save_fourlib_depth; @@ -812,11 +818,13 @@ /* Currently this function is never called. */ void -set_temporary_depth_values(int d, int b, int f, int k, int br, int b2, int ss) +set_temporary_depth_values(int d, int b, int b2, int bc, + int ss, int br, int f, int k) { save_depth = depth; save_backfill_depth = backfill_depth; save_backfill2_depth = backfill2_depth; + save_break_chain_depth = break_chain_depth; save_superstring_depth = superstring_depth; save_branch_depth = branch_depth; save_fourlib_depth = fourlib_depth; @@ -825,6 +833,7 @@ depth = d; backfill_depth = b; backfill2_depth = b2; + break_chain_depth = bc; superstring_depth = ss; branch_depth = br; fourlib_depth = f; @@ -837,6 +846,7 @@ depth = save_depth; backfill_depth = save_backfill_depth; backfill2_depth = save_backfill2_depth; + break_chain_depth = save_break_chain_depth; superstring_depth = save_superstring_depth; branch_depth = save_branch_depth; fourlib_depth = save_fourlib_depth; Index: interface/main.c =================================================================== RCS file: /cvsroot/gnugo/gnugo/interface/main.c,v retrieving revision 1.73 diff -u -r1.73 main.c --- interface/main.c 9 Jun 2003 16:33:19 -0000 1.73 +++ interface/main.c 19 Jun 2003 18:48:49 -0000 @@ -103,6 +103,7 @@ OPT_DECIDE_COMBINATION, OPT_BRANCH_DEPTH, OPT_BACKFILL2_DEPTH, + OPT_BREAK_CHAIN_DEPTH, OPT_SUPERSTRING_DEPTH, OPT_AA_DEPTH, OPT_DEBUG_FLAGS, @@ -203,6 +204,7 @@ {"backfill-depth", required_argument, 0, 'B'}, {"branch-depth", required_argument, 0, OPT_BRANCH_DEPTH}, {"backfill2-depth", required_argument, 0, OPT_BACKFILL2_DEPTH}, + {"break_chain-depth", required_argument, 0, OPT_BREAK_CHAIN_DEPTH}, {"superstring-depth", required_argument, 0, OPT_SUPERSTRING_DEPTH}, {"fourlib-depth", required_argument, 0, 'F'}, {"ko-depth", required_argument, 0, 'K'}, @@ -318,6 +320,7 @@ mandated_depth = -1; mandated_backfill_depth = -1; mandated_backfill2_depth = -1; + mandated_break_chain_depth = -1; mandated_superstring_depth = -1; mandated_fourlib_depth = -1; mandated_ko_depth = -1; @@ -719,6 +722,10 @@ mandated_backfill2_depth = atoi(gg_optarg); break; + case OPT_BREAK_CHAIN_DEPTH: + mandated_break_chain_depth = atoi(gg_optarg); + break; + case OPT_SUPERSTRING_DEPTH: mandated_superstring_depth = atoi(gg_optarg); break; @@ -1351,6 +1358,7 @@ -K, --ko-depth deep reading cutoff (default %d)\n\ --branch-depth deep reading cutoff (default %d)\n\ --backfill2-depth deep reading cutoff (default %d)\n\ + --break_chain-depth deep reading cutoff (default %d)\n\ --superstring-depth deep reading cutoff (default %d)\n\ --aa-depth deep reading cutoff (default %d)\n\ --owl-distrust owl distrust depth (default %d)\n\ @@ -1502,7 +1510,7 @@ set_depth_values(DEFAULT_LEVEL); fprintf(stderr, USAGE, depth, backfill_depth, fourlib_depth, ko_depth, branch_depth, - backfill2_depth, superstring_depth, aa_depth, + backfill2_depth, break_chain_depth, superstring_depth, aa_depth, owl_distrust_depth, owl_branch_depth, owl_reading_depth, owl_node_limit, DEFAULT_LEVEL); fprintf(stderr, USAGE1,