• The weapons, list index out of range, 119

 

Hello! When trying to complete this mission https://py.checkio.org/mission/the-weapons/solve/ im getting an error, "IndexError: list index out of range, , 119" i have no idea why it happens, my code works fine on my machine, and when i press "Run" in the editor on the site. I will be very thankful for any advice why this is happening. import math

def fight(unit_1, unit_2):
    while True:
        damage = (unit_1.attack - unit_2.defense)
        if damage < 0:
            damage = 0
        unit_2.health -= damage
        if unit_2.health <= 0:
            unit_2.is_alive = False
            return True
        if unit_1.name == 'vampire':
            unit_1.health += math.floor(damage * unit_1.vampirism)

        damage = (unit_2.attack - unit_1.defense)
        if damage < 0:
            damage = 0
        unit_1.health -= damage
        if unit_1.health <= 0:
            unit_1.is_alive = False
            return False

        if unit_2.name == 'vampire':
            unit_2.health += math.floor(damage * unit_2.vampirism)


def fight2(army1, army2):
    i = max(len(army1.units), len(army2.units))
    try:
        for j in range(i):
            # print(j)
            while army1.units[j].health >= 0 and army2.units[j].health >= 0:
                # print(army2.units[j].name, ' ', army2.units[j].health, 'vs', army1.units[j].health, ' ', army1.units[j].name)
                damage = (army1.units[j].attack - army2.units[j].defense)
                if damage < 0:
                    damage = 0
                army2.units[j].health -= damage
                if army1.units[j].name == 'vampire':
                    army1.units[j].health += math.floor(damage * army1.units[j].vampirism)
                if army2.units[j].health <= 0:
                    # print('unit dead 2', j)
                    break
                damage = (army2.units[j].attack - army1.units[j].defense)
                army1.units[j].health -= damage
                if damage < 0:
                    damage = 0
                if army2.units[j].name == 'vampire':
                    army2.units[j].health += math.floor(damage * army2.units[j].vampirism)
                if army1.units[j].health <= 0:
                    # print('unit dead 1', j)
                    break
    except:
        print(' ')


def clear_ranks(army_1, army_2):
    for unit1 in army_1.units[:]:
        if unit1.health <= 0:
            # print(unit1.health)
            army_1.units.pop(army_1.units.index(unit1))
    for unit2 in army_2.units[:]:
        if unit2.health <= 0:
            # print(unit2.health)
            army_2.units.pop(army_2.units.index(unit2))
    return army_1, army_2


class Warrior():
    def __init__(self):
        self.name = 'warrior'
        self.is_alive = True
        self.health = 50
        self.maxhealth = self.health
        self.attack = 5
        self.defense = 0
        self.vampirism = 0
        self.heal_power = 0

    def equip_weapon(self, weapon):
        self.health = max(self.health + weapon.health, 0)
        self.maxhealth = self.health
        if self.attack > 0:
            self.attack = max(self.attack + weapon.attack, 0)
        if self.defense > 0:
            self.defense = max(self.defense + weapon.defense, 0)
        if self.vampirism > 0:
            self.vampirism = max(self.vampirism + weapon.vampirism, 0)
        if self.heal_power > 0:
            self.heal_power = max(self.heal_power + weapon.heal_power, 0)


class Rookie(Warrior):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.health = 50
        self.maxhealth = self.health
        self.attack = 1
        self.name = 'rookie'
        self.is_alive = True
        self.defense = 0
        self.vampirism = 0
        self.heal_power = 0


class Knight(Warrior):
    def __init__(self):
        self.name = 'knight'
        self.is_alive = True
        self.attack = 7
        self.health = 50
        self.maxhealth = self.health
        self.defense = 0
        self.vampirism = 0
        self.heal_power = 0


class Defender(Warrior):
    def __init__(self):
        self.name = 'defender'
        self.is_alive = True
        self.attack = 3
        self.health = 60
        self.maxhealth = self.health
        self.defense = 2
        self.vampirism = 0
        self.heal_power = 0


class Vampire(Warrior):
    def __init__(self):
        self.name = 'vampire'
        self.is_alive = True
        self.attack = 4
        self.health = 40
        self.maxhealth = self.health
        self.defense = 0
        self.vampirism = 0.5
        self.heal_power = 0


class Lancer(Warrior):
    def __init__(self):
        self.name = 'lancer'
        self.is_alive = True
        self.attack = 6
        self.health = 50
        self.maxhealth = self.health
        self.defense = 0
        self.vampirism = 0
        self.heal_power = 0


