On this page
  1. How it plays
  2. In Factorio’s lineage
  3. Related
  4. Mechanics
  5. References
  6. Sources

OpenTTD is an open-source remake of Chris Sawyer’s Transport Tycoon Deluxe. The player runs a transport company from around 1950, building rail, road, air and sea routes, and tries to become the highest-ranking company by 20501. Its About page says it mimics the original game as closely as possible while adding new features2.

Owen Rudge, who would release the game, writes that Ludvig Strigeus began rebuilding Transport Tycoon Deluxe in C in June 20023. Players then ran the 1995 game with Josef Drexler’s TTDPatch, and Rudge recalls the patch’s limits: the map size was fixed, no cargo types could be added, and multiplayer was hard to improve4. Rudge released it as OpenTTD 0.1 on 6 March 2004. His release post called it 95% complete, and players still had to copy in the original game’s graphics and sound files to run it5. A community of developers formed around it6. Free replacements for those graphics, sounds and music made it a stand-alone game with version 1.0.0 in 20107, and it moved to GitHub in 2018 and reached Steam in 20218.

It heads the table of Obligement’s Amiga Games Award 20049. Lewis Denby put it on PC Gamer’s 2011 list of 20 free PC games you must play10, and Rock Paper Shotgun’s Graham Smith called it “one of the seven wonders of PC gaming” in 2021, writing that successors such as Transport Fever never recapture its joy of tinkering with trains and lorries11. Ted John has said OpenTTD heavily inspired his OpenRCT2, an open-source remake of RollerCoaster Tycoon 212.

#How it plays

Trains need signals to share track. A plain block signal stops a train while another train is anywhere in the stretch of track ahead, up to the next signals and through any junctions13. Three pre-signals look further. An entry signal also stays red when every exit signal leading out of the block ahead is red, even if that block is empty, so at the mouth of a station whose platform exits all show red it holds trains back. It doesn’t know which exit a train wants: any green exit clears it. A combo signal is an entry and an exit at once, so pre-signals can be chained14. Path signals, added in 200915, let a train reserve its own route through a junction to the next safe place to stop, and turn green only for the train that holds the reservation16. An ordinary path signal can be passed from behind; a one-way path signal can’t17. Each signal comes as a light or a semaphore, which only look different18.

Trains find their way with a pathfinder called YAPF19. It prices each route in track length, adding one tile’s worth for a gentle bend, six for a sharp turn and two for an upward slope, ten tiles’ worth for each tile of a station the train would run through without stopping, and more for a destination platform that’s too short for the train20. A red signal on the way costs most when it is the next one and less with each signal further on, and past the tenth signal a red one costs nothing21.

A vehicle follows a list of orders: stations, depots, waypoints, and conditional orders that skip ahead on its load, age, or need for servicing. Each station order sets how to load and unload22. A full-load order holds a train at the platform until every wagon is full, or, for “full load any cargo”, until the wagons of one cargo are23. Otherwise it stops loading when the cargo runs short and its timetabled stop is over, and a train running late cuts its stop short to catch up24. Timetables, added in 200725, set the stop and travel times for each order, and the wiki says they keep vehicles on shared orders from bunching up26.

#In Factorio’s lineage

In 2016 Friday Facts #126 added an “open ttd” inspired preview of the train to Factorio’s train screen, with a camera view and a map view27. OpenTTD’s train window has such a view: a small window on the map that follows the train and zooms with the mouse wheel28.

The signals invite comparison. OpenTTD’s block signal does the job of Factorio’s rail signal29. Factorio’s chain signal looks past the next block as an entry pre-signal does, but only at the exit on the train’s own route, and Friday Facts #81 says the chain signal resembles the “TTD pre signals” but works differently30. The TTDPatch manual describes pre-signals as a signal type its switches add to Transport Tycoon Deluxe31. OpenTTD’s changelog lists them in its 0.1.1 and 0.2 releases of March and April 200432, and an old wiki comparison says they, like path signals, work exactly as in TTDPatch33.

Both games’ train pathfinders weigh congestion less the farther ahead it lies34. They part on stations: Factorio makes passing a train stop as costly as 2,000 tiles of track, while OpenTTD charges 10 tiles of track for each tile of platform a train runs through35.

Mechanics

MechanicKindHow
Rail signallingAny exitentry, exit and combo pre-signals: an entry signal turns red when the block ahead has exit signals and none of them is green
Rail signallingPath reservationpath signals, since 2009: a train reserves track to the next safe place to stop, and the signal turns green for it when the reservation succeeds
Pathfindingtrains price each route in track length plus bends, slopes, stations passed, and red signals ahead, which count less the farther off they are
Rail transportorders to stations, depots and waypoints; a train can wait for a full load, and a timetable sets its stops
Every claim about this game, by concept (35)
generalOpenTTD's About page says the game is based upon Chris Sawyer's Transport Tycoon Deluxe and attempts to mimic it as closely as possible while extending it with new features.Publisher
OpenTTD's About page says many of its features were inspired by TTDPatch, and others are original. It doesn't name which.Publisher
Owen Rudge, who released OpenTTD, writes that Ludvig Strigeus ("Ludde") had been working on a clone of Transport Tycoon Deluxe since 30 June 2002, and first told him about it by ICQ message in March 2003: a working version of the game, written in C, though incomplete.Dev blog
Rudge recalls that in 2004 the Transport Tycoon community played Transport Tycoon Deluxe with Josef Drexler's TTDPatch, which had fundamental limits: the map size couldn't change, cargo types couldn't be added, and multiplayer was hard to improve. A clone in a high-level language, he writes, "got people very excited indeed". The OpenTTD wiki gives the same reason: the patch's way of changing the game made many features near impossible.Dev blog
Rudge released OpenTTD 0.1 as open source on 6 March 2004, naming it himself, with a SourceForge project and a forum on TT-Forums. His release-day post calls it Ludde's "C reconstruction of TTD", 95% complete, and tells players to copy Transport Tycoon Deluxe's Windows graphics and sound file to run it.Dev blog
After the release, Rudge writes, a community of developers formed to fix bugs and add features, and support for TTDPatch's NewGRF format began to work four months later. The OpenTTD wiki says other developers joined Strigeus on the project.Dev blog
OpenTTD's changelog lists "preliminary presignal support" in 0.1.1 (14 March 2004) and pre-signals, set by Ctrl-clicking an existing signal, in 0.2 (3 April 2004).Developer
OpenTTD's changelog lists "a form of timetabling for vehicles" in 0.6.0-beta1 (18 November 2007).Wiki
OpenTTD's changelog lists "path based signalling" in 0.7.0-beta1 (16 February 2009); 0.7.0 came out on 1 April 2009.Developer
Until the end of 2009 OpenTTD needed Transport Tycoon Deluxe's graphics and sounds; free replacements (OpenGFX, OpenSFX and OpenMSX) made it a stand-alone game, and the release that marked it was numbered 1.0.0, which the changelog dates 1 April 2010.Wiki
Rudge writes that the move to GitHub in 2018 and the release on Steam in 2021 re-energised development. Rock Paper Shotgun reported in February 2021 that OpenTTD would reach Steam on 1 April, with the 1.11 update, after it had reached the Microsoft Store; the changelog dates 1.11.0 to 1 April 2021.Dev blog
The OpenTTD wiki's manual calls it an open-source reimplementation of Transport Tycoon Deluxe in which the player runs a transport company from (typically) 1950, building rail, road, air and sea routes, and tries to be the highest-ranking company by 2050.Wiki
OpenTTD's About page lists, among its "significant enhancements from the original game", bigger maps, multiplayer for up to 255 players, new pathfinding, conditional and shared orders, and "presignals, semaphores, path based signalling".Publisher
An archived OpenTTD wiki page comparing OpenTTD with TTDPatch lists pre-signals and path-based signals among the features that "work exactly the same as in TTDPatch". The page is marked out of date and "only really of value as a historical document now".Wiki
OpenTTD heads the table of Obligement's Amiga Games Award 2004, credited to Ludvig Strigeus and the OpenTTD team under the GPL 2.Web
Lewis Denby put OpenTTD on PC Gamer's May 2011 list of "20 free PC games you must play", writing that dedicated fans had remade Transport Tycoon Deluxe from scratch, open-source and with "a heap of features", and that it "continues to captivate its followers".Web
Graham Smith of Rock Paper Shotgun called OpenTTD "one of the seven wonders of PC gaming" in 2021, and wrote that for his money later successors such as Transport Fever and Rise of Industry never recapture its "sedate joy of tinkering with trains and lorries".Web
Ted John (IntelOrca) writes that he started OpenRCT2, an open-source C++ reimplementation of RollerCoaster Tycoon 2, in early 2014, "heavily inspired by OpenTTD".Dev blog
PathfindingTrains route with YAPF ("Yet Another PathFinder"); OpenTTD 15.0-beta1 (December 2024) removed the older NPF pathfinder and the setting that chose between them.Code
YAPF prices a route in hundredths of a tile: 100 for a tile of straight track and 71 for a corner piece, the short piece inside a curve, plus 100 for a 45° bend, 600 for a 90° turn, 200 for an upward slope, 300 for a level crossing, added only on a straight tile, 5000 for reversing in a depot, and 1000 for each tile of a station platform the train passes through. The destination's platform instead costs 800 if it's longer than the train and 4000 if it's shorter.Code
For each of the first ten signals along a route, a red block or pre-signal adds a cost that falls with distance: 500 for the first, then 405, 320, 245, 180, 125, 80, 45, 20 and 5; green signals and red path signals add none. If the first signal is red, a block or entry signal adds 1000 more and an exit or combo signal 10000. With the rail_firstred_twoway_eol setting on, as it is by default, a red first block or pre-signal that is two-way, met after the route has had a choice of track, ends that branch of the search as a dead end.Code
Both games' train pathfinders count a red signal or a busy block for less the farther ahead it lies: Factorio divides the penalty for an occupied block by how many blocks it is from the start, and OpenTTD's default penalty for a red signal that isn't a path signal falls from 500 at the first signal to 5 at the tenth and stops.Wiki
Factorio's pathfinder, which costs a route by the length of its rail segments in tiles, adds 2000 for each train stop on the route other than the one at the train's start, while OpenTTD's charges 10 tiles' worth for each tile of station platform a train runs through.Code
Rail signallingOpenTTD 15.3 has six kinds of rail signal: the block signal; three pre-signals (entry, exit and combo); the path signal; and the one-way path signal. Each comes as a light signal or a semaphore, which look different and behave alike.Code
Any signal that isn't a path signal holding a reservation turns red while a train is anywhere in the block it leads into; a train inside a depot doesn't count. A block runs from signal to signal through junctions, stations, level crossings, tunnels and bridges, over the owning company's track only.Code
With no train in the block, an entry signal turns red when the block ahead has at least one exit or combo signal leading out of it and none of them is green, whichever way the waiting train would go. A combo signal acts as an entry and an exit at once; one placed both ways doesn't count its own back face as a way out. When an exit or combo signal changes color, the block behind it is worked out again, so a chain of combo signals passes the state back block by block.Code
A path signal with no reservation behind it is red when a train is in its block, and also when the block holds a junction or has more than one signal leading into it; otherwise it is green. A train at a path signal reserves track to the next safe place to stop, and the signal turns green for it when the reservation succeeds. A safe place is a depot, a signal that isn't a path signal, the tile before a path signal on a single line ahead, or, where the search allows it, a dead end; a one-way path signal facing the other way counts only as such a dead end.Code
The pathfinder treats a signal that faces only against the train as a dead end, unless it is a two-way path signal: that one a train may pass from behind, at a cost of 15 tiles of track while it is within the first ten signals of the path.Code
OpenTTD's block signal does what Factorio's rail signal does: it keeps a train out of a block another train is in.Dev blog
OpenTTD's entry pre-signal and Factorio's chain signal both look past the next block, but differently: the entry signal clears when any exit signal of the block ahead is green, whichever exit the train will take, while the chain signal looks only at the exit on the train's path. Friday Facts #81 (2015) says the chain signal resembles the "TTD pre signals" but works differently.Dev blog
Rail transportA vehicle's orders send it to stations, depots and waypoints, or skip ahead on a condition: its load, reliability, maximum reliability, top speed, age, remaining lifetime or need for servicing, or always. At a station an order sets how to load (if available, full load, full load any cargo, or none) and how to unload (normally, unload all, transfer, or none).Code
A train with a full-load order stays at the station until every vehicle in it is full; with "full load any cargo" it may leave once all the vehicles carrying some one cargo are full. The test runs on a loading round in which nothing was loaded or unloaded. Aircraft with passengers are the exception to the any-cargo rule: they wait until the passenger hold is full.Code
Without a full-load order, a vehicle stops loading once a round has unloaded nothing and filled no vehicle to the round's limit, no cargo reserved for it is left, and it has waited its timetabled time at the stop, less however late it is running.Code
The OpenTTD wiki describes timetables as setting how long a vehicle waits at each station and spends on each leg, with an autofill button that measures a run, and a late counter; it says they keep vehicles on shared orders from bunching up.Wiki
A train's window holds a small view of the map that follows the train and zooms with the mouse wheel unless the wheel is switched off in the settings; its location button centers the main view on the train, follows it on a double click, and opens a new viewport on it with Ctrl.Code

