Check for Winner
Hi Nick,
Great tutorial! I noticed something in the code which meant that it doesn't realise when all enemies or players have been killed. Hopefully below provides a solution for others (unless it is not the issue I thought it was, in which case, the below is an alternative way to do things)
We have hard coded:
# Check if battle is over
defeated_enemies = 0
defeated_players = 0
for enemy in enemies:
if enemy.get_hp() == 0:
defeated_enemies += 1
for player in players:
if player.get_hp() == 0:
defeated_players += 1
# Check if Player won
if defeated_enemies == 2:
print(bcolors.OKGREEN + "You win!" + bcolors.ENDC)
running = False
# Check if Enemy won
elif defeated_players == 2:
print(bcolors.FAIL + "Your enemies have defeated you!" + bcolors.ENDC)
running = False
which means that we need to kill 2 players or enemies (a small note is that we actually have 3 on each team) for the other team to win.
After each Person dies we've used the del enemies[enemy] or del players[player] (another small note: I think the second one should actually be del players[target]). This means the code above is never able to reach our hard coded limit as the number of "enemy in enemies" and "player in players" also reduces each time we use the del function. We also reset defeated_enemies = 0 defeated_players = 0 each time too.
I have made the following edits: First declare:
defeated_enemies = 0
defeated_players = 0
directly after instantiating People at the top of main.py
instead of
del enemies[enemies]
use
del enemies[enemies]
defeated_enemies += 1
and vice-versa for
del players[player]
I have deleted:
# Check if battle is over
defeated_enemies = 0
defeated_players = 0
for enemy in enemies:
if enemy.get_hp() == 0:
defeated_enemies += 1
for player in players:
if player.get_hp() == 0:
defeated_players += 1
and moved:
# Check if Enemy won
elif defeated_players == 2:
print(bcolors.FAIL + "Your enemies have defeated you!" + bcolors.ENDC)
running = False
to after the bottom of main.py after the enemy attack phase (but not included in the enemy attack phase)
The above seems to have fixed the issue but let me know if you think I've gone wrong anywhere.
Could you show me exactly what the code looks like after the edit is finished, I am having trouble applying the fix. Thank you in advanced
Hi, I have just pasted in my entire main.py file for you to look at. Apologies if there are a few other changes from Nick's original tutorial. I may have tweaked a few things and forgotten what I did.
from classes.game import Person, bcolours
from classes.magic import Spell
from classes.inventory import Item
import random
# Create Black Magic
fire = Spell("Fire", 25, 600, "black")
thunder = Spell("Thunder", 25, 600, "black")
blizzard = Spell("Blizzard", 25, 600, "black")
meteor = Spell("Meteor", 40, 1200, "black")
quake = Spell("Quake", 14, 140, "black")
# Create white magic
cure = Spell("Cure", 25, 620, "white")
cura = Spell("Cura", 32, 1500, "white")
curaga = Spell("Curaga", 50, 6000, "white")
#Creat some items
potion = Item("Potion", "potion", "Heals 50HP", 50)
hipotion = Item("Hi-Potion", "potion", "Heals 100HP", 100)
superpotion = Item("Super Potion", "potion", "Heals 500 HP", 500)
elixer = Item("Elixer", "elixer", "Fully restores HP/MP of one party member", 9999)
hielixer = Item("MegaElixer", "elixer", "Fully restores party's HP/MP", 9999)
grenade = Item("Grenade", "attack", "Deals 500 damage", 500)
player_spells = [fire, thunder, blizzard, meteor, cure, cura]
enemy_spells = [fire, meteor, curaga]
player_items = [{"item": potion, "quantity": 15},{"item": hipotion, "quantity": 5},
{"item": superpotion, "quantity": 5}, {"item": elixer, "quantity": 5},
{"item": hielixer, "quantity": 2}, {"item": grenade, "quantity": 5}]
#Instantiate People
player1 = Person("Valos:",3260, 132, 300, 34, player_spells, player_items)
player2 = Person("Nick :",4160, 188, 311, 34, player_spells, player_items)
player3 = Person("Robot:",3089, 174, 288, 34, player_spells, player_items)
enemy1 = Person("Imp1 :", 1250, 130, 560, 325, enemy_spells, [])
enemy2 = Person("Magus:",11200, 701, 525, 25, enemy_spells,[])
enemy3 = Person("Imp2 :", 1250, 130, 560, 325, enemy_spells, [])
players = [player1, player2, player3]
enemies = [enemy1, enemy2, enemy3]
defeated_enemies = 0
defeated_players = 0
running = True
i = 0
print (bcolours.HEADER + bcolours.BOLD + "AN ENEMY ATTACKS!" + bcolours.ENDC)
while running:
print("============================")
print("NAME HP MP")
for player in players:
player.get_stats()
print("\n")
for enemy in enemies:
enemy.get_enemy_stats()
for player in players:
player.choose_action()
choice = input(" Choose action:")
index = int(choice) - 1
if index == 0:
dmg = player.generate_damge()
enemy = player.choose_target(enemies)
enemies[enemy].take_damage(dmg)
print(bcolours.BOLD + player.name.replace(" ", "").replace(":", "") + " attacked " + enemies[enemy].name.replace(" ", "").replace(":", "") +
" for", dmg, "points of damage." + bcolours.ENDC)
if enemies[enemy].get_hp() == 0:
print(bcolours.OKGREEN + bcolours.BOLD + enemies[enemy].name.replace(" ", "").replace(":", "") + " has died!" + bcolours.ENDC)
del enemies[enemy]
defeated_enemies += 1
elif index == 1:
player.choose_magic()
magic_choice = int(input(" Choose magic:")) - 1
if magic_choice == -1:
continue
spell = player.magic[magic_choice]
magic_dmg = spell.generate_damage()
current_mp = player.get_mp()
if spell.cost > current_mp:
print(bcolours.FAIL + "\nNot enough MP\n" + bcolours.ENDC)
continue
player.reduce_mp(spell.cost)
if spell.type == "white":
player.heal(magic_dmg)
print(bcolours.OKBLUE + "\n" + spell.name + " heals for", str(magic_dmg), "HP." + bcolours.ENDC)
elif spell.type == "black":
enemy = player.choose_target(enemies)
enemies[enemy].take_damage(magic_dmg)
print(bcolours.OKBLUE + "\n" + spell.name + " deals", str(magic_dmg), "points of damage to " +
enemies[enemy].name.replace(" ", "").replace(":", "") + bcolours.ENDC)
if enemies[enemy].get_hp() == 0:
print(bcolours.OKGREEN + bcolours.BOLD + enemies[enemy].name.replace(" ", "").replace(":", "") +
" has died!" + bcolours.ENDC)
del enemies[enemy]
defeated_enemies += 1
elif index == 2:
player.choose_item()
item_choice = int(input(" Choose item:")) - 1
if item_choice == -1:
continue
item = player.items[item_choice]["item"]
if player.items[item_choice]["quantity"] == 0:
print(bcolours.FAIL + "\n" + "None left..." + bcolours.ENDC)
continue
player.items[item_choice]["quantity"] -= 1
if item.type == "potion":
player.heal(item.prop)
print(bcolours.OKGREEN + "\n" + item.name + " heals for", str(item.prop), " HP" + bcolours.ENDC)
elif item.type == "elixer":
if item.name == "MegaElixer":
for i in players:
i.hp = i.maxhp
i.mp = i.maxmp
else:
player.hp = player.maxhp
player.mp = player.maxmp
print(bcolours.OKGREEN + "\n" + item.name + " fully restores HP/MP" + bcolours.ENDC)
elif item.type == "attack":
enemy = player.choose_target(enemies)
enemies[enemy].take_damage(item.prop)
print(bcolours.FAIL + "\n" + item.name + " deals", str(item.prop), " points of damage to " +
enemies[enemy].name + bcolours.ENDC)
if enemies[enemy].get_hp() == 0:
print(bcolours.OKGREEN + bcolours.BOLD + enemies[enemy].name.replace(" ", "").replace(":", "") +
" has died!" + bcolours.ENDC)
del enemies[enemy]
defeated_enemies += 1
#Check is player has won
if defeated_enemies == 3:
print(bcolours.OKGREEN + "You win!" + bcolours.ENDC)
running = False
print("\n")
# Enemy attack phase
for enemy in enemies:
enemy_choice = random.randrange(0,2)
if enemy_choice == 0:
# Choose attack
target = random.randrange(0, len(players))
enemy_dmg = enemy.generate_damge()
players[target].take_damage(enemy_dmg)
print(bcolours.FAIL + bcolours.BOLD + enemy.name.replace(" ", "").replace(":", "") + " attacks " +
players[target].name.replace(" ", "").replace(":", "") + " for", enemy_dmg, bcolours.ENDC)
if players[target].get_hp() == 0:
print(bcolours.FAIL + bcolours.BOLD + players[target].name.replace(" ", "").replace(":", "") +
" has died!" + bcolours.ENDC)
del players[target]
defeated_players += 1
elif enemy_choice == 1:
spell, magic_dmg = enemy.choose_enemy_spell()
# magic_dmg = spell.generate_damage()
enemy.reduce_mp(spell.cost)
if spell.type == "white":
enemy.heal(magic_dmg)
print(bcolours.FAIL + spell.name + " heals " + enemy.name.replace(" ", "").replace(":", "") +
" for", str(magic_dmg), "HP." + bcolours.ENDC)
elif spell.type == "black":
target = random.randrange(0, len(players))
players[target].take_damage(magic_dmg)
print(bcolours.FAIL + bcolours.BOLD + enemy.name.replace(" ", "").replace(":","") + "'s " + spell.name +
" deals", str(magic_dmg), "points of damage to " +
players[target].name.replace(" ", "").replace(":","") + bcolours.ENDC)
if players[target].get_hp() == 0:
print(bcolours.FAIL + bcolours.BOLD + players[target].name.replace(" ", "").replace(":", "") +
" has died!" + bcolours.ENDC)
del players[target]
defeated_players += 1
#Check if Enemy won
if defeated_players == 3:
print(bcolours.FAIL + "Your enemies have defeated you!" + bcolours.ENDC)
running = False
Hopefully the above helps.
Hi mechengmaster,
I just wanted to add that I used a lot of your code to help me out on my code. I do have to add though that without the break statement after each check to see who won, the players would continue to do an action. For the enemy, there would be an error since they have no players to attack.
#Check if Enemy won
if defeated_players == 3:
print(bcolours.FAIL + "Your enemies have defeated you!" + bcolours.ENDC)
running = False
break
from classes.game import Person, bcolours from classes.magic import Spell from classes.inventory import Item import random
Create Black Magic
fire = Spell("Fire", 25, 600, "black") thunder = Spell("Thunder", 25, 600, "black") blizzard = Spell("Blizzard", 25, 600, "black") meteor = Spell("Meteor", 40, 1200, "black") quake = Spell("Quake", 14, 140, "black")
Create white magic
cure = Spell("Cure", 25, 620, "white") cura = Spell("Cura", 32, 1500, "white") curaga = Spell("Curaga", 50, 6000, "white")
#Creat some items potion = Item("Potion", "potion", "Heals 50HP", 50) hipotion = Item("Hi-Potion", "potion", "Heals 100HP", 100) superpotion = Item("Super Potion", "potion", "Heals 500 HP", 500) elixer = Item("Elixer", "elixer", "Fully restores HP/MP of one party member", 9999) hielixer = Item("MegaElixer", "elixer", "Fully restores party's HP/MP", 9999)
grenade = Item("Grenade", "attack", "Deals 500 damage", 500)
player_spells = [fire, thunder, blizzard, meteor, cure, cura] enemy_spells = [fire, meteor, curaga] player_items = [{"item": potion, "quantity": 15},{"item": hipotion, "quantity": 5}, {"item": superpotion, "quantity": 5}, {"item": elixer, "quantity": 5}, {"item": hielixer, "quantity": 2}, {"item": grenade, "quantity": 5}]
#Instantiate People player1 = Person("Valos:",3260, 132, 300, 34, player_spells, player_items) player2 = Person("Nick :",4160, 188, 311, 34, player_spells, player_items) player3 = Person("Robot:",3089, 174, 288, 34, player_spells, player_items)
enemy1 = Person("Imp1 :", 1250, 130, 560, 325, enemy_spells, []) enemy2 = Person("Magus:",11200, 701, 525, 25, enemy_spells,[]) enemy3 = Person("Imp2 :", 1250, 130, 560, 325, enemy_spells, [])
players = [player1, player2, player3] enemies = [enemy1, enemy2, enemy3]
defeated_enemies = 0 defeated_players = 0
running = True i = 0
print (bcolours.HEADER + bcolours.BOLD + "AN ENEMY ATTACKS!" + bcolours.ENDC)
while running: print("============================")
print("NAME HP MP")
for player in players:
player.get_stats()
print("\n")
for enemy in enemies:
enemy.get_enemy_stats()
for player in players:
player.choose_action()
choice = input(" Choose action:")
index = int(choice) - 1
if index == 0:
dmg = player.generate_damge()
enemy = player.choose_target(enemies)
enemies[enemy].take_damage(dmg)
print(bcolours.BOLD + player.name.replace(" ", "").replace(":", "") + " attacked " + enemies[enemy].name.replace(" ", "").replace(":", "") +
" for", dmg, "points of damage." + bcolours.ENDC)
if enemies[enemy].get_hp() == 0:
print(bcolours.OKGREEN + bcolours.BOLD + enemies[enemy].name.replace(" ", "").replace(":", "") + " has died!" + bcolours.ENDC)
del enemies[enemy]
defeated_enemies += 1
elif index == 1:
player.choose_magic()
magic_choice = int(input(" Choose magic:")) - 1
if magic_choice == -1:
continue
spell = player.magic[magic_choice]
magic_dmg = spell.generate_damage()
current_mp = player.get_mp()
if spell.cost > current_mp:
print(bcolours.FAIL + "\nNot enough MP\n" + bcolours.ENDC)
continue
player.reduce_mp(spell.cost)
if spell.type == "white":
player.heal(magic_dmg)
print(bcolours.OKBLUE + "\n" + spell.name + " heals for", str(magic_dmg), "HP." + bcolours.ENDC)
elif spell.type == "black":
enemy = player.choose_target(enemies)
enemies[enemy].take_damage(magic_dmg)
print(bcolours.OKBLUE + "\n" + spell.name + " deals", str(magic_dmg), "points of damage to " +
enemies[enemy].name.replace(" ", "").replace(":", "") + bcolours.ENDC)
if enemies[enemy].get_hp() == 0:
print(bcolours.OKGREEN + bcolours.BOLD + enemies[enemy].name.replace(" ", "").replace(":", "") +
" has died!" + bcolours.ENDC)
del enemies[enemy]
defeated_enemies += 1
elif index == 2:
player.choose_item()
item_choice = int(input(" Choose item:")) - 1
if item_choice == -1:
continue
item = player.items[item_choice]["item"]
if player.items[item_choice]["quantity"] == 0:
print(bcolours.FAIL + "\n" + "None left..." + bcolours.ENDC)
continue
player.items[item_choice]["quantity"] -= 1
if item.type == "potion":
player.heal(item.prop)
print(bcolours.OKGREEN + "\n" + item.name + " heals for", str(item.prop), " HP" + bcolours.ENDC)
elif item.type == "elixer":
if item.name == "MegaElixer":
for i in players:
i.hp = i.maxhp
i.mp = i.maxmp
else:
player.hp = player.maxhp
player.mp = player.maxmp
print(bcolours.OKGREEN + "\n" + item.name + " fully restores HP/MP" + bcolours.ENDC)
elif item.type == "attack":
enemy = player.choose_target(enemies)
enemies[enemy].take_damage(item.prop)
print(bcolours.FAIL + "\n" + item.name + " deals", str(item.prop), " points of damage to " +
enemies[enemy].name + bcolours.ENDC)
if enemies[enemy].get_hp() == 0:
print(bcolours.OKGREEN + bcolours.BOLD + enemies[enemy].name.replace(" ", "").replace(":", "") +
" has died!" + bcolours.ENDC)
del enemies[enemy]
defeated_enemies += 1
#Check is player has won
if defeated_enemies == 3:
print(bcolours.OKGREEN + "You win!" + bcolours.ENDC)
running = False
break
print("\n")
# Enemy attack phase
for enemy in enemies:
enemy_choice = random.randrange(0,2)
if enemy_choice == 0:
# Choose attack
target = random.randrange(0, len(players))
enemy_dmg = enemy.generate_damge()
players[target].take_damage(enemy_dmg)
print(bcolours.FAIL + bcolours.BOLD + enemy.name.replace(" ", "").replace(":", "") + " attacks " +
players[target].name.replace(" ", "").replace(":", "") + " for", enemy_dmg, bcolours.ENDC)
if players[target].get_hp() == 0:
print(bcolours.FAIL + bcolours.BOLD + players[target].name.replace(" ", "").replace(":", "") +
" has died!" + bcolours.ENDC)
del players[target]
defeated_players += 1
elif enemy_choice == 1:
spell, magic_dmg = enemy.choose_enemy_spell()
# magic_dmg = spell.generate_damage()
enemy.reduce_mp(spell.cost)
if spell.type == "white":
enemy.heal(magic_dmg)
print(bcolours.FAIL + spell.name + " heals " + enemy.name.replace(" ", "").replace(":", "") +
" for", str(magic_dmg), "HP." + bcolours.ENDC)
elif spell.type == "black":
target = random.randrange(0, len(players))
players[target].take_damage(magic_dmg)
print(bcolours.FAIL + bcolours.BOLD + enemy.name.replace(" ", "").replace(":","") + "'s " + spell.name +
" deals", str(magic_dmg), "points of damage to " +
players[target].name.replace(" ", "").replace(":","") + bcolours.ENDC)
if players[target].get_hp() == 0:
print(bcolours.FAIL + bcolours.BOLD + players[target].name.replace(" ", "").replace(":", "") +
" has died!" + bcolours.ENDC)
del players[target]
defeated_players += 1
#Check if Enemy won
if defeated_players == 3:
print(bcolours.FAIL + "Your enemies have defeated you!" + bcolours.ENDC)
running = False
break
i had modified my codes as you have suggested but still its not working properly.... it is showing the following error
Traceback (most recent call last):
File "main.py", line 254, in