Option to allow long trains to work reliably with roundabouts

Post your ideas and suggestions how to improve the game.

Moderator: ickputzdirwech

smcpeak
Burner Inserter
Burner Inserter
Posts: 18
Joined: Tue Dec 05, 2017 7:50 am
Contact:

Option to allow long trains to work reliably with roundabouts

Post by smcpeak »

TL;DR
Currently, a train longer than the circumference of a roundabout can collide with itself. Provide an option to prevent that.

What?
Currently, if a long train repaths at just the right moment while in a roundabout, it can choose a new path that will collide with itself. I would like an option to change train pathfinding to not do that, so they can reliably use such intersections.
example of a train colliding in a roundabout
example of a train colliding in a roundabout
loop-crash.jpg (432.69 KiB) Viewed 323 times
See the attached save game file for a reproducer (from which the screenshot is taken). Load the save, instruct the train near the "Before Trigger" station to advance to that station, and around 20 seconds later a train will collide with itself in the roundabout.

With the requested option enabled, the train would (in this case) instead continue on the path it originally selected, and hence wait for the other blocking train to move.

Why?
In a large factory, long trains are very useful for scale and efficiency since the throughput scales almost linearly with the average train length. Roundabouts are very simple and economical to build, and offer the flexibility of allowing trains to turn around. Whether or not you agree with the factory design tradeoffs, both represent sensible options the player should be allowed to play with, but the current behavior makes them unreliable to use together.

Furthermore, this isn't just a problem with roundabouts, although they are the most common cause. With sufficiently long trains (50+ loco/wagons), there will virtually always be a self-intersecting path somewhere in the network that could lead to a collision, and no good way to find and eliminate them all pre-emptively.

This problem has been reported many times, including recently by me (133314), with 77759 being the canonical dupe target, but the developers say the game is working as intended. Thus I'm asking for an option to change that.

How?
In 77759, boskid explains the reason for the current behavior:
There are no easy solutions to make trains pathfinder not find paths that would cross themselves given certain train length
I think this refers to the potential problem of a self-intersecting path that is passable only by short trains:
self intersection, safety depends on train length
self intersection, safety depends on train length
self-intersect.jpg (310.3 KiB) Viewed 323 times
Indeed, I can see how pathfinding could be expensive and complicated if it is supposed to distinguish between safe and unsafe self-intersecting paths.

Additionally, while it is tempting to simply say that pathfinding should just refuse to make a path that uses any block more than once (effectively treating every train as if it had infinite length), there is then a potential problem with networks like this loop:
loop with two stations, block reuse required
loop with two stations, block reuse required
two-station-loop.jpg (123.29 KiB) Viewed 323 times
Here, the train has plotted a path that takes it back to the segment it is already on (its starting and ending segments are the same, albeit with a waypoint between), and this sort of rail network design should be supported, rather than causing a "no path" alert.

Consequently, I suggest adding a large but finite penalty for a train to enter a segment it already occupies. The train pathfinding code is posted at https://gist.github.com/Rseding91/c0d4d ... 3f6c6a8fe6 and has this check:

Code: Select all

