-- Brainf***
-- (c) 2005 Richi Buetzer
-- Licensed under GPL v2.0 or above

create_world(20,13)
oxyd_default_flavor="b"

-- Boden
-- floor
fill_floor("fl-leaves")

  --P
  fill_floor("fl-leavesb",2,4,1,4)
  set_floor("fl-leavesd3",3,4)
  set_floor("fl-leavesd4",3,5)

  --R
  set_floor("fl-leavesb",4,7)
  set_floor("fl-leavesd1",4,6)
  set_floor("fl-leavesd3",5,6)

  --I
  set_floor("fl-leavesb",6,4)
  fill_floor("fl-leavesb",6,6,1,2)

  --N
  fill_floor("fl-leavesb",7,7,2,1)
  set_floor("fl-leavesd1",7,6)
  set_floor("fl-leavesd3",8,6)

  --T
  fill_floor("fl-leavesb",9,4,1,3)
  fill_floor("fl-leavesb",8,5,3,1)
  set_floor("fl-leavesd2",9,7)

  --2
  set_floor("fl-leavesd1",12,4)
  set_floor("fl-leavesb",13,4)
  set_floor("fl-leavesd3",14,4)
  set_floor("fl-leavesb",14,5)
  set_floor("fl-leavesd1",12,6)
  set_floor("fl-leavesb",13,6)
  set_floor("fl-leavesd4",14,6)
  set_floor("fl-leavesb",12,7)
  set_floor("fl-leavesd2",12,8)
  set_floor("fl-leavesb",13,8)
  set_floor("fl-leavesd4",14,8)

  --3
  set_floor("fl-leavesd1",15,3)
  set_floor("fl-leavesb",16,3)
  set_floor("fl-leavesd3",17,3)
  fill_floor("fl-leavesb",17,4,1,3)
  set_floor("fl-leavesb",16,5)
  set_floor("fl-leavesd2",15,7)
  set_floor("fl-leavesb",16,7)
  set_floor("fl-leavesd4",17,7)

-- Steine
-- stones
randstein="st-glass2"

draw_border(randstein)
fill_stones(randstein,1,1,18,2)
fill_stones(randstein,1,9,18,1)
fill_stones(randstein,15,10,1,2)

set_stone("st-door",17,9,{name="tor"})

set_stone("st-switch",1,2,{action="callback",target="add1"})
  set_stone("st-chargeplus",1,1)
set_stone("st-switch",3,2,{action="callback",target="add2"})
  set_stone("st-chargeminus",3,1)
set_stone("st-switch",5,2,{action="callback",target="add3"})
  set_stone("st-mirror-3>",5,1)
set_stone("st-switch",7,2,{action="callback",target="add4"})
  set_stone("st-mirror-3<",7,1)
set_stone("st-switch",9,2,{action="callback",target="add5"})
  set_stone("st-puzzle-e",9,1)
set_stone("st-switch",11,2,{action="callback",target="add6"})
  set_stone("st-puzzle-w",11,1)
set_stone("st-switch",13,2,{action="callback",target="add7"})
  set_stone("st-timeswitch",13,1)

set_stone("st-switch",16,2,{action="callback",target="remove"})
  set_stone("st-glass",16,1)
  set_floor("fl-red",16,1)
  set_item("it-puller-w",16,1)
set_stone("st-switch",18,2,{action="callback",target="run"})
  set_stone("st-glass",18,1)
  set_item("it-puller-e",18,1)

oxyd(16,11)
oxyd(18,11)

-- Was sonst noch auf dem Feld ist
-- Other stuff
set_item("it-document", 5,7, {text="ASCII-Table: ... 48=\"0\", 49=\"1\", 50=\"2\" ..."})
set_item("it-document", 5,8, {text="If you have never heard about Brainf***, visit e.g. http://en.wikipedia.org/wiki/Brainfuck before you try to solve this level."})
set_actor("ac-blackball", 1.5, 6.5, {player="0", mouseforce="1", name="actor"})

-- Lua-Sektion
-- lua-section

n=1 -- Anzahl der gesetzten Zeichen / number of set statements
p={} -- BF-Code

-- Zeichen zum Programm hinzufuegen /add a statement to the programm
function add(str,stone)
  if n>28 then return end
  p[n]=str
  set_stone(stone,ypos(),xpos())
  n=n+1
end

-- Zeichen aus dem Programm entfernen / remove a statement
function remove()
  if n>1 then
    n=n-1
    set_stone("st-invisible",ypos(),xpos())
    --enigma.KillStone(ypos(),xpos())
    p[n]=nil
  end
end

--Gibt x-Position des Steins n aus / return the x-position of a stone
function xpos()
  if n<15 then
    return 10
  else
    return 11
  end
end

--Gibt y-Position des Steins n aus / return the y-position of a stone
function ypos()
  if n<15 then
    return n
  else
    return n-14
  end
end

--Weiterleitungen / forwarding
function add1() add("+","st-chargeplus") end
function add2() add("-","st-chargeminus") end
function add3() add(">","st-mirror-3>") end
function add4() add("<","st-mirror-3<") end
function add5() add("[","st-puzzle-e") end
function add6() add("]","st-puzzle-w") end
function add7() add(".","st-timeswitch") end

error="" --Fehler-Ausgabestring / error-string

function run()
zaehler=1
avoidendless=0 
-- wird bei jeder Anweisung erhoeht. wenn >500, wird Interpreter gestoppt / will be increased at each statement. If >500 the interpreter stops.

a={0} -- BF-Datenfeld / BF-datafield
i=1 -- BF-Zeiger / BF-pointer

output="" --BF-Ausgabestring / BF-output
klammern={} -- Positionen der oeffnenden Klammern. / Positions of the opening brackets
kn=1 -- Tiefe der Schleifenverschachtelung / depth of bracket-nesting

 while zaehler<n do
   if p[zaehler]=="+" then
     a[i]=a[i]+1
   elseif p[zaehler]=="-" then
     a[i]=a[i]-1
   elseif p[zaehler]==">" then
     i=i+1
     if a[i]==nil then a[i]=0 end
   elseif p[zaehler]=="<" then
     if i>1 then
     i=i-1
     else
       setError("Out of range! You wanted to '<' below the first cell.")
       zaehler=n
     end
   elseif p[zaehler]=="[" then
     kn=kn+1
     klammern[kn]=zaehler
   elseif p[zaehler]=="]" then
     if kn<2 then
       setError("\"[\" expected")
       zaehler=n
     else
       if a[i]>0 then
         zaehler=klammern[kn]-1
       else
         klammern[kn]=nil
       end
       kn=kn-1
     end
   elseif p[zaehler]=="." then
     output=output..getAscii(a[i])
   end
   zaehler=zaehler+1
   avoidendless=avoidendless+1
   if avoidendless>500 then
     setError("Infinite loop")
     zaehler=n
   end
 end
   if kn>1 then setError("\"]\" expected") end
 if error=="" then
   set_item("it-document",17,4,{text="Output: \""..output.."\""})
 else
   set_item("it-document",17,4,{text="Error: "..error})
   error=""
 end
 set_item("it-document",17,5,{text="Debug-information: "..getVals(a)})
 --Tor oeffnen / open the door
 if output=="23" then
   SendMessage("tor","open")
 end
end


function getAscii(nr)
  asciitab={"","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""," ","!","\"","#","$","%","&","\'","\(","\)","\*","\+","\,","\-","\.","\/","0","1","2","3","4","5","6","7","8","9","\:","\;","\<","\=","\>","?","@","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","\[","\\","\]","\^","_","`","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","\{","\|","\}","~"}
  if nr>126 or nr<0 then
   return ""
  else
   return asciitab[nr+1]
  end
end

function getVals(a)
  strr=""
  i=1
  while a[i]~=nil do
   strr=strr.." a\["..(i-1).."\]\="..a[i]
   i=i+1
  end
  return strr
end

function setError(msg)
 if error=="" then error=msg end
end









