/*-----------------------------------------------------------------------
	Copyrighted Andrew Stuart, 2005-2009, andrew@scanraid.com
	First version: 23 May 2005
	This version: 1.53, 06-APR-2009
-----------------------------------------------------------------------*/
var stage=0,laststage=0,prevlaststage=0;
var print_version=false;
var showhints=true;
var steps=0;
var save_dstring='';
var bunched=false;
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=false;
var MAX_STRAT = sdx_list.length+7;
var coordmode=1;
var cnv, jg;

// Mask is a 2D array of ints which actually store bit arrays of numbers 1 to 9.
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 jb  =[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,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 ccm =[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,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,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 g1 ="4..8.52............8..7.......2.89.7........41.53............1............1..7..6"; // 18 clue moderate
var g2 ="7...2..8.......9.....3.9.51....7......845.1......6.......5...............1..8...2"; // Tough Strategies
var g3 =".....81..7...9..56..5...7.........7..8........6.......6.8...4...4..1...3..18....."; // Big Hidden Quad */
var g4 ="209006003000020600007000200008070020700682005052031867026040900074060002100200006"; // Y-Wing / X-Wing
var g5 =".1.2...5...9...4.....1........467.9...15.86...9.3.1........2.....8...9...7...5.4."; // SwordFish
var g6 =".....6....7.......63..1..7416......8.2.9.8.4.4......2979.....81.......6....7....."; // Simple Colouring
var g7 ="862719354051023700030850100200087005500001000000560003000045030024108500005000841"; // Y-Wing
var g8 ="5...6...2..2...3......54..6.2.....47...5.6...85.....3....34......4...2..9...2...4"; // Jelly-Fish
var g9 ="....9..5.89.5.2.3.4...8..7...96....3.........6....85...7..6...5.6.2.5.47.1..4...."; // X-Cycle on 7
var g10="000300796376190840490000310600020000000613000000080601130000084504031967067000103"; // UR 1
var g11="..9......31289.7..8.......2...98....7...4...9....52...9.......5..5.19267......1.."; // UR 4
var g12="625371849834060712791080356350020000400153008100090035047010003083040000216030504"; // XYZ-Wings
var g13="000106025102705006560802000009520008280960000306481209600208004920614507840309002"; // APE
var g14=".....2.4.8.3....1...9.1..2.7...3......5..........6...3.5..4.6...4....1.5...9....."; // Finned X-Wing
var g15="......4...2.31............17...23.9...2.9.8...3.45...6..........6..82.5...9......"; // Extreme Extreme
var g16="...378......1.4............93.....541...3...242.....13............8.1......596..."; // Unsolveable


var block1;

var jigsaw_maps = "211111112121111121112111211111212111111121111111212111112111211121111121211111112";






jig=-1;

/*---------------------------------------------------------------------*/
/* Draws the content of a square on the board							*/
/*---------------------------------------------------------------------*/
function set_square( x, y, val, setup )
{
	var t, s;
	var sq_col=['black','#CC0000','blue','blue'];
	var sq_siz=['8pt','14pt','14pt','14pt','8pt','18pt','18pt','18pt'];

	// Get the table cell name out using the coordinates
	t=document.getElementById("a"+y+x);
	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=(print_version) ? 'black' : sq_col[setup];
	t.style.fontSize=(print_version) ? '20pt' : sq_siz[setup];
	if( !print_version && setup == 3 ) t.style.backgroundColor = '#ff0000';
	if( print_version ) return;
	s="D" + y.toString()+x.toString();
	if( val == "&nbsp;" )
		document.forms.DataEntry.elements[s].value='';
	else if( setup ) document.forms.DataEntry.elements[s].value=val;
}
/*----------------------------------------------------------------------*/
/* 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;
	mask[y][x] -= deduct;
	show[y][x] += deduct;
	if( bunched )
	{
		if( bit_count(mask[y][x]) < 5 ) modfact=2;
		for( i=0;i<9;i++ ) if( mask[y][x] & (1 << i) )	// i=0 to 8 so first shift is 0 bits
		{
			if( lable.length > 0 ) lable=lable + "&nbsp;";

			if( c && (c % modfact) === 0 ) lable=lable + "<br>";
			lable=lable + (i+1);
			c++;	// <br> it every three numbers
		}
	}
	else
	{
		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>";
		}
	}
	some_changes=true;
	set_square(x,y,lable,0);
}
/*---------------------------------------------------------------------*/
/* Sets the board up from scratch and draws it. Called from onLoad */
/*---------------------------------------------------------------------*/
function load_board()
{
	var i,j,t,s,nt,k,p,a,doc,bdoc,c;
	var bd=location.search;
	var oRow,sRow,par;
	var content;
	prevlaststage=laststage=stage=0;

	cordX=new Array(81);
	cordY=new Array(81);
	APEstack=new Array(81);

/*	if( !document.ifrm )
		 doc = document.getElementById("ifrm").contentDocument;
	else doc = document.ifrm.document;
	doc.body.innerHTML='Results will go here!'; */

	for(j=0;j<9;j++)
		for(i=0;i<9;i++)
		{
			jb[j][i] = jigsaw_maps.charAt(j*9+i);
			if( bd.length==85 && firsttime )
			{
				if( IsNumeric(bd.charAt((j*9)+i+4)) )
					g[j][i]=bd.charAt((j*9)+i+4);
			}
			else if( !print_version )
			{
				switch( document.forms.DataEntry.elements["Example"].selectedIndex ) {
				case 0 : c=g1.charAt((j*9)+i)*1; break;
				case 1 : c=g2.charAt((j*9)+i)*1; break;
				case 2 : c=g3.charAt((j*9)+i)*1; break;
				case 3 : c=g4.charAt((j*9)+i)*1; break;
				case 4 : c=g5.charAt((j*9)+i)*1; break;
				case 5 : c=g6.charAt((j*9)+i)*1; break;
				case 6 : c=g7.charAt((j*9)+i)*1; break;
				case 7 : c=g8.charAt((j*9)+i)*1; break;
				case 8 : c=g9.charAt((j*9)+i)*1; break;
				case 9 : c=g10.charAt((j*9)+i)*1; break;
				case 10 : c=g11.charAt((j*9)+i)*1; break;
				case 11 : c=g12.charAt((j*9)+i)*1; break;
				case 12 : c=g13.charAt((j*9)+i)*1; break;
				case 13 : c=g14.charAt((j*9)+i)*1; break;
				case 14 : c=g15.charAt((j*9)+i)*1; break;
				case 15 : c=g16.charAt((j*9)+i)*1; break;
				}
				g[j][i]=(IsNumeric(c))?c:0;
			}
			show[j][i]=orig[j][i]=mask[j][i]=0;
			if( g[j][i] > 0 )
				set_square(i,j,g[j][i],1);
			else
			{
				orig[j][i]=mask[j][i]=511;
				lable_square( j,i,0 );
				document.forms.DataEntry.elements['D'+j+i].value='';
			}
			t=document.getElementById("a"+j+i);
			t.style.backgroundColor=( jb[j][i]==2 )?'#dddddd':'#ffffff';
		}

	reset_yes_no( sdx_list, 6 );
	document.getElementById("takestep").onclick=take_step;
	document.getElementById("takestep").className = 'SButton';
	if( readCookie('scanraidsudokuxcookie') )
	{
		document.getElementById("reload").className="SButton";
		some_saved=true;
	}
	some_changes=false;
	firsttime=false;

	if( !document.ifrm )
		 doc = document.getElementById("ifrm").contentDocument;
	else doc = document.ifrm.document;
	doc.body.innerHTML='Results go here';

	cnv = document.getElementById("myCanvas");
	jg = new jsGraphics(cnv);
	jg.clear();
}
function load_print_board(ptype)
{
	var i,j,k=2,t,s,sss,k,p,a,doc,jboard;
	var par;
	var content;

	cordX=new Array(81);
	cordY=new Array(81);
	APEstack=new Array(81);
	print_version=true;

	par=parent.opener.document;

	for(j=0;j<9;j++)
		for(i=0;i<9;i++)
		{
			jb[j][i]=show[j][i]=orig[j][i]=mask[j][i]=0;
			nt=( j < 3 ) ? "A" : (( j < 6 ) ? "B" : "C");
			nt=nt + (( i < 3 ) ? "1" : (( i < 6 ) ? "2" : "3"));
			t=document.getElementById(nt);
			s=par.getElementById(nt);
			oRow=t.rows[j % 3];
			sRow=s.rows[j % 3];
			content=sRow.cells[i % 3].innerHTML;
			issmall = false;
			if( content != '&nbsp;' )
			{
				if( content.search(/table/i)!=-1 ) issmall = true;
				if( ptype==1 )
				{
					content=content.replace(/<table.*?>/gi,'');
					content=content.replace(/<td.*?>/gi,'');
					content=content.replace(/[^1-9]/g,'');
				}
				if( ptype==2 )
				{
					rExp=/<font color=#ddeeff>0<\/font>/gi;
					content=content.replace(rExp,'&nbsp;&nbsp;');
				}
			}
			if( issmall ) {
				if( ptype == 1 )
					 oRow.cells[i % 3].className='innerLittle';
				else oRow.cells[i % 3].className='innerLittleCenter';
			}
			oRow.cells[i % 3].innerHTML=content;
		}
}

function import_sudoku()
{
	var dstring;
	var actualstr='';
	var c,i,j,s,t;

	dstring=window.prompt("Enter a string of 81 numbers (you can express blanks as 0, *, _ or '.')",save_dstring);
	if( dstring === null ) return;
	if( dstring.length == 0 ) return;

	save_dstring=dstring;

	for(i=0;i<dstring.length;i++)
	{
		c=dstring.charAt(i);
		if( IsNumeric(c) || c=='0' )
			actualstr=actualstr + dstring.charAt(i);
		else if( c=='.' || c=='*' || c=='_' )
			actualstr=actualstr + '0';
	}
	if( actualstr.length != 81 )
	{
		okay=false;
		alert("Your submission contained " + actualstr.length + " numbers. Please check it and press 'Import' again");
		return;
	}
	for(j=0;j<9;j++)
		for(i=0;i<9;i++)
		{
			t=document.getElementById("a"+j+i);
			t.style.backgroundColor=( jb[j][i]==2 )?'#dddddd':'#ffffff';
			t.style.color='black';
			t.style.fontSize='8pt';
			show[j][i]=mask[j][i]=0;
			g[j][i]=parseInt(actualstr.charAt((j*9)+i));
			if( g[j][i] > 0 )
				set_square(i,j,g[j][i],1);
			else
			{
				orig[j][i]=mask[j][i]=511;
				lable_square( j,i,0 );
				s="D" + j.toString()+i.toString();
				document.forms.DataEntry.elements[s].value='';
			}
		}
	reset_yes_no( sdx_list, 6 );
	some_changes=false;
	firsttime=false;
	prevlaststage=laststage=stage=0;
	document.getElementById("backstep").className='GButton';
	jg.clear();
}
function blank_board()
{
	var i,t,x,y,nt;
	prevlaststage=laststage=stage=0;
	t=document.getElementById("TestT");
	for(i=0;i<MAX_STRAT;i++)
		t.rows[i].cells[0].style.backgroundColor="#222222";
	document.getElementById("backstep").className='GButton';
	for(x=0;x<9;x++)
		for(y=0;y<9;y++)
		{
			t=document.getElementById("a"+y+x);
			t.style.backgroundColor=( jb[y][x]==2 )?'#dddddd':'#ffffff';
			t.style.color='black';
			t.style.fontSize='8pt';
			orig[x][y]=mask[x][y]=511;	// This is the key: numbers 1-9 in bits=511,
			g[x][y]=0;					// .. and there are no picked squares
			set_square(y,x,"&nbsp;",0);		// nbsp it so the borders show up
		}
	reset_yes_no( sdx_list, 6 );
	jg.clear();
}
function clear_board()
{
	var i,t,x,y,nt;
	prevlaststage=laststage=stage=0;
	t=document.getElementById("TestT");
	for(i=0;i<MAX_STRAT;i++)
		t.rows[i].cells[0].style.backgroundColor="#222222";
	document.getElementById("backstep").className='GButton';
	for(x=0;x<9;x++)
		for(y=0;y<9;y++)
		{
			t=document.getElementById("a"+y+x);
			t.style.backgroundColor=( jb[y][x]==2 )?'#dddddd':'#ffffff';
			t.style.color='black';
			t.style.fontSize='8pt';
			orig[x][y]=mask[x][y]=511;	// This is the key: numbers 1-9 in bits=511,
			g[x][y]=0;					// .. and there are no picked squares
		}
	reset_yes_no( sdx_list, 6 );
	jg.clear();
}
function save_board()
{
	var i,j,s='';
	for( j in g )
		for( i in g[j] ) {
			if( s.length ) s += ',';
			s = s + (g[j][i]?g[j][i]:-mask[j][i]);
			save[j][i]=g[j][i];
		}
	document.getElementById("reload").className="SButton";
	some_saved=true;

	var date = new Date();
	date.setTime(date.getTime()+(30*24*60*60*1000));

	document.cookie ='scanraidsudokuxcookie=' + s + '; expires=' + date.toGMTString() + '; path=/';

	alert("Current Board Saved (as a cookie)");
}
function reload_board()
{
	var i,j,x;
//	if( some_saved === false ) return;

	x = readCookie('scanraidsudokuxcookie');
	if (!x)
	{
		alert("No saved board found");
		return;
	}
	clear_board();
	if( x.length == 81 ) { // old cookie
		for( j=0;j<9;j++ )
			for( i=0;i<9;i++ )
			{
				g[j][i]=x.charAt((j*9)+i)*1;
				orig[j][i]=mask[j][i]=0;
				if( g[j][i] > 0 )
					set_square(i,j,g[j][i],1);
				else
				{
					orig[j][i]=mask[j][i]=511;
					lable_square( j,i,0 );
				}
			}
	} else {
		arr = x.split(',');
		for( j=0;j<9;j++ )
			for( i=0;i<9;i++ )
			{
				orig[j][i]=0;
				if( arr[(j*9)+i] > 0 ) {
					g[j][i]=parseInt(arr[(j*9)+i]);
					orig[j][i]=mask[j][i]=0;
				} else {
					orig[j][i]=mask[j][i]=-parseInt(arr[(j*9)+i]);
					g[j][i]=0;
				}
				if( g[j][i] > 0 )
					set_square(i,j,g[j][i],1);
				else
				{
					lable_square( j,i,0 );
					document.forms.DataEntry.elements['D'+j+i].value='';
				}
			}
	}
	reset_yes_no( sdx_list, 6 );
	jg.clear();
}
/*----------------------------------------------------------------------*/
/* First of the analyser functions - simply checks for single values	*/
/* which means a number MUST be the solution for that square			*/
/*----------------------------------------------------------------------*/
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);
								}
							}

	for( x=0;x<9;x++ )	// for diagonals
		if( !g[x][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[i][i] > 0 ) // check values in row
					if( (mask[x][x] & (1 << (g[i][i]-1))) )
					{
						mask[x][x] -= (1 << (g[i][i]-1));	// remove that bit
						changes=true;
					}
			}
			if( changes ) lable_square( x,x,0 );
		}

	for( x=0;x<9;x++ )	// for diagonals
		if( !g[x][8-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[i][8-i] > 0 ) // check values in row
					if( (mask[x][8-x] & (1 << (g[i][8-i]-1))) )
					{
						mask[x][8-x] -= (1 << (g[i][8-i]-1));	// remove that bit
						changes=true;
					}
			}
			if( changes ) lable_square( x,8-x,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;
				}
			}
}
function singles_in_diagonal( )
{
	var y,x,n,c,k;

	for(x=0;x<9;x++)	// for every square on the board...
		if( !g[x][x] )	// if it is an unknown square...
			for(n=0;n<9 && !g[x][x];n++) if( mask[x][x] & (1 << n) ) // For all numbers,if the number is a possible
			{
				for( c=k=0;k<9;k++)  // check the row
					if( !g[k][k] && (mask[k][k] & (1 << n)) ) c++;
				if( c==1 )
				{
					strat_add("SINGLE: " + cordit(x,x) + " set to " + abetx.charAt(n) + ", unique in Diagonal 1<br>");
					show[x][x]=(1 << n);
					lable_square(x,x,0);
					mask[x][x]=(1 << n);
				}
			}
	for(x=0;x<9;x++)	// for every square on the board...
		if( !g[x][8-x] )	// if it is an unknown square...
			for(n=0;n<9 && !g[x][8-x];n++) if( mask[x][8-x] & (1 << n) ) // For all numbers,if the number is a possible
			{
				for( c=k=0;k<9;k++)  // check the row
					if( !g[k][8-k] && (mask[k][8-k] & (1 << n)) ) c++;
				if( c==1 )
				{
					strat_add("SINGLE: " + cordit(x,8-x) + " set to " + abetx.charAt(n) + ", unique in Diagonal 1<br>");
					show[x][8-x]=(1 << n);
					lable_square(x,8-x,0);
					mask[x][8-x]=(1 << n);
				}
			}
}

