var maze
var startX
var startY
var startDirection
var lightSource

var message=""
var currentMessage=""

var screen01="01black"
var screen02="02sky"
var screen03="03black"
var screen04="04black"
var screen05="05sky"
var screen06="06black"
var screen07="07black"
var screen08="08black"
var screen09="09black"
var screen10="10black"
var screen11="11black"
var screen12="12black"
var screen13="13black"
var screen14="14black"
var screen15="15black"
var screen16="16black"
var screen17="17black"

var inventory1="00empty"
var inventory2="00empty"
var inventory3="00empty"
var inventory4="00empty"
var inventory5="00empty"
var inventory6="00empty"

var compass=
  (startDirection==3)?"00dirw":(startDirection==2)?"00dirs":
  (startDirection==1)?"00dire":"00dirn"

var started=false
var ended=false

var screenChanged=false
var itemsChanged=false
var compassChanged=false
var messageChanged=false

var positionX=0
var positionY=0
var direction=0
var item=new Array(0,0,0,0,0,0)

var lightTime=0

function updateScreen()
{
  var glassesOn
  var cellX
  var cellY
  var onEdge
  var maskForward
  var maskLeft
  var maskRight

  glassesOn=isItem(2)
  cellX=Math.round((positionX+(direction-1.5)/2)/2)
  cellY=Math.round((positionY+(direction-1.5)/2)/2)
  onEdge=(positionX%2!=0)||(positionY%2!=0)
  maskForward=(glassesOn?0x0011:0x0001)<<direction
  screen02="02sky"
  if (lightTime<=0)
  {
    screen01="01black"
    screen03="03black"
    screen04="04black"
    screen05=
      (onEdge||((maze[cellY][cellX]&maskForward)!=0))?"05sky":"05black"
    screen06="06black"
    screen07="07black"
    screen08="08black"
    screen09="09black"
    screen10="10black"
    screen11="11black"
    screen12="12black"
    screen13="13black"
    screen14="14black"
    screen15="15black"
    screen16="16black"
    screen17="17black"
  }
  else
  {
    maskLeft=(glassesOn?0x0011:0x0001)<<((direction+3)%4)
    maskRight=(glassesOn?0x0011:0x0001)<<((direction+1)%4)
    screen01=
      (onEdge||((maze[cellY][cellX]&maskLeft)==0))?"01wall":"01path"
    screen03=
      (onEdge||((maze[cellY][cellX]&maskRight)==0))?"03wall":"03path"
    screen17="17floor"
    if (!onEdge&&((maze[cellY][cellX]&maskForward)==0))
    {
      screen04="04end1"
      screen05="05end1"
      screen06="06end1"
      screen07="07end1"
      screen08="08end1"
      screen09="09end1"
      screen10="10end1"
      screen11="11end1"
      screen12="12end1"
      screen13="13end1"
      screen14="14end1"
      screen15="15end1"
      screen16="16end1"
    }
    else
    {
      screen05="05sky"
      if (((direction==0)&&(cellY==maze.length-1))||
          ((direction==1)&&(cellX==maze[cellY].length-1))||
          ((direction==2)&&(cellY==0))||
          ((direction==3)&&(cellX==0)))
      {
        screen04="04exit1"
        screen06="06exit1"
        screen07="07exit1"
        screen08="08black"
        screen09="09exit1"
        screen10="10exit1"
        screen11="11black"
        screen12="12exit1"
        screen13="13black"
        screen14="14exit1"
        screen15="15exit1"
        screen16="16exit1"
      }
      else
      {
        if (onEdge)
        {
          cellX+=(direction==3)?-1:(direction==1)?1:0
          cellY+=(direction==2)?-1:(direction==0)?1:0
        }
        onEdge=!onEdge
        screen04=
          (onEdge||((maze[cellY][cellX]&maskLeft)==0))?"04wall":
          (((direction==0)&&(cellX==0))||
           ((direction==1)&&(cellY==maze.length-1))||
           ((direction==2)&&(cellX==maze[cellY].length-1))||
           ((direction==3)&&(cellY==0)))?"04exit":"04path"
        screen06=
          (onEdge||((maze[cellY][cellX]&maskRight)==0))?"06wall":
          (((direction==0)&&(cellX==maze[cellY].length-1))||
          ((direction==1)&&(cellY==0))||
          ((direction==2)&&(cellX==0))||
          ((direction==3)&&(cellY==maze.length-1)))?"06exit":"06path"
        screen16=
          (onEdge||((maze[cellY][cellX]&0xFF00)==0))?"16floor":
          ((maze[cellY][cellX]&0x0F00)!=0)?"16tele":
          ((maze[cellY][cellX]&0xF000)==0xF000)?"16torch":
          ((maze[cellY][cellX]&0xF000)==0x2000)?"16glass":
          ((maze[cellY][cellX]&0xF000)==0x1000)?"16crown":"16floor"
        if ((maze[cellY][cellX]&maskForward)==0)
        {
          screen07="07end2"
          screen08="08end2"
          screen09="09end2"
          screen10="10end2"
          screen11="11end2"
          screen12="12end2"
          screen13="13end2"
          screen14="14end2"
          screen15="15end2"
        }
        else
        {
          screen08="08black"
          if (((direction==0)&&(cellY==maze.length-1))||
              ((direction==1)&&(cellX==maze[cellY].length-1))||
              ((direction==2)&&(cellY==0))||
              ((direction==3)&&(cellX==0)))
          {
            screen07="07exit2"
            screen09="09exit2"
            screen10="10exit2"
            screen11="11black"
            screen12="12exit2"
            screen13="13black"
            screen14="14exit2"
            screen15="15exit2"
          }
          else
          {
            if (onEdge)
            {
              cellX+=(direction==3)?-1:(direction==1)?1:0
              cellY+=(direction==2)?-1:(direction==0)?1:0
            }
            onEdge=!onEdge
            screen07=
              (onEdge||((maze[cellY][cellX]&maskLeft)==0))?"07wall":
              "07path"
            screen09=
              (onEdge||((maze[cellY][cellX]&maskRight)==0))?"09wall":
              "09path"
            screen15=
              (onEdge||((maze[cellY][cellX]&0xFF00)==0))?"15floor":
              ((maze[cellY][cellX]&0x0F00)!=0)?"15tele":
              ((maze[cellY][cellX]&0xF000)==0xF000)?"15torch":
              ((maze[cellY][cellX]&0xF000)==0x2000)?"15glass":
              ((maze[cellY][cellX]&0xF000)==0x1000)?"15crown":"15floor"
            if ((maze[cellY][cellX]&maskForward)==0)
            {
              screen10="10end3"
              screen11="11end3"
              screen12="12end3"
              screen13="13end3"
              screen14="14end3"
            }
            else
            {
              screen11="11black"
              if (((direction==0)&&(cellY==maze.length-1))||
                  ((direction==1)&&(cellX==maze[cellY].length-1))||
                  ((direction==2)&&(cellY==0))||
                  ((direction==3)&&(cellX==0)))
              {
                screen10="10exit3"
                screen12="12exit3"
                screen13="13black"
                screen14="14exit3"
              }
              else
              {
                if (onEdge)
                {
                  cellX+=(direction==3)?-1:(direction==1)?1:0
                  cellY+=(direction==2)?-1:(direction==0)?1:0
                }
                onEdge=!onEdge
                screen10=
                  (onEdge||((maze[cellY][cellX]&maskLeft)==0))?"10wall":
                  "10path"
                screen12=
                  (onEdge||((maze[cellY][cellX]&maskRight)==0))?"12wall":
                  "12path"
                screen14=
                  (!onEdge&&((maze[cellY][cellX]&0x0F00)!=0))?"14tele":
                  "14floor"
                if ((maze[cellY][cellX]&maskForward)==0)
                  screen13="13end4"
                else
                  screen13="13black"
              }
            }
          }
        }
      }
    }
  }
  screenChanged=true
}

