Merge branch 'master' into greedy2
[pachi.git] / uct / plugins.c
blob7132bc003b123922fc4e6755bc3e5510b39a963f
1 #include <assert.h>
2 #include <dlfcn.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
7 #include "board.h"
8 #include "debug.h"
9 #include "move.h"
10 #include "random.h"
11 #include "uct/plugins.h"
12 #include "uct/prior.h"
13 #include "uct/tree.h"
15 /* Plugin interface for UCT. External plugins may hook callbacks on various
16 * events and e.g. bias the tree. */
19 /* Keep the API typedefs in sync with <uct/plugin.h>. */
21 struct plugin {
22 char *path;
23 char *args;
24 void *dlh;
25 void *data;
27 void *(*init)(char *args, struct board *b, int seed);
28 void (*prior)(void *data, struct tree_node *node, struct prior_map *map, int eqex);
29 void (*done)(void *data);
32 struct uct_pluginset {
33 struct plugin *plugins;
34 int n_plugins;
35 struct board *b;
39 struct uct_pluginset *
40 pluginset_init(struct board *b)
42 struct uct_pluginset *ps = calloc(1, sizeof(*ps));
43 ps->b = b;
44 return ps;
47 void
48 pluginset_done(struct uct_pluginset *ps)
50 for (int i = 0; i < ps->n_plugins; i++) {
51 struct plugin *p = &ps->plugins[i];
52 p->done(p->data);
53 dlclose(p->dlh);
54 free(p->path);
55 free(p->args);
57 free(ps);
61 void
62 plugin_load(struct uct_pluginset *ps, char *path, char *args)
64 ps->plugins = realloc(ps->plugins, ++ps->n_plugins * sizeof(ps->plugins[0]));
65 struct plugin *p = &ps->plugins[ps->n_plugins - 1];
66 p->path = strdup(path);
67 p->args = args ? strdup(args) : args;
69 p->dlh = dlopen(path, RTLD_NOW);
70 if (!p->dlh) {
71 fprintf(stderr, "Cannot load plugin %s: %s\n", path, dlerror());
72 exit(EXIT_FAILURE);
74 #define loadsym(s_) do {\
75 p->s_ = dlsym(p->dlh, "pachi_plugin_" #s_); \
76 if (!p->s_) { \
77 fprintf(stderr, "Cannot find pachi_plugin_%s in plugin %s: %s\n", #s_, path, dlerror()); \
78 exit(EXIT_FAILURE); \
79 } \
80 } while (0)
81 loadsym(init);
82 loadsym(prior);
83 loadsym(done);
85 p->data = p->init(p->args, ps->b, fast_random(65536));
88 void
89 plugin_prior(struct uct_pluginset *ps, struct tree_node *node, struct prior_map *map, int eqex)
91 for (int i = 0; i < ps->n_plugins; i++) {
92 struct plugin *p = &ps->plugins[i];
93 p->prior(p->data, node, map, eqex);