Let's talk train design

Don't know how to use a machine? Looking for efficient setups? Stuck in a mission?
waterBear
Fast Inserter
Fast Inserter
Posts: 118
Joined: Thu Apr 23, 2020 2:05 pm
Contact:

Let's talk train design

Post by waterBear »

Here is something that's currently on my mind. We all want to build a logistic train system in vanilla. It sounded so easy in the FFF. Here's the problem: The natural way to do it with interrupts doesn't work with multiple provider stations. I think by now, all the train afficianados know the type of design I'm talking about. You have requester stations that put a request for X train loads of an item on the global (radar) circuit network, and provider stations open up based on that request. The trouble is that if you broadcast a need for 1 train load of red circuits, every red circuit provider turns on with a train limit of 1. Your logistic trains get deployed on the same tick and you end up with oversupply.

So I want to brain storm with people who know a lot about trains and the circuit network. Here are my current ideas, all of which are unsatisfying due to the included weaknesses.

- When a train arrives at a provider, have it double check demand levels before loading.
---- Weaknesses: Un-needed trains still get deployed. Some designs which are based on reducing requests by the C signal will briefly under-request while trains are leaving a provider and on the way to a requester, so additional delays may occasionally be introduced as trains are deployed, returned, and deployed again when the signal reappears.

- Have centralized deployment of trains from wait stations.
---- Reason: Allows for more complex logic in deployment of trains via complex combinator contraptions
---- Weaknesses: Trains can only be deployed from a wait station. During periods of high load, this will congest the train network further as trains are completing additional trips (back to the wait station). Also, adding a bunch of logic to determine how many trains to send increases complexity and thus makes the solution less maintainable and more brittle.

- Random assignment. When demand is positive, have providers randomly decide (by coin flip) whether to turn on. Only stop this procedure when the number of stations voting to enable equals the demand signal.
---- Weaknesses: Not sure I even have to state them. This is just a bad idea...but I had the idea, so I'm including it for completeness.

- Have centralized logic that determines which stations to turn on.
---- Weaknesses: How do you identify each individual station without a bunch of nasty circuit logic? I don't want to implement TDM or something just for my logistic train design.

- Round Robin activation. Let's say you have 2 providers of an item. Then station one sets its limit to (Demand+1 / 2) and station two sets it to (Demand / 2). So...for demand 1, station one has limit 1 and station 2 has limit 0. For demand 2, it's 1 and 1. For demand 3, it's 2 and 1. So on.
---- Reason: Simplicity. One additional combinator required at each provider.
---- Weaknesses: first of all you have an additional global variable to track (and update every time you add a stop!) which is the number of providers for an item type. This could be as simple as using an additional global signal of a different color. If you're broadcasting demand on red, broadcast the number of providers on green. The real issue is that you have to figure out how to deal with the situation when one of the stations is out of items or can't accept its assigned limit of trains. It needs additional logic to "put its assigned trains back on the global network" somehow. Once again, that means more combinators and more special cases that make it more fragile and harder to patch.

So. Please, if you are like me and like to think about trains and circuits, I'd love to hear your thoughts.
waterBear
Fast Inserter
Fast Inserter
Posts: 118
Joined: Thu Apr 23, 2020 2:05 pm
Contact:

Re: Let's talk train design

Post by waterBear »

New idea:

