[comp.emacs] Towers of Hanoi for uEMACS 3.9

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 &not &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 &not &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 ......"