From f2c7dbddb602db06ec8e8a8c9a4134451acd52e9 Mon Sep 17 00:00:00 2001 From: Supremist Date: Tue, 28 Oct 2025 23:47:23 +0200 Subject: Move common data structs to game.py --- creature.py | 39 +-------------------------- game.py | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.py | 45 +------------------------------- 3 files changed, 89 insertions(+), 82 deletions(-) create mode 100644 game.py diff --git a/creature.py b/creature.py index aa2f7f4..e30f877 100644 --- a/creature.py +++ b/creature.py @@ -1,43 +1,6 @@ import csv -import re -from enum import Enum -from dataclasses import dataclass - -class Difficulty(Enum): - Terrible = -2 - Low = -1 - Moderate = 0 - High = 1 - Extreme = 2 - - @classmethod - def from_str(cls, name): - name = name.strip().lower() - for member in cls: - if member.name.lower() == name: - 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 +from game import Difficulty, RollInfo def safe_item_level(creature_level: int): if creature_level <= 3: diff --git a/game.py b/game.py new file mode 100644 index 0000000..fd9aba0 --- /dev/null +++ b/game.py @@ -0,0 +1,87 @@ +import re +from enum import Enum +from dataclasses import dataclass + +from distribution import Distribution + +def d(edge_count): + res = Distribution() + if edge_count == 0: + res.insert(0, 1) + return res + prob = 1/edge_count + for val in range(1, edge_count+1): + res.insert(val, prob) + return res + + +class Roll: + Fumble = -1 + Fail = 0 + Success = 1 + Crit = 2 + + @staticmethod + def get_natural_success_mod(value): + if value <= 1: + return -1 + if value >= 20: + return 1 + return 0 + + @staticmethod + def check(value, dc, bonus=0): + res = 0 + rolled = value + bonus + if rolled >= dc + 10: + res = Roll.Crit + elif rolled >= dc: + res = Roll.Success + elif rolled <= dc - 10: + res = Roll.Fumble + res += Roll.get_natural_success_mod(value) + return Roll.clamp(res) + + @staticmethod + def clamp(value): + return max(Roll.Fumble, min(Roll.Crit, value)) + + +class Difficulty(Enum): + Terrible = -2 + Low = -1 + Moderate = 0 + High = 1 + Extreme = 2 + + @classmethod + def from_str(cls, name): + name = name.strip().lower() + for member in cls: + if member.name.lower() == name: + 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 distribution(self): + return self.dice_count * d(self.die_size) + self.bonus + diff --git a/main.py b/main.py index 7d55e96..138da27 100644 --- a/main.py +++ b/main.py @@ -1,53 +1,10 @@ import math -from sys import base_exec_prefix -from distribution import Distribution from character import CharacterPlan +from game import Roll, d import pb2e -def d(edge_count): - res = Distribution() - if edge_count == 0: - res.insert(0, 1) - return res - prob = 1/edge_count - for val in range(1, edge_count+1): - res.insert(val, prob) - return res - - -class Roll: - Fumble = -1 - Fail = 0 - Success = 1 - Crit = 2 - - @staticmethod - def get_natural_success_mod(value): - if value <= 1: - return -1 - if value >= 20: - return 1 - return 0 - - @staticmethod - def check(value, dc, bonus=0): - res = 0 - rolled = value + bonus - if rolled >= dc + 10: - res = Roll.Crit - elif rolled >= dc: - res = Roll.Success - elif rolled <= dc - 10: - res = Roll.Fumble - res += Roll.get_natural_success_mod(value) - return Roll.clamp(res) - - @staticmethod - def clamp(value): - return max(Roll.Fumble, min(Roll.Crit, value)) - class Weapon: def __init__(self, crit_effect, main_die, potency, striking=1, fatal=0, -- cgit v1.2.3