dnd5-scripts/faction_turns/tests/test_wwn_mechanics.py

144 lines
6.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.

import pytest
import sys
from pathlib import Path
# Добавляем родительскую директорию в sys.path для импорта модулей
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from wwn_mechanics import (
calc_hp_max, calc_income, calc_xp_cost_to_raise,
calc_asset_upkeep, calc_repair_heal, calc_faction_repair_heal,
get_available_upgrades, get_attack_extra_die_flags,
has_antimagical_penalty, check_massive_auto_win
)
# ----------------------------------------------- HP Tests ------------------------------------------------------------
def test_calc_hp_max():
"""Проверяет корректность расчета максимального HP фракции на основе атрибутов."""
assert calc_hp_max(2, 4, 5) == 17
assert calc_hp_max(3, 3, 3) == 12
assert calc_hp_max(1, 1, 1) == 3
assert calc_hp_max(8, 8, 8) == 60
# ----------------------------------------------- Income Tests ------------------------------------------------------------
def test_calc_income():
"""Проверяет правильность расчета дохода фракции (Treasure income) за один ход."""
assert calc_income(4, 2, 5) == 4
assert calc_income(2, 1, 1) == 2
assert calc_income(8, 7, 6) == 8
# ----------------------------------------------- XP Tests ------------------------------------------------------------
def test_calc_xp_cost_to_raise():
"""Проверяет получение стоимости в XP для повышения значения атрибута."""
assert calc_xp_cost_to_raise(1) == 2
assert calc_xp_cost_to_raise(4) == 9
assert calc_xp_cost_to_raise(7) == 20
assert calc_xp_cost_to_raise(8) is None
# ----------------------------------------------- Upkeep Tests ------------------------------------------------------------
def test_calc_asset_upkeep():
"""Проверяет расчет апкипа фракции за превышение лимитов активов."""
faction_fm = {
"force": 1, "wealth": 1, "cunning": 1,
"assets": [
{"name": "Infantry", "attribute": "Force", "is_base_of_influence": False},
{"name": "Thugs", "attribute": "Force", "is_base_of_influence": False}, # Excess
{"name": "Free Company", "attribute": "Wealth", "is_base_of_influence": False}, # special upkeep
{"name": "Farmers", "attribute": "Wealth", "is_base_of_influence": False}, # Excess
{"name": "BoI", "attribute": "Wealth", "is_base_of_influence": True} # Not counted
]
}
upkeep = calc_asset_upkeep(faction_fm)
assert upkeep["excess_force"] == 1
assert upkeep["excess_wealth"] == 1
assert upkeep["free_company_count"] == 1
assert upkeep["total_upkeep"] == 3 # 1 (Force) + 1 (Wealth) + 1 (Free Company)
assert "Thugs" in upkeep["excess_assets"]
# ----------------------------------------------- Repair Tests ------------------------------------------------------------
def test_calc_repair_heal():
"""Проверяет расчет стоимости и объема лечения актива."""
fm = {"force": 5, "wealth": 2, "cunning": 4}
res1 = calc_repair_heal(fm, "Force", 1)
assert res1["cost"] == 1
assert res1["heal"] == 3 # ceil(5/2)
res2 = calc_repair_heal(fm, "Cunning", 3)
assert res2["cost"] == 3
assert res2["heal"] == 2 # ceil(4/2)
def test_calc_faction_repair_heal():
"""Проверяет расчет лечения самой фракции."""
fm = {"force": 8, "wealth": 2, "cunning": 4}
res = calc_faction_repair_heal(fm)
assert res["cost"] == 1
assert res["heal"] == 5 # ceil((8+2)/2)
assert res["highest_attr"] == "force"
assert res["lowest_attr"] == "wealth"
# ----------------------------------------------- Faction Tags Tests ------------------------------------------------------------
def test_get_attack_extra_die_flags():
"""Проверяет флаги бонусных кубиков при атаке."""
atk_fm = {"faction_tags": ["Martial", "Machiavellian"]}
def_fm = {"faction_tags": ["Rich"]}
# Martial дает бонус на Force
a_extra, d_extra = get_attack_extra_die_flags(atk_fm, def_fm, "Force")
assert a_extra is True
assert d_extra is False
# Rich дает бонус на Wealth
a_extra, d_extra = get_attack_extra_die_flags(atk_fm, def_fm, "Wealth")
assert a_extra is False
assert d_extra is True
def test_has_antimagical_penalty():
"""Проверяет применение штрафа Antimagical."""
def_fm = {"faction_tags": ["Antimagical"]}
assert has_antimagical_penalty(def_fm, "High") is True
assert has_antimagical_penalty(def_fm, "Medium") is True
assert has_antimagical_penalty(def_fm, "Low") is False
def test_check_massive_auto_win():
"""Проверяет автопобеду тега Massive."""
atk_fm = {"faction_tags": ["Massive"], "force": 7}
def_fm = {"force": 3}
# Атакующий > 2 * защитника
assert check_massive_auto_win(atk_fm, def_fm, "Force") is True
def_fm["force"] = 4
# Не более чем в 2 раза
assert check_massive_auto_win(atk_fm, def_fm, "Force") is None
# Защитник Massive
atk_fm2 = {"force": 2}
def_fm2 = {"faction_tags": ["Massive"], "force": 5}
assert check_massive_auto_win(atk_fm2, def_fm2, "Force") is False
# ----------------------------------------------- Upgrades Tests ------------------------------------------------------------
def test_get_available_upgrades():
"""Проверяет получение доступных для повышения атрибутов."""
fm = {"force": 2, "wealth": 7, "cunning": 8, "xp": 15}
upgrades = get_available_upgrades(fm)
# Cunning 8 не должно быть в списке
assert len(upgrades) == 2
force_upg = next(u for u in upgrades if u["attribute"] == "force")
assert force_upg["current_value"] == 2
assert force_upg["next_value"] == 3
assert force_upg["xp_cost"] == 4
assert force_upg["can_afford"] is True
wealth_upg = next(u for u in upgrades if u["attribute"] == "wealth")
assert wealth_upg["xp_cost"] == 20
assert wealth_upg["can_afford"] is False