home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Inne / Gry / Enigma / Enigma-1.01-w7.exe / data / levels / lib / ant.xml < prev    next >
Extensible Markup Language  |  2009-12-13  |  48KB  |  1,545 lines

  1. <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
  2. <el:level xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://enigma-game.org/schema/level/1 level.xsd" xmlns:el="http://enigma-game.org/schema/level/1">
  3.   <el:protected>
  4.     <el:info el:type="library">
  5.       <el:identity el:title="" el:id="lib/ant"/>
  6.       <el:version el:score="1" el:release="1" el:revision="0" el:status="released"/>
  7.       <el:author  el:name="Petr Machata" el:email="" el:homepage=""/>
  8.       <el:copyright>Copyright ┬⌐ 2002-2003 Petr Machata</el:copyright>
  9.       <el:license el:type="GPL v2.0 or above" el:open="true"/>
  10.       <el:compatibility el:enigma="0.92">
  11.         <el:dependency el:path="lib/natmaze" el:id="lib/natmaze" el:release="1" el:preload="false"/>
  12.       </el:compatibility>
  13.       <el:modes el:easy="false" el:single="false" el:network="false"/>
  14.       <el:comments>
  15.         <el:code>Lua 5.1 and XML converted by Leveladministrators</el:code>
  16.       </el:comments>
  17.       <el:score el:easy="-" el:difficult="-"/>
  18.     </el:info>
  19.     <el:luamain><![CDATA[
  20. ------------------------------------------------------------------------
  21. -- Copyright (C) 2002-2003 Petr Machata
  22. --
  23. -- This program is free software; you can redistribute it and/or
  24. -- modify it under the terms of the GNU General Public License
  25. -- as published by the Free Software Foundation; either version 2
  26. -- of the License, or (at your option) any later version.
  27. --
  28. -- This program is distributed in the hope that it will be useful,
  29. -- but WITHOUT ANY WARRANTY; without even the implied warranty of
  30. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  31. -- GNU General Public License for more details.
  32. --
  33. -- You should have received a copy of the GNU General Public License along
  34. -- with this program; if not, write to the Free Software Foundation, Inc.,
  35. -- 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  36. --
  37. -- $Id: ant.lua,v 1.20 2004/02/10 21:47:44 ant_39 Exp $
  38. ------------------------------------------------------------------------
  39. --
  40. -- This module contains All Neccessary Tools for designing enigma maps.
  41. -- There is a documentation available, please read it if you want
  42. -- to find out how to use this (see <enigma-dir>/doc/ant_lua.txt),
  43. -- or look at how miscelaneous ant??.lua maps are done.
  44. -- Any questions, bug reports or anything related to this module please send to:
  45. --   my e-mail:              ant_39 at centrum.cz
  46. --   enigma-devel ML:  enigma-devel at nongnu.org
  47. --
  48. -- revision history:
  49. -- 2003-01-07 -- special floor types and train support
  50. -- 2003-01-11 -- multiples support (groups of doors, bolders etc.)
  51. -- 2003-01-14 -- bugfixes and error reporting, some new map-creating funcs
  52. -- 2003-02-09 --
  53. --   many changes. Fixes of rubberband functions, fixes in multiples support, some interfaces changed
  54. --   These changes require also fixes in several levels, but it's more logic this way. Besides this, it's
  55. --   finally possible to call functions from init.lua or any functions declared like func(x, y, args),
  56. --   for example oxyd(), fakeoxyd(), laser(), ...  and others.
  57. --   While I was rewriting, I finally implemented multichar maps, which I planned since the beginning...
  58. -- 2003-02-11 -- fixes in filling functions
  59. -- 2003-02-12 -- cell() now returns last created object; functional-drawing functions accept table; and fixes
  60. -- 2003-02-20 --
  61. --   major rewrite of cell() function. This require also changes in *all* (~30) levels so far
  62. --   I'll do it now, until there is just a few things to change... Later it could be too late
  63. --   and these changes are really necessary
  64. --   These changes include rewrites in parent function handling, so that it now supports a kind
  65. --   of curried functions from haskell. Also you can use the coordlists instead of simple coords and
  66. --   place several elements at once. And so on...
  67. --   Big changes in interfacing many parent functions, completely rewritten trains and puzzle generators,
  68. --   changes in multiples (there are more kinds, and interfacing changed).
  69. --   A bug in multichar cell key fixed
  70. -- 2003-02-25 --
  71. --   add_multi* now uses tinsert/tremove, functions that work with multiples adapted where necessary
  72. --   some comments fixed, few minor fixes across the source. warning().
  73. -- 2003-03-08 --
  74. --   support for parents that do not accept coordinates, default cell key meanings, updates in default
  75. --   parent handling, debug mode
  76. -- 2003-03-13 -- several cosmetic changes plus add_multitag, spread_tag, wormholes generator and slope generator
  77. -- 2003-03-21 -- warning may raise error if warning_raises_error is set to 1 (ralf)
  78. -- 2003-03-30 --
  79. --   some comments fixed, be_pedantic() added, add_multitag fix, draw_map and get_map_size
  80. --   were broken up to several parts so that particular tasks may be solved as designer wishes.
  81. --   cell0.tag removed - I'm not sure if it was ever used at all...
  82. --   some improvements in handling default cell key meanings at multichar maps
  83. -- 2003-04-12 -- interface of add_multiobject changed to match interface of other multiples
  84. -- 2003-04-25 -- boolean tables
  85. -- 2003-06-19 -- render_puzzles accepts a 'kind' argument. Thanks to ralf!
  86. -- 2003-10-09 -- oxyd_custom, oxyd_col and oxyd_fla added.
  87. -- 2004-02-09 -- add_multitag removed, many cosmetic changes across the code
  88.  
  89.  
  90. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  91. -- MISCELANEOUS - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  92. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  93. -- for warning messages
  94. function warning(text)
  95.    if (warning_raises_error) then
  96.       error(" [ant.lua]: "..text)
  97.    else
  98.       print("warning: [ant.lua]: "..text)
  99.    end
  100. end
  101.  
  102. -- turn warning messages to errors
  103. -- usage: be_pedantic() -> turn on raising errors instead of warnings
  104. function be_pedantic(mode)
  105.    warning_raises_error = ((mode==nil)or(mode~=0))
  106. end
  107.  
  108. -- for debug messages
  109. function debug(text)
  110.    if (DEBUG_MODE) then
  111.       print("debug: [ant.lua]: "..text)
  112.    end
  113. end
  114.  
  115. -- debug mode
  116. -- in debug mode, ant.lua produces messages that inform you about the execution
  117. DEBUG_MODE = nil
  118. function debug_mode()
  119.    DEBUG_MODE = 1
  120.    debug("debug_mode: debug mode turned on")
  121. end
  122.  
  123. -- turn off debug mode
  124. function debug_mode_off()
  125.    debug("debug_mode_off: turning debug mode off")
  126.    DEBUG_MODE = nil
  127. end
  128.  
  129. -- x,y should be numbers, although chars and strings are generally also the right choice
  130. function getkey(...)
  131.    local arg={...}
  132.    local key=""
  133.    for i = 1,getn(arg) do
  134.       if (i > 1) then key = key.."\0" end
  135.       key = key..arg[i]
  136.    end
  137.    return key
  138. end
  139.  
  140. -- todo: deep clone - clone also nested tables
  141. function clone_table(tab)
  142.    local ntab = {}
  143.  
  144.    for key,val in pairs(tab) do
  145.       ntab[key] = val
  146.    end
  147.  
  148.    return ntab;
  149. end
  150.  
  151. -- each ant.lua function, that accepts coordinates, may be
  152. -- called with negative coordinates as well. That in fact
  153. -- means to place the object relatively to lower right
  154. -- corner.
  155. --  location [-1,-1] means [levelw, levelh]
  156. --  size [0,0] means [levelw, levelh]
  157. function transform_coords(x,y,w,h)
  158.    local x, y = (x or 0), (y or 0)
  159.    local w, h = (w or 0), (h or 0)
  160.    if (x <  0) then x = level_width  + x - 1 end
  161.    if (y <  0) then y = level_height + y - 1 end
  162.    if (w <= 0) then w = level_width  + w end
  163.    if (h <= 0) then h = level_height + h end
  164.    return x,y,w,h
  165. end
  166.  
  167. -- this couple of functions takes care of converting common tile coordinates to real coordinates of placed
  168. -- actor. It depends on the given actor_mode, which is being declared like this:
  169. -- cells["O"]=cell{parent=cells["+"], actor={face="ac-blackball", attr={player=0}, mode=ACTOR_MODE}}
  170. --
  171. -- the meaning of actor mode is as follows:
  172. -- value || x | y || meaning
  173. -- ------++---+---++--------
  174. --  0    || 0 | 0 || actor is placed to left top corner of tile
  175. --  1    || 1 | 0 || actor is centered horizontally on tile
  176. --  2    || 0 | 1 || actor is centered vertically on tile
  177. --  3    || 1 | 1 || actor is centered in tile
  178. --
  179. function get_actor_x(x, actor_mode)
  180.    if ((actor_mode == 0) or (actor_mode == 2)) then
  181.       return x
  182.    else
  183.       return x + 0.5
  184.    end
  185. end
  186.  
  187. function get_actor_y(y, actor_mode)
  188.    if ((actor_mode == 0) or (actor_mode == 1)) then
  189.       return y
  190.    else
  191.       return y + 0.5
  192.    end
  193. end
  194.  
  195.  
  196.  
  197.  
  198. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  199. -- VISUAL MAP CREATION  -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  200. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  201.  
  202. -- width of key in map definition
  203. -- CELL_KEY_WIDTH means how many characters occupy single map cell. In several maps I strongly
  204. -- wanted this functions (cannonball for example), and after all here it is. Usable in maps with
  205. -- wide variety of different surfaces.
  206. CELL_KEY_WIDTH = 1
  207. function set_cell_key_width(w)
  208.    if ( (type(w) == "number") and (w>0) and (floor(w) == w) ) then
  209.       CELL_KEY_WIDTH = w
  210.       debug("set_cell_key_width: CELL_KEY_WIDTH is: "..w)
  211.       return w
  212.    else
  213.       warning("set_cell_key_width: CELL_KEY_WIDTH has to be positive whole number")
  214.       return -1
  215.    end
  216. end
  217.  
  218. -- get a table with cell functions
  219. -- with no argument given, global cells is looked for.
  220. -- if none is present, warning occurs.
  221. function get_cellfuncs(cellfuncs)
  222.    local funcs = cellfuncs or cells;  -- hope for a global cells
  223.  
  224.    if (not(funcs)) then
  225.       warning("get_cellfuncs: no cellfuncs declared and global variable 'cells' is absent.")
  226.       funcs = {};
  227.    else
  228.       debug("get_cellfuncs: ok, found cellfuncs table.")
  229.    end
  230.  
  231.    return funcs;
  232. end
  233.  
  234. -- this function tries to guess the width of key.
  235. -- It does so by looking for the most common width of keys in cells[key]
  236. function guess_cell_key_width(cellfuncs)
  237.    local funcs = get_cellfuncs(cellfuncs)
  238.    local freq_table = {}
  239.  
  240.    for key,_ in pairs(funcs) do
  241.       local ktype = type(key)
  242.       if (ktype == "string") then
  243.      local n = strlen(key)
  244.      freq_table[n] = (freq_table[n] or 0)+1
  245.       end
  246.    end
  247.  
  248.    local maxw,maxfreq = 0,0
  249.    for w,freq in pairs(freq_table) do
  250.       if (freq > maxfreq) then
  251.      maxw = w
  252.      maxfreq = freq
  253.       end
  254.    end
  255.  
  256.    debug("guess_cell_key_width: CELL_KEY_WIDTH guessed "..maxw)
  257.    return set_cell_key_width(maxw)
  258. end
  259.  
  260. -- default cell parent is called before any of common cell parents
  261. -- default parent is a table, where each element may be
  262. --  + a function
  263. --  + a string, in which case this is a key in cellfunc table
  264. -- also set_default_parent can be called with a single function
  265. -- or string argument. The table will be built from this.
  266. DEFAULT_CELL_PARENT = nil
  267. function set_default_parent(func)
  268.    if (not(func)) then
  269.       debug("set_default_parent: default parent turned off")
  270.       DEFAULT_CELL_PARENT = nil
  271.       return
  272.    end
  273.  
  274.    if ((type(func) == "function") or (type(func) == "string")) then
  275.       func = {func}
  276.    end
  277.  
  278.    if (type(func) == "table") then
  279.       for key,f in pairs(func) do
  280.      local ftype = type(f)
  281.      if ((ftype ~= "function") and (ftype ~= "string")) then
  282.         warning("set_default_parent: element "..key.." of DEFAULT_CELL_PARENT\n"..
  283.             "has to be function or string, not "..ftype.."!")
  284.         return
  285.      end
  286.       end
  287.       DEFAULT_CELL_PARENT = func
  288.    else
  289.       warning("set_default_parent: default parent has to be\n"..
  290.           "a function, table of functions or string key")
  291.    end
  292. end
  293.  
  294. -- each item:
  295. --  + face - name of stone/floor/item object
  296. --  + attr - set of attributes of given object
  297. function cell_item(it)
  298.    local tit = type(it)
  299.    if (tit == "string") then
  300.       it = {it}
  301.    elseif (tit == "table") then
  302.       -- this is O.K.
  303.    else
  304.       warning("cell_item: cell item may be string or table, not "..tit.."!")
  305.    end
  306.  
  307.    local n_it = {}
  308.    n_it.face = (it.face or it[1] or "")
  309.    n_it.attr = (it.attr or it[2] or {})
  310.    n_it.mode = (it.mode or it[3] or 3)
  311.  
  312.    return n_it
  313. end
  314.  
  315. -- each cell
  316. --  + stone - if present, the stone shall be added to defined position
  317. --  + floor - the same, but for floor
  318. --  + item  - the same, but for item
  319. --  + actor - the same, but for actor
  320. --    ++ mode - see get_actor_x() and _y() functions
  321. --  + mode - parent arglist handling mode. Defaults to 0 and it tells us where to put (x,y) couple in arglist
  322. --    ++ mode = -1 => do not place the (x,y) couple to arglist
  323. --    ++ mode = +0 => place it before parent arguments
  324.  
  325. --  ATTENTION: there *has* to be a coordlist even in case of pmode=-1, or NO arguments may be passed:
  326. --    -> func()
  327. --    -> func(x,y)
  328. --    -> func(x,y, arg1, arg2, ...)
  329. --    -> func(arg1, arg2) --> INCORRECT!!
  330.  
  331. function cell(structure)
  332.    local cell0 = {}
  333.  
  334.    cell0.floor = cell_item(structure.floor or {})
  335.    cell0.stone = cell_item(structure.stone or {})
  336.    cell0.item =  cell_item(structure.item or {})
  337.    cell0.actor = cell_item(structure.actor or {})
  338.  
  339.    -- get parent
  340.    -- parent is declared in this form: parent={{func1, arg1, arg2,...},...}
  341.    -- if it's not, convert to this form
  342.    local parent = (structure.parent or structure[1] or {})
  343.  
  344.    if (type(parent) == "function") then
  345.       parent = {parent}
  346.    elseif (type(parent) == "table") then
  347.       -- this is O.K.
  348.    else
  349.       warning("cell{}: parent has to be a function, a table of functions\n"..
  350.           "or a table of curry-functions, not "..type(parent))
  351.       parent = {}
  352.    end
  353.  
  354.    for a = 1,getn(parent) do
  355.       if (type(parent[a]) == "function") then
  356.      parent[a] = {parent[a]}
  357.       elseif (type(parent[a]) == "table") then
  358.      if (type(parent[a][1]) == "function") then
  359.         -- this is O.K. => a curry function call {func, arg1, arg2, ...}
  360.      else
  361.         warning("cell{}: parent element number "..a.." looks like a curry-function\n"..
  362.             "construction, but its first element isn't a function, it's "..type(parent[a])..".\n"..
  363.             "Using empty function instead.")
  364.         parent[a] = {function() end}
  365.      end
  366.       else
  367.      warning("cell{}: parent element number "..a.." should be a function\n"..
  368.          "or a curry-function construction, not "..type(parent[a])..".\n"..
  369.          "Using empty function instead.")
  370.      parent[a] = {function() end}
  371.       end
  372.    end
  373.  
  374.    --+ this functions manages calling various parent functions. Most functions are just func(x,y) or (x,y,something)
  375.    --  but it's also possible to call ({{x1,y1},{x2,y2}}, something1, something2)
  376.    --  This enables compatibility with and wrapping of functions form init.lua.
  377.    --+ At the same moment, it's possible to declare some parametters in cell functions, like this:
  378.    --     cell1 = cell{parent={{func, par1}}}
  379.    --  and then call  --cell1(par2)--  instead of  --func(par1, par2)--
  380.    --  It may be used as a sort of curried functions from haskell, as far as my poor haskell knowledge says...
  381.    return function(...)
  382.              local arg={...}
  383.          local xylist = tremove(arg, 1) or {}
  384.          local ret = nil
  385.  
  386.          -- first, get rid of cell(x,y) notation and convert it to cell({{x0,y0}}) notation
  387.          local xtp = type(xylist);
  388.          if (xtp == "number") then
  389.         xylist = {{xylist, tremove(arg, 1)}}
  390.          elseif ((xtp == "table") and (type(xylist[1]) == "number")) then
  391.         xylist = {xylist}
  392.          end
  393.  
  394.          for idx = 1,getn(parent) do
  395.         local tab0 = parent[idx]
  396.         --+ tab0 is table. first item is function, the rest are the the function arguments
  397.         --+ first extract function from tab0, then include arguments from function call to the
  398.         --  tab, add a place for x,y coordinates and call it. Eventually tab will look like this:
  399.         --    {x, y, pfpar1, pfpar2, ..., arg1, arg2, ...}
  400.         local func = tab0[1]
  401.         local pmode = tab0.mode or parent.mode or 0
  402.  
  403.         local tab;
  404.         if (pmode == 0) then
  405.            tab = {0,0}
  406.         else
  407.            tab = {}
  408.         end
  409.  
  410.         for a = 2, #tab0 do
  411.            tab[#tab + 1] = tab0[a]
  412.         end
  413.  
  414.         for a = 1,#arg do
  415.            tab[#tab + 1] = arg[a]
  416.         end
  417.  
  418.         -- and call a function
  419.         if (pmode == 0) then
  420.            for i = 1,#xylist do
  421.               tab[1],tab[2] = transform_coords(xylist[i][1], xylist[i][2])
  422.               ret = func(unpack(tab))
  423.            end
  424.         else
  425.            ret = func(unpack(tab))
  426.         end
  427.          end
  428.  
  429.          --process common map elements
  430.          for i = 1,#xylist do
  431.         local x,y = transform_coords(xylist[i][1], xylist[i][2])
  432.         if (structure.stone) then ret = set_stone(cell0.stone.face, x, y, cell0.stone.attr) end
  433.         if (structure.floor) then ret = set_floor(cell0.floor.face, x, y, cell0.floor.attr) end
  434.         if (structure.item ) then ret = set_item (cell0.item.face , x, y, cell0.item.attr ) end
  435.         if (structure.actor) then
  436.            local ax, ay = get_actor_x(x, cell0.actor.mode), get_actor_y(y, cell0.actor.mode)
  437.            ret = set_actor(cell0.actor.face, ax, ay, cell0.actor.attr)
  438.         end
  439.          end
  440.          return ret
  441.       end
  442. end
  443.  
  444. -- height is just number of lines
  445. function get_map_height(map)
  446.    return getn(map)
  447. end
  448.  
  449. -- width of particular map row
  450. function map_row_length(y, map)
  451.    return floor( strlen( map[y]) / CELL_KEY_WIDTH);
  452. end
  453.  
  454. -- width - this is width of the widest row of map
  455. function get_map_width(map)
  456.    local mapw = 0
  457.  
  458.    for y = 1,get_map_height(map) do
  459.       local w = map_row_length(y, map)
  460.       if w > mapw then
  461.      mapw = w
  462.       end
  463.    end
  464.  
  465.    return mapw
  466. end
  467.  
  468. -- and size combined
  469. function get_map_size(map)
  470.    return get_map_width(map), get_map_height(map)
  471. end
  472.  
  473. -- common map
  474. -- if a key has no meaning declared in given 'cellfuncs', we'll look here
  475. -- whether there is a 'default' meaning
  476. -- look at the bottom of ant.lua to see the map
  477. DEFAULT_KEY_MEANING = {}
  478. function map_cell_meaning(key, func)
  479.    DEFAULT_KEY_MEANING[key] = func
  480. end
  481.  
  482. -- use cells from default library in cellfuncs table
  483. -- this function accepts a table of cellfuncs and arbitrary number of string keys as arguments
  484. -- it loads the default keys to given cellfuncs table
  485. function use_cells(funcs, ...)
  486.    local arg={...}
  487.    for a = 1,getn(arg) do
  488.       funcs[arg[a]] = DEFAULT_KEY_MEANING[arg[a]]
  489.    end
  490. end
  491.  
  492. -- function picks a function from table of default cell keys
  493. -- and results it
  494. function default_cell(key)
  495.    return DEFAULT_KEY_MEANING[key]
  496. end
  497.  
  498. -- this function accepts a cell key and cellfuncs table
  499. -- it looks into that table and if there is no func with given key, it returns default
  500. -- value instead and inserts the value to given cellfuncs table
  501. function get_cell_func(key, cellfuncs)
  502.    if (cellfuncs[key]) then
  503.       return cellfuncs[key]
  504.    elseif (DEFAULT_KEY_MEANING[key]) then
  505.       debug("get_cell_func: using DEFAULT_KEY_MEANING of '"..key.."'")
  506.       cellfuncs[key] = DEFAULT_KEY_MEANING[key]
  507.       return DEFAULT_KEY_MEANING[key]
  508.    else
  509.       -- for multichar maps, try by the first char
  510.       if (strlen(key)>1) then
  511.      local ret = get_cell_func(strsub(key, 1, 1), cellfuncs)
  512.      if (ret) then
  513.         debug("get_cell_func: as a meaning of the key '"..key.."'")
  514.         cellfuncs[key] = ret;
  515.         return ret
  516.      end
  517.       end
  518.  
  519.       warning("get_cell_func: no function declared for map key '"..key.."'")
  520.       return nil
  521.    end
  522.  
  523.    --notreached
  524.    return nil
  525. end
  526.  
  527.  
  528.  
  529.  
  530. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  531. -- MAP RENDERING FUNCTIONS -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  532. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  533.  
  534. -- render a map square by key
  535. -- rx,ry are x,y coordinates of given cell on map
  536. -- key is a cell descriptor
  537. -- func is a table of cellfuncs
  538. function render_key(rx, ry, key, cellfuncs)
  539.    local cellfuncs = cellfuncs or get_cellfuncs(cellfuncs);
  540.  
  541.    -- call default parents
  542.    if (DEFAULT_CELL_PARENT) then
  543.       for _,val in pairs(DEFAULT_CELL_PARENT) do
  544.      local dpfunc = 0
  545.      if (type(val) == "string") then
  546.         dpfunc = get_cell_func(val, cellfuncs)
  547.      else
  548.         dpfunc = val
  549.      end
  550.  
  551.      if (type(dpfunc) == "function") then
  552.         dpfunc(rx, ry)
  553.      else
  554.         warning("render_key: unknown default parent type for the key: '"..val.."'")
  555.      end
  556.       end
  557.    end
  558.  
  559.    -- call common cell function
  560.    local func = get_cell_func(key, cellfuncs)
  561.    local ftype = type(func)
  562.    if (ftype == "function") then
  563.       func(rx, ry)
  564.    elseif (ftype == "nil") then
  565.       warning("render_key: function doesn't exist for map element '"..key.."'.")
  566.    else
  567.       warning("render_key: cell element '"..key.."' is not a function, it's "..ftype..".")
  568.    end
  569. end
  570.  
  571. -- this function returns a cell key by its x,y coordinates
  572. function get_cell_by_xy(mx, my, map)
  573.    return strsub(map[my], (mx - 1) * CELL_KEY_WIDTH + 1, mx * CELL_KEY_WIDTH)
  574. end
  575.  
  576. -- function renders a given cell of map
  577. -- rx0, ry0 are coordinates of left top square of map
  578. -- mx, my are coordinates of map square to be rendered
  579. function render_map_cell(rx0, ry0, mx, my, map, cellfuncs)
  580.    if (not(map)) then
  581.       warning("render_map_cell: no map given!")
  582.       return
  583.    end
  584.    local cellfuncs = cellfuncs or get_cellfuncs(cellfuncs)
  585.  
  586.    local rx = mx + rx0 - 1
  587.    local ry = my + ry0 - 1
  588.    local key = get_cell_by_xy(mx, my, map)
  589.    render_key(rx, ry, key, cellfuncs)
  590. end
  591.  
  592. -- this draws the map to the position [rx0,ry0]
  593. -- map is array of strings. Each string is one line of result map, each char is one map square.
  594. -- you may omit cellfuncs, default global 'cells' is used instead
  595. function draw_map_portion(rx0, ry0, mxy0, mxy1, map, cellfuncs)
  596.    if (not(map)) then
  597.       warning("draw_map: no map given!")
  598.       return
  599.    end
  600.    local cellfuncs = cellfuncs or get_cellfuncs(cellfuncs);
  601.  
  602.    for my = mxy0[2],mxy1[2] do
  603.       for mx = mxy0[1],mxy1[1] do
  604.      render_map_cell(rx0, ry0, mx, my, map, cellfuncs);
  605.       end
  606.    end
  607. end
  608.  
  609. -- this will draw whole map
  610. -- rx0, ry0 are coordinates of left top map corner
  611. function draw_map(rx0, ry0, map, cellfuncs)
  612.    local mapw, maph = get_map_size(map)
  613.    draw_map_portion(rx0, ry0, {1,1}, {mapw, maph}, map, cellfuncs)
  614. end
  615.  
  616. -- this just prepares the world, but no map is created
  617. function prepare_world_by_map(map)
  618.    local mapw, maph = get_map_size(map)
  619.    local flavor = oxyd_default_flavor
  620.  
  621.    debug("creating world ["..mapw.."x"..maph.."]")
  622.    create_world(mapw, maph)
  623.    oxyd_default_flavor = flavor or oxyd_default_flavor or "b"
  624. end
  625.  
  626. -- this prepares enigma world and draws given map
  627. -- you may omit cellfuncs, default global 'cells' is used instead
  628. function create_world_by_map(map, cellfuncs)
  629.    prepare_world_by_map(map)
  630.    draw_map(0, 0, map, cellfuncs)
  631. end
  632.  
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  640. -- FUNCTIOAL MAP DRAWING - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  641. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  642. -- functions in this section are much like those defined in init.lua. Major difference
  643. -- is that these functions accept a function as an argument. So, it's possible to call
  644. -- given function with several coordinates at once. Just one single prerequisity -
  645. -- the function must require at most two arguments, and they have to be coordinates
  646. --   func(x,y, non_required_arguments)
  647.  
  648. -- fill each square of map with given function
  649. function fill_world_func(fillfunc, x0, y0, w, h)
  650.    if (type(fillfunc) ~= "table") then
  651.       fillfunc = {fillfunc}
  652.    end
  653.    local x0,y0,w,h = transform_coords(x0, y0, w, h)
  654.  
  655.    for _,func in pairs(fillfunc) do
  656.       for x=x0, x0+w-1 do
  657.      for y=y0, y0+h-1 do
  658.         func(x, y)
  659.      end
  660.       end
  661.    end
  662. end
  663.  
  664. -- to draw border of map by given function
  665. function draw_border_func(fillfunc, x0, y0, w, h)
  666.    if (type(fillfunc) ~= "table") then
  667.       fillfunc = {fillfunc}
  668.    end
  669.    local x0,y0,w,h = transform_coords(x0, y0, w, h)
  670.  
  671.    for _,func in pairs(fillfunc) do
  672.       for x=x0,x0+w-1 do
  673.      func(x, y0)
  674.      func(x, y0+h-1)
  675.       end
  676.  
  677.       for y=y0,y0+h-1 do
  678.      func(x0, y)
  679.      func(x0+w-1, y)
  680.       end
  681.    end
  682. end
  683.  
  684. -- draws into corners of given boundary
  685. function draw_func_corners(fillfunc, x0, y0, w, h)
  686.    if (type(fillfunc) ~= "table") then
  687.       fillfunc = {fillfunc}
  688.    end
  689.    local x0,y0,w,h = transform_coords(x0, y0, w, h)
  690.  
  691.    for _,func in pairs(fillfunc) do
  692.       func(x0,y0)
  693.       func(x0,y0+h-1)
  694.       func(x0+w-1,y0)
  695.       func(x0+w-1,y0+h-1)
  696.    end
  697. end
  698.  
  699. -- like set_stones, but calling a function
  700. -- like: set_funcs(oxyd, {{1,2},{3,4},...})
  701. function set_funcs(fillfunc, poslist)
  702.    if (type(fillfunc) ~= "table") then
  703.       fillfunc = {fillfunc}
  704.    end
  705.  
  706.    for _,func in pairs(fillfunc) do
  707.       for i = 1,getn(poslist) do
  708.           local x,y,w,h = transform_coords(poslist[i][1], poslist[i][2])
  709.           func(x, y)
  710.       end
  711.    end
  712. end
  713.  
  714.  
  715. -- draw functions into a row -- like draw_stones, draw_floor and others, but calls a func
  716. -- generator of coordinates
  717. function get_draw_coords(xylist, dxdylist, steps)
  718.    if (type(xylist[1]) ~= "table") then
  719.       xylist = {xylist}
  720.    end
  721.    if (type(dxdylist[1]) ~= "table") then
  722.       dxdylist = {dxdylist}
  723.    end
  724.    local ret = {}
  725.  
  726.    -- convert
  727.    for i = 1,getn(xylist) do
  728.       local x0,y0 = transform_coords(xylist[i][1], xylist[i][2])
  729.  
  730.       tinsert(ret, {x0,y0})
  731.  
  732.       for j = 1,getn(dxdylist) do
  733.      local x,y   = x0,y0
  734.      local dx,dy = dxdylist[j][1], dxdylist[j][2]
  735.  
  736.      for i = 2,steps do
  737.         x = x+dx
  738.         y = y+dy
  739.         tinsert(ret, {x,y})
  740.      end
  741.       end
  742.    end
  743.    --
  744.    return ret
  745. end
  746.  
  747. -- drawing function
  748. function draw_func(fillfunc, ...)
  749.    local arg={...}
  750.    if (type(fillfunc) ~= "table") then
  751.       fillfunc = {fillfunc}
  752.    end
  753.  
  754.    local xylist = get_draw_coords(unpack(arg))
  755.  
  756.    for _,func in pairs(fillfunc) do
  757.       for i = 1,getn(xylist) do
  758.      local x,y = transform_coords(xylist[i][1], xylist[i][2])
  759.      func(x,y)
  760.       end
  761.    end
  762. end
  763.  
  764.  
  765. -- draw a function into a regular n-gon. Particularly usable for
  766. -- setting up arrangements of actors, as they accept real values,
  767. -- but if proper roundfunc is given, also stones etc. may be
  768. -- placed with this function.
  769.  
  770. -- generator of coordinates
  771. function get_ngon_coords(xylist, radiuslist, count, alpha0, roundfunc)
  772.    if (type(xylist[1]) ~= "table") then
  773.       xylist = {xylist}
  774.    end
  775.    if (type(radiuslist) ~= "table") then
  776.       radiuslist = {radiuslist}
  777.    end
  778.  
  779.    local astep = 360 / count
  780.    local roundfunc = roundfunc or (function(x) return x end)
  781.  
  782.    local ret = {}
  783.  
  784.    for i = 1,getn(xylist) do
  785.       local x0, y0 = transform_coords(xylist[i][1], xylist[i][2])
  786.  
  787.       for j = 1,getn(radiuslist) do
  788.      local radius = radiuslist[j]
  789.      local alpha  = alpha0 or 0
  790.  
  791.      for _ = 1,count do
  792.         local x00 = roundfunc(x0 + radius * sin(alpha))
  793.         local y00 = roundfunc(y0 + radius * cos(alpha))
  794.         tinsert(ret, {x00,y00})
  795.         alpha = alpha + astep
  796.      end
  797.       end
  798.    end
  799.  
  800.    return ret
  801. end
  802.  
  803. -- drawing function
  804. function ngon_funcs(fillfunc, ...)
  805.    local arg={...}
  806.    if (type(fillfunc) == "function") then
  807.       fillfunc = {fillfunc}
  808.    end
  809.  
  810.    local xylist = get_ngon_coords(unpack(arg))
  811.  
  812.    for _,func in pairs(fillfunc) do
  813.       for i = 1,getn(xylist) do
  814.      local x,y = transform_coords(xylist[i][1], xylist[i][2])
  815.      func(x,y)
  816.       end
  817.    end
  818. end
  819.  
  820.  
  821.  
  822.  
  823.  
  824.  
  825. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  826. -- SPECIAL FLOOR TYPES  -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  827. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  828. -- see ant.lua documentation for extensive howto
  829. -- (this is yet to be done)
  830.  
  831. -- draws checker floor
  832. -- sidex: horizontal size of checker square
  833. -- sidey: vertical size of checker square
  834. -- count: number of checker textures
  835. -- items: table of checker textures {1,2,3,...}
  836. -- x,y:   coordinates of checker field
  837. function mcheckerfloor(x, y, sidex, sidey, offsetx, offsety, count, items)
  838.    local x0 = floor( (x - offsetx + sidex) / sidex)
  839.    local y0 = floor( (y - offsety + sidey) / sidey)
  840.    local remainder = mod(x0+y0, count)
  841.    items[remainder + 1](x,y)
  842. end
  843.  
  844. -- the checkerfloor parent
  845. -- items: checkerfloor textures. Functions generated by cell({structure})
  846. -- eg:
  847. --   cells["."]=cell{floor={face="fl-metal"}}
  848. --   cells[","]=cell{floor={face="fl-normal"}}
  849. --   cells[" "]=cell{parent={{checkerfloor,{cells[","], cells["."]}}}}
  850. -- optionally, at the end of table there may be additional checkerboard generating variables:
  851. --   side - set size of checkerboard square
  852. --   sidex - only set horizontal size (defaults to 1)
  853. --   sidey - only set vertical size (defaults to 1)
  854. --     cells[" "]=cell{parent={{checkerfloor,{cells[","], cells["."]; side=2}}}}
  855. function checkerfloor(x, y, items)
  856.    local count = getn(items)
  857.    local remainder = mod(x+y, count)
  858.    local sidex, sidey = 1, 1
  859.    local offsetx, offsety = 0, 0
  860.  
  861.    if (items.side ~= nil) then
  862.       sidex = items.side
  863.       sidey = sidex
  864.    end
  865.  
  866.    if (items.sidex ~= nil) then
  867.       sidex = items.sidex
  868.    end
  869.  
  870.    if (items.sidey ~= nil) then
  871.       sidey = items.sidey
  872.    end
  873.  
  874.    if (items.offset ~= nil) then
  875.       offsetx = items.offset
  876.       offsety = offsetx
  877.    end
  878.  
  879.    if (items.offsetx ~= nil) then
  880.       offsetx = items.offsetx
  881.    end
  882.  
  883.    if (items.offsety ~= nil) then
  884.       offsety = items.offsety
  885.    end
  886.  
  887.    mcheckerfloor(x, y, sidex, sidey, offsetx, offsety, getn(items), items)
  888. end
  889.  
  890. -- the random floor parent
  891. --  every item may be:
  892. --   texture -- parent function, for example cell[] function
  893. --   occurence -- occurence factor for previous texture. Defaults to 1.
  894. function randomfloor(x, y, ...)
  895.    local count = 0
  896.    local total = 0 --total occurences
  897.  
  898.    local items = {}
  899.    if (getn(arg) == 1) then
  900.       if (type(arg[1]) == "table") then
  901.      items = arg[1]    -- table is passed
  902.       else
  903.      items = {arg[1]}  -- single function passed (hope it's a function)... who could do it?
  904.       end
  905.    else
  906.       items = arg          -- a list of functions and their rarities is not passed in table, but as arguments
  907.    end
  908.  
  909.    local itemlist = {}
  910.  
  911.    for i = 1,getn(items) do
  912.       local item  = items[i]
  913.       local titem = type(item)
  914.       if (titem == "function") then
  915.      count = count + 1
  916.      itemlist[count] = {}
  917.      itemlist[count].func = item
  918.      itemlist[count].occf = 1
  919.      total = total + 1
  920.       elseif (titem == "number") then
  921.      itemlist[count].occf = item
  922.      total = total + item-1
  923.       end
  924.    end
  925.  
  926.    local rand = total*random()
  927.    local ctr  = 0
  928.  
  929.    for i=1,count do
  930.       local move = itemlist[i].occf
  931.       if ((rand>=ctr) and (rand<ctr+move)) then
  932.      itemlist[i].func(x,y)
  933.       end
  934.       ctr = ctr + move
  935.    end
  936. end
  937.  
  938.  
  939.  
  940.  
  941.  
  942. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  943. -- OBJECT GROUPS [MULTIPLES]  -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  944. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  945. -- see ant.lua documentation for extensive howto
  946.  
  947. -- add a stone to a group
  948. -- face: this is stone face
  949. -- group: object group table
  950. -- attribs: object attributes
  951. function add_multistone(x, y, face, group, attribs)
  952.    local attribs = attribs or {}
  953.    attribs["name"] = attribs.name or (face..(getn(group)+1))
  954.    tinsert(group, set_stone(face, x, y, attribs))
  955. end
  956.  
  957. -- add a floor to a group
  958. -- face: this is floor face
  959. -- group: object group table
  960. -- attribs: object attributes
  961. function add_multifloor(x, y, face, group, attribs)
  962.    local attribs = attribs or {}
  963.    attribs["name"] = attribs.name or (face..(getn(group)+1))
  964.    tinsert(group, set_floor(face, x, y, attribs))
  965. end
  966.  
  967. -- add an item to a group
  968. -- face: this is an item kind
  969. -- group: object group table
  970. -- attribs: object attributes
  971. function add_multiitem(x, y, face, group, attribs)
  972.    local attribs = attribs or {}
  973.    attribs["name"] = attribs.name or (face..(getn(group)+1))
  974.    tinsert(group, set_item(face, x, y, attribs))
  975. end
  976.  
  977. -- add an actor to a group
  978. -- face: this is floor face
  979. -- group: object group table
  980. -- attribs: object attributes
  981. function add_multiactor(x, y, face, group, attribs, actor_mode)
  982.    local attribs = attribs or {}
  983.    local actor_mode = actor_mode or 3
  984.    attribs["name"] = attribs.name or (face..(getn(group)+1))
  985.    tinsert(group, set_actor(face, get_actor_x(x, actor_mode), get_actor_y(y, actor_mode), attribs))
  986. end
  987.  
  988. -- for generic multiples, this only stores cell coordinates and tag information
  989. -- this is usable for example to construct puzzles and trains, see below
  990. function add_multicell(x, y, group, tag)
  991.    local key = getkey(x,y)
  992.    group[key] = {}
  993.    group[key].x = x
  994.    group[key].y = y
  995.    group[key].tag = tag
  996. end
  997.  
  998. -- another generic multiple
  999. -- this stores the result of given function(x,y) to table
  1000. function add_multiobject(x, y, group, func)
  1001.    tinsert(group, func(x, y))
  1002. end
  1003.  
  1004.  
  1005.  
  1006. -- couple of functions to mark all cells in given area with
  1007. -- given tagnumber. Used for rendering gradients. Area must
  1008. -- be closed, otherwise stack overflow occurs.
  1009. -- usage:
  1010. --   slopes={}
  1011. --   pivots={}
  1012. --   cells["*"]=cell{{{add_multicell, slopes, 1}}}
  1013. --   cells["&"]=cell{{{add_multicell, pivots, slopes}}}
  1014. -- at the end of levelfile:
  1015. --   spread_tag(pivots)
  1016. --   render_slopes(slopes)
  1017. -- BUGS:
  1018. --  stack overflows, if:
  1019. --  + the shape is not closed
  1020. --  + area is too large (for example very long corridor...)
  1021. function spread_tag_depth(x0, y0, tab, tag)
  1022.    if tab[getkey(x0, y0)] then
  1023.       return
  1024.    end
  1025.  
  1026.    add_multicell(x0, y0, tab, tag)
  1027.    spread_tag_depth(x0,   y0-1, tab, tag)
  1028.    spread_tag_depth(x0+1, y0  , tab, tag)
  1029.    spread_tag_depth(x0,   y0+1, tab, tag)
  1030.    spread_tag_depth(x0-1, y0  , tab, tag)
  1031. end
  1032.  
  1033. function spread_tag(tab, tag)
  1034.    local tag = tag or 2
  1035.    for _,val in pairs(tab) do
  1036.       local x0 = val.x
  1037.       local y0 = val.y
  1038.       local tab0 = val.tag
  1039.       spread_tag_depth(x0, y0, tab0, tag)
  1040.    end
  1041. end
  1042.  
  1043. -- add the rubber band between all objects in group 1 and all objects in group 2
  1044. -- that is, each object from gr1 will be connected with each object from gr2
  1045. function add_rubber_bands(gr1, gr2, strength, length)
  1046.    for i = 1,getn(gr1) do
  1047.       for j = 1,getn(gr2) do
  1048.      AddRubberBand(gr1[i], gr2[j], strength, length)
  1049.       end
  1050.    end
  1051. end
  1052.  
  1053. -- add pairs: 1st object from gr1 will be connected with 1st from gr2 and so on
  1054. -- requires same sized groups, of course...
  1055. function add_rubber_band_pairs(gr1, gr2, strength, length)
  1056.    for i = 1,getn(gr1) do
  1057.       AddRubberBand(gr1[i], gr2[i], strength, length)
  1058.    end
  1059. end
  1060.  
  1061. -- to rubber-band given objects [1,2,3,...,n] like that:
  1062. --  1=2=3=...=n=1
  1063. function rubber_band_circle(gr1, strength, length)
  1064.    local remember = nil
  1065.    local first = nil
  1066.    for a = 1,getn(gr1) do
  1067.       local obj1 = gr1[a]
  1068.       if (remember) then
  1069.      AddRubberBand(obj1, remember, strength, length)
  1070.       else
  1071.      first = obj1
  1072.       end
  1073.  
  1074.       remember = obj1
  1075.    end
  1076.  
  1077.    if (first) then
  1078.       AddRubberBand(first, remember, strength, length)
  1079.    end
  1080. end
  1081.  
  1082. -- send message to each object in group
  1083. function send_group_message(group, message, third)
  1084.    for i = 1,getn(group) do
  1085.        SendMessage(group[i], message, third)
  1086.    end
  1087. end
  1088.  
  1089. -- send a message to named object
  1090. function send_message_named(objname, message, third)
  1091.     SendMessage(objname, message, third)
  1092. end
  1093.  
  1094. -- set attribute to each of the objects in group
  1095. function set_group_attribs(group, attribs)
  1096.    for i = 1,getn(group) do
  1097.       set_attribs(group[i], attribs)
  1098.    end
  1099. end
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1106. -- RAILWAY GENERATOR -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1107. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1108. -- see ant.lua documentation for extensive howto
  1109.  
  1110. function new_rail(engines, path)
  1111.    local func0 = function()
  1112.             for _,engine in pairs(engines) do
  1113.                local ekey = getkey(engine.x, engine.y)
  1114.  
  1115.                for _, dir in pairs({engine.dir,{1,0},{0,1},{-1,0},{0,-1}}) do
  1116.               local x0 = engine.x + dir[1]
  1117.               local y0 = engine.y + dir[2]
  1118.               local key = getkey(x0, y0)
  1119.  
  1120.               if ((path[key]) and (path[key].tag ~= path[ekey].tag)) then
  1121.                  path[key].tag = path[ekey].tag
  1122.                  engine.x, engine.y = x0, y0
  1123.                  engine.dir = dir -- remember direction
  1124.                  engine.tag(x0, y0)
  1125.                  break
  1126.               end
  1127.                end--for directions
  1128.  
  1129.             end--for engines
  1130.          end--function
  1131.    return func0
  1132. end
  1133.  
  1134.  
  1135.  
  1136.  
  1137. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1138. -- PUZZLE GENERATOR  -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1139. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1140. -- see ant.lua documentation for extensive howto
  1141. function render_puzzles(tab, kind, generatorfunc)
  1142.    for _,val in pairs(tab) do
  1143.       local kind = kind or puzzle
  1144.       local x,y = val.x, val.y
  1145.  
  1146.       local up   = 0;
  1147.       local down = 0;
  1148.       local left = 0;
  1149.       local right= 0;
  1150.       if (tab[getkey(x, y-1)] ~= nil) then up = 1 end
  1151.       if (tab[getkey(x, y+1)] ~= nil) then down = 1 end
  1152.       if (tab[getkey(x-1, y)] ~= nil) then left = 1 end
  1153.       if (tab[getkey(x+1, y)] ~= nil) then right = 1 end
  1154.  
  1155.       if (generatorfunc) then
  1156.      generatorfunc(val);
  1157.       end
  1158.  
  1159.       if ((val.tag ~= 2) and (kind)) then
  1160.      kind(x, y, getglobal("PUZ_"..up..right..down..left))
  1161.       end
  1162.    end
  1163. end
  1164.  
  1165.  
  1166.  
  1167.  
  1168. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1169. -- BLACK HOLES GENERATOR - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1170. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1171. -- see ant.lua documentation for extensive howto
  1172.  
  1173. function render_wormholes(holes, targets, whole_attribs, actor_mode)
  1174.    local whole_attribs = whole_attribs or {}
  1175.    local actor_mode = actor_mode or 3
  1176.  
  1177.    for _,hval in pairs(holes) do
  1178.       local target = 0
  1179.       for _,tval in pairs(targets) do
  1180.      if (tval.tag == hval.tag) then
  1181.         target = tval;
  1182.         break
  1183.      end
  1184.       end
  1185.  
  1186.       if (target ~= 0) then
  1187.      local targetx = get_actor_x(target.x, actor_mode)
  1188.      local targety = get_actor_y(target.y, actor_mode)
  1189.      wormhole(hval.x, hval.y, targetx, targety, whole_attribs)
  1190.       end
  1191.    end
  1192. end
  1193.  
  1194. function worm_hole_pair(cellfuncs, whole_cell, tgt_cell, whole_parent, tgt_parent, whole_grp, tgt_grp, tagnumber)
  1195.    cellfuncs[whole_cell] = cell{{whole_parent, {add_multicell, whole_grp, tagnumber}}}
  1196.    cellfuncs[tgt_cell]   = cell{{tgt_parent,   {add_multicell, tgt_grp,   tagnumber}}}
  1197. end
  1198.  
  1199.  
  1200.  
  1201.  
  1202.  
  1203.  
  1204. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1205. -- SLOPE GENERATOR - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1206. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1207. -- see ant.lua documentation for extensive howto
  1208.  
  1209. __slopemap = {}
  1210. __slopemap["x0x11x1x"]=SLOPE_N
  1211. __slopemap["x1x01x1x"]=SLOPE_W
  1212. __slopemap["x1x10x1x"]=SLOPE_E
  1213. __slopemap["x1x11x0x"]=SLOPE_S
  1214. __slopemap["x1x00x0x"]=SLOPE_S
  1215. __slopemap["x0x10x0x"]=SLOPE_E
  1216. __slopemap["x0x01x0x"]=SLOPE_W
  1217. __slopemap["x0x00x1x"]=SLOPE_N
  1218.  
  1219. -- soft conditions
  1220. __slopemap["x11x1xxx"]=SLOPE_SMALL_SW
  1221. __slopemap["x1x1111x"]=SLOPE_LARGE_NE
  1222. __slopemap["xxx1x11x"]=SLOPE_SMALL_NE
  1223. __slopemap["x1111x1x"]=SLOPE_LARGE_SW
  1224. __slopemap["xxxx1x11"]=SLOPE_SMALL_NW
  1225. __slopemap["11x11x1x"]=SLOPE_LARGE_SE
  1226. __slopemap["11x1xxxx"]=SLOPE_SMALL_SE
  1227. __slopemap["x1x11x11"]=SLOPE_LARGE_NW
  1228.  
  1229. -- hard conditions -- these don't match always, but help to break ambiguous matches
  1230. __slopemap["x1101x0x"]=SLOPE_SMALL_SW
  1231. __slopemap["x101111x"]=SLOPE_LARGE_NE
  1232. __slopemap["x0x1011x"]=SLOPE_SMALL_NE
  1233. __slopemap["x111101x"]=SLOPE_LARGE_SW
  1234. __slopemap["x0x01x11"]=SLOPE_SMALL_NW
  1235. __slopemap["11x11x10"]=SLOPE_LARGE_SE
  1236. __slopemap["11x10x0x"]=SLOPE_SMALL_SE
  1237. __slopemap["01x11x11"]=SLOPE_LARGE_NW
  1238.  
  1239. --inverses
  1240. __grad_inverse={}
  1241. __grad_inverse[SLOPE_S]=SLOPE_N
  1242. __grad_inverse[SLOPE_N]=SLOPE_S
  1243. __grad_inverse[SLOPE_E]=SLOPE_W
  1244. __grad_inverse[SLOPE_W]=SLOPE_E
  1245. __grad_inverse[SLOPE_LARGE_SE]=SLOPE_SMALL_NW
  1246. __grad_inverse[SLOPE_LARGE_SW]=SLOPE_SMALL_NE
  1247. __grad_inverse[SLOPE_LARGE_NE]=SLOPE_SMALL_SW
  1248. __grad_inverse[SLOPE_LARGE_NW]=SLOPE_SMALL_SE
  1249. __grad_inverse[SLOPE_SMALL_SE]=SLOPE_LARGE_NW
  1250. __grad_inverse[SLOPE_SMALL_NE]=SLOPE_LARGE_SW
  1251. __grad_inverse[SLOPE_SMALL_SW]=SLOPE_LARGE_NE
  1252. __grad_inverse[SLOPE_SMALL_NW]=SLOPE_LARGE_SE
  1253.  
  1254. -- return correct gradient type based on neighbors
  1255. function map_slope(x, y, node)
  1256.    local map = __slopemap;
  1257.    local re  = ""..node[1]..node[2]..node[3]..node[4]..node[5]..node[6]..node[7]..node[8]
  1258.    --
  1259.    local longest = 0;
  1260.    local longkey = 0;
  1261.    local longval = 0;
  1262.    local warns = {}
  1263.    --
  1264.    for key,val in pairs(map) do
  1265.       local okay = 1
  1266.       local count = 0
  1267.       -- okay turns to 0, if any char, that is not 'x', doesn't match
  1268.       for i = 1,strlen(key) do
  1269.      local char1 = strsub(key, i, i)
  1270.      local char2 = strsub(re, i, i)
  1271.      --
  1272.      if ((char1 ~= 'x') and (char2 ~= 'x') and (char1 ~= char2)) then
  1273.         okay = 0
  1274.         break
  1275.      else
  1276.         if ((char1 ~= 'x') and (char2 ~= 'x')) then
  1277.            count = count +1
  1278.         end
  1279.      end
  1280.       end
  1281.       --
  1282.       if (okay == 1) then
  1283.      if (count > longest) then
  1284.         longest = count;
  1285.         longkey = key;
  1286.         longval = val;
  1287.         warns = {}
  1288.      elseif (count == longest) then
  1289.         tinsert(warns, "map_slope: ambiguous match: '"..longkey.."' vs. '"..key.."' for re '"..re.."'")
  1290.      end
  1291.       end
  1292.    end
  1293.    --
  1294.    for i = 1,getn(warns) do
  1295.       debug(warns[i])
  1296.    end
  1297.  
  1298.    if (longest == 0) then
  1299.       warning("map_slope: no match for mask '"..re.."' at ["..x..","..y.."].")
  1300.    end
  1301.  
  1302.    return longval;
  1303. end
  1304.  
  1305. function render_slopes(tab, invert)
  1306.    for _,val in pairs(tab) do
  1307.       local x,y = val.x, val.y
  1308.  
  1309.       local node = {}
  1310.       if (tab[getkey(x-1,y-1)] ~= nil) then tinsert(node, 1) else  tinsert(node, 0) end
  1311.       if (tab[getkey(x  ,y-1)] ~= nil) then tinsert(node, 1) else  tinsert(node, 0) end
  1312.       if (tab[getkey(x+1,y-1)] ~= nil) then tinsert(node, 1) else  tinsert(node, 0) end
  1313.       if (tab[getkey(x-1,y  )] ~= nil) then tinsert(node, 1) else  tinsert(node, 0) end
  1314.       if (tab[getkey(x+1,y  )] ~= nil) then tinsert(node, 1) else  tinsert(node, 0) end
  1315.       if (tab[getkey(x-1,y+1)] ~= nil) then tinsert(node, 1) else  tinsert(node, 0) end
  1316.       if (tab[getkey(x  ,y+1)] ~= nil) then tinsert(node, 1) else  tinsert(node, 0) end
  1317.       if (tab[getkey(x+1,y+1)] ~= nil) then tinsert(node, 1) else  tinsert(node, 0) end
  1318.  
  1319.       if (val.tag ~= 2) then
  1320.      if( (invert ~= nil) ~= (val.tag == -1)) then   -- this is !(invert xor (val.tag == -1))
  1321.         gradient(x, y, __grad_inverse[map_slope(x, y, node)])
  1322.      else
  1323.         gradient(x, y, map_slope(x, y, node))
  1324.      end
  1325.       end
  1326.    end
  1327. end
  1328.  
  1329.  
  1330.  
  1331.  
  1332.  
  1333. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1334. -- BOOLEAN TABLES -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1335. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1336. -- see ant.lua documentation for extensive howto
  1337.  
  1338. -- bool_and tests table for and: all elements have to be '1' to succeed
  1339. function bool_and(tab)
  1340.    return tab.count == tab.value
  1341. end
  1342.  
  1343.  
  1344. -- bool_or tests table for or: at least one element has to be '1' to succeed
  1345. function bool_or(tab)
  1346.    return tab.value > 0
  1347. end
  1348.  
  1349.  
  1350. -- bool_xor tests table for xor: odd number of elements has to be '1' to succeed
  1351. function bool_xor(tab)
  1352.    return mod(tab.value, 2) ~= 0
  1353. end
  1354.  
  1355.  
  1356. -- bool_table initialization
  1357. -- count_tot  is number of cells in table (that is the number of triggers)
  1358. -- count_init is number of cells to init (number of negset triggers)
  1359. -- test_func  is a function to get called each set and negset - a test function
  1360. -- true_func  is a function to be called if test passed
  1361. -- false_func is a function to be called if test failed
  1362. function bool_table(count_tot, count_init, test_func, true_func, false_func)
  1363.    local tab   = {};
  1364.  
  1365.    tab.test    = test_func  or function() return nil end;
  1366.    tab.ontrue    = true_func  or function() return nil end;
  1367.    tab.onfalse   = false_func or function() return nil end;
  1368.    tab.count   = count_tot  or 1;
  1369.    tab.value   = count_init or 0;
  1370.    tab.remember= -1;
  1371.  
  1372.    return tab;
  1373. end
  1374.  
  1375.  
  1376. -- bool val set
  1377. -- this gets called upon every trigger/switcher state change
  1378. -- it changes value of one element of given table
  1379. function bool_set(value, omit, tab)
  1380.    if (value == 0) then
  1381.       tab.value = tab.value -1;
  1382.    else
  1383.       tab.value = tab.value +1;
  1384.    end
  1385.  
  1386.    local res = tab.test(tab);
  1387.    if (tab.remember ~= res) then
  1388.       tab.remember = res;
  1389.  
  1390.       if (res) then
  1391.      debug("bool_set: true")
  1392.      tab.ontrue()
  1393.       else
  1394.      debug("bool_set: false")
  1395.      tab.onfalse()
  1396.       end
  1397.    end
  1398. end
  1399.  
  1400.  
  1401. -- bool val negative set
  1402. -- this is similar to bool_val, except that it sets '1' if triggered off and vice versa
  1403. function bool_negset(value, omit, tab)
  1404.    if (value == 0) then
  1405.       bool_set(1, nil, tab)
  1406.    else
  1407.       bool_set(0, nil, tab)
  1408.    end
  1409. end
  1410.  
  1411.  
  1412.  
  1413.  
  1414.  
  1415. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1416. -- WRAPPED init.lua FUNCTIONS -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1417. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1418.  
  1419. -- This somehow generalizes oxyd() from init.lua. You can pick your
  1420. -- own color and flavor of oxyd stone. If you omit 'acolor', or pass a
  1421. -- '' (empty string) instead, default value (or last time used value)
  1422. -- is used instead. Omitting aflavor or passing empty string as
  1423. -- aflavor results in using default or last used flavor.
  1424.  
  1425. function oxyd_custom(x,y,aflavor,acolor)
  1426.    if ((not aflavor) or (aflavor=='')) then
  1427.       aflavor = oxyd_default_flavor
  1428.    end
  1429.  
  1430.    if ((not acolor) or (acolor=='')) then
  1431.       acolor = oxyd_current_color
  1432.    end
  1433.  
  1434.    oxyd_default_flavor = aflavor;
  1435.    oxyd_current_color = acolor;
  1436.  
  1437.    oxyd(x,y)
  1438. end
  1439.  
  1440.  
  1441. -- these functions override common init.lua functions, giving them the power
  1442. -- of ant.lua syntax -- that is, calling with list of coordinates,
  1443. -- using negative coordinates for positions relative to lower-right corner
  1444. -- and maybe also some others that I do not recall now :)
  1445. -- Note, that basic syntax remain intact, so at first glance no changes are visible!
  1446. -- Wrapped functions are a lot slower, empirically nearly 3.5 times. Not a great deal,
  1447. -- as LUA is really fast, and the same for enigma. Tested on rather slow 166MHz AMD,
  1448. -- 80 megs of memory, Win95 - you won't notice extra time spent by loading a level.
  1449.  
  1450. -- stones
  1451. oxyd =     cell{oxyd}
  1452. fakeoxyd = cell{fakeoxyd}
  1453. oneway =   cell{oneway}
  1454. laser =    cell{laser}
  1455. mirrorp =  cell{mirrorp}
  1456. mirror3 =  cell{mirror3}
  1457. puzzle =   cell{puzzle}
  1458. switch =   cell{switch}
  1459.  
  1460. -- floors
  1461. abyss =    cell{abyss}
  1462. hollow =   cell{hollow}
  1463. hill=      cell{item="it-hill"}
  1464.  
  1465. -- items
  1466. Document = cell{Document}
  1467. hammer =   cell{hammer}
  1468. dynamite = cell{dynamite}
  1469. bomb =     cell{bomb}
  1470. shogundot= cell{shogundot}
  1471. keya =     cell{keya}
  1472. keyb =     cell{keyb}
  1473. keyc =     cell{keyc}
  1474. shogundot1=cell{{{shogundot, 1}}}
  1475. shogundot2=cell{{{shogundot, 2}}}
  1476. shogundot3=cell{{{shogundot, 3}}}
  1477. Wormhole = cell{Wormhole}
  1478. doorh =    cell{doorh}
  1479. doorv =    cell{doorv}
  1480. gradient = cell{gradient}
  1481.  
  1482. -- lower case equivalents
  1483. document = Document
  1484. wormhole = Wormhole
  1485.  
  1486. -- 'andvanced' oxyd functions
  1487. oxyd_col = cell{{{oxyd_custom, ''}}}
  1488. oxyd_fla = cell{{{oxyd_custom}}}
  1489.  
  1490.  
  1491.  
  1492.  
  1493. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1494. -- MEANINGS FOR COMMON CELL KEYS -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1495. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  1496. -- here are declarations for default cell bindings
  1497.  
  1498. -- bindings based on init.lua functions
  1499. map_cell_meaning(".", abyss)
  1500. map_cell_meaning("0", oxyd)
  1501.  
  1502. -- common constructions
  1503. map_cell_meaning("W", cell{stone="st-wood"})
  1504. map_cell_meaning("B", cell{stone="st-block"})
  1505. map_cell_meaning("D", cell{stone="st-death"})
  1506. map_cell_meaning("=", cell{stone="st-glass"})
  1507. map_cell_meaning("X", cell{stone="st-grate1"})
  1508.  
  1509. -- actors
  1510. map_cell_meaning("o", cell{actor={"ac-whiteball-small", {player=0, mouseforce=1}}})
  1511. map_cell_meaning("O", cell{actor={"ac-blackball", {mouseforce=1}}})
  1512.  
  1513. -- presets
  1514. function meditation_mode()
  1515.    map_cell_meaning("O", hollow)
  1516. end
  1517.  
  1518. function multiplayer_mode()
  1519.    map_cell_meaning("1", cell{item="it-yinyang", actor={"ac-blackball", {mouseforce=1}}})
  1520.    map_cell_meaning("2", cell{item="it-yinyang", actor={"ac-whiteball", {mouseforce=1}}})
  1521. end
  1522.  
  1523. -- level mood
  1524. function grass_mode()
  1525.    map_cell_meaning(" ", cell{floor="fl-leaves"})
  1526.    map_cell_meaning("#", cell{stone="st-rock1"})
  1527. end
  1528.  
  1529. function metal_mode()
  1530.    map_cell_meaning(" ", cell{floor="fl-metal"})
  1531.    map_cell_meaning("#", cell{stone="st-rock2"})
  1532. end
  1533.  
  1534. -- maybe in a future, there will be a possibility to integrate Nat's mazes into maps
  1535. function maze_mode()
  1536.    enigma.LoadLib("lib/natmaze")
  1537.    --map_cell_meaning("!", )
  1538. end
  1539.  
  1540.     ]]></el:luamain>
  1541.     <el:i18n>
  1542.     </el:i18n>
  1543.   </el:protected>
  1544. </el:level>
  1545.