跳转到正文
文章目录

一、行为树的类型谱系

"行为树"(Behavior Tree)是一个宽泛的术语。在 NPC AI 和模拟器设计领域,常用的行为决策架构有以下几类,彼此并不互斥,通常组合使用。


1.1 概率行为树(Probabilistic Behavior Tree)

当前《大观园浮世录》使用的主要模型。

原理:每个节点是一个行为,每次决策掷一次随机数,根据概率区间落入对应行为。概率值可以是静态常量,也可以根据状态动态计算。

</> PLAINTEXT
r = random()
if r < P1(state):  行为A
if r < P1+P2:      行为B
else:              行为C(兜底)

优点:实现简单,容易产生"自然感"的变化。
缺点:角色的行为是对自身状态的反应,缺少对他人行为的感知和响应。凤姐不知道探春上回合干了什么,只知道自己当前的 fear 值是多少。


1.2 效用行为树(Utility-Based Behavior Tree)

原理:为每个可能的行为计算一个"效用分数"(utility score),选择当前效用最高的行为执行。效用函数综合多个变量加权计算。

</> PLAINTEXT
utility(贪腐) = 0.4 × (1 - fear) + 0.3 × wealth_deficit + 0.2 × prestige
utility(立威) = 0.5 × prestige_gap + 0.3 × morale_threat
execute( argmax(utilities) )

与概率树的区别:概率树是"掷骰子选行为",效用树是"算分数选最优行为"。效用树的角色行为更理性、更目标导向,适合模拟策略性人物(如凤姐)。

在红楼语境下:凤姐每回合会计算"贪更多的收益"与"被查的风险"之间的权衡,而不是随机地有时贪有时立威。


1.3 有限状态机(Finite State Machine, FSM)

原理:角色处于若干离散状态之一(如"潜伏期"、"扩张期"、"对抗期"、"溃败期"),状态之间有明确的转换条件。在某个状态内,行为是固定的或有限变化的。

</> PLAINTEXT
State: NEUTRAL
  → if evidence > 2: 转入 HOSTILE 状态
  → if wealth < 50: 转入 ACCUMULATE 状态

State: HOSTILE
  → 每回合必定尝试查账
  → if auditSuccess >= 2: 转入 TRIUMPH 状态

与概率树的区别:FSM 的行为取决于所处状态,而非每回合独立掷骰。角色有"阶段感",前期和后期行为截然不同。

当前模拟器的问题:凤姐的 attitude_tan 字段其实是个 FSM 的雏形(neutral/ally/hostile),但它目前只影响探春的查账概率,并没有真正改变凤姐自身的行为模式。这是一个已有骨架但未充分激活的结构。


1.4 目标导向行动计划(Goal-Oriented Action Planning, GOAP)

原理:角色有明确的目标(Goal),以及一组带前置条件和效果的动作(Action)。AI 在运行时动态规划一条能从当前状态到达目标的行动链。

</> PLAINTEXT
目标: 赎身出府(需要 wealth >= 220)
可用动作:
  - 收集情报(+intel, 耗时)
  - 举报凤姐(需要 intel > 1, +wealth)
  - 日常侍奉(+loyalty, +wealth少量)
规划: 日常侍奉 → 收集情报 → 举报凤姐 → 赎身

适用场景:目标明确、动作有前置条件的角色。雪雁的"赎身"弧线非常适合 GOAP——她的每个行为都应该服务于这个终极目标。


1.5 反应式行为树(Reactive/Event-Driven Behavior Tree)

原理:角色不主动行动,而是对其他角色的行为或世界事件做出反应。事件作为触发器,驱动对应的响应行为。

</> PLAINTEXT
当凤姐执行"贪腐"且leaked=true:
  → 探春: evidence += 0.5(反应)
  → 雪雁: intel += 0.3(反应,如果在场)

当宝玉情绪低落:
  → 晴雯: 概率触发"陪伴安慰"行为
  → 袭人: 概率触发"向王夫人报告"行为

