From 0b7ead15d2731fd940edb82fd80d2ecbeba93e53 Mon Sep 17 00:00:00 2001 From: Simon Brunning Date: Mon, 11 Mar 2024 08:38:27 +0000 Subject: [PATCH 1/2] Improve logging so we can see what veterancy is doing. To see a veteran generated, use: ./generator.py -vvv --type agent --count 1 --veterancy -a50 --- generator.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/generator.py b/generator.py index 5afc9bf..f722344 100755 --- a/generator.py +++ b/generator.py @@ -11,7 +11,7 @@ from dataclasses import dataclass from datetime import datetime from itertools import islice, cycle, chain -from math import floor +from math import floor, ceil from random import randint, shuffle, choice, sample, choices from textwrap import shorten, wrap from typing import List, Any, Dict, Tuple @@ -224,6 +224,7 @@ def generate_stats(self): shuffle(pool) for score, stat in zip(pool, self.STATS): self.d[stat] = score + logger.debug("%s,stat %s is %s", self, stat, score) def generate_derived_attributes(self): self.d["hitpoints"] = int(round((self.d["strength"] + self.d["constitution"]) / 2.0)) @@ -244,12 +245,16 @@ def generate_skills(self): self.d.update(self.DEFAULT_SKILLS) # Professional skills - self.d.update(self.profession["skills"]["fixed"]) + for skill, score in self.profession["skills"]["fixed"].items(): + self.d[skill] = score + logger.debug("%s, set fixed professional skill %s to %s", self, skill, score) + self.d.update() for skill, score in sample( list(self.profession["skills"].get("possible", {}).items()), self.profession["skills"].get("possible-count", 0), ): self.d[skill] = score + logger.debug("%s, set picked professional skill %s to %s", self, skill, score) for i in range(self.profession["bonds"]): self.d[f"bond{i}"] = self.d["charisma"] @@ -273,7 +278,7 @@ def apply_bonuses(self, potential_bonus_skills, number_to_boost, max_level): self.d[skill] = boosted bonuses_applied += 1 self.bonus_skills.append(skill) - logger.debug("%s, boosted %s to %s", self, skill, boosted) + logger.debug("%s, boosted bonus skill %s by 20%% to %s", self, skill, boosted) else: logger.debug( "%s, Skipped boost - %s already at %s", self, skill, self.d.get(skill, 0) @@ -303,7 +308,7 @@ def veterancy_skill_boosts(self): roll = randint(1, 100) if roll > current or roll == 100: self.d[skill] += 1 - logger.debug("%s, boosted %s from %s to %s by veterancy", self, skill, original, self.d[skill]) + logger.debug("%s, veterancy experience %s, %s checks, from %s to %s", self, skill, skill_checks, original, self.d[skill]) def veterancy_stat_losses(self): losses = 0 @@ -312,13 +317,13 @@ def veterancy_stat_losses(self): elif 60 <= self.age <= 69: losses = 4 elif 70 <= self.age <= 79: losses = 8 elif 80 <= self.age <= 89: losses = 16 - elif 80 <= self.age: losses = 32 + elif 90 <= self.age: losses = 32 while losses and not all(self.d[stat] <= 1 for stat in self.PHYSICAL_STATS): target = choice(self.PHYSICAL_STATS) if self.d[target] > 1: self.d[target] -= 1 losses -= 1 - logger.debug("%s, %s decreased to %s by veterancy", self, target, self.d[target]) + logger.debug("%s, %s decreased by 1 to %s by veterancy", self, target, self.d[target]) def damaged_veteran_changes(self): damage_count = choices(range(5), weights=[80, 10, 5, 4, 1])[0] @@ -333,6 +338,7 @@ def damaged_veteran_changes(self): damage = ["Damaged Veteran:"] for method in damage_methods: method(damage) + logger.debug("%s, damaged veteran changes %s", self, method.__name__) for i, description in enumerate(damage): self.e[f"detail{i}"] = description From ca6363fab8b517217e9d1c04c7a812a964f15145 Mon Sep 17 00:00:00 2001 From: Simon Brunning Date: Thu, 21 Mar 2024 11:20:06 +0000 Subject: [PATCH 2/2] Damaged veterans bug fixes: * Hard experience skill bumps should be 10%, not 20% * Show both original and current sanity values --- generator.py | 57 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/generator.py b/generator.py index f722344..6f8cec6 100755 --- a/generator.py +++ b/generator.py @@ -11,7 +11,7 @@ from dataclasses import dataclass from datetime import datetime from itertools import islice, cycle, chain -from math import floor, ceil +from math import floor from random import randint, shuffle, choice, sample, choices from textwrap import shorten, wrap from typing import List, Any, Dict, Tuple @@ -177,6 +177,9 @@ def __init__(self, self.data = data self.profession = profession self.sex = sex + self.san_lost = 0 + self.adapted_to_violence = 0 + self.adapted_to_helplessness = 0 # Hold all dictionaries self.d = {} @@ -229,7 +232,9 @@ def generate_stats(self): def generate_derived_attributes(self): self.d["hitpoints"] = int(round((self.d["strength"] + self.d["constitution"]) / 2.0)) self.d["willpower"] = self.d["power"] - self.d["sanity"] = (self.d["power"] * 5) - getattr(self, "san_loss", 0) + self.d["sanity"] = (self.d["power"] * 5) + if self.san_lost: + self.d["current_sanity"] = (self.d["power"] * 5) - self.san_lost self.d["breaking point"] = self.d["sanity"] - self.d["power"] self.damage_bonus = ((self.d["strength"] - 1) >> 2) - 2 self.d["damage bonus"] = "DB=%d" % self.damage_bonus @@ -237,8 +242,8 @@ def generate_derived_attributes(self): score = self.d[stat] self.d[f"{stat}_x5"] = score * 5 self.d[f"{stat}_distinguishing"] = self.distinguishing(stat, score) - self.d["violence"] = " ".join("X" for _ in range(getattr(self, "adapted_to_violence", 0))) - self.d["helplessness"] = " ".join("X" for _ in range(getattr(self, "adapted_to_helplessness", 0))) + self.d["violence"] = " ".join("X" for _ in range(self.adapted_to_violence)) + self.d["helplessness"] = " ".join("X" for _ in range(self.adapted_to_helplessness)) def generate_skills(self): # Default skills @@ -267,18 +272,21 @@ def generate_bonus_skills(self): for s in self.profession["skills"].get("bonus", []) if randint(1, 100) <= SUGGESTED_BONUS_CHANCE ] + sample(self.ALL_BONUS, len(self.ALL_BONUS)) - self.apply_bonuses(potential_bonus_skills, 8, 80) + self.apply_bonuses(potential_bonus_skills, 8, 20, 80) - def apply_bonuses(self, potential_bonus_skills, number_to_boost, max_level): + def apply_bonuses(self, potential_bonus_skills: list[str], + number_of_skills_to_boost: int, + boost_by_percentile: int, + max_skill_level: int) -> None: bonuses_applied = 0 - while bonuses_applied < number_to_boost: + while bonuses_applied < number_of_skills_to_boost: skill = potential_bonus_skills.pop(0) - boosted = self.d.get(skill, 0) + 20 - if boosted <= max_level: + boosted = self.d.get(skill, 0) + boost_by_percentile + if boosted <= max_skill_level: self.d[skill] = boosted bonuses_applied += 1 self.bonus_skills.append(skill) - logger.debug("%s, boosted bonus skill %s by 20%% to %s", self, skill, boosted) + logger.debug("%s, boosted bonus skill %s by %s%% to %s", self, skill, boost_by_percentile, boosted) else: logger.debug( "%s, Skipped boost - %s already at %s", self, skill, self.d.get(skill, 0) @@ -295,6 +303,9 @@ def skill_checks_at_age(age, earned_at_start=4, start_age=25, halve_rate=10): return earned_at_start * (1 / 2 ** ((age - start_age) / halve_rate)) def veterancy_skill_boosts(self): + ## Fixed prof - 4 per year + ## possible prof - 1/2 of them, 2 per year + ## Defaults & bonus - 1/4 of them, 2 per year skills_to_check = set(list(self.profession['skills']['fixed'].keys()) + list(self.profession['skills'].get('possible', {}).keys()) + # list(self.DEFAULT_SKILLS.keys()) + @@ -335,43 +346,45 @@ def damaged_veteran_changes(self): self.things_man_was_not_meant_to_know_changes], k=damage_count ) - damage = ["Damaged Veteran:"] + damage: list[str] = ["Damaged Veteran:"] for method in damage_methods: - method(damage) logger.debug("%s, damaged veteran changes %s", self, method.__name__) + method(damage) + logger.debug("%s, san lost, adapted_to_violence, adapted_to_helplessness now %s, %s, %s", self, + self.san_lost, self.adapted_to_violence, self.adapted_to_helplessness) for i, description in enumerate(damage): self.e[f"detail{i}"] = description - def extreme_violence_changes(self, damage): + def extreme_violence_changes(self, damage: list[str]): damage.append("• Extreme Violence") self.d["occult"] += 10 - self.san_loss = getattr(self, "san_loss", 0) + 5 + self.san_lost += 5 self.d["charisma"] -= 3 for i in range(self.profession["bonds"]): if f"bond{i}" in self.d: self.d[f"bond{i}"] -= 3 self.adapted_to_violence = 3 - def captivity_or_imprisonment_changes(self, damage): + def captivity_or_imprisonment_changes(self, damage: list[str]): damage.append("• Captivity or Imprisonment") self.d["occult"] += 10 - self.san_loss = getattr(self, "san_loss", 0) + 5 + self.san_lost += 5 self.d["power"] -= 3 self.adapted_to_helplessness = 3 - def hard_experience_changes(self, damage): + def hard_experience_changes(self, damage: list[str]): damage.append("• Hard Experience") self.d["occult"] += 10 potential_bonus_skills = sample(self.ALL_BONUS, len(self.ALL_BONUS)) - self.apply_bonuses(potential_bonus_skills, 5, 90) - self.san_loss = getattr(self, "san_loss", 0) + 5 + self.apply_bonuses(potential_bonus_skills, 5, 10, 90) + self.san_lost += 5 del self.d[f"bond{self.profession['bonds']-1}"] - def things_man_was_not_meant_to_know_changes(self, damage): + def things_man_was_not_meant_to_know_changes(self, damage: list[str]): damage.append("• Things Man Was Not Meant to Know") self.d["unnatural"] = self.d.get("unnatural", 0) + 10 self.d["occult"] += 20 - self.san_loss = getattr(self, "san_loss", 0) + self.d["power"] + self.san_lost += self.d["power"] self.d["disorder0"] = "Disorder: " + choice( ["Amnesia", "Depersonalization", @@ -382,6 +395,7 @@ def things_man_was_not_meant_to_know_changes(self, damage): "Paranoia", "Sleep Disorder", ]) + def potential_bonus_skills(self, profession): return [ s @@ -566,6 +580,7 @@ class Need2KnowPDF(object): "hitpoints": (195, 482, 11), "willpower": (195, 464, 11), "sanity": (195, 446, 11), + "current_sanity": (265, 446, 11), "breaking point": (195, 428, 11), "bond0": (512, 604, 11), "bond1": (512, 586, 11),