mxgmn / WaveFunctionCollapse

Bitmap & tilemap generation from a single example with the help of ideas from quantum mechanics
Other
23.05k stars 1.23k forks source link

Neighbor constraints do not always appear to be enforced #60

Closed PrettyFlower closed 3 years ago

PrettyFlower commented 4 years ago

Not sure if I'm just doing something wrong here but I tried running the algorithm today on a dummy tileset I made and got some results I wasn't expecting. I've uploaded a zip file with what I was using here: Base.zip

I modified samples.xml with this entry:

<simpletiled name="Base" width="3" height="3"/>

I also had to modify the for loop in Main.cs to let me run the algorithm 10,000 times as there seemed to be a lot of contradictions. One of the results I got looked like this: image

I don't understand how I got this though, as there are no neighbor constraints that include base_corner_1 on both the left and the right.

mxgmn commented 4 years ago

So you have 3 tiles essentially: center, corner, wall. My "Rooms" tileset contains these tiles (they're called empty, corner, side). Try making a subset of these 3 tiles (see how to make a subset in Knots/data.xml). Does it work?

PrettyFlower commented 4 years ago

The rules for the "Rooms" tileset didn't quite match what I was trying to do, as they're more permissive. I had to pare them down to this:

<set size="3">
    <tiles>
        <tile name="bend" symmetry="L" weight="0.5"/>
        <tile name="corner" symmetry="L" weight="0.5"/>
        <tile name="corridor" symmetry="I" weight="1.0"/>
        <tile name="door" symmetry="T" weight="0.5"/>
        <tile name="empty" symmetry="X"/>
        <tile name="side" symmetry="T" weight="2.0"/>
        <tile name="t" symmetry="T" weight="0.5"/>
        <tile name="turn" symmetry="L" weight="0.25"/>
        <tile name="wall" symmetry="X"/>
    </tiles>
    <neighbors>
        <neighbor left="corner" right="side 2"/>
        <neighbor left="empty" right="empty"/>
        <neighbor left="empty" right="side 3"/>
        <neighbor left="side" right="side"/>
    </neighbors>
    <subsets>
        <subset name="Subset">
            <tile name="empty"/>
            <tile name="corner"/>
            <tile name="side"/>
        </subset>
    </subsets>
</set>

I'm trying to just generate one big room, so corners/walls aren't allowed to be across from each other. I was still able to get that in the results though: image

mxgmn commented 4 years ago

I see. This happens because some tiles (side, corner) in your tileset don't have any allowed neighbors in some direction, and my propagation code assumes that in every direction any tile has >0 neighbors. A quick solution would be to return an error after line 196 if ST == 0. I'll implement a better solution when I have the time.

PrettyFlower commented 4 years ago

Hmm...interesting. Thanks for looking into this. As a workaround, I tried adding the wall tile back to the Rooms tileset and increasing the output size to 5x5 tiles, the idea being that the wall tiles can be placed along the outside edges and will satisfy the >0 neighbors constraint for sides, corners, and themselves. However I was still able to reproduce the issue. I did notice that returning an error after 196 if ST == 0 did produce an error, but I don't understand the code well enough to debug it.

toyboot4e commented 4 years ago

This happend in my overlapping model implementation where periodic input is not allowed. edit: so patterns on an edge may have no enabler in some direction

mxgmn commented 3 years ago

I added the quick fix.