How can i improve my "endless" corridor generation script?

Hello! I always wanted to make a randomly generated terrain/map type of thing, so i decided to make an “infinitely expanding” corridor that is never the same. And i managed to do it, but it’s difficult to introduce new corridor sections to the script.

-- this number is the default length of each corridor section. There's 2 of them to generate corridor to both sides.
numbera = -44.4
numberb = 44.4
 
 
-- There's one Number Range for every section of corridor. RNG determines which corridor section to use with these
nran1 = NumberRange.new(0,15)
nran2 = NumberRange.new(16,30)
nran3 = NumberRange.new(31,45)
nran4 = NumberRange.new(46,60)
nran5 = NumberRange.new(61,75)
nran6 = NumberRange.new(76,90)
nran7 = NumberRange.new(91,105)
nran8 = NumberRange.new(106,120)
nran9 = NumberRange.new(121,135)
 
-- here it generates a random number every time this function runs, and depending on the number generated it places the next corridor section.
local function makeCorridor()
    local rn = math.random(1,130)
    if rn >= nran1.Min and rn <= nran1.Max then
        local path = game.ReplicatedStorage:WaitForChild("C1"):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild("C1"):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        -- Here it offsets the path from the starting corridor
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        -- Here it does the same for the opposite side of the corridor.
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        -- here it increases the distance to offset from the main corridor part by the length of one corridor section to make up for it.
        numberb = numberb + 44.4
        numbera = numbera - 44.4
    elseif rn >= nran2.Min and rn <= nran2.Max then
        local path = game.ReplicatedStorage:WaitForChild("C2"):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild("C2"):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        numberb = numberb + 44.4
        numbera = numbera - 44.4
    elseif rn >= nran3.Min and rn <= nran3.Max then
        local path = game.ReplicatedStorage:WaitForChild("C3"):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild("C3"):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        numberb = numberb + 44.4
        numbera = numbera - 44.4
    elseif rn >= nran4.Min and rn <= nran4.Max then
        local path = game.ReplicatedStorage:WaitForChild("C4"):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild("C4"):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        numberb = numberb + 44.4
        numbera = numbera - 44.4
    elseif rn >= nran5.Min and rn <= nran5.Max then
        local path = game.ReplicatedStorage:WaitForChild("C5"):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild("C5"):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        numberb = numberb + 44.4
        numbera = numbera - 44.4
    elseif rn >= nran6.Min and rn <= nran6.Max then
        local path = game.ReplicatedStorage:WaitForChild("C6"):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild("C6"):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        numberb = numberb + 44.4
        numbera = numbera - 44.4
        elseif rn >= nran4.Min and rn <= nran4.Max then
        local path = game.ReplicatedStorage:WaitForChild("C4"):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild("C4"):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        numberb = numberb + 44.4
        numbera = numbera - 44.4
    elseif rn >= nran5.Min and rn <= nran5.Max then
        local path = game.ReplicatedStorage:WaitForChild("C5"):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild("C5"):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        numberb = numberb + 44.4
        numbera = numbera - 44.4
    elseif rn >= nran6.Min and rn <= nran6.Max then
        local path = game.ReplicatedStorage:WaitForChild("C6"):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild("C6"):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        numberb = numberb + 44.4
        numbera = numbera - 44.4
    elseif rn >= nran7.Min and rn <= nran7.Max then
        local path = game.ReplicatedStorage:WaitForChild("C7"):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild("C7"):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        numberb = numberb + 44.4
        numbera = numbera - 44.4
    elseif rn >= nran8.Min and rn <= nran8.Max then
        local path = game.ReplicatedStorage:WaitForChild("C8"):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild("C8"):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        numberb = numberb + 44.4
        numbera = numbera - 44.4
    elseif rn >= nran9.Min and rn <= nran9.Max then
        local path = game.ReplicatedStorage:WaitForChild("C9"):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild("C9"):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        numberb = numberb + 44.4
        numbera = numbera - 44.4
    end
end
 
-- here it loops the function 1000 times.
for i = 1, 1000 do
    makeCorridor()
    wait()
end

I had a couple ideas to improve the code a little bit, like;

  • Instead of using the numbera and numberb in the script the way i do, i could save the last corridors position, and offset the next corridor from that position.
  • Using modules to avoid re-using the same elseif statement with small changes every time i introduce a new corridor section. But i never used modules before so i couldn’t really think of a way to get it to work.

how could i make this more modular? and possibly remove the if statement spam?

so first thing I see is oh god the copy and paste with the if else statements.

The first and most simple thing that you can do is to use functions

