Problems with varies if statements after upgrading an AGS 2.72 game to AGS 3.6.0

Started by Gal Shemesh, Sat 19/08/2023 13:35:25

Previous topic - Next topic

Gal Shemesh

Hi everyone,

During my current project upgrading a friend's game from AGS 2.72 to AGS 3.6.0, I've noticed that some functions doesn't work. Digging in the code I've noticed that is seems like back in AGS 2.72 there was no need for 'else if' statements, and that you could just write your bare 'if' statements one after the other, and the engine checked them from top to bottom, skipping what's 'False' and continuing to the next check.

That behavior is not working in AGS 3.6.0, and if you have more than 1 'if' statement in a given function, only the first one is checked while the second one and beyond below it is ignored, as it should be 'else if' and not just 'if'. Problem is, during the migration process the scripts didn't update all the 'if' statements that should be 'else if'...

Should it had? Or that we need to manually set every 'if' statement that comes after the first one in a given function 'else if' in all of the functions?

Thanks
Gal Shemesh,
goldeng

Crimson Wizard

There seem to be some kind of misunderstanding here, so I must clarify something first.

There's a big difference between a sequence of bare "ifs" and "else ifs". These are logically different, and of course must not be substituted during the migration process.

1. Sequence of ifs:
Code: ags
    int a = 10;
    int b = 20;
    int c = 30;
    
    if (a == 10)
    {
        Display("Checked first");
    }
    if (b == 20)
    {
        Display("Checked second");
    }
    if (c == 30)
    {
        Display("Checked third");
    }

Here every "if" is a separate check, not depending on the previous ones, and therefore will be checked one by one regardless of the previous check's result. In the above example the engine will display all 3 lines.


2. Sequence with else ifs:
Code: ags
    int a = 10;
    int b = 20;
    int c = 30;
    
    if (a == 10)
    {
        Display("Checked first");
    }
    else if (b == 20)
    {
        Display("Checked second");
    }
    else if (c == 30)
    {
        Display("Checked third");
    }

Here the if/else ifs form a single chain of checks, and the following "else ifs" will only be checked if the previous failed. As soon as one of the checks succeeded, the rest of the sequence is skipped. In the above example engine will display only the first line.

These are the syntax rules, common to any program language using these constructs. If the engine's behavior does not match this, this would mean there's a error either in script compiler or in the engine.

I tested this in 3.6.0 just in case, and both cases work as expected there. (But I suppose if they did not, users would notice this long time ago.)

If some script does not work as expected in your game, then please post the actual script example, as there may be other reasons for it to not work.

Gal Shemesh

Much appreciated @Crimson Wizard. Thanks for the clear explanation! After posting I actually encountered both scenarios as you mentioned and it took me a while to realized the difference between the two - but nevertheless, your explanation is much more simpler and clearer to understand. So thanks! :)

I cleaned the code from too many actions to make it simpler to post here. It's a room script:
Code: ags
int AirConditionerFix; // for checking if AirConditioner is fixed

function room_FirstLoad()
{
  AirConditionerFix=0;
}

function hAirConditioner() // interact with the air conditioner hotspot
{
  if (AirConditionerFix==1)
  {
    Display("Scenario 1"); // <-- note that there's no closing curly bracket here.
  if (AirConditionerFix==0)
  {
    Display("Scenario 2");
  }
}

What happens is, in AGS 2.72 you can click on the air conditioner hotspot where the AirConditionerFix variable equals 0, and scenario 2 runs without any problem, even though it sits within the first 'if' statement.

However, in AGS 3.6.0, the code doesn't work at all - which makes sense as the AirConditionerFix variable equals to 0 when you first enter the room, and this second 'if' statement condition that checks for it will never run in the above code, as the first 'if' statement will be true only if the AirConditionerFix variable is equal to 1.

Only after putting a closing curly bracket at the end of the first 'if' statement and removing one from the end of the hAirConditioner function that it works in AGS 3.6.0.

So that what I'm trying to understand for over a day now. At this point I can only assume that the old engine version scripts were more forgiving.
Gal Shemesh,
goldeng

Crimson Wizard

Quote from: Gal Shemesh on Sat 19/08/2023 17:26:51At this point I can only assume that the old engine version scripts were more forgiving.

I suppose that this is the only option here, as the above code normally should not even compile, not finding a bracket match.

By the way, I recommend to put checks in order by default, making the game progression easier to understand: test variable case 0 first, then case 1, and so forth.

morganw

Quote from: Gal Shemesh on Sat 19/08/2023 17:26:51Only after putting a closing curly bracket at the end of the first 'if' statement and removing one from the end of the hAirConditioner function that it works in AGS 3.6.0.

The position where you are implying the opening curly bracket is optional can never be optional,  withouth it the logic of the function is changed to only check if the value is 0 if value was 1. Even if the previous scripting behaviour was to automatically close open blocks at the end of the file (adding missing closing brackets), it does not make sense for the example.

If you indent the code relative to the opening and closing of blocks then it will help to show that "Scenario 2" can only occur within "Scenario 1".

Code: ags
function hAirConditioner()
{
  if (AirConditionerFix==1)
  {
    Display("Scenario 1");
    if (AirConditionerFix==0) // <-- This is valid but probably does not make logical sense.
    {
      Display("Scenario 2");
    }
  // <-- The missing curly bracket to prevent an error goes here.
}

What you are describing as a fix (adding and removing a bracket) is rebalancing the brackets, whereas the example you've given is missing a bracket, so I'm not sure your example is real. The code you have shown will never compile regardless of what you do with brackets because the string quotes are never closed (I've fixed it in the example posted above).

Gal Shemesh

Hi @morganw. Appreciate your reply. Thanks for the heads up regarding the closing double-quotes - I probably removed them by mistake while editing the example. I just fixed it above. :)

I'm quite embarrased and must confess here:
This thing had 'drove me mad' of why it worked in AGS 2.72 and why it doesn't after the migration to the recent release, that I just had to went through the entire thing bit-by-bit in both editor versions, side by side. Finally, I saw the embarrased mistake of mine, and I wish to mention it here so if anyone else encounters something similar during a migration / translation process, they can learn from my mistake:

The old code actually HAS(!) a closing curly braket, but it was at the END of a line of the latest action that executes in scenario 1.
I did not play the entire game after the migration to check that each and every function in the game works, and directly went to replacing the string lines with the translation text - that must be where the closing curly bracket was deleted unintentionally. But it did not make any error when compiling as the engine then saw this interaction function as an 'if within an if' logic.

This thread wasn't for vain after all, as it what brought me to dig much deeper into this to understand where I was wrong. Hope it will also help other translators when changing lines in codes. Thanks everyone!!
Gal Shemesh,
goldeng

morganw

Quote from: Gal Shemesh on Sun 20/08/2023 12:27:13I also just checked the code I posted here again and you're right, I forgot to add closing 'double-quotes' in the 'Display' function strings when writing this example, but that's all. I just fixed it above as well. But apart from that, the code logic is real - taken directly from a working game in AGS 2.72.

I'm not saying it would not originally compile, but you can see from your GIF that the check for AirConditionerFix==0 will only run if AirConditionerFix has a value of 1.  The edit you are making is changing what the original code does, to always check for AirConditionerFix==0.

Gal Shemesh

Thanks @morganw. I've just finished editing my latest reply and you were ahead of me replying to its previous version with the GIF animation which I removed - I've confessed above with my embarrased mistake. :)
Gal Shemesh,
goldeng

SMF spam blocked by CleanTalk