61 lines
3.1 KiB
Python
61 lines
3.1 KiB
Python
# abilities.py
|
||
import random
|
||
|
||
CLASS_STAT_PRIORITY = {
|
||
"Barbarian": ["Strength", "Constitution", "Dexterity", "Wisdom", "Charisma", "Intelligence"],
|
||
"Bard": ["Charisma", "Dexterity", "Intelligence", "Constitution", "Wisdom", "Strength"],
|
||
"Cleric": ["Wisdom", "Strength", "Dexterity", "Constitution", "Charisma", "Intelligence"], # Приоритет будет скорректирован в особых случаях
|
||
"Druid": ["Wisdom", "Dexterity", "Constitution", "Intelligence", "Charisma", "Strength"],
|
||
"Fighter": ["Strength", "Constitution", "Dexterity", "Wisdom", "Charisma", "Intelligence"], # Приоритет будет скорректирован в особых случаях
|
||
"Monk": ["Wisdom", "Dexterity", "Constitution", "Charisma", "Intelligence", "Strength"],
|
||
"Paladin": ["Strength", "Constitution", "Charisma", "Wisdom", "Dexterity", "Intelligence"],
|
||
"Ranger": ["Dexterity", "Wisdom", "Constitution", "Strength", "Charisma", "Intelligence"],
|
||
"Rogue": ["Dexterity", "Charisma", "Intelligence", "Constitution", "Wisdom", "Strength"],
|
||
"Sorcerer": ["Charisma", "Constitution", "Dexterity", "Wisdom", "Intelligence", "Strength"],
|
||
"Warlock": ["Charisma", "Dexterity", "Constitution", "Wisdom", "Intelligence", "Strength"],
|
||
"Wizard": ["Intelligence", "Wisdom", "Constitution", "Dexterity", "Charisma", "Strength"],
|
||
"Commoner": ["Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma"],
|
||
}
|
||
|
||
|
||
def _roll_3d6() -> int:
|
||
return sum(random.randint(1, 6) for _ in range(3))
|
||
|
||
|
||
def _get_modifier(score: int) -> int:
|
||
return (score - 10) // 2
|
||
|
||
|
||
def _total_modifiers(scores: list[int]) -> int:
|
||
return sum(_get_modifier(s) for s in scores)
|
||
|
||
|
||
def get_ability_scores(character_class: str) -> dict[str, int]:
|
||
"""Бросает 3d6 × 6 до тех пор, пока сумма модификаторов ≥ 0,
|
||
затем распределяет значения по приоритету класса."""
|
||
|
||
while True:
|
||
rolled = [_roll_3d6() for _ in range(6)]
|
||
if _total_modifiers(rolled) >= 0:
|
||
break
|
||
|
||
rolled.sort(reverse=True)
|
||
|
||
# Commoner: полный рандом — характеристики раздаются случайно,
|
||
# без приоритета, чтобы не создавать искусственного перекоса
|
||
if character_class == "Commoner":
|
||
stats = ["Strength", "Dexterity", "Constitution",
|
||
"Intelligence", "Wisdom", "Charisma"]
|
||
random.shuffle(stats)
|
||
return {stat: rolled[i] for i, stat in enumerate(stats)}
|
||
|
||
priority = list(CLASS_STAT_PRIORITY[character_class]) # копия
|
||
|
||
# Особые случаи: Cleric / Fighter — Сила и Ловкость случайно меняются местами
|
||
if character_class in ("Cleric", "Fighter"):
|
||
str_idx = priority.index("Strength")
|
||
dex_idx = priority.index("Dexterity")
|
||
if str_idx != dex_idx and random.random() < 0.5:
|
||
priority[str_idx], priority[dex_idx] = priority[dex_idx], priority[str_idx]
|
||
|
||
return {stat: rolled[i] for i, stat in enumerate(priority)} |