76 lines
2.3 KiB
Python
76 lines
2.3 KiB
Python
# 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]
|