;;;###autoload
(defun hanoi (nrings)
"Towers of Hanoi diversion. Argument is number of rings."
- (interactive
- (list (if (null current-prefix-arg)
- 3
- (prefix-numeric-value current-prefix-arg))))
- (if (<= nrings 0) (error "Negative number of rings"))
+ (interactive "p")
+ (if (<= nrings 1) (setq nrings 7))
(let* (floor-row
fly-row
- (window-height (window-height (selected-window)))
+ (window-height (1- (window-height (selected-window))))
(window-width (window-width (selected-window)))
- ;; This is the unit of spacing to use between poles. It
- ;; must be even. We round down, since rounding up might
- ;; cause us to draw off the edge of the window.
- (pole-spacing (logand (/ window-width 6) (lognot 1))))
- (let (
- ;; The poles are (1+ NRINGS) rows high; we also want an
- ;; empty row at the top for the flying rings, a base, and a
- ;; blank line underneath that.
- (h (+ nrings 4))
-
- ;; If we have NRINGS rings, we label them with the numbers 0
- ;; through NRINGS-1. The width of ring i is 2i+3; it pokes
- ;; out i spaces on either side of the pole. Rather than
- ;; checking if the window is wide enough to accommodate this,
- ;; we make sure pole-spacing is large enough, since that
- ;; works even when we have decremented pole-spacing to make
- ;; it even.
- (w (1+ nrings)))
- (if (not (and (>= window-height h)
- (> pole-spacing w)))
- (progn
- (delete-other-windows)
- (if (not (and (>= (setq window-height
- (window-height (selected-window)))
- h)
- (> (setq pole-spacing
- (logand (/ window-width 6) (lognot 1)))
- w)))
- (error "Screen is too small (need at least %dx%d)" w h))))
- (setq floor-row (if (> (- window-height 3) h)
- (- window-height 3) window-height)))
+ ;; This is half the spacing to use between poles.
+ (pole-spacing (/ window-width 6)))
+ (if (not (and (> window-height (1+ nrings))
+ (> pole-spacing nrings)))
+ (progn
+ (delete-other-windows)
+ (if (not (and (> (setq window-height
+ (1- (window-height (selected-window))))
+ (1+ nrings))
+ (> (setq pole-spacing (/ window-width 6))
+ nrings)))
+ (error "Window is too small (need at least %dx%d)"
+ (* 6 (1+ nrings)) (+ 2 nrings)))))
+ (setq floor-row (if (> (- window-height 3) (1+ nrings))
+ (- window-height 3) window-height))
(let ((fly-row (- floor-row nrings 1))
;; pole: column . fill height
- (pole-1 (cons pole-spacing floor-row))
- (pole-2 (cons (* 3 pole-spacing) floor-row))
- (pole-3 (cons (* 5 pole-spacing) floor-row))
+ (pole-1 (cons (1- pole-spacing) floor-row))
+ (pole-2 (cons (1- (* 3 pole-spacing)) floor-row))
+ (pole-3 (cons (1- (* 5 pole-spacing)) floor-row))
(rings (make-vector nrings nil)))
;; construct the ring list
(let ((i 0))
(while (< i nrings)
;; ring: [pole-number string empty-string]
(aset rings i (vector nil
- (make-string (+ i i 3) (+ ?0 i))
+ (make-string (+ i i 3) (+ ?0 (% i 10)))
(make-string (+ i i 3) ?\ )))
(setq i (1+ i))))
;;
(let ((n 1))
(while (< n 6)
- (hanoi-topos fly-row (* n pole-spacing))
+ (hanoi-topos fly-row (1- (* n pole-spacing)))
(setq n (+ n 2))
(let ((i fly-row))
(while (< i floor-row)