Page 1 of 1

Fix noise.terrace(), or expose floor() and/or modf() to noise expressions

Posted: Sun Jun 07, 2020 5:10 am
by Maxreader
Greetings!

While playing around with some noise expression stuff, I came across the same issue in this post: viewtopic.php?f=25&t=83807&p=489988&hil ... ce#p489988. To illustrate what the terrace function is supposed to do given the code that was provided, see the graph of variable b in the following link: https://www.desmos.com/calculator/daav2vjkcs. Subtracting x from the result, if the "strength" is 1, gives a modulo function, which is what I desire. Of course, I ran into the same issue as mooman did, that the terrace function seemingly does not work for either of negative x or negative y, even if it does not consume that respective variable in that expression. Given below is one way to reproduce the issue, using the value of iron ore richness as a debug tool:

Code: Select all

--modulo function derived from noise.terrace()
local function modulo(val, range)
    range = range or 1
    return val - noise.terrace(val, 0, range, 1)
end

--noise expression wrapping that function
data:extend{
{
        type = "noise-expression",
        name = "new-iron-ore",
        expression = noise.define_noise_function(
            function(x, y, tile, map) return modulo(x, 32) * 100
                        end)
    }
}

--applying that noise expression to iron ore within a map preset, and allowing iron ore to always take precedence
local mgp = data.raw["map-gen-presets"].default
mgp["test-preset"] = {
    name = "fractured-preset",
    order = "z",
    basic_settings = {
        property_expression_names = {
            ["entity:iron-ore:richness"] = "new-iron-ore",
            ["entity:iron-ore:probability"] = 100
        },
    },
}
Which produces the following kind of map:
Image
As you can see, there are bands of ore, with the richness being 0 for every x value that's divisible by 32. However, the function fails for y < 0, even though y is referenced nowhere in the expression.

I request that the matter be at least given cursory investigation, and failing a solution being found there, the pure floor() function (alternatively modf()) used in the underlying c++ being made available for use.

Re: Fix noise.terrace(), or expose floor() and/or modf() to noise expressions

Posted: Sun Jun 07, 2020 5:28 am
by Maxreader
As an extra interesting tidbit that points toward broken behavior, if you take the same code I posted above and set "strength" to 0, you get the following:
Image
That is to say, instead of being 0 everywhere as expected, you get nothing (maybe 0, maybe some negative number) for negative x, but still modulo for positive x.

Re: Fix noise.terrace(), or expose floor() and/or modf() to noise expressions

Posted: Sun Jun 07, 2020 7:05 am
by posila
Ok, I looked into it and terrace is indeed broken. Luckily it is not used in base game, so it should be safe to fix.

Re: Fix noise.terrace(), or expose floor() and/or modf() to noise expressions

Posted: Sun Jun 07, 2020 7:23 am
by Maxreader
Awesome, thank you for looking into it!

Re: Fix noise.terrace(), or expose floor() and/or modf() to noise expressions

Posted: Sun Jun 07, 2020 7:32 am
by Maxreader
While we're at it, if-else-chain also seems to not work correctly. Image
Is there any insight as to why, or what it actually expects on the other end? The current workaround is doing nasty "multiply by 0 or 1" type expressions like the following:

Code: Select all

local difference = pDistance - minDistance
            local clampedDifference = noise.min(difference, 0)
            local isMinimum = clampedDifference / difference
            secondDistance = secondDistance + (minDistance - secondDistance) * isMinimum
            value = value + (point.val - value) * isMinimum
            minDistance = minDistance + clampedDifference
which Factorio will eventually parse, but is rather slow.

Re: Fix noise.terrace(), or expose floor() and/or modf() to noise expressions

Posted: Wed Jul 29, 2020 6:27 pm
by Bilka
Noise.terrace was already fixed a few versions ago. With 0.18.37 I added floor(), modulo() and if-else-chain allows you to use variables in its conditions.