Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] How to make a good sample? #6

Open
Supamiu opened this issue Nov 10, 2023 · 5 comments
Open

[Docs] How to make a good sample? #6

Supamiu opened this issue Nov 10, 2023 · 5 comments
Labels
documentation Improvements or additions to documentation

Comments

@Supamiu
Copy link
Contributor

Supamiu commented Nov 10, 2023

After using the addon I feel like I'm still struggling with the same thing: creating a proper sample.

Trying to imitate the one in the example scene will quickly hit limits, like when you have multiple types of ground tiles or you want to create different kind of biomes.

I feel like this might be a nice priority to have for the docs, feel free to close if that's not the case tho.

@AlexeyBond
Copy link
Owner

That's indeed a worth thing to document. We can start by collecting some of specific questions users have, so let's keep them in tis issue for now.

I will try to answer questions here and will collect them into a dedicated document later.


How add ground tiles?

When there is a single type of "ground" tiles (let's call it A), it's enough to have pattern like this in positive sample in order to define that the tile can repeated along both axes and fill any area:

AA
A

to add a second tile type B (and any other next) interchangable with A the following pattern will be enough:

 A
ABA
 A

The algorithm will be able to infer that combinations like

B  BB
B

are also valid - but only if complete_matrices flag in WFCRules2D is enabled (which is default). Otherwise you'll have to specify all possible combinations:

AA
ABB
 BA

When there are more interchangable cell types and complete_matrices is disabled, the pattern above should be repeated for every pair of interchangable tiles.


create different kind of biomes

I'm not sure, what does it mean, what you're trying to achieve in this case.

@Supamiu
Copy link
Contributor Author

Supamiu commented Nov 11, 2023

Thanks, I learned a lot with this answer 👍

By multiple kind of biomes, I mean more something like, being able to make it learn every possible transition but also the ones that cannot exist, alongside with making the solver learn that for instance, a grass patch must be at least X tiles by X tiles for consistency.

I've also been trying to create global rules (like no more than X times a given tile for instance) and I feel like having more explanations on how to implement a proper problem would be nice.

Extending WFC2DProblem is a good start I think and I started with this, but understanding which method will make you able to do what can be a bit hard and would be amazing with some docs on the topic.

@AlexeyBond
Copy link
Owner

learn every possible transition but also the ones that cannot exist

I don't quite get what this means, but seems like this may be related to how learns possible tile combinations.

The algorithm may learn some combinations that are not represented in the sample. For example, when there are cells A, B, X, Y, and the following combinations (let's consider only one dimension here): AX, BX, AX, the algorithm will alse decide that BY is an acceptable combination as well. It will decide so because both A and B can be placed left from X, so perhaps, they have the same pattern/connector on right side. It may be useful to think of tiles as jigsaw puzzle pieces - in this case A and B have the same shape on their right edge. And thus, since shape of A is compatible with both X and Y, shape of B should also be compatible with both of them if it is compatible with at least one of them.

However, sometimes, the algorithm may lern some combinations that aren't really valid or just don't look right aesthetically. In such cases, there are two possible ways to resolve this:

  • completely disable this behavior by disabling complete_matrices flag in rules. This way the algorithm will only learn combinations present in the sample, so it will require more manual work to build the sample.
  • disable some combinations using a negative sample. All combinations present in negative sample will be considered invalid, so be careful to not add some useful combinations there accidenally.

learn that for instance, a grass patch must be at least X tiles by X tiles for consistency

I'm afraid, that won't be possible with standard rules. When deciding, what tile can be placed in given cell, the solver looks only at limited number of other cells - by default it's neighbours along X and Y axes, but it can be changed using axes property of WFCRules2D.

Extending WFC2DProblem is a good start I think and I started with this, but understanding which method will make you able to do what can be a bit hard and would be amazing with some docs on the topic.

That's a complicated topic, and WFCProblem is currently missing some methods that coult make implementation of global constraints easier. I did leave some description of what's available now in #1.

Also I did leave a description of an alternative approach that may replace global constraints there - you can limit what tiles are placed in some cells before WFC starts. In fact, there is a more flexible version of that approach available in another branch, see WFC2DPrecondition. It allows user to define custom initial constraints in a more flexible way than strictly setting what tile should be placed at given coordinates. There is currently a dungeon generator that has customizable settings of what tiles are considered walls and roads. Generating different biomes may be another use case for preconditions - user may create few subsets of tiles for different biomes and precondition will use value of a noise texture to choose which biome each cell belongs to.

@Supamiu
Copy link
Contributor Author

Supamiu commented Nov 12, 2023

I feel like all this boils down to two issues (no offence, I'm trying to find good ways to help with the lib because I love it ^^):

  • DX is a bit lacking, this is mostly because the lib is a generic solver and not just a WFC solver, making it hard to follow for someone who's trying to just use it as a WFC solver and add their own constraints.
  • More examples would be amazing, for instance with a more complex tileset that's closer to what a real game would use (I was thinking something like https://freddypixelart.itch.io/top-down-adventure-pack and I'd be fine paying for a copy to use as example in the project).
    • Examples of what NOT to do would also be amazing (like this time in First attempt at making multi-layer solving work #4 where I had a tile that prevented multithreading for a reason that I'm not sure I understood, but that happened again on some tests I've made locally).

@AlexeyBond
Copy link
Owner

DX is a bit lacking, this is mostly because the lib is a generic solver and not just a WFC solver, making it hard to follow for someone who's trying to just use it as a WFC solver and add their own constraints

I'd say that the issue is rather lack of proper API/extension points for some kinds of modifications. The fact that the code is decomposed the way that solver does not depend on specific kind of problem shouldn't be an issue itself.

more complex tileset that's closer to what a real game would use (I was thinking something like https://freddypixelart.itch.io/top-down-adventure-pack and I'd be fine paying for a copy to use as example in the project)

Licence of that specific tile set does not allow redistribution. So if we use it in examples (examples are distributed along with the addon), everyone who wants to check them out will have to pay for their own copy of a tileset. This doesn't sound like a good idea to me 😆.

But that may be just a misinterpretation of the license. Anyway, I'd prefer to not mess with any proprietary assets. However, it totally makes sense to use a larger tileset - both to test and show how the addon works at larger scale and to test and show future feature with biome preconditions.

Examples of what NOT to do would also be amazing

Perhaps, a textual documentation will be enough for that. Since we're collecting Q&A here:


Why some rules stop the generator from using multiple threads or make it produce invalid results?

When deciding to use multithreading or not, the solver uses parameter of rule set named influence range. Influence range is the minimal distance from a cell at which change of it's domain (i.e. set of tiles that can be placed in a cell) never changes domains of other cells.

Example of influence range computation in 1-d case

Let's consider the following single-dimensional example:

  • the tile set contains tiles A, B and C
  • the following combinations are allowed: AA, AB, AC, BA, BB, BC, CA

To compute influence range, the algorithm will consider every tile:

  • A can be followed by any other tile - both AA, AB and AC are allowed. It's partial influence range is 1.
  • same goes for B - BA, BB, BC are allowed.
  • in case of C it can be followed by A only. But A then can be followed by any other tile: CAA, CAB, CAC. So partial influence range for C is 2.

Then the same is done for right-to-left direction 'cause result for some rule sets may be different in different directions. But in this example it's still 2. The final influence range for this rule set is also 2.

The generator uses approximated influence range value to decide how to split work among multiple threads: the lower the influence range is - the smaller chunks and the more threads will be efficiently used.

  • Influence range is infinite. Algorithm could detect it and disabled multithreading.
  • Algorithm couldn't correctly calculate influence range. Currently it uses an approximation of actual influence range that may be incorrect in some cases.
  • You could create a complicated set of rules for which the influence range logic is not applicable. This is even more likely to happen in case of modifications to WFC2DProblem. Unless you can simplify the rules, your best choice in this case is to just disable multithreading (by setting maximum threads number to 1).

Infinite influence range

A minimal example of a rule set with infinite influence range would be one with two tile types A and B and the following combinations allowed: AA, AB, BB. Tile B placed in any cell will influence all cells to the right 'cause rules don't allow to place anything except another B tile to the right from B tile.

Another example is set of rules that allows combinations AB and BA. With these rules, by putting, for example, tile A in an even cell, we decide that all even cells will contain A and all odd will contain B. Cases like this can be fixed by either allowing repeating tiles (AA or BB) or by adding third tile C and allowing it ti be placed between A and B (allowing AC and CB combinations).

A more trivial example is set of rules with combinations AB, BB allowed. Nothing can be placed to the left from A tile, so it always makes all cells to the left invalid. That is considered as infinite influence range as well. The same may happen with 2D rules defined by sample like

AB
BB

nothing can be placed on top or to the left from tile A. It may be fixed, for example, like this:

 B
BAB
 BB

When using WFC2DGenerator, such situation can be detected by enabling "Print rules" flag and running a generation. A message like

Influence range: (5, 6)
   At: res://addons/wfc/nodes/generator_2d.gd:126:start()

will be printed, along with full rule matrices. In cases when algorithm could detect infinite influence range, at least one of numbers will be 2147483647.

Undetectable infinite influence range

Current implementation can not detect influence of a tile if it is not propagated directly along one axis. For example let's consider a set of rules with floor tiles X, two road (or wall?) tiles and and the following sample map:

 XX
 ┐X
X└┐
XX 

With these rules, when or tile is placed at coordinates (x, y) there always will be the same tile in any cell with coordinates (x + a, y + a).

Best solution in situations like this would be to have dead-end tiles (e.g. and ). Allowing road to turn in different directions (, ) and move straight (, ) may also help to some extent.

@AlexeyBond AlexeyBond added the documentation Improvements or additions to documentation label Dec 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants