/// Rohmer Maxime /// 28 April 2022 /// TileMap.cs using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WaveFunctionCollapseCLI { // The TileMap will contain all the WaveFunctionColllapse internal class TileMap { private Size _dimensions; private Tile[,] _tiles; public Size Dimensions { get => _dimensions; set => _dimensions = value; } internal Tile[,] Tiles { get => _tiles; set => _tiles = value; } public TileMap(Size dimensions, List avaibleTypes) { Dimensions = dimensions; Tiles = new Tile[Dimensions.Width, Dimensions.Height]; for (int x = 0; x < Dimensions.Width; x++) { for (int y = 0; y < Dimensions.Height; y++) { Tiles[x, y] = new Tile(avaibleTypes); } } } 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); } } } } 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 = '#'; for (int x = 0; x < Dimensions.Width; x++) { for (int y = 0; y < Dimensions.Height; y++) { //we check if there only is one possibility 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))]; 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 { //this means that we need other steps to determinate wich Tile to use //Console.BackgroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray; } Console.Write(sprite); } Console.Write("\n"); } } } }