AlexeyBond / godot-constraint-solving

WFC (Wave Function Collapse) and generic constraint satisfaction problem solver implementation for Godot 4
https://godotengine.org/asset-library/asset/1951
MIT License
332 stars 14 forks source link

How to run precondition dungeon alone? #22

Closed Golden-kitty closed 3 weeks ago

Golden-kitty commented 1 month ago

During trying to generate my frist complex dungeon, I found myself having the need to use few precondition generation steps to create a guide map which consist different kinds of guide tiles, in order to prepare for subsequnental WFC generation on corresponding zone (erase and only earse one group of them first then use the WFC generation to fill the area, then move on to the next one) . However, there is no WFCrule2DNull like what precondition settings have. I tried disable runners/solver alone or create one to stop WFC generation, but failed. Is there any chance we could have a precondition-only nodes or a bool attribute that controls whether WFC should work?

AlexeyBond commented 1 month ago

Hi.

I'd like to help you but I couldn't get what you are trying to do. Can you explain in more details, maybe with some illustrations?

Golden-kitty commented 1 month ago

Sorry for the confusion I bring to you, I'll try to explain it more clearly.

In brief, i just want a bool attribute to toggle wfc generation process so i could running predungeon alone.

Here are the verbose version:

Since wfc always doing better in filling zones rather than constract them, any type of predungeon generation method would be a good partner for wfc who could take care of those preparation steps;

However,I found single run of predungeon is far short for real biome predungeon: it requires multiple preconstruct process with each have different attributes martix to complete different objective (like generate main road , spawn rooms , link them with few smaller alleys...), and thats when i felt lost control on this plugin cuz I cant customize it myself to met this requirement.

Here is current process of this plugin: 1: predungeon (with rooms and walkways) UYJ6F~WRM`DP6)NK`NE6C9E 2: wfc generation LCATR(NX38H5H$C3@5F 9C1

Here is my ideal process: 1: predungeon (roads) { 22YV_8YL PMN4Z_$P7R~F 2: predungeon (rooms) BYI YV`Z0T_2 8I@$~10`M 3: predungeon (alleys) @G_TIS@A47PJK1U`8QX$YNG 4: predungeon (zones) SXY@KJS HFW2IT4W6YN8_99 (before here, no wfc generation get involved yet) 5: wfc generation (multiple times or once for all) @8130_0%S{2KQ)TTQ2YUKAY

The mayjor obstacle prevented me from moving to new workflow is i cant use this plugin's predungeon function alone, without get wfc generation contaminat the preconstruct tilemap.

I've tried defining empty 2D rules, empty mappers, or using bool directly to skip all the WFC stages, but I can't sort out the state markup logic and assertion checking in the plugin, so I have to ask for your help.

AlexeyBond commented 1 month ago

I'm not sure, but it seems like you may have a bit of misunderstanding of how do preconditions work (sorry if I'm wrong). The preconditions do not modify the map. Instead, they decide what tiles can be placed in each cell of the map - one, multiple or all tiles may be allowed in each cell. read_domain method of WFC2DPrecondition returns a set of tiles allowed in specific cell.

If all you want is to fix tiles in some cells, you may write them to the map before starting WFC generator and use a WFC2DPreconditionReadExistingSettings precondition (which is default) - it will force the generator to keep the existing tiles unchanged and only place some tiles in empty cells.

But if you want WFC to choose from multiple (but not all) options for some cells, then the beheavior you need can be achieved by creating a custom procondition that will run steps 1 to 4, without any interactions with the map. It, most likely, should use some sort of internal representation for tile types (e.g. "a road in forest biome", "a wall in desert biome" e.t.c.) and then map it to WFC representation. That's how dungeon generator works - it uses 3 internal tile types (passable, wall, free) stored in an array and returns one of tile sets - set of passable tiles, set of wall tiles, set of all tiles (null means any tile is allowed) - in read_domain.

That's how preconditions are intended to be used.

However, it may not work if you want to generate separate parts of the map incrementally - the WFC2DGenerator will create new instance of precondition every time. And that's why you may actually want to run the procondition differently from how it's done by default. This can be worked around by either caching WFC2DPrecondition instance in precondition settings instance or by creating a WFC2DGenerator subclass and overriding _create_precondition method. It also may be a cleaner approach to create a custom node type instead of WFC2DGenerator to support your workflow. WFC2DGenerator is a very generic high-level facade for underlying components that fits multiple most possible use-cases, a very specific script may be much more simple.