dnd5-scripts/generate_npc/classes.py
2026-06-17 22:32:48 +03:00

76 lines
2.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# classes.py
import random
BARD = "Bard"
BARBARIAN = "Barbarian"
FIGHTER = "Fighter"
WIZARD = "Wizard"
DRUID = "Druid"
CLERIC = "Cleric"
WARLOCK = "Warlock"
MONK = "Monk"
PALADIN = "Paladin"
ROGUE = "Rogue"
RANGER = "Ranger"
SORCERER = "Sorcerer"
COMMONER = "Commoner"
CLASSES = [BARD, BARBARIAN, FIGHTER, WIZARD, DRUID, CLERIC,
WARLOCK, MONK, PALADIN, ROGUE, RANGER, SORCERER]
CLASSES_CHANCE = [2, 8, 26, 7, 4, 18, 2, 2, 6, 17, 6, 2]
DEFAULT_COMMONER_CHANCE = 0.90 # 90% мира — простолюдины
def get_random_class(
allowed_classes: list[str] | None = None,
commoner_chance: float = DEFAULT_COMMONER_CHANCE,
) -> str:
"""
Двухуровневый выбор класса.
allowed_classes:
None или [] → все классы, включая Commoner
["Fighter", "Rogue"] → только боевые из списка, Commoner исключён
["Commoner"] → всегда Commoner
["Fighter", "Commoner"] → Fighter или Commoner
commoner_chance:
Вероятность выпадения Commoner (если он допустим). Default 0.90.
"""
all_allowed = not allowed_classes # [] или None → все
commoner_allowed = all_allowed or (COMMONER in allowed_classes)
combat_pool = (
{cls: chance for cls, chance in zip(CLASSES, CLASSES_CHANCE)}
if all_allowed
else {cls: chance for cls, chance in zip(CLASSES, CLASSES_CHANCE)
if cls in allowed_classes}
)
has_combat = bool(combat_pool)
has_commoner = commoner_allowed
# Крайние случаи
if has_commoner and not has_combat:
return COMMONER
if has_combat and not has_commoner:
return _pick_from_combat(combat_pool)
# Общий случай: оба варианта допустимы
if random.random() < commoner_chance:
return COMMONER
return _pick_from_combat(combat_pool)
def _pick_from_combat(pool: dict[str, float]) -> str:
"""Взвешенный выбор из пула боевых классов."""
total = sum(pool.values())
r = random.random() * total
cumulative = 0.0
for cls, chance in pool.items():
cumulative += chance
if r < cumulative:
return cls
return list(pool.keys())[-1]