Refactor maze scripts: namespaces & cleanup

Move Maze-related scripts into the Hallucinate.GameSetup.Maze namespace and perform a broad refactor and cleanup. Make MapLocation a readonly struct, add Corridor/Wall/Path constants, and convert Maze into a clearer base class with serialized fields (width, depth, scale, mapParentObject), proper initialization, virtual Generate, and safer DrawMap behavior. Update neighbor-count helpers, tighten method visibility, and improve algorithm implementations (Crawler, Prims, Recursive, Wilsons) to use the new constants and more robust logic (including logging and loop guards). Add a Fisher–Yates Shuffle extension with a static RNG under Hallucinate.GameSetup.Maze.Extensions. Also update IDE metadata (.idea encodings.xml and workspace.xml) to record file encodings and some project settings.
This commit is contained in:
2026-04-21 21:44:26 +07:00
parent d2e3dbf653
commit 3a687a4d58
8 changed files with 460 additions and 286 deletions

View File

@@ -1,4 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise">
<file url="file://$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Crawler.cs" charset="ISO-8859-1" />
<file url="file://$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Extensions.cs" charset="ISO-8859-1" />
<file url="file://$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Wilsons.cs" charset="ISO-8859-1" />
</component>
</project>

View File

@@ -4,14 +4,23 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="f9183c68-daf0-43b8-be4c-fad79983f91b" name="Changes" comment="" />
<list default="true" id="f9183c68-daf0-43b8-be4c-fad79983f91b" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/.idea.HALLUCINATE/.idea/encodings.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.HALLUCINATE/.idea/encodings.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.HALLUCINATE/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.HALLUCINATE/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Crawler.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Crawler.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Extensions.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Extensions.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Maze.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Maze.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Prims.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Prims.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Recursive.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Recursive.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Wilsons.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/GameSetup/Maze/Wilsons.cs" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="EmbeddingIndexingInfo">
<option name="cachedIndexableFilesCount" value="10" />
<option name="cachedIndexableFilesCount" value="34" />
<option name="fileBasedEmbeddingIndicesEnabled" value="true" />
</component>
<component name="Git.Settings">
@@ -26,6 +35,7 @@
<commands />
<urls />
</component>
<component name="MetaFilesCheckinStateConfiguration" checkMetaFiles="true" />
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 4
}</component>
@@ -34,27 +44,27 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"ModuleVcsDetector.initialDetectionPerformed": "true",
"RunOnceActivity.MCP Project settings loaded": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
"RunOnceActivity.git.unshallow": "true",
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
"com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1": "true",
"git-widget-placeholder": "main",
"junie.onboarding.icon.badge.shown": "true",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "preferences.pluginManager",
"to.speed.mode.migration.done": "true",
"vue.rearranger.settings.migration": "true"
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;ModuleVcsDetector.initialDetectionPerformed&quot;: &quot;true&quot;,
&quot;RunOnceActivity.MCP Project settings loaded&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252&quot;: &quot;true&quot;,
&quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
&quot;RunOnceActivity.typescript.service.memoryLimit.init&quot;: &quot;true&quot;,
&quot;com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;main&quot;,
&quot;junie.onboarding.icon.badge.shown&quot;: &quot;true&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot;,
&quot;to.speed.mode.migration.done&quot;: &quot;true&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}]]></component>
}</component>
<component name="RunManager" selected="Attach to Unity Editor.Attach to Unity Editor">
<configuration name="Standalone Player" type="RunUnityExe" factoryName="Unity Executable">
<option name="EXE_PATH" value="$PROJECT_DIR$/../BAI MUTIPLAY\HALLUCINATE.exe" />
@@ -127,12 +137,14 @@
<workItem from="1775313757656" duration="8722000" />
<workItem from="1776130728673" duration="7161000" />
<workItem from="1776255558934" duration="1896000" />
<workItem from="1776780627914" duration="1908000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="UnityCheckinConfiguration" checkUnsavedScenes="true" />
<component name="UnityProjectConfiguration" hasMinimizedUI="true" />
<component name="UnityProjectDiscoverer">
<option name="hasUnityReference" value="true" />

