Ren'Py How to get multiple conditionals to work?

Unknown72

Member
Jan 3, 2021
217
287
Currently mainly just testing this as I've never done Renpy and I mostly understand things. However I've run into a snag with a current test. I basically have a working Day and Time system going, and I've successfully had it check for both when decide on where to jump, but as soon as I add the third variable it just ignores that one entirely even when that third variables conditions are met and instead just does the normal code without that variable.

This is what it looks like, everything is defined properly (as a result of prior testing), it's just for some reason not working right.

Code:
  menu:
        "Room 1":
            if clock.weekday == "Monday" and clock.time == "Morning":
                jump Room1_Monday_Morning
            if clock.weekday == "Monday" and clock.time == "Morning" and RubyI >= 1:
                jump Room1_Monday_Morning_Influence
            if clock.weekday == "Monday" and clock.time == "Noon":
                jump Room1_Monday_Noon
            if clock.weekday == "Tuesday" and clock.time == "Morning":
                jump Room1_Tuesday_Morning
It'll properly do the result for the normal ones without RubyI, but even when RubyI is increased to 1 it only jumps to Room1_Monday_Morning rather then Room1_Monday_Morning_Influence. The same thing happens when I change >= to == or increase the variable higher then one.

Any help would be appreciated!
 

Unknown72

Member
Jan 3, 2021
217
287
Inadvertently might have figured it out shortly afterwards. Apparently have to the ones with more conditionals above the ones with less? Moving the line and jump with RubyI above the normal Monday Morning line made it work.

Update: So now that that works, I'm trying it with a second triple conditional and now it defaults to the first conditional with RubyI >= 1 even though it meets the requirement for the next!


Code:
 menu:
        "Room 1":
            if clock.weekday == "Monday" and clock.time == "Morning" and RubyI >= 1:
                jump Room1_Monday_Morning_Influence
            if clock.weekday == "Monday" and clock.time == "Morning" and RubyI >= 5:
                jump Room1_Monday_Morning_Five_Influence
            if clock.weekday == "Monday" and clock.time == "Morning":
                jump Room1_Monday_Morning
            if clock.weekday == "Monday" and clock.time == "Noon":
                jump Room1_Monday_Noon
            if clock.weekday == "Tuesday" and clock.time == "Morning":
                jump Room1_Tuesday_Morning
Did I mess up somewhere or am I missing something?
 
Last edited:

Winterfire

Forum Fanatic
Respected User
Game Developer
Sep 27, 2018
5,676
8,299
If True:
jump Room1_Monday_Morning


It never gets the chance to reach second line. You'll have to nest it inside the first condition, or do better coding.

So, using your bad code it'd be:

Python:
  menu:
        "Room 1":
            if clock.weekday == "Monday" and clock.time == "Morning":
                if (RubyI >= 1):
                    jump Room1_Monday_Morning_Influence
                else:
                    jump Room1_Monday_Morning
This would be nesting.
If you want to actually improve your coding and make it cleaner and easier to extend and edit in future, start learning functions.
At the very least if you want to if if if if if, make sure to learn elif as well, since all if blocks are read (not in that case since you jump out of it).
 

Unknown72

Member
Jan 3, 2021
217
287
If True:
jump Room1_Monday_Morning


It never gets the chance to reach second line. You'll have to nest it inside the first condition, or do better coding.

So, using your bad code it'd be:

Python:
  menu:
        "Room 1":
            if clock.weekday == "Monday" and clock.time == "Morning":
                if (RubyI >= 1):
                    jump Room1_Monday_Morning_Influence
                else:
                    jump Room1_Monday_Morning
This would be nesting.
If you want to actually improve your coding and make it cleaner and easier to extend and edit in future, start learning functions.
At the very least if you want to if if if if if, make sure to learn elif as well, since all if blocks are read (not in that case since you jump out of it).
oh what's interesting is that I had tried doing that previously in a different way and it didn't work, so I thought this was the way it was supposed to be done. Though tbf I could've also done that wrong as well. I've only been doing this for a few days. I appreciate the help!

Tried it out with the nesting and you saying "It never gets the chance to reach the second line" was super helpful because it made me learn that, if I'm going with these by numbers, I need to put the higher numbers first so that it switches properly to them once it's reached, otherwise it'll only run the >= 1 version every time.

Immense help for learning this as I go, thanks!
 
Last edited:

Winterfire

