//      Magnetron
//	 for DEBUGGED @ http://www.truplex.com
//	written by Stephen Battey - March & October 1997
//	Magnetron originally written in BASIC for the Amstrad CPC464 in 1993




//			Set up global variables to be used

NoOfPuzzles=19
GameOn=false
DemoStat=0
Pulsing=false
NoOfMoves=0

Boxes = new Array()
for (i=1; i<9; i++) {
	Boxes[i] = new Array()
}




//-----------------------------------------------
//		Bottom level functions
//-----------------------------------------------


function Round(number) {
//			function returns the extracted integer part
//			of a decimal number - Math.round is not used
//			since it is only availiable on a Unix platform

	v=number.toString()
	dp=v.indexOf(".")
	if ( dp==-1 )
		return number
	if ( ( dp==0 ) | ( v.substring(0,dp)=="-" ) )
		return 0
	return eval(v.substring(0,dp))
}



function NumText(v,width,use) {
//			returns the number 'v' in a text string of minimum
//			length 'width', preceeding spaces being filled with//			the character specified in 'use'

	post=v.toString()
	pre=""
	uselen=width-post.length
	for (i=1; i<=uselen; i++) {
		pre+=use
	}
	return pre+post
}



//-------------------------------------------------
//		Screen output functions
//-------------------------------------------------


function ShowMoves() {
//			Displays number of moves taken

	TopForm.nom.value=NumText(NoOfMoves,5," ")
}



function ShowTime() {
//			Displays time taken

	TopForm.gtime.value=NumText(GameTimeM,2," ")+":"+NumText(GameTimeS,2,"0")
}



function ShowSideMags() {
//			Displays the two side magnets

	ImNo=(SideMagPos*14)+69
	document.images[ImNo].src="LeftMag.jpg"
	document.images[ImNo+11].src="RightMag.jpg"
}



function DelSideMags() {
//			Removes the two side magnets

	ImNo=(SideMagPos*14)+69
	document.images[ImNo].src="BlackDot.jpg"
	document.images[ImNo+11].src="BlackDot.jpg"
}



function ShowTopMag() {
//			Displays top magnet

	document.images[TopMagPos+40].src="TopMag.jpg"
	document.images[TopMagPos+54].src=GotStr
}



function DelTopMag() {
//			Removes top magnet

	document.images[TopMagPos+40].src="BlackDot.jpg"
	document.images[TopMagPos+54].src="BlackDot.jpg"
}



function ShowTile(r,c) {
//			Inserts the picture onto the screen

	ImNo=(r*14)+70+c
	document.images[ImNo].src=Boxes[r][c]
}



function SetSqBox(sn,Ssrc) {
//			Displays the sequence box

	document.images[sn+2].src=Ssrc
}





//-------------------------------------------
//		Timer function
//-------------------------------------------


function UpdateTime() {
//			Counts on one second in game time

	GameTimeS++
	if ( GameTimeS>59 ) {
		GameTimeS=0
		GameTimeM++
	}
	ShowTime()
	CounterTimer=window.setTimeout("UpdateTime()",1000)
}





//---------------------------------------------
// Functions used for editing the playing area
//---------------------------------------------


function EndFuncts() {
//			Ties up loose ends after game

	GameOn=false
	if ( DemoStat>0 )
		clearTimeout(DemoTimer)
	Pulsing=false
	clearTimeout(CounterTimer)
}



