Hello, I am working on a "dumb" gui that communicates with GNU Go over gtp. To save games between sessions, I have used loadsgf and printsgf. This is not ideal because printsgf does not save move history, which causes practical issues for playing games over multiple sessions.
To resolve this issue, I have added a new gtp command: printfullsgf, which produces output more similar to the ascii mode "save" command. I am posting this here because 1) I would like to contribute more in the future, and understand that I may need to submit a copyright assignment form before my changes could be incorporated, and 2) I have seen a similar post ignored in the mailing list, so I assume that this is the preferred place for them. Please correct me if either of these is false. Please find attached a patch implementing printfullsgf. Thanks, David Hashe
diff -cr gnugo-dev-orig/interface/play_gtp.c gnugo-dev-mod/interface/play_gtp.c *** gnugo-dev-orig/interface/play_gtp.c 2014-12-09 11:45:25.981240275 -0600 --- gnugo-dev-mod/interface/play_gtp.c 2014-12-09 11:49:47.701247839 -0600 *************** *** 32,40 **** --- 32,42 ---- #include "interface.h" #include "liberty.h" #include "gtp.h" + #include "sgftree.h" #include "gg_utils.h" /* Internal state that's not part of the engine. */ + static SGFTree sgftree; static int report_uncertainty = 0; static int gtp_orientation = 0; *************** *** 140,145 **** --- 142,148 ---- DECLARE(gtp_playwhite); DECLARE(gtp_popgo); DECLARE(gtp_printsgf); + DECLARE(gtp_printfullsgf); DECLARE(gtp_program_version); DECLARE(gtp_protocol_version); DECLARE(gtp_query_boardsize); *************** *** 284,289 **** --- 287,293 ---- {"play", gtp_play}, {"popgo", gtp_popgo}, {"printsgf", gtp_printsgf}, + {"printfullsgf", gtp_printfullsgf}, {"protocol_version", gtp_protocol_version}, {"query_boardsize", gtp_query_boardsize}, {"query_orientation", gtp_query_orientation}, *************** *** 342,347 **** --- 346,355 ---- gtp_orientation = gtp_initial_orientation; gtp_set_vertex_transform_hooks(rotate_on_input, rotate_on_output); + /* Clear sgftree state. */ + sgftree_clear(&sgftree); + sgftreeCreateHeaderNode(&sgftree, board_size, komi, handicap); + /* Initialize time handling. */ init_timers(); *************** *** 370,375 **** --- 378,384 ---- { UNUSED(s); gtp_success(""); + sgfFreeNode(sgftree.root); return GTP_QUIT; } *************** *** 459,464 **** --- 468,475 ---- board_size = boardsize; clear_board(); + sgftree_clear(&sgftree); + sgftreeCreateHeaderNode(&sgftree, boardsize, komi, handicap); gtp_internal_set_boardsize(boardsize); reset_engine(); return gtp_success(""); *************** *** 499,504 **** --- 510,517 ---- if (stones_on_board(BLACK | WHITE) > 0) update_random_seed(); + sgftree_clear(&sgftree); + sgftreeCreateHeaderNode(&sgftree, board_size, komi, handicap); clear_board(); init_timers(); *************** *** 524,529 **** --- 537,544 ---- if (orientation < 0 || orientation > 7) return gtp_failure("unacceptable orientation"); + sgftree_clear(&sgftree); + sgftreeCreateHeaderNode(&sgftree, board_size, komi, handicap); clear_board(); gtp_orientation = orientation; gtp_set_vertex_transform_hooks(rotate_on_input, rotate_on_output); *************** *** 611,616 **** --- 626,634 ---- if (!is_allowed_move(POS(i, j), BLACK)) return gtp_failure("illegal move"); + sgftreeAddPlay(&sgftree, BLACK, i, j); + sgffile_output(&sgftree); + gnugo_play_move(POS(i, j), BLACK); return gtp_success(""); } *************** *** 642,647 **** --- 660,668 ---- if (!is_allowed_move(POS(i, j), WHITE)) return gtp_failure("illegal move"); + sgftreeAddPlay(&sgftree, WHITE, i, j); + sgffile_output(&sgftree); + gnugo_play_move(POS(i, j), WHITE); return gtp_success(""); } *************** *** 666,671 **** --- 687,695 ---- if (!is_allowed_move(POS(i, j), color)) return gtp_failure("illegal move"); + sgftreeAddPlay(&sgftree, color, i, j); + sgffile_output(&sgftree); + gnugo_play_move(POS(i, j), color); return gtp_success(""); } *************** *** 685,692 **** int first = 1; int this_handicap; ! if (gtp_version == 1) clear_board(); else if (stones_on_board(BLACK | WHITE) > 0) return gtp_failure("board not empty"); --- 709,719 ---- int first = 1; int this_handicap; ! if (gtp_version == 1) { ! sgftree_clear(&sgftree); ! sgftreeCreateHeaderNode(&sgftree, board_size, komi, handicap); clear_board(); + } else if (stones_on_board(BLACK | WHITE) > 0) return gtp_failure("board not empty"); *************** *** 697,702 **** --- 724,731 ---- return gtp_failure("invalid handicap"); if (place_fixed_handicap(this_handicap) != this_handicap) { + sgftree_clear(&sgftree); + sgftreeCreateHeaderNode(&sgftree, board_size, komi, handicap); clear_board(); return gtp_failure("invalid handicap"); } *************** *** 708,713 **** --- 737,743 ---- for (m = 0; m < board_size; m++) for (n = 0; n < board_size; n++) if (BOARD(m, n) != EMPTY) { + sgftreeAddStone(&sgftree, BLACK, m, n); if (!first) gtp_printf(" "); else *************** *** 748,753 **** --- 778,784 ---- for (m = 0; m < board_size; m++) for (n = 0; n < board_size; n++) if (BOARD(m, n) != EMPTY) { + sgftreeAddStone(&sgftree, BLACK, m, n); if (!first) gtp_printf(" "); else *************** *** 780,789 **** --- 811,823 ---- n = gtp_decode_coord(s, &i, &j); if (n > 0) { if (board[POS(i, j)] != EMPTY) { + sgftree_clear(&sgftree); + sgftreeCreateHeaderNode(&sgftree, board_size, komi, handicap); clear_board(); return gtp_failure("repeated vertex"); } add_stone(POS(i, j), BLACK); + sgftreeAddStone(&sgftree, BLACK, i, j); s += n; } else if (sscanf(s, "%*s") != EOF) *************** *** 793,798 **** --- 827,834 ---- } if (k < 2) { + sgftree_clear(&sgftree); + sgftreeCreateHeaderNode(&sgftree, board_size, komi, handicap); clear_board(); return gtp_failure("invalid handicap"); } *************** *** 829,835 **** { char filename[GTP_BUFSIZE]; char untilstring[GTP_BUFSIZE]; - SGFTree sgftree; Gameinfo gameinfo; int nread; int color_to_move; --- 865,870 ---- *************** *** 839,844 **** --- 874,880 ---- return gtp_failure("missing filename"); sgftree_clear(&sgftree); + sgftreeCreateHeaderNode(&sgftree, board_size, komi, handicap); if (!sgftree_readfile(&sgftree, filename)) return gtp_failure("cannot open or parse '%s'", filename); *************** *** 856,863 **** reset_engine(); init_timers(); - sgfFreeNode(sgftree.root); - gtp_start_response(GTP_SUCCESS); gtp_mprintf("%C", color_to_move); return gtp_finish_response(); --- 892,897 ---- *************** *** 2427,2432 **** --- 2461,2469 ---- move = genmove(BLACK, NULL, NULL); + sgftreeAddPlay(&sgftree, BLACK, I(move), J(move)); + sgffile_output(&sgftree); + gnugo_play_move(move, BLACK); gtp_start_response(GTP_SUCCESS); *************** *** 2452,2457 **** --- 2489,2497 ---- move = genmove(WHITE, NULL, NULL); + sgftreeAddPlay(&sgftree, WHITE, I(move), J(move)); + sgffile_output(&sgftree); + gnugo_play_move(move, WHITE); gtp_start_response(GTP_SUCCESS); *************** *** 2487,2492 **** --- 2527,2535 ---- if (resign) return gtp_success("resign"); + sgftreeAddPlay(&sgftree, color, I(move), J(move)); + sgffile_output(&sgftree); + gnugo_play_move(move, color); gtp_start_response(GTP_SUCCESS); *************** *** 2666,2671 **** --- 2709,2717 ---- capture_all_dead = save_capture_all_dead; + sgftreeAddPlay(&sgftree, color, I(move), J(move)); + sgffile_output(&sgftree); + gnugo_play_move(move, color); gtp_start_response(GTP_SUCCESS); *************** *** 2817,2822 **** --- 2863,2870 ---- if (stackp > 0 || !undo_move(1)) return gtp_failure("cannot undo"); + sgftreeBack(&sgftree); + reset_engine(); return gtp_success(""); *************** *** 2832,2837 **** --- 2880,2886 ---- static int gtp_gg_undo(char *s) { + int i; int number_moves = 1; sscanf(s, "%d", &number_moves); *************** *** 2842,2847 **** --- 2891,2900 ---- if (stackp > 0 || !undo_move(number_moves)) return gtp_failure("cannot undo"); + for (i = 0; i < number_moves; i++) { + sgftreeBack(&sgftree); + } + reset_engine(); return gtp_success(""); *************** *** 4173,4178 **** --- 4226,4266 ---- } } + /* Function: Dump the current position as a branched sgf file to filename, + * or as output if filename is missing or "-" + * Arguments: optional filename + * Fails: never + * Returns: nothing if filename, otherwise the sgf + */ + static int + gtp_printfullsgf(char *s) + { + char filename[GTP_BUFSIZE]; + int nread; + + nread = sscanf(s, "%s", filename); + + if (nread < 1) + gg_snprintf(filename, GTP_BUFSIZE, "%s", "-"); + + sgf_write_header(sgftree.root, 1, get_random_seed(), komi, + handicap, get_level(), chinese_rules); + if (handicap > 0) + sgffile_recordboard(sgftree.root); + + if (strcmp(filename, "-") == 0) { + gtp_start_response(GTP_SUCCESS); + // sgffile_printsgf(next, filename); + writesgf(sgftree.root, filename); + gtp_printf("\n"); + return GTP_OK; + } + else { + // sgffile_printsgf(next, filename); + writesgf(sgftree.root, filename); + return gtp_success(""); + } + } /* Function: Tune the parameters for the move ordering in the tactical * reading.
_______________________________________________ gnugo-devel mailing list gnugo-devel@gnu.org https://lists.gnu.org/mailman/listinfo/gnugo-devel