Forum Fanatic
Respected User
Game Developer
Sep 27, 2018
5,676
8,299
oh what's interesting is that I had tried doing that previously in a different way and it didn't work, so I thought this was the way it was supposed to be done. Though tbf I could've also done that wrong as well. I've only been doing this for a few days. I appreciate the help!

Tried it out with the nesting and you saying "It never gets the chance to reach the second line" was super helpful because it made me learn that, if I'm going with these by numbers, I need to put the higher numbers first so that it switches properly to them once it's reached, otherwise it'll only run the >= 1 version every time.

Immense help for learning this as I go, thanks!
You can limit them, such as

if variable >= 1 and variable < 5

This would limit them to 1,2,3,4

But again, it's bad practice and it'll only get more complex and hard to read and edit as you go, and it'll become prone to bugs.
If you plan to extend that any further, I'd suggest you to learn more python and make a proper system for it.
 

Unknown72

Member
Jan 3, 2021
217
287
This is pretty good info! It also occurred to me that I could potentially do a series of jumps, with each jump checking for a valid condition. Like for example the first checks Day and Time, then it jumps to one that checks for Influence, which then decides what it shows.

Messy of course, but it's a thought!
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
11,426
17,391
And the thing that no one talked about:

Even when the conditions aren't conflicting and a true condition stop the process, always remember to use a full if/elif/else structure instead of many following isolated if.
This highlight the need for an "everything else failed" option in order to not break the game.

Python:
           if clock.weekday == "Monday" and clock.time == "Morning" and RubyI >= 1:
                jump Room1_Monday_Morning_Influence
           elif clock.weekday == "Monday" and clock.time == "Morning" and RubyI >= 5:
                jump Room1_Monday_Morning_Five_Influence
           elif clock.weekday == "Monday" and clock.time == "Morning":
                jump Room1_Monday_Morning
           elif clock.weekday == "Monday" and clock.time == "Noon":
                jump Room1_Monday_Noon
           elif clock.weekday == "Tuesday" and clock.time == "Morning":
                jump Room1_Tuesday_Morning
           else:
                [...]
All this being said, it's a whole lot of if for something that can be so much simplified thanks to Ren'Py dynamism.
is among the statements that accept the expression keyword, letting you build in real time the label where the jump will lead. And it happen that in your case there's not even a need to adapt the code, everything is already perfectly matching.

So, you starts the if structure by the exceptions, here there's just on that is a set of two, and you let the rest goes with pure dynamic branching:

Python:
 menu:
        "Room 1":
           #  The only exception in the example happen on Monday morning, 
           # and will only be triggered if /RubyI/ is at least at 1
           if clock.weekday == "Monday" and clock.time == "Morning" and RubyI >= 1:
                if RubyI >= 5:
                    jump Room1_Monday_Morning_Five_Influence
                else:
                    jump Room1_Monday_Morning_Influence
                # optionally can be wrote:
                # jump expression "Room1_Monday_Morning_{}Influence".format( "Five_" if RubyI >= 5 else "" )
            #  All the other branching on the example jump to label following the same format:
            #   roomName_dayName_periodName
            #  Therefore it can be built dynamically without problems.
            else:
                    jump expression "Room1_{}_{}".format( clock.weekday, clock.time )
        "Room 2":
            [...]
 

n00bi

Active Member
Nov 24, 2022
518
606
So, you starts the if structure by the exceptions, here there's just on that is a set of two, and you let the rest goes with pure dynamic branching:
....
long if statements with a lot of and's or or's can be a bit hard to read at times.
esp with a lot of if elsif esle and worse if you have a ton of nested if's
i wish python had a switch case statement like C/C++ have, i find it so much cleaner to read :\

but you can simulate something like a switch in python tho.

Python:
def python_switch(value):
    actions = {
        1: lambda: print("Case 1"),
        2: lambda: print("Case 2"),
        3: lambda: print("Case 3")
    }
    if value in actions:
        actions[value]()
    else:
        print("No case matched")

python_switch(1)  # Output: Case 1
python_switch(4)  # Output: No case matched

Also in many cases you can put your actions in a dict or a set and use lamda.
Something like this. altho it might be confusing to a lot of people who is just starting with python.
or just dislike using lambda :p

