Currently having issues with procedural generation

I stated how in the post.

And no I can’t. It isn’t a straight line.

Generation Example:

It will check all of these different positions if they’re further away than the last check.

Meaning if I try to generate while doing that it will add hints to random positions around the map and lead the player in circles, which I don’t want to do. By hints I mean subtle things that point the player in the correct direction, for example an arrow or some footprints on the floor, both would of course be facing towards the end of the maze.

Don’t you have something like a hitbox for a chunk of section you copy and paste? And why don’t you like store all the informations on a table and get the path for exit then place the hints?

I don’t get what you mean. If you mean making huge trees out of the branchdata then I’m not sure I’m going to do that.

No, well you do clone a model from somewhere and place it on workspace.

Just when you place your rooms you probs know if the room/hall has ended or if it continues and you also have defined the exit so you probs know the hall where the exit.

So what I am saying is when. Ever you place these halls why not store some infos in a table like ‘exit’, ‘ended’, ‘connected halls’ and seek for the path from that? Unless this is what u meant by making a huge tree.

I see what you are saying but the exit position is not predetermined. The exit is placed after the halls are generated. I see how you’re saying to link hallways to each other if they are connected, and I could try this, however it might become quite the large table due to the sheer size of the generation I am doing.

You can always shrink the table by eliminating ended hallways that you don’t need or some sort but also you should be able to just edit the table if it has an exit or not once you place the exit.

Keep in mind I am using junctions which have two separate possible links, However those are a lot rarer than the other variations due to there only being one variation, when the other halltypes have multiple variations.

Give me a moment to try this out.

Edit: Intellisense broke. This is going to take a bit longer than expected.

First off, how is a hint going to be displayed? Does each room have an arrow in it? Is there a sign in each room?

Currently dealing with intellisense suddenly deciding not to autofill even after setting reset and reinstall.

(No, it will pick a random hallway through the DataTree I’m trying to get working right now, but as said previously intellisense is being difficult.)

Would it be possible to just

  • Generate the maze
  • Pathfind for the optimal path
  • Get the model where each point is located
  • Pick random points where you will place your hints and put them in a table
  • Load your hints at around each point in the table
    I haven’t scripted in a while and I’m not good at pathfinding whatsoever so I won’t be able to just give the code

Please read the post closer before responding. I have already attempted to use pathfinding to no avail.

Pathfinding has always been finnicky and I have attempted using many different methods to fix this over the span of 6 hours.
Never managed to fix it.

Once I fix my Intellisense Autocomplete I’m going to test Currently having issues with procedural generation - #10 by MilkyFiend

Either I’m doing this extremely wrong or this is quite hard to accomplish.

I’m creating this tree and it works fine until the junctions are introduced, as I stated they may be an issue.

I’ve been researching procedural generation for the better part of a year. It’s very challenging. But here’s what I’d do:

You have your nodes, so you can calculate how far away a node is from the exit. Then you can just decide, if a node is X nodes away from the exit, place a sign.

Uh, the issue right now is that I can’t get these nodes you speak of since my table layout’s loader for some reason stops working after a junction is hit.
If I manage to figure that out then I should be able to easily do the rest.

If you want I can DM you the functions used for generation
(So you can better understand what’s going on in the backend, I don’t want to send it here as I plan to use this system in a fully fledged game.)

So it’s a data problem. You’re using T-junctions. That means you can store your data as a ‘Binary Search Tree’. From there, it’s not so difficult to find things like distances.

Here’s some of my old code. Use at own risk

--[[
local TreeNode = require(game.ReplicatedStorage["N-ary tree"])
-- Example usage
local root = TreeNode.new("Root")
local child1 = TreeNode.new("Child 1")
local child2 = TreeNode.new("Child 2")
local child3 = TreeNode.new("Child 3")
local child4 = TreeNode.new("Child 4")
local child5 = TreeNode.new("Child 5")

root:addChild(child1)
root:addChild(child2)
child1:addChild(child3)
child3:addChild(child4)
child2:addChild(child5)

-- Perform tree traversal
print("Preorder Traversal:")
root:preorderTraversal()

print("Postorder Traversal:")
root:postorderTraversal()

root:levelOrderTraversal()
]]

