- 新增 Stance 数据结构 (optimism/fear) - 情绪影响 stance (happy→乐观, anxious→恐惧) - 实现 apply_social_influence 社交影响函数 - 确定性随机选择接触对象 - 单次变化限制 ±0.1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
188 lines
5.5 KiB
Python
188 lines
5.5 KiB
Python
"""角色事件评论系统 - 基于规则生成观点"""
|
||
from typing import Dict, List, Optional
|
||
from .models import WorldState, AgentState, Opinion, Emotion, WorldEffect, Stance
|
||
|
||
# 情绪对 stance 的影响
|
||
EMOTION_STANCE_EFFECTS: Dict[str, Dict[str, float]] = {
|
||
"happy": {"optimism": 0.1, "fear": -0.05},
|
||
"calm": {"optimism": 0.0, "fear": 0.0},
|
||
"anxious": {"optimism": -0.05, "fear": 0.1},
|
||
}
|
||
|
||
|
||
# 观点模板:effect_type -> emotion -> 观点列表
|
||
OPINION_TEMPLATES: Dict[str, Dict[str, List[str]]] = {
|
||
"festival": {
|
||
"happy": [
|
||
"这真是个让人开心的日子!",
|
||
"节日的气氛太棒了!",
|
||
"大家都在庆祝,真好!",
|
||
],
|
||
"calm": [
|
||
"节日挺热闹的。",
|
||
"看来大家都很高兴。",
|
||
"难得的庆典活动。",
|
||
],
|
||
"anxious": [
|
||
"我不太确定这是不是好事...",
|
||
"人太多了,有点不安。",
|
||
"希望一切顺利吧。",
|
||
],
|
||
},
|
||
"storm": {
|
||
"happy": [
|
||
"暴风雨也有它的美!",
|
||
"待在室内也挺好的。",
|
||
"雨声其实很治愈。",
|
||
],
|
||
"calm": [
|
||
"暴风雨来了,注意安全。",
|
||
"等雨停了再出门吧。",
|
||
"天气变化无常啊。",
|
||
],
|
||
"anxious": [
|
||
"这暴风雨让我很担心...",
|
||
"情况看起来不太妙。",
|
||
"希望大家都平安。",
|
||
],
|
||
},
|
||
"scandal": {
|
||
"happy": [
|
||
"不管怎样,生活还要继续!",
|
||
"真相总会大白的。",
|
||
"保持乐观吧。",
|
||
],
|
||
"calm": [
|
||
"这件事确实令人意外。",
|
||
"让我们静观其变。",
|
||
"事情总会解决的。",
|
||
],
|
||
"anxious": [
|
||
"这消息太令人震惊了...",
|
||
"不知道接下来会怎样。",
|
||
"小镇的未来让人担忧。",
|
||
],
|
||
},
|
||
"miracle": {
|
||
"happy": [
|
||
"太神奇了!这是奇迹!",
|
||
"彩虹真的太美了!",
|
||
"今天是幸运的一天!",
|
||
],
|
||
"calm": [
|
||
"难得一见的景象。",
|
||
"大自然真是神奇。",
|
||
"值得记住的时刻。",
|
||
],
|
||
"anxious": [
|
||
"希望这是好兆头...",
|
||
"美丽的景象,但愿能持续。",
|
||
"也许事情会好转吧。",
|
||
],
|
||
},
|
||
"fire": {
|
||
"happy": [
|
||
"消防队很快就会控制住的!",
|
||
"大家齐心协力,一定没问题!",
|
||
"相信我们能度过难关!",
|
||
],
|
||
"calm": [
|
||
"火灾很危险,大家要小心。",
|
||
"希望没有人受伤。",
|
||
"消防队正在处理。",
|
||
],
|
||
"anxious": [
|
||
"情况变得不妙,我得小心...",
|
||
"火灾太可怕了...",
|
||
"希望大家都能平安。",
|
||
],
|
||
},
|
||
}
|
||
|
||
# 默认观点(未知事件类型)
|
||
DEFAULT_OPINIONS: Dict[str, List[str]] = {
|
||
"happy": ["不管发生什么,保持乐观!"],
|
||
"calm": ["让我们看看会怎样。"],
|
||
"anxious": ["不知道这意味着什么..."],
|
||
}
|
||
|
||
|
||
def get_opinion_text(
|
||
effect_type: str,
|
||
emotion: Emotion,
|
||
agent_id: str,
|
||
tick: int
|
||
) -> str:
|
||
"""根据事件类型和情绪生成观点文本"""
|
||
emotion_key = emotion.value
|
||
|
||
# 获取对应模板
|
||
if effect_type in OPINION_TEMPLATES:
|
||
templates = OPINION_TEMPLATES[effect_type].get(
|
||
emotion_key,
|
||
DEFAULT_OPINIONS[emotion_key]
|
||
)
|
||
else:
|
||
templates = DEFAULT_OPINIONS[emotion_key]
|
||
|
||
# 基于 agent_id 和 tick 选择模板(确保可复现)
|
||
index = (hash(agent_id) + tick) % len(templates)
|
||
return templates[index]
|
||
|
||
|
||
def update_stance_from_emotion(agent: AgentState) -> None:
|
||
"""根据情绪更新 stance(单次变化不超过 ±0.1)"""
|
||
emotion_key = agent.emotion.value
|
||
effects = EMOTION_STANCE_EFFECTS.get(emotion_key, {})
|
||
|
||
# 更新 optimism
|
||
new_optimism = agent.stance.optimism + effects.get("optimism", 0.0)
|
||
agent.stance.optimism = max(0.0, min(1.0, new_optimism))
|
||
|
||
# 更新 fear
|
||
new_fear = agent.stance.fear + effects.get("fear", 0.0)
|
||
agent.stance.fear = max(0.0, min(1.0, new_fear))
|
||
|
||
|
||
def generate_opinions(state: WorldState) -> None:
|
||
"""为所有 agent 生成对当前活跃事件的观点"""
|
||
# 无活跃效果时,清空 opinion
|
||
if not state.world_effects:
|
||
for agent in state.agents.values():
|
||
agent.opinion = None
|
||
return
|
||
|
||
# 取第一个活跃效果(优先级最高)
|
||
active_effect = state.world_effects[0]
|
||
effect_key = f"{active_effect.type}_{active_effect.name}"
|
||
|
||
for agent_id, agent in state.agents.items():
|
||
# 检查是否已对此事件发表过观点
|
||
if effect_key in agent.commented_effects:
|
||
continue
|
||
|
||
# 生成观点
|
||
text = get_opinion_text(
|
||
active_effect.type,
|
||
agent.emotion,
|
||
agent_id,
|
||
state.tick
|
||
)
|
||
|
||
# 更新 agent.opinion
|
||
agent.opinion = Opinion(
|
||
about=active_effect.type,
|
||
text=text,
|
||
tick=state.tick
|
||
)
|
||
|
||
# 根据情绪更新 stance
|
||
update_stance_from_emotion(agent)
|
||
|
||
# 记录到 memory
|
||
memory_entry = f"[{agent_id}对{active_effect.name}的看法] {text}"
|
||
agent.memory.append(memory_entry)
|
||
|
||
# 标记已评论
|
||
agent.commented_effects.append(effect_key)
|