

var board, planchette;    // DHTML layers.

var boardY, boardY;       // Coordinates.
var nextX, nextY;
var saveX, saveY;
var posX, posY;

var offsetX = 62;         // Offset of viewport on planchette.
var offsetY = 62;

var inReply   = false;    // Status flags.
var inContact = false;

var answer = "";          // Response to spell out.
var nextChar;             // Next character to move to.

var step = 10;            // Used for movement.
var angle;

// Board positions, each letter and number has position. In addition, other
// symbols are used for other areas of the board:
// ! = 'yes'
// ~ = 'no'
// ^ = 'goodbye'
// _ = rest position
// and a space is a blank spot on the board.

var chars = "abcdefghijklmnopqrstuvwxyz1234567890!~^_ ";

// Set up character positions.

posX = new Array(105, 134, 171, 204, 240, 270, 305, 340, 372, 389, 420, 452, 484,
                 114, 151, 182, 217, 249, 274, 300, 331, 365, 399, 436, 466, 492,
                 154, 184, 217, 251, 281, 314, 346, 378, 410, 441,
                 137, 465, 300, 300, 300);
posY = new Array(182, 161, 145, 134, 126, 123, 124, 125, 130, 140, 146, 155, 175,
                 223, 202, 190, 181, 174, 171, 169, 172, 174, 185, 199, 211, 231,
                 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
                 054, 054, 350, 140, 215);

//-----------------------------------------------------------------------------
// Initialize everything.
//-----------------------------------------------------------------------------

function init() {

  var i;

  // Initialize planchette.

  board = getImage("board");
  boardX = getImagePageLeft(board);
  boardY = getImagePageTop(board);

  planchette = getLayer("planchette");
  i = chars.indexOf("_");
  moveLayerTo(planchette, boardX + posX[i] - offsetX, boardY + posY[i] - offsetY);
  showLayer(planchette);
}

//-----------------------------------------------------------------------------
// These functions handle the movement of the planchette when revealing a
// response.
//-----------------------------------------------------------------------------

function handsOn() {

  inContact = true;
}

function handsOff() {

  inContact = false;
  if (inReply) {
    saveX = getLeft(planchette);
    saveY = getTop(planchette);
    shakePlanchette();
  }
}

function startReply() {

  // Start revealing an answer.

  answer += "_";
  if (!inContact) {
    saveX = getLeft(planchette);
    saveY = getTop(planchette);
    shakePlanchette();
  }
  if (getNext()) {
    inReply = true;
    movePlanchette();
  }
  else
    inReply = false;
}

function endReply() {

  // Done revealing answer.

  nextChar = "";
  inReply = false;
  inContact  = false;
}

function getNext() {

  var i;

  // Find the next character to move to.

  if (answer == "")
    return false;

  nextChar = answer.substr(0, 1)
  answer = answer.substr(1);
  for (i = 0; i < chars.length; i++)
    if (chars.charAt(i) == nextChar) {
      nextX = posX[i];
      nextY = posY[i];
      return true;
    }

  return false;
}

function movePlanchette() {

  var i, dx, dy, last, theta;

  // If no reply to give, return.

  if (!inReply)
    return;

  // If mouse is on planchette, move it.

  if (inContact) {

    // Move planchette toward the designated character.

    dx = boardX + nextX - getLeft(planchette) - offsetX;
    dy = boardY + nextY - getTop(planchette) - offsetY;
    theta = Math.round(Math.atan2(-dy, dx) * 180 / Math.PI);
    if (theta < 0)
      theta += 360;

    // If we reached the character, pause and start on the next one.

    if (Math.abs(dx) < step && Math.abs(dy) < step) {
      moveLayerBy(planchette, dx, dy);
      last = nextChar;

      // Circle if next character is the same as the last.

      if (getNext()) {
        if (nextChar == last) {
          angle = 0;
          setTimeout('circlePlanchette()', 2000);
          return;
        }
        setTimeout('movePlanchette()', 2000);
        return
      }

      // End movement if no more characters in reply.

      else
        endReply();
    }

    // If not, move it.

    else if (theta > 23 && theta <= 68)
      moveLayerBy(planchette, step, -step);
    else if (theta > 68 && theta <= 113)
      moveLayerBy(planchette, 0, -step);
    else if (theta > 113 && theta <= 158)
      moveLayerBy(planchette, -step, -step);
    else if (theta > 158 && theta <= 203)
      moveLayerBy(planchette, -step, 0);
    else if (theta > 203 && theta <= 248)
      moveLayerBy(planchette, -step, step);
    else if (theta > 248 && theta <= 293)
      moveLayerBy(planchette, 0, step);
    else if (theta > 293 && theta <= 338)
      moveLayerBy(planchette, step, step);
    else
      moveLayerBy(planchette, step, 0);
  }

  // Set up next call.

  setTimeout('movePlanchette()', 50);
  return;
}

