/*
Name    : Online Sudoku
Author  : Binny V A
Version : 2.00.A Beta
Website : http://www.geocities.com/binnyva
This code is Copyright (c) 2005 Binny V Abraham
License is granted to user to reuse this code on other Web site
if, and only if, this entire copyright notice is included. The Web Site
containing this script must be a not-for-profit(non-commercial) web site 
unless I gave permission for the use of the script.
End copyright - This must be retained and posted as is to use this script
along with a link to the original location.
*/



//Base Games
var puzzles = new Array(
"abc.gdefihdeif.hagcbfgh.cibade.bf.iehdcg.ae.acbf.gid.hghdiace.bficgdabhefh.b.f.cg.eaidde.ahfibcg", //15
"a.bfhiec.g.ddcg.fbai.heiehdg.cabfdegi.hc.fabai.cb.df.eghhf.be.agcidbfi.edhgcac.adgf.iheb.g.hebcaf.di", //19
"bfi.edhgcac.adgf.iheb.g.hebcaf.dia.b.fhiec.g.ddcg.fbai.heiehdg.cabfdegi.hc.fabai.cb.df.eghhf.be.agcid", //20
"ib.ad.c.g.efhe.hc.fbiagd.fg.daehcibbhcgd.faiegf.ei.ab.dchdai.hcebfgfgdcai.he.bbeahd.gc.ifih.c.e.bf.gda", //21
"aeh.dfi.cgbcf.b.e.hgiad.gidc.abfeh.fc.g.b.aeihdb.eifdha.gchda.ig.cebfg.bfhd.aeic.dcegi.f.hbaah.ibce.dfg",
"dah.iegfcbbigfd.cehae.fchab.gi.dbh.fe.gacidcedi.bhgaf.ag.i.d.cfbh.egb.ch.dea.f.ihf.e.aci.d.gbid.a.fbgceh",
"cf.b.ag.eidhhd.eif.cbaga.g.ibdh.fceg.acb.ifhe.d.dehgcafb.i.ifbe.hdg.acdc.iebg.f.haegf.ahd.cibhba.ci.f.deg",
"chfgeai.d.be.gdib.hcf.ab.iacf.dh.gefa.d.hcg.ebigic.bd.eahfeb.hfa.i.gdcd.gh.bica.fe.fei.hagd.cb.a.cbdefihg",
"adbfheig.c.icfba.gdeh.he.gcidfa.bcb.ide.ah.fgag.dh.fbei.cefhigcbd.abi.he.cd.gafg.de.fbach.i.acf.g.hid.b.e",
"ied.a.bfghchcfgeia.b.dagbh.cdi.efb.ied.ca.f.ghcga.ef.hdib.fd.hbig.cae.hdie.fg.cabb.a.e.ihcf.dggfcd.b.aehi",
"h.g.bc.ea.idfa.ci.bf.dgehfe.dih.gcbab.fi.ehg.acdh.dcfabi.geag.edc.ib.fhdah.gbe.ficebf.ci.ad.hggi.ch.df.e.ab",
".e.cadbhfgi.fbhegiad.cg.di.afch.bei.h.fba.g.cd.e.badhceif.g.ec.g.dif.b.hag.ibhe.da.fc.chagifde.bfedcabi.g.h",
"ge.c.h.i.fdabaif.bg.d.echdh.bae.cf.gic.he.fbdig.a.dbageifh.c.ifgca.hb.deb.dh.efg.acicf.e.ia.bhdggia.h.c.d.ebf",
"deb.cg.a.ihff.ah.dbi.egccgi.h.fe.bda.gcdf.bihae.a.fb.hd.ec.i.geihg.acfb.dbi.ca.d.hefgge.dbc.fi.haah.f.ie.gdcb"
);

////////////////////////////////////// Random Number Genarators //////////////////////////////////////
//Returns a random number between 1 and 9(inclusive)
function rand() {
	var number = Math.round(Math.random()*10);
	while (number < 1 || number > 9) { //If the number is 0 or 10, get another number.
		number = Math.round(Math.random()*10);
	}
	return number; 
}

