nickgermaine / python_text_battle

Simple rpg type text-based python battle script
103 stars 48 forks source link

'NoneType' object is not iterable #3

Open lekoook opened 7 years ago

lekoook commented 7 years ago

Hi Nick!

I am currently going through your python course and managed to follow this entire RPG section so far. However, it appears that this RPG battle script will occasionally produce TypeError: 'NoneType' object is not iterable. It points to spell, magic_dmg = choose_enemy_spell() on line 192 in main.py . After 2 hours of going through the entire script, I still cannot figure out the issue. What is wrong? It appears that the error occurs when the AI is trying to use a "white" spell. Looking forward to your reply! :)

JasperGeh commented 7 years ago

Yes, same for me. it has something to do with the line if self.mp < spell.cost or spell.type == "white" and pct > 50: in choose_enemy_spell()

henja commented 7 years ago

Hello,

This same thing is happening for me too. I've spent the past few hours trying to figure out whats causing it, but can't pin point it. I commented out or spell.type == "white" and pct > 50: and set up some print statements within the choose_enemy_spell() function and within the if enemy_choice section, but still can't tell whats causing the error. This is the first big Python tutorial that I've done, and I've really enjoyed it. I'm also enjoying trying to figure out what exactly is causing this error :)

Some more Googling has pointed me to Python's __iter__ method. So, it seems that its trying to run __iter__ (inherent within a for loop?) against "None" but I don't know what is being returned as "None"

Mattorix commented 7 years ago

I think I managed to fix this by adding return to make return self.choose_enemy_spell() however, it brings up another issue which I think is where if the enemy runs out of mp, it loops forever as there is no spell they can use.

mechengmaster commented 7 years ago

I had the same problem for the def choose_enemy_spell(self): function. @Mattorix , you were on the right lines with your return statement but then another error appeared. The problem appeared in the recursion when the enemy was told to pick again.

The code produced by Nick looks like this:

    def choose_enemy_spell(self):
        magic_choice = random.randrange(0, len(self.magic))
        spell = self.magic[magic_choice]
        magic_dmg = spell.generate_damage()

        pct = self.hp / self.maxhp * 100

        if self.mp < spell.cost or spell.type == "white" and pct > 50:
            self.choose_enemy_spell()
        else:
            return spell, magic_dmg

On line 187 (inside the if statement) the recursion occurs but it doesn't overwrite the variables spell or magic_dmg as there are out of scope within each recursion level so once I added in the return statement the "'NoneType' object is not iterable" error stopped but I noticed that Curaga was still passed through to main.py.

My code edit is as follows that seems to have done the trick:

    def choose_enemy_spell(self):
        magic_choice = random.randrange(0, len(self.magic))
        spell = self.magic[magic_choice]
        magic_dmg = spell.generate_damage()

        pct = self.hp / self.maxhp * 100

        if self.mp < spell.cost or spell.type == "white" and pct > 50:
            spell, magic_dmg = self.choose_enemy_spell()
            return spell, magic_dmg
        else:
            return spell, magic_dmg
iamvuppala commented 6 years ago

After this change, I got hit by Issue #2 But After fixing that, I'm hitting infinite loop in this function.