From 660023553b48cae4f91bd749b1dc62156adb8486 Mon Sep 17 00:00:00 2001 From: Duane Robertson Date: Thu, 26 May 2016 07:07:14 -0500 Subject: [PATCH] Initial fortress work (mazes). --- fortress.lua | 125 ++++++++++++++++++++++++++++++++++++++++++++ init.lua | 2 + mapgen.lua | 140 ++++++++++++++++++++++++++------------------------ unionfind.lua | 48 +++++++++++++++++ 4 files changed, 248 insertions(+), 67 deletions(-) create mode 100644 fortress.lua create mode 100644 unionfind.lua diff --git a/fortress.lua b/fortress.lua new file mode 100644 index 0000000..4d5efa0 --- /dev/null +++ b/fortress.lua @@ -0,0 +1,125 @@ + +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 = {} + + for y2 = 0, n-1 do + for i = 1, 2 * n * n do + walls[i] = i + end + table.shuffle(walls) + + local set = unionfind(n * n) + local a, b, c, i, j, u, v + + for m = 1, #walls do + c = walls[m] - 1 + 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) + 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 + + for z1 = z, z + (1-v) * 5 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 = ivm + 1 + end + end + end + 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/init.lua b/init.lua index 49111b6..6abea99 100644 --- a/init.lua +++ b/init.lua @@ -49,8 +49,10 @@ function fun_caves.clone_node(name) end +dofile(path .. "/unionfind.lua") dofile(path .. "/nodes.lua") dofile(path .. "/deco.lua") dofile(path .. "/fungal_tree.lua") +dofile(path .. "/fortress.lua") dofile(path .. "/mapgen.lua") dofile(path .. "/mobs.lua") diff --git a/mapgen.lua b/mapgen.lua index 184c39c..3c7d177 100644 --- a/mapgen.lua +++ b/mapgen.lua @@ -120,89 +120,95 @@ local function generate(p_minp, p_maxp, seed) -- use the same seed (based on perlin noise). math.randomseed(minetest.get_perlin(seed_noise):get2d({x=minp.x, y=minp.z})) - local cave_1 = minetest.get_perlin_map(cave_noise_1, csize):get3dMap_flat(minp) - local cave_2 = minetest.get_perlin_map(cave_noise_2, csize):get3dMap_flat(minp) - local cave_3 = minetest.get_perlin_map(cave_noise_3, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z}) - local biome_n = minetest.get_perlin_map(biome_noise, csize):get3dMap_flat(minp) + local fortress = maxp.y / 3100 + if maxp.y < -250 and (DEBUG or math.random(200) == 1) then + fun_caves.fortress(node, data, area, minp, maxp, math.ceil(maxp.y / 3100)) + write = true + else + local cave_1 = minetest.get_perlin_map(cave_noise_1, csize):get3dMap_flat(minp) + local cave_2 = minetest.get_perlin_map(cave_noise_2, csize):get3dMap_flat(minp) + local cave_3 = minetest.get_perlin_map(cave_noise_3, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z}) + local biome_n = minetest.get_perlin_map(biome_noise, csize):get3dMap_flat(minp) - local ivm, ivm2, height, new_node + local ivm, ivm2, height, new_node - 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) + 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) - height = heightmap[index] - if height >= maxp.y - 1 and data[area:index(x, maxp.y, z)] ~= node('air') then - height = 31000 - heightmap[index] = height - elseif height <= minp.y then - height = -31000 - heightmap[index] = height - end + height = heightmap[index] + if height >= maxp.y - 1 and data[area:index(x, maxp.y, z)] ~= node('air') then + height = 31000 + heightmap[index] = height + elseif height <= minp.y then + height = -31000 + heightmap[index] = height + end - for y = minp.y, maxp.y do - if data[ivm] ~= node('air') and y < height - cave_3[index] and cave_1[index3d] * cave_2[index3d] > 0.05 then - data[ivm] = node("air") - write = true + for y = minp.y, maxp.y do + if data[ivm] ~= node('air') and y < height - cave_3[index] and cave_1[index3d] * cave_2[index3d] > 0.05 then + data[ivm] = node("air") + write = true - if y > 0 and cave_3[index] < 1 and y == height then - -- Clear the air above a cave mouth. - ivm2 = ivm - for y2 = y + 1, maxp.y + 8 do - ivm2 = ivm2 + area.ystride - if data[ivm2] ~= node("default:water_source") then - data[ivm2] = node("air") + if y > 0 and cave_3[index] < 1 and y == height then + -- Clear the air above a cave mouth. + ivm2 = ivm + for y2 = y + 1, maxp.y + 8 do + ivm2 = ivm2 + area.ystride + if data[ivm2] ~= node("default:water_source") then + data[ivm2] = node("air") + end end end end - end - ivm = ivm + area.ystride - index3d = index3d + csize.x + ivm = ivm + area.ystride + index3d = index3d + csize.x + end end end - end - -- Air needs to be placed prior to decorations. - local index = 0 - local index3d = 0 - local pn, biome - 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) + -- Air needs to be placed prior to decorations. + local index = 0 + local index3d = 0 + local pn, biome + 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) - height = heightmap[index] + height = heightmap[index] - for y = minp.y, maxp.y do - if y <= height - deco_depth and (height < 31000 or y < 0) then - new_node = fun_caves.decorate_cave(node, data, area, minp, y, ivm, biome_n[index3d]) - if new_node then - data[ivm] = new_node - write = true - end - elseif y < height then - if data[ivm] == node("air") and (data[ivm - area.ystride] == node('default:stone') or data[ivm - area.ystride] == node('default:sandstone')) then - data[ivm - area.ystride] = node("dirt") - write = true - end - else - pn = minetest.get_perlin(plant_noise):get2d({x=x, y=z}) - biome = biome_ids[biomemap[index]] - new_node = fun_caves.decorate_water(node, data, area, minp, maxp, {x=x,y=y,z=z}, ivm, biome, pn) - if new_node then - data[ivm] = new_node - write = true + for y = minp.y, maxp.y do + if y <= height - deco_depth and (height < 31000 or y < 0) then + new_node = fun_caves.decorate_cave(node, data, area, minp, y, ivm, biome_n[index3d]) + if new_node then + data[ivm] = new_node + write = true + end + elseif y < height then + if data[ivm] == node("air") and (data[ivm - area.ystride] == node('default:stone') or data[ivm - area.ystride] == node('default:sandstone')) then + data[ivm - area.ystride] = node("dirt") + write = true + end + else + pn = minetest.get_perlin(plant_noise):get2d({x=x, y=z}) + biome = biome_ids[biomemap[index]] + new_node = fun_caves.decorate_water(node, data, area, minp, maxp, {x=x,y=y,z=z}, ivm, biome, pn) + if new_node then + data[ivm] = new_node + write = true + end end + + ivm = ivm + area.ystride + index3d = index3d + csize.x end - - ivm = ivm + area.ystride - index3d = index3d + csize.x end end end diff --git a/unionfind.lua b/unionfind.lua new file mode 100644 index 0000000..ada55bc --- /dev/null +++ b/unionfind.lua @@ -0,0 +1,48 @@ +function table.shuffle(self) + local j + local t = self + + for i = #t, 2, -1 do + j = math.random(i) + t[i], t[j] = t[j], t[i] + end +end + + +function unionfind(max) + local u = { _parent = {}, _rank = {} } + + for i = 1, max do + u._parent[i] = i + u._rank[i] = 1 + end + + u.find = function(self, i) + local p = self._parent[i] + if i == p then + return i + end + self._parent[i] = self:find(p) + return self._parent[i] + end + + u.union = function(self, i, j) + local root1 = self:find(i) + local root2 = self:find(j) + + if root1 == root2 then + return + end + + if self._rank[root1] > self._rank[root2] then + self._parent[root2] = root1 + elseif self._rank[root2] > self._rank[root1] then + self._parent[root1] = root2 + else + self._parent[root2] = root1 + self._rank[root1] = self._rank[root1] + 1 + end + end + + return u +end