home *** CD-ROM | disk | FTP | other *** search
/ GameStar Special 2004 August / GSSH0804.iso / Geschicklichkeit / Enigma / Enigma-081.exe / data / levels / ralf04.lua < prev    next >
Text File  |  2003-05-20  |  16KB  |  610 lines

  1. -- A level for Enigma
  2. -- Name:        Enigris
  3. -- Filename:     ralf04.lua
  4. -- Copyright:     (C) Mar 2003 Ralf Westram
  5. -- Contact:     amgine@reallysoft.de
  6. -- License:     GPL v2.0 or above
  7.  
  8. --warning_raises_error = 1
  9.  
  10. dofile(enigma.FindDataFile("levels/ralf.lua"))
  11.  
  12. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  13.  
  14. floorface      = "fl-marble"
  15. areafloorface  = "fl-sahara"
  16. prevfloorface  = "fl-bluegray"
  17.  
  18. uncountedface  = "st-brick"
  19. countedface    = "st-glass"
  20. wallface       = "st-glass"
  21.  
  22. floorcell      = cell{floor={face=floorface}}
  23. areafloorcell  = cell{floor={face=areafloorface}}
  24. prevfloorcell  = cell{floor={face=prevfloorface}}
  25.  
  26. marble         = cell{actor={face="ac-blackball", attr={player=0}, mode=3}}
  27.  
  28. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  29.  
  30. level = {
  31.    "O!!!!!!!!!!!O.......",
  32.    "%!!!!!!!!!!!%.@@@@@.",
  33.    "%!!!!!!!!!!!%.@@@@@.",
  34.    "%!!!!!!!!!!!%.@@@@@.",
  35.    "%!!!!!!!!!!!%.@@@@@.",
  36.    "%!!!!!!!!!!!%.@@@@@.",
  37.    "%!!!!!!!!!!!%...T...",
  38.    "%!!!!!!!!!!!%.#####.",
  39.    "%!!!!!!!!!!!%.#1 2#.",
  40.    "%!!!!!!!!!!!%.# o #.",
  41.    "%!!!!!!!!!!!%.#3 4#.",
  42.    "%!!!!!!!!!!!%.##5##.",
  43.    "L!!!!!!!!!!!L..###..",
  44. }
  45.  
  46. cells={}
  47. cells["."] = abyss
  48. cells["o"] = marble
  49.  
  50. cells["@"] = prevfloorcell
  51.  
  52. cells["!"] = areafloorcell
  53. cells["%"] = cell{parent=areafloorcell,stone={face=uncountedface}}
  54. cells["L"] = cell{parent=areafloorcell,stone={face="st-laser",attr={on=TRUE, dir=enigma.NORTH,name="soundstone"}}}
  55. cells["O"] = cell{parent={areafloorcell,oxyd}}
  56.  
  57. cells[" "] = floorcell
  58. cells["#"] = cell{parent=floorcell,stone={face=wallface}}
  59. cells["T"] = cell{parent=floorcell,stone={face="st-timer",attr={action="callback", target="tick",interval=0.1}}}
  60. cells["1"] = cell{parent=floorcell,item={face="it-trigger",attr={action="callback", target="trigger1"}}}
  61. cells["2"] = cell{parent=floorcell,item={face="it-trigger",attr={action="callback", target="trigger2"}}}
  62. cells["3"] = cell{parent=floorcell,item={face="it-trigger",attr={action="callback", target="trigger3"}}}
  63. cells["4"] = cell{parent=floorcell,item={face="it-trigger",attr={action="callback", target="trigger4"}}}
  64. cells["5"] = cell{parent=floorcell,item={face="it-trigger",attr={action="callback", target="trigger5"}}}
  65.  
  66. triggers = 5
  67.  
  68. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  69. -- The drop field:
  70. dfieldx,dfieldy = 1,0
  71. dfieldw,dfieldh = 11,13
  72.  
  73. -- The preview field:
  74. pfieldx,pfieldy = 14,0
  75. pfieldw,pfieldh = 5,5
  76.  
  77. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  78. -- The stones:
  79.  
  80. stone1={
  81.    "xx",
  82.    "x ",
  83.    "x ",
  84. }
  85. stone2={
  86.    "x ",
  87.    "x ",
  88.    "xx",
  89. }
  90. stone3={
  91.    "x",
  92.    "x",
  93.    "x",
  94.    "x",
  95. }
  96. stone4={
  97.    "x ",
  98.    "xx",
  99.    " x",
  100. }
  101. stone5={
  102.    " x",
  103.    "xx",
  104.    "x ",
  105. }
  106. stone6={
  107.    " x ",
  108.    "xxx",
  109. }
  110. stone7={
  111.    "xx",
  112.    "xx",
  113. }
  114. --stone8={
  115. --   " x ",
  116. --   "xxx",
  117. --   " x ",
  118. --}
  119. --stone9={
  120. --   "  x",
  121. --   "xxx",
  122. --   "x  ",
  123. --}
  124. --stone10={
  125. --   "x  ",
  126. --   "xxx",
  127. --   "  x",
  128. --}
  129. --stone10={
  130. --   "x   ",
  131. --   "xxxx",
  132. --   "x   ",
  133. --}
  134.  
  135.  
  136. stonedef = {
  137.    stone1, stone2, stone3, stone4, stone5,
  138.    stone6, stone7,
  139. --   stone8, stone9, stone10
  140. } -- list all stones here
  141.  
  142. stoneface = { -- define different faces for the stones
  143.    "st-brownie",
  144.    "st-rock5",
  145.    "st-glass",
  146.    "st-bluegray",
  147.    "st-wood_001",
  148.  
  149.    "st-rock2",
  150.    "st-stone_break",
  151.    "st-fakeoxyd",
  152. --   "st-wood",
  153. --   "st-brick",
  154. --   "st-grate1",
  155. --   "st-grate2",
  156. }
  157.  
  158. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  159.  
  160. randomseed(enigma.GetTicks())
  161. realstonenum = getn(stonedef) -- number of real different stones
  162. stonefacenum = getn(stoneface)
  163. stonexsize = {} -- calculated below
  164. stoneysize = {} -- calculated below
  165.  
  166. -- precalculate sizes of stones
  167. for s=1,realstonenum do
  168.    stonexsize[s],stoneysize[s] = get_map_size(stonedef[s])
  169. end
  170.  
  171. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  172.  
  173. function sound(sound)
  174.    enigma.PlaySound(enigma.GetNamedObject("soundstone"), sound)
  175. end
  176.  
  177. function gen_map(width,height)
  178.    local map={}
  179.    for h=1,height do
  180.       map[h] = strrep(" ",width)
  181.    end
  182.    return map
  183. end
  184.  
  185. function plot_stone(smap,x,y)
  186.    local row = smap[y]
  187.    local nrow = strsub(row,1,x-1).."x"..strsub(row,x+1)
  188.    smap[y] = nrow
  189. end
  190.  
  191. -- generate rotated stones:
  192. stonenum = realstonenum*4 -- including rotated stones
  193. for s=realstonenum+1,stonenum do
  194.    local left = s-realstonenum -- index of same stone (rotated leftwards)
  195.    stonexsize[s],stoneysize[s] = stoneysize[left],stonexsize[left]
  196.    stonedef[s] = gen_map(stonexsize[s],stoneysize[s])
  197.    for y=1,stoneysize[left] do
  198.       local row = stonedef[left][y]
  199.       for x=1,stonexsize[left] do
  200.          if (strsub(row,x,x) == "x") then
  201.             plot_stone(stonedef[s],stonexsize[s]-y+1,x)
  202.          end
  203.       end
  204.    end
  205. end
  206.  
  207. -- plots into a map
  208. -- returns 1 if successfull, 0 otherwise
  209. -- typ == 0 -> empty (always successfull)
  210. --     >= 1 -> number of stoneface
  211. function plot_map(tomap,x,y,typ)
  212. --   print(format("x=%i y=%i typ=%i",x,y,typ))
  213.    local row = tomap[y]
  214.    if (typ > 0) then
  215.       local pos = strsub(row,x,x)
  216.       if (pos >= "1") then return 0 end  -- error, pos already used
  217.    end
  218.    local nrow = strsub(row,1,x-1)
  219.    if (typ==0) then
  220.       nrow = nrow.."-"
  221.    else
  222.       nrow = nrow..tostring(typ)
  223.    end
  224.    nrow = nrow..strsub(row,x+1)
  225.    tomap[y] = nrow
  226.    return 1
  227. end
  228.  
  229. function dump_map(themap)
  230.    for y,str in themap do
  231.       print(y,"'",str,"'")
  232.    end
  233. end
  234.  
  235. -- inserts a stone into a map
  236. -- returns 1, if stone has been inserted
  237. function insert_stone(tomap,x0,y0,stonenr,facenr)
  238.    local stone = stonedef[stonenr]
  239.  
  240. --   print(format("x=%i y=%i stone=%i face=%i",x0,y0,stonenr,facenr))
  241.  
  242.    for y=1,stoneysize[stonenr] do
  243.       local idx = y+y0-1
  244.       if (idx >= 1) then
  245.          local srow = stone[y]
  246. --         print(format("y=%i srow='%s'",y,srow))
  247.  
  248.          for x=1,stonexsize[stonenr] do
  249.             local c = strsub(srow,x,x)
  250. --            print(format("x=%i y=%i c=%s", x,y,c))
  251.             if (c=="x") then
  252.                local ok = plot_map(tomap,x+x0-1,idx,facenr)
  253.  
  254.                if (ok == 0) then
  255.  
  256.                   -- error occurred -> remove already inserted part
  257.                   local xe,ye = x,y -- error position
  258.                   for y=1,ye do
  259.                      idx = y+y0-1
  260.                      if (idx >= 1) then
  261.                         local xm = stonexsize[stonenr]
  262.                         if (y==ye) then xm = xe-1 end
  263.                         srow = stone[y]
  264.                         for x=1,xm do
  265.                            if (strsub(srow,x,x)=="x") then
  266.                               plot_map(tomap,x+x0-1,idx,0)
  267.                            end
  268.                         end
  269.                      end
  270.                   end
  271.                   return 0
  272.  
  273.                end
  274.             end
  275.          end
  276.       end
  277.    end
  278. --   dump_map(tomap)
  279.    return 1
  280. end
  281.  
  282. function remove_stone(frommap,x,y,stonenr)
  283.    return insert_stone(frommap,x,y,stonenr,0)
  284. end
  285.  
  286. function ds(x,y,facenr)
  287.    set_stone(stoneface[facenr],x,y)
  288. end
  289. function rs(x,y)
  290.    enigma.KillStone(x,y)
  291. end
  292. function skull(x,y)
  293.    enigma.KillStone(x,y)
  294.    set_stone("st-death",x,y)
  295.    sound("shatter");
  296. end
  297. function breakout(x,y)
  298.    enigma.KillStone(x,y)
  299. end
  300.  
  301. function nothing(x,y)
  302. end
  303.  
  304. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  305. -- display defs for preview and game map
  306.  
  307. dcells={} -- draw
  308. dcells[" "] = cell{{nothing}}
  309. dcells["-"] = cell{parent={{rs}}}
  310. dcells["S"] = cell{parent={{skull}}}
  311. dcells["X"] = cell{parent={{breakout}}}
  312. for i=1,stonefacenum do
  313.    dcells[tostring(i)] = cell{parent={{ds,i}}}
  314. end
  315.  
  316. pmap = gen_map(pfieldw,pfieldh)
  317. dmap = gen_map(dfieldw,dfieldh)
  318.  
  319.  
  320. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  321. curr_s = {} -- current stone
  322. next_s = {} -- next stone
  323.  
  324. showx = { 3, 3, 2, 2, 1}
  325. showy = { 3, 3, 2, 2, 1}
  326.  
  327. broken_lines = {}
  328.  
  329. normalspeed = 10
  330. points = 0
  331.  
  332. function show_points()
  333.    local p = points
  334.    local x1,x2 = 0,(dfieldx+dfieldw)
  335.    for y=dfieldh-2,1,-1 do
  336.       enigma.KillStone(x1,y)
  337.       if (p>0) then
  338.          set_stone(countedface,x1,y)
  339.          p = p-1
  340.       else
  341.          set_stone(uncountedface,x1,y)
  342.       end
  343.       enigma.KillStone(x2,y)
  344.       if (p>0) then
  345.          set_stone(countedface,x2,y)
  346.          p = p-1
  347.       else
  348.          set_stone(uncountedface,x2,y)
  349.       end
  350.    end
  351. end
  352.  
  353. function check_breakouts()
  354.    local oldpoints = points
  355.    for y,str in dmap do
  356.       local spacefound = 0
  357.       for x=1,dfieldw do
  358.          local c = strsub(str,x,x)
  359.          if ((c==" ") or (c=="-")) then
  360.             spacefound = spacefound+1
  361.          end
  362.       end
  363.       if (spacefound == 0) then
  364.          dmap[y] = strrep("X",dfieldw)
  365.          broken_lines[y] = 1
  366.          points = points+1
  367.       end
  368.    end
  369.    if (oldpoints ~= points) then
  370.       show_points()
  371.       if (points ~= 0) then
  372.          sound("st-magic");
  373.       end
  374.    end
  375. end
  376.  
  377. function fit_broken_lines()
  378.    local maxy = 99
  379.    for y,broken in broken_lines do
  380.       if (broken == 1) then
  381.          if (y < maxy) then
  382.             maxy = y
  383.          end
  384.       end
  385.    end
  386.    if (maxy ~= 99) then
  387.       broken_lines[maxy] = 0
  388.       for y=maxy-1,1,-1 do
  389.          dmap[y+1] = dmap[y]
  390.       end
  391.       dmap[1] = strrep("-",dfieldw)
  392.    else
  393.       broken_lines = {}
  394.    end
  395. end
  396.  
  397. function stone_done(init)
  398.    if (init==0) then
  399.       remove_stone(pmap,next_s.x,next_s.y,next_s.stone)
  400.       curr_s = next_s
  401.       curr_s.x = random(1,dfieldw-stonexsize[curr_s.stone]+1)
  402.       curr_s.y = 2-stoneysize[curr_s.stone]
  403.    end
  404.    local nr = random(1,stonenum)
  405.    next_s = { x=showx[stonexsize[nr]], y=showy[stoneysize[nr]], stone=nr,face=random(1,stonefacenum)}
  406.    check_breakouts()
  407.    insert_stone(pmap,next_s.x,next_s.y,next_s.stone,next_s.face)
  408.    draw_map(pfieldx,pfieldy,pmap,dcells)
  409. end
  410.  
  411. game_over = 0 -- end of game flag
  412.  
  413. -- triggerState    player on        perform
  414. --                 trigger?         action?
  415. --       0           NO               NO
  416. --       1           YES              YES
  417. --       2           NO               YES
  418. --       3           YES              YES
  419. --
  420. -- triggerState changes by player:
  421. --       0 -> 1      step onto trigger
  422. --       1 -> 2      leave trigger (but signal stays valid)
  423. --       2 -> 1      step again onto trigger before signal was received
  424. --       3 -> 0      leave trigger after signal has been received
  425. --
  426. -- triggerState changes by tick():
  427. --       0 -> 0      no trigger -> no action
  428. --       1 -> 3      player on trigger, mark signal as received
  429. --       2 -> 0      player already left trigger, nevertheless perform action
  430. --       3 -> 3      player resting on trigger, perform action as long he rests there
  431. --
  432. -- NOTE: odd trigger means:  player is on trigger
  433. --       even trigger means: player is NOT on trigger
  434.  
  435. triggerState = {}
  436. for x=1,triggers do triggerState[x] = 0 end -- reset triggers
  437.  
  438. function trigger(which) -- by player
  439.    if     (triggerState[which]==0) then triggerState[which] = 1
  440.    elseif (triggerState[which]==1) then triggerState[which] = 2
  441.    elseif (triggerState[which]==2) then triggerState[which] = 1
  442.    elseif (triggerState[which]==3) then triggerState[which] = 0
  443.    end
  444. end
  445.  
  446. function readTrigger(which) -- by tick()
  447.    local action = 1
  448.    if     (triggerState[which]==0) then action = 0
  449.    elseif (triggerState[which]==1) then triggerState[which] = 3
  450.    elseif (triggerState[which]==2) then triggerState[which] = 0
  451.    end
  452.    return action
  453. end
  454.  
  455. function trigger1() trigger(1) end -- move left
  456. function trigger2() trigger(2) end -- move right
  457. function trigger3() trigger(3) end -- turn left
  458. function trigger4() trigger(4) end -- turn right
  459. function trigger5() trigger(5) end -- drop/restart
  460.  
  461. function end_game()
  462.    if (game_over == 0) then
  463.       game_over = 1
  464.       for key,str in dmap do
  465.          dmap[key] = gsub(str,"%d","S")
  466.       end
  467.    end
  468. end
  469.  
  470. speed = normalspeed
  471. ticker = 0
  472.  
  473. function game_tick(fall)
  474.    if (game_over == 0) then
  475.       local stop = 0
  476.       if ((curr_s.y + stoneysize[curr_s.stone]-1) >= dfieldh) then
  477.          stop = 1
  478.       else
  479.          remove_stone(dmap,curr_s.x,curr_s.y,curr_s.stone,curr_s.face)
  480.          local lastx,lasty,laststone = curr_s.x,curr_s.y,curr_s.stone
  481.          local next_sound = ""
  482.  
  483.          -- move/rotate stone
  484.          local user_move = 0
  485.          if (fall == 1) then
  486.             curr_s.y = curr_s.y+1
  487.             if (speed == 1) then
  488.                next_sound = "pickup"
  489.             else
  490.                next_sound = "st-move"
  491.             end
  492.          end
  493.          fit_broken_lines()
  494.          if (speed ~= 1) then
  495.             -- move left
  496.             if ((readTrigger(1) == 1) and (curr_s.x > 1)) then
  497.                curr_s.x = curr_s.x-1
  498.                user_move = 1
  499.                next_sound = "st-move"
  500.             end
  501.  
  502.             -- move right
  503.             if ((readTrigger(2) == 1) and ((curr_s.x + stonexsize[curr_s.stone]) <= dfieldw)) then
  504.                curr_s.x = curr_s.x+1
  505.                user_move = 1
  506.                next_sound = "st-move"
  507.             end
  508.  
  509.             local stoneRotated = 0
  510.             -- rotate left
  511.             if (readTrigger(3) == 1) then
  512.                curr_s.stone = curr_s.stone - realstonenum
  513.                if (curr_s.stone < 1) then
  514.                   curr_s.stone = curr_s.stone + stonenum
  515.                end
  516.                stoneRotated = 1
  517.                next_sound = "st-mirrorturn"
  518.             end
  519.  
  520.             -- rotate right
  521.             if (readTrigger(4) == 1) then
  522.                curr_s.stone = curr_s.stone + realstonenum
  523.                if (curr_s.stone > stonenum) then
  524.                   curr_s.stone = curr_s.stone - stonenum
  525.                end
  526.                stoneRotated = 1
  527.                next_sound = "st-mirrorturn"
  528.             end
  529.  
  530.             -- correct position if stone was rotated
  531.             if (stoneRotated == 1) then
  532.                if ((curr_s.x + stonexsize[curr_s.stone] - 1) > dfieldw) then
  533.                   curr_s.x = dfieldw - (stonexsize[curr_s.stone] - 1)
  534.                end
  535.                user_move = 1
  536.             end
  537.  
  538.             -- drop
  539.             if (readTrigger(5) == 1) then
  540.                speed = 1
  541.                ticker = 0
  542.             end
  543.          end
  544.  
  545.          local ok = insert_stone(dmap,curr_s.x,curr_s.y,curr_s.stone,curr_s.face)
  546.          if ((ok == 0) and (user_move == 1)) then
  547.             -- try again with user move skipped
  548.             curr_s.x     = lastx
  549.             curr_s.stone = laststone
  550.             ok = insert_stone(dmap,curr_s.x,curr_s.y,curr_s.stone,curr_s.face)
  551.          end
  552.  
  553.          if (ok == 0) then -- if error occurred while falling
  554.             curr_s.x,curr_s.y = lastx,lasty
  555.             insert_stone(dmap,curr_s.x,curr_s.y,curr_s.stone,curr_s.face)
  556.             if (curr_s.y <= 1) then -- end of game
  557.                end_game()
  558.             else
  559.                stop = 1
  560.             end
  561.          else
  562.             if (sound ~= "") then
  563.                sound(next_sound)
  564.             end
  565.          end
  566.       end
  567.       if (stop == 1) then
  568.          stone_done(0)
  569.          sound("st-thud")
  570.          speed = ceil(normalspeed-(points/3))
  571.          insert_stone(dmap,curr_s.x,curr_s.y,curr_s.stone,curr_s.face)
  572.       end
  573.       draw_map(dfieldx,dfieldy,dmap,dcells)
  574.    else
  575.       if (readTrigger(5) == 1) then -- restart game
  576.          game_over = 0
  577.          points = 0
  578.          show_points()
  579.          local line = strrep("-", dfieldw)
  580.          for y,str in dmap do
  581.             dmap[y] = line
  582.          end
  583.          stone_done(0)
  584.          draw_map(dfieldx,dfieldy,dmap,dcells)
  585.       end
  586.    end
  587. end
  588.  
  589. function tick()
  590.    ticker = ticker+1
  591.    local xmove1 = floor(speed/3)
  592.    local xmove2 = floor(speed/3*2)
  593.    if (ticker == speed) then
  594.       game_tick(1)
  595.       ticker = 0
  596.    else
  597.       if ((ticker == xmove1) or (ticker == xmove2)) then
  598.          game_tick(0)
  599.       end
  600.    end
  601. end
  602.  
  603. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  604.  
  605. rs_create_world(level,cells,floorcell)
  606. stone_done(1)
  607. stone_done(0)
  608.  
  609.  
  610.