//Returns a random number(1-9) that is not in the list given as the argument
function uniqueRand(list) {
	var number = rand();

	for(var a=0;a<list.length;a++) {
		if(list[a] == number) { //If the random number was found in the list,
			number = rand(); //get a new number,
			a=-1; //and start over again.
		}
	}
	return number;
}

//This will make new puzzles but replacing all numbers in a base game with other numbers - in effect creating
//	a entirely new game. This function is sneaky - Big Time
function makeNewOrder(str) {
	//Inits
	var alpha = " abcdefghijklmnopqrstuvwxyz";
	var new_order = "";

	//Get random numbers for all alphas - and store it in a array.
	var numbers = new Array("0");
	for(j=0;j<9;j++) {
		var new_numbers = uniqueRand(numbers); //Give random position for the numbers
		numbers.push(new_numbers);
	}

	//Now change all the alphas back to numbers - with new digits
	for(i=0;i<str.length;i++) {
		if(str.charAt(i)=="." || str.charAt(i)=="*" || str.charAt(i)=="x" || 
				str.charAt(i)=="_" || str.charAt(i)=="-" || str.charAt(i)=="+") { //It is a special char
			new_order += "."
		} else {
			new_order += numbers[alpha.indexOf(str.charAt(i))]
		}
	}

	return new_order;
}

//Creates the puzzle
function newGame() 
{
	var chosen = Math.floor((Math.random()*10) / (10/puzzles.length)); //'chosen' puzzle should be random
	this_puzzle = makeNewOrder(puzzles[chosen]);
	saveExistingValues();	
	
	//Clear the existing numbers first
	completed= false;
	var last_box_ended_at = 0;
	var extra_number_count = 0;
	
	//default_number_per_box = $("difficulty").value;
	default_number_per_box = 5;
 
	for(var i=0;i<9;i++) {
		//Initialisations
		var b=0,location_of_fixed_number=0;
		var arr_b = new Array();

		//Get the numbers for this box from the 'this_puzzle' varaible
		var limit = 9;
		var this_box = "";
		var dot_count = 0;
		for(var j=last_box_ended_at; j<last_box_ended_at+limit; j++) {
			if(this_puzzle.charAt(j) == ".") {
				limit++;
				dot_count++;
			}
			this_box = this_box + this_puzzle.charAt(j);
		}
		last_box_ended_at = last_box_ended_at + limit;

		//Decide how much numbers must appear in this box
		var number_of_numbers = default_number_per_box - extra_number_count;
		extra_number_count = 0;

		// 'extra_number_count' is used for reducing the number of populated cells in the next box if 
		//		the current box has more than 4 numbers.

		//If the number of dots are more than 4, use it
		if (dot_count > number_of_numbers) {
			if(rand() > 5) {
				extra_number_count = dot_count - number_of_numbers;
			} 
			number_of_numbers = dot_count;
		}

		//Empty the array.
		arr_b = new Array();
		//Get the positions in the box and insert the numbers there
		for(b=0;b<number_of_numbers;b++) {
			location_of_fixed_number = this_box.indexOf(".");

			if(location_of_fixed_number + 1) {//If there are dots...
				//Remove this dot
				this_box =  this_box.substring(0,location_of_fixed_number) +
							this_box.substring(location_of_fixed_number+1,this_box.length);
			
			} else { //No more dots - get some random locations
				location_of_fixed_number = uniqueRand(arr_b); //Give random position for the numbers
				location_of_fixed_number--;//uniqueRand gives 1-9. We need it from 0
			}

			arr_b.push(location_of_fixed_number+1);//Put the number into the don't repeat array

			//Get the numbers that should be inserted
			var insertion_number = this_box.charAt(location_of_fixed_number);
			cells[i][location_of_fixed_number]=insertion_number;
		}
	}
	
	initSudokuBoard();
}
function checkIfStarted()
{
	if(originalValues=="")
	{
		document.getElementById("workspace:consoleTextArea").value="Puzzle not started. \n"+document.getElementById("workspace:consoleTextArea").value;
		return false;
	}
	return true;
}
function checkSudokuBoard()
{
var val;
var i=1, j=0;
var status=true;
var board = this_puzzle.replace(/\./g,"");
	if(!checkIfStarted())
		return;
	if(completed)
	{
		document.getElementById("workspace:consoleTextArea").value="Puzzle already finished. \n"+document.getElementById("workspace:consoleTextArea").value;
		return;
	}
for(var z=0; z<3; z++)
	{ 
	for(var x =0; x<3; x++)
	{
		for(var y =0; y<19; y+=9)
		{
			for(var w=0; w<3; w++)
			{
			
			val = board.charAt((y+w)+(3*x)+(27*z));
		
			if(val=="" || isNaN(val) || val!=document.getElementById(j+"-"+i).innerHTML )
			{
				status=false;
				document.getElementById(j+"-"+i).focus();
			}
			j++;
			}
		}
	i++;
	j=0;
	}
	}
	
	if(status)
	{
	document.getElementById("workspace:consoleTextArea").value="Congrats puzzle completed. \n"+document.getElementById("workspace:consoleTextArea").value;
	completed=true;
	replayOrEnd();
	}
	else
	document.getElementById("workspace:consoleTextArea").value="Puzzle not finished. \n"+document.getElementById("workspace:consoleTextArea").value;
	
}