References

  1. ^The OpenTTD wiki's manual calls it an open-source reimplementation of Transport Tycoon Deluxe in which the player runs a transport company from (typically) 1950, building rail, road, air and sea routes, and tries to be the highest-ranking company by 2050.WikiOpenTTD Wiki, "Manual"
    How we know
    OpenTTD is an open source reimplementation of the Microprose game Transport Tycoon Deluxe (TTD). … As president of a start-up transportation company in (typically) 1950, you have a choice of building rail, road, air and maritime transportation routes to build up your transportation empire. … Outsmart your competition by beating them to attractive passenger and commodities routes to become the game's highest-ranking transport company by the year 2050.
    introduction · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  2. ^OpenTTD's About page says the game is based upon Chris Sawyer's Transport Tycoon Deluxe and attempts to mimic it as closely as possible while extending it with new features.PublisherOpenTTD, "About"
    How we know
    OpenTTD is an open source simulation game based upon the popular Microprose game "Transport Tycoon Deluxe", written by Chris Sawyer. It attempts to mimic the original game as closely as possible while extending it with new features.
    About · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  3. ^Owen Rudge, who released OpenTTD, writes that Ludvig Strigeus ("Ludde") had been working on a clone of Transport Tycoon Deluxe since 30 June 2002, and first told him about it by ICQ message in March 2003: a working version of the game, written in C, though incomplete.Dev blogOpenTTD 20th-anniversary post
    How we know
    Exactly 21 years ago, I received an ICQ message (look it up, kids) out of the blue from a guy named Ludvig Strigeus (nicknamed Ludde).
    paragraph 2 · archived copy ↗
    (He’d been working on it since 30th June 2002, so I guess that is technically the birthday of what would become OpenTTD…)
    paragraph 5 · archived copy ↗
    It was a fully functional version of Transport Tycoon Deluxe, written in C.
    paragraph 7 · archived copy ↗
    Admittedly incomplete at that time, it was still quite remarkable.
    paragraph 8 · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  4. ^Rudge recalls that in 2004 the Transport Tycoon community played Transport Tycoon Deluxe with Josef Drexler's TTDPatch, which had fundamental limits: the map size couldn't change, cargo types couldn't be added, and multiplayer was hard to improve. A clone in a high-level language, he writes, "got people very excited indeed". The OpenTTD wiki gives the same reason: the patch's way of changing the game made many features near impossible.Dev blogOpenTTD 20th-anniversary post · OpenTTD Wiki, "Manual"
    How we know
    To put things in context, in 2004, the Transport Tycoon community generally enjoyed playing the classic Transport Tycoon Deluxe with the excellent TTDPatch started by Josef Drexler.
    paragraph 9 · archived copy ↗
    TTDPatch was an amazing piece of software, but there were always some fundamental limitations - the map size couldn’t be changed, extra cargo types couldn’t be added, multiplayer was difficult to improve, and so on.
    paragraph 11 · archived copy ↗
    So having an almost fully-functional clone of TTD, written in a high-level programming language, suddenly appear out of nowhere got people very excited indeed.
    paragraph 12 · archived copy ↗
    The Patch's method of modifying the game made a lot of potential features near-impossible.
    History of Transport Tycoon, "Enter OpenTTD" · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  5. ^Rudge released OpenTTD 0.1 as open source on 6 March 2004, naming it himself, with a SourceForge project and a forum on TT-Forums. His release-day post calls it Ludde's "C reconstruction of TTD", 95% complete, and tells players to copy Transport Tycoon Deluxe's Windows graphics and sound file to run it.Dev blogOpenTTD 20th-anniversary post · TT-Forums, OpenTTD 0.1 announcement (2004)
    How we know
    Coincidentally, this happened exactly a year after I’d first spoken to him, on the 6th March 2004.
    paragraph 15 · archived copy ↗
    I don’t think I thought very much about it, but decided that “OpenTTD” had a nice ring to it, so registered a SourceForge project, created an OpenTTD forum on TT-Forums, and set it loose.
    paragraph 17 · archived copy ↗
    OpenTTD 0.1 was released.
    paragraph 18 · archived copy ↗
    Basically, a guy called Ludde (original author of ScummVM) has spent quite some time working on a C reconstruction of TTD. He's now let me release the code. So here it is. … It is 95% complete. … To play the game, copy the Windows TTD graphics and sample.cat file to the compact directory, and run ttd.exe.
    first post, orudge, 06 Mar 2004 19:26 · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  6. ^After the release, Rudge writes, a community of developers formed to fix bugs and add features, and support for TTDPatch's NewGRF format began to work four months later. The OpenTTD wiki says other developers joined Strigeus on the project.Dev blogOpenTTD 20th-anniversary post · OpenTTD Wiki, "Manual"revised
    How we know
    Things really got going after this, and a community started to form with enthusiastic developers fixing bugs, adding in new features, and smoothing off the rough edges.
    paragraph 20 · archived copy ↗
    Quick wins like higher vehicle limits came in very quickly, and support for TTDPatch’s NewGRF format started to be functional just four months later.
    paragraph 23 · archived copy ↗
    Response was positive, and other developers joined Ludde in the project.
    History of Transport Tycoon, "Enter OpenTTD" · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  7. ^Until the end of 2009 OpenTTD needed Transport Tycoon Deluxe's graphics and sounds; free replacements (OpenGFX, OpenSFX and OpenMSX) made it a stand-alone game, and the release that marked it was numbered 1.0.0, which the changelog dates 1 April 2010.WikiOpenTTD Wiki, "Manual" · OpenTTD 15.3 source
    How we know
    Up till this time graphics and sound files from Transport Tycoon Deluxe were required to play OpenTTD but now free and open alternatives, OpenGFX, OpenSFX and OpenMSX, are also available and supported. … These large community contributions made OpenTTD a fully stand-alone game for the first time and to mark this occasion this release was given the version number 1.0.0.
    History of Transport Tycoon, "OpenTTD 1.0.0" · archived copy ↗
    4596### 1.0.0 (2010-04-01)
    
    changelog.md line 4596 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  8. ^Rudge writes that the move to GitHub in 2018 and the release on Steam in 2021 re-energised development. Rock Paper Shotgun reported in February 2021 that OpenTTD would reach Steam on 1 April, with the 1.11 update, after it had reached the Microsoft Store; the changelog dates 1.11.0 to 1 April 2021.Dev blogOpenTTD 20th-anniversary post · RPS, OpenTTD on Steam (2021) · OpenTTD 15.3 sourcerevised
    How we know
    The move to GitHub in 2018 and the release of OpenTTD on Steam in 2021 have also re-energised development efforts, with thousands of people now enjoying playing the game regularly.
    paragraph 28 · archived copy ↗
    Now it should hopefully find a new audience, as it's coming to Steam for the first time on April 1st.
    paragraph 1 · archived copy ↗
    When it does come to Steam, it'll happen alongside the 1.11 update, which is currently in beta and improves MacOS support, among other tweaks. … It's already available via the Microsoft store now
    paragraph 3 · archived copy ↗
    1583### 1.11.0 (2021-04-01)
    
    changelog.md line 1583 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  9. ^OpenTTD heads the table of Obligement's Amiga Games Award 2004, credited to Ludvig Strigeus and the OpenTTD team under the GPL 2.WebAmiga Games Award 2004
    How we know
    Ludvig Strigeus / OpenTTD Team
    results table, row 1 · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  10. ^Lewis Denby put OpenTTD on PC Gamer's May 2011 list of "20 free PC games you must play", writing that dedicated fans had remade Transport Tycoon Deluxe from scratch, open-source and with "a heap of features", and that it "continues to captivate its followers".WebPC Gamer, "20 free PC games you must play" (2011)
    How we know
    That might be why some dedicated fans took it upon themselves to remake the latter from scratch, making it open-source and adding a heap of features along the way. To this day OpenTTD continues to captivate its followers.
    20. OpenTTD · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  11. ^Graham Smith of Rock Paper Shotgun called OpenTTD "one of the seven wonders of PC gaming" in 2021, and wrote that for his money later successors such as Transport Fever and Rise of Industry never recapture its "sedate joy of tinkering with trains and lorries".WebRPS, OpenTTD on Steam (2021)
    How we know
    Open Transport Tycoon Deluxe is one of the seven wonders of PC gaming.
    paragraph 1 · archived copy ↗
    It's as great a game as it ever was, and for my money, modern successors such as Transport Fever and Rise Of Industry never recapture the same sedate joy of tinkering with trains and lorries in OpenTTD.
    paragraph 4 · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  12. ^Ted John (IntelOrca) writes that he started OpenRCT2, an open-source C++ reimplementation of RollerCoaster Tycoon 2, in early 2014, "heavily inspired by OpenTTD".Dev blogIntelOrca's project page
    How we know
    An open-source clone of RollerCoaster Tycoon 2 (2002) written in C++. Heavily inspired by OpenTTD, I started the project early 2014
    OpenRCT2 · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  13. ^Any signal that isn't a path signal holding a reservation turns red while a train is anywhere in the block it leads into; a train inside a depot doesn't count. A block runs from signal to signal through junctions, stations, level crossings, tunnels and bridges, over the owning company's track only.CodeOpenTTD 15.3 sourcerevised
    How we know
    422		/* Signal state of reserved path signals is handled by the reserve/unreserve process. */
    423		if (IsPbsSignal(sig) && (GetRailReservationTrackBits(tile) & TrackToTrackBits(track)) != TRACK_BIT_NONE) continue;
    ⋮
    425		/* determine whether the new state is red */
    426		if (flags.Test(SigFlag::Train)) {
    427			/* train in the segment */
    428			newstate = SIGNAL_STATE_RED;
    
    src/signal.cpp lines 422–428 at 14ec60f · upstream ↗
    194static bool IsTrainAndNotInDepot(const Vehicle *v)
    ⋮
    196	return v->type == VEH_TRAIN && Train::From(v)->track != TRACK_BIT_DEPOT;
    
    src/signal.cpp lines 194–197 at 14ec60f · upstream ↗
    279				if (GetTileOwner(tile) != owner) continue; // do not propagate signals on others' tiles (remove for tracksharing)
    
    src/signal.cpp line 279 at 14ec60f · upstream ↗
    302					/* If no train detected yet, and there is not no train -> there is a train -> set the flag */
    303					if (!flags.Test(SigFlag::Train) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) flags. Set(SigFlag::Train);
    304				} else {
    305					if (tracks_masked == TRACK_BIT_NONE) continue; // no incidating track
    306					if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
    
    src/signal.cpp lines 302–306 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  14. ^With no train in the block, an entry signal turns red when the block ahead has at least one exit or combo signal leading out of it and none of them is green, whichever way the waiting train would go. A combo signal acts as an entry and an exit at once; one placed both ways doesn't count its own back face as a way out. When an exit or combo signal changes color, the block behind it is worked out again, so a chain of combo signals passes the state back block by block.CodeOpenTTD 15.3 source
    How we know
    432		} else {
    433			/* is it a bidir combo? - then do not count its other signal direction as exit */
    434			if (sig == SIGTYPE_COMBO && HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) {
    435				/* at least one more exit */
    436				if (flags.Test(SigFlag::MultiExit) &&
    437						/* no green exit */
    438						(!flags.Test(SigFlag::Green) ||
    439						/* only one green exit, and it is this one - so all other exits are red */
    440						(!flags.Test(SigFlag::MultiGreen) && GetSignalStateByTrackdir(tile, ReverseTrackdir(trackdir)) == SIGNAL_STATE_GREEN))) {
    441					newstate = SIGNAL_STATE_RED;
    ⋮
    443			} else { // entry, at least one exit, no green exit
    444				if (IsPresignalEntry(tile, TrackdirToTrack(trackdir)) && flags.Test(SigFlag::Exit) && !flags.Test(SigFlag::Green)) newstate = SIGNAL_STATE_RED;
    
    src/signal.cpp lines 432–446 at 14ec60f · upstream ↗
    330						/* if it is a presignal EXIT in OUR direction and we haven't found 2 green exits yes, do special check */
    331						if (!flags.Test(SigFlag::MultiGreen) && IsPresignalExit(tile, track) && HasSignalOnTrackdir(tile, trackdir)) { // found presignal exit
    332							if (flags.Test(SigFlag::Exit)) flags.Set(SigFlag::MultiExit); // found two (or more) exits
    333							flags.Set(SigFlag::Exit); // found at least one exit - allow for compiler optimizations
    334							if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN) { // found green presignal exit
    335								if (flags.Test(SigFlag::Green)) flags.Set(SigFlag::MultiGreen);
    336								flags.Set(SigFlag::Green);
    
    src/signal.cpp lines 329–338 at 14ec60f · upstream ↗
    448		/* only when the state changes */
    449		if (newstate != GetSignalStateByTrackdir(tile, trackdir)) {
    450			if (IsPresignalExit(tile, TrackdirToTrack(trackdir))) {
    451				/* for pre-signal exits, add block to the global set */
    452				DiagDirection exitdir = TrackdirToExitdir(ReverseTrackdir(trackdir));
    453				_globset.Add(tile, exitdir); // do not check for full global set, first update all signals
    
    src/signal.cpp lines 448–454 at 14ec60f · upstream ↗
    307inline bool IsPresignalEntry(Tile t, Track track)
    ⋮
    309	return GetSignalType(t, track) == SIGTYPE_ENTRY || GetSignalType(t, track) == SIGTYPE_COMBO;
    ⋮
    312inline bool IsPresignalExit(Tile t, Track track)
    ⋮
    314	return GetSignalType(t, track) == SIGTYPE_EXIT || GetSignalType(t, track) == SIGTYPE_COMBO;
    
    src/rail_map.h lines 307–315 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  15. ^OpenTTD's changelog lists "path based signalling" in 0.7.0-beta1 (16 February 2009); 0.7.0 came out on 1 April 2009.DeveloperOpenTTD 15.3 source
    How we know
    5411### 0.7.0-beta1 (2009-02-16)
    
    changelog.md line 5411 at 14ec60f · upstream ↗
    5455- Feature: Path based signalling (r13926-13967)
    
    changelog.md line 5455 at 14ec60f · upstream ↗
    5296### 0.7.0 (2009-04-01)
    
    changelog.md line 5296 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  16. ^A path signal with no reservation behind it is red when a train is in its block, and also when the block holds a junction or has more than one signal leading into it; otherwise it is green. A train at a path signal reserves track to the next safe place to stop, and the signal turns green for it when the reservation succeeds. A safe place is a depot, a signal that isn't a path signal, the tile before a path signal on a single line ahead, or, where the search allows it, a dead end; a one-way path signal facing the other way counts only as such a dead end.CodeOpenTTD 15.3 source
    How we know
    422		/* Signal state of reserved path signals is handled by the reserve/unreserve process. */
    423		if (IsPbsSignal(sig) && (GetRailReservationTrackBits(tile) & TrackToTrackBits(track)) != TRACK_BIT_NONE) continue;
    ⋮
    425		/* determine whether the new state is red */
    426		if (flags.Test(SigFlag::Train)) {
    427			/* train in the segment */
    428			newstate = SIGNAL_STATE_RED;
    429		} else if (IsPbsSignal(sig) && flags.Any({SigFlag::Split, SigFlag::MultiEnter})) {
    430			/* Turn path signals red if the segment has a junction or more than one way in. */
    431			newstate = SIGNAL_STATE_RED;
    
    src/signal.cpp lines 422–431 at 14ec60f · upstream ↗
    381bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg)
    ⋮
    383	if (IsRailDepotTile(tile)) return true;
    ⋮
    385	if (IsTileType(tile, MP_RAILWAY)) {
    386		/* For non-pbs signals, stop on the signal tile. */
    387		if (HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return true;
    ⋮
    390	/* Check next tile. For performance reasons, we check for 90 degree turns ourself. */
    391	CFollowTrackRail ft(v, GetAllCompatibleRailTypes(v->railtypes));
    ⋮
    393	/* End of track? */
    394	if (!ft.Follow(tile, trackdir)) {
    395		/* Last tile of a terminus station is a safe position. */
    396		if (include_line_end) return true;
    ⋮
    399	/* Check for reachable tracks. */
    ⋮
    
    src/pbs.cpp lines 381–417 at 14ec60f · upstream ↗
    2747		if (track != INVALID_TRACK && HasPbsSignalOnTrackdir(tile, TrackEnterdirToTrackdir(track, enterdir))) {
    2748			do_track_reservation = true;
    2749			changed_signal = true;
    2750			SetSignalStateByTrackdir(tile, TrackEnterdirToTrackdir(track, enterdir), SIGNAL_STATE_GREEN);
    
    src/train_cmd.cpp lines 2747–2750 at 14ec60f · upstream ↗
    2759	if (do_track_reservation) {
    2760		res_dest = ExtendTrainReservation(v, &tracks, &dest_enterdir);
    2761		if (res_dest.tile == INVALID_TILE) {
    2762			/* Reservation failed? */
    2763			if (mark_stuck) MarkTrainAsStuck(v);
    2764			if (changed_signal) SetSignalStateByTrackdir(tile, TrackEnterdirToTrackdir(best_track, enterdir), SIGNAL_STATE_RED);
    
    src/train_cmd.cpp lines 2759–2764 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  17. ^The pathfinder treats a signal that faces only against the train as a dead end, unless it is a two-way path signal: that one a train may pass from behind, at a cost of 15 tiles of track while it is within the first ten signals of the path.CodeOpenTTD 15.3 source
    How we know
    176		int cost = 0;
    177		/* if there is one-way signal in the opposite direction, then it is not our way */
    178		if (IsTileType(tile, MP_RAILWAY)) {
    179			bool has_signal_against = HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir));
    180			bool has_signal_along = HasSignalOnTrackdir(tile, trackdir);
    181			if (has_signal_against && !has_signal_along && IsOnewaySignal(tile, TrackdirToTrack(trackdir))) {
    182				/* one-way signal in opposite direction */
    183				n.segment->end_segment_reason.Set(EndSegmentReason::DeadEnd);
    
    src/pathfinder/yapf/yapf_costrail.hpp lines 176–183 at 14ec60f · upstream ↗
    237				if (has_signal_against && IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) {
    238					cost += n.num_signals_passed < Yapf().PfGetSettings().rail_look_ahead_max_signals ? Yapf().PfGetSettings().rail_pbs_signal_back_penalty : 0;
    
    src/pathfinder/yapf/yapf_costrail.hpp lines 237–239 at 14ec60f · upstream ↗
    318inline bool IsOnewaySignal(Tile t, Track track)
    ⋮
    320	return GetSignalType(t, track) != SIGTYPE_PBS;
    
    src/rail_map.h lines 318–321 at 14ec60f · upstream ↗
    261var      = pf.yapf.rail_pbs_signal_back_penalty
    ⋮
    264def      = 15 * YAPF_TILE_LENGTH
    
    src/table/settings/pathfinding_settings.ini lines 261–264 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  18. ^OpenTTD 15.3 has six kinds of rail signal: the block signal; three pre-signals (entry, exit and combo); the path signal; and the one-way path signal. Each comes as a light signal or a semaphore, which look different and behave alike.CodeOpenTTD 15.3 source
    How we know
    15/** Variant of the signal, i.e. how does the signal look? */
    16enum SignalVariant : uint8_t {
    17	SIG_ELECTRIC  = 0, ///< Light signal
    18	SIG_SEMAPHORE = 1, ///< Old-fashioned semaphore signal
    
    src/signal_type.h lines 15–19 at 14ec60f · upstream ↗
    22/** Type of signal, i.e. how does the signal behave? */
    23enum SignalType : uint8_t {
    24	SIGTYPE_BLOCK      = 0, ///< block signal
    25	SIGTYPE_ENTRY      = 1, ///< presignal block entry
    26	SIGTYPE_EXIT       = 2, ///< presignal block exit
    27	SIGTYPE_COMBO      = 3, ///< presignal inter-block
    28	SIGTYPE_PBS        = 4, ///< normal pbs signal
    29	SIGTYPE_PBS_ONEWAY = 5, ///< no-entry signal
    
    src/signal_type.h lines 22–29 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  19. ^Trains route with YAPF ("Yet Another PathFinder"); OpenTTD 15.0-beta1 (December 2024) removed the older NPF pathfinder and the setting that chose between them.CodeOpenTTD 15.3 source
    How we know
    2505	return YapfTrainChooseTrack(v, tile, enterdir, tracks, path_found, do_track_reservation, dest, final_dest);
    
    src/train_cmd.cpp line 2505 at 14ec60f · upstream ↗
    609- Remove: NPF and pathfinder change settings (#12209)
    
    changelog.md line 609 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  20. ^YAPF prices a route in hundredths of a tile: 100 for a tile of straight track and 71 for a corner piece, the short piece inside a curve, plus 100 for a 45° bend, 600 for a 90° turn, 200 for an upward slope, 300 for a level crossing, added only on a straight tile, 5000 for reversing in a depot, and 1000 for each tile of a station platform the train passes through. The destination's platform instead costs 800 if it's longer than the train and 4000 if it's shorter.CodeOpenTTD 15.3 sourcerevised
    How we know
    16static const int YAPF_TILE_LENGTH = 100;
    ⋮
    18/** Length (penalty) of a corner with YAPF */
    19static const int YAPF_TILE_CORNER_LENGTH = 71;
    
    src/pathfinder/pathfinder_type.h lines 16–19 at 14ec60f · upstream ↗
    124	inline int OneTileCost(TileIndex &tile, Trackdir trackdir)
    ⋮
    126		int cost = 0;
    127		/* set base cost */
    128		if (IsDiagonalTrackdir(trackdir)) {
    129			cost += YAPF_TILE_LENGTH;
    130			switch (GetTileType(tile)) {
    131				case MP_ROAD:
    132					/* Increase the cost for level crossings */
    133					if (IsLevelCrossing(tile)) {
    134						cost += Yapf().PfGetSettings().rail_crossing_penalty;
    ⋮
    136					break;
    ⋮
    138				default:
    ⋮
    
    src/pathfinder/yapf/yapf_costrail.hpp lines 124–146 at 14ec60f · upstream ↗
    102		if (TrackFollower::Allow90degTurns()
    103				&& HasTrackdir(TrackdirCrossesTrackdirs(td1), td2)) {
    104			/* 90-deg curve penalty */
    105			cost += Yapf().PfGetSettings().rail_curve90_penalty;
    106		} else if (td2 != NextTrackdir(td1)) {
    107			/* 45-deg curve penalty */
    108			cost += Yapf().PfGetSettings().rail_curve45_penalty;
    
    src/pathfinder/yapf/yapf_costrail.hpp lines 102–108 at 14ec60f · upstream ↗
    450				uint platform_length = follower->tiles_skipped + 1;
    451				/* We don't know yet if the station is our target or not. Act like
    452				 * if it is pass-through station (not our destination). */
    453				segment_cost += Yapf().PfGetSettings().rail_station_penalty * platform_length;
    
    src/pathfinder/yapf/yapf_costrail.hpp lines 450–453 at 14ec60f · upstream ↗
    604				/* Reduce the extra cost caused by passing-station penalty (each station receives it in the segment cost). */
    605				extra_cost -= Yapf().PfGetSettings().rail_station_penalty * platform_length;
    606				/* Add penalty for the inappropriate platform length. */
    607				extra_cost += PlatformLengthPenalty(platform_length);
    
    src/pathfinder/yapf/yapf_costrail.hpp lines 604–607 at 14ec60f · upstream ↗
    153var      = pf.yapf.rail_station_penalty
    ⋮
    156def      = 10 * YAPF_TILE_LENGTH
    ⋮
    162var      = pf.yapf.rail_slope_penalty
    ⋮
    165def      = 2 * YAPF_TILE_LENGTH
    ⋮
    171var      = pf.yapf.rail_curve45_penalty
    ⋮
    174def      = 1 * YAPF_TILE_LENGTH
    ⋮
    180var      = pf.yapf.rail_curve90_penalty
    ⋮
    183def      = 6 * YAPF_TILE_LENGTH
    ⋮
    189var      = pf.yapf.rail_depot_reverse_penalty
    ⋮
    192def      = 50 * YAPF_TILE_LENGTH
    ⋮
    198var      = pf.yapf.rail_crossing_penalty
    ⋮
    201def      = 3 * YAPF_TILE_LENGTH
    
    src/table/settings/pathfinding_settings.ini lines 153–201 at 14ec60f · upstream ↗
    279var      = pf.yapf.rail_longer_platform_penalty
    ⋮
    282def      = 8 * YAPF_TILE_LENGTH
    ⋮
    288var      = pf.yapf.rail_longer_platform_per_tile_penalty
    ⋮
    291def      = 0 * YAPF_TILE_LENGTH
    ⋮
    297var      = pf.yapf.rail_shorter_platform_penalty
    ⋮
    300def      = 40 * YAPF_TILE_LENGTH
    
    src/table/settings/pathfinding_settings.ini lines 279–300 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  21. ^For each of the first ten signals along a route, a red block or pre-signal adds a cost that falls with distance: 500 for the first, then 405, 320, 245, 180, 125, 80, 45, 20 and 5; green signals and red path signals add none. If the first signal is red, a block or entry signal adds 1000 more and an exit or combo signal 10000. With the rail_firstred_twoway_eol setting on, as it is by default, a red first block or pre-signal that is two-way, met after the route has had a choice of track, ends that branch of the search as a dead end.CodeOpenTTD 15.3 sourcerevised
    How we know
    62		int p0 = Yapf().PfGetSettings().rail_look_ahead_signal_p0;
    63		int p1 = Yapf().PfGetSettings().rail_look_ahead_signal_p1;
    64		int p2 = Yapf().PfGetSettings().rail_look_ahead_signal_p2;
    65		this->sig_look_ahead_costs.clear();
    66		this->sig_look_ahead_costs.reserve(Yapf().PfGetSettings().rail_look_ahead_max_signals);
    67		for (uint i = 0; i < Yapf().PfGetSettings().rail_look_ahead_max_signals; i++) {
    68			this->sig_look_ahead_costs.push_back(p0 + i * (p1 + i * p2));
    
    src/pathfinder/yapf/yapf_costrail.hpp lines 62–69 at 14ec60f · upstream ↗
    192					int look_ahead_cost = (n.num_signals_passed < this->sig_look_ahead_costs.size()) ? this->sig_look_ahead_costs[n.num_signals_passed] : 0;
    193					if (sig_state != SIGNAL_STATE_RED) {
    194						/* green signal */
    195						n.flags_u.flags_s.last_signal_was_red = false;
    196						/* negative look-ahead red-signal penalties would cause problems later, so use them as positive penalties for green signal */
    197						if (look_ahead_cost < 0) {
    198							/* add its negation to the cost */
    199							cost -= look_ahead_cost;
    ⋮
    201					} else {
    202						/* we have a red signal in our direction
    203						 * was it first signal which is two-way? */
    204						if (!IsPbsSignal(sig_type) && Yapf().TreatFirstRedTwoWaySignalAsEOL() && n.flags_u.flags_s.choice_seen && has_signal_against && n.num_signals_passed == 0) {
    ⋮
    
    src/pathfinder/yapf/yapf_costrail.hpp lines 192–229 at 14ec60f · upstream ↗
    111var      = pf.yapf.rail_firstred_twoway_eol
    ⋮
    113def      = true
    ⋮
    117var      = pf.yapf.rail_firstred_penalty
    ⋮
    120def      = 10 * YAPF_TILE_LENGTH
    ⋮
    126var      = pf.yapf.rail_firstred_exit_penalty
    ⋮
    129def      = 100 * YAPF_TILE_LENGTH
    
    src/table/settings/pathfinding_settings.ini lines 111–129 at 14ec60f · upstream ↗
    207var      = pf.yapf.rail_look_ahead_max_signals
    ⋮
    210def      = 10
    ⋮
    216var      = pf.yapf.rail_look_ahead_signal_p0
    ⋮
    219def      = 500
    ⋮
    225var      = pf.yapf.rail_look_ahead_signal_p1
    ⋮
    228def      = -100
    ⋮
    234var      = pf.yapf.rail_look_ahead_signal_p2
    ⋮
    237def      = 5
    
    src/table/settings/pathfinding_settings.ini lines 207–237 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  22. ^A vehicle's orders send it to stations, depots and waypoints, or skip ahead on a condition: its load, reliability, maximum reliability, top speed, age, remaining lifetime or need for servicing, or always. At a station an order sets how to load (if available, full load, full load any cargo, or none) and how to unload (normally, unload all, transfer, or none).CodeOpenTTD 15.3 sourcerevised
    How we know
    50enum OrderType : uint8_t {
    51	OT_BEGIN         = 0,
    52	OT_NOTHING       = 0,
    53	OT_GOTO_STATION  = 1,
    54	OT_GOTO_DEPOT    = 2,
    55	OT_LOADING       = 3,
    56	OT_LEAVESTATION  = 4,
    57	OT_DUMMY         = 5,
    58	OT_GOTO_WAYPOINT = 6,
    59	OT_CONDITIONAL   = 7,
    60	OT_IMPLICIT      = 8,
    61	OT_END
    
    src/order_type.h lines 50–61 at 14ec60f · upstream ↗
    67enum class OrderUnloadType : uint8_t {
    68	UnloadIfPossible = 0, ///< Unload all cargo that the station accepts.
    69	Unload = 1, ///< Force unloading all cargo onto the platform, possibly not getting paid.
    70	Transfer = 2, ///< Transfer all cargo onto the platform.
    71	NoUnload = 4, ///< Totally no unloading will be done.
    ⋮
    74/**
    75 * Loading order types.
    ⋮
    77enum class OrderLoadType : uint8_t {
    78	LoadIfPossible = 0, ///< Load as long as there is cargo that fits in the train.
    79	FullLoad = 2, ///< Full load all cargoes of the consist.
    80	FullLoadAny = 3, ///< Full load a single cargo of the consist.
    81	NoLoad = 4, ///< Do not load anything.
    
    src/order_type.h lines 67–81 at 14ec60f · upstream ↗
    128enum class OrderConditionVariable : uint8_t {
    129	LoadPercentage = 0, ///< Skip based on the amount of load
    130	Reliability = 1, ///< Skip based on the reliability
    131	MaxSpeed = 2, ///< Skip based on the maximum speed
    132	Age = 3, ///< Skip based on the age
    133	RequiresService = 4, ///< Skip when the vehicle requires service
    134	Unconditionally = 5, ///< Always skip
    135	RemainingLifetime = 6, ///< Skip based on the remaining lifetime
    136	MaxReliability = 7, ///< Skip based on the maximum reliability
    
    src/order_type.h lines 128–136 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  23. ^A train with a full-load order stays at the station until every vehicle in it is full; with "full load any cargo" it may leave once all the vehicles carrying some one cargo are full. The test runs on a loading round in which nothing was loaded or unloaded. Aircraft with passengers are the exception to the any-cargo rule: they wait until the passenger hold is full.CodeOpenTTD 15.3 source
    How we know
    1824		if (v->cargo.StoredCount() >= v->cargo_cap) {
    1825			SetBit(cargo_full, v->cargo_type);
    1826		} else {
    1827			SetBit(cargo_not_full, v->cargo_type);
    
    src/economy.cpp lines 1824–1828 at 14ec60f · upstream ↗
    1866		if (front->current_order.IsFullLoadOrder()) {
    1867			if (front->current_order.GetLoadType() == OrderLoadType::FullLoadAny) {
    1868				/* if the aircraft carries passengers and is NOT full, then
    1869				 * continue loading, no matter how much mail is in */
    1870				if ((front->type == VEH_AIRCRAFT && IsCargoInClass(front->cargo_type, CargoClass::Passengers) && front->cargo_cap > front->cargo.StoredCount()) ||
    1871						(cargo_not_full != 0 && (cargo_full & ~cargo_not_full) == 0)) { // There are still non-full cargoes
    1872					finished_loading = false;
    ⋮
    1874			} else if (cargo_not_full != 0) {
    1875				finished_loading = false;
    
    src/economy.cpp lines 1866–1876 at 14ec60f · upstream ↗
    77enum class OrderLoadType : uint8_t {
    78	LoadIfPossible = 0, ///< Load as long as there is cargo that fits in the train.
    79	FullLoad = 2, ///< Full load all cargoes of the consist.
    80	FullLoadAny = 3, ///< Full load a single cargo of the consist.
    81	NoLoad = 4, ///< Do not load anything.
    
    src/order_type.h lines 77–81 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  24. ^Without a full-load order, a vehicle stops loading once a round has unloaded nothing and filled no vehicle to the round's limit, no cargo reserved for it is left, and it has waited its timetabled time at the stop, less however late it is running.CodeOpenTTD 15.3 source
    How we know
    1855		/* We loaded less cargo than possible for all cargo types and it's not full
    1856		 * load and we're not supposed to wait any longer: stop loading. */
    1857		if (!anything_unloaded && full_load_amount == 0 && reservation_left == 0 && !front->current_order.IsFullLoadOrder() &&
    1858				front->current_order_time >= std::max(front->current_order.GetTimetabledWait() - front->lateness_counter, 0)) {
    1859			front->vehicle_flags.Set(VehicleFlag::StopLoading);
    
    src/economy.cpp lines 1855–1859 at 14ec60f · upstream ↗
    1789				if (loaded == cap_left) {
    1790					SetBit(full_load_amount, v->cargo_type);
    1791				} else {
    1792					ClrBit(full_load_amount, v->cargo_type);
    
    src/economy.cpp lines 1789–1793 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  25. ^OpenTTD's changelog lists "a form of timetabling for vehicles" in 0.6.0-beta1 (18 November 2007).WikiOpenTTD 15.3 source · OpenTTD Wiki, "Timetable"
    How we know
    6040### 0.6.0-beta1 (2007-11-18)
    
    changelog.md line 6040 at 14ec60f · upstream ↗
    6079- Feature: Introduce a form of timetabling for vehicles (r10236)
    
    changelog.md line 6079 at 14ec60f · upstream ↗
    Timetables were introduced in OpenTTD 0.6.0-beta2 (r10236).
    Using timetables, first paragraph · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  26. ^The OpenTTD wiki describes timetables as setting how long a vehicle waits at each station and spends on each leg, with an autofill button that measures a run, and a late counter; it says they keep vehicles on shared orders from bunching up.WikiOpenTTD Wiki, "Timetable"
    How we know
    You can choose how much time a vehicle should spend in a station
    Using timetables, first paragraph · archived copy ↗
    'Autofill' will measure how long your vehicle takes to travel each leg of the journey, and how long it spends in stations. … Timetables are useful for preventing vehicles from "bunching up".
    Using timetables · archived copy ↗
    Sets late counter to zero.
    Timetable window, "Reset late counter" · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  27. ^Friday Facts #126 (2016) says Factorio's single train screen gained an "open ttd" inspired preview of the train, with a camera view and a map view.Dev blogFFF-126
    How we know
    Namely adding the "open ttd" inspired preview of the train. There is a switchable "camera view" and "map view".
    Updated train screen · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  28. ^A train's window holds a small view of the map that follows the train and zooms with the mouse wheel unless the wheel is switched off in the settings; its location button centers the main view on the train, follows it on a double click, and opens a new viewport on it with Ctrl.CodeOpenTTD 15.3 sourcerevised
    How we know
    2837				NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_VV_VIEWPORT), SetMinimalSize(226, 84), SetResize(1, 1),
    
    src/vehicle_gui.cpp line 2837 at 14ec60f · upstream ↗
    3039		this->GetWidget<NWidgetViewport>(WID_VV_VIEWPORT)->InitializeViewport(this, static_cast<VehicleID>(this->window_number), ScaleZoomGUI(_vehicle_view_zoom_levels[v->type]));
    
    src/vehicle_gui.cpp line 3039 at 14ec60f · upstream ↗
    3338	void OnMouseWheel(int wheel, WidgetID widget) override
    ⋮
    3340		if (widget != WID_VV_VIEWPORT) return;
    3341		if (_settings_client.gui.scrollwheel_scrolling != SWS_OFF) {
    3342			DoZoomInOutWindow(wheel < 0 ? ZOOM_IN : ZOOM_OUT, this);
    
    src/vehicle_gui.cpp lines 3338–3343 at 14ec60f · upstream ↗
    3249			case WID_VV_LOCATION: // center main view
    3250				if (_ctrl_pressed) {
    3251					ShowExtraViewportWindow(TileVirtXY(v->x_pos, v->y_pos));
    3252				} else {
    3253					const Window *mainwindow = GetMainWindow();
    3254					if (click_count > 1) {
    3255						/* main window 'follows' vehicle */
    3256						mainwindow->viewport->follow_vehicle = v->index;
    3257					} else {
    3258						if (mainwindow->viewport->follow_vehicle == v->index) mainwindow->viewport->follow_vehicle = VehicleID::Invalid();
    3259						ScrollMainWindowTo(v->x_pos, v->y_pos, v->z_pos);
    ⋮
    3262				break;
    
    src/vehicle_gui.cpp lines 3249–3262 at 14ec60f · upstream ↗
    4441STR_VEHICLE_VIEW_TRAIN_CENTER_TOOLTIP                           :{BLACK}Centre main view on train's location. Double click to follow train in main view. Ctrl+Click to open a new viewport on train's location
    
    src/lang/english.txt line 4441 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  29. ^OpenTTD's block signal does what Factorio's rail signal does: it keeps a train out of a block another train is in.Dev blogOpenTTD 15.3 source · Friday Facts #81
    How we know
    426		if (flags.Test(SigFlag::Train)) {
    427			/* train in the segment */
    428			newstate = SIGNAL_STATE_RED;
    
    src/signal.cpp lines 426–428 at 14ec60f · upstream ↗
    While normal signal prevents train from entering the occupied block
    The definition · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  30. ^OpenTTD's entry pre-signal and Factorio's chain signal both look past the next block, but differently: the entry signal clears when any exit signal of the block ahead is green, whichever exit the train will take, while the chain signal looks only at the exit on the train's path. Friday Facts #81 (2015) says the chain signal resembles the "TTD pre signals" but works differently.Dev blogOpenTTD 15.3 source · Friday Facts #81
    How we know
    443			} else { // entry, at least one exit, no green exit
    444				if (IsPresignalEntry(tile, TrackdirToTrack(trackdir)) && flags.Test(SigFlag::Exit) && !flags.Test(SigFlag::Green)) newstate = SIGNAL_STATE_RED;
    
    src/signal.cpp lines 443–444 at 14ec60f · upstream ↗
    chain signal prevents train from entering the block also when the exit isn't free. When more exits exist, the one relevant to the train path is taken into account.
    The definition · archived copy ↗
    The chain signals have some similarities with the TTD pre signals, but as they actually work differently, we also decided to call them differently to avoid confusion.
    The chain signal in detail · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  31. ^Friday Facts #81 (2015) says Factorio's chain signals have some similarities with "TTD pre signals" but work differently, so they were given a different name. The TTDPatch manual describes pre-signals as a new type of signal that its switches introduce to Transport Tycoon Deluxe; who had them first isn't shown here.Dev blogFriday Facts #81 · TTDPatch manual, Pre-signals
    How we know
    The chain signals have some similarities with the TTD pre signals, but as they actually work differently, we also decided to call them differently to avoid confusion.
    The chain signal in detail · archived copy ↗
    These switches introduce a new type of signal to TTD, the "pre-signal."
    3.12 Pre-signals · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  32. ^OpenTTD's changelog lists "preliminary presignal support" in 0.1.1 (14 March 2004) and pre-signals, set by Ctrl-clicking an existing signal, in 0.2 (3 April 2004).DeveloperOpenTTD 15.3 source
    How we know
    7825### 0.1.1 (2004-03-14)
    ⋮
    7827- Feature: Preliminary presignal support
    
    changelog.md lines 7825–7827 at 14ec60f · upstream ↗
    7693### 0.2 (2004-04-03)
    ⋮
    7695- Feature: Autoscroll (only works to left/right)
    7696- Feature: Train checkpoints, instead of TTDPatch's nonstop handling
    7697- Feature: TTDPatch compatible nonstop handling
    7698- Feature: Refresh rate configuration setting
    7699- Feature: Town directory sorting options
    7700- Feature: Pre-signals (ctrl-click on existing signals to change signal type)
    
    changelog.md lines 7693–7700 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  33. ^An archived OpenTTD wiki page comparing OpenTTD with TTDPatch lists pre-signals and path-based signals among the features that "work exactly the same as in TTDPatch". The page is marked out of date and "only really of value as a historical document now".WikiOpenTTD Wiki, "Comparison of OpenTTD and TTDPatch features"
    How we know
    These features work exactly the same as in TTDPatch. … Presignals … Path Based Signals (PBS)
    Features shared by TTDPatch and OpenTTD · archived copy ↗
    This is only really of value as a historical document now.
    banner · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  34. ^Both games' train pathfinders count a red signal or a busy block for less the farther ahead it lies: Factorio divides the penalty for an occupied block by how many blocks it is from the start, and OpenTTD's default penalty for a red signal that isn't a path signal falls from 500 at the first signal to 5 at the tenth and stops.WikiFactorio Wiki: Train path finder · OpenTTD 15.3 sourcerevised
    How we know
    When the rail block is occupied by a train -> Add a penalty of 2 * length of the block divided by the number of blocks from the start, so the far away occupied paths don't matter much.
    Path finding penalties · archived copy ↗
    214						/* look-ahead signal penalty */
    215						if (!IsPbsSignal(sig_type) && look_ahead_cost > 0) {
    216							/* add the look ahead penalty only if it is positive */
    217							cost += look_ahead_cost;
    
    src/pathfinder/yapf/yapf_costrail.hpp lines 214–218 at 14ec60f · upstream ↗
    67		for (uint i = 0; i < Yapf().PfGetSettings().rail_look_ahead_max_signals; i++) {
    68			this->sig_look_ahead_costs.push_back(p0 + i * (p1 + i * p2));
    
    src/pathfinder/yapf/yapf_costrail.hpp lines 67–68 at 14ec60f · upstream ↗
    207var      = pf.yapf.rail_look_ahead_max_signals
    ⋮
    210def      = 10
    ⋮
    216var      = pf.yapf.rail_look_ahead_signal_p0
    ⋮
    219def      = 500
    ⋮
    225var      = pf.yapf.rail_look_ahead_signal_p1
    ⋮
    228def      = -100
    ⋮
    234var      = pf.yapf.rail_look_ahead_signal_p2
    ⋮
    237def      = 5
    
    src/table/settings/pathfinding_settings.ini lines 207–237 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

  35. ^Factorio's pathfinder, which costs a route by the length of its rail segments in tiles, adds 2000 for each train stop on the route other than the one at the train's start, while OpenTTD's charges 10 tiles' worth for each tile of station platform a train runs through.CodeFactorio Wiki: Train path finder · factorio-data 2.1.23 · OpenTTD 15.3 sourcerevised
    How we know
    Base cost for a block/segment is the length of the segment (linear grid length along the center of the rail). … When the path includes a train stop -> Add a penalty of 2000.
    Path finding penalties · archived copy ↗
    Train stop at train's starting segment exit is no longer counted into penalty.
    History, 0.18.1 · archived copy ↗
    320      train_stop_penalty = 2000,
    
    core/prototypes/utility-constants.lua line 320 at 39dbd0f · upstream ↗
    450				uint platform_length = follower->tiles_skipped + 1;
    451				/* We don't know yet if the station is our target or not. Act like
    452				 * if it is pass-through station (not our destination). */
    453				segment_cost += Yapf().PfGetSettings().rail_station_penalty * platform_length;
    
    src/pathfinder/yapf/yapf_costrail.hpp lines 450–453 at 14ec60f · upstream ↗
    153var      = pf.yapf.rail_station_penalty
    ⋮
    156def      = 10 * YAPF_TILE_LENGTH
    
    src/table/settings/pathfinding_settings.ini lines 153–156 at 14ec60f · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-26.

    Revised after a check by a second AI model, 2026-10-26.

    In the claim ledger

Sources

Code

Primary

Secondary