summaryrefslogtreecommitdiff
path: root/main.py
diff options
context:
space:
mode:
authorSupremist <sergkarv@gmail.com>2025-10-30 15:31:17 +0200
committerSupremist <sergkarv@gmail.com>2025-10-30 15:31:17 +0200
commit6cdeabcfc131a2b21599b3fa5980a4ecb59539bd (patch)
treefd454dd318a85db342354fe822696104d72e2c0e /main.py
parent9cc423f1e3b0a1d9e498c522cb550709e348eed7 (diff)
downloadpf2e_calc-6cdeabcfc131a2b21599b3fa5980a4ecb59539bd.tar.xz
pf2e_calc-6cdeabcfc131a2b21599b3fa5980a4ecb59539bd.zip
Test Demoralize
Diffstat (limited to 'main.py')
-rw-r--r--main.py111
1 files changed, 84 insertions, 27 deletions
diff --git a/main.py b/main.py
index 0a25394..65c9c45 100644
--- a/main.py
+++ b/main.py
@@ -1,5 +1,6 @@
import math
from character import CharacterPlan
+from distribution import Distribution
from game import Difficulty, Roll, d
from creature import CreaturePlan
from actions import Attack
@@ -24,13 +25,6 @@ def treat_wounds(check_res, heal_bonus=0):
if check_res == Roll.Crit:
return 4*d(8) + heal_bonus
-def strike(check_res, dmg, crit_dmg=0):
- if check_res == Roll.Success:
- return dmg
- if check_res == Roll.Crit:
- return 2*dmg + crit_dmg
- return 0
-
def show_stat(name, dist):
print(name)
@@ -67,26 +61,88 @@ def main():
treat = d(20).apply(Roll.check, 20, bonus+1).apply(treat_wounds, 15)
show_stat("Treat Wounds 20 +1", treat)
-
-def test3():
- # char_js = pb2e.download_character(pfb_id=160180)
- char_js = pb2e.open_character("quizrel2")
- char_plan = CharacterPlan(char_js)
- creature_plan = CreaturePlan(default_difficulty=Difficulty.Moderate)
- # creature_plan["reflex"] = Difficulty.High
- # creature_plan["ac"] = Difficulty.High
-
- def calc_damage(level):
- char = char_plan.build(level)
- creature = creature_plan.build(level)
- creature["ac"] -= 2
+class StatsTest:
+ def __init__(self) -> None:
+ # self.char_js = pb2e.download_character(pfb_id=160180)
+ self.char_js = pb2e.open_character("quizrel2")
+ self.char_plan = CharacterPlan(self.char_js)
+ self.creature_plan = CreaturePlan(default_difficulty=Difficulty.Moderate)
+ # self.creature_plan["reflex"] = Difficulty.High
+ # self.creature_plan["ac"] = Difficulty.High
+ self.char = self.char_plan.build(1)
+
+ def add_weapons(self):
falcata = Weapon("falcata", "martial", "sword", 8, fatal=12)
- sword = Weapon("sword", "martial", "sword", 8)
+ sword = Weapon("pick", "martial", "pick", 6, fatal=10)
rapier = Weapon("rapier", "martial", "sword", 6, finesse=True, deadly=8)
- sword2 = Weapon("sword_d6", "martial", "sword", 6)
- char.weapons = [falcata, sword, rapier, sword2]
- char.update_fundamental_runes()
+ urumi = Weapon("urumi", "martial", "flail", 6, deadly=10)
+ sword2 = Weapon("tricky pick", "martial", "pick", 6, fatal=10, backstabber=True)
+ self.char.weapons.extend([sword, falcata, rapier, sword2, urumi])
+
+ def get_weapon(self, name):
+ for wp in self.char.weapons:
+ if wp.name == name:
+ return wp
+ raise KeyError
+
+ def set_level(self, level):
+ self.char = self.char_plan.build(level)
+ self.creature = self.creature_plan.build(level)
+ self.add_weapons()
+ self.char.update_fundamental_runes()
+
+def test4():
+ t = StatsTest()
+ t.set_level(5)
+ urumi = t.get_weapon("urumi")
+ attack = Attack(t.char, t.creature, urumi)
+ print("Attack: ", Roll.short_str(attack.roll()))
+ print(f"Attack +{attack.bonus()} vs AC {attack.target.ac()} dmg +{attack.damage_bonus()}")
+ crit_chance = attack.roll().probabilities[Roll.Crit]
+ print(t.char.classDC() , t.creature["reflex"])
+ prone_save = d(20).apply(Roll.check, t.char.classDC(), t.creature["reflex"])
+ print("Prone save: ", Roll.short_str(prone_save))
+ prone_chace = prone_save.accumulate_prob(lambda x: x <= Roll.Fail)
+ print(f"Crit: {crit_chance}; Prone: {prone_chace}; Total Prone Chance: {crit_chance*prone_chace}")
+
+def make_check(name, bonus, dc):
+ roll = d(20).apply2(lambda v, bonus: Roll.check(v, dc, bonus), bonus)
+ if isinstance(bonus, Distribution):
+ bonus = bonus.expected()
+ print(f"{name} {bonus:+} vs DC {dc}:",
+ Roll.short_str(roll), f"Total: {dc-bonus-10:+}")
+ return roll
+
+def demoralize_test():
+ def bon_mot_pen(check):
+ if check == Roll.Success:
+ return -2
+ if check == Roll.Crit:
+ return -3
+ return 0
+ t = StatsTest()
+ t.creature_plan["will"] = Difficulty.Moderate
+ t.set_level(5)
+ t.char.features["diplomacy"] = 2
+ t.char.features["intimidation"] = 4
+ intimid_bonus = t.char.proficiency("intimidation") + 1
+ will_dc = 10+t.creature["will"]
+ roll = make_check("Demoralize", intimid_bonus, will_dc)
+ frightened = roll.apply(lambda x: x if x >= Roll.Success else 0).expected()
+ print("Frightened:", frightened)
+
+ bon_mot = make_check("Bon mot", t.char.proficiency("diplomacy"), will_dc)
+ penalty = bon_mot.apply(bon_mot_pen)
+ print("Bon Mot Penalty:", penalty.expected())
+
+ roll = make_check("Demoralize2", -penalty+intimid_bonus, will_dc)
+ frightened = roll.apply(lambda x: x if x >= Roll.Success else 0).expected()
+ print("Frightened:", frightened)
+def test3():
+ t = StatsTest()
+ def calc_damage(level):
+ t.set_level(level)
# print(char.toJSON())
# attack = Attack(char, creature, falcata)
# print(Roll.short_str(attack.roll()))
@@ -95,8 +151,8 @@ def test3():
# show_stat("falcata", attack.strike())
res = dict()
- for weapon in char.weapons:
- attack = Attack(char, creature, weapon)
+ for weapon in t.char.weapons:
+ attack = Attack(t.char, t.creature, weapon)
res[weapon.name] = attack.strike().expected()
# res["hp"] = creature["hp"]
return res
@@ -136,4 +192,5 @@ def levelup_view(title, ylabel, fn):
if __name__ == '__main__':
- test3()
+ # test4()
+ demoralize_test()