Advertisement
LuckyScripters

Maze Generator

Jan 5th, 2024 (edited)
861
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.34 KB | None | 0 0
  1. -- This maze has been generated using Prim's Algorithm
  2.  
  3. local rows = 100
  4. local colums = 100
  5. local cellSpace = 4
  6. local cellHeight = 10
  7.  
  8. local maze : {{{Cell : BasePart, Filtered : boolean, Visited : boolean}}} = {}
  9.  
  10. local startingPosition = Vector3.new(0, 10, 0)
  11.  
  12. local function createFolder() : Folder
  13.     local folder = Instance.new("Folder", workspace)
  14.     folder.Name = "Maze"
  15.     return folder
  16. end
  17.  
  18. local function createPart(size : Vector3, position : Vector3) : Part
  19.     local part = Instance.new("Part", workspace:FindFirstChild("Maze") or createFolder())
  20.     part.Name = "Wall"
  21.     part.Anchored = true
  22.     part.TopSurface = Enum.SurfaceType.Smooth
  23.     part.BottomSurface = Enum.SurfaceType.Smooth
  24.     part.Anchored = true
  25.     part.Material = Enum.Material.Grass
  26.     part.Locked = true
  27.     part.BrickColor = BrickColor.new("Bright green")
  28.     part.Size = size
  29.     part.Position = startingPosition + position
  30.     return part
  31. end
  32.  
  33. local function SnapToGrid(position : Vector3) : Vector3
  34.     return Vector3.new(position.X - position.X % cellSpace + cellSpace / 2, position.Y, position.Z - position.Z % cellSpace + cellSpace / 2)
  35. end
  36.    
  37. local function SnapToOddNumber(number : number) : number
  38.     if number % 2 == 1 then
  39.         return number
  40.     else
  41.         return number + 1
  42.     end
  43. end
  44.  
  45. local function createSinglePassage(x : number, z : number) : ()
  46.     maze[x][z].Visited = true
  47.     maze[x][z].Cell:Destroy()
  48. end
  49.  
  50.  
  51. local function createPassage(xStart : number, zStart : number, xGoal : number, zGoal : number) : ()
  52.     for index = 1, 2 do
  53.         local differenceX = xGoal - xStart
  54.         local differenceZ = zGoal - zStart
  55.         if differenceX < 0 or differenceZ < 0 then
  56.             maze[xStart - (differenceX < 0 and index or 0)][zStart - (differenceZ < 0 and index or 0)].Visited = true
  57.             maze[xStart - (differenceX < 0 and index or 0)][zStart - (differenceZ < 0 and index or 0)].Cell:Destroy()
  58.         elseif differenceX > 0 or differenceZ > 0 then
  59.             maze[xStart + (differenceX > 0 and index or 0)][zStart + (differenceZ > 0 and index or 0)].Visited = true
  60.             maze[xStart + (differenceX > 0 and index or 0)][zStart + (differenceZ > 0 and index or 0)].Cell:Destroy()
  61.         end
  62.     end
  63. end
  64.  
  65. local function mergeNeighborsTables(neighborsTable1 : {{X : number, Z : number, Cell : BasePart}}, neighborsTable2 : {{X : number, Z : number, Cell : BasePart}}) : {{X : number, Z : number, Cell : BasePart}}
  66.     local mergedNeighborsTable = {}
  67.     for index, neighbor in neighborsTable1 do
  68.         if not maze[neighbor.X][neighbor.Z].Visited then
  69.             table.insert(mergedNeighborsTable, neighbor)
  70.         end
  71.     end
  72.     for index, neighbor in neighborsTable2 do
  73.         if not maze[neighbor.X][neighbor.Z].Visited then
  74.             table.insert(mergedNeighborsTable, neighbor)
  75.         end
  76.     end
  77.     return mergedNeighborsTable
  78. end
  79.  
  80. local function generateCells() : ()
  81.     for x = 1, rows do
  82.         maze[x] = {}
  83.         for z = 1, colums do
  84.             if x == 1 or x == rows then
  85.                 maze[x][z] = {Cell = createPart(Vector3.new(cellSpace, cellHeight, cellSpace), Vector3.new((x - 1) * cellSpace, cellHeight / 2, (z - 1) * cellSpace)), Filtered = true, Visited = false}
  86.             elseif z == 1 or z == colums then
  87.                 maze[x][z] = {Cell = createPart(Vector3.new(cellSpace, cellHeight, cellSpace), Vector3.new((x - 1) * cellSpace, cellHeight / 2, (z - 1) * cellSpace)), Filtered = true, Visited = false}
  88.             else
  89.                 maze[x][z] = {Cell = createPart(Vector3.new(cellSpace, cellHeight, cellSpace), Vector3.new((x - 1) * cellSpace, cellHeight / 2, (z - 1) * cellSpace)), Filtered = false, Visited = false}
  90.             end
  91.         end
  92.     end
  93. end
  94.  
  95. local function getNeighbors(x : number, z : number, isVisited : boolean) : {{X : number, Z : number, Cell : BasePart}}
  96.     assert(x >= 1 and x <= rows, "x is out of range")
  97.     assert(z >= 1 and z <= colums, "z is out of range")
  98.     assert(not maze[x][z].Filtered, "Cannot get neighbors of a filtered cell")
  99.     local neighbors = {}
  100.     if isVisited then
  101.         if maze[x] and maze[x][z + 2] and not maze[x][z + 2].Filtered and maze[x][z + 2].Visited then
  102.             table.insert(neighbors, {X = x, Z = z + 2, Cell = maze[x][z + 2].Cell})
  103.         end
  104.         if maze[x] and maze[x][z - 2] and not maze[x][z - 2].Filtered and maze[x][z - 2].Visited then
  105.             table.insert(neighbors, {X = x, Z = z - 2, Cell = maze[x][z - 2].Cell})
  106.         end
  107.         if maze[x + 2] and maze[x + 2][z] and not maze[x + 2][z].Filtered and maze[x + 2][z].Visited then
  108.             table.insert(neighbors, {X = x + 2, Z = z, Cell = maze[x + 2][z].Cell})
  109.         end
  110.         if maze[x - 2] and maze[x - 2][z] and not maze[x - 2][z].Filtered and maze[x - 2][z].Visited then
  111.             table.insert(neighbors, {X = x - 2, Z = z, Cell = maze[x - 2][z].Cell})
  112.         end
  113.     else
  114.         if maze[x] and maze[x][z + 2] and not maze[x][z + 2].Filtered and not maze[x][z + 2].Visited then
  115.             table.insert(neighbors, {X = x, Z = z + 2, Cell = maze[x][z + 2].Cell})
  116.         end
  117.         if maze[x] and maze[x][z - 2] and not maze[x][z - 2].Filtered and not maze[x][z - 2].Visited then
  118.             table.insert(neighbors, {X = x, Z = z - 2, Cell = maze[x][z - 2].Cell})
  119.         end
  120.         if maze[x + 2] and maze[x + 2][z] and not maze[x + 2][z].Filtered and not maze[x + 2][z].Visited then
  121.             table.insert(neighbors, {X = x + 2, Z = z, Cell = maze[x + 2][z].Cell})
  122.         end
  123.         if maze[x - 2] and maze[x - 2][z] and not maze[x - 2][z].Filtered and not maze[x - 2][z].Visited then
  124.             table.insert(neighbors, {X = x - 2, Z = z, Cell = maze[x - 2][z].Cell})
  125.         end
  126.     end
  127.     return neighbors
  128. end
  129.  
  130. local function generateMaze() : ()
  131.     local cell = {X = 2, Z = 2, Cell = maze[2][2].Cell}
  132.     local neighborsUnvisited = getNeighbors(cell.X, cell.Z, false)
  133.     createSinglePassage(cell.X, cell.Z)
  134.     while table.maxn(neighborsUnvisited) > 0 do
  135.         local randomNeighborUnvisited = math.random(1, table.maxn(neighborsUnvisited))
  136.         local neighborsVisited = getNeighbors(neighborsUnvisited[randomNeighborUnvisited].X, neighborsUnvisited[randomNeighborUnvisited].Z, true)
  137.         local randomNeighborVisited = math.random(1, table.maxn(neighborsVisited))
  138.         createPassage(neighborsVisited[randomNeighborVisited].X, neighborsVisited[randomNeighborVisited].Z, neighborsUnvisited[randomNeighborUnvisited].X, neighborsUnvisited[randomNeighborUnvisited].Z)
  139.         neighborsUnvisited = mergeNeighborsTables(neighborsUnvisited, getNeighbors(neighborsUnvisited[randomNeighborUnvisited].X, neighborsUnvisited[randomNeighborUnvisited].Z, false))
  140.     end
  141. end
  142.  
  143. rows = SnapToOddNumber(math.max(rows, 3))
  144. colums = SnapToOddNumber(math.max(colums, 3))
  145. startingPosition = SnapToGrid(startingPosition)
  146.  
  147. generateCells()
  148. generateMaze()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement