/* Copyright 2004 Louis Jean­Richard (www.ljr.ch). All Rights Reserved. */
//	---------------------------- Towers of Hanoi --------------------
var maxPosts = 3
var maxDisks = 7
var postTop = maxDisks + 1
var hoverDisk = postTop + 1
var postBottom = hoverDisk + 1
var postSection = 0
var startPost = 0
var endPost = maxPosts - 1
var disks = 3
var gameIsOver = false
var selectedDisk = null
var selectedPost = null
var moves = 0
//	-----------------------------------
var disk = new Preload("../aa/game/2/")
disk.load("hanoi", postBottom + 1, ".gif")
var score = new Score()

//	-----------------------------------
function								InitArray(xCells) {
	this.length = xCells
	for (var x = 0; x < this.length; x++)
		this[x] = null
}
//	-----------------------------------
function					TwoDimensionalArray(xCells, yCells) {
	this.length = xCells
	for (var x = 0; x < this.length; x++)
		this[x] = new InitArray(yCells)
}
var board = new TwoDimensionalArray(maxPosts,maxDisks + 1)
//	-----------------------------------
function						ImageName(diskNumber)
{
	return disk.image[diskNumber].src
}
//	-----------------------------------
function						CellName(post,diskNumber)
{
	return "P" + post + "" + diskNumber
}
//	-----------------------------------
function						Draw(post,y,d)
{
	document.images[CellName(post,y)].src= ImageName(d)
}
//	-----------------------------------
function						Repaint()
{
	for (var post=0; post < board.length; post++)
		for (var y=0; y < board[0].length; y++)
			Draw(post, y, board[post][y])
}
//	-----------------------------------
function						topMostDisk(post)
{
	for (var y = 1; y < board[0].length; y++)
		if (board[post][y] != 0)
			return y
	return null
}
//	-----------------------------------
function						toggleDisk(post)
{
	if (selectedPost == null) {
		selectedDisk = topMostDisk(post)
		if (selectedDisk != null) {
			selectedPost = post
			Draw(selectedPost, selectedDisk, 0)
			Draw(selectedPost, 0, board[selectedPost][selectedDisk])
			window.defaultStatus = msg2()
		}
	}
	else {
		Draw(selectedPost, 0, hoverDisk)
		Draw(selectedPost, selectedDisk, board[selectedPost][selectedDisk])
		selectedPost = null
		selectedDisk = null
		window.defaultStatus = msg3()
	}
}
//	-----------------------------------
function						isEmpty(post)
{
	for (var y = 1; y < board[0].length; y++)
		if (board[post][y] != 0)
			return false
	return true
}
//	-----------------------------------
function						legalMove(post)
{
	return (isEmpty(post)
		|| (board[post][topMostDisk(post)] < board[selectedPost][selectedDisk]))
}
//	-----------------------------------
function						GoalAttained()
{
	var filledpost
	var val = 0
	for (post = 0; post < board.length; post++)
		if (isEmpty(post))
			val++
		else
			filledpost = post
	if ((val == 2) && (filledpost != startPost)) {
		gameIsOver= true
		endPost= filledpost
	}
	return gameIsOver
}
//	-----------------------------------
function						moveDisk(post)
{
	var tp = (isEmpty(post) ? maxDisks+1 : topMostDisk(post))
	board[post][tp-1] = board[selectedPost][selectedDisk]
	board[selectedPost][selectedDisk] = 0
	Draw(selectedPost,0, hoverDisk)
	Draw(post,tp-1, board[post][tp-1])
	selectedPost = null; selectedDisk = null
	moves++
	score.update(moves)
}
//	-----------------------------------
function						clicked(post,y)
{
	document.CONTROL.disc.focus() // get rid of annoying outline in MSIE
	if (gameIsOver)
		window.defaultStatus = msg6()
	else
		if ((selectedPost == null) || (selectedPost == post))
			toggleDisk(post)
		else
			if (legalMove(post))
				moveDisk(post)
}
//	------------------------------------------------ autoplay
var step = 0
var last_step = 0
var deltaT = 1000
var maxMoves = Math.pow(2, maxDisks)
var aps = new InitArray(maxMoves)
var apg = new InitArray(maxMoves)
//	-----------------------------------
function				PlayHanoi(disks, start_post, goal_post)
{
	if (disks > 0) {
		var free_post = maxPosts - start_post - goal_post
		PlayHanoi(disks - 1, start_post, free_post)
		aps[step]=start_post
		apg[step]=goal_post
		step++
		PlayHanoi(disks - 1 , free_post, goal_post)
	}
}
//	-----------------------------------
function								playStep()
{
	if (last_step > 0)	{
		toggleDisk(aps[step])
		moveDisk(apg[step])
		step++
		score.update(step)
		if (step<last_step)
			setTimeout("playStep()",deltaT)
	}
}
//	-----------------------------------
function								AutoPlay()
{
	step=0
	if (moves > 0)
		initHanoi()
	PlayHanoi(disks,startPost,endPost)
	last_step=step;	step=0
	playStep()
}
//	-----------------------------------
function								initHanoi()
{
	score.reset()
	with(document.CONTROL.disc)
		var os = options[selectedIndex].text
	for (var i = 1; i < os.length; i++) {
		var ch = os.substr(i,1)
		if ((ch >= '0') && (ch <= '9')) {
			disks = parseInt(ch)
			break
		}
	}
	selectedPost = null
	selectedDisk = null
	gameIsOver = false
	moves = 0
	last_step = 0
	endPost = (startPost-1 < 0 ? maxPosts-1 : startPost-1)
	var len = board[0].length
	for (var post = 0; post < board.length; post++) {
		board[post][0] = hoverDisk
		for (var y = 1; y < len; y++)
			board[post][y] = 0
	}
	for (y=1, j=len-disks; y<=disks; y++, j++)
		board[startPost][len-y]= j
	Repaint()
	window.onResize=Repaint
	window.defaultStatus = msg1()
}
//	-----------------------------------
function								drawControl()
{
	var output = '<form name="CONTROL">'
	output += '<select name="disc" size="1"'
	output += " onChange='javascript:initHanoi()'>"
	for (var o=1; o <= maxDisks; o++) {
		output += '<option'
		if (o == disks)
			output += ' selected'
		output += '>'
		output += text2(o)
	}
	output += "</select>"
	output += '<br /><input class="button" type="button" value='
	output += sQuoted(text3)
	output += " onClick='javascript:initHanoi()' />"
	output += '<br /><input class="button" type="button" value='
	output += sQuoted(text4)
	output += " onClick='javascript:AutoPlay()' />"
	output += "</form>"
	return output
}
//	-----------------------------------
function								drawBoard()
{
	var output = '<table><tr>'
	for (var post = 0; post < maxPosts; post++) {
		output += "<td>"
		output += "<a href='javascript:clicked(" + post + ",0)'>"
		output += '<img src=' + quoted(ImageName(hoverDisk))
		output += ' name=' + CellName(post,0)
		output += ' />'
		output += '</a>'
		output += "<a href='javascript:clicked(" + post + ",1)'>"
		output += '<img src=' + quoted(ImageName(postTop))
		output += ' />'
		for (var y=1; y <= maxDisks; y++) {
			output += '<img src=' + quoted(ImageName(postSection))
			output += ' name=' + CellName(post,y)
			output += ' />'
		}
		output += '<img src=' + quoted(ImageName(postBottom)) + ' />'
		output += '</a>'
		output += '</td>'
	}
	output += '</tr></table>'
	return output
}

