dnd5-scripts/faction_turns/wwn_assets_data.py
2026-07-06 01:48:00 +03:00

1250 lines
48 KiB
Python
Raw Permalink 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.

"""
wwn_assets_data.py — полный справочник активов системы фракций WWN (Worlds Without Number).
Содержит три таблицы активов из книги:
CUNNING_ASSETS — активы на основе Cunning (шпионаж, интриги, подкуп)
FORCE_ASSETS — активы на основе Force (военная сила, солдаты, оружие)
WEALTH_ASSETS — активы на основе Wealth (торговля, деньги, экономика)
Каждый актив — словарь со следующими полями:
name (str) — уникальное имя актива
attribute (str) — "Cunning" | "Force" | "Wealth"
tier_required (int) — минимальное значение атрибута для покупки (18)
cost (int) — стоимость покупки в Treasure
hp_max (int) — максимальные HP актива
magic_required (str) — "None" | "Low" | "Medium" | "High"
attack_attribute (str|None) — атрибут атаки ("Cunning"|"Force"|"Wealth"|None)
attack_vs (str|None) — атрибут защиты цели ("Cunning"|"Force"|"Wealth"|None)
attack_damage (str|None) — нотация урона ("1d6", "2d8+2") или "Special" или None
counterattack (str|None) — нотация урона при контратаке или None
qualities (list[str]) — список качеств: "Subtle", "Action", "Special"
description (str) — краткое описание эффекта актива
special_key (str|None) — ключ специального эффекта для wwn_mechanics.py или None
Вспомогательная функция:
get_asset(name) — найти актив по имени
get_assets_by_attribute(attr) — все активы для атрибута
get_available_assets(faction_data) — активы доступные фракции к покупке
"""
from typing import Optional
# ---------------------------------------------------------------------------
# Cunning Assets (стр. 328329 WWN)
# ---------------------------------------------------------------------------
CUNNING_ASSETS: list[dict] = [
# Tier 1
{
"name": "Informers",
"attribute": "Cunning", "tier_required": 1, "cost": 2, "hp_max": 3,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "Special",
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"Spend 1 Treasure as free action: Cunning vs Cunning against a chosen faction. "
"On success, all Stealthed assets of that faction within one move are revealed."
),
"special_key": "informers_reveal",
},
{
"name": "Petty Seers",
"attribute": "Cunning", "tier_required": 1, "cost": 2, "hp_max": 2,
"magic_required": "Medium",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "1d6",
"qualities": ["Subtle"],
"description": "Fortune-tellers and minor oracles; no attack, strong counterattack.",
"special_key": None,
},
{
"name": "Smugglers",
"attribute": "Cunning", "tier_required": 1, "cost": 2, "hp_max": 4,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Wealth",
"attack_damage": "1d4",
"counterattack": None,
"qualities": ["Subtle", "Action"],
"description": (
"Free action once per turn: move any allied Wealth or Cunning asset "
"in same location to destination within movement range, bypassing restrictions."
),
"special_key": "smugglers_move",
},
{
"name": "Useful Idiots",
"attribute": "Cunning", "tier_required": 1, "cost": 1, "hp_max": 2,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"If an allied asset within one move is struck, sacrifice Useful Idiots "
"to negate the attack. Only one band can be sacrificed per turn."
),
"special_key": "useful_idiots_sacrifice",
},
# Tier 2
{
"name": "Blackmail",
"attribute": "Cunning", "tier_required": 2, "cost": 4, "hp_max": 4,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "1d4",
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"While present, hostile factions can't roll more than one die during Attacks "
"made by or against them here, even with tags or assets granting bonus dice."
),
"special_key": "blackmail_suppress_dice",
},
{
"name": "Dancing Girls",
"attribute": "Cunning", "tier_required": 2, "cost": 4, "hp_max": 3,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Wealth",
"attack_damage": "2d4",
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"Immune to Attack or Counterattack damage from Force assets, "
"but cannot defend against Force asset attacks."
),
"special_key": "dancing_girls_force_immune",
},
{
"name": "Hired Friends",
"attribute": "Cunning", "tier_required": 2, "cost": 4, "hp_max": 4,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "1d6",
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"Free action once per turn: spend 1 Treasure to grant a Wealth asset "
"within one move the Subtle quality until Hired Friends move or are destroyed."
),
"special_key": "hired_friends_grant_subtle",
},
{
"name": "Saboteurs",
"attribute": "Cunning", "tier_required": 2, "cost": 5, "hp_max": 6,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Wealth",
"attack_damage": "2d4",
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"An asset attacked by Saboteurs can't use any free action abilities "
"next turn, regardless of attack success."
),
"special_key": "saboteurs_suppress_actions",
},
# Tier 3
{
"name": "Bewitching Charmer",
"attribute": "Cunning", "tier_required": 3, "cost": 6, "hp_max": 4,
"magic_required": "Low",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "Special",
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"On successful Attack: targeted asset cannot leave same location "
"until Charmer moves or is destroyed. Immune to Counterattack."
),
"special_key": "charmer_pin",
},
{
"name": "Covert Transport",
"attribute": "Cunning", "tier_required": 3, "cost": 8, "hp_max": 4,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"Free action once per turn: pay 1 Treasure to move any Cunning or Wealth "
"asset at same location; transported asset gains Stealth until used."
),
"special_key": "covert_transport_move",
},
{
"name": "Occult Infiltrators",
"attribute": "Cunning", "tier_required": 3, "cost": 6, "hp_max": 4,
"magic_required": "Medium",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "2d6",
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": "Magically gifted spies; always begin play with Stealth quality.",
"special_key": "occult_infiltrators_start_stealthed",
},
{
"name": "Spymaster",
"attribute": "Cunning", "tier_required": 3, "cost": 8, "hp_max": 4,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "1d6",
"counterattack": "2d6",
"qualities": ["Subtle"],
"description": "Veteran counterintelligence operative; strong counterattack.",
"special_key": None,
},
# Tier 4
{
"name": "Court Patronage",
"attribute": "Cunning", "tier_required": 4, "cost": 8, "hp_max": 8,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "1d6",
"counterattack": "1d6",
"qualities": ["Subtle", "Special"],
"description": "Automatically grants 1 Treasure to owning faction each turn.",
"special_key": "court_patronage_income",
},
{
"name": "Idealistic Thugs",
"attribute": "Cunning", "tier_required": 4, "cost": 8, "hp_max": 12,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Force",
"attack_damage": "1d6",
"counterattack": "1d6",
"qualities": ["Subtle"],
"description": "Easily-manipulated hotheads; high HP for a Cunning asset.",
"special_key": None,
},
{
"name": "Seditionists",
"attribute": "Cunning", "tier_required": 4, "cost": 12, "hp_max": 8,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": "Special",
"counterattack": None,
"qualities": ["Subtle"],
"description": (
"Instead of Attack: spend 1d4 Treasure to attach to a hostile asset in same location. "
"Until destroyed or moved, that asset cannot be used and grants no benefits."
),
"special_key": "seditionists_infest",
},
{
"name": "Vigilant Agents",
"attribute": "Cunning", "tier_required": 4, "cost": 12, "hp_max": 8,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "1d4",
"qualities": ["Subtle", "Special"],
"description": (
"When a Stealthed hostile asset moves into location within one move: "
"Cunning vs Cunning. On success, intruder loses Stealth after completing move."
),
"special_key": "vigilant_agents_detect",
},
# Tier 5
{
"name": "Cryptomancers",
"attribute": "Cunning", "tier_required": 5, "cost": 14, "hp_max": 6,
"magic_required": "Low",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "Special",
"counterattack": None,
"qualities": ["Subtle"],
"description": (
"Instead of Attack: Cunning vs Cunning against specific hostile asset within one move. "
"On success, target cannot act next turn. On failure, no counterattack."
),
"special_key": "cryptomancers_disable",
},
{
"name": "Organization Moles",
"attribute": "Cunning", "tier_required": 5, "cost": 8, "hp_max": 10,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "2d6",
"counterattack": None,
"qualities": ["Subtle"],
"description": "Sleeper agents deep in hostile organizations; no counterattack damage.",
"special_key": None,
},
{
"name": "Shapeshifters",
"attribute": "Cunning", "tier_required": 5, "cost": 14, "hp_max": 8,
"magic_required": "Medium",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "2d6",
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"Free action once per turn: spend 1 Treasure to gain Stealth quality."
),
"special_key": "shapeshifters_self_stealth",
},
# Tier 6
{
"name": "Interrupted Logistics",
"attribute": "Cunning", "tier_required": 6, "cost": 20, "hp_max": 10,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"Non-Stealthed hostile units cannot enter same location without "
"paying 1d4 Treasure and waiting one turn."
),
"special_key": "interrupted_logistics_toll",
},
{
"name": "Prophet",
"attribute": "Cunning", "tier_required": 6, "cost": 20, "hp_max": 10,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "2d8",
"counterattack": "1d8",
"qualities": ["Subtle"],
"description": "Charismatic prophet or rebel leader; powerful attack and counterattack.",
"special_key": None,
},
{
"name": "Underground Roads",
"attribute": "Cunning", "tier_required": 6, "cost": 18, "hp_max": 15,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"Free action: pay 1 Treasure to move any friendly asset from within "
"one move of Roads to another location within one move of Roads."
),
"special_key": "underground_roads_teleport",
},
# Tier 7
{
"name": "Expert Treachery",
"attribute": "Cunning", "tier_required": 7, "cost": 10, "hp_max": 5,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "Special",
"counterattack": None,
"qualities": ["Subtle"],
"description": (
"On successful Attack: this asset is lost, owning faction gains 5 Treasure, "
"and targeted asset switches sides (even if new owner lacks required attributes)."
),
"special_key": "expert_treachery_convert",
},
{
"name": "Mindbenders",
"attribute": "Cunning", "tier_required": 7, "cost": 20, "hp_max": 10,
"magic_required": "Medium",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "2d8",
"qualities": ["Subtle", "Special"],
"description": (
"Once per turn: force a rival faction to reroll any check they just made, "
"take whichever result Mindbenders prefer. A faction can only be affected once per turn."
),
"special_key": "mindbenders_reroll",
},
{
"name": "Popular Movement",
"attribute": "Cunning", "tier_required": 7, "cost": 25, "hp_max": 16,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "2d6",
"counterattack": "1d6",
"qualities": ["Subtle", "Special"],
"description": (
"Any friendly asset may move into same location as Popular Movement, "
"even if normally forbidden and lacking Subtle. If Popular Movement moves or is "
"destroyed, such assets must also leave or suffer usual consequences."
),
"special_key": "popular_movement_sanctuary",
},
# Tier 8
{
"name": "Just As Planned",
"attribute": "Cunning", "tier_required": 8, "cost": 40, "hp_max": 15,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "1d10",
"qualities": ["Subtle", "Special"],
"description": (
"When faction's assets make a Cunning roll: may reroll a failed check "
"at cost of 1d6 damage to Just As Planned. No range limit. May be used repeatedly."
),
"special_key": "just_as_planned_reroll",
},
{
"name": "Omniscient Seers",
"attribute": "Cunning", "tier_required": 8, "cost": 30, "hp_max": 10,
"magic_required": "High",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "1d8",
"qualities": ["Subtle", "Special"],
"description": (
"At start of turn: each hostile Stealthed asset within one move must succeed "
"Cunning vs Cunning or lose Stealth. Also grants extra Cunning die for all rolls "
"within one move."
),
"special_key": "omniscient_seers_mass_detect",
},
]
# ---------------------------------------------------------------------------
# Force Assets (стр. 330331 WWN)
# ---------------------------------------------------------------------------
FORCE_ASSETS: list[dict] = [
# Tier 1
{
"name": "Fearful Intimidation",
"attribute": "Force", "tier_required": 1, "cost": 2, "hp_max": 4,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "1d4",
"qualities": [],
"description": "Intimidation of locals; no attack, counterattack only.",
"special_key": None,
},
{
"name": "Local Guard",
"attribute": "Force", "tier_required": 1, "cost": 3, "hp_max": 4,
"magic_required": "None",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "1d3+1",
"counterattack": "1d4+1",
"qualities": [],
"description": "Citizen night watch and local guard units; better at defending.",
"special_key": None,
},
{
"name": "Summoned Hunter",
"attribute": "Force", "tier_required": 1, "cost": 4, "hp_max": 4,
"magic_required": "Medium",
"attack_attribute": "Cunning", "attack_vs": "Force",
"attack_damage": "1d6",
"counterattack": None,
"qualities": ["Subtle"],
"description": "Magically summoned or bound assassin-beast; begins play Stealthed.",
"special_key": "summoned_hunter_start_stealthed",
},
{
"name": "Thugs",
"attribute": "Force", "tier_required": 1, "cost": 2, "hp_max": 1,
"magic_required": "None",
"attack_attribute": "Force", "attack_vs": "Cunning",
"attack_damage": "1d6",
"counterattack": None,
"qualities": ["Subtle"],
"description": "Gutter ruffians and common kneebreakers; very fragile.",
"special_key": None,
},
# Tier 2
{
"name": "Guerrilla Populace",
"attribute": "Force", "tier_required": 2, "cost": 6, "hp_max": 4,
"magic_required": "None",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "1d4+1",
"counterattack": None,
"qualities": [],
"description": "Locals trained in guerrilla warfare; good against supply lines.",
"special_key": None,
},
{
"name": "Military Transport",
"attribute": "Force", "tier_required": 2, "cost": 4, "hp_max": 6,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": None,
"qualities": ["Action"],
"description": (
"Free action once per turn: bring an allied asset to its location or "
"move an allied asset from its location, within one move. Can chain movement."
),
"special_key": "military_transport_move",
},
{
"name": "Reserve Corps",
"attribute": "Force", "tier_required": 2, "cost": 4, "hp_max": 4,
"magic_required": "None",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "1d6",
"counterattack": "1d6",
"qualities": [],
"description": "Retired military personnel spread through area as colonists.",
"special_key": None,
},
{
"name": "Scouts",
"attribute": "Force", "tier_required": 2, "cost": 5, "hp_max": 5,
"magic_required": "None",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "2d4",
"counterattack": "1d4+1",
"qualities": ["Subtle"],
"description": "Long-range scouts and reconnaissance experts.",
"special_key": None,
},
# Tier 3
{
"name": "Enchanted Elites",
"attribute": "Force", "tier_required": 3, "cost": 8, "hp_max": 6,
"magic_required": "Medium",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "1d10",
"counterattack": "1d6",
"qualities": ["Subtle"],
"description": "Magically armed and blessed warriors; strong attack.",
"special_key": None,
},
{
"name": "Infantry",
"attribute": "Force", "tier_required": 3, "cost": 6, "hp_max": 6,
"magic_required": "None",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "1d8",
"counterattack": "1d6",
"qualities": [],
"description": "Common foot soldiers; reliable and numerous.",
"special_key": None,
},
{
"name": "Temple Fanatics",
"attribute": "Force", "tier_required": 3, "cost": 4, "hp_max": 6,
"magic_required": "None",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "2d6",
"counterattack": "2d6",
"qualities": ["Special"],
"description": (
"After every time they defend or successfully attack, take 1d4 damage. "
"High damage both ways."
),
"special_key": "temple_fanatics_self_damage",
},
{
"name": "Witch Hunters",
"attribute": "Force", "tier_required": 3, "cost": 6, "hp_max": 4,
"magic_required": "Low",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "1d4+1",
"counterattack": "1d6",
"qualities": [],
"description": "Trained to find traitors, spies and hostile magic.",
"special_key": None,
},
# Tier 4
{
"name": "Cavalry",
"attribute": "Force", "tier_required": 4, "cost": 8, "hp_max": 12,
"magic_required": "None",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "2d6",
"counterattack": "1d4",
"qualities": [],
"description": "Mounted troops; weak on defense, powerful charges.",
"special_key": None,
},
{
"name": "Military Roads",
"attribute": "Force", "tier_required": 4, "cost": 10, "hp_max": 10,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": None,
"qualities": ["Action"],
"description": (
"Logistical road network. Once per turn: move any one asset from any location "
"within reach to any other within reach for 1 Treasure."
),
"special_key": "military_roads_network",
},
{
"name": "Vanguard Unit",
"attribute": "Force", "tier_required": 4, "cost": 10, "hp_max": 10,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "1d6",
"qualities": ["Action"],
"description": (
"During Relocate Asset action: can move itself and allied units at same location "
"to any location within range, even normally-prohibited ones."
),
"special_key": "vanguard_forced_march",
},
{
"name": "War Fleet",
"attribute": "Force", "tier_required": 4, "cost": 12, "hp_max": 8,
"magic_required": "None",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "2d6",
"counterattack": "1d8",
"qualities": ["Action"],
"description": (
"Can only attack assets/locations reachable by waterways. "
"Once per turn: freely relocate to any coastal area within movement range."
),
"special_key": "war_fleet_coastal",
},
# Tier 5
{
"name": "Demonic Slayer",
"attribute": "Force", "tier_required": 5, "cost": 12, "hp_max": 4,
"magic_required": "High",
"attack_attribute": "Cunning", "attack_vs": "Cunning",
"attack_damage": "2d6+2",
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": "Summoned inhuman assassin-beast; enters play Stealthed.",
"special_key": "demonic_slayer_start_stealthed",
},
{
"name": "Magical Logistics",
"attribute": "Force", "tier_required": 5, "cost": 14, "hp_max": 6,
"magic_required": "Medium",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": None,
"qualities": ["Special"],
"description": (
"Once per faction turn as free action: repair 2 hit points of damage "
"to an allied Force asset."
),
"special_key": "magical_logistics_repair",
},
{
"name": "Siege Experts",
"attribute": "Force", "tier_required": 5, "cost": 10, "hp_max": 8,
"magic_required": "None",
"attack_attribute": "Force", "attack_vs": "Wealth",
"attack_damage": "1d6",
"counterattack": "1d6",
"qualities": [],
"description": (
"On successful Attack: target's owner loses 1d4 Treasure and this faction gains it."
),
"special_key": "siege_experts_loot",
},
# Tier 6
{
"name": "Fortification Program",
"attribute": "Force", "tier_required": 6, "cost": 20, "hp_max": 18,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "2d6",
"qualities": ["Action"],
"description": (
"Once per turn: when enemy makes Attack targeting faction's Force rating, "
"can use Fortification Program to defend if within one move of attack."
),
"special_key": "fortification_intercept",
},
{
"name": "Knights",
"attribute": "Force", "tier_required": 6, "cost": 18, "hp_max": 16,
"magic_required": "None",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "2d8",
"counterattack": "2d6",
"qualities": [],
"description": "Elite warriors of considerable personal prowess.",
"special_key": None,
},
{
"name": "War Machines",
"attribute": "Force", "tier_required": 6, "cost": 25, "hp_max": 14,
"magic_required": "Medium",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "2d10+4",
"counterattack": "1d10",
"qualities": [],
"description": "Mobile war machines driven by beasts or magical motive power.",
"special_key": None,
},
# Tier 7
{
"name": "Brilliant General",
"attribute": "Force", "tier_required": 7, "cost": 25, "hp_max": 8,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Force",
"attack_damage": "1d8",
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"When Brilliant General or any allied Force asset in same location "
"Attacks or defends, it rolls an extra die."
),
"special_key": "brilliant_general_extra_die",
},
{
"name": "Purity Rites",
"attribute": "Force", "tier_required": 7, "cost": 20, "hp_max": 10,
"magic_required": "Low",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "2d8+2",
"qualities": ["Special"],
"description": (
"Can only defend against attacks targeting faction's Cunning. "
"Allows faction to roll extra die to defend."
),
"special_key": "purity_rites_cunning_defense",
},
{
"name": "Warshaped",
"attribute": "Force", "tier_required": 7, "cost": 30, "hp_max": 16,
"magic_required": "High",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "2d8+2",
"counterattack": "2d8",
"qualities": ["Subtle"],
"description": "Magically altered creatures designed for warfare; elusive.",
"special_key": None,
},
# Tier 8
{
"name": "Apocalypse Engine",
"attribute": "Force", "tier_required": 8, "cost": 35, "hp_max": 20,
"magic_required": "Medium",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "3d10+4",
"counterattack": None,
"qualities": [],
"description": "Ancient super-weapon; devastating attack, no counterattack.",
"special_key": None,
},
{
"name": "Invincible Legion",
"attribute": "Force", "tier_required": 8, "cost": 40, "hp_max": 30,
"magic_required": "None",
"attack_attribute": "Force", "attack_vs": "Force",
"attack_damage": "2d10+4",
"counterattack": "2d10+4",
"qualities": ["Special"],
"description": (
"During Relocate Asset: can move to locations normally prohibited for military, "
"as if it had Subtle. It is not actually subtle."
),
"special_key": "invincible_legion_forced_entry",
},
]
# ---------------------------------------------------------------------------
# Wealth Assets (стр. 332333 WWN)
# ---------------------------------------------------------------------------
WEALTH_ASSETS: list[dict] = [
# Tier 1
{
"name": "Armed Guards",
"attribute": "Wealth", "tier_required": 1, "cost": 1, "hp_max": 3,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Force",
"attack_damage": "1d3",
"counterattack": "1d4",
"qualities": [],
"description": "Hired caravan guards and bodyguards.",
"special_key": None,
},
{
"name": "Cooperative Businesses",
"attribute": "Wealth", "tier_required": 1, "cost": 1, "hp_max": 2,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Wealth",
"attack_damage": "1d4-1",
"counterattack": None,
"qualities": ["Subtle", "Special"],
"description": (
"If any other faction attempts to create an asset in same location, "
"cost increases by 1 Treasure. Penalty stacks."
),
"special_key": "cooperative_businesses_price_hike",
},
{
"name": "Farmers",
"attribute": "Wealth", "tier_required": 1, "cost": 2, "hp_max": 4,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "1d4",
"qualities": ["Action"],
"description": (
"Once per turn as free action: roll 1d6; on 5+ gain 1 Treasure."
),
"special_key": "farmers_income",
},
{
"name": "Front Merchant",
"attribute": "Wealth", "tier_required": 1, "cost": 2, "hp_max": 3,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Wealth",
"attack_damage": "1d4",
"counterattack": "1d4-1",
"qualities": ["Subtle"],
"description": (
"On successful Attack: target faction loses 1 Treasure (if any), "
"Front Merchant's owner gains it. Once per turn."
),
"special_key": "front_merchant_steal",
},
# Tier 2
{
"name": "Caravan",
"attribute": "Wealth", "tier_required": 2, "cost": 5, "hp_max": 4,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Wealth",
"attack_damage": "1d4",
"counterattack": None,
"qualities": ["Action"],
"description": (
"Free action once per turn: spend 1 Treasure to move itself and "
"one other asset in same place to new location within one move."
),
"special_key": "caravan_move",
},
{
"name": "Dragomans",
"attribute": "Wealth", "tier_required": 2, "cost": 4, "hp_max": 4,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "1d4",
"qualities": ["Subtle", "Special"],
"description": (
"Faction taking Expand Influence in same location rolls extra die on all checks. "
"Free action once per turn: this asset can move."
),
"special_key": "dragomans_expand_bonus",
},
{
"name": "Pleaders",
"attribute": "Wealth", "tier_required": 2, "cost": 6, "hp_max": 4,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Wealth",
"attack_damage": "2d4",
"counterattack": "1d6",
"qualities": ["Special"],
"description": (
"Can turn local laws against enemies. Cannot Attack or inflict Counterattack "
"damage on Force assets."
),
"special_key": "pleaders_no_force",
},
{
"name": "Worker Mob",
"attribute": "Wealth", "tier_required": 2, "cost": 4, "hp_max": 6,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Force",
"attack_damage": "1d4+1",
"counterattack": "1d4",
"qualities": [],
"description": "Organized brutal laborers for disciplining enemies.",
"special_key": None,
},
# Tier 3
{
"name": "Ancient Mechanisms",
"attribute": "Wealth", "tier_required": 3, "cost": 8, "hp_max": 4,
"magic_required": "Medium",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": None,
"qualities": ["Special"],
"description": (
"When an asset in same location rolls to make a profit (Farmers, Manufactory), "
"roll the die twice and take the better result."
),
"special_key": "ancient_mechanisms_reroll",
},
{
"name": "Arcane Laboratory",
"attribute": "Wealth", "tier_required": 3, "cost": 6, "hp_max": 4,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": None,
"qualities": ["Special"],
"description": (
"Faction's overall Magic is counted as one step higher for creating assets "
"in same location. Multiple labs stack."
),
"special_key": "arcane_lab_magic_boost",
},
{
"name": "Free Company",
"attribute": "Wealth", "tier_required": 3, "cost": 8, "hp_max": 6,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Force",
"attack_damage": "2d4+2",
"counterattack": "1d6",
"qualities": ["Action", "Special"],
"description": (
"Free action once per turn: move itself. "
"Costs 1 Treasure upkeep per turn; if unpaid roll 1d6: 13 lost, 46 goes rogue."
),
"special_key": "free_company_upkeep",
},
{
"name": "Manufactory",
"attribute": "Wealth", "tier_required": 3, "cost": 8, "hp_max": 4,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "1d4",
"qualities": ["Action"],
"description": (
"Once per turn as free action: roll 1d6: "
"1 = lose 1 Treasure, 25 = gain 1 Treasure, 6 = gain 2 Treasure. "
"If Treasure lost and none available, asset is lost."
),
"special_key": "manufactory_gamble",
},
# Tier 4
{
"name": "Healers",
"attribute": "Wealth", "tier_required": 4, "cost": 12, "hp_max": 8,
"magic_required": "None",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": None,
"qualities": ["Action"],
"description": (
"When an asset within one move is destroyed by Force attack: "
"pay half its purchase cost (rounded up) to instantly restore it with 1 HP. "
"Cannot restore Bases of Influence."
),
"special_key": "healers_revive",
},
{
"name": "Monopoly",
"attribute": "Wealth", "tier_required": 4, "cost": 8, "hp_max": 12,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Wealth",
"attack_damage": "1d6",
"counterattack": "1d6",
"qualities": ["Action"],
"description": (
"Once per turn as free action: target an asset in same location; "
"that asset's owner must pay 1 Treasure to owning faction or lose the asset."
),
"special_key": "monopoly_extort",
},
{
"name": "Occult Countermeasures",
"attribute": "Wealth", "tier_required": 4, "cost": 10, "hp_max": 8,
"magic_required": "Low",
"attack_attribute": "Wealth", "attack_vs": "Cunning",
"attack_damage": "2d10",
"counterattack": "1d10",
"qualities": ["Special"],
"description": (
"Can only Attack or Counterattack assets that require at least Low Magic to purchase."
),
"special_key": "occult_countermeasures_magic_only",
},
{
"name": "Usurers",
"attribute": "Wealth", "tier_required": 4, "cost": 12, "hp_max": 8,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Wealth",
"attack_damage": "1d10",
"counterattack": None,
"qualities": ["Action"],
"description": (
"For each unit of Usurers owned: Treasure cost of buying assets may be decreased "
"by 2 (to minimum half cost). Each use inflicts 1d4 damage on Usurers."
),
"special_key": "usurers_discount",
},
# Tier 5
{
"name": "Mad Genius",
"attribute": "Wealth", "tier_required": 5, "cost": 6, "hp_max": 2,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Cunning",
"attack_damage": "1d6",
"counterattack": None,
"qualities": ["Action"],
"description": (
"Free action once per turn: move. "
"Free action once per turn: sacrifice to treat Magic in its location as High "
"for purpose of buying one asset."
),
"special_key": "mad_genius_magic_sacrifice",
},
{
"name": "Smuggling Fleet",
"attribute": "Wealth", "tier_required": 5, "cost": 12, "hp_max": 6,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Force",
"attack_damage": "2d6",
"counterattack": None,
"qualities": ["Subtle", "Action"],
"description": (
"Once per turn as free action: move itself and any one asset at current location "
"to any water-accessible location within one move. Moved asset gains Subtle until used."
),
"special_key": "smuggling_fleet_move",
},
{
"name": "Supply Interruption",
"attribute": "Wealth", "tier_required": 5, "cost": 10, "hp_max": 8,
"magic_required": "None",
"attack_attribute": "Cunning", "attack_vs": "Wealth",
"attack_damage": "1d6",
"counterattack": None,
"qualities": ["Subtle", "Action"],
"description": (
"Free action once per turn: Cunning vs Wealth check against asset in same location. "
"On success: owner must sacrifice Treasure equal to half target's purchase cost, "
"or asset is disabled until paid."
),
"special_key": "supply_interruption_disable",
},
# Tier 6
{
"name": "Economic Disruption",
"attribute": "Wealth", "tier_required": 6, "cost": 25, "hp_max": 10,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Wealth",
"attack_damage": "2d6",
"counterattack": None,
"qualities": ["Subtle", "Action"],
"description": "Free action once per turn: move itself without cost.",
"special_key": "economic_disruption_free_move",
},
{
"name": "Merchant Prince",
"attribute": "Wealth", "tier_required": 6, "cost": 20, "hp_max": 10,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Wealth",
"attack_damage": "2d8",
"counterattack": "1d8",
"qualities": ["Action"],
"description": (
"Free action once per turn before buying asset in same location: "
"Merchant Prince takes 1d4 damage, purchased asset costs 1d8 less "
"(to minimum half normal price)."
),
"special_key": "merchant_prince_discount",
},
{
"name": "Trade Company",
"attribute": "Wealth", "tier_required": 6, "cost": 15, "hp_max": 10,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Wealth",
"attack_damage": "2d6",
"counterattack": "1d6",
"qualities": ["Action"],
"description": (
"Free action once per turn: accept 1d4 damage to earn 1d6-1 Treasure."
),
"special_key": "trade_company_risk",
},
# Tier 7
{
"name": "Ancient Workshop",
"attribute": "Wealth", "tier_required": 7, "cost": 25, "hp_max": 16,
"magic_required": "Medium",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": None,
"qualities": [],
"description": (
"Free action once per turn: take 1d6 damage and gain 1d6 Treasure."
),
"special_key": "ancient_workshop_produce",
},
{
"name": "Lead or Silver",
"attribute": "Wealth", "tier_required": 7, "cost": 20, "hp_max": 10,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Wealth",
"attack_damage": "2d10",
"counterattack": "2d8",
"qualities": [],
"description": (
"If Attack reduces enemy asset to 0 HP: owner may immediately pay "
"half target's purchase cost to claim it, reviving with 1 HP."
),
"special_key": "lead_or_silver_capture",
},
{
"name": "Transport Network",
"attribute": "Wealth", "tier_required": 7, "cost": 15, "hp_max": 5,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Wealth",
"attack_damage": "1d12",
"counterattack": None,
"qualities": ["Action"],
"description": (
"Free action: spend 1 Treasure to move any friendly asset from within "
"two moves to any location within one move of either target or Network."
),
"special_key": "transport_network_relay",
},
# Tier 8
{
"name": "Golden Prosperity",
"attribute": "Wealth", "tier_required": 8, "cost": 40, "hp_max": 30,
"magic_required": "Medium",
"attack_attribute": None, "attack_vs": None,
"attack_damage": None,
"counterattack": "2d10",
"qualities": [],
"description": (
"Each turn as free action: gain 1d6 Treasure usable only to repair damaged assets. "
"Unspent Treasure from this ability is lost."
),
"special_key": "golden_prosperity_repair_fund",
},
{
"name": "Hired Legion",
"attribute": "Wealth", "tier_required": 8, "cost": 30, "hp_max": 20,
"magic_required": "None",
"attack_attribute": "Wealth", "attack_vs": "Force",
"attack_damage": "2d10+4",
"counterattack": "2d10",
"qualities": ["Action", "Special"],
"description": (
"Free action once per turn: move itself. "
"Costs 2 Treasure upkeep per turn; if unpaid goes rogue as Free Company. "
"Cannot be voluntarily sold or disbanded."
),
"special_key": "hired_legion_upkeep",
},
]
# ---------------------------------------------------------------------------
# Объединённый справочник и вспомогательные функции
# ---------------------------------------------------------------------------
ALL_ASSETS: list[dict] = CUNNING_ASSETS + FORCE_ASSETS + WEALTH_ASSETS
# Индекс по имени для быстрого поиска O(1)
_ASSET_INDEX: dict[str, dict] = {a["name"]: a for a in ALL_ASSETS}
# Числовые уровни magic для сравнения
MAGIC_LEVELS: dict[str, int] = {
"None": 0,
"Low": 1,
"Medium": 2,
"High": 3,
}
def get_asset(name: str) -> Optional[dict]:
"""
Возвращает определение актива по точному имени или None.
Поиск регистрозависимый — имена активов уникальны и зафиксированы.
"""
return _ASSET_INDEX.get(name)
def get_assets_by_attribute(attribute: str) -> list[dict]:
"""
Возвращает все активы для указанного атрибута.
attribute — "Cunning" | "Force" | "Wealth"
"""
return [a for a in ALL_ASSETS if a["attribute"] == attribute]
def get_available_assets(
faction_fm: dict,
location_wikilink: str,
) -> list[dict]:
"""
Возвращает список активов доступных фракции для покупки прямо сейчас.
Проверяет все условия WWN:
1. faction.attribute >= asset.tier_required
2. faction.magic >= asset.magic_required
3. faction.treasure >= asset.cost
4. Текущее количество активов этого атрибута < значение атрибута
(лимит: не более Force Force-активов, не более Wealth Wealth-активов и т.д.)
5. Фракция имеет Base of Influence в location_wikilink
6. У фракции ещё нет актива с таким именем
faction_fm — frontmatter фракции из get_faction()
location_wikilink — '[[Waterdeep]]' — место где есть BoI
"""
import re as _re
def _norm(s: str) -> str:
return _re.sub(r'^\[\[|\]\]$', '', s).split('|')[0].strip().lower()
loc_norm = _norm(location_wikilink)
# Проверяем наличие BoI в локации
has_boi = any(
a.get("is_base_of_influence") and _norm(a.get("location", "")) == loc_norm
for a in faction_fm.get("assets", [])
)
if not has_boi:
return []
# Текущие активы фракции
owned = faction_fm.get("assets", [])
owned_names = {a["name"] for a in owned}
# Считаем сколько активов каждого атрибута уже есть
attr_counts: dict[str, int] = {"Cunning": 0, "Force": 0, "Wealth": 0}
for a in owned:
attr = a.get("attribute")
if attr in attr_counts:
attr_counts[attr] += 1
faction_magic_level = MAGIC_LEVELS.get(faction_fm.get("magic", "None"), 0)
treasure = faction_fm.get("treasure", 0)
result = []
for asset_def in ALL_ASSETS:
attr = asset_def["attribute"]
tier_req = asset_def["tier_required"]
# Условие 1: атрибут достаточен
if faction_fm.get(attr.lower(), 0) < tier_req:
continue
# Условие 2: magic достаточен
asset_magic_level = MAGIC_LEVELS.get(asset_def["magic_required"], 0)
if faction_magic_level < asset_magic_level:
continue
# Условие 3: хватает Treasure
if treasure < asset_def["cost"]:
continue
# Условие 4: не превышен лимит активов атрибута
attr_limit = faction_fm.get(attr.lower(), 0)
if attr_counts.get(attr, 0) >= attr_limit:
continue
# Условие 5: BoI уже проверен выше
# Условие 6: актив ещё не куплен
if asset_def["name"] in owned_names:
continue
result.append(asset_def)
return result