summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSupremist <sergkarv@gmail.com>2025-10-28 23:47:23 +0200
committerSupremist <sergkarv@gmail.com>2025-10-28 23:47:23 +0200
commitf2c7dbddb602db06ec8e8a8c9a4134451acd52e9 (patch)
treee3d2e0e7900baf8057efc4e0813065ff16990b34
parente0911bc676e92ce15b7096b2e85f8b3965a48823 (diff)
downloadpf2e_calc-f2c7dbddb602db06ec8e8a8c9a4134451acd52e9.tar.xz
pf2e_calc-f2c7dbddb602db06ec8e8a8c9a4134451acd52e9.zip
Move common data structs to game.py
-rw-r--r--creature.py39
-rw-r--r--game.py87
-rw-r--r--main.py45
3 files changed, 89 insertions, 82 deletions
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,