30
function lua2xml:add_error (e)
31
self.errors[e] = (self.errors[e] or 0) + 1
32
self.errormsg = self.errormsg .. e .. "\n"
35
function lua2xml:has_error ()
36
return self.errormsg ~= ""
39
function lua2xml:resize_world (w, h)
48
function lua2xml:set_table (table, x, y, o)
49
x, y = lua.floor (tonumber (x)), lua.floor (tonumber (y))
50
if x >= 0 and y >= 0 and x<self.w and y<self.h then
56
function lua2xml:optimize_floor ()
58
for y = 0,(self.h-1) do
59
for x = 0,(self.w-1) do
60
local fl = self.fl[x][y]
62
fl = {name="fl-abyss"} -- replace missing floor tiles with fl-abyss
65
floorcnt[fl.name] = (floorcnt[fl.name] or 0) + 1
70
for k,v in floorcnt do tinsert (floorlist, k) end
71
sort (floorlist, function (x, y) return (%floorcnt[x] < %floorcnt[y]) end)
73
-- Fill floor with most common floor tile
74
self.fillfloor = floorlist[getn(floorlist)]
76
-- Remove these floor tiles from the array
77
for y = 0,(self.h-1) do
78
for x = 0,(self.w-1) do
79
local fl = self.fl[x][y].name
80
if fl == self.fillfloor then
89
------------------------------
90
------------------------------
92
function xmlout_info (s)
94
print ("\t\t<name></name>")
95
print ("\t\t<author></author>")
96
print ("\t\t<copyright></copyright>")
97
print ("\t\t<license></license>")
101
function xmlout_options (s)
102
function yesno(x) return x==TRUE and "YES" or "NO" end
103
function noyes(x) return x==TRUE and "NO" or "YES" end
104
function printopt (name, val)
106
print ('\t<option name="'..name..'" value="'..val..'" />')
110
printopt ("reset", noyes(enigma.ConserveLevel))
111
printopt ("oxydflavor", oxyd_default_flavor)
112
printopt ("shuffle", yesno (lua2xml.oxyd_shuffle))
113
printopt ("scrolling", lua2xml.scrollmode)
114
printopt ("brittleness", enigma.Brittleness)
115
printopt ("slopeforce", enigma.SlopeForce)
116
printopt ("flatforce", enigma.FlatForce)
117
printopt ("frictionfactor", enigma.FrictionFactor)
118
printopt ("electricforce", enigma.ElectricForce)
119
printopt ("bumperforce", enigma.BumperForce)
120
printopt ("magnetforce", enigma.MagnetForce)
121
printopt ("magnetrange", enigma.MagnetRange)
122
printopt ("wormholeforce", enigma.WormholeForce)
123
printopt ("wormholerange", enigma.WormholeRange)
124
printopt ("holeforce", enigma.HoleForce)
127
function string_attribs (a)
131
s = s .. k .. "='" .. v .. "',"
135
return ' attribs="' .. s .. '"'
141
function xmlout_actors (s)
144
for i=1,getn(s.actors) do
145
local ac = s.actors[i]
147
local a =string_attribs(o.attribs)
148
print (format ('\t\t<actor kind="%s" x="%f" y="%f" %s />', o.name, ac.x, ac.y, a))
154
function xmlout_grid (s, tag, table)
155
function optimize_row (r)
156
-- remove trailing " -"'s and " *"'s
157
r = gsub (r, "[%- ]+$", "")
159
-- compress repeated " #"'s
160
r = gsub (r, "(#[ #]+ )", function (v)
161
local n = (strlen(v))/2
162
return n>1 and (n .. " ") or v
164
r = gsub (r, "(%-[ %-]+ )", function (v)
165
local n = (strlen(v))/2
166
return n>1 and ("-" .. n .. " ") or v
171
local attribobjs = ""
177
local o = table[x][y]
180
numempty = numempty + 1
182
local a = string_attribs (o.attribs)
184
attribobjs = attribobjs .. '\t\t<' .. tag .. ' x="' .. x .. '" y="' .. y
185
.. '" kind="' .. o.name .. '"' .. a .. ' />\n'
188
if o.name == prevname then
191
row = row .. strsub(o.name, 4) .. " "
197
row = optimize_row (row)
198
if numempty == s.w then
199
elseif row ~= "" then
200
print ('\t\t<row y="' .. y .. '">' .. row .. "</row>")
203
if attribobjs ~= "" then print (attribobjs) end
206
function xmlout_floors (s)
209
print ('\t\t<fill kind="' .. s.fillfloor .. '" />')
211
xmlout_grid (s, "floor", s.fl)
215
function xmlout_stones (s)
217
xmlout_grid (s, "stone", s.st)
218
for i=1,getn(s.oxyds) do
219
print ('\t\t<oxyd x="' .. s.oxyds[i].x .. '" y="' .. s.oxyds[i].y .. '" />')
224
function xmlout_items (s)
226
xmlout_grid (s, "item", s.it)
230
function xmlout_signals (s)
231
if getn (s.signals) == 0 then return end
236
function xmlout_rubberbands (s)
237
if (getn (s.rubberbands) == 0) then return end
238
print "\t<rubberbands>"
239
for i=1,getn (s.rubberbands) do
240
local rb = s.rubberbands[i]
241
print (format ('\t\t<rubberband from="%s" to="%s" strength="%f" length="%f" minlen="%f" />',
242
rb.o1, rb.o2, rb.force, rb.len, rb.minlen))
244
print "\t</rubberbands>"
247
function xmlout_lua (s)
248
if (s.luacode ~= "") then
256
function xmlout_level (s)
257
print ("<level width=\"" .. s.w.. "\" height=\"" .. s.h.. "\">")
264
xmlout_rubberbands (s)
271
-----------------------------------------------
272
-----------------------------------------------
284
FOLLOW_SCROLLING = 1,
286
FOLLOW_SCREENSCROLLING = 3,
290
options.Difficulty = 2
292
function enigma.GetAttrib (o, name)
293
return o.attribs[name]
296
function enigma.SetAttrib (o, key, val)
297
function escapestr (str)
298
str = gsub (str, "'", "\\'")
302
if key == "action" and val == "callback" then
303
lua2xml:add_error "- uses callbacks"
304
elseif o.name == "fl-gradient" and key == "type" then
306
if val >= 1 and val <= 12 then
307
o.name = "fl-gradient" .. val
310
local t = {[22] = 13, [21] = 14, [24] = 15, [23] = 16}
311
o.name = "fl-gradient" .. t[val]
314
elseif o.name == "st-puzzle" and key == "connections" then
316
"hollow", "w", "s", "sw", "e", "ew", "es", "esw", "n",
317
"nw", "ns", "nsw", "ne", "new", "nes", "nesw",
319
o.name = "st-puzzle-" .. t[val]
321
elseif o.name == "st-bolder" and key == "direction" then
322
local t = { "w", "s", "e", "n" }
323
o.name = "st-bolder-" .. t[val+1]
325
elseif o.name == "st-oneway" and key == "orientation" then
326
local t = { "w", "s", "e", "n" }
327
o.name = "st-oneway-" .. t[val+1]
329
elseif (o.name == "st-door_a" or o.name == "st-door_b") and key == "type" then
332
o.attribs[key] = escapestr (val)
335
function enigma.GetKind (o)
339
function enigma.NameObject (o, name)
340
o.attribs["name"] = name
341
lua2xml.namedobjs[name] = o
344
function enigma.GetNamedObject (name)
345
return lua2xml.namedobjs[name]
348
function world.Resize (w, h)
349
lua2xml:resize_world (w, h)
352
function enigma.SendMessage (o, msg, val)
353
lua2xml:add_error "- uses enigma.SendMessage"
356
function enigma.GetTicks ()
357
lua2xml:add_error "- uses enigma.GetTicks"
361
function enigma.SetFloor (x, y, o) lua2xml:set_table (lua2xml.fl, x, y, o) end
362
function enigma.SetItem (x,y, o) lua2xml:set_table (lua2xml.it, x, y, o) end
363
function enigma.SetStone (x,y, o) lua2xml:set_table (lua2xml.st, x, y, o) end
364
function enigma.SetActor (x, y, o) tinsert (lua2xml.actors, {obj=o, x=x, y=y}) end
366
function enigma.KillFloor (x, y) lua2xml:set_table (lua2xml.fl, x, y, nil) end
367
function enigma.KillItem (x, y) lua2xml:set_table (lua2xml.it, x, y, nil) end
368
function enigma.KillStone (x, y) lua2xml:set_table (lua2xml.st, x, y, nil) end
370
function enigma.GetItem (x, y) return lua2xml.it[x][y] end
372
function enigma.MakeObject (name)
373
return {name=name, attribs = {}}
376
function enigma.AddRubberBand (o1, o2, force, len, minlen)
377
function add_missing_name (o)
378
if o.attribs.name == nil then
379
enigma.NameObject (o, "namedobj" .. lua2xml.objcnt)
380
lua2xml.objcnt = lua2xml.objcnt + 1
383
add_missing_name (o1); add_missing_name (o2)
384
tinsert (lua2xml.rubberbands,
385
{o1 = o1.attribs.name, o2=o2.attribs.name,
386
force = force, len = len, minlen = minlen or 0})
389
function display.SetFollowMode (m)
390
lua2xml.scrollmode = m
393
function enigma.FindDataFile (f)
394
return lua2xml.datadir .. "/" .. f
397
function enigma.AddConstantForce (x, y)
398
lua2xml.luacode = lua2xml.luacode .. "enigma.AddConstantForce (" .. x .. ", " .. y .. ")\n"
401
function enigma.SetCompatibility (name)
402
lua2xml.luacode = lua2xml.luacode .. "enigma.SetCompatibility (\"" .. name .. "\")\n"
405
function enigma.date ()
406
lua2xml:add_error "- uses enigma.date"
410
function enigma.GetObjectTemplate ()
411
lua2xml:add_error "- uses enigma.GetObjectTemplate"
414
function enigma.AddScramble ()
415
lua2xml:add_error "- uses enigma.AddScramble"
418
function enigma.SetScrambleIntensity ()
419
lua2xml:add_error "- uses enigma.SetScrambleIntensity"
422
function world.DefineSimpleStoneMovable ()
423
lua2xml:add_error "- uses world.DefineSimpleStoneMovable"
426
function world.DefineSimpleStone ()
427
lua2xml:add_error "- uses world.DefineSimpleStone"
430
function display.DefineAlias ()
431
lua2xml:add_error "- uses display.DefineAlias"
434
function enigma.IsSolved ()
435
lua2xml:add_error "- uses display.IsSolved"
439
function run_level_script (fname)
441
for k,v in globals() do g[k] = v end
442
local oldglobals = globals(g)
444
-- Include standard init.lua --
445
dofile (enigma.FindDataFile ("init.lua"))
447
-- Override definitions from init.lua --
448
function g.oxyd (x, y)
449
tinsert (lua2xml.oxyds, {x=x, y=y})
452
function g.oxyd_shuffle ()
453
lua2xml.oxyd_shuffle = TRUE
456
-- Run level script --
458
if not dofile (luafile) then
471
if getn (arg) ~= 1 then
472
print ("Usage: " .. arg[0] .. " filename.lua")
478
run_level_script (luafile)
480
--------------------------------
481
--------------------------------
483
lua2xml:optimize_floor ()
486
if not lua2xml:has_error() then
487
xmlout_level (lua2xml)
490
write (_STDERR, "There were errors converting '" .. luafile .. "': \n")
491
for k,v in lua2xml.errors do
492
write (_STDERR, k .. ' (' .. v .. ' times) \n')
494
write (_STDERR, '\n')