local numbera = -44.4
local numberb = 44.4

local function generate(PathName)
        local path = game.ReplicatedStorage:WaitForChild(PathName):Clone()
        local path2 = game.ReplicatedStorage:WaitForChild(PathName):Clone()
        path2.Parent = workspace.Pagmanning
        path2.Name = "Path"
        path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
        path.Parent = workspace.Pagmanning
        path.Name = "Path"
        path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
        numberb = numberb + 44.4
        numbera = numbera - 44.4
end

local function makeCorridor()
    local rn = math.random(1,130)
    if rn >= nran1.Min and rn <= nran1.Max then
        generate("C1")
    elseif rn >= nran2.Min and rn <= nran2.Max then
        generate("C2")
    -- keeps going on
end

This will simplify things a lot, but if you want to make it more modular, I would suggest using loops and tables.

local range = {
    NumberRange.new(0,15),
    NumberRange.new(16,30),
    NumberRange.new(31,45)
    -- more number ranges
}

local function makeCorridor()
    local rn = math.random(1,130)
    for i, nran in ipairs(range) do -- goes through the range table above
         if rn >= nran1.Min and rn <= nran1.Max then
              generate("C"..i) -- i is the index, so numberrange(0,15) is 1
              -- numberRange(16, 30) is 2
              -- etc
         end
    end
end
2 Likes

Oh my god this is exactly what i was looking for, thank you so much. Didn’t know i could do it this way. this will save me alot of headache and time, and make it way easier to introduce new sections.

Here’s how i implemented it

local numbera = -44.4
local numberb = 44.4

nran1 = NumberRange.new(0,15)
nran2 = NumberRange.new(16,30)
nran3 = NumberRange.new(31,45)
nran4 = NumberRange.new(46,60)
nran5 = NumberRange.new(61,75)
nran6 = NumberRange.new(76,90)
nran7 = NumberRange.new(91,105)
nran8 = NumberRange.new(106,120)
nran9 = NumberRange.new(121,135)

local function generate(PathName)
	local path = game.ReplicatedStorage:WaitForChild(PathName):Clone()
	local path2 = game.ReplicatedStorage:WaitForChild(PathName):Clone()
	path2.Parent = workspace.Pagmanning
	path2.Name = "Path"
	path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
	path.Parent = workspace.Pagmanning
	path.Name = "Path"
	path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
	numberb = numberb + 44.4
	numbera = numbera - 44.4
end

local function makeCorridor()
	local rn = math.random(1,130)
	if rn >= nran1.Min and rn <= nran1.Max then
		generate("C1")
	elseif rn >= nran2.Min and rn <= nran2.Max then
		generate("C2")
	elseif rn >= nran2.Min and rn <= nran3.Max then
		generate("C3")
	elseif rn >= nran2.Min and rn <= nran4.Max then
		generate("C4")
	elseif rn >= nran2.Min and rn <= nran5.Max then
		generate("C5")
	elseif rn >= nran2.Min and rn <= nran6.Max then
		generate("C6")
	elseif rn >= nran2.Min and rn <= nran7.Max then
		generate("C7")
	elseif rn >= nran2.Min and rn <= nran8.Max then
		generate("C8")
	elseif rn >= nran2.Min and rn <= nran9.Max then
		generate("C9")
	end
end

for i = 1, 1000 do
	makeCorridor()
	wait()
end

Here’s the version with the tables.

local numbera = -44.4
local numberb = 44.4

local range = {
	NumberRange.new(0,15),
	NumberRange.new(16,30),
	NumberRange.new(31,45),
	NumberRange.new(46,60),
	NumberRange.new(61,75),
	NumberRange.new(76,90),
	NumberRange.new(91,105),
	NumberRange.new(106,120),
	NumberRange.new(121,135)
}

local function generate(PathName)
	local path = game.ReplicatedStorage:WaitForChild(PathName):Clone()
	local path2 = game.ReplicatedStorage:WaitForChild(PathName):Clone()
	path2.Parent = workspace.Pagmanning
	path2.Name = "Path"
	path2:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numbera))
	path.Parent = workspace.Pagmanning
	path.Name = "Path"
	path:SetPrimaryPartCFrame(workspace.C1:GetPrimaryPartCFrame() + Vector3.new(0, 0, numberb))
	numberb = numberb + 44.4
	numbera = numbera - 44.4
end

local function makeCorridor()
	local rn = math.random(1,135)
	for i, nran in ipairs(range) do
		if rn >= nran.Min and rn <= nran.Max then
			generate("C"..i)
		end
	end
end

for i = 1, 1000 do
	makeCorridor()
	wait()
end