吓死人了!!!.py

我真服了gemini了,怎么这么:cow_face:b啊,deepseek+gemini两大模型齐心齐力,一起把我的心脏病吓出来了,啥也不说,直接上源代码:

<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>雨夜来访 · 悬疑文字冒险</title>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700&display=swap');

        :root {
            --bg-color: #050505;
            --text-color: #d4c3a5;
            --blood-red: #8a0303;
            --ui-border: #2a1b1b;
        }

        * {
            box-sizing: border-box;
            font-family: 'Noto Serif SC', 'Times New Roman', serif;
            user-select: none;
        }

        body {
            background: var(--bg-color);
            min-height: 100vh;
            margin: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 20px;
            color: var(--text-color);
            overflow: hidden;
            /* 防止特效导致滚动条闪烁 */
            transition: background 1s ease;
        }

        /* 屏幕扫描线滤镜 */
        .crt-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100vw;
            height: 100vh;
            background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));
            background-size: 100% 2px, 3px 100%;
            pointer-events: none;
            z-index: 998;
            opacity: 0.6;
        }

        /* 闪电特效 */
        .lightning {
            animation: flash 8s infinite;
        }

        @keyframes flash {

            0%,
            95%,
            98%,
            100% {
                box-shadow: 0 0 30px rgba(74, 0, 0, 0.3);
                background: #111;
            }

            96% {
                box-shadow: 0 0 100px rgba(255, 255, 255, 0.8);
                background: #333;
            }

            97% {
                box-shadow: 0 0 30px rgba(74, 0, 0, 0.3);
                background: #111;
            }

            99% {
                box-shadow: 0 0 80px rgba(255, 255, 255, 0.5);
                background: #222;
            }
        }

        /* 低理智幻觉特效 */
        .insane-mode {
            animation: heartbeat 2s infinite;
            text-shadow: 2px 0px 3px rgba(255, 0, 0, 0.5), -2px 0px 3px rgba(0, 0, 255, 0.5);
        }

        @keyframes heartbeat {
            0% {
                filter: blur(0px) contrast(1);
            }

            50% {
                filter: blur(1px) contrast(1.2) drop-shadow(0 0 10px var(--blood-red));
            }

            100% {
                filter: blur(0px) contrast(1);
            }
        }

        .game-container {
            max-width: 800px;
            width: 100%;
            background: #111;
            border: 1px solid var(--ui-border);
            padding: 30px;
            position: relative;
            z-index: 10;
            transition: all 0.5s;
        }

        /* UI 头栏 */
        .header-stats {
            display: flex;
            justify-content: space-between;
            border-bottom: 1px dashed var(--blood-red);
            padding-bottom: 15px;
            margin-bottom: 25px;
            font-size: 1.1rem;
            letter-spacing: 2px;
        }

        .stat span {
            font-weight: bold;
            color: #fff;
        }

        #sanityVal {
            transition: color 0.3s;
        }

        /* 线索区 */
        .clues {
            font-size: 0.85rem;
            color: #888;
            margin-bottom: 20px;
            min-height: 30px;
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
        }

        .clue-tag {
            background: #1a0a0a;
            border: 1px solid #4a1a1a;
            padding: 3px 8px;
            border-radius: 2px;
            color: #c7a9a9;
        }

        /* 剧情文本区 */
        .scene-box {
            font-size: 1.15rem;
            line-height: 1.8;
            min-height: 280px;
            margin-bottom: 30px;
            white-space: pre-wrap;
            color: #ccc;
            text-shadow: 0 1px 2px #000;
        }

        /* 选项按钮 */
        .options-area {
            display: flex;
            flex-direction: column;
            gap: 15px;
        }

        .option-btn {
            background: transparent;
            border: 1px solid #444;
            color: var(--text-color);
            padding: 12px 20px;
            font-size: 1.05rem;
            text-align: left;
            cursor: pointer;
            transition: all 0.3s;
            position: relative;
            overflow: hidden;
        }

        .option-btn::before {
            content: "▶ ";
            color: var(--blood-red);
            opacity: 0;
            transition: opacity 0.3s;
        }

        .option-btn:hover {
            border-color: var(--blood-red);
            background: rgba(138, 3, 3, 0.1);
            padding-left: 25px;
        }

        .option-btn:hover::before {
            opacity: 1;
        }

        /* 独立结局遮罩页(灵魂) */
        #endingScreen {
            position: fixed;
            top: 0;
            left: 0;
            width: 100vw;
            height: 100vh;
            background: #000;
            z-index: 1000;
            display: none;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            padding: 40px;
            opacity: 0;
            transition: opacity 2s ease-in;
        }

        #endingText {
            max-width: 800px;
            font-size: 1.3rem;
            line-height: 2;
            color: #fff;
            text-align: justify;
            white-space: pre-wrap;
        }

        .ending-title {
            font-size: 2.5rem;
            color: var(--blood-red);
            margin-bottom: 30px;
            letter-spacing: 5px;
            opacity: 0;
            text-shadow: 0 0 10px red;
            transition: opacity 2s 1s;
            /* 延迟显示 */
        }

        .restart-btn {
            margin-top: 50px;
            background: none;
            border: 1px solid var(--blood-red);
            color: var(--blood-red);
            padding: 10px 30px;
            cursor: pointer;
            font-size: 1rem;
            opacity: 0;
            transition: all 0.3s;
        }

        .restart-btn:hover {
            background: var(--blood-red);
            color: #000;
        }
    </style>