Python:
influences = {
    ("Monday", "Morning"): lambda: jump(Room1_Monday_Morning_Influence) if RubyI >= 1 else None,
    ("Monday", "Morning", 5): lambda: jump(Room1_Monday_Morning_Five_Influence) if RubyI >= 5 else None,
    ("Monday", "Noon"): lambda: jump(Room1_Monday_Noon),
    ("Monday", "Afternoon"): lambda: jump(Room1_Monday_Afternoon),
    ("Tuesday", "Morning"): lambda: jump(Room1_Tuesday_Morning)
}

if clock.weekday, clock.time in influences:
    influences[(clock.weekday, clock.time)]()
else:
    [...]
Anyway. just my 2 cents.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,628
2,286
Code:
  menu:
        "Room 1":
            if clock.weekday == "Monday" and clock.time == "Morning":
                jump Room1_Monday_Morning
            if clock.weekday == "Monday" and clock.time == "Morning" and RubyI >= 1:
                jump Room1_Monday_Morning_Influence

To simplify your own conclusions and other replies in an even simpler way...

RenPy script starts at the top and works its way down. The first true answer it encounters, it will execute. Since you're using jump there's no opportunity for the script to check any of the other values.

Most programming will not look for the "best" solution, just the ones you've told it to look for, in the order you've told it to look for them.
The eternal cry of programmers everywhere "Do what I meant... not what I said!"

I've noticed in your replies another symptom of the same problem. if RubyI >= 1 and if RubyI >= 5 are BOTH true if the value is 6, except because you check >= 1 first, that is what it'll use. You either want to code if RubyI >= 1 and RubyI < 5 or code the checks in reverse numerical order. (Check for >= 5 first, then >= 1, etc.) to limit the potential overlaps.

Personally, I would recommend splitting up your code if you're already running into problems. What you are trying to accomplish isn't bad, but it feels like it's a step further than you are ready for right now.

Perhaps consider something like:

Python:
label room1_what_next:

    if clock.weekday == "Sunday":
        jump Room1_Sunday
    if clock.weekday == "Monday":
        jump Room1_Monday
    if clock.weekday == "Tuesday":
        jump Room1_Tuesday
    if clock.weekday == "Wednesday":
        jump Room1_Wednesday
    if clock.weekday == "Thursday":
        jump Room1_Thursday
    if clock.weekday == "Friday":
        jump Room1_Friday
    if clock.weekday == "Saturday":
        jump Room1_Saturday

    "If the script reach this point, things have gone horribly wrong."

label Room1_Monday:

    if clock.time == "Morning":
        jump Room1_Monday_Morning
    if clock.time == "Afternoon":
        jump Room1_Monday_Afternoon
    if clock.time == "Evening":
        jump Room1_Monday_Evening
    if clock.time == "Night":
        jump Room1_Monday_Night

    "If the script reach this point, things have gone horribly wrong."

label Room1_Monday_Morning:

    if RubyI >= 5 then
        jump Room1_Monday_Morning_Ruby_High_Influence
    if RubyI >= 1 then
        jump Room1_Monday_Morning_Ruby_Low_Influence

    "Doing whatever happens on a Monday Morning when Ruby's influence is zero or less."

    # [...] Rinse and repeat...

It's a lot more long winded, but it's more straight forward and avoids some of the more obvious pitfalls you seem to be finding.

