
/*
 * Hanoi.
 */
#include <stdio.h>

FILE	*vt_fd;

int	top[3]	= { 22, 22, 22 };

main(argc, argv)
char *argv[];
{
	register n;

	if (argc == 0) {
		argc = 2;
		argv[0] = "hanoi";
		argv[1] = "5";
	}
	if (argc < 2) {
		fprintf(stderr, "Arg. count!\n");
		exit(1);
	}
	n = atoi(argv[1]);
	if (n<0 || n>13) {
		fprintf(stderr, "Bad number of rings!\n");
		exit(1);
	}
	if ((vt_fd = fopen("ti:", "wn")) == NULL)
		error("Can't open terminal");
	setup(n);
	hanoi(n, 0, 2, 1);
}

hanoi(n, a, b, c)
{
	if (n == 0)
		return;
	hanoi(n-1, a, c, b);
	movering(n, a, b);
	hanoi(n-1, c, b, a);
}

setup(n)
{
	register i;

	erase();
	for (i=11; i<23; ++i) {
		cput(15, i, '|');
		cput(40, i, '|');
		cput(65, i, '|');
	}
	dca(5, 23);
	for (i=5; i<76; ++i)
		putc('-', vt_fd);
	for (i=n; i>0; --i)
		draw(i, 15, top[0]--, 'x');
}


cput(x, y, c)
{
	dca(x, y);
	putc(c, vt_fd);
}

draw(ring, centre, y, ch)
{
	register i;

	dca(centre-ring, y);
	for (i=0; i<ring; ++i)
		putc(ch, vt_fd);
	dca(centre+1, y);
	for (i=0; i<ring; ++i)
		putc(ch, vt_fd);
}

movering(ring, from, to)
{
	int fromc, toc;
	int fromy, toy;

	fromc = 15 + from*25;
	toc = 15 + to*25;
	fromy = ++top[from];
	toy = top[to]--;
	while (fromy != 10) {
		draw(ring, fromc, fromy, ' ');
		draw(ring, fromc, --fromy, 'x');
	}
	if (fromc < toc) 
		while (fromc != toc) {
			cput(fromc-ring, fromy, ' ');
			cput(fromc, fromy, 'x');
			cput(fromc+1, fromy, ' ');
			cput(fromc+ring+1, fromy, 'x');
			++fromc;
		}
	else if (fromc > toc)
		while (fromc != toc) {
			cput(fromc+ring, fromy, ' ');
			cput(fromc, fromy, 'x');
			cput(fromc-1, fromy, ' ');
			cput(fromc-ring-1, fromy, 'x');
			--fromc;
		}
	while (fromy != toy) {
		draw(ring, fromc, fromy, ' ');
		draw(ring, fromc, ++fromy, 'x');
	}
}

/*
 *		C u r s o r   c o n t r o l   f u n c t i o n s
 *
 * On VMS, cursor must be linked with kbgetc and kbputb.
 *
 */


#define ESC	0233

static char dcastring[] { ESC, 'Y', '?', '?' };
#define DCAROW	2
#define DCACOL	3

dca(x, y)
int	x;		/* X -- Column on the screen			*/
int	y;		/* Y -- Row on the screen			*/
/*
 * Move the cursor to the indicated position.  [0,0] is the top left-hand
 * corner of the screen
 */
{
	dcastring[DCACOL] = 32 + x;
	dcastring[DCAROW] = 32 + y;
	ttyput(dcastring, sizeof dcastring);
}


static char clrscr[]	{ ESC, 'H', ESC, 'J', 0 };

erase()
/*
 * Clear the screen
 */
{
	ttyput(clrscr, sizeof clrscr);
}

ttyput(buffer, buflen)
char		*buffer;	/* What to output			*/
int		buflen;		/* Number of bytes to output		*/
/*
 * Output to the terminal.  RSX mode.
 */
{
	fput(buffer, buflen, vt_fd);
	fflush(vt_fd);
}
