Ren'Py Need help creating a variable with a variable maximum value.

ffprn09

New Member
May 26, 2019
4
1
Hi, i'm pretty new to programming and i want to create a game where you can upgrade your wallet or health or whathaveyou.
So when you start the game you can only have 10 bucks with a minimum of 0, you then find a bigger wallet and now you can hold 20 bucks. (Hooray!)

I have already looked around the internet and i did find some stuff like this thread:
In that thread Saltome posts a line of code:

Code:
$energy =max(min(energy, 100), 0)
About a year ago i was dicking around with renpy as well and I remember I found the same thread and have gotten this little line of code to work. (I don't remember how)
Now though it completely crashes.

So if I understand correctly, I think it should work like this: first the lowest value wil be selected between the variable "energy" and 100 at "min(energy, 100)" then the highest value will be selected between the value decided by the min part and 0 within "max(min(), 0)" This should limit the value between 100 because min won't pass a higher value and 0 because max won't pass a lower value.

Now I think this code crashes because the 2nd energy part needs a value from the first energy part which isn't there and then stuff goes apeshit.

This is the code i used to test specifically this:

Code:
label start:

$MaxCash = 10
$Cash = max(min(Cash, MaxCash), 0)

show screen Cash

label lbl1:
    menu:
        "+1":
            $ Cash += 1
            jump lbl1

        "-1":
            $ Cash -= 1
            jump lbl1

return
The screen is in a different .rpy file and goes like this:

Code:
screen Cash:
    text "Cash: [Cash]"
Change the "max(min(Cash, MaxCash), 0)" to zero and the code works fine. But $Cash will go up and down indefinitely.

Can you guys help me get this code to work or do you maybe have a different solution?
I have tried the other bits of code in that thread but i couldn't get those to work either.

Thanks!
 

the66

beware, the germans are cumming
Modder
Donor
Respected User
Jan 27, 2017
7,808
24,388
Python:
default Cash = 0
default MaxCash = 10

init python:
    def addCash(cash=0):
        if not isinstance(cash, (int, float)):
            return
        renpy.store.Cash = min(max(Cash + cash, 0), MaxCash)

screen Cash:
    text "Cash: [Cash]"

label start:
    show screen Cash

    menu lbl1:
        "+1":
            $ addCash(1)

        "-1":
            $ addCash(-1)
    jump lbl1

return
 
  • Like
Reactions: ffprn09

ffprn09

New Member
May 26, 2019
4
1
Dude.. Don't know exactly how it works but goddamnit it works! I'll see if i can figure it out. Anyway thanks a bunch!
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,607
2,256
Dude.. Don't know exactly how it works but goddamnit it works! I'll see if i can figure it out. Anyway thanks a bunch!

Okay... turning code into English...

Prepare for a wall of text... which I hope will be simple enough to follow from beginning to end...


First... Your code (which as far as I can see, didn't work)...

label start: # Just a pre-defined label RenPy uses when you click "Start" from the main menu.

$MaxCash = 10 # Set "MaxCash" to a value of 10.

$Cash = max(min(Cash, MaxCash), 0) # Set "Cash" to a value of... Okay... this one is going to need breaking down more.

It's all about the brackets ( ).​
So we're going to do : max ({something}, 0)
... So we need to figure out what {something} is.​
{something} = min(Cash, MaxCash) # So... pick the smallest number between Cash and MaxCash.​
PROBLEM #1 : You're trying to create a variable called "Cash" using a variable called "Cash". It doesn't exist yet and so it crashes.
No problem, let's change the code a bit...​
Python:
    $ MaxCash = 10
    $ Cash = 5
    $ Cash = max(min(Cash, MaxCash), 0)
Okay. So now we're doing min(Cash, MaxCash) # But Cash already had a value of 5 before trying this.​
Effectively you're doing "Tell me which is lower... 5 or 10"... Spoiler alert... it's 5.​
Alternatively if you did this instead:
Python:
    $ MaxCash = 10
    $ Cash = 20
    $ Cash = max(min(Cash, MaxCash), 0)
... the answer would be 10. (Which is lower 20 or 10?).​
So next, we go back to the max ({something}, 0)
We now know that (assuming $ Cash = 5) the result of the min ( ) is 5.​
So now we're doing max (5, 0) which is obviously going to be 5.​
So unless Cash ever ends up being negative, the first result will always be higher than 0.​
What you end up with is something the means the result is always going to be between 0 and MaxCash.​

So far, so good...

Then you go into:
Python:
label lbl1:
    menu:
        "+1":
            $ Cash += 1
            jump lbl1

        "-1":
            $ Cash -= 1
            jump lbl1
Okay, so depending on the choice... you're either adding 1 or subtracting 1 from Cash.
PROBLEM #2 : This has nothing at all to do with what has already happened. Assuming Cash = 5 before making a choice of "+1"... then Cash = 6. But if Cash = 10 and you do "+1", then Cash would be 11 even though MaxCash is 10 - since nothing has told it not to.

You could however do something like:
Python:
label lbl1:
    menu:
        "+1":
            $ Cash += 1
            $ Cash = max(min(Cash, MaxCash), 0)
            jump lbl1

        "-1":
            $ Cash -= 1
            $ Cash = max(min(Cash, MaxCash), 0)
            jump lbl1
This would change the value of Cash with one statement then immediately follow that up by applying the limits of "0 to MaxCash".

So now to the66 's solution....

Python:
default Cash = 0
default MaxCash = 10

init python:
    def addCash(cash=0):
        if not isinstance(cash, (int, float)):
            return
        renpy.store.Cash = min(max(Cash + cash, 0), MaxCash)

screen Cash:
    text "Cash: [Cash]"

label start:
    show screen Cash

    menu lbl1:
        "+1":
            $ addCash(1)

        "-1":
            $ addCash(-1)
    jump lbl1
Firstly he's setting up the variables Cash and MaxCash using default instead of $ . There are some technical reasons why... that honestly you don't need to know. Just take my word for it... it's a better way to do it.

Note: default lines can go anywhere in the code. They are run as the game is starting up. You could put them as the last line of your code and they would still run first. By convention most devs would put them right at the top of their code. If it helps you... think of it as "create this variable with this default value". Yeah... right up there at the top.

Next he's using def within init python:.
What this is doing is creating a new function (think of it as a new command) called "addCash".
def addCash(cash=0): # create a new function "addCash"... Store anything I send to that new function in a variable called cash. If I forget to pass a value to this new function, assume a value of zero.

Note: RenPy is case sensitive. cash and Cash are two entirely different things.

So next is...
Python:
        if not isinstance(cash, (int, float)):
            return
Long story short... this checks to make sure the value of cash sent to addCash() is a number. If it isn't, return (effectively stop). int is integer and just means whole numbers with no decimal places. float is a floating point number, also known as scientific notation... and is just a number WITH decimal places.

99.9% of the time, all variables are stored in a python object called "store", which itself is part of another object called "renpy". (at least by most devs in most RenPy games). So renpy.store.Cash is just another way of referring to the variable Cash. Problem is... all this is being set up while python is initializing... which is why you have to use the long arsed name instead of the shorter one you'd use practically everywhere else.

renpy.store.Cash = min(max(Cash + cash, 0), MaxCash) is doing the same max/min thing from earlier... but using the value passed along as cash (note: the lower case version of the name, passed as a value to function) added to the original version of Cash (the "real" variable "Cash").

So now, any time you do $ addCash ( {number} ), it does all those commands that make up the definition def of addCash().

$ addCash(6) would add 6 to whatever the value of Cash was. As long as the answer is between 0 and MaxCash.

$ addCash(1) would add 1 within those same limits.

$ addCash(-1) would add "-1"... which is effectively subtracting 1. Again, it can't drop below zero... because of the max / min thing within addCash().

$ addCash("fish") wouldn't do anything, because "fish" is neither an integer nor a floating point number (it's a string). But thankfully due to that clever check in the middle of the definition... it doesn't cause RenPy to crash and instead just does that return

Next is a choices menu: similar to how you coded it. If you didn't already notice... note that menu: statements can also effectively be label: statements too. It saves some typing, though not everyone knows it's even possible to merge the two into a single statement.
Python:
    menu lbl1:
        "+1":
            $ addCash(1)

        "-1":
            $ addCash(-1)
    jump lbl1

Hopefully that explains everything in a simple enough to follow. If not... fuck it. It works... Accept "it's magic" and move on.

Finally...


You don't have to use a screen to show the values.
Just make it a line of dialogue like any other.

I tested it with:
Python:
    "The value of Cash is [Cash], and MaxCash is [MaxCash]"

    # no different than...
    "You open the door"

You could even put it as part of your choices menu:
Python:
    menu lbl1:
        "The value of Cash is [Cash], and MaxCash is [MaxCash]"
        "+1":
            $ addCash(1)

        "-1":
            $ addCash(-1)
    jump lbl1

Since if the very first line after menu: isn't a choice... it's treated as dialogue.


A completely unnecessary change... but I'd be tempted to change things to this:
Edit: NOPE, NOPE, NOPE. What I wrote was complete bollocks. Forget I even mentioned it.

If you managed to read this far... well done. :devilish:
 
Last edited:

ffprn09

New Member
May 26, 2019
4
1
I did.. I did read it all. I was just working on my leprechaun theory for this code before i read this, but this makes way more sense. Anyway, thanks a lot dude! You really made a lot of things much more clear to me. :D
 
  • Like
Reactions: 79flavors

yihman1

Knockout Master
May 11, 2017
3,109
10,937
Hi, i'm pretty new to programming and i want to create a game where you can upgrade your wallet or health or whathaveyou.
So when you start the game you can only have 10 bucks with a minimum of 0, you then find a bigger wallet and now you can hold 20 bucks. (Hooray!)
I think others answered the coding aspects really good nice job on them and you got your answer. However, as a concept, I think it's a VERY BAD idea to have money as a variable that can be maxed out. Health points, magic points, item quantities, stat points, pretty much ANYTHING but money is reasonable to cap and you will get no argument from me.

Here is why money should NEVER cap:

In the history of the world;
no man has ever entered a bank and they said "Sorry you can not deposit more than X dollars".
no man has ever gotten a paycheck that was $0 because his boss gave him his money cap.
no man has ever went into a store that could not accept any more money for their sales because their profits were capped