Merge pull request #50 from lemonsqueeze/can_countercap
[pachi.git] / ownermap.c
blobfd92980546c5521263d470fb7460a5d3d088143b
1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdlib.h>
5 #include "board.h"
6 #include "debug.h"
7 #include "move.h"
8 #include "mq.h"
9 #include "ownermap.h"
11 static char *
12 printhook(struct board *board, coord_t c, char *s, char *end, void *data)
14 struct board_ownermap *ownermap = data;
15 if (!ownermap) {
16 strcat(s, ". ");
17 return s + 2;
19 const char chr[] = ":XO,"; // dame, black, white, unclear
20 const char chm[] = ":xo,";
21 char ch = chr[board_ownermap_judge_point(ownermap, c, GJ_THRES)];
22 if (ch == ',') { // less precise estimate then?
23 ch = chm[board_ownermap_judge_point(ownermap, c, 0.67)];
25 s += snprintf(s, end - s, "%c ", ch);
26 return s;
29 void
30 board_print_ownermap(struct board *b, FILE *f, struct board_ownermap *ownermap)
32 board_print_custom(b, stderr, printhook, ownermap);
35 void
36 board_ownermap_fill(struct board_ownermap *ownermap, struct board *b)
38 ownermap->playouts++;
39 foreach_point(b) {
40 enum stone color = board_at(b, c);
41 if (color == S_NONE)
42 color = board_get_one_point_eye(b, c);
43 ownermap->map[c][color]++;
44 } foreach_point_end;
47 void
48 board_ownermap_merge(int bsize2, struct board_ownermap *dst, struct board_ownermap *src)
50 dst->playouts += src->playouts;
51 for (int i = 0; i < bsize2; i++)
52 for (int j = 0; j < S_MAX; j++)
53 dst->map[i][j] += src->map[i][j];
56 float
57 board_ownermap_estimate_point(struct board_ownermap *ownermap, coord_t c)
59 assert(ownermap->map);
60 int b = ownermap->map[c][S_BLACK];
61 int w = ownermap->map[c][S_WHITE];
62 int total = ownermap->playouts;
63 return 1.0 * (b - w) / total;
66 enum point_judgement
67 board_ownermap_judge_point(struct board_ownermap *ownermap, coord_t c, floating_t thres)
69 assert(ownermap->map);
70 int n = ownermap->map[c][S_NONE];
71 int b = ownermap->map[c][S_BLACK];
72 int w = ownermap->map[c][S_WHITE];
73 int total = ownermap->playouts;
74 if (n >= total * thres)
75 return PJ_DAME;
76 else if (n + b >= total * thres)
77 return PJ_BLACK;
78 else if (n + w >= total * thres)
79 return PJ_WHITE;
80 else
81 return PJ_UNKNOWN;
84 void
85 board_ownermap_judge_groups(struct board *b, struct board_ownermap *ownermap, struct group_judgement *judge)
87 assert(ownermap->map);
88 assert(judge->gs);
89 memset(judge->gs, GS_NONE, board_size2(b) * sizeof(judge->gs[0]));
91 foreach_point(b) {
92 enum stone color = board_at(b, c);
93 group_t g = group_at(b, c);
94 if (!g) continue;
96 enum point_judgement pj = board_ownermap_judge_point(ownermap, c, judge->thres);
97 // assert(judge->gs[g] == GS_NONE || judge->gs[g] == pj);
98 if (pj == PJ_UNKNOWN) {
99 /* Fate is uncertain. */
100 judge->gs[g] = GS_UNKNOWN;
102 } else if (judge->gs[g] != GS_UNKNOWN) {
103 /* Update group state. */
104 enum gj_state new;
106 // Comparing enum types, casting (int) avoids compiler warnings
107 if ((int)pj == (int)color) {
108 new = GS_ALIVE;
109 } else if ((int)pj == (int)stone_other(color)) {
110 new = GS_DEAD;
111 } else { assert(pj == PJ_DAME);
112 /* Exotic! */
113 new = GS_UNKNOWN;
116 if (judge->gs[g] == GS_NONE) {
117 judge->gs[g] = new;
118 } else if (judge->gs[g] != new) {
119 /* Contradiction. :( */
120 judge->gs[g] = GS_UNKNOWN;
123 } foreach_point_end;
126 void
127 groups_of_status(struct board *b, struct group_judgement *judge, enum gj_state s, struct move_queue *mq)
129 foreach_point(b) { /* foreach_group, effectively */
130 group_t g = group_at(b, c);
131 if (!g || g != c) continue;
133 assert(judge->gs[g] != GS_NONE);
134 if (judge->gs[g] == s)
135 mq_add(mq, g, 0);
136 } foreach_point_end;