	// Javascript written by Jaap Scherphuis. (jaapsch a t yahoo d o t com)
var imagedir="http://www.solvemymath.com/games/logic_games/hanoi/hanoi_pic/";
function preload(){
	this.length=preload.arguments.length;
	for (var i=0;i<this.length;i++){
		this[i]=new Image();
		this[i].src=imagedir+preload.arguments[i];
	}
}
var pics=new preload("hn1.gif","hn2.gif","hn3.gif","hn4.gif","hn5.gif",
					"hn6.gif","hn7.gif","hn8.gif","hn9.gif",
			"hn0.gif","hntp.gif","hnbt.gif","hnbt2.gif","blank.gif",
			"edit.gif","edit2.gif",
			"rew.gif","back.gif",
			"play.gif","ff.gif",
			"up.gif","down.gif",
			"mix.gif","reset.gif","help.gif");
var posit = new Array ();
var disk = new Array ();
var tim;
var mode = 1;   //0=normal  1=solving scrambled  2=edit
var n = 9;  //number of disks to use
var edt;
var slct=-1;  //column selected for move
var auto=-1;
function initbrd(){
	posit[0] = new Array ();
	for(var i=0;i<n;i++) posit[0][i]=n-i;
	posit[1] = new Array ();
	posit[2] = new Array ();
	disk=new Array(0,0,0,0,0,0,0,0,0);
}
initbrd();
document.writeln("<table cellpadding=0 cellspacing=0 border=0><tr>");
for(var i=0;i<=9;i++){
	for(var j=0;j<3;j++){
		document.writeln("<td align=center><a href='javascript:clicked("+j+");focus();'><img src='"+pics[i==0? 10 : 9].src+"' width=100 height=16 border=0 name='d"+i+""+j+"'><\/a><\/td>");
	}
	document.writeln("<\/tr><tr>");
}
for(var j=0;j<3;j++){
	document.writeln("<td align=center><a href='javascript:clicked("+j+");focus();'><img src='"+pics[11].src+"' width=100 height=16 border=0 name='b"+j+"'><\/a><\/td>");
}
document.writeln("<\/tr><tr>");
document.writeln("<td height=10> <\/td>");
document.writeln("<\/tr><tr>");
document.write("<td colspan=3 align=center>");
document.write("<a href='javascript:mix();'><img src='"+pics[22].src+"' height=16 width=48 border=0><\/a>");
document.write("<a href='javascript:reset();'><img src='"+pics[23].src+"' height=16 width=48 border=0><\/a>");
document.write("<a href='javascript:edit();'><img src='"+pics[14].src+"' height=16 width=48 border=0 name='edit'><\/a>");
document.write("<a href='javascript:help();'><img src='"+pics[24].src+"' height=16 width=48 border=0><\/a> ");
document.write("<a href='javascript:up();'><img src='"+pics[20].src+"' height=16 width=48 border=0><\/a>");
document.write("<\/td><\/tr><tr><td colspan=3 align=center>");
document.write("<a href='javascript:autostep(0);'><img src='"+pics[16].src+"' height=16 width=48 border=0><\/a>");
document.write("<a href='javascript:step(0);'><img src='"+pics[17].src+"' height=16 width=48 border=0><\/a>");
document.write("<a href='javascript:step(2);'><img src='"+pics[18].src+"' height=16 width=48 border=0><\/a>");
document.write("<a href='javascript:autostep(2);'><img src='"+pics[19].src+"' height=16 width=48 border=0><\/a> ");
document.write("<a href='javascript:down();'><img src='"+pics[21].src+"' height=16 width=48 border=0><\/a>");
document.writeln("<\/td><\/tr><\/table>");
function display(){
	for (var i=0;i<3;i++){
		for (var j=0;j<=9;j++){
			if(j<n){
				var p=9;
				if(j<posit[i].length) p=posit[i][j]-1;
			}else if(j==n){
				var p=10;
			}else p=13;
			document.images["d"+(9-j)+""+i].src=pics[p].src;
		}
		document.images["b"+i].src=pics[ slct==i? 12 : 11 ].src;
	}
	document.images["edit"].src=pics[ mode==2 ? 15 : 14 ].src;
	if(mode==1 && solved()){
		alert("You solved it!\nYou don't get a prize for this though!");
		mode=0;
	}
}
function solved(){
	for (var i=0;i<n;i++){
		if(disk[i]!=2) return(false);
	}
	return(true);
}
display();
function mix(){
	autooff();
	posit[0].length=0
	posit[1].length=0
	posit[2].length=0
	disk[0]=new Array(0,0,0,0,0,0,0,0,0);
	for(var i=n-1;i>=0;i--){
		k=Math.floor(Math.random()*3);
		disk[i]=k;
		posit[k][posit[k].length]=i+1;
		//display();
		//alert("disk "+i+" in col "+k);
	}
	mode=1;
	slct=-1;
	display();
}
function reset(){
	autooff();
	initbrd();
	mode=1;
	display();
}
function up(){
	autooff();
	if(n<9){
		n++;
		reset();
		display();
	}
}
function down(){
	autooff();
	if(n>3){
		n--;
		reset();
		display();
	}
}
function edit(){
	autooff();
	posit[0]=new Array();
	posit[1]=new Array();
	posit[2]=new Array();
	disk[0]=new Array(0,0,0,0,0,0,0,0,0);
	mode=2;
	edt=n;   //first piece to be placed
	display();
}
function clicked(x){
	autooff();
	if(mode==2){  //editing
		posit[x][posit[x].length]=edt;
		disk[edt-1]=x;
		edt--;
		if(edt==0) mode=1;
	}else if(slct>=0){
		domove(slct,x);
		slct=-1;
	}else {
		slct=x;
	}
	display();
}
function domove(f,t){
	//Moves disk from f to t
	if(f==t) return(0);
	var c=posit[f].length;
	if(c==0)return(0);
	var d=posit[f][c-1];
	var e=posit[t].length;
	if(e!=0 && posit[t][e-1]<d){
		alert("Cannot place any disk\n on top of a smaller one!");
	}else{
		posit[f].length--;
		posit[t][e]=d;
		disk[d-1]=t;
	}
}
function step(c){
	if(auto>=0){
		clearTimeout(tim);
		auto=-1;
	}else{
		best(c);
	}
}
function autostep(c){
	if(auto<0){
		auto=256;
	}else if(auto>0){
		auto>>=1;
	}else{
		auto=0;
	}
	clearTimeout(tim);
	best(c);
}
function best(c){
	if(mode<=1){
		mode=0;
		var a=findbest(n,c);
		if(a>=0) {
			domove((a&12)/4,a&3);
			display();
		}else{
			auto=-1;
		}
		if(auto>=0){
			tim=setTimeout("best("+c+")",auto);
		}
	}
}
function findbest(p,c){
	//finds best move for moving pyramid with disks 1-p on peg c
	if(p==0) return(-1);
	//alert("Disk="+disk+"\nTrying disk "+p+" to "+c);
	if(disk[p-1]==c) return(findbest(p-1,c));
	var e=3-c-disk[p-1];
	var a=findbest(p-1,e)
	if(a>=0) return(a)
	return(4*disk[p-1]+c);
}
function autooff(){
	if(auto>=0){
		clearTimeout(tim);
		auto=-1;
	}
}
function help(){
	alert(
		"The Tower of Hanoi\n\n"+
		"The aim is to pile the disks up on the third peg, with\n"+
		"the disks arranged in order, the largest at the bottom.\n"+
		"You may only move one disk at a time, and only place it\n"+
		"on an empty peg or on a larger disk.\n"+
		"To move a disk, just click on the peg it is on and then\n"+
		"click on the peg you want to move it to.\n"+
		"\nFurther controls:\n"+
		"Up/Down: These buttons change the size of the puzzle.\n"+
		"Mix:    This button randomly mixes the puzzle up.\n"+
		"Reset:  Resets the puzzle to the initial position.\n"+
		"Edit:   Allows you to set up any position. The disks are\n"+
		"        cleared, and then you have to specify on which peg\n"+
		"        each of the pieces is, starting with the largest.\n"+
		"Play/Back: Solves the puzzle. Each time you click the play\n"+
		"        button, one move is performed until the puzzle is solved.\n"+
		"        The backwards play button does the same, but brings.\n"+
		"        the puzzle closer to the start position.\n"+
		"Forward/Rewind: This is like the play/back buttons, except that\n"+
		"        the moves will be continuously performed till the end or\n"+
		"        beginning. Clicking the button more than once speeds\n"+
		"        it up. To stop, press one of the other buttons.\n"+
		"Help:   Shows this help screen.\n"
	);
}

