map_gen_settings and autoplacers

Place to get help with not working mods / modding interface.
PyroFire
Filter Inserter
Filter Inserter
Posts: 356
Joined: Tue Mar 08, 2016 8:18 am
Contact:

map_gen_settings and autoplacers

Post by PyroFire »

map_gen_settings isn't very well documented, and is somewhat confusing.
Same goes for autoplace.
Add to this, there is only one detailed guides about it, and even it is not really enough.
Here's a list of resources.
If anyone has any more please linky.

Specifically, i'm looking for better documentation on the "noise" library.
It seems extremely useful.

1. map_gen_settings, Tiles, biomes, autoplacements, decoratives, and noise.
From what i can tell so far, the following game table entries are relevant to detecting any variations to the base game, aka detecting mod changes.
These tables contain the key autoplace_specification to find it.

game.decorative_prototypes - https://lua-api.factorio.com/latest/Lua ... prototypes
game.autoplace_control_prototypes - https://lua-api.factorio.com/latest/Lua ... prototypes
game.noise_layer_prototypes - https://lua-api.factorio.com/latest/Lua ... prototypes
game.tile_prototypes - https://lua-api.factorio.com/latest/Lua ... prototypes
game.entity_prototypes - https://lua-api.factorio.com/latest/Lua ... prototypes

Not sure what these are:
game.named_noise_expressions - https://lua-api.factorio.com/latest/Lua ... xpressions

See also:
https://lua-api.factorio.com/latest/Con ... enSettings


2. autoplace and autoplace_specification, expression and property_expression

https://togos.github.io/togos-example-noise-programs/
https://wiki.factorio.com/Types/NoiseExpression

Some more examples:

Image: Image
Linky: https://cdn.discordapp.com/attachments/ ... _0.0.1.zip

Image: Image
Linky: https://cdn.discordapp.com/attachments/ ... 8/data.lua
Last edited by PyroFire on Fri Aug 16, 2019 4:44 pm, edited 1 time in total.
TOGoS
Former Staff
Former Staff
Posts: 97
Joined: Fri Jun 24, 2016 2:29 pm
Contact:

Re: map_gen_settings and autoplacers

Post by TOGoS »

PyroFire wrote: ↑Fri Aug 16, 2019 3:28 pm Not sure what these are:
game.named_noise_expressions - https://lua-api.factorio.com/latest/Lua ... xpressions
https://wiki.factorio.com/Prototype/Nam ... Expression
PyroFire
Filter Inserter
Filter Inserter
Posts: 356
Joined: Tue Mar 08, 2016 8:18 am
Contact:

Re: map_gen_settings and autoplacers

Post by PyroFire »

TOGoS wrote: ↑Fri Aug 16, 2019 4:23 pm
PyroFire wrote: ↑Fri Aug 16, 2019 3:28 pm Not sure what these are:
game.named_noise_expressions - https://lua-api.factorio.com/latest/Lua ... xpressions
https://wiki.factorio.com/Prototype/Nam ... Expression
Those just link here.
https://lua-api.factorio.com/latest/Con ... Expression

Someone told me these were used for the adjustable settings on the map generation page.
I am also unsure as to how to interface with these properly when writing my own noise expressions.

https://gist.githubusercontent.com/Bilk ... 3c1ae7/raw
^ this has been checked too.
There doesn't seem to be much else that goes with it, but i'm sure it is or can be used in the property expressions somewhere.
TOGoS
Former Staff
Former Staff
Posts: 97
Joined: Fri Jun 24, 2016 2:29 pm
Contact:

Re: map_gen_settings and autoplacers

Post by TOGoS »

PyroFire wrote: ↑Fri Aug 16, 2019 4:45 pm Those just link here.
https://lua-api.factorio.com/latest/Con ... Expression

Someone told me these were used for the adjustable settings on the map generation page.
I am also unsure as to how to interface with these properly when writing my own noise expressions.
What are you trying to accomplish? Noise expressions can reference the map generation settings via a number of variables (expressions with type = "variable"). There are functions in noise.lua that will create variable references for you for most of the settings so that you don't need to know their names (e.g. by using the map_props argument to the define_noise_function callback or by using get_control_setting(<control name>)).
PyroFire
Filter Inserter
Filter Inserter
Posts: 356
Joined: Tue Mar 08, 2016 8:18 am
Contact:

Re: map_gen_settings and autoplacers

Post by PyroFire »

TOGoS wrote: ↑Mon Aug 19, 2019 1:04 pm Noise expressions can reference the map generation settings via a number of variables (expressions with type = "variable"). There are functions in noise.lua that will create variable references for you for most of the settings so that you don't need to know their names (e.g. by using the map_props argument to the define_noise_function callback or by using get_control_setting(<control name>)).
I have since determined that, although writing a custom noise function is plausible, it is not very practical.
Though i have also read it and the resource noise functions, it is well documented and I wish i had checked it sooner.
It helped answer most of my questions about how to physically write the noise expressions themselves.
This brings me to second problem, purpose of why i needed the noise function to start with.
TOGoS wrote: ↑Mon Aug 19, 2019 1:04 pm What are you trying to accomplish?
Great question!

I want autoplace_controls and autoplace_settings (tiles, entities, and decoratives) to behave according to a specific noise function on demand.
Namely, to have a library of different noise functions with different purposes and select which one i want the autoplacer to be using for a specific surface.
This is the most preferable option, however, it is also sadly not possible in a control.lua.

The work-around involves re-writing all the resource noise functions to include "overrides" which result in the desired outcome.
This however is highly impractical because there is no mod compatability.

A Practical Problem

https://mods.factorio.com/mod/warptorio2

Problem #1: This mod involves a platform that grows in size, and teleports you and your entire factory between various planets. This will often overlap starting resources. I need the starting resources to spawn a bit further away from the spawn radius. It appears in noise functions (120*distance, 300*distance), but i cannot reasonably access or change it. This could be worked around with a custom noise function... But may not correctly function with mod-introduced resources.

Problem #2: This mod involves heavy customization of the surfaces and map_gen_settings, and is very similar in many ways to the Space Exploration mod.
This is why i'm asking for more.

For anything more unique or interesting to be possible, like say... procedurally generated volcano's and mountain's, plus modified noise to the rocks and a custom lava tile and call it a magma planet....
I won't be able to do the rocks because it would ruin all other planets, and I won't be able to use the lava tiles on really any other planet, say lava lakes or something, because again... Can't change the noise function.

If you have any suggestions on how to simplify this for myself and other mod makers, for the following purposes (more of these):

https://mods.factorio.com/mod/warptorio_planet_pack
https://mods.factorio.com/mod/warptorio_planet_maze

Any support would be most appreciated.
User avatar
BlueTemplar
Smart Inserter
Smart Inserter
Posts: 3234
Joined: Fri Jun 08, 2018 2:16 pm
Contact:

Re: map_gen_settings and autoplacers

Post by BlueTemplar »

PyroFire wrote: ↑Mon Aug 19, 2019 1:46 pm [...]
Problem #1: This mod involves a platform that grows in size, and teleports you and your entire factory between various planets. This will often overlap starting resources. I need the starting resources to spawn a bit further away from the radius. It appears in noise functions (120*distance, 300*distance), but i cannot reasonably access or change it. This could be worked around with a custom noise function... But may not correctly function with mod-introduced resources.
[...]
Have you tried balancing your mod around NO starting resources ? (Except maybe at the very 1rst planet?)

The devs have suggested that they might introduce this as a start game option in 0.17, not sure how much of that was implemented ..?
BobDiggity (mod-scenario-pack)
PyroFire
Filter Inserter
Filter Inserter
Posts: 356
Joined: Tue Mar 08, 2016 8:18 am
Contact:

Re: map_gen_settings and autoplacers

Post by PyroFire »

This looks promising on the surface, and is close to what i need, but this deals with map_gen_settings which i already have full control over.
It doesn't appear to do anything with noise functions.
But linkys are certainly related and relevant, thankyou :)

Re balancing around no starting resources : This is currently what's happening anyway. The starting resources are covered by the platform.
I'd like to adjust the spawn settings for this if possible, as the platform gets upgraded.
slippycheeze
Filter Inserter
Filter Inserter
Posts: 587
Joined: Sun Jun 09, 2019 10:40 pm
Contact:

Re: map_gen_settings and autoplacers

Post by slippycheeze »

