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>
This commit is contained in:
empty
2025-12-30 13:25:20 +08:00
parent 62b4428cf1
commit 3f75eb26c4
5 changed files with 215 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
"""阵营技能树系统 - 允许阵营通过累积能量解锁技能"""
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)