Support per-floor variable maze sizes
Add configuration to vary floor sizes: FloorSizeMode enum, varyFloorSize, floorSizeMode and manualFloorSizes in MazeReworkConfig. MazeReworkGenerator now accepts explicit width/depth via an overload, threads width/depth through generation, and adds optional endBounds to placement logic; dead-end/furthest searches respect bounds. MazeReworkManager computes per-floor seeds and dynamic sizes (manual or randomized), instantiates per-floor generators, and passes end bounds between floors for both animated and instantaneous generation. Also includes minor IDE workspace.xml metadata formatting changes.
This commit is contained in:
14
.idea/.idea.BABA_YAGA/.idea/workspace.xml
generated
14
.idea/.idea.BABA_YAGA/.idea/workspace.xml
generated
@@ -12,7 +12,9 @@
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="d308d1cb-09fc-4331-ba20-00f7b43d1576" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.BABA_YAGA/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.BABA_YAGA/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkSpawner.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkSpawner.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkConfig.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkConfig.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkGenerator.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkGenerator.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkManager.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkManager.cs" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -36,10 +38,10 @@
|
||||
<setting file="file://$PROJECT_DIR$/Library/PackageCache/com.wooshii.foldericons@201a18f355d3/FolderIcons/Editor/FolderIcons.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Library/PackageCache/com.wooshii.foldericons@201a18f355d3/FolderIcons/Editor/FolderIconsEditor.asmdef" root0="SKIP_HIGHLIGHTING" />
|
||||
</component>
|
||||
<component name="KubernetesApiPersistence"><![CDATA[{}]]></component>
|
||||
<component name="KubernetesApiProvider"><![CDATA[{
|
||||
"isMigrated": true
|
||||
}]]></component>
|
||||
<component name="KubernetesApiPersistence">{}</component>
|
||||
<component name="KubernetesApiProvider">{
|
||||
"isMigrated": true
|
||||
}</component>
|
||||
<component name="McpProjectServerCommands">
|
||||
<commands />
|
||||
<urls />
|
||||
@@ -146,6 +148,8 @@
|
||||
<workItem from="1781765548760" duration="8210000" />
|
||||
<workItem from="1782445122703" duration="1948000" />
|
||||
<workItem from="1782825955934" duration="1783000" />
|
||||
<workItem from="1783149945807" duration="606000" />
|
||||
<workItem from="1783156047890" duration="1863000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
|
||||
@@ -18,6 +18,12 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
/// <summary>
|
||||
/// Configuration asset containing parameters for the reworked maze generation.
|
||||
/// </summary>
|
||||
public enum FloorSizeMode
|
||||
{
|
||||
Manual,
|
||||
Random
|
||||
}
|
||||
|
||||
[CreateAssetMenu(fileName = "MazeReworkConfig", menuName = "BABA_YAGA/MazeRework/Config")]
|
||||
public class MazeReworkConfig : ScriptableObject
|
||||
{
|
||||
@@ -36,6 +42,22 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
[MinValue(5)]
|
||||
public int depth = 21;
|
||||
|
||||
[FoldoutGroup("Grid Dimensions")]
|
||||
[Tooltip("If true, allows you to vary the floor size across multiple floors.")]
|
||||
public bool varyFloorSize = false;
|
||||
|
||||
[FoldoutGroup("Grid Dimensions")]
|
||||
[ShowIf("varyFloorSize")]
|
||||
[Tooltip("Random will pick random sizes up to the max width/depth. Manual uses the list below.")]
|
||||
[EnumToggleButtons]
|
||||
public FloorSizeMode floorSizeMode = FloorSizeMode.Random;
|
||||
|
||||
[FoldoutGroup("Grid Dimensions")]
|
||||
[ShowIf("@varyFloorSize && floorSizeMode == FloorSizeMode.Manual")]
|
||||
[ListDrawerSettings(ShowIndexLabels = true)]
|
||||
[Tooltip("List of manual sizes for each floor (Index 0 = Floor 0, etc). Must be odd numbers >= 5.")]
|
||||
public System.Collections.Generic.List<Vector2Int> manualFloorSizes = new System.Collections.Generic.List<Vector2Int>();
|
||||
|
||||
[FoldoutGroup("Seeding")]
|
||||
[Tooltip("If true, a random seed will be generated at runtime.")]
|
||||
public bool useRandomSeed = true;
|
||||
|
||||
@@ -49,10 +49,21 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
}
|
||||
|
||||
private readonly MazeReworkConfig _config;
|
||||
private readonly int _width;
|
||||
private readonly int _depth;
|
||||
|
||||
public MazeReworkGenerator(MazeReworkConfig config)
|
||||
{
|
||||
_config = config;
|
||||
_width = config != null ? config.width : 21;
|
||||
_depth = config != null ? config.depth : 21;
|
||||
}
|
||||
|
||||
public MazeReworkGenerator(MazeReworkConfig config, int width, int depth)
|
||||
{
|
||||
_config = config;
|
||||
_width = width;
|
||||
_depth = depth;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -69,12 +80,12 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
/// Generates a 2D layout of the maze of size config.width by config.depth using a specific seed.
|
||||
/// Generates the maze grid.
|
||||
/// </summary>
|
||||
public MazeReworkCellType[,] Generate(int seed, Vector2Int? forcedStart = null, Vector2Int? forcedDirection = null)
|
||||
public MazeReworkCellType[,] Generate(int seed, Vector2Int? forcedStart = null, Vector2Int? forcedDirection = null, Vector2Int? endBounds = null)
|
||||
{
|
||||
if (_config == null) return null;
|
||||
|
||||
int width = _config.width;
|
||||
int depth = _config.depth;
|
||||
int width = _width;
|
||||
int depth = _depth;
|
||||
var grid = new MazeReworkCellType[width, depth];
|
||||
|
||||
// 1. Initialize all cells as Wall
|
||||
@@ -129,7 +140,7 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
CarveLoops(grid, rng, width, depth);
|
||||
|
||||
// 8. Place Start & End points
|
||||
PlaceStartAndEnd(grid, rooms, width, depth, rng, forcedStart, forcedDirection, null);
|
||||
PlaceStartAndEnd(grid, rooms, width, depth, rng, forcedStart, forcedDirection, null, endBounds);
|
||||
|
||||
return grid;
|
||||
}
|
||||
@@ -149,12 +160,12 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
return GenerateAnimated(seed);
|
||||
}
|
||||
|
||||
public (MazeReworkCellType[,] grid, List<MazeCellChange> history) GenerateAnimated(int seed, Vector2Int? forcedStart = null, Vector2Int? forcedDirection = null)
|
||||
public (MazeReworkCellType[,] grid, List<MazeCellChange> history) GenerateAnimated(int seed, Vector2Int? forcedStart = null, Vector2Int? forcedDirection = null, Vector2Int? endBounds = null)
|
||||
{
|
||||
if (_config == null) return (null, null);
|
||||
|
||||
int width = _config.width;
|
||||
int depth = _config.depth;
|
||||
int width = _width;
|
||||
int depth = _depth;
|
||||
var grid = new MazeReworkCellType[width, depth];
|
||||
var history = new List<MazeCellChange>(width * depth * 2);
|
||||
|
||||
@@ -219,7 +230,7 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
|
||||
// 8. Place Start & End points (no highlighting needed for this step in animation)
|
||||
currentPhase = MazeAnimationPhase.StartEnd;
|
||||
PlaceStartAndEnd(grid, rooms, width, depth, rng, forcedStart, forcedDirection, recordNoHighlight);
|
||||
PlaceStartAndEnd(grid, rooms, width, depth, rng, forcedStart, forcedDirection, history, endBounds);
|
||||
|
||||
return (grid, history);
|
||||
}
|
||||
@@ -469,9 +480,12 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
}
|
||||
}
|
||||
|
||||
private void PlaceStartAndEnd(MazeReworkCellType[,] grid, List<Room> rooms, int width, int depth, System.Random rng, Vector2Int? forcedStart, Vector2Int? forcedDirection,
|
||||
Action<int, int, MazeReworkCellType> onCellChanged = null)
|
||||
private void PlaceStartAndEnd(MazeReworkCellType[,] grid, List<Room> rooms, int width, int depth, System.Random rng, Vector2Int? forcedStart, Vector2Int? forcedDirection, List<MazeCellChange> history = null, Vector2Int? endBounds = null)
|
||||
{
|
||||
Action<int, int, MazeReworkCellType> onCellChanged = history != null
|
||||
? (x, z, type) => history.Add(new MazeCellChange(x, z, type, MazeCellHighlight.None, MazeAnimationPhase.StartEnd))
|
||||
: (Action<int, int, MazeReworkCellType>)null;
|
||||
|
||||
Vector2Int startPt = new Vector2Int(-1, -1);
|
||||
|
||||
if (forcedStart.HasValue)
|
||||
@@ -480,7 +494,7 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
}
|
||||
else
|
||||
{
|
||||
startPt = FindDeadEnd(grid, width, depth, rng, new Vector2Int(-1, -1));
|
||||
startPt = FindDeadEnd(grid, width, depth, rng, new Vector2Int(-1, -1), endBounds);
|
||||
if (startPt.x == -1)
|
||||
{
|
||||
// Fallback to config start if no corridors exist
|
||||
@@ -493,17 +507,22 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
grid[startPt.x, startPt.y] = MazeReworkCellType.Start;
|
||||
onCellChanged?.Invoke(startPt.x, startPt.y, MazeReworkCellType.Start);
|
||||
|
||||
Vector2Int endPt = FindDeadEnd(grid, width, depth, rng, startPt);
|
||||
Vector2Int endPt = FindDeadEnd(grid, width, depth, rng, startPt, endBounds);
|
||||
|
||||
if (endPt.x == -1)
|
||||
{
|
||||
// Fallback: just pick the furthest corridor cell from startPt
|
||||
endPt = FindFurthestCorridor(grid, width, depth, startPt);
|
||||
endPt = FindFurthestCorridor(grid, width, depth, startPt, endBounds);
|
||||
|
||||
if (endPt.x == -1)
|
||||
{
|
||||
// Extreme fallback
|
||||
int ex = width - 2, ez = depth - 2;
|
||||
if (endBounds.HasValue)
|
||||
{
|
||||
ex = endBounds.Value.x - 2;
|
||||
ez = endBounds.Value.y - 2;
|
||||
}
|
||||
EnsureValidOddCoordinates(width, depth, ref ex, ref ez);
|
||||
endPt = new Vector2Int(ex, ez);
|
||||
}
|
||||
@@ -518,14 +537,17 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
EnforceSingleConnection(grid, endPt.x, endPt.y, null);
|
||||
}
|
||||
|
||||
private Vector2Int FindDeadEnd(MazeReworkCellType[,] grid, int width, int depth, System.Random rng, Vector2Int exclude)
|
||||
private Vector2Int FindDeadEnd(MazeReworkCellType[,] grid, int width, int depth, System.Random rng, Vector2Int exclude, Vector2Int? bounds = null)
|
||||
{
|
||||
List<Vector2Int> deadEnds = new List<Vector2Int>();
|
||||
List<Vector2Int> corridors = new List<Vector2Int>();
|
||||
|
||||
int maxW = bounds.HasValue ? Mathf.Min(width, bounds.Value.x) : width;
|
||||
int maxD = bounds.HasValue ? Mathf.Min(depth, bounds.Value.y) : depth;
|
||||
|
||||
for (int z = 1; z < depth - 1; z++)
|
||||
for (int z = 1; z < maxD - 1; z++)
|
||||
{
|
||||
for (int x = 1; x < width - 1; x++)
|
||||
for (int x = 1; x < maxW - 1; x++)
|
||||
{
|
||||
if (grid[x, z] == MazeReworkCellType.Corridor)
|
||||
{
|
||||
@@ -551,14 +573,17 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
return new Vector2Int(-1, -1);
|
||||
}
|
||||
|
||||
private Vector2Int FindFurthestCorridor(MazeReworkCellType[,] grid, int width, int depth, Vector2Int from)
|
||||
private Vector2Int FindFurthestCorridor(MazeReworkCellType[,] grid, int width, int depth, Vector2Int from, Vector2Int? bounds = null)
|
||||
{
|
||||
Vector2Int best = new Vector2Int(-1, -1);
|
||||
float maxDist = -1f;
|
||||
|
||||
int maxW = bounds.HasValue ? Mathf.Min(width, bounds.Value.x) : width;
|
||||
int maxD = bounds.HasValue ? Mathf.Min(depth, bounds.Value.y) : depth;
|
||||
|
||||
for (int z = 1; z < depth - 1; z++)
|
||||
for (int z = 1; z < maxD - 1; z++)
|
||||
{
|
||||
for (int x = 1; x < width - 1; x++)
|
||||
for (int x = 1; x < maxW - 1; x++)
|
||||
{
|
||||
if (grid[x, z] == MazeReworkCellType.Corridor)
|
||||
{
|
||||
|
||||
@@ -122,34 +122,83 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
ClearMaze();
|
||||
if (animator != null) animator.StopAnimation();
|
||||
|
||||
var generator = new MazeReworkGenerator(config);
|
||||
|
||||
if (animateGeneration && animator != null)
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
StartCoroutine(GenerateAndSpawnAnimatedRoutine(generator));
|
||||
StartCoroutine(GenerateAndSpawnAnimatedRoutine());
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[MazeReworkManager] Animation is only supported in Play Mode. Falling back to instantaneous generation.");
|
||||
GenerateInstantaneous(generator);
|
||||
GenerateInstantaneous();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GenerateInstantaneous(generator);
|
||||
GenerateInstantaneous();
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator GenerateAndSpawnAnimatedRoutine(MazeReworkGenerator generator)
|
||||
private void GetDynamicFloorSize(int floorIndex, int seed, out int width, out int depth)
|
||||
{
|
||||
width = config.width;
|
||||
depth = config.depth;
|
||||
|
||||
if (config.varyFloorSize)
|
||||
{
|
||||
if (config.floorSizeMode == FloorSizeMode.Manual)
|
||||
{
|
||||
if (config.manualFloorSizes != null && floorIndex < config.manualFloorSizes.Count)
|
||||
{
|
||||
width = config.manualFloorSizes[floorIndex].x;
|
||||
depth = config.manualFloorSizes[floorIndex].y;
|
||||
}
|
||||
}
|
||||
else // Random
|
||||
{
|
||||
System.Random rng = new System.Random(seed);
|
||||
// Generate random odd sizes between 5 and config.width/depth
|
||||
int wRange = (config.width - 5) / 2;
|
||||
int dRange = (config.depth - 5) / 2;
|
||||
width = 5 + rng.Next(0, wRange + 1) * 2;
|
||||
depth = 5 + rng.Next(0, dRange + 1) * 2;
|
||||
}
|
||||
|
||||
// Ensure they are odd and at least 5
|
||||
if (width % 2 == 0) width--;
|
||||
if (depth % 2 == 0) depth--;
|
||||
if (width < 5) width = 5;
|
||||
if (depth < 5) depth = 5;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator GenerateAndSpawnAnimatedRoutine()
|
||||
{
|
||||
int[] floorSeeds = new int[floorCount];
|
||||
Vector2Int[] floorSizes = new Vector2Int[floorCount];
|
||||
for (int i = 0; i < floorCount; i++)
|
||||
{
|
||||
floorSeeds[i] = config.useRandomSeed ? System.Guid.NewGuid().GetHashCode() : config.seed + i * 1000;
|
||||
GetDynamicFloorSize(i, floorSeeds[i], out int fW, out int fD);
|
||||
floorSizes[i] = new Vector2Int(fW, fD);
|
||||
}
|
||||
|
||||
Vector2Int? nextStartPos = null;
|
||||
Vector2Int? nextStartDir = null;
|
||||
for (int i = 0; i < floorCount; i++)
|
||||
{
|
||||
int seed = config.useRandomSeed ? System.Guid.NewGuid().GetHashCode() : config.seed + i * 1000;
|
||||
var (grid, history) = generator.GenerateAnimated(seed, nextStartPos, nextStartDir);
|
||||
int fWidth = floorSizes[i].x;
|
||||
int fDepth = floorSizes[i].y;
|
||||
var generator = new MazeReworkGenerator(config, fWidth, fDepth);
|
||||
|
||||
Vector2Int? endBounds = null;
|
||||
if (i < floorCount - 1)
|
||||
{
|
||||
endBounds = floorSizes[i + 1];
|
||||
}
|
||||
|
||||
var (grid, history) = generator.GenerateAnimated(floorSeeds[i], nextStartPos, nextStartDir, endBounds);
|
||||
|
||||
if (i > 0 && nextStartPos.HasValue)
|
||||
{
|
||||
@@ -159,9 +208,9 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
if (i < floorCount - 1)
|
||||
{
|
||||
Vector2Int endPos = new Vector2Int(-1, -1);
|
||||
for (int z = 0; z < config.depth; z++)
|
||||
for (int z = 0; z < fDepth; z++)
|
||||
{
|
||||
for (int x = 0; x < config.width; x++)
|
||||
for (int x = 0; x < fWidth; x++)
|
||||
{
|
||||
if (grid[x, z] == MazeReworkCellType.End) { endPos = new Vector2Int(x, z); break; }
|
||||
}
|
||||
@@ -192,14 +241,32 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
Debug.Log($"[MazeReworkManager] All floors animated! Beginning world position: {BeginningWorldPosition}");
|
||||
}
|
||||
|
||||
private void GenerateInstantaneous(MazeReworkGenerator generator)
|
||||
private void GenerateInstantaneous()
|
||||
{
|
||||
int[] floorSeeds = new int[floorCount];
|
||||
Vector2Int[] floorSizes = new Vector2Int[floorCount];
|
||||
for (int i = 0; i < floorCount; i++)
|
||||
{
|
||||
floorSeeds[i] = config.useRandomSeed ? System.Guid.NewGuid().GetHashCode() : config.seed + i * 1000;
|
||||
GetDynamicFloorSize(i, floorSeeds[i], out int fW, out int fD);
|
||||
floorSizes[i] = new Vector2Int(fW, fD);
|
||||
}
|
||||
|
||||
Vector2Int? nextStartPos = null;
|
||||
Vector2Int? nextStartDir = null;
|
||||
for (int i = 0; i < floorCount; i++)
|
||||
{
|
||||
int seed = config.useRandomSeed ? System.Guid.NewGuid().GetHashCode() : config.seed + i * 1000;
|
||||
var grid = generator.Generate(seed, nextStartPos, nextStartDir);
|
||||
int fWidth = floorSizes[i].x;
|
||||
int fDepth = floorSizes[i].y;
|
||||
var generator = new MazeReworkGenerator(config, fWidth, fDepth);
|
||||
|
||||
Vector2Int? endBounds = null;
|
||||
if (i < floorCount - 1)
|
||||
{
|
||||
endBounds = floorSizes[i + 1];
|
||||
}
|
||||
|
||||
var grid = generator.Generate(floorSeeds[i], nextStartPos, nextStartDir, endBounds);
|
||||
|
||||
// If this is not the first floor, replace the Start with StairsDown to connect to the floor below
|
||||
if (i > 0 && nextStartPos.HasValue)
|
||||
@@ -207,13 +274,12 @@ namespace Baba_yaga.GameSetup.MazeRework
|
||||
grid[nextStartPos.Value.x, nextStartPos.Value.y] = MazeReworkCellType.StairsDown;
|
||||
}
|
||||
|
||||
// If there is a floor above this one, convert the End cell to a StairsUp
|
||||
if (i < floorCount - 1)
|
||||
{
|
||||
Vector2Int endPos = new Vector2Int(-1, -1);
|
||||
for (int z = 0; z < config.depth; z++)
|
||||
for (int z = 0; z < fDepth; z++)
|
||||
{
|
||||
for (int x = 0; x < config.width; x++)
|
||||
for (int x = 0; x < fWidth; x++)
|
||||
{
|
||||
if (grid[x, z] == MazeReworkCellType.End)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user