ctrlmaniac
ctrlmaniac

Reputation: 444

How to make loops start, break and start over again according to a variable?

I am trying to make a module that handle the health of a user.

If self.hearts are 0 the user dies, and it will print that out. But if the user is not dead and self.hearts are less than 10, the user will be healed every 20 seconds.

With this code below, the monitor function will only heal the user and won't print that the user is dead (especially when it happens). What am I doing wrong?

import threading

class Health(object):
    def __init__(self):
        self.hearts = 10

    def monitor(self):
        if self.hearts <= 10 and self.hearts > 0:
            def heal():
                threading.Timer(20.0, heal).start()
                if self.hearts < 10 and self.hearts > 0:
                    self.hearts += 1
                    print '+1 heart! :D'
                    print 'hearts %d' % self.hearts
            heal()
        elif self.hearts < 1:
            print 'You are dead'
            quit()

    def add(self, amount):
        if self.hearts < 10:
            self.hearts += amount
            print '+{} hearts! :D'.format(amount)
        else:
            print 'You are full of hearts'


    def remove(self, amount):
        self.hearts -= amount
        print '-{} hearts! :\'('.format(amount)


    def health(self):
        print 'Hearts: ', self.hearts


me = Health()
me.monitor()

I feel that I need I while loop but I don't know how to code it in the right way. I wish I knew how to code a loop that starts, breaks and starts over again according to self.hearts. This loop must always wait for changes.

How can I make the module prompts that the user is dead when it actually happens?

When I run it on the python console everything work except the 'You are dead' prompt:

>>> me.remove(5)
-5 hearts! :'(
>>> +1 heart! :D
hearts 6
me.remove(10)
-10 hearts! :'(
>>> 

Upvotes: 0

Views: 270

Answers (2)

junnytony
junnytony

Reputation: 3515

You should save your timer object so you can call cancel() on it when self.hearts goes to zero.

So for example (in heal()):

self.healing_timer = threading.Timer(20.0, self.heal).start()

and in remove():

def remove(self, amount):
    self.hearts -= amount
    print '-{} hearts! :\'('.format(amount)
    if self.hearts < 1:
        self.healing_timer.cancel()
        print 'You are dead'

Upvotes: 1

intika
intika

Reputation: 9712

Try this version of your code

i just noticed that you don't test for death with the timer try this version

def monitor(self):
    if self.hearts <= 20 and self.hearts > 0:
        def heal():
            if self.hearts < 10 and self.hearts > 0:
                self.hearts += 1
                print '+1 heart! :D'
                print 'hearts %d' % self.hearts
                threading.Timer(10.0, heal).start()
            elif self.hearts < 1:
                quit()
        heal()

you also need to make a test for death on delete to avoid waiting next timer check

def remove(self, amount):
        self.hearts -= amount
        print '-{} hearts! :\'('.format(amount)
        if self.hearts < 1:
            print 'You are dead'

Edited to avoid code repetition

Upvotes: 2

Related Questions