- Have a supply train attempt to go to the requester first. If destination not full, reroute to a supplier. If destination full, go to wait for some duration.
---- Reason: Even if 11 suppliers are open, only one train will dispatch if only one requester is open. The rest will fail the condition that destination not full.
---- Weaknesses: As soon as you re-route the pickup train to a supplier, the train limit at the requester is wrong. You will need to set that based on other global signals, probably by modulating global request via the C signal from the supply station. Also, this will require completely overhauling the train schedules and interrupts. Might be a total mess. Still brainstorming. (Also, there is at least 1 frame between train rerouting and global signal modulation from C on the supplier, so it's still possible that oversupply happens).
Tertius
Smart Inserter
Smart Inserter
Posts: 1430
Joined: Fri Mar 19, 2021 5:58 pm
Contact:

Re: Let's talk train design

Post by Tertius »

waterBear wrote: Wed Sep 24, 2025 12:53 pm Here is something that's currently on my mind. We all want to build a logistic train system in vanilla. It sounded so easy in the FFF. Here's the problem: The natural way to do it with interrupts doesn't work with multiple provider stations. I think by now, all the train afficianados know the type of design I'm talking about.
You talk about an inferior general approach that nobody has managed to implement flawlessly yet.
waterBear wrote: Wed Sep 24, 2025 12:53 pm You have requester stations that put a request for X train loads of an item on the global (radar) circuit network, and provider stations open up based on that request.
What's the reasoning behind this decision? Why do you want the station open just on request? Why don't you just keep the stations open all the time?

In case you're talking about trains that will always carry one type of material at a time and you have unloading stations dedicated to one material:

Set their train limit to 1 (or 2 with a waiting area to minimize latency) and employ enough trains, and you have trains in all of your provider stations. Some of them currently loading and some of them full and waiting to deliver their items. Now, as soon as some requester station needs a new train load of items, it "opens up" and one of the full trains is dispatched automatically and immediately and is satisfying this request. That's completely by the train mechanics of the game engine, no circuits involved.

This is the fastest possible delivery and totally reliable. This "opening up" of a requester station doesn't need to be circuit controlled. If it has a train limit of 1, the mere leaving of an empty train will "opening up" this station, since the one slot is free again and the next train will drive there.

This works 100% without circuits and 100% with static train limits. Adding a tiny circuit to manipulate priority for provider stations with limit 2 lowers the latency even more.

People think this static approach doesn't work, because they usually don't add enough trains. By this design every station is supposed to have at least 1 train, either being loaded or full, or being emptied.

This system is completed by adding a depot for empty trains, so any train getting empty on an unloading station is driving to the depot if all loading stations are full, so the unloading station is free again and the next full train is able to reserve a slot and drive there.

Name all loading stations the same, for example "load". Put the item icon into the name of each unloading station, so you can build the name with the cargo wildcard in an interrupt, for example "(green cargo wildcard) unload". All trains with the same layout have the same train group and all stations are built for this train layout, for example 1-4 (1 locomotive, 4 cargo wagons).

Static schedule entry:
go to "load"; "wait for full"

Interrupt:
condition: cargo (green cargo wildcard) > 0
destination: go to "(green cargo wildcard) unload"; "wait for empty"

Interrupt:
condition: no path or destination full AND empty cargo AND not at depot
option: allowed to interrupt other interrupts
destination: go to depot; inactivity 1s

All stations static train limit 1.

If you have 10 loading stations and 4 unloading stations, you need to have 10+4=14 trains and a depot with 4 depot stations.

If you have 10 loading stations with train limit 2 and 4 unloading stations with train limit 3, you need a waiting area for 1 train on each loading station and a waiting area for 2 trains per unloading station, and 10*2 + 4*3 = 32 trains and a depot with 4 depot stations.

In case you ever see trains waiting for a longer time in your depot stations, this is a sign you have not enough loading stations to satisfy the throughput demand.

I built this system now on 2 maps, and it works flawlessly. No maintenance. It just works. I used station train limit 2 everywhere. The only circuit I added is to reduce loading station priority to 49 in case a train has reserved a slot, so first empty stations are filled, and only after all stations have at least 1 train the 2nd slot will be filled.

What I describe is a direct implementation of fff-389 https://factorio.com/blog/post/fff-389 and fff-395 https://factorio.com/blog/post/fff-395
waterBear
Fast Inserter
Fast Inserter
Posts: 118
Joined: Thu Apr 23, 2020 2:05 pm
Contact:

Re: Let's talk train design

Post by waterBear »

Tertius wrote: Wed Sep 24, 2025 3:37 pm reply
What you describe is essentially the intended approach from the FFF. Their solution is really only intended to abstract away the train type and schedule and not be a "vanilla LTN".

However, in the FFF, they say that LTN is one of the things you can build with this system. I am interested in answering that question.

I do appreciate your response, but I'm not interested in "stop asking the wrong question" types of replies. If I'm at the stage of the game where I can even ask this question and enumerate the alternatives and their flaws, I am already aware of how to build the basic "bag of trains".

Edit to add: The mods moved this post to the help section from general discussion. I can get why that might cause confusion. I am not a noob trying to make trains work, but am trying to build a rather advanced and general (as you say) system.
Tertius
Smart Inserter
Smart Inserter
Posts: 1430
Joined: Fri Mar 19, 2021 5:58 pm
Contact:

Re: Let's talk train design

Post by Tertius »

waterBear wrote: Wed Sep 24, 2025 4:56 pm I do appreciate your response, but I'm not interested in "stop asking the wrong question" types of replies. If I'm at the stage of the game where I can even ask this question and enumerate the alternatives and their flaws, I am already aware of how to build the basic "bag of trains".
I didn't just ask "why" as a dismissive why, instead I'm genuinely interested in why you're following that approach. Why is that approach good?
I'm genuinely interested in your reasoning, because I'm at a loss with understanding what advantages your approach brings. I don't see them, so what is it? Every time I ask this question, people are unable to answer.
From the reasons and from the strengths of the approach we might be able to find a way to some design, but without reason we don't have a design goal.

I always thought people seek for efficient solutions, and with all your brainstorming with all their caveats and edge cases you found it's clear that approach isn't efficient, at least not with the tools we're given by the game engine. I tried to build a fully circuit controlled and micromanaged train system myself, started with a crystal clear design, promising implementation, but half way through I found so many tiny flaws and edge cases, it's just not feasible. Yes, with may be 100 global combinators and 20 per station. This made me think the opposite way: instead of micromanage everything, manage nothing. And suddenly it worked perfectly. This is the message I have: don't micromanage. Explore, understand and properly use the tools given by the game engine.
computeraddict
Filter Inserter
Filter Inserter
Posts: 389
Joined: Sat Oct 07, 2023 6:44 am
Contact:

Re: Let's talk train design

Post by computeraddict »

Tertius wrote: Wed Sep 24, 2025 5:18 pm From the reasons and from the strengths of the approach we might be able to find a way to some design, but without reason we don't have a design goal.
Not OP, but perhaps it's minimizing number of items in flight?
robot256
Smart Inserter
Smart Inserter
Posts: 1274
Joined: Sun Mar 17, 2019 1:52 am
Contact:

Re: Let's talk train design

Post by robot256 »

I re-read the FFFs and didn't see where they mention LTN specifically. The idea that interrupts can *replace* LTN in a working factory was the immediate reaction to those blog posts. But the community has been trying for a year and a half to *replicate* LTN with interrupts alone and largely failed, through no fault of their own. The interrupt system as it was ultimately implemented has certain limitations, and I'm pretty sure you can logically prove that replicating LTN behavior exactly is impossible without circuits.

These posters claim to have actually replicated LTN by combining circuits and interrupts:
viewtopic.php?t=117777
viewtopic.php?f=194&t=117459
My mods: Multiple Unit Train Control, RGB Pipes, Shipping Containers, Rocket Log, Smart Artillery Wagons.
Maintainer of Auto Deconstruct, Cargo Ships, Vehicle Wagon, Honk, Shortwave.
waterBear
Fast Inserter
Fast Inserter
Posts: 118
Joined: Thu Apr 23, 2020 2:05 pm
Contact:

Re: Let's talk train design

Post by waterBear »

robot256 wrote: Wed Sep 24, 2025 5:32 pm I re-read the FFFs and didn't see where they mention LTN specifically. The idea that interrupts can *replace* LTN in a working factory was the immediate reaction to those blog posts. But the community has been trying for a year and a half to *replicate* LTN with interrupts alone and largely failed, through no fault of their own. The interrupt system as it was ultimately implemented has certain limitations, and I'm pretty sure you can logically prove that replicating LTN behavior exactly is impossible without circuits.

These posters claim to have actually replicated LTN by combining circuits and interrupts:
viewtopic.php?t=117777
viewtopic.php?f=194&t=117459
From https://www.factorio.com/blog/post/fff-389:
We have been asked to do something like 'logistic trains' many times. Schedule interrupts provide a more generic system, where logistic trains is just one of the things you can build from it. For example, you can have a system where you let the stop decide where to send the train using the circuit conditions and interrupts.
I expect there to be plenty of circuits involved in a real implementation, and am totally open to it. I can imagine some solutions based on some of the above ideas, but the issue is complexity. I don't want to build a FSM or use 50 combinators per stop, etc.

It may be impossible, not worth the effort, or just not that interesting to the community. In that case, I'll probably abandon the idea and just do vanilla bag of trains.
robot256
Smart Inserter
Smart Inserter
Posts: 1274
Joined: Sun Mar 17, 2019 1:52 am
Contact:

Re: Let's talk train design

Post by robot256 »

The fundamental reason LTN works is because a train departing the depot simultaneously reserves a slot at the selected provider station and the selected requester station. Vanilla trains can only reserve one stop at a time, regardless of how many stations are in the interrupt schedule. This is why circuits are required to notify the requesting stop that a train is on its way while that train is approaching/at the provider stop, before it reserves a slot at the requester stop. The timing of that transmission is critical, and it's very easy to accidentally dispatch more than one train to the same request if the circuit lag is not accounted for.

The reason people mostly stopped worrying about replicating LTN is that trains are cheap and pre-loading them reduces delivery time. I know certain modpacks stilk make this cumbersome, which is why Cybersyn and LTN are still popular.
My mods: Multiple Unit Train Control, RGB Pipes, Shipping Containers, Rocket Log, Smart Artillery Wagons.
Maintainer of Auto Deconstruct, Cargo Ships, Vehicle Wagon, Honk, Shortwave.
Tertius
Smart Inserter
Smart Inserter
Posts: 1430
Joined: Fri Mar 19, 2021 5:58 pm
Contact:

Re: Let's talk train design

Post by Tertius »

waterBear wrote: Wed Sep 24, 2025 5:35 pm
From https://www.factorio.com/blog/post/fff-389:
We have been asked to do something like 'logistic trains' many times. Schedule interrupts provide a more generic system, where logistic trains is just one of the things you can build from it. For example, you can have a system where you let the stop decide where to send the train using the circuit conditions and interrupts.
I expect there to be plenty of circuits involved in a real implementation, and am totally open to it. I can imagine some solutions based on some of the above ideas, but the issue is complexity. I don't want to build a FSM or use 50 combinators per stop, etc.
As far as I see, the blog tells about generic train logistics in general. Logistics is the science of transportation. It's not about integrating the mod with the name "logistic train network". The 1.1 behavior is a simple "go there, then there, then there, than repeat at the start", and this was upgraded to something dynamic. That's all in my opinion. It's not a mimic of the ltn mod, not even the concepts behind ltn.

I don't know if you see it, but the ltn mod is actually a specific Factorio 1.0 mod, made to circumvent the "black hole" effect of a train station being switched from deactivated to activated. This undesirable effect was fixed in Factorio 1.1 by implementing train limits. Since then, the ltn mod is obsolete.
mrt144
Long Handed Inserter
Long Handed Inserter
Posts: 53
Joined: Thu Sep 13, 2018 9:30 pm
Contact:

Re: Let's talk train design

Post by mrt144 »

Tertius wrote: Wed Sep 24, 2025 5:18 pm
I always thought people seek for efficient solutions, and with all your brainstorming with all their caveats and edge cases you found it's clear that approach isn't efficient, at least not with the tools we're given by the game engine. I tried to build a fully circuit controlled and micromanaged train system myself, started with a crystal clear design, promising implementation, but half way through I found so many tiny flaws and edge cases, it's just not feasible. Yes, with may be 100 global combinators and 20 per station. This made me think the opposite way: instead of micromanage everything, manage nothing. And suddenly it worked perfectly. This is the message I have: don't micromanage. Explore, understand and properly use the tools given by the game engine.
I think there's something to that, that basically you can make an overcomplicated system to achieve a larger game objective, but the real objective is making the system work - not well, not efficiently, not better than other designs, but just work on its own terms. The reason it often falls apart is trying to account for every edge which generates its own edge externality often enough, and then you're so many hours deep into a tangled mess of combinators and wires when the larger objective of getting A to B can be achieved so simply. There's a lot of 'ideas' that aren't straight up Homo Economus solutions, they're proofs of the tools in operation at all.

In another thread, I had that screwy idea about one drop off with 4 different item pickups - I made it work in the end and the bottlenecks are the bottlenecks after that part of it, but the theoretical knowledge might have a better application than what I did with it. Maybe not, I'll have to test what 'go fetch this if you run out of this' with other uses and see if it ever makes sense to rig up a circuit to do that in a factory shooting for high SPM.

I think you're mostly on the right track with your first impulse to simplify as much as possible for a larger game objective of throughput, it's just the parameter of 'efficiency' might be slightly different, e.g. 'efficient footprint' might be the primary objective over factory throughput. I think there's a few places - power consumption, factory footprint, for example, where the simplest and most straightforward might not tick the box.

One of the really cool things I saw over in the combinator sub forum is a factory that produces any makable item in the game - there's nothing about the concept that fits it into a shoebox if you do it in the simplest way possible without circuits (although proofs of a tiny factory of everything without circuits would be neat). Just something to keep in mind after deploying the first impulse to seek throughput efficiency with minimal rigging.
jaxmed2
Manual Inserter
Manual Inserter
Posts: 3
Joined: Wed Sep 24, 2025 2:07 am
Contact:

Re: Let's talk train design

Post by jaxmed2 »

Nooby question but is the reason why you'd need/want something more complex than the standard "bag of trains" interrupt-based approach described in the FFF just around not needing to make as many trains? I've been using that for a bit and haven't really ramped up too much but I did notice that it only really works well if I add a new train for every provider station slot, which is fine but yeah does take some of the niceness out of it and I'm left wondering if it's ultimately really that much better than the pre-2.0 dedicated resource train setups all things considered.
waterBear
Fast Inserter
Fast Inserter
Posts: 118
Joined: Thu Apr 23, 2020 2:05 pm
Contact:

Re: Let's talk train design

Post by waterBear »

jaxmed2 wrote: Wed Sep 24, 2025 9:10 pm Nooby question but is the reason why you'd need/want something more complex than the standard "bag of trains" interrupt-based approach described in the FFF just around not needing to make as many trains? I've been using that for a bit and haven't really ramped up too much but I did notice that it only really works well if I add a new train for every provider station slot, which is fine but yeah does take some of the niceness out of it and I'm left wondering if it's ultimately really that much better than the pre-2.0 dedicated resource train setups all things considered.
Have you ever wished that your trains could behave like logistic robots? If so, then that's what this idea is.

There is no compelling reason to do it beyond that. I know that there are others who have tried, and I was hoping some of them might chime in at some point and brainstorm with me.

So far, the thread has largely been unproductive. Well, sparking discussion is never bad, but no substantive progress has been made on the topic.
mrt144
Long Handed Inserter
Long Handed Inserter
Posts: 53
Joined: Thu Sep 13, 2018 9:30 pm
Contact:

Re: Let's talk train design

Post by mrt144 »

waterBear wrote: Wed Sep 24, 2025 9:20 pm
jaxmed2 wrote: Wed Sep 24, 2025 9:10 pm Nooby question but is the reason why you'd need/want something more complex than the standard "bag of trains" interrupt-based approach described in the FFF just around not needing to make as many trains? I've been using that for a bit and haven't really ramped up too much but I did notice that it only really works well if I add a new train for every provider station slot, which is fine but yeah does take some of the niceness out of it and I'm left wondering if it's ultimately really that much better than the pre-2.0 dedicated resource train setups all things considered.
Have you ever wished that your trains could behave like logistic robots? If so, then that's what this idea is.

There is no compelling reason to do it beyond that. I know that there are others who have tried, and I was hoping some of them might chime in at some point and brainstorm with me.

So far, the thread has largely been unproductive. Well, sparking discussion is never bad, but no substantive progress has been made on the topic.
Restate it a little more simply for me - is the only reason this isn't working like 'logistic robots' right now revolving around the ability to pick up from multiple 'supplies' or to ad hoc decide which 'supply' is best to fetch from?
waterBear
Fast Inserter
Fast Inserter
Posts: 118
Joined: Thu Apr 23, 2020 2:05 pm
Contact:

Re: Let's talk train design

Post by waterBear »

mrt144 wrote: Wed Sep 24, 2025 9:38 pm
waterBear wrote: Wed Sep 24, 2025 9:20 pm
jaxmed2 wrote: Wed Sep 24, 2025 9:10 pm Nooby question but is the reason why you'd need/want something more complex than the standard "bag of trains" interrupt-based approach described in the FFF just around not needing to make as many trains? I've been using that for a bit and haven't really ramped up too much but I did notice that it only really works well if I add a new train for every provider station slot, which is fine but yeah does take some of the niceness out of it and I'm left wondering if it's ultimately really that much better than the pre-2.0 dedicated resource train setups all things considered.
Have you ever wished that your trains could behave like logistic robots? If so, then that's what this idea is.

There is no compelling reason to do it beyond that. I know that there are others who have tried, and I was hoping some of them might chime in at some point and brainstorm with me.

So far, the thread has largely been unproductive. Well, sparking discussion is never bad, but no substantive progress has been made on the topic.
Restate it a little more simply for me - is the only reason this isn't working like 'logistic robots' right now revolving around the ability to pick up from multiple 'supplies' or to ad hoc decide which 'supply' is best to fetch from?
The basic idea for the most common implementation is this: A requesting stop globally broadcasts a needed number of train loads of an item. Provider stops then come online, and trains go straight to them.

There are lots of "gotchas" with the way trains and interrupts work that make this harder than it sounds in practice. It's do-able if you have one provider station for every item. By playing with the C signal from the stops, you can ensure that global demand gets reduced by 1 for every train on its way to either a provider stop for the item or to the requesting stop.

Things get harder when there's multiple provider stops. My brain stormed ideas at the top of this thread are all attempts to address that. I have had more, but if there's no one else really trying to help solve this problem, I'll take my work back offline.
mrt144
Long Handed Inserter
Long Handed Inserter
Posts: 53
Joined: Thu Sep 13, 2018 9:30 pm
Contact:

Re: Let's talk train design

Post by mrt144 »

waterBear wrote: Wed Sep 24, 2025 10:57 pm
mrt144 wrote: Wed Sep 24, 2025 9:38 pm
waterBear wrote: Wed Sep 24, 2025 9:20 pm
jaxmed2 wrote: Wed Sep 24, 2025 9:10 pm Nooby question but is the reason why you'd need/want something more complex than the standard "bag of trains" interrupt-based approach described in the FFF just around not needing to make as many trains? I've been using that for a bit and haven't really ramped up too much but I did notice that it only really works well if I add a new train for every provider station slot, which is fine but yeah does take some of the niceness out of it and I'm left wondering if it's ultimately really that much better than the pre-2.0 dedicated resource train setups all things considered.
Have you ever wished that your trains could behave like logistic robots? If so, then that's what this idea is.

There is no compelling reason to do it beyond that. I know that there are others who have tried, and I was hoping some of them might chime in at some point and brainstorm with me.

So far, the thread has largely been unproductive. Well, sparking discussion is never bad, but no substantive progress has been made on the topic.
Restate it a little more simply for me - is the only reason this isn't working like 'logistic robots' right now revolving around the ability to pick up from multiple 'supplies' or to ad hoc decide which 'supply' is best to fetch from?
The basic idea for the most common implementation is this: A requesting stop globally broadcasts a needed number of train loads of an item. Provider stops then come online, and trains go straight to them.

There are lots of "gotchas" with the way trains and interrupts work that make this harder than it sounds in practice. It's do-able if you have one provider station for every item. By playing with the C signal from the stops, you can ensure that global demand gets reduced by 1 for every train on its way to either a provider stop for the item or to the requesting stop.

Things get harder when there's multiple provider stops. My brain stormed ideas at the top of this thread are all attempts to address that. I have had more, but if there's no one else really trying to help solve this problem, I'll take my work back offline.
I don't know enough to really help out here just getting into interrupts, but it's on my mind as something to tackle at some point because I too have dreamed of trains that mostly operate based on demand, not a schedule. I think I'm looking at the central depot brainstorm, and using 'task codes' which contain a pickup/ destination/item type, and become mutually exclusive if they exist in system so no two trains can have the same task code at once. Don't know how feasible it is to pull off, but that's my initial lean here if we're aping fetch requests made by logistic robots. I made a very basic baby 'demand side' interrupt system work before scuttling the entire map because it was an island, not lakes...so we'll see what I can do with this outstanding problem when I get there.

One thing I wonder about is a kind of 'time to fulfill' context, where lets say we get this all working somehow - does it make sense for Train A to do a 10 minute round trip task that forces Train B to do an identical task with a 20 minute round trip, or should Train B wait 2 minutes for Train A to clear and then do its task in 10 minutes? i.e. If the closest supply is blocked off by another task, do we really want a train to burn fuel and time trying to fulfill it from another stop much further away or sit and wait for the quickest path to open for them? IDK, that seems hella advanced if we can even get the predicates to work right.

It's' a really cool idea worth tackling whether we toil in darkness or share what we find.
waterBear
Fast Inserter
Fast Inserter
Posts: 118
Joined: Thu Apr 23, 2020 2:05 pm
Contact:

Re: Let's talk train design

Post by waterBear »

mrt144 wrote: Wed Sep 24, 2025 11:40 pm
waterBear wrote: Wed Sep 24, 2025 10:57 pm
mrt144 wrote: Wed Sep 24, 2025 9:38 pm
waterBear wrote: Wed Sep 24, 2025 9:20 pm
jaxmed2 wrote: Wed Sep 24, 2025 9:10 pm Nooby question but is the reason why you'd need/want something more complex than the standard "bag of trains" interrupt-based approach described in the FFF just around not needing to make as many trains? I've been using that for a bit and haven't really ramped up too much but I did notice that it only really works well if I add a new train for every provider station slot, which is fine but yeah does take some of the niceness out of it and I'm left wondering if it's ultimately really that much better than the pre-2.0 dedicated resource train setups all things considered.
Have you ever wished that your trains could behave like logistic robots? If so, then that's what this idea is.

There is no compelling reason to do it beyond that. I know that there are others who have tried, and I was hoping some of them might chime in at some point and brainstorm with me.

So far, the thread has largely been unproductive. Well, sparking discussion is never bad, but no substantive progress has been made on the topic.
Restate it a little more simply for me - is the only reason this isn't working like 'logistic robots' right now revolving around the ability to pick up from multiple 'supplies' or to ad hoc decide which 'supply' is best to fetch from?
The basic idea for the most common implementation is this: A requesting stop globally broadcasts a needed number of train loads of an item. Provider stops then come online, and trains go straight to them.

There are lots of "gotchas" with the way trains and interrupts work that make this harder than it sounds in practice. It's do-able if you have one provider station for every item. By playing with the C signal from the stops, you can ensure that global demand gets reduced by 1 for every train on its way to either a provider stop for the item or to the requesting stop.

Things get harder when there's multiple provider stops. My brain stormed ideas at the top of this thread are all attempts to address that. I have had more, but if there's no one else really trying to help solve this problem, I'll take my work back offline.
I don't know enough to really help out here just getting into interrupts, but it's on my mind as something to tackle at some point because I too have dreamed of trains that mostly operate based on demand, not a schedule. I think I'm looking at the central depot brainstorm, and using 'task codes' which contain a pickup/ destination/item type, and become mutually exclusive if they exist in system so no two trains can have the same task code at once. Don't know how feasible it is to pull off, but that's my initial lean here if we're aping fetch requests made by logistic robots. I made a very basic baby 'demand side' interrupt system work before scuttling the entire map because it was an island, not lakes...so we'll see what I can do with this outstanding problem when I get there.

One thing I wonder about is a kind of 'time to fulfill' context, where lets say we get this all working somehow - does it make sense for Train A to do a 10 minute round trip task that forces Train B to do an identical task with a 20 minute round trip, or should Train B wait 2 minutes for Train A to clear and then do its task in 10 minutes? i.e. If the closest supply is blocked off by another task, do we really want a train to burn fuel and time trying to fulfill it from another stop much further away or sit and wait for the quickest path to open for them? IDK, that seems hella advanced if we can even get the predicates to work right.

It's' a really cool idea worth tackling whether we toil in darkness or share what we find.
Yeah, that's the dream. I think you can probably do it with a centralized system, but I am lazy and don't want to build (another) huge combinator brain. Good luck though!

As for the trip planning, I do everything I can to let the game mechanics do that for me. One of my tricks is to attach a single combinator to each stop that basically says "set priority to 50 minus C" where C is the number of trains on the way or at the stop. That automagically prevents the trains from all going to the nearest pickup and ignoring distant providers, for example. It also works for delivery stations. Sometimes you have multiple ore drop offs that all need to be evenly fed, and this trick solves that problem nicely - with one combinator.

It's one of the reasons I don't like a lot of my own solution ideas so far. I want to avoid a system that tells the trains where to go via signal, both because that's going to end up being a mess of combinators and also because then I have to do that work instead of the game engine.
Harb42
Burner Inserter
Burner Inserter
Posts: 19
Joined: Thu Oct 31, 2024 11:38 pm
Contact:

Re: Let's talk train design

Post by Harb42 »

Tertius wrote: Wed Sep 24, 2025 3:37 pm
waterBear wrote: Wed Sep 24, 2025 12:53 pm Here is something that's currently on my mind. We all want to build a logistic train system in vanilla. It sounded so easy in the FFF. Here's the problem: The natural way to do it with interrupts doesn't work with multiple provider stations. I think by now, all the train afficianados know the type of design I'm talking about.
You talk about an inferior general approach that nobody has managed to implement flawlessly yet.
waterBear wrote: Wed Sep 24, 2025 12:53 pm You have requester stations that put a request for X train loads of an item on the global (radar) circuit network, and provider stations open up based on that request.
What's the reasoning behind this decision? Why do you want the station open just on request? Why don't you just keep the stations open all the time?

In case you're talking about trains that will always carry one type of material at a time and you have unloading stations dedicated to one material:

Set their train limit to 1 (or 2 with a waiting area to minimize latency) and employ enough trains, and you have trains in all of your provider stations. Some of them currently loading and some of them full and waiting to deliver their items. Now, as soon as some requester station needs a new train load of items, it "opens up" and one of the full trains is dispatched automatically and immediately and is satisfying this request. That's completely by the train mechanics of the game engine, no circuits involved.

This is the fastest possible delivery and totally reliable. This "opening up" of a requester station doesn't need to be circuit controlled. If it has a train limit of 1, the mere leaving of an empty train will "opening up" this station, since the one slot is free again and the next train will drive there.

This works 100% without circuits and 100% with static train limits. Adding a tiny circuit to manipulate priority for provider stations with limit 2 lowers the latency even more.

People think this static approach doesn't work, because they usually don't add enough trains. By this design every station is supposed to have at least 1 train, either being loaded or full, or being emptied.

This system is completed by adding a depot for empty trains, so any train getting empty on an unloading station is driving to the depot if all loading stations are full, so the unloading station is free again and the next full train is able to reserve a slot and drive there.

Name all loading stations the same, for example "load". Put the item icon into the name of each unloading station, so you can build the name with the cargo wildcard in an interrupt, for example "(green cargo wildcard) unload". All trains with the same layout have the same train group and all stations are built for this train layout, for example 1-4 (1 locomotive, 4 cargo wagons).

Static schedule entry:
go to "load"; "wait for full"

Interrupt:
condition: cargo (green cargo wildcard) > 0
destination: go to "(green cargo wildcard) unload"; "wait for empty"

Interrupt:
condition: no path or destination full AND empty cargo AND not at depot
option: allowed to interrupt other interrupts
destination: go to depot; inactivity 1s

All stations static train limit 1.

If you have 10 loading stations and 4 unloading stations, you need to have 10+4=14 trains and a depot with 4 depot stations.

If you have 10 loading stations with train limit 2 and 4 unloading stations with train limit 3, you need a waiting area for 1 train on each loading station and a waiting area for 2 trains per unloading station, and 10*2 + 4*3 = 32 trains and a depot with 4 depot stations.

In case you ever see trains waiting for a longer time in your depot stations, this is a sign you have not enough loading stations to satisfy the throughput demand.

I built this system now on 2 maps, and it works flawlessly. No maintenance. It just works. I used station train limit 2 everywhere. The only circuit I added is to reduce loading station priority to 49 in case a train has reserved a slot, so first empty stations are filled, and only after all stations have at least 1 train the 2nd slot will be filled.

What I describe is a direct implementation of fff-389 https://factorio.com/blog/post/fff-389 and fff-395 https://factorio.com/blog/post/fff-395
Hi!

Does this approach works for you on a larger scale?
I have seen in the FFF and on some other pages, that you can go full interrupt based.
However I always faced some problems and basically the train system collapsed.
My main problem is the following:
- If I use wildcards to the fullest, and name all stations FluidLoaders/SolidLoaders, all trains will search for the loading station based on range. For example they carried oil, emptied the tankers, the interrupt kicks in, "let's go to theFluidLoader station", which is a water pump loader for example. By some time all fluid trains will carry water which become basically useless. They always prioritize that station.
- If I use '<fluid wild card> FluidLoader' in the station name it won't find it, because it is searching for that literal name. Even if the train has some fluid cargo.
(This way I inteded to 'attach' given train to a given fluid type; it will use that cargo type only.)
- If I start using specific Fluids in the FluidLoader name the whole concept is lost, because every more train then has to be created manually.

So the unloading part seems to be okay, but not the loading part.
Bunch of images:
Loader station examples:
09-25-2025, 06-14-50.png
09-25-2025, 06-14-50.png (45.16 KiB) Viewed 220 times
Unloader station examples:
With circuits I disable these when they are kinda full. The reason behind this is the same for loading: trains prioritize based on distance and they always go to the nearest one. Nearby ones are always full, far away ones are always starving. -> Disable the full ones, problem solved.
09-25-2025, 06-15-09.png
09-25-2025, 06-15-09.png (56.42 KiB) Viewed 220 times
The disable logic:
09-25-2025, 06-17-08.png
09-25-2025, 06-17-08.png (302.88 KiB) Viewed 220 times
09-25-2025, 06-17-16.png
09-25-2025, 06-17-16.png (489.69 KiB) Viewed 220 times
And now the interrupts:
09-25-2025, 06-17-51.png
09-25-2025, 06-17-51.png (130.07 KiB) Viewed 220 times
09-25-2025, 06-17-57.png
09-25-2025, 06-17-57.png (155.16 KiB) Viewed 220 times
09-25-2025, 06-18-04.png
09-25-2025, 06-18-04.png (124.83 KiB) Viewed 220 times
09-25-2025, 06-18-08.png
09-25-2025, 06-18-08.png (135.59 KiB) Viewed 220 times
09-25-2025, 06-18-13.png
09-25-2025, 06-18-13.png (159.77 KiB) Viewed 220 times
Docks are refuleres too.
computeraddict
Filter Inserter
Filter Inserter
Posts: 389
Joined: Sat Oct 07, 2023 6:44 am
Contact:

Re: Let's talk train design

Post by computeraddict »

Harb42 wrote: Thu Sep 25, 2025 3:52 am By some time all fluid trains will carry water which become basically useless.
That means you're doing it wrong, not that the mechanics have flaws. All of the solutions described in this thread cannot have this happen.
Tertius
Smart Inserter
Smart Inserter
Posts: 1430
Joined: Fri Mar 19, 2021 5:58 pm
Contact:

Re: Let's talk train design

Post by Tertius »

Harb42 wrote: Thu Sep 25, 2025 3:52 am My main problem is the following:
Your build contains a mistake, based on wrong assumption about the wildcard expansion. Use it for unloading, but not for loading.

The idea is to start with an empty train. Completely empty. For an empty train, no green cargo or fluid wildcard can match. So you cannot use the wildcard for the loading process. So instead of using an interrupt for loading, add the loading as the only static schedule entry. For this to work, you need to name all loading stations the same, no matter the material it's supposed to load. Instead of "(fluid type) load", name all of them just "fluid load". Overcome yourself and just equalize all fluid loading station names. And do it accordingly for the cargo item transport trains, name them all "cargo load".

So any empty train will go to the nearest free "fluid load" station and starts loading until it is full.
Now the interrupt condition (fluid wildcard) > 0 can trigger and will match the fluid just loaded. The waiting condition it creates should be (fluid wildcard) = 0 so it is ensured the train is completely empty after it leaves the unloading station, so the cycle will start again with an empty train on the static schedule entry. The train must be completely empty, not almost empty as you did.

Only if you completely empty a train this train system is universal. One cycle it is being loaded with water, the next cycle it might be filled with oil. This cannot happen if you keep some leftover. The train has to lose its identity to be available for everything the next cycle.

In case you see just the nearest fluid load station being visited and just the same fluid is available, you need to distribute more trains. If you have enough trains, the nearest station will always a train, either at the station or driving there, and the next train will reserve the next near station, and so on, until all loading stations are occupied.
The amount of trains with the same fluid will be implicitly limited by the sum of the train limits of the loading station of that fluid and the train limits of the unloading stations of that fluid. So if you have train limit 1 and 3 stations loading water and 1 water unloading station, you will see there will never be more than 4 trains loaded with water. So you add 4 trains for water.
So the 5th train cannot be loaded with water, it is available for loading with the next fluid. If you have a similar setup for the next fluid, you need to add 4 trains for the next fluid as well.
The trains themselves don't have an identity, they change fluids dynamically.
Post Reply

Return to “Gameplay Help”