-- A level library for Enigma -- Filename: ralf_pento1.lua -- Copyright: (C) Dec 2004 Ralf Westram -- Contact: amgine@reallysoft.de -- License: GPL v2.0 or above if dofile(enigma.FindDataFile("levels/ralf.lua")) == nil then error("can't load 'ralf.lua'"); end flip = {} mirrorx = {} mirrory = {} rot = {} for x=0,4 do for y=0,4 do local i = y*5+x flip[i] = x*5+y rot[i] = x*5+(4-y) mirrorx[i] = y*5+(4-x) mirrory[i] = (4-y)*5+x end end oxydpos={} oxydc=0 area={} areac=0 areaminx = 100 areaminy = 100 field={} fieldc=0 function picked_up(name) local item = enigma.GetNamedObject(name) if (item) then local x,y = enigma.GetPos(item); local itemthere = enigma.GetItem(x,y) if (itemthere==nil) then return 1 end end return 0 end function dumpstate(state,where) if (state==nil) then error("state==nil") end local s = "" for i=0,24 do if (state[i]==1) then s = s..'1'; else s = s..'0'; end end print(where.." '"..s.."'"); end function weight(state) local w = 0 local j = 1 for i=0,24 do if (state[i]==1) then w = w+j end j = j+j end return w end function getstate() local state = {} local i for i=0,24 do local pos = area[i] local st = enigma.GetStone(pos.x,pos.y); if (st == nil) then state[i] = 0 else state[i] = 1 end end return state; end function buildstate(stateid) local state = {} local j = 1 local i for i=0,24 do j=j+j end for i=0,24 do j = floor(j/2) if stateid >= j then state[i] = 1 stateid = stateid-j else state[i] = 0 end end --dumpstate(state,"buildstate") return state end function statesEqual(s1,s2) if ((s1 == nil) or (s2 == nil)) then if (s1 == s2) then return 1 end return 0 end for i=0,24 do if (s1[i]~=s2[i]) then return 0 end end return 1 end function upleftstate(state) local i=0 while (state[i]==0) do i = i+1 end local up = floor(i/5); i=0 while (state[flip[i]]==0) do i = i+1 end local left = floor(i/5); return up,left end function shiftstate(state,shift) if (shift==0) then return state end local newstate = {} local i = shift local j=0 while (i<25) do newstate[j] = state[i] j=j+1 i=i+1 end while (j<25) do newstate[j] = 0 j=j+1 end if (newstate==nil) then error("newstate==nil") end return newstate end function shiftedstate(state) local up,left = upleftstate(state) local shift = up*5+left return shiftstate(state,shift) end bit27 = 2^27 bit13 = 2^13 function centeredstate(state) state = reversestate(shiftedstate(reversestate(state),0)) local beststate = nil local bestdiff = bit27 local up,left = upleftstate(state) up,left = floor(up/2) , floor(left/2) return shiftstate(state,up*5+left) end function reversestate(state) for i=0,12 do local j = 24-i state[i],state[j] = state[j],state[i] end return state end function mirrorxstate(state) local newstate = {} for i=0,24 do newstate[mirrorx[i]] = state[i] end return newstate end function mirrorystate(state) local newstate = {} for i=0,24 do newstate[mirrory[i]] = state[i] end return newstate end function rotstate(state) local newstate = {} for i=0,24 do newstate[rot[i]] = state[i] end return newstate end function simplestmirror(s) local w = weight(s) local s1 = shiftedstate(mirrorxstate(s)) local w1 = weight(s1) local s2 = shiftedstate(mirrorystate(s)) local w2 = weight(s2) local s3 = shiftedstate(mirrorystate(s1)) local w3 = weight(s3) if (w10) then local simple = simplifystate(state) local ws = weight(simple) if (spawned[ws]==1) then unspawnstate(state) local retry = 5 local unwanted = weight(shiftedstate(state)) while (retry>0) do retry=retry-1 local r = random(3) if (r==1) then state = mirrorxstate(state) elseif (r==2) then state = mirrorystate(state) else state = rotstate(state) end state=shiftedstate(state) if (weight(state)~=unwanted) then retry=0 end end spawnstate(centeredstate(state),ws) do_sound("stonetransform") else do_sound("fart") end end end function hammer(x,y) local st = enigma.GetStone(x,y) if ((st ~= nil) and (enigma.GetKind(st)=="st-puzzle")) then local name = get_attrib(st,"pento") if ((name ~= nil) and (strsub(name,1,1)=="p")) then local id = tonumber(strsub(name,2)) if (id ~= nil) then unspawn_stateid(id) local xmin,ymin = x-5,y-5 local xmax,ymax = x+5,y+5 if (xmin<0) then xmin = 0 end if (ymin<0) then ymin = 0 end if (xmax>=worldw) then xmax = worldw end if (ymax>=worldh) then ymax = worldh end for x=xmin,xmax do for y=ymin,ymax do st = enigma.GetStone(x,y) if ((st ~= nil) and (enigma.GetKind(st)=="st-puzzle")) then local name2 = get_attrib(st,"pento") if (name2==name) then kill_stone(x,y) set_item("it-explosion1",x,y) end end end end return 1 end end end return 0 end function sw_kill() if (picked_up("thors")==1) then local it = enigma.GetItem(thorspos.x,thorspos.y) if (it==nil) then document(thorspos.x,thorspos.y,"Drop the hammer!") end else local x,y = enigma.GetPos(enigma.GetNamedObject("thors")) local count = hammer(x-1,y) count = count + hammer(x+1,y) count = count + hammer(x,y-1) count = count + hammer(x,y+1) if (count>0) then do_sound("whitebomb") end end end oxydsset=0 areaset=0 function tick() if (areaset==0 and picked_up("doc")==1) then for i=0,59 do local pos = field[i] set_floor(areafloor,pos.x,pos.y) end areaset=1 end if (oxydsset==0 and getn(unspawned)==0) then local i for i=0,59 do local pos = field[i] local st = enigma.GetStone(pos.x,pos.y) if (st==nil) then return end end setrealoxyds(); oxydsset=1 end end function early_check() if (oxydc~=12) then error("expected to have 12 oxyds") end if (fieldc~=60) then error("expected to have 60 greens") end end