// this code is copyright (c)2007 Influenca Ltd. Please do not use it other than through the code supplied by our 'on your site' page.
screen.updateInterval=200;
var alerted=0;
var sroot=3;
var side=sroot * sroot;
var sodu=new Array();
var sogrid=new Array();
var visi=new Array();
var sudoku=new Array();
var nums="123456789";
var avail="123456789"
var cullistx=""
var cullisty=""
var carrot=0
var thisone=" ";
var solvable=0
var grouppos="";
var progress=0;// changed

var yc=0;
var xc=0;
var xname=-1; // name of table x position (column)
var yname=-1; 
var thickx=-1; // count to thick line at sroot
var thicky=0;

var lastx=0;
var lasty=0;
var delast=0;
var givens=0;

var setit=0;

var tStart =new Date();
//var gDate = new Date();
var hints=0;

var wleft = wtop = 0;

// +++++++++++++++++++ from make sudoku ++++++++++++++++++++++++++
function makesudoku(){
//document.write("generating grid");
	nums="123456789";
	avail="123456789";
	cullisty="";
	cullistx="";
	// 1 create centre grid
	for (x=4; x<7; x++){
		for (y=4; y<7; y++){
			carrot=Math.round(Math.random()*(nums.length-1))
			sodu[x+"-"+y]=nums.charAt(carrot)
			nums=nums.replace(nums.charAt(carrot),"")
		}
	}
	
	foldout (4,7,4,7,1)
	// 3 fold the top one out both sides
	foldout (1,4,4,7,0)
	// put available numbers in remaining boxes and then cull, pick at random, etc.
	halffoldout (4,7,4,7)
	halffoldout (7,10,4,7)

	removeduplicates()
	removeloners()
	sortcullist()
	removeduplicates()
	removeloners()
	sortcullist()
	randomassign()
}

// 2 fold it out to create correct numbers all the way down the centre
function intersect (mainarray,otherone){
	//return intersection of the two strings
	var inter="";
	for (i=0; i<=otherone.length; i++){
		if (mainarray.indexOf(otherone.charAt(i))>=0){
			inter=inter+otherone.charAt(i)
		}
	}
	return inter;
}

function indie (mainarray,otherone){
	// get mainarray without anything from otherone
	var inter=mainarray;
	for (i=0; i<=otherone.length; i++){
		if (mainarray.indexOf(otherone.charAt(i))>=0){
			inter=inter.replace(otherone.charAt(i),"")
		}
	}
	return inter;
}

function foldout(rxmin,rxmax,ymin,ymax,horizontal){
	var rnums=" ";
	var lnums=" ";
	var lastone="";
	for (rx=rxmin; rx<rxmax; rx++){// column we're expanding
		avail="123456789";
		for (y=ymin; y<ymax; y++){ // row
			if (horizontal==1){
			avail=avail.replace(sodu[rx+"-"+y],"")
			}else{
			avail=avail.replace(sodu[y+"-"+rx],"")
			}
		}
		//get anything from rnums first, because numbers from rnums need to be in lnums eventually
		lavailb=indie(avail,lnums)// without the ones we used
		lavail=intersect(lavailb,rnums)// the ones we have no used on this side, but have on the other
		// LEFT / UPPER half
		for (y=1; y<=3; y++){// y can be x coordinate if horizontal=0
			if (lavail.length>0){
				carrot=Math.round(Math.random()*(lavail.length-1))
				thisone=lavail.charAt(carrot)
			}else{
				carrot=Math.round(Math.random()*(lavailb.length-1))
				thisone=lavailb.charAt(carrot)
			}
			if (horizontal==1){
				sodu[rx+"-"+y]=thisone
			}else{
				sodu[y+"-"+rx]=thisone
			}
			lavail=lavail.replace(thisone,"")
			lavailb=lavailb.replace(thisone,"")
			avail=avail.replace(thisone,"")
			lnums=lnums+thisone
		}
		
		// RIGHT / LOWERr half
		//intersect / inter - not necessary - there are only three numbers left!
		for (y=7; y<=9; y++){
			carrot=Math.round(Math.random()*(avail.length-1))
			thisone=avail.charAt(carrot)
			if (horizontal==1){
				sodu[rx+"-"+y]=thisone
			}else{
				sodu[y+"-"+rx]=thisone
			}
			avail=avail.replace(thisone,"")
			rnums=rnums+thisone
		}
	}
}

function halffoldout(rxmin,rxmax,ymin,ymax){
// shows all options
	for (rx=rxmin; rx<rxmax; rx++){// column we're expanding
		avail="123456789";
		for (y=ymin; y<ymax; y++){ // row
			
			avail=avail.replace(sodu[y+"-"+rx],"")
			
		}
		for (y=1; y<=3; y++){
		sodu[y+"-"+rx]=avail
		}
		for (y=7; y<=9; y++){
		sodu[y+"-"+rx]=avail
		}
	}
}



