UCT: Adjust default hint rates slightly
[pachi/peepo.git] / gtp.c
blob54a50b8cd2f2029fac6930517c2d31abcc18f048
1 #include <ctype.h>
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
7 #include "board.h"
8 #include "debug.h"
9 #include "engine.h"
10 #include "gtp.h"
12 void
13 gtp_prefix(char prefix, int id)
15 if (id >= 0)
16 printf("%c%d ", prefix, id);
17 else
18 printf("%c ", prefix);
21 void
22 gtp_output(char prefix, int id, va_list params)
24 gtp_prefix(prefix, id);
25 char *s;
26 while ((s = va_arg(params, char *))) {
27 fputs(s, stdout);
29 putchar('\n'); putchar('\n');
30 fflush(stdout);
33 void
34 gtp_reply(int id, ...)
36 va_list params;
37 va_start(params, id);
38 gtp_output('=', id, params);
39 va_end(params);
42 void
43 gtp_error(int id, ...)
45 va_list params;
46 va_start(params, id);
47 gtp_output('?', id, params);
48 va_end(params);
52 /* XXX: THIS IS TOTALLY INSECURE!!!!
53 * Even basic input checking is missing. */
55 void
56 gtp_parse(struct board *board, struct engine *engine, char *buf)
58 #define next_tok(to_) \
59 to_ = next; \
60 next = next + strcspn(next, " \t\r\n"); \
61 if (*next) { \
62 *next = 0; next++; \
63 next += strspn(next, " \t\r\n"); \
66 if (strchr(buf, '#'))
67 *strchr(buf, '#') = 0;
69 char *cmd, *next = buf;
70 next_tok(cmd);
72 int id = -1;
73 if (isdigit(*cmd)) {
74 id = atoi(cmd);
75 next_tok(cmd);
78 if (!*cmd)
79 return;
81 if (!strcasecmp(cmd, "protocol_version")) {
82 gtp_reply(id, "2", NULL);
84 } else if (!strcasecmp(cmd, "name")) {
85 /* KGS hack */
86 gtp_reply(id, "Pachi ", engine->name, ": ", engine->comment, NULL);
88 } else if (!strcasecmp(cmd, "version")) {
89 gtp_reply(id, NULL);
91 /* TODO: known_command */
93 } else if (!strcasecmp(cmd, "list_commands")) {
94 gtp_reply(id, "protocol_version\nname\nversion\nlist_commands\nquit\nboardsize\nclear_board\nkomi\nplay\ngenmove\nset_free_handicap\nplace_free_handicap", NULL);
96 } else if (!strcasecmp(cmd, "quit")) {
97 gtp_reply(id, NULL);
98 exit(0);
100 } else if (!strcasecmp(cmd, "boardsize")) {
101 char *arg;
102 next_tok(arg);
103 board_resize(board, atoi(arg));
105 gtp_reply(id, NULL);
107 } else if (!strcasecmp(cmd, "clear_board")) {
108 board_clear(board);
109 gtp_reply(id, NULL);
111 } else if (!strcasecmp(cmd, "komi")) {
112 char *arg;
113 next_tok(arg);
114 sscanf(arg, "%f", &board->komi);
116 gtp_reply(id, NULL);
118 } else if (!strcasecmp(cmd, "play")) {
119 struct move m;
121 char *arg;
122 next_tok(arg);
123 m.color = str2stone(arg);
124 next_tok(arg);
125 coord_t *c = str2coord(arg, board->size);
126 m.coord = *c; coord_done(c);
128 if (DEBUGL(1))
129 fprintf(stderr, "got move %d,%d,%d\n", m.color, coord_x(m.coord, board), coord_y(m.coord, board));
130 if (board_play(board, &m) < 0) {
131 if (DEBUGL(0))
132 fprintf(stderr, "! ILLEGAL MOVE %d,%d,%d\n", m.color, coord_x(m.coord, board), coord_y(m.coord, board));
133 gtp_error(id, "illegal move", NULL);
134 } else {
135 gtp_reply(id, NULL);
138 } else if (!strcasecmp(cmd, "genmove")) {
139 char *arg;
140 next_tok(arg);
141 enum stone color = str2stone(arg);
142 coord_t *c = engine->genmove(engine, board, color);
143 struct move m = { *c, color };
144 board_play(board, &m);
145 char *str = coord2str(*c, board);
146 if (DEBUGL(1))
147 fprintf(stderr, "playing move %s\n", str);
148 gtp_reply(id, str, NULL);
149 free(str); coord_done(c);
151 } else if (!strcasecmp(cmd, "set_free_handicap")) {
152 struct move m;
153 m.color = S_BLACK;
155 char *arg;
156 next_tok(arg);
157 do {
158 coord_t *c = str2coord(arg, board->size);
159 m.coord = *c; coord_done(c);
160 if (DEBUGL(1))
161 fprintf(stderr, "setting handicap %d,%d\n", coord_x(m.coord, board), coord_y(m.coord, board));
163 if (board_play(board, &m) < 0) {
164 if (DEBUGL(0))
165 fprintf(stderr, "! ILLEGAL MOVE %d,%d,%d\n", m.color, coord_x(m.coord, board), coord_y(m.coord, board));
166 gtp_error(id, "illegal move", NULL);
168 next_tok(arg);
169 } while (*arg);
170 gtp_reply(id, NULL);
172 /* TODO: Engine should choose free handicap; however, it tends to take
173 * overly long to think it all out, and unless it's clever its
174 * handicap stones won't be of much help. ;-) */
175 } else if (!strcasecmp(cmd, "place_free_handicap")
176 || !strcasecmp(cmd, "fixed_handicap")) {
177 char *arg;
178 next_tok(arg);
179 int stones = atoi(arg);
181 gtp_prefix('=', id);
182 board_handicap(board, stones, stdout);
183 printf("\n\n"); fflush(stdout);
185 } else if (!strcasecmp(cmd, "final_score")) {
186 float score = board_official_score(board);
187 char str[64];
188 if (DEBUGL(1))
189 fprintf(stderr, "counted score %.1f\n", score);
190 if (score == 0) {
191 gtp_reply(id, "0", NULL);
192 } else if (score > 0) {
193 snprintf(str, 64, "W+%.1f", score);
194 gtp_reply(id, str, NULL);
195 } else {
196 snprintf(str, 64, "B+%.1f", -score);
197 gtp_reply(id, str, NULL);
200 } else {
201 gtp_error(id, "unknown command", NULL);
204 #undef next_tok