Files
ai-town/engine-python/app/faction_skills.py
empty 3f75eb26c4 feat(engine): 实现阵营技能树系统
- 新增 FactionSkill、FactionSkillTree、FactionSkills 数据模型
- 创建 faction_skills.py 模块处理技能解锁和效果应用
- 技能解锁条件:power >= cost 且前置技能已解锁
- 技能效果:increase_positive_emotion、reduce_conflict、increase_fear、suppress_others
- 添加 4 个技能树测试用例,全部 30 个测试通过

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 13:25:20 +08:00

127 lines
4.0 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.
"""阵营技能树系统 - 允许阵营通过累积能量解锁技能"""
from typing import List, Optional
from .models import (
WorldState, FactionSkill, FactionSkillTree, FactionSkills
)
def get_default_faction_skills() -> FactionSkills:
"""返回默认技能树配置"""
return FactionSkills(
optimists=FactionSkillTree(
skills={
"festival_boost": FactionSkill(
unlocked=False,
cost=10,
effect="increase_positive_emotion",
requires=[]
),
"unity": FactionSkill(
unlocked=False,
cost=20,
effect="reduce_conflict",
requires=["festival_boost"]
)
}
),
fearful=FactionSkillTree(
skills={
"panic_spread": FactionSkill(
unlocked=False,
cost=10,
effect="increase_fear",
requires=[]
),
"control": FactionSkill(
unlocked=False,
cost=20,
effect="suppress_others",
requires=["panic_spread"]
)
}
)
)
def _check_requires_met(skill_tree: FactionSkillTree, requires: List[str]) -> bool:
"""检查前置技能是否已解锁"""
for req in requires:
if req not in skill_tree.skills:
return False
if not skill_tree.skills[req].unlocked:
return False
return True
def check_and_unlock_skills(state: WorldState) -> List[str]:
"""检查并解锁技能
规则:
1. faction.power >= skill.cost
2. 技能尚未解锁
3. 所有 requires 已解锁
返回:本次解锁的技能列表
"""
unlocked = []
# 检查乐观派技能
for skill_id, skill in state.faction_skills.optimists.skills.items():
if skill.unlocked:
continue
if state.factions.optimists.power < skill.cost:
continue
if not _check_requires_met(state.faction_skills.optimists, skill.requires):
continue
# 解锁技能
skill.unlocked = True
state.factions.optimists.power -= skill.cost
unlocked.append(f"optimists:{skill_id}")
# 检查恐惧派技能
for skill_id, skill in state.faction_skills.fearful.skills.items():
if skill.unlocked:
continue
if state.factions.fearful.power < skill.cost:
continue
if not _check_requires_met(state.faction_skills.fearful, skill.requires):
continue
# 解锁技能
skill.unlocked = True
state.factions.fearful.power -= skill.cost
unlocked.append(f"fearful:{skill_id}")
return unlocked
def apply_skill_effects(state: WorldState) -> None:
"""应用已解锁技能的持续效果
效果说明:
- increase_positive_emotion: 每 tick 提升 town_mood +1
- reduce_conflict: 降低恐惧派能量增长(每 tick -1
- increase_fear: 每 tick 降低 town_mood -1
- suppress_others: 降低乐观派能量增长(每 tick -1
"""
# 乐观派技能效果
for skill_id, skill in state.faction_skills.optimists.skills.items():
if not skill.unlocked:
continue
if skill.effect == "increase_positive_emotion":
state.town_mood = min(10, state.town_mood + 1)
elif skill.effect == "reduce_conflict":
state.factions.fearful.power = max(0, state.factions.fearful.power - 1)
# 恐惧派技能效果
for skill_id, skill in state.faction_skills.fearful.skills.items():
if not skill.unlocked:
continue
if skill.effect == "increase_fear":
state.town_mood = max(-10, state.town_mood - 1)
elif skill.effect == "suppress_others":
state.factions.optimists.power = max(0, state.factions.optimists.power - 1)