5 #define QUICK_BOARD_CODE
12 #include "tactics/1lib.h"
13 #include "tactics/selfatari.h"
17 struct selfatari_state
{
19 group_t groupids
[S_MAX
][4];
20 coord_t groupneis
[S_MAX
][4];
22 /* This is set if this move puts a group out of _all_
23 * liberties; we need to watch out for snapback then. */
24 bool friend_has_no_libs
;
25 /* We may have one liberty, but be looking for one more.
26 * In that case, @needs_more_lib is id of group
27 * already providing one, don't consider it again. */
28 group_t needs_more_lib
;
29 /* ID of the first liberty, providing it again is not
31 coord_t needs_more_lib_except
;
35 three_liberty_suicide(struct board
*b
, group_t g
, enum stone color
, coord_t to
, struct selfatari_state
*s
)
37 /* If a group has three liberties, by playing on one of
38 * them it is possible to kill the group clumsily. Check
39 * against that condition: "After our move, the opponent
40 * can unconditionally capture the group."
44 * O O O O O O O X X O O O O O O v-v- ladder
45 * O X X X X X O . O X X X X X O . . . O O
46 * O X ! . ! X O . O X ! . ! O . O X X . O
47 * O X X X X X O # # # # # # # # O O O O O */
49 /* Extract the other two liberties. */
50 coord_t other_libs
[2];
51 bool other_libs_adj
[2];
52 for (int i
= 0, j
= 0; i
< 3; i
++) {
53 coord_t lib
= board_group_info(b
, g
).lib
[i
];
55 other_libs_adj
[j
] = coord_is_adjecent(lib
, to
, b
);
56 other_libs
[j
++] = lib
;
60 /* Make sure this move is not useful by gaining liberties,
61 * splitting the other two liberties (quite possibly splitting
62 * 3-eyespace!) or connecting to a different group. */
63 if (immediate_liberty_count(b
, to
) - (other_libs_adj
[0] || other_libs_adj
[1]) > 0)
65 assert(!(other_libs_adj
[0] && other_libs_adj
[1]));
66 if (s
->groupcts
[color
] > 1)
69 /* Playing on the third liberty might be useful if it enables
70 * capturing some group (are we doing nakade or semeai?). */
71 for (int i
= 0; i
< s
->groupcts
[stone_other(color
)]; i
++)
72 if (board_group_info(b
, s
->groupids
[stone_other(color
)][i
]).libs
<= 3)
76 /* Okay. This looks like a pretty dangerous situation. The
77 * move looks useless, it definitely converts us to a 2-lib
78 * group. But we still want to play it e.g. if it takes off
79 * liberties of some unconspicous enemy group, and of course
80 * also at the game end to leave just single-point eyes. */
83 fprintf(stderr
, "3-lib danger\n");
85 /* Therefore, the final suicidal test is: (After filling this
86 * liberty,) when opponent fills liberty [0], playing liberty
87 * [1] will not help the group, or vice versa. */
88 bool other_libs_neighbors
= coord_is_adjecent(other_libs
[0], other_libs
[1], b
);
89 for (int i
= 0; i
< 2; i
++) {
90 int null_libs
= other_libs_neighbors
+ other_libs_adj
[i
];
91 if (board_is_one_point_eye(b
, other_libs
[1 - i
], color
)) {
92 /* The other liberty is an eye, happily go ahead.
93 * There are of course situations where this will
94 * take off semeai liberties, but without this check,
95 * many terminal endgame plays will be messed up. */
98 if (immediate_liberty_count(b
, other_libs
[i
]) - null_libs
> 1) {
99 /* Gains liberties. */
100 /* TODO: Check for ladder! */
104 foreach_neighbor(b
, other_libs
[i
], {
105 if (board_at(b
, c
) == color
106 && group_at(b
, c
) != g
107 && board_group_info(b
, group_at(b
, c
)).libs
> 1) {
108 /* Can connect to a friend. */
109 /* TODO: > 2? But maybe the group can capture
110 * a neighbor! But then better let it do that
115 /* If we can capture a neighbor, better do it now
116 * before wasting a liberty. So no need to check. */
117 /* Ok, the last liberty has no way to get out. */
119 fprintf(stderr
, "3-lib dangerous: %s\n", coord2sstr(other_libs
[i
], b
));
127 examine_friendly_groups(struct board
*b
, enum stone color
, coord_t to
, struct selfatari_state
*s
)
129 for (int i
= 0; i
< s
->groupcts
[color
]; i
++) {
130 /* We can escape by connecting to this group if it's
132 group_t g
= s
->groupids
[color
][i
];
134 if (board_group_info(b
, g
).libs
== 1) {
135 if (!s
->needs_more_lib
)
136 s
->friend_has_no_libs
= true;
137 // or we already have a friend with 1 lib
141 /* Could we self-atari the group here? */
142 if (board_group_info(b
, g
).libs
> 2) {
143 if (board_group_info(b
, g
).libs
== 3
144 && three_liberty_suicide(b
, g
, color
, to
, s
))
149 /* We need to have another liberty, and
150 * it must not be the other liberty of
152 int lib2
= board_group_other_lib(b
, g
, to
);
153 /* Maybe we already looked at another
154 * group providing one liberty? */
155 if (s
->needs_more_lib
&& s
->needs_more_lib
!= g
156 && s
->needs_more_lib_except
!= lib2
)
159 /* Can we get the liberty locally? */
160 /* Yes if we are route to more liberties... */
161 if (s
->groupcts
[S_NONE
] > 1)
163 /* ...or one liberty, but not lib2. */
164 if (s
->groupcts
[S_NONE
] > 0
165 && !coord_is_adjecent(lib2
, to
, b
))
168 /* ...ok, then we can still contribute a liberty
169 * later by capturing something. */
170 s
->needs_more_lib
= g
;
171 s
->needs_more_lib_except
= lib2
;
172 s
->friend_has_no_libs
= false;
179 examine_enemy_groups(struct board
*b
, enum stone color
, coord_t to
, struct selfatari_state
*s
)
181 /* We may be able to gain a liberty by capturing this group. */
182 group_t can_capture
= 0;
184 /* Examine enemy groups: */
185 for (int i
= 0; i
< s
->groupcts
[stone_other(color
)]; i
++) {
186 /* We can escape by capturing this group if it's in atari. */
187 group_t g
= s
->groupids
[stone_other(color
)][i
];
188 if (board_group_info(b
, g
).libs
> 1)
191 /* But we need to get to at least two liberties by this;
192 * we already have one outside liberty, or the group is
193 * more than 1 stone (in that case, capturing is always
195 if (s
->groupcts
[S_NONE
] > 0 || !group_is_onestone(b
, g
))
197 /* ...or, it's a ko stone, */
198 if (neighbor_count_at(b
, g
, color
) + neighbor_count_at(b
, g
, S_OFFBOARD
) == 3) {
199 /* and we don't have a group to save: then, just taking
200 * single stone means snapback! */
201 if (!s
->friend_has_no_libs
)
204 /* ...or, we already have one indirect liberty provided
205 * by another group. */
206 if (s
->needs_more_lib
|| (can_capture
&& can_capture
!= g
))
213 fprintf(stderr
, "no cap group\n");
215 if (!s
->needs_more_lib
&& !can_capture
&& !s
->groupcts
[S_NONE
]) {
216 /* We have no hope for more fancy tactics - this move is simply
217 * a suicide, not even a self-atari. */
219 fprintf(stderr
, "suicide\n");
222 /* XXX: I wonder if it makes sense to continue if we actually
223 * just !s->needs_more_lib. */
229 is_neighbor_group(struct board
*b
, enum stone color
, group_t g
, struct selfatari_state
*s
)
231 for (int i
= 0; i
< s
->groupcts
[color
]; i
++)
232 if (g
== s
->groupids
[color
][i
])
238 /* Instead of playing this self-atari, could we have connected/escaped by
239 * playing on the other liberty of a neighboring group ?
240 * Or there's a strong enemy group there (only checked if @check_enemy is set)
243 is_bad_nakade(struct board
*b
, enum stone color
, coord_t to
, coord_t lib2
,
244 bool check_enemy
, struct selfatari_state
*s
)
246 /* Let's look at neighbors of the other liberty: */
247 foreach_neighbor(b
, lib2
, {
248 /* If the other liberty has empty neighbor,
249 * it must be the original liberty; otherwise,
250 * since the whole group has only 2 liberties,
251 * the other liberty may not be internal and
252 * we are nakade'ing eyeless group from outside,
253 * which is stupid. */
254 if (board_at(b
, c
) == S_NONE
) {
262 /* Let's look at neighbors of the other liberty: */
263 foreach_neighbor(b
, lib2
, {
264 if (board_at(b
, c
) != color
)
267 group_t g2
= group_at(b
, c
);
268 /* Looking for a group we don't know about */
269 if (is_neighbor_group(b
, color
, g2
, s
))
272 /* Should connect these groups instead of self-atari
273 * on the other side. */
274 if (board_at(b
, c
) == color
)
278 /* FIXME Do we really need this ? */
282 /* The neighbor is enemy color. It's ok if this is its
283 * only liberty or it's one of our neighbor groups. */
284 if (board_group_info(b
, g2
).libs
== 1)
286 if (board_group_info(b
, g2
).libs
== 2
287 && (board_group_info(b
, g2
).lib
[0] == to
288 || board_group_info(b
, g2
).lib
[1] == to
))
291 /* Stronger enemy group. No nakade. */
297 /* Instead of playing this self-atari, could we have connected/escaped by
298 * playing on the other liberty of a neighboring group ? */
300 can_escape_instead(struct board
*b
, enum stone color
, coord_t to
, struct selfatari_state
*s
)
302 for (int i
= 0; i
< s
->groupcts
[color
]; i
++) {
303 group_t g
= s
->groupids
[color
][i
];
304 if (board_group_info(b
, g
).libs
!= 2)
306 coord_t other
= board_group_other_lib(b
, g
, to
);
308 /* Let's look at the other liberty of that group. */
309 if (immediate_liberty_count(b
, other
) >= 2 || /* Can escape ! */
310 is_bad_nakade(b
, color
, to
, other
, false, s
)) /* Should connect instead */
317 unreachable_lib_from_neighbors(struct board
*b
, enum stone color
, coord_t to
, struct selfatari_state
*s
,
320 for (int i
= 0; i
< s
->groupcts
[color
]; i
++) {
321 group_t g
= s
->groupids
[color
][i
];
322 for (int j
= 0; j
< board_group_info(b
, g
).libs
; j
++)
323 if (board_group_info(b
, g
).lib
[j
] == lib
)
329 /* This only looks at existing empty spots, not captures */
331 capture_would_make_extra_eye(struct board
*b
, enum stone color
, coord_t to
, struct selfatari_state
*s
)
333 foreach_neighbor(b
, to
, {
334 if (board_at(b
, c
) == S_NONE
)
335 if (unreachable_lib_from_neighbors(b
, color
, to
, s
, c
))
342 nakade_making_dead_shape(struct board
*b
, enum stone color
, coord_t to
, struct selfatari_state
*s
,
343 bool atariing_group
, int stones
)
345 int cap_would_make_eye
= false;
352 /* If not atariing surrounding group it's a good move if:
353 * - Shape after capturing us is dead AND
354 * - Oponent gets extra eye if he plays first OR
355 * - would create living shape
357 * If atariing surrounding group we only care about dead shape. */
360 cap_would_make_eye
= capture_would_make_extra_eye(b
, color
, to
, s
);
361 /* TODO: If there's so much eye space that even with filling + capture
362 * opponent still makes an extra eye it's a silly move. */
364 /* Can oponent make living shape if we don't play ?
365 * (don't bother killing stuff that's already dead...) */
366 if (!atariing_group
&& !cap_would_make_eye
&& s
->groupcts
[color
] == 1)
368 int would_live
= false;
369 int prev_neighbor
= neighbor_count_at(b
, to
, color
);
371 /* Play opponent color where we want to play */
372 with_move(b
, to
, stone_other(color
), {
374 /* Had 2 libs ? One more move to capture then */
375 if (prev_neighbor
== neighbor_count_at(b
, to
, color
)) {
376 group_t standing
= -1;
377 foreach_neighbor(b
, to
, {
378 group_t g
= group_at(b
, c
);
379 if (board_at(b
, c
) == color
) {
380 assert(board_group_info(b
, g
).libs
== 1); /* Should be in atari */
384 assert(standing
!= -1);
386 with_move_strict(b
, board_group_info(b
, standing
).lib
[0], stone_other(color
), {
387 /* Empty now since it's been captured */
388 coord_t empty
= group_base(s
->groupids
[color
][0]);
389 would_live
= !nakade_dead_shape(b
, empty
, stone_other(color
));
392 else { /* Empty now since it's been captured */
393 coord_t empty
= group_base(s
->groupids
[color
][0]);
394 would_live
= !nakade_dead_shape(b
, empty
, stone_other(color
));
398 if (!would_live
) /* And !cap_would_make_eye here */
399 return false; /* Bad nakade */
403 /* Play self-atari */
404 with_move_strict(b
, to
, color
, {
406 group_t g
= group_at(b
, to
);
407 with_move_strict(b
, board_group_info(b
, g
).lib
[0], stone_other(color
), {
408 dead_shape
= nakade_dead_shape(b
, to
, stone_other(color
));
415 /* More complex throw-in, or in-progress capture from
416 * the inside - we are in one of several situations:
417 * a O O O O X b O O O X c O O O X d O O O O O
418 * O . X . O O X . . O . X . O . X . O
419 * # # # # # # # # # # # # # # # # # #
420 * Throw-ins have been taken care of in check_throwin(),
421 * so it's either b or d now:
422 * - b is desirable here (since maybe O has no backup two eyes)
423 * - d is desirable if putting group in atari (otherwise we
424 * would never capture a single-eyed group). */
425 #define check_throw_in_or_inside_capture(b, color, to, s, capturing) \
426 if (s->groupcts[color] == 1 && group_is_onestone(b, s->groupids[color][0])) { \
427 group_t g2 = s->groupids[color][0]; \
428 assert(board_group_info(b, g2).libs <= 2); \
429 if (board_group_info(b, g2).libs == 1) \
430 return false; /* b */ \
436 setup_nakade_or_snapback(struct board
*b
, enum stone color
, coord_t to
, struct selfatari_state
*s
)
438 /* There is another possibility - we can self-atari if it is
439 * a nakade: we put an enemy group in atari from the inside. */
440 /* This branch also allows eyes falsification:
441 * O O O . . (This is different from throw-in to false eye
442 * X X O O . checked below in that there is no X stone at the
443 * X . X O . right of the star point in this diagram.)
446 /* We also allow to only nakade if the created shape is dead
447 * (http://senseis.xmp.net/?Nakade). */
449 /* This branch also covers snapback, which is kind of special
450 * nakade case. ;-) */
451 /* FIXME looks like check_throwin() does it actually. */
453 /* Look at the enemy groups and determine the other contended
454 * liberty. We must make sure the liberty:
455 * (i) is an internal liberty
456 * (ii) filling it to capture our group will not gain safety */
458 for (int i
= 0; i
< s
->groupcts
[stone_other(color
)]; i
++) {
459 group_t g
= s
->groupids
[stone_other(color
)][i
];
460 if (board_group_info(b
, g
).libs
!= 2)
463 coord_t this_lib2
= board_group_other_lib(b
, g
, to
);
466 else if (this_lib2
!= lib2
) {
467 /* If we have two neighboring groups that do
468 * not share the other liberty, this for sure
469 * is not a good nakade. */
474 /* Not putting any group in atari.
475 * Could be creating dead shape though */
477 /* Before checking if it's a useful nakade
478 * make sure it can't connect out ! */
479 if (can_escape_instead(b
, color
, to
, s
))
482 check_throw_in_or_inside_capture(b
, color
, to
, s
, false);
485 for (int j
= 0; j
< s
->groupcts
[color
]; j
++) {
486 group_t g2
= s
->groupids
[color
][j
];
487 stones
+= group_stone_count(b
, g2
, 6);
492 return (nakade_making_dead_shape(b
, color
, to
, s
, false, stones
) ? false : -1);
495 /* Let's look at neighbors of the other liberty: */
496 if (is_bad_nakade(b
, color
, to
, lib2
, true, s
) ||
497 can_escape_instead(b
, color
, to
, s
))
500 /* Now, we must distinguish between nakade and eye
501 * falsification; moreover, we must not falsify an eye
502 * by more than two stones. */
504 if (s
->groupcts
[color
] < 1)
505 return false; /* Simple throw-in, an easy case */
507 check_throw_in_or_inside_capture(b
, color
, to
, s
, true);
509 /* We would create more than 2-stone group; in that
510 * case, the liberty of our result must be lib2,
511 * indicating this really is a nakade. */
513 for (int j
= 0; j
< s
->groupcts
[color
]; j
++) {
514 group_t g2
= s
->groupids
[color
][j
];
515 assert(board_group_info(b
, g2
).libs
<= 2);
516 if (board_group_info(b
, g2
).libs
== 2) {
517 if (board_group_info(b
, g2
).lib
[0] != lib2
518 && board_group_info(b
, g2
).lib
[1] != lib2
)
521 assert(board_group_info(b
, g2
).lib
[0] == to
);
523 stones
+= group_stone_count(b
, g2
, 6);
528 return !nakade_making_dead_shape(b
, color
, to
, s
, true, stones
);
532 /* Fast but there are issues with this (triangle six is not dead !)
533 * We also need to know status if opponent plays first */
535 nakade_making_dead_shape_hack(struct board
*b
, enum stone color
, coord_t to
, int lib2
,
536 struct selfatari_state
*s
, int stones
)
538 /* It also remains to be seen whether it is nakade
539 * and not seki destruction. To do this properly, we
540 * would have to look at the group shape. But we can
541 * cheat too! Brett Combs helps to introduce a static
542 * rule that should in fact cover *all* cases:
543 * 1. Total number of pre-selfatari nakade stones must
544 * be 5 or smaller. (See above for that.)
545 * 2. If the selfatari is 8-touching all nakade stones,
546 * it is proper nakade.
547 * 3. Otherwise, there must be only a single nakade
548 * group, it must be at least 4-stone and its other
549 * liberty must be 8-touching the same number of
551 int touch8
= neighbor_count_at(b
, to
, color
);
552 foreach_diag_neighbor(b
, to
) {
553 if (board_at(b
, c
) != color
) continue;
554 /* Consider only internal stones. Otherwise, e.g.
556 * X . O X can make trouble, bottom O is
557 * O X X X irrelevant. */
558 if (board_group_info(b
, group_at(b
, c
)).lib
[0] == to
559 || board_group_info(b
, group_at(b
, c
)).lib
[1] == to
)
561 } foreach_diag_neighbor_end
;
562 if (touch8
== stones
)
565 if (s
->groupcts
[color
] > 1)
567 if (stones
== 3) // 4 stones and self-atari not 8-connected to all of them -> living shape
569 if (stones
< 3) // always dead shape
572 int ltouch8
= neighbor_count_at(b
, lib2
, color
);
573 foreach_diag_neighbor(b
, lib2
) {
574 if (board_at(b
, c
) != color
) continue;
575 if (board_group_info(b
, group_at(b
, c
)).lib
[0] == to
576 || board_group_info(b
, group_at(b
, c
)).lib
[1] == to
)
578 } foreach_diag_neighbor_end
;
579 return ltouch8
== touch8
;
585 check_throwin(struct board
*b
, enum stone color
, coord_t to
, struct selfatari_state
*s
)
587 /* We can be throwing-in to false eye:
588 * X X X O X X X O X X X X X
589 * X . * X * O . X * O O . X
590 * # # # # # # # # # # # # # */
591 /* We cannot sensibly throw-in into a corner. */
592 if (neighbor_count_at(b
, to
, S_OFFBOARD
) < 2
593 && neighbor_count_at(b
, to
, stone_other(color
))
594 + neighbor_count_at(b
, to
, S_OFFBOARD
) == 3
595 && board_is_false_eyelike(b
, to
, stone_other(color
))) {
596 assert(s
->groupcts
[color
] <= 1);
597 /* Single-stone throw-in may be ok... */
598 if (s
->groupcts
[color
] == 0) {
599 /* O X . There is one problem - when it's
600 * . * X actually not a throw-in!
602 foreach_neighbor(b
, to
, {
603 if (board_at(b
, c
) == S_NONE
) {
604 /* Is the empty neighbor an escape path? */
605 /* (Note that one S_NONE neighbor is already @to.) */
606 if (neighbor_count_at(b
, c
, stone_other(color
))
607 + neighbor_count_at(b
, c
, S_OFFBOARD
) < 2)
614 /* Multi-stone throwin...? */
615 assert(s
->groupcts
[color
] == 1);
616 group_t g
= s
->groupids
[color
][0];
618 assert(board_group_info(b
, g
).libs
<= 2);
619 /* Suicide is definitely NOT ok, no matter what else
621 if (board_group_info(b
, g
).libs
== 1)
624 /* In that case, we must be connected to at most one stone,
625 * or throwin will not destroy any eyes. */
626 if (group_is_onestone(b
, g
))
633 is_bad_selfatari_slow(struct board
*b
, enum stone color
, coord_t to
)
636 fprintf(stderr
, "sar check %s %s\n", stone2str(color
), coord2sstr(to
, b
));
637 /* Assess if we actually gain any liberties by this escape route.
638 * Note that this is not 100% as we cannot check whether we are
639 * connecting out or just to ourselves. */
641 struct selfatari_state s
;
642 memset(&s
, 0, sizeof(s
));
645 foreach_neighbor(b
, to
, {
646 enum stone color
= board_at(b
, c
);
647 group_t group
= group_at(b
, c
);
649 for (int i
= 0; i
< s
.groupcts
[color
]; i
++)
650 if (s
.groupids
[color
][i
] == group
) {
655 s
.groupneis
[color
][s
.groupcts
[color
]] = c
;
656 s
.groupids
[color
][s
.groupcts
[color
]++] = group_at(b
, c
);
660 /* We have shortage of liberties; that's the point. */
661 assert(s
.groupcts
[S_NONE
] <= 1);
663 d
= examine_friendly_groups(b
, color
, to
, &s
);
667 fprintf(stderr
, "no friendly group\n");
669 d
= examine_enemy_groups(b
, color
, to
, &s
);
673 fprintf(stderr
, "no capture\n");
675 d
= check_throwin(b
, color
, to
, &s
);
680 fprintf(stderr
, "no throw-in group\n");
682 d
= setup_nakade_or_snapback(b
, color
, to
, &s
);
686 fprintf(stderr
, "no nakade group\n");
689 /* No way to pull out, no way to connect out. This really
690 * is a bad self-atari! */
696 selfatari_cousin(struct board
*b
, enum stone color
, coord_t coord
, group_t
*bygroup
)
698 group_t groups
[4]; int groups_n
= 0;
699 int groupsbycolor
[4] = {0, 0, 0, 0};
701 fprintf(stderr
, "cousin group search: ");
702 foreach_neighbor(b
, coord
, {
703 enum stone s
= board_at(b
, c
);
704 group_t g
= group_at(b
, c
);
705 if (board_group_info(b
, g
).libs
== 2) {
706 groups
[groups_n
++] = g
;
709 fprintf(stderr
, "%s(%s) ", coord2sstr(c
, b
), stone2str(s
));
713 fprintf(stderr
, "\n");
719 if (groupsbycolor
[stone_other(color
)]) {
720 /* Prefer to fill the other liberty of an opponent
721 * group to filling own approach liberties. */
722 int gl
= fast_random(groups_n
);
723 for (gn
= gl
; gn
< groups_n
; gn
++)
724 if (board_at(b
, groups
[gn
]) == stone_other(color
))
726 for (gn
= 0; gn
< gl
; gn
++)
727 if (board_at(b
, groups
[gn
]) == stone_other(color
))
731 gn
= fast_random(groups_n
);
734 for (; gn
- gl
< groups_n
; gn
++) {
735 int gnm
= gn
% groups_n
;
736 group_t group
= groups
[gnm
];
739 /* Can we get liberties by capturing a neighbor? */
740 struct move_queue ccq
; ccq
.moves
= 0;
741 if (board_at(b
, group
) == color
&&
742 can_countercapture(b
, group
, &ccq
, 0)) {
743 lib2
= mq_pick(&ccq
);
746 lib2
= board_group_other_lib(b
, group
, coord
);
747 if (board_is_one_point_eye(b
, lib2
, board_at(b
, group
)))
749 if (is_bad_selfatari(b
, color
, lib2
))