Commit | Line | Data |
---|---|---|
0b6e8742 | 1 | ;;; hanoi.el --- towers of hanoi in Emacs |
1a06eabd | 2 | |
fc68affa ER |
3 | ;; Author: Damon Anton Permezel |
4 | ;; Maintainer: FSF | |
fc68affa ER |
5 | ;; Keywords: games |
6 | ||
80a677d9 | 7 | ; Author (a) 1985, Damon Anton Permezel |
2f4b997c RS |
8 | ; This is in the public domain |
9 | ; since he distributed it without copyright notice in 1985. | |
55535639 | 10 | ;; This file is part of GNU Emacs. |
0b6e8742 KH |
11 | ; |
12 | ; Support for horizontal poles, large numbers of rings, real-time, | |
13 | ; faces, defcustom, and Towers of Unix added in 1999 by Alakazam | |
14 | ; Petrofsky <Alakazam@Petrofsky.Berkeley.CA.US>. | |
80a677d9 | 15 | |
e41b2db1 ER |
16 | ;;; Commentary: |
17 | ||
18 | ;; Solves the Towers of Hanoi puzzle while-U-wait. | |
19 | ;; | |
20 | ;; The puzzle: Start with N rings, decreasing in sizes from bottom to | |
21 | ;; top, stacked around a post. There are two other posts. Your mission, | |
22 | ;; should you choose to accept it, is to shift the pile, stacked in its | |
23 | ;; original order, to another post. | |
24 | ;; | |
25 | ;; The challenge is to do it in the fewest possible moves. Each move | |
26 | ;; shifts one ring to a different post. But there's a rule; you can | |
27 | ;; only stack a ring on top of a larger one. | |
28 | ;; | |
29 | ;; The simplest nontrivial version of this puzzle is N = 3. Solution | |
30 | ;; time rises as 2**N, and programs to solve it have long been considered | |
31 | ;; classic introductory exercises in the use of recursion. | |
32 | ;; | |
33 | ;; The puzzle is called `Towers of Hanoi' because an early popular | |
34 | ;; presentation wove a fanciful legend around it. According to this | |
35 | ;; myth (uttered long before the Vietnam War), there is a Buddhist | |
36 | ;; monastery at Hanoi which contains a large room with three time-worn | |
37 | ;; posts in it surrounded by 21 golden discs. Monks, acting out the | |
38 | ;; command of an ancient prophecy, have been moving these disks, in | |
39 | ;; accordance with the rules of the puzzle, once every day since the | |
0b6e8742 | 40 | ;; monastery was founded over a thousand years ago. They are said to |
e41b2db1 ER |
41 | ;; believe that when the last move of the puzzle is completed, the |
42 | ;; world will end in a clap of thunder. Fortunately, they are nowhere | |
43 | ;; even close to being done... | |
0b6e8742 KH |
44 | ;; |
45 | ;; 1999 addition: The `Towers of Unix' command (hanoi-unix) stems from | |
46 | ;; the never-disproven legend of a Eunuch monastery at Princeton that | |
47 | ;; contains a large air-conditioned room with three time-worn posts in | |
48 | ;; it surrounded by 32 silicon discs. Nimble monks, acting out the | |
49 | ;; command of an ancient prophecy, have been moving these disks, in | |
50 | ;; accordance with the rules of the puzzle, once every second since | |
51 | ;; the monastery was founded almost a billion seconds ago. They are | |
52 | ;; said to believe that when the last move of the puzzle is completed, | |
53 | ;; the world will reboot in a clap of thunder. Actually, because the | |
54 | ;; bottom disc is blocked by the "Do not feed the monks" sign, it is | |
55 | ;; believed the End will come at the time that disc is to be moved... | |
e41b2db1 | 56 | |
fc68affa ER |
57 | ;;; Code: |
58 | ||
0b6e8742 | 59 | (eval-when-compile |
55df774a DL |
60 | (require 'cl) |
61 | ;; dynamic bondage: | |
62 | (defvar baseward-step) | |
63 | (defvar fly-step) | |
64 | (defvar fly-row-start) | |
65 | (defvar pole-width) | |
66 | (defvar pole-char) | |
67 | (defvar line-offset)) | |
0b6e8742 KH |
68 | |
69 | (defgroup hanoi nil | |
70 | "The Towers of Hanoi." | |
71 | :group 'games) | |
72 | ||
73 | (defcustom hanoi-horizontal-flag nil | |
74 | "*If non-nil, hanoi poles are oriented horizontally." | |
75 | :group 'hanoi :type 'boolean) | |
76 | ||
77 | (defcustom hanoi-move-period 1.0 | |
78 | "*Time, in seconds, for each pole-to-pole move of a ring. | |
79 | If nil, move rings as fast as possible while displaying all | |
80 | intermediate positions." | |
81 | :group 'hanoi :type '(restricted-sexp :match-alternatives (numberp 'nil))) | |
82 | ||
83 | (defcustom hanoi-use-faces nil | |
84 | "*If nil, all hanoi-*-face variables are ignored." | |
85 | :group 'hanoi :type 'boolean) | |
86 | ||
87 | (defcustom hanoi-pole-face 'highlight | |
88 | "*Face for poles. Ignored if hanoi-use-faces is nil." | |
89 | :group 'hanoi :type 'face) | |
90 | ||
91 | (defcustom hanoi-base-face 'highlight | |
92 | "*Face for base. Ignored if hanoi-use-faces is nil." | |
93 | :group 'hanoi :type 'face) | |
94 | ||
95 | (defcustom hanoi-even-ring-face 'region | |
96 | "*Face for even-numbered rings. Ignored if hanoi-use-faces is nil." | |
97 | :group 'hanoi :type 'face) | |
98 | ||
99 | (defcustom hanoi-odd-ring-face 'secondary-selection | |
100 | "*Face for odd-numbered rings. Ignored if hanoi-use-faces is nil." | |
101 | :group 'hanoi :type 'face) | |
102 | ||
80a677d9 JA |
103 | |
104 | ;;; | |
105 | ;;; hanoi - user callable Towers of Hanoi | |
106 | ;;; | |
f9f9507e | 107 | ;;;###autoload |
80a677d9 | 108 | (defun hanoi (nrings) |
a1506d29 | 109 | "Towers of Hanoi diversion. Use NRINGS rings." |
0b6e8742 KH |
110 | (interactive |
111 | (list (if (null current-prefix-arg) | |
112 | 3 | |
113 | (prefix-numeric-value current-prefix-arg)))) | |
114 | (if (< nrings 0) | |
115 | (error "Negative number of rings")) | |
116 | (hanoi-internal nrings (make-list nrings 0) (hanoi-current-time-float))) | |
117 | ||
118 | ;;;###autoload | |
119 | (defun hanoi-unix () | |
120 | "Towers of Hanoi, UNIX doomsday version. | |
121 | Displays 32-ring towers that have been progressing at one move per | |
122 | second since 1970-01-01 00:00:00 GMT. | |
123 | ||
124 | Repent before ring 31 moves." | |
125 | (interactive) | |
126 | (let* ((start (ftruncate (hanoi-current-time-float))) | |
127 | (bits (loop repeat 32 | |
128 | for x = (/ start (expt 2.0 31)) then (* x 2.0) | |
129 | collect (truncate (mod x 2.0)))) | |
130 | (hanoi-move-period 1.0)) | |
131 | (hanoi-internal 32 bits start))) | |
132 | ||
133 | ;;;###autoload | |
134 | (defun hanoi-unix-64 () | |
a1506d29 | 135 | "Like hanoi-unix, but pretend to have a 64-bit clock. |
530324e8 | 136 | This is, necessarily (as of Emacs 20.3), a crock. When the |
0b6e8742 KH |
137 | current-time interface is made s2G-compliant, hanoi.el will need |
138 | to be updated." | |
139 | (interactive) | |
140 | (let* ((start (ftruncate (hanoi-current-time-float))) | |
141 | (bits (loop repeat 64 | |
142 | for x = (/ start (expt 2.0 63)) then (* x 2.0) | |
143 | collect (truncate (mod x 2.0)))) | |
144 | (hanoi-move-period 1.0)) | |
145 | (hanoi-internal 64 bits start))) | |
146 | ||
147 | (defun hanoi-internal (nrings bits start-time) | |
148 | "Towers of Hanoi internal interface. Use NRINGS rings. | |
149 | Start after n steps, where BITS is a big-endian list of the bits of n. | |
150 | BITS must be of length nrings. Start at START-TIME." | |
151 | (switch-to-buffer "*Hanoi*") | |
152 | (buffer-disable-undo (current-buffer)) | |
10a806d3 | 153 | (setq show-trailing-whitespace nil) |
0b6e8742 KH |
154 | (unwind-protect |
155 | (let* | |
530324e8 | 156 | (;; These lines can cause Emacs to crash if you ask for too |
0b6e8742 KH |
157 | ;; many rings. If you uncomment them, on most systems you |
158 | ;; can get 10,000+ rings. | |
159 | ;;(max-specpdl-size (max max-specpdl-size (* nrings 15))) | |
160 | ;;(max-lisp-eval-depth (max max-lisp-eval-depth (+ nrings 20))) | |
161 | (vert (not hanoi-horizontal-flag)) | |
162 | (pole-width (length (format "%d" (max 0 (1- nrings))))) | |
163 | (pole-char (if vert ?\| ?\-)) | |
164 | (base-char (if vert ?\= ?\|)) | |
165 | (base-len (max (+ 8 (* pole-width 3)) | |
166 | (1- (if vert (window-width) (window-height))))) | |
167 | (max-ring-diameter (/ (- base-len 2) 3)) | |
168 | (pole1-coord (/ max-ring-diameter 2)) | |
169 | (pole2-coord (/ base-len 2)) | |
170 | (pole3-coord (- base-len (/ (1+ max-ring-diameter) 2))) | |
171 | (pole-coords (list pole1-coord pole2-coord pole3-coord)) | |
172 | ;; Number of lines displayed below the bottom-most rings. | |
173 | (base-lines | |
174 | (min 3 (max 0 (- (1- (if vert (window-height) (window-width))) | |
175 | (+ 2 nrings))))) | |
176 | ||
177 | ;; These variables will be set according to hanoi-horizontal-flag: | |
178 | ||
179 | ;; line-offset is the number of characters per line in the buffer. | |
180 | line-offset | |
181 | ;; fly-row-start is the buffer position of the leftmost or | |
182 | ;; uppermost position in the fly row. | |
183 | fly-row-start | |
184 | ;; Adding fly-step to a buffer position moves you one step | |
185 | ;; along the fly row in the direction from pole1 to pole2. | |
186 | fly-step | |
187 | ;; Adding baseward-step to a buffer position moves you one step | |
188 | ;; toward the base. | |
189 | baseward-step | |
190 | ) | |
191 | (setq buffer-read-only nil) | |
192 | (erase-buffer) | |
193 | (setq truncate-lines t) | |
194 | (if hanoi-horizontal-flag | |
195 | (progn | |
196 | (setq line-offset (+ base-lines nrings 3)) | |
197 | (setq fly-row-start (1- line-offset)) | |
198 | (setq fly-step line-offset) | |
199 | (setq baseward-step -1) | |
200 | (loop repeat base-len do | |
201 | (unless (zerop base-lines) | |
202 | (insert-char ?\ (1- base-lines)) | |
203 | (insert base-char) | |
204 | (hanoi-put-face (1- (point)) (point) hanoi-base-face)) | |
205 | (insert-char ?\ (+ 2 nrings)) | |
206 | (insert ?\n)) | |
207 | (delete-char -1) | |
208 | (loop for coord in pole-coords do | |
209 | (loop for row from (- coord (/ pole-width 2)) | |
210 | for start = (+ (* row line-offset) base-lines 1) | |
211 | repeat pole-width do | |
212 | (subst-char-in-region start (+ start nrings 1) | |
213 | ?\ pole-char) | |
214 | (hanoi-put-face start (+ start nrings 1) | |
215 | hanoi-pole-face)))) | |
216 | ;; vertical | |
217 | (setq line-offset (1+ base-len)) | |
218 | (setq fly-step 1) | |
219 | (setq baseward-step line-offset) | |
220 | (let ((extra-lines (- (1- (window-height)) (+ nrings 2) base-lines))) | |
221 | (insert-char ?\n (max 0 extra-lines)) | |
222 | (setq fly-row-start (point)) | |
223 | (insert-char ?\ base-len) | |
224 | (insert ?\n) | |
225 | (loop repeat (1+ nrings) | |
226 | with pole-line = | |
227 | (loop with line = (make-string base-len ?\ ) | |
228 | for coord in pole-coords | |
229 | for start = (- coord (/ pole-width 2)) | |
230 | for end = (+ start pole-width) do | |
231 | (hanoi-put-face start end hanoi-pole-face line) | |
232 | (loop for i from start below end do | |
233 | (aset line i pole-char)) | |
234 | finally return line) | |
235 | do (insert pole-line ?\n)) | |
236 | (insert-char base-char base-len) | |
237 | (hanoi-put-face (- (point) base-len) (point) hanoi-base-face) | |
238 | (set-window-start (selected-window) | |
239 | (1+ (* baseward-step | |
240 | (max 0 (- extra-lines))))))) | |
241 | ||
242 | (let | |
243 | (;; each pole is a pair of buffer positions: | |
244 | ;; the car is the position of the top ring currently on the pole, | |
245 | ;; (or the base of the pole if it is empty). | |
246 | ;; the cdr is in the fly-row just above the pole. | |
247 | (poles (loop for coord in pole-coords | |
248 | for fly-pos = (+ fly-row-start (* fly-step coord)) | |
249 | for base = (+ fly-pos (* baseward-step (+ 2 nrings))) | |
250 | collect (cons base fly-pos))) | |
251 | ;; compute the string for each ring and make the list of | |
252 | ;; ring pairs. Each ring pair is initially (str . diameter). | |
253 | ;; Once placed in buffer it is changed to (center-pos . diameter). | |
254 | (rings | |
255 | (loop | |
256 | ;; radii are measured from the edge of the pole out. | |
257 | ;; So diameter = 2 * radius + pole-width. When | |
258 | ;; there's room, we make each ring's radius = | |
259 | ;; pole-number + 1. If there isn't room, we step | |
260 | ;; evenly from the max radius down to 1. | |
261 | with max-radius = (min nrings | |
262 | (/ (- max-ring-diameter pole-width) 2)) | |
263 | for n from (1- nrings) downto 0 | |
264 | for radius = (1+ (/ (* n max-radius) nrings)) | |
265 | for diameter = (+ pole-width (* 2 radius)) | |
266 | with format-str = (format "%%0%dd" pole-width) | |
267 | for str = (concat (if vert "<" "^") | |
268 | (make-string (1- radius) (if vert ?\- ?\|)) | |
269 | (format format-str n) | |
270 | (make-string (1- radius) (if vert ?\- ?\|)) | |
271 | (if vert ">" "v")) | |
272 | for face = | |
cbf48ec9 DL |
273 | (if (eq (logand n 1) 1) ; oddp would require cl at runtime |
274 | hanoi-odd-ring-face hanoi-even-ring-face) | |
0b6e8742 KH |
275 | do (hanoi-put-face 0 (length str) face str) |
276 | collect (cons str diameter))) | |
277 | ;; Disable display of line and column numbers, for speed. | |
278 | (line-number-mode nil) (column-number-mode nil)) | |
279 | ;; do it! | |
280 | (hanoi-n bits rings (car poles) (cadr poles) (caddr poles) | |
281 | start-time)) | |
282 | (message "Done")) | |
283 | (setq buffer-read-only t) | |
284 | (force-mode-line-update))) | |
285 | ||
286 | (defun hanoi-current-time-float () | |
287 | "Return values from current-time combined into a single float." | |
288 | (destructuring-bind (high low micros) (current-time) | |
289 | (+ (* high 65536.0) low (/ micros 1000000.0)))) | |
290 | ||
291 | (defun hanoi-put-face (start end value &optional object) | |
292 | "If hanoi-use-faces is non-nil, call put-text-property for face property." | |
293 | (if hanoi-use-faces | |
294 | (put-text-property start end 'face value object))) | |
295 | ||
296 | \f | |
297 | ;;; Functions with a start-time argument (hanoi-0, hanoi-n, and | |
298 | ;;; hanoi-move-ring) start working at start-time and return the ending | |
299 | ;;; time. If hanoi-move-period is nil, start-time is ignored and the | |
300 | ;;; return value is junk. | |
80a677d9 JA |
301 | |
302 | ;;; | |
0b6e8742 KH |
303 | ;;; hanoi-0 - work horse of hanoi |
304 | (defun hanoi-0 (rings from to work start-time) | |
305 | (if (null rings) | |
306 | start-time | |
307 | (hanoi-0 (cdr rings) work to from | |
308 | (hanoi-move-ring (car rings) from to | |
309 | (hanoi-0 (cdr rings) from work to start-time))))) | |
310 | ||
311 | ;; start after n moves, where BITS is a big-endian list of the bits of n. | |
312 | ;; BITS must be of same length as rings. | |
313 | (defun hanoi-n (bits rings from to work start-time) | |
314 | (cond ((null rings) | |
315 | ;; All rings have been placed in starting positions. Update display. | |
316 | (hanoi-sit-for 0) | |
317 | start-time) | |
318 | ((zerop (car bits)) | |
319 | (hanoi-insert-ring (car rings) from) | |
320 | (hanoi-0 (cdr rings) work to from | |
321 | (hanoi-move-ring (car rings) from to | |
322 | (hanoi-n (cdr bits) (cdr rings) from work to | |
323 | start-time)))) | |
80a677d9 | 324 | (t |
0b6e8742 KH |
325 | (hanoi-insert-ring (car rings) to) |
326 | (hanoi-n (cdr bits) (cdr rings) work to from start-time)))) | |
80a677d9 | 327 | |
0b6e8742 KH |
328 | ;; put never-before-placed RING on POLE and update their cars. |
329 | (defun hanoi-insert-ring (ring pole) | |
330 | (decf (car pole) baseward-step) | |
331 | (let ((str (car ring)) | |
332 | (start (- (car pole) (* (/ (cdr ring) 2) fly-step)))) | |
333 | (setcar ring (car pole)) | |
334 | (loop for pos upfrom start by fly-step | |
335 | for i below (cdr ring) do | |
336 | (subst-char-in-region pos (1+ pos) (char-after pos) (aref str i)) | |
337 | (set-text-properties pos (1+ pos) (text-properties-at i str))) | |
338 | (hanoi-goto-char (car pole)))) | |
80a677d9 | 339 | |
0b6e8742 KH |
340 | ;; like goto-char, but if position is outside the window, then move to |
341 | ;; corresponding position in the first row displayed. | |
342 | (defun hanoi-goto-char (pos) | |
343 | (goto-char (if (or hanoi-horizontal-flag (<= (window-start) pos)) | |
344 | pos | |
345 | (+ (window-start) (% (- pos fly-row-start) baseward-step))))) | |
346 | ||
347 | ;; do one pole-to-pole move and update the ring and pole pairs. | |
348 | (defun hanoi-move-ring (ring from to start-time) | |
349 | (incf (car from) baseward-step) | |
350 | (decf (car to) baseward-step) | |
351 | (let* ;; We move flywards-steps steps up the pole to the fly row, | |
352 | ;; then fly fly-steps steps across the fly row, then go | |
353 | ;; baseward-steps steps down the new pole. | |
354 | ((flyward-steps (/ (- (car ring) (cdr from)) baseward-step)) | |
355 | (fly-steps (abs (/ (- (cdr to) (cdr from)) fly-step))) | |
356 | (directed-fly-step (/ (- (cdr to) (cdr from)) fly-steps)) | |
357 | (baseward-steps (/ (- (car to) (cdr to)) baseward-step)) | |
358 | (total-steps (+ flyward-steps fly-steps baseward-steps)) | |
359 | ;; A step is a character cell. A tick is a time-unit. To | |
360 | ;; make horizontal and vertical motion appear roughly the | |
361 | ;; same speed, we allow one tick per horizontal step and two | |
362 | ;; ticks per vertical step. | |
363 | (ticks-per-pole-step (if hanoi-horizontal-flag 1 2)) | |
364 | (ticks-per-fly-step (if hanoi-horizontal-flag 2 1)) | |
365 | (flyward-ticks (* ticks-per-pole-step flyward-steps)) | |
366 | (fly-ticks (* ticks-per-fly-step fly-steps)) | |
367 | (baseward-ticks (* ticks-per-pole-step baseward-steps)) | |
368 | (total-ticks (+ flyward-ticks fly-ticks baseward-ticks)) | |
369 | (tick-to-pos | |
370 | ;; Return the buffer position of the ring after TICK ticks. | |
371 | (lambda (tick) | |
372 | (cond | |
373 | ((<= tick flyward-ticks) | |
374 | (+ (cdr from) | |
375 | (* baseward-step | |
376 | (- flyward-steps (/ tick ticks-per-pole-step))))) | |
377 | ((<= tick (+ flyward-ticks fly-ticks)) | |
378 | (+ (cdr from) | |
379 | (* directed-fly-step | |
380 | (/ (- tick flyward-ticks) ticks-per-fly-step)))) | |
381 | (t | |
382 | (+ (cdr to) | |
383 | (* baseward-step | |
384 | (/ (- tick flyward-ticks fly-ticks) | |
385 | ticks-per-pole-step)))))))) | |
386 | (if hanoi-move-period | |
387 | (loop for elapsed = (- (hanoi-current-time-float) start-time) | |
388 | while (< elapsed hanoi-move-period) | |
389 | with tick-period = (/ (float hanoi-move-period) total-ticks) | |
390 | for tick = (ceiling (/ elapsed tick-period)) do | |
391 | (hanoi-ring-to-pos ring (funcall tick-to-pos tick)) | |
392 | (hanoi-sit-for (- (* tick tick-period) elapsed))) | |
393 | (loop for tick from 1 to total-ticks by 2 do | |
394 | (hanoi-ring-to-pos ring (funcall tick-to-pos tick)) | |
395 | (hanoi-sit-for 0))) | |
396 | ;; Always make last move to keep pole and ring data consistent | |
397 | (hanoi-ring-to-pos ring (car to)) | |
398 | (if hanoi-move-period (+ start-time hanoi-move-period)))) | |
399 | ||
400 | ;; update display and pause, quitting with a pithy comment if the user | |
401 | ;; hits a key. | |
402 | (defun hanoi-sit-for (seconds) | |
0369eb85 CY |
403 | (unless (sit-for seconds) |
404 | (signal 'quit '("I can tell you've had enough")))) | |
0b6e8742 KH |
405 | |
406 | ;; move ring to a given buffer position and update ring's car. | |
407 | (defun hanoi-ring-to-pos (ring pos) | |
408 | (unless (= (car ring) pos) | |
409 | (let* ((start (- (car ring) (* (/ (cdr ring) 2) fly-step))) | |
410 | (new-start (- pos (- (car ring) start)))) | |
411 | (if hanoi-horizontal-flag | |
412 | (loop for i below (cdr ring) | |
413 | for j = (if (< new-start start) i (- (cdr ring) i 1)) | |
414 | for old-pos = (+ start (* j fly-step)) | |
415 | for new-pos = (+ new-start (* j fly-step)) do | |
416 | (transpose-regions old-pos (1+ old-pos) new-pos (1+ new-pos))) | |
417 | (let ((end (+ start (cdr ring))) | |
418 | (new-end (+ new-start (cdr ring)))) | |
419 | (if (< (abs (- new-start start)) (- end start)) | |
420 | ;; Overlap. Adjust bounds | |
421 | (if (< start new-start) | |
422 | (setq new-start end) | |
423 | (setq new-end start))) | |
424 | (transpose-regions start end new-start new-end t)))) | |
425 | ;; If moved on or off a pole, redraw pole chars. | |
426 | (unless (eq (hanoi-pos-on-tower-p (car ring)) (hanoi-pos-on-tower-p pos)) | |
427 | (let* ((pole-start (- (car ring) (* fly-step (/ pole-width 2)))) | |
428 | (pole-end (+ pole-start (* fly-step pole-width))) | |
429 | (on-pole (hanoi-pos-on-tower-p (car ring))) | |
430 | (new-char (if on-pole pole-char ?\ )) | |
431 | (curr-char (if on-pole ?\ pole-char)) | |
432 | (face (if on-pole hanoi-pole-face nil))) | |
433 | (if hanoi-horizontal-flag | |
434 | (loop for pos from pole-start below pole-end by line-offset do | |
435 | (subst-char-in-region pos (1+ pos) curr-char new-char) | |
436 | (hanoi-put-face pos (1+ pos) face)) | |
437 | (subst-char-in-region pole-start pole-end curr-char new-char) | |
438 | (hanoi-put-face pole-start pole-end face)))) | |
439 | (setcar ring pos)) | |
440 | (hanoi-goto-char pos)) | |
441 | ||
442 | ;; Check if a buffer position lies on a tower (vis. in the fly row). | |
443 | (defun hanoi-pos-on-tower-p (pos) | |
444 | (if hanoi-horizontal-flag | |
445 | (/= (% pos fly-step) fly-row-start) | |
446 | (>= pos (+ fly-row-start baseward-step)))) | |
80a677d9 | 447 | |
62daf326 RM |
448 | (provide 'hanoi) |
449 | ||
cbee283d | 450 | ;; arch-tag: 7a901659-4346-495c-8883-14cbf540610c |
62daf326 | 451 | ;;; hanoi.el ends here |