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= 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 +#include +#include +#include + +#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 + +/* 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 Force the playing mode ('ascii', 'test' or 'gmp').\n\ + --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 +#endif + +#include +#include +#include +#include + +#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: + */