/*-----------------------------------------------------------------------
	This script is freeware. Use and abuse it as you see fit.
	However, your comments on how it could be improved would be more
	appreciated.
	Andrew Stuart, 23 May 2005
-----------------------------------------------------------------------*/
var stage = 0;
var ck=0;
var print_version = false;

// 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]];

// Default board to copy actual boards into. Not found a shorter way to declare and initialize
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],	// Something to store the board in in case the user
			[0,0,0,0,0,0,0,0,0],	// makes a correction on their numbers and then
			[0,0,0,0,0,0,0,0,0],	// changes their minds. Need to put the nums back.
			[0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0],
			[0,0,0,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],	// Something to store the board in in so the user
			[0,0,0,0,0,0,0,0,0],	// can step back one go
			[0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0],
			[0,0,0,0,0,0,0,0,0],
			[0,0,0,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 g1 = [[0,0,0,0,0,0,2,0,0],  // Phil Jackson, hidden pairs
		  [0,5,8,0,0,6,0,0,0],
		  [6,0,0,3,0,0,0,8,5],
		  [0,1,0,4,7,5,6,0,0],
		  [9,4,6,0,0,0,5,3,7],
		  [5,0,7,6,3,9,1,4,0],
		  [7,6,0,0,0,8,0,0,0],
		  [0,3,0,9,0,7,8,1,0],
		  [0,0,9,0,0,3,0,0,0]];
/*

var g1 = [[0,0,8,0,7,0,0,3,0],	// James Shute 11/6/05 bug
		  [3,5,0,4,0,8,0,7,9],
		  [0,0,0,0,0,1,6,0,0],
		  [4,8,7,0,0,0,0,0,0],
		  [9,3,5,0,0,0,8,4,7],
		  [0,2,0,8,4,7,3,9,5],
		  [0,0,9,2,0,0,0,0,0],
		  [8,1,0,0,0,9,0,0,3],
		  [0,6,3,0,8,0,9,0,0]];*/

/*
var g1 = [[0,0,0,0,8,3,4,0,0],		// David Filmer error
		 [3,0,0,0,0,4,8,2,1],
		 [7,0,0,0,0,0,0,0,0],
		 [0,0,9,4,0,1,0,8,3],
		 [0,0,0,0,0,0,0,0,0],
		 [4,6,0,5,0,7,1,0,0],
		 [0,0,0,0,0,0,0,0,7],
		 [1,2,5,3,0,0,0,0,9],
		 [0,0,7,2,4,0,0,0,0]]; */
/*
var g1 = [[0,1,0,4,2,0,0,0,5],		// Gentle
	      [0,0,2,0,7,1,0,3,9],
		  [0,0,0,0,0,0,0,4,0],
		  [2,0,7,1,0,0,0,0,6],
		  [0,0,0,0,4,0,0,0,0],
		  [6,0,0,0,0,7,4,0,3],
		  [0,7,0,0,0,0,0,0,0],
		  [1,2,0,7,3,0,5,0,0],
		  [3,0,0,0,8,2,0,7,0]]; */


var g2 = [[0,0,0,4,0,1,6,2,0],
		  [4,0,0,8,6,0,0,0,0],
		  [0,0,0,0,0,0,0,0,9],
		  [0,3,0,0,0,8,7,0,0],
		  [1,0,5,0,0,0,3,0,6],
		  [0,0,6,5,0,0,0,4,0],
		  [2,0,0,0,0,0,0,0,0],
		  [0,0,0,0,8,3,0,0,7],
		  [0,9,3,7,0,4,0,0,0]];


var g3 = [[0,0,0,3,7,0,1,8,6],		// Moderate
		 [0,0,0,0,0,0,4,0,0],
		 [7,3,0,0,0,0,0,2,9],
		 [0,0,6,0,2,0,0,5,0],
		 [0,0,0,9,0,8,0,0,0],
		 [0,0,0,0,1,0,3,0,0],
		 [4,6,0,0,0,0,0,9,5],
		 [0,0,7,0,0,0,0,0,0],
		 [8,1,9,0,6,7,0,0,0]];

var g4 = [[0,0,6,2,0,1,0,0,0],		// Moderate
	      [8,0,0,0,0,0,0,7,1],
		  [0,0,1,7,0,0,0,3,2],
		  [0,0,7,0,3,0,0,4,0],
		  [0,5,0,0,0,0,0,8,0],
		  [0,8,0,0,4,0,7,0,0],
		  [4,6,0,0,0,5,8,0,0],
		  [1,7,0,0,0,0,0,0,4],
		  [0,0,0,4,0,6,5,0,0]];

var g5 =   [[0,6,0,8,0,0,7,3,0],
			[3,0,0,0,2,0,8,0,6],
			[1,0,0,0,4,0,0,0,0],
			[0,4,2,0,0,3,0,8,0],
			[0,0,0,0,6,0,0,0,0],
			[0,1,0,5,0,0,6,2,0],
			[0,0,0,0,5,0,0,0,9],
			[7,0,6,0,3,0,0,0,5],
			[0,3,1,0,0,7,0,6,0]];

var g6 = [[0,0,1,9,0,0,0,0,8],		// Tough
	      [6,0,0,0,8,5,0,3,0],
		  [0,0,7,0,6,0,1,0,0],
		  [0,3,4,0,9,0,0,0,0],
		  [0,0,0,5,0,4,0,0,0],
		  [0,0,0,0,1,0,4,2,0],
		  [0,0,5,0,7,0,9,0,0],
		  [0,1,0,8,4,0,0,0,7],
		  [7,0,0,0,0,9,2,0,0]];

var g7 = [[7,3,0,0,0,4,6,0,0],		// Fiendish
		  [0,9,4,0,0,2,8,0,0],
		  [0,2,0,0,0,0,0,0,0],
		  [0,0,0,4,3,0,2,0,7],
		  [0,0,0,0,0,0,0,0,0],
		  [3,0,2,0,7,8,0,0,0],
		  [0,0,0,0,0,0,0,5,0],
		  [0,0,8,9,0,0,7,3,0],
		  [0,0,6,1,0,0,0,8,4]];

var g8 = [[0,0,0,0,0,1,0,7,0],		// Diabolical
		 [0,0,0,4,0,0,0,0,5],
		 [1,0,0,0,3,2,4,0,8],
		 [0,0,9,8,0,0,5,0,1],
		 [8,0,0,0,5,0,0,0,9],
		 [4,0,5,0,0,3,2,0,0],
		 [7,0,3,1,8,0,0,0,6],
		 [5,0,0,0,0,6,0,0,0],
		 [0,1,0,3,0,0,0,0,0]];

var g9 = [[0,9,0,7,0,0,8,6,0],	// Diabolical
		  [0,3,1,0,0,5,0,2,0],
		  [8,0,6,0,0,0,0,0,0],
		  [0,0,7,0,5,0,0,0,6],
		  [0,0,0,3,0,7,0,0,0],
		  [5,0,0,0,1,0,7,0,0],
		  [0,0,0,0,0,0,1,0,9],
		  [0,2,0,6,0,0,3,5,0],
		  [0,5,4,0,0,8,0,7,0]];

var g10 = [[2,5,8,1,0,4,0,3,7], // test of final pairs check
		  [9,3,6,8,2,7,5,1,4],
		  [4,7,1,5,3,0,2,8,0],
		  [7,1,5,2,0,3,0,4,0],
		  [8,4,9,6,7,5,3,2,1],
		  [3,6,2,4,1,0,0,7,5],
		  [1,2,4,9,0,0,7,5,3],
		  [5,9,3,7,4,2,1,6,8],
		  [6,8,7,3,5,1,4,9,2]];


var g11 = [[0,8,0,0,0,0,4,9,5],  // Andrew Pepperdine, hard pairs problem
		  [5,0,1,8,4,9,3,0,2],
		  [9,2,4,3,5,0,8,0,1],
		  [0,3,0,5,0,1,6,0,0],
		  [0,1,5,0,0,0,7,0,0],
		  [0,0,9,4,0,0,5,1,0],
		  [0,9,6,7,2,4,1,5,0],
		  [1,4,2,6,0,5,9,0,7],
		  [7,5,0,0,0,0,2,4,6]];

var g12   = [[7,0,0,0,0,5,6,2,0],	// Andy Pepperdine
			[0,0,0,4,0,0,3,0,0],
			[0,0,1,0,3,0,0,0,0],
			[6,0,7,0,0,8,0,0,0],
			[4,0,0,1,0,3,0,0,8],
			[0,0,0,0,0,0,1,0,4],
			[0,0,0,0,2,0,4,0,0],
			[0,0,8,0,0,4,0,0,0],
			[0,7,4,8,0,0,0,0,5]];


var some_changes = false;
var catchup = false;
var firsttime = true;
var some_saved = false;
var showhints = true;

function bit_count( b )
{
    var n = 0;
	if ( !b ) return 0;
    do { ++n; } while ( b &= (b-1) );
    return  n;
}
function IsNumeric(s)   //  check for valid numeric strings
{
	var strValidChars = "123456789";
	var strChar;
	var blnResult = true;

	if (s.length == 0) return false;

	//  test strString consists of valid characters listed above
	for (i = 0; i < s.length && blnResult == true; i++)
	{
	   strChar = s.charAt(i);
	   if (strValidChars.indexOf(strChar) == -1)
	      blnResult = false;
	}
	return blnResult;
}
/*---------------------------------------------------------------------*/
/* Draws the content of a square on the board							*/
/*---------------------------------------------------------------------*/
function set_square( x, y, val, setup )
{
	var t, s, nt;
	var oRow;
	var sq_col = ['black','red','blue','blue'];
	var sq_siz = ['8pt','14pt','14pt','14pt','8pt','18pt','18pt','18pt'];

	// Get the table cell name out using the coordinates
	nt = ( y < 3 ) ? "A" : (( y < 6 ) ? "B" : "C");
	nt = nt + (( x < 3 ) ? "1" : (( x < 6 ) ? "2" : "3"));

	t = document.getElementById(nt);
	oRow = t.rows[y % 3];
	if( (setup==0 && showhints) || setup > 0 )
		 oRow.cells[x % 3].innerHTML = val;	// Assign the new value to the cell
	else oRow.cells[x % 3].innerHTML = '&nbsp;';	// Assign the new value to the cell
	oRow.cells[x % 3].style.color = (print_version) ? 'black' : sq_col[setup];
	oRow.cells[x % 3].style.fontSize = sq_siz[(print_version) ? setup+4 : setup];
	oRow.cells[x % 3].style.backgroundColor = ( setup == 3 ) ? '#ff0000' : ((print_version) ? '#ffffff' : '#ddeeff');
	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( x, y, deduct )
{
	var lable, c, i, modfact=3;
	lable = '';
	c = 0;
	mask[x][y] -= deduct;
	if( bit_count(mask[x][y]) < 5 ) modfact = 2;
	for( i=0;i<9;i++ ) if( mask[x][y] & (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
	}
	some_changes = true;
	set_square(y,x,lable,0);
}
function change_hints()
{
	showhints = !showhints;
	for(j=0;j<9;j++)
		for(i=0;i<9;i++)
			if( g[j][i] == 0 )
				lable_square( j, i, 0 );
}
/*---------------------------------------------------------------------*/
/* Sets the board up from scratch and draws it. Called from onLoad */
/*---------------------------------------------------------------------*/
function load_board(pversion)
{
	var i, j, t, s, nt;
	var bd = location.search;
	var oRow, sRow, par;
	stage = 0;
	print_version = pversion;

	if( print_version ) par = parent.opener.document;

	for(j=0;j<9;j++)
		for(i=0;i<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 )
				// hard coded some example boards - not efficient but its just an example page
				// note: proof that C is better than javascript,
				// i wanted to just say g = g1, but ITS A POINTER! Damn it. I wanted the
				// whole array to copy like C but, no, there's no strong typing so you have
				// to watch what it does. In this case I have to copy each element individually.
				switch( document.forms.DataEntry.elements["Example"].selectedIndex ) {
				case 0 : g[j][i] = g1[j][i]; break;
				case 1 : g[j][i] = g2[j][i]; break;
				case 2 : g[j][i] = g3[j][i]; break;
				case 3 : g[j][i] = g4[j][i]; break;
				case 4 : g[j][i] = g5[j][i]; break;
				case 5 : g[j][i] = g6[j][i]; break;
				case 6 : g[j][i] = g7[j][i]; break;
				case 7 : g[j][i] = g8[j][i]; break;
				case 8 : g[j][i] = g9[j][i]; break;
				case 9 : g[j][i] = g10[j][i]; break;
				case 10 : g[j][i] = g11[j][i]; break;
				case 11 : g[j][i] = g12[j][i]; break;
				}
			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;	// This is the key: numbers 1-9 in bits = 511,
									// so its saying on the empty board all squares have all numbers
				if( !print_version )
					set_square(i,j,"&nbsp;", 0);
				else
				{
					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];
					oRow.cells[i % 3].innerHTML = sRow.cells[i % 3].innerHTML;
			//		alert(sRow.cells[i % 3].innerHTML);
				}
			}
		}
	firsttime = false;
}
/*---------------------------------------------------------------------*/
/* Does what it says on the tin		*/
/*---------------------------------------------------------------------*/
function clear_board()
{
	var t,x,y,nt;
	var oRow;
	stage=0;
	t = document.getElementById("TestT");
	t.rows[0].cells[0].style.backgroundColor = "black";
	t.rows[1].cells[0].style.backgroundColor = "black";
	t.rows[2].cells[0].style.backgroundColor = "black";
	t.rows[3].cells[0].style.backgroundColor = "black";
	t.rows[4].cells[0].style.backgroundColor = "black";
	t.rows[5].cells[0].style.backgroundColor = "black";
	document.getElementById("backstep").className = 'GButton';
	for(x=0;x<9;x++)
		for(y=0;y<9;y++)
		{
			// get the call name again. maybe I should have used a better naming convention ;-)
			nt = ( y < 3 ) ? "A" : (( y < 6 ) ? "B" : "C");
			nt = nt + (( x < 3 ) ? "1" : (( x < 6 ) ? "2" : "3"));
			t = document.getElementById(nt);
			oRow = t.rows[y % 3];
			oRow.cells[x % 3].style.backgroundColor = '#ddeeff';
			oRow.cells[x % 3].style.color = 'black';
			oRow.cells[x % 3].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
		}
	document.getElementById("counter").innerHTML = ck;
}
function save_board()
{
	var i, j;
	for( j in g )
		for( i in g[j] ) save[j][i] = g[j][i];
	document.getElementById("reload").className = "SButton";
	some_saved = true;
	alert("Current Board Saved");
}
function reload_board()
{
	var i, j;
	if( some_saved == false ) return;
	clear_board();
	for( j in g )
		for( i in g[j] )
		{
			g[j][i] = save[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;	// This is the key: numbers 1-9 in bits = 511,
									// so its saying on the empty board all squares have all numbers
				set_square(i,j,"&nbsp;",0);
			}
		}
}
/*----------------------------------------------------------------------*/
/* 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;
	for( y=0;y<9;y++ )
		for( x=0;x<9;x++ )	// for every square on the board
		{
			for(i=0;i<9;i++,ck++)	// 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
					some_changes = true;
				}
		}
}

function basic_test( which_part )
{
	var changes;
	var a,b,i,j,xx,zz,yy,x,y,n,c,bb,cc;
	var ax = new Array(12);
	var ay = new Array(12);

	if( which_part == 1 || which_part== 3 )
	{

		/*----------------------------------------------------------------------*/
		/* Point of test_row_col is to 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++,ck++ ) // 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 );
				}
				else ck++;

		/*----------------------------------------------------------------------*/
		/* The other check we must do on the rows/columns is to see if there	*/
		/* is only once occurance of a number									*/
		/*----------------------------------------------------------------------*/
		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( c=k=0;k<9;k++,ck++ )  // check the row
							if( !g[y][k] && (mask[y][k] & (1 << n)) ) c++;
						if( c==1 )
						{
							mask[y][x] = (1 << n);
							lable_square(y,x,0);
						}
						for( c=k=0;k<9;k++,ck++ )  // check the column
							if( !g[k][x] && (mask[k][x] & (1 << n)) ) c++;
						if( c==1 )
						{
							mask[y][x] = (1 << n);
							lable_square(y,x,0);
						}
					}
					else ck++;
				}
				else ck++;

	}
	if( which_part == 2 || which_part== 3 )
	{


		/*----------------------------------------------------------------------*/
		/* Point of test_box is to 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)		// Okay, 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++,ck++)
									if( g[zz][yy]==0 && (mask[zz][yy] & (1 << (g[i][j]-1))) )
										lable_square( zz, yy, (1 << (g[i][j]-1)) );


		/*----------------------------------------------------------------------*/
		/* 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++,ck++)
						{
							// if the square is unknown but the bit array has the current number
							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...
					{
						g[ay[0]][ax[0]] = n+1;				// Put the solution on the board
						mask[ay[0]][ax[0]] = 0;				// .. and wipe the mask
						set_square(ax[0],ay[0],g[ay[0]][ax[0]],2);	// .. and draw the square
						some_changes = true;
					}

				}
			}
	}
}
/*----------------------------------------------------------------------*/
/* pointing_pairs														*/
/*----------------------------------------------------------------------*/
function pointing_pairs()
{
	var bb,cc,n,i,j,c;
	var x = new Array(12);
	var y = new Array(12);

	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++,ck++)
					{
						// if the square is unknown but the bit array has the current number
						if( g[i][j]==0 && (mask[i][j] & (1 << n)) )
						{
							x[c] = j;	// Store the coordinates
							y[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
					}


				// New check - Pointing Pairs
	//				alert('(' + (n*1+1) + ') ' + x[0] + ',' + y[0] + ' || ' + x[1] + ',' + y[1]);
				if( c==2 && x[0]==x[1] )  // .. pointing along a column
					for(i=0;i<9;i++,ck++)
						if( g[i][x[0]]==0 && i!=y[0] && i!=y[1] && (mask[i][x[0]] & (1 << n)) )
							{ catchup=true; lable_square( i,x[0], (1 << n) ); }  // .. we don't need it in the bit array

				if( c==2 && y[0]==y[1] )  // .. pointing along a row
					for(i=0;i<9;i++,ck++)
						if( g[y[0]][i]==0 && i!=x[0] && i!=x[1] && (mask[y[0]][i] & (1 << n)) )
							{ catchup=true; lable_square( y[0],i, (1 << n) ); }	// bit array

 				// New check - Pointing triples
				if( c==3 && x[0]==x[1] && x[0]==x[2] && x[1]==x[2] )  // .. pointing along a column
					for(i=0;i<9;i++,ck++)
						if( g[i][x[0]]==0 && i!=y[0] && i!=y[1] && i!=y[2] && (mask[i][x[0]] & (1 << n)) )
							{ catchup=true; lable_square( i,x[0], (1 << n) ); }	// bit array

				if( c==3 && y[0]==y[1] && y[0]==y[2] && y[1]==y[2] )  // .. pointing along a row
					for(i=0;i<9;i++,ck++)
						if( g[y[0]][i]==0 && i!=x[0] && i!=x[1] && i!=x[2] && (mask[y[0]][i] & (1 << n)) )
							{ catchup=true; lable_square( y[0],i, (1 << n) ); }	// bit array
			}
		}
}
/*-------------------------------------------------------------------------*/
/* 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. 															   */
/*-------------------------------------------------------------------------*/
function hidden_pairs()
{
	var x,y,n,m,i,bb,cc;
	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++) pos[n] = 0;
			for(n=0;n<9;n++)	// .. check each number
			{
				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++,ck++,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++,ck++,i++)
								if( pos[n] & (1 << i) && bit_count(mask[y][x]) > 2 )
								{
							//		alert(n + ' ' + m);
									mask[y][x] = (1 << n) + (1 << m);
									lable_square( y, x, 0 );
									catchup=true;
								}

					}
		}

}
/*----------------------------------------------------------------------*/
/* Purpose of pair_test1 is to look for pairs of numbers, eg 3-7 and 3-7 */
/* in the same box. Since both numbers MUST be on both boxes they can   */
/* be eliminated from the rest of the box								*/
/*----------------------------------------------------------------------*/
function pair_test1_old()
{
	var bb,cc,n,m,i,j,k,c,h,a,b;
	var mbox = new Array(9);
	var cordX = new Array(9);
	var cordY = new Array(9);
	var cnt = 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)
		{
			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];
					cordX[k] = i;
					cordY[k++] = j;
				}

			for(n=0;n<9;n++)	// .. check each pair in the 1D box array
				for(m=n+1;m<9;m++)
					if( bit_count(mbox[n])==2 && mbox[n] == mbox[m] ) // Is the box unknown AND a pair?
					{
						// This block checks the BOX the pair resides in...
						for(i=0;i<9;i++) // Look for other squares
						{
							if( i!=n && i!=m && (mbox[i] & mbox[n]) )  // .. number is present
							{
								h = (mbox[i] & mbox[n]);
							//	alert("here n=" + n + " m=" + m + " i=" + i + " mbox[i]=" + mbox[i]);
								mbox[i] -= h; // remove that number
								lable_square( cordX[i],cordY[i], h );
							}
						}
					}
		}
}
/*----------------------------------------------------------------------*/
/* MAIN PAIR TEST														*/
/*----------------------------------------------------------------------*/
function main_pair_test()
{
	var bb,cc,n,m,i,j,k,a,b,y,x1,x2,h;
	var mbox = new Array(9);
	var cordX = new Array(9);
	var cordY = 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   */
	/* boxes 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++,ck++)
				{
					mbox[k] = mask[i][j];
					cordX[k] = i;
					cordY[k++] = j;
				}
			for(n=0;n<9;n++) cnt[n]=0;
			for(i=0;i<9;i++)	// for each square in the box
				for(n=0;n<9;n++)	// ..and each number
					if( mbox[i] & (1 << n) ) cnt[n]++;  // count occurances

			for(a=0;a<8;a++)	// .. check each pair in the 1D box array
				for(b=a+1;b<9;b++,ck++)
				{
					for(k=n=0;n<9;n++)	// for each number
						if( cnt[n]==2 && (mbox[a] & (1 << n)) && (mbox[b] & (1 << n)) )	k++;	// if it occurs twice..count it
					if( k==2 ) // two pairs of numbers occuring just twice
						for(n=0;n<9;n++)	// for each number
							if( cnt[n]==2 )		// if it occurs twice..
								for(m=0;m<9;m++)	// remove all other numbers
								{
									if( cnt[m]>2 && (mbox[a] & (1 << n)) && (mbox[a] & (1 << m)) )  // that appear more than twice
									{
								//		alert("here n=" + n + " m=" + m + " a=" + a + " mbox[a]=" + mbox[a] + " cnt[m]=" +cnt[m]);
										mbox[a] -= (1 << m); // remove that number
										lable_square( cordX[a],cordY[a], (1 << m) );
										catchup=true;
									}
									if( cnt[m]>2 && (mbox[b] & (1 << n)) && (mbox[b] & (1 << m)) )  // that appear more than twice
									{
								//		alert("here n=" + n + " m=" + m + " b=" + b + " mbox[b]=" + mbox[b] + " cnt[m]=" +cnt[m]);
										mbox[b] -= (1 << m); // remove that number
										lable_square( cordX[b],cordY[b], (1 << m) );
										catchup=true;
									}
								}
				}


		}

	/*----------------------------------------------------------------------*/
	/* Purpose of pair_test2 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 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++,ck++)
			{
				// 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++,ck++)
					{
						h = (mask[y][i] & mask[y][x1]);
						if( i!=x1 && i!=x2 && !g[y][i] && h )
						{
							lable_square( y,i, h ); // remove that number
							catchup=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++,ck++)
					{
						h = (mask[i][y] & mask[x1][y]);
						if( i!=x1 && i!=x2 && !g[i][y] && h )
						{
							lable_square( i,y, h );
							catchup=true;
						}
					}
			}
}
function locked_pair( a,b,x,y )
{
	var i,j;
	if( a == x ) return true;
	if( b == y ) return true;
//	alert(a + '-' + b + ' ' + x + '-' + y);
	for(i=0;i<9;i+=3)
		for(j=0;j<9;j+=3,ck++)
			if( a>=i && a<i+3 && x>=i && x<i+3
			&&	b>=j && b<j+3 && y>=j && y<j+3 ) return true;
	return false;
}
/*----------------------------------------------------------------------*/
/* See http://www.scanraid.com/remotepairs.htm for a full explanation	*/
/*----------------------------------------------------------------------*/
function remote_pair_test()
{
	var x,xx,y,yy,x1,x2,y1,y2,h,z1,z2,d,i,z;
	var sqlist = new Array(2);		// Pair list
	var pl=0;
	var sq=0;
	var oddness = new Array(20);
//	var abet = "ABCDEFGHIJLMNOP";
	sqlist[0] = new Array(20);	//	X of Square List
	sqlist[1] = new Array(20);	//	Y of Square List

	for(y=0;y<9;y++)
		for(x=0;x<9;x++)	// For every square...
			if( bit_count(mask[y][x])==2 )	// find a pair
			{
				sq = 0;
				sqlist[0][sq] = x;
				sqlist[1][sq++] = y;
				for(yy=0;yy<9;yy++)
					for(xx=0;xx<9;xx++,ck++)	// Find all other pairs..
						if( !(x==xx && y==yy) && mask[y][x] == mask[yy][xx] )
						{
			//				alert(sq + ' ' + xx + ' ' + yy);
							sqlist[0][sq] = xx;
							sqlist[1][sq++] = yy;
						}
				if( sq > 1 ) // At least 2 occurances of this pair
				{
					// Start the walk from the point of view of the start square
					for(i=0;i<sq;i++) oddness[i] = 99;  // set all to unknown
					oddness[0] = 0;  // Home Square
				//	sdebug = '';
					for(d=0;d<sq;d++)  		// maximum distance is number of pairs - sq
					{
						for(z1=0;z1<sq-1;z1++)
							for(z2=z1+1;z2<sq;z2++)
							{
						//		sdebug = sdebug + abet.charAt(z1) + '-' + abet.charAt(z2) + ' ' + oddness[z1] + '=' + d + ' & ' + oddness[z2] + '=99<br>';
								if( oddness[z1] == d && oddness[z2] == 99 )
									if( locked_pair(sqlist[0][z1],sqlist[1][z1],sqlist[0][z2],sqlist[1][z2]) )
									{
								//		sdebug = sdebug + '#' + z1 + ' ' + z2 + ' >' + (d*1+1) + '<br>';
										oddness[z2] = d+1;  // One locked pair away from other
									}
								if( oddness[z2] == d && oddness[z1] == 99 )
									if( locked_pair(sqlist[0][z1],sqlist[1][z1],sqlist[0][z2],sqlist[1][z2]) )
									{
								//		sdebug = sdebug + '#' + z1 + ' ' + z2 + ' >' + (d*1+1) + '<br>';
										oddness[z1] = d+1;  // One locked pair away from other
									}
							}

					}
				//	for(i=0;i<sq;i++)
				//		sdebug = sdebug + sq + '> ' + abet.charAt(i) + ' ' + oddness[i] + ' ' + sqlist[0][i] + ',' + sqlist[1][i] + '<br>';


				//	sdebug = sdebug + '------<br>';
					for(z=1;z<sq;z++)
						if( oddness[z]!=99 && (oddness[z] % 2) == 1 )
						{
						//	alert('i=' + i + ' s=' + s + ' road:' + road);
							x1 = sqlist[0][0];
							y1 = sqlist[1][0];
							x2 = sqlist[0][z];
							y2 = sqlist[1][z];
							if( y1!=y2 && x1!=x2 )
							{
					//			sdebug = sdebug + x1 + ',' + y1 + ' ' + x2 + ',' + y2 + '>g ' + g[y1][x2] + ' g' + g[y2][x1] + '<br>';
								h = (mask[y1][x1] & mask[y1][x2]);
								if( !g[y1][x2] && h ) // Its unknown .. but one of the numbers is
									{ catchup=true; lable_square( y1,x2, h ); } // remove that number

								h = (mask[y2][x1] & mask[y1][x1]);
								if( !g[y2][x1] && h )
									{ catchup=true; lable_square( y2,x1, h ); } // remove that number
							}
						}
				//	document.getElementById("debug").innerHTML = sdebug;
				//	alert(sq);
				}
			}
}
/*--------------------------------------------------------------------------*/
/* See http://www.scanraid.com/BoxLineReduction.htm for a full explanation	*/
/*--------------------------------------------------------------------------*/
function line_box_reduction()
{
	var x,n,c=0,xx,yy,y1,y2,col;

	for(y1=0;y1<9;y1+=3)	// for all boxes
		for(y2=0;y2<3;y2++)	// for all rows in box
		{
			for(n=0;n<9;n++)	// for all numbers
			{
				for(c=x=0;x<9;x++,ck++)	// scan along the line
				{
					if( mask[y1+y2][x] & (1 << n)) c |= (x<3)?1:((x<6)?2:4);
					if( g[y1+y2][x]==n+1 ) c = 9; // abort if n found on line
				}
				if( c==1 || c==2 || c==4 ) // the set of n exists in 1 box
				{
					col = (c==1)?0:((c==2)?3:6);
					for(yy=y1;yy<y1+3;yy++)	// ..check every other cell
						for(xx=col;xx<col+3;xx++,ck++)
							if( !g[yy][xx] && yy!=y1+y2 && (mask[yy][xx] & (1 << n)) )	// and the n is present
								{ catchup=true; lable_square( yy, xx, (1 << n) ); }	// bit array

				}
				// Switch X and Y to do columns as well
				for(c=x=0;x<9;x++,ck++)	// scan along the line
				{
					if( mask[x][y1+y2] & (1 << n)) c |= (x<3)?1:((x<6)?2:4);
					if( g[x][y1+y2]==n+1 ) c = 9; // abort if n found on line
				}
				if( c==1 || c==2 || c==4 ) // the set of n exists in 1 box
				{
					col = (c==1)?0:((c==2)?3:6);
					for(yy=y1;yy<y1+3;yy++)	// ..check every other cell
						for(xx=col;xx<col+3;xx++,ck++)
							if( !g[xx][yy] && yy!=y1+y2 && (mask[xx][yy] & (1 << n)) )	// and the n is present
								{ catchup=true; lable_square( xx, yy, (1 << n) ); }	// bit array

				}
			}
		}
}
/*----------------------------------------------------------------------*/
/* Function to check for conflicts with the rules						*/
/*----------------------------------------------------------------------*/
function sanity_check()
{
	var bb,cc,n,i,j,c,x,y,zz,yy;

	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++,ck++ ) // 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
					}
					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
					}
				}
			}


	for(bb=0;bb<9;bb+=3)			// Okay, 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++,ck++)
								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
								}
}
/* Function to reset the board to its normal blue background */
function blue_board()
{
	var x,y,done=0,nt;
	for(y=0;y<9;y++)		// Redraw the board to clear any user highlighting
		for(x=0;x<9;x++,ck++)
		{
			nt = ( y < 3 ) ? "A" : (( y < 6 ) ? "B" : "C");
			nt = nt + (( x < 3 ) ? "1" : (( x < 6 ) ? "2" : "3"));
			t = document.getElementById(nt);
			oRow = t.rows[y % 3];
			oRow.cells[x % 3].style.backgroundColor = '#ddeeff';
			if( g[y][x]>0 ) done++;
		}
	return done;
}
/*----------------------------------------------------------------------*/
/* Function to run the steps above in one go. Resets the board colors	*/
/*----------------------------------------------------------------------*/
function take_step()
{
	var i,j,done=0,t;
	done = blue_board();
	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
	{
		alert("Fantastico! Sudoki risolto!");
	}
	else
	{
		for( x in g )
			for( y in g[x] ) last[x][y] = mask[x][y];

		stage = (stage==6) ? 1 : stage + 1;
	/*	if( stage == 1 ) some_changes = false;
		if( stage == 1 ) { test_row_col(); test_singles(); }
		if( stage == 2 ) { test_box(); check_box(); check_for_single(); test_row_col(); }
		if( stage == 3 ) { pair_test1(); pair_test2(); if( some_changes ) { check_for_single(); test_row_col(); test_singles(); check_for_single(); test_box(); check_box(); } }
		if( stage == 4 ) { hidden_pairs(); if( some_changes ) { check_for_single(); test_row_col(); test_singles(); check_for_single(); test_box(); check_box(); }} //check_for_single(); } //alert("ccc"); test_box(); }
		if( stage == 5 ) { line_box_reduction(); }
		if( stage == 6 ) { remote_pair_test();  } */

		if( stage == 1 ) { some_changes = false; catchup = false; }
		if( stage == 1 ) basic_test(1);
		if( stage == 2 ) basic_test(2);
		if( catchup    ) basic_test(3);

		catchup = false;

		if( stage == 3 ) { pointing_pairs();		}
		if( stage == 4 ) { hidden_pairs(); main_pair_test(); }
		if( stage == 5 ) { line_box_reduction();  }
		if( stage == 6 ) { remote_pair_test();	}

		check_for_single();
		sanity_check();
		for( x in g )
			for( y in g[x] ) orig[x][y] = mask[x][y];

		t = document.getElementById("TestT");
		t.rows[0].cells[0].style.backgroundColor = (stage==1) ? "#777700" : "black";
		t.rows[1].cells[0].style.backgroundColor = (stage==2) ? "#777700" : "black";
		t.rows[2].cells[0].style.backgroundColor = (stage==3) ? "#777700" : "black";
		t.rows[3].cells[0].style.backgroundColor = (stage==4) ? "#777700" : "black";
		t.rows[4].cells[0].style.backgroundColor = (stage==5) ? "#777700" : "black";
		t.rows[5].cells[0].style.backgroundColor = (stage==6) ? "#777700" : "black";
		document.getElementById("backstep").className = 'SButton';
		document.getElementById("counter").innerHTML = ck;
		if( stage==6 && some_changes == false )
			alert("Mi dispiace... Sudoku non risolto!");
	}
}
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 )
			{
				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 = '';
			}
		}
	stage = (stage==1) ? 6 : stage - 1;
	t = document.getElementById("TestT");
	t.rows[0].cells[0].style.backgroundColor = (stage==1) ? "#777700" : "black";
	t.rows[1].cells[0].style.backgroundColor = (stage==2) ? "#777700" : "black";
	t.rows[2].cells[0].style.backgroundColor = (stage==3) ? "#777700" : "black";
	t.rows[3].cells[0].style.backgroundColor = (stage==4) ? "#777700" : "black";
	t.rows[4].cells[0].style.backgroundColor = (stage==5) ? "#777700" : "black";
	t.rows[5].cells[0].style.backgroundColor = (stage==6) ? "#777700" : "black";

	document.getElementById("backstep").className = 'GButton';
	blue_board();
}
function run_all()
{
	var i,j,done=0,t;

	do
	{
		some_changes = false;
		test_row_col();
		test_singles();
		test_box();
		check_box();
		pair_test1();
		pair_test2();
		line_box_reduction();
		check_for_single();

		for(done=j=0;j<9;j++)		// Redraw the board to clear any user highlighting
			for(i=0;i<9;i++)
				if( g[i][j]>0 ) done++;
	}
	while( some_changes );
	if( done == 81 )	// If the number of solutions = 81, we're all done
		alert("Fantastico! Sudoku risolto!");
	else
		alert("No more logical steps to take - you have to enter a number somewhere and then click 'Take Step'");
}
/*------------------------------------------------------------------------*/
/* Function to colour the board according to what the user has clicked on */
/*------------------------------------------------------------------------*/
function color_same(x,y)
{
	var t, i, j, nt;
	var oRow;

	for(j=0;j<9;j++)	// For each square on the board
	{
		for(i=0;i<9;i++)
		{
			// Get the table cell name
			nt = ( j < 3 ) ? "A" : (( j < 6 ) ? "B" : "C");
			nt = nt + (( i < 3 ) ? "1" : (( i < 6 ) ? "2" : "3"));
			t = document.getElementById(nt);
			oRow = t.rows[j % 3];
			if( g[y][x]==0 )	// If user clicked on an unknown square..
			{
				if( g[j][i]>0 && (mask[y][x] & (1 << (g[j][i]-1))) )
					oRow.cells[i % 3].style.backgroundColor = '#ddccaa';
				else if( mask[j][i] & mask[y][x] )
					oRow.cells[i % 3].style.backgroundColor = '#ffeedd';
				else
					oRow.cells[i % 3].style.backgroundColor = '#ddeeff';
			}
			else // If user clicked on a known number..
			{
				if( (x==i && y==j) || g[j][i]==g[y][x] ) // Highlight other occurances of that number
					oRow.cells[i % 3].style.backgroundColor = '#ddccaa';
				else if( (mask[j][i] & (1 << (g[y][x]-1))) )  // .. and where its possible
					oRow.cells[i % 3].style.backgroundColor = '#ffeedd';
				else	// .. otherwise its the normal background color
					oRow.cells[i % 3].style.backgroundColor = '#ddeeff';
			}
		}
	}
}
/*-----------------------------------------------------------------------*/
/* Function to put a number on the board from the data entry form 		 */
/*-----------------------------------------------------------------------*/
function add_data(t)
{
	var x,y;
	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 )
	}
	sanity_check();
}
function email_board()
{
	var x,y,done=0;
	var board = 'bd=';
	for(y=0;y<9;y++)		// Redraw the board to clear any user highlighting
		for(x=0;x<9;x++)
		{
			if( g[y][x]>0 ) done++;
			board = board + g[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=300,screenY=200,width=500,height=250');
    	if (!SGW.opener) SGW.opener = self;
	}
}
function print_board()
{
	var x,y,done=0;
	var board = 'bd=';
	for(y=0;y<9;y++)		// Redraw the board to clear any user highlighting
		for(x=0;x<9;x++)
			board = board + g[y][x];

	SGW = window.open('SudokuPrintable.htm?' + board,'_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=600,height=600');
	if (!SGW.opener) SGW.opener = self;
}