// JavaScript Word Search by Matthew Cole
// Last updated 26/01/2002
// Contact matt@gladys.org

// There is a known bug in this javascript word search:
// Words that contain another of the hidden words should NOT be used.
// EG watermelon should not be used in the same word search as melon.

// Be careful with your grid size in comparison to the number of
// words you have. The less space you have and the more words you
// have the longer it will take to generate the grid on the fly
// Current setup (15 x, 15 y, and 15 words) takes about 5 secs

// Preload images

// Tile path
var tilePath  = "/games/images/lettertiles/";
var imagePath = "/games/images/wordsearch/";
var alphabet  = "abcdefghijklmnopqrstuvwxyz";
// Preload images

_off = new Image(); _off.src = tilePath + "_off.gif";

for (var i = 0; i < alphabet.length; i++)
{
    eval(alphabet.charAt(i) + "_on = new Image();");
    eval(alphabet.charAt(i) + "_on.src = tilePath + \"" + alphabet.charAt(i) + "_on.gif\";");
    eval(alphabet.charAt(i) + "_off = new Image();");
    eval(alphabet.charAt(i) + "_off.src = tilePath + \"" + alphabet.charAt(i) + "_off.gif\";");
    eval(alphabet.charAt(i) + "_high = new Image();");
    eval(alphabet.charAt(i) + "_high.src = tilePath + \"" + alphabet.charAt(i) + "_high.gif\";");
}

// found / not found images

got_no = new Image(); got_no.src = imagePath + "got_no.gif";
got_yes = new Image(); got_yes.src = imagePath + "got_yes.gif";


// Grid dimensions

var gridWidth = 12;
var gridHeight = 12;

// Arrays

var grid = new Array();
//var words = new Array();
var coordList = new Array();
var found = new Array();

// 2D array containing toggles to show which letters are
// highlighted to indicate found words. IE "on" letters
// 1 when highlighted, 0 when not.

found[0]  = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[1]  = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[2]  = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[3]  = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[4]  = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[5]  = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[6]  = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[7]  = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[8]  = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[9]  = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[10] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[11] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[12] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[13] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
found[14] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

// 2D array containing the grid of letters of the wordsearch

grid[0]  = ["","","","","","","","","","","","","","",""];
grid[1]  = ["","","","","","","","","","","","","","",""];
grid[2]  = ["","","","","","","","","","","","","","",""];
grid[3]  = ["","","","","","","","","","","","","","",""];
grid[4]  = ["","","","","","","","","","","","","","",""];
grid[5]  = ["","","","","","","","","","","","","","",""];
grid[6]  = ["","","","","","","","","","","","","","",""];
grid[7]  = ["","","","","","","","","","","","","","",""];
grid[8]  = ["","","","","","","","","","","","","","",""];
grid[9]  = ["","","","","","","","","","","","","","",""];
grid[10] = ["","","","","","","","","","","","","","",""];
grid[11] = ["","","","","","","","","","","","","","",""];
grid[12] = ["","","","","","","","","","","","","","",""];
grid[13] = ["","","","","","","","","","","","","","",""];
grid[14] = ["","","","","","","","","","","","","","",""];

// 2D array containing the list of words to be found and a found "flag"
// to tell if they have been found
/*
words[0] =  ["armchair",   0];
words[1] =  ["bath",       0];
words[2] =  ["bed",        0];
words[3] =  ["bin",        0];
words[4] =  ["cupboard",   0];
words[5] =  ["lamp",       0];
words[6] =  ["oven",       0];
words[7] =  ["shelves",    0];
words[8] =  ["sink",       0];
words[9] =  ["sofa",       0];
words[10] = ["table",      0];
words[11] = ["tap",        0];
words[12] = ["telephone",  0];
words[13] = ["television", 0];
words[14] = ["wardrobe",   0];
*/
// Other global variables

var gameover = false;
var hasclicked = false;
var coordCount = 0;
var clickX;
var clickY;
var foundCount = 0;

