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
@@ -8,7 +8,7 @@
 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
@@ -53,6 +53,7 @@
 #define WHITE 1
 #define BLACK 2
 #define GRAY_BORDER 3
+#define GRAY 3
 #define WHITE_BORDER 4
 #define BLACK_BORDER 5
 #define NONE 6               /* for use with is_computer_player */
@@ -138,8 +139,7 @@
 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 */
 
@@ -362,6 +362,7 @@
 void find_cuts(void);
 void find_connections(void);
 void endgame(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
@@ -2489,6 +2489,20 @@
     fprintf(stdwhat, "%c says \"I lost!\"\n", (color == WHITE) ? 'W' : 'B');
 }
 
+float
+estimate_score(float fkomi)
+{
+  float white_score;
+  float black_score;
+  float result;
+
+  make_moyo(BLACK);
+  white_score = (float) terri_eval[WHITE] + fkomi;
+  black_score = (float) terri_eval[BLACK];
+  result = white_score - black_score;
+  return result;
+}
+
 
 
 void
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
@@ -2732,9 +2732,6 @@
 {
   int safe=0;
 
-  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);
     if (acode != 1)
@@ -2742,10 +2739,6 @@
     popgo();
   }
   
-  if (stackp == 0) {
-    safe_move_cache_when[i][j][color==BLACK] = movenum;
-    safe_move_cache[i][j][color==BLACK] = safe;
-  }
   return 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
@@ -158,13 +158,16 @@
   if (handicap > maxhand)
     handicap = maxhand;
   
-  sgfAddPropertyInt(sgf_root,"HA",handicap);
+  if (sgf_root)
+    sgfAddPropertyInt(sgf_root,"HA",handicap);
   /* special cases: 5 and 7 */
   if (handicap == 5 || handicap == 7) {
     p[mid][mid] = BLACK;
     handicap--;
-    sgfAddStone(sgf_root,BLACK,mid,mid);
-    sgf_set_stone(mid,mid,BLACK);
+    if (sgf_root) {
+      sgfAddStone(sgf_root,BLACK,mid,mid);
+      sgf_set_stone(mid,mid,BLACK);
+    }
   }
 
   for (x=0; x<handicap; ++x) {
@@ -185,8 +188,10 @@
     if ( j < 0) j += board_size-1;
 
     p[i][j] = BLACK;
-    sgfAddStone(sgf_root,BLACK,i,j);
-    sgf_set_stone(i,j,BLACK);
+    if (sgf_root) {
+      sgfAddStone(sgf_root,BLACK,i,j);
+      sgf_set_stone(i,j,BLACK);
+    }
   }
   return handicap;
 }
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
@@ -349,7 +349,6 @@
       case 's':
       {
 	char *s = va_arg(ap, char*);
-	assert( (int)*s >= board_size );  /* in case %s used in place of %m */
 	fputs(s, outputfile);
 	break;
       }
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
@@ -26,7 +26,10 @@
 	play_gmp.c \
 	play_solo.c \
 	play_test.c \
-	gmp.c
+	play_gtp.c \
+	gmp.c \
+	gtp.c \
+	gtp.h
 
 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
@@ -88,7 +88,7 @@
 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
@@ -104,7 +104,7 @@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
 gnugo_OBJECTS =  main.o interface.o play_ascii.o play_gmp.o play_solo.o \
-play_test.o gmp.o
+play_test.o play_gtp.o gmp.o gtp.o
 gnugo_LDADD = $(LDADD)
 gnugo_DEPENDENCIES =  ../engine/libengine.a ../patterns/libpatterns.a \
 ../sgf/libsgf.a ../utils/libutils.a
@@ -120,7 +120,7 @@
 
 DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
-TAR = tar
+TAR = gtar
 GZIP_ENV = --best
 SOURCES = $(gnugo_SOURCES)
 OBJECTS = $(gnugo_OBJECTS)
@@ -229,6 +229,7 @@
 	  fi; \
 	done
 gmp.o: gmp.c ../config.h gmp.h
+gtp.o: gtp.c gtp.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 \
@@ -241,6 +242,8 @@
 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 \
