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

Reply via email to