// onClick function
// takes x and y coordinates of a letter
function userClick(x,y)
{
  if (!gameover)
  {
    if(hasclicked)
    { 
      checkArray = new Array();      
      checkArray = checkString(getInputString());
      if ( checkArray[0] == true )
      {
        wordFound(checkArray[1])
      }
      deLightRow();
      deLightLetter(clickX,clickY);
      coordCount = 0;
      hasclicked = false;
    }
    else
    {
      clickX = x;
      clickY = y;
      highlightLetter(x,y);
      coordList[0] = [x,y];
      coordCount++;
      hasclicked = true;
    }
  }
  else
  {
    alert("Sorry, this game is over.\nPress \"Restart\" to play this grid again.\nPress \"New Grid\"to play a new grid.");
  }
}

// Mouse over function
// takes x and y coordinates of a letter
function userMouseOver(x,y)
{
  if (!gameover)
  {
    if(hasclicked)
    {
      // The mouse goes over the letter first clicked
      if ((clickX == x) && (clickY == y))
      {

      }
      // Vertical
      else if ( clickX == x )
      {
        if ( clickY < y )
        {
          highlightRow(x,y,0,1);
        }
        if ( clickY > y )
        {
          highlightRow(x,y,0,-1);
        }
      }
      // Horizontal
      else if ( clickY == y )
      {
        if ( clickX < x )
        {
          highlightRow(x,y,1,0);
        }
        if ( clickX > x )
        {
          highlightRow(x,y,-1,0);
        }
      }
      // Left Diagonal
      else if ((clickX - clickY) == (x - y))
      {
        if ( clickY < y )
        {
          highlightRow(x,y,1,1);
        }
        if ( clickY > y )
        {
          highlightRow(x,y,-1,-1);
        }
      }
      // Right Diagonal
      else if ((clickX + clickY) == (x + y))
      {
        if ( clickY < y )
        {
          highlightRow(x,y,-1,1);
        }
        if ( clickY > y )
        {
          highlightRow(x,y,1,-1);
        }
      }
    }
  }
}


// Mouse Out function
function userMouseOut()
{
  if (!gameover)
  {
    if(hasclicked)
    {
      deLightRow();
    }
  }
}

// highlights a row of letters
// takes the x and y coordinates of the last letter in the row
// and the differences between each step in x and y directions
function highlightRow(x,y,diffx,diffy)
{
  var myX = clickX;
  var myY = clickY;
  while ((myX != x) || (myY != y))
  { myX += diffx;
    myY += diffy;
    highlightLetter(myX,myY);
    coordList[coordCount] = [myX,myY];
    coordCount++;
  }
}

// Turns "off" a highlighted row of letters
function deLightRow()
{
  var coordtmp = coordCount;
  for (var iter = 1; iter < coordtmp; iter++)
  {
    deLightLetter(coordList[iter][0],coordList[iter][1]);
    coordCount--;
  }
}

// Highlights a letter
// Takes x and y coordinates of a letter
function highlightLetter(x,y)
{
  document["x" + x + "y" + y].src = eval(grid[y][x] + "_high.src");
}

// Turns a letter "off" or "on" depending upon it's found flag
// Takes x and y coordinates of a letter
function deLightLetter(x,y)
{
  if ( found[y][x] == 1 )
  {
  document["x" + x + "y" + y].src = eval(grid[y][x] + "_on.src");
  }
  else
  {
  document["x" + x + "y" + y].src = eval(grid[y][x] + "_off.src");
  }
}

// Turns a letter "on" and sets it's found flag to true (represented by 1)
// Takes x and y coordinates of a letter
function turnOnFoundLetter(x,y)
{
  found[y][x] = 1;
  document["x" + x + "y" + y].src = eval(grid[y][x] + "_on.src");
}

// Turns the selected string in coordList array "on"
function turnOnFoundRow()
{
  for (var iter = 0; iter < coordCount; iter++)
  {
    turnOnFoundLetter(coordList[iter][0],coordList[iter][1]);
  }
}

