|
|
|
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<Tile>();
|
|
|
|
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<Tile>();
|
|
|
|
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<int> Weights = new List<int>();
|
|
|
|
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<Tile> Yeat = new List<Tile>();
|
|
|
|
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<Tile> Possible;
|
|
|
|
public int TL, TR, BL, BR;
|
|
|
|
}
|
|
|
|
}
|