/*
 * Copyright (c) 2005-6, killersudokuonline.com
 * All Rights Reserverd.  
 * With the exception of the function getArgs, dhtmlLoadScript, 
 * defineNodeConstants.
 * Use of this code requires prior permission from webmaster@killersudokuonline.com
 * 
 */

var statHints = 0;
var statChecks = 0;
var statBugs = 0;
var statBugShow = 0;
var statDisp = 0;
var statPress = 0;
var statDone = 0;
var adjustTime = 0;
var lastPress = 0;

var forme=0;
var ksover = 4;
var ksover4 = true;
rowsol = new Array(10);
cellsol = new Array(10);
mysol = new Array(10);
myg = new Array(10);

var lastcell = 0;
var cellmap;
var dmap;
//var voted;

var poffsetleft;
var poffsettop;
var ulx;
var uly;
var lrx;
var lry;

var avoidMouseEvent = false;

function registercell() {
  if (avoidMouseEvent) {
    avoidMouseEvent = false;
    return;
  }
  lastcell = cellmap[this.prow][this.pcol];
  showRegisteredCell(lastcell);
}
function unregistertable() {
    lastcell = 0;
    if (lastreg != 0) {
      lastreg.style.backgroundColor = "transparent";
      lastreg = 0;
    }
}

function readCellContents(cell) {
  var str = "";
  if (cell.hasChildNodes()) {
    var children = cell.childNodes;
    for (var i=0; i<children.length; i++) {
      var n = children[i];
      if (n.nodeType == Node.TEXT_NODE) {
	str = str+n.nodeValue;
      }
    }
  }
  if (str.charCodeAt(0) == 160) {
    str = "";
  }
  return str;
}

function getCellContents(cell) {
  var str = readCellContents(cell);
  addChunk(cell, str);
  if (cell.hasChildNodes()) {
    removeAllChildren(cell);
  }
  return str;
}

var usecookie = true;
var cellheight;
var cellwidth;
var trackCorrect = 0;

function putCellContents(cell, str) 
{
  qi = str.indexOf("?");
  if (qi != -1) {
    if (str.length == 1) {
      str = "";
    } else if (qi+1 != str.length) {
      str = str.substr(0, qi)+str.substr(qi+1, str.length)+"?";
    }
  }
  while (str.charCodeAt(0) == 32) {
    str = str.substr(1);
  }
  if (0) {
  while ((str.length > 1) && ((str.charCodeAt(str.length-1) == 32)&&(str.charCodeAt(str.length-2) == 32))) {
    str = str.substr(0, str.length-1);
  }}
  var container = cell;
  var lh;
  var newvalue = str2mask(str);
  container.style.color = "black";
  if (str.length == 0) {
    str = String.fromCharCode(160);
  }
  if (str.length > 1) {
    if (str.length > 8) {
      container.style.fontSize = "10px";
      lh=1.4;
    } else {
      container.style.fontSize = "12px";
      lh=1.1;
    }
  } else {
    container.style.fontSize = "18px";
    if (newvalue == cellsol[cell.prow][cell.pcol]) trackCorrect++;
  }
  // save value of the cell
  mysol[cell.prow][cell.pcol] = newvalue;
  myg[cell.prow][cell.pcol] = str.indexOf("?") == -1 ? "s" : "g";
  // now add text
  if (str.length > 4) {
    var x = document.createTextNode(str.slice(0,4));
    container.style.lineHeight = lh;
    container.appendChild(x);
    container.appendChild(document.createElement("BR"));
    str = str.slice(4);
  }
  var x = document.createTextNode(str);
  container.appendChild(x);
  // if all done, go into won mode
  if (trackCorrect > 79) ensureCorrect();
  if (trackCorrect == 81) showWon();
  // finally update cookie
  if (usecookie) {
    var cookie="values="+puzzleid.length.toString()+puzzleid+"-";
    var i,j;
    for (i=0; i<9; i++) {
      for (j=0; j<9; j++) {
	if (mysol[i][j] != 0) {
	  var str = mask2str(mysol[i][j]);
	  var len = str.length.toString() + str;
	  cookie = cookie + i.toString() + j.toString() + myg[i][j] + len;
	}
      }
    }
    document.cookie = cookie;
  }
}

