[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnugo-devel] Patch to gnugo.el
From: |
bump |
Subject: |
[gnugo-devel] Patch to gnugo.el |
Date: |
Sun, 14 Nov 2004 19:58:37 -0800 |
This is a patch against Thi's gnugo.el version 2.2.7 available
at http://www.glug.org/people/ttn/software/ttn-pers-elisp/standalone/.
Except for copyright notices this is the same as the gnugo.el
in the current cvs (though NOT 3.6-pre4).
This patch requires a patch to the engine:
http://match.stanford.edu/gnugo/patches/move_history_3_6.1b
The patch adds some functionality that I find very useful
though it probably conflicts a little with Thi's vision
of how gnugo.el is to develop, so I'm not proposing to
add it in this form to GNU Go 3.6, though I hope at least
the bug fixes can go in.
A couple of bugs are fixed: the sgf tree and move
history are made correct after loading an sgf file
(which was a fixme), and gnugo-goto-pos doesn't attempt
to go to PASS.
After this patch, you can scroll forward and backward in the
game using the keystrokes `f' and `b', or undo and redo two
moves at a time with `u' and `r'. You can also jump to the
beginning or end of the game with `<' and `>' or to an
arbitrary move number with `j'. If you go to an
arbitrary move then enter a move at that point, the future
game record is discarded, and the engine will counter
with a move. Potentially you can switch colors this
way. But if you don't do play a move, you can browse an
sgf file, just as you could with any sgf editor.
The move number is added to the mode line.
Dan
--- gnugo.el-2.2.7 2004-11-11 08:41:31.712789416 -0800
+++ gnugo.el 2004-11-14 06:52:22.369051536 -0800
@@ -205,12 +205,13 @@
character in the string, then the next, and so on until the string (and/or
the viewer) is exhausted.")
-(defvar gnugo-mode-line "~b ~w :~u"
+(defvar gnugo-mode-line "~b ~w :~m :~u"
"*A `mode-line-format'-compliant value for GNUGO Board mode.
If a single string, the following special escape sequences are
replaced with their associated information:
~b,~w black,white captures (a number)
~p current player (black or white)
+ ~m move number
~t time waiting for the current move
~u time taken for the Ultimate (most recent) move
The times are in seconds, or \"-\" if that information is not available.
@@ -304,7 +305,7 @@
:move-history -- strictly speaking this is redundant since we have the
:sgf-tree, but this list is simple to understand and use;
see function `gnugo-push-move'
-
+ :future-history -- an undo stack. Undone moves are pushed here.
:last-waiting -- seconds and time value, respectively; see `gnugo-push-move'
:waiting-start
@@ -407,16 +408,17 @@
(defun gnugo-goto-pos (pos)
"Move point to board position POS, a letter-number string."
- (goto-char (point-min))
- (forward-line (- (1+ (gnugo-get :board-size))
- (string-to-number (substring pos 1))))
- (forward-char 1)
- (forward-char (+ (if (= 32 (following-char)) 1 2)
- (* 2 (- (let ((letter (aref pos 0)))
- (if (> ?I letter)
- letter
- (1- letter)))
- ?A)))))
+ (unless (string= pos "PASS")
+ (goto-char (point-min))
+ (forward-line (- (1+ (gnugo-get :board-size))
+ (string-to-number (substring pos 1))))
+ (forward-char 1)
+ (forward-char (+ (if (= 32 (following-char)) 1 2)
+ (* 2 (- (let ((letter (aref pos 0)))
+ (if (> ?I letter)
+ letter
+ (1- letter)))
+ ?A))))))
(defun gnugo-f (frag)
(intern (format ":gnugo-%s%s-props" (gnugo-get :diamond) frag)))
@@ -637,6 +639,7 @@
(when userp
(gnugo-put :last-user-bpos (and (not passp) (not resignp) move)))
(gnugo-put :move-history (cons move history))
+ (gnugo-put :future-history nil)
(gnugo-note (if (string= "black" color) :B :W) move t (not resignp))
(when resignp
(gnugo-note :EV "resignation"))
@@ -834,7 +837,7 @@
(cond ((stringp cur)
(setq cur (copy-sequence cur))
(let (acc cut c)
- (while (setq cut (string-match "~[bwptu]" cur))
+ (while (setq cut (string-match "~[bwmptu]" cur))
(aset cur cut ?%)
(setq cut (1+ cut) c (aref cur cut))
(aset cur cut ?s)
@@ -843,6 +846,7 @@
,(case c
(?b '(or (gnugo-get :black-captures) 0))
(?w '(or (gnugo-get :white-captures) 0))
+ (?m '(length (gnugo-get :move-history)))
(?p '(gnugo-other (gnugo-get :last-mover)))
(?t '(let ((ws (gnugo-get :waiting-start)))
(if ws
@@ -1154,10 +1158,101 @@
(insert ")\n")
(write-file filename))))
+(defun gnugo-warp-point ()
+ "Move the cursor to the next-to-last move in the history."
+ (if (cdr (gnugo-get :move-history))
+ (gnugo-goto-pos (car (cdr (gnugo-get :move-history))))))
+
(defun gnugo-read-sgf-file (filename)
"Load a game tree from FILENAME, a file in SGF format."
(interactive "fSGF file to load: ")
- (gnugo-command (format "loadsgf %s" (expand-file-name filename))))
+ (gnugo-command (format "loadsgf %s" (expand-file-name filename)))
+ (let* ((colorhistory
+ (mapcar
+ (lambda (x) (split-string x " "))
+ (split-string
+ (cdr (gnugo-synchronous-send/return "move_history")) "[=\n]")))
+ (k (length colorhistory)))
+ (gnugo-put :move-history
+ (mapcar (lambda (x) (nth 1 x)) colorhistory))
+ (gnugo-put :last-mover
+ (car (car colorhistory)))
+ (gnugo-put :board-size
+ (string-to-number (gnugo-query "query_boardsize")))
+ (gnugo-put :handicap
+ (string-to-number (gnugo-query "get_handicap")))
+ (gnugo-put :komi
+ (string-to-number (gnugo-query "get_komi")))
+ (let ((half (ash (1+ (gnugo-get :board-size)) -1)))
+ (gnugo-goto-pos (format "A%d" half))
+ (forward-char (* 2 (1- half)))
+ (gnugo-put :last-user-bpos
+ (gnugo-put :center-position
+ (get-text-property (point) 'gnugo-position))))
+ (gnugo-note :SZ (gnugo-get :board-size))
+ (gnugo-note :HA (gnugo-get :handicap))
+ (gnugo-note :KM (gnugo-get :komi))
+ (while (> k 0)
+ (decf k)
+ (gnugo-note (if (string= (car (nth k colorhistory)) "black") :B :W)
+ (nth 1 (nth k colorhistory)) t t)))
+ (gnugo-refresh t)
+ (gnugo-warp-point))
+
+(defun gnugo-undo (&optional norefresh)
+ "Undo one move. Interchange the colors of the two players."
+ (interactive)
+ (gnugo-gate)
+ (if (equal
+ (car
+ (split-string (cdr (gnugo-synchronous-send/return "undo")) " ")) "?")
+ (error "cannot undo"))
+ (gnugo-put :future-history
+ (cons (car (gnugo-get :move-history)) (gnugo-get :future-history)))
+ (if (gnugo-get :move-history)
+ (gnugo-put :move-history (cdr (gnugo-get :move-history))))
+ (gnugo-put :sgf-tree (cdr (gnugo-get :sgf-tree)))
+ (gnugo-put :user-color (gnugo-get :last-mover))
+ (gnugo-put :gnugo-color (gnugo-other (gnugo-get :last-mover)))
+ (gnugo-put :last-mover (gnugo-get :gnugo-color))
+ (gnugo-merge-showboard-results)
+ (unless norefresh
+ (gnugo-refresh t)
+ (gnugo-warp-point)))
+
+(defun gnugo-redo (&optional norefresh)
+ "Redo one move from the undo-stack (future-history).
+ Interchange the colors of the two players."
+ (interactive)
+ (gnugo-gate)
+ (if (equal (gnugo-get :future-history) nil)
+ (error "no more undone moves left to redo!"))
+ (let* ((buf (current-buffer))
+ (pos (car (gnugo-get :future-history)))
+ (move (format "play %s %s" (gnugo-get :user-color) pos))
+ (accept (cdr (gnugo-synchronous-send/return move))))
+ (gnugo-note (if (string= "black" (gnugo-get :user-color)) :B :W) pos t t)
+ (gnugo-put :future-history (cdr (gnugo-get :future-history)))
+ (gnugo-put :move-history (cons pos (gnugo-get :move-history)))
+ (gnugo-put :user-color (gnugo-get :last-mover))
+ (gnugo-put :gnugo-color (gnugo-other (gnugo-get :last-mover)))
+ (gnugo-put :last-mover (gnugo-other (gnugo-get :last-mover)))
+ (gnugo-merge-showboard-results)
+ (unless norefresh
+ (gnugo-refresh t)
+ (gnugo-warp-point))))
+
+(defun gnugo-redo-two-moves ()
+ "Redo a pair of moves (yours and GNU Go's).
+If two moves cannot be found, do nothing. (If there is
+exactly one move in the undo stack, you can still redo
+it using gnugo-redo.)"
+ (interactive)
+ (gnugo-gate)
+ (if (cdr (gnugo-get :future-history))
+ (gnugo-redo)
+ (error "can't redo two moves\n"))
+ (gnugo-redo))
(defun gnugo-magic-undo (spec)
"Undo moves on the GNUGO Board, based on SPEC, a string.
@@ -1168,7 +1263,9 @@
moves from the history, signaling an error if the history is exhausted
before finishing. Otherwise, signal \"bad spec\" error.
-Refresh the board for each move undone. If (in the case where SPEC is
+Refresh the board for each move undone. Warp the cursor to the next
+to the next-to-last move (which will be the next move undone if
+the command is executed again). If (in the case where SPEC is
a number) after finishing, the color to play is not the user's color,
schedule a move by GNU Go."
(gnugo-gate)
@@ -1198,6 +1295,8 @@
(setq ans (cdr (gnugo-synchronous-send/return "undo")))
(unless (= ?= (aref ans 0))
(error ans))
+ (gnugo-put :future-history
+ (cons (car (gnugo-get :move-history)) (gnugo-get :future-history)))
(gnugo-put :move-history (cdr (gnugo-get :move-history)))
(gnugo-put :sgf-tree (cdr (gnugo-get :sgf-tree)))
(gnugo-put :last-mover (gnugo-other (gnugo-get :last-mover)))
@@ -1225,6 +1324,32 @@
"1"
"2")))
+(defun gnugo-jump-to-move (movenum)
+ "scroll forward or backward in the game to the given move."
+ (interactive)
+ (unless
+ (and
+ (>= movenum 0)
+ (<= movenum (+ (length (gnugo-get :move-history))
+ (length (gnugo-get :future-history)))))
+ (error "invalid move number"))
+ (while (not (= movenum (length (gnugo-get :move-history))))
+ (if (< movenum (length (gnugo-get :move-history)))
+ (gnugo-undo t)
+ (gnugo-redo t)))
+ (gnugo-refresh t))
+
+(defun gnugo-jump-to-beginning ()
+ "jump to the beginning of the game."
+ (interactive)
+ (gnugo-jump-to-move 0))
+
+(defun gnugo-jump-to-end ()
+ "jump to the end of the game"
+ (interactive)
+ (gnugo-jump-to-move (+ (length (gnugo-get :move-history))
+ (length (gnugo-get :future-history)))))
+
(defun gnugo-display-final-score ()
"Display final score and other info in another buffer (when game over).
If the game is still ongoing, Emacs asks if you wish to stop play (by
@@ -1398,7 +1523,8 @@
(let ((hook
;; do not elide this binding; `run-hooks' needs it
(plist-get spec :post-hook)))
- (run-hooks 'hook))))))))
+ (run-hooks 'hook))))
+ (gnugo-refresh t)))))
;;;---------------------------------------------------------------------------
;;; Major mode for interacting with a GNUGO subprocess
@@ -1419,12 +1545,23 @@
u Run `gnugo-undo-two-moves'.
+ r Redo two moves.
+
U Pass to `gnugo-magic-undo' either the board position
at point (if no prefix arg), or the prefix arg converted
to a number. E.g., to undo 16 moves: `C-u C-u U' (see
`universal-argument'); to undo 42 moves: `M-4 M-2 U'.
- C-l Run `gnugo-refresh'.
+ f Scroll forward (redo one undone move);
+ potentially switch colors.
+
+ b Scroll backward (undo one move); potentially switch colors.
+
+ < Go to the beginning of the game
+
+ > Go to the end of the game
+
+ C-l Run `gnugo-refresh' to redraw the board.
_ or M-_ Bury the Board buffer (when the boss is near).
@@ -1442,7 +1579,9 @@
! Run `gnugo-estimate-score'.
- : or ; Run `gnugo-command' (for GTP commands to GNU Go).
+ : or ; Run `gnugo-command' (for GTP commands to GNU Go). For
+ example, `showboard' will draw the board in ascii with
+ a coordinate grid, useful for reference.
= Display board position under point (if valid).
@@ -1479,6 +1618,7 @@
:mode-line
:mode-line-form
:move-history
+ :future-history
:display-using-images
:xpms
:local-xpms
@@ -1657,6 +1797,13 @@
((consp x) (number-to-string (car x)))
(t (gnugo-position))))))
("u" . gnugo-undo-two-moves)
+ ("r" . gnugo-redo-two-moves)
+ ("f" . gnugo-redo)
+ ("b" . gnugo-undo)
+ ("j" . (lambda (x) (interactive "nJump to move number: ")
+ (gnugo-jump-to-move x)))
+ ("<" . gnugo-jump-to-beginning)
+ (">" . gnugo-jump-to-end)
("\C-l" . gnugo-refresh)
("\M-_" . bury-buffer)
("_" . bury-buffer)
- [gnugo-devel] Patch to gnugo.el,
bump <=