import random
elements = {
"normal": {"strong_against": ["None"], "weak_against": ["None"]},
"fire": {"strong_against": ["earth", "ice"], "weak_against": ["water", "ice"]},
"water": {"strong_against": ["fire", "poison"], "weak_against": ["earth", "electric"]},
"earth": {"strong_against": ["water", "poison"], "weak_against": ["fire", "nature"]},
"holy": {"strong_against": ["dark"], "weak_against": ["dark"]},
"dark": {"strong_against": ["holy"], "weak_against": ["holy"]},
"ice": {"strong_against": ["fire"], "weak_against": ["fire"]},
"electric": {"strong_against": ["water"], "weak_against": ["earth"]},
"poison": {"strong_against": ["nature"], "weak_against": ["earth", "water"]},
"nature": {"strong_against": ["earth"], "weak_against": ["poison", "fire"]}
}
class armor:
def __init__(self, name, defence, element=None):
self.name = name
self.defence = defence
self.element = element
class weapon:
def __init__(self, name, damage, element=None):
self.name = name
self.damage = damage
self.element = element
class restore_spell:
def __init__(self, name, restore_power,cost):
self.name = name
self.restore_power = restore_power
self.cost = cost
class attack_spell:
def __init__(self, name, attack_spell_power, cost, element=None):
self.name = name
self.attack_spell_power = attack_spell_power
self.cost = cost
self.element = element
class status_effects:
pass
class Person:
def __init__(self,name,armor=None,weapon=None,attack_spell=None,restore_spell=None,debuff=None,buff=None,max_health = 100,health=None,max_mp=48,mp=None,strength=18,defe=12,dex=10,magic=20,magic_defe=12,luck=16,evasion=2,exp=0,lvl=1,skill_points=0,attack_accuracy=100,max_lvl=100, base_d=0, base_d_m=0):
self.name = name
self.max_health = max_health
self.health = health if health is not None else max_health
self.weapon = weapon
self.attack_spell = attack_spell
self.restore_spell = restore_spell
self.buff = buff
self.debuff = debuff
self.max_mp = max_mp
self.mp = mp if mp is not None else max_mp
self.strength = strength
self.defe = defe
self.armor = armor
self.dex = dex
self.magic = magic
self.magic_defe = magic_defe
self.luck = luck
self.evasion = evasion
self.exp = exp
self.lvl = lvl
self.skill_points = skill_points
self.attack_accuracy = attack_accuracy
self.evasion = evasion
self.max_lvl = max_lvl
self.base_d_m = base_d_m
def see_stats(self):
print("max health: ", self.max_health,"/ health: ", self.health)
print("max mp: ", self.max_mp,"/ mp: ", self.mp)
print("strength: ", self.strength)
print("defense: ", self.defe)
print("magic defense: ", self.magic_defe)
print("dexterity: ", self.dex )
print("luck: ", self.luck)
print("exp: ", self.exp)
print("lvl: ", self.lvl)
def see_gear(self):
print("weapon: ", self.weapon.name if self.weapon else "None")
print("armor: ", self.armor.name if self.armor else "None")
def restore_health(self):
if self.health < self.max_health and self.restore_spell and self.mp >= self.restore_spell.cost:
self.health = min(self.health + self.restore_spell.restore_power, self.max_health)
self.mp -= self.restore_spell.cost
print(f"{self.name} used {self.restore_spell.name} and restored health to {self.health}")
else:
print(f"{self.name} cannot use the restore spell.")
def calculate_base_d(self):
return (self.strength + (self.weapon.damage if self.weapon else 0)) * random.uniform(0.9375, 1.0625)
def calculate_base_d_m(self):
return (self.magic + (self.attack_spell.attack_spell_power if self.attack_spell else 0)) * random.uniform(0.9375, 1.0625)
def attack(self):
attack_type = input("What kind of attack do you want to do (magic/physical): ").lower()
if attack_type == "magic" or "m":
if self.attack_spell and self.mp >= self.attack_spell.cost:
self.mp -= self.attack_spell.cost
return self.calculate_base_d_m()
else:
print("Not enough MP to cast a spell or no spell equipped.")
return 0
elif attack_type == "physical" or "p":
return self.calculate_base_d()
else:
print("Please enter a valid attack type.")
return 0
def exp_to_next_lvl(self):
if 1 <= self.lvl <= 9:
return self.lvl * 100
elif 10 <= self.lvl <= 15:
return self.lvl * 200
else:
return self.lvl * 300
def gain_exp(self, exp):
self.exp += exp
while self.exp >= self.exp_to_next_lvl():
self.level_up()
def level_up(self):
self.exp -= self.exp_to_next_lvl
self.lvl += 1
self.skill_points += 5
if 0 <= self.lvl <= 10:
self.max_health += 75
self.mp += 10
elif 11 <= self.lvl <= 50:
self.max_health += 150
self.mp += 15
elif 51 <= self.lvl <= 99:
self.max_health +=250
self.mp += 25
else:
print("you are at max lvl")
print(f"Congratulations! You've reached level {self.lvl}")
def s_skill_p(self):
if self.skill_points >0:
x = input("which skill you want to incrase:\nstrength\ndefense\nmagic\nmagic_defense\ndexterity\nluck ").lower()
if x == 'strength':
self.strength += 1
self.skill_points -= 1
elif x == 'defense':
self.defe += 1
self.skill_points -= 1
elif x == 'magic':
self.magic += 1
self.skill_points -= 1
elif x == 'magic_defense':
self.magic_defe += 1
self.skill_points -= 1
elif x == 'dexterity':
self.dex += 1
self.skill_points -= 1
elif x == 'luck':
self.luck += 1
self.skill_points -= 1
else:
print("Please enter a valid skill")
else:
print("you dont have skill points ")
def is_dead(self):
return self.health <= 0
class Barbarian(Person):
pass
class Wizard(Person):
def __init__(self, name, max_health=None, health=None, max_mp=48, mp=None, magic=20, magic_defe=12, attack_spells=None):
super().__init__(name, max_health, health, max_mp, mp, magic=magic, magic_defe=magic_defe)
self.attack_spells = attack_spells if attack_spells is not None else []
class Monster(Person):
def __init__(self, name, max_health=100, health=None, max_mp=48, mp=None, magic=20, magic_defe=12, element=None, attack_spells=None):
super().__init__(name, max_health, health, max_mp, mp, magic, magic_defe, element, attack_spells)
self.element = element
self.attack_spells = attack_spells if attack_spells is not None else []
def attack_m(self):
if self.health > self.max_health * 0.5:
return self.calculate_base_d()
else:
return self.calculate_base_d_m()
def battle(player, monster):
while not player.is_dead() and not monster.is_dead():
print(f"{player.name}'s turn:")
player_turn = True
while player_turn:
action = input("What do you want to do? (attack/restore/stats/gear): ").lower()
if action == "attack" or action == "a":
damage = player.attack()
if player.weapon and player.weapon.element or player.attack_spell and player.attack_spell.element:
attack_element = player.weapon.element if player.weapon else player.attack_spell.element
if monster.element and attack_element in elements[monster.element]['weak_against']:
damage *= 1.5
elif monster.element and attack_element in elements[monster.element]['strong_against']:
damage *= 0.5
monster.health -= damage
print(f"{player.name} attacks {monster.name} for {damage:.2f} damage!")
if monster.is_dead():
player.gain_exp(monster.exp)
break
player_turn = False
elif action == "stats" or action == "s":
player.see_stats()
elif action == "gear" or action == "g":
player.see_gear()
elif action == "restore" or action == "r":
player.restore_health()
player_turn = False
else:
print("Please enter a valid action.")
if monster.is_dead():
break
print(f"{monster.name}'s turn:")
m_damage = monster.attack_m()
player.health -= m_damage
print(f"{monster.name} attacks {player.name} for {m_damage:.2f} damage!")
if player.is_dead():
break
cure = restore_spell("cure", 50, 10)
fireball = attack_spell("fireball", 30, 15, "fire")
thunder = attack_spell("thunder", 25, 12, "electric")
player_weapon = weapon("Sword", 10, "normal")
player = Person(name = "Hero", weapon=player_weapon, attack_spell=fireball, restore_spell=cure)
monster = Monster(name = "Goblin", element = "fire", max_health=250, health=250, max_mp=20, mp=20, magic=10, attack_spells=None)
monster.weapon = weapon("Claws", 5, "fire")
battle(player, monster)
Я пытаюсь сделать что-то вроде ролевой игры на питоне, чтобы хорошо понимать классы. из ниоткуда функция is_dead начинает вызывать эту ошибку ('<=' не поддерживается между экземплярами 'str' и 'int'). Как я могу улучшить свой код и решить проблему Ребята, помогите, пожалуйста, я новичок в Python.
Как я могу решить эту проблему
Ваши дочерние классы, наследуемые от класса Person (Варвар, Волшебник, Монстр), проблематичны, особенно в методах инициализации. Когда вы вызываете конструктор super, вы передаете аргументы (например, max_health, health и т. д.) в качестве позиционных аргументов, но вы ожидаете, что они будут вести себя как аргументы ключевого слова. Результат: броня равна max_health, оружие становится здоровьем и т. д. В конечном итоге вы передаете строку в качестве позиционного аргумента для фактического здоровья или max_health, что в конечном итоге сломается в is_dead, когда вы попытаетесь сравнить строку с целым числом.
Короче говоря, ваш класс Person' __init__ ожидает много позиционных аргументов, но вы не предоставляете ему достаточно аргументов/в правильном порядке в своих подклассах. Например, max_health — это восьмой позиционный аргумент __init__ вашего Person, поэтому вам нужно передать аргументы для всех остальных первых семи позиционных аргументов, прежде чем передавать max_health. Тот факт, что имя передаваемой вами переменной совпадает с именем параметра, не означает, что Python автоматически узнает, какой параметр вы намеревались назначить.