function updateCompass()
{
  compass=
    (direction==3)?"00dirw":(direction==2)?"00dirs":
    (direction==1)?"00dire":"00dirn"
  compassChanged=true
}

function updateItems()
{
  inventory1=
    (item[0]==15)?"00torch":(item[0]==2)?"00glass":
    (item[0]==1)?"00crown":"00empty"
  inventory2=
    (item[1]==15)?"00torch":(item[1]==2)?"00glass":
    (item[1]==1)?"00crown":"00empty"
  inventory3=
    (item[2]==15)?"00torch":(item[2]==2)?"00glass":
    (item[2]==1)?"00crown":"00empty"
  inventory4=
    (item[3]==15)?"00torch":(item[3]==2)?"00glass":
    (item[3]==1)?"00crown":"00empty"
  inventory5=
    (item[4]==15)?"00torch":(item[4]==2)?"00glass":
    (item[4]==1)?"00crown":"00empty"
  inventory6=
    (item[5]==15)?"00torch":(item[5]==2)?"00glass":
    (item[5]==1)?"00crown":"00empty"
  itemsChanged=true
}

function updateMessage(text)
{
  if (message.length==0)
    message=text
  else
    message+="\n"+text
  messageChanged=true
}

function clearMessage()
{
  if (message.length!=0)
  {
    message=""
    messageChanged=true
  }
}

