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

int	top[3]	= { 22, 22, 22 };
FILE	*tty;

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 ((tty = fopen("ti:", "wn")) == NULL) {
		fprintf(stderr, "No tty!\n");
		exit(1);
	}
	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;

	fprintf(tty, "\033[2J");
	for (i=11; i<23; ++i) {
		cput(15, i, '|');
		cput(40, i, '|');
		cput(65, i, '|');
	}
	curse(5, 23);
	for (i=5; i<76; ++i)
		putc('-', tty);
	for (i=n; i>0; --i)
		draw(i, 15, top[0]--, 'x');
}

curse(x, y)
{
	fprintf(tty, "\033[%d;%dH", y+1, x+1);
}

cput(x, y, c)
{
	curse(x, y);
	putc(c, tty);
}

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

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

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');
	}
}
