From fd91c59d548e6770bf273a44338f7dd3faaaeca3 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Sun, 20 Feb 2011 20:46:39 +0100 Subject: [PATCH] is_middle_ladder(): Factor out middle_ladder_walk() --- tactics/ladder.c | 94 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/tactics/ladder.c b/tactics/ladder.c index 2acce21..27a1a6a 100644 --- a/tactics/ladder.c +++ b/tactics/ladder.c @@ -58,11 +58,60 @@ is_border_ladder(struct board *b, coord_t coord, enum stone lcolor) return true; } + /* This is very trivial and gets a lot of corner cases wrong. * We need this to be just very fast. One important point is * that we sometimes might not notice a ladder but if we do, * it should always work; thus we can use this for strong * negative hinting safely. */ + +static bool +middle_ladder_walk(struct board *b, enum stone lcolor, int x, int y, int xd, int yd) +{ +#define ladder_check(xd1_, yd1_, xd2_, yd2_, xd3_, yd3_) \ + if (board_atxy(b, x, y) != S_NONE) { \ + /* Did we hit a stone when playing out ladder? */ \ + if (ladder_catcher(b, x, y, lcolor)) \ + return true; /* ladder works */ \ + if (board_group_info(b, group_atxy(b, x, y)).lib[0] > 0) \ + return false; /* friend that's not in atari himself */ \ + } else { \ + /* No. So we are at new position. \ + * We need to check indirect ladder breakers. */ \ + /* . 2 x 3 . \ + * . x o O 1 <- only at O we can check for o at 2 \ + * x o o x . otherwise x at O would be still deadly \ + * o o x . . \ + * We check for o and x at 1, these are vital. \ + * We check only for o at 2; x at 2 would mean we \ + * need to fork (one step earlier). */ \ + coord_t c = coord_xy(b, x, y); \ + coord_t c1 = coord_xy(b, x + (xd1_), y + (yd1_)); \ + enum stone s1 = board_at(b, c1); \ + if (s1 == lcolor) return false; \ + if (s1 == stone_other(lcolor)) { \ + /* One more thing - if the position at 3 is \ + * friendly and safe, we escaped anyway! */ \ + coord_t c3 = coord_xy(b, x + (xd3_), y + (yd3_)); \ + return board_at(b, c3) != lcolor \ + || board_group_info(b, group_at(b, c3)).libs < 2; \ + } \ + enum stone s2 = board_atxy(b, x + (xd2_), y + (yd2_)); \ + if (s2 == lcolor) return false; \ + if (neighbor_count_at(b, c1, lcolor) + neighbor_count_at(b, c1, S_OFFBOARD) >= 2) \ + return false; /* It would be self-atari! */ \ + } +#define ladder_horiz do { if (DEBUGL(6)) fprintf(stderr, "%d,%d horiz step (%d,%d)\n", x, y, xd, yd); x += xd; ladder_check(xd, 0, -2 * xd, yd, 0, yd); } while (0) +#define ladder_vert do { if (DEBUGL(6)) fprintf(stderr, "%d,%d vert step of (%d,%d)\n", x, y, xd, yd); y += yd; ladder_check(0, yd, xd, -2 * yd, xd, 0); } while (0) + + if (ladder_catcher(b, x - xd, y, lcolor)) + ladder_horiz; + do { + ladder_vert; + ladder_horiz; + } while (1); +} + bool is_middle_ladder(struct board *b, coord_t coord, enum stone lcolor) { @@ -126,47 +175,6 @@ is_middle_ladder(struct board *b, coord_t coord, enum stone lcolor) } #undef check_catcher_danger #endif - -#define ladder_check(xd1_, yd1_, xd2_, yd2_, xd3_, yd3_) \ - if (board_atxy(b, x, y) != S_NONE) { \ - /* Did we hit a stone when playing out ladder? */ \ - if (ladder_catcher(b, x, y, lcolor)) \ - return true; /* ladder works */ \ - if (board_group_info(b, group_atxy(b, x, y)).lib[0] > 0) \ - return false; /* friend that's not in atari himself */ \ - } else { \ - /* No. So we are at new position. \ - * We need to check indirect ladder breakers. */ \ - /* . 2 x 3 . \ - * . x o O 1 <- only at O we can check for o at 2 \ - * x o o x . otherwise x at O would be still deadly \ - * o o x . . \ - * We check for o and x at 1, these are vital. \ - * We check only for o at 2; x at 2 would mean we \ - * need to fork (one step earlier). */ \ - coord_t c1 = coord_xy(b, x + (xd1_), y + (yd1_)); \ - enum stone s1 = board_at(b, c1); \ - if (s1 == lcolor) return false; \ - if (s1 == stone_other(lcolor)) { \ - /* One more thing - if the position at 3 is \ - * friendly and safe, we escaped anyway! */ \ - coord_t c3 = coord_xy(b, x + (xd3_), y + (yd3_)); \ - return board_at(b, c3) != lcolor \ - || board_group_info(b, group_at(b, c3)).libs < 2; \ - } \ - enum stone s2 = board_atxy(b, x + (xd2_), y + (yd2_)); \ - if (s2 == lcolor) return false; \ - /* Then, can X actually "play" 1 in the ladder? */ \ - if (neighbor_count_at(b, c1, lcolor) + neighbor_count_at(b, c1, S_OFFBOARD) >= 2) \ - return false; /* It would be self-atari! */ \ - } -#define ladder_horiz do { if (DEBUGL(6)) fprintf(stderr, "%d,%d horiz step (%d,%d)\n", x, y, xd, yd); x += xd; ladder_check(xd, 0, -2 * xd, yd, 0, yd); } while (0) -#define ladder_vert do { if (DEBUGL(6)) fprintf(stderr, "%d,%d vert step of (%d,%d)\n", x, y, xd, yd); y += yd; ladder_check(0, yd, xd, -2 * yd, xd, 0); } while (0) - - if (ladder_catcher(b, x - xd, y, lcolor)) - ladder_horiz; - do { - ladder_vert; - ladder_horiz; - } while (1); + + return middle_ladder_walk(b, lcolor, x, y, xd, yd); } -- 2.11.4.GIT