/*-------------------------------------------------------------------------*/
/* 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);

	gotsome = false;
	// Diagonal 1
	for(n=0;n<9;n++)	// .. check each number
		for(pos[n]=x=0;x<9;x++)
			if( !g[x][x] && (mask[x][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++)
					if( pos[n] & (1 << x) && bit_count(mask[x][x]) > 2 )
					{
						h=(1 << n) + (1 << m);
						apply_new_mask( "HIDDEN PAIR: ", " in diagonal ",1,x,x,h );
					}

	// Diagonal 2
	for(n=0;n<9;n++)	// .. check each number
		for(pos[n]=x=0;x<9;x++)
			if( !g[x][8-x] && (mask[x][8-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++)
					if( pos[n] & (1 << x) && bit_count(mask[x][8-x]) > 2 )
					{
						h=(1 << n) + (1 << m);
						apply_new_mask( "HIDDEN PAIR: ", " in diagonal ",2,x,8-x,h );
					}


	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 );
						}
	}
	return gotsome;
}
function hidden_triples()
{
	var x,y,n,m,p,i,bb,cc,a,b,c,h,box=0;
	var pos=new Array(9);

	// Diagonal 1
	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[x][x] && (mask[x][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( (a || b || c) && bit_count(mask[x][x]) > ((a>0)+(b>0)+(c>0)) )
						{
							h=(1 << n) + (1 << m) + (1 << p);
							apply_new_mask( "HIDDEN TRIPLE: ", " in diagonal ",1,x,x,h );
						}
					}
				}

	// Diagonal 2
	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[x][8-x] && (mask[x][8-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( (a || b || c) && bit_count(mask[x][8-x]) > ((a>0)+(b>0)+(c>0)) )
						{
							h=(1 << n) + (1 << m) + (1 << p);
							apply_new_mask( "HIDDEN TRIPLE: ", " in diagonal ",2,x,8-x,h );
						}
					}
				}


	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);

	// diagonal 1
	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[x][x] && (mask[x][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[x][x]) > ((a>0)+(b>0)+(c>0)+(d>0)) )
							{
								h=(1 << n) + (1 << m) + (1 << p) + (1 << q);
								apply_new_mask( "HIDDEN QUAD: ", " in diagonal 1 ",x,x,x,h );
							}
						}
					}

	// diagonal 2
	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[x][8-x] && (mask[x][8-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[x][8-x]) > ((a>0)+(b>0)+(c>0)+(d>0)) )
							{
								h=(1 << n) + (1 << m) + (1 << p) + (1 << q);
								apply_new_mask( "HIDDEN QUAD: ", " in diagonal 2 ",8-x,8-x,x,h );
							}
						}
					}


	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);

	gotsome = false;
	// Diagonal 1
	for(x1=0;x1<8;x1++)
		for(x2=x1+1;x2<9;x2++)
		{
			// This block checks diagonal 1 the pair resides in...
			if( bit_count(mask[x1][x1])==2 && mask[x1][x1] == mask[x2][x2] )
				for(i=0;i<9;i++)
				{
					h=(mask[i][i] & mask[x1][x1]);
					if( i!=x1 && i!=x2 && !g[i][i] && h )
					{
						strat_add("NAKED PAIR (Diag 1): " + cordit(x1,x1) + "/" + cordit(x2,x2) + " removes " + mask2str(mask[i][i] & h) + " from " + cordit(i,i) + "<br>");
						lable_square( i,i,h );
						gotsome = true;
					}
				}
		}
	// Diagonal 2
	for(x1=0;x1<8;x1++)
		for(x2=x1+1;x2<9;x2++)
		{
			// This block checks diagonal 2 the pair resides in...
			if( bit_count(mask[x1][8-x1])==2 && mask[x1][8-x1] == mask[x2][8-x2] )
				for(i=0;i<9;i++)
				{
					h=(mask[i][8-i] & mask[x1][8-x1]);
					if( i!=x1 && i!=x2 && !g[i][8-i] && h )
					{
						strat_add("NAKED PAIR (Diag 2): " + cordit(x1,8-x1) + "/" + cordit(x2,8-x2) + " removes " + mask2str(mask[i][8-i] & h) + " from " + cordit(i,8-i) + "<br>");
						lable_square( i,8-i,h );
						gotsome = true;
					}
				}
		}

	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) );
									gotsome = true;
								}
							}
					}
				}
		}

	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 );
							gotsome = true;
						}
					}

				// 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 );
							gotsome = true;
						}
					}
			}
	return gotsome;
}

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);


	for(x1=0;x1<7;x1++)
		for(x2=x1+1;x2<8;x2++)
			for(x3=x2+1;x3<9;x3++)
				// This block checks diagonal 1 the triple resides in...
				if( bit_count(mask[x1][x1])>1 && bit_count(mask[x2][x2])>1 && bit_count(mask[x3][x3])>1 )
				{
					h=mask[x1][x1] | mask[x2][x2] | mask[x3][x3];
					if( bit_count(h)==3 )
						for(i=0;i<9;i++)
						{
							off=(mask[i][i] & h);
							if( i!=x1 && i!=x2 && i!=x3 && off )
							{
								strat_add("NAKED TRIPLE (Diag 1): " + cordit(x1,x1) + "/" + cordit(x2,x2) + "/" + cordit(x3,x3) + " removes " + mask2str(off) + " from " + cordit(i,i) + "<br>");
								lable_square( i,i,off );
							}
						}
				}
	for(x1=0;x1<7;x1++)
		for(x2=x1+1;x2<8;x2++)
			for(x3=x2+1;x3<9;x3++)
				// This block checks diagonal 2 the triple resides in...
				if( bit_count(mask[x1][8-x1])>1 && bit_count(mask[x2][8-x2])>1 && bit_count(mask[x3][8-x3])>1 )
				{
					h=mask[x1][8-x1] | mask[x2][8-x2] | mask[x3][8-x3];
					if( bit_count(h)==3 )
						for(i=0;i<9;i++)
						{
							off=(mask[i][8-i] & h);
							if( i!=x1 && i!=x2 && i!=x3 && off )
							{
								strat_add("NAKED TRIPLE (Diag 2): " + cordit(x1,8-x1) + "/" + cordit(x2,8-x2) + "/" + cordit(x3,8-x3) + " removes " + mask2str(off) + " from " + cordit(i,8-i) + "<br>");
								lable_square( i,8-i,off );
							}
						}
				}

	// 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( x in g )
		if( g[x][x] )	// if it is an known square...
			for( i=0;i<9;i++ ) // check values in diagonal
				if( i != x && g[i][i] == g[x][x] )
				{
					set_square(i,i,g[i][i],3);	// hightlight conflicting squares
					set_square(x,x,g[x][x],3);	// hightlight conflicting squares
					failed+=2;
				}
	for( x in g )
		if( g[x][8-x] )	// if it is an known square...
			for( i=0;i<9;i++ ) // check values in diagonal
				if( i != x && g[i][8-i] == g[x][8-x] )
				{
					set_square(i,8-i,g[i][8-i],3);	// hightlight conflicting squares
					set_square(x,8-x,g[x][8-x],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=( jb[y][x]==2 )?'#dddddd':'#ffffff';
			if( g[y][x]>0 ) done++;
		}
	return done;
}
function grade_sudoku()
{
	var i,j,done=0,t,found=0,x,y;

	done=blue_board();
	if( stage>0 && done > 0 && !block_board() ) return;

	if( done == 0 )	// If the number of solutions=81, we're all done
	{
		alert("Put some numbers in the small board first.");
	}
	else if( done == 81 )	// If the number of solutions=81, we're all done
	{
		if( sanity_check()>0 )
			 alert("Opps. Some problem with the puzzle");
		else alert("The puzzle is complete");
	}
	else
	{
		if( !document.ifrm )
			 doc = document.getElementById("ifrm").contentDocument;
		else doc = document.ifrm.document;
		doc.body.innerHTML='';

	//	document.getElementById("ifrm").src = 'sudoku/SudokuSAPI.dll?GradeSudoku?-1');
	}
}
function post_to_form(cur_strat) {
	var x,y,s='',st='';
	for(y=0;y<9;y++)		// Redraw the board to clear any user highlighting
		for(x=0;x<9;x++)
		{
			if( g[y][x] )
				 s = s + ',' + (1 << (g[y][x]-1));
			else s = s + ',' + mask[y][x];
		}
	for( x=2;x<sdx_list.length;x++) if( document.getElementById("CB"+sdx_list[x]).checked===false )
	{
		st+=sdx_list[x];
	}
/*	var frm;
	var iframeEl = document.getElementById('ifrm');
	if ( iframeEl.contentDocument ) { // DOM
		frm = iframeEl.contentDocument.getElementById('servsolv');
	} else if ( iframeEl.contentWindow ) { // IE win
		frm = iframeEl.contentWindow.document.getElementById('servsolv');
	} else {
		alert("Can't find iframe in DOM");
	} */
	var frm = document.forms.servsolv;
	frm.elements['coordmode'].value = coordmode;
	frm.elements['strat'].value = cur_strat;
	frm.elements['stratmask'].value = st;
	frm.elements['mapno'].value = jig;
	frm.elements['board'].value = s.substr(1,s.length-1);
	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 === 0 )	// If the number of solutions=81, we're all done
	{
		alert("Put some numbers in the small board first.");
	}
	else 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<8 ) stage++;
			else stage=9;
		}

		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( sdx_list, 6 ); jg.clear(); clear_on_off_color(); }

			if( stage >= 7  )
			{
				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_diagonal(); singles_in_box(); }
			if( stage == 4  ) if( !main_pair_test() ) main_triple_test();
			if( stage == 5  ) { hidden_pairs(); hidden_triples(); }
			if( stage == 6  ) { naked_quads();  hidden_quads(); }
			if( stage == 7  ) /*pointing_pairs*/	post_to_form('PPR');
			if( stage == 8  ) /*LBR*/				post_to_form('LBR');

			if( stage == 9  ) /*all others*/ 		post_to_form('XWG');

			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" + sdx_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 );
				s="D" + j.toString()+i.toString();
				document.forms.DataEntry.elements[s].value='';
			}
		}
	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( sdx_list, stage, 7 );

	document.getElementById("backstep").className='GButton';
	document.getElementById("takestep").onclick=take_step;
	document.getElementById("takestep").className = 'SButton';
	blue_board();
	jg.clear();
}
/* Function to put a number on the board from the data entry form 		 */
function add_data(t)
{
	var x,y;
	some_changes=false;
	blue_board();
	x=t.id.charAt(1);	// Coordinate found in the input field name
	y=t.id.charAt(2);
	if( IsNumeric(t.value) )	// If the value is numeric
	{
		if( orig[x][y] & (1 << (t.value-1)) )	// ..Check if its a possible number for that square
		{
			g[x][y]=t.value;				// .. it is, so put it on the board
			mask[x][y]=0;
			set_square(y,x,g[x][y],2);
		}
		else t.value=( g[x][y] && !orig[x][y] ) ? g[x][y] : '';
	}
	else t.value='';
	if( t.value == '' )
	{
		if( orig[x][y]==0 ) orig[x][y]=511;
		mask[x][y]=orig[x][y];
		g[x][y]=0;
		lable_square(x,y,0)
	}
	stage=0;
	sanity_check();
}
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('SudokuXEmail.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)
{
	var x,y,done=0,SGW;
	var board='bd=';
	for(y=0;y<9;y++) for(x=0;x<9;x++)
		board=board + (g[y][x]?g[y][x]:0);

	if( ptype == 1 )
		 SGW=window.open('SudokuXPrintable.htm?' + board,'_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=670,height=700');
	else SGW=window.open('SudokuXPrintableV2.htm?' + board,'_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=670,height=700');
	if (!SGW.opener) SGW.opener=self;
}
function test_solutions(ptype)
{
	var x,y,done=0,SGW;
	var board='';

	done=blue_board();
	if( done < 10  ) { alert('Too few clues/numbers, please enter some more numbers.'); 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&-1,' + 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,www;
	var doc;
	if( !document.ifrm )
		 doc = document.getElementById("ifrm").contentDocument;
	else doc = document.ifrm.document;
	s = doc.getElementById("kbin").value;
	stratname = doc.getElementById("nstage").value;
	t=document.getElementById("TestT");

	if( stratname!="NO" )
	{
		stage = get_stage(sdx_list,stratname);

		d2 = doc.getElementById("cols1");
		if( d2 ) grn_blue_color(d2.value,"fshGrn",0);
		d2 = doc.getElementById("cols2");
		if( d2 ) grn_blue_color(d2.value,"fshBlu",0);
		d2 = doc.getElementById("cols3");
		if( d2 ) grn_blue_color(d2.value,"fshOFF",0);

		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();
		}
		if( s.length ) grn_blue_color(s,"fsh",1);

		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;

			mask[y][x] -= (1 << n);
			show[y][x] += (1 << n);
		//	lable_square(y,x,(1 << n));
			some_changes = true;
		}
		for(y=0;y<9;y++)
			for(x=0;x<9;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;
				}
			}
		if( stratname=="PPR" || stratname=="LBR" )
		{
			document.getElementById("R" + stratname).innerHTML=(some_changes)? '<font color=#00ff00><b>Yes</b></font>' : '<font color=#ff0000><b>No</b></font>';
		}
		else
		{
			for(i=0;i<MAX_STRAT-1;i++) {
				www = i*1+offset[i];
				t.rows[www].cells[1].style.backgroundColor=(stage==i) ? "#777700" : (((www%2)==0)?"#333333":"#222222");
			}
			paint_yes_no( sdx_list, stratname );
		}
	}
	else
	{
		if( stratname=="PP" || stratname=="LBR" )
			document.getElementById("R" + stratname).innerHTML='<font color=#ff0000><b>No</b></font>';
		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( sdx_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=6;i<=14;i++)
			document.getElementById("CB" + sdx_list[i]).checked = !document.getElementById("CB" + sdx_list[i]).checked;
		break;
	case 3 :
		for(i=15;i<=26;i++)
			document.getElementById("CB" + sdx_list[i]).checked = !document.getElementById("CB" + sdx_list[i]).checked;
		break;
	case 4 :
		for(i=27;i<=28;i++)
			document.getElementById("CB" + sdx_list[i]).checked = !document.getElementById("CB" + sdx_list[i]).checked;
		break;
	case 5 :
		document.getElementById("CBURT").checked = !document.getElementById("CBURT").checked;
		document.getElementById("CBHUR").checked = !document.getElementById("CBHUR").checked;
		document.getElementById("CBBUG").checked = !document.getElementById("CBBUG").checked;
	}
}
