Ren'Py [SOLVED] Help having smoother ifs

Sep 5, 2024
8
2
I wanted to have Renpy lines that look like this:
Python:
if (skill_check('stealth', 2) or skill_check('h2h', 2) or skill_check('guns', 2)):
If "skill_check" is a def'ed python function, the above works; but that adds a number of other complications and is not desirable. If it's a RenPy label, the above throws an error ("name 'skill_check' is not defined). The closest I have managed is:
Python:
call skill_check('stealth', 2)
$ temp = _return
call skill_check('h2h', 2)
$ temp |= _return
call skill_check('guns', 2)
$ temp |= _return
if temp:
But this is pretty painful.

What would be a smooth, idomatic way to do it in pure RenPy?

EDIT: The thread ended up long winded so just editing to include the answer up here. The answer is: there isn't such a thing.
 
Last edited:

Winterfire

Forum Fanatic
Respected User
Game Developer
Sep 27, 2018
5,296
7,695
I am confused, why aren't you creating a function (skillcheck) and getting the output from it?
Assuming you don't know what that is, or how to do it, here's a newbie asking the question and the response:
and here's a random snippet from the docs to see how it looks:


For more information, simply google "python tutorial"
 
Sep 5, 2024
8
2
Okay, seems like I wasn't clear. What I meant by
If "skill_check" is a def'ed python function, the above works; but that adds a number of other complications and is not desirable.
Is that defining the function 'skill_check' inside a python block is literally not desirable. I want it to perform regular RenPy things like, for example, calling on a label (see https://f95zone.to/threads/solved-bug-with-renpy-call.212417/post-14025249).

That's why I was asking if there's a RenPy way of doing it that isn't so verbose.
 
Last edited:

Winterfire

Forum Fanatic
Respected User
Game Developer
Sep 27, 2018
5,296
7,695
No, that's not an excuse to completely disregard functions, you just don't shove it inside a label. Keep it outside of any label, and there won't be any complications and/or issues.

You can use renpy functions inside functions, you can use existing variables outside of the python block, and even display/use the return of said functions in labels.
 
Sep 5, 2024
8
2
When I implement it as a function, the inner RenPy 'call' that are inside 'skill_check' (now turned into 'renpy.call(...)' because we're inside a python block) behave differently (they skip all remaining python logic in the function, returning to the next RenPy line in the higher context).

What am I missing? Is there a way to define a function that doesn't mean writing it inside a python block?
 

Winterfire

Forum Fanatic
Respected User
Game Developer
Sep 27, 2018
5,296
7,695
Why would you use "call" inside a skill_check function? Functions are meant to do (often small) portions of repeatable code, i'd imagine a "skill_check" function to take some parameters, maybe use a renpy.random for a roll, maybe even use a default variable, do some operations within the function, then simply return the result to be used in the game (For conditional checks, or even calling labels), but not inside the function itself. That's completely out of scope imho.
 
  • Like
Reactions: anne O'nymous

Winterfire

Forum Fanatic
Respected User
Game Developer
Sep 27, 2018
5,296
7,695
Here's a quick example, just in case I am misunderstanding something here as I am not sure if I clearly understood what you need:


Python:
default mod = 0

label start:
    #Use skill_check while displaying the result (or store it)
    $temp = skill_check(10)
    Player "Your result is %(temp)d"
    if (temp >= 20):
        jump win
    else:
        jump lose
        
init python:
    def skill_check(dexterity):
        roll = renpy.random.randint(1, 20)
        return mod+dexterity+roll

or...

Python:
default mod = 0


label start:
    #Use skill_check without displaying the result
    if (skill_check(10) >= 20):
        jump win
    else:
        jump lose
        
init python:
    def skill_check(dexterity):
        roll = renpy.random.randint(1, 20)
        return mod+dexterity+roll
 
  • Like
Reactions: anne O'nymous
Sep 5, 2024
8
2
I get what you mean, but it really doesn't matter. I said I wanted a non-python answer because I was using call. I could have said it was because I read somewhere that "RenPy games are supposed to be written in RenPy, not python", took it to heart and wanted to RenPy-fy this. It is just as true.

The point is, can
Python:
call skill_check('stealth', 2)
$ temp = _return
call skill_check('h2h', 2)
$ temp |= _return
call skill_check('guns', 2)
$ temp |= _return
if temp:
Be reduced to something more compact, ideally a one-liner, without turning skill_check into a python method?

Also nevermind the label name being skill check. This will be quick throwaway code. Doesn't mean I feel like unrolling my ifs into many lines, though.
 

Winterfire

Forum Fanatic
Respected User
Game Developer
Sep 27, 2018
5,296
7,695
I get what you mean, but it really doesn't matter. I said I wanted a non-python answer because I was using call. I could have said it was because I read somewhere that "RenPy games are supposed to be written in RenPy, not python", took it to heart and wanted to RenPy-fy this. It is just as true.

The point is, can
Python:
call skill_check('stealth', 2)
$ temp = _return
call skill_check('h2h', 2)
$ temp |= _return
call skill_check('guns', 2)
$ temp |= _return
if temp:
Be reduced to something more compact, ideally a one-liner, without turning skill_check into a python method?

Also nevermind the label name being skill check. This will be quick throwaway code. Doesn't mean I feel like unrolling my ifs into many lines, though.
Unfortunately I don't know of any way to make that more compact without using Python. I'm not sure if that's even possible, I am sure anne O'nymous knows though
 

gojira667

Member
Sep 9, 2019
287
273
I get what you mean, but it really doesn't matter. I said I wanted a non-python answer because I was using call. I could have said it was because I read somewhere that "RenPy games are supposed to be written in RenPy, not python", took it to heart and wanted to RenPy-fy this. It is just as true.
Seems a bit ignorant when a Python function gives you what you need with less effort and cleaner code. Python is not a dirty word with Ren'Py.

Anyway, rewrite skill_check to take a list of tuples then loop through the list:
Python:
call skill_check([('stealth', 2),('h2h', 2),('guns', 2)])

label skill_check(skillz):
    $ renpy.dynamic('skill','value','temp','result')
    $ temp = 0
    while skillz:
        $ skill, value = skillz.pop(0)
        # do stuff skill > value
        $ temp |= result # Bitwise OR?
    return temp
 
  • Like
Reactions: anne O'nymous

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,586
15,597
foreword: Okay, my Doc will kill me (in short I'm supposed to stay away from codes, but well, I'm just talking, right ?) but I've been pinged and I'm tempted to say "also indirectly quoted"...
And also, hmm, I'm on med, the kind that have big red "do not operate heavy machinery" everywhere, so I hope I'll be able to write intelligibly; at least I should write real words, thanks to the auto spellcheck ;)


[...] I read somewhere that "RenPy games are supposed to be written in RenPy, not python", took it to heart and wanted to RenPy-fy this. [...]
There's a difference between not using Python when Ren'Py can do it natively, and never using Python code. And the idiot who say, so often, that "Ren'Py games are supposed to be written in Ren'Py, not Python" should sometimes be more explicit and less grumpy...

What it mean is that there's no need to redo what PyTom and the guys have already done, but of course there's need to do what they haven't. And here, you're facing the last case, therefore winterfire answers are correct: use Python.

Now, when said this, you answered, with reason, that renpy.call() will break everything. But why the fuck using renpy.call() ? :/

Python:
init python:
    def skillCheck( what, min ):
        # Assuming that the skills are in the store, because you said nothing regarding this.
        return getattr( store, what ) >= min

label whatever:
    if skill_check('stealth', 2) or skill_check('h2h', 2) or skill_check('guns', 2):
        [do whatever there's to do]
Now, if really you want to be pure Ren'Py, while it's not necessary, Gojira667 gave you the answer:

Python:
label skill_check(skillz):
    $ renpy.dynamic('skill','value','temp')
    $ temp = False
    while skillz:
        $ skill, value = skillz.pop(0)
        # still assuming...
        $ temp |= getattr( store, skill ) >= value
    return temp

label whatever:
    call skill_check( [ ('stealth', 2), ('h2h', 2), ('guns', 2) ] )
    if _return:
        [do whatever there's to do]

But, well, can this really be said "pure Ren'Py" ? The label have six lines, four of them being inline Python...
There's a bit more "pure" alternative:
Python:
label skill_check(skillz):
    $ renpy.dynamic('skill','value')
    while skillz:
        $ skill, value = skillz.pop(0)
        # still assuming...
        if getattr( store, skill ) >= value:
           return True
    return False

label whatever:
    call skill_check( [ ('stealth', 2), ('h2h', 2), ('guns', 2) ] )
    if _return:
        [do whatever there's to do]
But it really feel like overdoing it, because it's, at best, six lines label, plus a two lines condition test, to replace a one line function and a one line condition test. And, of course, the Ren'Py version is less explicit, because you've to look at the label code to see that it's a OR check. Something explicit right from the starts with the function approach.

Also, the function approach will works whatever the way you want to combine the checks:
if skillCheck( "stealth", 2 ) and skillCheck( "h2h", 2 )
if skillCheck( "stealth" 2 ) or ( skillCheck( "h2h", 2) and skillCheck( "guns", 2 ) )
This while working with a label force you to add another label each time there's a new combination.


A last word, when I say that Ren'Py games should be in Ren'Py, what come first in my mind is: "Do not over complicate your life".
Ren'Py come natively with a tons of useful features, all tested by thousands developers and millions players. Even if sometimes it need to pass few days finding how to bend Ren'Py to your will, it will always be easier to use those features than searching a way to do the same in Python, then how to integrate this in your Ren'Py code, and then praying each day that there's no bugs.

But this imply also that one should not over complicate his life by trying to do in Ren'Py something that would highly benefit to be done with Python. Like it's the case here, where the Python approach is shorted, more flexible, more explicit, and guaranty to be bug free.

And the meds having started to kick in, I'll stop while I still looks like a smart guy.
 
Sep 5, 2024
8
2
Okay, after understanding everything, now I'm ready to answer these questions you have oh so fervently asked me.

"Why be complicated and ignorant and not use python for what is clearly intended to be done in python?"

And the reason is, because I didn't know the answer to the question wasn't "oh the syntax for that in RenPy is this, and now it works just like the python line".
I didn't know what the answer was, which is why I asked it. This includes not knowing that trying to do it in RenPy is "overcomplicating" and not some simple syntax change.