1 |
-- base methods for ant's enigma maps |
------------------------------------------------------------------------ |
2 |
-- (c) 2002-2003 Petr Machata/ant_39 |
-- Copyright (C) 2002-2003 Petr Machata |
|
-- Licensed under GPL v2.0 or above |
|
3 |
-- |
-- |
4 |
|
-- This program is free software; you can redistribute it and/or |
5 |
|
-- modify it under the terms of the GNU General Public License |
6 |
|
-- as published by the Free Software Foundation; either version 2 |
7 |
|
-- of the License, or (at your option) any later version. |
8 |
|
-- |
9 |
|
-- This program is distributed in the hope that it will be useful, |
10 |
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
|
-- GNU General Public License for more details. |
13 |
|
-- |
14 |
|
-- You should have received a copy of the GNU General Public License along |
15 |
|
-- with this program; if not, write to the Free Software Foundation, Inc., |
16 |
|
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. |
17 |
|
-- |
18 |
|
-- $Id$ |
19 |
|
------------------------------------------------------------------------ |
20 |
|
-- |
21 |
|
-- This module contains a support functions for designing enigma maps. |
22 |
|
-- There is a documentation available, please read it if you want |
23 |
|
-- to find out how to use this (see <enigma-dir>/doc/ant_lua.html), |
24 |
|
-- or look at how miscelaneous ant??.lua maps are done. |
25 |
|
-- Any questions, bug reports or anything related to this module please send to: |
26 |
|
-- my e-mail: ant_39 at centrum.cz |
27 |
|
-- enigma-devel ML: enigma-devel at nongnu.org |
28 |
|
-- |
29 |
|
-- revision history: |
30 |
-- 2003-01-07 -- special floor types and train support |
-- 2003-01-07 -- special floor types and train support |
31 |
-- 2003-01-11 -- multiples support (groups of doors, bolders etc.) |
-- 2003-01-11 -- multiples support (groups of doors, bolders etc.) |
32 |
-- 2003-01-14 -- bugfixes and error reporting, some new map-creating funcs |
-- 2003-01-14 -- bugfixes and error reporting, some new map-creating funcs |
48 |
-- Big changes in interfacing many parent functions, completely rewritten trains and puzzle generators, |
-- Big changes in interfacing many parent functions, completely rewritten trains and puzzle generators, |
49 |
-- changes in multiples (there are more kinds, and interfacing changed). |
-- changes in multiples (there are more kinds, and interfacing changed). |
50 |
-- A bug in multichar cell key fixed |
-- A bug in multichar cell key fixed |
51 |
|
-- 2003-02-25 -- |
52 |
|
-- add_multi* now uses tinsert/tremove, functions that work with multiples adapted where neccessary |
53 |
|
-- some comments fixed, few minor fixes across the source. warning(). |
54 |
|
-- 2003-03-08 -- |
55 |
|
-- support for parents that do not accept coordinates, default cell key meanings, updates in default |
56 |
|
-- parent handling, debug mode |
57 |
|
|
58 |
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
59 |
-- MISCELANEOUS - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
-- MISCELANEOUS - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
60 |
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
61 |
-- x,y should be numbers, although chars and strings are generally also the right choice, if you avoid ',' |
-- for warning messages |
62 |
|
function warning(text) |
63 |
|
print("warning: [ant.lua]: "..text) |
64 |
|
end |
65 |
|
|
66 |
|
-- for debug messages |
67 |
|
local ldm={str="", cnt=0} |
68 |
|
function debug(text) |
69 |
|
if (DEBUG_MODE) then |
70 |
|
if (%ldm.str~=text) then |
71 |
|
if (%ldm.cnt>1) then print("debug: [ant.lua]: last message repeated "..%ldm.cnt.." times") end |
72 |
|
if (text~="") then print("debug: [ant.lua]: "..text) end |
73 |
|
%ldm.str = text; |
74 |
|
%ldm.cnt = 0; |
75 |
|
else |
76 |
|
%ldm.cnt = %ldm.cnt +1; |
77 |
|
end |
78 |
|
end |
79 |
|
end |
80 |
|
|
81 |
|
-- x,y should be numbers, although chars and strings are generally also the right choice |
82 |
function getkey(...) |
function getkey(...) |
83 |
local key="" |
local key="" |
84 |
for i=1,getn(arg) do |
for i=1,getn(arg) do |
97 |
function transform_coords(x,y,w,h) |
function transform_coords(x,y,w,h) |
98 |
local x, y = (x or 0), (y or 0) |
local x, y = (x or 0), (y or 0) |
99 |
local w, h = (w or 0), (h or 0) |
local w, h = (w or 0), (h or 0) |
100 |
if (x) then if (x<0) then x = level_width +x-1 end end |
if (x<0) then x = level_width +x-1 end |
101 |
if (y) then if (y<0) then y = level_height+y-1 end end |
if (y<0) then y = level_height+y-1 end |
102 |
if (w) then if (w<=0) then w = level_width +w end end |
if (w<=0) then w = level_width +w end |
103 |
if (h) then if (h<=0) then h = level_height+h end end |
if (h<=0) then h = level_height+h end |
104 |
return x,y,w,h |
return x,y,w,h |
105 |
end |
end |
106 |
|
|
107 |
-- this couple of functions takes care of converting common tile coordinates to real coordinates of placed |
-- this couple of functions takes care of converting common tile coordinates to real coordinates of placed |
108 |
-- actor. It depends on the given actor_mode, which is being declared like this: |
-- actor. It depends on the given actor_mode, which is being declared like this: |
109 |
-- cells["O"]=cell{parent=cells["+"], item={face="ac-blackball", attr={player=0}, actor=ACTOR_MODE}} |
-- cells["O"]=cell{parent=cells["+"], actor={face="ac-blackball", attr={player=0}, mode=ACTOR_MODE}} |
110 |
-- |
-- |
111 |
-- the meaning of actor mode is as follows: |
-- the meaning of actor mode is as follows: |
112 |
-- value || x | y || meaning |
-- value || x | y || meaning |
138 |
-- VISUAL MAP CREATION -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
-- VISUAL MAP CREATION -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
139 |
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
140 |
|
|
141 |
|
-- debug mode |
142 |
|
-- in debug mode, ant.lua produces messages that inform you about the execution |
143 |
|
DEBUG_MODE = nil |
144 |
|
function debug_mode() |
145 |
|
DEBUG_MODE = 1 |
146 |
|
debug("debug mode turned on") |
147 |
|
end |
148 |
|
function debug_mode_off() |
149 |
|
debug("") |
150 |
|
DEBUG_MODE = nil |
151 |
|
warning("debug mode turned off") |
152 |
|
end |
153 |
|
|
154 |
-- width of key in map definition |
-- width of key in map definition |
155 |
-- CELL_KEY_WIDTH means how many characters occupy single map cell. In several maps I strongly |
-- CELL_KEY_WIDTH means how many characters occupy single map cell. In several maps I strongly |
156 |
-- wanted this functions (cannonball for example), and after all here it is. Usable in maps with |
-- wanted this functions (cannonball for example), and after all here it is. Usable in maps with |
159 |
function set_cell_key_width(w) |
function set_cell_key_width(w) |
160 |
if ( (type(w) == "number") and (w>0) and (floor(w)==w) ) then |
if ( (type(w) == "number") and (w>0) and (floor(w)==w) ) then |
161 |
CELL_KEY_WIDTH = w |
CELL_KEY_WIDTH = w |
162 |
|
debug("CELL_KEY_WIDTH is: "..w) |
163 |
return w |
return w |
164 |
else |
else |
165 |
print("warning: [ant.lua]: CELL_KEY_WIDTH has to be positive whole number") |
warning("CELL_KEY_WIDTH has to be positive whole number") |
166 |
return -1 |
return -1 |
167 |
end |
end |
168 |
end |
end |
191 |
end |
end |
192 |
end |
end |
193 |
|
|
194 |
|
debug("CELL_KEY_WIDTH guessed "..maxw) |
195 |
return set_cell_key_width(maxw) |
return set_cell_key_width(maxw) |
196 |
end |
end |
197 |
|
|
198 |
-- default cell parent is called before any of common cell parents |
-- default cell parent is called before any of common cell parents |
199 |
-- it may be a function(x,y) or a table of functions(x,y) |
-- default parent is a table, where each element may be |
200 |
|
-- + a function |
201 |
|
-- + a string, in which case this is a key in cellfunc table |
202 |
|
-- also set_default_parent can be called with a single function |
203 |
|
-- or string argument. The table will be built from this. |
204 |
DEFAULT_CELL_PARENT = nil |
DEFAULT_CELL_PARENT = nil |
205 |
function set_default_parent(func) |
function set_default_parent(func) |
206 |
if (type(func)=="function") then func = {func} end |
if ((type(func)=="function")or(type(func)=="string")) then |
207 |
|
func = {func} |
208 |
|
end |
209 |
|
|
210 |
if (type(func)=="table") then |
if (type(func)=="table") then |
211 |
for key,f in func do |
for key,f in func do |
212 |
local ftype = type(f) |
local ftype = type(f) |
213 |
if (ftype~="function") then |
if ((ftype~="function")and(ftype~="string")) then |
214 |
print("warning: [ant.lua]: element "..key.." of DEFAULT_CELL_PARENT has to be function, not "..ftype.."!") |
warning("element "..key.." of DEFAULT_CELL_PARENT has to be function or string, not "..ftype.."!") |
215 |
return |
return |
216 |
end |
end |
217 |
end |
end |
218 |
DEFAULT_CELL_PARENT = func |
DEFAULT_CELL_PARENT = func |
219 |
else print("warning: [ant.lua]: default parent has to be function or table of functions") |
else |
220 |
|
warning("default parent has to be function, table of functions or string key") |
221 |
end |
end |
222 |
end |
end |
223 |
|
|
241 |
-- + stone - if present, the stone shall be added to defined position |
-- + stone - if present, the stone shall be added to defined position |
242 |
-- + floor - the same, but for floor |
-- + floor - the same, but for floor |
243 |
-- + item - the same, but for item |
-- + item - the same, but for item |
244 |
-- ++ actor - if item.actor~=0 is set, set_actor will be called instead of set_item. |
-- + actor - the same, but for actor |
245 |
|
-- ++ mode - see get_actor_x() and _y() functions |
246 |
|
-- + pmode - parent arglist handling mode. Defaults to 0 and it means where to put (x,y) couple in arglist |
247 |
|
-- ++ pmode = -1 => do not place the (x,y) couple to arglist |
248 |
|
-- ++ pmode = +0 => place it before parent arguments |
249 |
function cell(structure) |
function cell(structure) |
250 |
local cell0 = {} |
local cell0 = {} |
251 |
|
|
259 |
-- parent is declared in this form: parent={{func1, arg1, arg2,...},...} |
-- parent is declared in this form: parent={{func1, arg1, arg2,...},...} |
260 |
-- if it's not, convert to this form |
-- if it's not, convert to this form |
261 |
local parent =(structure.parent or structure[1] or {}) |
local parent =(structure.parent or structure[1] or {}) |
262 |
if (type(parent)=="function") then parent = {parent} end |
|
263 |
for key,_ in parent do if (type(parent[key])=="function") then parent[key] = {parent[key]} end end |
if (type(parent)=="function") then |
264 |
|
parent = {parent} |
265 |
|
elseif (type(parent)=="table") then |
266 |
|
-- this is O.K. |
267 |
|
else |
268 |
|
warning("illegal: parent has to be a function, a table of functions") |
269 |
|
warning("or a table of curry-functions, not "..type(parent)) |
270 |
|
parent={} |
271 |
|
end |
272 |
|
|
273 |
|
for a=1,getn(parent) do |
274 |
|
if (type(parent[a])=="function") then |
275 |
|
parent[a] = {parent[a]} |
276 |
|
elseif (type(parent[a])=="table") then |
277 |
|
-- this is O.K. => a curry function call {func, arg1, arg2, ...} |
278 |
|
else |
279 |
|
warning("illegal: parent element id "..a.." should be a function or") |
280 |
|
warning("a curry-function construction, not "..type(parent[a])) |
281 |
|
parent[a]={function() end} |
282 |
|
end |
283 |
|
end |
284 |
|
|
285 |
--+ this functions manages calling various parent functions. Most functions are just func(x,y) or (x,y,something) |
--+ this functions manages calling various parent functions. Most functions are just func(x,y) or (x,y,something) |
286 |
-- but it's also possible to call ({{x1,y1},{x2,y2}}, something1, something2) |
-- but it's also possible to call ({{x1,y1},{x2,y2}}, something1, something2) |
287 |
-- This enables compatibility with and wrapping of functions form init.lua. |
-- This enables compatibility with and wrapping of functions form init.lua. |
288 |
--+ At the same moment, it's possible to declare some parametters in cell functions, like this: |
--+ At the same moment, it's possible to declare some parametters in cell functions, like this: |
289 |
-- cell1 = cell{parent={{func, par1}}} |
-- cell1 = cell{parent={{func, par1}}} |
290 |
-- and then call --cell(par2)-- instead of --func(par1, par2)-- |
-- and then call --cell1(par2)-- instead of --func(par1, par2)-- |
291 |
-- It may be used as a sort of curried functions from haskell, as far as my poor haskell knowledge says... |
-- It may be used as a sort of curried functions from haskell, as far as my poor haskell knowledge says... |
292 |
return function(...) |
return function(...) |
293 |
local xylist = tremove(arg, 1) |
local xylist = tremove(arg, 1) or {} |
294 |
local ret = nil |
local ret = nil |
295 |
|
|
296 |
-- first, get rid of cell(x,y) notation and convert it to cell({{x0,y0}}) notation |
-- first, get rid of cell(x,y) notation and convert it to cell({{x0,y0}}) notation |
297 |
if (type(xylist)=="number") then |
local xtp = type(xylist); |
298 |
|
if (xtp=="number") then |
299 |
xylist = {{xylist,tremove(arg,1)}} |
xylist = {{xylist,tremove(arg,1)}} |
300 |
elseif ((type(xylist)=="table")and(type(xylist[1])=="number")) then |
elseif ((xtp=="table")and(type(xylist[1])=="number")) then |
301 |
xylist = {xylist} |
xylist = {xylist} |
302 |
end |
end |
303 |
|
|
304 |
for _,tab0 in %parent do |
for idx=1,getn(%parent) do |
305 |
--+ item is table. first item is function, the rest are the the function arguments |
local tab0 = %parent[idx] |
306 |
--+ first extract function from tab, then include arguments from function call to the |
--+ tab0 is table. first item is function, the rest are the the function arguments |
307 |
|
--+ first extract function from tab0, then include arguments from function call to the |
308 |
-- tab, add a place for x,y coordinates and call it. Eventually tab will look like this: |
-- tab, add a place for x,y coordinates and call it. Eventually tab will look like this: |
309 |
-- {x, y, pfpar1, pfpar2, ..., arg1, arg2, ...} |
-- {x, y, pfpar1, pfpar2, ..., arg1, arg2, ...} |
310 |
local func = tab0[1] |
local func = tab0[1] |
311 |
local tab = {0,0} |
local pmode= tab0.mode or %parent.mode or 0 |
312 |
|
local tab = ((pmode==0) and {0,0}) or {} |
313 |
for a=2,getn(tab0) do tinsert(tab, tab0[a]) end |
for a=2,getn(tab0) do tinsert(tab, tab0[a]) end |
314 |
for a=1,getn(arg) do tinsert(tab, arg[a]) end |
for a=1,getn(arg) do tinsert(tab, arg[a]) end |
315 |
|
|
316 |
-- and call a function |
-- and call a function |
317 |
for i=1,getn(xylist) do |
if (pmode==0) then |
318 |
tab[1],tab[2] = transform_coords(xylist[i][1], xylist[i][2]) |
for i=1,getn(xylist) do |
319 |
ret = call(func, tab) |
tab[1],tab[2] = transform_coords(xylist[i][1], xylist[i][2]) |
320 |
|
ret = call(func, tab) |
321 |
|
end |
322 |
|
else |
323 |
|
ret = call(func, tab) |
324 |
end |
end |
325 |
end |
end |
326 |
|
|
339 |
end |
end |
340 |
end |
end |
341 |
|
|
|
|
|
342 |
-- width - this is width of the widest row of map |
-- width - this is width of the widest row of map |
343 |
function get_map_width(level) |
function get_map_width(level) |
344 |
local levelw = 0 |
local levelw = 0 |
362 |
return get_map_width(level), get_map_height(level) |
return get_map_width(level), get_map_height(level) |
363 |
end |
end |
364 |
|
|
365 |
|
-- common map |
366 |
|
-- if a key has no meaning declared in given 'cellfuncs', we'll look here |
367 |
|
-- whether there is no 'default' meaning |
368 |
|
-- look at the bottom of ant.lua to see the map |
369 |
|
DEFAULT_KEY_MEANING={} |
370 |
|
function map_cell_meaning(key, func) |
371 |
|
DEFAULT_KEY_MEANING[key]=func |
372 |
|
end |
373 |
|
|
374 |
|
-- use cells from default library in cellfuncs table |
375 |
|
-- this function accepts a table of cellfuncs and arbitrary number of string keys as arguments |
376 |
|
-- it loads the default keys to given cellfuncs table |
377 |
|
function use_cells(funcs, ...) |
378 |
|
for a=1,getn(arg) do |
379 |
|
funcs[arg[a]] = DEFAULT_KEY_MEANING[arg[a]] |
380 |
|
end |
381 |
|
end |
382 |
|
|
383 |
|
-- this function accepts a cell key and cellfuncs table |
384 |
|
-- it looks into that table and if there is no func with given key, it returns default value instead |
385 |
|
function get_cell_func(key, funcs) |
386 |
|
if (funcs[key]) then |
387 |
|
return funcs[key] |
388 |
|
elseif (DEFAULT_KEY_MEANING[key]) then |
389 |
|
debug("using DEFAULT_KEY_MEANING of '"..key.."'") |
390 |
|
return DEFAULT_KEY_MEANING[key] |
391 |
|
else |
392 |
|
warning("no default meaning found for map key '"..key.."'") |
393 |
|
return nil |
394 |
|
end |
395 |
|
end |
396 |
|
|
397 |
-- this draws the map to the position [x0,y0] |
-- this draws the map to the position [x0,y0] |
398 |
|
-- map is array of strings. Each string is one line of result map, each char is one map square. |
399 |
function draw_map(x0, y0, map, cellfuncs) |
function draw_map(x0, y0, map, cellfuncs) |
400 |
local funcs = cellfuncs or cells or {}; --we hope that if nil is passed, global cells is defined. |
local funcs = cellfuncs or cells or {}; --we hope that if nil is passed, global cells is defined. |
401 |
|
local map = map or {}; --but we have no default variable for a map itself |
402 |
|
|
403 |
for y,str in map do |
for y,str in map do |
404 |
local width = floor(strlen(str)/CELL_KEY_WIDTH); |
local width = floor(strlen(str)/CELL_KEY_WIDTH) |
405 |
|
|
406 |
for x = 1,width do |
for x = 1,width do |
407 |
local key = strsub(str, (x-1)*CELL_KEY_WIDTH+1, x*CELL_KEY_WIDTH) |
local key = strsub(str, (x-1)*CELL_KEY_WIDTH+1, x*CELL_KEY_WIDTH) |
|
local func = funcs[key] |
|
|
local ftype = type(func) |
|
408 |
local rx, ry = x+x0-1, y+y0-1 |
local rx, ry = x+x0-1, y+y0-1 |
409 |
|
|
410 |
-- call default parents |
-- call default parents |
411 |
if (DEFAULT_CELL_PARENT) then |
if (DEFAULT_CELL_PARENT) then |
412 |
for _,dpfunc in DEFAULT_CELL_PARENT do dpfunc(rx, ry) end |
for _,val in DEFAULT_CELL_PARENT do |
413 |
|
local dpfunc=0 |
414 |
|
if (type(val)=="string") then |
415 |
|
dpfunc=get_cell_func(val, funcs) |
416 |
|
else |
417 |
|
dpfunc=val |
418 |
|
end |
419 |
|
|
420 |
|
if (type(dpfunc)=="function") then |
421 |
|
dpfunc(rx, ry) |
422 |
|
else |
423 |
|
warning("unknown default parent for this key:") |
424 |
|
warning(val) |
425 |
|
end |
426 |
|
end |
427 |
end |
end |
428 |
|
|
429 |
-- call common cell function |
-- call common cell function |
430 |
|
local func = get_cell_func(key, funcs) |
431 |
|
local ftype = type(func) |
432 |
if (ftype == "function") then |
if (ftype == "function") then |
433 |
func(rx, ry) |
func(rx, ry) |
434 |
elseif (ftype == "nil") then |
elseif (ftype == "nil") then |
435 |
print("warning: [ant.lua]: function doesn't exist for map element '"..key.."'.") |
warning("function doesn't exist for map element '"..key.."'.") |
436 |
else |
else |
437 |
print("warning: [ant.lua]: cell element '"..key.."' is not a function, it's "..ftype..".") |
warning("cell element '"..key.."' is not a function, it's "..ftype..".") |
438 |
end |
end |
439 |
end |
end |
440 |
end |
end |
445 |
local flavor = oxyd_default_flavor |
local flavor = oxyd_default_flavor |
446 |
local levelw, levelh = get_map_size(level) |
local levelw, levelh = get_map_size(level) |
447 |
|
|
448 |
|
debug("creating world ["..levelw.."x"..levelh.."]") |
449 |
create_world(levelw, levelh) |
create_world(levelw, levelh) |
450 |
oxyd_default_flavor = flavor or oxyd_default_flavor or "b" |
oxyd_default_flavor = flavor or oxyd_default_flavor or "b" |
451 |
|
|
518 |
if (type(fillfunc)=="function") then fillfunc={fillfunc} end |
if (type(fillfunc)=="function") then fillfunc={fillfunc} end |
519 |
|
|
520 |
for _,func in fillfunc do |
for _,func in fillfunc do |
521 |
for i,xy in poslist do |
for i=1,getn(poslist) do |
522 |
func(transform_coords(xy[1], xy[2])) |
func(transform_coords(poslist[i][1], poslist[i][2])) |
523 |
end |
end |
524 |
end |
end |
525 |
end |
end |
758 |
-- group: object group table |
-- group: object group table |
759 |
-- attribs: object attributes |
-- attribs: object attributes |
760 |
function add_multistone(x, y, face, group, attribs) |
function add_multistone(x, y, face, group, attribs) |
761 |
local bc = getn(group)+1 |
local attribs = attribs or {} |
762 |
local bn = face..bc |
attribs["name"] = attribs.name or (face..(getn(group)+1)) |
763 |
|
tinsert(group, set_stone(face, x, y, attribs)) |
|
attribs = attribs or {} |
|
|
attribs["name"] = bn |
|
|
|
|
|
group[bc] = set_stone(face, x, y, attribs) |
|
764 |
end |
end |
765 |
|
|
766 |
-- add a floor to a group |
-- add a floor to a group |
768 |
-- group: object group table |
-- group: object group table |
769 |
-- attribs: object attributes |
-- attribs: object attributes |
770 |
function add_multifloor(x, y, face, group, attribs) |
function add_multifloor(x, y, face, group, attribs) |
771 |
local bc = getn(group)+1 |
local attribs = attribs or {} |
772 |
local bn = face..bc |
attribs["name"] = attribs.name or (face..(getn(group)+1)) |
773 |
|
tinsert(group, set_floor(face, x, y, attribs)) |
|
attribs = attribs or {} |
|
|
attribs["name"] = bn |
|
|
|
|
|
group[bc] = set_floor(face, x, y, attribs) |
|
774 |
end |
end |
775 |
|
|
776 |
-- add an item to a group |
-- add an item to a group |
779 |
-- attribs: object attributes |
-- attribs: object attributes |
780 |
function add_multiitem(x, y, face, group, attribs) |
function add_multiitem(x, y, face, group, attribs) |
781 |
local attribs = attribs or {} |
local attribs = attribs or {} |
782 |
attribs["name"] = face..(getn(group)+1) |
attribs["name"] = attribs.name or (face..(getn(group)+1)) |
783 |
tinsert(group, set_item(face, x, y, attribs)) |
tinsert(group, set_item(face, x, y, attribs)) |
784 |
end |
end |
785 |
|
|
787 |
-- face: this is floor face |
-- face: this is floor face |
788 |
-- group: object group table |
-- group: object group table |
789 |
-- attribs: object attributes |
-- attribs: object attributes |
790 |
function add_multiactor(x, y, face, group, opts, actor_mode) |
function add_multiactor(x, y, face, group, attribs, actor_mode) |
791 |
|
local attribs = attribs or {} |
792 |
local actor_mode = actor_mode or 3 |
local actor_mode = actor_mode or 3 |
793 |
local bc = getn(group)+1 |
attribs["name"] = attribs.name or (face..(getn(group)+1)) |
794 |
local bn = face..bc |
tinsert(group, set_actor(face, get_actor_x(x, actor_mode), get_actor_y(y, actor_mode), attribs)) |
|
|
|
|
opts = opts or {} |
|
|
opts["name"] = bn |
|
|
|
|
|
group[bc] = set_actor(face, get_actor_x(x, actor_mode or 1), get_actor_y(y, actor_mode), opts) |
|
795 |
end |
end |
796 |
|
|
797 |
-- for generic multiples, this only stores cell coordinates and tag information |
-- for generic multiples, this only stores cell coordinates and tag information |
807 |
-- another generic multiple |
-- another generic multiple |
808 |
-- this stores the result of given function(x,y) to table |
-- this stores the result of given function(x,y) to table |
809 |
function add_multiobject(x, y, func, group) |
function add_multiobject(x, y, func, group) |
810 |
local bc = getn(group)+1 |
tinsert(group, func(x, y)) |
|
group[bc] = func(x, y) |
|
811 |
end |
end |
812 |
|
|
813 |
-- add the rubber band between all objects in group 1 and all objects in group 2 |
-- add the rubber band between all objects in group 1 and all objects in group 2 |
814 |
-- that is, each object from gr1 will be connected with each object from gr2 |
-- that is, each object from gr1 will be connected with each object from gr2 |
815 |
function add_rubber_bands(gr1, gr2, strength, length) |
function add_rubber_bands(gr1, gr2, strength, length) |
816 |
for _,obj1 in gr1 do |
for i=1,getn(gr1) do |
817 |
for _,obj2 in gr2 do |
for j=1,getn(gr2) do |
818 |
AddRubberBand(obj1, obj2, strength, length) |
AddRubberBand(gr1[i], gr2[j], strength, length) |
819 |
end |
end |
820 |
end |
end |
821 |
end |
end |
823 |
-- add pairs: 1st object from gr1 will be connected with 1st from gr2 and so on |
-- add pairs: 1st object from gr1 will be connected with 1st from gr2 and so on |
824 |
-- requires same sized groups, of course... |
-- requires same sized groups, of course... |
825 |
function add_rubber_band_pairs(gr1, gr2, strength, length) |
function add_rubber_band_pairs(gr1, gr2, strength, length) |
826 |
for key1,obj1 in gr1 do |
for i=1,getn(gr1) do |
827 |
AddRubberBand(obj1, gr2[key1], strength, length) |
AddRubberBand(gr1[i], gr2[i], strength, length) |
828 |
end |
end |
829 |
end |
end |
830 |
|
|
851 |
|
|
852 |
-- send message to each object in group |
-- send message to each object in group |
853 |
function send_group_message(group, message, third) |
function send_group_message(group, message, third) |
854 |
for _,item in group do |
for i=1,getn(group) do |
855 |
enigma.SendMessage(item, message, third) |
enigma.SendMessage(group[i], message, third) |
856 |
end |
end |
857 |
end |
end |
858 |
|
|
859 |
|
-- send a message to named object |
860 |
|
function send_message_named(objname, message, third) |
861 |
|
enigma.SendMessage(enigma.GetNamedObject(objname), message, third) |
862 |
|
end |
863 |
|
|
864 |
-- set attribute to each of the objects in group |
-- set attribute to each of the objects in group |
865 |
function set_group_attribs(group, attribs) |
function set_group_attribs(group, attribs) |
866 |
for _,item in group do |
for i=1,getn(group) do |
867 |
set_attribs(item, attribs) |
set_attribs(group[i], attribs) |
868 |
end |
end |
869 |
end |
end |
870 |
|
|
877 |
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
878 |
|
|
879 |
-- creating trains: |
-- creating trains: |
880 |
-- each train is defined by two tables: |
-- each train is defined by two tables: |
881 |
-- +table of cells that the path consists of |
-- +table of cells that the path consists of |
882 |
-- +table of engines - path constructors and destructors |
-- +table of engines - path constructors and destructors |
883 |
-- |
-- |
884 |
-- basic idea is as follows: |
-- basic idea is as follows: |
885 |
-- in each tick, each of engines is moved to next cell in its path |
-- in each tick, each of engines is moved to next cell on its path |
886 |
-- each engine marks its rail - it sets a tag number of a current cell to some value |
-- each engine marks its rail - it sets a tag number of a current cell to some value |
887 |
-- constructors set tag number to 1 destructors to 0 |
-- constructors set tag number to 1, destructors to 0 |
888 |
-- constructor will only move to such a path cell, that has different tag from its own tag |
-- constructor will only move to such a path cell, that has different tag from its own tag |
889 |
-- that is, constructors will only move to non-1-tagged cells |
-- that is, constructors will only move to non-1-tagged cells |
890 |
-- and destructors will never move to cells tagged as zero |
-- and destructors will never move to cells tagged to zero |
891 |
-- and as each move means new tag value, the train keeps going forward |
-- and as each move means new tag value, the train keeps going forward |
892 |
-- |
-- |
893 |
-- how to setup a rail |
-- how to setup a rail |
901 |
-- cells["c"]=cell{parent={cells["_"], {add_multicell, loco, construct}}} |
-- cells["c"]=cell{parent={cells["_"], {add_multicell, loco, construct}}} |
902 |
-- cells["d"]=cell{parent={cells["!"], {add_multicell, loco, destruct}}} |
-- cells["d"]=cell{parent={cells["!"], {add_multicell, loco, destruct}}} |
903 |
-- |
-- |
904 |
-- that means: |
-- that means: |
905 |
-- cells marked "!" are part of path and are tagged to zero |
-- cells marked "!" are part of path and are tagged to zero |
906 |
-- cells marked "_" are also part of path, but are tagged to 1 instead |
-- cells marked "_" are also part of path, but are tagged to 1 instead |
907 |
-- cells marked "c" are part of engine ('loco' in example), and are tagged by function 'construct' |
-- cells marked "c" are part of engine ('loco' in example), and are tagged by function 'construct' |
908 |
-- cells marked "d" are also engines, but are tagged by function 'destruct' |
-- cells marked "d" are also engines, but are tagged by function 'destruct' |
909 |
-- |
-- |
910 |
-- you also need to declare tag-functions 'construct' and 'destruct', and also cells["."] and cells["'"] have |
-- you also need to declare tag-functions 'construct' and 'destruct', and also cells["."] and cells["'"] have |
911 |
-- to be defined somewhere. cells["."] is empty cell, if there is no train - abyss, a water or similar |
-- to be defined somewhere. cells["."] is empty cell, if there is no train - abyss, a water or similar |
912 |
-- cells["'"] is a surface of train - fl-normal, fl-wood, you choose. |
-- cells["'"] is a surface of train - fl-normal, fl-wood, you choose. |
954 |
-- cells["*"] - all puzzle stones are marked as asterisk in level map |
-- cells["*"] - all puzzle stones are marked as asterisk in level map |
955 |
-- |
-- |
956 |
-- puzzles = {}; -- create a table of puzzle stones |
-- puzzles = {}; -- create a table of puzzle stones |
957 |
-- cells["*"]=cell{parent={{add_multicell, puzzles}}} -- use generic multiple to add a cell to table |
-- cells["*"]=cell{{{add_multicell, puzzles}}} -- use generic multiple to add a cell to table |
958 |
-- |
-- |
959 |
-- and finally, at the end of the level: |
-- and finally, at the end of the level: |
960 |
-- render_puzzles(puzzles) -- place information from puzzle table to map |
-- render_puzzles(puzzles) -- place information from puzzle table to level |
961 |
|
-- |
962 |
|
-- if a puzzle cell is marked with tag=2: |
963 |
|
-- cells["#"]=cell{{{add_multicell, puzzles, 2}}} |
964 |
|
-- then the puzzle won't be generated on given map element, but it's neighbors will have their sockets |
965 |
|
-- opened in this direction like there should be one. |
966 |
|
|
967 |
|
|
968 |
-- this functions is called at the end of level file. It accepts |
-- this functions is called at the end of level file. It accepts |
969 |
-- tab, which is a list of registered puzzle cells |
-- tab, which is a list of registered puzzle cells |
970 |
-- generatorfunc, which is a cell[] function to add the floor or items to each registered cell |
-- generatorfunc, which is a cell[] function to add the floor or items to each registered cell |
971 |
-- the function goes through all registered cells, observing their neighbors |
-- the function goes through all registered cells, observing their neighbors |
972 |
-- and adding right puzzle stones to right places |
-- and adding right puzzle stones to right places |
973 |
function render_puzzles (tab, generatorfunc) |
function render_puzzles (tab, generatorfunc) |
974 |
for _,val in tab do |
for _,val in tab do |
984 |
end |
end |
985 |
|
|
986 |
dostring("puz = PUZ_"..up..right..down..left) |
dostring("puz = PUZ_"..up..right..down..left) |
987 |
puzzle(x, y, puz) |
if (val.tag~=2) then |
988 |
|
puzzle(x, y, puz) |
989 |
|
end |
990 |
end |
end |
991 |
end |
end |
992 |
|
|
1002 |
-- and maybe also some others that I do not recall now :) |
-- and maybe also some others that I do not recall now :) |
1003 |
-- Note, that basic syntax remain intact, so at first glance no changes are visible! |
-- Note, that basic syntax remain intact, so at first glance no changes are visible! |
1004 |
-- Wrapped functions are a lot slower, empirically nearly 3.5 times. Not a great deal, |
-- Wrapped functions are a lot slower, empirically nearly 3.5 times. Not a great deal, |
1005 |
-- as LUA is really fast. |
-- as LUA is really fast, and the same for enigma. Tested on rather slow 166MHz AMD, |
1006 |
|
-- 80 megs of memory, Win95 - you won't notice extra time spent by loading a level. |
1007 |
|
|
1008 |
-- stones |
-- stones |
1009 |
oxyd = cell{{{oxyd}}} |
oxyd = cell{oxyd} |
1010 |
fakeoxyd = cell{{{fakeoxyd}}} |
fakeoxyd = cell{fakeoxyd} |
1011 |
oneway = cell{{{oneway}}} |
oneway = cell{oneway} |
1012 |
laser = cell{{{laser}}} |
laser = cell{laser} |
1013 |
mirrorp = cell{{{mirrorp}}} |
mirrorp = cell{mirrorp} |
1014 |
mirror3 = cell{{{mirror3}}} |
mirror3 = cell{mirror3} |
1015 |
puzzle = cell{{{puzzle}}} |
puzzle = cell{puzzle} |
1016 |
switch = cell{{{switch}}} |
switch = cell{switch} |
1017 |
|
|
1018 |
-- floors |
-- floors |
1019 |
abyss = cell{{{abyss}}} |
abyss = cell{abyss} |
1020 |
hollow = cell{{{hollow}}} |
hollow = cell{hollow} |
1021 |
|
hill= cell{item="it-hill"} |
1022 |
|
|
1023 |
-- items |
-- items |
1024 |
Document = cell{{{Document}}} |
Document = cell{Document} |
1025 |
hammer = cell{{{hammer}}} |
hammer = cell{hammer} |
1026 |
dynamite = cell{{{dynamite}}} |
dynamite = cell{dynamite} |
1027 |
bomb = cell{{{bomb}}} |
bomb = cell{bomb} |
1028 |
shogundot= cell{{{shogundot}}} |
shogundot= cell{shogundot} |
1029 |
keya = cell{{{keya}}} |
keya = cell{keya} |
1030 |
keyb = cell{{{keyb}}} |
keyb = cell{keyb} |
1031 |
keyc = cell{{{keyc}}} |
keyc = cell{keyc} |
1032 |
shogundot1=cell{{{shogundot, 1}}} |
shogundot1=cell{{{shogundot, 1}}} |
1033 |
shogundot2=cell{{{shogundot, 2}}} |
shogundot2=cell{{{shogundot, 2}}} |
1034 |
shogundot3=cell{{{shogundot, 3}}} |
shogundot3=cell{{{shogundot, 3}}} |
1035 |
Wormhole = cell{{{Wormhole}}} |
Wormhole = cell{Wormhole} |
1036 |
doorh = cell{{{doorh}}} |
doorh = cell{doorh} |
1037 |
doorv = cell{{{doorv}}} |
doorv = cell{doorv} |
1038 |
gradient = cell{{{gradient}}} |
gradient = cell{gradient} |
1039 |
|
|
1040 |
-- lower case equivalents |
-- lower case equivalents |
1041 |
document = Document |
document = Document |
1042 |
wormhole = Wormhole |
wormhole = Wormhole |
1043 |
|
|
1044 |
|
|
1045 |
|
|
1046 |
|
|
1047 |
|
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
1048 |
|
-- MEANINGS FOR COMMON CELL KEYS -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
1049 |
|
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
1050 |
|
-- here are declarations for default cell bindings |
1051 |
|
|
1052 |
|
-- bindings based on init.lua functions |
1053 |
|
map_cell_meaning(".", abyss) |
1054 |
|
map_cell_meaning("0", oxyd) |
1055 |
|
|
1056 |
|
-- common constructions |
1057 |
|
map_cell_meaning("W", cell{stone="st-wood"}) |
1058 |
|
map_cell_meaning("=", cell{stone="st-glass"}) |
1059 |
|
map_cell_meaning("X", cell{stone="st-grate1"}) |
1060 |
|
map_cell_meaning("~", cell{stone="st-timer"}) |
1061 |
|
map_cell_meaning("o", cell{actor={"ac-whiteball-small", {player=0, mouseforce=1}}}) |
1062 |
|
map_cell_meaning("O", cell{actor={"ac-blackball", {player=0, mouseforce=1}}}) |
1063 |
|
|
1064 |
|
-- presets |
1065 |
|
function meditation_mode() |
1066 |
|
map_cell_meaning("O", hollow) |
1067 |
|
end |
1068 |
|
|
1069 |
|
function grass_mode() |
1070 |
|
map_cell_meaning(" ", cell{floor="fl-leaves"}) |
1071 |
|
map_cell_meaning("#", cell{stone="st-rock1"}) |
1072 |
|
end |
1073 |
|
|
1074 |
|
-- maybe in a future, there will be a possibility to integrate Nat's mazes into maps |
1075 |
|
function maze_mode() |
1076 |
|
Require("levels/natmaze.lua") |
1077 |
|
--map_cell_meaning("!", ) |
1078 |
|
end |