-- Define a basic N-ary tree node structure
local TreeNode = {}
TreeNode.__index = TreeNode

function TreeNode.new(value)
	local self = setmetatable({}, TreeNode)
	self.value = value
	self.children = {}
	return self
end

function TreeNode:addChild(childNode)
	table.insert(self.children, childNode)
end

-- Tree traversal functions with indentation
function TreeNode:preorderTraversal(indent)
	indent = indent or 0
	print(string.rep("  ", indent) .. self.value) -- Indent based on depth
	for _, child in ipairs(self.children) do
		child:preorderTraversal(indent + 1)
	end
end

function TreeNode:postorderTraversal(indent)
	indent = indent or 0
	for _, child in ipairs(self.children) do
		child:postorderTraversal(indent + 1)
	end
	print(string.rep("  ", indent) .. self.value) -- Indent based on depth
end

-- Method to count the number of children for a node
function TreeNode:getChildCount()
	return #self.children
end

-- Method to check if a node is a leaf (has no children)
function TreeNode:isLeaf()
	return #self.children == 0
end

-- Method to check if a node is the root of the tree
function TreeNode:isRoot()
	return not self.parent
end

-- Method to get the depth of a node in the tree
function TreeNode:getDepth()
	if not self.parent then
		return 0
	else
		return 1 + self.parent:getDepth()
	end
end

-- Method to find a node with a specific value in the tree
function TreeNode:findNode(targetValue)
	if self.value == targetValue then
		return self
	else
		for _, child in ipairs(self.children) do
			local result = child:findNode(targetValue)
			if result then
				return result
			end
		end
		return nil
	end
end

-- Method to remove a child node from the current node
function TreeNode:removeChild(childNode)
	for i, child in ipairs(self.children) do
		if child == childNode then
			table.remove(self.children, i)
			childNode.parent = nil -- Clear the parent reference for the removed child
			return true -- Child node removed successfully
		end
	end
	return false -- Child node not found
end

-- Level order traversal with level information
function TreeNode:levelOrderTraversal()
	local queue = {{self, 0}} -- Initialize the queue with the root node and its level

	while #queue > 0 do
		local currentEntry = table.remove(queue, 1)
		local current = currentEntry[1]
		local level = currentEntry[2]

		print("Level " .. level .. ": " .. current.value) -- Print level and value

		for _, child in ipairs(current.children) do
			table.insert(queue, {child, level + 1}) -- Enqueue child nodes with increased level
		end
	end
end

return TreeNode

At this point I just plan on giving up, I’ve been too out of it recently to be trying to get this one stupid feature to work for 13 hours.

Appreciate the help. I’ll try this when I decide to pick this back up again.

If I were you I’d get to the root of the issue. I wouldn’t leaf it alone. Just gotta tree again.

You are correct, I do sort of need this done soon, but if you’re going to help it’d be better if we moved to messages instead since messages are more confidential than public topics. (Obviously)

As I keep kinda hinting at throughout this entire thread, I don’t want to leak any of my server stuff.

1 Like

While this is way above my script knowledge, a couple of things come to mind which may help you do this. Firstly, when you create the maze, I’m assuming you’re using objects from some kind of storage. Perhaps make an alternate model that has arrows or hints that you can randomly place using some kind of random number generator when it’s being formed.

The other idea which I feel is way more complicated is once the maze is done (and before the player has control of their character) use the pathfinding service to create a path (similar to an NPC find its way) from the start to the finish and count the number of path points into an array. Then find the position of that point and the cframe of whatever it’s spawned on and replace that part of the model with a new model containing the hints.

I do apologize if I completely missed the point.

For anyone who needs to do something like this, what I did is I made a table which spawns 2 entry tables and passes them to a function.

In that function, it generates the hallways and puts the hallway assets under this entry table. Once the script reaches a T-Junction, it creates a new entry table under the first entry table and passes that to the same function, effectively creating a loop and DataTree you can iterate through to get the path to the exit.

To avoid it going to dead ends, you can have the iterate function to get the path to the end check if a hallway its iterating through abruptly ends without reaching the exit designation.

You can redo this every time you reach an entry table.

(P.S. Thank you Exercitus for the inspiration for this method with his N-ary module.)