Как сделать эффект нарастания в экземпляре класса?

Подскажите, пожалуйста, как сделать так, чтобы при вызове berserk1 = Berserk(berserk), berserk1.get_stats() имел так сказать эффект двойной силы, по сравнению с berserk.get_stats()? т.е. как в компьютерных играх, когда, к примеру накладывают какой-то положительный эффект на персонажа повторно, то эффекты стакаются. Заранее спасибо!

from abc import ABC, abstractmethod


class Hero:
    def __init__(self):
        self.positive_effects = []
        self.negative_effects = []

        self.stats = {
            "HP": 128,
            "MP": 42,
            "SP": 100,

            "Strength": 15,
            "Perception": 4,
            "Endurance": 8,
            "Charisma": 2,
            "Intelligence": 3,
            "Agility": 8,
            "Luck": 1
        }

    def get_positive_effects(self):
        return self.positive_effects.copy()

    def get_negative_effects(self):
        return self.negative_effects.copy()

    def get_stats(self):
        return self.stats.copy()


class AbstractPositive(Hero, ABC):
    def __init__(self, base):
        self.base = base
        super().__init__()



class Berserk(AbstractPositive):
    def get_stats(self):
        self.base.stats["Strength"] += 7
        self.base.stats["Endurance"] += 7
        self.base.stats["Agility"] += 7
        self.base.stats["Luck"] += 7
        self.base.stats['Perception'] -= 3
        self.base.stats["Charisma"] -= 3
        self.base.stats['Intelligence'] -= 3
        self.base.stats['HP'] += 50

        return self.base.stats.copy()

        hero = Hero()
        berserk = Berserk(hero)
        berserk1 = Berserk(berserk)
        print(berserk1.get_stats())
        print(berserk1.get_positive_effects())

Ответы (1 шт):

Автор решения: mrEvgenX

В python все объект, можно даже просто функции одинаковой сигнатуры использовать в качестве эффектов, накапливать сами функции в экземпляре класса, а наружу давать геттер свойств, который эффекты применяет.

Для самого начала должно сработать, а развивать эту схему можно бесконечно. Здесь пригодится паттерн проектирования "Команда", как например здесь можно найти подробности https://github.com/faif/python-patterns/blob/master/patterns/behavioral/command.py.

class Hero:

    def __init__(self):
        self._stats = {
            'HP': 100,
            'strength': 10,
            'speed': 10,
            'intelligence': 10
        }
        self._effects = []
    
    def cast_spell(self, target, effect):
        target._effects.append(effect)
    
    def get_stats(self):
        stats = self._stats.copy()
        for effect in self._effects:
            stats = effect(stats)
        return stats


def berserk_effect(stats):
    result_stats = stats.copy()
    result_stats['HP'] = stats['HP'] + 25
    result_stats['strength'] = stats['strength'] + 5
    result_stats['speed'] = stats['speed'] + 5
    result_stats['intelligence'] = stats['intelligence'] - 5
    return result_stats


if __name__ == '__main__':
    hero = Hero()
    print(hero.get_stats())
    hero.cast_spell(hero, berserk_effect)
    print(hero.get_stats())
    hero.cast_spell(hero, berserk_effect)
    print(hero.get_stats())
    hero.cast_spell(hero, berserk_effect)
    print(hero.get_stats())

В результате будет такое:

{'HP': 100, 'strength': 10, 'speed': 10, 'intelligence': 10}
{'HP': 125, 'strength': 15, 'speed': 15, 'intelligence': 5}
{'HP': 150, 'strength': 20, 'speed': 20, 'intelligence': 0}
{'HP': 175, 'strength': 25, 'speed': 25, 'intelligence': -5}

Естественно понадобится понятие книги заклинаний, иначе любой герой умеет накладывать любой эффект с рождения.

→ Ссылка