diff --git a/WaveFunctionCollapseCLI/Program.cs b/WaveFunctionCollapseCLI/Program.cs index 882f89f..31d1609 100644 --- a/WaveFunctionCollapseCLI/Program.cs +++ b/WaveFunctionCollapseCLI/Program.cs @@ -43,16 +43,21 @@ namespace WaveFunctionCollapseCLI colors.Add(ConsoleColor.DarkGreen); //Little_Forest colors.Add(ConsoleColor.DarkGray); //Forest (Sorry I dont have tha many colors to work with) + int step = 1; + while (true) { Console.Clear(); Console.WriteLine("********** Welcome to WaveFunctionCollapse **********"); Console.WriteLine("Press any key to to to the next step"); + Console.WriteLine($"Step : {step}"); - map.NextStep(); + if (step > 1) + map.NextStep(); map.Display(avaibleTilesTypes,colors); Console.ReadKey(); + step++; } } } diff --git a/WaveFunctionCollapseCLI/Tile.cs b/WaveFunctionCollapseCLI/Tile.cs index af79fc4..de9866b 100644 --- a/WaveFunctionCollapseCLI/Tile.cs +++ b/WaveFunctionCollapseCLI/Tile.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace WaveFunctionCollapseCLI { - internal class Tile + internal class Tile:ICloneable,IEqualityComparer { private List _possibleTyles; private List _avaibleTypes; @@ -26,5 +26,25 @@ namespace WaveFunctionCollapseCLI PossibleTyles.Add(theType); } } + + public object Clone() + { + Tile copy = new Tile(this.AvaibleTypes); + copy.PossibleTyles.Clear(); + foreach (TileType pt in PossibleTyles) + { + copy.PossibleTyles.Add((TileType)pt.Clone()); + } + return copy; + } + + public bool Equals(Tile x, Tile y) + { + return x.PossibleTyles.Equals(y.PossibleTyles); + } + public int GetHashCode(Tile obj) + { + throw new NotImplementedException(); + } } } diff --git a/WaveFunctionCollapseCLI/TileMap.cs b/WaveFunctionCollapseCLI/TileMap.cs index 0aa439c..01efc8b 100644 --- a/WaveFunctionCollapseCLI/TileMap.cs +++ b/WaveFunctionCollapseCLI/TileMap.cs @@ -19,7 +19,7 @@ namespace WaveFunctionCollapseCLI public Size Dimensions { get => _dimensions; set => _dimensions = value; } internal Tile[,] Tiles { get => _tiles; set => _tiles = value; } - public TileMap(Size dimensions,List avaibleTypes) + public TileMap(Size dimensions, List avaibleTypes) { Dimensions = dimensions; @@ -35,9 +35,121 @@ namespace WaveFunctionCollapseCLI public void NextStep() { + Random rnd = new Random(); + List lowestEntropyTiles = new List(); + int lowestEntropy = -1; + + foreach (Tile t in Tiles) + { + int tileEntropy = t.PossibleTyles.Count; + + if (lowestEntropy == -1) + { + //checks if its the first tile + lowestEntropy = tileEntropy; + lowestEntropyTiles.Add(t); + } + else + { + if (lowestEntropy > tileEntropy) + { + lowestEntropy = tileEntropy; + lowestEntropyTiles.Clear(); + lowestEntropyTiles.Add(t); + } + else + { + if (lowestEntropy == tileEntropy) + { + lowestEntropyTiles.Add(t); + } + } + } + + //the list contains all the tyles that have exactly the same entropy + //now we can randomly select one and set one of the posssible types and set it, then we need to recursively change everything + + int tileCount = lowestEntropyTiles.Count; + + int tileIndex = rnd.Next(0, tileCount); + List options = lowestEntropyTiles[tileIndex].PossibleTyles; + + int optionCount = options.Count(); + if (optionCount > 0) + { + int idx = rnd.Next(0, optionCount); + lowestEntropyTiles[tileIndex].PossibleTyles = new List { options[idx] }; + } + + Wave(); + + } + } + private void Wave() + { + // we need to iterate trough the map to update every possibleTile every tile can have with the modified array + // each pass can mean more tile to refresh so we need to do it until a pass does not change the array + //for that we also need to deep copy it + + // Tiles and tiletypes have implemented clone + + Tile[,] oldTiles = new Tile[Dimensions.Width,Dimensions.Height]; + //while (!oldTiles.Equals(Tiles)) + { + oldTiles = (Tile[,])Tiles.Clone(); + for (int x = 0; x < Dimensions.Width; x++) + { + for (int y = 0; y < Dimensions.Height; y++) + { + CheckNeighbours(x, y); + } + } + } } - public void Display(List types,List colors) + private void CheckNeighbours(int x, int y) + { + //checks that the tile is not on a corner + List Neighbours = new List(); + Tile target = Tiles[x, y]; + if (x > 0 && x < Dimensions.Width - 1 && y > 0 && y < Dimensions.Height - 1) + { + Neighbours.Add(Tiles[x, y - 1]); //Top + Neighbours.Add(Tiles[x, y + 1]); //Bottom + Neighbours.Add(Tiles[x - 1, y]); //Left + Neighbours.Add(Tiles[x + 1, y]); //Right + } + else + { + //TODO + } + + List typesToRemove = new List(); + foreach (Tile t in Neighbours) + { + typesToRemove.Clear(); + foreach (TileType tyleType in t.PossibleTyles) + { + bool typePossible = false; + foreach (TileType targetTyleType in target.PossibleTyles) + { + if (!tyleType.IsCompatible(targetTyleType)) + { + typePossible = true; + } + } + if (!typePossible) + { + typesToRemove.Add(tyleType); + } + } + foreach (TileType toRmv in typesToRemove) + { + t.PossibleTyles.Remove(toRmv); + } + } + } + public void Display(List types, List colors) { Console.Write("\n"); char sprite = '#'; @@ -46,10 +158,23 @@ namespace WaveFunctionCollapseCLI for (int y = 0; y < Dimensions.Height; y++) { //we check if there only is one possibility - if (Tiles[x,y].PossibleTyles.Count < 2) + if (Tiles[x, y].PossibleTyles.Count < 2) { //Console.BackgroundColor = colors[types.IndexOf(new TileType(Tiles[x, y].PossibleTyles[0].Name))]; - Console.ForegroundColor = colors[types.IndexOf(new TileType(Tiles[x, y].PossibleTyles[0].Name))]; + //Console.ForegroundColor = colors[types.IndexOf(new TileType(Tiles[x, y].PossibleTyles[0].Name))]; + + int idxColor = 0; + for (int i = 0;i < types.Count;i++) + { + if (Tiles[x, y].PossibleTyles.Count > 0) + { + if (types[i].Name == Tiles[x, y].PossibleTyles[0].Name) + { + idxColor = i; + } + } + } + Console.ForegroundColor = colors[idxColor]; } else { diff --git a/WaveFunctionCollapseCLI/TileType.cs b/WaveFunctionCollapseCLI/TileType.cs index 2be8bfa..9159382 100644 --- a/WaveFunctionCollapseCLI/TileType.cs +++ b/WaveFunctionCollapseCLI/TileType.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace WaveFunctionCollapseCLI { - internal class TileType + internal class TileType: ICloneable,IEqualityComparer { //We only have one list but you may find code that have a different list for every side private List _compatibleTiles; @@ -31,5 +31,20 @@ namespace WaveFunctionCollapseCLI { return CompatibleTiles.Contains(tile); } + + public object Clone() + { + return new TileType(this.Name); + } + + public bool Equals(TileType x, TileType y) + { + return x.Name == y.Name; + } + + public int GetHashCode(TileType obj) + { + throw new NotImplementedException(); + } } }