5 #define QUICK_BOARD_CODE
11 #include "tactics/1lib.h"
12 #include "tactics/ladder.h"
13 #include "tactics/selfatari.h"
17 capturing_group_is_snapback(struct board
*b
, group_t group
)
19 coord_t lib
= board_group_info(b
, group
).lib
[0];
21 if (immediate_liberty_count(b
, lib
) > 0 ||
22 group_stone_count(b
, group
, 2) > 1)
25 enum stone to_play
= stone_other(board_at(b
, group
));
26 enum stone other
= stone_other(to_play
);
27 if (board_is_eyelike(b
, lib
, other
))
30 foreach_neighbor(b
, lib
, {
31 group_t g
= group_at(b
, c
);
32 if (board_at(b
, c
) == S_OFFBOARD
|| g
== group
)
35 if (board_at(b
, c
) == other
&&
36 board_group_info(b
, g
).libs
== 1) // capture more than one group
38 if (board_at(b
, c
) == to_play
&&
39 board_group_info(b
, g
).libs
> 1)
45 /* Whether to avoid capturing/atariing doomed groups (this is big
46 * performance hit and may reduce playouts balance; it does increase
47 * the strength, but not quite proportionally to the performance). */
48 //#define NO_DOOMED_GROUPS
52 can_capture(struct board
*b
, group_t g
, enum stone to_play
)
54 coord_t capture
= board_group_info(b
, g
).lib
[0];
56 fprintf(stderr
, "can capture group %d (%s)?\n",
57 g
, coord2sstr(capture
, b
));
58 /* Does playing on the liberty usefully capture the group? */
59 if (board_is_valid_play(b
, to_play
, capture
)
60 && !capturing_group_is_snapback(b
, g
))
67 can_play_on_lib(struct board
*b
, group_t g
, enum stone to_play
)
69 coord_t capture
= board_group_info(b
, g
).lib
[0];
71 fprintf(stderr
, "can capture group %d (%s)?\n",
72 g
, coord2sstr(capture
, b
));
73 /* Does playing on the liberty usefully capture the group? */
74 if (board_is_valid_play(b
, to_play
, capture
)
75 && !is_bad_selfatari(b
, to_play
, capture
))
82 static inline __attribute__((always_inline
)) bool
83 capturable_group(struct board
*b
, enum stone capturer
, coord_t c
,
86 group_t g
= group_at(b
, c
);
87 if (likely(board_at(b
, c
) != stone_other(capturer
)
88 || board_group_info(b
, g
).libs
> 1))
91 return can_capture(b
, g
, to_play
);
95 can_countercapture(struct board
*b
, enum stone owner
, group_t g
,
96 enum stone to_play
, struct move_queue
*q
, int tag
)
101 unsigned int qmoves_prev
= q
? q
->moves
: 0;
103 foreach_in_group(b
, g
) {
104 foreach_neighbor(b
, c
, {
105 if (!capturable_group(b
, owner
, c
, to_play
))
111 mq_add(q
, board_group_info(b
, group_at(b
, c
)).lib
[0], tag
);
114 } foreach_in_group_end
;
116 bool can
= q
? q
->moves
> qmoves_prev
: false;
120 static inline __attribute__((always_inline
)) bool
121 capturable_group_fast(struct board
*b
, enum stone capturer
, coord_t c
,
124 group_t g
= group_at(b
, c
);
125 if (likely(board_at(b
, c
) != stone_other(capturer
)
126 || board_group_info(b
, g
).libs
> 1))
129 coord_t lib
= board_group_info(b
, g
).lib
[0];
130 return board_is_valid_play(b
, to_play
, lib
);
134 can_countercapture_any(struct board
*b
, enum stone owner
, group_t g
,
135 enum stone to_play
, struct move_queue
*q
, int tag
)
140 unsigned int qmoves_prev
= q
? q
->moves
: 0;
142 foreach_in_group(b
, g
) {
143 foreach_neighbor(b
, c
, {
144 if (!capturable_group_fast(b
, owner
, c
, to_play
))
150 mq_add(q
, board_group_info(b
, group_at(b
, c
)).lib
[0], tag
);
153 } foreach_in_group_end
;
155 bool can
= q
? q
->moves
> qmoves_prev
: false;
161 can_countercapture_(struct board
*b
, enum stone owner
, group_t g
,
162 enum stone to_play
, struct move_queue
*q
, int tag
)
165 board_at(b
, g
) != owner
||
167 board_print(b
, stderr
);
168 fprintf(stderr
, "can_countercap(%s %s %s): \n",
169 stone2str(owner
), coord2sstr(g
, b
), stone2str(to_play
));
173 assert(board_at(b
, g
) == owner
);
174 assert(owner
== to_play
);
177 bool r1
= my_can_countercapture(b
, owner
, g
, to_play
, NULL
, 0);
178 bool r2
= orig_can_countercapture(b
, owner
, g
, to_play
, NULL
, 0);
180 fprintf(stderr
, "---------------------------------------------------------------\n");
181 board_print(b
, stderr
);
182 fprintf(stderr
, "can_countercap(%s %s %s) diff ! my:%i org:%i\n",
183 stone2str(owner
), coord2sstr(g
, b
), stone2str(to_play
), r1
, r2
);
186 return orig_can_countercapture(b
, owner
, g
, to_play
, q
, tag
);
190 #ifdef NO_DOOMED_GROUPS
192 can_be_rescued(struct board
*b
, group_t group
, enum stone color
, int tag
)
194 /* Does playing on the liberty rescue the group? */
195 if (can_play_on_lib(b
, group
, color
))
198 /* Then, maybe we can capture one of our neighbors? */
199 return can_countercapture(b
, color
, group
, color
, NULL
, tag
);
204 group_atari_check(unsigned int alwaysccaprate
, struct board
*b
, group_t group
, enum stone to_play
,
205 struct move_queue
*q
, coord_t
*ladder
, bool middle_ladder
, int tag
)
207 enum stone color
= board_at(b
, group_base(group
));
208 coord_t lib
= board_group_info(b
, group
).lib
[0];
210 assert(color
!= S_OFFBOARD
&& color
!= S_NONE
);
212 fprintf(stderr
, "[%s] atariiiiiiiii %s of color %d\n",
213 coord2sstr(group
, b
), coord2sstr(lib
, b
), color
);
214 assert(board_at(b
, lib
) == S_NONE
);
216 if (to_play
!= color
) {
217 /* We are the attacker! In that case, do not try defending
218 * our group, since we can capture the culprit. */
219 #ifdef NO_DOOMED_GROUPS
220 /* Do not remove group that cannot be saved by the opponent. */
221 if (!can_be_rescued(b
, group
, color
, tag
))
224 if (can_play_on_lib(b
, group
, to_play
)) {
231 /* Can we capture some neighbor? */
232 /* XXX Attempts at using new can_countercapture() here failed so far.
233 * Could be because of a bug / under the stones situations
234 * (maybe not so uncommon in moggy ?) / it upsets moggy's balance somehow
235 * (there's always a chance opponent doesn't capture after taking snapback) */
236 bool ccap
= can_countercapture_any(b
, color
, group
, to_play
, q
, tag
);
237 if (ccap
&& !ladder
&& alwaysccaprate
> fast_random(100))
240 /* Otherwise, do not save kos. */
241 if (group_is_onestone(b
, group
)
242 && neighbor_count_at(b
, lib
, color
) + neighbor_count_at(b
, lib
, S_OFFBOARD
) == 4) {
243 /* Except when the ko is for an eye! */
244 bool eyeconnect
= false;
245 foreach_diag_neighbor(b
, lib
) {
246 if (board_at(b
, c
) == S_NONE
&& neighbor_count_at(b
, c
, color
) + neighbor_count_at(b
, c
, S_OFFBOARD
) == 4) {
250 } foreach_diag_neighbor_end
;
255 /* Do not suicide... */
256 if (!can_play_on_lib(b
, group
, to_play
))
259 fprintf(stderr
, "...escape route valid\n");
261 /* ...or play out ladders (unless we can counter-capture anytime). */
263 if (is_ladder(b
, lib
, group
, middle_ladder
)) {
264 /* Sometimes we want to keep the ladder move in the
265 * queue in order to discourage it. */
270 } else if (DEBUGL(6))
271 fprintf(stderr
, "...no ladder\n");