// remove all spaces, etc. from string
function trimstr(str) {
  return str.replace(/ /g,"");
}

// make this cells a sure thing - only 1 value or no effect
function makeCellSureThing(cell) {
  var already=getCellContents(cell);
  var i = already.indexOf("?");
  if (i != -1) 
    already = already.substr(0, i);
  while (already.charCodeAt(already.length-1)==32) {
    already = already.substr(0, already.length-1);
  }
  putCellContents(cell, already);
}

// make this cells a guess - only 1 value or no effect
function addSpace(cell) {
  var already = getCellContents(cell);
  already = already+" ";
  putCellContents(lastcell, already);
}

// make this cells a guess - only 1 value or no effect
function makeCellGuess(cell) {
  var already = getCellContents(cell);
  if ((already.length > 0) && (already.indexOf("?") == -1))
    already = already+"?";
  putCellContents(lastcell, already);
}

// toggle guess status
function toggleCellGuess(cell) {
  var already = getCellContents(cell);
  var i = already.indexOf("?");
  if ((i == -1)&&(already.length > 0)) {
    already = already+"?";
  } else {
    already = already.substr(0, i);
  }
  putCellContents(lastcell, already);
}

function clearCell(cell) {
  getCellContents(cell);
  putCellContents(cell, String.fromCharCode(160));
}

var lastreg = 0;
function showRegisteredCell(cell) {
  if (lastreg != cell) {
    if (lastreg != 0) {
            lastreg.style.backgroundColor = "transparent";
	    //            lastreg.style.backgroundPosition = "100 100";
	    //    lastreg.style.borderStyle = "hidden";
    }
    lastreg = cell;
    //lastreg.style.borderStyle = "solid";
    //lastreg.style.borderColor = "red";
            cell.style.backgroundColor = "Gold";
	    //cell.style.backgroundPosition = "0 0";
  }
}

var keepCellsSorted = 0;

function sortmethod(how) {
  if (how == 1) {
    keepCellsSorted = 1;
  } else {
    keepCellsSorted = 0;
  }
  document.control.sortcells.blur();
}

var digits = "0123456789";

function str2mask(str)
{
  var mask = 0;
  var i;
  for (i=1; i<=9; i++) {
    if (str.indexOf(digits.charAt(i)) != -1) {
      mask |= num2mask(i);
    }
  }
  return mask;
}

function num2mask(num)
{
  return (1 << num);
}

function mask2sum(mask)
{
  var total = 0;
  var i;

  for (i=9; i>0; i--) {
    if (mask & (1 << i)) total+=i;
  }
  return total;
}

function mask2str(mask)
{
  var p = "";
  var i;

  for (i=1; i<=9; i++) {
    if (mask & (1 << i)) p = p + String.fromCharCode(i+48);
  }
  return p;
}  

function getMaskCount(mask)
{
  var count = 0;
  var i;

  for (i=1; i<=9; i++)
    if ((1<<i)&mask) count++;
  return count;
}


function gotoNextCell(cell) {
  return gotoRelCell(cell, 0, 1);
}

var epsilon=11;
var dowrapincr=0;

