From f5ed9d1cb22969f9b3b6ca6dbcf64c306f6e3637 Mon Sep 17 00:00:00 2001 From: Duane Robertson Date: Thu, 26 May 2016 10:10:36 -0500 Subject: [PATCH] Fix maze algorithm. --- fortress.lua | 142 +++++++++++++++++--------------------------------- unionfind.lua | 28 ++++++++-- 2 files changed, 71 insertions(+), 99 deletions(-) diff --git a/fortress.lua b/fortress.lua index 4d5efa0..5ab6230 100644 --- a/fortress.lua +++ b/fortress.lua @@ -1,61 +1,72 @@ fun_caves.fortress = function(node, data, area, minp, maxp, level) - for z = minp.z, maxp.z do - for x = minp.x, maxp.x do - ivm = area:index(x, minp.y, z) - for y = minp.y, maxp.y do - if x == minp.x or x == maxp.x or z == minp.z or z == maxp.z then - data[ivm] = node('default:steelblock') - elseif (y - minp.y) % 5 == 0 then - data[ivm] = node('default:steelblock') - else - data[ivm] = node('air') - end - ivm = ivm + area.ystride - end - end - end - local n = 16 local walls = {} + local a, b, c, i, j, u, v, x, y, z, ivm, set, dox, doz for y2 = 0, n-1 do - for i = 1, 2 * n * n do + --for y2 = 0, 0 do + -- walls is zero-based. + for i = 0, 2 * n * n - 1 do walls[i] = i end table.shuffle(walls) - local set = unionfind(n * n) - local a, b, c, i, j, u, v + dox, doz = math.random(0, n-1), math.random(0, n-1) + for z = minp.z, maxp.z do + for y = minp.y + y2 * 5, minp.y + y2 * 5 + 4 do + ivm = area:index(minp.x, y, z) + for x = minp.x, maxp.x do + if (y - minp.y) % 5 == 0 then + if math.floor((z - minp.z) / 5) == doz and math.floor((x - minp.x) / 5) == dox and (z - minp.z) % 5 ~= 0 and (x - minp.x) % 5 ~= 0 and y ~= minp.y then + data[ivm] = node("air") + else + data[ivm] = node('default:steelblock') + end + elseif x == minp.x or z == minp.z or x == maxp.x or z == maxp.z then + data[ivm] = node('default:steelblock') + elseif (z - minp.z) % 5 == 0 or (x - minp.x) % 5 == 0 then + data[ivm] = node("default:sandstone") + else + data[ivm] = node("air") + end + ivm = ivm + 1 + end + end + end - for m = 1, #walls do - c = walls[m] - 1 + set = unionfind(n * n) + + for m = 0, #walls do + c = walls[m] a = math.floor(c / 2) i = a % n j = math.floor(a / n) u = c % 2 == 0 and 1 or 0 v = c % 2 == 1 and 1 or 0 b = a + u + n * v - if i < n - u and j < n - v and set:find(a+1) ~= set:find(b+1) then - set:union(a+1, b+1) + if i < n - u and j < n - v and set:find(a) ~= set:find(b) then + set:union(a, b) x = (i + u) * 5 + minp.x y = minp.y + y2 * 5 z = (j + v) * 5 + minp.z - if y > minp.y and math.random(20) == 1 then - for z1 = z + 1, z + 4 do - ivm = area:index(x+1, y, z1) - for x1 = x + 1, x + 4 do - data[ivm] = node("air") - ivm = ivm + 1 - end - end - end + --if y > minp.y and math.random(20) == 1 then + -- for z1 = z + 1, z + 4 do + -- ivm = area:index(x+1, y, z1) + -- for x1 = x + 1, x + 4 do + -- data[ivm] = node("air") + -- ivm = ivm + 1 + -- end + -- end + --end - for z1 = z, z + (1-v) * 5 do + for z1 = z + (1-v), z + (1-v) * 4 do for y1 = y + 1, y + 4 do - ivm = area:index(x, y1, z1) - for x1 = x, x + (1-u) * 5 do - data[ivm] = node("default:sandstone") + ivm = area:index(x + (1-u), y1, z1) + for x1 = x + (1-u), x + (1-u) * 4 do + if x1 < maxp.x and z1 < maxp.z and x1 > minp.x and z1 > minp.z then + data[ivm] = node("air") + end ivm = ivm + 1 end end @@ -63,63 +74,4 @@ fun_caves.fortress = function(node, data, area, minp, maxp, level) end end end - - --local n = 16 - --local walls = {} - --for i = 1, 3 * n * n * n do - -- walls[i] = i - --end - --table.shuffle(walls) - - --local set = unionfind(n * n * n) - --local a, b, c, i, j, k, u, v, w - - --for m = 1, #walls do - -- c = walls[m] - 1 - -- a = math.floor(c / 3) - -- i = a % n - -- j = math.floor(a / n) % n - -- k = math.floor(math.floor(a / n) / n) - -- u = c % 3 == 0 and 1 or 0 - -- v = c % 3 == 1 and 1 or 0 - -- w = c % 3 == 2 and 1 or 0 - -- b = a + u + n * (v + n * w) - -- if i < n - u and j < n - v and k < n - w and set:find(a+1) ~= set:find(b+1) then - -- set:union(a+1, b+1) - -- x = (i + u) * 5 + minp.x - -- y = (j + v) * 5 + minp.y - -- z = (k + w) * 5 + minp.z - -- for z1 = z, z + (1-w) * 5 do - -- for y1 = y, y + (1-v) * 5 do - -- ivm = area:index(x, y1, z1) - -- for x1 = x, x + (1-u) * 5 do - -- data[ivm] = node("default:steelblock") - -- ivm = ivm + 1 - -- end - -- end - -- end - -- end - --end - - --local index = 0 - --local index3d = 0 - --for z = minp.z, maxp.z do - -- for x = minp.x, maxp.x do - -- index = index + 1 - -- --index3d = noise_area:index(x - minp.x, 0, z - minp.z) - -- ivm = area:index(x, minp.y, z) - -- for y = minp.y, maxp.y do - -- if x == minp.x or x == maxp.x or z == minp.z or z == maxp.z or y == minp.y or y == maxp.y then - -- data[ivm] = node("default:steelblock") - -- elseif (y - minp.y) % 5 == 0 then - -- data[ivm] = node("default:stone") - -- else - -- data[ivm] = node("air") - -- end - - -- ivm = ivm + area.ystride - -- --index3d = index3d + csize.x - -- end - -- end - --end end diff --git a/unionfind.lua b/unionfind.lua index ada55bc..bc4f3cb 100644 --- a/unionfind.lua +++ b/unionfind.lua @@ -1,9 +1,12 @@ +-- All arrays are zero-based. + + function table.shuffle(self) local j local t = self - for i = #t, 2, -1 do - j = math.random(i) + for i = #t, 1, -1 do + j = math.random(0, i) t[i], t[j] = t[j], t[i] end end @@ -12,9 +15,9 @@ end function unionfind(max) local u = { _parent = {}, _rank = {} } - for i = 1, max do + for i = 0, max-1 do u._parent[i] = i - u._rank[i] = 1 + u._rank[i] = 0 end u.find = function(self, i) @@ -27,6 +30,8 @@ function unionfind(max) end u.union = function(self, i, j) + i = i or 0 + j = j or 0 local root1 = self:find(i) local root2 = self:find(j) @@ -46,3 +51,18 @@ function unionfind(max) return u end + +--local u = unionfind(5) +--print(dump(u)) +--u:union(1,2) +--print(dump(u)) +--u:union(1,2) +--print(dump(u)) +--u:union(3,4) +--print(dump(u)) +--u:union(1,0) +--print(dump(u)) +--u:union(1,3) +--print(dump(u)) +--u:union(4) +--print(dump(u))