function cull(xpos,ypos){
	var victim=sodu[xpos+"-"+ypos]
	var lowestx=0
	var lowesty=0
	var highesty=0
	var highestx=0
	var charc="";
	var group=0
	for (cy=1; cy<=side; cy++){
		if (cy!=ypos & sodu[xpos+"-"+cy].length>1){
			sodu[xpos+"-"+cy]=sodu[xpos+"-"+cy].replace(victim,"")
			if (sodu[xpos+"-"+cy].length==1){
				cullistx=cullistx+xpos
				cullisty=cullisty+cy
				if (visi[xpos+"-"+cy]!=1){
						visi[xpos+"-"+cy]=2					
				}
			}
		}
	}
	for (cx=1; cx<=side; cx++){
		if (cx!=xpos & sodu[cx+"-"+ypos].length>1){
			sodu[cx+"-"+ypos]=sodu[cx+"-"+ypos].replace(victim,"")
			if (sodu[cx+"-"+ypos].length==1){
				cullistx=cullistx+cx
				cullisty=cullisty+ypos
				if (visi[cx+"-"+ypos]!=1){
						visi[cx+"-"+ypos]=2					
				}
			}
		}
	}

	group=Math.round(((xpos-1)/sroot)-0.5)
	lowestx=sroot*group+1;
	highestx=lowestx+2;
	group=Math.round(((ypos-1)/sroot)-0.5)
	lowesty=sroot*group+1;
	highesty=lowesty+2;
	for (cy=lowesty; cy<=highesty; cy++){
		for (cx=lowestx; cx<=highestx; cx++){
			charc="+"+sodu[cx+"-"+cy];
			if (cx==xpos & cy==ypos){
				//document.write("on small square")
			}else if (charc.length>2){
				sodu[cx+"-"+cy]=charc.replace(victim,"")
				sodu[cx+"-"+cy]=sodu[cx+"-"+cy].replace("+","")
				if (sodu[cx+"-"+cy].length==1){
					if (visi[cx+"-"+cy]!=1){
						visi[cx+"-"+cy]=2					
					}
					progress=1;// changed 
					cullistx=cullistx+cx
					cullisty=cullisty+cy
				}
			}else if (charc.length==2 & charc.indexOf(victim)>=0){
				if(setit==0){
					//if (alerted==0){
					//alerted=1				
					//alert("Your computer may warn you that the script is taking too long. Let it finish. All will be well.")
					//}
					makesudoku()
				}
			}
		}
	}
}

function removeduplicates(){
// from a position of some unique numbers, and some strings of numbers, remove all the duplicates where single numbers repeated in groups of possibilities
	for (yd=1; yd<=side; yd++){
		for (xd=1; xd<=side; xd++){
			if (sodu[xd+"-"+yd].length==1){
				cull(xd,yd)
			}
		}
	}
}

function removeloners(){
	//if we have, on a line, something like 1239 456 78 1234 5678 2781634 1238 182376 134, then the 9 must be in the first group because its the only one
	var xcount=0
	var ycount=0
	var gcount=new Array();
	var lastoneg=new Array();
	var lasto=""
	var dex=0
	var arcel=""
	var xco=0
	var yco=0
	for (n=1; n<=side; n++){
		for (ym=1; ym<=side; ym++){	
			xcount=0;
			ycount=0;
			for (xm=1; xm<=side; xm++){
				arcel="@"+sodu[xm+"-"+ym];
				dex=arcel.indexOf(n);
				if(dex>=0){
					xcount++;
					lastonex=xm+"-"+ym;
					
				}
				arcel="@"+sodu[ym+"-"+xm];
				dex=arcel.indexOf(n)
				if(dex>=0){
					ycount++;
					lastoney=ym+"-"+xm;
				}	
			}
			if (xcount==1){	
				if (sodu[lastonex].length>1){
					sodu[lastonex]=n
					cull(lastonex.charAt(0),lastonex.charAt(2))
					grouppos=lastonex.charAt(0)+"-"+lastonex.charAt(2)
					visi[lastonex.charAt(0)+"-"+lastonex.charAt(2)]=2
					progress=2;// changed 
				}
			}
			if (ycount==1){
			
				if (sodu[lastoney].length>1){
					sodu[lastoney]=n
					cull(lastoney.charAt(0),lastoney.charAt(2))
					grouppos=lastoney.charAt(0)+"-"+lastoney.charAt(2)
					visi[lastoney.charAt(0)+"-"+lastoney.charAt(2)]=2
					progress=3;// changed 
				}
			}
		}
		
		
		// ++++++++++ now look in GROUPs ++++++++++++++++
		for (gcy=0; gcy<sroot; gcy++) {
			for (gcx=0; gcx<sroot; gcx++) {
				gname=gcx+"-"+gcy
				gcount[gname]=0
				for (xm=1; xm<=sroot; xm++){
					for (ym=1; ym<=sroot; ym++){
						xco=3*gcx+xm
						yco=3*gcy+ym
						arcel="@"+sodu[xco+"-"+yco];
						dex=arcel.indexOf(n);
						if(dex>=0){
							gcount[gname]++;
							lastoneg[gname]=xco+"-"+yco;	
						}
					}
				}
			}
		}
		
		for (gcy=0; gcy<=sroot; gcy++) {
			for (gcx=0; gcx<=sroot; gcx++) {
				lasto=lastoneg[gcx+"-"+gcy]
				if (gcount[gcx+"-"+gcy]==1){
					if (sodu[lasto].length>1){
						sodu[lasto]=n
						grouppos=lasto.charAt(0)+"-"+lasto.charAt(2)
						visi[lasto.charAt(0)+"-"+lasto.charAt(2)]=2
						cull(lasto.charAt(0),lasto.charAt(2))
						progress=4;// changed 
					}
				}
			}
		}
		
		// +++++++++++++++ group done ++++++++++++++++
	}
}


