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
[email protected]
https://lists.gnu.org/mailman/listinfo/gnugo-devel