Created
June 22, 2019 22:58
-
-
Save OzuYatamutsu/54438c6d2ebdc4da45343b01ef1027df to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import annotations | |
from dataclasses import dataclass | |
from typing import Union | |
from enum import Enum | |
from random import choice | |
@dataclass | |
class Item: | |
name: str | |
value: int | |
class Command(Enum): | |
ATTACK = "attack" | |
DO_NOTHING = "do_nothing" | |
@classmethod | |
def from_player_input(cls, player_input: str): | |
player_input = player_input.lower() | |
if player_input in ['attack', 'a']: | |
return cls("attack") | |
else: | |
return cls("do_nothing") | |
class Player: | |
def __init__(self, name, hp, damage=1, inventory=tuple()): | |
# Make sure we have a name, non-0 HP, and >0 attack. | |
assert len(name) > 0 | |
assert hp > 0 | |
assert damage >= 0 | |
self.name = name | |
self.hp = hp | |
self.damage = damage | |
self.inventory = list(inventory) | |
def attack(self, other: Player) -> Player: | |
""" | |
Reduce the other player's hp by our attack | |
""" | |
other.hp -= self.damage | |
return other | |
def get_item(self, item: Item) -> None: | |
""" | |
Add item to our inventory | |
""" | |
self.inventory.append(item) | |
def drop_item(self) -> Union[Item, None]: | |
""" | |
Drops an item from our inventory | |
""" | |
if self.inventory: | |
return self.inventory.pop() | |
class PlayerCharacter(Player): | |
def get_item(self, item: Item) -> None: | |
print(f"You got {item.name}!") | |
super().get_item(item) | |
def battle(player0: Player, player1: Player) -> tuple: | |
print(f"A wild {player1.name} has appeared.") | |
# Loop battle flow while both combatants have non-0 HP. | |
def _should_continue_battle(): | |
return all(player.hp > 0 for player in [player0, player1]) | |
while _should_continue_battle(): | |
print(f"{player0.name} HP: {player0.hp}") | |
print(f"{player1.name} HP: {player1.hp}") | |
print() | |
# What will player0 do? | |
print(f"What will {player0.name} do? ", end="") | |
player_input = Command.from_player_input(input()) | |
# Now, do it! | |
if player_input is Command.ATTACK: | |
player1 = player0.attack(player1) | |
print( | |
f"{player0.name} struck {player1.name} " | |
f"for {player0.damage} damage!" | |
) | |
elif player_input is Command.DO_NOTHING: | |
print(f"{player0.name} decided to do nothing. x3") | |
# If the monster is still alive, it attacks back! | |
if not _should_continue_battle(): | |
break | |
player0 = player1.attack(player0) | |
print( | |
f"{player1.name} struck {player0.name} " | |
f"for {player1.damage} damage!" | |
) | |
# The battle is over. | |
winner = player0 if player0.hp > 0 else player1 | |
loser = player0 if player0.hp <= 0 else player1 | |
print(f"The battle is over! {loser.name} is dead.") | |
# The loser drops an item that the winner picks up. | |
winner.get_item(loser.drop_item()) | |
# Reflect new state of the two combatants to the calling function | |
return player0, player1 | |
if __name__ == "__main__": | |
# Set up a fight between us and a random monster | |
us = PlayerCharacter( | |
name='Jinhai', hp=99, damage=9, | |
inventory=(Item(name='Fresh steak', value=90),) | |
) | |
monster_pool = [ | |
Player( | |
name='Slime', hp=50, damage=3, | |
inventory=(Item(name='Gel', value=1),) | |
), | |
Player( | |
name='Lackey', hp=50, damage=3, | |
inventory=(Item(name='Sign of the Occult', value=1),) | |
) | |
] | |
battle(us, choice(monster_pool)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment