import math from character import CharacterPlan from game import Difficulty, Roll, d from creature import CreaturePlan import pb2e class Weapon: def __init__(self, crit_effect, main_die, potency, striking=1, fatal=0, deadly=0, backstabber=False, agile=False, twin=False) -> None: self.main_die = main_die self.striking = striking self.potency = potency self.backstabber = backstabber self.fatal = fatal self.deadly = deadly self.agile = agile self.twin = twin self.crit_effect = crit_effect def get_map(self, number): number = max(0, min(2, number)) if self.agile: return number * -4 return number * -5 def damage(self, dmg_bonus, check=Roll.Success, number = 0): persistant_damage_factor = 3 + 1/3 if self.backstabber: dmg_bonus += 1 if self.potency >= 3: dmg_bonus += 1 if self.twin and number > 0: dmg_bonus += self.striking if check == Roll.Success: return self.striking * d(self.main_die) + dmg_bonus if check == Roll.Crit: dmg = None if self.fatal is not None and self.fatal > 0: dmg = (self.striking + 1) * d(self.fatal) else: dmg = self.striking * d(self.main_die) dmg = 2 * (dmg+dmg_bonus) if self.deadly is not None and self.deadly > 0: dmg += max(1, self.striking-1) * d(self.deadly) if self.crit_effect == "crossbow": dmg += persistant_damage_factor * d(8).expected() elif self.crit_effect == "dart" or self.crit_effect == "knife": dmg += persistant_damage_factor * d(6).expected() elif self.crit_effect == "dagger": dmg += persistant_damage_factor * d(6).expected() elif self.crit_effect == "pick": dmg += 2 * self.striking return dmg return 0 def strike(self, attack_bonus, dmg_bonus, ac, number = 0): def strike_dmg(check): return self.damage(dmg_bonus, check, number) bonus = attack_bonus+self.potency+self.get_map(number) attack_roll = d(20).apply(Roll.check, ac, bonus) return attack_roll.apply(strike_dmg) def treat_wounds(check_res, heal_bonus=0): if check_res <= Roll.Fumble: return -d(8) if check_res == Roll.Fail: return 0 if check_res == Roll.Success: return 2*d(8) + heal_bonus 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) values = list(dist.probabilities.keys()) mn = min(values) mx = max(values) print("min", mn, dist.probabilities[mn]) print("max", mx, dist.probabilities[mx]) print("Exp", dist.expected()) print("Std", dist.standard_deviation()) print("<0", dist.accumulate_prob(lambda x: x < 0)) print(">0", dist.accumulate_prob(lambda x: x > 0)) print("") assert abs(dist.accumulate_prob(lambda x: True) - 1) < math.pow(10, -10) coin = d(2) def main(): treat_options = [ {"dc": 15, "heal_bonus": 0}, {"dc": 20, "heal_bonus": 15} ] bonus = 10 show_stat("Assurance 15", 2*d(8)) for opt in treat_options: dc = opt["dc"] treat = d(20).apply(Roll.check, dc, bonus).apply(treat_wounds, opt["heal_bonus"]) risky = d(20).apply(Roll.check, dc, bonus+2).apply(lambda x: Roll.Crit if x == Roll.Success else x) risky = risky.apply(treat_wounds, opt["heal_bonus"]) + (-d(8)) show_stat("Treat Wounds " + str(dc), treat) show_stat("Risky Surgery " + str(dc), risky) treat = d(20).apply(Roll.check, 20, bonus+1).apply(treat_wounds, 15) show_stat("Treat Wounds 20 +1", treat) def main2(): ac = 18 bonus = +8 dmg = d(6)+4 attack = d(20).apply(Roll.check, ac, bonus) show_stat("attack", attack) total_dmg = attack.apply(strike, dmg+1) show_stat("dogslicer", total_dmg) total_dmg = attack.apply(strike, dmg, d(8)) show_stat("rapier", total_dmg) def test3(): falcata = Weapon("sword", 8, 0, fatal=0) ac = 18 bonus = +8 +3 dmg_bonus = d(6)+4 attack = d(20).apply(Roll.check, ac, bonus) show_stat("attack", attack) show_stat("falcata", falcata.strike(bonus, dmg_bonus, ac, 0)) def main4(): #char_js = pb2e.download_character(pfb_id=160180) char_js = pb2e.open_character("quizrel2") plan = CharacterPlan(char_js) char = plan.build(1) print(char.toJSON()) char = plan.build(5) print(char.toJSON()) def main5(): creature_plan = CreaturePlan(default_difficulty=Difficulty.Moderate) creature_plan["reflex"] = Difficulty.High creature = creature_plan.build(10) print(creature) if __name__ == '__main__': main5()