--- gmp.c.~1.4.~ 2002-12-31 12:41:09.000000000 +0000 +++ gmp.c 2003-07-10 15:42:22.000000000 +0000 @@ -15,6 +15,10 @@ version distributed with GoDummy. */ +/* Modified by Paul Pogonyshev on 10.07.2003. + * Added support for Simplified GTP. + */ + #ifdef HAVE_CONFIG_H #include #endif @@ -60,7 +64,10 @@ * Constants **********************************************************************/ -#define GMP_TIMEOUTSECS 60 +#define GMP_TIMEOUTRETRIES 60 +#define GMP_RETRYSECS 1 +#define SGMP_TIMEOUTRETRIES 9 +#define SGMP_RETRYSECS 20 #define GMP_MAXSENDSQUEUED 16 @@ -92,7 +99,8 @@ typedef struct Gmp_struct { int iAmWhite, colorVerified; Query lastQuerySent; - int recvSoFar, sendsQueued, sendFailures; + int recvSoFar, sendsQueued; + int sendFailures, noResponseSecs; int waitingHighAck; time_t lastSendTime; int myLastSeq, hisLastSeq; @@ -104,6 +112,8 @@ typedef struct Gmp_struct { int earlyMovePresent; int earlyMoveX, earlyMoveY; + + int simplified; } Gmp; @@ -177,6 +187,7 @@ Gmp *gmp_create(int inFile, int outFile ge->recvSoFar = 0; ge->sendsQueued = 0; ge->sendFailures = 0; + ge->noResponseSecs = 0; ge->waitingHighAck = 0; ge->lastSendTime = 0; ge->myLastSeq = 0; @@ -348,6 +359,7 @@ static GmpResult parsePacket(Gmp *ge, i } else { ge->hisLastSeq = seq; ge->sendFailures = 0; + ge->noResponseSecs = 0; return(processCommand(ge, command, val, out1, out2, error)); } } else { @@ -359,6 +371,7 @@ static GmpResult parsePacket(Gmp *ge, i return(gmp_nothing); } ge->sendFailures = 0; + ge->noResponseSecs = 0; ge->waitingHighAck = 0; if (!gmp_verified(ge)) { askQuery(ge); @@ -374,6 +387,7 @@ static GmpResult parsePacket(Gmp *ge, i /* His command is old. */ } else if (ack == ge->myLastSeq) { ge->sendFailures = 0; + ge->noResponseSecs = 0; ge->waitingHighAck = 0; ge->hisLastSeq = seq; result = processCommand(ge, command, val, out1, out2, error); @@ -565,18 +579,27 @@ static GmpResult respond(Gmp *ge, Query static void askQuery(Gmp *ge) { - if (!ge->rulesVerified) { - ge->lastQuerySent = query_rules; - } else if (!ge->sizeVerified) { - ge->lastQuerySent = query_boardSize; - } else if (!ge->handicapVerified) { - ge->lastQuerySent = query_handicap; -/* } else if (!ge->komiVerified) { - ge->lastQuerySent = query_komi; query komi is not define in GMP !?*/ - } else { - assert(!ge->colorVerified); - ge->lastQuerySent = query_color; + if (!ge->simplified) { + if (!ge->rulesVerified) { + ge->lastQuerySent = query_rules; + } else if (!ge->sizeVerified) { + ge->lastQuerySent = query_boardSize; + } else if (!ge->handicapVerified) { + ge->lastQuerySent = query_handicap; + /* } else if (!ge->komiVerified) { + ge->lastQuerySent = query_komi; query komi is not define in GMP !? */ + } else { + assert(!ge->colorVerified); + ge->lastQuerySent = query_color; + } } + else { + if (!ge->colorVerified) + ge->lastQuerySent = query_color; + else if (!ge->handicapVerified) + ge->lastQuerySent = query_handicap; + } + putCommand(ge, cmd_query, ge->lastQuerySent); } @@ -691,24 +714,28 @@ static GmpResult gotQueryResponse(Gmp * static int heartbeat(Gmp *ge) { Command cmd; - if (ge->waitingHighAck) { - if (++ge->sendFailures > GMP_TIMEOUTSECS) { - return(0); - } else { - if (gmp_debug) { - cmd = (ge->sendData[2] >> 4) & 7; - if (cmd == cmd_query) { - if (gmp_debug) - fprintf(stderr, "GMP: Sending command: %s %s (retry)\n", - commandNames[cmd], - queryNames[ge->sendData[3] & 0x7f]); + if (ge->waitingHighAck) { + if (++ge->noResponseSecs + > (ge->simplified ? SGMP_RETRYSECS : GMP_RETRYSECS)) { + if (++ge->sendFailures + > (ge->simplified ? SGMP_TIMEOUTRETRIES : GMP_TIMEOUTRETRIES)) { + return(0); + } else { + if (gmp_debug) { + cmd = (ge->sendData[2] >> 4) & 7; + if (cmd == cmd_query) { + if (gmp_debug) + fprintf(stderr, "GMP: Sending command: %s %s (retry)\n", + commandNames[cmd], + queryNames[ge->sendData[3] & 0x7f]); + } + else + if (gmp_debug) + fprintf(stderr, "GMP: Sending command: %s (retry)\n", + commandNames[cmd]); } - else - if (gmp_debug) - fprintf(stderr, "GMP: Sending command: %s (retry)\n", - commandNames[cmd]); + write(ge->outFile, ge->sendData, 4); } - write(ge->outFile, ge->sendData, 4); } } return(1); @@ -716,14 +743,14 @@ static int heartbeat(Gmp *ge) { void gmp_startGame(Gmp *ge, int size, int handicap, float komi, - int chineseRules, int iAmWhite) { + int chineseRules, int iAmWhite, int simplified) { assert((size == -1) || ((size > 1) && (size <= 22))); assert((handicap >= -1) && (handicap <= 27)); assert((chineseRules >= -1) && (chineseRules <= 1)); assert((iAmWhite >= -1) && (iAmWhite <= 1)); ge->boardSize = size; - ge->sizeVerified = 0; + ge->sizeVerified = simplified; ge->handicap = handicap; ge->handicapVerified = 0; @@ -731,13 +758,15 @@ void gmp_startGame(Gmp *ge, int size, i ge->komi = komi; ge->chineseRules = chineseRules; - ge->rulesVerified = 0; + ge->rulesVerified = simplified; ge->iAmWhite = iAmWhite; ge->colorVerified = 0; ge->earlyMovePresent = 0; + ge->simplified = simplified; + if (iAmWhite != 1) { putCommand(ge, cmd_reset, 0); } --- gmp.h.~1.3.~ 2001-09-06 21:34:20.000000000 +0000 +++ gmp.h 2003-07-10 04:16:16.000000000 +0000 @@ -23,6 +23,10 @@ * above copyright notices. */ +/* Modified by Paul Pogonyshev on 10.07.2003. + * Added support for Simplified GTP. + */ + #ifndef _GMP_H_ #define _GMP_H_ 1 @@ -60,7 +64,8 @@ extern void gmp_destroy(Gmp *ge); * set to -1, and you can start the game. */ extern void gmp_startGame(Gmp *ge, int boardsize, int handicap, - float komi, int chineseRules, int iAmWhite); + float komi, int chineseRules, int iAmWhite, + int simplified); /* * Pretty self-explanatory set of routines. For sendMove, (0,0) is the --- interface.h.~1.11.~ 2003-01-02 00:23:29.000000000 +0000 +++ interface.h 2003-07-10 03:51:27.000000000 +0000 @@ -36,7 +36,7 @@ void play_ascii(SGFTree *tree, Gameinfo void play_ascii_emacs(SGFTree *tree, Gameinfo *gameinfo, char *filename, char *until); void play_gtp(FILE *gtp_input, int gtp_initial_orientation); -void play_gmp(Gameinfo *gameinfo); +void play_gmp(Gameinfo *gameinfo, int simplified); void play_solo(Gameinfo *gameinfo, int benchmark); void play_replay(Gameinfo *gameinfo, int color_to_test); --- main.c.~1.75.~ 2003-07-09 23:40:29.000000000 +0000 +++ main.c 2003-07-10 15:43:04.000000000 +0000 @@ -148,6 +148,7 @@ enum mode { MODE_ASCII_EMACS, MODE_GTP, MODE_GMP, + MODE_SGMP, MODE_SGF, MODE_LOAD_AND_ANALYZE, MODE_LOAD_AND_SCORE, @@ -601,6 +602,8 @@ main(int argc, char *argv[]) playmode = MODE_GTP; else if (strcmp(gg_optarg, "gmp") == 0) playmode = MODE_GMP; + else if (strcmp(gg_optarg, "sgmp") == 0) + playmode = MODE_SGMP; else { fprintf(stderr, "Invalid mode selection: %s\n", gg_optarg); fprintf(stderr, "Try `gnugo --help' for more information.\n"); @@ -988,10 +991,11 @@ main(int argc, char *argv[]) } fclose(output_check); } - + switch (playmode) { - case MODE_GMP: - + case MODE_GMP: + case MODE_SGMP: + /* not supported by the protocol */ resign_allowed = 0; @@ -1000,7 +1004,9 @@ main(int argc, char *argv[]) summon_oracle(); #endif - play_gmp(&gameinfo); + /* EMPTY is valid for play_gmp.c. */ + gameinfo.computer_player = mandated_color; + play_gmp(&gameinfo, playmode == MODE_SGMP); #if ORACLE if (metamachine) @@ -1352,8 +1358,8 @@ show_version(void) Usage: gnugo [-opts]\n\ \n\ Main Options:\n\ - --mode Force the playing mode ('ascii', 'gmp', or 'gtp').\n\ - Default is ASCII.\n\ + --mode Force the playing mode ('ascii', 'gmp', 'sgmp',\n\ + or 'gtp'). Default is ASCII.\n\ If no terminal is detected GMP (Go Modem Protocol)\n\ will be assumed.\n\ --quiet Don't print copyright and informational messages\n\ --- play_gmp.c.~1.22.~ 2003-07-09 23:40:29.000000000 +0000 +++ play_gmp.c 2003-07-10 15:39:15.000000000 +0000 @@ -36,7 +36,7 @@ /* Play a game against a go-modem-protocol (GMP) client. */ /* --------------------------------------------------------------*/ void -play_gmp(Gameinfo *gameinfo) +play_gmp(Gameinfo *gameinfo, int simplified) { SGFTree sgftree; @@ -49,25 +49,45 @@ play_gmp(Gameinfo *gameinfo) int passes = 0; /* two passes and its over */ int to_move; /* who's turn is next ? */ - int mycolor; /* who has which color */ + int mycolor = -1; /* who has which color */ int yourcolor; - - mycolor = gameinfo->computer_player; + + if (gameinfo->computer_player == WHITE) + mycolor = 1; + else if (gameinfo->computer_player == BLACK) + mycolor = 0; sgftree_clear(&sgftree); sgftreeCreateHeaderNode(&sgftree, gnugo_get_boardsize(), gnugo_get_komi()); - yourcolor = OTHER_COLOR(mycolor); - ge = gmp_create(0, 1); TRACE("board size=%d\n", gnugo_get_boardsize()); - /* Leave all the -1's so the client can negotiate the game parameters. */ - if (chinese_rules) - gmp_startGame(ge, -1, -1, 5.5, -1, -1); - else - gmp_startGame(ge, -1, -1, 5.5, 0, -1); - + /* + * The specification of the go modem protocol doesn't even discuss + * komi. So we have to guess the komi. If the komi is set on the + * command line, keep it. Otherwise, its value will be 0.0 and we + * use 5.5 in an even game, 0.5 otherwise. + */ + if (gnugo_get_komi() == 0.0) { + if (gameinfo->handicap == 0) + gnugo_set_komi(5.5); + else + gnugo_set_komi(0.5); + } + + if (!simplified) { + /* Leave all the -1's so the client can negotiate the game parameters. */ + if (chinese_rules) + gmp_startGame(ge, -1, -1, 5.5, -1, mycolor, 0); + else + gmp_startGame(ge, -1, -1, 5.5, 0, mycolor, 0); + } + else { + gmp_startGame(ge, board_size, gameinfo->handicap, + gnugo_get_komi(), chinese_rules, mycolor, 1); + } + do { message = gmp_check(ge, 1, NULL, NULL, &error); } while (message == gmp_nothing || message == gmp_reset); @@ -85,24 +105,14 @@ play_gmp(Gameinfo *gameinfo) gameinfo->handicap = gmp_handicap(ge); gnugo_clear_board(gmp_size(ge)); + /* Let's pretend GMP knows about komi in case something will ever change. */ + gnugo_set_komi(gmp_komi(ge)); + #if ORACLE if (metamachine && oracle_exists) oracle_clear_board(gnugo_get_boardsize()); #endif - /* - * The specification of the go modem protocol doesn't even discuss - * komi. So we have to guess the komi. If the komi is set on the - * command line, keep it. Otherwise, its value will be 0.0 and we - * use 5.5 in an even game, 0.5 otherwise. - */ - if (gnugo_get_komi() == 0.0) { - if (gameinfo->handicap == 0) - gnugo_set_komi(5.5); - else - gnugo_set_komi(0.5); - } - sgfOverwritePropertyInt(sgftree.root, "SZ", gnugo_get_boardsize()); TRACE("size=%d, handicap=%d, komi=%f\n", gnugo_get_boardsize(), @@ -205,21 +215,17 @@ play_gmp(Gameinfo *gameinfo) /* two passes: game over */ gmp_sendPass(ge); - /* We hang around here until cgoban asks us to go, since - * sometimes cgoban crashes if we exit first. - */ - if (!quiet) fprintf(stderr, "Game over - waiting for client to shut us down\n"); who_wins(mycolor, stderr); if (showtime) { - gprintf("\nSLOWEST MOVE: %d at %1m ", slowest_movenum, slowest_move); - fprintf(stderr, "(%.2f seconds)\n", slowest_time); - fprintf(stderr, "\nAVERAGE TIME: %.2f seconds per move\n", - total_time / movenum); - fprintf(stderr, "\nTOTAL TIME: %.2f seconds\n", - total_time); + gprintf("\nSLOWEST MOVE: %d at %1m ", slowest_movenum, slowest_move); + fprintf(stderr, "(%.2f seconds)\n", slowest_time); + fprintf(stderr, "\nAVERAGE TIME: %.2f seconds per move\n", + total_time / movenum); + fprintf(stderr, "\nTOTAL TIME: %.2f seconds\n", + total_time); } @@ -230,13 +236,21 @@ play_gmp(Gameinfo *gameinfo) sgfWriteResult(sgftree.root, score, 1); sgffile_output(&sgftree); - - while (1) { - message = gmp_check(ge, 1, &j, &i, &error); - if (!quiet) - fprintf(stderr, "Message %d from gmp\n", message); - if (message == gmp_err) - break; + + if (!simplified) { + /* We hang around here until cgoban asks us to go, since + * sometimes cgoban crashes if we exit first. + * + * FIXME: Check if this is still needed. I made it dependand on + * `simplifed' just to avoid changes in GMP mode. + */ + while (1) { + message = gmp_check(ge, 1, &j, &i, &error); + if (!quiet) + fprintf(stderr, "Message %d from gmp\n", message); + if (message == gmp_err) + break; + } } #if ORACLE