fbook: Fix double free of fbook structure
[pachi/json.git] / zzgo.c
blobb87489d1b9aec5c715f5e5f60f74104ab6cf0b5e
1 #define DEBUG
2 #include <assert.h>
3 #include <getopt.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <time.h>
8 #include <unistd.h>
10 #include "board.h"
11 #include "debug.h"
12 #include "engine.h"
13 #include "replay/replay.h"
14 #include "montecarlo/montecarlo.h"
15 #include "random/random.h"
16 #include "patternscan/patternscan.h"
17 #include "joseki/joseki.h"
18 #include "t-unit/test.h"
19 #include "uct/uct.h"
20 #include "distributed/distributed.h"
21 #include "gtp.h"
22 #include "timeinfo.h"
23 #include "random.h"
24 #include "version.h"
25 #include "network.h"
27 int debug_level = 3;
28 long verbose_logs = 0;
29 int seed;
32 enum engine_id {
33 E_RANDOM,
34 E_REPLAY,
35 E_PATTERNSCAN,
36 E_MONTECARLO,
37 E_UCT,
38 E_DISTRIBUTED,
39 E_JOSEKI,
40 E_MAX,
43 static struct engine *(*engine_init[E_MAX])(char *arg, struct board *b) = {
44 engine_random_init,
45 engine_replay_init,
46 engine_patternscan_init,
47 engine_montecarlo_init,
48 engine_uct_init,
49 engine_distributed_init,
50 engine_joseki_init,
53 static struct engine *init_engine(enum engine_id engine, char *e_arg, struct board *b)
55 char *arg = e_arg? strdup(e_arg) : e_arg;
56 assert(engine < E_MAX);
57 struct engine *e = engine_init[engine](arg, b);
58 if (arg) free(arg);
59 return e;
62 static void done_engine(struct engine *e)
64 if (e->done) e->done(e);
65 if (e->data) free(e->data);
66 free(e);
69 static void usage(char *name)
71 fprintf(stderr, "Pachi version %s\n", PACHI_VERSION);
72 fprintf(stderr, "Usage: %s [-e random|replay|patternscan|montecarlo|uct|distributed]\n"
73 " [-d DEBUG_LEVEL] [-s RANDOM_SEED] [-t TIME_SETTINGS] [-u TEST_FILENAME]\n"
74 " [-g [HOST:]GTP_PORT] [-l [HOST:]LOG_PORT] [-f FBOOKFILE] [ENGINE_ARGS]\n", name);
77 int main(int argc, char *argv[])
79 enum engine_id engine = E_UCT;
80 struct time_info ti_default = { .period = TT_NULL };
81 char *testfile = NULL;
82 char *gtp_port = NULL;
83 char *log_port = NULL;
84 int gtp_sock = -1;
85 char *fbookfile = NULL;
87 seed = time(NULL) ^ getpid();
89 int opt;
90 while ((opt = getopt(argc, argv, "e:d:f:g:l:s:t:u:")) != -1) {
91 switch (opt) {
92 case 'e':
93 if (!strcasecmp(optarg, "random")) {
94 engine = E_RANDOM;
95 } else if (!strcasecmp(optarg, "patternscan")) {
96 engine = E_PATTERNSCAN;
97 } else if (!strcasecmp(optarg, "replay")) {
98 engine = E_REPLAY;
99 } else if (!strcasecmp(optarg, "montecarlo")) {
100 engine = E_MONTECARLO;
101 } else if (!strcasecmp(optarg, "uct")) {
102 engine = E_UCT;
103 } else if (!strcasecmp(optarg, "distributed")) {
104 engine = E_DISTRIBUTED;
105 } else if (!strcasecmp(optarg, "joseki")) {
106 engine = E_JOSEKI;
107 } else {
108 fprintf(stderr, "%s: Invalid -e argument %s\n", argv[0], optarg);
109 exit(1);
111 break;
112 case 'd':
113 debug_level = atoi(optarg);
114 break;
115 case 'f':
116 fbookfile = strdup(optarg);
117 break;
118 case 'g':
119 gtp_port = strdup(optarg);
120 break;
121 case 'l':
122 log_port = strdup(optarg);
123 break;
124 case 's':
125 seed = atoi(optarg);
126 break;
127 case 't':
128 /* Time settings to follow; if specified,
129 * GTP time information is ignored. Useful
130 * e.g. when you want to force your bot to
131 * play weaker while giving the opponent
132 * reasonable time to play, or force play
133 * by number of simulations in timed games. */
134 /* Please see timeinfo.h:time_parse()
135 * description for syntax details. */
136 if (!time_parse(&ti_default, optarg)) {
137 fprintf(stderr, "%s: Invalid -t argument %s\n", argv[0], optarg);
138 exit(1);
140 ti_default.ignore_gtp = true;
141 assert(ti_default.period != TT_NULL);
142 break;
143 case 'u':
144 testfile = strdup(optarg);
145 break;
146 default: /* '?' */
147 usage(argv[0]);
148 exit(1);
152 if (log_port)
153 open_log_port(log_port);
155 fast_srandom(seed);
156 if (DEBUGL(0))
157 fprintf(stderr, "Random seed: %d\n", seed);
159 struct board *b = board_init(fbookfile);
160 struct time_info ti[S_MAX];
161 ti[S_BLACK] = ti_default;
162 ti[S_WHITE] = ti_default;
164 char *e_arg = NULL;
165 if (optind < argc)
166 e_arg = argv[optind];
167 struct engine *e = init_engine(engine, e_arg, b);
169 if (testfile) {
170 unittest(testfile);
171 return 0;
174 if (gtp_port) {
175 open_gtp_connection(&gtp_sock, gtp_port);
178 for (;;) {
179 char buf[4096];
180 while (fgets(buf, 4096, stdin)) {
181 if (DEBUGL(1))
182 fprintf(stderr, "IN: %s", buf);
184 enum parse_code c = gtp_parse(b, e, ti, buf);
185 if (c == P_ENGINE_RESET) {
186 ti[S_BLACK] = ti_default;
187 ti[S_WHITE] = ti_default;
188 if (!e->keep_on_clear) {
189 b->es = NULL;
190 done_engine(e);
191 e = init_engine(engine, e_arg, b);
193 } else if (c == P_UNKNOWN_COMMAND && gtp_port) {
194 /* The gtp command is a weak identity check,
195 * close the connection with a wrong peer. */
196 break;
199 if (!gtp_port) break;
200 open_gtp_connection(&gtp_sock, gtp_port);
202 done_engine(e);
203 return 0;