Merge pull request #50 from lemonsqueeze/can_countercap
[pachi.git] / uct / plugins.c
blob79bd55dde97234b55d72ff1306661cc720bae205
1 #include <assert.h>
2 #ifndef WIN32
3 #include <dlfcn.h>
4 #endif
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
9 #include "board.h"
10 #include "debug.h"
11 #include "move.h"
12 #include "random.h"
13 #include "uct/plugins.h"
14 #include "uct/prior.h"
15 #include "uct/tree.h"
17 /* Plugin interface for UCT. External plugins may hook callbacks on various
18 * events and e.g. bias the tree. */
21 /* Keep the API typedefs in sync with <uct/plugin.h>. */
23 struct plugin {
24 char *path;
25 char *args;
26 void *dlh;
27 void *data;
29 void *(*init)(char *args, struct board *b, int seed);
30 void (*prior)(void *data, struct tree_node *node, struct prior_map *map, int eqex);
31 void (*done)(void *data);
34 struct uct_pluginset {
35 struct plugin *plugins;
36 int n_plugins;
37 struct board *b;
41 #ifdef WIN32
43 /* We do not support plugins on Windows. Minimal dummy stubs. */
45 struct uct_pluginset *
46 pluginset_init(struct board *b)
48 return NULL;
50 void
51 pluginset_done(struct uct_pluginset *ps)
53 assert(!ps);
55 void
56 plugin_load(struct uct_pluginset *ps, char *path, char *args)
58 assert(!ps);
60 void
61 plugin_prior(struct uct_pluginset *ps, struct tree_node *node, struct prior_map *map, int eqex)
63 assert(!ps);
66 #else
68 struct uct_pluginset *
69 pluginset_init(struct board *b)
71 struct uct_pluginset *ps = calloc(1, sizeof(*ps));
72 ps->b = b;
73 return ps;
76 void
77 pluginset_done(struct uct_pluginset *ps)
79 for (int i = 0; i < ps->n_plugins; i++) {
80 struct plugin *p = &ps->plugins[i];
81 p->done(p->data);
82 dlclose(p->dlh);
83 free(p->path);
84 free(p->args);
86 free(ps);
90 void
91 plugin_load(struct uct_pluginset *ps, char *path, char *args)
93 ps->plugins = realloc(ps->plugins, ++ps->n_plugins * sizeof(ps->plugins[0]));
94 struct plugin *p = &ps->plugins[ps->n_plugins - 1];
95 p->path = strdup(path);
96 p->args = args ? strdup(args) : args;
98 p->dlh = dlopen(path, RTLD_NOW);
99 if (!p->dlh) {
100 fprintf(stderr, "Cannot load plugin %s: %s\n", path, dlerror());
101 exit(EXIT_FAILURE);
103 #define loadsym(s_) do {\
104 p->s_ = dlsym(p->dlh, "pachi_plugin_" #s_); \
105 if (!p->s_) { \
106 fprintf(stderr, "Cannot find pachi_plugin_%s in plugin %s: %s\n", #s_, path, dlerror()); \
107 exit(EXIT_FAILURE); \
109 } while (0)
110 loadsym(init);
111 loadsym(prior);
112 loadsym(done);
114 p->data = p->init(p->args, ps->b, fast_random(65536));
117 void
118 plugin_prior(struct uct_pluginset *ps, struct tree_node *node, struct prior_map *map, int eqex)
120 for (int i = 0; i < ps->n_plugins; i++) {
121 struct plugin *p = &ps->plugins[i];
122 p->prior(p->data, node, map, eqex);
126 #endif