diff --git a/cheaprpg.py b/cheaprpg.py index 75af97e..3ddc2f1 100755 --- a/cheaprpg.py +++ b/cheaprpg.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 import time +import random +import sys +import subprocess class Unit: @@ -8,6 +11,8 @@ class Unit: self.title = 'Default Unit' self.hp = 100 self.hp_max = 100 + self.damage_min = 10 + self.damage_max = 15 self.effects = [] self.abilities = [] @@ -17,6 +22,12 @@ class Unit: {'effect': effect, 'lifetime': 0} ) + def add_damage(self, damage): + self.hp -= damage + + if self.hp < 0: + self.hp = 0 + def remove_effect_set(self, effect): self.effects.remove(effect) @@ -42,6 +53,7 @@ class Mage(Unit): class Player(Mage): def __init__(self): + Mage.__init__(self) self.target = None self.mana = 400 self.mana_max = 400 @@ -55,7 +67,7 @@ class Ability: self.error_message = '' def cast(self) -> bool: - raise Error('Cast method must be implemented!') + raise Exception('Cast method must be implemented!') class DaggerImpact(Ability): @@ -78,34 +90,70 @@ class DaggerImpact(Ability): class Ui: def show_enemies(self, enemies): - raise Error('Method must be implemented!') + raise Exception('Method must be implemented!') class Cli(Ui): def __init__(self): Ui.__init__(self) + def clear_screen(self): + if sys.platform == 'win32': + subprocess.call(['cls']) + else: + subprocess.call(['clear']) + def show_enemies(self, player, enemies): - enemy_names = [] + print() + print('Vor dir stehen:') for e in enemies: - name = e.title + name = '\t%s (%d/%d)' % (e.title, e.hp, e.hp_max) if e == player.target: - name = '[' + name + ']' + name = ' >' + name - enemy_names.append(name) + print(name) + + def show_message_board(self, *lines): + ornament = '-=W=-' + width = len(ornament) + 2 + + for l in lines: + length = len(l) + + if length > width: + width = length + + if width % 2 == 0: + width += 1 + + side = int((width - len(ornament) + 2) / 2) print() - print('Vor dir stehen %s.' % (', '.join(enemy_names))) + print('o' + ('-' * side) + ornament + ('-' * side) + 'o') + + for l in lines: + print('| ' + l.ljust(width, ' ') + ' |') + + print('o' + ('-' * (width + 2)) + 'o') + + def show_player_status(self, player): + self.show_message_board( + 'HP: %d/%d Mana: %d/%d' % (player.hp, player.hp_max, player.mana, player.mana_max) + ) def make_choice(self, choices = [], callbacks = []): if len(choices) != len(callbacks): - raise Error('Number of callbacks must equal the number of choices!') + raise Exception('Number of callbacks must equal the number of choices!') + + print() for i,c in enumerate(choices): print('[%d] %s' % (i + 1, c)) + print() + choice = 0 while choice == 0: @@ -127,7 +175,7 @@ class Effect: self.lifetime = 0 def apply_to_unit(self, unit) -> str: - raise Error('This abstract method must be implemented!') + raise Exception('This abstract method must be implemented!') return 'This abstract method must be implemented!' @@ -150,27 +198,65 @@ class Fight: self.ui = ui self.player = player self.enemies = [] + self.is_running = True def add_enemy(self, enemy): self.enemies.append(enemy) def start(self): while len(self.enemies) > 0: + self.ui.clear_screen() + + if not self.is_running: + print('Feigling!') + return + + self.ui.show_player_status(self.player) + self.ui.show_enemies(self.player, self.enemies) - ui.make_choice( - ['Gegner wählen', 'Fähigkeit wirken'], - [self.choose_enemy, self.choose_ability] - ) + choices = [] + callbacks = [] + + choices.append('Gegner wählen') + callbacks.append(self.choose_enemy) + + if self.player.target is not None: + choices.append('Angreifen') + callbacks.append(self.attack_target) + + choices.append('Fähigkeit wirken') + callbacks.append(self.choose_ability) + + choices.append('Weglaufen') + callbacks.append(self.quit) + + ui.make_choice(choices, callbacks) print('Du warst siegreich.') + def enemies_attack(self): + for e in self.enemies: + damage = random.randint(e.damage_min, e.damage_max) + self.player.add_damage(damage) + + print('%s greift an und verursacht %d Schaden.' % (e.title, damage)) + + def quit(self): + self.is_running = False + + def attack_target(self): + damage = random.randint(self.player.damage_min, self.player.damage_max) + self.player.target.add_damage(damage) + + print('Du hast %d Schaden an %s verursacht.' % (damage, self.player.target.title)) + def choose_enemy(self): choices = [] callbacks = [] for e in self.enemies: - choices.append(e.title) + choices.append('%s (%d/%d)' % (e.title, e.hp, e.hp_max)) callbacks.append(lambda e=e: self.set_player_target(e)) ui.make_choice(choices, callbacks) @@ -184,14 +270,20 @@ class Fight: callbacks = [] for a in self.player.abilities: - names.append(a.title) + names.append('%s (%d Mana)' % (a.title, a.mana_cost)) 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)) + if ability.mana_cost > self.player.mana: + print('Nicht genug Mana!') + return + ability.cast() + self.player.mana -= ability.mana_cost + + print('Wirke %s.' % (ability.title)) if __name__ == '__main__': @@ -202,9 +294,6 @@ if __name__ == '__main__': DaggerImpact(player) ] - u = Unit() - u.add_effect(EffectBleedOut()) - dog = Unit() dog.title = 'Räudiger Hund' dog.hp = 20 @@ -226,6 +315,9 @@ if __name__ == '__main__': fight.add_enemy(orc) fight.start() + u = Unit() + u.add_effect(EffectBleedOut()) + while u.hp > 0: to_be_removed = []