/*-----------------------------------------------------------------------
	Copyrighted Andrew Stuart, 2005-2009, andrew@scanraid.com
	First version: 23 May 2005
	This version: 1.60, 13-JUN-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 = sud_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 gex=["000105000140000670080002400063070010900000003010090520007200080026000035000409000", // Easiest
"000004028406000005100030600000301000087000140000709000002010003900000507670400000", // Gentle
"400010000000309040070005009000060021004070600190050000900400070030608000000030006", // Moderate */
"309000400200709000087000000750060230600904008028050041000000590000106007006000104", // Tough
"000704005020010070000080002090006250600070008053200010400090000030060090200407000", // Diabolical
"000041000060000200000000000320600000000050041700000000000200300048000000501000000", // Easy 17 Clue
"002090300805000000100000000090060040000000058000000001070000200300500000000100000", // Hard 17 Clue
"000000000001900500560310090100600028004000700270004003040068035002005900000000000", // Naked Triples
"300000000970010000600583000200000900500621003008000005000435002000090056000000001", // Hidden Triple
"000921003009000060000000500080403006007000800500700040003000000020000700800195000", // Intersection Removeal
"294167835736080192158090476007010029029740518581029047902030754805070963073950281", // x-wing example
"123000587005817239987000164051008473390750618708100925076000891530081746810070352", // Simple Colouring Rule 2
"036210840800045631014863009287030456693584000145672398408396000350028064060450083", // Simple Colouring Rule 4
"004630500605401003370059640938060154457198362216345987043506019060903405509014036", // Simple Colouring Rule 5
"645010893738459621219638745597060184481975000326841579902080010803190000164020908", // y-wing example
"050030602642895317037020800023504700406000520571962483214000900760109234300240170", // SwordFish
"008003102002810306314260980923648700476351298185900634047030820209080500801700460", // X-Cycle (weak link)  #.....3..2..2.1.3...1..6..8.9.3..87....6...2....59..6.4.4..3..2...9.8.5..8..7.....
"723659481050834027004721305246193758507400003300570046960345072072900534435207009", // X-Cycle (strong link)  #...6..4.1.5...4.2....721..524..9...8.........3...7..469..345....7.9...3.4.5..7...
"506094003000086925892513647738629050154378296629451738987145362000960000000830009", // XY-Chain #5............86....9.51.64.7....9.5...43.82...2.4....8.87.45.6....96............9
"093824560085600002206075008321769845000258300578040296850016723007082650002507180", // 3D Medusa Rule 1 #.938.45....56.....2.6.7.....2..6..4....2.8....7..4..9.....1.7.3.....26....25.718.
"300052000250300010004607523093200805570000030408035060005408300030506084840023056", // 3D Medusa Rule 2 #3...5....25.3...1...46.75...9.2..8.5.7.....3.4.8..5.6...54.83...3...6.84....2...6
"290000830000020970000109402845761293600000547009045008903407000060030709050000384", // 3D Medusa Rule 3 #29.....3.....2..7....1.94.28..76.2..6.......7..9.45..89.34.7....6..3.....5.....84
"730490001002015037005237809800003014003040900460000003504369100000180305300570006", // 3D Medusa Rule 4 #7...9......2.15.....523.8.98......14..3...9..46......35.4.691.....18.3......7...6
"587412693206037800100008200002001748050724900714800500005240109001085400420170305", // 3D Medusa Rule 5 #5.7.1..9...6.3.8..1....82....2..17.8...724...7.48..5....52....9..1.8.4...2..7.3.5
"923407015876050924500200030769020140432000059185004260098042071207030486000708092", // 3D Medusa Rule 6 #9..4.7...876.5...4...2...3..6....1..43.....59..5....6..9...2...2...3.486...7.8..2
"024090008800402900719000240075804300240900587038507604082000059007209003490050000", // Jelly-Fish		# ....9...88..4.29..71.....4...58.43..2.......7..85.76...8.....59..72.9..34...5....
"760005804530400060849006050307060205256710003904050607423600570695007000178500026", // UR type 1  # .6...58.4...4......49..6.5.3.7...2..2...1...3..4...6.7.2.6..57......7...1.85...2.
"100480003070156492400370186729564318584031009010290745007040901040913067901020004", // UR type 2  # 1...8...3.7.1.6.9.....7....72..64.1.5.......9.1.29..45....4.....4.9.3.6.9...2...4
"100390004029000300000502800016000570900000006042000080000139000695000731231756008", // UR type 2b # 1..39...4.29...3.....5.2....1....57.9.......6.42....8....1.9.....5...73.2...56..8
"592178346063245089840936050006852904904617508085394600059481060400063890608029400", // UR type 4  # ..2.7.3...6........4.936.5....852...9.......8...394....5.481.6........9...8.2.4..
"200008001194762835000010042470000020009200100020000059658927010913654287742183596", // UR type 4b # 2....8..1.9.76........1..4247.....2...9...1...2.....5965..2........54.8.7..1....6
"617304800485010307923857641359040078164078530278030064592761483841003706736480010", // HUR type 1  # .....48..........79.38..6.1....4..78.64.7.53.27..3....5.2..14.38..........64.....
"400052008708300002900080040596127384187030256004568719840000005000003801000895400", // HUR type 2  # ....52...7.83.....9......4...612.3....7...2....4.687...4......5.....38.1...89....
"004302985080100006000800041900600500036950070057008693590000007000509060602700859", // HUR type 2b # ..4..29.5.8.1............419..6..5...3..5..7...7..8..359............9.6.6.27..8..
"400080009005904003009706548927341856004859001158672394543197682700400905090060407", // XYZ-Wing
"400052008708300002900080040596127384187030256004568719840000005000003801000895400", // APE		# ....52...7.83.....9......4...612.3....7...2....4.687...4......5.....38.1...89....
"620050030000920150015004000003000600180000075062000300001249700296785413040060592", // GXC	(weak link)	# 62..5..3....92.1....5..4.....3...6..18.....75..2...3.....2..7....6.85....4..6..92
"000602400002403600000080021070000840309040207045000030500060000003159780008204500", // ER  # ...6.24....24.36......8...1.7....84.3.9...2.7.45....3.5...6......31.97....82.4...
"010600000000103207400950006745869000829000465100524978600090004201406000004000680", // FXW  # .1..........1.32.74...5...67.58......29...46......49.86...9...42.14.6..........8.
"080000070001800009270961005100082700007413500008790003300248007800000200742000060", // FSF  # .8.....7...1.....92..961..51...82.....74.35.....79...33..248..78.....2...4.....6.
"900008503080020097006000004300406002060080359800203001700860205650070018008500006", // FSF Sashimi  # 9....8....8..2..97..6.....43..4.6..2.6..8..5.8..2.3..17.....2..65..7..1....5....6
"005907600090000080000830490010580000009000300000096010452018000030000040007400200", // AIC (Weak)	# ..5..76...9.....8....83.49..1.58......9...3......96.1..52.18....3.....4...74..2..
"103200400000010000804703020030570000765000394000039000040908005000040000912357846", // AIC (Strong) # 1.32..4......1....8..7.3.2....57....76.....94....39....4.9.8..5....4......2..78.6
"520800367709630050600725009006080700800056003002070600100542906090068500065007040", // AIC (off chain) # .2....3....963..5.6..7.5..9..6.8.7..8.......3..2.7.6..1..5.2..6.9..685....5....4.
"006019500907068043080000000804190000000645800000802904000006420540001607002984300", // Dual CFC  # ..6.195..9.7....43.8.......8.41........6.5........29.4.......2.54....6.7..298.3..
"092400018846312597100900002000601004610040080704809000200003006001064820460000070", // Triple CFC # .9.....1..463..5..1..9....2...6.1..4.1..4..8.7..8.9...2....3..6..1..482..6.....7.
"002006500400000023000002406978060312613729845245010679800900200320600054004200008", // Triple CFC + ALS.....65..4......23.....2..6978.6.3..6.3...8.5..5.1.6798..9.....32......4..42.....
"300000709019070005076090030090086301108000600600410050080060203700030086963000007", // Triple UFC 3.....7.9.1..7...5..6.9..3..9..86..1..8...6..6..41..5..8..6.2..7...3..8.9.3.....7
"060000509002400600905000070009010086000206905056080700090000162008007493604000857", // ALS
"900875001000109000001302009190023058208057103530081060400706800000204000700518004", // DB # 9...75..1.....9.....13....9.9..2..5.2.8...1.3.3..8..6.4....68.....2.....7..51...4
"002300000300706002950124700005962000030478059000531600004803001100240006000610400", // POM  # ..2......3....6..29..1.47....59.2....3..7..5....5.16....48.3..11..2....6......4..
"900875001000109000001302009190023058208057103530081060410706800000204000700518004", // QFC # 9...75..1.....9.....13....9.9..2..5.2.8...1.3.3..8..6.4....68.....2.....7..51...4
"000000605000300090080004001040020970000000000031080060900600020010007000504000000", // Riddle of Sho
"100007090030020008009600500005300900010080002600004000300000010041000007007000300"]; // ESCARGOT


