- Add FactionData model with power and members fields - Add FactionEventResult model for faction event responses - Add faction field to AgentState - Implement faction classification based on emotion - Add faction event triggers (festival/panic) when power >= 5 - Update StepResponse to include triggered_faction_event - Add tests for new faction system 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
139 lines
4.3 KiB
Python
139 lines
4.3 KiB
Python
"""派系系统 - 基于立场分类角色并影响世界"""
|
||
from typing import Dict, Tuple
|
||
from .models import (
|
||
WorldState, AgentState, Factions, FactionData,
|
||
FactionEventResult, WorldEffect, Emotion
|
||
)
|
||
|
||
# 派系分类阈值
|
||
OPTIMIST_THRESHOLD = 0.6
|
||
FEARFUL_THRESHOLD = 0.6
|
||
|
||
# 阵营技能触发阈值
|
||
FACTION_POWER_THRESHOLD = 5
|
||
|
||
# 阵营事件对情绪的影响
|
||
FACTION_EVENT_EFFECTS = {
|
||
"festival": 0.2, # 乐观派事件提升情绪
|
||
"panic": -0.3, # 恐惧派事件降低情绪
|
||
}
|
||
|
||
|
||
def classify_faction(agent: AgentState) -> str:
|
||
"""根据 emotion 分类角色所属派系
|
||
|
||
规则:
|
||
- emotion 偏正 (happy) → optimists
|
||
- emotion 偏负 (anxious) → fearful
|
||
- 其它 (calm) → neutral
|
||
"""
|
||
if agent.emotion == Emotion.HAPPY:
|
||
return "optimists"
|
||
elif agent.emotion == Emotion.ANXIOUS:
|
||
return "fearful"
|
||
else:
|
||
return "neutral"
|
||
|
||
|
||
def update_factions(state: WorldState) -> None:
|
||
"""统计各派系并更新 world_state
|
||
|
||
流程:
|
||
1. 清空 factions.members
|
||
2. 遍历所有 agents,根据 emotion 分类
|
||
3. 更新 agent.faction 字段
|
||
4. 将 agent 加入对应 faction.members
|
||
5. 每个 agent 为 faction 增加 power += 1
|
||
"""
|
||
# 重置 factions
|
||
state.factions = Factions(
|
||
optimists=FactionData(power=0, members=[]),
|
||
fearful=FactionData(power=0, members=[])
|
||
)
|
||
|
||
for agent_id, agent in state.agents.items():
|
||
faction = classify_faction(agent)
|
||
agent.faction = faction
|
||
|
||
if faction == "optimists":
|
||
state.factions.optimists.members.append(agent_id)
|
||
state.factions.optimists.power += 1
|
||
elif faction == "fearful":
|
||
state.factions.fearful.members.append(agent_id)
|
||
state.factions.fearful.power += 1
|
||
# neutral 不加入任何派系
|
||
|
||
|
||
def apply_faction_influence(state: WorldState) -> None:
|
||
"""派系分布影响世界情绪(保留原有逻辑)"""
|
||
optimists = state.factions.optimists.power
|
||
fearful = state.factions.fearful.power
|
||
|
||
if optimists > fearful:
|
||
state.town_mood = min(10, state.town_mood + 1)
|
||
elif fearful > optimists:
|
||
state.town_mood = max(-10, state.town_mood - 1)
|
||
|
||
|
||
def check_and_trigger_faction_event(state: WorldState) -> FactionEventResult:
|
||
"""检查并触发阵营事件
|
||
|
||
规则:
|
||
- 当 faction.power >= 5 时,触发对应世界事件
|
||
- optimists → festival(提升情绪)
|
||
- fearful → panic(降低情绪)
|
||
- 触发后该 faction.power 归零
|
||
"""
|
||
result = FactionEventResult(type=None, source_faction=None)
|
||
|
||
# 检查乐观派
|
||
if state.factions.optimists.power >= FACTION_POWER_THRESHOLD:
|
||
result = FactionEventResult(type="festival", source_faction="optimists")
|
||
_apply_faction_event(state, "festival")
|
||
state.factions.optimists.power = 0
|
||
|
||
# 检查恐惧派
|
||
elif state.factions.fearful.power >= FACTION_POWER_THRESHOLD:
|
||
result = FactionEventResult(type="panic", source_faction="fearful")
|
||
_apply_faction_event(state, "panic")
|
||
state.factions.fearful.power = 0
|
||
|
||
return result
|
||
|
||
|
||
def _apply_faction_event(state: WorldState, event_type: str) -> None:
|
||
"""应用阵营事件效果
|
||
|
||
1. 创建 WorldEffect 写入 world_state.world_effects
|
||
2. 影响所有 agent 的 emotion
|
||
"""
|
||
# 创建持续影响效果
|
||
if event_type == "festival":
|
||
effect = WorldEffect(
|
||
type="faction_event",
|
||
name="节日庆典",
|
||
intensity=1,
|
||
remaining_ticks=3,
|
||
mood_modifier=1
|
||
)
|
||
else: # panic
|
||
effect = WorldEffect(
|
||
type="faction_event",
|
||
name="恐慌蔓延",
|
||
intensity=1,
|
||
remaining_ticks=3,
|
||
mood_modifier=-1
|
||
)
|
||
|
||
state.world_effects.append(effect)
|
||
|
||
# 影响所有 agent 的 stance(间接影响下一轮 emotion)
|
||
emotion_delta = FACTION_EVENT_EFFECTS.get(event_type, 0)
|
||
for agent in state.agents.values():
|
||
if emotion_delta > 0:
|
||
agent.stance.optimism = min(1.0, agent.stance.optimism + emotion_delta)
|
||
agent.stance.fear = max(0.0, agent.stance.fear - emotion_delta * 0.5)
|
||
else:
|
||
agent.stance.fear = min(1.0, agent.stance.fear + abs(emotion_delta))
|
||
agent.stance.optimism = max(0.0, agent.stance.optimism - abs(emotion_delta) * 0.5)
|