My Project
gtp.c
Go to the documentation of this file.
1
11#include "options.h"
12#include "search.h"
13#include "util.h"
14#include "ui.h"
15#include "play.h"
16
17#include <ctype.h>
18
19static Log gtp_log[1];
20
21static void gtp_observer(Result *result)
22{
23 if (log_is_open(gtp_log)) {
24 result_print(result, gtp_log->f);
25 putc('\n', gtp_log->f);
26 }
27}
28
29/*
30 * @brief Preprocess a line according to GTP2.
31 *
32 * @param line string to process
33 */
34void gtp_preprocess(char *line)
35{
36 char *s;
37
38 for (s = line; *line; ++line) {
39 if (*line == '\t') *line = ' ';
40 if (*line == '#') break;
41 if (*line < 32 && *line != '\n') continue;
42
43 *s++ = *line;
44 }
45 *s = '\0';
46}
47
48static void gtp_send(const char *s, int id, bool has_id)
49{
50 if (has_id) printf("= %d ", id);
51 else printf("= ");
52 puts(s);
53 putchar('\n'); fflush(stdout);
54
55 log_print(gtp_log, "sent> \"%s\"\n", s);
56}
57
58static void gtp_fail(const char *s, int id, bool has_id)
59{
60 if (has_id) printf("? %d ", id);
61 else printf("? ");
62 puts(s);
63 putchar('\n'); fflush(stdout);
64
65 log_print(gtp_log, "error> \"%s\"\n", s);
66}
67
68static char *gtp_parse_color(char *s, int *color)
69{
70 char word[8];
71
72 s = parse_word(s, word, 7);
73
74 if (strcmp(word, "black") == 0) {
75 *color = BLACK;
76 } else if (strcmp(word, "b") == 0) {
77 *color = BLACK;
78 } else if (strcmp(word, "white") == 0) {
79 *color = WHITE;
80 } else if (strcmp(word, "w") == 0) {
81 *color = WHITE;
82 } else {
83 *color = EMPTY;
84 }
85
86 return s;
87}
88
93void ui_init_gtp(UI *ui)
94{
95 Play *play = ui->play;
96
98 options.info = 0;
99
100 play_init(play, ui->book);
101 ui->book->search = play->search;
103 play->search->id = 1;
105 ui->mode = 3;
106 play->type = ui->type;
107
109}
110
116{
118 book_free(ui->book);
119 play_free(ui->play);
121}
122
128{
129 char *cmd = NULL, *param = NULL, *move;
130 Play *play = ui->play;
131 int id = 0;
132 bool has_id = false;
133 int komi, color, size;
134 int byo_yomi_time = 0, byo_yomi_stone = 0, main_time = 315576000;
135
136 // loop forever
137 for (;;) {
138 errno = 0;
139
140 if (log_is_open(gtp_log)) {
141 play_print(play, gtp_log->f);
142 }
143
144 ui_event_wait(ui, &cmd, &param);
145
146 log_print(gtp_log, "received: \"%s %s\"\n", cmd, param);
147
148 if (isdigit(*cmd)) {
149 has_id = true;
150 parse_int(cmd, &id);
151 parse_command(param, cmd, param, strlen(param));
152 }
153
154 if (*cmd == '\0') {
155
156 } else if (strcmp(cmd, "protocol_version") == 0) {
157 gtp_send("2", id, has_id);
158
159 } else if (strcmp(cmd, "name") == 0) {
160 gtp_send("Edax", id, has_id);
161
162 } else if (strcmp(cmd, "version") == 0) {
163 gtp_send(VERSION_STRING, id, has_id);
164
165 } else if (strcmp(cmd, "known_command") == 0) {
166 if (strcmp(param, "protocol_version") == 0 ||
167 strcmp(param, "name") == 0 ||
168 strcmp(param, "version") == 0 ||
169 strcmp(param, "known_command") == 0 ||
170 strcmp(param, "list_commands") == 0 ||
171 strcmp(param, "quit") == 0 ||
172 strcmp(param, "boardsize") == 0 ||
173 strcmp(param, "clear_board") == 0 ||
174 strcmp(param, "komi") == 0 ||
175 strcmp(param, "play") == 0 ||
176 strcmp(param, "genmove") == 0 ||
177 strcmp(param, "undo") == 0 ||
178 strcmp(param, "time_settings") == 0 ||
179 strcmp(param, "time_left") == 0 ||
180 strcmp(param, "set_game") == 0 ||
181 strcmp(param, "list_games") == 0 ||
182 strcmp(param, "loadsgf") == 0 ||
183 strcmp(param, "reg_genmove") == 0 ||
184 strcmp(param, "showboard") == 0) gtp_send("true", id, has_id);
185 else gtp_send("false", id, has_id);
186
187 } else if (strcmp(cmd, "list_commands") == 0) {
188 gtp_send("protocol_version\nname\nversion\nknown_command\nlist_commands\n"
189 "quit\nboardsize\nclear_board\nkomi\nplay\ngenmove\nundo\n"
190 "time_settings\ntime_left\nset_game\nlist_games\n"
191 "loadsgf\nreg_genmove\nshowboard", id, has_id);
192
193 } else if (strcmp(cmd, "quit") == 0 || strcmp(cmd, "eof") == 0) {
194 gtp_send("", id, has_id);
195 free(cmd); free(param);
196 return;
197
198 } else if (strcmp(cmd, "boardsize") == 0) {
199 size = string_to_int(param, 0);
200 if (size != 8) gtp_fail("unacceptable size", id, has_id);
201 else gtp_send("", id, has_id);
202
203 } else if (strcmp(cmd, "clear_board") == 0) {
204 play_new(play);
205 gtp_send("", id, has_id);
206
207 } else if (strcmp(cmd, "komi") == 0) {
208 komi = string_to_int(param, 0);
209 gtp_send("", id, has_id);
210 (void) komi; // do nothing of it....
211
212 } else if (strcmp(cmd, "play") == 0) {
213 move = gtp_parse_color(param, &color);
214 if (color == EMPTY) {
215 gtp_fail("syntax error (wrong or missing color)", id, has_id);
216 continue;
217 } else if (color != play->player) {
218 if (play_must_pass(play)) {
219 play_move(play, PASS);
220 } else {
221 gtp_fail("wrong color", has_id, id);
222 continue;
223 }
224 }
225
226 if (play_user_move(play, move)) {
227 gtp_send("", id, has_id);
228 } else {
229 gtp_fail("illegal move", id, has_id);
230 }
231
232 } else if (strcmp(cmd, "genmove") == 0) {
233 char m[4];
234 gtp_parse_color(param, &color);
235 if (color == EMPTY) {
236 gtp_fail("syntax error (wrong or missing color)", id, has_id);
237 continue;
238 } else if (color != play->player) {
239 if (play_must_pass(play)) {
240 play_move(play, PASS);
241 } else {
242 gtp_fail("wrong color", has_id, id);
243 continue;
244 }
245 }
246 play_go(play, true);
247 if (play_get_last_move(play)->x == PASS) gtp_send("pass", id, has_id);
248 else gtp_send(move_to_string(play_get_last_move(play)->x, WHITE, m), id, has_id);
249
250 // optional GTP commands but needed or supported by Quarry
251 } else if (strcmp(cmd, "undo") == 0) {
252 if (play->i_game <= 0) {
253 gtp_fail("cannot undo", has_id, id);
254 } else {
255 play_undo(play);
256 gtp_send("", id, has_id);
257 }
258
259 } else if (strcmp(cmd, "time_settings") == 0) {
260 char *s;
261 s = parse_int(param, &main_time);
262 s = parse_int(s, &byo_yomi_time);
263 s = parse_int(s, &byo_yomi_stone);
264 if (byo_yomi_stone > 0) {
266 } else {
268 }
269 options.time = 1000 * main_time;
270 gtp_send("", id, has_id);
271
272 } else if (strcmp(cmd, "time_left") == 0) {
273 char *s;
274 double t = 0.0;
275 int n = 0;
276 s = gtp_parse_color(param, &color);
277 s = parse_real(s, &t); t *= 1000;
278 s = parse_int(s, &n);
279 options.level = 60;
280 if (options.play_type == EDAX_TIME_PER_MOVE) {// time_per_move ?
281 if (n == 0) play->time[color].left = (t + byo_yomi_time * 1000) / byo_yomi_stone;
282 else play->time[color].left = t / n;
283 } else { // time_per_game
284 play->time[color].left = t;
285 }
286 gtp_send("", id, has_id);
287
288 } else if (strcmp(cmd, "set_game") == 0) {
289 if (strcmp(param, "Othello") == 0) gtp_send("", id, has_id);
290 else gtp_fail("unsupported game", id, has_id);
291
292 } else if (strcmp(cmd, "list_games") == 0) {
293 gtp_send("Othello", id, has_id);
294
295 // regression subset
296 } else if (strcmp(cmd, "loadsgf") == 0) {
297 if (play_load(play, param)) {
298 gtp_send("", id, has_id);
299 } else {
300 gtp_fail(play->error_message, id, has_id);
301 }
302
303 } else if (strcmp(cmd, "reg_genmove") == 0) {
304 char m[4];
305 gtp_parse_color(param, &color);
306 if (color == EMPTY) {
307 gtp_fail("syntax error (wrong or missing color)", id, has_id);
308 continue;
309 } else if (color != play->player) {
310 if (play_must_pass(play)) {
311 play_move(play, PASS);
312 } else {
313 gtp_fail("wrong color", has_id, id);
314 continue;
315 }
316 }
317 play_go(play, false);
318 if (play_get_last_move(play)->x == PASS) gtp_send("pass", id, has_id);
319 else gtp_send(move_to_string(play_get_last_move(play)->x, WHITE, m), id, has_id);
320
321 // optional commands
322 } else if (strcmp(cmd, "showboard") == 0) {
323 printf("= ");
324 if (has_id) printf("%d\n", id);
325 board_print(play->board, play->player, stdout);
326 putchar('\n'); fflush(stdout);
327
328 // error: unknown message
329 } else {
330 gtp_fail("unknown command", id, has_id);
331 }
332 }
333}
334
335
void board_print(const Board *board, const int player, FILE *f)
Print out the board.
Definition board.c:1230
void book_free(Book *book)
Free resources used by the opening book.
Definition book.c:1422
void book_save(Book *book, const char *file)
Save an opening book.
Definition book.c:1622
void book_load(Book *book, const char *file)
Load the opening book.
Definition book.c:1471
@ PASS
Definition const.h:37
#define VERSION_STRING
Definition const.h:88
@ WHITE
Definition const.h:43
@ EMPTY
Definition const.h:44
@ BLACK
Definition const.h:42
void gtp_preprocess(char *line)
Definition gtp.c:34
static char * gtp_parse_color(char *s, int *color)
Definition gtp.c:68
void ui_init_gtp(UI *ui)
initialize edax protocol
Definition gtp.c:93
static void gtp_fail(const char *s, int id, bool has_id)
Definition gtp.c:58
static Log gtp_log[1]
Definition gtp.c:19
void ui_loop_gtp(UI *ui)
Loop event.
Definition gtp.c:127
static void gtp_observer(Result *result)
Definition gtp.c:21
static void gtp_send(const char *s, int id, bool has_id)
Definition gtp.c:48
void ui_free_gtp(UI *ui)
free resources used by edax protocol
Definition gtp.c:115
char * move_to_string(const int x, const int player, char *s)
Print out a move.
Definition move.c:76
Options options
Definition options.c:22
@ EDAX_TIME_PER_GAME
Definition options.h:19
@ EDAX_TIME_PER_MOVE
Definition options.h:20
bool play_must_pass(Play *play)
Check if player must pass.
Definition play.c:202
void play_print(Play *play, FILE *f)
Print the game state.
Definition play.c:1225
bool play_move(Play *play, int x)
Play a move.
Definition play.c:889
void play_new(Play *play)
Start a new game.
Definition play.c:62
void play_init(Play *play, Book *book)
Initialization.
Definition play.c:27
bool play_user_move(Play *play, const char *string)
Play a user move.
Definition play.c:909
Move * play_get_last_move(Play *play)
Get the last played move.
Definition play.c:927
bool play_load(Play *play, const char *file)
Load a saved game.
Definition play.c:84
void play_undo(Play *play)
Undo a move.
Definition play.c:779
void play_go(Play *play, const bool update)
Start thinking.
Definition play.c:214
void play_free(Play *play)
Free resources.
Definition play.c:52
Edax play control - header file.
void result_print(Result *result, FILE *f)
Print the current search result.
Definition search.c:1106
void search_set_observer(Search *search, void(*observer)(Result *))
set observer.
Definition search.c:1095
bool need_saving
Definition book.h:47
Search * search
Definition book.h:49
LogFile.
Definition util.h:423
FILE * f
Definition util.h:424
PlayType play_type
Definition options.h:42
int level
Definition options.h:40
char * ui_log_file
Definition options.h:78
long long time
Definition options.h:41
bool info
Definition options.h:36
char * book_file
Definition options.h:59
int verbosity
Definition options.h:32
Definition play.h:25
int player
Definition play.h:32
Board board[1]
Definition play.h:26
long long left
Definition play.h:42
struct Play::@21 time[2]
Search search[1]
Definition play.h:28
int type
Definition play.h:31
char error_message[PLAY_MESSAGE_MAX_LENGTH]
Definition play.h:59
int i_game
Definition play.h:35
Definition search.h:41
int id
Definition search.h:101
Definition ui.h:31
int type
Definition ui.h:36
Play play[2]
Definition ui.h:32
Book book[1]
Definition ui.h:33
int mode
Definition ui.h:37
void ui_event_wait(UI *ui, char **cmd, char **param)
Wait input.
Definition ui.c:147
User interface header.
char * parse_int(const char *string, int *result)
Parse an integer.
Definition util.c:761
char * parse_real(const char *string, double *result)
Parse a real number (as a double floating point).
Definition util.c:796
int string_to_int(const char *s, const int default_value)
Convert a string into an integer.
Definition util.c:457
char * parse_command(const char *string, char *cmd, char *param, const unsigned int size)
Parse a command.
Definition util.c:867
char * parse_word(const char *string, char *word, unsigned int n)
Parse a word.
Definition util.c:562
Miscellaneous utilities header.
#define log_close(l)
Close an opened log file.
Definition util.h:435
#define log_print(l,...)
Print into the log file.
Definition util.h:442
#define log_open(l, file)
open a log file if allowed.
Definition util.h:429
#define log_is_open(l)
Check if the log stream can be used.
Definition util.h:448