The Advtrains mod for Luanti

\(\newcommand{\footnotename}{footnote}\) \(\def \LWRfootnote {1}\) \(\newcommand {\footnote }[2][\LWRfootnote ]{{}^{\mathrm {#1}}}\) \(\newcommand {\footnotemark }[1][\LWRfootnote ]{{}^{\mathrm {#1}}}\) \(\let \LWRorighspace \hspace \) \(\renewcommand {\hspace }{\ifstar \LWRorighspace \LWRorighspace }\) \(\newcommand {\mathnormal }[1]{{#1}}\) \(\newcommand \ensuremath [1]{#1}\) \(\newcommand {\LWRframebox }[2][]{\fbox {#2}} \newcommand {\framebox }[1][]{\LWRframebox } \) \(\newcommand {\setlength }[2]{}\) \(\newcommand {\addtolength }[2]{}\) \(\newcommand {\setcounter }[2]{}\) \(\newcommand {\addtocounter }[2]{}\) \(\newcommand {\arabic }[1]{}\) \(\newcommand {\number }[1]{}\) \(\newcommand {\noalign }[1]{\text {#1}\notag \\}\) \(\newcommand {\cline }[1]{}\) \(\newcommand {\directlua }[1]{\text {(directlua)}}\) \(\newcommand {\luatexdirectlua }[1]{\text {(directlua)}}\) \(\newcommand {\protect }{}\) \(\def \LWRabsorbnumber #1 {}\) \(\def \LWRabsorbquotenumber "#1 {}\) \(\newcommand {\LWRabsorboption }[1][]{}\) \(\newcommand {\LWRabsorbtwooptions }[1][]{\LWRabsorboption }\) \(\def \mathchar {\ifnextchar "\LWRabsorbquotenumber \LWRabsorbnumber }\) \(\def \mathcode #1={\mathchar }\) \(\let \delcode \mathcode \) \(\let \delimiter \mathchar \) \(\def \oe {\unicode {x0153}}\) \(\def \OE {\unicode {x0152}}\) \(\def \ae {\unicode {x00E6}}\) \(\def \AE {\unicode {x00C6}}\) \(\def \aa {\unicode {x00E5}}\) \(\def \AA {\unicode {x00C5}}\) \(\def \o {\unicode {x00F8}}\) \(\def \O {\unicode {x00D8}}\) \(\def \l {\unicode {x0142}}\) \(\def \L {\unicode {x0141}}\) \(\def \ss {\unicode {x00DF}}\) \(\def \SS {\unicode {x1E9E}}\) \(\def \dag {\unicode {x2020}}\) \(\def \ddag {\unicode {x2021}}\) \(\def \P {\unicode {x00B6}}\) \(\def \copyright {\unicode {x00A9}}\) \(\def \pounds {\unicode {x00A3}}\) \(\let \LWRref \ref \) \(\renewcommand {\ref }{\ifstar \LWRref \LWRref }\) \( \newcommand {\multicolumn }[3]{#3}\) \(\require {textcomp}\) \(\newcommand {\mathlarger }[1]{#1}\) \(\newcommand {\mathsmaller }[1]{#1}\) \(\newcommand {\intertext }[1]{\text {#1}\notag \\}\) \(\let \Hat \hat \) \(\let \Check \check \) \(\let \Tilde \tilde \) \(\let \Acute \acute \) \(\let \Grave \grave \) \(\let \Dot \dot \) \(\let \Ddot \ddot \) \(\let \Breve \breve \) \(\let \Bar \bar \) \(\let \Vec \vec \) \(\newcommand {\tothe }[1]{^{#1}}\) \(\newcommand {\raiseto }[2]{{#2}^{#1}}\) \(\newcommand {\LWRsiunitxEND }{}\) \(\def \LWRsiunitxang #1;#2;#3;#4\LWRsiunitxEND {\ifblank {#1}{}{\num {#1}\degree }\ifblank {#2}{}{\num {#2}^{\unicode {x2032}}}\ifblank {#3}{}{\num {#3}^{\unicode {x2033}}}}\) \(\newcommand {\ang }[2][]{\LWRsiunitxang #2;;;\LWRsiunitxEND }\) \(\def \LWRsiunitxdistribunit {}\) \(\newcommand {\LWRsiunitxENDTWO }{}\) \(\def \LWRsiunitxprintdecimalsubtwo #1,#2,#3\LWRsiunitxENDTWO {\ifblank {#1}{0}{\mathrm {#1}}\ifblank {#2}{}{{\LWRsiunitxdecimal }\mathrm {#2}}}\) \(\def \LWRsiunitxprintdecimalsub #1.#2.#3\LWRsiunitxEND {\LWRsiunitxprintdecimalsubtwo #1,,\LWRsiunitxENDTWO \ifblank {#2}{}{{\LWRsiunitxdecimal }\LWRsiunitxprintdecimalsubtwo #2,,\LWRsiunitxENDTWO }}\) \(\newcommand {\LWRsiunitxprintdecimal }[1]{\LWRsiunitxprintdecimalsub #1...\LWRsiunitxEND }\) \(\def \LWRsiunitxnumplus #1+#2+#3\LWRsiunitxEND {\ifblank {#2}{\LWRsiunitxprintdecimal {#1}}{\ifblank {#1}{\LWRsiunitxprintdecimal {#2}}{\LWRsiunitxprintdecimal {#1}\unicode {x02B}\LWRsiunitxprintdecimal {#2}}}\LWRsiunitxdistribunit }\) \(\def \LWRsiunitxnumminus #1-#2-#3\LWRsiunitxEND {\ifblank {#2}{\LWRsiunitxnumplus #1+++\LWRsiunitxEND }{\ifblank {#1}{}{\LWRsiunitxprintdecimal {#1}}\unicode {x02212}\LWRsiunitxprintdecimal {#2}\LWRsiunitxdistribunit }}\) \(\def \LWRsiunitxnumpmmacro #1\pm #2\pm #3\LWRsiunitxEND {\ifblank {#2}{\LWRsiunitxnumminus #1---\LWRsiunitxEND }{\LWRsiunitxprintdecimal {#1}\unicode {x0B1}\LWRsiunitxprintdecimal {#2}\LWRsiunitxdistribunit }}\) \(\def \LWRsiunitxnumpm #1+-#2+-#3\LWRsiunitxEND {\ifblank {#2}{\LWRsiunitxnumpmmacro #1\pm \pm \pm \LWRsiunitxEND }{\LWRsiunitxprintdecimal {#1}\unicode {x0B1}\LWRsiunitxprintdecimal {#2}\LWRsiunitxdistribunit }}\) \(\newcommand {\LWRsiunitxnumscientific }[2]{\ifblank {#1}{}{\ifstrequal {#1}{-}{-}{\LWRsiunitxprintdecimal {#1}\times }}10^{\LWRsiunitxprintdecimal {#2}}\LWRsiunitxdistribunit }\) \(\def \LWRsiunitxnumD #1D#2D#3\LWRsiunitxEND {\ifblank {#2}{\LWRsiunitxnumpm #1+-+-\LWRsiunitxEND }{\mathrm {\LWRsiunitxnumscientific {#1}{#2}}}}\) \(\def \LWRsiunitxnumd #1d#2d#3\LWRsiunitxEND {\ifblank {#2}{\LWRsiunitxnumD #1DDD\LWRsiunitxEND }{\mathrm {\LWRsiunitxnumscientific {#1}{#2}}}}\) \(\def \LWRsiunitxnumE #1E#2E#3\LWRsiunitxEND {\ifblank {#2}{\LWRsiunitxnumd #1ddd\LWRsiunitxEND }{\mathrm {\LWRsiunitxnumscientific {#1}{#2}}}}\) \(\def \LWRsiunitxnume #1e#2e#3\LWRsiunitxEND {\ifblank {#2}{\LWRsiunitxnumE #1EEE\LWRsiunitxEND }{\mathrm {\LWRsiunitxnumscientific {#1}{#2}}}}\) \(\def \LWRsiunitxnumx #1x#2x#3x#4\LWRsiunitxEND {\ifblank {#2}{\LWRsiunitxnume #1eee\LWRsiunitxEND }{\ifblank {#3}{\LWRsiunitxnume #1eee\LWRsiunitxEND \times \LWRsiunitxnume #2eee\LWRsiunitxEND }{\LWRsiunitxnume #1eee\LWRsiunitxEND \times \LWRsiunitxnume #2eee\LWRsiunitxEND \times \LWRsiunitxnume #3eee\LWRsiunitxEND }}}\) \(\newcommand {\num }[2][]{\LWRsiunitxnumx #2xxxxx\LWRsiunitxEND }\) \(\newcommand {\si }[2][]{\mathrm {\gsubstitute {#2}{~}{\,}}}\) \(\def \LWRsiunitxSIopt #1[#2]#3{\def \LWRsiunitxdistribunit {\,\si {#3}}{#2}\num {#1}\def \LWRsiunitxdistribunit {}}\) \(\newcommand {\LWRsiunitxSI }[2]{\def \LWRsiunitxdistribunit {\,\si {#2}}\num {#1}\def \LWRsiunitxdistribunit {}}\) \(\newcommand {\SI }[2][]{\ifnextchar [{\LWRsiunitxSIopt {#2}}{\LWRsiunitxSI {#2}}}\) \(\newcommand {\numlist }[2][]{\text {#2}}\) \(\newcommand {\numrange }[3][]{\num {#2}\ \LWRsiunitxrangephrase \ \num {#3}}\) \(\newcommand {\SIlist }[3][]{\text {#2}\,\si {#3}}\) \(\newcommand {\SIrange }[4][]{\num {#2}\,#4\ \LWRsiunitxrangephrase \ \num {#3}\,#4}\) \(\newcommand {\tablenum }[2][]{\mathrm {#2}}\) \(\newcommand {\ampere }{\mathrm {A}}\) \(\newcommand {\candela }{\mathrm {cd}}\) \(\newcommand {\kelvin }{\mathrm {K}}\) \(\newcommand {\kilogram }{\mathrm {kg}}\) \(\newcommand {\metre }{\mathrm {m}}\) \(\newcommand {\mole }{\mathrm {mol}}\) \(\newcommand {\second }{\mathrm {s}}\) \(\newcommand {\becquerel }{\mathrm {Bq}}\) \(\newcommand {\degreeCelsius }{\unicode {x2103}}\) \(\newcommand {\coulomb }{\mathrm {C}}\) \(\newcommand {\farad }{\mathrm {F}}\) \(\newcommand {\gray }{\mathrm {Gy}}\) \(\newcommand {\hertz }{\mathrm {Hz}}\) \(\newcommand {\henry }{\mathrm {H}}\) \(\newcommand {\joule }{\mathrm {J}}\) \(\newcommand {\katal }{\mathrm {kat}}\) \(\newcommand {\lumen }{\mathrm {lm}}\) \(\newcommand {\lux }{\mathrm {lx}}\) \(\newcommand {\newton }{\mathrm {N}}\) \(\newcommand {\ohm }{\mathrm {\Omega }}\) \(\newcommand {\pascal }{\mathrm {Pa}}\) \(\newcommand {\radian }{\mathrm {rad}}\) \(\newcommand {\siemens }{\mathrm {S}}\) \(\newcommand {\sievert }{\mathrm {Sv}}\) \(\newcommand {\steradian }{\mathrm {sr}}\) \(\newcommand {\tesla }{\mathrm {T}}\) \(\newcommand {\volt }{\mathrm {V}}\) \(\newcommand {\watt }{\mathrm {W}}\) \(\newcommand {\weber }{\mathrm {Wb}}\) \(\newcommand {\day }{\mathrm {d}}\) \(\newcommand {\degree }{\mathrm {^\circ }}\) \(\newcommand {\hectare }{\mathrm {ha}}\) \(\newcommand {\hour }{\mathrm {h}}\) \(\newcommand {\litre }{\mathrm {l}}\) \(\newcommand {\liter }{\mathrm {L}}\) \(\newcommand {\arcminute }{^\prime }\) \(\newcommand {\minute }{\mathrm {min}}\) \(\newcommand {\arcsecond }{^{\prime \prime }}\) \(\newcommand {\tonne }{\mathrm {t}}\) \(\newcommand {\astronomicalunit }{au}\) \(\newcommand {\atomicmassunit }{u}\) \(\newcommand {\bohr }{\mathit {a}_0}\) \(\newcommand {\clight }{\mathit {c}_0}\) \(\newcommand {\dalton }{\mathrm {D}_\mathrm {a}}\) \(\newcommand {\electronmass }{\mathit {m}_{\mathrm {e}}}\) \(\newcommand {\electronvolt }{\mathrm {eV}}\) \(\newcommand {\elementarycharge }{\mathit {e}}\) \(\newcommand {\hartree }{\mathit {E}_{\mathrm {h}}}\) \(\newcommand {\planckbar }{\mathit {\unicode {x210F}}}\) \(\newcommand {\angstrom }{\mathrm {\unicode {x212B}}}\) \(\let \LWRorigbar \bar \) \(\newcommand {\bar }{\mathrm {bar}}\) \(\newcommand {\barn }{\mathrm {b}}\) \(\newcommand {\bel }{\mathrm {B}}\) \(\newcommand {\decibel }{\mathrm {dB}}\) \(\newcommand {\knot }{\mathrm {kn}}\) \(\newcommand {\mmHg }{\mathrm {mmHg}}\) \(\newcommand {\nauticalmile }{\mathrm {M}}\) \(\newcommand {\neper }{\mathrm {Np}}\) \(\newcommand {\yocto }{\mathrm {y}}\) \(\newcommand {\zepto }{\mathrm {z}}\) \(\newcommand {\atto }{\mathrm {a}}\) \(\newcommand {\femto }{\mathrm {f}}\) \(\newcommand {\pico }{\mathrm {p}}\) \(\newcommand {\nano }{\mathrm {n}}\) \(\newcommand {\micro }{\mathrm {\unicode {x00B5}}}\) \(\newcommand {\milli }{\mathrm {m}}\) \(\newcommand {\centi }{\mathrm {c}}\) \(\newcommand {\deci }{\mathrm {d}}\) \(\newcommand {\deca }{\mathrm {da}}\) \(\newcommand {\hecto }{\mathrm {h}}\) \(\newcommand {\kilo }{\mathrm {k}}\) \(\newcommand {\mega }{\mathrm {M}}\) \(\newcommand {\giga }{\mathrm {G}}\) \(\newcommand {\tera }{\mathrm {T}}\) \(\newcommand {\peta }{\mathrm {P}}\) \(\newcommand {\exa }{\mathrm {E}}\) \(\newcommand {\zetta }{\mathrm {Z}}\) \(\newcommand {\yotta }{\mathrm {Y}}\) \(\newcommand {\percent }{\mathrm {\%}}\) \(\newcommand {\meter }{\mathrm {m}}\) \(\newcommand {\metre }{\mathrm {m}}\) \(\newcommand {\gram }{\mathrm {g}}\) \(\newcommand {\kg }{\kilo \gram }\) \(\newcommand {\of }[1]{_{\mathrm {#1}}}\) \(\newcommand {\squared }{^2}\) \(\newcommand {\square }[1]{\mathrm {#1}^2}\) \(\newcommand {\cubed }{^3}\) \(\newcommand {\cubic }[1]{\mathrm {#1}^3}\) \(\newcommand {\per }{\,\mathrm {/}}\) \(\newcommand {\celsius }{\unicode {x2103}}\) \(\newcommand {\fg }{\femto \gram }\) \(\newcommand {\pg }{\pico \gram }\) \(\newcommand {\ng }{\nano \gram }\) \(\newcommand {\ug }{\micro \gram }\) \(\newcommand {\mg }{\milli \gram }\) \(\newcommand {\g }{\gram }\) \(\newcommand {\kg }{\kilo \gram }\) \(\newcommand {\amu }{\mathrm {u}}\) \(\newcommand {\pm }{\pico \metre }\) \(\newcommand {\nm }{\nano \metre }\) \(\newcommand {\um }{\micro \metre }\) \(\newcommand {\mm }{\milli \metre }\) \(\newcommand {\cm }{\centi \metre }\) \(\newcommand {\dm }{\deci \metre }\) \(\newcommand {\m }{\metre }\) \(\newcommand {\km }{\kilo \metre }\) \(\newcommand {\as }{\atto \second }\) \(\newcommand {\fs }{\femto \second }\) \(\newcommand {\ps }{\pico \second }\) \(\newcommand {\ns }{\nano \second }\) \(\newcommand {\us }{\micro \second }\) \(\newcommand {\ms }{\milli \second }\) \(\newcommand {\s }{\second }\) \(\newcommand {\fmol }{\femto \mol }\) \(\newcommand {\pmol }{\pico \mol }\) \(\newcommand {\nmol }{\nano \mol }\) \(\newcommand {\umol }{\micro \mol }\) \(\newcommand {\mmol }{\milli \mol }\) \(\newcommand {\mol }{\mol }\) \(\newcommand {\kmol }{\kilo \mol }\) \(\newcommand {\pA }{\pico \ampere }\) \(\newcommand {\nA }{\nano \ampere }\) \(\newcommand {\uA }{\micro \ampere }\) \(\newcommand {\mA }{\milli \ampere }\) \(\newcommand {\A }{\ampere }\) \(\newcommand {\kA }{\kilo \ampere }\) \(\newcommand {\ul }{\micro \litre }\) \(\newcommand {\ml }{\milli \litre }\) \(\newcommand {\l }{\litre }\) \(\newcommand {\hl }{\hecto \litre }\) \(\newcommand {\uL }{\micro \liter }\) \(\newcommand {\mL }{\milli \liter }\) \(\newcommand {\L }{\liter }\) \(\newcommand {\hL }{\hecto \liter }\) \(\newcommand {\mHz }{\milli \hertz }\) \(\newcommand {\Hz }{\hertz }\) \(\newcommand {\kHz }{\kilo \hertz }\) \(\newcommand {\MHz }{\mega \hertz }\) \(\newcommand {\GHz }{\giga \hertz }\) \(\newcommand {\THz }{\tera \hertz }\) \(\newcommand {\mN }{\milli \newton }\) \(\newcommand {\N }{\newton }\) \(\newcommand {\kN }{\kilo \newton }\) \(\newcommand {\MN }{\mega \newton }\) \(\newcommand {\Pa }{\pascal }\) \(\newcommand {\kPa }{\kilo \pascal }\) \(\newcommand {\MPa }{\mega \pascal }\) \(\newcommand {\GPa }{\giga \pascal }\) \(\newcommand {\mohm }{\milli \ohm }\) \(\newcommand {\kohm }{\kilo \ohm }\) \(\newcommand {\Mohm }{\mega \ohm }\) \(\newcommand {\pV }{\pico \volt }\) \(\newcommand {\nV }{\nano \volt }\) \(\newcommand {\uV }{\micro \volt }\) \(\newcommand {\mV }{\milli \volt }\) \(\newcommand {\V }{\volt }\) \(\newcommand {\kV }{\kilo \volt }\) \(\newcommand {\W }{\watt }\) \(\newcommand {\uW }{\micro \watt }\) \(\newcommand {\mW }{\milli \watt }\) \(\newcommand {\kW }{\kilo \watt }\) \(\newcommand {\MW }{\mega \watt }\) \(\newcommand {\GW }{\giga \watt }\) \(\newcommand {\J }{\joule }\) \(\newcommand {\uJ }{\micro \joule }\) \(\newcommand {\mJ }{\milli \joule }\) \(\newcommand {\kJ }{\kilo \joule }\) \(\newcommand {\eV }{\electronvolt }\) \(\newcommand {\meV }{\milli \electronvolt }\) \(\newcommand {\keV }{\kilo \electronvolt }\) \(\newcommand {\MeV }{\mega \electronvolt }\) \(\newcommand {\GeV }{\giga \electronvolt }\) \(\newcommand {\TeV }{\tera \electronvolt }\) \(\newcommand {\kWh }{\kilo \watt \hour }\) \(\newcommand {\F }{\farad }\) \(\newcommand {\fF }{\femto \farad }\) \(\newcommand {\pF }{\pico \farad }\) \(\newcommand {\K }{\mathrm {K}}\) \(\newcommand {\dB }{\mathrm {dB}}\) \(\newcommand {\kibi }{\mathrm {Ki}}\) \(\newcommand {\mebi }{\mathrm {Mi}}\) \(\newcommand {\gibi }{\mathrm {Gi}}\) \(\newcommand {\tebi }{\mathrm {Ti}}\) \(\newcommand {\pebi }{\mathrm {Pi}}\) \(\newcommand {\exbi }{\mathrm {Ei}}\) \(\newcommand {\zebi }{\mathrm {Zi}}\) \(\newcommand {\yobi }{\mathrm {Yi}}\) \(\let \unit \si \) \(\let \qty \SI \) \(\let \qtylist \SIlist \) \(\let \qtyrange \SIrange \) \(\let \numproduct \num \) \(\let \qtyproduct \SI \) \(\let \complexnum \num \) \(\newcommand {\complexqty }[3][]{(\complexnum {#2})\si {#3}}\) \(\newcommand {\tcbset }[1]{}\) \(\newcommand {\tcbsetforeverylayer }[1]{}\) \(\newcommand {\tcbox }[2][]{\boxed {\text {#2}}}\) \(\newcommand {\tcboxfit }[2][]{\boxed {#2}}\) \(\newcommand {\tcblower }{}\) \(\newcommand {\tcbline }{}\) \(\newcommand {\tcbtitle }{}\) \(\newcommand {\tcbsubtitle [2][]{\mathrm {#2}}}\) \(\newcommand {\tcboxmath }[2][]{\boxed {#2}}\) \(\newcommand {\tcbhighmath }[2][]{\boxed {#2}}\) \(\newcommand {\toprule }[1][]{\hline }\) \(\let \midrule \toprule \) \(\let \bottomrule \toprule \) \(\def \LWRbooktabscmidruleparen (#1)#2{}\) \(\newcommand {\LWRbooktabscmidrulenoparen }[1]{}\) \(\newcommand {\cmidrule }[1][]{\ifnextchar (\LWRbooktabscmidruleparen \LWRbooktabscmidrulenoparen }\) \(\newcommand {\morecmidrules }{}\) \(\newcommand {\specialrule }[3]{\hline }\) \(\newcommand {\addlinespace }[1][]{}\) \(\def \LWRsiunitxrangephrase { \protect \mbox {to} }\) \(\def \LWRsiunitxdecimal {.}\)

3 Interlocking and line automation

Interlocking is a set of equipments employed to prevent train collisions while allowing trains to go to their destinations. This chapter will explain some basic concepts and includes a task at the end that you can try to do yourself.

Please note that this chapter is also intended to be used as a reference, so some things may be explained in a way that is not easy to understand at first. If that is the case, the following links may be helpful, albeit possibly outdated:

It is also recommended for new players to read through the entire section to understand various concepts of the interlocking system before following the instructions in the subsections. Section B includes certain examples that may be helpful.

Exercise 2

After you finish reading this section, set up interlocking for the three-station setup shown below.

(-tikz- diagram)

3.1 Basic concepts of interlocking

Unlike road traffic, trains are not always able to brake to a complete stop within a distance that the driver can see. It is therefore required that the track ahead of a train is secured using technical means1 in such a way that the train can run on the tracks safely even when the driver has limited sight. Among other things, it is necessary that

  • The train does not run into another train unless this is intended for the purpose of shunting.

  • Track components (in particular, turnouts) are not modified while the train is running on the tracks.

1 In terms of Advtrains, the track is secured by the interlocking system.

IRL: Flanking and flank protection

In addition to preventing collisions from the front (and, implicitly, the rear) end of the train, real-life rail operation additionally involves preventing accidents in which one train (usually a runaway train) collides into the side of another train. This is known as flanking:

(-tikz- diagram)

In the above example, the turnout T must be set to the straight direction to prevent the two trains from colliding, even if this turnout does not need to be locked in normal operation.

While prevention against such accidents (known as flank protection) is possible with Advtrains’ interlocking system, this currently comes at a cost of lower capacity due to internal limitations of the interlocking system, while the risk of flanking from runaway trains is generally low enough to be tolerable.

A path along such tracks, along with the states that various components should be put into for safe operation, is called a route . A route can be set only if the above conditions can be met. Such a route are sometimes described as being available . The system used for setting routes is called routesetting . After setting a route, track components can no longer be adjusted, and conflicting routes for other trains are not allowed to be set.

Note that setting conflicting routes is not allowed in the sense that the interlocking system would not allow such paths to be set.2 However, this alone does not directly prevent a train from proceeding along a potentially dangerous path. Therefore, the signaling system is needed to make sure that trains only follow routes that are set for the train to travel along. Signals are described in detail in section 4.

Note that there is a subtle but important difference between rail and road traffic. A rail signal showing that the route ahead is clear indicates that the train may safely proceed to the next signal and that there is no obstacle along the route. A green light in road traffic does not guarantee this - it can be green even in a traffic jam, in which case blindly driving ahead likely has undesirable results.

To guarantee that the route ahead is clear, Advtrains uses a system known as fixed block signaling. Tracks are divided into sections , and each section should not be occupied by more than one train at a time (with the exception of call-on routes). Routes are then set by reserving the track sections along the route until the train passes through the section. A route can therefore only be set if none of the sections along the route is occupied by or reserved for a different train.

2 There are also Luanti-specific situations that the interlocking system cannot guard against, such as manually placing wagons along a set route.

IRL: Moving block signaling

Some signaling systems in real life additionally use moving block signaling, in which blocks are defined based on the position of the trains and trains only need to keep sufficient distance between each other.

(-tikz- diagram)

Advtrains does not support moving block signaling.

3.2 TCBs

Track circuit breaks (TCBs) are nodes that can be assigned to two-way tracks and indicate the limits of track sections. TCBs have two sides - each corresponding to a direction of the track that the TCB is assigned to - that can be assigned to two track sections.

To assign a TCB to a track:

  • Place a TCB, ideally adjacent to the track it will be assigned to.

  • Right-click the TCB.

  • You will be told in the chat to punch a track to assign the TCB to. Punch the track to assign the TCB to - this track will, as explained in later subsections, form the boundary of track sections.

  • A TCB marker showing the two sides (A and B) will appear on the track you have assigned the TCB to. This will be explained in further detail below.

After assigning the TCB, you can right click it to open the TCB formspec. This will be used in the following sections. Please note that the TCB formspec has a section for side A and one for side B - when following the instructions in the following subsections, make sure you click the button for the right TCB side. The two sides of the TCB are assigned based on the orientation of the tracks. In particular, straight tracks with different orientations can still appear visually the same. For this reason, most graphs in the rest of this chapter will use cardinal directions instead of actual TCB sides, or omit TCB sides if these are irrelevant.

For new players, it is recommended to set up all TCBs before creating new track sections.

3.3 Track sections

In terms of interlocking, track sections are segments of tracks that can be occupied by a train or reserved for a train to pass. The following graph shows TCBs and sections along a line segment. For simplicity, letters are used instead of actual coordinates and IDs.

(-tikz- diagram)

Section \(a\) begins at the side A of \(P\) (sometimes written as \(P/\mathrm {A}\)) and extends to the west beyond the graph. Section \(b\) is limited by \(P/\mathrm {B}\) and \(Q/\mathrm {A}\), effectively spanning the line segment \(\overline {PQ}\). \(Q/\mathrm {B}\) is not part of any track section and is therefore known as end of interlocking or EOI, as the track beyond it is not part of the interlocking system.

The graph below shows a track segment where \(P\), \(Q\), and \(R\) form a section around the turnout \(T\). Notice that a train entering from \(Q\) cannot directly reach \(R\) without reversing (or vice versa), while a train entering from \(P\) can reach both \(Q\) and \(R\).

(-tikz- diagram)

To create a track section, punch a track along the section while holding down Aux1. Alternatively, you can also click on “Create new track section” in the TCB formspec. This should create a new track section and add the TCB side to the track section. Other track sides that face the track side you created the TCB with will also be added to the track section. In the graph above, creating a track section at the west side of \(Q\) will automatically add the south-west side of \(R\) and the east side of \(P\) to the track section.

After the track section is created, you can open the track section formspec by right-clicking a track with the trackworker or clicking on “Show track section” in the TCB formspec. The track section formspec allows, among other things, setting route locks (see section 3.6).

Note that placing TCBs inside a track section causes the section to be split. Conversely, removing a TCB merges the sections on both sides of the TCB.

3.4 Signals

Each TCB side can have a signal assigned to the side. The signal will then indicate whether the train is allowed to enter the section to which the same TCB side is assigned to. Signals need to be set up in order to be able to set up routes. In the previous graph, in order to let trains move from \(P\) to \(Q\) or \(R\), a signal needs to be set up on the side of \(P\) that faces the track section (i.e. the east side of \(P\)). For an overview of the signals available in Advtrains, refer to section 4. Signals should conventionally face the opposite direction of the side of the TCB so that the driver can see the signals. Signals can be assigned automatically by setting the influence point (see below) for the signal or manually with the “Assign a signal” button in the TCB formspec.

Every signal can optionally have an influence point. This is the point where the aspect of the signal becomes effective, and should be located before the train passes the TCB side that the signal is assigned to. The influence point for signals that are independent of track sections is irrelevant, but should conventionally be close to the signal. The influence point can be set and changed in the signal formspec. This can be opened by right-clicking (and, if the signal is already assigned to a TCB, additionally holding down Aux1) the signal.

3.5 Routes

As explained earlier, routes are paths along the track that trains can safely travel on. A route includes sections along the route and (optionally) components that need to be locked for the train to travel safely. Routes are bound to TCB sides, but they usually need to start at ones with a signal assigned.

3.5.1 Creating routes

Since version 2.5.0, routes can be created automatically with the Smart Route tool:

  • 1. Click on “Smart Route”.

  • 2. Click on “Search further” until all desired routes appear in the form.

  • 3. Click on “Apply”.

In the Smart Route tool, the length of the route is the number of sections that the train passes along the route.

Routes can also be created manually:

  • 1. Click on “New (Manual)”.

  • 2. Set up passive components (e.g. turnouts) in the section appropriately and lock them by punching, if necessary.

  • 3. Punch the next TCB that the train should pass. The track that the TCB is assigned to should have a marker showing “END ROUTE”.

  • 4. If the following track section is the last track section in the route and does not require any further setup from step 2 or have more than two TCB sides, click “Finish route at the end of NEXT section”.

  • 5. If the route leads to the end of the physical line, click “Finish route at the end of NEXT section”.

  • 6. If the route ends at the TCB, click “Finish route HERE”.

  • 7. If the route continues beyond the TCB, click “Advance to next route section” and repeat the above steps, starting from step 2.

You can also click “Finish route at the end of NEXT section” at the starting TCB. This can be useful when the last part of a route does not involve setting up further passive components or when the route continues to a dead end.

If the TCB is not considered suitable for route continuation, please check that the side of the TCB from which the train passes the TCB is part of a track section and that the train can reach there without passing a point assigned to another TCB. If you see “Advancing over next section is impossible at this place. End of interlocking.”, please check that the side of the TCB corresponding to the driving direction is part of a track section.

(-tikz- diagram)

After finishing the route, you are prompted for the name of the route. It is recommended to use a sensible name. You should then see the route formspec. If you don’t, click on the name of the route you just created and click “Edit route”, and proceed to the next section regarding ARS.

End of routes

The Smart Route tool requires routes to always end at a signal that is not a pure distant signal. Bumpers built with Advtrains 2.5.0 and later internally include a TCB with a signal assigned to the same position and can therefore be used at the end of the route.

When manually creating routes, it is possible to end the route at a TCB without a signal. However, doing so is generally discouraged as it often counters the goal of interlocking: trains can move beyond the extent of the route without any benefits of the interlocking system.

3.5.2 Editing routes

Routes can be edited by selecting the route in the signaling formspec and clicking “Edit”.

The editing form shows a list of entries that are part of the route. An example is shown below:

(+) Route #3
1 (254 9 246) / B (o)
= 01996977 =
L 800980FE80F5 -> cr
2 (251 9 238) / A (o)
= 22738001 = [CO]
E (251 9 227) / A (R)
(More Options)

The first line indicates that the route is the third route in the list of route. If the first signal is named, the name of the signal is shown instead of +.

The second, fifth, and seventh lines each indicate a TCB. The first column (1, 2, and E, respectively) indicates the order in which the TCB appears in the route. E indicates that the route ends at the given TCB. The numbers in parentheses before the / symbol indicate the position of the track that the TCB is assigned to; for example, (254 9 246) indicates that the TCB is assigned to the track located at (254, 9, 246). The letter after the / symbol indicates the side of the TCB that the route begins or continues into. The final column indicates the name of the signal assigned to the side of the TCB (e.g. R); the name is enclosed in parentheses. (o) indicates that the signal is not explicitly assigned a name; (-) indicates that the TCB side does not have a signal assigned to it.

If a signal is assigned to a TCB side, selecting a line representing a TCB allows adjusting the signal aspect displayed by the signal if the route is set. The “Announce distant signal” option controls whether the signal should additionally act like a distant signal (i.e. report the aspect of the next signal).

The third and sixth lines indicate track section between the two TCBs. The name (or, if no name is explicitly set, the ID) of the section is shown delimited by equals signs; = 01996977 = indicates the section with the name or (in this case) the ID 01996977. [CO] indicates a call-on section (see below).

If a line representing a track section is selected, it is possible to control whether this section is a call-on section. If selected, this option allows trains to enter the section even if it is occupied.

The fourth line indicates a route lock (see 3.6). The hexadecimal string indicates the position of the passive component.3 The text after arrow symbol (->) indicates the state that the passive component is locked to. In this example, the component is locked to the cr state, which is the diverging (i.e. curved) direction of a turnout.

The last line allows selecting further options. The “Auto lock turnouts” option controls whether turnouts along the route should be automatically locked.

The route editing form additionally includes the following options:

  • Route name (UI element)

    Displays the name of the route. Clicking the adjacent “Set” button sets the name.

  • <<< (UI element)

    Displays the editing form for the previous route.

  • >>> (UI element)

    Displays the editing form for the next route.

  • <k>/<n> (UI element)

    Returns to the signaling form. <k> indicates the position of the currently viewed route within the route list, and <n> indicates the total number of routes at the TCB side.

  • Delete route (UI element)

    Deletes the currently viewed route.

  • Back to signal (UI element)

    Returns to the signaling form.

  • Clone Route (UI element)

    Creates a route with the same configuration as the currently viewed route.

  • New From Route (UI element)

    Begins manual route programming mode using the configuration of the currently viewed route.

  • ARS Rule List (UI element)

    The ARS rules for selecting the route (see 3.7). Clicking the adjacent “Save ARS List” button saves the ARS rules.

3 This is encoded in an older format that is still used by some parts of Advtrains. The position is encoded in as a 3-tuple à 4 hexademical digits indicating the Y, X, and Z coordinates, where each value is shifted by 32768 (0x8000). In this example, 800980FE80F5 encodes the position (254, 9, 245).

3.6 Locking passive elements

As explained at the beginning of this section, there are situations in which one may need to lock further passive components (e.g. level crossings) along the route.

The “old” method of locking passive components is to lock these elements as part of manually programming the route(). This method has multiple drawbacks:

  • Locks need to be set up for every route that involves the passive components in question. These routes also need to be reprogrammed if passive components are adjusted (e.g. if a road is widened and requires the level crossing signals to be moved).

  • The Smart Route system is not able to detect the presence of other passive components besides turnouts. It is therefore not possible to use route locks for routes created with the Smart Route tool.

To address these problems, Advtrains 2.5.0 and later also allow locking passive components for individual track sections, independently of routes. Such locks can be set in the track section formspec.

3.7 Automatic routesetting

Automatic routesetting (ARS) is a method of choosing a route based on a set of matching patterns. In the previous section, you learned to set up a route, and there is a text input box where you can enter the ARS rules. This area is empty by default, which means that the route is not selected in any case.

ARS rules are expresses in a way comparable to disjunctive normal forms. A route can be selected if one of the rules (and all subsequent rules that are part of the same conjunctive form) is satisfied.

Rules are delimited by at least one newline character, and each line may contain one of the following:

  • # <comment> (pattern)

    Comment. Does not match any train.

  • & <base rule> (pattern)

    Matches trains that satisfy the given <base rule> and the rule defined in the previous line. Available since 2.6.0.

  • [priority] <base rule> (pattern)

    Matches trains that satisfy the given <base rule>. Since 2.6.0, [priority] may be specified for multi-ARS.

  • [priority] * (pattern)

    Matches all trains. Since 2.6.0, [priority] may be specified for multi-ARS.

<base rule> may be one of the following:

  • LN <line> (pattern)

    Matches trains with the exact line name <line>.

  • RC <routing code> (pattern)

    Matches trains that contain the routing code <routing code>.

  • TL [min]-<max> (pattern)

    Matches trains that are less than <max> wagons long and (if specified) at least [min] wagons long. Available since 2.7.0.

  • TL <min> (pattern)

    Matches trains that are at least <min> wagons long. Available since 2.7.0.

A whitespace is required before the argument. <base rule> may be prepended with an exclamation mark (!), in which case the condition is negated, i.e., the rule matches trains that do not satisfy the given requirement.

The following demonstrates an annotated example of ARS rules.

# Matches trains with line A and without the routing code FREIGHT
LN A
& !RC FREIGHT

# Matches trains with line 1
*
& LN 1

The default rule is the * rule. The conjunction containing the default rule is always evaluated last, i.e. if all other rules do not match.

A default route is a route where only the conjunction including the default rule is satisfied. The route in the above example is a default route only if the approaching train has the line 1.

The priority of a route is the numeric value associated with the first matching rule for a route. A higher numeric values indicates lower priority.

ARS differentiates between selecting and setting routes. The former defines which routes may be set, while the latter defines which route is used by the train.

ARS selects and sets routes in the following order:

  • If a matching non-default route does not define a priority value, the first such route is selected, regardless of whether it can be set.

  • If all matching non-default routes include a priority value, all matching routes are selected (regardless of whether one can be set), and the available route with the highest priority is set.

  • If all matching routes are default routes, the routes are selected analogously based on the above rules with regard to priority.

The mechanism for selecting multiple routes is known as multi-ARS .

Consider the following example:

# Route 1
LN 1

# Route 2
2 RC R
LN 1

# Route 3
0 RC R

# Route 4
*

In the above example,

  • Trains with the line number 1 only take the route 1, waiting for the route to become available if necessary.

  • Trains with the routing code R (and without the line number 1) only take either route 2 or route 3, waiting for one of the routes to become available if necessary. Route 3 is taken if both routes are available.

  • All other trains only take the route 4, waiting for it to become available if necessary.

3.8 Automatic working

Automatic working is a system that sets the route after the train passes the signal. To enable automatic working, click on “Enable Automatic Working” in the signal formspec after the route is set. Clicking on the same button again will disable automatic working.

3.9 Station/stop tracks

Station/stop tracks (sometimes simply called station tracks) are special tracks that register a station where a train should stop. The interface of the formspec should be self-explanatory, with a few things to notice:

  • You need to click “Save” after changing the settings.

  • The station code is used to identify the station. The station name is shared among all tracks with the same station code (not vice versa).

  • Station tracks disable ARS for the specific train when the train arrives at the station and enables ARS on the train before departure.

3.10 Considerations for interlocking

The previous sections were mainly theoretical in that the sections mostly introduced new concepts or described how to do things. This section will focus on the practical part of interlocking, in particular certain things to consider when setting up interlocking on a rail line.

3.10.1 Junctions and grade separation

One of the most important considerations when setting up interlocking at a junction is to make sure that multiple trains can go through the junction at the same time when possible.

Consider the junction from exercise 1. Try to interlock the junction based on what you have learned in the last few sections.

The lazy method would be to set up the entire junction as a single track section - you only need 6 TCBs for that. However, a train passing through would occupy the entire junction, even when two trains could use the junction at the same time - for example, a train going from east to west and another one from west to east. This can be solved by a slightly more complicated setup with four sections, each shown below with a different color:

(-tikz- diagram)

It is also possible to build the junction on multiple levels. This is known as grade separation. Note that grade-separated junctions may appear less realistic because slopes are significantly steeper than their real-life counterparts.

Exercise 3

Build a grade-separated double-track T junction.

3.10.2 Track capacity and deadlock

It is not possible to run an infinite number of trains on a line. Adding too many trains to a line can result in a deadlock, where every train is stuck at a red signal, waiting for the previous train to clear the track section ahead, while the previous train is also stuck at a red signal, waiting for the train ahead of it to leave the section ahead, and so on:

(-tikz- diagram)

This problem can be trivially solved by removing a train and, if necessary, resetting the track section that the train previously occupied (this can be done in the track section formspec):

(-tikz- diagram)

However, only the train at the bottom-right can move; other trains have to wait for the trains ahead to leave the section. The ideal situation is that the section length and the number of trains are decided in such a way that trains do not have to stop or slow down between stations:

(-tikz- diagram)

When actually building a rail line, signals are spaced away much further than in the illustration above. On servers, the distance between signals typically range between about 50 nodes to a few hundred, depending on the speed at which trains run on the line and the number of trains using the line. The distance between signals in station areas usually depend on the size of the station.

Single-track sections can also be a source of deadlocks:

(-tikz- diagram)

With single-track sections, routes should generally be set up in a way that the train does not stop in single track sections (like train A in the above diagram):

(-tikz- diagram)

In the modified setup, the leftmost signal requires the entire marked area to be clear, avoiding the deadlock situation described earlier. However, this also reduces the capacity of the line.

Note that the end of the track (e.g. train B) is an exception, where the train has to stop and reverse. Removing train B in the original setup is not guaranteed to resolve the deadlock, as a train approaching from the west may enter the area, restoring the original situation.

3.10.3 Short routes

In some cases, there may be setups with very short routes. In particular, if the length of a route is shorter than the braking distance of the train for which the route is set, the signal at the end of the route will be triggered to set a route.

If short routes are desired, such as at stations, it is generally recommended to disable ARS for the train, such as by using the A0 ATC command, and keep some distance between the influence point of the signal and the point at which the train is expected to stop. Alternatively, you can also limit the speed of the train to trigger the routesetting system later, but this is not the ideal solution in most use cases of short routes.