+	interface.h gtp.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
@@ -0,0 +1,417 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * 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     *
+ * documentation.                                                *
+ *                                                               *
+ * 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       *
+ * SOFTWARE.                                                     *
+ *                                                               *
+ * 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.  *
+\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "gtp.h"
+
+/* These are copied from gnugo.h. We don't include this file in order
+ * to remain as independent as possible of GNU Go internals.
+ */
+#define EMPTY        0
+#define WHITE        1
+#define BLACK        2
+
+/* 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. */
+void
+gtp_main_loop(struct gtp_command commands[])
+{
+  char line[GTP_BUFSIZE];
+  char command[GTP_BUFSIZE];
+  char *p;
+  int i;
+  int id;
+  int n;
+  int status = GTP_OK;
+  
+  while (status == GTP_OK) {
+    /* Read a line from stdin. */
+    if (!fgets(line, GTP_BUFSIZE, stdin))
+      break; /* EOF or some error */
+
+    /* Remove comments. */
+    if ((p = strchr(line, '#')) != NULL)
+      *p = 0;
+    
+    p = line;
+
+    /* Look for an identification number. */
+    if (sscanf(p, "%d%n", &id, &n) == 1)
+      p += n;
+    else
+      id = -1; /* No identification number. */
+
+    /* Look for command name. */
+    if (sscanf(p, " %s %n", command, &n) < 1)
+      continue; /* Whitespace only on this line, ignore. */
+    p += n;
+
+    /* Search the list of commands and call the corresponding function
+     * if it's found.
+     */
+    for (i = 0; commands[i].name != NULL; i++) {
+      if (strcmp(command, commands[i].name) == 0) {
+	status = (*commands[i].function)(p, id);
+	break;
+      }
+    }
+    if (commands[i].name == NULL)
+      gtp_failure(id, "unknown command: '%s'", command);
+
+    if (status == GTP_FATAL)
+      gtp_panic();
+  }
+}
+
+
+/* Set the board size used in coordinate conversions. */
+void
+gtp_internal_set_boardsize(int size)
+{
+  gtp_boardsize = 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.
+ */
+void 
+gtp_mprintf(const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  
+  for ( ; *fmt ; ++fmt ) {
+    if (*fmt == '%') {
+      switch (*++fmt) {
+      case 'c':
+      {
+	/* rules of promotion => passed as int, not char */
+	int c = va_arg(ap, int);
+	putc(c, stdout);
+	break;
+      }
+      case 'd':
+      {
+	int d = va_arg(ap, int);
+	fprintf(stdout, "%d", d);
+	break;
+      }
+      case 'f':
+      {
+	double f = va_arg(ap, double); /* passed as double, not float */
+	fprintf(stdout, "%f", f);
+	break;
+      }
+      case 's':
+      {
+	char *s = va_arg(ap, char*);
+	fputs(s, stdout);
+	break;
+      }
+      case 'm':
+      {
+	int m = va_arg(ap, int);
+	int n = va_arg(ap, int);
+	if (m == -1 && n == -1)
+	  fputs("PASS", stdout);
+	else if ((m<0) || (n<0) || (m>=gtp_boardsize) || (n>=gtp_boardsize))
+	  fprintf(stdout, "??");
+	else
+	  fprintf(stdout, "%c%d", 'A' + n + (n >= 8), gtp_boardsize - m);
+	break;
+      }
+      case 'C':
+      {
+	int color = va_arg(ap, int);
+	if (color == WHITE)
+	  fputs("white", stdout);
+	else if (color == BLACK)
+	  fputs("black", stdout);
+	else
+	  fputs("empty", stdout);
+	break;
+      }
+      default:
+	fprintf(stdout, "\n\nUnknown format character '%c'\n", *fmt);
+	break;
+      }
+    }
+    else
+      putc(*fmt, stdout);
+  }
+  va_end(ap);
+}
+
+
+/* This currently works exactly like printf. */
+void
+gtp_printf(const char *format, ...)
+{
+  va_list ap;
+  va_start(ap, format);
+  vfprintf(stdout, format, ap);
+  va_end(ap);
+}
+
+
+/* Write success or failure indication plus identity number if one was
+ * given.
+ */
+void
+gtp_printid(int id, int status)
+{
+  if (status == GTP_SUCCESS)
+    gtp_printf("=");
+  else
+    gtp_printf("?");
+  
+  if (id < 0)
+    gtp_printf(" ");
+  else
+    gtp_printf("%d ", id);
+}
+
+
+/* Finish a GTP response by writing a double newline and returning GTP_OK. */
+int
+gtp_finish_response()
+{
+  gtp_printf("\n\n");
+  return GTP_OK;
+}
+
+
+/* Write a full success response. Except for the id number, the call
+ * is just like one to printf.
+ */
+int
+gtp_success(int id, const char *format, ...)
+{
+  va_list ap;
+  gtp_printid(id, GTP_SUCCESS);
+  va_start(ap, format);
+  vfprintf(stdout, format, ap);
+  va_end(ap);
+  return gtp_finish_response();
+}
+
+
+/* Write a full failure response. The call is identical to gtp_success. */
+int
+gtp_failure(int id, const char *format, ...)
+{
+  va_list ap;
+  gtp_printid(id, GTP_FAILURE);
+  va_start(ap, format);
+  vfprintf(stdout, format, ap);
+  va_end(ap);
+  return gtp_finish_response();
+}
+
+
+/* Write a panic message. */
+void
+gtp_panic()
+{
+  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.
+ */
+int
+gtp_decode_color(char *s, int *color)
+{
+  char color_string[7];
+  int i;
+  int n;
+
+  assert(gtp_boardsize > 0);
+
+  if (sscanf(s, "%6s%n", color_string, &n) != 1)
+    return 0;
+
+  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)
+    *color = BLACK;
+  else if (strcmp(color_string, "w") == 0
+	   || strcmp(color_string, "white") == 0)
+    *color = WHITE;
+  else
+    return 0;
+  
+  return n;
+}
+
+
+/* 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.
+ */
+int
+gtp_decode_coord(char *s, int *i, int *j)
+{
+  char column;
+  int row;
+  int n;
+
+  assert(gtp_boardsize > 0);
+
+  if (sscanf(s, " %c%d%n", &column, &row, &n) != 2)
+    return 0;
+  
+  if (tolower((int) column) == 'i')
+    return 0;
+  *j = tolower((int) column) - 'a';
+  if (tolower((int) column) > 'i')
+    --*j;
+
+  *i = gtp_boardsize - row;
+
+  if (*i < 0 || *i >= gtp_boardsize || *j < 0 || *j >= gtp_boardsize)
+    return 0;
+
+  return n;
+}
+
+/* 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
+ * s.
+ */
+int
+gtp_decode_move(char *s, int *color, int *i, int *j)
+{
+  int n1, n2;
+
+  assert(gtp_boardsize > 0);
+
+  n1 = gtp_decode_color(s, color);
+  if (n1 == 0)
+    return 0;
+
+  n2 = gtp_decode_coord(s + n1, i, j);
+  if (n2 == 0)
+    return 0;
+
+  return n1 + n2;
+}
+
+/* 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
+ * qsort.
+ */
+static void
+sort_moves(int n, int movei[], int movej[])
+{
+  int b, a;
+  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])) {
+	int tmp;
+	tmp = movei[b];
+	movei[b] = movei[a];
+	movei[a] = tmp;
+	tmp = movej[b];
+	movej[b] = movej[a];
+	movej[a] = tmp;
+      }
+    }
+  }
+}
+
+/* Write a number of space separated vertices. The moves are sorted
+ * before being written.
+ */
+void
+gtp_print_vertices(int n, int movei[], int movej[])
+{
+  int k;
+  
+  assert(gtp_boardsize > 0);
+  
+  sort_moves(n, movei, movej);
+  for (k = 0; k < n; k++) {
+    if (k > 0)
+      gtp_printf(" ");
+    if ((movei[k] == -1 && movej[k] == -1)
+	|| (movei[k] == gtp_boardsize && movej[k] == gtp_boardsize))
+      gtp_printf("PASS");
+    else if (movei[k] < 0 || movei[k] >= gtp_boardsize
+	     || movej[k] < 0 || movej[k] >= gtp_boardsize) {
+      gtp_printf("?? %d %d", movei[k], movej[k]);
+    }
+    else
+      gtp_printf("%c%d", 'A' + movej[k] + (movej[k] >= 8),
+		 gtp_boardsize - movei[k]);
+  }
+}
+
+/* Write a single move. */
+void
+gtp_print_vertex(int i, int j)
+{
+  gtp_print_vertices(1, &i, &j);
+}
+
+
+/*
+ * Local Variables:
+ * tab-width: 8
+ * c-basic-offset: 2
+ * End:
+ */
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
@@ -0,0 +1,83 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * 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     *
+ * documentation.                                                *
+ *                                                               *
+ * 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       *
+ * SOFTWARE.                                                     *
+ *                                                               *
+ * 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.  *
+\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdarg.h>
+
+/* Maximum allowed line length in GTP. */
+#define GTP_BUFSIZE 1000
+
+/* Status returned from callback functions. */
+#define GTP_QUIT    -1
+#define GTP_OK       0
+#define GTP_FATAL    1
+
+/* Whether the GTP command was successful. */
+#define GTP_SUCCESS  0
+#define GTP_FAILURE  1
+
+/* 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. */
+struct gtp_command {
+  const char *name;
+  gtp_fn_ptr function;
+};
+
+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, ...);
+void gtp_panic(void);
+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);
+
+/*
+ * Local Variables:
+ * tab-width: 8
+ * c-basic-offset: 2
+ * End:
+ */
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
@@ -326,14 +326,14 @@
 int 
 clear_board(board_t **board)
 {
-  if(board==NULL)
-    {
+  if (board==NULL) {
       memset(p,EMPTY,sizeof(p));
-    }
-  else
-    {
-      memset(board,EMPTY,MAX_BOARD*MAX_BOARD*sizeof(board_t));
-    }
+  }
+  else {
+    memset(board,EMPTY,MAX_BOARD*MAX_BOARD*sizeof(board_t));
+  }
+  white_captured = 0;
+  black_captured = 0;
   return 1;
 }
 
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
@@ -42,6 +42,7 @@
 void play_ascii(char * filename);
 void play_ascii_emacs(char * filename);
 void play_gmp(void);