function gotoRelCell(cell, row, col) {
  var c = cell.pcol + col;
  var r = cell.prow + row;
  if (c < 0) {
    if (dowrapincr) {
      r--;
      if (r < 0) {
	r=8;
      }
    }
    c=8;
  } else if (c > 8) {
    if (dowrapincr) {
      r++;
      if (r > 8) {
	r = 0;
      }
    }
    c=0;
  }
  if (r<0) {
    r=8;
    if (dowrapincr) {
      c--;
      if (c < 0) c=8;
    }
  } else if (r > 8) {
    r=0;
    if (dowrapincr) {
      c++;
      if (c>8) c=0;
    }
  }
  lastcell = cellmap[r][c];

  if (0) {
    avoidMouseEvent = true;
    lastcell.scrollIntoView(false);
  } else {
    // scrolling
    var loff = findPosX(lastcell);
    var toff = findPosY(lastcell);
    checkScroll();
    //    debug("pt:"+poffsettop+" ["+ulx+","+uly+"] ["+lrx+","+lry+"] L:"+loff+" T:"+toff);
    if (((loff < (ulx+epsilon))||(loff > (lrx-epsilon)))||(toff < (uly+epsilon))||(toff > (lry-epsilon))) {
      // center cell
      avoidMouseEvent = true;
      var newx = loff-((lrx-ulx)/2);
      var newy = toff-((lry-uly)/2);
      if (newx < 0) newx = 0;
      if (newy < 0) newy = 0;
      //            debug("Scroll to: "+newx+" , "+newy);
      window.scrollTo(newx, newy);
    }
  }

  showRegisteredCell(lastcell);
  return lastcell;
}