// Add some cost to the path depending on what are the trains doing in the block
if (neighborSegment->getBlock() != currentSegment->getBlock())
{
  for (auto& item : neighborSegment->getBlock()->getTrainsInBlock())
  {
    const Train* neighbourTrain = item.first;
    if (neighbourTrain == request.train)        // <----- HERE
      continue;
The "continue" here means there is currently no additional penalty for a train that wants to drive onto a segment it currently occupies (whereas the code afterward adds a penalty for using a segment that has some other train currently on it). The option I'm asking for could be implemented as a user-controllable boolean that chooses between a penalty value of zero (the current behavior) and a large one. For maximum reliability, the penalty should be large enough to be disuasive even if multiple other trains are blocking the non-self-intersecting path.
Attachments
train_self_collision.zip
reproducer of repath collision
(4.75 MiB) Downloaded 5 times
computeraddict
Filter Inserter
Filter Inserter
Posts: 431
Joined: Sat Oct 07, 2023 6:44 am
Contact:

Re: Option to allow long trains to work reliably with roundabouts

Post by computeraddict »

A minimal example of a self-deadlocking setup if the "never pass red signal" rule is applied, that is avoided with current logic. The train in this example is short enough that it will not self-collide, but the proposed pathing logic would deadlock it anyway.
04-10-2026, 22-39-04.png
04-10-2026, 22-39-04.png (2.72 MiB) Viewed 285 times
Kyralessa
Filter Inserter
Filter Inserter
Posts: 849
Joined: Thu Sep 29, 2016 5:58 pm
Contact:

Re: Option to allow long trains to work reliably with roundabouts

Post by Kyralessa »

This seems like kind of a "Doctor, it hurts if I do this" issue.

You're creating track that crosses itself, and then creating a train long enough to hit itself, and then asking how this can be prevented.

Maybe by creating longer track or a shorter train?
Rseding91
Factorio Staff
Factorio Staff
Posts: 16705
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Option to allow long trains to work reliably with roundabouts

Post by Rseding91 »

I think there has been a misunderstanding with this; if there was a way for us to make this work (that didn’t have terrible performance) we already would have done it. So, asking for an option to something that as far as we know isn’t possible … isn’t possible.
If you want to get ahold of me I'm almost always on Discord.
smcpeak
Burner Inserter
Burner Inserter
Posts: 18
Joined: Tue Dec 05, 2017 7:50 am
Contact:

Re: Option to allow long trains to work reliably with roundabouts

Post by smcpeak »

Could you explain why the cost adjustment I suggested won't work?
computeraddict
Filter Inserter
Filter Inserter
Posts: 431
Joined: Sat Oct 07, 2023 6:44 am
Contact:

Re: Option to allow long trains to work reliably with roundabouts

Post by computeraddict »

smcpeak wrote: Sat Apr 11, 2026 3:50 pm Could you explain why the cost adjustment I suggested won't work?
The one you suggested, a penalty at pathing time, only applies to the train's initial position and doesn't actually eliminate self intersection, even in all the examples you gave (the 270 degree turn). It also would result in degraded performance for networks with properly sized loops and trains even in the example roundabout scenario - a train that fits comfortably entirely inside the example roundabout would be repathed off to Narnia instead of being able to just continue around the roundabout to its new destination.

The only solution that doesn't ruin some other path finding scenario (or pathfinding computation time) is to just stop building footguns.
smcpeak
Burner Inserter
Burner Inserter
Posts: 18
Joined: Tue Dec 05, 2017 7:50 am
Contact:

Re: Option to allow long trains to work reliably with roundabouts

Post by smcpeak »

computeraddict wrote: Sat Apr 11, 2026 8:38 pm The one you suggested [...] doesn't actually eliminate self intersection
The suggested penalty eliminates the problem of a train pathing into itself while in a roundabout, as shown in the first screenshot. For clarity let me explain how it works in detail.

In that situation, the train computes a new path when its head is at the one o'clock position in the roundabout (indicated by where the transport belts are). At that moment, it sees two paths to the destination.

The first path, call it Path A, exits the roundabout to the west; this is the path the train chose when it first started moving. The following screenshot shows the train's complete path on the tick just before it changes its mind:
Path A
Path A
roundabout-path-a.jpg (79.61 KiB) Viewed 32 times
Here is a closeup of the roundabout at that moment:
Path A closeup
Path A closeup
roundabout-path-a-closeup.jpg (303.24 KiB) Viewed 32 times
This path has a penalty of at least 500 due to the stopped train in the indicated block that wasn't there when the path was originally calculated.

The second path, Path B, exits the roundabout to the north. The following screenshot shows the path on the tick when it chooses it:
Path B
Path B
roundabout-path-b.jpg (63.32 KiB) Viewed 32 times
And here is a closeup of the roundabout:
Path B closeup
Path B closeup
roundabout-path-b-closeup.jpg (306.38 KiB) Viewed 32 times
This path avoids the stopped train, so looks better to the pathfinding algorithm. However, it goes through a segment currently occupied by the train doing the pathing. Right now, that has zero penalty, but I am suggesting to instead make that have a large penalty (like 10000). If that change were made, then the train would prefer to remain on Path A since Path B would have a larger cost.
computeraddict wrote: Sat Apr 11, 2026 8:38 pm even in all the examples you gave (the 270 degree turn)
You are right that this change does not eliminate all possibilities for collisions in self-intersecting paths, especially when a train path crosses itself at (e.g.) a right angle, since in that case there are no segments (which are delimited by intersections, signals, and stops) in common between the paths. However, I am not trying to solve that problem; I am only trying to solve the problem with roundabouts.

I apologize for not being clear that the suggestion does not entirely eliminate all self-intersection risks. The problem is more general than roundabouts, but respecting the developers' concerns about complexity and performance, my suggested solution is focused on roundabouts (it is not exclusive to roundabouts, but only affects cases where a segment, rather than a block, is reused).
computeraddict wrote: Sat Apr 11, 2026 8:38 pm a train that fits comfortably entirely inside the example roundabout would be repathed off to Narnia
You are also right that, in this example, with my proposed change, a shorter train would also use Path A (and hence wait for the other train), whereas without my change it would use Path B but would not collide. I think the former behavior is fine because, among other things, the decision to use Path A respects the red train signal at the bottom of the roundabout, unlike Path B.

It seems you have the opposite opinion, which supports making this behavior change be optional: if you prefer that trains always assume they will get out of their own way before any self-intersection collision, even when that means crossing a red signal, you can leave the option disabled.
Post Reply

Return to “Ideas and Suggestions”