in go/board.cc [1584:1688]
float GetTrompTaylorScore(const Board *board, const Stone *group_stats, Stone *territory) {
Stone * internal_territory = NULL;
if (territory == NULL) {
internal_territory = new Stone[BOARD_SIZE * BOARD_SIZE];
territory = internal_territory;
}
::memset(territory, S_EMPTY, BOARD_SIZE * BOARD_SIZE * sizeof(Stone));
//
Coord queue[BOARD_SIZE * BOARD_SIZE];
int territories[4] = { 0, 0, 0, 0 };
// Flood fill, starts with an empty location and expand.
// The output territory is 1 = BLACK, 2 = WHITE, and 3 = DAME
for (int i = 0; i < BOARD_SIZE; ++i) {
for (int j = 0; j < BOARD_SIZE; ++j) {
Coord c = OFFSETXY(i, j);
Stone s = board->_infos[c].color;
// printf("Check %s ... \n", get_move_str(c, s));
// Skip any stone.
if (s != S_EMPTY) {
Stone *t = &territory[EXPORT_OFFSET(c)];
if (*t == S_EMPTY) {
// Get the true color of the stone
unsigned char id = board->_infos[c].id;
if (group_stats != NULL && (group_stats[id] & S_DEAD)) s = OPPONENT(s);
*t = s;
territories[s] ++;
}
continue;
}
// It is visited.
if (territory[EXPORT_OFFSET_XY(i, j)] != S_EMPTY) continue;
// Empty space and it is not visited.
// Do DFS
Stone owner = S_EMPTY;
int q_start = 0, q_end = 0;
queue[q_end ++] = c;
territory[EXPORT_OFFSET(c)] = S_DAME;
// printf("Start DFS ...\n");
// fflush(stdout);
while (q_end - q_start > 0) {
Coord cc = queue[q_start ++];
// printf("Visited %s..owner = %d\n", get_move_str(cc, board->_infos[cc].color), owner);
// fflush(stdout);
// Put its neighbor into the queue
FOR4(cc, _, ccc) {
Stone sss = board->_infos[ccc].color;
if (sss != S_EMPTY) {
if (sss != S_OFF_BOARD && owner != S_DAME) {
Stone *t = &territory[EXPORT_OFFSET(ccc)];
if (*t == S_EMPTY) {
// Get the true color of the stone
unsigned char id = board->_infos[ccc].id;
if (group_stats != NULL && (group_stats[id] & S_DEAD)) sss = OPPONENT(sss);
*t = sss;
territories[sss] ++;
}
if (owner == S_EMPTY) owner = *t;
else if (owner != *t) owner = S_DAME;
// printf("sss = %d, owner = %d\n", *t, owner);
// fflush(stdout);
}
} else if (territory[EXPORT_OFFSET(ccc)] == S_EMPTY) {
// Make it visited with S_DAME
territory[EXPORT_OFFSET(ccc)] = S_DAME;
// Empty slot and empty territory, put them in.
queue[q_end ++] = ccc;
}
} ENDFOR4
}
// Finish BFS, then we go through the visited again and set them to owner (if owner is not S_DAME).
if (owner == S_EMPTY) {
// Empty board.
return 0.0;
}
if (owner != S_DAME) {
for (int i = 0; i < q_end; ++i) {
// printf("Deal with %s\n", get_move_str(queue[i], owner));
// fflush(stdout);
territory[EXPORT_OFFSET(queue[i])] = owner;
// Each empty spot only visited once.
territories[owner] ++;
}
}
// Check whether we have visited all board locations, if so, just break.
if (territories[S_BLACK] + territories[S_WHITE] == BOARD_SIZE * BOARD_SIZE) break;
// fflush(stdout);
}
}
if (internal_territory) delete [] internal_territory;
// Finally count the score.
// printf("black = %d\n", territories[S_BLACK]);
// printf("white = %d\n", territories[S_WHITE]);
return territories[S_BLACK] - territories[S_WHITE];
}