function addItem(newItem)
{
  var index
  var count
  var index2

  index=0
  count=0
  while ((index<item.length)&&(item[index]>newItem))
    index++
  while ((index<item.length)&&(item[index]==newItem))
  {
    index++
    count++
  }
  if ((count>=4)||((newItem!=15)&&(count>=1)))
    return false
  for (index2=item.length-1;index2>index;index2--)
    item[index2]=item[index2-1]
  item[index]=newItem
  updateItems()
  return true
}

function removeItem(oldItem)
{
  var index
  var index2

  index=0
  while ((index<item.length)&&(item[index]>=oldItem))
    index++
  if (index==0)
    updateMessage("Internal error: no item "+oldItem+" in inventory")
  else
  {
    if (index<item.length)
      for (index2=index;index2<item.length;index2++)
        item[index2-1]=item[index2]
    item[item.length-1]=0
    updateItems()
  }
}

function isItem(thisItem)
{
  var index

  index=0
  while ((index<item.length)&&(item[index]!=thisItem))
    index++
  return index!=item.length
}

function evaluateLight()
{
  if (lightTime>0)
  {
    if (lightSource<2)
      lightTime--
    if (lightTime<=0)
    {
      removeItem(15)
      if (!isItem(15))
        updateMessage("Your last torch has burnt out.")
      else
        updateMessage("A new torch is lighted.")
    }
  }
  if ((lightTime<=0)&&(isItem(15)))
    lightTime=50
}

function initialize()
{
  var index

  clearMessage()
  positionX=2*startX
  positionY=2*startY
  direction=startDirection
  lightTime=0
  for (index=0;index<6;index++)
    item[index]=0
  if (lightSource>0)
    addItem(15)
  evaluateLight()
  updateCompass()
  updateMessage("Click on the arrows to move.")
  updateScreen()
  started=true
}

function updateWindow()
{
  if (screenChanged)
  {
    document.images["screen1"].src=screen01+".jpg"
    document.images["screen2"].src=screen02+".jpg"
    document.images["screen3"].src=screen03+".jpg"
    document.images["screen4"].src=screen04+".jpg"
    document.images["screen5"].src=screen05+".jpg"
    document.images["screen6"].src=screen06+".jpg"
    document.images["screen7"].src=screen07+".jpg"
    document.images["screen8"].src=screen08+".jpg"
    document.images["screen9"].src=screen09+".jpg"
    document.images["screen10"].src=screen10+".jpg"
    document.images["screen11"].src=screen11+".jpg"
    document.images["screen12"].src=screen12+".jpg"
    document.images["screen13"].src=screen13+".jpg"
    document.images["screen14"].src=screen14+".jpg"
    document.images["screen15"].src=screen15+".jpg"
    document.images["screen16"].src=screen16+".jpg"
    document.images["screen17"].src=screen17+".jpg"
  }
  if (itemsChanged)
  {
    document.images["inventory1"].src=inventory1+".gif"
    document.images["inventory2"].src=inventory2+".gif"
    document.images["inventory3"].src=inventory3+".gif"
    document.images["inventory4"].src=inventory4+".gif"
    document.images["inventory5"].src=inventory5+".gif"
    document.images["inventory6"].src=inventory6+".gif"
  }
  if (compassChanged)
    document.images["compass"].src=compass+".gif"
  if (messageChanged)
  {
    currentMessage=message
    document.MessageForm.MessageBox.value=currentMessage
  }
  screenChanged=false
  itemsChanged=false
  compassChanged=false
  messageChanged=false
}

function restoreMessage()
{
  document.MessageForm.MessageBox.value=currentMessage
}

function handleExit(atExit)
{
  if (atExit)
    if (isItem(1))
      updateMessage
        ("You have done it, you returned the crown! Congratulations!")
    else
      updateMessage
        ("Eternal shame on you! You have returned without the crown.")
  else
    updateMessage
      ("You walked into a trap! There is no way out. You are doomed.")
  updateMessage("Click on the compass to exit.")
  ended=true
}

function doTeleport(X,Y,index)
{
  var cellX
  var cellY

  cellY=0
  cellX=maze[cellY].length
  while ((cellY<maze.length)&&(cellX==maze[cellY].length))
  {
    cellX=0
    while ((cellX<maze[cellY].length)&&
            (((maze[cellY][cellX]&0x0F00)!=(index<<8))||
             ((cellX==X)&&(cellY==Y))))
      cellX++
    if (cellX==maze[cellY].length)
      cellY++
  }
  if (cellY!=maze.length)
  {
    positionX=2*cellX
    positionY=2*cellY
    updateMessage("Teleported!")
  }
  else
    updateMessage
      ("Internal error: no matching teleport destination "+index+".")
}

