1 |
-- This is the library used by all xsok_????.lua's |
-- This is the library used by all Sokoban levels |
2 |
-- Filename: ralf_sokoban.lua |
-- Filename: ralf_sokoban.lua |
3 |
-- Copyright: (C) Mar 2003 Ralf Westram |
-- Copyright: (C) Mar 2003 Ralf Westram |
4 |
-- Contact: amgine@reallysoft.de |
-- Contact: amgine@reallysoft.de |
22 |
-- 'o' boxes |
-- 'o' boxes |
23 |
-- '.' targets |
-- '.' targets |
24 |
-- '*' box on target |
-- '*' box on target |
25 |
-- '@' player (needed) |
-- '@' player |
26 |
|
-- '+' player (on target) |
27 |
|
|
28 |
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |
29 |
|
|
69 |
debug("level done"); |
debug("level done"); |
70 |
end |
end |
71 |
|
|
72 |
|
locked_door_triggered = 0 -- one of the doors is locked until ALL targets are covered |
73 |
|
|
74 |
function trig(which) |
function trig(which) |
75 |
local state = strsub(triggerstate,which,which) |
local state = strsub(triggerstate,which,which) |
76 |
if (state == "0") then state = "1" else state = "0" end |
if (state == "0") then state = "1" else state = "0" end |
77 |
|
|
78 |
|
local trig_door = -1 |
79 |
if (doors == triggers) then -- 1 trigger <-> 1 door |
if (doors == triggers) then -- 1 trigger <-> 1 door |
80 |
enigma.SendMessage(enigma.GetNamedObject("door"..shuffle[which]), "openclose", nil) |
trig_door = shuffle[which] |
81 |
|
-- enigma.SendMessage(enigma.GetNamedObject("door"..shuffle[which]), "openclose", nil) |
82 |
else |
else |
83 |
local s0,s1 = 0,0 |
local s0,s1 = 0,0 |
84 |
if (state=="1") then s1 = 1 else s0 = 1 end |
if (state=="1") then s1 = 1 else s0 = 1 end |
101 |
debug("s0="..s0.." s1="..s1.." wlow="..wlow) |
debug("s0="..s0.." s1="..s1.." wlow="..wlow) |
102 |
|
|
103 |
if ((s0==0) or (s0==1 and state=="0")) then |
if ((s0==0) or (s0==1 and state=="0")) then |
104 |
enigma.SendMessage(enigma.GetNamedObject("door"..shuffle[wlow]), "openclose", nil) |
trig_door = shuffle[wlow] |
105 |
debug("triggering door "..shuffle[wlow]) |
-- enigma.SendMessage(enigma.GetNamedObject("door"..shuffle[wlow]), "openclose", nil) |
106 |
|
-- debug("triggering door "..shuffle[wlow]) |
107 |
end |
end |
108 |
end |
end |
109 |
|
|
110 |
triggerstate = strsub(triggerstate,1,which-1)..state..strsub(triggerstate,which+1) |
triggerstate = strsub(triggerstate,1,which-1)..state..strsub(triggerstate,which+1) |
111 |
|
local all_covered = not strfind(triggerstate,"0") |
112 |
|
debug(triggerstate) |
113 |
|
|
114 |
if (not strfind(triggerstate,"0")) then |
if (trig_door ~= -1) then |
115 |
yep() |
if (trig_door ~= 1) then |
116 |
|
enigma.SendMessage(enigma.GetNamedObject("door"..trig_door), "openclose", nil) |
117 |
|
end |
118 |
end |
end |
119 |
debug(triggerstate) |
|
120 |
|
if (all_covered) then |
121 |
|
if (locked_door_triggered==0) then |
122 |
|
enigma.SendMessage(enigma.GetNamedObject("door1"), "open", nil) |
123 |
|
locked_door_triggered = 1 |
124 |
|
end |
125 |
|
else |
126 |
|
if (locked_door_triggered==1) then |
127 |
|
enigma.SendMessage(enigma.GetNamedObject("door1"), "close", nil) |
128 |
|
locked_door_triggered = 0 |
129 |
|
end |
130 |
|
end |
131 |
|
debug("locked_door_triggered="..locked_door_triggered) |
132 |
|
end |
133 |
|
|
134 |
|
-- actors position |
135 |
|
acx = 0 |
136 |
|
acy = 0 |
137 |
|
|
138 |
|
function set_the_actor(x,y) |
139 |
|
acx,acy = x+.5,y+.5 |
140 |
end |
end |
141 |
|
|
142 |
function set_soko_trigger(x,y) |
function set_soko_trigger(x,y) |
146 |
set_item(triggerface,x,y,{action="callback", target=funcn}) |
set_item(triggerface,x,y,{action="callback", target=funcn}) |
147 |
end |
end |
148 |
|
|
149 |
|
function set_actor_on_trigger(x,y) |
150 |
|
set_the_actor(x,y) |
151 |
|
set_soko_trigger(x,y) |
152 |
|
end |
153 |
|
|
154 |
function count_space(x,y) |
function count_space(x,y) |
155 |
space_count = space_count+1 |
space_count = space_count+1 |
156 |
end |
end |
157 |
|
|
158 |
function set_dok1(x,y) |
--function set_dok1(x,y) |
159 |
document(x,y, "1") |
-- document(x,y, "1") |
160 |
end |
--end |
161 |
function set_dok2(x,y) |
--function set_dok2(x,y) |
162 |
document(x,y, "2") |
-- document(x,y, "2") |
163 |
end |
--end |
164 |
|
|
165 |
function init(num) |
function init(num) |
166 |
local first = 0 |
local first = 0 |
196 |
cells["!"] = cell{parent = {spacecell,count_space}} |
cells["!"] = cell{parent = {spacecell,count_space}} |
197 |
cells[" "] = floorcell |
cells[" "] = floorcell |
198 |
cells["#"] = cell{parent = floorcell, stone = {face = wallface}} |
cells["#"] = cell{parent = floorcell, stone = {face = wallface}} |
199 |
|
|
200 |
cells["o"] = cell{parent = floorcell, stone = {face = boxface}} |
cells["o"] = cell{parent = floorcell, stone = {face = boxface}} |
201 |
cells["."] = cell{parent = {floorcell, set_soko_trigger}} |
cells["."] = cell{parent = {floorcell, set_soko_trigger}} |
202 |
|
cells["@"] = cell{parent = {floorcell, set_the_actor}} |
203 |
|
|
204 |
cells["*"] = cell{parent = {cells["o"], set_soko_trigger}} |
cells["*"] = cell{parent = {cells["o"], set_soko_trigger}} |
205 |
cells["@"] = cell{parent = floorcell, actor = {"ac-blackball", {player = 0}}} |
cells["+"] = cell{parent = {floorcell, set_actor_on_trigger}} |
206 |
|
|
207 |
if (first == 1) then |
-- if (first == 1) then |
208 |
cells["1"] = cell{parent={cells[" "], set_dok1}} |
-- cells["1"] = cell{parent={cells[" "], set_dok1}} |
209 |
cells["2"] = cell{parent={cells[" "], set_dok2}} |
-- cells["2"] = cell{parent={cells[" "], set_dok2}} |
210 |
end |
-- end |
211 |
end |
end |
212 |
|
|
213 |
-- wether there's space outside the level |
-- wether there's space outside the level |
261 |
local reachable = 0 |
local reachable = 0 |
262 |
local spacehere = 0 |
local spacehere = 0 |
263 |
for n=1,4 do |
for n=1,4 do |
264 |
if (state[n]=='!') then spacehere = n end |
if (state[n]=='!') then |
265 |
if (state[n]=='o' or state[n]==' ' or state[n]=='@') then reachable = n end |
if (spacehere == 0) then |
266 |
|
spacehere = n |
267 |
|
else |
268 |
|
-- positions with more than 1 adjacent space should never be used as doors |
269 |
|
-- (because you may escape there) |
270 |
|
spacehere = -1 |
271 |
|
end |
272 |
|
end |
273 |
|
if (state[n]=='o' or state[n]==' ' or state[n]=='@') then |
274 |
|
if (reachable == 0) then |
275 |
|
reachable = n |
276 |
|
else |
277 |
|
-- positions with more than 1 adjacent floor should never be used as doors |
278 |
|
-- (because they change the level logic) |
279 |
|
reachable = -1 |
280 |
|
end |
281 |
|
end |
282 |
end |
end |
283 |
|
|
284 |
if ((reachable~=0) and (spacehere~=0)) then |
if ((reachable>0) and (spacehere>0)) then |
285 |
local t = "v"; |
local t = "v"; |
286 |
if (spacehere >= 3) then t="h" end |
if (spacehere >= 3) then t="h" end |
287 |
|
|
294 |
end |
end |
295 |
end |
end |
296 |
|
|
297 |
-- delete adjacent oxyds |
-- delete adjacent oxyds and adjacent doors |
298 |
-- [first those with two neighbours or more neighbours, then those with one neighbour] |
-- [first those with two neighbours or more neighbours, then those with one neighbour] |
299 |
for delif=2,1,-1 do |
for delif=2,1,-1 do |
300 |
local deleted = 1 |
local deleted = 1 |
301 |
while (deleted==1) do |
while (deleted==1) do |
302 |
deleted = 0 |
deleted = 0 |
303 |
for p=1,positions do |
for p=1,positions do |
304 |
|
local xd1,yd1 = position[p][1],position[p][2] |
305 |
local xo1,yo1 = position[p][3],position[p][4] |
local xo1,yo1 = position[p][3],position[p][4] |
306 |
local neighbours = 0 |
local oneighbours = 0 |
307 |
|
local dneighbours = 0 |
308 |
for q=1,positions do |
for q=1,positions do |
309 |
if (p~=q) then |
if (p~=q) then |
310 |
|
local xd2,yd2 = position[q][1],position[q][2] |
311 |
local xo2,yo2 = position[q][3],position[q][4] |
local xo2,yo2 = position[q][3],position[q][4] |
312 |
|
|
313 |
if (xo1==xo2 and yo1==yo2) then -- oxyds use same position |
if (xo1==xo2 and yo1==yo2) then -- oxyds use same position |
314 |
neighbours = delif |
oneighbours = delif |
315 |
break |
break |
316 |
elseif (adjacent(xo1,yo1,xo2,yo2)) then |
elseif (adjacent(xo1,yo1,xo2,yo2)) then |
317 |
neighbours = neighbours+1 |
oneighbours = oneighbours+1 |
318 |
if (neighbours==delif) then break end |
if (oneighbours==delif) then break end |
319 |
|
end |
320 |
|
|
321 |
|
if (adjacent(xd1,yd1,xd2,yd2)) then |
322 |
|
dneighbours = dneighbours+1 |
323 |
|
if (dneighbours==delif) then break end |
324 |
end |
end |
325 |
end |
end |
326 |
end |
end |
327 |
if (neighbours>=delif) then |
if ((oneighbours>=delif) or (dneighbours>=delif)) then |
328 |
tremove(position,p) |
tremove(position,p) |
329 |
positions = positions-1 |
positions = positions-1 |
330 |
deleted = 1 |
deleted = 1 |
340 |
positions = positions - 1 |
positions = positions - 1 |
341 |
end |
end |
342 |
|
|
343 |
|
if (positions == 0) then |
344 |
|
error("No oxyds.") |
345 |
|
end |
346 |
|
|
347 |
-- now really set oxyds |
-- now really set oxyds |
348 |
for p=1,positions do |
for p=1,positions do |
349 |
local xd,yd = position[p][1],position[p][2] |
local xd,yd = position[p][1],position[p][2] |
400 |
|
|
401 |
triggerstate = strrep("0",triggers) |
triggerstate = strrep("0",triggers) |
402 |
display.SetFollowMode(display.FOLLOW_SCROLLING) |
display.SetFollowMode(display.FOLLOW_SCROLLING) |
403 |
|
|
404 |
|
set_actor("ac-blackball",acx,acy,{player=0}) |
405 |
end |
end |
406 |
|
|