"""角色事件评论系统 - 基于规则生成观点""" 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)