function evaluatePosition()
{
  var cellX
  var cellY
  var teleport
  var object

  if ((positionX%2==0)&&(positionY%2==0))
  {
    cellX=Math.round(positionX/2)
    cellY=Math.round(positionY/2)
    teleport=maze[cellY][cellX]&0x0F00
    if (teleport!=0)
      doTeleport(cellX,cellY,teleport>>>8)
    else
    {
      object=maze[cellY][cellX]&0xF000
      if (object!=0)
        if (addItem(object>>>12))
          maze[cellY][cellX]&=0x0FFF
    }
  }
  else
  {
    cellY=Math.round((positionY+(direction-1.5)/2)/2)
    if ((positionY==-1)||(positionX==-1)||(positionY==2*maze.length-1)||
        (positionX==2*maze[cellY].length-1))
      handleExit(true)
  }
}

function doMove()
{
  var cellX
  var cellY
  var mask

  evaluateLight()
  if (direction%2!=0)
  {
    if (positionX%2!=0)
    {
      positionX+=(direction==3)?-1:1
      evaluatePosition()
    }
    else
    {
      cellX=Math.round(positionX/2)
      cellY=Math.round((positionY+(direction-1.5)/2)/2)
      mask=0x0011<<direction
      if ((maze[cellY][cellX]&mask)!=0)
      {
        positionX+=(direction==3)?-1:1
        evaluatePosition()
      }
      else
        if ((maze[cellY][cellX]&0x00FF)==0)
          handleExit(false)
        else
          updateMessage("Ouch! That is a solid wall.")
    }
  }
  else
    if (positionY%2!=0)
    {
      positionY+=(direction==2)?-1:1
      evaluatePosition()
    }
    else
    {
      cellX=Math.round((positionX+(direction-1.5)/2)/2)
      cellY=Math.round(positionY/2)
      mask=0x0011<<direction
      if ((maze[cellY][cellX]&mask)!=0)
      {
        positionY+=(direction==2)?-1:1
        evaluatePosition()
      }
      else
        if ((maze[cellY][cellX]&0x00FF)==0)
          handleExit(false)
        else
          updateMessage("Ouch! That is a solid wall.")
    }
  if (!ended)
  {
    evaluateLight()
    updateScreen()
  }
}

function doRotate(quarters)
{
  var cellX
  var cellY
  var mask

  evaluateLight()
  if ((positionX%2!=0)||(positionY%2!=0))
    if (quarters==2)
    {
      direction=(direction+quarters)%4
      updateCompass()
      updateScreen()
    }
    else
      updateMessage("Ouch! That is a solid wall.")
  else
  {
    cellX=Math.round(positionX/2)
    cellY=Math.round(positionY/2)
    mask=0x0011<<((direction+quarters)%4)
    if ((maze[cellY][cellX]&mask)!=0)
    {
      direction=(direction+quarters)%4
      updateCompass()
      updateScreen()
    }
    else
      if ((maze[cellY][cellX]&0x00FF)==0)
        handleExit(false)
      else
        updateMessage("Ouch! That is a solid wall.")
  }
}

function goForward()
{
  if (started&&(!ended))
  {
    clearMessage()
    doMove()
    updateWindow()
  }
}

function goBack()
{
  if (started&&(!ended))
  {
    clearMessage()
    doRotate(2)
    updateWindow()
  }
}

function goLeft()
{
  if (started&&(!ended))
  {
    clearMessage()
    doRotate(3)
    updateWindow()
  }
}

function goRight()
{
  if (started&&(!ended))
  {
    clearMessage()
    doRotate(1)
    updateWindow()
  }
}

function clickCompass()
{
  if (ended)
    history.back()
  else
  {
    if (!started)
      initialize()
    updateWindow()
  }
}