View File

@@ -1,51 +1,70 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Crawler : Maze
namespace Hallucinate.GameSetup.Maze
{
public override void Generate()
/// <summary>
/// A maze generation algorithm that "crawls" through the grid in a semi-random walk.
/// It creates long, winding corridors by moving vertically or horizontally.
/// </summary>
public class Crawler : Maze
{
//for (int i = 0; i < 2; i++)
// CrawlV();
//for(int i = 0; i < 3; i++)
// CrawlH();
}
void CrawlV()
{
bool done = false;
int x = Random.Range(1,width-1);
int z = 1;
while (!done)
/// <summary>
/// Orchestrates the crawling generation.
/// (Currently empty as per original procedural logic).
/// </summary>
public override void Generate()
{
map[x, z] = 0;
if (Random.Range(0, 100) < 50)
x += Random.Range(-1, 2);
else
z += Random.Range(0, 2);
done |= (x < 1 || x >= width-1 || z < 1 || z >= depth-1);
// Implementation can be expanded as needed.
}
/// <summary>
/// Performs a vertical crawl starting from a random X position at the bottom.
/// </summary>
protected void CrawlV()
{
bool done = false;
int x = Random.Range(1, width - 1);
int z = 1;
while (!done)
{
map[x, z] = Corridor;
if (Random.Range(0, 100) < 50)
{
x += Random.Range(-1, 2);
}
else
{
z += Random.Range(0, 2);
}
done |= (x < 1 || x >= width - 1 || z < 1 || z >= depth - 1);
}
}
/// <summary>
/// Performs a horizontal crawl starting from a random Z position at the left.
/// </summary>
protected void CrawlH()
{
bool done = false;
int x = 1;
int z = Random.Range(1, depth - 1);
while (!done)
{
map[x, z] = Corridor;
if (Random.Range(0, 100) < 50)
{
x += Random.Range(0, 2);
}
else
{
z += Random.Range(-1, 2);
}
done |= (x < 1 || x >= width - 1 || z < 1 || z >= depth - 1);
}
}
}
void CrawlH()
{
bool done = false;
int x = 1;
int z = Random.Range(1,depth-1);
while (!done)
{
map[x, z] = 0;
if (Random.Range(0, 100) < 50)
x += Random.Range(0, 2);
else
z += Random.Range(-1, 2);
done |= (x < 1 || x >= width-1 || z < 1 || z >= depth-1);
}
}
}

View File