//	============================================================
//							S C O R E
//	============================================================

function 								Score(aGame, aBoard) {
	this.moves = 0
	this.chrono = new Chrono()
	this.displayed = false
	//
	this.board = aBoard
}
//	-----------------------------------
function                                htmlScore(){
	output = '<form name="SCORE">'
	output += '<table><tr><td>'
	output += text5d + '</td><td>'
	output += text5e
	output += "</td></tr><tr><td>"
	output += htmlDisplay('moves', '') + '</td><td>'
	output += htmlDisplay('time', '')
	output += "</td></tr></table>"
	output += "</form>"
	this.displayed = true
	return output
}
Score.prototype.html = htmlScore
//	-----------------------------------
function                                resetScore(){
	this.moves = 0
	document.SCORE.time.value = ''
	document.SCORE.moves.value = this.moves
	this.chrono.stop()
}
Score.prototype.reset = resetScore
//	-----------------------------------
function                                updateScore(moves){
	if (moves == 0)
		this.reset()
	else {
		this.moves = moves
		if (moves == 1)
			this.chrono.start()
		else
			document.SCORE.time.value = this.chrono.elapsedMinutes()
	}
	document.SCORE.moves.value = this.moves
}
Score.prototype.update = updateScore

//	============================================================
//						I N T E R F A C E
//	============================================================

