1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<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">
<el:protected>
<el:info el:type="library">
<el:identity el:title="" el:id="lib/libpuzzle"/>
<el:version el:score="2" el:release="3" el:revision="6" el:status="released"/>
<el:author el:name="Ronald Lamprecht" el:email="" el:homepage=""/>
<el:copyright>Copyright © 2008 Ronald Lamprecht</el:copyright>
<el:license el:type="GPL v2.0 or above" el:open="true"/>
<el:compatibility el:enigma="1.10">
</el:compatibility>
<el:modes el:easy="false" el:single="false" el:network="false"/>
<el:comments>
</el:comments>
<el:score el:easy="-" el:difficult="-"/>
</el:info>
<el:luamain><![CDATA[
function res.puzzle_finalization(context)
-- print("puzzle final - num pos "..#context[5])
local stones = {}
for i, ppos in ipairs(context[5]) do
local stone = st(context[5][i])
if -stone and stone:is("st_puzzle") then
table.insert(stones, stone)
end
end
stones = grp(stones)
-- seperate puzzles into huddles
local huddles = {}
while #stones > 0 do
local huddle = stones[1]:get_adjacents()
table.insert(huddles, huddle)
stones = stones - huddle
-- print("puzzle final - huddle of size "..#huddle)
end
-- print("puzzle final - num huddles "..#huddles)
-- shuffle huddles
local width = wo["Width"]
local height = wo["Height"]
local offsets = {W, S, E, N}
local dirchars = {"w","s","e","n"}
for h, huddle in ipairs(huddles) do
-- print("puzzle final - shuffle huddle of size "..#huddle)
local pfloors = fl(huddle)
local pushes = {}
local intensity = 0
local algorithm = 0 -- std
for puz in huddle do
local alg = puz["algorithm"]
if alg == "marked" then
algorithm = 1
end
intensity = math.max(intensity, puz["intensity"])
end
for puz in huddle do
for dir, offset in ipairs(offsets) do
local cand = puz - offset
if cand:exists() then
local cfloor = fl(cand)
local may_push = true
if pfloors[cfloor] == nil then
if algorithm == 1 then
local pushdirs = cfloor["push_directions"]
if type(pushdirs) ~= "string" or not pushdirs:find(dirchars[dir]) then
may_push = false
end
end
else -- floor is under the puzzle but if its marked, the levelautor wants to shuffle from here
may_push = false
if algorithm == 1 then
local pushdirs = cfloor["push_directions"]
if type(pushdirs) == "string" and pushdirs:find(dirchars[dir]) then
may_push = true
end
end
end
-- Add all possible shuffles from current position to the table
if may_push then
local length = 1
local lpos = puz + offset
while lpos:exists() and pfloors[fl(lpos)] ~= nil do
length = length + 1
lpos = lpos + offset
end
if length > 1 then
table.insert(pushes, {fl(puz), dir - 1, length})
-- print(" push ("..cfloor.x..","..cfloor.y..") dir "..(dir-1).." length "..length)
end
end
end
end
end
-- How many pull_rotations we try to do?
intensity = intensity * #huddle
if intensity > 0 then
intensity = intensity + math.random(0, 1)
end
-- and now, let's shuffle!
while intensity > 0 and #pushes > 0 do
local pidx = random(#pushes) -- select a random push pos/dir
local puzz = st(pushes[pidx][1])
local dir = pushes[pidx][2]
local length = pushes[pidx][3]
local nextpuzz = st(puzz + offsets[dir + 1])
-- check for leading sequence of hollow puzzles
while length > 2 and puzz["hollow"] and nextpuzz["hollow"] do
puzz = nextpuzz
nextpuzz = st(puzz + offsets[dir + 1])
length = length - 1
end
if not nextpuzz["hollow"] then
puzz:pull_rotate(dir)
end
-- decrement in any case - there may exist no way scramble
intensity = intensity - 1
end
end
-- cleanup for subsequent calls
context[5] = {}
end
function res.puzzle_newtile(key, template, suffix)
local decl = template:_declaration() -- get a deep copy
local result
for i, tile in ipairs(decl) do
if type(tile) == "string" then
if result == nil then
result = ti[tile]
else
result = result .. ti[tile]
end
else
if tile[1]:find("st_puzzle", 1, true) then
local clusteridx = ("01234pqrstuvwxyz"):find(suffix, 1, true)
local connections = (" abcdefghijklmno"):find(suffix, 1 , true)
if clusteridx == nil then
clusteridx = ("56789PQRSTUVWXYZ"):find(suffix, 1, true)
if clusteridx ~= nil then
tile["hollow"] = true
end
end
if connections == nil then
connections = ("+ABCDEFGHIJKLMNO"):find(suffix, 1, true)
if connections ~= nil then
tile["hollow"] = true
end
end
if clusteridx ~= nil then
if clusteridx < 6 then
tile["cluster"] = clusteridx - 1
else -- pqr...xyz = 10...20
tile["cluster"] = clusteridx + 4
end
elseif connections ~= nil then
tile["connections"] = ({"","w","s","sw","e","ew","es","esw",
"n","nw","ns","nsw","ne","new","nes","nesw"})[connections]
end
end
if result == nil then
result = ti(tile)
else
result = result .. ti(tile)
end
end
end
ti[key] = result
end
function res.puzzle_implementation(context, evaluator, key, x, y)
for i, prefix in ipairs (context[4]) do
if key:find(prefix, 1, true) == 1 then
-- prefix based substitution
if evaluator(context[3], key, x, y) == nil then
local template = ti[prefix]
local suffix = key:sub(#(prefix) + 1)
assert_bool(template, "Resolver puzzle missing template rule '" ..prefix.."'.", 2)
assert_bool(#suffix == 1, "Resolver puzzle key '"..key.."' does not match template rule '" ..prefix.."'", 2)
res.puzzle_newtile(key, template, suffix)
end
table.insert(context[5], po(x,y))
return ti[key]
end
end
return evaluator(context[3], key, x, y)
end
function res.puzzle(subresolver, ...)
-- syntax: ... = <prefixkey>
-- context: [4] = table with unmodified rule tables
assert_bool(is_resolver(subresolver), "res.puzzle first argument (subresolver)", 2)
local args = {...}
local length = 0
for i, prefix in ipairs(args) do
assert_type(prefix, "res.puzzle puzzle prefix", 2, "string")
if length == 0 then
length = #prefix
elseif length ~= #prefix then
error("Resolver puzzle prefix " .. i.." mismatch of length", 2)
end
end
local context = {res.puzzle_implementation, res.puzzle_finalization, subresolver, args, {}}
setmetatable(context, res.metatable)
return context
end
]]></el:luamain>
<el:i18n>
</el:i18n>
</el:protected>
</el:level>
|