Currently having issues with procedural generation

There’s probably some hacky solution to this, but I’m looking for the most optimal solution to this issue.

I have a maze system which generates a maze by branching off of each hallways exit points by choosing a turn, straight hall, or junction (T Hall).

After the generation is complete, the system chooses the furthest hallway model from the spawn, and then sets it to the exit. (Evil, I know.)

I am trying to make this less evil by adding hints to where to go, however that is where my issue lies. I’m not sure how to add hints in the direction of the exit without having it preset, which I don’t want to do.

This probably has some easy solution for it, but I’m not perfect.

Anyways, I have already attempted to use pathfinding (Yes, I know, super hacky solution), and it barely functions 3% of the time. other 97% it just NoPaths. (Have already tried clearing the pathway to the best of my ability, to no avail.)

Any help appreciated, and will be credited during the end credits.

Bumping post since I need an answer 2 this

Bumping post again. Still looking for answers.

How do you even generate the maze? Can’t you just put hints while checking for the longest path or something?

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.