From aef5ce1e170b7af77e358d111619fa09f6fcbf4f Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Wed, 7 Oct 2009 11:39:45 +0200 Subject: [PATCH] is_bad_selfatari(): Introduce struct selfatari_state --- tactics.c | 91 ++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/tactics.c b/tactics.c index fbdaa51..4a9cf91 100644 --- a/tactics.c +++ b/tactics.c @@ -6,6 +6,22 @@ #include "debug.h" +struct selfatari_state { + int groupcts[S_MAX]; + group_t groupids[S_MAX][4]; + + /* This is set if this move puts a group out of _all_ + * liberties; we need to watch out for snapback then. */ + bool friend_has_no_libs; + /* We may have one liberty, but be looking for one more. + * In that case, @needs_more_lib is id of group + * already providing one, don't consider it again. */ + group_t needs_more_lib; + /* ID of the first liberty, providing it again is not + * interesting. */ + coord_t needs_more_lib_except; +}; + bool is_bad_selfatari_slow(struct board *b, enum stone color, coord_t to) { @@ -13,37 +29,28 @@ is_bad_selfatari_slow(struct board *b, enum stone color, coord_t to) /* Assess if we actually gain any liberties by this escape route. * Note that this is not 100% as we cannot check whether we are * connecting out or just to ourselves. */ - int groupcts[S_MAX] = {}; - group_t groupids[S_MAX][4] = {}; + + struct selfatari_state s; + memset(&s, 0, sizeof(s)); + foreach_neighbor(b, to, { - enum stone s = board_at(b, c); - groupids[s][groupcts[s]++] = group_at(b, c); + enum stone color = board_at(b, c); + s.groupids[color][s.groupcts[color]++] = group_at(b, c); }); /* We have shortage of liberties; that's the point. */ - assert(groupcts[S_NONE] <= 1); - - /* This is set if this move puts a group out of _all_ - * liberties; we need to watch out for snapback then. */ - bool friend_has_no_libs = false; - /* We may have one liberty, but be looking for one more. - * In that case, @needs_more_lib is id of group - * already providing one, don't consider it again. */ - group_t needs_more_lib = 0; - /* ID of the first liberty, providing it again is not - * interesting. */ - coord_t needs_more_lib_except = 0; + assert(s.groupcts[S_NONE] <= 1); /* Examine friendly groups: */ for (int i = 0; i < 4; i++) { /* We can escape by connecting to this group if it's * not in atari. */ - group_t g = groupids[color][i]; + group_t g = s.groupids[color][i]; if (!g) continue; if (board_group_info(b, g).libs == 1) { - if (!needs_more_lib) - friend_has_no_libs = true; + if (!s.needs_more_lib) + s.friend_has_no_libs = true; // or we already have a friend with 1 lib continue; } @@ -59,24 +66,24 @@ is_bad_selfatari_slow(struct board *b, enum stone color, coord_t to) if (lib2 == to) lib2 = board_group_info(b, g).lib[1]; /* Maybe we already looked at another * group providing one liberty? */ - if (needs_more_lib && needs_more_lib != g - && needs_more_lib_except != lib2) + if (s.needs_more_lib && s.needs_more_lib != g + && s.needs_more_lib_except != lib2) return false; /* Can we get the liberty locally? */ /* Yes if we are route to more liberties... */ - if (groupcts[S_NONE] > 1) + if (s.groupcts[S_NONE] > 1) return false; /* ...or one liberty, but not lib2. */ - if (groupcts[S_NONE] > 0 + if (s.groupcts[S_NONE] > 0 && !coord_is_adjecent(lib2, to, b)) return false; /* ...ok, then we can still contribute a liberty * later by capturing something. */ - needs_more_lib = g; - needs_more_lib_except = lib2; - friend_has_no_libs = false; + s.needs_more_lib = g; + s.needs_more_lib_except = lib2; + s.friend_has_no_libs = false; } //fprintf(stderr, "no friendly group\n"); @@ -87,7 +94,7 @@ is_bad_selfatari_slow(struct board *b, enum stone color, coord_t to) /* Examine enemy groups: */ for (int i = 0; i < 4; i++) { /* We can escape by capturing this group if it's in atari. */ - group_t g = groupids[stone_other(color)][i]; + group_t g = s.groupids[stone_other(color)][i]; if (!g || board_group_info(b, g).libs > 1) continue; @@ -95,18 +102,18 @@ is_bad_selfatari_slow(struct board *b, enum stone color, coord_t to) * we already have one outside liberty, or the group is * more than 1 stone (in that case, capturing is always * nice!). */ - if (groupcts[S_NONE] > 0 || !group_is_onestone(b, g)) + if (s.groupcts[S_NONE] > 0 || !group_is_onestone(b, g)) return false; /* ...or, it's a ko stone, */ if (neighbor_count_at(b, g, color) + neighbor_count_at(b, g, S_OFFBOARD) == 3) { /* and we don't have a group to save: then, just taking * single stone means snapback! */ - if (!friend_has_no_libs) + if (!s.friend_has_no_libs) return false; } /* ...or, we already have one indirect liberty provided * by another group. */ - if (needs_more_lib || (can_capture && can_capture != g)) + if (s.needs_more_lib || (can_capture && can_capture != g)) return false; can_capture = g; @@ -114,14 +121,14 @@ is_bad_selfatari_slow(struct board *b, enum stone color, coord_t to) //fprintf(stderr, "no cap group\n"); - if (!needs_more_lib && !can_capture && !groupcts[S_NONE]) { + if (!s.needs_more_lib && !can_capture && !s.groupcts[S_NONE]) { /* We have no hope for more fancy tactics - this move is simply * a suicide, not even a self-atari. */ //fprintf(stderr, "suicide\n"); return true; } /* XXX: I wonder if it makes sense to continue if we actually - * just !needs_more_lib. */ + * just !s.needs_more_lib. */ /* There is another possibility - we can self-atari if it is * a nakade: we put an enemy group in atari from the inside. */ @@ -137,11 +144,11 @@ is_bad_selfatari_slow(struct board *b, enum stone color, coord_t to) /* This branch also covers snapback, which is kind of special * nakade case. ;-) */ for (int i = 0; i < 4; i++) { - group_t g = groupids[stone_other(color)][i]; + group_t g = s.groupids[stone_other(color)][i]; if (!g || board_group_info(b, g).libs != 2) continue; /* Simple check not to re-examine the same group. */ - if (i > 0 && groupids[stone_other(color)][i] == groupids[stone_other(color)][i - 1]) + if (i > 0 && s.groupids[stone_other(color)][i] == s.groupids[stone_other(color)][i - 1]) continue; /* We must make sure the other liberty of that group: @@ -186,7 +193,7 @@ is_bad_selfatari_slow(struct board *b, enum stone color, coord_t to) * we (@to) are connected to. */ int j; for (j = 0; j < 4; j++) - if (groupids[color][j] == g2) + if (s.groupids[color][j] == g2) break; if (j == 4) goto invalid_nakade; @@ -211,15 +218,15 @@ is_bad_selfatari_slow(struct board *b, enum stone color, coord_t to) /* Now, we must distinguish between nakade and eye * falsification; we must not falsify an eye by more * than two stones. */ - if (groupcts[color] < 1 || - (groupcts[color] == 1 && group_is_onestone(b, groupids[color][0]))) + if (s.groupcts[color] < 1 || + (s.groupcts[color] == 1 && group_is_onestone(b, s.groupids[color][0]))) return false; /* We would create more than 2-stone group; in that * case, the liberty of our result must be lib2, * indicating this really is a nakade. */ for (int j = 0; j < 4; j++) { - group_t g2 = groupids[color][j]; + group_t g2 = s.groupids[color][j]; if (!g2) continue; assert(board_group_info(b, g2).libs <= 2); if (board_group_info(b, g2).libs == 2) { @@ -247,9 +254,9 @@ invalid_nakade:; && neighbor_count_at(b, to, stone_other(color)) + neighbor_count_at(b, to, S_OFFBOARD) == 3 && board_is_false_eyelike(b, &to, stone_other(color))) { - assert(groupcts[color] <= 1); + assert(s.groupcts[color] <= 1); /* Single-stone throw-in may be ok... */ - if (groupcts[color] == 0) { + if (s.groupcts[color] == 0) { /* O X . There is one problem - when it's * . * X actually not a throw-in! * # # # */ @@ -266,8 +273,8 @@ invalid_nakade:; } /* Multi-stone throwin...? */ - assert(groupcts[color] == 1); - group_t g = groupids[color][0]; + assert(s.groupcts[color] == 1); + group_t g = s.groupids[color][0]; assert(board_group_info(b, g).libs <= 2); /* Suicide is definitely NOT ok, no matter what else -- 2.11.4.GIT