pachi_py/pachi/ownermap.c (94 lines of code) (raw):

#include <assert.h> #include <stdio.h> #include <stdlib.h> #include "board.h" #include "debug.h" #include "move.h" #include "mq.h" #include "ownermap.h" void board_ownermap_fill(struct board_ownermap *ownermap, struct board *b) { ownermap->playouts++; foreach_point(b) { enum stone color = board_at(b, c); if (color == S_NONE) color = board_get_one_point_eye(b, c); ownermap->map[c][color]++; } foreach_point_end; } void board_ownermap_merge(int bsize2, struct board_ownermap *dst, struct board_ownermap *src) { dst->playouts += src->playouts; for (int i = 0; i < bsize2; i++) for (int j = 0; j < S_MAX; j++) dst->map[i][j] += src->map[i][j]; } float board_ownermap_estimate_point(struct board_ownermap *ownermap, coord_t c) { assert(ownermap->map); int b = ownermap->map[c][S_BLACK]; int w = ownermap->map[c][S_WHITE]; int total = ownermap->playouts; return 1.0 * (b - w) / total; } enum point_judgement board_ownermap_judge_point(struct board_ownermap *ownermap, coord_t c, floating_t thres) { assert(ownermap->map); int n = ownermap->map[c][S_NONE]; int b = ownermap->map[c][S_BLACK]; int w = ownermap->map[c][S_WHITE]; int total = ownermap->playouts; if (n >= total * thres) return PJ_DAME; else if (n + b >= total * thres) return PJ_BLACK; else if (n + w >= total * thres) return PJ_WHITE; else return PJ_UNKNOWN; } void board_ownermap_judge_groups(struct board *b, struct board_ownermap *ownermap, struct group_judgement *judge) { assert(ownermap->map); assert(judge->gs); memset(judge->gs, GS_NONE, board_size2(b) * sizeof(judge->gs[0])); foreach_point(b) { enum stone color = board_at(b, c); group_t g = group_at(b, c); if (!g) continue; enum point_judgement pj = board_ownermap_judge_point(ownermap, c, judge->thres); // assert(judge->gs[g] == GS_NONE || judge->gs[g] == pj); if (pj == PJ_UNKNOWN) { /* Fate is uncertain. */ judge->gs[g] = GS_UNKNOWN; } else if (judge->gs[g] != GS_UNKNOWN) { /* Update group state. */ enum gj_state new; // Comparing enum types, casting (int) avoids compiler warnings if ((int)pj == (int)color) { new = GS_ALIVE; } else if ((int)pj == (int)stone_other(color)) { new = GS_DEAD; } else { assert(pj == PJ_DAME); /* Exotic! */ new = GS_UNKNOWN; } if (judge->gs[g] == GS_NONE) { judge->gs[g] = new; } else if (judge->gs[g] != new) { /* Contradiction. :( */ judge->gs[g] = GS_UNKNOWN; } } } foreach_point_end; } void groups_of_status(struct board *b, struct group_judgement *judge, enum gj_state s, struct move_queue *mq) { foreach_point(b) { /* foreach_group, effectively */ group_t g = group_at(b, c); if (!g || g != c) continue; assert(judge->gs[g] != GS_NONE); if (judge->gs[g] == s) mq_add(mq, g, 0); } foreach_point_end; }