File: libflood_1.xml

package info (click to toggle)
enigma 1.30%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 76,132 kB
  • sloc: xml: 162,251; cpp: 67,393; ansic: 28,606; makefile: 1,986; sh: 1,298; yacc: 288; perl: 84; sed: 16
file content (419 lines) | stat: -rw-r--r-- 13,725 bytes parent folder | download | duplicates (5)
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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
<?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/libflood"/>
      <el:version el:score="1" el:release="1" el:revision="6" el:status="released"/>
      <el:author  el:name="Raoul Bourquin" el:email="" el:homepage=""/>
      <el:copyright>Copyright © 2007 Raoul Bourquin</el:copyright>
      <el:license el:type="GPL v2.0 or above" el:open="true"/>
      <el:compatibility el:enigma="0.92">
      </el:compatibility>
      <el:modes el:easy="false" el:single="false" el:network="false"/>
      <el:comments>
        <el:code>Lua 5.1 and XML converted by Leveladministrators</el:code>
      </el:comments>
      <el:score el:easy="-" el:difficult="-"/>
    </el:info>
    <el:luamain><![CDATA[
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- REFERENCE --
---------------
-- Parameters:
--
-- land_map: Charmap containig the landscape with the (un)floodable floors
-- Allowed chars: "#" : unfloodable
--                " " : floodable, not yet flooded
--                "~" : flooded (is water)
--
-- top_left: Array with the real levelcoordinates of the top left corner.
-- 
-- flood_method: Method to determine the next tiles.
-- This can be: 1 : only examine the north, east, south and west field
--              2 : examine all 8 neighbour fields
--
-- Used Globals (interesting for programmers only):
-- flood_map: Arraymap with the current state of the flood, starts as copy of land_map
-- flood_front: Coordinates of all tiles to examine in this step
-- to_flood: All tiles that will be flooded at the end of this step

-- Defaults:
-- Declare all as local to avoid a conflict with variables maybe used by the levelauthors
local land_map = nil
local top_left = nil
local flood_method = nil
local flood_map = nil
local flood_front = nil
local to_flood = nil

function init_flood(new_map, corner, method)
    -- Set defaults if no values are given:
    if new_map ~= nil then
        land_map = new_map
    else
        land_map = {"~"}
    end
    if corner ~= nil then
        top_left = corner
    else
        top_left = {0,0}
    end
    if flood_method ~= nil then
        flood_method = method
    else
        flood_method = 1
    end

    -- Is the map bigger than 0 x 0 ?
    local x, y = get_map_size(land_map)
    if x < 1 or y < 1 then
        error("init_flood(new_map, corner, method): Map "..tostring(x).." x "..tostring(y).." is too small!\n")
    end
    -- Is the map rectangular?
    is_rectangular()
    -- Test top_left corner for valid koordinates
    -- We do not test, if the map is bigger than the level!
    -- The bottom right corner may lie outside of the level -> flood_it will raise an error ...
    if top_left[1] < 0 or top_left[2] < 0 then
        error("init_flood(new_map, corner, method): Invalid value for top left map corner! "..tostring(top_left[1])..";"..tostring(top_left[2]).."\n")
    end
    -- Valid flood method?
    if flood_method ~= 1 and flood_method ~= 2 then
        error("init_flood(new_map, corner, method): Invalid value for method: "..tostring(method).."! Values are 1 or 2.\n")
    end

    -- Build up the flood_map table.
    build_up_flood_map(land_map)
    -- Build up the data for a new flood_front.
    new_flood_front()
    search_initial_water()
    -- Now draw the initial waterspots.
    flood_it(flood_front,top_left)
    return 0
end

function do_flood()
    -- Create a new global to_flood.
    new_to_flood()
    -- Iterate over all elements in flood_front to find the tiles, we have to flood.
    local flood_front_size = table.getn(flood_front)
    -- DEBUG:
    --print("Flood Front has size: "..tostring(flood_front_size))
    
    local k,v
    for k,v in pairs(flood_front) do
        local akt_pos = flood_front[k]
        if flood_method == 1 then
            examine_field_nesw(akt_pos[1], akt_pos[2])
        elseif flood_method == 2 then
            examine_field_all8(akt_pos[1], akt_pos[2])
        end
    end

    -- Write the to_flood to flood_front.
    clear_flood_front()
    copy_to_flood_to_flood_front()
    -- We don't need to update the flood_map, because we updated it in
    -- examine_field_neighbour(x,y). This improves performance a big bit!
    --update_flood_map()
    -- FLOOD!
    flood_it(to_flood,top_left)
    return 0
end
--------------------------------------------------------------------------------
-- Export public functions:
-- Not yet used
--init_flood = init_flood
--do_flood = do_flood
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Get the dimensions of the land_map:
function get_map_size(land_map)
    local y_size=table.getn(land_map)
    local x_size=string.len(land_map[1])
    return x_size, y_size
end

-- Get the dimensions of the flood_map:
function get_flood_map_size(flood_map)
    local y_size=table.getn(flood_map)
    local x_size=table.getn(flood_map[1])
    return x_size, y_size
end

-- This function is not used anymore
function is_inside_map(x,y)
    -- Test, if x and y are inside the flood_map. If no, raise an error.
    local x_size, y_size = get_flood_map_size(flood_map)
    if x > x_size then
        error("is_inside_map(x,y): x is not inside the map! "..tostring(x).."\n")
    end
    if y > y_size then
        error("is_inside_map(x,y): y is not inside the map! "..tostring(y).."\n")
    end
end

function is_on_border(x,y)
    -- Test, if x and y are on the flood_map border.
    local x_size, y_size = get_flood_map_size(flood_map)
    local on_left, on_right, on_top, on_bottom = false, false, false, false
    if x == 1 then
        -- is on left border
        on_left = true
    end
    if x == x_size then
        -- is on right border
        on_right = true
    end
    if y == 1 then
        -- is on top border
        on_top = true
    end
    if y == y_size then
        -- is on bottom border
        on_bottom = true
    end
    return on_left, on_right, on_top, on_bottom
end

function is_rectangular()
    local x_size, y_size = get_map_size(land_map)
    -- Length of the first line in the map:
    local buffer = string.len(land_map[1])
    local i, temp
    for i=1, y_size do
        temp = string.len(land_map[i])
        if temp ~= buffer then
            error("init_flood(new_map, corner, method): Map is not rectangular!\n")
        end
    end
    return 0
end
--------------------------------------------------------------------------------
function get_specific_char(x,y)
    local akt_line = land_map[y]
    local this_char = string.sub(akt_line,x,x)
    return this_char
end

function parse_this_char(akt_char)
    if akt_char == "#" then
        -- Unfloodable
        return 0
    elseif akt_char == " " then
        -- Floodable, not yet flooded
        return 1
    elseif akt_char == "~" then
        -- Floodable, flooded
        return 2
    else
        error("init_flood(new_map, corner, method): Illegal char \""..akt_char.."\" in the map! Valid chars are: [#, ,~].\n")
    end
end

function build_up_flood_map(land_map)
    -- new global:
    flood_map={}
    local x_size, y_size = get_map_size(land_map)
    -- build up the flood_map table:
    local i,j
    for i=1, y_size do
        -- each line is a table:
        flood_map[i]={}
        for j=1, x_size do
            local akt_char = get_specific_char(j,i)
            flood_map[i][j] = parse_this_char(akt_char)
        end
    end
    return 0
end
--------------------------------------------------------------------------------
function modify_flood_map(x,y,type)
    -- Not needed, calls from within this lib are valid
    --is_inside_map(x,y)
    -- type valid?
    --if type ~= 0 and type ~= 1 and type ~= 2 then
    --    error("modify_flood_map(x,y,type): Illegal type! "..tostring(type).."\n")
    --end
    flood_map[y][x] = type
    return 0
end
--------------------------------------------------------------------------------
function new_flood_front()
    -- new global:
    flood_front = {}
    return 0
end

function add_to_flood_front(x,y)
    local this_pos = {x,y}
    table.insert(flood_front,this_pos)
    return 0
end
--------------------------------------------------------------------------------
function search_initial_water()
    local x_size, y_size = get_flood_map_size(flood_map)
    local has_any_water = 0
    local i,j
    for i=1, y_size do
        for j=1, x_size do
            if flood_map[i][j] == 2 then
                has_any_water = has_any_water+1
                add_to_flood_front(j,i)
            end
        end
    end
    if has_any_water == 0 then
        error("init_flood(new_map, corner, method): No water found! Please set at least 1 water tile!\n")
    end
    return 0
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function new_to_flood()
    -- new global:
    to_flood = {}
    return 0
end

function add_to_flood(x,y)
    local this_pos = {x,y}
    table.insert(to_flood,this_pos)
    return 0
end
--------------------------------------------------------------------------------
---F-L-O-O-D---M-E-T-H-O-D-S----------------------------------------------------
-- Method 1:
function examine_field_nesw(x,y)
    -- Check, if x or y is out of the flood_map bounds
    -- Not needed, calls from within this lib are valid
    --is_inside_map(x,y)

    local on_left, on_right, on_top, on_bottom = is_on_border(x,y)
    -- NORTH
    if not on_top then
        examine_field_neighbour(x,y-1)
    end
    -- EAST
    if not on_right then
        examine_field_neighbour(x+1,y)
    end
    -- SOUTH
    if not on_bottom then
        examine_field_neighbour(x,y+1)
    end
    -- WEST
    if not on_left then
        examine_field_neighbour(x-1,y)
    end
    return 0
end

-- Method 2:
function examine_field_all8(x,y)
    -- Check, if x or y is out of the flood_map bounds
    -- Not needed, calls from within this lib are valid
    --is_inside_map(x,y)

    local on_left, on_right, on_top, on_bottom = is_on_border(x,y)
    -- NORTH
    if not on_top then
        examine_field_neighbour(x,y-1)
        -- Check also for north-west and north-east
        if not on_left then
            examine_field_neighbour(x-1,y-1)
        end
        if not on_right then
            examine_field_neighbour(x+1,y-1)
        end
    end
    -- EAST
    if not on_right then
        examine_field_neighbour(x+1,y)
    end
    -- SOUTH
    if not on_bottom then
        examine_field_neighbour(x,y+1)
        -- Check also for south-west and south-east
        if not on_left then
            examine_field_neighbour(x-1,y+1)
        end
        if not on_right then
            examine_field_neighbour(x+1,y+1)
        end
    end
    -- WEST
    if not on_left then
        examine_field_neighbour(x-1,y)
    end
    return 0
end
--------------------------------------------------------------------------------
function examine_field_neighbour(x,y)
    -- What sort of floor is the examined position?
    if flood_map[y][x] == 0 then
        -- DEBUG:
        --print("Stone found at: "..tostring(x)..";"..tostring(y).."\n")
    elseif flood_map[y][x] == 1 then
        -- the only case we have to do something
        -- DEBUG:
        --print("Floodable ground found at: "..tostring(x)..";"..tostring(y).."\n")
        add_to_flood(x,y)
        -- Mark field as flooded in flood_map here will improve performance!!
        modify_flood_map(x, y, 2)
    elseif flood_map[y][x] == 2 then
        -- DEBUG:
        --print("Water found at: "..tostring(x)..";"..tostring(y).."\n")
    -- If there are more possibilities, add more elseifs here.
    -- We need no default-error, because flood_map IS clean.
    -- Errors were detected in parse_this_char().
    end
end
--------------------------------------------------------------------------------
function clear_flood_front()
    -- Just recreate the var.
    new_flood_front()
    return 0
end

function copy_to_flood_to_flood_front()
    local tab_size = table.getn(to_flood)
    for i=1, tab_size do
        local temp = to_flood[i]
        local temp_x = temp[1]
        local temp_y = temp[2]
        add_to_flood_front(temp_x,temp_y)
    end
    return 0
end

-- Fill the flood_map with the additional flooded fields. This is obsolete since
-- we add the fields just when they are detected.
function update_flood_map()
    local tab_size = table.getn(flood_front)
    for i=1, tab_size do
        local temp = to_flood[i]
        local temp_x = temp[1]
        local temp_y = temp[2]
        modify_flood_map(temp_x, temp_y, 2)
    end
    return 0
end
--------------------------------------------------------------------------------
function flood_it(map,top_left)
    local k, v
    for k,v in pairs(map) do
        local akt_pos = map[k]
        set_floor("fl-water", top_left[1]+akt_pos[1]-1, top_left[2]+akt_pos[2]-1)
    end
end
--------------------------------------------------------------------------------
---E--N--D------O--F------L--I--B--F--L--O--O--D--------------------------------
--------------------------------------------------------------------------------
    ]]></el:luamain>
    <el:i18n>
    </el:i18n>
  </el:protected>
</el:level>