Implementing if/else-if logic in NFO with Action7

Discussions about the technical aspects of graphics development, including NewGRF tools and utilities.

Moderator: Graphics Moderators

Post Reply
User avatar
CMircea
Chairman
Chairman
Posts: 887
Joined: 29 Dec 2006 14:05

Implementing if/else-if logic in NFO with Action7

Post by CMircea »

Hello! I'm struggling to figure out how to use Action7 to implement if then else-if logic. I want to set a tracktype for a train, if that is not available use another, if that isn't available either, use a fallback.

Currently the train has tracktype set to 3RDC, but if that is not available, ELRL is set:

Code: Select all

Pseudocode:
-----------
set track type to 3RDC

if rail type 3RDC is not available
    set track type to ELRL

NML equivalent:
---------------
if (railtype_available("3RDC")) {
    track_type: "3RDC"
} else {
    track_type: SAAZ
}

Actual NFO:
----------
<num> * 7    00 // Action0
             00 // Feature: trains
             01 // Number of props to change
             01 // Number of vehicles to change
             <id> // Vehicle ID
             05 // Property: track type
             03 // Index in rail type table: 3RDC
             
<num> * 9    07 // Action7
             00 // Variable: ignored for this condition
             04 // Var size in bytes
             0E // Condition: rail type is defined
             "3RDC" // Value: rail type label
             01 // Number of sprites to skip

<num> * 7    00 // Action0
             00 // Feature: trains
             01 // Number of props to change
             01 // Number of vehicles to change
             <id> // Vehicle ID
             05 // Property: track type
             01 // Index in rail type table: ELRL
However, I also need to check if SAAZ is available, to use that if 3RDC is not, but keep the ELRL fallback if neither are available. Like this:

Code: Select all

Pseudocode:
-----------
set track type to 3RDC

if rail type 3RDC is not available
    if rail type SAAZ is not available
        set track type to ELRL
    else
        set track type  to SAAZ

NML equivalent:
---------------
if (railtype_available("3RDC")) {
    track_type: "3RDC"
} else {
    if (railtype_available(SAAZ)) {
        track_type: SAAZ
    } else {
        track_type: ELRL
    }
}
Action7 can be used to jump a fixed number of sprites (or to a label) based on the "is railtype defined" or "is railtype not defined" conditions. I came up with this:

Code: Select all

<num> * 7    00 // Action0
             00 // Feature: trains
             01 // Number of props to change
             01 // Number of vehicles to change
             <id> // Vehicle ID
             05 // Property: track type
             03 // Index in rail type table: 3RDC

// If rail type 3RDC is defined skip next 3 sprites
<num> * 9    07 // Action7
             00 // Variable; ignored for this condition
             04 // 4 bytes
             0E // Condition: Rail type label is defined
             "3RDC" // Value: rail type
             03 // Number of sprites to skip

// If rail type SAAZ is defined skip next sprite
<num> * 9    07 // Action7
             00 // Variable; ignored for this condition
             04 // 4 bytes
             0E // Condition: Rail type label is defined
             "SAAZ" // Value: rail type
             01 // Number of sprites to skip

// Set train track type to ELRL
<num> * 7    00 // Action0
             00 // Feature: trains
             01 // Number of props to change
             01 // Number of vehicles to change
             <id> // Vehicle ID
             05 // Property: track types
             01 // Index in rail type table: ELRL

// Set train railtype to SAAZ
<num> * 7    00 // Action0
             00 // Feature: trains
             01 // Number of props to change
             01 // Number of vehicles to change
             <id> // Vehicle ID
             05 // Property: track types
             17 // Index in rail type table: SAAZ
But now the vehicle doesn't start on ELRL/SAAN with a "not powered" error. I'm not sure if it's an issue in the track set or not - I have no idea what the powered & compatible rail types are; the NewGRF debug tool for inspect doesn't show that info for a track tile :(
User avatar
OzTrans
Tycoon
Tycoon
Posts: 1674
Joined: 04 Mar 2005 01:07

Re: Implementing if/else-if logic in NFO with Action7

Post by OzTrans »

CMircea wrote: 08 May 2021 20:36 Hello! I'm struggling to figure out how to use Action7 to implement if then else-if logic. ...
To implement 'if then else-if' logic use variable 0x9A to make unconditional jumps over not to be tested Action-7s once an 'If' has been satisfied.

If Action-7 Test is false jump to next Action-7; if true do what ever needs to be done, then jump unconditionally over the remaining Action-7s that need no longer be tested.

Sample :

Code: Select all

   1 * 6        07 83 01 03 00 02    // Test climate, jump to 4 if true (not temperate)
   2 * nn                            // Do what needs to be set, if climate is temperate
   3 * 6        07 9A 01 02 FF 04    // Unconditional Jump, over remaining IFs and Fallback
   4 * 6        07 83 01 03 01 02    // Test climate, jump to 7 if true (not arctic)
   5 * nn                            // Do what needs to be set, if climate is arctic
   6 * 6        07 9A 01 02 FF 01    // Unconditional Jump, over Fallback
   7 * nn                            // Do what needs to be set, Fallback for tropical
Eddi
Tycoon
Tycoon
Posts: 8254
Joined: 17 Jan 2007 00:14

Re: Implementing if/else-if logic in NFO with Action7

Post by Eddi »

in general, there are two different approaches to if-blocks:
"negative logic" like shown in the post above, the general structure is like this:

Code: Select all

label A: check condition NOT a, jump to label B
<block A>
jump to label END
label B: check condition NOT b, jump to label C
<block B>
jump to label END
label C: ...
label END:
and the other strategy is "positive logic":

Code: Select all

check condition a, jump to label A
check condition b, jump to label B
...
jump to label END
label A: <block A>
jump to label END
label B: <block B>
jump to label END
...
label END:
michael blunck
Tycoon
Tycoon
Posts: 5948
Joined: 27 Apr 2005 07:09
Contact:

Re: Implementing if/else-if logic in NFO with Action7

Post by michael blunck »

And what would be the better strategy? 8)

scnr
Michael
Image
User avatar
CMircea
Chairman
Chairman
Posts: 887
Joined: 29 Dec 2006 14:05

Re: Implementing if/else-if logic in NFO with Action7

Post by CMircea »

Thanks guys, I didn't know about the unconditional jump, that's a neat trick with var 9A :)
michael blunck
Tycoon
Tycoon
Posts: 5948
Joined: 27 Apr 2005 07:09
Contact:

Re: Implementing if/else-if logic in NFO with Action7

Post by michael blunck »

In m4nfo this is handled by functions skipif() and skip():
http://www.ttdpatch.de/grfspecs/m4nfoMa ... l#examples

regards
Michael
Image
Post Reply

Return to “NewGRF Technical Discussions”

Who is online

Users browsing this forum: No registered users and 6 guests