emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] 01/01: [gnugo] Add command ‘g nugo-frolic-in-the-leaves’ and keyb


From: Thien-Thi Nguyen
Subject: [elpa] 01/01: [gnugo] Add command ‘g nugo-frolic-in-the-leaves’ and keybinding.
Date: Thu, 03 Apr 2014 10:49:39 +0000

ttn pushed a commit to branch master
in repository elpa.

commit 4f5a05271906e3dcdcb4866d67eebc52a813ca11
Author: Thien-Thi Nguyen <address@hidden>
Date:   Thu Apr 3 12:50:09 2014 +0200

    [gnugo] Add command ‘gnugo-frolic-in-the-leaves’ and keybinding.
    
    * packages/gnugo/gnugo.el: Require ‘ascii-art-to-unicode’.
    (gnugo--as-pos-func): New func.
    (gnugo-frolic-in-the-leaves): New command.
    (gnugo-board-mode-map): Bind ‘L’ to ‘gnugo-frolic-in-the-leaves’.
---
 packages/gnugo/NEWS     |    1 +
 packages/gnugo/gnugo.el |  233 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 234 insertions(+), 0 deletions(-)

diff --git a/packages/gnugo/NEWS b/packages/gnugo/NEWS
index ee374a2..5a4d9d0 100644
--- a/packages/gnugo/NEWS
+++ b/packages/gnugo/NEWS
@@ -16,6 +16,7 @@ NB: "RCS: X..Y " means that the particular release includes
   - new keybinding for ‘gnugo-undo-one-move’: M-u
   - ‘gnugo-undo-one-move’ can optionally arrange for you to play next
   - new command: ‘o’ (gnugo-oops)
+  - new command: ‘L’ (gnugo-frolic-in-the-leaves)
   - ‘gnugo-move-history’ returns last two moves w/ RSEL ‘two’
   - performance improvements
   - of interest to hackers (see source, BI => backward incompatible)