// Creates the selected string from coordList array
function getInputString()
{
  var inputStr = "";
  for (var itrt = 0; itrt < coordCount; itrt++)
  {
    inputStr += grid[coordList[itrt][1]][coordList[itrt][0]];
  }
  return(inputStr);
}

// Checks to see if a string matches one of the words in the words array that has not already been found
function checkString(myStr)
{
  var retArray = new Array();
  for (var cnt = 0; cnt < words.length; cnt++)
  {
    if ((( myStr == words[cnt][0].toLowerCase() ) || ( revString(myStr) == words[cnt][0].toLowerCase() )) && ( words[cnt][1] != 1 ))
    {
      retArray[0] = true;
      retArray[1] = cnt;
      return(retArray);
    }
  }
  retArray[0] = false;
  return(retArray);
}

// Reverses a string
// Takes and returns a string
function revString(inStr)
{
  var outStr = "";
  for (var revCount = inStr.length; revCount > 0; revCount--)
  {
    outStr += inStr.charAt(revCount-1);
  }
  return(outStr);
}

// Performs necessary changes when a word is found
// n is an array index of ta word
function wordFound(n)
{
  words[n][1] = 1;
  turnOnFoundRow();
  foundCount++;
  document["list" + n].src = got_yes.src;
  document.getElementById("wordlist" + n).style.color = "#999999";
  document.getElementById("wordlist" + n).style.textDecoration = "line-through";
  changeWordCount( words.length - foundCount);
  if ( foundCount == words.length )
  {
    gameover = true;
  }
}

// Restores images on screen when window resized (JavaScript 1.2 and above only, otherwise ignored)
function onResize()
{
  for (var resCntY = 0; resCntY < gridHeight; resCntY++)
  {
    for (var resCntX = 0; resCntX < gridWidth; resCntX++)
    {
      if ( found[resCntY][resCntX] == 1 )
      {
        document["x" + resCntX + "y" + resCntY].src = eval(grid[resCntY][resCntX] + "_on.src");
      }
      else
      {
        document["x" + resCntX + "y" + resCntY].src = eval(grid[resCntY][resCntX] + "_off.src");
      }
    }
  }
  for (var resCntW = 0; resCntW < words.length; resCntW++)
  {
    if (words[resCntW][1] == 1)
    {
      document["list" + resCntW].src = got_yes.src;
    }
  }
  if (hasclicked)
  {
    highlightLetter(clickX,clickY);
  }

  changeWordCount(words.length - foundCount);
}

// Resets variables and images
function gameReset()
{
  for (var resCntY = 0; resCntY < gridHeight; resCntY++)
  {
    for (var resCntX = 0; resCntX < gridWidth; resCntX++)
    {
      found[resCntY][resCntX] = 0;
      if ( grid[resCntY][resCntX] == 0 )
      {
        document["x" + resCntX + "y" + resCntY].src = eval("a_off.src");
      }
      else
      {
        document["x" + resCntX + "y" + resCntY].src = eval(grid[resCntY][resCntX] + "_off.src");
      }
    }
  }
  for (var resCntW = 0; resCntW < words.length; resCntW++)
  {
    words[resCntW][1] = 0;
    document["list" + resCntW].src = got_no.src;
    document.getElementById("wordlist" + resCntW).style.color = "#FFFFFF";
    document.getElementById("wordlist" + resCntW).style.textDecoration = "none";
  }
  changeWordCount(words.length);
  gameover = false;
  hasclicked = false;
  coordCount = 0;
  foundCount = 0;
}

// clears the grid array
function gridClear()
{
  for (var count = 0; count < gridHeight; count++)
  {
    for (var count2 = 0; count2 < gridWidth; count2++)
    {
      grid[count][count2] = "";
    }
  }
}

// updates the grid on the screen
function gridUpdate()
{
  for (var count = 0; count < gridHeight; count++)
  {
    for (var count2 = 0; count2 < gridWidth; count2++)
    {
      document["x" + count2 + "y" + count].src = eval(grid[count][count2] + "_off.src");
    }
  }
}

// fills in any spaces in the grid array not taken up by words
function fillEmptySquares()
{
  var alphabet = new Array();
  alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
  for (var count = 0; count < gridHeight; count++)
  {
    for (var count2 = 0; count2 < gridWidth; count2++)
    {
      if ( grid[count][count2] == "" )
      {
        var ranNum = Math.floor((Math.random() * alphabet.length));
        grid[count][count2] = alphabet[ranNum];
      }
    }
  }
}

// "on the fly" grid generator
function makeNewGrid()
{
  genGridText();
  gridClear();
  var mybool = false;
  while (!mybool)
  {
    if(fitWords())
    {
      mybool = true;
    }
    else
    {
      gridClear();
    }
  }
  fillEmptySquares();
  gameReset();
}

// fits the words in the grid array
// returns false if it fails
// returns true if it's successful
function fitWords()
{
  var posArr= new Array();
  for (itr = 0; itr < words.length; itr++)
  {
    posArr = willItFit(words[itr][0]);
    if ( posArr.length == 0 )
    {
      return(false);
    }
    else
    {
       var ranNum = Math.floor((Math.random() * posArr.length));
       placeWord(posArr[ranNum],words[itr][0]);
    }
  }
  return(true);
}

// Writes the word into the grid array
function placeWord(inArr,wStr)
{
  Xpos = inArr[0];
  Ypos = inArr[1];
  for (myItr = 0; myItr < wStr.length; myItr++)
  {
    grid[Ypos][Xpos] = wStr.charAt(myItr).toLowerCase();
    Xpos += inArr[2];
    Ypos += inArr[3];
  }
}

// checks all the places a word can go and returns an array with starting
// position and direction variables
// Takes a string
function willItFit(wordStr)
{
  var posPlaces = new Array();
  var wl = wordStr.length;
  for (var count = 0; count < gridHeight; count++)
  {
    for (var count2 = 0; count2 < gridWidth; count2++)
    {
      // Vertical Up
      if ( (count-wl) > 0 )
      {
        if (willItGo(wordStr,count2,count,0,-1))
        {
          posPlaces[posPlaces.length] = [count2,count,0,-1];
        }
      }
      // Vertical Down
      if ( (count+wl) < gridHeight )
      {
        if (willItGo(wordStr,count2,count,0,1))
        {
          posPlaces[posPlaces.length] = [count2,count,0,1];
        }
      }

      // Horizontal Left
      if ( (count2-wl) > 0 )
      {
        if (willItGo(wordStr,count2,count,-1,0))
        {
          posPlaces[posPlaces.length] = [count2,count,-1,0];
        }
      }
      // Horizontal Right
      if ( (count2+wl) < gridWidth )
      {
        if (willItGo(wordStr,count2,count,1,0))
        {
          posPlaces[posPlaces.length] = [count2,count,1,0];
        }
      }
      // Left Diagonal Up
      if (( (count-wl) > 0 ) && ( (count2-wl) > 0 ))
      {
        if (willItGo(wordStr,count2,count,-1,-1))
        {
          posPlaces[posPlaces.length] = [count2,count,-1,-1];
        }
      }
      // Left Diagonal Down
      if (( (count+wl) < gridHeight ) && ( (count2+wl) < gridHeight ))
      {
        if (willItGo(wordStr,count2,count,1,1))
        {
          posPlaces[posPlaces.length] = [count2,count,1,1];
        }
      }
      // Right Diagonal Up
      if (( (count-wl) > 0 ) && ( (count2+wl) < gridWidth ))
      {
        if (willItGo(wordStr,count2,count,1,-1))
        {
          posPlaces[posPlaces.length] = [count2,count,1,-1];
        }
      }
      // Right Diagonal Down
      if (( (count+wl) < gridHeight ) && ( (count2-wl) > 0 ))
      {
        if (willItGo(wordStr,count2,count,-1,1))
        {
          posPlaces[posPlaces.length] = [count2,count,-1,1];
        }
      }
    }
  }
return(posPlaces);
}