//Clear all the fields - and enable all the disabled cells
function saveExistingValues()
 {
	var x=1;
	
	for(var i=0; i<9; i++) 
	{
		for(var j=0; j<9; j++) 
		{
			cells[i][j] = "#";
			document.getElementById(j+"-"+x).contentEditable=true;
			
			
			var val = document.getElementById(j+"-"+x).innerHTML;
			if(val.length>0)
				originalValues += document.getElementById(j+"-"+x).innerHTML+",";
			else
				originalValues += " ,";
			
			document.getElementById(j+"-"+x).innerHTML ="";
		}
	x++;
	}

}
function restoreValues()
{
	if(!checkIfStarted())
		return;
	
	var x=0;
	completed=true;
	var values = originalValues.split(",");
	for(var i=1;i<10;i++) 
	{
		for(var j=0;j<9;j++) 
		{
		  document.getElementById(j+"-"+i).style.backgroundColor="transparent";
		  if(values[x]!=" ")
		  {
			  document.getElementById(j+"-"+i).innerHTML = values[x];
		  }
		  else
			  document.getElementById(j+"-"+i).innerHTML ="";
		  document.getElementById(j+"-"+i).contentEditable =true;
		  document.getElementById(j+"-"+i).style.color="black";
		  x++;
		}
	}
	originalValues="";
}
function initSudokuBoard()
{
	var sudokuBoard="";
	for(var i=0;i<9;i++) 
	{
		for(var j=0;j<9;j++) 
		{
			sudokuBoard = sudokuBoard + cells[i][j];
		}
	}
	insertBoardElements(true, sudokuBoard);
}
function solveBoard()
{
	if(!checkIfStarted())
		return;
	solveCurrentBoard(this_puzzle);

}
function solveCurrentBoard(currentBoard)
{
	currentBoard = currentBoard.replace(/\./g,"");
	insertBoardElements(false, currentBoard);
	completed=true;
}
function replayOrEnd()
{
	if(confirm("Play again? \n")) 
	{
		newGame();
	}
	else
		restoreValues();
}
function insertBoardElements(colorFlag, currBoard)
{
	var i=1, j=0;
	var val;
	var cellColor="transparent";
	for(var z=0; z<3; z++)
	{ 
	for(var x =0; x<3; x++)
	{
		for(var y =0; y<19; y+=9)
		{
			for(var w=0; w<3; w++)
			{
			if(colorFlag)
			{
			if((z==1 || y==9) && !(z==1 && y==9))
				cellColor="#56A5EC";
			else
				cellColor="#FFFFFF";
			}
			
			val = currBoard.charAt((y+w)+(3*x)+(27*z));
			if(colorFlag)
				document.getElementById(j+"-"+i).style.backgroundColor=cellColor;
				
			if(val!="#" || !isNaN(val))
			{
				document.getElementById(j+"-"+i).innerHTML = val;
				document.getElementById(j+"-"+i).style.color="blue";
				document.getElementById(j+"-"+i).contentEditable=false;
			}
			j++;
			
			}
		}
	i++;
	j=0;
	}
	}
}