jig=0;

/*---------------------------------------------------------------------*/
/* 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
	{
		modfact=3;
		lable = '<table id="cl' + y + x + '" class="candtb" cellspacing=0 align=center>';
		for( i=0;i<9;i++ )
		{
			if( (i % modfact) == 0 )
				lable=lable + "<tr>";
			cel = '<td id="w' + y + x + i + '"';
			if( mask[y][x] & (1 << i) )	// i=0 to 8 so first shift is 0 bits
			{
				if( show[y][x] & (1 << i) )
					lable=lable + cel + ' class="fsh">' + (i+1) + '</td>';
				else
					lable=lable + cel + '>' + (i+1) + "</td>";
			}
			else
			{
				if( show[y][x] & (1 << i) )
					lable=lable + cel + ' class="fsh">' + (i+1) + '</td>';
				else lable=lable + cel + '>&nbsp;</td>';
			}
			if( (i % modfact) == 2 )
				lable=lable + "</tr>";
		}
		lable=lable + "</table>";
	}
	some_changes=true;
	set_square(x,y,lable,0);
}
/*---------------------------------------------------------------------*/
/* 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,choose;
	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!';
	doc.body.style.backgroundColor='#ddeeff';
	doc.body.style.color='#000000';
*/
	choose = document.forms.DataEntry.elements["Example"].selectedIndex;
	for(j=0;j<9;j++)
		for(i=0;i<9;i++)
		{
			jb[j][i] = 0;
			if( bd.length==85 && firsttime )
			{
				if( IsNumeric(bd.charAt((j*9)+i+4)) )
					g[j][i]=bd.charAt((j*9)+i+4);
			}
			else {
				c=gex[choose].charAt((j*9)+i)*1;
				g[j][i]=(IsNumeric(c))?c:0;
				show[j][i]=orig[j][i]=mask[j][i]=0;
			}
		}
	for(j=0;j<9;j++)
		for(i=0;i<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 );
				document.forms.DataEntry.elements['D'+j+i].value='';
			}
		}
	reset_yes_no( sud_list, 6 );
	document.getElementById("takestep").onclick=take_step;
	document.getElementById("takestep").className = 'SButton';
	if( readCookie('scanraidsudokucookie') )
	{
		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,issmall;

	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( 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':'#ddeeff';
			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( sud_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':'#ddeeff';
			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( sud_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':'#ddeeff';
			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( sud_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 ='scanraidsudokucookie=' + s + '; expires=' + date.toGMTString() + '; path=/';

	alert("Current Board Saved (as a cookie)");
}
function reload_board()
{
	var i,j,x,arr;
//	if( some_saved === false ) return;

	x = readCookie('scanraidsudokucookie');
	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( sud_list, 6 );
	document.getElementById("takestep").onclick=take_step;
	document.getElementById("takestep").className = 'SButton';
	some_changes=false;
	firsttime=false;
	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);
								}
							}

}
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;
				}
			}
}

/*----------------------------------------------------------------------*/
/* pointing_pairs														*/
/*----------------------------------------------------------------------*/
function pointing_pairs()
{
	var bb,cc,n,i,j,c,cn;
	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;
				cn=abetx.charAt(n);
				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)) )
						{
							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++)
						if( g[i][x[0]]===0 && i!=y[0] && i!=y[1] && (mask[i][x[0]] & (1 << n)) )
						{
							lable_square( i,x[0],(1 << n) );   // .. we don't need it in the bit array
							strat_add("POINTING PAIR: " + cn + "s at " + cordit(y[0],x[0]) + "/" + cordit(y[1],x[1]) + " points to " + cordit(i,x[1]) + ", removing " + cn + "<br>");
						}
				if( c==2 && y[0]==y[1] )  // .. pointing along a row
					for(i=0;i<9;i++)
						if( g[y[0]][i]===0 && i!=x[0] && i!=x[1] && (mask[y[0]][i] & (1 << n)) )
						{
							lable_square( y[0],i,(1 << n) );
							strat_add("POINTING PAIR: " + cn + "s at " + cordit(y[0],x[0]) + "/" + cordit(y[1],x[1]) + " points to " + cordit(y[0],i) + ", removing " + cn + "<br>");
						}

 				// 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++)
						if( g[i][x[0]]===0 && i!=y[0] && i!=y[1] && i!=y[2] && (mask[i][x[0]] & (1 << n)) )
						{
							lable_square( i,x[0],(1 << n) );
							strat_add("POINTING TRIPLE: " + cn + "s at " + cordit(y[0],x[0]) + "/" + cordit(y[1],x[1]) + "/" + cordit(y[2],x[2]) + " points to " + cordit(i,x[1]) + ", removing " + cn + "<br>");
						}

				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++)
						if( g[y[0]][i]===0 && i!=x[0] && i!=x[1] && i!=x[2] && (mask[y[0]][i] & (1 << n)) )
						{
							lable_square( y[0],i,(1 << n) );
							strat_add("POINTING TRIPLE: " + cn + "s at " + cordit(y[0],x[0]) + "/" + cordit(y[1],x[1]) + "/" + cordit(y[2],x[2]) + " points to " + cordit(y[0],i) + ", removing " + cn + "<br>");
						}
			}
		}
}
/*-------------------------------------------------------------------------*/
/* 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 )
{
	if( direction == " in row " )
		 strat_add(desc + mask2str(h) + direction + abety.charAt(unit) + ": " + cordit(y,x) + " - " + mask2str(mask[y][x]) + " -> " + mask2str(mask[y][x] & h) + "<br>");
	else strat_add(desc + mask2str(h) + direction + abetx.charAt(unit) + ": " + cordit(y,x) + " - " + mask2str(mask[y][x]) + " -> " + mask2str(mask[y][x] & h) + "<br>");
	show[y][x] = mask[y][x] - (mask[y][x] & h);
	mask[y][x] &= h;
	lable_square( y,x,0 );
	gotsome = true;
}
function hidden_pairs()
{
	var x,y,n,m,i,bb,cc,box=0,h;
	var pos=new Array(9);

	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
		{
			for(n=0;n<9;n++)	// .. check each number
			{
				pos[n]=i=0;
				for(y=bb;y<bb+3;y++)	// which means looking in each 3 by 3 box
					for(x=cc;x<cc+3;x++,i++)
						if( !g[y][x] && (mask[y][x] & (1 << n)) )
							pos[n] += (1 << i);  // ith position of n
			}
			for(n=0;n<8;n++)
				for(m=n+1;m<9;m++)
					if( bit_count(pos[n])==2 && pos[n] == pos[m] )
					{
						i=0;
						for(y=bb;y<bb+3;y++)	// which means looking in each 3 by 3 box
							for(x=cc;x<cc+3;x++,i++)
								if( pos[n] & (1 << i) && bit_count(mask[y][x]) > 2 )
								{
									h=(1 << n) + (1 << m);
									apply_new_mask( "HIDDEN PAIR: ", " in box ", box,y,x,h );
								}
					}
			box++;
		}

	/*-------------------------------------------------------------------------*/
	/* Checking in the box will get most hidden pairs, but some are aligned    */
	/* over two box but still on the same row or columns				       */
	/*-------------------------------------------------------------------------*/
	for(y=0;y<9;y++)
	{
		for(n=0;n<9;n++)	// .. check each number
			for(pos[n]=x=0;x<9;x++)	// which means looking in each row/col
				if( !g[y][x] && (mask[y][x] & (1 << n)) )
					pos[n] += (1 << x);  // ith position of n

		for(n=0;n<8;n++)
			for(m=n+1;m<9;m++)
				if( bit_count(pos[n])==2 && pos[n] == pos[m] )
					for(x=0;x<9;x++)	// which means looking in each row/col
						if( pos[n] & (1 << x) && bit_count(mask[y][x]) > 2 )
						{
							h=(1 << n) + (1 << m);
							apply_new_mask( "HIDDEN PAIR: ", " in row ",y,y,x,h );
						}
	}
	for(x=0;x<9;x++)
	{
		for(n=0;n<9;n++)	// .. check each number
			for(pos[n]=y=0;y<9;y++)	// which means looking in each row/col
				if( !g[y][x] && (mask[y][x] & (1 << n)) )
					pos[n] += (1 << y);  // ith position of n

		for(n=0;n<8;n++)
			for(m=n+1;m<9;m++)
				if( bit_count(pos[n])==2 && pos[n] == pos[m] )
					for(y=0;y<9;y++)	// which means looking in each row/col
						if( pos[n] & (1 << y) && bit_count(mask[y][x]) > 2 )
						{
							h=(1 << n) + (1 << m);
							apply_new_mask( "HIDDEN PAIR: ", " in col ",x,y,x,h );
						}
	}
}
function hidden_triples()
{
	var x,y,n,m,p,i,bb,cc,a,b,c,h,box=0;
	var pos=new Array(9);

	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
		{
			for(n=0;n<9;n++)	// .. check each number
			{
				pos[n]=i=0;
				for(y=bb;y<bb+3;y++)	// which means looking in each 3 by 3 box
					for(x=cc;x<cc+3;x++,i++)
						if( !g[y][x] && (mask[y][x] & (1 << n)) )
							pos[n] += (1 << i);  // ith position of n
			}
			for(n=0;n<7;n++)
				for(m=n+1;m<8;m++)
					for(p=m+1;p<9;p++)
						if( bit_count(pos[n] | pos[m] | pos[p]) == 3 && pos[n] && pos[m] && pos[p] )
						{
							i=0;
							for(y=bb;y<bb+3;y++)	// which means looking in each 3 by 3 box
								for(x=cc;x<cc+3;x++,i++)
								{
									a=pos[n] & (1 << i);
									b=pos[m] & (1 << i);
									c=pos[p] & (1 << i);
									if( (a || b || c)
									  && bit_count(mask[y][x]) > ((a>0)+(b>0)+(c>0)) )
									{
										h=(1 << n) + (1 << m) + (1 << p);
										apply_new_mask( "HIDDEN TRIPLE: ", " in box ",box,y,x,h );
									}
								}
						}
			box++;
		}

	/*-------------------------------------------------------------------------*/
	/* Checking in the box will get most hidden pairs, but some are aligned    */
	/* over two box but still on the same row or columns				       */
	/*-------------------------------------------------------------------------*/
	for(y=0;y<9;y++)
	{
		for(n=0;n<9;n++)	// .. check each number
			for(pos[n]=x=0;x<9;x++)	// which means looking in each row/col
				if( !g[y][x] && (mask[y][x] & (1 << n)) )
					pos[n] += (1 << x);  // ith position of n

		for(n=0;n<7;n++)
			for(m=n+1;m<8;m++)
				for(p=m+1;p<9;p++)
					if( bit_count(pos[n] | pos[m] | pos[p]) == 3 && pos[n] && pos[m] && pos[p] )
					{
						for(x=0;x<9;x++)
						{
							a=pos[n] & (1 << x);
							b=pos[m] & (1 << x);
							c=pos[p] & (1 << x);
						//	if( y==4 ) alert( x + ' abc: ' + a + ' ' + b + ' ' + c + ' nmp: ' + n + ' ' + m + ' ' + p );
							if( (a || b || c)
							  && bit_count(mask[y][x]) > ((a>0)+(b>0)+(c>0)) )
							{
								h=(1 << n) + (1 << m) + (1 << p);
								apply_new_mask( "HIDDEN TRIPLE: ", " in row ",y,y,x,h );
							}
						}
					}
	}
	for(x=0;x<9;x++)
	{
		for(n=0;n<9;n++)	// .. check each number
			for(pos[n]=y=0;y<9;y++)	// which means looking in each row/col
				if( !g[y][x] && (mask[y][x] & (1 << n)) )
					pos[n] += (1 << y);  // ith position of n

		for(n=0;n<7;n++)
			for(m=n+1;m<8;m++)
				for(p=m+1;p<9;p++)
					if( bit_count(pos[n] | pos[m] | pos[p]) == 3 && pos[n] && pos[m] && pos[p] )
					{
						for(y=0;y<9;y++)
						{
							a=pos[n] & (1 << y);
							b=pos[m] & (1 << y);
							c=pos[p] & (1 << y);
							if( (a || b || c)
							  && bit_count(mask[y][x]) > ((a>0)+(b>0)+(c>0)) )
							{
								h=(1 << n) + (1 << m) + (1 << p);
								apply_new_mask( "HIDDEN TRIPLE: ", " in col ",x,y,x,h );
							}
						}
					}
	}
}
function hidden_quads()
{
	var x,y,n,m,p,q,i,bb,cc,a,b,c,d,h,box=0;
	var pos=new Array(9);

	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
		{
			for(n=0;n<9;n++)	// .. check each number
			{
				pos[n]=i=0;
				for(y=bb;y<bb+3;y++)	// which means looking in each 3 by 3 box
					for(x=cc;x<cc+3;x++,i++)
						if( !g[y][x] && (mask[y][x] & (1 << n)) )
							pos[n] += (1 << i);  // ith position of n
			}
			for(n=0;n<6;n++)
				for(m=n+1;m<7;m++)
					for(p=m+1;p<8;p++)
						for(q=p+1;q<9;q++)
							if( bit_count(pos[n] | pos[m] | pos[p] | pos[q]) == 4 && pos[n] && pos[m] && pos[p] && pos[q] )
							{
								i=0;
								for(y=bb;y<bb+3;y++)	// which means looking in each 3 by 3 box
									for(x=cc;x<cc+3;x++,i++)
									{
										a=pos[n] & (1 << i);
										b=pos[m] & (1 << i);
										c=pos[p] & (1 << i);
										d=pos[q] & (1 << i);
										if( (a || b || c || d)
										  && bit_count(mask[y][x]) > ((a>0)+(b>0)+(c>0)+(d>0)) )
										{
											h=(1 << n) + (1 << m) + (1 << p) + (1 << q);
											apply_new_mask( "HIDDEN QUAD: ", " in box ",box,y,x,h );
										}
									}
							}
			box++;
		}

	/*-------------------------------------------------------------------------*/
	/* Checking in the box will get most hidden pairs, but some are aligned    */
	/* over two box but still on the same row or columns				       */
	/*-------------------------------------------------------------------------*/
	for(y=0;y<9;y++)
	{

		for(n=0;n<9;n++)	// .. check each number
			for(pos[n]=x=0;x<9;x++)	// which means looking in each row/col
				if( !g[y][x] && (mask[y][x] & (1 << n)) )
					pos[n] += (1 << x);  // ith position of n

		for(n=0;n<6;n++)
			for(m=n+1;m<7;m++)
				for(p=m+1;p<8;p++)
					for(q=p+1;q<9;q++)
						if( bit_count(pos[n] | pos[m] | pos[p] | pos[q]) == 4 && pos[n] && pos[m] && pos[p] && pos[q] )
						{
							for(x=0;x<9;x++)
							{
								a=pos[n] & (1 << x);
								b=pos[m] & (1 << x);
								c=pos[p] & (1 << x);
								d=pos[q] & (1 << x);
								if( (a || b || c || d)
								  && bit_count(mask[y][x]) > ((a>0)+(b>0)+(c>0)+(d>0)) )
								{
									h=(1 << n) + (1 << m) + (1 << p) + (1 << q);
									apply_new_mask( "HIDDEN QUAD: ", " in row ",y,y,x,h );
								}
							}
						}
	}
	for(x=0;x<9;x++)
	{
		for(n=0;n<9;n++)	// .. check each number
			for(pos[n]=y=0;y<9;y++)	// which means looking in each row/col
				if( !g[y][x] && (mask[y][x] & (1 << n)) )
					pos[n] += (1 << y);  // ith position of n

		for(n=0;n<6;n++)
			for(m=n+1;m<7;m++)
				for(p=m+1;p<8;p++)
					for(q=p+1;q<9;q++)
						if( bit_count(pos[n] | pos[m] | pos[p] | pos[q]) == 3 && pos[n] && pos[m] && pos[p] && pos[q] )
						{
							for(y=0;y<9;y++)
							{
								a=pos[n] & (1 << y);
								b=pos[m] & (1 << y);
								c=pos[p] & (1 << y);
								d=pos[q] & (1 << y);
								if( (a || b || c)
								  && bit_count(mask[y][x]) > ((a>0)+(b>0)+(c>0)+(d>0)) )
								  {
									h=(1 << n) + (1 << m) + (1 << p) + (1 << q);
								  	apply_new_mask( "HIDDEN QUAD: ", " in col ",x,y,x,h );
								  }
							}
						}
	}
}

