#!/usr/bin/env python3 import time class Unit: def __init__(self): self.title = 'Default Unit' self.hp = 100 self.hp_max = 100 self.effects = [] self.abilities = [] def add_effect(self, effect): if self._can_effect_be_added(effect): self.effects.append( {'effect': effect, 'lifetime': 0} ) def remove_effect_set(self, effect): self.effects.remove(effect) def _can_effect_be_added(self, effect): count = 0 for e in self.effects: if e['effect'].id == effect.id: count += 1 if count > effect.stags_max: return False return True class Mage(Unit): def __init__(self): Unit.__init__(self) self.mana = 100 self.mana_max = 100 class Player(Mage): def __init__(self): self.target = None self.mana = 400 self.mana_max = 400 class Ability: def __init__(self, caster): self.caster = caster self.title = 'Default Ability' self.mana_cost = 0 self.error_message = '' def cast(self) -> bool: raise Error('Cast method must be implemented!') class DaggerImpact(Ability): def __init__(self, caster): Ability.__init__(self, caster) self.title = 'Klingenstoß' self.mana_cost = 150 self.damage = 60 def cast(self) -> bool: if self.caster.target is None: self.error_message = 'Kein Ziel ausgewählt!' return False self.caster.target.hp -= self.damage self.caster.target.add_effect(EffectBleedOut()) return True class Ui: def show_enemies(self, enemies): raise Error('Method must be implemented!') class Cli(Ui): def __init__(self): Ui.__init__(self) def show_enemies(self, player, enemies): enemy_names = [] for e in enemies: name = e.title if e == player.target: name = '[' + name + ']' enemy_names.append(name) print() print('Vor dir stehen %s.' % (', '.join(enemy_names))) def make_choice(self, choices = [], callbacks = []): if len(choices) != len(callbacks): raise Error('Number of callbacks must equal the number of choices!') for i,c in enumerate(choices): print('[%d] %s' % (i + 1, c)) choice = 0 while choice == 0: choice = int(input('Triff deine Wahl: ')) if choice < 1 or choice > len(choices): choice = 0 else: callbacks[choice - 1]() return class Effect: def __init__(self): self.id = 0 self.title = 'Effect' self.stags_max = 1 self.lifetime = 0 def apply_to_unit(self, unit) -> str: raise Error('This abstract method must be implemented!') return 'This abstract method must be implemented!' class EffectBleedOut(Effect): def __init__(self): Effect.__init__(self) self.id = 1 self.title = 'Blutung' self.amount = 3 self.lifetime = 5 self.stags_max = 5 def apply_to_unit(self, unit): unit.hp -= self.amount class Fight: def __init__(self, ui, player): self.ui = ui self.player = player self.enemies = [] def add_enemy(self, enemy): self.enemies.append(enemy) def start(self): while len(self.enemies) > 0: self.ui.show_enemies(self.player, self.enemies) ui.make_choice( ['Gegner wählen', 'Fähigkeit wirken'], [self.choose_enemy, self.choose_ability] ) print('Du warst siegreich.') def choose_enemy(self): choices = [] callbacks = [] for e in self.enemies: choices.append(e.title) callbacks.append(lambda e=e: self.set_player_target(e)) ui.make_choice(choices, callbacks) def set_player_target(self, target): self.player.target = target print('%s ist jetzt dein Ziel.' % (target.title)) def choose_ability(self): names = [] callbacks = [] for a in self.player.abilities: names.append(a.title) callbacks.append(lambda a=a: self.cast_ability(a)) self.ui.make_choice(names, callbacks) def cast_ability(self, ability): print('Wirke %s.' % (ability.title)) ability.cast() if __name__ == '__main__': ui = Cli() player = Player() player.abilities = [ DaggerImpact(player) ] u = Unit() u.add_effect(EffectBleedOut()) dog = Unit() dog.title = 'Räudiger Hund' dog.hp = 20 dog.hp_max = 20 dragon = Unit() dragon.title = 'Feuerdrache' dragon.hp = 800 dragon.hp_max = 800 orc = Unit() orc.title = 'Dämlicher Ork' orc.hp = 350 orc.hp_max = 350 fight = Fight(ui, player) fight.add_enemy(dog) fight.add_enemy(dragon) fight.add_enemy(orc) fight.start() while u.hp > 0: to_be_removed = [] for e in u.effects: e['effect'].apply_to_unit(u) e['lifetime'] += 1 if e['lifetime'] == e['effect'].lifetime: to_be_removed.append(e) for r in to_be_removed: print(r['effect'].title, 'klingt ab.') u.remove_effect_set(r) if u.hp < 0: u.hp = 0 print(u.hp, end='') time.sleep(1)