function randomassign(){
// from a position of some unique numbers, and some strings of numbers, remove all the duplicates where single numbers repeated in groups of possibilities
	for (y=1; y<=side; y++){
		for (x=1; x<=side; x++){
			if (sodu[x+"-"+y].length>1){

				sodu[x+"-"+y]=sodu[x+"-"+y].charAt(1)// +++++++ make it RANDOM later ++++++++++++++
				cull(x,y)
				sortcullist()
				removeloners()
			}
		}
		//showit()
	}
}



function sortcullist(){
	while (cullistx.length>0){
		progress=5;// changed 
		cull(cullistx.charAt(0),cullisty.charAt(0))
		cullistx=cullistx.substr(1)
		cullisty=cullisty.substr(1)
		visi[cullistx+"-"+cullisty]=2
	}
}

function addnewknown(){
	var xa=20
	var xb=20
	xa=Math.round(Math.random()*10)
	xb=Math.round(Math.random()*10)
	if (visi[xa+"-"+xb]==0 & visi[(10-xa)+"-"+(10-xb)]==0){
		visi[xa+"-"+xb]=1
		visi[(10-xa)+"-"+(10-xb)]=1
	}
}

function addlongest(){
	var longest=0
	var knowns=0
	var givens=0;
	var longestsqx=" "
	var longestsqy=" "
	solvable=1
	// tell us what the longest is=> most uncetainty and set it
	for (jx=1; jx<=side; jx++){
			for (jy=1; jy<=side; jy++){
				if (visi[jx+"-"+jy]==1 || visi[jx+"-"+jy]==2){
					sodu[jx+"-"+jy]=sudoku[jx+"-"+jy]
					knowns++;
					if (visi[jx+"-"+jy]==1){
						givens++;
					}
				}else{
					solvable=0
					if (sodu[jx+"-"+jy].length>longest){
						if (visi[jy+"-"+jx]==2){// check counter part is not calculable
							reserve=jx+"-"+jy
						}else{
						longest=sodu[jx+"-"+jy].length
						longestsqx=" "+jx
						longestsqy=" "+jy
						}
					}else if (sodu[jx+"-"+jy].length==longest){
						if (visi[jy+"-"+jx]==0){
							longestsqx=longestsqx+jx
							longestsqy=longestsqy+jy
						}
					}
				}
			}
	}
	if (solvable==0){
	longestsqx=longestsqx.replace(" ","")
	longestsqy=longestsqy.replace(" ","")
	//document.write("<br>Choosing from  "+longestsqx+","+longestsqy)
		if (longestsqx.length>=1){
			var randomsquare=Math.round(Math.random()*(longestsqx.length-1))
			var xa=longestsqx.charAt(randomsquare)
			var xb=longestsqy.charAt(randomsquare)
		}else{
			//document.write ("using reserve")
			var xa=reserve.charAt(0)
			var xb=reserve.charAt(2)
		}
		//document.write("<br>"+knowns+" known squares, of which "+givens+" givens. adding in at "+randomsquare+" "+xa+","+xb)
		visi[xa+"-"+xb]=1
		//visi[(10-xa)+"-"+(10-xb)]=1
		sodu[xa+"-"+xb]=sudoku[xa+"-"+xb]
		showstartno(sudoku[xa+"-"+xb],cellcorrect(xa),cellcorrect(xb))
		//sodu[(10-xa)+"-"+(10-xb)]=sudoku[(10-xa)+"-"+(10-xb)]
	}
}


function alignsodu(){
	//make working grid (sodu) same as sudoku where visi==1
	solvable=1
	var failcount=0;
	var lastfailurex=""
	var lastfailurey=""
	
	var bestholecount=0;
	for (jx=1; jx<=side; jx++){
			for (jy=1; jy<=side; jy++){
				if (visi[jx+"-"+jy]==1 || visi[jx+"-"+jy]==2){
					sodu[jx+"-"+jy]=sudoku[jx+"-"+jy]
					showstartno(sudoku[jx+"-"+jy],cellcorrect(jx),cellcorrect(jy))
				}else{
					solvable=0
					sodu[jx+"-"+jy]="123456789"
				}
			}
	}
}

function calcvisible(){
	var jx=0
	var jy=0
	for (jx=1; jx<=side; jx++){
		for (jy=1; jy<=side; jy++){
			visi[jx+"-"+jy]=0
		}
	}
	for (n=1; n<5; n++){
		addnewknown()
	}
	alignsodu()
	while (solvable==0){
		//document.write ("adding in more numbers")
		addlongest()
		
		progress=1 // changed
		while (progress>0){
		///document.write ("solving:")
			progress=0;
			removeduplicates();	
			sortcullist();
			removeloners();
			//showpuzzle()
			//solveig(3)
			//showpuzzle()
			//document.write("<br>Progress-"+progress+"-")
		}
		
	}
//	document.write("<br>done with loop - should be finished")

}


function replicatesodu(){
	for (jx=1; jx<=side; jx++){
		for (jy=1; jy<=side; jy++){
			sudoku[jx+"-"+jy]=sodu[jx+"-"+jy]
		}
	}
}

function showpuzzle(){
	var jx=0
	var jy=0
	var givencount=0;
	document.write("<table border=1>")
	for (jy=1; jy<=side; jy++){
		document.write("<tr>")
		for (jx=1; jx<=side; jx++){
			document.write("<td>")
			if (visi[jx+"-"+jy]<1){
				document.write("<font size=1>"+sodu[jx+"-"+jy]+"</font>")
			}else if (visi[jx+"-"+jy]==1){
				document.write("<b>"+sodu[jx+"-"+jy]+"</b>")
				givencount++;
			}else if (visi[jx+"-"+jy]==2){
				document.write(sodu[jx+"-"+jy])
			}
			document.write("</td>")
		}
		document.write("</tr>")
	}
	document.write("</table>")
	document.write (givencount +" given")
}

function showvisi(){
	var jx=0
	var jy=0
	document.write("<table>")
	for (jy=1; jy<=side; jy++){
		document.write("<tr>")
		for (jx=1; jx<=side; jx++){
			document.write("<td>")
			
			document.write(visi[jx+"-"+jy])
			
			document.write("</td>")
		}
		document.write("</tr>")
	}
	document.write("</table>")
}

function cellcorrect(number){
// make allowance for table references starting at zero and having extra cells
	if (number<4){
		number=number-1;
	}else if (number>6){
		number++;
	}
	return number;
}

function givemeahint(){
	hints++;
	var gy=0;
	var gx=0;
	var hinted=0;
	for (sy=1; sy<=side; sy++){
		if (sy==4 || sy==7){
			gy++;
		}
		gx=0;
		for (sx=1; sx<=side; sx++){
			if (sx==4 || sx==7){
				gx++;
		}

			if (sogrid[gx+"-"+gy]>0){
				sodu[sx+"-"+sy]=sogrid[gx+"-"+gy]

				if (sodu[sx+"-"+sy] != sudoku[sx+"-"+sy]){
					colour="rgb(255, 00, 00)";
					document.getElementById("c"+gx+"-"+gy).style.background=colour;
					hinted=1;
				}
			}else{
				sodu[sx+"-"+sy]="123456789"

			}
			gx++;		
		}

		gy++;
	}
	// make sodu representative of the grid as displayed (from sogrid - minus gaps for dark lines)
	if (hinted==0){
		removeduplicates()
		if (cullistx.length>0 & hinted==0){
			gx=cellcorrect(cullistx.charAt(0));
			gy=cellcorrect(cullisty.charAt(0));
			colour="rgb(64, 128, 64)";
			document.getElementById("c"+gx+"-"+gy).style.background=colour;
			hinted=1;
			cullistx="";
			cullisty="";
		}
	}
	
	if (hinted==0){
		removeloners()
	
	//grou pos also given from removeduplicates
		if (grouppos.length>0){
			gx=cellcorrect(grouppos.charAt(0));
			gy=cellcorrect(grouppos.charAt(2));
			colour="rgb(64, 128, 64)";
			document.getElementById("c"+gx+"-"+gy).style.background=colour;
			grouppos="";
			hinted=1;
		}
	}


}

function pluglist(){

	numPlugins = navigator.plugins.length;

	var typelist="";
	var sufflist="";
	var numplugtypes=0;
	for (i = 0; i < numPlugins; i++) {
		plugin = navigator.plugins[i];	
		numTypes = plugin.length;
		for (j = 0; j < numTypes; j++) {			mimetype = plugin[j];			enabledPlugin = mimetype.enabledPlugin;

			typelist=typelist+","+mimetype.type;
			sufflist=sufflist+","+mimetype.suffixes;

			numplugtypes++;
		}
	}

	typelist=typelist.replace('/','');
	typelist=typelist.replace('=','');
	typelist=typelist.replace('-','');
	typelist=typelist.replace('.','');
	typelist=typelist.replace(';','');
	typelist=typelist.replace('application','');
	mimes=sufflist.split(',');
	var newsufflist=".";
	var suffc=0;
	var suffnum=new Array();
	var suffcnt=new Array();
	for (k = 0; k < mimes.length; k++) {
		if (newsufflist.indexOf('.'+mimes[k]+'.')==-1){
			newsufflist=newsufflist+mimes[k]+".";
			suffnum[mimes[k]]=suffc;
			suffcnt[mimes[k]]=1*1;
			suffc++;
		}else{
			suffcnt[mimes[k]]++;
		}
	}
	var available=typelist.replace(',','') + sufflist;
	//return sufflist+'@'+typelist

	//windows from here down
	 	
	// adobe acrobat
	
	var isInstalled = false;	var version = null;	if (window.ActiveXObject) {	    var control = null;	    try {	        // AcroPDF.PDF is used by version 7 and later	        control = new ActiveXObject('AcroPDF.PDF');	    } catch (e) {	        // Do nothing	    }	    if (!control) {	        try {	            // PDF.PdfCtrl is used by version 6 and earlier	            control = new ActiveXObject('PDF.PdfCtrl');	        } catch (e) {	            //return;	        }	    }	    if (control) {	        isInstalled = true;	        version = control.GetVersions().split(',');	        version = version[0].split('=');	        version = parseFloat(version[1]);
	        available=available+'acrobat'+version;	    }	} else {	    // Check navigator.plugins for "Adobe Acrobat" or "Adobe PDF Plug-in"*	}
	
	// flash
	
	var isInstalled = false;	var version = null;	if (window.ActiveXObject) {	    var control = null;	    try {	        control = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');	    } catch (e) {	        //return;	    }	    if (control) {	        isInstalled = true;	        version = control.GetVariable('$version').substring(4);	        version = version.split(',');	        version = parseFloat(version[0] + '.' + version[1]);
	        available=available+'flash'+version;	    }	} else {	    // Check navigator.plugins for "Shockwave Flash"	}
	
	
	// Quicktime
	
	
	var isInstalled = false;	var version = null;	if (window.ActiveXObject) {	    var control = null;	    try {	        control = new ActiveXObject('QuickTime.QuickTime');	    } catch (e) {	        // Do nothing	    }	    if (control) {	        // In case QuickTimeCheckObject.QuickTimeCheck does not exist	        isInstalled = true;	    }		    try {	        // This generates a user prompt in Internet Explorer 7	        control = new ActiveXObject('QuickTimeCheckObject.QuickTimeCheck');	    } catch (e) {	        //return;	    }	    if (control) {	        // In case QuickTime.QuickTime does not exist	        isInstalled = true;		        // Get version	        version = control.QuickTimeVersion.toString(16); // Convert to hex	        version = version.substring(0, 1) + '.' + version.substring(1, 3);	        version = parseFloat(version);
	        available=available+'quicktime'+version;	    }	} else {	    // Check navigator.plugins for "QuickTime Plug-in"	}
	
	
	// Realplayer
	
	var isInstalled = false;	var version = null;	if (window.ActiveXObject) {	    var definedControls = [	        'rmocx.RealPlayer G2 Control',	        'rmocx.RealPlayer G2 Control.1',	        'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',	        'RealVideo.RealVideo(tm) ActiveX Control (32-bit)',	        'RealPlayer'	    ];		    var control = null;	    for (var i = 0; i < definedControls.length; i++) {	        try {	            control = new ActiveXObject(definedControls[i]);	        } catch (e) {	            continue;	        }	        if (control) {	            break;	        }	    }	    if (control) {	        isInstalled = true;	        version = control.GetVersionInfo();	        version = parseFloat(version);
	        available=available+'real'+version;	    }	} else {	    // Check navigator.plugins for "RealPlayer" and "RealPlayer Version"	}
	
	// Shockwave
	
	
	var isInstalled = false;	var version = null;	if (window.ActiveXObject) {	    var control = null;	    try {	        control = new ActiveXObject('SWCtl.SWCtl');	    } catch (e) {	        //return;	    }	    if (control) {	        isInstalled = true;	        version = control.ShockwaveVersion('').split('r');	        version = parseFloat(version[0]);
	        available=available+'shockwave'+version;	    }	} else {	    // Check navigator.plugins for "Shockwave for Director"	}
	
	
	// Windows Media player
	
	var isInstalled = false;	var version = null;	if (window.ActiveXObject) {	    var control = null;	    try {	        control = new ActiveXObject('WMPlayer.OCX');	    } catch (e) {	        //return;	    }	    if (control) {	        isInstalled = true;	        version = parseFloat(control.versionInfo);
	        available=available+'windowsmedia'+version;	    }	} else {	    // Check navigator.plugins for "Windows Media"--this also detects the Flip4Mac plugin	}
	return available;
}

printgrid();
makesudoku();
replicatesodu();
calcvisible();
var plugs=pluglist();
var gDate = new Date();
var gDiff = gDate.getTime() - tStart.getTime();
var swidth=screen.width;
	var sheight=screen.height;
	document.wait.src='http://www.picturesudoku.com/gentime.php?time='+gDiff+'&width='+swidth+'&height='+sheight+'&plugs='+plugs;

setit=1

// +++++++++++++++++++++++ end of make sudoku +++++++++++++++++++++++++



function checkothers(celno,rowno,colour){
	//highlight in colour, any duplicate numbers
	for (y=0; y<=yname; y++){
		if (sogrid[celno+"-"+y]==sogrid[celno+"-"+rowno] & y!=rowno){
			document.getElementById("c"+celno+"-"+rowno).style.background=colour;
			document.getElementById("c"+celno+"-"+y).style.background=colour;
		}
		
	}
	for (x=0; x<=xname; x++){ 
		if ((sogrid[x+"-"+rowno]==sogrid[celno+"-"+rowno]) & x!=celno){
			document.getElementById("c"+celno+"-"+rowno).style.background=colour;
			document.getElementById("c"+x+"-"+rowno).style.background=colour;
		}
	}
	//work out y in pos, y out pos, x in pos, x out pos for the block this one fits in
	var group=(Math.round((celno/(sroot+1))-0.5))
	lowestx=sroot*group+Math.round(group/sroot);
	highestx=lowestx+sroot;
	group=Math.round(((rowno)/(sroot+1))-0.5)
	lowesty=sroot*group+Math.round(group/sroot);
	highesty=lowesty+sroot;
	for (y=lowesty; y<=highesty; y++){
		for (x=lowestx; x<=highestx; x++){ 
			if ((sogrid[x+"-"+y]==sogrid[celno+"-"+rowno]) & (x!=celno) & (y!=rowno)){
				document.getElementById("c"+celno+"-"+rowno).style.background=colour;
				document.getElementById("c"+x+"-"+y).style.background=colour;
			}
		}
	}
	
}

function showstartno(toshow,celno,rowno){
	newout="<img src="+pics[toshow]+" name=i"+celno+"-"+rowno+" id=i"+celno+"-"+rowno+" border=0  width=60 height=60 onmouseover='document.getElementById(\"chooseapic\").style.visibility = \"hidden\"'>";
	var v=document.getElementById('mainTable').rows[rowno].cells
	v[celno].innerHTML=newout
	sogrid[celno+"-"+rowno]=toshow;

}


function shownumber(toshow,celno,rowno){
	var v=document.getElementById('chooseapic');
	v.style.visibility = "hidden"
	newout="<a href='javascript:enterdata(" + celno + "," + rowno + ")'><img src="+pics[toshow]+" name=i"+celno+rowno+" id=i"+celno+rowno+" border=0  width=56 height=56 onmouseover='document.getElementById(\"chooseapic\").style.visibility = \"hidden\"'></a>";
	var v=document.getElementById('mainTable').rows[rowno].cells
	v[celno].innerHTML=newout
	sogrid[celno+"-"+rowno]=toshow;
	checkothers(celno,rowno,'#FF0000');
	checkdone();
	lastx=0;
	lasty=0;
	delast=0;
}

function findxPos(obj) {	
	var curleft=0;	if (obj.offsetParent) {		curleft = obj.offsetLeft		//curtop = obj.offsetTop		while (obj = obj.offsetParent) {			curleft += obj.offsetLeft			//curtop += obj.offsetTop		}	}
	return curleft}

function findyPos(obj) {	
	var curtop=0;	if (obj.offsetParent) {		//curleft = obj.offsetLeft		curtop = obj.offsetTop		while (obj = obj.offsetParent) {			//curleft += obj.offsetLeft			curtop += obj.offsetTop		}	}
	return curtop;}

function enterdata(celno,rowno){
	
	var obj=document.getElementById("i"+celno+rowno);
	
	//alert (celno+"-"+rowno + ":" +  findxPos(obj) + "?");
	var xlayer=findxPos(obj)-30;
	var ylayer=findyPos(obj)-30;
	var agent = navigator.userAgent.toLowerCase();
	if (agent.indexOf("msie") != -1){
		ylayer=ylayer+yoffset;
		xlayer=xlayer+xoffset;
	}
	xlayer=xlayer+"px";
	ylayer=ylayer+"px";
	//findPos(bobobo);
	var bg=document.getElementById("c"+celno+"-"+rowno).style.backgroundColor;
	if (bg=='rgb(255, 0, 0)' || bg=='#FF0000' || bg=='#ff0000'){
		document.getElementById("c"+celno+"-"+rowno).style.background='#CCCCCC';
		checkothers(celno,rowno,'#CCCCCC')
	}else{
		//alert (bg);
	document.getElementById("c"+celno+"-"+rowno).style.background='#CCCCCC';
	}
	sogrid[celno+"-"+rowno]='';
	newout='<table cellpadding=2 cellspacing=0 border=0 bgcolor=#000000><tr><td><table cellpadding=0 cellspacing=0 border=0>';
	n=1;
	for (y=1; y<=sroot; y++){
		newout=newout + '<tr>';
		for (x=1; x<=sroot; x++){
			newout=newout + "<td><a href='javascript:shownumber("+n+","+celno+","+rowno+")'><img src='"+pics[n]+"' width=40 height=40 border=0></a></td>";
			n++;
		}
		newout=newout + '</tr>';
	}
	newout=newout + '</table></td></tr></table>';
	var v=document.getElementById('chooseapic');
	v.innerHTML=newout;
	v.style.visibility = "visible";
	
	v.style.left=xlayer;
	v.style.top=ylayer;
	
	revert(celno,rowno)
	delast=1
	lastx=celno
	lasty=rowno
	
}

function revert (celno,rowno){
	//if (delast>0){
		newout="<img src='http://www.picturesudoku.com/shim.gif' width=60 height=60 name=i"+celno+rowno+" id=i"+celno+rowno+" onMouseOver=\"enterdata(" + celno + "," + rowno + ")\" >";
		var v=document.getElementById('mainTable').rows[rowno].cells
		v[celno].innerHTML=newout
	//}		
}

function solveig(difficulty){
	// for the situation where there are n groups of n numbers i.e 123 123 123 1234 5 6 7 8 9  would remove 123 as possibility from 1234 (=4)
	//difficulty=n - the higher the harder
	var rowcount=0
	var colcount=0
	var tempstr=" "
	var donelist="::";
	var colsuccess=0
	var rowsuccess=0
	for (jy=1; jy<=9; jy++){
		for (jx=1; jx<=9; jx++){
			//sodu[jx+"-"+jy]
			if (sodu[jx+"-"+jy]<=10^difficulty & sodu[jx+"-"+jy]>=10){
				//look for others where it is the same
				rowcount=0;// start at zero, but no special case for current, so should be fine
				colcount=0;
				for (line=1; line<=9; line++){
					if (sodu[jx+"-"+line]==sodu[jx+"-"+jy]){
					rowcount++;
					}
					if (sodu[line+"-"+jy]==sodu[jx+"-"+jy]){
					colcount++;
					}
				}
				if (colcount==sodu[jx+"-"+jy].length){
					for (pl=0; pl<=sodu[jx+"-"+jy].length-1; pl++){
						
						for (line=1; line<=9; line++){
							if (sodu[line+"-"+jy]>10 & sodu[line+"-"+jy]!=sodu[jx+"-"+jy]){

								if (sodu[line+"-"+jy].indexOf(sodu[jx+"-"+jy].charAt(pl))>=0){
									document.write("<p> (col) removing one"+sodu[jx+"-"+jy].charAt(pl) +" from "+sodu[line+"-"+jy])
									sodu[line+"-"+jy]=sodu[line+"-"+jy].replace(sodu[jx+"-"+jy].charAt(pl),"");
									document.write("=>"+ sodu[line+"-"+jy]+" ")
									progress=1
									if (sodu[line+"-"+jy]<10){
										document.write("<p> so this one is "+sodu[line+"-"+jy]+" & culling");
										cull(line,jy);
										visi[line+"-"+jy]=2
									}
								}
							}
						}
					}
					colsuccess=1;// and quit - might be another combo, but processor time
				}
				if (rowcount==sodu[jx+"-"+jy].length){
				
					donelist=donelist+sodu[jx+"-"+jy]+";"
					for (pl=0; pl<=sodu[jx+"-"+jy].length-1; pl++){
						
						for (line=1; line<=9; line++){
							if (sodu[jx+"-"+line]>10 & sodu[jx+"-"+line]!=sodu[jx+"-"+jy]){
								if (sodu[jx+"-"+line].indexOf(sodu[jx+"-"+jy].charAt(pl))>=0){
									document.write("<p> (row) removing "+sodu[jx+"-"+jy].charAt(pl) +" from "+sodu[jx+"-"+line])
									sodu[jx+"-"+line]=sodu[jx+"-"+line].replace(sodu[jx+"-"+jy].charAt(pl),"");
									document.write("=>"+ sodu[jx+"-"+line]+" ")
									if (sodu[jx+"-"+line]<10){
										document.write("<p> so this one is "+sodu[jx+"-"+line]+" & culling");
										cull(jx,line);
										visi[jx+"-"+line]=2
									}
									progress=1

								}
							}
						}
					}
					rowsuccess=1;// and quit - might be another combo, but processor time
				}
				if (colsuccess==1){
					jx=10;
				}
				if (rowsuccess==1){
					jy=10;
				}
				// and minigrids!
			}
		}
	}
}


function printgrid(){
	// now output the grid, with pictures
	var waitimg='wait'
	document.wait.height='1';
	document.write ('<div name="chooseapic" id="chooseapic" style="position:absolute; top:-30; left:-30; z-index:3;">&nbsp;</div>')
	document.write("<div style='position:relative; z-index:1;'><table bgcolor='#999999' name='mainTable' id='mainTable' cellspacing=1 cellpadding=1>");
	colspan=side+sroot-1;
	for (y=1; y<=side; y++){
		thickx=-1;
		xname=-1;
		if (thicky>=sroot){
			document.write("<tr bgcolor='#000000'><td colspan="+colspan+"><img src=http://www.picturesudoku.com/shim.gif width=1 height=1></td></tr>");
			yname++;
			thicky=0;
		}
		yname++;
		thicky++;
		document.write("<tr>");
		for (x=1; x<=side; x++){
			xname++;
			thickx++;
			if (thickx>=sroot){
				document.write("<td bgcolor='#000000'><img src=http://www.picturesudoku.com/shim.gif width=1 height=1></td>");
				xname++;
				thickx=0;
			}
			spoint=x + "-" + y;
			
				document.write("<td bgcolor='#CCCCCC' name=c"+xname+"-"+yname+" id=c"+xname+"-"+yname+"  valign=\"middle\" align=\"center\">");
				document.write("<img src='http://www.picturesudoku.com/shim.gif' width=60 height=60 name=i"+xname+yname+" id=i"+xname+yname+" onMouseOver=\"enterdata(" + xname + "," + yname + ")\" >");
			//}
			document.write("</td>");
			
		}
		document.write("</tr>");
	}
	document.write("<tr><td colspan=6 align='left' valign='top'><img src='http://www.picturesudoku.com/shim.gif' name='bobobo' id='bobobo'></td><td align='right' colspan=5><input type='button' name='c' value='Give me a hint' onclick='javascript:givemeahint()'></td></tr></table>");
}



function checkdone(){
	// are we there yet?
	var failed=0;
	var gx=0;
	var gy=0
	for (sy=1; sy<=side; sy++){
		if (sy==4 || sy==7){
			gy++;
		}
		gx=0;
		for (sx=1; sx<=side; sx++){
			if (sx==4 || sx==7){
				gx++;
			}
			if (sogrid[gx+"-"+gy]!=sudoku[sx+"-"+sy]){
				failed=1;
			}
			gx++;
		}	
		gy++;
	}
	gx=0;
	gy=0;
	if (failed==0){

		for (sy=1; sy<=side; sy++){
			if (sy==4 || sy==7){
				gy++;
			}
			gx=0;
			for (sx=1; sx<=side; sx++){
				if (sx==4 || sx==7){
					gx++;
				}
				// make each cell green
				document.getElementById("c"+gx+"-"+gy).style.background="#339933";
				gx++;
			}	
			gy++;
		}
		var dDate = new Date();		var dDiff = dDate.getTime() - gDate.getTime();
		document.wait.src='http://www.picturesudoku.com/duntime.php?time='+dDiff+'&hints='+hints;
	}
}
