Best way of detecting the linked objects between two objects

This may seem a little hazy, but bear with me while I explain.

Essentially, I want to create a signaling system in which the player may choose two signals and a script would identify any equipment that connects the first and final signals.

Here’s what I’ve got thus far:

local stationequipment = {}

for i,v in pairs(script.Parent.Signals:GetChildren()) do
	local object = v:FindFirstChild("LinkedEquipment")

	if object then

		stationequipment[v.Name] = {
			["Name"] = v.Name,
			["Icon"] = v,
			["Object"] = object.Value,
			["SpecialObjectType"] = v.EquipmentType.SignalType.Value,
			["Type"] = "Signal",
			["linkedEquipment"] = {
				["signals"] = {},
				["switches"] = {},
			},
			["tracks"] = {}
		}

		local linkingEquipmentFolder = v:FindFirstChild("LinkingEquipment")

		if linkingEquipmentFolder then
			for _,p in pairs(linkingEquipmentFolder:GetChildren()) do
				for equipmentindex, equipment in pairs(p:GetChildren()) do
					if p.Name == "Signals" then
						table.insert(stationequipment[v.Name]["linkedEquipment"]["signals"], equipment.Value)
					elseif p.Name == "Tracks" then
						table.insert(stationequipment[v.Name]["tracks"], equipment.Value)
					elseif p.Name == "Switches" then
						table.insert(stationequipment[v.Name]["linkedEquipment"]["switches"], equipment.Value)
					end
				end
			end	
		end
	end
end

for i,v in pairs(script.Parent.Switches:GetChildren()) do
	local object = v:FindFirstChild("LinkedEquipment")

	if object then
		stationequipment[v.Name] = {
			["Name"] = v.Name,
			["Icon"] = v,
			["Object"] = object.Value,
			["SpecialObjectType"] = v.EquipmentType.SwitchType.Value,
			["Type"] = "Switch",
			["linkedEquipment"] = {
				["signals"] = {},
				["switches"] = {},
			},
			["tracks"] = {}
		}

		local linkingEquipmentFolder = v:FindFirstChild("LinkingEquipment")

		if linkingEquipmentFolder then
			for _,p in pairs(linkingEquipmentFolder:GetChildren()) do
				for equipmentindex, equipment in pairs(p:GetChildren()) do
					if p.Name == "Signals" then
						table.insert(stationequipment[v.Name]["linkedEquipment"]["signals"], equipment.Value)
					elseif p.Name == "Tracks" then
						table.insert(stationequipment[v.Name]["tracks"], equipment.Value)
					elseif p.Name == "Switches" then
						table.insert(stationequipment[v.Name]["linkedEquipment"]["switches"], equipment.Value)
					end
				end
			end	
		end
	end
end

local function calculateRoute(first_input, second_input, preset)
	local first_signal_object = stationequipment[first_input]
	local second_signal_object = stationequipment[second_input]

	local loopingThroughEquipment = first_signal_object

	local foundAPath = false

	for i,v in pairs(stationequipment[first_input]["linkedEquipment"]) do
		for _,p in pairs(v) do
			local loopingThroughEquipment = p

			repeat
				for k,q in pairs(stationequipment[loopingThroughEquipment]["linkedEquipment"]) do
					for e,w in pairs(q) do
						if w == second_input then
							print("found it")
							foundAPath = true
						else
							loopingThroughEquipment = w
						end
					end
				end
				wait()
			until foundAPath == true
		end
	end

end

local signalsSelected = 0
local firstSignalSelected = "N/A"

for index, value in pairs(stationequipment) do
	if value["Type"] == "Signal" then
		value.Icon.MouseButton1Click:Connect(function()
			if firstSignalSelected ~= value.Name then
				signalsSelected = signalsSelected + 1
				if signalsSelected == 1 then
					value.Icon.BorderSizePixel = 5
					firstSignalSelected = value.Name
				elseif signalsSelected == 2 then
					value.Icon.BorderSizePixel = 5
					if stationequipment[firstSignalSelected]["SpecialObjectType"] ==	"ENTRY" then
						if value["SpecialObjectType"] == "DEP" then
							calculateRoute(firstSignalSelected, value.Name, "station_entrance")
						end
					end
					signalsSelected = 0
					firstSignalSelected = "N/A"
				end
			else
				displayError("You can't select the same signal twice.")
			end
		end)
	end
end

The issue appears to be with the ‘calculateRoute’ function, since it only accepts the initial indices and eventually gets stopped at one piece of equipment.

If anyone has a suggestion, please share it with me; I would really appreciate it!

This is pretty complicated and probably needs some kind of diagram to explain how it should work.

image

Posting an example

Each signal and switch is saved in the stationequipment table.

Every equipment is linked to another piece of equipment (signal1 is linked to switch1, switch1 is linked to signal2 and switch2, switch2 is linked to signal3 and signal4).

The way the system should work is: I select signal1, then either signal2, signal3 or signal4 and the script should find every switch and signal between these two signals.

Do your “lines” connecting signals through switches have a single direction, as in they are not bi-directional? This is important because it can make the problem much easier. Also, can your system contain loops, such as a connection between the black line where signal2 is and the line under signal1?

If your system contains links with only one direction and there are no loops, then your problem contains what is known as a DAG and you have many search algorithms available that will do the job, such as a Depth First Search. If not, the problem is significantly harder and you’ll have to use a reliable shortest path finding algorithm such as Dijkstra’s Algorithm