home *** CD-ROM | disk | FTP | other *** search
- -- A level for Enigma
- -- Name: Enigris
- -- Filename: ralf04.lua
- -- Copyright: (C) Mar 2003 Ralf Westram
- -- Contact: amgine@reallysoft.de
- -- License: GPL v2.0 or above
-
- --warning_raises_error = 1
-
- dofile(enigma.FindDataFile("levels/ralf.lua"))
-
- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-
- floorface = "fl-marble"
- areafloorface = "fl-sahara"
- prevfloorface = "fl-bluegray"
-
- uncountedface = "st-brick"
- countedface = "st-glass"
- wallface = "st-glass"
-
- floorcell = cell{floor={face=floorface}}
- areafloorcell = cell{floor={face=areafloorface}}
- prevfloorcell = cell{floor={face=prevfloorface}}
-
- marble = cell{actor={face="ac-blackball", attr={player=0}, mode=3}}
-
- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-
- level = {
- "O!!!!!!!!!!!O.......",
- "%!!!!!!!!!!!%.@@@@@.",
- "%!!!!!!!!!!!%.@@@@@.",
- "%!!!!!!!!!!!%.@@@@@.",
- "%!!!!!!!!!!!%.@@@@@.",
- "%!!!!!!!!!!!%.@@@@@.",
- "%!!!!!!!!!!!%...T...",
- "%!!!!!!!!!!!%.#####.",
- "%!!!!!!!!!!!%.#1 2#.",
- "%!!!!!!!!!!!%.# o #.",
- "%!!!!!!!!!!!%.#3 4#.",
- "%!!!!!!!!!!!%.##5##.",
- "L!!!!!!!!!!!L..###..",
- }
-
- cells={}
- cells["."] = abyss
- cells["o"] = marble
-
- cells["@"] = prevfloorcell
-
- cells["!"] = areafloorcell
- cells["%"] = cell{parent=areafloorcell,stone={face=uncountedface}}
- cells["L"] = cell{parent=areafloorcell,stone={face="st-laser",attr={on=TRUE, dir=enigma.NORTH,name="soundstone"}}}
- cells["O"] = cell{parent={areafloorcell,oxyd}}
-
- cells[" "] = floorcell
- cells["#"] = cell{parent=floorcell,stone={face=wallface}}
- cells["T"] = cell{parent=floorcell,stone={face="st-timer",attr={action="callback", target="tick",interval=0.1}}}
- cells["1"] = cell{parent=floorcell,item={face="it-trigger",attr={action="callback", target="trigger1"}}}
- cells["2"] = cell{parent=floorcell,item={face="it-trigger",attr={action="callback", target="trigger2"}}}
- cells["3"] = cell{parent=floorcell,item={face="it-trigger",attr={action="callback", target="trigger3"}}}
- cells["4"] = cell{parent=floorcell,item={face="it-trigger",attr={action="callback", target="trigger4"}}}
- cells["5"] = cell{parent=floorcell,item={face="it-trigger",attr={action="callback", target="trigger5"}}}
-
- triggers = 5
-
- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- -- The drop field:
- dfieldx,dfieldy = 1,0
- dfieldw,dfieldh = 11,13
-
- -- The preview field:
- pfieldx,pfieldy = 14,0
- pfieldw,pfieldh = 5,5
-
- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- -- The stones:
-
- stone1={
- "xx",
- "x ",
- "x ",
- }
- stone2={
- "x ",
- "x ",
- "xx",
- }
- stone3={
- "x",
- "x",
- "x",
- "x",
- }
- stone4={
- "x ",
- "xx",
- " x",
- }
- stone5={
- " x",
- "xx",
- "x ",
- }
- stone6={
- " x ",
- "xxx",
- }
- stone7={
- "xx",
- "xx",
- }
- --stone8={
- -- " x ",
- -- "xxx",
- -- " x ",
- --}
- --stone9={
- -- " x",
- -- "xxx",
- -- "x ",
- --}
- --stone10={
- -- "x ",
- -- "xxx",
- -- " x",
- --}
- --stone10={
- -- "x ",
- -- "xxxx",
- -- "x ",
- --}
-
-
- stonedef = {
- stone1, stone2, stone3, stone4, stone5,
- stone6, stone7,
- -- stone8, stone9, stone10
- } -- list all stones here
-
- stoneface = { -- define different faces for the stones
- "st-brownie",
- "st-rock5",
- "st-glass",
- "st-bluegray",
- "st-wood_001",
-
- "st-rock2",
- "st-stone_break",
- "st-fakeoxyd",
- -- "st-wood",
- -- "st-brick",
- -- "st-grate1",
- -- "st-grate2",
- }
-
- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-
- randomseed(enigma.GetTicks())
- realstonenum = getn(stonedef) -- number of real different stones
- stonefacenum = getn(stoneface)
- stonexsize = {} -- calculated below
- stoneysize = {} -- calculated below
-
- -- precalculate sizes of stones
- for s=1,realstonenum do
- stonexsize[s],stoneysize[s] = get_map_size(stonedef[s])
- end
-
- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-
- function sound(sound)
- enigma.PlaySound(enigma.GetNamedObject("soundstone"), sound)
- end
-
- function gen_map(width,height)
- local map={}
- for h=1,height do
- map[h] = strrep(" ",width)
- end
- return map
- end
-
- function plot_stone(smap,x,y)
- local row = smap[y]
- local nrow = strsub(row,1,x-1).."x"..strsub(row,x+1)
- smap[y] = nrow
- end
-
- -- generate rotated stones:
- stonenum = realstonenum*4 -- including rotated stones
- for s=realstonenum+1,stonenum do
- local left = s-realstonenum -- index of same stone (rotated leftwards)
- stonexsize[s],stoneysize[s] = stoneysize[left],stonexsize[left]
- stonedef[s] = gen_map(stonexsize[s],stoneysize[s])
- for y=1,stoneysize[left] do
- local row = stonedef[left][y]
- for x=1,stonexsize[left] do
- if (strsub(row,x,x) == "x") then
- plot_stone(stonedef[s],stonexsize[s]-y+1,x)
- end
- end
- end
- end
-
- -- plots into a map
- -- returns 1 if successfull, 0 otherwise
- -- typ == 0 -> empty (always successfull)
- -- >= 1 -> number of stoneface
- function plot_map(tomap,x,y,typ)
- -- print(format("x=%i y=%i typ=%i",x,y,typ))
- local row = tomap[y]
- if (typ > 0) then
- local pos = strsub(row,x,x)
- if (pos >= "1") then return 0 end -- error, pos already used
- end
- local nrow = strsub(row,1,x-1)
- if (typ==0) then
- nrow = nrow.."-"
- else
- nrow = nrow..tostring(typ)
- end
- nrow = nrow..strsub(row,x+1)
- tomap[y] = nrow
- return 1
- end
-
- function dump_map(themap)
- for y,str in themap do
- print(y,"'",str,"'")
- end
- end
-
- -- inserts a stone into a map
- -- returns 1, if stone has been inserted
- function insert_stone(tomap,x0,y0,stonenr,facenr)
- local stone = stonedef[stonenr]
-
- -- print(format("x=%i y=%i stone=%i face=%i",x0,y0,stonenr,facenr))
-
- for y=1,stoneysize[stonenr] do
- local idx = y+y0-1
- if (idx >= 1) then
- local srow = stone[y]
- -- print(format("y=%i srow='%s'",y,srow))
-
- for x=1,stonexsize[stonenr] do
- local c = strsub(srow,x,x)
- -- print(format("x=%i y=%i c=%s", x,y,c))
- if (c=="x") then
- local ok = plot_map(tomap,x+x0-1,idx,facenr)
-
- if (ok == 0) then
-
- -- error occurred -> remove already inserted part
- local xe,ye = x,y -- error position
- for y=1,ye do
- idx = y+y0-1
- if (idx >= 1) then
- local xm = stonexsize[stonenr]
- if (y==ye) then xm = xe-1 end
- srow = stone[y]
- for x=1,xm do
- if (strsub(srow,x,x)=="x") then
- plot_map(tomap,x+x0-1,idx,0)
- end
- end
- end
- end
- return 0
-
- end
- end
- end
- end
- end
- -- dump_map(tomap)
- return 1
- end
-
- function remove_stone(frommap,x,y,stonenr)
- return insert_stone(frommap,x,y,stonenr,0)
- end
-
- function ds(x,y,facenr)
- set_stone(stoneface[facenr],x,y)
- end
- function rs(x,y)
- enigma.KillStone(x,y)
- end
- function skull(x,y)
- enigma.KillStone(x,y)
- set_stone("st-death",x,y)
- sound("shatter");
- end
- function breakout(x,y)
- enigma.KillStone(x,y)
- end
-
- function nothing(x,y)
- end
-
- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- -- display defs for preview and game map
-
- dcells={} -- draw
- dcells[" "] = cell{{nothing}}
- dcells["-"] = cell{parent={{rs}}}
- dcells["S"] = cell{parent={{skull}}}
- dcells["X"] = cell{parent={{breakout}}}
- for i=1,stonefacenum do
- dcells[tostring(i)] = cell{parent={{ds,i}}}
- end
-
- pmap = gen_map(pfieldw,pfieldh)
- dmap = gen_map(dfieldw,dfieldh)
-
-
- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- curr_s = {} -- current stone
- next_s = {} -- next stone
-
- showx = { 3, 3, 2, 2, 1}
- showy = { 3, 3, 2, 2, 1}
-
- broken_lines = {}
-
- normalspeed = 10
- points = 0
-
- function show_points()
- local p = points
- local x1,x2 = 0,(dfieldx+dfieldw)
- for y=dfieldh-2,1,-1 do
- enigma.KillStone(x1,y)
- if (p>0) then
- set_stone(countedface,x1,y)
- p = p-1
- else
- set_stone(uncountedface,x1,y)
- end
- enigma.KillStone(x2,y)
- if (p>0) then
- set_stone(countedface,x2,y)
- p = p-1
- else
- set_stone(uncountedface,x2,y)
- end
- end
- end
-
- function check_breakouts()
- local oldpoints = points
- for y,str in dmap do
- local spacefound = 0
- for x=1,dfieldw do
- local c = strsub(str,x,x)
- if ((c==" ") or (c=="-")) then
- spacefound = spacefound+1
- end
- end
- if (spacefound == 0) then
- dmap[y] = strrep("X",dfieldw)
- broken_lines[y] = 1
- points = points+1
- end
- end
- if (oldpoints ~= points) then
- show_points()
- if (points ~= 0) then
- sound("st-magic");
- end
- end
- end
-
- function fit_broken_lines()
- local maxy = 99
- for y,broken in broken_lines do
- if (broken == 1) then
- if (y < maxy) then
- maxy = y
- end
- end
- end
- if (maxy ~= 99) then
- broken_lines[maxy] = 0
- for y=maxy-1,1,-1 do
- dmap[y+1] = dmap[y]
- end
- dmap[1] = strrep("-",dfieldw)
- else
- broken_lines = {}
- end
- end
-
- function stone_done(init)
- if (init==0) then
- remove_stone(pmap,next_s.x,next_s.y,next_s.stone)
- curr_s = next_s
- curr_s.x = random(1,dfieldw-stonexsize[curr_s.stone]+1)
- curr_s.y = 2-stoneysize[curr_s.stone]
- end
- local nr = random(1,stonenum)
- next_s = { x=showx[stonexsize[nr]], y=showy[stoneysize[nr]], stone=nr,face=random(1,stonefacenum)}
- check_breakouts()
- insert_stone(pmap,next_s.x,next_s.y,next_s.stone,next_s.face)
- draw_map(pfieldx,pfieldy,pmap,dcells)
- end
-
- game_over = 0 -- end of game flag
-
- -- triggerState player on perform
- -- trigger? action?
- -- 0 NO NO
- -- 1 YES YES
- -- 2 NO YES
- -- 3 YES YES
- --
- -- triggerState changes by player:
- -- 0 -> 1 step onto trigger
- -- 1 -> 2 leave trigger (but signal stays valid)
- -- 2 -> 1 step again onto trigger before signal was received
- -- 3 -> 0 leave trigger after signal has been received
- --
- -- triggerState changes by tick():
- -- 0 -> 0 no trigger -> no action
- -- 1 -> 3 player on trigger, mark signal as received
- -- 2 -> 0 player already left trigger, nevertheless perform action
- -- 3 -> 3 player resting on trigger, perform action as long he rests there
- --
- -- NOTE: odd trigger means: player is on trigger
- -- even trigger means: player is NOT on trigger
-
- triggerState = {}
- for x=1,triggers do triggerState[x] = 0 end -- reset triggers
-
- function trigger(which) -- by player
- if (triggerState[which]==0) then triggerState[which] = 1
- elseif (triggerState[which]==1) then triggerState[which] = 2
- elseif (triggerState[which]==2) then triggerState[which] = 1
- elseif (triggerState[which]==3) then triggerState[which] = 0
- end
- end
-
- function readTrigger(which) -- by tick()
- local action = 1
- if (triggerState[which]==0) then action = 0
- elseif (triggerState[which]==1) then triggerState[which] = 3
- elseif (triggerState[which]==2) then triggerState[which] = 0
- end
- return action
- end
-
- function trigger1() trigger(1) end -- move left
- function trigger2() trigger(2) end -- move right
- function trigger3() trigger(3) end -- turn left
- function trigger4() trigger(4) end -- turn right
- function trigger5() trigger(5) end -- drop/restart
-
- function end_game()
- if (game_over == 0) then
- game_over = 1
- for key,str in dmap do
- dmap[key] = gsub(str,"%d","S")
- end
- end
- end
-
- speed = normalspeed
- ticker = 0
-
- function game_tick(fall)
- if (game_over == 0) then
- local stop = 0
- if ((curr_s.y + stoneysize[curr_s.stone]-1) >= dfieldh) then
- stop = 1
- else
- remove_stone(dmap,curr_s.x,curr_s.y,curr_s.stone,curr_s.face)
- local lastx,lasty,laststone = curr_s.x,curr_s.y,curr_s.stone
- local next_sound = ""
-
- -- move/rotate stone
- local user_move = 0
- if (fall == 1) then
- curr_s.y = curr_s.y+1
- if (speed == 1) then
- next_sound = "pickup"
- else
- next_sound = "st-move"
- end
- end
- fit_broken_lines()
- if (speed ~= 1) then
- -- move left
- if ((readTrigger(1) == 1) and (curr_s.x > 1)) then
- curr_s.x = curr_s.x-1
- user_move = 1
- next_sound = "st-move"
- end
-
- -- move right
- if ((readTrigger(2) == 1) and ((curr_s.x + stonexsize[curr_s.stone]) <= dfieldw)) then
- curr_s.x = curr_s.x+1
- user_move = 1
- next_sound = "st-move"
- end
-
- local stoneRotated = 0
- -- rotate left
- if (readTrigger(3) == 1) then
- curr_s.stone = curr_s.stone - realstonenum
- if (curr_s.stone < 1) then
- curr_s.stone = curr_s.stone + stonenum
- end
- stoneRotated = 1
- next_sound = "st-mirrorturn"
- end
-
- -- rotate right
- if (readTrigger(4) == 1) then
- curr_s.stone = curr_s.stone + realstonenum
- if (curr_s.stone > stonenum) then
- curr_s.stone = curr_s.stone - stonenum
- end
- stoneRotated = 1
- next_sound = "st-mirrorturn"
- end
-
- -- correct position if stone was rotated
- if (stoneRotated == 1) then
- if ((curr_s.x + stonexsize[curr_s.stone] - 1) > dfieldw) then
- curr_s.x = dfieldw - (stonexsize[curr_s.stone] - 1)
- end
- user_move = 1
- end
-
- -- drop
- if (readTrigger(5) == 1) then
- speed = 1
- ticker = 0
- end
- end
-
- local ok = insert_stone(dmap,curr_s.x,curr_s.y,curr_s.stone,curr_s.face)
- if ((ok == 0) and (user_move == 1)) then
- -- try again with user move skipped
- curr_s.x = lastx
- curr_s.stone = laststone
- ok = insert_stone(dmap,curr_s.x,curr_s.y,curr_s.stone,curr_s.face)
- end
-
- if (ok == 0) then -- if error occurred while falling
- curr_s.x,curr_s.y = lastx,lasty
- insert_stone(dmap,curr_s.x,curr_s.y,curr_s.stone,curr_s.face)
- if (curr_s.y <= 1) then -- end of game
- end_game()
- else
- stop = 1
- end
- else
- if (sound ~= "") then
- sound(next_sound)
- end
- end
- end
- if (stop == 1) then
- stone_done(0)
- sound("st-thud")
- speed = ceil(normalspeed-(points/3))
- insert_stone(dmap,curr_s.x,curr_s.y,curr_s.stone,curr_s.face)
- end
- draw_map(dfieldx,dfieldy,dmap,dcells)
- else
- if (readTrigger(5) == 1) then -- restart game
- game_over = 0
- points = 0
- show_points()
- local line = strrep("-", dfieldw)
- for y,str in dmap do
- dmap[y] = line
- end
- stone_done(0)
- draw_map(dfieldx,dfieldy,dmap,dcells)
- end
- end
- end
-
- function tick()
- ticker = ticker+1
- local xmove1 = floor(speed/3)
- local xmove2 = floor(speed/3*2)
- if (ticker == speed) then
- game_tick(1)
- ticker = 0
- else
- if ((ticker == xmove1) or (ticker == xmove2)) then
- game_tick(0)
- end
- end
- end
-
- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-
- rs_create_world(level,cells,floorcell)
- stone_done(1)
- stone_done(0)
-
-
-