这正是当前模拟器最欠缺的部分——角色几乎不对彼此的具体行为做出反应,只对彼此留下的数值痕迹(evidence、loyalty等)做出延迟反应。


1.6 行为树的类型对比

类型 决策基础 角色感知 适合人物类型
概率行为树 自身状态+随机 低(只感知数值) 所有人物(基础层)
效用行为树 多变量加权得分 中(感知多维状态) 策略型:凤姐、探春
有限状态机 所处阶段 中(感知关键阈值) 有明确阶段弧线的角色
GOAP 目标规划 中(感知距目标距离) 目标驱动型:雪雁、袭人
反应式行为树 他者行为事件 高(感知他人行动) 所有人物(关联层)

真实可信的 NPC 系统通常是多层复合的:用 FSM 定义人物所处阶段,用效用树在阶段内选择最优行为,用反应式层响应他人行动。


二、当前模拟器的关联性断层诊断

2.1 问题的本质

当前《大观园浮世录 v4》的架构可以用一句话概括:

一组独立运行的概率状态机,共享同一张数值表格,但不互相观察。

每个角色在自己的决策函数(decideFeng()、decideMaids() 等)里独立运行,读取的是 G 对象中的数值,但这些数值是上一时刻的结果沉淀,而不是对方刚刚做了什么的实时感知。

角色之间的联系完全通过"数值中介"实现:

</> PLAINTEXT
凤姐贪腐 → G.feng.ledger++ → 探春读取 ledger 值 → 决策

这中间没有直接的"我看到你做了这件事,我要回应"的机制。结果是每个角色的行为读起来像是平行的独立故事,而非一张相互缠绕的关系网。


2.2 具体断层清单

断层一:凤探博弈没有直接互动回合

凤姐的 decideFeng() 和探春的 decideTan() 各自独立执行,没有"对话帧"——不存在"探春这回合向凤姐当面对质,凤姐在同一回合必须选择回应策略"的机制。现实中,博弈的精髓恰恰在于当面的应对和反制,而非各自暗中行动后数值此消彼长。

断层二:宝玉与怡红院丫鬟的情感几乎单向

宝玉的好感度 bao.affinity.qw、bao.affinity.xr 存在于状态表里,但晴雯和袭人的行为几乎不因宝玉的即时行为而改变。宝玉今天情绪崩溃,晴雯不会特别去安慰;宝玉今天心情大好,袭人不会趁机提出姨娘的要求。情感关系是静态的好感数值,而不是动态的双向互动流。

断层三:黛玉的愁绪与宏观事件脱节

黛玉的 sadness 每天随机浮动,偶尔触发"宝玉挨打"等事件时才有显著波动。但她不会因为"探春刚刚成功查账,府中震动"而感到不安;不会因为"省亲消息传来,全府繁忙,无人顾及她"而愁绪大增。她的情绪是封闭的内循环,与政治层完全隔离。

断层四:王夫人的干政是被动的数值,不是主动的角色行为

王夫人的 supportFeng 和 suspectTan 字段存在,袭人的告密会触发 wfy.suspectTan = true,但王夫人自己没有独立的决策函数。她不会在某个时刻主动介入,召见凤姐训话,或者当着众人面表扬探春。她只是一个被动的修正系数,而非一个行为主体。

断层五:丫鬟之间没有横向互动

晴雯的遭遇不影响紫鹃的情绪;袭人的告密不影响麝月的处境;雪雁赎身成功不影响春纤的忠诚(甚至不影响任何人)。原著中丫鬟群像的精彩之处在于横向的连带与对比,而模拟器中她们六人是六条平行的独立折线。

断层六:事件没有人格化响应

大事件触发后,会直接修改数值(deficit+、turmoil+ 等),但没有触发相关角色的即时响应行为。"宝玉挨打"事件发生后,黛玉不会立刻哭倒,贾母不会立刻介入,凤姐不会立刻趁乱——他们只在下一个常规回合里继续执行各自的独立决策流程。