function EndMessage(f) {
//			Congratualtes the user when the game is completed

	BestMoves = new Array (null,10,11,9,14,30,39,29,39,28,45,35,55,61,63,60,26,65,57,44,67)

	EndFuncts()

	if ( DemoStat>0 ) {
		DemoStat=0
		if ( confirm("\n\n  Attempt the first puzzle?\n") ) {
			TopForm.GameNo.selectedIndex=1
			StartGame()
		}
		return
	}

	ShowStr="\n\n  --== CONGRATULATIONS ==--\n\n             A job well done !\n"
	if ( NoOfMoves>BestMoves[GameNo] ) {
		if ( confirm(ShowStr+"   But there is a simpler solution\n    Want to try this puzzle again?") )
			StartGame()
		else {
			if ( confirm("\n\n  Move onto next game anyway?\n") ) {
				TopForm.GameNo.selectedIndex=GameNo
				StartGame()
			}
		}
	} else {
		ShowStr+="And in the lowest number of moves !\n"
		if ( GameNo==NoOfPuzzles ) {
			if ( confirm(ShowStr+"  You can request more puzzles by\n                e-mail") )
				parent.location="mailto:batteysp@aston.ac.uk?subject=More Magnetron puzzles"
		} else {
			if ( confirm(ShowStr+"      Move on to the next puzzle?") ) {
				TopForm.GameNo.selectedIndex=GameNo
				StartGame()
			}
		}
	}
}



function Explode(n) {
//			Animate bomb explosion

	AnimBomb = new Array("Ex1.jpg","Ex2.jpg","Ex3.jpg","BlackDot.jpg")
	AnimMag = new Array("TopMag.jpg","BrokenMag.jpg","BrokenMag.jpg","BlackDot.jpg")

	GameOn=false
	if ( n<4 ) {
		document.images[TopMagPos+54].src=AnimBomb[n]
		document.images[TopMagPos+40].src=AnimMag[n]
		n++
		ExplodeTimer=window.setTimeout("Explode("+n+")",200)
	} else {
		EndFuncts()
		if ( confirm("\n      OOoooops !!\n\nTry this puzzle again?\n") )
			StartGame()
	}
}



function BoxName(bn) {
//			Calculates the box name by its number in the sequence

	ForeStr= new Array("Blue","Red","Yellow","Green","Pink","Cyan","White")
	AftStr = new Array("Triangle","Square","Circle")

	if ( bn<21 ) {
		fn=Round(bn/3)
		an=bn-(3*fn)
		return  ForeStr[fn]+AftStr[an]+".jpg"
	}
	if ( bn==21 )
		return "Blank.gif"
	if ( bn==22 )
		return "Bomb.jpg"
	if ( bn==23 )
		return "BlackDot.jpg"
}



function CountUp(thisBox) {
//			Scans the boxes and counts up the
//			number of 'thisBox's occuring

	Count=0
	for (c=1; c<9; c++) {
		for (r=1; r<9; r++) {
			if ( Boxes[r][c]==thisBox )
				Count++
		}
	}
	return Count
}



function NextToGet() {
//			Calculates which letter is required
//			to be removed next

	if ( WantNo>-1)
		SetSqBox(WantNo,"Blank.gif")
	while ( 1==1 ) {
		WantNo++
		WantStr=BoxName(WantNo)

		NoOfWant=CountUp(WantStr)

		if ( ( NoOfWant>0 ) | ( WantStr=="Blank.gif" ) )
			break
	}
	BotForm.LeftWant.src=WantStr
	BotForm.RightWant.src=WantStr
}



function SetSequence() {
//			Shows the boxes that need collecting

	for (sqBox=0; sqBox<21; sqBox++) {
		if ( CountUp(BoxName(sqBox))==0 )
			SetSqBox(sqBox,"Blank.gif")
		else
			SetSqBox(sqBox,BoxName(sqBox))
	}
}



function NextBelow(c,r) {
//			Calculates the position of the block
//			directly below the 'r'th row in the 'c'th column

	r++
	while ( r<9 ) {
		if ( Boxes[r][c]!="BlackDot.jpg" )
			break
		r++
	}
	return r
}



function PickUp() {
//			Procedure to pick up a block from the playing area

	//		Search for block under magnet
	FromCol=TopMagPos-2
	FromRow=NextBelow(FromCol,0)

	//		If we've found a block
	if ( FromRow<9 ) {

	//		Check it is an active one
		TheBox=Boxes[FromRow][FromCol]
		if ( ( TheBox==WantStr ) | ( TheBox=="Blank.gif" ) | ( TheBox=="Bomb.jpg" ) ) {

			NoOfMoves++
			ShowMoves()
			GotStr=TheBox
			Boxes[FromRow][FromCol]="BlackDot.jpg"
			ShowTopMag()
			ShowTile(FromRow,FromCol)

			if ( GotStr=="Bomb.jpg" )
				ExplodeTimer=window.setTimeout("Explode(0)",20)
		}
	}
}