function circlePlanchette() {

  var x, y;

  // Mouse on planchette?

  if (!inContact) {
    setTimeout('circlePlanchette()', 50);
    return;
  }

  // Move the planchette in a small circle.

  x = getLeft(planchette) + step * Math.cos(angle);
  y = getTop(planchette) - step * Math.sin(angle);
  moveLayerTo(planchette, x, y);
  angle += Math.PI / 10;
  if (angle < 2 * Math.PI)
    setTimeout('circlePlanchette()', 50);
  else
    movePlanchette();
}

function shakePlanchette() {

  var dx, dy, x, y;

  // Mouse on planchette?

  if (inContact)
    return;

  // Randomly move planchette around it's original position.

  dx = Math.floor(Math.random() * 5) - 2;
  dy = Math.floor(Math.random() * 5) - 2;
  x = saveX + dx;
  y = saveY + dy;
  moveLayerTo(planchette, x, y);
  setTimeout('shakePlanchette()', 50);
}

//-----------------------------------------------------------------------------
// This code handles the analysis of a question and generates an answer.
//-----------------------------------------------------------------------------

// Lists of responses by category.

var none = new Array("vraag het", "vraag mij", "ik ben hier", "wees niet bang", "spreek",
                     "zeg het mij", "ik luister", "ik wacht");
var days = new Array("zondag", "maandag", "dinsdag", "woensdag", "donderdag",
                     "vrijdag", "zaterdag", "vandaag");
var months = new Array("januari", "februari", "maart", "april", "mei", "juni",
                       "juli", "augustus", "september", "oktober", "november",
                       "december");
var seasons = new Array("voorjaar", "zomer", "herfst", "winter");
var times = new Array("nooit", "binnenkort", "heel gauw", "morgen", "volgende week",
                      "niet nu", "later", "ooit", "niet klaar");
var people = new Array("vriend", "vreemdeling", "jij", "niemand", "een naaste");
var places = new Array("ver weg", "dichtbij", "vlak naast", "ergens anders",
                       "niet hier");
var other = new Array("mag ik niet vertellen", "ik weet het niet", "onbekend", "vraag niet nu",
                      "onbekend", "niet gezien", "misschien later", "wazige toekomst",
                      "te donker", "niet helder", "troebel");
var pim = new Array("hallo is top");
var pimtwee = new Array("pim gunzel");
var eten = new Array("paella", "boerenkool", "tapas", "hutspot", "zuurkool", "pens", "vis",
                     "gravad lax", "kip", "lamsbout", "talinkjes", "biersoep", "patat", "chinees",
                     "indisch", "andijvie", "spinazie", "gehaktbal", "kroket", "brood",
                     "japans", "biefstuk", "bbq");
var weer = new Array("zonnig", "bewolkt", "regen", "koud", "heet", "tropisch", "slecht", "mist",
                     "onweer", "storm", "onbewolkt", "stralend", "lekker", "guur", "mooi", "zomers",
                     "vorst", "sneeuw", "hagel", "buien", "super", "vallende sterren", "zalig");
