Hwo to detect if 2 train stops are connected?

Place to get help with not working mods / modding interface.
Post Reply
mrvn
Smart Inserter
Smart Inserter
Posts: 5710
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Hwo to detect if 2 train stops are connected?

Post by mrvn »

Is there a simple way to detect if 2 train stops are on the same rail network? Is there something like a rail-network-id like there is for signal networks that I can compare?

The only idea I have to test if 2 train stops are connected would be to place a train at the first stop, set a schedule and then check train.has_path. That has all sorts of special cases like there already being a train at the first stop or having multiple stops with the same name and and and .... So not ideal if it works at all. Is the path even generated when I set a schedule or do I have to wait 1 tick for the game engine to actually process the train? So before I try this rather complex way I wonder if there is some simpler way I'm missing.

In my use case I want to know if the train stops are connected by rails ignoring all signals. If they are connected but there isn't actually a path from one to the other due to signals I would still want to say they are connected. Would I have to manually search through all the connected segments/blocks to find a path myself?

User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 2252
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: Hwo to detect if 2 train stops are connected?

Post by boskid »

Unfortunately there are no ways to check that. The closest data we have internally are rail blocks and rail segments but traversal of those data is expensive. Direct answer from the game engine would require implementing trains pathfinder lua API to allow lua to perform direct queries of paths between 2 rails, that would be a modding interface request which would need a separate discussion because of amount of input and output variables that would make this api expensive to query and expensive to push results.

Questions about rail network topology are in various ways tricky, fortunately you specified your condition precisely: you want to find of one stop is accessible from position of another train stop, however there are various rail network structures where using rail blocks could give you a completly useless answer just because we may have 2 rails crossing each other while being part of different "rail networks": in terms of paths they are separate networks unless there are external rails connecting them, but in terms of rails blocks they are both required to be part of same rail block and could be considered part of same rail network.

mrvn
Smart Inserter
Smart Inserter
Posts: 5710
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: How to detect if 2 train stops are connected?

Post by mrvn »

My initial problem is a map with islands. Trains on island A simply can't get to island B and then you have to be careful with setting the network ID unique for each island with LTN so it doesn't try to deliver goods across the ocean. And there are only 32 bits for the network ID limiting one to 32 islands at most before things break down.

I didn't consider rail crossings between different networks. But obviously that is a possibility in a non-island scenario.

I think it would be good if rails had a network ID where the network ID is the same on any 2 rails that are connected in a way a train drives. They are not connected by one rail crossing the other at an angle. A single rail block could have rails from different networks inside. I don't think the rail block code has to look at or interact with the network ID at all so this should not be a problem. This would make the API simple too as it would be exactly one read only variable to query.

Should also be somewhat CPU inexpensive. Placing a rail potentially merges 2 networks, remapping one of them to the other. That's a simple graph traversal. Removing can split a network and would require a traversal to check if the two sides connected to the removed rails remain connected some other way followed by a graph traversal to give one half a new ID. The first traversal could reuse the path finding code but ignores signals.

Even better this could be done lazy. When accessed compute the value and store it. When merging / splitting check if the rail even has a network ID and maybe erase it on split. This would then require an API function to query the rail network ID instead of a read only variable.

Do you think such a feature would be possible? Seems straight forward enough to implement but only useful for mods the generate train schedules like ĹTN.

computeraddict
Fast Inserter
Fast Inserter
Posts: 112
Joined: Sat Oct 07, 2023 6:44 am
Contact:

Re: How to detect if 2 train stops are connected?

Post by computeraddict »

mrvn wrote:
Tue Dec 05, 2023 8:42 pm
And there are only 32 bits for the network ID limiting one to 32 islands at most before things break down.
I haven't used LTN, but 32 bits should allow for 2^32 networks, no?

mrvn
Smart Inserter
Smart Inserter
Posts: 5710
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: How to detect if 2 train stops are connected?

Post by mrvn »

computeraddict wrote:
Tue Dec 05, 2023 11:27 pm
mrvn wrote:
Tue Dec 05, 2023 8:42 pm
And there are only 32 bits for the network ID limiting one to 32 islands at most before things break down.
I haven't used LTN, but 32 bits should allow for 2^32 networks, no?
It's a bitmask. Usually you have one large connected network and you use the network ID to split that into overlapping sub networks. The network ID is a bitmask so you can have stations in multiple networks. And since it's circuit controlled this gives you great flexibility.

It's kind of hard to find a use case in vanilla but with mods you sometimes have recipes that have side products that you have to get rid off. Say for example a recipe gives coal as a side product. Some coal you can use to make plastic. But if you end up with too much coal the factory would stop working. So what you do is set the network ID for the coal provider (and all other stops really) to not 1 (lowest bit clear). You then add a decider combinator "coal > 100000 ===> Network ID 1" and connect that to the train stop. Last you build a request station asking for coal with network ID 1 that burns the coal for fuel in your smelter. That way you never burn coal from the coal mines or when you don't drown in coal.

You can setup the same for solid fuel giving you a second fuel source in case you have more oil than you use up. Last you can also set up the smelter to switch to network ID 3 when they run low on fuel. Now suddenly they will request any fuel they can get their hand on and not just fuel you have too much of.

User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 2252
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: Hwo to detect if 2 train stops are connected?

Post by boskid »

Given that trains pathfinder API was implemented (https://lua-api.factorio.com/latest/cla ... train_path) which is available in current stable version of 1.1.x i think this can be solved now quite easily: using trains pathfinder API, check if from one train stop position there is a path to another train stop position.

Post Reply

Return to “Modding help”