-
-
Save dmillerw/4b06fad10ebfd42a5c38 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
public class DrunkenGenerator { | |
private System.Random rand; | |
// Map arrays | |
private bool[,] Map; | |
private bool[,] WouldSmooth; | |
// Map dimensions | |
public int MapX = 10; | |
public int MapY = 10; | |
// How many steps to take | |
public int Iterations = 100; | |
// Cave smoothing | |
public bool SmoothCaves = true; | |
// How many neighbors are required to fill the cell | |
public int SmoothingNeighborStart = 2; | |
// How many times should the map be passed over | |
public int SmoothPasses = 1; | |
// Corridor bias - If true will continue going in the same direction as the last step | |
public bool CorridorBias = true; | |
public int CorridorBiasProbability = 50; | |
public int CorridorIterationHold = 0; | |
// Center bias - If true will try and head for the center of the map | |
public bool CenterBias = false; | |
public int CenterBiasProbablility = 50; | |
public int CenterIterationHold = 0; | |
// Origin bias - If true will try and head back to the starting point | |
public bool OriginBias = false; | |
public int OriginBiasProbablility = 50; | |
public int OriginIterationHold = 0; | |
// Whether steps can go over already active cells - Note, if the active cell is completely enclosed, it will ignore this rule | |
public bool RetraceSteps = false; | |
// Internal flag to allow for the skipping of a retrace check - Used when the current position can't walk out by normal means | |
private bool SkipFlagNextWalk = false; | |
// Starting point | |
public int OriginX,OriginY = 0; | |
// Location of the current step | |
private int CurrX,CurrY = 0; | |
// Location of previous step | |
private int LastX,LastY = 0; | |
// Last direction headed (only used if corridor bias is enabled) | |
private int LastDirection = -1; | |
public DrunkenGenerator() { | |
rand = new System.Random(); | |
} | |
public void Build() { | |
Map = new bool[MapX, MapY]; | |
WouldSmooth = new bool[MapX, MapY]; | |
CurrX = OriginX; | |
CurrY = OriginY; | |
for (int i=0; i<Iterations; i++) { | |
// Sets the origin point to active, then begins walking | |
Map[CurrX,CurrY] = true; | |
Walk(i); | |
} | |
if (SmoothCaves) { | |
for (int i=0; i<SmoothPasses; i++) { | |
for (int x=0; x<MapX; x++) { | |
for (int y=0; y<MapY; y++) { | |
if (!Map[x, y] && NeighborCount(x, y) >= SmoothingNeighborStart) { | |
WouldSmooth[x, y] = true; | |
} | |
} | |
} | |
for (int x=0; x<MapX; x++) { | |
for (int y=0; y<MapY; y++) { | |
if (WouldSmooth[x, y]) { | |
Map[x, y] = true; | |
} | |
} | |
} | |
} | |
} | |
} | |
public bool GetCellState(int CellX, int CellY) { | |
if (!InMapBounds(CellX, CellY)) { | |
return false; | |
} else { | |
return Map[CellX, CellY]; | |
} | |
} | |
private bool InMapBounds() { | |
return InMapBounds(CurrX, CurrY); | |
} | |
private bool InMapBounds(int CellX, int CellY) { | |
return CellX >= 0 && CellX < MapX && CellY >= 0 && CellY < MapY; | |
} | |
private void Walk(int CurrentIteration) { | |
LastX = CurrX; | |
LastY = CurrY; | |
int Direction = rand.Next(0, 4); | |
if (CorridorBias && CorridorIterationHold <= CurrentIteration && rand.Next(0, 100) < CorridorBiasProbability) { | |
int Last = Direction; | |
if (LastDirection != -1) { | |
Direction = LastDirection; | |
} | |
LastDirection = Last; | |
} else if (CenterBias && CenterIterationHold <= CurrentIteration && rand.Next(0, 100) < CenterBiasProbablility) { | |
Direction = GetDirectionTowardsPoint((MapX / 2), (MapY / 2)); | |
} else if (OriginBias && OriginIterationHold <= CurrentIteration && rand.Next(0, 100) < OriginBiasProbablility) { | |
Direction = GetDirectionTowardsPoint(OriginX, OriginY); | |
} | |
switch(Direction) { | |
case 0: CurrY++; break; | |
case 1: CurrX++; break; | |
case 2: CurrY--; break; | |
case 3: CurrX--; break; | |
} | |
if (!InMapBounds()) { | |
CurrX = LastX; | |
CurrY = LastY; | |
Walk(CurrentIteration); | |
} else { | |
// If not allowed to retrace steps, and the current step would hit an active cell | |
if ((!RetraceSteps && Map[CurrX, CurrY]) && !SkipFlagNextWalk) { | |
// Get the neighbor count of the originating cell | |
int LastNeighborCount = NeighborCount(LastX, LastY); | |
// If neighbor count is less than 4, there's room for it to move, so manually walk to a free spot | |
if (LastNeighborCount < 4) { | |
if (InMapBounds(CurrX + 1, CurrY) && !Map[CurrX + 1, CurrY]) { | |
CurrX++; | |
} else if (InMapBounds(CurrX - 1, CurrY) && !Map[CurrX - 1, CurrY]) { | |
CurrX--; | |
} else if (InMapBounds(CurrX, CurrY + 1) && !Map[CurrX, CurrY + 1]) { | |
CurrY++; | |
} else if (InMapBounds(CurrX, CurrY - 1) && !Map[CurrX, CurrY - 1]) { | |
CurrY--; | |
} | |
} else { // Otherwise, the cell is completely enclosed and we set a flag to ignore the retrace steps flag for the next walk | |
SkipFlagNextWalk = true; | |
} | |
} | |
} | |
} | |
public int NeighborCount(int CellX, int CellY) { | |
int Count = 0; | |
for (int x=-1; x<=1; x++) { | |
for (int y=-1; y<=1; y++) { | |
if (x != 0 && y != 0) { | |
if (CellX + x >= 0 && CellX + x < MapX && CellY + y >= 0 && CellY + y < MapY) { | |
if (Map[CellX + x, CellY + y]) { | |
Count++; | |
} | |
} | |
} | |
} | |
} | |
return Count; | |
} | |
private int GetDirectionTowardsPoint(int DirX, int DirY) { | |
DirX -= CurrX; | |
DirY -= CurrY; | |
if (DirX > 0) { | |
DirX = 1; | |
} else if (DirX < 0) { | |
DirX = -1; | |
} else { | |
DirX = 0; | |
} | |
if (DirY > 0) { | |
DirY = 1; | |
} else if (DirY < 0) { | |
DirY = -1; | |
} else { | |
DirY = 0; | |
} | |
System.Random rand = new System.Random(); | |
if (rand.NextDouble() >= 0.5) { | |
return DirX == 1 ? 1 : 3; | |
} else { | |
return DirY == 1 ? 0 : 2; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment