using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Tilemaps; using System.Threading; public class RoomsGen : MonoBehaviour { private Vector2Int size; private Wave[,] Waves; private Vector2Int lowest; private System.Random ran; private Thread genthread; private bool Print; private bool running; public Tilemap Map; public Tile[] Tiles; [SerializeField][ReadOnly] private float Entropy; void OnDisable() { genthread.Interrupt(); genthread.Abort(); } private void FixedUpdate() { if (Print) { Print = false; Map.ClearAllTiles(); for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { try { Map.SetTile(new Vector3Int(x, y, 0), Waves[x, y].Possible[0].tile); } catch{} } } } } public void makeRoom() { if (running) { return; } running = true; genthread = new Thread(new ThreadStart(inmakeRoom)); genthread.Start(); } private void inmakeRoom() { ran = new System.Random(); size = new Vector2Int(ran.Next(10, 30), ran.Next(7, 15)); Waves = new Wave[size.x, size.y]; for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { Waves[x, y].Possible = new List(); Waves[x, y].Possible.AddRange(Tiles); Waves[x, y].TL = -1; Waves[x, y].TR = -1; Waves[x, y].BL = -1; Waves[x, y].BR = -1; if (y == 0 || y == size.y - 1 || x == 0 || x == size.x - 1) { Waves[x, y].Possible = new List(); Waves[x, y].Possible.Add(Tiles[0]); Waves[x, y].TL = 1; Waves[x, y].TR = 1; Waves[x, y].BL = 1; Waves[x, y].BR = 1; } } } int runs = 0; while (true) { runs++; Debug.Log("Runs: " + runs); CalcEntropy(); if (Select()) { break; } Wave[,] Temp = Waves; Observe(); for (int i = 0; i < 100; i++) { if (!Propagate()) { break; } } if(PathCheck()) { Waves = Temp; } } running = false; Print = true; } public void CalcEntropy() { for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { float weight = 0; if (Waves[x, y].Possible.Count <= 1) { Waves[x, y].Entropy = 0; continue; } foreach (var we in Waves[x, y].Possible) { weight += we.weight; } Waves[x, y].Entropy = weight; } } } public bool Select() { bool Sel = false; int tries = 0; while (true) { tries++; lowest = new Vector2Int(ran.Next(0, size.x), ran.Next(0, size.y)); if (Waves[lowest.x, lowest.y].Entropy != 0) { break; } if (tries >= 2000) { tries = 0; float entropy = 0; for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { entropy += Waves[x, y].Entropy; } } if (entropy == 0) { break; } } } float entroexit = 0; for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { if (Waves[x, y].Entropy < Waves[lowest.x, lowest.y].Entropy && Waves[x, y].Entropy != 0) { lowest = new Vector2Int(x, y); } entroexit += Waves[x, y].Entropy; } } Entropy = entroexit; if (entroexit == 0) { Sel = true; } return Sel; } public void Observe() { List Weights = new List(); int maxweight = 0; foreach (var item in Waves[lowest.x, lowest.y].Possible) { Weights.Add(item.weight); maxweight += item.weight; } Weights.Sort(); double selected = Math.Pow(Math.Floor(ran.NextDouble() * 10), 2) / maxweight; for (int i = 0; i < Weights.Count; i++) { selected -= Weights[i]; if (selected < 0) { selected = i; break; } } selected = Math.Clamp(selected, 0, Weights.Count-1); for (int i = 0; i < Waves[lowest.x, lowest.y].Possible.Count; i++) { Debug.Log(Waves[lowest.x, lowest.y].Possible[i].weight); Debug.Log("AAAA: " + Weights[(int)selected]); if(Waves[lowest.x, lowest.y].Possible[i].weight == Weights[(int)selected]) { selected = i; break; } } Waves[lowest.x, lowest.y].Entropy = 0; Tile temp = Waves[lowest.x, lowest.y].Possible[(int)selected]; Waves[lowest.x, lowest.y].Possible.Clear(); Waves[lowest.x, lowest.y].Possible.Add(temp); Waves[lowest.x, lowest.y].TL = ToInt(temp.TL); Waves[lowest.x, lowest.y].TR = ToInt(temp.TR); Waves[lowest.x, lowest.y].BL = ToInt(temp.BL); Waves[lowest.x, lowest.y].BR = ToInt(temp.BR); } public bool Propagate() { bool edited = false; for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { if (x - 1 >= 0) { check(new Vector2Int(x, y), new Vector2Int(x - 1, y)); if (y - 1 >= 0) { check(new Vector2Int(x, y), new Vector2Int(x - 1, y - 1)); } if (y + 1 < size.y) { check(new Vector2Int(x, y), new Vector2Int(x - 1, y + 1)); } } if (y - 1 >= 0) { check(new Vector2Int(x, y), new Vector2Int(x, y - 1)); if (x + 1 < size.x) { check(new Vector2Int(x, y), new Vector2Int(x + 1, y - 1)); } } if (x + 1 < size.x) { check(new Vector2Int(x, y), new Vector2Int(x + 1, y)); } if (y + 1 < size.y) { check(new Vector2Int(x, y), new Vector2Int(x, y + 1)); if (x + 1 < size.x) { check(new Vector2Int(x, y), new Vector2Int(x + 1, y + 1)); } } if (!edited) { try { edited = Clean(new Vector2Int(x, y)); } catch { } } else { try { Clean(new Vector2Int(x, y)); } catch { } } } } return edited; } public void check(Vector2Int Current, Vector2Int Check) { Vector2Int normal = Check - Current; if (normal.x == 0) { if (normal.y == -1) { if (Waves[Check.x, Check.y].TL != -1) { Waves[Current.x, Current.y].BL = Waves[Check.x, Check.y].TL; } if (Waves[Check.x, Check.y].TR != -1) { Waves[Current.x, Current.y].BR = Waves[Check.x, Check.y].TR; } } else if (normal.y == 1) { if (Waves[Check.x, Check.y].BL != -1) { Waves[Current.x, Current.y].TL = Waves[Check.x, Check.y].BL; } if (Waves[Check.x, Check.y].BR != -1) { Waves[Current.x, Current.y].TR = Waves[Check.x, Check.y].BR; } } } else if (normal.y == 0) { if (normal.x == -1) { if (Waves[Check.x, Check.y].TR != -1) { Waves[Current.x, Current.y].TL = Waves[Check.x, Check.y].TR; } if (Waves[Check.x, Check.y].BR != -1) { Waves[Current.x, Current.y].BL = Waves[Check.x, Check.y].BR; } } else if (normal.x == 1) { if (Waves[Check.x, Check.y].TL != -1) { Waves[Current.x, Current.y].TR = Waves[Check.x, Check.y].TL; } if (Waves[Check.x, Check.y].BL != -1) { Waves[Current.x, Current.y].BR = Waves[Check.x, Check.y].BL; } } } else { if (normal.y == 1 && normal.x == -1) { if (Waves[Check.x, Check.y].BR != -1) { Waves[Current.x, Current.y].TL = Waves[Check.x, Check.y].BR; } } if (normal.y == 1 && normal.x == 1) { if (Waves[Check.x, Check.y].BL != -1) { Waves[Current.x, Current.y].TR = Waves[Check.x, Check.y].BL; } } if (normal.y == -1 && normal.x == -1) { if (Waves[Check.x, Check.y].TR != -1) { Waves[Current.x, Current.y].BL = Waves[Check.x, Check.y].TR; } } if (normal.y == -1 && normal.x == 1) { if (Waves[Check.x, Check.y].TL != -1) { Waves[Current.x, Current.y].BR = Waves[Check.x, Check.y].TL; } } } } public bool Clean(Vector2Int Current) { List Yeat = new List(); foreach (var item in Waves[Current.x, Current.y].Possible) { if (ToInt(item.BL) != Waves[Current.x, Current.y].BL && Waves[Current.x, Current.y].BL != -1) { Yeat.Add(item); continue; } if (ToInt(item.BR) != Waves[Current.x, Current.y].BR && Waves[Current.x, Current.y].BR != -1) { Yeat.Add(item); continue; } if (ToInt(item.TL) != Waves[Current.x, Current.y].TL && Waves[Current.x, Current.y].TL != -1) { Yeat.Add(item); continue; } if (ToInt(item.TR) != Waves[Current.x, Current.y].TR && Waves[Current.x, Current.y].TR != -1) { Yeat.Add(item); continue; } } bool e = false; foreach (var item in Yeat) { Waves[Current.x, Current.y].Possible.Remove(item); e = true; } if (Waves[Current.x, Current.y].Possible.Count <= 1) { Waves[Current.x, Current.y].Entropy = 0; } return e; } public bool PathCheck() { return false; } public int ToInt(bool In) { if (In) { return 1; } return 0; } [System.Serializable] public struct Tile { public TileBase tile; public int weight; public bool TL, TR, BL, BR; } public struct Wave { public float Entropy; public List Possible; public int TL, TR, BL, BR; } }