From dff7ea1e6818d8e8df16e58d7bd957a1b0986a36 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Mon, 11 Oct 2010 12:22:05 +0200 Subject: [PATCH] Move group_atari_check() et al. to tactics/1lib.c. --- playout/moggy.c | 137 +------------------------------------------------ tactics/1lib.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tactics/1lib.h | 17 +++++++ tactics/Makefile | 2 +- 4 files changed, 172 insertions(+), 137 deletions(-) create mode 100644 tactics/1lib.c create mode 100644 tactics/1lib.h diff --git a/playout/moggy.c b/playout/moggy.c index 58fc43c..14ea34e 100644 --- a/playout/moggy.c +++ b/playout/moggy.c @@ -16,6 +16,7 @@ #include "playout.h" #include "playout/moggy.h" #include "random.h" +#include "tactics/1lib.h" #include "tactics/ladder.h" #include "tactics/selfatari.h" #include "uct/prior.h" @@ -181,142 +182,6 @@ apply_pattern(struct playout_policy *p, struct board *b, struct move *m, struct } -static bool -can_play_on_lib(struct board *b, group_t g, enum stone to_play) -{ - coord_t capture = board_group_info(b, g).lib[0]; - if (DEBUGL(6)) - fprintf(stderr, "can capture group %d (%s)?\n", - g, coord2sstr(capture, b)); - /* Does playing on the liberty usefully capture the group? */ - if (board_is_valid_play(b, to_play, capture) - && !is_bad_selfatari(b, to_play, capture)) - return true; - - return false; -} - -/* For given position @c, decide if this is a group that is in danger from - * @capturer and @to_play can do anything about it (play at the last - * liberty to either capture or escape). */ -/* Note that @to_play is important; e.g. consider snapback, it's good - * to play at the last liberty by attacker, but not defender. */ -static __attribute__((always_inline)) bool -capturable_group(struct board *b, enum stone capturer, coord_t c, - enum stone to_play) -{ - group_t g = group_at(b, c); - if (likely(board_at(b, c) != stone_other(capturer) - || board_group_info(b, g).libs > 1)) - return false; - - return can_play_on_lib(b, g, to_play); -} - -/* For given atari group @group owned by @owner, decide if @to_play - * can save it / keep it in danger by dealing with one of the - * neighboring groups. */ -static bool -can_countercapture(struct board *b, enum stone owner, group_t g, - enum stone to_play, struct move_queue *q, int tag) -{ - if (b->clen < 2) - return false; - - unsigned int qmoves_prev = q ? q->moves : 0; - - foreach_in_group(b, g) { - foreach_neighbor(b, c, { - if (!capturable_group(b, owner, c, to_play)) - continue; - - if (!q) { - return true; - } - mq_add(q, board_group_info(b, group_at(b, c)).lib[0], tag); - mq_nodup(q); - }); - } foreach_in_group_end; - - bool can = q ? q->moves > qmoves_prev : false; - return can; -} - -#ifdef NO_DOOMED_GROUPS -static bool -can_be_rescued(struct board *b, group_t group, enum stone color, int tag) -{ - /* Does playing on the liberty rescue the group? */ - if (can_play_on_lib(b, group, color)) - return true; - - /* Then, maybe we can capture one of our neighbors? */ - return can_countercapture(b, color, group, color, NULL, tag); -} -#endif - -/* ladder != NULL implies to always enqueue all relevant moves. */ -static void -group_atari_check(unsigned int alwaysccaprate, struct board *b, group_t group, enum stone to_play, - struct move_queue *q, coord_t *ladder, int tag) -{ - int qmoves_prev = q->moves; - - /* We don't use @to_play almost anywhere since any moves here are good - * for both defender and attacker. */ - - enum stone color = board_at(b, group_base(group)); - coord_t lib = board_group_info(b, group).lib[0]; - - assert(color != S_OFFBOARD && color != S_NONE); - if (DEBUGL(5)) - fprintf(stderr, "[%s] atariiiiiiiii %s of color %d\n", - coord2sstr(group, b), coord2sstr(lib, b), color); - assert(board_at(b, lib) == S_NONE); - - /* Can we capture some neighbor? */ - bool ccap = can_countercapture(b, color, group, to_play, q, tag); - if (ccap && !ladder && alwaysccaprate > fast_random(100)) - return; - - /* Otherwise, do not save kos. */ - if (group_is_onestone(b, group) - && neighbor_count_at(b, lib, color) + neighbor_count_at(b, lib, S_OFFBOARD) == 4) - return; - - /* Do not suicide... */ - if (!can_play_on_lib(b, group, to_play)) - return; -#ifdef NO_DOOMED_GROUPS - /* Do not remove group that cannot be saved by the opponent. */ - if (to_play != color && !can_be_rescued(b, group, color, tag)) - return; -#endif - if (DEBUGL(6)) - fprintf(stderr, "...escape route valid\n"); - - /* ...or play out ladders. */ - if (is_ladder(b, lib, group)) { - /* Sometimes we want to keep the ladder move in the - * queue in order to discourage it. */ - if (!ladder) - return; - else - *ladder = lib; - } - if (DEBUGL(6)) - fprintf(stderr, "...no ladder\n"); - - if (to_play != color) { - /* We are the attacker! In that case, throw away the moves - * that defend our groups, since we can capture the culprit. */ - q->moves = qmoves_prev; - } - - mq_add(q, lib, tag); - mq_nodup(q); -} - static void joseki_check(struct playout_policy *p, struct board *b, enum stone to_play, struct move_queue *q) { diff --git a/tactics/1lib.c b/tactics/1lib.c new file mode 100644 index 0000000..6f78732 --- /dev/null +++ b/tactics/1lib.c @@ -0,0 +1,153 @@ +#include +#include +#include + +#define DEBUG +#include "board.h" +#include "debug.h" +#include "mq.h" +#include "tactics/1lib.h" +#include "tactics/ladder.h" +#include "tactics/selfatari.h" + + +/* Whether to avoid capturing/atariing doomed groups (this is big + * performance hit and may reduce playouts balance; it does increase + * the strength, but not quite proportionally to the performance). */ +//#define NO_DOOMED_GROUPS + + +static bool +can_play_on_lib(struct board *b, group_t g, enum stone to_play) +{ + coord_t capture = board_group_info(b, g).lib[0]; + if (DEBUGL(6)) + fprintf(stderr, "can capture group %d (%s)?\n", + g, coord2sstr(capture, b)); + /* Does playing on the liberty usefully capture the group? */ + if (board_is_valid_play(b, to_play, capture) + && !is_bad_selfatari(b, to_play, capture)) + return true; + + return false; +} + +/* For given position @c, decide if this is a group that is in danger from + * @capturer and @to_play can do anything about it (play at the last + * liberty to either capture or escape). */ +/* Note that @to_play is important; e.g. consider snapback, it's good + * to play at the last liberty by attacker, but not defender. */ +static __attribute__((always_inline)) bool +capturable_group(struct board *b, enum stone capturer, coord_t c, + enum stone to_play) +{ + group_t g = group_at(b, c); + if (likely(board_at(b, c) != stone_other(capturer) + || board_group_info(b, g).libs > 1)) + return false; + + return can_play_on_lib(b, g, to_play); +} + +/* For given atari group @group owned by @owner, decide if @to_play + * can save it / keep it in danger by dealing with one of the + * neighboring groups. */ +static bool +can_countercapture(struct board *b, enum stone owner, group_t g, + enum stone to_play, struct move_queue *q, int tag) +{ + if (b->clen < 2) + return false; + + unsigned int qmoves_prev = q ? q->moves : 0; + + foreach_in_group(b, g) { + foreach_neighbor(b, c, { + if (!capturable_group(b, owner, c, to_play)) + continue; + + if (!q) { + return true; + } + mq_add(q, board_group_info(b, group_at(b, c)).lib[0], tag); + mq_nodup(q); + }); + } foreach_in_group_end; + + bool can = q ? q->moves > qmoves_prev : false; + return can; +} + +#ifdef NO_DOOMED_GROUPS +static bool +can_be_rescued(struct board *b, group_t group, enum stone color, int tag) +{ + /* Does playing on the liberty rescue the group? */ + if (can_play_on_lib(b, group, color)) + return true; + + /* Then, maybe we can capture one of our neighbors? */ + return can_countercapture(b, color, group, color, NULL, tag); +} +#endif + +void +group_atari_check(unsigned int alwaysccaprate, struct board *b, group_t group, enum stone to_play, + struct move_queue *q, coord_t *ladder, int tag) +{ + int qmoves_prev = q->moves; + + /* We don't use @to_play almost anywhere since any moves here are good + * for both defender and attacker. */ + + enum stone color = board_at(b, group_base(group)); + coord_t lib = board_group_info(b, group).lib[0]; + + assert(color != S_OFFBOARD && color != S_NONE); + if (DEBUGL(5)) + fprintf(stderr, "[%s] atariiiiiiiii %s of color %d\n", + coord2sstr(group, b), coord2sstr(lib, b), color); + assert(board_at(b, lib) == S_NONE); + + /* Can we capture some neighbor? */ + bool ccap = can_countercapture(b, color, group, to_play, q, tag); + if (ccap && !ladder && alwaysccaprate > fast_random(100)) + return; + + /* Otherwise, do not save kos. */ + if (group_is_onestone(b, group) + && neighbor_count_at(b, lib, color) + neighbor_count_at(b, lib, S_OFFBOARD) == 4) + return; + + /* Do not suicide... */ + if (!can_play_on_lib(b, group, to_play)) + return; +#ifdef NO_DOOMED_GROUPS + /* Do not remove group that cannot be saved by the opponent. */ + if (to_play != color && !can_be_rescued(b, group, color, tag)) + return; +#endif + if (DEBUGL(6)) + fprintf(stderr, "...escape route valid\n"); + + /* ...or play out ladders. */ + if (is_ladder(b, lib, group)) { + /* Sometimes we want to keep the ladder move in the + * queue in order to discourage it. */ + if (!ladder) + return; + else + *ladder = lib; + } + if (DEBUGL(6)) + fprintf(stderr, "...no ladder\n"); + + if (to_play != color) { + /* We are the attacker! In that case, throw away the moves + * that defend our groups, since we can capture the culprit. */ + q->moves = qmoves_prev; + } + + mq_add(q, lib, tag); + mq_nodup(q); +} diff --git a/tactics/1lib.h b/tactics/1lib.h new file mode 100644 index 0000000..af8f938 --- /dev/null +++ b/tactics/1lib.h @@ -0,0 +1,17 @@ +#ifndef ZZGO_TACTICS_1LIB_H +#define ZZGO_TACTICS_1LIB_H + +/* One-liberty tactical checks (i.e. dealing with atari situations). */ + +#include "board.h" +#include "debug.h" + +struct move_queue; + +/* Examine given group in atari, suggesting suitable moves for player + * @to_play to deal with it (rescuing or capturing it). */ +/* ladder != NULL implies to always enqueue all relevant moves. */ +void group_atari_check(unsigned int alwaysccaprate, struct board *b, group_t group, enum stone to_play, + struct move_queue *q, coord_t *ladder, int tag); + +#endif diff --git a/tactics/Makefile b/tactics/Makefile index dd0e7ba..31a0c91 100644 --- a/tactics/Makefile +++ b/tactics/Makefile @@ -1,5 +1,5 @@ INCLUDES=-I.. -OBJS=ladder.o selfatari.o util.o +OBJS=1lib.o ladder.o selfatari.o util.o all: tactics.a tactics.a: $(OBJS) -- 2.11.4.GIT