I have been trying to achieve procedural generation à la The Binding of Isaac. I have never successfully created any procedural generation algorithm before so this is new territory for me.
The way I tried to re-create this is this way
Where the black cube with a red zero inside is the starting point where I would generate a room depending on the random number generated from 0 to 3. These are representing directions as
0 is -z
1 is +x
2 is +z
3 is -z
These numbers are named after a bool value inside the model of the room to determine if the door is taken by another occupied room in that direction.
These bools instances also have an attribute to determine by which room they are each taken from.
From that logic would it work ? I’m clearly lost here and would like some advice thanks in advance
Here’s my script:
local SSS = game.ServerScriptService
local Rooms =game.Workspace.Rooms
local R0 = Rooms['0']
local rand
local RoomsTotal
local newRoom
local newPart
local ui = SSS:FindFirstChild('NumberRoom')
local function CreateRoom()
local uis = ui:Clone()
newRoom = Instance.new('Model')
newRoom.Name = tostring(#Rooms:GetChildren())
-- [[ Attributes
local p0 = Instance.new('BoolValue')
local p1 = Instance.new('BoolValue')
local p2 = Instance.new('BoolValue')
local p3 = Instance.new('BoolValue')
p0:SetAttribute('RoomAssociatedWith', nil)
p1:SetAttribute('RoomAssociatedWith', nil)
p2:SetAttribute('RoomAssociatedWith', nil)
p3:SetAttribute('RoomAssociatedWith', nil)
p0.Name = '0'
p1.Name = '1'
p2.Name = '2'
p3.Name = '3'
p0.Parent = newRoom
p1.Parent = newRoom
p2.Parent = newRoom
p3.Parent = newRoom
--]]
newRoom.Parent = Rooms
newPart = Instance.new('Part')
newPart.Size = R0.Room.Size
newPart.Anchored = true
newPart.Name = "Room"
newPart.Parent = newRoom
uis.Parent = newPart
uis:FindFirstChild('RoomNumber').Text = #Rooms:GetChildren() - 1
return newRoom
end
local function AbortOperation(room)
for v,i in ipairs(Rooms:GetChildren()) do
if i:FindFirstChild('Room').Position == room.Position and i.Name ~= room.Parent.Name then
warn(room.Parent)
return true
end
continue
end
return false
end
local function AbortIfDoesntRespectDoorLimit(room, numberOfDoorAllowed)
--local count = 0
--if room then
-- for v,i in ipairs(Rooms:GetChildren()) do
-- if i:FindFirstChild('Room').Position == room.Position + Vector3.new(-10,0,0) or
-- i:FindFirstChild('Room').Position == room.Position + Vector3.new(10,0,0) or
-- i:FindFirstChild('Room').Position == room.Position + Vector3.new(0,0,10) or
-- i:FindFirstChild('Room').Position == room.Position + Vector3.new(0,0,-10)
-- then
-- count += 1
-- end
-- if count > numberOfDoorAllowed then
-- return true
-- end
-- end
--end
--return false
end
local function SetRoom(RoomSelected, rand, doorAllowed)
local TheNewRoom = CreateRoom()
--print("No room there")
warn('Creating a room at ' .. tostring(rand) .. ' door. On the room labeled ' .. RoomSelected.Name)
local DoorTakenFromSelected = RoomSelected:FindFirstChild(tostring(rand))
DoorTakenFromSelected.Value = true
local DoorTakenFromNewRoom
if rand == 0 then DoorTakenFromNewRoom = TheNewRoom:FindFirstChild('2') end
if rand == 1 then DoorTakenFromNewRoom = TheNewRoom:FindFirstChild('3') end
if rand == 2 then DoorTakenFromNewRoom = TheNewRoom:FindFirstChild('0') end
if rand == 3 then DoorTakenFromNewRoom = TheNewRoom:FindFirstChild('1') end
DoorTakenFromNewRoom.Value = true
--if AbortIfDoesntRespectDoorLimit(TheNewRoom:FindFirstChild('Room'), doorAllowed) then TheNewRoom:Destroy() end
if DoorTakenFromSelected.Name == '0' then TheNewRoom:FindFirstChild('Room').Position = RoomSelected:FindFirstChild('Room').Position + Vector3.new(0,0,-10) end
if DoorTakenFromSelected.Name == '1' then TheNewRoom:FindFirstChild('Room').Position = RoomSelected:FindFirstChild('Room').Position + Vector3.new(10,0,0) end
if DoorTakenFromSelected.Name == '2' then TheNewRoom:FindFirstChild('Room').Position = RoomSelected:FindFirstChild('Room').Position + Vector3.new(0,0,10) end
if DoorTakenFromSelected.Name == '3' then TheNewRoom:FindFirstChild('Room').Position = RoomSelected:FindFirstChild('Room').Position + Vector3.new(-10,0,0) end
if AbortOperation(TheNewRoom:FindFirstChild('Room')) then TheNewRoom:Destroy() end
if TheNewRoom then
DoorTakenFromSelected:SetAttribute('RoomAssociatedWith', TheNewRoom.Name)
DoorTakenFromNewRoom:SetAttribute('RoomAssociatedWith', RoomSelected.Name)
else
end
--Have to redo the set room as a whole doesnt work have to check every instance near the part to check i a room is there ? dunno sob
--for v,i in ipairs(Rooms:GetChildren()) do
-- if i:FindFirstChild('Room').Position == TheNewRoom:FindFirstChild('Room').Position + Vector3.new(-10,0,0) and i['3'] then
-- end
--end
--if AbortIfDoesntRespectDoorLimit(TheNewRoom:FindFirstChild('Room'), doorAllowed) then TheNewRoom:Destroy() end
end
local function Main()
newPart = nil
newRoom = nil
rand = math.random(0,3)
RoomsTotal = math.random(0,25)
while not Rooms:FindFirstChild(tostring(RoomsTotal)) do
warn('Trying Step #1')
RoomsTotal = math.random(0,25)
end
if #Rooms:GetChildren() <= 50 then
local RoomSelected = nil
if Rooms:FindFirstChild(tostring(RoomsTotal)) then
RoomSelected = Rooms:FindFirstChild(tostring(RoomsTotal))
end
if RoomSelected and RoomSelected:FindFirstChild(tostring(rand)).Value == false then
local doorAllowed = math.random(1 , 2)
-- 1 -> 2 room available
-- 2 -> 3 room available
local count = 0
for v,i in ipairs(RoomSelected:GetChildren()) do
if i:IsA('BoolValue') and i.Value == true then
count += 1
end
end
if count < 2 and (doorAllowed == 1) then
SetRoom(RoomSelected, rand, doorAllowed)
end
if count < 3 and (doorAllowed == 2) then
SetRoom(RoomSelected, rand, doorAllowed)
end
end
else
return false
end
end
while true do
while Main() ~= false do
task.wait()
end
task.wait(2)
for v,i in ipairs(Rooms:GetChildren()) do
if i.Name ~= '0' then
i:Destroy()
end
end
Rooms['0']['0'].Value = false
Rooms['0']['1'].Value = false
Rooms['0']['2'].Value = false
Rooms['0']['3'].Value = false
end
Sorry for ugly code I’m testing if it would work before optimizing anything