PyroFire wrote: ↑Mon Aug 19, 2019 5:11 pm Re balancing around no starting resources : This is currently what's happening anyway. The starting resources are covered by the platform.
I'd like to adjust the spawn settings for this if possible, as the platform gets upgraded.
(see the bottom for another strategy that'd work effectively for your needs, also.)

Each surface can have independant map generation settings, and they work, y'know, independently. You can set them when you create a new surface via LuaGameScript.create_surface as the optional second argument.
PyroFire wrote: ↑Mon Aug 19, 2019 1:46 pm I want autoplace_controls and autoplace_settings (tiles, entities, and decoratives) to behave according to a specific noise function on demand.
Set the `autoplace_controls`,`autoplace_settings`, and when appropriate, `starting_area`, `starting_points`, and `property_expression_names` fields in the MapGenSettings when you create your surface. Set them to generate as you want, using pre-existing, or your own, noise expressions, etc.
PyroFire wrote: ↑Mon Aug 19, 2019 1:46 pm Namely, to have a library of different noise functions with different purposes and select which one i want the autoplacer to be using for a specific surface.
This is the most preferable option, however, it is also sadly not possible in a control.lua.
This is absolutely, entirely possible during the control phase. You can't define a *new* noise expression at that time, but the only thing that matters for is the *structure* of the noise expression. You can configure as many shapes as you want, and have them reference arbitrary variables from the `property_expression_names` table.

Since those variables can be noise expressions, you can even assemble arbitrarily complex structures by providing yourself the component parts to put together at runtime. So your worst case is a bit of time investment in building fully parameterized noise expressions in the basic shapes you want. There do not need be *any* fixed values in an expression.
PyroFire wrote: ↑Mon Aug 19, 2019 1:46 pm The work-around involves re-writing all the resource noise functions to include "overrides" which result in the desired outcome.
This however is highly impractical because there is no mod compatability.
This is entirely, two hundred percent "mod compatible", in the sense that those noise expressions are present in the map generator settings, and the mods can reference them or override them in the same way. That means that you have problems only if:
  • A mod blindly overwrites placement rules; That would stop your settings being used regardless of them being the "core" expressions, or your own expressions.
  • A mod places resources using lua scripting, not the core placement stuff, like "Resource Spawner Overhaul". That'll completely ignore your rules the same way if they are core or custom expressions.
  • A mod mutates the resources via lua scripting after placement, like the "Space Exploration" mod scaling all the resources on surface 1 down to <= 100 percent richness settings in the autoplace control expressions.
  • A mod places per-tile (or whatever) overrides, in which case it would already ignore your custom noise expressions.
...so, in any of the cases where a mod is incompatible because it doesn't respect the MapGenSettings rules, you wouldn't gain anything with core expressions being more configurable.

If by "no mod compatibility" you mean it won't work with custom resources in mods, you can use LuaGameScript.get_filtered_entity_prototypes or simple iteration on the entity prototypes in game, to find all the resources, and then override (as with core placement rules) their autoplacement rules to your hearts content.

The set of data is, of course, entirely fixed when control is entered the first time, so you can update that on init, and on configuration change, and it'll stay the same until the next time one of those is invoked.
How *else* could you do this?
Instead of using autoplacement controls, select the starting position of the platform and player when they move to the surface, via scripting creation of the platform, and manually placing the player, or by scripting to move the starting area resources out of the way. Either option will work just fineβ„’ for letting you do this in any way you want without having to deal with noise expressions, or anything else.

This is worse than just using the map generator as designed, I think, but the option remains open.
Is there a reasonable feature request somewhere in here?
I think so: asking for specific, concrete variables slotted into the "core" noise expressions to allow targeting specific parts of them for overriding without having to rewrite them. For example, you mention fixed values in the starting area expression. Asking for *those* to be configurable, with the same defaults as variables you can override, seems useful.
PyroFire
Filter Inserter
Filter Inserter
Posts: 356
Joined: Tue Mar 08, 2016 8:18 am
Contact:

Re: map_gen_settings and autoplacers

Post by PyroFire »

Hey thanks for response, there's a lot to cover here -
slippycheeze wrote: ↑Mon Aug 19, 2019 6:10 pm Each surface can have independant map generation settings, and they work, y'know, independently. You can set them when you create a new surface via LuaGameScript.create_surface as the optional second argument.
I don't have a problem with the map_gen_settings
slippycheeze wrote: ↑Mon Aug 19, 2019 6:10 pm Set the `autoplace_controls`,`autoplace_settings`, and when appropriate, `starting_area`, `starting_points`, and `property_expression_names` fields in the MapGenSettings when you create your surface. Set them to generate as you want, using pre-existing, or your own, noise expressions, etc.
I already have full control over the map_gen_settings to set these, but it does not let me control the noise functions very well.

slippycheeze wrote: ↑Mon Aug 19, 2019 6:10 pm This is absolutely, entirely possible during the control phase. You can't define a *new* noise expression at that time, but the only thing that matters for is the *structure* of the noise expression. You can configure as many shapes as you want, and have them reference arbitrary variables from the `property_expression_names` table.

Since those variables can be noise expressions, you can even assemble arbitrarily complex structures by providing yourself the component parts to put together at runtime. So your worst case is a bit of time investment in building fully parameterized noise expressions in the basic shapes you want. There do not need be *any* fixed values in an expression.
Yes this is the only work around.
slippycheeze wrote: ↑Mon Aug 19, 2019 6:10 pm This is entirely, two hundred percent "mod compatible", in the sense that those noise expressions are present in the map generator settings, and the mods can reference them or override them in the same way. That means that you have problems only if:
  • A mod blindly overwrites placement rules; That would stop your settings being used regardless of them being the "core" expressions, or your own expressions.
  • A mod places resources using lua scripting, not the core placement stuff, like "Resource Spawner Overhaul". That'll completely ignore your rules the same way if they are core or custom expressions.
  • A mod mutates the resources via lua scripting after placement, like the "Space Exploration" mod scaling all the resources on surface 1 down to <= 100 percent richness settings in the autoplace control expressions.
  • A mod places per-tile (or whatever) overrides, in which case it would already ignore your custom noise expressions.
Manual chunk generation would achieve the desired outcome, but that is over-complicating the problem.
Also i should add, I have already finished an example that directly overrides a map generator that uses on_chunk_generated to build its map:
https://mods.factorio.com/mod/warptorio ... _dangoreus
slippycheeze wrote: ↑Mon Aug 19, 2019 6:10 pm ...so, in any of the cases where a mod is incompatible because it doesn't respect the MapGenSettings rules, you wouldn't gain anything with core expressions being more configurable.
I would then either override it manually or ask the mod author for compatibility, like the dangoreus planet.
slippycheeze wrote: ↑Mon Aug 19, 2019 6:10 pm If by "no mod compatibility" you mean it won't work with custom resources in mods, you can use LuaGameScript.get_filtered_entity_prototypes or simple iteration on the entity prototypes in game, to find all the resources, and then override (as with core placement rules) their autoplacement rules to your hearts content.
Warptorio already does this.
It's needed for mod compatability with alien biomes and any other resource mods.
slippycheeze wrote: ↑Mon Aug 19, 2019 6:10 pm
How *else* could you do this?
Instead of using autoplacement controls, select the starting position of the platform and player when they move to the surface, via scripting creation of the platform, and manually placing the player, or by scripting to move the starting area resources out of the way. Either option will work just fineβ„’ for letting you do this in any way you want without having to deal with noise expressions, or anything else.

This is worse than just using the map generator as designed, I think, but the option remains open.
This would not achieve the desired outcome at all.
Changing which position on the map the platform spawns at does not change noise functions.
Nor would there be any way to predict what would be near the destination area.
slippycheeze wrote: ↑Mon Aug 19, 2019 6:10 pm
Is there a reasonable feature request somewhere in here?
I think so: asking for specific, concrete variables slotted into the "core" noise expressions to allow targeting specific parts of them for overriding without having to rewrite them. For example, you mention fixed values in the starting area expression. Asking for *those* to be configurable, with the same defaults as variables you can override, seems useful.
Yes adding more variables to the basic noise functions will allow specific overriding.
This addresses problem #1 for sure, but it does little to address the problem of needing multiple noise functions for the same control.

---------------------------------------------

You're right about the workaround - taking the base noise function (say coal for example), and adding a (default_noise * map_gen_settings.ENABLE_DEFAULT_NOISE=0 or 1)+(my_custom_noise) would achieve the desired outcome.
But this workaround over-complicates what is already a very big subject.
Not to mention the inefficiencies of running all that math just to * 0 when it's overridden.

What i'm hoping for is a way to define a "named_noise_expression", then set a control or autoplacer to use this noise expression by name.
That would simplify everything and give me the full control over the noise functions without any real hassle.

The "double, triple, quadruple the size of the noise function, add some multiply by zero's as overrides and simply tack on your other generators there" is too complicated, and it would become unmanageable very quickly and when only using just a couple of additional noise generators.
And yes.. that's before mentioning other mods.
As a result of the complexity and the workaround being too involved, i have already decided to not waste my time on such features.

It's a shame, but i'd rather get more of my mod done than fiddle around with something that was never intended to do what i'm trying to make it do.
Because keep in mind - Not only do i need to actually make this thing work, i would then need to make it mod-accessible and compatible, then write a guide on how other people can do it too: https://mods.factorio.com/mod/warptorio_planet_pack/faq

Yeah.. not going to waste my time unless it is easier to use custom noise functions on demand.

Instead of "name your variables this", "use this noise variable here", "use this 100 liner of code to "insert" your noise function alongside the other noise functions", then writing a convoluted script to "standardize" the noise functions, for example:
NOISE EXPRESSION:
myNoises={
["maze"]=noise.to_noise_function(...) return {} end,
}

for k,v in pairs(data.tile)do
if(v.autoplace)then
for i,e in pairs(v)do
table.insert(e.arguments,{function="multiply",value=noise.GetVariable("override_default")})
for x,y in pairs(myNoises)
table.insert(e,y)
e={arguments=e,function="add"}
end
end
end
end

CONTROL CODE:
named_noise_expressions={ ["iron-ore"]={["override_default"]=0,["override_maze"]=0,["override_dangoreus"]=0} }
-- Don't forget to add the new new noise variables whenever warptorio gets updated!
My suggestion would enable me to just do something like:
data:extend{ {type="custom_named_iron-ore_noise", expression={ whatever noise here} }

my_planet={
map_gen_settings={
named_noise_expressions={ ["iron-ore"]="custom_named_iron-ore_noise" },
},
}
Hopefully this will illustrate clearly why i'm asking to make this thing easier.
The problem is not that it isn't explicitly *impossible*, it's that it's too difficult to achieve cleanly, efficiently and effectively.
So the alternative is to simply not waste my time on something this involved and needlessly over-complicated.
That's fine by me.

So it is not me who is actually missing out on anything here.
It is, in fact, you the player who misses out by this being too complicated.


Another possible work-around is to extend copies of the autoplacement entities, tiles, decoratives etc and put my noise functions on those.
Then handle these autoplacement copies like a typical tile, overriding the nauvis ones when needed.
But there is a limit of 255 tiles and that would be reached fast.
This would otherwise work for all other autoplacers (controls, resources, entities and decoratives)
It just seems like there would be a better way than this.
slippycheeze
Filter Inserter
Filter Inserter
Posts: 587
Joined: Sun Jun 09, 2019 10:40 pm
Contact:

Re: map_gen_settings and autoplacers

Post by slippycheeze »

PyroFire wrote: ↑Tue Aug 20, 2019 12:58 am
slippycheeze wrote: ↑Mon Aug 19, 2019 6:10 pm Set the `autoplace_controls`,`autoplace_settings`, and when appropriate, `starting_area`, `starting_points`, and `property_expression_names` fields in the MapGenSettings when you create your surface. Set them to generate as you want, using pre-existing, or your own, noise expressions, etc.
I already have full control over the map_gen_settings to set these, but it does not let me control the noise functions very well.
OK. It is pretty clear by this point that there is a communication breakdown, and I don't understand what you want to achieve. You keep saying that you have full control over the map_gen_settings, and you *also* keep saying it won't let you solve the problem.

Which means that I (and I guess everyone else here, and in discord) don't understand what the actual problem is, because every single problem I understand you to have, you can solve with those.
PyroFire wrote: ↑Tue Aug 20, 2019 12:58 am You're right about the workaround - taking the base noise function (say coal for example), and adding a (default_noise * map_gen_settings.ENABLE_DEFAULT_NOISE=0 or 1)+(my_custom_noise) would achieve the desired outcome.
Which noise expression? The autoplace controls for coal (like every resource) have exactly two noise expressions: probability, and richness. Which one do you want to control?

Not that the answer to that question matters, because the way you do what you want is this:

Code: Select all

-- I can't remember the name of the "deep table copy" function, so this may not run correctly
new_mgs = table.deepcopy(game.player.surface.map_gen_settings)
-- use a custom noise function for coal placement, overriding the default value
new_mgs.property_expression_names["entity:coal:probability"] = "custom_coal_noise_function_name_for_probability"
new_mgs.property_expression_names["entity:coal:richness"] = "custom_coal_noise_function_name_for_richness"
-- create a new surface that will use those custom noise functions
surface = game.create_surface("custom_coal", new_mgs)
PyroFire wrote: ↑Tue Aug 20, 2019 12:58 am What i'm hoping for is a way to define a "named_noise_expression", then set a control or autoplacer to use this noise expression by name.
That would simplify everything and give me the full control over the noise functions without any real hassle.
So ... as far as I can tell what I answered above, and what you asked for here, are the same thing.

If not, please, be specific: which aspect of the noise expression(s) for coal did you want to change, and which you can't change using that mechanism?
PyroFire
Filter Inserter
Filter Inserter
Posts: 356
Joined: Tue Mar 08, 2016 8:18 am
Contact:

Re: map_gen_settings and autoplacers

Post by PyroFire »

slippycheeze wrote: ↑Tue Aug 20, 2019 2:17 pm If not, please, be specific: which aspect of the noise expression(s) for coal did you want to change, and which you can't change using that mechanism?
I want to use more than 1 noise expression at a time.


So.

Not an aspect of the noise expression.

The noise expression itself.

The perlin noise function.

This thing:

Image

I want it to be:

Image

OR

Image

But i want to switch between these 3 distinct, separate, individual and completely unique and unrelated from eachother, and do so on a per-surface basis.

Image



This is the sort of thing i was looking for, yes, but with a bit more control. not just probability or richness, but the noise expression itself.

Code: Select all

-- I can't remember the name of the "deep table copy" function, so this may not run correctly
new_mgs = table.deepcopy(game.player.surface.map_gen_settings)
-- use a custom noise function for coal placement, overriding the default value
new_mgs.property_expression_names["entity:coal:probability"] = "custom_coal_noise_function_name_for_probability"
new_mgs.property_expression_names["entity:coal:richness"] = "custom_coal_noise_function_name_for_richness"
-- create a new surface that will use those custom noise functions
surface = game.create_surface("custom_coal", new_mgs)
Are there any special arguments for the functions, do they get the x,y values and such? or are they called without args?
Trebor
Filter Inserter
Filter Inserter
Posts: 293
Joined: Sun Apr 30, 2017 1:39 pm
Contact:

Re: map_gen_settings and autoplacers

Post by Trebor »

You have three noise functions: N1, N2, N3. You want to use one of them based on surface S. Write N4 to call one of them depending on S, register N4 with the map generator.
slippycheeze
Filter Inserter
Filter Inserter
Posts: 587
Joined: Sun Jun 09, 2019 10:40 pm
Contact:

Re: map_gen_settings and autoplacers

Post by slippycheeze »

PyroFire wrote: ↑Tue Aug 20, 2019 3:25 pm
slippycheeze wrote: ↑Tue Aug 20, 2019 2:17 pm If not, please, be specific: which aspect of the noise expression(s) for coal did you want to change, and which you can't change using that mechanism?
I want to use more than 1 noise expression at a time.
Not an aspect of the noise expression.
The noise expression itself.
The perlin noise function.
I don't think you mean that you want to use something other than perlin noise generation, right? Like, this isn't "let me use a different function to generate the noise, such as a wavlet based noise generator", right? You just want to control the inputs to the existing perlin noise generator, in order to control the output?
PyroFire wrote: ↑Tue Aug 20, 2019 3:25 pm But i want to switch between these 3 distinct, separate, individual and completely unique and unrelated from eachother, and do so on a per-surface basis.
This is the sort of thing i was looking for, yes, but with a bit more control. not just probability or richness, but the noise expression itself.
....I'm really not following you here, and I think my problem is exactly that final sentence: "not just probability or richness, but the noise expression itself."

I'm pretty confident, now, part of the communication problem is that you keep talking about "THE" noise expression, and I keep talking about the multiple noise expressions associated with resource autoplacement.

So I'm obviously not working out what you are talking about correctly. Can you point to the, like, existing definition of the noise expression you want to change, or which part of the autoplace expression, or whatever it is?
PyroFire wrote: ↑Tue Aug 20, 2019 3:25 pm Are there any special arguments for the functions, do they get the x,y values and such? or are they called without args?
All the noise expressions evaluate "at the time they are used", independently on each surface. They have access to those through "variables", which include "x", "y", "distance", plus all the stuff in the map_gen_settings `property_expression_names`, which includes standard values like "moisture" and "elevation", but can also have whatever custom stuff you want in there.

So ... "with arguments", I guess, in the sense those variables are available. If you use the metatable magic in noise.define_noise_function to define them, then you would get them as arguments -- but you can reference any variable you want.
PyroFire
Filter Inserter
Filter Inserter
Posts: 356
Joined: Tue Mar 08, 2016 8:18 am
Contact:

Re: map_gen_settings and autoplacers

Post by PyroFire »

Trebor wrote: ↑Tue Aug 20, 2019 3:51 pm You have three noise functions: N1, N2, N3. You want to use one of them based on surface S. Write N4 to call one of them depending on S, register N4 with the map generator.
slippycheeze wrote: ↑Tue Aug 20, 2019 4:01 pm All the noise expressions evaluate "at the time they are used", independently on each surface. They have access to those through "variables", which include "x", "y", "distance", plus all the stuff in the map_gen_settings `property_expression_names`, which includes standard values like "moisture" and "elevation", but can also have whatever custom stuff you want in there.

So ... "with arguments", I guess, in the sense those variables are available. If you use the metatable magic in noise.define_noise_function to define them, then you would get them as arguments -- but you can reference any variable you want.
This is what I've been looking for.

Let me use a different function to generate the noise, such as a wavlet based noise generator.

And Trebor's idea to use a "control" noise function linked to several others will help to take a lot of the complexity out of the problem.

Hurray progress.

I can look closer into this stuff sometime soon.
slippycheeze
Filter Inserter
Filter Inserter
Posts: 587
Joined: Sun Jun 09, 2019 10:40 pm
Contact:

Re: map_gen_settings and autoplacers

Post by slippycheeze »

PyroFire wrote: ↑Tue Aug 20, 2019 4:11 pm This is what I've been looking for.
Let me use a different function to generate the noise, such as a wavlet based noise generator.
If that is actually what you want, it is impossible. Factorio only has a Perlin noise source, implemented in C++, and you can't add or change sources of noise. No mod can, though -- it is just as impossible for them as it would be for you. So I'm pretty sure that isn't what you want.

Two questions:

1. When is the noise expression evaluated? As in, when, exactly, during the life of the game, is the math done? During the data phase? Control phase?
2. How is wavlet based noise generator different to the perlin noise generator, in terms of what you could do with it in the game? (or, more briefly, why do you want to use wavlet noise generation instead?)

I suspect that answer will get to the root of the problem here. One way or another...
PyroFire
Filter Inserter
Filter Inserter
Posts: 356
Joined: Tue Mar 08, 2016 8:18 am
Contact:

Re: map_gen_settings and autoplacers

Post by PyroFire »

slippycheeze wrote: ↑Tue Aug 20, 2019 5:38 pm If that is actually what you want, it is impossible. Factorio only has a Perlin noise source, implemented in C++, and you can't add or change sources of noise. No mod can, though -- it is just as impossible for them as it would be for you. So I'm pretty sure that isn't what you want.
well, from what i've seen it is actually possible.
You just need to have a script that actually implements the noise type.

Example of different noise types:
https://mods.factorio.com/mod/dangOreus
https://mods.factorio.com/mod/warptorio ... _dangoreus

slippycheeze wrote: ↑Tue Aug 20, 2019 5:38 pm 1. When is the noise expression evaluated? As in, when, exactly, during the life of the game, is the math done? During the data phase? Control phase?
To be honest i'm not entirely sure when the expression is evaluated, but i'm pretty sure the timing is irrelevant - at least for my purposes.
Basically, differing math formulas and equations is needed for *some* different planets (but not all).
slippycheeze wrote: ↑Tue Aug 20, 2019 5:38 pm 2. How is wavlet based noise generator different to the perlin noise generator, in terms of what you could do with it in the game? (or, more briefly, why do you want to use wavlet noise generation instead?)
It's actually more about the noise math than the type of noise.
The peaks and the valleys as well as their distributions.

In terms of what needs to be done in the game -
See the first post, there are 2 pictures of the green water being used, and they are made by 2 different sets of noise math.
The first one has large smooth lakes.
The second one has messy green water patches scattered all over the place.

What i'm asking about is how to switch between these 2 "outcomes" on an as-needed, per-surface basis.

So the idea is for Planet A to have the large green lakes, but Planet B has the scattered green water.
These 2 planets use the same tile (graphics and such), but will use different autoplace noise expressions.
slippycheeze
Filter Inserter
Filter Inserter
Posts: 587
Joined: Sun Jun 09, 2019 10:40 pm
Contact:

Re: map_gen_settings and autoplacers

Post by slippycheeze »

PyroFire wrote: ↑Wed Aug 21, 2019 3:10 am
slippycheeze wrote: ↑Tue Aug 20, 2019 5:38 pm If that is actually what you want, it is impossible. Factorio only has a Perlin noise source, implemented in C++, and you can't add or change sources of noise. No mod can, though -- it is just as impossible for them as it would be for you. So I'm pretty sure that isn't what you want.
well, from what i've seen it is actually possible.
You just need to have a script that actually implements the noise type.
Sorry, yes, you are right: I didn't make it clear that is true only for the built-in map generator. You can absolutely do anything by overriding the `on_chunk_generated` event and writing it in Lua, as dangOreus, RSO, etc, do.

What you can't do is use `map_gen_settings` for that. You would just need to check the surface you were generating on in your `on_chunk_generated` and use whatever custom noise generator you wanted.

If that is what you want, just check the `surface` value in your `on_chunk_generated` handler, and dispatch to whatever you want for each individual surface. So your mod would work with the dangOreus integration mod to establish that a surface uses a Lua handler for resource generation, and (a) set the map_gen_settings to not place stuff, and (b) dispatch to the appropriate code, when that surface was the one live in `on_chunk_generated`.

Since it sounds like you need that at least some of the time, are you clear on how both those steps would be done?
PyroFire wrote: ↑Wed Aug 21, 2019 3:10 am
slippycheeze wrote: ↑Tue Aug 20, 2019 5:38 pm 1. When is the noise expression evaluated? As in, when, exactly, during the life of the game, is the math done? During the data phase? Control phase?
To be honest i'm not entirely sure when the expression is evaluated, but i'm pretty sure the timing is irrelevant - at least for my purposes.
Basically, differing math formulas and equations is needed for *some* different planets (but not all).
Cool. They evaluate during the C++ equivalent of `on_chunk_generated`, using the named noise expression that is set in the `map_gen_settings` for that specific surface. During the data phase the *equation* is configured, but it isn't evaluated. So you can't build a new equation on the fly, for the built-in generator. You can only change which one the C++ code uses for each surface, individually.
[/quote]

PyroFire wrote: ↑Wed Aug 21, 2019 3:10 am
slippycheeze wrote: ↑Tue Aug 20, 2019 5:38 pm 2. How is wavlet based noise generator different to the perlin noise generator, in terms of what you could do with it in the game? (or, more briefly, why do you want to use wavlet noise generation instead?)
It's actually more about the noise math than the type of noise.
The peaks and the valleys as well as their distributions.

In terms of what needs to be done in the game -
See the first post, there are 2 pictures of the green water being used, and they are made by 2 different sets of noise math.
The first one has large smooth lakes.
The second one has messy green water patches scattered all over the place.

What i'm asking about is how to switch between these 2 "outcomes" on an as-needed, per-surface basis.

So the idea is for Planet A to have the large green lakes, but Planet B has the scattered green water.
These 2 planets use the same tile (graphics and such), but will use different autoplace noise expressions.
Cool. OK. So, I think I do understand what you need here, and I just need to figure out how to communicate effectively about how to achieve that.

In Types/AutoplaceSpecification in the wiki, there is a list of properties, right?

Two of those have associated noise expressions, `probability_expression`, and `richness_expression`.
Those are the two fundamental noise equations that are used in placing resources by the C++ version of `on_chunk_generated`.

To override those two properties for a specific surface you can change the map_gen_settings for it as I showed before:

Code: Select all

map_gen_settings.property_expression_names["{tile|entity|decorative}:" .. prototype_name .. ":{probability|richness}"]
The value of that argument is a "named noise expression" defined during the data phase. So, if you do nothing the "green water" tile -- water-green, IIRC -- uses the values set during the data phase.

To change that for one surface, and one surface only, you do it by changing the map_gen_settings for that surface. The best way is setting it via the argument to `game.create_surface`, but you can fiddle it any time, and it'll apply to any new chunks generated.

That is, in the AutoplaceSpecification type the property field `probability_expression` corresponds to the control stage setting `map_gen_settings.property_expression_names["tile:water-green:probability"]`, and the property field `richness_expression` corresponds to `map_gen_settings.property_expression_names["tile:water-green:richness"]`.

Inside the C++ code the `on_chunk_generated` logic is evaluated for every surface individually, and uses the map_gen_settings for the individual surface to check for an override. If there isn't an override in property_expression_names, it goes back to the values in the autoplace specification prototype for the entity.

So, each surface has a unique and distinct `map_gen_settings`, which include a `seed` property -- the PRNG seed used for generating chunks on that surface, which also controls the perlin noise generator output. That means that even if two surfaces have the same map_gen_settings equations, as long as the seed is different they will generate different noise, and that flows through to different placement.

(If you don't specify the map_gen_settings in game.create_surface, it'll get an automatic copy of the "default" values, as in, surface[1], aka "navius", but they still have their own set of map_gen_settings.)

In summary:
  • if you need to generate noise from a non-perlin source, you can only do that in lua, ignoring the default map generation tools.
  • if you need to override the equations for any autoplaced entity, tile, or decorative, you can do that with the `map_gen_settings.property_expression_names` on a per-surface basis.
I believe that should allow you to achieve your goal: you can tell the map generation system in C++ to use a different noise expression for the various properties found in the "autoplace specification" type for the resource via those per-surface overrides.

Does it?

how to apply those rules on a per-surface basis
Since you have to have lua code calling `game.create_surface` to make a new surface, you need to apply your logic to work out which type of surface -- planet -- the next one will be *before* you create it, and then apply the overrides from it when you call `game.create_surface`, and it should behave as you want.

Oh, and if you check the examples at the bottom of MapGenSettings in the API docs they include two concrete examples: one for changing the probability a tile is a specific type of grass, and one for making deep water always have a probability of -1,000, aka "never gonna place you", which show how to implement this exactly.


autoplace controls
An autoplace control is a way of telling the game engine to add a widget during the "new game" map generation setup page, before you hit "play", that lets the player adjust the values as documented in Types/AutoplaceSpecification#Controls in the wiki.

You can completely ignore them on new surfaces if you want to have player customizations (like resource frequency/richness) apply, or you can configure them in Lua for a planet using the `autoplace_controls` field in `map_gen_settings` -- that'll override the player choices, but of course, only for the surface using that specific set of `map_gen_settings`.

no richness_expression is set in the prototype for a resource, only a probability_expression
Per the wiki, if there is no richness_expression, probability_expression is used instead.

what are the default placement expressions?
https://github.com/wube/factorio-data/b ... s.lua#L274
https://github.com/wube/factorio-data/b ... .lua#L1078

Tile placement expressions are big. Shockingly huge, in fact. Those functions end up generating some wildly huge expressions.

Resource placement stuff is much more trivial.

anything else?
Are there any other properties of tile, entity (resource, rocks), or decorative placement you need to control, and which this doesn't explain how to adjust?
TOGoS
Former Staff
Former Staff
Posts: 97
Joined: Fri Jun 24, 2016 2:29 pm
Contact:

Re: map_gen_settings and autoplacers

Post by TOGoS »

slippycheeze wrote: ↑Wed Aug 21, 2019 3:25 pm Two of those have associated noise expressions, `probability_expression`, and `richness_expression`.
Those are the two fundamental noise equations that are used in placing resources by the C++ version of `on_chunk_generated`.

To override those two properties for a specific surface you can change the map_gen_settings for it as I showed before:

Code: Select all

map_gen_settings.property_expression_names["{tile|entity|decorative}:" .. prototype_name .. ":{probability|richness}"]
I just wanted to thank you for taking the time to respond to this thread, slippycheeze. You've nailed the explanations of how this stuff works, probably better than I could have.
slippycheeze
Filter Inserter
Filter Inserter
Posts: 587
Joined: Sun Jun 09, 2019 10:40 pm
Contact:

Re: map_gen_settings and autoplacers

Post by slippycheeze »

TOGoS wrote: ↑Fri Aug 23, 2019 2:26 pm
slippycheeze wrote: ↑Wed Aug 21, 2019 3:25 pm Two of those have associated noise expressions, `probability_expression`, and `richness_expression`.
Those are the two fundamental noise equations that are used in placing resources by the C++ version of `on_chunk_generated`.

To override those two properties for a specific surface you can change the map_gen_settings for it as I showed before:

Code: Select all

map_gen_settings.property_expression_names["{tile|entity|decorative}:" .. prototype_name .. ":{probability|richness}"]
I just wanted to thank you for taking the time to respond to this thread, slippycheeze. You've nailed the explanations of how this stuff works, probably better than I could have.
Thank you. A couple decades practice, I guess, have actually paid off. It can be hard sometimes, but I'm glad an early mentor advised me that communication was one of the most critical core skills for software developers and sysadmins. :)

Hopefully I got all the technical bits correct. Y'all are welcome to use anything I said to integrate into your documentation or whatever, with no obligation or anything, should you wish.
Post Reply

Return to β€œModding help”