function DropDown() {
//			Procedure to drop a block from the over-head magnet

	//		Search for space under magnet
	FromCol=TopMagPos-2
	FromRow=NextBelow(FromCol,0)

	//		If enough room, drop it down
	if ( FromRow>1 ) {
		NoOfMoves++
		ShowMoves()
		Boxes[FromRow-1][FromCol]=GotStr
		GotStr="BlackDot.jpg"
		ShowTile(FromRow-1,FromCol)
		document.images[TopMagPos+54].src="BlackDot.jpg"
	}
}



function SetPlayingArea(gno) {
//			Displays boxes for beginning of game

	OrgSetting = new Array ("                                              #*  *****A***DB***","                                  *     ****    FFBA    DDCC    ","                                                ******  FEDCBA  ","                                           **   *  DD   ACBCEFFF","                             *      *A** ***BCCK BDDGJJJ EHFKKKK","                         *      CACCCCC CCEEFFF FFEEDDD#HHHHHHHB","                               *       ** ********BJKAC***FGEDH*","                        #       *#*#    ABAB * ***** * *FFDE**C*","                       *# P E N*D C D B*R J A M*K F G K*L R H R*","            ***     *ALB    *NLL   #*NRRCCCEMMKKDHGJRRNNF***PPRR","        *       **      ***     ****    A*** HHH**CB GFH*E*D****","             ***  ###DAA  CHEJK*  CJJFK*  GGGDJ*  ******BC******","                      ** FFFFFFA EH*HHHD#JJJGJJD#LLLMMMDCPKRRRRN","              ##  FFEDD#  GGEDD#  MCCCC#  ALMKBP  MPJHPP  MHKNNN","                        #****** CCKAAECCDDH**LLFGGML*JLLLMML*JNN","                        A       *  ***  C* *A**B** ****B****E**D","         ******  #ALLPC  #GHHEJ  #RFGGJ  BNUYMM  DNKVYT  XYTSYY ","                APKDDH  J****B  E****B  E****G  L****C**LMMNRF**","                 ****** *CCAAB#**BC**BK**DD**JE**DDGGFH*********","        #******#*AADBAF**C****E**CJJFLE**CNGMHK*****************","         ")

	RelStr="ABCDEFGHJKLMNPRSTUVXY#* "
	DefStr=OrgSetting[gno-1]

	rowNo=1
	colNo=1

	for (p=0; p<64; p++) {
		bNo=RelStr.indexOf(DefStr.substring(p,p+1))
		Boxes[rowNo][colNo]=BoxName(bNo)
		ShowTile(rowNo,colNo)
		colNo++
		if ( colNo>8 ) {
			colNo=1
			rowNo++
		}
	}


}




//-----------------------------------------------------
//		Top level functions
//-----------------------------------------------------


function StartGame() {
//			This procedure sets up the variables for
//			the start of a new game



	if ( Pulsing )
		return
	if ( GameOn ) {
		if ( NoOfMoves>0 ) {
			if ( !confirm("\n Wipe current status,\nand start a new game?") )
				return
		}
		clearTimeout(CounterTimer)
		if ( DemoStat>0 )
			clearTimeout(DemoTimer)
	}

	TopForm=document.GameSel
	BotForm=document

	GameOn=true
	GameNo=TopForm.GameNo.selectedIndex+1

	GotStr="remove"
	for (TopMagPos=1; TopMagPos<13; TopMagPos++) {
		DelTopMag()
	}
	for (SideMagPos=1; SideMagPos<9; SideMagPos++) {
		DelSideMags()
	}
	SetPlayingArea(GameNo)
	SetSequence()

	NoOfMoves=0
	ShowMoves()

	GotStr="BlackDot.jpg"
	TopMagPos=6
	ShowTopMag()

	SideMagPos=8
	ShowSideMags()

	GameTimeM=0
	GameTimeS=0
	ShowTime()
	CounterTimer=window.setTimeout("UpdateTime()",1000)

	WantNo=-1
	NextToGet()

	if ( GameNo==1 ) {
		DemoStat=1
		window.status=" HOW TO PLAY   > > > >"
		DemoTimer=window.setTimeout("DemoGame()",2000)
	}
}



