  var firstPlay = false;
  var playerTiles = "";
  var playScore = 0;
  var invRowsAndCols = false;
  var invNoLetter    = "";
  var invJoin        = false;
  var invGap         = false;
  var invFirstPlay   = false;
  var remainingTiles;
  var blanks = 0;
  var tilesPlayed = 0;
  
  var letterValues = new Array(11);
  letterValues[0] = "-";
  letterValues[1]  = "aeilnorstu";
  letterValues[2]  = "dg";
  letterValues[3]  = "bcmp";
  letterValues[4]  = "fhvwy";
  letterValues[5]  = "k";
  letterValues[6]  = "";
  letterValues[7]  = "";
  letterValues[8]  = "jx";
  letterValues[9]  = "";
  letterValues[10] = "qz";
  var theForm = document.forms[0];

  function handleKey(field, event)
  {
    if (event.type == "keyup")
    {
      score();
      return false;
    }

    // else move;
  
    var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;	
               
    var currentName = field.name;
    var newName;
  
    var col = currentName.charAt(3);
    var row = currentName.substring(4, currentName.length);
    row = parseInt(row);	
    var colNum = col.charCodeAt(0);
    
    if (keyCode == 40) // Down
    {
      for (var newRow=row+1; newRow<=14; newRow++)
      {
        newName = "row" + col + newRow;
	var theField = findInputSquare(newName);
          if (theField)
          {
            theField.focus();
            break;
          }
        }
    }
    else if (keyCode == 38) // Up
    {
      for (var newRow=row-1; newRow>=0; newRow--)
      {
        newName = "row" + col + newRow;
	var theField = findInputSquare(newName);
          if (theField)
          {
            theField.focus();
            break;
          }
        }
    }
    else if (keyCode == 37) // Left
    {
      for (var newColNum=colNum-1; newColNum>="a".charCodeAt(0); newColNum--)
      {
        var newCol = String.fromCharCode(newColNum);
        newName = "row" + newCol + row;
	var theField = findInputSquare(newName);
          if (theField)
          {
            theField.focus();
            break;
          }
        }
    }
    else if (keyCode == 39) // Right
    {
      for (var newColNum=colNum+1; newColNum<="o".charCodeAt(0); newColNum++)
      {
        var newCol = String.fromCharCode(newColNum);
        newName = "row" + newCol + row;
	var theField = findInputSquare(newName);
          if (theField)
          {
            theField.focus();
            break;
          }
        }
    }
    else if ((keyCode == 46) || (keyCode == 8) || (keyCode == 32)) // Delete/backspace/space
    {
      theForm.elements[currentName].value = ""; 
      return;
    } 
    else if (letterValue(String.fromCharCode(keyCode).toLowerCase()) >= 0)
    {
      theForm.elements[currentName].value = "";
      return true;
    }
    else if (keyCode == 13) // Return key
    {
    return true;   
    } 
    else if (keyCode == 27)
    {
      return true;  // allow key
    }
    else if (keyCode == 9)
    {
      return true;  // Tab key
    }
    
    return false;
  }
  
  function createPlayerTiles()
  {
    playerTiles = "";
    
    var boardTable = document.getElementById('board');
    var firstRow = (boardTable.rows != null) ? boardTable.rows[0]
                                             : document.getElementById('firstRow');
    
    for (var row = firstRow; row != null; row = row.nextSibling)
    if (row.nodeType == 1)
      for (var cell = row.firstChild, i = 0; cell != null; cell = cell.nextSibling)
        if (cell.nodeType == 1)
        {
          if (cell.id == "vacant")
          {
            var inp = cell.firstChild.firstChild.childNodes[0];
            var val = inp.value;
            if ((val == "") || (val == " "))
              playerTiles += "_";
            else if (letterValue(val.toLowerCase()) > -1)
            {
              playerTiles += val.toLowerCase();
              tilesPlayed++;
            }
            else
              playerTiles += "_";
          }
          else
          {
            playerTiles += "!";
          }
        }
  }   
  
  function findInputSquare(inputName)
  {
    var boardTable = document.getElementById('board');
    var firstRow = (boardTable.rows != null) ? boardTable.rows[0]
                                             : document.getElementById('firstRow');
    
    for (var row = firstRow; row != null; row = row.nextSibling)
    if (row.nodeType == 1)
      for (var cell = row.firstChild, i = 0; cell != null; cell = cell.nextSibling)
        if (cell.nodeType == 1)
        {
          if (cell.id == "vacant")
	  {
	    var inp = cell.firstChild.firstChild.childNodes[0];
	    var name = inp.name;
	    if (name == inputName)
	      return inp;
	  }
	}
	
    return null;
  } 

  function score(event)
  { 
    var plays = "";
    playScore = 0;
    tilesPlayed = 0;
    invNoLetter = "";
    invRowsAndCols = false;
    invFirstPlay = false;
    invJoin = true;
    invGaps = false;
    
    extractRack();
    createPlayerTiles();
    processRack();
    validatePlay();
    
    for (var i=0; i<=14; i++)
      plays += scoreHoriz(i) + scoreVert(i);
      
    var scoreHTML = "Instant Scoring: ";
    
    if (plays.length > 0)    
      scoreHTML += plays.substring(0,plays.length - 2) + " = " + playScore;
     
    if (invNoLetter.length > 0)
      scoreHTML += " <font color='#ff0000'> (Ooops, you do not have the tile(s): '" + invNoLetter.toUpperCase() + "')<font color='#0066cc'> ";
    else if (invRowsAndCols)
      scoreHTML += " <font color='#ff0000'> (Played tiles must be in one row or column)<font color='#0066cc'> ";
    else if (invFirstPlay)
      scoreHTML += " <font color='#ff0000'> (First plays must pass over the centre square)<font color='#0066cc'> ";
    else if (invGaps)
      scoreHTML += " <font color='#ff0000'> (Played tiles are not touching)<font color='#0066cc'> ";
    
    else if ((tilesPlayed > 0) && invJoin && !firstPlay)
     scoreHTML += " <font color='#ff0000'> (Play not touching existing tiles)<font color='#0066cc'> ";

    document.getElementById("score").innerHTML = scoreHTML;  
      
    return true;
  }
  
  function extractRack()
  {
    remainingTiles = "";
    blanks = 0;
    for (var i=0, n = rack.length; i<n; i++)
    {
      var letter = rack.charAt(i);
      if (letter != "&")
        remainingTiles += letter.toLowerCase();
	
      if (letter == "-")
        blanks++;
    }
  }
  
  function processRack()
  {
    var newPlayerTiles = "";
    for (var i=0; i<playerTiles.length; i++)
    {
      var tile = playerTiles.charAt(i);
      if ((tile == "_") || (tile == "!"))
      {
        newPlayerTiles += tile;
        continue;
      }
	
      if (takeLetterFromRack(tile))
        newPlayerTiles += "-";
      else
        newPlayerTiles += tile;
    }
    playerTiles = newPlayerTiles;
  }
  
  function takeLetterFromRack(letter)
  {
    var i = remainingTiles.indexOf(letter);
    
    if (i != -1)
    {
      remainingTiles = remainingTiles.substring(0,i) + remainingTiles.substring(i+1);
      
      if (letter == "-")
        blanks--;
	
      return false;
    }
    
    if (blanks <= 0)
    {
      invNoLetter += letter;
      return false;
    }
  
    i = remainingTiles.indexOf("-");
    
    if (i != -1)
    {
      remainingTiles = remainingTiles.substring(0,i) + remainingTiles.substring(i+1);
      blanks--;
      return true;
    }
    
    invNoLetter += letter;
    return false;
  }
  
   function validatePlay()
  {
    validateRowsAndCols();
    validateGaps();
    
    if (tiles.charAt(7*15+7) == "!")
      firstPlay = true;
    
    if (firstPlay)
      validateFirstPlay();
  }


  
  function validateRowsAndCols()
  {
    invRowsAndCols = false;
    var row = -1;
    var col = -1;
    
    for (var x=0; x<=14; x++)
      for (var y=0; y<=14; y++)
      {
        var c = playerTiles.charAt(y*15+x);
        if (!((c == "_") || (c == "!") || (c == "") || (c == " ")))
        {
          if ((row != -1) && (y != row) && (col != -1) && (x != col))
          {
            invRowsAndCols = true;
            return;
          }
          
          if (row == -1)
            row = y;
            
          if (col == -1)
            col = x;
        }
      }
  }
  
  function validateFirstPlay()
  {
    var c = playerTiles.charAt(7*15+7);
    if ((c == "_") || (c == "!") || (c == "") || (c == " "))
      invFirstPlay = true;
  }
  
  function validateGaps()
  {
    invGaps = false;
    
    for (var x=0; x<=14; x++)
    {
      var userTileFound = false;
      var spaceFound = false;
      for (var y=0; y<=14; y++)
      {
        var c = playerTiles.charAt(y*15+x);
	
        if ((c == "_") && userTileFound) 
          spaceFound = true;
	
        if (!((c == "_") || (c == "!") || (c == "") || (c == " ")))
        {
          if (userTileFound && spaceFound)
          {
            invGaps = true;
            return;
          }
          userTileFound = true;
        }
      }
    }    
   
    for (var y=0; y<=14; y++)
    {
      var userTileFound = false;
      var spaceFound = false;
      for (var x=0; x<=14; x++)
      {
        var c = playerTiles.charAt(y*15+x);
	
        if ((c == "_") && userTileFound) 
          spaceFound = true;
	
        if (!((c == "_") || (c == "!") || (c == "") || (c == " ")))
        {
          if (userTileFound && spaceFound)
          {
            invGaps = true;
            return;
          }
          userTileFound = true;
        }
      }
    }
  }

  function scoreHoriz(row)
  {
    var col = 0;
    var hWords = "";
    
    while(col<=14)
    {
      var word = "";
      var i=col;
      
      var wordMultiplier = 1;
      var wordScore = 0;
      var userTilesUsed = 0;
      var previousPlayTile = false;
      var userWord = false;
      
      for (; i<=14; i++)
      {
        var playerTile = playerTiles.charAt(row*15+i);
          
        if (playerTile == "!")
        {
          previousPlayTile = true;
          var letter = tiles.charAt(row*15+i);
          word += letter.toLowerCase();
          
          if (letter == letter.toLowerCase())
            wordScore += letterValue(letter);
        }
        else
        {
          if (playerTile == "_")
          {
            if (word.length > 0)
              break;
            else
              continue;
          }
            
          word += playerTile;
          wordMultiplier = getWordMultiplier(wordMultiplier, row, i);
          var letterScore = letterValue(playerTile);
          letterScore *= getLetterMultiplier(row, i);
          wordScore += letterScore;
          userWord = true;
          userTilesUsed++;
        }
      }

      if (previousPlayTile && userWord)
        invJoin = false;
 
      col = i;
      wordScore *= wordMultiplier;
      if (userTilesUsed == 7)
        wordScore += 50;
      
      if (userWord && word.length > 1)
      {
        hWords += word.toUpperCase() + " (" + wordScore + "), ";
        playScore += wordScore;
      }
    }
    
    return hWords;
  } 
  
  function scoreVert(col)
  {
    var row = 0;
    var hWords = "";
    
    while(row<=14)
    {
      var word = "";
      var j=row;
      
      var wordMultiplier = 1;
      var wordScore = 0;
      var userTilesUsed = 0;
      var previousPlayTile = false;
      
      var userWord = false;
      
      for (; j<=14; j++)
      {
        var playerTile = playerTiles.charAt(j*15+col);
          
        if (playerTile == "!")
        {
          previousPlayTile = true;
          var letter = tiles.charAt(j*15+col);
          word += letter.toLowerCase();
          if (letter == letter.toLowerCase())
            wordScore += letterValue(letter);
        }
        else
        {
          if (playerTile == "_") // hit empty square
          {
            if (word.length > 0)
              break;
            else
              continue;
          }
            
          word += playerTile;
          wordMultiplier = getWordMultiplier(wordMultiplier, j, col);
          var letterScore = letterValue(playerTile);
          letterScore *= getLetterMultiplier(j, col);
          wordScore += letterScore;
          userWord = true;
          userTilesUsed++;
        }
      }

      if (previousPlayTile && userWord)
        invJoin = false;
	
      row = j;
      wordScore *= wordMultiplier;
      if (userTilesUsed >= 7)
        wordScore += 50;
	      
      if (userWord && word.length > 1)
      {
        hWords += word.toUpperCase() + " (" + wordScore + "), ";
        playScore += wordScore;
      }
    }
    
    return hWords;
  } 
  
  function letterValue(letter)
  {
    for (var l=0; l<letterValues.length; l++)
    {
      if (letterValues[l].indexOf(letter) != -1)
        return l;
    }
     
    // Handle "-" for IE
    if (String.fromCharCode(189).toLowerCase() == letter)
      return 0;

    return -1;
  }
  
  function getWordMultiplier(currentMultiplier, row, col)
  {
    var code = hs.charAt(row*15 + col);
    if (code == "4")
      return currentMultiplier * 3;
    if ((code == "5") || (code == "3"))
      return currentMultiplier * 2;
    
    return currentMultiplier;
  }
  
  function getLetterMultiplier(row, col)
  {
    var code = hs.charAt(row*15 + col);
    if (code == "1")
      return 2;
    if (code == "2")
      return 3;
    
    return 1;
  }