193 lines
6.8 KiB
C#
193 lines
6.8 KiB
C#
/// Rohmer Maxime <maxluligames@gmail.com>
|
|
/// 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<TileType> 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<Tile> lowestEntropyTiles = new List<Tile>();
|
|
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<TileType> options = lowestEntropyTiles[tileIndex].PossibleTyles;
|
|
|
|
int optionCount = options.Count();
|
|
if (optionCount > 0)
|
|
{
|
|
int idx = rnd.Next(0, optionCount);
|
|
lowestEntropyTiles[tileIndex].PossibleTyles = new List<TileType> { 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<Tile> Neighbours = new List<Tile>();
|
|
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<TileType> typesToRemove = new List<TileType>();
|
|
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<TileType> types, List<ConsoleColor> 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");
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|