in go/board.cc [1406:1498]
void VerifyBoard(Board* board) {
// Groups
// 1. Check if the number of groups is the same as indicated by board->_num_groups.
unsigned short group_size[MAX_GROUP];
memset(group_size, 0, sizeof(group_size));
printf("-----Beging verifying-----\n");
for (int i = 0; i < BOARD_SIZE; ++i) {
for (int j = 0; j < BOARD_SIZE; ++j) {
Coord c = OFFSETXY(i, j);
const Info* info = &board->_infos[c];
if (G_HAS_STONE(info->id) != HAS_STONE(board->_infos[c].color)) {
printf("[VerifyError]: id [%d] and stone [%d] mismatch at (%d, %d)\n", info->id, board->_infos[c].color, X(c), Y(c));
}
if (HAS_STONE(board->_infos[c].color)) {
group_size[info->id] ++;
}
}
}
if (board->_num_groups < 1 || board->_num_groups >= MAX_GROUP) {
printf("[VerifyError]: #groups = %d [MAX_GROUP = %d]", board->_num_groups - 1, MAX_GROUP);
}
// Group id starts from 1.
for (int i = 1; i < board->_num_groups; ++i) {
Group* g = &board->_groups[i];
// printf("Group %d: Start [%d] at (%d, %d)\n", i, g->start, X(g->start), Y(g->start));
int num_of_stones = 0;
if (g->color == 0 || g->stones == 0 || g->liberties <= 0 || g->start == 0) {
printf("[VerifyError]: Group %d is wrong: color: %d, stone: %d [%d from board], liberties: %d, start: [%d] (%d, %d)\n",
i, g->color, g->stones, group_size[i], g->liberties, g->start, X(g->start), Y(g->start));
continue;
}
TRAVERSE(board, i, c) {
const Info* info = &board->_infos[c];
if (info->id != i) {
printf("[VerifyError]: stone %d: info->id [%d] and group id [%d] are not consistent on (%d, %d)\n", num_of_stones, info->id, i, X(c), Y(c));
}
num_of_stones ++;
} ENDTRAVERSE
// Check stones.
if (num_of_stones != g->stones) {
printf("[VerifyError]: Group %d: Actual #stones from linked_list [%d] != recorded [%d]\n", i, num_of_stones, g->stones);
}
if (g->stones != group_size[i]) {
printf("[VerifyError]: Group %d: Actual #stones from board [%d] != recorded [%d]\n", i, group_size[i], g->stones);
}
// Check liberties.
short recorded_liberties = g->liberties;
RecomputeGroupLiberties(board, i);
if (recorded_liberties != g->liberties) {
printf("[VerifyError]: Group %d: Actual liberty [%d] != recorded [%d]\n", i, g->liberties, recorded_liberties);
// Bring back the wrong liberties.
g->liberties = recorded_liberties;
}
// Check connectivity.
Coord *visited = new Coord[group_size[i]];
::memset(visited, 0, group_size[i] * sizeof(Coord));
// A simple BFS with two pointers.
int push_index = 1, pop_index = 0;
visited[0] = g->start;
// EXTREMELY HACK HERE: Use the id as the visited mask.
board->_infos[g->start].id = 0;
while (pop_index < push_index) {
Coord c = visited[pop_index++];
// printf("Visit (%d, %d)\n", X(c), Y(c));
if (board->_infos[c].color != g->color) {
printf("[VerifyError]: Stone at (%d, %d) has different color [%d] than its group [%d], whose color is %d\n", X(c), Y(c), board->_infos[c].color, i, g->color);
}
FOR4(c, _, c4) {
if (board->_infos[c4].id == i) {
// Put it into the queue. Mark it as visited.
board->_infos[c4].id = 0;
visited[push_index++] = c4;
}
} ENDFOR4
}
if (push_index != group_size[i]) {
printf("[VerifyError]: Group %d: connected component has %d entries, while #group = %d\n", i, push_index, group_size[i]);
}
// Resume the id.
while (--push_index >= 0) {
board->_infos[visited[push_index]].id = i;
}
// Free the memory.
delete [] visited;
}
printf("-----End verifying-----\n");
}