function enableScript(index)
{
  if (index==1)
  {
    maze=
      new Array(
        new Array(0xF001,0x0006,0x0009,0x0003,0x2008),
        new Array(0x0007,0x0109,0x0016,0xF00E,0x0209),
        new Array(0x1004,0x0006,0x004B,0x0009,0x0005),
        new Array(0x0002,0x0109,0x0004,0x0204,0x0005),
        new Array(0x0002,0xF00E,0x000A,0x0028,0xF084))
    startX=1
    startY=0
    startDirection=1
    lightSource=1
  }
  else if (index==2)
  {
    maze=
      new Array(
        new Array(0x0003,0x0008,0x1001,0x0001),
        new Array(0x0006,0x0009,0x0006,0x000D),
        new Array(0x0003,0x000F,0x000A,0x000D),
        new Array(0x0004,0x0005,0x0002,0x000C))
    startX=1
    startY=3
    startDirection=2
    lightSource=2
  }
  else if (index==3)
  {
    maze=
      new Array(
        new Array(0x0003,0x0008,0x0001,0x0002,0x000B,0x2009),
        new Array(0x0005,0x1001,0x0007,0x0008,0x0004,0x0005),
        new Array(0x0006,0x000E,0x000D,0x0002,0x000B,0x000C),
        new Array(0x0003,0x000A,0x002D,0x0081,0x0007,0x000A),
        new Array(0x0006,0x0009,0x0004,0x0007,0x000E,0x0009),
        new Array(0x0002,0x000E,0x0008,0x0004,0x0002,0x000C))
    startX=5
    startY=3
    startDirection=3
    lightSource=2
  }
  else if (index==4)
  {
    maze=
      new Array(
        new Array(0x0003,0xF00A,0x0009,0x0002,0x100A,0x000B,0x0009),
        new Array(0x0005,0x0001,0x0007,0x000B,0x0008,0xF005,0x0004),
        new Array(0x0104,0x0006,0x000C,0x0005,0x0003,0x000F,0x0008),
        new Array(0xF003,0x000B,0x000A,0x020F,0x000C,0x0006,0x0009),
        new Array(0x0004,0x0004,0xF003,0x000C,0x0001,0x0001,0xF004),
        new Array(0x000A,0x0208,0x0007,0x000A,0x000C,0x0007,0x0009),
        new Array(0x0100,0x0002,0x000E,0x000A,0x000A,0xF00C,0x0004))
    startX=0
    startY=5
    startDirection=1
    lightSource=1
  }
  else
  {
    maze=
      new Array(
        new Array(0x0003,0x000B,0x0009,0x0003,0x000A,0x0009,0x0003,0x000A,0x000B,0x0009,0x0002,0x000B,0x0009),
        new Array(0x0007,0xF00D,0x0006,0xF00E,0x0009,0x0006,0x000F,0x0009,0xF005,0x0004,0x0002,0x000D,0x0005),
        new Array(0x0005,0x0006,0x010A,0x0009,0x0007,0x0008,0xF005,0x0006,0x000E,0x0008,0x0003,0xF00C,0x0005),
        new Array(0x0007,0x0008,0x0002,0x000E,0x000C,0x0003,0x000E,0x2008,0x0003,0x000A,0x000D,0x0003,0x000C),
        new Array(0x0005,0x0003,0x0009,0x0002,0x000B,0x000E,0x0008,0x0003,0x000E,0x0008,0xF006,0x000E,0x0009),
        new Array(0x0006,0xF00D,0x0007,0x0008,0x0005,0x0003,0x0009,0xF006,0x000B,0x000A,0x0009,0x0003,0x000C),
        new Array(0x0002,0x000E,0x000E,0x000A,0x000C,0xF007,0x000C,0x0001,0x0024,0x0081,0x0006,0x000D,0x0001),
        new Array(0x0001,0x0003,0x0009,0x0002,0x000B,0x020C,0x0003,0xF00E,0x000B,0xF00C,0x0003,0x000E,0x000D),
        new Array(0x0007,0x000C,0x0006,0xF00B,0x000C,0x0002,0x000F,0x0009,0x0007,0x0009,0xF005,0x0003,0xF00C),
        new Array(0x0007,0xF008,0x0001,0x0006,0x0009,0x0102,0x000C,0x0007,0x000C,0x0004,0x0007,0x000F,0x0008),
        new Array(0x0006,0x0009,0x1005,0x0003,0x000E,0x0008,0x0003,0xF00C,0x0003,0x000A,0x000C,0x0005,0x0001),
        new Array(0x0003,0x000D,0x0006,0xF00D,0x0001,0x0002,0x000F,0x0009,0x0007,0x0008,0x0201,0x0006,0x000D),
        new Array(0x0004,0x0006,0x000A,0x000C,0x0006,0x000A,0x000C,0x0005,0x0006,0x000A,0x000E,0xF00A,0x000C))
    startX=7
    startY=12
    startDirection=2
    lightSource=1
  }
  updateMessage("Welcome to the Hathorian maze.")
  updateMessage("Your task is to find the crown and to return safely.")
  updateMessage("Click on the compass to start your journey.")
  currentMessage=message
  document.MessageForm.MessageBox.value=currentMessage
}

