selfatari_cousin(): Suggest counter-captures
[pachi.git] / tactics / selfatari.c
blobf75fd10eab7e0a887a72ac1153e3009f2b2f3b49
1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdlib.h>
5 #define DEBUG
6 #include "board.h"
7 #include "debug.h"
8 #include "mq.h"
9 #include "random.h"
10 #include "tactics/1lib.h"
11 #include "tactics/selfatari.h"
14 struct selfatari_state {
15 int groupcts[S_MAX];
16 group_t groupids[S_MAX][4];
17 coord_t groupneis[S_MAX][4];
19 /* This is set if this move puts a group out of _all_
20 * liberties; we need to watch out for snapback then. */
21 bool friend_has_no_libs;
22 /* We may have one liberty, but be looking for one more.
23 * In that case, @needs_more_lib is id of group
24 * already providing one, don't consider it again. */
25 group_t needs_more_lib;
26 /* ID of the first liberty, providing it again is not
27 * interesting. */
28 coord_t needs_more_lib_except;
31 static bool
32 three_liberty_suicide(struct board *b, group_t g, enum stone color, coord_t to, struct selfatari_state *s)
34 /* If a group has three liberties, by playing on one of
35 * them it is possible to kill the group clumsily. Check
36 * against that condition: "After our move, the opponent
37 * can unconditionally capture the group."
39 * Examples:
41 * O O O O O O O X X O O O O O O v-v- ladder
42 * O X X X X X O . O X X X X X O . . . O O
43 * O X ! . ! X O . O X ! . ! O . O X X . O
44 * O X X X X X O # # # # # # # # O O O O O */
46 /* Extract the other two liberties. */
47 coord_t other_libs[2];
48 bool other_libs_adj[2];
49 for (int i = 0, j = 0; i < 3; i++) {
50 coord_t lib = board_group_info(b, g).lib[i];
51 if (lib != to) {
52 other_libs_adj[j] = coord_is_adjecent(lib, to, b);
53 other_libs[j++] = lib;
57 /* Make sure this move is not useful by gaining liberties,
58 * splitting the other two liberties (quite possibly splitting
59 * 3-eyespace!) or connecting to a different group. */
60 if (immediate_liberty_count(b, to) - (other_libs_adj[0] || other_libs_adj[1]) > 0)
61 return false;
62 assert(!(other_libs_adj[0] && other_libs_adj[1]));
63 if (s->groupcts[color] > 1)
64 return false;
66 /* Playing on the third liberty might be useful if it enables
67 * capturing some group (are we doing nakade or semeai?). */
68 for (int i = 0; i < s->groupcts[stone_other(color)]; i++)
69 if (board_group_info(b, s->groupids[stone_other(color)][i]).libs <= 3)
70 return false;
73 /* Okay. This looks like a pretty dangerous situation. The
74 * move looks useless, it definitely converts us to a 2-lib
75 * group. But we still want to play it e.g. if it takes off
76 * liberties of some unconspicous enemy group, and of course
77 * also at the game end to leave just single-point eyes. */
79 if (DEBUGL(6))
80 fprintf(stderr, "3-lib danger\n");
82 /* Therefore, the final suicidal test is: (After filling this
83 * liberty,) when opponent fills liberty [0], playing liberty
84 * [1] will not help the group, or vice versa. */
85 bool other_libs_neighbors = coord_is_adjecent(other_libs[0], other_libs[1], b);
86 for (int i = 0; i < 2; i++) {
87 int null_libs = other_libs_neighbors + other_libs_adj[i];
88 if (board_is_one_point_eye(b, other_libs[1 - i], color)) {
89 /* The other liberty is an eye, happily go ahead.
90 * There are of course situations where this will
91 * take off semeai liberties, but without this check,
92 * many terminal endgame plays will be messed up. */
93 return false;
95 if (immediate_liberty_count(b, other_libs[i]) - null_libs > 1) {
96 /* Gains liberties. */
97 /* TODO: Check for ladder! */
98 next_lib:
99 continue;
101 foreach_neighbor(b, other_libs[i], {
102 if (board_at(b, c) == color
103 && group_at(b, c) != g
104 && board_group_info(b, group_at(b, c)).libs > 1) {
105 /* Can connect to a friend. */
106 /* TODO: > 2? But maybe the group can capture
107 * a neighbor! But then better let it do that
108 * first? */
109 goto next_lib;
112 /* If we can capture a neighbor, better do it now
113 * before wasting a liberty. So no need to check. */
114 /* Ok, the last liberty has no way to get out. */
115 if (DEBUGL(6))
116 fprintf(stderr, "3-lib dangerous: %s\n", coord2sstr(other_libs[i], b));
117 return true;
120 return false;
123 static int
124 examine_friendly_groups(struct board *b, enum stone color, coord_t to, struct selfatari_state *s)
126 for (int i = 0; i < s->groupcts[color]; i++) {
127 /* We can escape by connecting to this group if it's
128 * not in atari. */
129 group_t g = s->groupids[color][i];
131 if (board_group_info(b, g).libs == 1) {
132 if (!s->needs_more_lib)
133 s->friend_has_no_libs = true;
134 // or we already have a friend with 1 lib
135 continue;
138 /* Could we self-atari the group here? */
139 if (board_group_info(b, g).libs > 2) {
140 if (board_group_info(b, g).libs == 3
141 && three_liberty_suicide(b, g, color, to, s))
142 return true;
143 return false;
146 /* We need to have another liberty, and
147 * it must not be the other liberty of
148 * the group. */
149 int lib2 = board_group_other_lib(b, g, to);
150 /* Maybe we already looked at another
151 * group providing one liberty? */
152 if (s->needs_more_lib && s->needs_more_lib != g
153 && s->needs_more_lib_except != lib2)
154 return false;
156 /* Can we get the liberty locally? */
157 /* Yes if we are route to more liberties... */
158 if (s->groupcts[S_NONE] > 1)
159 return false;
160 /* ...or one liberty, but not lib2. */
161 if (s->groupcts[S_NONE] > 0
162 && !coord_is_adjecent(lib2, to, b))
163 return false;
165 /* ...ok, then we can still contribute a liberty
166 * later by capturing something. */
167 s->needs_more_lib = g;
168 s->needs_more_lib_except = lib2;
169 s->friend_has_no_libs = false;
172 return -1;
175 static int
176 examine_enemy_groups(struct board *b, enum stone color, coord_t to, struct selfatari_state *s)
178 /* We may be able to gain a liberty by capturing this group. */
179 group_t can_capture = 0;
181 /* Examine enemy groups: */
182 for (int i = 0; i < s->groupcts[stone_other(color)]; i++) {
183 /* We can escape by capturing this group if it's in atari. */
184 group_t g = s->groupids[stone_other(color)][i];
185 if (board_group_info(b, g).libs > 1)
186 continue;
188 /* But we need to get to at least two liberties by this;
189 * we already have one outside liberty, or the group is
190 * more than 1 stone (in that case, capturing is always
191 * nice!). */
192 if (s->groupcts[S_NONE] > 0 || !group_is_onestone(b, g))
193 return false;
194 /* ...or, it's a ko stone, */
195 if (neighbor_count_at(b, g, color) + neighbor_count_at(b, g, S_OFFBOARD) == 3) {
196 /* and we don't have a group to save: then, just taking
197 * single stone means snapback! */
198 if (!s->friend_has_no_libs)
199 return false;
201 /* ...or, we already have one indirect liberty provided
202 * by another group. */
203 if (s->needs_more_lib || (can_capture && can_capture != g))
204 return false;
205 can_capture = g;
209 if (DEBUGL(6))
210 fprintf(stderr, "no cap group\n");
212 if (!s->needs_more_lib && !can_capture && !s->groupcts[S_NONE]) {
213 /* We have no hope for more fancy tactics - this move is simply
214 * a suicide, not even a self-atari. */
215 if (DEBUGL(6))
216 fprintf(stderr, "suicide\n");
217 return true;
219 /* XXX: I wonder if it makes sense to continue if we actually
220 * just !s->needs_more_lib. */
222 return -1;
225 static int
226 setup_nakade_or_snapback(struct board *b, enum stone color, coord_t to, struct selfatari_state *s)
228 /* There is another possibility - we can self-atari if it is
229 * a nakade: we put an enemy group in atari from the inside. */
230 /* This branch also allows eyes falsification:
231 * O O O . . (This is different from throw-in to false eye
232 * X X O O . checked below in that there is no X stone at the
233 * X . X O . right of the star point in this diagram.)
234 * X X X O O
235 * X O * . . */
236 /* TODO: Allow to only nakade if the created shape is dead
237 * (http://senseis.xmp.net/?Nakade). */
239 /* This branch also covers snapback, which is kind of special
240 * nakade case. ;-) */
242 /* Look at the enemy groups and determine the other contended
243 * liberty. We must make sure the liberty:
244 * (i) is an internal liberty
245 * (ii) filling it to capture our group will not gain safety */
246 coord_t lib2 = pass;
247 for (int i = 0; i < s->groupcts[stone_other(color)]; i++) {
248 group_t g = s->groupids[stone_other(color)][i];
249 if (board_group_info(b, g).libs != 2)
250 continue;
252 coord_t this_lib2 = board_group_other_lib(b, g, to);
253 if (is_pass(lib2))
254 lib2 = this_lib2;
255 else if (this_lib2 != lib2) {
256 /* If we have two neighboring groups that do
257 * not share the other liberty, this for sure
258 * is not a good nakade. */
259 return -1;
262 if (is_pass(lib2)) {
263 /* Not putting any group in atari. Therefore, this
264 * self-atari is not nakade or snapback. */
265 return -1;
268 /* Let's look at neighbors of the other liberty: */
269 foreach_neighbor(b, lib2, {
270 /* This neighbor of course does not contribute
271 * anything to the enemy. */
272 if (board_at(b, c) == S_OFFBOARD)
273 continue;
275 /* If the other liberty has empty neighbor,
276 * it must be the original liberty; otherwise,
277 * since the whole group has only 2 liberties,
278 * the other liberty may not be internal and
279 * we are nakade'ing eyeless group from outside,
280 * which is stupid. */
281 if (board_at(b, c) == S_NONE) {
282 if (c == to)
283 continue;
284 else
285 return -1;
288 int g2 = group_at(b, c);
289 /* If the neighbor is of our color, it must
290 * be also a 2-lib group. If it is more,
291 * we CERTAINLY want that liberty to be played
292 * first, what if it is an alive group? If it
293 * is in atari, we want to extend from it to
294 * prevent eye-making capture. However, if it
295 * is 2-lib, it is selfatari connecting two
296 * nakade'ing groups! */
297 /* X X X X We will not allow play on 'a',
298 * X X a X because 'b' would capture two
299 * X O b X different groups, forming two
300 * X X X X eyes. */
301 if (board_at(b, c) == color) {
302 if (board_group_info(b, group_at(b, c)).libs == 2)
303 continue;
304 return -1;
307 /* The neighbor is enemy color. It's ok if this is its
308 * only liberty or it's one of our neighbor groups. */
309 if (board_group_info(b, g2).libs == 1)
310 continue;
311 if (board_group_info(b, g2).libs == 2
312 && (board_group_info(b, g2).lib[0] == to
313 || board_group_info(b, g2).lib[1] == to))
314 continue;
316 /* Stronger enemy group. No nakade. */
317 return -1;
320 /* Now, we must distinguish between nakade and eye
321 * falsification; moreover, we must not falsify an eye
322 * by more than two stones. */
324 if (s->groupcts[color] < 1)
325 return false; // simple throw-in, an easy case
327 if (s->groupcts[color] == 1 && group_is_onestone(b, s->groupids[color][0])) {
328 /* More complex throw-in, or in-progress capture from
329 * the inside - we are in one of several situations:
330 * a O O O O X b O O O X c O O O X d O O O O O
331 * O . X . O O X . . O . X . O . X . O
332 * # # # # # # # # # # # # # # # # # #
333 * b is desirable here (since maybe O has no
334 * backup two eyes); a may be desirable, but
335 * is tested next in check_throwin(). c is
336 * never desirable. d is desirable (otherwise
337 * we would never capture a single-eyed group). */
338 group_t g2 = s->groupids[color][0];
339 assert(board_group_info(b, g2).libs <= 2);
340 if (board_group_info(b, g2).libs >= 1)
341 return false; // b or d
342 return -1; // a or c
345 /* We would create more than 2-stone group; in that
346 * case, the liberty of our result must be lib2,
347 * indicating this really is a nakade. */
348 int stones = 0;
349 for (int j = 0; j < s->groupcts[color]; j++) {
350 group_t g2 = s->groupids[color][j];
351 assert(board_group_info(b, g2).libs <= 2);
352 if (board_group_info(b, g2).libs == 2) {
353 if (board_group_info(b, g2).lib[0] != lib2
354 && board_group_info(b, g2).lib[1] != lib2)
355 return -1;
356 } else {
357 assert(board_group_info(b, g2).lib[0] == to);
359 /* See below: */
360 stones += group_stone_count(b, g2, 6);
361 // fprintf(stderr, "%d (%d,%d) %d,%d\n", __LINE__, j, g2, stones);
362 if (stones > 5)
363 return true;
366 /* It also remains to be seen whether it is nakade
367 * and not seki destruction. To do this properly, we
368 * would have to look at the group shape. But we can
369 * cheat too! Brett Combs helps to introduce a static
370 * rule that should in fact cover *all* cases:
371 * 1. Total number of pre-selfatari nakade stones must
372 * be 5 or smaller. (See above for that.)
373 * 2. If the selfatari is 8-touching all nakade stones,
374 * it is proper nakade.
375 * 3. Otherwise, there must be only a single nakade
376 * group, it must be at least 4-stone and its other
377 * liberty must be 8-touching the same number of
378 * stones as us. */
379 int touch8 = neighbor_count_at(b, to, color);
380 foreach_diag_neighbor(b, to) {
381 if (board_at(b, c) != color) continue;
382 /* Consider only internal stones. Otherwise, e.g.
383 * X O . X
384 * X . O X can make trouble, bottom O is
385 * O X X X irrelevant. */
386 if (board_group_info(b, group_at(b, c)).lib[0] == to
387 || board_group_info(b, group_at(b, c)).lib[1] == to)
388 touch8++;
389 } foreach_diag_neighbor_end;
390 if (touch8 == stones)
391 return false;
393 if (s->groupcts[color] > 1 || stones < 4)
394 return true;
395 int ltouch8 = neighbor_count_at(b, lib2, color);
396 foreach_diag_neighbor(b, lib2) {
397 if (board_at(b, c) != color) continue;
398 if (board_group_info(b, group_at(b, c)).lib[0] == to
399 || board_group_info(b, group_at(b, c)).lib[1] == to)
400 ltouch8++;
401 } foreach_diag_neighbor_end;
402 return ltouch8 != touch8;
405 static int
406 check_throwin(struct board *b, enum stone color, coord_t to, struct selfatari_state *s)
408 /* We can be throwing-in to false eye:
409 * X X X O X X X O X X X X X
410 * X . * X * O . X * O O . X
411 * # # # # # # # # # # # # # */
412 /* We cannot sensibly throw-in into a corner. */
413 if (neighbor_count_at(b, to, S_OFFBOARD) < 2
414 && neighbor_count_at(b, to, stone_other(color))
415 + neighbor_count_at(b, to, S_OFFBOARD) == 3
416 && board_is_false_eyelike(b, to, stone_other(color))) {
417 assert(s->groupcts[color] <= 1);
418 /* Single-stone throw-in may be ok... */
419 if (s->groupcts[color] == 0) {
420 /* O X . There is one problem - when it's
421 * . * X actually not a throw-in!
422 * # # # */
423 foreach_neighbor(b, to, {
424 if (board_at(b, c) == S_NONE) {
425 /* Is the empty neighbor an escape path? */
426 /* (Note that one S_NONE neighbor is already @to.) */
427 if (neighbor_count_at(b, c, stone_other(color))
428 + neighbor_count_at(b, c, S_OFFBOARD) < 2)
429 return -1;
432 return false;
435 /* Multi-stone throwin...? */
436 assert(s->groupcts[color] == 1);
437 group_t g = s->groupids[color][0];
439 assert(board_group_info(b, g).libs <= 2);
440 /* Suicide is definitely NOT ok, no matter what else
441 * we could test. */
442 if (board_group_info(b, g).libs == 1)
443 return true;
445 /* In that case, we must be connected to at most one stone,
446 * or throwin will not destroy any eyes. */
447 if (group_is_onestone(b, g))
448 return false;
450 return -1;
453 bool
454 is_bad_selfatari_slow(struct board *b, enum stone color, coord_t to)
456 if (DEBUGL(5))
457 fprintf(stderr, "sar check %s %s\n", stone2str(color), coord2sstr(to, b));
458 /* Assess if we actually gain any liberties by this escape route.
459 * Note that this is not 100% as we cannot check whether we are
460 * connecting out or just to ourselves. */
462 struct selfatari_state s;
463 memset(&s, 0, sizeof(s));
464 int d;
466 foreach_neighbor(b, to, {
467 enum stone color = board_at(b, c);
468 group_t group = group_at(b, c);
469 bool dup = false;
470 for (int i = 0; i < s.groupcts[color]; i++)
471 if (s.groupids[color][i] == group) {
472 dup = true;
473 break;
475 if (!dup) {
476 s.groupneis[color][s.groupcts[color]] = c;
477 s.groupids[color][s.groupcts[color]++] = group_at(b, c);
481 /* We have shortage of liberties; that's the point. */
482 assert(s.groupcts[S_NONE] <= 1);
484 d = examine_friendly_groups(b, color, to, &s);
485 if (d >= 0)
486 return d;
488 if (DEBUGL(6))
489 fprintf(stderr, "no friendly group\n");
491 d = examine_enemy_groups(b, color, to, &s);
492 if (d >= 0)
493 return d;
495 if (DEBUGL(6))
496 fprintf(stderr, "no escape\n");
498 d = setup_nakade_or_snapback(b, color, to, &s);
499 if (d >= 0)
500 return d;
502 if (DEBUGL(6))
503 fprintf(stderr, "no nakade group\n");
505 d = check_throwin(b, color, to, &s);
506 if (d >= 0)
507 return d;
509 if (DEBUGL(6))
510 fprintf(stderr, "no throw-in group\n");
512 /* No way to pull out, no way to connect out. This really
513 * is a bad self-atari! */
514 return true;
518 coord_t
519 selfatari_cousin(struct board *b, enum stone color, coord_t coord, group_t *bygroup)
521 group_t groups[4]; int groups_n = 0;
522 int groupsbycolor[4] = {0, 0, 0, 0};
523 if (DEBUGL(6))
524 fprintf(stderr, "cousin group search: ");
525 foreach_neighbor(b, coord, {
526 enum stone s = board_at(b, c);
527 group_t g = group_at(b, c);
528 if (board_group_info(b, g).libs == 2) {
529 groups[groups_n++] = g;
530 groupsbycolor[s]++;
531 if (DEBUGL(6))
532 fprintf(stderr, "%s(%s) ", coord2sstr(c, b), stone2str(s));
535 if (DEBUGL(6))
536 fprintf(stderr, "\n");
538 if (!groups_n)
539 return pass;
541 int gn;
542 if (groupsbycolor[stone_other(color)]) {
543 /* Prefer to fill the other liberty of an opponent
544 * group to filling own approach liberties. */
545 int gl = fast_random(groups_n);
546 for (gn = gl; gn < groups_n; gn++)
547 if (board_at(b, groups[gn]) == stone_other(color))
548 goto found;
549 for (gn = 0; gn < gl; gn++)
550 if (board_at(b, groups[gn]) == stone_other(color))
551 goto found;
552 found:;
553 } else {
554 gn = fast_random(groups_n);
556 int gl = gn;
557 for (; gn - gl < groups_n; gn++) {
558 int gnm = gn % groups_n;
559 group_t group = groups[gnm];
561 coord_t lib2;
562 /* Can we get liberties by capturing a neighbor? */
563 struct move_queue ccq; ccq.moves = 0;
564 if (can_countercapture(b, color, group, color, &ccq, 0)) {
565 lib2 = mq_pick(&ccq);
567 } else {
568 lib2 = board_group_other_lib(b, group, coord);
569 if (board_is_one_point_eye(b, lib2, board_at(b, group)))
570 continue;
571 if (is_bad_selfatari(b, color, lib2))
572 continue;
574 if (bygroup)
575 *bygroup = group;
576 return lib2;
578 return pass;