Support log proxy for the distributed engine.
[pachi.git] / zzgo.c
blob4128153d03851fc9233680b9ee69618f3141a4e3
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 "t-unit/test.h"
18 #include "uct/uct.h"
19 #include "gtp.h"
20 #include "timeinfo.h"
21 #include "random.h"
22 #include "version.h"
23 #include "network.h"
25 int debug_level = 3;
26 int seed;
29 enum engine_id {
30 E_RANDOM,
31 E_REPLAY,
32 E_PATTERNSCAN,
33 E_MONTECARLO,
34 E_UCT,
35 E_MAX,
38 static struct engine *(*engine_init[E_MAX])(char *arg, struct board *b) = {
39 engine_random_init,
40 engine_replay_init,
41 engine_patternscan_init,
42 engine_montecarlo_init,
43 engine_uct_init,
46 static struct engine *init_engine(enum engine_id engine, char *e_arg, struct board *b)
48 char *arg = e_arg? strdup(e_arg) : e_arg;
49 assert(engine < E_MAX);
50 struct engine *e = engine_init[engine](arg, b);
51 if (arg) free(arg);
52 return e;
55 static void done_engine(struct engine *e)
57 if (e->done) e->done(e);
58 if (e->data) free(e->data);
59 free(e);
62 static void usage(char *name)
64 fprintf(stderr, "Pachi version %s\n", PACHI_VERSION);
65 fprintf(stderr, "Usage: %s [-e random|replay|patternscan|montecarlo|uct]\n"
66 " [-d DEBUG_LEVEL] [-s RANDOM_SEED] [-t TIME_SETTINGS] [-u TEST_FILENAME]"
67 " [-g [HOST:]GTP_PORT] [-l [HOST:]LOG_PORT] [ENGINE_ARGS]\n", name);
70 bool engine_reset = false;
73 int main(int argc, char *argv[])
75 enum engine_id engine = E_UCT;
76 struct time_info ti_default = { .period = TT_NULL };
77 char *testfile = NULL;
78 char *gtp_port = NULL;
79 char *log_port = NULL;
80 int gtp_sock = -1;
82 seed = time(NULL) ^ getpid();
84 int opt;
85 while ((opt = getopt(argc, argv, "e:d:g:l:s:t:u:")) != -1) {
86 switch (opt) {
87 case 'e':
88 if (!strcasecmp(optarg, "random")) {
89 engine = E_RANDOM;
90 } else if (!strcasecmp(optarg, "patternscan")) {
91 engine = E_PATTERNSCAN;
92 } else if (!strcasecmp(optarg, "replay")) {
93 engine = E_REPLAY;
94 } else if (!strcasecmp(optarg, "montecarlo")) {
95 engine = E_MONTECARLO;
96 } else if (!strcasecmp(optarg, "uct")) {
97 engine = E_UCT;
98 } else {
99 fprintf(stderr, "%s: Invalid -e argument %s\n", argv[0], optarg);
100 exit(1);
102 break;
103 case 'd':
104 debug_level = atoi(optarg);
105 break;
106 case 'g':
107 gtp_port = strdup(optarg);
108 break;
109 case 'l':
110 log_port = strdup(optarg);
111 break;
112 case 's':
113 seed = atoi(optarg);
114 break;
115 case 't':
116 /* Time settings to follow; if specified,
117 * GTP time information is ignored. Useful
118 * e.g. when you want to force your bot to
119 * play weaker while giving the opponent
120 * reasonable time to play, or force play
121 * by number of simulations in timed games. */
122 /* Please see timeinfo.h:time_parse()
123 * description for syntax details. */
124 if (!time_parse(&ti_default, optarg)) {
125 fprintf(stderr, "%s: Invalid -t argument %s\n", argv[0], optarg);
126 exit(1);
128 ti_default.ignore_gtp = true;
129 assert(ti_default.period != TT_NULL);
130 break;
131 case 'u':
132 testfile = strdup(optarg);
133 break;
134 default: /* '?' */
135 usage(argv[0]);
136 exit(1);
140 if (log_port)
141 open_log_port(log_port);
143 fast_srandom(seed);
144 if (DEBUGL(0))
145 fprintf(stderr, "Random seed: %d\n", seed);
147 struct board *b = board_init();
148 struct time_info ti[S_MAX];
149 ti[S_BLACK] = ti_default;
150 ti[S_WHITE] = ti_default;
152 char *e_arg = NULL;
153 if (optind < argc)
154 e_arg = argv[optind];
155 struct engine *e = init_engine(engine, e_arg, b);
157 if (testfile) {
158 unittest(testfile);
159 return 0;
162 if (gtp_port) {
163 open_gtp_connection(&gtp_sock, gtp_port);
166 for (;;) {
167 char buf[4096];
168 while (fgets(buf, 4096, stdin)) {
169 if (DEBUGL(1))
170 fprintf(stderr, "IN: %s", buf);
171 gtp_parse(b, e, ti, buf);
172 if (engine_reset) {
173 if (!e->keep_on_clear) {
174 b->es = NULL;
175 done_engine(e);
176 e = init_engine(engine, e_arg, b);
177 ti[S_BLACK] = ti_default;
178 ti[S_WHITE] = ti_default;
180 engine_reset = false;
183 if (!gtp_port) break;
184 open_gtp_connection(&gtp_sock, gtp_port);
186 done_engine(e);
187 return 0;