From version 3.3, Train Director allows scenario creators to specify both the behavior and the appearance of individual signals.

The introduction of this functionality allows the display of the aspects of the signals for distant signals, distant and protection signals, for signals specifying a reduction in speed based on the selected itinerary and so on.

Moreover, it is now possible to display the signal aspects used by different railroad administrations.

All of this is implemented by using text files that are independent from the scenario. These files describe the icons to use, the behavior of the train when approaching the signal, and how to decide the aspect of the signal based on line conditions.

These text files are called "Train Director Scripts", or simply ".tds files".

A .tds file can be associated to one or more signals. The association is specified through the "Signal Properties" dialog.

 


This is an example of a .tds file:

# One light signal (red,yellow,green)

Aspect: red
    IconE: rE.xpm
    IconW: rW.xpm
    IconS: rS.xpm
    IconN: rN.xpm
    Action: stop

Aspect: yellow
    IconE: yE.xpm
    Action: proceed

Aspect: green
    IconE: gE.xpm
    Action: proceed

OnInit:
    .aspect = red
end

OnCleared:
    if .aspect = red
        if next.aspect = red
            .aspect = yellow
        else
            .aspect = green
        end
    end
end

OnUpdate:
    if .aspect = red
        return
    end
    if next.aspect = red
        .aspect = yellow
    else
        .aspect = green
    end
end

Let's describe each section of the file:

Comments

The first row of the file is a comment, and shows the type of the signal:

# One light signal (red,yellow,green)

All characters from the # included to the end of the row will be ignored by the program.

Comments are completely optional, so you don't have to use them. However their presence is a big help to other authors who want to better understand the logic of the file and to which signal to apply it to.

Aspects

The next section describes the various aspects that the signal can show:

Aspect: red
    IconE: rE.xpm
    IconW: rW.xpm
    IconS: rS.xpm
    IconN: rN.xpm
    Action: stop

Aspect: yellow
    IconE: yE.xpm
    Action: proceed

Aspect: green
    IconE: gE.xpm
    Action: proceed

The name of the aspect is indicated by the "Aspect:" rows. In this case we have 3 aspects: "red", "yellow", and "green".

For each aspect, it's necessary to specify the icon to display when the signal is in the corresponding state "for each of the 4 directions", east, west, north, south.

If the scenario does not use signals directed to north or south, the corresponding directions can be omitted.

In this page's examples we'll only use the east direction, assuming that the author will have to specify the other directions as well.

It is also possible to specify more than one icon per each direction. The various icons will be displayed in sequence, going back to the first icon after the last one has been displayed. This feature allows to "animate" the signal, for example to show flashing signals. For example:

Aspect: blinking_yellow
    IconE: yellowE.xpm blackE.xpm
    Action: speedLimit 60

In addition to the icon file, every aspect has associated an action, specified in the "Action:" rows. This action will be executed when a train is traveling in the track section preceding the signal. The possible actions are:

  • "stop": the signal cannot be crossed. The train will stop before the signal.
  • "proceed": the signal can be crossed without specific restrictions. The train will proceed beyond the signal.
  • "speedLimit X": the signal can be crossed at speed X (replace X with a number). The train will start to decelerate before reaching the signal; that means that the signal behaves like a speed limit associated to the track element linked to the signal.
  • "none": the signal is ignored by trains; clicks on the signal's icon will also be ignored. The signal is fully controlled by the program. Distant signals use this action, since their aspect depends solely on the condition of the track section after them.

With these simple instructions it's possible to create a number of cases, so that one can describe the most common combinations.

The following sections tell to the program when to change the aspect of the signal.

Events and Conditions

Obviously, a signal must change its aspect when certain conditions on the layout occur. These conditions can be generated both by the player and by trains movement.

Let's consider for each condition which actions can be applied.

OnInit : when the scenario is loaded

The actions associated with "OnInit:" are executed when the scenario is opened the first time. Typically the associated action is the definition of the initial aspect of the signal (usually red).

OnInit:
    .aspect = red
end

Let's examine in greater detail the syntax to use in this section of the .tds file.

The section starts with the event that we are describing, that is "OnInit:".

After the name of the event, we specify a sequence of actions in the form of expressions. In this case, ".aspect = red" means "change the signal aspect according to the instructions in the "Aspect: red" section.".

Assigning a name to the aspect tells Train Director to change the icon and the action associated with that signal, using the information specified in the corresponding "Aspect:" section.

The use of the "dot" in ".aspect", indicates that we are referring to the signal associated with this .tds file. We'll see later how is possible to refer to other signals.

The section is always terminated by a row with the word "end".

OnCleared : the user clears the signal

When the user clicks on the signal's icon, if the following track section is clear Train Director will examine the instructions associated to the "OnCleared:" event to decide how to change the signal's aspect. In this case, the actions to carry out are more complex:

OnCleared:
    if .aspect = red
        if next.aspect = red
            .aspect = yellow
        else
            .aspect = green
        end
    end
end

As you can see, it's possible to query if certain conditions are valid by using the "if" word. In the first row we are checking whether the current aspect of the signal is red ("if .aspect = red"). If it isn't, the program ignores all actions included between the "if" row and the corresponding "end".

If instead the condition is true, the program continues with the execution of the next row. In this example, we check what is the aspect of the next signal after the current one ("if next.aspect = xxxx"). As you can see, the use if the word "next" before the word ".aspect" tells Train Director to "look ahead" in the track section protected by the signal. It is also possible to look ahead 2 or 3 track sections, by simply concatenating multiple "next" words, as in "next.next.aspect".

Therefore, if the next signal is red ("if next.aspect = red"), then the current signal should display a get ready to stop aspect; to do this, we change its aspect to yellow (".aspect = yellow").

If instead the next signal is not red, Train Director will examine the actions associated to the "else" word, in this case by changing the aspect of the signal to green (".aspect = green").

Note how to each "if" always corresponds an "end" (2 ifs, 2 ends plus the end-of-section "end"). The convention to shift to the right the instruction related to each "if" helps in understanding which condition controls the execution of those instructions.

OnUpdate : another signal has changed aspect

When another signal on the layout has changed aspect, Train Director will execute the instructions associated with the "OnUpdate:" section. This allows changing the aspect of a signal when the signal in the controlled track section changes aspect. In our example:

OnUpdate:
    if .aspect = red
        return
    end
    if next.aspect = red
        .aspect = yellow
    else
        .aspect = green
    end
end

The logic is as follows: if the current signal is red, no action is performed; the row with the "return" word tells Train Director to ignore all the following instructions for this signal.

If the current signal is not red, then we need to look at the next signal to verify its aspect ("if next.aspect = xxxx").

If the next signal has become red, then we need to change the aspect of the current signal to yellow (".aspect = yellow").

If the next signal is not red, then we need to change the aspect of the current signal to green (".aspect = green").

 

By specifying the signal's behavior in the way just described allows the representation of many combinations specified in the "Regolamento Segnali" of Trenitalia, and hopefully of other international railroad administrations.

In the following page we present more complex cases.