Need Help With Lists In Python

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
Nero
Veteran
Posts: 248
Joined: Tue Aug 09, 2016 2:59 pm
Contact:

Need Help With Lists In Python

#1 Post by Nero »

I will be quick you will understand my problem better if you run this code as I explained it detailed in game script.

Now I will try to explain it here what was on my mind when I tried to code this. So basically I have created 2 Players which are inside of the list players=[bob, jack] and 1 Ailment effect (Poison) which has duration of 5 turns and deals 25 points of damage each turn. Inside Players class I created a status list which would hold all ailments that are inflicted on players.

When we insert poison variable into status list of a player we get a text that pops up in screen and tells us the name and the duration of current ailment(Poison).
Since this is turn based game I run the function that will run each time on next players turn named next_turn() which will decrease the poison duration on current player by -1.

Problem starts here:
If we have 1 player this works very nicely however if we have 2 players that gets poisoned in same time they will share the same duration. So if Bob got poisoned for 1 turn his duration counter will show number 4 but if we poison Jack next turn his poison duration will also show 4 instead of 5 which is what I don't want. Correct way of this working would actually be Bob duration = 4 and Jack duration = 5 as 5 is default duration value of poison. (Please run my code to have better understanding if I don't make sense here.)

The second problem:
Even if we ignore first problem there is second problem. If Bob and Jack are both poisoned in same time this will somehow mess up (next_turn function) now every turn duration will be decreased by -2 . If we add 3 players duration will be decreased by -3, 4 players duration decreases by -4 you get the idea. I found some half solution to this problem by using "deepcopy" but this messes up with my code in future and as I heared is rarely used when coding making it pretty bad choice and I'm interested in making my code as compact and proffessional as possible.

Any suggestion is welcome even complete code rework is okay with me I just want to understand what I'm doing wrong here where did I think the wrong way when doing this.

Or maybe explain me the way you would do the same exact thing?

Code:

Code: Select all

screen test_screen():
    vbox:
        xalign 0.100
        yalign 0.100
        for p in players: #for every member in players list
            if len(p.status) > 0: #if their status list is not empty
                vbox:
                    for s in p.status: #for each status change in their status list
                        if s.duration > 0:
                            text "{}: Ailment Duration: {}".format(p.name,s.duration)


init python:
    def next_turn(): # This function runs every turn means that Ailment duration should be decreased by -1 each turn
        for p in players: #for every player in players list
            for s in p.status: #for each status change in their status list
                if s.duration <= 0:
                    s.duration = 0
                    p.status.remove(s)
                else:
                    s.duration -= 1

init python:
    class Ailment(object): # We defined Ailments here in this case Poison only
        def __init__(self,name,damage,duration):
            self.name = name
            self.damage = damage
            self.duration = duration #Duration of ailment this must be different for each player (how many turns)

    class Poison(Ailment):
        def __init__(self):
            self.name = "Poison"
            self.damage = 25
            self.duration = 5
    poison = Poison()


init python:
    class Player(object): # We defined players in here
        def __init__(self,name,hp,mp):
            self.name = name
            self.hp = hp
            self.mp = mp
            self.status = [] # used to hold the ailment of affected player

        def player_gets_poisoned(self, ailment): # We run this method when we give ailment to a player
            self.status.append(ailment)

        def THIS_WORKS_BUT_CREATES_OTHER_PROBLEMS(self, ailment): # This is not active in the code just an example..
            from copy import deepcopy #import deepcopy so we can append a new object with the same properties
            #This is so the same status is not added twice, just in case
            for s in self.status:
                if ailment.name == s.name:
                    return
            self.status.append(deepcopy(ailment))

    class Bob(Player):
        def __init__(self):
            self.name = "Bob"
            self.hp = 100
            self.mp = 10
            self.status = []
    bob = Bob()

    class Jack(Player):
        def __init__(self):
            self.name = "Jack"
            self.hp = 200
            self.mp = 10
            self.status = []
    jack = Jack()




label start:
    show screen test_screen
    $ players = [bob, jack]
    "Game starts"
    $ bob.player_gets_poisoned(poison)
    "Bob got poisoned!"
    $ next_turn()
    "Next turn happens right now this works nicely lets pretend Bob took damage and now is Poison duration decreased by -1 making it to 4."
    "Now lets poison second player Jack."
    $ jack.player_gets_poisoned(poison)
    "Jack is poisoned now!"
    "Error number 1: Poison duration is same as duration of Bob! Instead what should happen right now is that Bob Poison duration should be 4 and Jack duration should be 5."
    "So when next turn happens Bob Poison duration should be = 3, Jack Poison duration should be  = 4"
    $ next_turn()
    "Next turn happens right now!"
    "Error number 2: Poison duration is now decreased by -2! Which is not what we want."
    "Question is how do I run this the correct way any suggestion is welcome. Even a full code rework is fine as long as I learn how this interactions work with each other."
    "So each turn ailment duration should be decreased by -1 and when another player gets ailment the duration on this player should be reset to a default value of duration which is in this case 5. like shown in example above."
    "Note that I tried to use deepcopy but this method interfere with my code in wrong way making me unable to change ailment duration the way I want it... Example of this method is shown in code (THIS_WORKS_BUT_CREATES_OTHER_PROBLEMS)"

User avatar
Alex
Lemma-Class Veteran
Posts: 3094
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: Need Help With Lists In Python

#2 Post by Alex »

Instead of

Code: Select all

$ bob.player_gets_poisoned(poison)
try

Code: Select all

$ bob.player_gets_poisoned(Poison())

Nero
Veteran
Posts: 248
Joined: Tue Aug 09, 2016 2:59 pm
Contact:

Re: Need Help With Lists In Python

#3 Post by Nero »

Awesome thanks didn't know you could use class directly like that I thought I always need to create a variable for it to be used.

Since you used object like that so is there a way object can be used in text renpy without needing to define variable?
What i mean is this is how you do it by defining the variable:

Code: Select all

init python:
    class Poison(Ailment):
        def __init__(self):
            self.name = "Poison"
            self.damage = 25
            self.duration = 5
    poison = Poison()
    
label start:    
    "Game starts"
    "[poison.name]"
Can this be done something like this: (I know this wont work but you get the idea about my question)

Code: Select all

"[Poison().name]"

Post Reply

Who is online

Users browsing this forum: Google [Bot], Ocelot, voluorem