</head>

<body>

    <div class="crt-overlay"></div>

    <div class="game-container lightning" id="gameContainer">
        <div class="header-stats">
            <div class="stat">理智 🧠 <span id="sanityVal">100</span></div>
            <div class="stat">信任 🤝 <span id="trustVal">0</span></div>
            <div class="stat">线索 📜 <span id="clueCount">0</span></div>
        </div>
        <div class="clues" id="clueList"></div>
        <div class="scene-box" id="sceneDesc"></div>
        <div class="options-area" id="optionsContainer"></div>
    </div>

    <div id="endingScreen">
        <div class="ending-title" id="endingTitle"></div>
        <div id="endingText"></div>
        <button class="restart-btn" id="restartBtn" onclick="location.reload()">重新坠入雨夜</button>
    </div>

    <script>
        (function () {
            let state = {
                sanity: 100,
                trust: 0,
                money: 0, // 新增金钱系统,补全购买绳索的逻辑闭环
                clues: [],
                hasDiary: false,
                hasFireReport: false,
                hasJidianLetter: false,
                hasKey: false,
                currentScene: 'OPENING',
            };

            function addClue(clueName) {
                if (!state.clues.includes(clueName)) {
                    state.clues.push(clueName);
                    refreshUI();
                }
            }

            function modifySanity(val) {
                state.sanity = Math.max(0, state.sanity + val);
                const sanDOM = document.getElementById('sanityVal');
                sanDOM.innerText = state.sanity;

                // 视觉压迫特效
                if (state.sanity < 30) {
                    sanDOM.style.color = "red";
                    document.body.classList.add('insane-mode');
                } else {
                    sanDOM.style.color = "#fff";
                    document.body.classList.remove('insane-mode');
                }
            }

            function refreshUI() {
                document.getElementById('sanityVal').innerText = state.sanity;
                document.getElementById('trustVal').innerText = state.trust;
                document.getElementById('clueCount').innerText = state.clues.length;

                const clueDOM = document.getElementById('clueList');
                clueDOM.innerHTML = state.clues.length ? state.clues.map(c => `<span class="clue-tag">${c}</span>`).join('') : '<span style="color:#555">你的大脑一片空白...</span>';

                renderScene();
            }

            // --- 核心剧本重构 ---
            const scenes = {
                OPENING: {
                    desc: `[雨夜。昏黄的灯光从罩着绿纱的吊灯垂下,照着这间凌乱的侦探事务所。窗户玻璃上淌着水痕,街对面的霓虹招牌一明一灭,将红光短暂地投在屋内。]\n\n[你坐在转椅里。指尖夹着一支快燃尽的香烟。收音机里传来断断续续的沪剧唱腔,混着窗外的雨声。]`,
                    options: [
                        { text: '掐灭烟', action: () => proceed('DOORBELL') },
                        { text: '环顾四周', action: () => { addClue('霓虹灯节奏:闪三停一'); proceed('DOORBELL'); } },
                        { text: '回想今日', action: () => { modifySanity(-2); proceed('DOORBELL'); } },
                        { text: '查看烟灰缸', action: () => { addClue('医生的警告'); proceed('DOORBELL'); } }
                    ]
                },
                DOORBELL: {
                    desc: `[门铃响起。叮铃。在雨声中显得格外刺耳。你没有动。叮铃。又是两声,短促而固执。]`,
                    options: [
                        { text: '立即起身开门', action: () => proceed('MEET_WOMAN') },
                        { text: '隔着门问“谁?”', action: () => { state.trust -= 1; proceed('MEET_WOMAN'); } }
                    ]
                },
                MEET_WOMAN: {
                    desc: `[你打开了门。楼道昏暗的灯光下,站着一个女人。黑色旗袍湿漉漉地贴在身上。]\n\n“请问……您是沈默先生吗?”她的声音带着颤抖,“他们说,只有您会接那种没人愿意碰的案子。”\n\n[闪电划过,将她的影子猛地投在墙上。影子比真人长出一截,扭曲地延伸到天花板。你眨了眨眼——再看时,影子已经恢复正常。]`,
                    actionPre: () => modifySanity(-3),
                    options: [
                        { text: '侧身让路:“进来谈。”', action: () => { state.trust += 5; proceed('WOMAN_INSIDE'); } },
                        { text: '盯着她的眼睛:“什么案子?”', action: () => { addClue('闪避的目光'); proceed('WOMAN_INSIDE'); } }
                    ]
                },
                WOMAN_INSIDE: {
                    desc: `[她迈进门槛,递给你一张照片。]\n“我丈夫失踪了。三天前。他叫程继先,圣约翰大学历史讲师。巡捕房说是跟舞女私奔。但他走的那天早上,连书房的门都特意锁了……他从来不锁书房的门。”`,
                    actionPre: () => addClue('程继先的照片'),
                    options: [
                        { text: '问:“书房里有什么?”', action: () => { modifySanity(-10); proceed('ASK_STUDY') } },
                        { text: '沉默,等她继续说', action: () => proceed('ASK_STUDY') }
                    ]
                },
                ASK_STUDY: {
                    desc: `“门锁着,钥匙他带走了。但我找到了这个。”\n[她拿出一把黄铜钥匙和一封泛黄的信。钥匙柄上烧烙着:0713。信封上写着三个字:不可拆。]`,
                    options: [
                        {
                            text: '打开信封', action: () => {
                                addClue('继业的信(藏书楼,不可看/听/说)');
                                state.hasJidianLetter = true;
                                proceed('LETTER_OPENED');
                            }
                        },
                        { text: '不打开,问她:“你为什么找我?”', action: () => proceed('WHY_ME') }
                    ]
                },
                LETTER_OPENED: {
                    desc: `[你抽出信纸:“继先吾弟:此事不可为外人道。藏书楼之事,须在月圆之前了结。切记:不可看,不可听,不可说。兄 继业 民国十六年七月十三”]\n\n她脸色苍白:“继业……他哥哥,那年失踪了……”`,
                    options: [
                        { text: '问她:“你为什么找我?”', action: () => proceed('WHY_ME') }
                    ]
                },
                WHY_ME: {
                    desc: `“去年法租界的画中人案子,我知道是您查出来的。我需要一个不怕‘那个’的人。”\n[她恳求你今晚就去程家查看书房。]`,
                    options: [
                        { text: '答应,即刻前往', action: () => proceed('CHENG_HOUSE') },
                        { text: '答应,但要求先收定金 (获得5大洋)', action: () => { state.trust -= 10; state.money = 5; addClue('5块大洋'); proceed('PREPARE_STORE'); } },
                        { text: '拒绝,让她找别人', action: () => proceed('DEATH_LUNG') }
                    ]
                },
                DEATH_LUNG: {
                    desc: `[你继续坐在事务所里,听着雨声。三个月后,你死于肺病。]`,
                    options: [
                        { text: '(重新开始)', action: () => location.reload() }
                    ] // 将在代码逻辑中拦截并触发结局机制,但这里保留文本作为备用
                },
                PREPARE_STORE: {
                    desc: `[出门前,你路过了楼下的杂货铺。你手里有她给的5块大洋。]`,
                    options: [
                        { text: '购买打桩绳索 (-5大洋)', action: () => { addClue('绳索'); proceed('CHENG_HOUSE'); } },
                        { text: '什么都不买,直接去程宅', action: () => proceed('CHENG_HOUSE') }
                    ]
                },
                CHENG_HOUSE: {
                    desc: `[你们来到程家二楼书房。书房不大,一张书桌,书架上有一排书脊朝内的旧书,地上的老式保险柜有被拖拽的划痕。]`,
                    options: [
                        {
                            text: '调查书桌日记', action: () => {
                                if (!state.hasDiary) {
                                    modifySanity(-8); addClue('日记(那东西在窗外)'); state.hasDiary = true;
                                }
                                proceed('CHENG_HOUSE_2');
                            }
                        },
                        { text: '询问藏书楼的位置', action: () => proceed('ASK_LIBRARY') }
                    ]
                },
                CHENG_HOUSE_2: {
                    desc: `[你放下日记,书房里弥漫着一股陈旧的纸张气味。地上的划痕和那排倒置的旧书显得格格不入。]`,
                    options: [
                        { text: '询问藏书楼的位置', action: () => proceed('ASK_LIBRARY') }
                    ]
                },
                ASK_LIBRARY: {
                    desc: `“沪江大学的藏书楼……那是二十年前就关闭的地方。民国十六年大火,烧死了七个学生。”\n[民国十六年。正是继业写信的那一年。]`,
                    options: [
                        { text: '立刻前往藏书楼', action: () => proceed('LIBRARY_EXT') },
                        { text: '让程婉宜留在这里,你独自前往', action: () => { state.trust += 5; proceed('LIBRARY_EXT'); } }
                    ]
                },
                LIBRARY_EXT: {
                    desc: `[藏书楼外墙爬满枯死藤蔓。铁门紧锁。月亮从云层后露出。你注意到,三楼的窗户……有一扇是开着的。]`,
                    actionPre: () => modifySanity(-5),
                    options: [
                        { text: '用黄铜钥匙0713开门', action: () => proceed('LIBRARY_LOBBY') },
                        {
                            text: '利用绳索从三楼开着的窗户爬入', action: () => {
                                if (state.clues.includes('绳索')) {
                                    proceed('FLOOR_3_DIRECT');
                                } else {
                                    alert('墙壁太滑,你没有攀爬工具,险些摔断脖子!');
                                    modifySanity(-10);
                                    proceed('LIBRARY_EXT');
                                }
                            }
                        }
                    ]
                },
                LIBRARY_LOBBY: {
                    desc: `[钥匙转动,门开了。\n楼内弥漫焦臭味。大厅中央的镜子里……你看到一个人影。你猛地回头,身后无人。再看镜子,人影消失了。]`,
                    actionPre: () => modifySanity(-5),
                    options: [
                        { text: '先检查一楼废墟', action: () => proceed('FLOOR_1') },
                        { text: '直接上二楼', action: () => proceed('FLOOR_2') }
                    ]
                },
                FLOOR_1: {
                    desc: `[一楼阅览室满地灰烬。你捡起一片烧焦的书页,上面写着英文:“仪式必须在满月前完成。它们在等待。”]`,
                    actionPre: () => { modifySanity(-10); addClue('残页(它们在等待)'); },
                    options: [
                        { text: '前往二楼', action: () => proceed('FLOOR_2') }
                    ]
                },
                FLOOR_2: {
                    desc: `[二楼藏书室角落有个完好的铁皮柜。里面是《民国十六年火灾调查报告》。死者名单第三个名字赫然是:程继业。\n死人,怎么会给活着的弟弟写信?]`,
                    actionPre: () => { modifySanity(-8); state.hasFireReport = true; addClue('报告(继业已死)'); },
                    options: [
                        { text: '深吸一口气,上三楼', action: () => proceed('FLOOR_3') }
                    ]
                },
                FLOOR_3: {
                    desc: `[三楼。走廊尽头那扇窗户开着。路过第二扇紧闭的门时,你停下了。\n\n门缝里,一只眼睛也在盯着你。]`,
                    actionPre: () => modifySanity(-10),
                    options: [
                        { text: '推开那扇门', action: () => { triggerEnding('DOOR'); } },
                        { text: '无视它,走向走廊尽头的窗户', action: () => { triggerEnding('WINDOW'); } },
                        {
                            text: '转身逃跑', action: () => {
                                if (state.sanity < 40) triggerEnding('ESCAPE');
                                else proceed('LIBRARY_LOBBY'); // 理智够高还能退回大厅
                            }
                        }
                    ]
                },
                FLOOR_3_DIRECT: {
                    desc: `[你顺着绳索翻入三楼走廊。惨白的月光下,走廊里的一扇门缝处,似乎有什么东西正在蠕动...]`,
                    options: [
                        { text: '靠近那扇门', action: () => proceed('FLOOR_3') }
                    ]
                }
            };

            // --- 结局剧本(完美还原原定字数与意境) ---
            const endings = {
                TRUE: {
                    title: "结局一:沉默的代价",
                    text: "你拼凑出真相:\n\n民国十六年,程继业和六名学生,在藏书楼进行一场禁忌的仪式——试图召唤“门后之物”。仪式失败,七人死亡。但程继业在死前,用自己的血写下了那封信,寄给弟弟。\n\n二十年来,程继先一直在研究哥哥留下的遗物。他发现了仪式的真相,也发现了——“它们”从未离开。它们一直在等。等月圆之夜,等一个“自愿者”完成仪式。\n\n三天前,程继先来到藏书楼。他决定完成哥哥未竟的事——不是为了召唤,而是为了关闭那扇门。\n\n你推开三楼最里面的门。月光从窗外照进来。程继先坐在椅子上,低着头,像是睡着了。他的手里握着一本烧焦一半的日记。最后一页写着:\n\n『我关上门了。代价是我自己。婉宜,对不起。沈先生,若您看到这些,请告诉她——不要来找我。永远不要。』\n\n你抬起头。程继先的“身体”开始风化,碎成粉末,散落在月光里。\n\n你完成了委托。但你知道,你永远不会告诉她真相。"
                },
                DOOR_THING: {
                    title: "结局二:永远的雨夜",
                    text: "你没有找到程继先。\n\n但你在三楼最里面的房间里,看到了那扇“门”。它不是普通的门。它嵌在墙上,由暗红色的木头制成,没有任何把手、任何缝隙。\n\n但它……在呼吸。\n\n你盯着它。它也“盯”着你。你听到门后传来声音。很多人的声音。他们在低语,在呼唤——呼唤你的名字。\n\n你转身就跑。一路冲出藏书楼,冲过程家的大门,冲回你的事务所。你锁上门,关上窗,蜷缩在沙发里。\n\n门外,雨又下起来了。\n\n雨声中,你听到——有人在敲门。\n\n一下。两下。三下。\n\n你不敢开门。"
                },
                MIRROR: {
                    title: "结局三:它来了",
                    text: "你在藏书楼的镜子里,看到了自己。\n\n但那个“你”在笑。\n\n极度的恐惧压垮了你,你甚至连尖叫都发不出,跌跌撞撞地逃出了那栋大楼。你回到了事务所,试图继续过你接私活、找猫狗的日子,试图把那一夜当成一场幻觉。\n\n但是,有些东西被打破了。\n\n每天早晨,你在盥洗室照镜子的时候,镜子里的人动作总会比你快上那么一瞬。\n\n直到今天早晨,你还没有牵扯嘴角。\n\n但他先对你笑了。"
                },
                MADNESS: {
                    title: "结局四:第七个",
                    text: "你无法承受看到的那些东西。你的理智彻底崩溃了。\n\n巡捕房在三天后找到了你。你蜷缩在藏书楼三楼冰冷的地板上,怀里紧紧抱着一个烧焦的洋娃娃。无论谁跟你说话,你的嘴里只是反复呢喃着:\n\n“不可看……不可听……不可说……”\n\n他们把你送进了宛平南路的精神病院。\n\n后来的每一个月圆之夜,你都会准时在午夜醒来,对着雪白的墙壁说话。值班的护士在病历上写着你“经常出现对空交谈的幻觉”。\n\n但护士们看不见。\n\n在你的对面,一直整整齐齐地坐着七个穿着民国十六年校服的人。他们在听你说话。"
                },
                ZERO: {
                    title: "结局五:门已开",
                    text: "理智值的清零,反而让你终于明白了那三个字的真正含义。\n\n不可看——但你看了。\n不可听——但你听了。\n不可说——但现在,你要说了。\n\n你的咽喉里发出不属于人类的怪异音节,你开口,念出了你在那封烧焦的信上看到的咒文。不是为了召唤它们,而是因为——“它们”需要一具现实中的皮囊,替它们在现世说出那个名字。\n\n你说出了那个名字。\n\n沉重的吱呀声响起。门,开了。\n\n第二天,人们在藏书楼发现了你。你安安静静地坐在三楼办公室的椅子上,面带微笑,瞳孔早已涣散。法医鉴定后确认,你的死亡时间……是七天前。\n\n可是,昨夜的你,明明还活着。"
                },
                NOTH: {
                    title: "死",
                    text: "你继续坐在事务所里,听着雨声。三个月后,你死于肺病。"
                }
            };

            function triggerEnding(type) {

                document.getElementById('gameContainer').style.display = 'none';
                const scr = document.getElementById('endingScreen');
                scr.style.display = 'flex';
                // 强制重绘以触发淡入
                setTimeout(() => { scr.style.opacity = 1; }, 50);

                let endData;

                // 核心判据:补全剧本要求的理智分层逻辑
                if (type === 'WINDOW') {
                    endData = endings.MADNESS;
                    scr.style.background = "#0a0000"; // 微红底
                }
                else if (state.sanity >= 60 && state.hasDiary && state.hasFireReport && state.hasJidianLetter && type === 'DOOR' && state.trust >= 5) {
                    endData = endings.TRUE;
                    scr.style.background = "#050505"; // 黑色底
                } else if (state.sanity >= 30 && type === 'DOOR') {
                    endData = endings.DOOR_THING;
                    scr.style.background = "#0a0000"; // 微红底
                } else if (state.sanity > 0 && state.sanity < 30 && type === 'DOOR') {
                    endData = endings.MIRROR;
                    scr.style.background = "#1a1a1a";
                }
                else if (state.sanity <= 0 || type === 'ESCAPE') {
                    endData = endings.ZERO;
                    scr.style.background = "#3a0000"; // 猩红底
                } else {
                    endData = endings.NOTH;
                    scr.style.background = "#5a0000"; // 紫红底
                }

                document.getElementById('endingTitle').innerText = endData.title;
                document.getElementById('endingTitle').style.opacity = 1;

                // sanDOM.style.color = "red";
                document.body.classList.add('insane-mode');

                // 打字机特效输出恐怖文本
                const textDOM = document.getElementById('endingText');
                textDOM.innerHTML = '';
                let i = 0;
                let txt = endData.text;

                function typeWriter() {
                    if (i < txt.length) {
                        textDOM.innerHTML += txt.charAt(i) === '\n' ? '<br>' : txt.charAt(i);
                        i++;
                        // 根据标点停顿增加压抑感
                        let speed = 40;
                        let char = txt.charAt(i - 1);
                        if (char === '。' || char === '…') speed = 500;
                        if (char === ',') speed = 200;
                        setTimeout(typeWriter, speed);
                    } else {
                        document.getElementById('restartBtn').style.opacity = 1;
                    }
                }
                setTimeout(typeWriter, 2000); // 标题显示2秒后开始打字
            }

            function proceed(sceneId) {
                if (sceneId === 'DEATH_LUNG') {
                    state.sanity = 100; // 强制走归零判定或单独处理
                    triggerEnding('DEATH');
                    return;
                }

                if (scenes[sceneId] && scenes[sceneId].actionPre) {
                    scenes[sceneId].actionPre();
                }

                // 绝望防线:随时监控理智崩溃
                if (state.sanity <= 0 && sceneId !== 'OPENING' && !sceneId.includes('ENDING')) {
                    triggerEnding('MAD');
                    return;
                }

                state.currentScene = sceneId;
                refreshUI();
            }

            function renderScene() {
                let scene = scenes[state.currentScene];
                if (!scene) return;

                let desc = scene.desc;
                if (state.sanity < 30) {
                    desc += '\n\n[你的视线边缘开始扭曲,耳畔传来窸窸窣窣的低语声……]';
                }
                document.getElementById('sceneDesc').innerText = desc;

                let optionsHtml = '';
                if (scene.options && scene.options.length > 0) {
                    scene.options.forEach((opt, idx) => {
                        optionsHtml += `<button class="option-btn" data-idx="${idx}">${opt.text}</button>`;
                    });
                }
                document.getElementById('optionsContainer').innerHTML = optionsHtml;

                document.querySelectorAll('.option-btn').forEach(btn => {
                    btn.addEventListener('click', (e) => {
                        const idx = e.target.getAttribute('data-idx');
                        if (scene.options[idx].action) {
                            scene.options[idx].action();
                        }
                    });
                });
            }

            // 启动游戏
            refreshUI();
        })();
    </script>
</body>

</html>

直接复制放文本文档里就好,改一下后缀双击就可体验窒息的感觉(ps:千万不要晚上玩!!!!)

管理大大补药删帖o(>﹏<)o,违规了自己会删的,极水贴,若好玩给个赞吧。

效果图

image

@HIM 后缀改成什么额?

我还是太菜了

我知道了

改了三板了,好不容易改好了

改成.html

可以再试一下

呵呵