|
|
1.1 root 1: ;
2: ; hanoi - towers of hanoi in GNUmacs
3: ;
4: ; Author (a) 1985, Damon Anton Permezel
5: ;
6:
7: ;;;
8: ;;; hanoi-topos - direct cursor addressing
9: ;;;
10: (defun hanoi-topos (row col)
11: (goto-line row)
12: (beginning-of-line)
13: (forward-char col))
14:
15: ;;;
16: ;;; hanoi - user callable Towers of Hanoi
17: ;;;
18: (defun hanoi (n-rings)
19: "Towers of Hanoi diversion. Arg is number of rings."
20: (interactive "p")
21: (if (or (> n-rings 9) (<= n-rings 0))
22: (error "Funny number of rings"))
23:
24: (let ((floor-row 21)
25: (fly-row (- 21 n-rings 1))
26: (pole-1 (cons 20 20)) ; pole: column . fill height
27: (pole-2 (cons 40 20)) ; (these must be consed, not '(x . y)
28: (pole-3 (cons 60 20)) ; otherwise we are not reentrant)
29: (rings '(t (1 . 0) (2 . 0) (3 . 0) (4 . 0) (5 . 0)
30: (6 . 0) (7 . 0) (8 . 0) (9 . 0))))
31: ;;
32: ;; init the screen
33: ;;
34: (switch-to-buffer " *Hanoi*")
35: (delete-other-windows)
36: (erase-buffer)
37:
38: (let ((i 1)) ; 21 copies of a line of 78 blanks
39: (while (< i floor-row)
40: (setq i (1+ i))
41: (insert " \n")))
42:
43: (let ((i 0)) ; draw the base
44: (while (< i 78)
45: (setq i (1+ i))
46: (insert ?=)))
47:
48: (mapcar (function (lambda (x) ; draw the towers
49: (hanoi-topos fly-row x)
50: (let ((i fly-row))
51: (while (< i floor-row)
52: (setq i (1+ i))
53: (next-line 1)
54: (insert ?|)
55: (delete-char 1)
56: (backward-char 1)))))
57: '(20 40 60))
58: (sit-for 0)
59: ;;
60: ;; now init the rings
61: ;;
62: (let ((where (1- floor-row))
63: (i n-rings)
64: r)
65: (while (> i 0)
66: (setq r (car (nthcdr i rings))) ; extract desired ring
67: (setcdr r where) ; indicate ring row
68: (setq where (1- where))
69: (hanoi-move-ring i pole-1 pole-1)
70: (setq i (1- i))))
71: (sit-for 0)
72: (hanoi0 n-rings pole-1 pole-2 pole-3))
73: (message "Done"))
74:
75: ;;;
76: ;;; hanoi0 - work horse of hanoi
77: ;;;
78: (defun hanoi0 (n from to work)
79: (if (> n 0)
80: (progn
81: (hanoi0 (1- n) from work to)
82: (hanoi-move-ring n from to)
83: (hanoi0 (1- n) work to from))))
84:
85: ;;;
86: ;;; hanoi-move-ring - move ring 'n' from 'from' to 'to'
87: ;;;
88: ;;; from and to are dotted pairs consisting of (pole col . fill height)
89: ;;;
90: (defun hanoi-move-ring (n from to)
91: (let ((r (car (nthcdr n rings)))) ; r <- ring: (ring# . row)
92: (if (eq from to) ; must change poles?
93: ;;
94: ;; ring on same pole - used for initialization
95: ;;
96: (progn
97: (hanoi-topos (cdr to) (- (car to) n))
98: (hanoi-draw-ring n t nil)
99: (setcdr to (1- (cdr to))))
100: (let ((row (cdr r)) ; row <- row ring is on
101: (col (- (car from) n)) ; col <- left edge of ring
102: (dst-col (- (car to) n)) ; dst-col <- dest col for left edge
103: (dst-row (cdr to))) ; dst-row <- dest row for ring
104: (hanoi-topos row col)
105: (while (> row fly-row) ; move up to the fly row
106: (hanoi-draw-ring n nil nil) ; blank out ring
107: (previous-line 1) ; move up a line
108: (hanoi-draw-ring n t nil) ; redraw
109: (sit-for 0)
110: (setq row (1- row)))
111: (setcdr from (1+ (cdr from))) ; adjust top row
112: ;;
113: ;; fly the ring over to the right pole
114: ;;
115: (while (not (equal dst-col col))
116: (cond ((> dst-col col) ; dst-col > col: right shift
117: (end-of-line 1)
118: (delete-backward-char 2)
119: (beginning-of-line 1)
120: (insert " ")
121: (sit-for 0)
122: (setq col (1+ (1+ col))))
123: ((< dst-col col) ; dst-col < col: left shift
124: (beginning-of-line 1)
125: (delete-char 2)
126: (end-of-line 1)
127: (insert " ")
128: (sit-for 0)
129: (setq col (1- (1- col))))))
130: ;;
131: ;; let the ring float down
132: ;;
133: (hanoi-topos fly-row dst-col)
134: (while (< row dst-row) ; move down to the dest row
135: (hanoi-draw-ring n nil (equal row fly-row)) ; blank out ring
136: (next-line 1) ; move down a line
137: (hanoi-draw-ring n t nil) ; redraw ring
138: (sit-for 0)
139: (setq row (1+ row)))
140: (setcdr r dst-row)
141: (setcdr to (1- (cdr to))))))) ; adjust top row
142:
143: ;;;
144: ;;; hanoi-draw-ring - draw the ring at dot, leave dot unchanged
145: ;;;
146: ;;; Input:
147: ;;; n - ring #. used to select drawing character
148: ;;; f1 - flag: t -> draw, nil -> erase
149: ;;; f2 - flag: t -> erasing ring from fly-row -> dont redraw ?|
150: ;;;
151: (defun hanoi-draw-ring (n f1 f2)
152: (save-excursion
153: (let ((i 0)
154: (repl (if f1
155: (car (nthcdr n '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)))
156: ? )))
157: (delete-char (+ 1 (* 2 n)))
158: (while (< i n)
159: (insert repl)
160: (setq i (1+ i)))
161: (insert (if f1 repl (if f2 ? ?|)))
162: (setq i 0)
163: (while (< i n)
164: (insert repl)
165: (setq i (1+ i))))))
166:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.