diff --git a/packages/gnugo/gnugo.el b/packages/gnugo/gnugo.el
index b2f9333..ce93f1c 100644
--- a/packages/gnugo/gnugo.el
+++ b/packages/gnugo/gnugo.el
@@ -75,6 +75,7 @@
 ;;; Code:
 
 (eval-when-compile (require 'cl))       ; use the source luke!
+(require 'ascii-art-to-unicode)         ; for `aa2u'
 (require 'time-date)                    ; for `time-subtract'
 
 ;;;---------------------------------------------------------------------------
@@ -633,6 +634,17 @@ when you are sure the command cannot fail."
   (or (assq :B node)
       (assq :W node)))
 
+(defun gnugo--as-pos-func (size)
+  (lexical-let ((size size))
+    ;; rv
+    (lambda (cc)
+      (if (string= "" cc)
+          "PASS"
+        (let ((col (aref cc 0)))
+          (format "%c%d"
+                  (+ ?A (- (if (> ?i col) col (1+ col)) ?a))
+                  (- size (- (aref cc 1) ?a))))))))
+
 (defun gnugo-move-history (&optional rsel)
   "Determine and return the game's move history.
 Optional arg RSEL controls side effects and return value.
@@ -682,6 +694,226 @@ For all other values of RSEL, do nothing and return nil."
         (`two (nn) (nn) acc)
         (_ nil)))))
 
+(defun gnugo-frolic-in-the-leaves ()
+  "Display the game tree in a *GNUGO Frolic* buffer.
+This looks something like:
+
+  1 B  --  E7    E7    E7    E7
+  2 W  --  K10   K10   K10   K10
+  3 B  --  E2    E2    E2    E2
+  4 W  --  J3    J3    J3    J3
+  5 B  --  A6    A6    A6    A6
+  6 W  --  C9    C9    C9    C9
+           │
+           ├─────┬─────┐
+           │     │     │
+  7 B  --  H7    B8    C8    C8
+                       │
+                       ├─────┐
+                       │     │
+  8 W  --  D9    D9    D9    E9
+  9 B  --              H8    H8
+ 10 W  --              PASS  PASS
+ 11 B  --              H5    PASS
+ 12 W  --              PASS
+ 13 B  --             *PASS
+
+with 0, 1, ... N (in this case N is 3) in the header line
+to indicate the branches.  Branch 0 is the \"main line\".
+Point (* in this example) indicates the current position,
+and moves not actually on the game tree (e.g., E7, branch 3)
+are dimmed.  The buffer is in View minor mode."
+  (interactive)
+  (let* ((buf (get-buffer-create (concat (gnugo-get :diamond)
+                                         "*GNUGO Frolic*")))
+         ;; todo: use defface once we finally succumb to ‘customize’
+         (dimmed-node-face (list :inherit 'default
+                                 :foreground "gray50"))
+         (tree (gnugo-get :sgf-gametree))
+         (seen (make-hash-table :test 'eq))
+         (soil (make-hash-table :test 'eq))
+         (width (length tree))
+         (lanes (number-sequence 0 (1- width)))
+         (monkey (gnugo-get :monkey))
+         (as-pos (gnugo--as-pos-func (gnugo-get :SZ)))
+         (at (car (aref monkey 0)))
+         (bidx (aref monkey 1))
+         (max-move-num (aref monkey 2))
+         (eert (make-vector width nil))
+         finish)
+    (cl-flet
+        ((on (node)
+             (gethash node seen))
+         (emph (s face)
+               (propertize s 'face face))
+         (fsi (fmt &rest args)
+              (insert (apply 'format fmt args))))
+      ;; breathe in
+      (let ((order (make-hash-table :test 'eq))
+            (monkey-on-main-line (zerop bidx))
+            fixup)
+        ;; monkey knows a lot
+        (loop with move-num = (1+ max-move-num)
+              with acc
+              for node in (aref monkey 0)
+              do (puthash node bidx seen)
+              if (gnugo--move-prop node)
+              do (progn
+                   (push node acc)
+                   (puthash node (decf move-num) order))
+              finally do (progn
+                           (unless monkey-on-main-line
+                             (setq fixup (apply 'vector acc)))
+                           (aset eert bidx acc)))
+        ;; but monkey does not know everything
+        (loop
+         for bx below width
+         do (loop
+             with (bef acc node fork cur)
+             for ls on (aref tree bx)
+             do (if (setq node (car ls)
+                          fork (on node))
+                    (cl-flet
+                        ((link (other)
+                               (push other (gethash node soil))))
+                      (let ((move-num (gethash node order)))
+                        (when (< bx fork)
+                          (assert (and (not monkey-on-main-line)
+                                       (= fork bidx)))
+                          (loop for old in ls
+                                while (< bx (on old))
+                                do (puthash old bx seen))
+                          (when (< move-num (length fixup))
+                            (link (aref fixup move-num))))
+                        ;; ugh, wasteful
+                        (when (setq bef (copy-sequence (aref eert fork)))
+                          (setcdr (nthcdr (1- move-num) bef)
+                                  acc))
+                        (aset eert bx (or bef acc))
+                        (dolist (node acc)
+                          (puthash node (incf move-num)
+                                   order))
+                        (setq max-move-num (max max-move-num
+                                                move-num))
+                        (when acc
+                          (link (car acc)))))
+                  (puthash node bx seen)
+                  (when (gnugo--move-prop node)
+                    (push node acc)))
+             until fork)))
+      ;; breathe out
+      (switch-to-buffer buf)
+      (when view-mode
+        (view-mode -1))
+      (buffer-disable-undo)
+      (erase-buffer)
+      (setq header-line-format
+            (concat (make-string 11 ?\s)
+                    (mapconcat (lambda (n)
+                                 (format "%-5s" n))
+                               lanes
+                               " ")))
+      (loop
+       for n                            ; move number
+       from 1 upto max-move-num
+       do
+       (loop
+        with (move forks br)
+        initially (fsi "%3d %s  -- "
+                       n (aref ["W" "B"] (logand 1 n)))
+        for bx below width
+        do (let* ((node (pop (aref eert bx)))
+                  (ok (when node
+                        (= bx (on node))))
+                  (s (cond ((not node) "")
+                           ((not (setq move (gnugo--move-prop node))) "-")
+                           (t (funcall as-pos (cdr move))))))
+             ;; todo: move this into "breathe in"
+             (when (and ok (setq br (gethash node soil)))
+               (setq br (delq bx (mapcar #'on br)))
+               (when (and br (car (aref eert bx)))
+                 (push bx br))
+               ;; do not point w/ a fist
+               (when br
+                 (push (cons bx (sort br '<))
+                       forks)))
+             (fsi " %-5s"
+                  (cond ((and (eq at node)
+                              (or ok (= bx bidx)))
+                         (when (= bx bidx)
+                           (setq finish (point)))
+                         (emph s (list :inherit 'default
+                                       :foreground (frame-parameter
+                                                    nil 'cursor-color))))
+                        ((not ok)
+                         (emph s dimmed-node-face))
+                        (t s))))
+        finally do
+        (when (progn (newline)
+                     (setq forks (nreverse forks)))
+          (let* ((margin (make-string 11 ?\s))
+                 (count (length forks))
+                 (heads (mapcar #'car forks))
+                 (tails (mapcar #'cdr forks)))
+            (cl-flet*
+                ((spaced (lanes func)
+                         (mapconcat func lanes "     "))
+                 ;;  live to play               ~   ~              ()
+                 ;;  play to learn             (+) (-)       . o O
+                 ;;  learn to live  --ttn        .M.   _____U
+                 (dashed (lanes func) ;;;       _____ ^^^^
+                         (mapconcat func lanes "-----"))
+                 (cnxn (lanes set)
+                       (spaced lanes (lambda (bx)
+                                       (if (memq bx set)
+                                           "|"
+                                         " "))))
+                 (pad-unless (condition)
+                             (if condition
+                                 ""
+                               "     "))
+                 (edge (set)
+                       (insert margin
+                               (cnxn lanes set)
+                               "\n")))
+              (edge heads)
+              (loop with bef
+                    for ls on forks
+                    do (let* ((one (car ls))
+                              (yes (append
+                                    ;; "aft" heads
+                                    (mapcar 'car (cdr ls))
+                                    ;; ‘bef’ tails
+                                    (apply 'append (mapcar 'cdr bef))))
+                              (ord (sort one '<))
+                              (beg (car ord))
+                              (end (car (last ord))))
+                         (cl-flet
+                             ((also (b e) (cnxn (number-sequence b e)
+                                                yes)))
+                           (insert
+                            margin
+                            (also 0 (1- beg))
+                            (pad-unless (zerop beg))
+                            (dashed (number-sequence beg end)
+                                    (lambda (bx)
+                                      (cond ((memq bx ord) "+")
+                                            ((memq bx yes) "|")
+                                            (t             "-"))))
+                            (pad-unless (>= end width))
+                            (also (1+ end) (1- width))
+                            "\n"))
+                         (push one bef)))
+              (edge (apply 'append tails))
+              ;; NB: This requires ascii-art-to-unicode.el 1.5 or later.
+              (aa2u (line-beginning-position
+                     (- (1+ (length forks))))
+                    (point))))))))
+    (when finish
+      (goto-char finish)
+      (recenter (- (count-lines (line-beginning-position) (point-max)))))
+    (view-mode 1)))
+
 (defun gnugo-boss-is-near ()
   "Do `bury-buffer' until the current one is not a GNU Board."
   (interactive)
@@ -1955,6 +2187,7 @@ starting a new one.  See `gnugo-board-mode' documentation 
for more info."
           ("\M-_"     . gnugo-boss-is-near)
           ("_"        . gnugo-boss-is-near)
           ("h"        . gnugo-move-history)
+          ("L"        . gnugo-frolic-in-the-leaves)
           ("i"        . gnugo-toggle-image-display-command)
           ("w"        . gnugo-worm-stones)
           ("W"        . gnugo-worm-data)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]