Next: GTP command reference, Previous: The Metamachine, Up: GTP
The implementation of GTP in GNU Go is distributed over three files, interface/gtp.h, interface/gtp.c, and interface/play_gtp.c. The first two implement a small library of helper functions which can be used also by other programs. In the interest of promoting the GTP they are licensed with minimal restrictions (see GTP License). The actual GTP commands are implemented in play_gtp.c, which has knowledge about the engine internals.
To see how a simple but fairly typical command is implemented we look at
gtp_countlib()
(a GNU Go private extension command):
static int gtp_countlib(char *s) { int i, j; if (!gtp_decode_coord(s, &i, &j)) return gtp_failure("invalid coordinate"); if (BOARD(i, j) == EMPTY) return gtp_failure("vertex must not be empty"); return gtp_success("%d", countlib(POS(i, j))); }
The arguments to the command are passed in the string s
. In this
case we expect a vertex as argument and thus try to read it with
gtp_decode_coord()
from gtp.c.
A correctly formatted response should start with either `=' or `?', followed by the identity number (if one was sent), the actual result, and finally two consecutive newlines. It is important to get this formatting correct since the controller in the other end relies on it. Naturally the result itself cannot contain two consecutive newlines but it may be split over several lines by single newlines.
The easiest way to generate a correctly formatted response is with one
of the functions gtp_failure()
and gtp_success()
, assuming
that their formatted output does not end with a newline.
Sometimes the output is too complex for use with gtp_success, e.g. if
we want to print vertices, which gtp_success() does not
support. Then we have to fall back to the construction in e.g.
gtp_genmove()
:
static int gtp_genmove(char *s) { [...] gtp_start_response(GTP_SUCCESS); gtp_print_vertex(i, j); return gtp_finish_response(); }
Here gtp_start_response()
writes the equal sign and the identity
number while gtp_finish_response()
adds the final two newlines.
The next example is from gtp_list_commands()
:
static int gtp_list_commands(char *s) { int k; UNUSED(s); gtp_start_response(GTP_SUCCESS); for (k = 0; commands[k].name != NULL; k++) gtp_printf("%s\n", commands[k].name); gtp_printf("\n"); return GTP_OK; }
As we have said, the response should be finished with two newlines. Here we have to finish up the response ourselves since we already have one newline in place from the last command printed in the loop.
In order to add a new GTP command to GNU Go, the following pieces of code need to be inserted in play_gtp.c:
DECLARE
macro in the list
starting at line 68.
commands[]
array starting at line 200.
Useful helper functions in gtp.c/gtp.h are:
gtp_printf()
for basic formatted printing.
gtp_mprintf()
for printing with special format codes for
vertices and colors.
gtp_success()
and gtp_failure()
for simple responses.
gtp_start_response()
and gtp_end_response()
for more
complex responses.
gtp_print_vertex()
and gtp_print_vertices()
for
printing one or multiple vertices.
gtp_decode_color()
to read in a color from the command arguments.
gtp_decode_coord()
to read in a vertex from the command arguments.
gtp_decode_move()
to read in a move, i.e. color plus
vertex, from the command arguments.