function SideMag(ToPos,thisSide) {
//			Move the side magnets to 'ToPos'

	if ( GameOn ) {
		if ( ToPos==SideMagPos ) {
			thisDir=1
			if ( thisSide==8 )
				thisDir=-1
			Pulse(thisSide,thisDir)
			return
		}
		DelSideMags()
		SideMagPos=ToPos
		ShowSideMags()
	}
}



function TopMagMove(ClickPos) {
//			Move the over-head magnet

	if ( !GameOn )
		return

	if ( TopMagPos==ClickPos ) {
		ThrowSwitch()
		return
	}

	dir=1
	if ( TopMagPos>ClickPos )
		dir=-1

	NewPos=TopMagPos+dir
	DelTopMag()
	TopMagPos=NewPos
	ShowTopMag()

	if ( ( TopMagPos==1 ) | ( TopMagPos==12 ) ) {
		if ( GotStr==WantStr ) {
			GotStr="BlackDot.jpg"
			document.images[TopMagPos+54].src="BlackDot.jpg"

			NoOfWant--
			if ( NoOfWant==0 ) {
				NextToGet()
				if ( WantStr=="Blank.gif" ) {
					BotForm.LeftWant.src="Rock.jpg"
					BotForm.RightWant.src="Rock.jpg"
					EndMessage()
				}
			}
		}
	}
}



function ThrowSwitch() {
//			Switch the over-head magnet on/off

	if ( ( TopMagPos<3 ) | ( TopMagPos>10 ) )
		return

	if ( GotStr=="BlackDot.jpg" )
		PickUp()
	else
		DropDown()
}



function Pulse(firstCol,dir) {
//			Pulse one of the side magnets

	if ( !GameOn )
		return

	GameOn=false
	Pulsing=true

	pulseDir=dir
	pulseRow=SideMagPos

	pulseCol=firstCol
	ToCol=firstCol
	NoMoved=0

	PulseTimer=window.setTimeout("Drag(1)",20)
}

function Drag(n) {
//			Drag boxes across

	if ( n<9 ) {
		if ( Boxes[pulseRow][pulseCol]=="BlackDot.jpg" ) {
			Boxes[pulseRow][pulseCol]="Flux.jpg"
		} else {
			held=false
			if ( pulseRow>1 ) {
				if ( Boxes[pulseRow-1][pulseCol]!="BlackDot.jpg" )
					held=true
			}
			if ( held )
				ToCol=pulseCol+pulseDir
			else {
				if ( ToCol!=pulseCol ) {
					NoMoved++
					Boxes[pulseRow][ToCol]=Boxes[pulseRow][pulseCol]
					Boxes[pulseRow][pulseCol]="Flux.jpg"
					ShowTile(pulseRow,ToCol)
				}
				ToCol+=pulseDir
			}
		}
		ShowTile(pulseRow,pulseCol)
		pulseCol+=pulseDir
		n++
		PulseTimer=window.setTimeout("Drag("+n+")",50)
	} else {
		for (i=1; i<3000; i--) {
			i+=2
		}
		pulseCol-=pulseDir
		PulseTimer=window.setTimeout("Drop(1)",20)
	}
}

function Drop(n) {
//			Drop boxes down

	if ( n<9 ) {
		if ( Boxes[pulseRow][pulseCol]=="Flux.jpg" ) {
			Boxes[pulseRow][pulseCol]="BlackDot.jpg"
		} else {
			ToRow=NextBelow(pulseCol,pulseRow)-1
			if ( ToRow!=pulseRow ) {
				Boxes[ToRow][pulseCol]=Boxes[pulseRow][pulseCol]
				Boxes[pulseRow][pulseCol]="BlackDot.jpg"
				ShowTile(ToRow,pulseCol)
			}
		}
		ShowTile(pulseRow,pulseCol)
		pulseCol-=pulseDir
		n++
		PulseTimer=window.setTimeout("Drop("+n+")",50)
	} else {
		if ( NoMoved>0 ) {
			NoOfMoves++
			ShowMoves()
		}
		Pulsing=false
		GameOn=true
	}
}




