void VerifyBoard()

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");
}