summaryrefslogtreecommitdiff
path: root/creature.py
diff options
context:
space:
mode:
Diffstat (limited to 'creature.py')
-rw-r--r--creature.py64
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()