www.delorie.com/gnu/docs/gnugo/gnugo_209.html   search  
 
Buy GNU books!


GNU Go Documentation

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

20.3 Protocol conventions

The GTP is currently unfinished and unstandardized. It is hoped that it will grow to fill the needs currently served by the GMP and perhaps other functions. As it is yet unstandardized, this section gives some general remarks which we hope will constrain its development. We also discuss how the GTP is implemented in GNU Go, for the benefit of anyone wishing to add new commands. Notice that the current set of GTP commands is a mix of generally useful ones and highly GNU Go specific ones. Only the former should be part of a standardized protocol while the latter should be private extensions.

The purpose of the protocol is machine-machine communication. It may be tempting to modify the protocol so that it becomes more comfortable for the human user, for example with an automatic showboard after every move. This is absolutely not the purpose of the protocol! Use the ascii interface instead if you're inclined to make such a change.

Newlines are implemented differently on different operating systems. On Unix, a newline is just a line feed LF (ascii \012). On DOS/Windows it is CRLF (\013\012). Thus whether GNU Go sends a carriage return with the line feed depends on which platform it is compiled for. The arbiter should silently discard carriage returns.

Applications using GTP should never have to guess about the basic structure of the responses, defined above. The basic construction for coding a GTP command can be found in gtp_countlib():

 
static int
gtp_countlib(char *s, int id)
{
  int i, j;
  if (!gtp_decode_coord(s, &i, &j))
    return gtp_failure(id, "invalid coordinate");

  if (p[i][j] == EMPTY)
    return gtp_failure(id, "vertex must not be empty");

  return gtp_success(id, "%d", countlib(POS(i, j)));
}

The functions gtp_failure() and gtp_success() automatically ensures the specified response format, assuming the strings they are printing do 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() doesn't support. Then we have to fall back to the construction in e.g. gtp_genmove_white():

 
static int
gtp_genmove_white(char *s, int id)
{
  int i, j;
  UNUSED(s);
  if (genmove(&i, &j, WHITE) >= 0)
    play_move(POS(i, j), WHITE);

  gtp_printid(id, GTP_SUCCESS);
  gtp_print_vertex(i, j);
  return gtp_finish_response();
}

Here gtp_printid() writes the equal sign and the request id while gtp_finish_response() adds the final two newlines. The next example is from gtp_influence():

 
  gtp_printid(id, GTP_SUCCESS);
  get_initial_influence(color, 1, white_influence,
			black_influence, influence_regions);
  print_influence(white_influence, black_influence, influence_regions);
  /* We already have one newline, thus can't use gtp_finish_response(). */
  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.

One problem that can be expected to be common is that an engine happens to finish its response with three (or more) rather than two consecutive newlines. This is an error by the engine that the controller can easily detect and ignore. Thus a well behaved engine should not send stray newlines, but should they appear the controller should ignore them. The opposite problem of an engine failing to properly finish its response with two newlines will result in deadlock. Don't do this mistake!

Although it doesn't suffice in more complex cases, gtp_success() is by far the most convenient construction when it does. For example, the function gtp_report_uncertainty takes a single argument which is expected to be "on" or "off", after which it sets the value of report_uncertainty, a variable which affects the form of future GTP responses, reports success, and exits. The function is coded thus:

 
static int
gtp_report_uncertainty(char *s, int id)
{
  if (!strncmp(s, "on", 2)) {
    report_uncertainty = 1;
    return gtp_success(id, "");
  }
  if (!strncmp(s, "off", 3)) {
    report_uncertainty = 0;
    return gtp_success(id, "");
  }
  return gtp_failure(id, "invalid argument");
}


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

  webmaster     delorie software   privacy  
  Copyright 2003   by The Free Software Foundation     Updated Jun 2003