feat(relation): 親近度會改變情緒的份量;提到 ≠ 接觸(v0.0.8 同批)
① 親近度 → 情緒的份量(`relationGain()`) 在這之前 `applyEmotion()` 完全沒吃關係圖:親近度只影響語氣層、羞恥度與主動關心, 情緒的 delta 從頭到尾是人格自己挑的,**跟對象是誰無關**。 但同一句「你最近怪怪的」,從親近 97 的人跟從生人嘴裡出來,衝擊不該一樣。 現在 `emotion --apply` 會依對象親近度把 delta 乘 0.7–1.35(親近 96 → ×1.28、 親近 8 → ×0.75),`--from <對象>` 指定是誰引起的,沒指定就用當前對話對象。 **只調幅度、不調方向**——誰講的都不會讓難過變成高興。 ② 提到 ≠ 接觸(`contactsFromRooms()`) 主動關心的依據是 `last_contact_at`,而睡眠以前是掃短期記憶的 `entities` 來蓋章。 那等於「我在日記裡寫到尤吉歐」就算「我跟尤吉歐接觸過」——沉默計時被無聲重置, 關心名單於是永遠是空的。實測就是這樣:所有人都停在 1.09 天,沒有人會被想起。 現在只認真的有來有往:同一個聊天室裡我發過言、他也發過言。 沒有聊天室的對象(真人節點)走 `relation node --contact` 明確蓋章。 測試:340 項全過(新增 7 項)。既有的「關係時間戳有蓋上」拆成兩條—— 只被提到的不蓋、真的接觸過才蓋,正好把新語意釘住。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+44
-1
@@ -1198,7 +1198,14 @@ check("預設保留載入鎖(--release 才收工)",
|
||||
sleepJson.kept_lock === true && pl.lockStatus("epsilon").locked);
|
||||
check("睡眠寫下 state/sleep.json 與距上次睡眠的時數",
|
||||
pl.loadSleepState("epsilon").last_slept_at !== null && pl.hoursAwake("epsilon") !== null);
|
||||
check("關係時間戳有蓋上(主動關心的依據)", (() => {
|
||||
// 提到 ≠ 接觸:只在短期記憶裡被提到的人,睡眠不會把他的沉默計時歸零
|
||||
check("只被提到的人不會被蓋時間戳", (() => {
|
||||
const node = pl.loadRelations("epsilon").nodes.find((n) => n.id === "zeta");
|
||||
return !node?.last_contact_at;
|
||||
})(), JSON.stringify(pl.loadRelations("epsilon").nodes.find((n) => n.id === "zeta")));
|
||||
// 真的接觸過要蓋得上:沒有聊天室的對象走 `relation node --contact` 明確蓋章
|
||||
cli(["relation", "node", "--persona", "epsilon", "--session", S_SLEEP, "--name", "zeta", "--contact"]);
|
||||
check("真的接觸過就蓋得上時間戳(主動關心的依據)", (() => {
|
||||
const node = pl.loadRelations("epsilon").nodes.find((n) => n.id === "zeta");
|
||||
return Boolean(node?.last_contact_at);
|
||||
})());
|
||||
@@ -1387,6 +1394,42 @@ check("sleeper 型別存在且宣告了唯讀工具限制", (() => {
|
||||
md.includes("回傳值裡不得出現任何記憶內容");
|
||||
})());
|
||||
|
||||
console.log("\n親近度 → 情緒的份量;提到 ≠ 接觸");
|
||||
{
|
||||
const S_REL = "sess-rel-6666";
|
||||
cli(["load", "--persona", "alpha", "--session", S_REL, "--takeover"]);
|
||||
cli(["relation", "node", "--persona", "alpha", "--session", S_REL, "--name", "枕邊人",
|
||||
"--kind", "human", "--bond", "partner", "--closeness", "96", "--trust", "95"]);
|
||||
cli(["relation", "node", "--persona", "alpha", "--session", S_REL, "--name", "路人甲",
|
||||
"--kind", "human", "--bond", "stranger", "--closeness", "8", "--trust", "10"]);
|
||||
const close = pl.relationGain("alpha", "枕邊人");
|
||||
const far = pl.relationGain("alpha", "路人甲");
|
||||
check("親近的人講的話,份量比較重", close.gain > 1.2 && far.gain < 0.85, `${close.gain} vs ${far.gain}`);
|
||||
check("找不到對象就不放大也不縮小", pl.relationGain("alpha", "不存在的人").gain === 1);
|
||||
// 同樣的 delta,來自不同的人,落下來的量不一樣
|
||||
const before = pl.loadEmotion("alpha").levels.joy;
|
||||
cli(["emotion", "--persona", "alpha", "--session", S_REL, "--apply", "joy=+10",
|
||||
"--from", "枕邊人", "--trigger", "她說的"]);
|
||||
const afterClose = pl.loadEmotion("alpha").levels.joy - before;
|
||||
cli(["emotion", "--persona", "alpha", "--session", S_REL, "--baseline", `joy=${Math.round(before)}`]);
|
||||
const before2 = pl.loadEmotion("alpha").levels.joy;
|
||||
cli(["emotion", "--persona", "alpha", "--session", S_REL, "--apply", "joy=+10",
|
||||
"--from", "路人甲", "--trigger", "路人說的"]);
|
||||
const afterFar = pl.loadEmotion("alpha").levels.joy - before2;
|
||||
check("同一句話,枕邊人講的比路人講的更動搖你", afterClose > afterFar, `close=${afterClose} far=${afterFar}`);
|
||||
check("只調幅度、不調方向(都還是往上)", afterClose > 0 && afterFar > 0);
|
||||
|
||||
// 提到 ≠ 接觸
|
||||
cli(["relation", "node", "--persona", "alpha", "--session", S_REL, "--name", "只被提到的人",
|
||||
"--kind", "human", "--bond", "friend", "--closeness", "80"]);
|
||||
cli(["remember", "--persona", "alpha", "--session", S_REL, "--role", "persona",
|
||||
"--text", "我在日記裡寫到只被提到的人", "--entities", "只被提到的人", "--salience", "50"]);
|
||||
const real = pl.contactsFromRooms("alpha");
|
||||
check("被提到的人不算接觸過(睡眠不再拿 entities 蓋時間戳)",
|
||||
!real.includes("只被提到的人"), JSON.stringify(real));
|
||||
cli(["release", "--session", S_REL]);
|
||||
}
|
||||
|
||||
console.log("\n劇場模式:心裡話不能外流");
|
||||
{
|
||||
const S_INNER = "sess-inner-8888";
|
||||
|
||||
Reference in New Issue
Block a user