diff options
Diffstat (limited to 'creature.py')
| -rw-r--r-- | creature.py | 64 |
1 files changed, 56 insertions, 8 deletions
diff --git a/creature.py b/creature.py index 3584cf0..aa2f7f4 100644 --- a/creature.py +++ b/creature.py @@ -1,5 +1,7 @@ import csv +import re from enum import Enum +from dataclasses import dataclass class Difficulty(Enum): Terrible = -2 @@ -16,8 +18,41 @@ class Difficulty(Enum): return member raise ValueError(f"{name!r} is not a valid {cls.__name__}") +@dataclass +class RollInfo: + die_size: int + dice_count: int = 1 + bonus: int = 0 + + @classmethod + def parse(cls, str_data): + # match strings like 2d6+8 (15) + match = re.fullmatch(r"^(\d+)d(\d+)\s*(\+\s*\d+)?\s*(\s*\(\s*\d+\s*\))?", + str_data) + if not match: + raise ValueError(f"{str_data!r} is not a valid RollInfo") + res = RollInfo(int(match.group(2).strip())) + res.dice_count = int(match.group(1).strip()) + bonus = match.group(3) + if bonus: + res.bonus = int(bonus.strip(" +")) + return res + + +def safe_item_level(creature_level: int): + if creature_level <= 3: + return 0 + if creature_level == 4: + return 1 + return creature_level - 4 def load_csv(name, value_parser=None): + def parse_col_name(name): + try: + return Difficulty.from_str(name) + except ValueError: + return name.lower() + if value_parser is None: value_parser = lambda x:x res = dict() # Table by level and Difficulty @@ -25,22 +60,35 @@ def load_csv(name, value_parser=None): reader = csv.DictReader(file) for row in reader: level = int(row.pop("Level")) - res[level] = {Difficulty.from_str(name): + res[level] = {parse_col_name(name): value_parser(val) for name,val in row.items()} return res -def parse_range(str_data): +def parse_stat(str_data): try: - value = int(str_data) - return (value, value) + return int(str_data) except ValueError: - return tuple([int(i) for i in str_data.split("-")[:2]]) + pass + + separator = "-" + if separator in str_data: + # parse range + values = [int(i) for i in str_data.split(separator)[:2]] + return tuple((min(*values), max(*values))) + else: + return RollInfo.parse(str_data) + class StatsDB: + stat_names = ["ac","abilities","attack_bonus", "hp", + "perception", "saves", "resistances", "skills", "strike_damage"] + def __init__(self) -> None: - self.ac = load_csv("ac", int) - self.saves = load_csv("saves", int) - self.hp = load_csv("hp", parse_range) + self.stats = dict() + for stat_name in StatsDB.stat_names: + self.stats[stat_name] = load_csv(stat_name, parse_stat) + self.stats["resistances"] = {k:(v["minimum"], v["maximum"]) + for k,v in self.stats["resistances"].items()} stats = StatsDB() |
