Merge pull request #49 from lemonsqueeze/dragon
[pachi.git] / uct / policy / generic.h
blobe7a5c8b87649c138505fcd5749fb20a20683e93b
1 #ifndef PACHI_UCT_POLICY_GENERIC_H
2 #define PACHI_UCT_POLICY_GENERIC_H
4 /* Some default policy routines and templates. */
6 #include "board.h"
7 #include "stone.h"
8 #include "uct/internal.h"
10 struct board;
11 struct tree_node;
13 struct tree_node *uctp_generic_choose(struct uct_policy *p, struct tree_node *node, struct board *b, enum stone color, coord_t exclude);
14 void uctp_generic_winner(struct uct_policy *p, struct tree *tree, struct uct_descent *descent);
17 /* Some generic stitching for tree descent. */
19 #if 0
20 #define uctd_debug(fmt...) fprintf(stderr, fmt);
21 #else
22 #define uctd_debug(fmt...)
23 #endif
25 #define uctd_try_node_children(tree, descent, allow_pass, parity, tenuki_d, di, urgency) \
26 /* Information abound best children. */ \
27 /* XXX: We assume board <=25x25. */ \
28 struct uct_descent dbest[BOARD_MAX_MOVES + 1] = { { .node = descent->node->children, .lnode = NULL } }; int dbests = 1; \
29 floating_t best_urgency = -9999; \
30 /* Descent children iterator. */ \
31 struct uct_descent dci = { .node = descent->node->children, .lnode = descent->lnode ? descent->lnode->children : NULL }; \
33 for (; dci.node; dci.node = dci.node->sibling) { \
34 floating_t urgency; \
35 /* Do not consider passing early. */ \
36 if (unlikely((!allow_pass && is_pass(node_coord(dci.node))) || (dci.node->hints & TREE_HINT_INVALID))) \
37 continue; \
38 /* Position dci.lnode to point at or right after the local
39 * node corresponding to dci.node. */ \
40 while (dci.lnode && node_coord(dci.lnode) < node_coord(dci.node)) \
41 dci.lnode = dci.lnode->sibling; \
42 /* Set up descent-further iterator. This is the public-accessible
43 * one, and usually is similar to dci. However, in case of local
44 * trees, we may keep next-candidate pointer in dci while storing
45 * actual-specimen in di. */ \
46 struct uct_descent di = dci; \
47 if (dci.lnode) { \
48 /* Set lnode to local tree node corresponding
49 * to node (dci.lnode, pass-lnode or NULL). */ \
50 di.lnode = tree_lnode_for_node(tree, dci.node, dci.lnode, tenuki_d); \
53 /* ...your urgency computation code goes here... */
55 #define uctd_set_best_child(di, urgency) \
56 uctd_debug("(%s) %f\n", coord2sstr(node_coord(di.node), tree->board), urgency); \
57 if (urgency - best_urgency > __FLT_EPSILON__) { /* urgency > best_urgency */ \
58 uctd_debug("new best\n"); \
59 best_urgency = urgency; dbests = 0; \
60 } \
61 if (urgency - best_urgency > -__FLT_EPSILON__) { /* urgency >= best_urgency */ \
62 uctd_debug("another best\n"); \
63 /* We want to always choose something else than a pass \
64 * in case of a tie. pass causes degenerative behaviour. */ \
65 if (dbests == 1 && is_pass(node_coord(dbest[0].node))) { \
66 dbests--; \
67 } \
68 struct uct_descent db = di; \
69 /* Make sure lnode information is meaningful. */ \
70 if (db.lnode && is_pass(node_coord(db.lnode))) \
71 db.lnode = NULL; \
72 dbest[dbests++] = db; \
73 } \
76 #define uctd_get_best_child(descent) *(descent) = dbest[fast_random(dbests)];
79 #endif