diff options
| -rw-r--r-- | creature.py | 64 | ||||
| -rw-r--r-- | creature_stats/abilities.csv | 27 | ||||
| -rw-r--r-- | creature_stats/ac.csv | 4 | ||||
| -rw-r--r-- | creature_stats/attack_bonus.csv | 27 | ||||
| -rw-r--r-- | creature_stats/perception.csv | 27 | ||||
| -rw-r--r-- | creature_stats/resistances.csv | 27 | ||||
| -rw-r--r-- | creature_stats/saves.csv | 4 | ||||
| -rw-r--r-- | creature_stats/skills.csv | 27 | ||||
| -rw-r--r-- | creature_stats/strike_damage.csv | 27 | ||||
| -rw-r--r-- | main.py | 5 |
10 files changed, 226 insertions, 13 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() diff --git a/creature_stats/abilities.csv b/creature_stats/abilities.csv new file mode 100644 index 0000000..dd1f57e --- /dev/null +++ b/creature_stats/abilities.csv @@ -0,0 +1,27 @@ +Level,Extreme,High,Moderate,Low +-1,4,3,2,0 +0,4,3,2,0 +1,5,4,3,1 +2,5,4,3,1 +3,5,4,3,1 +4,6,5,3,2 +5,6,5,4,2 +6,7,5,4,2 +7,7,6,4,2 +8,7,6,4,3 +9,7,6,4,3 +10,8,7,5,3 +11,8,7,5,3 +12,8,7,5,4 +13,9,8,5,4 +14,9,8,5,4 +15,9,8,6,4 +16,10,9,6,5 +17,10,9,6,5 +18,10,9,6,5 +19,11,10,6,5 +20,11,10,7,6 +21,11,10,7,6 +22,11,10,8,6 +23,11,10,8,6 +24,13,12,9,7
\ No newline at end of file diff --git a/creature_stats/ac.csv b/creature_stats/ac.csv index 0743521..b706e0f 100644 --- a/creature_stats/ac.csv +++ b/creature_stats/ac.csv @@ -1,5 +1,5 @@ Level,Extreme,High,Moderate,Low -–1,18,15,14,12 +-1,18,15,14,12 0,19,16,15,13 1,19,16,15,13 2,21,18,17,15 @@ -24,4 +24,4 @@ Level,Extreme,High,Moderate,Low 21,49,46,45,43 22,51,48,47,45 23,52,49,48,46 -24,54,51,50,48
\ No newline at end of file +24,54,51,50,48 diff --git a/creature_stats/attack_bonus.csv b/creature_stats/attack_bonus.csv new file mode 100644 index 0000000..97db6a0 --- /dev/null +++ b/creature_stats/attack_bonus.csv @@ -0,0 +1,27 @@ +Level,Extreme,High,Moderate,Low +-1,10,8,6,4 +0,10,8,6,4 +1,11,9,7,5 +2,13,11,9,7 +3,14,12,10,8 +4,16,14,12,9 +5,17,15,13,11 +6,19,17,15,12 +7,20,18,16,13 +8,22,20,18,15 +9,23,21,19,16 +10,25,23,21,17 +11,27,24,22,19 +12,28,26,24,20 +13,29,27,25,21 +14,31,29,27,23 +15,32,30,28,24 +16,34,32,30,25 +17,35,33,31,27 +18,37,35,33,28 +19,38,36,34,29 +20,40,38,36,31 +21,41,39,37,32 +22,43,41,39,33 +23,44,42,40,35 +24,46,44,42,36
\ No newline at end of file diff --git a/creature_stats/perception.csv b/creature_stats/perception.csv new file mode 100644 index 0000000..de49fc1 --- /dev/null +++ b/creature_stats/perception.csv @@ -0,0 +1,27 @@ +Level,Extreme,High,Moderate,Low,Terrible +-1,9,8,5,2,0 +0,10,9,6,3,1 +1,11,10,7,4,2 +2,12,11,8,5,3 +3,14,12,9,6,4 +4,15,14,11,8,6 +5,17,15,12,9,7 +6,18,17,14,11,8 +7,20,18,15,12,10 +8,21,19,16,13,11 +9,23,21,18,15,12 +10,24,22,19,16,14 +11,26,24,21,18,15 +12,27,25,22,19,16 +13,29,26,23,20,18 +14,30,28,25,22,19 +15,32,29,26,23,20 +16,33,30,28,25,22 +17,35,32,29,26,23 +18,36,33,30,27,24 +19,38,35,32,29,26 +20,39,36,33,30,27 +21,41,38,35,32,28 +22,43,39,36,33,30 +23,44,40,37,34,31 +24,46,42,38,36,32
\ No newline at end of file diff --git a/creature_stats/resistances.csv b/creature_stats/resistances.csv new file mode 100644 index 0000000..a0ded9f --- /dev/null +++ b/creature_stats/resistances.csv @@ -0,0 +1,27 @@ +Level,Maximum,Minimum +-1,1,1 +0,3,1 +1,3,2 +2,5,2 +3,6,3 +4,7,4 +5,8,4 +6,9,5 +7,10,5 +8,11,6 +9,12,6 +10,13,7 +11,14,7 +12,15,8 +13,16,8 +14,17,9 +15,18,9 +16,19,9 +17,19,10 +18,20,10 +19,21,11 +20,22,11 +21,23,12 +22,24,12 +23,25,13 +24,26,13
\ No newline at end of file diff --git a/creature_stats/saves.csv b/creature_stats/saves.csv index ec41b0f..e3b2614 100644 --- a/creature_stats/saves.csv +++ b/creature_stats/saves.csv @@ -1,5 +1,5 @@ Level,Extreme,High,Moderate,Low,Terrible -–1,9,8,5,2,0 +-1,9,8,5,2,0 0,10,9,6,3,1 1,11,10,7,4,2 2,12,11,8,5,3 @@ -24,4 +24,4 @@ Level,Extreme,High,Moderate,Low,Terrible 21,41,38,35,32,28 22,43,39,36,33,30 23,44,40,37,34,31 -24,46,42,38,36,32
\ No newline at end of file +24,46,42,38,36,32 diff --git a/creature_stats/skills.csv b/creature_stats/skills.csv new file mode 100644 index 0000000..5527e0b --- /dev/null +++ b/creature_stats/skills.csv @@ -0,0 +1,27 @@ +Level,Extreme,High,Moderate,Low +-1,8,5,4,2-1 +0,9,6,5,3-2 +1,10,7,6,4-3 +2,11,8,7,5-4 +3,13,10,9,7-5 +4,15,12,10,8-7 +5,16,13,12,10-8 +6,18,15,13,11-9 +7,20,17,15,13-11 +8,21,18,16,14-12 +9,23,20,18,16-13 +10,25,22,19,17-15 +11,26,23,21,19-16 +12,28,25,22,20-17 +13,30,27,24,22-19 +14,31,28,25,23-20 +15,33,30,27,25-21 +16,35,32,28,26-23 +17,36,33,30,28-24 +18,38,35,31,29-25 +19,40,37,33,31-27 +20,41,38,34,32-28 +21,43,40,36,34-29 +22,45,42,37,35-31 +23,46,43,38,36-32 +24,48,45,40,38-33 diff --git a/creature_stats/strike_damage.csv b/creature_stats/strike_damage.csv new file mode 100644 index 0000000..61cff3b --- /dev/null +++ b/creature_stats/strike_damage.csv @@ -0,0 +1,27 @@ +Level,Extreme,High,Moderate,Low +-1,1d6+1 (4),1d4+1 (3),1d4 (3),1d4 (2) +0,1d6+3 (6),1d6+2 (5),1d4+2 (4),1d4+1 (3) +1,1d8+4 (8),1d6+3 (6),1d6+2 (5),1d4+2 (4) +2,1d12+4 (11),1d10+4 (9),1d8+4 (8),1d6+3 (6) +3,1d12+8 (15),1d10+6 (12),1d8+6 (10),1d6+5 (8) +4,2d10+7 (18),2d8+5 (14),2d6+5 (12),2d4+4 (9) +5,2d12+7 (20),2d8+7 (16),2d6+6 (13),2d4+6 (11) +6,2d12+10 (23),2d8+9 (18),2d6+8 (15),2d4+7 (12) +7,2d12+12 (25),2d10+9 (20),2d8+8 (17),2d6+6 (13) +8,2d12+15 (28),2d10+11 (22),2d8+9 (18),2d6+8 (15) +9,2d12+17 (30),2d10+13 (24),2d8+11 (20),2d6+9 (16) +10,2d12+20 (33),2d12+13 (26),2d10+11 (22),2d6+10 (17) +11,2d12+22 (35),2d12+15 (28),2d10+12 (23),2d8+10 (19) +12,3d12+19 (38),3d10+14 (30),3d8+12 (25),3d6+10 (20) +13,3d12+21 (40),3d10+16 (32),3d8+14 (27),3d6+11 (21) +14,3d12+24 (43),3d10+18 (34),3d8+15 (28),3d6+13 (23) +15,3d12+26 (45),3d12+17 (36),3d10+14 (30),3d6+14 (24) +16,3d12+29 (48),3d12+18 (37),3d10+15 (31),3d6+15 (25) +17,3d12+31 (50),3d12+19 (38),3d10+16 (32),3d6+16 (26) +18,3d12+34 (53),3d12+20 (40),3d10+17 (33),3d6+17 (27) +19,4d12+29 (55),4d10+20 (42),4d8+17 (35),4d6+14 (28) +20,4d12+32 (58),4d10+22 (44),4d8+19 (37),4d6+15 (29) +21,4d12+34 (60),4d10+24 (46),4d8+20 (38),4d6+17 (31) +22,4d12+37 (63),4d10+26 (48),4d8+22 (40),4d6+18 (32) +23,4d12+39 (65),4d12+24 (50),4d10+20 (42),4d6+19 (33) +24,4d12+42 (68),4d12+26 (52),4d10+22 (44),4d6+21 (35)
\ No newline at end of file @@ -197,7 +197,10 @@ def main4(): char = plan.build(5) print(char.toJSON()) +def main5(): + from creature import stats + print(stats.stats) if __name__ == '__main__': - main4() + main5() |
