using System.Collections;
using System.Collections.Generic;
public static class VectorConstant
public static Vector3 East = new Vector3(1, 0, 0);
public static Vector3 West = new Vector3(-1, 0, 0);
public static Vector3 Up = new Vector3(0, 1, 0);
public static Vector3 Down = new Vector3(0, -1, 0);
public static Vector3 North = new Vector3(0, 0, 1);
public static Vector3 South = new Vector3(0, 0, -1);
public static Vector3[] Directions = {East, West, Up, Down, North, South};
public Random rand = new Random();
public void GenerationLoop(Level level)
HashSet<Vector3> jobSet = new HashSet<Vector3>(level.Data.Keys);
HashSet<Vector3> jobSetBuffer = new HashSet<Vector3>{};
foreach (Vector3 job in jobSet)
jobSetBuffer.UnionWith(Compare(level, job));
jobSet.UnionWith(jobSetBuffer);
jobSet.UnionWith(CollapseRandomSlot(level));
public Tile ForceCollapseWave(HashSet<Tile> wave)
foreach (Tile tile in wave)
float roll = (float)rand.NextDouble() * cumProb;
foreach (Tile tile in wave)
Console.Write("Collapse Error");
public HashSet<Vector3> Compare(Level level, Vector3 slot)
int count = level.Data[slot].Count;
HashSet<Vector3> resultSet = new HashSet<Vector3>();
foreach (Vector3 direction in VectorConstant.Directions)
if (level.Data.ContainsKey(slot + direction))
level.Data[slot].IntersectWith(GetPossibleSet(level.Data[slot + direction], direction));
if (count > level.Data[slot].Count)
foreach (Vector3 direction in VectorConstant.Directions)
if (level.Data.ContainsKey(slot + direction))
resultSet.Add(slot + direction);
public HashSet<Tile> GetPossibleSet(HashSet<Tile> wave, Vector3 direction)
HashSet<Tile> result = new HashSet<Tile>();
foreach (Tile tile in wave)
result.UnionWith(tile.GetNeighbour(direction));
public HashSet<Vector3> CollapseRandomSlot(Level level)
List<KeyValuePair<Vector3, HashSet<Tile>>> uncollapsedWaves = new List<KeyValuePair<Vector3, HashSet<Tile>>>();
foreach (var entry in level.Data)
if (entry.Value.Count > 1)
uncollapsedWaves.Add(entry);
if (uncollapsedWaves.Count == 0)
return new HashSet<Vector3>();
int index = rand.Next(uncollapsedWaves.Count);
HashSet<Tile> randomWave = uncollapsedWaves[index].Value;
randomWave.IntersectWith(new HashSet<Tile>{ForceCollapseWave(randomWave)});
HashSet<Vector3> resultSet = new HashSet<Vector3>();
foreach (Vector3 direction in VectorConstant.Directions)
if (level.Data.ContainsKey(uncollapsedWaves[index].Key + direction))
resultSet.Add(uncollapsedWaves[index].Key + direction);
public static void Main()
Propagator LevelGenerator = new Propagator();
TileBank bank = new TileBank();
bank.Data.Add(-8, new Tile(bank, -8, 1f, "0"));
bank.Data.Add(-7, new Tile(bank, -7, 1f, "0"));
bank.Data.Add(-6, new Tile(bank, -6, 1f, "0"));
bank.Data.Add(-5, new Tile(bank, -5, 1f, "0"));
bank.Data.Add(-4, new Tile(bank, -4, 1f, "0"));
bank.Data.Add(-3, new Tile(bank, -3, 1f, "0"));
bank.Data.Add(-2, new Tile(bank, -2, 1f, "0"));
bank.Data.Add(-1, new Tile(bank, -1, 1f, "0"));
bank.Data.Add(0, new Tile(bank, 0, 1f, " "));
bank.Data.Add(1, new Tile(bank, 1, 1f, "."));
bank.Data.Add(2, new Tile(bank, 2, 1f, ","));
bank.Data.Add(3, new Tile(bank, 3, 1f, ":"));
bank.Data.Add(4, new Tile(bank, 4, 1f, "^"));
bank.Data.Add(5, new Tile(bank, 5, 1f, ">"));
bank.Data.Add(6, new Tile(bank, 6, 1f, "="));
bank.Data.Add(7, new Tile(bank, 7, 1f, "+"));
bank.Data.Add(8, new Tile(bank, 8, 1f, "*"));
bank.Data.Add(9, new Tile(bank, 9, 1f, "&"));
bank.Data.Add(10, new Tile(bank, 10, 1f, "%"));
bank.Data.Add(11, new Tile(bank, 11, 1f, "$"));
bank.Data.Add(12, new Tile(bank, 12, 1f, "@"));
bank.Data.Add(13, new Tile(bank, 13, 1f, "#"));
bank.Data.Add(14, new Tile(bank, 14, 1f, "M"));
bank.Data.Add(15, new Tile(bank, 15, 1f, "W"));
Level level = new Level(bank);
LevelGenerator.GenerationLoop(level);
public Dictionary<Vector3, HashSet<Tile>> Data = new Dictionary<Vector3, HashSet<Tile>>();
public Propagator Propagator = new Propagator();
public Vector3 Size = new Vector3(64, 1, 64);
public Level(TileBank tileBank)
for (int i = 0; i < Size.X; i++)
for (int j = 0; j < Size.Y; j++)
for (int k = 0; k < Size.Z; k++)
Data.Add(new Vector3(i, j, k), new HashSet<Tile>(Bank.GetFullSet()));
for (int i = 0; i < Size.X; i++)
for (int k = 0; k < Size.Z; k++)
Tile[] options = new Tile[Data[new Vector3(i, 0, k)].Count];
if (Data[new Vector3(i, 0, k)].Count > 1)
Data[new Vector3(i, 0, k)].CopyTo(options);
else if (Data[new Vector3(i, 0, k)].Count == 1)
Data[new Vector3(i, 0, k)].CopyTo(options);
Console.Write(options[0].Draw);
public string Draw = "@";
public Tile(TileBank bank, int id, float prob, string draw)
public HashSet<Tile> GetNeighbour(Vector3 direction)
HashSet<Tile> result = new HashSet<Tile>();
for (int i = Id - 1; i < Id + 2; i++)
if (Bank.Data.ContainsKey(i))
result.Add(Bank.Data[i]);
public Dictionary<int, Tile> Data = new Dictionary<int, Tile>();
public HashSet<Tile> GetFullSet()
HashSet<Tile> result = new HashSet<Tile>();
foreach (var entry in Data)