Of course, there are "other" ways (It's RenPy, there are always other ways)...

Using my own code, influenced but not directly copied for yours:

Python:
default current_room = "room1"
default clock_day = "tuesday"
default clock_time = "morning"

label start:

    scene black with fade

    jump expression current_room + "_" + clock_day + "_" + clock_time


label room1_monday_morning:

    "It's Monday morning and I'm in Room #1"

    jump the_end

label room1_tuesday_morning:

    "It's Tuesday morning and I'm in Room #1"

    jump the_end

    # [...] Rinse and repeat...

jump expression is a "clever" way of working around all those if statements. Of course, "clever" code is evil if you don't understand it completely.

General rule of thumb: Keep it simple or at least as simple as makes sense to you.
 

Unknown72

Member
Jan 3, 2021
217
287
To simplify your own conclusions and other replies in an even simpler way...

RenPy script starts at the top and works its way down. The first true answer it encounters, it will execute. Since you're using jump there's no opportunity for the script to check any of the other values.

Most programming will not look for the "best" solution, just the ones you've told it to look for, in the order you've told it to look for them.
The eternal cry of programmers everywhere "Do what I meant... not what I said!"

I've noticed in your replies another symptom of the same problem. if RubyI >= 1 and if RubyI >= 5 are BOTH true if the value is 6, except because you check >= 1 first, that is what it'll use. You either want to code if RubyI >= 1 and RubyI < 5 or code the checks in reverse numerical order. (Check for >= 5 first, then >= 1, etc.) to limit the potential overlaps.

Personally, I would recommend splitting up your code if you're already running into problems. What you are trying to accomplish isn't bad, but it feels like it's a step further than you are ready for right now.

Perhaps consider something like:

Python:
label room1_what_next:

    if clock.weekday == "Sunday":
        jump Room1_Sunday
    if clock.weekday == "Monday":
        jump Room1_Monday
    if clock.weekday == "Tuesday":
        jump Room1_Tuesday
    if clock.weekday == "Wednesday":
        jump Room1_Wednesday
    if clock.weekday == "Thursday":
        jump Room1_Thursday
    if clock.weekday == "Friday":
        jump Room1_Friday
    if clock.weekday == "Saturday":
        jump Room1_Saturday

    "If the script reach this point, things have gone horribly wrong."

label Room1_Monday:

    if clock.time == "Morning":
        jump Room1_Monday_Morning
    if clock.time == "Afternoon":
        jump Room1_Monday_Afternoon
    if clock.time == "Evening":
        jump Room1_Monday_Evening
    if clock.time == "Night":
        jump Room1_Monday_Night

    "If the script reach this point, things have gone horribly wrong."

label Room1_Monday_Morning:

    if RubyI >= 5 then
        jump Room1_Monday_Morning_Ruby_High_Influence
    if RubyI >= 1 then
        jump Room1_Monday_Morning_Ruby_Low_Influence

    "Doing whatever happens on a Monday Morning when Ruby's influence is zero or less."

    # [...] Rinse and repeat...

It's a lot more long winded, but it's more straight forward and avoids some of the more obvious pitfalls you seem to be finding.

Of course, there are "other" ways (It's RenPy, there are always other ways)...

Using my own code, influenced but not directly copied for yours:

Python:
default current_room = "room1"
default clock_day = "tuesday"
default clock_time = "morning"

label start:

    scene black with fade

    jump expression current_room + "_" + clock_day + "_" + clock_time


label room1_monday_morning:

    "It's Monday morning and I'm in Room #1"

    jump the_end

label room1_tuesday_morning:

    "It's Tuesday morning and I'm in Room #1"

    jump the_end

    # [...] Rinse and repeat...

jump expression is a "clever" way of working around all those if statements. Of course, "clever" code is evil if you don't understand it completely.

General rule of thumb: Keep it simple or at least as simple as makes sense to you.
In that first example where the checks are split into different labels for each check is actually exactly what I was thinking of doing, so it's nice to see it laid out like that. I have no clue what "jump expression" does mostly cause, as mentioned, I've only started learning how to do all this the last few days/week, so most of what I know is from me looking at the code of other stuff for reference/learning/studying or experimenting on my own, so I appreciate all this new knowledge!
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
11,426
17,391
Beeeeeeep... Bugs Alert, this is not a drill... I repeat... Bugs Alert, this is not drill...


Python:
influences = {
    ("Monday", "Morning"): lambda: jump(Room1_Monday_Morning_Influence) if RubyI >= 1 else None,
    ("Monday", "Morning", 5): lambda: jump(Room1_Monday_Morning_Five_Influence) if RubyI >= 5 else None,
    ("Monday", "Noon"): lambda: jump(Room1_Monday_Noon),
    ("Monday", "Afternoon"): lambda: jump(Room1_Monday_Afternoon),
    ("Tuesday", "Morning"): lambda: jump(Room1_Tuesday_Morning)
}

if clock.weekday, clock.time in influences:
    influences[(clock.weekday, clock.time)]()
else:
    [...]
Firstly:
Your influences[(clock.weekday, clock.time)]() will only match one entry:
("Monday", "Morning"): lambda: jump(Room1_Monday_Morning_Influence) if RubyI >= 1 else None
The second entry, ("Monday", "Morning", 5): lambda: jump(Room1_Monday_Morning_Five_Influence) if RubyI >= 5 else None is never addressed because of the third entity in the tuple that serve as key.

Firstly dot five:
Like dictionaries are unordered, even if the code was working, you would have cases where the code branch you to "Room1_Monday_Morning_Influence" despite RubyI being superior or equal to 5. This just because it would be the first match found by Python, and therefore the one tested.

Secondly:
Lambdas expect Python statement, jump() is not a Python statement, nor is it a Ren'Py one.

Thirdly:
The else will only catch cases where the day and period aren't used as key for the dictionary, not the case where the lambda will return None.




Add to this the fact that:

Firstly:
You forgot the entry for Monday Morning when RubyI is lower than 1.


Secondly:
You need 10 lines, 11 if you add the missing Monday Morning, 26 if you include the default branching for the rest of the days. Against 7 lines in my example, even when including the default branching for the rest of the days.
And the difference grow further and further the more room and exceptions there's to handle. Your approach need to explicitly declare all day/period couple even when there's no exceptions, mine have them handled by default in the code.
A solution that need at least three times more lines, and is so much prone to bugs is not a simplification.


Thirdly:
RubyI isn't necessarily the only secondary branching condition. Therefore you can't correct your code with something like if clock.weekday, clock.time, RubyI in influences:.
Instead, you need a branching depending on the optional third condition. What imply that you also need to find a way to discriminate this in your dict, because RubyI >= 5 isn't the same than RubyC >= 5, while, as it is defined, both would lead to a dictionary entry labeled ( "Monday", "Morning", 5 ).


Fourthly:
In your example there's no reason to have the jump as lambda (even when done right), you could perfectly just have the label.

Without the exception to simply the explanation:
Python:
influences = {
    ("Monday", "Morning"): "Room1_Monday_Morning",
    ("Monday", "Noon"): "Room1_Monday_Noon",
    ("Monday", "Afternoon"): "Room1_Monday_Afternoon",
    ("Tuesday", "Morning"): "Room1_Tuesday_Morning"
}

if clock.weekday, clock.time in influences:
    jump exception influences[(clock.weekday, clock.time)]
else:
    [...]
With the exception:
Python:
influences = {
    ("Monday", "Morning"): lambda: "Room1_Monday_Morning_Five_Influence" if RubyI >=5 else ( "Room1_Monday_Morning_Five_Influence" if RubyI >= 1 else "Room1_Monday_Morning_Influence" ),
    ("Monday", "Noon"): lambda: "Room1_Monday_Noon",
    ("Monday", "Afternoon"): lambda: "Room1_Monday_Afternoon",
    ("Tuesday", "Morning"): lambda: "Room1_Tuesday_Morning"
}

if clock.weekday, clock.time in influences:
    jump exception influences[(clock.weekday, clock.time)]()
else:
    [...]
In both case it's still more lines since the example I gave in my previous post; an example that works exactly the same without the need of a dictionary. And, of course, when the exception enter the scene it lead to way too complex lambdas.


Fifthly:
You totally misunderstood how porting switch/case into Python should be done.

Python:
define dayRoom1 = { 
    "clock.weekday == 'Monday' and clock.time == 'Morning' and 1 <= RubyI < 5": "Room1_Monday_Morning_Influence",
    "clock.weekday == 'Monday' and clock.time == 'Morning' and RubyI >= 5": "Room1_Monday_Morning_Five_Influence",
    "clock.weekday == 'Monday' and clock.time == 'Morning'": "Room1_Monday_Morning",
    "clock.weekday == 'Monday' and clock.time == 'Noon'": "Room1_Monday_Noon",
    "clock.weekday == 'Monday' and clock.time == 'Afternoon'": "Room1_Monday_Afternoon",
    "clock.weekday == 'Thuesday' and clock.time == 'Noon'": "Room1_Thuesday_Noon",
}

menu:
    "room1:
        python:
            jumpingLabel = "Default_label_in_case_of_error"
            for condition in dayRoom1:
                if eval( condition ):
                    jumpingLabel = dayRoom1[atom]
                    break
        jump expression jumpingLabel
What is still heavier than the code I gave, but can be lightened. For this you just need to care about the exception in the dictionary, and rely on a generic function working for all rooms:
Python:
init python:

    def labelFinder( room, specialCases ):

        retVal = ""

        for atom in specialCases:
            if eval( atom ):
                retVal = specialCases[atom]
                break

        #  No exception have been found for that day at that period, therefore
        # use the default label matching that day and period.
        #  This present the advantage to not need a default label in case of error.
        if retVal == "":
            retVal = "{}_{}_{}".format( room, clock.weekday, clock.time )

        return retVal


# The conditions matching the special cases for room 1.
define dayRoom1 = { 
    "clock.weekday == 'Monday' and clock.time == 'Morning' and 1 <= RubyI < 5": "Room1_Monday_Morning_Influence",
    "clock.weekday == 'Monday' and clock.time == 'Morning' and RubyI >= 5": "Room1_Monday_Morning_Five_Influence",
}

# The conditions matching the special cases for room 2.
define dayRoom2 = { [...] }

menu:
    "room 1":
        jump expression labelFinder( "Room1", dayRoom1 )
    "room 2
        jump expression labelFinder( "Room2", dayRoom2 )
It need 13 lines against your 11 lines. But it will still only need those 13 lines if you add the 5 missing days and their three periods, against 26 lines for your example. This because here you don't have to add entries for the days and period that don't have exceptions.

The condition are a bit heavy, but they can be simplified too:
[I use the opportunity to also reduce the /labelFinder/ part]
Python:
init python:

    def labelFinder( room, specialCases ):

        retVal = ""

        for atom in specialCases[(clock.weekday,clock.time)]:
            #  You don't really need the /break/, browsing all the entries will not 
            # need much time since you limits by the day and period.
            if eval( atom ): retVal = specialCases[atom]

        return retVal if retVal != "" else "{}_{}_{}".format( room, clock.weekday, clock.time )


# The conditions matching the special cases for room 1.
define dayRoom1 = { 
    ( "Monday", "Morning" ): { "1 <= RubyI < 5": "Room1_Monday_Morning_Influence",
                               "RubyI >= 5": "Room1_Monday_Morning_Five_Influence" },
    ( "Monday", "Noon" ): { [exception for Monday Noon] },
    [...]

# The conditions matching the special cases for room 2.
define dayRoom2 = { [...] }

menu:
    "room 1":
        jump expression labelFinder( "Room1", dayRoom1 )
    "room 2
        jump expression labelFinder( "Room2", dayRoom2 )
We now drop to 10 lines, including the default branching for all days and periods, against your broken 11 lines that only applied for 1 days plus one period of another day.

Simpler, lighter, bug free(minus the errors possibly made in the conditions themselves), and apply for all periods of all days of all rooms without needing to add more than one line by exception.


This is how you do a switch/case in Python and with Ren'Py.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,628
2,286
I have no clue what "jump expression" does mostly cause, as mentioned, I've only started learning how to do all this the last few days/week, so most of what I know is from me looking at the code of other stuff for reference/learning/studying or experimenting on my own, so I appreciate all this new knowledge!

Yeah. Normally, I include links to the original documentation. I didn't expect you to want to use this one, so I didn't. But that isn't to say someone else reading this won't take a look. Thing is, the documentation doesn't really help much on this one.

expression is essentially "use this calculated value".
Okay. That doesn't help much.

Using a random statement...
$ myvar = current_room + "_" + clock_day + "_" + clock_time
  • $ is pretty much "do single python command".
  • myvar = is change the value of this variable myvar to the value on the right side of the equals sign.
  • + (at least in this context) is (add) two strings together.
In my example, this would take the value of current_room add an underscore to it, then add the value of clock_day, add another underscore and then finally add clock_time.
The end result would be the same as $ myvar = "room1_tuesday_morning".

So now, that would end up executing as jump room1_tuesday_morning, because it sticks the value of the expression into the command - even though the value would change, as the variables change.

Of course, bad things would happen if the label didn't exist or the combination of variables was wrong. But that's your job as a programmer to make sure that doesn't happen.

To clarify more, just in case... $ myvar = "camel" + "mint" would lead to a value of "camelmint". It's just string manipulation.
 

n00bi

Active Member
Nov 24, 2022
518
606
Beeeeeeep... Missed the Point Alert
I am sorry, but that example of mine was not intended to be used.
I was just pointing out that a ton of if statements can be done in other ways.
Yes my example is not a valid example for real life and has flaws..
I just tossed that quick together without looking to much at it.

Lambdas expect Python statement, jump() is not a Python statement, nor is it a Ren'Py one.
Yes ofc. that's true. i wasn't thinking. but you should still be able to use lambda for all other things in your gamelogic.


You totally misunderstood how porting switch/case into Python should be done.
I did?

Basic C Switch statement.
Code:
char result = (a & b) || (c & d)
switch(result) {
  case(1): { code..} break;
  case(2): { code..} break;
  ...
  default: {code..}
}
There is no "how it should be done."
If you don't want to emulate a switch case expression using a if elseif else. "which is basically the closest thing to it".
It is up to the coder to decide how they implements their versions of it.
What floats your boat might not be suited for others.

Having that said. a C swtich statement has one small trick up its sleeve tho.
You don't have permission to view the spoiler content. Log in or register now.

I was merly trying to point out that.
Code:
Line01: if (foo and bar and moo == a)
Line02: elseif (foo and bar and moo == b)
Line97: elseif (foo and bar and moo == zx)
....
Might not be the best way to go about things as there are methods around this.
This is a typical linear way of doing it as you would in a system language.
No need to write the code like it was C/C++, might as well use it then :p
Most times therer is a more "pythonic" way to write the code.

I didnt put a disclaimer on my post with "not intended for real use and is only meant to give a general idea".
Sorry about that.
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
11,426
17,391
It is up to the coder to decide how they implements their versions of it.
What floats your boat might not be suited for others.
It's not about what floats my boat, but about using the strength of the language, while avoiding its flaw.


Like dictionaries are unordered, basing a whole switch/[/icode]case[/icode] structure on them is opening the gate for unpredictable behavior, because you've no guaranty that the keys will always be in the same order. The most obvious issue with that would be a dev adding few entries in an update, and breaking his game, precisely because the order have now changed. And good luck to find the error, since the previous code was working perfectly fine.
It's also calling for an exponential complexity of the structure, each time you have a new condition. What would also imply a total reworks of the whole code to take count of it.
Using dictionaries to mimic switch/case structure isn't necessarily a bad idea, but it only works when applied to constants values, not for conditional ones like it's the case here. Something like:
Python:
actionHub = { "fight": myGameEngine.fight, "protect": myGameEngine.shield, "retreat": myGameEngine.retreat }

chosenAction = [ask player for his action]
if chosenAction in actionHub:
    actionHub[chosenAction]()
else:
    "I don't understand you."

But the instant the case are conditionals, using a list of evaluable values if thousand times more efficient, while mimicking perfectly a switch/case behavior; after all, internally it's nothing more than a list of assessed conditions.

It ensure that the order will be constant, what permit to simplify the conditions; all the previous case have failed, you can discard them. If you've two conditions, one being whatever >= 5 and the other being whatever < 5 and this is True, if you keep them in this order, you can get rid of the whatever < 5 and part, because you know that it will always be true.
Something that isn't possible with a dictionary, due to the order not being enforced; you've no guaranty regarding which one of the two will be tested first.
And, of course, like there's no restriction enforced by the code, you can expend the conditions as much as you want without having to change a single line of your code. Something not possible with a dictionary, because the keys have a frozen structure.


I was merly trying to point out that.
Code:
Line01: if (foo and bar and moo == a)
Line02: elseif (foo and bar and moo == b)
Line97: elseif (foo and bar and moo == zx)
....
Might not be the best way to go about things as there are methods around this.
Without noticing that it wasn't at all the code I was advertising for...

I don't write long posts for the pleasure to write long post. All the intermediary explanations and codes are here to help readers who don't have much knowledge (what is how OP describe himself) to understand what will be the last, and advertised, step.
It's a progressive dive in complexity, with each step being relatively easy to understand. This while the code permit to do some test, and ensure that understanding. Readers will then end with a code that have a bigger complexity, but that still will be relatively easy to understand, because only being a bit more complex that the previous one.


Most times therer is a more "pythonic" way to write the code.
I can assure you that there's nothing "pythonic" is my code.
The "pythonic" way is precisely to rely on pure if/elif structures, that are more stable, more readable, less opened to bugs, and generally more optimized, in term of processing time, than whatever alternative you can come with.
 
  • Hey there
Reactions: n00bi

Turning Tricks

Rendering Fantasies
Game Developer
Apr 9, 2022
1,519
2,807
Currently mainly just testing this as I've never done Renpy and I mostly understand things. However I've run into a snag with a current test. I basically have a working Day and Time system going, and I've successfully had it check for both when decide on where to jump, but as soon as I add the third variable it just ignores that one entirely even when that third variables conditions are met and instead just does the normal code without that variable.

This is what it looks like, everything is defined properly (as a result of prior testing), it's just for some reason not working right.

Code:
  menu:
        "Room 1":
            if clock.weekday == "Monday" and clock.time == "Morning":
                jump Room1_Monday_Morning
            if clock.weekday == "Monday" and clock.time == "Morning" and RubyI >= 1:
                jump Room1_Monday_Morning_Influence
            if clock.weekday == "Monday" and clock.time == "Noon":
                jump Room1_Monday_Noon
            if clock.weekday == "Tuesday" and clock.time == "Morning":
                jump Room1_Tuesday_Morning
It'll properly do the result for the normal ones without RubyI, but even when RubyI is increased to 1 it only jumps to Room1_Monday_Morning rather then Room1_Monday_Morning_Influence. The same thing happens when I change >= to == or increase the variable higher then one.

Any help would be appreciated!

I'm surprised nobody has mentioned the if all statement. It's another way to handle multiple conditional arguments.

And like others have mentioned in this thread, you really have to pay attention to the order of your logical tests. Like your first two arguments can cause issues because both are correct. So the first one would be selected always, in the case of it being Monday and Morning. So I added a counter-argument to your first statement. It will only be correct if Ruby's influence is less than 1.

Here's how I would code your OP using if all and elif all ...

Python:
label Room1:

    if all ([clock.weekday == "Monday", clock.time == "Morning", RubyI <= 0]):
        jump Room1_Monday_Morning
    elif all ([clock.weekday == "Monday", clock.time == "Morning", RubyI >= 1]):
        jump Room1_Monday_Morning_Influence
    elif all ([clock.weekday == "Monday", clock.time == "Noon"]):
        jump Room1_Monday_Noon
    elif all ([clock.weekday == "Tuesday", clock.time == "Morning"]):
        jump Room1_Tuesday_Morning
 

n00bi

Active Member
Nov 24, 2022
518
606
It's not about what floats my boat, but about using the strength of the language, while avoiding its flaw.
Here i strongly disagree, Ofcourse its about what floats yours/mine boat. yes i agree that you should use the strength of the language.
Hence me trying to point of that the python code should be "pythonic".
The code shown in my spoiler shows that a C switch statement is not just a simple: if elseif else equivalent.
It can have a little different behavior.
To emulate how it truly works you need to write your own method.
And that is not written in stone how it should be done, even i didn't provide an example for that.
you can just use a dict like.
Code:
 switch = { 1: fnc_1, 2: fnc_2, };  result = switch.get(value, some_default_fnc)()
or your own function, or a full blown bloated class with all the setters and getter. nothing is set in stone.


Like dictionaries are unordered, basing a whole switch/[/icode]case[/icode] structure on them is opening the gate for unpredictable behavior, because you've no guaranty that the keys will always be in the same order.
Ok yes. i agree. updates and changes etc may f.up things.. good point.
But here we are talking about best coding practices and not whats doable.

I should have spend a bit more time on the 1st post explaining my intentions.
Maybe i just did it on purpose, because i knew you would come in and give a proper example :whistle:
Just kidding ofcource.


I can assure you that there's nothing "pythonic" is my code.
The "pythonic" way is precisely to rely on pure if/elif structures, that are more stable, more readable, less opened to bugs, and generally more optimized, in term of processing time, than whatever alternative you can come with.
I can assure you that you are wrong.
For example chaining comparison (1 <= RubyI < 5) is pythonic and it executes faster than using two comparisons.
You write too much py to see it your self :p

But regarding This: "The pytonic way ... rely on purly if/else...
I disagree, having C as my main language and py is my hobby one. i can tell you i hate looking at code where half the page
looks like
Code:
if (foo) {
...
} else if (foo1) {...
} else if (foo2){...
...
A millions lines later.
} else {... }
That's the nice thing about python. you can often avoid this.
This is a the classical "linear" way of writing logic.
It gets the job done, works, but looks like shit, makes code harder to navigate/bloated <-(imo).
But as you said yourself. its about using the strength of the language.
Python has all sort of fancy pancy ways to avoid writeing the code like classic C/C++ style.

Is it easier to read? that is subjective and i would say has partly to do with skills aswell.
For someone new to the language yes the classical way may be simpler to understand.

But as i said, you can often write the code more pytonic.
Don't get me wrong. I am not trying to say.. don't use if elseif else.
We all need to use them.
I am just saying that, there are "better ways" imo in many scenarios.

Discussing, Learning, sharing knowledge, best coding practices,is something i strongly advocate for
We have nothing to loose by learning or sharing something with others.
 
Last edited: