- Home /
Question by
ridlr · Nov 16, 2020 at 09:31 PM ·
c#scripting problemerror
Infinite While Loop
So I'm trying to create a Wave Function Collapse algorithm for my project (2D dungeon crawler) and I keep getting stuck in an infinite while loop. "uncollapsedTiles.Count" somehow remains at the value 2303 throughout the highest level while loop: while (uncollapsedTiles.Count) > 0. I know it's long and a bit confusing but I would really appreciate any help I can get...
class OverlappingModel
{
public Color[,] output;
public OverlappingModel(Texture2D input, int n, int symmetry, bool periodicInput, bool periodicOutput, int outputWidth, int outputHeight)
{
int inputWidth = input.width;
int inputHeight = input.height;
List<Color[,]> tiles = new List<Color[,]>();
int maxInputX = periodicInput ? inputWidth : inputWidth - n + 1;
int maxInputY = periodicInput ? inputHeight : inputHeight - n + 1;
for (int cornerX = 0; cornerX < maxInputX; cornerX++)
{
for (int cornerY = 0; cornerY < maxInputY; cornerY++)
{
Color[,] pixels = new Color[n, n];
for (int x = cornerX; x < cornerX + n; x++)
{
for (int y = cornerY; y < cornerY + n; y++)
{
pixels[x - cornerX, y - cornerY] = input.GetPixel(x >= inputWidth ? x - inputWidth: x, y >= inputHeight ? y - inputHeight : y);
}
}
tiles.Add(pixels);
if (symmetry >= 2) tiles.Add(RotatedTile(pixels, 90));
if (symmetry >= 3) tiles.Add(RotatedTile(pixels, 180));
if (symmetry >= 4) tiles.Add(RotatedTile(pixels, 270));
if (symmetry >= 5) tiles.Add(ReflectedTile(pixels, Reflection.Horizontal));
if (symmetry >= 6) tiles.Add(ReflectedTile(pixels, Reflection.Vertical));
if (symmetry >= 7) tiles.Add(ReflectedTile(pixels, Reflection.PositiveSlant));
if (symmetry == 8) tiles.Add(ReflectedTile(pixels, Reflection.NegativeSlant));
}
}
int maxOutputX = periodicInput ? outputWidth : outputWidth - n + 1;
int maxOutputY = periodicInput ? outputHeight : outputHeight - n + 1;
output = new Color[outputWidth, outputHeight];
List<Color[,]>[,] superpositions = new List<Color[,]>[maxOutputX, maxOutputY];
for (int x = 0; x < maxOutputX; x++)
{
for (int y = 0; y < maxOutputY; y++)
{
superpositions[x, y] = tiles;
}
}
List<Vector2Int> uncollapsedTiles = new List<Vector2Int>();
for (int x = 0; x < maxOutputX; x++)
{
for (int y = 0; y < maxOutputY; y++)
{
uncollapsedTiles.Add(new Vector2Int(x, y));
}
}
int currentX = UnityEngine.Random.Range(0, maxOutputX);
int currentY = UnityEngine.Random.Range(0, maxOutputY);
List<Color[,]> randomFirstTile = new List<Color[,]>();
randomFirstTile.Add(tiles[UnityEngine.Random.Range(0, tiles.Count)]);
superpositions[currentX, currentY] = randomFirstTile;
uncollapsedTiles.Remove(new Vector2Int(currentX, currentY));
for (int x = currentX; x < currentX + n; x++)
{
for (int y = currentY; y < currentY + n; y++)
{
output[WrappedInt(x, 0, outputWidth), WrappedInt(y, 0, outputHeight)] = superpositions[currentX, currentY][0][x - currentX, y - currentY];
}
}
FileIO.WriteStringToFile("debug.txt", "Running WFC Algorithm", true);
while (uncollapsedTiles.Count > 0)
{
FileIO.WriteStringToFile("debug.txt", "Uncollapsed tiles: " + uncollapsedTiles.Count, true);
for (int cornerX = currentX - 2; cornerX < currentX + 2; cornerX++)
{
for (int cornerY = currentY - 2; cornerY < currentY + 2; cornerY++)
{
if ((!periodicOutput && WithinOutput(cornerX, cornerY)) || periodicOutput)
{
int realCornerX = WrappedInt(cornerX, 0, outputWidth);
int realCornerY = WrappedInt(cornerY, 0, outputHeight);
for (int i = 0; i < superpositions[realCornerX, realCornerY].Count; i++)
{
bool illegalTile = false;
for (int x = cornerX; x < cornerX + n; x++)
{
for (int y = cornerY; y < cornerY + n; y++)
{
Color outputPixel = output[WrappedInt(x, 0, outputWidth), WrappedInt(y, 0, outputHeight)];
if (!(superpositions[realCornerX, realCornerY][i][x - cornerX, y - cornerY] == outputPixel || outputPixel == null))
{
superpositions[realCornerX, realCornerY].RemoveAt(i);
i--;
illegalTile = true;
break;
}
}
if (illegalTile) break;
}
}
}
}
}
Vector2Int randomTile = uncollapsedTiles[UnityEngine.Random.Range(0, uncollapsedTiles.Count)];
List<Color[,]> lowestEntropyTile = superpositions[randomTile.x, randomTile.y];
currentX = randomTile.x;
currentY = randomTile.y;
for (int i = 0; i < uncollapsedTiles.Count; i++)
{
if (superpositions[uncollapsedTiles[i].x, uncollapsedTiles[i].y].Count < lowestEntropyTile.Count)
{
lowestEntropyTile = superpositions[uncollapsedTiles[i].x, uncollapsedTiles[i].y];
currentX = uncollapsedTiles[i].x;
currentY = uncollapsedTiles[i].y;
}
}
List<Color[,]> currentTile = new List<Color[,]>();
currentTile.Add(lowestEntropyTile[UnityEngine.Random.Range(0, lowestEntropyTile.Count)]);
superpositions[currentX, currentY] = currentTile;
uncollapsedTiles.Remove(new Vector2Int(currentX, currentY));
for (int x = currentX; x < currentX + n; x++)
{
for (int y = currentY; y < currentY + n; y++)
{
output[WrappedInt(x, 0, outputWidth), WrappedInt(y, 0, outputHeight)] = superpositions[currentX, currentY][0][x - currentX, y - currentY];
}
}
}
int WrappedInt(int num, int min, int max)
{
int wrapped = num;
while (wrapped < min)
{
wrapped += max - min;
}
while (wrapped >= max)
{
wrapped -= max - min;
}
return wrapped;
}
Color[,] RotatedTile(Color[,] tile, int degrees)
{
Color[,] oldTile = tile;
Color[,] newTile = new Color[n, n];
for (int rotations = 0; rotations < degrees / 90; rotations++)
{
for (int x = 0; x < n; x++)
{
for (int y = 0; y < n; y++)
{
newTile[x, y] = tile[n - y - 1, x];
}
}
oldTile = newTile;
}
return newTile;
}
Color[,] ReflectedTile(Color[,] tile, Reflection reflection)
{
Color[,] newTile = new Color[n, n];
for (int x = 0; x < n; x++)
{
for (int y = 0; y < n; y++)
{
if (reflection == Reflection.Horizontal)
{
newTile[x, y] = tile[n - x - 1, y];
}
else if (reflection == Reflection.Vertical)
{
newTile[x, y] = tile[x, n - y - 1];
}
else if (reflection == Reflection.PositiveSlant)
{
newTile[x, y] = tile[n - x - 1, n - y - 1];
}
else if (reflection == Reflection.NegativeSlant)
{
newTile[x, y] = tile[n - y - 1, n - x - 1];
}
}
}
return newTile;
}
bool WithinOutput(int x, int y)
{
return x >= 0 && x < maxOutputX && y >= 0 && y < maxOutputY;
}
}
}
Comment
Your answer
Follow this Question
Related Questions
UnityIAP? Assembly [...] will not be loaded due to errors: 0 Answers
Distribute terrain in zones 3 Answers
No Monobehaviour scripts in files 1 Answer