/*----------------------------------------------------------------------*/
/* MAIN PAIR TEST														*/
/*----------------------------------------------------------------------*/
function main_pair_test()
{
	var bb,cc,n,m,i,j,k,a,b,y,x1,x2,x3,h,cn;
	var mbox=new Array(9);
	var cnt=new Array(9);

	/*----------------------------------------------------------------------*/
	/* Purpose of this pair test is to look for pairs of numbers,			*/
	/* eg 3-7 and 3-7 in the same box. Since both numbers MUST be on both   */
	/* cells they can be eliminated from the rest of the box				*/
	/*----------------------------------------------------------------------*/
	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
		{
			k=0;
			for(i=bb;i<bb+3;i++)	// put the box in a 1D array for ease of use
				for(j=cc;j<cc+3;j++)
				{
					mbox[k]=mask[i][j];
					cnt[k]=bit_count(mask[i][j]);
					cordX[k]=j;
					cordY[k++]=i;
				}
			for(a=0;a<8;a++)	// .. check each pair in the 1D box array
				for(b=a+1;b<9;b++)
				{
					if( cnt[a]==2 && mbox[a] == mbox[b] )  // If same 2 numbers in the same 2 squares
					{
						for(m=0;m<9;m++)	// for all squares in the box
							for(n=0;n<9;n++) // for all numbers
							{
								if( m!=a && m!=b && (mbox[a] & (1 << n)) && (mbox[m] & (1 << n)) )
								{
								//	alert("here n=" + n + " m=" + m + " a=" + a + " mbox[a]=" + mbox[a] + " cnt[m]=" + cnt[m]);
									cn=abetx.charAt(n);
									strat_add("NAKED PAIR (Box): " + cordit(cordY[a],cordX[a]) + "/" + cordit(cordY[b],cordX[b]) + " removes " + cn + " from " + cordit(cordY[m],cordX[m]) + "<br>");
									mbox[m] -= (1 << n); // remove that number
									lable_square( cordY[m],cordX[m],(1 << n) );
								}
							}
					}
				}
		}

	/*----------------------------------------------------------------------*/
	/* Purpose of pair_test2 is to look for pairs of numbers, eg 3-7 and 3-7 */
	/* in the same row/col. Since both numbers MUST be on both cells they 	*/
	/* can be elininated from the rest of the ROW or COLUMN they are		*/
	/* aligned with. How cool is that?										*/
	/*----------------------------------------------------------------------*/

	for(y=0;y<9;y++)
		for(x1=0;x1<8;x1++)	// For every square...
			for(x2=x1+1;x2<9;x2++)
			{
				// This block checks the ROW the pair resides in...
				if( bit_count(mask[y][x1])==2 && mask[y][x1] == mask[y][x2] )
					for(i=0;i<9;i++)
					{
						h=(mask[y][i] & mask[y][x1]);
						if( i!=x1 && i!=x2 && !g[y][i] && h )
						{
							strat_add("NAKED PAIR (Row): " + cordit(y,x1) + "/" + cordit(y,x2) + " removes " + mask2str(mask[y][i] & h) + " from " + cordit(y,i) + "<br>");
							lable_square( y,i,h );
						}
					}

				// This block checks the COLUMN the pair resides in...
				if( bit_count(mask[x1][y])==2 && mask[x1][y] == mask[x2][y] )
					for(i=0;i<9;i++)
					{
						h=(mask[i][y] & mask[x1][y]);
						if( i!=x1 && i!=x2 && !g[i][y] && h )
						{
							strat_add("NAKED PAIR (Col): " + cordit(x1,y) + "/" + cordit(x2,y) + " removes " + mask2str(mask[i][y] & h) + " from " + cordit(i,y) + "<br>");
							lable_square( i,y,h );
						}
					}
			}
}

