[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnugo-devel] tactics code cleanup
From: |
Evan Berggren Daniel |
Subject: |
[gnugo-devel] tactics code cleanup |
Date: |
Fri, 29 Nov 2002 23:30:13 -0500 (EST) |
This patch converts the remaining tactics functions to the candidate move
mechanism (eg int find_cap(int str, int *move) -> void
find_cap_moves(int str, struct reading_moves *moves)).
This actually has a moderate number of regression changes (10 so far). I
have yet to investigate all of them, but they seem to be a result of
moving from the simplified trymove() code in the original functions to the
more complex code in the attackn() and defendn() functions. For example,
optics:1201 now passes again. This is because no tactical attack on the
t13 string is found. After w makes a dead eyespace, b plays atari above,
and the passes, forcing w to fill liberties inside. However, black picks
up the four w stones, gaining four internal liberties at stackp == 10, and
is counted alive tactically. Previously, the findcap() function required
a defense by black, which inevitably shortened a liberty. I believe the
change as a result of the cleanup is an improvement.
The performance differnce as a result of the patch is a slight slowdown
(reading nodes in reading.tst 97293 -> 98746). However, this seems to be
a result of poor ordering. My patch removes some overlap between the
different functions, but also removes the ordering of the function calls.
Tuning of the move ordering should solve this.
I plan to redo the move ordering patch I sent in earlier on a larger test
suite, so that should fix the performance problem.
Thanks
Evan Daniel
The delta so far (as of nngs.tst):
./regress.sh . reading.tst
173 unexpected PASS!
./regress.sh . ld_owl.tst
188 unexpected FAIL: Correct '2 Q19', got '0'
302 unexpected FAIL: Correct 'critical T19 (Q19|R18)', got 'alive'
./regress.sh . optics.tst
1201 unexpected PASS!
./regress.sh . connection.tst
26 unexpected FAIL: Correct '1 B4', got '0'
27 unexpected FAIL: Correct '1 B4', got '0'
./regress.sh . trevora.tst
390 unexpected FAIL: Correct 'A2', got 'J4'
./regress.sh . arb.tst
150 unexpected PASS!
./regress.sh . lazarus.tst
6 unexpected PASS!
./regress.sh . trevorb.tst
160 unexpected PASS!
And the patch:
Index: engine/reading.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/reading.c,v
retrieving revision 1.86
diff -u -r1.86 reading.c
--- engine/reading.c 27 Nov 2002 16:32:08 -0000 1.86
+++ engine/reading.c 30 Nov 2002 04:05:07 -0000
@@ -144,8 +144,8 @@
struct reading_moves *moves);
static void special_rescue2_moves(int str, int libs[2],
struct reading_moves *moves);
-static int special_rescue3(int str, int libs[3], int *move,
- int komaster, int kom_pos);
+static void special_rescue3_moves(int str, int libs[3],
+ struct reading_moves *moves);
static void hane_rescue_moves(int str, int libs[4],
struct reading_moves *moves);
static void special_rescue5_moves(int str, int libs[3],
@@ -158,17 +158,16 @@
static int attack2(int str, int *move, int komaster, int kom_pos);
static int attack3(int str, int *move, int komaster, int kom_pos);
static int attack4(int str, int *move, int komaster, int kom_pos);
-static int find_cap2(int str, int alib, int blib, int *move,
- int komaster, int kom_pos);
-static int find_cap(int str, int *move, int komaster, int kom_pos);
-static int special_attack2(int str, int libs[2], int *move,
- int komaster, int kom_pos);
-static int special_attack3(int str, int libs[2], int *move,
- int komaster, int kom_pos);
-static int special_attack4(int str, int libs[2], int *move,
- int komaster, int kom_pos);
-static int draw_back(int str, int *move, int komaster, int kom_pos);
-static int edge_closing_backfill(int str, int apos, int *move);
+static void find_cap_moves(int str, struct reading_moves *moves);
+static void special_attack2_moves(int str, int libs[2],
+ struct reading_moves *moves);
+static void special_attack3_moves(int str, int libs[2],
+ struct reading_moves *moves);
+static void special_attack4_moves(int str, int libs[2],
+ struct reading_moves *moves);
+static void draw_back_moves(int str, struct reading_moves *moves);
+static void edge_closing_backfill_moves(int str, int apos,
+ struct reading_moves *moves);
static void edge_block_moves(int str, int apos,
struct reading_moves *moves);
static void propose_edge_moves(int str, int *libs, int liberties,
@@ -181,10 +180,9 @@
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 int break_chain3(int str, int *move, int komaster, int kom_pos);
-static int superstring_breakchain(int str, int *move,
- int komaster, int kom_pos,
- int liberty_cap);
+static void break_chain3_moves(int str, struct reading_moves *moves);
+static void superstring_breakchain_moves(int str, int liberty_cap,
+ struct reading_moves *moves);
static void double_atari_chain2_moves(int str,
struct reading_moves *moves);
static void order_moves(int str, struct reading_moves *moves,
@@ -1349,17 +1347,15 @@
}
}
+ saved_num_moves = moves.num;
+
if (stackp <= superstring_depth) {
- int dcode = superstring_breakchain(str, &xpos, komaster, kom_pos, 4);
- CHECK_RESULT_UNREVERSED(savecode, savemove, dcode, xpos, move,
- "superstring_breakchain");
+ superstring_breakchain_moves(str, 4, &moves);
}
-
/* If nothing else works, we try playing a liberty of the
* super_string.
*/
- saved_num_moves = moves.num;
if (stackp <= superstring_depth) {
int ss_liberties;
int ss_libs[MAX_LIBERTIES + 4];
@@ -1393,6 +1389,10 @@
if (stackp <= backfill_depth) {
special_rescue5_moves(str, libs, &moves);
}
+
+ if (stackp <= backfill2_depth) {
+ break_chain3_moves(str, &moves);
+ }
/* Only order and test the new set of moves. */
order_moves(str, &moves, other, read_function_name, saved_num_moves);
@@ -1422,17 +1422,6 @@
}
}
- /* We place the more speculative moves trying to break chain links
- * with 2 or 3 liberties last, because these moves often are not
- * really relevant.
- */
-
- if (stackp <= backfill2_depth) {
- int bc = break_chain3(str, &xpos, komaster, kom_pos);
- CHECK_RESULT_UNREVERSED(savecode, savemove, bc, xpos, move,
- "break chain3");
- }
-
if (savecode != 0)
RETURN_RESULT(savecode, savemove, move, "saved move");
@@ -1587,28 +1576,25 @@
/* If nothing else works, try to defend with second order liberties. */
- if (stackp <= backfill_depth) {
- int dcode = special_rescue3(str, libs, &xpos, komaster, kom_pos);
- CHECK_RESULT_UNREVERSED(savecode, savemove, dcode, xpos, move,
- "special rescue3");
- }
-
+ saved_num_moves = moves.num;
+
if (level >= 10 && stackp <= backfill2_depth) {
- int dcode = superstring_breakchain(str, &xpos, komaster, kom_pos, 4);
- CHECK_RESULT_UNREVERSED(savecode, savemove, dcode, xpos, move,
- "superstring_breakchain");
+ superstring_breakchain_moves(str, 4, &moves);
+ }
+
+ if (stackp <= backfill_depth) {
+ special_rescue3_moves(str, libs, &moves);
}
-
-
- saved_num_moves = moves.num;
if (stackp <= depth) {
for (k = 0; k < liberties; k++)
special_rescue_moves(str, libs[k], &moves);
}
- if (stackp <= backfill2_depth)
+ if (stackp <= backfill2_depth) {
break_chain2_defense_moves(str, &moves);
+ break_chain3_moves(str, &moves);
+ }
/* If nothing else works, we try playing a liberty of the
* super_string.
@@ -1674,17 +1660,6 @@
}
}
- /* We place the more speculative moves trying to break chain links
- * with 2 or 3 liberties last, because these moves often are not
- * really relevant.
- */
-
- if (stackp <= backfill2_depth) {
- int bc = break_chain3(str, &xpos, komaster, kom_pos);
- CHECK_RESULT_UNREVERSED(savecode, savemove, bc, xpos, move,
- "break chain3");
- }
-
if (savecode != 0)
RETURN_RESULT(savecode, savemove, move, "saved move");
@@ -1891,14 +1866,12 @@
* .*. afg
* --- b--
*/
-static int
-special_rescue3(int str, int libs[3], int *move, int komaster, int kom_pos)
+static void
+special_rescue3_moves(int str, int libs[3], struct reading_moves *moves)
{
int color = board[str];
int other = OTHER_COLOR(color);
int apos, bpos, cpos, dpos, epos, fpos, gpos;
- int savemove = 0;
- int savecode = 0;
int k, l, r;
ASSERT1(countlib(str) == 3, str);
@@ -1948,26 +1921,10 @@
continue;
/* Try to play at (fpos). */
- if (trymove(fpos, color, "special_rescue3", str, komaster, kom_pos)) {
- int acode = do_attack(str, NULL, komaster, kom_pos);
- if (acode != WIN) {
- if (acode == 0) {
- popgo();
- *move = fpos;
- return WIN;
- }
- UPDATE_SAVED_KO_RESULT(savecode, savemove, acode, fpos);
- }
- popgo();
- }
+ ADD_CANDIDATE_MOVE(fpos, 0, *moves);
}
}
}
-
- if (savecode != 0)
- *move = savemove;
-
- return savecode;
}
@@ -3083,7 +3040,6 @@
int adj, adjs[MAXCHAIN];
int savemove = 0;
int savecode = 0;
- int acode;
int dcode;
int k;
int atari_possible = 0;
@@ -3189,7 +3145,15 @@
break_chain_moves(apos, &moves);
}
+ if (stackp <= backfill_depth) {
+ special_attack2_moves(str, libs, &moves);
+ special_attack3_moves(str, libs, &moves);
+ special_attack4_moves(str, libs, &moves);
+ }
+
+
propose_edge_moves(str, libs, liberties, &moves, other);
+ find_cap_moves(str, &moves);
order_moves(str, &moves, other, read_function_name, 0);
for (k = 0; k < moves.num; k++) {
@@ -3223,28 +3187,6 @@
}
}
- /* The simple ataris didn't work. Try something more fancy. */
- acode = find_cap2(str, libs[0], libs[1], &xpos, komaster, kom_pos);
- CHECK_RESULT_UNREVERSED(savecode, savemove, acode, xpos, move, "find cap2");
-
- if (stackp <= backfill_depth) {
- acode = special_attack2(str, libs, &xpos, komaster, kom_pos);
- CHECK_RESULT_UNREVERSED(savecode, savemove, acode, xpos, move,
- "special attack2");
- }
-
- if (stackp <= backfill_depth) {
- acode = special_attack3(str, libs, &xpos, komaster, kom_pos);
- CHECK_RESULT_UNREVERSED(savecode, savemove, acode, xpos, move,
- "special attack3");
- }
-
- if (stackp <= backfill_depth) {
- acode = special_attack4(str, libs, &xpos, komaster, kom_pos);
- CHECK_RESULT_UNREVERSED(savecode, savemove, acode, xpos, move,
- "special attack4");
- }
-
/* If it is not possible to make a direct atari, we try filling
* a liberty of the superstring.
*/
@@ -3385,8 +3327,7 @@
|| !is_self_atari(apos, other))
ADD_CANDIDATE_MOVE(apos, 0, moves);
- if (edge_closing_backfill(str, apos, &xpos))
- ADD_CANDIDATE_MOVE(xpos, 0, moves);
+ edge_closing_backfill_moves(str, apos, &moves);
#if 0
/* Try backfilling if atari is impossible. */
@@ -3402,6 +3343,16 @@
/* Pick up some edge moves. */
propose_edge_moves(str, libs, liberties, &moves, other);
+
+ /* The simple ataris didn't work. Try something more fancy. */
+ if (stackp <= backfill_depth) {
+ find_cap_moves(str, &moves);
+ }
+
+ if (stackp <= fourlib_depth) {
+ draw_back_moves(str, &moves);
+ }
+
order_moves(str, &moves, other, read_function_name, 0);
/* Try the moves collected so far. */
@@ -3437,19 +3388,6 @@
}
}
- /* The simple ataris didn't work. Try something more fancy. */
- if (stackp <= backfill_depth) {
- int acode = find_cap(str, &xpos, komaster, kom_pos);
- CHECK_RESULT_UNREVERSED(savecode, savemove, acode, xpos, move,
- "find cap3");
- }
-
- if (stackp <= fourlib_depth) {
- int acode = draw_back(str, &xpos, komaster, kom_pos);
- CHECK_RESULT_UNREVERSED(savecode, savemove, acode, xpos, move,
- "draw back");
- }
-
/* Try to defend chain links with two liberties. */
if (stackp <= backfill2_depth) {
int saved_num_moves = moves.num;
@@ -3623,8 +3561,7 @@
|| !is_self_atari(apos, other))
ADD_CANDIDATE_MOVE(apos, 0, moves);
- if (edge_closing_backfill(str, apos, &xpos))
- ADD_CANDIDATE_MOVE(xpos, 10, moves);
+ edge_closing_backfill_moves(str, apos, &moves);
/* Look for edge blocking moves. */
edge_block_moves(str, apos, &moves);
@@ -3632,6 +3569,11 @@
/* Pick up some edge moves. */
propose_edge_moves(str, libs, liberties, &moves, other);
+
+ if (stackp <= backfill_depth) {
+ find_cap_moves(str, &moves);
+ }
+
order_moves(str, &moves, other, read_function_name, 0);
/* Try the moves collected so far. */
@@ -3668,94 +3610,19 @@
}
}
- if (stackp <= backfill_depth) {
- int acode = find_cap(str, &xpos, komaster, kom_pos);
- CHECK_RESULT_UNREVERSED(savecode, savemove, acode, xpos, move,
- "find cap");
- }
-
RETURN_RESULT(savecode, savemove, move, "saved move");
}
-/* find_cap2(str, alib, blib, &i, &j, komaster)
- * looks for a configuration of the following type:
- *
- * X.
- * .*
- *
- * where X is an element of the string in question. It tries the
- * move at * and returns true this move captures the string, leaving
- * (i, j) pointing to *.
- */
-
-static int
-find_cap2(int str, int alib, int blib, int *move, int komaster, int kom_pos)
-{
- int ai, aj;
- int bi, bj;
-
- /* Check if the two liberties are located like the figure above. */
- if (alib != SW(blib)
- && alib != NW(blib)
- && alib != NE(blib)
- && alib != SE(blib))
- return 0;
-
- ai = I(alib);
- aj = J(alib);
- bi = I(blib);
- bj = J(blib);
- /* Which of the two corner points should we use? One of them is
- * always occupied by the string at (str), the other one is either
- * free or occupied by something else.
- */
- if (BOARD(bi, aj) == EMPTY)
- *move = POS(bi, aj);
- else if (BOARD(ai, bj) == EMPTY)
- *move = POS(ai, bj);
- else
- return 0;
-
- /* Ok, we found the spot. Now see if the move works. */
- RTRACE("trying to capture %1m with capping move at %1m\n", str, *move);
- if (trymove(*move, OTHER_COLOR(board[str]), "find_cap2", str,
- komaster, kom_pos)) {
- int dcode = do_find_defense(str, NULL, komaster, kom_pos);
- popgo();
- switch (dcode) {
- case 0:
- RTRACE("cap2 succeeded!\n");
- return WIN;
- break;
- case WIN:
- RTRACE("cap2 failed!\n");
- return 0;
- break;
- case KO_B:
- RTRACE("cap2 succeeded with ko return code KO_B\n");
- return KO_B;
- break;
- case KO_A:
- RTRACE("cap2 succeeded with ko return code KO_A\n");
- return KO_A;
- break;
- }
- }
-
- return 0;
-}
-
-
-/* If (str) points to a string with 2 - 4 liberties, find_cap(str, &move)
+/* If (str) points to a string with 2 - 4 liberties,
+ * find_cap_moves(str, &moves)
* looks for a configuration of the following type:
*
* Xa
* b*
*
* where X are elements of the string in question and a and b are
- * two of its liberties. It tries the move at * and returns true
- * this move captures the string, leaving (*move) pointing to *.
+ * two of its liberties.
*
* For larger strings, this can find moves like
*
@@ -3768,39 +3635,46 @@
* even though they are not capping moves.
*/
-static int
-find_cap(int str, int *move, int komaster, int kom_pos)
+static void
+find_cap_moves(int str, struct reading_moves *moves)
{
int alib, blib;
int numlibs;
int libs[4];
- int xpos = 0;
int i,j;
- int savemove = 0;
- int savecode = 0;
- int acode;
+ int ai, aj;
+ int bi, bj;
numlibs = findlib(str, 4, libs);
if (numlibs > 4 || numlibs < 2)
- return 0;
+ return;
- for (i = 0; i < numlibs - 1; i++)
+ for (i = 0; i < numlibs - 1; i++) {
for (j = i + 1; j < numlibs; j++) {
alib = libs[i];
blib = libs[j];
- acode = find_cap2(str, alib, blib, &xpos, komaster, kom_pos);
- if (acode == WIN) {
- *move = xpos;
- return WIN;
- }
- UPDATE_SAVED_KO_RESULT_UNREVERSED(savecode, savemove, acode, xpos);
+ /* Check if the two liberties are located like the figure above. */
+ if (alib != SW(blib)
+ && alib != NW(blib)
+ && alib != NE(blib)
+ && alib != SE(blib))
+ continue;
+
+ ai = I(alib);
+ aj = J(alib);
+ bi = I(blib);
+ bj = J(blib);
+ /* Which of the two corner points should we use? One of them is
+ * always occupied by the string at (str), the other one is either
+ * free or occupied by something else.
+ */
+ if (BOARD(bi, aj) == EMPTY)
+ ADD_CANDIDATE_MOVE(POS(bi, aj), 10, *moves);
+ else if (BOARD(ai, bj) == EMPTY)
+ ADD_CANDIDATE_MOVE(POS(ai, bj), 10, *moves);
}
-
- if (savecode != 0)
- *move = savemove;
-
- return savecode;
+ }
}
@@ -3818,15 +3692,13 @@
* fairly similar to this situation.
*/
-static int
-special_attack2(int str, int libs[2], int *move, int komaster, int kom_pos)
+static void
+special_attack2_moves(int str, int libs[2], struct reading_moves *moves)
{
int color = board[str];
int other = OTHER_COLOR(color);
int newlibs[3];
int xpos;
- int savemove = 0;
- int savecode = 0;
int k;
for (k = 0; k < 2; k++) {
@@ -3837,26 +3709,11 @@
else
xpos = newlibs[1];
- if (!is_self_atari(xpos, other)
- && trymove(xpos, other, "special_attack2", str, komaster, kom_pos)) {
- int dcode = do_find_defense(str, NULL, komaster, kom_pos);
- if (dcode != WIN && do_attack(str, NULL, komaster, kom_pos)) {
- if (dcode == 0) {
- popgo();
- *move = xpos;
- return WIN;
- }
- UPDATE_SAVED_KO_RESULT(savecode, savemove, dcode, xpos);
- }
- popgo();
+ if (!is_self_atari(xpos, other)) {
+ ADD_CANDIDATE_MOVE(xpos, 0, *moves);
}
}
}
-
- if (savecode != 0)
- *move = savemove;
-
- return savecode;
}
@@ -3872,18 +3729,12 @@
* the code that follows can find the attacking move at c.
*/
-static int
-special_attack3(int str, int libs[2], int *move, int komaster, int kom_pos)
+static void
+special_attack3_moves(int str, int libs[2], struct reading_moves *moves)
{
int color = board[str];
int other = OTHER_COLOR(color);
- int acode;
- int dcode;
- int savemove = 0;
- int savecode = 0;
- int newlibs[2];
int xpos;
- int ypos;
int apos;
int bpos;
int k;
@@ -3911,49 +3762,11 @@
continue;
}
else
- return 0; /* Incorrect configuration, give up. */
+ return; /* Incorrect configuration, give up. */
- if (is_self_atari(xpos, other)
- || !trymove(xpos, other, "special_attack3-A", str, komaster, kom_pos))
- continue;
-
- if (countlib(xpos) == 2) {
- findlib(xpos, 2, newlibs);
- if (newlibs[0] == apos)
- ypos = newlibs[1];
- else
- ypos = newlibs[0];
-
- if (!is_self_atari(ypos, color)
- && trymove(ypos, color, "special_attack3-B", str,
- komaster, kom_pos)) {
- acode = do_attack(str, NULL, komaster, kom_pos);
- if (acode == 0) {
- popgo();
- popgo();
- continue;
- }
- UPDATE_SAVED_KO_RESULT_UNREVERSED(savecode, savemove, acode, xpos);
- popgo();
- }
- }
-
- dcode = do_find_defense(str, NULL, komaster, kom_pos);
- if (dcode != WIN && do_attack(str, NULL, komaster, kom_pos)) {
- if (dcode == 0) {
- popgo();
- *move = xpos;
- return WIN;
- }
- UPDATE_SAVED_KO_RESULT(savecode, savemove, dcode, xpos);
- }
- popgo();
+ if (!is_self_atari(xpos, other))
+ ADD_CANDIDATE_MOVE(xpos, 0, *moves);
}
-
- if (savecode != 0)
- *move = savemove;
-
- return savecode;
}
@@ -3968,14 +3781,11 @@
* the code that follows can find the attacking move at *.
*/
-static int
-special_attack4(int str, int libs[2], int *move, int komaster, int kom_pos)
+static void
+special_attack4_moves(int str, int libs[2], struct reading_moves *moves)
{
int color = board[str];
int other = OTHER_COLOR(color);
- int dcode;
- int savemove = 0;
- int savecode = 0;
int adj, adjs[MAXCHAIN];
int adj2, adjs2[MAXCHAIN];
int libs2[2];
@@ -3995,7 +3805,7 @@
*/
if (!is_self_atari(libs[0], other)
|| !is_self_atari(libs[1], other))
- return 0;
+ return;
/* Pick up chain links with 2 liberties. */
adj = chainlinks2(str, adjs, 2);
@@ -4050,27 +3860,10 @@
if (elibs > dlibs)
continue;
- if (trymove(dpos, other, "special_attack4", str, komaster, kom_pos)) {
- dcode = do_find_defense(str, NULL, komaster, kom_pos);
-
- if (dcode != WIN && do_attack(str, NULL, komaster, kom_pos)) {
- if (dcode == 0) {
- popgo();
- *move = dpos;
- return WIN;
- }
- UPDATE_SAVED_KO_RESULT(savecode, savemove, dcode, dpos);
- }
- popgo();
- }
+ ADD_CANDIDATE_MOVE(dpos, 0, *moves);
}
}
}
-
- if (savecode != 0)
- *move = savemove;
-
- return savecode;
}
@@ -4087,14 +3880,12 @@
*
*/
-static int
-draw_back(int str, int *move, int komaster, int kom_pos)
+static void
+draw_back_moves(int str, struct reading_moves *moves)
{
int r, k;
int adj, adjs[MAXCHAIN];
int libs[2];
- int savemove = 0;
- int savecode = 0;
adj = chainlinks2(str, adjs, 2);
for (r = 0; r < adj; r++) {
@@ -4109,27 +3900,10 @@
&& liberty_of_string(NORTH(libs[k]), str))
|| (ON_BOARD1(EAST(libs[k]))
&& liberty_of_string(EAST(libs[k]), str)))) {
- if (trymove(libs[k], OTHER_COLOR(board[str]), "draw_back", str,
- komaster, kom_pos)) {
- int dcode = do_find_defense(str, NULL, komaster, kom_pos);
- if (dcode != WIN && do_attack(str, NULL, komaster, kom_pos)) {
- if (dcode == 0) {
- popgo();
- *move = libs[k];
- return WIN;
- }
- UPDATE_SAVED_KO_RESULT(savecode, savemove, dcode, libs[k]);
- }
- popgo();
- }
+ ADD_CANDIDATE_MOVE(libs[k], 0, *moves);
}
}
}
-
- if (savecode != 0)
- *move = savemove;
-
- return savecode;
}
/* In the following position the reading is much simplifed if we start
@@ -4152,8 +3926,8 @@
* and b and c do not contain more O stones than X stones.
*/
-static int
-edge_closing_backfill(int str, int apos, int *move)
+static void
+edge_closing_backfill_moves(int str, int apos, struct reading_moves *moves)
{
int color = board[str];
int other = OTHER_COLOR(color);
@@ -4168,7 +3942,7 @@
if (ON_BOARD(apos - up))
continue;
if (board[apos + up] != color)
- return 0;
+ return;
if (board[apos + right] == EMPTY
&& (!ON_BOARD(apos - right)
|| board[apos - right] == color))
@@ -4180,14 +3954,14 @@
right = -right;
}
else
- return 0;
+ return;
if (board[apos + up + right] != other)
- return 0;
+ return;
bpos = apos + up + 2 * right;
if (!ON_BOARD(bpos))
- return 0;
+ return;
cpos = apos + 2 * right;
@@ -4204,13 +3978,11 @@
number_o++;
if (number_o > number_x)
- return 0;
+ return;
- *move = apos + right;
- return WIN;
+ ADD_CANDIDATE_MOVE(apos + right, 0, *moves);
+ return;
}
-
- return 0;
}
@@ -4612,19 +4384,15 @@
/*
- * (str) points to a group. break_chain3(str, *move)
- * returns 1 if there is a string in the surrounding chain having
+ * (str) points to a group.
+ * If there is a string in the surrounding chain having
* exactly three liberties whose attack leads to the rescue of
- * (str). Then (*move) points to the location of the attacking move.
- *
- * Returns KO_A if the saving move depends on ignoring a ko threat;
- *
- * Returns KO_B if the saving move requires making a ko threat and winning
- * the ko.
+ * (str), break_chain3(str, *moves) adds attack moves against
+ * the surrounding string as candidate moves.
*/
-static int
-break_chain3(int str, int *move, int komaster, int kom_pos)
+static void
+break_chain3_moves(int str, struct reading_moves *moves)
{
int color = board[str];
int other = OTHER_COLOR(color);
@@ -4635,13 +4403,8 @@
int adj;
int adjs[MAXCHAIN];
int libs[3];
- int moves[MAX_MOVES];
+ int possible_moves[MAX_MOVES];
int mw[BOARDMAX];
- int savemove = 0;
- int savecode = 0;
- int liberties = countlib(str);
-
- SETUP_TRACE_INFO("break_chain3", str);
memset(mw, 0, sizeof(mw));
@@ -4658,6 +4421,7 @@
*/
findlib(apos, 3, libs);
+#if 1
/* If the 3 liberty chain easily can run away through one of the
* liberties, we don't play on any of the other liberties.
*/
@@ -4672,146 +4436,70 @@
if (lib1 >= 4 && !mw[libs[0]]) {
mw[libs[0]] = 1;
- moves[u++] = libs[0];
+ possible_moves[u++] = libs[0];
continue;
}
if (lib2 >= 4 && !mw[libs[1]]) {
mw[libs[1]] = 1;
- moves[u++] = libs[1];
+ possible_moves[u++] = libs[1];
continue;
}
if (lib3 >= 4 && !mw[libs[2]]) {
mw[libs[2]] = 1;
- moves[u++] = libs[2];
+ possible_moves[u++] = libs[2];
continue;
}
+#endif
/* No easy escape, try all liberties. */
for (k = 0; k < 3; k++) {
if (!mw[libs[k]]) {
mw[libs[k]] = 1;
- moves[u++] = libs[k];
+ possible_moves[u++] = libs[k];
}
}
}
/* We do not wish to consider the move if it can be
* immediately recaptured, unless stackp <= backfill2_depth.
+ * This doesn't actually seem to impact reading node counts.
*/
for (v = 0; v < u; v++) {
- if (!trymove(moves[v], color, "break_chain3-A", str, komaster, kom_pos))
- continue;
-
- if (countlib(moves[v]) == 1 && stackp > backfill2_depth) {
- popgo();
+#if 1
+ if (approxlib(possible_moves[v], color, 5, NULL) == 1 && stackp >
backfill2_depth)
continue;
- }
-
- /* If we just filled our own liberty we back out now */
- if (countlib(str) >= liberties) {
- int acode = do_attack(str, NULL, komaster, kom_pos);
- if (acode == 0) {
- *move = moves[v];
- popgo();
- SGFTRACE(moves[v], WIN, "attack defended");
- return WIN;
- }
- UPDATE_SAVED_KO_RESULT(savecode, savemove, acode, moves[v]);
- }
- popgo(); /* (moves[v]) */
- }
-
- if (savecode != 0) {
- *move = savemove;
- SGFTRACE(savemove, savecode, "saved move");
- return savecode;
+#endif
+ ADD_CANDIDATE_MOVE(possible_moves[v], 0, *moves);
}
-
- SGFTRACE(0, 0, NULL);
- return 0;
}
/* 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,
* and which are not adjacent to the string itself, since those
- * are tested by break_chain. If such a boundary chain can be
- * attacked, and if attacking the boundary results in saving
- * the (str) string, then success is reported.
+ * are tested by break_chain.
*/
-/* FIXME: Consider ko captures */
-static int
-superstring_breakchain(int str, int *move, int komaster, int kom_pos,
- int liberty_cap)
+static void
+superstring_breakchain_moves(int str, int liberty_cap, struct reading_moves
*moves)
{
- int color = board[str];
int adj;
int adjs[MAXCHAIN];
int k;
int apos;
- struct reading_moves moves;
- int savemove = 0;
- int savecode = 0;
-
- SETUP_TRACE_INFO("superstring_breakchain", str);
-
- moves.num = 0;
proper_superstring_chainlinks(str, &adj, adjs, liberty_cap);
for (k = 0; k < adj; k++) {
int liberties = countlib(adjs[k]);
if (liberties == 1) {
findlib(adjs[k], 1, &apos);
- ADD_CANDIDATE_MOVE(apos, 0, moves);
+ ADD_CANDIDATE_MOVE(apos, 0, *moves);
}
else if (liberties == 2)
- do_find_break_chain2_efficient_moves(str, adjs[k], &moves);
+ do_find_break_chain2_efficient_moves(str, adjs[k], moves);
}
-
- order_moves(str, &moves, color, read_function_name, 0);
-
- for (k = 0; k < moves.num; k++) {
- int new_komaster, new_kom_pos;
- int ko_move;
-
- apos = moves.pos[k];
- if (komaster_trymove(apos, color, "superstring_break_chain", str,
- komaster, kom_pos, &new_komaster, &new_kom_pos,
- &ko_move, savecode == 0 && stackp <= ko_depth)) {
- if (!ko_move) {
- int acode = do_attack(str, NULL, new_komaster, new_kom_pos);
- if (acode == 0) {
- popgo();
- *move = apos;
- SGFTRACE(apos, WIN, "attack defended");
- return WIN;
- }
- else if (acode != WIN) {
- UPDATE_SAVED_KO_RESULT(savecode, savemove, acode, apos);
- }
- popgo();
- }
- else {
- if (do_attack(str, NULL, new_komaster, new_kom_pos) != WIN) {
- savemove = apos;
- savecode = KO_B;
- }
- popgo();
- }
- }
- }
-
- if (savecode != 0) {
- *move = savemove;
- SGFTRACE(savemove, savecode, "saved move");
- return savecode;
- }
-
- SGFTRACE(0, 0, NULL);
- return 0;
}
/*
- [gnugo-devel] tactics code cleanup,
Evan Berggren Daniel <=