"""社交影响系统 - 角色间观点传播""" from typing import Dict, List, Tuple from .models import WorldState, AgentState, Stance # 单次 stance 变化上限 MAX_STANCE_CHANGE = 0.1 # 影响强度系数 INFLUENCE_STRENGTH = 0.05 def get_contact_targets( agent_id: str, all_agent_ids: List[str], tick: int ) -> List[str]: """ 确定性地选择 1-2 个接触对象 基于 agent_id 和 tick 确保可复现 """ # 排除自己 others = [aid for aid in all_agent_ids if aid != agent_id] if not others: return [] # 基于 hash 确定性选择 seed = hash(agent_id) + tick # 选择 1 或 2 个目标 num_targets = 1 + (seed % 2) num_targets = min(num_targets, len(others)) targets = [] for i in range(num_targets): idx = (seed + i * 7) % len(others) target = others[idx] if target not in targets: targets.append(target) return targets def calculate_influence( agent_stance: Stance, target_stance: Stance ) -> Tuple[float, float]: """ 计算社交影响产生的 stance 变化 逻辑: - 相近立场 → 强化原有立场 - 相反立场 → 产生反向影响 返回: (optimism_delta, fear_delta) """ # 计算差异 opt_diff = target_stance.optimism - agent_stance.optimism fear_diff = target_stance.fear - agent_stance.fear # 相近度判断(差异小于 0.3 视为相近) opt_similar = abs(opt_diff) < 0.3 fear_similar = abs(fear_diff) < 0.3 opt_delta = 0.0 fear_delta = 0.0 if opt_similar: # 相近 → 强化原有立场(向中间靠拢后再强化) opt_delta = opt_diff * INFLUENCE_STRENGTH else: # 相反 → 反向影响(抵抗) opt_delta = -opt_diff * INFLUENCE_STRENGTH * 0.5 if fear_similar: fear_delta = fear_diff * INFLUENCE_STRENGTH else: fear_delta = -fear_diff * INFLUENCE_STRENGTH * 0.5 # 限制单次变化幅度 opt_delta = max(-MAX_STANCE_CHANGE, min(MAX_STANCE_CHANGE, opt_delta)) fear_delta = max(-MAX_STANCE_CHANGE, min(MAX_STANCE_CHANGE, fear_delta)) return opt_delta, fear_delta def apply_social_influence(state: WorldState) -> None: """ 应用社交影响:每个 agent 与 1-2 个其他 agent 接触 所有变化写入 world_state """ agent_ids = list(state.agents.keys()) if len(agent_ids) < 2: return # 收集所有变化(先计算,后应用,避免顺序影响) stance_changes: Dict[str, Tuple[float, float]] = {} for agent_id in agent_ids: agent = state.agents[agent_id] targets = get_contact_targets(agent_id, agent_ids, state.tick) total_opt_delta = 0.0 total_fear_delta = 0.0 for target_id in targets: target = state.agents[target_id] opt_delta, fear_delta = calculate_influence( agent.stance, target.stance ) total_opt_delta += opt_delta total_fear_delta += fear_delta # 限制总变化 total_opt_delta = max(-MAX_STANCE_CHANGE, min(MAX_STANCE_CHANGE, total_opt_delta)) total_fear_delta = max(-MAX_STANCE_CHANGE, min(MAX_STANCE_CHANGE, total_fear_delta)) stance_changes[agent_id] = (total_opt_delta, total_fear_delta) # 应用所有变化 for agent_id, (opt_delta, fear_delta) in stance_changes.items(): agent = state.agents[agent_id] new_opt = agent.stance.optimism + opt_delta new_fear = agent.stance.fear + fear_delta agent.stance.optimism = max(0.0, min(1.0, new_opt)) agent.stance.fear = max(0.0, min(1.0, new_fear))