Implement undo command
authorH.G. Muller <h.g.muller@hccnet.nl>
Fri, 13 Sep 2013 13:42:27 +0000 (15:42 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Fri, 13 Sep 2013 17:49:50 +0000 (19:49 +0200)
This is decoded with the native bonanza commands, and should thus work
both in xboard and native mode. It resets the game by faking a 'new' command,
and then loads all moves except the last. For this the move list and startup
string needed to be remembered.

makemove.c
proce.c
readme.txt
shogi.h

index 83d8c9e..7ed2b7d 100644 (file)
@@ -421,6 +421,7 @@ make_move_root( tree_t * restrict ptree, unsigned int move, int flag )
     }
 
   root_turn = Flip( root_turn );
+  move_list[move_ptr++] = move; // [HGM] undo: remember all moves played in root
 
   /* detect checkmate */
   if ( check && is_mate( ptree, 1 ) ) { game_status |= flag_mated; }
@@ -500,6 +501,7 @@ unmake_move_root( tree_t * restrict ptree, unsigned int move )
   root_nrep   -= 1;
   game_status &= ~( flag_drawn | flag_mated );
   root_turn   = Flip(root_turn);
+  move_ptr--; // [HGM] undo: clip last move off game history
 
   ptree->save_material[1]      = ptree->save_material[0];
   UnMakeMove( root_turn, move, 1 );
diff --git a/proce.c b/proce.c
index 94db5d0..214c78b 100644 (file)
--- a/proce.c
+++ b/proce.c
@@ -74,6 +74,7 @@ static int cmd_new( tree_t * restrict ptree, char **lasts );
 static int cmd_read( tree_t * restrict ptree, char **lasts );
 static int cmd_resign( tree_t * restrict ptree, char **lasts );
 static int cmd_time( char **lasts );
+static int cmd_undo( tree_t * restrict ptree );    // [HGM] undo
 static int is_move( const char *str );
 
 
@@ -90,6 +91,9 @@ procedure( tree_t * restrict ptree )
   return proce_cui( ptree );
 }
 
+char *start_pos, start_data[512]; // [HGM] undo: for remembering start position
+int move_list[1024], move_ptr;
+
 #ifdef XBOARD
 #define IF(X) else if(!strcmp(command, X))
 
@@ -168,7 +172,8 @@ Out("# from=%d\n",from);
                        sprintf(line, "%c%c%c%c%s", 'a'+'9'-fromX, '1'+'9'-fromY, 'a'+'9'-toX, '1'+'9'-toY,
                                  astr_table_piece[abs(BOARD[from]) + (promo == '+' ? promote : 0)]);
                    }
-                   plyNr++; return 0;
+                   plyNr++;
+                   return 0;
                  }
   IF("undo")     { ; }
   IF("remove")   { ; }
@@ -214,6 +219,7 @@ proce_cui( tree_t * restrict ptree )
   if ( ! strcmp( token, "resign" ) )    { return cmd_resign( ptree, &last ); }
   if ( ! strcmp( token, "suspend" ) )   { return cmd_suspend(); }
   if ( ! strcmp( token, "time" ) )      { return cmd_time( &last ); }
+  if ( ! strcmp( token, "undo" ) )      { return cmd_undo( ptree ); }    // [HGM] undo
 #if defined(CSA_LAN)
   if ( ! strcmp( token, "connect" ) )   { return cmd_connect( ptree, &last ); }
 #endif
@@ -384,6 +390,27 @@ cmd_mnjmove( tree_t * restrict ptree, char **lasts, int is_alter )
 #endif
 
 
+static int
+cmd_undo( tree_t * restrict ptree )
+{ // [HGM] undo: restart the game, and feed all moves except the last
+  int i, last = move_ptr;
+  char *p = start_data;
+  if( move_ptr <= 0 ) {
+    str_error = "undo past start of game ignored";
+    return -2;
+  }
+
+  AbortDifficultCommand;
+
+  last--;
+  cmd_new( ptree, &p );
+  for(i=0; i<last; i++) {
+    make_move_root( ptree, move_list[i], 0);
+  }
+  return 1;
+}
+
+
 static int
 is_move( const char *str )
 {
@@ -1159,8 +1186,11 @@ cmd_new( tree_t * restrict ptree, char **lasts )
 
   AbortDifficultCommand;
 
+  start_pos = *lasts; move_ptr = 0; // [HGM] undo: remember start position
+
   if ( str1 != NULL )
     {
+      strncpy(start_data, str1, 511); // [HGM] undo: remember start position
       memset( &min_posi.asquare, empty, nsquare );
       min_posi.hand_black = min_posi.hand_white = 0;
       iret = read_board_rep1( str1, &min_posi );
index 7aaf0fb..02641a8 100644 (file)
@@ -539,6 +539,9 @@ directory to dump log files.
     when TLP macro is defined in the Makefile. 'num' is the number of
     threads. The default value is 1.
 
+- undo
+    This command causes the latest move to be taken back.
+
 - #
     A line beginning with # causes all characters on that line
     to be ignored.
diff --git a/shogi.h b/shogi.h
index 809e687..1aa2585 100644 (file)
--- a/shogi.h
+++ b/shogi.h
@@ -1023,6 +1023,7 @@ extern const char ach_turn[2];
 extern const char ashell_h[ SHELL_H_LEN ];
 extern const unsigned char aifile[ nsquare ];
 extern const unsigned char airank[ nsquare ];
+extern int move_list[], move_ptr; // [HGM] undo: game history (used in proce.c and makemove.c)
 
 void pv_close( tree_t * restrict ptree, int ply, int type );
 void pv_copy( tree_t * restrict ptree, int ply );