AI Porn is here, Create and Fap TRY FREE
x

Ren'Py Negative figures

mr.moonmi

New Member
Game Developer
Jun 21, 2020
13
991
277
Hello everyone.
Does anybody know how to write a function for checking all variables in the game and prevent them from going below the 0?

Here are a couple of variables from my game:
Python:
default s_alpha = 0
default s_beta = 0
default s_chloe = 0
And after some choices players can decrease some of them even below zero. And I don't want that.

I've found one solution that works, but I have to use it every time I want to decrease the value.
Python:
$ s_alpha = max(0, points-1)
I'm pretty sure there's a better and more elegant way to check ALL variables and prevent them from going below the 0.
Hope someone knows how :) Thanks.
 

appelflappel

New Member
Mar 10, 2019
4
3
33
One way to do this is by creating a class which inherits the standard integer type and doesn't allow the value to go below zero. This would look something like
Python:
class NonNegative(int):
    def __new__(cls, value, *args, **kwargs):
        return  super(cls, cls).__new__(cls, max(value, 0))

    def __add__(self, other):
        res = super(NonNegative, self).__add__(other)
        return self.__class__(max(res, 0))

    def __sub__(self, other):
        res = super(NonNegative, self).__sub__(other)
        return self.__class__(max(res, 0))

    def __mul__(self, other):
        res = super(NonNegative, self).__mul__(other)
        return self.__class__(max(res, 0))

    def __div__(self, other):
        res = super(NonNegative, self).__div__(other)
        return self.__class__(max(res, 0))

    def __str__(self):
        return "%d" % int(self)

    def __repr__(self):
        return "NonNegative(%d)" % int(self)
At this point you can create an instance of this class by saying default s_alpha = NonNegative(0). You can now do anything you want with this variable like s_alpha += 3 or s_alpha -= 1 but the value should never go below zero. If you want to do something like s_alpha = points-1, you have to make sure that this points variable is also an instance of NonNegative, since otherwise you would overwrite s_alpha to become a regular integer again. (If points is not an instance of NonNegative, you could for example use s_alpha = NonNegative(points-1))

To keep your code clean I would put this class in some separate python file misc.py and import the class with from misc import NonNegative. Hope this helps!
 
  • Like
Reactions: anne O'nymous

Rich

Old Fart
Modder
Donor
Respected User
Game Developer
Jun 25, 2017
2,698
8,017
715
Another, perhaps slightly simpler, way to do this is to update your variables using a function, rather than directly.
Code:
default love = 0
...
init python:
    def change_love(amount):
        global love

        love += amount
        if love < 0:
            love = 0
Given that, in your script you can then do
Code:
    me "I love you more"
    $ change_love(1)

    me "I love you less"
    $ change_love(-1)
By using a function, you can check boundaries, relationships with other variables, etc.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
12,969
21,596
1,026
Python:
class NonNegative(int):
    def __new__(cls, value, *args, **kwargs):
        return  super(cls, cls).__new__(cls, max(value, 0))

    def __add__(self, other):
        res = super(NonNegative, self).__add__(other)
        return self.__class__(max(res, 0))
Since you already max the value at creation time, you don't need to do it elsewhere.
Code:
    def __add__(self, other):
        return self.__class__(super(NonNegative, self).__add__(other))
Would be enough.

You also don't need to define __str__ and __repr__, the one coming from the ancestor are enough, and you forgot __floordiv__.


This being said, and since we are talking about this, here's a class to have truly capped integers, with either/both a minimal and maximal value.
Python:
init python:

    class CappedInt(int):
        def __new__(cls, value, maxValue=None, minValue=None ):
            if not maxValue is None: value = min( value, maxValue )
            if not minValue is None: value = max( minValue, value )
            self = super(cls, cls).__new__(cls, value )
            self.maxValue = maxValue
            self.minValue = minValue
            return self

        def __add__(self, value):
            return self.__class__( super(CappedInt, self).__add__(value), self.maxValue, self.minValue )

        def __sub__(self, value):
            return self.__class__( super(CappedInt, self).__sub__(value), self.maxValue, self.minValue )

        def __mul__(self, value):
            return self.__class__( super(CappedInt, self).__mul__(value), self.maxValue, self.minValue )

        def __div__(self, value):
            return self.__class__( super(CappedInt, self).__div__(value), self.maxValue, self.minValue )

        def __floordiv__(self, value):
            return self.__class__( super(CappedInt, self).__floordiv__(value), self.maxValue, self.minValue )

        def __rshift__(self, value):
            return self.__class__( super(CappedInt, self).__rshift__(value), self.maxValue, self.minValue )

        def __lshift__(self, value):
            return self.__class__( super(CappedInt, self).__lshift__(value), self.maxValue, self.minValue )

        def __pow__(self, value):
            return self.__class__( super(CappedInt, self).__pow__(value), self.maxValue, self.minValue )

default lovePercent = CappedInt( 0, maxValue=100, minValue=0 )
default money = CappedInt( 0, minValue=0 )
default hateFactor = CappedInt( 0, maxValue=10, minValue=-10 )
default answer = CappedInt( 0, maxValue=41 )
 
  • Like
Reactions: drKlauz