/*-----------------------------------------------------------------------
	Copyrighted Andrew Stuart, 2005-2010, andrew@scanraid.com
	First version: 23 May 2005
	This version: 1.54, 01-MAY-2010
-----------------------------------------------------------------------*/
var stage=0,laststage=0,prevlaststage=0;
var showhints=true;
var steps=0;
var save_dstring='';
var some_changes=false;
var firsttime=true;
var some_saved=false;
var cordX;
var cordY;
var rcbname=["Row","Col","Box"];
var abety="ABCDEFGHJ";
var abetx="123456789";
var editmode=true;
var MAX_STRAT = kil_list.length;
var coordmode=1;
var validkiller = false;

var mask=[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var g   =[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var save=[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var orig=[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var last=[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var rcm =[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var cid =[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var map =[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var ccl =[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var csz =[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var show=[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var which_box=[[0,0,0,1,1,1,2,2,2],[0,0,0,1,1,1,2,2,2],[0,0,0,1,1,1,2,2,2],[3,3,3,4,4,4,5,5,5],[3,3,3,4,4,4,5,5,5],[3,3,3,4,4,4,5,5,5],[6,6,6,7,7,7,8,8,8],[6,6,6,7,7,7,8,8,8],[6,6,6,7,7,7,8,8,8]];
var offset=[0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4];
var sq_bck=['#ffffcc','#ccffcc','#ccccff','#ffcccc','#ffccff'];
var cnv, jg;

var g1 = ["212112111212112223213331443231221241134412231124133132322122212344411312111411312","171510202026111111171510202026262611171511111117161611171101060617091616111117170909090916111817160808040910161818161111112110161818181818142110080808181818142110","171510200026110000000000000000000011000011000017160000001101060000090016110017000900000900001800160800040010160000001100002100001800001800140000080000000000000000","693547128217386945458219736571428369342691587869735412784963251936152874125874693"];
var g2 = ["112212211133211211133133233221121121213323323312212233221332112331223112331123322","202018181617172222202222181616172222202222060909171010191906061306061109191303031309091114031311110817171414040426161617242415202026131311242415202026261311111515","200018001617002200002200000000000000000000060900001000190000001306001109001303000009000014030011000817000000040026160000240015200000130011000000000000000000000000","713654928426938175895127364642371589981265437357489216134796852569812743278543691"];
var g3 = ["112212121213312121232223331231112231232232212142233312144422212121213342121212244","131311111209120824181311111209120824181415151521212124181410101020202124181430301820200820241130301818180820241111112424240820241511061008081520241511061007071515","130011001209120824180011000000000000001415000021000000000010000020000000000030001800000820241100000000000000000000002400000000001511061008001500000000000007000000","385691724124738569679245183931452678247863915856917432512379846493186257768524391"];
var g4 = ["111222211211334411223331123144413323122214441213312221212233344331133114332222111","323232191919191616123232232309091616121223232312120910141010102011110910142121212007070714080603032021212114080617172626260909202007072626323209202017171717323232","320000190000001600120000230009000000000000000012000910141000002011000000002100000007000014080603000021000000000017002600000900200007000000320000000017000000000000","753641892289573614461829357817296543695734128342185976528967431974318265136452789"];
var g5 = ["112122221112133311232122444234411211122434221112334412333112312114442344133332344","242408181414141421242408181313132121101508181212121212101518180909191313101515181718191913101015171718180712141414050521120712131307070721121818133030303021121818","240008181400000021000000001300000000101500001200120000000018000900191300101500001718000000000000000000000712140000050021120000130007000000001800003000000000000000","981732546254691378763548291398154627126973854547286913815327469632419785479865132"];

var block1;
var sq_col=['black','#CC0000','blue','blue'];
var sq_siz=['8pt','14pt','14pt','14pt','8pt','18pt','18pt','18pt'];

jig=0;

/*---------------------------------------------------------------------*/
/* Draws the content of a square on the board							*/
/*---------------------------------------------------------------------*/
function set_square( x, y, val, setup )
{
	var t, s;

	// Get the table cell name out using the coordinates
	t=document.getElementById("a"+y+x);
	if( t.style.backgroundColor != sq_bck[map[y][x]-1] )
		t.style.backgroundColor = sq_bck[map[y][x]-1];

	if( (setup===0 && showhints) || setup > 0 )
		 t.innerHTML=val;	// Assign the new value to the cell
	else t.innerHTML='&nbsp;';	// Assign the new value to the cell
	t.style.color=sq_col[setup];
	t.style.fontSize=sq_siz[setup];
	if( setup == 3 ) t.style.backgroundColor = '#ff0000';
}
/*----------------------------------------------------------------------*/
/* Converts the bit array to a string of numbers for display			*/
/*----------------------------------------------------------------------*/
function lable_square( y, x, deduct )
{
	var lable, c, i, modfact=3, cel;
	lable='';
	c=0;
	if( (mask[y][x] & deduct) != deduct ) alert(mask[y][x] + " != " + deduct);
	mask[y][x] -= deduct;
	show[y][x] += deduct;

	for( i=0;i<9;i++ )
	{
		lable = '<table id="cl' + y + x + '" class="candtb" cellspacing=0 align=center>';
		for( i=0;i<9;i++ )
		{
			if( (i % modfact) == 0 )
				lable=lable + "<tr>";
			cel = '<td id="w' + y + x + i + '"';
			if( mask[y][x] & (1 << i) )	// i=0 to 8 so first shift is 0 bits
			{
				if( show[y][x] & (1 << i) )
					lable=lable + cel + ' class="fsh">' + (i+1) + '</td>';
				else
					lable=lable + cel + '>' + (i+1) + "</td>";
			}
			else
			{
				if( show[y][x] & (1 << i) )
					lable=lable + cel + ' class="fsh">' + (i+1) + '</td>';
				else lable=lable + cel + '>&nbsp;</td>';
			}
			if( (i % modfact) == 2 )
				lable=lable + "</tr>";
		}
		lable=lable + "</table>";
	}
	some_changes=true;
	set_square(x,y,lable,0);
}
function find_cage_size(y,x,target_col)
{
	var c=0;
	if( x<0 || x>8 || y<0 || y>8 ) return 0;
	if( map[y][x] != target_col ) return 0;
	if( csz[y][x] != 0 ) return 0;
	csz[y][x] = -1;
	c++;
	c+=find_cage_size(y,x-1,target_col);
	c+=find_cage_size(y,x+1,target_col);
	c+=find_cage_size(y-1,x,target_col);
	c+=find_cage_size(y+1,x,target_col);
	return c;
}
function set_cage_size(y,x,target_col,s)
{
	if( x<0 || x>8 || y<0 || y>8 ) return 0;
	if( map[y][x] != target_col ) return 0;
	if( csz[y][x] != -1 ) return 0;
	csz[y][x] = s;
	set_cage_size(y,x-1,target_col,s);
	set_cage_size(y,x+1,target_col,s);
	set_cage_size(y-1,x,target_col,s);
	set_cage_size(y+1,x,target_col,s);
}
function compute_cage_sizes()
{
	var i,j,s;
	for(j=0;j<9;j++)
		for(i=0;i<9;i++)
			if( csz[j][i]==0 ) {
				s = find_cage_size(j,i,map[j][i]);
				set_cage_size(j,i,map[j][i],s);
			}
}
function str2map( s )
{
	var x,y,c;
	for(y=0;y<9;y++) for(x=0;x<9;x++) {
		c = s.substr((y*9)+x,1);
		map[y][x]=c*1;
	}
}
function str2ccl( s )
{
	var x,y,c;
	for(y=0;y<9;y++) for(x=0;x<9;x++) {
		c = s.substr(((y*9)+x)*2,2)
		ccl[y][x]=c*1;
	}
}
function comb(t) {
	var y = t.id.charAt(1);
	var x = t.id.charAt(2);
	var s = '';
	if( t.innerHTML == '' ) return;
	if( csz[y][x]==1 ) {
		s = 'Single Cage';
	}
	else
	{
		for(var i=0;i<combinations.length;i++)
			if( combinations[i][0] == csz[y][x]
			 && combinations[i][2] == ccl[y][x] ) {
				 if( s!='' ) s+='<br>';
				 s += combinations[i][1];
			}
		if( s=='' ) s = 'Illegal cage clue and size!';
	}
	tooltip.show(s);
}
function load_from_fields()
{
	var i,j,t;

	var frm = document.forms.servsolv;

	str2ccl(frm.elements['cluemap'].value);
	str2map(frm.elements['colmap'].value);

	prevlaststage=laststage=stage=0;
	for(j=0;j<9;j++)
		for(i=0;i<9;i++)
		{
			g[j][i]=csz[j][i]=show[j][i]=cid[j][i]=0;
			orig[j][i]=mask[j][i]=511;
		}

	cordX=new Array(81);
	cordY=new Array(81);

	compute_cage_sizes();

	for(j=0;j<9;j++)
		for(i=0;i<9;i++)
		{
			if( csz[j][i]==1 ) { g[j][i] = ccl[j][i]; mask[j][i]=0; }
			if( g[j][i] > 0 )
				set_square(i,j,g[j][i],1);
			else
			{
				lable_square( j,i,0 );
			}
			t = document.getElementById("K"+ j + i);
			t.innerHTML=( ccl[j][i]>0 ) ? ccl[j][i] : '';
			t.style.backgroundColor = sq_bck[map[j][i]-1];

		}
	for(j=0;j<9;j++)
		for(i=0;i<8;i++)
		{
			t = document.getElementById("CR"+ j + i);
			t.style.backgroundColor = ( map[j][i]==map[j][i+1] ) ? sq_bck[map[j][i]-1] : '#000000';
		}
	for(j=0;j<8;j++)
		for(i=0;i<9;i++)
		{
			t = document.getElementById("CB"+ j + i);
			t.style.backgroundColor = ( map[j][i]==map[j+1][i] ) ? sq_bck[map[j][i]-1] : '#000000';
		}

	reset_yes_no( kil_list,6 );
	document.getElementById("takestep").onclick=take_step;
	document.getElementById("takestep").className = 'SButton';
/*	if( readCookie('scanraidkillercookie') )
	{
		document.getElementById("reload").className="SButton";
		some_saved=true;
	} */
	some_changes=false;
	firsttime=false;

	cnv = document.getElementById("myCanvas");
	jg = new jsGraphics(cnv);
	jg.clear();
}
function load_board()
{
	if( location.search.substr(0,6) == '?daily' ) {
		call_load_daily(location.search);
		return;
	}

	var colmap='', cluemap='';
	switch( document.forms.DataEntry.elements["Example"].selectedIndex ) {
	case 0 : cluemap = g1[2]; break;
	case 1 : cluemap = g2[2]; break;
	case 2 : cluemap = g3[2]; break;
	case 3 : cluemap = g4[2]; break;
	case 4 : cluemap = g5[2]; break;
	}
	switch( document.forms.DataEntry.elements["Example"].selectedIndex ) {
	case 0 : colmap = g1[0]; break;
	case 1 : colmap = g2[0]; break;
	case 2 : colmap = g3[0]; break;
	case 3 : colmap = g4[0]; break;
	case 4 : colmap = g5[0]; break;
	}
	if( colmap=='' ) return;
	frm = document.forms.servsolv;
	frm.elements['colmap'].value = colmap;
	frm.elements['cluemap'].value = cluemap;

	load_from_fields();
}
function load_print_board()
{
	var x,y,cage;
	var styleline,b='',internal='';
	var isSol = false;
	var inColour = (location.search=='?p=1');

	for(y=0;y<9;y++) for(x=0;x<9;x++) csz[y][x]=ccl[y][x]=rcm[y][x]=map[y][x]=0;

	if( opener === null
	 || opener.document === null
	 || opener.document.getElementById('servsolv') === null ) {
		alert('Cannot find the parent document - the Killer Solve page');
		return;
	}
	frm = opener.document.getElementById('servsolv');

	str2map(frm.elements['colmap'].value);
	str2ccl(frm.elements['cluemap'].value);

	document.getElementById("colmap").value = frm.elements['colmap'].value;
	document.getElementById("cluemap").value = frm.elements['cluemap'].value;


	for(y=0;y<9;y++)
	{
		b = b + "<tr>\n";
		for(x=0;x<9;x++)
		{
			styleline = '';
			if( x == 0 )
				styleline = styleline + "border-left: 4px solid #000000;";
			else if( x==3 || x==6 )
				styleline = styleline + "border-left: 2px solid #000000;";

			if( x == 8 )
				styleline = styleline + "border-right: 4px solid #000000;";
			else if( x==2 || x==5 )
				styleline = styleline + "border-right: 2px solid #000000;";

			if( y == 0 )
				styleline = styleline + "border-top: 4px solid #000000;";
			else if( y==3 || y==6 )
				styleline = styleline + "border-top: 2px solid #000000;";

			if( y == 8 )
				styleline = styleline + "border-bottom: 4px solid #000000;";
			else if( y==2 || y==5 )
				styleline = styleline + "border-bottom: 2px solid #000000;";

			if( inColour ) styleline = styleline + "background-color:" + sq_bck[map[y][x]-1] + ";";

			internal = "\n<table border=0 width=100% height=100%><tr><td style=\""
			cage = 0;
			if( x == 0 )
			{	internal = internal + "border-left: 1px dashed #000000;"; cage++; }
			else if( map[y][x] != map[y][x-1] )
			{	internal = internal + "border-left: 1px dashed #000000;"; cage++; }

			if( x == 8 )
			{	internal = internal + "border-right: 1px dashed #000000;"; cage++; }
			else if( map[y][x] != map[y][x+1] )
			{	internal = internal + "border-right: 1px dashed #000000;"; cage++; }

			if( y == 0 )
			{	internal = internal + "border-top: 1px dashed #000000;"; cage++; }
			else if( map[y][x] != map[y-1][x] )
			{	internal = internal + "border-top: 1px dashed #000000;"; cage++; }

			if( y == 8 )
			{	internal = internal + "border-bottom: 1px dashed #000000;"; cage++; }
			else if( map[y][x] != map[y+1][x] )
			{	internal = internal + "border-bottom: 1px dashed #000000;"; cage++; }


			if( isSol || cage==4 )
				internal = internal + "\" class=\"InnerSol\"";
			else
				internal = internal + "\" class=\"InnerK\"";


			if( isSol )
				internal = internal + ">" & g[y][x] & "</td></tr></table>\n";
			else
			{
				if( ccl[y][x] == 0 )
					internal = internal + ">&nbsp</td></tr></table>\n";
				else
					internal = internal + ">" + ccl[y][x] + "</td></tr></table>\n";
			}
			b += "<td class=\"InnerTDone\" style=\"" + styleline + "\">" + internal + "</td>\n";
		}
		b = b + "</tr>\n";
	}
	document.getElementById("boardgoeshere").innerHTML = "<table border=0 cellpadding=0 cellspacing=0>" + b + "</table>";
}
function fill_transfer_vars(cur_strat)
{
	var x,y,s='',st='',frm;
	var cluemap='',colmap='';

	for(y=0;y<9;y++)		// Redraw the board to clear any user highlighting
		for(x=0;x<9;x++)
		{
			cluemap = cluemap + padzero(ccl[y][x]);
			colmap = colmap + map[y][x];
			if( g[y][x] )
				 s = s + ',' + (1 << (g[y][x]-1));
			else s = s + ',' + mask[y][x];
		}
	for( x=5;x<kil_list.length;x++) if( document.getElementById("CB"+kil_list[x]).checked===false )
	{
		st+=kil_list[x];
	}

	frm = document.forms.servsolv;
	frm.elements['coordmode'].value = coordmode;
	frm.elements['strat'].value = cur_strat;
	frm.elements['stratmask'].value = st;
	frm.elements['colmap'].value = colmap;
	frm.elements['cluemap'].value = cluemap;
	frm.elements['board'].value = s.substr(1,s.length-1);
}
function import_killer(isNew)
{
	var dstring;
	var actualstr='';
	var c,i,j,s,t;

	if( isNew ) fill_transfer_vars(0);


	var SGW=window.open('KillerSudokuDesigner.htm?n=' + isNew,'_designer','resizable=no,scrollbars=no,screenX=200,screenY=200,width=710,height=490');
	if (!SGW.opener) SGW.opener=self;
	jg.clear();
}
function save_board()
{
	fill_transfer_vars(0);

	document.getElementById("reload").className="SButton";
	some_saved=true;

	var date = new Date();
	date.setTime(date.getTime()+(30*24*60*60*1000));

	var frm = document.forms.servsolv;

	document.cookie ='scanraidkillercookiea=' + frm.elements['colmap'].value + '; expires=' + date.toGMTString() + '; path=/';
	document.cookie ='scanraidkillercookieb=' + frm.elements['cluemap'].value + '; expires=' + date.toGMTString() + '; path=/';
	document.cookie ='scanraidkillercookiec=' + frm.elements['board'].value + '; expires=' + date.toGMTString() + '; path=/';

	alert("Current Board Saved (as a cookie)");
}
function reload_board()
{
	var x = readCookie('scanraidkillercookiea');
	if (x)
	{
		var frm = document.forms.servsolv;
		frm.elements['colmap'].value = x;
		frm.elements['cluemap'].value = readCookie('scanraidkillercookieb');
		frm.elements['board'].value = readCookie('scanraidkillercookiec');
		load_from_fields();
	}
	else
	{
		alert("No saved board found");
	}
	jg.clear();
}
function call_load_daily(params)
{
	window.frames["ifrm"].location.href = "/DailyKillerLoad.asp" + params;
}
function check_for_single()
{
	var i,x,y,done=0;
	for( y=0;y<9;y++ )
		for( x=0;x<9;x++ )	// for every square on the board
		{
			for(i=0;i<9;i++)	// if the bit array contains only one bit
				if( mask[y][x] == (1 << i) )
				{
					g[y][x]=i+1;		// we have a single number and a solution
					mask[y][x]=0;		// ...wipe the mask
					set_square(x,y,g[y][x],2);	// and draw the number
					done++;
			//		some_changes=true;
				}
		}
	return done;
}
function check_for_one_single( y,x )
{
	var n;
	for(n=0;n<9;n++)
		if( mask[y][x] == (1 << n) )
		{
			g[y][x]=n+1;		// we have a single number and a solution
			mask[y][x]=0;		// ...wipe the mask
			set_square(x,y,g[y][x],2);	// and draw the number
			some_changes=true;
			return true;
		}
	return false;
}

function show_candidates()
{
	var changes;
	var x,y,i,a,b,j,zz,yy,n;

	/*----------------------------------------------------------------------*/
	/* check the rows and columns of each square							*/
	/* and to remove any bits for numbers that are found. Ie,we start with	*/
	/* 123456789 and zero any numbers in the array in each row/column		*/
	/*----------------------------------------------------------------------*/
	for( y=0;y<9;y++ )
		for( x=0;x<9;x++ )	// for every square on the board
			if( !g[y][x] )	// if it is an unknown square...
			{
				changes=false;
				for( i=0;i<9;i++) // for the size of the board
				{
					if( i != x && g[y][i] > 0 ) // check values in row
						if( (mask[y][x] & (1 << (g[y][i]-1))) )
						{
							mask[y][x] -= (1 << (g[y][i]-1));	// remove that bit
							changes=true;
						}
					if( i != y && g[i][x] > 0 ) // check values in column
						if( (mask[y][x] & (1 << (g[i][x]-1))) )
						{
							mask[y][x] -= (1 << (g[i][x]-1));	// remove that bit
							changes=true;
						}
				}
				if( changes ) lable_square( y,x,0 );
			}

	/*----------------------------------------------------------------------*/
	/* check number in each box - which MUST 								*/
	/* contain only 1 to 9. If we have known numbers then they must be		*/
	/* removed from the choices in the bit array found in test_row_col		*/
	/*----------------------------------------------------------------------*/
	for(a=0;a<9;a+=3)		// for each box (9 of them 3 by 3 each)
		for(b=0;b<9;b+=3)
			for(i=a;i<a+3;i++)		// which means looking in each 3 by 3 box
				for(j=b;j<b+3;j++)
					if( g[i][j]>0 )
						for(zz=a;zz<a+3;zz++)	// ..check every other cell
							for(yy=b;yy<b+3;yy++)
							{
								n=g[i][j]-1;
								if( mask[zz][yy] & (1 << n) )
								{
									mask[zz][yy] -= (1 << n);
									lable_square( zz,yy,0);
								}
							}

}
function singles_in_row_col( )
{
	var y,x,n,cr,cc,k;

	for(y=0;y<9;y++)
		for(x=0;x<9;x++)	// for every square on the board...
			if( !g[y][x] )	// if it is an unknown square...
			{
				for(n=0;n<9 && !g[y][x];n++) if( mask[y][x] & (1 << n) ) // For all numbers,if the number is a possible
				{
					for( cc=cr=k=0;k<9;k++)
					{
						if( !g[y][k] && (mask[y][k] & (1 << n)) ) cr++;  // check the row
						if( !g[k][x] && (mask[k][x] & (1 << n)) ) cc++;  // check the column
					}
					if( cr==1 || cc==1 )
					{
						if( cr==1 ) strat_add("SINGLE: " + cordit(y,x) + " set to " + abetx.charAt(n) + ", unique in Row<br>");
						if( cc==1 ) strat_add("SINGLE: " + cordit(y,x) + " set to " + abetx.charAt(n) + ", unique in Column<br>");
						show[y][x]=(1 << n);
						lable_square(y,x,0);
						mask[y][x]=(1 << n);
					}
				}
			}
}

function singles_in_box( )
{
	var ax=new Array(12);
	var ay=new Array(12);
	var bb,cc,n,c,i,j;

	/*----------------------------------------------------------------------*/
	/* Point of check_box is that now we have a whole board set up with	*/
	/* a bit array for each square. Lets check that bit array in each		*/
	/* box to see if any of the nine squares have numbers which only occur	*/
	/* once. If so we have a NEW solution for that square.					*/
	/*----------------------------------------------------------------------*/

	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
			for(n=0;n<9;n++)	// .. check each number
			{
				c=0;
				for(i=bb;i<bb+3 && c<9;i++)	// which means looking in each 3 by 3 box
					for(j=cc;j<cc+3 && c<9;j++)
					{
						if( g[i][j]===0 && (mask[i][j] & (1 << n)) )
						{
							ax[c]=j;	// Store the coordinates
							ay[c++]=i; // and count how many times this happens
						}
						else if( g[i][j]==n+1 ) c=9;	// if that number is known we can ignore it
					}
				if( c == 1 )	// If we only have one occurance...
				{
					strat_add("SINGLE: " + cordit(ay[0],ax[0]) + " set to " + abetx.charAt(n) + ", unique in Box<br>");
					show[ay[0]][ax[0]]=(1 << n);
					lable_square(ay[0],ax[0],0);
					mask[ay[0]][ax[0]]=(1 << n);
					some_changes=true;
				}
			}
}

/*-------------------------------------------------------------------------*/
/* Purpose of hidden_pairs is to look for pairs of numbers, eg 3-7 and 3-7 */
/* mixed up in the same two squares with other numbers - which can be      */
/* eliminated. 															   */
/*-------------------------------------------------------------------------*/
var gotsome;
function apply_new_mask( desc,direction,unit,y,x,h )
{
	strat_add(desc + mask2str(h) + direction + abetx.charAt(unit) + ": " + cordit(y,x) + " - " + mask2str(mask[y][x]) + " -> " + mask2str(mask[y][x] & h) + "<br>");
	show[y][x] = mask[y][x] - (mask[y][x] & h);
	mask[y][x] &= h;
	lable_square( y,x,0 );
	gotsome = true;
}
function hidden_pairs()
{
	var x,y,n,m,i,bb,cc,box=0,h;
	var pos=new Array(9);

	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
		{
			for(n=0;n<9;n++)	// .. check each number
			{
				pos[n]=i=0;
				for(y=bb;y<bb+3;y++)	// which means looking in each 3 by 3 box
					for(x=cc;x<cc+3;x++,i++)
						if( !g[y][x] && (mask[y][x] & (1 << n)) )
							pos[n] += (1 << i);  // ith position of n
			}
			for(n=0;n<8;n++)
				for(m=n+1;m<9;m++)
					if( bit_count(pos[n])==2 && pos[n] == pos[m] )
					{
						i=0;
						for(y=bb;y<bb+3;y++)	// which means looking in each 3 by 3 box
							for(x=cc;x<cc+3;x++,i++)
								if( pos[n] & (1 << i) && bit_count(mask[y][x]) > 2 )
								{
									h=(1 << n) + (1 << m);
									apply_new_mask( "HIDDEN PAIR: ", " in box ", box,y,x,h );
								}
					}
			box++;
		}

	/*-------------------------------------------------------------------------*/
	/* Checking in the box will get most hidden pairs, but some are aligned    */
	/* over two box but still on the same row or columns				       */
	/*-------------------------------------------------------------------------*/
	for(y=0;y<9;y++)
	{
		for(n=0;n<9;n++)	// .. check each number
			for(pos[n]=x=0;x<9;x++)	// which means looking in each row/col
				if( !g[y][x] && (mask[y][x] & (1 << n)) )
					pos[n] += (1 << x);  // ith position of n

		for(n=0;n<8;n++)
			for(m=n+1;m<9;m++)
				if( bit_count(pos[n])==2 && pos[n] == pos[m] )
					for(x=0;x<9;x++)	// which means looking in each row/col
						if( pos[n] & (1 << x) && bit_count(mask[y][x]) > 2 )
						{
							h=(1 << n) + (1 << m);
							apply_new_mask( "HIDDEN PAIR: ", " in row ",y,y,x,h );
						}
	}
	for(x=0;x<9;x++)
	{
		for(n=0;n<9;n++)	// .. check each number
			for(pos[n]=y=0;y<9;y++)	// which means looking in each row/col
				if( !g[y][x] && (mask[y][x] & (1 << n)) )
					pos[n] += (1 << y);  // ith position of n

		for(n=0;n<8;n++)
			for(m=n+1;m<9;m++)
				if( bit_count(pos[n])==2 && pos[n] == pos[m] )
					for(y=0;y<9;y++)	// which means looking in each row/col
						if( pos[n] & (1 << y) && bit_count(mask[y][x]) > 2 )
						{
							h=(1 << n) + (1 << m);
							apply_new_mask( "HIDDEN PAIR: ", " in col ",x,y,x,h );
						}
	}
}
function hidden_triples()
{
	var x,y,n,m,p,i,bb,cc,a,b,c,h,box=0;
	var pos=new Array(9);

	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
		{
			for(n=0;n<9;n++)	// .. check each number
			{
				pos[n]=i=0;
				for(y=bb;y<bb+3;y++)	// which means looking in each 3 by 3 box
					for(x=cc;x<cc+3;x++,i++)
						if( !g[y][x] && (mask[y][x] & (1 << n)) )
							pos[n] += (1 << i);  // ith position of n
			}
			for(n=0;n<7;n++)
				for(m=n+1;m<8;m++)
					for(p=m+1;p<9;p++)
						if( bit_count(pos[n] | pos[m] | pos[p]) == 3 && pos[n] && pos[m] && pos[p] )
						{
							i=0;
							for(y=bb;y<bb+3;y++)	// which means looking in each 3 by 3 box
								for(x=cc;x<cc+3;x++,i++)
								{
									a=pos[n] & (1 << i);
									b=pos[m] & (1 << i);
									c=pos[p] & (1 << i);
									if( (a || b || c)
									  && bit_count(mask[y][x]) > ((a>0)+(b>0)+(c>0)) )
									{
										h=(1 << n) + (1 << m) + (1 << p);
										apply_new_mask( "HIDDEN TRIPLE: ", " in box ",box,y,x,h );
									}
								}
						}
			box++;
		}

	/*-------------------------------------------------------------------------*/
	/* Checking in the box will get most hidden pairs, but some are aligned    */
	/* over two box but still on the same row or columns				       */
	/*-------------------------------------------------------------------------*/
	for(y=0;y<9;y++)
	{
		for(n=0;n<9;n++)	// .. check each number
			for(pos[n]=x=0;x<9;x++)	// which means looking in each row/col
				if( !g[y][x] && (mask[y][x] & (1 << n)) )
					pos[n] += (1 << x);  // ith position of n

		for(n=0;n<7;n++)
			for(m=n+1;m<8;m++)
				for(p=m+1;p<9;p++)
					if( bit_count(pos[n] | pos[m] | pos[p]) == 3 && pos[n] && pos[m] && pos[p] )
					{
						for(x=0;x<9;x++)
						{
							a=pos[n] & (1 << x);
							b=pos[m] & (1 << x);
							c=pos[p] & (1 << x);
						//	if( y==4 ) alert( x + ' abc: ' + a + ' ' + b + ' ' + c + ' nmp: ' + n + ' ' + m + ' ' + p );
							if( (a || b || c)
							  && bit_count(mask[y][x]) > ((a>0)+(b>0)+(c>0)) )
							{
								h=(1 << n) + (1 << m) + (1 << p);
								apply_new_mask( "HIDDEN TRIPLE: ", " in row ",y,y,x,h );
							}
						}
					}
	}
	for(x=0;x<9;x++)
	{
		for(n=0;n<9;n++)	// .. check each number
			for(pos[n]=y=0;y<9;y++)	// which means looking in each row/col
				if( !g[y][x] && (mask[y][x] & (1 << n)) )
					pos[n] += (1 << y);  // ith position of n

		for(n=0;n<7;n++)
			for(m=n+1;m<8;m++)
				for(p=m+1;p<9;p++)
					if( bit_count(pos[n] | pos[m] | pos[p]) == 3 && pos[n] && pos[m] && pos[p] )
					{
						for(y=0;y<9;y++)
						{
							a=pos[n] & (1 << y);
							b=pos[m] & (1 << y);
							c=pos[p] & (1 << y);
							if( (a || b || c)
							  && bit_count(mask[y][x]) > ((a>0)+(b>0)+(c>0)) )
							{
								h=(1 << n) + (1 << m) + (1 << p);
								apply_new_mask( "HIDDEN TRIPLE: ", " in col ",x,y,x,h );
							}
						}
					}
	}
}
function hidden_quads()
{
	var x,y,n,m,p,q,i,bb,cc,a,b,c,d,h,box=0;
	var pos=new Array(9);

	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
		{
			for(n=0;n<9;n++)	// .. check each number
			{
				pos[n]=i=0;
				for(y=bb;y<bb+3;y++)	// which means looking in each 3 by 3 box
					for(x=cc;x<cc+3;x++,i++)
						if( !g[y][x] && (mask[y][x] & (1 << n)) )
							pos[n] += (1 << i);  // ith position of n
			}
			for(n=0;n<6;n++)
				for(m=n+1;m<7;m++)
					for(p=m+1;p<8;p++)
						for(q=p+1;q<9;q++)
							if( bit_count(pos[n] | pos[m] | pos[p] | pos[q]) == 4 && pos[n] && pos[m] && pos[p] && pos[q] )
							{
								i=0;
								for(y=bb;y<bb+3;y++)	// which means looking in each 3 by 3 box
									for(x=cc;x<cc+3;x++,i++)
									{
										a=pos[n] & (1 << i);
										b=pos[m] & (1 << i);
										c=pos[p] & (1 << i);
										d=pos[q] & (1 << i);
										if( (a || b || c || d)
										  && bit_count(mask[y][x]) > ((a>0)+(b>0)+(c>0)+(d>0)) )
										{
											h=(1 << n) + (1 << m) + (1 << p) + (1 << q);
											apply_new_mask( "HIDDEN QUAD: ", " in box ",box,y,x,h );
										}
									}
							}
			box++;
		}

	/*-------------------------------------------------------------------------*/
	/* Checking in the box will get most hidden pairs, but some are aligned    */
	/* over two box but still on the same row or columns				       */
	/*-------------------------------------------------------------------------*/
	for(y=0;y<9;y++)
	{

		for(n=0;n<9;n++)	// .. check each number
			for(pos[n]=x=0;x<9;x++)	// which means looking in each row/col
				if( !g[y][x] && (mask[y][x] & (1 << n)) )
					pos[n] += (1 << x);  // ith position of n

		for(n=0;n<6;n++)
			for(m=n+1;m<7;m++)
				for(p=m+1;p<8;p++)
					for(q=p+1;q<9;q++)
						if( bit_count(pos[n] | pos[m] | pos[p] | pos[q]) == 4 && pos[n] && pos[m] && pos[p] && pos[q] )
						{
							for(x=0;x<9;x++)
							{
								a=pos[n] & (1 << x);
								b=pos[m] & (1 << x);
								c=pos[p] & (1 << x);
								d=pos[q] & (1 << x);
								if( (a || b || c || d)
								  && bit_count(mask[y][x]) > ((a>0)+(b>0)+(c>0)+(d>0)) )
								{
									h=(1 << n) + (1 << m) + (1 << p) + (1 << q);
									apply_new_mask( "HIDDEN QUAD: ", " in row ",y,y,x,h );
								}
							}
						}
	}
	for(x=0;x<9;x++)
	{
		for(n=0;n<9;n++)	// .. check each number
			for(pos[n]=y=0;y<9;y++)	// which means looking in each row/col
				if( !g[y][x] && (mask[y][x] & (1 << n)) )
					pos[n] += (1 << y);  // ith position of n

		for(n=0;n<6;n++)
			for(m=n+1;m<7;m++)
				for(p=m+1;p<8;p++)
					for(q=p+1;q<9;q++)
						if( bit_count(pos[n] | pos[m] | pos[p] | pos[q]) == 3 && pos[n] && pos[m] && pos[p] && pos[q] )
						{
							for(y=0;y<9;y++)
							{
								a=pos[n] & (1 << y);
								b=pos[m] & (1 << y);
								c=pos[p] & (1 << y);
								d=pos[q] & (1 << y);
								if( (a || b || c)
								  && bit_count(mask[y][x]) > ((a>0)+(b>0)+(c>0)+(d>0)) )
								  {
									h=(1 << n) + (1 << m) + (1 << p) + (1 << q);
								  	apply_new_mask( "HIDDEN QUAD: ", " in col ",x,y,x,h );
								  }
							}
						}
	}
}

/*----------------------------------------------------------------------*/
/* MAIN PAIR TEST														*/
/*----------------------------------------------------------------------*/
function main_pair_test()
{
	var bb,cc,n,m,i,j,k,a,b,y,x1,x2,x3,h,cn;
	var mbox=new Array(9);
	var cnt=new Array(9);

	/*----------------------------------------------------------------------*/
	/* Purpose of this pair test is to look for pairs of numbers,			*/
	/* eg 3-7 and 3-7 in the same box. Since both numbers MUST be on both   */
	/* cells they can be eliminated from the rest of the box				*/
	/*----------------------------------------------------------------------*/
	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
		{
			k=0;
			for(i=bb;i<bb+3;i++)	// put the box in a 1D array for ease of use
				for(j=cc;j<cc+3;j++)
				{
					mbox[k]=mask[i][j];
					cnt[k]=bit_count(mask[i][j]);
					cordX[k]=j;
					cordY[k++]=i;
				}
			for(a=0;a<8;a++)	// .. check each pair in the 1D box array
				for(b=a+1;b<9;b++)
				{
					if( cnt[a]==2 && mbox[a] == mbox[b] )  // If same 2 numbers in the same 2 squares
					{
						for(m=0;m<9;m++)	// for all squares in the box
							for(n=0;n<9;n++) // for all numbers
							{
								if( m!=a && m!=b && (mbox[a] & (1 << n)) && (mbox[m] & (1 << n)) )
								{
								//	alert("here n=" + n + " m=" + m + " a=" + a + " mbox[a]=" + mbox[a] + " cnt[m]=" + cnt[m]);
									cn=abetx.charAt(n);
									strat_add("NAKED PAIR (Box): " + cordit(cordY[a],cordX[a]) + "/" + cordit(cordY[b],cordX[b]) + " removes " + cn + " from " + cordit(cordY[m],cordX[m]) + "<br>");
									mbox[m] -= (1 << n); // remove that number
									lable_square( cordY[m],cordX[m],(1 << n) );
								}
							}
					}
				}
		}

	/*----------------------------------------------------------------------*/
	/* Purpose of pair_test2 is to look for pairs of numbers, eg 3-7 and 3-7 */
	/* in the same row/col. Since both numbers MUST be on both cells they 	*/
	/* can be elininated from the rest of the ROW or COLUMN they are		*/
	/* aligned with. How cool is that?										*/
	/*----------------------------------------------------------------------*/

	for(y=0;y<9;y++)
		for(x1=0;x1<8;x1++)	// For every square...
			for(x2=x1+1;x2<9;x2++)
			{
				// This block checks the ROW the pair resides in...
				if( bit_count(mask[y][x1])==2 && mask[y][x1] == mask[y][x2] )
					for(i=0;i<9;i++)
					{
						h=(mask[y][i] & mask[y][x1]);
						if( i!=x1 && i!=x2 && !g[y][i] && h )
						{
							strat_add("NAKED PAIR (Row): " + cordit(y,x1) + "/" + cordit(y,x2) + " removes " + mask2str(mask[y][i] & h) + " from " + cordit(y,i) + "<br>");
							lable_square( y,i,h );
						}
					}

				// This block checks the COLUMN the pair resides in...
				if( bit_count(mask[x1][y])==2 && mask[x1][y] == mask[x2][y] )
					for(i=0;i<9;i++)
					{
						h=(mask[i][y] & mask[x1][y]);
						if( i!=x1 && i!=x2 && !g[i][y] && h )
						{
							strat_add("NAKED PAIR (Col): " + cordit(x1,y) + "/" + cordit(x2,y) + " removes " + mask2str(mask[i][y] & h) + " from " + cordit(i,y) + "<br>");
							lable_square( i,y,h );
						}
					}
			}
}

function main_triple_test()
{
	var bb,cc,i,j,k,y,x1,x2,x3,h,off;
	var mbox=new Array(9);
	var cnt=new Array(9);

	// LOOK FOR TRIPLES
	for(y=0;y<9;y++)
		for(x1=0;x1<7;x1++)	// For each triple
			for(x2=x1+1;x2<8;x2++)
				for(x3=x2+1;x3<9;x3++)
				{
					// This block checks the ROW the triple resides in...
					if( bit_count(mask[y][x1])>1 && bit_count(mask[y][x2])>1 && bit_count(mask[y][x3])>1 )
					{
						h=mask[y][x1] | mask[y][x2] | mask[y][x3];
						if( bit_count(h)==3 )
							for(i=0;i<9;i++)
							{
								off=(mask[y][i] & h);
								if( i!=x1 && i!=x2 && i!=x3 && off )
								{
									strat_add("NAKED TRIPLE (Row): " + cordit(y,x1) + "/" + cordit(y,x2) + "/" + cordit(y,x3) + " removes " + mask2str(off) + " from " + cordit(y,i) + "<br>");
									lable_square( y,i,off );
								}
							}
					}
					// This block checks the COLUMN the triple resides in...
					if( bit_count(mask[x1][y])>1 && bit_count(mask[x2][y])>1 && bit_count(mask[x3][y])>1 )
					{
						h=mask[x1][y] | mask[x2][y] | mask[x3][y];
						if( bit_count(h)==3 )
							for(i=0;i<9;i++)
							{
								off=(mask[i][y] & h);
								if( i!=x1 && i!=x2 && i!=x3 && off )
								{
									strat_add("NAKED TRIPLE (Col): " + cordit(x1,y) + "/" + cordit(x2,y) + "/" + cordit(x3,y) + " removes " + mask2str(off) + " from " + cordit(i,y) + "<br>");
									lable_square( i,y,off );
								}
							}
					}
				}
	/*----------------------------------------------------------------------*/
	// This block checks the BOX the triple resides in...
	/*----------------------------------------------------------------------*/
	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
		{
			k=0;
			for(i=bb;i<bb+3;i++)	// put the box in a 1D array for ease of use
				for(j=cc;j<cc+3;j++)
				{
					mbox[k]=mask[i][j];
					cnt[k]=bit_count(mask[i][j]);
					cordX[k]=j;
					cordY[k++]=i;
				}
			for(x1=0;x1<7;x1++)	// For each triple
				for(x2=x1+1;x2<8;x2++)
					for(x3=x2+1;x3<9;x3++)
					{
						if( cnt[x1]>1 && cnt[x2]>1 && cnt[x3]>1 )
						{
							h=mbox[x1] | mbox[x2] | mbox[x3];
							if( bit_count(h)==3 )
								for(i=0;i<9;i++)
								{
									off=(mbox[i] & h);
									if( i!=x1 && i!=x2 && i!=x3 && off )
									{
										strat_add("NAKED TRIPLE (Box): " + cordit(cordY[x1],cordX[x1]) + "/" + cordit(cordY[x2],cordX[x2]) + "/" + cordit(cordY[x3],cordX[x3]) + " removes " + mask2str(off) + " from " + cordit(cordY[i],cordX[i]) + "<br>");
										mbox[i] -= off; // remove that number
										lable_square( cordY[i],cordX[i],off ); // remove that number
									}
								}
						}
					}
		}
}
function naked_quads()
{
	var bb,cc,i,j,k,y,x1,x2,x3,x4,h,off;
	var mbox=new Array(9);
	var cnt=new Array(9);

	// LOOK FOR QUADS
	for(y=0;y<9;y++)
		for(x1=0;x1<6;x1++)	// For each quad
			for(x2=x1+1;x2<7;x2++)
				for(x3=x2+1;x3<8;x3++)
					for(x4=x3+1;x4<9;x4++)
					{
						// This block checks the ROW the quad resides in...
						if( bit_count(mask[y][x1])>1 && bit_count(mask[y][x2])>1 && bit_count(mask[y][x3])>1 && bit_count(mask[y][x4])>1 )
						{
							h=mask[y][x1] | mask[y][x2] | mask[y][x3] | mask[y][x4];
							if( bit_count(h)==4 )
								for(i=0;i<9;i++)
								{
									off=(mask[y][i] & h);
									if( i!=x1 && i!=x2 && i!=x3 && i!=x4 && off )
									{
										strat_add("NAKED QUAD (Row): " + cordit(y,x1) + "/" + cordit(y,x2) + "/" + cordit(y,x3) + "/" + cordit(y,x4) + " removes " + mask2str(off) + " from " + cordit(y,i) + "<br>");
										lable_square( y,i,off );
									}
								}
						}
						// This block checks the COLUMN the triple resides in...
						if( bit_count(mask[x1][y])>1 && bit_count(mask[x2][y])>1 && bit_count(mask[x3][y])>1 && bit_count(mask[x4][y])>1 )
						{
							h=mask[x1][y] | mask[x2][y] | mask[x3][y] | mask[x4][y];
							if( bit_count(h)==4 )
								for(i=0;i<9;i++)
								{
									off=(mask[i][y] & h);
									if( i!=x1 && i!=x2 && i!=x3 && i!=x4 && off )
									{
										strat_add("NAKED QUAD (Col): " + cordit(x1,y) + "/" + cordit(x2,y) + "/" + cordit(x3,y) + "/" + cordit(x4,y) + " removes " + mask2str(off) + " from " + cordit(i,y) + "<br>");
										lable_square( i,y,off );
									}
								}
						}
					}
	/*----------------------------------------------------------------------*/
	// This block checks the BOX the triple resides in...
	/*----------------------------------------------------------------------*/
	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
		{
			k=0;
			for(i=bb;i<bb+3;i++)	// put the box in a 1D array for ease of use
				for(j=cc;j<cc+3;j++)
				{
					mbox[k]=mask[i][j];
					cnt[k]=bit_count(mask[i][j]);
					cordX[k]=j;
					cordY[k++]=i;
				}
			for(x1=0;x1<6;x1++)	// For each triple
				for(x2=x1+1;x2<7;x2++)
					for(x3=x2+1;x3<8;x3++)
						for(x4=x3+1;x4<9;x4++)
						{
							if( cnt[x1]>1 && cnt[x2]>1 && cnt[x3]>1 && cnt[x4]>1 )
							{
								h=mbox[x1] | mbox[x2] | mbox[x3] | mbox[x4];
								if( bit_count(h)==4 )
									for(i=0;i<9;i++)
									{
										off=(mbox[i] & h);
										if( i!=x1 && i!=x2 && i!=x3 && i!=x4 && off )
										{
											strat_add("NAKED QUAD (Box): " + cordit(cordY[x1],cordX[x1]) + "/" + cordit(cordY[x2],cordX[x2]) + "/" + cordit(cordY[x3],cordX[x3])  + "/" + cordit(cordY[x4],cordX[x4]) + " removes " + mask2str(off) + " from " + cordit(cordY[i],cordX[i]) + "<br>");
											mbox[i] -= off; // remove that number
											lable_square( cordY[i],cordX[i],off ); // remove that number
										}
									}
							}
						}
		}
}
/*----------------------------------------------------------------------*/
/* Function to check for conflicts with the rules						*/
/*----------------------------------------------------------------------*/
function sanity_check()
{
	var bb,cc,n,i,j,c,x,y,zz,yy,failed=0;

	for( x in g )
		for( y in g[x] )	// for every square on the board...
			if( g[x][y]===0 && mask[x][y]===0 )	// if it is an known square...
			{
				set_square(y,x,g[x][y],3);	// hightlight conflicting squares
				return true;
			}

	for( x in g )
		for( y in g[x] )	// for every square on the board...
			if( g[x][y] )	// if it is an known square...
			{
				for( i=0;i<9;i++ ) // check values in row
				{
					if( i != y && g[x][i] == g[x][y] )
					{
						set_square(i,x,g[x][i],3);	// hightlight conflicting squares
						set_square(y,x,g[x][y],3);	// hightlight conflicting squares
						failed+=2;
					}
					if( i != x && g[i][y] == g[x][y] )
					{
						set_square(y,i,g[i][y],3);	// hightlight conflicting squares
						set_square(y,x,g[x][y],3);	// hightlight conflicting squares
						failed+=2;
					}
				}
			}


	for(bb=0;bb<9;bb+=3)			// for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
			for(i=bb;i<bb+3;i++)		// which means looking in each 3 by 3 box
				for(j=cc;j<cc+3;j++)
					if( g[i][j] ) // if the square is known ...
						for(zz=bb;zz<bb+3;zz++)	// ..check every other cell
							for(yy=cc;yy<cc+3;yy++)
								if( !(zz==i && yy==j) && g[zz][yy] == g[i][j] )	// .. if the number is known
								{
									set_square(yy,zz,g[zz][yy],3);	// hightlight conflicting squares
									set_square(j,i,g[i][j],3);	// hightlight conflicting squares
									failed+=2;
								}
	return failed;
}
/* Function to reset the board to its normal blue background */
function blue_board()
{
	var x,y,done=0;
	for(y=0;y<9;y++)		// Redraw the board to clear any user highlighting
		for(x=0;x<9;x++)
		{
			if( some_changes===false ) t=document.getElementById("a"+y+x);
			if( some_changes===false ) t.style.backgroundColor=sq_bck[map[y][x]-1];
			if( g[y][x]>0 ) done++;
		}
	return done;
}
function post_to_form(cur_strat) {
	var frm = document.forms.servsolv;
	fill_transfer_vars(cur_strat);
	frm.submit();
}
/*----------------------------------------------------------------------*/
/* Function to run the steps above in one go. Resets the board colors	*/
/*----------------------------------------------------------------------*/
function take_step()
{
	var i,j,done=0,t,found=0,x,y;

	done=blue_board();
//	if( stage>0 && done > 0 && !block_board() ) return;

	if( done === 81 )	// If the number of solutions=81, we're all done
	{
		if( sanity_check()>0 )
			 alert("Opps. Not a valid Sudoku solution");
		else alert("Thats it! All done");
	}
	else
	{
		if( stage === 0 ) some_changes=false;

		if( stage!==0 && !some_changes )
		{
			for( x in g )
				for( y in g[x] ) last[x][y]=mask[x][y];
			prevlaststage=stage;
			laststage=stage;
		}
		if( some_changes ) stage=0;
		else
		{
			if( stage==MAX_STRAT ) stage=1
			else if( stage<11 ) stage++;
			else stage=12;
		}

		if( stage == 0 )
		{
			found=check_for_single();
			document.getElementById("R0").innerHTML=(found)? '<font color=#00ff00><b>' + found + '</b></font>' : '<font color=#ff0000><b>0</b></font>';
			some_changes=false;
		}
		else
		{
		/*	if( !document.ifrm )
				 doc = document.getElementById("ifrm").contentDocument;
			else doc = document.ifrm.document;
			doc.body.innerHTML='';
			doc.body.style.backgroundColor='#ddeeff';
			doc.body.style.color='#000000';
		*/
			if( stage == 1 ) { reset_yes_no( kil_list,6 ); jg.clear(); clear_on_off_color(); }

			if( stage > 6 )
			{
				document.getElementById("takestep").onclick=null;
				document.getElementById("takestep").className = 'GButton';
			}
			if( sanity_check() )
				alert("Oops - you've got an error on the board");
			clear_results = true;

			if( stage == 1  ) show_candidates();
			if( stage == 2  ) singles_in_row_col();
			if( stage == 3  ) singles_in_box();
			if( stage == 4  ) { main_pair_test(); main_triple_test(); }
			if( stage == 5  ) { hidden_pairs(); hidden_triples(); }
			if( stage == 6  ) { naked_quads();  hidden_quads(); }

			if( stage == 7  ) /*K1*/ 				post_to_form('KL1');
			if( stage == 8  ) /*Innies/Outies*/ 	post_to_form('KIO');
			if( stage == 9  ) /*Cage Splitting*/ 	post_to_form('KCS');

			if( stage == 10 ) /*PP*/ 				post_to_form('PPR'); //pointing_pairs();
			if( stage == 11 ) /*LBR*/ 				post_to_form('LBR'); //line_box_reduction();

			if( stage == 12 ) /*all others*/ 		post_to_form('KL4');

			if( stage == 1 )
				for( x in g )
					for( y in g[x] ) if( mask[y][x] && show[y][x] ) { show[y][x]=0; lable_square(y,x,0); }

			if( stage < 7  ) {
				document.getElementById("R" + stage).innerHTML=(some_changes)? '<font color=#00ff00><b>Yes</b></font>' : '<font color=#ff0000><b>No</b></font>';
			} else {
				document.getElementById("R" + kil_list[stage-7]).innerHTML=(some_changes)? '<font color=#00ff00><b>Yes</b></font>' : '<font color=#ffff00><b>Wait</b></font>';
			}
			for( x in g )
				for( y in g[x] ) orig[x][y]=mask[x][y];
		}
		if( sanity_check() )
			alert("Oops - you've got an error on the board");

		t=document.getElementById("TestT");
		for(i=0;i<MAX_STRAT-1;i++)
			t.rows[i*1+offset[i]].cells[1].style.backgroundColor=(stage==i) ? "#777700" : ((((i*1+offset[i])%2)==0)?"#333333":"#222222");
		document.getElementById("backstep").className='SButton';
		if( stage==MAX_STRAT && some_changes == false )
			alert("No more known logical steps to take - you have to enter a number somewhere and then click 'Take Step'");
	}
}
function back_step()
{
	var i,j,s;
	if( document.getElementById("backstep").className == 'GButton' ) return;
	for( j in g )
		for( i in g[j] )
		{
			if( last[j][i]>0 )
			{
				show[j][i]=g[j][i]=0;
				orig[j][i]=mask[j][i]=last[j][i];
				lable_square( j,i,0 );
			}
		}
	some_changes=false;
	stage=(stage==0)?prevlaststage:laststage;
	t=document.getElementById("TestT");
	for(i=0;i<MAX_STRAT;i++)
		t.rows[i*1+offset[i]].cells[1].style.backgroundColor=(stage==i) ? "#777700" : ((((i*1+offset[i])%2)==0)?"#333333":"#222222");
	backup_yes_no( kil_list, stage, 7 );

	document.getElementById("backstep").className='GButton';
	document.getElementById("takestep").onclick=take_step;
	document.getElementById("takestep").className = 'SButton';
	blue_board();
	jg.clear();
}
function email_board()
{
	var x,y,done=0,SGW;
	var board='bd=';
	for(y=0;y<9;y++)
		for(x=0;x<9;x++)
		{
			if( g[y][x]>0 ) done++;
			if( g[y][x]>0 ) board=board + ',' + (1 << (g[y][x]-1));
			else board=board + ',' + mask[y][x];
		}
	if( !done )
		alert("This board is empty!");
	else
	{
		SGW=window.open('SudokuEmail.htm?' + board,'_blank','resizable=no,scrollbars=no,left=300,top=200,screenX=200,screenY=200,width=750,height=420');
    	if (!SGW.opener) SGW.opener=self;
	}
}
function print_board(ptype)
{
	SGW=window.open('KillerPrintable.htm?p='+ptype,'_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=670,height=680');
	if (!SGW.opener) SGW.opener=self;
}
function test_solutions(ptype)
{
	var x,y,done=0,SGW;
	var board='';

	done=blue_board();
	if( done < 16  ) { alert('Too few clues/numbers, normal sudoku must have 17 clues minimum.'); return; }
	if( done == 81  ) { alert('Puzzle is complete.'); return; }

	for(y=0;y<9;y++) for(x=0;x<9;x++)
		board=board + g[y][x];

	SGW=window.open('S/WebSudoku.dll?solutions&0,' + board,'_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=670,height=480');
	if (!SGW.opener) SGW.opener=self;
}
function fired_event()
{
	var s,c,y,x,n,t,stratname;
	var doc;

	if( !document.ifrm )
		 doc = document.getElementById("ifrm").contentDocument;
	else doc = document.ifrm.document;
	if( !doc.getElementById("kbin") ) return;
	s = doc.getElementById("kbin").value;
	stratname = doc.getElementById("nstage").value;
	t=document.getElementById("TestT");

	if( stratname!="NO" )
	{
		if( stratname == "KL1" ) stage = 7;
		else if( stratname == "KIO" ) stage = 8;
		else if( stratname == "KCS" ) stage = 9;
		else stage = get_stage(kil_list,stratname);
		for(y=0;y<9;y++) for(x=0;x<9;x++) rcm[y][x]=0;

		d2 = doc.getElementById("cols1");
		if( d2 ) grn_blue_color(d2.value,"fshGrn");
		d2 = doc.getElementById("cols2");
		if( d2 ) grn_blue_color(d2.value,"fshBlu");

		if( jg ) {
			jg.clear();

			d = doc.getElementById("chain1")
			if( d ) parsemychain( d.value, "#0000ff" );

			d = doc.getElementById("chain2")
			if( d ) parsemychain( d.value, "#990099" );

			d = doc.getElementById("chain3")
			if( d ) parsemychain( d.value, "#ff0000" );

			d = doc.getElementById("chain4")
			if( d ) parsemychain( d.value, "#009900" );

			jg.paint();
		}
		for(i=0;i<s.length;i+=3)
		{
			c = s.charAt(i);
			if( c == '{' ) break;
			y = s.charAt(i)-1;
			x = s.charAt(i+1)-1;
			n = s.charAt(i+2)-1;
			rcm[y][x] |= (1 << n);
			some_changes = true;
		}
		for(y=0;y<9;y++)
			for(x=0;x<9;x++)
			{
				if( rcm[y][x] ) lable_square(y,x,rcm[y][x] & mask[y][x]);
				switch( s.charAt(y*9+x+i+1) ){
				case '1' : document.getElementById("a"+y+x).style.backgroundColor='#ffff55'; break;
				case '2' : document.getElementById("a"+y+x).style.backgroundColor='#eeaa55'; break;
				case '3' : document.getElementById("a"+y+x).style.backgroundColor='#55ff55'; break;
				case '4' : document.getElementById("a"+y+x).style.backgroundColor='#55ffcc'; break;
				}
			}
	//	alert(stratname + ' ' + stage);
		for(i=0;i<MAX_STRAT-1;i++)
			t.rows[i*1+offset[i]].cells[1].style.backgroundColor=(stage==i) ? "#777700" : ((((i*1+offset[i])%2)==0)?"#333333":"#222222");
		paint_yes_no( kil_list, stratname );
	}
	else
	{
		for(i=0;i<MAX_STRAT;i++)
			t.rows[i*1+offset[i]].cells[1].style.backgroundColor=((((i*1+offset[i])%2)==0)?"#333333":"#222222");
		paint_yes_no( kil_list, stratname );
	}
	document.getElementById("takestep").onclick=take_step;
	document.getElementById("takestep").className = 'SButton';
}
function toggle_strats( whichset )
{
	var i;
	switch( whichset ) {
	case 2 :
		for(i=10;i<=16;i++)
			document.getElementById("CB" + kil_list[i]).checked = !document.getElementById("CB" + kil_list[i]).checked;
		break;
	case 3 :
		for(i=17;i<=28;i++)
			document.getElementById("CB" + kil_list[i]).checked = !document.getElementById("CB" + kil_list[i]).checked;
		break;
	case 4 :
		for(i=23;i<=34;i++)
			document.getElementById("CB" + kil_list[i]).checked = !document.getElementById("CB" + kil_list[i]).checked;
		break;
	}
}
function add_cage_num(t)
{
	var x,y;
	x=t.id.charAt(2);
	y=t.id.charAt(3);
	if( !IsNumeric2(t.value) )
		t.value='';

	validate_killer();
}
function isBlack( t )
{
	if( t.style.backgroundColor == '') return true;
	if( t.style.backgroundColor == 'rgb(0, 0, 0)') return true;
	if( t.style.backgroundColor == 'rgb(0,0,0)') return true;
	if( t.style.backgroundColor == '#000000') return true;
	return false;
}
var cur_id = 1;
function set_pentomino_id( y, x )
{
	var many=0;
	if( cid[y][x]!=0 ) return 0;
	cid[y][x] = cur_id;
	many = 1;
	if( y > 0 && !isBlack(document.getElementById("CBL"+(y-1)+x)) ) many += set_pentomino_id( y-1, x );
	if( x > 0 && !isBlack(document.getElementById("CRL"+y+(x-1))) ) many += set_pentomino_id( y, x-1 );
	if( y < 8 && !isBlack(document.getElementById("CBL"+y+x)) ) many += set_pentomino_id( y+1, x );
	if( x < 8 && !isBlack(document.getElementById("CRL"+y+x)) ) many += set_pentomino_id( y, x+1 );
	return many;
}
function set_pentomino_size( y, x, target_id, many )
{
	if( x < 0 || x > 8 ) return 0;
	if( y < 0 || y > 8 ) return 0;

	if( cid[y][x] != target_id ) return 0;
	if( rcm[y][x] == 1 ) return 0;
	rcm[y][x] = 1;
	csz[y][x] = many;
	set_pentomino_size(y,x-1,target_id, many);
	set_pentomino_size(y,x+1,target_id, many);
	set_pentomino_size(y-1,x,target_id, many);
	set_pentomino_size(y+1,x,target_id, many);
}
function get_neighbour_colours( y, x, tcid )
{
	var c = 0;
	if( x < 0 || x > 8 ) return 0;
	if( y < 0 || y > 8 ) return 0;

	if( rcm[y][x] == 1 ) return 0;
	rcm[y][x] = 1;

	if( cid[y][x] != tcid )
	{
		if( map[y][x]==0 ) return 0;
		return (1 << map[y][x]);
	}
	c |= get_neighbour_colours( y-1, x, tcid );
	c |= get_neighbour_colours( y, x-1, tcid );
	c |= get_neighbour_colours( y+1, x, tcid );
	c |= get_neighbour_colours( y, x+1, tcid );
	return c;
}
function paint_cells( y, x, tcid, newcol )
{
	if( x < 0 || x > 8 ) return;
	if( y < 0 || y > 8 ) return;

	if( rcm[y][x] == 1 ) return;
	if( cid[y][x] != tcid ) return;
	if( map[y][x] > 0 ) return;

	rcm[y][x] = 1;
	map[y][x] = newcol;

	var t = document.getElementById("KL"+y+x);
	if( t.style.backgroundColor != sq_bck[map[y][x]-1] ) {

		t.style.backgroundColor = sq_bck[map[y][x]-1];

		if( y<8 && !isBlack(document.getElementById("CBL"+y+x)) )
			document.getElementById("CBL"+y+x).style.backgroundColor = sq_bck[map[y][x]-1];

		if( x<8 && !isBlack(document.getElementById("CRL"+y+x)) )
			document.getElementById("CRL"+y+x).style.backgroundColor = sq_bck[map[y][x]-1];
	}

	document.getElementById('board').value = y + ' ' + x;


	paint_cells( y-1, x, tcid, newcol );
	paint_cells( y, x-1, tcid, newcol );
	paint_cells( y+1, x, tcid, newcol );
	paint_cells( y, x+1, tcid, newcol );
}

function asign_four_color_map()
{
	var emptycells = 81;
	var ncol;
	var y,x,sx,sy,i,j;

	while( emptycells )
	{
		for(j=0;j<9;j++) for(i=0;i<9;i++) rcm[j][i]=0;
		x=y=-1;
		for(sy=0;sy<9 && y==-1;sy++)
			for(sx=0;sx<9 && x==-1;sx++)
				if( map[sy][sx]===0 ) { x=sx;y=sy; }
		if( x==-1 ) break;

		ncol = get_neighbour_colours( y, x, cid[y][x] );
		lastncol = ncol;

		for(j=0;j<9;j++) for(i=0;i<9;i++) rcm[j][i]=0;
		if( ncol == 62 ) { return false; }
		if( !ncol || (ncol & 2) == 0 ) paint_cells( y, x, cid[y][x], 1 );
		else if( (ncol & 4) == 0 ) paint_cells( y, x, cid[y][x], 2 );
		else if( (ncol & 8) == 0 ) paint_cells( y, x, cid[y][x], 3 );
		else if( (ncol & 16) == 0 ) paint_cells( y, x, cid[y][x], 4 );
		else if( (ncol & 32) == 0 ) paint_cells( y, x, cid[y][x], 5 );

		for(emptycells=y=0;y<9;y++) for(x=0;x<9;x++) if( map[y][x]==0 ) emptycells++;
	}
	return true;
}
function cager(t)
{
	var x=t.id.charAt(4);
	var y=t.id.charAt(3);
	t.style.backgroundColor = ( isBlack(t) ) ? sq_bck[map[y][x]-1] : '#000000';

	validate_killer();
}
function cageb(t)
{
	var x=t.id.charAt(4);
	var y=t.id.charAt(3);
	t.style.backgroundColor = ( isBlack(t) ) ? sq_bck[map[y][x]-1] : '#000000';

	validate_killer();
}
function load_parent_puzzle()
{
	var x,y,s='',st=0,frm,t;

	for(y=0;y<9;y++) for(x=0;x<9;x++) csz[y][x]=ccl[y][x]=rcm[y][x]=map[y][x]=0;

	if( location.search != '?n=1' )
	{
		validate_killer();
		return;
	}
	if( opener === null
	 || opener.document === null
	 || opener.document.getElementById('servsolv') === null ) {
		alert('Cannot find the parent document - the Killer Solve page');
		return;
	}
	frm = opener.document.getElementById('servsolv');

	str2map(frm.elements['colmap'].value);
	str2ccl(frm.elements['cluemap'].value);

	document.getElementById("colmap").value = frm.elements['colmap'].value;
	document.getElementById("cluemap").value = frm.elements['cluemap'].value;

	for(y=0;y<9;y++) for(x=0;x<9;x++)
	{
		t = document.getElementById("KL"+y+x);
		t.style.backgroundColor = sq_bck[map[y][x]-1];
		document.forms.BoardDesign.elements["CL"+y+x].value=( ccl[y][x]>0 ) ? ccl[y][x] : '';
	}

	for(y=0;y<9;y++)
		for(x=0;x<8;x++)
		{
			t = document.getElementById("CRL"+ y + x);
			if( t ) t.style.backgroundColor = ( map[y][x]==map[y][x+1] ) ? sq_bck[map[y][x]-1] : '#000000';
		}
	for(y=0;y<8;y++)
		for(x=0;x<9;x++)
		{
			t = document.getElementById("CBL"+ y + x);
			if( t ) t.style.backgroundColor = ( map[y][x]==map[y+1][x] ) ? sq_bck[map[y][x]-1] : '#000000';
		}
	compute_cage_sizes();
}

function validate_killer()
{
	var x,y,many;
	var cluemap = '',colmap='';
	var totcur = 0;

	validkiller = true;

	for(y=0;y<9;y++) for(x=0;x<9;x++) cid[y][x]=csz[y][x]=rcm[y][x]=map[y][x]=0;
	cur_id = 1;
	for(y=0;y<9;y++)
		for(x=0;x<9;x++)
		{
			many = set_pentomino_id( y, x );
			set_pentomino_size( y, x, cur_id, many );
			cur_id++;
		}

	if( !asign_four_color_map() )
		alert('oops, cant assign 4 colors');

	for(y=0;y<9;y++)
		for(x=0;x<9;x++)
		{
			v = document.getElementById("CL"+y+x);
			if( v.value != '' ) totcur += parseInt(v.value);
		}
	document.getElementById("cagetotal").value = totcur;

	if( document.getElementById("cagetotal").value != 405 ) validkiller = false;

	document.getElementById("sendsolv").className = (validkiller) ? 'GrnButton' : 'GButton';
}
function validate_killer_but()
{
	validate_killer();

	if( document.getElementById("cagetotal").value != 405 ) {
		alert('You need to enter values for the cages which add up to 45 x 9, or 405');
	}

}

function send_to_solver()
{
	var x,y,many;
	var cluemap = '',colmap='';

	if( !validkiller ) {
		alert('Current Killer is not validating, please modify');
	}

	for(y=0;y<9;y++)
		for(x=0;x<9;x++)
		{
			v = document.getElementById("CL"+y+x);
			cluemap += padzero(v.value);
			colmap += map[y][x].toString();
		}

	document.getElementById("cluemap").value = cluemap;
	document.getElementById("colmap").value = colmap;


		if( opener === null
		 || opener.document === null
		 || opener.document.getElementById('servsolv') === null ) {
			alert('Cannot find the parent document - the Killer Solve page');
			return;
		}


	frm = opener.document.getElementById('servsolv');

	frm.elements['cluemap'].value = cluemap;
	frm.elements['colmap'].value = colmap;

	window.opener.load_from_fields();

	window.close();
}
function clear_design()
{
	var x,y;
	for(y=0;y<9;y++)
		for(x=0;x<9;x++)
		{
			document.getElementById("CL"+y+x).value = '';
		}
	for(y=0;y<9;y++)
		for(x=0;x<8;x++)
		{
			document.getElementById("CRL"+ y + x).style.backgroundColor = '#000000';
		}
	for(y=0;y<8;y++)
		for(x=0;x<9;x++)
		{
			document.getElementById("CBL"+ y + x).style.backgroundColor = '#000000';
		}
	validate_killer();
}
function import_from_lines()
{
	var x,y;
	for(y=0;y<9;y++) for(x=0;x<9;x++) csz[y][x]=ccl[y][x]=rcm[y][x]=map[y][x]=0;

	str2map(document.getElementById("colmap").value);
	str2ccl(document.getElementById("cluemap").value);

	for(y=0;y<9;y++) for(x=0;x<9;x++)
	{
		t = document.getElementById("KL"+y+x);
		t.style.backgroundColor = sq_bck[map[y][x]-1];
		document.forms.BoardDesign.elements["CL"+y+x].value=( ccl[y][x]>0 ) ? ccl[y][x] : '';
	}

	for(y=0;y<9;y++)
		for(x=0;x<8;x++)
		{
			t = document.getElementById("CRL"+ y + x);
			if( t ) t.style.backgroundColor = ( map[y][x]==map[y][x+1] ) ? sq_bck[map[y][x]-1] : '#000000';
		}
	for(y=0;y<8;y++)
		for(x=0;x<9;x++)
		{
			t = document.getElementById("CBL"+ y + x);
			if( t ) t.style.backgroundColor = ( map[y][x]==map[y+1][x] ) ? sq_bck[map[y][x]-1] : '#000000';
		}
	compute_cage_sizes();
	validate_killer();
}