static bool test_can_countercapture(struct board *b, char *arg) { coord_t c = str2scoord(arg, board_size(b)); arg += strcspn(arg, " ") + 1; int eres = atoi(arg); board_print_test(2, b); if (DEBUGL(1)) printf("can_countercap %s %d...\t", coord2sstr(c, b), eres); enum stone color = board_at(b, c); group_t g = group_at(b, c); assert(color == S_BLACK || color == S_WHITE); int rres = can_countercapture(b, g, NULL, 0); if (rres == eres) { if (DEBUGL(1)) printf("OK\n"); } else { if (debug_level <= 2) { board_print_test(0, b); printf("can_countercap %s %d...\t", coord2sstr(c, b), eres); } printf("FAILED (%d)\n", rres); } return rres == eres; }
bool is_middle_ladder(Board *b, Coord coord, group_t laddered, Stone lcolor) { /* TODO: Remove the redundant parameters. */ assert(group_at(b, laddered)->liberties == 1); Coord last_lib = get_nlibs_of_group(b, laddered, 1, NULL); assert(last_lib == coord); assert(group_at(b, laddered)->color == lcolor); /* If we can move into empty space or do not have enough space * to escape, this is obviously not a ladder. */ if (immediate_liberty_count(b, coord) != 2) { /* if (DEBUGL(5)) fprintf(stderr, "no ladder, wrong free space\n"); */ return false; } /* A fair chance for a ladder. Group in atari, with some but limited * space to escape. Time for the expensive stuff - set up a temporary * board and start selective 2-liberty search. */ Board *bset = (Board *)malloc(BOARD_MAX_SIZE * 2 * sizeof(Board)); struct move_queue ccq = { .moves = 0 }; if (can_countercapture(b, lcolor, laddered, lcolor, &ccq, 0)) { /* We could escape by countercapturing a group. * Investigate. */ assert(ccq.moves > 0); for (unsigned int i = 0; i < ccq.moves; i++) { Board b2; CopyBoard(&b2, b); bool is_ladder = middle_ladder_walk(&b2, bset, laddered, ccq.move[i], lcolor); // board_done_noalloc(&b2); if (!is_ladder) { free(bset); return false; } } } Board b2; CopyBoard(&b2, b); Coord last_lib2 = get_nlibs_of_group(&b2, laddered, 1, NULL); bool is_ladder = middle_ladder_walk(&b2, bset, laddered, last_lib2, lcolor); // board_done_noalloc(&b2); free(bset); return is_ladder; } bool wouldbe_ladder(Board *b, group_t group, Coord escapelib, Coord chaselib, Stone lcolor) { assert(b->_groups[group].liberties == 2); assert(b->_groups[group].color == lcolor); /* if (DEBUGL(6)) fprintf(stderr, "would-be ladder check - does %s %s play out chasing move %s?\n", stone2str(lcolor), coord2sstr(escapelib, b), coord2sstr(chaselib, b)); */ if (!NEIGHBOR8(escapelib, chaselib)) { /* if (DEBUGL(5)) fprintf(stderr, "cannot determine ladder for remote simulated stone\n"); */ return false; } if (neighbor_count_at(b, chaselib, lcolor) != 1 || immediate_liberty_count(b, chaselib) != 2) { /* if (DEBUGL(5)) fprintf(stderr, "overly trivial for a ladder\n"); */ return false; } bool is_ladder = false; Board *bset = (Board *)malloc(BOARD_MAX_SIZE * 2 * sizeof(Board)); Board b2; CopyBoard(&b2, b); GroupId4 ids; if (TryPlay(&b2, X(chaselib), Y(chaselib), OPPONENT(lcolor), &ids)) { Play(&b2, &ids); Coord last_lib2 = get_nlibs_of_group(&b2, group, 1, NULL); is_ladder = middle_ladder_walk(&b2, bset, group, last_lib2, lcolor); } // board_done_noalloc(&b2); free(bset); return is_ladder; }