15 static struct tree_node
*
16 tree_init_node(coord_t coord
)
18 struct tree_node
*n
= calloc(1, sizeof(*n
));
24 tree_init(struct board
*board
)
26 struct tree
*t
= calloc(1, sizeof(*t
));
27 /* The root PASS move is only virtual, we never play it. */
28 t
->root
= tree_init_node(pass
);
35 tree_done_node(struct tree_node
*n
)
37 struct tree_node
*ni
= n
->children
;
39 struct tree_node
*nj
= ni
->sibling
;
47 tree_done(struct tree
*t
)
49 tree_done_node(t
->root
);
55 tree_node_dump(struct tree
*tree
, struct tree_node
*node
, int l
)
57 for (int i
= 0; i
< l
; i
++) fputc(' ', stderr
);
58 fprintf(stderr
, "[%s] %f (%d/%d playouts)\n", coord2sstr(node
->coord
, tree
->board
), node
->value
, node
->wins
, node
->playouts
);
60 /* Print nodes sorted by #playouts. */
62 struct tree_node
*nbox
[1000]; int nboxl
= 0;
63 for (struct tree_node
*ni
= node
->children
; ni
; ni
= ni
->sibling
)
64 if (ni
->playouts
> 200)
69 for (int i
= 0; i
< nboxl
; i
++)
70 if (nbox
[i
] && (best
< 0 || nbox
[i
]->playouts
> nbox
[best
]->playouts
))
74 tree_node_dump(tree
, nbox
[best
], l
+ 1);
80 tree_dump(struct tree
*tree
)
82 tree_node_dump(tree
, tree
->root
, 0);
87 tree_expand_node(struct tree
*t
, struct tree_node
*node
, struct board
*b
)
89 assert(!node
->children
);
91 struct tree_node
*ni
= tree_init_node(pass
);
92 ni
->parent
= node
; node
->children
= ni
;
94 /* The loop excludes the offboard margin. */
95 for (int i
= 1; i
< t
->board
->size
; i
++) {
96 for (int j
= 1; j
< t
->board
->size
; j
++) {
97 coord_t c
= coord_xy_otf(i
, j
, t
->board
);
98 if (board_at(b
, c
) != S_NONE
)
100 struct tree_node
*nj
= tree_init_node(coord_xy_otf(i
, j
, t
->board
));
101 nj
->parent
= node
; ni
->sibling
= nj
; ni
= nj
;
107 tree_unlink_node(struct tree_node
*node
)
109 struct tree_node
*ni
= node
->parent
;
110 if (ni
->children
== node
) {
111 ni
->children
= node
->sibling
;
114 while (ni
->sibling
!= node
)
116 ni
->sibling
= node
->sibling
;
121 tree_delete_node(struct tree_node
*node
)
123 tree_unlink_node(node
);
124 assert(!node
->children
);
129 tree_promote_node(struct tree
*tree
, struct tree_node
*node
)
131 assert(node
->parent
== tree
->root
);
132 tree_unlink_node(node
);
133 tree_done_node(tree
->root
);
139 tree_leaf_node(struct tree_node
*node
)
141 return !(node
->children
);
145 tree_best_child(struct tree_node
*node
, struct board
*b
, enum stone color
)
147 struct tree_node
*nbest
= NULL
;
148 for (struct tree_node
*ni
= node
->children
; ni
; ni
= ni
->sibling
)
149 // we compare playouts and choose the best-explored
150 // child; comparing values is more brittle
151 if (!nbest
|| ni
->playouts
> nbest
->playouts
) {
152 /* Play pass only if we can afford scoring */
153 if (is_pass(ni
->coord
)) {
154 float score
= board_fast_score(b
);
155 if (color
== S_BLACK
)
157 //fprintf(stderr, "%d score %f\n", b->last_move.color, score);
168 tree_uct_descend(struct tree
*tree
, struct tree_node
*node
, int parity
, bool allow_pass
)
170 float xpl
= log(node
->playouts
) * tree
->explore_p
;
172 struct tree_node
*nbest
= node
->children
;
173 float best_urgency
= -9999;
174 for (struct tree_node
*ni
= node
->children
; ni
; ni
= ni
->sibling
) {
175 /* Do not consider passing early. */
176 if (likely(!allow_pass
) && unlikely(is_pass(ni
->coord
)))
179 float xpl_loc
= (ni
->value
- ni
->value
* ni
->value
);
180 if (parity
< 0) xpl_loc
= 1 - xpl_loc
;
181 xpl_loc
+= sqrt(xpl
/ ni
->playouts
);
182 if (xpl_loc
> 1.0/4) xpl_loc
= 1.0/4;
183 float urgency
= ni
->value
* parity
+ sqrt(xpl
* xpl_loc
/ ni
->playouts
);
185 float urgency
= ni
->value
* parity
+ sqrt(xpl
/ ni
->playouts
);
187 if (urgency
> best_urgency
) {
188 best_urgency
= urgency
;
196 tree_uct_update(struct tree_node
*node
, int result
)
198 for (; node
; node
= node
->parent
) {
200 node
->wins
+= result
;
201 node
->value
= (float)node
->wins
/ node
->playouts
;