Difference between revisions of "NML:Random switch"
Andythenorth (talk | contribs) (Add road types and tram types to bits and triggers table) |
Andythenorth (talk | contribs) |
||
(4 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
{{NMLNavBlocksyntax}} |
{{NMLNavBlocksyntax}} |
||
+ | |||
+ | == Syntax == |
||
While a [[NML:Switch|switch-block]] allows making a predictable decision, a random_switch allows a randomised choice between several options. |
While a [[NML:Switch|switch-block]] allows making a predictable decision, a random_switch allows a randomised choice between several options. |
||
Line 8: | Line 10: | ||
(<probability>: <return_value>;)+ |
(<probability>: <return_value>;)+ |
||
} |
} |
||
+ | |||
+ | == Feature and Type == |
||
The first parameter <code style="color:darkgreen"><feature></code> specifies the feature to use. <code style="color:darkgreen"><type></code>, the second parameter, is used to define what random data is used. The supported combinations are listed in the following table. The amount of random data is given in the third column. The maximum number of possible combinations is equal to 2^x, with x being the number of random bits. Not all combinations support re-randomizing via triggers, this is indicated in the fourth column. The last column specifies the object of which the random data is used. |
The first parameter <code style="color:darkgreen"><feature></code> specifies the feature to use. <code style="color:darkgreen"><type></code>, the second parameter, is used to define what random data is used. The supported combinations are listed in the following table. The amount of random data is given in the third column. The maximum number of possible combinations is equal to 2^x, with x being the number of random bits. Not all combinations support re-randomizing via triggers, this is indicated in the fourth column. The last column specifies the object of which the random data is used. |
||
− | {| class=" |
+ | {| class="wikitable sortable" |
! Feature |
! Feature |
||
! Type |
! Type |
||
Line 20: | Line 24: | ||
| Vehicles |
| Vehicles |
||
| SELF |
| SELF |
||
+ | | 8 {{ottdp|14.0|no}} 16 |
||
− | | 8 |
||
| Yes |
| Yes |
||
| Vehicle itself |
| Vehicle itself |
||
Line 26: | Line 30: | ||
| Vehicles |
| Vehicles |
||
| PARENT |
| PARENT |
||
+ | | 8 {{ottdp|14.0|no}} 16 |
||
− | | 8 |
||
| No |
| No |
||
| Leading engine |
| Leading engine |
||
Line 32: | Line 36: | ||
| Vehicles |
| Vehicles |
||
| BACKWARD_SELF(x) |
| BACKWARD_SELF(x) |
||
+ | | 8 {{ottdp|14.0|no}} 16 |
||
− | | 8 |
||
| No |
| No |
||
| Count x vehicles backward (away from the engine), starting at the vehicle itself <ref name=expression>x can be any expression. It may access parameters, registers, or variables of the vehicle itself. Uses register 0x100 if x is not a constant expression between 1 and 15</ref> |
| Count x vehicles backward (away from the engine), starting at the vehicle itself <ref name=expression>x can be any expression. It may access parameters, registers, or variables of the vehicle itself. Uses register 0x100 if x is not a constant expression between 1 and 15</ref> |
||
Line 38: | Line 42: | ||
| Vehicles |
| Vehicles |
||
| FORWARD_SELF(x) |
| FORWARD_SELF(x) |
||
+ | | 8 {{ottdp|14.0|no}} 16 |
||
− | | 8 |
||
| No |
| No |
||
| Count x vehicles forward (towards the engine), starting at the vehicle itself <ref name=expression /> |
| Count x vehicles forward (towards the engine), starting at the vehicle itself <ref name=expression /> |
||
Line 44: | Line 48: | ||
| Vehicles |
| Vehicles |
||
| BACKWARD_ENGINE(x) |
| BACKWARD_ENGINE(x) |
||
+ | | 8 {{ottdp|14.0|no}} 16 |
||
− | | 8 |
||
| No |
| No |
||
| Count x vehicles backward, starting at the leading engine <ref name=expression /> |
| Count x vehicles backward, starting at the leading engine <ref name=expression /> |
||
Line 50: | Line 54: | ||
| Vehicles |
| Vehicles |
||
| BACKWARD_SAMEID(x) |
| BACKWARD_SAMEID(x) |
||
+ | | 8 {{ottdp|14.0|no}} 16 |
||
− | | 8 |
||
| No |
| No |
||
| Count x vehicles backward, starting at the first vehicle in the chain with the same ID <ref name=expression /> |
| Count x vehicles backward, starting at the first vehicle in the chain with the same ID <ref name=expression /> |
||
Line 102: | Line 106: | ||
| Object tile (different per tile) |
| Object tile (different per tile) |
||
|- |
|- |
||
+ | | Railtypes |
||
− | | Rail types |
||
| SELF |
| SELF |
||
| 2 |
| 2 |
||
Line 108: | Line 112: | ||
| Rail tile (pseudo-random, based on location) |
| Rail tile (pseudo-random, based on location) |
||
|- |
|- |
||
+ | | Roadtypes |
||
− | | Road types |
||
| SELF |
| SELF |
||
| 2 |
| 2 |
||
Line 114: | Line 118: | ||
| Road tile (pseudo-random, based on location) |
| Road tile (pseudo-random, based on location) |
||
|- |
|- |
||
+ | | Tramtypes |
||
− | | Tram types |
||
| SELF |
| SELF |
||
| 2 |
| 2 |
||
Line 123: | Line 127: | ||
<references /> |
<references /> |
||
+ | == ID == |
||
⚫ | |||
+ | The third parameter <code style="color:darkgreen"><ID></code> can be used to refer to this block from other (random-)switch-blocks. |
||
− | {| class="t" |
||
+ | |||
+ | == Triggers == |
||
+ | |||
⚫ | The last parameter <code style="color:darkgreen"><triggers></code> is optional and allows re-randomizing when certain conditions occur. The events and accompanying trigger names are given in the following tables. To re-randomize graphics when any of a set of events occurs, use <code style="color:darkgreen">bitmask(TRIGGER_A, TRIGGER_B, .. , TRIGGER_Z)</code> To re-randomize only when ''all'' of the events have occured, add <code style="color:darkgreen">TRIGGER_ALL_NEEDED</code> to the list of used triggers, e.g. use <code style="color:darkgreen">bitmask(TRIGGER_ALL_NEEDED, TRIGGER_A, ...)</code> |
||
+ | |||
+ | === Vehicles === |
||
+ | |||
+ | {| class="wikitable sortable" |
||
|+ Vehicle triggers |
|+ Vehicle triggers |
||
|- |
|- |
||
Line 149: | Line 161: | ||
To re-randomize when the consist has been emptied and then receives new cargo, use <code style="color:darkgreen">bitmask(TRIGGER_VEHICLE_UNLOAD_ALL, TRIGGER_VEHICLE_ANY_LOAD, TRIGGER_ALL_NEEDED)</code> |
To re-randomize when the consist has been emptied and then receives new cargo, use <code style="color:darkgreen">bitmask(TRIGGER_VEHICLE_UNLOAD_ALL, TRIGGER_VEHICLE_ANY_LOAD, TRIGGER_ALL_NEEDED)</code> |
||
+ | === Stations === |
||
− | {| class="t" |
||
+ | |||
+ | {| class="wikitable sortable" |
||
|+ Station triggers |
|+ Station triggers |
||
|- |
|- |
||
Line 181: | Line 195: | ||
|} |
|} |
||
− | + | All triggering events involve a cargo-type (which arrives, is loaded, or unloaded). The triggers only apply to a station section, if the cargo-type is listed in the property <code style="color:darkgreen">cargo_random_triggers</code>. |
|
+ | The last four triggers in the table only trigger on the platform on which they occur. |
||
− | {| class="t" |
||
+ | |||
+ | Note that triggers are only saved per-station, not per-tile, so using <code style="color:darkgreen">TRIGGER_ALL_NEEDED</code> doesn't make a lot of sense for per-platform triggers; or in general, if a station is composed of sections from different NewGRF. |
||
+ | |||
+ | === Houses === |
||
+ | |||
+ | {| class="wikitable sortable" |
||
|+ House triggers |
|+ House triggers |
||
|- |
|- |
||
Line 198: | Line 218: | ||
Using <code style="color:darkgreen">TRIGGER_HOUSE_TOP_TILELOOP</code>, it is possible to re-randomize the whole building as one unit. All tiles of a multi-tile house will get the same new random data. |
Using <code style="color:darkgreen">TRIGGER_HOUSE_TOP_TILELOOP</code>, it is possible to re-randomize the whole building as one unit. All tiles of a multi-tile house will get the same new random data. |
||
+ | === Industry tiles === |
||
− | {| class="t" |
||
+ | |||
+ | {| class="wikitable sortable" |
||
|+ Industry tile triggers |
|+ Industry tile triggers |
||
|- |
|- |
||
Line 215: | Line 237: | ||
Industry tiles can rerandomise both their own random bits as well as the random bits of the industry (via type <code style="color:darkgreen">PARENT</code>). The triggers for rerandomisation are in both cases shared per tile (when using <code style="color:darkgreen">TRIGGER_ALL_NEEDED</code>), i.e. the triggers are in all cases independent for different tiles. Industries have random bits. However, they can only be rerandomised by their tiles. |
Industry tiles can rerandomise both their own random bits as well as the random bits of the industry (via type <code style="color:darkgreen">PARENT</code>). The triggers for rerandomisation are in both cases shared per tile (when using <code style="color:darkgreen">TRIGGER_ALL_NEEDED</code>), i.e. the triggers are in all cases independent for different tiles. Industries have random bits. However, they can only be rerandomised by their tiles. |
||
+ | |||
+ | == independent and dependent == |
||
<code style="color:darkgreen"><independent>: <other_random>;</code> makes sure that this random_switch block and <code style="color:darkgreen"><other_random></code> use different (non-intersecting) random data. This allows making multiple randomized decisions that are independent of each other. |
<code style="color:darkgreen"><independent>: <other_random>;</code> makes sure that this random_switch block and <code style="color:darkgreen"><other_random></code> use different (non-intersecting) random data. This allows making multiple randomized decisions that are independent of each other. |
||
Line 221: | Line 245: | ||
Both of these options require enough random data to be available. Also, the combination must make sense. For example, if A is dependent on B and B is dependent on C, then A cannot be independent of C. |
Both of these options require enough random data to be available. Also, the combination must make sense. For example, if A is dependent on B and B is dependent on C, then A cannot be independent of C. |
||
+ | |||
+ | == Choices == |
||
Following this, there is a list of options, one of which will be chosen randomly. The syntax is <code style="color:darkgreen"><probability>: <return_value>;</code>. The relative probability that this option will be chosen is given by <code style="color:darkgreen"><probability></code>. The chance is equal to the probability divided by the sum of all probabilities. If this sum is not equal to a power of two (2, 4, 8, 16, ...), then rounding is done and the probabilities may be inexact. For information about <code style="color:darkgreen"><return_value></code>, see the [[NML:Switch|switch-block]]. Note that accessed variables in the return value are always in the scope of the item itself (i.e. <code style="color:darkgreen">SELF</code>) |
Following this, there is a list of options, one of which will be chosen randomly. The syntax is <code style="color:darkgreen"><probability>: <return_value>;</code>. The relative probability that this option will be chosen is given by <code style="color:darkgreen"><probability></code>. The chance is equal to the probability divided by the sum of all probabilities. If this sum is not equal to a power of two (2, 4, 8, 16, ...), then rounding is done and the probabilities may be inexact. For information about <code style="color:darkgreen"><return_value></code>, see the [[NML:Switch|switch-block]]. Note that accessed variables in the return value are always in the scope of the item itself (i.e. <code style="color:darkgreen">SELF</code>) |
||
+ | |||
+ | == Usage in graphics and callbacks == |
||
Note that re-randomizing is done only during a special callback, <code style="color:darkgreen">random_trigger</code>. This callback is called whenever a trigger event occurs. As a consequence, it's ''absolutely necessary'' for the random_switch block to be executed during this callback, or trigger-based re-randomizing won't take place. Also, the callback may not fail (end with CB_FAILED), so return an arbitrary value or even a sprite set instead. This return value is not used anywhere. |
Note that re-randomizing is done only during a special callback, <code style="color:darkgreen">random_trigger</code>. This callback is called whenever a trigger event occurs. As a consequence, it's ''absolutely necessary'' for the random_switch block to be executed during this callback, or trigger-based re-randomizing won't take place. Also, the callback may not fail (end with CB_FAILED), so return an arbitrary value or even a sprite set instead. This return value is not used anywhere. |
||
+ | |||
+ | == Example == |
||
Let's conclude with an example: |
Let's conclude with an example: |
Latest revision as of 07:30, 10 September 2023
Vehicles, Stations, Canals, Bridges, Towns, Houses, Industries (Tiles), Cargos, Airports+Tiles, Objects, Railtypes, Roadtypes, Tramtypes, Terrain
Syntax
While a switch-block allows making a predictable decision, a random_switch allows a randomised choice between several options.
random_switch (<feature>, <type>, <ID>[, <triggers>]) { (independent: <other_random>;)* (dependent: <other_random>;)* (<probability>: <return_value>;)+ }
Feature and Type
The first parameter <feature>
specifies the feature to use. <type>
, the second parameter, is used to define what random data is used. The supported combinations are listed in the following table. The amount of random data is given in the third column. The maximum number of possible combinations is equal to 2^x, with x being the number of random bits. Not all combinations support re-randomizing via triggers, this is indicated in the fourth column. The last column specifies the object of which the random data is used.
Feature | Type | # of random bits | Triggers possible? | Random data used |
---|---|---|---|---|
Vehicles | SELF | 8 14.0 16 | Yes | Vehicle itself |
Vehicles | PARENT | 8 14.0 16 | No | Leading engine |
Vehicles | BACKWARD_SELF(x) | 8 14.0 16 | No | Count x vehicles backward (away from the engine), starting at the vehicle itself [1] |
Vehicles | FORWARD_SELF(x) | 8 14.0 16 | No | Count x vehicles forward (towards the engine), starting at the vehicle itself [1] |
Vehicles | BACKWARD_ENGINE(x) | 8 14.0 16 | No | Count x vehicles backward, starting at the leading engine [1] |
Vehicles | BACKWARD_SAMEID(x) | 8 14.0 16 | No | Count x vehicles backward, starting at the first vehicle in the chain with the same ID [1] |
Stations / airport tiles | SELF | 16 | Stations only | Station |
Stations / airport tiles | TILE | 4 | Stations only | Specific station tile |
Canals | SELF | 8 | No | Canal tile |
Houses | SELF | 8 | Yes | House tile [2] |
Industry tiles | SELF | 8 | Yes | Industry tile |
Industry tiles | PARENT | 16 | Yes | Industry as a whole |
Industries | SELF | 16 | No | Industry (same as above) |
Objects | SELF | 8 | No | Object tile (different per tile) |
Railtypes | SELF | 2 | No | Rail tile (pseudo-random, based on location) |
Roadtypes | SELF | 2 | No | Road tile (pseudo-random, based on location) |
Tramtypes | SELF | 2 | No | Road tile (pseudo-random, based on location) |
ID
The third parameter <ID>
can be used to refer to this block from other (random-)switch-blocks.
Triggers
The last parameter <triggers>
is optional and allows re-randomizing when certain conditions occur. The events and accompanying trigger names are given in the following tables. To re-randomize graphics when any of a set of events occurs, use bitmask(TRIGGER_A, TRIGGER_B, .. , TRIGGER_Z)
To re-randomize only when all of the events have occured, add TRIGGER_ALL_NEEDED
to the list of used triggers, e.g. use bitmask(TRIGGER_ALL_NEEDED, TRIGGER_A, ...)
Vehicles
Trigger | Event |
---|---|
TRIGGER_VEHICLE_NEW_LOAD | Vehicle gets new load of cargo (only after it was empty) |
TRIGGER_VEHICLE_SERVICE | Vehicle enters a depot and is serviced |
TRIGGER_VEHICLE_UNLOAD_ALL | The consist has unloaded all cargo (use with type 'SELF') |
TRIGGER_VEHICLE_ANY_LOAD | Any vehicle of the consist receives cargo (use with type 'SELF') |
TRIGGER_VEHICLE_32_CALLBACK | 32-day callback returned 1 |
To re-randomize when the consist has been emptied and then receives new cargo, use bitmask(TRIGGER_VEHICLE_UNLOAD_ALL, TRIGGER_VEHICLE_ANY_LOAD, TRIGGER_ALL_NEEDED)
Stations
Trigger | Event | Triggered on |
---|---|---|
TRIGGER_STATION_NEW_CARGO | New cargo waiting | Entire station |
TRIGGER_STATION_NO_MORE_CARGO | No more cargo waiting | Entire station |
TRIGGER_STATION_TRAIN_ARRIVES | Train arrives (starts loading/unloading) | Platform the train is on |
TRIGGER_STATION_TRAIN_LEAVES | Train leaves (done loading/unloading) | Platform the train is on |
TRIGGER_STATION_TRAIN_LOADS_UNLOADS | Train loads/unloads cargo | Platform the train is on |
TRIGGER_STATION_TRAIN_RESERVES | Train reserves platform using PBS | Platform the train is on |
All triggering events involve a cargo-type (which arrives, is loaded, or unloaded). The triggers only apply to a station section, if the cargo-type is listed in the property cargo_random_triggers
.
The last four triggers in the table only trigger on the platform on which they occur.
Note that triggers are only saved per-station, not per-tile, so using TRIGGER_ALL_NEEDED
doesn't make a lot of sense for per-platform triggers; or in general, if a station is composed of sections from different NewGRF.
Houses
Trigger | Event |
---|---|
TRIGGER_HOUSE_TILELOOP | The house tile is processed in the periodic tile-processing loop |
TRIGGER_HOUSE_TOP_TILELOOP | The top tile of the house is processed in the periodic tile-processing loop |
Using TRIGGER_HOUSE_TOP_TILELOOP
, it is possible to re-randomize the whole building as one unit. All tiles of a multi-tile house will get the same new random data.
Industry tiles
Trigger | Event |
---|---|
TRIGGER_INDUSTRYTILE_TILELOOP | The industry tile is processed in the periodic tile-processing loop |
TRIGGER_INDUSTRYTILE_256_TICKS | Triggers simultaneously for all tiles of the industry every 256 ticks. If the industry is a primary one, output cargo is generated at the same time. |
TRIGGER_INDUSTRYTILE_CARGO_DELIVERY | Cargo is delivered to the industry. If the industry is a processing one, output cargo is generated at the same time. |
Industry tiles can rerandomise both their own random bits as well as the random bits of the industry (via type PARENT
). The triggers for rerandomisation are in both cases shared per tile (when using TRIGGER_ALL_NEEDED
), i.e. the triggers are in all cases independent for different tiles. Industries have random bits. However, they can only be rerandomised by their tiles.
independent and dependent
<independent>: <other_random>;
makes sure that this random_switch block and <other_random>
use different (non-intersecting) random data. This allows making multiple randomized decisions that are independent of each other.
<dependent>: <other_random>;
, on the other hand, lets this random_switch block and <other_random>
use the same random data. To make this possible, it should not require more random data (i.e. have a higher sum of probabilities) than the block it is dependent on.
Both of these options require enough random data to be available. Also, the combination must make sense. For example, if A is dependent on B and B is dependent on C, then A cannot be independent of C.
Choices
Following this, there is a list of options, one of which will be chosen randomly. The syntax is <probability>: <return_value>;
. The relative probability that this option will be chosen is given by <probability>
. The chance is equal to the probability divided by the sum of all probabilities. If this sum is not equal to a power of two (2, 4, 8, 16, ...), then rounding is done and the probabilities may be inexact. For information about <return_value>
, see the switch-block. Note that accessed variables in the return value are always in the scope of the item itself (i.e. SELF
)
Usage in graphics and callbacks
Note that re-randomizing is done only during a special callback, random_trigger
. This callback is called whenever a trigger event occurs. As a consequence, it's absolutely necessary for the random_switch block to be executed during this callback, or trigger-based re-randomizing won't take place. Also, the callback may not fail (end with CB_FAILED), so return an arbitrary value or even a sprite set instead. This return value is not used anywhere.
Example
Let's conclude with an example:
random_switch (FEAT_TRAINS, SELF, random_42, bitmask(TRIGGER_VEHICLE_UNLOAD_ALL, TRIGGER_VEHICLE_ANY_LOAD, TRIGGER_ALL_NEEDED)) { /* re-randomize when vehicle has been emptied and then received new cargo */ independent: random_43; // decision should be independent from random_43, which is defined elsewhere 6: group_open; // 6/11 chance to display open wagon 3: group_closed; // 3/11 chance to display closed wagon (with cover) 2: group_halfopen; // 2/11 chance to display a half-covered wagon }