|
|
@ -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 |
|
|
|
|
|
|
|
print(name) |
|
|
|
|
|
|
|
def show_message_board(self, *lines): |
|
|
|
ornament = '-=W=-' |
|
|
|
width = len(ornament) + 2 |
|
|
|
|
|
|
|
enemy_names.append(name) |
|
|
|
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 = [] |
|
|
|
|
|
|
|