function findPosX(obj)
{
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

function findPosY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

var wonMode;			/* whether they have won already */
var puzzleimage;		/* image for this puzzle */
var pi;				/* puzzle image */

function doTop50() {
  wonMode = 0;
  pi.src = puzzleimage;
  return;
  //  if (voted) return;
  //  voted = true;
  //  window.open("http://www.inertiasoftware.com/top50/index.php?id=218", "_blank");
} 

function uncolorRed(cell) {
  d = dmap[cell.prow][cell.pcol];
  d.red = 0;
  top = parseInt(d.style.top);
  left = parseInt(d.style.left);
  d.style.top = ""+(top+5)+"px";
  d.style.left = ""+(left+5)+"px";
  d.style.borderWidth = "0px 0px 0px 0px";
  d.style.borderColor = "#000000";
  d.style.borderStyle = "hidden";
}

function colorRed(cell) {
  d = dmap[cell.prow][cell.pcol];
  if (d.red) {
    uncolorRed(cell);
    return;
  }
  d.red = 1;
  top = parseInt(d.style.top);
  left = parseInt(d.style.left);
  d.style.top = ""+(top-5)+"px";
  d.style.left = ""+(left-5)+"px";
  d.style.borderWidth = "2px 2px 2px 2px";
  d.style.borderColor = "#ff0000 #ff0000 #ff0000 #ff0000";
  d.style.borderStyle = "solid solid solid solid";
  adjustBorder(cell);
}

function colorBlue(cell) {
  d = dmap[cell.prow][cell.pcol];
  if (d.red) {
    uncolorRed(cell);
    return;
  }
  d.red = 1;
  top = parseInt(d.style.top);
  left = parseInt(d.style.left);
  d.style.top = ""+(top-5)+"px";
  d.style.left = ""+(left-5)+"px";
  d.style.borderWidth = "2px 2px 2px 2px";
  d.style.borderColor = "#0000ff #0000ff #0000ff #0000ff";
  d.style.borderStyle = "solid solid solid solid";
  adjustBorder(cell);
}

function resetBorder(d, top, right, bottom, left) {
  border = d.style.borderStyle;
  var all = border.split(" ");
  if (top == 1) {
    all[0] = "hidden";
  }
  if (right == 1) {
    all[1] = "hidden";
  }
  if (bottom == 1) {
    all[2] = "hidden";
  }
  if (left == 1) {
    all[3] = "hidden";
  }
  newborder = all[0]+" "+all[1]+" "+all[2]+" "+all[3];
  d.style.borderStyle = newborder;
}

function adjustBorder(cell) {
  i = cell.prow;
  j = cell.pcol;
  d = dmap[i][j];
  if (i > 0) {
    dd = dmap[i-1][j];
    if (dd.red) {
      resetBorder(dd, 0, 0, 1, 0);
      resetBorder(d, 1, 0, 0, 0);
    }
  }
  if (i < 9) {
    dd = dmap[i+1][j];
    if (dd.red) {
      resetBorder(dd, 1, 0, 0, 0);
      resetBorder(d, 0, 0, 1, 0);
    }
  }
  if (j > 0) {
    dd = dmap[i][j-1];
    if (dd.red) {
      resetBorder(dd, 0, 1, 0, 0);
      resetBorder(d, 0, 0, 0, 1);
    }
  }
  if (i < 9) {
    dd = dmap[i][j+1];
    if (dd.red) {
      resetBorder(dd, 0, 0, 0, 1);
      resetBorder(d, 0, 1, 0, 0);
    }
  }
}

function keyup(evt) {
  if (lastcell != 0) {
    initSolution();
    var key = evt.keyCode;
    var y = String.fromCharCode(evt.keyCode);
    if ((key >= 97) && (key <=105)) {
      key = key-97+49; // keypad key
      y=digits.charAt(key-48);
    }
    if (((key < 49)||(key > (49+9)))) {
      if (forme && (y == "R")) {
	colorRed(lastcell);
      } else if (forme && (y == "B")) {
	colorBlue(lastcell);
      } else if (y == "S") {
	makeCellSureThing(lastcell);
      } else if (y == "G") {
	makeCellGuess(lastcell);
      } else if (y == "Z") {
	undo();
      } else if (y == "C") {
	clearCell(lastcell);
      } else if (key == 32) {
	addSpace(lastcell);
      } else if (key == 13) {
	lastcell = gotoNextCell(lastcell);
      } else if (key == 37) {
	lastcell = gotoRelCell(lastcell, 0,-1);
      } else if (key == 38) {
	lastcell = gotoRelCell(lastcell, -1,0);
      } else if (key == 39) {
	lastcell = gotoRelCell(lastcell, 0,1);
      } else if (key == 40) {
	lastcell = gotoRelCell(lastcell, 1,0);
      } else if (key == 191) {
	toggleCellGuess(lastcell);
      }
      return false;
    }

    var thisPress = new Date();
    if (statPress == 0) {
       statPress = new Date(); 
       adjustTime = 0;
    } else {
      delay = thisPress.getTime() - lastPress.getTime();
      if (delay > 600000) {
	adjustTime += delay;
      }
    }
    lastPress = thisPress;

    var already=getCellContents(lastcell);
    if (evt.shiftKey) {
      // no matter what state of cell, set to key
      already=y;
    } else {
      if (keepCellsSorted) {
	var oldval = mysol[lastcell.prow][lastcell.pcol];
	oldval = oldval^num2mask(key-48);
	already = mask2str(oldval);
      } else {
	var idx = already.indexOf(y);
	if (idx != -1) {
	  // remove y from string
	  already = already.substr(0,idx)+already.substr(idx+1);
	  while (already.charCodeAt(already.length-1) == 32) {
	    already = already.substr(0, already.length-1);
	  }
	} else {
	  already = already+y;
	}
      }
      if (already.length == 0) {
	already = String.fromCharCode(160);
      }
    }
    putCellContents(lastcell, already);
    return false;
  }
}



var inited = false;

function initSolution() {
  if (inited) return;
  wonMode = 0;
  trackCorrect = 0;
  inited = true;
  for (var i=0; i<9; i++) {
    cellsol[i] = new Array(10);
    for (var j=0; j<9; j++) {
      cellsol[i][j] = str2mask(rowsol[i].slice(j,j+1));
    }
  }
  statDisp = new Date();
  statHints = statChecks = statBugs = statBugShow = statPress = statDone = lastPress = adjustTime = 0;
}

function logIt() {
       statDone = new Date();
       var f = setupForm("stat", "http://www.killersudokuonline.com/cgi-bin/recordStat.pl");
//"http://localhost/cgi-bin/recordStat.pl");
       addInput2Form(f, "hidden", "hints", statHints);
       addInput2Form(f, "hidden", "checks", statChecks);
       addInput2Form(f, "hidden", "bugs", statBugs);
       addInput2Form(f, "hidden", "shown", statBugShow);
       addInput2Form(f, "hidden", "seen", statDone.getTime()-statDisp.getTime());
       if (statPress != 0) {
	  addInput2Form(f, "hidden", "keyed", statDone.getTime()-statPress.getTime());
       }
       addInput2Form(f, "hidden", "puzzle", puzzleid);
       addInput2Form(f, "hidden", "ip", clientip);
       addInput2Form(f, "hidden", "adjust", adjustTime);
       f.submit();
}

function showWon() {
    pi.src = "images/bravo1.png";
    wonMode = 1;
    if (statDone == 0) {
	logIt();
    }
}

// return number of bad cells AND update trackCorrect
function ensureCorrect() {
  var bad=0;
  trackCorrect = 0;
  for (var i=0; i<9; i++) {
    for (var j=0; j<9; j++) {
      if (mysol[i][j] != 0) {
	if (!(mysol[i][j] & cellsol[i][j])) {
	  if (myg[i][j] != "g") bad++;
	} else {
	  if ((getMaskCount(mysol[i][j]) == 1) && (myg[i][j] != "g"))
	    trackCorrect++;
	}
      }
    }
  }
  return bad;
}

function checksolution() {
  statChecks++;
  initSolution();
  var bad = ensureCorrect();
  if (bad) {
    statBugs++;
    var show = confirm("There are "+bad+" Errors.\nDo you want to see the bad cells?");
    if (show) {
      colorBadRed();
      statBugShow++;
    }
  } else {
    if (trackCorrect < 81)
      alert("So far so good. Keep up the good work!");
    else
      showWon();
  }
  document.control.check.blur();
}

function colorBadRed() {
  for (var i=0; i<9; i++) {
    for (var j=0; j<9; j++) {
      if (mysol[i][j] != 0) {
	if (!(mysol[i][j] & cellsol[i][j])) {
	  cellmap[i][j].style.color = "red";
	}
      }
    }
  }
}

var sumtable = new Array(50);
var sumsalready = 0;

var sumsopen=0;
function sumcalc() {
  sumsopen++;
  var win = window.open("sumcalculator.html", "SumCalc"+sumsopen.toString(), "height=460,width=560,scrollbars=1,resizable=1");
  win.mydata = sumtable;
}	
function savegame() {
  // save the game in a cookie which expires next year
  var allcookies = document.cookie;
  var pos = allcookies.indexOf("values=");
  if (pos == -1) {
    alert("Nothing to save yet.");
    return;
  }
  var end = allcookies.indexOf(";", pos);
  if (end == -1) end = allcookies.length;
  var val = allcookies.substr(pos, end);
  var nextyear = new Date();
  nextyear.setFullYear(nextyear.getFullYear() + 1);
  val = val + "; expires=" + nextyear.toGMTString();
  document.cookie = val;
  document.control.save.blur();
}

function resetboard() {
  /* ask first, then clear entire board */
  var show = confirm("Do you really want to erase all your work and reset the board? (This is not undoable)");
  if (show) {
    turnOffUndo();
    for (var i=0; i<9; i++) {
      for (var j=0; j<9; j++) {
	getCellContents(cellmap[i][j]);
	putCellContents(cellmap[i][j], "");
      }
    }
    turnOnUndo();
    resetUndoList();
  }
  document.control.clear.blur();
}

function showhelp() {
  /* show help window, as pop-up */
  var win = window.open("playhelp.html", "Help", "width=420,height=540,scrollbars=yes,resizeable=yes");
  document.control.help.blur();
}

function hintsolution() {
  var countbad = 0;
  initSolution();
  for (var i=0; i<9; i++) {
    for (var j=0; j<9; j++) {
      if ((mysol[i][j] == 0)||(!(mysol[i][j] & cellsol[i][j]))) {
	countbad++;
      }
    }
  }
  var r = Math.random()*countbad;
  countbad=0;
  var done=0;
  for (var i=0; i<9; i++) {
    if (done == 1) break;
    for (var j=0; j<9; j++) {
      if (done == 1) break;
      if ((mysol[i][j] == 0)||(!(mysol[i][j] & cellsol[i][j]))) {
	countbad++;
	if (countbad >= r) {
	  getCellContents(cellmap[i][j]);
	  putCellContents(cellmap[i][j], mask2str(cellsol[i][j]));
	  showRegisteredCell(cellmap[i][j]);
	  done = 1;
	}
      }
    }
  }
  document.control.hint.blur();
  statHints++;
}

var thisbody;

function preInitPlayer(body) {
  thisbody = body;
  //  voted = false;
  defineNodeConstants();
  args = getArgs();
  if (args.puzzle) {
    puzzleid = args.puzzle;
  } else {
    // puzzleid defined in head. puzzleid = "j270849";
  }
  puzzleimage = "puzzles/puzzle-"+puzzleid+".gif";
  pi=getById("image");
  pi.src = puzzleimage;
  dhtmlLoadScript("puzzles/solution-"+puzzleid+".js");
}

var tw=48;
var th=47;
function makenewdivs(tab) {
  var adjust = 0;
  if (tab.offsetWidth) {
    if (tab.offsetWidth != 420) {
      adjust = 1;
    }
  }
  cellheight = (th-1);
  cellwidth = (tw-2);
  for (i=0; i<9; i++) {
    for (j=0; j<9; j++) {
      var d = document.createElement("DIV");
      d.style.height = cellheight+"px";
      d.style.width = cellwidth+"px";
      d.style.borderWidth = "0 0 0 0";
      d.style.padding = "0 0 0 0";
      d.style.margin = "0 0 0 0";
      d.style.textAlign = "center";
      d.style.overflow = "hidden";
      d.style.position = "absolute";
      tab.appendChild(d);

      // set top of box
      var pos = i*th+18+12;
      if (i < 6) pos-=3;
      if (i < 3) pos-=1;
      if (adjust) pos-=1;
      d.style.top = pos+"px"; 

      // set left of box
      pos = j*tw+2+3;
      if (j>5) pos-=2;
      if (adjust) pos -=3;
      d.style.left = pos+"px";

      //      d.style.backgroundColor = "white";
      //d.style.borderWidth = "3px 3px 3px 3px";
      //     d.style.borderStyle = "solid";
      //    d.style.borderColor = "red";
	    //      d.style.backgroundColor = "blue";

      d.prow = i;
      d.pcol = j;
      d.style.fontSize = "12px";
      d.onmouseover = registercell;
      d.id = i+":"+j;

      dmap[i][j] = d;

      var e;

      e = document.createElement("TABLE");
      e.className = "scelltab";
      d.appendChild(e);
      
      body = document.createElement("TBODY");
      e.appendChild(body);
      e = body;
      
      f = document.createElement("TR");
      f.className = "scellrow";
      f.style.height = (cellheight-12)+"px";
      e.appendChild(f);
      
      e = document.createElement("TD");
      e.className = "scelldata";
      e.style.width = (cellwidth-10)+"px";
      f.appendChild(e);
      
      e.prow = i;
      e.pcol = j;

      cellmap[i][j] = e;
    }

  }
  lastcell = cellmap[0][0];
  showRegisteredCell(lastcell);
}

// disable backspace
function checkKeycode(e) {
  var key;
  if (window.event) {
    e = window.event;
  }
  if (e.which) {
    key = e.which;
  } else if (e.keyCode) {
    key = e.keyCode;
  }

  if (forme) {
    if (e.target) targ = e.target;
    else if (e.srcElement) targ = e.srcElement;
    if (targ.nodeType == 3) // defeat Safari bug
      targ = targ.parentNode;
    
    //    debug(targ.nodeName);
    if (targ.nodeName != "HTML") {
      return;
    }
  }

	//debug("which:"+e.which+" code:"+e.keyCode+".");

  if (wonMode == 1) {
    doTop50();
  } 

  if (((key >=97)&&(key<=105))||(key==8)||((key>=49)&&(key<=58))||
      (key == 13)||((key>=37)&&(key<=40))||(key==191)||(key==32)) {
    e.cancelBubble = true;
    e.returnValue = false;
    if (e.preventDefault) e.preventDefault();
    if (e.stopPropagation) e.stopPropagation();
    if (window.event) {
      window.event.cancelBubble=true;
    }
    return false;
  }
  return true;
}

function saveTip() {
  var data = document.control.tip.value;
  var i;
  for (i=0; i<data.length; i++) {
    if (data.charCodeAt(i) == 10) {
      data = data.substr(0,i+1)+"<p>"+data.substr(i+1);
      i+=2;
    }
  }
  var tiptable = getById("tips");
  var num = tiptable.rows.length;
  var x=tiptable.insertRow(num);
  var z=x.insertCell(0);
  z.innerHTML=" "+num+" ";
  z=x.insertCell(1);
  z.innerHTML=data;
  z = x.insertCell(2);
  z.innerHTML="<img src=\"images/newtips/"+num+"-ready.png\">";
  document.control.tip.value = "";
}  

function initPlayer() {
  body = thisbody;
  lastcell = 0;
  var tab=getById("puzzlecontainer");
  if (forme) tab.onmouseout = unregistertable;//SCG
  tab=getById("puzzletable");
  //    tab.onmouseout = unregistertable;
  //  tab.onmouseover = regtable;
  trow = -1;
  tcol = 0;
  dmap = new Array(10);
  cellmap = new Array(10);
  for (var i=0; i<10; i++) {
    cellmap[i] = new Array(10);
    dmap[i] = new Array(10);
  }
  makenewdivs(tab);
  lastcell = cellmap[0][0];
  showRegisteredCell(lastcell);

  document.control.sortcells[0].checked=1;

  inited = false;
  initSolution();

  // init mysol
  for (var i=0; i<9; i++) {
    mysol[i] = new Array(10);
    myg[i] =  new Array(10);
    for (var j=0; j<9; j++) {
      mysol[i][j] = 0;
      myg[i][j] = 0;
    }
  }
  
  // get location of table
  tab = getById("puzzletable");
  poffsetleft = tab.offsetLeft;
  poffsettop = tab.offsetTop;
  // lets see if a cookie exists
  var allcookies = document.cookie;
  var pos = allcookies.indexOf("values=");
  usecookie = false;
  if (pos != -1) {
    // restore old values
    pos += 7;
    var end = allcookies.indexOf(";", pos);
    //    debug(allcookies);
    if (end == -1) end = allcookies.length;
    //    debug("starting: "+pos.toString()+" to "+end.toString());
    var endid = allcookies.indexOf("-", pos);
    var pid=allcookies.substr(pos+2, endid-pos-2);
    //    debug("pid: "+pid.toString()+" == "+puzzleid.toString())
    if (pid == puzzleid) {
      turnOffUndo();
      pos = endid+1;
      while (pos < end) {
	//	debug("Remaining: ["+allcookies.substr(pos)+"]");
	var x=allcookies.charCodeAt(pos)-48;
	if (x < 0) break;
	var y=allcookies.charCodeAt(pos+1)-48;
	var g=allcookies.substr(pos+2, 1);
	var num=allcookies.charCodeAt(pos+3)-48;
	var val=allcookies.substr(pos+4, num);
	//	debug("Setting "+x.toString()+","+y.toString()+" "+num.toString()+" ["+g+val+"]");
	getCellContents(cellmap[x][y]);
	if (g == "g") val += "?";
	putCellContents(cellmap[x][y], val);
	pos += (4+num);
      }
    }
  }
  turnOnUndo();
  resetUndoList();
  usecookie = true;
}


function Sum(m, n) {
  this.mask = m;
  this.next = n;
}

function makeSum(m, n) {
  return new Sum(m,n);
}

function checkScroll() {
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
  } else if (document.documentElement && 
	     (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  var scrOfX = 0, scrOfY = 0;
  if(typeof( window.pageYOffset ) == 'number') {
    //Netscape compliant
    scrOfY = window.pageYOffset;
    scrOfX = window.pageXOffset;
  } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
    //DOM compliant
    scrOfY = document.body.scrollTop;
    scrOfX = document.body.scrollLeft;
  } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
    //IE6 standards compliant mode
    scrOfY = document.documentElement.scrollTop;
    scrOfX = document.documentElement.scrollLeft;
  }
  ulx=scrOfX;
  uly=scrOfY;
  lrx=scrOfX+myWidth;
  lry=scrOfY+myHeight;
}

