\ MIDNIGHT.SEQ (C) Copyright 1979, 1989 Peter Midnight comment: I first wrote this graphic presentation of the ancient Towers of Hanoi puzzle in Pascal. The class assignment was to use recursion to produce a list of the moves required to solve the puzzle. But I wanted to see the rings move. That version was published in the Jan/Feb 1980 Newsletter of the Homebrew Computer Club. Next I translated this program into FIG Forth. In order to compare the two languages, I resisted the temptation to improve the program in the process of translation. That version is published in FORTH Dimensions Volume 2 Number 2 and in The Best of FORTH Dimensions. Now I have transported the same program into F-PC, again without improvement. This is my first machine readable publication of this program. This program is my claim to fame. As long as its popularity continues, I may never need another. Peter Midnight comment; ONLY FORTH ALSO DEFINITIONS DECIMAL : GOTOXY ( row col --- ) \ position cursor AT ; : CLEARSCREEN ( --- ) \ clear screen CLS ; COLS 3 - 6 / VALUE NMAX \ maximum rings for display size NMAX VALUE N \ number of rings FALSE CONSTANT HELL_FREEZES_OVER TRUE CONSTANT THE_POPE_IS_A_CATHOLIC ASCII + VALUE COLOR \ character used to represent a ring 13 ARRAY RING \ array (1..N) of tower numbers : DELAY ( centiseconds --- ) \ pause for clarity 10 * MS ; : POS ( tower --- col ) \ get display column for tower N 2* 1+ * N + ; : HALFDISPLAY ( color size --- ) \ display half a ring 0 DO DUP EMIT LOOP DROP ; : ( line color size --- ) \ display a whole ring 2DUP HALFDISPLAY ROT 3 < IF BL ELSE ASCII | THEN EMIT HALFDISPLAY ; : DISPLAY ( size col line color --- ) \ display at proper position SWAP >R -ROT OVER - R@ GOTOXY R> -ROT ; : PRESENCE ( tower ring --- f ) \ true if ring is on tower RING + C@ = ; : LINE ( tower --- line ) \ top of pile on tower 4 N 1+ 1 DO OVER I PRESENCE 0= - LOOP NIP ; : RAISE ( size tower --- ) \ raise ring DUP POS SWAP LINE 2 SWAP DO 2DUP I BL DISPLAY \ erase ring where it is 2DUP I 1- COLOR DISPLAY \ show it one line higher -1 +LOOP 2DROP ; : LOWER ( size tower --- ) \ lower ring DUP POS SWAP LINE 1+ 2 DO 2DUP I 1- BL DISPLAY \ erase ring where it is 2DUP I COLOR DISPLAY \ show it one line lower LOOP 2DROP ; : MOVELEFT ( size source destination --- ) \ move ring to left POS SWAP POS 1- DO DUP I 1+ 1 BL DISPLAY \ erase it where it is DUP I 1 COLOR DISPLAY \ show it 1 column left -1 +LOOP DROP ; : MOVERIGHT ( size source destination --- ) \ move ring to right POS 1+ SWAP POS 1+ DO DUP I 1- 1 BL DISPLAY \ erase it where it is DUP I 1 COLOR DISPLAY \ show it 1 column right LOOP DROP ; : TRAVERSE ( size source destination --- ) \ move ring sideways 2DUP > IF MOVELEFT ELSE MOVERIGHT THEN ; : MOVE ( size source destination --- ) \ complete one move KEY? IF 0 N 6 + GOTOXY CURSOR-ON ABORT THEN -ROT 2DUP RAISE >R 2DUP R> ROT TRAVERSE 2DUP RING + C! \ also update location array SWAP LOWER ; \ The following word is the recursive solution to the puzzle. : MULTIMOVE ( size source destination spare --- ) RECURSIVE 3 PICK 1 = \ test for case of smallest ring IF DROP MOVE \ single ring move ELSE 2>R SWAP 1- SWAP 2R> \ refer to next smaller ring, above 4DUP SWAP MULTIMOVE \ move it to spare tower 4DUP DROP \ drop spare tower number ROT 1+ -ROT MOVE \ move specified ring -ROT SWAP MULTIMOVE \ move next smaller ring from spare THEN ; : MAKETOWER ( tower --- ) \ draw tower on display POS 4 N + 3 DO DUP I GOTOXY ASCII | EMIT LOOP DROP ; : MAKEBASE ( --- ) \ draw base on display 0 N 4 + GOTOXY N 6 * 3 + 0 DO ASCII - EMIT LOOP ; : MAKERING ( tower size --- ) \ materialize ring on display 2DUP RING + C! \ mark ring location in array SWAP LOWER ; : SETUP ( --- ) \ initialize display of puzzle CLEARSCREEN CURSOR-OFF N 1+ 0 DO 1 RING I + C! LOOP \ initialize array 3 0 DO I MAKETOWER LOOP \ draw towers MAKEBASE \ draw base 1 N DO 0 I MAKERING -1 +LOOP ; \ materialize rings \ The following word performs the solution repeatedly. : TOWERS ( quantity --- ) \ use specified number of rings 1 MAX NMAX MIN !> N SETUP N 2 0 1 BEGIN OVER POS N 4 + GOTOXY \ put cursor under rings N 0 DO BEEP 50 DELAY LOOP \ announce completion ROT 4DUP MULTIMOVE \ move all to next tower HELL_FREEZES_OVER UNTIL ; \ repeat indefinitely