@@ -1,21 +1,31 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class Extensions
namespace Hallucinate.GameSetup.Maze.Extensions
{
private static System.Random rng = new System.Random();
public static void Shuffle<T>(this IList<T> list)
/// <summary>
/// Provides utility extension methods for maze generation algorithms.
/// </summary>
public static class Extensions
{
int n = list.Count;
while (n > 1)
private static System.Random _rng = new System.Random();
/// <summary>
/// Shuffles the elements of an <see cref="IList{T}"/> using the Fisher-Yates algorithm.
/// This is used to randomize directions for maze generation.
/// </summary>
/// <typeparam name="T">The type of elements in the list.</typeparam>
/// <param name="list">The list to shuffle.</param>
public static void Shuffle<T>(this IList<T> list)
{
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
int n = list.Count;
while (n > 1)
{
n--;
int k = _rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}
}

View File

@@ -1,100 +1,178 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MapLocation
namespace Hallucinate.GameSetup.Maze
{
public int x;
public int z;
public MapLocation(int _x, int _z)
/// <summary>
/// Represents a 2D coordinate on the maze grid.
/// Used as a lightweight value type to avoid GC allocations.
/// </summary>
public readonly struct MapLocation
{
x = _x;
z = _z;
}
}
public readonly int x;
public readonly int z;
public class Maze : MonoBehaviour
{
public List<MapLocation> directions = new List<MapLocation>() {
new MapLocation(1,0),
new MapLocation(0,1),
new MapLocation(-1,0),
new MapLocation(0,-1) };
public int width = 30; //x length
public int depth = 30; //z length
public byte[,] map;
public int scale = 6;
public Transform _mapParentObjet;
// Start is called before the first frame update
void Start()
{
InitialiseMap();
Generate();
DrawMap();
public MapLocation(int _x, int _z)
{
x = _x;
z = _z;
}
}
void InitialiseMap()
/// <summary>
/// The base class for maze generation.
/// Handles map initialization, basic neighbor counting logic, and debug rendering.
/// </summary>
public class Maze : MonoBehaviour
{
map = new byte[width,depth];
for (int z = 0; z < depth; z++)
for (int x = 0; x < width; x++)
#region Constants
public const byte Corridor = 0;
public const byte Wall = 1;
public const byte Path = 2;
#endregion
#region Fields
[Header("Maze Settings")]
[SerializeField] protected int width = 30; // x length
[SerializeField] protected int depth = 30; // z length
[SerializeField] protected int scale = 6;
[Header("Hierarchy Settings")]
[UnityEngine.Serialization.FormerlySerializedAs("_mapParentObjet")]
[SerializeField] protected Transform mapParentObject;
/// <summary>
/// List of cardinal directions used for neighbor checking and navigation.
/// </summary>
protected List<MapLocation> directions = new List<MapLocation>()
{
new MapLocation(1, 0),
new MapLocation(0, 1),
new MapLocation(-1, 0),
new MapLocation(0, -1)
};
/// <summary>
/// 2D array representing the maze grid.
/// 0 = Corridor, 1 = Wall, 2 = Special Path.
/// </summary>
public byte[,] map;
#endregion
protected virtual void Start()
{
InitialiseMap();
Generate();
DrawMap();
}
/// <summary>
/// Initializes the map array and fills it with walls.
/// </summary>
protected void InitialiseMap()
{
map = new byte[width, depth];
for (int z = 0; z < depth; z++)
{
map[x, z] = 1; //1 = wall 0 = corridor
}
}
public virtual void Generate()
{
for (int z = 0; z < depth; z++)
for (int x = 0; x < width; x++)
{
if(Random.Range(0,100) < 50)
map[x, z] = 0; //1 = wall 0 = corridor
}
}
void DrawMap()
{
for (int z = 0; z < depth; z++)
for (int x = 0; x < width; x++)
{
if (map[x, z] == 1)
for (int x = 0; x < width; x++)
{
Vector3 pos = new Vector3(x * scale, 0, z * scale);
GameObject wall = GameObject.CreatePrimitive(PrimitiveType.Cube);
wall.transform.localScale = new Vector3(scale, scale, scale);
wall.transform.position = pos;
wall.transform.SetParent(_mapParentObjet.transform);
map[x, z] = Wall;
}
}
}
}
public int CountSquareNeighbours(int x, int z)
{
int count = 0;
if (x <= 0 || x >= width - 1 || z <= 0 || z >= depth - 1) return 5;
if (map[x - 1, z] == 0) count++;
if (map[x + 1, z] == 0) count++;
if (map[x, z + 1] == 0) count++;
if (map[x, z - 1] == 0) count++;
return count;
}
/// <summary>
/// Virtual method to be overridden by specific maze generation algorithms.
/// Default implementation creates a random noise-based map.
/// </summary>
public virtual void Generate()
{
for (int z = 0; z < depth; z++)
{
for (int x = 0; x < width; x++)
{
if (Random.Range(0, 100) < 50)
{
map[x, z] = Corridor;
}
}
}
}
public int CountDiagonalNeighbours(int x, int z)
{
int count = 0;
if (x <= 0 || x >= width - 1 || z <= 0 || z >= depth - 1) return 5;
if (map[x - 1, z - 1] == 0) count++;
if (map[x + 1, z + 1] == 0) count++;
if (map[x - 1, z + 1] == 0) count++;
if (map[x + 1, z - 1] == 0) count++;
return count;
}
/// <summary>
/// Renders the maze in the scene using Unity primitives.
/// </summary>
protected void DrawMap()
{
for (int z = 0; z < depth; z++)
{
for (int x = 0; x < width; x++)
{
if (map[x, z] == Wall)
{
Vector3 pos = new Vector3(x * scale, 0, z * scale);
GameObject wall = GameObject.CreatePrimitive(PrimitiveType.Cube);
wall.transform.localScale = new Vector3(scale, scale, scale);
wall.transform.position = pos;
if (mapParentObject != null)
{
wall.transform.SetParent(mapParentObject);
}
}
}
}
}
public int CountAllNeighbours(int x, int z)
{
return CountSquareNeighbours(x,z) + CountDiagonalNeighbours(x,z);
#region Helpers
/// <summary>
/// Counts the number of horizontal and vertical neighbors that are corridors.
/// </summary>
/// <param name="x">X coordinate.</param>
/// <param name="z">Z coordinate.</param>
/// <returns>The count of square neighbors.</returns>
public int CountSquareNeighbours(int x, int z)
{
int count = 0;
if (x <= 0 || x >= width - 1 || z <= 0 || z >= depth - 1) return 5;
if (map[x - 1, z] == Corridor) count++;
if (map[x + 1, z] == Corridor) count++;
if (map[x, z + 1] == Corridor) count++;
if (map[x, z - 1] == Corridor) count++;
return count;
}
/// <summary>
/// Counts the number of diagonal neighbors that are corridors.
/// </summary>
/// <param name="x">X coordinate.</param>
/// <param name="z">Z coordinate.</param>
/// <returns>The count of diagonal neighbors.</returns>
public int CountDiagonalNeighbours(int x, int z)
{
int count = 0;
if (x <= 0 || x >= width - 1 || z <= 0 || z >= depth - 1) return 5;
if (map[x - 1, z - 1] == Corridor) count++;
if (map[x + 1, z + 1] == Corridor) count++;
if (map[x - 1, z + 1] == Corridor) count++;
if (map[x + 1, z - 1] == Corridor) count++;
return count;
}
/// <summary>
/// Counts all neighbors (square + diagonal) that are corridors.
/// </summary>
/// <param name="x">X coordinate.</param>
/// <param name="z">Z coordinate.</param>
/// <returns>Total neighbor count.</returns>
public int CountAllNeighbours(int x, int z)
{
return CountSquareNeighbours(x, z) + CountDiagonalNeighbours(x, z);
}
#endregion
}
}

View File

@@ -1,39 +1,51 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Prims : Maze
namespace Hallucinate.GameSetup.Maze
{
public override void Generate()
/// <summary>
/// Implements a simplified version of Prim's algorithm for maze generation.
/// It picks walls at random and converts them into corridors if they only have one corridor neighbor.
/// </summary>
public class Prims : Maze
{
int x = 2;
int z = 2;
map[x, z] = 0;
List<MapLocation> walls = new List<MapLocation>();
walls.Add(new MapLocation(x + 1, z));
walls.Add(new MapLocation(x - 1, z));
walls.Add(new MapLocation(x, z + 1));
walls.Add(new MapLocation(x, z - 1));
int countloops = 0;
while (walls.Count > 0 && countloops < 5000)
/// <summary>
/// Generates the maze using Prim's algorithm logic.
/// </summary>
public override void Generate()
{
int rwall = Random.Range(0, walls.Count);
x = walls[rwall].x;
z = walls[rwall].z;
walls.RemoveAt(rwall);
if (CountSquareNeighbours(x, z) == 1)
{
map[x, z] = 0;
walls.Add(new MapLocation(x + 1, z));
walls.Add(new MapLocation(x - 1, z));
walls.Add(new MapLocation(x, z + 1));
walls.Add(new MapLocation(x, z - 1));
}
int x = 2;
int z = 2;
countloops++;
map[x, z] = Corridor;
List<MapLocation> walls = new List<MapLocation>
{
new MapLocation(x + 1, z),
new MapLocation(x - 1, z),
new MapLocation(x, z + 1),
new MapLocation(x, z - 1)
};
int countloops = 0;
while (walls.Count > 0 && countloops < 5000)
{
int rwall = Random.Range(0, walls.Count);
x = walls[rwall].x;
z = walls[rwall].z;
walls.RemoveAt(rwall);
if (CountSquareNeighbours(x, z) == 1)
{
map[x, z] = Corridor;
walls.Add(new MapLocation(x + 1, z));
walls.Add(new MapLocation(x - 1, z));
walls.Add(new MapLocation(x, z + 1));
walls.Add(new MapLocation(x, z - 1));
}
countloops++;
}
}
}
}

View File

@@ -1,25 +1,40 @@
using System.Collections;
using System.Collections.Generic;
using Hallucinate.GameSetup.Maze.Extensions;
using UnityEngine;
public class Recursive : Maze
namespace Hallucinate.GameSetup.Maze
{
public override void Generate()
/// <summary>
/// A recursive backtracker algorithm for maze generation.
/// It explores the grid randomly and backtracks when it reaches a dead end.
/// </summary>
public class Recursive : Maze
{
Generate(5, 5);
/// <summary>
/// Entry point for the recursive generation.
/// Starts from a fixed position (5, 5).
/// </summary>
public override void Generate()
{
Generate(5, 5);
}
/// <summary>
/// Internal recursive method that carves corridors by exploring neighbors in a random order.
/// </summary>
/// <param name="x">The current X coordinate.</param>
/// <param name="z">The current Z coordinate.</param>
protected void Generate(int x, int z)
{
if (CountSquareNeighbours(x, z) >= 2) return;
map[x, z] = Corridor;
directions.Shuffle();
Generate(x + directions[0].x, z + directions[0].z);
Generate(x + directions[1].x, z + directions[1].z);
Generate(x + directions[2].x, z + directions[2].z);
Generate(x + directions[3].x, z + directions[3].z);
}
}
void Generate(int x, int z)
{
if (CountSquareNeighbours(x, z) >= 2) return;
map[x, z] = 0;
directions.Shuffle();
Generate(x + directions[0].x, z + directions[0].z);
Generate(x + directions[1].x, z + directions[1].z);
Generate(x + directions[2].x, z + directions[2].z);
Generate(x + directions[3].x, z + directions[3].z);
}
}

View File

@@ -1,108 +1,132 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Wilsons : Maze
namespace Hallucinate.GameSetup.Maze
{
List<MapLocation> notUsed = new List<MapLocation>();
public override void Generate()
/// <summary>
/// Implements Wilson's algorithm for generating a Uniform Spanning Tree of the grid.
/// It uses loop-erased random walks to connect unvisited cells to the existing maze.
/// </summary>
public class Wilsons : Maze
{
//create a starting cell
int x = Random.Range(2, width - 1);
int z = Random.Range(2, depth - 1);
map[x, z] = 2;
private List<MapLocation> _notUsed = new List<MapLocation>();
while(GetAvailableCells() > 1)
RandomWalk();
}
int CountSquareMazeNeighbours(int x, int z)
{
int count = 0;
for (int d = 0; d < directions.Count; d++)
/// <summary>
/// Generates the maze using Wilson's algorithm logic.
/// </summary>
public override void Generate()
{
int nx = x + directions[d].x;
int nz = z + directions[d].z;
if (map[nx, nz] == 2)
// Create a starting cell
int x = Random.Range(2, width - 1);
int z = Random.Range(2, depth - 1);
map[x, z] = Path;
while (GetAvailableCells() > 1)
{
count++;
RandomWalk();
}
}
return count;
}
int GetAvailableCells()
{
notUsed.Clear();
for (int z = 1; z < depth - 1; z++)
for (int x = 1; x < width - 1; x++)
/// <summary>
/// Counts how many neighbors are already part of the finalized "Path".
/// </summary>
private int CountSquareMazeNeighbours(int x, int z)
{
int count = 0;
for (int d = 0; d < directions.Count; d++)
{
if (CountSquareMazeNeighbours(x, z) == 0)
int nx = x + directions[d].x;
int nz = z + directions[d].z;
if (map[nx, nz] == Path)
{
notUsed.Add(new MapLocation(x, z));
count++;
}
}
return notUsed.Count;
}
return count;
}
void RandomWalk()
{
List<MapLocation> inWalk = new List<MapLocation>();
int cx;
int cz;
int rstartIndex = Random.Range(0, notUsed.Count);
cx = notUsed[rstartIndex].x;
cz = notUsed[rstartIndex].z;
inWalk.Add(new MapLocation(cx, cz));
int loop = 0;
bool validPath = false;
while (cx > 0 && cx < width - 1 && cz > 0 && cz < depth - 1 && loop < 5000 && !validPath)
/// <summary>
/// Scans the grid for cells that are not yet connected to the maze.
/// </summary>
/// <returns>The number of available (unused) cells.</returns>
private int GetAvailableCells()
{
map[cx, cz] = 0;
if (CountSquareMazeNeighbours(cx, cz) > 1)
break;
int rd = Random.Range(0, directions.Count);
int nx = cx + directions[rd].x;
int nz = cz + directions[rd].z;
if (CountSquareNeighbours(nx, nz) < 2)
_notUsed.Clear();
for (int z = 1; z < depth - 1; z++)
{
cx = nx;
cz = nz;
inWalk.Add(new MapLocation(cx, cz));
for (int x = 1; x < width - 1; x++)
{
if (CountSquareMazeNeighbours(x, z) == 0)
{
_notUsed.Add(new MapLocation(x, z));
}
}
}
validPath = CountSquareMazeNeighbours(cx, cz) == 1;
loop++;
return _notUsed.Count;
}
if (validPath)
/// <summary>
/// Performs a random walk from an unused cell until it hits the existing maze.
/// </summary>
private void RandomWalk()
{
map[cx, cz] = 0;
Debug.Log("PathFound");
List<MapLocation> inWalk = new List<MapLocation>();
int rStartIndex = Random.Range(0, _notUsed.Count);
foreach (MapLocation m in inWalk)
int cx = _notUsed[rStartIndex].x;
int cz = _notUsed[rStartIndex].z;
inWalk.Add(new MapLocation(cx, cz));
int loopCount = 0;
bool validPath = false;
while (cx > 0 && cx < width - 1 && cz > 0 && cz < depth - 1 && loopCount < 5000 && !validPath)
{
map[m.x, m.z] = 2;
map[cx, cz] = Corridor;
if (CountSquareMazeNeighbours(cx, cz) > 1)
{
break;
}
int rd = Random.Range(0, directions.Count);
int nx = cx + directions[rd].x;
int nz = cz + directions[rd].z;
if (CountSquareNeighbours(nx, nz) < 2)
{
cx = nx;
cz = nz;
inWalk.Add(new MapLocation(cx, cz));
}
validPath = CountSquareMazeNeighbours(cx, cz) == 1;
loopCount++;
}
inWalk.Clear();
}
else
{
foreach (MapLocation m in inWalk)
map[m.x, m.z] = 1;
inWalk.Clear();
}
if (validPath)
{
map[cx, cz] = Corridor;
Debug.Log("Path Found");
foreach (MapLocation m in inWalk)
{
map[m.x, m.z] = Path;
}
inWalk.Clear();
}
else
{
foreach (MapLocation m in inWalk)
{
map[m.x, m.z] = Wall;
}
inWalk.Clear();
}
}
}
}