var side = 3;
var size = 9;
var rows = ['', '1', '1', '1', '2', '2', '2', '3', '3', '3'];
var cols = ['', '1', '2', '3', '1', '2', '3', '1', '2', '3'];
var order = [['', '', '', ''], ['', '1', '2', '3'], ['', '4', '5', '6'], ['', '7', '8', '9']];
var numbers = new Array(size+1);
var count = new Array(size+1);
var status = new Array(size+1);
var flag = new Array(size+1);
var remaining = size*size;

// Initiate arrays
for (box=1; box<=9; box++) {
  numbers[box] = new Array(size+1);
  count[box] = new Array(size+1);
  status[box] = new Array(size+1);
  flag[box] = new Array(size+1);
  for (number=1; number<=size; number++) {
    numbers[box][number] = 0;
    count[box][number] = size;
    status[box][number] = new Array(size+1);
    flag[box][number] = new Array(size+1);
    for (cell=1; cell<=size; cell++) {
      status[box][number][cell] = 1;
      flag[box][number][cell] = 0;
    }
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
function doGenerate() {
/////////////////////////////////////////////////////////////////////////////////////////

  //Generate Table
  height = side*width;
  for (j=1; j<=side; j++) { // Box Row Loop
    for (l=1; l<=side; l++) { // Number Row Loop
      document.write('<tr height='+height+'>');
      for (i=1; i<=side; i++) { // Box Loop
        for (k=1; k<=side; k++) { // Number Loop
          box = order[j][i];
          number = order[l][k];
          document.write('<td class=cell'+number+'>');
          document.write('<table border=0 cellpadding=0 cellspacing=0 width='+height+'>');
          for (n=1; n<=side; n++) { // Cell Row Loop
            document.write('<tr height='+width+'>');
            for (m=1; m<=side; m++) { // Cell Loop
              cell = order[n][m];
              if (numbers[box][number] == 0) {
                document.write('<td><a href="javascript:clickNumber('+box+','+number+','+cell+');"><img name="img'+box+number+cell+'" src="img/'+cell+'.gif" width='+width+' height='+width+' border=0></a></td>');
              } else {
                document.write('<td><a href="javascript:clickNumber('+box+','+number+','+cell+');"><img name="img'+box+number+cell+'" src="img/'+numbers[box][number]+'_'+cell+'.gif" width='+width+' height='+width+' border=0></a></td>');
              }
            }
            document.write('</tr>'); // End Cell Row
          }
          document.write('</table>'); // End Number Table
          document.write('</td>');
          if (numbers[box][number] != 0) {
            remaining--;
          }
        }
      }
      document.write('</tr>'); // End Number Row
    }
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
function clickNumber(clickbox, clicknumber, clickcell) {
/////////////////////////////////////////////////////////////////////////////////////////

  // Remove a number
  if (numbers[clickbox][clicknumber] != 0) {
    for (cell=1; cell<=size; cell++) {
      if ((flag[clickbox][clicknumber][cell] == 1) && (f.flag.checked)) {
        document.images['img'+clickbox+clicknumber+cell].src = 'img/'+cell+'r.gif';
      } else if (status[clickbox][clicknumber][cell] == 1) {
        document.images['img'+clickbox+clicknumber+cell].src = 'img/'+cell+'.gif';
      } else {
        document.images['img'+clickbox+clicknumber+cell].src = 'img/transparent.gif';
      }
    }
    numbers[clickbox][clicknumber] = 0;
    count[clickbox][clicknumber] = size;
    remaining++;
    return;
  }

  // Change a single cell
  if (((count[clickbox][clicknumber] > 1) || (status[clickbox][clicknumber][clickcell] == 0)) &&
      (!(f.setup.checked)) && (flag[clickbox][clicknumber][clickcell] == 0)) {
    if (status[clickbox][clicknumber][clickcell] == 1) {
      document.images['img'+clickbox+clicknumber+clickcell].src = 'img/transparent.gif';
      count[clickbox][clicknumber]--;
      status[clickbox][clicknumber][clickcell] = 0;
    } else {
      document.images['img'+clickbox+clicknumber+clickcell].src = 'img/'+clickcell+'.gif';
      count[clickbox][clicknumber]++;
      status[clickbox][clicknumber][clickcell] = 1;
    }
    if (f.flag.checked) {
      doFlags();
    }
    return;
  }

  // First check that this number is allowed in this position
  if (!(isAllowed(clickbox, clicknumber, clickcell))) {
    return;
  }

  setNumber(clickbox, clicknumber, clickcell);

  if (f.manual.checked) {
    return;
  }

  doNumber(clickbox, clicknumber, clickcell);

  if (f.flag.checked) {
    doFlags();
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
function isAllowed(clickbox, clicknumber, clickcell) {
/////////////////////////////////////////////////////////////////////////////////////////

  // Check this number in the row
  for (num=1; num<=size; num++) {
    box = order[rows[clickbox]][rows[num]];
    number = order[rows[clicknumber]][cols[num]];
    if (numbers[box][number] == clickcell) {
      alert('Number '+clickcell+' is\nalready displayed\nin this row');
      return false;
    }
  }

  // Check this number in the column
  for (num=1; num<=size; num++) {
    box = order[rows[num]][cols[clickbox]];
    number = order[cols[num]][cols[clicknumber]];
    if (numbers[box][number] == clickcell) {
      alert('Number '+clickcell+' is\nalready displayed\nin this column');
      return false;
    }
  }

  // Check this number in the box
  for (seq=1; seq<=size; seq++) {
    if (numbers[clickbox][seq] == clickcell) {
      alert('Number '+clickcell+' is\nalready displayed\nin this box');
      return false;
    }
  }

  return true;
}

/////////////////////////////////////////////////////////////////////////////////////////
function setNumber(clickbox, clicknumber, clickcell) {
/////////////////////////////////////////////////////////////////////////////////////////

  // Now, set the picture files to the number
  for (cell=1; cell<=size; cell++) { // Cell Loop
    document.images['img'+clickbox+clicknumber+cell].src = 'img/'+clickcell+'_'+cell+'.gif';
  }
  numbers[clickbox][clicknumber] = clickcell;
  remaining--;
}

/////////////////////////////////////////////////////////////////////////////////////////
function doNumber(clickbox, clicknumber, clickcell) {
/////////////////////////////////////////////////////////////////////////////////////////

  var num = "local";
  var box = "local";
  var number = "local";

  // Blank this number in the row
  for (num=1; num<=size; num++) {
    box = order[rows[clickbox]][rows[num]];
    number = order[rows[clicknumber]][cols[num]];
    if ((numbers[box][number] == 0) && (status[box][number][clickcell] == 1)) {
      count[box][number]--;
      status[box][number][clickcell] = 0;
      document.images['img'+box+number+clickcell].src = 'img/transparent.gif';
    }
  }

  // Blank this number in the column
  for (num=1; num<=size; num++) {
    box = order[rows[num]][cols[clickbox]];
    number = order[cols[num]][cols[clicknumber]];
    if ((numbers[box][number] == 0) && (status[box][number][clickcell] == 1)) {
      count[box][number] -=1;
      status[box][number][clickcell] = 0;
      document.images['img'+box+number+clickcell].src = 'img/transparent.gif';
    }
  }

  // Blank this number in the box
  for (number=1; number<=size; number++) {
    if ((numbers[clickbox][number] == 0) && (status[clickbox][number][clickcell] == 1)) {
      count[clickbox][number] -= 1;
      status[clickbox][number][clickcell] = 0;
      document.images['img'+clickbox+number+clickcell].src = 'img/transparent.gif';
    }
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
function doFlags() {
/////////////////////////////////////////////////////////////////////////////////////////

  // Look for Lone numbers in the boxes
  numcount = new Array(size);
  for (box=1; box<=size; box++) { // Box Loop
    for (seq=1; seq<=size; seq++) {
      numcount[seq] = 0;
    }
    for (number=1; number<=size; number++) {
      if (numbers[box][number] == 0) { // Number not already selected
        for (seq=1; seq<=size; seq++) {
          if (status[box][number][seq] == 1) {
            if (numcount[seq] == 0) {
              numcount[seq] = number;
            } else {
              numcount[seq] = 10;
            }
            if (count[box][number] == 1) {
              document.images['img'+box+number+seq].src = 'img/'+seq+'r.gif';
              flag[box][number][seq] = 1;
              if ((f.autosolve.value == 'Y') && (remaining > 0)) {
                setNumber(box, number, seq);
                doNumber(box, number, seq);
                doFlags();
                return;
              }
            } else if (flag[box][number][seq] == 1) {
              document.images['img'+box+number+seq].src = 'img/'+seq+'.gif';
              flag[box][number][seq] = 0;
            }
          }
        }
      } else { // Number already selected
        numcount[numbers[box][number]] = 10;
      }
    }
    for (seq=1; seq<=size; seq++) {
      if ((numcount[seq] != 0) && (numcount[seq] != 10)) {
        document.images['img'+box+numcount[seq]+seq].src = 'img/'+seq+'r.gif';
        flag[box][numcount[seq]][seq] = 1;
        if ((f.autosolve.value == 'Y') && (remaining > 0)) {
          setNumber(box, numcount[seq], seq);
          doNumber(box, numcount[seq], seq);
          doFlags();
          return;
        }
      }
    }
  }

  // Look for Lone numbers in rows
  for (row=1; row<=size; row++) { // Row Loop
    for (seq=1; seq<=size; seq++) {
      numcount[seq] = 0;
    }
    for (col=1; col<=size; col++) {
      box = order[rows[row]][rows[col]];
      number = order[cols[row]][cols[col]];
      if (numbers[box][number] == 0) { // Number not already selected
        for (seq=1; seq<=size; seq++) {
          if (status[box][number][seq] == 1) {
            if (numcount[seq] == 0) {
              numcount[seq] = col;
            } else {
              numcount[seq] = 10;
            }
          }          
        }
      } else { // Number already selected
        numcount[numbers[box][number]] = 10;
      }
    }
    for (seq=1; seq<=size; seq++) {
      if ((numcount[seq] != 0) && (numcount[seq] != 10)) {
        box = order[rows[row]][rows[numcount[seq]]];
        number = order[cols[row]][cols[numcount[seq]]];
        document.images['img'+box+number+seq].src = 'img/'+seq+'r.gif';
        flag[box][number][seq] = 1;
        if ((f.autosolve.value == 'Y') && (remaining > 0)) {
          setNumber(box, number, seq);
          doNumber(box, number, seq);
          doFlags();
          return;
        }
      }
    }
  }

  // Look for Lone numbers in columns
  for (col=1; col<=size; col++) { // Col Loop
    for (seq=1; seq<=size; seq++) {
      numcount[seq] = 0;
    }
    for (row=1; row<=size; row++) {
      box = order[rows[row]][rows[col]];
      number = order[cols[row]][cols[col]];
      if (numbers[box][number] == 0) { // Number not already selected
        for (seq=1; seq<=size; seq++) {
          if (status[box][number][seq] == 1) {
            if (numcount[seq] == 0) {
              numcount[seq] = row;
            } else {
              numcount[seq] = 10;
            }
          }          
        }
      } else { // Number already selected
        numcount[numbers[box][number]] = 10;
      }
    }
    for (seq=1; seq<=size; seq++) {
      if ((numcount[seq] != 0) && (numcount[seq] != 10)) {
        box = order[rows[numcount[seq]]][rows[col]];
        number = order[cols[numcount[seq]]][cols[col]];
        document.images['img'+box+number+seq].src = 'img/'+seq+'r.gif';
        flag[box][number][seq] = 1;
        if ((f.autosolve.value == 'Y') && (remaining > 0)) {
          setNumber(box, number, seq);
          doNumber(box, number, seq);
          doFlags();
          return;
        }
      }
    }
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
function undoFlags() {
/////////////////////////////////////////////////////////////////////////////////////////

  for (box=1; box<=size; box++) {
    for (number=1; number<=size; number++) {
      if (numbers[box][number] == 0) {
        for (cell=1; cell<=size; cell++) {
          if (flag[box][number][cell] == 1) {
            document.images['img'+box+number+cell].src = 'img/'+cell+'.gif';
            flag[box][number][cell] = 0;
          }
        }
      }
    }
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
function doRefresh() {
/////////////////////////////////////////////////////////////////////////////////////////

  // First make all the green numbers visible
  for (box=1; box<=size; box++) {
    for (number=1; number<=size; number++) {
      if (numbers[box][number] == 0) {
        for (cell=1; cell<=size; cell++) {
          if (status[box][number][cell] == 0) {
            document.images['img'+box+number+cell].src = 'img/'+cell+'.gif';
            status[box][number][cell] = 1;
          }
          if (flag[box][number][cell] == 1) {
            document.images['img'+box+number+cell].src = 'img/'+cell+'.gif';
            flag[box][number][cell] = 0;
          }
          count[box][number] = 9;
        }
      }
    }
  }

  // Now remove the green numbers based on the grid
  for (box=1; box<=size; box++) {
    for (number=1; number<=size; number++) {
      if (numbers[box][number] != 0) {
        doNumber(box, number, numbers[box][number]);
      }
    }
  }

  if (f.flag.checked) {
    doFlags();
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
function clickFlags() {
/////////////////////////////////////////////////////////////////////////////////////////

  if (f.flag.checked) {
    doFlags();
  } else {
    undoFlags();
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
function doSolve() {
/////////////////////////////////////////////////////////////////////////////////////////

  // Loop through the boxes and numbers
  f.autosolve.value = 'Y';
  saveflag = f.flag.checked;
  f.flag.checked = false;
  doRefresh();
  f.flag.checked = true;
  doFlags();
  f.autosolve.value = '';
  f.flag.checked = saveflag;
}

/////////////////////////////////////////////////////////////////////////////////////////
function doSave() {
/////////////////////////////////////////////////////////////////////////////////////////

  var parameters = '';
  if (f.manual.checked) {
    parameters = '&manual=on';
  }
  if (f.flag.checked) {
    parameters += '&flag=on';
  }

  // Loop through the boxes and numbers
  data = '';
  for (box=1; box<=size; box++) {
    for (number=1; number<=size; number++) {
      data += numbers[box][number];
    }
  }
  document.location.href = 'save.cgi?data='+data+parameters;
}

/////////////////////////////////////////////////////////////////////////////////////////
function doRestart() {
/////////////////////////////////////////////////////////////////////////////////////////

  var parameters = '';
  if (f.manual.checked) {
    parameters = '&manual=on';
  }
  if (f.flag.checked) {
    parameters += '&flag=on';
  }
  document.location.href = 'sudoku.cgi?game='+f.game.value+parameters;
}

/////////////////////////////////////////////////////////////////////////////////////////
function doRandom() {
/////////////////////////////////////////////////////////////////////////////////////////

  if (f.manual.checked) {
    document.forms.random.manual.value = 'on';
  }
  if (f.flag.checked) {
    document.forms.random.flag.value = 'on';
  }
  return true;
}

/////////////////////////////////////////////////////////////////////////////////////////
function doLoad() {
/////////////////////////////////////////////////////////////////////////////////////////

  if (f.manual.checked) {
    document.forms.load.manual.value = 'on';
  }
  if (f.flag.checked) {
    document.forms.load.flag.value = 'on';
  }
  return true;
}