В сообщении об ошибке написано '<=' not supported between instances of 'str' and 'int'. Это означает, что вы использовали оператор <=, пытаясь сравнить строку и целое число. Ваша функция is_dead() имеет только одну строку, return self.health <= 0. Мы знаем, что 0 — целое число. Таким образом, в какой-то момент вы присваиваете строку атрибуту health человека.
Как уже упоминал Пол М., проблема заключается в вызове super() в вашем Monster классе.
super().__init__(name, max_health, health, max_mp, mp, magic, magic_defe, element, attack_spells)
Вам не хватает спецификаторов ключевых слов при вызове функции. Это должно выглядеть так:
super().__init__(name, max_health=max_health, health=health, max_mp=max_mp, mp=mp, magic=magic, magic_defe=magic_defe)
Python не проверяет имена переменных в области вызывающего объекта и не сопоставляет их с сигнатурой функции, вам необходимо указать имена. Опуская их, конструктор родительского класса получает аргументы по порядку. Это означает, что когда Monster инициализируется, ему присваиваются armor=max_health, weapon=health, attack_spell=max_mp и т. д.
Также вы передаете element и attack_spells в super(), но у Person нет этих атрибутов.
Та же проблема существует и для других подклассов Person.
И еще: для вашего elements я настоятельно рекомендую использовать strong_against: [] вместо strong_against: ["None"].
Посмотрите на эту строку кода:
super().__init__(name, max_health, health, max_mp, mp, magic, magic_defe, element, attack_spells)
И это:
def __init__(self, name, armor=None, weapon=None, attack_spell=None, restore_spell=None, debuff=None, buff=None,
max_health=100, health=None, max_mp=48, mp=None, strength=18, defe=12, dex=10, magic=20, magic_defe=12,
luck=16, evasion=2, exp=0, lvl=1, skill_points=0, attack_accuracy=100, max_lvl=100, base_d=0,
base_d_m=0):
В функции init Person health является девятым параметром (не считая self). Однако когда вы передаете значение, это третий параметр. То же самое и с max_health; на самом деле он получает значение element. Таким образом, ваши значения путаются, и в результате health становится строкой. Убедитесь, что вы передаете значения в одном и том же порядке или используете аргументы ключевых слов. Я бы рекомендовал использовать аргументы ключевых слов, чтобы сделать его менее запутанным.
super().__init__(name=name, max_health=max_health, health=health, max_mp=max_mp, mp=mp, magic=magic,
magic_defe=magic_defe)
Есть еще несколько вещей, на которые стоит обратить внимание. Все имена классов должны быть в PascalCase. Например: class armor должно быть class Armor. Также attack_type == 'magic' or 'm' — это ошибка. Поскольку 'm' не является пустой строкой, ее оценка True сделает все утверждение истинным, несмотря ни на что. Измените это на attack_type == 'magic' or attack_type == 'm'. Это касается и attack_type == 'physical' or 'p'.
другой синтаксис для проверки attack_type, который мне нравится использовать для CLI: attack_type in ('magic', 'm')
Добро пожаловать в Stack Overflow. Пожалуйста, включите полную ошибку трассировки, а также образец входных данных. Я заметил одну вещь:
if attack_type == "magic" or "m":не делает того, что вы думаете.