Skip to content

Instantly share code, notes, and snippets.

@OzuYatamutsu
Created June 22, 2019 22:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OzuYatamutsu/54438c6d2ebdc4da45343b01ef1027df to your computer and use it in GitHub Desktop.
Save OzuYatamutsu/54438c6d2ebdc4da45343b01ef1027df to your computer and use it in GitHub Desktop.
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