class Healer(Warrior):
    def __init__(self):
        self.name = 'healer'
        self.is_alive = True
        self.attack = 0
        self.health = 60
        self.maxhealth = self.health
        self.defense = 0
        self.vampirism = 0
        self.heal_power = 2

    def heal(self, unit):
        unit.health += self.heal_power
        if unit.health > unit.maxhealth:
            unit.health = unit.maxhealth


class Weapon():
    def __init__(self, health, attack, defense, vampirism, heal_power):
        self.health = health
        self.attack = attack
        self.defense = defense
        self.vampirism = vampirism
        self.heal_power = heal_power


class Sword(Weapon):
    def __init__(self):
        self.health = 5
        self.attack = 2
        self.defense = 0
        self.vampirism = 0
        self.heal_power = 0


class Shield(Weapon):
    def __init__(self):
        self.health = 20
        self.attack = -1
        self.defense = 2
        self.vampirism = 0
        self.heal_power = 0


class GreatAxe(Weapon):
    def __init__(self):
        self.health = -15
        self.attack = 5
        self.defense = -2
        self.vampirism = 0.1
        self.heal_power = 0


class Katana(Weapon):
    def __init__(self):
        self.health = -20
        self.attack = 6
        self.defense = -5
        self.vampirism = 0.5
        self.heal_power = 0


class MagicWand(Weapon):
    def __init__(self):
        self.health = 30
        self.attack = 3
        self.defense = 0
        self.vampirism = 0
        self.heal_power = 3


class Army():
    def __init__(self):
        self.units = []

    def add_units(self, unit, num):
        if unit == Knight:
            for i in range(num):
                self.units.append(Knight())
        if unit == Warrior:
            for i in range(num):
                self.units.append(Warrior())
        if unit == Defender:
            for i in range(num):
                self.units.append(Defender())
        if unit == Vampire:
            for i in range(num):
                self.units.append(Vampire())
        if unit == Lancer:
            for i in range(num):
                self.units.append(Lancer())
        if unit == Healer:
            for i in range(num):
                self.units.append(Healer())
        if unit == Rookie:
            for i in range(num):
                self.units.append(Rookie())

    def army_comp(self):
        for i in self.units:
            print(i)


class Battle():
    def fight(self, army1, army2):
        while len(army1.units) > 0 and len(army2.units) > 0:
            damage = (army1.units[0].attack - army2.units[0].defense)
            army2.units[0].health -= damage
            if len(army2.units) > 1:
                if army1.units[0].name == 'lancer':
                    dmg = army1.units[0].attack - army2.units[1].defense
                    army2.units[1].health -= dmg / 2
            if army2.units[0].health <= 0:
                army2.units.pop(0)
                if army2.units == []:
                    return True
                continue
            if army1.units[0].name == 'vampire':
                army1.units[0].health += (damage * army1.units[0].vampirism)
            if len(army2.units) > 1:
                if army2.units[1].name == 'healer':
                    army2.units[1].heal(army2.units[0])
            damage = (army2.units[0].attack - army1.units[0].defense)
            army1.units[0].health -= damage
            if len(army1.units) > 1:
                if army2.units[0].name == 'lancer':
                    dmg = army2.units[0].attack - army1.units[1].defense
                    army1.units[1].health -= dmg / 2
            if army1.units[0].health <= 0:
                army1.units.pop(0)
                if army1.units == []:
                    return False
                continue
            if army2.units[0].name == 'vampire':
                army2.units[0].health += (damage * army2.units[0].vampirism)
            if len(army1.units) > 1:
                if army1.units[1].name == 'healer':
                    army1.units[1].heal(army1.units[0])

    def straight_fight(self, army1, army2):
        while len(army1.units) > 0 and len(army2.units) > 0:
            fight2(army1, army2)
            clear_ranks(army1, army2)
            if army1.units == []:
                return False
            elif army2.units == []:
                return True

Error happens with these test values:

weapon_1 = Katana()
weapon_2 = Shield()
my_army = Army()
my_army.add_units(Vampire, 2)
my_army.add_units(Rookie, 2)
enemy_army = Army()
enemy_army.add_units(Warrior, 1)
enemy_army.add_units(Defender, 2)
my_army.units[0].equip_weapon(weapon_1)
my_army.units[1].equip_weapon(weapon_1)
my_army.units[2].equip_weapon(weapon_2)
enemy_army.units[0].equip_weapon(weapon_1)
enemy_army.units[1].equip_weapon(weapon_2)
enemy_army.units[2].equip_weapon(weapon_2)
battle = Battle()
battle.straight_fight(my_army, enemy_army)

Edit: Code pasted

11