function                                displayGame(language) {
	initLanguage(language)

	var output = '<table class="game"><tr><td class="score">'
	output += score.html()
	output += '</td><td class="board" rowspan="2">'
	output += drawBoard()
	output += '</td></tr><tr><td class="control">'
	output += drawControl()
	output += '</td></tr></table>'

	document.open()
	document.write(output)
	document.close()

	initHanoi()
//	window.onresize=board.repaint
}

//	============================================================
var langCode = undefined
var text3 = 'Restart the game'
var text4 = 'Play it for me !'
var text5d = 'moves'
var text5e = 'time'
//	-----------------------------------
function initLanguage(language) {
	if (langCode == undefined)
		langCode = language
	else
		return
	switch (langCode) {
	case 'de':
		text3 = 'Das Spiel neu starten'
		text4 = 'Spiel es mir vor !'
		text5d = 'Schritte'
		text5e = 'Zeit'
		break
	case 'es':
		text3 = 'Reempezar el juego'
		text4 = 'Jueguelo para mi !'
		text5d = 'pasos'
		text5e = 'tiempo'
		break
	case 'fr':
		text3 = 'Recommence le jeu'
		text4 = 'Joue-le pour moi !'
		text5d = 'pas'
		text5e = 'temps'
		break
	case 'it':
		text3 = 'Ricomincia il gioco'
		text4 = 'Giocalo per me !'
		text5d = 'mosse'
		text5e = 'tempo'
		break
	}
}
//	-----------------------------------
function msg1(){
	switch (langCode) {
	case 'de':
		return 'Sie k&ouml;nnen beginnen! W&auml;hlen Sie eine Platte.'
	case 'es':
		return 'Usted puede jugar! Escoja un disco para mover.'
	case 'fr':
		return 'Vous pouvez commencer! Choisissez un disque.'
	case 'it':
		return 'Potete cominciare il gioco. Selezionate un disco da spostare.'
	default:
		return 'You may begin! Select a piece to move.'
	}
}
//	-----------------------------------
function msg2(){
	switch (langCode) {
	case 'de':
		return 'Klicken Sie au dem Pfosten wo die Platte gelegt werden soll.'
	case 'es':
		return 'Clicar el palo donde poner el disco.'
	case 'fr':
		return 'Cliquez sur le poteau de destination.'
	case 'it':
		return 'Cliccate sul palo di destinazione.'
	default:
		return 'Click on the post where to move the disk.'
	}
}
//	-----------------------------------
function msg3(){
	switch (langCode) {
	case 'de':
		return 'W&auml;hlen Sie eine Platte.'
	case 'es':
		return 'Escoja un disco para mover.'
	case 'fr':
		return 'Choisissez un disque.'
	case 'it':
		return 'Selezionate un disco da spostare.'
	default:
		return 'Select a piece to move.'
	}
}
//	-----------------------------------
function msg4(N){
	switch (langCode) {
	case 'de':
		return 'Es werden ' + N + ' Bewegungen ben&ouml;tigt um den Plattenturm zu verschieben.'
	case 'es':
		return 'Se necesitan ' + N + ' pasos para desplazar la pila.'
	case 'fr':
		return 'Il faut ' + N + ' mouvements pour d&eacute;placer la pile.'
	case 'it':
		return 'Sono richieste ' + N + ' mosse per spostare la pila.'
	default:
		return N.toString() + ' moves are required to attain the goal.'
	}
}
//	-----------------------------------
function msg6(){
	switch (langCode) {
	case 'de':
		return 'Versuchen Sie mit einer andere Zahl von Platten !'
	case 'es':
		return 'Pruebe con otro numer ode discos !'
	case 'fr':
		return 'Essayez avec un nombre different de disques !'
	case 'it':
		return 'Provate con un numero differente di dischi !'
	default:
		return 'Try with another setting !'
	}
}
//	-----------------------------------
function text2(N){
	switch (langCode) {
	case 'de':
		return 'Spielen mit ' + N + ' Platten'
	case 'es':
		return 'Jugar con ' + N + ' discos'
	case 'fr':
		return 'Jouer avec ' + N + ' disques'
	case 'it':
		return 'Giocare con ' + N + ' dischi'
	default:
		return 'Play with ' + N + ' disks'
	}
}
//	-----------------------------------