function DemoGame() {
//			controls the demo game

	ToDisplay = new Array(" ","To uncover the required box ..",".. click either side to place the side magnets in position ..",".. then click on the left magnet to pulse.","Now move the overhead magnet over the blue triangle.","Click on the magnet to lift the box out.","Move the box to the side to remove it completely.","You can use blanks to 'hold down' boxes when dragging.","Now drag the boxes to uncover the last piece.","It's that easy !!")


	FuncSeq = new Array(null,   0,34,35,34,35,34,35,36,25,36,25,36,25,6   ,0,24,26,24,26,24,26,33   ,0,27,28,19,27,28,19,27,28,19,27,28,19   ,0,27,29,19   ,0,30,31,21,30,31,21   ,12,12,12,12,12,12,12,12,12,12   ,17,17,17,17,17,17   ,7,33,10,16,21,21,21,21,21,21,21   ,0,32,33,15,15,15,15,15,15,15,10,10,10,10,10)

	TimeSet = new Array(null,   2500,250,150,250,150,250,2500,250,150,250,150,250,600,1000   ,2000,250,150,250,150,250,150,3350   ,2500,250,150,0,250,150,0,250,150,0,250,150,0   ,2500,350,150,2000   ,2500,250,150,0,250,150,1500   ,175,175,175,175,175,175,175,175,175,2500   ,175,175,175,175,175,1475   ,1000,3350,500,500,175,175,175,175,175,175,175   ,2250,3500,3350,175,175,175,175,175,350,500,175,175,175,175,175)

	TextSeq = new Array(null,   1,1,1,1,1,1,2,2,2,2,2,2,2,0   ,3,3,3,3,3,3,3,0   ,4,4,4,4,4,4,4,0,0,0,0,0,0   ,5,5,5,0   ,6,6,6,6,6,6,6   ,0,0,0,0,0,0,0,0,0,7   ,7,7,7,7,7,7   ,7,7,7,7,0,0,0,0,0,0,0   ,8,8,8,8,8,8,0,0,0,0,0,0,0,0,9)



	window.status=ToDisplay[TextSeq[DemoStat]]
	q=FuncSeq[DemoStat]
	if ( ( q>0 ) & ( q<9 ) )
		SideMag(q,0)
	if ( ( q>9 ) & ( q<22 ) )
		TopMagMove(q-9)
	if ( q==25 ) {
		BotForm.Sp1.src="BlackDot.jpg"
		BotForm.Sp0.src="BlackDot.jpg"
	}
	if ( q==36 ) {
		BotForm.Sp1.src="WhiteDot.gif"
		BotForm.Sp0.src="WhiteDot.gif"
	}
	if ( q==24 )
		BotForm.Sp1.src="WhiteDot.gif"
	if ( q==26 )
		BotForm.Sp1.src="LeftMag.jpg"
	if ( q==27 )
		BotForm.Sp2.src="WhiteDot.gif"
	if ( q==28 )
		BotForm.Sp2.src="BlackDot.jpg"
	if ( q==29 )
		BotForm.Sp2.src="TopMag.jpg"
	if ( q==30 )
		BotForm.Sp3.src="WhiteDot.gif"
	if ( q==31 )
		BotForm.Sp3.src="BlackDot.jpg"
	if ( q==32 )
		Pulse(8,-1)
	if ( q==33 )
		Pulse(1,1)
	if ( q==34 ) {
		BotForm.Sp4.src="WhiteDot.gif"
		BotForm.Sp5.src="WhiteDot.gif"
	}
	if ( q==35 ) {
		BotForm.Sp4.src="BlueTriangle.jpg"
		BotForm.Sp5.src="BlueTriangle.jpg"
	}

	if ( DemoStat>0 ) {
		DemoTimer=window.setTimeout("DemoGame()",TimeSet[DemoStat])
		DemoStat++
	}
}
