You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RatAttack2D/Assets/Scripts/RoomsGen.cs

423 lines
12 KiB

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;
}
}