2.3 断层的根源:缺少三种机制

机制一:行为事件总线(Event Bus)

每当一个角色执行有意义的行为,应当向全局广播一个事件,其他角色可以订阅并即时响应。

</> PLAINTEXT
// 凤姐贪腐时广播
emit('FENG_CORRUPT', { amount: 45, leaked: true })

// 探春订阅
on('FENG_CORRUPT', ({ leaked }) => {
  if (leaked) tan.evidence += 0.5
  if (tan.attitude === 'hostile') tan.reactNow = true  // 下回合优先查账
})

// 紫鹃订阅
on('FENG_CORRUPT', () => {
  if (Math.random() < 0.3) zj.intel += 0.2  // 潇湘馆有人听到了风声
})

机制二:对话/冲突帧(Confrontation Frame)

当两个角色的关系进入 hostile 状态,且都有精力时,应触发一个"共同回合",双方在同一帧内互动,结果取决于双方的当前状态对比,而非各自的独立随机数。

</> PLAINTEXT
if (feng.attitude === 'hostile' && tan.attitude === 'hostile'
    && feng.stamina > 0 && tan.stamina > 0) {
  runConfrontation(feng, tan)
  // 双方各出一张牌,综合计算胜负
}

机制三:情感传播网络(Emotional Contagion)

情绪和消息应该在关系网络中传播,而不是每个角色孤立地随机浮动。

</> PLAINTEXT
// 宝玉情绪崩溃时
if (bao.mood < 20) {
  propagate('BAO_DISTRESS', {
    qw: { loyalty: +3, triggerComfort: 0.6 },   // 晴雯更想护主
    xr: { spyChance: +0.2 },                    // 袭人更想去告密
    dai: { sadness: +8 },                        // 黛玉感应到了
  })
}

三、改进方向的优先级建议

综合以上分析,关联性改进按投入产出比排序如下:

第一优先:为主要角色添加行为事件广播
工作量小,效果立竿见影。凤姐的贪腐、探春的查账、宝玉的情绪事件各自广播,其他角色订阅响应。这一改动能立刻让日志变得"有因有果"。

第二优先:激活王夫人为真正的行为主体
给王夫人添加 decideWfy() 函数,让她根据凤姐威望、探春改革进度、袭人告密次数做出主动行为(召见、训斥、赐福),而不只是一个修正系数。

第三优先:将凤探关系升级为 FSM + 对话帧
将 attitude 字段真正激活为状态机,在 hostile 状态下触发对抗帧,让两人在同一回合内博弈,而不是各自行动后对数值做加减。

第四优先:添加情感传播规则
为宝玉的情绪、黛玉的健康、晴雯被撵等高影响力事件添加向外传播的情感波纹,使大事件的后果能在多个角色间漾开。

第五优先:将雪雁、袭人升级为 GOAP 模型
两人各有明确的人生目标(赎身、成为姨娘),所有行为都应服务于这个目标。GOAP 能让她们的行动逻辑更连贯,而不是每回合随机选择"告密还是侍奉"。


四、小结

当前模拟器的核心问题不是"缺少更好的行为树类型",而是缺少角色之间的信息流通机制。无论使用什么类型的行为树,如果每个角色只能感知自身的数值状态,而无法感知他人的即时行为,那么他们必然是"各做各的"。

真正有生命力的多角色模拟,需要在决策层之下建立一张事件-响应网络:角色做出行为,行为产生事件,事件传播给相关角色,相关角色据此调整下一步决策。这个循环的密度和复杂度,决定了模拟世界的"活"的程度。

《红楼梦》原著之所以震撼人心,正是因为书中每一个角色的命运都与他人深度缠绕——一个丫鬟的赎身,牵扯着管家的账目;一个公子的痴病,映照着才女的泪水。模拟器若要还原这种缠绕感,事件总线和情感传播网络是不可或缺的基础设施。


文档生成时间:2026-03-23 04:19 CST

评论

搜索站内内容

输入关键词开始搜索