ram@altger.UUCP (Reimer A. Mellin) (12/07/88)
Hello,
The uEMACS Macro-language is quite powerful but can't handle recursive
function-calls (at least in 3.9i). So here is one way of implementing
recursive calls.... As a first test I programmed the Towers of Hanoi.
Please realize that my version isn't programmed for speed but for
straightforwardness (mostly :-).
You should have the programm 'banner' on your system, because hanoi will
use it via 'pipe-command' to generate a neat title-page.
The numbers of the disks are also restricted to 9, because the pushing
of the parameters is done with characters. (someone going to fix this
?, maybe pushing of %number as '&chr %number' and reading with '&asc
%number' ?)
starting hanoi:
interpret hanoi.cmd with the '-f'-option or with the
'execute-buffer'-command. Then call the procedure hanoi with 'run
hanoi'. Hanoi then asks for the number of disks and will display the
moves.
At this point I want to express my thank to Daniel Lawrence for this
really small, neat, powerful and FREE editor.
Greetings
Reimer Mellin
------------------------S-T-A-R-T----------------------------------------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: hanoi.cmd
# Wrapped by ram@ramsys on Wed Dec 7 00:39:33 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'hanoi.cmd' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'hanoi.cmd'\"
else
echo shar: Extracting \"'hanoi.cmd'\" \(4811 characters\)
sed "s/^X//" >'hanoi.cmd' <<'END_OF_FILE'
X; The Towers of Hanoi for the uEMACS 3.9e
X; Author: Reimer A. Mellin (ram@altger)
X; Date: 6.12.1988
X; Implements the recursive algorith. with a buffer :-)
X; Well, why shouldn't it work ?
X; Just intended as a test version for recursion ....
X; Copy, modify, use, abuse this as you like ....
X
X; BTW: dont forget Green-peace and all organizations against famine in
X; the third world.
X
X
X;This procedure pushes the string %pusharg on our stack ....
X;i.e. writes at the end of the buffer
Xstore-procedure push
X select-buffer [stack]
X insert-string %pusharg
X newline
X!endm
X
X;here we kill our actual context (the previous line in the stack-buffer)
X;and re-read our old context !!!
Xstore-procedure pop
X select-buffer [stack]
X previous-line
X kill-to-end-of-line
X run readarg
X!endm
X
X; read the current incarnation of our variables on the stack.
Xstore-procedure readarg
X select-buffer [stack]
X set-mark
X previous-line
X exchange-point-and-mark
X copy-region
X set %number &left $kill 1
X set %src &mid $kill 2 1
X set %aux &mid $kill 3 1
X set %dest &mid $kill 4 1
X!endm
X
X;just a silly procedure to print our first screen of the towers
Xstore-procedure init-screen
X beginning-of-file
X set-mark
X end-of-file
X kill-region
X set %i 0
X !while ¬ &equ %i &sub 10 %number
X insert-string &cat %trenner &cat %disk0
X insert-string &cat %trenner &cat %disk0
X insert-string &cat %trenner &cat %disk0
X newline
X set %i &add %i 1
X !endwhile
X set %j 1
X !while ¬ &equ %i 10
X set %ivar &cat "%disk" %j
X insert-string &cat %trenner &cat &ind %ivar
X insert-string &cat %trenner &cat %disk0
X insert-string &cat %trenner &cat %disk0
X newline
X set %i &add %i 1
X set %j &add %j 1
X !endwhile
X 75 insert-string "^"
X update-screen
X set %j @"Press Return to start the fun ..."
X!endm
X
X; the various disks and their starting positions on the first screen
Xstore-procedure init-vars
X set %disk9 "#########|#########"
X set %disk8 " ########|######## "
X set %disk7 " #######|####### "
X set %disk6 " ######|###### "
X set %disk5 " #####|##### "
X set %disk4 " ####|#### "
X set %disk3 " ###|### "
X set %disk2 " ##|## "
X set %disk1 " #|# "
X set %disk0 " | "
X set %trenner " "
X set %ynoL %number
X set %ynoM 0
X set %ynoR 0
X set %xnoL 5
X set %xnoM 29
X set %xnoR 53
X!endm
X
X;do the move of the uppermost disk on 'src' to 'dest'
Xstore-procedure moveone
X select-buffer [output]
X;delete old disk
X beginning-of-file
X set %yvar &cat "%yno" %src
X set %xvar &ind &cat "%xno" %src
X &sub 10 &ind %yvar next-line
X set %old &mid $line %xvar 19
X %xvar forward-character
X 19 delete-next-character
X insert-string %disk0
X set &ind %yvar &sub &ind %yvar 1
X;insert on new place
X beginning-of-file
X set %yvar &cat "%yno" %dest
X set &ind %yvar &add &ind %yvar 1
X set %xvar &ind &cat "%xno" %dest
X &sub 10 &ind %yvar next-line
X &sub %xvar 1 forward-character
X 19 delete-next-character
X insert-string %old
X
X beginning-of-file
X update-screen
X!endm
X
X;the trivial recursive hanoi algorithism. push news args before calling an
X;new incarnation of 'move'.
Xstore-procedure move
X run readarg ; get new context !!!!
X !if &equ %number 1
X run moveone
X !return
X !endif
X set %pusharg &cat &sub %number 1 &cat %src &cat %dest &cat %aux
X run push
X run move
X run pop
X run moveone
X set %pusharg &cat &sub %number 1 &cat %aux &cat %src &cat %dest
X run push
X run move
X run pop
X!endm
X
X
X;straight forward coding of making the starting window and asking for
X;the numbers of disks (with checking). Also handles initialisation and
X;destruction of our internal buffers (for recursion and display).
X;uses banner to get a neat display (at least on my machine).
X; ???? Why can't i use 'unmark-buffer name' ????
Xstore-procedure hanoi
X set %olddiscmd $discmd
X set $discmd FALSE
X delete-other-windows
X set %savebuf $cbufname
X select-buffer [output]
X pipe-command "banner 'Towers of'"
X set %savebuf1 $cbufname
X set-mark
X end-of-file
X copy-region
X next-window
X yank
X delete-other-windows
X delete-buffer %savebuf1
X pipe-command "banner ' Hanoi!'"
X set-mark
X end-of-file
X copy-region
X next-window
X yank
X insert-string "for uEMACS 3.9e (and higher) by Reimer A. Mellin ....."
X delete-other-windows
X delete-buffer %savebuf1
X update-screen
X*label1
X set %number @"How may disks on first pole (1-9) ?"
X !if &or &sgr %number "9" &sle %number "1"
X !goto label1
X !endif
X run init-vars
X run init-screen
X; move %numbers disks from Left to Right using Middle
X; don't change 'LMR' since the characters are used to construct some
X; variables (using '&ind').
X set %pusharg &cat %number "LMR"
X run push
X run move
X select-buffer [stack]
X unmark-buffer
X select-buffer [output]
X set %number @"Finished .... Press Return ....."
X unmark-buffer
X select-buffer %savebuf
X delete-buffer [stack]
X delete-buffer [output]
X set $discmd %olddiscmd
X!endm
END_OF_FILE
if test 4811 -ne `wc -c <'hanoi.cmd'`; then
echo shar: \"'hanoi.cmd'\" unpacked with wrong size!
fi
# end of 'hanoi.cmd'
fi
echo shar: End of shell archive.
exit 0
--
Reimer A. Mellin UUCP : unido!altger!ram
Germany->Bavaria->Munich VOICE: 49-89-791 36 68
"Real programmers don't write in any language, they patch ......"