GMS 2 Nested if statements

Sorry, this a bit of a newbie question but I'm cleaning, house as much as possible. Hence several posts over that past few days.

What is the best way to deal with nested if statements?

Code:
if the weather is dry
{
    if im at home
    {
        if im not tired
        {
            if i have no work that day
            {
                if today is not sunday
                {
                    if i'm not dead
                    {
                        go to the park
                    }
                }
            }
        }
    }
How can I make these less ugly?

Thanks
 

FrostyCat

Member
You should have been taught long ago to use && for this kind of setup.
GML:
if (condition1 && condition2 && condition3 && condition4) {
    ...
}
 

ophelius

Member
Code:
if(weather == dry && at_home && !tired && work == 0 && day != Sunday && !dead)
   destination = park;
 

zendraw

Member
You should have been taught long ago to use && for this kind of setup.
GML:
if (condition1 && condition2 && condition3 && condition4) {
    ...
}
this is not aways the case, meny times you will nest ifs becouse you need to calculate stuff in the middle. espetially for games its better to nest then to stack. you cant expand with if (&&&&&&&&), the resault will be one, and in the other case the resault will vary.
 

ophelius

Member
this is not aways the case, meny times you will nest ifs becouse you need to calculate stuff in the middle. espetially for games its better to nest then to stack. you cant expand with if (&&&&&&&&), the resault will be one, and in the other case the resault will vary.
I agree, sometimes you have conditions that shouldn't be checked unless some other condition is true:

Code:
if(condition1){

    if(condition2 & condition3){


   }

}
 
I don't believe I should have been taught this at all. That's just as ugly. It's just one really big line and yes I know how to use and 'and' &&. You can multi-line it yes but it's the same logical statement.

Zendraw. This was just an example I regret using this example now because it made it sound as though I were reading a textbook for the first time. What I mean is if I had100 conditions. This is an exaggeration but lets say you genuinely needed to check lots of items would you do if this == that && this && that && this && that && this && that && this && that && this && that && this && that && this && that && this && that && this && that && this && that && this && that && this&& that.

I don't mean I could use a case statement. Which I'm sure is coming. If this is that but not that but is this unless that is not this and so on.

I don't think I'm making myself clear. I think this is my biggest problem when asking questions. I'll have to re-think how I'm going to ask this. It makes me sound like a total newb. It's frustrating as hell.

Are you saying if you had 100 conditions even ones with other logical operators we might have not just && but || and ! and ^^. How do we make this readable?
Code:
if (condition1 &&
condition2 &&
condition3 &&
condition4 &&
condition5 &&
condition6 &&
condition7 &&
condition8 &&
condition9 &&
condition10 &&
condition11 &&
condition12 &&
condition13) {
    ...
}

This is good is it. Maybe I don't know it dosen't feel right.
 
Last edited:

chamaeleon

Member
And at a certain point one will ponder whether to implement a more dynamic schema that uses collections of "must-have" state attributes and "must-not-have" state attributes, and a comparison function with the current state attributes and some given pair of must-have and must-not-have attributes. Perhaps implemented using bits as flags, perhaps as arrays or ds_lists, or something completely different.
GML:
var must_have_attrs = scr_make_mask(Cond.dry, Cond.home);
var must_not_have_attrs = scr_make_mask(Cond.tired, Cond.work, Cond.sunday, Cond.dead);
if (scr_check_state(current_state, must_have_attrs, must_not_have_attrs)) {
    // go to the park
}
 

BB Scary

Member
and what about this funny solution?

GML:
//create event

the_weather_is_dry = 1;
im_at_home = 1;
im_not_tired = 1;
i_have_no_work_that_day = 1;
today_is_not_sunday = 1;
i'm_not_dead = 1;

//step event
all_right = (the weather_is_dry + im_not_tired + im_not_tired + i_have_no_work_that_day + today_is_not_sunday + i'm_not_dead);
if all_right == 6 {
    go_to_the_park;
    }
if you meet all the conditions, you can go out :D
 

zendraw

Member
i think you think more then do, for 7 years im yet to get to a need to write more then a bunch of ifs. the tons of other calculations if done right wuldnt make you to nest a ton of if`s. its just when you make mechanics and stuffs in a game it never gets to that point to make so menyh ifs unless you have some bad practices.

what you are after in the end is a resault that you can manipulate to get another resault and so on, now your character hangs on a ledge. you want to get that resault in a smart way. thats why you write facing=floor((dir+22.5)/45); and not if dir<45 or dir>315 facing=0 for all the situations.
 
'I think you think more than you do'. A very true statement is exactly what's happening to me.

I don't, in reality, have more than about four nests at any point. So I haven't hit that wall. But what if I did. I'm thinking that the maximum number of nested if's should be 3. If it's more than that it needs to be rethought.

The reason I do the things the way I do is that the larger the project the more magnified smaller problems become. I comment and consider every line of code. To the point, I spend days coming up with systems to ensure that even my comments are consistent. If I declare a variable I say // Set. If I do a loop the comment always starts with // loop through if I use and if the state the comments will be // Determine if...

I'm a bugger for perfection and it kills me.

You're probably right I think too hard. And do too little. I think this is because I have been stung before.

You will see my other questions relating to things like data types. It upsets me when things are not perfect. Because it can cause problems and I lose sleep over it.

I think I need to chill out a bit more about these things.

Thank you.
 
Last edited:
As Shakespeare said: “Striving to better, oft we mar what’s well.”

Perfection within code is a mirage. You will always get better than you currently are and your previous code will seem rife with stupidity. Spending time thinking about bettering your practices is not a bad thing, but it comes with it's own associated cost; that of progress paralysis. Always remember that by completing a game, not matter how badly coded it is, you have achieved more than 90% of people who want to make a game.

So you have two paths, spend the rest of your life philosophically considering how to craft perfect code or spend your current moments actually making something. Neither is inherently wrong, but they definitely have different results.
 
I want good results. :)

I appreciate that. I fell slightly better now.

I just feel like it's building a house on sand. yes, you can build a house, but what if you want an extension at a later point and don't want to knock your 'perfectly' good house down because it's on the edge of a cliff and you don't have room to build the extension.
 
Last edited:

EvanSki

King of Raccoons
you could use a switch statement

GML:
switch(mood)
{
    case happy: //because theres no break here it will do case sad's code
    case sad:
    {
        state.mood_action = cry;
    }
    break;
    
    case tired: state.mood_action = sleep; break;

    default: state.mood_action = eat_some_bees; break;
}
 
Sorry dude you may have miss understood.

I stated before...

'I don't mean I could use a case statement. Which I'm sure is coming. If this is that but not that but is this unless that is not this and so on.'
 

Yal

🐧 *penguin noises*
GMC Elder
So you have two paths, spend the rest of your life philosophically considering how to craft perfect code or spend your current moments actually making something. Neither is inherently wrong, but they definitely have different results.
This, so much this.

Also, players don't care about how well a game is coded, as long as it's not Beteshda levels of buggy. If you ever consider a refactor, do it because the bad coding style currently is getting in your way, not because you think you need better karma.


Separated nested if statements are easier to add elses to, which can be useful in a lot of cases (debug messages where you're wondering WHICH statement fails, for instance) so I generally use them instead of &&/||s unless I know for certain that some conditions are inseparably linked together (for instance, the different coordinate checks in a collision check don't make sense on their own).
 

Niels

Member
I used to like the {} of coding, but now I'm more experienced in python I actually prefer the : and tabbed system
 

MishMash

Member
It really depends on the exact problem you are trying to solve, if all of the conditions are valid and independent, then that is exactly what if statements are for.
However, it is often the case that there are far more practical ways of dealing with multiple conditions, depending on the type of code. In some cases, state encapsulation or caching is more valid, sometimes, you can defer use of a condition to actually being integrated in the logic.

A Few Examples
  • For situations where only a number of states can be true simultaneously, you can use a state machine instead (store state in a variable, using enums and then switch on it for logic).
  • If you have a variety of independent systems which can all influence the output indirectly, I tend to prefer organising my code to avoid nesting, and tracking some validity:

    GML:
    var canDoSomething = true;
    if(isDead){
    canDoSomething = false;
    }
    
    if(isSunday){
    canDoSomething = false;
    }
    
    if(specialOverridingPowerupMechanicThatAllowsMeToAvoidDeathTemporarily){
    canDoSomething = true;
    }
    
    if(canDoSomething) {
    justDoIt();
    }
    Vertical code can make your life easier, and also cater for greater control if you suddenly decide that you want one special condition that overrides the previous condition. The problem with nesting in this case is you would then need to add an OR condition to all of your otherwise valid statements.

  • Similarly, as others have suggested, it can sometimes be preferable to store a bunch of these conditions in a variable, then just check the condition when other state updates:

    Code:
    var canDoSomething = (!isDead && !isSunday);
    if(canDoSomething){
    justDoIt();
    }
  • For situations where the logic is overly complex, you can also move the check into a different script, there's nothing inherently wrong with doing so in order to make your code neater. Combining the ideas of this, it can also be quite prudent to combine ideas, for example the ide of a state machine above, you can condense ideas down:

  • Code:
    // function getState()enum MyStates { STATE_A, STATE_B, STATE_C};
    
    if(!isDead && !isSunday){
    if(someConditon){
    return STATE_A;
    } else {
    return STATE_B;
    }
    } else {
    return STATE_C;
    }
    
    // Use
    var myState = getState();
    switch(myState){
    case STATE_A:
    ...
    break;
    case STATE_B:
    ...
    break;
    case STATE_C:
    ...
    break;
    }
  • Finally, if you are using if statements to switch on item types for example, this should be entirely avoided if possible.
    This is a picture from an open source game I once saw with their item switch implemented as a massive, horrendous, if-else chain:


    In this instance, this is a perfect example of when NOT to use if statements.
    For something like this, the logic for each individual item should be encapsulated in a separate script, and the script run.

    Note that the reason if statements are used here, rather than a switch is that multiple items can be equipped at once, this chain captures all items. In reality, you could do this one after the other, but that would still incur a lot of waste as you are checking items that may not necessarily be equipped. -- I'd always suggestgiving each item its own script and allowing it to manipulate the logic.
Notes on Optimisation/Efficiency

Finally, wanted to make a comment on efficiency. Generally speaking, nested if statements will be no less efficient than separated vertical if statements. As a general rule of thumb, trust the compiler to do a better organisational job of structuring branching in your project than you do, it'll always find the best way based on the combination of logic used and whether it can collapse state. This is true for a lot of micro-optimisation.
Instead, your focus as a programming should be on two things:

- Readability and Maintainability (as we can see the code in the above statement is neither of these).
- Ensure what you are doing uses the best programming device for the task at hand, whether that be a data structure, a state machine, separate scripts, or nested if statements.
 
Firstly the Monty python clip was brilliant I needed that.

Mishmash: I may come back again like columbo but that pretty much makes me happy. It is a horse for courses situation if I have understood you correctly. I just get hung up on these things sometimes because I believe that there is something that someone else knows that I don't which is very likely.

I don't want to finish a game, be incredibly proud because it works, it looks great etc then have someone come along and say I wouldn't have done it like that, or did you not know you could do it like this. I would feel like I had to re-write the whole thing. Especialy if they had a good solid point.
 
I don't want to finish a game, be incredibly proud because it works, it looks great etc then have someone come along and say I wouldn't have done it like that, or did you not know you could do it like this. I would feel like I had to re-write the whole thing. Especialy if they had a good solid point.
Everyone who has ever made a game has made compromises and mistakes, literally everyone. No-one has ever made a game that has perfect code with every nook and cranny functioning in the best possible way and absolutely no way to improve on the codebase. That's the exact difference between waxing philosophical and getting your hands dirty. You can imagine that it's possible, the same way that I can imagine flying to another galaxy is possible, but it simply will not happen in RL.
 
Agreed. I don't actually do things like this of course. Never have I encountered that many stairs in reality. I just hope I never do and want to avoid them. I'm a paranoid programmer for sure. I have mentioned style cop a couple of times previously. I.E is there anything like it for GM but this seems to be one of the things noone wants to talk about. I hope it's not like Beetlejuice and I get kicked off the forum.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
I would just like to point out that sometimes nested ifs are better, especially when using expensive functions, and also keep in mind that GMS2 has an "early out" system, so if an if has multiple statements and the first evaluates to false, then the others won't run (when using &&...). For example:
GML:
// Good
if (mouse_check_button(mb_left)) // Cheap function
{
if (point_distance(mouse_x, mouse_y x, y) > 100) // Expensive function
    {
    // do something
    }
}

// Bad
if (point_distance(mouse_x, mouse_y x, y) > 100) // Expensive function
{
if (mouse_check_button(mb_left)) // Cheap function
    {
    // do something
    }
}

// Good
if (mouse_check_button(mb_left)) && (point_distance(mouse_x, mouse_y x, y) > 100)
{
// do something
}

// Bad
if (point_distance(mouse_x, mouse_y x, y) > 100) && (mouse_check_button(mb_left))
{
// do something
}
This is one of those "micro" optimisations that is actually really easy to impliment and will add up over time. :)
 
That's all good to know. I'm hearing a lot of positive affirmations about what I have already been doing. I just get paranoid sometimes. Some great advice on this thread. thank you all. or yall.
 

Yal

🐧 *penguin noises*
GMC Elder
also keep in mind that GMS2 has an "early out" system, so if an if has multiple statements and the first evaluates to false, then the others won't run
Just to add to this: keep it in mind both ways, since functions with side effects you might want to happen might not always run if they're later in an && chain and this can result in fun quirky bugs.
 
Top