This patch to GNU Go 2.6 allows it to play with the Go Text Protocol.
diff -u -N -r -x *\.orig -x *\.info* ./configure.in ../gnugo-2.6.1/gnugo-2.6.1/configure.in
--- ./configure.in Sun Feb 13 03:02:11 2000
+++ ../gnugo-2.6.1/gnugo-2.6.1/configure.in Sat Aug 4 00:10:58 2001
AC_PREREQ(2.12)dnl dnl Minimum Autoconf version required.
dnl this defines VERSION and PACKAGE
-AM_INIT_AUTOMAKE([gnugo], [2.6])
+AM_INIT_AUTOMAKE([gnugo], [2.6.1])
GNU_PACKAGE="GNU $PACKAGE"
AC_DEFINE_UNQUOTED(GNU_PACKAGE, "$GNU_PACKAGE")
diff -u -N -r -x *\.orig -x *\.info* ./engine/liberty.h ../gnugo-2.6.1/gnugo-2.6.1/engine/liberty.h
--- ./engine/liberty.h Tue Feb 8 19:59:07 2000
+++ ../gnugo-2.6.1/gnugo-2.6.1/engine/liberty.h Fri Aug 10 16:20:09 2001
#define NONE 6 /* for use with is_computer_player */
void restore_state(void);
int dragon_status(int i, int j);
void change_dragon_status(int x, int y, int status);
-void who_wins(int color, float fkomi, FILE* stdwhat);
+void who_wins(int color, float fkomi, FILE * stdwhat);
/* data concerning a dragon. A copy is kept at each stone of the string */
void find_connections(void);
+float estimate_score(float komi);
/* various different strategies for finding a move */
diff -u -N -r -x *\.orig -x *\.info* ./engine/moyo.c ../gnugo-2.6.1/gnugo-2.6.1/engine/moyo.c
--- ./engine/moyo.c Tue Feb 8 19:59:07 2000
+++ ../gnugo-2.6.1/gnugo-2.6.1/engine/moyo.c Fri Aug 10 16:21:10 2001
fprintf(stdwhat, "%c says \"I lost!\"\n", (color == WHITE) ? 'W' : 'B');
+estimate_score(float fkomi)
+ white_score = (float) terri_eval[WHITE] + fkomi;
+ black_score = (float) terri_eval[BLACK];
+ result = white_score - black_score;
diff -u -N -r -x *\.orig -x *\.info* ./engine/reading.c ../gnugo-2.6.1/gnugo-2.6.1/engine/reading.c
--- ./engine/reading.c Tue Feb 8 19:59:07 2000
+++ ../gnugo-2.6.1/gnugo-2.6.1/engine/reading.c Sat Aug 4 00:10:58 2001
- if (stackp == 0 && safe_move_cache_when[i][j][color==BLACK] == movenum)
- return safe_move_cache[i][j][color==BLACK];
if (trymove(i, j, color, "safe_move", -1, -1)) {
int acode = attack(i, j, NULL, NULL);
- safe_move_cache_when[i][j][color==BLACK] = movenum;
- safe_move_cache[i][j][color==BLACK] = safe;
diff -u -N -r -x *\.orig -x *\.info* ./engine/sethand.c ../gnugo-2.6.1/gnugo-2.6.1/engine/sethand.c
--- ./engine/sethand.c Sat Feb 5 05:59:53 2000
+++ ../gnugo-2.6.1/gnugo-2.6.1/engine/sethand.c Sat Aug 4 00:10:58 2001
- sgfAddPropertyInt(sgf_root,"HA",handicap);
+ sgfAddPropertyInt(sgf_root,"HA",handicap);
/* special cases: 5 and 7 */
if (handicap == 5 || handicap == 7) {
- sgfAddStone(sgf_root,BLACK,mid,mid);
- sgf_set_stone(mid,mid,BLACK);
+ sgfAddStone(sgf_root,BLACK,mid,mid);
+ sgf_set_stone(mid,mid,BLACK);
for (x=0; x<handicap; ++x) {
if ( j < 0) j += board_size-1;
- sgfAddStone(sgf_root,BLACK,i,j);
- sgf_set_stone(i,j,BLACK);
+ sgfAddStone(sgf_root,BLACK,i,j);
+ sgf_set_stone(i,j,BLACK);
diff -u -N -r -x *\.orig -x *\.info* ./engine/utils.c ../gnugo-2.6.1/gnugo-2.6.1/engine/utils.c
--- ./engine/utils.c Tue Feb 8 19:59:07 2000
+++ ../gnugo-2.6.1/gnugo-2.6.1/engine/utils.c Sat Aug 4 00:10:58 2001
char *s = va_arg(ap, char*);
- assert( (int)*s >= board_size ); /* in case %s used in place of %m */
diff -u -N -r -x *\.orig -x *\.info* ./interface/Makefile.am ../gnugo-2.6.1/gnugo-2.6.1/interface/Makefile.am
--- ./interface/Makefile.am Thu Feb 3 20:48:50 2000
+++ ../gnugo-2.6.1/gnugo-2.6.1/interface/Makefile.am Sat Aug 4 00:10:58 2001
AIXOPTS=-O -qmaxmem=16384 -qro -qroconst -qinfo
diff -u -N -r -x *\.orig -x *\.info* ./interface/Makefile.in ../gnugo-2.6.1/gnugo-2.6.1/interface/Makefile.in
--- ./interface/Makefile.in Mon Feb 14 07:10:44 2000
+++ ../gnugo-2.6.1/gnugo-2.6.1/interface/Makefile.in Tue Aug 14 01:17:57 2001
LDADD = ../engine/libengine.a ../patterns/libpatterns.a ../sgf/libsgf.a ../utils/libutils.a
-gnugo_SOURCES = main.c interface.c play_ascii.c play_gmp.c play_solo.c play_test.c gmp.c
+gnugo_SOURCES = main.c interface.c play_ascii.c play_gmp.c play_solo.c play_test.c play_gtp.c gmp.c gtp.c gtp.h
AIXOPTS = -O -qmaxmem=16384 -qro -qroconst -qinfo
gnugo_OBJECTS = main.o interface.o play_ascii.o play_gmp.o play_solo.o \
+play_test.o play_gtp.o gmp.o gtp.o
gnugo_DEPENDENCIES = ../engine/libengine.a ../patterns/libpatterns.a \
../sgf/libsgf.a ../utils/libutils.a
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
SOURCES = $(gnugo_SOURCES)
OBJECTS = $(gnugo_OBJECTS)
gmp.o: gmp.c ../config.h gmp.h
interface.o: interface.c ../config.h ../sgf/sgf.h ../engine/liberty.h \
../engine/hash.h interface.h ../engine/main.h
main.o: main.c ../config.h ../utils/getopt.h ../engine/main.h \
play_gmp.o: play_gmp.c interface.h ../engine/liberty.h ../config.h \
../engine/hash.h gmp.h ../sgf/sgf.h ../sgf/ttsgf.h \
../sgf/ttsgf_write.h ../sgf/sgfana.h
+play_gtp.o: play_gtp.c ../config.h ../engine/liberty.h ../engine/hash.h \
play_solo.o: play_solo.c ../config.h interface.h ../engine/liberty.h \
../engine/hash.h ../sgf/sgf.h ../sgf/sgf_properties.h \
../sgf/ttsgf_read.h ../sgf/ttsgf.h ../sgf/sgfana.h
diff -u -N -r -x *\.orig -x *\.info* ./interface/gtp.c ../gnugo-2.6.1/gnugo-2.6.1/interface/gtp.c
--- ./interface/gtp.c Thu Jan 1 00:00:00 1970
+++ ../gnugo-2.6.1/gnugo-2.6.1/interface/gtp.c Tue Aug 14 00:50:36 2001
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see *
+ * http://www.gnu.org/software/gnugo/ for more information. *
+ * To facilitate development of the Go Text Protocol, the two *
+ * files gtp.c and gtp.h are licensed under less restrictive *
+ * terms than the rest of GNU Go. *
+ * Copyright 2001 by the Free Software Foundation. *
+ * Permission is hereby granted, free of charge, to any person *
+ * obtaining a copy of this file gtp.c, to deal in the Software *
+ * without restriction, including without limitation the rights *
+ * to use, copy, modify, merge, publish, distribute, and/or *
+ * sell copies of the Software, and to permit persons to whom *
+ * the Software is furnished to do so, provided that the above *
+ * copyright notice(s) and this permission notice appear in all *
+ * copies of the Software and that both the above copyright *
+ * notice(s) and this permission notice appear in supporting *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY *
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE *
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR *
+ * PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO *
+ * EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS *
+ * NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR *
+ * CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING *
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF *
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT *
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS *
+ * Except as contained in this notice, the name of a copyright *
+ * holder shall not be used in advertising or otherwise to *
+ * promote the sale, use or other dealings in this Software *
+ * without prior written authorization of the copyright holder. *
+\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* These are copied from gnugo.h. We don't include this file in order
+ * to remain as independent as possible of GNU Go internals.
+/* We need to keep track of the board size in order to be able to
+ * convert between coordinate descriptions. We could also have passed
+ * the board size in all calls needing it, but that would be
+ * unnecessarily inconvenient.
+static int gtp_boardsize = -1;
+/* Read stdin linewise and interpret as GTP commands. */
+gtp_main_loop(struct gtp_command commands[])
+ char line[GTP_BUFSIZE];
+ char command[GTP_BUFSIZE];
+ while (status == GTP_OK) {
+ /* Read a line from stdin. */
+ if (!fgets(line, GTP_BUFSIZE, stdin))
+ break; /* EOF or some error */
+ if ((p = strchr(line, '#')) != NULL)
+ /* Look for an identification number. */
+ if (sscanf(p, "%d%n", &id, &n) == 1)
+ id = -1; /* No identification number. */
+ /* Look for command name. */
+ if (sscanf(p, " %s %n", command, &n) < 1)
+ continue; /* Whitespace only on this line, ignore. */
+ /* Search the list of commands and call the corresponding function
+ for (i = 0; commands[i].name != NULL; i++) {
+ if (strcmp(command, commands[i].name) == 0) {
+ status = (*commands[i].function)(p, id);
+ if (commands[i].name == NULL)
+ gtp_failure(id, "unknown command: '%s'", command);
+ if (status == GTP_FATAL)
+/* Set the board size used in coordinate conversions. */
+gtp_internal_set_boardsize(int size)
+ * This function works like printf, except that it only understands
+ * very few of the standard formats, to be precise %c, %d, %f, %s.
+ * But it also accepts %m, which takes two integers and writes a move,
+ * and %C, which takes a color value and writes a color string.
+gtp_mprintf(const char *fmt, ...)
+ for ( ; *fmt ; ++fmt ) {
+ /* rules of promotion => passed as int, not char */
+ int c = va_arg(ap, int);
+ int d = va_arg(ap, int);
+ fprintf(stdout, "%d", d);
+ double f = va_arg(ap, double); /* passed as double, not float */
+ fprintf(stdout, "%f", f);
+ char *s = va_arg(ap, char*);
+ int m = va_arg(ap, int);
+ int n = va_arg(ap, int);
+ if (m == -1 && n == -1)
+ else if ((m<0) || (n<0) || (m>=gtp_boardsize) || (n>=gtp_boardsize))
+ fprintf(stdout, "%c%d", 'A' + n + (n >= 8), gtp_boardsize - m);
+ int color = va_arg(ap, int);
+ fputs("white", stdout);
+ else if (color == BLACK)
+ fputs("black", stdout);
+ fputs("empty", stdout);
+ fprintf(stdout, "\n\nUnknown format character '%c'\n", *fmt);
+/* This currently works exactly like printf. */
+gtp_printf(const char *format, ...)
+ vfprintf(stdout, format, ap);
+/* Write success or failure indication plus identity number if one was
+gtp_printid(int id, int status)
+ if (status == GTP_SUCCESS)
+/* Finish a GTP response by writing a double newline and returning GTP_OK. */
+/* Write a full success response. Except for the id number, the call
+ * is just like one to printf.
+gtp_success(int id, const char *format, ...)
+ gtp_printid(id, GTP_SUCCESS);
+ vfprintf(stdout, format, ap);
+ return gtp_finish_response();
+/* Write a full failure response. The call is identical to gtp_success. */
+gtp_failure(int id, const char *format, ...)
+ gtp_printid(id, GTP_FAILURE);
+ vfprintf(stdout, format, ap);
+ return gtp_finish_response();
+/* Write a panic message. */
+ gtp_printf("! panic\n\n");
+/* Convert a string describing a color, "b", "black", "w", or "white",
+ * to GNU Go's integer representation of colors. Return the number of
+ * characters read from the string s.
+gtp_decode_color(char *s, int *color)
+ assert(gtp_boardsize > 0);
+ if (sscanf(s, "%6s%n", color_string, &n) != 1)
+ for (i = 0; i < (int) strlen(color_string); i++)
+ color_string[i] = tolower((int) color_string[i]);
+ if (strcmp(color_string, "b") == 0
+ || strcmp(color_string, "black") == 0)
+ else if (strcmp(color_string, "w") == 0
+ || strcmp(color_string, "white") == 0)
+/* Convert an intersection given by a string to two coordinates
+ * according to GNU Go's convention. Return the number of characters
+ * read from the string s.
+gtp_decode_coord(char *s, int *i, int *j)
+ assert(gtp_boardsize > 0);
+ if (sscanf(s, " %c%d%n", &column, &row, &n) != 2)
+ if (tolower((int) column) == 'i')
+ *j = tolower((int) column) - 'a';
+ if (tolower((int) column) > 'i')
+ *i = gtp_boardsize - row;
+ if (*i < 0 || *i >= gtp_boardsize || *j < 0 || *j >= gtp_boardsize)
+/* Convert a move, i.e. "b" or "w" followed by a vertex to a color and
+ * coordinates. Return the number of characters read from the string
+gtp_decode_move(char *s, int *color, int *i, int *j)
+ assert(gtp_boardsize > 0);
+ n1 = gtp_decode_color(s, color);
+ n2 = gtp_decode_coord(s + n1, i, j);
+/* This a bubble sort. Given the expected size of the sets to
+ * sort, it's probably not worth the overhead to set up a call to
+sort_moves(int n, int movei[], int movej[])
+ for (b = n-1; b > 0; b--) {
+ for (a = 0; a < b; a++) {
+ if (movei[a] > movei[b]
+ || (movei[a] == movei[b] && movej[a] > movej[b])) {
+/* Write a number of space separated vertices. The moves are sorted
+ * before being written.
+gtp_print_vertices(int n, int movei[], int movej[])
+ assert(gtp_boardsize > 0);
+ sort_moves(n, movei, movej);
+ for (k = 0; k < n; k++) {
+ if ((movei[k] == -1 && movej[k] == -1)
+ || (movei[k] == gtp_boardsize && movej[k] == gtp_boardsize))
+ else if (movei[k] < 0 || movei[k] >= gtp_boardsize
+ || movej[k] < 0 || movej[k] >= gtp_boardsize) {
+ gtp_printf("?? %d %d", movei[k], movej[k]);
+ gtp_printf("%c%d", 'A' + movej[k] + (movej[k] >= 8),
+ gtp_boardsize - movei[k]);
+/* Write a single move. */
+gtp_print_vertex(int i, int j)
+ gtp_print_vertices(1, &i, &j);
diff -u -N -r -x *\.orig -x *\.info* ./interface/gtp.h ../gnugo-2.6.1/gnugo-2.6.1/interface/gtp.h
--- ./interface/gtp.h Thu Jan 1 00:00:00 1970
+++ ../gnugo-2.6.1/gnugo-2.6.1/interface/gtp.h Sat Aug 4 00:10:58 2001
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see *
+ * http://www.gnu.org/software/gnugo/ for more information. *
+ * To facilitate development of the Go Text Protocol, the two *
+ * files gtp.c and gtp.h are licensed under less restrictive *
+ * terms than the rest of GNU Go. *
+ * Copyright 2001 by the Free Software Foundation. *
+ * Permission is hereby granted, free of charge, to any person *
+ * obtaining a copy of this file gtp.h, to deal in the Software *
+ * without restriction, including without limitation the rights *
+ * to use, copy, modify, merge, publish, distribute, and/or *
+ * sell copies of the Software, and to permit persons to whom *
+ * the Software is furnished to do so, provided that the above *
+ * copyright notice(s) and this permission notice appear in all *
+ * copies of the Software and that both the above copyright *
+ * notice(s) and this permission notice appear in supporting *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY *
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE *
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR *
+ * PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO *
+ * EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS *
+ * NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR *
+ * CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING *
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF *
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT *
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS *
+ * Except as contained in this notice, the name of a copyright *
+ * holder shall not be used in advertising or otherwise to *
+ * promote the sale, use or other dealings in this Software *
+ * without prior written authorization of the copyright holder. *
+\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* Maximum allowed line length in GTP. */
+#define GTP_BUFSIZE 1000
+/* Status returned from callback functions. */
+/* Whether the GTP command was successful. */
+/* Function pointer for callback functions. */
+typedef int (*gtp_fn_ptr)(char *s, int id);
+/* Elements in the array of commands required by gtp_main_loop. */
+void gtp_main_loop(struct gtp_command commands[]);
+void gtp_internal_set_boardsize(int size);
+void gtp_mprintf(const char *format, ...);
+void gtp_printf(const char *format, ...);
+void gtp_printid(int id, int status);
+int gtp_finish_response(void);
+int gtp_success(int id, const char *format, ...);
+int gtp_failure(int id, const char *format, ...);
+int gtp_decode_color(char *s, int *color);
+int gtp_decode_coord(char *s, int *m, int *n);
+int gtp_decode_move(char *s, int *color, int *i, int *j);
+void gtp_print_vertices(int n, int movei[], int movej[]);
+void gtp_print_vertex(int i, int j);
diff -u -N -r -x *\.orig -x *\.info* ./interface/interface.c ../gnugo-2.6.1/gnugo-2.6.1/interface/interface.c
--- ./interface/interface.c Sat Feb 5 06:03:19 2000
+++ ../gnugo-2.6.1/gnugo-2.6.1/interface/interface.c Tue Aug 14 00:49:58 2001
clear_board(board_t **board)
memset(p,EMPTY,sizeof(p));
- memset(board,EMPTY,MAX_BOARD*MAX_BOARD*sizeof(board_t));
+ memset(board,EMPTY,MAX_BOARD*MAX_BOARD*sizeof(board_t));
diff -u -N -r -x *\.orig -x *\.info* ./interface/interface.h ../gnugo-2.6.1/gnugo-2.6.1/interface/interface.h
--- ./interface/interface.h Sat Feb 5 06:03:25 2000
+++ ../gnugo-2.6.1/gnugo-2.6.1/interface/interface.h Sat Aug 4 00:10:58 2001
void play_ascii(char * filename);
void play_ascii_emacs(char * filename);
void play_test(struct SGFNode *, enum testmode);
int load_sgf_file(struct SGFNode *, const char *untilstr);
diff -u -N -r -x *\.orig -x *\.info* ./interface/main.c ../gnugo-2.6.1/gnugo-2.6.1/interface/main.c
--- ./interface/main.c Sat Feb 12 04:37:42 2000
+++ ../gnugo-2.6.1/gnugo-2.6.1/interface/main.c Sat Aug 4 00:10:58 2001
- --mode <mode> Force the playing mode ('ascii', 'test' or 'gmp').\n\
+ --mode <mode> Select mode ('ascii', 'test, 'gmp', 'gtp').\n\
If no terminal is detected GMP (Go Modem Protocol)\n\
if (strcmp(optarg,"ascii")==0) playmode = MODE_ASCII;
else if (strcmp(optarg,"emacs")==0) playmode = MODE_ASCII_EMACS;
else if (strcmp(optarg,"gmp")==0) playmode = MODE_GMP;
+ else if (strcmp(optarg,"gtp")==0) playmode = MODE_GTP;
else if (strcmp(optarg,"test")==0) playmode = MODE_TEST;
fprintf(stderr,"Invalid mode selection: %s\n",optarg);
set_computer_player(NONE);
play_ascii_emacs(infile);
diff -u -N -r -x *\.orig -x *\.info* ./interface/play_gtp.c ../gnugo-2.6.1/gnugo-2.6.1/interface/play_gtp.c
--- ./interface/play_gtp.c Thu Jan 1 00:00:00 1970
+++ ../gnugo-2.6.1/gnugo-2.6.1/interface/play_gtp.c Tue Aug 14 01:16:03 2001
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see *
+ * http://www.gnu.org/software/gnugo/ for more information. *
+ * Copyright 1999, 2000, 2001 by the Free Software Foundation. *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation - version 3. *
+ * This program is distributed in the hope that it will be *
+ * useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *
+ * PURPOSE. See the GNU General Public License in file COPYING *
+ * You should have received a copy of the GNU General Public *
+ * License along with this program; if not, write to the Free *
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
+ * Boston, MA 02111, USA. *
+\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+#define MAXLIBS (2*(MAX_BOARD*MAX_BOARD + 1)/3)
+/* Internal state that's not part of the engine. */
+#define DECLARE(func) static int func(char *s, int id)
+DECLARE(gtp_fixed_handicap);
+DECLARE(gtp_genmove_black);
+DECLARE(gtp_genmove_white);
+DECLARE(gtp_estimate_score);
+DECLARE(gtp_set_boardsize);
+float estimate_score(float komi);
+/* List of known commands. */
+static struct gtp_command commands[] = {
+ {"black", gtp_playblack},
+ {"boardsize", gtp_set_boardsize},
+ {"fixed_handicap", gtp_fixed_handicap},
+ {"genmove_black", gtp_genmove_black},
+ {"genmove_white", gtp_genmove_white},
+ {"komi", gtp_set_komi},
+ {"estimate_score", gtp_estimate_score},
+ {"showboard", gtp_showboard},
+ {"version", gtp_version},
+ {"white", gtp_playwhite},
+/* Start playing using the Go Text Protocol. */
+ /* Try to make sure that we have a useful level of buffering of stdout. */
+ gtp_internal_set_boardsize(19);
+ gtp_main_loop(commands);
+gtp_quit(char *s, int id)
+/****************************
+ ****************************/
+/* Function: Report the name of the program.
+ * Returns: program name
+gtp_name(char *s, int id)
+ return gtp_success(id, "GNU Go");
+/* Function: Report the version number of the program.
+ * Returns: version number
+gtp_version(char *s, int id)
+ return gtp_success(id, VERSION);
+/* Function: Set the board size to NxN and clear the board.
+ * Fails: board size outside engine's limits
+gtp_set_boardsize(char *s, int id)
+ if (sscanf(s, "%d", &boardsize) < 1)
+ return gtp_failure(id, "boardsize not an integer");
+ if (boardsize < MIN_BOARD || boardsize > MAX_BOARD)
+ return gtp_failure(id, "unacceptable boardsize");
+ set_boardsize(boardsize);
+ gtp_internal_set_boardsize(boardsize);
+ return gtp_success(id, "");
+/* Function: Set the komi.
+ * Fails: incorrect argument
+gtp_set_komi(char *s, int id)
+ if (sscanf(s, "%f", &komi) < 1)
+ return gtp_failure(id, "komi not a float");
+ return gtp_success(id, "");
+/* Function: Play a black stone at the given vertex.
+ * Fails: invalid vertex, illegal move
+gtp_playblack(char *s, int id)
+ if (strncmp(s, "pass", 4) == 0) {
+ else if (!gtp_decode_coord(s, &i, &j))
+ return gtp_failure(id, "invalid coordinate");
+ if (!legal(i, j, BLACK))
+ return gtp_failure(id, "illegal move");
+ updateboard(i, j, BLACK);
+ return gtp_success(id, "");
+/* Function: Play a white stone at the given vertex.
+ * Fails: invalid vertex, illegal move
+gtp_playwhite(char *s, int id)
+ if (strncmp(s, "pass", 4) == 0) {
+ else if (!gtp_decode_coord(s, &i, &j))
+ return gtp_failure(id, "invalid coordinate");
+ if (!legal(i, j, WHITE))
+ return gtp_failure(id, "illegal move");
+ updateboard(i, j, WHITE);
+ return gtp_success(id, "");
+/* Function: Set up fixed placement handicap stones.
+ * Arguments: number of handicap stones
+ * Fails: invalid number of stones for the current boardsize
+ * Returns: list of vertices with handicap stones
+gtp_fixed_handicap(char *s, int id)
+ if (sscanf(s, "%d", &handicap) < 1)
+ return gtp_failure(id, "handicap not an integer");
+ if (sethand(handicap) != handicap)
+ return gtp_failure(id, "invalid handicap");
+ gtp_printid(id, GTP_SUCCESS);
+ for (m = 0; m < board_size; m++)
+ for (n = 0; n < board_size; n++)
+ if (p[m][n] != EMPTY) {
+ gtp_mprintf("%m", m, n);
+ return gtp_finish_response();
+/* Function: Generate and play the supposedly best black move.
+ * Returns: a move coordinate (or "PASS")
+gtp_genmove_black(char *s, int id)
+ if (genmove(&i, &j, BLACK) >= 0)
+ updateboard(i, j, BLACK);
+ gtp_printid(id, GTP_SUCCESS);
+ gtp_print_vertex(i, j);
+ return gtp_finish_response();
+/* Function: Generate and play the supposedly best white move.
+ * Returns: a move coordinate (or "PASS")
+gtp_genmove_white(char *s, int id)
+ if (genmove(&i, &j, WHITE) >= 0)
+ updateboard(i, j, WHITE);
+ gtp_printid(id, GTP_SUCCESS);
+ gtp_print_vertex(i, j);
+ return gtp_finish_response();
+gtp_estimate_score(char *s, int id)
+ genmove(&i, &j, BLACK);
+ score = estimate_score(komi);
+ gtp_printid(id, GTP_SUCCESS);
+ gtp_printf("W+%3.1f (upper bound: %3.1f, lower: %3.1f)",
+ gtp_printf("B+%3.1f (upper bound: %3.1f, lower: %3.1f)",
+ return gtp_finish_response();
+/* Function: Write the position to stderr.
+gtp_showboard(char *s, int id)
+ return gtp_success(id, "");
+/* Function: List all known commands
+ * Returns: list of known commands, one per line
+gtp_help(char *s, int id)
+ gtp_printid(id, GTP_SUCCESS);
+ for (k = 0; commands[k].name != NULL; k++)
+ gtp_printf("%s\n", commands[k].name);