// Checks the grid array to see a word can go in a specific place
// wordStr is the string you wish to place
// startx and starty are the starting coords
// xdiff and ydiff are direction variables
function willItGo(wordStr,startx,starty,xdiff,ydiff)
{
  var Xcoord = startx;
  var Ycoord = starty;
  for (cnt = 0; cnt < wordStr.length; cnt++)
  {
    if ((grid[Ycoord][Xcoord] != "") && (grid[Ycoord][Xcoord] != wordStr.charAt(cnt)))
    {
      return(false);
    }
    Xcoord += xdiff;
    Ycoord += ydiff;
  }
  return(true);
}

function genGridText()
{
  gridClear();
  placeWord([1,3,1,0],"generating");
  placeWord([4,4,1,0],"grid");
  placeWord([3,6,1,0],"please");
  placeWord([4,7,1,0],"wait");
  gridUpdate();
}

function changeWordCount(count)
{
    if (count == 0)
    {
        document.getElementById("wordCount").innerHTML = "Well done!";
    }
    else
    {
        document.getElementById("wordCount").innerHTML = count + " word" + ( count != 1 ? "s" : "") + " to find.";
    }
}

// Writes the HTML

var theHTML  = "<div id=\"wordCount\">" + words.length + " word" + (words.length != 1 ? "s" : "") + " to find.</div>";
    theHTML += "<table id=\"wordsearch\"><tr><td>";
    theHTML += "<table><tr><td>";
    theHTML += "<div id=\"theGrid\"><table>";

    for (var count = 0; count < gridHeight; count++)
    {
        theHTML += "<tr>";
        for (var count2 = 0; count2 < gridWidth; count2++)
        {
            theHTML += "<td><a href=\"javascript:userClick(" + count2 + "," + count + ");\" onMouseOver=\"userMouseOver(" + count2 + "," + count + ")\;\" onMouseOut=\"userMouseOut()\;\"><img src=\"/games/images/lettertiles/_off.gif\" width=\"30\" height=\"30\" name=\"x" + count2 + "y" + count + "\" /></a></td>";
        }
        theHTML += "</tr>";
    }
    theHTML += "</table></div>";
    theHTML += "</td>";
    theHTML +="<td><table id=\"wordlist\">";
    for (var count = 0; count < (words.length); count++)
    {
        theHTML += "<tr><td class=\"wordlistEntry\" id=\"wordlist" + count + "\">" + words[count][0] + "</td><td class=\"wordlistEntryImage\"><img src=\"/games/images/wordsearch/got_no.gif\" width=\"25\" height=\"15\" alt=\"Found?\" name=\"list" + count + "\"></td></tr>";
    }
    theHTML += "<tr><td colspan=\"2\"><br /><form name=\"wsearchForm\"><a href=\"javascript:gameReset()\;\"><img src=\"/games/images/wordsearch/restart.gif\" width=\"100\" height=\"28\" alt=\"Restart\" name=\"restart\" /></a><br /><a href=\"javascript:makeNewGrid()\;\"><img src=\"/games/images/wordsearch/newgrid.gif\" width=\"100\" height=\"29\" alt=\"New Grid\" name=\"newGrid\" /></a></form></td></tr>";
    theHTML += "<tr><td colspan=\"2\"><a href=\"/help.php?subject=wordsearch\" target=\"_blank\"><img src=\"/games/images/help.gif\" width=\"100\" height=\"30\" alt=\"Help\" name=\"Help\"></a></td></tr>";
    theHTML += "</table>";
    theHTML += "</td></tr></table>";
    theHTML += "</td></tr></table>";

function drawHTML(divId)
{
    document.getElementById(divId).innerHTML = theHTML;
}