function main_triple_test()
{
	var bb,cc,i,j,k,y,x1,x2,x3,h,off;
	var mbox=new Array(9);
	var cnt=new Array(9);

	// LOOK FOR TRIPLES
	for(y=0;y<9;y++)
		for(x1=0;x1<7;x1++)	// For each triple
			for(x2=x1+1;x2<8;x2++)
				for(x3=x2+1;x3<9;x3++)
				{
					// This block checks the ROW the triple resides in...
					if( bit_count(mask[y][x1])>1 && bit_count(mask[y][x2])>1 && bit_count(mask[y][x3])>1 )
					{
						h=mask[y][x1] | mask[y][x2] | mask[y][x3];
						if( bit_count(h)==3 )
							for(i=0;i<9;i++)
							{
								off=(mask[y][i] & h);
								if( i!=x1 && i!=x2 && i!=x3 && off )
								{
									strat_add("NAKED TRIPLE (Row): " + cordit(y,x1) + "/" + cordit(y,x2) + "/" + cordit(y,x3) + " removes " + mask2str(off) + " from " + cordit(y,i) + "<br>");
									lable_square( y,i,off );
								}
							}
					}
					// This block checks the COLUMN the triple resides in...
					if( bit_count(mask[x1][y])>1 && bit_count(mask[x2][y])>1 && bit_count(mask[x3][y])>1 )
					{
						h=mask[x1][y] | mask[x2][y] | mask[x3][y];
						if( bit_count(h)==3 )
							for(i=0;i<9;i++)
							{
								off=(mask[i][y] & h);
								if( i!=x1 && i!=x2 && i!=x3 && off )
								{
									strat_add("NAKED TRIPLE (Col): " + cordit(x1,y) + "/" + cordit(x2,y) + "/" + cordit(x3,y) + " removes " + mask2str(off) + " from " + cordit(i,y) + "<br>");
									lable_square( i,y,off );
								}
							}
					}
				}
	/*----------------------------------------------------------------------*/
	// This block checks the BOX the triple resides in...
	/*----------------------------------------------------------------------*/
	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
		{
			k=0;
			for(i=bb;i<bb+3;i++)	// put the box in a 1D array for ease of use
				for(j=cc;j<cc+3;j++)
				{
					mbox[k]=mask[i][j];
					cnt[k]=bit_count(mask[i][j]);
					cordX[k]=j;
					cordY[k++]=i;
				}
			for(x1=0;x1<7;x1++)	// For each triple
				for(x2=x1+1;x2<8;x2++)
					for(x3=x2+1;x3<9;x3++)
					{
						if( cnt[x1]>1 && cnt[x2]>1 && cnt[x3]>1 )
						{
							h=mbox[x1] | mbox[x2] | mbox[x3];
							if( bit_count(h)==3 )
								for(i=0;i<9;i++)
								{
									off=(mbox[i] & h);
									if( i!=x1 && i!=x2 && i!=x3 && off )
									{
										strat_add("NAKED TRIPLE (Box): " + cordit(cordY[x1],cordX[x1]) + "/" + cordit(cordY[x2],cordX[x2]) + "/" + cordit(cordY[x3],cordX[x3]) + " removes " + mask2str(off) + " from " + cordit(cordY[i],cordX[i]) + "<br>");
										mbox[i] -= off; // remove that number
										lable_square( cordY[i],cordX[i],off ); // remove that number
									}
								}
						}
					}
		}
}
function naked_quads()
{
	var bb,cc,i,j,k,y,x1,x2,x3,x4,h,off;
	var mbox=new Array(9);
	var cnt=new Array(9);

	// LOOK FOR QUADS
	for(y=0;y<9;y++)
		for(x1=0;x1<6;x1++)	// For each quad
			for(x2=x1+1;x2<7;x2++)
				for(x3=x2+1;x3<8;x3++)
					for(x4=x3+1;x4<9;x4++)
					{
						// This block checks the ROW the quad resides in...
						if( bit_count(mask[y][x1])>1 && bit_count(mask[y][x2])>1 && bit_count(mask[y][x3])>1 && bit_count(mask[y][x4])>1 )
						{
							h=mask[y][x1] | mask[y][x2] | mask[y][x3] | mask[y][x4];
							if( bit_count(h)==4 )
								for(i=0;i<9;i++)
								{
									off=(mask[y][i] & h);
									if( i!=x1 && i!=x2 && i!=x3 && i!=x4 && off )
									{
										strat_add("NAKED QUAD (Row): " + cordit(y,x1) + "/" + cordit(y,x2) + "/" + cordit(y,x3) + "/" + cordit(y,x4) + " removes " + mask2str(off) + " from " + cordit(y,i) + "<br>");
										lable_square( y,i,off );
									}
								}
						}
						// This block checks the COLUMN the triple resides in...
						if( bit_count(mask[x1][y])>1 && bit_count(mask[x2][y])>1 && bit_count(mask[x3][y])>1 && bit_count(mask[x4][y])>1 )
						{
							h=mask[x1][y] | mask[x2][y] | mask[x3][y] | mask[x4][y];
							if( bit_count(h)==4 )
								for(i=0;i<9;i++)
								{
									off=(mask[i][y] & h);
									if( i!=x1 && i!=x2 && i!=x3 && i!=x4 && off )
									{
										strat_add("NAKED QUAD (Col): " + cordit(x1,y) + "/" + cordit(x2,y) + "/" + cordit(x3,y) + "/" + cordit(x4,y) + " removes " + mask2str(off) + " from " + cordit(i,y) + "<br>");
										lable_square( i,y,off );
									}
								}
						}
					}
	/*----------------------------------------------------------------------*/
	// This block checks the BOX the triple resides in...
	/*----------------------------------------------------------------------*/
	for(bb=0;bb<9;bb+=3)		// Once more, for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
		{
			k=0;
			for(i=bb;i<bb+3;i++)	// put the box in a 1D array for ease of use
				for(j=cc;j<cc+3;j++)
				{
					mbox[k]=mask[i][j];
					cnt[k]=bit_count(mask[i][j]);
					cordX[k]=j;
					cordY[k++]=i;
				}
			for(x1=0;x1<6;x1++)	// For each triple
				for(x2=x1+1;x2<7;x2++)
					for(x3=x2+1;x3<8;x3++)
						for(x4=x3+1;x4<9;x4++)
						{
							if( cnt[x1]>1 && cnt[x2]>1 && cnt[x3]>1 && cnt[x4]>1 )
							{
								h=mbox[x1] | mbox[x2] | mbox[x3] | mbox[x4];
								if( bit_count(h)==4 )
									for(i=0;i<9;i++)
									{
										off=(mbox[i] & h);
										if( i!=x1 && i!=x2 && i!=x3 && i!=x4 && off )
										{
											strat_add("NAKED QUAD (Box): " + cordit(cordY[x1],cordX[x1]) + "/" + cordit(cordY[x2],cordX[x2]) + "/" + cordit(cordY[x3],cordX[x3])  + "/" + cordit(cordY[x4],cordX[x4]) + " removes " + mask2str(off) + " from " + cordit(cordY[i],cordX[i]) + "<br>");
											mbox[i] -= off; // remove that number
											lable_square( cordY[i],cordX[i],off ); // remove that number
										}
									}
							}
						}
		}
}
/*--------------------------------------------------------------------------*/
/* 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++)	// 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++)
							if( !g[yy][xx] && yy!=y1+y2 && (mask[yy][xx] & (1 << n)) )	// and the n is present
							{
								strat_add("LBR: " + abetx.charAt(n) + " exists only in box " + abetx.charAt(which_box[yy][xx]) + " and row " + abety.charAt(y1+y2) + ", can remove from " + cordit(yy,xx) + "<br>");
								lable_square( yy,xx,(1 << n) );
							}

				}
				// Switch X and Y to do columns as well
				for(c=x=0;x<9;x++)	// 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++)
							if( !g[xx][yy] && yy!=y1+y2 && (mask[xx][yy] & (1 << n)) )	// and the n is present
							{
								strat_add("LBR: " + abetx.charAt(n) + " exists only in box " + abetx.charAt(which_box[xx][yy]) + " and col " + abetx.charAt(y1+y2) + ", can remove from " + cordit(xx,yy) + "<br>");
								lable_square( xx,yy,(1 << n) );
							}
				}
			}
		}
}
/*----------------------------------------------------------------------*/
/* Function to check for conflicts with the rules						*/
/*----------------------------------------------------------------------*/
function sanity_check()
{
	var bb,cc,n,i,j,c,x,y,zz,yy,failed=0;

	for( x in g )
		for( y in g[x] )	// for every square on the board...
			if( g[x][y]===0 && mask[x][y]===0 )	// if it is an known square...
			{
				set_square(y,x,g[x][y],3);	// hightlight conflicting squares
				return true;
			}

	for( x in g )
		for( y in g[x] )	// for every square on the board...
			if( g[x][y] )	// if it is an known square...
			{
				for( i=0;i<9;i++ ) // check values in row
				{
					if( i != y && g[x][i] == g[x][y] )
					{
						set_square(i,x,g[x][i],3);	// hightlight conflicting squares
						set_square(y,x,g[x][y],3);	// hightlight conflicting squares
						failed+=2;
					}
					if( i != x && g[i][y] == g[x][y] )
					{
						set_square(y,i,g[i][y],3);	// hightlight conflicting squares
						set_square(y,x,g[x][y],3);	// hightlight conflicting squares
						failed+=2;
					}
				}
			}


	for(bb=0;bb<9;bb+=3)			// for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
			for(i=bb;i<bb+3;i++)		// which means looking in each 3 by 3 box
				for(j=cc;j<cc+3;j++)
					if( g[i][j] ) // if the square is known ...
						for(zz=bb;zz<bb+3;zz++)	// ..check every other cell
							for(yy=cc;yy<cc+3;yy++)
								if( !(zz==i && yy==j) && g[zz][yy] == g[i][j] )	// .. if the number is known
								{
									set_square(yy,zz,g[zz][yy],3);	// hightlight conflicting squares
									set_square(j,i,g[i][j],3);	// hightlight conflicting squares
									failed+=2;
								}
	return failed;
}
/* Function to reset the board to its normal blue background */
function blue_board()
{
	var x,y,done=0;
	for(y=0;y<9;y++)		// Redraw the board to clear any user highlighting
		for(x=0;x<9;x++)
		{
			if( some_changes===false ) t=document.getElementById("a"+y+x);
			if( some_changes===false ) t.style.backgroundColor=( jb[y][x]==2 )?'#dddddd':'#ddeeff';
			if( g[y][x]>0 ) done++;
		}
	return done;
}
function block_board()
{
	var x,y,c,okay=false;
	return true; // turns off block
}
function grade_sudoku()
{
	var i,j,done=0,t,found=0,x,y;
	var s='',st='';

	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
	{
		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<sud_list.length;x++) if( document.getElementById("CB"+sud_list[x]).checked===false )
			st+=sud_list[x];

		var frm = document.forms.servsolv;
		frm.elements['coordmode'].value = coordmode;
		frm.elements['gors'].value = 1;
		frm.elements['strat'].value = 'XWG';
		frm.elements['stratmask'].value = st;
		frm.elements['mapno'].value = jig;
		frm.elements['board'].value = s.substr(1,s.length-1);
		frm.submit();
	}
}
function post_to_form() {
	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<sud_list.length;x++) if( document.getElementById("CB"+sud_list[x]).checked===false )
	{
		st+=sud_list[x];
	}
	var frm = document.forms.servsolv;
	frm.elements['coordmode'].value = coordmode;
	frm.elements['gors'].value = 0;
	frm.elements['strat'].value = 'XWG';
	frm.elements['stratmask'].value = st;
	frm.elements['mapno'].value = jig;
	frm.elements['board'].value = s.substr(1,s.length-1);
	frm.submit();

}

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;
		}
	//	alert('before: ' + stage + ' ' + some_changes);
		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( sud_list, 6 ); jg.clear(); clear_on_off_color(); }

			if( stage >= 9 )
			{
				document.getElementById("takestep").onclick=null;
				document.getElementById("takestep").className = 'GButton';
			}
			if( sanity_check() )
				alert("Oops - you've got an error on the board");
			clear_results = true;

			if( stage == 1  ) show_candidates();
			if( stage == 2  ) singles_in_row_col();
			if( stage == 3  ) singles_in_box();
			if( stage == 4  ) { main_pair_test(); main_triple_test(); }
			if( stage == 5  ) { hidden_pairs(); hidden_triples(); }
			if( stage == 6  ) { naked_quads();  hidden_quads(); }
			if( stage == 7  ) pointing_pairs();
			if( stage == 8  ) line_box_reduction();
			if( stage == 9  ) post_to_form();

			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 if( stage < 9  ) {
				document.getElementById("R" + sud_list[stage-7]).innerHTML=(some_changes)? '<font color=#00ff00><b>Yes</b></font>' : '<font color=#ff0000><b>No</b></font>';
			} else {
				document.getElementById("R" + sud_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( sud_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)
		document.getElementById("R0").innerHTML = '';
	}
	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('SudokuEmail.htm?' + board,'_blank','resizable=no,scrollbars=no,left=300,top=200,screenX=200,screenY=200,width=750,height=420');
    	if (!SGW.opener) SGW.opener=self;
	}
}
function print_board(ptype)
{
	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('SudokuPrintable.htm?' + board,'_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=670,height=680');
	else SGW=window.open('SudokuPrintableV2.htm?' + board,'_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=670,height=680');
	if (!SGW.opener) SGW.opener=self;
}
function test_solutions(ptype)
{
	var x,y,done=0,SGW;
	var board='';

	done=blue_board();
	if( done < 16  ) { alert('Too few clues/numbers, normal sudoku must have 17 clues minimum.'); return; }
	if( done == 81  ) { alert('Puzzle is complete.'); return; }

	for(y=0;y<9;y++) for(x=0;x<9;x++)
		board=board + g[y][x];

	SGW=window.open('S/WebSudoku.dll?solutions&0,' + board,'_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=670,height=480');
	if (!SGW.opener) SGW.opener=self;
}
function fired_event()
{
	var s,c,y,x,n,t,stratname;
	var doc,d,d2;

	if( !document.ifrm )
		 doc = document.getElementById("ifrm").contentDocument;
	else doc = document.ifrm.document;
	d = doc.getElementById("kbin")
	if( !d ) return;
	s = d.value;
	stratname = doc.getElementById("nstage").value;
	t=document.getElementById("TestT");

	if( stratname!="NO" )
	{
		stage = get_stage(sud_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;
				}
			}
//		alert(stratname + ' ' + stage);
		for(i=0;i<MAX_STRAT-1;i++)
			t.rows[i*1+offset[i]].cells[1].style.backgroundColor=(stage==i) ? "#777700" : ((((i*1+offset[i])%2)==0)?"#333333":"#222222");
		paint_yes_no( sud_list, stratname );
		some_changes = true;
	}
	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( sud_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" + sud_list[i]).checked = !document.getElementById("CB" + sud_list[i]).checked;
		break;
	case 3 :
		for(i=15;i<=27;i++)
			document.getElementById("CB" + sud_list[i]).checked = !document.getElementById("CB" + sud_list[i]).checked;
		break;
	case 4 :
		for(i=28;i<=29;i++)
			document.getElementById("CB" + sud_list[i]).checked = !document.getElementById("CB" + sud_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;
	}
}

