// games/yinian.js — 《一念》 // 内心法庭。七个声音,一个决定。 // 单击=接纳这个声音,双击=让它走。 // 结局由接纳了哪些声音决定。 const GAME_YINIAN = { id: 'yinian', intro: '你坐在黑暗里,独自一人。今晚你必须做一个决定——你自己知道是什么。七个声音在等着和你说话。单击,让它说完。双击,让它走。', first: 'v01', bgm: null, ambience: '../audio/mp3/ambience/amb_apartment_night_01_v1.mp3', initialState: { accepted: [], // 接纳的声音 rejected: [], // 放走的声音 // 关键标记 kept_fear: false, kept_longing: false, kept_apology: false, kept_past: false, }, scenes: { // ── 第一个声音:三年前的自己 ── v01: { delay: 1000, narrate: '第一个声音来了。是三年前的你。那时候你刚做了一个选择,你觉得那是对的。那时候的你说:我们当时想要的,你还记得吗?', tap: { label: '听它说完', narrate: '你让三年前的自己说完了。她说,你当时很想要那件事。你知道那是真的。', state: s => ({ accepted: [...s.accepted, '三年前的自己'], rejected: s.rejected, kept_past: true }), next: 'v02', }, doubleTap: { label: '让它走', narrate: '三年前的声音淡去了。你选择了不看它。', state: s => ({ accepted: s.accepted, rejected: [...s.rejected, '三年前的自己'], kept_past: false }), next: 'v02', }, }, // ── 第二个声音:一个老朋友的留言 ── v02: { delay: 1000, narrate: '第二个声音。是一个你很久没联系的朋友,她留了条语音。她说:你最近怎么样,我有点担心你。很久了,你一直没回。', tap: { label: '听下去', narrate: '你把这份担心收进来了。她还在关心你,这件事是真实的。', state: s => ({ accepted: [...s.accepted, '朋友的担心'], rejected: s.rejected }), next: 'v03', }, doubleTap: { label: '让它走', narrate: '留言消失了。你没有听完。', state: s => ({ accepted: s.accepted, rejected: [...s.rejected, '朋友的担心'] }), next: 'v03', }, }, // ── 第三个声音:关于钱的恐惧 ── v03: { delay: 1000, narrate: '第三个声音。是关于钱的恐惧。它说:你知道你现在能撑多久吗?如果这件事不成,你怎么办?它问得很具体,很冷静。', tap: { label: '正视它', narrate: '你承认了:这份恐惧是真实的。你带着它,而不是假装它不存在。', state: s => ({ accepted: [...s.accepted, '对钱的恐惧'], rejected: s.rejected, kept_fear: true }), next: 'v04', }, doubleTap: { label: '先不管它', narrate: '恐惧的声音淡下去了。你知道它还在,但今晚先不看。', state: s => ({ accepted: s.accepted, rejected: [...s.rejected, '对钱的恐惧'], kept_fear: false }), next: 'v04', }, }, // ── 第四个声音:关于孤独的渴望 ── v04: { delay: 1000, narrate: '第四个声音。是一种渴望——想要被人理解,想要有人在身边,想要不那么孤独。它来得轻,但是很深。', tap: { label: '承认它', narrate: '你承认了这份渴望。它是真实的,不是软弱。', state: s => ({ accepted: [...s.accepted, '对连接的渴望'], rejected: s.rejected, kept_longing: true }), next: 'v05', }, doubleTap: { label: '让它走', narrate: '渴望漂走了。你告诉自己,一个人也没什么。', state: s => ({ accepted: s.accepted, rejected: [...s.rejected, '对连接的渴望'], kept_longing: false }), next: 'v05', }, }, // ── 第五个声音:一个未说出口的道歉 ── v05: { delay: 1000, narrate: '第五个声音。是一个你一直没有说出口的道歉。你知道是对谁的,你知道说的是什么。这个声音只是在等你。', tap: { label: '说出来', narrate: '你在黑暗里,说了那句对不起。没有人听见,但你说了。有什么东西松开了。', state: s => ({ accepted: [...s.accepted, '那声道歉'], rejected: s.rejected, kept_apology: true }), next: 'v06', }, doubleTap: { label: '还没准备好', narrate: '道歉的声音还在那里。你没有说。它等着。', state: s => ({ accepted: s.accepted, rejected: [...s.rejected, '那声道歉'], kept_apology: false }), next: 'v06', }, }, // ── 第六个声音:关于那个决定 ── v06: { delay: 1000, narrate: '第六个声音。是今晚那个决定本身。它把两种可能都摆在你面前,不说话,只是等着你看清楚。', tap: { label: '看清楚它', narrate: '你看了。两条路都有代价,你知道了。这不让选择变得更容易,但让它变得更真实。', state: s => ({ accepted: [...s.accepted, '那个决定本身'], rejected: s.rejected }), next: 'v07', }, doubleTap: { label: '还不想看', narrate: '你把眼睛闭上了。还没准备好看那两条路。', state: s => ({ accepted: s.accepted, rejected: [...s.rejected, '那个决定本身'] }), next: 'v07', }, }, // ── 第七个声音:现在的自己 ── v07: { delay: 2000, narrate: s => { const n = s.accepted.length; if (n >= 5) return '第七个声音,是现在的你。她说:你今晚接住了很多,你没有回避它们。这需要力气。'; if (n <= 1) return '第七个声音,是现在的你。她沉默了很久,然后说:你把它们都推走了。也许你需要的不是答案,是喘息。'; if (s.kept_fear && !s.kept_longing) return '第七个声音,是现在的你。她说:你把恐惧留下了,但把渴望推走了。你知道这意味着什么吗?'; return '第七个声音,是现在的你。她说:你接住了一些,放走了一些。这就是你今晚的状态。'; }, tap: { label: '听下去', narrate: '你听完了现在的自己说话。她说:不管你今晚做什么决定,你都已经在这里待过了。这算数。', state: s => ({ accepted: [...s.accepted, '现在的自己'], rejected: s.rejected }), next: null, }, doubleTap: { label: '就这样', narrate: '你没有听完。你觉得你已经知道了你需要知道的。', state: s => ({ accepted: s.accepted, rejected: [...s.rejected, '现在的自己'] }), next: null, }, }, }, getEnding: s => { if (s.kept_apology) return 'reconcile'; const n = s.accepted.length; if (n >= 5) return 'accept'; if (n <= 1) return 'release'; if (s.kept_fear && !s.kept_longing) return 'stuck'; return 'between'; }, endings: { accept: { narrate: '《接纳》。你今晚接住了很多,你没有选择只是轻装。也许你的决定,就是带着这些往前走。', }, release: { narrate: '《出发》。你今晚把大部分都放走了。你想要的也许是轻。轻装,也是一种勇气。', }, stuck: { narrate: '《困住》。你接受了恐惧,但推走了渴望。你知道风险,但忘了你想要的是什么。这个决定,也许需要再等一等。', }, reconcile: { narrate: '《和解》。你说出了那声道歉。不管今晚的决定是什么,你和自己和解了一点点。这很重要。', }, between: { narrate: '《悬在中间》。你接住了一些,放走了一些。你还悬在两个答案之间。也许这就是你今晚真实的状态。', }, }, };