Stepwise/source/useable.py

98 lines
2.7 KiB
Python

from __future__ import annotations
from typing import Optional, TYPE_CHECKING
if TYPE_CHECKING:
from stats import Stats
class BaseUseable:
"""Base type for useable items, with various utilities"""
current_stack: int
maximum_stack: int
consumable: bool
def __init__(self, *, current_stack: int = 1, maximum_stack: int = -1, consumable: bool = False):
self.current_stack = current_stack
self.maximum_stack = maximum_stack
self.consumable = consumable
def apply(self, stats: Stats) -> bool:
"""
Use this item's effects.
Returns `True` if the item's state changed.
"""
raise NotImplementedError()
def get_used_msg(self, appearance: str) -> Optional[str]:
"""
May return a string to display to the user.
`appearance` is what the item looks like, and can be substituted into the result.
"""
return None #default
#utils
def reduce_stack(self, amount: int = 1) -> bool:
"""
Reduce the size of a stack by an amount.
Returns `True` if this item should be deleted.
"""
if self.maximum_stack > 0:
self.current_stack -= amount
return self.current_stack <= 0
return self.consumable
def is_stack_empty(self) -> bool:
return self.consumable and self.maximum_stack > 0 and self.current_stack <= 0
def is_stack_mergable(self, other: BaseUseable) -> bool:
"""
If this returns `True`, this instance can be merged with the other instance.
"""
if self.__class__ is not other.__class__:
return False
max_stack = max(self.maximum_stack, other.maximum_stack)
return self.current_stack + other.current_stack <= max_stack
class Unuseable(BaseUseable):
"""A placeholder Useable for dead entities."""
def __init__(self):
super().__init__() #enforce defaults
def apply(self, stats: Stats) -> bool:
return None
def get_used_msg(self, appearance: str) -> Optional[str]:
return f"This {appearance} is utterly useless."
class PotionOfHealing(BaseUseable):
"""Restores 4d4 health when applied."""
__last_roll: int = -1
def apply(self, stats: Stats) -> bool:
self.__last_roll = roll_dice(4, 4)
stats.current_hp += self.__last_roll
return self.reduce_stack()
def get_used_msg(self, appearance: str) -> Optional[str]:
return f"You restored {self.__last_roll} health."
# NOTE: NetHack's version
# Healing: 8d4 | 6d4 | 4d4. If the result is above MaxHP, MaxHP is incrased by 1 | 1 | 0.
# Extra Healing: 8d8 | 6d8 | 4d8. If the result is above MaxHP, MaxHP is incrased by 5 | 2 | 0.
# Full Healing: 400 | 400 | 400. If the result is above MaxHP, MaxHP is incrased by 8 | 4 | 0.
#TODO: move this into a different file, 'utils.py'
import random
def roll_dice(number: int, sides: int) -> int:
total: int = 0
for i in range(number):
total += random.randint(1, sides)
return total