  //***********************************************************************/
  function Dictionary(useDefault)
  {
    //Define Functions
    this.wordInDictionary                  = Dictionary_wordInDictionary;
    this.parseLetterCount                  = Dictionary_parseLetterCount;
    this.findCharOffset                    = Dictionary_findCharOffset;
    this.isWordContainedIn                 = Dictionary_isWordContainedIn;
    this.findMakeableWordList              = Dictionary_findMakeableWordList;
    this.findMakeableWordCountByBruteForce = Dictionary_findMakeableWordCountByBruteForce;
    this.isWordMakableByBruteForce         = Dictionary_isWordMakableByBruteForce;
    this.makeShortenedCardList             = Dictionary_makeShortenedCardList;
    this.init                              = Dictionary_init;

    //init
    this.cheat = false;
    this.words = new Array();
    if (useDefault)
    {
      this.init("ace", "acerous");
    }
    return this;
  }
  //***********************************************************************/
  function Dictionary_init()
  {
  	for(var i = 0; i < arguments.length; i++)
  	{
  	  this.words[i] = arguments[i];
  	}
  }
  //***********************************************************************/
  function Dictionary_wordInDictionary(theWord)
  {
  	theWord = theWord.toLowerCase();
    for (var i = 0; i < this.words.length; i++)
    {
      if(theWord == this.words[i])
      {
        return true;
      }
    }
    return false;
  }
  //***********************************************************************/
  function Dictionary_parseLetterCount(s)
  {
    var letters = new Array(0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0);
    for(var i = 0; i < s.length; i++)
    {
      letters[this.findCharOffset(s.charCodeAt(i))]++;
    }
    return letters;
  }
  //***********************************************************************/
  function Dictionary_findCharOffset(c)
  {
    return (c - "a".charCodeAt(0));
  }
  //***********************************************************************/
  function Dictionary_isWordContainedIn(desiredWord, letters)
  {
    if (letters.length < desiredWord.length)
    {
      //alert("'" + desiredWord + "' is longer than '" + letters + "'");
      return false; //letters does not contain enough letters to work
    }
    var longer = this.parseLetterCount(letters);
    var shorter = this.parseLetterCount(desiredWord);
//    alert("length is " + shorter.length);
    for (var i = 0; i < shorter.length; i++)
    {
      if (longer[i] < shorter[i])
      {
//        if (show)
//        {
//          alert("not enough of " + i + " in '" + letters + "','" + desiredWord + "'" + longer[i] + ", " + shorter[i] );
//        }
        return false; //letters do not have enough of the Letter [i] 
      }
    }
    return true;
  }  
  //***********************************************************************/
  function Dictionary_findMakeableWordList(letters, stopAt1)
  {
  	var matches = new Array(); 
    var total = "";
//    alert("letters = " + letters);
  	//alert("there are " + this.words.length + " words in the dictionary");
    for (var i = 0; i < this.words.length; i++)
    {
    	if (this.isWordContainedIn(this.words[i], letters))
      {
      	matches[matches.length] = this.words[i];
        if (this.cheat)
        {
          total += "\"" + this.words[i] + "\".";
        }
        if (stopAt1)
        {
//          alert("found word in " + i + "/" + this.words.length + " tries");
          return matches;
        }
//        alert(this.words[i] + " is makeable");
      }
    }
    if (this.cheat)
    {
      //alert("There are " + matches + " words that can be made");
      alert(total);
    }
    return matches;
  }
  //***********************************************************************/
  function Dictionary_findMakeableWordCountByBruteForce(wordList, cards, stopAt1)
  {
    var matches = 0; 
//    alert("letters = " + letters);
    //alert("there are " + this.words.length + " words in the dictionary");
    var total = "";
    for (var i = 0; i < wordList.length; i++)
    {
      if (this.isWordMakableByBruteForce("", cards, wordList[i], 0))
      {
        if (this.cheat)
        {
            total += "\"" + wordList[i] + "\".";
        }
        matches++;
        if (stopAt1)
        {
//          alert("found BRUTE word in " + i + "/" + wordList.length + " tries");
          return 1;
        }
      }
    }
    if (this.cheat)
    {
      //alert("There are " + matches + " words that can be made");
      alert(total);
    }
    return matches;
  }
  //***********************************************************************/
  /**
    * Tests if you can make a word by actually stringing together cards.
    **/
  function Dictionary_isWordMakableByBruteForce(startingWord, cards, desiredWord, cardCount)
  {
    //Is Complete
    if (desiredWord.toLowerCase() == startingWord.toLowerCase())
    {
//        alert("\"" + desiredWord + "\"" +" is makeable");
      return (cardCount > 1);
   	}
  	//Is valid so far,
  	if (desiredWord.toLowerCase().substring(0,startingWord.length) != startingWord.toLowerCase())
    {
    	return false;
    }
  	//Add Letters.
  	for(var i = 0; i < cards.length; i++)
    {
    	var newWord = startingWord + cards[i].getLetter();
    	if (this.isWordMakableByBruteForce(newWord, this.makeShortenedCardList(cards, i), desiredWord, cardCount + 1))
      {
//        alert("trickle Down");
      	return true;
      }
    }
    // Nothing Worked
    return false;
  }
  //***********************************************************************/
  /**
    * Creates a clone of an existing array of cards, minus one card.
    * used for the Dictionary_isWordMakableByBruteForce.
    **/
  function Dictionary_makeShortenedCardList(cards, exculed)
  {
  	var list = new Array();
    for(var i = 0; i < cards.length; i++)
    {
    	if (i != exculed)
      {
      	list[list.length] = cards[i];
      }
    }
    return list;
  }
  //***********************************************************************/
  //***********************************************************************/
  