· 8 years ago · Aug 25, 2018, 10:26 PM
1--Original was Recursive Backtrack Algorithm by AxonMega
2--Current is Kruskal Algorithm by GreekForge (Used to be Xstarlight)
3
4local baseplate = workspace.Baseplate
5local bPos = baseplate.Position
6local rs = game:GetService("RunService")
7local xStart = bPos.X - 210 --require for
8local yStart = bPos.Y + 1
9local zStart = bPos.Z - 210
10local size = Vector3.new(0.2,0.2,0.2)
11local walls = {}
12local cells = {}
13local edgeWalls = {}
14 --cell count should be 400
15
16local function pause() --used instead of wait
17 rs.Stepped:Wait()
18end
19math.randomseed(tick())
20
21--create
22local mazeF = Instance.new("Folder") --maze folder
23mazeF.Name = "Kruskal's Maze"
24mazeF.Parent = workspace
25local floorF = Instance.new("Folder") --pathfinding
26floorF.Name = "Floors"
27floorF.Parent = mazeF
28local wallF = Instance.new("Folder") --wall container
29wallF.Name = "Walls"
30wallF.Parent = mazeF
31local baseFloor = Instance.new("Part")
32baseFloor.Name = "Floor"
33baseFloor.Material = Enum.Material.DiamondPlate
34baseFloor.BrickColor = BrickColor.new("Really black")
35baseFloor.Size = Vector3.new(10,1,10) --aka the cell size for x and z value
36baseFloor.Anchored = true
37baseFloor.TopSurface = Enum.SurfaceType.Smooth
38baseFloor.BottomSurface = Enum.SurfaceType.Smooth
39local baseWall = Instance.new("Part") --base wall for cloning
40baseWall.Name = "Wall"
41baseWall.BrickColor = BrickColor.new("Institutional white")
42baseWall.Material = Enum.Material.DiamondPlate
43baseWall.Reflectance = 0.25
44baseWall.Anchored = true
45baseWall.Size = Vector3.new(10, 20, 10)
46baseWall.TopSurface = Enum.SurfaceType.Smooth
47baseWall.BottomSurface = Enum.SurfaceType.Smooth
48
49--create cells and walls
50local rowCount = 0
51function createMaze() --much use
52 rowCount = 0
53 local serial = 1
54 local evenRow = true
55 local wallID = 1
56 for _, c in ipairs(wallF:GetChildren()) do --destroy each wall
57 c:Destroy()
58 walls = {}
59 end
60 for _, c in ipairs(floorF:GetChildren()) do --destroy each floor
61 c:Destroy()
62 cells = {}
63 end
64 for i=1, 41 do --for each row
65 evenRow = (not evenRow)
66 local currentlyEvenRow = evenRow
67 local evenColumn = true
68 local row = xStart + i*10
69 local function fillRow()
70 for i2 = 1, 41 do --for each column
71 local floor = baseFloor:Clone()
72 floor.Parent = floorF
73 floor.CFrame = CFrame.new(row, yStart, zStart + i2*10)
74 evenColumn = (not evenColumn)
75 if currentlyEvenRow and evenColumn then
76 table.insert(cells,#cells+1,floor)
77 local ID = Instance.new("StringValue")
78 ID.Name = "IDChip"
79 ID.Value = serial
80 ID.Parent = floor
81 local pos = Instance.new("StringValue")
82 pos.Name = "CreationNum"
83 pos.Value = serial
84 pos.Parent = floor
85 serial = serial + 1
86 else
87 local wall = baseWall:Clone()
88 wall.Parent = wallF
89 wall.CFrame = floor.CFrame + Vector3.new(0,10.5,0) --its position according to the floor
90 local ID2 = Instance.new("StringValue")
91 ID2.Name = "WallChip"
92 ID2.Value = wallID
93 ID2.Parent = wall
94 wallID = wallID + 1
95 table.insert(walls, #walls+1,wall)
96 if wall.Position.X == 200 or wall.Position.X == -200 then
97 local edge = Instance.new("BoolValue")
98 edge.Name = "OnEdge"
99 edge.Value = true
100 edge.Parent = wall
101 table.insert(edgeWalls, #edgeWalls+1, wall) --inserting this wall to be identifyable
102 elseif wall.Position.Z == 200 or wall.Position.Z == -200 then
103 local edge = Instance.new("BoolValue")
104 edge.Name = "OnEdge"
105 edge.Value = true
106 edge.Parent = wall
107 table.insert(edgeWalls, #edgeWalls+1, wall) --inserting this wall to be identifyable
108 end
109 end
110 pause()
111 end
112 rowCount = rowCount + 1
113 end
114 coroutine.resume(coroutine.create(fillRow))
115 pause()
116 end
117 repeat wait() until rowCount == 41
118 print("Starter made!")
119end
120
121--stating all functions
122
123function numDifSerials() --for how many different groupings there are
124 local tabel = {}
125 for i=1, #cells do --for each cell
126 local idVal = cells[i].IDChip --get their serial code
127 if idVal and #tabel < 1 then --if there aren't any serials in the table
128 table.insert(tabel,#tabel+1,idVal.Value) --insert into table
129 elseif idVal then --else
130 for i2=1, #tabel do --for each cell in the table
131 if i2 == #tabel then --if we reached max number of loops
132 table.insert(tabel,#tabel+1,idVal) --insert to table
133 end
134 if tabel[i2] == idVal.Value then --unless we have two of the same
135 break --ends this loop
136 end
137 end
138 end
139 end
140 return #tabel
141end
142
143function findCell(currentCell, direction) --find thou cell from curPos
144 local newPos = currentCell.Position + direction
145 local parts = workspace:FindPartsInRegion3(Region3.new(newPos - size, newPos + size))
146 local newCell = parts[1]
147 if newCell and newCell.Name == "Floor" then
148 return newCell
149 end
150end
151
152function closeWalls(CCell) --if surrounded by walls
153 local directions = {Vector3.new(20,0,0),Vector3.new(-20,0,0),Vector3.new(0,0,20),Vector3.new(0,0,-20)}
154 local wall1 = false
155 local wall2 = false
156 local wall3 = false
157 local wall4 = false
158 for i=1, 4 do
159 local cell2 = findCell(CCell, directions[i])
160 if cell2 then
161 local wallPos = ((CCell.Position + cell2.Position)/2) + Vector3.new(0, 20.5, 0)
162 local walls = workspace:FindPartsInRegion3(Region3.new(wallPos - size, wallPos + size))
163 local wall = walls[1]
164 if wall then
165 if i == 1 then
166 wall1 = true
167 elseif i == 2 then
168 wall2 = true
169 elseif i == 3 then
170 wall3 = true
171 elseif i == 4 then
172 wall4 = true
173 end
174 end
175 end
176 end
177 if wall1 or wall2 or wall3 or wall4 then
178 return true
179 else
180 return false
181 end
182end
183
184function getGroup(CCell) --so we may change the groups serial
185 local sTable = {}
186 for i=1, #cells do
187 local id = CCell.IDChip
188 local id2 = cells[i].IDChip
189 if id.Value == id2.Value then
190 table.insert(sTable,#sTable+1,cells[i])
191 end
192 end
193 return sTable
194end
195
196function breakWall(cell1, cell2)
197 local wallPos = ((cell1.Position + cell2.Position)/2) + Vector3.new(0, 20.5, 0)
198 local walls = workspace:FindPartsInRegion3(Region3.new(wallPos - size, wallPos + size))
199 local wall = walls[1]
200 if wall and wall.Name == "Wall" then
201 wall:Destroy()
202 local group = getGroup(cell2)
203 for i=1, #group do
204 local cellI = group[i]
205 local id = cellI.IDChip
206 id.Value = cell1.IDChip.Value
207 end
208 end
209end
210
211function randomCell() --choose a new cell
212 local r = math.random(1,#cells)
213 local c = cells[r]
214 return c
215end
216
217function mazeGenerate()
218 local cell = cells[1] --incase the begining choice doesnt work
219 while numDifSerials() > 2 do
220 cell = randomCell()
221 local IDC = cell.IDChip
222 local directions = {Vector3.new(20,0,0),Vector3.new(-20,0,0),Vector3.new(0,0,20),Vector3.new(0,0,-20)}
223 local newCell = nil
224 while (not newCell) and (#directions > 0) do --find our new cell
225 local choice = math.random(1, #directions)
226 newCell = findCell(cell, directions[choice])
227 local idN = nil
228 if closeWalls(cell) then --if the cell is a 4-way; makes it marginally quicker
229 else
230
231 local pos = cell.CreationNum.Value--remove this to get rid of stand-alone pillars--
232 table.remove(cells, pos)--remove this to get rid of stand-alone pillars--
233 cell = randomCell()
234 newCell = nil
235 break
236
237 end
238 if not newCell then --if cell no exist
239
240 if #directions == 1 then--remove this to get rid of stand-alone pillars--
241 local pos = cell.CreationNum.Value--remove this to get rid of stand-alone pillars--
242 newCell = nil--remove this to get rid of stand-alone pillars--
243 cell = randomCell()--remove this to get rid of stand-alone pillars--
244 table.remove(cells, pos)--remove this to get rid of stand-alone pillars--
245 table.remove(directions, choice)--remove this to get rid of stand-alone pillars--
246 break--remove this to get rid of stand-alone pillars--
247 end--remove this to get rid of stand-alone pillars--
248
249 table.remove(directions, choice)
250 else
251 idN = newCell.IDChip
252 end
253 if idN then --if it exists
254 if idN.Value == IDC.Value then
255 table.remove(directions, choice)
256 newCell = nil
257 end
258 else
259 newCell = nil
260 end
261 pause()
262 end
263 if newCell then
264 breakWall(cell,newCell)
265 end
266 pause()
267 end
268 print("Kruskal maze completed!")
269 --for i=1, #cells do
270 -- local id = cells[i].IDChip
271 -- print("Serial number that conquered all: "..id.Value)
272 --end
273end
274
275local event = game.ReplicatedStorage.RemoteEvents.PlayerSpeaks
276
277local creating = false
278event.OnServerEvent:Connect(function(player, pass)
279 if pass == "MakeMaze" and creating == false then
280 creating = true
281 createMaze()
282 wait()
283 mazeGenerate()
284 creating = false
285 end
286end)