From 9db4f7af6aebd6e902e578d0486d436f79fdec52 Mon Sep 17 00:00:00 2001 From: Izzy Date: Sun, 2 Jun 2019 12:43:56 -0600 Subject: [PATCH] big nasty function to find flat areas --- behaviors/area_stats.lua | 190 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 behaviors/area_stats.lua diff --git a/behaviors/area_stats.lua b/behaviors/area_stats.lua new file mode 100644 index 0000000..d2ddead --- /dev/null +++ b/behaviors/area_stats.lua @@ -0,0 +1,190 @@ + + + + +local type_lookup = {} + +for name,def in pairs(minetest.registered_nodes) do + if def.groups.soil then + type_lookup[minetest.get_content_id(name)] = 1 -- 1 is "ground" + elseif def.groups.cracky then + type_lookup[minetest.get_content_id(name)] = 1 -- cracky things are part of the ground + elseif def.groups.sand then + type_lookup[minetest.get_content_id(name)] = 1 + elseif def.groups.crumbly then + type_lookup[minetest.get_content_id(name)] = 1 -- gravel, clay, snow, etc + + elseif def.groups.choppy then + type_lookup[minetest.get_content_id(name)] = 0 -- trees, wood, etc + elseif def.groups.snappy then + type_lookup[minetest.get_content_id(name)] = 0 -- grass, leaves, etc + elseif def.groups.fleshy then + type_lookup[minetest.get_content_id(name)] = 0 -- apples + elseif def.groups.liquid then + type_lookup[minetest.get_content_id(name)] = 0 -- water, lava + end + +end + +type_lookup[minetest.get_content_id("air")] = 0 + + + + + +bt.register_action("AreaIsFlat", { + tick = function(node, data) + if not data.targetPos then + return "failed" + end + data.targetPos = vector.floor(data.targetPos) + + local mmin = vector.add(node.min, data.targetPos) + local mmax = vector.add(node.max, data.targetPos) + +-- local x1 = node.max.x + data.targetPos.x +-- local y1 = node.max.y + data.targetPos.y +-- local z1 = node.max.z + data.targetPos.z +-- local x0 = node.min.x + data.targetPos.x +-- local y0 = node.min.y + data.targetPos.y +-- local z0 = node.min.z + data.targetPos.z + + local vm = minetest.get_voxel_manip() + local emin, emax = vm:read_from_map( + mmin, + mmax + ) + local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax} + local data = vm:get_data() + print(dump(emin)) + print(dump(emax)) + + local x1 = mmax.x -- node.min.x + local y1 = mmax.y -- node.min.y + local z1 = mmax.z -- node.min.z + local x0 = mmin.x + local y0 = mmin.y + local z0 = mmin.z + + function ind(x, y, z) + local i = (z * area.zstride) + (y * area.ystride) + x + 1 + return math.floor(i) + end + + + local deltas = {} + local last_y = (y1 + y0) / 2 + local total_found = 0 + local mean = 0 + local total_missing = 0 +-- print(x1 .. " " .. y1 .. " " ..z1 ) + for z = z0, z1 do -- for each xy plane progressing northwards + for x = x0, x1 do -- for each node do + + local y = math.floor(y1 / 2) + local vi = area:index(x, y, z) + + + local t = type_lookup[data[vi]] or 0 +-- print(t .. " d:" .. data[vi].. " - x: " .. x .. ", y: " .. y .. ", z: " ..z) + + local found = false + if t == 0 then -- in the air, go down + while y > y0 do + y = y - 1 + vi = area:index(x, y, z) + t = type_lookup[data[vi]] or 0 +-- print("too high "..y) +-- print(t .. " d:" .. data[vi].. " - x: " .. x .. ", y: " .. y .. ", z: " ..z) + + + if t == 1 then + -- found the ground +-- print(minetest.get_name_from_content_id(data[vi])) + found = true + break + else +-- print(minetest.get_name_from_content_id(data[vi])) + end + end + + else -- underground, go up + + while y < y1 do + y = y + 1 + vi = area:index(x, y, z) +-- print("too low " .. y) + t = type_lookup[data[vi] ] or 0 +-- print(t .. " d:" .. data[vi].. " - x: " .. x .. ", y: " .. y .. ", z: " ..z) +-- print( + if t == 0 then + -- found the sky, go back down one + y = y - 1 + vi = area:index(x, y, z) +-- print(minetest.get_name_from_content_id(data[vi])) + found = true + break + else +-- print(minetest.get_name_from_content_id(data[vi])) + end + end + + end + + if found then + vi = area:index(x, y, z) +-- print("----- found " .. data[vi] .. " " ..minetest.get_name_from_content_id(data[vi])) + last_y = y + local dy = y - y0 + deltas[dy] = (deltas[dy] or 0) + 1 + total_found = total_found + 1 + mean = mean + dy + else + total_missing = total_missing + 1 +-- print("--------- missing") + end + + end + end + + print("total_found ".. total_found) + print("total_missing ".. total_missing) + print(dump(deltas)) + mean = mean / total_found + + local variance = 0 + for k,v in pairs(deltas) do + local d = mean - k + variance = variance + (d * d) + end + + variance = variance / total_found + + print("variance: ".. variance) + if variance > node.max_variance then + return "failed" + end + + return "success" + end, + + ctor = function(min, max, max_variance) + return { + min = min, + max = max, + max_variance = max_variance, + } + end, +}) + + + + + + + + + + + +