+void play_gtp(void);
 void play_solo(int);
 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
@@ -79,7 +79,7 @@
 Usage : gnugo [-opts]\n\
 \n\
 Main Options:\n\
-       --mode <mode>     Force the playing mode ('ascii', 'test' or 'gmp').\n\
+       --mode <mode>     Select mode ('ascii', 'test, 'gmp', 'gtp').\n\
                          Default is ASCII.\n\
                          If no terminal is detected GMP (Go Modem Protocol)\n\
                          will be assumed.\n\
@@ -185,6 +185,7 @@
   MODE_ASCII,
   MODE_ASCII_EMACS,
   MODE_GMP,
+  MODE_GTP,
   MODE_SGF,
   MODE_LOAD_AND_ANALYZE,
   MODE_LOAD_AND_SCORE,
@@ -482,6 +483,7 @@
 	 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;
 	 else {
 	   fprintf(stderr,"Invalid mode selection: %s\n",optarg);
@@ -718,6 +720,10 @@
          set_computer_player(NONE);
        }
      play_ascii_emacs(infile);
+     break;
+
+   case MODE_GTP:
+     play_gtp();
      break;
 
    case MODE_ASCII :  
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
@@ -0,0 +1,377 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * 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  *
+ * for more details.                                             *
+ *                                                               *
+ * 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.                                        *
+\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "liberty.h"
+#include "interface.h"
+#include "gtp.h"
+
+#define MAXLIBS (2*(MAX_BOARD*MAX_BOARD + 1)/3)
+#define UNUSED(x)  x=x
+
+/* Internal state that's not part of the engine. */
+int color_to_move;
+float komi;
+int handicap;
+
+#define DECLARE(func) static int func(char *s, int id)
+
+DECLARE(gtp_fixed_handicap);
+DECLARE(gtp_genmove_black);
+DECLARE(gtp_genmove_white);
+DECLARE(gtp_name);
+DECLARE(gtp_estimate_score);
+DECLARE(gtp_playblack);
+DECLARE(gtp_playwhite);
+DECLARE(gtp_quit);
+DECLARE(gtp_set_boardsize);
+DECLARE(gtp_set_komi);
+DECLARE(gtp_showboard);
+DECLARE(gtp_version);
+DECLARE(gtp_help);
+float estimate_score(float komi);
+
+void play_gtp(void);
+
+/* 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},
+  {"help",                    gtp_help},
+  {"komi",        	      gtp_set_komi},
+  {"name",                    gtp_name},
+  {"estimate_score",          gtp_estimate_score},
+  {"quit",                    gtp_quit},
+  {"showboard",        	      gtp_showboard},
+  {"version",                 gtp_version},
+  {"white",            	      gtp_playwhite},
+  {NULL,                      NULL}
+};
+
+
+/* Start playing using the Go Text Protocol. */
+void
+play_gtp(void)
+{
+  /* Try to make sure that we have a useful level of buffering of stdout. */
+#ifdef HAVE_SETLINEBUF
+  setlinebuf(stdout);
+#else
+  setbuf(stdout, NULL);
+#endif
+
+  gtp_internal_set_boardsize(19);
+
+  gtp_main_loop(commands);
+}
+
+
+/* Function:  Quit
+ * Arguments: none
+ * Fails:     never
+ * Returns:   nothing
+ */
+static int
+gtp_quit(char *s, int id)
+{
+  UNUSED(s);
+  gtp_success(id, "");
+  return GTP_QUIT;
+}
+
+
+/****************************
+ * Program identity.        *
+ ****************************/
+
+/* Function:  Report the name of the program.
+ * Arguments: none
+ * Fails:     never
+ * Returns:   program name
+ */
+static int
+gtp_name(char *s, int id)
+{
+  UNUSED(s);
+  return gtp_success(id, "GNU Go");
+}
+
+
+/* Function:  Report the version number of the program.
+ * Arguments: none
+ * Fails:     never
+ * Returns:   version number
+ */
+static int
+gtp_version(char *s, int id)
+{
+  UNUSED(s);
+  return gtp_success(id, VERSION);
+}
+
+
+/* Function:  Set the board size to NxN and clear the board.
+ * Arguments: integer
+ * Fails:     board size outside engine's limits
+ * Returns:   nothing
+ */
+static int
+gtp_set_boardsize(char *s, int id)
+{
+  int boardsize;
+  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);
+  clear_board(NULL);
+  gtp_internal_set_boardsize(boardsize);
+  return gtp_success(id, "");
+}
+
+
+/* Function:  Set the komi.
+ * Arguments: float
+ * Fails:     incorrect argument
+ * Returns:   nothing
+ */
+static int
+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.
+ * Arguments: vertex
+ * Fails:     invalid vertex, illegal move
+ * Returns:   nothing
+ */
+static int
+gtp_playblack(char *s, int id)
+{
+  int i, j;
+  char *c;
+
+  for (c = s; *c; c++)
+    *c = tolower(*c);
+
+  if (strncmp(s, "pass", 4) == 0) {
+    i = get_boardsize();
+    j = get_boardsize();
+  }
+  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.
+ * Arguments: vertex
+ * Fails:     invalid vertex, illegal move
+ * Returns:   nothing
+ */
+static int
+gtp_playwhite(char *s, int id)
+{
+  int i, j;
+  char *c;
+
+  for (c = s; *c; c++)
+    *c = tolower(*c);
+
+  if (strncmp(s, "pass", 4) == 0) {
+    i = get_boardsize();
+    j = get_boardsize();
+  }
+  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
+ */
+static int
+gtp_fixed_handicap(char *s, int id)
+{
+  int m, n;
+  int first = 1;
+  int handicap;
+  if (sscanf(s, "%d", &handicap) < 1)
+    return gtp_failure(id, "handicap not an integer");
+  
+  clear_board(NULL);
+  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) {
+	if (!first)
+	  gtp_printf(" ");
+	else
+	  first = 0;
+	gtp_mprintf("%m", m, n);
+      }
+
+  return gtp_finish_response();
+}
+
+
+/* Function:  Generate and play the supposedly best black move.
+ * Arguments: none
+ * Fails:     never
+ * Returns:   a move coordinate (or "PASS")
+ */
+static int
+gtp_genmove_black(char *s, int id)
+{
+  int i, j;
+  UNUSED(s);
+  
+  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.
+ * Arguments: none
+ * Fails:     never
+ * Returns:   a move coordinate (or "PASS")
+ */
+static int
+gtp_genmove_white(char *s, int id)
+{
+  int i, j;
+  UNUSED(s);
+  if (genmove(&i, &j, WHITE) >= 0)
+    updateboard(i, j, WHITE);
+
+  gtp_printid(id, GTP_SUCCESS);
+  gtp_print_vertex(i, j);
+  return gtp_finish_response();
+}
+
+static int
+gtp_estimate_score(char *s, int id)
+{
+  int i, j;
+  float score;
+  UNUSED(s);
+
+  genmove(&i, &j, BLACK);
+  score = estimate_score(komi);
+
+  gtp_printid(id, GTP_SUCCESS);
+  if (score > 0.0) 
+    gtp_printf("W+%3.1f (upper bound: %3.1f, lower: %3.1f)", 
+	       score, score, score);
+  else if (score < 0.0)
+    gtp_printf("B+%3.1f (upper bound: %3.1f, lower: %3.1f)", 
+	       -score, score, score);
+  else
+    gtp_printf("0");
+  return gtp_finish_response();
+}  
+
+
+/* Function:  Write the position to stderr.
+ * Arguments: none
+ * Fails:     never
+ * Returns:   nothing
+ */
+static int
+gtp_showboard(char *s, int id)
+{
+  UNUSED(s);
+  showboard(1);
+  return gtp_success(id, "");
+}
+
+
+/* Function:  List all known commands
+ * Arguments: none
+ * Fails:     never
+ * Returns:   list of known commands, one per line
+ */
+static int
+gtp_help(char *s, int id)
+{
+  int k;
+  UNUSED(s);
+
+  gtp_printid(id, GTP_SUCCESS);
+
+  for (k = 0; commands[k].name != NULL; k++)
+    gtp_printf("%s\n", commands[k].name);
+
+  gtp_printf("\n");
+  return GTP_OK;
+}
+
+
+
+
+/*
+ * Local Variables:
+ * tab-width: 8
+ * c-basic-offset: 2
+ * End:
+ */