var persoon = new Array("homo sapiens", "mens", "hallo lezer", "computernerd");
function consult() {

  var question, words, r;
  var i, today;

  // Make up and answer based on keywords in the question.

  inContact = false;
  question = document.forms[0].elements[0].value;
  question = clean(question);
  words = question.split(" ");
  r = Math.random();

  // No question?

  if (question == "") {
    answer = pickFromList(none);
    startReply();
    return false;
  }

  // Look for two words surrounding 'of' and pick one at random.

  if (words.length >= 3)
    for (i = 0; i < words.length - 3; i++)
      if (words[i + 1] == "of") {
        if (r < .5)
          answer = words[i];
        else
          answer = words[i + 2];
        startReply();
        return false;
      }

  // At random, give a ambiguous answer.

  if (r < .1)
    answer = pickFromList(other);

  // Time related question?

  else if (inList(words, "dag")) {         // Pick a random day.
    if (r < .7)
      answer = pickFromList(days);
    else
      answer = pickFromList(times);
  }
  else if (inList(words, "maand")) {    // Pick a random month.
    if (r < .7)
      answer = pickFromList(months);
    else
      answer = pickFromList(times);
  }
  else if (inList(words, "tijd"))            // Pick random time.
    answer = Math.floor(Math.random() * 12) + 1;
  else if (inList(words, "wanneer")) {          // Pick a random time.
    if (r < .3)
      answer = pickFromList(days);
    if (r < .4)
      answer = pickFromList(months);
    if (r < .5)
      answer = pickFromList(seasons);
    else
      answer = pickFromList(times);
  }

  // Asking for a number?

  else if (inList(words, "hoe") &&
      (inList(words, "weinig") ||
       inList(words, "vaak") ||
       inList(words, "veel") ||
       inList(words, "laat"))) {
    answer = Math.round(Math.random() * 10) + 1;    // Give a one or two digit
    if (answer != 10 && r < .5)                     // random number.
      answer += Math.round(Math.random() * 10);
  }

   // Asking for a i.d.?

  else if (inList(words, "wie") &&
      (inList(words, "bent") ||
       inList(words, "jij") ||
       inList(words, "u"))) 
    answer = pickFromList(pimtwee);

   // Asking for uw persoon?

  else if (inList(words, "ik") &&
      (inList(words, "ben") ||
       inList(words, "heet"))) 
    answer = pickFromList(persoon);

   // Asking for eten?

  else if (inList(words, "wat") &&
      (inList(words, "eten") ||
       inList(words, "happen") ||
       inList(words, "koken") ||
       inList(words, "kopen") ||
       inList(words, "halen") ||
       inList(words, "bakken") ||
       inList(words, "eet") ||
       inList(words, "kook") ||
       inList(words, "maken"))) 
    answer = pickFromList(eten);

   // Asking for het weer?

  else if (inList(words, "weer") &&
      (inList(words, "wat") ||
       inList(words, "morgen") ||
       inList(words, "vandaag") ||
       inList(words, "week") ||
       inList(words, "jaar") ||
       inList(words, "voor") ||
       inList(words, "wordt") ||
       inList(words, "was") ||
       inList(words, "is"))) 
    answer = pickFromList(weer);

  // Asking about a person?

  else if (inList(words, "wie"))
    answer = pickFromList(people);

  // Asking about hallo again?

  else if (inList(words, "wie") &&
      (inList(words, "hallo") ||
       inList(words, "gidske") ||
       inList(words, "dikvoormekaar") ||
       inList(words, "web"))) 
    answer = pickFromList(pim);
  
  // Asking about hallo?

  else if (inList(words, "hallo") &&
      (inList(words, "wie") ||
       inList(words, "wat") ||
       inList(words, "of") ||
       inList(words, "mooier") ||
       inList(words, "meest") ||
       inList(words, "best") ||
       inList(words, "beter") ||
       inList(words, "mooiste") ||
       inList(words, "krant") ||
       inList(words, "costa") ||
       inList(words, "blanca") ||
       inList(words, "sol") ||
       inList(words, "weekblad") ||
       inList(words, "nederlandstalig") ||
       inList(words, "gidske") ||
       inList(words, "dik") ||
       inList(words, "dikvoormekaar") ||
       inList(words, "voormekaar") ||
       inList(words, "spanje"))) 
    answer = pickFromList(pim);

  // Asking about a place?

  else if (inList(words, "waar"))
    answer = pickFromList(places);

  // Asking about a thing?

  else if (inList(words, "wat"))
    answer = pickFromList(other);

  // Yes or no question?

  else if (inList(words, "ben") ||
           inList(words, "is") ||
           inList(words, "zijn") ||
           inList(words, "word") ||
           inList(words, "wordt") ||
           inList(words, "doe") ||
           inList(words, "doen") ||
           inList(words, "kan") ||
           inList(words, "zal") ||
           inList(words, "mag") ||
           inList(words, "ga") ||
           inList(words, "gaat") ||
           inList(words, "gaan") ||
           inList(words, "moet")) {
    if (r < .5)
      answer = "!";
    else
      answer = "~";
  }

  // All else failed, give a nice, ambiguous answer.

  if (answer == "")
    answer = pickFromList(other);
  startReply();
  return false;
}

function clean(s) {

  var i, c, t;
  var letters = "abcdefghijklmnopqrstuvwxyz";

  // Convert string to lower case.

  t = s.toLowerCase();

  // Expand any contractions.

  s = "";
  for (i = 0; i < t.length; i++) {
    if (t.substr(i, 2) == "'s") {
      s += " zijn";
      i++;
    }
    else if (t.substr(i, 2) == "'t") {
      s += " not";
      i++;
    }
    else if (t.substr(i, 3) == "'ll") {
      s += " will";
      i += 2;
    }
    else
      s += t.substr(i, 1);
  }

  // Replace any non-letters with spaces.

  t = "";
  for (i = 0; i < s.length; i++) {
    c = s.substr(i, 1);
    if (letters.indexOf(c) >= 0)
      t += c;
    else
      t += " ";
  }
  return t;
}

function inList(list, word) {

  var i;

  // Return true if the given word is in the list.

  for (i = 0; i < list.length; i++)
    if (list[i] == word)
      return true;
  return false;
}

function pickFromList(list) {

  var r;

  // Return a random word from a list.

  r = Math.floor(Math.random() * list.length);
  return list[r];
}
