// ----------------------------------------------------------------------- // Wait_For_GMP_Move: // void Wait_For_GMP_Move (Gmp* ge, GO_BOARD board, GO_PIECE his_stone, int* his_turn) { GmpResult message; int x, y; const char* error; do { message = gmp_check(ge, 1, &x, &y, &error); } while (message == gmp_nothing); switch (message) { case gmp_err: fprintf(stderr, "dummy: Got error \"%s\"\n", error); exit(1); case gmp_move: passes = 0; Go_Board_Place_Stone (board, his_stone, x, y); break; case gmp_pass: if (++passes == 2) { Go_Board_Destroy (&board); exit (0); } break; case gmp_reset: Go_Board_Destroy (&board); exit (0); case gmp_undo: fprintf(stderr, "dummy: I am asked to undo %d moves.\n", x); if ((x & 1) == 0) { // // Since an even number of undos were made, it is still the other // player's turn. This flag makes me skip my turn. // *his_turn = 1; } break; default: fprintf(stderr, "Got a \"%s\" command during game play. Exiting.\n", gmp_resultString(message)); exit(1); } // switch on return type } // Wait_For_GMP_Move
static void waitForNewGame(Gmp *ge) { GmpResult result; const char *err; do { result = gmp_check(ge, 1, NULL, NULL, &err); } while ((result == gmp_nothing) || (result == gmp_reset)); if (result == gmp_err) { fprintf(stderr, "dummy: Error \"%s\" occurred.\n", err); exit(1); } else if (result != gmp_newGame) { fprintf(stderr, "Expecting a newGame, got %s\n", gmp_resultString(result)); exit(1); } }
/* --------------------------------------------------------------*/ void play_gmp(Gameinfo *gameinfo, int simplified) { SGFTree sgftree; Gmp *ge; GmpResult message; const char *error; int i, j; int passes = 0; /* two passes and its over */ int to_move; /* who's turn is next ? */ int mycolor = -1; /* who has which color */ int yourcolor; if (gameinfo->computer_player == WHITE) mycolor = 1; else if (gameinfo->computer_player == BLACK) mycolor = 0; sgftree_clear(&sgftree); sgftreeCreateHeaderNode(&sgftree, board_size, komi, gameinfo->handicap); ge = gmp_create(0, 1); TRACE("board size=%d\n", board_size); /* * 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 (komi == 0.0) { if (gameinfo->handicap == 0) komi = 5.5; else 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, komi, chinese_rules, mycolor, 1); } do { message = gmp_check(ge, 1, NULL, NULL, &error); } while (message == gmp_nothing || message == gmp_reset); if (message == gmp_err) { fprintf(stderr, "gnugo-gmp: Error \"%s\" occurred.\n", error); exit(EXIT_FAILURE); } else if (message != gmp_newGame) { fprintf(stderr, "gnugo-gmp: Expecting a newGame, got %s\n", gmp_resultString(message)); exit(EXIT_FAILURE); } gameinfo->handicap = gmp_handicap(ge); if (!check_boardsize(gmp_size(ge), stderr)) exit(EXIT_FAILURE); gnugo_clear_board(gmp_size(ge)); /* Let's pretend GMP knows about komi in case something will ever change. */ komi = gmp_komi(ge); #if ORACLE if (metamachine && oracle_exists) oracle_clear_board(board_size); #endif sgfOverwritePropertyInt(sgftree.root, "SZ", board_size); TRACE("size=%d, handicap=%d, komi=%f\n", board_size, gameinfo->handicap, komi); if (gameinfo->handicap) to_move = WHITE; else to_move = BLACK; if (gmp_iAmWhite(ge)) { mycolor = WHITE; /* computer white */ yourcolor = BLACK; /* human black */ } else { mycolor = BLACK; yourcolor = WHITE; } gameinfo->computer_player = mycolor; sgf_write_header(sgftree.root, 1, get_random_seed(), komi, gameinfo->handicap, get_level(), chinese_rules); gameinfo->handicap = gnugo_sethand(gameinfo->handicap, sgftree.root); sgfOverwritePropertyInt(sgftree.root, "HA", gameinfo->handicap); /* main GMP loop */ while (passes < 2) { if (to_move == yourcolor) { int move; /* Get opponent's move from gmp client. */ message = gmp_check(ge, 1, &j, &i, &error); if (message == gmp_err) { fprintf(stderr, "GNU Go: Sorry, error from gmp client\n"); sgftreeAddComment(&sgftree, "got error from gmp client"); sgffile_output(&sgftree); return; } if (message == gmp_undo) { int k; assert(j > 0); for (k = 0; k < j; k++) { if (!undo_move(1)) { fprintf(stderr, "GNU Go: play_gmp UNDO: can't undo %d moves\n", j - k); break; } sgftreeAddComment(&sgftree, "undone"); sgftreeBack(&sgftree); to_move = OTHER_COLOR(to_move); } continue; } if (message == gmp_pass) { passes++; move = PASS_MOVE; } else { passes = 0; move = POS(i, j); } TRACE("\nyour move: %1m\n\n", move); sgftreeAddPlay(&sgftree, to_move, I(move), J(move)); gnugo_play_move(move, yourcolor); sgffile_output(&sgftree); } else { /* Generate my next move. */ float move_value; int move; if (autolevel_on) adjust_level_offset(mycolor); move = genmove(mycolor, &move_value, NULL); gnugo_play_move(move, mycolor); sgffile_add_debuginfo(sgftree.lastnode, move_value); if (is_pass(move)) { /* pass */ sgftreeAddPlay(&sgftree, to_move, -1, -1); gmp_sendPass(ge); ++passes; } else { /* not pass */ sgftreeAddPlay(&sgftree, to_move, I(move), J(move)); gmp_sendMove(ge, J(move), I(move)); passes = 0; TRACE("\nmy move: %1m\n\n", move); } sgffile_add_debuginfo(sgftree.lastnode, 0.0); sgffile_output(&sgftree); } to_move = OTHER_COLOR(to_move); } /* two passes: game over */ gmp_sendPass(ge); 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); } /* play_gmp() does not return to main(), therefore the score * writing code is here. */ { float score = gnugo_estimate_score(NULL, NULL); sgfWriteResult(sgftree.root, score, 1); } sgffile_output(&sgftree); 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 if (metamachine && oracle_exists) dismiss_oracle(); #endif if (!quiet) fprintf(stderr, "gnugo going down\n"); }
/* * This is just about the world's stupidest go player. It picks random * locations, checking for moves with at least one liberty. If it finds * one, it makes the move. Otherwise it tries again. Eventually it will * give up and pass. * It is so stupid it doesn't even deal with captures or undos. */ static void playGame(Gmp *ge, int size, int himFirst) { int *board, i, x, y; int moveMade, passes = 0; GmpResult message; const char *error; board = malloc(size * size * sizeof(int)); for (i = 0; i < size * size; ++i) board[i] = 0; for (;;) { if (!himFirst) { moveMade = 0; for (i = 0; (i < 50) && !moveMade; ++i) { x = rand() % size; y = rand() % size; if ((board[x + y * size] == 0) && (((x > 0) && (board[(x - 1) + y * size] == 0)) || ((y > 0) && (board[x + (y - 1) * size] == 0)) || ((x < size-1) && (board[(x + 1) + y * size] == 0)) || ((y < size-1) && (board[x + (y + 1) * size] == 0)))) { passes = 0; gmp_sendMove(ge, x, y); board[x + y * size] = 1; moveMade = 1; } } if (!moveMade) { gmp_sendPass(ge); if (++passes == 2) { /* * Game over! */ return; } } } himFirst = 0; do { message = gmp_check(ge, 1, &x, &y, &error); } while (message == gmp_nothing); if (message == gmp_err) { fprintf(stderr, "dummy: Got error \"%s\"\n", error); exit(1); } if (message == gmp_move) { passes = 0; board[x + y * size] = 1; } else if (message == gmp_pass) { if (++passes == 2) { /* * Game over! */ return; } } else if (message == gmp_reset) { /* Game over! */ return; } else if (message == gmp_undo) { fprintf(stderr, "dummy: I am asked to undo %d moves.\n", x); if ((x & 1) == 0) { /* * Since an even number of undos were made, it is still the other * player's turn. This flag makes me skip my turn. */ himFirst = 1; } } else { fprintf(stderr, "Got a \"%s\" command during game play. Exiting.\n", gmp_resultString(message)); exit(1); } } }