UCT dynkomi linear rootbased: Introduce option
[pachi/peepo.git] / uct / dynkomi.c
blob83a8c748bb1cee5e2020b5cb18c31ad0e6b34f90
1 #include <assert.h>
2 #include <math.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
7 #include "board.h"
8 #include "debug.h"
9 #include "tactics.h"
10 #include "uct/dynkomi.h"
11 #include "uct/internal.h"
12 #include "uct/tree.h"
15 static void
16 uct_dynkomi_generic_done(struct uct_dynkomi *d)
18 if (d->data) free(d->data);
19 free(d);
23 /* NONE dynkomi strategy - never fiddle with komi values. */
25 struct uct_dynkomi *
26 uct_dynkomi_init_none(struct uct *u, char *arg, struct board *b)
28 struct uct_dynkomi *d = calloc(1, sizeof(*d));
29 d->uct = u;
30 d->permove = NULL;
31 d->persim = NULL;
32 d->done = uct_dynkomi_generic_done;
33 d->data = NULL;
35 if (arg) {
36 fprintf(stderr, "uct: Dynkomi method none accepts no arguments\n");
37 exit(1);
40 return d;
44 /* LINEAR dynkomi strategy - Linearly Decreasing Handicap Compensation. */
45 /* At move 0, we impose extra komi of handicap_count*handicap_value, then
46 * we linearly decrease this extra komi throughout the game down to 0
47 * at @moves moves. */
49 struct dynkomi_linear {
50 int handicap_value;
51 int moves;
52 bool rootbased;
55 float
56 uct_dynkomi_linear_permove(struct uct_dynkomi *d, struct board *b, struct tree *tree)
58 struct dynkomi_linear *l = d->data;
59 if (b->moves >= l->moves)
60 return 0;
62 float base_komi = board_effective_handicap(b, l->handicap_value);
63 float extra_komi = base_komi * (l->moves - b->moves) / l->moves;
64 return extra_komi;
67 float
68 uct_dynkomi_linear_persim(struct uct_dynkomi *d, struct board *b, struct tree *tree, struct tree_node *node)
70 struct dynkomi_linear *l = d->data;
71 if (l->rootbased)
72 return tree->extra_komi;
73 /* We don't reuse computed value from tree->extra_komi,
74 * since we want to use value correct for this node depth.
75 * This also means the values will stay correct after
76 * node promotion. */
77 return uct_dynkomi_linear_permove(d, b, tree);
80 struct uct_dynkomi *
81 uct_dynkomi_init_linear(struct uct *u, char *arg, struct board *b)
83 struct uct_dynkomi *d = calloc(1, sizeof(*d));
84 d->uct = u;
85 d->permove = uct_dynkomi_linear_permove;
86 d->persim = uct_dynkomi_linear_persim;
87 d->done = uct_dynkomi_generic_done;
89 struct dynkomi_linear *l = calloc(1, sizeof(*l));
90 d->data = l;
92 if (board_size(b) - 2 >= 19)
93 l->moves = 200;
94 l->handicap_value = 7;
96 if (arg) {
97 char *optspec, *next = arg;
98 while (*next) {
99 optspec = next;
100 next += strcspn(next, ":");
101 if (*next) { *next++ = 0; } else { *next = 0; }
103 char *optname = optspec;
104 char *optval = strchr(optspec, '=');
105 if (optval) *optval++ = 0;
107 if (!strcasecmp(optname, "moves") && optval) {
108 /* Dynamic komi in handicap game; linearly
109 * decreases to basic settings until move
110 * #optval. */
111 l->moves = atoi(optval);
112 } else if (!strcasecmp(optname, "handicap_value") && optval) {
113 /* Point value of single handicap stone,
114 * for dynkomi computation. */
115 l->handicap_value = atoi(optval);
116 } else if (!strcasecmp(optname, "rootbased")) {
117 /* If set, the extra komi applied will be
118 * the same for all simulations within a move,
119 * instead of being same for all simulations
120 * within the tree node. */
121 l->rootbased = !optval || atoi(optval);
122 } else {
123 fprintf(stderr, "uct: Invalid dynkomi argument %s or missing value\n", optname);
124 exit(1);
129 return d;