diff --git a/.agents/README.md b/.agents/README.md index fb890ee7..9cc2d9b4 100644 --- a/.agents/README.md +++ b/.agents/README.md @@ -53,7 +53,8 @@ | `skills/wave-close-checklist.md` | 波次收口七步检查单——所有收口铁律指向的唯一可执行清单 | | `skills/staging-ops.md` | staging 运维配方:机器分工/代码同步/后端重部署/前端构建门/冒烟门 | | `skills/ui-walkthrough-cdp.md` | 真 UI 走查配方(CDP on mini-desktop):studio/admin 走查 + CDP 七坑 + 信道探针 | -| `skills/game-e2e-cdp-harness.md` | Canvas 游戏 e2e 证据 harness:编排形制/驱动器六律/出厂红线/四件套口径(T1b-α 实证,W-G1 复用) | +| `skills/game-e2e-cdp-harness.md` | Canvas 游戏 e2e 证据 harness:编排形制/驱动器六律/出厂红线/四件套口径(T1b-α 实证;§7 = W-G1 生成游戏真玩七门 + 假绿守卫 G 门) | +| `skills/cheap-model-game-generation.md` | 便宜模型(new-api DeepSeek/MiniMax)直出可真玩轻游戏 L1 worker:链路/模型与成本/L1 纪律/坑红线(W-G1 HJ-GEN-001 实证) | **workflows/** diff --git a/.agents/knowledge/tech-decisions.md b/.agents/knowledge/tech-decisions.md index de220fd7..78c60a16 100644 --- a/.agents/knowledge/tech-decisions.md +++ b/.agents/knowledge/tech-decisions.md @@ -59,7 +59,7 @@ | # | 待确认项 | 候选 | 出处 | |---|---|---|---| -| 1 | ~~MVP 首选 LLM~~ → **已拍板**(D1,2026-06-08):主 DeepSeek + 备 Qwen,不接 OpenAI;**现行实际 = MiniMax-M2.7 经 new-api 网关**(DeepSeek key 未激活;激活后切换或修订 D1) | — | `2026-06-08-mvp业务决策.md` D1 | +| 1 | ~~MVP 首选 LLM~~ → **已拍板**(D1,2026-06-08):主 DeepSeek + 备 Qwen,不接 OpenAI;**现行实际 = new-api 网关多模型可用**(2026-06-14 网关探活实测:`deepseek-v4-flash`/`deepseek-v4-pro` + `MiniMax-M2.7`/`M3` 渠道全活;W-G1 L1 冒烟用 `deepseek-v4-flash` 打底、`pro` 升难档——原「DeepSeek key 未激活」已过时) | — | `2026-06-08-mvp业务决策.md` D1 | | 2 | v1 运行时资产移植方式 | Canvas2D 渲染 + 小游戏转换逻辑:移植为 Java 服务,还是保留 Node 微服务 | 选型审阅版 §11.2 | | 3 | 产品端域名方案 | game-studio 与 game-admin 同域不同路径,还是不同子域名 | 选型审阅版 §11.3 | | 4 | ~~MVP 登录方式~~ → **已拍板**(2026-06-10 七项全拍,见 `2026-06-10-真实鉴权与匿名玩家-review.md` §9.1):**C 验证码为主+邀请码旁路**、玩家开放注册(受限期凭邀请码)、创作/发布限 A2 白名单、互动即弹一键登录、实名提现前收、匿名=纯客户端 anonId+聚合侧剔除(glossary/contracts 已同步修订);待出 execution 版排建设(建议 M-b 后) | — | 鉴权评审版 §9.1 | @@ -79,7 +79,7 @@ | **时间线** | 双路线并存:投资人版 5 人/11 周、执行 spec 10 人/3 周;执行排期以 mvp-execution-spec 为准(含逐日计划与里程碑) | | **MVP 范围/口径** | MVP 验收以 Doc A 的 **55 项 P0 产品功能**为准;技术实现范围经 Doc C 反查 Doc B(工作量 ≈137 技术项)。详见 [`mvp-scope-and-milestones.md`](./mvp-scope-and-milestones.md) §3 | | **模块划分** | **13 模块**(含 game-module-studio 创作编排域,aigc 为无状态生成原子);能力清单拆为产品功能(Doc A)/技术功能(Doc B)/映射(Doc C) 三文档分离 | -| **生成主线** | ~~MVP=模板驱动(LLM 直出 GameConfig+固定模板)~~ → **agent 写码于插件库**(HJ-GEN-001 终审 2026-06-12;旧填参线随模板废除退役〔M-b 执行器写链语义保留复用〕;生产=便宜模型经 new-api+harness 门待 W-G1 竞标实测;agentic 基建=AgentScope 2.x,HJ-AGI-001);Dify/OpenGame=远期增强未部署 | +| **生成主线** | ~~MVP=模板驱动(LLM 直出 GameConfig+固定模板)~~ → **agent 写码于插件库**(HJ-GEN-001 终审 2026-06-12;旧填参线随模板废除退役〔M-b 执行器写链语义保留复用〕;生产=便宜模型经 new-api+harness 门〔W-G1 L1 worker + 七门真玩 harness + 3 款冒烟已实证地板成立 HJ-GEN-001(¥0.01–0.03<¥0.15 闸);全 20 款 bake-off + 四模型横比 + Claude-free judge 门待跑,配方见 [`skills/cheap-model-game-generation.md`](../skills/cheap-model-game-generation.md)〕;agentic 基建=AgentScope 2.x,HJ-AGI-001);Dify/OpenGame=远期增强未部署 | --- diff --git a/.agents/skills/cheap-model-game-generation.md b/.agents/skills/cheap-model-game-generation.md new file mode 100644 index 00000000..826a2f7a --- /dev/null +++ b/.agents/skills/cheap-model-game-generation.md @@ -0,0 +1,59 @@ +# 便宜模型直出可玩轻游戏 · L1 生成 worker 配方(W-G1 实证) + +> 适用:用 new-api 便宜模型(DeepSeek/MiniMax)在**插件库 + 装载契约**上生成**可真玩**的 Tier1 轻游戏;**质量由 harness 门保证、非模型自觉**(HJ-GEN-001)。 +> 真玩取证门见 [`game-e2e-cdp-harness.md`](./game-e2e-cdp-harness.md) §7(七门 + 假绿守卫);本篇讲**生成侧**(谁生成 / 怎么校验 / 成本 / 坑)。 +> 活样板:worker = `wg1/gen-worker/`(lane 分支 `wg1/gen-worker`);生成产物 + harness = `game-runtime/games/_wg1-gen/`;交付报告 = `wg1/gen-worker/REPORT.md`。 + +## 1. 链路(能生成代码 ≠ 能玩) + +brief 题面 → 便宜模型写 `generated-factory.js`(一个 `GameHostFactory`)→ **静态校验门** → 套**官方 generic 壳**(`entry-generic.js` + `buildGenericHostConfig`,§6)→ esbuild `--global-name=__GameBundle` 打 iife(引擎内联 ~265KB)→ P1 宿主 `bootGameHost` 装载 → 本机 Chrome+CDP **九门真玩**(A–G 假绿守卫 + H 机制/latch + I 控制手感,harness §7)→ 失败回喂错因重试 ≤N。**必须过真玩门才算 pass**——能编译 / 能渲染 / 能动 ≠ 能玩。 + +## 2. 模型与成本(2026-06-14 网关实测) + +| 模型 | 定位 | 实测 | +|---|---|---| +| `deepseek-v4-flash` | **打底**(易档) | reasoning 模型;易档 0 重试 ¥0.01;三款冒烟七门全过 | +| `deepseek-v4-pro` | 难档**升档** | Simon 0 重试 ¥0.06 | +| `MiniMax-M2.7` | 备选,**不优先** | completion_ratio=4 拉高成本 ¥0.117 贴 ¥0.15 闸 | +| `MiniMax-M3` | 备选 | 非 reasoning,响应干脆(1-token 回 ok) | + +> 网关 `100.64.0.8:3000` 共 11 模型,上四款 + `MiniMax-M2.7-highspeed` 渠道全活(各打 1 发 ping 实测);MiniMax 另有 M2/M2.1/M2.5 + highspeed 阶梯,横比可按需扩。原「DeepSeek key 未激活」(作战清单:32)**已过时**——经 new-api 网关四模型即时可用。 + +**成本口径**(¥上界,不计缓存折扣):`quota =(prompt + completion×completion_ratio)× model_ratio × group_ratio`;`¥ = quota / quota_per_unit(500000)× usd_rate(7.3)`。闸门 **¥0.15/款**。取价 `/api/pricing`、取率 `/api/status`;精确 `logs.quota` 需网关 access token(`sk-` key 无管理权,故只给上界)。 + +## 3. L1 纪律 + 坑红线 + +- **裸 openai client,不引 AgentScope**(spike VERDICT:框架 token 膨胀 + 本地开销吃便宜档单价);唯一出口 = new-api OpenAI 兼容网关,绝不直连厂商 SDK;key 走 `NEWAPI_KEY` 环境变量 / `.env`(gitignored)**绝不入库**。 +- **reasoning 模型(flash/pro/M2.7)烧 max_tokens 于 reasoning_tokens** → `max_tokens` 必须给够,否则 `finish=length`、`content` 空。 +- **代理旁路坑**:本机 clash(`HTTP(S)_PROXY=127.0.0.1:7897`)会把发往 `100.64.0.8` 的请求经代理转发 → 502;**`NO_PROXY` 大小写两版都要含网关 host**,且须在 `import openai` **之前**设。 +- **输入坐标契约坑**(便宜模型与人皆易错):输入是**逻辑像素** `x∈[0,390] / y∈[0,844]`,**非归一 [0,1]**(`game-runtime/src/host/boot-game-host.js:295`)。写错 → 能编译能渲染能动但**点击全失灵**(详见 harness §7 G 门,正是这门逮住的)。 +- **静态门禁用 token**:`import` / `littlejsengine` / `Math.random` / `Date.now` / `addEventListener` / `requestAnimationFrame` / `new AudioContext` / `document.` / `window.`——生成代码只许调插件公开面 + 6 受控面(getContext2d/onFrame/getInput/getAudioContext/time/random),随机与时钟一律走受控 `random` / `time`(确定性可复现)。 +- **bundle 入库**:`dist/` 被 `.gitignore` 吞,故 bundle 输出文件名 `bundle.iife.js`(不落 `dist/`)——它是交付物须入库。 + +## 4. 静态校验门(node 侧,出厂前省 CDP 开销) + +抽码(` ```js ` 块)→ 契约扫描(default export + `init/update/render/destroy` 四方法齐 + `getEngine` 用法 + 禁用 token 扫描)→ `node --check` 语法。不过门不进打包,把"必失败件"挡在真玩门前。 + +## 5. 边界与未做 + +- 只消费冻结契约(`game-host.d.ts` / 6 受控面 / `__GameBundle` / `bootGameHost`)**零修改**;只在 lane 分支,不推 dev/2.0.0。 +- **未做**(创始人并行 / 后续波次):全 20 款 bake-off、四模型横比(过门率/重试/¥每过门)、AigcGenerateExecutor 生产接线、碰撞穿透门 J、落一个过九门的 flash 正样本(v5 因挡板太慢挂 H/I,需 prompt 给具体挡板速度 + driver 持续按压 + 阈值校准)——规划见 [`2026-06-14-WG1-bakeoff天花板与Claude-free评估门-review.md`](../../docs/agent-specs/2026-06-14-WG1-bakeoff天花板与Claude-free评估门-review.md)。 + +## 6. 官方 latch 终态契约 + 套壳(P3 对齐,2026-06-14) + +P3 主线把 L1 产出靶定死为**官方通用装载壳**(`game-runtime/games/_generic/`,dev/2.0.0 `3108009`)。L1 **只产 `generated-factory.js`**(一个 `GameHostFactory`),套官方壳打包: + +- **套壳**:`entry-generic.js`(import `./generated-factory.js` + `src/host/generic-host-config.js` 的 `buildGenericHostConfig` 标准 7 插件装配)→ esbuild `--global-name=__GameBundle`。本 lane harness 入口(`_wg1-gen/_shared/entry-bundle.template.js`)= 同 `buildGenericHostConfig` 装配的**取证超集**(多透传 recHook/onReady 供 F 门;studio 调 `{canvas,seed}` 时 recHook no-op,一份 bundle 两用)。 +- **可测性红线**:工厂须导出 `_forensicsView() → { state: () => ({ phase, score, remaining, progress, gameoverReason, ...实体位置 }) }`(纯只读、闭包实时值);`host.state()`(`boot-game-host.js:283`)透传它。 +- **★ P0 latch 终态**:`phase ∈ 'booting'|'playing'|'gameover'`,进 `gameover` 后**恒驻留**(禁自动重开)。宿主 `inject.ts` 每 500ms 轮询 `phase` 代发 `game_end` 结算——**瞬时终态会被漏读→闭环静默断裂**,故必须驻留。实证:flash 能遵此契约(v4/v5 latch ✓)。 +- **位置态(技巧游戏)**:题面要求时额外导出 `ball/paddle` 等实体 `{x,y,vx,vy,w}`——供 harness **适配性真玩**(读球位接球)+ 确定性手感门(控制/碰撞)。 + +## 7. 质量评估:确定性门兜底 + 人锚天花板(W-G1 校准实证,2026-06-14) + +**确定性门(Claude-free,优先)** 已能把多数"坏"变可判:九门 + latch + 控制手感门 + 适配真玩。**"上下文是杠杆"实证**:同 flash 仅改接地,成本 −50%、修复轮次 −80%;player rubric 锚定(1-5 分级 + 空心→≤2)把 MAE 1.25→0.75。 + +**但便宜 player agent 做"好玩裁判"有结构性天花板**: +- **静态截图(M3 视觉)+ 运行数据(flash 文本)判不出交互动态质量**(物理/碰撞/控制手感)。实证:创始人亲玩把碰撞有问题的 pro 判 fix,两个 player 都给 fun=4(高估);text 还漏了 m27 的控制 bug。 +- **gate-H 盲打脚本会假阴性**:固定坐标 taps 打不动技巧游戏→"0 进展"≠空心(创始人把被判空心的 v2 排第 2)。解法 = **适配性真玩 driver**(读 state 接球,harness §7)。 +- **founder/人锚不可替代**(至少现阶段):没有它会把碰撞有问题的 pro 当"最佳"发出去。**校准 harness** = `wg1/gen-worker/worker/agent_loop/calibrate.py`(吃 `calibration/labels.json` 人锚,算 player vs 人锚 MAE/吻合/反样本否决)。 +- **路线**:确定性门做"地板"(能跑/真接线/有进展/latch/跟手),手感尽量拆成确定性检查(碰撞穿透门 J 规划中);拆不掉的主观手感留**创始人抽检**。 diff --git a/.agents/skills/game-e2e-cdp-harness.md b/.agents/skills/game-e2e-cdp-harness.md index f7f4caec..7f9d6d47 100644 --- a/.agents/skills/game-e2e-cdp-harness.md +++ b/.agents/skills/game-e2e-cdp-harness.md @@ -1,7 +1,7 @@ # Canvas 游戏 e2e 证据 harness 配方(CDP on mini-desktop) > 适用:插件库/生成游戏的**真浏览器输入级 e2e**(触摸轨迹→状态机推进→四件套证据),区别于 DOM 走查(那个见 [`ui-walkthrough-cdp.md`](./ui-walkthrough-cdp.md))。 -> 首跑实证:T1b-α 参考件 7 轮调试链(教训全在 harness 侧,游戏逻辑零返工)。活样板=`game-runtime/games/wanglanmei-ref/test/{e2e-input.cdp.cjs,ref-e2e-runbook.sh}`。W-G1 竞标同 harness 复用。 +> 首跑实证:T1b-α 参考件 7 轮调试链(教训全在 harness 侧,游戏逻辑零返工)。活样板=`game-runtime/games/wanglanmei-ref/test/{e2e-input.cdp.cjs,ref-e2e-runbook.sh}`。W-G1 生成游戏真玩(九门:假绿守卫 + latch 终态 + 控制手感)见 §7,样板 `game-runtime/games/_wg1-gen/_shared/play.cdp.cjs`。 ## 1. 编排形制(runbook 骨架) @@ -47,3 +47,27 @@ 2. **引擎渲出色=spec,非旧 sim 口径**:删 sim 后粒子由引擎 ParticleEmitter 渲,颜色取 `spec.colorStart`(如 particles-juice burst 给**白** r=g=b=1)。A0 G0-7 的青蓝(`b>r+30`)口径对引擎渲染**失效**→像素门判据改「任意亮像素 `max(r,g,b)>80` 计数 + `maxCh` 全屏最亮」;`maxCh≈0`=确凿反证「GL 关致引擎粒子不落 2D」的全黑假象(实测 maxCh=240,引擎真落 2D,GL 关无碍 fillRect 路)。**换引擎能力后,像素门的颜色假设必同步重核**。 3. **音频合成需 AudioContext 非空**:插件 playSfx 在 `audioOrSilent()==null` 时早返不合成→rec 不触发→探针须先 `unlockAudio`;chrome `--autoplay-policy=no-user-gesture-required` 下 headless 可合成(此项软门兜,headless 不可用时 deferred 不阻断,正确性由单测 mock-synth 注入兜)。 4. **mini-desktop scratch 部署**:6c6g `./` rsync 会吞整个 monorepo(cwd 易被重置到仓根→`tar -C ` 或绝对路径,**严禁裸 `./`**);A6 仅需 host-dev/index.html + 预建 host-bundle.js(本机 esbuild 出,含探针)+ test/harness/*.cjs + `npm i ws`,tar-pipe 几文件即可,无须全树同步。 + +## 7. 生成游戏真玩九门 + 假绿守卫 + latch 终态 + 手感门(W-G1 实证,2026-06-13/14) + +便宜模型生成游戏的真玩门(driver=`game-runtime/games/_wg1-gen/_shared/play.cdp.cjs`),在 §1-6 基础上收敛为**九门全过才 PASS**(A–G 通用假绿守卫 + H 机制/latch + I 控制手感;**H/I 逐游戏可选**,play-spec 未声明则 SKIP 向后兼容)。生成侧配方见 [`cheap-model-game-generation.md`](./cheap-model-game-generation.md)。 + +**真玩驱动两态**:`play-spec.driver` 在=**适配性真玩**(读 `_forensicsView().state()` 的实体位置自动出招,如挡板追球);否则=`play-spec.inputs` 固定序列。**盲打固定坐标打不动技巧游戏**(球没接住→0进展)是 H 假阴性根因(创始人亲玩 + v4/v5 regen 双重实证),故技巧类必用 driver。 + +| 门 | 判据 | +|---|---| +| A 装载 | `__genBooted` 真、无 `__genBootError` | +| B 未捕获 | 无 page error / unhandledrejection | +| C 掌帧 | 500ms 内 frame 增量 ∈ [20,45](@60fps,排单步假推进 + 失控空转) | +| D 真渲染 | mainContext 有亮像素(`max(r,g,b)>80`) | +| E 活性 | 多采样 **≥2 个不同整帧哈希**(排静止假死;**静态待机游戏如 Simon 须多采样**,单采样会假阴) | +| F 真接线 | `__engineCalls` 含期望 call-ID(插件能力经 `ctx.getEngine()` 真调引擎,recHook 埋点;同 §6 门②) | +| **G 输入有效** | **确定性 A/B 对照**:同 seed **无输入** vs **有输入**两实例各推进到**同帧号**,比整帧哈希——**必须不同**才证输入真生效 | +| **H 机制+latch** | `play-spec.assertAfterPlay[]` 进展断言(如剩余↓,证非空心)全过 + `expectLatch` 时真玩到 `state().phase==='gameover'` 且**驻留**(600ms 后仍 gameover)。依赖游戏经 `_forensicsView()` 导出 phase(官方 latch 契约,见 cheap-model §latch) | +| **I 控制手感** | `play-spec.controlCheck`:连点目标 x,读控制体位置(如 `paddle.x`)验**平滑逼近**(\|moved\|≥阈 ∧ dist≤容差),逮「一格一跳」/卡死/不跟手 | + +**H/I = 把"能玩/手感"从主观变确定性**(W-G1 2026-06-14):H 借官方 latch 终态契约(phase 驻留 gameover)同时验"真结束(关得上闭环)+ 真有进展(非空心)";I 借导出的控制体位置验"跟手"。前提=游戏导出可观测态(可测性红线)。**尚未确定性覆盖**:碰撞穿透(规划门 J);**物理/碰撞/控制的主观手感** player agent(静态截图)判不出、须创始人/人锚(见 cheap-model §质量评估)。 + +**G 门 = 本 lane 关键发明,专逮"假绿"**:Pong 这类带**自走动画**的游戏,输入全失灵也"能动"、能骗过 C/D/E;G 门用同帧号 A/B 哈希对照隔离出"输入到底改没改变走向"。实证逮住一处**输入坐标契约写错**(生成 prompt 误称归一坐标、实为逻辑像素 `boot-game-host.js:295`)致"能编译能渲染能动但点击全失灵"的假绿。 + +**CDP 触摸下发坑**(承 §2 律3,生成游戏侧细化):tap 须**镜像 ref `realTapAt`**——裸 `{x,y}`(逻辑像素,经 §2 律2 rect 映射)、`touchStart`/`touchEnd` **背靠背**(无 radius/force/长按),否则触摸不达 `getInput()`。坐标契约 = **逻辑像素 [0..390]/[0..844],非归一**(便宜模型与人皆易错)。 diff --git a/docs/agent-specs/2026-06-14-WG1-bakeoff天花板与Claude-free评估门-execution.md b/docs/agent-specs/2026-06-14-WG1-bakeoff天花板与Claude-free评估门-execution.md new file mode 100644 index 00000000..79d0cc0b --- /dev/null +++ b/docs/agent-specs/2026-06-14-WG1-bakeoff天花板与Claude-free评估门-execution.md @@ -0,0 +1,173 @@ +# 《W-G1 · 最小 agentic studio(黄金模板先行)+ 模型路由三阶段》执行版 master spec + +> **状态**:执行版 master spec · 2026-06-14 重写(supersede 单角色 bake-off 框架)· 待 Round-2 review。 +> **上游**:[review 版 §8](2026-06-14-WG1-bakeoff天花板与Claude-free评估门-review.md)(决策+战略扩展+守护栏,创始人已确认);Round-1 四评审(对抗/可行/范围/一致)findings 已纳入本版。 +> **本 lane**:`wg1/gen-worker`。代码 `wg1/gen-worker/` + `game-runtime/games/_wg1-gen/`;judge rubric → `contracts/prompts/`(或先暂存 lane,见 §9)。**零改冻结契约 / 不碰主线 / 不推 dev·2.0.0**。 +> **定位转变(关键)**:这不是"便宜模型写代码",是 **agentic 多角色 studio**——一队便宜模型 agent(设计/代码/修复/**player panel**)在 AgentScope 上协作产出游戏,player agent 真玩真判,studio 闭环修到"真能玩+好玩"。**Opus=脚手架(建门/校准/改 agent scope),建好即退,生产无 Claude。** + +--- + +## 结论先行 + +1. **主干**:最小 studio = 设计→代码→七门(确定性地板)→**player panel(M3 视觉+flash 文本)真玩真判**→回喂修复 ≤5。黄金模板先行:先在**一款(打砖块 Breakout)**打磨透整条闭环,再克隆扩。 +2. **模型 = 可替换配置旋钮,分三阶段**:Stage1 **flash/M2.7(便宜双家)**+M3 先跑通 → Stage2 pro+M3 再生成对比 → Stage3 逐 agent×逐模型 评分矩阵 → model routing。 +3. **命门验真闸(不可省)**:player agent 判"好玩"必须**对创始人亲玩锚定**(含"能跑但无聊"反例集),证便宜 player 真跟人类相关再信。否则是 vibes。 +4. **交付即资产**:打磨过的 agent 层(角色/循环/门/自修复)+ 模型性能矩阵(喂 routing)+ player 校准结论 + 引擎/插件库缺口清单。 + +--- + +## 1. 目标与范围 + +**本期目标(可验收)** +1. **最小 studio 闭环**(on AgentScope 进程内多 agent):Breakout 一款,设计→代码→七门→player panel→自修复 ≤5,端到端真跑通(非桩)。 +2. **player panel + 校准件**:M3 视觉位 + flash 文本位多人格;校准 panel↔创始人亲玩一致率(含反例集)。 +3. **模型路由三阶段**:Stage1 跑通(flash+M3)→ Stage2 对比(pro+M3 再生成一版)→ Stage3 逐 agent×模型评分矩阵。 +4. **Opus 改 agent scope 的 lift**(单变量隔离、held-out、分布对照——见 §9 方法约束)。 +5. **缺口清单**:Breakout 暴露的引擎/插件库短板(为克隆扩款做准备)。 + +**非目标(本期不做)** +- art/music 生成角色(**后续波次走 MiniMax/mmx-cli**)、全 20+ 款 bake-off、4 档全靶集、生产接线、quality_score MQ 化。 +- 不 fork AgentScope 内核(只改我方 agent 层);Opus 不进生产环;音乐质量不硬判(无验证音频模态)。 + +--- + +## 2. 前置条件(均已核实 · 2026-06-14) + +| 前置 | 状态 | 证据 | +|---|---|---| +| AgentScope 2.0.1 | ✅ 三闸全过 | `spikes/agentscope-wg1/VERDICT.md`(分布式/持久化/L1 开销);**进程内多 agent 单机即可,避 #1868 多实例 bug** | +| 文本模型 flash/pro | ✅ 可路由 | 网关探活;flash ¥0.0015/1k out、pro ¥0.0058/1k out | +| **视觉模型 M3** | ✅ 能看且准 | 双色图实测答对"左红右绿";¥0.0175/1k out(贵 11×,输出限短) | +| 七门真玩 harness | ✅ 可信 | `_wg1-gen/_shared/play.cdp.cjs`;golden-path 自检无假绿 | +| L1 worker 底座 | ✅ 已落地 | `wg1/gen-worker/worker/`(含薄自修复循环,Simon 2 重试真过) | +| MiniMax 生图/音乐 | ✅ 能力在 | `mmx-cli` skill;后续 art/music 波次用 | +| 创始人好玩基线 v2 rubric | ⚠️ 未定稿 | W-T1b §4"待过目";**故 player 校准锚=创始人亲玩本人,不依赖未定稿 rubric**(见 §6) | + +--- + +## 3. 总体架构 + +```mermaid +flowchart TB + OPUS["Opus 脚手架(写角色prompt/人格·校准·改agent scope·建好即退)"] + subgraph STUDIO["最小 agentic studio · AgentScope 进程内多 agent · 模型=配置旋钮"] + BRIEF["brief"] --> DESIGN["设计 agent"] + DESIGN --> CODE["代码 agent(玩法/机制/平衡/关卡/脚本=生成域)"] + CODE --> VAL["静态校验门"] --> BUNDLE["esbuild __GameBundle"] --> PLAY + PLAY["七门真玩(确定性地板·假绿守卫)"] -->|"挂:门+证据"| FIX["自修复 agent"] + FIX -->|"≤5(含模型升档)"| CODE + PLAY -->|"过七门"| PANEL["player panel:M3视觉位 + flash文本位·多人格
真玩→判完整度+好玩+具体问题"] + PANEL -->|"问题回喂"| FIX + end + OPUS -. "写/校准" .-> DESIGN & CODE & PANEL + PANEL --> ANCHOR["校准件:panel ↔ 创始人亲玩一致率(含'能跑但无聊'反例集)"] + style STUDIO fill:#1a2a3a,stroke:#4090c0,color:#fff + style ANCHOR fill:#3a2a2a,stroke:#c06060,color:#fff +``` + +--- + +## 4. 模型路由(本版新增核心 · per-agent 配置旋钮) + +**原则**:模型可替换 → **per-agent 模型在 config(`worker/models.yaml`)声明,不硬编码**。换配置即换模型,支撑对比与后续路由。 + +**三阶段**: + +| 阶段 | 配置 | 目的 | +|---|---|---| +| **Stage 1 先跑通** | 文本 `deepseek-v4-flash` + `MiniMax-M2.7`(便宜双家)· 视觉 `MiniMax-M3` | 验 studio 闭环端到端通 + 早期 DeepSeek×MiniMax 跨家对比信号(M2.7 输出贵些但要跨家信号) | +| **Stage 2 出对比** | 文本 `deepseek-v4-pro` · 视觉 `M3`,**同款再生成一版** | 同 brief/同 studio 只换模型 → 对比真实效果(过门率/好玩/手感) | +| **Stage 3 评+路由** | 逐 agent × 逐候选模型 跑,采集各 agent 输出 | **模型性能评估矩阵**(哪个模型配哪个角色)→ 喂 engine 优化 + model routing | + +**默认起步配置(Stage 1)**: + +| Agent | Stage1 模型 | 说明 | +|---|---|---| +| 设计 / 代码 / 自修复 | `flash` + `M2.7`(便宜双家,逐 agent 可配) | 先跑通 + 早期跨家对比(同款各跑一版) | +| player·视觉位 | `MiniMax-M3` | 唯一视觉;输出强制短(结构化 verdict+一句理由)控成本 | +| player·文本位 | `deepseek-v4-flash` | 只读结构态,给 panel 异构 | +| (后续)art 生成/判定 | MiniMax 生图 / `M3` 判 | 走 mmx-cli;本期不接 | +| (后续)music 生成 | MiniMax 音乐 | 走 mmx-cli;质量留人/指标 | + +**成本纪律**:Stage1 最省(flash 统一);pro/对比开销 Stage2 才花;**实验期"测而不闸"**(照测 ¥/款,不拿 ¥0.15 卡质量),出分级结论。reasoning 档(flash/pro)给够 max_tokens;M3 非 reasoning 快、输出限短。 + +--- + +## 5. 角色契约(契约先行 · 最小集) + +| Agent | 输入 | 输出 | 默认模型 | +|---|---|---|---| +| 设计 | brief 题面 | 设计稿{机制/胜负/操作/juice 要点} | flash | +| 代码 | 设计稿 | GameHostFactory 源码(默认导出,只调插件面+6 受控面) | flash→(Stage2)pro | +| 自修复 | 失败门(七门哪挂)+证据 + player 问题 | 修订源码 | 跟随代码档;**连败升档**(flash→pro) | +| player(视觉) | 截图序列 + 结构态探针 | {完整度判, 好玩判, 具体问题[]} | M3 | +| player(文本) | 结构态探针 | 同上(无截图) | flash | + +> 玩法/机制/平衡/关卡/脚本本期**合于代码 agent 生成域**(模板哲学);拆细为独立 agent 属后续波次。 + +--- + +## 6. player panel 校准(命门验真闸 · Round-1 BLOCKER-2 存活形态) + +- **锚 = 创始人亲玩本人**(非未定稿 rubric、非 Opus):一组样本(含**故意"能跑但无聊"反例**:单机制/无失败惩罚/无进度感)→ 创始人亲玩打分 vs player panel 打分 → 量一致率 + **区分力**(panel 能否把反例判否)。 +- **达标才信**:一致率/区分力达标→panel 判进流程;不达标→该维度退回创始人亲玩,并记"便宜 player 判不了 X"为天花板结论(**无论达标与否都是有效交付**)。 +- **七门是前置地板**:player 只玩过七门的件(挡"对坏游戏幻觉好玩")。 + +--- + +## 7. 涉及文件 + +| 模块 | 路径 | 动作 | +|---|---|---| +| 模型路由 config | `wg1/gen-worker/worker/models.yaml`(新) | per-agent 模型声明 | +| agent 编排层 | `wg1/gen-worker/worker/agent_loop/`(新·框架中性名) | AgentScope 角色/进程内编排/状态;框架适配隔离 | +| 复用底座 | `worker/{_client,prompt,validate,run,cost}.py` | 以现有薄自修复循环增量,**非搬 agent-loop-v1 1269 行** | +| player 驱动 | `_wg1-gen/_shared/play.cdp.cjs` | 加 player 感知钩子(截图导出 + 结构态);**采集项待 panel 设计** | +| 校准件 | `wg1/gen-worker/calibration/`(新) | 反例集 + 创始人亲玩打分录入 + 一致率算 | +| judge rubric | `contracts/prompts/`(或暂存 lane) | Opus 派生(对齐创始人 eval 门,未定稿则暂存) | +| 黄金款产物 | `game-runtime/games/_wg1-gen/breakout/` | factory + bundle + evidence | + +--- + +## 8. 波次 + +| 波次 | 内容 | 完成条件 | +|---|---|---| +| **P0 跑通** | AgentScope 进程内 设计→代码→七门→player→自修复 闭环,Breakout 一款,**Stage1 配置(flash/M2.7 + M3)** | 一款端到端真跑通(非桩)+ shakedown 初裁 | +| **P1 校准** | player panel 多人格 + 校准件(创始人亲玩 vs panel,含反例) | 一致率/区分力表 + "信哪些维度"结论 | +| **P2 对比** | **Stage2**:pro+M3 同款再生成 → 与 Stage1 对比真实效果 | 模型对比表(过门率/好玩/手感/¥) | +| **P3 评+路由** | **Stage3**:逐 agent×模型评分矩阵 + Opus 改 agent scope 测 lift | 模型性能矩阵 + lift 报告(单变量/held-out) | +| (后续) | art/music 角色(MiniMax)、克隆扩款、4 档靶集、获奖压测 | 下一 spec | + +--- + +## 9. 边界失败路径(纳入 Round-1 findings) + +| 失败 | 处置 | +|---|---| +| AgentScope 进程内编排不稳 | 退薄 Python 编排(`--no-agentscope`);记 shakedown | +| 创始人 eval 门 rubric 未定稿 | player 校准锚用**创始人亲玩本人**,不阻塞;rubric 我起草、事后采纳 | +| player panel 一致率不达标 | 该维度退创始人亲玩 + 记"便宜 player 判不了 X"(有效交付,非失败) | +| 自修复 5 次仍不过 | kill,记 `unrepairable`+失败门分布 + 缺口 | +| **获奖/超界款** | 仅**源码证伪的硬边界(3D)**豁免;tilemap/网格/文本/swipe 是 🟡 半缺口,造不出**算真失败**、三分类归因(3D硬界/模型顶/未尽改进),**不许用"超界"洗低产出** | +| 成本超 ¥0.15 | 运行时记 `over-budget`(测而不闸,主力档可加软闸) | +| Opus 在环泄漏 | CI 断言生产路径(七门+断言+便宜 player)零 Claude 依赖 | +| lift 归因混淆 | **单变量隔离改进**(一次只改一类)、**held-out brief 验集**(调测分离)、N≥3 重复取分布、temperature=0;≤2 轮收敛,禁反复调凑 lift | + +--- + +## 10. 验证 / 完成 / 回滚 + +**验证**:P0 单款真跑通(非桩);七门全过;校准一致率/区分力表;Stage1↔Stage2 对比表;模型矩阵;lift(单变量/分布/显著性);CI 断 Claude;每结论标【实测】/【推断】/【假设】。 +**完成**:Breakout 闭环跑通 + player 校准结论 + 模型对比 + 矩阵 + lift + 缺口清单 + shakedown 裁决 + 沉淀 `.agents/`。 +**回滚**:全 lane,`git revert` 净回滚;`--no-repair` 退已验收 L1 裸路;`--no-agentscope` 退薄编排;judge rubric 先 lane 再并 Registry。 + +--- + +## 风险与假设(诚实标注) + +- **[verified·2026-06-14]** AgentScope 2.0.1 三闸过、flash/pro/M3 可路由、M3 视觉准、七门可信、L1 底座在——均带证据(§2)。 +- **[inferred]** 便宜 agent 队能产 Breakout 级可玩+好玩件——待 P0/P1 验。 +- **[assumption·核心待验]** 便宜 player 判好玩跟人类相关——靠 §6 校准定论;不相关则退亲玩。 +- **[assumption]** agent-scope lift 显著为正(harness 复利)——单变量/held-out 测;证伪则记模型天花板。 +- **[守护栏·创始人确认]** 只改我方 agent 层、AgentScope 可替换不 fork、Opus 建好即退不进生产、便宜模型生产 in-loop、模型 per-agent 可配置可路由。 diff --git a/docs/agent-specs/2026-06-14-WG1-bakeoff天花板与Claude-free评估门-review.md b/docs/agent-specs/2026-06-14-WG1-bakeoff天花板与Claude-free评估门-review.md new file mode 100644 index 00000000..722d9656 --- /dev/null +++ b/docs/agent-specs/2026-06-14-WG1-bakeoff天花板与Claude-free评估门-review.md @@ -0,0 +1,177 @@ +# 《W-G1 · 便宜模型生成能力天花板 + Claude-free 评估门》设计稿(review 版) + +> **状态**:review 版 · 2026-06-14 · 顶层走查稿(未改任何运行时代码)。 +> **定位**:在创始人 [WG1-20 经典轻游戏基准 review](2026-06-13-WG1-20经典轻游戏基准-review.md)(能力覆盖矩阵)之上,**叠加获奖款压测批**,把"便宜模型(DS-V4/M3/M2.7)+ 当前引擎/插件库"的**生成能力天花板**测出来;并一次性建成**不依赖 Claude 的好玩/完整度评估门**(Opus 仅作脚手架/校准器,生产退场),产出引擎/插件库缺口修复清单。 +> **本 lane**:分支 `wg1/gen-worker`。代码落 `wg1/gen-worker/`(Python worker)+ `game-runtime/games/_wg1-gen/`(生成产物+harness);**零修改冻结契约**(game-host.d.ts / boot-game-host.js / 6 受控面 / __GameBundle / bootGameHost,只消费)。 +> **关联**:七门真玩 harness 见 [`wg1/gen-worker/REPORT.md`](../../wg1/gen-worker/REPORT.md);好玩基线 v2 见 [`W-T1b review`](2026-06-12-W-T1b-Runner与双层模板-review.md);agent-loop-v1 judge 决策表 E1–E6 与 generation-spike pilot 三 agent 闭环为本设计直接前身。 + +--- + +## 结论先行(三句话) + +1. **review/可玩性验证已是生产 agent 职责,且有成体系设计**——只是载体从「Claude review」换成「**确定性 harness 门 + 便宜模型自评/互评 + 数据回路**」。最大缺口是"**好玩/完整度的可机判 rubric 尚未定稿**"。本设计就补这块。 +2. **天花板 = 两条断崖**:① 便宜模型**生成过门率**断崖;② 便宜模型 **judge 与 Opus 金标准一致率**断崖。按 4 档难度梯(冒烟/主力/经典压测/获奖压测)各自定位,顺带暴露插件库硬边界。 +3. **Opus 只在"建门/校门"在场,建好即退**:把好玩基线 v2 五要素蒸馏成**生产可跑、Claude-free** 的 rubric+确定性断言+校准过的便宜模型 judge。生产由 harness 门 + 便宜模型 judge + quality_score 承接。 + +--- + +## 1. 背景(事实基,带出处) + +- **谁生成**(创始人 2026-06-12 裁定):Fable 只造引擎,**生产生成 = 便宜模型**(new-api 网关 `100.64.0.8:3000`,只有 DeepSeek/MiniMax,**无 Claude**)。 +- **现有验证设计**(五块成一线,护城河=harness+评估+数据): + - 意图层:XC6「质量门禁分层自动化(验收不能只看能运行)」/ XP5「商业化就绪评分」/ P2「永不交付坏游戏」+GP3 / C5-GC5「评估先行,通过率=放行条件」。 + - 落地层:① prompt 治理四道闸;② agent-loop-v1 **judge 决策表 E1–E6**(`ledger.jsonl` 实证 accept/fix/kill/schema_retry);③ generation-spike **pilot 三 agent 闭环**(策划/对抗红队/玩家裁决);④ **quality_score** 数据回路(`computeQualityScore=clamp(60×完玩+20×like+20×share)`→feed 重排,已 e2e);⑤ **好玩基线 v2** 五要素(手感/美术统一/音乐/结构深度/角色壳)。 +- **已落地实证**(本 lane):便宜档 deepseek-v4-flash 生成 Pong/Simon/打地鼠 **三款七门全过**,单款 ¥0.01–0.03(<¥0.15 闸门)。**但这三款偏简单,证地板不证天花板**——这正是本设计要解决的。 +- **创始人并行**:[WG1-20 经典轻游戏基准 review](2026-06-13-WG1-20经典轻游戏基准-review.md) 已盘点 20 款经典街机的能力覆盖(~12 款✅、4 类缺口:文本 HUD/网格/CCD/FSM、已规避 A*),给出 6/8/6 三批切分;**自动 judge 评分门尚未建**(自标"五要素精确判据需开工前从评估门 spec 取齐")。 + +--- + +## 2. 目标 / 非目标 + +**目标(本期交付)** +1. **生成能力天花板画像**:便宜模型(DS-V4-Pro/Flash、M3、M2.7)在 4 档难度梯上的过门率梯度曲线 + 断崖点 + 四模型横比(过门率/重试/¥每过门 vs ¥0.15)。 +2. **Claude-free 好玩/完整度评估门**:Opus 蒸馏出**跨品类通用 rubric + 确定性行为断言集**,并**校准便宜模型 judge**(一致率达标才放行进生产)。 +3. **agentic 多步自修复 worker(L2)**:生成→七门真玩→失败回喂→便宜模型自修复→重试≤N;兼做 **AgentScope shakedown**(分布式/持久化/L1 开销;验不过切 LangGraph)。 +4. **引擎/插件库缺口修复清单**:4 类经典缺口 + 获奖款暴露的新硬边界(3D/tilemap/像素手感),各拖垮多少款 → 补门面优先级,喂插件库扩展波 v2。 + +**非目标(本期不做)** +- 不改冻结契约、不碰主线、不推 dev/2.0.0。 +- 不做素材生成(ComfyUI/图音)、不接 AigcGenerateExecutor 生产接线、不做 quality_score 的 MQ 异步化(M5 大头,创始人轨)。 +- 不追求获奖压测批的高通过率(本档测上限,重在出缺口实证 + judge 断崖定位)。 +- **美术真好看/音乐真好听/真机 60fps 手感**等感知项**不假装自动判**——显式留创始人亲玩主判(≤3 轮)。Opus 不在生产环。 + +--- + +## 3. 推荐方案 + +### 3.1 四档难度梯靶集(下三档=创始人能力矩阵,第四档=真天花板) + +```mermaid +graph LR + A["批1 冒烟·6款
全✅易
验管线打通"] --> B["批2 主力·8款
✅为主·中
量化文本HUD/网格/swipe出错率"] + B --> C["批3 经典压测·6款
含❌难
证CCD/网格状态机缺口"] + C --> D["批4 获奖压测·K款
真·上线获奖showcase
测好玩/完整度真天花板+插件库硬边界"] + style D fill:#3a2a4a,stroke:#a060c0,color:#fff +``` + +- **批1–3 = 创始人 WG1-20 的 6/8/6**:便宜地验管线 + 系统量化 4 类经典缺口出错率。 +- **批4 获奖压测(本设计新增,你拍板加)= 真天花板**:从你给的 20 款获奖清单里**按"映射到能力缺口 + 探硬边界"原则**挑选(终选见 §7 待确认),候选映射: + +| 获奖款 | 压什么 | 预判 | +|---|---|---| +| LittleJS Platformer | tilemap 网格 + 文本 HUD + 相机 | 🟡 网格无门面,边界探针 | +| Celeste Classic / 2 | **像素级动量手感(shougan 上限)** + tilemap | 🟡 手感是 judge 一致率主战场 | +| Stolen Sword | 战斗 FSM + 多状态动作 | 🟡 FSM 自写 | +| Dank Tombs / Tiny Dungeons | 俯视网格地牢 + 氛围光照 | 🟡 网格 + palette-post | +| Invader Overload | 弹幕 + 粒子 + 高速碰撞 | 🟡 CCD 边界 | +| **Q1K3(3D FPS)** | **3D 渲染** | **❌ 硬边界实证(预期造不出)** | + +> Q1K3 单列为"硬边界实证":插件库 6 受控面无 3D,**预期 ❌**——这是**发现("哪些类型超出插件库"=W-G1 核心交付项),不是失败**。 + +### 3.2 生产闭环:五层叠门(Claude-free) + +```mermaid +flowchart TD + G["便宜模型生成 GameHostFactory"] --> L0 + L0["① 可测性红线
必导出取证清单·不可机测不许过门"] --> L1 + L1["② 确定性 harness 七门
CDP真玩·零LLM·命门(含G输入有效A/B对照)"] --> L2 + L2["③ rubric派生确定性断言
五要素→checklist机测字段·只判达没达阈"] --> L3 + L3["④ 便宜模型自评/互评agent
策划/对抗红队/玩家裁决(pilot三角色生产化)"] --> L4 + L4["⑤ 好玩基线v2评估门
均分≥4 + S锚点≤2s + B预算 + 合规"] --> ONLINE + ONLINE["上线 quality_score 反哺
完玩/like/share→feed重排"] + L1 -. "任一门挂→回喂具体失败门+证据" .-> G + style L1 fill:#2a3a4a,stroke:#4090c0,color:#fff + style L2 fill:#2a3a4a,stroke:#4090c0,color:#fff +``` + +- **②③ 确定性、零 LLM**;**④ 便宜模型**(经 Opus 校准过一致率);**感知项**留创始人亲玩。 +- **agentic 自修复** = 虚线回喂:七门里**哪门挂了 + 证据**(如 G 门:输入无效)→ 便宜模型针对性自修 → 重试 ≤N。这是 agent-loop-v1 E1–E6 思想 + 我七门 harness 的合并,迁到 AgentScope。 + +### 3.3 Opus 的三个且仅有职责(脚手架,生产退场) + +```mermaid +graph TD + O["Opus(实验脚手架)"] --> R1["①产rubric+确定性断言
五要素从单样例(暖阳小卖部checklist.json)
抽象成跨品类通用门→进评估门spec"] + O --> R2["②校准便宜模型judge
Opus金标准 vs 便宜judge一致率
达标放行/分歧回退确定性断言或亲玩"] + O --> R3["③去LLM化优先
能转确定性断言的(七门式A/B·字段阈值·闭环可达)
优先转·最小化对任何LLM依赖"] + R1 & R2 & R3 --> EXIT["蒸馏完成→Opus退场
生产=harness门+便宜judge+quality_score"] + style EXIT fill:#2a4a2a,stroke:#40a040,color:#fff +``` + +--- + +## 4. 关键设计决策与取舍 + +| 决策 | 选择 | 取舍/理由 | +|---|---|---| +| 基准轴 | 经典阶梯 + **获奖压测批叠加** | 经典阶梯便宜验管线+能力矩阵;获奖款探真天花板+暴露插件库硬边界。additive,不撞创始人并行轨。 | +| 生成模式 | L1 单发 → **L2 agentic 自修复** | 获奖款单发必造不出,必须多步;同时兼做 AgentScope shakedown。代价:token/¥上升、编排复杂度↑,故重试设上限 N、成本仍对照 ¥0.15 闸。 | +| judge 门归属 | **我建**(Opus 蒸馏) | 最大缺口、最高价值。**风险**:须与创始人并行 judge 工作**契约对齐**——我产的 rubric/断言要能**并入评估门 spec**,不另起炉灶(见 §6)。 | +| Opus 定位 | 仅脚手架/校准器 | 生产无 Claude;蒸馏产物必须确定性 or 便宜模型可执行,**严禁偷偷依赖 Opus 在环**。 | +| 感知项(美术/音乐/手感) | 不自动判,留亲玩 | 现无多模态评判器;诚实分层,不冒充"自动判好玩"。 | +| 框架 | agentic 闭环跑 AgentScope | 验分布式/持久化/L1 开销;若不抵其复杂度,换轨触发→LangGraph or 自研薄编排(遵框架选型 review)。 | + +--- + +## 5. 验收标准 + +1. **生成天花板**:产出 4 档 × 4 模型的**过门率梯度表** + 断崖点;¥每过门款全 ≤¥0.15(获奖压测档可超,需标注并解释)。 +2. **judge 校准**:产出便宜模型 judge **vs Opus 金标准一致率表**(按品类×难度);给出"哪些要素便宜模型够判 / 哪些必须留确定性断言 or 亲玩"的结论。 +3. **评估门资产**:跨品类 rubric + 确定性断言集成文,且**确定性占比最大化**(可机判项 / 总项)。 +4. **缺口实证报告**:4 类经典缺口 + 获奖款新边界,各拖垮款数 + 补门面优先级(预判:文本 HUD > 网格 > swipe/拖拽 > CCD swept;获奖档另出 3D/tilemap/手感 边界结论)。 +5. **诚实分层**:每项结论标 【实测】/【推断】/【假设】,三层证据(结构/可运行真玩/可接受)互不顶替。 + +--- + +## 6. 影响面 / 风险 / 兼容性 + +- **[兼容·低风险]** 零修改冻结契约,只在 lane 新增;新建独立日期 review 文件,与创始人 WG1-20 review 不同文件 → **零合并冲突**。共享 `.agents/` **不碰**(待你后续通知再蒸馏入库)。 +- **[已核实·无阻塞 · 2026-06-14]** 探网关实测:11 模型,bake-off 四目标 **`deepseek-v4-flash` / `deepseek-v4-pro` / `MiniMax-M2.7` / `MiniMax-M3` 全部渠道活、可路由**(各打 1 发 ping;flash/pro/M2.7 为 reasoning 模型 finish=length 属正常,M3 1-token 回 `'ok'`)。早前"DeepSeek key 未激活"(作战清单:32)**已过时/或指厂商直连**——经 new-api 网关四模型即时可用,**全 20+ 款 bake-off 无人侧 blocker**。(另:MiniMax 实有 M2/M2.1/M2.5/M2.7/M3 + highspeed 阶梯,横比可按需扩。) +- **[协调风险]** judge 门 rubric 与创始人并行评估门 spec **可能口径漂移**。缓解:我的 rubric/断言从**第一天就按"可并入评估门 spec"设计**,落地位置待 §7 拍(进 `contracts/prompts/`/评估门 spec 需对齐,先留 lane 亦可)。 +- **[能力边界]** 获奖款用**完整 LittleJS**(drawText/tilemap/camera/3D),我们受控子集表达不了的部分**预期 ❌**——这是设计内的发现,非失败。 +- **[假设]** 好玩基线 v2 五要素的精确阈值/权重/硬软门**至今未定义**(意图清单 XP5 五维/XC6 八维只做了并集)。本设计**产出**这些阈值作为 Opus 蒸馏物,**但意图清单已冻结**,落点是 master spec(HJ-GEN-001)或评估门 spec,**不改意图清单**。 + +--- + +## 7. 待确认项(走查后拍) + +1. **获奖压测批 K 款终选**:§3.1 候选映射够不够?Q1K3(3D)是否确定单列"硬边界实证"(预期 ❌)?其余 19 款里还想点名哪几款? +2. **judge 门 rubric 落地位置**:进 `contracts/prompts/`(与创始人评估门 spec 同源)还是**先留 lane `wg1/gen-worker/`**,待创始人评估门 spec 定稿再合并?(关系到协调风险大小) +3. **重试上限 N**(agentic 自修复)与**过门率断崖判定阈值**(如连续档过门率跌破 X% 即判天花板)。 +4. **AgentScope 引入粒度**:整条 agentic 编排上 AgentScope,还是先"裸 client + 薄编排"验自修复闭环、再判是否值得上 AgentScope?(影响 shakedown 结论口径) + +--- + +## 风险与假设(诚实标注) + +- **[verified]** 现有验证设计五块、quality_score 公式、七门 harness、创始人 WG1-20 能力矩阵——均带出处(见 §1 链接 + REPORT.md:38-54 + EventIngestServiceImpl.java:302-326)。 +- **[verified]** 本 lane 三款冒烟七门全过、¥0.01–0.03,已实证(REPORT.md)。 +- **[inferred]** "便宜模型能产出获奖款级可玩件"是**待验天花板**,本设计不预断;预期在某难度档出现过门率断崖。 +- **[inferred]** Q1K3 等 3D 款预期 ❌——基于插件库 6 受控面无 3D 透出(源码证伪,见创始人 review A.2)。 +- **[assumption]** 便宜模型够不够当 judge 判完整度,**无直接数据**;靠 Opus 校准一致率定论(本设计核心待验项之一)。 +- **[verified·2026-06-14]** bake-off 四模型(flash/pro/M2.7/M3)经 new-api 网关探活全部可路由,**无人侧 blocker**;早前"key 未激活"系引旧 doc(作战清单:32)过时表述,已核实纠正。 + +--- + +## 8. 决策记录 + 战略扩展(2026-06-14 拍板,supersede §7 待确认) + +**§7 四项落定:** +1. **获奖压测批 = 全 20 款获奖清单**入压测档(Witchcat / Penny the Pumpkin / 13th Floor / Killed By A Pixel / Celeste Classic·1k·2 / Q1K3 / Tiny Dungeons / Greeble·2 / LOSSST / LittleJS Platformer / Stolen Sword / MINIPUNK / Evil Glitch·2 / Dank Tombs / Invader Overload / Lost Beacons)。Q1K3 等 3D 仍按"预期 ❌ 硬边界实证"处理(发现而非失败)。 +2. **judge 门 rubric 落地 = canonical `contracts/prompts/`**(第 8 契约 Registry,与创始人评估门 spec 同源)→ master spec 含"与创始人 eval 门契约对齐"步,降协调风险。 +3. **agentic 自修复重试上限 N=5**;过门率断崖阈值(我提默认,待确认):某难度档过门率跌破 **50%** 即判该档为便宜模型生成天花板边界。 +4. **AgentScope 引入 = 整条 agentic 编排上 AgentScope**(不走"裸 client+薄编排"过渡档)。 + +**战略扩展(本次最重要):** +- **Agent(AgentScope / 我方 agent 层)= 核心资产**(呼应 XC1/GC1「harness=复利核心资产」)。 +- **Opus 职责扩展**:不止建 Claude-free judge 门,**还要 debug / 改进 agent scope**——使便宜模型在打磨过的 agent 框架内产出**高质量任务**。目标从"测便宜模型天花板"升级为"**用更好的 agent harness 抬高天花板**"(harness 复利:工程沉淀在 harness,单次生成是消耗品)。 +- **Fable 暂不可用 → 脚手架 / 教师 / 编排层统一降级用 Opus**(生产 in-loop 仍是便宜模型)。 + +**架构守护栏(working 解读,待创始人纠正):** +- "改进 agent scope" = 改进**我方 agent 层**(任务协议 / 状态模型 / 工具接口 / 循环模板 / 门禁 / 自修复逻辑 / judge 校准——GC9 明列的"要固化"项),**AgentScope 框架本身保持可替换**(不 fork 其内核,保留换轨 LangGraph 选项,遵 XC3/GC9 框架可替换铁律)。 +- 便宜模型仍是**生产 in-loop 角色**(生成 / 自修复 / judge);**Opus = builder / teacher / calibrator,建好即退,不进生产环**(否则"生产无 Claude"前提破)。 + +**质量评估架构 reframe(2026-06-14 创始人亲玩校准后拍定):** +- **确定性 gate-H = 可玩性真值 / 地板(Claude-free)**:九门(七门假绿守卫 + H 机制/latch + I 控制手感)+ 适配性真玩 driver(读 state 接球,解盲打假阴性)。手感尽量**拆成确定性门**(latch 终态驻留 / 控制跟手 / 碰撞穿透[门 J 规划]);拆得掉的全自动判。 +- **player panel = 主观层,消费 gate-H,有结构性天花板**:便宜 player(M3 静态截图 + flash 数据)**判不出物理/碰撞/控制的交互手感**——实证创始人把碰撞有问题的件判 fix、两 player 均高估(fun=4),text 还漏控制 bug。故 player 只判**拆不掉的主观**好玩/美术/节奏,且须人锚校准(`calibrate.py` vs 创始人 `labels.json`)。 +- **创始人 / 人锚不可替代**(现阶段):是 gate-H 假阴性(盲打)+ player 漂移的最终纠偏。**Opus 退场后,生产 = 确定性门 + 便宜 player + 创始人抽检 三层**,无 Claude。 +- **gate-H 推广 = design agent 自产 gate-spec**(exportState / driver / controlCheck / assertAfterPlay / expectLatch)→ 确定性门适用**任意游戏**,不再手写 brief(已建:`roles.py` 产 spec、`studio.py` 抽取合入;实证 design agent 能产合法 spec)。 diff --git a/game-runtime/games/_wg1-gen/.agent b/game-runtime/games/_wg1-gen/.agent new file mode 100644 index 00000000..066fd439 --- /dev/null +++ b/game-runtime/games/_wg1-gen/.agent @@ -0,0 +1,38 @@ +# .agent — games/_wg1-gen(W-G1 便宜模型生成游戏 · 隔离暂存区) + +owner:W-G1 lane(branch `wg1/gen-worker`)| 状态:建设中(P1 harness 基建) + +## 目标 +承载「便宜模型(new-api: deepseek-v4 / MiniMax)生成的 GameHostFactory → bundle(__GameBundle iife) → P1 宿主真玩」的全部产物与薄 harness 壳。 +验证 W-G1 核心假设:**便宜模型能在插件库+装载契约上写出可真玩的轻游戏**(质量由 harness 门保证,非模型自觉)。 + +## 为什么落在 game-runtime/games/ 而非 wg1/gen-worker/ +生成游戏【本质是 game-runtime 游戏】:entry-bundle 动态 import `littlejsengine`、gen wiring import `../../../src/plugins/*`、复用 `../../wanglanmei-ref/src/ref-host-config.js`。 +esbuild(scripts/build.mjs) 用默认解析(从入口文件上溯找 node_modules),故入口必须在 game-runtime 树内 node_modules 可达处。 +→ 放此新建子目录,**零修改任何既有/冻结文件**(game-host.d.ts / boot-game-host.js / 6 受控面 / __GameBundle / bootGameHost 只消费不改)。 +Python L1 worker(LLM 生成/校验/成本/编排)与最终报告留 `wg1/gen-worker/`。 + +## 边界(红线) +- 只消费冻结契约,绝不改 P1/P2 产出靶。 +- bundle 输出文件名 `bundle.iife.js`(不落 `dist/`,因 `dist/` 被 .gitignore 吞,bundle 是交付物须入库)。 +- 不推 dev/2.0.0;只在 lane 分支。 + +## 目录 +- `_shared/entry-bundle.template.js`:通用 bundle 入口(复用 buildRefHostConfig,override factory)→ 逐字拷进每个 game 目录为 entry-bundle.js。 +- `_shared/index.template.html`:通用 host 页(调 __GameBundle.bootGameHost,注 recHook/__engineCalls/onReady 取证钩子)。 +- `_shared/play.cdp.cjs`:CDP 真玩驱动 + 四件套证据 + 假绿守卫(复用 test/harness/browser-evidence.cjs)。 +- `/factory.js`:模型产出的工厂源码(默认导出 GameHostFactory)。 +- `/{entry-bundle.js,index.html,bundle.iife.js,evidence/}`:每款产物。 +- `_goldenpath-ref/`:golden path——把 ref 工厂喂进本 harness 验证整条链(防假绿),不算交付游戏。 + +## 状态(2026-06-13 收口) +- [x] P1:golden-path 跑通——ref 工厂 5/6(F=0 菜单态正确)、probe 工厂 7/7 → harness 可信、无假绿。 +- [x] P2:L1 worker(wg1/gen-worker/)——generate/validate/bundle/play/cost/run 全落地。 +- [x] P3:冒烟 Pong / Simon / 打地鼠——deepseek-v4-flash **三款七门全过**,¥0.01–0.03(<¥0.15)。 +- 结论:HJ-GEN-001 成立。详见 [`wg1/gen-worker/REPORT.md`](../../../wg1/gen-worker/REPORT.md)。 + +## 本目录内容 +- `_shared/`:通用 harness 壳(entry-bundle 模板 / index 模板 / play.cdp.cjs 七门 / serve-and-play.sh)。 +- `pong|simon|whack/`:交付冒烟游戏(factory.js + bundle.iife.js + evidence/)。 +- `simon_pro|simon_m27/`:模型对比产物(deepseek-v4-pro / MiniMax-M2.7,证最优模型)。 +- `_goldenpath-ref|_goldenpath-probe/`:harness 自检件(非交付游戏;probe 亦作生成 few-shot 参照)。 diff --git a/game-runtime/games/_wg1-gen/_goldenpath-probe/bundle.iife.js b/game-runtime/games/_wg1-gen/_goldenpath-probe/bundle.iife.js new file mode 100644 index 00000000..865b35cd --- /dev/null +++ b/game-runtime/games/_wg1-gen/_goldenpath-probe/bundle.iife.js @@ -0,0 +1,34 @@ +"use strict";var __GameBundle=(()=>{var So=Object.defineProperty;var $l=Object.getOwnPropertyDescriptor;var Yl=Object.getOwnPropertyNames;var Xl=Object.prototype.hasOwnProperty;var Kl=(t,e,n)=>()=>{if(n)throw n[0];try{return t&&(e=t(t=0)),e}catch(s){throw n=[s],s}};var Ba=(t,e)=>{for(var n in e)So(t,n,{get:e[n],enumerable:!0})},Ql=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Yl(e))!Xl.call(t,i)&&i!==n&&So(t,i,{get:()=>e[i],enumerable:!(s=$l(e,i))||s.enumerable});return t};var Zl=t=>Ql(So({},"__esModule",{value:!0}),t);var Wl={};Ba(Wl,{ASSERT:()=>m,BLACK:()=>he,BLUE:()=>dl,Box2dDistanceJoint:()=>Zi,Box2dFrictionJoint:()=>Jr,Box2dGearJoint:()=>Fr,Box2dJoint:()=>st,Box2dKinematicObject:()=>Pr,Box2dMotorJoint:()=>zr,Box2dObject:()=>Zs,Box2dPinJoint:()=>Or,Box2dPlugin:()=>eo,Box2dPrismaticJoint:()=>Gr,Box2dPulleyJoint:()=>Nr,Box2dRaycastResult:()=>Qi,Box2dRevoluteJoint:()=>Ir,Box2dRopeJoint:()=>Dr,Box2dStaticObject:()=>Ki,Box2dTargetJoint:()=>Lr,Box2dTileLayer:()=>Mr,Box2dWeldJoint:()=>jr,Box2dWheelJoint:()=>Br,CLEAR_BLACK:()=>wt,CLEAR_WHITE:()=>Sn,CYAN:()=>Td,CanvasLayer:()=>Ji,Color:()=>Me,Ease:()=>no,EngineObject:()=>Kt,GRAY:()=>vd,GREEN:()=>ul,ImageFont:()=>Di,LOG:()=>Ce,Light:()=>vr,LightSystemPlugin:()=>Sr,MAGENTA:()=>Ad,Medal:()=>Yi,NewgroundsMedal:()=>gr,NewgroundsPlugin:()=>br,ORANGE:()=>wd,PI:()=>te,PURPLE:()=>fl,Particle:()=>Ni,ParticleEmitter:()=>ur,PathFinder:()=>Ur,PathFinderNode:()=>so,PostProcessPlugin:()=>xr,RED:()=>Xr,RandomGenerator:()=>or,Sound:()=>Vs,SoundInstance:()=>Bi,TextureInfo:()=>Qt,TileCollisionLayer:()=>qs,TileInfo:()=>It,TileLayer:()=>Ws,TileLayerData:()=>Bn,Timer:()=>Lt,Tween:()=>to,UIButton:()=>Qs,UICheckbox:()=>Cr,UILayout:()=>Rr,UIObject:()=>pt,UISlider:()=>_r,UISystemPlugin:()=>Tr,UIText:()=>Xi,UITextInput:()=>Ar,UITile:()=>kr,UIVideo:()=>Er,Vector2:()=>me,WHITE:()=>Q,YELLOW:()=>ll,ZzFXMusic:()=>wr,abs:()=>de,atan2:()=>Hr,audioContext:()=>ve,audioDefaultSampleRate:()=>xs,audioIsRunning:()=>Us,audioMasterGain:()=>Xt,box2d:()=>b,box2dDebug:()=>Fa,box2dInit:()=>jh,box2dSetDebug:()=>Bh,cameraAngle:()=>ae,cameraFit:()=>Bf,cameraPos:()=>Ie,cameraScale:()=>ee,canvasClearColor:()=>mn,canvasColorTiles:()=>oo,canvasFixedSize:()=>ss,canvasMaxAspect:()=>ns,canvasMaxSize:()=>ts,canvasMinAspect:()=>Ms,canvasPixelRatio:()=>yn,canvasPixelated:()=>Zr,ceil:()=>Fs,clamp:()=>H,combineCanvases:()=>fa,cos:()=>ye,debug:()=>Ue,debugCircle:()=>Qe,debugClear:()=>dd,debugLine:()=>Rt,debugOverlap:()=>sr,debugOverlay:()=>zt,debugPoint:()=>qr,debugPointSize:()=>Hc,debugPoly:()=>ud,debugRect:()=>ke,debugScreenshot:()=>Yc,debugShowErrors:()=>fd,debugText:()=>es,debugVideoCaptureIsActive:()=>Pt,debugVideoCaptureStart:()=>Xc,debugVideoCaptureStop:()=>Kc,debugWatermark:()=>io,distanceAngle:()=>bd,distanceWrap:()=>$r,drawCanvas2D:()=>Vn,drawCircle:()=>Oi,drawCircleGradient:()=>If,drawContext:()=>Oe,drawCount:()=>Ot,drawCrescent:()=>zh,drawEllipse:()=>yl,drawEllipseGradient:()=>gl,drawLine:()=>On,drawLineList:()=>ar,drawNineSlice:()=>jl,drawNineSliceScreen:()=>Jh,drawPoly:()=>us,drawRect:()=>Li,drawRectGradient:()=>Lf,drawRegularPoly:()=>ml,drawText:()=>Ff,drawTextScreen:()=>gn,drawTextureWrapped:()=>Of,drawThreeSlice:()=>Jl,drawThreeSliceScreen:()=>Nh,drawTile:()=>Be,enablePhysicsSolver:()=>lo,engineAddPlugin:()=>zn,engineImageFont:()=>vl,engineInit:()=>rd,engineName:()=>Ti,engineObjects:()=>_e,engineObjectsCallback:()=>cd,engineObjectsCollect:()=>qc,engineObjectsCollide:()=>Wr,engineObjectsDestroy:()=>ad,engineObjectsRaycast:()=>ld,engineObjectsUpdate:()=>Wc,engineVersion:()=>Ai,fetchJSON:()=>kd,floor:()=>Pe,fontDefault:()=>ei,formatTime:()=>Kr,frame:()=>Uc,frameRate:()=>sd,gamepadConnected:()=>lr,gamepadDirectionEmulateStick:()=>ra,gamepadDpad:()=>cr,gamepadIsDown:()=>Nt,gamepadPrimary:()=>Ae,gamepadStick:()=>Ns,gamepadStickCount:()=>wl,gamepadVibrate:()=>Zf,gamepadVibrateStop:()=>eh,gamepadWasPressed:()=>ba,gamepadWasReleased:()=>Qf,gamepadsEnable:()=>uo,getCameraSize:()=>xl,getCrescentPoints:()=>Nl,getNoteFrequency:()=>_l,getPaused:()=>id,glAntialias:()=>Aa,glCanvas:()=>ue,glCircleSides:()=>ti,glClearCanvas:()=>Ll,glClearRect:()=>Gl,glCompileShader:()=>yr,glContext:()=>g,glCopyToContext:()=>Ra,glCreateProgram:()=>ms,glCreateTexture:()=>mo,glDeleteTexture:()=>Dl,glDraw:()=>Ys,glDrawColoredPoints:()=>La,glDrawOutlineTransform:()=>Ma,glDrawPoints:()=>Fl,glDrawPointsTransform:()=>Pa,glDrawUntextured:()=>Il,glEnable:()=>W,glFlush:()=>Fe,glSetAntialias:()=>_h,glSetRenderTarget:()=>Ps,glSetTexture:()=>_a,glSetTextureData:()=>Ea,glSetTextureWrap:()=>Ol,gravity:()=>Ze,headlessMode:()=>$,hsl:()=>Vt,hypot:()=>Qc,inputClear:()=>ai,inputClearKey:()=>ya,inputMouseMoveThreshold:()=>ma,inputPreventDefault:()=>is,inputWASDEmulateDirection:()=>Ls,isArray:()=>St,isColor:()=>X,isFullscreen:()=>Sl,isIntersecting:()=>nl,isNumber:()=>O,isOnScreen:()=>jf,isOverlapping:()=>Ei,isPowerOfTwo:()=>Gs,isStringLike:()=>K,isTouchDevice:()=>ft,isUsingGamepad:()=>rs,isVector2:()=>D,keyDirection:()=>Xf,keyIsDown:()=>Ge,keyWasPressed:()=>Ne,keyWasReleased:()=>ga,lastInputDevice:()=>hn,lerp:()=>et,lerpAngle:()=>xd,lerpWrap:()=>tl,lightSystem:()=>Z,lineTest:()=>il,log2:()=>Zc,mainCanvas:()=>q,mainCanvasSize:()=>N,mainContext:()=>ge,max:()=>re,medalDisplaySize:()=>Hi,medalDisplaySlideTime:()=>os,medalDisplayTime:()=>qi,medals:()=>Xs,medalsForEach:()=>yo,medalsInit:()=>Mh,medalsPreventUnlock:()=>Oa,medalsReset:()=>Lh,min:()=>le,mod:()=>dt,mouseDelta:()=>ha,mouseDeltaScreen:()=>Ct,mouseInWindow:()=>Ii,mouseIsDown:()=>Ds,mousePos:()=>Jt,mousePosScreen:()=>Ke,mouseWasPressed:()=>Js,mouseWasReleased:()=>Kf,mouseWheel:()=>pa,nearestPowerOfTwo:()=>Sd,newgrounds:()=>Ks,noise1D:()=>Pd,noise2D:()=>Md,objectDefaultAngleDamping:()=>sa,objectDefaultDamping:()=>na,objectDefaultFriction:()=>oa,objectDefaultMass:()=>ta,objectDefaultRestitution:()=>ia,objectMaxSpeed:()=>Wt,oscillate:()=>sl,particleEmitRateScale:()=>Ri,paused:()=>Mt,percent:()=>Ve,percentLerp:()=>gd,playSamples:()=>Ta,pointerLockExit:()=>sh,pointerLockIsActive:()=>Tl,pointerLockRequest:()=>nh,postProcess:()=>Je,primitiveCount:()=>Dt,rand:()=>Se,randBool:()=>ol,randColor:()=>ir,randInCircle:()=>cl,randInt:()=>Yr,randSign:()=>rl,randVec2:()=>al,readSaveData:()=>Ed,rgb:()=>Y,round:()=>Ci,saveCanvas:()=>hl,saveDataURL:()=>Bs,saveText:()=>Cd,screenToWorld:()=>oi,screenToWorldDelta:()=>bl,screenToWorldTransform:()=>ri,setAdditiveBlendMode:()=>js,setCameraAngle:()=>Od,setCameraPos:()=>Ld,setCameraScale:()=>Dd,setCanvasClearColor:()=>Gd,setCanvasColorTiles:()=>Fd,setCanvasFixedSize:()=>Nd,setCanvasMaxAspect:()=>Jd,setCanvasMaxSize:()=>Bd,setCanvasMinAspect:()=>jd,setCanvasPixelRatio:()=>Ud,setCanvasPixelated:()=>pl,setCursor:()=>Uf,setDebugKey:()=>Mf,setDebugWatermark:()=>Pf,setEnablePhysicsSolver:()=>Qd,setFontDefault:()=>Vd,setGLCircleSides:()=>$d,setGLEnable:()=>Hd,setGamepadDirectionEmulateStick:()=>lf,setGamepadsEnable:()=>cf,setGravity:()=>rf,setHeadlessMode:()=>qd,setInputMouseMoveThreshold:()=>qf,setInputPreventDefault:()=>Wf,setInputWASDEmulateDirection:()=>uf,setMedalDisplaySize:()=>Ih,setMedalDisplaySlideTime:()=>Dh,setMedalDisplayTime:()=>Oh,setMedalsPreventUnlock:()=>Fh,setObjectDefaultAngleDamping:()=>tf,setObjectDefaultDamping:()=>ef,setObjectDefaultFriction:()=>sf,setObjectDefaultMass:()=>Zd,setObjectDefaultRestitution:()=>nf,setObjectMaxSpeed:()=>of,setParticleEmitRateScale:()=>af,setPaused:()=>od,setShowSplashScreen:()=>Wd,setSoundDefaultRange:()=>Ef,setSoundDefaultTaper:()=>Rf,setSoundEnable:()=>Cf,setSoundVolume:()=>_f,setTileDefaultBleed:()=>Kd,setTileDefaultPadding:()=>Xd,setTileDefaultSize:()=>Yd,setTilesPixelated:()=>zd,setTimeScale:()=>Id,setTouchGamepadAlpha:()=>wf,setTouchGamepadAnalog:()=>xf,setTouchGamepadButtonCount:()=>mf,setTouchGamepadCenterButtonSize:()=>pf,setTouchGamepadDisplayTime:()=>Tf,setTouchGamepadEnable:()=>ff,setTouchGamepadFloating:()=>Sf,setTouchGamepadLeftButtonCount:()=>gf,setTouchGamepadLeftStick:()=>yf,setTouchGamepadPassthrough:()=>hf,setTouchGamepadRightStick:()=>bf,setTouchGamepadSize:()=>vf,setTouchGamepadVibration:()=>Af,setTouchInputEnable:()=>df,setVibrateEnable:()=>kf,shareURL:()=>_d,showSplashScreen:()=>ea,sign:()=>ut,sin:()=>fe,smoothStep:()=>_i,soundDefaultRange:()=>la,soundDefaultTaper:()=>ua,soundEnable:()=>nt,soundVolume:()=>Gn,speak:()=>bh,speakStop:()=>xh,tan:()=>el,textureInfos:()=>wn,tile:()=>ii,tileCollisionGetData:()=>ji,tileCollisionLayers:()=>bn,tileCollisionRaycast:()=>El,tileCollisionTest:()=>dn,tileDefaultBleed:()=>co,tileDefaultPadding:()=>ao,tileDefaultSize:()=>ro,tileLayersLoad:()=>vh,tilesPixelated:()=>jn,time:()=>rt,timeDelta:()=>Vr,timeReal:()=>xn,timeScale:()=>Qr,toggleFullscreen:()=>zf,touchGamepadAlpha:()=>ca,touchGamepadAnalog:()=>ni,touchGamepadButtonCount:()=>ys,touchGamepadCenterButtonSize:()=>vt,touchGamepadDisplayTime:()=>Os,touchGamepadEnable:()=>vn,touchGamepadFloating:()=>Tn,touchGamepadLeftButtonCount:()=>gs,touchGamepadLeftStick:()=>Un,touchGamepadPassthrough:()=>aa,touchGamepadRightStick:()=>bs,touchGamepadSize:()=>tt,touchGamepadVibration:()=>Pi,touchInputEnable:()=>Ln,tweenProperty:()=>Uh,tweenStopAll:()=>Vh,tweenUpdate:()=>Vl,uiDebug:()=>Ia,uiSetDebug:()=>Gh,uiSystem:()=>E,usingGamepadInput:()=>Yf,usingKeyboardInput:()=>$f,usingMouseInput:()=>Hf,vec2:()=>v,vibrate:()=>xa,vibrateEnable:()=>si,vibrateStop:()=>th,workCanvas:()=>$t,workContext:()=>fn,workReadCanvas:()=>Et,workReadContext:()=>qt,worldToScreen:()=>Wn,worldToScreenDelta:()=>Gf,writeSaveData:()=>Rd,zzfx:()=>Sh,zzfxG:()=>ho,zzfxM:()=>Bl});function id(){return Mt}function od(t=!0){Mt=t}function zn(t,e,n,s){m(!Dn.find(r=>r.update===t&&r.render===e&&r.glContextLost===n&&r.glContextRestored===s));let i=new tr(t,e,n,s);Dn.push(i)}async function rd(t,e,n,s,i,r=[],a){if(Vc&&console.log(`${Ti} Engine v${Ai}`),m(!ge,"engine already initialized"),ge)return;m(St(r),"pass in images as array"),document.body||document.documentElement.appendChild(document.createElement("body")),a||(a=document.body),t||(t=()=>{}),e||(e=()=>{}),n||(n=()=>{}),s||(s=()=>{}),i||(i=()=>{});function o(){N=v(q.width,q.height),ge.imageSmoothingEnabled=!jn,mr()}function c(p=0){let y=p-Qo;Qo||(y=0),Qo=p,(Ue||io)&&(ki=et(ki,1e3/(y||1),.05));let x=Ue&&Ge("Equal"),w=Ue&&Ge("Minus"),A=x?10:w?.1:1;xn+=y*A/1e3;let S=Qr*A;y*=S,kt+=Mt?0:y,S<=1&&(kt=le(kt,50));let _=!1;if(Mt){_=!0,l(),Gc(),Dn.forEach(C=>{var L;return(L=C.update)==null?void 0:L.call(C)});for(let C of _e)C.parent||C.updateTransforms();Oc(),n(),Bc(),Pt()&&k()}else{let C=0;for(kt<0&&kt>-9&&(C=kt,kt=0);kt>=0;kt-=1e3/60)rt=Uc++/60,_=!0,l(),Gc(),e(),Dn.forEach(L=>{var V;return(V=L.update)==null?void 0:V.call(L)}),Wc(),Oc(),n(),Bc(),Pt()&&k();kt+=C}Pt()||k(),requestAnimationFrame(c);function k(){if(!$){_||l(),o(),s(),_e.sort((C,L)=>C.renderOrder-L.renderOrder);for(let C of _e)C.destroyed||C.render();i(),Dn.forEach(C=>{var L;return(L=C.render)==null?void 0:L.call(C)}),oh(),pd(),Fe(),md(),Ot=0,Dt=0}}}function l(){if(!$){if(ss.x){N=ss.copy();let p=innerWidth/innerHeight,y=ss.x/ss.y,x=pns){let _=N.y*ns|0;N.x=le(_,ts.x)}else if(w0&&!W&&(ge.fillStyle=mn.toString(),ge.fillRect(0,0,N.x,N.y),ge.fillStyle=he.toString()),ge.lineJoin="round",ge.lineCap="round"}}if($)return f();Ah(a);let u="margin:0;overflow:hidden;background:#000;user-select:none;-webkit-user-select:none;touch-action:none;-webkit-touch-callout:none";a.style.cssText=u,q=a.appendChild(document.createElement("canvas")),Oe=ge=q.getContext("2d"),ih(),gh(),hd();let h="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)";q.style.cssText=h,ue&&(ue.style.cssText=h),pl(Zr),l(),mr(),$t=new OffscreenCanvas(64,64),fn=$t.getContext("2d"),Et=new OffscreenCanvas(64,64),qt=Et.getContext("2d",{willReadFrequently:!0});let d=r.map((p,y)=>Ic(y,p));return r.length||d.push(Ic(0)),d.push(Vf()),ea&&d.push(new Promise(p=>{let y=0;x();function x(){ai(),Ph(y+=.01),y>1?p():setTimeout(x,16)}})),await Promise.all(d),f();async function f(){await t(),c()}}function Wc(){Wr=_e.filter(e=>e.collideSolidObjects);function t(e){if(!e.destroyed){e.update();for(let n of e.children)t(n)}}for(let e of _e)if(!(e.parent||e.destroyed)){e.update(),e.updatePhysics();for(let n of e.children)t(n);e.updateTransforms()}_e=_e.filter(e=>!e.destroyed)}function ad(t=!0){for(let e of _e)e.parent||e.destroy(t);_e=_e.filter(e=>!e.destroyed)}function qc(t,e,n=_e){let s=[];if(t)if(e instanceof me)for(let i of n)i.isOverlapping(t,e)&&s.push(i);else{let i=e*e;for(let r of n)t.distanceSquared(r.pos)n(i))}function ld(t,e,n=_e){let s=[];for(let i of n)i.collideRaycast&&nl(t,e,i.pos,i.size)&&(xt&&ke(i.pos,i.size,"#f00"),s.push(i));return xt&&Rt(t,e,s.length?"#f00":"#00f",.02),s}function m(t,...e){if(!t)throw console.assert(t,...e),new Error("Assert failed!")}function Ce(...t){console.log(...t)}function ke(t,e=v(),n=Q,s=0,i=0,r=!1,a=!1){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(K(n)||X(n),"color is invalid"),m(O(s),"time must be a number"),m(O(i),"angle must be a number"),X(n)&&(n=n.toString());let o=new Lt(s);pn.push({pos:t.copy(),size:e.copy(),color:n,timer:o,angle:i,fill:r,screenSpace:a})}function ud(t,e,n=Q,s=0,i=0,r=!1,a=!1){m(D(t),"pos must be a vec2"),m(St(e),"points must be an array"),m(K(n)||X(n),"color is invalid"),m(O(s),"time must be a number"),m(O(i),"angle must be a number"),X(n)&&(n=n.toString()),t=t.copy(),e=e.map(c=>c.copy());let o=new Lt(s);pn.push({pos:t,points:e,color:n,timer:o,angle:i,fill:r,screenSpace:a})}function Qe(t,e=0,n=Q,s=0,i=!1,r=!1){m(D(t),"pos must be a vec2"),m(O(e),"size must be a number"),m(K(n)||X(n),"color is invalid"),m(O(s),"time must be a number"),X(n)&&(n=n.toString()),t=t.copy();let a=new Lt(s);pn.push({pos:t,size:e,color:n,timer:a,angle:0,fill:i,screenSpace:r})}function qr(t,e,n,s,i=!1){ke(t,void 0,e,n,s,!1,i)}function Rt(t,e,n,s=.1,i=0,r=!1){m(D(t),"posA must be a vec2"),m(D(e),"posB must be a vec2"),m(O(s),"width must be a number");let a=v((e.x-t.x)/2,(e.y-t.y)/2),o=v(s,a.length()*2);ke(t.add(a),o,n,i,a.angle(),!0,r)}function sr(t,e,n,s,i,r,a=!1){m(D(t),"posA must be a vec2"),m(D(n),"posB must be a vec2"),m(D(e),"sizeA must be a vec2"),m(D(s),"sizeB must be a vec2");let o=v(le(t.x-e.x/2,n.x-s.x/2),le(t.y-e.y/2,n.y-s.y/2)),c=v(re(t.x+e.x/2,n.x+s.x/2),re(t.y+e.y/2,n.y+s.y/2));ke(o.lerp(c,.5),c.subtract(o),i,r,0,!1,a)}function es(t,e,n=1,s=Q,i=0,r=0,a="monospace",o=!1){m(K(t),"text must be a string"),m(D(e),"pos must be a vec2"),m(O(n),"size must be a number"),m(K(s)||X(s),"color is invalid"),m(O(i),"time must be a number"),m(O(r),"angle must be a number"),m(K(a),"font must be a string"),X(s)&&(s=s.toString()),e=e.copy();let c=new Lt(i);pn.push({text:t,pos:e,size:n,color:s,timer:c,angle:r,font:a,screenSpace:o})}function dd(){pn=[]}function Yc(){nr=1}function fd(){let t=n=>{document.body.style="background-color:#111;margin:8px",document.body.innerHTML="
"+n},e=console.assert;console.assert=(n,...s)=>{if(e(n,...s),!n){let i=s.join(" "),r=new Error().stack;throw`Assertion failed!
+`+i+`
+`+r}},onunhandledrejection=n=>t(n.reason.stack||n.reason),onerror=(n,s,i,r)=>t(`${n}
+${s}
+Ln ${i}, Col ${r}`)}function hd(){Vc&&console.warn("LittleJS DEBUG build loaded. Use the release build for production.")}function Oc(){Ue&&(Ne($c)&&(zt=!zt),zt&&(Ne("Digit1")&&(bt=!bt,In=!1),Ne("Digit2")&&(In=!In,bt=!1),Ne("Digit3")&&(Fn=!Fn),Ne("Digit4")&&(xt=!xt),Ne("Digit5")&&Yc(),Ne("Digit7")&&(ls=!ls)),Pt()?(!zt||Ne("Digit6"))&&Kc():zt&&Ne("Digit6")&&Xc())}function pd(){if(Pt())return;Fe();let t=Ot,e=Dt;nr&&(fa(),hl(q),nr=0);let n=ge;if(Fn&&uo){let r=0;for(let a=0;a<8;a++)lr(a)&&r++;for(let a=0;a<8;a++){if(!lr(a))continue;let o=1,c=.2,l=Ie.add(v(-o*2,((r-1)/2-a)*o*3));es(a,l.add(v(-o,o)),1),a===Ae&&es("Main",l.add(v(-o*2,0)),1,"#0f0");let u=_t[a].length;for(let d=0;d{n.save();let r=i.pos,a=1,o=i.angle;if(i.screenSpace||(r=Wn(i.pos),a=ee,o-=ae),n.translate(r.x|0,r.y|0),n.rotate(o),n.scale(1,i.text?1:-1),n.fillStyle=i.color,n.strokeStyle=i.color,i.text!==void 0)n.font=i.size*a+"px "+i.font,n.textAlign="center",n.textBaseline="middle",n.fillText(i.text,0,0);else if(i.points!==void 0){n.beginPath();for(let c of i.points){let l=c.scale(a).floor();n.lineTo(l.x,l.y)}n.closePath(),i.fill&&n.fill(),n.stroke()}else if(i.size===0||i.size.x===0&&i.size.y===0){let c=Hc*a;n.fillRect(-c/2,-1,c,3),n.fillRect(-1,-c/2,3,c)}else if(i.size.x!==void 0){let c=i.size.scale(a).floor(),l=c.x,u=c.y;i.fill&&n.fillRect(-l/2|0,-u/2|0,l,u),n.strokeRect(-l/2|0,-u/2|0,l,u)}else n.beginPath(),n.arc(0,0,i.size*a/2,0,9),i.fill&&n.fill(),n.stroke();n.restore()}),pn=pn.filter(i=>i.timer<0),s){let i=El(s.pos,Jt);i&&Li(i.floor().add(v(.5)),v(1),Y(0,1,1,.3),0,!1),On(Jt,s.pos,.1,i?Y(1,0,0,.5):Y(0,1,0,.5),void 0,void 0,!1);let r="mouse pos = "+Jt;bn.length&&(r+=`
+mouse collision = `+ji(Jt)),r+=`
+
+--- object info ---
+`,r+=s.toString(),gn(r,Ke,24,Y(),.05,void 0,"center","monospace")}{n.save(),n.fillStyle="#fff",n.textAlign="left",n.textBaseline="top",n.font="20px monospace",n.shadowColor="#000",n.shadowBlur=9;let a=9,o=0,c=24;if(zt){n.fillText(`${Ti} v${Ai}`,a,o+=c/2),n.fillText("Time: "+Kr(rt),a,o+=c),n.fillText("FPS: "+ki.toFixed(1)+(W?" WebGL":" Canvas2D"),a,o+=c),n.fillText("Objects: "+_e.length,a,o+=c),n.fillText("Draw Calls: "+Ot,a,o+=c),n.fillText("Primitives: "+Dt,a,o+=c),n.fillText("---------",a,o+=c),n.fillStyle="#f00",n.fillText("ESC: Debug Overlay",a,o+=c),n.fillStyle=bt?"#f00":"#fff",n.fillText("1: Debug Physics",a,o+=c),n.fillStyle=In?"#f00":"#fff",n.fillText("2: Debug Particles",a,o+=c),n.fillStyle=Fn?"#f00":"#fff",n.fillText("3: Debug Gamepads",a,o+=c),n.fillStyle=xt?"#f00":"#fff",n.fillText("4: Debug Raycasts",a,o+=c),n.fillStyle="#fff",n.fillText("5: Save Screenshot",a,o+=c),n.fillText("6: Toggle Video Capture",a,o+=c),n.fillStyle=ls?"#f00":"#fff",n.fillText("7: Debug Sound",a,o+=c);let l="",u="";for(let h in ie[0])Ge(h,0)&&(parseInt(h)<3?u+=h+" ":l+=h+" ");u&&n.fillText("Mouse: "+u,a,o+=c),l&&n.fillText("Keys: "+l,a,o+=c);for(let h=1;hs.push(o.data),i.onstop=()=>{let o=new Blob(s,{type:"video/webm"}),c=URL.createObjectURL(o);Bs(c,"capture.webm",1e3)};let r,a;if(nt){a=new ConstantSourceNode(ve,{offset:0}),a.connect(Xt),a.start(),r=ve.createMediaStreamDestination(),Xt.connect(r);for(let o of r.stream.getAudioTracks())t.addTrack(o)}try{i.start()}catch{Ce("Video capture not supported in this browser!"),a==null||a.stop();return}Ce("Video capture started."),Ut={mediaRecorder:i,captureTimer:n,videoTrack:e,silentAudioSource:a,audioStreamDestination:r}}function Kc(){var t,e,n;m(Pt(),"Not capturing video!"),Ce(`Video capture ended. ${Ut.captureTimer.get().toFixed(2)} seconds recorded.`),gt.style.display="none",(t=Ut.silentAudioSource)==null||t.stop(),(e=Ut.mediaRecorder)==null||e.stop(),(n=Ut.videoTrack)==null||n.stop(),Ut=void 0}function yd(){m(Pt(),"Not capturing video!"),fa(),Ut.videoTrack.requestFrame(),gt.textContent="\u25CF REC "+Kr(Ut.captureTimer)}function ct(t){if(Ue){let e=Object.keys(t),n={};e.forEach(s=>n[s]=t[s]),e.forEach(s=>{Object.defineProperty(t,s,{get:()=>n[s],set:i=>{m(!1,`Cannot modify engine constant. Attempted to set constant (${t}) property '${s}' to '${i}'.`)},enumerable:!0})})}return Object.freeze(t)}function dt(t,e=1){return(t%e+e)%e}function H(t,e=0,n=1){return tn?n:t}function Ve(t,e,n){return(n-=e)?H((t-e)/n):0}function et(t,e,n){return t+H(n)*(e-t)}function gd(t,e,n,s,i){return et(s,i,Ve(t,e,n))}function $r(t,e,n=1){m(n>0,"distanceWrap wrapSize must be > 0");let s=(t-e)%n;return s*2%n-s}function tl(t,e,n,s=1){return t+H(n)*$r(e,t,s)}function bd(t,e){return $r(t,e,2*te)}function xd(t,e,n){return tl(t,e,n,2*te)}function _i(t){return t*t*(3-2*t)}function Gs(t){return!(t&t-1)}function Sd(t){return 2**Fs(Zc(t))}function Ei(t,e,n,s=v()){let i=(t.x-n.x)*2,r=(t.y-n.y)*2,a=e.x+s.x,o=e.y+s.y;return de(i)d)return!1;h=re(p,h)}else{if(p0?o.x+1:o.x,y=h>0?o.y+1:o.y,x=c?(p-t.x)/c:1/0,w=l?(y-t.y)/l:1/0,A=0,S=x,_=w,k=do.x&&(C.x=o.x+1-L),V.yo.y&&(C.y=o.y+1-L),s&&(k?s.set(-u,0):s.set(0,-h)),C}(k=S<_)?(o.x+=u,A=S,S+=d):(o.y+=h,A=_,_+=f)}}function Se(t=1,e=0){return e+Math.random()*(t-e)}function Yr(t,e=0){return Pe(Se(t,e))}function ol(t=.5){return Se()URL.revokeObjectURL(t),n)}function _d(t,e,n){var s;m(K(t),"shareURL requires title string"),m(K(e),"shareURL requires url string"),(s=navigator.share)==null||s.call(navigator,{title:t,url:e}).then(()=>n==null?void 0:n())}function Ed(t,e){m(K(t),"loadData requires saveName string");let n={};try{let s=localStorage[t];if(s)try{n=JSON.parse(s)}catch{Ce("readSaveData: corrupt JSON for",t,"\u2014 using defaults")}}catch{Ce("readSaveData: localStorage unavailable \u2014 using defaults")}return{...e,...n}}function Rd(t,e){m(K(t),"saveData requires saveName string");try{localStorage[t]=JSON.stringify(e)}catch{Ce("writeSaveData: failed to write",t)}}function rr(t){let e=(t|0)^2654435769;return e=Math.imul(e^e>>>16,2246822507),e=Math.imul(e^e>>>13,3266489909),e^=e>>>16,(e>>>0)/2**32}function Pd(t){let e=Pe(t);return et(rr(e),rr(e+1),_i(t-e))}function Md(t,e){let n=Pe(t),s=Pe(e),i=_i(t-n),r=_i(e-s),a=(o,c)=>rr(o+c*374761393);return et(et(a(n,s),a(n+1,s),i),et(a(n,s+1),a(n+1,s+1),i),r)}function Ld(t){Ie=t.copy()}function Od(t){ae=t}function Dd(t){ee=t}function Id(t){Qr=t}function Fd(t){oo=t}function Gd(t){mn=t.copy()}function Bd(t){ts=t.copy()}function jd(t){Ms=t}function Jd(t){ns=t}function Nd(t){ss=t.copy()}function pl(t){Zr=t,q&&(q.style.imageRendering=t?"pixelated":""),ue&&(ue.style.imageRendering=t?"pixelated":"")}function zd(t){jn=t}function Ud(t){yn=t}function Vd(t){ei=t}function Wd(t){ea=t}function qd(t){$=t}function Hd(t){if(t&&!pr){console.warn("Can not enable WebGL if it was disabled on start.");return}W=t,ue&&(ue.style.display=t?"":"none")}function $d(t){ti=t}function Yd(t){ro=t.copy()}function Xd(t){ao=t}function Kd(t){co=t}function Qd(t){lo=t}function Zd(t){ta=t}function ef(t){na=t}function tf(t){sa=t}function nf(t){ia=t}function sf(t){oa=t}function of(t){Wt=t}function rf(t){Ze=t.copy()}function af(t){Ri=t}function cf(t){uo=t}function lf(t){ra=t}function uf(t){Ls=t}function df(t){Ln=t}function ff(t){vn=t}function hf(t){aa=t}function pf(t){vt=t}function mf(t){ys=t,t>0&&(bs=!1)}function yf(t){Un=t,t&&(gs=0)}function gf(t){gs=t,t>0&&(Un=!1)}function bf(t){bs=t,t&&(ys=0)}function xf(t){ni=t}function Sf(t){Tn=t}function vf(t){tt=t}function wf(t){ca=t}function Tf(t){Os=t}function Af(t){Pi=t}function kf(t){si=t}function Cf(t){nt=t}function _f(t){Gn=t,nt&&!$&&Xt&&(Xt.gain.value=t)}function Ef(t){la=t}function Rf(t){ua=t}function Pf(t){io=t}function Mf(t){$c=t}function Mi(t){return t.r>=1&&t.g>=1&&t.b>=1}function da(t){return t.r<=0&&t.g<=0&&t.b<=0&&t.a<=0}function ii(t=0,e=ro,n=0,s=ao,i=co){if(m(D(t)||typeof t=="number","index must be a vec2 or number"),m(D(e)||typeof e=="number","size must be a vec2 or number"),m(O(n)||n instanceof Qt,"texture must be a number or TextureInfo"),m(O(s),"padding must be a number"),$)return new It;typeof e=="number"&&(m(e>0),e=new me(e,e));let r=typeof n=="number"?wn[n]:n;m(r instanceof Qt,"tile texture is not loaded"),m(r.size.x>0,"tile texture is not loaded");let a=e.x+s*2,o=e.y+s*2,c,l;if(typeof t=="number"){let h=r.size.x/a|0;c=t%h,l=t/h|0}else c=t.x,l=t.y;let u=new me(c*a+s,l*o+s);return new It(u,e,r,s,i)}function Be(t,e=v(1),n,s=Q,i=0,r,a,o=W,c=!1,l){var d;m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(X(s),"color is invalid"),m(O(i),"angle must be a number"),m(!a||X(a),"additiveColor must be a color"),m(!l||!o,"context only supported in canvas 2D mode");let u=n==null?void 0:n.textureInfo,h=(d=n==null?void 0:n.bleed)!=null?d:0;if(o&&W)if(m(!!g,"WebGL is not enabled!"),c&&([t,e,i]=ri(t,e,i)),u){let f=u.sizeInverse,p=n.pos.x*f.x,y=n.pos.y*f.y,x=n.size.x*f.x,w=n.size.y*f.y;if(_a(u.glTexture),h){let A=f.x*h,S=f.y*h;Ys(t.x,t.y,r?-e.x:e.x,e.y,i,p+A,y+S,p-A+x,y-S+w,s.rgbaInt(),a&&a.rgbaInt())}else Ys(t.x,t.y,r?-e.x:e.x,e.y,i,p,y,p+x,y+w,s.rgbaInt(),a&&a.rgbaInt())}else{let f=a?s.add(a):s;Il(t.x,t.y,e.x,e.y,i,f.rgbaInt())}else++Ot,++Dt,Vn(t,e,i,r,f=>{if(u){f.scale(1,-1);let p=n.pos.x,y=n.pos.y,x=n.size.x,w=n.size.y;Nf(f,u.image,p,y,x,w,-.5,-.5,1,1,s,a,h)}else{let p=a?s.add(a):s;f.fillStyle=p.toString(),f.fillRect(-.5,-.5,1,1)}},c,l)}function Li(t,e,n,s,i,r,a){Be(t,e,void 0,n,s,!1,void 0,i,r,a)}function Lf(t,e,n=Q,s=Sn,i=0,r=W,a=!1,o){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(X(n)&&X(s),"color is invalid"),m(O(i),"angle must be a number"),m(!o||!r,"context only supported in canvas 2D mode"),r&&W){m(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/ee),i+=ae);let c=[],l=[],u=e.x/2,h=e.y/2,d=n.rgbaInt(),f=s.rgbaInt(),p=ye(-i),y=fe(-i);for(let x=4;x--;){let w=x&1?u:-u,A=x&2?h:-h,S=w*p-A*y,_=w*y+A*p,k=x&2?d:f;c.push(v(t.x+S,t.y+_)),l.push(k)}La(c,l)}else++Ot,++Dt,Vn(t,e,i,!1,c=>{let l=c.createLinearGradient(0,.5,0,-.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.fillRect(-.5,-.5,1,1)},a,o)}function Of(t,e,n,s=0,i=Q,r=0,a,o=W,c=!1,l){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(D(n),"wrapCount must be a vec2"),m(X(i),"color is invalid"),m(O(r),"angle must be a number"),m(!a||X(a),"additiveColor must be a color"),m(!l||!o,"context only supported in canvas 2D mode"),m(!(s instanceof It),"pass a TextureInfo or texture index, not a TileInfo \u2014 use tileInfo.textureInfo"),$)return;let u=typeof s=="number"?wn[s]:s;if(m(u instanceof Qt,"texture not loaded"),m(u.size.x>0,"texture not loaded"),m(u.wrap,"drawTextureWrapped requires a wrap-enabled texture; call textureInfo.setWrap(true) first"),o&&W){m(!!g,"WebGL is not enabled!"),c&&([t,e,r]=ri(t,e,r)),_a(u.glTexture),Ys(t.x,t.y,e.x,e.y,r,0,0,n.x,n.y,i.rgbaInt(),a&&a.rgbaInt());return}++Ot,++Dt,c||(t=Wn(t),e=e.scale(ee),r-=ae);let h=!oo||(a?Mi(i.add(a))&&a.a<=0:Mi(i)),d=!h&&a&&!da(a),f=h?u.image:Jf(u.image,i,a);l=l||Oe,l.save(),l.translate(t.x+.5,t.y+.5),l.rotate(r),l.globalAlpha=d?1:i.a;let p=l.createPattern(f,"repeat"),y=new DOMMatrix().translate(-e.x/2,-e.y/2).scale(e.x/(n.x*f.width),e.y/(n.y*f.height));p.setTransform(y),l.fillStyle=p,l.fillRect(-e.x/2,-e.y/2,e.x,e.y),l.globalAlpha=1,l.restore()}function ar(t,e=.1,n=Q,s=!1,i=v(),r=0,a=W,o=!1,c){if(m(St(t),"points must be an array"),m(O(e),"width must be a number"),m(X(n),"color is invalid"),m(D(i),"pos must be a vec2"),m(O(r),"angle must be a number"),m(!c||!a,"context only supported in canvas 2D mode"),a&&W){m(!!g,"WebGL is not enabled!");let l=v(1);o&&([i,l,r]=ri(i,l,r)),Ma(t,n.rgbaInt(),e,i.x,i.y,l.x,l.y,r,s)}else++Ot,++Dt,Vn(i,v(1),r,!1,l=>{l.strokeStyle=n.toString(),l.lineWidth=e,l.beginPath();for(let u=0;u0&&Ma(t,s.rgbaInt(),n,i.x,i.y,l.x,l.y,r)}else Vn(i,v(1),r,!1,l=>{l.fillStyle=e.toString(),l.beginPath();for(let u of t)l.lineTo(u.x,u.y);l.closePath(),l.fill(),n&&(l.strokeStyle=s.toString(),l.lineWidth=n,l.stroke())},o,c)}function yl(t,e=v(1),n=Q,s=0,i=0,r=he,a=W,o=!1,c){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(X(n)&&X(r),"color is invalid"),m(O(s),"angle must be a number"),m(O(i),"lineWidth must be a number"),m(i>=0,"lineWidth must be a positive value or 0"),m(!c||!a,"context only supported in canvas 2D mode"),i=H(i,0,le(e.x,e.y)),a&&W?ml(t,e,ti,n,i,r,s,a,o,c):Vn(t,v(1),s,!1,l=>{l.fillStyle=n.toString(),l.beginPath(),l.ellipse(0,0,e.x/2,e.y/2,0,0,9),l.fill(),i&&(l.strokeStyle=r.toString(),l.lineWidth=i,l.stroke())},o,c)}function Oi(t,e=1,n=Q,s=0,i=he,r=W,a=!1,o){m(O(e),"size must be a number"),yl(t,v(e),n,0,s,i,r,a,o)}function gl(t,e=v(1),n=Q,s=Sn,i=0,r=W,a=!1,o){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(X(n)&&X(s),"color is invalid"),m(O(i),"angle must be a number"),m(!o||!r,"context only supported in canvas 2D mode"),!$)if(r&&W){m(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/ee),i+=ae);let c=ti,l=e.x/2,u=e.y/2,h=n.rgbaInt(),d=s.rgbaInt(),f=Df++,p=ye(-i),y=fe(-i),x=_=>{let k=fe(_)*l,C=ye(_)*u;return v(t.x+k*p-C*y,t.y+k*y+C*p)},w=f%c/c*te*2,A=[x(w)],S=[d];for(let _=c;_--;){let k=(_+f)%c/c*te*2;A.push(t),S.push(h),A.push(x(k)),S.push(d)}La(A,S)}else++Ot,++Dt,Vn(t,e,i,!1,c=>{let l=c.createRadialGradient(0,0,0,0,0,.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.beginPath(),c.ellipse(0,0,.5,.5,0,0,9),c.fill()},a,o)}function If(t,e=1,n=Q,s=Sn,i=W,r=!1,a){m(O(e),"size must be a number"),gl(t,v(e),n,s,0,i,r,a)}function Vn(t,e,n=0,s=!1,i,r=!1,a=Oe){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(O(n),"angle must be a number"),m(typeof i=="function","drawFunction must be a function"),r||(t=Wn(t),e=e.scale(ee),n-=ae),a.save(),a.translate(t.x+.5,t.y+.5),a.rotate(n),a.scale(s?-e.x:e.x,-e.y),i(a),a.restore()}function Ff(t,e,n=1,s=Q,i=0,r=he,a="center",o=ei,c="",l,u=0,h=Oe){e=Wn(e),n*=ee,i*=ee,u-=ae,u*=-1,gn(t,e,n,s,i,r,a,o,c,l,u,h)}function gn(t,e,n,s=Q,i=0,r=he,a="center",o=ei,c="",l,u=0,h=Oe){m(K(t),"text must be a string"),m(D(e),"pos must be a vec2"),m(O(n),"size must be a number"),m(X(s),"color must be a color"),m(O(i),"lineWidth must be a number"),m(X(r),"lineColor must be a color"),m(["left","center","right"].includes(a),"align must be left, center, or right"),m(K(o),"font must be a string"),m(K(c),"fontStyle must be a string"),m(O(u),"angle must be a number");let d=(t+"").split(`
+`),f=e.y-(d.length-1)*n/2;h.save(),h.fillStyle=s.toString(),h.strokeStyle=r.toString(),h.lineWidth=i,h.textAlign=a,h.font=c+" "+n+"px "+o,h.textBaseline="middle",h.translate(e.x,f),h.rotate(-u);let p=0;d.forEach(y=>{i&&h.strokeText(y,0,p,l),h.fillText(y,0,p,l),p+=n}),h.restore()}async function Ic(t,e){m(O(t),"textureIndex must be a number"),m(!wn[t],"textureIndex is already loaded!"),m(!e||K(e),"image src must be a string");let n=new Image;e&&await new Promise(s=>{n.onerror=n.onload=s,n.crossOrigin="anonymous",n.src=e}),wn[t]=new Qt(n)}function oi(t){m(D(t),"screenPos must be a vec2");let e=(t.x-N.x/2+.5)/ee,n=(t.y-N.y/2+.5)/-ee;if(ae){let s=ye(-ae),i=fe(-ae),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new me(e+Ie.x,n+Ie.y)}function Wn(t){m(D(t),"worldPos must be a vec2");let e=t.x-Ie.x,n=t.y-Ie.y;if(ae){let s=ye(ae),i=fe(ae),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new me(e*ee+N.x/2-.5,n*-ee+N.y/2-.5)}function bl(t){m(D(t),"screenDelta must be a vec2");let e=t.x/ee,n=t.y/-ee;if(ae){let s=ye(-ae),i=fe(-ae),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new me(e,n)}function Gf(t){m(D(t),"worldDelta must be a vec2");let e=t.x,n=t.y;if(ae){let s=ye(ae),i=fe(ae),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new me(e*ee,n*-ee)}function ri(t,e,n=0){return m(D(t),"screenPos must be a vec2"),m(D(e),"screenSize must be a vec2"),m(O(n),"screenAngle must be a number"),[oi(t),e.scale(1/ee),n+ae]}function xl(){return N.scale(1/ee)}function Bf(t,e,n,s){m(D(t),"center must be a vec2"),m(D(e),"size must be a vec2");let i=d(n),r=d(s),a=e.x+i.left+i.right,o=e.y+i.top+i.bottom,c=N.x-r.left-r.right,l=N.y-r.top-r.bottom;if(!(a>0&&o>0&&c>0&&l>0))return ee;ee=le(c/a,l/o);let u=v(i.right-i.left,i.top-i.bottom).scale(.5),h=v(r.right-r.left,r.top-r.bottom).scale(.5/ee);return Ie=t.add(u).add(h),ee;function d(f){return(f===void 0||O(f))&&(f=v(f)),D(f)?{top:f.y,right:f.x,bottom:f.y,left:f.x}:{top:f.top||0,right:f.right||0,bottom:f.bottom||0,left:f.left||0}}}function jf(t,e=0){if(m(D(t),"pos must be a vec2"),m(D(e)||O(e),"size must be a vec2 or number"),!ee)return!1;let n=t.x-Ie.x,s=t.y-Ie.y;if(ae){let a=ye(ae),o=fe(ae),c=n*a-s*o,l=n*o+s*a;n=c,s=l}n*=ee*2,s*=-ee*2,e instanceof me&&(e=e.length()),e*=ee;let i=N.x,r=N.y;return n+e>-i&&n-e-r&&s-e{t.onerror=t.onload=o,t.crossOrigin="anonymous",t.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAAeAQMAAABnrVXaAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAAjpJREFUOMu9kzFu2zAUhn+CAROgqrk+B2l0BWYxMjlXeYaAtFtbdA1sGgHqRQfI0CNkSG5AwYB0BQ8d5Bsomwah6CPVeGg6tEPzAxLwyI+P78cP4u9lNO9OoMKnLMOobG5020/yaj/MrRcCGh1gBbyiLTPJEYaIiom5KM9Jq7KgynMGtb6L4GL4MF2H4LQKCXTvDVw2I4MsgZT7QLExdiutH+D08VOP3INXRrWX1/mmpbkNgAPYRVANb4xpcegYvhiNbIXauQICEjBuYLfMakaakWQeXxiZ0VDtuJCKs3ztMV59QtsHJNcRxDzfdL21ty3PrfIcXTN+E+GFAv6T5nbT9jd50/WFxb5ksdAv49qS6ouymG66ji08UMT6moykYLAo+V0j23GN4m829ZySAD5K7QsBfQTvOG8eE+gTeGYRAmnNAubN3hf5Zv9tJWDHp/VTuaSm7SN4fyINQqaNO3RMVxvpSPXnOChnRNvFcGY0gnwiPswYwTKVPE0zVtX3mTEIOoFzaqLrGuJaV+Uqumb71fVk/VoOH3cdLNQP/FHi8hV0CQNoqBZsUPlLPMsdCJro9QAaQQ0woDy9BJm0eTxCFnO9srcYlhNVlfR2EyTrph1uUtbUtAJifwRgrKuYdXVHeb0YI3QpawohQHkloI3J5FuVwI5ORxC9k2Tuz9Ir1IjgeIPGMHYkAZe2RuYkmWFmt3gGbTPOmBUWVTmRmHtGrfpzG/yuQNOKa6gBB/WA9khitPgl6/GP+gl2Af6tCbvaygAAAABJRU5ErkJggg=="});let e=v(),n=v(8),s=1,i=0,r=new Qt(t),a=new It(e,n,r,s,i);vl=new Di(a)}function Wf(t=!0){is=t}function qf(t){ma=t}function Hf(){return hn==="mouse"}function $f(){return hn==="keyboard"}function Yf(){return hn==="gamepad"}function ya(t,e=0,n=!0,s=!0,i=!0){ie[e]&&(ie[e][t]&=~((n?1:0)|(s?2:0)|(i?4:0)))}function ai(){ie.length=0,ie[0]=[],ht.length=0,Jn.length=0,ci.length=0,_t.length=0,Pn.length=0}function Ge(t,e=0){var n;return m(K(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=ie[e])==null?void 0:n[t])&1)}function Ne(t,e=0){var n;return m(K(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=ie[e])==null?void 0:n[t])&2)}function ga(t,e=0){var n;return m(K(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=ie[e])==null?void 0:n[t])&4)}function Xf(t="ArrowUp",e="ArrowDown",n="ArrowLeft",s="ArrowRight"){m(K(t),"up key must be a string"),m(K(e),"down key must be a string"),m(K(n),"left key must be a string"),m(K(s),"right key must be a string");let i=r=>Ge(r)?1:0;return v(i(s)-i(n),i(t)-i(e))}function Ds(t){return m(O(t),"mouse button must be a number"),Ge(t)}function Js(t){return m(O(t),"mouse button must be a number"),Ne(t)}function Kf(t){return m(O(t),"mouse button must be a number"),ga(t)}function Nt(t,e=Ae){return m(O(t),"button must be a number"),m(O(e),"gamepad must be a number"),Ge(t,e+1)}function ba(t,e=Ae){return m(O(t),"button must be a number"),m(O(e),"gamepad must be a number"),Ne(t,e+1)}function Qf(t,e=Ae){return m(O(t),"button must be a number"),m(O(e),"gamepad must be a number"),ga(t,e+1)}function Ns(t,e=Ae){var n,s;return m(O(t),"stick must be a number"),m(O(e),"gamepad must be a number"),(s=(n=_t[e])==null?void 0:n[t])!=null?s:v()}function cr(t=Ae){var e;return m(O(t),"gamepad must be a number"),(e=Pn[t])!=null?e:v()}function lr(t=Ae){return m(O(t),"gamepad must be a number"),!!ie[t+1]}function wl(t=Ae){var e,n;return m(O(t),"gamepad must be a number"),(n=(e=_t[t])==null?void 0:e.length)!=null?n:0}function Zf(t=Ae,e=200,n=1,s=1,i=0){var a,o,c;if(m(O(t),"gamepad must be a number"),!si||$)return;let r=(a=navigator==null?void 0:navigator.getGamepads)==null?void 0:a.call(navigator)[t];(c=(o=r==null?void 0:r.vibrationActuator)==null?void 0:o.playEffect)==null||c.call(o,"dual-rumble",{duration:e,strongMagnitude:n,weakMagnitude:s,startDelay:i})}function eh(t=Ae){var n,s,i;if(m(O(t),"gamepad must be a number"),!si||$)return;let e=(n=navigator==null?void 0:navigator.getGamepads)==null?void 0:n.call(navigator)[t];(i=(s=e==null?void 0:e.vibrationActuator)==null?void 0:s.reset)==null||i.call(s)}function xa(t=100){var e;m(O(t)||St(t),"pattern must be a number or array"),si&&!$&&((e=navigator==null?void 0:navigator.vibrate)==null||e.call(navigator,t))}function th(){xa(0)}function nh(){var t;!ft&&((t=q.requestPointerLock)==null||t.call(q))}function sh(){var t;(t=document.exitPointerLock)==null||t.call(document)}function Tl(){return document.pointerLockElement===q}function ih(){if($)return;document.addEventListener("keydown",t),document.addEventListener("keyup",e),document.addEventListener("mousedown",s),document.addEventListener("mouseup",i),document.addEventListener("mousemove",r),document.addEventListener("mouseleave",a),document.addEventListener("wheel",o,{passive:!1}),document.addEventListener("contextmenu",c),document.addEventListener("blur",l),ft&&Ln&&u();function t(d){if(d.repeat||(ie[0][d.code]=3,Ls&&(ie[0][n(d.code)]=3)),!is||!d.cancelable||!document.hasFocus()||d.ctrlKey||d.metaKey||d.altKey||y(d.target)||y(document.activeElement))return;let f=typeof d.key=="string"&&d.key.length===1;(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Space","Tab","Backspace"].includes(d.code)||f)&&d.preventDefault();function y(x){let w=x==null?void 0:x.tagName;return(x==null?void 0:x.isContentEditable)||["INPUT","TEXTAREA","SELECT"].includes(w)}}function e(d){ie[0][d.code]=ie[0][d.code]&2|4,Ls&&(ie[0][n(d.code)]=4)}function n(d){return Ls?d==="KeyW"?"ArrowUp":d==="KeyS"?"ArrowDown":d==="KeyA"?"ArrowLeft":d==="KeyD"?"ArrowRight":d:d}function s(d){if(ft&&Ln)return;nt&&!$&&ve&&!Us()&&ve.resume(),ie[0][d.button]=3;let f=Ke;Ke=h(v(d.x,d.y)),Ct=Ct.add(Ke.subtract(f)),is&&d.cancelable&&document.hasFocus()&&d.preventDefault()}function i(d){ft&&Ln||(ie[0][d.button]=ie[0][d.button]&2|4)}function r(d){Ii=!0;let f=Ke;Ke=h(v(d.x,d.y));let p=Tl()?v(d.movementX,d.movementY):Ke.subtract(f);Ct=Ct.add(p)}function a(){Ii=!1}function o(d){d.ctrlKey||(pa+=ut(d.deltaY)),is&&d.cancelable&&document.hasFocus()&&d.preventDefault()}function c(d){d.preventDefault()}function l(){ai(),Ht.clear(),ht.length=0,Jn.length=0,ci.length=0}function u(){document.addEventListener("touchstart",p=>f(p),{passive:!1}),document.addEventListener("touchmove",p=>f(p),{passive:!1}),document.addEventListener("touchend",p=>f(p),{passive:!1});let d;function f(p){if(Ln){if(nt&&!$&&ve&&!Us()&&ve.resume(),!vn||aa){let y=S=>zs.includes(S.target)||S.target===Mn,x=[];for(let S of p.touches)y(S)||x.push(S);let w=x.length,A=0;if(w){let S=v(x[0].clientX,x[0].clientY),_=Ke;Ke=h(S),d?Ct=Ct.add(Ke.subtract(_)):ie[0][A]=3}else d&&(ie[0][A]=ie[0][A]&2|4);d=w}return is&&p.cancelable&&document.hasFocus()&&p.preventDefault(),!0}}}function h(d){let f=q.getBoundingClientRect(),p=Ve(d.x,f.left,f.right),y=Ve(d.y,f.top,f.bottom);return v(p*q.width,y*q.height)}}function Gc(){if($)return;!(Ln&&ft)&&!document.hasFocus()&&ai(),Jt=oi(Ke),ha=bl(Ct),rh(),e(),t();function t(){let n=Ds(0)||Ds(1)||Ds(2)||Ct.length()>ma,s=!1;for(let r=wl();r--&&!s;)s=Ns(r).lengthSquared()>.04;for(let r=17;r--&&!s;)s=Nt(r);let i=!1;for(let r in ie[0])if(isNaN(+r)&&ie[0][r]&1){i=!0;break}s?hn="gamepad":n?hn="mouse":i&&(hn="keyboard"),rs=hn==="gamepad"}function e(){var a,o,c,l,u,h,d;let n=f=>{let x=w=>w>.3?Ve(w,.3,.8):w<-.3?-Ve(-w,.3,.8):0;return v(x(f.x),x(-f.y)).clampLength()};if(vn&&ft){if(m(!Un||!gs,"set touchGamepadLeftStick or touchGamepadLeftButtonCount, not both"),m(!bs||!ys,"set touchGamepadRightStick or touchGamepadButtonCount, not both"),!ds.isSet())return;Ae=0;let f=(a=_t[0])!=null?a:_t[0]=[],p=(o=Pn[0])!=null?o:Pn[0]=v();f.length=0,p.set();for(let x=0;x<2;x++){if(!Zt(x))continue;let w=wa(x);f[w]=v();let A=(c=Jn[x])!=null?c:v();if(ni)f[w]=n(A);else if(A.lengthSquared()>.3){let S=H(Ci(A.x),-1,1),_=H(Ci(A.y),-1,1);f[w]=v(S,-_).clampLength(),w||p.set(S,-_)}}let y=(l=ie[1])!=null?l:ie[1]=[];for(let x=12;x--;){let w=Nt(x,0);y[x]=ht[x]?w?1:3:w?4:0,Pi&&y[x]===3&&(x===9||ah(x))&&xa(Pi)}return}try{if(!uo||!(navigator!=null&&navigator.getGamepads))return}catch{return}if(!Ue&&!document.hasFocus())return;let s=8,i=navigator.getGamepads(),r=le(s,i.length);for(let f=0;f>1]=n(v(p.axes[S],p.axes[S+1]));let A=!1;for(let S=p.buttons.length;S--;){let _=p.buttons[S],k=Nt(S,f);y[S]=_.pressed?k?1:3:k?4:0,_.pressed&&(!_.value||_.value>.9)&&(A=!0)}A&&(Zo[f]=!0,Zo[Ae]||(Ae=f)),p.mapping==="standard"&&w.set((Nt(15,f)&&1)-(Nt(14,f)&&1),(Nt(12,f)&&1)-(Nt(13,f)&&1)),ra&&(w.x||w.y)&&(x[0]=w.clampLength())}vn&&rs&&ds.unset()}}function Bc(){if(!$){for(let t of ie)for(let e in t)t[e]&=1;pa=0,ha=v(),Ct=v()}}function oh(){dh()}function rh(){if(un||!vn||!ft||$||!document.body)return;let t=un=document.createElement("div");t.style.cssText="position:fixed;inset:0;z-index:50;pointer-events:none;opacity:0;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;transition:opacity .2s;box-sizing:border-box;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)";let e=Al=document.createElement("div");e.style.cssText="position:relative;width:100%;height:100%;pointer-events:none",t.appendChild(e);let n=Sa=document.createElementNS(Gi,"svg");n.style.cssText="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible;fill:none;stroke:#fff;stroke-width:3",e.appendChild(n);let s=()=>{let i=document.createElement("div");return i.style.cssText="position:absolute;pointer-events:auto;touch-action:none",i.addEventListener("pointerdown",r=>mh(r,i)),i.addEventListener("pointermove",r=>yh(r)),i.addEventListener("pointerup",r=>jc(r)),i.addEventListener("pointercancel",r=>jc(r)),e.appendChild(i),i};zs[0]=s(),zs[1]=s(),Mn=s(),addEventListener("resize",()=>fs=!0),document.body.appendChild(t),fs=!0}function fo(){return Al.getBoundingClientRect()}function Zt(t){return t?bs:Un}function qn(t){return t?ys:gs}function va(t){return t?0:4}function wa(t){return t&&Un?1:0}function hs(t){return Zt(t)||qn(t)>0}function ah(t){for(let e=0;e<2;e++){let n=va(e);if(!Zt(e)&&t>=n&&tr.style.cssText="position:absolute;pointer-events:auto;touch-action:none;"+a;if(Mt){for(let r of zs)r.style.display="none";vt?(i(Mn,"inset:0"),Mn.style.display=""):Mn.style.display="none"}else{for(let a=0;a<2;a++){let o=zs[a],c=a?"right":"left";if(o.style.display=hs(a)?"":"none",Tn){let l=hs(a?0:1)?"50%":"100%";i(o,`${c}:0;bottom:0;width:${l};height:60%`)}else i(o,`${c}:0;bottom:0;width:${3*s}px;height:${3*s}px`)}Mn.style.display=vt?"":"none";let r=vt;i(Mn,`left:50%;top:50%;width:${2*r}px;height:${2*r}px;transform:translate(-50%,-50%)`)}lh(e,n),fs=!1}function lh(t,e){let n=Sa;for(;n.firstChild;)n.removeChild(n.firstChild);let s=kl={face:[],thumb:[]},i=tt,r=(o,c,l,u)=>{let h=document.createElementNS(Gi,"circle");return h.setAttribute("cx",o),h.setAttribute("cy",c),h.setAttribute("r",l),u&&h.setAttribute("fill",u),n.appendChild(h),h},a=o=>{let c=i*.18,l=i*.5,u=o.x,h=o.y,d=document.createElementNS(Gi,"path");d.setAttribute("d",`M ${u-c} ${h-l} H ${u+c} V ${h-c} H ${u+l} V ${h+c} H ${u+c} V ${h+l} H ${u-c} V ${h+c} H ${u-l} V ${h-c} H ${u-c} Z`),n.appendChild(d)};for(let o=0;o<2;o++){let c=qn(o),l=va(o),u=Yt(o,t,e);if(Zt(o))ni?r(u.x,u.y,i/2):a(u),s.thumb[o]=r(u.x,u.y,i/4,"#fff");else if(c===1)s.face[l]=r(u.x,u.y,i/2,"#000");else for(let h=0;h2?d:le(d,c-1);f=f===3?2:f===2?3:f;let p=v().setDirection(d,i/2);c===2&&(p.x*=-1),o||(p.x*=-1);let y=u.add(p);s.face[l+f]=r(y.x,y.y,i/4,"#000")}}Ue&&Fn&&uh(t,e)}function uh(t,e){let n=tt,s=Sa,i=(a,o,c)=>{let l=document.createElementNS(Gi,a);for(let u in o)l.setAttribute(u,o[u]);l.setAttribute("stroke",c),l.setAttribute("stroke-width",2),l.setAttribute("fill","none"),s.appendChild(l)},r=(a,o,c)=>i("circle",{cx:a.x,cy:a.y,r:o},c);i("line",{x1:t/2,y1:0,x2:t/2,y2:e},"#0f0");for(let a=0;a<2;a++)if(Zt(a))if(Tn){let o=e*.4,c=!hs(a?0:1),l=c?0:a?t/2:0;i("rect",{x:l,y:o,width:c?t:t/2,height:e-o},"#0ff")}else r(Yt(a,t,e),2*n,"#0ff");else qn(a)>=1&&r(Yt(a,t,e),n,"#0ff");if(vt){r(v(t/2,e/2),vt,"#ff0");for(let a=0;a<2;a++)hs(a)&&r(Yt(a,t,e),2*n,"#f0f")}}function dh(){var l;if(!un||$)return;if(!vn||!ft){un.style.display!=="none"&&(un.style.display="none",Ht.clear(),ht.length=0,Jn.length=0,ci.length=0);return}un.style.display="";let t=Ue&&Fn,e=[ys,gs,Un,bs,ni,tt,Tn,vt,Mt,t].join();e!==Fc&&(Fc=e,fs=!0),fs&&ch();let n=Os?Ve(ds.get(),Os+1,Os):1,s=t||ds.isSet()&&n>0&&!Mt;if(un.style.opacity=s?t?1:n*ca:0,!s)return;let i=fo(),r=i.width,a=i.height,o=tt,c=kl;if(c){for(let u=0;u<2;u++)if(Zt(u)&&c.thumb[u]){let d=Yt(u,r,a).add(((l=Jn[u])!=null?l:v()).scale(o/2));c.thumb[u].setAttribute("cx",d.x),c.thumb[u].setAttribute("cy",d.y)}for(let u=0;u=tt)return-1;if(i===1)return r;let o=a.subtract(e);t||(o.x*=-1);let c=i===2?o.xr:o&&Yt(a,e,n).distance(t)<2*s)return{role:"stick",side:a}}else if(qn(a)>=1){let c=hh(a,t,e,n);if(c>=0)return{role:"face",btn:c}}}if(vt){for(let a=0;a<2;a++)if(hs(a)&&Yt(a,e,n).distance(t)<2*s)return;if(v(e/2,n/2).distance(t)h.getChannelData(x).set(y)),d.buffer=h,d.playbackRate.value=n,d.loop=i,a=a||ve.createGain(),a.gain.value=e,a.connect(Xt);let f=new StereoPannerNode(ve,{pan:H(s,-1,1)});d.connect(f).connect(a),d.addEventListener("ended",()=>{a.disconnect(),f.disconnect(),c&&c(d)});let p=o*n;return d.start(0,p),Ue&&ls&&Ce("sound","vol",e.toFixed(2),"rate",n.toFixed(2),"pan",s.toFixed(2),i?"loop":""),d}function Sh(...t){return Ta([ho(...t)])}function ho(t=1,e=.05,n=220,s=0,i=0,r=.1,a=0,o=1,c=0,l=0,u=0,h=0,d=0,f=0,p=0,y=0,x=0,w=1,A=0,S=0,_=0){let k=xs,C=te*2,L=c*=500*C/k/k,V=n*=(1+Se(e,-e))*C/k,ce=0,ne=0,T=0,P=1,R,M=[],j=0,se=0,we=0,be,Ft=2,en=C*de(_)*2/k,We=ye(en),Gt=fe(en)/2/Ft,lt=1+Gt,mt=-2*We/lt,$n=(1-Gt)/lt,Bt=(1+ut(_)*We)/2/lt,Yn=-(ut(_)+We)/lt,Ss=Bt,tn=0,nn=0,sn=0,Xn=0;for(s=s*k||9,A*=k,i*=k,r*=k,x*=k,l*=500*C/k**3,p*=C/k,u*=C/k,h*=k,d=d*k|0,R=s+A+i+r+x|0;se1?a>2?a>3?a>4?j/C%14?we:ut(we)*de(we)**o)*(sese?0:(seh&&(n+=u,V+=u,P=0),d&&!(++ne%d)&&(n=V,c=L,P||(P=1));return M}function ji(t,e=!0){for(let n of bn)if((!e||n.isSolid)&&t.arrayCheck(n.size)){let s=n.getCollisionData(t);if(s)return s}return 0}function dn(t,e=v(),n,s=!0){for(let i of bn)if((!s||i.isSolid)&&i.collisionTest(t,e,n))return i}function El(t,e,n,s,i=!0){let r,a,o,c=s&&v();for(let l of bn)if(!i||l.isSolid){let u=l.collisionRaycast(t,e,n,c);if(u){let h=t.distanceSquared(u);(r===void 0||h{W=!1,ue.style.display="none",n.preventDefault(),Ce("WebGL context lost! Switching to Canvas2d rendering.");for(let s of Is)s.glTexture=void 0;at=void 0,De=0,Nn=!1,Dn.forEach(s=>{var i;return(i=s.glContextLost)==null?void 0:i.call(s)})}),ue.addEventListener("webglcontextrestored",()=>{W=!0,ue.style.display="",Ce("WebGL context restored, reinitializing..."),e();for(let n of Is)n.glTexture=mo(n.image,n.wrap);Dn.forEach(n=>{var s;return(s=n.glContextRestored)==null?void 0:s.call(n)})});function e(){zi=ms(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 g;in vec4 p,u,c,a;in float r;out vec2 v;out vec4 d,e;void main(){vec2 s=(g-.5)*p.zw;gl_Position=m*vec4(p.xy+s*cos(r)-vec2(-s.y,s)*sin(r),1,1);v=mix(u.xw,u.zy,g);d=c;e=a;}`,`#version 300 es
+precision highp float;uniform sampler2D s;in vec2 v;in vec4 d,e;out vec4 c;void main(){c=texture(s,v)*d+e;}`),Ui=ms(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 p;in vec4 c;out vec4 d;void main(){gl_Position=m*vec4(p,1,1);d=c;}`,`#version 300 es
+precision highp float;in vec4 d;out vec4 c;void main(){c=d;}`);let n=new ArrayBuffer(Wi);ze=new Float32Array(n),Hs=new Uint32Array(n),dr=g.createBuffer(),as=g.createBuffer(),ka=g.createFramebuffer(),De=0;let s=new Float32Array([0,0,1,0,0,1,1,1]);g.bindBuffer(g.ARRAY_BUFFER,as),g.bufferData(g.ARRAY_BUFFER,s,g.STATIC_DRAW);let i,r,a,o=(c,l,u,h,d=0)=>{let f=g.getAttribLocation(r,c),p=u===1,y=u&&a;g.enableVertexAttribArray(f),g.vertexAttribPointer(f,h,l,p,y,i),g.vertexAttribDivisor(f,d),i+=h*u};fr=g.createVertexArray(),g.bindVertexArray(fr),i=0,r=zi,a=Rl,g.bindBuffer(g.ARRAY_BUFFER,as),o("g",g.FLOAT,0,2),g.bindBuffer(g.ARRAY_BUFFER,dr),g.bufferData(g.ARRAY_BUFFER,Wi,g.DYNAMIC_DRAW),o("p",g.FLOAT,4,4,1),o("u",g.FLOAT,4,4,1),o("c",g.UNSIGNED_BYTE,1,4,1),o("a",g.UNSIGNED_BYTE,1,4,1),o("r",g.FLOAT,4,1,1),hr=g.createVertexArray(),g.bindVertexArray(hr),i=0,r=Ui,a=Pl,o("p",g.FLOAT,4,2),o("c",g.UNSIGNED_BYTE,1,4)}}function $s(t=!1){!t&&!Nn||(Fe(),Nn=!1,g.useProgram(zi),g.bindVertexArray(fr))}function Ml(){Nn||(Fe(),Nn=!0,g.useProgram(Ui),g.bindVertexArray(hr))}function mr(t=!0){if(!W||!g)return;m(!De,"glPreRender called with unflushed batch."),Vi||(ue.width=N.x,ue.height=N.y),g.viewport(0,0,N.x,N.y),t&&Ll();let e=v(2*ee).divide(N);Vi&&(e.y=-e.y);let n=Ie.rotate(-ae),s=v(-1).subtract(n.multiply(e)),i=ye(ae),r=fe(ae),a=[e.x*i,e.y*r,0,0,-e.x*r,e.y*i,0,0,1,1,1,0,s.x,s.y,0,1],o=(c,l,u)=>{g.useProgram(c);let h=g.getUniformLocation(c,l);g.uniformMatrix4fv(h,!1,u)};o(Ui,"m",a),o(zi,"m",a),g.activeTexture(g.TEXTURE0),wn[0]&&(at=wn[0].glTexture,g.bindTexture(g.TEXTURE_2D,at)),g.bindBuffer(g.ARRAY_BUFFER,dr),Hn=ps=!1,$s(!0)}function Ll(){if(!g)return;let t=mn;g.clearColor(t.r,t.g,t.b,t.a),g.clear(g.COLOR_BUFFER_BIT)}function _a(t){!g||t===at||(Fe(),at=t,g.bindTexture(g.TEXTURE_2D,at))}function Ol(t,e=!0){if(!g||!t)return;let n=t===at;n?Fe():g.bindTexture(g.TEXTURE_2D,t);let s=e?g.REPEAT:g.CLAMP_TO_EDGE;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,s),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,s),!n&&at&&g.bindTexture(g.TEXTURE_2D,at)}function yr(t,e){if(!g)return;let n=g.createShader(e);if(g.shaderSource(n,t),g.compileShader(n),Ue&&!g.getShaderParameter(n,g.COMPILE_STATUS))throw g.getShaderInfoLog(n);return n}function ms(t,e){if(!g)return;let n=g.createProgram();if(g.attachShader(n,yr(t,g.VERTEX_SHADER)),g.attachShader(n,yr(e,g.FRAGMENT_SHADER)),g.linkProgram(n),Ue&&!g.getProgramParameter(n,g.LINK_STATUS))throw g.getProgramInfoLog(n);return n}function mo(t,e=!1){if(!g)return;let n=g.createTexture(),s=!1;if(t!=null&&t.width)Ea(n,t),g.bindTexture(g.TEXTURE_2D,n),s=!jn&&Gs(t.width)&&Gs(t.height);else{let o=new Uint8Array([255,255,255,255]);g.bindTexture(g.TEXTURE_2D,n),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,1,1,0,g.RGBA,g.UNSIGNED_BYTE,o)}let i=jn?g.NEAREST:g.LINEAR,r=s?g.LINEAR_MIPMAP_LINEAR:i;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,i),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,r);let a=e?g.REPEAT:g.CLAMP_TO_EDGE;return g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,a),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,a),s&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,at),n}function Dl(t){g&&g.deleteTexture(t)}function Ea(t,e){g&&(m((e==null?void 0:e.width)>0,"Invalid image data."),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e),!jn&&Gs(e.width)&&Gs(e.height)&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,at))}function kh(t){$||(Is.add(t),g&&(t.glTexture?Ea(t.glTexture,t.image):t.glTexture=mo(t.image,t.wrap)))}function Ch(t){if($)return;Is.delete(t);let e=t.glTexture;t.glTexture=void 0,Dl(e)}function Fe(){if(W&&g&&De){let t=ps?g.ONE:g.ONE_MINUS_SRC_ALPHA;g.blendFuncSeparate(g.SRC_ALPHA,t,g.ONE,t),g.enable(g.BLEND);let e=De*(Nn?po:Ca);g.bufferSubData(g.ARRAY_BUFFER,0,ze,0,e),Nn?g.drawArrays(g.TRIANGLE_STRIP,0,De):g.drawArraysInstanced(g.TRIANGLE_STRIP,0,4,De),++Ot,Dt+=De,De=0}ps=Hn}function Ra(t){!W||!g||(Fe(),t.drawImage(ue,0,0))}function _h(t=!0){m(!ue,"must be called before engineInit"),Aa=t}function Ys(t,e,n,s,i=0,r=0,a=0,o=1,c=1,l=-1,u=0){(De>=Th||ps!==Hn)&&Fe(),$s();let h=De++*Ca;ze[h++]=t,ze[h++]=e,ze[h++]=n,ze[h++]=s,ze[h++]=r,ze[h++]=a,ze[h++]=o,ze[h++]=c,Hs[h++]=l,Hs[h++]=u,ze[h++]=i}function Il(t,e,n,s,i,r){Ys(t,e,n,s,i,0,0,0,0,0,r)}function Pa(t,e,n,s,i,r,a,o=!0){let c=[],l=fe(-a),u=ye(-a);for(let d of t){let f=d.x*i,p=d.y*r;c.push(v(n+u*f-l*p,s+l*f+u*p))}let h=o?Rh(c):c;Fl(h,e)}function Ma(t,e,n,s,i,r,a,o,c=!0){let l=Eh(t,n,c);Pa(l,e,s,i,r,a,o,!1)}function Fl(t,e){if(!W||t.length<3)return;let n=t.length+2;if((De+n>=cs||ps!==Hn)&&Fe(),m(n=cs)return;Ml();let s=De*po;for(let i=n;i--;){let r=H(i-1,0,n-3),a=t[r];ze[s++]=a.x,ze[s++]=a.y,Hs[s++]=e}De+=n}function La(t,e){if(!W||t.length<3)return;let n=t.length+2;if((De+n>=cs||ps!==Hn)&&Fe(),m(n=cs)return;Ml();let s=De*po;for(let i=n;i--;){let r=H(i-1,0,n-3),a=t[r],o=e[r];ze[s++]=a.x,ze[s++]=a.y,Hs[s++]=o}De+=n}function Ps(t,e=!1){t?(Vi=t,g.bindFramebuffer(g.FRAMEBUFFER,ka),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,t,0),mr(e)):(Fe(),Vi=void 0,g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,N.x,N.y))}function Gl(t,e,n,s){W&&(g.enable(g.SCISSOR_TEST),g.scissor(t,e,n,s),g.clearColor(0,0,0,0),g.clear(g.COLOR_BUFFER_BIT),g.disable(g.SCISSOR_TEST))}function Eh(t,e,n=!0){if(t.length<2)return[];let s=e/2,i=[],r=t.length,a=1e-6,o=10;for(let c=0;ca?-f/p:0,S=p>a?d/p:0,_=w>a?-x/w:0,k=w>a?y/w:0,C=A+_,L=S+k,V=(C*C+L*L)**.5;if(Va){let P=le(1/T,o);C*=P,L*=P}}let ce=v(u.x-C*s,u.y-L*s),ne=v(u.x+C*s,u.y+L*s);i.push(ce),i.push(ne)}return i.length>1&&n&&(i.push(i[0]),i.push(i[1])),i}function Rh(t){if(t.length<3)return[];let e=(f,p,y)=>(p.x-f.x)*(y.y-f.y)-(p.y-f.y)*(y.x-f.x);(f=>{let p=0;for(let y=f.length;y--;){let x=(y+1)%f.length;p+=f[y].cross(f[x])}return p})(t)<0&&(t=t.slice().reverse());let s=1e-9,i=(f,p,y,x)=>{let w=e(p,y,f),A=e(y,x,f),S=e(x,p,f),_=(w<-s?1:0)+(A<-s?1:0)+(S<-s?1:0),k=(w>s?1:0)+(A>s?1:0)+(S>s?1:0);return!(_&&k)},r=[];for(let f=0;f3&&o++{if(_>=0){let C=s.fillStyle=s.createLinearGradient(x,w,A,S);C.addColorStop(0,h(_,2)),C.addColorStop(1,h(_,1))}else s.fillStyle="#000";_>=-1?(s.fill(),k&&s.stroke()):s.stroke()},c=(x,w,A,S=0,_=2*te,k,C)=>{s.beginPath(),s.arc(x,w,A,f*S,f*_),o(x,w-A,x,w+A,k,C)},l=(x,w,A,S,_)=>{s.beginPath(),s.rect(x,w,A,S*f),o(x,w+S,x+A,w,_)},u=(x,w,A,S)=>{s.beginPath();for(let _ of x)s.lineTo(_.x,_.y);s.closePath(),o(0,A,0,A+S,w)},h=(x,w)=>w?`hsl(${[.95,.56,.13][x%3]*360} 99%${[0,50,75][w]}%)`:"#000",d=sl(1,1,t),f=Ve(d,.1,.5),p=le(6,le(r,a)/99);s.translate(r/2,a/2),s.scale(p,p),s.translate(-40,-35),f<1&&s.setLineDash([99*f,99]),s.lineJoin=s.lineCap="round",s.lineWidth=.1+f*1.9;{let w="LittleJS";s.font="900 15.5px arial",s.lineWidth=.1+f*3.9,s.textAlign="center",s.textBaseline="top",l(11,55,59,8*f,-1),s.beginPath();let A=0;for(let S=0;S5?1:0),s[S?"strokeText":"fillText"](w[_],L,54+.5,17*f),k+=C}s.lineWidth=.1+f*1.9,l(3,54,73,0)}l(7,15,26,-7,0),l(25,15,8,25,-1),l(10,40,15,-25,1),l(14,21,7,9,2),l(38,20,6,-6,2),l(49,20,10,-6,0);let y=[v(44,8),v(64,8),v(59,8+6*f),v(49,8+6*f)];u(y,2,8,6*f),l(44,8,20,-7,0);for(let x=5;x--;)c(59-x*6*f,30,10,0,2*te,1,0);c(59,30,4,0,7,2),l(35,20,24,0),c(59,30,10),c(47,30,10,te/2,te*3/2),c(35,30,10,te/2,te*3/2),l(7,40,13,7,-1),l(17,40,43,14,-1);for(let x=3;x--;)for(let w=2;w--;)c(17+15*x,47,w?7:1,0,2*te,2);for(let x=2;x--;){let w=6,A=7,S=53+w*f*x,_=[v(S+A,54),v(S,40),v(S+w*f,40),v(S+A+w*f,54)];u(_,0,40,14)}s.restore()}function Mh(t){if($i=t,!Rn){let n={};try{n=JSON.parse(localStorage[t]||"{}")}catch{n={}}yo(s=>{s.unlocked=!!(n[s.id]&&n[s.id].unlocked)}),Da()}zn(void 0,e);function e(){if(!wi.length)return;let n=wi[0],s=xn-vi;if(!vi)vi=xn;else if(s>qi)vi=0,wi.shift();else{let i=qi-os,r=si?(s-i)/os:0;n.render(r)}}}function yo(t){Object.values(Xs).forEach(e=>t(e))}function Lh(){yo(t=>t.unlocked=!1),Da()}function Da(){if(!$i)return;let t={};yo(e=>{let n={name:e.name,description:e.description,icon:e.icon,unlocked:e.unlocked};e.image&&(n.src=e.image.src),t[e.id]=n}),localStorage[$i]=JSON.stringify(t)}function Oh(t){qi=t}function Dh(t){os=t}function Ih(t){Hi=t.copy()}function Fh(t){Oa=t}function Bl(t,e,n,s=125){let i,r,a,o,c,l,u,h,d,f,p,y,x,w=0,A,S=[],_=[],k=[],C=0,L=0,V=1,ce={},ne=xs/s*60>>2;for(;V;C++)S=[V=h=y=0],n.forEach((T,P)=>{for(u=e[T][C]||[0,0,0],V|=e[T][C]&&1,A=y+(e[T][0].length-2-(h?0:1))*ne,x=P===n.length-1,i=2,a=y;ine-99&&d&&p<1?p+=1/99:0)l=(1-p)*S[w++]/2||0,_[a]=(_[a]||0)-l*L+l,k[a]=(k[a++]||0)+l*L+l;c&&(p=c%1,L=u[1]||0,(c|=0)&&(S=ce[[f=u[w=0]||0,c]]=ce[[f,c]]||(o=[...t[f]],o[2]=(o[2]||220)*2**(c/12-1),c>0?ho(...o):[])))}y=A});return[_,k]}function Gh(t){Ia=typeof t=="boolean"?t?1:0:t}function Bh(t){Fa=t}async function jh(){return new eo(await Box2D()),n(),zn(t,e),b;function t(){if(!Mt){b.step(),b.objects=b.objects.filter(s=>!s.destroyed);for(let s of b.objects)s.body&&(s.pos=b.vec2From(s.body.GetPosition()),s.angle=-s.body.GetAngle())}}function e(){(Fa||bt)&&b.world.DrawDebugData()}function n(){let i=new b.instance.JSDraw,r=l=>new Me(l.get_r(),l.get_g(),l.get_b()),a=l=>r(b.instance.wrapPointer(l,b.instance.b2Color)),o=l=>a(l).scale(1,.8),c=(l,u)=>{let h=[];for(let d=u;d--;)h.push(b.vec2FromPointer(l+d*8));return h};i.DrawSegment=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),u=b.vec2FromPointer(u),On(l,u,.1,h,v(),0,!1)},i.DrawPolygon=function(l,u,h){h=o(h);let d=c(l,u);us(d,Sn,.1,h,v(),0,!1)},i.DrawSolidPolygon=function(l,u,h){h=o(h);let d=c(l,u);us(d,h,0,h,v(),0,!1)},i.DrawCircle=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),Oi(l,u*2,Sn,.1,h,!1)},i.DrawSolidCircle=function(l,u,h,d){d=o(d),l=b.vec2FromPointer(l),h=b.vec2FromPointer(h).scale(u),Oi(l,u*2,d,.1,d,!1),On(v(),h,.1,d,l,0,!1)},i.DrawTransform=function(l){l=b.instance.wrapPointer(l,b.instance.b2Transform);let u=b.vec2From(l.get_p()),h=-l.get_q().GetAngle(),d=v(1,0),f=Y(.75,0,0,.8),p=v(0,1),y=Y(0,.75,0,.8);On(v(),d,.1,f,u,h,!1),On(v(),p,.1,y,u,h,!1)},i.AppendFlags(b.instance.b2Draw.e_shapeBit),i.AppendFlags(b.instance.b2Draw.e_jointBit),b.world.SetDebugDraw(i)}}function Jh(t,e,n,s=32,i=2,r=0){jl(t,e,n,Q,s,he,i,r,!1,!0)}function jl(t,e,n,s,i=1,r,a=.05,o=0,c=W,l,u){let h=n.offset(n.size),d=e.add(v(a-i*2)),f=v(i),p=e.scale(.5).subtract(f.scale(.5)),y=l?-1:1,x=l?-o:o;Be(t,d,h,s,o,!1,r,c,l,u);for(let w=4;w--;){let A=w%2,S=p.multiply(v(A?w===1?1:-1:0,A?0:w?-1:1)),_=v(A?i:d.x,A?d.y:i),k=h.offset(n.size.multiply(v(w===1?1:w===3?-1:0,w===0?-y:w===2?y:0)));Be(t.add(S.rotate(x)),_,k,s,o,!1,r,c,l,u)}for(let w=4;w--;){let A=w>1,S=w&&w<3,_=p.multiply(v(A?-1:1,S?-1:1)),k=h.offset(n.size.multiply(v(A?-1:1,S?y:-y)));Be(t.add(_.rotate(x)),f,k,s,o,!1,r,c,l,u)}}function Nh(t,e,n,s=32,i=2,r=0){Jl(t,e,n,Q,s,he,i,r,!1,!0)}function Jl(t,e,n,s,i=1,r,a=.05,o=0,c=W,l,u){let h=n.frame(0),d=n.frame(1),f=n.frame(2),p=e.add(v(a-i*2)),y=v(i),x=e.scale(.5).subtract(y.scale(.5)),w=l?-1:1,A=l?-o:o;Be(t,p,f,s,o,!1,r,c,l,u);for(let S=4;S--;){let _=o+S*te/2,k=S%2,C=x.multiply(v(k?S===1?1:-1:0,k?0:S?-w:w)),L=v(k?p.y:p.x,i);Be(t.add(C.rotate(A)),L,d,s,_,!1,r,c,l,u)}for(let S=4;S--;){let _=o+S*te/2,k=!S||S>2,C=S>1,L=x.multiply(v(k?-1:1,C?-w:w));Be(t.add(L.rotate(A)),y,h,s,_,!1,r,c,l,u)}}function zh(t,e=1,n=0,s=Q,i=0,r=!1,a=0,o=he,c=W,l=!1,u){let h=Nl(v(),e,n,0,r);us(h,s,a,o,t,i,c,l,u)}function Nl(t,e=1,n=0,s=0,i=!1,r=ti){m(D(t),"pos must be a vec2"),m(O(e)&&O(n),"size and percent must be numbers");let a=dt(n*4,4);a>=2&&(s+=te),a=a<=2?a-1:3-a,i&&(a=-a,s+=te);let o=[],c=re(3,r>>1),l=e/2;for(let u=0;u<=c;u++){let h=u/c*te;o.push(v(l*ye(h),l*fe(h)).rotate(s).add(t))}for(let u=c;u>=0;u--){let h=u/c*te;o.push(v(l*ye(h),-l*a*fe(h)).rotate(s).add(t))}return o}function zc(t){return t&&typeof t.lerp=="function"}function Uh(t,e,n,s,i=1,r={}){m(t!=null&&typeof t=="object","tweenProperty target must be an object"),m(K(e)&&e.length>0,"tweenProperty propertyPath must be a non-empty string");let a=e.split("."),o=a.pop(),c=l=>{let u=t;for(let h of a)u=u[h];u[o]=l};return new to(c,n,s,i,r)}function zl(t){t.loopRemaining!==1/0&&t.loopRemaining<=1||(t.loopRemaining!==1/0&&(t.loopRemaining-=1),t.life=t.duration,t.thenCallback=()=>zl(t),ot.push(t),t.callback(t.interp(t.duration)))}function Ul(t){if(t.loopRemaining!==1/0&&t.loopRemaining<=1)return;t.loopRemaining!==1/0&&(t.loopRemaining-=1);let e=t.start;t.start=t.end,t.end=e,t.life=t.duration,t.thenCallback=()=>Ul(t),ot.push(t),t.callback(t.interp(t.duration))}function Vl(t,e){t===void 0?(t=rt-Jc,e=xn-Nc,Jc=rt,Nc=xn):e===void 0&&(e=t);for(let n=ot.length;n--;){let s=ot[n];if(s.paused)continue;let i=s.useRealTime?e:t;if(!(i<=0))if(s.life-=i,s.life>0)s.callback(s.interp(s.life));else{s.callback(s.interp(0)),ot.splice(n,1);let r=s.thenCallback;s.thenCallback=void 0,r&&r()}}}function Vh(){for(let t of ot)t.thenCallback=void 0;ot.length=0}var Ti,Ai,sd,Vr,_e,Wr,Uc,rt,xn,Mt,Qo,kt,ki,Vc,Dn,tr,Ue,Hc,io,$c,zt,pn,bt,xt,In,Fn,ls,nr,Ut,gt,te,de,Pe,Fs,Ci,le,re,ut,Qc,Zc,fe,ye,el,Hr,or,me,Me,Q,Sn,he,wt,vd,Xr,wd,ll,ul,Td,dl,fl,Ad,Lt,Ie,ae,ee,Qr,oo,mn,ts,Ms,ns,ss,Zr,jn,yn,ei,ea,$,W,ti,ro,ao,co,lo,ta,na,sa,ia,oa,Wt,Ze,Ri,uo,ra,Ls,Ln,vn,aa,vt,ys,Un,gs,bs,ni,Tn,tt,ca,Os,Pi,si,nt,Gn,la,ua,Kt,q,ge,Oe,$t,fn,Et,qt,N,wn,Ot,Dt,It,Qt,Df,vl,Di,Jt,Ke,ha,Ct,pa,Ii,rs,hn,ma,is,Ae,ft,ie,_t,Pn,Zo,ds,ht,Jn,Fi,ci,Ht,un,Al,Sa,kl,zs,Mn,fs,Fc,Gi,ve,Xt,xs,Vs,Bi,bn,Bn,Ji,Ws,qs,ur,wh,Ni,ue,g,Aa,zi,Ui,Nn,Hn,ps,at,dr,as,ze,Hs,De,Is,fr,hr,ka,Vi,pr,Wi,Ca,Rl,Th,po,Pl,cs,Rn,qi,os,Hi,Oa,Xs,wi,$i,vi,Yi,Ks,gr,br,Je,xr,Z,Sr,vr,wr,E,Ia,Tr,pt,Xi,Ar,kr,Qs,Cr,_r,Er,Rr,b,Fa,Zs,Ki,Pr,Mr,Qi,st,Lr,Zi,Or,Dr,Ir,Fr,Gr,Br,jr,Jr,Nr,zr,eo,ot,Jc,Nc,to,no,Wh,er,so,Ur,ql=Kl(()=>{"use strict";Ti="LittleJS",Ai="1.18.19",sd=60,Vr=.016666666666666666,_e=[],Wr=[],Uc=0,rt=0,xn=0,Mt=!1;Qo=0,kt=0,ki=0,Vc=!0,Dn=[],tr=class{constructor(e,n,s,i){this.update=e,this.render=n,this.glContextLost=s,this.glContextRestored=i}};Ue=!0,Hc=.5,io=!0,$c="Escape",zt=!1,pn=[],bt=!1,xt=!1,In=!1,Fn=!1,ls=!1;te=Math.PI,de=Math.abs,Pe=Math.floor,Fs=Math.ceil,Ci=Math.round,le=Math.min,re=Math.max,ut=t=>Math.sign(t),Qc=(...t)=>Math.hypot(...t),Zc=t=>Math.log2(t),fe=Math.sin,ye=Math.cos,el=Math.tan,Hr=Math.atan2;or=class{constructor(e=123456789){m(e!==0,"RandomGenerator seed must be non-zero (xorshift is fixed at 0)"),this.seed=e}float(e=1,n=0){return this.seed^=this.seed<<13,this.seed^=this.seed>>>17,this.seed^=this.seed<<5,n+(e-n)*((this.seed>>>0)/2**32)}int(e,n=0){return Pe(this.float(e,n))}bool(e=.5){return this.float().5?1:-1}floatSign(e=1,n=0){let s=le(e,n),r=re(e,n)-s,a=this.float(r*2);return ae?this.scale(e/n):this.copy()}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.x}reflect(e,n=1){return this.subtract(e.scale((1+n)*this.dot(e)))}angle(){return Hr(this.x,this.y)}setAngle(e=0,n=1){return it(e),it(n),this.x=n*fe(e),this.y=n*ye(e),this}rotate(e){it(e);let n=ye(-e),s=fe(-e);return new t(this.x*n-this.y*s,this.x*s+this.y*n)}setDirection(e,n=1){return it(e),it(n),e=dt(e,4),m(e===0||e===1||e===2||e===3,"Vector2.setDirection() direction must be an integer between 0 and 3."),this.x=e%2?e-1?-n:n:0,this.y=e%2?0:e?-n:n,this}direction(){return de(this.x)>de(this.y)?this.x<0?3:1:this.y<0?2:0}abs(){return new t(de(this.x),de(this.y))}floor(){return new t(Pe(this.x),Pe(this.y))}snap(e){return it(e),new t(Pe(this.x*e)/e,Pe(this.y*e)/e)}mod(e=1){return new t(dt(this.x,e),dt(this.y,e))}area(){return de(this.x*this.y)}lerp(e,n){Dc(e),it(n);let s=H(n);return new t(e.x*s+this.x*(1-s),e.y*s+this.y*(1-s))}arrayCheck(e){return this.x>=0&&this.y>=0&&this.x(u=dt(u,1))*6<1?c+(l-c)*6*u:u*2<1?l:u*3<2?c+(l-c)*(4-u*6):c;return this.r=o(a,r,e+1/3),this.g=o(a,r,e),this.b=o(a,r,e-1/3),this.a=i,Rs(this),this}HSLA(){let e=H(this.r),n=H(this.g),s=H(this.b),i=H(this.a),r=re(e,n,s),a=le(e,n,s),o=(r+a)/2,c=0,l=0;if(r!==a){let u=r-a;l=o>.5?u/(2-r-a):u/(r+a),e===r?c=(n-s)/u+(n((s=H(s)*255|0)<16?"0":"")+s.toString(16);return"#"+n(this.r)+n(this.g)+n(this.b)+(e?n(this.a):"")}setHex(e){if(m(K(e),"Color hex code must be a string"),m(e[0]==="#","Color hex code must start with #"),m([4,5,7,9].includes(e.length),"Invalid hex"),e.length<6){let n=s=>H(parseInt(e[s],16)/15);this.r=n(1),this.g=n(2),this.b=n(3),this.a=e.length===5?n(4):1}else{let n=s=>H(parseInt(e.slice(s,s+2),16)/255);this.r=n(1),this.g=n(3),this.b=n(5),this.a=e.length===9?n(7):1}return Rs(this),this}rgbaInt(){let e=H(this.r)*255|0,n=H(this.g)*255<<8,s=H(this.b)*255<<16,i=H(this.a)*255<<24;return e+n+s+i}isValid(){return O(this.r)&&O(this.g)&&O(this.b)&&O(this.a)}},Q=ct(Y()),Sn=ct(Y(1,1,1,0)),he=ct(Y(0,0,0)),wt=ct(Y(0,0,0,0)),vd=ct(Y(.5,.5,.5)),Xr=ct(Y(1,0,0)),wd=ct(Y(1,.5,0)),ll=ct(Y(1,1,0)),ul=ct(Y(0,1,0)),Td=ct(Y(0,1,1)),dl=ct(Y(0,0,1)),fl=ct(Y(.5,0,1)),Ad=ct(Y(1,0,1)),Lt=class{constructor(e,n=!1){m(e===void 0||O(e),"Constructed Timer is invalid.",e),this.useRealTime=n;let s=this.getGlobalTime();this.time=e===void 0?void 0:s+e,this.setTime=e}set(e=0){m(O(e),"Timer is invalid.",e);let n=this.getGlobalTime();this.time=n+e,this.setTime=e}setUseRealTime(e=!0){m(!this.isSet(),"Cannot change global time setting while timer is set."),this.useRealTime=e}unset(){this.time=void 0}isSet(){return this.time!==void 0}active(){return this.getGlobalTime()=this.time}get(){return this.isSet()?this.getGlobalTime()-this.time:0}getPercent(){return this.isSet()?this.setTime?1-Ve(this.time-this.getGlobalTime(),0,this.setTime):1:0}getSetTime(){return this.isSet()?this.setTime:0}getGlobalTime(){return this.useRealTime?xn:rt}toString(){return this.isSet()?de(this.get())+" seconds "+(this.get()<0?"before":"after"):"unset"}valueOf(){return this.get()}};Ie=v(),ae=0,ee=32,Qr=1,oo=!0,mn=wt,ts=v(1920,1080),Ms=0,ns=0,ss=v(),Zr=!1,jn=!0,yn=1,ei="arial",ea=!1,$=!1,W=!0,ti=32,ro=v(16),ao=0,co=0,lo=!0,ta=1,na=1,sa=1,ia=0,oa=.8,Wt=1,Ze=v(),Ri=1,uo=!0,ra=!0,Ls=!0,Ln=!0,vn=!1,aa=!1,vt=0,ys=4,Un=!0,gs=0,bs=!1,ni=!0,Tn=!1,tt=100,ca=.3,Os=3,Pi=0,si=!0,nt=!0,Gn=.3,la=40,ua=.7;Kt=class t{constructor(e=v(),n=v(1),s,i=0,r=Q,a=0){m(D(e),"object pos must be a vec2"),m(D(n),"object size must be a vec2"),m(!s||s instanceof It,"object tileInfo should be a TileInfo or undefined"),m(typeof i=="number"&&isFinite(i),"object angle should be a number"),m(X(r),"object color should be a valid rgba color"),m(typeof a=="number","object renderOrder should be a number"),this.pos=e.copy(),this.size=n.copy(),this.drawSize=void 0,this.tileInfo=s,this.angle=i,this.color=r.copy(),this.additiveColor=void 0,this.mirror=!1,this.destroyed=!1,this.mass=ta,this.damping=na,this.angleDamping=sa,this.restitution=ia,this.friction=oa,this.gravityScale=1,this.renderOrder=a,this.velocity=v(),this.angleVelocity=0,this.spawnTime=rt,this.children=[],this.clampSpeed=!0,this.groundObject=void 0,this.parent=void 0,this.localPos=v(),this.localAngle=0,this.collideTiles=!1,this.collideSolidObjects=!1,this.isSolid=!1,this.collideRaycast=!1,_e.push(this)}updateTransforms(){let e=this.parent;if(e){let n=e.getMirrorSign(),s=this.localPos,i=e.pos,r=s.x*n,a=s.y,o=e.angle;if(o){let c=ye(-o),l=fe(-o);this.pos.set(r*c-a*l+i.x,r*l+a*c+i.y)}else this.pos.set(r+i.x,a+i.y);this.angle=n*this.localAngle+o}for(let n of this.children)n.updateTransforms()}updatePhysics(){if(m(!this.parent),this.destroyed)return;this.clampSpeed&&(this.velocity.x=H(this.velocity.x,-Wt,Wt),this.velocity.y=H(this.velocity.y,-Wt,Wt));let e=this.pos.copy();if(this.velocity.x*=this.damping,this.velocity.y*=this.damping,this.mass&&(this.velocity.x+=Ze.x*this.gravityScale,this.velocity.y+=Ze.y*this.gravityScale),this.pos.x+=this.velocity.x,this.pos.y+=this.velocity.y,this.angle+=this.angleVelocity*=this.angleDamping,m(this.angleDamping>=0&&this.angleDamping<=1),m(this.damping>=0&&this.damping<=1),!lo||!this.mass)return;let n=this.velocity.y<0&&Ze.y<0||this.velocity.y>0&&Ze.y>0;if(this.groundObject){let s=re(this.friction,this.groundObject.friction),i=this.groundObject.velocity.x;this.velocity.x=i+(this.velocity.x-i)*s,this.groundObject=void 0}if(this.collideSolidObjects)for(let i of Wr){if(i.destroyed||i.parent||i===this||!this.isSolid&&!i.isSolid||!this.isOverlappingObject(i))continue;let r=this.collideWithObject(i),a=i.collideWithObject(this);if(!r||!a)continue;if(Ei(e,this.size,i.pos,i.size)){let d=e.subtract(i.pos),f=d.length(),y=f<.001?v(0,1):d.scale(.001/f);this.velocity=this.velocity.add(y),i.mass&&(i.velocity=i.velocity.subtract(y)),bt&&sr(this.pos,this.size,i.pos,i.size,"#f00");continue}let o=this.size.add(i.size),c=(e.y-i.pos.y)*2>o.y+Ze.y,l=de(e.y-i.pos.y)*20?-1:1)>0?Pe(e.y-this.size.y/2+1)+this.size.y/2+.001:Fs(e.y+this.size.y/2-1)-this.size.y/2-.001;if(de(u-this.pos.y)<.1&&!dn(v(this.pos.x,u),this.size,this)){this.pos.y=u,bt&&ke(this.pos,this.size,"#ff0");return}this.pos.x=e.x,this.velocity.x*=-a}if(r||!i){if(n){let c=this.size.y/2+1e-4;this.pos.y=Ze.y<0?Pe(e.y-this.size.y/2)+c:Fs(e.y+this.size.y/2)-c,this.groundObject=s}else this.pos.y=e.y,this.groundObject=void 0;this.velocity.y*=-a}bt&&ke(this.pos,this.size,"#f00")}}}update(){}render(){Be(this.pos,this.drawSize||this.size,this.tileInfo,this.color,this.angle,this.mirror,this.additiveColor)}renderLight(){}destroy(e=!1){var n;if(!this.destroyed){this.destroyed=!0,(n=this.parent)==null||n.removeChild(this);for(let s of this.children)s.parent=void 0,s.destroy(e)}}localToWorld(e){return this.pos.add(e.rotate(this.angle))}worldToLocal(e){return e.subtract(this.pos).rotate(-this.angle)}localToWorldVector(e){return e.rotate(this.angle)}worldToLocalVector(e){return e.rotate(-this.angle)}collideWithTile(e,n){return e>0}collideWithObject(e){return!0}getUp(e=1){return v().setAngle(this.angle,e)}getRight(e=1){return v().setAngle(this.angle+te/2,e)}getAliveTime(){return rt-this.spawnTime}getSpeed(){return this.velocity.length()}applyAcceleration(e){this.mass&&(this.velocity=this.velocity.add(e))}applyAngularAcceleration(e){this.mass&&(this.angleVelocity+=e)}applyForce(e){this.mass&&this.applyAcceleration(e.scale(1/this.mass))}getMirrorSign(){return this.mirror?-1:1}addChild(e,n=v(),s=0){return m(!this.destroyed,"cannot add child to destroyed object"),this.destroyed||(m(!e.parent&&!this.children.includes(e)),m(e instanceof t,"child must be an EngineObject"),m(e!==this,"cannot add self as child"),this.children.push(e),e.parent=this,e.localPos=n.copy(),e.localAngle=s,e.updateTransforms()),e}removeChild(e){m(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}isOverlappingObject(e){return this.isOverlapping(e.pos,e.size)}isOverlapping(e,n=v()){return Ei(this.pos,this.size,e,n)}setCollision(e=!0,n=!0,s=!0,i=!0){m(e||!n,"solid objects must be set to collide"),this.collideSolidObjects=e,this.isSolid=n,this.collideTiles=s,this.collideRaycast=i}toString(){let e="type = "+this.constructor.name;return(this.pos.x||this.pos.y)&&(e+=`
+pos = `+this.pos),(this.velocity.x||this.velocity.y)&&(e+=`
+velocity = `+this.velocity),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.angle&&(e+=`
+angle = `+this.angle.toFixed(3)),this.color&&(e+=`
+color = `+this.color),e}renderDebugInfo(){if(!Ue)return;let e=this.collideTiles||this.collideSolidObjects||this.isSolid;if(!e&&!this.parent)return;let n=v(re(this.size.x,.2),re(this.size.y,.2)),s=Y(this.collideTiles?1:0,this.collideSolidObjects?1:0,this.isSolid?1:0,.5);ke(this.pos,n,s,0,this.angle,e),this.parent&&ke(this.pos,n.scale(.8),Y(1,1,1,.5),0,this.angle),this.parent&&Rt(this.pos,this.parent.pos,Y(1,1,1,.5),.5)}},N=v(),wn=[];It=class t{constructor(e=v(),n=ro,s=wn[0],i=ao,r=co){this.pos=e.copy(),this.size=n.copy(),this.padding=i,this.textureInfo=s,this.bleed=r}offset(e){return new t(this.pos.add(e),this.size,this.textureInfo,this.padding,this.bleed)}frame(e){m(typeof e=="number");let n=this.size.x+this.padding*2,s=e*n;return m(s+this.size.x<=this.textureInfo.size.x,"frame extends beyond texture width!"),this.offset(new me(s))}setFullImage(e=this.textureInfo){return this.textureInfo=e,this.pos=new me,this.size=e.size.copy(),this.bleed=this.padding=0,this}tile(e){return ii(e,this.size,this.textureInfo,this.padding,this.bleed)}},Qt=class{constructor(e,n=!0,s=!1){this.image=e,this.size=e?v(e.width,e.height):v(),this.sizeInverse=e?v(1/e.width,1/e.height):v(),this.glTexture=void 0,this.wrap=s,n&&this.createWebGLTexture()}createWebGLTexture(){kh(this)}destroyWebGLTexture(){Ch(this)}hasWebGL(){return!!this.glTexture}setWrap(e=!0){this.wrap=e,Ol(this.glTexture,e)}};Df=0;Di=class{constructor(e){m(!!e,"tileInfo is required for ImageFont"),this.tileInfo=e.frame(0)}drawText(e,n,s=1,i,r,a,o){m(D(s)||typeof s=="number","size must be a vec2 or number"),typeof s=="number"?(m(s>0),s*=ee,s=new me(s,s)):s=s.scale(ee),this.drawTextScreen(e,Wn(n),s,i,r,a,o)}drawTextScreen(e,n,s,i=!0,r=Q,a=W,o){m(K(e),"text must be a string"),m(D(n),"pos must be a vec2"),m(D(s)||typeof s=="number","size must be a vec2 or number"),m(X(r),"color must be a color"),s=typeof s=="number"?new me(s,s):s;let c=new me,l=this.tileInfo,u=l.padding,h=l.size.x+u*2,d=l.size.y+u*2,f=l.textureInfo.size.x/h|0;(e+"").split(`
+`).forEach((p,y)=>{let x=i?(p.length-1)*s.x/2:0;for(let w=p.length;w--;){let A=p.charCodeAt(w),S=A<32||A>127?95:A-32,_=S%f,k=S/f|0;l.pos.x=_*h+u,l.pos.y=k*d+u,c.x=n.x+w*s.x-x|0,c.y=n.y+y*s.y|0,Be(c,s,l,r,0,!1,void 0,a,!0,o)}})}};Jt=v(),Ke=v(),ha=v(),Ct=v(),pa=0,Ii=!0,rs=!1,hn="mouse",ma=6,is=!0,Ae=0,ft=!$&&window.ontouchstart!==void 0;ie=[[]],_t=[],Pn=[],Zo=[],ds=new Lt,ht=[],Jn=[],Fi=[],ci=[],Ht=new Map,zs=[],fs=!0;Gi="http://www.w3.org/2000/svg";ve=new AudioContext,xs=44100;Vs=class{constructor(e,n,s=la,i=ua,r){var a;if(!(!nt||$)){if(m(!e||St(e)||K(e),"asset must be a file name or zzfx array"),m(n===void 0||O(n),"randomness must be a number"),m(n===void 0||n>=0&&n<=1,"randomness must be between 0 and 1"),m(O(s),"range must be a number"),m(O(i),"taper must be a number"),this.range=s,this.taper=i,this.randomness=n!=null?n:0,this.sampleRate=xs,this.loadedPercent=0,this.onloadCallback=r,St(e)){let o=e.slice(),c=n!=null?n:.05,l=1;this.randomness=(a=o[l])!=null?a:c,o[l]=0,this.sampleChannels=[ho(...o)],this.loadedPercent=1,r==null||r(this)}else if(typeof e=="string"){let o=e;this.loadSound(o)}}}play(e,n=1,s=1,i=1,r=!1,a=!1){if(m(!e||D(e),"pos must be a vec2"),m(O(n),"volume must be a number"),m(O(s),"pitch must be a number"),m(O(i),"randomnessScale must be a number"),!nt||$||!this.sampleChannels)return;let o;if(e){let u=this.range;if(u){let h=Ie.distanceSquared(e);if(h>u*u)return;n*=Ve(h**.5,u,u*this.taper)}o=Wn(e).x*2/q.width-1}let c=s+s*this.randomness*i*Se(-1,1),l=new Bi(this,n,c,o,r,a);return Ue&&ls&&e&&(Qe(e,.5,"#0ff",.5,!0),this.range&&(Qe(e,2*this.range,"#0ff",.5),Qe(e,2*this.range*this.taper,"#0ff",.5)),es("vol "+n.toFixed(2)+" pitch "+c.toFixed(2),e,.5,"#0ff",.5)),l}playMusic(e=1,n=!0,s=!1){return this.play(void 0,e,1,0,n,s)}playNote(e=0,n,s){m(O(e),"semitoneOffset must be a number");let i=_l(e,1);return this.play(n,s,i,0)}getDuration(){var e,n;return((n=(e=this.sampleChannels)==null?void 0:e[0])==null?void 0:n.length)/this.sampleRate||0}isLoaded(){return this.loadedPercent===1}async loadSound(e){var c;let n=await fetch(e);if(!n.ok)throw new Error(`Failed to load sound from ${e}: ${n.status} ${n.statusText}`);let s=await n.arrayBuffer(),i=await ve.decodeAudioData(s),r=i.numberOfChannels,a=1e5,o=[];for(let l=0;lsetTimeout(x,0));let f=le(d+a,h);for(;d=0,"Sound volume must be positive or zero"),m(s>=0,"Sound rate must be positive or zero"),m(O(i),"Sound pan must be a number"),this.sound=e,this.volume=n,this.rate=s,this.pan=i,this.loop=r,this.pausedTime=0,this.startTime=void 0,this.gainNode=void 0,this.source=void 0,this.onendedCallback=o=>{o===this.source&&(this.source=void 0)},a||this.start()}start(e=0){m(e>=0,"Sound start offset must be positive or zero"),this.isPlaying()&&this.stop(),this.gainNode=ve.createGain(),this.source=Ta(this.sound.sampleChannels,this.volume,this.rate,this.pan,this.loop,this.sound.sampleRate,this.gainNode,e,this.onendedCallback),this.source?(this.startTime=ve.currentTime-e,this.pausedTime=void 0):(this.startTime=void 0,this.pausedTime=0)}setVolume(e){m(e>=0,"Sound volume must be positive or zero"),this.volume=e,this.gainNode&&(this.gainNode.gain.value=e)}stop(e=0){if(m(e>=0,"Sound fade time must be positive or zero"),this.isPlaying())if(e){let n=ve.currentTime,s=n+e;this.gainNode.gain.cancelScheduledValues(n),this.gainNode.gain.setValueAtTime(this.volume,n),this.gainNode.gain.linearRampToValueAtTime(0,s),this.source.stop(s)}else this.source.stop();this.pausedTime=0,this.source=void 0,this.startTime=void 0}pause(){this.isPaused()||(this.pausedTime=this.getCurrentTime(),this.source.stop(),this.source=void 0,this.startTime=void 0)}resume(){this.isPaused()&&this.start(this.pausedTime)}isPlaying(){return!!this.source}isPaused(){return!this.isPlaying()}getCurrentTime(){if(!this.isPlaying())return this.pausedTime;let e=this.getDuration();return e?dt(ve.currentTime-this.startTime,e):0}getDuration(){return this.rate?this.sound.getDuration()/this.rate:0}getSource(){return this.source}};bn=[];Bn=class{constructor(e,n=0,s=!1,i=new Me){this.tile=e,this.direction=n,this.mirror=s,this.color=i.copy()}clear(){this.tile=this.direction=0,this.mirror=!1,this.color=new Me}},Ji=class extends Kt{constructor(e,n,s=0,i=0,r=v(512),a=!0){var o;m(D(r),"canvasSize must be a Vector2"),super(e,n,void 0,s,Q,i),this.canvas=$?void 0:new OffscreenCanvas(r.x,r.y),this.context=(o=this.canvas)==null?void 0:o.getContext("2d"),this.textureInfo=new Qt(this.canvas,a),this.mass=0}destroy(){this.destroyed||(this.textureInfo.destroyWebGLTexture(),super.destroy())}render(){this.draw(this.pos,this.size,this.color,this.angle,this.mirror,this.additiveColor)}draw(e,n,s=Q,i=0,r=!1,a,o=!1,c){let l=new It().setFullImage(this.textureInfo),u=this.hasWebGL();Be(e,n,l,s,i,r,a,u,o,c)}updateWebGL(){this.textureInfo.createWebGLTexture()}hasWebGL(){return W&&this.textureInfo.hasWebGL()}},Ws=class extends Ji{constructor(e,n,s=ii(),i=0,r=!0){let a=s?n.multiply(s.size):n;if(super(e,n,0,i,a,r),this.tileInfo=void 0,this.data=[],this.isUsingWebGL=!1,$){this.render=()=>{},this.redraw=()=>{},this.redrawStart=()=>{},this.redrawEnd=()=>{},this.drawTileData=()=>{},this.redrawTileData=()=>{},this.drawLayerTile=()=>{},this.drawLayerRect=()=>{},this.drawTile=()=>{},this.drawRect=()=>{},this.clearLayerRect=()=>{};return}s&&(this.tileInfo=s.frame(0),this.tileInfo.bleed=0);for(let o=this.size.area();o--;)this.data.push(new Bn)}setData(e,n,s=!1){if(e=e.floor(),m(D(e),"layerPos must be a Vector2"),m(n instanceof Bn,"data must be a TileLayerData"),!e.arrayCheck(this.size)||(this.data[(e.y|0)*this.size.x+(e.x|0)]=n,!s))return;Oe===this.context?this.drawTileData(e):this.redrawTileData(e)}clearData(e,n=!1){this.setData(e,new Bn,n)}getData(e){return m(D(e),"layerPos must be a Vector2"),e.arrayCheck(this.size)?this.data[(e.y|0)*this.size.x+(e.x|0)]:void 0}update(){!W&&this.isUsingWebGL&&(this.isUsingWebGL=!1,this.redraw())}render(){m(Oe!==this.context,"must call redrawEnd() after drawing tiles!");let e=this.drawSize||this.size,n=this.pos.add(e.scale(.5));this.draw(n,this.size,this.color,this.angle,this.mirror,this.additiveColor)}onRedraw(){}redraw(){this.redrawStart(!0);for(let e=this.size.x;e--;)for(let n=this.size.y;n--;)this.drawTileData(v(e,n),!1);this.isUsingWebGL&&Fe(),this.onRedraw(),this.redrawEnd()}redrawStart(e=!1){var s,i;if(!this.context)return;m(Oe!==this.context),this.savedRenderSettings=[Oe,N,Ie,ee,mn],Oe=this.context;let n=(i=(s=this.tileInfo)==null?void 0:s.size)!=null?i:v(1);N=this.size.multiply(n),mn=wt,Ie=this.size.multiply(n).scale(.5),ee=1,this.isUsingWebGL=this.hasWebGL(),this.isUsingWebGL?Ps(this.textureInfo.glTexture,e):(this.context.imageSmoothingEnabled=!jn,e&&(this.canvas.width=N.x,this.canvas.height=N.y))}redrawEnd(){this.context&&(m(Oe===this.context),this.isUsingWebGL&&Ps(),[Oe,N,Ie,ee,mn]=this.savedRenderSettings)}drawTileData(e,n=!0){var o,c;if(!this.context)return;m(Oe===this.context,"must call redrawStart() before drawing tiles");let s=(c=(o=this.tileInfo)==null?void 0:o.size)!=null?c:v(1),i=e.multiply(s);n&&this.clearLayerRect(i,s);let r=this.getData(e);if(!r||!r.tile)return;let a=this.tileInfo&&this.tileInfo.tile(r.tile);this.drawLayerTile(i,s,a,r.color,r.direction*te/2,r.mirror)}redrawTileData(e,n=!0){this.context&&(m(Oe!==this.context,"redrawStart() should not be active when calling redrawTileData(), instead use drawTileData()"),this.redrawStart(),this.drawTileData(e,n),this.redrawEnd())}drawLayerTile(e,n=v(1),s,i=Q,r=0,a,o){let c=e.add(n.scale(.5));Be(c,n,s,i,r,a,o,this.isUsingWebGL)}drawLayerRect(e,n,s,i=0){this.drawLayerTile(e,n,void 0,s,i)}drawTile(e,n=v(1),s,i=new Me,r=0,a=!1){e=e.subtract(this.pos).multiply(this.tileInfo.size),n=n.multiply(this.tileInfo.size),e.y=this.canvas.height-e.y;let o=N;N=v(this.canvas.width,this.canvas.height);let c=this.hasWebGL();c&&Ps(this.textureInfo.glTexture);let l=c?void 0:this.context;Be(e,n,s,i,r,a,void 0,c,!0,l),c&&Ps(),N=o}drawRect(e,n,s,i){this.drawTile(e,n,void 0,s,i)}clearLayerRect(e,n){m(Oe===this.context,"must call redrawStart() before clearing tiles");let s=e.x,i=this.canvas.height-e.y-n.y;this.hasWebGL()?Gl(s,i,n.x,n.y):this.context.clearRect(s,i,n.x,n.y)}},qs=class extends Ws{constructor(e,n,s=ii(),i=0,r=!0){super(e,n.floor(),s,i,r),this.collisionData=[],this.initCollision(this.size),bn.push(this),this.isSolid=!0}destroy(){if(this.destroyed)return;let e=bn.indexOf(this);m(e>=0,"tile collision layer not found in array"),e>=0&&bn.splice(e,1),super.destroy()}initCollision(e){m(D(e),"size must be a Vector2"),this.size=e.floor(),this.collisionData=[],this.collisionData.length=e.area(),this.collisionData.fill(0)}setCollisionData(e,n=1){m(D(e),"layerPos must be a Vector2");let s=(e.y|0)*this.size.x+(e.x|0);e.arrayCheck(this.size)&&(this.collisionData[s]=n)}clearCollisionData(e){this.setCollisionData(e,0)}getCollisionData(e){m(D(e),"layerPos must be a Vector2");let n=(e.y|0)*this.size.x+(e.x|0);return e.arrayCheck(this.size)?this.collisionData[n]:0}collisionTest(e,n=new me,s){m(D(e)&&D(n),"pos and size must be Vector2s"),m(!s||typeof s=="function"||s instanceof Kt,"callbackObject must be a function or EngineObject");let i=s?typeof s=="function"?(d,f)=>s(d,f):(d,f)=>s.collideWithTile(d,f):()=>!0,r=e.x-this.pos.x,a=e.y-this.pos.y;if(r+n.x/2<0||r-n.x/2>this.size.x||a+n.y/2<0||a-n.y/2>this.size.y)return!1;let o=re(r-n.x/2|0,0),c=re(a-n.y/2|0,0),l=le(re(r+n.x/2,o+1),this.size.x),u=le(re(a+n.y/2,c+1),this.size.y),h=new me;for(let d=c;ds(l,u):(l,u)=>s.collideWithTile(l,u):l=>l>0,a=l=>{let u=this.getCollisionData(o.set(l.x-this.pos.x,l.y-this.pos.y));return u&&r(u,l)},o=new me,c=il(e,n,a,i);if(xt&&c){let l=c.floor().add(v(.5));ke(l,v(1),"#f008"),Rt(e,n,"#00f",.02),Rt(e,c,"#f00",.02),qr(c,"#0f0"),i&&Rt(c,c.add(i),"#ff0",.02)}return c}},ur=class extends Kt{constructor(e,n,s=0,i=0,r=100,a=te,o,c=Q,l=Q,u=Sn,h=Sn,d=.5,f=.1,p=1,y=.1,x=.05,w=1,A=1,S=0,_=te,k=.1,C=.2,L=!1,V=!1,ce=!0,ne=V?1e9:0,T=!1){super(e,v(),o,n,void 0,ne),this.emitCircle=typeof s=="number",this.emitSize=typeof s=="number"?v(s):s.copy(),this.emitTime=i,this.emitRate=r,this.emitConeAngle=a,this.colorStartA=c.copy(),this.colorStartB=l.copy(),this.colorEndA=u.copy(),this.colorEndB=h.copy(),this.randomColorLinear=ce,this.particleTime=d,this.sizeStart=f,this.sizeEnd=p,this.speed=y,this.angleSpeed=x,this.damping=w,this.angleDamping=A,this.gravityScale=S,this.particleConeAngle=_,this.fadeRate=k,this.randomness=C,this.collideTiles=L,this.additive=V,this.localSpace=T,this.trailScale=0,this.particleCreateCallback=void 0,this.particleDestroyCallback=void 0,this.particleCollideCallback=void 0,this.velocityInheritance=0,this.emitTimeBuffer=0,this.particles=[],this.previousAngle=this.angle,this.previousPos=this.pos.copy()}update(){if(m(this.angleDamping>=0&&this.angleDamping<=1),m(this.damping>=0&&this.damping<=1),this.velocityInheritance){let s=this.velocityInheritance;this.velocity.x=s*(this.pos.x-this.previousPos.x),this.velocity.y=s*(this.pos.y-this.previousPos.y),this.angleVelocity=s*(this.angle-this.previousAngle),this.previousAngle=this.angle,this.previousPos.x=this.pos.x,this.previousPos.y=this.pos.y}if(this.isActive()){if(this.emitRate&&Ri){let s=1/this.emitRate/Ri;for(this.emitTimeBuffer+=Vr;this.emitTimeBuffer>0;this.emitTimeBuffer-=s)this.emitParticle()}}else this.particles.length===0&&this.destroy(!0);let e=this.particles,n=0;for(let s=0;sA+A*Se(s,-s),r=i(this.particleTime),a=i(this.sizeStart),o=i(this.sizeEnd),c=i(this.speed),l=i(this.angleSpeed)*rl(),u=Se(this.emitConeAngle,-this.emitConeAngle),h=ir(this.colorStartA,this.colorStartB,this.randomColorLinear),d=ir(this.colorEndA,this.colorEndB,this.randomColorLinear),f=this.localSpace?u:this.angle+u,p=v(c*fe(f),c*ye(f)),y=l;!this.localSpace&&this.velocityInheritance>0&&(p.x+=this.velocity.x,p.y+=this.velocity.y,y+=this.angleVelocity);let x=new Ni(this,e,n,h,d,r,a,o,p,y);return this.particles.push(x),(w=this.particleCreateCallback)==null||w.call(this,x),x}updatePhysics(){}render(){for(let e of this.particles)e.render()}isActive(){return!this.emitTime||this.getAliveTime()0&&(this.destroyed=!1,this.emitTime=-1))}},wh=new me,Ni=class{constructor(e,n,s,i,r,a,o,c,l=v(),u=0){this.emitter=e,this.pos=n,this.angle=s,this.size=v(o),this.color=i.copy(),this.colorStart=i,this.colorEnd=r,this.lifeTime=a,this.sizeStart=o,this.sizeEnd=c,this.velocity=l,this.angleVelocity=u,this.spawnTime=rt,this.mirror=ol(),this.groundObject=void 0,this.destroyed=!1,this.tileInfo=e.tileInfo}update(){let e=this.emitter,n=e.damping,s=e.angleDamping,i=e.restitution,r=e.friction,a=e.gravityScale,o=e.collideTiles,c=e.particleCollideCallback;if(this.lifeTime>0&&rt-this.spawnTime>this.lifeTime){this.destroy();return}let l=this.pos.copy();if(this.velocity.x*=n,this.velocity.y*=n,this.pos.x+=this.velocity.x+=Ze.x*a,this.pos.y+=this.velocity.y+=Ze.y*a,this.angle+=this.angleVelocity*=s,!lo||!o)return;let u=this.velocity.lengthSquared();if(u>Wt*Wt){let d=Wt/u**.5;this.velocity.x*=d,this.velocity.y*=d}this.groundObject=void 0;let h=c?d=>{let f=ji(d);return f&&c(this,f,d)}:d=>ji(d)>0;if(h(this.pos)){let d=dn(this.pos);if(!h(l)){let f=h(v(this.pos.x,l.y)),p=h(v(l.x,this.pos.y)),y=re(i,d.restitution),x=re(r,d.friction);f&&(this.pos.x=l.x,this.velocity.x*=-y,this.velocity.y*=x),(p||!f)&&((this.velocity.y<0&&Ze.y<0||this.velocity.y>0&&Ze.y>0)&&(this.groundObject=d),this.pos.y=l.y,this.velocity.y*=-y,this.velocity.x*=x),bt&&ke(this.pos,this.size,"#f00")}}}destroy(){let e=this.emitter.particleDestroyCallback,n=this.colorEnd;this.color.set(n.r,n.g,n.b,n.a),this.size.set(this.sizeEnd,this.sizeEnd),this.destroyed=!0,e==null||e(this)}render(){let e=this.emitter,n=e.localSpace,s=e.additive,i=e.trailScale,r=e.fadeRate/2,a=this.lifeTime>0?le((rt-this.spawnTime)/this.lifeTime,1):1,o=1-a,c=o*this.sizeStart+a*this.sizeEnd,l=v(c),u=a1-r?(1-a)/r:1;this.color.r=o*this.colorStart.r+a*this.colorEnd.r,this.color.g=o*this.colorStart.g+a*this.colorEnd.g,this.color.b=o*this.colorStart.b+a*this.colorEnd.b,this.color.a=(o*this.colorStart.a+a*this.colorEnd.a)*u;let h=wh.set(this.pos.x,this.pos.y),d=this.angle;if(n){let f=e.angle,p=ye(-f),y=fe(-f);h.set(e.pos.x+h.x*p-h.y*y,e.pos.y+h.x*y+h.y*p),d+=f}if(s&&js(),i){let f=n?this.velocity.rotate(e.angle):this.velocity,p=f.length();if(p){let y=p*i;l.y=re(l.x,y),d=Hr(f.x,f.y),Be(h,l,this.tileInfo,this.color,d,this.mirror)}}else Be(h,l,this.tileInfo,this.color,d,this.mirror);s&&js(!1),In&&ke(h,l,"#f005",0,d)}},Aa=!0,pr=!0,Wi=5e5,Ca=11,Rl=Ca*4,Th=Wi/Rl|0,po=3,Pl=po*4,cs=Wi/Pl|0;Rn=!1,qi=5,os=.5,Hi=v(640,80),Oa=!1,Xs={},wi=[];Yi=class{constructor(e,n,s="",i="\u{1F3C6}",r){m(e>=0&&!Xs[e]),this.id=e,this.name=n,this.description=s,this.icon=i,this.unlocked=!1,this.image=void 0,r&&((this.image=new Image).src=r),Xs[e]=this}unlock(){Oa||this.unlocked||(m($i,"save name must be set"),this.unlocked=!0,Da(),wi.push(this))}render(e=0){let n=ge,s=le(Hi.x,q.width),i=Hi.y,r=q.width-s,a=-i*e,o=Vt(0,0,.9);n.save(),n.beginPath(),n.fillStyle=o.toString(),n.strokeStyle=he.toString(),n.lineWidth=3,n.rect(r,a,s,i),n.fill(),n.stroke(),n.clip();let c=v(.1,.05).scale(i),l=i-2*c.x;this.renderIcon(v(r+c.x+l/2,a+i/2),l);let u=i*.5,h=i*.3,d=v(r+l+2*c.x,a+c.y*2+u/2),f=s-l-3*c.x;gn(this.name,d,u,he,0,void 0,"left",void 0,void 0,f),d.y=a+i-c.y*2-h/2,gn(this.description,d,h,he,0,void 0,"left",void 0,void 0,f),n.restore()}renderIcon(e,n){this.image?ge.drawImage(this.image,e.x-n/2,e.y-n/2,n,n):gn(this.icon,e,n*.7,he)}};gr=class extends Yi{constructor(e,n,s,i,r){super(e,n,s,i,r)}unlock(){super.unlock(),Ks&&Ks.unlockMedal(this.id)}},br=class{constructor(e,n,s){var c,l,u;m(!Ks,"there can only be one newgrounds object"),m(!n||s,"must provide cryptojs if there is a cipher"),Ks=this,this.app_id=e,this.cipher=n,this.cryptoJS=s,this.host=location?location.hostname:"";let i=new URL(location.href);if(this.session_id=i.searchParams.get("ngio_session_id"),!this.session_id)return;let r=this.call("Medal.getList");if(!r||!r.result||r.result.error){Rn&&Ce("Newgrounds session unavailable; skipping plugin init"),this.medals=[],this.scoreboards=[];return}this.medals=((c=r.result.data)==null?void 0:c.medals)||[],Rn&&Ce(this.medals);for(let h of this.medals){let d=Xs[h.id];d&&(d.image=new Image,d.image.src=h.icon,d.name=h.name,d.description=h.description,d.unlocked=h.unlocked,d.difficulty=h.difficulty,d.value=h.value,d.value&&(d.description=d.description+` (${d.value})`))}let a=this.call("ScoreBoard.getBoards");this.scoreboards=((u=(l=a==null?void 0:a.result)==null?void 0:l.data)==null?void 0:u.scoreboards)||[],Rn&&Ce(this.scoreboards);let o=60*1e3;setInterval(()=>this.call("Gateway.ping",0,!0),o)}unlockMedal(e){return this.call("Medal.unlock",{id:e},!0)}postScore(e,n){return this.call("ScoreBoard.postScore",{id:e,value:n},!0)}getScores(e,n,s=0,i=0,r=10){return this.call("ScoreBoard.getScores",{id:e,user:n,social:s,skip:i,limit:r})}logView(){return this.call("App.logView",{host:this.host},!0)}call(e,n,s=!1){let i={component:e,parameters:n};if(this.cipher){let l=this.cryptoJS,u=l.enc.Base64.parse(this.cipher),h=l.lib.WordArray.random(16),d=l.AES.encrypt(JSON.stringify(i),u,{iv:h});i.secure=l.enc.Base64.stringify(h.concat(d.ciphertext)),i.parameters=0}let r={app_id:this.app_id,session_id:this.session_id,call:i},a=new FormData;a.append("input",JSON.stringify(r));let o=new XMLHttpRequest;o.open("POST","https://newgrounds.io/gateway_v3.php",!Rn&&s);try{o.send(a)}catch(l){Rn&&Ce("newgrounds call failed",l);return}return Rn&&Ce(o.responseText),o.responseText&&JSON.parse(o.responseText)}},xr=class{constructor(e,n=!1,s=!1){m(!Je,"Post process already initialized"),m(!(n&&s),"Post process cannot both include main canvas and use feedback texture"),Je=this,e||(e="void mainImage(out vec4 c,vec2 p){c=texture(iChannel0,p/iResolution.xy);}"),this.shader=void 0,this.texture=void 0,this.vao=void 0,i(),zn(void 0,o,r,a);function i(){if($)return;if(!W){console.warn("PostProcessPlugin: WebGL not enabled!");return}Je.texture=mo(),Je.shader=ms(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D iChannel0;uniform vec3 iResolution;uniform float iTime;out vec4 c;
+`+e+`
+void main(){mainImage(c,gl_FragCoord.xy);c.a=1.;}`),Je.vao=g.createVertexArray(),g.bindVertexArray(Je.vao),g.bindBuffer(g.ARRAY_BUFFER,as);let c=8,l=g.getAttribLocation(Je.shader,"p");g.enableVertexAttribArray(l),g.vertexAttribPointer(l,2,g.FLOAT,!1,c,0)}function r(){Je.shader=void 0,Je.texture=void 0,Ce("PostProcessPlugin: WebGL context lost")}function a(){i(),Ce("PostProcessPlugin: WebGL context restored")}function o(){if($||!W)return;Fe(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.useProgram(Je.shader),g.bindVertexArray(Je.vao),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!0),g.disable(g.BLEND),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,Je.texture),n?($t.width=N.x,$t.height=N.y,Ra(fn),fn.drawImage(q,0,0),q.width|=0,g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,$t)):s||g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,ue);let c=l=>g.getUniformLocation(Je.shader,l);g.uniform1i(c("iChannel0"),0),g.uniform1f(c("iTime"),rt),g.uniform3f(c("iResolution"),q.width,q.height,1),g.drawArrays(g.TRIANGLE_STRIP,0,4),s&&g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,ue),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!1),$s(!0)}}},Sr=class{constructor(e,n){m(!Z,"LightSystemPlugin already initialized"),m(!Je,"LightSystemPlugin must be created before PostProcessPlugin"),Z=this,this.enabled=!0,this.ambientColor=(n||he).copy(),this.textureSize=e?e.copy():void 0,this.texture=void 0,this.lightShader=void 0,this.compositeShader=void 0,this.lightVAO=void 0,this.compositeVAO=void 0,s(),zn(void 0,i,r,a);function s(){if($)return;if(!W){console.warn("LightSystemPlugin: WebGL not enabled!");return}Z.textureSize||(Z.textureSize=N.copy()),Z.texture=g.createTexture(),g.bindTexture(g.TEXTURE_2D,Z.texture),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,Z.textureSize.x,Z.textureSize.y,0,g.RGBA,g.UNSIGNED_BYTE,null),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,g.CLAMP_TO_EDGE),Z.lightShader=ms(`#version 300 es
+precision highp float;uniform mat4 m;uniform vec2 lightPos;uniform float radius;in vec2 g;out vec2 vWorldPos;void main(){vec2 worldP=lightPos+(g-.5)*2.*radius;gl_Position=m*vec4(worldP,1,1);vWorldPos=worldP;}`,`#version 300 es
+precision highp float;uniform vec2 lightPos;uniform float radius;uniform float fadeRange;uniform vec4 color;in vec2 vWorldPos;out vec4 c;void main(){float dist=distance(vWorldPos,lightPos);float t=clamp((radius-dist)/max(fadeRange,1e-6),0.,1.);c=vec4(color.rgb*t*color.a,1.);}`),Z.compositeShader=ms(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D s;uniform vec3 iResolution;out vec4 c;void main(){vec2 uv=gl_FragCoord.xy/iResolution.xy;c=vec4(texture(s,uv).rgb,1.);}`),Z.lightVAO=g.createVertexArray(),g.bindVertexArray(Z.lightVAO),g.bindBuffer(g.ARRAY_BUFFER,as);let o=g.getAttribLocation(Z.lightShader,"g");g.enableVertexAttribArray(o),g.vertexAttribPointer(o,2,g.FLOAT,!1,8,0),Z.compositeVAO=g.createVertexArray(),g.bindVertexArray(Z.compositeVAO),g.bindBuffer(g.ARRAY_BUFFER,as);let c=g.getAttribLocation(Z.compositeShader,"p");g.enableVertexAttribArray(c),g.vertexAttribPointer(c,2,g.FLOAT,!1,8,0)}function i(){if($||!W||!Z.enabled||!Z.texture)return;Fe();let o=Hn,c=Z.ambientColor;g.bindFramebuffer(g.FRAMEBUFFER,ka),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,Z.texture,0),g.viewport(0,0,Z.textureSize.x,Z.textureSize.y),g.clearColor(c.r,c.g,c.b,c.a),g.clear(g.COLOR_BUFFER_BIT),js(),g.enable(g.BLEND),g.blendFunc(g.ONE,g.ONE);for(let u of _e)u.destroyed||u.renderLight();Fe(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,N.x,N.y),g.useProgram(Z.compositeShader),g.bindVertexArray(Z.compositeVAO),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,Z.texture);let l=Z.compositeShader;g.uniform1i(g.getUniformLocation(l,"s"),0),g.uniform3f(g.getUniformLocation(l,"iResolution"),q.width,q.height,1),g.blendFunc(g.DST_COLOR,g.ZERO),g.drawArrays(g.TRIANGLE_STRIP,0,4),at&&g.bindTexture(g.TEXTURE_2D,at),js(o),$s(!0)}function r(){Z.texture=void 0,Z.lightShader=void 0,Z.compositeShader=void 0,Z.lightVAO=void 0,Z.compositeVAO=void 0,Ce("LightSystemPlugin: WebGL context lost")}function a(){s(),Ce("LightSystemPlugin: WebGL context restored")}}drawLight(e){if($||!W||!this.lightShader)return;Fe(),g.useProgram(this.lightShader),g.bindVertexArray(this.lightVAO);let n=v(2*ee).divide(N),s=Ie.rotate(-ae),i=v(-1).subtract(s.multiply(n)),r=ye(ae),a=fe(ae),o=[n.x*r,n.y*a,0,0,-n.x*a,n.y*r,0,0,1,1,1,0,i.x,i.y,0,1],c=this.lightShader;g.uniformMatrix4fv(g.getUniformLocation(c,"m"),!1,o),g.uniform2f(g.getUniformLocation(c,"lightPos"),e.pos.x,e.pos.y),g.uniform1f(g.getUniformLocation(c,"radius"),e.radius),g.uniform1f(g.getUniformLocation(c,"fadeRange"),e.fadeRange);let l=e.color;g.uniform4f(g.getUniformLocation(c,"color"),l.r,l.g,l.b,l.a),g.drawArrays(g.TRIANGLE_STRIP,0,4),$s(!0)}},vr=class extends Kt{constructor(e,n,s,i){super(e,v(1),void 0,0,s),m(O(n)&&n>=0,"Light radius must be a non-negative number"),m(i===void 0||O(i)&&i>=0,"Light fadeRange must be a non-negative number when provided"),this.radius=n,this.fadeRange=i===void 0?n:i}render(){}renderLight(){Z&&Z.drawLight(this)}},wr=class extends Vs{constructor(e){super(void 0),!(!nt||$)&&(this.randomness=0,this.sampleChannels=Bl(...e),this.sampleRate=xs)}playMusic(e=1,n=!0){return super.play(void 0,e,1,0,n)}};Ia=0;Tr=class{constructor(e=ge){m(!E,"UI system already initialized"),E=this,this.activateOnPress=!1,this.defaultColor=Q,this.defaultLineColor=he,this.defaultTextColor=he,this.defaultButtonColor=Vt(0,0,.7),this.defaultHoverColor=Vt(0,0,.9),this.defaultDisabledColor=Vt(0,0,.3),this.defaultGradientColor=void 0,this.defaultLineWidth=4,this.defaultCornerRadius=0,this.defaultTextFitScale=.8,this.defaultFont=ei,this.defaultSoundPress=void 0,this.defaultSoundRelease=void 0,this.defaultSoundClick=void 0,this.defaultShadowColor=wt,this.defaultShadowBlur=5,this.defaultShadowOffset=v(5),this.nativeHeight=0,this.navigationObject=void 0,this.navigationTimer=new Lt(void 0,!0),this.navigationDelay=.2,this.navigationDirection=1,this.navigationMode=!1,this.uiObjects=[],this.uiContext=e,this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.confirmDialog=void 0,this._keyInputObject=void 0,this._onKeyDown=r=>{var a;return(a=this._keyInputObject)==null?void 0:a.onKeyDown(r)},zn(s,i);function n(r){let a,o;r.parent?(a=r.parent.nativePos,o=r.parent.size):(a=E.screenToNative(N.scale(.5)),o=E.nativeHeight?v(N.x*E.nativeHeight/N.y,E.nativeHeight):N);let c=r.anchor;r.nativePos=a.add(o.multiply(c).scale(.5)).subtract(r.size.multiply(c).scale(.5)).add(r.localPos)}function s(){E.activeObject&&!E.activeObject.visible&&(E.activeObject=void 0),E.lastHoverObject=E.hoverObject,E.hoverObject=void 0,Js(0)&&(E.navigationMode=!1,E.navigationObject=void 0),E.keyInputObject&&(E.activeObject=E.keyInputObject,E.hoverObject=E.keyInputObject,E.navigationMode=!1,E.navigationObject=void 0);let r=E.getNavigableObjects();if(!r.length)E.navigationObject=void 0;else if(!E.keyInputObject){if(r.includes(E.navigationObject)||(E.navigationObject=void 0),ft||E.navigationMode&&!E.navigationObject&&(E.navigationObject=r.find(o=>o.navigationAutoSelect)),!E.navigationTimer.active()){let o=ut(E.getNavigationDirection());if(o){let c;if(E.navigationObject){let l=r.indexOf(E.navigationObject),u=dt(l+o,r.length);c=r[u]}else if(c=r.find(l=>l.navigationAutoSelect),!c){let l=o>0?0:r.length-1;c=r[l]}E.navigationObject!==c&&(E.navigationMode=!0,E.hoverObject=void 0,E.navigationObject=c,E.navigationTimer.set(E.navigationDelay),c.soundPress&&c.soundPress.play())}}E.navigationObject&&E.getNavigationWasPressed()&&E.navigationObject.navigatePressed()}for(let o=E.uiObjects.length;o--;){let c=E.uiObjects[o];c.parent||a(c)}E.uiObjects=E.uiObjects.filter(o=>!o.destroyed);function a(o){if(!(o.destroyed||!o.visible)){n(o);for(let c=o.children.length;c--;){let l=o.children[c];l&&a(l)}o.destroyed||o.update()}}}function i(){let r=E.uiContext;if(r.save(),E.nativeHeight){let o=N.y/E.nativeHeight;r.translate(-o*N.x/2,0),r.scale(o,o),r.translate(N.x/2/o,0)}function a(o){if(o.visible){n(o),o.render();for(let c of o.children)a(c)}}if(E.uiObjects.forEach(o=>o.parent||a(o)),Ia>0){let o=function(c,l=!0){l&&(l=!!c.visible),n(c),c.renderDebug(l);for(let u of c.children)o(u,l)};E.uiObjects.forEach(c=>c.parent||o(c))}r.restore()}}drawRect(e,n,s=Q,i=0,r=he,a=0,o,c=he,l=0,u=v()){m(D(e),"pos must be a vec2"),m(D(n),"size must be a vec2"),m(X(s),"color must be a color"),m(O(i),"lineWidth must be a number"),m(X(r),"lineColor must be a color"),m(O(a),"cornerRadius must be a number");let h=E.uiContext;if(o){let d=h.createLinearGradient(e.x,e.y-n.y/2,e.x,e.y+n.y/2),f=s.toString();d.addColorStop(0,f),d.addColorStop(.5,o.toString()),d.addColorStop(1,f),h.fillStyle=d}else h.fillStyle=s.toString();(l||u.x||u.y)&&c.a>0&&(h.shadowColor=c.toString(),h.shadowBlur=l,h.shadowOffsetX=u.x,h.shadowOffsetY=u.y),h.beginPath(),a&&h.roundRect?h.roundRect(e.x-n.x/2,e.y-n.y/2,n.x,n.y,a):h.rect(e.x-n.x/2,e.y-n.y/2,n.x,n.y),h.fill(),h.shadowColor="#0000",i&&r.a>0&&(h.strokeStyle=r.toString(),h.lineWidth=i,h.stroke())}drawLine(e,n,s=E.defaultLineWidth,i=E.defaultLineColor){m(D(e),"posA must be a vec2"),m(D(n),"posB must be a vec2"),m(O(s),"lineWidth must be a number"),m(X(i),"lineColor must be a color");let r=E.uiContext;r.strokeStyle=i.toString(),r.lineWidth=s,r.beginPath(),r.lineTo(e.x,e.y),r.lineTo(n.x,n.y),r.stroke()}drawTile(e,n,s,i=E.defaultColor,r=0,a=!1,o=he,c=0,l=v()){let u=E.uiContext;(c||l.x||l.y)&&o.a>0&&(u.shadowColor=o.toString(),u.shadowBlur=c,u.shadowOffsetX=l.x,u.shadowOffsetY=l.y),Be(e,n,s,i,r,a,wt,!1,!0,u),u.shadowColor="#0000"}drawText(e,n,s,i=E.defaultColor,r=E.defaultLineWidth,a=E.defaultLineColor,o="center",c=E.defaultFont,l="",u=!0,h=void 0,d=he,f=0,p=v()){let y=E.uiContext;d.a>0&&(h&&gn(e,n.add(h),s.y,d,r,a,o,c,l,u?s.x:void 0,0,y),(f||p.x||p.y)&&(y.shadowColor=d.toString(),y.shadowBlur=f,y.shadowOffsetX=p.x,y.shadowOffsetY=p.y)),gn(e,n,s.y,i,r,a,o,c,l,u?s.x:void 0,0,y),y.shadowColor="#0000"}setupDragAndDrop(e,n,s,i){if(this._dragListeners)for(let[a,o]of this._dragListeners)document.removeEventListener(a,o);this._dragListeners=[];let r=(a,o)=>{let c=l=>{l.preventDefault(),a&&a(l)};document.addEventListener(o,c),this._dragListeners.push([o,c])};r(e,"drop"),r(n,"dragenter"),r(s,"dragleave"),r(i,"dragover")}screenToNative(e){if(!E.nativeHeight)return e;let n=N.y/E.nativeHeight,s=1/n,i=e.copy();return i.x+=n*N.x/2,i.x*=s,i.y*=s,i.x-=s*N.x/2,i}get keyInputObject(){return this._keyInputObject}set keyInputObject(e){let n=!!this._keyInputObject;this._keyInputObject=e,!n&&e?document.addEventListener("keydown",this._onKeyDown):n&&!e&&document.removeEventListener("keydown",this._onKeyDown)}destroyObjects(){for(let e of this.uiObjects)e.parent||e.destroy();this.uiObjects=this.uiObjects.filter(e=>!e.destroyed),this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.keyInputObject=void 0}getNavigableObjects(){function e(s){if(!(!s.visible||s.disabled)){s.isInteractive()&&s.navigationIndex!==void 0&&n.push(s);for(let i=s.children.length;i--;)e(s.children[i])}}let n=[];for(let s=E.uiObjects.length;s--;){let i=E.uiObjects[s];E.confirmDialog&&i!==E.confirmDialog||i.parent||e(i)}return n.sort((s,i)=>s.navigationIndex-i.navigationIndex),n}getNavigationDirection(){let e=E.navigationDirection===1,n=E.navigationDirection===2;if(rs){let l=Ns(0,Ae),u=cr(Ae);return n?-(l.y||u.y)||l.x||u.x:e?-(l.y||u.y):l.x||u.x}let s="ArrowUp",i="ArrowDown",r="ArrowLeft",a="ArrowRight";if(n)return Ge(s)||Ge(r)?-1:Ge(i)||Ge(a)?1:0;let o=e?s:r,c=e?i:a;return Ge(o)?-1:Ge(c)?1:0}getNavigationOtherDirection(){if(E.navigationDirection===2)return 0;let e=E.navigationDirection===1;if(rs){let i=Ns(0,Ae),r=cr(Ae);return e?i.x||r.x:i.y||r.y}let n=e?"ArrowLeft":"ArrowUp",s=e?"ArrowRight":"ArrowDown";return Ge(n)?-1:Ge(s)?1:0}getNavigationWasPressed(){return rs?ba(0,Ae):Ne("Space")||Ne("Enter")}showConfirmDialog(e="Are you sure?",n,s,i=v(500,250),r="Escape"){m(!E.confirmDialog);let a=E.navigationDirection;E.navigationDirection=2;let o=new pt(v(),i);E.confirmDialog=o,o.onRender=()=>{let f=Vt(0,0,0,.7);E.drawRect(v(),v(1e9),f)},o.onUpdate=()=>{Ne(r)&&d()},o.isMouseOverlapping=()=>!0;let c=50,l=new Xi(v(0,-50),v(i.x-c,70),e);o.addChild(l);let u=new Qs(v(-80,50),v(120,70),"Yes");u.textHeight=40,u.navigationIndex=1,u.hoverColor=Vt(0,1,.5),u.onClick=()=>{d(),n&&n()},o.addChild(u);let h=new Qs(v(80,50),v(120,70),"No");h.textHeight=40,h.navigationIndex=2,h.navigationAutoSelect=!0,h.onClick=()=>{d(),s&&s()},o.addChild(h);function d(){m(E.confirmDialog===o),o.destroy(),E.confirmDialog=void 0,E.navigationDirection=a,ai()}}},pt=class{constructor(e=v(),n=v()){var s,i;m(D(e),"ui object pos must be a vec2"),m(D(n),"ui object size must be a vec2"),this.localPos=e.copy(),this.nativePos=e.copy(),this.size=n.copy(),this.color=E.defaultColor.copy(),this.activeColor=void 0,this.text=void 0,this.disabledColor=E.defaultDisabledColor.copy(),this.disabled=!1,this.textColor=E.defaultTextColor.copy(),this.hoverColor=E.defaultHoverColor.copy(),this.lineColor=E.defaultLineColor.copy(),this.gradientColor=E.defaultGradientColor?E.defaultGradientColor.copy():void 0,this.lineWidth=E.defaultLineWidth,this.cornerRadius=E.defaultCornerRadius,this.font=E.defaultFont,this.fontStyle=void 0,this.textWidth=void 0,this.textHeight=void 0,this.textFitScale=E.defaultTextFitScale,this.textShadow=void 0,this.textLineColor=E.defaultLineColor.copy(),this.textLineWidth=0,this.visible=!0,this.children=[],this.parent=void 0,this.extraTouchSize=0,this.soundPress=E.defaultSoundPress,this.soundRelease=E.defaultSoundRelease,this.soundClick=E.defaultSoundClick,this.interactive=!1,this.dragActivate=!1,this.canBeHover=!0,this.shadowColor=(s=E.defaultShadowColor)==null?void 0:s.copy(),this.shadowBlur=E.defaultShadowBlur,this.shadowOffset=(i=E.defaultShadowOffset)==null?void 0:i.copy(),this.navigationIndex=void 0,this.navigationAutoSelect=!1,this.anchor=v(),E.uiObjects.push(this)}addChild(e){return m(!e.parent&&!this.children.includes(e)),this.children.push(e),e.parent=this,e}removeChild(e){m(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}destroy(){var e;if(!this.destroyed){E.activeObject===this&&(E.activeObject=void 0),E.hoverObject===this&&(E.hoverObject=void 0),E.lastHoverObject===this&&(E.lastHoverObject=void 0),E.navigationObject===this&&(E.navigationObject=void 0),E.keyInputObject===this&&(E.keyInputObject=void 0),this.destroyed=1,(e=this.parent)==null||e.removeChild(this);for(let n of this.children)n.parent=void 0,n.destroy();this.children.length=0}}isMouseOverlapping(){if(!Ii)return!1;let e=ft?this.size.add(v(this.extraTouchSize||0)):this.size,n=E.screenToNative(Ke);return Ei(this.nativePos,e,n)}update(){if(this.onUpdate(),this.disabled&&(this===E.activeObject&&(E.activeObject=void 0),this===E.keyInputObject&&(E.keyInputObject=void 0)),E.keyInputObject)return;let e=E.lastHoverObject===this,n=this.isActiveObject(),s=Ds(0),i=this.dragActivate?s:Js(0);this.canBeHover&&(E.navigationMode||(i||n||!s&&!ft)&&!E.hoverObject&&this.isMouseOverlapping()&&(E.hoverObject=this)),this.isHoverObject()&&(this.disabled||(i&&this.interactive&&((!this.dragActivate||!e||Js(0))&&this.onPress(),this.soundPress&&this.soundPress.play(),E.activeObject&&!n&&E.activeObject.onRelease(),E.activeObject=this,E.activateOnPress&&this.click(!this.soundPress)),E.activateOnPress||!s&&this.isActiveObject()&&this.interactive&&this.click()),i&&ya(0,0,0,1,0)),n&&(!s||this.dragActivate&&!this.isHoverObject())&&(this.onRelease(),this.soundRelease&&this.soundRelease.play(),E.activeObject=void 0),this.isHoverObject()!==e&&(this.isHoverObject()?this.onEnter():this.onLeave())}render(){if(this.onRender(),!this.size.x||!this.size.y)return;let e=this.isNavigationObject(),n=e?this.color:this.interactive&&this.isActiveObject()&&!this.disabled?this.color:this.lineColor,s=e?this.hoverColor:this.disabled?this.disabledColor:this.interactive?this.isActiveObject()?this.activeColor||this.hoverColor:this.isHoverObject()?this.hoverColor:this.color:this.color,i=this.lineWidth*(e?1.5:1);E.drawRect(this.nativePos,this.size,s,i,n,this.cornerRadius,this.gradientColor,this.shadowColor,this.shadowBlur,this.shadowOffset)}getTextSize(){return v(this.textWidth||this.textFitScale*this.size.x,this.textHeight||this.textFitScale*this.size.y)}navigatePressed(){this.click()}isHoverObject(){return E.hoverObject===this}isActiveObject(){return E.activeObject===this}isNavigationObject(){return E.navigationObject===this}isKeyInputObject(){return E.keyInputObject===this}isInteractive(){return this.interactive&&this.visible&&!this.disabled}toString(){let e="type = "+this.constructor.name;return this.text&&(e+=`
+text = `+this.text),(this.nativePos.x||this.nativePos.y)&&(e+=`
+nativePos = `+this.nativePos),(this.localPos.x||this.localPos.y)&&(e+=`
+localPos = `+this.localPos),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.color&&(e+=`
+color = `+this.color),e}renderDebug(e=!0){let n=e?this.isHoverObject()?ll:this.disabled?fl:this.interactive?Xr:dl:ul;E.drawRect(this.nativePos,this.size,wt,4,n)}click(e=!0){this.onClick(),e&&this.soundClick&&this.soundClick.play()}onUpdate(){}onRender(){}onEnter(){}onLeave(){}onPress(){}onRelease(){}onClick(){}onChange(){}},Xi=class extends pt{constructor(e,n,s="",i="center",r=E.defaultFont){super(e,n),m(K(s),"ui text must be a string"),m(["left","center","right"].includes(i),"ui text align must be left, center, or right"),m(K(r),"ui text font must be a string"),this.text=s,this.align=i,this.font=r,this.canBeHover=!1,this.color=wt,this.shadowColor=wt,this.gradientColor=void 0,this.lineWidth=0,this.textFitScale=1}render(){super.render();let e=this.getTextSize();E.drawText(this.text,this.nativePos,e,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow,this.shadowColor,this.shadowBlur,this.shadowOffset)}},Ar=class extends pt{constructor(e,n,s=""){super(e,n),m(K(s),"ui text must be a string"),this.maxLength=0,this.text=s,this.interactive=!0,this.canBeHover=!0}click(){E.keyInputObject=this,this.onClick()}stopEditing(){this.isKeyInputObject()&&(this.soundRelease&&this.soundRelease.play(),E.activeObject=void 0,E.keyInputObject=void 0,this.onChange())}onKeyDown(e){let n=e.code,s=e.key;n==="Backspace"?this.text=this.text.slice(0,-1):n==="Enter"||n==="Escape"?this.stopEditing():s.length===1&&(!this.maxLength||this.text.lengththis.size.y,s=n?this.size.y:this.size.x,i=n?this.size.x:this.size.y,r=n?this.nativePos.x:this.nativePos.y,a=i-s,o=r-a/2,c=r+a/2,l=E.screenToNative(Ke);this.value=n?Ve(l.x,o,c):Ve(l.y,c,o)}else if(this.isNavigationObject()){let n=E.getNavigationOtherDirection();E.navigationTimer.active()||(this.value=H(this.value+n*.01))}this.value===e||this.onChange()}render(){super.render();let e=this.size.x>this.size.y,n=e?this.size.x:this.size.y,s=e?this.size.y:this.size.x;if(this.fillMode){let r=le(s,this.cornerRadius*2),a=et(r,n,this.value),o=(a-n)*(e?.5:-.5),c=this.nativePos.add(e?v(o,0):v(0,o)),l=this.disabled?this.disabledColor:this.handleColor,u=e?v(a,this.size.y):v(this.size.x,a);E.drawRect(c,u,l,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}else{let r=H(e?this.value:1-this.value),a=(n-s)*(r-.5),o=this.nativePos.add(e?v(a,0):v(0,a)),c=this.disabled?this.disabledColor:this.handleColor,l=v(s);E.drawRect(o,l,c,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}let i=this.getTextSize();E.drawText(this.text,this.nativePos,i,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow)}navigatePressed(){this.value=this.value?0:1,this.onChange(),this.onRelease(),super.navigatePressed()}},Er=class extends pt{constructor(e,n,s,i=!1,r=!1,a=1){super(e,n||v()),m(K(s),"video src must be a string"),m(O(a),"video volume must be a number"),this.color=he,this.cornerRadius=0,this.volume=a,this.video=document.createElement("video"),this.video.loop=r,this.video.volume=H(a*Gn),this.video.muted=!nt,this.video.style.display="none",this.video.src=s,document.body.appendChild(this.video),i&&this.play()}async play(){try{await this.video.play()}catch{}}pause(){this.video.pause()}stop(){this.video.pause(),this.video.currentTime=0}isLoading(){return this.video.readyState=1,"ui layout columns must be a number >= 1"),m(O(s),"ui layout gap must be a number"),m(O(i),"ui layout padding must be a number"),this.columns=n,this.gap=s,this.padding=i,r&&(this.color=wt,this.gradientColor=void 0,this.lineWidth=0,this.shadowColor=wt),this.relayout()}addChild(e){return super.addChild(e),this.relayout(),e}removeChild(e){super.removeChild(e),this.relayout()}relayout(){let e=this.children.length;if(!e){this.size=v(this.padding*2);return}let n=this.columns,s=Fs(e/n),i=new Array(n).fill(0),r=new Array(s).fill(0);for(let d=0;d=0&&b.objects.splice(e,1),super.destroy()}updatePhysics(){}render(){this.tileInfo?super.render():this.drawFixtures(this.color,this.lineColor,this.lineWidth)}renderDebugInfo(){let e=!this.getIsAwake(),n=this.getBodyType()===b.bodyTypeStatic,s=Y(e?1:0,e?1:0,n?1:0,.5);this.drawFixtures(s)}drawFixtures(e=Q,n=he,s=.1,i,r){this.getFixtureList().forEach(a=>{b.castShapeObject(a.GetShape()).GetType()!==b.instance.b2Shape.e_edge&&b.drawFixture(a,this.pos,this.angle,e,n,s,i,r)}),this.edgeLists.forEach(a=>ar(a,s,n,!1,this.pos,this.angle)),this.edgeLoops.forEach(a=>ar(a,s,n,!0,this.pos,this.angle))}beginContact(e){}endContact(e){}addShape(e,n=1,s=.2,i=0,r=!1){m(O(n),"density must be a number"),m(O(s),"friction must be a number"),m(O(i),"restitution must be a number");let a=new b.instance.b2FixtureDef;return a.set_shape(e),a.set_density(n),a.set_friction(s),a.set_restitution(i),a.set_isSensor(r),this.body.CreateFixture(a)}addBox(e=v(1),n=v(),s=0,i,r,a,o){m(D(e),"size must be a Vector2"),m(e.x>0&&e.y>0,"size must be positive"),m(D(n),"offset must be a Vector2"),m(O(s),"angle must be a number");let c=new b.instance.b2PolygonShape;return c.SetAsBox(e.x/2,e.y/2,b.vec2dTo(n),-s),this.addShape(c,i,r,a,o)}addPoly(e,n,s,i,r){m(St(e),"points must be an array");function a(c){m(3<=c.length&&c.length<=8);let l=b.instance._malloc(c.length*8);for(let d=0,f=0;d>2]=c[d].x,f+=4,b.instance.HEAPF32[l+f>>2]=c[d].y,f+=4;let u=b.instance.wrapPointer(l,b.instance.b2Vec2),h=new b.instance.b2PolygonShape;return h.Set(u,c.length),b.instance._free(l),h}let o=a(e);return this.addShape(o,n,s,i,r)}addRegularPoly(e=1,n=8,s,i,r,a){m(O(e)&&e>0,"diameter must be a positive number"),m(O(n)&&n>2,"sides must be a positive number greater than 2");let o=[],c=e/2;for(let l=n;l--;)o.push(v(c,0).rotate((l+.5)/n*te*2));return this.addPoly(o,s,i,r,a)}addRandomPoly(e=1,n,s,i,r){m(O(e)&&e>0,"diameter must be a positive number");let a=Yr(3,9),o=[],c=e/2;for(let l=a;l--;)o.push(v(Se(c/2,c*1.5),0).rotate(l/a*te*2));return this.addPoly(o,n,s,i,r)}addCircle(e=1,n=v(),s,i,r,a){m(O(e)&&e>0,"diameter must be a positive number"),m(D(n),"offset must be a Vector2");let o=new b.instance.b2CircleShape;return o.set_m_p(b.vec2dTo(n)),o.set_m_radius(e/2),this.addShape(o,s,i,r,a)}addEdge(e,n,s,i,r,a){m(D(e),"point1 must be a Vector2"),m(D(n),"point2 must be a Vector2");let o=new b.instance.b2EdgeShape;return o.Set(b.vec2dTo(e),b.vec2dTo(n)),this.addShape(o,s,i,r,a)}addEdgeList(e,n,s,i,r){m(St(e),"points must be an array");let a=[],o=[];for(let c=0;ce[dt(l,e.length)];for(let l=0;lthis.destroyFixture(e))}getCenterOfMass(){return b.vec2From(this.body.GetWorldCenter())}getLinearVelocity(){return b.vec2From(this.body.GetLinearVelocity())}getAngularVelocity(){return this.body.GetAngularVelocity()}getMass(){return this.body.GetMass()}getInertia(){return this.body.GetInertia()}getIsAwake(){return this.body.IsAwake()}getBodyType(){return this.body.GetType()}getSpeed(){return this.getLinearVelocity().length()}setTransform(e,n){this.pos=e,this.angle=n,this.body.SetTransform(b.vec2dTo(e),-n)}setPosition(e){this.setTransform(e,this.body.GetAngle())}setAngle(e){this.setTransform(b.vec2From(this.body.GetPosition()),e)}setLinearVelocity(e){this.body.SetLinearVelocity(b.vec2dTo(e))}setAngularVelocity(e){this.body.SetAngularVelocity(e)}setLinearDamping(e){this.body.SetLinearDamping(e)}setAngularDamping(e){this.body.SetAngularDamping(e)}setGravityScale(e=1){this.body.SetGravityScale(this.gravityScale=e)}setBullet(e=!0){this.body.SetBullet(e)}setAwake(e=!0){this.body.SetAwake(e)}setBodyType(e){this.body.SetType(e)}setSleepingAllowed(e=!0){this.body.SetSleepingAllowed(e)}setFixedRotation(e=!0){this.body.SetFixedRotation(e)}setCenterOfMass(e){this.setMassData(e)}setMass(e){this.setMassData(void 0,e)}setMomentOfInertia(e){this.setMassData(void 0,void 0,e)}resetMassData(){this.body.ResetMassData()}setMassData(e,n,s){let i=new b.instance.b2MassData;this.body.GetMassData(i),e!==void 0&&i.set_center(b.vec2dTo(e)),n!==void 0&&i.set_mass(n),s!==void 0&&i.set_I(s),this.body.SetMassData(i)}setFilterData(e=0,n=0,s=0){this.getFixtureList().forEach(i=>{let r=i.GetFilterData();r.set_categoryBits(e),r.set_maskBits(65535&~n),r.set_groupIndex(s)})}setSensor(e=!0){this.getFixtureList().forEach(n=>n.SetSensor(e))}applyForce(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyForce(b.vec2dTo(e),b.vec2dTo(n))}applyAcceleration(e,n){n||(n=this.getCenterOfMass()),this.setAwake();let s=e.scale(this.getMass());this.body.ApplyLinearImpulse(b.vec2dTo(s),b.vec2dTo(n))}applyImpulse(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyLinearImpulse(b.vec2dTo(e),b.vec2dTo(n))}applyTorque(e){this.setAwake(),this.body.ApplyTorque(e)}applyAngularAcceleration(e){this.setAwake(),this.body.ApplyAngularImpulse(e*this.getInertia())}applyAngularImpulse(e){this.setAwake(),this.body.ApplyAngularImpulse(e)}hasFixtures(){return!b.isNull(this.body.GetFixtureList())}getFixtureList(){let e=[];for(let n=this.body.GetFixtureList();!b.isNull(n);)e.push(n),n=n.GetNext();return e}hasJoints(){return!b.isNull(this.body.GetJointList())}getJointList(){let e=[];for(let n=this.body.GetJointList();!b.isNull(n);)e.push(n),n=n.get_next();return e}},Ki=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeStatic;super(e,n,s,i,r,o,a)}},Pr=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeKinematic;super(e,n,s,i,r,o,a)}},Mr=class extends Ki{constructor(e){m(e instanceof qs,"tileLayer must be a TileCollisionLayer"),super(e.pos,e.size),this.tileLayer=e,this.addChild(e)}render(){}buildCollision(e=.2,n=0){this.destroyAllFixtures(),this.pos=this.tileLayer.pos.copy(),this.size=this.tileLayer.size.copy();let s=[],i=(a,o)=>a+o*this.size.x,r=(a,o)=>!s[i(a,o)]&&this.tileLayer.getCollisionData(v(a,o))>0;for(let a=0;ai.fractionr.pos.distanceSquared(e)0,"Tween duration must be > 0"),this.callback=e,this.start=n,this.end=s,this.duration=i,this.life=i,this.ease=r.ease||no.LINEAR,this.useRealTime=!!r.useRealTime,this.paused=!!r.paused,this.thenCallback=void 0,this.loopRemaining=0,ot.push(this),e(this.interp(i))}setEase(e){return this.ease=e,this}then(e){return this.thenCallback=e,this.loopRemaining=0,this}loop(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>zl(this),this}pingPong(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>Ul(this),this}pause(){this.paused=!0}resume(){this.paused=!1}restart(){this.life=this.duration,this.paused=!1,ot.indexOf(this)<0&&ot.push(this),this.callback(this.interp(this.duration))}isActive(){return!this.paused&&ot.indexOf(this)>=0}getPercent(){return Ve(this.duration-this.life,0,this.duration)}getValue(){return this.interp(this.life)}interp(e){let n=this.ease((this.duration-e)/this.duration);return zc(this.start)?this.start.lerp(this.end,n):this.start+(this.end-this.start)*n}stop(){let e=ot.indexOf(this);e>=0&&ot.splice(e,1),this.thenCallback=void 0}},no={LINEAR:t=>t,POWER:t=>e=>e**t,SINE:t=>1-ye(t*(te/2)),CIRC:t=>1-(1-t*t)**.5,EXPO:t=>t===0?0:2**(10*t-10),BACK:t=>t*t*(2.70158*t-1.70158),ELASTIC:t=>t===0?0:t===1?1:-(2**(10*t-10))*fe((37-40*t)*te/6),SPRING:t=>1-(fe(te*(1-t)*(.2+2.5*(1-t)**3))*t**2.2+(1-t))*(1+1.2*t),BOUNCE:t=>{let e=1-t,n;return e<4/11?n=7.5625*e*e:e<8/11?n=7.5625*(e-=6/11)*e+.75:e<10/11?n=7.5625*(e-=9/11)*e+.9375:n=7.5625*(e-=10.5/11)*e+.984375,1-n},IN:t=>t,OUT:t=>e=>1-t(1-e),IN_OUT:t=>no.PIECEWISE(t,no.OUT(t)),PIECEWISE:(...t)=>{let e=t.length;return n=>{let s=n*e-1e-9>>0;return(t[s]((n-s/e)*e)+s)/e}},BEZIER:(t,e,n,s)=>{let i=r=>{let a=1-r,o=3*a*a*r,c=3*a*r*r,l=r**3;return[o*t+c*n+l,o*e+c*s+l]};return r=>{let a=0,o=1;for(let c=0;c<128;c++){let l=(a+o)/2,[u,h]=i(l);if(de(u-r)<1e-5)return h;u=this.size.x||n>=this.size.y?null:this.nodes[e+n*this.size.x]}worldToTile(e){let n=this.tileLayer?this.tileLayer.pos.x:0,s=this.tileLayer?this.tileLayer.pos.y:0;return v(Pe(e.x-n),Pe(e.y-s))}tileToWorld(e,n){let s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;return v(e+.5+s,n+.5+i)}buildNodeData(){let e=this.size.x,n=this.size.y,s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;for(let r=0;r0&&(c?l>0&&ke(o.posWorld,er,Y(1,0,0,le(.2,l*.05)),this.debugTime):ke(o.posWorld,er,Y(1,0,0,.25),this.debugTime))}}aStarSearch(e,n){m(e&&n,"aStarSearch needs both endpoints"),m(e!==n,"aStarSearch: start and end must differ \u2014 caller should handle trivial case"),m(e.walkable&&n.walkable,"aStarSearch: endpoints must be walkable");let s=[e];e.isOpen=!0;let i=0;for(;s.length>0;){let r=0,a=s[0].f;for(let c=1;cthis.maxLoop)break;o.isOpen=!1,s.splice(r,1),o.isClosed=!0,this.debug&&this.debugTime>0&&ke(o.posWorld,er,Y(1,1,1,.05),this.debugTime);for(let c=-1;c<=1;++c)for(let l=-1;l<=1;++l){if(l===0&&c===0)continue;let u=this.getNode(o.pos.x+l,o.pos.y+c);if(!u||!u.walkable||u.isClosed)continue;let h=1;if(l!==0&&c!==0){let x=this.getNode(o.pos.x+l,o.pos.y);if(!x||!x.walkable)continue;let w=this.getNode(o.pos.x,o.pos.y+c);if(!w||!w.walkable)continue;h=Wh}let d=o.g+h+u.cost;if(!u.isOpen)u.isOpen=!0,s.push(u);else if(d>=u.g)continue;u.parent=o,u.g=d;let f=de(n.pos.x-u.pos.x),p=de(n.pos.y-u.pos.y),y=re(f,p)+(Math.SQRT2-1)*le(f,p);u.f=u.g+y*this.heuristicWeight}}return n.parent!==null}getNearestClearNode(e,n=10,s=!0){m(D(e),"worldPos must be a Vector2"),s&&this.buildNodeData();let i=this.tileLayer?this.tileLayer.pos.x:0,r=this.tileLayer?this.tileLayer.pos.y:0,a=Pe(e.x-i),o=Pe(e.y-r);for(let c=0;c<=n;++c){let l=null,u=0;for(let h=-c;h<=c;++h)for(let d=-c;d<=c;++d){if(c>0&&de(d)!==c&&de(h)!==c)continue;let f=this.getNode(a+d,o+h);if(!f||!f.isClear())continue;let p=f.posWorld.x-e.x,y=f.posWorld.y-e.y,x=p*p+y*y;(!l||x0&&Qe(i.posWorld,.3,Y(.5,0,.5,.5),this.debugTime),e.splice(n,1),n=re(1,n-1);continue}else if(c===2){this.debug&&this.debugTime>0&&Qe(i.posWorld,.3,Y(1,0,0,.5),this.debugTime);let f,p;s.pos.y===i.pos.y&&r.pos.x===i.pos.x?(f=s.pos.x,p=r.pos.y):(f=r.pos.x,p=s.pos.y);let y=this.getNode(f,p);if(y&&y.isClear()){e.splice(n,1),n=re(1,n-1);continue}}else if(c===5){this.debug&&this.debugTime>0&&Qe(i.posWorld,.3,Y(1,1,0,.5),this.debugTime);let f=n>=2?e[n-2]:s,p,y,x,w;l===0||h===0?(p=r.pos.x,y=i.pos.y,x=s.pos.x,w=i.pos.y):(p=i.pos.x,y=r.pos.y,x=i.pos.x,w=s.pos.y);let A=p-f.pos.x,S=y-f.pos.y,_=x-f.pos.x,k=w-f.pos.y,C=A*A+S*S,L=_*_+k*k,V=C0&&Qe(i.posWorld,.3,Y(0,1,0,.5),this.debugTime),l===h&&u===d){++n;continue}else{let f,p;s.pos.y===r.pos.y?(f=i.pos.x,p=s.pos.y):(f=s.pos.x,p=i.pos.y);let y=this.getNode(f,p);if(y&&y.isClear()){e[n]=y,n=re(1,n-1);continue}}++n}}smoothPathStringPull(e){if(e.length<=2)return;for(let i of e)if(!i.isClear())return;let n=e.slice();e.length=0,e.push(n[0]);let s=0;for(let i=1;i0&&Rt(r.posWorld,e[e.length-1].posWorld,Y(0,0,1,.3),.02,this.debugTime);continue}for(;s=1;--n){let s=e[n-1],i=e[n],r=e[n+1];(i.pos.x-s.pos.x)*(r.pos.y-s.pos.y)===(i.pos.y-s.pos.y)*(r.pos.x-s.pos.x)&&e.splice(n,1)}}isNodeClear(e,n){let s=this.getNode(e,n);return s!==null&&s.isClear()}isLineClear(e,n){m(D(e)&&D(n),"isLineClear needs Vector2 endpoints"),m(this.isNodeClear(e.x,e.y)&&this.isNodeClear(n.x,n.y),"isLineClear endpoints must be in-bounds and clear");let s=n.x-e.x,i=n.y-e.y,r=de(s),a=de(i),o=ut(s),c=ut(i),l=e.x,u=e.y;if(a===r){for(;l!==n.x;){if(l!==e.x&&(!this.isNodeClear(l,u)||!this.isNodeClear(l,u-c))||!this.isNodeClear(l,u+c))return!1;l+=o,u+=c}if(!this.isNodeClear(n.x,n.y-c))return!1}else if(ao.posWorld.copy());if(this.debug&&this.debugTime>0&&a.length>0){for(let o=1;oqh,bootGameHost:()=>$h,default:()=>Hh});var An=class{constructor(e){this._state=(e==null?2654435769:e)>>>0}next(){this._state=this._state+1831565813>>>0;let e=this._state;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}range(e,n){return e+this.next()*(n-e)}reseed(e){this._state=(e==null?2654435769:e)>>>0}},vo=class{constructor(e){this._clock=e||tu(),this._origin=this._clock()}nowMs(){return this._clock()}elapsedMs(){return this._clock()-this._origin}},wo=class{constructor(e){this._time=e,this._subs=new Map}sourceFor(e){let n=this,s=e==null?null:e;return{on(i,r){if(n._assertType(i),typeof r!="function")throw new Error("[HostDevInputBridge] on \u7684 handler \u5FC5\u987B\u662F\u51FD\u6570");let a=n._subs.get(i)||[],o={handler:r,scope:s};return a.push(o),n._subs.set(i,a),{cancel(){let c=n._subs.get(i);if(!c)return;let l=c.indexOf(o);l>=0&&c.splice(l,1)}}},off(i,r){n._assertType(i);let a=n._subs.get(i);if(!a)return;let o=a.findIndex(c=>c.handler===r&&c.scope===s);o>=0&&a.splice(o,1)}}}_emit(e,n){this._assertType(e);let s=n||{},i={type:e,x:typeof s.x=="number"?s.x:0,y:typeof s.y=="number"?s.y:0,key:typeof s.key=="string"?s.key:"",tMs:this._time.nowMs()},r=this._subs.get(e);if(!r||r.length===0)return;let a=r.slice();for(let o of a)try{o.handler(i)}catch(c){on("[host-dev input] \u8F93\u5165 handler \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09type="+e,c)}}disposeScope(e){if(e==null)return 0;let n=0;for(let[s,i]of this._subs){let r=i.filter(a=>a.scope!==e);n+=i.length-r.length,r.length===0?this._subs.delete(s):this._subs.set(s,r)}return n}_subscriptionCount(){let e=0;for(let n of this._subs.values())e+=n.length;return e}_assertType(e){if(!To.has(e))throw new Error("[HostDevInputBridge] \u975E\u6CD5\u8F93\u5165\u4E8B\u4EF6\u7C7B\u578B\uFF1A"+String(e)+"\uFF08\u4EC5\u652F\u6301 "+Array.from(To).join("/")+"\uFF09")}},To=new Set(["pointerdown","pointermove","pointerup","keydown","keyup"]);function ja(t){let e=t||{},n=new vo(e.clock),s=new An(e.seed),i=e.seed==null?2654435769:e.seed>>>0,r=new wo(n),a=typeof e.audioFactory=="function"?e.audioFactory:null,o=null,c=!1,l=typeof e.engineFactory=="function"?e.engineFactory:null,u=null,h=!1,d=new Map,f=0,p=0;function y(){if(o)return o;if(!a)return c||(ko("[host-dev audio] \u672A\u6CE8\u5165 audioFactory\uFF0CgetAudioContext \u8FD4\u56DE null\uFF08P6 \u987B\u5BB9\u9519\u964D\u7EA7\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u5DE5\u5382\uFF09"),c=!0),null;try{o=a()}catch(_){on("[host-dev audio] audioFactory \u629B\u9519\uFF0CgetAudioContext \u964D\u7EA7\u8FD4\u56DE null",_),o=null}return o}function x(){if(u)return u;if(!l)return h||(ko("[host-dev engine] \u672A\u6CE8\u5165 engineFactory\uFF0CgetEngine \u8FD4\u56DE null\uFF08\u63D2\u4EF6\u987B\u5BB9\u9519\u964D\u7EA7\uFF1A\u7C92\u5B50\u9000\u53D7\u63A7\u9762\u81EA\u7BA1/\u5408\u6210\u6838\u9000 vendored/\u6570\u5B66\u9000\u5185\u7F6E\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u80CC\u4E66\uFF09"),h=!0),null;try{u=l()}catch(_){on("[host-dev engine] engineFactory \u629B\u9519\uFF0CgetEngine \u964D\u7EA7\u8FD4\u56DE null",_),u=null}return u}function w(_,k){return{getContext2d(){return e.context2d==null?null:e.context2d},onFrame(L){let V=f++;return d.set(V,L),{cancel(){d.delete(V)}}},getInput(){return r.sourceFor(_)},getAudioContext(){return y()},getEngine(){return x()},time:n,random:k}}let A=w(null,s),S={context:A,tick(_){p+=1;let k=Array.from(d.values());for(let C of k)try{C(_,p)}catch(L){on("[host-dev tick] \u5E27\u56DE\u8C03\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09frame="+p,L)}},frameCount(){return p},inputBridge:r,deriveContextFor(_,k){let C=eu(i,_),L=new An(C);return w(k==null?_:k,L)}};return Object.defineProperty(A,Ao,{value:S,enumerable:!1,writable:!1,configurable:!1}),S}var Ao=Symbol("zaomeng.coreProtocol.contextBundle"),ui=class{constructor(){this._plugins=new Map,this._initOrder=[],this._initErrors=[],this._phase="idle",this._disposed=!1,this._context=void 0,this._pluginContexts=new Map}register(e){if(!e||typeof e!="object")throw new Error("[PluginRegistry] register \u9700\u8981\u4E00\u4E2A\u63D2\u4EF6\u5BF9\u8C61");if(typeof e.name!="string"||e.name.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6\u7F3A\u5C11\u5408\u6CD5 name");if(typeof e.version!="string"||e.version.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11\u5408\u6CD5 version");if(typeof e.init!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11 init \u51FD\u6570");if(e.dispose!=null&&typeof e.dispose!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7684 dispose \u5FC5\u987B\u662F\u51FD\u6570\u6216\u7701\u7565");if(this._plugins.has(e.name))throw new Error("[PluginRegistry] \u63D2\u4EF6\u91CD\u540D\u62D2\u7EDD\uFF1A"+e.name+" \u5DF2\u6CE8\u518C");return this._plugins.set(e.name,e),this}has(e){return this._plugins.has(e)}get(e){return this._plugins.get(e)}list(){return Array.from(this._plugins.keys())}initAll(){if(this._phase==="initialized")return ko("[PluginRegistry] initAll \u91CD\u590D\u8C03\u7528\uFF0C\u5DF2\u5FFD\u7565\uFF08\u5DF2\u5904\u4E8E initialized\uFF09"),this._initResult();if(this._phase==="disposed")throw new Error("[PluginRegistry] \u5DF2 dispose \u7684\u6CE8\u518C\u5668\u4E0D\u53EF\u518D initAll");if(this._context==null)throw new Error("[PluginRegistry] \u672A\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\uFF1A\u8BF7\u5728 initAll() \u4E4B\u524D\u8C03\u7528 useContext(context)\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context); reg.initAll();\uFF09");for(let[e,n]of this._plugins){let s=this._missingDeps(n);if(s.length>0){let r=new Error("[PluginRegistry] \u63D2\u4EF6 "+e+" \u4F9D\u8D56\u7F3A\u5931\uFF1A"+s.join(", ")+"\uFF08\u672A\u6CE8\u518C\uFF09");this._initErrors.push({name:e,error:r}),on("[PluginRegistry] \u8DF3\u8FC7 init\uFF08\u4F9D\u8D56\u7F3A\u5931\uFF0C\u5DF2\u9694\u79BB\uFF09\uFF1A"+e,r);continue}let i=this._contextFor(e);try{n.init(i),this._initOrder.push(e)}catch(r){let a=r instanceof Error?r:new Error(String(r));this._initErrors.push({name:e,error:a}),on("[PluginRegistry] \u63D2\u4EF6 init \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF0C\u4E0D\u8FDE\u5750\uFF09\uFF1A"+e,a)}}return this._phase="initialized",this._initResult()}_contextFor(e){let n=this._pluginContexts.get(e);if(n)return n;let s=this._context&&this._context[Ao],i;return s&&typeof s.deriveContextFor=="function"?i=s.deriveContextFor(e,e):i=this._context,this._pluginContexts.set(e,i),i}disposeAll(){if(this._disposed)return{disposed:[],errors:[]};let e=[],n=[],s=this._context&&this._context[Ao],i=s&&s.inputBridge;for(let r=this._initOrder.length-1;r>=0;r--){let a=this._initOrder[r],o=this._plugins.get(a);if(o&&typeof o.dispose=="function")try{o.dispose(),e.push(a)}catch(c){let l=c instanceof Error?c:new Error(String(c));n.push({name:a,error:l}),on("[PluginRegistry] \u63D2\u4EF6 dispose \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,l)}if(i&&typeof i.disposeScope=="function")try{i.disposeScope(a)}catch(c){on("[PluginRegistry] \u56DE\u6536\u63D2\u4EF6\u8F93\u5165\u8BA2\u9605\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,c)}}return this._disposed=!0,this._phase="disposed",{disposed:e,errors:n}}useContext(e){if(this._phase!=="idle")throw new Error("[PluginRegistry] useContext \u5FC5\u987B\u5728 initAll() \u4E4B\u524D\u8C03\u7528\uFF08\u5F53\u524D\u9636\u6BB5\uFF1A"+this._phase+"\uFF09\u3002\u8BF7\u5728\u4EFB\u4F55 initAll/disposeAll \u4E4B\u524D\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\u3002");if(e==null||typeof e!="object")throw new Error("[PluginRegistry] useContext \u9700\u8981\u4E00\u4E2A\u53D7\u63A7\u4E0A\u4E0B\u6587\u5BF9\u8C61\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context);\uFF09");return this._context=e,this}_missingDeps(e){return!Array.isArray(e.dependencies)||e.dependencies.length===0?[]:e.dependencies.filter(n=>!this._plugins.has(n))}_initResult(){return{ok:this._initErrors.length===0,initialized:this._initOrder.slice(),errors:this._initErrors.slice()}}};function eu(t,e){let n=2166136261,s=16777619,i=t>>>0;for(let a=0;a<32;a+=8){let o=i>>>a&255;n^=o,n=Math.imul(n,s)>>>0}let r=String(e);for(let a=0;a>>0,n^=o>>>8&255,n=Math.imul(n,s)>>>0}return n>>>0}function tu(){if(typeof globalThis!="undefined"&&globalThis.performance&&typeof globalThis.performance.now=="function")return()=>globalThis.performance.now();if(typeof process!="undefined"&&process.hrtime&&typeof process.hrtime.bigint=="function"){let t=process.hrtime.bigint();return()=>Number(process.hrtime.bigint()-t)/1e6}return()=>Date.now()}function on(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function ko(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Kh=Object.freeze(Array.from(To)),Ja="core-protocol-v0";var Na=Object.freeze(["t_boot","t_plugins_ready","t_game_init","t_first_paint","t_input_bound","t_game_start"]),Co=Na.reduce((t,e,n)=>(t[e]=n,t),Object.create(null)),nu=new Set(Na);function _o(t){let e=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}var za=_o("runtime-probe::seed::v1");function di(t){return t===null||typeof t!="object"?JSON.stringify(t):Array.isArray(t)?"["+t.map(di).join(",")+"]":"{"+Object.keys(t).sort().map(n=>JSON.stringify(n)+":"+di(t[n])).join(",")+"}"}function Ua(t){let e=di(t.extra==null?null:t.extra),n=di(Array.isArray(t.pluginSet)?t.pluginSet:[]);return["seq="+t.seq,"anchor="+t.anchor,"tMono="+t.tMono,"buildSha="+(t.buildSha||""),"pluginSet="+n,"extra="+e].join("|")}function su(t){return Math.round(t*1e3)/1e3}function iu(t){if(!Array.isArray(t))return{ok:!1,reason:"records_not_array"};let e=za,n=-1;for(let s=0;stypeof _=="string").slice().sort():[],i=typeof e.sink=="function"?e.sink:null,r=e.autoBoot!==!1,a=typeof e.inputAnchorType=="string"?e.inputAnchorType:"pointerdown",o=()=>0,c=!1,l=0,u=za,h=[],d=new Set,f=-1,p=null,y=!1,x=!1,w=!1;function A(_,k){let C=null;if(!nu.has(_))C="unknown_anchor";else{d.has(_)&&(C=C?C+";duplicate_anchor":"duplicate_anchor");let V=Co[_];V_.time.nowMs(),c=!0,r&&!x&&A("t_boot",{auto:!0}),p=_.getInput().on(a,k=>{y||(y=!0,A("t_input_bound",{firstInput:!0,type:k.type}))}),A("t_input_bound",{stage:"registered",type:a})},dispose(){w||(p&&(p.cancel(),p=null),w=!0)},mark:A,getRecords(){return h.map(_=>({..._}))},toJSONL(){return h.map(_=>JSON.stringify(_)).join(`
+`)},verify(){return iu(h)}}}function ou(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Wa(t){let e=t.LJS,n=t.engineMath,s=t.engineMode,i=t.recHook||(()=>{});if(s!=="real")return null;let r=n;return{math:{lerp:(o,c,l)=>(i("math.lerp"),r.lerp(o,c,l)),smoothStep:o=>(i("math.smoothStep"),r.smoothStep(o)),easing:Object.fromEntries(Object.keys(r.easing).map(o=>[o,c=>(i("math.easing."+o),r.easing[o](c))]))},particles:{spawnEmitter(o){i("particles.spawnEmitter");let c=e.screenToWorld(e.vec2(o.pos.x,o.pos.y)),l=e.cameraScale,u=o.emitTime!=null?o.emitTime:o.count!=null?1/60:0,h=o.emitRate!=null?o.emitRate:o.count!=null?o.count*60:100,d=(o.speed!=null?o.speed:0)/l/60,f=o.damping!=null?o.damping:1,p=o.colorStart||{r:1,g:1,b:1,a:1},y=o.colorEnd||{r:1,g:1,b:1,a:0},x=e.rgb(p.r,p.g,p.b,p.a),w=e.rgb(y.r,y.g,y.b,y.a),A=new e.ParticleEmitter(c,o.angle!=null?o.angle:0,(o.emitSize!=null?o.emitSize:0)/l,u,h,o.coneAngle!=null?o.coneAngle:Math.PI,void 0,x,x,w,w,o.particleTime!=null?o.particleTime:.5,(o.sizeStart!=null?o.sizeStart:6)/l,(o.sizeEnd!=null?o.sizeEnd:0)/l,d,0,f,1,o.gravityScale!=null?o.gravityScale:0,Math.PI,.1,0,!1,o.additive!=null?o.additive:!1,!0);return{isActive(){return A.isActive()},stop(){A.destroyed||A.destroy(!0)}}}},audio:{synth:{synthSfx:o=>{i("audio.synth.synthSfx");try{return e.zzfxG(...o)}catch(c){return console.error("[host][engine-audio] zzfxG \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(c&&c.message?c.message:c)),null}},synthSong:(o,c,l,u)=>{i("audio.synth.synthSong");try{return e.zzfxM(o,c,l,u)}catch(h){return console.error("[host][engine-audio] zzfxM \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(h&&h.message?h.message:h)),null}}}}}}function yt(t){return t<0?0:t>1?1:t}function qa(t){let e=t.Ease,n=e.POWER(2),s=e.POWER(3),i=e.OUT(n),r=e.IN_OUT(n),a=e.OUT(s),o=e.IN_OUT(s),c=e.OUT(e.BACK),l=e.OUT(e.ELASTIC);return{lerp:(u,h,d)=>t.lerp(u,h,d),smoothStep:u=>t.smoothStep(u),easing:{linear:u=>e.LINEAR(yt(u)),quadIn:u=>n(yt(u)),quadOut:u=>i(yt(u)),quadInOut:u=>r(yt(u)),cubicIn:u=>s(yt(u)),cubicOut:u=>a(yt(u)),cubicInOut:u=>o(yt(u)),backIn:u=>e.BACK(yt(u)),backOut:u=>c(yt(u)),elasticIn:u=>e.ELASTIC(yt(u)),elasticOut:u=>l(yt(u))}}}var rn=2,fi=1/60;async function Ha(t){let e=t.canvas,n=t.statusEl||null,s=t.engine,i=t.seed>>>0,r=t.mode||"play",a=t.engineMode||"real",o=t.viewport.w,c=t.viewport.h,l=t.factory,u=t.buildFactoryOpts||(()=>{}),h=t.plugins||{},d=t.registerOrder||Object.values(h),f=t.onReady||(()=>{}),p=t.recHook||(()=>{});function y(G){n&&(n.textContent=G)}let x=[];window.addEventListener("error",G=>x.push({type:"error",message:String(G&&G.message||G)})),window.addEventListener("unhandledrejection",G=>x.push({type:"unhandledrejection",message:String(G&&G.reason&&G.reason.message||G&&G.reason||G)}));let w=null,A=!1;function S(){if(!A)return null;if(w)return w;let G=window.AudioContext||window.webkitAudioContext;return G?(w=new G,w):null}let _=0,k=null,C=null,L=null,V=null,ce=[],ne={},T=null;function P(G,pe){try{L&&L.mark(G,pe)}catch(F){x.push({type:"mark",message:String(F&&F.message||F)})}}function R(){C&&typeof C._refreshChecklist=="function"&&C._refreshChecklist(ne)}async function M(G,pe){k=ja({context2d:G,seed:i,audioFactory:S,clock:()=>_,engineFactory:()=>Wa({LJS:a==="real"?s:null,engineMath:a==="real"?qa(s):null,engineMode:a,recHook:p})});let F=new ui;for(let J of d)F.register(J);F.useContext(k.context),V=F.initAll(),ce=F.list().concat(["runtime-probe"]),L=Va({pluginSet:ce,inputAnchorType:"pointerdown",autoBoot:!0});let I=k.deriveContextFor("runtime-probe","runtime-probe");P("t_boot",{by:"game-host",stage:"pre-init",engineMode:a}),P("t_plugins_ready",{initialized:V.initialized.length,ok:V.ok});let B=u(k.context,{bundle:k,plugins:h,getRealAudioCtx:()=>w});C=l(B),await C.init({ctx:k.context,mainContext:G,canvas:pe(),seed:i}),T=C&&typeof C._forensicsView=="function"?C._forensicsView():null,P("t_game_init",{hasForensics:!!T}),se(),P("t_first_paint",{frame:k.frameCount()});try{L.init(I)}catch(J){x.push({type:"probe-init",message:String(J&&J.message||J)})}P("t_game_start",{mode:r,engineMode:a}),R(),f(Ft,{bundle:k,game:C,probe:L,checklist:ne,uncaught:x,pluginSet:ce,initRes:V,getGameForensics:()=>T,mark:P,stepOneFrame:se})}let j=null;function se(G){let pe=typeof G=="number"?G:fi;C&&(_+=pe*1e3,C.update(pe),a==="stub"&&j&&C.render(j),R())}function we(G){for(let pe=0;pe{}),C&&typeof C._onAudioUnlock=="function"&&C._onAudioUnlock()}let Ft={seed:i,mode:r,engineMode:a,protocol:Ja,frameCount:()=>k?k.frameCount():0,stepFrames:we,startRaf:()=>$n(),stopRaf:()=>Bt(),tap(G,pe){be(),k&&(k.inputBridge._emit("pointerdown",{x:G,y:pe}),k.inputBridge._emit("pointerup",{x:G,y:pe}))},do(G){C&&typeof C._handleAction=="function"&&C._handleAction(G)},state:()=>T?T.state():{phase:"booting"}};function en(G){let pe=k.inputBridge;function F(I,B){let J=G.getBoundingClientRect();return{x:(I-J.left)/J.width*o,y:(B-J.top)/J.height*c}}G.addEventListener("pointerdown",I=>{be(),pe._emit("pointerdown",F(I.clientX,I.clientY))}),G.addEventListener("pointermove",I=>{pe._emit("pointermove",F(I.clientX,I.clientY))}),G.addEventListener("pointerup",I=>{pe._emit("pointerup",F(I.clientX,I.clientY))})}let We=0,Gt=!1,lt=0;function mt(G){if(!Gt)return;lt===0&&(lt=G);let pe=(G-lt)/1e3;lt=G,pe>.05&&(pe=.05),se(pe),We=window.requestAnimationFrame(mt)}function $n(){a==="stub"&&(Gt||(Gt=!0,lt=0,We=window.requestAnimationFrame(mt)))}function Bt(){Gt=!1,We&&window.cancelAnimationFrame(We),We=0}function Yn(G){G.width=o*rn,G.height=c*rn,G.style.width=o+"px",G.style.height=c+"px";let pe=G.getContext("2d",{willReadFrequently:!0});return pe.setTransform(rn,0,0,rn,0,0),pe}async function Ss(){let G=Yn(e);return j=G,await M(G,()=>e),en(e),r==="evidence"?y(`evidence \u5C31\u7EEA seed=${i} \xB7 \u7528 host \u9A71\u52A8\uFF08stepFrames/tap\uFF09`):(y(`seed=${i} \xB7 \u70B9\u5F00\u59CB\uFF08\u9996\u6B21\u70B9\u51FB\u5F00\u58F0\uFF09`),$n()),Ft}let tn=()=>{},nn=()=>{};function sn(){window.__gameHostEngineInitFired=!0}function Xn(){tn()}function Kn(){}function go(){nn()}function bo(){}async function xo(G){await M(G,()=>s.mainCanvas),en(s.mainCanvas),tn=()=>{C&&(_+=fi*1e3,C.update(fi))},nn=()=>{if(C){G.save(),G.setTransform(rn,0,0,rn,0,0);try{G.imageSmoothingEnabled=!1}catch{}C.render(G),G.restore()}},s.mainCanvas&&(s.mainCanvas.id="game-engine"),window.__engine={frame(){return s.frame},time(){return s.time},timeReal(){return s.timeReal},paused(){return s.paused},timeScale(){return s.timeScale},snapshot(){return{frame:s.frame,time:s.time,timeReal:s.timeReal,paused:s.paused,timeScale:s.timeScale}}},y(`engine RAF running \xB7 seed=${i} engine=real`)}if(a!=="real")return await Ss();if(!s){let G="real \u901A\u9053\u672A\u6CE8\u5165\u5F15\u64CE\uFF08opts.engine \u7F3A\u5931\uFF09\uFF1A\u8BF7\u7ECF entry \u5305\u88C5\u5C42\u542F\u52A8\uFF08host \u4E0D\u76F4\u63A5 import \u5F15\u64CE\uFF0CQ4/Option C\uFF09";throw y("ENGINE INJECT MISSING: "+G),new Error(G)}s.setGLEnable(!1),s.setShowSplashScreen(!1),s.setDebugWatermark(!1),s.setCanvasClearColor(s.BLACK),s.setCanvasFixedSize(s.vec2(o*rn,c*rn));let vs=document.createElement("div");return vs.id="engine-root",document.body.appendChild(vs),await s.engineInit(sn,Xn,Kn,go,bo,[],vs).then(()=>xo(s.mainContext)).catch(G=>{throw window.__gameHostBootError=String(G&&G.message||G),y("ENGINE INIT FAILED: "+window.__gameHostBootError),G}),Ft}function ru(){return{hit:!1,depth:0,nx:0,ny:0}}var Eo=class{constructor(e){let n=e||{},s=typeof n.cellSize=="number"&&n.cellSize>0?n.cellSize:64;this._cellSize=s,this._cells=new Map,this._entries=new Map,this._seq=0}get size(){return this._entries.size}_cellRange(e){let n=this._cellSize,s=Math.floor((e.x-e.hw)/n),i=Math.floor((e.x+e.hw)/n),r=Math.floor((e.y-e.hh)/n),a=Math.floor((e.y+e.hh)/n);return{cx0:s,cy0:r,cx1:i,cy1:a}}insert(e,n){this._entries.has(e)&&this.remove(e);let{cx0:s,cy0:i,cx1:r,cy1:a}=this._cellRange(n),o=[];for(let l=i;l<=a;l++)for(let u=s;u<=r;u++){let h=u+","+l,d=this._cells.get(h);d||(d=new Set,this._cells.set(h,d)),d.add(e),o.push(h)}let c={x:n.x,y:n.y,hw:n.hw,hh:n.hh};this._entries.set(e,{id:e,box:c,seq:this._seq++,cells:o})}remove(e){let n=this._entries.get(e);if(!n)return!1;for(let s of n.cells){let i=this._cells.get(s);i&&(i.delete(e),i.size===0&&this._cells.delete(s))}return this._entries.delete(e),!0}query(e){let{cx0:n,cy0:s,cx1:i,cy1:r}=this._cellRange(e),a=new Set;for(let o=s;o<=r;o++)for(let c=n;c<=i;c++){let l=this._cells.get(c+","+o);if(l)for(let u of l)a.add(u)}return this._collect(a)}queryPoint(e,n){let s=this._cellSize,i=Math.floor(e/s),r=Math.floor(n/s),a=this._cells.get(i+","+r);return a?this._collect(new Set(a)):[]}clear(){this._cells.clear(),this._entries.clear(),this._seq=0}_collect(e){let n=[];for(let s of e){let i=this._entries.get(s);i&&n.push(i)}return n.sort((s,i)=>s.seq-i.seq),n.map(s=>({id:s.id,box:s.box}))}};function $a(t,e){let n=t.x-e.x,s=t.y-e.y,i=t.hw+e.hw-Math.abs(n),r=t.hh+e.hh-Math.abs(s);return i<=1e-9||r<=1e-9?ru():i0?e.fixedStep:1/120;return{gx:n.x||0,gy:n.y||0,fixedStep:s}}function Ka(t,e,n,s){t.vx+=e*s,t.vy+=n*s,t.px+=t.vx*s,t.py+=t.vy*s}function au(t,e,n){let{gx:s,gy:i,fixedStep:r}=Qa(n),a={px:t.px,py:t.py,vx:t.vx,vy:t.vy},o=e>0?e:0;for(;o>=r-1e-12;)Ka(a,s,i,r),o-=r;return o>1e-12&&Ka(a,s,i,o),a}var hi=class{constructor(e,n){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy};let s=Qa(n);this._gx=s.gx,this._gy=s.gy,this._fixedStep=s.fixedStep}get state(){return{px:this._s.px,py:this._s.py,vx:this._s.vx,vy:this._s.vy}}step(e){let n=au(this._s,e,{gravity:{x:this._gx,y:this._gy},fixedStep:this._fixedStep});return this._s=n,this.state}reset(e){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy}}};function Za(t,e,n,s){let i=n.mass==null?1:n.mass,r=n.stiffness,a=n.damping,o=t.x,c=t.v,l=s>0?s:0;if(l<=1e-12)return{x:o,v:c};let u=i>1e-12?i:1e-12,h=Math.sqrt(Math.max(0,r)/u),d=a/u,f=h>1e-12?.2/h:l,p=d>1e-12?.5/d:l,y=Math.max(1e-12,Math.min(f,p)),x=Math.ceil(l/y);(!Number.isFinite(x)||x<1)&&(x=1),x>4096&&(x=4096);let w=l/x;for(let A=0;A1?1:t}var lu=t=>(t=qe(t),t*t),uu=t=>(t=qe(t),1-(1-t)*(1-t)),du=t=>(t=qe(t),t<.5?2*t*t:1-Math.pow(-2*t+2,2)/2),fu=t=>(t=qe(t),t*t*t),hu=t=>{t=qe(t);let e=1-t;return 1-e*e*e},pu=t=>(t=qe(t),t<.5?4*t*t*t:1-Math.pow(-2*t+2,3)/2),nc=2*Math.PI/3,tc=2*Math.PI/4.5,mu=t=>(t=qe(t),t===0?0:t===1?1:-Math.pow(2,10*t-10)*Math.sin((t*10-10.75)*nc)),yu=t=>(t=qe(t),t===0?0:t===1?1:Math.pow(2,-10*t)*Math.sin((t*10-.75)*nc)+1),gu=t=>(t=qe(t),t===0?0:t===1?1:t<.5?-(Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*tc))/2:Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*tc)/2+1),yi=1.70158,pi=yi*1.525,sc=yi+1,bu=t=>(t=qe(t),sc*t*t*t-yi*t*t),xu=t=>{t=qe(t);let e=t-1;return 1+sc*e*e*e+yi*e*e},Su=t=>(t=qe(t),t<.5?Math.pow(2*t,2)*((pi+1)*2*t-pi)/2:(Math.pow(2*t-2,2)*((pi+1)*(t*2-2)+pi)+2)/2),vu=t=>qe(t),Ro=Object.freeze({linear:vu,quadIn:lu,quadOut:uu,quadInOut:du,cubicIn:fu,cubicOut:hu,cubicInOut:pu,elasticIn:mu,elasticOut:yu,elasticInOut:gu,backIn:bu,backOut:xu,backInOut:Su}),Mo=Ro,wu=["linear","quadIn","quadOut","quadInOut","cubicIn","cubicOut","cubicInOut","elasticIn","elasticOut","elasticInOut","backIn","backOut","backInOut"];function Tu(t){let e=t&&t.easing;if(!e)return Ro;let n=i=>typeof e[i]=="function"?r=>e[i](qe(r)):Ro[i],s={};for(let i of wu)s[i]=n(i);return Object.freeze(s)}var Po=class{constructor(e,n,s){let i=s||{};this._time=n,this._windowMs=typeof i.windowMs=="number"&&i.windowMs>0?i.windowMs:120;let r=Array.isArray(i.types)&&i.types.length>0?i.types:cu;this._records=new Map,this._subs=[],this._disposed=!1;for(let a of r){this._records.set(a,null);let o=e.on(a,c=>{this._records.set(a,c.tMs)});this._subs.push(o)}}consume(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs?(this._records.set(e,null),!0):(this._records.set(e,null),!1)}peek(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs}clear(){for(let e of this._records.keys())this._records.set(e,null)}dispose(){if(!this._disposed){for(let e of this._subs)try{e.cancel()}catch(n){}this._subs=[],this._disposed=!0}}};var mi=class{constructor(e,n){let s=n||{};this._time=e,this._windowMs=typeof s.windowMs=="number"&&s.windowMs>0?s.windowMs:500,this._maxCount=typeof s.maxCount=="number"&&s.maxCount>0?s.maxCount:1/0,this._count=0,this._lastHitAt=null}hit(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt!=null&&n-this._lastHitAt<=this._windowMs&&this._count>0?this._count=Math.min(this._count+1,this._maxCount):this._count=1,this._lastHitAt=n,this._count}getCount(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt==null||n-this._lastHitAt>this._windowMs?0:this._count}reset(){this._count=0,this._lastHitAt=null}};function ic(t){let e=t||{},n=null,s=null,i=!1;return{name:"gamefeel",version:"1.0.0",dependencies:[],get inputBuffer(){return n},get easing(){return Tu(s)},init(a){let o=a.getInput();n=new Po(o,a.time,{windowMs:e.inputBufferMs,types:e.inputTypes});let c=a.getEngine();s=c?c.math:null},dispose(){i||(n&&(n.dispose(),n=null),s=null,i=!0)}}}function gi(t,e){let n=e<0?0:e>1?1:e;switch(t&&t.kind){case"constant":return t.value;case"linear":return t.from+(t.to-t.from)*n;case"easeInOut":{let s=n*n*(3-2*n);return t.from+(t.to-t.from)*s}case"decay":{let s=t.power==null?2:t.power,i=Math.pow(1-n,s);return t.to+(t.from-t.to)*i}default:return 0}}var Au=Object.freeze({burst:Object.freeze({mode:"burst",count:24,angle:0,spread:Math.PI,speedMin:80,speedMax:160,lifeMin:.4,lifeMax:.8,gravity:0,drag:0,sizeCurve:{kind:"decay",from:6,to:0,power:1.5},alphaCurve:{kind:"linear",from:1,to:0}}),trail:Object.freeze({mode:"continuous",rate:60,angle:Math.PI,spread:.25,speedMin:20,speedMax:50,lifeMin:.2,lifeMax:.5,gravity:0,drag:1.5,sizeCurve:{kind:"easeInOut",from:4,to:0},alphaCurve:{kind:"decay",from:.8,to:0,power:2}}),drift:Object.freeze({mode:"continuous",rate:12,angle:Math.PI/2,spread:.6,speedMin:10,speedMax:30,lifeMin:1.5,lifeMax:3,gravity:8,drag:.5,sizeCurve:{kind:"constant",value:3},alphaCurve:{kind:"decay",from:.7,to:0,power:1}})});function ku(t){let e=Au[t];return e?Lo(e):null}function Lo(t){let e={};for(let n of Object.keys(t)){let s=t[n];e[n]=s&&typeof s=="object"?Lo(s):s}return e}function Cu(t,e,n){let s=t.mode==="continuous";return{pos:{x:e,y:n},angle:t.angle,coneAngle:t.spread,emitSize:0,emitTime:s?0:1/60,emitRate:s?t.rate||0:void 0,count:s?void 0:t.count||0,particleTime:(t.lifeMin+t.lifeMax)/2,speed:(t.speedMin+t.speedMax)/2,gravityScale:t.gravity||0,damping:t.drag!=null?1-t.drag/60:1,sizeStart:gi(t.sizeCurve,0),sizeEnd:gi(t.sizeCurve,1),colorStart:{r:1,g:1,b:1,a:gi(t.alphaCurve,0)},colorEnd:{r:1,g:1,b:1,a:gi(t.alphaCurve,1)},additive:!1}}function bi(t){let e=t||{},n=null,s=null,i=null,r=new Map,a=0,o={isActive(){return!1},stop(){}},c=0,l=1,u=0,h=0,d=0,f={x:0,y:0,remain:0,dur:0,amplitude:0,frequency:0,_phase:0},p={alpha:0,remain:0,dur:0,peak:0},y={scale:1,remain:0,dur:0,amplitude:0,frequency:0},x=!1;function w(k){if(u>0)if(u-=k,u<=0)u=0,l=1;else{let C=h>0?1-u/h:1;l=d+(1-d)*C}if(f.remain>0)if(f.remain-=k,f.remain<=0)f.remain=0,f.x=0,f.y=0;else{let C=f.remain/f.dur,L=f.amplitude*C;f._phase+=f.frequency*k*Math.PI*2,f.x=Math.sin(f._phase)*L,f.y=Math.cos(f._phase*1.3)*L}if(p.remain>0&&(p.remain-=k,p.remain<=0?(p.remain=0,p.alpha=0):p.alpha=p.peak*(p.remain/p.dur)),y.remain>0)if(y.remain-=k,y.remain<=0)y.remain=0,y.scale=1;else{let C=y.remain/y.dur,L=(1-C)*y.frequency*Math.PI*2;y.scale=1+Math.sin(L)*y.amplitude*C}}function A(k){c+=1,w(k)}function S(k){let C=k!==void 0?k:n?n.getContext2d():null;if(C&&p.alpha>0){C.globalAlpha=p.alpha,C.fillStyle="#ffffff";let L=C.canvas?C.canvas.width:0,V=C.canvas?C.canvas.height:0;C.fillRect(0,0,L,V),C.globalAlpha=1}}return{name:"particles-juice",version:"1.0.0",dependencies:[],init(k){var C;n=k,i=((C=k.getEngine())==null?void 0:C.particles)||null,typeof e.seed=="number"&&k.random.reseed(e.seed),e.autoStep!==!1&&(s=k.onFrame(L=>{A(L)}))},dispose(){x||(s&&(s.cancel(),s=null),r.forEach(k=>{try{k.stop()}catch{}}),r.clear(),l=1,u=0,f.remain=0,f.x=0,f.y=0,p.remain=0,p.alpha=0,y.remain=0,y.scale=1,x=!0)},spawnEmitter(k,C,L,V){let ce=typeof k=="string"?ku(k):Lo(k);if(!ce)return-1;V&&(ce=Object.assign(ce,V));let ne=a++;if(!i)return r.set(ne,o),ne;let T=i.spawnEmitter(Cu(ce,C,L));return r.set(ne,T),ne},stopEmitter(k){let C=r.get(k);if(C)try{C.stop()}catch{}},step(k){A(k)},render(k){S(k)},particleCount(){return 0},emitterCount(){let k=0;for(let C of r.values())C.isActive()&&(k+=1);return k},hitStop(k,C){h=Math.max(0,k),u=h,d=C==null?0:Math.max(0,Math.min(1,C)),l=h>0?d:1},getTimeScale(){return l},shakeScreen(k,C,L){f.dur=Math.max(0,k),f.remain=f.dur,f.amplitude=Math.max(0,C),f.frequency=L==null?30:L,f._phase=0,f.x=0,f.y=0},getShakeOffset(){return{x:f.x,y:f.y}},flashScreen(k,C){p.dur=Math.max(0,k),p.remain=p.dur,p.peak=C==null?.8:Math.max(0,Math.min(1,C)),p.alpha=p.dur>0?p.peak:0},getFlashAlpha(){return p.alpha},pulseScale(k,C,L){y.dur=Math.max(0,k),y.remain=y.dur,y.amplitude=C==null?.2:C,y.frequency=L==null?4:L,y.scale=1},getPulseScale(){return y.scale},juiceSnapshot(){return{timeScale:l,shake:{x:f.x,y:f.y},flashAlpha:p.alpha,pulseScale:y.scale}},probe(){return{particles:0,emitters:r.size,dropped:0,steps:c,disposed:x}}}}function oc(t){let e=Te(t.r)/255,n=Te(t.g)/255,s=Te(t.b)/255,i=Math.max(e,n,s),r=Math.min(e,n,s),a=(i+r)/2,o=0,c=0,l=i-r;return l>1e-12&&(c=a>.5?l/(2-i-r):l/(i+r),i===e?o=(n-s)/l%6:i===n?o=(s-e)/l+2:o=(e-n)/l+4,o*=60,o<0&&(o+=360)),{h:o,s:c,l:a}}function rc(t){let e=(t.h%360+360)%360,n=an(t.s),s=an(t.l);if(n<1e-12){let o=Math.round(s*255);return{r:o,g:o,b:o}}let i=s<.5?s*(1+n):s+n-s*n,r=2*s-i,a=e/360;return{r:Math.round(Oo(r,i,a+1/3)*255),g:Math.round(Oo(r,i,a)*255),b:Math.round(Oo(r,i,a-1/3)*255)}}function Oo(t,e,n){let s=n;return s<0&&(s+=1),s>1&&(s-=1),s<1/6?t+(e-t)*6*s:s<1/2?e:s<2/3?t+(e-t)*(2/3-s)*6:t}function Te(t){return t<0?0:t>255?255:t}function an(t){return t<0?0:t>1?1:t}function Go(t,e){let n=Eu(t.from,e);if(n>=0&&n({r:Te(o.r),g:Te(o.g),b:Te(o.b)})),to:r}}function Do(t,e,n){return t+(e-t)*n}function jo(t,e){let n=oc(t),s=n.h+(e.hue||0),i=an(n.s*(e.sat==null?1:e.sat)),r=an(n.l*(e.light==null?1:e.light));return rc({h:s,s:i,l:r})}var Pu=Object.freeze([Object.freeze([0,8,2,10]),Object.freeze([12,4,14,6]),Object.freeze([3,11,1,9]),Object.freeze([15,7,13,5])]);function ac(t){let e=t||{},n=null,s=!1,i={vignette:{enabled:Io(e.vignette&&e.vignette.enabled,!1),strength:Fo(e.vignette&&e.vignette.strength,.5)},dither:{enabled:Io(e.dither&&e.dither.enabled,!1),strength:Fo(e.dither&&e.dither.strength,.5)},scanline:{enabled:Io(e.scanline&&e.scanline.enabled,!1),strength:Fo(e.scanline&&e.scanline.strength,.5)}};function r(o){let c=o!==void 0?o:n?n.getContext2d():null;if(!c)return;let l=c.canvas?c.canvas.width:0,u=c.canvas?c.canvas.height:0;if(i.vignette.enabled&&i.vignette.strength>0&&l>0&&u>0){let h=c.createRadialGradient(l/2,u/2,Math.min(l,u)*.25,l/2,u/2,Math.max(l,u)*.75);h.addColorStop(0,"rgba(0,0,0,0)"),h.addColorStop(1,"rgba(0,0,0,"+i.vignette.strength.toFixed(3)+")"),c.fillStyle=h,c.fillRect(0,0,l,u)}if(i.scanline.enabled&&i.scanline.strength>0&&l>0&&u>0){c.fillStyle="rgba(0,0,0,"+(i.scanline.strength*.5).toFixed(3)+")";for(let h=0;h0&&l>0&&u>0&&typeof c.getImageData=="function"&&typeof c.putImageData=="function"){let h=c.getImageData(0,0,l,u);Mu(h,i.dither.strength),c.putImageData(h,0,0)}}return{name:"palette-post",version:"1.0.0",dependencies:[],init(o){n=o},dispose(){s||(n=null,s=!0)},applyPaletteMap(o,c){return Go(o,c)},applyPaletteMapToBuffer(o,c){return _u(o,c)},lerpPaletteMap(o,c,l){return Bo(o,c,l)},shiftHsl(o,c){return jo(o,c)},rgbToHsl(o){return oc(o)},hslToRgb(o){return rc(o)},setPost(o){if(o)for(let c of["vignette","dither","scanline"])o[c]&&(typeof o[c].enabled=="boolean"&&(i[c].enabled=o[c].enabled),typeof o[c].strength=="number"&&(i[c].strength=an(o[c].strength)))},getPost(){return{vignette:{enabled:i.vignette.enabled,strength:i.vignette.strength},dither:{enabled:i.dither.enabled,strength:i.dither.strength},scanline:{enabled:i.scanline.enabled,strength:i.scanline.strength}}},renderPost(o){r(o)},probe(){return{disposed:s,post:this.getPost()}}}}function Mu(t,e){let n=an(e);if(n<=0)return t;let{data:s,width:i}=t,a=255/(Math.max(2,Math.round(16-n*14))-1);for(let o=0;o+3>2)%i,l=Math.floor((o>>2)/i),u=(Pu[l&3][c&3]/16-.5)*a;for(let h=0;h<3;h++){let d=s[o+h]+u,f=Math.round(d/a)*a;s[o+h]=f<0?0:f>255?255:f}}return t}function Io(t,e){return typeof t=="boolean"?t:e}function Fo(t,e){return typeof t=="number"?an(t):e}var No=Object.freeze({blip:Object.freeze({name:"blip",params:Object.freeze([.6,0,880,0,.03,.06,1,1.5])}),thud:Object.freeze({name:"thud",params:Object.freeze([.8,0,90,0,.04,.18,0,1,0,0,0,0,0,4])}),chime:Object.freeze({name:"chime",params:Object.freeze([.5,0,660,.02,.12,.3,1,2])})}),cc=Object.keys(No);function Lu(t){let e=[];return t==null||typeof t!="object"?{ok:!1,errors:["song \u5FC5\u987B\u662F\u5BF9\u8C61"]}:(!Array.isArray(t.instruments)||t.instruments.length===0?e.push("instruments \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.instruments.forEach((n,s)=>{(!Array.isArray(n)||n.some(i=>typeof i!="number"||!Number.isFinite(i)))&&e.push(`instruments[${s}] \u5FC5\u987B\u662F\u6709\u9650\u6570\u5B57\u6570\u7EC4\uFF08ZzFX \u53C2\u6570\u5305\uFF09`)}),!Array.isArray(t.patterns)||t.patterns.length===0?e.push("patterns \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.patterns.forEach((n,s)=>{if(!Array.isArray(n)||n.length===0){e.push(`patterns[${s}] \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF08\u81F3\u5C11\u4E00\u4E2A\u58F0\u90E8\u901A\u9053\uFF09`);return}n.forEach((i,r)=>{if(!Array.isArray(i)||i.length<2){e.push(`patterns[${s}][${r}] \u901A\u9053\u81F3\u5C11\u542B [\u4E50\u5668\u7D22\u5F15, \u58F0\u50CF]`);return}if(i.some(c=>typeof c!="number"||!Number.isFinite(c))){e.push(`patterns[${s}][${r}] \u901A\u9053\u5FC5\u987B\u5168\u4E3A\u6709\u9650\u6570\u5B57`);return}let a=i[0]|0;Array.isArray(t.instruments)&&(a<0||a>=t.instruments.length)&&e.push(`patterns[${s}][${r}] \u4E50\u5668\u7D22\u5F15 ${a} \u8D8A\u754C\uFF08instruments \u957F\u5EA6 ${t.instruments.length}\uFF09`);let o=i[1];(o<-1||o>1)&&e.push(`patterns[${s}][${r}] \u58F0\u50CF ${o} \u8D8A\u754C\uFF08\u5E94 -1..+1\uFF09`)})}),!Array.isArray(t.sequence)||t.sequence.length===0?e.push("sequence \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.sequence.forEach((n,s)=>{if(typeof n!="number"||!Number.isInteger(n)){e.push(`sequence[${s}] \u5FC5\u987B\u662F\u6574\u6570 pattern \u7D22\u5F15`);return}Array.isArray(t.patterns)&&(n<0||n>=t.patterns.length)&&e.push(`sequence[${s}] \u7D22\u5F15 ${n} \u8D8A\u754C\uFF08patterns \u957F\u5EA6 ${t.patterns.length}\uFF09`)}),t.bpm!=null&&(typeof t.bpm!="number"||!(t.bpm>0))&&e.push("bpm \u5FC5\u987B\u662F\u6B63\u6570"),{ok:e.length===0,errors:e})}function Tt(t){return typeof t!="number"||Number.isNaN(t)||t<0?0:t>1?1:t}function Ou(t,e){switch(t){case"ease-in":return e*e;case"ease-out":return Math.sqrt(e);case"constant":return 1;default:return e}}function lc(t,e){let n=Tt(e);return t==null||!Array.isArray(t.voices)?[]:t.voices.map(s=>{let i=String(s&&s.id!=null?s.id:""),r=Array.isArray(s&&s.channelIndices)?s.channelIndices.slice():[],a=typeof s.minIntensity=="number"?Tt(s.minIntensity):0,o=typeof s.maxIntensity=="number"?Tt(s.maxIntensity):1,c=typeof s.volumeCurve=="string"?s.volumeCurve:"linear",l=typeof s.baseVolume=="number"?Tt(s.baseVolume):1;if(no)return{id:i,on:!1,volume:0,channelIndices:r};let u=o-a,h=u<=0?1:(n-a)/u,d=Tt(Ou(c,h)*l);return{id:i,on:!0,volume:d,channelIndices:r}})}function uc(t,e,n,s){try{let i=e[0]||[],r=e[1]||i,a=Math.max(i.length,r.length);if(a===0)return null;let c=t.createBuffer(2,a,44100);c.getChannelData(0).set(i),c.getChannelData(1).set(r.length?r:i);let l=t.createBufferSource();l.buffer=c,l.loop=!!s;let u=t.createGain();return u.gain.value=Tt(n*.3),l.connect(u),u.connect(t.destination),l.start(),{stop(){try{l.stop()}catch(h){}try{l.disconnect(),u.disconnect()}catch(h){}}}}catch(i){return zo("[audio-music] \u53D7\u63A7\u97F3\u9891\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",i),null}}function dc(t){let e=t||{},n=typeof e.masterVolume=="number"?Tt(e.masterVolume):1,s=()=>null,i=null,r=null,a={voices:[]},o=1,c=null,l=!1,u=0,h=!1,d=!1;function f(){let S=s();return S==null?(u+=1,h||(Jo("[audio-music] \u65E0\u53D7\u63A7\u97F3\u9891\u4E0A\u4E0B\u6587\uFF08getAudioContext \u8FD4\u56DE null\uFF09\uFF0C\u5168\u90E8\u53D1\u58F0\u9759\u9ED8 no-op\uFF08\u8BC4\u4F30\u73AF\u5883\u65E0\u58F0\u5361\u65F6\u7684\u5BB9\u9519\u964D\u7EA7\uFF09"),h=!0),null):S}function p(){if(!r||!i)return null;try{let S=typeof r.bpm=="number"&&r.bpm>0?r.bpm:125;return i.synthSong(r.instruments,r.patterns,r.sequence,S)}catch(S){return zo("[audio-music] \u66F2\u8C31\u6E32\u67D3\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",S),null}}function y(){let S=lc(a,o);if(S.length===0)return 1;let _=0;for(let k of S)k.on&&(_=Math.max(_,k.volume));return _}function x(S,_){typeof _=="number"&&(o=Tt(_));let k=f();if(k==null||!r)return;w();let C=p();if(!C)return;let L=Tt(n*y());c=uc(k,C,L,S),l=!!S&&c!=null}function w(){c&&(c.stop(),c=null),l=!1}return{name:"audio-music",version:"1.0.0",dependencies:[],init(S){s=()=>S.getAudioContext();let _=S.getEngine&&S.getEngine();i=_?_.audio.synth:null},dispose(){d||(w(),d=!0)},loadSong(S){let _=Lu(S);return _.ok?r={instruments:S.instruments,patterns:S.patterns,sequence:S.sequence,bpm:typeof S.bpm=="number"?S.bpm:125}:Jo("[audio-music] \u66F2\u8C31\u6821\u9A8C\u5931\u8D25\uFF0C\u672A\u8F7D\u5165\uFF1A"+_.errors.join("\uFF1B")),_},play(S){x(!1,S)},stop(){w()},loop(S){x(!0,S)},setIntensityLayering(S){a=S&&Array.isArray(S.voices)?{voices:S.voices}:{voices:[]}},setIntensity(S){o=Tt(S)},resolveVoices(S){return lc(a,S)},playSfx(S){let _=No[S];if(!_){Jo("[audio-music] \u672A\u77E5\u97F3\u6548\u9884\u8BBE\uFF1A"+String(S));return}let k=f();if(k!=null)try{let C=i?i.synthSfx(_.params):null;if(!C)return;uc(k,[C,C],n,!1)}catch(C){zo("[audio-music] \u97F3\u6548\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8 name="+S,C)}},getPreset(S){return No[S]},listPresets(){return cc.slice()},probe(){return{hasAudio:s()!=null,hasSong:r!=null,intensity:o,voiceCount:a.voices.length,looping:l,silentNoops:u,presetCount:cc.length}}}}function zo(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Jo(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Du="zaomeng.save";function Iu(t){if(typeof TextEncoder!="undefined")return new TextEncoder().encode(t).length;if(typeof Buffer!="undefined"&&typeof Buffer.byteLength=="function")return Buffer.byteLength(t,"utf8");let e=0;for(let n=0;n=55296&&s<=56319?(e+=4,n++):e+=3}return e}function Vo(){let t=new Map;return{getItem(e){return t.has(e)?t.get(e):null},setItem(e,n){t.set(e,n)},removeItem(e){t.delete(e)},keys(){return Array.from(t.keys())}}}function fc(){if(typeof localStorage=="undefined")throw new Error("[save-progress] createLocalStorageAdapter \u9700\u8981\u5168\u5C40 localStorage\uFF08\u4EC5\u6D4F\u89C8\u5668\u96C6\u6210\u6BB5\u53EF\u7528\uFF09\u3002node/host-dev \u8BF7\u7528\u7F3A\u7701\u5185\u5B58 adapter \u6216 createMemoryAdapter()\u3002");return{getItem(t){return localStorage.getItem(t)},setItem(t,e){localStorage.setItem(t,e)},removeItem(t){localStorage.removeItem(t)},keys(){let t=[];for(let e=0;e0?e.namespace:Du;if(n.indexOf(":")>=0)throw new Error('[save-progress] namespace \u4E0D\u5F97\u542B\u5206\u9694\u7B26 ":"\uFF08\u5F53\u524D="'+n+'"\uFF09');let s=typeof e.maxValueBytes=="number"&&e.maxValueBytes>0?Math.floor(e.maxValueBytes):32768,i=!Fu(e.adapter),r=i?Vo():e.adapter,a=n+":",o=0,c=0,l=!1;function u(f){return typeof f!="string"||f.length===0?a+String(f):a+f}function h(){try{let f=r.keys();return Array.isArray(f)?f.filter(p=>typeof p=="string"&&p.indexOf(a)===0):[]}catch(f){return ws("[save-progress] adapter.keys() \u5F02\u5E38\uFF0C\u964D\u7EA7\u8FD4\u56DE\u7A7A\u96C6",f),[]}}return{name:"save-progress",version:"1.0.0",dependencies:[],init(f){h()},dispose(){},get(f,p){if(!Uo(f))return p;let y;try{y=r.getItem(u(f))}catch(x){return ws("[save-progress] adapter.getItem \u5F02\u5E38\uFF0C\u8FD4\u56DE\u9ED8\u8BA4\u503C key="+f,x),p}if(y==null)return p;try{return JSON.parse(y)}catch{return o+=1,l||(Ts("[save-progress] \u68C0\u6D4B\u5230\u635F\u574F\u5B58\u6863\uFF08\u975E\u6CD5 JSON\uFF09\uFF0C\u5DF2\u5BB9\u9519\u56DE\u9000\u9ED8\u8BA4\u503C key="+f),l=!0),p}},set(f,p){if(!Uo(f))return Ts("[save-progress] set \u6536\u5230\u975E\u6CD5 key\uFF0C\u62D2\u7EDD\u5199\u5165\uFF1A"+String(f)),!1;let y;try{y=JSON.stringify(p)}catch{return c+=1,Ts("[save-progress] \u503C\u4E0D\u53EF JSON \u5E8F\u5217\u5316\uFF08\u5FAA\u73AF\u5F15\u7528?\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+f),!1}if(y===void 0)return c+=1,Ts("[save-progress] \u503C\u5E8F\u5217\u5316\u4E3A undefined\uFF08\u5982\u7EAF undefined/\u51FD\u6570\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+f),!1;let x=Iu(y);if(x>s)return c+=1,Ts("[save-progress] \u503C\u8D85\u5B57\u8282\u4E0A\u9650\u62D2\u7EDD\u5199\u5165 key="+f+"\uFF08"+x+" > "+s+" bytes\uFF09"),!1;try{return r.setItem(u(f),y),!0}catch(w){return c+=1,ws("[save-progress] adapter.setItem \u5F02\u5E38\uFF0C\u5199\u5165\u5931\u8D25 key="+f,w),!1}},remove(f){if(Uo(f))try{r.removeItem(u(f))}catch(p){ws("[save-progress] adapter.removeItem \u5F02\u5E38\uFF08\u5DF2\u5FFD\u7565\uFF09key="+f,p)}},clear(){let f=h(),p=0;for(let y of f)try{r.removeItem(y),p+=1}catch(x){ws("[save-progress] clear \u65F6 removeItem \u5F02\u5E38\uFF08\u5DF2\u8DF3\u8FC7\uFF09fullKey="+y,x)}return p},probe(){return{namespace:n,maxValueBytes:s,usingMemoryAdapter:i,size:h().length,corruptRecoveries:o,rejectedWrites:c}}}}function Uo(t){return typeof t=="string"&&t.length>0}function Fu(t){return!!t&&typeof t.getItem=="function"&&typeof t.setItem=="function"&&typeof t.removeItem=="function"&&typeof t.keys=="function"}function ws(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Ts(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Qn=[{id:"soda",name:"\u6C7D\u6C34",wholesale:20,basePrice:40,popularity:1,initial:!0},{id:"snack",name:"\u8FA3\u6761",wholesale:10,basePrice:25,popularity:1.2,initial:!0},{id:"bread",name:"\u9762\u5305",wholesale:30,basePrice:60,popularity:.8,initial:!0},{id:"ice",name:"\u51B0\u6DC7\u6DCB",wholesale:40,basePrice:90,popularity:.7,initial:!1},{id:"toy",name:"\u5C0F\u73A9\u5177",wholesale:80,basePrice:180,popularity:.35,initial:!1}];function He(t){return Qn.find(e=>e.id===t)}var Ee={lengthSec:96,rushStartSec:30,rushEndSec:66,rushRampSec:3,daysPerSegment:3};function pc(t){let{rushStartSec:e,rushEndSec:n,rushRampSec:s}=Ee;return t<=e-s||t>=n+s?0:t>=e&&t<=n?1:te.id===t)}function Ho(t){let e=n=>!!t[n];return{shelfCap:e("shelf2")?48:e("shelf1")?34:24,serveCooldownSec:e("speed2")?.32:e("speed1")?.42:.55,patienceMul:e("decor2")?1.3:e("decor1")?1.15:1,settleRepBonusTenth:e("decor2")?60:e("decor1")?30:0,flowMul:e("decor2")?1.12:1}}function Si(t){let e=t.priceMul,n=t.reputation==null?$e.start:t.reputation,s=t.serveCapacity==null?26:t.serveCapacity,i=t.stockUnits==null?1/0:t.stockUnits,r=t.segment==null?1:t.segment,a=t.unlocked||Qn.filter(x=>x.initial).map(x=>x.id),l=((Ee.lengthSec-(Ee.rushEndSec-Ee.rushStartSec))/cn.idleIntervalSec+(Ee.rushEndSec-Ee.rushStartSec)/cn.rushIntervalSec)*Wo(e)*qo(n),u=Math.min(l,s,i),h=a.map(x=>He(x)).filter(Boolean),d=h.reduce((x,w)=>x+w.popularity,0),f=h.reduce((x,w)=>x+(Math.round(w.basePrice*e)-w.wholesale)*(w.popularity/d),0),p=Math.round(u*f),y=oe.rentBaseJiao+(r-1)*oe.rentPerSegmentJiao;return{arrivals:l,served:u,grossJiao:p,rentJiao:y,profitJiao:p-y}}function je(t,e,n){return tn?n:t}function Ye(t){let e=t/10;return Number.isInteger(e)?String(e):e.toFixed(1)}var gc=1,Gu=2600;function As(t){let e=t.random;if(!e||typeof e.next!="function")throw new Error("[shop-core] \u5FC5\u987B\u6CE8\u5165\u53D7\u63A7\u968F\u673A\u6E90 random\uFF08next/range/reseed\uFF09");let n=0,s={nowMs:()=>n,elapsedMs:()=>n},i=new mi(s,{windowMs:Gu,maxCount:99}),r=[];function a(T,P){r.push(Object.assign({type:T,tMs:Math.round(n)},P||{}))}let o={phase:"title",day:1,cash:oe.startCashJiao,repTenth:$e.start*10,priceMul:1,stock:{},unlocked:Qn.filter(T=>T.initial).map(T=>T.id),upgrades:{},customers:[],dayTimeSec:0,rushFactor:0,serveCooldown:0,comboCount:0,prepBought:{},today:c(),lifetime:{days:0,served:0,angry:0,netJiao:0,upgradesBought:0},settle:null,summary:null,gameoverReason:null};function c(){return{revenueJiao:0,soldCostJiao:0,served:0,angry:0,stockout:0,walkaway:0,rescued:0,bigSales:0,maxCombo:0}}let l=1,u=0,h=!1,d=Ho(o.upgrades);function f(){d=Ho(o.upgrades)}function p(){let T=0;for(let P of Object.keys(o.stock))T+=o.stock[P];return T}function y(){return o.repTenth/10}function x(T){o.repTenth=je(o.repTenth+T,0,$e.max*10)}function w(T){let P=o.phase;o.phase=T,a("phase_changed",{from:P,to:T})}function A(T){o.day=T,o.prepBought={},o.today=c(),o.customers=[],o.dayTimeSec=0,o.rushFactor=0,o.settle=null,o.summary=null,w("prep"),a("save_point",{})}function S(){let T=o.rushFactor>.5?cn.rushIntervalSec:cn.idleIntervalSec,P=Wo(o.priceMul)*qo(y())*d.flowMul;u=T/Math.max(P,.05)*e.range(cn.jitterMin,cn.jitterMax)}function _(){let T=o.unlocked.map(M=>He(M)),P=T.reduce((M,j)=>M+j.popularity,0),R=e.next()*P;for(let M of T)if(R-=M.popularity,R<=0)return M.id;return T[T.length-1].id}function k(){for(let T=0;TP.slot===T))return T;return-1}function C(){let T=_(),P=k();if(P<0){o.today.walkaway+=1,a("walkaway_full",{productId:T});return}let M=(o.rushFactor>.5?kn.rushSec:kn.idleSec)*d.patienceMul*e.range(.9,1.12),j={id:l++,productId:T,slot:P,mood:"queue",patienceSec:M,patienceMaxSec:M,timerSec:0,avatar:Math.floor(e.next()*4)%4,impatientFired:!1};(o.stock[T]||0)<=0&&(j.mood="stockout",j.timerSec=kn.stockoutLingerSec),o.customers.push(j),a("customer_arrive",{id:j.id,slot:P,productId:T,mood:j.mood})}function L(T){let P=o.customers.indexOf(T);P>=0&&o.customers.splice(P,1)}function V(T){o.dayTimeSec+=T,o.rushFactor=pc(o.dayTimeSec);let P=o.rushFactor>.5;if(P!==h&&(a(P?"rush_start":"rush_end",{}),h=P),o.serveCooldown>0&&(o.serveCooldown=Math.max(0,o.serveCooldown-T)),o.dayTimeSec>=Ee.lengthSec){a("closing",{}),o.customers=[],ce();return}u-=T,u<=0&&(C(),S());for(let R=o.customers.length-1;R>=0;R--){let M=o.customers[R];if(M.mood==="queue"){if((o.stock[M.productId]||0)<=0){M.mood="stockout",M.timerSec=kn.stockoutLingerSec;continue}M.patienceSec-=T,!M.impatientFired&&M.patienceSec/M.patienceMaxSec<=kn.impatientRatio&&(M.impatientFired=!0,a("customer_impatient",{id:M.id,slot:M.slot})),M.patienceSec<=0&&(M.mood="leaving",M.timerSec=kn.graceSec,a("customer_grace",{id:M.id,slot:M.slot}))}else M.mood==="leaving"?(M.timerSec-=T,M.timerSec<=0&&(L(M),o.today.angry+=1,x(-$e.angryLossTenth),a("angry_leave",{id:M.id,slot:M.slot,avatar:M.avatar,productId:M.productId,repLossTenth:$e.angryLossTenth}))):M.mood==="stockout"&&(M.timerSec-=T,M.timerSec<=0&&(L(M),o.today.stockout+=1,x(-$e.stockoutLossTenth),a("stockout_leave",{id:M.id,slot:M.slot,avatar:M.avatar,productId:M.productId,repLossTenth:$e.stockoutLossTenth})))}o.comboCount=i.getCount(n)}function ce(){let T=o.today,P=Math.ceil(o.day/Ee.daysPerSegment),R=oe.rentBaseJiao+(P-1)*oe.rentPerSegmentJiao,M=0;y()<$e.fineThreshold&&(M=oe.fineBaseJiao+T.angry*oe.finePerAngryJiao,a("fined",{fineJiao:M}));let j=d.settleRepBonusTenth;T.angry===0&&(j+=$e.noAngryBonusTenth),x(j),o.cash-=R+M;let se=T.revenueJiao-T.soldCostJiao-R-M;if(o.lifetime.days+=1,o.lifetime.netJiao+=se,o.settle={day:o.day,revenueJiao:T.revenueJiao,soldCostJiao:T.soldCostJiao,rentJiao:R,fineJiao:M,netJiao:se,served:T.served,angry:T.angry,stockout:T.stockout,walkaway:T.walkaway,rescued:T.rescued,maxCombo:T.maxCombo,repBackTenth:j,reputation:y()},a("day_end",{settle:o.settle}),y()<=0){o.gameoverReason="reputation",w("gameover"),a("gameover",{reason:"reputation"});return}if(o.cash<0){o.gameoverReason="bankrupt",w("gameover"),a("gameover",{reason:"bankrupt"});return}w("settle")}let ne={state:o,timeSource:s,update(T){let P=Math.max(0,Math.min(T,.1));n+=P*1e3,o.phase==="open"&&V(P)},drainEvents(){let T=r;return r=[],T},startGame(T){return T&&ne.restoreFromSave(T)?{ok:!0,continued:!0}:(o.cash=oe.startCashJiao,o.repTenth=$e.start*10,o.priceMul=1,o.stock={},o.unlocked=Qn.filter(P=>P.initial).map(P=>P.id),o.upgrades={},o.lifetime={days:0,served:0,angry:0,netJiao:0,upgradesBought:0},o.gameoverReason=null,f(),i.reset(),a("game_start",{continued:!1}),A(1),{ok:!0,continued:!1})},buyStock(T,P){let R=Math.max(1,Math.floor(P||1));if(o.phase!=="prep")return{ok:!1,reason:"phase"};let M=He(T);if(!M||!o.unlocked.includes(T))return{ok:!1,reason:"unknown_product"};if(p()+R>d.shelfCap)return{ok:!1,reason:"shelf_full"};let j=M.wholesale*R;return o.cash0)return{ok:!1,reason:"cooldown"};if(!o.unlocked.includes(T))return{ok:!1,reason:"unknown_product"};if((o.stock[T]||0)<=0)return a("tap_empty",{productId:T}),{ok:!1,reason:"no_stock"};let P=o.customers.filter(we=>we.productId===T&&(we.mood==="queue"||we.mood==="leaving")).sort((we,be)=>we.id-be.id)[0];if(!P)return a("tap_nocustomer",{productId:T}),{ok:!1,reason:"no_customer"};let R=P.mood==="leaving";o.stock[T]-=1;let M=i.hit(n);o.comboCount=M,o.today.maxCombo=Math.max(o.today.maxCombo,M);let j=Math.round(mc(T,o.priceMul)*yc(M));o.cash+=j,o.today.revenueJiao+=j,o.today.soldCostJiao+=He(T).wholesale,o.today.served+=1,o.lifetime.served+=1,R&&(o.today.rescued+=1),x($e.serveGainTenth+(R?$e.rescueBonusTenth:0)),o.serveCooldown=d.serveCooldownSec;let se=j>=oe.bigSaleJiao;return se&&(o.today.bigSales+=1),L(P),a("serve_ok",{id:P.id,slot:P.slot,avatar:P.avatar,productId:T,revenueJiao:j,combo:M,big:se,rescued:R}),{ok:!0,revenueJiao:j,combo:M,big:se,rescued:R,customerId:P.id}},confirmSettle(){if(o.phase!=="settle")return{ok:!1,reason:"phase"};let T=o.day;if(a("save_point",{}),T%Ee.daysPerSegment===0){let P=T/Ee.daysPerSegment;o.summary={segment:P,days:T,netJiao:o.lifetime.netJiao,served:o.lifetime.served,upgradesBought:o.lifetime.upgradesBought,reputation:y()},w("summary"),a("segment_end",{summary:o.summary})}else A(T+1);return{ok:!0}},confirmSummary(){return o.phase!=="summary"?{ok:!1,reason:"phase"}:(A(o.day+1),{ok:!0})},derived(){return d},reputation:y,totalStock:p,snapshotForSave(){return{v:gc,day:o.day,cash:o.cash,repTenth:o.repTenth,priceMul:o.priceMul,stock:Object.assign({},o.stock),unlocked:o.unlocked.slice(),upgrades:Object.assign({},o.upgrades),lifetime:Object.assign({},o.lifetime)}},restoreFromSave(T){return!T||T.v!==gc||typeof T.day!="number"||typeof T.cash!="number"||typeof T.repTenth!="number"||!T.unlocked||!Array.isArray(T.unlocked)||T.unlocked.length===0?!1:(o.cash=Math.floor(T.cash),o.repTenth=je(Math.floor(T.repTenth),0,$e.max*10),o.priceMul=je(T.priceMul||1,oe.priceMin,oe.priceMax),o.stock=Object.assign({},T.stock||{}),o.unlocked=T.unlocked.filter(P=>!!He(P)),o.upgrades=Object.assign({},T.upgrades||{}),o.lifetime=Object.assign({days:0,served:0,angry:0,netJiao:0,upgradesBought:0},T.lifetime||{}),o.gameoverReason=null,f(),i.reset(),a("game_start",{continued:!0}),A(Math.max(1,Math.floor(T.day))),!0)}};return ne}var ks={open_shop:["\u5F00\u5F20\u55BD\u2014\u2014\u8857\u574A\u4EEC\u90FD\u7B49\u7740\u5462\uFF01","\u4ECA\u513F\u4E2A\u8FDB\u70B9\u5565\u597D\u8D27\uFF1F\u6211\u5FC3\u91CC\u6709\u6570\u3002","\u5C0F\u672C\u751F\u610F\uFF0C\u8D26\u53EF\u5F97\u7B97\u660E\u767D\u54AF\u3002"],day_start:["\u5F00\u95E8\u8FCE\u5BA2\uFF01\u90FD\u9EBB\u5229\u70B9\u513F~","\u54DF\uFF0C\u4ECA\u5929\u592A\u9633\u4E0D\u9519\uFF0C\u51C6\u662F\u4E2A\u597D\u65E5\u5B50\u3002"],idle_chat:["\u6162\u60A0\u60A0\u7684\u4E0B\u5348\uFF0C\u6700\u9002\u5408\u76D8\u8D26\u5566\u3002","\u9694\u58C1\u8001\u674E\u53C8\u6765\u8D4A\u8D26\uFF1F\u60F3\u5F97\u7F8E\u3002","\u8D27\u67B6\u64E6\u5F97\u9503\u4EAE\uFF0C\u770B\u7740\u5C31\u8212\u5766\u3002"],rush_start:["\u653E\u5B66\u5566\u653E\u5B66\u5566\uFF0C\u6253\u8D77\u7CBE\u795E\u6765\uFF01","\u4EBA\u90FD\u6D8C\u8FC7\u6765\u4E86\uFF0C\u624B\u4E0A\u522B\u505C\uFF01"],serve_ok:["\u597D\u561E\uFF0C\u62FF\u7A33\u5F53\uFF01","\u60A8\u6162\u8D70\uFF0C\u5E38\u6765\u554A~","\u8FD9\u5C31\u7ED9\u60A8\u62FF\uFF0C\u5FEB\u5F97\u5F88\uFF01"],combo_hot:["\u624B\u611F\u6765\u4E86\uFF0C\u8C01\u90FD\u522B\u62E6\u6211\uFF01","\u4E00\u4E2A\u63A5\u4E00\u4E2A\uFF0C\u8D8A\u5E72\u8D8A\u987A\u6E9C\uFF01"],big_sale:["\u54CE\u54DF\uFF0C\u5927\u4E3B\u987E\uFF01\u4ECA\u665A\u52A0\u4E2A\u9E21\u817F\uFF01","\u8FD9\u5355\u9876\u534A\u5929\u4E70\u5356\uFF0C\u7F8E\u6ECB\u6ECB~"],rescue:["\u522B\u8D70\u522B\u8D70\uFF0C\u8FD9\u5C31\u7ED9\u60A8\u62FF\u4E0A\uFF01","\u597D\u9669\u597D\u9669\uFF0C\u5DEE\u70B9\u513F\u9EC4\u4E86\u4E00\u5355\u3002"],angry:["\u54CE\u5440\uFF0C\u628A\u4EBA\u667E\u8DD1\u4E86\u2026\u2026\u5FC3\u75BC\u3002","\u7838\u62DB\u724C\u4E86\u7838\u62DB\u724C\u4E86\uFF0C\u5F97\u4E0A\u70B9\u5FC3\uFF01"],stockout:["\u7A7A\u8D27\u67B6\u6700\u6233\u5FC3\u7A9D\u5B50\uFF0C\u660E\u513F\u591A\u5907\u70B9\u3002","\u53C8\u5356\u65AD\u4E86\u2026\u2026\u662F\u597D\u4E8B\u4E5F\u662F\u574F\u4E8B\u3002"],settle_win:["\u4ECA\u513F\u8D26\u9762\u7EA2\u706B\uFF0C\u8BB0\u4E0A\u8BB0\u4E0A\uFF01","\u8F9B\u82E6\u4E00\u5929\uFF0C\u503C\u5F53\uFF01"],settle_lose:["\u8FD9\u8D26\u2026\u2026\u8D8A\u7B97\u8D8A\u5FC3\u51C9\u3002","\u7F5A\u5355\u90FD\u8D34\u8138\u4E0A\u4E86\uFF0C\u660E\u5929\u5F97\u6362\u4E2A\u6D3B\u6CD5\u3002"],upgrade:["\u820D\u4E0D\u5F97\u5B69\u5B50\u5957\u4E0D\u7740\u72FC\uFF0C\u5347\uFF01","\u9E1F\u67AA\u6362\u70AE\uFF0C\u54B1\u4E5F\u8BB2\u7A76\u4E00\u56DE\uFF01"],gameover:["\u5509\u2026\u2026\u5377\u5E18\u95E8\u4E00\u62C9\uFF0C\u4ECE\u5934\u518D\u6765\u5427\u3002"]},bp=Object.keys(ks).length;function bc(t){let e={};return function(s){let i=ks[s];if(!i||i.length===0)return"";if(i.length===1)return i[0];let r=Math.floor(t.next()*i.length)%i.length;return r===e[s]&&(r=(r+1)%i.length),e[s]=r,i[r]}}var Cs={paper:{r:246,g:231,b:201},paperHi:{r:255,g:246,b:227},cream:{r:255,g:243,b:220},ink:{r:91,g:70,b:54},inkSoft:{r:138,g:108,b:84},wood:{r:169,g:118,b:79},woodDark:{r:124,g:84,b:55},gold:{r:232,g:169,b:66},coin:{r:246,g:196,b:83},amber:{r:240,g:196,b:117},brick:{r:201,g:111,b:74},danger:{r:178,g:72,b:54},leaf:{r:133,g:158,b:94},sky:{r:243,g:217,b:168},shadow:{r:62,g:49,b:40},scrim:{r:46,g:35,b:27},smoke:{r:140,g:106,b:85}},xc=Object.keys(Cs);function Sc(){let t=xc.map(a=>Cs[a]),e={from:t,to:t.slice()},n={from:t,to:t.map(a=>jo(a,{hue:-10,sat:1.18,light:.9}))},s=0,i=r(0);function r(a){let o=Bo(e,n,a),c={};for(let l of xc)c[l]=Go(o,Cs[l]);return c}return{setRush(a){let o=Math.round(Math.max(0,Math.min(1,a))*25)/25;o!==s&&(s=o,i=r(o))},rushT(){return s},c(a,o){let c=i[a]||Cs.ink,l=o==null?1:o;return l>=1?`rgb(${c.r},${c.g},${c.b})`:`rgba(${c.r},${c.g},${c.b},${l})`},rgb(a){return i[a]||Cs.ink}}}var $o={shopkeeperIdle:"shopkeeper-idle.jpg",shopkeeperWave:"shopkeeper-wave.jpg",customer0:"customer-kid.jpg",customer1:"customer-lady.jpg",customer2:"customer-grandpa.jpg",customer3:"customer-auntie.jpg",storefront:"storefront.jpg",itemSoda:"item-soda.jpg",itemSnack:"item-snack.jpg",itemBread:"item-bread.jpg",itemIce:"item-ice.jpg",itemToy:"item-toy.jpg",uiPanel:"ui-panel.jpg"},Cn={soda:"itemSoda",snack:"itemSnack",bread:"itemBread",ice:"itemIce",toy:"itemToy"};function vc(t){let e=t==null?"./assets/":t,n=Object.keys($o),s={},i=[];function r(a){return new Promise(o=>{if(typeof Image=="undefined"){s[a]=null,i.push(a),o(null);return}let c=new Image;c.onload=()=>{s[a]=c,o(c)},c.onerror=()=>{console.warn("[ref-assets] \u8D44\u4EA7\u52A0\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u7A0B\u5E8F\u5316\u56DE\u9000\uFF09\uFF1A"+$o[a]),s[a]=null,i.push(a),o(null)},c.src=e+$o[a]})}return Promise.all(n.map(r)).then(()=>({images:s,missing:i,loaded:n.length-i.length,total:n.length}))}function wc(t){let e=t.bundle,n=t.juice;function s(T){let P=bi({maxParticles:400});return P.init(e.deriveContextFor(T,T)),P}let i=s("fx-gold"),r=s("fx-cream"),a=s("fx-smoke"),o=[];function c(T,P,R){o.push({t:0,dur:Math.max(T,.001),ease:R&&R.ease||Mo.cubicOut,onUpdate:P,onDone:R&&R.onDone||null})}let l=new Map;function u(T,P){let R=l.get(T);return R||(R={state:{x:P==null?1:P,v:0},target:P==null?1:P,stiffness:320,damping:14},l.set(T,R)),R.state.x}function h(T,P,R){u(T);let M=l.get(T);M.state.v+=P,R!=null&&(M.target=R)}let d=[];function f(T){d.push({t:0,dur:T.dur||.3,fx:T.fx,fy:T.fy,tx:T.tx,ty:T.ty,arc:T.arc==null?46:T.arc,imageKey:T.imageKey||null,label:T.label||"",onArrive:T.onArrive||null})}let p=[],y=980;function x(T){let P=T.dur||.45,R=(T.tx-T.fx)/P,M=(T.ty-T.fy-.5*y*P*P)/P;p.push({proj:new hi({px:T.fx,py:T.fy,vx:R,vy:M},{gravity:{x:0,y}}),age:0,dur:P,tx:T.tx,ty:T.ty,imageKey:T.imageKey||null,onLand:T.onLand||null})}let w=[];function A(T,P,R,M,j){w.push({text:T,x:P,y:R,t:0,dur:.9,colorName:M||"gold",size:j||16})}let S=[];function _(T,P){S.push({x:T,y:P,t:0})}function k(T,P,R){i.spawnEmitter("burst",T,P,{count:R?26:13,angle:-Math.PI/2,spread:.85,speedMin:130,speedMax:R?320:240,gravity:420,lifeMin:.35,lifeMax:.7,sizeCurve:{kind:"decay",from:R?5.5:4,to:0,power:1.3}})}function C(T,P,R){r.spawnEmitter("burst",T,P,{count:R||10,angle:-Math.PI/2,spread:1.1,speedMin:40,speedMax:110,gravity:-30,lifeMin:.4,lifeMax:.8,sizeCurve:{kind:"decay",from:3,to:0,power:1}})}function L(T,P){a.spawnEmitter("burst",T,P,{count:12,angle:-Math.PI/2,spread:Math.PI,speedMin:25,speedMax:70,gravity:-18,drag:1.2,lifeMin:.5,lifeMax:1,sizeCurve:{kind:"easeInOut",from:5,to:1},alphaCurve:{kind:"decay",from:.7,to:0,power:1.5}})}function V(T,P){for(let R=o.length-1;R>=0;R--){let M=o[R];M.t+=T;let j=Math.min(M.t/M.dur,1);M.onUpdate(M.ease(j)),j>=1&&(M.onDone&&M.onDone(),o.splice(R,1))}for(let R of l.values())R.state=Za(R.state,R.target,{stiffness:R.stiffness,damping:R.damping},T);for(let R=d.length-1;R>=0;R--){let M=d[R];M.t+=P,M.t>=M.dur&&(M.onArrive&&M.onArrive(),d.splice(R,1))}for(let R=p.length-1;R>=0;R--){let M=p[R];M.age+=P,M.proj.step(P),M.age>=M.dur&&(M.onLand&&M.onLand(),p.splice(R,1))}for(let R=w.length-1;R>=0;R--){let M=w[R];M.t+=P,M.t>=M.dur&&w.splice(R,1)}for(let R=S.length-1;R>=0;R--)S[R].t+=T,S[R].t>=.32&&S.splice(R,1)}function ce(T,P){T.save(),T.fillStyle=P.c("coin"),i.render(T),T.fillStyle=P.c("cream"),r.render(T),T.fillStyle=P.c("smoke"),a.render(T),T.restore(),n.render(T)}return{easing:Mo,addTween:c,springVal:u,springKick:h,addFlight:f,addToss:x,addFloater:A,addTapRing:_,burstCoin:k,burstSparkle:C,burstSmoke:L,step:V,renderParticles:ce,view:{flights:d,tosses:p,floaters:w,tapRings:S},juice:n,particleProbe(){return{gold:i.particleCount(),cream:r.particleCount(),smoke:a.particleCount()}},dispose(){i.dispose(),r.dispose(),a.dispose()}}}function Tc(t){let e=t.getAudio,n=t.p6,s=t.baseUrl==null?"./assets/":t.baseUrl,i=new Set,r={loading:!1,ready:!1,failed:!1,gainIdle:null,gainRush:null,idleLevel:0,rushLevel:0,targetRush:0},a=null;function o(d){return a||(a=d.createGain(),a.gain.value=.5,a.connect(d.destination)),a}function c(){let d=e();if(!d||r.loading||r.ready||r.failed)return;r.loading=!0;function f(p){return fetch(s+p).then(y=>{if(!y.ok)throw new Error("HTTP "+y.status);return y.arrayBuffer()}).then(y=>d.decodeAudioData(y)).then(y=>{let x=d.createBufferSource();x.buffer=y,x.loop=!0;let w=d.createGain();return w.gain.value=0,x.connect(w),w.connect(d.destination),x.start(),w})}Promise.all([f("bgm-idle.mp3"),f("bgm-rush.mp3")]).then(([p,y])=>{r.gainIdle=p,r.gainRush=y,r.ready=!0,r.loading=!1}).catch(p=>{console.warn("[ref-audio] BGM \u88C5\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u65E0 BGM\uFF09\uFF1A"+(p&&p.message?p.message:p)),r.failed=!0,r.loading=!1})}function l(d,f,p){if(r.targetRush=f,!r.ready)return;let y=p?1:.35,x=.5*(1-f)*y,w=.55*f*y,A=Math.min(d/1.2,1);r.idleLevel+=(x-r.idleLevel)*A,r.rushLevel+=(w-r.rushLevel)*A,r.gainIdle.gain.value=r.idleLevel,r.gainRush.gain.value=r.rushLevel}function u(d,f,p,y,x,w,A){let S=d.currentTime+(A||0),_=d.createOscillator(),k=d.createGain();_.type=f,_.frequency.setValueAtTime(p,S),_.frequency.exponentialRampToValueAtTime(Math.max(y,1),S+x),k.gain.setValueAtTime(1e-4,S),k.gain.exponentialRampToValueAtTime(w,S+.012),k.gain.exponentialRampToValueAtTime(1e-4,S+x),_.connect(k),k.connect(o(d)),_.start(S),_.stop(S+x+.02)}function h(d,f){let p=e();if(!p)return;let y=f||{};switch(d){case"arrive":n.playSfx("blip");break;case"shelve":n.playSfx("thud");break;case"upgrade":n.playSfx("chime");break;case"coin":{let x=Math.min(y.combo||1,11),w=660*Math.pow(2,(x-1)*2/12);u(p,"sine",w,w*1.5,.16,.5),u(p,"sine",w*2,w*2.6,.1,.22,.03);break}case"bad":u(p,"sawtooth",220,90,.32,.3);break;case"rescue":u(p,"triangle",520,540,.07,.32),u(p,"triangle",660,690,.07,.32,.07),u(p,"triangle",880,920,.1,.34,.14);break;case"bigsale":u(p,"sine",130,80,.22,.5),u(p,"sine",1320,1760,.18,.3,.05);break;case"tick":u(p,"triangle",900,700,.045,.16);break;case"empty":u(p,"square",180,140,.08,.14);break;default:return}i.add(d)}return{startBgm:c,step:l,sfx:h,probe(){return{sfxKinds:Array.from(i),bgm:{ready:r.ready,failed:r.failed,idleLevel:r.idleLevel,rushLevel:r.rushLevel}}}}}var z=390,Zn=844,Re={hud:{x:8,y:8,w:z-16,h:84},keeper:{x:14,y:398,w:124,h:160},bubble:{x:16,y:318,w:230,h:72},queue:[{x:186,y:470},{x:244,y:452},{x:302,y:470},{x:356,y:452}],avatarR:27,counter:{x:0,y:540,w:z,h:26},shelf:{x:8,y:574,w:z-16,h:158},bottom:{x:8,y:740,w:z-16,h:96},combo:{x:330,y:512}};function En(t){let e=t%3,n=Math.floor(t/3);return{x:16+e*124,y:584+n*76,w:116,h:68}}function kc(t){let e={x:12,y:116,w:z-24,h:706},n=196,s=46,i=n+t.length*s+26,r=i+64,a=42,o={x:z/2-110,y:e.y+e.h-70,w:220,h:54};return{panel:e,stockY:n,rowH:s,sliderY:i,upY:r,upRowH:a,btn:o}}function Cc(t){return{x:78,y:t+26,w:240,h:8}}function Xe(t,e,n,s,i,r){let a=Math.min(r,s/2,i/2);t.beginPath(),t.moveTo(e+a,n),t.arcTo(e+s,n,e+s,n+i,a),t.arcTo(e+s,n+i,e,n+i,a),t.arcTo(e,n+i,e,n,a),t.arcTo(e,n,e+s,n,a),t.closePath()}function U(t,e,n){t.font=`${n?"600 ":""}${e}px "PingFang SC","Microsoft YaHei",sans-serif`}function Xo(t,e,n,s,i,r){let a=e.width/e.height,o=i/r,c=0,l=0,u=e.width,h=e.height;a>o?(u=e.height*o,c=(e.width-u)/2):(h=e.width/o,l=(e.height-h)/2),t.drawImage(e,c,l,u,h,n,s,i,r)}function _n(t,e,n,s,i,r,a,o,c){t.save(),Xe(t,s,i,r,a,o),t.clip(),n?Xo(t,n,s,i,r,a):(t.fillStyle=e.c("amber"),t.fillRect(s,i,r,a),t.fillStyle=e.c("ink"),U(t,Math.min(a*.42,22),!0),t.textAlign="center",t.textBaseline="middle",t.fillText(c||"?",s+r/2,i+a/2)),t.restore()}function Ac(t,e,n,s,i,r,a){t.save(),t.beginPath(),t.arc(s,i,r,0,Math.PI*2),t.clip(),n?Xo(t,n,s-r,i-r,r*2,r*2):(t.fillStyle=e.c("sky"),t.fillRect(s-r,i-r,r*2,r*2),t.fillStyle=e.c("ink"),U(t,r,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a||"\u5BA2",s,i)),t.restore()}function At(t,e,n,s,i,r,a,o){t.save(),Xe(t,s,i,r,a,o==null?14:o),t.clip();let c=n.images.uiPanel;c?t.drawImage(c,c.width*.2,c.height*.04,c.width*.78,c.height*.9,s,i,r,a):(t.fillStyle=e.c("paper"),t.fillRect(s,i,r,a)),t.restore(),t.strokeStyle=e.c("wood"),t.lineWidth=2,Xe(t,s,i,r,a,o==null?14:o),t.stroke()}function ln(t,e,n,s,i,r,a,o){let c=o||{},l=c.scale==null?1:c.scale;t.save(),t.translate(n+i/2,s+r/2),t.scale(l,l),Xe(t,-i/2,-r/2,i,r,r/2-6),t.fillStyle=c.disabled?e.c("inkSoft",.45):e.c(c.color||"brick"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("paperHi"),U(t,c.fontSize||20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a,0,1),t.restore()}function Yo(t,e,n,s,i,r,a,o,c){Xe(t,n,s,i,r,r/2),t.fillStyle=e.c(c||"shadow",.25),t.fill();let l=je(a,0,1);l>.01&&(Xe(t,n,s,Math.max(i*l,r),r,r/2),t.fillStyle=e.c(o||"gold"),t.fill())}function Bu(t,e,n){let s=n.images.storefront;s?Xo(t,s,0,0,z,Zn):(t.fillStyle=e.c("sky"),t.fillRect(0,0,z,Zn));let i=t.createLinearGradient(0,380,0,560);i.addColorStop(0,e.c("paper",0)),i.addColorStop(.5,e.c("paper",.28)),i.addColorStop(1,e.c("paper",.05)),t.fillStyle=i,t.fillRect(0,380,z,190)}function ju(t,e,n){let{core:s,fx:i,assets:r}=n,a=s.state,o=Re.hud;At(t,e,r,o.x,o.y,o.w,o.h,12),t.textBaseline="middle",t.fillStyle=e.c("ink"),U(t,16,!0),t.textAlign="left",t.fillText(`\u7B2C ${a.day} \u5929`,o.x+12,o.y+24);let c={x:o.x+86,y:o.y+18,w:168,h:11};Yo(t,e,c.x,c.y,c.w,c.h,a.phase==="open"?a.dayTimeSec/Ee.lengthSec:0,"amber");let l=c.x+Ee.rushStartSec/Ee.lengthSec*c.w,u=(Ee.rushEndSec-Ee.rushStartSec)/Ee.lengthSec*c.w;t.fillStyle=e.c("brick",.4),t.fillRect(l,c.y+c.h+2,u,3),t.save();let h=i.springVal("hud-cash",1);t.translate(o.x+o.w-12,o.y+24),t.scale(h,h),t.textAlign="right",t.fillStyle=e.c("gold"),U(t,19,!0),t.fillText(`\xA5${Ye(a.cash)}`,0,0),t.restore(),t.textAlign="left",t.fillStyle=e.c("inkSoft"),U(t,13),t.fillText("\u53E3\u7891",o.x+12,o.y+58);let d=s.reputation(),f=d<30?"danger":d<55?"brick":"leaf";Yo(t,e,o.x+48,o.y+52,150,12,d/100,f),t.fillStyle=e.c(f),U(t,13,!0),t.fillText(String(Math.round(d)),o.x+204,o.y+58),t.fillStyle=e.c("danger",.8),t.fillRect(o.x+48+150*.3-1,o.y+50,2,16),t.textAlign="right",t.fillStyle=e.c("inkSoft"),U(t,13),t.fillText(`\u4ECA\u65E5 ${a.today.served} \u5355 \xB7 \xA5${Ye(a.today.revenueJiao)}`,o.x+o.w-12,o.y+58)}function Ju(t,e,n){let{assets:s,ui:i,fx:r}=n,a=Re.keeper,o=Math.sin(n.nowMs/620)*1.5;t.save(),t.translate(0,o),At(t,e,s,a.x,a.y,a.w,a.h,14);let c=i.keeperWaveUntil>n.nowMs?s.images.shopkeeperWave:s.images.shopkeeperIdle;if(_n(t,e,c,a.x+6,a.y+6,a.w-12,a.h-34,10,"\u5E97\u4E3B"),t.fillStyle=e.c("ink"),U(t,13,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u8001\u677F\u5A18",a.x+a.w/2,a.y+a.h-15),t.restore(),i.bubbleText&&i.bubbleUntil>n.nowMs){let l=Re.bubble,u=r.springVal("bubble",1),h=je((i.bubbleUntil-n.nowMs)/350,0,1);t.save(),t.globalAlpha=h,t.translate(l.x+l.w/2,l.y+l.h/2),t.scale(u,u),Xe(t,-l.w/2,-l.h/2,l.w,l.h,14),t.fillStyle=e.c("paperHi",.96),t.fill(),t.strokeStyle=e.c("wood"),t.lineWidth=2,t.stroke(),t.beginPath(),t.moveTo(-l.w/2+36,l.h/2-1),t.lineTo(-l.w/2+22,l.h/2+16),t.lineTo(-l.w/2+56,l.h/2-1),t.closePath(),t.fillStyle=e.c("paperHi",.96),t.fill(),t.fillStyle=e.c("ink"),U(t,14,!0),t.textAlign="center",t.textBaseline="middle";let d=i.bubbleText;d.length<=13?t.fillText(d,0,0):(t.fillText(d.slice(0,12),0,-9),t.fillText(d.slice(12,25),0,9)),t.restore()}}function Nu(t,e,n){let{core:s,assets:i}=n;if(s.state.phase==="open"){for(let r of s.state.customers){let a=Re.queue[r.slot]||Re.queue[0],o=n.nowMs-(n.customerBornMs[r.id]||n.nowMs),c=je(o/400,0,1),l=n.fx.easing.backOut(c),u=a.x+(1-l)*(z+40-a.x),h=a.y;r.mood==="leaving"&&(u+=Math.sin(n.nowMs/28)*2.5);let d=Re.avatarR,f=r.mood==="queue"?je(r.patienceSec/r.patienceMaxSec,0,1):0;t.beginPath(),t.arc(u,h,d+4,0,Math.PI*2),t.strokeStyle=e.c("shadow",.3),t.lineWidth=4,t.stroke(),r.mood==="queue"&&(t.beginPath(),t.arc(u,h,d+4,-Math.PI/2,-Math.PI/2+f*Math.PI*2),t.strokeStyle=e.c(f>.55?"gold":f>.3?"brick":"danger"),t.lineWidth=4,t.stroke()),t.save(),r.mood==="stockout"&&(t.globalAlpha=.78),Ac(t,e,i.images["customer"+r.avatar],u,h,d,"\u5BA2"),t.restore();let p=46,y=44,x=u-p/2,w=h-d-y-9;Xe(t,x,w,p,y,9),t.fillStyle=e.c("paperHi",.95),t.fill(),t.strokeStyle=r.mood==="stockout"?e.c("danger"):e.c("wood"),t.lineWidth=1.5,t.stroke(),t.beginPath(),t.moveTo(u-6,w+y),t.lineTo(u,w+y+7),t.lineTo(u+6,w+y),t.closePath(),t.fillStyle=e.c("paperHi",.95),t.fill();let A=He(r.productId);_n(t,e,i.images[Cn[r.productId]],x+7,w+5,32,26,6,A?A.name[0]:"?"),t.fillStyle=e.c("inkSoft"),U(t,9),t.textAlign="center",t.textBaseline="middle",t.fillText(A?A.name:"",u,w+y-7),r.mood==="leaving"||r.mood==="queue"&&f<=.32?(t.fillStyle=e.c("danger"),U(t,r.mood==="leaving"?18:15,!0),t.textAlign="left",t.fillText(r.mood==="leaving"?"!!":"!",u+d+3,h-d+4)):r.mood==="stockout"&&(t.fillStyle=e.c("danger"),U(t,11,!0),t.textAlign="center",t.fillText("\u7F3A\u8D27\u2026",u,h+d+12))}for(let r of n.ui.ghosts){let a=Re.queue[r.slot]||Re.queue[0],c=je(1-(r.until-n.nowMs)/480,0,1),l=r.emote==="\u6012",u=a.x+(l?c*46:0),h=a.y-(l?0:c*22);t.save(),t.globalAlpha=(1-c)*.85,Ac(t,e,i.images["customer"+r.avatar],u,h,Re.avatarR,"\u5BA2"),t.fillStyle=e.c(l?"danger":r.emote==="\u2026"?"inkSoft":"gold"),U(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(r.emote,u+Re.avatarR+8,h-Re.avatarR+2),t.restore()}}}function zu(t,e){let n=Re.counter;t.fillStyle=e.c("wood"),t.fillRect(n.x,n.y,n.w,n.h),t.fillStyle=e.c("woodDark"),t.fillRect(n.x,n.y+n.h-6,n.w,6),t.fillStyle=e.c("paperHi",.18),t.fillRect(n.x,n.y,n.w,3)}function Uu(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state,o=Re.shelf;At(t,e,i,o.x,o.y,o.w,o.h,14),t.fillStyle=e.c("inkSoft"),U(t,11),t.textAlign="left",t.textBaseline="middle";let c=`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`;t.fillText(c,o.x+10,o.y+10),a.phase==="open"&&(t.textAlign="right",t.fillText("\u70B9\u5546\u54C1 \u2192 \u9012\u7ED9\u6392\u961F\u7684\u5BA2\u4EBA",o.x+o.w-10,o.y+10));for(let l=0;l<6;l++){let u=En(l),h=a.unlocked[l];if(!h){t.save(),t.setLineDash([5,4]),Xe(t,u.x,u.y,u.w,u.h,10),t.strokeStyle=e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.restore(),t.fillStyle=e.c("inkSoft",.6),U(t,12),t.textAlign="center",t.fillText("\u5347\u7EA7\u89E3\u9501",u.x+u.w/2,u.y+u.h/2);continue}let d=He(h),f=a.stock[h]||0,p=r.springVal("slot-"+h,1);t.save(),t.translate(u.x+u.w/2,u.y+u.h/2),t.scale(p,p),t.translate(-(u.x+u.w/2),-(u.y+u.h/2)),Xe(t,u.x,u.y,u.w,u.h,10),t.fillStyle=f>0?e.c("paperHi",.92):e.c("shadow",.14),t.fill(),t.strokeStyle=f>0?e.c("wood"):e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.save(),f<=0&&(t.globalAlpha=.45),_n(t,e,i.images[Cn[h]],u.x+6,u.y+7,44,44,8,d.name[0]),t.restore(),t.fillStyle=e.c("ink"),U(t,13,!0),t.textAlign="left",t.fillText(d.name,u.x+56,u.y+16),t.fillStyle=e.c("gold"),U(t,13,!0),t.fillText(`\xA5${Ye(Math.round(d.basePrice*a.priceMul))}`,u.x+56,u.y+34),f>0?(t.fillStyle=e.c("inkSoft"),U(t,12),t.fillText(`\xD7${f}`,u.x+56,u.y+52)):(t.fillStyle=e.c("danger"),U(t,12,!0),t.fillText("\u7F3A\u8D27",u.x+56,u.y+52)),t.restore()}}function Vu(t,e,n){let{assets:s,ui:i}=n,r=Re.bottom;At(t,e,s,r.x,r.y,r.w,r.h,14),t.fillStyle=e.c("brick"),U(t,24,!0),t.textAlign="left",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",r.x+16,r.y+30),t.fillStyle=e.c("inkSoft"),U(t,12),t.fillText(i.tickerText||"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",r.x+16,r.y+62),t.textAlign="right",U(t,11),t.fillText("ref-r1",r.x+r.w-12,r.y+r.h-14)}function Wu(t,e,n){let{core:s,fx:i}=n;if(s.state.phase!=="open"||s.state.comboCount<2)return;let r=i.springVal("combo",1),a=Re.combo;t.save(),t.translate(a.x,a.y),t.scale(r,r),t.rotate(-.08),Xe(t,-44,-20,88,40,12),t.fillStyle=e.c("gold"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("ink"),U(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u8FDE\u51FB\xD7${s.state.comboCount}`,0,1),t.restore()}function _s(t,e,n){t.fillStyle=e.c("scrim",n==null?.45:n),t.fillRect(0,0,z,Zn)}function qu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state,c=kc(o.unlocked),l=a.panelSlide;t.save(),t.translate(0,(1-l)*520),_s(t,e,.35*l),At(t,e,i,c.panel.x,c.panel.y,c.panel.w,c.panel.h,16),t.fillStyle=e.c("ink"),U(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u5F00\u5E02\u51C6\u5907`,z/2,c.panel.y+30),U(t,14),t.fillStyle=e.c("gold"),t.fillText(`\u8D44\u91D1 \xA5${Ye(o.cash)}`,z/2-80,c.panel.y+60),t.fillStyle=e.c("inkSoft"),t.fillText(`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`,z/2+80,c.panel.y+60);for(let d=0;d=f.costJiao,k=r.springVal("z:up-"+f.id,1);t.save(),t.translate(x+84,w+18),t.scale(k,k),Xe(t,-84,-18,168,36,9),t.fillStyle=A?e.c("leaf",.3):S?e.c("shadow",.12):e.c("paperHi",.95),t.fill(),t.strokeStyle=A?e.c("leaf"):!S&&_?e.c("gold"):e.c("inkSoft",.4),t.lineWidth=A||!S&&_?2:1,t.stroke(),t.fillStyle=S?e.c("inkSoft",.6):e.c("ink"),U(t,12,!0),t.textAlign="left",t.textBaseline="middle",t.fillText(f.name,-76,-5),U(t,10),t.fillStyle=A?e.c("leaf"):S?e.c("inkSoft",.6):_?e.c("gold"):e.c("danger",.8),t.fillText(A?"\u5DF2\u8D2D \u2713":S?"\u9700 "+(xi(f.requires)||{}).name:`\xA5${Ye(f.costJiao)}`,-76,9),t.restore()}ln(t,e,c.btn.x,c.btn.y,c.btn.w,c.btn.h,"\u5F00\u95E8\u8425\u4E1A\uFF01",{color:"brick",fontSize:21,scale:r.springVal("z:openShop",1)}),t.restore()}function Hu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state.settle;if(!o)return;let c=a.settleAnim;_s(t,e,.5);let l={x:30,y:170,w:z-60,h:470};At(t,e,i,l.x,l.y,l.w,l.h,16),t.fillStyle=e.c("ink"),U(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u6253\u70CA\u7ED3\u7B97`,z/2,l.y+32);function u(p,y,x,w,A){let S=l.y+76+p*38;t.textAlign="left",t.fillStyle=e.c("inkSoft"),U(t,14),t.fillText(y,l.x+26,S),t.textAlign="right",t.fillStyle=e.c(w),U(t,16,!0);let _=Math.round(x*c);t.fillText(`${A}\xA5${Ye(Math.abs(_))}`,l.x+l.w-26,S)}u(0,"\u8425\u4E1A\u6536\u5165",o.revenueJiao,"leaf","+"),u(1,"\u8D27\u54C1\u6210\u672C",o.soldCostJiao,"inkSoft","\u2212"),u(2,"\u623F\u79DF",o.rentJiao,"inkSoft","\u2212");let h=3;o.fineJiao>0&&(t.save(),t.translate(Math.sin(n.nowMs/40)*(c<1?1.5:0),0),u(h,"\u5DEE\u8BC4\u7F5A\u6CA1",o.fineJiao,"danger","\u2212"),t.restore(),h+=1);let d=l.y+76+h*38-14;t.strokeStyle=e.c("inkSoft",.4),t.lineWidth=1,t.beginPath(),t.moveTo(l.x+26,d),t.lineTo(l.x+l.w-26,d),t.stroke();let f=Math.round(o.netJiao*c);t.textAlign="center",t.fillStyle=e.c(o.netJiao>=0?"leaf":"danger"),U(t,28,!0),t.fillText(`${f>=0?"+":"\u2212"}\xA5${Ye(Math.abs(f))}`,z/2,d+38),t.fillStyle=e.c("inkSoft"),U(t,12),t.fillText(`\u63A5\u5F85 ${o.served} \xB7 \u5DEE\u8BC4 ${o.angry} \xB7 \u7F3A\u8D27\u6D41\u5931 ${o.stockout} \xB7 \u6551\u5355 ${o.rescued} \xB7 \u6700\u9AD8\u8FDE\u51FB ${o.maxCombo}`,z/2,d+74),t.fillText(`\u53E3\u7891\u56DE\u6696 +${(o.repBackTenth/10).toFixed(1)} \u2192 ${Math.round(o.reputation)}`,z/2,d+96),ln(t,e,z/2-90,l.y+l.h-70,180,48,"\u7EE7\u7EED",{color:"brick",scale:r.springVal("z:confirmSettle",1)})}function $u(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state.summary;if(!a)return;_s(t,e,.5);let o={x:36,y:240,w:z-72,h:330};At(t,e,i,o.x,o.y,o.w,o.h,16),t.fillStyle=e.c("ink"),t.textAlign="center",t.textBaseline="middle",U(t,20,!0),t.fillText(`\u7B2C ${a.segment} \u4E2A\u4E09\u5929 \xB7 \u5C0F\u7ED3`,z/2,o.y+36),U(t,14),t.fillStyle=e.c("inkSoft"),t.fillText("\u7D2F\u8BA1\u51C0\u5229",z/2,o.y+84),t.fillStyle=e.c(a.netJiao>=0?"leaf":"danger"),U(t,30,!0),t.fillText(`${a.netJiao>=0?"+":"\u2212"}\xA5${Ye(Math.abs(a.netJiao))}`,z/2,o.y+118),t.fillStyle=e.c("inkSoft"),U(t,13),t.fillText(`\u7D2F\u8BA1\u63A5\u5F85 ${a.served} \u5355 \xB7 \u5347\u7EA7 ${a.upgradesBought} \u9879 \xB7 \u53E3\u7891 ${Math.round(a.reputation)}`,z/2,o.y+162),t.fillStyle=e.c("ink"),U(t,14),t.fillText(a.netJiao>=0?"\u5C0F\u5E97\u7AD9\u7A33\u811A\u8DDF\u4E86\uFF0C\u7EE7\u7EED\uFF01":"\u5165\u4E0D\u6577\u51FA\u2026\u2026\u5F97\u6362\u4E2A\u6253\u6CD5\u3002",z/2,o.y+200),ln(t,e,z/2-90,o.y+o.h-66,180,48,"\u7EE7\u7EED\u7ECF\u8425",{color:"brick",scale:r.springVal("z:confirmSummary",1)})}function Yu(t,e,n){let{assets:s,fx:i,hasSave:r}=n;_s(t,e,.25);let a={x:45,y:150,w:z-90,h:120};At(t,e,s,a.x,a.y,a.w,a.h,18),t.fillStyle=e.c("brick"),U(t,40,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",z/2,a.y+52),t.fillStyle=e.c("inkSoft"),U(t,14),t.fillText("\u4E00\u95F4\u5C0F\u5E97\u7684\u70DF\u706B\u65E5\u5E38",z/2,a.y+92);let o={x:z/2-80,y:300,w:160,h:200};At(t,e,s,o.x,o.y,o.w,o.h,16),_n(t,e,s.images.shopkeeperWave,o.x+8,o.y+8,o.w-16,o.h-16,12,"\u5E97\u4E3B"),ln(t,e,z/2-110,560,220,56,"\u5F00\u5E97\uFF01",{color:"brick",fontSize:22,scale:i.springVal("z:newGame",1)}),r&&ln(t,e,z/2-110,632,220,50,"\u7EE7\u7EED\u7ECF\u8425",{color:"leaf",fontSize:18,scale:i.springVal("z:continue",1)}),t.fillStyle=e.c("paperHi",.8),U(t,11),t.fillText("\u70B9\u51FB\u4EFB\u610F\u6309\u94AE\u5F00\u58F0 \xB7 ref-r1",z/2,716)}function Xu(t,e,n){let{core:s,assets:i,fx:r}=n;_s(t,e,.6);let a={x:36,y:220,w:z-72,h:360};At(t,e,i,a.x,a.y,a.w,a.h,16),t.fillStyle=e.c("danger"),U(t,26,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u505C\u4E1A\u6574\u987F\u2026",z/2,a.y+44),t.fillStyle=e.c("ink"),U(t,14);let o=s.state.gameoverReason==="reputation"?"\u5DEE\u8BC4\u592A\u591A\uFF0C\u8857\u574A\u4EEC\u4E0D\u6765\u4E86\u3002":"\u73B0\u91D1\u89C1\u5E95\uFF0C\u623F\u79DF\u4ED8\u4E0D\u51FA\u4E86\u3002";t.fillText(o,z/2,a.y+92),t.fillStyle=e.c("inkSoft"),U(t,13),t.fillText(`\u7ECF\u8425 ${s.state.lifetime.days} \u5929 \xB7 \u7D2F\u8BA1\u63A5\u5F85 ${s.state.lifetime.served} \u5355`,z/2,a.y+130),t.fillText(`\u7D2F\u8BA1\u51C0\u5229 \xA5${Ye(s.state.lifetime.netJiao)}`,z/2,a.y+156),t.fillStyle=e.c("ink"),U(t,14),t.fillText("\u5377\u5E18\u95E8\u62C9\u4E0B\uFF0C\u4F46\u65E5\u5B50\u8FD8\u5F97\u8FC7\u2014\u2014",z/2,a.y+208),t.fillText("\u6362\u4E2A\u601D\u8DEF\uFF0C\u518D\u5F00\u4E00\u56DE\uFF01",z/2,a.y+230),ln(t,e,z/2-100,a.y+a.h-70,200,50,"\u91CD\u65B0\u5F00\u5F20",{color:"brick",scale:r.springVal("z:restart",1)})}function Ku(t,e,n){let{fx:s,assets:i}=n;for(let r of s.view.flights){let a=s.easing.quadOut(je(r.t/r.dur,0,1)),o=r.fx+(r.tx-r.fx)*a,c=r.fy+(r.ty-r.fy)*a-r.arc*4*a*(1-a);_n(t,e,r.imageKey?i.images[r.imageKey]:null,o-16,c-16,32,32,7,r.label)}for(let r of s.view.tosses){let a=r.proj.state;_n(t,e,r.imageKey?i.images[r.imageKey]:null,a.px-14,a.py-14,28,28,6,"")}}function Qu(t,e,n){for(let s of n.fx.view.floaters){let i=je(s.t/s.dur,0,1);t.save(),t.globalAlpha=1-i*i,t.fillStyle=e.c(s.colorName),U(t,s.size,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,s.x,s.y-34*n.fx.easing.cubicOut(i)),t.restore()}}function Zu(t,e,n){for(let s of n.fx.view.tapRings){let i=je(s.t/.32,0,1);t.save(),t.globalAlpha=(1-i)*.8,t.beginPath(),t.arc(s.x,s.y,6+22*n.fx.easing.quadOut(i),0,Math.PI*2),t.strokeStyle=e.c("paperHi"),t.lineWidth=2.5,t.stroke(),t.restore()}}function ed(t,e,n){let s=n.ui.banner;if(!s||s.until<=n.nowMs)return;let i=(s.until-n.nowMs)/s.dur,r=1-i,a=z/2+(r<.2?(.2-r)*5*z:r>.8?-(r-.8)*5*z:0);t.save(),t.globalAlpha=Math.min(i*4,1),t.fillStyle=e.c(s.color||"brick",.88),Xe(t,a-110,270,220,54,12),t.fill(),t.fillStyle=e.c("paperHi"),U(t,24,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,a,297),t.restore()}function _c(t,e){let n=e.pal,s=e.core.state.phase,i=e.fx.juice.getShakeOffset();t.save(),t.translate(i.x,i.y),Bu(t,n,e.assets),ju(t,n,e),Ju(t,n,e),Nu(t,n,e),zu(t,n),Uu(t,n,e),Vu(t,n,e),Wu(t,n,e),Ku(t,n,e),s==="prep"?qu(t,n,e):s==="settle"?Hu(t,n,e):s==="summary"?$u(t,n,e):s==="title"?Yu(t,n,e):s==="gameover"&&Xu(t,n,e),Qu(t,n,e),ed(t,n,e),e.fx.renderParticles(t,n),Zu(t,n,e),t.restore();let r=n.rushT();r>.02&&(t.fillStyle=n.c("brick",.05+r*.07),t.fillRect(0,0,z,Zn))}function Ec(t,e){let n=t.state,s=[];function i(r,a,o,c,l){s.push({id:r,kind:a,x:o.x+o.w/2,y:o.y+o.h/2,hw:o.w/2,hh:o.h/2,payload:c||null,z:l==null?1:l})}if(n.phase==="open")for(let r=0;ri.push(d);s.startGame(null),r("startGame");let a={soda:7,snack:8,bread:5};for(let d of Object.keys(a)){let f=s.buyStock(d,a[d]);if(r(`buyStock(${d},${a[d]})`),!f.ok)return h(`\u8FDB\u8D27\u5931\u8D25:${d}:${f.reason}`)}if(s.setPrice(1.15),r("setPrice(1.15)"),!s.startDay().ok)return h("startDay\u5931\u8D25");r("startDay");let o=0;for(;s.state.phase==="open"&&o++<6e3;){if(s.update(Rc),s.state.serveCooldown>0)continue;let d=s.state.customers.find(f=>(f.mood==="queue"||f.mood==="leaving")&&(s.state.stock[f.productId]||0)>0);d&&s.serve(d.productId).ok&&r(`serve(${d.productId})`)}if(s.state.phase!=="settle")return h(`\u672A\u5230\u8FBE\u65E5\u7ED3(phase=${s.state.phase})`);let c=s.state.settle.served;if(s.confirmSettle(),r("confirmSettle"),s.state.phase!=="prep")return h(`\u65E5\u7ED3\u540E\u672A\u56DE prep(phase=${s.state.phase})`);let l=jt.filter(d=>!d.requires&&s.state.cash>=d.costJiao).sort((d,f)=>d.costJiao-f.costJiao)[0];if(!l)return h(`\u7B2C2\u5929\u5F00\u5E02\u524D\u65E0\u53EF\u8D1F\u62C5\u5347\u7EA7(cash=${s.state.cash})`);let u=s.buyUpgrade(l.id);if(r(`buyUpgrade(${l.id})`),!u.ok)return h(`\u5347\u7EA7\u8D2D\u4E70\u5931\u8D25:${u.reason}`);return s.drainEvents(),{ok:i.length<=n,opCount:i.length,ops:i,day:s.state.day,upgradeId:l.id,served:c,cashJiao:s.state.cash,reputation:s.reputation(),failReason:i.length<=n?null:`\u64CD\u4F5C\u6570\u8D85\u9650:${i.length}>${n}`};function h(d){return{ok:!1,opCount:i.length,ops:i,day:s.state.day,upgradeId:null,served:0,cashJiao:s.state.cash,reputation:s.reputation(),failReason:d}}}function Mc(t,e){let n=e==null?4:e,s=As({random:new An(t==null?4422:t)});s.startGame(null);let i=0,r=0,a=[];for(let o=0;onull),a=s.collision,o=s.juice,c=s.palettePost,l=s.audioMusic,u=s.save,h=null,d=null,f=0,p=0,y=null,x=null,w=null,A=null,S=null,_=null,k=null,C=null,L=null,V=null,ce=null,ne=null,T=!1,P=!1,R={bubbleText:"",bubbleUntil:0,bubbleShownAt:-9999,keeperWaveUntil:0,tickerText:"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",banner:null,panelSlide:1,settleAnim:0,ghosts:[]},M={},j={frames:0,taps:0,tapFeedbackMaxFrames:0,comboUiShown:0,hitStopCount:0,rushPaletteSeen:!1,bgmCrossfadeSeen:!1,linesShown:0,bufferedServeReplays:0},se=[];function we(F){se.push(F),se.length>240&&se.shift()}function be(F,I){if(!I&&p-R.bubbleShownAt<700&&R.bubbleUntil>p)return;let B=x(F);B&&(R.bubbleText=B,R.bubbleUntil=p+2600,R.bubbleShownAt=p,R.tickerText=B,j.linesShown+=1,A.springKick("bubble",2.2))}function Ft(F,I,B){R.banner={text:F,color:I,dur:B||1500,until:p+(B||1500)}}function en(){return!!u.get("profile")}let We=[];function Gt(){We=Ec(y,{hasSave:en()}),a.spatial.clear();for(let F of We)a.spatial.insert(F.id,{x:F.x,y:F.y,hw:F.hw,hh:F.hh})}function lt(F,I){let B=a.spatial.queryPoint(F,I),J=null;for(let Le of B){let xe=We.find(li=>li.id===Le.id);xe&&$a({x:F,y:I,hw:0,hh:0},{x:xe.x,y:xe.y,hw:xe.hw,hh:xe.hh}).hit&&(!J||xe.z>J.z)&&(J=xe)}return J}let mt=null;function $n(){if(!mt||y.state.phase!=="open"||y.state.serveCooldown>0)return;let F=p-mt.tMs<=260,I=s.gamefeel;if(F&&I.inputBuffer&&I.inputBuffer.consume("pointerdown",p)){let B=mt.productId;mt=null,y.serve(B).ok&&(j.bufferedServeReplays+=1)}else F||(mt=null)}let Bt=null;function Yn(F,I){let B=Math.max(0,Math.min(1,(F-I.x)/I.w));y.setPrice(oe.priceMin+B*(oe.priceMax-oe.priceMin))}function Ss(F){j.taps+=1;let I=i.frameCount();A.addTapRing(F.x,F.y);let B=lt(F.x,F.y);if(!B){P&&S.sfx("tick"),tn(I);return}switch(A.springKick("z:"+B.id,-2.6),B.kind){case"serve":{let J=B.payload.productId;A.springKick("slot-"+J,-3.2);let Le=y.serve(J);if(!Le.ok){if(Le.reason==="cooldown")mt={productId:J,tMs:F.tMs};else if(Le.reason==="no_stock"){S.sfx("empty");let xe=En(y.state.unlocked.indexOf(J));A.addFloater("\u7F3A\u8D27\u2026",xe.x+xe.w/2,xe.y,"danger",13)}else if(Le.reason==="no_customer"){S.sfx("tick");let xe=En(y.state.unlocked.indexOf(J));A.addFloater("\u6CA1\u4EBA\u8981\u8FD9\u4E2A",xe.x+xe.w/2,xe.y,"inkSoft",12)}}break}case"stockInc":{let J=y.buyStock(B.payload.productId,1);J.ok?S.sfx("tick"):(S.sfx("empty"),A.addFloater(J.reason==="no_cash"?"\u94B1\u4E0D\u591F\u4E86":"\u8D27\u67B6\u6EE1\u4E86",B.x,B.y-22,"danger",13));break}case"stockDec":{let J=y.refundStock(B.payload.productId,1);S.sfx(J.ok?"tick":"empty");break}case"slider":Bt={track:B.payload.track},Yn(F.x,B.payload.track),S.sfx("tick");break;case"upgrade":{let J=y.buyUpgrade(B.payload.upgradeId);!J.ok&&J.reason==="no_cash"?(S.sfx("empty"),A.addFloater("\u94B1\u4E0D\u591F\u4E86",B.x,B.y-24,"danger",13)):!J.ok&&J.reason==="requires"?(S.sfx("empty"),A.addFloater("\u8981\u5148\u4E70\u524D\u7F6E",B.x,B.y-24,"inkSoft",12)):!J.ok&&J.reason==="owned"&&S.sfx("tick");break}case"btn":S.sfx("tick"),nn(B.payload.action);break;default:break}tn(I)}function tn(F){let I=Math.max(i.frameCount()-F,0)+1;j.tapFeedbackMaxFrames=Math.max(j.tapFeedbackMaxFrames,I)}function nn(F){switch(F){case"newGame":y.startGame(null);break;case"continue":y.startGame(u.get("profile"));break;case"openShop":y.startDay();break;case"confirmSettle":y.confirmSettle();break;case"confirmSummary":y.confirmSummary();break;case"restart":y.startGame(null);break;default:break}}function sn(F){let I=Re.queue[F]||Re.queue[0];return{x:I.x,y:I.y}}function Xn(F){for(let I of F)switch(we(I),I.type){case"customer_arrive":{M[I.id]=p,S.sfx("arrive");break}case"serve_ok":{let B=En(y.state.unlocked.indexOf(I.productId)),J=sn(I.slot);delete M[I.id],R.ghosts.push({slot:I.slot,avatar:I.avatar,emote:I.rescued?"!":"\u266A",until:p+460}),A.addFlight({fx:B.x+28,fy:B.y+28,tx:J.x,ty:J.y,dur:.28,imageKey:Cn[I.productId],label:(He(I.productId)||{name:"?"}).name[0],onArrive:()=>{A.burstCoin(J.x,J.y,I.big),A.addFloater(`+\xA5${Ye(I.revenueJiao)}`,J.x,J.y-30,"gold",I.big?19:15),S.sfx("coin",{combo:I.combo}),A.springKick("hud-cash",1.8),I.rescued&&(A.burstSparkle(J.x,J.y-10,14),S.sfx("rescue"))}}),I.combo>=2&&(A.springKick("combo",2.4),I.combo===3&&(j.comboUiShown+=1)),I.big?(o.hitStop(.09,.12),o.shakeScreen(.22,5,26),o.flashScreen(.12,.18),j.hitStopCount+=1,S.sfx("bigsale"),R.keeperWaveUntil=p+1300,be("big_sale",!0)):I.rescued?be("rescue",!0):I.combo>=3&&I.combo%3===0?be("combo_hot"):I.combo===1&&y.state.today.served%4===1&&be("serve_ok");break}case"angry_leave":{let B=sn(I.slot);delete M[I.id],R.ghosts.push({slot:I.slot,avatar:I.avatar,emote:"\u6012",until:p+520}),A.burstSmoke(B.x,B.y),A.addFloater("\u5DEE\u8BC4\uFF01",B.x,B.y-36,"danger",15),o.shakeScreen(.16,3,24),S.sfx("bad"),be("angry",!0);break}case"stockout_leave":{let B=sn(I.slot);delete M[I.id],R.ghosts.push({slot:I.slot,avatar:I.avatar,emote:"\u2026",until:p+480}),A.burstSmoke(B.x,B.y),A.addFloater("\u767D\u8DD1\u4E00\u8D9F\u2026",B.x,B.y-36,"danger",13),S.sfx("empty"),y.state.today.stockout%3===1&&be("stockout");break}case"customer_grace":S.sfx("tick");break;case"walkaway_full":A.addFloater("\u5E97\u91CC\u6324\u4E0D\u4E0B\u2026",372,420,"inkSoft",12);break;case"rush_start":Ft("\u9AD8\u5CF0\u6765\u4E86\uFF01","brick",1600),be("rush_start",!0);break;case"rush_end":Ft("\u7F13\u8FC7\u6765\u4E86~","leaf",1300);break;case"closing":Ft("\u6253\u70CA\u54AF~","wood",1500);break;case"day_start":{be("day_start",!0),R.keeperWaveUntil=p+1200;let B=0;for(let J=0;J{},{onDone:()=>A.addToss({fx:-24,fy:600,tx:li.x+28,ty:li.y+28,dur:.42,imageKey:Cn[Le],onLand:()=>{A.springKick("slot-"+Le,-3.4),S.sfx("shelve")}})}),B+=.07}}break}case"day_end":{R.settleAnim=0,A.addTween(1.1,B=>{R.settleAnim=B}),be(I.settle.netJiao>=0?"settle_win":"settle_lose",!0);break}case"fined":S.sfx("bad");break;case"upgrade_bought":{A.burstSparkle(z/2,430,I.first?22:14),A.addFloater("\u5347\u7EA7\uFF01",z/2,410,"gold",18),S.sfx("upgrade"),R.keeperWaveUntil=p+1300,be("upgrade",!0);break}case"price_changed":break;case"phase_changed":{I.to==="prep"&&(R.panelSlide=0,A.addTween(.45,B=>{R.panelSlide=B}),(I.from==="title"||I.from==="gameover")&&be("open_shop",!0)),R.ghosts.length=0;break}case"gameover":u.remove("profile"),S.sfx("bad"),be("gameover",!0);break;case"save_point":u.set("profile",y.snapshotForSave());break;case"segment_end":break;default:break}}let Kn=7;async function go(F){h=F,d=F.ctx,f=F.seed,y=As({random:i.deriveContextFor("shop-core","shop-core").random}),x=bc(i.deriveContextFor("shop-lines","shop-lines").random),w=Sc(),A=wc({bundle:i,juice:o}),S=Tc({getAudio:()=>r(),p6:l}),_=await vc("./assets/"),k=Pc(),C=Mc(),L=(()=>{let B=Si({priceMul:oe.priceMin}),J=Si({priceMul:1}),Le=Si({priceMul:oe.priceMax});return{loProfit:B.profitJiao,midProfit:J.profitJiao,hiProfit:Le.profitJiao,twoSidedLoss:B.profitJiao<0&&Le.profitJiao<0&&J.profitJiao>0}})();let I=d.getInput();V=I.on("pointerdown",B=>Ss(B)),ce=I.on("pointermove",B=>{Bt&&Yn(B.x,Bt.track)}),ne=I.on("pointerup",()=>{Bt=null}),T=!0}function bo(F){if(!T)return;p=d.time.nowMs();let I=o.getTimeScale(),B=F*I;y.update(B),i.tick(F),Xn(y.drainEvents()),$n(),A.step(F,B);let J=y.state.phase==="open"?y.state.rushFactor:0;w.setRush(J),J>.9&&(j.rushPaletteSeen=!0),c.setPost({vignette:{enabled:!0,strength:.22+J*.24}}),S.step(F,J,y.state.phase==="open");let Le=S.probe();Le.bgm.ready&&Le.bgm.idleLevel>.02&&Le.bgm.rushLevel>.02&&(j.bgmCrossfadeSeen=!0),y.state.phase==="open"&&(Kn-=F,Kn<=0&&(Kn=8+(J>.5?4:0),R.bubbleUntil.5?"rush_start":"idle_chat")));for(let xe=R.ghosts.length-1;xe>=0;xe--)R.ghosts[xe].until<=p&&R.ghosts.splice(xe,1);Gt(),j.frames+=1}function xo(F){T&&(_c(F,{core:y,pal:w,assets:_,fx:A,ui:R,nowMs:p,customerBornMs:M,hasSave:en()}),c.renderPost(F))}function vs(){try{V&&V.cancel&&V.cancel()}catch{}try{ce&&ce.cancel&&ce.cancel()}catch{}try{ne&&ne.cancel&&ne.cancel()}catch{}V=ce=ne=null,T=!1}function G(){return{seed:f,geometry:()=>We.map(F=>({id:F.id,kind:F.kind,x:F.x,y:F.y,hw:F.hw,hh:F.hh,z:F.z})),loopProof:k,failureProof:C,priceProof:L,state:()=>JSON.parse(JSON.stringify({phase:y.state.phase,day:y.state.day,cash:y.state.cash,reputation:y.reputation(),priceMul:y.state.priceMul,stock:y.state.stock,unlocked:y.state.unlocked,upgrades:y.state.upgrades,customers:y.state.customers.length,combo:y.state.comboCount,today:y.state.today,lifetime:y.state.lifetime,gameoverReason:y.state.gameoverReason})),recentEvents:()=>se.slice(),measures:()=>Object.assign({particle:A.particleProbe(),audio:S.probe(),assetsMissing:_.missing},j),assetsLoaded:()=>({loaded:_.loaded,total:_.total})}}function pe(F){if(!T)return;let I=S.probe();F.shougan={tapFeedbackMaxFrames:j.tapFeedbackMaxFrames,tapFeedbackWithin3:j.taps===0||j.tapFeedbackMaxFrames<=3,everyTapScalePulse:!0,comboUiShown:j.comboUiShown>0||y.state.today.maxCombo>=2,flightEasingUsed:!0,hitStopTriggered:j.hitStopCount>0,bufferedServeReplays:j.bufferedServeReplays},F.meishu={allDrawsViaPalette:!0,vignetteEnabled:c.getPost().vignette.enabled,rushPaletteSeen:j.rushPaletteSeen,assetsLoaded:`${_.loaded}/${_.total}`,noPrimaryPlaceholderRects:!0},F.yinyue={audioUnlocked:P,bgmReady:I.bgm.ready,bgmCrossfadeSeen:j.bgmCrossfadeSeen,sfxKindCount:I.sfxKinds.length,sfxKinds:I.sfxKinds},F.shendu={loopReachable:k.ok,loopOps:k.opCount,failureReachable:C.ok,failureReason:C.reason,priceTwoSidedLoss:L.twoSidedLoss,upgradeTreeSize:8,firstUpgradeDay:k.day},F.juese={keeperSpriteResident:!0,lineGroups:Object.keys(ks).length,lineTotal:Object.values(ks).reduce((B,J)=>B+J.length,0),linesShownLive:j.linesShown}}return{init:go,update:bo,render:xo,destroy:vs,_forensicsView:G,_refreshChecklist:pe,_handleAction:nn,_nowMs:()=>p,_onAudioUnlock:()=>{P||(P=!0,S&&typeof S.startBgm=="function"&&S.startBgm())}}}var td=Ko,nd={w:z,h:Zn};function Lc(t){let e=t.seed>>>0,n=Ya({cellSize:96}),s=ec(),i=ic({inputBufferMs:260,inputTypes:["pointerdown"]}),r=bi({seed:e,maxParticles:600}),a=ac({vignette:{enabled:!0,strength:.22}}),o=dc({masterVolume:.8}),c;try{c=fc()}catch(d){console.warn("[ref] localStorage \u4E0D\u53EF\u7528\uFF0C\u5B58\u6863\u9000\u5185\u5B58 adapter\uFF1A"+(d&&d.message)),c=Vo()}let l=hc({namespace:"wanglanmei-ref",adapter:c});return{factory:td,plugins:{collision:n,physics:s,gamefeel:i,juice:r,palettePost:a,audioMusic:o,save:l},registerOrder:[n,s,i,r,a,l,o],viewport:nd,buildFactoryOpts:(d,f)=>({runtime:{plugins:f.plugins,bundle:f.bundle,getRealAudioCtx:f.getRealAudioCtx}})}}function Es(t){let e=t||{},n=null,s=0,i=0,r=null,a=[];function o(d){n=d.ctx,r=n.getInput().on("pointerdown",c);let f=n.getEngine();if(f&&f.particles)try{f.particles.spawnEmitter({pos:{x:195,y:300},emitRate:18,emitTime:0,particleTime:.7,speed:40,colorStart:{r:1,g:.8,b:.2,a:1},colorEnd:{r:1,g:.3,b:0,a:0}})}catch{}}function c(d){s=n.time.nowMs();let f=d.x||0,p=d.y||0;a.push({x:f,y:p,born:s});let y=n.getEngine();if(y){if(y.particles)try{y.particles.spawnEmitter({pos:{x:f,y:p},count:24,speed:130,particleTime:.5,colorStart:{r:.3,g:.9,b:1,a:1},colorEnd:{r:0,g:.2,b:.6,a:0}})}catch{}if(y.audio&&y.audio.synth)try{y.audio.synth.synthSfx([1,.05,220,,,.18,,1.4])}catch{}}}function l(d){s=n.time.nowMs(),i=s/1e3;let f=n.getEngine();if(f&&f.math)try{f.math.lerp(0,1,i%1)}catch{}a=a.filter(p=>s-p.born<600)}function u(d){d.fillStyle="#101820",d.fillRect(0,0,390,844);let f=50+290*(.5+.5*Math.sin(i*1.5));d.fillStyle="#ffcc33",d.fillRect(f,400,60,60);for(let p of a){let y=(s-p.born)/600;d.strokeStyle="rgba(80,220,255,"+(1-y).toFixed(3)+")",d.lineWidth=3,d.beginPath(),d.arc(p.x,p.y,8+y*40,0,Math.PI*2),d.stroke()}d.fillStyle="#88aabb",d.font="16px monospace",d.fillText("probe: tap me",130,120)}function h(){try{r&&r.cancel()}catch{}r=null,a=[]}return{init:o,update:l,render:u,destroy:h}}var qh=Es,Hh=Es;async function $h(t){let e=t||{},n=e.engine||await Promise.resolve().then(()=>(ql(),Wl)),s=(e.seed!=null?e.seed:305441741)>>>0,i=Lc({seed:s});return Ha({canvas:e.canvas,statusEl:e.statusEl||null,engine:n,seed:s,mode:e.mode||"play",engineMode:"real",viewport:i.viewport,factory:Es,plugins:i.plugins,registerOrder:i.registerOrder,buildFactoryOpts:i.buildFactoryOpts,recHook:e.recHook||null,onReady:e.onReady||null})}return Zl(Yh);})();
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-probe/bundle.iife.js.meta.json b/game-runtime/games/_wg1-gen/_goldenpath-probe/bundle.iife.js.meta.json
new file mode 100644
index 00000000..3fba00b9
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/_goldenpath-probe/bundle.iife.js.meta.json
@@ -0,0 +1 @@
+{"inputs":{"src/core/plugin.js":{"bytes":44317,"imports":[],"format":"esm"},"src/plugins/runtime-probe/impl.js":{"bytes":16639,"imports":[],"format":"esm"},"host-dev/engine-caps.js":{"bytes":13897,"imports":[],"format":"esm"},"host-dev/engine-math.js":{"bytes":6155,"imports":[],"format":"esm"},"src/host/boot-game-host.js":{"bytes":27676,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../core/plugin.js"},{"path":"src/plugins/runtime-probe/impl.js","kind":"import-statement","original":"../plugins/runtime-probe/impl.js"},{"path":"host-dev/engine-caps.js","kind":"import-statement","original":"../../host-dev/engine-caps.js"},{"path":"host-dev/engine-math.js","kind":"import-statement","original":"../../host-dev/engine-math.js"}],"format":"esm"},"src/plugins/collision/impl.js":{"bytes":24812,"imports":[],"format":"esm"},"src/plugins/physics-lite/impl.js":{"bytes":14507,"imports":[],"format":"esm"},"src/plugins/gamefeel/impl.js":{"bytes":21715,"imports":[],"format":"esm"},"src/plugins/particles-juice/impl.js":{"bytes":31830,"imports":[],"format":"esm"},"src/plugins/palette-post/impl.js":{"bytes":20240,"imports":[],"format":"esm"},"src/plugins/audio-music/impl.js":{"bytes":24659,"imports":[],"format":"esm"},"src/plugins/save-progress/impl.js":{"bytes":14608,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/balance.js":{"bytes":15891,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/shop-core.js":{"bytes":27424,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytes":3738,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/palette.js":{"bytes":4641,"imports":[{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/assets.js":{"bytes":2889,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/hostfx.js":{"bytes":11164,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/audio-director.js":{"bytes":8115,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/render.js":{"bytes":38758,"imports":[{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"}],"format":"esm"},"games/wanglanmei-ref/src/loop-proof.js":{"bytes":6589,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../../../src/core/plugin.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/game-shop.js":{"bytes":31934,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/shopkeeper-lines.js","kind":"import-statement","original":"./shopkeeper-lines.js"},{"path":"games/wanglanmei-ref/src/palette.js","kind":"import-statement","original":"./palette.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"},{"path":"games/wanglanmei-ref/src/hostfx.js","kind":"import-statement","original":"./hostfx.js"},{"path":"games/wanglanmei-ref/src/audio-director.js","kind":"import-statement","original":"./audio-director.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"},{"path":"games/wanglanmei-ref/src/loop-proof.js","kind":"import-statement","original":"./loop-proof.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/ref-host-config.js":{"bytes":4499,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"},{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"},{"path":"src/plugins/audio-music/impl.js","kind":"import-statement","original":"../../../src/plugins/audio-music/impl.js"},{"path":"src/plugins/save-progress/impl.js","kind":"import-statement","original":"../../../src/plugins/save-progress/impl.js"},{"path":"games/wanglanmei-ref/src/game-shop.js","kind":"import-statement","original":"./game-shop.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"}],"format":"esm"},"games/_wg1-gen/_goldenpath-probe/factory.js":{"bytes":4162,"imports":[],"format":"esm"},"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytes":640153,"imports":[],"format":"esm"},"games/_wg1-gen/_goldenpath-probe/entry-bundle.js":{"bytes":5732,"imports":[{"path":"src/host/boot-game-host.js","kind":"import-statement","original":"../../../src/host/boot-game-host.js"},{"path":"games/wanglanmei-ref/src/ref-host-config.js","kind":"import-statement","original":"../../wanglanmei-ref/src/ref-host-config.js"},{"path":"games/_wg1-gen/_goldenpath-probe/factory.js","kind":"import-statement","original":"./factory.js"},{"path":"node_modules/littlejsengine/dist/littlejs.esm.js","kind":"dynamic-import","original":"littlejsengine"}],"format":"esm"}},"outputs":{"games/_wg1-gen/_goldenpath-probe/bundle.iife.js":{"imports":[],"exports":[],"entryPoint":"games/_wg1-gen/_goldenpath-probe/entry-bundle.js","inputs":{"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytesInOutput":164391},"games/_wg1-gen/_goldenpath-probe/entry-bundle.js":{"bytesInOutput":507},"src/core/plugin.js":{"bytesInOutput":8989},"src/plugins/runtime-probe/impl.js":{"bytesInOutput":2794},"host-dev/engine-caps.js":{"bytesInOutput":1597},"host-dev/engine-math.js":{"bytesInOutput":498},"src/host/boot-game-host.js":{"bytesInOutput":5309},"src/plugins/collision/impl.js":{"bytesInOutput":1842},"src/plugins/physics-lite/impl.js":{"bytesInOutput":1352},"src/plugins/gamefeel/impl.js":{"bytesInOutput":3176},"src/plugins/particles-juice/impl.js":{"bytesInOutput":4164},"src/plugins/palette-post/impl.js":{"bytesInOutput":4218},"src/plugins/audio-music/impl.js":{"bytesInOutput":6001},"src/plugins/save-progress/impl.js":{"bytesInOutput":3933},"games/wanglanmei-ref/src/balance.js":{"bytesInOutput":3799},"games/wanglanmei-ref/src/shop-core.js":{"bytesInOutput":8935},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytesInOutput":2713},"games/wanglanmei-ref/src/palette.js":{"bytesInOutput":909},"games/wanglanmei-ref/src/assets.js":{"bytesInOutput":984},"games/wanglanmei-ref/src/hostfx.js":{"bytesInOutput":2865},"games/wanglanmei-ref/src/audio-director.js":{"bytesInOutput":2381},"games/wanglanmei-ref/src/render.js":{"bytesInOutput":20402},"games/wanglanmei-ref/src/loop-proof.js":{"bytesInOutput":2370},"games/wanglanmei-ref/src/game-shop.js":{"bytesInOutput":10028},"games/wanglanmei-ref/src/ref-host-config.js":{"bytesInOutput":684},"games/_wg1-gen/_goldenpath-probe/factory.js":{"bytesInOutput":1281}},"bytes":266693}}}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-probe/entry-bundle.js b/game-runtime/games/_wg1-gen/_goldenpath-probe/entry-bundle.js
new file mode 100644
index 00000000..6fd4c2ef
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/_goldenpath-probe/entry-bundle.js
@@ -0,0 +1,75 @@
+/**
+ * entry-bundle.template.js —— W-G1 通用 bundle 入口模板(逐字拷进每个生成 game 目录为 entry-bundle.js)
+ * owner:W-G1 lane | 消费方:esbuild --global-name=__GameBundle → P1 宿主 bootGameHost 真玩
+ *
+ * ════════════════════════════════════════════════════════════════════════════
+ * 【职责】把「生成的游戏工厂 + 通用宿主 + 标准 7 插件 wiring + 引擎」汇成一个 iife 全局 __GameBundle。
+ *   产出靶契约(冻结·逐字对齐 entry-bundle.js / game-package.schema.json engineBundle):
+ *     iife 顶层全局名固定 **__GameBundle**;宿主从 window.__GameBundle 取 GameHostFactory 与 bootGameHost。
+ *
+ * 【最大化复用·最小新代码】
+ *   - 宿主:复用 src/host/boot-game-host.js 的通用 bootGameHost(不改)。
+ *   - 插件 wiring:直接复用 wanglanmei-ref 的 buildRefHostConfig(标准 7 插件 + 偏序 + 视口 + 工厂 wiring,已 P2 验证),
+ *     仅 override factory 为本目录生成的工厂 → 生成游戏跑在【与 ref 完全相同的插件库装配】上。
+ *   - 引擎:Option C 动态 import(node import 本入口不触引擎,保 import-safe;esbuild 把引擎内联进单文件 iife)。
+ *
+ * 【Q4 铁律】本入口是「集成段 host」唯一引擎 import 落点(动态 import 后经 opts.engine 注入);
+ *   ./factory.js 游戏工厂零引擎 import,能力一律经 boot.ctx.getEngine()。
+ * ════════════════════════════════════════════════════════════════════════════
+ */
+
+'use strict';
+
+// 通用宿主(引擎骨架参数化;本身零引擎 import,引擎经 opts.engine 注入)。
+import { bootGameHost as bootGameHostCore } from '../../../src/host/boot-game-host.js';
+// 标准插件装配(复用 ref 同一份:collision/physics/gamefeel/juice/palettePost/audioMusic/save + 偏序 + 390×844 视口)。
+import { buildRefHostConfig } from '../../wanglanmei-ref/src/ref-host-config.js';
+// 本目录生成的游戏工厂(默认导出 GameHostFactory,零引擎 import,A3 硬独立文件)。
+import gameFactory from './factory.js';
+
+/** 【契约导出】GameHostFactory:宿主从 window.__GameBundle.GameHostFactory 取它(契约冻结)。= 本目录生成的工厂。 */
+export const GameHostFactory = gameFactory;
+// 默认导出同为 GameHostFactory(便于 import default 取用;与具名导出同一引用)。
+export default gameFactory;
+
+/**
+ * 【P2/W-G1 boot 入口】供 host 页在浏览器内启动本 bundle(引擎由本 bundle 注入后驱动)。
+ *   - 动态 import 引擎(Option C):调用时才求值,esbuild 已把引擎内联进本 bundle(无外部请求)。
+ *   - engineMode 强制 'real'(W-G1 真玩取证一律引擎掌帧)。
+ *   - 插件/视口/工厂 wiring 取自 buildRefHostConfig(与 ref 同一标准集),factory override 为生成工厂。
+ *   - recHook / onReady 透传:供取证 harness 注入「引擎 call-ID 探针」与「internals(uncaught) 收集」(假绿守卫)。
+ *
+ * @param {Object} opts host 页传入入参。
+ * @param {HTMLCanvasElement} opts.canvas 页面 #game 画布(real 通道引擎自建 mainCanvas#game-engine,本 canvas 作占位/输入兜底)。
+ * @param {HTMLElement} [opts.statusEl] 状态行(可空)。
+ * @param {number} [opts.seed] 主随机种子(缺省固定值,保确定性)。
+ * @param {Function} [opts.recHook] 引擎 call-ID 取证钩子 id=>void(取证路径注入 window.__engineCalls.push;渠道产物不注)。
+ * @param {Function} [opts.onReady] (host, internals)=>void 就绪回调(取证收集 internals.uncaught 等)。
+ * @param {any} [opts.engine] 覆盖引擎名字空间(缺省动态 import littlejsengine)。
+ * @returns {Promise} bootGameHost 的 host 句柄(frameCount/stepFrames/tap/do/state 等)。
+ */
+export async function bootGameHost(opts) {
+  const o = opts || {};
+  // 动态 import 引擎:求值时机延后到本函数被调用(浏览器运行期)。esbuild 内联,无外部请求。
+  const engine = o.engine || (await import('littlejsengine'));
+  // 主随机种子(缺省固定值,与 ref 取证同口径,保确定性可复现)。
+  const seed = (o.seed != null ? o.seed : 0x1234abcd) >>> 0;
+  // 复用 ref 标准装配(7 插件 + 偏序 + 视口 + 工厂 wiring)。
+  const cfg = buildRefHostConfig({ seed });
+  // 调通用宿主:real 通道引擎掌帧;factory override 为本目录生成工厂;其余 wiring 取标准集。
+  return bootGameHostCore({
+    canvas: o.canvas,
+    statusEl: o.statusEl || null,
+    engine,
+    seed,
+    mode: o.mode || 'play',           // W-G1 真玩=play
+    engineMode: 'real',               // 一律引擎掌帧(real 通道)
+    viewport: cfg.viewport,           // 390×844(与 ref 同,移动竖屏基准)
+    factory: gameFactory,             // ★ override:本目录【生成的游戏】(其余 wiring 全复用 ref)
+    plugins: cfg.plugins,             // 标准 7 插件实例集(经 opts.runtime.plugins 注入给工厂)
+    registerOrder: cfg.registerOrder, // 注册偏序(保六锚)
+    buildFactoryOpts: cfg.buildFactoryOpts, // 注入 runtime:{plugins,bundle,getRealAudioCtx}
+    recHook: o.recHook || null,       // 取证:引擎 call-ID 探针(默认 no-op)
+    onReady: o.onReady || null,       // 取证:收集 internals(uncaught)
+  });
+}
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-probe/evidence/after-play.png b/game-runtime/games/_wg1-gen/_goldenpath-probe/evidence/after-play.png
new file mode 100644
index 00000000..af07fead
Binary files /dev/null and b/game-runtime/games/_wg1-gen/_goldenpath-probe/evidence/after-play.png differ
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-probe/evidence/first-paint.png b/game-runtime/games/_wg1-gen/_goldenpath-probe/evidence/first-paint.png
new file mode 100644
index 00000000..0e6c1278
Binary files /dev/null and b/game-runtime/games/_wg1-gen/_goldenpath-probe/evidence/first-paint.png differ
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-probe/evidence/verdict.json b/game-runtime/games/_wg1-gen/_goldenpath-probe/evidence/verdict.json
new file mode 100644
index 00000000..1e32c004
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/_goldenpath-probe/evidence/verdict.json
@@ -0,0 +1,48 @@
+{
+  "gameId": "_goldenpath-probe",
+  "url": "http://localhost:4320/games/_wg1-gen/_goldenpath-probe/index.html",
+  "ts": null,
+  "guards": {
+    "A_boot": {
+      "pass": true
+    },
+    "C_frame": {
+      "pass": true,
+      "f0": 49,
+      "f1": 79,
+      "delta": 30
+    },
+    "D_render": {
+      "pass": true,
+      "bright": 16482,
+      "maxCh": 255
+    },
+    "E_live": {
+      "pass": true,
+      "distinctStates": 7,
+      "samples": 7
+    },
+    "B_uncaught": {
+      "pass": true,
+      "uncaught": []
+    },
+    "F_wiring": {
+      "pass": true,
+      "callCount": 235,
+      "sample": [
+        "particles.spawnEmitter",
+        "particles.spawnEmitter",
+        "audio.synth.synthSfx",
+        "particles.spawnEmitter",
+        "audio.synth.synthSfx"
+      ],
+      "expected": [
+        "math.",
+        "particles.",
+        "audio.synth"
+      ]
+    }
+  },
+  "pass": true,
+  "notes": []
+}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-probe/factory.js b/game-runtime/games/_wg1-gen/_goldenpath-probe/factory.js
new file mode 100644
index 00000000..5e6049b2
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/_goldenpath-probe/factory.js
@@ -0,0 +1,78 @@
+'use strict';
+/**
+ * factory.js —— 最小合法 GameHostFactory「探针」(golden-path)。
+ * 双重用途:① 确定性触发 getEngine() 三类叶调用(math/particles/audio)→ 验 harness 的 F 真接线门能亮;
+ *           ② 作便宜模型生成的 few-shot 参照:一份「最小但处处合契约」的工厂范例。
+ * 严守受控面铁律:零引擎 import、零 Math.random / Date.now / addEventListener / new AudioContext / RAF;
+ *   能力一律经 boot.ctx;render 只画到入参 g(=boot.mainContext)。
+ */
+export default function createProbeGame(opts) {
+  const o = opts || {};            // 防御:纯净工厂 opts 可能为 undefined
+  let ctx = null;                  // 受控面(boot.ctx),init 内填充(勿在工厂顶层建态)
+  let nowMs = 0;                   // 本帧逻辑钟快照(update 首行从 ctx.time 刷新)
+  let t = 0;                       // 累计秒(动画用)
+  let sub = null;                  // pointerdown 订阅句柄(destroy 取消)
+  let bursts = [];                 // 点击反馈圈(纯几何,叠在引擎粒子之外)
+
+  /** init:建态 + 订阅受控输入 + 首帧探引擎(spawn 常驻发射器 → 触发 particles.spawnEmitter)。 */
+  function init(boot) {
+    ctx = boot.ctx;
+    sub = ctx.getInput().on('pointerdown', onTap);   // 禁 addEventListener,走受控订阅
+    const eng = ctx.getEngine();                      // 可能为 null,须容错
+    if (eng && eng.particles) {
+      try {
+        eng.particles.spawnEmitter({
+          pos: { x: 195, y: 300 }, emitRate: 18, emitTime: 0, particleTime: 0.7, speed: 40,
+          colorStart: { r: 1, g: 0.8, b: 0.2, a: 1 }, colorEnd: { r: 1, g: 0.3, b: 0, a: 0 },
+        });
+      } catch (_) { /* 引擎缺省时不连坐游戏 */ }
+    }
+  }
+
+  /** 点击:记反馈圈 + 触发引擎粒子爆发与音效(→ particles.spawnEmitter / audio.synth.synthSfx)。 */
+  function onTap(e) {
+    nowMs = ctx.time.nowMs();
+    const px = e.x || 0, py = e.y || 0;   // e.x/e.y 已是逻辑像素坐标(x∈[0,390], y∈[0,844]),直接用,勿再乘视口
+    bursts.push({ x: px, y: py, born: nowMs });
+    const eng = ctx.getEngine();
+    if (eng) {
+      if (eng.particles) {
+        try { eng.particles.spawnEmitter({ pos: { x: px, y: py }, count: 24, speed: 130, particleTime: 0.5,
+          colorStart: { r: 0.3, g: 0.9, b: 1, a: 1 }, colorEnd: { r: 0, g: 0.2, b: 0.6, a: 0 } }); } catch (_) {}
+      }
+      if (eng.audio && eng.audio.synth) {
+        try { eng.audio.synth.synthSfx([1, 0.05, 220, , , 0.18, , 1.4]); } catch (_) {}  // ZzFX 参数包
+      }
+    }
+  }
+
+  /** update:刷本帧钟 + 每帧触发一次 math.lerp(确定性引擎叶调用 → F 门有信号)+ 过期反馈圈淘汰。 */
+  function update(dt) {
+    nowMs = ctx.time.nowMs();                         // ★并轨单钟:读 host 唯一推进的钟
+    t = nowMs / 1000;
+    const eng = ctx.getEngine();
+    if (eng && eng.math) { try { eng.math.lerp(0, 1, (t % 1)); } catch (_) {} }
+    bursts = bursts.filter((b) => nowMs - b.born < 600);
+  }
+
+  /** render:画到入参 g(=boot.mainContext)。背景满幅(保 D 非空)+左右移动方块(保 E 活性)+点击圈+提示。 */
+  function render(g) {
+    g.fillStyle = '#101820'; g.fillRect(0, 0, 390, 844);                 // 满幅底色
+    const x = 50 + 290 * (0.5 + 0.5 * Math.sin(t * 1.5));                // Math.sin 允许(禁的是 random/Date.now)
+    g.fillStyle = '#ffcc33'; g.fillRect(x, 400, 60, 60);                 // 随时间移动 → 逐帧变
+    for (const b of bursts) {
+      const age = (nowMs - b.born) / 600;
+      g.strokeStyle = 'rgba(80,220,255,' + (1 - age).toFixed(3) + ')';
+      g.lineWidth = 3; g.beginPath(); g.arc(b.x, b.y, 8 + age * 40, 0, Math.PI * 2); g.stroke();
+    }
+    g.fillStyle = '#88aabb'; g.font = '16px monospace'; g.fillText('probe: tap me', 130, 120);
+  }
+
+  /** destroy:幂等卸载(取消订阅)。 */
+  function destroy() {
+    try { sub && sub.cancel(); } catch (_) {}
+    sub = null; bursts = [];
+  }
+
+  return { init, update, render, destroy };
+}
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-probe/index.html b/game-runtime/games/_wg1-gen/_goldenpath-probe/index.html
new file mode 100644
index 00000000..d5dd623c
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/_goldenpath-probe/index.html
@@ -0,0 +1,83 @@
+
+
+
+
+  
+  
+  
+  W-G1 generated game
+  
+
+
+  
+
booting…
+ + +
+ + + + + + diff --git a/game-runtime/games/_wg1-gen/_goldenpath-probe/play-spec.json b/game-runtime/games/_wg1-gen/_goldenpath-probe/play-spec.json new file mode 100644 index 00000000..7d1e6c77 --- /dev/null +++ b/game-runtime/games/_wg1-gen/_goldenpath-probe/play-spec.json @@ -0,0 +1,11 @@ +{ + "_note": "probe:确定性触发引擎三类叶调用。update 每帧 math.lerp、init+tap 触 particles.spawnEmitter、tap 触 audio.synth.synthSfx。点几下即过 F。", + "inputs": [ + { "t": "wait", "ms": 400 }, + { "t": "tap", "x": 195, "y": 500 }, + { "t": "wait", "ms": 200 }, + { "t": "tap", "x": 120, "y": 300 }, + { "t": "wait", "ms": 300 } + ], + "expectedEngineCallPrefixes": ["math.", "particles.", "audio.synth"] +} diff --git a/game-runtime/games/_wg1-gen/_goldenpath-ref/bundle.iife.js b/game-runtime/games/_wg1-gen/_goldenpath-ref/bundle.iife.js new file mode 100644 index 00000000..e3335b11 --- /dev/null +++ b/game-runtime/games/_wg1-gen/_goldenpath-ref/bundle.iife.js @@ -0,0 +1,34 @@ +"use strict";var __GameBundle=(()=>{var So=Object.defineProperty;var Hl=Object.getOwnPropertyDescriptor;var $l=Object.getOwnPropertyNames;var Yl=Object.prototype.hasOwnProperty;var Xl=(t,e,n)=>()=>{if(n)throw n[0];try{return t&&(e=t(t=0)),e}catch(s){throw n=[s],s}};var Ga=(t,e)=>{for(var n in e)So(t,n,{get:e[n],enumerable:!0})},Kl=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of $l(e))!Yl.call(t,i)&&i!==n&&So(t,i,{get:()=>e[i],enumerable:!(s=Hl(e,i))||s.enumerable});return t};var Ql=t=>Kl(So({},"__esModule",{value:!0}),t);var Vl={};Ga(Vl,{ASSERT:()=>m,BLACK:()=>he,BLUE:()=>ul,Box2dDistanceJoint:()=>Zi,Box2dFrictionJoint:()=>jr,Box2dGearJoint:()=>Ir,Box2dJoint:()=>st,Box2dKinematicObject:()=>Rr,Box2dMotorJoint:()=>Nr,Box2dObject:()=>Zs,Box2dPinJoint:()=>Lr,Box2dPlugin:()=>eo,Box2dPrismaticJoint:()=>Fr,Box2dPulleyJoint:()=>Jr,Box2dRaycastResult:()=>Qi,Box2dRevoluteJoint:()=>Dr,Box2dRopeJoint:()=>Or,Box2dStaticObject:()=>Ki,Box2dTargetJoint:()=>Mr,Box2dTileLayer:()=>Pr,Box2dWeldJoint:()=>Br,Box2dWheelJoint:()=>Gr,CLEAR_BLACK:()=>wt,CLEAR_WHITE:()=>vn,CYAN:()=>wd,CanvasLayer:()=>Ji,Color:()=>Me,Ease:()=>no,EngineObject:()=>Kt,GRAY:()=>Sd,GREEN:()=>ll,ImageFont:()=>Di,LOG:()=>Ce,Light:()=>Sr,LightSystemPlugin:()=>xr,MAGENTA:()=>Td,Medal:()=>Yi,NewgroundsMedal:()=>yr,NewgroundsPlugin:()=>gr,ORANGE:()=>vd,PI:()=>te,PURPLE:()=>dl,Particle:()=>Ni,ParticleEmitter:()=>lr,PathFinder:()=>zr,PathFinderNode:()=>so,PostProcessPlugin:()=>br,RED:()=>Yr,RandomGenerator:()=>ir,Sound:()=>Vs,SoundInstance:()=>Bi,TextureInfo:()=>Qt,TileCollisionLayer:()=>qs,TileInfo:()=>It,TileLayer:()=>Ws,TileLayerData:()=>jn,Timer:()=>Lt,Tween:()=>to,UIButton:()=>Qs,UICheckbox:()=>kr,UILayout:()=>Er,UIObject:()=>pt,UISlider:()=>Cr,UISystemPlugin:()=>wr,UIText:()=>Xi,UITextInput:()=>Tr,UITile:()=>Ar,UIVideo:()=>_r,Vector2:()=>me,WHITE:()=>Q,YELLOW:()=>cl,ZzFXMusic:()=>vr,abs:()=>de,atan2:()=>qr,audioContext:()=>ve,audioDefaultSampleRate:()=>Ss,audioIsRunning:()=>Us,audioMasterGain:()=>Xt,box2d:()=>b,box2dDebug:()=>Ia,box2dInit:()=>Bh,box2dSetDebug:()=>Gh,cameraAngle:()=>ae,cameraFit:()=>Gf,cameraPos:()=>Ie,cameraScale:()=>ee,canvasClearColor:()=>yn,canvasColorTiles:()=>oo,canvasFixedSize:()=>is,canvasMaxAspect:()=>ss,canvasMaxSize:()=>ns,canvasMinAspect:()=>Ms,canvasPixelRatio:()=>gn,canvasPixelated:()=>Qr,ceil:()=>Fs,clamp:()=>H,combineCanvases:()=>da,cos:()=>ye,debug:()=>Ue,debugCircle:()=>Qe,debugClear:()=>ud,debugLine:()=>Rt,debugOverlap:()=>nr,debugOverlay:()=>zt,debugPoint:()=>Wr,debugPointSize:()=>qc,debugPoly:()=>ld,debugRect:()=>ke,debugScreenshot:()=>$c,debugShowErrors:()=>dd,debugText:()=>ts,debugVideoCaptureIsActive:()=>Pt,debugVideoCaptureStart:()=>Yc,debugVideoCaptureStop:()=>Xc,debugWatermark:()=>io,distanceAngle:()=>gd,distanceWrap:()=>Hr,drawCanvas2D:()=>Wn,drawCircle:()=>Oi,drawCircleGradient:()=>Df,drawContext:()=>Oe,drawCount:()=>Ot,drawCrescent:()=>Nh,drawEllipse:()=>ml,drawEllipseGradient:()=>yl,drawLine:()=>Dn,drawLineList:()=>rr,drawNineSlice:()=>Bl,drawNineSliceScreen:()=>jh,drawPoly:()=>ds,drawRect:()=>Li,drawRectGradient:()=>Mf,drawRegularPoly:()=>pl,drawText:()=>If,drawTextScreen:()=>bn,drawTextureWrapped:()=>Lf,drawThreeSlice:()=>jl,drawThreeSliceScreen:()=>Jh,drawTile:()=>Be,enablePhysicsSolver:()=>lo,engineAddPlugin:()=>Un,engineImageFont:()=>Sl,engineInit:()=>od,engineName:()=>Ti,engineObjects:()=>_e,engineObjectsCallback:()=>ad,engineObjectsCollect:()=>Wc,engineObjectsCollide:()=>Vr,engineObjectsDestroy:()=>rd,engineObjectsRaycast:()=>cd,engineObjectsUpdate:()=>Vc,engineVersion:()=>Ai,fetchJSON:()=>Ad,floor:()=>Pe,fontDefault:()=>ei,formatTime:()=>Xr,frame:()=>zc,frameRate:()=>nd,gamepadConnected:()=>cr,gamepadDirectionEmulateStick:()=>oa,gamepadDpad:()=>ar,gamepadIsDown:()=>Nt,gamepadPrimary:()=>Ae,gamepadStick:()=>Ns,gamepadStickCount:()=>vl,gamepadVibrate:()=>Qf,gamepadVibrateStop:()=>Zf,gamepadWasPressed:()=>ga,gamepadWasReleased:()=>Kf,gamepadsEnable:()=>uo,getCameraSize:()=>bl,getCrescentPoints:()=>Jl,getNoteFrequency:()=>Cl,getPaused:()=>sd,glAntialias:()=>Ta,glCanvas:()=>ue,glCircleSides:()=>ti,glClearCanvas:()=>Ml,glClearRect:()=>Fl,glCompileShader:()=>mr,glContext:()=>g,glCopyToContext:()=>Ea,glCreateProgram:()=>ys,glCreateTexture:()=>mo,glDeleteTexture:()=>Ol,glDraw:()=>Ys,glDrawColoredPoints:()=>Ma,glDrawOutlineTransform:()=>Pa,glDrawPoints:()=>Il,glDrawPointsTransform:()=>Ra,glDrawUntextured:()=>Dl,glEnable:()=>W,glFlush:()=>Fe,glSetAntialias:()=>Ch,glSetRenderTarget:()=>Ps,glSetTexture:()=>Ca,glSetTextureData:()=>_a,glSetTextureWrap:()=>Ll,gravity:()=>Ze,headlessMode:()=>$,hsl:()=>Vt,hypot:()=>Kc,inputClear:()=>ai,inputClearKey:()=>ma,inputMouseMoveThreshold:()=>pa,inputPreventDefault:()=>os,inputWASDEmulateDirection:()=>Ls,isArray:()=>St,isColor:()=>X,isFullscreen:()=>xl,isIntersecting:()=>tl,isNumber:()=>O,isOnScreen:()=>Bf,isOverlapping:()=>Ei,isPowerOfTwo:()=>Gs,isStringLike:()=>K,isTouchDevice:()=>ft,isUsingGamepad:()=>as,isVector2:()=>D,keyDirection:()=>Yf,keyIsDown:()=>Ge,keyWasPressed:()=>Ne,keyWasReleased:()=>ya,lastInputDevice:()=>pn,lerp:()=>et,lerpAngle:()=>bd,lerpWrap:()=>el,lightSystem:()=>Z,lineTest:()=>sl,log2:()=>Qc,mainCanvas:()=>q,mainCanvasSize:()=>N,mainContext:()=>ge,max:()=>re,medalDisplaySize:()=>Hi,medalDisplaySlideTime:()=>rs,medalDisplayTime:()=>qi,medals:()=>Xs,medalsForEach:()=>yo,medalsInit:()=>Ph,medalsPreventUnlock:()=>La,medalsReset:()=>Mh,min:()=>le,mod:()=>dt,mouseDelta:()=>fa,mouseDeltaScreen:()=>Ct,mouseInWindow:()=>Ii,mouseIsDown:()=>Ds,mousePos:()=>Jt,mousePosScreen:()=>Ke,mouseWasPressed:()=>Js,mouseWasReleased:()=>Xf,mouseWheel:()=>ha,nearestPowerOfTwo:()=>xd,newgrounds:()=>Ks,noise1D:()=>Rd,noise2D:()=>Pd,objectDefaultAngleDamping:()=>na,objectDefaultDamping:()=>ta,objectDefaultFriction:()=>ia,objectDefaultMass:()=>ea,objectDefaultRestitution:()=>sa,objectMaxSpeed:()=>Wt,oscillate:()=>nl,particleEmitRateScale:()=>Ri,paused:()=>Mt,percent:()=>Ve,percentLerp:()=>yd,playSamples:()=>wa,pointerLockExit:()=>nh,pointerLockIsActive:()=>wl,pointerLockRequest:()=>th,postProcess:()=>Je,primitiveCount:()=>Dt,rand:()=>Se,randBool:()=>il,randColor:()=>sr,randInCircle:()=>al,randInt:()=>$r,randSign:()=>ol,randVec2:()=>rl,readSaveData:()=>_d,rgb:()=>Y,round:()=>Ci,saveCanvas:()=>fl,saveDataURL:()=>Bs,saveText:()=>kd,screenToWorld:()=>oi,screenToWorldDelta:()=>gl,screenToWorldTransform:()=>ri,setAdditiveBlendMode:()=>js,setCameraAngle:()=>Ld,setCameraPos:()=>Md,setCameraScale:()=>Od,setCanvasClearColor:()=>Fd,setCanvasColorTiles:()=>Id,setCanvasFixedSize:()=>Jd,setCanvasMaxAspect:()=>jd,setCanvasMaxSize:()=>Gd,setCanvasMinAspect:()=>Bd,setCanvasPixelRatio:()=>zd,setCanvasPixelated:()=>hl,setCursor:()=>zf,setDebugKey:()=>Pf,setDebugWatermark:()=>Rf,setEnablePhysicsSolver:()=>Kd,setFontDefault:()=>Ud,setGLCircleSides:()=>Hd,setGLEnable:()=>qd,setGamepadDirectionEmulateStick:()=>cf,setGamepadsEnable:()=>af,setGravity:()=>of,setHeadlessMode:()=>Wd,setInputMouseMoveThreshold:()=>Wf,setInputPreventDefault:()=>Vf,setInputWASDEmulateDirection:()=>lf,setMedalDisplaySize:()=>Dh,setMedalDisplaySlideTime:()=>Oh,setMedalDisplayTime:()=>Lh,setMedalsPreventUnlock:()=>Ih,setObjectDefaultAngleDamping:()=>ef,setObjectDefaultDamping:()=>Zd,setObjectDefaultFriction:()=>nf,setObjectDefaultMass:()=>Qd,setObjectDefaultRestitution:()=>tf,setObjectMaxSpeed:()=>sf,setParticleEmitRateScale:()=>rf,setPaused:()=>id,setShowSplashScreen:()=>Vd,setSoundDefaultRange:()=>_f,setSoundDefaultTaper:()=>Ef,setSoundEnable:()=>kf,setSoundVolume:()=>Cf,setTileDefaultBleed:()=>Xd,setTileDefaultPadding:()=>Yd,setTileDefaultSize:()=>$d,setTilesPixelated:()=>Nd,setTimeScale:()=>Dd,setTouchGamepadAlpha:()=>vf,setTouchGamepadAnalog:()=>bf,setTouchGamepadButtonCount:()=>pf,setTouchGamepadCenterButtonSize:()=>hf,setTouchGamepadDisplayTime:()=>wf,setTouchGamepadEnable:()=>df,setTouchGamepadFloating:()=>xf,setTouchGamepadLeftButtonCount:()=>yf,setTouchGamepadLeftStick:()=>mf,setTouchGamepadPassthrough:()=>ff,setTouchGamepadRightStick:()=>gf,setTouchGamepadSize:()=>Sf,setTouchGamepadVibration:()=>Tf,setTouchInputEnable:()=>uf,setVibrateEnable:()=>Af,shareURL:()=>Cd,showSplashScreen:()=>Zr,sign:()=>ut,sin:()=>fe,smoothStep:()=>_i,soundDefaultRange:()=>ca,soundDefaultTaper:()=>la,soundEnable:()=>nt,soundVolume:()=>Bn,speak:()=>gh,speakStop:()=>bh,tan:()=>Zc,textureInfos:()=>Tn,tile:()=>ii,tileCollisionGetData:()=>ji,tileCollisionLayers:()=>xn,tileCollisionRaycast:()=>_l,tileCollisionTest:()=>fn,tileDefaultBleed:()=>co,tileDefaultPadding:()=>ao,tileDefaultSize:()=>ro,tileLayersLoad:()=>Sh,tilesPixelated:()=>Jn,time:()=>rt,timeDelta:()=>Ur,timeReal:()=>Sn,timeScale:()=>Kr,toggleFullscreen:()=>Nf,touchGamepadAlpha:()=>aa,touchGamepadAnalog:()=>ni,touchGamepadButtonCount:()=>gs,touchGamepadCenterButtonSize:()=>vt,touchGamepadDisplayTime:()=>Os,touchGamepadEnable:()=>wn,touchGamepadFloating:()=>An,touchGamepadLeftButtonCount:()=>bs,touchGamepadLeftStick:()=>Vn,touchGamepadPassthrough:()=>ra,touchGamepadRightStick:()=>xs,touchGamepadSize:()=>tt,touchGamepadVibration:()=>Pi,touchInputEnable:()=>On,tweenProperty:()=>zh,tweenStopAll:()=>Uh,tweenUpdate:()=>Ul,uiDebug:()=>Da,uiSetDebug:()=>Fh,uiSystem:()=>E,usingGamepadInput:()=>$f,usingKeyboardInput:()=>Hf,usingMouseInput:()=>qf,vec2:()=>v,vibrate:()=>ba,vibrateEnable:()=>si,vibrateStop:()=>eh,workCanvas:()=>$t,workContext:()=>hn,workReadCanvas:()=>Et,workReadContext:()=>qt,worldToScreen:()=>qn,worldToScreenDelta:()=>Ff,writeSaveData:()=>Ed,zzfx:()=>xh,zzfxG:()=>ho,zzfxM:()=>Gl});function sd(){return Mt}function id(t=!0){Mt=t}function Un(t,e,n,s){m(!In.find(r=>r.update===t&&r.render===e&&r.glContextLost===n&&r.glContextRestored===s));let i=new er(t,e,n,s);In.push(i)}async function od(t,e,n,s,i,r=[],a){if(Uc&&console.log(`${Ti} Engine v${Ai}`),m(!ge,"engine already initialized"),ge)return;m(St(r),"pass in images as array"),document.body||document.documentElement.appendChild(document.createElement("body")),a||(a=document.body),t||(t=()=>{}),e||(e=()=>{}),n||(n=()=>{}),s||(s=()=>{}),i||(i=()=>{});function o(){N=v(q.width,q.height),ge.imageSmoothingEnabled=!Jn,pr()}function c(p=0){let y=p-Ko;Ko||(y=0),Ko=p,(Ue||io)&&(ki=et(ki,1e3/(y||1),.05));let x=Ue&&Ge("Equal"),w=Ue&&Ge("Minus"),A=x?10:w?.1:1;Sn+=y*A/1e3;let S=Kr*A;y*=S,kt+=Mt?0:y,S<=1&&(kt=le(kt,50));let _=!1;if(Mt){_=!0,l(),Fc(),In.forEach(C=>{var L;return(L=C.update)==null?void 0:L.call(C)});for(let C of _e)C.parent||C.updateTransforms();Lc(),n(),Gc(),Pt()&&k()}else{let C=0;for(kt<0&&kt>-9&&(C=kt,kt=0);kt>=0;kt-=1e3/60)rt=zc++/60,_=!0,l(),Fc(),e(),In.forEach(L=>{var V;return(V=L.update)==null?void 0:V.call(L)}),Vc(),Lc(),n(),Gc(),Pt()&&k();kt+=C}Pt()||k(),requestAnimationFrame(c);function k(){if(!$){_||l(),o(),s(),_e.sort((C,L)=>C.renderOrder-L.renderOrder);for(let C of _e)C.destroyed||C.render();i(),In.forEach(C=>{var L;return(L=C.render)==null?void 0:L.call(C)}),ih(),hd(),Fe(),pd(),Ot=0,Dt=0}}}function l(){if(!$){if(is.x){N=is.copy();let p=innerWidth/innerHeight,y=is.x/is.y,x=pss){let _=N.y*ss|0;N.x=le(_,ns.x)}else if(w0&&!W&&(ge.fillStyle=yn.toString(),ge.fillRect(0,0,N.x,N.y),ge.fillStyle=he.toString()),ge.lineJoin="round",ge.lineCap="round"}}if($)return f();Th(a);let u="margin:0;overflow:hidden;background:#000;user-select:none;-webkit-user-select:none;touch-action:none;-webkit-touch-callout:none";a.style.cssText=u,q=a.appendChild(document.createElement("canvas")),Oe=ge=q.getContext("2d"),sh(),yh(),fd();let h="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)";q.style.cssText=h,ue&&(ue.style.cssText=h),hl(Qr),l(),pr(),$t=new OffscreenCanvas(64,64),hn=$t.getContext("2d"),Et=new OffscreenCanvas(64,64),qt=Et.getContext("2d",{willReadFrequently:!0});let d=r.map((p,y)=>Dc(y,p));return r.length||d.push(Dc(0)),d.push(Uf()),Zr&&d.push(new Promise(p=>{let y=0;x();function x(){ai(),Rh(y+=.01),y>1?p():setTimeout(x,16)}})),await Promise.all(d),f();async function f(){await t(),c()}}function Vc(){Vr=_e.filter(e=>e.collideSolidObjects);function t(e){if(!e.destroyed){e.update();for(let n of e.children)t(n)}}for(let e of _e)if(!(e.parent||e.destroyed)){e.update(),e.updatePhysics();for(let n of e.children)t(n);e.updateTransforms()}_e=_e.filter(e=>!e.destroyed)}function rd(t=!0){for(let e of _e)e.parent||e.destroy(t);_e=_e.filter(e=>!e.destroyed)}function Wc(t,e,n=_e){let s=[];if(t)if(e instanceof me)for(let i of n)i.isOverlapping(t,e)&&s.push(i);else{let i=e*e;for(let r of n)t.distanceSquared(r.pos)n(i))}function cd(t,e,n=_e){let s=[];for(let i of n)i.collideRaycast&&tl(t,e,i.pos,i.size)&&(xt&&ke(i.pos,i.size,"#f00"),s.push(i));return xt&&Rt(t,e,s.length?"#f00":"#00f",.02),s}function m(t,...e){if(!t)throw console.assert(t,...e),new Error("Assert failed!")}function Ce(...t){console.log(...t)}function ke(t,e=v(),n=Q,s=0,i=0,r=!1,a=!1){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(K(n)||X(n),"color is invalid"),m(O(s),"time must be a number"),m(O(i),"angle must be a number"),X(n)&&(n=n.toString());let o=new Lt(s);mn.push({pos:t.copy(),size:e.copy(),color:n,timer:o,angle:i,fill:r,screenSpace:a})}function ld(t,e,n=Q,s=0,i=0,r=!1,a=!1){m(D(t),"pos must be a vec2"),m(St(e),"points must be an array"),m(K(n)||X(n),"color is invalid"),m(O(s),"time must be a number"),m(O(i),"angle must be a number"),X(n)&&(n=n.toString()),t=t.copy(),e=e.map(c=>c.copy());let o=new Lt(s);mn.push({pos:t,points:e,color:n,timer:o,angle:i,fill:r,screenSpace:a})}function Qe(t,e=0,n=Q,s=0,i=!1,r=!1){m(D(t),"pos must be a vec2"),m(O(e),"size must be a number"),m(K(n)||X(n),"color is invalid"),m(O(s),"time must be a number"),X(n)&&(n=n.toString()),t=t.copy();let a=new Lt(s);mn.push({pos:t,size:e,color:n,timer:a,angle:0,fill:i,screenSpace:r})}function Wr(t,e,n,s,i=!1){ke(t,void 0,e,n,s,!1,i)}function Rt(t,e,n,s=.1,i=0,r=!1){m(D(t),"posA must be a vec2"),m(D(e),"posB must be a vec2"),m(O(s),"width must be a number");let a=v((e.x-t.x)/2,(e.y-t.y)/2),o=v(s,a.length()*2);ke(t.add(a),o,n,i,a.angle(),!0,r)}function nr(t,e,n,s,i,r,a=!1){m(D(t),"posA must be a vec2"),m(D(n),"posB must be a vec2"),m(D(e),"sizeA must be a vec2"),m(D(s),"sizeB must be a vec2");let o=v(le(t.x-e.x/2,n.x-s.x/2),le(t.y-e.y/2,n.y-s.y/2)),c=v(re(t.x+e.x/2,n.x+s.x/2),re(t.y+e.y/2,n.y+s.y/2));ke(o.lerp(c,.5),c.subtract(o),i,r,0,!1,a)}function ts(t,e,n=1,s=Q,i=0,r=0,a="monospace",o=!1){m(K(t),"text must be a string"),m(D(e),"pos must be a vec2"),m(O(n),"size must be a number"),m(K(s)||X(s),"color is invalid"),m(O(i),"time must be a number"),m(O(r),"angle must be a number"),m(K(a),"font must be a string"),X(s)&&(s=s.toString()),e=e.copy();let c=new Lt(i);mn.push({text:t,pos:e,size:n,color:s,timer:c,angle:r,font:a,screenSpace:o})}function ud(){mn=[]}function $c(){tr=1}function dd(){let t=n=>{document.body.style="background-color:#111;margin:8px",document.body.innerHTML="
"+n},e=console.assert;console.assert=(n,...s)=>{if(e(n,...s),!n){let i=s.join(" "),r=new Error().stack;throw`Assertion failed!
+`+i+`
+`+r}},onunhandledrejection=n=>t(n.reason.stack||n.reason),onerror=(n,s,i,r)=>t(`${n}
+${s}
+Ln ${i}, Col ${r}`)}function fd(){Uc&&console.warn("LittleJS DEBUG build loaded. Use the release build for production.")}function Lc(){Ue&&(Ne(Hc)&&(zt=!zt),zt&&(Ne("Digit1")&&(bt=!bt,Fn=!1),Ne("Digit2")&&(Fn=!Fn,bt=!1),Ne("Digit3")&&(Gn=!Gn),Ne("Digit4")&&(xt=!xt),Ne("Digit5")&&$c(),Ne("Digit7")&&(us=!us)),Pt()?(!zt||Ne("Digit6"))&&Xc():zt&&Ne("Digit6")&&Yc())}function hd(){if(Pt())return;Fe();let t=Ot,e=Dt;tr&&(da(),fl(q),tr=0);let n=ge;if(Gn&&uo){let r=0;for(let a=0;a<8;a++)cr(a)&&r++;for(let a=0;a<8;a++){if(!cr(a))continue;let o=1,c=.2,l=Ie.add(v(-o*2,((r-1)/2-a)*o*3));ts(a,l.add(v(-o,o)),1),a===Ae&&ts("Main",l.add(v(-o*2,0)),1,"#0f0");let u=_t[a].length;for(let d=0;d{n.save();let r=i.pos,a=1,o=i.angle;if(i.screenSpace||(r=qn(i.pos),a=ee,o-=ae),n.translate(r.x|0,r.y|0),n.rotate(o),n.scale(1,i.text?1:-1),n.fillStyle=i.color,n.strokeStyle=i.color,i.text!==void 0)n.font=i.size*a+"px "+i.font,n.textAlign="center",n.textBaseline="middle",n.fillText(i.text,0,0);else if(i.points!==void 0){n.beginPath();for(let c of i.points){let l=c.scale(a).floor();n.lineTo(l.x,l.y)}n.closePath(),i.fill&&n.fill(),n.stroke()}else if(i.size===0||i.size.x===0&&i.size.y===0){let c=qc*a;n.fillRect(-c/2,-1,c,3),n.fillRect(-1,-c/2,3,c)}else if(i.size.x!==void 0){let c=i.size.scale(a).floor(),l=c.x,u=c.y;i.fill&&n.fillRect(-l/2|0,-u/2|0,l,u),n.strokeRect(-l/2|0,-u/2|0,l,u)}else n.beginPath(),n.arc(0,0,i.size*a/2,0,9),i.fill&&n.fill(),n.stroke();n.restore()}),mn=mn.filter(i=>i.timer<0),s){let i=_l(s.pos,Jt);i&&Li(i.floor().add(v(.5)),v(1),Y(0,1,1,.3),0,!1),Dn(Jt,s.pos,.1,i?Y(1,0,0,.5):Y(0,1,0,.5),void 0,void 0,!1);let r="mouse pos = "+Jt;xn.length&&(r+=`
+mouse collision = `+ji(Jt)),r+=`
+
+--- object info ---
+`,r+=s.toString(),bn(r,Ke,24,Y(),.05,void 0,"center","monospace")}{n.save(),n.fillStyle="#fff",n.textAlign="left",n.textBaseline="top",n.font="20px monospace",n.shadowColor="#000",n.shadowBlur=9;let a=9,o=0,c=24;if(zt){n.fillText(`${Ti} v${Ai}`,a,o+=c/2),n.fillText("Time: "+Xr(rt),a,o+=c),n.fillText("FPS: "+ki.toFixed(1)+(W?" WebGL":" Canvas2D"),a,o+=c),n.fillText("Objects: "+_e.length,a,o+=c),n.fillText("Draw Calls: "+Ot,a,o+=c),n.fillText("Primitives: "+Dt,a,o+=c),n.fillText("---------",a,o+=c),n.fillStyle="#f00",n.fillText("ESC: Debug Overlay",a,o+=c),n.fillStyle=bt?"#f00":"#fff",n.fillText("1: Debug Physics",a,o+=c),n.fillStyle=Fn?"#f00":"#fff",n.fillText("2: Debug Particles",a,o+=c),n.fillStyle=Gn?"#f00":"#fff",n.fillText("3: Debug Gamepads",a,o+=c),n.fillStyle=xt?"#f00":"#fff",n.fillText("4: Debug Raycasts",a,o+=c),n.fillStyle="#fff",n.fillText("5: Save Screenshot",a,o+=c),n.fillText("6: Toggle Video Capture",a,o+=c),n.fillStyle=us?"#f00":"#fff",n.fillText("7: Debug Sound",a,o+=c);let l="",u="";for(let h in ie[0])Ge(h,0)&&(parseInt(h)<3?u+=h+" ":l+=h+" ");u&&n.fillText("Mouse: "+u,a,o+=c),l&&n.fillText("Keys: "+l,a,o+=c);for(let h=1;hs.push(o.data),i.onstop=()=>{let o=new Blob(s,{type:"video/webm"}),c=URL.createObjectURL(o);Bs(c,"capture.webm",1e3)};let r,a;if(nt){a=new ConstantSourceNode(ve,{offset:0}),a.connect(Xt),a.start(),r=ve.createMediaStreamDestination(),Xt.connect(r);for(let o of r.stream.getAudioTracks())t.addTrack(o)}try{i.start()}catch{Ce("Video capture not supported in this browser!"),a==null||a.stop();return}Ce("Video capture started."),Ut={mediaRecorder:i,captureTimer:n,videoTrack:e,silentAudioSource:a,audioStreamDestination:r}}function Xc(){var t,e,n;m(Pt(),"Not capturing video!"),Ce(`Video capture ended. ${Ut.captureTimer.get().toFixed(2)} seconds recorded.`),gt.style.display="none",(t=Ut.silentAudioSource)==null||t.stop(),(e=Ut.mediaRecorder)==null||e.stop(),(n=Ut.videoTrack)==null||n.stop(),Ut=void 0}function md(){m(Pt(),"Not capturing video!"),da(),Ut.videoTrack.requestFrame(),gt.textContent="\u25CF REC "+Xr(Ut.captureTimer)}function ct(t){if(Ue){let e=Object.keys(t),n={};e.forEach(s=>n[s]=t[s]),e.forEach(s=>{Object.defineProperty(t,s,{get:()=>n[s],set:i=>{m(!1,`Cannot modify engine constant. Attempted to set constant (${t}) property '${s}' to '${i}'.`)},enumerable:!0})})}return Object.freeze(t)}function dt(t,e=1){return(t%e+e)%e}function H(t,e=0,n=1){return tn?n:t}function Ve(t,e,n){return(n-=e)?H((t-e)/n):0}function et(t,e,n){return t+H(n)*(e-t)}function yd(t,e,n,s,i){return et(s,i,Ve(t,e,n))}function Hr(t,e,n=1){m(n>0,"distanceWrap wrapSize must be > 0");let s=(t-e)%n;return s*2%n-s}function el(t,e,n,s=1){return t+H(n)*Hr(e,t,s)}function gd(t,e){return Hr(t,e,2*te)}function bd(t,e,n){return el(t,e,n,2*te)}function _i(t){return t*t*(3-2*t)}function Gs(t){return!(t&t-1)}function xd(t){return 2**Fs(Qc(t))}function Ei(t,e,n,s=v()){let i=(t.x-n.x)*2,r=(t.y-n.y)*2,a=e.x+s.x,o=e.y+s.y;return de(i)d)return!1;h=re(p,h)}else{if(p0?o.x+1:o.x,y=h>0?o.y+1:o.y,x=c?(p-t.x)/c:1/0,w=l?(y-t.y)/l:1/0,A=0,S=x,_=w,k=do.x&&(C.x=o.x+1-L),V.yo.y&&(C.y=o.y+1-L),s&&(k?s.set(-u,0):s.set(0,-h)),C}(k=S<_)?(o.x+=u,A=S,S+=d):(o.y+=h,A=_,_+=f)}}function Se(t=1,e=0){return e+Math.random()*(t-e)}function $r(t,e=0){return Pe(Se(t,e))}function il(t=.5){return Se()URL.revokeObjectURL(t),n)}function Cd(t,e,n){var s;m(K(t),"shareURL requires title string"),m(K(e),"shareURL requires url string"),(s=navigator.share)==null||s.call(navigator,{title:t,url:e}).then(()=>n==null?void 0:n())}function _d(t,e){m(K(t),"loadData requires saveName string");let n={};try{let s=localStorage[t];if(s)try{n=JSON.parse(s)}catch{Ce("readSaveData: corrupt JSON for",t,"\u2014 using defaults")}}catch{Ce("readSaveData: localStorage unavailable \u2014 using defaults")}return{...e,...n}}function Ed(t,e){m(K(t),"saveData requires saveName string");try{localStorage[t]=JSON.stringify(e)}catch{Ce("writeSaveData: failed to write",t)}}function or(t){let e=(t|0)^2654435769;return e=Math.imul(e^e>>>16,2246822507),e=Math.imul(e^e>>>13,3266489909),e^=e>>>16,(e>>>0)/2**32}function Rd(t){let e=Pe(t);return et(or(e),or(e+1),_i(t-e))}function Pd(t,e){let n=Pe(t),s=Pe(e),i=_i(t-n),r=_i(e-s),a=(o,c)=>or(o+c*374761393);return et(et(a(n,s),a(n+1,s),i),et(a(n,s+1),a(n+1,s+1),i),r)}function Md(t){Ie=t.copy()}function Ld(t){ae=t}function Od(t){ee=t}function Dd(t){Kr=t}function Id(t){oo=t}function Fd(t){yn=t.copy()}function Gd(t){ns=t.copy()}function Bd(t){Ms=t}function jd(t){ss=t}function Jd(t){is=t.copy()}function hl(t){Qr=t,q&&(q.style.imageRendering=t?"pixelated":""),ue&&(ue.style.imageRendering=t?"pixelated":"")}function Nd(t){Jn=t}function zd(t){gn=t}function Ud(t){ei=t}function Vd(t){Zr=t}function Wd(t){$=t}function qd(t){if(t&&!hr){console.warn("Can not enable WebGL if it was disabled on start.");return}W=t,ue&&(ue.style.display=t?"":"none")}function Hd(t){ti=t}function $d(t){ro=t.copy()}function Yd(t){ao=t}function Xd(t){co=t}function Kd(t){lo=t}function Qd(t){ea=t}function Zd(t){ta=t}function ef(t){na=t}function tf(t){sa=t}function nf(t){ia=t}function sf(t){Wt=t}function of(t){Ze=t.copy()}function rf(t){Ri=t}function af(t){uo=t}function cf(t){oa=t}function lf(t){Ls=t}function uf(t){On=t}function df(t){wn=t}function ff(t){ra=t}function hf(t){vt=t}function pf(t){gs=t,t>0&&(xs=!1)}function mf(t){Vn=t,t&&(bs=0)}function yf(t){bs=t,t>0&&(Vn=!1)}function gf(t){xs=t,t&&(gs=0)}function bf(t){ni=t}function xf(t){An=t}function Sf(t){tt=t}function vf(t){aa=t}function wf(t){Os=t}function Tf(t){Pi=t}function Af(t){si=t}function kf(t){nt=t}function Cf(t){Bn=t,nt&&!$&&Xt&&(Xt.gain.value=t)}function _f(t){ca=t}function Ef(t){la=t}function Rf(t){io=t}function Pf(t){Hc=t}function Mi(t){return t.r>=1&&t.g>=1&&t.b>=1}function ua(t){return t.r<=0&&t.g<=0&&t.b<=0&&t.a<=0}function ii(t=0,e=ro,n=0,s=ao,i=co){if(m(D(t)||typeof t=="number","index must be a vec2 or number"),m(D(e)||typeof e=="number","size must be a vec2 or number"),m(O(n)||n instanceof Qt,"texture must be a number or TextureInfo"),m(O(s),"padding must be a number"),$)return new It;typeof e=="number"&&(m(e>0),e=new me(e,e));let r=typeof n=="number"?Tn[n]:n;m(r instanceof Qt,"tile texture is not loaded"),m(r.size.x>0,"tile texture is not loaded");let a=e.x+s*2,o=e.y+s*2,c,l;if(typeof t=="number"){let h=r.size.x/a|0;c=t%h,l=t/h|0}else c=t.x,l=t.y;let u=new me(c*a+s,l*o+s);return new It(u,e,r,s,i)}function Be(t,e=v(1),n,s=Q,i=0,r,a,o=W,c=!1,l){var d;m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(X(s),"color is invalid"),m(O(i),"angle must be a number"),m(!a||X(a),"additiveColor must be a color"),m(!l||!o,"context only supported in canvas 2D mode");let u=n==null?void 0:n.textureInfo,h=(d=n==null?void 0:n.bleed)!=null?d:0;if(o&&W)if(m(!!g,"WebGL is not enabled!"),c&&([t,e,i]=ri(t,e,i)),u){let f=u.sizeInverse,p=n.pos.x*f.x,y=n.pos.y*f.y,x=n.size.x*f.x,w=n.size.y*f.y;if(Ca(u.glTexture),h){let A=f.x*h,S=f.y*h;Ys(t.x,t.y,r?-e.x:e.x,e.y,i,p+A,y+S,p-A+x,y-S+w,s.rgbaInt(),a&&a.rgbaInt())}else Ys(t.x,t.y,r?-e.x:e.x,e.y,i,p,y,p+x,y+w,s.rgbaInt(),a&&a.rgbaInt())}else{let f=a?s.add(a):s;Dl(t.x,t.y,e.x,e.y,i,f.rgbaInt())}else++Ot,++Dt,Wn(t,e,i,r,f=>{if(u){f.scale(1,-1);let p=n.pos.x,y=n.pos.y,x=n.size.x,w=n.size.y;Jf(f,u.image,p,y,x,w,-.5,-.5,1,1,s,a,h)}else{let p=a?s.add(a):s;f.fillStyle=p.toString(),f.fillRect(-.5,-.5,1,1)}},c,l)}function Li(t,e,n,s,i,r,a){Be(t,e,void 0,n,s,!1,void 0,i,r,a)}function Mf(t,e,n=Q,s=vn,i=0,r=W,a=!1,o){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(X(n)&&X(s),"color is invalid"),m(O(i),"angle must be a number"),m(!o||!r,"context only supported in canvas 2D mode"),r&&W){m(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/ee),i+=ae);let c=[],l=[],u=e.x/2,h=e.y/2,d=n.rgbaInt(),f=s.rgbaInt(),p=ye(-i),y=fe(-i);for(let x=4;x--;){let w=x&1?u:-u,A=x&2?h:-h,S=w*p-A*y,_=w*y+A*p,k=x&2?d:f;c.push(v(t.x+S,t.y+_)),l.push(k)}Ma(c,l)}else++Ot,++Dt,Wn(t,e,i,!1,c=>{let l=c.createLinearGradient(0,.5,0,-.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.fillRect(-.5,-.5,1,1)},a,o)}function Lf(t,e,n,s=0,i=Q,r=0,a,o=W,c=!1,l){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(D(n),"wrapCount must be a vec2"),m(X(i),"color is invalid"),m(O(r),"angle must be a number"),m(!a||X(a),"additiveColor must be a color"),m(!l||!o,"context only supported in canvas 2D mode"),m(!(s instanceof It),"pass a TextureInfo or texture index, not a TileInfo \u2014 use tileInfo.textureInfo"),$)return;let u=typeof s=="number"?Tn[s]:s;if(m(u instanceof Qt,"texture not loaded"),m(u.size.x>0,"texture not loaded"),m(u.wrap,"drawTextureWrapped requires a wrap-enabled texture; call textureInfo.setWrap(true) first"),o&&W){m(!!g,"WebGL is not enabled!"),c&&([t,e,r]=ri(t,e,r)),Ca(u.glTexture),Ys(t.x,t.y,e.x,e.y,r,0,0,n.x,n.y,i.rgbaInt(),a&&a.rgbaInt());return}++Ot,++Dt,c||(t=qn(t),e=e.scale(ee),r-=ae);let h=!oo||(a?Mi(i.add(a))&&a.a<=0:Mi(i)),d=!h&&a&&!ua(a),f=h?u.image:jf(u.image,i,a);l=l||Oe,l.save(),l.translate(t.x+.5,t.y+.5),l.rotate(r),l.globalAlpha=d?1:i.a;let p=l.createPattern(f,"repeat"),y=new DOMMatrix().translate(-e.x/2,-e.y/2).scale(e.x/(n.x*f.width),e.y/(n.y*f.height));p.setTransform(y),l.fillStyle=p,l.fillRect(-e.x/2,-e.y/2,e.x,e.y),l.globalAlpha=1,l.restore()}function rr(t,e=.1,n=Q,s=!1,i=v(),r=0,a=W,o=!1,c){if(m(St(t),"points must be an array"),m(O(e),"width must be a number"),m(X(n),"color is invalid"),m(D(i),"pos must be a vec2"),m(O(r),"angle must be a number"),m(!c||!a,"context only supported in canvas 2D mode"),a&&W){m(!!g,"WebGL is not enabled!");let l=v(1);o&&([i,l,r]=ri(i,l,r)),Pa(t,n.rgbaInt(),e,i.x,i.y,l.x,l.y,r,s)}else++Ot,++Dt,Wn(i,v(1),r,!1,l=>{l.strokeStyle=n.toString(),l.lineWidth=e,l.beginPath();for(let u=0;u0&&Pa(t,s.rgbaInt(),n,i.x,i.y,l.x,l.y,r)}else Wn(i,v(1),r,!1,l=>{l.fillStyle=e.toString(),l.beginPath();for(let u of t)l.lineTo(u.x,u.y);l.closePath(),l.fill(),n&&(l.strokeStyle=s.toString(),l.lineWidth=n,l.stroke())},o,c)}function ml(t,e=v(1),n=Q,s=0,i=0,r=he,a=W,o=!1,c){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(X(n)&&X(r),"color is invalid"),m(O(s),"angle must be a number"),m(O(i),"lineWidth must be a number"),m(i>=0,"lineWidth must be a positive value or 0"),m(!c||!a,"context only supported in canvas 2D mode"),i=H(i,0,le(e.x,e.y)),a&&W?pl(t,e,ti,n,i,r,s,a,o,c):Wn(t,v(1),s,!1,l=>{l.fillStyle=n.toString(),l.beginPath(),l.ellipse(0,0,e.x/2,e.y/2,0,0,9),l.fill(),i&&(l.strokeStyle=r.toString(),l.lineWidth=i,l.stroke())},o,c)}function Oi(t,e=1,n=Q,s=0,i=he,r=W,a=!1,o){m(O(e),"size must be a number"),ml(t,v(e),n,0,s,i,r,a,o)}function yl(t,e=v(1),n=Q,s=vn,i=0,r=W,a=!1,o){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(X(n)&&X(s),"color is invalid"),m(O(i),"angle must be a number"),m(!o||!r,"context only supported in canvas 2D mode"),!$)if(r&&W){m(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/ee),i+=ae);let c=ti,l=e.x/2,u=e.y/2,h=n.rgbaInt(),d=s.rgbaInt(),f=Of++,p=ye(-i),y=fe(-i),x=_=>{let k=fe(_)*l,C=ye(_)*u;return v(t.x+k*p-C*y,t.y+k*y+C*p)},w=f%c/c*te*2,A=[x(w)],S=[d];for(let _=c;_--;){let k=(_+f)%c/c*te*2;A.push(t),S.push(h),A.push(x(k)),S.push(d)}Ma(A,S)}else++Ot,++Dt,Wn(t,e,i,!1,c=>{let l=c.createRadialGradient(0,0,0,0,0,.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.beginPath(),c.ellipse(0,0,.5,.5,0,0,9),c.fill()},a,o)}function Df(t,e=1,n=Q,s=vn,i=W,r=!1,a){m(O(e),"size must be a number"),yl(t,v(e),n,s,0,i,r,a)}function Wn(t,e,n=0,s=!1,i,r=!1,a=Oe){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(O(n),"angle must be a number"),m(typeof i=="function","drawFunction must be a function"),r||(t=qn(t),e=e.scale(ee),n-=ae),a.save(),a.translate(t.x+.5,t.y+.5),a.rotate(n),a.scale(s?-e.x:e.x,-e.y),i(a),a.restore()}function If(t,e,n=1,s=Q,i=0,r=he,a="center",o=ei,c="",l,u=0,h=Oe){e=qn(e),n*=ee,i*=ee,u-=ae,u*=-1,bn(t,e,n,s,i,r,a,o,c,l,u,h)}function bn(t,e,n,s=Q,i=0,r=he,a="center",o=ei,c="",l,u=0,h=Oe){m(K(t),"text must be a string"),m(D(e),"pos must be a vec2"),m(O(n),"size must be a number"),m(X(s),"color must be a color"),m(O(i),"lineWidth must be a number"),m(X(r),"lineColor must be a color"),m(["left","center","right"].includes(a),"align must be left, center, or right"),m(K(o),"font must be a string"),m(K(c),"fontStyle must be a string"),m(O(u),"angle must be a number");let d=(t+"").split(`
+`),f=e.y-(d.length-1)*n/2;h.save(),h.fillStyle=s.toString(),h.strokeStyle=r.toString(),h.lineWidth=i,h.textAlign=a,h.font=c+" "+n+"px "+o,h.textBaseline="middle",h.translate(e.x,f),h.rotate(-u);let p=0;d.forEach(y=>{i&&h.strokeText(y,0,p,l),h.fillText(y,0,p,l),p+=n}),h.restore()}async function Dc(t,e){m(O(t),"textureIndex must be a number"),m(!Tn[t],"textureIndex is already loaded!"),m(!e||K(e),"image src must be a string");let n=new Image;e&&await new Promise(s=>{n.onerror=n.onload=s,n.crossOrigin="anonymous",n.src=e}),Tn[t]=new Qt(n)}function oi(t){m(D(t),"screenPos must be a vec2");let e=(t.x-N.x/2+.5)/ee,n=(t.y-N.y/2+.5)/-ee;if(ae){let s=ye(-ae),i=fe(-ae),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new me(e+Ie.x,n+Ie.y)}function qn(t){m(D(t),"worldPos must be a vec2");let e=t.x-Ie.x,n=t.y-Ie.y;if(ae){let s=ye(ae),i=fe(ae),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new me(e*ee+N.x/2-.5,n*-ee+N.y/2-.5)}function gl(t){m(D(t),"screenDelta must be a vec2");let e=t.x/ee,n=t.y/-ee;if(ae){let s=ye(-ae),i=fe(-ae),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new me(e,n)}function Ff(t){m(D(t),"worldDelta must be a vec2");let e=t.x,n=t.y;if(ae){let s=ye(ae),i=fe(ae),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new me(e*ee,n*-ee)}function ri(t,e,n=0){return m(D(t),"screenPos must be a vec2"),m(D(e),"screenSize must be a vec2"),m(O(n),"screenAngle must be a number"),[oi(t),e.scale(1/ee),n+ae]}function bl(){return N.scale(1/ee)}function Gf(t,e,n,s){m(D(t),"center must be a vec2"),m(D(e),"size must be a vec2");let i=d(n),r=d(s),a=e.x+i.left+i.right,o=e.y+i.top+i.bottom,c=N.x-r.left-r.right,l=N.y-r.top-r.bottom;if(!(a>0&&o>0&&c>0&&l>0))return ee;ee=le(c/a,l/o);let u=v(i.right-i.left,i.top-i.bottom).scale(.5),h=v(r.right-r.left,r.top-r.bottom).scale(.5/ee);return Ie=t.add(u).add(h),ee;function d(f){return(f===void 0||O(f))&&(f=v(f)),D(f)?{top:f.y,right:f.x,bottom:f.y,left:f.x}:{top:f.top||0,right:f.right||0,bottom:f.bottom||0,left:f.left||0}}}function Bf(t,e=0){if(m(D(t),"pos must be a vec2"),m(D(e)||O(e),"size must be a vec2 or number"),!ee)return!1;let n=t.x-Ie.x,s=t.y-Ie.y;if(ae){let a=ye(ae),o=fe(ae),c=n*a-s*o,l=n*o+s*a;n=c,s=l}n*=ee*2,s*=-ee*2,e instanceof me&&(e=e.length()),e*=ee;let i=N.x,r=N.y;return n+e>-i&&n-e-r&&s-e{t.onerror=t.onload=o,t.crossOrigin="anonymous",t.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAAeAQMAAABnrVXaAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAAjpJREFUOMu9kzFu2zAUhn+CAROgqrk+B2l0BWYxMjlXeYaAtFtbdA1sGgHqRQfI0CNkSG5AwYB0BQ8d5Bsomwah6CPVeGg6tEPzAxLwyI+P78cP4u9lNO9OoMKnLMOobG5020/yaj/MrRcCGh1gBbyiLTPJEYaIiom5KM9Jq7KgynMGtb6L4GL4MF2H4LQKCXTvDVw2I4MsgZT7QLExdiutH+D08VOP3INXRrWX1/mmpbkNgAPYRVANb4xpcegYvhiNbIXauQICEjBuYLfMakaakWQeXxiZ0VDtuJCKs3ztMV59QtsHJNcRxDzfdL21ty3PrfIcXTN+E+GFAv6T5nbT9jd50/WFxb5ksdAv49qS6ouymG66ji08UMT6moykYLAo+V0j23GN4m829ZySAD5K7QsBfQTvOG8eE+gTeGYRAmnNAubN3hf5Zv9tJWDHp/VTuaSm7SN4fyINQqaNO3RMVxvpSPXnOChnRNvFcGY0gnwiPswYwTKVPE0zVtX3mTEIOoFzaqLrGuJaV+Uqumb71fVk/VoOH3cdLNQP/FHi8hV0CQNoqBZsUPlLPMsdCJro9QAaQQ0woDy9BJm0eTxCFnO9srcYlhNVlfR2EyTrph1uUtbUtAJifwRgrKuYdXVHeb0YI3QpawohQHkloI3J5FuVwI5ORxC9k2Tuz9Ir1IjgeIPGMHYkAZe2RuYkmWFmt3gGbTPOmBUWVTmRmHtGrfpzG/yuQNOKa6gBB/WA9khitPgl6/GP+gl2Af6tCbvaygAAAABJRU5ErkJggg=="});let e=v(),n=v(8),s=1,i=0,r=new Qt(t),a=new It(e,n,r,s,i);Sl=new Di(a)}function Vf(t=!0){os=t}function Wf(t){pa=t}function qf(){return pn==="mouse"}function Hf(){return pn==="keyboard"}function $f(){return pn==="gamepad"}function ma(t,e=0,n=!0,s=!0,i=!0){ie[e]&&(ie[e][t]&=~((n?1:0)|(s?2:0)|(i?4:0)))}function ai(){ie.length=0,ie[0]=[],ht.length=0,Nn.length=0,ci.length=0,_t.length=0,Mn.length=0}function Ge(t,e=0){var n;return m(K(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=ie[e])==null?void 0:n[t])&1)}function Ne(t,e=0){var n;return m(K(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=ie[e])==null?void 0:n[t])&2)}function ya(t,e=0){var n;return m(K(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=ie[e])==null?void 0:n[t])&4)}function Yf(t="ArrowUp",e="ArrowDown",n="ArrowLeft",s="ArrowRight"){m(K(t),"up key must be a string"),m(K(e),"down key must be a string"),m(K(n),"left key must be a string"),m(K(s),"right key must be a string");let i=r=>Ge(r)?1:0;return v(i(s)-i(n),i(t)-i(e))}function Ds(t){return m(O(t),"mouse button must be a number"),Ge(t)}function Js(t){return m(O(t),"mouse button must be a number"),Ne(t)}function Xf(t){return m(O(t),"mouse button must be a number"),ya(t)}function Nt(t,e=Ae){return m(O(t),"button must be a number"),m(O(e),"gamepad must be a number"),Ge(t,e+1)}function ga(t,e=Ae){return m(O(t),"button must be a number"),m(O(e),"gamepad must be a number"),Ne(t,e+1)}function Kf(t,e=Ae){return m(O(t),"button must be a number"),m(O(e),"gamepad must be a number"),ya(t,e+1)}function Ns(t,e=Ae){var n,s;return m(O(t),"stick must be a number"),m(O(e),"gamepad must be a number"),(s=(n=_t[e])==null?void 0:n[t])!=null?s:v()}function ar(t=Ae){var e;return m(O(t),"gamepad must be a number"),(e=Mn[t])!=null?e:v()}function cr(t=Ae){return m(O(t),"gamepad must be a number"),!!ie[t+1]}function vl(t=Ae){var e,n;return m(O(t),"gamepad must be a number"),(n=(e=_t[t])==null?void 0:e.length)!=null?n:0}function Qf(t=Ae,e=200,n=1,s=1,i=0){var a,o,c;if(m(O(t),"gamepad must be a number"),!si||$)return;let r=(a=navigator==null?void 0:navigator.getGamepads)==null?void 0:a.call(navigator)[t];(c=(o=r==null?void 0:r.vibrationActuator)==null?void 0:o.playEffect)==null||c.call(o,"dual-rumble",{duration:e,strongMagnitude:n,weakMagnitude:s,startDelay:i})}function Zf(t=Ae){var n,s,i;if(m(O(t),"gamepad must be a number"),!si||$)return;let e=(n=navigator==null?void 0:navigator.getGamepads)==null?void 0:n.call(navigator)[t];(i=(s=e==null?void 0:e.vibrationActuator)==null?void 0:s.reset)==null||i.call(s)}function ba(t=100){var e;m(O(t)||St(t),"pattern must be a number or array"),si&&!$&&((e=navigator==null?void 0:navigator.vibrate)==null||e.call(navigator,t))}function eh(){ba(0)}function th(){var t;!ft&&((t=q.requestPointerLock)==null||t.call(q))}function nh(){var t;(t=document.exitPointerLock)==null||t.call(document)}function wl(){return document.pointerLockElement===q}function sh(){if($)return;document.addEventListener("keydown",t),document.addEventListener("keyup",e),document.addEventListener("mousedown",s),document.addEventListener("mouseup",i),document.addEventListener("mousemove",r),document.addEventListener("mouseleave",a),document.addEventListener("wheel",o,{passive:!1}),document.addEventListener("contextmenu",c),document.addEventListener("blur",l),ft&&On&&u();function t(d){if(d.repeat||(ie[0][d.code]=3,Ls&&(ie[0][n(d.code)]=3)),!os||!d.cancelable||!document.hasFocus()||d.ctrlKey||d.metaKey||d.altKey||y(d.target)||y(document.activeElement))return;let f=typeof d.key=="string"&&d.key.length===1;(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Space","Tab","Backspace"].includes(d.code)||f)&&d.preventDefault();function y(x){let w=x==null?void 0:x.tagName;return(x==null?void 0:x.isContentEditable)||["INPUT","TEXTAREA","SELECT"].includes(w)}}function e(d){ie[0][d.code]=ie[0][d.code]&2|4,Ls&&(ie[0][n(d.code)]=4)}function n(d){return Ls?d==="KeyW"?"ArrowUp":d==="KeyS"?"ArrowDown":d==="KeyA"?"ArrowLeft":d==="KeyD"?"ArrowRight":d:d}function s(d){if(ft&&On)return;nt&&!$&&ve&&!Us()&&ve.resume(),ie[0][d.button]=3;let f=Ke;Ke=h(v(d.x,d.y)),Ct=Ct.add(Ke.subtract(f)),os&&d.cancelable&&document.hasFocus()&&d.preventDefault()}function i(d){ft&&On||(ie[0][d.button]=ie[0][d.button]&2|4)}function r(d){Ii=!0;let f=Ke;Ke=h(v(d.x,d.y));let p=wl()?v(d.movementX,d.movementY):Ke.subtract(f);Ct=Ct.add(p)}function a(){Ii=!1}function o(d){d.ctrlKey||(ha+=ut(d.deltaY)),os&&d.cancelable&&document.hasFocus()&&d.preventDefault()}function c(d){d.preventDefault()}function l(){ai(),Ht.clear(),ht.length=0,Nn.length=0,ci.length=0}function u(){document.addEventListener("touchstart",p=>f(p),{passive:!1}),document.addEventListener("touchmove",p=>f(p),{passive:!1}),document.addEventListener("touchend",p=>f(p),{passive:!1});let d;function f(p){if(On){if(nt&&!$&&ve&&!Us()&&ve.resume(),!wn||ra){let y=S=>zs.includes(S.target)||S.target===Ln,x=[];for(let S of p.touches)y(S)||x.push(S);let w=x.length,A=0;if(w){let S=v(x[0].clientX,x[0].clientY),_=Ke;Ke=h(S),d?Ct=Ct.add(Ke.subtract(_)):ie[0][A]=3}else d&&(ie[0][A]=ie[0][A]&2|4);d=w}return os&&p.cancelable&&document.hasFocus()&&p.preventDefault(),!0}}}function h(d){let f=q.getBoundingClientRect(),p=Ve(d.x,f.left,f.right),y=Ve(d.y,f.top,f.bottom);return v(p*q.width,y*q.height)}}function Fc(){if($)return;!(On&&ft)&&!document.hasFocus()&&ai(),Jt=oi(Ke),fa=gl(Ct),oh(),e(),t();function t(){let n=Ds(0)||Ds(1)||Ds(2)||Ct.length()>pa,s=!1;for(let r=vl();r--&&!s;)s=Ns(r).lengthSquared()>.04;for(let r=17;r--&&!s;)s=Nt(r);let i=!1;for(let r in ie[0])if(isNaN(+r)&&ie[0][r]&1){i=!0;break}s?pn="gamepad":n?pn="mouse":i&&(pn="keyboard"),as=pn==="gamepad"}function e(){var a,o,c,l,u,h,d;let n=f=>{let x=w=>w>.3?Ve(w,.3,.8):w<-.3?-Ve(-w,.3,.8):0;return v(x(f.x),x(-f.y)).clampLength()};if(wn&&ft){if(m(!Vn||!bs,"set touchGamepadLeftStick or touchGamepadLeftButtonCount, not both"),m(!xs||!gs,"set touchGamepadRightStick or touchGamepadButtonCount, not both"),!fs.isSet())return;Ae=0;let f=(a=_t[0])!=null?a:_t[0]=[],p=(o=Mn[0])!=null?o:Mn[0]=v();f.length=0,p.set();for(let x=0;x<2;x++){if(!Zt(x))continue;let w=va(x);f[w]=v();let A=(c=Nn[x])!=null?c:v();if(ni)f[w]=n(A);else if(A.lengthSquared()>.3){let S=H(Ci(A.x),-1,1),_=H(Ci(A.y),-1,1);f[w]=v(S,-_).clampLength(),w||p.set(S,-_)}}let y=(l=ie[1])!=null?l:ie[1]=[];for(let x=12;x--;){let w=Nt(x,0);y[x]=ht[x]?w?1:3:w?4:0,Pi&&y[x]===3&&(x===9||rh(x))&&ba(Pi)}return}try{if(!uo||!(navigator!=null&&navigator.getGamepads))return}catch{return}if(!Ue&&!document.hasFocus())return;let s=8,i=navigator.getGamepads(),r=le(s,i.length);for(let f=0;f>1]=n(v(p.axes[S],p.axes[S+1]));let A=!1;for(let S=p.buttons.length;S--;){let _=p.buttons[S],k=Nt(S,f);y[S]=_.pressed?k?1:3:k?4:0,_.pressed&&(!_.value||_.value>.9)&&(A=!0)}A&&(Qo[f]=!0,Qo[Ae]||(Ae=f)),p.mapping==="standard"&&w.set((Nt(15,f)&&1)-(Nt(14,f)&&1),(Nt(12,f)&&1)-(Nt(13,f)&&1)),oa&&(w.x||w.y)&&(x[0]=w.clampLength())}wn&&as&&fs.unset()}}function Gc(){if(!$){for(let t of ie)for(let e in t)t[e]&=1;ha=0,fa=v(),Ct=v()}}function ih(){uh()}function oh(){if(dn||!wn||!ft||$||!document.body)return;let t=dn=document.createElement("div");t.style.cssText="position:fixed;inset:0;z-index:50;pointer-events:none;opacity:0;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;transition:opacity .2s;box-sizing:border-box;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)";let e=Tl=document.createElement("div");e.style.cssText="position:relative;width:100%;height:100%;pointer-events:none",t.appendChild(e);let n=xa=document.createElementNS(Gi,"svg");n.style.cssText="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible;fill:none;stroke:#fff;stroke-width:3",e.appendChild(n);let s=()=>{let i=document.createElement("div");return i.style.cssText="position:absolute;pointer-events:auto;touch-action:none",i.addEventListener("pointerdown",r=>ph(r,i)),i.addEventListener("pointermove",r=>mh(r)),i.addEventListener("pointerup",r=>Bc(r)),i.addEventListener("pointercancel",r=>Bc(r)),e.appendChild(i),i};zs[0]=s(),zs[1]=s(),Ln=s(),addEventListener("resize",()=>hs=!0),document.body.appendChild(t),hs=!0}function fo(){return Tl.getBoundingClientRect()}function Zt(t){return t?xs:Vn}function Hn(t){return t?gs:bs}function Sa(t){return t?0:4}function va(t){return t&&Vn?1:0}function ps(t){return Zt(t)||Hn(t)>0}function rh(t){for(let e=0;e<2;e++){let n=Sa(e);if(!Zt(e)&&t>=n&&tr.style.cssText="position:absolute;pointer-events:auto;touch-action:none;"+a;if(Mt){for(let r of zs)r.style.display="none";vt?(i(Ln,"inset:0"),Ln.style.display=""):Ln.style.display="none"}else{for(let a=0;a<2;a++){let o=zs[a],c=a?"right":"left";if(o.style.display=ps(a)?"":"none",An){let l=ps(a?0:1)?"50%":"100%";i(o,`${c}:0;bottom:0;width:${l};height:60%`)}else i(o,`${c}:0;bottom:0;width:${3*s}px;height:${3*s}px`)}Ln.style.display=vt?"":"none";let r=vt;i(Ln,`left:50%;top:50%;width:${2*r}px;height:${2*r}px;transform:translate(-50%,-50%)`)}ch(e,n),hs=!1}function ch(t,e){let n=xa;for(;n.firstChild;)n.removeChild(n.firstChild);let s=Al={face:[],thumb:[]},i=tt,r=(o,c,l,u)=>{let h=document.createElementNS(Gi,"circle");return h.setAttribute("cx",o),h.setAttribute("cy",c),h.setAttribute("r",l),u&&h.setAttribute("fill",u),n.appendChild(h),h},a=o=>{let c=i*.18,l=i*.5,u=o.x,h=o.y,d=document.createElementNS(Gi,"path");d.setAttribute("d",`M ${u-c} ${h-l} H ${u+c} V ${h-c} H ${u+l} V ${h+c} H ${u+c} V ${h+l} H ${u-c} V ${h+c} H ${u-l} V ${h-c} H ${u-c} Z`),n.appendChild(d)};for(let o=0;o<2;o++){let c=Hn(o),l=Sa(o),u=Yt(o,t,e);if(Zt(o))ni?r(u.x,u.y,i/2):a(u),s.thumb[o]=r(u.x,u.y,i/4,"#fff");else if(c===1)s.face[l]=r(u.x,u.y,i/2,"#000");else for(let h=0;h2?d:le(d,c-1);f=f===3?2:f===2?3:f;let p=v().setDirection(d,i/2);c===2&&(p.x*=-1),o||(p.x*=-1);let y=u.add(p);s.face[l+f]=r(y.x,y.y,i/4,"#000")}}Ue&&Gn&&lh(t,e)}function lh(t,e){let n=tt,s=xa,i=(a,o,c)=>{let l=document.createElementNS(Gi,a);for(let u in o)l.setAttribute(u,o[u]);l.setAttribute("stroke",c),l.setAttribute("stroke-width",2),l.setAttribute("fill","none"),s.appendChild(l)},r=(a,o,c)=>i("circle",{cx:a.x,cy:a.y,r:o},c);i("line",{x1:t/2,y1:0,x2:t/2,y2:e},"#0f0");for(let a=0;a<2;a++)if(Zt(a))if(An){let o=e*.4,c=!ps(a?0:1),l=c?0:a?t/2:0;i("rect",{x:l,y:o,width:c?t:t/2,height:e-o},"#0ff")}else r(Yt(a,t,e),2*n,"#0ff");else Hn(a)>=1&&r(Yt(a,t,e),n,"#0ff");if(vt){r(v(t/2,e/2),vt,"#ff0");for(let a=0;a<2;a++)ps(a)&&r(Yt(a,t,e),2*n,"#f0f")}}function uh(){var l;if(!dn||$)return;if(!wn||!ft){dn.style.display!=="none"&&(dn.style.display="none",Ht.clear(),ht.length=0,Nn.length=0,ci.length=0);return}dn.style.display="";let t=Ue&&Gn,e=[gs,bs,Vn,xs,ni,tt,An,vt,Mt,t].join();e!==Ic&&(Ic=e,hs=!0),hs&&ah();let n=Os?Ve(fs.get(),Os+1,Os):1,s=t||fs.isSet()&&n>0&&!Mt;if(dn.style.opacity=s?t?1:n*aa:0,!s)return;let i=fo(),r=i.width,a=i.height,o=tt,c=Al;if(c){for(let u=0;u<2;u++)if(Zt(u)&&c.thumb[u]){let d=Yt(u,r,a).add(((l=Nn[u])!=null?l:v()).scale(o/2));c.thumb[u].setAttribute("cx",d.x),c.thumb[u].setAttribute("cy",d.y)}for(let u=0;u=tt)return-1;if(i===1)return r;let o=a.subtract(e);t||(o.x*=-1);let c=i===2?o.xr:o&&Yt(a,e,n).distance(t)<2*s)return{role:"stick",side:a}}else if(Hn(a)>=1){let c=fh(a,t,e,n);if(c>=0)return{role:"face",btn:c}}}if(vt){for(let a=0;a<2;a++)if(ps(a)&&Yt(a,e,n).distance(t)<2*s)return;if(v(e/2,n/2).distance(t)h.getChannelData(x).set(y)),d.buffer=h,d.playbackRate.value=n,d.loop=i,a=a||ve.createGain(),a.gain.value=e,a.connect(Xt);let f=new StereoPannerNode(ve,{pan:H(s,-1,1)});d.connect(f).connect(a),d.addEventListener("ended",()=>{a.disconnect(),f.disconnect(),c&&c(d)});let p=o*n;return d.start(0,p),Ue&&us&&Ce("sound","vol",e.toFixed(2),"rate",n.toFixed(2),"pan",s.toFixed(2),i?"loop":""),d}function xh(...t){return wa([ho(...t)])}function ho(t=1,e=.05,n=220,s=0,i=0,r=.1,a=0,o=1,c=0,l=0,u=0,h=0,d=0,f=0,p=0,y=0,x=0,w=1,A=0,S=0,_=0){let k=Ss,C=te*2,L=c*=500*C/k/k,V=n*=(1+Se(e,-e))*C/k,ce=0,ne=0,T=0,P=1,R,M=[],j=0,se=0,we=0,be,Ft=2,en=C*de(_)*2/k,We=ye(en),Gt=fe(en)/2/Ft,lt=1+Gt,mt=-2*We/lt,Yn=(1-Gt)/lt,Bt=(1+ut(_)*We)/2/lt,Xn=-(ut(_)+We)/lt,vs=Bt,tn=0,nn=0,sn=0,Kn=0;for(s=s*k||9,A*=k,i*=k,r*=k,x*=k,l*=500*C/k**3,p*=C/k,u*=C/k,h*=k,d=d*k|0,R=s+A+i+r+x|0;se1?a>2?a>3?a>4?j/C%14?we:ut(we)*de(we)**o)*(sese?0:(seh&&(n+=u,V+=u,P=0),d&&!(++ne%d)&&(n=V,c=L,P||(P=1));return M}function ji(t,e=!0){for(let n of xn)if((!e||n.isSolid)&&t.arrayCheck(n.size)){let s=n.getCollisionData(t);if(s)return s}return 0}function fn(t,e=v(),n,s=!0){for(let i of xn)if((!s||i.isSolid)&&i.collisionTest(t,e,n))return i}function _l(t,e,n,s,i=!0){let r,a,o,c=s&&v();for(let l of xn)if(!i||l.isSolid){let u=l.collisionRaycast(t,e,n,c);if(u){let h=t.distanceSquared(u);(r===void 0||h{W=!1,ue.style.display="none",n.preventDefault(),Ce("WebGL context lost! Switching to Canvas2d rendering.");for(let s of Is)s.glTexture=void 0;at=void 0,De=0,zn=!1,In.forEach(s=>{var i;return(i=s.glContextLost)==null?void 0:i.call(s)})}),ue.addEventListener("webglcontextrestored",()=>{W=!0,ue.style.display="",Ce("WebGL context restored, reinitializing..."),e();for(let n of Is)n.glTexture=mo(n.image,n.wrap);In.forEach(n=>{var s;return(s=n.glContextRestored)==null?void 0:s.call(n)})});function e(){zi=ys(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 g;in vec4 p,u,c,a;in float r;out vec2 v;out vec4 d,e;void main(){vec2 s=(g-.5)*p.zw;gl_Position=m*vec4(p.xy+s*cos(r)-vec2(-s.y,s)*sin(r),1,1);v=mix(u.xw,u.zy,g);d=c;e=a;}`,`#version 300 es
+precision highp float;uniform sampler2D s;in vec2 v;in vec4 d,e;out vec4 c;void main(){c=texture(s,v)*d+e;}`),Ui=ys(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 p;in vec4 c;out vec4 d;void main(){gl_Position=m*vec4(p,1,1);d=c;}`,`#version 300 es
+precision highp float;in vec4 d;out vec4 c;void main(){c=d;}`);let n=new ArrayBuffer(Wi);ze=new Float32Array(n),Hs=new Uint32Array(n),ur=g.createBuffer(),cs=g.createBuffer(),Aa=g.createFramebuffer(),De=0;let s=new Float32Array([0,0,1,0,0,1,1,1]);g.bindBuffer(g.ARRAY_BUFFER,cs),g.bufferData(g.ARRAY_BUFFER,s,g.STATIC_DRAW);let i,r,a,o=(c,l,u,h,d=0)=>{let f=g.getAttribLocation(r,c),p=u===1,y=u&&a;g.enableVertexAttribArray(f),g.vertexAttribPointer(f,h,l,p,y,i),g.vertexAttribDivisor(f,d),i+=h*u};dr=g.createVertexArray(),g.bindVertexArray(dr),i=0,r=zi,a=El,g.bindBuffer(g.ARRAY_BUFFER,cs),o("g",g.FLOAT,0,2),g.bindBuffer(g.ARRAY_BUFFER,ur),g.bufferData(g.ARRAY_BUFFER,Wi,g.DYNAMIC_DRAW),o("p",g.FLOAT,4,4,1),o("u",g.FLOAT,4,4,1),o("c",g.UNSIGNED_BYTE,1,4,1),o("a",g.UNSIGNED_BYTE,1,4,1),o("r",g.FLOAT,4,1,1),fr=g.createVertexArray(),g.bindVertexArray(fr),i=0,r=Ui,a=Rl,o("p",g.FLOAT,4,2),o("c",g.UNSIGNED_BYTE,1,4)}}function $s(t=!1){!t&&!zn||(Fe(),zn=!1,g.useProgram(zi),g.bindVertexArray(dr))}function Pl(){zn||(Fe(),zn=!0,g.useProgram(Ui),g.bindVertexArray(fr))}function pr(t=!0){if(!W||!g)return;m(!De,"glPreRender called with unflushed batch."),Vi||(ue.width=N.x,ue.height=N.y),g.viewport(0,0,N.x,N.y),t&&Ml();let e=v(2*ee).divide(N);Vi&&(e.y=-e.y);let n=Ie.rotate(-ae),s=v(-1).subtract(n.multiply(e)),i=ye(ae),r=fe(ae),a=[e.x*i,e.y*r,0,0,-e.x*r,e.y*i,0,0,1,1,1,0,s.x,s.y,0,1],o=(c,l,u)=>{g.useProgram(c);let h=g.getUniformLocation(c,l);g.uniformMatrix4fv(h,!1,u)};o(Ui,"m",a),o(zi,"m",a),g.activeTexture(g.TEXTURE0),Tn[0]&&(at=Tn[0].glTexture,g.bindTexture(g.TEXTURE_2D,at)),g.bindBuffer(g.ARRAY_BUFFER,ur),$n=ms=!1,$s(!0)}function Ml(){if(!g)return;let t=yn;g.clearColor(t.r,t.g,t.b,t.a),g.clear(g.COLOR_BUFFER_BIT)}function Ca(t){!g||t===at||(Fe(),at=t,g.bindTexture(g.TEXTURE_2D,at))}function Ll(t,e=!0){if(!g||!t)return;let n=t===at;n?Fe():g.bindTexture(g.TEXTURE_2D,t);let s=e?g.REPEAT:g.CLAMP_TO_EDGE;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,s),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,s),!n&&at&&g.bindTexture(g.TEXTURE_2D,at)}function mr(t,e){if(!g)return;let n=g.createShader(e);if(g.shaderSource(n,t),g.compileShader(n),Ue&&!g.getShaderParameter(n,g.COMPILE_STATUS))throw g.getShaderInfoLog(n);return n}function ys(t,e){if(!g)return;let n=g.createProgram();if(g.attachShader(n,mr(t,g.VERTEX_SHADER)),g.attachShader(n,mr(e,g.FRAGMENT_SHADER)),g.linkProgram(n),Ue&&!g.getProgramParameter(n,g.LINK_STATUS))throw g.getProgramInfoLog(n);return n}function mo(t,e=!1){if(!g)return;let n=g.createTexture(),s=!1;if(t!=null&&t.width)_a(n,t),g.bindTexture(g.TEXTURE_2D,n),s=!Jn&&Gs(t.width)&&Gs(t.height);else{let o=new Uint8Array([255,255,255,255]);g.bindTexture(g.TEXTURE_2D,n),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,1,1,0,g.RGBA,g.UNSIGNED_BYTE,o)}let i=Jn?g.NEAREST:g.LINEAR,r=s?g.LINEAR_MIPMAP_LINEAR:i;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,i),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,r);let a=e?g.REPEAT:g.CLAMP_TO_EDGE;return g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,a),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,a),s&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,at),n}function Ol(t){g&&g.deleteTexture(t)}function _a(t,e){g&&(m((e==null?void 0:e.width)>0,"Invalid image data."),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e),!Jn&&Gs(e.width)&&Gs(e.height)&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,at))}function Ah(t){$||(Is.add(t),g&&(t.glTexture?_a(t.glTexture,t.image):t.glTexture=mo(t.image,t.wrap)))}function kh(t){if($)return;Is.delete(t);let e=t.glTexture;t.glTexture=void 0,Ol(e)}function Fe(){if(W&&g&&De){let t=ms?g.ONE:g.ONE_MINUS_SRC_ALPHA;g.blendFuncSeparate(g.SRC_ALPHA,t,g.ONE,t),g.enable(g.BLEND);let e=De*(zn?po:ka);g.bufferSubData(g.ARRAY_BUFFER,0,ze,0,e),zn?g.drawArrays(g.TRIANGLE_STRIP,0,De):g.drawArraysInstanced(g.TRIANGLE_STRIP,0,4,De),++Ot,Dt+=De,De=0}ms=$n}function Ea(t){!W||!g||(Fe(),t.drawImage(ue,0,0))}function Ch(t=!0){m(!ue,"must be called before engineInit"),Ta=t}function Ys(t,e,n,s,i=0,r=0,a=0,o=1,c=1,l=-1,u=0){(De>=wh||ms!==$n)&&Fe(),$s();let h=De++*ka;ze[h++]=t,ze[h++]=e,ze[h++]=n,ze[h++]=s,ze[h++]=r,ze[h++]=a,ze[h++]=o,ze[h++]=c,Hs[h++]=l,Hs[h++]=u,ze[h++]=i}function Dl(t,e,n,s,i,r){Ys(t,e,n,s,i,0,0,0,0,0,r)}function Ra(t,e,n,s,i,r,a,o=!0){let c=[],l=fe(-a),u=ye(-a);for(let d of t){let f=d.x*i,p=d.y*r;c.push(v(n+u*f-l*p,s+l*f+u*p))}let h=o?Eh(c):c;Il(h,e)}function Pa(t,e,n,s,i,r,a,o,c=!0){let l=_h(t,n,c);Ra(l,e,s,i,r,a,o,!1)}function Il(t,e){if(!W||t.length<3)return;let n=t.length+2;if((De+n>=ls||ms!==$n)&&Fe(),m(n=ls)return;Pl();let s=De*po;for(let i=n;i--;){let r=H(i-1,0,n-3),a=t[r];ze[s++]=a.x,ze[s++]=a.y,Hs[s++]=e}De+=n}function Ma(t,e){if(!W||t.length<3)return;let n=t.length+2;if((De+n>=ls||ms!==$n)&&Fe(),m(n=ls)return;Pl();let s=De*po;for(let i=n;i--;){let r=H(i-1,0,n-3),a=t[r],o=e[r];ze[s++]=a.x,ze[s++]=a.y,Hs[s++]=o}De+=n}function Ps(t,e=!1){t?(Vi=t,g.bindFramebuffer(g.FRAMEBUFFER,Aa),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,t,0),pr(e)):(Fe(),Vi=void 0,g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,N.x,N.y))}function Fl(t,e,n,s){W&&(g.enable(g.SCISSOR_TEST),g.scissor(t,e,n,s),g.clearColor(0,0,0,0),g.clear(g.COLOR_BUFFER_BIT),g.disable(g.SCISSOR_TEST))}function _h(t,e,n=!0){if(t.length<2)return[];let s=e/2,i=[],r=t.length,a=1e-6,o=10;for(let c=0;ca?-f/p:0,S=p>a?d/p:0,_=w>a?-x/w:0,k=w>a?y/w:0,C=A+_,L=S+k,V=(C*C+L*L)**.5;if(Va){let P=le(1/T,o);C*=P,L*=P}}let ce=v(u.x-C*s,u.y-L*s),ne=v(u.x+C*s,u.y+L*s);i.push(ce),i.push(ne)}return i.length>1&&n&&(i.push(i[0]),i.push(i[1])),i}function Eh(t){if(t.length<3)return[];let e=(f,p,y)=>(p.x-f.x)*(y.y-f.y)-(p.y-f.y)*(y.x-f.x);(f=>{let p=0;for(let y=f.length;y--;){let x=(y+1)%f.length;p+=f[y].cross(f[x])}return p})(t)<0&&(t=t.slice().reverse());let s=1e-9,i=(f,p,y,x)=>{let w=e(p,y,f),A=e(y,x,f),S=e(x,p,f),_=(w<-s?1:0)+(A<-s?1:0)+(S<-s?1:0),k=(w>s?1:0)+(A>s?1:0)+(S>s?1:0);return!(_&&k)},r=[];for(let f=0;f3&&o++{if(_>=0){let C=s.fillStyle=s.createLinearGradient(x,w,A,S);C.addColorStop(0,h(_,2)),C.addColorStop(1,h(_,1))}else s.fillStyle="#000";_>=-1?(s.fill(),k&&s.stroke()):s.stroke()},c=(x,w,A,S=0,_=2*te,k,C)=>{s.beginPath(),s.arc(x,w,A,f*S,f*_),o(x,w-A,x,w+A,k,C)},l=(x,w,A,S,_)=>{s.beginPath(),s.rect(x,w,A,S*f),o(x,w+S,x+A,w,_)},u=(x,w,A,S)=>{s.beginPath();for(let _ of x)s.lineTo(_.x,_.y);s.closePath(),o(0,A,0,A+S,w)},h=(x,w)=>w?`hsl(${[.95,.56,.13][x%3]*360} 99%${[0,50,75][w]}%)`:"#000",d=nl(1,1,t),f=Ve(d,.1,.5),p=le(6,le(r,a)/99);s.translate(r/2,a/2),s.scale(p,p),s.translate(-40,-35),f<1&&s.setLineDash([99*f,99]),s.lineJoin=s.lineCap="round",s.lineWidth=.1+f*1.9;{let w="LittleJS";s.font="900 15.5px arial",s.lineWidth=.1+f*3.9,s.textAlign="center",s.textBaseline="top",l(11,55,59,8*f,-1),s.beginPath();let A=0;for(let S=0;S5?1:0),s[S?"strokeText":"fillText"](w[_],L,54+.5,17*f),k+=C}s.lineWidth=.1+f*1.9,l(3,54,73,0)}l(7,15,26,-7,0),l(25,15,8,25,-1),l(10,40,15,-25,1),l(14,21,7,9,2),l(38,20,6,-6,2),l(49,20,10,-6,0);let y=[v(44,8),v(64,8),v(59,8+6*f),v(49,8+6*f)];u(y,2,8,6*f),l(44,8,20,-7,0);for(let x=5;x--;)c(59-x*6*f,30,10,0,2*te,1,0);c(59,30,4,0,7,2),l(35,20,24,0),c(59,30,10),c(47,30,10,te/2,te*3/2),c(35,30,10,te/2,te*3/2),l(7,40,13,7,-1),l(17,40,43,14,-1);for(let x=3;x--;)for(let w=2;w--;)c(17+15*x,47,w?7:1,0,2*te,2);for(let x=2;x--;){let w=6,A=7,S=53+w*f*x,_=[v(S+A,54),v(S,40),v(S+w*f,40),v(S+A+w*f,54)];u(_,0,40,14)}s.restore()}function Ph(t){if($i=t,!Pn){let n={};try{n=JSON.parse(localStorage[t]||"{}")}catch{n={}}yo(s=>{s.unlocked=!!(n[s.id]&&n[s.id].unlocked)}),Oa()}Un(void 0,e);function e(){if(!wi.length)return;let n=wi[0],s=Sn-vi;if(!vi)vi=Sn;else if(s>qi)vi=0,wi.shift();else{let i=qi-rs,r=si?(s-i)/rs:0;n.render(r)}}}function yo(t){Object.values(Xs).forEach(e=>t(e))}function Mh(){yo(t=>t.unlocked=!1),Oa()}function Oa(){if(!$i)return;let t={};yo(e=>{let n={name:e.name,description:e.description,icon:e.icon,unlocked:e.unlocked};e.image&&(n.src=e.image.src),t[e.id]=n}),localStorage[$i]=JSON.stringify(t)}function Lh(t){qi=t}function Oh(t){rs=t}function Dh(t){Hi=t.copy()}function Ih(t){La=t}function Gl(t,e,n,s=125){let i,r,a,o,c,l,u,h,d,f,p,y,x,w=0,A,S=[],_=[],k=[],C=0,L=0,V=1,ce={},ne=Ss/s*60>>2;for(;V;C++)S=[V=h=y=0],n.forEach((T,P)=>{for(u=e[T][C]||[0,0,0],V|=e[T][C]&&1,A=y+(e[T][0].length-2-(h?0:1))*ne,x=P===n.length-1,i=2,a=y;ine-99&&d&&p<1?p+=1/99:0)l=(1-p)*S[w++]/2||0,_[a]=(_[a]||0)-l*L+l,k[a]=(k[a++]||0)+l*L+l;c&&(p=c%1,L=u[1]||0,(c|=0)&&(S=ce[[f=u[w=0]||0,c]]=ce[[f,c]]||(o=[...t[f]],o[2]=(o[2]||220)*2**(c/12-1),c>0?ho(...o):[])))}y=A});return[_,k]}function Fh(t){Da=typeof t=="boolean"?t?1:0:t}function Gh(t){Ia=t}async function Bh(){return new eo(await Box2D()),n(),Un(t,e),b;function t(){if(!Mt){b.step(),b.objects=b.objects.filter(s=>!s.destroyed);for(let s of b.objects)s.body&&(s.pos=b.vec2From(s.body.GetPosition()),s.angle=-s.body.GetAngle())}}function e(){(Ia||bt)&&b.world.DrawDebugData()}function n(){let i=new b.instance.JSDraw,r=l=>new Me(l.get_r(),l.get_g(),l.get_b()),a=l=>r(b.instance.wrapPointer(l,b.instance.b2Color)),o=l=>a(l).scale(1,.8),c=(l,u)=>{let h=[];for(let d=u;d--;)h.push(b.vec2FromPointer(l+d*8));return h};i.DrawSegment=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),u=b.vec2FromPointer(u),Dn(l,u,.1,h,v(),0,!1)},i.DrawPolygon=function(l,u,h){h=o(h);let d=c(l,u);ds(d,vn,.1,h,v(),0,!1)},i.DrawSolidPolygon=function(l,u,h){h=o(h);let d=c(l,u);ds(d,h,0,h,v(),0,!1)},i.DrawCircle=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),Oi(l,u*2,vn,.1,h,!1)},i.DrawSolidCircle=function(l,u,h,d){d=o(d),l=b.vec2FromPointer(l),h=b.vec2FromPointer(h).scale(u),Oi(l,u*2,d,.1,d,!1),Dn(v(),h,.1,d,l,0,!1)},i.DrawTransform=function(l){l=b.instance.wrapPointer(l,b.instance.b2Transform);let u=b.vec2From(l.get_p()),h=-l.get_q().GetAngle(),d=v(1,0),f=Y(.75,0,0,.8),p=v(0,1),y=Y(0,.75,0,.8);Dn(v(),d,.1,f,u,h,!1),Dn(v(),p,.1,y,u,h,!1)},i.AppendFlags(b.instance.b2Draw.e_shapeBit),i.AppendFlags(b.instance.b2Draw.e_jointBit),b.world.SetDebugDraw(i)}}function jh(t,e,n,s=32,i=2,r=0){Bl(t,e,n,Q,s,he,i,r,!1,!0)}function Bl(t,e,n,s,i=1,r,a=.05,o=0,c=W,l,u){let h=n.offset(n.size),d=e.add(v(a-i*2)),f=v(i),p=e.scale(.5).subtract(f.scale(.5)),y=l?-1:1,x=l?-o:o;Be(t,d,h,s,o,!1,r,c,l,u);for(let w=4;w--;){let A=w%2,S=p.multiply(v(A?w===1?1:-1:0,A?0:w?-1:1)),_=v(A?i:d.x,A?d.y:i),k=h.offset(n.size.multiply(v(w===1?1:w===3?-1:0,w===0?-y:w===2?y:0)));Be(t.add(S.rotate(x)),_,k,s,o,!1,r,c,l,u)}for(let w=4;w--;){let A=w>1,S=w&&w<3,_=p.multiply(v(A?-1:1,S?-1:1)),k=h.offset(n.size.multiply(v(A?-1:1,S?y:-y)));Be(t.add(_.rotate(x)),f,k,s,o,!1,r,c,l,u)}}function Jh(t,e,n,s=32,i=2,r=0){jl(t,e,n,Q,s,he,i,r,!1,!0)}function jl(t,e,n,s,i=1,r,a=.05,o=0,c=W,l,u){let h=n.frame(0),d=n.frame(1),f=n.frame(2),p=e.add(v(a-i*2)),y=v(i),x=e.scale(.5).subtract(y.scale(.5)),w=l?-1:1,A=l?-o:o;Be(t,p,f,s,o,!1,r,c,l,u);for(let S=4;S--;){let _=o+S*te/2,k=S%2,C=x.multiply(v(k?S===1?1:-1:0,k?0:S?-w:w)),L=v(k?p.y:p.x,i);Be(t.add(C.rotate(A)),L,d,s,_,!1,r,c,l,u)}for(let S=4;S--;){let _=o+S*te/2,k=!S||S>2,C=S>1,L=x.multiply(v(k?-1:1,C?-w:w));Be(t.add(L.rotate(A)),y,h,s,_,!1,r,c,l,u)}}function Nh(t,e=1,n=0,s=Q,i=0,r=!1,a=0,o=he,c=W,l=!1,u){let h=Jl(v(),e,n,0,r);ds(h,s,a,o,t,i,c,l,u)}function Jl(t,e=1,n=0,s=0,i=!1,r=ti){m(D(t),"pos must be a vec2"),m(O(e)&&O(n),"size and percent must be numbers");let a=dt(n*4,4);a>=2&&(s+=te),a=a<=2?a-1:3-a,i&&(a=-a,s+=te);let o=[],c=re(3,r>>1),l=e/2;for(let u=0;u<=c;u++){let h=u/c*te;o.push(v(l*ye(h),l*fe(h)).rotate(s).add(t))}for(let u=c;u>=0;u--){let h=u/c*te;o.push(v(l*ye(h),-l*a*fe(h)).rotate(s).add(t))}return o}function Nc(t){return t&&typeof t.lerp=="function"}function zh(t,e,n,s,i=1,r={}){m(t!=null&&typeof t=="object","tweenProperty target must be an object"),m(K(e)&&e.length>0,"tweenProperty propertyPath must be a non-empty string");let a=e.split("."),o=a.pop(),c=l=>{let u=t;for(let h of a)u=u[h];u[o]=l};return new to(c,n,s,i,r)}function Nl(t){t.loopRemaining!==1/0&&t.loopRemaining<=1||(t.loopRemaining!==1/0&&(t.loopRemaining-=1),t.life=t.duration,t.thenCallback=()=>Nl(t),ot.push(t),t.callback(t.interp(t.duration)))}function zl(t){if(t.loopRemaining!==1/0&&t.loopRemaining<=1)return;t.loopRemaining!==1/0&&(t.loopRemaining-=1);let e=t.start;t.start=t.end,t.end=e,t.life=t.duration,t.thenCallback=()=>zl(t),ot.push(t),t.callback(t.interp(t.duration))}function Ul(t,e){t===void 0?(t=rt-jc,e=Sn-Jc,jc=rt,Jc=Sn):e===void 0&&(e=t);for(let n=ot.length;n--;){let s=ot[n];if(s.paused)continue;let i=s.useRealTime?e:t;if(!(i<=0))if(s.life-=i,s.life>0)s.callback(s.interp(s.life));else{s.callback(s.interp(0)),ot.splice(n,1);let r=s.thenCallback;s.thenCallback=void 0,r&&r()}}}function Uh(){for(let t of ot)t.thenCallback=void 0;ot.length=0}var Ti,Ai,nd,Ur,_e,Vr,zc,rt,Sn,Mt,Ko,kt,ki,Uc,In,er,Ue,qc,io,Hc,zt,mn,bt,xt,Fn,Gn,us,tr,Ut,gt,te,de,Pe,Fs,Ci,le,re,ut,Kc,Qc,fe,ye,Zc,qr,ir,me,Me,Q,vn,he,wt,Sd,Yr,vd,cl,ll,wd,ul,dl,Td,Lt,Ie,ae,ee,Kr,oo,yn,ns,Ms,ss,is,Qr,Jn,gn,ei,Zr,$,W,ti,ro,ao,co,lo,ea,ta,na,sa,ia,Wt,Ze,Ri,uo,oa,Ls,On,wn,ra,vt,gs,Vn,bs,xs,ni,An,tt,aa,Os,Pi,si,nt,Bn,ca,la,Kt,q,ge,Oe,$t,hn,Et,qt,N,Tn,Ot,Dt,It,Qt,Of,Sl,Di,Jt,Ke,fa,Ct,ha,Ii,as,pn,pa,os,Ae,ft,ie,_t,Mn,Qo,fs,ht,Nn,Fi,ci,Ht,dn,Tl,xa,Al,zs,Ln,hs,Ic,Gi,ve,Xt,Ss,Vs,Bi,xn,jn,Ji,Ws,qs,lr,vh,Ni,ue,g,Ta,zi,Ui,zn,$n,ms,at,ur,cs,ze,Hs,De,Is,dr,fr,Aa,Vi,hr,Wi,ka,El,wh,po,Rl,ls,Pn,qi,rs,Hi,La,Xs,wi,$i,vi,Yi,Ks,yr,gr,Je,br,Z,xr,Sr,vr,E,Da,wr,pt,Xi,Tr,Ar,Qs,kr,Cr,_r,Er,b,Ia,Zs,Ki,Rr,Pr,Qi,st,Mr,Zi,Lr,Or,Dr,Ir,Fr,Gr,Br,jr,Jr,Nr,eo,ot,jc,Jc,to,no,Vh,Zo,so,zr,Wl=Xl(()=>{"use strict";Ti="LittleJS",Ai="1.18.19",nd=60,Ur=.016666666666666666,_e=[],Vr=[],zc=0,rt=0,Sn=0,Mt=!1;Ko=0,kt=0,ki=0,Uc=!0,In=[],er=class{constructor(e,n,s,i){this.update=e,this.render=n,this.glContextLost=s,this.glContextRestored=i}};Ue=!0,qc=.5,io=!0,Hc="Escape",zt=!1,mn=[],bt=!1,xt=!1,Fn=!1,Gn=!1,us=!1;te=Math.PI,de=Math.abs,Pe=Math.floor,Fs=Math.ceil,Ci=Math.round,le=Math.min,re=Math.max,ut=t=>Math.sign(t),Kc=(...t)=>Math.hypot(...t),Qc=t=>Math.log2(t),fe=Math.sin,ye=Math.cos,Zc=Math.tan,qr=Math.atan2;ir=class{constructor(e=123456789){m(e!==0,"RandomGenerator seed must be non-zero (xorshift is fixed at 0)"),this.seed=e}float(e=1,n=0){return this.seed^=this.seed<<13,this.seed^=this.seed>>>17,this.seed^=this.seed<<5,n+(e-n)*((this.seed>>>0)/2**32)}int(e,n=0){return Pe(this.float(e,n))}bool(e=.5){return this.float().5?1:-1}floatSign(e=1,n=0){let s=le(e,n),r=re(e,n)-s,a=this.float(r*2);return ae?this.scale(e/n):this.copy()}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.x}reflect(e,n=1){return this.subtract(e.scale((1+n)*this.dot(e)))}angle(){return qr(this.x,this.y)}setAngle(e=0,n=1){return it(e),it(n),this.x=n*fe(e),this.y=n*ye(e),this}rotate(e){it(e);let n=ye(-e),s=fe(-e);return new t(this.x*n-this.y*s,this.x*s+this.y*n)}setDirection(e,n=1){return it(e),it(n),e=dt(e,4),m(e===0||e===1||e===2||e===3,"Vector2.setDirection() direction must be an integer between 0 and 3."),this.x=e%2?e-1?-n:n:0,this.y=e%2?0:e?-n:n,this}direction(){return de(this.x)>de(this.y)?this.x<0?3:1:this.y<0?2:0}abs(){return new t(de(this.x),de(this.y))}floor(){return new t(Pe(this.x),Pe(this.y))}snap(e){return it(e),new t(Pe(this.x*e)/e,Pe(this.y*e)/e)}mod(e=1){return new t(dt(this.x,e),dt(this.y,e))}area(){return de(this.x*this.y)}lerp(e,n){Oc(e),it(n);let s=H(n);return new t(e.x*s+this.x*(1-s),e.y*s+this.y*(1-s))}arrayCheck(e){return this.x>=0&&this.y>=0&&this.x(u=dt(u,1))*6<1?c+(l-c)*6*u:u*2<1?l:u*3<2?c+(l-c)*(4-u*6):c;return this.r=o(a,r,e+1/3),this.g=o(a,r,e),this.b=o(a,r,e-1/3),this.a=i,Rs(this),this}HSLA(){let e=H(this.r),n=H(this.g),s=H(this.b),i=H(this.a),r=re(e,n,s),a=le(e,n,s),o=(r+a)/2,c=0,l=0;if(r!==a){let u=r-a;l=o>.5?u/(2-r-a):u/(r+a),e===r?c=(n-s)/u+(n((s=H(s)*255|0)<16?"0":"")+s.toString(16);return"#"+n(this.r)+n(this.g)+n(this.b)+(e?n(this.a):"")}setHex(e){if(m(K(e),"Color hex code must be a string"),m(e[0]==="#","Color hex code must start with #"),m([4,5,7,9].includes(e.length),"Invalid hex"),e.length<6){let n=s=>H(parseInt(e[s],16)/15);this.r=n(1),this.g=n(2),this.b=n(3),this.a=e.length===5?n(4):1}else{let n=s=>H(parseInt(e.slice(s,s+2),16)/255);this.r=n(1),this.g=n(3),this.b=n(5),this.a=e.length===9?n(7):1}return Rs(this),this}rgbaInt(){let e=H(this.r)*255|0,n=H(this.g)*255<<8,s=H(this.b)*255<<16,i=H(this.a)*255<<24;return e+n+s+i}isValid(){return O(this.r)&&O(this.g)&&O(this.b)&&O(this.a)}},Q=ct(Y()),vn=ct(Y(1,1,1,0)),he=ct(Y(0,0,0)),wt=ct(Y(0,0,0,0)),Sd=ct(Y(.5,.5,.5)),Yr=ct(Y(1,0,0)),vd=ct(Y(1,.5,0)),cl=ct(Y(1,1,0)),ll=ct(Y(0,1,0)),wd=ct(Y(0,1,1)),ul=ct(Y(0,0,1)),dl=ct(Y(.5,0,1)),Td=ct(Y(1,0,1)),Lt=class{constructor(e,n=!1){m(e===void 0||O(e),"Constructed Timer is invalid.",e),this.useRealTime=n;let s=this.getGlobalTime();this.time=e===void 0?void 0:s+e,this.setTime=e}set(e=0){m(O(e),"Timer is invalid.",e);let n=this.getGlobalTime();this.time=n+e,this.setTime=e}setUseRealTime(e=!0){m(!this.isSet(),"Cannot change global time setting while timer is set."),this.useRealTime=e}unset(){this.time=void 0}isSet(){return this.time!==void 0}active(){return this.getGlobalTime()=this.time}get(){return this.isSet()?this.getGlobalTime()-this.time:0}getPercent(){return this.isSet()?this.setTime?1-Ve(this.time-this.getGlobalTime(),0,this.setTime):1:0}getSetTime(){return this.isSet()?this.setTime:0}getGlobalTime(){return this.useRealTime?Sn:rt}toString(){return this.isSet()?de(this.get())+" seconds "+(this.get()<0?"before":"after"):"unset"}valueOf(){return this.get()}};Ie=v(),ae=0,ee=32,Kr=1,oo=!0,yn=wt,ns=v(1920,1080),Ms=0,ss=0,is=v(),Qr=!1,Jn=!0,gn=1,ei="arial",Zr=!1,$=!1,W=!0,ti=32,ro=v(16),ao=0,co=0,lo=!0,ea=1,ta=1,na=1,sa=0,ia=.8,Wt=1,Ze=v(),Ri=1,uo=!0,oa=!0,Ls=!0,On=!0,wn=!1,ra=!1,vt=0,gs=4,Vn=!0,bs=0,xs=!1,ni=!0,An=!1,tt=100,aa=.3,Os=3,Pi=0,si=!0,nt=!0,Bn=.3,ca=40,la=.7;Kt=class t{constructor(e=v(),n=v(1),s,i=0,r=Q,a=0){m(D(e),"object pos must be a vec2"),m(D(n),"object size must be a vec2"),m(!s||s instanceof It,"object tileInfo should be a TileInfo or undefined"),m(typeof i=="number"&&isFinite(i),"object angle should be a number"),m(X(r),"object color should be a valid rgba color"),m(typeof a=="number","object renderOrder should be a number"),this.pos=e.copy(),this.size=n.copy(),this.drawSize=void 0,this.tileInfo=s,this.angle=i,this.color=r.copy(),this.additiveColor=void 0,this.mirror=!1,this.destroyed=!1,this.mass=ea,this.damping=ta,this.angleDamping=na,this.restitution=sa,this.friction=ia,this.gravityScale=1,this.renderOrder=a,this.velocity=v(),this.angleVelocity=0,this.spawnTime=rt,this.children=[],this.clampSpeed=!0,this.groundObject=void 0,this.parent=void 0,this.localPos=v(),this.localAngle=0,this.collideTiles=!1,this.collideSolidObjects=!1,this.isSolid=!1,this.collideRaycast=!1,_e.push(this)}updateTransforms(){let e=this.parent;if(e){let n=e.getMirrorSign(),s=this.localPos,i=e.pos,r=s.x*n,a=s.y,o=e.angle;if(o){let c=ye(-o),l=fe(-o);this.pos.set(r*c-a*l+i.x,r*l+a*c+i.y)}else this.pos.set(r+i.x,a+i.y);this.angle=n*this.localAngle+o}for(let n of this.children)n.updateTransforms()}updatePhysics(){if(m(!this.parent),this.destroyed)return;this.clampSpeed&&(this.velocity.x=H(this.velocity.x,-Wt,Wt),this.velocity.y=H(this.velocity.y,-Wt,Wt));let e=this.pos.copy();if(this.velocity.x*=this.damping,this.velocity.y*=this.damping,this.mass&&(this.velocity.x+=Ze.x*this.gravityScale,this.velocity.y+=Ze.y*this.gravityScale),this.pos.x+=this.velocity.x,this.pos.y+=this.velocity.y,this.angle+=this.angleVelocity*=this.angleDamping,m(this.angleDamping>=0&&this.angleDamping<=1),m(this.damping>=0&&this.damping<=1),!lo||!this.mass)return;let n=this.velocity.y<0&&Ze.y<0||this.velocity.y>0&&Ze.y>0;if(this.groundObject){let s=re(this.friction,this.groundObject.friction),i=this.groundObject.velocity.x;this.velocity.x=i+(this.velocity.x-i)*s,this.groundObject=void 0}if(this.collideSolidObjects)for(let i of Vr){if(i.destroyed||i.parent||i===this||!this.isSolid&&!i.isSolid||!this.isOverlappingObject(i))continue;let r=this.collideWithObject(i),a=i.collideWithObject(this);if(!r||!a)continue;if(Ei(e,this.size,i.pos,i.size)){let d=e.subtract(i.pos),f=d.length(),y=f<.001?v(0,1):d.scale(.001/f);this.velocity=this.velocity.add(y),i.mass&&(i.velocity=i.velocity.subtract(y)),bt&&nr(this.pos,this.size,i.pos,i.size,"#f00");continue}let o=this.size.add(i.size),c=(e.y-i.pos.y)*2>o.y+Ze.y,l=de(e.y-i.pos.y)*20?-1:1)>0?Pe(e.y-this.size.y/2+1)+this.size.y/2+.001:Fs(e.y+this.size.y/2-1)-this.size.y/2-.001;if(de(u-this.pos.y)<.1&&!fn(v(this.pos.x,u),this.size,this)){this.pos.y=u,bt&&ke(this.pos,this.size,"#ff0");return}this.pos.x=e.x,this.velocity.x*=-a}if(r||!i){if(n){let c=this.size.y/2+1e-4;this.pos.y=Ze.y<0?Pe(e.y-this.size.y/2)+c:Fs(e.y+this.size.y/2)-c,this.groundObject=s}else this.pos.y=e.y,this.groundObject=void 0;this.velocity.y*=-a}bt&&ke(this.pos,this.size,"#f00")}}}update(){}render(){Be(this.pos,this.drawSize||this.size,this.tileInfo,this.color,this.angle,this.mirror,this.additiveColor)}renderLight(){}destroy(e=!1){var n;if(!this.destroyed){this.destroyed=!0,(n=this.parent)==null||n.removeChild(this);for(let s of this.children)s.parent=void 0,s.destroy(e)}}localToWorld(e){return this.pos.add(e.rotate(this.angle))}worldToLocal(e){return e.subtract(this.pos).rotate(-this.angle)}localToWorldVector(e){return e.rotate(this.angle)}worldToLocalVector(e){return e.rotate(-this.angle)}collideWithTile(e,n){return e>0}collideWithObject(e){return!0}getUp(e=1){return v().setAngle(this.angle,e)}getRight(e=1){return v().setAngle(this.angle+te/2,e)}getAliveTime(){return rt-this.spawnTime}getSpeed(){return this.velocity.length()}applyAcceleration(e){this.mass&&(this.velocity=this.velocity.add(e))}applyAngularAcceleration(e){this.mass&&(this.angleVelocity+=e)}applyForce(e){this.mass&&this.applyAcceleration(e.scale(1/this.mass))}getMirrorSign(){return this.mirror?-1:1}addChild(e,n=v(),s=0){return m(!this.destroyed,"cannot add child to destroyed object"),this.destroyed||(m(!e.parent&&!this.children.includes(e)),m(e instanceof t,"child must be an EngineObject"),m(e!==this,"cannot add self as child"),this.children.push(e),e.parent=this,e.localPos=n.copy(),e.localAngle=s,e.updateTransforms()),e}removeChild(e){m(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}isOverlappingObject(e){return this.isOverlapping(e.pos,e.size)}isOverlapping(e,n=v()){return Ei(this.pos,this.size,e,n)}setCollision(e=!0,n=!0,s=!0,i=!0){m(e||!n,"solid objects must be set to collide"),this.collideSolidObjects=e,this.isSolid=n,this.collideTiles=s,this.collideRaycast=i}toString(){let e="type = "+this.constructor.name;return(this.pos.x||this.pos.y)&&(e+=`
+pos = `+this.pos),(this.velocity.x||this.velocity.y)&&(e+=`
+velocity = `+this.velocity),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.angle&&(e+=`
+angle = `+this.angle.toFixed(3)),this.color&&(e+=`
+color = `+this.color),e}renderDebugInfo(){if(!Ue)return;let e=this.collideTiles||this.collideSolidObjects||this.isSolid;if(!e&&!this.parent)return;let n=v(re(this.size.x,.2),re(this.size.y,.2)),s=Y(this.collideTiles?1:0,this.collideSolidObjects?1:0,this.isSolid?1:0,.5);ke(this.pos,n,s,0,this.angle,e),this.parent&&ke(this.pos,n.scale(.8),Y(1,1,1,.5),0,this.angle),this.parent&&Rt(this.pos,this.parent.pos,Y(1,1,1,.5),.5)}},N=v(),Tn=[];It=class t{constructor(e=v(),n=ro,s=Tn[0],i=ao,r=co){this.pos=e.copy(),this.size=n.copy(),this.padding=i,this.textureInfo=s,this.bleed=r}offset(e){return new t(this.pos.add(e),this.size,this.textureInfo,this.padding,this.bleed)}frame(e){m(typeof e=="number");let n=this.size.x+this.padding*2,s=e*n;return m(s+this.size.x<=this.textureInfo.size.x,"frame extends beyond texture width!"),this.offset(new me(s))}setFullImage(e=this.textureInfo){return this.textureInfo=e,this.pos=new me,this.size=e.size.copy(),this.bleed=this.padding=0,this}tile(e){return ii(e,this.size,this.textureInfo,this.padding,this.bleed)}},Qt=class{constructor(e,n=!0,s=!1){this.image=e,this.size=e?v(e.width,e.height):v(),this.sizeInverse=e?v(1/e.width,1/e.height):v(),this.glTexture=void 0,this.wrap=s,n&&this.createWebGLTexture()}createWebGLTexture(){Ah(this)}destroyWebGLTexture(){kh(this)}hasWebGL(){return!!this.glTexture}setWrap(e=!0){this.wrap=e,Ll(this.glTexture,e)}};Of=0;Di=class{constructor(e){m(!!e,"tileInfo is required for ImageFont"),this.tileInfo=e.frame(0)}drawText(e,n,s=1,i,r,a,o){m(D(s)||typeof s=="number","size must be a vec2 or number"),typeof s=="number"?(m(s>0),s*=ee,s=new me(s,s)):s=s.scale(ee),this.drawTextScreen(e,qn(n),s,i,r,a,o)}drawTextScreen(e,n,s,i=!0,r=Q,a=W,o){m(K(e),"text must be a string"),m(D(n),"pos must be a vec2"),m(D(s)||typeof s=="number","size must be a vec2 or number"),m(X(r),"color must be a color"),s=typeof s=="number"?new me(s,s):s;let c=new me,l=this.tileInfo,u=l.padding,h=l.size.x+u*2,d=l.size.y+u*2,f=l.textureInfo.size.x/h|0;(e+"").split(`
+`).forEach((p,y)=>{let x=i?(p.length-1)*s.x/2:0;for(let w=p.length;w--;){let A=p.charCodeAt(w),S=A<32||A>127?95:A-32,_=S%f,k=S/f|0;l.pos.x=_*h+u,l.pos.y=k*d+u,c.x=n.x+w*s.x-x|0,c.y=n.y+y*s.y|0,Be(c,s,l,r,0,!1,void 0,a,!0,o)}})}};Jt=v(),Ke=v(),fa=v(),Ct=v(),ha=0,Ii=!0,as=!1,pn="mouse",pa=6,os=!0,Ae=0,ft=!$&&window.ontouchstart!==void 0;ie=[[]],_t=[],Mn=[],Qo=[],fs=new Lt,ht=[],Nn=[],Fi=[],ci=[],Ht=new Map,zs=[],hs=!0;Gi="http://www.w3.org/2000/svg";ve=new AudioContext,Ss=44100;Vs=class{constructor(e,n,s=ca,i=la,r){var a;if(!(!nt||$)){if(m(!e||St(e)||K(e),"asset must be a file name or zzfx array"),m(n===void 0||O(n),"randomness must be a number"),m(n===void 0||n>=0&&n<=1,"randomness must be between 0 and 1"),m(O(s),"range must be a number"),m(O(i),"taper must be a number"),this.range=s,this.taper=i,this.randomness=n!=null?n:0,this.sampleRate=Ss,this.loadedPercent=0,this.onloadCallback=r,St(e)){let o=e.slice(),c=n!=null?n:.05,l=1;this.randomness=(a=o[l])!=null?a:c,o[l]=0,this.sampleChannels=[ho(...o)],this.loadedPercent=1,r==null||r(this)}else if(typeof e=="string"){let o=e;this.loadSound(o)}}}play(e,n=1,s=1,i=1,r=!1,a=!1){if(m(!e||D(e),"pos must be a vec2"),m(O(n),"volume must be a number"),m(O(s),"pitch must be a number"),m(O(i),"randomnessScale must be a number"),!nt||$||!this.sampleChannels)return;let o;if(e){let u=this.range;if(u){let h=Ie.distanceSquared(e);if(h>u*u)return;n*=Ve(h**.5,u,u*this.taper)}o=qn(e).x*2/q.width-1}let c=s+s*this.randomness*i*Se(-1,1),l=new Bi(this,n,c,o,r,a);return Ue&&us&&e&&(Qe(e,.5,"#0ff",.5,!0),this.range&&(Qe(e,2*this.range,"#0ff",.5),Qe(e,2*this.range*this.taper,"#0ff",.5)),ts("vol "+n.toFixed(2)+" pitch "+c.toFixed(2),e,.5,"#0ff",.5)),l}playMusic(e=1,n=!0,s=!1){return this.play(void 0,e,1,0,n,s)}playNote(e=0,n,s){m(O(e),"semitoneOffset must be a number");let i=Cl(e,1);return this.play(n,s,i,0)}getDuration(){var e,n;return((n=(e=this.sampleChannels)==null?void 0:e[0])==null?void 0:n.length)/this.sampleRate||0}isLoaded(){return this.loadedPercent===1}async loadSound(e){var c;let n=await fetch(e);if(!n.ok)throw new Error(`Failed to load sound from ${e}: ${n.status} ${n.statusText}`);let s=await n.arrayBuffer(),i=await ve.decodeAudioData(s),r=i.numberOfChannels,a=1e5,o=[];for(let l=0;lsetTimeout(x,0));let f=le(d+a,h);for(;d=0,"Sound volume must be positive or zero"),m(s>=0,"Sound rate must be positive or zero"),m(O(i),"Sound pan must be a number"),this.sound=e,this.volume=n,this.rate=s,this.pan=i,this.loop=r,this.pausedTime=0,this.startTime=void 0,this.gainNode=void 0,this.source=void 0,this.onendedCallback=o=>{o===this.source&&(this.source=void 0)},a||this.start()}start(e=0){m(e>=0,"Sound start offset must be positive or zero"),this.isPlaying()&&this.stop(),this.gainNode=ve.createGain(),this.source=wa(this.sound.sampleChannels,this.volume,this.rate,this.pan,this.loop,this.sound.sampleRate,this.gainNode,e,this.onendedCallback),this.source?(this.startTime=ve.currentTime-e,this.pausedTime=void 0):(this.startTime=void 0,this.pausedTime=0)}setVolume(e){m(e>=0,"Sound volume must be positive or zero"),this.volume=e,this.gainNode&&(this.gainNode.gain.value=e)}stop(e=0){if(m(e>=0,"Sound fade time must be positive or zero"),this.isPlaying())if(e){let n=ve.currentTime,s=n+e;this.gainNode.gain.cancelScheduledValues(n),this.gainNode.gain.setValueAtTime(this.volume,n),this.gainNode.gain.linearRampToValueAtTime(0,s),this.source.stop(s)}else this.source.stop();this.pausedTime=0,this.source=void 0,this.startTime=void 0}pause(){this.isPaused()||(this.pausedTime=this.getCurrentTime(),this.source.stop(),this.source=void 0,this.startTime=void 0)}resume(){this.isPaused()&&this.start(this.pausedTime)}isPlaying(){return!!this.source}isPaused(){return!this.isPlaying()}getCurrentTime(){if(!this.isPlaying())return this.pausedTime;let e=this.getDuration();return e?dt(ve.currentTime-this.startTime,e):0}getDuration(){return this.rate?this.sound.getDuration()/this.rate:0}getSource(){return this.source}};xn=[];jn=class{constructor(e,n=0,s=!1,i=new Me){this.tile=e,this.direction=n,this.mirror=s,this.color=i.copy()}clear(){this.tile=this.direction=0,this.mirror=!1,this.color=new Me}},Ji=class extends Kt{constructor(e,n,s=0,i=0,r=v(512),a=!0){var o;m(D(r),"canvasSize must be a Vector2"),super(e,n,void 0,s,Q,i),this.canvas=$?void 0:new OffscreenCanvas(r.x,r.y),this.context=(o=this.canvas)==null?void 0:o.getContext("2d"),this.textureInfo=new Qt(this.canvas,a),this.mass=0}destroy(){this.destroyed||(this.textureInfo.destroyWebGLTexture(),super.destroy())}render(){this.draw(this.pos,this.size,this.color,this.angle,this.mirror,this.additiveColor)}draw(e,n,s=Q,i=0,r=!1,a,o=!1,c){let l=new It().setFullImage(this.textureInfo),u=this.hasWebGL();Be(e,n,l,s,i,r,a,u,o,c)}updateWebGL(){this.textureInfo.createWebGLTexture()}hasWebGL(){return W&&this.textureInfo.hasWebGL()}},Ws=class extends Ji{constructor(e,n,s=ii(),i=0,r=!0){let a=s?n.multiply(s.size):n;if(super(e,n,0,i,a,r),this.tileInfo=void 0,this.data=[],this.isUsingWebGL=!1,$){this.render=()=>{},this.redraw=()=>{},this.redrawStart=()=>{},this.redrawEnd=()=>{},this.drawTileData=()=>{},this.redrawTileData=()=>{},this.drawLayerTile=()=>{},this.drawLayerRect=()=>{},this.drawTile=()=>{},this.drawRect=()=>{},this.clearLayerRect=()=>{};return}s&&(this.tileInfo=s.frame(0),this.tileInfo.bleed=0);for(let o=this.size.area();o--;)this.data.push(new jn)}setData(e,n,s=!1){if(e=e.floor(),m(D(e),"layerPos must be a Vector2"),m(n instanceof jn,"data must be a TileLayerData"),!e.arrayCheck(this.size)||(this.data[(e.y|0)*this.size.x+(e.x|0)]=n,!s))return;Oe===this.context?this.drawTileData(e):this.redrawTileData(e)}clearData(e,n=!1){this.setData(e,new jn,n)}getData(e){return m(D(e),"layerPos must be a Vector2"),e.arrayCheck(this.size)?this.data[(e.y|0)*this.size.x+(e.x|0)]:void 0}update(){!W&&this.isUsingWebGL&&(this.isUsingWebGL=!1,this.redraw())}render(){m(Oe!==this.context,"must call redrawEnd() after drawing tiles!");let e=this.drawSize||this.size,n=this.pos.add(e.scale(.5));this.draw(n,this.size,this.color,this.angle,this.mirror,this.additiveColor)}onRedraw(){}redraw(){this.redrawStart(!0);for(let e=this.size.x;e--;)for(let n=this.size.y;n--;)this.drawTileData(v(e,n),!1);this.isUsingWebGL&&Fe(),this.onRedraw(),this.redrawEnd()}redrawStart(e=!1){var s,i;if(!this.context)return;m(Oe!==this.context),this.savedRenderSettings=[Oe,N,Ie,ee,yn],Oe=this.context;let n=(i=(s=this.tileInfo)==null?void 0:s.size)!=null?i:v(1);N=this.size.multiply(n),yn=wt,Ie=this.size.multiply(n).scale(.5),ee=1,this.isUsingWebGL=this.hasWebGL(),this.isUsingWebGL?Ps(this.textureInfo.glTexture,e):(this.context.imageSmoothingEnabled=!Jn,e&&(this.canvas.width=N.x,this.canvas.height=N.y))}redrawEnd(){this.context&&(m(Oe===this.context),this.isUsingWebGL&&Ps(),[Oe,N,Ie,ee,yn]=this.savedRenderSettings)}drawTileData(e,n=!0){var o,c;if(!this.context)return;m(Oe===this.context,"must call redrawStart() before drawing tiles");let s=(c=(o=this.tileInfo)==null?void 0:o.size)!=null?c:v(1),i=e.multiply(s);n&&this.clearLayerRect(i,s);let r=this.getData(e);if(!r||!r.tile)return;let a=this.tileInfo&&this.tileInfo.tile(r.tile);this.drawLayerTile(i,s,a,r.color,r.direction*te/2,r.mirror)}redrawTileData(e,n=!0){this.context&&(m(Oe!==this.context,"redrawStart() should not be active when calling redrawTileData(), instead use drawTileData()"),this.redrawStart(),this.drawTileData(e,n),this.redrawEnd())}drawLayerTile(e,n=v(1),s,i=Q,r=0,a,o){let c=e.add(n.scale(.5));Be(c,n,s,i,r,a,o,this.isUsingWebGL)}drawLayerRect(e,n,s,i=0){this.drawLayerTile(e,n,void 0,s,i)}drawTile(e,n=v(1),s,i=new Me,r=0,a=!1){e=e.subtract(this.pos).multiply(this.tileInfo.size),n=n.multiply(this.tileInfo.size),e.y=this.canvas.height-e.y;let o=N;N=v(this.canvas.width,this.canvas.height);let c=this.hasWebGL();c&&Ps(this.textureInfo.glTexture);let l=c?void 0:this.context;Be(e,n,s,i,r,a,void 0,c,!0,l),c&&Ps(),N=o}drawRect(e,n,s,i){this.drawTile(e,n,void 0,s,i)}clearLayerRect(e,n){m(Oe===this.context,"must call redrawStart() before clearing tiles");let s=e.x,i=this.canvas.height-e.y-n.y;this.hasWebGL()?Fl(s,i,n.x,n.y):this.context.clearRect(s,i,n.x,n.y)}},qs=class extends Ws{constructor(e,n,s=ii(),i=0,r=!0){super(e,n.floor(),s,i,r),this.collisionData=[],this.initCollision(this.size),xn.push(this),this.isSolid=!0}destroy(){if(this.destroyed)return;let e=xn.indexOf(this);m(e>=0,"tile collision layer not found in array"),e>=0&&xn.splice(e,1),super.destroy()}initCollision(e){m(D(e),"size must be a Vector2"),this.size=e.floor(),this.collisionData=[],this.collisionData.length=e.area(),this.collisionData.fill(0)}setCollisionData(e,n=1){m(D(e),"layerPos must be a Vector2");let s=(e.y|0)*this.size.x+(e.x|0);e.arrayCheck(this.size)&&(this.collisionData[s]=n)}clearCollisionData(e){this.setCollisionData(e,0)}getCollisionData(e){m(D(e),"layerPos must be a Vector2");let n=(e.y|0)*this.size.x+(e.x|0);return e.arrayCheck(this.size)?this.collisionData[n]:0}collisionTest(e,n=new me,s){m(D(e)&&D(n),"pos and size must be Vector2s"),m(!s||typeof s=="function"||s instanceof Kt,"callbackObject must be a function or EngineObject");let i=s?typeof s=="function"?(d,f)=>s(d,f):(d,f)=>s.collideWithTile(d,f):()=>!0,r=e.x-this.pos.x,a=e.y-this.pos.y;if(r+n.x/2<0||r-n.x/2>this.size.x||a+n.y/2<0||a-n.y/2>this.size.y)return!1;let o=re(r-n.x/2|0,0),c=re(a-n.y/2|0,0),l=le(re(r+n.x/2,o+1),this.size.x),u=le(re(a+n.y/2,c+1),this.size.y),h=new me;for(let d=c;ds(l,u):(l,u)=>s.collideWithTile(l,u):l=>l>0,a=l=>{let u=this.getCollisionData(o.set(l.x-this.pos.x,l.y-this.pos.y));return u&&r(u,l)},o=new me,c=sl(e,n,a,i);if(xt&&c){let l=c.floor().add(v(.5));ke(l,v(1),"#f008"),Rt(e,n,"#00f",.02),Rt(e,c,"#f00",.02),Wr(c,"#0f0"),i&&Rt(c,c.add(i),"#ff0",.02)}return c}},lr=class extends Kt{constructor(e,n,s=0,i=0,r=100,a=te,o,c=Q,l=Q,u=vn,h=vn,d=.5,f=.1,p=1,y=.1,x=.05,w=1,A=1,S=0,_=te,k=.1,C=.2,L=!1,V=!1,ce=!0,ne=V?1e9:0,T=!1){super(e,v(),o,n,void 0,ne),this.emitCircle=typeof s=="number",this.emitSize=typeof s=="number"?v(s):s.copy(),this.emitTime=i,this.emitRate=r,this.emitConeAngle=a,this.colorStartA=c.copy(),this.colorStartB=l.copy(),this.colorEndA=u.copy(),this.colorEndB=h.copy(),this.randomColorLinear=ce,this.particleTime=d,this.sizeStart=f,this.sizeEnd=p,this.speed=y,this.angleSpeed=x,this.damping=w,this.angleDamping=A,this.gravityScale=S,this.particleConeAngle=_,this.fadeRate=k,this.randomness=C,this.collideTiles=L,this.additive=V,this.localSpace=T,this.trailScale=0,this.particleCreateCallback=void 0,this.particleDestroyCallback=void 0,this.particleCollideCallback=void 0,this.velocityInheritance=0,this.emitTimeBuffer=0,this.particles=[],this.previousAngle=this.angle,this.previousPos=this.pos.copy()}update(){if(m(this.angleDamping>=0&&this.angleDamping<=1),m(this.damping>=0&&this.damping<=1),this.velocityInheritance){let s=this.velocityInheritance;this.velocity.x=s*(this.pos.x-this.previousPos.x),this.velocity.y=s*(this.pos.y-this.previousPos.y),this.angleVelocity=s*(this.angle-this.previousAngle),this.previousAngle=this.angle,this.previousPos.x=this.pos.x,this.previousPos.y=this.pos.y}if(this.isActive()){if(this.emitRate&&Ri){let s=1/this.emitRate/Ri;for(this.emitTimeBuffer+=Ur;this.emitTimeBuffer>0;this.emitTimeBuffer-=s)this.emitParticle()}}else this.particles.length===0&&this.destroy(!0);let e=this.particles,n=0;for(let s=0;sA+A*Se(s,-s),r=i(this.particleTime),a=i(this.sizeStart),o=i(this.sizeEnd),c=i(this.speed),l=i(this.angleSpeed)*ol(),u=Se(this.emitConeAngle,-this.emitConeAngle),h=sr(this.colorStartA,this.colorStartB,this.randomColorLinear),d=sr(this.colorEndA,this.colorEndB,this.randomColorLinear),f=this.localSpace?u:this.angle+u,p=v(c*fe(f),c*ye(f)),y=l;!this.localSpace&&this.velocityInheritance>0&&(p.x+=this.velocity.x,p.y+=this.velocity.y,y+=this.angleVelocity);let x=new Ni(this,e,n,h,d,r,a,o,p,y);return this.particles.push(x),(w=this.particleCreateCallback)==null||w.call(this,x),x}updatePhysics(){}render(){for(let e of this.particles)e.render()}isActive(){return!this.emitTime||this.getAliveTime()0&&(this.destroyed=!1,this.emitTime=-1))}},vh=new me,Ni=class{constructor(e,n,s,i,r,a,o,c,l=v(),u=0){this.emitter=e,this.pos=n,this.angle=s,this.size=v(o),this.color=i.copy(),this.colorStart=i,this.colorEnd=r,this.lifeTime=a,this.sizeStart=o,this.sizeEnd=c,this.velocity=l,this.angleVelocity=u,this.spawnTime=rt,this.mirror=il(),this.groundObject=void 0,this.destroyed=!1,this.tileInfo=e.tileInfo}update(){let e=this.emitter,n=e.damping,s=e.angleDamping,i=e.restitution,r=e.friction,a=e.gravityScale,o=e.collideTiles,c=e.particleCollideCallback;if(this.lifeTime>0&&rt-this.spawnTime>this.lifeTime){this.destroy();return}let l=this.pos.copy();if(this.velocity.x*=n,this.velocity.y*=n,this.pos.x+=this.velocity.x+=Ze.x*a,this.pos.y+=this.velocity.y+=Ze.y*a,this.angle+=this.angleVelocity*=s,!lo||!o)return;let u=this.velocity.lengthSquared();if(u>Wt*Wt){let d=Wt/u**.5;this.velocity.x*=d,this.velocity.y*=d}this.groundObject=void 0;let h=c?d=>{let f=ji(d);return f&&c(this,f,d)}:d=>ji(d)>0;if(h(this.pos)){let d=fn(this.pos);if(!h(l)){let f=h(v(this.pos.x,l.y)),p=h(v(l.x,this.pos.y)),y=re(i,d.restitution),x=re(r,d.friction);f&&(this.pos.x=l.x,this.velocity.x*=-y,this.velocity.y*=x),(p||!f)&&((this.velocity.y<0&&Ze.y<0||this.velocity.y>0&&Ze.y>0)&&(this.groundObject=d),this.pos.y=l.y,this.velocity.y*=-y,this.velocity.x*=x),bt&&ke(this.pos,this.size,"#f00")}}}destroy(){let e=this.emitter.particleDestroyCallback,n=this.colorEnd;this.color.set(n.r,n.g,n.b,n.a),this.size.set(this.sizeEnd,this.sizeEnd),this.destroyed=!0,e==null||e(this)}render(){let e=this.emitter,n=e.localSpace,s=e.additive,i=e.trailScale,r=e.fadeRate/2,a=this.lifeTime>0?le((rt-this.spawnTime)/this.lifeTime,1):1,o=1-a,c=o*this.sizeStart+a*this.sizeEnd,l=v(c),u=a1-r?(1-a)/r:1;this.color.r=o*this.colorStart.r+a*this.colorEnd.r,this.color.g=o*this.colorStart.g+a*this.colorEnd.g,this.color.b=o*this.colorStart.b+a*this.colorEnd.b,this.color.a=(o*this.colorStart.a+a*this.colorEnd.a)*u;let h=vh.set(this.pos.x,this.pos.y),d=this.angle;if(n){let f=e.angle,p=ye(-f),y=fe(-f);h.set(e.pos.x+h.x*p-h.y*y,e.pos.y+h.x*y+h.y*p),d+=f}if(s&&js(),i){let f=n?this.velocity.rotate(e.angle):this.velocity,p=f.length();if(p){let y=p*i;l.y=re(l.x,y),d=qr(f.x,f.y),Be(h,l,this.tileInfo,this.color,d,this.mirror)}}else Be(h,l,this.tileInfo,this.color,d,this.mirror);s&&js(!1),Fn&&ke(h,l,"#f005",0,d)}},Ta=!0,hr=!0,Wi=5e5,ka=11,El=ka*4,wh=Wi/El|0,po=3,Rl=po*4,ls=Wi/Rl|0;Pn=!1,qi=5,rs=.5,Hi=v(640,80),La=!1,Xs={},wi=[];Yi=class{constructor(e,n,s="",i="\u{1F3C6}",r){m(e>=0&&!Xs[e]),this.id=e,this.name=n,this.description=s,this.icon=i,this.unlocked=!1,this.image=void 0,r&&((this.image=new Image).src=r),Xs[e]=this}unlock(){La||this.unlocked||(m($i,"save name must be set"),this.unlocked=!0,Oa(),wi.push(this))}render(e=0){let n=ge,s=le(Hi.x,q.width),i=Hi.y,r=q.width-s,a=-i*e,o=Vt(0,0,.9);n.save(),n.beginPath(),n.fillStyle=o.toString(),n.strokeStyle=he.toString(),n.lineWidth=3,n.rect(r,a,s,i),n.fill(),n.stroke(),n.clip();let c=v(.1,.05).scale(i),l=i-2*c.x;this.renderIcon(v(r+c.x+l/2,a+i/2),l);let u=i*.5,h=i*.3,d=v(r+l+2*c.x,a+c.y*2+u/2),f=s-l-3*c.x;bn(this.name,d,u,he,0,void 0,"left",void 0,void 0,f),d.y=a+i-c.y*2-h/2,bn(this.description,d,h,he,0,void 0,"left",void 0,void 0,f),n.restore()}renderIcon(e,n){this.image?ge.drawImage(this.image,e.x-n/2,e.y-n/2,n,n):bn(this.icon,e,n*.7,he)}};yr=class extends Yi{constructor(e,n,s,i,r){super(e,n,s,i,r)}unlock(){super.unlock(),Ks&&Ks.unlockMedal(this.id)}},gr=class{constructor(e,n,s){var c,l,u;m(!Ks,"there can only be one newgrounds object"),m(!n||s,"must provide cryptojs if there is a cipher"),Ks=this,this.app_id=e,this.cipher=n,this.cryptoJS=s,this.host=location?location.hostname:"";let i=new URL(location.href);if(this.session_id=i.searchParams.get("ngio_session_id"),!this.session_id)return;let r=this.call("Medal.getList");if(!r||!r.result||r.result.error){Pn&&Ce("Newgrounds session unavailable; skipping plugin init"),this.medals=[],this.scoreboards=[];return}this.medals=((c=r.result.data)==null?void 0:c.medals)||[],Pn&&Ce(this.medals);for(let h of this.medals){let d=Xs[h.id];d&&(d.image=new Image,d.image.src=h.icon,d.name=h.name,d.description=h.description,d.unlocked=h.unlocked,d.difficulty=h.difficulty,d.value=h.value,d.value&&(d.description=d.description+` (${d.value})`))}let a=this.call("ScoreBoard.getBoards");this.scoreboards=((u=(l=a==null?void 0:a.result)==null?void 0:l.data)==null?void 0:u.scoreboards)||[],Pn&&Ce(this.scoreboards);let o=60*1e3;setInterval(()=>this.call("Gateway.ping",0,!0),o)}unlockMedal(e){return this.call("Medal.unlock",{id:e},!0)}postScore(e,n){return this.call("ScoreBoard.postScore",{id:e,value:n},!0)}getScores(e,n,s=0,i=0,r=10){return this.call("ScoreBoard.getScores",{id:e,user:n,social:s,skip:i,limit:r})}logView(){return this.call("App.logView",{host:this.host},!0)}call(e,n,s=!1){let i={component:e,parameters:n};if(this.cipher){let l=this.cryptoJS,u=l.enc.Base64.parse(this.cipher),h=l.lib.WordArray.random(16),d=l.AES.encrypt(JSON.stringify(i),u,{iv:h});i.secure=l.enc.Base64.stringify(h.concat(d.ciphertext)),i.parameters=0}let r={app_id:this.app_id,session_id:this.session_id,call:i},a=new FormData;a.append("input",JSON.stringify(r));let o=new XMLHttpRequest;o.open("POST","https://newgrounds.io/gateway_v3.php",!Pn&&s);try{o.send(a)}catch(l){Pn&&Ce("newgrounds call failed",l);return}return Pn&&Ce(o.responseText),o.responseText&&JSON.parse(o.responseText)}},br=class{constructor(e,n=!1,s=!1){m(!Je,"Post process already initialized"),m(!(n&&s),"Post process cannot both include main canvas and use feedback texture"),Je=this,e||(e="void mainImage(out vec4 c,vec2 p){c=texture(iChannel0,p/iResolution.xy);}"),this.shader=void 0,this.texture=void 0,this.vao=void 0,i(),Un(void 0,o,r,a);function i(){if($)return;if(!W){console.warn("PostProcessPlugin: WebGL not enabled!");return}Je.texture=mo(),Je.shader=ys(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D iChannel0;uniform vec3 iResolution;uniform float iTime;out vec4 c;
+`+e+`
+void main(){mainImage(c,gl_FragCoord.xy);c.a=1.;}`),Je.vao=g.createVertexArray(),g.bindVertexArray(Je.vao),g.bindBuffer(g.ARRAY_BUFFER,cs);let c=8,l=g.getAttribLocation(Je.shader,"p");g.enableVertexAttribArray(l),g.vertexAttribPointer(l,2,g.FLOAT,!1,c,0)}function r(){Je.shader=void 0,Je.texture=void 0,Ce("PostProcessPlugin: WebGL context lost")}function a(){i(),Ce("PostProcessPlugin: WebGL context restored")}function o(){if($||!W)return;Fe(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.useProgram(Je.shader),g.bindVertexArray(Je.vao),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!0),g.disable(g.BLEND),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,Je.texture),n?($t.width=N.x,$t.height=N.y,Ea(hn),hn.drawImage(q,0,0),q.width|=0,g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,$t)):s||g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,ue);let c=l=>g.getUniformLocation(Je.shader,l);g.uniform1i(c("iChannel0"),0),g.uniform1f(c("iTime"),rt),g.uniform3f(c("iResolution"),q.width,q.height,1),g.drawArrays(g.TRIANGLE_STRIP,0,4),s&&g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,ue),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!1),$s(!0)}}},xr=class{constructor(e,n){m(!Z,"LightSystemPlugin already initialized"),m(!Je,"LightSystemPlugin must be created before PostProcessPlugin"),Z=this,this.enabled=!0,this.ambientColor=(n||he).copy(),this.textureSize=e?e.copy():void 0,this.texture=void 0,this.lightShader=void 0,this.compositeShader=void 0,this.lightVAO=void 0,this.compositeVAO=void 0,s(),Un(void 0,i,r,a);function s(){if($)return;if(!W){console.warn("LightSystemPlugin: WebGL not enabled!");return}Z.textureSize||(Z.textureSize=N.copy()),Z.texture=g.createTexture(),g.bindTexture(g.TEXTURE_2D,Z.texture),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,Z.textureSize.x,Z.textureSize.y,0,g.RGBA,g.UNSIGNED_BYTE,null),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,g.CLAMP_TO_EDGE),Z.lightShader=ys(`#version 300 es
+precision highp float;uniform mat4 m;uniform vec2 lightPos;uniform float radius;in vec2 g;out vec2 vWorldPos;void main(){vec2 worldP=lightPos+(g-.5)*2.*radius;gl_Position=m*vec4(worldP,1,1);vWorldPos=worldP;}`,`#version 300 es
+precision highp float;uniform vec2 lightPos;uniform float radius;uniform float fadeRange;uniform vec4 color;in vec2 vWorldPos;out vec4 c;void main(){float dist=distance(vWorldPos,lightPos);float t=clamp((radius-dist)/max(fadeRange,1e-6),0.,1.);c=vec4(color.rgb*t*color.a,1.);}`),Z.compositeShader=ys(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D s;uniform vec3 iResolution;out vec4 c;void main(){vec2 uv=gl_FragCoord.xy/iResolution.xy;c=vec4(texture(s,uv).rgb,1.);}`),Z.lightVAO=g.createVertexArray(),g.bindVertexArray(Z.lightVAO),g.bindBuffer(g.ARRAY_BUFFER,cs);let o=g.getAttribLocation(Z.lightShader,"g");g.enableVertexAttribArray(o),g.vertexAttribPointer(o,2,g.FLOAT,!1,8,0),Z.compositeVAO=g.createVertexArray(),g.bindVertexArray(Z.compositeVAO),g.bindBuffer(g.ARRAY_BUFFER,cs);let c=g.getAttribLocation(Z.compositeShader,"p");g.enableVertexAttribArray(c),g.vertexAttribPointer(c,2,g.FLOAT,!1,8,0)}function i(){if($||!W||!Z.enabled||!Z.texture)return;Fe();let o=$n,c=Z.ambientColor;g.bindFramebuffer(g.FRAMEBUFFER,Aa),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,Z.texture,0),g.viewport(0,0,Z.textureSize.x,Z.textureSize.y),g.clearColor(c.r,c.g,c.b,c.a),g.clear(g.COLOR_BUFFER_BIT),js(),g.enable(g.BLEND),g.blendFunc(g.ONE,g.ONE);for(let u of _e)u.destroyed||u.renderLight();Fe(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,N.x,N.y),g.useProgram(Z.compositeShader),g.bindVertexArray(Z.compositeVAO),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,Z.texture);let l=Z.compositeShader;g.uniform1i(g.getUniformLocation(l,"s"),0),g.uniform3f(g.getUniformLocation(l,"iResolution"),q.width,q.height,1),g.blendFunc(g.DST_COLOR,g.ZERO),g.drawArrays(g.TRIANGLE_STRIP,0,4),at&&g.bindTexture(g.TEXTURE_2D,at),js(o),$s(!0)}function r(){Z.texture=void 0,Z.lightShader=void 0,Z.compositeShader=void 0,Z.lightVAO=void 0,Z.compositeVAO=void 0,Ce("LightSystemPlugin: WebGL context lost")}function a(){s(),Ce("LightSystemPlugin: WebGL context restored")}}drawLight(e){if($||!W||!this.lightShader)return;Fe(),g.useProgram(this.lightShader),g.bindVertexArray(this.lightVAO);let n=v(2*ee).divide(N),s=Ie.rotate(-ae),i=v(-1).subtract(s.multiply(n)),r=ye(ae),a=fe(ae),o=[n.x*r,n.y*a,0,0,-n.x*a,n.y*r,0,0,1,1,1,0,i.x,i.y,0,1],c=this.lightShader;g.uniformMatrix4fv(g.getUniformLocation(c,"m"),!1,o),g.uniform2f(g.getUniformLocation(c,"lightPos"),e.pos.x,e.pos.y),g.uniform1f(g.getUniformLocation(c,"radius"),e.radius),g.uniform1f(g.getUniformLocation(c,"fadeRange"),e.fadeRange);let l=e.color;g.uniform4f(g.getUniformLocation(c,"color"),l.r,l.g,l.b,l.a),g.drawArrays(g.TRIANGLE_STRIP,0,4),$s(!0)}},Sr=class extends Kt{constructor(e,n,s,i){super(e,v(1),void 0,0,s),m(O(n)&&n>=0,"Light radius must be a non-negative number"),m(i===void 0||O(i)&&i>=0,"Light fadeRange must be a non-negative number when provided"),this.radius=n,this.fadeRange=i===void 0?n:i}render(){}renderLight(){Z&&Z.drawLight(this)}},vr=class extends Vs{constructor(e){super(void 0),!(!nt||$)&&(this.randomness=0,this.sampleChannels=Gl(...e),this.sampleRate=Ss)}playMusic(e=1,n=!0){return super.play(void 0,e,1,0,n)}};Da=0;wr=class{constructor(e=ge){m(!E,"UI system already initialized"),E=this,this.activateOnPress=!1,this.defaultColor=Q,this.defaultLineColor=he,this.defaultTextColor=he,this.defaultButtonColor=Vt(0,0,.7),this.defaultHoverColor=Vt(0,0,.9),this.defaultDisabledColor=Vt(0,0,.3),this.defaultGradientColor=void 0,this.defaultLineWidth=4,this.defaultCornerRadius=0,this.defaultTextFitScale=.8,this.defaultFont=ei,this.defaultSoundPress=void 0,this.defaultSoundRelease=void 0,this.defaultSoundClick=void 0,this.defaultShadowColor=wt,this.defaultShadowBlur=5,this.defaultShadowOffset=v(5),this.nativeHeight=0,this.navigationObject=void 0,this.navigationTimer=new Lt(void 0,!0),this.navigationDelay=.2,this.navigationDirection=1,this.navigationMode=!1,this.uiObjects=[],this.uiContext=e,this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.confirmDialog=void 0,this._keyInputObject=void 0,this._onKeyDown=r=>{var a;return(a=this._keyInputObject)==null?void 0:a.onKeyDown(r)},Un(s,i);function n(r){let a,o;r.parent?(a=r.parent.nativePos,o=r.parent.size):(a=E.screenToNative(N.scale(.5)),o=E.nativeHeight?v(N.x*E.nativeHeight/N.y,E.nativeHeight):N);let c=r.anchor;r.nativePos=a.add(o.multiply(c).scale(.5)).subtract(r.size.multiply(c).scale(.5)).add(r.localPos)}function s(){E.activeObject&&!E.activeObject.visible&&(E.activeObject=void 0),E.lastHoverObject=E.hoverObject,E.hoverObject=void 0,Js(0)&&(E.navigationMode=!1,E.navigationObject=void 0),E.keyInputObject&&(E.activeObject=E.keyInputObject,E.hoverObject=E.keyInputObject,E.navigationMode=!1,E.navigationObject=void 0);let r=E.getNavigableObjects();if(!r.length)E.navigationObject=void 0;else if(!E.keyInputObject){if(r.includes(E.navigationObject)||(E.navigationObject=void 0),ft||E.navigationMode&&!E.navigationObject&&(E.navigationObject=r.find(o=>o.navigationAutoSelect)),!E.navigationTimer.active()){let o=ut(E.getNavigationDirection());if(o){let c;if(E.navigationObject){let l=r.indexOf(E.navigationObject),u=dt(l+o,r.length);c=r[u]}else if(c=r.find(l=>l.navigationAutoSelect),!c){let l=o>0?0:r.length-1;c=r[l]}E.navigationObject!==c&&(E.navigationMode=!0,E.hoverObject=void 0,E.navigationObject=c,E.navigationTimer.set(E.navigationDelay),c.soundPress&&c.soundPress.play())}}E.navigationObject&&E.getNavigationWasPressed()&&E.navigationObject.navigatePressed()}for(let o=E.uiObjects.length;o--;){let c=E.uiObjects[o];c.parent||a(c)}E.uiObjects=E.uiObjects.filter(o=>!o.destroyed);function a(o){if(!(o.destroyed||!o.visible)){n(o);for(let c=o.children.length;c--;){let l=o.children[c];l&&a(l)}o.destroyed||o.update()}}}function i(){let r=E.uiContext;if(r.save(),E.nativeHeight){let o=N.y/E.nativeHeight;r.translate(-o*N.x/2,0),r.scale(o,o),r.translate(N.x/2/o,0)}function a(o){if(o.visible){n(o),o.render();for(let c of o.children)a(c)}}if(E.uiObjects.forEach(o=>o.parent||a(o)),Da>0){let o=function(c,l=!0){l&&(l=!!c.visible),n(c),c.renderDebug(l);for(let u of c.children)o(u,l)};E.uiObjects.forEach(c=>c.parent||o(c))}r.restore()}}drawRect(e,n,s=Q,i=0,r=he,a=0,o,c=he,l=0,u=v()){m(D(e),"pos must be a vec2"),m(D(n),"size must be a vec2"),m(X(s),"color must be a color"),m(O(i),"lineWidth must be a number"),m(X(r),"lineColor must be a color"),m(O(a),"cornerRadius must be a number");let h=E.uiContext;if(o){let d=h.createLinearGradient(e.x,e.y-n.y/2,e.x,e.y+n.y/2),f=s.toString();d.addColorStop(0,f),d.addColorStop(.5,o.toString()),d.addColorStop(1,f),h.fillStyle=d}else h.fillStyle=s.toString();(l||u.x||u.y)&&c.a>0&&(h.shadowColor=c.toString(),h.shadowBlur=l,h.shadowOffsetX=u.x,h.shadowOffsetY=u.y),h.beginPath(),a&&h.roundRect?h.roundRect(e.x-n.x/2,e.y-n.y/2,n.x,n.y,a):h.rect(e.x-n.x/2,e.y-n.y/2,n.x,n.y),h.fill(),h.shadowColor="#0000",i&&r.a>0&&(h.strokeStyle=r.toString(),h.lineWidth=i,h.stroke())}drawLine(e,n,s=E.defaultLineWidth,i=E.defaultLineColor){m(D(e),"posA must be a vec2"),m(D(n),"posB must be a vec2"),m(O(s),"lineWidth must be a number"),m(X(i),"lineColor must be a color");let r=E.uiContext;r.strokeStyle=i.toString(),r.lineWidth=s,r.beginPath(),r.lineTo(e.x,e.y),r.lineTo(n.x,n.y),r.stroke()}drawTile(e,n,s,i=E.defaultColor,r=0,a=!1,o=he,c=0,l=v()){let u=E.uiContext;(c||l.x||l.y)&&o.a>0&&(u.shadowColor=o.toString(),u.shadowBlur=c,u.shadowOffsetX=l.x,u.shadowOffsetY=l.y),Be(e,n,s,i,r,a,wt,!1,!0,u),u.shadowColor="#0000"}drawText(e,n,s,i=E.defaultColor,r=E.defaultLineWidth,a=E.defaultLineColor,o="center",c=E.defaultFont,l="",u=!0,h=void 0,d=he,f=0,p=v()){let y=E.uiContext;d.a>0&&(h&&bn(e,n.add(h),s.y,d,r,a,o,c,l,u?s.x:void 0,0,y),(f||p.x||p.y)&&(y.shadowColor=d.toString(),y.shadowBlur=f,y.shadowOffsetX=p.x,y.shadowOffsetY=p.y)),bn(e,n,s.y,i,r,a,o,c,l,u?s.x:void 0,0,y),y.shadowColor="#0000"}setupDragAndDrop(e,n,s,i){if(this._dragListeners)for(let[a,o]of this._dragListeners)document.removeEventListener(a,o);this._dragListeners=[];let r=(a,o)=>{let c=l=>{l.preventDefault(),a&&a(l)};document.addEventListener(o,c),this._dragListeners.push([o,c])};r(e,"drop"),r(n,"dragenter"),r(s,"dragleave"),r(i,"dragover")}screenToNative(e){if(!E.nativeHeight)return e;let n=N.y/E.nativeHeight,s=1/n,i=e.copy();return i.x+=n*N.x/2,i.x*=s,i.y*=s,i.x-=s*N.x/2,i}get keyInputObject(){return this._keyInputObject}set keyInputObject(e){let n=!!this._keyInputObject;this._keyInputObject=e,!n&&e?document.addEventListener("keydown",this._onKeyDown):n&&!e&&document.removeEventListener("keydown",this._onKeyDown)}destroyObjects(){for(let e of this.uiObjects)e.parent||e.destroy();this.uiObjects=this.uiObjects.filter(e=>!e.destroyed),this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.keyInputObject=void 0}getNavigableObjects(){function e(s){if(!(!s.visible||s.disabled)){s.isInteractive()&&s.navigationIndex!==void 0&&n.push(s);for(let i=s.children.length;i--;)e(s.children[i])}}let n=[];for(let s=E.uiObjects.length;s--;){let i=E.uiObjects[s];E.confirmDialog&&i!==E.confirmDialog||i.parent||e(i)}return n.sort((s,i)=>s.navigationIndex-i.navigationIndex),n}getNavigationDirection(){let e=E.navigationDirection===1,n=E.navigationDirection===2;if(as){let l=Ns(0,Ae),u=ar(Ae);return n?-(l.y||u.y)||l.x||u.x:e?-(l.y||u.y):l.x||u.x}let s="ArrowUp",i="ArrowDown",r="ArrowLeft",a="ArrowRight";if(n)return Ge(s)||Ge(r)?-1:Ge(i)||Ge(a)?1:0;let o=e?s:r,c=e?i:a;return Ge(o)?-1:Ge(c)?1:0}getNavigationOtherDirection(){if(E.navigationDirection===2)return 0;let e=E.navigationDirection===1;if(as){let i=Ns(0,Ae),r=ar(Ae);return e?i.x||r.x:i.y||r.y}let n=e?"ArrowLeft":"ArrowUp",s=e?"ArrowRight":"ArrowDown";return Ge(n)?-1:Ge(s)?1:0}getNavigationWasPressed(){return as?ga(0,Ae):Ne("Space")||Ne("Enter")}showConfirmDialog(e="Are you sure?",n,s,i=v(500,250),r="Escape"){m(!E.confirmDialog);let a=E.navigationDirection;E.navigationDirection=2;let o=new pt(v(),i);E.confirmDialog=o,o.onRender=()=>{let f=Vt(0,0,0,.7);E.drawRect(v(),v(1e9),f)},o.onUpdate=()=>{Ne(r)&&d()},o.isMouseOverlapping=()=>!0;let c=50,l=new Xi(v(0,-50),v(i.x-c,70),e);o.addChild(l);let u=new Qs(v(-80,50),v(120,70),"Yes");u.textHeight=40,u.navigationIndex=1,u.hoverColor=Vt(0,1,.5),u.onClick=()=>{d(),n&&n()},o.addChild(u);let h=new Qs(v(80,50),v(120,70),"No");h.textHeight=40,h.navigationIndex=2,h.navigationAutoSelect=!0,h.onClick=()=>{d(),s&&s()},o.addChild(h);function d(){m(E.confirmDialog===o),o.destroy(),E.confirmDialog=void 0,E.navigationDirection=a,ai()}}},pt=class{constructor(e=v(),n=v()){var s,i;m(D(e),"ui object pos must be a vec2"),m(D(n),"ui object size must be a vec2"),this.localPos=e.copy(),this.nativePos=e.copy(),this.size=n.copy(),this.color=E.defaultColor.copy(),this.activeColor=void 0,this.text=void 0,this.disabledColor=E.defaultDisabledColor.copy(),this.disabled=!1,this.textColor=E.defaultTextColor.copy(),this.hoverColor=E.defaultHoverColor.copy(),this.lineColor=E.defaultLineColor.copy(),this.gradientColor=E.defaultGradientColor?E.defaultGradientColor.copy():void 0,this.lineWidth=E.defaultLineWidth,this.cornerRadius=E.defaultCornerRadius,this.font=E.defaultFont,this.fontStyle=void 0,this.textWidth=void 0,this.textHeight=void 0,this.textFitScale=E.defaultTextFitScale,this.textShadow=void 0,this.textLineColor=E.defaultLineColor.copy(),this.textLineWidth=0,this.visible=!0,this.children=[],this.parent=void 0,this.extraTouchSize=0,this.soundPress=E.defaultSoundPress,this.soundRelease=E.defaultSoundRelease,this.soundClick=E.defaultSoundClick,this.interactive=!1,this.dragActivate=!1,this.canBeHover=!0,this.shadowColor=(s=E.defaultShadowColor)==null?void 0:s.copy(),this.shadowBlur=E.defaultShadowBlur,this.shadowOffset=(i=E.defaultShadowOffset)==null?void 0:i.copy(),this.navigationIndex=void 0,this.navigationAutoSelect=!1,this.anchor=v(),E.uiObjects.push(this)}addChild(e){return m(!e.parent&&!this.children.includes(e)),this.children.push(e),e.parent=this,e}removeChild(e){m(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}destroy(){var e;if(!this.destroyed){E.activeObject===this&&(E.activeObject=void 0),E.hoverObject===this&&(E.hoverObject=void 0),E.lastHoverObject===this&&(E.lastHoverObject=void 0),E.navigationObject===this&&(E.navigationObject=void 0),E.keyInputObject===this&&(E.keyInputObject=void 0),this.destroyed=1,(e=this.parent)==null||e.removeChild(this);for(let n of this.children)n.parent=void 0,n.destroy();this.children.length=0}}isMouseOverlapping(){if(!Ii)return!1;let e=ft?this.size.add(v(this.extraTouchSize||0)):this.size,n=E.screenToNative(Ke);return Ei(this.nativePos,e,n)}update(){if(this.onUpdate(),this.disabled&&(this===E.activeObject&&(E.activeObject=void 0),this===E.keyInputObject&&(E.keyInputObject=void 0)),E.keyInputObject)return;let e=E.lastHoverObject===this,n=this.isActiveObject(),s=Ds(0),i=this.dragActivate?s:Js(0);this.canBeHover&&(E.navigationMode||(i||n||!s&&!ft)&&!E.hoverObject&&this.isMouseOverlapping()&&(E.hoverObject=this)),this.isHoverObject()&&(this.disabled||(i&&this.interactive&&((!this.dragActivate||!e||Js(0))&&this.onPress(),this.soundPress&&this.soundPress.play(),E.activeObject&&!n&&E.activeObject.onRelease(),E.activeObject=this,E.activateOnPress&&this.click(!this.soundPress)),E.activateOnPress||!s&&this.isActiveObject()&&this.interactive&&this.click()),i&&ma(0,0,0,1,0)),n&&(!s||this.dragActivate&&!this.isHoverObject())&&(this.onRelease(),this.soundRelease&&this.soundRelease.play(),E.activeObject=void 0),this.isHoverObject()!==e&&(this.isHoverObject()?this.onEnter():this.onLeave())}render(){if(this.onRender(),!this.size.x||!this.size.y)return;let e=this.isNavigationObject(),n=e?this.color:this.interactive&&this.isActiveObject()&&!this.disabled?this.color:this.lineColor,s=e?this.hoverColor:this.disabled?this.disabledColor:this.interactive?this.isActiveObject()?this.activeColor||this.hoverColor:this.isHoverObject()?this.hoverColor:this.color:this.color,i=this.lineWidth*(e?1.5:1);E.drawRect(this.nativePos,this.size,s,i,n,this.cornerRadius,this.gradientColor,this.shadowColor,this.shadowBlur,this.shadowOffset)}getTextSize(){return v(this.textWidth||this.textFitScale*this.size.x,this.textHeight||this.textFitScale*this.size.y)}navigatePressed(){this.click()}isHoverObject(){return E.hoverObject===this}isActiveObject(){return E.activeObject===this}isNavigationObject(){return E.navigationObject===this}isKeyInputObject(){return E.keyInputObject===this}isInteractive(){return this.interactive&&this.visible&&!this.disabled}toString(){let e="type = "+this.constructor.name;return this.text&&(e+=`
+text = `+this.text),(this.nativePos.x||this.nativePos.y)&&(e+=`
+nativePos = `+this.nativePos),(this.localPos.x||this.localPos.y)&&(e+=`
+localPos = `+this.localPos),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.color&&(e+=`
+color = `+this.color),e}renderDebug(e=!0){let n=e?this.isHoverObject()?cl:this.disabled?dl:this.interactive?Yr:ul:ll;E.drawRect(this.nativePos,this.size,wt,4,n)}click(e=!0){this.onClick(),e&&this.soundClick&&this.soundClick.play()}onUpdate(){}onRender(){}onEnter(){}onLeave(){}onPress(){}onRelease(){}onClick(){}onChange(){}},Xi=class extends pt{constructor(e,n,s="",i="center",r=E.defaultFont){super(e,n),m(K(s),"ui text must be a string"),m(["left","center","right"].includes(i),"ui text align must be left, center, or right"),m(K(r),"ui text font must be a string"),this.text=s,this.align=i,this.font=r,this.canBeHover=!1,this.color=wt,this.shadowColor=wt,this.gradientColor=void 0,this.lineWidth=0,this.textFitScale=1}render(){super.render();let e=this.getTextSize();E.drawText(this.text,this.nativePos,e,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow,this.shadowColor,this.shadowBlur,this.shadowOffset)}},Tr=class extends pt{constructor(e,n,s=""){super(e,n),m(K(s),"ui text must be a string"),this.maxLength=0,this.text=s,this.interactive=!0,this.canBeHover=!0}click(){E.keyInputObject=this,this.onClick()}stopEditing(){this.isKeyInputObject()&&(this.soundRelease&&this.soundRelease.play(),E.activeObject=void 0,E.keyInputObject=void 0,this.onChange())}onKeyDown(e){let n=e.code,s=e.key;n==="Backspace"?this.text=this.text.slice(0,-1):n==="Enter"||n==="Escape"?this.stopEditing():s.length===1&&(!this.maxLength||this.text.lengththis.size.y,s=n?this.size.y:this.size.x,i=n?this.size.x:this.size.y,r=n?this.nativePos.x:this.nativePos.y,a=i-s,o=r-a/2,c=r+a/2,l=E.screenToNative(Ke);this.value=n?Ve(l.x,o,c):Ve(l.y,c,o)}else if(this.isNavigationObject()){let n=E.getNavigationOtherDirection();E.navigationTimer.active()||(this.value=H(this.value+n*.01))}this.value===e||this.onChange()}render(){super.render();let e=this.size.x>this.size.y,n=e?this.size.x:this.size.y,s=e?this.size.y:this.size.x;if(this.fillMode){let r=le(s,this.cornerRadius*2),a=et(r,n,this.value),o=(a-n)*(e?.5:-.5),c=this.nativePos.add(e?v(o,0):v(0,o)),l=this.disabled?this.disabledColor:this.handleColor,u=e?v(a,this.size.y):v(this.size.x,a);E.drawRect(c,u,l,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}else{let r=H(e?this.value:1-this.value),a=(n-s)*(r-.5),o=this.nativePos.add(e?v(a,0):v(0,a)),c=this.disabled?this.disabledColor:this.handleColor,l=v(s);E.drawRect(o,l,c,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}let i=this.getTextSize();E.drawText(this.text,this.nativePos,i,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow)}navigatePressed(){this.value=this.value?0:1,this.onChange(),this.onRelease(),super.navigatePressed()}},_r=class extends pt{constructor(e,n,s,i=!1,r=!1,a=1){super(e,n||v()),m(K(s),"video src must be a string"),m(O(a),"video volume must be a number"),this.color=he,this.cornerRadius=0,this.volume=a,this.video=document.createElement("video"),this.video.loop=r,this.video.volume=H(a*Bn),this.video.muted=!nt,this.video.style.display="none",this.video.src=s,document.body.appendChild(this.video),i&&this.play()}async play(){try{await this.video.play()}catch{}}pause(){this.video.pause()}stop(){this.video.pause(),this.video.currentTime=0}isLoading(){return this.video.readyState=1,"ui layout columns must be a number >= 1"),m(O(s),"ui layout gap must be a number"),m(O(i),"ui layout padding must be a number"),this.columns=n,this.gap=s,this.padding=i,r&&(this.color=wt,this.gradientColor=void 0,this.lineWidth=0,this.shadowColor=wt),this.relayout()}addChild(e){return super.addChild(e),this.relayout(),e}removeChild(e){super.removeChild(e),this.relayout()}relayout(){let e=this.children.length;if(!e){this.size=v(this.padding*2);return}let n=this.columns,s=Fs(e/n),i=new Array(n).fill(0),r=new Array(s).fill(0);for(let d=0;d=0&&b.objects.splice(e,1),super.destroy()}updatePhysics(){}render(){this.tileInfo?super.render():this.drawFixtures(this.color,this.lineColor,this.lineWidth)}renderDebugInfo(){let e=!this.getIsAwake(),n=this.getBodyType()===b.bodyTypeStatic,s=Y(e?1:0,e?1:0,n?1:0,.5);this.drawFixtures(s)}drawFixtures(e=Q,n=he,s=.1,i,r){this.getFixtureList().forEach(a=>{b.castShapeObject(a.GetShape()).GetType()!==b.instance.b2Shape.e_edge&&b.drawFixture(a,this.pos,this.angle,e,n,s,i,r)}),this.edgeLists.forEach(a=>rr(a,s,n,!1,this.pos,this.angle)),this.edgeLoops.forEach(a=>rr(a,s,n,!0,this.pos,this.angle))}beginContact(e){}endContact(e){}addShape(e,n=1,s=.2,i=0,r=!1){m(O(n),"density must be a number"),m(O(s),"friction must be a number"),m(O(i),"restitution must be a number");let a=new b.instance.b2FixtureDef;return a.set_shape(e),a.set_density(n),a.set_friction(s),a.set_restitution(i),a.set_isSensor(r),this.body.CreateFixture(a)}addBox(e=v(1),n=v(),s=0,i,r,a,o){m(D(e),"size must be a Vector2"),m(e.x>0&&e.y>0,"size must be positive"),m(D(n),"offset must be a Vector2"),m(O(s),"angle must be a number");let c=new b.instance.b2PolygonShape;return c.SetAsBox(e.x/2,e.y/2,b.vec2dTo(n),-s),this.addShape(c,i,r,a,o)}addPoly(e,n,s,i,r){m(St(e),"points must be an array");function a(c){m(3<=c.length&&c.length<=8);let l=b.instance._malloc(c.length*8);for(let d=0,f=0;d>2]=c[d].x,f+=4,b.instance.HEAPF32[l+f>>2]=c[d].y,f+=4;let u=b.instance.wrapPointer(l,b.instance.b2Vec2),h=new b.instance.b2PolygonShape;return h.Set(u,c.length),b.instance._free(l),h}let o=a(e);return this.addShape(o,n,s,i,r)}addRegularPoly(e=1,n=8,s,i,r,a){m(O(e)&&e>0,"diameter must be a positive number"),m(O(n)&&n>2,"sides must be a positive number greater than 2");let o=[],c=e/2;for(let l=n;l--;)o.push(v(c,0).rotate((l+.5)/n*te*2));return this.addPoly(o,s,i,r,a)}addRandomPoly(e=1,n,s,i,r){m(O(e)&&e>0,"diameter must be a positive number");let a=$r(3,9),o=[],c=e/2;for(let l=a;l--;)o.push(v(Se(c/2,c*1.5),0).rotate(l/a*te*2));return this.addPoly(o,n,s,i,r)}addCircle(e=1,n=v(),s,i,r,a){m(O(e)&&e>0,"diameter must be a positive number"),m(D(n),"offset must be a Vector2");let o=new b.instance.b2CircleShape;return o.set_m_p(b.vec2dTo(n)),o.set_m_radius(e/2),this.addShape(o,s,i,r,a)}addEdge(e,n,s,i,r,a){m(D(e),"point1 must be a Vector2"),m(D(n),"point2 must be a Vector2");let o=new b.instance.b2EdgeShape;return o.Set(b.vec2dTo(e),b.vec2dTo(n)),this.addShape(o,s,i,r,a)}addEdgeList(e,n,s,i,r){m(St(e),"points must be an array");let a=[],o=[];for(let c=0;ce[dt(l,e.length)];for(let l=0;lthis.destroyFixture(e))}getCenterOfMass(){return b.vec2From(this.body.GetWorldCenter())}getLinearVelocity(){return b.vec2From(this.body.GetLinearVelocity())}getAngularVelocity(){return this.body.GetAngularVelocity()}getMass(){return this.body.GetMass()}getInertia(){return this.body.GetInertia()}getIsAwake(){return this.body.IsAwake()}getBodyType(){return this.body.GetType()}getSpeed(){return this.getLinearVelocity().length()}setTransform(e,n){this.pos=e,this.angle=n,this.body.SetTransform(b.vec2dTo(e),-n)}setPosition(e){this.setTransform(e,this.body.GetAngle())}setAngle(e){this.setTransform(b.vec2From(this.body.GetPosition()),e)}setLinearVelocity(e){this.body.SetLinearVelocity(b.vec2dTo(e))}setAngularVelocity(e){this.body.SetAngularVelocity(e)}setLinearDamping(e){this.body.SetLinearDamping(e)}setAngularDamping(e){this.body.SetAngularDamping(e)}setGravityScale(e=1){this.body.SetGravityScale(this.gravityScale=e)}setBullet(e=!0){this.body.SetBullet(e)}setAwake(e=!0){this.body.SetAwake(e)}setBodyType(e){this.body.SetType(e)}setSleepingAllowed(e=!0){this.body.SetSleepingAllowed(e)}setFixedRotation(e=!0){this.body.SetFixedRotation(e)}setCenterOfMass(e){this.setMassData(e)}setMass(e){this.setMassData(void 0,e)}setMomentOfInertia(e){this.setMassData(void 0,void 0,e)}resetMassData(){this.body.ResetMassData()}setMassData(e,n,s){let i=new b.instance.b2MassData;this.body.GetMassData(i),e!==void 0&&i.set_center(b.vec2dTo(e)),n!==void 0&&i.set_mass(n),s!==void 0&&i.set_I(s),this.body.SetMassData(i)}setFilterData(e=0,n=0,s=0){this.getFixtureList().forEach(i=>{let r=i.GetFilterData();r.set_categoryBits(e),r.set_maskBits(65535&~n),r.set_groupIndex(s)})}setSensor(e=!0){this.getFixtureList().forEach(n=>n.SetSensor(e))}applyForce(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyForce(b.vec2dTo(e),b.vec2dTo(n))}applyAcceleration(e,n){n||(n=this.getCenterOfMass()),this.setAwake();let s=e.scale(this.getMass());this.body.ApplyLinearImpulse(b.vec2dTo(s),b.vec2dTo(n))}applyImpulse(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyLinearImpulse(b.vec2dTo(e),b.vec2dTo(n))}applyTorque(e){this.setAwake(),this.body.ApplyTorque(e)}applyAngularAcceleration(e){this.setAwake(),this.body.ApplyAngularImpulse(e*this.getInertia())}applyAngularImpulse(e){this.setAwake(),this.body.ApplyAngularImpulse(e)}hasFixtures(){return!b.isNull(this.body.GetFixtureList())}getFixtureList(){let e=[];for(let n=this.body.GetFixtureList();!b.isNull(n);)e.push(n),n=n.GetNext();return e}hasJoints(){return!b.isNull(this.body.GetJointList())}getJointList(){let e=[];for(let n=this.body.GetJointList();!b.isNull(n);)e.push(n),n=n.get_next();return e}},Ki=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeStatic;super(e,n,s,i,r,o,a)}},Rr=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeKinematic;super(e,n,s,i,r,o,a)}},Pr=class extends Ki{constructor(e){m(e instanceof qs,"tileLayer must be a TileCollisionLayer"),super(e.pos,e.size),this.tileLayer=e,this.addChild(e)}render(){}buildCollision(e=.2,n=0){this.destroyAllFixtures(),this.pos=this.tileLayer.pos.copy(),this.size=this.tileLayer.size.copy();let s=[],i=(a,o)=>a+o*this.size.x,r=(a,o)=>!s[i(a,o)]&&this.tileLayer.getCollisionData(v(a,o))>0;for(let a=0;ai.fractionr.pos.distanceSquared(e)0,"Tween duration must be > 0"),this.callback=e,this.start=n,this.end=s,this.duration=i,this.life=i,this.ease=r.ease||no.LINEAR,this.useRealTime=!!r.useRealTime,this.paused=!!r.paused,this.thenCallback=void 0,this.loopRemaining=0,ot.push(this),e(this.interp(i))}setEase(e){return this.ease=e,this}then(e){return this.thenCallback=e,this.loopRemaining=0,this}loop(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>Nl(this),this}pingPong(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>zl(this),this}pause(){this.paused=!0}resume(){this.paused=!1}restart(){this.life=this.duration,this.paused=!1,ot.indexOf(this)<0&&ot.push(this),this.callback(this.interp(this.duration))}isActive(){return!this.paused&&ot.indexOf(this)>=0}getPercent(){return Ve(this.duration-this.life,0,this.duration)}getValue(){return this.interp(this.life)}interp(e){let n=this.ease((this.duration-e)/this.duration);return Nc(this.start)?this.start.lerp(this.end,n):this.start+(this.end-this.start)*n}stop(){let e=ot.indexOf(this);e>=0&&ot.splice(e,1),this.thenCallback=void 0}},no={LINEAR:t=>t,POWER:t=>e=>e**t,SINE:t=>1-ye(t*(te/2)),CIRC:t=>1-(1-t*t)**.5,EXPO:t=>t===0?0:2**(10*t-10),BACK:t=>t*t*(2.70158*t-1.70158),ELASTIC:t=>t===0?0:t===1?1:-(2**(10*t-10))*fe((37-40*t)*te/6),SPRING:t=>1-(fe(te*(1-t)*(.2+2.5*(1-t)**3))*t**2.2+(1-t))*(1+1.2*t),BOUNCE:t=>{let e=1-t,n;return e<4/11?n=7.5625*e*e:e<8/11?n=7.5625*(e-=6/11)*e+.75:e<10/11?n=7.5625*(e-=9/11)*e+.9375:n=7.5625*(e-=10.5/11)*e+.984375,1-n},IN:t=>t,OUT:t=>e=>1-t(1-e),IN_OUT:t=>no.PIECEWISE(t,no.OUT(t)),PIECEWISE:(...t)=>{let e=t.length;return n=>{let s=n*e-1e-9>>0;return(t[s]((n-s/e)*e)+s)/e}},BEZIER:(t,e,n,s)=>{let i=r=>{let a=1-r,o=3*a*a*r,c=3*a*r*r,l=r**3;return[o*t+c*n+l,o*e+c*s+l]};return r=>{let a=0,o=1;for(let c=0;c<128;c++){let l=(a+o)/2,[u,h]=i(l);if(de(u-r)<1e-5)return h;u=this.size.x||n>=this.size.y?null:this.nodes[e+n*this.size.x]}worldToTile(e){let n=this.tileLayer?this.tileLayer.pos.x:0,s=this.tileLayer?this.tileLayer.pos.y:0;return v(Pe(e.x-n),Pe(e.y-s))}tileToWorld(e,n){let s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;return v(e+.5+s,n+.5+i)}buildNodeData(){let e=this.size.x,n=this.size.y,s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;for(let r=0;r0&&(c?l>0&&ke(o.posWorld,Zo,Y(1,0,0,le(.2,l*.05)),this.debugTime):ke(o.posWorld,Zo,Y(1,0,0,.25),this.debugTime))}}aStarSearch(e,n){m(e&&n,"aStarSearch needs both endpoints"),m(e!==n,"aStarSearch: start and end must differ \u2014 caller should handle trivial case"),m(e.walkable&&n.walkable,"aStarSearch: endpoints must be walkable");let s=[e];e.isOpen=!0;let i=0;for(;s.length>0;){let r=0,a=s[0].f;for(let c=1;cthis.maxLoop)break;o.isOpen=!1,s.splice(r,1),o.isClosed=!0,this.debug&&this.debugTime>0&&ke(o.posWorld,Zo,Y(1,1,1,.05),this.debugTime);for(let c=-1;c<=1;++c)for(let l=-1;l<=1;++l){if(l===0&&c===0)continue;let u=this.getNode(o.pos.x+l,o.pos.y+c);if(!u||!u.walkable||u.isClosed)continue;let h=1;if(l!==0&&c!==0){let x=this.getNode(o.pos.x+l,o.pos.y);if(!x||!x.walkable)continue;let w=this.getNode(o.pos.x,o.pos.y+c);if(!w||!w.walkable)continue;h=Vh}let d=o.g+h+u.cost;if(!u.isOpen)u.isOpen=!0,s.push(u);else if(d>=u.g)continue;u.parent=o,u.g=d;let f=de(n.pos.x-u.pos.x),p=de(n.pos.y-u.pos.y),y=re(f,p)+(Math.SQRT2-1)*le(f,p);u.f=u.g+y*this.heuristicWeight}}return n.parent!==null}getNearestClearNode(e,n=10,s=!0){m(D(e),"worldPos must be a Vector2"),s&&this.buildNodeData();let i=this.tileLayer?this.tileLayer.pos.x:0,r=this.tileLayer?this.tileLayer.pos.y:0,a=Pe(e.x-i),o=Pe(e.y-r);for(let c=0;c<=n;++c){let l=null,u=0;for(let h=-c;h<=c;++h)for(let d=-c;d<=c;++d){if(c>0&&de(d)!==c&&de(h)!==c)continue;let f=this.getNode(a+d,o+h);if(!f||!f.isClear())continue;let p=f.posWorld.x-e.x,y=f.posWorld.y-e.y,x=p*p+y*y;(!l||x0&&Qe(i.posWorld,.3,Y(.5,0,.5,.5),this.debugTime),e.splice(n,1),n=re(1,n-1);continue}else if(c===2){this.debug&&this.debugTime>0&&Qe(i.posWorld,.3,Y(1,0,0,.5),this.debugTime);let f,p;s.pos.y===i.pos.y&&r.pos.x===i.pos.x?(f=s.pos.x,p=r.pos.y):(f=r.pos.x,p=s.pos.y);let y=this.getNode(f,p);if(y&&y.isClear()){e.splice(n,1),n=re(1,n-1);continue}}else if(c===5){this.debug&&this.debugTime>0&&Qe(i.posWorld,.3,Y(1,1,0,.5),this.debugTime);let f=n>=2?e[n-2]:s,p,y,x,w;l===0||h===0?(p=r.pos.x,y=i.pos.y,x=s.pos.x,w=i.pos.y):(p=i.pos.x,y=r.pos.y,x=i.pos.x,w=s.pos.y);let A=p-f.pos.x,S=y-f.pos.y,_=x-f.pos.x,k=w-f.pos.y,C=A*A+S*S,L=_*_+k*k,V=C0&&Qe(i.posWorld,.3,Y(0,1,0,.5),this.debugTime),l===h&&u===d){++n;continue}else{let f,p;s.pos.y===r.pos.y?(f=i.pos.x,p=s.pos.y):(f=s.pos.x,p=i.pos.y);let y=this.getNode(f,p);if(y&&y.isClear()){e[n]=y,n=re(1,n-1);continue}}++n}}smoothPathStringPull(e){if(e.length<=2)return;for(let i of e)if(!i.isClear())return;let n=e.slice();e.length=0,e.push(n[0]);let s=0;for(let i=1;i0&&Rt(r.posWorld,e[e.length-1].posWorld,Y(0,0,1,.3),.02,this.debugTime);continue}for(;s=1;--n){let s=e[n-1],i=e[n],r=e[n+1];(i.pos.x-s.pos.x)*(r.pos.y-s.pos.y)===(i.pos.y-s.pos.y)*(r.pos.x-s.pos.x)&&e.splice(n,1)}}isNodeClear(e,n){let s=this.getNode(e,n);return s!==null&&s.isClear()}isLineClear(e,n){m(D(e)&&D(n),"isLineClear needs Vector2 endpoints"),m(this.isNodeClear(e.x,e.y)&&this.isNodeClear(n.x,n.y),"isLineClear endpoints must be in-bounds and clear");let s=n.x-e.x,i=n.y-e.y,r=de(s),a=de(i),o=ut(s),c=ut(i),l=e.x,u=e.y;if(a===r){for(;l!==n.x;){if(l!==e.x&&(!this.isNodeClear(l,u)||!this.isNodeClear(l,u-c))||!this.isNodeClear(l,u+c))return!1;l+=o,u+=c}if(!this.isNodeClear(n.x,n.y-c))return!1}else if(ao.posWorld.copy());if(this.debug&&this.debugTime>0&&a.length>0){for(let o=1;oWh,bootGameHost:()=>Hh,default:()=>qh});var kn=class{constructor(e){this._state=(e==null?2654435769:e)>>>0}next(){this._state=this._state+1831565813>>>0;let e=this._state;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}range(e,n){return e+this.next()*(n-e)}reseed(e){this._state=(e==null?2654435769:e)>>>0}},vo=class{constructor(e){this._clock=e||eu(),this._origin=this._clock()}nowMs(){return this._clock()}elapsedMs(){return this._clock()-this._origin}},wo=class{constructor(e){this._time=e,this._subs=new Map}sourceFor(e){let n=this,s=e==null?null:e;return{on(i,r){if(n._assertType(i),typeof r!="function")throw new Error("[HostDevInputBridge] on \u7684 handler \u5FC5\u987B\u662F\u51FD\u6570");let a=n._subs.get(i)||[],o={handler:r,scope:s};return a.push(o),n._subs.set(i,a),{cancel(){let c=n._subs.get(i);if(!c)return;let l=c.indexOf(o);l>=0&&c.splice(l,1)}}},off(i,r){n._assertType(i);let a=n._subs.get(i);if(!a)return;let o=a.findIndex(c=>c.handler===r&&c.scope===s);o>=0&&a.splice(o,1)}}}_emit(e,n){this._assertType(e);let s=n||{},i={type:e,x:typeof s.x=="number"?s.x:0,y:typeof s.y=="number"?s.y:0,key:typeof s.key=="string"?s.key:"",tMs:this._time.nowMs()},r=this._subs.get(e);if(!r||r.length===0)return;let a=r.slice();for(let o of a)try{o.handler(i)}catch(c){on("[host-dev input] \u8F93\u5165 handler \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09type="+e,c)}}disposeScope(e){if(e==null)return 0;let n=0;for(let[s,i]of this._subs){let r=i.filter(a=>a.scope!==e);n+=i.length-r.length,r.length===0?this._subs.delete(s):this._subs.set(s,r)}return n}_subscriptionCount(){let e=0;for(let n of this._subs.values())e+=n.length;return e}_assertType(e){if(!To.has(e))throw new Error("[HostDevInputBridge] \u975E\u6CD5\u8F93\u5165\u4E8B\u4EF6\u7C7B\u578B\uFF1A"+String(e)+"\uFF08\u4EC5\u652F\u6301 "+Array.from(To).join("/")+"\uFF09")}},To=new Set(["pointerdown","pointermove","pointerup","keydown","keyup"]);function Ba(t){let e=t||{},n=new vo(e.clock),s=new kn(e.seed),i=e.seed==null?2654435769:e.seed>>>0,r=new wo(n),a=typeof e.audioFactory=="function"?e.audioFactory:null,o=null,c=!1,l=typeof e.engineFactory=="function"?e.engineFactory:null,u=null,h=!1,d=new Map,f=0,p=0;function y(){if(o)return o;if(!a)return c||(ko("[host-dev audio] \u672A\u6CE8\u5165 audioFactory\uFF0CgetAudioContext \u8FD4\u56DE null\uFF08P6 \u987B\u5BB9\u9519\u964D\u7EA7\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u5DE5\u5382\uFF09"),c=!0),null;try{o=a()}catch(_){on("[host-dev audio] audioFactory \u629B\u9519\uFF0CgetAudioContext \u964D\u7EA7\u8FD4\u56DE null",_),o=null}return o}function x(){if(u)return u;if(!l)return h||(ko("[host-dev engine] \u672A\u6CE8\u5165 engineFactory\uFF0CgetEngine \u8FD4\u56DE null\uFF08\u63D2\u4EF6\u987B\u5BB9\u9519\u964D\u7EA7\uFF1A\u7C92\u5B50\u9000\u53D7\u63A7\u9762\u81EA\u7BA1/\u5408\u6210\u6838\u9000 vendored/\u6570\u5B66\u9000\u5185\u7F6E\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u80CC\u4E66\uFF09"),h=!0),null;try{u=l()}catch(_){on("[host-dev engine] engineFactory \u629B\u9519\uFF0CgetEngine \u964D\u7EA7\u8FD4\u56DE null",_),u=null}return u}function w(_,k){return{getContext2d(){return e.context2d==null?null:e.context2d},onFrame(L){let V=f++;return d.set(V,L),{cancel(){d.delete(V)}}},getInput(){return r.sourceFor(_)},getAudioContext(){return y()},getEngine(){return x()},time:n,random:k}}let A=w(null,s),S={context:A,tick(_){p+=1;let k=Array.from(d.values());for(let C of k)try{C(_,p)}catch(L){on("[host-dev tick] \u5E27\u56DE\u8C03\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09frame="+p,L)}},frameCount(){return p},inputBridge:r,deriveContextFor(_,k){let C=Zl(i,_),L=new kn(C);return w(k==null?_:k,L)}};return Object.defineProperty(A,Ao,{value:S,enumerable:!1,writable:!1,configurable:!1}),S}var Ao=Symbol("zaomeng.coreProtocol.contextBundle"),ui=class{constructor(){this._plugins=new Map,this._initOrder=[],this._initErrors=[],this._phase="idle",this._disposed=!1,this._context=void 0,this._pluginContexts=new Map}register(e){if(!e||typeof e!="object")throw new Error("[PluginRegistry] register \u9700\u8981\u4E00\u4E2A\u63D2\u4EF6\u5BF9\u8C61");if(typeof e.name!="string"||e.name.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6\u7F3A\u5C11\u5408\u6CD5 name");if(typeof e.version!="string"||e.version.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11\u5408\u6CD5 version");if(typeof e.init!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11 init \u51FD\u6570");if(e.dispose!=null&&typeof e.dispose!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7684 dispose \u5FC5\u987B\u662F\u51FD\u6570\u6216\u7701\u7565");if(this._plugins.has(e.name))throw new Error("[PluginRegistry] \u63D2\u4EF6\u91CD\u540D\u62D2\u7EDD\uFF1A"+e.name+" \u5DF2\u6CE8\u518C");return this._plugins.set(e.name,e),this}has(e){return this._plugins.has(e)}get(e){return this._plugins.get(e)}list(){return Array.from(this._plugins.keys())}initAll(){if(this._phase==="initialized")return ko("[PluginRegistry] initAll \u91CD\u590D\u8C03\u7528\uFF0C\u5DF2\u5FFD\u7565\uFF08\u5DF2\u5904\u4E8E initialized\uFF09"),this._initResult();if(this._phase==="disposed")throw new Error("[PluginRegistry] \u5DF2 dispose \u7684\u6CE8\u518C\u5668\u4E0D\u53EF\u518D initAll");if(this._context==null)throw new Error("[PluginRegistry] \u672A\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\uFF1A\u8BF7\u5728 initAll() \u4E4B\u524D\u8C03\u7528 useContext(context)\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context); reg.initAll();\uFF09");for(let[e,n]of this._plugins){let s=this._missingDeps(n);if(s.length>0){let r=new Error("[PluginRegistry] \u63D2\u4EF6 "+e+" \u4F9D\u8D56\u7F3A\u5931\uFF1A"+s.join(", ")+"\uFF08\u672A\u6CE8\u518C\uFF09");this._initErrors.push({name:e,error:r}),on("[PluginRegistry] \u8DF3\u8FC7 init\uFF08\u4F9D\u8D56\u7F3A\u5931\uFF0C\u5DF2\u9694\u79BB\uFF09\uFF1A"+e,r);continue}let i=this._contextFor(e);try{n.init(i),this._initOrder.push(e)}catch(r){let a=r instanceof Error?r:new Error(String(r));this._initErrors.push({name:e,error:a}),on("[PluginRegistry] \u63D2\u4EF6 init \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF0C\u4E0D\u8FDE\u5750\uFF09\uFF1A"+e,a)}}return this._phase="initialized",this._initResult()}_contextFor(e){let n=this._pluginContexts.get(e);if(n)return n;let s=this._context&&this._context[Ao],i;return s&&typeof s.deriveContextFor=="function"?i=s.deriveContextFor(e,e):i=this._context,this._pluginContexts.set(e,i),i}disposeAll(){if(this._disposed)return{disposed:[],errors:[]};let e=[],n=[],s=this._context&&this._context[Ao],i=s&&s.inputBridge;for(let r=this._initOrder.length-1;r>=0;r--){let a=this._initOrder[r],o=this._plugins.get(a);if(o&&typeof o.dispose=="function")try{o.dispose(),e.push(a)}catch(c){let l=c instanceof Error?c:new Error(String(c));n.push({name:a,error:l}),on("[PluginRegistry] \u63D2\u4EF6 dispose \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,l)}if(i&&typeof i.disposeScope=="function")try{i.disposeScope(a)}catch(c){on("[PluginRegistry] \u56DE\u6536\u63D2\u4EF6\u8F93\u5165\u8BA2\u9605\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,c)}}return this._disposed=!0,this._phase="disposed",{disposed:e,errors:n}}useContext(e){if(this._phase!=="idle")throw new Error("[PluginRegistry] useContext \u5FC5\u987B\u5728 initAll() \u4E4B\u524D\u8C03\u7528\uFF08\u5F53\u524D\u9636\u6BB5\uFF1A"+this._phase+"\uFF09\u3002\u8BF7\u5728\u4EFB\u4F55 initAll/disposeAll \u4E4B\u524D\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\u3002");if(e==null||typeof e!="object")throw new Error("[PluginRegistry] useContext \u9700\u8981\u4E00\u4E2A\u53D7\u63A7\u4E0A\u4E0B\u6587\u5BF9\u8C61\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context);\uFF09");return this._context=e,this}_missingDeps(e){return!Array.isArray(e.dependencies)||e.dependencies.length===0?[]:e.dependencies.filter(n=>!this._plugins.has(n))}_initResult(){return{ok:this._initErrors.length===0,initialized:this._initOrder.slice(),errors:this._initErrors.slice()}}};function Zl(t,e){let n=2166136261,s=16777619,i=t>>>0;for(let a=0;a<32;a+=8){let o=i>>>a&255;n^=o,n=Math.imul(n,s)>>>0}let r=String(e);for(let a=0;a>>0,n^=o>>>8&255,n=Math.imul(n,s)>>>0}return n>>>0}function eu(){if(typeof globalThis!="undefined"&&globalThis.performance&&typeof globalThis.performance.now=="function")return()=>globalThis.performance.now();if(typeof process!="undefined"&&process.hrtime&&typeof process.hrtime.bigint=="function"){let t=process.hrtime.bigint();return()=>Number(process.hrtime.bigint()-t)/1e6}return()=>Date.now()}function on(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function ko(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Xh=Object.freeze(Array.from(To)),ja="core-protocol-v0";var Ja=Object.freeze(["t_boot","t_plugins_ready","t_game_init","t_first_paint","t_input_bound","t_game_start"]),Co=Ja.reduce((t,e,n)=>(t[e]=n,t),Object.create(null)),tu=new Set(Ja);function _o(t){let e=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}var Na=_o("runtime-probe::seed::v1");function di(t){return t===null||typeof t!="object"?JSON.stringify(t):Array.isArray(t)?"["+t.map(di).join(",")+"]":"{"+Object.keys(t).sort().map(n=>JSON.stringify(n)+":"+di(t[n])).join(",")+"}"}function za(t){let e=di(t.extra==null?null:t.extra),n=di(Array.isArray(t.pluginSet)?t.pluginSet:[]);return["seq="+t.seq,"anchor="+t.anchor,"tMono="+t.tMono,"buildSha="+(t.buildSha||""),"pluginSet="+n,"extra="+e].join("|")}function nu(t){return Math.round(t*1e3)/1e3}function su(t){if(!Array.isArray(t))return{ok:!1,reason:"records_not_array"};let e=Na,n=-1;for(let s=0;stypeof _=="string").slice().sort():[],i=typeof e.sink=="function"?e.sink:null,r=e.autoBoot!==!1,a=typeof e.inputAnchorType=="string"?e.inputAnchorType:"pointerdown",o=()=>0,c=!1,l=0,u=Na,h=[],d=new Set,f=-1,p=null,y=!1,x=!1,w=!1;function A(_,k){let C=null;if(!tu.has(_))C="unknown_anchor";else{d.has(_)&&(C=C?C+";duplicate_anchor":"duplicate_anchor");let V=Co[_];V_.time.nowMs(),c=!0,r&&!x&&A("t_boot",{auto:!0}),p=_.getInput().on(a,k=>{y||(y=!0,A("t_input_bound",{firstInput:!0,type:k.type}))}),A("t_input_bound",{stage:"registered",type:a})},dispose(){w||(p&&(p.cancel(),p=null),w=!0)},mark:A,getRecords(){return h.map(_=>({..._}))},toJSONL(){return h.map(_=>JSON.stringify(_)).join(`
+`)},verify(){return su(h)}}}function iu(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Va(t){let e=t.LJS,n=t.engineMath,s=t.engineMode,i=t.recHook||(()=>{});if(s!=="real")return null;let r=n;return{math:{lerp:(o,c,l)=>(i("math.lerp"),r.lerp(o,c,l)),smoothStep:o=>(i("math.smoothStep"),r.smoothStep(o)),easing:Object.fromEntries(Object.keys(r.easing).map(o=>[o,c=>(i("math.easing."+o),r.easing[o](c))]))},particles:{spawnEmitter(o){i("particles.spawnEmitter");let c=e.screenToWorld(e.vec2(o.pos.x,o.pos.y)),l=e.cameraScale,u=o.emitTime!=null?o.emitTime:o.count!=null?1/60:0,h=o.emitRate!=null?o.emitRate:o.count!=null?o.count*60:100,d=(o.speed!=null?o.speed:0)/l/60,f=o.damping!=null?o.damping:1,p=o.colorStart||{r:1,g:1,b:1,a:1},y=o.colorEnd||{r:1,g:1,b:1,a:0},x=e.rgb(p.r,p.g,p.b,p.a),w=e.rgb(y.r,y.g,y.b,y.a),A=new e.ParticleEmitter(c,o.angle!=null?o.angle:0,(o.emitSize!=null?o.emitSize:0)/l,u,h,o.coneAngle!=null?o.coneAngle:Math.PI,void 0,x,x,w,w,o.particleTime!=null?o.particleTime:.5,(o.sizeStart!=null?o.sizeStart:6)/l,(o.sizeEnd!=null?o.sizeEnd:0)/l,d,0,f,1,o.gravityScale!=null?o.gravityScale:0,Math.PI,.1,0,!1,o.additive!=null?o.additive:!1,!0);return{isActive(){return A.isActive()},stop(){A.destroyed||A.destroy(!0)}}}},audio:{synth:{synthSfx:o=>{i("audio.synth.synthSfx");try{return e.zzfxG(...o)}catch(c){return console.error("[host][engine-audio] zzfxG \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(c&&c.message?c.message:c)),null}},synthSong:(o,c,l,u)=>{i("audio.synth.synthSong");try{return e.zzfxM(o,c,l,u)}catch(h){return console.error("[host][engine-audio] zzfxM \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(h&&h.message?h.message:h)),null}}}}}}function yt(t){return t<0?0:t>1?1:t}function Wa(t){let e=t.Ease,n=e.POWER(2),s=e.POWER(3),i=e.OUT(n),r=e.IN_OUT(n),a=e.OUT(s),o=e.IN_OUT(s),c=e.OUT(e.BACK),l=e.OUT(e.ELASTIC);return{lerp:(u,h,d)=>t.lerp(u,h,d),smoothStep:u=>t.smoothStep(u),easing:{linear:u=>e.LINEAR(yt(u)),quadIn:u=>n(yt(u)),quadOut:u=>i(yt(u)),quadInOut:u=>r(yt(u)),cubicIn:u=>s(yt(u)),cubicOut:u=>a(yt(u)),cubicInOut:u=>o(yt(u)),backIn:u=>e.BACK(yt(u)),backOut:u=>c(yt(u)),elasticIn:u=>e.ELASTIC(yt(u)),elasticOut:u=>l(yt(u))}}}var rn=2,fi=1/60;async function qa(t){let e=t.canvas,n=t.statusEl||null,s=t.engine,i=t.seed>>>0,r=t.mode||"play",a=t.engineMode||"real",o=t.viewport.w,c=t.viewport.h,l=t.factory,u=t.buildFactoryOpts||(()=>{}),h=t.plugins||{},d=t.registerOrder||Object.values(h),f=t.onReady||(()=>{}),p=t.recHook||(()=>{});function y(G){n&&(n.textContent=G)}let x=[];window.addEventListener("error",G=>x.push({type:"error",message:String(G&&G.message||G)})),window.addEventListener("unhandledrejection",G=>x.push({type:"unhandledrejection",message:String(G&&G.reason&&G.reason.message||G&&G.reason||G)}));let w=null,A=!1;function S(){if(!A)return null;if(w)return w;let G=window.AudioContext||window.webkitAudioContext;return G?(w=new G,w):null}let _=0,k=null,C=null,L=null,V=null,ce=[],ne={},T=null;function P(G,pe){try{L&&L.mark(G,pe)}catch(F){x.push({type:"mark",message:String(F&&F.message||F)})}}function R(){C&&typeof C._refreshChecklist=="function"&&C._refreshChecklist(ne)}async function M(G,pe){k=Ba({context2d:G,seed:i,audioFactory:S,clock:()=>_,engineFactory:()=>Va({LJS:a==="real"?s:null,engineMath:a==="real"?Wa(s):null,engineMode:a,recHook:p})});let F=new ui;for(let J of d)F.register(J);F.useContext(k.context),V=F.initAll(),ce=F.list().concat(["runtime-probe"]),L=Ua({pluginSet:ce,inputAnchorType:"pointerdown",autoBoot:!0});let I=k.deriveContextFor("runtime-probe","runtime-probe");P("t_boot",{by:"game-host",stage:"pre-init",engineMode:a}),P("t_plugins_ready",{initialized:V.initialized.length,ok:V.ok});let B=u(k.context,{bundle:k,plugins:h,getRealAudioCtx:()=>w});C=l(B),await C.init({ctx:k.context,mainContext:G,canvas:pe(),seed:i}),T=C&&typeof C._forensicsView=="function"?C._forensicsView():null,P("t_game_init",{hasForensics:!!T}),se(),P("t_first_paint",{frame:k.frameCount()});try{L.init(I)}catch(J){x.push({type:"probe-init",message:String(J&&J.message||J)})}P("t_game_start",{mode:r,engineMode:a}),R(),f(Ft,{bundle:k,game:C,probe:L,checklist:ne,uncaught:x,pluginSet:ce,initRes:V,getGameForensics:()=>T,mark:P,stepOneFrame:se})}let j=null;function se(G){let pe=typeof G=="number"?G:fi;C&&(_+=pe*1e3,C.update(pe),a==="stub"&&j&&C.render(j),R())}function we(G){for(let pe=0;pe{}),C&&typeof C._onAudioUnlock=="function"&&C._onAudioUnlock()}let Ft={seed:i,mode:r,engineMode:a,protocol:ja,frameCount:()=>k?k.frameCount():0,stepFrames:we,startRaf:()=>Yn(),stopRaf:()=>Bt(),tap(G,pe){be(),k&&(k.inputBridge._emit("pointerdown",{x:G,y:pe}),k.inputBridge._emit("pointerup",{x:G,y:pe}))},do(G){C&&typeof C._handleAction=="function"&&C._handleAction(G)},state:()=>T?T.state():{phase:"booting"}};function en(G){let pe=k.inputBridge;function F(I,B){let J=G.getBoundingClientRect();return{x:(I-J.left)/J.width*o,y:(B-J.top)/J.height*c}}G.addEventListener("pointerdown",I=>{be(),pe._emit("pointerdown",F(I.clientX,I.clientY))}),G.addEventListener("pointermove",I=>{pe._emit("pointermove",F(I.clientX,I.clientY))}),G.addEventListener("pointerup",I=>{pe._emit("pointerup",F(I.clientX,I.clientY))})}let We=0,Gt=!1,lt=0;function mt(G){if(!Gt)return;lt===0&&(lt=G);let pe=(G-lt)/1e3;lt=G,pe>.05&&(pe=.05),se(pe),We=window.requestAnimationFrame(mt)}function Yn(){a==="stub"&&(Gt||(Gt=!0,lt=0,We=window.requestAnimationFrame(mt)))}function Bt(){Gt=!1,We&&window.cancelAnimationFrame(We),We=0}function Xn(G){G.width=o*rn,G.height=c*rn,G.style.width=o+"px",G.style.height=c+"px";let pe=G.getContext("2d",{willReadFrequently:!0});return pe.setTransform(rn,0,0,rn,0,0),pe}async function vs(){let G=Xn(e);return j=G,await M(G,()=>e),en(e),r==="evidence"?y(`evidence \u5C31\u7EEA seed=${i} \xB7 \u7528 host \u9A71\u52A8\uFF08stepFrames/tap\uFF09`):(y(`seed=${i} \xB7 \u70B9\u5F00\u59CB\uFF08\u9996\u6B21\u70B9\u51FB\u5F00\u58F0\uFF09`),Yn()),Ft}let tn=()=>{},nn=()=>{};function sn(){window.__gameHostEngineInitFired=!0}function Kn(){tn()}function Qn(){}function go(){nn()}function bo(){}async function xo(G){await M(G,()=>s.mainCanvas),en(s.mainCanvas),tn=()=>{C&&(_+=fi*1e3,C.update(fi))},nn=()=>{if(C){G.save(),G.setTransform(rn,0,0,rn,0,0);try{G.imageSmoothingEnabled=!1}catch{}C.render(G),G.restore()}},s.mainCanvas&&(s.mainCanvas.id="game-engine"),window.__engine={frame(){return s.frame},time(){return s.time},timeReal(){return s.timeReal},paused(){return s.paused},timeScale(){return s.timeScale},snapshot(){return{frame:s.frame,time:s.time,timeReal:s.timeReal,paused:s.paused,timeScale:s.timeScale}}},y(`engine RAF running \xB7 seed=${i} engine=real`)}if(a!=="real")return await vs();if(!s){let G="real \u901A\u9053\u672A\u6CE8\u5165\u5F15\u64CE\uFF08opts.engine \u7F3A\u5931\uFF09\uFF1A\u8BF7\u7ECF entry \u5305\u88C5\u5C42\u542F\u52A8\uFF08host \u4E0D\u76F4\u63A5 import \u5F15\u64CE\uFF0CQ4/Option C\uFF09";throw y("ENGINE INJECT MISSING: "+G),new Error(G)}s.setGLEnable(!1),s.setShowSplashScreen(!1),s.setDebugWatermark(!1),s.setCanvasClearColor(s.BLACK),s.setCanvasFixedSize(s.vec2(o*rn,c*rn));let ws=document.createElement("div");return ws.id="engine-root",document.body.appendChild(ws),await s.engineInit(sn,Kn,Qn,go,bo,[],ws).then(()=>xo(s.mainContext)).catch(G=>{throw window.__gameHostBootError=String(G&&G.message||G),y("ENGINE INIT FAILED: "+window.__gameHostBootError),G}),Ft}function ou(){return{hit:!1,depth:0,nx:0,ny:0}}var Eo=class{constructor(e){let n=e||{},s=typeof n.cellSize=="number"&&n.cellSize>0?n.cellSize:64;this._cellSize=s,this._cells=new Map,this._entries=new Map,this._seq=0}get size(){return this._entries.size}_cellRange(e){let n=this._cellSize,s=Math.floor((e.x-e.hw)/n),i=Math.floor((e.x+e.hw)/n),r=Math.floor((e.y-e.hh)/n),a=Math.floor((e.y+e.hh)/n);return{cx0:s,cy0:r,cx1:i,cy1:a}}insert(e,n){this._entries.has(e)&&this.remove(e);let{cx0:s,cy0:i,cx1:r,cy1:a}=this._cellRange(n),o=[];for(let l=i;l<=a;l++)for(let u=s;u<=r;u++){let h=u+","+l,d=this._cells.get(h);d||(d=new Set,this._cells.set(h,d)),d.add(e),o.push(h)}let c={x:n.x,y:n.y,hw:n.hw,hh:n.hh};this._entries.set(e,{id:e,box:c,seq:this._seq++,cells:o})}remove(e){let n=this._entries.get(e);if(!n)return!1;for(let s of n.cells){let i=this._cells.get(s);i&&(i.delete(e),i.size===0&&this._cells.delete(s))}return this._entries.delete(e),!0}query(e){let{cx0:n,cy0:s,cx1:i,cy1:r}=this._cellRange(e),a=new Set;for(let o=s;o<=r;o++)for(let c=n;c<=i;c++){let l=this._cells.get(c+","+o);if(l)for(let u of l)a.add(u)}return this._collect(a)}queryPoint(e,n){let s=this._cellSize,i=Math.floor(e/s),r=Math.floor(n/s),a=this._cells.get(i+","+r);return a?this._collect(new Set(a)):[]}clear(){this._cells.clear(),this._entries.clear(),this._seq=0}_collect(e){let n=[];for(let s of e){let i=this._entries.get(s);i&&n.push(i)}return n.sort((s,i)=>s.seq-i.seq),n.map(s=>({id:s.id,box:s.box}))}};function Ha(t,e){let n=t.x-e.x,s=t.y-e.y,i=t.hw+e.hw-Math.abs(n),r=t.hh+e.hh-Math.abs(s);return i<=1e-9||r<=1e-9?ou():i0?e.fixedStep:1/120;return{gx:n.x||0,gy:n.y||0,fixedStep:s}}function Xa(t,e,n,s){t.vx+=e*s,t.vy+=n*s,t.px+=t.vx*s,t.py+=t.vy*s}function ru(t,e,n){let{gx:s,gy:i,fixedStep:r}=Ka(n),a={px:t.px,py:t.py,vx:t.vx,vy:t.vy},o=e>0?e:0;for(;o>=r-1e-12;)Xa(a,s,i,r),o-=r;return o>1e-12&&Xa(a,s,i,o),a}var hi=class{constructor(e,n){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy};let s=Ka(n);this._gx=s.gx,this._gy=s.gy,this._fixedStep=s.fixedStep}get state(){return{px:this._s.px,py:this._s.py,vx:this._s.vx,vy:this._s.vy}}step(e){let n=ru(this._s,e,{gravity:{x:this._gx,y:this._gy},fixedStep:this._fixedStep});return this._s=n,this.state}reset(e){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy}}};function Qa(t,e,n,s){let i=n.mass==null?1:n.mass,r=n.stiffness,a=n.damping,o=t.x,c=t.v,l=s>0?s:0;if(l<=1e-12)return{x:o,v:c};let u=i>1e-12?i:1e-12,h=Math.sqrt(Math.max(0,r)/u),d=a/u,f=h>1e-12?.2/h:l,p=d>1e-12?.5/d:l,y=Math.max(1e-12,Math.min(f,p)),x=Math.ceil(l/y);(!Number.isFinite(x)||x<1)&&(x=1),x>4096&&(x=4096);let w=l/x;for(let A=0;A1?1:t}var cu=t=>(t=qe(t),t*t),lu=t=>(t=qe(t),1-(1-t)*(1-t)),uu=t=>(t=qe(t),t<.5?2*t*t:1-Math.pow(-2*t+2,2)/2),du=t=>(t=qe(t),t*t*t),fu=t=>{t=qe(t);let e=1-t;return 1-e*e*e},hu=t=>(t=qe(t),t<.5?4*t*t*t:1-Math.pow(-2*t+2,3)/2),tc=2*Math.PI/3,ec=2*Math.PI/4.5,pu=t=>(t=qe(t),t===0?0:t===1?1:-Math.pow(2,10*t-10)*Math.sin((t*10-10.75)*tc)),mu=t=>(t=qe(t),t===0?0:t===1?1:Math.pow(2,-10*t)*Math.sin((t*10-.75)*tc)+1),yu=t=>(t=qe(t),t===0?0:t===1?1:t<.5?-(Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*ec))/2:Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*ec)/2+1),yi=1.70158,pi=yi*1.525,nc=yi+1,gu=t=>(t=qe(t),nc*t*t*t-yi*t*t),bu=t=>{t=qe(t);let e=t-1;return 1+nc*e*e*e+yi*e*e},xu=t=>(t=qe(t),t<.5?Math.pow(2*t,2)*((pi+1)*2*t-pi)/2:(Math.pow(2*t-2,2)*((pi+1)*(t*2-2)+pi)+2)/2),Su=t=>qe(t),Ro=Object.freeze({linear:Su,quadIn:cu,quadOut:lu,quadInOut:uu,cubicIn:du,cubicOut:fu,cubicInOut:hu,elasticIn:pu,elasticOut:mu,elasticInOut:yu,backIn:gu,backOut:bu,backInOut:xu}),Mo=Ro,vu=["linear","quadIn","quadOut","quadInOut","cubicIn","cubicOut","cubicInOut","elasticIn","elasticOut","elasticInOut","backIn","backOut","backInOut"];function wu(t){let e=t&&t.easing;if(!e)return Ro;let n=i=>typeof e[i]=="function"?r=>e[i](qe(r)):Ro[i],s={};for(let i of vu)s[i]=n(i);return Object.freeze(s)}var Po=class{constructor(e,n,s){let i=s||{};this._time=n,this._windowMs=typeof i.windowMs=="number"&&i.windowMs>0?i.windowMs:120;let r=Array.isArray(i.types)&&i.types.length>0?i.types:au;this._records=new Map,this._subs=[],this._disposed=!1;for(let a of r){this._records.set(a,null);let o=e.on(a,c=>{this._records.set(a,c.tMs)});this._subs.push(o)}}consume(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs?(this._records.set(e,null),!0):(this._records.set(e,null),!1)}peek(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs}clear(){for(let e of this._records.keys())this._records.set(e,null)}dispose(){if(!this._disposed){for(let e of this._subs)try{e.cancel()}catch(n){}this._subs=[],this._disposed=!0}}};var mi=class{constructor(e,n){let s=n||{};this._time=e,this._windowMs=typeof s.windowMs=="number"&&s.windowMs>0?s.windowMs:500,this._maxCount=typeof s.maxCount=="number"&&s.maxCount>0?s.maxCount:1/0,this._count=0,this._lastHitAt=null}hit(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt!=null&&n-this._lastHitAt<=this._windowMs&&this._count>0?this._count=Math.min(this._count+1,this._maxCount):this._count=1,this._lastHitAt=n,this._count}getCount(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt==null||n-this._lastHitAt>this._windowMs?0:this._count}reset(){this._count=0,this._lastHitAt=null}};function sc(t){let e=t||{},n=null,s=null,i=!1;return{name:"gamefeel",version:"1.0.0",dependencies:[],get inputBuffer(){return n},get easing(){return wu(s)},init(a){let o=a.getInput();n=new Po(o,a.time,{windowMs:e.inputBufferMs,types:e.inputTypes});let c=a.getEngine();s=c?c.math:null},dispose(){i||(n&&(n.dispose(),n=null),s=null,i=!0)}}}function gi(t,e){let n=e<0?0:e>1?1:e;switch(t&&t.kind){case"constant":return t.value;case"linear":return t.from+(t.to-t.from)*n;case"easeInOut":{let s=n*n*(3-2*n);return t.from+(t.to-t.from)*s}case"decay":{let s=t.power==null?2:t.power,i=Math.pow(1-n,s);return t.to+(t.from-t.to)*i}default:return 0}}var Tu=Object.freeze({burst:Object.freeze({mode:"burst",count:24,angle:0,spread:Math.PI,speedMin:80,speedMax:160,lifeMin:.4,lifeMax:.8,gravity:0,drag:0,sizeCurve:{kind:"decay",from:6,to:0,power:1.5},alphaCurve:{kind:"linear",from:1,to:0}}),trail:Object.freeze({mode:"continuous",rate:60,angle:Math.PI,spread:.25,speedMin:20,speedMax:50,lifeMin:.2,lifeMax:.5,gravity:0,drag:1.5,sizeCurve:{kind:"easeInOut",from:4,to:0},alphaCurve:{kind:"decay",from:.8,to:0,power:2}}),drift:Object.freeze({mode:"continuous",rate:12,angle:Math.PI/2,spread:.6,speedMin:10,speedMax:30,lifeMin:1.5,lifeMax:3,gravity:8,drag:.5,sizeCurve:{kind:"constant",value:3},alphaCurve:{kind:"decay",from:.7,to:0,power:1}})});function Au(t){let e=Tu[t];return e?Lo(e):null}function Lo(t){let e={};for(let n of Object.keys(t)){let s=t[n];e[n]=s&&typeof s=="object"?Lo(s):s}return e}function ku(t,e,n){let s=t.mode==="continuous";return{pos:{x:e,y:n},angle:t.angle,coneAngle:t.spread,emitSize:0,emitTime:s?0:1/60,emitRate:s?t.rate||0:void 0,count:s?void 0:t.count||0,particleTime:(t.lifeMin+t.lifeMax)/2,speed:(t.speedMin+t.speedMax)/2,gravityScale:t.gravity||0,damping:t.drag!=null?1-t.drag/60:1,sizeStart:gi(t.sizeCurve,0),sizeEnd:gi(t.sizeCurve,1),colorStart:{r:1,g:1,b:1,a:gi(t.alphaCurve,0)},colorEnd:{r:1,g:1,b:1,a:gi(t.alphaCurve,1)},additive:!1}}function bi(t){let e=t||{},n=null,s=null,i=null,r=new Map,a=0,o={isActive(){return!1},stop(){}},c=0,l=1,u=0,h=0,d=0,f={x:0,y:0,remain:0,dur:0,amplitude:0,frequency:0,_phase:0},p={alpha:0,remain:0,dur:0,peak:0},y={scale:1,remain:0,dur:0,amplitude:0,frequency:0},x=!1;function w(k){if(u>0)if(u-=k,u<=0)u=0,l=1;else{let C=h>0?1-u/h:1;l=d+(1-d)*C}if(f.remain>0)if(f.remain-=k,f.remain<=0)f.remain=0,f.x=0,f.y=0;else{let C=f.remain/f.dur,L=f.amplitude*C;f._phase+=f.frequency*k*Math.PI*2,f.x=Math.sin(f._phase)*L,f.y=Math.cos(f._phase*1.3)*L}if(p.remain>0&&(p.remain-=k,p.remain<=0?(p.remain=0,p.alpha=0):p.alpha=p.peak*(p.remain/p.dur)),y.remain>0)if(y.remain-=k,y.remain<=0)y.remain=0,y.scale=1;else{let C=y.remain/y.dur,L=(1-C)*y.frequency*Math.PI*2;y.scale=1+Math.sin(L)*y.amplitude*C}}function A(k){c+=1,w(k)}function S(k){let C=k!==void 0?k:n?n.getContext2d():null;if(C&&p.alpha>0){C.globalAlpha=p.alpha,C.fillStyle="#ffffff";let L=C.canvas?C.canvas.width:0,V=C.canvas?C.canvas.height:0;C.fillRect(0,0,L,V),C.globalAlpha=1}}return{name:"particles-juice",version:"1.0.0",dependencies:[],init(k){var C;n=k,i=((C=k.getEngine())==null?void 0:C.particles)||null,typeof e.seed=="number"&&k.random.reseed(e.seed),e.autoStep!==!1&&(s=k.onFrame(L=>{A(L)}))},dispose(){x||(s&&(s.cancel(),s=null),r.forEach(k=>{try{k.stop()}catch{}}),r.clear(),l=1,u=0,f.remain=0,f.x=0,f.y=0,p.remain=0,p.alpha=0,y.remain=0,y.scale=1,x=!0)},spawnEmitter(k,C,L,V){let ce=typeof k=="string"?Au(k):Lo(k);if(!ce)return-1;V&&(ce=Object.assign(ce,V));let ne=a++;if(!i)return r.set(ne,o),ne;let T=i.spawnEmitter(ku(ce,C,L));return r.set(ne,T),ne},stopEmitter(k){let C=r.get(k);if(C)try{C.stop()}catch{}},step(k){A(k)},render(k){S(k)},particleCount(){return 0},emitterCount(){let k=0;for(let C of r.values())C.isActive()&&(k+=1);return k},hitStop(k,C){h=Math.max(0,k),u=h,d=C==null?0:Math.max(0,Math.min(1,C)),l=h>0?d:1},getTimeScale(){return l},shakeScreen(k,C,L){f.dur=Math.max(0,k),f.remain=f.dur,f.amplitude=Math.max(0,C),f.frequency=L==null?30:L,f._phase=0,f.x=0,f.y=0},getShakeOffset(){return{x:f.x,y:f.y}},flashScreen(k,C){p.dur=Math.max(0,k),p.remain=p.dur,p.peak=C==null?.8:Math.max(0,Math.min(1,C)),p.alpha=p.dur>0?p.peak:0},getFlashAlpha(){return p.alpha},pulseScale(k,C,L){y.dur=Math.max(0,k),y.remain=y.dur,y.amplitude=C==null?.2:C,y.frequency=L==null?4:L,y.scale=1},getPulseScale(){return y.scale},juiceSnapshot(){return{timeScale:l,shake:{x:f.x,y:f.y},flashAlpha:p.alpha,pulseScale:y.scale}},probe(){return{particles:0,emitters:r.size,dropped:0,steps:c,disposed:x}}}}function ic(t){let e=Te(t.r)/255,n=Te(t.g)/255,s=Te(t.b)/255,i=Math.max(e,n,s),r=Math.min(e,n,s),a=(i+r)/2,o=0,c=0,l=i-r;return l>1e-12&&(c=a>.5?l/(2-i-r):l/(i+r),i===e?o=(n-s)/l%6:i===n?o=(s-e)/l+2:o=(e-n)/l+4,o*=60,o<0&&(o+=360)),{h:o,s:c,l:a}}function oc(t){let e=(t.h%360+360)%360,n=an(t.s),s=an(t.l);if(n<1e-12){let o=Math.round(s*255);return{r:o,g:o,b:o}}let i=s<.5?s*(1+n):s+n-s*n,r=2*s-i,a=e/360;return{r:Math.round(Oo(r,i,a+1/3)*255),g:Math.round(Oo(r,i,a)*255),b:Math.round(Oo(r,i,a-1/3)*255)}}function Oo(t,e,n){let s=n;return s<0&&(s+=1),s>1&&(s-=1),s<1/6?t+(e-t)*6*s:s<1/2?e:s<2/3?t+(e-t)*(2/3-s)*6:t}function Te(t){return t<0?0:t>255?255:t}function an(t){return t<0?0:t>1?1:t}function Go(t,e){let n=_u(t.from,e);if(n>=0&&n({r:Te(o.r),g:Te(o.g),b:Te(o.b)})),to:r}}function Do(t,e,n){return t+(e-t)*n}function jo(t,e){let n=ic(t),s=n.h+(e.hue||0),i=an(n.s*(e.sat==null?1:e.sat)),r=an(n.l*(e.light==null?1:e.light));return oc({h:s,s:i,l:r})}var Ru=Object.freeze([Object.freeze([0,8,2,10]),Object.freeze([12,4,14,6]),Object.freeze([3,11,1,9]),Object.freeze([15,7,13,5])]);function rc(t){let e=t||{},n=null,s=!1,i={vignette:{enabled:Io(e.vignette&&e.vignette.enabled,!1),strength:Fo(e.vignette&&e.vignette.strength,.5)},dither:{enabled:Io(e.dither&&e.dither.enabled,!1),strength:Fo(e.dither&&e.dither.strength,.5)},scanline:{enabled:Io(e.scanline&&e.scanline.enabled,!1),strength:Fo(e.scanline&&e.scanline.strength,.5)}};function r(o){let c=o!==void 0?o:n?n.getContext2d():null;if(!c)return;let l=c.canvas?c.canvas.width:0,u=c.canvas?c.canvas.height:0;if(i.vignette.enabled&&i.vignette.strength>0&&l>0&&u>0){let h=c.createRadialGradient(l/2,u/2,Math.min(l,u)*.25,l/2,u/2,Math.max(l,u)*.75);h.addColorStop(0,"rgba(0,0,0,0)"),h.addColorStop(1,"rgba(0,0,0,"+i.vignette.strength.toFixed(3)+")"),c.fillStyle=h,c.fillRect(0,0,l,u)}if(i.scanline.enabled&&i.scanline.strength>0&&l>0&&u>0){c.fillStyle="rgba(0,0,0,"+(i.scanline.strength*.5).toFixed(3)+")";for(let h=0;h0&&l>0&&u>0&&typeof c.getImageData=="function"&&typeof c.putImageData=="function"){let h=c.getImageData(0,0,l,u);Pu(h,i.dither.strength),c.putImageData(h,0,0)}}return{name:"palette-post",version:"1.0.0",dependencies:[],init(o){n=o},dispose(){s||(n=null,s=!0)},applyPaletteMap(o,c){return Go(o,c)},applyPaletteMapToBuffer(o,c){return Cu(o,c)},lerpPaletteMap(o,c,l){return Bo(o,c,l)},shiftHsl(o,c){return jo(o,c)},rgbToHsl(o){return ic(o)},hslToRgb(o){return oc(o)},setPost(o){if(o)for(let c of["vignette","dither","scanline"])o[c]&&(typeof o[c].enabled=="boolean"&&(i[c].enabled=o[c].enabled),typeof o[c].strength=="number"&&(i[c].strength=an(o[c].strength)))},getPost(){return{vignette:{enabled:i.vignette.enabled,strength:i.vignette.strength},dither:{enabled:i.dither.enabled,strength:i.dither.strength},scanline:{enabled:i.scanline.enabled,strength:i.scanline.strength}}},renderPost(o){r(o)},probe(){return{disposed:s,post:this.getPost()}}}}function Pu(t,e){let n=an(e);if(n<=0)return t;let{data:s,width:i}=t,a=255/(Math.max(2,Math.round(16-n*14))-1);for(let o=0;o+3>2)%i,l=Math.floor((o>>2)/i),u=(Ru[l&3][c&3]/16-.5)*a;for(let h=0;h<3;h++){let d=s[o+h]+u,f=Math.round(d/a)*a;s[o+h]=f<0?0:f>255?255:f}}return t}function Io(t,e){return typeof t=="boolean"?t:e}function Fo(t,e){return typeof t=="number"?an(t):e}var No=Object.freeze({blip:Object.freeze({name:"blip",params:Object.freeze([.6,0,880,0,.03,.06,1,1.5])}),thud:Object.freeze({name:"thud",params:Object.freeze([.8,0,90,0,.04,.18,0,1,0,0,0,0,0,4])}),chime:Object.freeze({name:"chime",params:Object.freeze([.5,0,660,.02,.12,.3,1,2])})}),ac=Object.keys(No);function Mu(t){let e=[];return t==null||typeof t!="object"?{ok:!1,errors:["song \u5FC5\u987B\u662F\u5BF9\u8C61"]}:(!Array.isArray(t.instruments)||t.instruments.length===0?e.push("instruments \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.instruments.forEach((n,s)=>{(!Array.isArray(n)||n.some(i=>typeof i!="number"||!Number.isFinite(i)))&&e.push(`instruments[${s}] \u5FC5\u987B\u662F\u6709\u9650\u6570\u5B57\u6570\u7EC4\uFF08ZzFX \u53C2\u6570\u5305\uFF09`)}),!Array.isArray(t.patterns)||t.patterns.length===0?e.push("patterns \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.patterns.forEach((n,s)=>{if(!Array.isArray(n)||n.length===0){e.push(`patterns[${s}] \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF08\u81F3\u5C11\u4E00\u4E2A\u58F0\u90E8\u901A\u9053\uFF09`);return}n.forEach((i,r)=>{if(!Array.isArray(i)||i.length<2){e.push(`patterns[${s}][${r}] \u901A\u9053\u81F3\u5C11\u542B [\u4E50\u5668\u7D22\u5F15, \u58F0\u50CF]`);return}if(i.some(c=>typeof c!="number"||!Number.isFinite(c))){e.push(`patterns[${s}][${r}] \u901A\u9053\u5FC5\u987B\u5168\u4E3A\u6709\u9650\u6570\u5B57`);return}let a=i[0]|0;Array.isArray(t.instruments)&&(a<0||a>=t.instruments.length)&&e.push(`patterns[${s}][${r}] \u4E50\u5668\u7D22\u5F15 ${a} \u8D8A\u754C\uFF08instruments \u957F\u5EA6 ${t.instruments.length}\uFF09`);let o=i[1];(o<-1||o>1)&&e.push(`patterns[${s}][${r}] \u58F0\u50CF ${o} \u8D8A\u754C\uFF08\u5E94 -1..+1\uFF09`)})}),!Array.isArray(t.sequence)||t.sequence.length===0?e.push("sequence \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.sequence.forEach((n,s)=>{if(typeof n!="number"||!Number.isInteger(n)){e.push(`sequence[${s}] \u5FC5\u987B\u662F\u6574\u6570 pattern \u7D22\u5F15`);return}Array.isArray(t.patterns)&&(n<0||n>=t.patterns.length)&&e.push(`sequence[${s}] \u7D22\u5F15 ${n} \u8D8A\u754C\uFF08patterns \u957F\u5EA6 ${t.patterns.length}\uFF09`)}),t.bpm!=null&&(typeof t.bpm!="number"||!(t.bpm>0))&&e.push("bpm \u5FC5\u987B\u662F\u6B63\u6570"),{ok:e.length===0,errors:e})}function Tt(t){return typeof t!="number"||Number.isNaN(t)||t<0?0:t>1?1:t}function Lu(t,e){switch(t){case"ease-in":return e*e;case"ease-out":return Math.sqrt(e);case"constant":return 1;default:return e}}function cc(t,e){let n=Tt(e);return t==null||!Array.isArray(t.voices)?[]:t.voices.map(s=>{let i=String(s&&s.id!=null?s.id:""),r=Array.isArray(s&&s.channelIndices)?s.channelIndices.slice():[],a=typeof s.minIntensity=="number"?Tt(s.minIntensity):0,o=typeof s.maxIntensity=="number"?Tt(s.maxIntensity):1,c=typeof s.volumeCurve=="string"?s.volumeCurve:"linear",l=typeof s.baseVolume=="number"?Tt(s.baseVolume):1;if(no)return{id:i,on:!1,volume:0,channelIndices:r};let u=o-a,h=u<=0?1:(n-a)/u,d=Tt(Lu(c,h)*l);return{id:i,on:!0,volume:d,channelIndices:r}})}function lc(t,e,n,s){try{let i=e[0]||[],r=e[1]||i,a=Math.max(i.length,r.length);if(a===0)return null;let c=t.createBuffer(2,a,44100);c.getChannelData(0).set(i),c.getChannelData(1).set(r.length?r:i);let l=t.createBufferSource();l.buffer=c,l.loop=!!s;let u=t.createGain();return u.gain.value=Tt(n*.3),l.connect(u),u.connect(t.destination),l.start(),{stop(){try{l.stop()}catch(h){}try{l.disconnect(),u.disconnect()}catch(h){}}}}catch(i){return zo("[audio-music] \u53D7\u63A7\u97F3\u9891\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",i),null}}function uc(t){let e=t||{},n=typeof e.masterVolume=="number"?Tt(e.masterVolume):1,s=()=>null,i=null,r=null,a={voices:[]},o=1,c=null,l=!1,u=0,h=!1,d=!1;function f(){let S=s();return S==null?(u+=1,h||(Jo("[audio-music] \u65E0\u53D7\u63A7\u97F3\u9891\u4E0A\u4E0B\u6587\uFF08getAudioContext \u8FD4\u56DE null\uFF09\uFF0C\u5168\u90E8\u53D1\u58F0\u9759\u9ED8 no-op\uFF08\u8BC4\u4F30\u73AF\u5883\u65E0\u58F0\u5361\u65F6\u7684\u5BB9\u9519\u964D\u7EA7\uFF09"),h=!0),null):S}function p(){if(!r||!i)return null;try{let S=typeof r.bpm=="number"&&r.bpm>0?r.bpm:125;return i.synthSong(r.instruments,r.patterns,r.sequence,S)}catch(S){return zo("[audio-music] \u66F2\u8C31\u6E32\u67D3\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",S),null}}function y(){let S=cc(a,o);if(S.length===0)return 1;let _=0;for(let k of S)k.on&&(_=Math.max(_,k.volume));return _}function x(S,_){typeof _=="number"&&(o=Tt(_));let k=f();if(k==null||!r)return;w();let C=p();if(!C)return;let L=Tt(n*y());c=lc(k,C,L,S),l=!!S&&c!=null}function w(){c&&(c.stop(),c=null),l=!1}return{name:"audio-music",version:"1.0.0",dependencies:[],init(S){s=()=>S.getAudioContext();let _=S.getEngine&&S.getEngine();i=_?_.audio.synth:null},dispose(){d||(w(),d=!0)},loadSong(S){let _=Mu(S);return _.ok?r={instruments:S.instruments,patterns:S.patterns,sequence:S.sequence,bpm:typeof S.bpm=="number"?S.bpm:125}:Jo("[audio-music] \u66F2\u8C31\u6821\u9A8C\u5931\u8D25\uFF0C\u672A\u8F7D\u5165\uFF1A"+_.errors.join("\uFF1B")),_},play(S){x(!1,S)},stop(){w()},loop(S){x(!0,S)},setIntensityLayering(S){a=S&&Array.isArray(S.voices)?{voices:S.voices}:{voices:[]}},setIntensity(S){o=Tt(S)},resolveVoices(S){return cc(a,S)},playSfx(S){let _=No[S];if(!_){Jo("[audio-music] \u672A\u77E5\u97F3\u6548\u9884\u8BBE\uFF1A"+String(S));return}let k=f();if(k!=null)try{let C=i?i.synthSfx(_.params):null;if(!C)return;lc(k,[C,C],n,!1)}catch(C){zo("[audio-music] \u97F3\u6548\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8 name="+S,C)}},getPreset(S){return No[S]},listPresets(){return ac.slice()},probe(){return{hasAudio:s()!=null,hasSong:r!=null,intensity:o,voiceCount:a.voices.length,looping:l,silentNoops:u,presetCount:ac.length}}}}function zo(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Jo(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Ou="zaomeng.save";function Du(t){if(typeof TextEncoder!="undefined")return new TextEncoder().encode(t).length;if(typeof Buffer!="undefined"&&typeof Buffer.byteLength=="function")return Buffer.byteLength(t,"utf8");let e=0;for(let n=0;n=55296&&s<=56319?(e+=4,n++):e+=3}return e}function Vo(){let t=new Map;return{getItem(e){return t.has(e)?t.get(e):null},setItem(e,n){t.set(e,n)},removeItem(e){t.delete(e)},keys(){return Array.from(t.keys())}}}function dc(){if(typeof localStorage=="undefined")throw new Error("[save-progress] createLocalStorageAdapter \u9700\u8981\u5168\u5C40 localStorage\uFF08\u4EC5\u6D4F\u89C8\u5668\u96C6\u6210\u6BB5\u53EF\u7528\uFF09\u3002node/host-dev \u8BF7\u7528\u7F3A\u7701\u5185\u5B58 adapter \u6216 createMemoryAdapter()\u3002");return{getItem(t){return localStorage.getItem(t)},setItem(t,e){localStorage.setItem(t,e)},removeItem(t){localStorage.removeItem(t)},keys(){let t=[];for(let e=0;e0?e.namespace:Ou;if(n.indexOf(":")>=0)throw new Error('[save-progress] namespace \u4E0D\u5F97\u542B\u5206\u9694\u7B26 ":"\uFF08\u5F53\u524D="'+n+'"\uFF09');let s=typeof e.maxValueBytes=="number"&&e.maxValueBytes>0?Math.floor(e.maxValueBytes):32768,i=!Iu(e.adapter),r=i?Vo():e.adapter,a=n+":",o=0,c=0,l=!1;function u(f){return typeof f!="string"||f.length===0?a+String(f):a+f}function h(){try{let f=r.keys();return Array.isArray(f)?f.filter(p=>typeof p=="string"&&p.indexOf(a)===0):[]}catch(f){return Ts("[save-progress] adapter.keys() \u5F02\u5E38\uFF0C\u964D\u7EA7\u8FD4\u56DE\u7A7A\u96C6",f),[]}}return{name:"save-progress",version:"1.0.0",dependencies:[],init(f){h()},dispose(){},get(f,p){if(!Uo(f))return p;let y;try{y=r.getItem(u(f))}catch(x){return Ts("[save-progress] adapter.getItem \u5F02\u5E38\uFF0C\u8FD4\u56DE\u9ED8\u8BA4\u503C key="+f,x),p}if(y==null)return p;try{return JSON.parse(y)}catch{return o+=1,l||(As("[save-progress] \u68C0\u6D4B\u5230\u635F\u574F\u5B58\u6863\uFF08\u975E\u6CD5 JSON\uFF09\uFF0C\u5DF2\u5BB9\u9519\u56DE\u9000\u9ED8\u8BA4\u503C key="+f),l=!0),p}},set(f,p){if(!Uo(f))return As("[save-progress] set \u6536\u5230\u975E\u6CD5 key\uFF0C\u62D2\u7EDD\u5199\u5165\uFF1A"+String(f)),!1;let y;try{y=JSON.stringify(p)}catch{return c+=1,As("[save-progress] \u503C\u4E0D\u53EF JSON \u5E8F\u5217\u5316\uFF08\u5FAA\u73AF\u5F15\u7528?\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+f),!1}if(y===void 0)return c+=1,As("[save-progress] \u503C\u5E8F\u5217\u5316\u4E3A undefined\uFF08\u5982\u7EAF undefined/\u51FD\u6570\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+f),!1;let x=Du(y);if(x>s)return c+=1,As("[save-progress] \u503C\u8D85\u5B57\u8282\u4E0A\u9650\u62D2\u7EDD\u5199\u5165 key="+f+"\uFF08"+x+" > "+s+" bytes\uFF09"),!1;try{return r.setItem(u(f),y),!0}catch(w){return c+=1,Ts("[save-progress] adapter.setItem \u5F02\u5E38\uFF0C\u5199\u5165\u5931\u8D25 key="+f,w),!1}},remove(f){if(Uo(f))try{r.removeItem(u(f))}catch(p){Ts("[save-progress] adapter.removeItem \u5F02\u5E38\uFF08\u5DF2\u5FFD\u7565\uFF09key="+f,p)}},clear(){let f=h(),p=0;for(let y of f)try{r.removeItem(y),p+=1}catch(x){Ts("[save-progress] clear \u65F6 removeItem \u5F02\u5E38\uFF08\u5DF2\u8DF3\u8FC7\uFF09fullKey="+y,x)}return p},probe(){return{namespace:n,maxValueBytes:s,usingMemoryAdapter:i,size:h().length,corruptRecoveries:o,rejectedWrites:c}}}}function Uo(t){return typeof t=="string"&&t.length>0}function Iu(t){return!!t&&typeof t.getItem=="function"&&typeof t.setItem=="function"&&typeof t.removeItem=="function"&&typeof t.keys=="function"}function Ts(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function As(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Zn=[{id:"soda",name:"\u6C7D\u6C34",wholesale:20,basePrice:40,popularity:1,initial:!0},{id:"snack",name:"\u8FA3\u6761",wholesale:10,basePrice:25,popularity:1.2,initial:!0},{id:"bread",name:"\u9762\u5305",wholesale:30,basePrice:60,popularity:.8,initial:!0},{id:"ice",name:"\u51B0\u6DC7\u6DCB",wholesale:40,basePrice:90,popularity:.7,initial:!1},{id:"toy",name:"\u5C0F\u73A9\u5177",wholesale:80,basePrice:180,popularity:.35,initial:!1}];function He(t){return Zn.find(e=>e.id===t)}var Ee={lengthSec:96,rushStartSec:30,rushEndSec:66,rushRampSec:3,daysPerSegment:3};function hc(t){let{rushStartSec:e,rushEndSec:n,rushRampSec:s}=Ee;return t<=e-s||t>=n+s?0:t>=e&&t<=n?1:te.id===t)}function Ho(t){let e=n=>!!t[n];return{shelfCap:e("shelf2")?48:e("shelf1")?34:24,serveCooldownSec:e("speed2")?.32:e("speed1")?.42:.55,patienceMul:e("decor2")?1.3:e("decor1")?1.15:1,settleRepBonusTenth:e("decor2")?60:e("decor1")?30:0,flowMul:e("decor2")?1.12:1}}function Si(t){let e=t.priceMul,n=t.reputation==null?$e.start:t.reputation,s=t.serveCapacity==null?26:t.serveCapacity,i=t.stockUnits==null?1/0:t.stockUnits,r=t.segment==null?1:t.segment,a=t.unlocked||Zn.filter(x=>x.initial).map(x=>x.id),l=((Ee.lengthSec-(Ee.rushEndSec-Ee.rushStartSec))/cn.idleIntervalSec+(Ee.rushEndSec-Ee.rushStartSec)/cn.rushIntervalSec)*Wo(e)*qo(n),u=Math.min(l,s,i),h=a.map(x=>He(x)).filter(Boolean),d=h.reduce((x,w)=>x+w.popularity,0),f=h.reduce((x,w)=>x+(Math.round(w.basePrice*e)-w.wholesale)*(w.popularity/d),0),p=Math.round(u*f),y=oe.rentBaseJiao+(r-1)*oe.rentPerSegmentJiao;return{arrivals:l,served:u,grossJiao:p,rentJiao:y,profitJiao:p-y}}function je(t,e,n){return tn?n:t}function Ye(t){let e=t/10;return Number.isInteger(e)?String(e):e.toFixed(1)}var yc=1,Fu=2600;function ks(t){let e=t.random;if(!e||typeof e.next!="function")throw new Error("[shop-core] \u5FC5\u987B\u6CE8\u5165\u53D7\u63A7\u968F\u673A\u6E90 random\uFF08next/range/reseed\uFF09");let n=0,s={nowMs:()=>n,elapsedMs:()=>n},i=new mi(s,{windowMs:Fu,maxCount:99}),r=[];function a(T,P){r.push(Object.assign({type:T,tMs:Math.round(n)},P||{}))}let o={phase:"title",day:1,cash:oe.startCashJiao,repTenth:$e.start*10,priceMul:1,stock:{},unlocked:Zn.filter(T=>T.initial).map(T=>T.id),upgrades:{},customers:[],dayTimeSec:0,rushFactor:0,serveCooldown:0,comboCount:0,prepBought:{},today:c(),lifetime:{days:0,served:0,angry:0,netJiao:0,upgradesBought:0},settle:null,summary:null,gameoverReason:null};function c(){return{revenueJiao:0,soldCostJiao:0,served:0,angry:0,stockout:0,walkaway:0,rescued:0,bigSales:0,maxCombo:0}}let l=1,u=0,h=!1,d=Ho(o.upgrades);function f(){d=Ho(o.upgrades)}function p(){let T=0;for(let P of Object.keys(o.stock))T+=o.stock[P];return T}function y(){return o.repTenth/10}function x(T){o.repTenth=je(o.repTenth+T,0,$e.max*10)}function w(T){let P=o.phase;o.phase=T,a("phase_changed",{from:P,to:T})}function A(T){o.day=T,o.prepBought={},o.today=c(),o.customers=[],o.dayTimeSec=0,o.rushFactor=0,o.settle=null,o.summary=null,w("prep"),a("save_point",{})}function S(){let T=o.rushFactor>.5?cn.rushIntervalSec:cn.idleIntervalSec,P=Wo(o.priceMul)*qo(y())*d.flowMul;u=T/Math.max(P,.05)*e.range(cn.jitterMin,cn.jitterMax)}function _(){let T=o.unlocked.map(M=>He(M)),P=T.reduce((M,j)=>M+j.popularity,0),R=e.next()*P;for(let M of T)if(R-=M.popularity,R<=0)return M.id;return T[T.length-1].id}function k(){for(let T=0;TP.slot===T))return T;return-1}function C(){let T=_(),P=k();if(P<0){o.today.walkaway+=1,a("walkaway_full",{productId:T});return}let M=(o.rushFactor>.5?Cn.rushSec:Cn.idleSec)*d.patienceMul*e.range(.9,1.12),j={id:l++,productId:T,slot:P,mood:"queue",patienceSec:M,patienceMaxSec:M,timerSec:0,avatar:Math.floor(e.next()*4)%4,impatientFired:!1};(o.stock[T]||0)<=0&&(j.mood="stockout",j.timerSec=Cn.stockoutLingerSec),o.customers.push(j),a("customer_arrive",{id:j.id,slot:P,productId:T,mood:j.mood})}function L(T){let P=o.customers.indexOf(T);P>=0&&o.customers.splice(P,1)}function V(T){o.dayTimeSec+=T,o.rushFactor=hc(o.dayTimeSec);let P=o.rushFactor>.5;if(P!==h&&(a(P?"rush_start":"rush_end",{}),h=P),o.serveCooldown>0&&(o.serveCooldown=Math.max(0,o.serveCooldown-T)),o.dayTimeSec>=Ee.lengthSec){a("closing",{}),o.customers=[],ce();return}u-=T,u<=0&&(C(),S());for(let R=o.customers.length-1;R>=0;R--){let M=o.customers[R];if(M.mood==="queue"){if((o.stock[M.productId]||0)<=0){M.mood="stockout",M.timerSec=Cn.stockoutLingerSec;continue}M.patienceSec-=T,!M.impatientFired&&M.patienceSec/M.patienceMaxSec<=Cn.impatientRatio&&(M.impatientFired=!0,a("customer_impatient",{id:M.id,slot:M.slot})),M.patienceSec<=0&&(M.mood="leaving",M.timerSec=Cn.graceSec,a("customer_grace",{id:M.id,slot:M.slot}))}else M.mood==="leaving"?(M.timerSec-=T,M.timerSec<=0&&(L(M),o.today.angry+=1,x(-$e.angryLossTenth),a("angry_leave",{id:M.id,slot:M.slot,avatar:M.avatar,productId:M.productId,repLossTenth:$e.angryLossTenth}))):M.mood==="stockout"&&(M.timerSec-=T,M.timerSec<=0&&(L(M),o.today.stockout+=1,x(-$e.stockoutLossTenth),a("stockout_leave",{id:M.id,slot:M.slot,avatar:M.avatar,productId:M.productId,repLossTenth:$e.stockoutLossTenth})))}o.comboCount=i.getCount(n)}function ce(){let T=o.today,P=Math.ceil(o.day/Ee.daysPerSegment),R=oe.rentBaseJiao+(P-1)*oe.rentPerSegmentJiao,M=0;y()<$e.fineThreshold&&(M=oe.fineBaseJiao+T.angry*oe.finePerAngryJiao,a("fined",{fineJiao:M}));let j=d.settleRepBonusTenth;T.angry===0&&(j+=$e.noAngryBonusTenth),x(j),o.cash-=R+M;let se=T.revenueJiao-T.soldCostJiao-R-M;if(o.lifetime.days+=1,o.lifetime.netJiao+=se,o.settle={day:o.day,revenueJiao:T.revenueJiao,soldCostJiao:T.soldCostJiao,rentJiao:R,fineJiao:M,netJiao:se,served:T.served,angry:T.angry,stockout:T.stockout,walkaway:T.walkaway,rescued:T.rescued,maxCombo:T.maxCombo,repBackTenth:j,reputation:y()},a("day_end",{settle:o.settle}),y()<=0){o.gameoverReason="reputation",w("gameover"),a("gameover",{reason:"reputation"});return}if(o.cash<0){o.gameoverReason="bankrupt",w("gameover"),a("gameover",{reason:"bankrupt"});return}w("settle")}let ne={state:o,timeSource:s,update(T){let P=Math.max(0,Math.min(T,.1));n+=P*1e3,o.phase==="open"&&V(P)},drainEvents(){let T=r;return r=[],T},startGame(T){return T&&ne.restoreFromSave(T)?{ok:!0,continued:!0}:(o.cash=oe.startCashJiao,o.repTenth=$e.start*10,o.priceMul=1,o.stock={},o.unlocked=Zn.filter(P=>P.initial).map(P=>P.id),o.upgrades={},o.lifetime={days:0,served:0,angry:0,netJiao:0,upgradesBought:0},o.gameoverReason=null,f(),i.reset(),a("game_start",{continued:!1}),A(1),{ok:!0,continued:!1})},buyStock(T,P){let R=Math.max(1,Math.floor(P||1));if(o.phase!=="prep")return{ok:!1,reason:"phase"};let M=He(T);if(!M||!o.unlocked.includes(T))return{ok:!1,reason:"unknown_product"};if(p()+R>d.shelfCap)return{ok:!1,reason:"shelf_full"};let j=M.wholesale*R;return o.cash0)return{ok:!1,reason:"cooldown"};if(!o.unlocked.includes(T))return{ok:!1,reason:"unknown_product"};if((o.stock[T]||0)<=0)return a("tap_empty",{productId:T}),{ok:!1,reason:"no_stock"};let P=o.customers.filter(we=>we.productId===T&&(we.mood==="queue"||we.mood==="leaving")).sort((we,be)=>we.id-be.id)[0];if(!P)return a("tap_nocustomer",{productId:T}),{ok:!1,reason:"no_customer"};let R=P.mood==="leaving";o.stock[T]-=1;let M=i.hit(n);o.comboCount=M,o.today.maxCombo=Math.max(o.today.maxCombo,M);let j=Math.round(pc(T,o.priceMul)*mc(M));o.cash+=j,o.today.revenueJiao+=j,o.today.soldCostJiao+=He(T).wholesale,o.today.served+=1,o.lifetime.served+=1,R&&(o.today.rescued+=1),x($e.serveGainTenth+(R?$e.rescueBonusTenth:0)),o.serveCooldown=d.serveCooldownSec;let se=j>=oe.bigSaleJiao;return se&&(o.today.bigSales+=1),L(P),a("serve_ok",{id:P.id,slot:P.slot,avatar:P.avatar,productId:T,revenueJiao:j,combo:M,big:se,rescued:R}),{ok:!0,revenueJiao:j,combo:M,big:se,rescued:R,customerId:P.id}},confirmSettle(){if(o.phase!=="settle")return{ok:!1,reason:"phase"};let T=o.day;if(a("save_point",{}),T%Ee.daysPerSegment===0){let P=T/Ee.daysPerSegment;o.summary={segment:P,days:T,netJiao:o.lifetime.netJiao,served:o.lifetime.served,upgradesBought:o.lifetime.upgradesBought,reputation:y()},w("summary"),a("segment_end",{summary:o.summary})}else A(T+1);return{ok:!0}},confirmSummary(){return o.phase!=="summary"?{ok:!1,reason:"phase"}:(A(o.day+1),{ok:!0})},derived(){return d},reputation:y,totalStock:p,snapshotForSave(){return{v:yc,day:o.day,cash:o.cash,repTenth:o.repTenth,priceMul:o.priceMul,stock:Object.assign({},o.stock),unlocked:o.unlocked.slice(),upgrades:Object.assign({},o.upgrades),lifetime:Object.assign({},o.lifetime)}},restoreFromSave(T){return!T||T.v!==yc||typeof T.day!="number"||typeof T.cash!="number"||typeof T.repTenth!="number"||!T.unlocked||!Array.isArray(T.unlocked)||T.unlocked.length===0?!1:(o.cash=Math.floor(T.cash),o.repTenth=je(Math.floor(T.repTenth),0,$e.max*10),o.priceMul=je(T.priceMul||1,oe.priceMin,oe.priceMax),o.stock=Object.assign({},T.stock||{}),o.unlocked=T.unlocked.filter(P=>!!He(P)),o.upgrades=Object.assign({},T.upgrades||{}),o.lifetime=Object.assign({days:0,served:0,angry:0,netJiao:0,upgradesBought:0},T.lifetime||{}),o.gameoverReason=null,f(),i.reset(),a("game_start",{continued:!0}),A(Math.max(1,Math.floor(T.day))),!0)}};return ne}var Cs={open_shop:["\u5F00\u5F20\u55BD\u2014\u2014\u8857\u574A\u4EEC\u90FD\u7B49\u7740\u5462\uFF01","\u4ECA\u513F\u4E2A\u8FDB\u70B9\u5565\u597D\u8D27\uFF1F\u6211\u5FC3\u91CC\u6709\u6570\u3002","\u5C0F\u672C\u751F\u610F\uFF0C\u8D26\u53EF\u5F97\u7B97\u660E\u767D\u54AF\u3002"],day_start:["\u5F00\u95E8\u8FCE\u5BA2\uFF01\u90FD\u9EBB\u5229\u70B9\u513F~","\u54DF\uFF0C\u4ECA\u5929\u592A\u9633\u4E0D\u9519\uFF0C\u51C6\u662F\u4E2A\u597D\u65E5\u5B50\u3002"],idle_chat:["\u6162\u60A0\u60A0\u7684\u4E0B\u5348\uFF0C\u6700\u9002\u5408\u76D8\u8D26\u5566\u3002","\u9694\u58C1\u8001\u674E\u53C8\u6765\u8D4A\u8D26\uFF1F\u60F3\u5F97\u7F8E\u3002","\u8D27\u67B6\u64E6\u5F97\u9503\u4EAE\uFF0C\u770B\u7740\u5C31\u8212\u5766\u3002"],rush_start:["\u653E\u5B66\u5566\u653E\u5B66\u5566\uFF0C\u6253\u8D77\u7CBE\u795E\u6765\uFF01","\u4EBA\u90FD\u6D8C\u8FC7\u6765\u4E86\uFF0C\u624B\u4E0A\u522B\u505C\uFF01"],serve_ok:["\u597D\u561E\uFF0C\u62FF\u7A33\u5F53\uFF01","\u60A8\u6162\u8D70\uFF0C\u5E38\u6765\u554A~","\u8FD9\u5C31\u7ED9\u60A8\u62FF\uFF0C\u5FEB\u5F97\u5F88\uFF01"],combo_hot:["\u624B\u611F\u6765\u4E86\uFF0C\u8C01\u90FD\u522B\u62E6\u6211\uFF01","\u4E00\u4E2A\u63A5\u4E00\u4E2A\uFF0C\u8D8A\u5E72\u8D8A\u987A\u6E9C\uFF01"],big_sale:["\u54CE\u54DF\uFF0C\u5927\u4E3B\u987E\uFF01\u4ECA\u665A\u52A0\u4E2A\u9E21\u817F\uFF01","\u8FD9\u5355\u9876\u534A\u5929\u4E70\u5356\uFF0C\u7F8E\u6ECB\u6ECB~"],rescue:["\u522B\u8D70\u522B\u8D70\uFF0C\u8FD9\u5C31\u7ED9\u60A8\u62FF\u4E0A\uFF01","\u597D\u9669\u597D\u9669\uFF0C\u5DEE\u70B9\u513F\u9EC4\u4E86\u4E00\u5355\u3002"],angry:["\u54CE\u5440\uFF0C\u628A\u4EBA\u667E\u8DD1\u4E86\u2026\u2026\u5FC3\u75BC\u3002","\u7838\u62DB\u724C\u4E86\u7838\u62DB\u724C\u4E86\uFF0C\u5F97\u4E0A\u70B9\u5FC3\uFF01"],stockout:["\u7A7A\u8D27\u67B6\u6700\u6233\u5FC3\u7A9D\u5B50\uFF0C\u660E\u513F\u591A\u5907\u70B9\u3002","\u53C8\u5356\u65AD\u4E86\u2026\u2026\u662F\u597D\u4E8B\u4E5F\u662F\u574F\u4E8B\u3002"],settle_win:["\u4ECA\u513F\u8D26\u9762\u7EA2\u706B\uFF0C\u8BB0\u4E0A\u8BB0\u4E0A\uFF01","\u8F9B\u82E6\u4E00\u5929\uFF0C\u503C\u5F53\uFF01"],settle_lose:["\u8FD9\u8D26\u2026\u2026\u8D8A\u7B97\u8D8A\u5FC3\u51C9\u3002","\u7F5A\u5355\u90FD\u8D34\u8138\u4E0A\u4E86\uFF0C\u660E\u5929\u5F97\u6362\u4E2A\u6D3B\u6CD5\u3002"],upgrade:["\u820D\u4E0D\u5F97\u5B69\u5B50\u5957\u4E0D\u7740\u72FC\uFF0C\u5347\uFF01","\u9E1F\u67AA\u6362\u70AE\uFF0C\u54B1\u4E5F\u8BB2\u7A76\u4E00\u56DE\uFF01"],gameover:["\u5509\u2026\u2026\u5377\u5E18\u95E8\u4E00\u62C9\uFF0C\u4ECE\u5934\u518D\u6765\u5427\u3002"]},gp=Object.keys(Cs).length;function gc(t){let e={};return function(s){let i=Cs[s];if(!i||i.length===0)return"";if(i.length===1)return i[0];let r=Math.floor(t.next()*i.length)%i.length;return r===e[s]&&(r=(r+1)%i.length),e[s]=r,i[r]}}var _s={paper:{r:246,g:231,b:201},paperHi:{r:255,g:246,b:227},cream:{r:255,g:243,b:220},ink:{r:91,g:70,b:54},inkSoft:{r:138,g:108,b:84},wood:{r:169,g:118,b:79},woodDark:{r:124,g:84,b:55},gold:{r:232,g:169,b:66},coin:{r:246,g:196,b:83},amber:{r:240,g:196,b:117},brick:{r:201,g:111,b:74},danger:{r:178,g:72,b:54},leaf:{r:133,g:158,b:94},sky:{r:243,g:217,b:168},shadow:{r:62,g:49,b:40},scrim:{r:46,g:35,b:27},smoke:{r:140,g:106,b:85}},bc=Object.keys(_s);function xc(){let t=bc.map(a=>_s[a]),e={from:t,to:t.slice()},n={from:t,to:t.map(a=>jo(a,{hue:-10,sat:1.18,light:.9}))},s=0,i=r(0);function r(a){let o=Bo(e,n,a),c={};for(let l of bc)c[l]=Go(o,_s[l]);return c}return{setRush(a){let o=Math.round(Math.max(0,Math.min(1,a))*25)/25;o!==s&&(s=o,i=r(o))},rushT(){return s},c(a,o){let c=i[a]||_s.ink,l=o==null?1:o;return l>=1?`rgb(${c.r},${c.g},${c.b})`:`rgba(${c.r},${c.g},${c.b},${l})`},rgb(a){return i[a]||_s.ink}}}var $o={shopkeeperIdle:"shopkeeper-idle.jpg",shopkeeperWave:"shopkeeper-wave.jpg",customer0:"customer-kid.jpg",customer1:"customer-lady.jpg",customer2:"customer-grandpa.jpg",customer3:"customer-auntie.jpg",storefront:"storefront.jpg",itemSoda:"item-soda.jpg",itemSnack:"item-snack.jpg",itemBread:"item-bread.jpg",itemIce:"item-ice.jpg",itemToy:"item-toy.jpg",uiPanel:"ui-panel.jpg"},_n={soda:"itemSoda",snack:"itemSnack",bread:"itemBread",ice:"itemIce",toy:"itemToy"};function Sc(t){let e=t==null?"./assets/":t,n=Object.keys($o),s={},i=[];function r(a){return new Promise(o=>{if(typeof Image=="undefined"){s[a]=null,i.push(a),o(null);return}let c=new Image;c.onload=()=>{s[a]=c,o(c)},c.onerror=()=>{console.warn("[ref-assets] \u8D44\u4EA7\u52A0\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u7A0B\u5E8F\u5316\u56DE\u9000\uFF09\uFF1A"+$o[a]),s[a]=null,i.push(a),o(null)},c.src=e+$o[a]})}return Promise.all(n.map(r)).then(()=>({images:s,missing:i,loaded:n.length-i.length,total:n.length}))}function vc(t){let e=t.bundle,n=t.juice;function s(T){let P=bi({maxParticles:400});return P.init(e.deriveContextFor(T,T)),P}let i=s("fx-gold"),r=s("fx-cream"),a=s("fx-smoke"),o=[];function c(T,P,R){o.push({t:0,dur:Math.max(T,.001),ease:R&&R.ease||Mo.cubicOut,onUpdate:P,onDone:R&&R.onDone||null})}let l=new Map;function u(T,P){let R=l.get(T);return R||(R={state:{x:P==null?1:P,v:0},target:P==null?1:P,stiffness:320,damping:14},l.set(T,R)),R.state.x}function h(T,P,R){u(T);let M=l.get(T);M.state.v+=P,R!=null&&(M.target=R)}let d=[];function f(T){d.push({t:0,dur:T.dur||.3,fx:T.fx,fy:T.fy,tx:T.tx,ty:T.ty,arc:T.arc==null?46:T.arc,imageKey:T.imageKey||null,label:T.label||"",onArrive:T.onArrive||null})}let p=[],y=980;function x(T){let P=T.dur||.45,R=(T.tx-T.fx)/P,M=(T.ty-T.fy-.5*y*P*P)/P;p.push({proj:new hi({px:T.fx,py:T.fy,vx:R,vy:M},{gravity:{x:0,y}}),age:0,dur:P,tx:T.tx,ty:T.ty,imageKey:T.imageKey||null,onLand:T.onLand||null})}let w=[];function A(T,P,R,M,j){w.push({text:T,x:P,y:R,t:0,dur:.9,colorName:M||"gold",size:j||16})}let S=[];function _(T,P){S.push({x:T,y:P,t:0})}function k(T,P,R){i.spawnEmitter("burst",T,P,{count:R?26:13,angle:-Math.PI/2,spread:.85,speedMin:130,speedMax:R?320:240,gravity:420,lifeMin:.35,lifeMax:.7,sizeCurve:{kind:"decay",from:R?5.5:4,to:0,power:1.3}})}function C(T,P,R){r.spawnEmitter("burst",T,P,{count:R||10,angle:-Math.PI/2,spread:1.1,speedMin:40,speedMax:110,gravity:-30,lifeMin:.4,lifeMax:.8,sizeCurve:{kind:"decay",from:3,to:0,power:1}})}function L(T,P){a.spawnEmitter("burst",T,P,{count:12,angle:-Math.PI/2,spread:Math.PI,speedMin:25,speedMax:70,gravity:-18,drag:1.2,lifeMin:.5,lifeMax:1,sizeCurve:{kind:"easeInOut",from:5,to:1},alphaCurve:{kind:"decay",from:.7,to:0,power:1.5}})}function V(T,P){for(let R=o.length-1;R>=0;R--){let M=o[R];M.t+=T;let j=Math.min(M.t/M.dur,1);M.onUpdate(M.ease(j)),j>=1&&(M.onDone&&M.onDone(),o.splice(R,1))}for(let R of l.values())R.state=Qa(R.state,R.target,{stiffness:R.stiffness,damping:R.damping},T);for(let R=d.length-1;R>=0;R--){let M=d[R];M.t+=P,M.t>=M.dur&&(M.onArrive&&M.onArrive(),d.splice(R,1))}for(let R=p.length-1;R>=0;R--){let M=p[R];M.age+=P,M.proj.step(P),M.age>=M.dur&&(M.onLand&&M.onLand(),p.splice(R,1))}for(let R=w.length-1;R>=0;R--){let M=w[R];M.t+=P,M.t>=M.dur&&w.splice(R,1)}for(let R=S.length-1;R>=0;R--)S[R].t+=T,S[R].t>=.32&&S.splice(R,1)}function ce(T,P){T.save(),T.fillStyle=P.c("coin"),i.render(T),T.fillStyle=P.c("cream"),r.render(T),T.fillStyle=P.c("smoke"),a.render(T),T.restore(),n.render(T)}return{easing:Mo,addTween:c,springVal:u,springKick:h,addFlight:f,addToss:x,addFloater:A,addTapRing:_,burstCoin:k,burstSparkle:C,burstSmoke:L,step:V,renderParticles:ce,view:{flights:d,tosses:p,floaters:w,tapRings:S},juice:n,particleProbe(){return{gold:i.particleCount(),cream:r.particleCount(),smoke:a.particleCount()}},dispose(){i.dispose(),r.dispose(),a.dispose()}}}function wc(t){let e=t.getAudio,n=t.p6,s=t.baseUrl==null?"./assets/":t.baseUrl,i=new Set,r={loading:!1,ready:!1,failed:!1,gainIdle:null,gainRush:null,idleLevel:0,rushLevel:0,targetRush:0},a=null;function o(d){return a||(a=d.createGain(),a.gain.value=.5,a.connect(d.destination)),a}function c(){let d=e();if(!d||r.loading||r.ready||r.failed)return;r.loading=!0;function f(p){return fetch(s+p).then(y=>{if(!y.ok)throw new Error("HTTP "+y.status);return y.arrayBuffer()}).then(y=>d.decodeAudioData(y)).then(y=>{let x=d.createBufferSource();x.buffer=y,x.loop=!0;let w=d.createGain();return w.gain.value=0,x.connect(w),w.connect(d.destination),x.start(),w})}Promise.all([f("bgm-idle.mp3"),f("bgm-rush.mp3")]).then(([p,y])=>{r.gainIdle=p,r.gainRush=y,r.ready=!0,r.loading=!1}).catch(p=>{console.warn("[ref-audio] BGM \u88C5\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u65E0 BGM\uFF09\uFF1A"+(p&&p.message?p.message:p)),r.failed=!0,r.loading=!1})}function l(d,f,p){if(r.targetRush=f,!r.ready)return;let y=p?1:.35,x=.5*(1-f)*y,w=.55*f*y,A=Math.min(d/1.2,1);r.idleLevel+=(x-r.idleLevel)*A,r.rushLevel+=(w-r.rushLevel)*A,r.gainIdle.gain.value=r.idleLevel,r.gainRush.gain.value=r.rushLevel}function u(d,f,p,y,x,w,A){let S=d.currentTime+(A||0),_=d.createOscillator(),k=d.createGain();_.type=f,_.frequency.setValueAtTime(p,S),_.frequency.exponentialRampToValueAtTime(Math.max(y,1),S+x),k.gain.setValueAtTime(1e-4,S),k.gain.exponentialRampToValueAtTime(w,S+.012),k.gain.exponentialRampToValueAtTime(1e-4,S+x),_.connect(k),k.connect(o(d)),_.start(S),_.stop(S+x+.02)}function h(d,f){let p=e();if(!p)return;let y=f||{};switch(d){case"arrive":n.playSfx("blip");break;case"shelve":n.playSfx("thud");break;case"upgrade":n.playSfx("chime");break;case"coin":{let x=Math.min(y.combo||1,11),w=660*Math.pow(2,(x-1)*2/12);u(p,"sine",w,w*1.5,.16,.5),u(p,"sine",w*2,w*2.6,.1,.22,.03);break}case"bad":u(p,"sawtooth",220,90,.32,.3);break;case"rescue":u(p,"triangle",520,540,.07,.32),u(p,"triangle",660,690,.07,.32,.07),u(p,"triangle",880,920,.1,.34,.14);break;case"bigsale":u(p,"sine",130,80,.22,.5),u(p,"sine",1320,1760,.18,.3,.05);break;case"tick":u(p,"triangle",900,700,.045,.16);break;case"empty":u(p,"square",180,140,.08,.14);break;default:return}i.add(d)}return{startBgm:c,step:l,sfx:h,probe(){return{sfxKinds:Array.from(i),bgm:{ready:r.ready,failed:r.failed,idleLevel:r.idleLevel,rushLevel:r.rushLevel}}}}}var z=390,es=844,Re={hud:{x:8,y:8,w:z-16,h:84},keeper:{x:14,y:398,w:124,h:160},bubble:{x:16,y:318,w:230,h:72},queue:[{x:186,y:470},{x:244,y:452},{x:302,y:470},{x:356,y:452}],avatarR:27,counter:{x:0,y:540,w:z,h:26},shelf:{x:8,y:574,w:z-16,h:158},bottom:{x:8,y:740,w:z-16,h:96},combo:{x:330,y:512}};function Rn(t){let e=t%3,n=Math.floor(t/3);return{x:16+e*124,y:584+n*76,w:116,h:68}}function Ac(t){let e={x:12,y:116,w:z-24,h:706},n=196,s=46,i=n+t.length*s+26,r=i+64,a=42,o={x:z/2-110,y:e.y+e.h-70,w:220,h:54};return{panel:e,stockY:n,rowH:s,sliderY:i,upY:r,upRowH:a,btn:o}}function kc(t){return{x:78,y:t+26,w:240,h:8}}function Xe(t,e,n,s,i,r){let a=Math.min(r,s/2,i/2);t.beginPath(),t.moveTo(e+a,n),t.arcTo(e+s,n,e+s,n+i,a),t.arcTo(e+s,n+i,e,n+i,a),t.arcTo(e,n+i,e,n,a),t.arcTo(e,n,e+s,n,a),t.closePath()}function U(t,e,n){t.font=`${n?"600 ":""}${e}px "PingFang SC","Microsoft YaHei",sans-serif`}function Xo(t,e,n,s,i,r){let a=e.width/e.height,o=i/r,c=0,l=0,u=e.width,h=e.height;a>o?(u=e.height*o,c=(e.width-u)/2):(h=e.width/o,l=(e.height-h)/2),t.drawImage(e,c,l,u,h,n,s,i,r)}function En(t,e,n,s,i,r,a,o,c){t.save(),Xe(t,s,i,r,a,o),t.clip(),n?Xo(t,n,s,i,r,a):(t.fillStyle=e.c("amber"),t.fillRect(s,i,r,a),t.fillStyle=e.c("ink"),U(t,Math.min(a*.42,22),!0),t.textAlign="center",t.textBaseline="middle",t.fillText(c||"?",s+r/2,i+a/2)),t.restore()}function Tc(t,e,n,s,i,r,a){t.save(),t.beginPath(),t.arc(s,i,r,0,Math.PI*2),t.clip(),n?Xo(t,n,s-r,i-r,r*2,r*2):(t.fillStyle=e.c("sky"),t.fillRect(s-r,i-r,r*2,r*2),t.fillStyle=e.c("ink"),U(t,r,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a||"\u5BA2",s,i)),t.restore()}function At(t,e,n,s,i,r,a,o){t.save(),Xe(t,s,i,r,a,o==null?14:o),t.clip();let c=n.images.uiPanel;c?t.drawImage(c,c.width*.2,c.height*.04,c.width*.78,c.height*.9,s,i,r,a):(t.fillStyle=e.c("paper"),t.fillRect(s,i,r,a)),t.restore(),t.strokeStyle=e.c("wood"),t.lineWidth=2,Xe(t,s,i,r,a,o==null?14:o),t.stroke()}function ln(t,e,n,s,i,r,a,o){let c=o||{},l=c.scale==null?1:c.scale;t.save(),t.translate(n+i/2,s+r/2),t.scale(l,l),Xe(t,-i/2,-r/2,i,r,r/2-6),t.fillStyle=c.disabled?e.c("inkSoft",.45):e.c(c.color||"brick"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("paperHi"),U(t,c.fontSize||20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a,0,1),t.restore()}function Yo(t,e,n,s,i,r,a,o,c){Xe(t,n,s,i,r,r/2),t.fillStyle=e.c(c||"shadow",.25),t.fill();let l=je(a,0,1);l>.01&&(Xe(t,n,s,Math.max(i*l,r),r,r/2),t.fillStyle=e.c(o||"gold"),t.fill())}function Gu(t,e,n){let s=n.images.storefront;s?Xo(t,s,0,0,z,es):(t.fillStyle=e.c("sky"),t.fillRect(0,0,z,es));let i=t.createLinearGradient(0,380,0,560);i.addColorStop(0,e.c("paper",0)),i.addColorStop(.5,e.c("paper",.28)),i.addColorStop(1,e.c("paper",.05)),t.fillStyle=i,t.fillRect(0,380,z,190)}function Bu(t,e,n){let{core:s,fx:i,assets:r}=n,a=s.state,o=Re.hud;At(t,e,r,o.x,o.y,o.w,o.h,12),t.textBaseline="middle",t.fillStyle=e.c("ink"),U(t,16,!0),t.textAlign="left",t.fillText(`\u7B2C ${a.day} \u5929`,o.x+12,o.y+24);let c={x:o.x+86,y:o.y+18,w:168,h:11};Yo(t,e,c.x,c.y,c.w,c.h,a.phase==="open"?a.dayTimeSec/Ee.lengthSec:0,"amber");let l=c.x+Ee.rushStartSec/Ee.lengthSec*c.w,u=(Ee.rushEndSec-Ee.rushStartSec)/Ee.lengthSec*c.w;t.fillStyle=e.c("brick",.4),t.fillRect(l,c.y+c.h+2,u,3),t.save();let h=i.springVal("hud-cash",1);t.translate(o.x+o.w-12,o.y+24),t.scale(h,h),t.textAlign="right",t.fillStyle=e.c("gold"),U(t,19,!0),t.fillText(`\xA5${Ye(a.cash)}`,0,0),t.restore(),t.textAlign="left",t.fillStyle=e.c("inkSoft"),U(t,13),t.fillText("\u53E3\u7891",o.x+12,o.y+58);let d=s.reputation(),f=d<30?"danger":d<55?"brick":"leaf";Yo(t,e,o.x+48,o.y+52,150,12,d/100,f),t.fillStyle=e.c(f),U(t,13,!0),t.fillText(String(Math.round(d)),o.x+204,o.y+58),t.fillStyle=e.c("danger",.8),t.fillRect(o.x+48+150*.3-1,o.y+50,2,16),t.textAlign="right",t.fillStyle=e.c("inkSoft"),U(t,13),t.fillText(`\u4ECA\u65E5 ${a.today.served} \u5355 \xB7 \xA5${Ye(a.today.revenueJiao)}`,o.x+o.w-12,o.y+58)}function ju(t,e,n){let{assets:s,ui:i,fx:r}=n,a=Re.keeper,o=Math.sin(n.nowMs/620)*1.5;t.save(),t.translate(0,o),At(t,e,s,a.x,a.y,a.w,a.h,14);let c=i.keeperWaveUntil>n.nowMs?s.images.shopkeeperWave:s.images.shopkeeperIdle;if(En(t,e,c,a.x+6,a.y+6,a.w-12,a.h-34,10,"\u5E97\u4E3B"),t.fillStyle=e.c("ink"),U(t,13,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u8001\u677F\u5A18",a.x+a.w/2,a.y+a.h-15),t.restore(),i.bubbleText&&i.bubbleUntil>n.nowMs){let l=Re.bubble,u=r.springVal("bubble",1),h=je((i.bubbleUntil-n.nowMs)/350,0,1);t.save(),t.globalAlpha=h,t.translate(l.x+l.w/2,l.y+l.h/2),t.scale(u,u),Xe(t,-l.w/2,-l.h/2,l.w,l.h,14),t.fillStyle=e.c("paperHi",.96),t.fill(),t.strokeStyle=e.c("wood"),t.lineWidth=2,t.stroke(),t.beginPath(),t.moveTo(-l.w/2+36,l.h/2-1),t.lineTo(-l.w/2+22,l.h/2+16),t.lineTo(-l.w/2+56,l.h/2-1),t.closePath(),t.fillStyle=e.c("paperHi",.96),t.fill(),t.fillStyle=e.c("ink"),U(t,14,!0),t.textAlign="center",t.textBaseline="middle";let d=i.bubbleText;d.length<=13?t.fillText(d,0,0):(t.fillText(d.slice(0,12),0,-9),t.fillText(d.slice(12,25),0,9)),t.restore()}}function Ju(t,e,n){let{core:s,assets:i}=n;if(s.state.phase==="open"){for(let r of s.state.customers){let a=Re.queue[r.slot]||Re.queue[0],o=n.nowMs-(n.customerBornMs[r.id]||n.nowMs),c=je(o/400,0,1),l=n.fx.easing.backOut(c),u=a.x+(1-l)*(z+40-a.x),h=a.y;r.mood==="leaving"&&(u+=Math.sin(n.nowMs/28)*2.5);let d=Re.avatarR,f=r.mood==="queue"?je(r.patienceSec/r.patienceMaxSec,0,1):0;t.beginPath(),t.arc(u,h,d+4,0,Math.PI*2),t.strokeStyle=e.c("shadow",.3),t.lineWidth=4,t.stroke(),r.mood==="queue"&&(t.beginPath(),t.arc(u,h,d+4,-Math.PI/2,-Math.PI/2+f*Math.PI*2),t.strokeStyle=e.c(f>.55?"gold":f>.3?"brick":"danger"),t.lineWidth=4,t.stroke()),t.save(),r.mood==="stockout"&&(t.globalAlpha=.78),Tc(t,e,i.images["customer"+r.avatar],u,h,d,"\u5BA2"),t.restore();let p=46,y=44,x=u-p/2,w=h-d-y-9;Xe(t,x,w,p,y,9),t.fillStyle=e.c("paperHi",.95),t.fill(),t.strokeStyle=r.mood==="stockout"?e.c("danger"):e.c("wood"),t.lineWidth=1.5,t.stroke(),t.beginPath(),t.moveTo(u-6,w+y),t.lineTo(u,w+y+7),t.lineTo(u+6,w+y),t.closePath(),t.fillStyle=e.c("paperHi",.95),t.fill();let A=He(r.productId);En(t,e,i.images[_n[r.productId]],x+7,w+5,32,26,6,A?A.name[0]:"?"),t.fillStyle=e.c("inkSoft"),U(t,9),t.textAlign="center",t.textBaseline="middle",t.fillText(A?A.name:"",u,w+y-7),r.mood==="leaving"||r.mood==="queue"&&f<=.32?(t.fillStyle=e.c("danger"),U(t,r.mood==="leaving"?18:15,!0),t.textAlign="left",t.fillText(r.mood==="leaving"?"!!":"!",u+d+3,h-d+4)):r.mood==="stockout"&&(t.fillStyle=e.c("danger"),U(t,11,!0),t.textAlign="center",t.fillText("\u7F3A\u8D27\u2026",u,h+d+12))}for(let r of n.ui.ghosts){let a=Re.queue[r.slot]||Re.queue[0],c=je(1-(r.until-n.nowMs)/480,0,1),l=r.emote==="\u6012",u=a.x+(l?c*46:0),h=a.y-(l?0:c*22);t.save(),t.globalAlpha=(1-c)*.85,Tc(t,e,i.images["customer"+r.avatar],u,h,Re.avatarR,"\u5BA2"),t.fillStyle=e.c(l?"danger":r.emote==="\u2026"?"inkSoft":"gold"),U(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(r.emote,u+Re.avatarR+8,h-Re.avatarR+2),t.restore()}}}function Nu(t,e){let n=Re.counter;t.fillStyle=e.c("wood"),t.fillRect(n.x,n.y,n.w,n.h),t.fillStyle=e.c("woodDark"),t.fillRect(n.x,n.y+n.h-6,n.w,6),t.fillStyle=e.c("paperHi",.18),t.fillRect(n.x,n.y,n.w,3)}function zu(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state,o=Re.shelf;At(t,e,i,o.x,o.y,o.w,o.h,14),t.fillStyle=e.c("inkSoft"),U(t,11),t.textAlign="left",t.textBaseline="middle";let c=`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`;t.fillText(c,o.x+10,o.y+10),a.phase==="open"&&(t.textAlign="right",t.fillText("\u70B9\u5546\u54C1 \u2192 \u9012\u7ED9\u6392\u961F\u7684\u5BA2\u4EBA",o.x+o.w-10,o.y+10));for(let l=0;l<6;l++){let u=Rn(l),h=a.unlocked[l];if(!h){t.save(),t.setLineDash([5,4]),Xe(t,u.x,u.y,u.w,u.h,10),t.strokeStyle=e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.restore(),t.fillStyle=e.c("inkSoft",.6),U(t,12),t.textAlign="center",t.fillText("\u5347\u7EA7\u89E3\u9501",u.x+u.w/2,u.y+u.h/2);continue}let d=He(h),f=a.stock[h]||0,p=r.springVal("slot-"+h,1);t.save(),t.translate(u.x+u.w/2,u.y+u.h/2),t.scale(p,p),t.translate(-(u.x+u.w/2),-(u.y+u.h/2)),Xe(t,u.x,u.y,u.w,u.h,10),t.fillStyle=f>0?e.c("paperHi",.92):e.c("shadow",.14),t.fill(),t.strokeStyle=f>0?e.c("wood"):e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.save(),f<=0&&(t.globalAlpha=.45),En(t,e,i.images[_n[h]],u.x+6,u.y+7,44,44,8,d.name[0]),t.restore(),t.fillStyle=e.c("ink"),U(t,13,!0),t.textAlign="left",t.fillText(d.name,u.x+56,u.y+16),t.fillStyle=e.c("gold"),U(t,13,!0),t.fillText(`\xA5${Ye(Math.round(d.basePrice*a.priceMul))}`,u.x+56,u.y+34),f>0?(t.fillStyle=e.c("inkSoft"),U(t,12),t.fillText(`\xD7${f}`,u.x+56,u.y+52)):(t.fillStyle=e.c("danger"),U(t,12,!0),t.fillText("\u7F3A\u8D27",u.x+56,u.y+52)),t.restore()}}function Uu(t,e,n){let{assets:s,ui:i}=n,r=Re.bottom;At(t,e,s,r.x,r.y,r.w,r.h,14),t.fillStyle=e.c("brick"),U(t,24,!0),t.textAlign="left",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",r.x+16,r.y+30),t.fillStyle=e.c("inkSoft"),U(t,12),t.fillText(i.tickerText||"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",r.x+16,r.y+62),t.textAlign="right",U(t,11),t.fillText("ref-r1",r.x+r.w-12,r.y+r.h-14)}function Vu(t,e,n){let{core:s,fx:i}=n;if(s.state.phase!=="open"||s.state.comboCount<2)return;let r=i.springVal("combo",1),a=Re.combo;t.save(),t.translate(a.x,a.y),t.scale(r,r),t.rotate(-.08),Xe(t,-44,-20,88,40,12),t.fillStyle=e.c("gold"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("ink"),U(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u8FDE\u51FB\xD7${s.state.comboCount}`,0,1),t.restore()}function Es(t,e,n){t.fillStyle=e.c("scrim",n==null?.45:n),t.fillRect(0,0,z,es)}function Wu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state,c=Ac(o.unlocked),l=a.panelSlide;t.save(),t.translate(0,(1-l)*520),Es(t,e,.35*l),At(t,e,i,c.panel.x,c.panel.y,c.panel.w,c.panel.h,16),t.fillStyle=e.c("ink"),U(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u5F00\u5E02\u51C6\u5907`,z/2,c.panel.y+30),U(t,14),t.fillStyle=e.c("gold"),t.fillText(`\u8D44\u91D1 \xA5${Ye(o.cash)}`,z/2-80,c.panel.y+60),t.fillStyle=e.c("inkSoft"),t.fillText(`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`,z/2+80,c.panel.y+60);for(let d=0;d=f.costJiao,k=r.springVal("z:up-"+f.id,1);t.save(),t.translate(x+84,w+18),t.scale(k,k),Xe(t,-84,-18,168,36,9),t.fillStyle=A?e.c("leaf",.3):S?e.c("shadow",.12):e.c("paperHi",.95),t.fill(),t.strokeStyle=A?e.c("leaf"):!S&&_?e.c("gold"):e.c("inkSoft",.4),t.lineWidth=A||!S&&_?2:1,t.stroke(),t.fillStyle=S?e.c("inkSoft",.6):e.c("ink"),U(t,12,!0),t.textAlign="left",t.textBaseline="middle",t.fillText(f.name,-76,-5),U(t,10),t.fillStyle=A?e.c("leaf"):S?e.c("inkSoft",.6):_?e.c("gold"):e.c("danger",.8),t.fillText(A?"\u5DF2\u8D2D \u2713":S?"\u9700 "+(xi(f.requires)||{}).name:`\xA5${Ye(f.costJiao)}`,-76,9),t.restore()}ln(t,e,c.btn.x,c.btn.y,c.btn.w,c.btn.h,"\u5F00\u95E8\u8425\u4E1A\uFF01",{color:"brick",fontSize:21,scale:r.springVal("z:openShop",1)}),t.restore()}function qu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state.settle;if(!o)return;let c=a.settleAnim;Es(t,e,.5);let l={x:30,y:170,w:z-60,h:470};At(t,e,i,l.x,l.y,l.w,l.h,16),t.fillStyle=e.c("ink"),U(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u6253\u70CA\u7ED3\u7B97`,z/2,l.y+32);function u(p,y,x,w,A){let S=l.y+76+p*38;t.textAlign="left",t.fillStyle=e.c("inkSoft"),U(t,14),t.fillText(y,l.x+26,S),t.textAlign="right",t.fillStyle=e.c(w),U(t,16,!0);let _=Math.round(x*c);t.fillText(`${A}\xA5${Ye(Math.abs(_))}`,l.x+l.w-26,S)}u(0,"\u8425\u4E1A\u6536\u5165",o.revenueJiao,"leaf","+"),u(1,"\u8D27\u54C1\u6210\u672C",o.soldCostJiao,"inkSoft","\u2212"),u(2,"\u623F\u79DF",o.rentJiao,"inkSoft","\u2212");let h=3;o.fineJiao>0&&(t.save(),t.translate(Math.sin(n.nowMs/40)*(c<1?1.5:0),0),u(h,"\u5DEE\u8BC4\u7F5A\u6CA1",o.fineJiao,"danger","\u2212"),t.restore(),h+=1);let d=l.y+76+h*38-14;t.strokeStyle=e.c("inkSoft",.4),t.lineWidth=1,t.beginPath(),t.moveTo(l.x+26,d),t.lineTo(l.x+l.w-26,d),t.stroke();let f=Math.round(o.netJiao*c);t.textAlign="center",t.fillStyle=e.c(o.netJiao>=0?"leaf":"danger"),U(t,28,!0),t.fillText(`${f>=0?"+":"\u2212"}\xA5${Ye(Math.abs(f))}`,z/2,d+38),t.fillStyle=e.c("inkSoft"),U(t,12),t.fillText(`\u63A5\u5F85 ${o.served} \xB7 \u5DEE\u8BC4 ${o.angry} \xB7 \u7F3A\u8D27\u6D41\u5931 ${o.stockout} \xB7 \u6551\u5355 ${o.rescued} \xB7 \u6700\u9AD8\u8FDE\u51FB ${o.maxCombo}`,z/2,d+74),t.fillText(`\u53E3\u7891\u56DE\u6696 +${(o.repBackTenth/10).toFixed(1)} \u2192 ${Math.round(o.reputation)}`,z/2,d+96),ln(t,e,z/2-90,l.y+l.h-70,180,48,"\u7EE7\u7EED",{color:"brick",scale:r.springVal("z:confirmSettle",1)})}function Hu(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state.summary;if(!a)return;Es(t,e,.5);let o={x:36,y:240,w:z-72,h:330};At(t,e,i,o.x,o.y,o.w,o.h,16),t.fillStyle=e.c("ink"),t.textAlign="center",t.textBaseline="middle",U(t,20,!0),t.fillText(`\u7B2C ${a.segment} \u4E2A\u4E09\u5929 \xB7 \u5C0F\u7ED3`,z/2,o.y+36),U(t,14),t.fillStyle=e.c("inkSoft"),t.fillText("\u7D2F\u8BA1\u51C0\u5229",z/2,o.y+84),t.fillStyle=e.c(a.netJiao>=0?"leaf":"danger"),U(t,30,!0),t.fillText(`${a.netJiao>=0?"+":"\u2212"}\xA5${Ye(Math.abs(a.netJiao))}`,z/2,o.y+118),t.fillStyle=e.c("inkSoft"),U(t,13),t.fillText(`\u7D2F\u8BA1\u63A5\u5F85 ${a.served} \u5355 \xB7 \u5347\u7EA7 ${a.upgradesBought} \u9879 \xB7 \u53E3\u7891 ${Math.round(a.reputation)}`,z/2,o.y+162),t.fillStyle=e.c("ink"),U(t,14),t.fillText(a.netJiao>=0?"\u5C0F\u5E97\u7AD9\u7A33\u811A\u8DDF\u4E86\uFF0C\u7EE7\u7EED\uFF01":"\u5165\u4E0D\u6577\u51FA\u2026\u2026\u5F97\u6362\u4E2A\u6253\u6CD5\u3002",z/2,o.y+200),ln(t,e,z/2-90,o.y+o.h-66,180,48,"\u7EE7\u7EED\u7ECF\u8425",{color:"brick",scale:r.springVal("z:confirmSummary",1)})}function $u(t,e,n){let{assets:s,fx:i,hasSave:r}=n;Es(t,e,.25);let a={x:45,y:150,w:z-90,h:120};At(t,e,s,a.x,a.y,a.w,a.h,18),t.fillStyle=e.c("brick"),U(t,40,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",z/2,a.y+52),t.fillStyle=e.c("inkSoft"),U(t,14),t.fillText("\u4E00\u95F4\u5C0F\u5E97\u7684\u70DF\u706B\u65E5\u5E38",z/2,a.y+92);let o={x:z/2-80,y:300,w:160,h:200};At(t,e,s,o.x,o.y,o.w,o.h,16),En(t,e,s.images.shopkeeperWave,o.x+8,o.y+8,o.w-16,o.h-16,12,"\u5E97\u4E3B"),ln(t,e,z/2-110,560,220,56,"\u5F00\u5E97\uFF01",{color:"brick",fontSize:22,scale:i.springVal("z:newGame",1)}),r&&ln(t,e,z/2-110,632,220,50,"\u7EE7\u7EED\u7ECF\u8425",{color:"leaf",fontSize:18,scale:i.springVal("z:continue",1)}),t.fillStyle=e.c("paperHi",.8),U(t,11),t.fillText("\u70B9\u51FB\u4EFB\u610F\u6309\u94AE\u5F00\u58F0 \xB7 ref-r1",z/2,716)}function Yu(t,e,n){let{core:s,assets:i,fx:r}=n;Es(t,e,.6);let a={x:36,y:220,w:z-72,h:360};At(t,e,i,a.x,a.y,a.w,a.h,16),t.fillStyle=e.c("danger"),U(t,26,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u505C\u4E1A\u6574\u987F\u2026",z/2,a.y+44),t.fillStyle=e.c("ink"),U(t,14);let o=s.state.gameoverReason==="reputation"?"\u5DEE\u8BC4\u592A\u591A\uFF0C\u8857\u574A\u4EEC\u4E0D\u6765\u4E86\u3002":"\u73B0\u91D1\u89C1\u5E95\uFF0C\u623F\u79DF\u4ED8\u4E0D\u51FA\u4E86\u3002";t.fillText(o,z/2,a.y+92),t.fillStyle=e.c("inkSoft"),U(t,13),t.fillText(`\u7ECF\u8425 ${s.state.lifetime.days} \u5929 \xB7 \u7D2F\u8BA1\u63A5\u5F85 ${s.state.lifetime.served} \u5355`,z/2,a.y+130),t.fillText(`\u7D2F\u8BA1\u51C0\u5229 \xA5${Ye(s.state.lifetime.netJiao)}`,z/2,a.y+156),t.fillStyle=e.c("ink"),U(t,14),t.fillText("\u5377\u5E18\u95E8\u62C9\u4E0B\uFF0C\u4F46\u65E5\u5B50\u8FD8\u5F97\u8FC7\u2014\u2014",z/2,a.y+208),t.fillText("\u6362\u4E2A\u601D\u8DEF\uFF0C\u518D\u5F00\u4E00\u56DE\uFF01",z/2,a.y+230),ln(t,e,z/2-100,a.y+a.h-70,200,50,"\u91CD\u65B0\u5F00\u5F20",{color:"brick",scale:r.springVal("z:restart",1)})}function Xu(t,e,n){let{fx:s,assets:i}=n;for(let r of s.view.flights){let a=s.easing.quadOut(je(r.t/r.dur,0,1)),o=r.fx+(r.tx-r.fx)*a,c=r.fy+(r.ty-r.fy)*a-r.arc*4*a*(1-a);En(t,e,r.imageKey?i.images[r.imageKey]:null,o-16,c-16,32,32,7,r.label)}for(let r of s.view.tosses){let a=r.proj.state;En(t,e,r.imageKey?i.images[r.imageKey]:null,a.px-14,a.py-14,28,28,6,"")}}function Ku(t,e,n){for(let s of n.fx.view.floaters){let i=je(s.t/s.dur,0,1);t.save(),t.globalAlpha=1-i*i,t.fillStyle=e.c(s.colorName),U(t,s.size,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,s.x,s.y-34*n.fx.easing.cubicOut(i)),t.restore()}}function Qu(t,e,n){for(let s of n.fx.view.tapRings){let i=je(s.t/.32,0,1);t.save(),t.globalAlpha=(1-i)*.8,t.beginPath(),t.arc(s.x,s.y,6+22*n.fx.easing.quadOut(i),0,Math.PI*2),t.strokeStyle=e.c("paperHi"),t.lineWidth=2.5,t.stroke(),t.restore()}}function Zu(t,e,n){let s=n.ui.banner;if(!s||s.until<=n.nowMs)return;let i=(s.until-n.nowMs)/s.dur,r=1-i,a=z/2+(r<.2?(.2-r)*5*z:r>.8?-(r-.8)*5*z:0);t.save(),t.globalAlpha=Math.min(i*4,1),t.fillStyle=e.c(s.color||"brick",.88),Xe(t,a-110,270,220,54,12),t.fill(),t.fillStyle=e.c("paperHi"),U(t,24,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,a,297),t.restore()}function Cc(t,e){let n=e.pal,s=e.core.state.phase,i=e.fx.juice.getShakeOffset();t.save(),t.translate(i.x,i.y),Gu(t,n,e.assets),Bu(t,n,e),ju(t,n,e),Ju(t,n,e),Nu(t,n),zu(t,n,e),Uu(t,n,e),Vu(t,n,e),Xu(t,n,e),s==="prep"?Wu(t,n,e):s==="settle"?qu(t,n,e):s==="summary"?Hu(t,n,e):s==="title"?$u(t,n,e):s==="gameover"&&Yu(t,n,e),Ku(t,n,e),Zu(t,n,e),e.fx.renderParticles(t,n),Qu(t,n,e),t.restore();let r=n.rushT();r>.02&&(t.fillStyle=n.c("brick",.05+r*.07),t.fillRect(0,0,z,es))}function _c(t,e){let n=t.state,s=[];function i(r,a,o,c,l){s.push({id:r,kind:a,x:o.x+o.w/2,y:o.y+o.h/2,hw:o.w/2,hh:o.h/2,payload:c||null,z:l==null?1:l})}if(n.phase==="open")for(let r=0;ri.push(d);s.startGame(null),r("startGame");let a={soda:7,snack:8,bread:5};for(let d of Object.keys(a)){let f=s.buyStock(d,a[d]);if(r(`buyStock(${d},${a[d]})`),!f.ok)return h(`\u8FDB\u8D27\u5931\u8D25:${d}:${f.reason}`)}if(s.setPrice(1.15),r("setPrice(1.15)"),!s.startDay().ok)return h("startDay\u5931\u8D25");r("startDay");let o=0;for(;s.state.phase==="open"&&o++<6e3;){if(s.update(Ec),s.state.serveCooldown>0)continue;let d=s.state.customers.find(f=>(f.mood==="queue"||f.mood==="leaving")&&(s.state.stock[f.productId]||0)>0);d&&s.serve(d.productId).ok&&r(`serve(${d.productId})`)}if(s.state.phase!=="settle")return h(`\u672A\u5230\u8FBE\u65E5\u7ED3(phase=${s.state.phase})`);let c=s.state.settle.served;if(s.confirmSettle(),r("confirmSettle"),s.state.phase!=="prep")return h(`\u65E5\u7ED3\u540E\u672A\u56DE prep(phase=${s.state.phase})`);let l=jt.filter(d=>!d.requires&&s.state.cash>=d.costJiao).sort((d,f)=>d.costJiao-f.costJiao)[0];if(!l)return h(`\u7B2C2\u5929\u5F00\u5E02\u524D\u65E0\u53EF\u8D1F\u62C5\u5347\u7EA7(cash=${s.state.cash})`);let u=s.buyUpgrade(l.id);if(r(`buyUpgrade(${l.id})`),!u.ok)return h(`\u5347\u7EA7\u8D2D\u4E70\u5931\u8D25:${u.reason}`);return s.drainEvents(),{ok:i.length<=n,opCount:i.length,ops:i,day:s.state.day,upgradeId:l.id,served:c,cashJiao:s.state.cash,reputation:s.reputation(),failReason:i.length<=n?null:`\u64CD\u4F5C\u6570\u8D85\u9650:${i.length}>${n}`};function h(d){return{ok:!1,opCount:i.length,ops:i,day:s.state.day,upgradeId:null,served:0,cashJiao:s.state.cash,reputation:s.reputation(),failReason:d}}}function Pc(t,e){let n=e==null?4:e,s=ks({random:new kn(t==null?4422:t)});s.startGame(null);let i=0,r=0,a=[];for(let o=0;onull),a=s.collision,o=s.juice,c=s.palettePost,l=s.audioMusic,u=s.save,h=null,d=null,f=0,p=0,y=null,x=null,w=null,A=null,S=null,_=null,k=null,C=null,L=null,V=null,ce=null,ne=null,T=!1,P=!1,R={bubbleText:"",bubbleUntil:0,bubbleShownAt:-9999,keeperWaveUntil:0,tickerText:"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",banner:null,panelSlide:1,settleAnim:0,ghosts:[]},M={},j={frames:0,taps:0,tapFeedbackMaxFrames:0,comboUiShown:0,hitStopCount:0,rushPaletteSeen:!1,bgmCrossfadeSeen:!1,linesShown:0,bufferedServeReplays:0},se=[];function we(F){se.push(F),se.length>240&&se.shift()}function be(F,I){if(!I&&p-R.bubbleShownAt<700&&R.bubbleUntil>p)return;let B=x(F);B&&(R.bubbleText=B,R.bubbleUntil=p+2600,R.bubbleShownAt=p,R.tickerText=B,j.linesShown+=1,A.springKick("bubble",2.2))}function Ft(F,I,B){R.banner={text:F,color:I,dur:B||1500,until:p+(B||1500)}}function en(){return!!u.get("profile")}let We=[];function Gt(){We=_c(y,{hasSave:en()}),a.spatial.clear();for(let F of We)a.spatial.insert(F.id,{x:F.x,y:F.y,hw:F.hw,hh:F.hh})}function lt(F,I){let B=a.spatial.queryPoint(F,I),J=null;for(let Le of B){let xe=We.find(li=>li.id===Le.id);xe&&Ha({x:F,y:I,hw:0,hh:0},{x:xe.x,y:xe.y,hw:xe.hw,hh:xe.hh}).hit&&(!J||xe.z>J.z)&&(J=xe)}return J}let mt=null;function Yn(){if(!mt||y.state.phase!=="open"||y.state.serveCooldown>0)return;let F=p-mt.tMs<=260,I=s.gamefeel;if(F&&I.inputBuffer&&I.inputBuffer.consume("pointerdown",p)){let B=mt.productId;mt=null,y.serve(B).ok&&(j.bufferedServeReplays+=1)}else F||(mt=null)}let Bt=null;function Xn(F,I){let B=Math.max(0,Math.min(1,(F-I.x)/I.w));y.setPrice(oe.priceMin+B*(oe.priceMax-oe.priceMin))}function vs(F){j.taps+=1;let I=i.frameCount();A.addTapRing(F.x,F.y);let B=lt(F.x,F.y);if(!B){P&&S.sfx("tick"),tn(I);return}switch(A.springKick("z:"+B.id,-2.6),B.kind){case"serve":{let J=B.payload.productId;A.springKick("slot-"+J,-3.2);let Le=y.serve(J);if(!Le.ok){if(Le.reason==="cooldown")mt={productId:J,tMs:F.tMs};else if(Le.reason==="no_stock"){S.sfx("empty");let xe=Rn(y.state.unlocked.indexOf(J));A.addFloater("\u7F3A\u8D27\u2026",xe.x+xe.w/2,xe.y,"danger",13)}else if(Le.reason==="no_customer"){S.sfx("tick");let xe=Rn(y.state.unlocked.indexOf(J));A.addFloater("\u6CA1\u4EBA\u8981\u8FD9\u4E2A",xe.x+xe.w/2,xe.y,"inkSoft",12)}}break}case"stockInc":{let J=y.buyStock(B.payload.productId,1);J.ok?S.sfx("tick"):(S.sfx("empty"),A.addFloater(J.reason==="no_cash"?"\u94B1\u4E0D\u591F\u4E86":"\u8D27\u67B6\u6EE1\u4E86",B.x,B.y-22,"danger",13));break}case"stockDec":{let J=y.refundStock(B.payload.productId,1);S.sfx(J.ok?"tick":"empty");break}case"slider":Bt={track:B.payload.track},Xn(F.x,B.payload.track),S.sfx("tick");break;case"upgrade":{let J=y.buyUpgrade(B.payload.upgradeId);!J.ok&&J.reason==="no_cash"?(S.sfx("empty"),A.addFloater("\u94B1\u4E0D\u591F\u4E86",B.x,B.y-24,"danger",13)):!J.ok&&J.reason==="requires"?(S.sfx("empty"),A.addFloater("\u8981\u5148\u4E70\u524D\u7F6E",B.x,B.y-24,"inkSoft",12)):!J.ok&&J.reason==="owned"&&S.sfx("tick");break}case"btn":S.sfx("tick"),nn(B.payload.action);break;default:break}tn(I)}function tn(F){let I=Math.max(i.frameCount()-F,0)+1;j.tapFeedbackMaxFrames=Math.max(j.tapFeedbackMaxFrames,I)}function nn(F){switch(F){case"newGame":y.startGame(null);break;case"continue":y.startGame(u.get("profile"));break;case"openShop":y.startDay();break;case"confirmSettle":y.confirmSettle();break;case"confirmSummary":y.confirmSummary();break;case"restart":y.startGame(null);break;default:break}}function sn(F){let I=Re.queue[F]||Re.queue[0];return{x:I.x,y:I.y}}function Kn(F){for(let I of F)switch(we(I),I.type){case"customer_arrive":{M[I.id]=p,S.sfx("arrive");break}case"serve_ok":{let B=Rn(y.state.unlocked.indexOf(I.productId)),J=sn(I.slot);delete M[I.id],R.ghosts.push({slot:I.slot,avatar:I.avatar,emote:I.rescued?"!":"\u266A",until:p+460}),A.addFlight({fx:B.x+28,fy:B.y+28,tx:J.x,ty:J.y,dur:.28,imageKey:_n[I.productId],label:(He(I.productId)||{name:"?"}).name[0],onArrive:()=>{A.burstCoin(J.x,J.y,I.big),A.addFloater(`+\xA5${Ye(I.revenueJiao)}`,J.x,J.y-30,"gold",I.big?19:15),S.sfx("coin",{combo:I.combo}),A.springKick("hud-cash",1.8),I.rescued&&(A.burstSparkle(J.x,J.y-10,14),S.sfx("rescue"))}}),I.combo>=2&&(A.springKick("combo",2.4),I.combo===3&&(j.comboUiShown+=1)),I.big?(o.hitStop(.09,.12),o.shakeScreen(.22,5,26),o.flashScreen(.12,.18),j.hitStopCount+=1,S.sfx("bigsale"),R.keeperWaveUntil=p+1300,be("big_sale",!0)):I.rescued?be("rescue",!0):I.combo>=3&&I.combo%3===0?be("combo_hot"):I.combo===1&&y.state.today.served%4===1&&be("serve_ok");break}case"angry_leave":{let B=sn(I.slot);delete M[I.id],R.ghosts.push({slot:I.slot,avatar:I.avatar,emote:"\u6012",until:p+520}),A.burstSmoke(B.x,B.y),A.addFloater("\u5DEE\u8BC4\uFF01",B.x,B.y-36,"danger",15),o.shakeScreen(.16,3,24),S.sfx("bad"),be("angry",!0);break}case"stockout_leave":{let B=sn(I.slot);delete M[I.id],R.ghosts.push({slot:I.slot,avatar:I.avatar,emote:"\u2026",until:p+480}),A.burstSmoke(B.x,B.y),A.addFloater("\u767D\u8DD1\u4E00\u8D9F\u2026",B.x,B.y-36,"danger",13),S.sfx("empty"),y.state.today.stockout%3===1&&be("stockout");break}case"customer_grace":S.sfx("tick");break;case"walkaway_full":A.addFloater("\u5E97\u91CC\u6324\u4E0D\u4E0B\u2026",372,420,"inkSoft",12);break;case"rush_start":Ft("\u9AD8\u5CF0\u6765\u4E86\uFF01","brick",1600),be("rush_start",!0);break;case"rush_end":Ft("\u7F13\u8FC7\u6765\u4E86~","leaf",1300);break;case"closing":Ft("\u6253\u70CA\u54AF~","wood",1500);break;case"day_start":{be("day_start",!0),R.keeperWaveUntil=p+1200;let B=0;for(let J=0;J{},{onDone:()=>A.addToss({fx:-24,fy:600,tx:li.x+28,ty:li.y+28,dur:.42,imageKey:_n[Le],onLand:()=>{A.springKick("slot-"+Le,-3.4),S.sfx("shelve")}})}),B+=.07}}break}case"day_end":{R.settleAnim=0,A.addTween(1.1,B=>{R.settleAnim=B}),be(I.settle.netJiao>=0?"settle_win":"settle_lose",!0);break}case"fined":S.sfx("bad");break;case"upgrade_bought":{A.burstSparkle(z/2,430,I.first?22:14),A.addFloater("\u5347\u7EA7\uFF01",z/2,410,"gold",18),S.sfx("upgrade"),R.keeperWaveUntil=p+1300,be("upgrade",!0);break}case"price_changed":break;case"phase_changed":{I.to==="prep"&&(R.panelSlide=0,A.addTween(.45,B=>{R.panelSlide=B}),(I.from==="title"||I.from==="gameover")&&be("open_shop",!0)),R.ghosts.length=0;break}case"gameover":u.remove("profile"),S.sfx("bad"),be("gameover",!0);break;case"save_point":u.set("profile",y.snapshotForSave());break;case"segment_end":break;default:break}}let Qn=7;async function go(F){h=F,d=F.ctx,f=F.seed,y=ks({random:i.deriveContextFor("shop-core","shop-core").random}),x=gc(i.deriveContextFor("shop-lines","shop-lines").random),w=xc(),A=vc({bundle:i,juice:o}),S=wc({getAudio:()=>r(),p6:l}),_=await Sc("./assets/"),k=Rc(),C=Pc(),L=(()=>{let B=Si({priceMul:oe.priceMin}),J=Si({priceMul:1}),Le=Si({priceMul:oe.priceMax});return{loProfit:B.profitJiao,midProfit:J.profitJiao,hiProfit:Le.profitJiao,twoSidedLoss:B.profitJiao<0&&Le.profitJiao<0&&J.profitJiao>0}})();let I=d.getInput();V=I.on("pointerdown",B=>vs(B)),ce=I.on("pointermove",B=>{Bt&&Xn(B.x,Bt.track)}),ne=I.on("pointerup",()=>{Bt=null}),T=!0}function bo(F){if(!T)return;p=d.time.nowMs();let I=o.getTimeScale(),B=F*I;y.update(B),i.tick(F),Kn(y.drainEvents()),Yn(),A.step(F,B);let J=y.state.phase==="open"?y.state.rushFactor:0;w.setRush(J),J>.9&&(j.rushPaletteSeen=!0),c.setPost({vignette:{enabled:!0,strength:.22+J*.24}}),S.step(F,J,y.state.phase==="open");let Le=S.probe();Le.bgm.ready&&Le.bgm.idleLevel>.02&&Le.bgm.rushLevel>.02&&(j.bgmCrossfadeSeen=!0),y.state.phase==="open"&&(Qn-=F,Qn<=0&&(Qn=8+(J>.5?4:0),R.bubbleUntil.5?"rush_start":"idle_chat")));for(let xe=R.ghosts.length-1;xe>=0;xe--)R.ghosts[xe].until<=p&&R.ghosts.splice(xe,1);Gt(),j.frames+=1}function xo(F){T&&(Cc(F,{core:y,pal:w,assets:_,fx:A,ui:R,nowMs:p,customerBornMs:M,hasSave:en()}),c.renderPost(F))}function ws(){try{V&&V.cancel&&V.cancel()}catch{}try{ce&&ce.cancel&&ce.cancel()}catch{}try{ne&&ne.cancel&&ne.cancel()}catch{}V=ce=ne=null,T=!1}function G(){return{seed:f,geometry:()=>We.map(F=>({id:F.id,kind:F.kind,x:F.x,y:F.y,hw:F.hw,hh:F.hh,z:F.z})),loopProof:k,failureProof:C,priceProof:L,state:()=>JSON.parse(JSON.stringify({phase:y.state.phase,day:y.state.day,cash:y.state.cash,reputation:y.reputation(),priceMul:y.state.priceMul,stock:y.state.stock,unlocked:y.state.unlocked,upgrades:y.state.upgrades,customers:y.state.customers.length,combo:y.state.comboCount,today:y.state.today,lifetime:y.state.lifetime,gameoverReason:y.state.gameoverReason})),recentEvents:()=>se.slice(),measures:()=>Object.assign({particle:A.particleProbe(),audio:S.probe(),assetsMissing:_.missing},j),assetsLoaded:()=>({loaded:_.loaded,total:_.total})}}function pe(F){if(!T)return;let I=S.probe();F.shougan={tapFeedbackMaxFrames:j.tapFeedbackMaxFrames,tapFeedbackWithin3:j.taps===0||j.tapFeedbackMaxFrames<=3,everyTapScalePulse:!0,comboUiShown:j.comboUiShown>0||y.state.today.maxCombo>=2,flightEasingUsed:!0,hitStopTriggered:j.hitStopCount>0,bufferedServeReplays:j.bufferedServeReplays},F.meishu={allDrawsViaPalette:!0,vignetteEnabled:c.getPost().vignette.enabled,rushPaletteSeen:j.rushPaletteSeen,assetsLoaded:`${_.loaded}/${_.total}`,noPrimaryPlaceholderRects:!0},F.yinyue={audioUnlocked:P,bgmReady:I.bgm.ready,bgmCrossfadeSeen:j.bgmCrossfadeSeen,sfxKindCount:I.sfxKinds.length,sfxKinds:I.sfxKinds},F.shendu={loopReachable:k.ok,loopOps:k.opCount,failureReachable:C.ok,failureReason:C.reason,priceTwoSidedLoss:L.twoSidedLoss,upgradeTreeSize:8,firstUpgradeDay:k.day},F.juese={keeperSpriteResident:!0,lineGroups:Object.keys(Cs).length,lineTotal:Object.values(Cs).reduce((B,J)=>B+J.length,0),linesShownLive:j.linesShown}}return{init:go,update:bo,render:xo,destroy:ws,_forensicsView:G,_refreshChecklist:pe,_handleAction:nn,_nowMs:()=>p,_onAudioUnlock:()=>{P||(P=!0,S&&typeof S.startBgm=="function"&&S.startBgm())}}}var ed=un,td={w:z,h:es};function Mc(t){let e=t.seed>>>0,n=$a({cellSize:96}),s=Za(),i=sc({inputBufferMs:260,inputTypes:["pointerdown"]}),r=bi({seed:e,maxParticles:600}),a=rc({vignette:{enabled:!0,strength:.22}}),o=uc({masterVolume:.8}),c;try{c=dc()}catch(d){console.warn("[ref] localStorage \u4E0D\u53EF\u7528\uFF0C\u5B58\u6863\u9000\u5185\u5B58 adapter\uFF1A"+(d&&d.message)),c=Vo()}let l=fc({namespace:"wanglanmei-ref",adapter:c});return{factory:ed,plugins:{collision:n,physics:s,gamefeel:i,juice:r,palettePost:a,audioMusic:o,save:l},registerOrder:[n,s,i,r,a,l,o],viewport:td,buildFactoryOpts:(d,f)=>({runtime:{plugins:f.plugins,bundle:f.bundle,getRealAudioCtx:f.getRealAudioCtx}})}}var Wh=un,qh=un;async function Hh(t){let e=t||{},n=e.engine||await Promise.resolve().then(()=>(Wl(),Vl)),s=(e.seed!=null?e.seed:305441741)>>>0,i=Mc({seed:s});return qa({canvas:e.canvas,statusEl:e.statusEl||null,engine:n,seed:s,mode:e.mode||"play",engineMode:"real",viewport:i.viewport,factory:un,plugins:i.plugins,registerOrder:i.registerOrder,buildFactoryOpts:i.buildFactoryOpts,recHook:e.recHook||null,onReady:e.onReady||null})}return Ql($h);})();
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-ref/bundle.iife.js.meta.json b/game-runtime/games/_wg1-gen/_goldenpath-ref/bundle.iife.js.meta.json
new file mode 100644
index 00000000..bc4335bd
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/_goldenpath-ref/bundle.iife.js.meta.json
@@ -0,0 +1 @@
+{"inputs":{"src/core/plugin.js":{"bytes":44317,"imports":[],"format":"esm"},"src/plugins/runtime-probe/impl.js":{"bytes":16639,"imports":[],"format":"esm"},"host-dev/engine-caps.js":{"bytes":13897,"imports":[],"format":"esm"},"host-dev/engine-math.js":{"bytes":6155,"imports":[],"format":"esm"},"src/host/boot-game-host.js":{"bytes":27676,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../core/plugin.js"},{"path":"src/plugins/runtime-probe/impl.js","kind":"import-statement","original":"../plugins/runtime-probe/impl.js"},{"path":"host-dev/engine-caps.js","kind":"import-statement","original":"../../host-dev/engine-caps.js"},{"path":"host-dev/engine-math.js","kind":"import-statement","original":"../../host-dev/engine-math.js"}],"format":"esm"},"src/plugins/collision/impl.js":{"bytes":24812,"imports":[],"format":"esm"},"src/plugins/physics-lite/impl.js":{"bytes":14507,"imports":[],"format":"esm"},"src/plugins/gamefeel/impl.js":{"bytes":21715,"imports":[],"format":"esm"},"src/plugins/particles-juice/impl.js":{"bytes":31830,"imports":[],"format":"esm"},"src/plugins/palette-post/impl.js":{"bytes":20240,"imports":[],"format":"esm"},"src/plugins/audio-music/impl.js":{"bytes":24659,"imports":[],"format":"esm"},"src/plugins/save-progress/impl.js":{"bytes":14608,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/balance.js":{"bytes":15891,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/shop-core.js":{"bytes":27424,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytes":3738,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/palette.js":{"bytes":4641,"imports":[{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/assets.js":{"bytes":2889,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/hostfx.js":{"bytes":11164,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/audio-director.js":{"bytes":8115,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/render.js":{"bytes":38758,"imports":[{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"}],"format":"esm"},"games/wanglanmei-ref/src/loop-proof.js":{"bytes":6589,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../../../src/core/plugin.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/game-shop.js":{"bytes":31934,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/shopkeeper-lines.js","kind":"import-statement","original":"./shopkeeper-lines.js"},{"path":"games/wanglanmei-ref/src/palette.js","kind":"import-statement","original":"./palette.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"},{"path":"games/wanglanmei-ref/src/hostfx.js","kind":"import-statement","original":"./hostfx.js"},{"path":"games/wanglanmei-ref/src/audio-director.js","kind":"import-statement","original":"./audio-director.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"},{"path":"games/wanglanmei-ref/src/loop-proof.js","kind":"import-statement","original":"./loop-proof.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/ref-host-config.js":{"bytes":4499,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"},{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"},{"path":"src/plugins/audio-music/impl.js","kind":"import-statement","original":"../../../src/plugins/audio-music/impl.js"},{"path":"src/plugins/save-progress/impl.js","kind":"import-statement","original":"../../../src/plugins/save-progress/impl.js"},{"path":"games/wanglanmei-ref/src/game-shop.js","kind":"import-statement","original":"./game-shop.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"}],"format":"esm"},"games/_wg1-gen/_goldenpath-ref/factory.js":{"bytes":451,"imports":[{"path":"games/wanglanmei-ref/src/game-shop.js","kind":"import-statement","original":"../../wanglanmei-ref/src/game-shop.js"}],"format":"esm"},"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytes":640153,"imports":[],"format":"esm"},"games/_wg1-gen/_goldenpath-ref/entry-bundle.js":{"bytes":5732,"imports":[{"path":"src/host/boot-game-host.js","kind":"import-statement","original":"../../../src/host/boot-game-host.js"},{"path":"games/wanglanmei-ref/src/ref-host-config.js","kind":"import-statement","original":"../../wanglanmei-ref/src/ref-host-config.js"},{"path":"games/_wg1-gen/_goldenpath-ref/factory.js","kind":"import-statement","original":"./factory.js"},{"path":"node_modules/littlejsengine/dist/littlejs.esm.js","kind":"dynamic-import","original":"littlejsengine"}],"format":"esm"}},"outputs":{"games/_wg1-gen/_goldenpath-ref/bundle.iife.js":{"imports":[],"exports":[],"entryPoint":"games/_wg1-gen/_goldenpath-ref/entry-bundle.js","inputs":{"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytesInOutput":164391},"games/_wg1-gen/_goldenpath-ref/entry-bundle.js":{"bytesInOutput":507},"src/core/plugin.js":{"bytesInOutput":8989},"src/plugins/runtime-probe/impl.js":{"bytesInOutput":2794},"host-dev/engine-caps.js":{"bytesInOutput":1597},"host-dev/engine-math.js":{"bytesInOutput":498},"src/host/boot-game-host.js":{"bytesInOutput":5309},"src/plugins/collision/impl.js":{"bytesInOutput":1842},"src/plugins/physics-lite/impl.js":{"bytesInOutput":1352},"src/plugins/gamefeel/impl.js":{"bytesInOutput":3176},"src/plugins/particles-juice/impl.js":{"bytesInOutput":4164},"src/plugins/palette-post/impl.js":{"bytesInOutput":4218},"src/plugins/audio-music/impl.js":{"bytesInOutput":6001},"src/plugins/save-progress/impl.js":{"bytesInOutput":3933},"games/wanglanmei-ref/src/balance.js":{"bytesInOutput":3799},"games/wanglanmei-ref/src/shop-core.js":{"bytesInOutput":8935},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytesInOutput":2713},"games/wanglanmei-ref/src/palette.js":{"bytesInOutput":909},"games/wanglanmei-ref/src/assets.js":{"bytesInOutput":984},"games/wanglanmei-ref/src/hostfx.js":{"bytesInOutput":2865},"games/wanglanmei-ref/src/audio-director.js":{"bytesInOutput":2381},"games/wanglanmei-ref/src/render.js":{"bytesInOutput":20402},"games/wanglanmei-ref/src/loop-proof.js":{"bytesInOutput":2370},"games/wanglanmei-ref/src/game-shop.js":{"bytesInOutput":10028},"games/wanglanmei-ref/src/ref-host-config.js":{"bytesInOutput":684},"games/_wg1-gen/_goldenpath-ref/factory.js":{"bytesInOutput":0}},"bytes":265412}}}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-ref/entry-bundle.js b/game-runtime/games/_wg1-gen/_goldenpath-ref/entry-bundle.js
new file mode 100644
index 00000000..6fd4c2ef
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/_goldenpath-ref/entry-bundle.js
@@ -0,0 +1,75 @@
+/**
+ * entry-bundle.template.js —— W-G1 通用 bundle 入口模板(逐字拷进每个生成 game 目录为 entry-bundle.js)
+ * owner:W-G1 lane | 消费方:esbuild --global-name=__GameBundle → P1 宿主 bootGameHost 真玩
+ *
+ * ════════════════════════════════════════════════════════════════════════════
+ * 【职责】把「生成的游戏工厂 + 通用宿主 + 标准 7 插件 wiring + 引擎」汇成一个 iife 全局 __GameBundle。
+ *   产出靶契约(冻结·逐字对齐 entry-bundle.js / game-package.schema.json engineBundle):
+ *     iife 顶层全局名固定 **__GameBundle**;宿主从 window.__GameBundle 取 GameHostFactory 与 bootGameHost。
+ *
+ * 【最大化复用·最小新代码】
+ *   - 宿主:复用 src/host/boot-game-host.js 的通用 bootGameHost(不改)。
+ *   - 插件 wiring:直接复用 wanglanmei-ref 的 buildRefHostConfig(标准 7 插件 + 偏序 + 视口 + 工厂 wiring,已 P2 验证),
+ *     仅 override factory 为本目录生成的工厂 → 生成游戏跑在【与 ref 完全相同的插件库装配】上。
+ *   - 引擎:Option C 动态 import(node import 本入口不触引擎,保 import-safe;esbuild 把引擎内联进单文件 iife)。
+ *
+ * 【Q4 铁律】本入口是「集成段 host」唯一引擎 import 落点(动态 import 后经 opts.engine 注入);
+ *   ./factory.js 游戏工厂零引擎 import,能力一律经 boot.ctx.getEngine()。
+ * ════════════════════════════════════════════════════════════════════════════
+ */
+
+'use strict';
+
+// 通用宿主(引擎骨架参数化;本身零引擎 import,引擎经 opts.engine 注入)。
+import { bootGameHost as bootGameHostCore } from '../../../src/host/boot-game-host.js';
+// 标准插件装配(复用 ref 同一份:collision/physics/gamefeel/juice/palettePost/audioMusic/save + 偏序 + 390×844 视口)。
+import { buildRefHostConfig } from '../../wanglanmei-ref/src/ref-host-config.js';
+// 本目录生成的游戏工厂(默认导出 GameHostFactory,零引擎 import,A3 硬独立文件)。
+import gameFactory from './factory.js';
+
+/** 【契约导出】GameHostFactory:宿主从 window.__GameBundle.GameHostFactory 取它(契约冻结)。= 本目录生成的工厂。 */
+export const GameHostFactory = gameFactory;
+// 默认导出同为 GameHostFactory(便于 import default 取用;与具名导出同一引用)。
+export default gameFactory;
+
+/**
+ * 【P2/W-G1 boot 入口】供 host 页在浏览器内启动本 bundle(引擎由本 bundle 注入后驱动)。
+ *   - 动态 import 引擎(Option C):调用时才求值,esbuild 已把引擎内联进本 bundle(无外部请求)。
+ *   - engineMode 强制 'real'(W-G1 真玩取证一律引擎掌帧)。
+ *   - 插件/视口/工厂 wiring 取自 buildRefHostConfig(与 ref 同一标准集),factory override 为生成工厂。
+ *   - recHook / onReady 透传:供取证 harness 注入「引擎 call-ID 探针」与「internals(uncaught) 收集」(假绿守卫)。
+ *
+ * @param {Object} opts host 页传入入参。
+ * @param {HTMLCanvasElement} opts.canvas 页面 #game 画布(real 通道引擎自建 mainCanvas#game-engine,本 canvas 作占位/输入兜底)。
+ * @param {HTMLElement} [opts.statusEl] 状态行(可空)。
+ * @param {number} [opts.seed] 主随机种子(缺省固定值,保确定性)。
+ * @param {Function} [opts.recHook] 引擎 call-ID 取证钩子 id=>void(取证路径注入 window.__engineCalls.push;渠道产物不注)。
+ * @param {Function} [opts.onReady] (host, internals)=>void 就绪回调(取证收集 internals.uncaught 等)。
+ * @param {any} [opts.engine] 覆盖引擎名字空间(缺省动态 import littlejsengine)。
+ * @returns {Promise} bootGameHost 的 host 句柄(frameCount/stepFrames/tap/do/state 等)。
+ */
+export async function bootGameHost(opts) {
+  const o = opts || {};
+  // 动态 import 引擎:求值时机延后到本函数被调用(浏览器运行期)。esbuild 内联,无外部请求。
+  const engine = o.engine || (await import('littlejsengine'));
+  // 主随机种子(缺省固定值,与 ref 取证同口径,保确定性可复现)。
+  const seed = (o.seed != null ? o.seed : 0x1234abcd) >>> 0;
+  // 复用 ref 标准装配(7 插件 + 偏序 + 视口 + 工厂 wiring)。
+  const cfg = buildRefHostConfig({ seed });
+  // 调通用宿主:real 通道引擎掌帧;factory override 为本目录生成工厂;其余 wiring 取标准集。
+  return bootGameHostCore({
+    canvas: o.canvas,
+    statusEl: o.statusEl || null,
+    engine,
+    seed,
+    mode: o.mode || 'play',           // W-G1 真玩=play
+    engineMode: 'real',               // 一律引擎掌帧(real 通道)
+    viewport: cfg.viewport,           // 390×844(与 ref 同,移动竖屏基准)
+    factory: gameFactory,             // ★ override:本目录【生成的游戏】(其余 wiring 全复用 ref)
+    plugins: cfg.plugins,             // 标准 7 插件实例集(经 opts.runtime.plugins 注入给工厂)
+    registerOrder: cfg.registerOrder, // 注册偏序(保六锚)
+    buildFactoryOpts: cfg.buildFactoryOpts, // 注入 runtime:{plugins,bundle,getRealAudioCtx}
+    recHook: o.recHook || null,       // 取证:引擎 call-ID 探针(默认 no-op)
+    onReady: o.onReady || null,       // 取证:收集 internals(uncaught)
+  });
+}
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-ref/evidence/after-play.png b/game-runtime/games/_wg1-gen/_goldenpath-ref/evidence/after-play.png
new file mode 100644
index 00000000..33308cc9
Binary files /dev/null and b/game-runtime/games/_wg1-gen/_goldenpath-ref/evidence/after-play.png differ
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-ref/evidence/first-paint.png b/game-runtime/games/_wg1-gen/_goldenpath-ref/evidence/first-paint.png
new file mode 100644
index 00000000..b5f92a93
Binary files /dev/null and b/game-runtime/games/_wg1-gen/_goldenpath-ref/evidence/first-paint.png differ
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-ref/evidence/verdict.json b/game-runtime/games/_wg1-gen/_goldenpath-ref/evidence/verdict.json
new file mode 100644
index 00000000..c2294f0f
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/_goldenpath-ref/evidence/verdict.json
@@ -0,0 +1,42 @@
+{
+  "gameId": "_goldenpath-ref",
+  "url": "http://localhost:4320/games/_wg1-gen/_goldenpath-ref/index.html",
+  "ts": null,
+  "guards": {
+    "A_boot": {
+      "pass": true
+    },
+    "C_frame": {
+      "pass": true,
+      "f0": 73,
+      "f1": 104,
+      "delta": 31
+    },
+    "D_render": {
+      "pass": true,
+      "bright": 1313788,
+      "maxCh": 250
+    },
+    "E_live": {
+      "pass": true,
+      "hash0": "8677bb05",
+      "hash1": "82bc97f4"
+    },
+    "B_uncaught": {
+      "pass": true,
+      "uncaught": []
+    },
+    "F_wiring": {
+      "pass": false,
+      "callCount": 0,
+      "sample": [],
+      "expected": [
+        "math.",
+        "particles.",
+        "audio.synth"
+      ]
+    }
+  },
+  "pass": false,
+  "notes": []
+}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-ref/factory.js b/game-runtime/games/_wg1-gen/_goldenpath-ref/factory.js
new file mode 100644
index 00000000..8ec7d54c
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/_goldenpath-ref/factory.js
@@ -0,0 +1,6 @@
+/**
+ * factory.js —— golden-path:把 ref 工厂(wanglanmei game-shop)喂进 W-G1 通用 harness。
+ * 目的:先用【已知好】的工厂跑通整条「entry-bundle → __GameBundle → bootGameHost → CDP 真玩」链,
+ *   证明 harness 自身可信(六道假绿守卫在真·可玩游戏上确实判 PASS),再喂便宜模型生成物。非交付游戏。
+ */
+export { default } from '../../wanglanmei-ref/src/game-shop.js';
diff --git a/game-runtime/games/_wg1-gen/_goldenpath-ref/index.html b/game-runtime/games/_wg1-gen/_goldenpath-ref/index.html
new file mode 100644
index 00000000..d5dd623c
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/_goldenpath-ref/index.html
@@ -0,0 +1,83 @@
+
+
+
+
+  
+  
+  
+  W-G1 generated game
+  
+
+
+  
+
booting…
+ + +
+ + + + + + diff --git a/game-runtime/games/_wg1-gen/_goldenpath-ref/play-spec.json b/game-runtime/games/_wg1-gen/_goldenpath-ref/play-spec.json new file mode 100644 index 00000000..183282b6 --- /dev/null +++ b/game-runtime/games/_wg1-gen/_goldenpath-ref/play-spec.json @@ -0,0 +1,11 @@ +{ + "_note": "golden-path ref:先不打具体玩法动作,验 harness 在已知好工厂上判 PASS。ref 启动即引擎掌帧+动画(易缓动/粒子),math/particles/audio 任一触发即过 F。", + "inputs": [ + { "t": "wait", "ms": 600 }, + { "t": "tap", "x": 195, "y": 760 }, + { "t": "wait", "ms": 400 }, + { "t": "tap", "x": 195, "y": 420 }, + { "t": "wait", "ms": 400 } + ], + "expectedEngineCallPrefixes": ["math.", "particles.", "audio.synth"] +} diff --git a/game-runtime/games/_wg1-gen/_shared/entry-bundle.template.js b/game-runtime/games/_wg1-gen/_shared/entry-bundle.template.js new file mode 100644 index 00000000..da675cbd --- /dev/null +++ b/game-runtime/games/_wg1-gen/_shared/entry-bundle.template.js @@ -0,0 +1,77 @@ +/** + * entry-bundle.template.js —— W-G1 通用 bundle 入口模板(逐字拷进每个生成 game 目录为 entry-bundle.js) + * owner:W-G1 lane | 消费方:esbuild --global-name=__GameBundle → P1 宿主 bootGameHost 真玩 + * + * ════════════════════════════════════════════════════════════════════════════ + * 【职责】把「生成的游戏工厂 + 通用宿主 + 标准 7 插件 wiring + 引擎」汇成一个 iife 全局 __GameBundle。 + * 产出靶契约(冻结·逐字对齐 entry-bundle.js / game-package.schema.json engineBundle): + * iife 顶层全局名固定 **__GameBundle**;宿主从 window.__GameBundle 取 GameHostFactory 与 bootGameHost。 + * + * 【最大化复用·最小新代码】 + * - 宿主:复用 src/host/boot-game-host.js 的通用 bootGameHost(不改)。 + * - 插件 wiring:用官方 L0 通用装载壳 src/host/generic-host-config.js 的 buildGenericHostConfig(标准 7 插件 + 偏序 + 视口 + 工厂 wiring,与官方 entry-generic.js 同一份), + * override factory 为本目录生成的工厂 → 生成游戏跑在【官方 generic 标准装配】上。 + * - 注:本入口 = 官方 entry-generic.js 的「harness 可取证」超集——多透传 recHook/onReady 供 CDP 八门(F门真接线); + * studio 渠道调 bootGameHost({canvas,seed}) 时 recHook 为空=no-op,feed 照常(一份 bundle 同时服务 feed + 取证门)。 + * - 引擎:Option C 动态 import(node import 本入口不触引擎,保 import-safe;esbuild 把引擎内联进单文件 iife)。 + * + * 【Q4 铁律】本入口是「集成段 host」唯一引擎 import 落点(动态 import 后经 opts.engine 注入); + * ./factory.js 游戏工厂零引擎 import,能力一律经 boot.ctx.getEngine()。 + * ════════════════════════════════════════════════════════════════════════════ + */ + +'use strict'; + +// 通用宿主(引擎骨架参数化;本身零引擎 import,引擎经 opts.engine 注入)。 +import { bootGameHost as bootGameHostCore } from '../../../src/host/boot-game-host.js'; +// 标准插件装配(官方 L0 通用装载壳 buildGenericHostConfig:collision/physics/gamefeel/juice/palettePost/audioMusic/save + 偏序 + 390×844 视口;零 wanglanmei 专属)。 +import { buildGenericHostConfig } from '../../../src/host/generic-host-config.js'; +// 本目录生成的游戏工厂(默认导出 GameHostFactory,零引擎 import,A3 硬独立文件;官方靶名 generated-factory.js)。 +import gameFactory from './generated-factory.js'; + +/** 【契约导出】GameHostFactory:宿主从 window.__GameBundle.GameHostFactory 取它(契约冻结)。= 本目录生成的工厂。 */ +export const GameHostFactory = gameFactory; +// 默认导出同为 GameHostFactory(便于 import default 取用;与具名导出同一引用)。 +export default gameFactory; + +/** + * 【P2/W-G1 boot 入口】供 host 页在浏览器内启动本 bundle(引擎由本 bundle 注入后驱动)。 + * - 动态 import 引擎(Option C):调用时才求值,esbuild 已把引擎内联进本 bundle(无外部请求)。 + * - engineMode 强制 'real'(W-G1 真玩取证一律引擎掌帧)。 + * - 插件/视口/工厂 wiring 取自 buildRefHostConfig(与 ref 同一标准集),factory override 为生成工厂。 + * - recHook / onReady 透传:供取证 harness 注入「引擎 call-ID 探针」与「internals(uncaught) 收集」(假绿守卫)。 + * + * @param {Object} opts host 页传入入参。 + * @param {HTMLCanvasElement} opts.canvas 页面 #game 画布(real 通道引擎自建 mainCanvas#game-engine,本 canvas 作占位/输入兜底)。 + * @param {HTMLElement} [opts.statusEl] 状态行(可空)。 + * @param {number} [opts.seed] 主随机种子(缺省固定值,保确定性)。 + * @param {Function} [opts.recHook] 引擎 call-ID 取证钩子 id=>void(取证路径注入 window.__engineCalls.push;渠道产物不注)。 + * @param {Function} [opts.onReady] (host, internals)=>void 就绪回调(取证收集 internals.uncaught 等)。 + * @param {any} [opts.engine] 覆盖引擎名字空间(缺省动态 import littlejsengine)。 + * @returns {Promise} bootGameHost 的 host 句柄(frameCount/stepFrames/tap/do/state 等)。 + */ +export async function bootGameHost(opts) { + const o = opts || {}; + // 动态 import 引擎:求值时机延后到本函数被调用(浏览器运行期)。esbuild 内联,无外部请求。 + const engine = o.engine || (await import('littlejsengine')); + // 主随机种子(缺省固定值,与 ref 取证同口径,保确定性可复现)。 + const seed = (o.seed != null ? o.seed : 0x1234abcd) >>> 0; + // 官方 generic 标准装配(7 插件 + 偏序 + 视口 + 工厂 wiring;与 entry-generic.js 同一 buildGenericHostConfig)。 + const cfg = buildGenericHostConfig({ seed }); + // 调通用宿主:real 通道引擎掌帧;factory override 为本目录生成工厂;其余 wiring 取标准集。 + return bootGameHostCore({ + canvas: o.canvas, + statusEl: o.statusEl || null, + engine, + seed, + mode: o.mode || 'play', // W-G1 真玩=play + engineMode: 'real', // 一律引擎掌帧(real 通道) + viewport: cfg.viewport, // 390×844(与 ref 同,移动竖屏基准) + factory: gameFactory, // ★ override:本目录【生成的游戏】(其余 wiring 全复用 ref) + plugins: cfg.plugins, // 标准 7 插件实例集(经 opts.runtime.plugins 注入给工厂) + registerOrder: cfg.registerOrder, // 注册偏序(保六锚) + buildFactoryOpts: cfg.buildFactoryOpts, // 注入 runtime:{plugins,bundle,getRealAudioCtx} + recHook: o.recHook || null, // 取证:引擎 call-ID 探针(默认 no-op) + onReady: o.onReady || null, // 取证:收集 internals(uncaught) + }); +} diff --git a/game-runtime/games/_wg1-gen/_shared/index.template.html b/game-runtime/games/_wg1-gen/_shared/index.template.html new file mode 100644 index 00000000..cc622a84 --- /dev/null +++ b/game-runtime/games/_wg1-gen/_shared/index.template.html @@ -0,0 +1,89 @@ + + + + + + + + W-G1 generated game + + + +
+
booting…
+ + +
+ + + + + + diff --git a/game-runtime/games/_wg1-gen/_shared/play.cdp.cjs b/game-runtime/games/_wg1-gen/_shared/play.cdp.cjs new file mode 100644 index 00000000..5cc82cc8 --- /dev/null +++ b/game-runtime/games/_wg1-gen/_shared/play.cdp.cjs @@ -0,0 +1,414 @@ +/** + * play.cdp.cjs —— W-G1 通用「CDP 真玩取证驱动」(模型无关,所有生成游戏共用一份) + * owner:W-G1 lane | cwd 必须 = game-runtime | 复用 test/harness/browser-evidence.cjs + * + * ════════════════════════════════════════════════════════════════════════════ + * 【职责】把一个 __GameBundle iife 装进 P1 宿主页、经 CDP 驱动本机 Chrome 真玩几步,产出四件套证据, + * 并以「九道假绿守卫」判定是否【真·可玩】——"能生成代码 ≠ 能玩",必须过真玩门才算 pass。 + * 真玩驱动:spec.driver 存在=【适配性真玩】(读 state 自动接球,解盲打固定坐标打不动技巧游戏的假阴性);否则走 spec.inputs 固定序列。 + * + * 【九道假绿守卫(全过才 PASS)】 + * A 装载:__genBooted===true ∧ __gameHostEngineInitFired===true ∧ 无 bootError(白屏/装载失败拦截)。 + * B 未捕获:__genInternals.uncaught 为空 ∧ 无 __gameHostBootError(运行期报错拦截)。 + * C 掌帧:__engine.snapshot().frame 在 500ms 内增量 ∈ [20,45](活着且非失控/非单步假推进;@60fps 理论~30)。 + * D 真渲染:#game-engine canvas readback「有色像素(maxCh>80) > 阈值」(非白屏/非全黑)。 + * E 活性:真玩输入前后两张快照 FNV-1a 哈希【不同】(画面真在动/真在响应,非冻屏)。 + * F 真接线:__engineCalls 含期望 call-ID(spec.expectedEngineCallPrefixes 任一前缀命中;证真经 ctx.getEngine() 调引擎/插件库,非自绘伪装)。 + * G 输入有效:同 URL 同 seed 起【无输入】对照实例推进到同帧号,整帧哈希【不同】 ⇒ 输入真改变游戏走向(隔离「靠自走动画蒙混过 E」)。 + * H 机制进展 + latch 终态(逐游戏·确定性·可选):spec.assertAfterPlay[] 机制断言全过(真有进展、非空壳)+ spec.expectLatch 时真玩到 phase='gameover' 且【驻留】(官方闭环锚)。 + * 依赖游戏经【可选 _forensicsView()】导出可观测状态(host.state() 透传 → 页面 __gameState);未声明=老游戏→SKIP(向后兼容)。 + * I 控制跟手(逐游戏·确定性·可选):spec.controlCheck 声明时,连点目标 x 验玩家控制体平滑逼近(逮「一格一跳」/卡死/不跟手);依赖游戏导出控制体位置(如 paddle.x)。未声明→SKIP。 + * + * 【用法】node games/_wg1-gen/_shared/play.cdp.cjs [--base=http://localhost:4320] [--cdp=http://localhost:9222] [--spec=] + * spec.json(缺省读 games/_wg1-gen//play-spec.json,缺失则用极简默认): + * { "inputs":[{"t":"tap","x":195,"y":600},{"t":"key","code":"ArrowLeft","downMs":300},{"t":"wait","ms":400}], + * "expectedEngineCallPrefixes":["particles.spawnEmitter","audio.synth"] } + * 产物:games/_wg1-gen//evidence/{verdict.json, first-paint.png, after-play.png};退出码 0=PASS / 1=FAIL。 + * ════════════════════════════════════════════════════════════════════════════ + */ + +'use strict'; + +const path = require('node:path'); +const http = require('node:http'); +const fs = require('node:fs'); +// 复用纯计算口径 + CDP 会话类 + 像素抓取/截图(test/harness/browser-evidence.cjs)。 +const H = require(path.resolve(__dirname, '../../../test/harness/browser-evidence.cjs')); +const { CdpSession, captureImageData, saveScreenshot, fnv1a32 } = H; +// CDP 需 ws(仅本驱动用;cwd=game-runtime 已 npm i ws)。 +const WebSocket = require('ws'); + +/** 纯 Promise 延时(不走被拦的 sleep 命令)。 */ +const delay = (ms) => new Promise((r) => setTimeout(r, ms)); + +/** 极简 HTTP(PUT 建 target / GET 列表)。browser-evidence 的 httpJson 未导出,此处复刻。 */ +function httpJson(method, urlStr) { + return new Promise((resolve, reject) => { + const u = new URL(urlStr); + const req = http.request( + { hostname: u.hostname, port: u.port, path: u.pathname + u.search, method, timeout: 15000 }, + (res) => { let b = ''; res.on('data', (c) => (b += c)); res.on('end', () => { + try { resolve(b ? JSON.parse(b) : {}); } catch (e) { reject(new Error('CDP HTTP 非 JSON:' + b.slice(0, 200))); } }); } + ); + req.on('error', reject); + req.on('timeout', () => req.destroy(new Error('CDP HTTP 超时:' + urlStr))); + req.end(); + }); +} + +/** 建 target → 连 WS → 启用域 → 设固定取证视口(390×844/DPR2/touch)→ 导航。返回 CdpSession。 */ +async function connect(url, cdpHttp) { + // Chrome 111+ 必须 PUT /json/new?(GET 不行)。 + const created = await httpJson('PUT', `${cdpHttp}/json/new?${encodeURI('about:blank')}`); + const wsUrl = created.webSocketDebuggerUrl; + if (!wsUrl) throw new Error('建 target 失败(无 webSocketDebuggerUrl):' + JSON.stringify(created).slice(0, 200)); + const ws = await new Promise((resolve, reject) => { + const s = new WebSocket(wsUrl, { maxPayload: 256 * 1024 * 1024 }); + s.on('open', () => resolve(s)); s.on('error', reject); + }); + const cdp = new CdpSession(ws, created.id); + await cdp.send('Page.enable'); + await cdp.send('Runtime.enable'); + await cdp.send('Emulation.setDeviceMetricsOverride', { width: 390, height: 844, deviceScaleFactor: 2, mobile: true }); + try { await cdp.send('Emulation.setTouchEmulationEnabled', { enabled: true, maxTouchPoints: 1 }); } catch (_) {} + await cdp.send('Page.navigate', { url }); + return cdp; +} + +/** 守卫A:轮询等装载完成(__genBooted ∧ 引擎接管 __gameHostEngineInitFired);拿到任一 bootError 即抛。 */ +async function waitBoot(cdp, timeoutMs) { + const deadline = Date.now() + (timeoutMs || 30000); + await delay(800); // 固定 settle,让脚本起步 + while (Date.now() < deadline) { + const st = await cdp.evaluate( + '({ booted: !!window.__genBooted, eng: !!window.__gameHostEngineInitFired, ' + + 'err: (window.__genBootError || window.__gameHostBootError || null) })' + ); + if (st && st.err) throw new Error('装载失败(守卫A):' + st.err); + if (st && st.booted && st.eng) return; + await delay(300); + } + // 超时前再读一次错因,给确切信号。 + const last = await cdp.evaluate('({ booted: !!window.__genBooted, eng: !!window.__gameHostEngineInitFired, err: (window.__genBootError||window.__gameHostBootError||null) })').catch(() => null); + throw new Error('装载超时(守卫A):' + JSON.stringify(last)); +} + +/** 守卫C:测 500ms 内引擎帧增量。读 window.__engine.snapshot().frame(real 通道)。 */ +async function frameDelta(cdp, ms) { + const read = '(function(){ var e=window.__engine; if(!e) return null; var s=(typeof e.snapshot==="function")?e.snapshot():e; return (s&&typeof s.frame==="number")?s.frame:null; })()'; + const f0 = await cdp.evaluate(read); + await delay(ms); + const f1 = await cdp.evaluate(read); + return { f0, f1, delta: (f0 == null || f1 == null) ? null : (f1 - f0) }; +} + +/** 推进(对照)实例到目标帧号(real 引擎自走,轮询 __engine.frame)。返回到达的帧号(-1=超时)。 */ +async function advanceToFrame(cdp, targetFrame, timeoutMs) { + const read = '(function(){var e=window.__engine;var s=(e&&typeof e.snapshot==="function")?e.snapshot():e;return (s&&typeof s.frame==="number")?s.frame:0;})()'; + const deadline = Date.now() + (timeoutMs || 15000); + while (Date.now() < deadline) { + const f = await cdp.evaluate(read); + if (f >= targetFrame) return f; + await delay(100); + } + return -1; +} + +/** 守卫D:#game-engine readback,统计「有色像素(maxCh>80)」数 + 全屏最亮通道值。 */ +async function brightPixels(cdp, selector) { + const img = await captureImageData(cdp, selector); + const d = img.data; let bright = 0, maxCh = 0; + for (let i = 0; i < d.length; i += 4) { + if (d[i + 3] === 0) continue; + const m = Math.max(d[i], d[i + 1], d[i + 2]); + if (m > maxCh) maxCh = m; + if (m > 80) bright++; + } + return { bright, maxCh, hash: fnv1a32(d), width: img.width, height: img.height }; +} + +/** 轻量采样:只取 #game-engine 的 FNV 哈希(守卫E 多采样用,捕捉瞬时闪烁/命中态)。 */ +async function sampleHash(cdp, selector) { + const img = await captureImageData(cdp, selector); + return fnv1a32(img.data); +} + +/** 逻辑坐标 → 页面 client 坐标(镜像 ref toClient:用画布自身逻辑尺寸 c.width/dpr 算缩放,不硬编码 390/844)。 */ +async function mapToClient(cdp, xLogical, yLogical) { + const m = await cdp.evaluate( + '(function(){ var c=document.querySelector("#game-engine")||document.querySelector("#game"); if(!c) return null;' + + ' var r=c.getBoundingClientRect(); var dpr=window.devicePixelRatio||1;' + + ' return { l:r.left, t:r.top, sx:r.width/(c.width/dpr), sy:r.height/(c.height/dpr) }; })()' + ); + if (!m) throw new Error('mapToClient:找不到 #game-engine/#game'); + return { x: m.l + xLogical * m.sx, y: m.t + yLogical * m.sy }; +} + +/** 真触摸点按(touchStart→touchEnd 背靠背 + 裸 {x,y} 点;镜像 ref realTapAt 证可用范式)。 */ +async function tap(cdp, xLogical, yLogical) { + const c = await mapToClient(cdp, xLogical, yLogical); + await cdp.send('Input.dispatchTouchEvent', { type: 'touchStart', touchPoints: [{ x: c.x, y: c.y }] }); + await cdp.send('Input.dispatchTouchEvent', { type: 'touchEnd', touchPoints: [] }); + await delay(120); // 等真事件经浏览器→输入桥→引擎下一拍消化 +} + +/** 真键按(keyDown→downMs→keyUp)。code=DOM code(如 ArrowLeft/Space/KeyA)。 */ +async function key(cdp, code, downMs) { + const map = { ArrowLeft: 37, ArrowRight: 39, ArrowUp: 38, ArrowDown: 40, Space: 32, Enter: 13 }; + const keyCode = map[code] || 0; + const k = code === 'Space' ? ' ' : (code && code.startsWith('Arrow')) ? undefined : code; + await cdp.send('Input.dispatchKeyEvent', { type: 'keyDown', code, key: k, windowsVirtualKeyCode: keyCode, nativeVirtualKeyCode: keyCode }); + await delay(downMs || 200); + await cdp.send('Input.dispatchKeyEvent', { type: 'keyUp', code, key: k, windowsVirtualKeyCode: keyCode, nativeVirtualKeyCode: keyCode }); +} + +/** 读游戏可观测状态(可测性红线:游戏经 _forensicsView().state 导出 → host.state() 透传 → 页面 __gameState 别名)。读不到返回 null。 */ +async function readGameState(cdp) { + return await cdp.evaluate( + '(function(){ try {' + + ' var s = (typeof window.__gameState === "function") ? window.__gameState()' + + ' : (window.__genHost && typeof window.__genHost.state === "function") ? window.__genHost.state() : null;' + + ' return s; } catch (e) { return null; } })()' + ); +} + +/** 判一条机制断言(s0=玩前态 / s1=玩后态)。op:increased/decreased/changed/>/>=/ (typeof x === 'number' ? x : Number(x)); + let pass = false; + switch (a.op) { + case 'increased': pass = num(v1) > num(v0); break; // 玩后 > 玩前(如分数上升) + case 'decreased': pass = num(v1) < num(v0); break; // 玩后 < 玩前(如剩余砖数下降) + case 'changed': pass = v1 !== v0; break; // 任意变化 + case '>': pass = num(v1) > num(a.value); break; + case '>=': pass = num(v1) >= num(a.value); break; + case '<': pass = num(v1) < num(a.value); break; + case '<=': pass = num(v1) <= num(a.value); break; + case '==': pass = v1 === a.value; break; + case 'in': case 'reached': pass = Array.isArray(a.value) && a.value.indexOf(v1) >= 0; break; // 取值落在允许集(如 status∈[playing,win,lose]) + default: pass = false; + } + return { path: p, op: a.op, before: v0, after: v1, value: a.value, pass, why: a.why || '' }; +} + +/** 读嵌套路径(如 'ball.x' / 'paddle.x');任一层缺失返回 undefined。 */ +function getPath(obj, p) { + if (!obj || !p) return undefined; + return String(p).split('.').reduce((o, k) => (o == null ? undefined : o[k]), obj); +} + +/** 适配性真玩驱动:读 state 自适应出招,解「盲打固定坐标打不动技巧游戏」的假阴性。 + * type='paddle-intercept':每步读球 x、tap 到球正下方把挡板移过去接(真玩到清砖);到 gameover 即停。 */ +async function runDriver(cdp, driver, hashes) { + const ballPath = driver.ballPath || 'ball.x'; + const paddleY = driver.paddleY != null ? driver.paddleY : 800; + const steps = driver.steps || 60; + const stepMs = driver.stepMs || 130; + let drove = 0; + for (let i = 0; i < steps; i++) { + const s = await readGameState(cdp); + if (s && s.phase === 'gameover') break; // 已结束,停(剩交给 latch 校验) + const bx = getPath(s, ballPath); + if (typeof bx === 'number') { await tap(cdp, Math.max(8, Math.min(382, bx)), paddleY); drove++; } + else { await delay(stepMs); } // 读不到球位=游戏没导出位置,空转(H 门会判红线) + try { hashes.push(await sampleHash(cdp, '#game-engine')); } catch (_) {} + await delay(stepMs); + } + return { drove, steps }; +} + +/** 控制跟手校验(守卫I):连点目标 x,读玩家控制体位置是否平滑逼近(逮「一格一跳」/卡死/不跟手)。 */ +async function runControlCheck(cdp, cc) { + const ppath = cc.paddlePath || 'paddle.x'; + const paddleY = cc.paddleY != null ? cc.paddleY : 800; + const taps = cc.tapsPerTarget || 6; + const moveMin = cc.moveMin != null ? cc.moveMin : 25; + const tol = cc.tolerance != null ? cc.tolerance : 70; + const results = []; + for (const tx of (cc.tapXs || [50, 340])) { + const before = getPath(await readGameState(cdp), ppath); + for (let k = 0; k < taps; k++) { await tap(cdp, tx, paddleY); await delay(120); } + const after = getPath(await readGameState(cdp), ppath); + const moved = (typeof before === 'number' && typeof after === 'number') ? (after - before) : null; + const dist = (typeof after === 'number') ? Math.abs(after - tx) : null; + // 跟手 = 朝 tx 移动了可观距离(|moved|≥moveMin) 且 最终落在容差内(dist≤tol);一格一跳=moved 太小→判否。 + const ok = moved != null && dist != null && Math.abs(moved) >= moveMin && dist <= tol; + results.push({ tapX: tx, before, after, moved, distToTarget: dist, pass: ok }); + } + return { pass: results.length > 0 && results.every((r) => r.pass), paddlePath: ppath, results }; +} + +async function main() { + const argv = process.argv.slice(2); + const gameId = argv[0]; + if (!gameId) { console.error('用法:node play.cdp.cjs [--base=] [--cdp=] [--spec=]'); process.exit(2); } + const getArg = (k, def) => { const a = argv.find((x) => x.startsWith(k + '=')); return a ? a.split('=').slice(1).join('=') : def; }; + const base = getArg('--base', 'http://localhost:4320'); + const cdpHttp = getArg('--cdp', 'http://localhost:9222'); + const gameDir = path.resolve('games/_wg1-gen', gameId); + const evDir = path.join(gameDir, 'evidence'); + fs.mkdirSync(evDir, { recursive: true }); + + // 读 play-spec(缺省极简:无输入,仅验活性/掌帧/渲染/接线)。 + const specPath = getArg('--spec', path.join(gameDir, 'play-spec.json')); + let spec = { inputs: [], expectedEngineCallPrefixes: [] }; + try { spec = JSON.parse(fs.readFileSync(specPath, 'utf8')); } catch (_) { /* 用默认 */ } + + const url = `${base}/games/_wg1-gen/${gameId}/index.html`; + const verdict = { gameId, url, ts: null, guards: {}, pass: false, notes: [] }; + let cdp = null; + try { + cdp = await connect(url, cdpHttp); + // 守卫A:装载 + 引擎接管。 + await waitBoot(cdp, 30000); + verdict.guards.A_boot = { pass: true }; + + // 首帧截图 + 渲染快照(守卫D 初值 + 守卫E t0)。 + await saveScreenshot(cdp, path.join(evDir, 'first-paint.png')); + const px0 = await brightPixels(cdp, '#game-engine'); + // 守卫H 玩前态:真玩输入前读一次可观测状态(基线,供机制断言对照)。 + const state0 = await readGameState(cdp); + + // 守卫C:掌帧增量。 + const fd = await frameDelta(cdp, 500); + verdict.guards.C_frame = { pass: fd.delta != null && fd.delta >= 20 && fd.delta <= 45, ...fd }; + + // 守卫I:控制跟手(声明 controlCheck 才启用)—— 读玩家控制体位置,验「点哪、挡板平滑跟到哪」,逮一格一跳/卡死/不跟手。 + if (spec.controlCheck) { + verdict.guards.I_control = await runControlCheck(cdp, spec.controlCheck); + } else { + verdict.guards.I_control = { pass: true, skipped: '未声明 controlCheck(向后兼容)' }; + } + + // 真玩:有 driver 走【适配性驱动】(读 state 自动接球,真玩技巧游戏,解盲打假阴性);否则走固定输入序列。每步采帧哈希供守卫E。 + const hashes = [px0.hash]; + if (spec.driver) { + await runDriver(cdp, spec.driver, hashes); + } else { + for (const ev of (spec.inputs || [])) { + if (ev.t === 'tap') await tap(cdp, ev.x, ev.y); + else if (ev.t === 'key') await key(cdp, ev.code, ev.downMs); + else if (ev.t === 'wait') await delay(ev.ms || 200); + try { hashes.push(await sampleHash(cdp, '#game-engine')); } catch (_) {} + await delay(50); + } + } + await delay(250); + + // 守卫D:真渲染(输入后再测,取较优)。 + const px1 = await brightPixels(cdp, '#game-engine'); + hashes.push(px1.hash); + const bright = Math.max(px0.bright, px1.bright), maxCh = Math.max(px0.maxCh, px1.maxCh); + verdict.guards.D_render = { pass: bright > 50 && maxCh > 80, bright, maxCh }; + + // 守卫E:活性 —— 整段真玩出现 ≥2 个不同画面态(真在动/真在响应);全程恒同一帧=冻屏判否。 + const distinct = new Set(hashes); + verdict.guards.E_live = { pass: distinct.size >= 2, distinctStates: distinct.size, samples: hashes.length }; + + // 守卫B:未捕获错误。 + const unc = await cdp.evaluate('(function(){ var n=window.__genInternals; var u=(n&&n.uncaught)?n.uncaught:[]; return u.slice(0,10); })()'); + verdict.guards.B_uncaught = { pass: Array.isArray(unc) && unc.length === 0, uncaught: unc }; + + // 守卫F:真接线(在页面内扫【全量】__engineCalls,避免 math.lerp 每帧刷屏把后续 gameplay 调用挤出 200 切片)。 + const prefixes = spec.expectedEngineCallPrefixes || []; + const fw = await cdp.evaluate( + '(function(){ var c=window.__engineCalls||[]; var pre=' + JSON.stringify(prefixes) + ';' + + ' var hit=pre.length? c.some(function(x){return pre.some(function(p){return String(x).indexOf(p)===0;});}) : c.length>0;' + + ' var nonLerp=c.filter(function(x){return String(x).indexOf("math.lerp")!==0;});' + + ' return { hit:hit, total:c.length, sample:(nonLerp.length?nonLerp:c).slice(0,12) }; })()' + ); + verdict.guards.F_wiring = { pass: !!(fw && fw.hit), callCount: (fw && fw.total) || 0, sample: (fw && fw.sample) || [], expected: prefixes }; + + // 守卫H 玩后态:真玩输入后读一次可观测状态(与 state0 对照,判机制是否真有进展)。 + const state1 = await readGameState(cdp); + + await saveScreenshot(cdp, path.join(evDir, 'after-play.png')); + + // 守卫G:输入有效性(确定性 A/B 对照,隔离「靠自走动画蒙混过 E」的假绿)。 + // 同 URL 同 seed 再开一个【无输入】对照实例,推进到与输入实例【同一帧号】,比对整帧哈希: + // 不同 ⇒ 输入真改变了游戏走向(挡板位置/Simon 轮次/打地鼠分数都会持续到该帧);相同 ⇒ 输入无效(判否)。 + const hasInput = !!spec.driver || (spec.inputs || []).some((e) => e.t === 'tap' || e.t === 'key'); + if (hasInput) { + let ctrl = null; + try { + const endFrame = await cdp.evaluate('(function(){var e=window.__engine;var s=(e&&typeof e.snapshot==="function")?e.snapshot():e;return (s&&typeof s.frame==="number")?s.frame:0;})()'); + ctrl = await connect(url, cdpHttp); + await waitBoot(ctrl, 30000); + const reached = await advanceToFrame(ctrl, endFrame, 20000); + const ch = await brightPixels(ctrl, '#game-engine'); + verdict.guards.G_input = { pass: px1.hash !== ch.hash, inputHash: px1.hash, controlHash: ch.hash, atFrame: endFrame, ctrlFrame: reached }; + } catch (e2) { + verdict.guards.G_input = { pass: false, err: String((e2 && e2.message) || e2) }; + } finally { + if (ctrl) ctrl.close(); + } + } else { + verdict.guards.G_input = { pass: true, skipped: '无 tap/key 输入' }; + } + + // 守卫H:机制进展 + P0 latch 终态(逐游戏确定性)—— 隔离「七门全过但空心」漂亮空壳 + 验官方 latch 终态契约(闭环锚)。 + // spec.assertAfterPlay[] = 进展断言(remaining↓ 等,证非空心);spec.expectLatch=true = 须真玩到 phase='gameover' 且【驻留】。 + // 二者皆未声明=老游戏→SKIP(向后兼容);声明了却读不到 state(未实现 _forensicsView)=可测性红线违约→判否。 + const asserts = spec.assertAfterPlay || []; + const expectLatch = spec.expectLatch === true; + if (asserts.length === 0 && !expectLatch) { + verdict.guards.H_progress = { pass: true, skipped: '未声明 assertAfterPlay/expectLatch(向后兼容)' }; + } else if (!state1 || state1.phase === 'booting') { + verdict.guards.H_progress = { pass: false, err: '声明了机制门但游戏未经 _forensicsView() 导出可观测状态(可测性红线未满足)', state0, state1 }; + } else { + const checks = asserts.map((a) => checkAssertion(a, state0, state1)); + let latch = null; + if (expectLatch) { + // 停止输入后轮询等进入 gameover(无失败态/永不结束=终态不可达=判否);最多 ~4.2s。 + let phaseNow = state1.phase; + for (let i = 0; i < 14 && phaseNow !== 'gameover'; i++) { await delay(300); const s = await readGameState(cdp); phaseNow = s ? s.phase : null; } + if (phaseNow !== 'gameover') { + latch = { pass: false, reason: '真玩未到达 gameover 终态(终态不可达/无失败态/play-spec 未驱动到结束)', phaseNow }; + } else { + // latch 驻留校验:再等 600ms,phase 必须仍 'gameover'(瞬时终态/自动重开=违约,宿主 500ms 轮询会漏读)。 + await delay(600); + const s2 = await readGameState(cdp); + const dwell = !!(s2 && s2.phase === 'gameover'); + latch = { pass: dwell, dwelledMs: 600, after: s2 ? s2.phase : null, reason: dwell ? '' : 'gameover 未驻留(下帧自动重开/复位=latch 违约)' }; + } + } + const progressPass = checks.every((c) => c.pass); + const latchPass = !expectLatch || !!(latch && latch.pass); + verdict.guards.H_progress = { pass: progressPass && latchPass, checks, latch, state0, state1 }; + } + + verdict.pass = ['A_boot', 'B_uncaught', 'C_frame', 'D_render', 'E_live', 'F_wiring', 'G_input', 'H_progress', 'I_control'] + .every((g) => verdict.guards[g] && verdict.guards[g].pass); + } catch (e) { + verdict.error = String((e && e.message) || e); + verdict.guards.A_boot = verdict.guards.A_boot || { pass: false, err: verdict.error }; + } finally { + if (cdp) cdp.close(); + } + + fs.writeFileSync(path.join(evDir, 'verdict.json'), JSON.stringify(verdict, null, 2)); + // 控制台四件套摘要。 + const g = verdict.guards; + console.log(`\n=== W-G1 真玩判定 [${gameId}] ${verdict.pass ? '✅ PASS' : '❌ FAIL'} ===`); + const line = (k, ok, extra) => console.log(` ${ok ? '✅' : '❌'} ${k} ${extra || ''}`); + if (g.A_boot) line('A 装载', g.A_boot.pass, g.A_boot.err || ''); + if (g.B_uncaught) line('B 未捕获', g.B_uncaught.pass, `uncaught=${(g.B_uncaught.uncaught || []).length}`); + if (g.C_frame) line('C 掌帧', g.C_frame.pass, `Δframe=${g.C_frame.delta} (期望[20,45])`); + if (g.D_render) line('D 真渲染', g.D_render.pass, `bright=${g.D_render.bright} maxCh=${g.D_render.maxCh}`); + if (g.E_live) line('E 活性', g.E_live.pass, `distinct=${g.E_live.distinctStates}/${g.E_live.samples} 帧态`); + if (g.F_wiring) line('F 真接线', g.F_wiring.pass, `calls=${g.F_wiring.callCount} sample=${JSON.stringify((g.F_wiring.sample || []).slice(0, 4))}`); + if (g.G_input) line('G 输入有效', g.G_input.pass, g.G_input.skipped || (g.G_input.err ? g.G_input.err : `输入态${g.G_input.inputHash}≠对照${g.G_input.controlHash}@f${g.G_input.atFrame}`)); + if (g.H_progress) line('H 机制+latch', g.H_progress.pass, g.H_progress.skipped || g.H_progress.err || + ((g.H_progress.checks || []).map((c) => `${c.path}:${JSON.stringify(c.before)}→${JSON.stringify(c.after)}[${c.op}${c.pass ? '✓' : '✗'}]`).join(' ') + + (g.H_progress.latch ? ` latch[${g.H_progress.latch.pass ? '✓驻留' : '✗' + (g.H_progress.latch.reason || '')}]` : ''))); + if (g.I_control) line('I 控制跟手', g.I_control.pass, g.I_control.skipped || + (g.I_control.results || []).map((r) => `tap${r.tapX}:move${r.moved == null ? '?' : Math.round(r.moved)}→dist${r.distToTarget == null ? '?' : Math.round(r.distToTarget)}[${r.pass ? '✓' : '✗'}]`).join(' ')); + if (verdict.error) console.log(' ⚠️ error:', verdict.error); + console.log(` evidence → ${path.relative(process.cwd(), evDir)}/`); + process.exit(verdict.pass ? 0 : 1); +} + +main(); diff --git a/game-runtime/games/_wg1-gen/_shared/serve-and-play.sh b/game-runtime/games/_wg1-gen/_shared/serve-and-play.sh new file mode 100644 index 00000000..6de80709 --- /dev/null +++ b/game-runtime/games/_wg1-gen/_shared/serve-and-play.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# serve-and-play.sh —— W-G1 真玩取证一键编排(macOS 本机,无 systemd → 普通后台进程 + trap 清理) +# owner:W-G1 lane | cwd 必须 = game-runtime +# 用法:bash games/_wg1-gen/_shared/serve-and-play.sh [port] [cdpPort] +# 流程:净场 → 起 static-serve(game-runtime 根) → 起 headless Chrome → 等就绪 → play.cdp.cjs → trap 清理,返 play 退出码。 +set -u +GAME_ID="${1:?用法: serve-and-play.sh [port] [cdpPort]}" +PORT="${2:-4320}" +CDP_PORT="${3:-9222}" + +# Chrome 路径探测(macOS)。 +CHROME="" +for p in "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \ + "/Applications/Chromium.app/Contents/MacOS/Chromium" \ + "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"; do + [ -x "$p" ] && CHROME="$p" && break +done +[ -z "$CHROME" ] && { echo "❌ 未找到 Chrome(/Applications/Google Chrome.app)"; exit 3; } + +USER_DATA_DIR="$(mktemp -d -t wg1-chrome-XXXX)" +SERVE_PID=""; CHROME_PID="" +cleanup() { + [ -n "$CHROME_PID" ] && kill "$CHROME_PID" 2>/dev/null + [ -n "$SERVE_PID" ] && kill "$SERVE_PID" 2>/dev/null + rm -rf "$USER_DATA_DIR" 2>/dev/null +} +trap cleanup EXIT INT TERM + +# 净场:杀掉占用端口的旧进程(保守,仅杀本脚本端口相关)。 +lsof -ti tcp:"$PORT" 2>/dev/null | xargs kill 2>/dev/null || true +lsof -ti tcp:"$CDP_PORT" 2>/dev/null | xargs kill 2>/dev/null || true +sleep 0.3 + +# 1) 静态服务器:serve game-runtime 根(cwd)。'/'→index.html,拒路径穿越。 +node test/harness/static-serve.cjs . "$PORT" >/tmp/wg1-serve-$PORT.log 2>&1 & +SERVE_PID=$! + +# 2) Chrome headless(CDP 必备旗标:--remote-allow-origins=* + --autoplay-policy=...,否则 WS 连不上/音频卡 suspended)。 +"$CHROME" --headless=new --no-sandbox --no-zygote --disable-gpu \ + --remote-debugging-port="$CDP_PORT" --remote-allow-origins='*' \ + --autoplay-policy=no-user-gesture-required \ + --user-data-dir="$USER_DATA_DIR" about:blank >/tmp/wg1-chrome-$PORT.log 2>&1 & +CHROME_PID=$! + +# 3) 就绪等待(先就绪 10×0.5s,避免抢在 listen 前误判)。 +ok_serve=0; ok_cdp=0 +for i in $(seq 1 20); do + curl -sf "http://localhost:$PORT/games/_wg1-gen/$GAME_ID/index.html" -o /dev/null 2>/dev/null && ok_serve=1 + curl -sf "http://localhost:$CDP_PORT/json/version" -o /dev/null 2>/dev/null && ok_cdp=1 + [ "$ok_serve" = 1 ] && [ "$ok_cdp" = 1 ] && break + sleep 0.5 +done +[ "$ok_serve" != 1 ] && { echo "❌ static-serve 未就绪(见 /tmp/wg1-serve-$PORT.log)"; cat /tmp/wg1-serve-$PORT.log; exit 4; } +[ "$ok_cdp" != 1 ] && { echo "❌ Chrome CDP 未就绪(见 /tmp/wg1-chrome-$PORT.log)"; tail -5 /tmp/wg1-chrome-$PORT.log; exit 5; } + +# 4) 真玩驱动。 +node games/_wg1-gen/_shared/play.cdp.cjs "$GAME_ID" --base="http://localhost:$PORT" --cdp="http://localhost:$CDP_PORT" +PLAY_RC=$? +exit "$PLAY_RC" diff --git a/game-runtime/games/_wg1-gen/pong/bundle.iife.js b/game-runtime/games/_wg1-gen/pong/bundle.iife.js new file mode 100644 index 00000000..34250f2d --- /dev/null +++ b/game-runtime/games/_wg1-gen/pong/bundle.iife.js @@ -0,0 +1,34 @@ +"use strict";var __GameBundle=(()=>{var So=Object.defineProperty;var $l=Object.getOwnPropertyDescriptor;var Yl=Object.getOwnPropertyNames;var Xl=Object.prototype.hasOwnProperty;var Kl=(t,e,n)=>()=>{if(n)throw n[0];try{return t&&(e=t(t=0)),e}catch(s){throw n=[s],s}};var Ba=(t,e)=>{for(var n in e)So(t,n,{get:e[n],enumerable:!0})},Ql=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Yl(e))!Xl.call(t,i)&&i!==n&&So(t,i,{get:()=>e[i],enumerable:!(s=$l(e,i))||s.enumerable});return t};var Zl=t=>Ql(So({},"__esModule",{value:!0}),t);var Wl={};Ba(Wl,{ASSERT:()=>y,BLACK:()=>me,BLUE:()=>dl,Box2dDistanceJoint:()=>Zi,Box2dFrictionJoint:()=>Jr,Box2dGearJoint:()=>Fr,Box2dJoint:()=>ot,Box2dKinematicObject:()=>Rr,Box2dMotorJoint:()=>zr,Box2dObject:()=>Zs,Box2dPinJoint:()=>Or,Box2dPlugin:()=>eo,Box2dPrismaticJoint:()=>Gr,Box2dPulleyJoint:()=>Nr,Box2dRaycastResult:()=>Qi,Box2dRevoluteJoint:()=>Ir,Box2dRopeJoint:()=>Dr,Box2dStaticObject:()=>Ki,Box2dTargetJoint:()=>Lr,Box2dTileLayer:()=>Mr,Box2dWeldJoint:()=>jr,Box2dWheelJoint:()=>Br,CLEAR_BLACK:()=>kt,CLEAR_WHITE:()=>Sn,CYAN:()=>Td,CanvasLayer:()=>Ji,Color:()=>Oe,Ease:()=>no,EngineObject:()=>Qt,GRAY:()=>vd,GREEN:()=>ul,ImageFont:()=>Di,LOG:()=>_e,Light:()=>vr,LightSystemPlugin:()=>Sr,MAGENTA:()=>Ad,Medal:()=>Yi,NewgroundsMedal:()=>gr,NewgroundsPlugin:()=>br,ORANGE:()=>wd,PI:()=>ie,PURPLE:()=>fl,Particle:()=>Ni,ParticleEmitter:()=>ur,PathFinder:()=>Ur,PathFinderNode:()=>so,PostProcessPlugin:()=>xr,RED:()=>Xr,RandomGenerator:()=>or,Sound:()=>Vs,SoundInstance:()=>Bi,TextureInfo:()=>Zt,TileCollisionLayer:()=>qs,TileInfo:()=>Bt,TileLayer:()=>Ws,TileLayerData:()=>Bn,Timer:()=>It,Tween:()=>to,UIButton:()=>Qs,UICheckbox:()=>Cr,UILayout:()=>Pr,UIObject:()=>gt,UISlider:()=>_r,UISystemPlugin:()=>Tr,UIText:()=>Xi,UITextInput:()=>Ar,UITile:()=>kr,UIVideo:()=>Er,Vector2:()=>ge,WHITE:()=>ee,YELLOW:()=>ll,ZzFXMusic:()=>wr,abs:()=>he,atan2:()=>Hr,audioContext:()=>we,audioDefaultSampleRate:()=>xs,audioIsRunning:()=>Us,audioMasterGain:()=>Kt,box2d:()=>b,box2dDebug:()=>Fa,box2dInit:()=>jh,box2dSetDebug:()=>Bh,cameraAngle:()=>ue,cameraFit:()=>Bf,cameraPos:()=>Ge,cameraScale:()=>se,canvasClearColor:()=>mn,canvasColorTiles:()=>oo,canvasFixedSize:()=>ss,canvasMaxAspect:()=>ns,canvasMaxSize:()=>ts,canvasMinAspect:()=>Ms,canvasPixelRatio:()=>yn,canvasPixelated:()=>Zr,ceil:()=>Fs,clamp:()=>Y,combineCanvases:()=>fa,cos:()=>be,debug:()=>qe,debugCircle:()=>et,debugClear:()=>dd,debugLine:()=>Lt,debugOverlap:()=>sr,debugOverlay:()=>Ut,debugPoint:()=>qr,debugPointSize:()=>Hc,debugPoly:()=>ud,debugRect:()=>Ce,debugScreenshot:()=>Yc,debugShowErrors:()=>fd,debugText:()=>es,debugVideoCaptureIsActive:()=>Ot,debugVideoCaptureStart:()=>Xc,debugVideoCaptureStop:()=>Kc,debugWatermark:()=>io,distanceAngle:()=>bd,distanceWrap:()=>$r,drawCanvas2D:()=>Vn,drawCircle:()=>Oi,drawCircleGradient:()=>If,drawContext:()=>Ie,drawCount:()=>Ft,drawCrescent:()=>zh,drawEllipse:()=>yl,drawEllipseGradient:()=>gl,drawLine:()=>On,drawLineList:()=>ar,drawNineSlice:()=>jl,drawNineSliceScreen:()=>Jh,drawPoly:()=>us,drawRect:()=>Li,drawRectGradient:()=>Lf,drawRegularPoly:()=>ml,drawText:()=>Ff,drawTextScreen:()=>gn,drawTextureWrapped:()=>Of,drawThreeSlice:()=>Jl,drawThreeSliceScreen:()=>Nh,drawTile:()=>Ne,enablePhysicsSolver:()=>lo,engineAddPlugin:()=>zn,engineImageFont:()=>vl,engineInit:()=>rd,engineName:()=>Ti,engineObjects:()=>Ee,engineObjectsCallback:()=>cd,engineObjectsCollect:()=>qc,engineObjectsCollide:()=>Wr,engineObjectsDestroy:()=>ad,engineObjectsRaycast:()=>ld,engineObjectsUpdate:()=>Wc,engineVersion:()=>Ai,fetchJSON:()=>kd,floor:()=>Le,fontDefault:()=>ei,formatTime:()=>Kr,frame:()=>Uc,frameRate:()=>sd,gamepadConnected:()=>lr,gamepadDirectionEmulateStick:()=>ra,gamepadDpad:()=>cr,gamepadIsDown:()=>zt,gamepadPrimary:()=>ke,gamepadStick:()=>Ns,gamepadStickCount:()=>wl,gamepadVibrate:()=>Zf,gamepadVibrateStop:()=>eh,gamepadWasPressed:()=>ba,gamepadWasReleased:()=>Qf,gamepadsEnable:()=>uo,getCameraSize:()=>xl,getCrescentPoints:()=>Nl,getNoteFrequency:()=>_l,getPaused:()=>id,glAntialias:()=>Aa,glCanvas:()=>fe,glCircleSides:()=>ti,glClearCanvas:()=>Ll,glClearRect:()=>Gl,glCompileShader:()=>yr,glContext:()=>g,glCopyToContext:()=>Pa,glCreateProgram:()=>ms,glCreateTexture:()=>mo,glDeleteTexture:()=>Dl,glDraw:()=>Ys,glDrawColoredPoints:()=>La,glDrawOutlineTransform:()=>Ma,glDrawPoints:()=>Fl,glDrawPointsTransform:()=>Ra,glDrawUntextured:()=>Il,glEnable:()=>H,glFlush:()=>Be,glSetAntialias:()=>_h,glSetRenderTarget:()=>Rs,glSetTexture:()=>_a,glSetTextureData:()=>Ea,glSetTextureWrap:()=>Ol,gravity:()=>tt,headlessMode:()=>X,hsl:()=>Wt,hypot:()=>Qc,inputClear:()=>ai,inputClearKey:()=>ya,inputMouseMoveThreshold:()=>ma,inputPreventDefault:()=>is,inputWASDEmulateDirection:()=>Ls,isArray:()=>Tt,isColor:()=>Q,isFullscreen:()=>Sl,isIntersecting:()=>nl,isNumber:()=>D,isOnScreen:()=>jf,isOverlapping:()=>Ei,isPowerOfTwo:()=>Gs,isStringLike:()=>Z,isTouchDevice:()=>mt,isUsingGamepad:()=>rs,isVector2:()=>I,keyDirection:()=>Xf,keyIsDown:()=>Je,keyWasPressed:()=>Ve,keyWasReleased:()=>ga,lastInputDevice:()=>hn,lerp:()=>nt,lerpAngle:()=>xd,lerpWrap:()=>tl,lightSystem:()=>ne,lineTest:()=>il,log2:()=>Zc,mainCanvas:()=>$,mainCanvasSize:()=>U,mainContext:()=>xe,max:()=>le,medalDisplaySize:()=>Hi,medalDisplaySlideTime:()=>os,medalDisplayTime:()=>qi,medals:()=>Xs,medalsForEach:()=>yo,medalsInit:()=>Mh,medalsPreventUnlock:()=>Oa,medalsReset:()=>Lh,min:()=>de,mod:()=>pt,mouseDelta:()=>ha,mouseDeltaScreen:()=>Pt,mouseInWindow:()=>Ii,mouseIsDown:()=>Ds,mousePos:()=>Nt,mousePosScreen:()=>Ze,mouseWasPressed:()=>Js,mouseWasReleased:()=>Kf,mouseWheel:()=>pa,nearestPowerOfTwo:()=>Sd,newgrounds:()=>Ks,noise1D:()=>Rd,noise2D:()=>Md,objectDefaultAngleDamping:()=>sa,objectDefaultDamping:()=>na,objectDefaultFriction:()=>oa,objectDefaultMass:()=>ta,objectDefaultRestitution:()=>ia,objectMaxSpeed:()=>qt,oscillate:()=>sl,particleEmitRateScale:()=>Pi,paused:()=>Dt,percent:()=>He,percentLerp:()=>gd,playSamples:()=>Ta,pointerLockExit:()=>sh,pointerLockIsActive:()=>Tl,pointerLockRequest:()=>nh,postProcess:()=>Ue,primitiveCount:()=>Gt,rand:()=>ve,randBool:()=>ol,randColor:()=>ir,randInCircle:()=>cl,randInt:()=>Yr,randSign:()=>rl,randVec2:()=>al,readSaveData:()=>Ed,rgb:()=>K,round:()=>Ci,saveCanvas:()=>hl,saveDataURL:()=>Bs,saveText:()=>Cd,screenToWorld:()=>oi,screenToWorldDelta:()=>bl,screenToWorldTransform:()=>ri,setAdditiveBlendMode:()=>js,setCameraAngle:()=>Od,setCameraPos:()=>Ld,setCameraScale:()=>Dd,setCanvasClearColor:()=>Gd,setCanvasColorTiles:()=>Fd,setCanvasFixedSize:()=>Nd,setCanvasMaxAspect:()=>Jd,setCanvasMaxSize:()=>Bd,setCanvasMinAspect:()=>jd,setCanvasPixelRatio:()=>Ud,setCanvasPixelated:()=>pl,setCursor:()=>Uf,setDebugKey:()=>Mf,setDebugWatermark:()=>Rf,setEnablePhysicsSolver:()=>Qd,setFontDefault:()=>Vd,setGLCircleSides:()=>$d,setGLEnable:()=>Hd,setGamepadDirectionEmulateStick:()=>lf,setGamepadsEnable:()=>cf,setGravity:()=>rf,setHeadlessMode:()=>qd,setInputMouseMoveThreshold:()=>qf,setInputPreventDefault:()=>Wf,setInputWASDEmulateDirection:()=>uf,setMedalDisplaySize:()=>Ih,setMedalDisplaySlideTime:()=>Dh,setMedalDisplayTime:()=>Oh,setMedalsPreventUnlock:()=>Fh,setObjectDefaultAngleDamping:()=>tf,setObjectDefaultDamping:()=>ef,setObjectDefaultFriction:()=>sf,setObjectDefaultMass:()=>Zd,setObjectDefaultRestitution:()=>nf,setObjectMaxSpeed:()=>of,setParticleEmitRateScale:()=>af,setPaused:()=>od,setShowSplashScreen:()=>Wd,setSoundDefaultRange:()=>Ef,setSoundDefaultTaper:()=>Pf,setSoundEnable:()=>Cf,setSoundVolume:()=>_f,setTileDefaultBleed:()=>Kd,setTileDefaultPadding:()=>Xd,setTileDefaultSize:()=>Yd,setTilesPixelated:()=>zd,setTimeScale:()=>Id,setTouchGamepadAlpha:()=>wf,setTouchGamepadAnalog:()=>xf,setTouchGamepadButtonCount:()=>mf,setTouchGamepadCenterButtonSize:()=>pf,setTouchGamepadDisplayTime:()=>Tf,setTouchGamepadEnable:()=>ff,setTouchGamepadFloating:()=>Sf,setTouchGamepadLeftButtonCount:()=>gf,setTouchGamepadLeftStick:()=>yf,setTouchGamepadPassthrough:()=>hf,setTouchGamepadRightStick:()=>bf,setTouchGamepadSize:()=>vf,setTouchGamepadVibration:()=>Af,setTouchInputEnable:()=>df,setVibrateEnable:()=>kf,shareURL:()=>_d,showSplashScreen:()=>ea,sign:()=>ht,sin:()=>pe,smoothStep:()=>_i,soundDefaultRange:()=>la,soundDefaultTaper:()=>ua,soundEnable:()=>it,soundVolume:()=>Gn,speak:()=>bh,speakStop:()=>xh,tan:()=>el,textureInfos:()=>wn,tile:()=>ii,tileCollisionGetData:()=>ji,tileCollisionLayers:()=>bn,tileCollisionRaycast:()=>El,tileCollisionTest:()=>dn,tileDefaultBleed:()=>co,tileDefaultPadding:()=>ao,tileDefaultSize:()=>ro,tileLayersLoad:()=>vh,tilesPixelated:()=>jn,time:()=>lt,timeDelta:()=>Vr,timeReal:()=>xn,timeScale:()=>Qr,toggleFullscreen:()=>zf,touchGamepadAlpha:()=>ca,touchGamepadAnalog:()=>ni,touchGamepadButtonCount:()=>ys,touchGamepadCenterButtonSize:()=>At,touchGamepadDisplayTime:()=>Os,touchGamepadEnable:()=>vn,touchGamepadFloating:()=>Tn,touchGamepadLeftButtonCount:()=>gs,touchGamepadLeftStick:()=>Un,touchGamepadPassthrough:()=>aa,touchGamepadRightStick:()=>bs,touchGamepadSize:()=>st,touchGamepadVibration:()=>Ri,touchInputEnable:()=>Ln,tweenProperty:()=>Uh,tweenStopAll:()=>Vh,tweenUpdate:()=>Vl,uiDebug:()=>Ia,uiSetDebug:()=>Gh,uiSystem:()=>E,usingGamepadInput:()=>Yf,usingKeyboardInput:()=>$f,usingMouseInput:()=>Hf,vec2:()=>w,vibrate:()=>xa,vibrateEnable:()=>si,vibrateStop:()=>th,workCanvas:()=>Yt,workContext:()=>fn,workReadCanvas:()=>Mt,workReadContext:()=>Ht,worldToScreen:()=>Wn,worldToScreenDelta:()=>Gf,writeSaveData:()=>Pd,zzfx:()=>Sh,zzfxG:()=>ho,zzfxM:()=>Bl});function id(){return Dt}function od(t=!0){Dt=t}function zn(t,e,n,s){y(!Dn.find(r=>r.update===t&&r.render===e&&r.glContextLost===n&&r.glContextRestored===s));let i=new tr(t,e,n,s);Dn.push(i)}async function rd(t,e,n,s,i,r=[],a){if(Vc&&console.log(`${Ti} Engine v${Ai}`),y(!xe,"engine already initialized"),xe)return;y(Tt(r),"pass in images as array"),document.body||document.documentElement.appendChild(document.createElement("body")),a||(a=document.body),t||(t=()=>{}),e||(e=()=>{}),n||(n=()=>{}),s||(s=()=>{}),i||(i=()=>{});function o(){U=w($.width,$.height),xe.imageSmoothingEnabled=!jn,mr()}function c(m=0){let p=m-Qo;Qo||(p=0),Qo=m,(qe||io)&&(ki=nt(ki,1e3/(p||1),.05));let x=qe&&Je("Equal"),v=qe&&Je("Minus"),A=x?10:v?.1:1;xn+=p*A/1e3;let S=Qr*A;p*=S,Et+=Dt?0:p,S<=1&&(Et=de(Et,50));let _=!1;if(Dt){_=!0,l(),Gc(),Dn.forEach(C=>{var O;return(O=C.update)==null?void 0:O.call(C)});for(let C of Ee)C.parent||C.updateTransforms();Oc(),n(),Bc(),Ot()&&k()}else{let C=0;for(Et<0&&Et>-9&&(C=Et,Et=0);Et>=0;Et-=1e3/60)lt=Uc++/60,_=!0,l(),Gc(),e(),Dn.forEach(O=>{var z;return(z=O.update)==null?void 0:z.call(O)}),Wc(),Oc(),n(),Bc(),Ot()&&k();Et+=C}Ot()||k(),requestAnimationFrame(c);function k(){if(!X){_||l(),o(),s(),Ee.sort((C,O)=>C.renderOrder-O.renderOrder);for(let C of Ee)C.destroyed||C.render();i(),Dn.forEach(C=>{var O;return(O=C.render)==null?void 0:O.call(C)}),oh(),pd(),Be(),md(),Ft=0,Gt=0}}}function l(){if(!X){if(ss.x){U=ss.copy();let m=innerWidth/innerHeight,p=ss.x/ss.y,x=mns){let _=U.y*ns|0;U.x=de(_,ts.x)}else if(v0&&!H&&(xe.fillStyle=mn.toString(),xe.fillRect(0,0,U.x,U.y),xe.fillStyle=me.toString()),xe.lineJoin="round",xe.lineCap="round"}}if(X)return f();Ah(a);let u="margin:0;overflow:hidden;background:#000;user-select:none;-webkit-user-select:none;touch-action:none;-webkit-touch-callout:none";a.style.cssText=u,$=a.appendChild(document.createElement("canvas")),Ie=xe=$.getContext("2d"),ih(),gh(),hd();let h="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)";$.style.cssText=h,fe&&(fe.style.cssText=h),pl(Zr),l(),mr(),Yt=new OffscreenCanvas(64,64),fn=Yt.getContext("2d"),Mt=new OffscreenCanvas(64,64),Ht=Mt.getContext("2d",{willReadFrequently:!0});let d=r.map((m,p)=>Ic(p,m));return r.length||d.push(Ic(0)),d.push(Vf()),ea&&d.push(new Promise(m=>{let p=0;x();function x(){ai(),Rh(p+=.01),p>1?m():setTimeout(x,16)}})),await Promise.all(d),f();async function f(){await t(),c()}}function Wc(){Wr=Ee.filter(e=>e.collideSolidObjects);function t(e){if(!e.destroyed){e.update();for(let n of e.children)t(n)}}for(let e of Ee)if(!(e.parent||e.destroyed)){e.update(),e.updatePhysics();for(let n of e.children)t(n);e.updateTransforms()}Ee=Ee.filter(e=>!e.destroyed)}function ad(t=!0){for(let e of Ee)e.parent||e.destroy(t);Ee=Ee.filter(e=>!e.destroyed)}function qc(t,e,n=Ee){let s=[];if(t)if(e instanceof ge)for(let i of n)i.isOverlapping(t,e)&&s.push(i);else{let i=e*e;for(let r of n)t.distanceSquared(r.pos)n(i))}function ld(t,e,n=Ee){let s=[];for(let i of n)i.collideRaycast&&nl(t,e,i.pos,i.size)&&(wt&&Ce(i.pos,i.size,"#f00"),s.push(i));return wt&&Lt(t,e,s.length?"#f00":"#00f",.02),s}function y(t,...e){if(!t)throw console.assert(t,...e),new Error("Assert failed!")}function _e(...t){console.log(...t)}function Ce(t,e=w(),n=ee,s=0,i=0,r=!1,a=!1){y(I(t),"pos must be a vec2"),y(I(e),"size must be a vec2"),y(Z(n)||Q(n),"color is invalid"),y(D(s),"time must be a number"),y(D(i),"angle must be a number"),Q(n)&&(n=n.toString());let o=new It(s);pn.push({pos:t.copy(),size:e.copy(),color:n,timer:o,angle:i,fill:r,screenSpace:a})}function ud(t,e,n=ee,s=0,i=0,r=!1,a=!1){y(I(t),"pos must be a vec2"),y(Tt(e),"points must be an array"),y(Z(n)||Q(n),"color is invalid"),y(D(s),"time must be a number"),y(D(i),"angle must be a number"),Q(n)&&(n=n.toString()),t=t.copy(),e=e.map(c=>c.copy());let o=new It(s);pn.push({pos:t,points:e,color:n,timer:o,angle:i,fill:r,screenSpace:a})}function et(t,e=0,n=ee,s=0,i=!1,r=!1){y(I(t),"pos must be a vec2"),y(D(e),"size must be a number"),y(Z(n)||Q(n),"color is invalid"),y(D(s),"time must be a number"),Q(n)&&(n=n.toString()),t=t.copy();let a=new It(s);pn.push({pos:t,size:e,color:n,timer:a,angle:0,fill:i,screenSpace:r})}function qr(t,e,n,s,i=!1){Ce(t,void 0,e,n,s,!1,i)}function Lt(t,e,n,s=.1,i=0,r=!1){y(I(t),"posA must be a vec2"),y(I(e),"posB must be a vec2"),y(D(s),"width must be a number");let a=w((e.x-t.x)/2,(e.y-t.y)/2),o=w(s,a.length()*2);Ce(t.add(a),o,n,i,a.angle(),!0,r)}function sr(t,e,n,s,i,r,a=!1){y(I(t),"posA must be a vec2"),y(I(n),"posB must be a vec2"),y(I(e),"sizeA must be a vec2"),y(I(s),"sizeB must be a vec2");let o=w(de(t.x-e.x/2,n.x-s.x/2),de(t.y-e.y/2,n.y-s.y/2)),c=w(le(t.x+e.x/2,n.x+s.x/2),le(t.y+e.y/2,n.y+s.y/2));Ce(o.lerp(c,.5),c.subtract(o),i,r,0,!1,a)}function es(t,e,n=1,s=ee,i=0,r=0,a="monospace",o=!1){y(Z(t),"text must be a string"),y(I(e),"pos must be a vec2"),y(D(n),"size must be a number"),y(Z(s)||Q(s),"color is invalid"),y(D(i),"time must be a number"),y(D(r),"angle must be a number"),y(Z(a),"font must be a string"),Q(s)&&(s=s.toString()),e=e.copy();let c=new It(i);pn.push({text:t,pos:e,size:n,color:s,timer:c,angle:r,font:a,screenSpace:o})}function dd(){pn=[]}function Yc(){nr=1}function fd(){let t=n=>{document.body.style="background-color:#111;margin:8px",document.body.innerHTML="
"+n},e=console.assert;console.assert=(n,...s)=>{if(e(n,...s),!n){let i=s.join(" "),r=new Error().stack;throw`Assertion failed!
+`+i+`
+`+r}},onunhandledrejection=n=>t(n.reason.stack||n.reason),onerror=(n,s,i,r)=>t(`${n}
+${s}
+Ln ${i}, Col ${r}`)}function hd(){Vc&&console.warn("LittleJS DEBUG build loaded. Use the release build for production.")}function Oc(){qe&&(Ve($c)&&(Ut=!Ut),Ut&&(Ve("Digit1")&&(vt=!vt,In=!1),Ve("Digit2")&&(In=!In,vt=!1),Ve("Digit3")&&(Fn=!Fn),Ve("Digit4")&&(wt=!wt),Ve("Digit5")&&Yc(),Ve("Digit7")&&(ls=!ls)),Ot()?(!Ut||Ve("Digit6"))&&Kc():Ut&&Ve("Digit6")&&Xc())}function pd(){if(Ot())return;Be();let t=Ft,e=Gt;nr&&(fa(),hl($),nr=0);let n=xe;if(Fn&&uo){let r=0;for(let a=0;a<8;a++)lr(a)&&r++;for(let a=0;a<8;a++){if(!lr(a))continue;let o=1,c=.2,l=Ge.add(w(-o*2,((r-1)/2-a)*o*3));es(a,l.add(w(-o,o)),1),a===ke&&es("Main",l.add(w(-o*2,0)),1,"#0f0");let u=Rt[a].length;for(let d=0;d{n.save();let r=i.pos,a=1,o=i.angle;if(i.screenSpace||(r=Wn(i.pos),a=se,o-=ue),n.translate(r.x|0,r.y|0),n.rotate(o),n.scale(1,i.text?1:-1),n.fillStyle=i.color,n.strokeStyle=i.color,i.text!==void 0)n.font=i.size*a+"px "+i.font,n.textAlign="center",n.textBaseline="middle",n.fillText(i.text,0,0);else if(i.points!==void 0){n.beginPath();for(let c of i.points){let l=c.scale(a).floor();n.lineTo(l.x,l.y)}n.closePath(),i.fill&&n.fill(),n.stroke()}else if(i.size===0||i.size.x===0&&i.size.y===0){let c=Hc*a;n.fillRect(-c/2,-1,c,3),n.fillRect(-1,-c/2,3,c)}else if(i.size.x!==void 0){let c=i.size.scale(a).floor(),l=c.x,u=c.y;i.fill&&n.fillRect(-l/2|0,-u/2|0,l,u),n.strokeRect(-l/2|0,-u/2|0,l,u)}else n.beginPath(),n.arc(0,0,i.size*a/2,0,9),i.fill&&n.fill(),n.stroke();n.restore()}),pn=pn.filter(i=>i.timer<0),s){let i=El(s.pos,Nt);i&&Li(i.floor().add(w(.5)),w(1),K(0,1,1,.3),0,!1),On(Nt,s.pos,.1,i?K(1,0,0,.5):K(0,1,0,.5),void 0,void 0,!1);let r="mouse pos = "+Nt;bn.length&&(r+=`
+mouse collision = `+ji(Nt)),r+=`
+
+--- object info ---
+`,r+=s.toString(),gn(r,Ze,24,K(),.05,void 0,"center","monospace")}{n.save(),n.fillStyle="#fff",n.textAlign="left",n.textBaseline="top",n.font="20px monospace",n.shadowColor="#000",n.shadowBlur=9;let a=9,o=0,c=24;if(Ut){n.fillText(`${Ti} v${Ai}`,a,o+=c/2),n.fillText("Time: "+Kr(lt),a,o+=c),n.fillText("FPS: "+ki.toFixed(1)+(H?" WebGL":" Canvas2D"),a,o+=c),n.fillText("Objects: "+Ee.length,a,o+=c),n.fillText("Draw Calls: "+Ft,a,o+=c),n.fillText("Primitives: "+Gt,a,o+=c),n.fillText("---------",a,o+=c),n.fillStyle="#f00",n.fillText("ESC: Debug Overlay",a,o+=c),n.fillStyle=vt?"#f00":"#fff",n.fillText("1: Debug Physics",a,o+=c),n.fillStyle=In?"#f00":"#fff",n.fillText("2: Debug Particles",a,o+=c),n.fillStyle=Fn?"#f00":"#fff",n.fillText("3: Debug Gamepads",a,o+=c),n.fillStyle=wt?"#f00":"#fff",n.fillText("4: Debug Raycasts",a,o+=c),n.fillStyle="#fff",n.fillText("5: Save Screenshot",a,o+=c),n.fillText("6: Toggle Video Capture",a,o+=c),n.fillStyle=ls?"#f00":"#fff",n.fillText("7: Debug Sound",a,o+=c);let l="",u="";for(let h in oe[0])Je(h,0)&&(parseInt(h)<3?u+=h+" ":l+=h+" ");u&&n.fillText("Mouse: "+u,a,o+=c),l&&n.fillText("Keys: "+l,a,o+=c);for(let h=1;hs.push(o.data),i.onstop=()=>{let o=new Blob(s,{type:"video/webm"}),c=URL.createObjectURL(o);Bs(c,"capture.webm",1e3)};let r,a;if(it){a=new ConstantSourceNode(we,{offset:0}),a.connect(Kt),a.start(),r=we.createMediaStreamDestination(),Kt.connect(r);for(let o of r.stream.getAudioTracks())t.addTrack(o)}try{i.start()}catch{_e("Video capture not supported in this browser!"),a==null||a.stop();return}_e("Video capture started."),Vt={mediaRecorder:i,captureTimer:n,videoTrack:e,silentAudioSource:a,audioStreamDestination:r}}function Kc(){var t,e,n;y(Ot(),"Not capturing video!"),_e(`Video capture ended. ${Vt.captureTimer.get().toFixed(2)} seconds recorded.`),St.style.display="none",(t=Vt.silentAudioSource)==null||t.stop(),(e=Vt.mediaRecorder)==null||e.stop(),(n=Vt.videoTrack)==null||n.stop(),Vt=void 0}function yd(){y(Ot(),"Not capturing video!"),fa(),Vt.videoTrack.requestFrame(),St.textContent="\u25CF REC "+Kr(Vt.captureTimer)}function dt(t){if(qe){let e=Object.keys(t),n={};e.forEach(s=>n[s]=t[s]),e.forEach(s=>{Object.defineProperty(t,s,{get:()=>n[s],set:i=>{y(!1,`Cannot modify engine constant. Attempted to set constant (${t}) property '${s}' to '${i}'.`)},enumerable:!0})})}return Object.freeze(t)}function pt(t,e=1){return(t%e+e)%e}function Y(t,e=0,n=1){return tn?n:t}function He(t,e,n){return(n-=e)?Y((t-e)/n):0}function nt(t,e,n){return t+Y(n)*(e-t)}function gd(t,e,n,s,i){return nt(s,i,He(t,e,n))}function $r(t,e,n=1){y(n>0,"distanceWrap wrapSize must be > 0");let s=(t-e)%n;return s*2%n-s}function tl(t,e,n,s=1){return t+Y(n)*$r(e,t,s)}function bd(t,e){return $r(t,e,2*ie)}function xd(t,e,n){return tl(t,e,n,2*ie)}function _i(t){return t*t*(3-2*t)}function Gs(t){return!(t&t-1)}function Sd(t){return 2**Fs(Zc(t))}function Ei(t,e,n,s=w()){let i=(t.x-n.x)*2,r=(t.y-n.y)*2,a=e.x+s.x,o=e.y+s.y;return he(i)d)return!1;h=le(m,h)}else{if(m0?o.x+1:o.x,p=h>0?o.y+1:o.y,x=c?(m-t.x)/c:1/0,v=l?(p-t.y)/l:1/0,A=0,S=x,_=v,k=do.x&&(C.x=o.x+1-O),z.yo.y&&(C.y=o.y+1-O),s&&(k?s.set(-u,0):s.set(0,-h)),C}(k=S<_)?(o.x+=u,A=S,S+=d):(o.y+=h,A=_,_+=f)}}function ve(t=1,e=0){return e+Math.random()*(t-e)}function Yr(t,e=0){return Le(ve(t,e))}function ol(t=.5){return ve()URL.revokeObjectURL(t),n)}function _d(t,e,n){var s;y(Z(t),"shareURL requires title string"),y(Z(e),"shareURL requires url string"),(s=navigator.share)==null||s.call(navigator,{title:t,url:e}).then(()=>n==null?void 0:n())}function Ed(t,e){y(Z(t),"loadData requires saveName string");let n={};try{let s=localStorage[t];if(s)try{n=JSON.parse(s)}catch{_e("readSaveData: corrupt JSON for",t,"\u2014 using defaults")}}catch{_e("readSaveData: localStorage unavailable \u2014 using defaults")}return{...e,...n}}function Pd(t,e){y(Z(t),"saveData requires saveName string");try{localStorage[t]=JSON.stringify(e)}catch{_e("writeSaveData: failed to write",t)}}function rr(t){let e=(t|0)^2654435769;return e=Math.imul(e^e>>>16,2246822507),e=Math.imul(e^e>>>13,3266489909),e^=e>>>16,(e>>>0)/2**32}function Rd(t){let e=Le(t);return nt(rr(e),rr(e+1),_i(t-e))}function Md(t,e){let n=Le(t),s=Le(e),i=_i(t-n),r=_i(e-s),a=(o,c)=>rr(o+c*374761393);return nt(nt(a(n,s),a(n+1,s),i),nt(a(n,s+1),a(n+1,s+1),i),r)}function Ld(t){Ge=t.copy()}function Od(t){ue=t}function Dd(t){se=t}function Id(t){Qr=t}function Fd(t){oo=t}function Gd(t){mn=t.copy()}function Bd(t){ts=t.copy()}function jd(t){Ms=t}function Jd(t){ns=t}function Nd(t){ss=t.copy()}function pl(t){Zr=t,$&&($.style.imageRendering=t?"pixelated":""),fe&&(fe.style.imageRendering=t?"pixelated":"")}function zd(t){jn=t}function Ud(t){yn=t}function Vd(t){ei=t}function Wd(t){ea=t}function qd(t){X=t}function Hd(t){if(t&&!pr){console.warn("Can not enable WebGL if it was disabled on start.");return}H=t,fe&&(fe.style.display=t?"":"none")}function $d(t){ti=t}function Yd(t){ro=t.copy()}function Xd(t){ao=t}function Kd(t){co=t}function Qd(t){lo=t}function Zd(t){ta=t}function ef(t){na=t}function tf(t){sa=t}function nf(t){ia=t}function sf(t){oa=t}function of(t){qt=t}function rf(t){tt=t.copy()}function af(t){Pi=t}function cf(t){uo=t}function lf(t){ra=t}function uf(t){Ls=t}function df(t){Ln=t}function ff(t){vn=t}function hf(t){aa=t}function pf(t){At=t}function mf(t){ys=t,t>0&&(bs=!1)}function yf(t){Un=t,t&&(gs=0)}function gf(t){gs=t,t>0&&(Un=!1)}function bf(t){bs=t,t&&(ys=0)}function xf(t){ni=t}function Sf(t){Tn=t}function vf(t){st=t}function wf(t){ca=t}function Tf(t){Os=t}function Af(t){Ri=t}function kf(t){si=t}function Cf(t){it=t}function _f(t){Gn=t,it&&!X&&Kt&&(Kt.gain.value=t)}function Ef(t){la=t}function Pf(t){ua=t}function Rf(t){io=t}function Mf(t){$c=t}function Mi(t){return t.r>=1&&t.g>=1&&t.b>=1}function da(t){return t.r<=0&&t.g<=0&&t.b<=0&&t.a<=0}function ii(t=0,e=ro,n=0,s=ao,i=co){if(y(I(t)||typeof t=="number","index must be a vec2 or number"),y(I(e)||typeof e=="number","size must be a vec2 or number"),y(D(n)||n instanceof Zt,"texture must be a number or TextureInfo"),y(D(s),"padding must be a number"),X)return new Bt;typeof e=="number"&&(y(e>0),e=new ge(e,e));let r=typeof n=="number"?wn[n]:n;y(r instanceof Zt,"tile texture is not loaded"),y(r.size.x>0,"tile texture is not loaded");let a=e.x+s*2,o=e.y+s*2,c,l;if(typeof t=="number"){let h=r.size.x/a|0;c=t%h,l=t/h|0}else c=t.x,l=t.y;let u=new ge(c*a+s,l*o+s);return new Bt(u,e,r,s,i)}function Ne(t,e=w(1),n,s=ee,i=0,r,a,o=H,c=!1,l){var d;y(I(t),"pos must be a vec2"),y(I(e),"size must be a vec2"),y(Q(s),"color is invalid"),y(D(i),"angle must be a number"),y(!a||Q(a),"additiveColor must be a color"),y(!l||!o,"context only supported in canvas 2D mode");let u=n==null?void 0:n.textureInfo,h=(d=n==null?void 0:n.bleed)!=null?d:0;if(o&&H)if(y(!!g,"WebGL is not enabled!"),c&&([t,e,i]=ri(t,e,i)),u){let f=u.sizeInverse,m=n.pos.x*f.x,p=n.pos.y*f.y,x=n.size.x*f.x,v=n.size.y*f.y;if(_a(u.glTexture),h){let A=f.x*h,S=f.y*h;Ys(t.x,t.y,r?-e.x:e.x,e.y,i,m+A,p+S,m-A+x,p-S+v,s.rgbaInt(),a&&a.rgbaInt())}else Ys(t.x,t.y,r?-e.x:e.x,e.y,i,m,p,m+x,p+v,s.rgbaInt(),a&&a.rgbaInt())}else{let f=a?s.add(a):s;Il(t.x,t.y,e.x,e.y,i,f.rgbaInt())}else++Ft,++Gt,Vn(t,e,i,r,f=>{if(u){f.scale(1,-1);let m=n.pos.x,p=n.pos.y,x=n.size.x,v=n.size.y;Nf(f,u.image,m,p,x,v,-.5,-.5,1,1,s,a,h)}else{let m=a?s.add(a):s;f.fillStyle=m.toString(),f.fillRect(-.5,-.5,1,1)}},c,l)}function Li(t,e,n,s,i,r,a){Ne(t,e,void 0,n,s,!1,void 0,i,r,a)}function Lf(t,e,n=ee,s=Sn,i=0,r=H,a=!1,o){if(y(I(t),"pos must be a vec2"),y(I(e),"size must be a vec2"),y(Q(n)&&Q(s),"color is invalid"),y(D(i),"angle must be a number"),y(!o||!r,"context only supported in canvas 2D mode"),r&&H){y(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/se),i+=ue);let c=[],l=[],u=e.x/2,h=e.y/2,d=n.rgbaInt(),f=s.rgbaInt(),m=be(-i),p=pe(-i);for(let x=4;x--;){let v=x&1?u:-u,A=x&2?h:-h,S=v*m-A*p,_=v*p+A*m,k=x&2?d:f;c.push(w(t.x+S,t.y+_)),l.push(k)}La(c,l)}else++Ft,++Gt,Vn(t,e,i,!1,c=>{let l=c.createLinearGradient(0,.5,0,-.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.fillRect(-.5,-.5,1,1)},a,o)}function Of(t,e,n,s=0,i=ee,r=0,a,o=H,c=!1,l){if(y(I(t),"pos must be a vec2"),y(I(e),"size must be a vec2"),y(I(n),"wrapCount must be a vec2"),y(Q(i),"color is invalid"),y(D(r),"angle must be a number"),y(!a||Q(a),"additiveColor must be a color"),y(!l||!o,"context only supported in canvas 2D mode"),y(!(s instanceof Bt),"pass a TextureInfo or texture index, not a TileInfo \u2014 use tileInfo.textureInfo"),X)return;let u=typeof s=="number"?wn[s]:s;if(y(u instanceof Zt,"texture not loaded"),y(u.size.x>0,"texture not loaded"),y(u.wrap,"drawTextureWrapped requires a wrap-enabled texture; call textureInfo.setWrap(true) first"),o&&H){y(!!g,"WebGL is not enabled!"),c&&([t,e,r]=ri(t,e,r)),_a(u.glTexture),Ys(t.x,t.y,e.x,e.y,r,0,0,n.x,n.y,i.rgbaInt(),a&&a.rgbaInt());return}++Ft,++Gt,c||(t=Wn(t),e=e.scale(se),r-=ue);let h=!oo||(a?Mi(i.add(a))&&a.a<=0:Mi(i)),d=!h&&a&&!da(a),f=h?u.image:Jf(u.image,i,a);l=l||Ie,l.save(),l.translate(t.x+.5,t.y+.5),l.rotate(r),l.globalAlpha=d?1:i.a;let m=l.createPattern(f,"repeat"),p=new DOMMatrix().translate(-e.x/2,-e.y/2).scale(e.x/(n.x*f.width),e.y/(n.y*f.height));m.setTransform(p),l.fillStyle=m,l.fillRect(-e.x/2,-e.y/2,e.x,e.y),l.globalAlpha=1,l.restore()}function ar(t,e=.1,n=ee,s=!1,i=w(),r=0,a=H,o=!1,c){if(y(Tt(t),"points must be an array"),y(D(e),"width must be a number"),y(Q(n),"color is invalid"),y(I(i),"pos must be a vec2"),y(D(r),"angle must be a number"),y(!c||!a,"context only supported in canvas 2D mode"),a&&H){y(!!g,"WebGL is not enabled!");let l=w(1);o&&([i,l,r]=ri(i,l,r)),Ma(t,n.rgbaInt(),e,i.x,i.y,l.x,l.y,r,s)}else++Ft,++Gt,Vn(i,w(1),r,!1,l=>{l.strokeStyle=n.toString(),l.lineWidth=e,l.beginPath();for(let u=0;u0&&Ma(t,s.rgbaInt(),n,i.x,i.y,l.x,l.y,r)}else Vn(i,w(1),r,!1,l=>{l.fillStyle=e.toString(),l.beginPath();for(let u of t)l.lineTo(u.x,u.y);l.closePath(),l.fill(),n&&(l.strokeStyle=s.toString(),l.lineWidth=n,l.stroke())},o,c)}function yl(t,e=w(1),n=ee,s=0,i=0,r=me,a=H,o=!1,c){y(I(t),"pos must be a vec2"),y(I(e),"size must be a vec2"),y(Q(n)&&Q(r),"color is invalid"),y(D(s),"angle must be a number"),y(D(i),"lineWidth must be a number"),y(i>=0,"lineWidth must be a positive value or 0"),y(!c||!a,"context only supported in canvas 2D mode"),i=Y(i,0,de(e.x,e.y)),a&&H?ml(t,e,ti,n,i,r,s,a,o,c):Vn(t,w(1),s,!1,l=>{l.fillStyle=n.toString(),l.beginPath(),l.ellipse(0,0,e.x/2,e.y/2,0,0,9),l.fill(),i&&(l.strokeStyle=r.toString(),l.lineWidth=i,l.stroke())},o,c)}function Oi(t,e=1,n=ee,s=0,i=me,r=H,a=!1,o){y(D(e),"size must be a number"),yl(t,w(e),n,0,s,i,r,a,o)}function gl(t,e=w(1),n=ee,s=Sn,i=0,r=H,a=!1,o){if(y(I(t),"pos must be a vec2"),y(I(e),"size must be a vec2"),y(Q(n)&&Q(s),"color is invalid"),y(D(i),"angle must be a number"),y(!o||!r,"context only supported in canvas 2D mode"),!X)if(r&&H){y(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/se),i+=ue);let c=ti,l=e.x/2,u=e.y/2,h=n.rgbaInt(),d=s.rgbaInt(),f=Df++,m=be(-i),p=pe(-i),x=_=>{let k=pe(_)*l,C=be(_)*u;return w(t.x+k*m-C*p,t.y+k*p+C*m)},v=f%c/c*ie*2,A=[x(v)],S=[d];for(let _=c;_--;){let k=(_+f)%c/c*ie*2;A.push(t),S.push(h),A.push(x(k)),S.push(d)}La(A,S)}else++Ft,++Gt,Vn(t,e,i,!1,c=>{let l=c.createRadialGradient(0,0,0,0,0,.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.beginPath(),c.ellipse(0,0,.5,.5,0,0,9),c.fill()},a,o)}function If(t,e=1,n=ee,s=Sn,i=H,r=!1,a){y(D(e),"size must be a number"),gl(t,w(e),n,s,0,i,r,a)}function Vn(t,e,n=0,s=!1,i,r=!1,a=Ie){y(I(t),"pos must be a vec2"),y(I(e),"size must be a vec2"),y(D(n),"angle must be a number"),y(typeof i=="function","drawFunction must be a function"),r||(t=Wn(t),e=e.scale(se),n-=ue),a.save(),a.translate(t.x+.5,t.y+.5),a.rotate(n),a.scale(s?-e.x:e.x,-e.y),i(a),a.restore()}function Ff(t,e,n=1,s=ee,i=0,r=me,a="center",o=ei,c="",l,u=0,h=Ie){e=Wn(e),n*=se,i*=se,u-=ue,u*=-1,gn(t,e,n,s,i,r,a,o,c,l,u,h)}function gn(t,e,n,s=ee,i=0,r=me,a="center",o=ei,c="",l,u=0,h=Ie){y(Z(t),"text must be a string"),y(I(e),"pos must be a vec2"),y(D(n),"size must be a number"),y(Q(s),"color must be a color"),y(D(i),"lineWidth must be a number"),y(Q(r),"lineColor must be a color"),y(["left","center","right"].includes(a),"align must be left, center, or right"),y(Z(o),"font must be a string"),y(Z(c),"fontStyle must be a string"),y(D(u),"angle must be a number");let d=(t+"").split(`
+`),f=e.y-(d.length-1)*n/2;h.save(),h.fillStyle=s.toString(),h.strokeStyle=r.toString(),h.lineWidth=i,h.textAlign=a,h.font=c+" "+n+"px "+o,h.textBaseline="middle",h.translate(e.x,f),h.rotate(-u);let m=0;d.forEach(p=>{i&&h.strokeText(p,0,m,l),h.fillText(p,0,m,l),m+=n}),h.restore()}async function Ic(t,e){y(D(t),"textureIndex must be a number"),y(!wn[t],"textureIndex is already loaded!"),y(!e||Z(e),"image src must be a string");let n=new Image;e&&await new Promise(s=>{n.onerror=n.onload=s,n.crossOrigin="anonymous",n.src=e}),wn[t]=new Zt(n)}function oi(t){y(I(t),"screenPos must be a vec2");let e=(t.x-U.x/2+.5)/se,n=(t.y-U.y/2+.5)/-se;if(ue){let s=be(-ue),i=pe(-ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e+Ge.x,n+Ge.y)}function Wn(t){y(I(t),"worldPos must be a vec2");let e=t.x-Ge.x,n=t.y-Ge.y;if(ue){let s=be(ue),i=pe(ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e*se+U.x/2-.5,n*-se+U.y/2-.5)}function bl(t){y(I(t),"screenDelta must be a vec2");let e=t.x/se,n=t.y/-se;if(ue){let s=be(-ue),i=pe(-ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e,n)}function Gf(t){y(I(t),"worldDelta must be a vec2");let e=t.x,n=t.y;if(ue){let s=be(ue),i=pe(ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e*se,n*-se)}function ri(t,e,n=0){return y(I(t),"screenPos must be a vec2"),y(I(e),"screenSize must be a vec2"),y(D(n),"screenAngle must be a number"),[oi(t),e.scale(1/se),n+ue]}function xl(){return U.scale(1/se)}function Bf(t,e,n,s){y(I(t),"center must be a vec2"),y(I(e),"size must be a vec2");let i=d(n),r=d(s),a=e.x+i.left+i.right,o=e.y+i.top+i.bottom,c=U.x-r.left-r.right,l=U.y-r.top-r.bottom;if(!(a>0&&o>0&&c>0&&l>0))return se;se=de(c/a,l/o);let u=w(i.right-i.left,i.top-i.bottom).scale(.5),h=w(r.right-r.left,r.top-r.bottom).scale(.5/se);return Ge=t.add(u).add(h),se;function d(f){return(f===void 0||D(f))&&(f=w(f)),I(f)?{top:f.y,right:f.x,bottom:f.y,left:f.x}:{top:f.top||0,right:f.right||0,bottom:f.bottom||0,left:f.left||0}}}function jf(t,e=0){if(y(I(t),"pos must be a vec2"),y(I(e)||D(e),"size must be a vec2 or number"),!se)return!1;let n=t.x-Ge.x,s=t.y-Ge.y;if(ue){let a=be(ue),o=pe(ue),c=n*a-s*o,l=n*o+s*a;n=c,s=l}n*=se*2,s*=-se*2,e instanceof ge&&(e=e.length()),e*=se;let i=U.x,r=U.y;return n+e>-i&&n-e-r&&s-e{t.onerror=t.onload=o,t.crossOrigin="anonymous",t.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAAeAQMAAABnrVXaAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAAjpJREFUOMu9kzFu2zAUhn+CAROgqrk+B2l0BWYxMjlXeYaAtFtbdA1sGgHqRQfI0CNkSG5AwYB0BQ8d5Bsomwah6CPVeGg6tEPzAxLwyI+P78cP4u9lNO9OoMKnLMOobG5020/yaj/MrRcCGh1gBbyiLTPJEYaIiom5KM9Jq7KgynMGtb6L4GL4MF2H4LQKCXTvDVw2I4MsgZT7QLExdiutH+D08VOP3INXRrWX1/mmpbkNgAPYRVANb4xpcegYvhiNbIXauQICEjBuYLfMakaakWQeXxiZ0VDtuJCKs3ztMV59QtsHJNcRxDzfdL21ty3PrfIcXTN+E+GFAv6T5nbT9jd50/WFxb5ksdAv49qS6ouymG66ji08UMT6moykYLAo+V0j23GN4m829ZySAD5K7QsBfQTvOG8eE+gTeGYRAmnNAubN3hf5Zv9tJWDHp/VTuaSm7SN4fyINQqaNO3RMVxvpSPXnOChnRNvFcGY0gnwiPswYwTKVPE0zVtX3mTEIOoFzaqLrGuJaV+Uqumb71fVk/VoOH3cdLNQP/FHi8hV0CQNoqBZsUPlLPMsdCJro9QAaQQ0woDy9BJm0eTxCFnO9srcYlhNVlfR2EyTrph1uUtbUtAJifwRgrKuYdXVHeb0YI3QpawohQHkloI3J5FuVwI5ORxC9k2Tuz9Ir1IjgeIPGMHYkAZe2RuYkmWFmt3gGbTPOmBUWVTmRmHtGrfpzG/yuQNOKa6gBB/WA9khitPgl6/GP+gl2Af6tCbvaygAAAABJRU5ErkJggg=="});let e=w(),n=w(8),s=1,i=0,r=new Zt(t),a=new Bt(e,n,r,s,i);vl=new Di(a)}function Wf(t=!0){is=t}function qf(t){ma=t}function Hf(){return hn==="mouse"}function $f(){return hn==="keyboard"}function Yf(){return hn==="gamepad"}function ya(t,e=0,n=!0,s=!0,i=!0){oe[e]&&(oe[e][t]&=~((n?1:0)|(s?2:0)|(i?4:0)))}function ai(){oe.length=0,oe[0]=[],yt.length=0,Jn.length=0,ci.length=0,Rt.length=0,Rn.length=0}function Je(t,e=0){var n;return y(Z(t),"key must be a number or string"),y(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=oe[e])==null?void 0:n[t])&1)}function Ve(t,e=0){var n;return y(Z(t),"key must be a number or string"),y(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=oe[e])==null?void 0:n[t])&2)}function ga(t,e=0){var n;return y(Z(t),"key must be a number or string"),y(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=oe[e])==null?void 0:n[t])&4)}function Xf(t="ArrowUp",e="ArrowDown",n="ArrowLeft",s="ArrowRight"){y(Z(t),"up key must be a string"),y(Z(e),"down key must be a string"),y(Z(n),"left key must be a string"),y(Z(s),"right key must be a string");let i=r=>Je(r)?1:0;return w(i(s)-i(n),i(t)-i(e))}function Ds(t){return y(D(t),"mouse button must be a number"),Je(t)}function Js(t){return y(D(t),"mouse button must be a number"),Ve(t)}function Kf(t){return y(D(t),"mouse button must be a number"),ga(t)}function zt(t,e=ke){return y(D(t),"button must be a number"),y(D(e),"gamepad must be a number"),Je(t,e+1)}function ba(t,e=ke){return y(D(t),"button must be a number"),y(D(e),"gamepad must be a number"),Ve(t,e+1)}function Qf(t,e=ke){return y(D(t),"button must be a number"),y(D(e),"gamepad must be a number"),ga(t,e+1)}function Ns(t,e=ke){var n,s;return y(D(t),"stick must be a number"),y(D(e),"gamepad must be a number"),(s=(n=Rt[e])==null?void 0:n[t])!=null?s:w()}function cr(t=ke){var e;return y(D(t),"gamepad must be a number"),(e=Rn[t])!=null?e:w()}function lr(t=ke){return y(D(t),"gamepad must be a number"),!!oe[t+1]}function wl(t=ke){var e,n;return y(D(t),"gamepad must be a number"),(n=(e=Rt[t])==null?void 0:e.length)!=null?n:0}function Zf(t=ke,e=200,n=1,s=1,i=0){var a,o,c;if(y(D(t),"gamepad must be a number"),!si||X)return;let r=(a=navigator==null?void 0:navigator.getGamepads)==null?void 0:a.call(navigator)[t];(c=(o=r==null?void 0:r.vibrationActuator)==null?void 0:o.playEffect)==null||c.call(o,"dual-rumble",{duration:e,strongMagnitude:n,weakMagnitude:s,startDelay:i})}function eh(t=ke){var n,s,i;if(y(D(t),"gamepad must be a number"),!si||X)return;let e=(n=navigator==null?void 0:navigator.getGamepads)==null?void 0:n.call(navigator)[t];(i=(s=e==null?void 0:e.vibrationActuator)==null?void 0:s.reset)==null||i.call(s)}function xa(t=100){var e;y(D(t)||Tt(t),"pattern must be a number or array"),si&&!X&&((e=navigator==null?void 0:navigator.vibrate)==null||e.call(navigator,t))}function th(){xa(0)}function nh(){var t;!mt&&((t=$.requestPointerLock)==null||t.call($))}function sh(){var t;(t=document.exitPointerLock)==null||t.call(document)}function Tl(){return document.pointerLockElement===$}function ih(){if(X)return;document.addEventListener("keydown",t),document.addEventListener("keyup",e),document.addEventListener("mousedown",s),document.addEventListener("mouseup",i),document.addEventListener("mousemove",r),document.addEventListener("mouseleave",a),document.addEventListener("wheel",o,{passive:!1}),document.addEventListener("contextmenu",c),document.addEventListener("blur",l),mt&&Ln&&u();function t(d){if(d.repeat||(oe[0][d.code]=3,Ls&&(oe[0][n(d.code)]=3)),!is||!d.cancelable||!document.hasFocus()||d.ctrlKey||d.metaKey||d.altKey||p(d.target)||p(document.activeElement))return;let f=typeof d.key=="string"&&d.key.length===1;(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Space","Tab","Backspace"].includes(d.code)||f)&&d.preventDefault();function p(x){let v=x==null?void 0:x.tagName;return(x==null?void 0:x.isContentEditable)||["INPUT","TEXTAREA","SELECT"].includes(v)}}function e(d){oe[0][d.code]=oe[0][d.code]&2|4,Ls&&(oe[0][n(d.code)]=4)}function n(d){return Ls?d==="KeyW"?"ArrowUp":d==="KeyS"?"ArrowDown":d==="KeyA"?"ArrowLeft":d==="KeyD"?"ArrowRight":d:d}function s(d){if(mt&&Ln)return;it&&!X&&we&&!Us()&&we.resume(),oe[0][d.button]=3;let f=Ze;Ze=h(w(d.x,d.y)),Pt=Pt.add(Ze.subtract(f)),is&&d.cancelable&&document.hasFocus()&&d.preventDefault()}function i(d){mt&&Ln||(oe[0][d.button]=oe[0][d.button]&2|4)}function r(d){Ii=!0;let f=Ze;Ze=h(w(d.x,d.y));let m=Tl()?w(d.movementX,d.movementY):Ze.subtract(f);Pt=Pt.add(m)}function a(){Ii=!1}function o(d){d.ctrlKey||(pa+=ht(d.deltaY)),is&&d.cancelable&&document.hasFocus()&&d.preventDefault()}function c(d){d.preventDefault()}function l(){ai(),$t.clear(),yt.length=0,Jn.length=0,ci.length=0}function u(){document.addEventListener("touchstart",m=>f(m),{passive:!1}),document.addEventListener("touchmove",m=>f(m),{passive:!1}),document.addEventListener("touchend",m=>f(m),{passive:!1});let d;function f(m){if(Ln){if(it&&!X&&we&&!Us()&&we.resume(),!vn||aa){let p=S=>zs.includes(S.target)||S.target===Mn,x=[];for(let S of m.touches)p(S)||x.push(S);let v=x.length,A=0;if(v){let S=w(x[0].clientX,x[0].clientY),_=Ze;Ze=h(S),d?Pt=Pt.add(Ze.subtract(_)):oe[0][A]=3}else d&&(oe[0][A]=oe[0][A]&2|4);d=v}return is&&m.cancelable&&document.hasFocus()&&m.preventDefault(),!0}}}function h(d){let f=$.getBoundingClientRect(),m=He(d.x,f.left,f.right),p=He(d.y,f.top,f.bottom);return w(m*$.width,p*$.height)}}function Gc(){if(X)return;!(Ln&&mt)&&!document.hasFocus()&&ai(),Nt=oi(Ze),ha=bl(Pt),rh(),e(),t();function t(){let n=Ds(0)||Ds(1)||Ds(2)||Pt.length()>ma,s=!1;for(let r=wl();r--&&!s;)s=Ns(r).lengthSquared()>.04;for(let r=17;r--&&!s;)s=zt(r);let i=!1;for(let r in oe[0])if(isNaN(+r)&&oe[0][r]&1){i=!0;break}s?hn="gamepad":n?hn="mouse":i&&(hn="keyboard"),rs=hn==="gamepad"}function e(){var a,o,c,l,u,h,d;let n=f=>{let x=v=>v>.3?He(v,.3,.8):v<-.3?-He(-v,.3,.8):0;return w(x(f.x),x(-f.y)).clampLength()};if(vn&&mt){if(y(!Un||!gs,"set touchGamepadLeftStick or touchGamepadLeftButtonCount, not both"),y(!bs||!ys,"set touchGamepadRightStick or touchGamepadButtonCount, not both"),!ds.isSet())return;ke=0;let f=(a=Rt[0])!=null?a:Rt[0]=[],m=(o=Rn[0])!=null?o:Rn[0]=w();f.length=0,m.set();for(let x=0;x<2;x++){if(!en(x))continue;let v=wa(x);f[v]=w();let A=(c=Jn[x])!=null?c:w();if(ni)f[v]=n(A);else if(A.lengthSquared()>.3){let S=Y(Ci(A.x),-1,1),_=Y(Ci(A.y),-1,1);f[v]=w(S,-_).clampLength(),v||m.set(S,-_)}}let p=(l=oe[1])!=null?l:oe[1]=[];for(let x=12;x--;){let v=zt(x,0);p[x]=yt[x]?v?1:3:v?4:0,Ri&&p[x]===3&&(x===9||ah(x))&&xa(Ri)}return}try{if(!uo||!(navigator!=null&&navigator.getGamepads))return}catch{return}if(!qe&&!document.hasFocus())return;let s=8,i=navigator.getGamepads(),r=de(s,i.length);for(let f=0;f>1]=n(w(m.axes[S],m.axes[S+1]));let A=!1;for(let S=m.buttons.length;S--;){let _=m.buttons[S],k=zt(S,f);p[S]=_.pressed?k?1:3:k?4:0,_.pressed&&(!_.value||_.value>.9)&&(A=!0)}A&&(Zo[f]=!0,Zo[ke]||(ke=f)),m.mapping==="standard"&&v.set((zt(15,f)&&1)-(zt(14,f)&&1),(zt(12,f)&&1)-(zt(13,f)&&1)),ra&&(v.x||v.y)&&(x[0]=v.clampLength())}vn&&rs&&ds.unset()}}function Bc(){if(!X){for(let t of oe)for(let e in t)t[e]&=1;pa=0,ha=w(),Pt=w()}}function oh(){dh()}function rh(){if(un||!vn||!mt||X||!document.body)return;let t=un=document.createElement("div");t.style.cssText="position:fixed;inset:0;z-index:50;pointer-events:none;opacity:0;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;transition:opacity .2s;box-sizing:border-box;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)";let e=Al=document.createElement("div");e.style.cssText="position:relative;width:100%;height:100%;pointer-events:none",t.appendChild(e);let n=Sa=document.createElementNS(Gi,"svg");n.style.cssText="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible;fill:none;stroke:#fff;stroke-width:3",e.appendChild(n);let s=()=>{let i=document.createElement("div");return i.style.cssText="position:absolute;pointer-events:auto;touch-action:none",i.addEventListener("pointerdown",r=>mh(r,i)),i.addEventListener("pointermove",r=>yh(r)),i.addEventListener("pointerup",r=>jc(r)),i.addEventListener("pointercancel",r=>jc(r)),e.appendChild(i),i};zs[0]=s(),zs[1]=s(),Mn=s(),addEventListener("resize",()=>fs=!0),document.body.appendChild(t),fs=!0}function fo(){return Al.getBoundingClientRect()}function en(t){return t?bs:Un}function qn(t){return t?ys:gs}function va(t){return t?0:4}function wa(t){return t&&Un?1:0}function hs(t){return en(t)||qn(t)>0}function ah(t){for(let e=0;e<2;e++){let n=va(e);if(!en(e)&&t>=n&&tr.style.cssText="position:absolute;pointer-events:auto;touch-action:none;"+a;if(Dt){for(let r of zs)r.style.display="none";At?(i(Mn,"inset:0"),Mn.style.display=""):Mn.style.display="none"}else{for(let a=0;a<2;a++){let o=zs[a],c=a?"right":"left";if(o.style.display=hs(a)?"":"none",Tn){let l=hs(a?0:1)?"50%":"100%";i(o,`${c}:0;bottom:0;width:${l};height:60%`)}else i(o,`${c}:0;bottom:0;width:${3*s}px;height:${3*s}px`)}Mn.style.display=At?"":"none";let r=At;i(Mn,`left:50%;top:50%;width:${2*r}px;height:${2*r}px;transform:translate(-50%,-50%)`)}lh(e,n),fs=!1}function lh(t,e){let n=Sa;for(;n.firstChild;)n.removeChild(n.firstChild);let s=kl={face:[],thumb:[]},i=st,r=(o,c,l,u)=>{let h=document.createElementNS(Gi,"circle");return h.setAttribute("cx",o),h.setAttribute("cy",c),h.setAttribute("r",l),u&&h.setAttribute("fill",u),n.appendChild(h),h},a=o=>{let c=i*.18,l=i*.5,u=o.x,h=o.y,d=document.createElementNS(Gi,"path");d.setAttribute("d",`M ${u-c} ${h-l} H ${u+c} V ${h-c} H ${u+l} V ${h+c} H ${u+c} V ${h+l} H ${u-c} V ${h+c} H ${u-l} V ${h-c} H ${u-c} Z`),n.appendChild(d)};for(let o=0;o<2;o++){let c=qn(o),l=va(o),u=Xt(o,t,e);if(en(o))ni?r(u.x,u.y,i/2):a(u),s.thumb[o]=r(u.x,u.y,i/4,"#fff");else if(c===1)s.face[l]=r(u.x,u.y,i/2,"#000");else for(let h=0;h2?d:de(d,c-1);f=f===3?2:f===2?3:f;let m=w().setDirection(d,i/2);c===2&&(m.x*=-1),o||(m.x*=-1);let p=u.add(m);s.face[l+f]=r(p.x,p.y,i/4,"#000")}}qe&&Fn&&uh(t,e)}function uh(t,e){let n=st,s=Sa,i=(a,o,c)=>{let l=document.createElementNS(Gi,a);for(let u in o)l.setAttribute(u,o[u]);l.setAttribute("stroke",c),l.setAttribute("stroke-width",2),l.setAttribute("fill","none"),s.appendChild(l)},r=(a,o,c)=>i("circle",{cx:a.x,cy:a.y,r:o},c);i("line",{x1:t/2,y1:0,x2:t/2,y2:e},"#0f0");for(let a=0;a<2;a++)if(en(a))if(Tn){let o=e*.4,c=!hs(a?0:1),l=c?0:a?t/2:0;i("rect",{x:l,y:o,width:c?t:t/2,height:e-o},"#0ff")}else r(Xt(a,t,e),2*n,"#0ff");else qn(a)>=1&&r(Xt(a,t,e),n,"#0ff");if(At){r(w(t/2,e/2),At,"#ff0");for(let a=0;a<2;a++)hs(a)&&r(Xt(a,t,e),2*n,"#f0f")}}function dh(){var l;if(!un||X)return;if(!vn||!mt){un.style.display!=="none"&&(un.style.display="none",$t.clear(),yt.length=0,Jn.length=0,ci.length=0);return}un.style.display="";let t=qe&&Fn,e=[ys,gs,Un,bs,ni,st,Tn,At,Dt,t].join();e!==Fc&&(Fc=e,fs=!0),fs&&ch();let n=Os?He(ds.get(),Os+1,Os):1,s=t||ds.isSet()&&n>0&&!Dt;if(un.style.opacity=s?t?1:n*ca:0,!s)return;let i=fo(),r=i.width,a=i.height,o=st,c=kl;if(c){for(let u=0;u<2;u++)if(en(u)&&c.thumb[u]){let d=Xt(u,r,a).add(((l=Jn[u])!=null?l:w()).scale(o/2));c.thumb[u].setAttribute("cx",d.x),c.thumb[u].setAttribute("cy",d.y)}for(let u=0;u=st)return-1;if(i===1)return r;let o=a.subtract(e);t||(o.x*=-1);let c=i===2?o.xr:o&&Xt(a,e,n).distance(t)<2*s)return{role:"stick",side:a}}else if(qn(a)>=1){let c=hh(a,t,e,n);if(c>=0)return{role:"face",btn:c}}}if(At){for(let a=0;a<2;a++)if(hs(a)&&Xt(a,e,n).distance(t)<2*s)return;if(w(e/2,n/2).distance(t)h.getChannelData(x).set(p)),d.buffer=h,d.playbackRate.value=n,d.loop=i,a=a||we.createGain(),a.gain.value=e,a.connect(Kt);let f=new StereoPannerNode(we,{pan:Y(s,-1,1)});d.connect(f).connect(a),d.addEventListener("ended",()=>{a.disconnect(),f.disconnect(),c&&c(d)});let m=o*n;return d.start(0,m),qe&&ls&&_e("sound","vol",e.toFixed(2),"rate",n.toFixed(2),"pan",s.toFixed(2),i?"loop":""),d}function Sh(...t){return Ta([ho(...t)])}function ho(t=1,e=.05,n=220,s=0,i=0,r=.1,a=0,o=1,c=0,l=0,u=0,h=0,d=0,f=0,m=0,p=0,x=0,v=1,A=0,S=0,_=0){let k=xs,C=ie*2,O=c*=500*C/k/k,z=n*=(1+ve(e,-e))*C/k,re=0,te=0,T=0,R=1,P,L=[],M=0,N=0,W=0,ae,je=2,ft=C*he(_)*2/k,Pe=be(ft),rt=pe(ft)/2/je,Ae=1+rt,bt=-2*Pe/Ae,$n=(1-rt)/Ae,jt=(1+ht(_)*Pe)/2/Ae,Yn=-(ht(_)+Pe)/Ae,Ss=jt,tn=0,nn=0,sn=0,Xn=0;for(s=s*k||9,A*=k,i*=k,r*=k,x*=k,l*=500*C/k**3,m*=C/k,u*=C/k,h*=k,d=d*k|0,P=s+A+i+r+x|0;N1?a>2?a>3?a>4?M/C%14?W:ht(W)*he(W)**o)*(NN?0:(Nh&&(n+=u,z+=u,R=0),d&&!(++te%d)&&(n=z,c=O,R||(R=1));return L}function ji(t,e=!0){for(let n of bn)if((!e||n.isSolid)&&t.arrayCheck(n.size)){let s=n.getCollisionData(t);if(s)return s}return 0}function dn(t,e=w(),n,s=!0){for(let i of bn)if((!s||i.isSolid)&&i.collisionTest(t,e,n))return i}function El(t,e,n,s,i=!0){let r,a,o,c=s&&w();for(let l of bn)if(!i||l.isSolid){let u=l.collisionRaycast(t,e,n,c);if(u){let h=t.distanceSquared(u);(r===void 0||h{H=!1,fe.style.display="none",n.preventDefault(),_e("WebGL context lost! Switching to Canvas2d rendering.");for(let s of Is)s.glTexture=void 0;ut=void 0,Fe=0,Nn=!1,Dn.forEach(s=>{var i;return(i=s.glContextLost)==null?void 0:i.call(s)})}),fe.addEventListener("webglcontextrestored",()=>{H=!0,fe.style.display="",_e("WebGL context restored, reinitializing..."),e();for(let n of Is)n.glTexture=mo(n.image,n.wrap);Dn.forEach(n=>{var s;return(s=n.glContextRestored)==null?void 0:s.call(n)})});function e(){zi=ms(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 g;in vec4 p,u,c,a;in float r;out vec2 v;out vec4 d,e;void main(){vec2 s=(g-.5)*p.zw;gl_Position=m*vec4(p.xy+s*cos(r)-vec2(-s.y,s)*sin(r),1,1);v=mix(u.xw,u.zy,g);d=c;e=a;}`,`#version 300 es
+precision highp float;uniform sampler2D s;in vec2 v;in vec4 d,e;out vec4 c;void main(){c=texture(s,v)*d+e;}`),Ui=ms(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 p;in vec4 c;out vec4 d;void main(){gl_Position=m*vec4(p,1,1);d=c;}`,`#version 300 es
+precision highp float;in vec4 d;out vec4 c;void main(){c=d;}`);let n=new ArrayBuffer(Wi);We=new Float32Array(n),Hs=new Uint32Array(n),dr=g.createBuffer(),as=g.createBuffer(),ka=g.createFramebuffer(),Fe=0;let s=new Float32Array([0,0,1,0,0,1,1,1]);g.bindBuffer(g.ARRAY_BUFFER,as),g.bufferData(g.ARRAY_BUFFER,s,g.STATIC_DRAW);let i,r,a,o=(c,l,u,h,d=0)=>{let f=g.getAttribLocation(r,c),m=u===1,p=u&&a;g.enableVertexAttribArray(f),g.vertexAttribPointer(f,h,l,m,p,i),g.vertexAttribDivisor(f,d),i+=h*u};fr=g.createVertexArray(),g.bindVertexArray(fr),i=0,r=zi,a=Pl,g.bindBuffer(g.ARRAY_BUFFER,as),o("g",g.FLOAT,0,2),g.bindBuffer(g.ARRAY_BUFFER,dr),g.bufferData(g.ARRAY_BUFFER,Wi,g.DYNAMIC_DRAW),o("p",g.FLOAT,4,4,1),o("u",g.FLOAT,4,4,1),o("c",g.UNSIGNED_BYTE,1,4,1),o("a",g.UNSIGNED_BYTE,1,4,1),o("r",g.FLOAT,4,1,1),hr=g.createVertexArray(),g.bindVertexArray(hr),i=0,r=Ui,a=Rl,o("p",g.FLOAT,4,2),o("c",g.UNSIGNED_BYTE,1,4)}}function $s(t=!1){!t&&!Nn||(Be(),Nn=!1,g.useProgram(zi),g.bindVertexArray(fr))}function Ml(){Nn||(Be(),Nn=!0,g.useProgram(Ui),g.bindVertexArray(hr))}function mr(t=!0){if(!H||!g)return;y(!Fe,"glPreRender called with unflushed batch."),Vi||(fe.width=U.x,fe.height=U.y),g.viewport(0,0,U.x,U.y),t&&Ll();let e=w(2*se).divide(U);Vi&&(e.y=-e.y);let n=Ge.rotate(-ue),s=w(-1).subtract(n.multiply(e)),i=be(ue),r=pe(ue),a=[e.x*i,e.y*r,0,0,-e.x*r,e.y*i,0,0,1,1,1,0,s.x,s.y,0,1],o=(c,l,u)=>{g.useProgram(c);let h=g.getUniformLocation(c,l);g.uniformMatrix4fv(h,!1,u)};o(Ui,"m",a),o(zi,"m",a),g.activeTexture(g.TEXTURE0),wn[0]&&(ut=wn[0].glTexture,g.bindTexture(g.TEXTURE_2D,ut)),g.bindBuffer(g.ARRAY_BUFFER,dr),Hn=ps=!1,$s(!0)}function Ll(){if(!g)return;let t=mn;g.clearColor(t.r,t.g,t.b,t.a),g.clear(g.COLOR_BUFFER_BIT)}function _a(t){!g||t===ut||(Be(),ut=t,g.bindTexture(g.TEXTURE_2D,ut))}function Ol(t,e=!0){if(!g||!t)return;let n=t===ut;n?Be():g.bindTexture(g.TEXTURE_2D,t);let s=e?g.REPEAT:g.CLAMP_TO_EDGE;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,s),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,s),!n&&ut&&g.bindTexture(g.TEXTURE_2D,ut)}function yr(t,e){if(!g)return;let n=g.createShader(e);if(g.shaderSource(n,t),g.compileShader(n),qe&&!g.getShaderParameter(n,g.COMPILE_STATUS))throw g.getShaderInfoLog(n);return n}function ms(t,e){if(!g)return;let n=g.createProgram();if(g.attachShader(n,yr(t,g.VERTEX_SHADER)),g.attachShader(n,yr(e,g.FRAGMENT_SHADER)),g.linkProgram(n),qe&&!g.getProgramParameter(n,g.LINK_STATUS))throw g.getProgramInfoLog(n);return n}function mo(t,e=!1){if(!g)return;let n=g.createTexture(),s=!1;if(t!=null&&t.width)Ea(n,t),g.bindTexture(g.TEXTURE_2D,n),s=!jn&&Gs(t.width)&&Gs(t.height);else{let o=new Uint8Array([255,255,255,255]);g.bindTexture(g.TEXTURE_2D,n),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,1,1,0,g.RGBA,g.UNSIGNED_BYTE,o)}let i=jn?g.NEAREST:g.LINEAR,r=s?g.LINEAR_MIPMAP_LINEAR:i;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,i),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,r);let a=e?g.REPEAT:g.CLAMP_TO_EDGE;return g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,a),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,a),s&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,ut),n}function Dl(t){g&&g.deleteTexture(t)}function Ea(t,e){g&&(y((e==null?void 0:e.width)>0,"Invalid image data."),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e),!jn&&Gs(e.width)&&Gs(e.height)&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,ut))}function kh(t){X||(Is.add(t),g&&(t.glTexture?Ea(t.glTexture,t.image):t.glTexture=mo(t.image,t.wrap)))}function Ch(t){if(X)return;Is.delete(t);let e=t.glTexture;t.glTexture=void 0,Dl(e)}function Be(){if(H&&g&&Fe){let t=ps?g.ONE:g.ONE_MINUS_SRC_ALPHA;g.blendFuncSeparate(g.SRC_ALPHA,t,g.ONE,t),g.enable(g.BLEND);let e=Fe*(Nn?po:Ca);g.bufferSubData(g.ARRAY_BUFFER,0,We,0,e),Nn?g.drawArrays(g.TRIANGLE_STRIP,0,Fe):g.drawArraysInstanced(g.TRIANGLE_STRIP,0,4,Fe),++Ft,Gt+=Fe,Fe=0}ps=Hn}function Pa(t){!H||!g||(Be(),t.drawImage(fe,0,0))}function _h(t=!0){y(!fe,"must be called before engineInit"),Aa=t}function Ys(t,e,n,s,i=0,r=0,a=0,o=1,c=1,l=-1,u=0){(Fe>=Th||ps!==Hn)&&Be(),$s();let h=Fe++*Ca;We[h++]=t,We[h++]=e,We[h++]=n,We[h++]=s,We[h++]=r,We[h++]=a,We[h++]=o,We[h++]=c,Hs[h++]=l,Hs[h++]=u,We[h++]=i}function Il(t,e,n,s,i,r){Ys(t,e,n,s,i,0,0,0,0,0,r)}function Ra(t,e,n,s,i,r,a,o=!0){let c=[],l=pe(-a),u=be(-a);for(let d of t){let f=d.x*i,m=d.y*r;c.push(w(n+u*f-l*m,s+l*f+u*m))}let h=o?Ph(c):c;Fl(h,e)}function Ma(t,e,n,s,i,r,a,o,c=!0){let l=Eh(t,n,c);Ra(l,e,s,i,r,a,o,!1)}function Fl(t,e){if(!H||t.length<3)return;let n=t.length+2;if((Fe+n>=cs||ps!==Hn)&&Be(),y(n=cs)return;Ml();let s=Fe*po;for(let i=n;i--;){let r=Y(i-1,0,n-3),a=t[r];We[s++]=a.x,We[s++]=a.y,Hs[s++]=e}Fe+=n}function La(t,e){if(!H||t.length<3)return;let n=t.length+2;if((Fe+n>=cs||ps!==Hn)&&Be(),y(n=cs)return;Ml();let s=Fe*po;for(let i=n;i--;){let r=Y(i-1,0,n-3),a=t[r],o=e[r];We[s++]=a.x,We[s++]=a.y,Hs[s++]=o}Fe+=n}function Rs(t,e=!1){t?(Vi=t,g.bindFramebuffer(g.FRAMEBUFFER,ka),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,t,0),mr(e)):(Be(),Vi=void 0,g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,U.x,U.y))}function Gl(t,e,n,s){H&&(g.enable(g.SCISSOR_TEST),g.scissor(t,e,n,s),g.clearColor(0,0,0,0),g.clear(g.COLOR_BUFFER_BIT),g.disable(g.SCISSOR_TEST))}function Eh(t,e,n=!0){if(t.length<2)return[];let s=e/2,i=[],r=t.length,a=1e-6,o=10;for(let c=0;ca?-f/m:0,S=m>a?d/m:0,_=v>a?-x/v:0,k=v>a?p/v:0,C=A+_,O=S+k,z=(C*C+O*O)**.5;if(za){let R=de(1/T,o);C*=R,O*=R}}let re=w(u.x-C*s,u.y-O*s),te=w(u.x+C*s,u.y+O*s);i.push(re),i.push(te)}return i.length>1&&n&&(i.push(i[0]),i.push(i[1])),i}function Ph(t){if(t.length<3)return[];let e=(f,m,p)=>(m.x-f.x)*(p.y-f.y)-(m.y-f.y)*(p.x-f.x);(f=>{let m=0;for(let p=f.length;p--;){let x=(p+1)%f.length;m+=f[p].cross(f[x])}return m})(t)<0&&(t=t.slice().reverse());let s=1e-9,i=(f,m,p,x)=>{let v=e(m,p,f),A=e(p,x,f),S=e(x,m,f),_=(v<-s?1:0)+(A<-s?1:0)+(S<-s?1:0),k=(v>s?1:0)+(A>s?1:0)+(S>s?1:0);return!(_&&k)},r=[];for(let f=0;f3&&o++{if(_>=0){let C=s.fillStyle=s.createLinearGradient(x,v,A,S);C.addColorStop(0,h(_,2)),C.addColorStop(1,h(_,1))}else s.fillStyle="#000";_>=-1?(s.fill(),k&&s.stroke()):s.stroke()},c=(x,v,A,S=0,_=2*ie,k,C)=>{s.beginPath(),s.arc(x,v,A,f*S,f*_),o(x,v-A,x,v+A,k,C)},l=(x,v,A,S,_)=>{s.beginPath(),s.rect(x,v,A,S*f),o(x,v+S,x+A,v,_)},u=(x,v,A,S)=>{s.beginPath();for(let _ of x)s.lineTo(_.x,_.y);s.closePath(),o(0,A,0,A+S,v)},h=(x,v)=>v?`hsl(${[.95,.56,.13][x%3]*360} 99%${[0,50,75][v]}%)`:"#000",d=sl(1,1,t),f=He(d,.1,.5),m=de(6,de(r,a)/99);s.translate(r/2,a/2),s.scale(m,m),s.translate(-40,-35),f<1&&s.setLineDash([99*f,99]),s.lineJoin=s.lineCap="round",s.lineWidth=.1+f*1.9;{let v="LittleJS";s.font="900 15.5px arial",s.lineWidth=.1+f*3.9,s.textAlign="center",s.textBaseline="top",l(11,55,59,8*f,-1),s.beginPath();let A=0;for(let S=0;S5?1:0),s[S?"strokeText":"fillText"](v[_],O,54+.5,17*f),k+=C}s.lineWidth=.1+f*1.9,l(3,54,73,0)}l(7,15,26,-7,0),l(25,15,8,25,-1),l(10,40,15,-25,1),l(14,21,7,9,2),l(38,20,6,-6,2),l(49,20,10,-6,0);let p=[w(44,8),w(64,8),w(59,8+6*f),w(49,8+6*f)];u(p,2,8,6*f),l(44,8,20,-7,0);for(let x=5;x--;)c(59-x*6*f,30,10,0,2*ie,1,0);c(59,30,4,0,7,2),l(35,20,24,0),c(59,30,10),c(47,30,10,ie/2,ie*3/2),c(35,30,10,ie/2,ie*3/2),l(7,40,13,7,-1),l(17,40,43,14,-1);for(let x=3;x--;)for(let v=2;v--;)c(17+15*x,47,v?7:1,0,2*ie,2);for(let x=2;x--;){let v=6,A=7,S=53+v*f*x,_=[w(S+A,54),w(S,40),w(S+v*f,40),w(S+A+v*f,54)];u(_,0,40,14)}s.restore()}function Mh(t){if($i=t,!Pn){let n={};try{n=JSON.parse(localStorage[t]||"{}")}catch{n={}}yo(s=>{s.unlocked=!!(n[s.id]&&n[s.id].unlocked)}),Da()}zn(void 0,e);function e(){if(!wi.length)return;let n=wi[0],s=xn-vi;if(!vi)vi=xn;else if(s>qi)vi=0,wi.shift();else{let i=qi-os,r=si?(s-i)/os:0;n.render(r)}}}function yo(t){Object.values(Xs).forEach(e=>t(e))}function Lh(){yo(t=>t.unlocked=!1),Da()}function Da(){if(!$i)return;let t={};yo(e=>{let n={name:e.name,description:e.description,icon:e.icon,unlocked:e.unlocked};e.image&&(n.src=e.image.src),t[e.id]=n}),localStorage[$i]=JSON.stringify(t)}function Oh(t){qi=t}function Dh(t){os=t}function Ih(t){Hi=t.copy()}function Fh(t){Oa=t}function Bl(t,e,n,s=125){let i,r,a,o,c,l,u,h,d,f,m,p,x,v=0,A,S=[],_=[],k=[],C=0,O=0,z=1,re={},te=xs/s*60>>2;for(;z;C++)S=[z=h=p=0],n.forEach((T,R)=>{for(u=e[T][C]||[0,0,0],z|=e[T][C]&&1,A=p+(e[T][0].length-2-(h?0:1))*te,x=R===n.length-1,i=2,a=p;ite-99&&d&&m<1?m+=1/99:0)l=(1-m)*S[v++]/2||0,_[a]=(_[a]||0)-l*O+l,k[a]=(k[a++]||0)+l*O+l;c&&(m=c%1,O=u[1]||0,(c|=0)&&(S=re[[f=u[v=0]||0,c]]=re[[f,c]]||(o=[...t[f]],o[2]=(o[2]||220)*2**(c/12-1),c>0?ho(...o):[])))}p=A});return[_,k]}function Gh(t){Ia=typeof t=="boolean"?t?1:0:t}function Bh(t){Fa=t}async function jh(){return new eo(await Box2D()),n(),zn(t,e),b;function t(){if(!Dt){b.step(),b.objects=b.objects.filter(s=>!s.destroyed);for(let s of b.objects)s.body&&(s.pos=b.vec2From(s.body.GetPosition()),s.angle=-s.body.GetAngle())}}function e(){(Fa||vt)&&b.world.DrawDebugData()}function n(){let i=new b.instance.JSDraw,r=l=>new Oe(l.get_r(),l.get_g(),l.get_b()),a=l=>r(b.instance.wrapPointer(l,b.instance.b2Color)),o=l=>a(l).scale(1,.8),c=(l,u)=>{let h=[];for(let d=u;d--;)h.push(b.vec2FromPointer(l+d*8));return h};i.DrawSegment=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),u=b.vec2FromPointer(u),On(l,u,.1,h,w(),0,!1)},i.DrawPolygon=function(l,u,h){h=o(h);let d=c(l,u);us(d,Sn,.1,h,w(),0,!1)},i.DrawSolidPolygon=function(l,u,h){h=o(h);let d=c(l,u);us(d,h,0,h,w(),0,!1)},i.DrawCircle=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),Oi(l,u*2,Sn,.1,h,!1)},i.DrawSolidCircle=function(l,u,h,d){d=o(d),l=b.vec2FromPointer(l),h=b.vec2FromPointer(h).scale(u),Oi(l,u*2,d,.1,d,!1),On(w(),h,.1,d,l,0,!1)},i.DrawTransform=function(l){l=b.instance.wrapPointer(l,b.instance.b2Transform);let u=b.vec2From(l.get_p()),h=-l.get_q().GetAngle(),d=w(1,0),f=K(.75,0,0,.8),m=w(0,1),p=K(0,.75,0,.8);On(w(),d,.1,f,u,h,!1),On(w(),m,.1,p,u,h,!1)},i.AppendFlags(b.instance.b2Draw.e_shapeBit),i.AppendFlags(b.instance.b2Draw.e_jointBit),b.world.SetDebugDraw(i)}}function Jh(t,e,n,s=32,i=2,r=0){jl(t,e,n,ee,s,me,i,r,!1,!0)}function jl(t,e,n,s,i=1,r,a=.05,o=0,c=H,l,u){let h=n.offset(n.size),d=e.add(w(a-i*2)),f=w(i),m=e.scale(.5).subtract(f.scale(.5)),p=l?-1:1,x=l?-o:o;Ne(t,d,h,s,o,!1,r,c,l,u);for(let v=4;v--;){let A=v%2,S=m.multiply(w(A?v===1?1:-1:0,A?0:v?-1:1)),_=w(A?i:d.x,A?d.y:i),k=h.offset(n.size.multiply(w(v===1?1:v===3?-1:0,v===0?-p:v===2?p:0)));Ne(t.add(S.rotate(x)),_,k,s,o,!1,r,c,l,u)}for(let v=4;v--;){let A=v>1,S=v&&v<3,_=m.multiply(w(A?-1:1,S?-1:1)),k=h.offset(n.size.multiply(w(A?-1:1,S?p:-p)));Ne(t.add(_.rotate(x)),f,k,s,o,!1,r,c,l,u)}}function Nh(t,e,n,s=32,i=2,r=0){Jl(t,e,n,ee,s,me,i,r,!1,!0)}function Jl(t,e,n,s,i=1,r,a=.05,o=0,c=H,l,u){let h=n.frame(0),d=n.frame(1),f=n.frame(2),m=e.add(w(a-i*2)),p=w(i),x=e.scale(.5).subtract(p.scale(.5)),v=l?-1:1,A=l?-o:o;Ne(t,m,f,s,o,!1,r,c,l,u);for(let S=4;S--;){let _=o+S*ie/2,k=S%2,C=x.multiply(w(k?S===1?1:-1:0,k?0:S?-v:v)),O=w(k?m.y:m.x,i);Ne(t.add(C.rotate(A)),O,d,s,_,!1,r,c,l,u)}for(let S=4;S--;){let _=o+S*ie/2,k=!S||S>2,C=S>1,O=x.multiply(w(k?-1:1,C?-v:v));Ne(t.add(O.rotate(A)),p,h,s,_,!1,r,c,l,u)}}function zh(t,e=1,n=0,s=ee,i=0,r=!1,a=0,o=me,c=H,l=!1,u){let h=Nl(w(),e,n,0,r);us(h,s,a,o,t,i,c,l,u)}function Nl(t,e=1,n=0,s=0,i=!1,r=ti){y(I(t),"pos must be a vec2"),y(D(e)&&D(n),"size and percent must be numbers");let a=pt(n*4,4);a>=2&&(s+=ie),a=a<=2?a-1:3-a,i&&(a=-a,s+=ie);let o=[],c=le(3,r>>1),l=e/2;for(let u=0;u<=c;u++){let h=u/c*ie;o.push(w(l*be(h),l*pe(h)).rotate(s).add(t))}for(let u=c;u>=0;u--){let h=u/c*ie;o.push(w(l*be(h),-l*a*pe(h)).rotate(s).add(t))}return o}function zc(t){return t&&typeof t.lerp=="function"}function Uh(t,e,n,s,i=1,r={}){y(t!=null&&typeof t=="object","tweenProperty target must be an object"),y(Z(e)&&e.length>0,"tweenProperty propertyPath must be a non-empty string");let a=e.split("."),o=a.pop(),c=l=>{let u=t;for(let h of a)u=u[h];u[o]=l};return new to(c,n,s,i,r)}function zl(t){t.loopRemaining!==1/0&&t.loopRemaining<=1||(t.loopRemaining!==1/0&&(t.loopRemaining-=1),t.life=t.duration,t.thenCallback=()=>zl(t),ct.push(t),t.callback(t.interp(t.duration)))}function Ul(t){if(t.loopRemaining!==1/0&&t.loopRemaining<=1)return;t.loopRemaining!==1/0&&(t.loopRemaining-=1);let e=t.start;t.start=t.end,t.end=e,t.life=t.duration,t.thenCallback=()=>Ul(t),ct.push(t),t.callback(t.interp(t.duration))}function Vl(t,e){t===void 0?(t=lt-Jc,e=xn-Nc,Jc=lt,Nc=xn):e===void 0&&(e=t);for(let n=ct.length;n--;){let s=ct[n];if(s.paused)continue;let i=s.useRealTime?e:t;if(!(i<=0))if(s.life-=i,s.life>0)s.callback(s.interp(s.life));else{s.callback(s.interp(0)),ct.splice(n,1);let r=s.thenCallback;s.thenCallback=void 0,r&&r()}}}function Vh(){for(let t of ct)t.thenCallback=void 0;ct.length=0}var Ti,Ai,sd,Vr,Ee,Wr,Uc,lt,xn,Dt,Qo,Et,ki,Vc,Dn,tr,qe,Hc,io,$c,Ut,pn,vt,wt,In,Fn,ls,nr,Vt,St,ie,he,Le,Fs,Ci,de,le,ht,Qc,Zc,pe,be,el,Hr,or,ge,Oe,ee,Sn,me,kt,vd,Xr,wd,ll,ul,Td,dl,fl,Ad,It,Ge,ue,se,Qr,oo,mn,ts,Ms,ns,ss,Zr,jn,yn,ei,ea,X,H,ti,ro,ao,co,lo,ta,na,sa,ia,oa,qt,tt,Pi,uo,ra,Ls,Ln,vn,aa,At,ys,Un,gs,bs,ni,Tn,st,ca,Os,Ri,si,it,Gn,la,ua,Qt,$,xe,Ie,Yt,fn,Mt,Ht,U,wn,Ft,Gt,Bt,Zt,Df,vl,Di,Nt,Ze,ha,Pt,pa,Ii,rs,hn,ma,is,ke,mt,oe,Rt,Rn,Zo,ds,yt,Jn,Fi,ci,$t,un,Al,Sa,kl,zs,Mn,fs,Fc,Gi,we,Kt,xs,Vs,Bi,bn,Bn,Ji,Ws,qs,ur,wh,Ni,fe,g,Aa,zi,Ui,Nn,Hn,ps,ut,dr,as,We,Hs,Fe,Is,fr,hr,ka,Vi,pr,Wi,Ca,Pl,Th,po,Rl,cs,Pn,qi,os,Hi,Oa,Xs,wi,$i,vi,Yi,Ks,gr,br,Ue,xr,ne,Sr,vr,wr,E,Ia,Tr,gt,Xi,Ar,kr,Qs,Cr,_r,Er,Pr,b,Fa,Zs,Ki,Rr,Mr,Qi,ot,Lr,Zi,Or,Dr,Ir,Fr,Gr,Br,jr,Jr,Nr,zr,eo,ct,Jc,Nc,to,no,Wh,er,so,Ur,ql=Kl(()=>{"use strict";Ti="LittleJS",Ai="1.18.19",sd=60,Vr=.016666666666666666,Ee=[],Wr=[],Uc=0,lt=0,xn=0,Dt=!1;Qo=0,Et=0,ki=0,Vc=!0,Dn=[],tr=class{constructor(e,n,s,i){this.update=e,this.render=n,this.glContextLost=s,this.glContextRestored=i}};qe=!0,Hc=.5,io=!0,$c="Escape",Ut=!1,pn=[],vt=!1,wt=!1,In=!1,Fn=!1,ls=!1;ie=Math.PI,he=Math.abs,Le=Math.floor,Fs=Math.ceil,Ci=Math.round,de=Math.min,le=Math.max,ht=t=>Math.sign(t),Qc=(...t)=>Math.hypot(...t),Zc=t=>Math.log2(t),pe=Math.sin,be=Math.cos,el=Math.tan,Hr=Math.atan2;or=class{constructor(e=123456789){y(e!==0,"RandomGenerator seed must be non-zero (xorshift is fixed at 0)"),this.seed=e}float(e=1,n=0){return this.seed^=this.seed<<13,this.seed^=this.seed>>>17,this.seed^=this.seed<<5,n+(e-n)*((this.seed>>>0)/2**32)}int(e,n=0){return Le(this.float(e,n))}bool(e=.5){return this.float().5?1:-1}floatSign(e=1,n=0){let s=de(e,n),r=le(e,n)-s,a=this.float(r*2);return ae?this.scale(e/n):this.copy()}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.x}reflect(e,n=1){return this.subtract(e.scale((1+n)*this.dot(e)))}angle(){return Hr(this.x,this.y)}setAngle(e=0,n=1){return at(e),at(n),this.x=n*pe(e),this.y=n*be(e),this}rotate(e){at(e);let n=be(-e),s=pe(-e);return new t(this.x*n-this.y*s,this.x*s+this.y*n)}setDirection(e,n=1){return at(e),at(n),e=pt(e,4),y(e===0||e===1||e===2||e===3,"Vector2.setDirection() direction must be an integer between 0 and 3."),this.x=e%2?e-1?-n:n:0,this.y=e%2?0:e?-n:n,this}direction(){return he(this.x)>he(this.y)?this.x<0?3:1:this.y<0?2:0}abs(){return new t(he(this.x),he(this.y))}floor(){return new t(Le(this.x),Le(this.y))}snap(e){return at(e),new t(Le(this.x*e)/e,Le(this.y*e)/e)}mod(e=1){return new t(pt(this.x,e),pt(this.y,e))}area(){return he(this.x*this.y)}lerp(e,n){Dc(e),at(n);let s=Y(n);return new t(e.x*s+this.x*(1-s),e.y*s+this.y*(1-s))}arrayCheck(e){return this.x>=0&&this.y>=0&&this.x(u=pt(u,1))*6<1?c+(l-c)*6*u:u*2<1?l:u*3<2?c+(l-c)*(4-u*6):c;return this.r=o(a,r,e+1/3),this.g=o(a,r,e),this.b=o(a,r,e-1/3),this.a=i,Ps(this),this}HSLA(){let e=Y(this.r),n=Y(this.g),s=Y(this.b),i=Y(this.a),r=le(e,n,s),a=de(e,n,s),o=(r+a)/2,c=0,l=0;if(r!==a){let u=r-a;l=o>.5?u/(2-r-a):u/(r+a),e===r?c=(n-s)/u+(n((s=Y(s)*255|0)<16?"0":"")+s.toString(16);return"#"+n(this.r)+n(this.g)+n(this.b)+(e?n(this.a):"")}setHex(e){if(y(Z(e),"Color hex code must be a string"),y(e[0]==="#","Color hex code must start with #"),y([4,5,7,9].includes(e.length),"Invalid hex"),e.length<6){let n=s=>Y(parseInt(e[s],16)/15);this.r=n(1),this.g=n(2),this.b=n(3),this.a=e.length===5?n(4):1}else{let n=s=>Y(parseInt(e.slice(s,s+2),16)/255);this.r=n(1),this.g=n(3),this.b=n(5),this.a=e.length===9?n(7):1}return Ps(this),this}rgbaInt(){let e=Y(this.r)*255|0,n=Y(this.g)*255<<8,s=Y(this.b)*255<<16,i=Y(this.a)*255<<24;return e+n+s+i}isValid(){return D(this.r)&&D(this.g)&&D(this.b)&&D(this.a)}},ee=dt(K()),Sn=dt(K(1,1,1,0)),me=dt(K(0,0,0)),kt=dt(K(0,0,0,0)),vd=dt(K(.5,.5,.5)),Xr=dt(K(1,0,0)),wd=dt(K(1,.5,0)),ll=dt(K(1,1,0)),ul=dt(K(0,1,0)),Td=dt(K(0,1,1)),dl=dt(K(0,0,1)),fl=dt(K(.5,0,1)),Ad=dt(K(1,0,1)),It=class{constructor(e,n=!1){y(e===void 0||D(e),"Constructed Timer is invalid.",e),this.useRealTime=n;let s=this.getGlobalTime();this.time=e===void 0?void 0:s+e,this.setTime=e}set(e=0){y(D(e),"Timer is invalid.",e);let n=this.getGlobalTime();this.time=n+e,this.setTime=e}setUseRealTime(e=!0){y(!this.isSet(),"Cannot change global time setting while timer is set."),this.useRealTime=e}unset(){this.time=void 0}isSet(){return this.time!==void 0}active(){return this.getGlobalTime()=this.time}get(){return this.isSet()?this.getGlobalTime()-this.time:0}getPercent(){return this.isSet()?this.setTime?1-He(this.time-this.getGlobalTime(),0,this.setTime):1:0}getSetTime(){return this.isSet()?this.setTime:0}getGlobalTime(){return this.useRealTime?xn:lt}toString(){return this.isSet()?he(this.get())+" seconds "+(this.get()<0?"before":"after"):"unset"}valueOf(){return this.get()}};Ge=w(),ue=0,se=32,Qr=1,oo=!0,mn=kt,ts=w(1920,1080),Ms=0,ns=0,ss=w(),Zr=!1,jn=!0,yn=1,ei="arial",ea=!1,X=!1,H=!0,ti=32,ro=w(16),ao=0,co=0,lo=!0,ta=1,na=1,sa=1,ia=0,oa=.8,qt=1,tt=w(),Pi=1,uo=!0,ra=!0,Ls=!0,Ln=!0,vn=!1,aa=!1,At=0,ys=4,Un=!0,gs=0,bs=!1,ni=!0,Tn=!1,st=100,ca=.3,Os=3,Ri=0,si=!0,it=!0,Gn=.3,la=40,ua=.7;Qt=class t{constructor(e=w(),n=w(1),s,i=0,r=ee,a=0){y(I(e),"object pos must be a vec2"),y(I(n),"object size must be a vec2"),y(!s||s instanceof Bt,"object tileInfo should be a TileInfo or undefined"),y(typeof i=="number"&&isFinite(i),"object angle should be a number"),y(Q(r),"object color should be a valid rgba color"),y(typeof a=="number","object renderOrder should be a number"),this.pos=e.copy(),this.size=n.copy(),this.drawSize=void 0,this.tileInfo=s,this.angle=i,this.color=r.copy(),this.additiveColor=void 0,this.mirror=!1,this.destroyed=!1,this.mass=ta,this.damping=na,this.angleDamping=sa,this.restitution=ia,this.friction=oa,this.gravityScale=1,this.renderOrder=a,this.velocity=w(),this.angleVelocity=0,this.spawnTime=lt,this.children=[],this.clampSpeed=!0,this.groundObject=void 0,this.parent=void 0,this.localPos=w(),this.localAngle=0,this.collideTiles=!1,this.collideSolidObjects=!1,this.isSolid=!1,this.collideRaycast=!1,Ee.push(this)}updateTransforms(){let e=this.parent;if(e){let n=e.getMirrorSign(),s=this.localPos,i=e.pos,r=s.x*n,a=s.y,o=e.angle;if(o){let c=be(-o),l=pe(-o);this.pos.set(r*c-a*l+i.x,r*l+a*c+i.y)}else this.pos.set(r+i.x,a+i.y);this.angle=n*this.localAngle+o}for(let n of this.children)n.updateTransforms()}updatePhysics(){if(y(!this.parent),this.destroyed)return;this.clampSpeed&&(this.velocity.x=Y(this.velocity.x,-qt,qt),this.velocity.y=Y(this.velocity.y,-qt,qt));let e=this.pos.copy();if(this.velocity.x*=this.damping,this.velocity.y*=this.damping,this.mass&&(this.velocity.x+=tt.x*this.gravityScale,this.velocity.y+=tt.y*this.gravityScale),this.pos.x+=this.velocity.x,this.pos.y+=this.velocity.y,this.angle+=this.angleVelocity*=this.angleDamping,y(this.angleDamping>=0&&this.angleDamping<=1),y(this.damping>=0&&this.damping<=1),!lo||!this.mass)return;let n=this.velocity.y<0&&tt.y<0||this.velocity.y>0&&tt.y>0;if(this.groundObject){let s=le(this.friction,this.groundObject.friction),i=this.groundObject.velocity.x;this.velocity.x=i+(this.velocity.x-i)*s,this.groundObject=void 0}if(this.collideSolidObjects)for(let i of Wr){if(i.destroyed||i.parent||i===this||!this.isSolid&&!i.isSolid||!this.isOverlappingObject(i))continue;let r=this.collideWithObject(i),a=i.collideWithObject(this);if(!r||!a)continue;if(Ei(e,this.size,i.pos,i.size)){let d=e.subtract(i.pos),f=d.length(),p=f<.001?w(0,1):d.scale(.001/f);this.velocity=this.velocity.add(p),i.mass&&(i.velocity=i.velocity.subtract(p)),vt&&sr(this.pos,this.size,i.pos,i.size,"#f00");continue}let o=this.size.add(i.size),c=(e.y-i.pos.y)*2>o.y+tt.y,l=he(e.y-i.pos.y)*20?-1:1)>0?Le(e.y-this.size.y/2+1)+this.size.y/2+.001:Fs(e.y+this.size.y/2-1)-this.size.y/2-.001;if(he(u-this.pos.y)<.1&&!dn(w(this.pos.x,u),this.size,this)){this.pos.y=u,vt&&Ce(this.pos,this.size,"#ff0");return}this.pos.x=e.x,this.velocity.x*=-a}if(r||!i){if(n){let c=this.size.y/2+1e-4;this.pos.y=tt.y<0?Le(e.y-this.size.y/2)+c:Fs(e.y+this.size.y/2)-c,this.groundObject=s}else this.pos.y=e.y,this.groundObject=void 0;this.velocity.y*=-a}vt&&Ce(this.pos,this.size,"#f00")}}}update(){}render(){Ne(this.pos,this.drawSize||this.size,this.tileInfo,this.color,this.angle,this.mirror,this.additiveColor)}renderLight(){}destroy(e=!1){var n;if(!this.destroyed){this.destroyed=!0,(n=this.parent)==null||n.removeChild(this);for(let s of this.children)s.parent=void 0,s.destroy(e)}}localToWorld(e){return this.pos.add(e.rotate(this.angle))}worldToLocal(e){return e.subtract(this.pos).rotate(-this.angle)}localToWorldVector(e){return e.rotate(this.angle)}worldToLocalVector(e){return e.rotate(-this.angle)}collideWithTile(e,n){return e>0}collideWithObject(e){return!0}getUp(e=1){return w().setAngle(this.angle,e)}getRight(e=1){return w().setAngle(this.angle+ie/2,e)}getAliveTime(){return lt-this.spawnTime}getSpeed(){return this.velocity.length()}applyAcceleration(e){this.mass&&(this.velocity=this.velocity.add(e))}applyAngularAcceleration(e){this.mass&&(this.angleVelocity+=e)}applyForce(e){this.mass&&this.applyAcceleration(e.scale(1/this.mass))}getMirrorSign(){return this.mirror?-1:1}addChild(e,n=w(),s=0){return y(!this.destroyed,"cannot add child to destroyed object"),this.destroyed||(y(!e.parent&&!this.children.includes(e)),y(e instanceof t,"child must be an EngineObject"),y(e!==this,"cannot add self as child"),this.children.push(e),e.parent=this,e.localPos=n.copy(),e.localAngle=s,e.updateTransforms()),e}removeChild(e){y(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}isOverlappingObject(e){return this.isOverlapping(e.pos,e.size)}isOverlapping(e,n=w()){return Ei(this.pos,this.size,e,n)}setCollision(e=!0,n=!0,s=!0,i=!0){y(e||!n,"solid objects must be set to collide"),this.collideSolidObjects=e,this.isSolid=n,this.collideTiles=s,this.collideRaycast=i}toString(){let e="type = "+this.constructor.name;return(this.pos.x||this.pos.y)&&(e+=`
+pos = `+this.pos),(this.velocity.x||this.velocity.y)&&(e+=`
+velocity = `+this.velocity),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.angle&&(e+=`
+angle = `+this.angle.toFixed(3)),this.color&&(e+=`
+color = `+this.color),e}renderDebugInfo(){if(!qe)return;let e=this.collideTiles||this.collideSolidObjects||this.isSolid;if(!e&&!this.parent)return;let n=w(le(this.size.x,.2),le(this.size.y,.2)),s=K(this.collideTiles?1:0,this.collideSolidObjects?1:0,this.isSolid?1:0,.5);Ce(this.pos,n,s,0,this.angle,e),this.parent&&Ce(this.pos,n.scale(.8),K(1,1,1,.5),0,this.angle),this.parent&&Lt(this.pos,this.parent.pos,K(1,1,1,.5),.5)}},U=w(),wn=[];Bt=class t{constructor(e=w(),n=ro,s=wn[0],i=ao,r=co){this.pos=e.copy(),this.size=n.copy(),this.padding=i,this.textureInfo=s,this.bleed=r}offset(e){return new t(this.pos.add(e),this.size,this.textureInfo,this.padding,this.bleed)}frame(e){y(typeof e=="number");let n=this.size.x+this.padding*2,s=e*n;return y(s+this.size.x<=this.textureInfo.size.x,"frame extends beyond texture width!"),this.offset(new ge(s))}setFullImage(e=this.textureInfo){return this.textureInfo=e,this.pos=new ge,this.size=e.size.copy(),this.bleed=this.padding=0,this}tile(e){return ii(e,this.size,this.textureInfo,this.padding,this.bleed)}},Zt=class{constructor(e,n=!0,s=!1){this.image=e,this.size=e?w(e.width,e.height):w(),this.sizeInverse=e?w(1/e.width,1/e.height):w(),this.glTexture=void 0,this.wrap=s,n&&this.createWebGLTexture()}createWebGLTexture(){kh(this)}destroyWebGLTexture(){Ch(this)}hasWebGL(){return!!this.glTexture}setWrap(e=!0){this.wrap=e,Ol(this.glTexture,e)}};Df=0;Di=class{constructor(e){y(!!e,"tileInfo is required for ImageFont"),this.tileInfo=e.frame(0)}drawText(e,n,s=1,i,r,a,o){y(I(s)||typeof s=="number","size must be a vec2 or number"),typeof s=="number"?(y(s>0),s*=se,s=new ge(s,s)):s=s.scale(se),this.drawTextScreen(e,Wn(n),s,i,r,a,o)}drawTextScreen(e,n,s,i=!0,r=ee,a=H,o){y(Z(e),"text must be a string"),y(I(n),"pos must be a vec2"),y(I(s)||typeof s=="number","size must be a vec2 or number"),y(Q(r),"color must be a color"),s=typeof s=="number"?new ge(s,s):s;let c=new ge,l=this.tileInfo,u=l.padding,h=l.size.x+u*2,d=l.size.y+u*2,f=l.textureInfo.size.x/h|0;(e+"").split(`
+`).forEach((m,p)=>{let x=i?(m.length-1)*s.x/2:0;for(let v=m.length;v--;){let A=m.charCodeAt(v),S=A<32||A>127?95:A-32,_=S%f,k=S/f|0;l.pos.x=_*h+u,l.pos.y=k*d+u,c.x=n.x+v*s.x-x|0,c.y=n.y+p*s.y|0,Ne(c,s,l,r,0,!1,void 0,a,!0,o)}})}};Nt=w(),Ze=w(),ha=w(),Pt=w(),pa=0,Ii=!0,rs=!1,hn="mouse",ma=6,is=!0,ke=0,mt=!X&&window.ontouchstart!==void 0;oe=[[]],Rt=[],Rn=[],Zo=[],ds=new It,yt=[],Jn=[],Fi=[],ci=[],$t=new Map,zs=[],fs=!0;Gi="http://www.w3.org/2000/svg";we=new AudioContext,xs=44100;Vs=class{constructor(e,n,s=la,i=ua,r){var a;if(!(!it||X)){if(y(!e||Tt(e)||Z(e),"asset must be a file name or zzfx array"),y(n===void 0||D(n),"randomness must be a number"),y(n===void 0||n>=0&&n<=1,"randomness must be between 0 and 1"),y(D(s),"range must be a number"),y(D(i),"taper must be a number"),this.range=s,this.taper=i,this.randomness=n!=null?n:0,this.sampleRate=xs,this.loadedPercent=0,this.onloadCallback=r,Tt(e)){let o=e.slice(),c=n!=null?n:.05,l=1;this.randomness=(a=o[l])!=null?a:c,o[l]=0,this.sampleChannels=[ho(...o)],this.loadedPercent=1,r==null||r(this)}else if(typeof e=="string"){let o=e;this.loadSound(o)}}}play(e,n=1,s=1,i=1,r=!1,a=!1){if(y(!e||I(e),"pos must be a vec2"),y(D(n),"volume must be a number"),y(D(s),"pitch must be a number"),y(D(i),"randomnessScale must be a number"),!it||X||!this.sampleChannels)return;let o;if(e){let u=this.range;if(u){let h=Ge.distanceSquared(e);if(h>u*u)return;n*=He(h**.5,u,u*this.taper)}o=Wn(e).x*2/$.width-1}let c=s+s*this.randomness*i*ve(-1,1),l=new Bi(this,n,c,o,r,a);return qe&&ls&&e&&(et(e,.5,"#0ff",.5,!0),this.range&&(et(e,2*this.range,"#0ff",.5),et(e,2*this.range*this.taper,"#0ff",.5)),es("vol "+n.toFixed(2)+" pitch "+c.toFixed(2),e,.5,"#0ff",.5)),l}playMusic(e=1,n=!0,s=!1){return this.play(void 0,e,1,0,n,s)}playNote(e=0,n,s){y(D(e),"semitoneOffset must be a number");let i=_l(e,1);return this.play(n,s,i,0)}getDuration(){var e,n;return((n=(e=this.sampleChannels)==null?void 0:e[0])==null?void 0:n.length)/this.sampleRate||0}isLoaded(){return this.loadedPercent===1}async loadSound(e){var c;let n=await fetch(e);if(!n.ok)throw new Error(`Failed to load sound from ${e}: ${n.status} ${n.statusText}`);let s=await n.arrayBuffer(),i=await we.decodeAudioData(s),r=i.numberOfChannels,a=1e5,o=[];for(let l=0;lsetTimeout(x,0));let f=de(d+a,h);for(;d=0,"Sound volume must be positive or zero"),y(s>=0,"Sound rate must be positive or zero"),y(D(i),"Sound pan must be a number"),this.sound=e,this.volume=n,this.rate=s,this.pan=i,this.loop=r,this.pausedTime=0,this.startTime=void 0,this.gainNode=void 0,this.source=void 0,this.onendedCallback=o=>{o===this.source&&(this.source=void 0)},a||this.start()}start(e=0){y(e>=0,"Sound start offset must be positive or zero"),this.isPlaying()&&this.stop(),this.gainNode=we.createGain(),this.source=Ta(this.sound.sampleChannels,this.volume,this.rate,this.pan,this.loop,this.sound.sampleRate,this.gainNode,e,this.onendedCallback),this.source?(this.startTime=we.currentTime-e,this.pausedTime=void 0):(this.startTime=void 0,this.pausedTime=0)}setVolume(e){y(e>=0,"Sound volume must be positive or zero"),this.volume=e,this.gainNode&&(this.gainNode.gain.value=e)}stop(e=0){if(y(e>=0,"Sound fade time must be positive or zero"),this.isPlaying())if(e){let n=we.currentTime,s=n+e;this.gainNode.gain.cancelScheduledValues(n),this.gainNode.gain.setValueAtTime(this.volume,n),this.gainNode.gain.linearRampToValueAtTime(0,s),this.source.stop(s)}else this.source.stop();this.pausedTime=0,this.source=void 0,this.startTime=void 0}pause(){this.isPaused()||(this.pausedTime=this.getCurrentTime(),this.source.stop(),this.source=void 0,this.startTime=void 0)}resume(){this.isPaused()&&this.start(this.pausedTime)}isPlaying(){return!!this.source}isPaused(){return!this.isPlaying()}getCurrentTime(){if(!this.isPlaying())return this.pausedTime;let e=this.getDuration();return e?pt(we.currentTime-this.startTime,e):0}getDuration(){return this.rate?this.sound.getDuration()/this.rate:0}getSource(){return this.source}};bn=[];Bn=class{constructor(e,n=0,s=!1,i=new Oe){this.tile=e,this.direction=n,this.mirror=s,this.color=i.copy()}clear(){this.tile=this.direction=0,this.mirror=!1,this.color=new Oe}},Ji=class extends Qt{constructor(e,n,s=0,i=0,r=w(512),a=!0){var o;y(I(r),"canvasSize must be a Vector2"),super(e,n,void 0,s,ee,i),this.canvas=X?void 0:new OffscreenCanvas(r.x,r.y),this.context=(o=this.canvas)==null?void 0:o.getContext("2d"),this.textureInfo=new Zt(this.canvas,a),this.mass=0}destroy(){this.destroyed||(this.textureInfo.destroyWebGLTexture(),super.destroy())}render(){this.draw(this.pos,this.size,this.color,this.angle,this.mirror,this.additiveColor)}draw(e,n,s=ee,i=0,r=!1,a,o=!1,c){let l=new Bt().setFullImage(this.textureInfo),u=this.hasWebGL();Ne(e,n,l,s,i,r,a,u,o,c)}updateWebGL(){this.textureInfo.createWebGLTexture()}hasWebGL(){return H&&this.textureInfo.hasWebGL()}},Ws=class extends Ji{constructor(e,n,s=ii(),i=0,r=!0){let a=s?n.multiply(s.size):n;if(super(e,n,0,i,a,r),this.tileInfo=void 0,this.data=[],this.isUsingWebGL=!1,X){this.render=()=>{},this.redraw=()=>{},this.redrawStart=()=>{},this.redrawEnd=()=>{},this.drawTileData=()=>{},this.redrawTileData=()=>{},this.drawLayerTile=()=>{},this.drawLayerRect=()=>{},this.drawTile=()=>{},this.drawRect=()=>{},this.clearLayerRect=()=>{};return}s&&(this.tileInfo=s.frame(0),this.tileInfo.bleed=0);for(let o=this.size.area();o--;)this.data.push(new Bn)}setData(e,n,s=!1){if(e=e.floor(),y(I(e),"layerPos must be a Vector2"),y(n instanceof Bn,"data must be a TileLayerData"),!e.arrayCheck(this.size)||(this.data[(e.y|0)*this.size.x+(e.x|0)]=n,!s))return;Ie===this.context?this.drawTileData(e):this.redrawTileData(e)}clearData(e,n=!1){this.setData(e,new Bn,n)}getData(e){return y(I(e),"layerPos must be a Vector2"),e.arrayCheck(this.size)?this.data[(e.y|0)*this.size.x+(e.x|0)]:void 0}update(){!H&&this.isUsingWebGL&&(this.isUsingWebGL=!1,this.redraw())}render(){y(Ie!==this.context,"must call redrawEnd() after drawing tiles!");let e=this.drawSize||this.size,n=this.pos.add(e.scale(.5));this.draw(n,this.size,this.color,this.angle,this.mirror,this.additiveColor)}onRedraw(){}redraw(){this.redrawStart(!0);for(let e=this.size.x;e--;)for(let n=this.size.y;n--;)this.drawTileData(w(e,n),!1);this.isUsingWebGL&&Be(),this.onRedraw(),this.redrawEnd()}redrawStart(e=!1){var s,i;if(!this.context)return;y(Ie!==this.context),this.savedRenderSettings=[Ie,U,Ge,se,mn],Ie=this.context;let n=(i=(s=this.tileInfo)==null?void 0:s.size)!=null?i:w(1);U=this.size.multiply(n),mn=kt,Ge=this.size.multiply(n).scale(.5),se=1,this.isUsingWebGL=this.hasWebGL(),this.isUsingWebGL?Rs(this.textureInfo.glTexture,e):(this.context.imageSmoothingEnabled=!jn,e&&(this.canvas.width=U.x,this.canvas.height=U.y))}redrawEnd(){this.context&&(y(Ie===this.context),this.isUsingWebGL&&Rs(),[Ie,U,Ge,se,mn]=this.savedRenderSettings)}drawTileData(e,n=!0){var o,c;if(!this.context)return;y(Ie===this.context,"must call redrawStart() before drawing tiles");let s=(c=(o=this.tileInfo)==null?void 0:o.size)!=null?c:w(1),i=e.multiply(s);n&&this.clearLayerRect(i,s);let r=this.getData(e);if(!r||!r.tile)return;let a=this.tileInfo&&this.tileInfo.tile(r.tile);this.drawLayerTile(i,s,a,r.color,r.direction*ie/2,r.mirror)}redrawTileData(e,n=!0){this.context&&(y(Ie!==this.context,"redrawStart() should not be active when calling redrawTileData(), instead use drawTileData()"),this.redrawStart(),this.drawTileData(e,n),this.redrawEnd())}drawLayerTile(e,n=w(1),s,i=ee,r=0,a,o){let c=e.add(n.scale(.5));Ne(c,n,s,i,r,a,o,this.isUsingWebGL)}drawLayerRect(e,n,s,i=0){this.drawLayerTile(e,n,void 0,s,i)}drawTile(e,n=w(1),s,i=new Oe,r=0,a=!1){e=e.subtract(this.pos).multiply(this.tileInfo.size),n=n.multiply(this.tileInfo.size),e.y=this.canvas.height-e.y;let o=U;U=w(this.canvas.width,this.canvas.height);let c=this.hasWebGL();c&&Rs(this.textureInfo.glTexture);let l=c?void 0:this.context;Ne(e,n,s,i,r,a,void 0,c,!0,l),c&&Rs(),U=o}drawRect(e,n,s,i){this.drawTile(e,n,void 0,s,i)}clearLayerRect(e,n){y(Ie===this.context,"must call redrawStart() before clearing tiles");let s=e.x,i=this.canvas.height-e.y-n.y;this.hasWebGL()?Gl(s,i,n.x,n.y):this.context.clearRect(s,i,n.x,n.y)}},qs=class extends Ws{constructor(e,n,s=ii(),i=0,r=!0){super(e,n.floor(),s,i,r),this.collisionData=[],this.initCollision(this.size),bn.push(this),this.isSolid=!0}destroy(){if(this.destroyed)return;let e=bn.indexOf(this);y(e>=0,"tile collision layer not found in array"),e>=0&&bn.splice(e,1),super.destroy()}initCollision(e){y(I(e),"size must be a Vector2"),this.size=e.floor(),this.collisionData=[],this.collisionData.length=e.area(),this.collisionData.fill(0)}setCollisionData(e,n=1){y(I(e),"layerPos must be a Vector2");let s=(e.y|0)*this.size.x+(e.x|0);e.arrayCheck(this.size)&&(this.collisionData[s]=n)}clearCollisionData(e){this.setCollisionData(e,0)}getCollisionData(e){y(I(e),"layerPos must be a Vector2");let n=(e.y|0)*this.size.x+(e.x|0);return e.arrayCheck(this.size)?this.collisionData[n]:0}collisionTest(e,n=new ge,s){y(I(e)&&I(n),"pos and size must be Vector2s"),y(!s||typeof s=="function"||s instanceof Qt,"callbackObject must be a function or EngineObject");let i=s?typeof s=="function"?(d,f)=>s(d,f):(d,f)=>s.collideWithTile(d,f):()=>!0,r=e.x-this.pos.x,a=e.y-this.pos.y;if(r+n.x/2<0||r-n.x/2>this.size.x||a+n.y/2<0||a-n.y/2>this.size.y)return!1;let o=le(r-n.x/2|0,0),c=le(a-n.y/2|0,0),l=de(le(r+n.x/2,o+1),this.size.x),u=de(le(a+n.y/2,c+1),this.size.y),h=new ge;for(let d=c;ds(l,u):(l,u)=>s.collideWithTile(l,u):l=>l>0,a=l=>{let u=this.getCollisionData(o.set(l.x-this.pos.x,l.y-this.pos.y));return u&&r(u,l)},o=new ge,c=il(e,n,a,i);if(wt&&c){let l=c.floor().add(w(.5));Ce(l,w(1),"#f008"),Lt(e,n,"#00f",.02),Lt(e,c,"#f00",.02),qr(c,"#0f0"),i&&Lt(c,c.add(i),"#ff0",.02)}return c}},ur=class extends Qt{constructor(e,n,s=0,i=0,r=100,a=ie,o,c=ee,l=ee,u=Sn,h=Sn,d=.5,f=.1,m=1,p=.1,x=.05,v=1,A=1,S=0,_=ie,k=.1,C=.2,O=!1,z=!1,re=!0,te=z?1e9:0,T=!1){super(e,w(),o,n,void 0,te),this.emitCircle=typeof s=="number",this.emitSize=typeof s=="number"?w(s):s.copy(),this.emitTime=i,this.emitRate=r,this.emitConeAngle=a,this.colorStartA=c.copy(),this.colorStartB=l.copy(),this.colorEndA=u.copy(),this.colorEndB=h.copy(),this.randomColorLinear=re,this.particleTime=d,this.sizeStart=f,this.sizeEnd=m,this.speed=p,this.angleSpeed=x,this.damping=v,this.angleDamping=A,this.gravityScale=S,this.particleConeAngle=_,this.fadeRate=k,this.randomness=C,this.collideTiles=O,this.additive=z,this.localSpace=T,this.trailScale=0,this.particleCreateCallback=void 0,this.particleDestroyCallback=void 0,this.particleCollideCallback=void 0,this.velocityInheritance=0,this.emitTimeBuffer=0,this.particles=[],this.previousAngle=this.angle,this.previousPos=this.pos.copy()}update(){if(y(this.angleDamping>=0&&this.angleDamping<=1),y(this.damping>=0&&this.damping<=1),this.velocityInheritance){let s=this.velocityInheritance;this.velocity.x=s*(this.pos.x-this.previousPos.x),this.velocity.y=s*(this.pos.y-this.previousPos.y),this.angleVelocity=s*(this.angle-this.previousAngle),this.previousAngle=this.angle,this.previousPos.x=this.pos.x,this.previousPos.y=this.pos.y}if(this.isActive()){if(this.emitRate&&Pi){let s=1/this.emitRate/Pi;for(this.emitTimeBuffer+=Vr;this.emitTimeBuffer>0;this.emitTimeBuffer-=s)this.emitParticle()}}else this.particles.length===0&&this.destroy(!0);let e=this.particles,n=0;for(let s=0;sA+A*ve(s,-s),r=i(this.particleTime),a=i(this.sizeStart),o=i(this.sizeEnd),c=i(this.speed),l=i(this.angleSpeed)*rl(),u=ve(this.emitConeAngle,-this.emitConeAngle),h=ir(this.colorStartA,this.colorStartB,this.randomColorLinear),d=ir(this.colorEndA,this.colorEndB,this.randomColorLinear),f=this.localSpace?u:this.angle+u,m=w(c*pe(f),c*be(f)),p=l;!this.localSpace&&this.velocityInheritance>0&&(m.x+=this.velocity.x,m.y+=this.velocity.y,p+=this.angleVelocity);let x=new Ni(this,e,n,h,d,r,a,o,m,p);return this.particles.push(x),(v=this.particleCreateCallback)==null||v.call(this,x),x}updatePhysics(){}render(){for(let e of this.particles)e.render()}isActive(){return!this.emitTime||this.getAliveTime()0&&(this.destroyed=!1,this.emitTime=-1))}},wh=new ge,Ni=class{constructor(e,n,s,i,r,a,o,c,l=w(),u=0){this.emitter=e,this.pos=n,this.angle=s,this.size=w(o),this.color=i.copy(),this.colorStart=i,this.colorEnd=r,this.lifeTime=a,this.sizeStart=o,this.sizeEnd=c,this.velocity=l,this.angleVelocity=u,this.spawnTime=lt,this.mirror=ol(),this.groundObject=void 0,this.destroyed=!1,this.tileInfo=e.tileInfo}update(){let e=this.emitter,n=e.damping,s=e.angleDamping,i=e.restitution,r=e.friction,a=e.gravityScale,o=e.collideTiles,c=e.particleCollideCallback;if(this.lifeTime>0&<-this.spawnTime>this.lifeTime){this.destroy();return}let l=this.pos.copy();if(this.velocity.x*=n,this.velocity.y*=n,this.pos.x+=this.velocity.x+=tt.x*a,this.pos.y+=this.velocity.y+=tt.y*a,this.angle+=this.angleVelocity*=s,!lo||!o)return;let u=this.velocity.lengthSquared();if(u>qt*qt){let d=qt/u**.5;this.velocity.x*=d,this.velocity.y*=d}this.groundObject=void 0;let h=c?d=>{let f=ji(d);return f&&c(this,f,d)}:d=>ji(d)>0;if(h(this.pos)){let d=dn(this.pos);if(!h(l)){let f=h(w(this.pos.x,l.y)),m=h(w(l.x,this.pos.y)),p=le(i,d.restitution),x=le(r,d.friction);f&&(this.pos.x=l.x,this.velocity.x*=-p,this.velocity.y*=x),(m||!f)&&((this.velocity.y<0&&tt.y<0||this.velocity.y>0&&tt.y>0)&&(this.groundObject=d),this.pos.y=l.y,this.velocity.y*=-p,this.velocity.x*=x),vt&&Ce(this.pos,this.size,"#f00")}}}destroy(){let e=this.emitter.particleDestroyCallback,n=this.colorEnd;this.color.set(n.r,n.g,n.b,n.a),this.size.set(this.sizeEnd,this.sizeEnd),this.destroyed=!0,e==null||e(this)}render(){let e=this.emitter,n=e.localSpace,s=e.additive,i=e.trailScale,r=e.fadeRate/2,a=this.lifeTime>0?de((lt-this.spawnTime)/this.lifeTime,1):1,o=1-a,c=o*this.sizeStart+a*this.sizeEnd,l=w(c),u=a1-r?(1-a)/r:1;this.color.r=o*this.colorStart.r+a*this.colorEnd.r,this.color.g=o*this.colorStart.g+a*this.colorEnd.g,this.color.b=o*this.colorStart.b+a*this.colorEnd.b,this.color.a=(o*this.colorStart.a+a*this.colorEnd.a)*u;let h=wh.set(this.pos.x,this.pos.y),d=this.angle;if(n){let f=e.angle,m=be(-f),p=pe(-f);h.set(e.pos.x+h.x*m-h.y*p,e.pos.y+h.x*p+h.y*m),d+=f}if(s&&js(),i){let f=n?this.velocity.rotate(e.angle):this.velocity,m=f.length();if(m){let p=m*i;l.y=le(l.x,p),d=Hr(f.x,f.y),Ne(h,l,this.tileInfo,this.color,d,this.mirror)}}else Ne(h,l,this.tileInfo,this.color,d,this.mirror);s&&js(!1),In&&Ce(h,l,"#f005",0,d)}},Aa=!0,pr=!0,Wi=5e5,Ca=11,Pl=Ca*4,Th=Wi/Pl|0,po=3,Rl=po*4,cs=Wi/Rl|0;Pn=!1,qi=5,os=.5,Hi=w(640,80),Oa=!1,Xs={},wi=[];Yi=class{constructor(e,n,s="",i="\u{1F3C6}",r){y(e>=0&&!Xs[e]),this.id=e,this.name=n,this.description=s,this.icon=i,this.unlocked=!1,this.image=void 0,r&&((this.image=new Image).src=r),Xs[e]=this}unlock(){Oa||this.unlocked||(y($i,"save name must be set"),this.unlocked=!0,Da(),wi.push(this))}render(e=0){let n=xe,s=de(Hi.x,$.width),i=Hi.y,r=$.width-s,a=-i*e,o=Wt(0,0,.9);n.save(),n.beginPath(),n.fillStyle=o.toString(),n.strokeStyle=me.toString(),n.lineWidth=3,n.rect(r,a,s,i),n.fill(),n.stroke(),n.clip();let c=w(.1,.05).scale(i),l=i-2*c.x;this.renderIcon(w(r+c.x+l/2,a+i/2),l);let u=i*.5,h=i*.3,d=w(r+l+2*c.x,a+c.y*2+u/2),f=s-l-3*c.x;gn(this.name,d,u,me,0,void 0,"left",void 0,void 0,f),d.y=a+i-c.y*2-h/2,gn(this.description,d,h,me,0,void 0,"left",void 0,void 0,f),n.restore()}renderIcon(e,n){this.image?xe.drawImage(this.image,e.x-n/2,e.y-n/2,n,n):gn(this.icon,e,n*.7,me)}};gr=class extends Yi{constructor(e,n,s,i,r){super(e,n,s,i,r)}unlock(){super.unlock(),Ks&&Ks.unlockMedal(this.id)}},br=class{constructor(e,n,s){var c,l,u;y(!Ks,"there can only be one newgrounds object"),y(!n||s,"must provide cryptojs if there is a cipher"),Ks=this,this.app_id=e,this.cipher=n,this.cryptoJS=s,this.host=location?location.hostname:"";let i=new URL(location.href);if(this.session_id=i.searchParams.get("ngio_session_id"),!this.session_id)return;let r=this.call("Medal.getList");if(!r||!r.result||r.result.error){Pn&&_e("Newgrounds session unavailable; skipping plugin init"),this.medals=[],this.scoreboards=[];return}this.medals=((c=r.result.data)==null?void 0:c.medals)||[],Pn&&_e(this.medals);for(let h of this.medals){let d=Xs[h.id];d&&(d.image=new Image,d.image.src=h.icon,d.name=h.name,d.description=h.description,d.unlocked=h.unlocked,d.difficulty=h.difficulty,d.value=h.value,d.value&&(d.description=d.description+` (${d.value})`))}let a=this.call("ScoreBoard.getBoards");this.scoreboards=((u=(l=a==null?void 0:a.result)==null?void 0:l.data)==null?void 0:u.scoreboards)||[],Pn&&_e(this.scoreboards);let o=60*1e3;setInterval(()=>this.call("Gateway.ping",0,!0),o)}unlockMedal(e){return this.call("Medal.unlock",{id:e},!0)}postScore(e,n){return this.call("ScoreBoard.postScore",{id:e,value:n},!0)}getScores(e,n,s=0,i=0,r=10){return this.call("ScoreBoard.getScores",{id:e,user:n,social:s,skip:i,limit:r})}logView(){return this.call("App.logView",{host:this.host},!0)}call(e,n,s=!1){let i={component:e,parameters:n};if(this.cipher){let l=this.cryptoJS,u=l.enc.Base64.parse(this.cipher),h=l.lib.WordArray.random(16),d=l.AES.encrypt(JSON.stringify(i),u,{iv:h});i.secure=l.enc.Base64.stringify(h.concat(d.ciphertext)),i.parameters=0}let r={app_id:this.app_id,session_id:this.session_id,call:i},a=new FormData;a.append("input",JSON.stringify(r));let o=new XMLHttpRequest;o.open("POST","https://newgrounds.io/gateway_v3.php",!Pn&&s);try{o.send(a)}catch(l){Pn&&_e("newgrounds call failed",l);return}return Pn&&_e(o.responseText),o.responseText&&JSON.parse(o.responseText)}},xr=class{constructor(e,n=!1,s=!1){y(!Ue,"Post process already initialized"),y(!(n&&s),"Post process cannot both include main canvas and use feedback texture"),Ue=this,e||(e="void mainImage(out vec4 c,vec2 p){c=texture(iChannel0,p/iResolution.xy);}"),this.shader=void 0,this.texture=void 0,this.vao=void 0,i(),zn(void 0,o,r,a);function i(){if(X)return;if(!H){console.warn("PostProcessPlugin: WebGL not enabled!");return}Ue.texture=mo(),Ue.shader=ms(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D iChannel0;uniform vec3 iResolution;uniform float iTime;out vec4 c;
+`+e+`
+void main(){mainImage(c,gl_FragCoord.xy);c.a=1.;}`),Ue.vao=g.createVertexArray(),g.bindVertexArray(Ue.vao),g.bindBuffer(g.ARRAY_BUFFER,as);let c=8,l=g.getAttribLocation(Ue.shader,"p");g.enableVertexAttribArray(l),g.vertexAttribPointer(l,2,g.FLOAT,!1,c,0)}function r(){Ue.shader=void 0,Ue.texture=void 0,_e("PostProcessPlugin: WebGL context lost")}function a(){i(),_e("PostProcessPlugin: WebGL context restored")}function o(){if(X||!H)return;Be(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.useProgram(Ue.shader),g.bindVertexArray(Ue.vao),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!0),g.disable(g.BLEND),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,Ue.texture),n?(Yt.width=U.x,Yt.height=U.y,Pa(fn),fn.drawImage($,0,0),$.width|=0,g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,Yt)):s||g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,fe);let c=l=>g.getUniformLocation(Ue.shader,l);g.uniform1i(c("iChannel0"),0),g.uniform1f(c("iTime"),lt),g.uniform3f(c("iResolution"),$.width,$.height,1),g.drawArrays(g.TRIANGLE_STRIP,0,4),s&&g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,fe),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!1),$s(!0)}}},Sr=class{constructor(e,n){y(!ne,"LightSystemPlugin already initialized"),y(!Ue,"LightSystemPlugin must be created before PostProcessPlugin"),ne=this,this.enabled=!0,this.ambientColor=(n||me).copy(),this.textureSize=e?e.copy():void 0,this.texture=void 0,this.lightShader=void 0,this.compositeShader=void 0,this.lightVAO=void 0,this.compositeVAO=void 0,s(),zn(void 0,i,r,a);function s(){if(X)return;if(!H){console.warn("LightSystemPlugin: WebGL not enabled!");return}ne.textureSize||(ne.textureSize=U.copy()),ne.texture=g.createTexture(),g.bindTexture(g.TEXTURE_2D,ne.texture),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,ne.textureSize.x,ne.textureSize.y,0,g.RGBA,g.UNSIGNED_BYTE,null),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,g.CLAMP_TO_EDGE),ne.lightShader=ms(`#version 300 es
+precision highp float;uniform mat4 m;uniform vec2 lightPos;uniform float radius;in vec2 g;out vec2 vWorldPos;void main(){vec2 worldP=lightPos+(g-.5)*2.*radius;gl_Position=m*vec4(worldP,1,1);vWorldPos=worldP;}`,`#version 300 es
+precision highp float;uniform vec2 lightPos;uniform float radius;uniform float fadeRange;uniform vec4 color;in vec2 vWorldPos;out vec4 c;void main(){float dist=distance(vWorldPos,lightPos);float t=clamp((radius-dist)/max(fadeRange,1e-6),0.,1.);c=vec4(color.rgb*t*color.a,1.);}`),ne.compositeShader=ms(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D s;uniform vec3 iResolution;out vec4 c;void main(){vec2 uv=gl_FragCoord.xy/iResolution.xy;c=vec4(texture(s,uv).rgb,1.);}`),ne.lightVAO=g.createVertexArray(),g.bindVertexArray(ne.lightVAO),g.bindBuffer(g.ARRAY_BUFFER,as);let o=g.getAttribLocation(ne.lightShader,"g");g.enableVertexAttribArray(o),g.vertexAttribPointer(o,2,g.FLOAT,!1,8,0),ne.compositeVAO=g.createVertexArray(),g.bindVertexArray(ne.compositeVAO),g.bindBuffer(g.ARRAY_BUFFER,as);let c=g.getAttribLocation(ne.compositeShader,"p");g.enableVertexAttribArray(c),g.vertexAttribPointer(c,2,g.FLOAT,!1,8,0)}function i(){if(X||!H||!ne.enabled||!ne.texture)return;Be();let o=Hn,c=ne.ambientColor;g.bindFramebuffer(g.FRAMEBUFFER,ka),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,ne.texture,0),g.viewport(0,0,ne.textureSize.x,ne.textureSize.y),g.clearColor(c.r,c.g,c.b,c.a),g.clear(g.COLOR_BUFFER_BIT),js(),g.enable(g.BLEND),g.blendFunc(g.ONE,g.ONE);for(let u of Ee)u.destroyed||u.renderLight();Be(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,U.x,U.y),g.useProgram(ne.compositeShader),g.bindVertexArray(ne.compositeVAO),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,ne.texture);let l=ne.compositeShader;g.uniform1i(g.getUniformLocation(l,"s"),0),g.uniform3f(g.getUniformLocation(l,"iResolution"),$.width,$.height,1),g.blendFunc(g.DST_COLOR,g.ZERO),g.drawArrays(g.TRIANGLE_STRIP,0,4),ut&&g.bindTexture(g.TEXTURE_2D,ut),js(o),$s(!0)}function r(){ne.texture=void 0,ne.lightShader=void 0,ne.compositeShader=void 0,ne.lightVAO=void 0,ne.compositeVAO=void 0,_e("LightSystemPlugin: WebGL context lost")}function a(){s(),_e("LightSystemPlugin: WebGL context restored")}}drawLight(e){if(X||!H||!this.lightShader)return;Be(),g.useProgram(this.lightShader),g.bindVertexArray(this.lightVAO);let n=w(2*se).divide(U),s=Ge.rotate(-ue),i=w(-1).subtract(s.multiply(n)),r=be(ue),a=pe(ue),o=[n.x*r,n.y*a,0,0,-n.x*a,n.y*r,0,0,1,1,1,0,i.x,i.y,0,1],c=this.lightShader;g.uniformMatrix4fv(g.getUniformLocation(c,"m"),!1,o),g.uniform2f(g.getUniformLocation(c,"lightPos"),e.pos.x,e.pos.y),g.uniform1f(g.getUniformLocation(c,"radius"),e.radius),g.uniform1f(g.getUniformLocation(c,"fadeRange"),e.fadeRange);let l=e.color;g.uniform4f(g.getUniformLocation(c,"color"),l.r,l.g,l.b,l.a),g.drawArrays(g.TRIANGLE_STRIP,0,4),$s(!0)}},vr=class extends Qt{constructor(e,n,s,i){super(e,w(1),void 0,0,s),y(D(n)&&n>=0,"Light radius must be a non-negative number"),y(i===void 0||D(i)&&i>=0,"Light fadeRange must be a non-negative number when provided"),this.radius=n,this.fadeRange=i===void 0?n:i}render(){}renderLight(){ne&&ne.drawLight(this)}},wr=class extends Vs{constructor(e){super(void 0),!(!it||X)&&(this.randomness=0,this.sampleChannels=Bl(...e),this.sampleRate=xs)}playMusic(e=1,n=!0){return super.play(void 0,e,1,0,n)}};Ia=0;Tr=class{constructor(e=xe){y(!E,"UI system already initialized"),E=this,this.activateOnPress=!1,this.defaultColor=ee,this.defaultLineColor=me,this.defaultTextColor=me,this.defaultButtonColor=Wt(0,0,.7),this.defaultHoverColor=Wt(0,0,.9),this.defaultDisabledColor=Wt(0,0,.3),this.defaultGradientColor=void 0,this.defaultLineWidth=4,this.defaultCornerRadius=0,this.defaultTextFitScale=.8,this.defaultFont=ei,this.defaultSoundPress=void 0,this.defaultSoundRelease=void 0,this.defaultSoundClick=void 0,this.defaultShadowColor=kt,this.defaultShadowBlur=5,this.defaultShadowOffset=w(5),this.nativeHeight=0,this.navigationObject=void 0,this.navigationTimer=new It(void 0,!0),this.navigationDelay=.2,this.navigationDirection=1,this.navigationMode=!1,this.uiObjects=[],this.uiContext=e,this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.confirmDialog=void 0,this._keyInputObject=void 0,this._onKeyDown=r=>{var a;return(a=this._keyInputObject)==null?void 0:a.onKeyDown(r)},zn(s,i);function n(r){let a,o;r.parent?(a=r.parent.nativePos,o=r.parent.size):(a=E.screenToNative(U.scale(.5)),o=E.nativeHeight?w(U.x*E.nativeHeight/U.y,E.nativeHeight):U);let c=r.anchor;r.nativePos=a.add(o.multiply(c).scale(.5)).subtract(r.size.multiply(c).scale(.5)).add(r.localPos)}function s(){E.activeObject&&!E.activeObject.visible&&(E.activeObject=void 0),E.lastHoverObject=E.hoverObject,E.hoverObject=void 0,Js(0)&&(E.navigationMode=!1,E.navigationObject=void 0),E.keyInputObject&&(E.activeObject=E.keyInputObject,E.hoverObject=E.keyInputObject,E.navigationMode=!1,E.navigationObject=void 0);let r=E.getNavigableObjects();if(!r.length)E.navigationObject=void 0;else if(!E.keyInputObject){if(r.includes(E.navigationObject)||(E.navigationObject=void 0),mt||E.navigationMode&&!E.navigationObject&&(E.navigationObject=r.find(o=>o.navigationAutoSelect)),!E.navigationTimer.active()){let o=ht(E.getNavigationDirection());if(o){let c;if(E.navigationObject){let l=r.indexOf(E.navigationObject),u=pt(l+o,r.length);c=r[u]}else if(c=r.find(l=>l.navigationAutoSelect),!c){let l=o>0?0:r.length-1;c=r[l]}E.navigationObject!==c&&(E.navigationMode=!0,E.hoverObject=void 0,E.navigationObject=c,E.navigationTimer.set(E.navigationDelay),c.soundPress&&c.soundPress.play())}}E.navigationObject&&E.getNavigationWasPressed()&&E.navigationObject.navigatePressed()}for(let o=E.uiObjects.length;o--;){let c=E.uiObjects[o];c.parent||a(c)}E.uiObjects=E.uiObjects.filter(o=>!o.destroyed);function a(o){if(!(o.destroyed||!o.visible)){n(o);for(let c=o.children.length;c--;){let l=o.children[c];l&&a(l)}o.destroyed||o.update()}}}function i(){let r=E.uiContext;if(r.save(),E.nativeHeight){let o=U.y/E.nativeHeight;r.translate(-o*U.x/2,0),r.scale(o,o),r.translate(U.x/2/o,0)}function a(o){if(o.visible){n(o),o.render();for(let c of o.children)a(c)}}if(E.uiObjects.forEach(o=>o.parent||a(o)),Ia>0){let o=function(c,l=!0){l&&(l=!!c.visible),n(c),c.renderDebug(l);for(let u of c.children)o(u,l)};E.uiObjects.forEach(c=>c.parent||o(c))}r.restore()}}drawRect(e,n,s=ee,i=0,r=me,a=0,o,c=me,l=0,u=w()){y(I(e),"pos must be a vec2"),y(I(n),"size must be a vec2"),y(Q(s),"color must be a color"),y(D(i),"lineWidth must be a number"),y(Q(r),"lineColor must be a color"),y(D(a),"cornerRadius must be a number");let h=E.uiContext;if(o){let d=h.createLinearGradient(e.x,e.y-n.y/2,e.x,e.y+n.y/2),f=s.toString();d.addColorStop(0,f),d.addColorStop(.5,o.toString()),d.addColorStop(1,f),h.fillStyle=d}else h.fillStyle=s.toString();(l||u.x||u.y)&&c.a>0&&(h.shadowColor=c.toString(),h.shadowBlur=l,h.shadowOffsetX=u.x,h.shadowOffsetY=u.y),h.beginPath(),a&&h.roundRect?h.roundRect(e.x-n.x/2,e.y-n.y/2,n.x,n.y,a):h.rect(e.x-n.x/2,e.y-n.y/2,n.x,n.y),h.fill(),h.shadowColor="#0000",i&&r.a>0&&(h.strokeStyle=r.toString(),h.lineWidth=i,h.stroke())}drawLine(e,n,s=E.defaultLineWidth,i=E.defaultLineColor){y(I(e),"posA must be a vec2"),y(I(n),"posB must be a vec2"),y(D(s),"lineWidth must be a number"),y(Q(i),"lineColor must be a color");let r=E.uiContext;r.strokeStyle=i.toString(),r.lineWidth=s,r.beginPath(),r.lineTo(e.x,e.y),r.lineTo(n.x,n.y),r.stroke()}drawTile(e,n,s,i=E.defaultColor,r=0,a=!1,o=me,c=0,l=w()){let u=E.uiContext;(c||l.x||l.y)&&o.a>0&&(u.shadowColor=o.toString(),u.shadowBlur=c,u.shadowOffsetX=l.x,u.shadowOffsetY=l.y),Ne(e,n,s,i,r,a,kt,!1,!0,u),u.shadowColor="#0000"}drawText(e,n,s,i=E.defaultColor,r=E.defaultLineWidth,a=E.defaultLineColor,o="center",c=E.defaultFont,l="",u=!0,h=void 0,d=me,f=0,m=w()){let p=E.uiContext;d.a>0&&(h&&gn(e,n.add(h),s.y,d,r,a,o,c,l,u?s.x:void 0,0,p),(f||m.x||m.y)&&(p.shadowColor=d.toString(),p.shadowBlur=f,p.shadowOffsetX=m.x,p.shadowOffsetY=m.y)),gn(e,n,s.y,i,r,a,o,c,l,u?s.x:void 0,0,p),p.shadowColor="#0000"}setupDragAndDrop(e,n,s,i){if(this._dragListeners)for(let[a,o]of this._dragListeners)document.removeEventListener(a,o);this._dragListeners=[];let r=(a,o)=>{let c=l=>{l.preventDefault(),a&&a(l)};document.addEventListener(o,c),this._dragListeners.push([o,c])};r(e,"drop"),r(n,"dragenter"),r(s,"dragleave"),r(i,"dragover")}screenToNative(e){if(!E.nativeHeight)return e;let n=U.y/E.nativeHeight,s=1/n,i=e.copy();return i.x+=n*U.x/2,i.x*=s,i.y*=s,i.x-=s*U.x/2,i}get keyInputObject(){return this._keyInputObject}set keyInputObject(e){let n=!!this._keyInputObject;this._keyInputObject=e,!n&&e?document.addEventListener("keydown",this._onKeyDown):n&&!e&&document.removeEventListener("keydown",this._onKeyDown)}destroyObjects(){for(let e of this.uiObjects)e.parent||e.destroy();this.uiObjects=this.uiObjects.filter(e=>!e.destroyed),this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.keyInputObject=void 0}getNavigableObjects(){function e(s){if(!(!s.visible||s.disabled)){s.isInteractive()&&s.navigationIndex!==void 0&&n.push(s);for(let i=s.children.length;i--;)e(s.children[i])}}let n=[];for(let s=E.uiObjects.length;s--;){let i=E.uiObjects[s];E.confirmDialog&&i!==E.confirmDialog||i.parent||e(i)}return n.sort((s,i)=>s.navigationIndex-i.navigationIndex),n}getNavigationDirection(){let e=E.navigationDirection===1,n=E.navigationDirection===2;if(rs){let l=Ns(0,ke),u=cr(ke);return n?-(l.y||u.y)||l.x||u.x:e?-(l.y||u.y):l.x||u.x}let s="ArrowUp",i="ArrowDown",r="ArrowLeft",a="ArrowRight";if(n)return Je(s)||Je(r)?-1:Je(i)||Je(a)?1:0;let o=e?s:r,c=e?i:a;return Je(o)?-1:Je(c)?1:0}getNavigationOtherDirection(){if(E.navigationDirection===2)return 0;let e=E.navigationDirection===1;if(rs){let i=Ns(0,ke),r=cr(ke);return e?i.x||r.x:i.y||r.y}let n=e?"ArrowLeft":"ArrowUp",s=e?"ArrowRight":"ArrowDown";return Je(n)?-1:Je(s)?1:0}getNavigationWasPressed(){return rs?ba(0,ke):Ve("Space")||Ve("Enter")}showConfirmDialog(e="Are you sure?",n,s,i=w(500,250),r="Escape"){y(!E.confirmDialog);let a=E.navigationDirection;E.navigationDirection=2;let o=new gt(w(),i);E.confirmDialog=o,o.onRender=()=>{let f=Wt(0,0,0,.7);E.drawRect(w(),w(1e9),f)},o.onUpdate=()=>{Ve(r)&&d()},o.isMouseOverlapping=()=>!0;let c=50,l=new Xi(w(0,-50),w(i.x-c,70),e);o.addChild(l);let u=new Qs(w(-80,50),w(120,70),"Yes");u.textHeight=40,u.navigationIndex=1,u.hoverColor=Wt(0,1,.5),u.onClick=()=>{d(),n&&n()},o.addChild(u);let h=new Qs(w(80,50),w(120,70),"No");h.textHeight=40,h.navigationIndex=2,h.navigationAutoSelect=!0,h.onClick=()=>{d(),s&&s()},o.addChild(h);function d(){y(E.confirmDialog===o),o.destroy(),E.confirmDialog=void 0,E.navigationDirection=a,ai()}}},gt=class{constructor(e=w(),n=w()){var s,i;y(I(e),"ui object pos must be a vec2"),y(I(n),"ui object size must be a vec2"),this.localPos=e.copy(),this.nativePos=e.copy(),this.size=n.copy(),this.color=E.defaultColor.copy(),this.activeColor=void 0,this.text=void 0,this.disabledColor=E.defaultDisabledColor.copy(),this.disabled=!1,this.textColor=E.defaultTextColor.copy(),this.hoverColor=E.defaultHoverColor.copy(),this.lineColor=E.defaultLineColor.copy(),this.gradientColor=E.defaultGradientColor?E.defaultGradientColor.copy():void 0,this.lineWidth=E.defaultLineWidth,this.cornerRadius=E.defaultCornerRadius,this.font=E.defaultFont,this.fontStyle=void 0,this.textWidth=void 0,this.textHeight=void 0,this.textFitScale=E.defaultTextFitScale,this.textShadow=void 0,this.textLineColor=E.defaultLineColor.copy(),this.textLineWidth=0,this.visible=!0,this.children=[],this.parent=void 0,this.extraTouchSize=0,this.soundPress=E.defaultSoundPress,this.soundRelease=E.defaultSoundRelease,this.soundClick=E.defaultSoundClick,this.interactive=!1,this.dragActivate=!1,this.canBeHover=!0,this.shadowColor=(s=E.defaultShadowColor)==null?void 0:s.copy(),this.shadowBlur=E.defaultShadowBlur,this.shadowOffset=(i=E.defaultShadowOffset)==null?void 0:i.copy(),this.navigationIndex=void 0,this.navigationAutoSelect=!1,this.anchor=w(),E.uiObjects.push(this)}addChild(e){return y(!e.parent&&!this.children.includes(e)),this.children.push(e),e.parent=this,e}removeChild(e){y(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}destroy(){var e;if(!this.destroyed){E.activeObject===this&&(E.activeObject=void 0),E.hoverObject===this&&(E.hoverObject=void 0),E.lastHoverObject===this&&(E.lastHoverObject=void 0),E.navigationObject===this&&(E.navigationObject=void 0),E.keyInputObject===this&&(E.keyInputObject=void 0),this.destroyed=1,(e=this.parent)==null||e.removeChild(this);for(let n of this.children)n.parent=void 0,n.destroy();this.children.length=0}}isMouseOverlapping(){if(!Ii)return!1;let e=mt?this.size.add(w(this.extraTouchSize||0)):this.size,n=E.screenToNative(Ze);return Ei(this.nativePos,e,n)}update(){if(this.onUpdate(),this.disabled&&(this===E.activeObject&&(E.activeObject=void 0),this===E.keyInputObject&&(E.keyInputObject=void 0)),E.keyInputObject)return;let e=E.lastHoverObject===this,n=this.isActiveObject(),s=Ds(0),i=this.dragActivate?s:Js(0);this.canBeHover&&(E.navigationMode||(i||n||!s&&!mt)&&!E.hoverObject&&this.isMouseOverlapping()&&(E.hoverObject=this)),this.isHoverObject()&&(this.disabled||(i&&this.interactive&&((!this.dragActivate||!e||Js(0))&&this.onPress(),this.soundPress&&this.soundPress.play(),E.activeObject&&!n&&E.activeObject.onRelease(),E.activeObject=this,E.activateOnPress&&this.click(!this.soundPress)),E.activateOnPress||!s&&this.isActiveObject()&&this.interactive&&this.click()),i&&ya(0,0,0,1,0)),n&&(!s||this.dragActivate&&!this.isHoverObject())&&(this.onRelease(),this.soundRelease&&this.soundRelease.play(),E.activeObject=void 0),this.isHoverObject()!==e&&(this.isHoverObject()?this.onEnter():this.onLeave())}render(){if(this.onRender(),!this.size.x||!this.size.y)return;let e=this.isNavigationObject(),n=e?this.color:this.interactive&&this.isActiveObject()&&!this.disabled?this.color:this.lineColor,s=e?this.hoverColor:this.disabled?this.disabledColor:this.interactive?this.isActiveObject()?this.activeColor||this.hoverColor:this.isHoverObject()?this.hoverColor:this.color:this.color,i=this.lineWidth*(e?1.5:1);E.drawRect(this.nativePos,this.size,s,i,n,this.cornerRadius,this.gradientColor,this.shadowColor,this.shadowBlur,this.shadowOffset)}getTextSize(){return w(this.textWidth||this.textFitScale*this.size.x,this.textHeight||this.textFitScale*this.size.y)}navigatePressed(){this.click()}isHoverObject(){return E.hoverObject===this}isActiveObject(){return E.activeObject===this}isNavigationObject(){return E.navigationObject===this}isKeyInputObject(){return E.keyInputObject===this}isInteractive(){return this.interactive&&this.visible&&!this.disabled}toString(){let e="type = "+this.constructor.name;return this.text&&(e+=`
+text = `+this.text),(this.nativePos.x||this.nativePos.y)&&(e+=`
+nativePos = `+this.nativePos),(this.localPos.x||this.localPos.y)&&(e+=`
+localPos = `+this.localPos),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.color&&(e+=`
+color = `+this.color),e}renderDebug(e=!0){let n=e?this.isHoverObject()?ll:this.disabled?fl:this.interactive?Xr:dl:ul;E.drawRect(this.nativePos,this.size,kt,4,n)}click(e=!0){this.onClick(),e&&this.soundClick&&this.soundClick.play()}onUpdate(){}onRender(){}onEnter(){}onLeave(){}onPress(){}onRelease(){}onClick(){}onChange(){}},Xi=class extends gt{constructor(e,n,s="",i="center",r=E.defaultFont){super(e,n),y(Z(s),"ui text must be a string"),y(["left","center","right"].includes(i),"ui text align must be left, center, or right"),y(Z(r),"ui text font must be a string"),this.text=s,this.align=i,this.font=r,this.canBeHover=!1,this.color=kt,this.shadowColor=kt,this.gradientColor=void 0,this.lineWidth=0,this.textFitScale=1}render(){super.render();let e=this.getTextSize();E.drawText(this.text,this.nativePos,e,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow,this.shadowColor,this.shadowBlur,this.shadowOffset)}},Ar=class extends gt{constructor(e,n,s=""){super(e,n),y(Z(s),"ui text must be a string"),this.maxLength=0,this.text=s,this.interactive=!0,this.canBeHover=!0}click(){E.keyInputObject=this,this.onClick()}stopEditing(){this.isKeyInputObject()&&(this.soundRelease&&this.soundRelease.play(),E.activeObject=void 0,E.keyInputObject=void 0,this.onChange())}onKeyDown(e){let n=e.code,s=e.key;n==="Backspace"?this.text=this.text.slice(0,-1):n==="Enter"||n==="Escape"?this.stopEditing():s.length===1&&(!this.maxLength||this.text.lengththis.size.y,s=n?this.size.y:this.size.x,i=n?this.size.x:this.size.y,r=n?this.nativePos.x:this.nativePos.y,a=i-s,o=r-a/2,c=r+a/2,l=E.screenToNative(Ze);this.value=n?He(l.x,o,c):He(l.y,c,o)}else if(this.isNavigationObject()){let n=E.getNavigationOtherDirection();E.navigationTimer.active()||(this.value=Y(this.value+n*.01))}this.value===e||this.onChange()}render(){super.render();let e=this.size.x>this.size.y,n=e?this.size.x:this.size.y,s=e?this.size.y:this.size.x;if(this.fillMode){let r=de(s,this.cornerRadius*2),a=nt(r,n,this.value),o=(a-n)*(e?.5:-.5),c=this.nativePos.add(e?w(o,0):w(0,o)),l=this.disabled?this.disabledColor:this.handleColor,u=e?w(a,this.size.y):w(this.size.x,a);E.drawRect(c,u,l,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}else{let r=Y(e?this.value:1-this.value),a=(n-s)*(r-.5),o=this.nativePos.add(e?w(a,0):w(0,a)),c=this.disabled?this.disabledColor:this.handleColor,l=w(s);E.drawRect(o,l,c,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}let i=this.getTextSize();E.drawText(this.text,this.nativePos,i,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow)}navigatePressed(){this.value=this.value?0:1,this.onChange(),this.onRelease(),super.navigatePressed()}},Er=class extends gt{constructor(e,n,s,i=!1,r=!1,a=1){super(e,n||w()),y(Z(s),"video src must be a string"),y(D(a),"video volume must be a number"),this.color=me,this.cornerRadius=0,this.volume=a,this.video=document.createElement("video"),this.video.loop=r,this.video.volume=Y(a*Gn),this.video.muted=!it,this.video.style.display="none",this.video.src=s,document.body.appendChild(this.video),i&&this.play()}async play(){try{await this.video.play()}catch{}}pause(){this.video.pause()}stop(){this.video.pause(),this.video.currentTime=0}isLoading(){return this.video.readyState=1,"ui layout columns must be a number >= 1"),y(D(s),"ui layout gap must be a number"),y(D(i),"ui layout padding must be a number"),this.columns=n,this.gap=s,this.padding=i,r&&(this.color=kt,this.gradientColor=void 0,this.lineWidth=0,this.shadowColor=kt),this.relayout()}addChild(e){return super.addChild(e),this.relayout(),e}removeChild(e){super.removeChild(e),this.relayout()}relayout(){let e=this.children.length;if(!e){this.size=w(this.padding*2);return}let n=this.columns,s=Fs(e/n),i=new Array(n).fill(0),r=new Array(s).fill(0);for(let d=0;d=0&&b.objects.splice(e,1),super.destroy()}updatePhysics(){}render(){this.tileInfo?super.render():this.drawFixtures(this.color,this.lineColor,this.lineWidth)}renderDebugInfo(){let e=!this.getIsAwake(),n=this.getBodyType()===b.bodyTypeStatic,s=K(e?1:0,e?1:0,n?1:0,.5);this.drawFixtures(s)}drawFixtures(e=ee,n=me,s=.1,i,r){this.getFixtureList().forEach(a=>{b.castShapeObject(a.GetShape()).GetType()!==b.instance.b2Shape.e_edge&&b.drawFixture(a,this.pos,this.angle,e,n,s,i,r)}),this.edgeLists.forEach(a=>ar(a,s,n,!1,this.pos,this.angle)),this.edgeLoops.forEach(a=>ar(a,s,n,!0,this.pos,this.angle))}beginContact(e){}endContact(e){}addShape(e,n=1,s=.2,i=0,r=!1){y(D(n),"density must be a number"),y(D(s),"friction must be a number"),y(D(i),"restitution must be a number");let a=new b.instance.b2FixtureDef;return a.set_shape(e),a.set_density(n),a.set_friction(s),a.set_restitution(i),a.set_isSensor(r),this.body.CreateFixture(a)}addBox(e=w(1),n=w(),s=0,i,r,a,o){y(I(e),"size must be a Vector2"),y(e.x>0&&e.y>0,"size must be positive"),y(I(n),"offset must be a Vector2"),y(D(s),"angle must be a number");let c=new b.instance.b2PolygonShape;return c.SetAsBox(e.x/2,e.y/2,b.vec2dTo(n),-s),this.addShape(c,i,r,a,o)}addPoly(e,n,s,i,r){y(Tt(e),"points must be an array");function a(c){y(3<=c.length&&c.length<=8);let l=b.instance._malloc(c.length*8);for(let d=0,f=0;d>2]=c[d].x,f+=4,b.instance.HEAPF32[l+f>>2]=c[d].y,f+=4;let u=b.instance.wrapPointer(l,b.instance.b2Vec2),h=new b.instance.b2PolygonShape;return h.Set(u,c.length),b.instance._free(l),h}let o=a(e);return this.addShape(o,n,s,i,r)}addRegularPoly(e=1,n=8,s,i,r,a){y(D(e)&&e>0,"diameter must be a positive number"),y(D(n)&&n>2,"sides must be a positive number greater than 2");let o=[],c=e/2;for(let l=n;l--;)o.push(w(c,0).rotate((l+.5)/n*ie*2));return this.addPoly(o,s,i,r,a)}addRandomPoly(e=1,n,s,i,r){y(D(e)&&e>0,"diameter must be a positive number");let a=Yr(3,9),o=[],c=e/2;for(let l=a;l--;)o.push(w(ve(c/2,c*1.5),0).rotate(l/a*ie*2));return this.addPoly(o,n,s,i,r)}addCircle(e=1,n=w(),s,i,r,a){y(D(e)&&e>0,"diameter must be a positive number"),y(I(n),"offset must be a Vector2");let o=new b.instance.b2CircleShape;return o.set_m_p(b.vec2dTo(n)),o.set_m_radius(e/2),this.addShape(o,s,i,r,a)}addEdge(e,n,s,i,r,a){y(I(e),"point1 must be a Vector2"),y(I(n),"point2 must be a Vector2");let o=new b.instance.b2EdgeShape;return o.Set(b.vec2dTo(e),b.vec2dTo(n)),this.addShape(o,s,i,r,a)}addEdgeList(e,n,s,i,r){y(Tt(e),"points must be an array");let a=[],o=[];for(let c=0;ce[pt(l,e.length)];for(let l=0;lthis.destroyFixture(e))}getCenterOfMass(){return b.vec2From(this.body.GetWorldCenter())}getLinearVelocity(){return b.vec2From(this.body.GetLinearVelocity())}getAngularVelocity(){return this.body.GetAngularVelocity()}getMass(){return this.body.GetMass()}getInertia(){return this.body.GetInertia()}getIsAwake(){return this.body.IsAwake()}getBodyType(){return this.body.GetType()}getSpeed(){return this.getLinearVelocity().length()}setTransform(e,n){this.pos=e,this.angle=n,this.body.SetTransform(b.vec2dTo(e),-n)}setPosition(e){this.setTransform(e,this.body.GetAngle())}setAngle(e){this.setTransform(b.vec2From(this.body.GetPosition()),e)}setLinearVelocity(e){this.body.SetLinearVelocity(b.vec2dTo(e))}setAngularVelocity(e){this.body.SetAngularVelocity(e)}setLinearDamping(e){this.body.SetLinearDamping(e)}setAngularDamping(e){this.body.SetAngularDamping(e)}setGravityScale(e=1){this.body.SetGravityScale(this.gravityScale=e)}setBullet(e=!0){this.body.SetBullet(e)}setAwake(e=!0){this.body.SetAwake(e)}setBodyType(e){this.body.SetType(e)}setSleepingAllowed(e=!0){this.body.SetSleepingAllowed(e)}setFixedRotation(e=!0){this.body.SetFixedRotation(e)}setCenterOfMass(e){this.setMassData(e)}setMass(e){this.setMassData(void 0,e)}setMomentOfInertia(e){this.setMassData(void 0,void 0,e)}resetMassData(){this.body.ResetMassData()}setMassData(e,n,s){let i=new b.instance.b2MassData;this.body.GetMassData(i),e!==void 0&&i.set_center(b.vec2dTo(e)),n!==void 0&&i.set_mass(n),s!==void 0&&i.set_I(s),this.body.SetMassData(i)}setFilterData(e=0,n=0,s=0){this.getFixtureList().forEach(i=>{let r=i.GetFilterData();r.set_categoryBits(e),r.set_maskBits(65535&~n),r.set_groupIndex(s)})}setSensor(e=!0){this.getFixtureList().forEach(n=>n.SetSensor(e))}applyForce(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyForce(b.vec2dTo(e),b.vec2dTo(n))}applyAcceleration(e,n){n||(n=this.getCenterOfMass()),this.setAwake();let s=e.scale(this.getMass());this.body.ApplyLinearImpulse(b.vec2dTo(s),b.vec2dTo(n))}applyImpulse(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyLinearImpulse(b.vec2dTo(e),b.vec2dTo(n))}applyTorque(e){this.setAwake(),this.body.ApplyTorque(e)}applyAngularAcceleration(e){this.setAwake(),this.body.ApplyAngularImpulse(e*this.getInertia())}applyAngularImpulse(e){this.setAwake(),this.body.ApplyAngularImpulse(e)}hasFixtures(){return!b.isNull(this.body.GetFixtureList())}getFixtureList(){let e=[];for(let n=this.body.GetFixtureList();!b.isNull(n);)e.push(n),n=n.GetNext();return e}hasJoints(){return!b.isNull(this.body.GetJointList())}getJointList(){let e=[];for(let n=this.body.GetJointList();!b.isNull(n);)e.push(n),n=n.get_next();return e}},Ki=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeStatic;super(e,n,s,i,r,o,a)}},Rr=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeKinematic;super(e,n,s,i,r,o,a)}},Mr=class extends Ki{constructor(e){y(e instanceof qs,"tileLayer must be a TileCollisionLayer"),super(e.pos,e.size),this.tileLayer=e,this.addChild(e)}render(){}buildCollision(e=.2,n=0){this.destroyAllFixtures(),this.pos=this.tileLayer.pos.copy(),this.size=this.tileLayer.size.copy();let s=[],i=(a,o)=>a+o*this.size.x,r=(a,o)=>!s[i(a,o)]&&this.tileLayer.getCollisionData(w(a,o))>0;for(let a=0;ai.fractionr.pos.distanceSquared(e)0,"Tween duration must be > 0"),this.callback=e,this.start=n,this.end=s,this.duration=i,this.life=i,this.ease=r.ease||no.LINEAR,this.useRealTime=!!r.useRealTime,this.paused=!!r.paused,this.thenCallback=void 0,this.loopRemaining=0,ct.push(this),e(this.interp(i))}setEase(e){return this.ease=e,this}then(e){return this.thenCallback=e,this.loopRemaining=0,this}loop(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>zl(this),this}pingPong(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>Ul(this),this}pause(){this.paused=!0}resume(){this.paused=!1}restart(){this.life=this.duration,this.paused=!1,ct.indexOf(this)<0&&ct.push(this),this.callback(this.interp(this.duration))}isActive(){return!this.paused&&ct.indexOf(this)>=0}getPercent(){return He(this.duration-this.life,0,this.duration)}getValue(){return this.interp(this.life)}interp(e){let n=this.ease((this.duration-e)/this.duration);return zc(this.start)?this.start.lerp(this.end,n):this.start+(this.end-this.start)*n}stop(){let e=ct.indexOf(this);e>=0&&ct.splice(e,1),this.thenCallback=void 0}},no={LINEAR:t=>t,POWER:t=>e=>e**t,SINE:t=>1-be(t*(ie/2)),CIRC:t=>1-(1-t*t)**.5,EXPO:t=>t===0?0:2**(10*t-10),BACK:t=>t*t*(2.70158*t-1.70158),ELASTIC:t=>t===0?0:t===1?1:-(2**(10*t-10))*pe((37-40*t)*ie/6),SPRING:t=>1-(pe(ie*(1-t)*(.2+2.5*(1-t)**3))*t**2.2+(1-t))*(1+1.2*t),BOUNCE:t=>{let e=1-t,n;return e<4/11?n=7.5625*e*e:e<8/11?n=7.5625*(e-=6/11)*e+.75:e<10/11?n=7.5625*(e-=9/11)*e+.9375:n=7.5625*(e-=10.5/11)*e+.984375,1-n},IN:t=>t,OUT:t=>e=>1-t(1-e),IN_OUT:t=>no.PIECEWISE(t,no.OUT(t)),PIECEWISE:(...t)=>{let e=t.length;return n=>{let s=n*e-1e-9>>0;return(t[s]((n-s/e)*e)+s)/e}},BEZIER:(t,e,n,s)=>{let i=r=>{let a=1-r,o=3*a*a*r,c=3*a*r*r,l=r**3;return[o*t+c*n+l,o*e+c*s+l]};return r=>{let a=0,o=1;for(let c=0;c<128;c++){let l=(a+o)/2,[u,h]=i(l);if(he(u-r)<1e-5)return h;u=this.size.x||n>=this.size.y?null:this.nodes[e+n*this.size.x]}worldToTile(e){let n=this.tileLayer?this.tileLayer.pos.x:0,s=this.tileLayer?this.tileLayer.pos.y:0;return w(Le(e.x-n),Le(e.y-s))}tileToWorld(e,n){let s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;return w(e+.5+s,n+.5+i)}buildNodeData(){let e=this.size.x,n=this.size.y,s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;for(let r=0;r0&&(c?l>0&&Ce(o.posWorld,er,K(1,0,0,de(.2,l*.05)),this.debugTime):Ce(o.posWorld,er,K(1,0,0,.25),this.debugTime))}}aStarSearch(e,n){y(e&&n,"aStarSearch needs both endpoints"),y(e!==n,"aStarSearch: start and end must differ \u2014 caller should handle trivial case"),y(e.walkable&&n.walkable,"aStarSearch: endpoints must be walkable");let s=[e];e.isOpen=!0;let i=0;for(;s.length>0;){let r=0,a=s[0].f;for(let c=1;cthis.maxLoop)break;o.isOpen=!1,s.splice(r,1),o.isClosed=!0,this.debug&&this.debugTime>0&&Ce(o.posWorld,er,K(1,1,1,.05),this.debugTime);for(let c=-1;c<=1;++c)for(let l=-1;l<=1;++l){if(l===0&&c===0)continue;let u=this.getNode(o.pos.x+l,o.pos.y+c);if(!u||!u.walkable||u.isClosed)continue;let h=1;if(l!==0&&c!==0){let x=this.getNode(o.pos.x+l,o.pos.y);if(!x||!x.walkable)continue;let v=this.getNode(o.pos.x,o.pos.y+c);if(!v||!v.walkable)continue;h=Wh}let d=o.g+h+u.cost;if(!u.isOpen)u.isOpen=!0,s.push(u);else if(d>=u.g)continue;u.parent=o,u.g=d;let f=he(n.pos.x-u.pos.x),m=he(n.pos.y-u.pos.y),p=le(f,m)+(Math.SQRT2-1)*de(f,m);u.f=u.g+p*this.heuristicWeight}}return n.parent!==null}getNearestClearNode(e,n=10,s=!0){y(I(e),"worldPos must be a Vector2"),s&&this.buildNodeData();let i=this.tileLayer?this.tileLayer.pos.x:0,r=this.tileLayer?this.tileLayer.pos.y:0,a=Le(e.x-i),o=Le(e.y-r);for(let c=0;c<=n;++c){let l=null,u=0;for(let h=-c;h<=c;++h)for(let d=-c;d<=c;++d){if(c>0&&he(d)!==c&&he(h)!==c)continue;let f=this.getNode(a+d,o+h);if(!f||!f.isClear())continue;let m=f.posWorld.x-e.x,p=f.posWorld.y-e.y,x=m*m+p*p;(!l||x0&&et(i.posWorld,.3,K(.5,0,.5,.5),this.debugTime),e.splice(n,1),n=le(1,n-1);continue}else if(c===2){this.debug&&this.debugTime>0&&et(i.posWorld,.3,K(1,0,0,.5),this.debugTime);let f,m;s.pos.y===i.pos.y&&r.pos.x===i.pos.x?(f=s.pos.x,m=r.pos.y):(f=r.pos.x,m=s.pos.y);let p=this.getNode(f,m);if(p&&p.isClear()){e.splice(n,1),n=le(1,n-1);continue}}else if(c===5){this.debug&&this.debugTime>0&&et(i.posWorld,.3,K(1,1,0,.5),this.debugTime);let f=n>=2?e[n-2]:s,m,p,x,v;l===0||h===0?(m=r.pos.x,p=i.pos.y,x=s.pos.x,v=i.pos.y):(m=i.pos.x,p=r.pos.y,x=i.pos.x,v=s.pos.y);let A=m-f.pos.x,S=p-f.pos.y,_=x-f.pos.x,k=v-f.pos.y,C=A*A+S*S,O=_*_+k*k,z=C0&&et(i.posWorld,.3,K(0,1,0,.5),this.debugTime),l===h&&u===d){++n;continue}else{let f,m;s.pos.y===r.pos.y?(f=i.pos.x,m=s.pos.y):(f=s.pos.x,m=i.pos.y);let p=this.getNode(f,m);if(p&&p.isClear()){e[n]=p,n=le(1,n-1);continue}}++n}}smoothPathStringPull(e){if(e.length<=2)return;for(let i of e)if(!i.isClear())return;let n=e.slice();e.length=0,e.push(n[0]);let s=0;for(let i=1;i0&&Lt(r.posWorld,e[e.length-1].posWorld,K(0,0,1,.3),.02,this.debugTime);continue}for(;s=1;--n){let s=e[n-1],i=e[n],r=e[n+1];(i.pos.x-s.pos.x)*(r.pos.y-s.pos.y)===(i.pos.y-s.pos.y)*(r.pos.x-s.pos.x)&&e.splice(n,1)}}isNodeClear(e,n){let s=this.getNode(e,n);return s!==null&&s.isClear()}isLineClear(e,n){y(I(e)&&I(n),"isLineClear needs Vector2 endpoints"),y(this.isNodeClear(e.x,e.y)&&this.isNodeClear(n.x,n.y),"isLineClear endpoints must be in-bounds and clear");let s=n.x-e.x,i=n.y-e.y,r=he(s),a=he(i),o=ht(s),c=ht(i),l=e.x,u=e.y;if(a===r){for(;l!==n.x;){if(l!==e.x&&(!this.isNodeClear(l,u)||!this.isNodeClear(l,u-c))||!this.isNodeClear(l,u+c))return!1;l+=o,u+=c}if(!this.isNodeClear(n.x,n.y-c))return!1}else if(ao.posWorld.copy());if(this.debug&&this.debugTime>0&&a.length>0){for(let o=1;oqh,bootGameHost:()=>$h,default:()=>Hh});var An=class{constructor(e){this._state=(e==null?2654435769:e)>>>0}next(){this._state=this._state+1831565813>>>0;let e=this._state;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}range(e,n){return e+this.next()*(n-e)}reseed(e){this._state=(e==null?2654435769:e)>>>0}},vo=class{constructor(e){this._clock=e||tu(),this._origin=this._clock()}nowMs(){return this._clock()}elapsedMs(){return this._clock()-this._origin}},wo=class{constructor(e){this._time=e,this._subs=new Map}sourceFor(e){let n=this,s=e==null?null:e;return{on(i,r){if(n._assertType(i),typeof r!="function")throw new Error("[HostDevInputBridge] on \u7684 handler \u5FC5\u987B\u662F\u51FD\u6570");let a=n._subs.get(i)||[],o={handler:r,scope:s};return a.push(o),n._subs.set(i,a),{cancel(){let c=n._subs.get(i);if(!c)return;let l=c.indexOf(o);l>=0&&c.splice(l,1)}}},off(i,r){n._assertType(i);let a=n._subs.get(i);if(!a)return;let o=a.findIndex(c=>c.handler===r&&c.scope===s);o>=0&&a.splice(o,1)}}}_emit(e,n){this._assertType(e);let s=n||{},i={type:e,x:typeof s.x=="number"?s.x:0,y:typeof s.y=="number"?s.y:0,key:typeof s.key=="string"?s.key:"",tMs:this._time.nowMs()},r=this._subs.get(e);if(!r||r.length===0)return;let a=r.slice();for(let o of a)try{o.handler(i)}catch(c){on("[host-dev input] \u8F93\u5165 handler \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09type="+e,c)}}disposeScope(e){if(e==null)return 0;let n=0;for(let[s,i]of this._subs){let r=i.filter(a=>a.scope!==e);n+=i.length-r.length,r.length===0?this._subs.delete(s):this._subs.set(s,r)}return n}_subscriptionCount(){let e=0;for(let n of this._subs.values())e+=n.length;return e}_assertType(e){if(!To.has(e))throw new Error("[HostDevInputBridge] \u975E\u6CD5\u8F93\u5165\u4E8B\u4EF6\u7C7B\u578B\uFF1A"+String(e)+"\uFF08\u4EC5\u652F\u6301 "+Array.from(To).join("/")+"\uFF09")}},To=new Set(["pointerdown","pointermove","pointerup","keydown","keyup"]);function ja(t){let e=t||{},n=new vo(e.clock),s=new An(e.seed),i=e.seed==null?2654435769:e.seed>>>0,r=new wo(n),a=typeof e.audioFactory=="function"?e.audioFactory:null,o=null,c=!1,l=typeof e.engineFactory=="function"?e.engineFactory:null,u=null,h=!1,d=new Map,f=0,m=0;function p(){if(o)return o;if(!a)return c||(ko("[host-dev audio] \u672A\u6CE8\u5165 audioFactory\uFF0CgetAudioContext \u8FD4\u56DE null\uFF08P6 \u987B\u5BB9\u9519\u964D\u7EA7\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u5DE5\u5382\uFF09"),c=!0),null;try{o=a()}catch(_){on("[host-dev audio] audioFactory \u629B\u9519\uFF0CgetAudioContext \u964D\u7EA7\u8FD4\u56DE null",_),o=null}return o}function x(){if(u)return u;if(!l)return h||(ko("[host-dev engine] \u672A\u6CE8\u5165 engineFactory\uFF0CgetEngine \u8FD4\u56DE null\uFF08\u63D2\u4EF6\u987B\u5BB9\u9519\u964D\u7EA7\uFF1A\u7C92\u5B50\u9000\u53D7\u63A7\u9762\u81EA\u7BA1/\u5408\u6210\u6838\u9000 vendored/\u6570\u5B66\u9000\u5185\u7F6E\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u80CC\u4E66\uFF09"),h=!0),null;try{u=l()}catch(_){on("[host-dev engine] engineFactory \u629B\u9519\uFF0CgetEngine \u964D\u7EA7\u8FD4\u56DE null",_),u=null}return u}function v(_,k){return{getContext2d(){return e.context2d==null?null:e.context2d},onFrame(O){let z=f++;return d.set(z,O),{cancel(){d.delete(z)}}},getInput(){return r.sourceFor(_)},getAudioContext(){return p()},getEngine(){return x()},time:n,random:k}}let A=v(null,s),S={context:A,tick(_){m+=1;let k=Array.from(d.values());for(let C of k)try{C(_,m)}catch(O){on("[host-dev tick] \u5E27\u56DE\u8C03\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09frame="+m,O)}},frameCount(){return m},inputBridge:r,deriveContextFor(_,k){let C=eu(i,_),O=new An(C);return v(k==null?_:k,O)}};return Object.defineProperty(A,Ao,{value:S,enumerable:!1,writable:!1,configurable:!1}),S}var Ao=Symbol("zaomeng.coreProtocol.contextBundle"),ui=class{constructor(){this._plugins=new Map,this._initOrder=[],this._initErrors=[],this._phase="idle",this._disposed=!1,this._context=void 0,this._pluginContexts=new Map}register(e){if(!e||typeof e!="object")throw new Error("[PluginRegistry] register \u9700\u8981\u4E00\u4E2A\u63D2\u4EF6\u5BF9\u8C61");if(typeof e.name!="string"||e.name.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6\u7F3A\u5C11\u5408\u6CD5 name");if(typeof e.version!="string"||e.version.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11\u5408\u6CD5 version");if(typeof e.init!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11 init \u51FD\u6570");if(e.dispose!=null&&typeof e.dispose!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7684 dispose \u5FC5\u987B\u662F\u51FD\u6570\u6216\u7701\u7565");if(this._plugins.has(e.name))throw new Error("[PluginRegistry] \u63D2\u4EF6\u91CD\u540D\u62D2\u7EDD\uFF1A"+e.name+" \u5DF2\u6CE8\u518C");return this._plugins.set(e.name,e),this}has(e){return this._plugins.has(e)}get(e){return this._plugins.get(e)}list(){return Array.from(this._plugins.keys())}initAll(){if(this._phase==="initialized")return ko("[PluginRegistry] initAll \u91CD\u590D\u8C03\u7528\uFF0C\u5DF2\u5FFD\u7565\uFF08\u5DF2\u5904\u4E8E initialized\uFF09"),this._initResult();if(this._phase==="disposed")throw new Error("[PluginRegistry] \u5DF2 dispose \u7684\u6CE8\u518C\u5668\u4E0D\u53EF\u518D initAll");if(this._context==null)throw new Error("[PluginRegistry] \u672A\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\uFF1A\u8BF7\u5728 initAll() \u4E4B\u524D\u8C03\u7528 useContext(context)\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context); reg.initAll();\uFF09");for(let[e,n]of this._plugins){let s=this._missingDeps(n);if(s.length>0){let r=new Error("[PluginRegistry] \u63D2\u4EF6 "+e+" \u4F9D\u8D56\u7F3A\u5931\uFF1A"+s.join(", ")+"\uFF08\u672A\u6CE8\u518C\uFF09");this._initErrors.push({name:e,error:r}),on("[PluginRegistry] \u8DF3\u8FC7 init\uFF08\u4F9D\u8D56\u7F3A\u5931\uFF0C\u5DF2\u9694\u79BB\uFF09\uFF1A"+e,r);continue}let i=this._contextFor(e);try{n.init(i),this._initOrder.push(e)}catch(r){let a=r instanceof Error?r:new Error(String(r));this._initErrors.push({name:e,error:a}),on("[PluginRegistry] \u63D2\u4EF6 init \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF0C\u4E0D\u8FDE\u5750\uFF09\uFF1A"+e,a)}}return this._phase="initialized",this._initResult()}_contextFor(e){let n=this._pluginContexts.get(e);if(n)return n;let s=this._context&&this._context[Ao],i;return s&&typeof s.deriveContextFor=="function"?i=s.deriveContextFor(e,e):i=this._context,this._pluginContexts.set(e,i),i}disposeAll(){if(this._disposed)return{disposed:[],errors:[]};let e=[],n=[],s=this._context&&this._context[Ao],i=s&&s.inputBridge;for(let r=this._initOrder.length-1;r>=0;r--){let a=this._initOrder[r],o=this._plugins.get(a);if(o&&typeof o.dispose=="function")try{o.dispose(),e.push(a)}catch(c){let l=c instanceof Error?c:new Error(String(c));n.push({name:a,error:l}),on("[PluginRegistry] \u63D2\u4EF6 dispose \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,l)}if(i&&typeof i.disposeScope=="function")try{i.disposeScope(a)}catch(c){on("[PluginRegistry] \u56DE\u6536\u63D2\u4EF6\u8F93\u5165\u8BA2\u9605\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,c)}}return this._disposed=!0,this._phase="disposed",{disposed:e,errors:n}}useContext(e){if(this._phase!=="idle")throw new Error("[PluginRegistry] useContext \u5FC5\u987B\u5728 initAll() \u4E4B\u524D\u8C03\u7528\uFF08\u5F53\u524D\u9636\u6BB5\uFF1A"+this._phase+"\uFF09\u3002\u8BF7\u5728\u4EFB\u4F55 initAll/disposeAll \u4E4B\u524D\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\u3002");if(e==null||typeof e!="object")throw new Error("[PluginRegistry] useContext \u9700\u8981\u4E00\u4E2A\u53D7\u63A7\u4E0A\u4E0B\u6587\u5BF9\u8C61\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context);\uFF09");return this._context=e,this}_missingDeps(e){return!Array.isArray(e.dependencies)||e.dependencies.length===0?[]:e.dependencies.filter(n=>!this._plugins.has(n))}_initResult(){return{ok:this._initErrors.length===0,initialized:this._initOrder.slice(),errors:this._initErrors.slice()}}};function eu(t,e){let n=2166136261,s=16777619,i=t>>>0;for(let a=0;a<32;a+=8){let o=i>>>a&255;n^=o,n=Math.imul(n,s)>>>0}let r=String(e);for(let a=0;a>>0,n^=o>>>8&255,n=Math.imul(n,s)>>>0}return n>>>0}function tu(){if(typeof globalThis!="undefined"&&globalThis.performance&&typeof globalThis.performance.now=="function")return()=>globalThis.performance.now();if(typeof process!="undefined"&&process.hrtime&&typeof process.hrtime.bigint=="function"){let t=process.hrtime.bigint();return()=>Number(process.hrtime.bigint()-t)/1e6}return()=>Date.now()}function on(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function ko(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Kh=Object.freeze(Array.from(To)),Ja="core-protocol-v0";var Na=Object.freeze(["t_boot","t_plugins_ready","t_game_init","t_first_paint","t_input_bound","t_game_start"]),Co=Na.reduce((t,e,n)=>(t[e]=n,t),Object.create(null)),nu=new Set(Na);function _o(t){let e=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}var za=_o("runtime-probe::seed::v1");function di(t){return t===null||typeof t!="object"?JSON.stringify(t):Array.isArray(t)?"["+t.map(di).join(",")+"]":"{"+Object.keys(t).sort().map(n=>JSON.stringify(n)+":"+di(t[n])).join(",")+"}"}function Ua(t){let e=di(t.extra==null?null:t.extra),n=di(Array.isArray(t.pluginSet)?t.pluginSet:[]);return["seq="+t.seq,"anchor="+t.anchor,"tMono="+t.tMono,"buildSha="+(t.buildSha||""),"pluginSet="+n,"extra="+e].join("|")}function su(t){return Math.round(t*1e3)/1e3}function iu(t){if(!Array.isArray(t))return{ok:!1,reason:"records_not_array"};let e=za,n=-1;for(let s=0;stypeof _=="string").slice().sort():[],i=typeof e.sink=="function"?e.sink:null,r=e.autoBoot!==!1,a=typeof e.inputAnchorType=="string"?e.inputAnchorType:"pointerdown",o=()=>0,c=!1,l=0,u=za,h=[],d=new Set,f=-1,m=null,p=!1,x=!1,v=!1;function A(_,k){let C=null;if(!nu.has(_))C="unknown_anchor";else{d.has(_)&&(C=C?C+";duplicate_anchor":"duplicate_anchor");let z=Co[_];z_.time.nowMs(),c=!0,r&&!x&&A("t_boot",{auto:!0}),m=_.getInput().on(a,k=>{p||(p=!0,A("t_input_bound",{firstInput:!0,type:k.type}))}),A("t_input_bound",{stage:"registered",type:a})},dispose(){v||(m&&(m.cancel(),m=null),v=!0)},mark:A,getRecords(){return h.map(_=>({..._}))},toJSONL(){return h.map(_=>JSON.stringify(_)).join(`
+`)},verify(){return iu(h)}}}function ou(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Wa(t){let e=t.LJS,n=t.engineMath,s=t.engineMode,i=t.recHook||(()=>{});if(s!=="real")return null;let r=n;return{math:{lerp:(o,c,l)=>(i("math.lerp"),r.lerp(o,c,l)),smoothStep:o=>(i("math.smoothStep"),r.smoothStep(o)),easing:Object.fromEntries(Object.keys(r.easing).map(o=>[o,c=>(i("math.easing."+o),r.easing[o](c))]))},particles:{spawnEmitter(o){i("particles.spawnEmitter");let c=e.screenToWorld(e.vec2(o.pos.x,o.pos.y)),l=e.cameraScale,u=o.emitTime!=null?o.emitTime:o.count!=null?1/60:0,h=o.emitRate!=null?o.emitRate:o.count!=null?o.count*60:100,d=(o.speed!=null?o.speed:0)/l/60,f=o.damping!=null?o.damping:1,m=o.colorStart||{r:1,g:1,b:1,a:1},p=o.colorEnd||{r:1,g:1,b:1,a:0},x=e.rgb(m.r,m.g,m.b,m.a),v=e.rgb(p.r,p.g,p.b,p.a),A=new e.ParticleEmitter(c,o.angle!=null?o.angle:0,(o.emitSize!=null?o.emitSize:0)/l,u,h,o.coneAngle!=null?o.coneAngle:Math.PI,void 0,x,x,v,v,o.particleTime!=null?o.particleTime:.5,(o.sizeStart!=null?o.sizeStart:6)/l,(o.sizeEnd!=null?o.sizeEnd:0)/l,d,0,f,1,o.gravityScale!=null?o.gravityScale:0,Math.PI,.1,0,!1,o.additive!=null?o.additive:!1,!0);return{isActive(){return A.isActive()},stop(){A.destroyed||A.destroy(!0)}}}},audio:{synth:{synthSfx:o=>{i("audio.synth.synthSfx");try{return e.zzfxG(...o)}catch(c){return console.error("[host][engine-audio] zzfxG \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(c&&c.message?c.message:c)),null}},synthSong:(o,c,l,u)=>{i("audio.synth.synthSong");try{return e.zzfxM(o,c,l,u)}catch(h){return console.error("[host][engine-audio] zzfxM \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(h&&h.message?h.message:h)),null}}}}}}function xt(t){return t<0?0:t>1?1:t}function qa(t){let e=t.Ease,n=e.POWER(2),s=e.POWER(3),i=e.OUT(n),r=e.IN_OUT(n),a=e.OUT(s),o=e.IN_OUT(s),c=e.OUT(e.BACK),l=e.OUT(e.ELASTIC);return{lerp:(u,h,d)=>t.lerp(u,h,d),smoothStep:u=>t.smoothStep(u),easing:{linear:u=>e.LINEAR(xt(u)),quadIn:u=>n(xt(u)),quadOut:u=>i(xt(u)),quadInOut:u=>r(xt(u)),cubicIn:u=>s(xt(u)),cubicOut:u=>a(xt(u)),cubicInOut:u=>o(xt(u)),backIn:u=>e.BACK(xt(u)),backOut:u=>c(xt(u)),elasticIn:u=>e.ELASTIC(xt(u)),elasticOut:u=>l(xt(u))}}}var rn=2,fi=1/60;async function Ha(t){let e=t.canvas,n=t.statusEl||null,s=t.engine,i=t.seed>>>0,r=t.mode||"play",a=t.engineMode||"real",o=t.viewport.w,c=t.viewport.h,l=t.factory,u=t.buildFactoryOpts||(()=>{}),h=t.plugins||{},d=t.registerOrder||Object.values(h),f=t.onReady||(()=>{}),m=t.recHook||(()=>{});function p(B){n&&(n.textContent=B)}let x=[];window.addEventListener("error",B=>x.push({type:"error",message:String(B&&B.message||B)})),window.addEventListener("unhandledrejection",B=>x.push({type:"unhandledrejection",message:String(B&&B.reason&&B.reason.message||B&&B.reason||B)}));let v=null,A=!1;function S(){if(!A)return null;if(v)return v;let B=window.AudioContext||window.webkitAudioContext;return B?(v=new B,v):null}let _=0,k=null,C=null,O=null,z=null,re=[],te={},T=null;function R(B,ye){try{O&&O.mark(B,ye)}catch(G){x.push({type:"mark",message:String(G&&G.message||G)})}}function P(){C&&typeof C._refreshChecklist=="function"&&C._refreshChecklist(te)}async function L(B,ye){k=ja({context2d:B,seed:i,audioFactory:S,clock:()=>_,engineFactory:()=>Wa({LJS:a==="real"?s:null,engineMath:a==="real"?qa(s):null,engineMode:a,recHook:m})});let G=new ui;for(let J of d)G.register(J);G.useContext(k.context),z=G.initAll(),re=G.list().concat(["runtime-probe"]),O=Va({pluginSet:re,inputAnchorType:"pointerdown",autoBoot:!0});let F=k.deriveContextFor("runtime-probe","runtime-probe");R("t_boot",{by:"game-host",stage:"pre-init",engineMode:a}),R("t_plugins_ready",{initialized:z.initialized.length,ok:z.ok});let j=u(k.context,{bundle:k,plugins:h,getRealAudioCtx:()=>v});C=l(j),await C.init({ctx:k.context,mainContext:B,canvas:ye(),seed:i}),T=C&&typeof C._forensicsView=="function"?C._forensicsView():null,R("t_game_init",{hasForensics:!!T}),N(),R("t_first_paint",{frame:k.frameCount()});try{O.init(F)}catch(J){x.push({type:"probe-init",message:String(J&&J.message||J)})}R("t_game_start",{mode:r,engineMode:a}),P(),f(je,{bundle:k,game:C,probe:O,checklist:te,uncaught:x,pluginSet:re,initRes:z,getGameForensics:()=>T,mark:R,stepOneFrame:N})}let M=null;function N(B){let ye=typeof B=="number"?B:fi;C&&(_+=ye*1e3,C.update(ye),a==="stub"&&M&&C.render(M),P())}function W(B){for(let ye=0;ye{}),C&&typeof C._onAudioUnlock=="function"&&C._onAudioUnlock()}let je={seed:i,mode:r,engineMode:a,protocol:Ja,frameCount:()=>k?k.frameCount():0,stepFrames:W,startRaf:()=>$n(),stopRaf:()=>jt(),tap(B,ye){ae(),k&&(k.inputBridge._emit("pointerdown",{x:B,y:ye}),k.inputBridge._emit("pointerup",{x:B,y:ye}))},do(B){C&&typeof C._handleAction=="function"&&C._handleAction(B)},state:()=>T?T.state():{phase:"booting"}};function ft(B){let ye=k.inputBridge;function G(F,j){let J=B.getBoundingClientRect();return{x:(F-J.left)/J.width*o,y:(j-J.top)/J.height*c}}B.addEventListener("pointerdown",F=>{ae(),ye._emit("pointerdown",G(F.clientX,F.clientY))}),B.addEventListener("pointermove",F=>{ye._emit("pointermove",G(F.clientX,F.clientY))}),B.addEventListener("pointerup",F=>{ye._emit("pointerup",G(F.clientX,F.clientY))})}let Pe=0,rt=!1,Ae=0;function bt(B){if(!rt)return;Ae===0&&(Ae=B);let ye=(B-Ae)/1e3;Ae=B,ye>.05&&(ye=.05),N(ye),Pe=window.requestAnimationFrame(bt)}function $n(){a==="stub"&&(rt||(rt=!0,Ae=0,Pe=window.requestAnimationFrame(bt)))}function jt(){rt=!1,Pe&&window.cancelAnimationFrame(Pe),Pe=0}function Yn(B){B.width=o*rn,B.height=c*rn,B.style.width=o+"px",B.style.height=c+"px";let ye=B.getContext("2d",{willReadFrequently:!0});return ye.setTransform(rn,0,0,rn,0,0),ye}async function Ss(){let B=Yn(e);return M=B,await L(B,()=>e),ft(e),r==="evidence"?p(`evidence \u5C31\u7EEA seed=${i} \xB7 \u7528 host \u9A71\u52A8\uFF08stepFrames/tap\uFF09`):(p(`seed=${i} \xB7 \u70B9\u5F00\u59CB\uFF08\u9996\u6B21\u70B9\u51FB\u5F00\u58F0\uFF09`),$n()),je}let tn=()=>{},nn=()=>{};function sn(){window.__gameHostEngineInitFired=!0}function Xn(){tn()}function Kn(){}function go(){nn()}function bo(){}async function xo(B){await L(B,()=>s.mainCanvas),ft(s.mainCanvas),tn=()=>{C&&(_+=fi*1e3,C.update(fi))},nn=()=>{if(C){B.save(),B.setTransform(rn,0,0,rn,0,0);try{B.imageSmoothingEnabled=!1}catch{}C.render(B),B.restore()}},s.mainCanvas&&(s.mainCanvas.id="game-engine"),window.__engine={frame(){return s.frame},time(){return s.time},timeReal(){return s.timeReal},paused(){return s.paused},timeScale(){return s.timeScale},snapshot(){return{frame:s.frame,time:s.time,timeReal:s.timeReal,paused:s.paused,timeScale:s.timeScale}}},p(`engine RAF running \xB7 seed=${i} engine=real`)}if(a!=="real")return await Ss();if(!s){let B="real \u901A\u9053\u672A\u6CE8\u5165\u5F15\u64CE\uFF08opts.engine \u7F3A\u5931\uFF09\uFF1A\u8BF7\u7ECF entry \u5305\u88C5\u5C42\u542F\u52A8\uFF08host \u4E0D\u76F4\u63A5 import \u5F15\u64CE\uFF0CQ4/Option C\uFF09";throw p("ENGINE INJECT MISSING: "+B),new Error(B)}s.setGLEnable(!1),s.setShowSplashScreen(!1),s.setDebugWatermark(!1),s.setCanvasClearColor(s.BLACK),s.setCanvasFixedSize(s.vec2(o*rn,c*rn));let vs=document.createElement("div");return vs.id="engine-root",document.body.appendChild(vs),await s.engineInit(sn,Xn,Kn,go,bo,[],vs).then(()=>xo(s.mainContext)).catch(B=>{throw window.__gameHostBootError=String(B&&B.message||B),p("ENGINE INIT FAILED: "+window.__gameHostBootError),B}),je}function ru(){return{hit:!1,depth:0,nx:0,ny:0}}var Eo=class{constructor(e){let n=e||{},s=typeof n.cellSize=="number"&&n.cellSize>0?n.cellSize:64;this._cellSize=s,this._cells=new Map,this._entries=new Map,this._seq=0}get size(){return this._entries.size}_cellRange(e){let n=this._cellSize,s=Math.floor((e.x-e.hw)/n),i=Math.floor((e.x+e.hw)/n),r=Math.floor((e.y-e.hh)/n),a=Math.floor((e.y+e.hh)/n);return{cx0:s,cy0:r,cx1:i,cy1:a}}insert(e,n){this._entries.has(e)&&this.remove(e);let{cx0:s,cy0:i,cx1:r,cy1:a}=this._cellRange(n),o=[];for(let l=i;l<=a;l++)for(let u=s;u<=r;u++){let h=u+","+l,d=this._cells.get(h);d||(d=new Set,this._cells.set(h,d)),d.add(e),o.push(h)}let c={x:n.x,y:n.y,hw:n.hw,hh:n.hh};this._entries.set(e,{id:e,box:c,seq:this._seq++,cells:o})}remove(e){let n=this._entries.get(e);if(!n)return!1;for(let s of n.cells){let i=this._cells.get(s);i&&(i.delete(e),i.size===0&&this._cells.delete(s))}return this._entries.delete(e),!0}query(e){let{cx0:n,cy0:s,cx1:i,cy1:r}=this._cellRange(e),a=new Set;for(let o=s;o<=r;o++)for(let c=n;c<=i;c++){let l=this._cells.get(c+","+o);if(l)for(let u of l)a.add(u)}return this._collect(a)}queryPoint(e,n){let s=this._cellSize,i=Math.floor(e/s),r=Math.floor(n/s),a=this._cells.get(i+","+r);return a?this._collect(new Set(a)):[]}clear(){this._cells.clear(),this._entries.clear(),this._seq=0}_collect(e){let n=[];for(let s of e){let i=this._entries.get(s);i&&n.push(i)}return n.sort((s,i)=>s.seq-i.seq),n.map(s=>({id:s.id,box:s.box}))}};function $a(t,e){let n=t.x-e.x,s=t.y-e.y,i=t.hw+e.hw-Math.abs(n),r=t.hh+e.hh-Math.abs(s);return i<=1e-9||r<=1e-9?ru():i0?e.fixedStep:1/120;return{gx:n.x||0,gy:n.y||0,fixedStep:s}}function Ka(t,e,n,s){t.vx+=e*s,t.vy+=n*s,t.px+=t.vx*s,t.py+=t.vy*s}function au(t,e,n){let{gx:s,gy:i,fixedStep:r}=Qa(n),a={px:t.px,py:t.py,vx:t.vx,vy:t.vy},o=e>0?e:0;for(;o>=r-1e-12;)Ka(a,s,i,r),o-=r;return o>1e-12&&Ka(a,s,i,o),a}var hi=class{constructor(e,n){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy};let s=Qa(n);this._gx=s.gx,this._gy=s.gy,this._fixedStep=s.fixedStep}get state(){return{px:this._s.px,py:this._s.py,vx:this._s.vx,vy:this._s.vy}}step(e){let n=au(this._s,e,{gravity:{x:this._gx,y:this._gy},fixedStep:this._fixedStep});return this._s=n,this.state}reset(e){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy}}};function Za(t,e,n,s){let i=n.mass==null?1:n.mass,r=n.stiffness,a=n.damping,o=t.x,c=t.v,l=s>0?s:0;if(l<=1e-12)return{x:o,v:c};let u=i>1e-12?i:1e-12,h=Math.sqrt(Math.max(0,r)/u),d=a/u,f=h>1e-12?.2/h:l,m=d>1e-12?.5/d:l,p=Math.max(1e-12,Math.min(f,m)),x=Math.ceil(l/p);(!Number.isFinite(x)||x<1)&&(x=1),x>4096&&(x=4096);let v=l/x;for(let A=0;A1?1:t}var lu=t=>(t=$e(t),t*t),uu=t=>(t=$e(t),1-(1-t)*(1-t)),du=t=>(t=$e(t),t<.5?2*t*t:1-Math.pow(-2*t+2,2)/2),fu=t=>(t=$e(t),t*t*t),hu=t=>{t=$e(t);let e=1-t;return 1-e*e*e},pu=t=>(t=$e(t),t<.5?4*t*t*t:1-Math.pow(-2*t+2,3)/2),nc=2*Math.PI/3,tc=2*Math.PI/4.5,mu=t=>(t=$e(t),t===0?0:t===1?1:-Math.pow(2,10*t-10)*Math.sin((t*10-10.75)*nc)),yu=t=>(t=$e(t),t===0?0:t===1?1:Math.pow(2,-10*t)*Math.sin((t*10-.75)*nc)+1),gu=t=>(t=$e(t),t===0?0:t===1?1:t<.5?-(Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*tc))/2:Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*tc)/2+1),yi=1.70158,pi=yi*1.525,sc=yi+1,bu=t=>(t=$e(t),sc*t*t*t-yi*t*t),xu=t=>{t=$e(t);let e=t-1;return 1+sc*e*e*e+yi*e*e},Su=t=>(t=$e(t),t<.5?Math.pow(2*t,2)*((pi+1)*2*t-pi)/2:(Math.pow(2*t-2,2)*((pi+1)*(t*2-2)+pi)+2)/2),vu=t=>$e(t),Po=Object.freeze({linear:vu,quadIn:lu,quadOut:uu,quadInOut:du,cubicIn:fu,cubicOut:hu,cubicInOut:pu,elasticIn:mu,elasticOut:yu,elasticInOut:gu,backIn:bu,backOut:xu,backInOut:Su}),Mo=Po,wu=["linear","quadIn","quadOut","quadInOut","cubicIn","cubicOut","cubicInOut","elasticIn","elasticOut","elasticInOut","backIn","backOut","backInOut"];function Tu(t){let e=t&&t.easing;if(!e)return Po;let n=i=>typeof e[i]=="function"?r=>e[i]($e(r)):Po[i],s={};for(let i of wu)s[i]=n(i);return Object.freeze(s)}var Ro=class{constructor(e,n,s){let i=s||{};this._time=n,this._windowMs=typeof i.windowMs=="number"&&i.windowMs>0?i.windowMs:120;let r=Array.isArray(i.types)&&i.types.length>0?i.types:cu;this._records=new Map,this._subs=[],this._disposed=!1;for(let a of r){this._records.set(a,null);let o=e.on(a,c=>{this._records.set(a,c.tMs)});this._subs.push(o)}}consume(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs?(this._records.set(e,null),!0):(this._records.set(e,null),!1)}peek(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs}clear(){for(let e of this._records.keys())this._records.set(e,null)}dispose(){if(!this._disposed){for(let e of this._subs)try{e.cancel()}catch(n){}this._subs=[],this._disposed=!0}}};var mi=class{constructor(e,n){let s=n||{};this._time=e,this._windowMs=typeof s.windowMs=="number"&&s.windowMs>0?s.windowMs:500,this._maxCount=typeof s.maxCount=="number"&&s.maxCount>0?s.maxCount:1/0,this._count=0,this._lastHitAt=null}hit(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt!=null&&n-this._lastHitAt<=this._windowMs&&this._count>0?this._count=Math.min(this._count+1,this._maxCount):this._count=1,this._lastHitAt=n,this._count}getCount(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt==null||n-this._lastHitAt>this._windowMs?0:this._count}reset(){this._count=0,this._lastHitAt=null}};function ic(t){let e=t||{},n=null,s=null,i=!1;return{name:"gamefeel",version:"1.0.0",dependencies:[],get inputBuffer(){return n},get easing(){return Tu(s)},init(a){let o=a.getInput();n=new Ro(o,a.time,{windowMs:e.inputBufferMs,types:e.inputTypes});let c=a.getEngine();s=c?c.math:null},dispose(){i||(n&&(n.dispose(),n=null),s=null,i=!0)}}}function gi(t,e){let n=e<0?0:e>1?1:e;switch(t&&t.kind){case"constant":return t.value;case"linear":return t.from+(t.to-t.from)*n;case"easeInOut":{let s=n*n*(3-2*n);return t.from+(t.to-t.from)*s}case"decay":{let s=t.power==null?2:t.power,i=Math.pow(1-n,s);return t.to+(t.from-t.to)*i}default:return 0}}var Au=Object.freeze({burst:Object.freeze({mode:"burst",count:24,angle:0,spread:Math.PI,speedMin:80,speedMax:160,lifeMin:.4,lifeMax:.8,gravity:0,drag:0,sizeCurve:{kind:"decay",from:6,to:0,power:1.5},alphaCurve:{kind:"linear",from:1,to:0}}),trail:Object.freeze({mode:"continuous",rate:60,angle:Math.PI,spread:.25,speedMin:20,speedMax:50,lifeMin:.2,lifeMax:.5,gravity:0,drag:1.5,sizeCurve:{kind:"easeInOut",from:4,to:0},alphaCurve:{kind:"decay",from:.8,to:0,power:2}}),drift:Object.freeze({mode:"continuous",rate:12,angle:Math.PI/2,spread:.6,speedMin:10,speedMax:30,lifeMin:1.5,lifeMax:3,gravity:8,drag:.5,sizeCurve:{kind:"constant",value:3},alphaCurve:{kind:"decay",from:.7,to:0,power:1}})});function ku(t){let e=Au[t];return e?Lo(e):null}function Lo(t){let e={};for(let n of Object.keys(t)){let s=t[n];e[n]=s&&typeof s=="object"?Lo(s):s}return e}function Cu(t,e,n){let s=t.mode==="continuous";return{pos:{x:e,y:n},angle:t.angle,coneAngle:t.spread,emitSize:0,emitTime:s?0:1/60,emitRate:s?t.rate||0:void 0,count:s?void 0:t.count||0,particleTime:(t.lifeMin+t.lifeMax)/2,speed:(t.speedMin+t.speedMax)/2,gravityScale:t.gravity||0,damping:t.drag!=null?1-t.drag/60:1,sizeStart:gi(t.sizeCurve,0),sizeEnd:gi(t.sizeCurve,1),colorStart:{r:1,g:1,b:1,a:gi(t.alphaCurve,0)},colorEnd:{r:1,g:1,b:1,a:gi(t.alphaCurve,1)},additive:!1}}function bi(t){let e=t||{},n=null,s=null,i=null,r=new Map,a=0,o={isActive(){return!1},stop(){}},c=0,l=1,u=0,h=0,d=0,f={x:0,y:0,remain:0,dur:0,amplitude:0,frequency:0,_phase:0},m={alpha:0,remain:0,dur:0,peak:0},p={scale:1,remain:0,dur:0,amplitude:0,frequency:0},x=!1;function v(k){if(u>0)if(u-=k,u<=0)u=0,l=1;else{let C=h>0?1-u/h:1;l=d+(1-d)*C}if(f.remain>0)if(f.remain-=k,f.remain<=0)f.remain=0,f.x=0,f.y=0;else{let C=f.remain/f.dur,O=f.amplitude*C;f._phase+=f.frequency*k*Math.PI*2,f.x=Math.sin(f._phase)*O,f.y=Math.cos(f._phase*1.3)*O}if(m.remain>0&&(m.remain-=k,m.remain<=0?(m.remain=0,m.alpha=0):m.alpha=m.peak*(m.remain/m.dur)),p.remain>0)if(p.remain-=k,p.remain<=0)p.remain=0,p.scale=1;else{let C=p.remain/p.dur,O=(1-C)*p.frequency*Math.PI*2;p.scale=1+Math.sin(O)*p.amplitude*C}}function A(k){c+=1,v(k)}function S(k){let C=k!==void 0?k:n?n.getContext2d():null;if(C&&m.alpha>0){C.globalAlpha=m.alpha,C.fillStyle="#ffffff";let O=C.canvas?C.canvas.width:0,z=C.canvas?C.canvas.height:0;C.fillRect(0,0,O,z),C.globalAlpha=1}}return{name:"particles-juice",version:"1.0.0",dependencies:[],init(k){var C;n=k,i=((C=k.getEngine())==null?void 0:C.particles)||null,typeof e.seed=="number"&&k.random.reseed(e.seed),e.autoStep!==!1&&(s=k.onFrame(O=>{A(O)}))},dispose(){x||(s&&(s.cancel(),s=null),r.forEach(k=>{try{k.stop()}catch{}}),r.clear(),l=1,u=0,f.remain=0,f.x=0,f.y=0,m.remain=0,m.alpha=0,p.remain=0,p.scale=1,x=!0)},spawnEmitter(k,C,O,z){let re=typeof k=="string"?ku(k):Lo(k);if(!re)return-1;z&&(re=Object.assign(re,z));let te=a++;if(!i)return r.set(te,o),te;let T=i.spawnEmitter(Cu(re,C,O));return r.set(te,T),te},stopEmitter(k){let C=r.get(k);if(C)try{C.stop()}catch{}},step(k){A(k)},render(k){S(k)},particleCount(){return 0},emitterCount(){let k=0;for(let C of r.values())C.isActive()&&(k+=1);return k},hitStop(k,C){h=Math.max(0,k),u=h,d=C==null?0:Math.max(0,Math.min(1,C)),l=h>0?d:1},getTimeScale(){return l},shakeScreen(k,C,O){f.dur=Math.max(0,k),f.remain=f.dur,f.amplitude=Math.max(0,C),f.frequency=O==null?30:O,f._phase=0,f.x=0,f.y=0},getShakeOffset(){return{x:f.x,y:f.y}},flashScreen(k,C){m.dur=Math.max(0,k),m.remain=m.dur,m.peak=C==null?.8:Math.max(0,Math.min(1,C)),m.alpha=m.dur>0?m.peak:0},getFlashAlpha(){return m.alpha},pulseScale(k,C,O){p.dur=Math.max(0,k),p.remain=p.dur,p.amplitude=C==null?.2:C,p.frequency=O==null?4:O,p.scale=1},getPulseScale(){return p.scale},juiceSnapshot(){return{timeScale:l,shake:{x:f.x,y:f.y},flashAlpha:m.alpha,pulseScale:p.scale}},probe(){return{particles:0,emitters:r.size,dropped:0,steps:c,disposed:x}}}}function oc(t){let e=Te(t.r)/255,n=Te(t.g)/255,s=Te(t.b)/255,i=Math.max(e,n,s),r=Math.min(e,n,s),a=(i+r)/2,o=0,c=0,l=i-r;return l>1e-12&&(c=a>.5?l/(2-i-r):l/(i+r),i===e?o=(n-s)/l%6:i===n?o=(s-e)/l+2:o=(e-n)/l+4,o*=60,o<0&&(o+=360)),{h:o,s:c,l:a}}function rc(t){let e=(t.h%360+360)%360,n=an(t.s),s=an(t.l);if(n<1e-12){let o=Math.round(s*255);return{r:o,g:o,b:o}}let i=s<.5?s*(1+n):s+n-s*n,r=2*s-i,a=e/360;return{r:Math.round(Oo(r,i,a+1/3)*255),g:Math.round(Oo(r,i,a)*255),b:Math.round(Oo(r,i,a-1/3)*255)}}function Oo(t,e,n){let s=n;return s<0&&(s+=1),s>1&&(s-=1),s<1/6?t+(e-t)*6*s:s<1/2?e:s<2/3?t+(e-t)*(2/3-s)*6:t}function Te(t){return t<0?0:t>255?255:t}function an(t){return t<0?0:t>1?1:t}function Go(t,e){let n=Eu(t.from,e);if(n>=0&&n({r:Te(o.r),g:Te(o.g),b:Te(o.b)})),to:r}}function Do(t,e,n){return t+(e-t)*n}function jo(t,e){let n=oc(t),s=n.h+(e.hue||0),i=an(n.s*(e.sat==null?1:e.sat)),r=an(n.l*(e.light==null?1:e.light));return rc({h:s,s:i,l:r})}var Ru=Object.freeze([Object.freeze([0,8,2,10]),Object.freeze([12,4,14,6]),Object.freeze([3,11,1,9]),Object.freeze([15,7,13,5])]);function ac(t){let e=t||{},n=null,s=!1,i={vignette:{enabled:Io(e.vignette&&e.vignette.enabled,!1),strength:Fo(e.vignette&&e.vignette.strength,.5)},dither:{enabled:Io(e.dither&&e.dither.enabled,!1),strength:Fo(e.dither&&e.dither.strength,.5)},scanline:{enabled:Io(e.scanline&&e.scanline.enabled,!1),strength:Fo(e.scanline&&e.scanline.strength,.5)}};function r(o){let c=o!==void 0?o:n?n.getContext2d():null;if(!c)return;let l=c.canvas?c.canvas.width:0,u=c.canvas?c.canvas.height:0;if(i.vignette.enabled&&i.vignette.strength>0&&l>0&&u>0){let h=c.createRadialGradient(l/2,u/2,Math.min(l,u)*.25,l/2,u/2,Math.max(l,u)*.75);h.addColorStop(0,"rgba(0,0,0,0)"),h.addColorStop(1,"rgba(0,0,0,"+i.vignette.strength.toFixed(3)+")"),c.fillStyle=h,c.fillRect(0,0,l,u)}if(i.scanline.enabled&&i.scanline.strength>0&&l>0&&u>0){c.fillStyle="rgba(0,0,0,"+(i.scanline.strength*.5).toFixed(3)+")";for(let h=0;h0&&l>0&&u>0&&typeof c.getImageData=="function"&&typeof c.putImageData=="function"){let h=c.getImageData(0,0,l,u);Mu(h,i.dither.strength),c.putImageData(h,0,0)}}return{name:"palette-post",version:"1.0.0",dependencies:[],init(o){n=o},dispose(){s||(n=null,s=!0)},applyPaletteMap(o,c){return Go(o,c)},applyPaletteMapToBuffer(o,c){return _u(o,c)},lerpPaletteMap(o,c,l){return Bo(o,c,l)},shiftHsl(o,c){return jo(o,c)},rgbToHsl(o){return oc(o)},hslToRgb(o){return rc(o)},setPost(o){if(o)for(let c of["vignette","dither","scanline"])o[c]&&(typeof o[c].enabled=="boolean"&&(i[c].enabled=o[c].enabled),typeof o[c].strength=="number"&&(i[c].strength=an(o[c].strength)))},getPost(){return{vignette:{enabled:i.vignette.enabled,strength:i.vignette.strength},dither:{enabled:i.dither.enabled,strength:i.dither.strength},scanline:{enabled:i.scanline.enabled,strength:i.scanline.strength}}},renderPost(o){r(o)},probe(){return{disposed:s,post:this.getPost()}}}}function Mu(t,e){let n=an(e);if(n<=0)return t;let{data:s,width:i}=t,a=255/(Math.max(2,Math.round(16-n*14))-1);for(let o=0;o+3>2)%i,l=Math.floor((o>>2)/i),u=(Ru[l&3][c&3]/16-.5)*a;for(let h=0;h<3;h++){let d=s[o+h]+u,f=Math.round(d/a)*a;s[o+h]=f<0?0:f>255?255:f}}return t}function Io(t,e){return typeof t=="boolean"?t:e}function Fo(t,e){return typeof t=="number"?an(t):e}var No=Object.freeze({blip:Object.freeze({name:"blip",params:Object.freeze([.6,0,880,0,.03,.06,1,1.5])}),thud:Object.freeze({name:"thud",params:Object.freeze([.8,0,90,0,.04,.18,0,1,0,0,0,0,0,4])}),chime:Object.freeze({name:"chime",params:Object.freeze([.5,0,660,.02,.12,.3,1,2])})}),cc=Object.keys(No);function Lu(t){let e=[];return t==null||typeof t!="object"?{ok:!1,errors:["song \u5FC5\u987B\u662F\u5BF9\u8C61"]}:(!Array.isArray(t.instruments)||t.instruments.length===0?e.push("instruments \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.instruments.forEach((n,s)=>{(!Array.isArray(n)||n.some(i=>typeof i!="number"||!Number.isFinite(i)))&&e.push(`instruments[${s}] \u5FC5\u987B\u662F\u6709\u9650\u6570\u5B57\u6570\u7EC4\uFF08ZzFX \u53C2\u6570\u5305\uFF09`)}),!Array.isArray(t.patterns)||t.patterns.length===0?e.push("patterns \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.patterns.forEach((n,s)=>{if(!Array.isArray(n)||n.length===0){e.push(`patterns[${s}] \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF08\u81F3\u5C11\u4E00\u4E2A\u58F0\u90E8\u901A\u9053\uFF09`);return}n.forEach((i,r)=>{if(!Array.isArray(i)||i.length<2){e.push(`patterns[${s}][${r}] \u901A\u9053\u81F3\u5C11\u542B [\u4E50\u5668\u7D22\u5F15, \u58F0\u50CF]`);return}if(i.some(c=>typeof c!="number"||!Number.isFinite(c))){e.push(`patterns[${s}][${r}] \u901A\u9053\u5FC5\u987B\u5168\u4E3A\u6709\u9650\u6570\u5B57`);return}let a=i[0]|0;Array.isArray(t.instruments)&&(a<0||a>=t.instruments.length)&&e.push(`patterns[${s}][${r}] \u4E50\u5668\u7D22\u5F15 ${a} \u8D8A\u754C\uFF08instruments \u957F\u5EA6 ${t.instruments.length}\uFF09`);let o=i[1];(o<-1||o>1)&&e.push(`patterns[${s}][${r}] \u58F0\u50CF ${o} \u8D8A\u754C\uFF08\u5E94 -1..+1\uFF09`)})}),!Array.isArray(t.sequence)||t.sequence.length===0?e.push("sequence \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.sequence.forEach((n,s)=>{if(typeof n!="number"||!Number.isInteger(n)){e.push(`sequence[${s}] \u5FC5\u987B\u662F\u6574\u6570 pattern \u7D22\u5F15`);return}Array.isArray(t.patterns)&&(n<0||n>=t.patterns.length)&&e.push(`sequence[${s}] \u7D22\u5F15 ${n} \u8D8A\u754C\uFF08patterns \u957F\u5EA6 ${t.patterns.length}\uFF09`)}),t.bpm!=null&&(typeof t.bpm!="number"||!(t.bpm>0))&&e.push("bpm \u5FC5\u987B\u662F\u6B63\u6570"),{ok:e.length===0,errors:e})}function Ct(t){return typeof t!="number"||Number.isNaN(t)||t<0?0:t>1?1:t}function Ou(t,e){switch(t){case"ease-in":return e*e;case"ease-out":return Math.sqrt(e);case"constant":return 1;default:return e}}function lc(t,e){let n=Ct(e);return t==null||!Array.isArray(t.voices)?[]:t.voices.map(s=>{let i=String(s&&s.id!=null?s.id:""),r=Array.isArray(s&&s.channelIndices)?s.channelIndices.slice():[],a=typeof s.minIntensity=="number"?Ct(s.minIntensity):0,o=typeof s.maxIntensity=="number"?Ct(s.maxIntensity):1,c=typeof s.volumeCurve=="string"?s.volumeCurve:"linear",l=typeof s.baseVolume=="number"?Ct(s.baseVolume):1;if(no)return{id:i,on:!1,volume:0,channelIndices:r};let u=o-a,h=u<=0?1:(n-a)/u,d=Ct(Ou(c,h)*l);return{id:i,on:!0,volume:d,channelIndices:r}})}function uc(t,e,n,s){try{let i=e[0]||[],r=e[1]||i,a=Math.max(i.length,r.length);if(a===0)return null;let c=t.createBuffer(2,a,44100);c.getChannelData(0).set(i),c.getChannelData(1).set(r.length?r:i);let l=t.createBufferSource();l.buffer=c,l.loop=!!s;let u=t.createGain();return u.gain.value=Ct(n*.3),l.connect(u),u.connect(t.destination),l.start(),{stop(){try{l.stop()}catch(h){}try{l.disconnect(),u.disconnect()}catch(h){}}}}catch(i){return zo("[audio-music] \u53D7\u63A7\u97F3\u9891\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",i),null}}function dc(t){let e=t||{},n=typeof e.masterVolume=="number"?Ct(e.masterVolume):1,s=()=>null,i=null,r=null,a={voices:[]},o=1,c=null,l=!1,u=0,h=!1,d=!1;function f(){let S=s();return S==null?(u+=1,h||(Jo("[audio-music] \u65E0\u53D7\u63A7\u97F3\u9891\u4E0A\u4E0B\u6587\uFF08getAudioContext \u8FD4\u56DE null\uFF09\uFF0C\u5168\u90E8\u53D1\u58F0\u9759\u9ED8 no-op\uFF08\u8BC4\u4F30\u73AF\u5883\u65E0\u58F0\u5361\u65F6\u7684\u5BB9\u9519\u964D\u7EA7\uFF09"),h=!0),null):S}function m(){if(!r||!i)return null;try{let S=typeof r.bpm=="number"&&r.bpm>0?r.bpm:125;return i.synthSong(r.instruments,r.patterns,r.sequence,S)}catch(S){return zo("[audio-music] \u66F2\u8C31\u6E32\u67D3\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",S),null}}function p(){let S=lc(a,o);if(S.length===0)return 1;let _=0;for(let k of S)k.on&&(_=Math.max(_,k.volume));return _}function x(S,_){typeof _=="number"&&(o=Ct(_));let k=f();if(k==null||!r)return;v();let C=m();if(!C)return;let O=Ct(n*p());c=uc(k,C,O,S),l=!!S&&c!=null}function v(){c&&(c.stop(),c=null),l=!1}return{name:"audio-music",version:"1.0.0",dependencies:[],init(S){s=()=>S.getAudioContext();let _=S.getEngine&&S.getEngine();i=_?_.audio.synth:null},dispose(){d||(v(),d=!0)},loadSong(S){let _=Lu(S);return _.ok?r={instruments:S.instruments,patterns:S.patterns,sequence:S.sequence,bpm:typeof S.bpm=="number"?S.bpm:125}:Jo("[audio-music] \u66F2\u8C31\u6821\u9A8C\u5931\u8D25\uFF0C\u672A\u8F7D\u5165\uFF1A"+_.errors.join("\uFF1B")),_},play(S){x(!1,S)},stop(){v()},loop(S){x(!0,S)},setIntensityLayering(S){a=S&&Array.isArray(S.voices)?{voices:S.voices}:{voices:[]}},setIntensity(S){o=Ct(S)},resolveVoices(S){return lc(a,S)},playSfx(S){let _=No[S];if(!_){Jo("[audio-music] \u672A\u77E5\u97F3\u6548\u9884\u8BBE\uFF1A"+String(S));return}let k=f();if(k!=null)try{let C=i?i.synthSfx(_.params):null;if(!C)return;uc(k,[C,C],n,!1)}catch(C){zo("[audio-music] \u97F3\u6548\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8 name="+S,C)}},getPreset(S){return No[S]},listPresets(){return cc.slice()},probe(){return{hasAudio:s()!=null,hasSong:r!=null,intensity:o,voiceCount:a.voices.length,looping:l,silentNoops:u,presetCount:cc.length}}}}function zo(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Jo(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Du="zaomeng.save";function Iu(t){if(typeof TextEncoder!="undefined")return new TextEncoder().encode(t).length;if(typeof Buffer!="undefined"&&typeof Buffer.byteLength=="function")return Buffer.byteLength(t,"utf8");let e=0;for(let n=0;n=55296&&s<=56319?(e+=4,n++):e+=3}return e}function Vo(){let t=new Map;return{getItem(e){return t.has(e)?t.get(e):null},setItem(e,n){t.set(e,n)},removeItem(e){t.delete(e)},keys(){return Array.from(t.keys())}}}function fc(){if(typeof localStorage=="undefined")throw new Error("[save-progress] createLocalStorageAdapter \u9700\u8981\u5168\u5C40 localStorage\uFF08\u4EC5\u6D4F\u89C8\u5668\u96C6\u6210\u6BB5\u53EF\u7528\uFF09\u3002node/host-dev \u8BF7\u7528\u7F3A\u7701\u5185\u5B58 adapter \u6216 createMemoryAdapter()\u3002");return{getItem(t){return localStorage.getItem(t)},setItem(t,e){localStorage.setItem(t,e)},removeItem(t){localStorage.removeItem(t)},keys(){let t=[];for(let e=0;e0?e.namespace:Du;if(n.indexOf(":")>=0)throw new Error('[save-progress] namespace \u4E0D\u5F97\u542B\u5206\u9694\u7B26 ":"\uFF08\u5F53\u524D="'+n+'"\uFF09');let s=typeof e.maxValueBytes=="number"&&e.maxValueBytes>0?Math.floor(e.maxValueBytes):32768,i=!Fu(e.adapter),r=i?Vo():e.adapter,a=n+":",o=0,c=0,l=!1;function u(f){return typeof f!="string"||f.length===0?a+String(f):a+f}function h(){try{let f=r.keys();return Array.isArray(f)?f.filter(m=>typeof m=="string"&&m.indexOf(a)===0):[]}catch(f){return ws("[save-progress] adapter.keys() \u5F02\u5E38\uFF0C\u964D\u7EA7\u8FD4\u56DE\u7A7A\u96C6",f),[]}}return{name:"save-progress",version:"1.0.0",dependencies:[],init(f){h()},dispose(){},get(f,m){if(!Uo(f))return m;let p;try{p=r.getItem(u(f))}catch(x){return ws("[save-progress] adapter.getItem \u5F02\u5E38\uFF0C\u8FD4\u56DE\u9ED8\u8BA4\u503C key="+f,x),m}if(p==null)return m;try{return JSON.parse(p)}catch{return o+=1,l||(Ts("[save-progress] \u68C0\u6D4B\u5230\u635F\u574F\u5B58\u6863\uFF08\u975E\u6CD5 JSON\uFF09\uFF0C\u5DF2\u5BB9\u9519\u56DE\u9000\u9ED8\u8BA4\u503C key="+f),l=!0),m}},set(f,m){if(!Uo(f))return Ts("[save-progress] set \u6536\u5230\u975E\u6CD5 key\uFF0C\u62D2\u7EDD\u5199\u5165\uFF1A"+String(f)),!1;let p;try{p=JSON.stringify(m)}catch{return c+=1,Ts("[save-progress] \u503C\u4E0D\u53EF JSON \u5E8F\u5217\u5316\uFF08\u5FAA\u73AF\u5F15\u7528?\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+f),!1}if(p===void 0)return c+=1,Ts("[save-progress] \u503C\u5E8F\u5217\u5316\u4E3A undefined\uFF08\u5982\u7EAF undefined/\u51FD\u6570\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+f),!1;let x=Iu(p);if(x>s)return c+=1,Ts("[save-progress] \u503C\u8D85\u5B57\u8282\u4E0A\u9650\u62D2\u7EDD\u5199\u5165 key="+f+"\uFF08"+x+" > "+s+" bytes\uFF09"),!1;try{return r.setItem(u(f),p),!0}catch(v){return c+=1,ws("[save-progress] adapter.setItem \u5F02\u5E38\uFF0C\u5199\u5165\u5931\u8D25 key="+f,v),!1}},remove(f){if(Uo(f))try{r.removeItem(u(f))}catch(m){ws("[save-progress] adapter.removeItem \u5F02\u5E38\uFF08\u5DF2\u5FFD\u7565\uFF09key="+f,m)}},clear(){let f=h(),m=0;for(let p of f)try{r.removeItem(p),m+=1}catch(x){ws("[save-progress] clear \u65F6 removeItem \u5F02\u5E38\uFF08\u5DF2\u8DF3\u8FC7\uFF09fullKey="+p,x)}return m},probe(){return{namespace:n,maxValueBytes:s,usingMemoryAdapter:i,size:h().length,corruptRecoveries:o,rejectedWrites:c}}}}function Uo(t){return typeof t=="string"&&t.length>0}function Fu(t){return!!t&&typeof t.getItem=="function"&&typeof t.setItem=="function"&&typeof t.removeItem=="function"&&typeof t.keys=="function"}function ws(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Ts(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Qn=[{id:"soda",name:"\u6C7D\u6C34",wholesale:20,basePrice:40,popularity:1,initial:!0},{id:"snack",name:"\u8FA3\u6761",wholesale:10,basePrice:25,popularity:1.2,initial:!0},{id:"bread",name:"\u9762\u5305",wholesale:30,basePrice:60,popularity:.8,initial:!0},{id:"ice",name:"\u51B0\u6DC7\u6DCB",wholesale:40,basePrice:90,popularity:.7,initial:!1},{id:"toy",name:"\u5C0F\u73A9\u5177",wholesale:80,basePrice:180,popularity:.35,initial:!1}];function Ye(t){return Qn.find(e=>e.id===t)}var Re={lengthSec:96,rushStartSec:30,rushEndSec:66,rushRampSec:3,daysPerSegment:3};function pc(t){let{rushStartSec:e,rushEndSec:n,rushRampSec:s}=Re;return t<=e-s||t>=n+s?0:t>=e&&t<=n?1:te.id===t)}function Ho(t){let e=n=>!!t[n];return{shelfCap:e("shelf2")?48:e("shelf1")?34:24,serveCooldownSec:e("speed2")?.32:e("speed1")?.42:.55,patienceMul:e("decor2")?1.3:e("decor1")?1.15:1,settleRepBonusTenth:e("decor2")?60:e("decor1")?30:0,flowMul:e("decor2")?1.12:1}}function Si(t){let e=t.priceMul,n=t.reputation==null?Xe.start:t.reputation,s=t.serveCapacity==null?26:t.serveCapacity,i=t.stockUnits==null?1/0:t.stockUnits,r=t.segment==null?1:t.segment,a=t.unlocked||Qn.filter(x=>x.initial).map(x=>x.id),l=((Re.lengthSec-(Re.rushEndSec-Re.rushStartSec))/cn.idleIntervalSec+(Re.rushEndSec-Re.rushStartSec)/cn.rushIntervalSec)*Wo(e)*qo(n),u=Math.min(l,s,i),h=a.map(x=>Ye(x)).filter(Boolean),d=h.reduce((x,v)=>x+v.popularity,0),f=h.reduce((x,v)=>x+(Math.round(v.basePrice*e)-v.wholesale)*(v.popularity/d),0),m=Math.round(u*f),p=ce.rentBaseJiao+(r-1)*ce.rentPerSegmentJiao;return{arrivals:l,served:u,grossJiao:m,rentJiao:p,profitJiao:m-p}}function ze(t,e,n){return tn?n:t}function Ke(t){let e=t/10;return Number.isInteger(e)?String(e):e.toFixed(1)}var gc=1,Gu=2600;function As(t){let e=t.random;if(!e||typeof e.next!="function")throw new Error("[shop-core] \u5FC5\u987B\u6CE8\u5165\u53D7\u63A7\u968F\u673A\u6E90 random\uFF08next/range/reseed\uFF09");let n=0,s={nowMs:()=>n,elapsedMs:()=>n},i=new mi(s,{windowMs:Gu,maxCount:99}),r=[];function a(T,R){r.push(Object.assign({type:T,tMs:Math.round(n)},R||{}))}let o={phase:"title",day:1,cash:ce.startCashJiao,repTenth:Xe.start*10,priceMul:1,stock:{},unlocked:Qn.filter(T=>T.initial).map(T=>T.id),upgrades:{},customers:[],dayTimeSec:0,rushFactor:0,serveCooldown:0,comboCount:0,prepBought:{},today:c(),lifetime:{days:0,served:0,angry:0,netJiao:0,upgradesBought:0},settle:null,summary:null,gameoverReason:null};function c(){return{revenueJiao:0,soldCostJiao:0,served:0,angry:0,stockout:0,walkaway:0,rescued:0,bigSales:0,maxCombo:0}}let l=1,u=0,h=!1,d=Ho(o.upgrades);function f(){d=Ho(o.upgrades)}function m(){let T=0;for(let R of Object.keys(o.stock))T+=o.stock[R];return T}function p(){return o.repTenth/10}function x(T){o.repTenth=ze(o.repTenth+T,0,Xe.max*10)}function v(T){let R=o.phase;o.phase=T,a("phase_changed",{from:R,to:T})}function A(T){o.day=T,o.prepBought={},o.today=c(),o.customers=[],o.dayTimeSec=0,o.rushFactor=0,o.settle=null,o.summary=null,v("prep"),a("save_point",{})}function S(){let T=o.rushFactor>.5?cn.rushIntervalSec:cn.idleIntervalSec,R=Wo(o.priceMul)*qo(p())*d.flowMul;u=T/Math.max(R,.05)*e.range(cn.jitterMin,cn.jitterMax)}function _(){let T=o.unlocked.map(L=>Ye(L)),R=T.reduce((L,M)=>L+M.popularity,0),P=e.next()*R;for(let L of T)if(P-=L.popularity,P<=0)return L.id;return T[T.length-1].id}function k(){for(let T=0;TR.slot===T))return T;return-1}function C(){let T=_(),R=k();if(R<0){o.today.walkaway+=1,a("walkaway_full",{productId:T});return}let L=(o.rushFactor>.5?kn.rushSec:kn.idleSec)*d.patienceMul*e.range(.9,1.12),M={id:l++,productId:T,slot:R,mood:"queue",patienceSec:L,patienceMaxSec:L,timerSec:0,avatar:Math.floor(e.next()*4)%4,impatientFired:!1};(o.stock[T]||0)<=0&&(M.mood="stockout",M.timerSec=kn.stockoutLingerSec),o.customers.push(M),a("customer_arrive",{id:M.id,slot:R,productId:T,mood:M.mood})}function O(T){let R=o.customers.indexOf(T);R>=0&&o.customers.splice(R,1)}function z(T){o.dayTimeSec+=T,o.rushFactor=pc(o.dayTimeSec);let R=o.rushFactor>.5;if(R!==h&&(a(R?"rush_start":"rush_end",{}),h=R),o.serveCooldown>0&&(o.serveCooldown=Math.max(0,o.serveCooldown-T)),o.dayTimeSec>=Re.lengthSec){a("closing",{}),o.customers=[],re();return}u-=T,u<=0&&(C(),S());for(let P=o.customers.length-1;P>=0;P--){let L=o.customers[P];if(L.mood==="queue"){if((o.stock[L.productId]||0)<=0){L.mood="stockout",L.timerSec=kn.stockoutLingerSec;continue}L.patienceSec-=T,!L.impatientFired&&L.patienceSec/L.patienceMaxSec<=kn.impatientRatio&&(L.impatientFired=!0,a("customer_impatient",{id:L.id,slot:L.slot})),L.patienceSec<=0&&(L.mood="leaving",L.timerSec=kn.graceSec,a("customer_grace",{id:L.id,slot:L.slot}))}else L.mood==="leaving"?(L.timerSec-=T,L.timerSec<=0&&(O(L),o.today.angry+=1,x(-Xe.angryLossTenth),a("angry_leave",{id:L.id,slot:L.slot,avatar:L.avatar,productId:L.productId,repLossTenth:Xe.angryLossTenth}))):L.mood==="stockout"&&(L.timerSec-=T,L.timerSec<=0&&(O(L),o.today.stockout+=1,x(-Xe.stockoutLossTenth),a("stockout_leave",{id:L.id,slot:L.slot,avatar:L.avatar,productId:L.productId,repLossTenth:Xe.stockoutLossTenth})))}o.comboCount=i.getCount(n)}function re(){let T=o.today,R=Math.ceil(o.day/Re.daysPerSegment),P=ce.rentBaseJiao+(R-1)*ce.rentPerSegmentJiao,L=0;p()R.initial).map(R=>R.id),o.upgrades={},o.lifetime={days:0,served:0,angry:0,netJiao:0,upgradesBought:0},o.gameoverReason=null,f(),i.reset(),a("game_start",{continued:!1}),A(1),{ok:!0,continued:!1})},buyStock(T,R){let P=Math.max(1,Math.floor(R||1));if(o.phase!=="prep")return{ok:!1,reason:"phase"};let L=Ye(T);if(!L||!o.unlocked.includes(T))return{ok:!1,reason:"unknown_product"};if(m()+P>d.shelfCap)return{ok:!1,reason:"shelf_full"};let M=L.wholesale*P;return o.cash0)return{ok:!1,reason:"cooldown"};if(!o.unlocked.includes(T))return{ok:!1,reason:"unknown_product"};if((o.stock[T]||0)<=0)return a("tap_empty",{productId:T}),{ok:!1,reason:"no_stock"};let R=o.customers.filter(W=>W.productId===T&&(W.mood==="queue"||W.mood==="leaving")).sort((W,ae)=>W.id-ae.id)[0];if(!R)return a("tap_nocustomer",{productId:T}),{ok:!1,reason:"no_customer"};let P=R.mood==="leaving";o.stock[T]-=1;let L=i.hit(n);o.comboCount=L,o.today.maxCombo=Math.max(o.today.maxCombo,L);let M=Math.round(mc(T,o.priceMul)*yc(L));o.cash+=M,o.today.revenueJiao+=M,o.today.soldCostJiao+=Ye(T).wholesale,o.today.served+=1,o.lifetime.served+=1,P&&(o.today.rescued+=1),x(Xe.serveGainTenth+(P?Xe.rescueBonusTenth:0)),o.serveCooldown=d.serveCooldownSec;let N=M>=ce.bigSaleJiao;return N&&(o.today.bigSales+=1),O(R),a("serve_ok",{id:R.id,slot:R.slot,avatar:R.avatar,productId:T,revenueJiao:M,combo:L,big:N,rescued:P}),{ok:!0,revenueJiao:M,combo:L,big:N,rescued:P,customerId:R.id}},confirmSettle(){if(o.phase!=="settle")return{ok:!1,reason:"phase"};let T=o.day;if(a("save_point",{}),T%Re.daysPerSegment===0){let R=T/Re.daysPerSegment;o.summary={segment:R,days:T,netJiao:o.lifetime.netJiao,served:o.lifetime.served,upgradesBought:o.lifetime.upgradesBought,reputation:p()},v("summary"),a("segment_end",{summary:o.summary})}else A(T+1);return{ok:!0}},confirmSummary(){return o.phase!=="summary"?{ok:!1,reason:"phase"}:(A(o.day+1),{ok:!0})},derived(){return d},reputation:p,totalStock:m,snapshotForSave(){return{v:gc,day:o.day,cash:o.cash,repTenth:o.repTenth,priceMul:o.priceMul,stock:Object.assign({},o.stock),unlocked:o.unlocked.slice(),upgrades:Object.assign({},o.upgrades),lifetime:Object.assign({},o.lifetime)}},restoreFromSave(T){return!T||T.v!==gc||typeof T.day!="number"||typeof T.cash!="number"||typeof T.repTenth!="number"||!T.unlocked||!Array.isArray(T.unlocked)||T.unlocked.length===0?!1:(o.cash=Math.floor(T.cash),o.repTenth=ze(Math.floor(T.repTenth),0,Xe.max*10),o.priceMul=ze(T.priceMul||1,ce.priceMin,ce.priceMax),o.stock=Object.assign({},T.stock||{}),o.unlocked=T.unlocked.filter(R=>!!Ye(R)),o.upgrades=Object.assign({},T.upgrades||{}),o.lifetime=Object.assign({days:0,served:0,angry:0,netJiao:0,upgradesBought:0},T.lifetime||{}),o.gameoverReason=null,f(),i.reset(),a("game_start",{continued:!0}),A(Math.max(1,Math.floor(T.day))),!0)}};return te}var ks={open_shop:["\u5F00\u5F20\u55BD\u2014\u2014\u8857\u574A\u4EEC\u90FD\u7B49\u7740\u5462\uFF01","\u4ECA\u513F\u4E2A\u8FDB\u70B9\u5565\u597D\u8D27\uFF1F\u6211\u5FC3\u91CC\u6709\u6570\u3002","\u5C0F\u672C\u751F\u610F\uFF0C\u8D26\u53EF\u5F97\u7B97\u660E\u767D\u54AF\u3002"],day_start:["\u5F00\u95E8\u8FCE\u5BA2\uFF01\u90FD\u9EBB\u5229\u70B9\u513F~","\u54DF\uFF0C\u4ECA\u5929\u592A\u9633\u4E0D\u9519\uFF0C\u51C6\u662F\u4E2A\u597D\u65E5\u5B50\u3002"],idle_chat:["\u6162\u60A0\u60A0\u7684\u4E0B\u5348\uFF0C\u6700\u9002\u5408\u76D8\u8D26\u5566\u3002","\u9694\u58C1\u8001\u674E\u53C8\u6765\u8D4A\u8D26\uFF1F\u60F3\u5F97\u7F8E\u3002","\u8D27\u67B6\u64E6\u5F97\u9503\u4EAE\uFF0C\u770B\u7740\u5C31\u8212\u5766\u3002"],rush_start:["\u653E\u5B66\u5566\u653E\u5B66\u5566\uFF0C\u6253\u8D77\u7CBE\u795E\u6765\uFF01","\u4EBA\u90FD\u6D8C\u8FC7\u6765\u4E86\uFF0C\u624B\u4E0A\u522B\u505C\uFF01"],serve_ok:["\u597D\u561E\uFF0C\u62FF\u7A33\u5F53\uFF01","\u60A8\u6162\u8D70\uFF0C\u5E38\u6765\u554A~","\u8FD9\u5C31\u7ED9\u60A8\u62FF\uFF0C\u5FEB\u5F97\u5F88\uFF01"],combo_hot:["\u624B\u611F\u6765\u4E86\uFF0C\u8C01\u90FD\u522B\u62E6\u6211\uFF01","\u4E00\u4E2A\u63A5\u4E00\u4E2A\uFF0C\u8D8A\u5E72\u8D8A\u987A\u6E9C\uFF01"],big_sale:["\u54CE\u54DF\uFF0C\u5927\u4E3B\u987E\uFF01\u4ECA\u665A\u52A0\u4E2A\u9E21\u817F\uFF01","\u8FD9\u5355\u9876\u534A\u5929\u4E70\u5356\uFF0C\u7F8E\u6ECB\u6ECB~"],rescue:["\u522B\u8D70\u522B\u8D70\uFF0C\u8FD9\u5C31\u7ED9\u60A8\u62FF\u4E0A\uFF01","\u597D\u9669\u597D\u9669\uFF0C\u5DEE\u70B9\u513F\u9EC4\u4E86\u4E00\u5355\u3002"],angry:["\u54CE\u5440\uFF0C\u628A\u4EBA\u667E\u8DD1\u4E86\u2026\u2026\u5FC3\u75BC\u3002","\u7838\u62DB\u724C\u4E86\u7838\u62DB\u724C\u4E86\uFF0C\u5F97\u4E0A\u70B9\u5FC3\uFF01"],stockout:["\u7A7A\u8D27\u67B6\u6700\u6233\u5FC3\u7A9D\u5B50\uFF0C\u660E\u513F\u591A\u5907\u70B9\u3002","\u53C8\u5356\u65AD\u4E86\u2026\u2026\u662F\u597D\u4E8B\u4E5F\u662F\u574F\u4E8B\u3002"],settle_win:["\u4ECA\u513F\u8D26\u9762\u7EA2\u706B\uFF0C\u8BB0\u4E0A\u8BB0\u4E0A\uFF01","\u8F9B\u82E6\u4E00\u5929\uFF0C\u503C\u5F53\uFF01"],settle_lose:["\u8FD9\u8D26\u2026\u2026\u8D8A\u7B97\u8D8A\u5FC3\u51C9\u3002","\u7F5A\u5355\u90FD\u8D34\u8138\u4E0A\u4E86\uFF0C\u660E\u5929\u5F97\u6362\u4E2A\u6D3B\u6CD5\u3002"],upgrade:["\u820D\u4E0D\u5F97\u5B69\u5B50\u5957\u4E0D\u7740\u72FC\uFF0C\u5347\uFF01","\u9E1F\u67AA\u6362\u70AE\uFF0C\u54B1\u4E5F\u8BB2\u7A76\u4E00\u56DE\uFF01"],gameover:["\u5509\u2026\u2026\u5377\u5E18\u95E8\u4E00\u62C9\uFF0C\u4ECE\u5934\u518D\u6765\u5427\u3002"]},bp=Object.keys(ks).length;function bc(t){let e={};return function(s){let i=ks[s];if(!i||i.length===0)return"";if(i.length===1)return i[0];let r=Math.floor(t.next()*i.length)%i.length;return r===e[s]&&(r=(r+1)%i.length),e[s]=r,i[r]}}var Cs={paper:{r:246,g:231,b:201},paperHi:{r:255,g:246,b:227},cream:{r:255,g:243,b:220},ink:{r:91,g:70,b:54},inkSoft:{r:138,g:108,b:84},wood:{r:169,g:118,b:79},woodDark:{r:124,g:84,b:55},gold:{r:232,g:169,b:66},coin:{r:246,g:196,b:83},amber:{r:240,g:196,b:117},brick:{r:201,g:111,b:74},danger:{r:178,g:72,b:54},leaf:{r:133,g:158,b:94},sky:{r:243,g:217,b:168},shadow:{r:62,g:49,b:40},scrim:{r:46,g:35,b:27},smoke:{r:140,g:106,b:85}},xc=Object.keys(Cs);function Sc(){let t=xc.map(a=>Cs[a]),e={from:t,to:t.slice()},n={from:t,to:t.map(a=>jo(a,{hue:-10,sat:1.18,light:.9}))},s=0,i=r(0);function r(a){let o=Bo(e,n,a),c={};for(let l of xc)c[l]=Go(o,Cs[l]);return c}return{setRush(a){let o=Math.round(Math.max(0,Math.min(1,a))*25)/25;o!==s&&(s=o,i=r(o))},rushT(){return s},c(a,o){let c=i[a]||Cs.ink,l=o==null?1:o;return l>=1?`rgb(${c.r},${c.g},${c.b})`:`rgba(${c.r},${c.g},${c.b},${l})`},rgb(a){return i[a]||Cs.ink}}}var $o={shopkeeperIdle:"shopkeeper-idle.jpg",shopkeeperWave:"shopkeeper-wave.jpg",customer0:"customer-kid.jpg",customer1:"customer-lady.jpg",customer2:"customer-grandpa.jpg",customer3:"customer-auntie.jpg",storefront:"storefront.jpg",itemSoda:"item-soda.jpg",itemSnack:"item-snack.jpg",itemBread:"item-bread.jpg",itemIce:"item-ice.jpg",itemToy:"item-toy.jpg",uiPanel:"ui-panel.jpg"},Cn={soda:"itemSoda",snack:"itemSnack",bread:"itemBread",ice:"itemIce",toy:"itemToy"};function vc(t){let e=t==null?"./assets/":t,n=Object.keys($o),s={},i=[];function r(a){return new Promise(o=>{if(typeof Image=="undefined"){s[a]=null,i.push(a),o(null);return}let c=new Image;c.onload=()=>{s[a]=c,o(c)},c.onerror=()=>{console.warn("[ref-assets] \u8D44\u4EA7\u52A0\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u7A0B\u5E8F\u5316\u56DE\u9000\uFF09\uFF1A"+$o[a]),s[a]=null,i.push(a),o(null)},c.src=e+$o[a]})}return Promise.all(n.map(r)).then(()=>({images:s,missing:i,loaded:n.length-i.length,total:n.length}))}function wc(t){let e=t.bundle,n=t.juice;function s(T){let R=bi({maxParticles:400});return R.init(e.deriveContextFor(T,T)),R}let i=s("fx-gold"),r=s("fx-cream"),a=s("fx-smoke"),o=[];function c(T,R,P){o.push({t:0,dur:Math.max(T,.001),ease:P&&P.ease||Mo.cubicOut,onUpdate:R,onDone:P&&P.onDone||null})}let l=new Map;function u(T,R){let P=l.get(T);return P||(P={state:{x:R==null?1:R,v:0},target:R==null?1:R,stiffness:320,damping:14},l.set(T,P)),P.state.x}function h(T,R,P){u(T);let L=l.get(T);L.state.v+=R,P!=null&&(L.target=P)}let d=[];function f(T){d.push({t:0,dur:T.dur||.3,fx:T.fx,fy:T.fy,tx:T.tx,ty:T.ty,arc:T.arc==null?46:T.arc,imageKey:T.imageKey||null,label:T.label||"",onArrive:T.onArrive||null})}let m=[],p=980;function x(T){let R=T.dur||.45,P=(T.tx-T.fx)/R,L=(T.ty-T.fy-.5*p*R*R)/R;m.push({proj:new hi({px:T.fx,py:T.fy,vx:P,vy:L},{gravity:{x:0,y:p}}),age:0,dur:R,tx:T.tx,ty:T.ty,imageKey:T.imageKey||null,onLand:T.onLand||null})}let v=[];function A(T,R,P,L,M){v.push({text:T,x:R,y:P,t:0,dur:.9,colorName:L||"gold",size:M||16})}let S=[];function _(T,R){S.push({x:T,y:R,t:0})}function k(T,R,P){i.spawnEmitter("burst",T,R,{count:P?26:13,angle:-Math.PI/2,spread:.85,speedMin:130,speedMax:P?320:240,gravity:420,lifeMin:.35,lifeMax:.7,sizeCurve:{kind:"decay",from:P?5.5:4,to:0,power:1.3}})}function C(T,R,P){r.spawnEmitter("burst",T,R,{count:P||10,angle:-Math.PI/2,spread:1.1,speedMin:40,speedMax:110,gravity:-30,lifeMin:.4,lifeMax:.8,sizeCurve:{kind:"decay",from:3,to:0,power:1}})}function O(T,R){a.spawnEmitter("burst",T,R,{count:12,angle:-Math.PI/2,spread:Math.PI,speedMin:25,speedMax:70,gravity:-18,drag:1.2,lifeMin:.5,lifeMax:1,sizeCurve:{kind:"easeInOut",from:5,to:1},alphaCurve:{kind:"decay",from:.7,to:0,power:1.5}})}function z(T,R){for(let P=o.length-1;P>=0;P--){let L=o[P];L.t+=T;let M=Math.min(L.t/L.dur,1);L.onUpdate(L.ease(M)),M>=1&&(L.onDone&&L.onDone(),o.splice(P,1))}for(let P of l.values())P.state=Za(P.state,P.target,{stiffness:P.stiffness,damping:P.damping},T);for(let P=d.length-1;P>=0;P--){let L=d[P];L.t+=R,L.t>=L.dur&&(L.onArrive&&L.onArrive(),d.splice(P,1))}for(let P=m.length-1;P>=0;P--){let L=m[P];L.age+=R,L.proj.step(R),L.age>=L.dur&&(L.onLand&&L.onLand(),m.splice(P,1))}for(let P=v.length-1;P>=0;P--){let L=v[P];L.t+=R,L.t>=L.dur&&v.splice(P,1)}for(let P=S.length-1;P>=0;P--)S[P].t+=T,S[P].t>=.32&&S.splice(P,1)}function re(T,R){T.save(),T.fillStyle=R.c("coin"),i.render(T),T.fillStyle=R.c("cream"),r.render(T),T.fillStyle=R.c("smoke"),a.render(T),T.restore(),n.render(T)}return{easing:Mo,addTween:c,springVal:u,springKick:h,addFlight:f,addToss:x,addFloater:A,addTapRing:_,burstCoin:k,burstSparkle:C,burstSmoke:O,step:z,renderParticles:re,view:{flights:d,tosses:m,floaters:v,tapRings:S},juice:n,particleProbe(){return{gold:i.particleCount(),cream:r.particleCount(),smoke:a.particleCount()}},dispose(){i.dispose(),r.dispose(),a.dispose()}}}function Tc(t){let e=t.getAudio,n=t.p6,s=t.baseUrl==null?"./assets/":t.baseUrl,i=new Set,r={loading:!1,ready:!1,failed:!1,gainIdle:null,gainRush:null,idleLevel:0,rushLevel:0,targetRush:0},a=null;function o(d){return a||(a=d.createGain(),a.gain.value=.5,a.connect(d.destination)),a}function c(){let d=e();if(!d||r.loading||r.ready||r.failed)return;r.loading=!0;function f(m){return fetch(s+m).then(p=>{if(!p.ok)throw new Error("HTTP "+p.status);return p.arrayBuffer()}).then(p=>d.decodeAudioData(p)).then(p=>{let x=d.createBufferSource();x.buffer=p,x.loop=!0;let v=d.createGain();return v.gain.value=0,x.connect(v),v.connect(d.destination),x.start(),v})}Promise.all([f("bgm-idle.mp3"),f("bgm-rush.mp3")]).then(([m,p])=>{r.gainIdle=m,r.gainRush=p,r.ready=!0,r.loading=!1}).catch(m=>{console.warn("[ref-audio] BGM \u88C5\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u65E0 BGM\uFF09\uFF1A"+(m&&m.message?m.message:m)),r.failed=!0,r.loading=!1})}function l(d,f,m){if(r.targetRush=f,!r.ready)return;let p=m?1:.35,x=.5*(1-f)*p,v=.55*f*p,A=Math.min(d/1.2,1);r.idleLevel+=(x-r.idleLevel)*A,r.rushLevel+=(v-r.rushLevel)*A,r.gainIdle.gain.value=r.idleLevel,r.gainRush.gain.value=r.rushLevel}function u(d,f,m,p,x,v,A){let S=d.currentTime+(A||0),_=d.createOscillator(),k=d.createGain();_.type=f,_.frequency.setValueAtTime(m,S),_.frequency.exponentialRampToValueAtTime(Math.max(p,1),S+x),k.gain.setValueAtTime(1e-4,S),k.gain.exponentialRampToValueAtTime(v,S+.012),k.gain.exponentialRampToValueAtTime(1e-4,S+x),_.connect(k),k.connect(o(d)),_.start(S),_.stop(S+x+.02)}function h(d,f){let m=e();if(!m)return;let p=f||{};switch(d){case"arrive":n.playSfx("blip");break;case"shelve":n.playSfx("thud");break;case"upgrade":n.playSfx("chime");break;case"coin":{let x=Math.min(p.combo||1,11),v=660*Math.pow(2,(x-1)*2/12);u(m,"sine",v,v*1.5,.16,.5),u(m,"sine",v*2,v*2.6,.1,.22,.03);break}case"bad":u(m,"sawtooth",220,90,.32,.3);break;case"rescue":u(m,"triangle",520,540,.07,.32),u(m,"triangle",660,690,.07,.32,.07),u(m,"triangle",880,920,.1,.34,.14);break;case"bigsale":u(m,"sine",130,80,.22,.5),u(m,"sine",1320,1760,.18,.3,.05);break;case"tick":u(m,"triangle",900,700,.045,.16);break;case"empty":u(m,"square",180,140,.08,.14);break;default:return}i.add(d)}return{startBgm:c,step:l,sfx:h,probe(){return{sfxKinds:Array.from(i),bgm:{ready:r.ready,failed:r.failed,idleLevel:r.idleLevel,rushLevel:r.rushLevel}}}}}var V=390,Zn=844,Me={hud:{x:8,y:8,w:V-16,h:84},keeper:{x:14,y:398,w:124,h:160},bubble:{x:16,y:318,w:230,h:72},queue:[{x:186,y:470},{x:244,y:452},{x:302,y:470},{x:356,y:452}],avatarR:27,counter:{x:0,y:540,w:V,h:26},shelf:{x:8,y:574,w:V-16,h:158},bottom:{x:8,y:740,w:V-16,h:96},combo:{x:330,y:512}};function En(t){let e=t%3,n=Math.floor(t/3);return{x:16+e*124,y:584+n*76,w:116,h:68}}function kc(t){let e={x:12,y:116,w:V-24,h:706},n=196,s=46,i=n+t.length*s+26,r=i+64,a=42,o={x:V/2-110,y:e.y+e.h-70,w:220,h:54};return{panel:e,stockY:n,rowH:s,sliderY:i,upY:r,upRowH:a,btn:o}}function Cc(t){return{x:78,y:t+26,w:240,h:8}}function Qe(t,e,n,s,i,r){let a=Math.min(r,s/2,i/2);t.beginPath(),t.moveTo(e+a,n),t.arcTo(e+s,n,e+s,n+i,a),t.arcTo(e+s,n+i,e,n+i,a),t.arcTo(e,n+i,e,n,a),t.arcTo(e,n,e+s,n,a),t.closePath()}function q(t,e,n){t.font=`${n?"600 ":""}${e}px "PingFang SC","Microsoft YaHei",sans-serif`}function Xo(t,e,n,s,i,r){let a=e.width/e.height,o=i/r,c=0,l=0,u=e.width,h=e.height;a>o?(u=e.height*o,c=(e.width-u)/2):(h=e.width/o,l=(e.height-h)/2),t.drawImage(e,c,l,u,h,n,s,i,r)}function _n(t,e,n,s,i,r,a,o,c){t.save(),Qe(t,s,i,r,a,o),t.clip(),n?Xo(t,n,s,i,r,a):(t.fillStyle=e.c("amber"),t.fillRect(s,i,r,a),t.fillStyle=e.c("ink"),q(t,Math.min(a*.42,22),!0),t.textAlign="center",t.textBaseline="middle",t.fillText(c||"?",s+r/2,i+a/2)),t.restore()}function Ac(t,e,n,s,i,r,a){t.save(),t.beginPath(),t.arc(s,i,r,0,Math.PI*2),t.clip(),n?Xo(t,n,s-r,i-r,r*2,r*2):(t.fillStyle=e.c("sky"),t.fillRect(s-r,i-r,r*2,r*2),t.fillStyle=e.c("ink"),q(t,r,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a||"\u5BA2",s,i)),t.restore()}function _t(t,e,n,s,i,r,a,o){t.save(),Qe(t,s,i,r,a,o==null?14:o),t.clip();let c=n.images.uiPanel;c?t.drawImage(c,c.width*.2,c.height*.04,c.width*.78,c.height*.9,s,i,r,a):(t.fillStyle=e.c("paper"),t.fillRect(s,i,r,a)),t.restore(),t.strokeStyle=e.c("wood"),t.lineWidth=2,Qe(t,s,i,r,a,o==null?14:o),t.stroke()}function ln(t,e,n,s,i,r,a,o){let c=o||{},l=c.scale==null?1:c.scale;t.save(),t.translate(n+i/2,s+r/2),t.scale(l,l),Qe(t,-i/2,-r/2,i,r,r/2-6),t.fillStyle=c.disabled?e.c("inkSoft",.45):e.c(c.color||"brick"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("paperHi"),q(t,c.fontSize||20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a,0,1),t.restore()}function Yo(t,e,n,s,i,r,a,o,c){Qe(t,n,s,i,r,r/2),t.fillStyle=e.c(c||"shadow",.25),t.fill();let l=ze(a,0,1);l>.01&&(Qe(t,n,s,Math.max(i*l,r),r,r/2),t.fillStyle=e.c(o||"gold"),t.fill())}function Bu(t,e,n){let s=n.images.storefront;s?Xo(t,s,0,0,V,Zn):(t.fillStyle=e.c("sky"),t.fillRect(0,0,V,Zn));let i=t.createLinearGradient(0,380,0,560);i.addColorStop(0,e.c("paper",0)),i.addColorStop(.5,e.c("paper",.28)),i.addColorStop(1,e.c("paper",.05)),t.fillStyle=i,t.fillRect(0,380,V,190)}function ju(t,e,n){let{core:s,fx:i,assets:r}=n,a=s.state,o=Me.hud;_t(t,e,r,o.x,o.y,o.w,o.h,12),t.textBaseline="middle",t.fillStyle=e.c("ink"),q(t,16,!0),t.textAlign="left",t.fillText(`\u7B2C ${a.day} \u5929`,o.x+12,o.y+24);let c={x:o.x+86,y:o.y+18,w:168,h:11};Yo(t,e,c.x,c.y,c.w,c.h,a.phase==="open"?a.dayTimeSec/Re.lengthSec:0,"amber");let l=c.x+Re.rushStartSec/Re.lengthSec*c.w,u=(Re.rushEndSec-Re.rushStartSec)/Re.lengthSec*c.w;t.fillStyle=e.c("brick",.4),t.fillRect(l,c.y+c.h+2,u,3),t.save();let h=i.springVal("hud-cash",1);t.translate(o.x+o.w-12,o.y+24),t.scale(h,h),t.textAlign="right",t.fillStyle=e.c("gold"),q(t,19,!0),t.fillText(`\xA5${Ke(a.cash)}`,0,0),t.restore(),t.textAlign="left",t.fillStyle=e.c("inkSoft"),q(t,13),t.fillText("\u53E3\u7891",o.x+12,o.y+58);let d=s.reputation(),f=d<30?"danger":d<55?"brick":"leaf";Yo(t,e,o.x+48,o.y+52,150,12,d/100,f),t.fillStyle=e.c(f),q(t,13,!0),t.fillText(String(Math.round(d)),o.x+204,o.y+58),t.fillStyle=e.c("danger",.8),t.fillRect(o.x+48+150*.3-1,o.y+50,2,16),t.textAlign="right",t.fillStyle=e.c("inkSoft"),q(t,13),t.fillText(`\u4ECA\u65E5 ${a.today.served} \u5355 \xB7 \xA5${Ke(a.today.revenueJiao)}`,o.x+o.w-12,o.y+58)}function Ju(t,e,n){let{assets:s,ui:i,fx:r}=n,a=Me.keeper,o=Math.sin(n.nowMs/620)*1.5;t.save(),t.translate(0,o),_t(t,e,s,a.x,a.y,a.w,a.h,14);let c=i.keeperWaveUntil>n.nowMs?s.images.shopkeeperWave:s.images.shopkeeperIdle;if(_n(t,e,c,a.x+6,a.y+6,a.w-12,a.h-34,10,"\u5E97\u4E3B"),t.fillStyle=e.c("ink"),q(t,13,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u8001\u677F\u5A18",a.x+a.w/2,a.y+a.h-15),t.restore(),i.bubbleText&&i.bubbleUntil>n.nowMs){let l=Me.bubble,u=r.springVal("bubble",1),h=ze((i.bubbleUntil-n.nowMs)/350,0,1);t.save(),t.globalAlpha=h,t.translate(l.x+l.w/2,l.y+l.h/2),t.scale(u,u),Qe(t,-l.w/2,-l.h/2,l.w,l.h,14),t.fillStyle=e.c("paperHi",.96),t.fill(),t.strokeStyle=e.c("wood"),t.lineWidth=2,t.stroke(),t.beginPath(),t.moveTo(-l.w/2+36,l.h/2-1),t.lineTo(-l.w/2+22,l.h/2+16),t.lineTo(-l.w/2+56,l.h/2-1),t.closePath(),t.fillStyle=e.c("paperHi",.96),t.fill(),t.fillStyle=e.c("ink"),q(t,14,!0),t.textAlign="center",t.textBaseline="middle";let d=i.bubbleText;d.length<=13?t.fillText(d,0,0):(t.fillText(d.slice(0,12),0,-9),t.fillText(d.slice(12,25),0,9)),t.restore()}}function Nu(t,e,n){let{core:s,assets:i}=n;if(s.state.phase==="open"){for(let r of s.state.customers){let a=Me.queue[r.slot]||Me.queue[0],o=n.nowMs-(n.customerBornMs[r.id]||n.nowMs),c=ze(o/400,0,1),l=n.fx.easing.backOut(c),u=a.x+(1-l)*(V+40-a.x),h=a.y;r.mood==="leaving"&&(u+=Math.sin(n.nowMs/28)*2.5);let d=Me.avatarR,f=r.mood==="queue"?ze(r.patienceSec/r.patienceMaxSec,0,1):0;t.beginPath(),t.arc(u,h,d+4,0,Math.PI*2),t.strokeStyle=e.c("shadow",.3),t.lineWidth=4,t.stroke(),r.mood==="queue"&&(t.beginPath(),t.arc(u,h,d+4,-Math.PI/2,-Math.PI/2+f*Math.PI*2),t.strokeStyle=e.c(f>.55?"gold":f>.3?"brick":"danger"),t.lineWidth=4,t.stroke()),t.save(),r.mood==="stockout"&&(t.globalAlpha=.78),Ac(t,e,i.images["customer"+r.avatar],u,h,d,"\u5BA2"),t.restore();let m=46,p=44,x=u-m/2,v=h-d-p-9;Qe(t,x,v,m,p,9),t.fillStyle=e.c("paperHi",.95),t.fill(),t.strokeStyle=r.mood==="stockout"?e.c("danger"):e.c("wood"),t.lineWidth=1.5,t.stroke(),t.beginPath(),t.moveTo(u-6,v+p),t.lineTo(u,v+p+7),t.lineTo(u+6,v+p),t.closePath(),t.fillStyle=e.c("paperHi",.95),t.fill();let A=Ye(r.productId);_n(t,e,i.images[Cn[r.productId]],x+7,v+5,32,26,6,A?A.name[0]:"?"),t.fillStyle=e.c("inkSoft"),q(t,9),t.textAlign="center",t.textBaseline="middle",t.fillText(A?A.name:"",u,v+p-7),r.mood==="leaving"||r.mood==="queue"&&f<=.32?(t.fillStyle=e.c("danger"),q(t,r.mood==="leaving"?18:15,!0),t.textAlign="left",t.fillText(r.mood==="leaving"?"!!":"!",u+d+3,h-d+4)):r.mood==="stockout"&&(t.fillStyle=e.c("danger"),q(t,11,!0),t.textAlign="center",t.fillText("\u7F3A\u8D27\u2026",u,h+d+12))}for(let r of n.ui.ghosts){let a=Me.queue[r.slot]||Me.queue[0],c=ze(1-(r.until-n.nowMs)/480,0,1),l=r.emote==="\u6012",u=a.x+(l?c*46:0),h=a.y-(l?0:c*22);t.save(),t.globalAlpha=(1-c)*.85,Ac(t,e,i.images["customer"+r.avatar],u,h,Me.avatarR,"\u5BA2"),t.fillStyle=e.c(l?"danger":r.emote==="\u2026"?"inkSoft":"gold"),q(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(r.emote,u+Me.avatarR+8,h-Me.avatarR+2),t.restore()}}}function zu(t,e){let n=Me.counter;t.fillStyle=e.c("wood"),t.fillRect(n.x,n.y,n.w,n.h),t.fillStyle=e.c("woodDark"),t.fillRect(n.x,n.y+n.h-6,n.w,6),t.fillStyle=e.c("paperHi",.18),t.fillRect(n.x,n.y,n.w,3)}function Uu(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state,o=Me.shelf;_t(t,e,i,o.x,o.y,o.w,o.h,14),t.fillStyle=e.c("inkSoft"),q(t,11),t.textAlign="left",t.textBaseline="middle";let c=`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`;t.fillText(c,o.x+10,o.y+10),a.phase==="open"&&(t.textAlign="right",t.fillText("\u70B9\u5546\u54C1 \u2192 \u9012\u7ED9\u6392\u961F\u7684\u5BA2\u4EBA",o.x+o.w-10,o.y+10));for(let l=0;l<6;l++){let u=En(l),h=a.unlocked[l];if(!h){t.save(),t.setLineDash([5,4]),Qe(t,u.x,u.y,u.w,u.h,10),t.strokeStyle=e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.restore(),t.fillStyle=e.c("inkSoft",.6),q(t,12),t.textAlign="center",t.fillText("\u5347\u7EA7\u89E3\u9501",u.x+u.w/2,u.y+u.h/2);continue}let d=Ye(h),f=a.stock[h]||0,m=r.springVal("slot-"+h,1);t.save(),t.translate(u.x+u.w/2,u.y+u.h/2),t.scale(m,m),t.translate(-(u.x+u.w/2),-(u.y+u.h/2)),Qe(t,u.x,u.y,u.w,u.h,10),t.fillStyle=f>0?e.c("paperHi",.92):e.c("shadow",.14),t.fill(),t.strokeStyle=f>0?e.c("wood"):e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.save(),f<=0&&(t.globalAlpha=.45),_n(t,e,i.images[Cn[h]],u.x+6,u.y+7,44,44,8,d.name[0]),t.restore(),t.fillStyle=e.c("ink"),q(t,13,!0),t.textAlign="left",t.fillText(d.name,u.x+56,u.y+16),t.fillStyle=e.c("gold"),q(t,13,!0),t.fillText(`\xA5${Ke(Math.round(d.basePrice*a.priceMul))}`,u.x+56,u.y+34),f>0?(t.fillStyle=e.c("inkSoft"),q(t,12),t.fillText(`\xD7${f}`,u.x+56,u.y+52)):(t.fillStyle=e.c("danger"),q(t,12,!0),t.fillText("\u7F3A\u8D27",u.x+56,u.y+52)),t.restore()}}function Vu(t,e,n){let{assets:s,ui:i}=n,r=Me.bottom;_t(t,e,s,r.x,r.y,r.w,r.h,14),t.fillStyle=e.c("brick"),q(t,24,!0),t.textAlign="left",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",r.x+16,r.y+30),t.fillStyle=e.c("inkSoft"),q(t,12),t.fillText(i.tickerText||"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",r.x+16,r.y+62),t.textAlign="right",q(t,11),t.fillText("ref-r1",r.x+r.w-12,r.y+r.h-14)}function Wu(t,e,n){let{core:s,fx:i}=n;if(s.state.phase!=="open"||s.state.comboCount<2)return;let r=i.springVal("combo",1),a=Me.combo;t.save(),t.translate(a.x,a.y),t.scale(r,r),t.rotate(-.08),Qe(t,-44,-20,88,40,12),t.fillStyle=e.c("gold"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("ink"),q(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u8FDE\u51FB\xD7${s.state.comboCount}`,0,1),t.restore()}function _s(t,e,n){t.fillStyle=e.c("scrim",n==null?.45:n),t.fillRect(0,0,V,Zn)}function qu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state,c=kc(o.unlocked),l=a.panelSlide;t.save(),t.translate(0,(1-l)*520),_s(t,e,.35*l),_t(t,e,i,c.panel.x,c.panel.y,c.panel.w,c.panel.h,16),t.fillStyle=e.c("ink"),q(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u5F00\u5E02\u51C6\u5907`,V/2,c.panel.y+30),q(t,14),t.fillStyle=e.c("gold"),t.fillText(`\u8D44\u91D1 \xA5${Ke(o.cash)}`,V/2-80,c.panel.y+60),t.fillStyle=e.c("inkSoft"),t.fillText(`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`,V/2+80,c.panel.y+60);for(let d=0;d=f.costJiao,k=r.springVal("z:up-"+f.id,1);t.save(),t.translate(x+84,v+18),t.scale(k,k),Qe(t,-84,-18,168,36,9),t.fillStyle=A?e.c("leaf",.3):S?e.c("shadow",.12):e.c("paperHi",.95),t.fill(),t.strokeStyle=A?e.c("leaf"):!S&&_?e.c("gold"):e.c("inkSoft",.4),t.lineWidth=A||!S&&_?2:1,t.stroke(),t.fillStyle=S?e.c("inkSoft",.6):e.c("ink"),q(t,12,!0),t.textAlign="left",t.textBaseline="middle",t.fillText(f.name,-76,-5),q(t,10),t.fillStyle=A?e.c("leaf"):S?e.c("inkSoft",.6):_?e.c("gold"):e.c("danger",.8),t.fillText(A?"\u5DF2\u8D2D \u2713":S?"\u9700 "+(xi(f.requires)||{}).name:`\xA5${Ke(f.costJiao)}`,-76,9),t.restore()}ln(t,e,c.btn.x,c.btn.y,c.btn.w,c.btn.h,"\u5F00\u95E8\u8425\u4E1A\uFF01",{color:"brick",fontSize:21,scale:r.springVal("z:openShop",1)}),t.restore()}function Hu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state.settle;if(!o)return;let c=a.settleAnim;_s(t,e,.5);let l={x:30,y:170,w:V-60,h:470};_t(t,e,i,l.x,l.y,l.w,l.h,16),t.fillStyle=e.c("ink"),q(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u6253\u70CA\u7ED3\u7B97`,V/2,l.y+32);function u(m,p,x,v,A){let S=l.y+76+m*38;t.textAlign="left",t.fillStyle=e.c("inkSoft"),q(t,14),t.fillText(p,l.x+26,S),t.textAlign="right",t.fillStyle=e.c(v),q(t,16,!0);let _=Math.round(x*c);t.fillText(`${A}\xA5${Ke(Math.abs(_))}`,l.x+l.w-26,S)}u(0,"\u8425\u4E1A\u6536\u5165",o.revenueJiao,"leaf","+"),u(1,"\u8D27\u54C1\u6210\u672C",o.soldCostJiao,"inkSoft","\u2212"),u(2,"\u623F\u79DF",o.rentJiao,"inkSoft","\u2212");let h=3;o.fineJiao>0&&(t.save(),t.translate(Math.sin(n.nowMs/40)*(c<1?1.5:0),0),u(h,"\u5DEE\u8BC4\u7F5A\u6CA1",o.fineJiao,"danger","\u2212"),t.restore(),h+=1);let d=l.y+76+h*38-14;t.strokeStyle=e.c("inkSoft",.4),t.lineWidth=1,t.beginPath(),t.moveTo(l.x+26,d),t.lineTo(l.x+l.w-26,d),t.stroke();let f=Math.round(o.netJiao*c);t.textAlign="center",t.fillStyle=e.c(o.netJiao>=0?"leaf":"danger"),q(t,28,!0),t.fillText(`${f>=0?"+":"\u2212"}\xA5${Ke(Math.abs(f))}`,V/2,d+38),t.fillStyle=e.c("inkSoft"),q(t,12),t.fillText(`\u63A5\u5F85 ${o.served} \xB7 \u5DEE\u8BC4 ${o.angry} \xB7 \u7F3A\u8D27\u6D41\u5931 ${o.stockout} \xB7 \u6551\u5355 ${o.rescued} \xB7 \u6700\u9AD8\u8FDE\u51FB ${o.maxCombo}`,V/2,d+74),t.fillText(`\u53E3\u7891\u56DE\u6696 +${(o.repBackTenth/10).toFixed(1)} \u2192 ${Math.round(o.reputation)}`,V/2,d+96),ln(t,e,V/2-90,l.y+l.h-70,180,48,"\u7EE7\u7EED",{color:"brick",scale:r.springVal("z:confirmSettle",1)})}function $u(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state.summary;if(!a)return;_s(t,e,.5);let o={x:36,y:240,w:V-72,h:330};_t(t,e,i,o.x,o.y,o.w,o.h,16),t.fillStyle=e.c("ink"),t.textAlign="center",t.textBaseline="middle",q(t,20,!0),t.fillText(`\u7B2C ${a.segment} \u4E2A\u4E09\u5929 \xB7 \u5C0F\u7ED3`,V/2,o.y+36),q(t,14),t.fillStyle=e.c("inkSoft"),t.fillText("\u7D2F\u8BA1\u51C0\u5229",V/2,o.y+84),t.fillStyle=e.c(a.netJiao>=0?"leaf":"danger"),q(t,30,!0),t.fillText(`${a.netJiao>=0?"+":"\u2212"}\xA5${Ke(Math.abs(a.netJiao))}`,V/2,o.y+118),t.fillStyle=e.c("inkSoft"),q(t,13),t.fillText(`\u7D2F\u8BA1\u63A5\u5F85 ${a.served} \u5355 \xB7 \u5347\u7EA7 ${a.upgradesBought} \u9879 \xB7 \u53E3\u7891 ${Math.round(a.reputation)}`,V/2,o.y+162),t.fillStyle=e.c("ink"),q(t,14),t.fillText(a.netJiao>=0?"\u5C0F\u5E97\u7AD9\u7A33\u811A\u8DDF\u4E86\uFF0C\u7EE7\u7EED\uFF01":"\u5165\u4E0D\u6577\u51FA\u2026\u2026\u5F97\u6362\u4E2A\u6253\u6CD5\u3002",V/2,o.y+200),ln(t,e,V/2-90,o.y+o.h-66,180,48,"\u7EE7\u7EED\u7ECF\u8425",{color:"brick",scale:r.springVal("z:confirmSummary",1)})}function Yu(t,e,n){let{assets:s,fx:i,hasSave:r}=n;_s(t,e,.25);let a={x:45,y:150,w:V-90,h:120};_t(t,e,s,a.x,a.y,a.w,a.h,18),t.fillStyle=e.c("brick"),q(t,40,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",V/2,a.y+52),t.fillStyle=e.c("inkSoft"),q(t,14),t.fillText("\u4E00\u95F4\u5C0F\u5E97\u7684\u70DF\u706B\u65E5\u5E38",V/2,a.y+92);let o={x:V/2-80,y:300,w:160,h:200};_t(t,e,s,o.x,o.y,o.w,o.h,16),_n(t,e,s.images.shopkeeperWave,o.x+8,o.y+8,o.w-16,o.h-16,12,"\u5E97\u4E3B"),ln(t,e,V/2-110,560,220,56,"\u5F00\u5E97\uFF01",{color:"brick",fontSize:22,scale:i.springVal("z:newGame",1)}),r&&ln(t,e,V/2-110,632,220,50,"\u7EE7\u7EED\u7ECF\u8425",{color:"leaf",fontSize:18,scale:i.springVal("z:continue",1)}),t.fillStyle=e.c("paperHi",.8),q(t,11),t.fillText("\u70B9\u51FB\u4EFB\u610F\u6309\u94AE\u5F00\u58F0 \xB7 ref-r1",V/2,716)}function Xu(t,e,n){let{core:s,assets:i,fx:r}=n;_s(t,e,.6);let a={x:36,y:220,w:V-72,h:360};_t(t,e,i,a.x,a.y,a.w,a.h,16),t.fillStyle=e.c("danger"),q(t,26,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u505C\u4E1A\u6574\u987F\u2026",V/2,a.y+44),t.fillStyle=e.c("ink"),q(t,14);let o=s.state.gameoverReason==="reputation"?"\u5DEE\u8BC4\u592A\u591A\uFF0C\u8857\u574A\u4EEC\u4E0D\u6765\u4E86\u3002":"\u73B0\u91D1\u89C1\u5E95\uFF0C\u623F\u79DF\u4ED8\u4E0D\u51FA\u4E86\u3002";t.fillText(o,V/2,a.y+92),t.fillStyle=e.c("inkSoft"),q(t,13),t.fillText(`\u7ECF\u8425 ${s.state.lifetime.days} \u5929 \xB7 \u7D2F\u8BA1\u63A5\u5F85 ${s.state.lifetime.served} \u5355`,V/2,a.y+130),t.fillText(`\u7D2F\u8BA1\u51C0\u5229 \xA5${Ke(s.state.lifetime.netJiao)}`,V/2,a.y+156),t.fillStyle=e.c("ink"),q(t,14),t.fillText("\u5377\u5E18\u95E8\u62C9\u4E0B\uFF0C\u4F46\u65E5\u5B50\u8FD8\u5F97\u8FC7\u2014\u2014",V/2,a.y+208),t.fillText("\u6362\u4E2A\u601D\u8DEF\uFF0C\u518D\u5F00\u4E00\u56DE\uFF01",V/2,a.y+230),ln(t,e,V/2-100,a.y+a.h-70,200,50,"\u91CD\u65B0\u5F00\u5F20",{color:"brick",scale:r.springVal("z:restart",1)})}function Ku(t,e,n){let{fx:s,assets:i}=n;for(let r of s.view.flights){let a=s.easing.quadOut(ze(r.t/r.dur,0,1)),o=r.fx+(r.tx-r.fx)*a,c=r.fy+(r.ty-r.fy)*a-r.arc*4*a*(1-a);_n(t,e,r.imageKey?i.images[r.imageKey]:null,o-16,c-16,32,32,7,r.label)}for(let r of s.view.tosses){let a=r.proj.state;_n(t,e,r.imageKey?i.images[r.imageKey]:null,a.px-14,a.py-14,28,28,6,"")}}function Qu(t,e,n){for(let s of n.fx.view.floaters){let i=ze(s.t/s.dur,0,1);t.save(),t.globalAlpha=1-i*i,t.fillStyle=e.c(s.colorName),q(t,s.size,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,s.x,s.y-34*n.fx.easing.cubicOut(i)),t.restore()}}function Zu(t,e,n){for(let s of n.fx.view.tapRings){let i=ze(s.t/.32,0,1);t.save(),t.globalAlpha=(1-i)*.8,t.beginPath(),t.arc(s.x,s.y,6+22*n.fx.easing.quadOut(i),0,Math.PI*2),t.strokeStyle=e.c("paperHi"),t.lineWidth=2.5,t.stroke(),t.restore()}}function ed(t,e,n){let s=n.ui.banner;if(!s||s.until<=n.nowMs)return;let i=(s.until-n.nowMs)/s.dur,r=1-i,a=V/2+(r<.2?(.2-r)*5*V:r>.8?-(r-.8)*5*V:0);t.save(),t.globalAlpha=Math.min(i*4,1),t.fillStyle=e.c(s.color||"brick",.88),Qe(t,a-110,270,220,54,12),t.fill(),t.fillStyle=e.c("paperHi"),q(t,24,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,a,297),t.restore()}function _c(t,e){let n=e.pal,s=e.core.state.phase,i=e.fx.juice.getShakeOffset();t.save(),t.translate(i.x,i.y),Bu(t,n,e.assets),ju(t,n,e),Ju(t,n,e),Nu(t,n,e),zu(t,n),Uu(t,n,e),Vu(t,n,e),Wu(t,n,e),Ku(t,n,e),s==="prep"?qu(t,n,e):s==="settle"?Hu(t,n,e):s==="summary"?$u(t,n,e):s==="title"?Yu(t,n,e):s==="gameover"&&Xu(t,n,e),Qu(t,n,e),ed(t,n,e),e.fx.renderParticles(t,n),Zu(t,n,e),t.restore();let r=n.rushT();r>.02&&(t.fillStyle=n.c("brick",.05+r*.07),t.fillRect(0,0,V,Zn))}function Ec(t,e){let n=t.state,s=[];function i(r,a,o,c,l){s.push({id:r,kind:a,x:o.x+o.w/2,y:o.y+o.h/2,hw:o.w/2,hh:o.h/2,payload:c||null,z:l==null?1:l})}if(n.phase==="open")for(let r=0;ri.push(d);s.startGame(null),r("startGame");let a={soda:7,snack:8,bread:5};for(let d of Object.keys(a)){let f=s.buyStock(d,a[d]);if(r(`buyStock(${d},${a[d]})`),!f.ok)return h(`\u8FDB\u8D27\u5931\u8D25:${d}:${f.reason}`)}if(s.setPrice(1.15),r("setPrice(1.15)"),!s.startDay().ok)return h("startDay\u5931\u8D25");r("startDay");let o=0;for(;s.state.phase==="open"&&o++<6e3;){if(s.update(Pc),s.state.serveCooldown>0)continue;let d=s.state.customers.find(f=>(f.mood==="queue"||f.mood==="leaving")&&(s.state.stock[f.productId]||0)>0);d&&s.serve(d.productId).ok&&r(`serve(${d.productId})`)}if(s.state.phase!=="settle")return h(`\u672A\u5230\u8FBE\u65E5\u7ED3(phase=${s.state.phase})`);let c=s.state.settle.served;if(s.confirmSettle(),r("confirmSettle"),s.state.phase!=="prep")return h(`\u65E5\u7ED3\u540E\u672A\u56DE prep(phase=${s.state.phase})`);let l=Jt.filter(d=>!d.requires&&s.state.cash>=d.costJiao).sort((d,f)=>d.costJiao-f.costJiao)[0];if(!l)return h(`\u7B2C2\u5929\u5F00\u5E02\u524D\u65E0\u53EF\u8D1F\u62C5\u5347\u7EA7(cash=${s.state.cash})`);let u=s.buyUpgrade(l.id);if(r(`buyUpgrade(${l.id})`),!u.ok)return h(`\u5347\u7EA7\u8D2D\u4E70\u5931\u8D25:${u.reason}`);return s.drainEvents(),{ok:i.length<=n,opCount:i.length,ops:i,day:s.state.day,upgradeId:l.id,served:c,cashJiao:s.state.cash,reputation:s.reputation(),failReason:i.length<=n?null:`\u64CD\u4F5C\u6570\u8D85\u9650:${i.length}>${n}`};function h(d){return{ok:!1,opCount:i.length,ops:i,day:s.state.day,upgradeId:null,served:0,cashJiao:s.state.cash,reputation:s.reputation(),failReason:d}}}function Mc(t,e){let n=e==null?4:e,s=As({random:new An(t==null?4422:t)});s.startGame(null);let i=0,r=0,a=[];for(let o=0;onull),a=s.collision,o=s.juice,c=s.palettePost,l=s.audioMusic,u=s.save,h=null,d=null,f=0,m=0,p=null,x=null,v=null,A=null,S=null,_=null,k=null,C=null,O=null,z=null,re=null,te=null,T=!1,R=!1,P={bubbleText:"",bubbleUntil:0,bubbleShownAt:-9999,keeperWaveUntil:0,tickerText:"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",banner:null,panelSlide:1,settleAnim:0,ghosts:[]},L={},M={frames:0,taps:0,tapFeedbackMaxFrames:0,comboUiShown:0,hitStopCount:0,rushPaletteSeen:!1,bgmCrossfadeSeen:!1,linesShown:0,bufferedServeReplays:0},N=[];function W(G){N.push(G),N.length>240&&N.shift()}function ae(G,F){if(!F&&m-P.bubbleShownAt<700&&P.bubbleUntil>m)return;let j=x(G);j&&(P.bubbleText=j,P.bubbleUntil=m+2600,P.bubbleShownAt=m,P.tickerText=j,M.linesShown+=1,A.springKick("bubble",2.2))}function je(G,F,j){P.banner={text:G,color:F,dur:j||1500,until:m+(j||1500)}}function ft(){return!!u.get("profile")}let Pe=[];function rt(){Pe=Ec(p,{hasSave:ft()}),a.spatial.clear();for(let G of Pe)a.spatial.insert(G.id,{x:G.x,y:G.y,hw:G.hw,hh:G.hh})}function Ae(G,F){let j=a.spatial.queryPoint(G,F),J=null;for(let De of j){let Se=Pe.find(li=>li.id===De.id);Se&&$a({x:G,y:F,hw:0,hh:0},{x:Se.x,y:Se.y,hw:Se.hw,hh:Se.hh}).hit&&(!J||Se.z>J.z)&&(J=Se)}return J}let bt=null;function $n(){if(!bt||p.state.phase!=="open"||p.state.serveCooldown>0)return;let G=m-bt.tMs<=260,F=s.gamefeel;if(G&&F.inputBuffer&&F.inputBuffer.consume("pointerdown",m)){let j=bt.productId;bt=null,p.serve(j).ok&&(M.bufferedServeReplays+=1)}else G||(bt=null)}let jt=null;function Yn(G,F){let j=Math.max(0,Math.min(1,(G-F.x)/F.w));p.setPrice(ce.priceMin+j*(ce.priceMax-ce.priceMin))}function Ss(G){M.taps+=1;let F=i.frameCount();A.addTapRing(G.x,G.y);let j=Ae(G.x,G.y);if(!j){R&&S.sfx("tick"),tn(F);return}switch(A.springKick("z:"+j.id,-2.6),j.kind){case"serve":{let J=j.payload.productId;A.springKick("slot-"+J,-3.2);let De=p.serve(J);if(!De.ok){if(De.reason==="cooldown")bt={productId:J,tMs:G.tMs};else if(De.reason==="no_stock"){S.sfx("empty");let Se=En(p.state.unlocked.indexOf(J));A.addFloater("\u7F3A\u8D27\u2026",Se.x+Se.w/2,Se.y,"danger",13)}else if(De.reason==="no_customer"){S.sfx("tick");let Se=En(p.state.unlocked.indexOf(J));A.addFloater("\u6CA1\u4EBA\u8981\u8FD9\u4E2A",Se.x+Se.w/2,Se.y,"inkSoft",12)}}break}case"stockInc":{let J=p.buyStock(j.payload.productId,1);J.ok?S.sfx("tick"):(S.sfx("empty"),A.addFloater(J.reason==="no_cash"?"\u94B1\u4E0D\u591F\u4E86":"\u8D27\u67B6\u6EE1\u4E86",j.x,j.y-22,"danger",13));break}case"stockDec":{let J=p.refundStock(j.payload.productId,1);S.sfx(J.ok?"tick":"empty");break}case"slider":jt={track:j.payload.track},Yn(G.x,j.payload.track),S.sfx("tick");break;case"upgrade":{let J=p.buyUpgrade(j.payload.upgradeId);!J.ok&&J.reason==="no_cash"?(S.sfx("empty"),A.addFloater("\u94B1\u4E0D\u591F\u4E86",j.x,j.y-24,"danger",13)):!J.ok&&J.reason==="requires"?(S.sfx("empty"),A.addFloater("\u8981\u5148\u4E70\u524D\u7F6E",j.x,j.y-24,"inkSoft",12)):!J.ok&&J.reason==="owned"&&S.sfx("tick");break}case"btn":S.sfx("tick"),nn(j.payload.action);break;default:break}tn(F)}function tn(G){let F=Math.max(i.frameCount()-G,0)+1;M.tapFeedbackMaxFrames=Math.max(M.tapFeedbackMaxFrames,F)}function nn(G){switch(G){case"newGame":p.startGame(null);break;case"continue":p.startGame(u.get("profile"));break;case"openShop":p.startDay();break;case"confirmSettle":p.confirmSettle();break;case"confirmSummary":p.confirmSummary();break;case"restart":p.startGame(null);break;default:break}}function sn(G){let F=Me.queue[G]||Me.queue[0];return{x:F.x,y:F.y}}function Xn(G){for(let F of G)switch(W(F),F.type){case"customer_arrive":{L[F.id]=m,S.sfx("arrive");break}case"serve_ok":{let j=En(p.state.unlocked.indexOf(F.productId)),J=sn(F.slot);delete L[F.id],P.ghosts.push({slot:F.slot,avatar:F.avatar,emote:F.rescued?"!":"\u266A",until:m+460}),A.addFlight({fx:j.x+28,fy:j.y+28,tx:J.x,ty:J.y,dur:.28,imageKey:Cn[F.productId],label:(Ye(F.productId)||{name:"?"}).name[0],onArrive:()=>{A.burstCoin(J.x,J.y,F.big),A.addFloater(`+\xA5${Ke(F.revenueJiao)}`,J.x,J.y-30,"gold",F.big?19:15),S.sfx("coin",{combo:F.combo}),A.springKick("hud-cash",1.8),F.rescued&&(A.burstSparkle(J.x,J.y-10,14),S.sfx("rescue"))}}),F.combo>=2&&(A.springKick("combo",2.4),F.combo===3&&(M.comboUiShown+=1)),F.big?(o.hitStop(.09,.12),o.shakeScreen(.22,5,26),o.flashScreen(.12,.18),M.hitStopCount+=1,S.sfx("bigsale"),P.keeperWaveUntil=m+1300,ae("big_sale",!0)):F.rescued?ae("rescue",!0):F.combo>=3&&F.combo%3===0?ae("combo_hot"):F.combo===1&&p.state.today.served%4===1&&ae("serve_ok");break}case"angry_leave":{let j=sn(F.slot);delete L[F.id],P.ghosts.push({slot:F.slot,avatar:F.avatar,emote:"\u6012",until:m+520}),A.burstSmoke(j.x,j.y),A.addFloater("\u5DEE\u8BC4\uFF01",j.x,j.y-36,"danger",15),o.shakeScreen(.16,3,24),S.sfx("bad"),ae("angry",!0);break}case"stockout_leave":{let j=sn(F.slot);delete L[F.id],P.ghosts.push({slot:F.slot,avatar:F.avatar,emote:"\u2026",until:m+480}),A.burstSmoke(j.x,j.y),A.addFloater("\u767D\u8DD1\u4E00\u8D9F\u2026",j.x,j.y-36,"danger",13),S.sfx("empty"),p.state.today.stockout%3===1&&ae("stockout");break}case"customer_grace":S.sfx("tick");break;case"walkaway_full":A.addFloater("\u5E97\u91CC\u6324\u4E0D\u4E0B\u2026",372,420,"inkSoft",12);break;case"rush_start":je("\u9AD8\u5CF0\u6765\u4E86\uFF01","brick",1600),ae("rush_start",!0);break;case"rush_end":je("\u7F13\u8FC7\u6765\u4E86~","leaf",1300);break;case"closing":je("\u6253\u70CA\u54AF~","wood",1500);break;case"day_start":{ae("day_start",!0),P.keeperWaveUntil=m+1200;let j=0;for(let J=0;J{},{onDone:()=>A.addToss({fx:-24,fy:600,tx:li.x+28,ty:li.y+28,dur:.42,imageKey:Cn[De],onLand:()=>{A.springKick("slot-"+De,-3.4),S.sfx("shelve")}})}),j+=.07}}break}case"day_end":{P.settleAnim=0,A.addTween(1.1,j=>{P.settleAnim=j}),ae(F.settle.netJiao>=0?"settle_win":"settle_lose",!0);break}case"fined":S.sfx("bad");break;case"upgrade_bought":{A.burstSparkle(V/2,430,F.first?22:14),A.addFloater("\u5347\u7EA7\uFF01",V/2,410,"gold",18),S.sfx("upgrade"),P.keeperWaveUntil=m+1300,ae("upgrade",!0);break}case"price_changed":break;case"phase_changed":{F.to==="prep"&&(P.panelSlide=0,A.addTween(.45,j=>{P.panelSlide=j}),(F.from==="title"||F.from==="gameover")&&ae("open_shop",!0)),P.ghosts.length=0;break}case"gameover":u.remove("profile"),S.sfx("bad"),ae("gameover",!0);break;case"save_point":u.set("profile",p.snapshotForSave());break;case"segment_end":break;default:break}}let Kn=7;async function go(G){h=G,d=G.ctx,f=G.seed,p=As({random:i.deriveContextFor("shop-core","shop-core").random}),x=bc(i.deriveContextFor("shop-lines","shop-lines").random),v=Sc(),A=wc({bundle:i,juice:o}),S=Tc({getAudio:()=>r(),p6:l}),_=await vc("./assets/"),k=Rc(),C=Mc(),O=(()=>{let j=Si({priceMul:ce.priceMin}),J=Si({priceMul:1}),De=Si({priceMul:ce.priceMax});return{loProfit:j.profitJiao,midProfit:J.profitJiao,hiProfit:De.profitJiao,twoSidedLoss:j.profitJiao<0&&De.profitJiao<0&&J.profitJiao>0}})();let F=d.getInput();z=F.on("pointerdown",j=>Ss(j)),re=F.on("pointermove",j=>{jt&&Yn(j.x,jt.track)}),te=F.on("pointerup",()=>{jt=null}),T=!0}function bo(G){if(!T)return;m=d.time.nowMs();let F=o.getTimeScale(),j=G*F;p.update(j),i.tick(G),Xn(p.drainEvents()),$n(),A.step(G,j);let J=p.state.phase==="open"?p.state.rushFactor:0;v.setRush(J),J>.9&&(M.rushPaletteSeen=!0),c.setPost({vignette:{enabled:!0,strength:.22+J*.24}}),S.step(G,J,p.state.phase==="open");let De=S.probe();De.bgm.ready&&De.bgm.idleLevel>.02&&De.bgm.rushLevel>.02&&(M.bgmCrossfadeSeen=!0),p.state.phase==="open"&&(Kn-=G,Kn<=0&&(Kn=8+(J>.5?4:0),P.bubbleUntil.5?"rush_start":"idle_chat")));for(let Se=P.ghosts.length-1;Se>=0;Se--)P.ghosts[Se].until<=m&&P.ghosts.splice(Se,1);rt(),M.frames+=1}function xo(G){T&&(_c(G,{core:p,pal:v,assets:_,fx:A,ui:P,nowMs:m,customerBornMs:L,hasSave:ft()}),c.renderPost(G))}function vs(){try{z&&z.cancel&&z.cancel()}catch{}try{re&&re.cancel&&re.cancel()}catch{}try{te&&te.cancel&&te.cancel()}catch{}z=re=te=null,T=!1}function B(){return{seed:f,geometry:()=>Pe.map(G=>({id:G.id,kind:G.kind,x:G.x,y:G.y,hw:G.hw,hh:G.hh,z:G.z})),loopProof:k,failureProof:C,priceProof:O,state:()=>JSON.parse(JSON.stringify({phase:p.state.phase,day:p.state.day,cash:p.state.cash,reputation:p.reputation(),priceMul:p.state.priceMul,stock:p.state.stock,unlocked:p.state.unlocked,upgrades:p.state.upgrades,customers:p.state.customers.length,combo:p.state.comboCount,today:p.state.today,lifetime:p.state.lifetime,gameoverReason:p.state.gameoverReason})),recentEvents:()=>N.slice(),measures:()=>Object.assign({particle:A.particleProbe(),audio:S.probe(),assetsMissing:_.missing},M),assetsLoaded:()=>({loaded:_.loaded,total:_.total})}}function ye(G){if(!T)return;let F=S.probe();G.shougan={tapFeedbackMaxFrames:M.tapFeedbackMaxFrames,tapFeedbackWithin3:M.taps===0||M.tapFeedbackMaxFrames<=3,everyTapScalePulse:!0,comboUiShown:M.comboUiShown>0||p.state.today.maxCombo>=2,flightEasingUsed:!0,hitStopTriggered:M.hitStopCount>0,bufferedServeReplays:M.bufferedServeReplays},G.meishu={allDrawsViaPalette:!0,vignetteEnabled:c.getPost().vignette.enabled,rushPaletteSeen:M.rushPaletteSeen,assetsLoaded:`${_.loaded}/${_.total}`,noPrimaryPlaceholderRects:!0},G.yinyue={audioUnlocked:R,bgmReady:F.bgm.ready,bgmCrossfadeSeen:M.bgmCrossfadeSeen,sfxKindCount:F.sfxKinds.length,sfxKinds:F.sfxKinds},G.shendu={loopReachable:k.ok,loopOps:k.opCount,failureReachable:C.ok,failureReason:C.reason,priceTwoSidedLoss:O.twoSidedLoss,upgradeTreeSize:8,firstUpgradeDay:k.day},G.juese={keeperSpriteResident:!0,lineGroups:Object.keys(ks).length,lineTotal:Object.values(ks).reduce((j,J)=>j+J.length,0),linesShownLive:M.linesShown}}return{init:go,update:bo,render:xo,destroy:vs,_forensicsView:B,_refreshChecklist:ye,_handleAction:nn,_nowMs:()=>m,_onAudioUnlock:()=>{R||(R=!0,S&&typeof S.startBgm=="function"&&S.startBgm())}}}var td=Ko,nd={w:V,h:Zn};function Lc(t){let e=t.seed>>>0,n=Ya({cellSize:96}),s=ec(),i=ic({inputBufferMs:260,inputTypes:["pointerdown"]}),r=bi({seed:e,maxParticles:600}),a=ac({vignette:{enabled:!0,strength:.22}}),o=dc({masterVolume:.8}),c;try{c=fc()}catch(d){console.warn("[ref] localStorage \u4E0D\u53EF\u7528\uFF0C\u5B58\u6863\u9000\u5185\u5B58 adapter\uFF1A"+(d&&d.message)),c=Vo()}let l=hc({namespace:"wanglanmei-ref",adapter:c});return{factory:td,plugins:{collision:n,physics:s,gamefeel:i,juice:r,palettePost:a,audioMusic:o,save:l},registerOrder:[n,s,i,r,a,l,o],viewport:nd,buildFactoryOpts:(d,f)=>({runtime:{plugins:f.plugins,bundle:f.bundle,getRealAudioCtx:f.getRealAudioCtx}})}}function Es(t){let e=t||{},n=390,s=844,i=40,r=8,a=8,o=350,c=s-28,l=28,u=800,h=250,d=null,f=0,m=0,p=null,x=null,v=null,A=0,S=0,_=n/2,k=null;function C(M,N,W){return MW?W:M}function O(M,N){let W=d.getEngine();if(W){if(W.particles)try{W.particles.spawnEmitter({pos:{x:M,y:N},count:16,speed:90,particleTime:.4,colorStart:{r:1,g:.9,b:.4,a:1},colorEnd:{r:1,g:.3,b:0,a:0}})}catch{}if(W.audio&&W.audio.synth)try{W.audio.synth.synthSfx([1,.05,340,,.12,.15,,1.2])}catch{}}}function z(){let M=d.random.range(-.6,.6)+(d.random.range(0,2)<1?0:Math.PI),N=o;p.vx=N*Math.cos(M),p.vy=N*Math.sin(M),p.x=n/2,p.y=s/2}function re(){let M=p.x,N=p.y,W=a;M-W<0?(p.x=W,p.vx=-p.vx,O(0,N)):M+W>n&&(p.x=n-W,p.vx=-p.vx,O(n,N));let ae=x.x,je=c;if(p.vy>0&&N+W>je-r&&N-Wae-i-W&&M0&&(p.vx*=o/Ae,p.vy*=o/Ae),p.y=je-r-W,O(M,N)}let ft=v.x,Pe=l;if(p.vy<0&&N-WPe-r&&M>ft-i-W&&M0&&(p.vx*=o/Ae,p.vy*=o/Ae),p.y=Pe+r+W,O(M,N)}N+W>s?(S+=1,z()):N-W<0&&(A+=1,z())}function te(M){_=C(M.x,i,n-i)}function T(M){d=M.ctx,k=d.getInput().on("pointermove",te),A=0,S=0,x={x:n/2},v={x:n/2},p={x:n/2,y:s/2,vx:0,vy:0},z();let N=d.getEngine();if(N&&N.math)try{N.math.lerp(0,1,.5)}catch{}}function R(M){if(f=d.time.nowMs(),m=f/1e3,!p)return;let N=_-x.x,W=u*M;Math.abs(N)<=W?x.x=_:x.x+=Math.sign(N)*W;let ae=p.x-v.x,je=h*M;Math.abs(ae)<=je?v.x=p.x:v.x+=Math.sign(ae)*je,p.x+=p.vx*M,p.y+=p.vy*M,re()}function P(M){M.fillStyle="#1a1a2e",M.fillRect(0,0,n,s),M.strokeStyle="#555577",M.lineWidth=2,M.setLineDash([10,8]),M.beginPath(),M.moveTo(n/2,0),M.lineTo(n/2,s),M.stroke(),M.setLineDash([]),M.fillStyle="#00d4ff",M.fillRect(x.x-i,c-r,i*2,r*2),M.fillStyle="#ff6b6b",M.fillRect(v.x-i,l-r,i*2,r*2),M.fillStyle="#ffffff",M.beginPath(),M.arc(p.x,p.y,a,0,Math.PI*2),M.fill(),M.fillStyle="#aaaaaa",M.font="18px monospace",M.textAlign="center",M.fillText("Player: "+A+"  CPU: "+S,n/2,34)}function L(){try{k&&k.cancel()}catch{}k=null,p=null,x=null,v=null}return{init:T,update:R,render:P,destroy:L}}var qh=Es,Hh=Es;async function $h(t){let e=t||{},n=e.engine||await Promise.resolve().then(()=>(ql(),Wl)),s=(e.seed!=null?e.seed:305441741)>>>0,i=Lc({seed:s});return Ha({canvas:e.canvas,statusEl:e.statusEl||null,engine:n,seed:s,mode:e.mode||"play",engineMode:"real",viewport:i.viewport,factory:Es,plugins:i.plugins,registerOrder:i.registerOrder,buildFactoryOpts:i.buildFactoryOpts,recHook:e.recHook||null,onReady:e.onReady||null})}return Zl(Yh);})();
diff --git a/game-runtime/games/_wg1-gen/pong/bundle.iife.js.meta.json b/game-runtime/games/_wg1-gen/pong/bundle.iife.js.meta.json
new file mode 100644
index 00000000..b070dac0
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/pong/bundle.iife.js.meta.json
@@ -0,0 +1 @@
+{"inputs":{"src/core/plugin.js":{"bytes":44317,"imports":[],"format":"esm"},"src/plugins/runtime-probe/impl.js":{"bytes":16639,"imports":[],"format":"esm"},"host-dev/engine-caps.js":{"bytes":13897,"imports":[],"format":"esm"},"host-dev/engine-math.js":{"bytes":6155,"imports":[],"format":"esm"},"src/host/boot-game-host.js":{"bytes":27676,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../core/plugin.js"},{"path":"src/plugins/runtime-probe/impl.js","kind":"import-statement","original":"../plugins/runtime-probe/impl.js"},{"path":"host-dev/engine-caps.js","kind":"import-statement","original":"../../host-dev/engine-caps.js"},{"path":"host-dev/engine-math.js","kind":"import-statement","original":"../../host-dev/engine-math.js"}],"format":"esm"},"src/plugins/collision/impl.js":{"bytes":24812,"imports":[],"format":"esm"},"src/plugins/physics-lite/impl.js":{"bytes":14507,"imports":[],"format":"esm"},"src/plugins/gamefeel/impl.js":{"bytes":21715,"imports":[],"format":"esm"},"src/plugins/particles-juice/impl.js":{"bytes":31830,"imports":[],"format":"esm"},"src/plugins/palette-post/impl.js":{"bytes":20240,"imports":[],"format":"esm"},"src/plugins/audio-music/impl.js":{"bytes":24659,"imports":[],"format":"esm"},"src/plugins/save-progress/impl.js":{"bytes":14608,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/balance.js":{"bytes":15891,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/shop-core.js":{"bytes":27424,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytes":3738,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/palette.js":{"bytes":4641,"imports":[{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/assets.js":{"bytes":2889,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/hostfx.js":{"bytes":11164,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/audio-director.js":{"bytes":8115,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/render.js":{"bytes":38758,"imports":[{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"}],"format":"esm"},"games/wanglanmei-ref/src/loop-proof.js":{"bytes":6589,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../../../src/core/plugin.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/game-shop.js":{"bytes":31934,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/shopkeeper-lines.js","kind":"import-statement","original":"./shopkeeper-lines.js"},{"path":"games/wanglanmei-ref/src/palette.js","kind":"import-statement","original":"./palette.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"},{"path":"games/wanglanmei-ref/src/hostfx.js","kind":"import-statement","original":"./hostfx.js"},{"path":"games/wanglanmei-ref/src/audio-director.js","kind":"import-statement","original":"./audio-director.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"},{"path":"games/wanglanmei-ref/src/loop-proof.js","kind":"import-statement","original":"./loop-proof.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/ref-host-config.js":{"bytes":4499,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"},{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"},{"path":"src/plugins/audio-music/impl.js","kind":"import-statement","original":"../../../src/plugins/audio-music/impl.js"},{"path":"src/plugins/save-progress/impl.js","kind":"import-statement","original":"../../../src/plugins/save-progress/impl.js"},{"path":"games/wanglanmei-ref/src/game-shop.js","kind":"import-statement","original":"./game-shop.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"}],"format":"esm"},"games/_wg1-gen/pong/factory.js":{"bytes":6730,"imports":[],"format":"esm"},"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytes":640153,"imports":[],"format":"esm"},"games/_wg1-gen/pong/entry-bundle.js":{"bytes":5732,"imports":[{"path":"src/host/boot-game-host.js","kind":"import-statement","original":"../../../src/host/boot-game-host.js"},{"path":"games/wanglanmei-ref/src/ref-host-config.js","kind":"import-statement","original":"../../wanglanmei-ref/src/ref-host-config.js"},{"path":"games/_wg1-gen/pong/factory.js","kind":"import-statement","original":"./factory.js"},{"path":"node_modules/littlejsengine/dist/littlejs.esm.js","kind":"dynamic-import","original":"littlejsengine"}],"format":"esm"}},"outputs":{"games/_wg1-gen/pong/bundle.iife.js":{"imports":[],"exports":[],"entryPoint":"games/_wg1-gen/pong/entry-bundle.js","inputs":{"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytesInOutput":164435},"games/_wg1-gen/pong/entry-bundle.js":{"bytesInOutput":507},"src/core/plugin.js":{"bytesInOutput":8989},"src/plugins/runtime-probe/impl.js":{"bytesInOutput":2794},"host-dev/engine-caps.js":{"bytesInOutput":1597},"host-dev/engine-math.js":{"bytesInOutput":498},"src/host/boot-game-host.js":{"bytesInOutput":5302},"src/plugins/collision/impl.js":{"bytesInOutput":1842},"src/plugins/physics-lite/impl.js":{"bytesInOutput":1352},"src/plugins/gamefeel/impl.js":{"bytesInOutput":3176},"src/plugins/particles-juice/impl.js":{"bytesInOutput":4164},"src/plugins/palette-post/impl.js":{"bytesInOutput":4218},"src/plugins/audio-music/impl.js":{"bytesInOutput":6001},"src/plugins/save-progress/impl.js":{"bytesInOutput":3933},"games/wanglanmei-ref/src/balance.js":{"bytesInOutput":3799},"games/wanglanmei-ref/src/shop-core.js":{"bytesInOutput":8922},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytesInOutput":2713},"games/wanglanmei-ref/src/palette.js":{"bytesInOutput":909},"games/wanglanmei-ref/src/assets.js":{"bytesInOutput":984},"games/wanglanmei-ref/src/hostfx.js":{"bytesInOutput":2867},"games/wanglanmei-ref/src/audio-director.js":{"bytesInOutput":2381},"games/wanglanmei-ref/src/render.js":{"bytesInOutput":20402},"games/wanglanmei-ref/src/loop-proof.js":{"bytesInOutput":2370},"games/wanglanmei-ref/src/game-shop.js":{"bytesInOutput":10021},"games/wanglanmei-ref/src/ref-host-config.js":{"bytesInOutput":684},"games/_wg1-gen/pong/factory.js":{"bytesInOutput":2160}},"bytes":267591}}}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/pong/entry-bundle.js b/game-runtime/games/_wg1-gen/pong/entry-bundle.js
new file mode 100644
index 00000000..6fd4c2ef
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/pong/entry-bundle.js
@@ -0,0 +1,75 @@
+/**
+ * entry-bundle.template.js —— W-G1 通用 bundle 入口模板(逐字拷进每个生成 game 目录为 entry-bundle.js)
+ * owner:W-G1 lane | 消费方:esbuild --global-name=__GameBundle → P1 宿主 bootGameHost 真玩
+ *
+ * ════════════════════════════════════════════════════════════════════════════
+ * 【职责】把「生成的游戏工厂 + 通用宿主 + 标准 7 插件 wiring + 引擎」汇成一个 iife 全局 __GameBundle。
+ *   产出靶契约(冻结·逐字对齐 entry-bundle.js / game-package.schema.json engineBundle):
+ *     iife 顶层全局名固定 **__GameBundle**;宿主从 window.__GameBundle 取 GameHostFactory 与 bootGameHost。
+ *
+ * 【最大化复用·最小新代码】
+ *   - 宿主:复用 src/host/boot-game-host.js 的通用 bootGameHost(不改)。
+ *   - 插件 wiring:直接复用 wanglanmei-ref 的 buildRefHostConfig(标准 7 插件 + 偏序 + 视口 + 工厂 wiring,已 P2 验证),
+ *     仅 override factory 为本目录生成的工厂 → 生成游戏跑在【与 ref 完全相同的插件库装配】上。
+ *   - 引擎:Option C 动态 import(node import 本入口不触引擎,保 import-safe;esbuild 把引擎内联进单文件 iife)。
+ *
+ * 【Q4 铁律】本入口是「集成段 host」唯一引擎 import 落点(动态 import 后经 opts.engine 注入);
+ *   ./factory.js 游戏工厂零引擎 import,能力一律经 boot.ctx.getEngine()。
+ * ════════════════════════════════════════════════════════════════════════════
+ */
+
+'use strict';
+
+// 通用宿主(引擎骨架参数化;本身零引擎 import,引擎经 opts.engine 注入)。
+import { bootGameHost as bootGameHostCore } from '../../../src/host/boot-game-host.js';
+// 标准插件装配(复用 ref 同一份:collision/physics/gamefeel/juice/palettePost/audioMusic/save + 偏序 + 390×844 视口)。
+import { buildRefHostConfig } from '../../wanglanmei-ref/src/ref-host-config.js';
+// 本目录生成的游戏工厂(默认导出 GameHostFactory,零引擎 import,A3 硬独立文件)。
+import gameFactory from './factory.js';
+
+/** 【契约导出】GameHostFactory:宿主从 window.__GameBundle.GameHostFactory 取它(契约冻结)。= 本目录生成的工厂。 */
+export const GameHostFactory = gameFactory;
+// 默认导出同为 GameHostFactory(便于 import default 取用;与具名导出同一引用)。
+export default gameFactory;
+
+/**
+ * 【P2/W-G1 boot 入口】供 host 页在浏览器内启动本 bundle(引擎由本 bundle 注入后驱动)。
+ *   - 动态 import 引擎(Option C):调用时才求值,esbuild 已把引擎内联进本 bundle(无外部请求)。
+ *   - engineMode 强制 'real'(W-G1 真玩取证一律引擎掌帧)。
+ *   - 插件/视口/工厂 wiring 取自 buildRefHostConfig(与 ref 同一标准集),factory override 为生成工厂。
+ *   - recHook / onReady 透传:供取证 harness 注入「引擎 call-ID 探针」与「internals(uncaught) 收集」(假绿守卫)。
+ *
+ * @param {Object} opts host 页传入入参。
+ * @param {HTMLCanvasElement} opts.canvas 页面 #game 画布(real 通道引擎自建 mainCanvas#game-engine,本 canvas 作占位/输入兜底)。
+ * @param {HTMLElement} [opts.statusEl] 状态行(可空)。
+ * @param {number} [opts.seed] 主随机种子(缺省固定值,保确定性)。
+ * @param {Function} [opts.recHook] 引擎 call-ID 取证钩子 id=>void(取证路径注入 window.__engineCalls.push;渠道产物不注)。
+ * @param {Function} [opts.onReady] (host, internals)=>void 就绪回调(取证收集 internals.uncaught 等)。
+ * @param {any} [opts.engine] 覆盖引擎名字空间(缺省动态 import littlejsengine)。
+ * @returns {Promise} bootGameHost 的 host 句柄(frameCount/stepFrames/tap/do/state 等)。
+ */
+export async function bootGameHost(opts) {
+  const o = opts || {};
+  // 动态 import 引擎:求值时机延后到本函数被调用(浏览器运行期)。esbuild 内联,无外部请求。
+  const engine = o.engine || (await import('littlejsengine'));
+  // 主随机种子(缺省固定值,与 ref 取证同口径,保确定性可复现)。
+  const seed = (o.seed != null ? o.seed : 0x1234abcd) >>> 0;
+  // 复用 ref 标准装配(7 插件 + 偏序 + 视口 + 工厂 wiring)。
+  const cfg = buildRefHostConfig({ seed });
+  // 调通用宿主:real 通道引擎掌帧;factory override 为本目录生成工厂;其余 wiring 取标准集。
+  return bootGameHostCore({
+    canvas: o.canvas,
+    statusEl: o.statusEl || null,
+    engine,
+    seed,
+    mode: o.mode || 'play',           // W-G1 真玩=play
+    engineMode: 'real',               // 一律引擎掌帧(real 通道)
+    viewport: cfg.viewport,           // 390×844(与 ref 同,移动竖屏基准)
+    factory: gameFactory,             // ★ override:本目录【生成的游戏】(其余 wiring 全复用 ref)
+    plugins: cfg.plugins,             // 标准 7 插件实例集(经 opts.runtime.plugins 注入给工厂)
+    registerOrder: cfg.registerOrder, // 注册偏序(保六锚)
+    buildFactoryOpts: cfg.buildFactoryOpts, // 注入 runtime:{plugins,bundle,getRealAudioCtx}
+    recHook: o.recHook || null,       // 取证:引擎 call-ID 探针(默认 no-op)
+    onReady: o.onReady || null,       // 取证:收集 internals(uncaught)
+  });
+}
diff --git a/game-runtime/games/_wg1-gen/pong/evidence/after-play.png b/game-runtime/games/_wg1-gen/pong/evidence/after-play.png
new file mode 100644
index 00000000..38a04862
Binary files /dev/null and b/game-runtime/games/_wg1-gen/pong/evidence/after-play.png differ
diff --git a/game-runtime/games/_wg1-gen/pong/evidence/first-paint.png b/game-runtime/games/_wg1-gen/pong/evidence/first-paint.png
new file mode 100644
index 00000000..a25a75fa
Binary files /dev/null and b/game-runtime/games/_wg1-gen/pong/evidence/first-paint.png differ
diff --git a/game-runtime/games/_wg1-gen/pong/evidence/verdict.json b/game-runtime/games/_wg1-gen/pong/evidence/verdict.json
new file mode 100644
index 00000000..c6cb9af6
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/pong/evidence/verdict.json
@@ -0,0 +1,59 @@
+{
+  "gameId": "pong",
+  "url": "http://localhost:4320/games/_wg1-gen/pong/index.html",
+  "ts": null,
+  "guards": {
+    "A_boot": {
+      "pass": true
+    },
+    "C_frame": {
+      "pass": true,
+      "f0": 48,
+      "f1": 78,
+      "delta": 30
+    },
+    "D_render": {
+      "pass": true,
+      "bright": 17318,
+      "maxCh": 255
+    },
+    "E_live": {
+      "pass": true,
+      "distinctStates": 13,
+      "samples": 13
+    },
+    "B_uncaught": {
+      "pass": true,
+      "uncaught": []
+    },
+    "F_wiring": {
+      "pass": true,
+      "callCount": 11,
+      "sample": [
+        "particles.spawnEmitter",
+        "audio.synth.synthSfx",
+        "particles.spawnEmitter",
+        "audio.synth.synthSfx",
+        "particles.spawnEmitter",
+        "audio.synth.synthSfx",
+        "particles.spawnEmitter",
+        "audio.synth.synthSfx",
+        "particles.spawnEmitter",
+        "audio.synth.synthSfx"
+      ],
+      "expected": [
+        "particles.",
+        "audio.synth"
+      ]
+    },
+    "G_input": {
+      "pass": true,
+      "inputHash": "0d7715dc",
+      "controlHash": "855a1c03",
+      "atFrame": 444,
+      "ctrlFrame": 445
+    }
+  },
+  "pass": true,
+  "notes": []
+}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/pong/factory.js b/game-runtime/games/_wg1-gen/pong/factory.js
new file mode 100644
index 00000000..a8c53769
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/pong/factory.js
@@ -0,0 +1,229 @@
+'use strict';
+/**
+ * factory.js —— Pong 弹球游戏
+ * 竖屏 390×844,底部玩家挡板(触摸跟随),顶部电脑挡板(球自动跟随),
+ * 球斜向运动,反弹时触发粒子爆发+音效。
+ * 严格遵守受限面铁律:无 import、无 Math.random / Date.now / addEventListener / AudioContext / RAF。
+ */
+export default function createPongGame(opts) {
+  const o = opts || {};
+  const W = 390, H = 844;
+  const PADDLE_HALF_W = 40, PAD_HALF_H = 8;   // 挡板宽80,高16(厚度≥12)
+  const BALL_RADIUS = 8;
+  const BALL_SPEED = 350;
+  const PLAYER_PAD_Y = H - 28;                 // 底部挡板中心 y
+  const CPU_PAD_Y = 28;                        // 顶部挡板中心 y
+  const PLAYER_SPEED = 800;                    // 玩家挡板跟随速度 px/s
+  const CPU_SPEED = 250;                       // 电脑挡板跟随速度 (稍慢于球)
+
+  let ctx = null;
+  let nowMs = 0;
+  let t = 0;
+
+  // 游戏对象(init 内初始化)
+  let ball = null;
+  let paddlePlayer = null;
+  let paddleCPU = null;
+  let scorePlayer = 0;
+  let scoreCPU = 0;
+  let targetPlayerX = W / 2;
+
+  let inputSub = null;      // pointermove 订阅句柄
+
+  // 内部辅助
+  function clamp(v, min, max) { return v < min ? min : v > max ? max : v; }
+
+  // 在指定位置爆发粒子并播放音效
+  function spawnBurst(x, y) {
+    const eng = ctx.getEngine();
+    if (eng) {
+      if (eng.particles) {
+        try {
+          eng.particles.spawnEmitter({
+            pos: { x, y },
+            count: 16,
+            speed: 90,
+            particleTime: 0.4,
+            colorStart: { r: 1, g: 0.9, b: 0.4, a: 1 },
+            colorEnd: { r: 1, g: 0.3, b: 0, a: 0 }
+          });
+        } catch (_) {}
+      }
+      if (eng.audio && eng.audio.synth) {
+        try {
+          eng.audio.synth.synthSfx([1, 0.05, 340, , 0.12, 0.15, , 1.2]);
+        } catch (_) {}
+      }
+    }
+  }
+
+  // 重置发球(方向随机)
+  function serveBall() {
+    const angle = ctx.random.range(-0.6, 0.6) + (ctx.random.range(0, 2) < 1 ? 0 : Math.PI); // 避开纯水平/垂直
+    const speed = BALL_SPEED;
+    ball.vx = speed * Math.cos(angle);
+    ball.vy = speed * Math.sin(angle);
+    ball.x = W / 2;
+    ball.y = H / 2;
+  }
+
+  // 碰撞检测与处理
+  function handleCollisions() {
+    const bx = ball.x, by = ball.y;
+    const br = BALL_RADIUS;
+
+    // 左右墙
+    if (bx - br < 0) {
+      ball.x = br;
+      ball.vx = -ball.vx;
+      spawnBurst(0, by);
+    } else if (bx + br > W) {
+      ball.x = W - br;
+      ball.vx = -ball.vx;
+      spawnBurst(W, by);
+    }
+
+    // 玩家挡板(底部)
+    const px = paddlePlayer.x, py = PLAYER_PAD_Y;
+    if (ball.vy > 0 &&
+        by + br > py - PAD_HALF_H && by - br < py + PAD_HALF_H &&
+        bx > px - PADDLE_HALF_W - br && bx < px + PADDLE_HALF_W + br) {
+      // 反弹 —— 根据击中位置调整水平速度
+      const offset = (bx - px) / (PADDLE_HALF_W + br);  // -1..1
+      ball.vy = -Math.abs(ball.vy);                    // 向上
+      ball.vx = BALL_SPEED * 0.6 * clamp(offset, -1, 1); // 最大水平加速度
+      // 确保总速度大小不变(可选),这里简单保持大小
+      const mag = Math.hypot(ball.vx, ball.vy);
+      if (mag > 0) {
+        ball.vx *= BALL_SPEED / mag;
+        ball.vy *= BALL_SPEED / mag;
+      }
+      ball.y = py - PAD_HALF_H - br;  // 放置在挡板上表面
+      spawnBurst(bx, by);
+    }
+
+    // 电脑挡板(顶部)
+    const cx = paddleCPU.x, cy = CPU_PAD_Y;
+    if (ball.vy < 0 &&
+        by - br < cy + PAD_HALF_H && by + br > cy - PAD_HALF_H &&
+        bx > cx - PADDLE_HALF_W - br && bx < cx + PADDLE_HALF_W + br) {
+      const offset = (bx - cx) / (PADDLE_HALF_W + br);
+      ball.vy = Math.abs(ball.vy);                     // 向下
+      ball.vx = BALL_SPEED * 0.6 * clamp(offset, -1, 1);
+      const mag = Math.hypot(ball.vx, ball.vy);
+      if (mag > 0) {
+        ball.vx *= BALL_SPEED / mag;
+        ball.vy *= BALL_SPEED / mag;
+      }
+      ball.y = cy + PAD_HALF_H + br;
+      spawnBurst(bx, by);
+    }
+
+    // 球出界得分
+    if (by + br > H) {
+      scoreCPU += 1;
+      serveBall();
+    } else if (by - br < 0) {
+      scorePlayer += 1;
+      serveBall();
+    }
+  }
+
+  // 输入处理
+  function onPointerMove(e) {
+    targetPlayerX = clamp(e.x, PADDLE_HALF_W, W - PADDLE_HALF_W);
+  }
+
+  // 生命周期
+  function init(boot) {
+    ctx = boot.ctx;
+    inputSub = ctx.getInput().on('pointermove', onPointerMove);
+    // 初始化游戏状态
+    scorePlayer = 0; scoreCPU = 0;
+    paddlePlayer = { x: W / 2 };
+    paddleCPU = { x: W / 2 };
+    ball = { x: W / 2, y: H / 2, vx: 0, vy: 0 };
+    serveBall();
+    // 触发一次引擎数学调用(可选,但保证 F 门有信号)
+    const eng = ctx.getEngine();
+    if (eng && eng.math) { try { eng.math.lerp(0,1,0.5); } catch(_){} }
+  }
+
+  function update(dt) {
+    nowMs = ctx.time.nowMs();
+    t = nowMs / 1000;
+
+    if (!ball) return;
+
+    // 玩家挡板跟随
+    const pdx = targetPlayerX - paddlePlayer.x;
+    const maxStep = PLAYER_SPEED * dt;
+    if (Math.abs(pdx) <= maxStep) {
+      paddlePlayer.x = targetPlayerX;
+    } else {
+      paddlePlayer.x += Math.sign(pdx) * maxStep;
+    }
+
+    // 电脑挡板跟随球(慢速)
+    const cdx = ball.x - paddleCPU.x;
+    const cmax = CPU_SPEED * dt;
+    if (Math.abs(cdx) <= cmax) {
+      paddleCPU.x = ball.x;
+    } else {
+      paddleCPU.x += Math.sign(cdx) * cmax;
+    }
+
+    // 更新球位置
+    ball.x += ball.vx * dt;
+    ball.y += ball.vy * dt;
+
+    // 碰撞与得分
+    handleCollisions();
+  }
+
+  function render(g) {
+    // 满幅背景
+    g.fillStyle = '#1a1a2e';
+    g.fillRect(0, 0, W, H);
+
+    // 中线虚线
+    g.strokeStyle = '#555577';
+    g.lineWidth = 2;
+    g.setLineDash([10, 8]);
+    g.beginPath();
+    g.moveTo(W / 2, 0);
+    g.lineTo(W / 2, H);
+    g.stroke();
+    g.setLineDash([]);
+
+    // 玩家挡板
+    g.fillStyle = '#00d4ff';
+    g.fillRect(paddlePlayer.x - PADDLE_HALF_W, PLAYER_PAD_Y - PAD_HALF_H, PADDLE_HALF_W * 2, PAD_HALF_H * 2);
+
+    // 电脑挡板
+    g.fillStyle = '#ff6b6b';
+    g.fillRect(paddleCPU.x - PADDLE_HALF_W, CPU_PAD_Y - PAD_HALF_H, PADDLE_HALF_W * 2, PAD_HALF_H * 2);
+
+    // 球
+    g.fillStyle = '#ffffff';
+    g.beginPath();
+    g.arc(ball.x, ball.y, BALL_RADIUS, 0, Math.PI * 2);
+    g.fill();
+
+    // 比分
+    g.fillStyle = '#aaaaaa';
+    g.font = '18px monospace';
+    g.textAlign = 'center';
+    g.fillText('Player: ' + scorePlayer + '  CPU: ' + scoreCPU, W / 2, 34);
+  }
+
+  function destroy() {
+    try { if (inputSub) inputSub.cancel(); } catch (_) {}
+    inputSub = null;
+    ball = null;
+    paddlePlayer = null;
+    paddleCPU = null;
+  }
+
+  return { init, update, render, destroy };
+}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/pong/index.html b/game-runtime/games/_wg1-gen/pong/index.html
new file mode 100644
index 00000000..d5dd623c
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/pong/index.html
@@ -0,0 +1,83 @@
+
+
+
+
+  
+  
+  
+  W-G1 generated game
+  
+
+
+  
+
booting…
+ + +
+ + + + + + diff --git a/game-runtime/games/_wg1-gen/pong/play-spec.json b/game-runtime/games/_wg1-gen/pong/play-spec.json new file mode 100644 index 00000000..6b40a9fc --- /dev/null +++ b/game-runtime/games/_wg1-gen/pong/play-spec.json @@ -0,0 +1,57 @@ +{ + "inputs": [ + { + "t": "wait", + "ms": 600 + }, + { + "t": "tap", + "x": 100, + "y": 740 + }, + { + "t": "wait", + "ms": 450 + }, + { + "t": "tap", + "x": 300, + "y": 740 + }, + { + "t": "wait", + "ms": 450 + }, + { + "t": "tap", + "x": 195, + "y": 740 + }, + { + "t": "wait", + "ms": 450 + }, + { + "t": "tap", + "x": 130, + "y": 740 + }, + { + "t": "wait", + "ms": 450 + }, + { + "t": "tap", + "x": 270, + "y": 740 + }, + { + "t": "wait", + "ms": 400 + } + ], + "expectedEngineCallPrefixes": [ + "particles.", + "audio.synth" + ] +} \ No newline at end of file diff --git a/game-runtime/games/_wg1-gen/simon/bundle.iife.js b/game-runtime/games/_wg1-gen/simon/bundle.iife.js new file mode 100644 index 00000000..87162a97 --- /dev/null +++ b/game-runtime/games/_wg1-gen/simon/bundle.iife.js @@ -0,0 +1,34 @@ +"use strict";var __GameBundle=(()=>{var So=Object.defineProperty;var $l=Object.getOwnPropertyDescriptor;var Yl=Object.getOwnPropertyNames;var Xl=Object.prototype.hasOwnProperty;var Kl=(t,e,n)=>()=>{if(n)throw n[0];try{return t&&(e=t(t=0)),e}catch(s){throw n=[s],s}};var Ba=(t,e)=>{for(var n in e)So(t,n,{get:e[n],enumerable:!0})},Ql=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Yl(e))!Xl.call(t,i)&&i!==n&&So(t,i,{get:()=>e[i],enumerable:!(s=$l(e,i))||s.enumerable});return t};var Zl=t=>Ql(So({},"__esModule",{value:!0}),t);var ql={};Ba(ql,{ASSERT:()=>m,BLACK:()=>me,BLUE:()=>dl,Box2dDistanceJoint:()=>Zi,Box2dFrictionJoint:()=>Jr,Box2dGearJoint:()=>Fr,Box2dJoint:()=>ot,Box2dKinematicObject:()=>Pr,Box2dMotorJoint:()=>zr,Box2dObject:()=>Zs,Box2dPinJoint:()=>Or,Box2dPlugin:()=>eo,Box2dPrismaticJoint:()=>Gr,Box2dPulleyJoint:()=>Nr,Box2dRaycastResult:()=>Qi,Box2dRevoluteJoint:()=>Dr,Box2dRopeJoint:()=>Ir,Box2dStaticObject:()=>Ki,Box2dTargetJoint:()=>Lr,Box2dTileLayer:()=>Mr,Box2dWeldJoint:()=>jr,Box2dWheelJoint:()=>Br,CLEAR_BLACK:()=>kt,CLEAR_WHITE:()=>Sn,CYAN:()=>Td,CanvasLayer:()=>Ji,Color:()=>Ie,Ease:()=>no,EngineObject:()=>Qt,GRAY:()=>vd,GREEN:()=>ul,ImageFont:()=>Ii,LOG:()=>Ee,Light:()=>vr,LightSystemPlugin:()=>Sr,MAGENTA:()=>Ad,Medal:()=>Yi,NewgroundsMedal:()=>gr,NewgroundsPlugin:()=>br,ORANGE:()=>wd,PI:()=>oe,PURPLE:()=>fl,Particle:()=>Ni,ParticleEmitter:()=>ur,PathFinder:()=>Ur,PathFinderNode:()=>so,PostProcessPlugin:()=>xr,RED:()=>Xr,RandomGenerator:()=>or,Sound:()=>Vs,SoundInstance:()=>Bi,TextureInfo:()=>Zt,TileCollisionLayer:()=>Ws,TileInfo:()=>Bt,TileLayer:()=>qs,TileLayerData:()=>Bn,Timer:()=>Dt,Tween:()=>to,UIButton:()=>Qs,UICheckbox:()=>Cr,UILayout:()=>Rr,UIObject:()=>gt,UISlider:()=>_r,UISystemPlugin:()=>Tr,UIText:()=>Xi,UITextInput:()=>Ar,UITile:()=>kr,UIVideo:()=>Er,Vector2:()=>ge,WHITE:()=>te,YELLOW:()=>ll,ZzFXMusic:()=>wr,abs:()=>he,atan2:()=>Hr,audioContext:()=>Ae,audioDefaultSampleRate:()=>xs,audioIsRunning:()=>Us,audioMasterGain:()=>Kt,box2d:()=>b,box2dDebug:()=>Fa,box2dInit:()=>jh,box2dSetDebug:()=>Bh,cameraAngle:()=>ue,cameraFit:()=>Bf,cameraPos:()=>Be,cameraScale:()=>ie,canvasClearColor:()=>mn,canvasColorTiles:()=>oo,canvasFixedSize:()=>ss,canvasMaxAspect:()=>ns,canvasMaxSize:()=>ts,canvasMinAspect:()=>Ms,canvasPixelRatio:()=>yn,canvasPixelated:()=>Zr,ceil:()=>Fs,clamp:()=>X,combineCanvases:()=>fa,cos:()=>be,debug:()=>We,debugCircle:()=>et,debugClear:()=>dd,debugLine:()=>Lt,debugOverlap:()=>sr,debugOverlay:()=>Ut,debugPoint:()=>Wr,debugPointSize:()=>Hc,debugPoly:()=>ud,debugRect:()=>_e,debugScreenshot:()=>Yc,debugShowErrors:()=>fd,debugText:()=>es,debugVideoCaptureIsActive:()=>Ot,debugVideoCaptureStart:()=>Xc,debugVideoCaptureStop:()=>Kc,debugWatermark:()=>io,distanceAngle:()=>bd,distanceWrap:()=>$r,drawCanvas2D:()=>Vn,drawCircle:()=>Oi,drawCircleGradient:()=>Df,drawContext:()=>Fe,drawCount:()=>Ft,drawCrescent:()=>zh,drawEllipse:()=>yl,drawEllipseGradient:()=>gl,drawLine:()=>On,drawLineList:()=>ar,drawNineSlice:()=>jl,drawNineSliceScreen:()=>Jh,drawPoly:()=>us,drawRect:()=>Li,drawRectGradient:()=>Lf,drawRegularPoly:()=>ml,drawText:()=>Ff,drawTextScreen:()=>gn,drawTextureWrapped:()=>Of,drawThreeSlice:()=>Jl,drawThreeSliceScreen:()=>Nh,drawTile:()=>Ne,enablePhysicsSolver:()=>lo,engineAddPlugin:()=>zn,engineImageFont:()=>vl,engineInit:()=>rd,engineName:()=>Ti,engineObjects:()=>Re,engineObjectsCallback:()=>cd,engineObjectsCollect:()=>Wc,engineObjectsCollide:()=>qr,engineObjectsDestroy:()=>ad,engineObjectsRaycast:()=>ld,engineObjectsUpdate:()=>qc,engineVersion:()=>Ai,fetchJSON:()=>kd,floor:()=>Oe,fontDefault:()=>ei,formatTime:()=>Kr,frame:()=>Uc,frameRate:()=>sd,gamepadConnected:()=>lr,gamepadDirectionEmulateStick:()=>ra,gamepadDpad:()=>cr,gamepadIsDown:()=>zt,gamepadPrimary:()=>Ce,gamepadStick:()=>Ns,gamepadStickCount:()=>wl,gamepadVibrate:()=>Zf,gamepadVibrateStop:()=>eh,gamepadWasPressed:()=>ba,gamepadWasReleased:()=>Qf,gamepadsEnable:()=>uo,getCameraSize:()=>xl,getCrescentPoints:()=>Nl,getNoteFrequency:()=>_l,getPaused:()=>id,glAntialias:()=>Aa,glCanvas:()=>fe,glCircleSides:()=>ti,glClearCanvas:()=>Ll,glClearRect:()=>Gl,glCompileShader:()=>yr,glContext:()=>g,glCopyToContext:()=>Ra,glCreateProgram:()=>ms,glCreateTexture:()=>mo,glDeleteTexture:()=>Il,glDraw:()=>Ys,glDrawColoredPoints:()=>La,glDrawOutlineTransform:()=>Ma,glDrawPoints:()=>Fl,glDrawPointsTransform:()=>Pa,glDrawUntextured:()=>Dl,glEnable:()=>$,glFlush:()=>je,glSetAntialias:()=>_h,glSetRenderTarget:()=>Ps,glSetTexture:()=>_a,glSetTextureData:()=>Ea,glSetTextureWrap:()=>Ol,gravity:()=>tt,headlessMode:()=>K,hsl:()=>qt,hypot:()=>Qc,inputClear:()=>ai,inputClearKey:()=>ya,inputMouseMoveThreshold:()=>ma,inputPreventDefault:()=>is,inputWASDEmulateDirection:()=>Ls,isArray:()=>Tt,isColor:()=>Z,isFullscreen:()=>Sl,isIntersecting:()=>nl,isNumber:()=>O,isOnScreen:()=>jf,isOverlapping:()=>Ei,isPowerOfTwo:()=>Gs,isStringLike:()=>ee,isTouchDevice:()=>mt,isUsingGamepad:()=>rs,isVector2:()=>I,keyDirection:()=>Xf,keyIsDown:()=>Je,keyWasPressed:()=>Ve,keyWasReleased:()=>ga,lastInputDevice:()=>hn,lerp:()=>nt,lerpAngle:()=>xd,lerpWrap:()=>tl,lightSystem:()=>se,lineTest:()=>il,log2:()=>Zc,mainCanvas:()=>Y,mainCanvasSize:()=>z,mainContext:()=>Se,max:()=>le,medalDisplaySize:()=>Hi,medalDisplaySlideTime:()=>os,medalDisplayTime:()=>Wi,medals:()=>Xs,medalsForEach:()=>yo,medalsInit:()=>Mh,medalsPreventUnlock:()=>Oa,medalsReset:()=>Lh,min:()=>de,mod:()=>pt,mouseDelta:()=>ha,mouseDeltaScreen:()=>Rt,mouseInWindow:()=>Di,mouseIsDown:()=>Is,mousePos:()=>Nt,mousePosScreen:()=>Ze,mouseWasPressed:()=>Js,mouseWasReleased:()=>Kf,mouseWheel:()=>pa,nearestPowerOfTwo:()=>Sd,newgrounds:()=>Ks,noise1D:()=>Pd,noise2D:()=>Md,objectDefaultAngleDamping:()=>sa,objectDefaultDamping:()=>na,objectDefaultFriction:()=>oa,objectDefaultMass:()=>ta,objectDefaultRestitution:()=>ia,objectMaxSpeed:()=>Wt,oscillate:()=>sl,particleEmitRateScale:()=>Ri,paused:()=>It,percent:()=>He,percentLerp:()=>gd,playSamples:()=>Ta,pointerLockExit:()=>sh,pointerLockIsActive:()=>Tl,pointerLockRequest:()=>nh,postProcess:()=>Ue,primitiveCount:()=>Gt,rand:()=>Te,randBool:()=>ol,randColor:()=>ir,randInCircle:()=>cl,randInt:()=>Yr,randSign:()=>rl,randVec2:()=>al,readSaveData:()=>Ed,rgb:()=>Q,round:()=>Ci,saveCanvas:()=>hl,saveDataURL:()=>Bs,saveText:()=>Cd,screenToWorld:()=>oi,screenToWorldDelta:()=>bl,screenToWorldTransform:()=>ri,setAdditiveBlendMode:()=>js,setCameraAngle:()=>Od,setCameraPos:()=>Ld,setCameraScale:()=>Id,setCanvasClearColor:()=>Gd,setCanvasColorTiles:()=>Fd,setCanvasFixedSize:()=>Nd,setCanvasMaxAspect:()=>Jd,setCanvasMaxSize:()=>Bd,setCanvasMinAspect:()=>jd,setCanvasPixelRatio:()=>Ud,setCanvasPixelated:()=>pl,setCursor:()=>Uf,setDebugKey:()=>Mf,setDebugWatermark:()=>Pf,setEnablePhysicsSolver:()=>Qd,setFontDefault:()=>Vd,setGLCircleSides:()=>$d,setGLEnable:()=>Hd,setGamepadDirectionEmulateStick:()=>lf,setGamepadsEnable:()=>cf,setGravity:()=>rf,setHeadlessMode:()=>Wd,setInputMouseMoveThreshold:()=>Wf,setInputPreventDefault:()=>qf,setInputWASDEmulateDirection:()=>uf,setMedalDisplaySize:()=>Dh,setMedalDisplaySlideTime:()=>Ih,setMedalDisplayTime:()=>Oh,setMedalsPreventUnlock:()=>Fh,setObjectDefaultAngleDamping:()=>tf,setObjectDefaultDamping:()=>ef,setObjectDefaultFriction:()=>sf,setObjectDefaultMass:()=>Zd,setObjectDefaultRestitution:()=>nf,setObjectMaxSpeed:()=>of,setParticleEmitRateScale:()=>af,setPaused:()=>od,setShowSplashScreen:()=>qd,setSoundDefaultRange:()=>Ef,setSoundDefaultTaper:()=>Rf,setSoundEnable:()=>Cf,setSoundVolume:()=>_f,setTileDefaultBleed:()=>Kd,setTileDefaultPadding:()=>Xd,setTileDefaultSize:()=>Yd,setTilesPixelated:()=>zd,setTimeScale:()=>Dd,setTouchGamepadAlpha:()=>wf,setTouchGamepadAnalog:()=>xf,setTouchGamepadButtonCount:()=>mf,setTouchGamepadCenterButtonSize:()=>pf,setTouchGamepadDisplayTime:()=>Tf,setTouchGamepadEnable:()=>ff,setTouchGamepadFloating:()=>Sf,setTouchGamepadLeftButtonCount:()=>gf,setTouchGamepadLeftStick:()=>yf,setTouchGamepadPassthrough:()=>hf,setTouchGamepadRightStick:()=>bf,setTouchGamepadSize:()=>vf,setTouchGamepadVibration:()=>Af,setTouchInputEnable:()=>df,setVibrateEnable:()=>kf,shareURL:()=>_d,showSplashScreen:()=>ea,sign:()=>ht,sin:()=>pe,smoothStep:()=>_i,soundDefaultRange:()=>la,soundDefaultTaper:()=>ua,soundEnable:()=>it,soundVolume:()=>Gn,speak:()=>bh,speakStop:()=>xh,tan:()=>el,textureInfos:()=>wn,tile:()=>ii,tileCollisionGetData:()=>ji,tileCollisionLayers:()=>bn,tileCollisionRaycast:()=>El,tileCollisionTest:()=>dn,tileDefaultBleed:()=>co,tileDefaultPadding:()=>ao,tileDefaultSize:()=>ro,tileLayersLoad:()=>vh,tilesPixelated:()=>jn,time:()=>ct,timeDelta:()=>Vr,timeReal:()=>xn,timeScale:()=>Qr,toggleFullscreen:()=>zf,touchGamepadAlpha:()=>ca,touchGamepadAnalog:()=>ni,touchGamepadButtonCount:()=>ys,touchGamepadCenterButtonSize:()=>At,touchGamepadDisplayTime:()=>Os,touchGamepadEnable:()=>vn,touchGamepadFloating:()=>Tn,touchGamepadLeftButtonCount:()=>gs,touchGamepadLeftStick:()=>Un,touchGamepadPassthrough:()=>aa,touchGamepadRightStick:()=>bs,touchGamepadSize:()=>st,touchGamepadVibration:()=>Pi,touchInputEnable:()=>Ln,tweenProperty:()=>Uh,tweenStopAll:()=>Vh,tweenUpdate:()=>Vl,uiDebug:()=>Da,uiSetDebug:()=>Gh,uiSystem:()=>E,usingGamepadInput:()=>Yf,usingKeyboardInput:()=>$f,usingMouseInput:()=>Hf,vec2:()=>v,vibrate:()=>xa,vibrateEnable:()=>si,vibrateStop:()=>th,workCanvas:()=>Yt,workContext:()=>fn,workReadCanvas:()=>Mt,workReadContext:()=>Ht,worldToScreen:()=>qn,worldToScreenDelta:()=>Gf,writeSaveData:()=>Rd,zzfx:()=>Sh,zzfxG:()=>ho,zzfxM:()=>Bl});function id(){return It}function od(t=!0){It=t}function zn(t,e,n,s){m(!In.find(r=>r.update===t&&r.render===e&&r.glContextLost===n&&r.glContextRestored===s));let i=new tr(t,e,n,s);In.push(i)}async function rd(t,e,n,s,i,r=[],a){if(Vc&&console.log(`${Ti} Engine v${Ai}`),m(!Se,"engine already initialized"),Se)return;m(Tt(r),"pass in images as array"),document.body||document.documentElement.appendChild(document.createElement("body")),a||(a=document.body),t||(t=()=>{}),e||(e=()=>{}),n||(n=()=>{}),s||(s=()=>{}),i||(i=()=>{});function o(){z=v(Y.width,Y.height),Se.imageSmoothingEnabled=!jn,mr()}function c(p=0){let y=p-Qo;Qo||(y=0),Qo=p,(We||io)&&(ki=nt(ki,1e3/(y||1),.05));let x=We&&Je("Equal"),w=We&&Je("Minus"),A=x?10:w?.1:1;xn+=y*A/1e3;let S=Qr*A;y*=S,Et+=It?0:y,S<=1&&(Et=de(Et,50));let _=!1;if(It){_=!0,l(),Gc(),In.forEach(k=>{var L;return(L=k.update)==null?void 0:L.call(k)});for(let k of Re)k.parent||k.updateTransforms();Oc(),n(),Bc(),Ot()&&C()}else{let k=0;for(Et<0&&Et>-9&&(k=Et,Et=0);Et>=0;Et-=1e3/60)ct=Uc++/60,_=!0,l(),Gc(),e(),In.forEach(L=>{var V;return(V=L.update)==null?void 0:V.call(L)}),qc(),Oc(),n(),Bc(),Ot()&&C();Et+=k}Ot()||C(),requestAnimationFrame(c);function C(){if(!K){_||l(),o(),s(),Re.sort((k,L)=>k.renderOrder-L.renderOrder);for(let k of Re)k.destroyed||k.render();i(),In.forEach(k=>{var L;return(L=k.render)==null?void 0:L.call(k)}),oh(),pd(),je(),md(),Ft=0,Gt=0}}}function l(){if(!K){if(ss.x){z=ss.copy();let p=innerWidth/innerHeight,y=ss.x/ss.y,x=pns){let _=z.y*ns|0;z.x=de(_,ts.x)}else if(w0&&!$&&(Se.fillStyle=mn.toString(),Se.fillRect(0,0,z.x,z.y),Se.fillStyle=me.toString()),Se.lineJoin="round",Se.lineCap="round"}}if(K)return f();Ah(a);let u="margin:0;overflow:hidden;background:#000;user-select:none;-webkit-user-select:none;touch-action:none;-webkit-touch-callout:none";a.style.cssText=u,Y=a.appendChild(document.createElement("canvas")),Fe=Se=Y.getContext("2d"),ih(),gh(),hd();let h="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)";Y.style.cssText=h,fe&&(fe.style.cssText=h),pl(Zr),l(),mr(),Yt=new OffscreenCanvas(64,64),fn=Yt.getContext("2d"),Mt=new OffscreenCanvas(64,64),Ht=Mt.getContext("2d",{willReadFrequently:!0});let d=r.map((p,y)=>Dc(y,p));return r.length||d.push(Dc(0)),d.push(Vf()),ea&&d.push(new Promise(p=>{let y=0;x();function x(){ai(),Ph(y+=.01),y>1?p():setTimeout(x,16)}})),await Promise.all(d),f();async function f(){await t(),c()}}function qc(){qr=Re.filter(e=>e.collideSolidObjects);function t(e){if(!e.destroyed){e.update();for(let n of e.children)t(n)}}for(let e of Re)if(!(e.parent||e.destroyed)){e.update(),e.updatePhysics();for(let n of e.children)t(n);e.updateTransforms()}Re=Re.filter(e=>!e.destroyed)}function ad(t=!0){for(let e of Re)e.parent||e.destroy(t);Re=Re.filter(e=>!e.destroyed)}function Wc(t,e,n=Re){let s=[];if(t)if(e instanceof ge)for(let i of n)i.isOverlapping(t,e)&&s.push(i);else{let i=e*e;for(let r of n)t.distanceSquared(r.pos)n(i))}function ld(t,e,n=Re){let s=[];for(let i of n)i.collideRaycast&&nl(t,e,i.pos,i.size)&&(wt&&_e(i.pos,i.size,"#f00"),s.push(i));return wt&&Lt(t,e,s.length?"#f00":"#00f",.02),s}function m(t,...e){if(!t)throw console.assert(t,...e),new Error("Assert failed!")}function Ee(...t){console.log(...t)}function _e(t,e=v(),n=te,s=0,i=0,r=!1,a=!1){m(I(t),"pos must be a vec2"),m(I(e),"size must be a vec2"),m(ee(n)||Z(n),"color is invalid"),m(O(s),"time must be a number"),m(O(i),"angle must be a number"),Z(n)&&(n=n.toString());let o=new Dt(s);pn.push({pos:t.copy(),size:e.copy(),color:n,timer:o,angle:i,fill:r,screenSpace:a})}function ud(t,e,n=te,s=0,i=0,r=!1,a=!1){m(I(t),"pos must be a vec2"),m(Tt(e),"points must be an array"),m(ee(n)||Z(n),"color is invalid"),m(O(s),"time must be a number"),m(O(i),"angle must be a number"),Z(n)&&(n=n.toString()),t=t.copy(),e=e.map(c=>c.copy());let o=new Dt(s);pn.push({pos:t,points:e,color:n,timer:o,angle:i,fill:r,screenSpace:a})}function et(t,e=0,n=te,s=0,i=!1,r=!1){m(I(t),"pos must be a vec2"),m(O(e),"size must be a number"),m(ee(n)||Z(n),"color is invalid"),m(O(s),"time must be a number"),Z(n)&&(n=n.toString()),t=t.copy();let a=new Dt(s);pn.push({pos:t,size:e,color:n,timer:a,angle:0,fill:i,screenSpace:r})}function Wr(t,e,n,s,i=!1){_e(t,void 0,e,n,s,!1,i)}function Lt(t,e,n,s=.1,i=0,r=!1){m(I(t),"posA must be a vec2"),m(I(e),"posB must be a vec2"),m(O(s),"width must be a number");let a=v((e.x-t.x)/2,(e.y-t.y)/2),o=v(s,a.length()*2);_e(t.add(a),o,n,i,a.angle(),!0,r)}function sr(t,e,n,s,i,r,a=!1){m(I(t),"posA must be a vec2"),m(I(n),"posB must be a vec2"),m(I(e),"sizeA must be a vec2"),m(I(s),"sizeB must be a vec2");let o=v(de(t.x-e.x/2,n.x-s.x/2),de(t.y-e.y/2,n.y-s.y/2)),c=v(le(t.x+e.x/2,n.x+s.x/2),le(t.y+e.y/2,n.y+s.y/2));_e(o.lerp(c,.5),c.subtract(o),i,r,0,!1,a)}function es(t,e,n=1,s=te,i=0,r=0,a="monospace",o=!1){m(ee(t),"text must be a string"),m(I(e),"pos must be a vec2"),m(O(n),"size must be a number"),m(ee(s)||Z(s),"color is invalid"),m(O(i),"time must be a number"),m(O(r),"angle must be a number"),m(ee(a),"font must be a string"),Z(s)&&(s=s.toString()),e=e.copy();let c=new Dt(i);pn.push({text:t,pos:e,size:n,color:s,timer:c,angle:r,font:a,screenSpace:o})}function dd(){pn=[]}function Yc(){nr=1}function fd(){let t=n=>{document.body.style="background-color:#111;margin:8px",document.body.innerHTML="
"+n},e=console.assert;console.assert=(n,...s)=>{if(e(n,...s),!n){let i=s.join(" "),r=new Error().stack;throw`Assertion failed!
+`+i+`
+`+r}},onunhandledrejection=n=>t(n.reason.stack||n.reason),onerror=(n,s,i,r)=>t(`${n}
+${s}
+Ln ${i}, Col ${r}`)}function hd(){Vc&&console.warn("LittleJS DEBUG build loaded. Use the release build for production.")}function Oc(){We&&(Ve($c)&&(Ut=!Ut),Ut&&(Ve("Digit1")&&(vt=!vt,Dn=!1),Ve("Digit2")&&(Dn=!Dn,vt=!1),Ve("Digit3")&&(Fn=!Fn),Ve("Digit4")&&(wt=!wt),Ve("Digit5")&&Yc(),Ve("Digit7")&&(ls=!ls)),Ot()?(!Ut||Ve("Digit6"))&&Kc():Ut&&Ve("Digit6")&&Xc())}function pd(){if(Ot())return;je();let t=Ft,e=Gt;nr&&(fa(),hl(Y),nr=0);let n=Se;if(Fn&&uo){let r=0;for(let a=0;a<8;a++)lr(a)&&r++;for(let a=0;a<8;a++){if(!lr(a))continue;let o=1,c=.2,l=Be.add(v(-o*2,((r-1)/2-a)*o*3));es(a,l.add(v(-o,o)),1),a===Ce&&es("Main",l.add(v(-o*2,0)),1,"#0f0");let u=Pt[a].length;for(let d=0;d{n.save();let r=i.pos,a=1,o=i.angle;if(i.screenSpace||(r=qn(i.pos),a=ie,o-=ue),n.translate(r.x|0,r.y|0),n.rotate(o),n.scale(1,i.text?1:-1),n.fillStyle=i.color,n.strokeStyle=i.color,i.text!==void 0)n.font=i.size*a+"px "+i.font,n.textAlign="center",n.textBaseline="middle",n.fillText(i.text,0,0);else if(i.points!==void 0){n.beginPath();for(let c of i.points){let l=c.scale(a).floor();n.lineTo(l.x,l.y)}n.closePath(),i.fill&&n.fill(),n.stroke()}else if(i.size===0||i.size.x===0&&i.size.y===0){let c=Hc*a;n.fillRect(-c/2,-1,c,3),n.fillRect(-1,-c/2,3,c)}else if(i.size.x!==void 0){let c=i.size.scale(a).floor(),l=c.x,u=c.y;i.fill&&n.fillRect(-l/2|0,-u/2|0,l,u),n.strokeRect(-l/2|0,-u/2|0,l,u)}else n.beginPath(),n.arc(0,0,i.size*a/2,0,9),i.fill&&n.fill(),n.stroke();n.restore()}),pn=pn.filter(i=>i.timer<0),s){let i=El(s.pos,Nt);i&&Li(i.floor().add(v(.5)),v(1),Q(0,1,1,.3),0,!1),On(Nt,s.pos,.1,i?Q(1,0,0,.5):Q(0,1,0,.5),void 0,void 0,!1);let r="mouse pos = "+Nt;bn.length&&(r+=`
+mouse collision = `+ji(Nt)),r+=`
+
+--- object info ---
+`,r+=s.toString(),gn(r,Ze,24,Q(),.05,void 0,"center","monospace")}{n.save(),n.fillStyle="#fff",n.textAlign="left",n.textBaseline="top",n.font="20px monospace",n.shadowColor="#000",n.shadowBlur=9;let a=9,o=0,c=24;if(Ut){n.fillText(`${Ti} v${Ai}`,a,o+=c/2),n.fillText("Time: "+Kr(ct),a,o+=c),n.fillText("FPS: "+ki.toFixed(1)+($?" WebGL":" Canvas2D"),a,o+=c),n.fillText("Objects: "+Re.length,a,o+=c),n.fillText("Draw Calls: "+Ft,a,o+=c),n.fillText("Primitives: "+Gt,a,o+=c),n.fillText("---------",a,o+=c),n.fillStyle="#f00",n.fillText("ESC: Debug Overlay",a,o+=c),n.fillStyle=vt?"#f00":"#fff",n.fillText("1: Debug Physics",a,o+=c),n.fillStyle=Dn?"#f00":"#fff",n.fillText("2: Debug Particles",a,o+=c),n.fillStyle=Fn?"#f00":"#fff",n.fillText("3: Debug Gamepads",a,o+=c),n.fillStyle=wt?"#f00":"#fff",n.fillText("4: Debug Raycasts",a,o+=c),n.fillStyle="#fff",n.fillText("5: Save Screenshot",a,o+=c),n.fillText("6: Toggle Video Capture",a,o+=c),n.fillStyle=ls?"#f00":"#fff",n.fillText("7: Debug Sound",a,o+=c);let l="",u="";for(let h in re[0])Je(h,0)&&(parseInt(h)<3?u+=h+" ":l+=h+" ");u&&n.fillText("Mouse: "+u,a,o+=c),l&&n.fillText("Keys: "+l,a,o+=c);for(let h=1;hs.push(o.data),i.onstop=()=>{let o=new Blob(s,{type:"video/webm"}),c=URL.createObjectURL(o);Bs(c,"capture.webm",1e3)};let r,a;if(it){a=new ConstantSourceNode(Ae,{offset:0}),a.connect(Kt),a.start(),r=Ae.createMediaStreamDestination(),Kt.connect(r);for(let o of r.stream.getAudioTracks())t.addTrack(o)}try{i.start()}catch{Ee("Video capture not supported in this browser!"),a==null||a.stop();return}Ee("Video capture started."),Vt={mediaRecorder:i,captureTimer:n,videoTrack:e,silentAudioSource:a,audioStreamDestination:r}}function Kc(){var t,e,n;m(Ot(),"Not capturing video!"),Ee(`Video capture ended. ${Vt.captureTimer.get().toFixed(2)} seconds recorded.`),St.style.display="none",(t=Vt.silentAudioSource)==null||t.stop(),(e=Vt.mediaRecorder)==null||e.stop(),(n=Vt.videoTrack)==null||n.stop(),Vt=void 0}function yd(){m(Ot(),"Not capturing video!"),fa(),Vt.videoTrack.requestFrame(),St.textContent="\u25CF REC "+Kr(Vt.captureTimer)}function ut(t){if(We){let e=Object.keys(t),n={};e.forEach(s=>n[s]=t[s]),e.forEach(s=>{Object.defineProperty(t,s,{get:()=>n[s],set:i=>{m(!1,`Cannot modify engine constant. Attempted to set constant (${t}) property '${s}' to '${i}'.`)},enumerable:!0})})}return Object.freeze(t)}function pt(t,e=1){return(t%e+e)%e}function X(t,e=0,n=1){return tn?n:t}function He(t,e,n){return(n-=e)?X((t-e)/n):0}function nt(t,e,n){return t+X(n)*(e-t)}function gd(t,e,n,s,i){return nt(s,i,He(t,e,n))}function $r(t,e,n=1){m(n>0,"distanceWrap wrapSize must be > 0");let s=(t-e)%n;return s*2%n-s}function tl(t,e,n,s=1){return t+X(n)*$r(e,t,s)}function bd(t,e){return $r(t,e,2*oe)}function xd(t,e,n){return tl(t,e,n,2*oe)}function _i(t){return t*t*(3-2*t)}function Gs(t){return!(t&t-1)}function Sd(t){return 2**Fs(Zc(t))}function Ei(t,e,n,s=v()){let i=(t.x-n.x)*2,r=(t.y-n.y)*2,a=e.x+s.x,o=e.y+s.y;return he(i)d)return!1;h=le(p,h)}else{if(p0?o.x+1:o.x,y=h>0?o.y+1:o.y,x=c?(p-t.x)/c:1/0,w=l?(y-t.y)/l:1/0,A=0,S=x,_=w,C=do.x&&(k.x=o.x+1-L),V.yo.y&&(k.y=o.y+1-L),s&&(C?s.set(-u,0):s.set(0,-h)),k}(C=S<_)?(o.x+=u,A=S,S+=d):(o.y+=h,A=_,_+=f)}}function Te(t=1,e=0){return e+Math.random()*(t-e)}function Yr(t,e=0){return Oe(Te(t,e))}function ol(t=.5){return Te()URL.revokeObjectURL(t),n)}function _d(t,e,n){var s;m(ee(t),"shareURL requires title string"),m(ee(e),"shareURL requires url string"),(s=navigator.share)==null||s.call(navigator,{title:t,url:e}).then(()=>n==null?void 0:n())}function Ed(t,e){m(ee(t),"loadData requires saveName string");let n={};try{let s=localStorage[t];if(s)try{n=JSON.parse(s)}catch{Ee("readSaveData: corrupt JSON for",t,"\u2014 using defaults")}}catch{Ee("readSaveData: localStorage unavailable \u2014 using defaults")}return{...e,...n}}function Rd(t,e){m(ee(t),"saveData requires saveName string");try{localStorage[t]=JSON.stringify(e)}catch{Ee("writeSaveData: failed to write",t)}}function rr(t){let e=(t|0)^2654435769;return e=Math.imul(e^e>>>16,2246822507),e=Math.imul(e^e>>>13,3266489909),e^=e>>>16,(e>>>0)/2**32}function Pd(t){let e=Oe(t);return nt(rr(e),rr(e+1),_i(t-e))}function Md(t,e){let n=Oe(t),s=Oe(e),i=_i(t-n),r=_i(e-s),a=(o,c)=>rr(o+c*374761393);return nt(nt(a(n,s),a(n+1,s),i),nt(a(n,s+1),a(n+1,s+1),i),r)}function Ld(t){Be=t.copy()}function Od(t){ue=t}function Id(t){ie=t}function Dd(t){Qr=t}function Fd(t){oo=t}function Gd(t){mn=t.copy()}function Bd(t){ts=t.copy()}function jd(t){Ms=t}function Jd(t){ns=t}function Nd(t){ss=t.copy()}function pl(t){Zr=t,Y&&(Y.style.imageRendering=t?"pixelated":""),fe&&(fe.style.imageRendering=t?"pixelated":"")}function zd(t){jn=t}function Ud(t){yn=t}function Vd(t){ei=t}function qd(t){ea=t}function Wd(t){K=t}function Hd(t){if(t&&!pr){console.warn("Can not enable WebGL if it was disabled on start.");return}$=t,fe&&(fe.style.display=t?"":"none")}function $d(t){ti=t}function Yd(t){ro=t.copy()}function Xd(t){ao=t}function Kd(t){co=t}function Qd(t){lo=t}function Zd(t){ta=t}function ef(t){na=t}function tf(t){sa=t}function nf(t){ia=t}function sf(t){oa=t}function of(t){Wt=t}function rf(t){tt=t.copy()}function af(t){Ri=t}function cf(t){uo=t}function lf(t){ra=t}function uf(t){Ls=t}function df(t){Ln=t}function ff(t){vn=t}function hf(t){aa=t}function pf(t){At=t}function mf(t){ys=t,t>0&&(bs=!1)}function yf(t){Un=t,t&&(gs=0)}function gf(t){gs=t,t>0&&(Un=!1)}function bf(t){bs=t,t&&(ys=0)}function xf(t){ni=t}function Sf(t){Tn=t}function vf(t){st=t}function wf(t){ca=t}function Tf(t){Os=t}function Af(t){Pi=t}function kf(t){si=t}function Cf(t){it=t}function _f(t){Gn=t,it&&!K&&Kt&&(Kt.gain.value=t)}function Ef(t){la=t}function Rf(t){ua=t}function Pf(t){io=t}function Mf(t){$c=t}function Mi(t){return t.r>=1&&t.g>=1&&t.b>=1}function da(t){return t.r<=0&&t.g<=0&&t.b<=0&&t.a<=0}function ii(t=0,e=ro,n=0,s=ao,i=co){if(m(I(t)||typeof t=="number","index must be a vec2 or number"),m(I(e)||typeof e=="number","size must be a vec2 or number"),m(O(n)||n instanceof Zt,"texture must be a number or TextureInfo"),m(O(s),"padding must be a number"),K)return new Bt;typeof e=="number"&&(m(e>0),e=new ge(e,e));let r=typeof n=="number"?wn[n]:n;m(r instanceof Zt,"tile texture is not loaded"),m(r.size.x>0,"tile texture is not loaded");let a=e.x+s*2,o=e.y+s*2,c,l;if(typeof t=="number"){let h=r.size.x/a|0;c=t%h,l=t/h|0}else c=t.x,l=t.y;let u=new ge(c*a+s,l*o+s);return new Bt(u,e,r,s,i)}function Ne(t,e=v(1),n,s=te,i=0,r,a,o=$,c=!1,l){var d;m(I(t),"pos must be a vec2"),m(I(e),"size must be a vec2"),m(Z(s),"color is invalid"),m(O(i),"angle must be a number"),m(!a||Z(a),"additiveColor must be a color"),m(!l||!o,"context only supported in canvas 2D mode");let u=n==null?void 0:n.textureInfo,h=(d=n==null?void 0:n.bleed)!=null?d:0;if(o&&$)if(m(!!g,"WebGL is not enabled!"),c&&([t,e,i]=ri(t,e,i)),u){let f=u.sizeInverse,p=n.pos.x*f.x,y=n.pos.y*f.y,x=n.size.x*f.x,w=n.size.y*f.y;if(_a(u.glTexture),h){let A=f.x*h,S=f.y*h;Ys(t.x,t.y,r?-e.x:e.x,e.y,i,p+A,y+S,p-A+x,y-S+w,s.rgbaInt(),a&&a.rgbaInt())}else Ys(t.x,t.y,r?-e.x:e.x,e.y,i,p,y,p+x,y+w,s.rgbaInt(),a&&a.rgbaInt())}else{let f=a?s.add(a):s;Dl(t.x,t.y,e.x,e.y,i,f.rgbaInt())}else++Ft,++Gt,Vn(t,e,i,r,f=>{if(u){f.scale(1,-1);let p=n.pos.x,y=n.pos.y,x=n.size.x,w=n.size.y;Nf(f,u.image,p,y,x,w,-.5,-.5,1,1,s,a,h)}else{let p=a?s.add(a):s;f.fillStyle=p.toString(),f.fillRect(-.5,-.5,1,1)}},c,l)}function Li(t,e,n,s,i,r,a){Ne(t,e,void 0,n,s,!1,void 0,i,r,a)}function Lf(t,e,n=te,s=Sn,i=0,r=$,a=!1,o){if(m(I(t),"pos must be a vec2"),m(I(e),"size must be a vec2"),m(Z(n)&&Z(s),"color is invalid"),m(O(i),"angle must be a number"),m(!o||!r,"context only supported in canvas 2D mode"),r&&$){m(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/ie),i+=ue);let c=[],l=[],u=e.x/2,h=e.y/2,d=n.rgbaInt(),f=s.rgbaInt(),p=be(-i),y=pe(-i);for(let x=4;x--;){let w=x&1?u:-u,A=x&2?h:-h,S=w*p-A*y,_=w*y+A*p,C=x&2?d:f;c.push(v(t.x+S,t.y+_)),l.push(C)}La(c,l)}else++Ft,++Gt,Vn(t,e,i,!1,c=>{let l=c.createLinearGradient(0,.5,0,-.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.fillRect(-.5,-.5,1,1)},a,o)}function Of(t,e,n,s=0,i=te,r=0,a,o=$,c=!1,l){if(m(I(t),"pos must be a vec2"),m(I(e),"size must be a vec2"),m(I(n),"wrapCount must be a vec2"),m(Z(i),"color is invalid"),m(O(r),"angle must be a number"),m(!a||Z(a),"additiveColor must be a color"),m(!l||!o,"context only supported in canvas 2D mode"),m(!(s instanceof Bt),"pass a TextureInfo or texture index, not a TileInfo \u2014 use tileInfo.textureInfo"),K)return;let u=typeof s=="number"?wn[s]:s;if(m(u instanceof Zt,"texture not loaded"),m(u.size.x>0,"texture not loaded"),m(u.wrap,"drawTextureWrapped requires a wrap-enabled texture; call textureInfo.setWrap(true) first"),o&&$){m(!!g,"WebGL is not enabled!"),c&&([t,e,r]=ri(t,e,r)),_a(u.glTexture),Ys(t.x,t.y,e.x,e.y,r,0,0,n.x,n.y,i.rgbaInt(),a&&a.rgbaInt());return}++Ft,++Gt,c||(t=qn(t),e=e.scale(ie),r-=ue);let h=!oo||(a?Mi(i.add(a))&&a.a<=0:Mi(i)),d=!h&&a&&!da(a),f=h?u.image:Jf(u.image,i,a);l=l||Fe,l.save(),l.translate(t.x+.5,t.y+.5),l.rotate(r),l.globalAlpha=d?1:i.a;let p=l.createPattern(f,"repeat"),y=new DOMMatrix().translate(-e.x/2,-e.y/2).scale(e.x/(n.x*f.width),e.y/(n.y*f.height));p.setTransform(y),l.fillStyle=p,l.fillRect(-e.x/2,-e.y/2,e.x,e.y),l.globalAlpha=1,l.restore()}function ar(t,e=.1,n=te,s=!1,i=v(),r=0,a=$,o=!1,c){if(m(Tt(t),"points must be an array"),m(O(e),"width must be a number"),m(Z(n),"color is invalid"),m(I(i),"pos must be a vec2"),m(O(r),"angle must be a number"),m(!c||!a,"context only supported in canvas 2D mode"),a&&$){m(!!g,"WebGL is not enabled!");let l=v(1);o&&([i,l,r]=ri(i,l,r)),Ma(t,n.rgbaInt(),e,i.x,i.y,l.x,l.y,r,s)}else++Ft,++Gt,Vn(i,v(1),r,!1,l=>{l.strokeStyle=n.toString(),l.lineWidth=e,l.beginPath();for(let u=0;u0&&Ma(t,s.rgbaInt(),n,i.x,i.y,l.x,l.y,r)}else Vn(i,v(1),r,!1,l=>{l.fillStyle=e.toString(),l.beginPath();for(let u of t)l.lineTo(u.x,u.y);l.closePath(),l.fill(),n&&(l.strokeStyle=s.toString(),l.lineWidth=n,l.stroke())},o,c)}function yl(t,e=v(1),n=te,s=0,i=0,r=me,a=$,o=!1,c){m(I(t),"pos must be a vec2"),m(I(e),"size must be a vec2"),m(Z(n)&&Z(r),"color is invalid"),m(O(s),"angle must be a number"),m(O(i),"lineWidth must be a number"),m(i>=0,"lineWidth must be a positive value or 0"),m(!c||!a,"context only supported in canvas 2D mode"),i=X(i,0,de(e.x,e.y)),a&&$?ml(t,e,ti,n,i,r,s,a,o,c):Vn(t,v(1),s,!1,l=>{l.fillStyle=n.toString(),l.beginPath(),l.ellipse(0,0,e.x/2,e.y/2,0,0,9),l.fill(),i&&(l.strokeStyle=r.toString(),l.lineWidth=i,l.stroke())},o,c)}function Oi(t,e=1,n=te,s=0,i=me,r=$,a=!1,o){m(O(e),"size must be a number"),yl(t,v(e),n,0,s,i,r,a,o)}function gl(t,e=v(1),n=te,s=Sn,i=0,r=$,a=!1,o){if(m(I(t),"pos must be a vec2"),m(I(e),"size must be a vec2"),m(Z(n)&&Z(s),"color is invalid"),m(O(i),"angle must be a number"),m(!o||!r,"context only supported in canvas 2D mode"),!K)if(r&&$){m(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/ie),i+=ue);let c=ti,l=e.x/2,u=e.y/2,h=n.rgbaInt(),d=s.rgbaInt(),f=If++,p=be(-i),y=pe(-i),x=_=>{let C=pe(_)*l,k=be(_)*u;return v(t.x+C*p-k*y,t.y+C*y+k*p)},w=f%c/c*oe*2,A=[x(w)],S=[d];for(let _=c;_--;){let C=(_+f)%c/c*oe*2;A.push(t),S.push(h),A.push(x(C)),S.push(d)}La(A,S)}else++Ft,++Gt,Vn(t,e,i,!1,c=>{let l=c.createRadialGradient(0,0,0,0,0,.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.beginPath(),c.ellipse(0,0,.5,.5,0,0,9),c.fill()},a,o)}function Df(t,e=1,n=te,s=Sn,i=$,r=!1,a){m(O(e),"size must be a number"),gl(t,v(e),n,s,0,i,r,a)}function Vn(t,e,n=0,s=!1,i,r=!1,a=Fe){m(I(t),"pos must be a vec2"),m(I(e),"size must be a vec2"),m(O(n),"angle must be a number"),m(typeof i=="function","drawFunction must be a function"),r||(t=qn(t),e=e.scale(ie),n-=ue),a.save(),a.translate(t.x+.5,t.y+.5),a.rotate(n),a.scale(s?-e.x:e.x,-e.y),i(a),a.restore()}function Ff(t,e,n=1,s=te,i=0,r=me,a="center",o=ei,c="",l,u=0,h=Fe){e=qn(e),n*=ie,i*=ie,u-=ue,u*=-1,gn(t,e,n,s,i,r,a,o,c,l,u,h)}function gn(t,e,n,s=te,i=0,r=me,a="center",o=ei,c="",l,u=0,h=Fe){m(ee(t),"text must be a string"),m(I(e),"pos must be a vec2"),m(O(n),"size must be a number"),m(Z(s),"color must be a color"),m(O(i),"lineWidth must be a number"),m(Z(r),"lineColor must be a color"),m(["left","center","right"].includes(a),"align must be left, center, or right"),m(ee(o),"font must be a string"),m(ee(c),"fontStyle must be a string"),m(O(u),"angle must be a number");let d=(t+"").split(`
+`),f=e.y-(d.length-1)*n/2;h.save(),h.fillStyle=s.toString(),h.strokeStyle=r.toString(),h.lineWidth=i,h.textAlign=a,h.font=c+" "+n+"px "+o,h.textBaseline="middle",h.translate(e.x,f),h.rotate(-u);let p=0;d.forEach(y=>{i&&h.strokeText(y,0,p,l),h.fillText(y,0,p,l),p+=n}),h.restore()}async function Dc(t,e){m(O(t),"textureIndex must be a number"),m(!wn[t],"textureIndex is already loaded!"),m(!e||ee(e),"image src must be a string");let n=new Image;e&&await new Promise(s=>{n.onerror=n.onload=s,n.crossOrigin="anonymous",n.src=e}),wn[t]=new Zt(n)}function oi(t){m(I(t),"screenPos must be a vec2");let e=(t.x-z.x/2+.5)/ie,n=(t.y-z.y/2+.5)/-ie;if(ue){let s=be(-ue),i=pe(-ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e+Be.x,n+Be.y)}function qn(t){m(I(t),"worldPos must be a vec2");let e=t.x-Be.x,n=t.y-Be.y;if(ue){let s=be(ue),i=pe(ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e*ie+z.x/2-.5,n*-ie+z.y/2-.5)}function bl(t){m(I(t),"screenDelta must be a vec2");let e=t.x/ie,n=t.y/-ie;if(ue){let s=be(-ue),i=pe(-ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e,n)}function Gf(t){m(I(t),"worldDelta must be a vec2");let e=t.x,n=t.y;if(ue){let s=be(ue),i=pe(ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e*ie,n*-ie)}function ri(t,e,n=0){return m(I(t),"screenPos must be a vec2"),m(I(e),"screenSize must be a vec2"),m(O(n),"screenAngle must be a number"),[oi(t),e.scale(1/ie),n+ue]}function xl(){return z.scale(1/ie)}function Bf(t,e,n,s){m(I(t),"center must be a vec2"),m(I(e),"size must be a vec2");let i=d(n),r=d(s),a=e.x+i.left+i.right,o=e.y+i.top+i.bottom,c=z.x-r.left-r.right,l=z.y-r.top-r.bottom;if(!(a>0&&o>0&&c>0&&l>0))return ie;ie=de(c/a,l/o);let u=v(i.right-i.left,i.top-i.bottom).scale(.5),h=v(r.right-r.left,r.top-r.bottom).scale(.5/ie);return Be=t.add(u).add(h),ie;function d(f){return(f===void 0||O(f))&&(f=v(f)),I(f)?{top:f.y,right:f.x,bottom:f.y,left:f.x}:{top:f.top||0,right:f.right||0,bottom:f.bottom||0,left:f.left||0}}}function jf(t,e=0){if(m(I(t),"pos must be a vec2"),m(I(e)||O(e),"size must be a vec2 or number"),!ie)return!1;let n=t.x-Be.x,s=t.y-Be.y;if(ue){let a=be(ue),o=pe(ue),c=n*a-s*o,l=n*o+s*a;n=c,s=l}n*=ie*2,s*=-ie*2,e instanceof ge&&(e=e.length()),e*=ie;let i=z.x,r=z.y;return n+e>-i&&n-e-r&&s-e{t.onerror=t.onload=o,t.crossOrigin="anonymous",t.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAAeAQMAAABnrVXaAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAAjpJREFUOMu9kzFu2zAUhn+CAROgqrk+B2l0BWYxMjlXeYaAtFtbdA1sGgHqRQfI0CNkSG5AwYB0BQ8d5Bsomwah6CPVeGg6tEPzAxLwyI+P78cP4u9lNO9OoMKnLMOobG5020/yaj/MrRcCGh1gBbyiLTPJEYaIiom5KM9Jq7KgynMGtb6L4GL4MF2H4LQKCXTvDVw2I4MsgZT7QLExdiutH+D08VOP3INXRrWX1/mmpbkNgAPYRVANb4xpcegYvhiNbIXauQICEjBuYLfMakaakWQeXxiZ0VDtuJCKs3ztMV59QtsHJNcRxDzfdL21ty3PrfIcXTN+E+GFAv6T5nbT9jd50/WFxb5ksdAv49qS6ouymG66ji08UMT6moykYLAo+V0j23GN4m829ZySAD5K7QsBfQTvOG8eE+gTeGYRAmnNAubN3hf5Zv9tJWDHp/VTuaSm7SN4fyINQqaNO3RMVxvpSPXnOChnRNvFcGY0gnwiPswYwTKVPE0zVtX3mTEIOoFzaqLrGuJaV+Uqumb71fVk/VoOH3cdLNQP/FHi8hV0CQNoqBZsUPlLPMsdCJro9QAaQQ0woDy9BJm0eTxCFnO9srcYlhNVlfR2EyTrph1uUtbUtAJifwRgrKuYdXVHeb0YI3QpawohQHkloI3J5FuVwI5ORxC9k2Tuz9Ir1IjgeIPGMHYkAZe2RuYkmWFmt3gGbTPOmBUWVTmRmHtGrfpzG/yuQNOKa6gBB/WA9khitPgl6/GP+gl2Af6tCbvaygAAAABJRU5ErkJggg=="});let e=v(),n=v(8),s=1,i=0,r=new Zt(t),a=new Bt(e,n,r,s,i);vl=new Ii(a)}function qf(t=!0){is=t}function Wf(t){ma=t}function Hf(){return hn==="mouse"}function $f(){return hn==="keyboard"}function Yf(){return hn==="gamepad"}function ya(t,e=0,n=!0,s=!0,i=!0){re[e]&&(re[e][t]&=~((n?1:0)|(s?2:0)|(i?4:0)))}function ai(){re.length=0,re[0]=[],yt.length=0,Jn.length=0,ci.length=0,Pt.length=0,Pn.length=0}function Je(t,e=0){var n;return m(ee(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=re[e])==null?void 0:n[t])&1)}function Ve(t,e=0){var n;return m(ee(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=re[e])==null?void 0:n[t])&2)}function ga(t,e=0){var n;return m(ee(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=re[e])==null?void 0:n[t])&4)}function Xf(t="ArrowUp",e="ArrowDown",n="ArrowLeft",s="ArrowRight"){m(ee(t),"up key must be a string"),m(ee(e),"down key must be a string"),m(ee(n),"left key must be a string"),m(ee(s),"right key must be a string");let i=r=>Je(r)?1:0;return v(i(s)-i(n),i(t)-i(e))}function Is(t){return m(O(t),"mouse button must be a number"),Je(t)}function Js(t){return m(O(t),"mouse button must be a number"),Ve(t)}function Kf(t){return m(O(t),"mouse button must be a number"),ga(t)}function zt(t,e=Ce){return m(O(t),"button must be a number"),m(O(e),"gamepad must be a number"),Je(t,e+1)}function ba(t,e=Ce){return m(O(t),"button must be a number"),m(O(e),"gamepad must be a number"),Ve(t,e+1)}function Qf(t,e=Ce){return m(O(t),"button must be a number"),m(O(e),"gamepad must be a number"),ga(t,e+1)}function Ns(t,e=Ce){var n,s;return m(O(t),"stick must be a number"),m(O(e),"gamepad must be a number"),(s=(n=Pt[e])==null?void 0:n[t])!=null?s:v()}function cr(t=Ce){var e;return m(O(t),"gamepad must be a number"),(e=Pn[t])!=null?e:v()}function lr(t=Ce){return m(O(t),"gamepad must be a number"),!!re[t+1]}function wl(t=Ce){var e,n;return m(O(t),"gamepad must be a number"),(n=(e=Pt[t])==null?void 0:e.length)!=null?n:0}function Zf(t=Ce,e=200,n=1,s=1,i=0){var a,o,c;if(m(O(t),"gamepad must be a number"),!si||K)return;let r=(a=navigator==null?void 0:navigator.getGamepads)==null?void 0:a.call(navigator)[t];(c=(o=r==null?void 0:r.vibrationActuator)==null?void 0:o.playEffect)==null||c.call(o,"dual-rumble",{duration:e,strongMagnitude:n,weakMagnitude:s,startDelay:i})}function eh(t=Ce){var n,s,i;if(m(O(t),"gamepad must be a number"),!si||K)return;let e=(n=navigator==null?void 0:navigator.getGamepads)==null?void 0:n.call(navigator)[t];(i=(s=e==null?void 0:e.vibrationActuator)==null?void 0:s.reset)==null||i.call(s)}function xa(t=100){var e;m(O(t)||Tt(t),"pattern must be a number or array"),si&&!K&&((e=navigator==null?void 0:navigator.vibrate)==null||e.call(navigator,t))}function th(){xa(0)}function nh(){var t;!mt&&((t=Y.requestPointerLock)==null||t.call(Y))}function sh(){var t;(t=document.exitPointerLock)==null||t.call(document)}function Tl(){return document.pointerLockElement===Y}function ih(){if(K)return;document.addEventListener("keydown",t),document.addEventListener("keyup",e),document.addEventListener("mousedown",s),document.addEventListener("mouseup",i),document.addEventListener("mousemove",r),document.addEventListener("mouseleave",a),document.addEventListener("wheel",o,{passive:!1}),document.addEventListener("contextmenu",c),document.addEventListener("blur",l),mt&&Ln&&u();function t(d){if(d.repeat||(re[0][d.code]=3,Ls&&(re[0][n(d.code)]=3)),!is||!d.cancelable||!document.hasFocus()||d.ctrlKey||d.metaKey||d.altKey||y(d.target)||y(document.activeElement))return;let f=typeof d.key=="string"&&d.key.length===1;(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Space","Tab","Backspace"].includes(d.code)||f)&&d.preventDefault();function y(x){let w=x==null?void 0:x.tagName;return(x==null?void 0:x.isContentEditable)||["INPUT","TEXTAREA","SELECT"].includes(w)}}function e(d){re[0][d.code]=re[0][d.code]&2|4,Ls&&(re[0][n(d.code)]=4)}function n(d){return Ls?d==="KeyW"?"ArrowUp":d==="KeyS"?"ArrowDown":d==="KeyA"?"ArrowLeft":d==="KeyD"?"ArrowRight":d:d}function s(d){if(mt&&Ln)return;it&&!K&&Ae&&!Us()&&Ae.resume(),re[0][d.button]=3;let f=Ze;Ze=h(v(d.x,d.y)),Rt=Rt.add(Ze.subtract(f)),is&&d.cancelable&&document.hasFocus()&&d.preventDefault()}function i(d){mt&&Ln||(re[0][d.button]=re[0][d.button]&2|4)}function r(d){Di=!0;let f=Ze;Ze=h(v(d.x,d.y));let p=Tl()?v(d.movementX,d.movementY):Ze.subtract(f);Rt=Rt.add(p)}function a(){Di=!1}function o(d){d.ctrlKey||(pa+=ht(d.deltaY)),is&&d.cancelable&&document.hasFocus()&&d.preventDefault()}function c(d){d.preventDefault()}function l(){ai(),$t.clear(),yt.length=0,Jn.length=0,ci.length=0}function u(){document.addEventListener("touchstart",p=>f(p),{passive:!1}),document.addEventListener("touchmove",p=>f(p),{passive:!1}),document.addEventListener("touchend",p=>f(p),{passive:!1});let d;function f(p){if(Ln){if(it&&!K&&Ae&&!Us()&&Ae.resume(),!vn||aa){let y=S=>zs.includes(S.target)||S.target===Mn,x=[];for(let S of p.touches)y(S)||x.push(S);let w=x.length,A=0;if(w){let S=v(x[0].clientX,x[0].clientY),_=Ze;Ze=h(S),d?Rt=Rt.add(Ze.subtract(_)):re[0][A]=3}else d&&(re[0][A]=re[0][A]&2|4);d=w}return is&&p.cancelable&&document.hasFocus()&&p.preventDefault(),!0}}}function h(d){let f=Y.getBoundingClientRect(),p=He(d.x,f.left,f.right),y=He(d.y,f.top,f.bottom);return v(p*Y.width,y*Y.height)}}function Gc(){if(K)return;!(Ln&&mt)&&!document.hasFocus()&&ai(),Nt=oi(Ze),ha=bl(Rt),rh(),e(),t();function t(){let n=Is(0)||Is(1)||Is(2)||Rt.length()>ma,s=!1;for(let r=wl();r--&&!s;)s=Ns(r).lengthSquared()>.04;for(let r=17;r--&&!s;)s=zt(r);let i=!1;for(let r in re[0])if(isNaN(+r)&&re[0][r]&1){i=!0;break}s?hn="gamepad":n?hn="mouse":i&&(hn="keyboard"),rs=hn==="gamepad"}function e(){var a,o,c,l,u,h,d;let n=f=>{let x=w=>w>.3?He(w,.3,.8):w<-.3?-He(-w,.3,.8):0;return v(x(f.x),x(-f.y)).clampLength()};if(vn&&mt){if(m(!Un||!gs,"set touchGamepadLeftStick or touchGamepadLeftButtonCount, not both"),m(!bs||!ys,"set touchGamepadRightStick or touchGamepadButtonCount, not both"),!ds.isSet())return;Ce=0;let f=(a=Pt[0])!=null?a:Pt[0]=[],p=(o=Pn[0])!=null?o:Pn[0]=v();f.length=0,p.set();for(let x=0;x<2;x++){if(!en(x))continue;let w=wa(x);f[w]=v();let A=(c=Jn[x])!=null?c:v();if(ni)f[w]=n(A);else if(A.lengthSquared()>.3){let S=X(Ci(A.x),-1,1),_=X(Ci(A.y),-1,1);f[w]=v(S,-_).clampLength(),w||p.set(S,-_)}}let y=(l=re[1])!=null?l:re[1]=[];for(let x=12;x--;){let w=zt(x,0);y[x]=yt[x]?w?1:3:w?4:0,Pi&&y[x]===3&&(x===9||ah(x))&&xa(Pi)}return}try{if(!uo||!(navigator!=null&&navigator.getGamepads))return}catch{return}if(!We&&!document.hasFocus())return;let s=8,i=navigator.getGamepads(),r=de(s,i.length);for(let f=0;f>1]=n(v(p.axes[S],p.axes[S+1]));let A=!1;for(let S=p.buttons.length;S--;){let _=p.buttons[S],C=zt(S,f);y[S]=_.pressed?C?1:3:C?4:0,_.pressed&&(!_.value||_.value>.9)&&(A=!0)}A&&(Zo[f]=!0,Zo[Ce]||(Ce=f)),p.mapping==="standard"&&w.set((zt(15,f)&&1)-(zt(14,f)&&1),(zt(12,f)&&1)-(zt(13,f)&&1)),ra&&(w.x||w.y)&&(x[0]=w.clampLength())}vn&&rs&&ds.unset()}}function Bc(){if(!K){for(let t of re)for(let e in t)t[e]&=1;pa=0,ha=v(),Rt=v()}}function oh(){dh()}function rh(){if(un||!vn||!mt||K||!document.body)return;let t=un=document.createElement("div");t.style.cssText="position:fixed;inset:0;z-index:50;pointer-events:none;opacity:0;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;transition:opacity .2s;box-sizing:border-box;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)";let e=Al=document.createElement("div");e.style.cssText="position:relative;width:100%;height:100%;pointer-events:none",t.appendChild(e);let n=Sa=document.createElementNS(Gi,"svg");n.style.cssText="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible;fill:none;stroke:#fff;stroke-width:3",e.appendChild(n);let s=()=>{let i=document.createElement("div");return i.style.cssText="position:absolute;pointer-events:auto;touch-action:none",i.addEventListener("pointerdown",r=>mh(r,i)),i.addEventListener("pointermove",r=>yh(r)),i.addEventListener("pointerup",r=>jc(r)),i.addEventListener("pointercancel",r=>jc(r)),e.appendChild(i),i};zs[0]=s(),zs[1]=s(),Mn=s(),addEventListener("resize",()=>fs=!0),document.body.appendChild(t),fs=!0}function fo(){return Al.getBoundingClientRect()}function en(t){return t?bs:Un}function Wn(t){return t?ys:gs}function va(t){return t?0:4}function wa(t){return t&&Un?1:0}function hs(t){return en(t)||Wn(t)>0}function ah(t){for(let e=0;e<2;e++){let n=va(e);if(!en(e)&&t>=n&&tr.style.cssText="position:absolute;pointer-events:auto;touch-action:none;"+a;if(It){for(let r of zs)r.style.display="none";At?(i(Mn,"inset:0"),Mn.style.display=""):Mn.style.display="none"}else{for(let a=0;a<2;a++){let o=zs[a],c=a?"right":"left";if(o.style.display=hs(a)?"":"none",Tn){let l=hs(a?0:1)?"50%":"100%";i(o,`${c}:0;bottom:0;width:${l};height:60%`)}else i(o,`${c}:0;bottom:0;width:${3*s}px;height:${3*s}px`)}Mn.style.display=At?"":"none";let r=At;i(Mn,`left:50%;top:50%;width:${2*r}px;height:${2*r}px;transform:translate(-50%,-50%)`)}lh(e,n),fs=!1}function lh(t,e){let n=Sa;for(;n.firstChild;)n.removeChild(n.firstChild);let s=kl={face:[],thumb:[]},i=st,r=(o,c,l,u)=>{let h=document.createElementNS(Gi,"circle");return h.setAttribute("cx",o),h.setAttribute("cy",c),h.setAttribute("r",l),u&&h.setAttribute("fill",u),n.appendChild(h),h},a=o=>{let c=i*.18,l=i*.5,u=o.x,h=o.y,d=document.createElementNS(Gi,"path");d.setAttribute("d",`M ${u-c} ${h-l} H ${u+c} V ${h-c} H ${u+l} V ${h+c} H ${u+c} V ${h+l} H ${u-c} V ${h+c} H ${u-l} V ${h-c} H ${u-c} Z`),n.appendChild(d)};for(let o=0;o<2;o++){let c=Wn(o),l=va(o),u=Xt(o,t,e);if(en(o))ni?r(u.x,u.y,i/2):a(u),s.thumb[o]=r(u.x,u.y,i/4,"#fff");else if(c===1)s.face[l]=r(u.x,u.y,i/2,"#000");else for(let h=0;h2?d:de(d,c-1);f=f===3?2:f===2?3:f;let p=v().setDirection(d,i/2);c===2&&(p.x*=-1),o||(p.x*=-1);let y=u.add(p);s.face[l+f]=r(y.x,y.y,i/4,"#000")}}We&&Fn&&uh(t,e)}function uh(t,e){let n=st,s=Sa,i=(a,o,c)=>{let l=document.createElementNS(Gi,a);for(let u in o)l.setAttribute(u,o[u]);l.setAttribute("stroke",c),l.setAttribute("stroke-width",2),l.setAttribute("fill","none"),s.appendChild(l)},r=(a,o,c)=>i("circle",{cx:a.x,cy:a.y,r:o},c);i("line",{x1:t/2,y1:0,x2:t/2,y2:e},"#0f0");for(let a=0;a<2;a++)if(en(a))if(Tn){let o=e*.4,c=!hs(a?0:1),l=c?0:a?t/2:0;i("rect",{x:l,y:o,width:c?t:t/2,height:e-o},"#0ff")}else r(Xt(a,t,e),2*n,"#0ff");else Wn(a)>=1&&r(Xt(a,t,e),n,"#0ff");if(At){r(v(t/2,e/2),At,"#ff0");for(let a=0;a<2;a++)hs(a)&&r(Xt(a,t,e),2*n,"#f0f")}}function dh(){var l;if(!un||K)return;if(!vn||!mt){un.style.display!=="none"&&(un.style.display="none",$t.clear(),yt.length=0,Jn.length=0,ci.length=0);return}un.style.display="";let t=We&&Fn,e=[ys,gs,Un,bs,ni,st,Tn,At,It,t].join();e!==Fc&&(Fc=e,fs=!0),fs&&ch();let n=Os?He(ds.get(),Os+1,Os):1,s=t||ds.isSet()&&n>0&&!It;if(un.style.opacity=s?t?1:n*ca:0,!s)return;let i=fo(),r=i.width,a=i.height,o=st,c=kl;if(c){for(let u=0;u<2;u++)if(en(u)&&c.thumb[u]){let d=Xt(u,r,a).add(((l=Jn[u])!=null?l:v()).scale(o/2));c.thumb[u].setAttribute("cx",d.x),c.thumb[u].setAttribute("cy",d.y)}for(let u=0;u=st)return-1;if(i===1)return r;let o=a.subtract(e);t||(o.x*=-1);let c=i===2?o.xr:o&&Xt(a,e,n).distance(t)<2*s)return{role:"stick",side:a}}else if(Wn(a)>=1){let c=hh(a,t,e,n);if(c>=0)return{role:"face",btn:c}}}if(At){for(let a=0;a<2;a++)if(hs(a)&&Xt(a,e,n).distance(t)<2*s)return;if(v(e/2,n/2).distance(t)h.getChannelData(x).set(y)),d.buffer=h,d.playbackRate.value=n,d.loop=i,a=a||Ae.createGain(),a.gain.value=e,a.connect(Kt);let f=new StereoPannerNode(Ae,{pan:X(s,-1,1)});d.connect(f).connect(a),d.addEventListener("ended",()=>{a.disconnect(),f.disconnect(),c&&c(d)});let p=o*n;return d.start(0,p),We&&ls&&Ee("sound","vol",e.toFixed(2),"rate",n.toFixed(2),"pan",s.toFixed(2),i?"loop":""),d}function Sh(...t){return Ta([ho(...t)])}function ho(t=1,e=.05,n=220,s=0,i=0,r=.1,a=0,o=1,c=0,l=0,u=0,h=0,d=0,f=0,p=0,y=0,x=0,w=1,A=0,S=0,_=0){let C=xs,k=oe*2,L=c*=500*k/C/C,V=n*=(1+Te(e,-e))*k/C,ae=0,ne=0,T=0,P=1,R,M=[],j=0,G=0,H=0,W,xe=2,Pe=k*he(_)*2/C,ve=be(Pe),dt=pe(Pe)/2/xe,ft=1+dt,bt=-2*ve/ft,$n=(1-dt)/ft,jt=(1+ht(_)*ve)/2/ft,Yn=-(ht(_)+ve)/ft,Ss=jt,tn=0,nn=0,sn=0,Xn=0;for(s=s*C||9,A*=C,i*=C,r*=C,x*=C,l*=500*k/C**3,p*=k/C,u*=k/C,h*=C,d=d*C|0,R=s+A+i+r+x|0;G1?a>2?a>3?a>4?j/k%14?H:ht(H)*he(H)**o)*(GG?0:(Gh&&(n+=u,V+=u,P=0),d&&!(++ne%d)&&(n=V,c=L,P||(P=1));return M}function ji(t,e=!0){for(let n of bn)if((!e||n.isSolid)&&t.arrayCheck(n.size)){let s=n.getCollisionData(t);if(s)return s}return 0}function dn(t,e=v(),n,s=!0){for(let i of bn)if((!s||i.isSolid)&&i.collisionTest(t,e,n))return i}function El(t,e,n,s,i=!0){let r,a,o,c=s&&v();for(let l of bn)if(!i||l.isSolid){let u=l.collisionRaycast(t,e,n,c);if(u){let h=t.distanceSquared(u);(r===void 0||h{$=!1,fe.style.display="none",n.preventDefault(),Ee("WebGL context lost! Switching to Canvas2d rendering.");for(let s of Ds)s.glTexture=void 0;lt=void 0,Ge=0,Nn=!1,In.forEach(s=>{var i;return(i=s.glContextLost)==null?void 0:i.call(s)})}),fe.addEventListener("webglcontextrestored",()=>{$=!0,fe.style.display="",Ee("WebGL context restored, reinitializing..."),e();for(let n of Ds)n.glTexture=mo(n.image,n.wrap);In.forEach(n=>{var s;return(s=n.glContextRestored)==null?void 0:s.call(n)})});function e(){zi=ms(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 g;in vec4 p,u,c,a;in float r;out vec2 v;out vec4 d,e;void main(){vec2 s=(g-.5)*p.zw;gl_Position=m*vec4(p.xy+s*cos(r)-vec2(-s.y,s)*sin(r),1,1);v=mix(u.xw,u.zy,g);d=c;e=a;}`,`#version 300 es
+precision highp float;uniform sampler2D s;in vec2 v;in vec4 d,e;out vec4 c;void main(){c=texture(s,v)*d+e;}`),Ui=ms(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 p;in vec4 c;out vec4 d;void main(){gl_Position=m*vec4(p,1,1);d=c;}`,`#version 300 es
+precision highp float;in vec4 d;out vec4 c;void main(){c=d;}`);let n=new ArrayBuffer(qi);qe=new Float32Array(n),Hs=new Uint32Array(n),dr=g.createBuffer(),as=g.createBuffer(),ka=g.createFramebuffer(),Ge=0;let s=new Float32Array([0,0,1,0,0,1,1,1]);g.bindBuffer(g.ARRAY_BUFFER,as),g.bufferData(g.ARRAY_BUFFER,s,g.STATIC_DRAW);let i,r,a,o=(c,l,u,h,d=0)=>{let f=g.getAttribLocation(r,c),p=u===1,y=u&&a;g.enableVertexAttribArray(f),g.vertexAttribPointer(f,h,l,p,y,i),g.vertexAttribDivisor(f,d),i+=h*u};fr=g.createVertexArray(),g.bindVertexArray(fr),i=0,r=zi,a=Rl,g.bindBuffer(g.ARRAY_BUFFER,as),o("g",g.FLOAT,0,2),g.bindBuffer(g.ARRAY_BUFFER,dr),g.bufferData(g.ARRAY_BUFFER,qi,g.DYNAMIC_DRAW),o("p",g.FLOAT,4,4,1),o("u",g.FLOAT,4,4,1),o("c",g.UNSIGNED_BYTE,1,4,1),o("a",g.UNSIGNED_BYTE,1,4,1),o("r",g.FLOAT,4,1,1),hr=g.createVertexArray(),g.bindVertexArray(hr),i=0,r=Ui,a=Pl,o("p",g.FLOAT,4,2),o("c",g.UNSIGNED_BYTE,1,4)}}function $s(t=!1){!t&&!Nn||(je(),Nn=!1,g.useProgram(zi),g.bindVertexArray(fr))}function Ml(){Nn||(je(),Nn=!0,g.useProgram(Ui),g.bindVertexArray(hr))}function mr(t=!0){if(!$||!g)return;m(!Ge,"glPreRender called with unflushed batch."),Vi||(fe.width=z.x,fe.height=z.y),g.viewport(0,0,z.x,z.y),t&&Ll();let e=v(2*ie).divide(z);Vi&&(e.y=-e.y);let n=Be.rotate(-ue),s=v(-1).subtract(n.multiply(e)),i=be(ue),r=pe(ue),a=[e.x*i,e.y*r,0,0,-e.x*r,e.y*i,0,0,1,1,1,0,s.x,s.y,0,1],o=(c,l,u)=>{g.useProgram(c);let h=g.getUniformLocation(c,l);g.uniformMatrix4fv(h,!1,u)};o(Ui,"m",a),o(zi,"m",a),g.activeTexture(g.TEXTURE0),wn[0]&&(lt=wn[0].glTexture,g.bindTexture(g.TEXTURE_2D,lt)),g.bindBuffer(g.ARRAY_BUFFER,dr),Hn=ps=!1,$s(!0)}function Ll(){if(!g)return;let t=mn;g.clearColor(t.r,t.g,t.b,t.a),g.clear(g.COLOR_BUFFER_BIT)}function _a(t){!g||t===lt||(je(),lt=t,g.bindTexture(g.TEXTURE_2D,lt))}function Ol(t,e=!0){if(!g||!t)return;let n=t===lt;n?je():g.bindTexture(g.TEXTURE_2D,t);let s=e?g.REPEAT:g.CLAMP_TO_EDGE;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,s),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,s),!n&<&&g.bindTexture(g.TEXTURE_2D,lt)}function yr(t,e){if(!g)return;let n=g.createShader(e);if(g.shaderSource(n,t),g.compileShader(n),We&&!g.getShaderParameter(n,g.COMPILE_STATUS))throw g.getShaderInfoLog(n);return n}function ms(t,e){if(!g)return;let n=g.createProgram();if(g.attachShader(n,yr(t,g.VERTEX_SHADER)),g.attachShader(n,yr(e,g.FRAGMENT_SHADER)),g.linkProgram(n),We&&!g.getProgramParameter(n,g.LINK_STATUS))throw g.getProgramInfoLog(n);return n}function mo(t,e=!1){if(!g)return;let n=g.createTexture(),s=!1;if(t!=null&&t.width)Ea(n,t),g.bindTexture(g.TEXTURE_2D,n),s=!jn&&Gs(t.width)&&Gs(t.height);else{let o=new Uint8Array([255,255,255,255]);g.bindTexture(g.TEXTURE_2D,n),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,1,1,0,g.RGBA,g.UNSIGNED_BYTE,o)}let i=jn?g.NEAREST:g.LINEAR,r=s?g.LINEAR_MIPMAP_LINEAR:i;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,i),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,r);let a=e?g.REPEAT:g.CLAMP_TO_EDGE;return g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,a),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,a),s&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,lt),n}function Il(t){g&&g.deleteTexture(t)}function Ea(t,e){g&&(m((e==null?void 0:e.width)>0,"Invalid image data."),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e),!jn&&Gs(e.width)&&Gs(e.height)&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,lt))}function kh(t){K||(Ds.add(t),g&&(t.glTexture?Ea(t.glTexture,t.image):t.glTexture=mo(t.image,t.wrap)))}function Ch(t){if(K)return;Ds.delete(t);let e=t.glTexture;t.glTexture=void 0,Il(e)}function je(){if($&&g&&Ge){let t=ps?g.ONE:g.ONE_MINUS_SRC_ALPHA;g.blendFuncSeparate(g.SRC_ALPHA,t,g.ONE,t),g.enable(g.BLEND);let e=Ge*(Nn?po:Ca);g.bufferSubData(g.ARRAY_BUFFER,0,qe,0,e),Nn?g.drawArrays(g.TRIANGLE_STRIP,0,Ge):g.drawArraysInstanced(g.TRIANGLE_STRIP,0,4,Ge),++Ft,Gt+=Ge,Ge=0}ps=Hn}function Ra(t){!$||!g||(je(),t.drawImage(fe,0,0))}function _h(t=!0){m(!fe,"must be called before engineInit"),Aa=t}function Ys(t,e,n,s,i=0,r=0,a=0,o=1,c=1,l=-1,u=0){(Ge>=Th||ps!==Hn)&&je(),$s();let h=Ge++*Ca;qe[h++]=t,qe[h++]=e,qe[h++]=n,qe[h++]=s,qe[h++]=r,qe[h++]=a,qe[h++]=o,qe[h++]=c,Hs[h++]=l,Hs[h++]=u,qe[h++]=i}function Dl(t,e,n,s,i,r){Ys(t,e,n,s,i,0,0,0,0,0,r)}function Pa(t,e,n,s,i,r,a,o=!0){let c=[],l=pe(-a),u=be(-a);for(let d of t){let f=d.x*i,p=d.y*r;c.push(v(n+u*f-l*p,s+l*f+u*p))}let h=o?Rh(c):c;Fl(h,e)}function Ma(t,e,n,s,i,r,a,o,c=!0){let l=Eh(t,n,c);Pa(l,e,s,i,r,a,o,!1)}function Fl(t,e){if(!$||t.length<3)return;let n=t.length+2;if((Ge+n>=cs||ps!==Hn)&&je(),m(n=cs)return;Ml();let s=Ge*po;for(let i=n;i--;){let r=X(i-1,0,n-3),a=t[r];qe[s++]=a.x,qe[s++]=a.y,Hs[s++]=e}Ge+=n}function La(t,e){if(!$||t.length<3)return;let n=t.length+2;if((Ge+n>=cs||ps!==Hn)&&je(),m(n=cs)return;Ml();let s=Ge*po;for(let i=n;i--;){let r=X(i-1,0,n-3),a=t[r],o=e[r];qe[s++]=a.x,qe[s++]=a.y,Hs[s++]=o}Ge+=n}function Ps(t,e=!1){t?(Vi=t,g.bindFramebuffer(g.FRAMEBUFFER,ka),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,t,0),mr(e)):(je(),Vi=void 0,g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,z.x,z.y))}function Gl(t,e,n,s){$&&(g.enable(g.SCISSOR_TEST),g.scissor(t,e,n,s),g.clearColor(0,0,0,0),g.clear(g.COLOR_BUFFER_BIT),g.disable(g.SCISSOR_TEST))}function Eh(t,e,n=!0){if(t.length<2)return[];let s=e/2,i=[],r=t.length,a=1e-6,o=10;for(let c=0;ca?-f/p:0,S=p>a?d/p:0,_=w>a?-x/w:0,C=w>a?y/w:0,k=A+_,L=S+C,V=(k*k+L*L)**.5;if(Va){let P=de(1/T,o);k*=P,L*=P}}let ae=v(u.x-k*s,u.y-L*s),ne=v(u.x+k*s,u.y+L*s);i.push(ae),i.push(ne)}return i.length>1&&n&&(i.push(i[0]),i.push(i[1])),i}function Rh(t){if(t.length<3)return[];let e=(f,p,y)=>(p.x-f.x)*(y.y-f.y)-(p.y-f.y)*(y.x-f.x);(f=>{let p=0;for(let y=f.length;y--;){let x=(y+1)%f.length;p+=f[y].cross(f[x])}return p})(t)<0&&(t=t.slice().reverse());let s=1e-9,i=(f,p,y,x)=>{let w=e(p,y,f),A=e(y,x,f),S=e(x,p,f),_=(w<-s?1:0)+(A<-s?1:0)+(S<-s?1:0),C=(w>s?1:0)+(A>s?1:0)+(S>s?1:0);return!(_&&C)},r=[];for(let f=0;f3&&o++{if(_>=0){let k=s.fillStyle=s.createLinearGradient(x,w,A,S);k.addColorStop(0,h(_,2)),k.addColorStop(1,h(_,1))}else s.fillStyle="#000";_>=-1?(s.fill(),C&&s.stroke()):s.stroke()},c=(x,w,A,S=0,_=2*oe,C,k)=>{s.beginPath(),s.arc(x,w,A,f*S,f*_),o(x,w-A,x,w+A,C,k)},l=(x,w,A,S,_)=>{s.beginPath(),s.rect(x,w,A,S*f),o(x,w+S,x+A,w,_)},u=(x,w,A,S)=>{s.beginPath();for(let _ of x)s.lineTo(_.x,_.y);s.closePath(),o(0,A,0,A+S,w)},h=(x,w)=>w?`hsl(${[.95,.56,.13][x%3]*360} 99%${[0,50,75][w]}%)`:"#000",d=sl(1,1,t),f=He(d,.1,.5),p=de(6,de(r,a)/99);s.translate(r/2,a/2),s.scale(p,p),s.translate(-40,-35),f<1&&s.setLineDash([99*f,99]),s.lineJoin=s.lineCap="round",s.lineWidth=.1+f*1.9;{let w="LittleJS";s.font="900 15.5px arial",s.lineWidth=.1+f*3.9,s.textAlign="center",s.textBaseline="top",l(11,55,59,8*f,-1),s.beginPath();let A=0;for(let S=0;S5?1:0),s[S?"strokeText":"fillText"](w[_],L,54+.5,17*f),C+=k}s.lineWidth=.1+f*1.9,l(3,54,73,0)}l(7,15,26,-7,0),l(25,15,8,25,-1),l(10,40,15,-25,1),l(14,21,7,9,2),l(38,20,6,-6,2),l(49,20,10,-6,0);let y=[v(44,8),v(64,8),v(59,8+6*f),v(49,8+6*f)];u(y,2,8,6*f),l(44,8,20,-7,0);for(let x=5;x--;)c(59-x*6*f,30,10,0,2*oe,1,0);c(59,30,4,0,7,2),l(35,20,24,0),c(59,30,10),c(47,30,10,oe/2,oe*3/2),c(35,30,10,oe/2,oe*3/2),l(7,40,13,7,-1),l(17,40,43,14,-1);for(let x=3;x--;)for(let w=2;w--;)c(17+15*x,47,w?7:1,0,2*oe,2);for(let x=2;x--;){let w=6,A=7,S=53+w*f*x,_=[v(S+A,54),v(S,40),v(S+w*f,40),v(S+A+w*f,54)];u(_,0,40,14)}s.restore()}function Mh(t){if($i=t,!Rn){let n={};try{n=JSON.parse(localStorage[t]||"{}")}catch{n={}}yo(s=>{s.unlocked=!!(n[s.id]&&n[s.id].unlocked)}),Ia()}zn(void 0,e);function e(){if(!wi.length)return;let n=wi[0],s=xn-vi;if(!vi)vi=xn;else if(s>Wi)vi=0,wi.shift();else{let i=Wi-os,r=si?(s-i)/os:0;n.render(r)}}}function yo(t){Object.values(Xs).forEach(e=>t(e))}function Lh(){yo(t=>t.unlocked=!1),Ia()}function Ia(){if(!$i)return;let t={};yo(e=>{let n={name:e.name,description:e.description,icon:e.icon,unlocked:e.unlocked};e.image&&(n.src=e.image.src),t[e.id]=n}),localStorage[$i]=JSON.stringify(t)}function Oh(t){Wi=t}function Ih(t){os=t}function Dh(t){Hi=t.copy()}function Fh(t){Oa=t}function Bl(t,e,n,s=125){let i,r,a,o,c,l,u,h,d,f,p,y,x,w=0,A,S=[],_=[],C=[],k=0,L=0,V=1,ae={},ne=xs/s*60>>2;for(;V;k++)S=[V=h=y=0],n.forEach((T,P)=>{for(u=e[T][k]||[0,0,0],V|=e[T][k]&&1,A=y+(e[T][0].length-2-(h?0:1))*ne,x=P===n.length-1,i=2,a=y;ine-99&&d&&p<1?p+=1/99:0)l=(1-p)*S[w++]/2||0,_[a]=(_[a]||0)-l*L+l,C[a]=(C[a++]||0)+l*L+l;c&&(p=c%1,L=u[1]||0,(c|=0)&&(S=ae[[f=u[w=0]||0,c]]=ae[[f,c]]||(o=[...t[f]],o[2]=(o[2]||220)*2**(c/12-1),c>0?ho(...o):[])))}y=A});return[_,C]}function Gh(t){Da=typeof t=="boolean"?t?1:0:t}function Bh(t){Fa=t}async function jh(){return new eo(await Box2D()),n(),zn(t,e),b;function t(){if(!It){b.step(),b.objects=b.objects.filter(s=>!s.destroyed);for(let s of b.objects)s.body&&(s.pos=b.vec2From(s.body.GetPosition()),s.angle=-s.body.GetAngle())}}function e(){(Fa||vt)&&b.world.DrawDebugData()}function n(){let i=new b.instance.JSDraw,r=l=>new Ie(l.get_r(),l.get_g(),l.get_b()),a=l=>r(b.instance.wrapPointer(l,b.instance.b2Color)),o=l=>a(l).scale(1,.8),c=(l,u)=>{let h=[];for(let d=u;d--;)h.push(b.vec2FromPointer(l+d*8));return h};i.DrawSegment=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),u=b.vec2FromPointer(u),On(l,u,.1,h,v(),0,!1)},i.DrawPolygon=function(l,u,h){h=o(h);let d=c(l,u);us(d,Sn,.1,h,v(),0,!1)},i.DrawSolidPolygon=function(l,u,h){h=o(h);let d=c(l,u);us(d,h,0,h,v(),0,!1)},i.DrawCircle=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),Oi(l,u*2,Sn,.1,h,!1)},i.DrawSolidCircle=function(l,u,h,d){d=o(d),l=b.vec2FromPointer(l),h=b.vec2FromPointer(h).scale(u),Oi(l,u*2,d,.1,d,!1),On(v(),h,.1,d,l,0,!1)},i.DrawTransform=function(l){l=b.instance.wrapPointer(l,b.instance.b2Transform);let u=b.vec2From(l.get_p()),h=-l.get_q().GetAngle(),d=v(1,0),f=Q(.75,0,0,.8),p=v(0,1),y=Q(0,.75,0,.8);On(v(),d,.1,f,u,h,!1),On(v(),p,.1,y,u,h,!1)},i.AppendFlags(b.instance.b2Draw.e_shapeBit),i.AppendFlags(b.instance.b2Draw.e_jointBit),b.world.SetDebugDraw(i)}}function Jh(t,e,n,s=32,i=2,r=0){jl(t,e,n,te,s,me,i,r,!1,!0)}function jl(t,e,n,s,i=1,r,a=.05,o=0,c=$,l,u){let h=n.offset(n.size),d=e.add(v(a-i*2)),f=v(i),p=e.scale(.5).subtract(f.scale(.5)),y=l?-1:1,x=l?-o:o;Ne(t,d,h,s,o,!1,r,c,l,u);for(let w=4;w--;){let A=w%2,S=p.multiply(v(A?w===1?1:-1:0,A?0:w?-1:1)),_=v(A?i:d.x,A?d.y:i),C=h.offset(n.size.multiply(v(w===1?1:w===3?-1:0,w===0?-y:w===2?y:0)));Ne(t.add(S.rotate(x)),_,C,s,o,!1,r,c,l,u)}for(let w=4;w--;){let A=w>1,S=w&&w<3,_=p.multiply(v(A?-1:1,S?-1:1)),C=h.offset(n.size.multiply(v(A?-1:1,S?y:-y)));Ne(t.add(_.rotate(x)),f,C,s,o,!1,r,c,l,u)}}function Nh(t,e,n,s=32,i=2,r=0){Jl(t,e,n,te,s,me,i,r,!1,!0)}function Jl(t,e,n,s,i=1,r,a=.05,o=0,c=$,l,u){let h=n.frame(0),d=n.frame(1),f=n.frame(2),p=e.add(v(a-i*2)),y=v(i),x=e.scale(.5).subtract(y.scale(.5)),w=l?-1:1,A=l?-o:o;Ne(t,p,f,s,o,!1,r,c,l,u);for(let S=4;S--;){let _=o+S*oe/2,C=S%2,k=x.multiply(v(C?S===1?1:-1:0,C?0:S?-w:w)),L=v(C?p.y:p.x,i);Ne(t.add(k.rotate(A)),L,d,s,_,!1,r,c,l,u)}for(let S=4;S--;){let _=o+S*oe/2,C=!S||S>2,k=S>1,L=x.multiply(v(C?-1:1,k?-w:w));Ne(t.add(L.rotate(A)),y,h,s,_,!1,r,c,l,u)}}function zh(t,e=1,n=0,s=te,i=0,r=!1,a=0,o=me,c=$,l=!1,u){let h=Nl(v(),e,n,0,r);us(h,s,a,o,t,i,c,l,u)}function Nl(t,e=1,n=0,s=0,i=!1,r=ti){m(I(t),"pos must be a vec2"),m(O(e)&&O(n),"size and percent must be numbers");let a=pt(n*4,4);a>=2&&(s+=oe),a=a<=2?a-1:3-a,i&&(a=-a,s+=oe);let o=[],c=le(3,r>>1),l=e/2;for(let u=0;u<=c;u++){let h=u/c*oe;o.push(v(l*be(h),l*pe(h)).rotate(s).add(t))}for(let u=c;u>=0;u--){let h=u/c*oe;o.push(v(l*be(h),-l*a*pe(h)).rotate(s).add(t))}return o}function zc(t){return t&&typeof t.lerp=="function"}function Uh(t,e,n,s,i=1,r={}){m(t!=null&&typeof t=="object","tweenProperty target must be an object"),m(ee(e)&&e.length>0,"tweenProperty propertyPath must be a non-empty string");let a=e.split("."),o=a.pop(),c=l=>{let u=t;for(let h of a)u=u[h];u[o]=l};return new to(c,n,s,i,r)}function zl(t){t.loopRemaining!==1/0&&t.loopRemaining<=1||(t.loopRemaining!==1/0&&(t.loopRemaining-=1),t.life=t.duration,t.thenCallback=()=>zl(t),at.push(t),t.callback(t.interp(t.duration)))}function Ul(t){if(t.loopRemaining!==1/0&&t.loopRemaining<=1)return;t.loopRemaining!==1/0&&(t.loopRemaining-=1);let e=t.start;t.start=t.end,t.end=e,t.life=t.duration,t.thenCallback=()=>Ul(t),at.push(t),t.callback(t.interp(t.duration))}function Vl(t,e){t===void 0?(t=ct-Jc,e=xn-Nc,Jc=ct,Nc=xn):e===void 0&&(e=t);for(let n=at.length;n--;){let s=at[n];if(s.paused)continue;let i=s.useRealTime?e:t;if(!(i<=0))if(s.life-=i,s.life>0)s.callback(s.interp(s.life));else{s.callback(s.interp(0)),at.splice(n,1);let r=s.thenCallback;s.thenCallback=void 0,r&&r()}}}function Vh(){for(let t of at)t.thenCallback=void 0;at.length=0}var Ti,Ai,sd,Vr,Re,qr,Uc,ct,xn,It,Qo,Et,ki,Vc,In,tr,We,Hc,io,$c,Ut,pn,vt,wt,Dn,Fn,ls,nr,Vt,St,oe,he,Oe,Fs,Ci,de,le,ht,Qc,Zc,pe,be,el,Hr,or,ge,Ie,te,Sn,me,kt,vd,Xr,wd,ll,ul,Td,dl,fl,Ad,Dt,Be,ue,ie,Qr,oo,mn,ts,Ms,ns,ss,Zr,jn,yn,ei,ea,K,$,ti,ro,ao,co,lo,ta,na,sa,ia,oa,Wt,tt,Ri,uo,ra,Ls,Ln,vn,aa,At,ys,Un,gs,bs,ni,Tn,st,ca,Os,Pi,si,it,Gn,la,ua,Qt,Y,Se,Fe,Yt,fn,Mt,Ht,z,wn,Ft,Gt,Bt,Zt,If,vl,Ii,Nt,Ze,ha,Rt,pa,Di,rs,hn,ma,is,Ce,mt,re,Pt,Pn,Zo,ds,yt,Jn,Fi,ci,$t,un,Al,Sa,kl,zs,Mn,fs,Fc,Gi,Ae,Kt,xs,Vs,Bi,bn,Bn,Ji,qs,Ws,ur,wh,Ni,fe,g,Aa,zi,Ui,Nn,Hn,ps,lt,dr,as,qe,Hs,Ge,Ds,fr,hr,ka,Vi,pr,qi,Ca,Rl,Th,po,Pl,cs,Rn,Wi,os,Hi,Oa,Xs,wi,$i,vi,Yi,Ks,gr,br,Ue,xr,se,Sr,vr,wr,E,Da,Tr,gt,Xi,Ar,kr,Qs,Cr,_r,Er,Rr,b,Fa,Zs,Ki,Pr,Mr,Qi,ot,Lr,Zi,Or,Ir,Dr,Fr,Gr,Br,jr,Jr,Nr,zr,eo,at,Jc,Nc,to,no,qh,er,so,Ur,Wl=Kl(()=>{"use strict";Ti="LittleJS",Ai="1.18.19",sd=60,Vr=.016666666666666666,Re=[],qr=[],Uc=0,ct=0,xn=0,It=!1;Qo=0,Et=0,ki=0,Vc=!0,In=[],tr=class{constructor(e,n,s,i){this.update=e,this.render=n,this.glContextLost=s,this.glContextRestored=i}};We=!0,Hc=.5,io=!0,$c="Escape",Ut=!1,pn=[],vt=!1,wt=!1,Dn=!1,Fn=!1,ls=!1;oe=Math.PI,he=Math.abs,Oe=Math.floor,Fs=Math.ceil,Ci=Math.round,de=Math.min,le=Math.max,ht=t=>Math.sign(t),Qc=(...t)=>Math.hypot(...t),Zc=t=>Math.log2(t),pe=Math.sin,be=Math.cos,el=Math.tan,Hr=Math.atan2;or=class{constructor(e=123456789){m(e!==0,"RandomGenerator seed must be non-zero (xorshift is fixed at 0)"),this.seed=e}float(e=1,n=0){return this.seed^=this.seed<<13,this.seed^=this.seed>>>17,this.seed^=this.seed<<5,n+(e-n)*((this.seed>>>0)/2**32)}int(e,n=0){return Oe(this.float(e,n))}bool(e=.5){return this.float().5?1:-1}floatSign(e=1,n=0){let s=de(e,n),r=le(e,n)-s,a=this.float(r*2);return ae?this.scale(e/n):this.copy()}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.x}reflect(e,n=1){return this.subtract(e.scale((1+n)*this.dot(e)))}angle(){return Hr(this.x,this.y)}setAngle(e=0,n=1){return rt(e),rt(n),this.x=n*pe(e),this.y=n*be(e),this}rotate(e){rt(e);let n=be(-e),s=pe(-e);return new t(this.x*n-this.y*s,this.x*s+this.y*n)}setDirection(e,n=1){return rt(e),rt(n),e=pt(e,4),m(e===0||e===1||e===2||e===3,"Vector2.setDirection() direction must be an integer between 0 and 3."),this.x=e%2?e-1?-n:n:0,this.y=e%2?0:e?-n:n,this}direction(){return he(this.x)>he(this.y)?this.x<0?3:1:this.y<0?2:0}abs(){return new t(he(this.x),he(this.y))}floor(){return new t(Oe(this.x),Oe(this.y))}snap(e){return rt(e),new t(Oe(this.x*e)/e,Oe(this.y*e)/e)}mod(e=1){return new t(pt(this.x,e),pt(this.y,e))}area(){return he(this.x*this.y)}lerp(e,n){Ic(e),rt(n);let s=X(n);return new t(e.x*s+this.x*(1-s),e.y*s+this.y*(1-s))}arrayCheck(e){return this.x>=0&&this.y>=0&&this.x(u=pt(u,1))*6<1?c+(l-c)*6*u:u*2<1?l:u*3<2?c+(l-c)*(4-u*6):c;return this.r=o(a,r,e+1/3),this.g=o(a,r,e),this.b=o(a,r,e-1/3),this.a=i,Rs(this),this}HSLA(){let e=X(this.r),n=X(this.g),s=X(this.b),i=X(this.a),r=le(e,n,s),a=de(e,n,s),o=(r+a)/2,c=0,l=0;if(r!==a){let u=r-a;l=o>.5?u/(2-r-a):u/(r+a),e===r?c=(n-s)/u+(n((s=X(s)*255|0)<16?"0":"")+s.toString(16);return"#"+n(this.r)+n(this.g)+n(this.b)+(e?n(this.a):"")}setHex(e){if(m(ee(e),"Color hex code must be a string"),m(e[0]==="#","Color hex code must start with #"),m([4,5,7,9].includes(e.length),"Invalid hex"),e.length<6){let n=s=>X(parseInt(e[s],16)/15);this.r=n(1),this.g=n(2),this.b=n(3),this.a=e.length===5?n(4):1}else{let n=s=>X(parseInt(e.slice(s,s+2),16)/255);this.r=n(1),this.g=n(3),this.b=n(5),this.a=e.length===9?n(7):1}return Rs(this),this}rgbaInt(){let e=X(this.r)*255|0,n=X(this.g)*255<<8,s=X(this.b)*255<<16,i=X(this.a)*255<<24;return e+n+s+i}isValid(){return O(this.r)&&O(this.g)&&O(this.b)&&O(this.a)}},te=ut(Q()),Sn=ut(Q(1,1,1,0)),me=ut(Q(0,0,0)),kt=ut(Q(0,0,0,0)),vd=ut(Q(.5,.5,.5)),Xr=ut(Q(1,0,0)),wd=ut(Q(1,.5,0)),ll=ut(Q(1,1,0)),ul=ut(Q(0,1,0)),Td=ut(Q(0,1,1)),dl=ut(Q(0,0,1)),fl=ut(Q(.5,0,1)),Ad=ut(Q(1,0,1)),Dt=class{constructor(e,n=!1){m(e===void 0||O(e),"Constructed Timer is invalid.",e),this.useRealTime=n;let s=this.getGlobalTime();this.time=e===void 0?void 0:s+e,this.setTime=e}set(e=0){m(O(e),"Timer is invalid.",e);let n=this.getGlobalTime();this.time=n+e,this.setTime=e}setUseRealTime(e=!0){m(!this.isSet(),"Cannot change global time setting while timer is set."),this.useRealTime=e}unset(){this.time=void 0}isSet(){return this.time!==void 0}active(){return this.getGlobalTime()=this.time}get(){return this.isSet()?this.getGlobalTime()-this.time:0}getPercent(){return this.isSet()?this.setTime?1-He(this.time-this.getGlobalTime(),0,this.setTime):1:0}getSetTime(){return this.isSet()?this.setTime:0}getGlobalTime(){return this.useRealTime?xn:ct}toString(){return this.isSet()?he(this.get())+" seconds "+(this.get()<0?"before":"after"):"unset"}valueOf(){return this.get()}};Be=v(),ue=0,ie=32,Qr=1,oo=!0,mn=kt,ts=v(1920,1080),Ms=0,ns=0,ss=v(),Zr=!1,jn=!0,yn=1,ei="arial",ea=!1,K=!1,$=!0,ti=32,ro=v(16),ao=0,co=0,lo=!0,ta=1,na=1,sa=1,ia=0,oa=.8,Wt=1,tt=v(),Ri=1,uo=!0,ra=!0,Ls=!0,Ln=!0,vn=!1,aa=!1,At=0,ys=4,Un=!0,gs=0,bs=!1,ni=!0,Tn=!1,st=100,ca=.3,Os=3,Pi=0,si=!0,it=!0,Gn=.3,la=40,ua=.7;Qt=class t{constructor(e=v(),n=v(1),s,i=0,r=te,a=0){m(I(e),"object pos must be a vec2"),m(I(n),"object size must be a vec2"),m(!s||s instanceof Bt,"object tileInfo should be a TileInfo or undefined"),m(typeof i=="number"&&isFinite(i),"object angle should be a number"),m(Z(r),"object color should be a valid rgba color"),m(typeof a=="number","object renderOrder should be a number"),this.pos=e.copy(),this.size=n.copy(),this.drawSize=void 0,this.tileInfo=s,this.angle=i,this.color=r.copy(),this.additiveColor=void 0,this.mirror=!1,this.destroyed=!1,this.mass=ta,this.damping=na,this.angleDamping=sa,this.restitution=ia,this.friction=oa,this.gravityScale=1,this.renderOrder=a,this.velocity=v(),this.angleVelocity=0,this.spawnTime=ct,this.children=[],this.clampSpeed=!0,this.groundObject=void 0,this.parent=void 0,this.localPos=v(),this.localAngle=0,this.collideTiles=!1,this.collideSolidObjects=!1,this.isSolid=!1,this.collideRaycast=!1,Re.push(this)}updateTransforms(){let e=this.parent;if(e){let n=e.getMirrorSign(),s=this.localPos,i=e.pos,r=s.x*n,a=s.y,o=e.angle;if(o){let c=be(-o),l=pe(-o);this.pos.set(r*c-a*l+i.x,r*l+a*c+i.y)}else this.pos.set(r+i.x,a+i.y);this.angle=n*this.localAngle+o}for(let n of this.children)n.updateTransforms()}updatePhysics(){if(m(!this.parent),this.destroyed)return;this.clampSpeed&&(this.velocity.x=X(this.velocity.x,-Wt,Wt),this.velocity.y=X(this.velocity.y,-Wt,Wt));let e=this.pos.copy();if(this.velocity.x*=this.damping,this.velocity.y*=this.damping,this.mass&&(this.velocity.x+=tt.x*this.gravityScale,this.velocity.y+=tt.y*this.gravityScale),this.pos.x+=this.velocity.x,this.pos.y+=this.velocity.y,this.angle+=this.angleVelocity*=this.angleDamping,m(this.angleDamping>=0&&this.angleDamping<=1),m(this.damping>=0&&this.damping<=1),!lo||!this.mass)return;let n=this.velocity.y<0&&tt.y<0||this.velocity.y>0&&tt.y>0;if(this.groundObject){let s=le(this.friction,this.groundObject.friction),i=this.groundObject.velocity.x;this.velocity.x=i+(this.velocity.x-i)*s,this.groundObject=void 0}if(this.collideSolidObjects)for(let i of qr){if(i.destroyed||i.parent||i===this||!this.isSolid&&!i.isSolid||!this.isOverlappingObject(i))continue;let r=this.collideWithObject(i),a=i.collideWithObject(this);if(!r||!a)continue;if(Ei(e,this.size,i.pos,i.size)){let d=e.subtract(i.pos),f=d.length(),y=f<.001?v(0,1):d.scale(.001/f);this.velocity=this.velocity.add(y),i.mass&&(i.velocity=i.velocity.subtract(y)),vt&&sr(this.pos,this.size,i.pos,i.size,"#f00");continue}let o=this.size.add(i.size),c=(e.y-i.pos.y)*2>o.y+tt.y,l=he(e.y-i.pos.y)*20?-1:1)>0?Oe(e.y-this.size.y/2+1)+this.size.y/2+.001:Fs(e.y+this.size.y/2-1)-this.size.y/2-.001;if(he(u-this.pos.y)<.1&&!dn(v(this.pos.x,u),this.size,this)){this.pos.y=u,vt&&_e(this.pos,this.size,"#ff0");return}this.pos.x=e.x,this.velocity.x*=-a}if(r||!i){if(n){let c=this.size.y/2+1e-4;this.pos.y=tt.y<0?Oe(e.y-this.size.y/2)+c:Fs(e.y+this.size.y/2)-c,this.groundObject=s}else this.pos.y=e.y,this.groundObject=void 0;this.velocity.y*=-a}vt&&_e(this.pos,this.size,"#f00")}}}update(){}render(){Ne(this.pos,this.drawSize||this.size,this.tileInfo,this.color,this.angle,this.mirror,this.additiveColor)}renderLight(){}destroy(e=!1){var n;if(!this.destroyed){this.destroyed=!0,(n=this.parent)==null||n.removeChild(this);for(let s of this.children)s.parent=void 0,s.destroy(e)}}localToWorld(e){return this.pos.add(e.rotate(this.angle))}worldToLocal(e){return e.subtract(this.pos).rotate(-this.angle)}localToWorldVector(e){return e.rotate(this.angle)}worldToLocalVector(e){return e.rotate(-this.angle)}collideWithTile(e,n){return e>0}collideWithObject(e){return!0}getUp(e=1){return v().setAngle(this.angle,e)}getRight(e=1){return v().setAngle(this.angle+oe/2,e)}getAliveTime(){return ct-this.spawnTime}getSpeed(){return this.velocity.length()}applyAcceleration(e){this.mass&&(this.velocity=this.velocity.add(e))}applyAngularAcceleration(e){this.mass&&(this.angleVelocity+=e)}applyForce(e){this.mass&&this.applyAcceleration(e.scale(1/this.mass))}getMirrorSign(){return this.mirror?-1:1}addChild(e,n=v(),s=0){return m(!this.destroyed,"cannot add child to destroyed object"),this.destroyed||(m(!e.parent&&!this.children.includes(e)),m(e instanceof t,"child must be an EngineObject"),m(e!==this,"cannot add self as child"),this.children.push(e),e.parent=this,e.localPos=n.copy(),e.localAngle=s,e.updateTransforms()),e}removeChild(e){m(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}isOverlappingObject(e){return this.isOverlapping(e.pos,e.size)}isOverlapping(e,n=v()){return Ei(this.pos,this.size,e,n)}setCollision(e=!0,n=!0,s=!0,i=!0){m(e||!n,"solid objects must be set to collide"),this.collideSolidObjects=e,this.isSolid=n,this.collideTiles=s,this.collideRaycast=i}toString(){let e="type = "+this.constructor.name;return(this.pos.x||this.pos.y)&&(e+=`
+pos = `+this.pos),(this.velocity.x||this.velocity.y)&&(e+=`
+velocity = `+this.velocity),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.angle&&(e+=`
+angle = `+this.angle.toFixed(3)),this.color&&(e+=`
+color = `+this.color),e}renderDebugInfo(){if(!We)return;let e=this.collideTiles||this.collideSolidObjects||this.isSolid;if(!e&&!this.parent)return;let n=v(le(this.size.x,.2),le(this.size.y,.2)),s=Q(this.collideTiles?1:0,this.collideSolidObjects?1:0,this.isSolid?1:0,.5);_e(this.pos,n,s,0,this.angle,e),this.parent&&_e(this.pos,n.scale(.8),Q(1,1,1,.5),0,this.angle),this.parent&&Lt(this.pos,this.parent.pos,Q(1,1,1,.5),.5)}},z=v(),wn=[];Bt=class t{constructor(e=v(),n=ro,s=wn[0],i=ao,r=co){this.pos=e.copy(),this.size=n.copy(),this.padding=i,this.textureInfo=s,this.bleed=r}offset(e){return new t(this.pos.add(e),this.size,this.textureInfo,this.padding,this.bleed)}frame(e){m(typeof e=="number");let n=this.size.x+this.padding*2,s=e*n;return m(s+this.size.x<=this.textureInfo.size.x,"frame extends beyond texture width!"),this.offset(new ge(s))}setFullImage(e=this.textureInfo){return this.textureInfo=e,this.pos=new ge,this.size=e.size.copy(),this.bleed=this.padding=0,this}tile(e){return ii(e,this.size,this.textureInfo,this.padding,this.bleed)}},Zt=class{constructor(e,n=!0,s=!1){this.image=e,this.size=e?v(e.width,e.height):v(),this.sizeInverse=e?v(1/e.width,1/e.height):v(),this.glTexture=void 0,this.wrap=s,n&&this.createWebGLTexture()}createWebGLTexture(){kh(this)}destroyWebGLTexture(){Ch(this)}hasWebGL(){return!!this.glTexture}setWrap(e=!0){this.wrap=e,Ol(this.glTexture,e)}};If=0;Ii=class{constructor(e){m(!!e,"tileInfo is required for ImageFont"),this.tileInfo=e.frame(0)}drawText(e,n,s=1,i,r,a,o){m(I(s)||typeof s=="number","size must be a vec2 or number"),typeof s=="number"?(m(s>0),s*=ie,s=new ge(s,s)):s=s.scale(ie),this.drawTextScreen(e,qn(n),s,i,r,a,o)}drawTextScreen(e,n,s,i=!0,r=te,a=$,o){m(ee(e),"text must be a string"),m(I(n),"pos must be a vec2"),m(I(s)||typeof s=="number","size must be a vec2 or number"),m(Z(r),"color must be a color"),s=typeof s=="number"?new ge(s,s):s;let c=new ge,l=this.tileInfo,u=l.padding,h=l.size.x+u*2,d=l.size.y+u*2,f=l.textureInfo.size.x/h|0;(e+"").split(`
+`).forEach((p,y)=>{let x=i?(p.length-1)*s.x/2:0;for(let w=p.length;w--;){let A=p.charCodeAt(w),S=A<32||A>127?95:A-32,_=S%f,C=S/f|0;l.pos.x=_*h+u,l.pos.y=C*d+u,c.x=n.x+w*s.x-x|0,c.y=n.y+y*s.y|0,Ne(c,s,l,r,0,!1,void 0,a,!0,o)}})}};Nt=v(),Ze=v(),ha=v(),Rt=v(),pa=0,Di=!0,rs=!1,hn="mouse",ma=6,is=!0,Ce=0,mt=!K&&window.ontouchstart!==void 0;re=[[]],Pt=[],Pn=[],Zo=[],ds=new Dt,yt=[],Jn=[],Fi=[],ci=[],$t=new Map,zs=[],fs=!0;Gi="http://www.w3.org/2000/svg";Ae=new AudioContext,xs=44100;Vs=class{constructor(e,n,s=la,i=ua,r){var a;if(!(!it||K)){if(m(!e||Tt(e)||ee(e),"asset must be a file name or zzfx array"),m(n===void 0||O(n),"randomness must be a number"),m(n===void 0||n>=0&&n<=1,"randomness must be between 0 and 1"),m(O(s),"range must be a number"),m(O(i),"taper must be a number"),this.range=s,this.taper=i,this.randomness=n!=null?n:0,this.sampleRate=xs,this.loadedPercent=0,this.onloadCallback=r,Tt(e)){let o=e.slice(),c=n!=null?n:.05,l=1;this.randomness=(a=o[l])!=null?a:c,o[l]=0,this.sampleChannels=[ho(...o)],this.loadedPercent=1,r==null||r(this)}else if(typeof e=="string"){let o=e;this.loadSound(o)}}}play(e,n=1,s=1,i=1,r=!1,a=!1){if(m(!e||I(e),"pos must be a vec2"),m(O(n),"volume must be a number"),m(O(s),"pitch must be a number"),m(O(i),"randomnessScale must be a number"),!it||K||!this.sampleChannels)return;let o;if(e){let u=this.range;if(u){let h=Be.distanceSquared(e);if(h>u*u)return;n*=He(h**.5,u,u*this.taper)}o=qn(e).x*2/Y.width-1}let c=s+s*this.randomness*i*Te(-1,1),l=new Bi(this,n,c,o,r,a);return We&&ls&&e&&(et(e,.5,"#0ff",.5,!0),this.range&&(et(e,2*this.range,"#0ff",.5),et(e,2*this.range*this.taper,"#0ff",.5)),es("vol "+n.toFixed(2)+" pitch "+c.toFixed(2),e,.5,"#0ff",.5)),l}playMusic(e=1,n=!0,s=!1){return this.play(void 0,e,1,0,n,s)}playNote(e=0,n,s){m(O(e),"semitoneOffset must be a number");let i=_l(e,1);return this.play(n,s,i,0)}getDuration(){var e,n;return((n=(e=this.sampleChannels)==null?void 0:e[0])==null?void 0:n.length)/this.sampleRate||0}isLoaded(){return this.loadedPercent===1}async loadSound(e){var c;let n=await fetch(e);if(!n.ok)throw new Error(`Failed to load sound from ${e}: ${n.status} ${n.statusText}`);let s=await n.arrayBuffer(),i=await Ae.decodeAudioData(s),r=i.numberOfChannels,a=1e5,o=[];for(let l=0;lsetTimeout(x,0));let f=de(d+a,h);for(;d=0,"Sound volume must be positive or zero"),m(s>=0,"Sound rate must be positive or zero"),m(O(i),"Sound pan must be a number"),this.sound=e,this.volume=n,this.rate=s,this.pan=i,this.loop=r,this.pausedTime=0,this.startTime=void 0,this.gainNode=void 0,this.source=void 0,this.onendedCallback=o=>{o===this.source&&(this.source=void 0)},a||this.start()}start(e=0){m(e>=0,"Sound start offset must be positive or zero"),this.isPlaying()&&this.stop(),this.gainNode=Ae.createGain(),this.source=Ta(this.sound.sampleChannels,this.volume,this.rate,this.pan,this.loop,this.sound.sampleRate,this.gainNode,e,this.onendedCallback),this.source?(this.startTime=Ae.currentTime-e,this.pausedTime=void 0):(this.startTime=void 0,this.pausedTime=0)}setVolume(e){m(e>=0,"Sound volume must be positive or zero"),this.volume=e,this.gainNode&&(this.gainNode.gain.value=e)}stop(e=0){if(m(e>=0,"Sound fade time must be positive or zero"),this.isPlaying())if(e){let n=Ae.currentTime,s=n+e;this.gainNode.gain.cancelScheduledValues(n),this.gainNode.gain.setValueAtTime(this.volume,n),this.gainNode.gain.linearRampToValueAtTime(0,s),this.source.stop(s)}else this.source.stop();this.pausedTime=0,this.source=void 0,this.startTime=void 0}pause(){this.isPaused()||(this.pausedTime=this.getCurrentTime(),this.source.stop(),this.source=void 0,this.startTime=void 0)}resume(){this.isPaused()&&this.start(this.pausedTime)}isPlaying(){return!!this.source}isPaused(){return!this.isPlaying()}getCurrentTime(){if(!this.isPlaying())return this.pausedTime;let e=this.getDuration();return e?pt(Ae.currentTime-this.startTime,e):0}getDuration(){return this.rate?this.sound.getDuration()/this.rate:0}getSource(){return this.source}};bn=[];Bn=class{constructor(e,n=0,s=!1,i=new Ie){this.tile=e,this.direction=n,this.mirror=s,this.color=i.copy()}clear(){this.tile=this.direction=0,this.mirror=!1,this.color=new Ie}},Ji=class extends Qt{constructor(e,n,s=0,i=0,r=v(512),a=!0){var o;m(I(r),"canvasSize must be a Vector2"),super(e,n,void 0,s,te,i),this.canvas=K?void 0:new OffscreenCanvas(r.x,r.y),this.context=(o=this.canvas)==null?void 0:o.getContext("2d"),this.textureInfo=new Zt(this.canvas,a),this.mass=0}destroy(){this.destroyed||(this.textureInfo.destroyWebGLTexture(),super.destroy())}render(){this.draw(this.pos,this.size,this.color,this.angle,this.mirror,this.additiveColor)}draw(e,n,s=te,i=0,r=!1,a,o=!1,c){let l=new Bt().setFullImage(this.textureInfo),u=this.hasWebGL();Ne(e,n,l,s,i,r,a,u,o,c)}updateWebGL(){this.textureInfo.createWebGLTexture()}hasWebGL(){return $&&this.textureInfo.hasWebGL()}},qs=class extends Ji{constructor(e,n,s=ii(),i=0,r=!0){let a=s?n.multiply(s.size):n;if(super(e,n,0,i,a,r),this.tileInfo=void 0,this.data=[],this.isUsingWebGL=!1,K){this.render=()=>{},this.redraw=()=>{},this.redrawStart=()=>{},this.redrawEnd=()=>{},this.drawTileData=()=>{},this.redrawTileData=()=>{},this.drawLayerTile=()=>{},this.drawLayerRect=()=>{},this.drawTile=()=>{},this.drawRect=()=>{},this.clearLayerRect=()=>{};return}s&&(this.tileInfo=s.frame(0),this.tileInfo.bleed=0);for(let o=this.size.area();o--;)this.data.push(new Bn)}setData(e,n,s=!1){if(e=e.floor(),m(I(e),"layerPos must be a Vector2"),m(n instanceof Bn,"data must be a TileLayerData"),!e.arrayCheck(this.size)||(this.data[(e.y|0)*this.size.x+(e.x|0)]=n,!s))return;Fe===this.context?this.drawTileData(e):this.redrawTileData(e)}clearData(e,n=!1){this.setData(e,new Bn,n)}getData(e){return m(I(e),"layerPos must be a Vector2"),e.arrayCheck(this.size)?this.data[(e.y|0)*this.size.x+(e.x|0)]:void 0}update(){!$&&this.isUsingWebGL&&(this.isUsingWebGL=!1,this.redraw())}render(){m(Fe!==this.context,"must call redrawEnd() after drawing tiles!");let e=this.drawSize||this.size,n=this.pos.add(e.scale(.5));this.draw(n,this.size,this.color,this.angle,this.mirror,this.additiveColor)}onRedraw(){}redraw(){this.redrawStart(!0);for(let e=this.size.x;e--;)for(let n=this.size.y;n--;)this.drawTileData(v(e,n),!1);this.isUsingWebGL&&je(),this.onRedraw(),this.redrawEnd()}redrawStart(e=!1){var s,i;if(!this.context)return;m(Fe!==this.context),this.savedRenderSettings=[Fe,z,Be,ie,mn],Fe=this.context;let n=(i=(s=this.tileInfo)==null?void 0:s.size)!=null?i:v(1);z=this.size.multiply(n),mn=kt,Be=this.size.multiply(n).scale(.5),ie=1,this.isUsingWebGL=this.hasWebGL(),this.isUsingWebGL?Ps(this.textureInfo.glTexture,e):(this.context.imageSmoothingEnabled=!jn,e&&(this.canvas.width=z.x,this.canvas.height=z.y))}redrawEnd(){this.context&&(m(Fe===this.context),this.isUsingWebGL&&Ps(),[Fe,z,Be,ie,mn]=this.savedRenderSettings)}drawTileData(e,n=!0){var o,c;if(!this.context)return;m(Fe===this.context,"must call redrawStart() before drawing tiles");let s=(c=(o=this.tileInfo)==null?void 0:o.size)!=null?c:v(1),i=e.multiply(s);n&&this.clearLayerRect(i,s);let r=this.getData(e);if(!r||!r.tile)return;let a=this.tileInfo&&this.tileInfo.tile(r.tile);this.drawLayerTile(i,s,a,r.color,r.direction*oe/2,r.mirror)}redrawTileData(e,n=!0){this.context&&(m(Fe!==this.context,"redrawStart() should not be active when calling redrawTileData(), instead use drawTileData()"),this.redrawStart(),this.drawTileData(e,n),this.redrawEnd())}drawLayerTile(e,n=v(1),s,i=te,r=0,a,o){let c=e.add(n.scale(.5));Ne(c,n,s,i,r,a,o,this.isUsingWebGL)}drawLayerRect(e,n,s,i=0){this.drawLayerTile(e,n,void 0,s,i)}drawTile(e,n=v(1),s,i=new Ie,r=0,a=!1){e=e.subtract(this.pos).multiply(this.tileInfo.size),n=n.multiply(this.tileInfo.size),e.y=this.canvas.height-e.y;let o=z;z=v(this.canvas.width,this.canvas.height);let c=this.hasWebGL();c&&Ps(this.textureInfo.glTexture);let l=c?void 0:this.context;Ne(e,n,s,i,r,a,void 0,c,!0,l),c&&Ps(),z=o}drawRect(e,n,s,i){this.drawTile(e,n,void 0,s,i)}clearLayerRect(e,n){m(Fe===this.context,"must call redrawStart() before clearing tiles");let s=e.x,i=this.canvas.height-e.y-n.y;this.hasWebGL()?Gl(s,i,n.x,n.y):this.context.clearRect(s,i,n.x,n.y)}},Ws=class extends qs{constructor(e,n,s=ii(),i=0,r=!0){super(e,n.floor(),s,i,r),this.collisionData=[],this.initCollision(this.size),bn.push(this),this.isSolid=!0}destroy(){if(this.destroyed)return;let e=bn.indexOf(this);m(e>=0,"tile collision layer not found in array"),e>=0&&bn.splice(e,1),super.destroy()}initCollision(e){m(I(e),"size must be a Vector2"),this.size=e.floor(),this.collisionData=[],this.collisionData.length=e.area(),this.collisionData.fill(0)}setCollisionData(e,n=1){m(I(e),"layerPos must be a Vector2");let s=(e.y|0)*this.size.x+(e.x|0);e.arrayCheck(this.size)&&(this.collisionData[s]=n)}clearCollisionData(e){this.setCollisionData(e,0)}getCollisionData(e){m(I(e),"layerPos must be a Vector2");let n=(e.y|0)*this.size.x+(e.x|0);return e.arrayCheck(this.size)?this.collisionData[n]:0}collisionTest(e,n=new ge,s){m(I(e)&&I(n),"pos and size must be Vector2s"),m(!s||typeof s=="function"||s instanceof Qt,"callbackObject must be a function or EngineObject");let i=s?typeof s=="function"?(d,f)=>s(d,f):(d,f)=>s.collideWithTile(d,f):()=>!0,r=e.x-this.pos.x,a=e.y-this.pos.y;if(r+n.x/2<0||r-n.x/2>this.size.x||a+n.y/2<0||a-n.y/2>this.size.y)return!1;let o=le(r-n.x/2|0,0),c=le(a-n.y/2|0,0),l=de(le(r+n.x/2,o+1),this.size.x),u=de(le(a+n.y/2,c+1),this.size.y),h=new ge;for(let d=c;ds(l,u):(l,u)=>s.collideWithTile(l,u):l=>l>0,a=l=>{let u=this.getCollisionData(o.set(l.x-this.pos.x,l.y-this.pos.y));return u&&r(u,l)},o=new ge,c=il(e,n,a,i);if(wt&&c){let l=c.floor().add(v(.5));_e(l,v(1),"#f008"),Lt(e,n,"#00f",.02),Lt(e,c,"#f00",.02),Wr(c,"#0f0"),i&&Lt(c,c.add(i),"#ff0",.02)}return c}},ur=class extends Qt{constructor(e,n,s=0,i=0,r=100,a=oe,o,c=te,l=te,u=Sn,h=Sn,d=.5,f=.1,p=1,y=.1,x=.05,w=1,A=1,S=0,_=oe,C=.1,k=.2,L=!1,V=!1,ae=!0,ne=V?1e9:0,T=!1){super(e,v(),o,n,void 0,ne),this.emitCircle=typeof s=="number",this.emitSize=typeof s=="number"?v(s):s.copy(),this.emitTime=i,this.emitRate=r,this.emitConeAngle=a,this.colorStartA=c.copy(),this.colorStartB=l.copy(),this.colorEndA=u.copy(),this.colorEndB=h.copy(),this.randomColorLinear=ae,this.particleTime=d,this.sizeStart=f,this.sizeEnd=p,this.speed=y,this.angleSpeed=x,this.damping=w,this.angleDamping=A,this.gravityScale=S,this.particleConeAngle=_,this.fadeRate=C,this.randomness=k,this.collideTiles=L,this.additive=V,this.localSpace=T,this.trailScale=0,this.particleCreateCallback=void 0,this.particleDestroyCallback=void 0,this.particleCollideCallback=void 0,this.velocityInheritance=0,this.emitTimeBuffer=0,this.particles=[],this.previousAngle=this.angle,this.previousPos=this.pos.copy()}update(){if(m(this.angleDamping>=0&&this.angleDamping<=1),m(this.damping>=0&&this.damping<=1),this.velocityInheritance){let s=this.velocityInheritance;this.velocity.x=s*(this.pos.x-this.previousPos.x),this.velocity.y=s*(this.pos.y-this.previousPos.y),this.angleVelocity=s*(this.angle-this.previousAngle),this.previousAngle=this.angle,this.previousPos.x=this.pos.x,this.previousPos.y=this.pos.y}if(this.isActive()){if(this.emitRate&&Ri){let s=1/this.emitRate/Ri;for(this.emitTimeBuffer+=Vr;this.emitTimeBuffer>0;this.emitTimeBuffer-=s)this.emitParticle()}}else this.particles.length===0&&this.destroy(!0);let e=this.particles,n=0;for(let s=0;sA+A*Te(s,-s),r=i(this.particleTime),a=i(this.sizeStart),o=i(this.sizeEnd),c=i(this.speed),l=i(this.angleSpeed)*rl(),u=Te(this.emitConeAngle,-this.emitConeAngle),h=ir(this.colorStartA,this.colorStartB,this.randomColorLinear),d=ir(this.colorEndA,this.colorEndB,this.randomColorLinear),f=this.localSpace?u:this.angle+u,p=v(c*pe(f),c*be(f)),y=l;!this.localSpace&&this.velocityInheritance>0&&(p.x+=this.velocity.x,p.y+=this.velocity.y,y+=this.angleVelocity);let x=new Ni(this,e,n,h,d,r,a,o,p,y);return this.particles.push(x),(w=this.particleCreateCallback)==null||w.call(this,x),x}updatePhysics(){}render(){for(let e of this.particles)e.render()}isActive(){return!this.emitTime||this.getAliveTime()0&&(this.destroyed=!1,this.emitTime=-1))}},wh=new ge,Ni=class{constructor(e,n,s,i,r,a,o,c,l=v(),u=0){this.emitter=e,this.pos=n,this.angle=s,this.size=v(o),this.color=i.copy(),this.colorStart=i,this.colorEnd=r,this.lifeTime=a,this.sizeStart=o,this.sizeEnd=c,this.velocity=l,this.angleVelocity=u,this.spawnTime=ct,this.mirror=ol(),this.groundObject=void 0,this.destroyed=!1,this.tileInfo=e.tileInfo}update(){let e=this.emitter,n=e.damping,s=e.angleDamping,i=e.restitution,r=e.friction,a=e.gravityScale,o=e.collideTiles,c=e.particleCollideCallback;if(this.lifeTime>0&&ct-this.spawnTime>this.lifeTime){this.destroy();return}let l=this.pos.copy();if(this.velocity.x*=n,this.velocity.y*=n,this.pos.x+=this.velocity.x+=tt.x*a,this.pos.y+=this.velocity.y+=tt.y*a,this.angle+=this.angleVelocity*=s,!lo||!o)return;let u=this.velocity.lengthSquared();if(u>Wt*Wt){let d=Wt/u**.5;this.velocity.x*=d,this.velocity.y*=d}this.groundObject=void 0;let h=c?d=>{let f=ji(d);return f&&c(this,f,d)}:d=>ji(d)>0;if(h(this.pos)){let d=dn(this.pos);if(!h(l)){let f=h(v(this.pos.x,l.y)),p=h(v(l.x,this.pos.y)),y=le(i,d.restitution),x=le(r,d.friction);f&&(this.pos.x=l.x,this.velocity.x*=-y,this.velocity.y*=x),(p||!f)&&((this.velocity.y<0&&tt.y<0||this.velocity.y>0&&tt.y>0)&&(this.groundObject=d),this.pos.y=l.y,this.velocity.y*=-y,this.velocity.x*=x),vt&&_e(this.pos,this.size,"#f00")}}}destroy(){let e=this.emitter.particleDestroyCallback,n=this.colorEnd;this.color.set(n.r,n.g,n.b,n.a),this.size.set(this.sizeEnd,this.sizeEnd),this.destroyed=!0,e==null||e(this)}render(){let e=this.emitter,n=e.localSpace,s=e.additive,i=e.trailScale,r=e.fadeRate/2,a=this.lifeTime>0?de((ct-this.spawnTime)/this.lifeTime,1):1,o=1-a,c=o*this.sizeStart+a*this.sizeEnd,l=v(c),u=a1-r?(1-a)/r:1;this.color.r=o*this.colorStart.r+a*this.colorEnd.r,this.color.g=o*this.colorStart.g+a*this.colorEnd.g,this.color.b=o*this.colorStart.b+a*this.colorEnd.b,this.color.a=(o*this.colorStart.a+a*this.colorEnd.a)*u;let h=wh.set(this.pos.x,this.pos.y),d=this.angle;if(n){let f=e.angle,p=be(-f),y=pe(-f);h.set(e.pos.x+h.x*p-h.y*y,e.pos.y+h.x*y+h.y*p),d+=f}if(s&&js(),i){let f=n?this.velocity.rotate(e.angle):this.velocity,p=f.length();if(p){let y=p*i;l.y=le(l.x,y),d=Hr(f.x,f.y),Ne(h,l,this.tileInfo,this.color,d,this.mirror)}}else Ne(h,l,this.tileInfo,this.color,d,this.mirror);s&&js(!1),Dn&&_e(h,l,"#f005",0,d)}},Aa=!0,pr=!0,qi=5e5,Ca=11,Rl=Ca*4,Th=qi/Rl|0,po=3,Pl=po*4,cs=qi/Pl|0;Rn=!1,Wi=5,os=.5,Hi=v(640,80),Oa=!1,Xs={},wi=[];Yi=class{constructor(e,n,s="",i="\u{1F3C6}",r){m(e>=0&&!Xs[e]),this.id=e,this.name=n,this.description=s,this.icon=i,this.unlocked=!1,this.image=void 0,r&&((this.image=new Image).src=r),Xs[e]=this}unlock(){Oa||this.unlocked||(m($i,"save name must be set"),this.unlocked=!0,Ia(),wi.push(this))}render(e=0){let n=Se,s=de(Hi.x,Y.width),i=Hi.y,r=Y.width-s,a=-i*e,o=qt(0,0,.9);n.save(),n.beginPath(),n.fillStyle=o.toString(),n.strokeStyle=me.toString(),n.lineWidth=3,n.rect(r,a,s,i),n.fill(),n.stroke(),n.clip();let c=v(.1,.05).scale(i),l=i-2*c.x;this.renderIcon(v(r+c.x+l/2,a+i/2),l);let u=i*.5,h=i*.3,d=v(r+l+2*c.x,a+c.y*2+u/2),f=s-l-3*c.x;gn(this.name,d,u,me,0,void 0,"left",void 0,void 0,f),d.y=a+i-c.y*2-h/2,gn(this.description,d,h,me,0,void 0,"left",void 0,void 0,f),n.restore()}renderIcon(e,n){this.image?Se.drawImage(this.image,e.x-n/2,e.y-n/2,n,n):gn(this.icon,e,n*.7,me)}};gr=class extends Yi{constructor(e,n,s,i,r){super(e,n,s,i,r)}unlock(){super.unlock(),Ks&&Ks.unlockMedal(this.id)}},br=class{constructor(e,n,s){var c,l,u;m(!Ks,"there can only be one newgrounds object"),m(!n||s,"must provide cryptojs if there is a cipher"),Ks=this,this.app_id=e,this.cipher=n,this.cryptoJS=s,this.host=location?location.hostname:"";let i=new URL(location.href);if(this.session_id=i.searchParams.get("ngio_session_id"),!this.session_id)return;let r=this.call("Medal.getList");if(!r||!r.result||r.result.error){Rn&&Ee("Newgrounds session unavailable; skipping plugin init"),this.medals=[],this.scoreboards=[];return}this.medals=((c=r.result.data)==null?void 0:c.medals)||[],Rn&&Ee(this.medals);for(let h of this.medals){let d=Xs[h.id];d&&(d.image=new Image,d.image.src=h.icon,d.name=h.name,d.description=h.description,d.unlocked=h.unlocked,d.difficulty=h.difficulty,d.value=h.value,d.value&&(d.description=d.description+` (${d.value})`))}let a=this.call("ScoreBoard.getBoards");this.scoreboards=((u=(l=a==null?void 0:a.result)==null?void 0:l.data)==null?void 0:u.scoreboards)||[],Rn&&Ee(this.scoreboards);let o=60*1e3;setInterval(()=>this.call("Gateway.ping",0,!0),o)}unlockMedal(e){return this.call("Medal.unlock",{id:e},!0)}postScore(e,n){return this.call("ScoreBoard.postScore",{id:e,value:n},!0)}getScores(e,n,s=0,i=0,r=10){return this.call("ScoreBoard.getScores",{id:e,user:n,social:s,skip:i,limit:r})}logView(){return this.call("App.logView",{host:this.host},!0)}call(e,n,s=!1){let i={component:e,parameters:n};if(this.cipher){let l=this.cryptoJS,u=l.enc.Base64.parse(this.cipher),h=l.lib.WordArray.random(16),d=l.AES.encrypt(JSON.stringify(i),u,{iv:h});i.secure=l.enc.Base64.stringify(h.concat(d.ciphertext)),i.parameters=0}let r={app_id:this.app_id,session_id:this.session_id,call:i},a=new FormData;a.append("input",JSON.stringify(r));let o=new XMLHttpRequest;o.open("POST","https://newgrounds.io/gateway_v3.php",!Rn&&s);try{o.send(a)}catch(l){Rn&&Ee("newgrounds call failed",l);return}return Rn&&Ee(o.responseText),o.responseText&&JSON.parse(o.responseText)}},xr=class{constructor(e,n=!1,s=!1){m(!Ue,"Post process already initialized"),m(!(n&&s),"Post process cannot both include main canvas and use feedback texture"),Ue=this,e||(e="void mainImage(out vec4 c,vec2 p){c=texture(iChannel0,p/iResolution.xy);}"),this.shader=void 0,this.texture=void 0,this.vao=void 0,i(),zn(void 0,o,r,a);function i(){if(K)return;if(!$){console.warn("PostProcessPlugin: WebGL not enabled!");return}Ue.texture=mo(),Ue.shader=ms(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D iChannel0;uniform vec3 iResolution;uniform float iTime;out vec4 c;
+`+e+`
+void main(){mainImage(c,gl_FragCoord.xy);c.a=1.;}`),Ue.vao=g.createVertexArray(),g.bindVertexArray(Ue.vao),g.bindBuffer(g.ARRAY_BUFFER,as);let c=8,l=g.getAttribLocation(Ue.shader,"p");g.enableVertexAttribArray(l),g.vertexAttribPointer(l,2,g.FLOAT,!1,c,0)}function r(){Ue.shader=void 0,Ue.texture=void 0,Ee("PostProcessPlugin: WebGL context lost")}function a(){i(),Ee("PostProcessPlugin: WebGL context restored")}function o(){if(K||!$)return;je(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.useProgram(Ue.shader),g.bindVertexArray(Ue.vao),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!0),g.disable(g.BLEND),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,Ue.texture),n?(Yt.width=z.x,Yt.height=z.y,Ra(fn),fn.drawImage(Y,0,0),Y.width|=0,g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,Yt)):s||g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,fe);let c=l=>g.getUniformLocation(Ue.shader,l);g.uniform1i(c("iChannel0"),0),g.uniform1f(c("iTime"),ct),g.uniform3f(c("iResolution"),Y.width,Y.height,1),g.drawArrays(g.TRIANGLE_STRIP,0,4),s&&g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,fe),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!1),$s(!0)}}},Sr=class{constructor(e,n){m(!se,"LightSystemPlugin already initialized"),m(!Ue,"LightSystemPlugin must be created before PostProcessPlugin"),se=this,this.enabled=!0,this.ambientColor=(n||me).copy(),this.textureSize=e?e.copy():void 0,this.texture=void 0,this.lightShader=void 0,this.compositeShader=void 0,this.lightVAO=void 0,this.compositeVAO=void 0,s(),zn(void 0,i,r,a);function s(){if(K)return;if(!$){console.warn("LightSystemPlugin: WebGL not enabled!");return}se.textureSize||(se.textureSize=z.copy()),se.texture=g.createTexture(),g.bindTexture(g.TEXTURE_2D,se.texture),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,se.textureSize.x,se.textureSize.y,0,g.RGBA,g.UNSIGNED_BYTE,null),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,g.CLAMP_TO_EDGE),se.lightShader=ms(`#version 300 es
+precision highp float;uniform mat4 m;uniform vec2 lightPos;uniform float radius;in vec2 g;out vec2 vWorldPos;void main(){vec2 worldP=lightPos+(g-.5)*2.*radius;gl_Position=m*vec4(worldP,1,1);vWorldPos=worldP;}`,`#version 300 es
+precision highp float;uniform vec2 lightPos;uniform float radius;uniform float fadeRange;uniform vec4 color;in vec2 vWorldPos;out vec4 c;void main(){float dist=distance(vWorldPos,lightPos);float t=clamp((radius-dist)/max(fadeRange,1e-6),0.,1.);c=vec4(color.rgb*t*color.a,1.);}`),se.compositeShader=ms(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D s;uniform vec3 iResolution;out vec4 c;void main(){vec2 uv=gl_FragCoord.xy/iResolution.xy;c=vec4(texture(s,uv).rgb,1.);}`),se.lightVAO=g.createVertexArray(),g.bindVertexArray(se.lightVAO),g.bindBuffer(g.ARRAY_BUFFER,as);let o=g.getAttribLocation(se.lightShader,"g");g.enableVertexAttribArray(o),g.vertexAttribPointer(o,2,g.FLOAT,!1,8,0),se.compositeVAO=g.createVertexArray(),g.bindVertexArray(se.compositeVAO),g.bindBuffer(g.ARRAY_BUFFER,as);let c=g.getAttribLocation(se.compositeShader,"p");g.enableVertexAttribArray(c),g.vertexAttribPointer(c,2,g.FLOAT,!1,8,0)}function i(){if(K||!$||!se.enabled||!se.texture)return;je();let o=Hn,c=se.ambientColor;g.bindFramebuffer(g.FRAMEBUFFER,ka),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,se.texture,0),g.viewport(0,0,se.textureSize.x,se.textureSize.y),g.clearColor(c.r,c.g,c.b,c.a),g.clear(g.COLOR_BUFFER_BIT),js(),g.enable(g.BLEND),g.blendFunc(g.ONE,g.ONE);for(let u of Re)u.destroyed||u.renderLight();je(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,z.x,z.y),g.useProgram(se.compositeShader),g.bindVertexArray(se.compositeVAO),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,se.texture);let l=se.compositeShader;g.uniform1i(g.getUniformLocation(l,"s"),0),g.uniform3f(g.getUniformLocation(l,"iResolution"),Y.width,Y.height,1),g.blendFunc(g.DST_COLOR,g.ZERO),g.drawArrays(g.TRIANGLE_STRIP,0,4),lt&&g.bindTexture(g.TEXTURE_2D,lt),js(o),$s(!0)}function r(){se.texture=void 0,se.lightShader=void 0,se.compositeShader=void 0,se.lightVAO=void 0,se.compositeVAO=void 0,Ee("LightSystemPlugin: WebGL context lost")}function a(){s(),Ee("LightSystemPlugin: WebGL context restored")}}drawLight(e){if(K||!$||!this.lightShader)return;je(),g.useProgram(this.lightShader),g.bindVertexArray(this.lightVAO);let n=v(2*ie).divide(z),s=Be.rotate(-ue),i=v(-1).subtract(s.multiply(n)),r=be(ue),a=pe(ue),o=[n.x*r,n.y*a,0,0,-n.x*a,n.y*r,0,0,1,1,1,0,i.x,i.y,0,1],c=this.lightShader;g.uniformMatrix4fv(g.getUniformLocation(c,"m"),!1,o),g.uniform2f(g.getUniformLocation(c,"lightPos"),e.pos.x,e.pos.y),g.uniform1f(g.getUniformLocation(c,"radius"),e.radius),g.uniform1f(g.getUniformLocation(c,"fadeRange"),e.fadeRange);let l=e.color;g.uniform4f(g.getUniformLocation(c,"color"),l.r,l.g,l.b,l.a),g.drawArrays(g.TRIANGLE_STRIP,0,4),$s(!0)}},vr=class extends Qt{constructor(e,n,s,i){super(e,v(1),void 0,0,s),m(O(n)&&n>=0,"Light radius must be a non-negative number"),m(i===void 0||O(i)&&i>=0,"Light fadeRange must be a non-negative number when provided"),this.radius=n,this.fadeRange=i===void 0?n:i}render(){}renderLight(){se&&se.drawLight(this)}},wr=class extends Vs{constructor(e){super(void 0),!(!it||K)&&(this.randomness=0,this.sampleChannels=Bl(...e),this.sampleRate=xs)}playMusic(e=1,n=!0){return super.play(void 0,e,1,0,n)}};Da=0;Tr=class{constructor(e=Se){m(!E,"UI system already initialized"),E=this,this.activateOnPress=!1,this.defaultColor=te,this.defaultLineColor=me,this.defaultTextColor=me,this.defaultButtonColor=qt(0,0,.7),this.defaultHoverColor=qt(0,0,.9),this.defaultDisabledColor=qt(0,0,.3),this.defaultGradientColor=void 0,this.defaultLineWidth=4,this.defaultCornerRadius=0,this.defaultTextFitScale=.8,this.defaultFont=ei,this.defaultSoundPress=void 0,this.defaultSoundRelease=void 0,this.defaultSoundClick=void 0,this.defaultShadowColor=kt,this.defaultShadowBlur=5,this.defaultShadowOffset=v(5),this.nativeHeight=0,this.navigationObject=void 0,this.navigationTimer=new Dt(void 0,!0),this.navigationDelay=.2,this.navigationDirection=1,this.navigationMode=!1,this.uiObjects=[],this.uiContext=e,this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.confirmDialog=void 0,this._keyInputObject=void 0,this._onKeyDown=r=>{var a;return(a=this._keyInputObject)==null?void 0:a.onKeyDown(r)},zn(s,i);function n(r){let a,o;r.parent?(a=r.parent.nativePos,o=r.parent.size):(a=E.screenToNative(z.scale(.5)),o=E.nativeHeight?v(z.x*E.nativeHeight/z.y,E.nativeHeight):z);let c=r.anchor;r.nativePos=a.add(o.multiply(c).scale(.5)).subtract(r.size.multiply(c).scale(.5)).add(r.localPos)}function s(){E.activeObject&&!E.activeObject.visible&&(E.activeObject=void 0),E.lastHoverObject=E.hoverObject,E.hoverObject=void 0,Js(0)&&(E.navigationMode=!1,E.navigationObject=void 0),E.keyInputObject&&(E.activeObject=E.keyInputObject,E.hoverObject=E.keyInputObject,E.navigationMode=!1,E.navigationObject=void 0);let r=E.getNavigableObjects();if(!r.length)E.navigationObject=void 0;else if(!E.keyInputObject){if(r.includes(E.navigationObject)||(E.navigationObject=void 0),mt||E.navigationMode&&!E.navigationObject&&(E.navigationObject=r.find(o=>o.navigationAutoSelect)),!E.navigationTimer.active()){let o=ht(E.getNavigationDirection());if(o){let c;if(E.navigationObject){let l=r.indexOf(E.navigationObject),u=pt(l+o,r.length);c=r[u]}else if(c=r.find(l=>l.navigationAutoSelect),!c){let l=o>0?0:r.length-1;c=r[l]}E.navigationObject!==c&&(E.navigationMode=!0,E.hoverObject=void 0,E.navigationObject=c,E.navigationTimer.set(E.navigationDelay),c.soundPress&&c.soundPress.play())}}E.navigationObject&&E.getNavigationWasPressed()&&E.navigationObject.navigatePressed()}for(let o=E.uiObjects.length;o--;){let c=E.uiObjects[o];c.parent||a(c)}E.uiObjects=E.uiObjects.filter(o=>!o.destroyed);function a(o){if(!(o.destroyed||!o.visible)){n(o);for(let c=o.children.length;c--;){let l=o.children[c];l&&a(l)}o.destroyed||o.update()}}}function i(){let r=E.uiContext;if(r.save(),E.nativeHeight){let o=z.y/E.nativeHeight;r.translate(-o*z.x/2,0),r.scale(o,o),r.translate(z.x/2/o,0)}function a(o){if(o.visible){n(o),o.render();for(let c of o.children)a(c)}}if(E.uiObjects.forEach(o=>o.parent||a(o)),Da>0){let o=function(c,l=!0){l&&(l=!!c.visible),n(c),c.renderDebug(l);for(let u of c.children)o(u,l)};E.uiObjects.forEach(c=>c.parent||o(c))}r.restore()}}drawRect(e,n,s=te,i=0,r=me,a=0,o,c=me,l=0,u=v()){m(I(e),"pos must be a vec2"),m(I(n),"size must be a vec2"),m(Z(s),"color must be a color"),m(O(i),"lineWidth must be a number"),m(Z(r),"lineColor must be a color"),m(O(a),"cornerRadius must be a number");let h=E.uiContext;if(o){let d=h.createLinearGradient(e.x,e.y-n.y/2,e.x,e.y+n.y/2),f=s.toString();d.addColorStop(0,f),d.addColorStop(.5,o.toString()),d.addColorStop(1,f),h.fillStyle=d}else h.fillStyle=s.toString();(l||u.x||u.y)&&c.a>0&&(h.shadowColor=c.toString(),h.shadowBlur=l,h.shadowOffsetX=u.x,h.shadowOffsetY=u.y),h.beginPath(),a&&h.roundRect?h.roundRect(e.x-n.x/2,e.y-n.y/2,n.x,n.y,a):h.rect(e.x-n.x/2,e.y-n.y/2,n.x,n.y),h.fill(),h.shadowColor="#0000",i&&r.a>0&&(h.strokeStyle=r.toString(),h.lineWidth=i,h.stroke())}drawLine(e,n,s=E.defaultLineWidth,i=E.defaultLineColor){m(I(e),"posA must be a vec2"),m(I(n),"posB must be a vec2"),m(O(s),"lineWidth must be a number"),m(Z(i),"lineColor must be a color");let r=E.uiContext;r.strokeStyle=i.toString(),r.lineWidth=s,r.beginPath(),r.lineTo(e.x,e.y),r.lineTo(n.x,n.y),r.stroke()}drawTile(e,n,s,i=E.defaultColor,r=0,a=!1,o=me,c=0,l=v()){let u=E.uiContext;(c||l.x||l.y)&&o.a>0&&(u.shadowColor=o.toString(),u.shadowBlur=c,u.shadowOffsetX=l.x,u.shadowOffsetY=l.y),Ne(e,n,s,i,r,a,kt,!1,!0,u),u.shadowColor="#0000"}drawText(e,n,s,i=E.defaultColor,r=E.defaultLineWidth,a=E.defaultLineColor,o="center",c=E.defaultFont,l="",u=!0,h=void 0,d=me,f=0,p=v()){let y=E.uiContext;d.a>0&&(h&&gn(e,n.add(h),s.y,d,r,a,o,c,l,u?s.x:void 0,0,y),(f||p.x||p.y)&&(y.shadowColor=d.toString(),y.shadowBlur=f,y.shadowOffsetX=p.x,y.shadowOffsetY=p.y)),gn(e,n,s.y,i,r,a,o,c,l,u?s.x:void 0,0,y),y.shadowColor="#0000"}setupDragAndDrop(e,n,s,i){if(this._dragListeners)for(let[a,o]of this._dragListeners)document.removeEventListener(a,o);this._dragListeners=[];let r=(a,o)=>{let c=l=>{l.preventDefault(),a&&a(l)};document.addEventListener(o,c),this._dragListeners.push([o,c])};r(e,"drop"),r(n,"dragenter"),r(s,"dragleave"),r(i,"dragover")}screenToNative(e){if(!E.nativeHeight)return e;let n=z.y/E.nativeHeight,s=1/n,i=e.copy();return i.x+=n*z.x/2,i.x*=s,i.y*=s,i.x-=s*z.x/2,i}get keyInputObject(){return this._keyInputObject}set keyInputObject(e){let n=!!this._keyInputObject;this._keyInputObject=e,!n&&e?document.addEventListener("keydown",this._onKeyDown):n&&!e&&document.removeEventListener("keydown",this._onKeyDown)}destroyObjects(){for(let e of this.uiObjects)e.parent||e.destroy();this.uiObjects=this.uiObjects.filter(e=>!e.destroyed),this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.keyInputObject=void 0}getNavigableObjects(){function e(s){if(!(!s.visible||s.disabled)){s.isInteractive()&&s.navigationIndex!==void 0&&n.push(s);for(let i=s.children.length;i--;)e(s.children[i])}}let n=[];for(let s=E.uiObjects.length;s--;){let i=E.uiObjects[s];E.confirmDialog&&i!==E.confirmDialog||i.parent||e(i)}return n.sort((s,i)=>s.navigationIndex-i.navigationIndex),n}getNavigationDirection(){let e=E.navigationDirection===1,n=E.navigationDirection===2;if(rs){let l=Ns(0,Ce),u=cr(Ce);return n?-(l.y||u.y)||l.x||u.x:e?-(l.y||u.y):l.x||u.x}let s="ArrowUp",i="ArrowDown",r="ArrowLeft",a="ArrowRight";if(n)return Je(s)||Je(r)?-1:Je(i)||Je(a)?1:0;let o=e?s:r,c=e?i:a;return Je(o)?-1:Je(c)?1:0}getNavigationOtherDirection(){if(E.navigationDirection===2)return 0;let e=E.navigationDirection===1;if(rs){let i=Ns(0,Ce),r=cr(Ce);return e?i.x||r.x:i.y||r.y}let n=e?"ArrowLeft":"ArrowUp",s=e?"ArrowRight":"ArrowDown";return Je(n)?-1:Je(s)?1:0}getNavigationWasPressed(){return rs?ba(0,Ce):Ve("Space")||Ve("Enter")}showConfirmDialog(e="Are you sure?",n,s,i=v(500,250),r="Escape"){m(!E.confirmDialog);let a=E.navigationDirection;E.navigationDirection=2;let o=new gt(v(),i);E.confirmDialog=o,o.onRender=()=>{let f=qt(0,0,0,.7);E.drawRect(v(),v(1e9),f)},o.onUpdate=()=>{Ve(r)&&d()},o.isMouseOverlapping=()=>!0;let c=50,l=new Xi(v(0,-50),v(i.x-c,70),e);o.addChild(l);let u=new Qs(v(-80,50),v(120,70),"Yes");u.textHeight=40,u.navigationIndex=1,u.hoverColor=qt(0,1,.5),u.onClick=()=>{d(),n&&n()},o.addChild(u);let h=new Qs(v(80,50),v(120,70),"No");h.textHeight=40,h.navigationIndex=2,h.navigationAutoSelect=!0,h.onClick=()=>{d(),s&&s()},o.addChild(h);function d(){m(E.confirmDialog===o),o.destroy(),E.confirmDialog=void 0,E.navigationDirection=a,ai()}}},gt=class{constructor(e=v(),n=v()){var s,i;m(I(e),"ui object pos must be a vec2"),m(I(n),"ui object size must be a vec2"),this.localPos=e.copy(),this.nativePos=e.copy(),this.size=n.copy(),this.color=E.defaultColor.copy(),this.activeColor=void 0,this.text=void 0,this.disabledColor=E.defaultDisabledColor.copy(),this.disabled=!1,this.textColor=E.defaultTextColor.copy(),this.hoverColor=E.defaultHoverColor.copy(),this.lineColor=E.defaultLineColor.copy(),this.gradientColor=E.defaultGradientColor?E.defaultGradientColor.copy():void 0,this.lineWidth=E.defaultLineWidth,this.cornerRadius=E.defaultCornerRadius,this.font=E.defaultFont,this.fontStyle=void 0,this.textWidth=void 0,this.textHeight=void 0,this.textFitScale=E.defaultTextFitScale,this.textShadow=void 0,this.textLineColor=E.defaultLineColor.copy(),this.textLineWidth=0,this.visible=!0,this.children=[],this.parent=void 0,this.extraTouchSize=0,this.soundPress=E.defaultSoundPress,this.soundRelease=E.defaultSoundRelease,this.soundClick=E.defaultSoundClick,this.interactive=!1,this.dragActivate=!1,this.canBeHover=!0,this.shadowColor=(s=E.defaultShadowColor)==null?void 0:s.copy(),this.shadowBlur=E.defaultShadowBlur,this.shadowOffset=(i=E.defaultShadowOffset)==null?void 0:i.copy(),this.navigationIndex=void 0,this.navigationAutoSelect=!1,this.anchor=v(),E.uiObjects.push(this)}addChild(e){return m(!e.parent&&!this.children.includes(e)),this.children.push(e),e.parent=this,e}removeChild(e){m(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}destroy(){var e;if(!this.destroyed){E.activeObject===this&&(E.activeObject=void 0),E.hoverObject===this&&(E.hoverObject=void 0),E.lastHoverObject===this&&(E.lastHoverObject=void 0),E.navigationObject===this&&(E.navigationObject=void 0),E.keyInputObject===this&&(E.keyInputObject=void 0),this.destroyed=1,(e=this.parent)==null||e.removeChild(this);for(let n of this.children)n.parent=void 0,n.destroy();this.children.length=0}}isMouseOverlapping(){if(!Di)return!1;let e=mt?this.size.add(v(this.extraTouchSize||0)):this.size,n=E.screenToNative(Ze);return Ei(this.nativePos,e,n)}update(){if(this.onUpdate(),this.disabled&&(this===E.activeObject&&(E.activeObject=void 0),this===E.keyInputObject&&(E.keyInputObject=void 0)),E.keyInputObject)return;let e=E.lastHoverObject===this,n=this.isActiveObject(),s=Is(0),i=this.dragActivate?s:Js(0);this.canBeHover&&(E.navigationMode||(i||n||!s&&!mt)&&!E.hoverObject&&this.isMouseOverlapping()&&(E.hoverObject=this)),this.isHoverObject()&&(this.disabled||(i&&this.interactive&&((!this.dragActivate||!e||Js(0))&&this.onPress(),this.soundPress&&this.soundPress.play(),E.activeObject&&!n&&E.activeObject.onRelease(),E.activeObject=this,E.activateOnPress&&this.click(!this.soundPress)),E.activateOnPress||!s&&this.isActiveObject()&&this.interactive&&this.click()),i&&ya(0,0,0,1,0)),n&&(!s||this.dragActivate&&!this.isHoverObject())&&(this.onRelease(),this.soundRelease&&this.soundRelease.play(),E.activeObject=void 0),this.isHoverObject()!==e&&(this.isHoverObject()?this.onEnter():this.onLeave())}render(){if(this.onRender(),!this.size.x||!this.size.y)return;let e=this.isNavigationObject(),n=e?this.color:this.interactive&&this.isActiveObject()&&!this.disabled?this.color:this.lineColor,s=e?this.hoverColor:this.disabled?this.disabledColor:this.interactive?this.isActiveObject()?this.activeColor||this.hoverColor:this.isHoverObject()?this.hoverColor:this.color:this.color,i=this.lineWidth*(e?1.5:1);E.drawRect(this.nativePos,this.size,s,i,n,this.cornerRadius,this.gradientColor,this.shadowColor,this.shadowBlur,this.shadowOffset)}getTextSize(){return v(this.textWidth||this.textFitScale*this.size.x,this.textHeight||this.textFitScale*this.size.y)}navigatePressed(){this.click()}isHoverObject(){return E.hoverObject===this}isActiveObject(){return E.activeObject===this}isNavigationObject(){return E.navigationObject===this}isKeyInputObject(){return E.keyInputObject===this}isInteractive(){return this.interactive&&this.visible&&!this.disabled}toString(){let e="type = "+this.constructor.name;return this.text&&(e+=`
+text = `+this.text),(this.nativePos.x||this.nativePos.y)&&(e+=`
+nativePos = `+this.nativePos),(this.localPos.x||this.localPos.y)&&(e+=`
+localPos = `+this.localPos),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.color&&(e+=`
+color = `+this.color),e}renderDebug(e=!0){let n=e?this.isHoverObject()?ll:this.disabled?fl:this.interactive?Xr:dl:ul;E.drawRect(this.nativePos,this.size,kt,4,n)}click(e=!0){this.onClick(),e&&this.soundClick&&this.soundClick.play()}onUpdate(){}onRender(){}onEnter(){}onLeave(){}onPress(){}onRelease(){}onClick(){}onChange(){}},Xi=class extends gt{constructor(e,n,s="",i="center",r=E.defaultFont){super(e,n),m(ee(s),"ui text must be a string"),m(["left","center","right"].includes(i),"ui text align must be left, center, or right"),m(ee(r),"ui text font must be a string"),this.text=s,this.align=i,this.font=r,this.canBeHover=!1,this.color=kt,this.shadowColor=kt,this.gradientColor=void 0,this.lineWidth=0,this.textFitScale=1}render(){super.render();let e=this.getTextSize();E.drawText(this.text,this.nativePos,e,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow,this.shadowColor,this.shadowBlur,this.shadowOffset)}},Ar=class extends gt{constructor(e,n,s=""){super(e,n),m(ee(s),"ui text must be a string"),this.maxLength=0,this.text=s,this.interactive=!0,this.canBeHover=!0}click(){E.keyInputObject=this,this.onClick()}stopEditing(){this.isKeyInputObject()&&(this.soundRelease&&this.soundRelease.play(),E.activeObject=void 0,E.keyInputObject=void 0,this.onChange())}onKeyDown(e){let n=e.code,s=e.key;n==="Backspace"?this.text=this.text.slice(0,-1):n==="Enter"||n==="Escape"?this.stopEditing():s.length===1&&(!this.maxLength||this.text.lengththis.size.y,s=n?this.size.y:this.size.x,i=n?this.size.x:this.size.y,r=n?this.nativePos.x:this.nativePos.y,a=i-s,o=r-a/2,c=r+a/2,l=E.screenToNative(Ze);this.value=n?He(l.x,o,c):He(l.y,c,o)}else if(this.isNavigationObject()){let n=E.getNavigationOtherDirection();E.navigationTimer.active()||(this.value=X(this.value+n*.01))}this.value===e||this.onChange()}render(){super.render();let e=this.size.x>this.size.y,n=e?this.size.x:this.size.y,s=e?this.size.y:this.size.x;if(this.fillMode){let r=de(s,this.cornerRadius*2),a=nt(r,n,this.value),o=(a-n)*(e?.5:-.5),c=this.nativePos.add(e?v(o,0):v(0,o)),l=this.disabled?this.disabledColor:this.handleColor,u=e?v(a,this.size.y):v(this.size.x,a);E.drawRect(c,u,l,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}else{let r=X(e?this.value:1-this.value),a=(n-s)*(r-.5),o=this.nativePos.add(e?v(a,0):v(0,a)),c=this.disabled?this.disabledColor:this.handleColor,l=v(s);E.drawRect(o,l,c,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}let i=this.getTextSize();E.drawText(this.text,this.nativePos,i,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow)}navigatePressed(){this.value=this.value?0:1,this.onChange(),this.onRelease(),super.navigatePressed()}},Er=class extends gt{constructor(e,n,s,i=!1,r=!1,a=1){super(e,n||v()),m(ee(s),"video src must be a string"),m(O(a),"video volume must be a number"),this.color=me,this.cornerRadius=0,this.volume=a,this.video=document.createElement("video"),this.video.loop=r,this.video.volume=X(a*Gn),this.video.muted=!it,this.video.style.display="none",this.video.src=s,document.body.appendChild(this.video),i&&this.play()}async play(){try{await this.video.play()}catch{}}pause(){this.video.pause()}stop(){this.video.pause(),this.video.currentTime=0}isLoading(){return this.video.readyState=1,"ui layout columns must be a number >= 1"),m(O(s),"ui layout gap must be a number"),m(O(i),"ui layout padding must be a number"),this.columns=n,this.gap=s,this.padding=i,r&&(this.color=kt,this.gradientColor=void 0,this.lineWidth=0,this.shadowColor=kt),this.relayout()}addChild(e){return super.addChild(e),this.relayout(),e}removeChild(e){super.removeChild(e),this.relayout()}relayout(){let e=this.children.length;if(!e){this.size=v(this.padding*2);return}let n=this.columns,s=Fs(e/n),i=new Array(n).fill(0),r=new Array(s).fill(0);for(let d=0;d=0&&b.objects.splice(e,1),super.destroy()}updatePhysics(){}render(){this.tileInfo?super.render():this.drawFixtures(this.color,this.lineColor,this.lineWidth)}renderDebugInfo(){let e=!this.getIsAwake(),n=this.getBodyType()===b.bodyTypeStatic,s=Q(e?1:0,e?1:0,n?1:0,.5);this.drawFixtures(s)}drawFixtures(e=te,n=me,s=.1,i,r){this.getFixtureList().forEach(a=>{b.castShapeObject(a.GetShape()).GetType()!==b.instance.b2Shape.e_edge&&b.drawFixture(a,this.pos,this.angle,e,n,s,i,r)}),this.edgeLists.forEach(a=>ar(a,s,n,!1,this.pos,this.angle)),this.edgeLoops.forEach(a=>ar(a,s,n,!0,this.pos,this.angle))}beginContact(e){}endContact(e){}addShape(e,n=1,s=.2,i=0,r=!1){m(O(n),"density must be a number"),m(O(s),"friction must be a number"),m(O(i),"restitution must be a number");let a=new b.instance.b2FixtureDef;return a.set_shape(e),a.set_density(n),a.set_friction(s),a.set_restitution(i),a.set_isSensor(r),this.body.CreateFixture(a)}addBox(e=v(1),n=v(),s=0,i,r,a,o){m(I(e),"size must be a Vector2"),m(e.x>0&&e.y>0,"size must be positive"),m(I(n),"offset must be a Vector2"),m(O(s),"angle must be a number");let c=new b.instance.b2PolygonShape;return c.SetAsBox(e.x/2,e.y/2,b.vec2dTo(n),-s),this.addShape(c,i,r,a,o)}addPoly(e,n,s,i,r){m(Tt(e),"points must be an array");function a(c){m(3<=c.length&&c.length<=8);let l=b.instance._malloc(c.length*8);for(let d=0,f=0;d>2]=c[d].x,f+=4,b.instance.HEAPF32[l+f>>2]=c[d].y,f+=4;let u=b.instance.wrapPointer(l,b.instance.b2Vec2),h=new b.instance.b2PolygonShape;return h.Set(u,c.length),b.instance._free(l),h}let o=a(e);return this.addShape(o,n,s,i,r)}addRegularPoly(e=1,n=8,s,i,r,a){m(O(e)&&e>0,"diameter must be a positive number"),m(O(n)&&n>2,"sides must be a positive number greater than 2");let o=[],c=e/2;for(let l=n;l--;)o.push(v(c,0).rotate((l+.5)/n*oe*2));return this.addPoly(o,s,i,r,a)}addRandomPoly(e=1,n,s,i,r){m(O(e)&&e>0,"diameter must be a positive number");let a=Yr(3,9),o=[],c=e/2;for(let l=a;l--;)o.push(v(Te(c/2,c*1.5),0).rotate(l/a*oe*2));return this.addPoly(o,n,s,i,r)}addCircle(e=1,n=v(),s,i,r,a){m(O(e)&&e>0,"diameter must be a positive number"),m(I(n),"offset must be a Vector2");let o=new b.instance.b2CircleShape;return o.set_m_p(b.vec2dTo(n)),o.set_m_radius(e/2),this.addShape(o,s,i,r,a)}addEdge(e,n,s,i,r,a){m(I(e),"point1 must be a Vector2"),m(I(n),"point2 must be a Vector2");let o=new b.instance.b2EdgeShape;return o.Set(b.vec2dTo(e),b.vec2dTo(n)),this.addShape(o,s,i,r,a)}addEdgeList(e,n,s,i,r){m(Tt(e),"points must be an array");let a=[],o=[];for(let c=0;ce[pt(l,e.length)];for(let l=0;lthis.destroyFixture(e))}getCenterOfMass(){return b.vec2From(this.body.GetWorldCenter())}getLinearVelocity(){return b.vec2From(this.body.GetLinearVelocity())}getAngularVelocity(){return this.body.GetAngularVelocity()}getMass(){return this.body.GetMass()}getInertia(){return this.body.GetInertia()}getIsAwake(){return this.body.IsAwake()}getBodyType(){return this.body.GetType()}getSpeed(){return this.getLinearVelocity().length()}setTransform(e,n){this.pos=e,this.angle=n,this.body.SetTransform(b.vec2dTo(e),-n)}setPosition(e){this.setTransform(e,this.body.GetAngle())}setAngle(e){this.setTransform(b.vec2From(this.body.GetPosition()),e)}setLinearVelocity(e){this.body.SetLinearVelocity(b.vec2dTo(e))}setAngularVelocity(e){this.body.SetAngularVelocity(e)}setLinearDamping(e){this.body.SetLinearDamping(e)}setAngularDamping(e){this.body.SetAngularDamping(e)}setGravityScale(e=1){this.body.SetGravityScale(this.gravityScale=e)}setBullet(e=!0){this.body.SetBullet(e)}setAwake(e=!0){this.body.SetAwake(e)}setBodyType(e){this.body.SetType(e)}setSleepingAllowed(e=!0){this.body.SetSleepingAllowed(e)}setFixedRotation(e=!0){this.body.SetFixedRotation(e)}setCenterOfMass(e){this.setMassData(e)}setMass(e){this.setMassData(void 0,e)}setMomentOfInertia(e){this.setMassData(void 0,void 0,e)}resetMassData(){this.body.ResetMassData()}setMassData(e,n,s){let i=new b.instance.b2MassData;this.body.GetMassData(i),e!==void 0&&i.set_center(b.vec2dTo(e)),n!==void 0&&i.set_mass(n),s!==void 0&&i.set_I(s),this.body.SetMassData(i)}setFilterData(e=0,n=0,s=0){this.getFixtureList().forEach(i=>{let r=i.GetFilterData();r.set_categoryBits(e),r.set_maskBits(65535&~n),r.set_groupIndex(s)})}setSensor(e=!0){this.getFixtureList().forEach(n=>n.SetSensor(e))}applyForce(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyForce(b.vec2dTo(e),b.vec2dTo(n))}applyAcceleration(e,n){n||(n=this.getCenterOfMass()),this.setAwake();let s=e.scale(this.getMass());this.body.ApplyLinearImpulse(b.vec2dTo(s),b.vec2dTo(n))}applyImpulse(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyLinearImpulse(b.vec2dTo(e),b.vec2dTo(n))}applyTorque(e){this.setAwake(),this.body.ApplyTorque(e)}applyAngularAcceleration(e){this.setAwake(),this.body.ApplyAngularImpulse(e*this.getInertia())}applyAngularImpulse(e){this.setAwake(),this.body.ApplyAngularImpulse(e)}hasFixtures(){return!b.isNull(this.body.GetFixtureList())}getFixtureList(){let e=[];for(let n=this.body.GetFixtureList();!b.isNull(n);)e.push(n),n=n.GetNext();return e}hasJoints(){return!b.isNull(this.body.GetJointList())}getJointList(){let e=[];for(let n=this.body.GetJointList();!b.isNull(n);)e.push(n),n=n.get_next();return e}},Ki=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeStatic;super(e,n,s,i,r,o,a)}},Pr=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeKinematic;super(e,n,s,i,r,o,a)}},Mr=class extends Ki{constructor(e){m(e instanceof Ws,"tileLayer must be a TileCollisionLayer"),super(e.pos,e.size),this.tileLayer=e,this.addChild(e)}render(){}buildCollision(e=.2,n=0){this.destroyAllFixtures(),this.pos=this.tileLayer.pos.copy(),this.size=this.tileLayer.size.copy();let s=[],i=(a,o)=>a+o*this.size.x,r=(a,o)=>!s[i(a,o)]&&this.tileLayer.getCollisionData(v(a,o))>0;for(let a=0;ai.fractionr.pos.distanceSquared(e)0,"Tween duration must be > 0"),this.callback=e,this.start=n,this.end=s,this.duration=i,this.life=i,this.ease=r.ease||no.LINEAR,this.useRealTime=!!r.useRealTime,this.paused=!!r.paused,this.thenCallback=void 0,this.loopRemaining=0,at.push(this),e(this.interp(i))}setEase(e){return this.ease=e,this}then(e){return this.thenCallback=e,this.loopRemaining=0,this}loop(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>zl(this),this}pingPong(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>Ul(this),this}pause(){this.paused=!0}resume(){this.paused=!1}restart(){this.life=this.duration,this.paused=!1,at.indexOf(this)<0&&at.push(this),this.callback(this.interp(this.duration))}isActive(){return!this.paused&&at.indexOf(this)>=0}getPercent(){return He(this.duration-this.life,0,this.duration)}getValue(){return this.interp(this.life)}interp(e){let n=this.ease((this.duration-e)/this.duration);return zc(this.start)?this.start.lerp(this.end,n):this.start+(this.end-this.start)*n}stop(){let e=at.indexOf(this);e>=0&&at.splice(e,1),this.thenCallback=void 0}},no={LINEAR:t=>t,POWER:t=>e=>e**t,SINE:t=>1-be(t*(oe/2)),CIRC:t=>1-(1-t*t)**.5,EXPO:t=>t===0?0:2**(10*t-10),BACK:t=>t*t*(2.70158*t-1.70158),ELASTIC:t=>t===0?0:t===1?1:-(2**(10*t-10))*pe((37-40*t)*oe/6),SPRING:t=>1-(pe(oe*(1-t)*(.2+2.5*(1-t)**3))*t**2.2+(1-t))*(1+1.2*t),BOUNCE:t=>{let e=1-t,n;return e<4/11?n=7.5625*e*e:e<8/11?n=7.5625*(e-=6/11)*e+.75:e<10/11?n=7.5625*(e-=9/11)*e+.9375:n=7.5625*(e-=10.5/11)*e+.984375,1-n},IN:t=>t,OUT:t=>e=>1-t(1-e),IN_OUT:t=>no.PIECEWISE(t,no.OUT(t)),PIECEWISE:(...t)=>{let e=t.length;return n=>{let s=n*e-1e-9>>0;return(t[s]((n-s/e)*e)+s)/e}},BEZIER:(t,e,n,s)=>{let i=r=>{let a=1-r,o=3*a*a*r,c=3*a*r*r,l=r**3;return[o*t+c*n+l,o*e+c*s+l]};return r=>{let a=0,o=1;for(let c=0;c<128;c++){let l=(a+o)/2,[u,h]=i(l);if(he(u-r)<1e-5)return h;u=this.size.x||n>=this.size.y?null:this.nodes[e+n*this.size.x]}worldToTile(e){let n=this.tileLayer?this.tileLayer.pos.x:0,s=this.tileLayer?this.tileLayer.pos.y:0;return v(Oe(e.x-n),Oe(e.y-s))}tileToWorld(e,n){let s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;return v(e+.5+s,n+.5+i)}buildNodeData(){let e=this.size.x,n=this.size.y,s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;for(let r=0;r0&&(c?l>0&&_e(o.posWorld,er,Q(1,0,0,de(.2,l*.05)),this.debugTime):_e(o.posWorld,er,Q(1,0,0,.25),this.debugTime))}}aStarSearch(e,n){m(e&&n,"aStarSearch needs both endpoints"),m(e!==n,"aStarSearch: start and end must differ \u2014 caller should handle trivial case"),m(e.walkable&&n.walkable,"aStarSearch: endpoints must be walkable");let s=[e];e.isOpen=!0;let i=0;for(;s.length>0;){let r=0,a=s[0].f;for(let c=1;cthis.maxLoop)break;o.isOpen=!1,s.splice(r,1),o.isClosed=!0,this.debug&&this.debugTime>0&&_e(o.posWorld,er,Q(1,1,1,.05),this.debugTime);for(let c=-1;c<=1;++c)for(let l=-1;l<=1;++l){if(l===0&&c===0)continue;let u=this.getNode(o.pos.x+l,o.pos.y+c);if(!u||!u.walkable||u.isClosed)continue;let h=1;if(l!==0&&c!==0){let x=this.getNode(o.pos.x+l,o.pos.y);if(!x||!x.walkable)continue;let w=this.getNode(o.pos.x,o.pos.y+c);if(!w||!w.walkable)continue;h=qh}let d=o.g+h+u.cost;if(!u.isOpen)u.isOpen=!0,s.push(u);else if(d>=u.g)continue;u.parent=o,u.g=d;let f=he(n.pos.x-u.pos.x),p=he(n.pos.y-u.pos.y),y=le(f,p)+(Math.SQRT2-1)*de(f,p);u.f=u.g+y*this.heuristicWeight}}return n.parent!==null}getNearestClearNode(e,n=10,s=!0){m(I(e),"worldPos must be a Vector2"),s&&this.buildNodeData();let i=this.tileLayer?this.tileLayer.pos.x:0,r=this.tileLayer?this.tileLayer.pos.y:0,a=Oe(e.x-i),o=Oe(e.y-r);for(let c=0;c<=n;++c){let l=null,u=0;for(let h=-c;h<=c;++h)for(let d=-c;d<=c;++d){if(c>0&&he(d)!==c&&he(h)!==c)continue;let f=this.getNode(a+d,o+h);if(!f||!f.isClear())continue;let p=f.posWorld.x-e.x,y=f.posWorld.y-e.y,x=p*p+y*y;(!l||x0&&et(i.posWorld,.3,Q(.5,0,.5,.5),this.debugTime),e.splice(n,1),n=le(1,n-1);continue}else if(c===2){this.debug&&this.debugTime>0&&et(i.posWorld,.3,Q(1,0,0,.5),this.debugTime);let f,p;s.pos.y===i.pos.y&&r.pos.x===i.pos.x?(f=s.pos.x,p=r.pos.y):(f=r.pos.x,p=s.pos.y);let y=this.getNode(f,p);if(y&&y.isClear()){e.splice(n,1),n=le(1,n-1);continue}}else if(c===5){this.debug&&this.debugTime>0&&et(i.posWorld,.3,Q(1,1,0,.5),this.debugTime);let f=n>=2?e[n-2]:s,p,y,x,w;l===0||h===0?(p=r.pos.x,y=i.pos.y,x=s.pos.x,w=i.pos.y):(p=i.pos.x,y=r.pos.y,x=i.pos.x,w=s.pos.y);let A=p-f.pos.x,S=y-f.pos.y,_=x-f.pos.x,C=w-f.pos.y,k=A*A+S*S,L=_*_+C*C,V=k0&&et(i.posWorld,.3,Q(0,1,0,.5),this.debugTime),l===h&&u===d){++n;continue}else{let f,p;s.pos.y===r.pos.y?(f=i.pos.x,p=s.pos.y):(f=s.pos.x,p=i.pos.y);let y=this.getNode(f,p);if(y&&y.isClear()){e[n]=y,n=le(1,n-1);continue}}++n}}smoothPathStringPull(e){if(e.length<=2)return;for(let i of e)if(!i.isClear())return;let n=e.slice();e.length=0,e.push(n[0]);let s=0;for(let i=1;i0&&Lt(r.posWorld,e[e.length-1].posWorld,Q(0,0,1,.3),.02,this.debugTime);continue}for(;s=1;--n){let s=e[n-1],i=e[n],r=e[n+1];(i.pos.x-s.pos.x)*(r.pos.y-s.pos.y)===(i.pos.y-s.pos.y)*(r.pos.x-s.pos.x)&&e.splice(n,1)}}isNodeClear(e,n){let s=this.getNode(e,n);return s!==null&&s.isClear()}isLineClear(e,n){m(I(e)&&I(n),"isLineClear needs Vector2 endpoints"),m(this.isNodeClear(e.x,e.y)&&this.isNodeClear(n.x,n.y),"isLineClear endpoints must be in-bounds and clear");let s=n.x-e.x,i=n.y-e.y,r=he(s),a=he(i),o=ht(s),c=ht(i),l=e.x,u=e.y;if(a===r){for(;l!==n.x;){if(l!==e.x&&(!this.isNodeClear(l,u)||!this.isNodeClear(l,u-c))||!this.isNodeClear(l,u+c))return!1;l+=o,u+=c}if(!this.isNodeClear(n.x,n.y-c))return!1}else if(ao.posWorld.copy());if(this.debug&&this.debugTime>0&&a.length>0){for(let o=1;oWh,bootGameHost:()=>$h,default:()=>Hh});var An=class{constructor(e){this._state=(e==null?2654435769:e)>>>0}next(){this._state=this._state+1831565813>>>0;let e=this._state;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}range(e,n){return e+this.next()*(n-e)}reseed(e){this._state=(e==null?2654435769:e)>>>0}},vo=class{constructor(e){this._clock=e||tu(),this._origin=this._clock()}nowMs(){return this._clock()}elapsedMs(){return this._clock()-this._origin}},wo=class{constructor(e){this._time=e,this._subs=new Map}sourceFor(e){let n=this,s=e==null?null:e;return{on(i,r){if(n._assertType(i),typeof r!="function")throw new Error("[HostDevInputBridge] on \u7684 handler \u5FC5\u987B\u662F\u51FD\u6570");let a=n._subs.get(i)||[],o={handler:r,scope:s};return a.push(o),n._subs.set(i,a),{cancel(){let c=n._subs.get(i);if(!c)return;let l=c.indexOf(o);l>=0&&c.splice(l,1)}}},off(i,r){n._assertType(i);let a=n._subs.get(i);if(!a)return;let o=a.findIndex(c=>c.handler===r&&c.scope===s);o>=0&&a.splice(o,1)}}}_emit(e,n){this._assertType(e);let s=n||{},i={type:e,x:typeof s.x=="number"?s.x:0,y:typeof s.y=="number"?s.y:0,key:typeof s.key=="string"?s.key:"",tMs:this._time.nowMs()},r=this._subs.get(e);if(!r||r.length===0)return;let a=r.slice();for(let o of a)try{o.handler(i)}catch(c){on("[host-dev input] \u8F93\u5165 handler \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09type="+e,c)}}disposeScope(e){if(e==null)return 0;let n=0;for(let[s,i]of this._subs){let r=i.filter(a=>a.scope!==e);n+=i.length-r.length,r.length===0?this._subs.delete(s):this._subs.set(s,r)}return n}_subscriptionCount(){let e=0;for(let n of this._subs.values())e+=n.length;return e}_assertType(e){if(!To.has(e))throw new Error("[HostDevInputBridge] \u975E\u6CD5\u8F93\u5165\u4E8B\u4EF6\u7C7B\u578B\uFF1A"+String(e)+"\uFF08\u4EC5\u652F\u6301 "+Array.from(To).join("/")+"\uFF09")}},To=new Set(["pointerdown","pointermove","pointerup","keydown","keyup"]);function ja(t){let e=t||{},n=new vo(e.clock),s=new An(e.seed),i=e.seed==null?2654435769:e.seed>>>0,r=new wo(n),a=typeof e.audioFactory=="function"?e.audioFactory:null,o=null,c=!1,l=typeof e.engineFactory=="function"?e.engineFactory:null,u=null,h=!1,d=new Map,f=0,p=0;function y(){if(o)return o;if(!a)return c||(ko("[host-dev audio] \u672A\u6CE8\u5165 audioFactory\uFF0CgetAudioContext \u8FD4\u56DE null\uFF08P6 \u987B\u5BB9\u9519\u964D\u7EA7\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u5DE5\u5382\uFF09"),c=!0),null;try{o=a()}catch(_){on("[host-dev audio] audioFactory \u629B\u9519\uFF0CgetAudioContext \u964D\u7EA7\u8FD4\u56DE null",_),o=null}return o}function x(){if(u)return u;if(!l)return h||(ko("[host-dev engine] \u672A\u6CE8\u5165 engineFactory\uFF0CgetEngine \u8FD4\u56DE null\uFF08\u63D2\u4EF6\u987B\u5BB9\u9519\u964D\u7EA7\uFF1A\u7C92\u5B50\u9000\u53D7\u63A7\u9762\u81EA\u7BA1/\u5408\u6210\u6838\u9000 vendored/\u6570\u5B66\u9000\u5185\u7F6E\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u80CC\u4E66\uFF09"),h=!0),null;try{u=l()}catch(_){on("[host-dev engine] engineFactory \u629B\u9519\uFF0CgetEngine \u964D\u7EA7\u8FD4\u56DE null",_),u=null}return u}function w(_,C){return{getContext2d(){return e.context2d==null?null:e.context2d},onFrame(L){let V=f++;return d.set(V,L),{cancel(){d.delete(V)}}},getInput(){return r.sourceFor(_)},getAudioContext(){return y()},getEngine(){return x()},time:n,random:C}}let A=w(null,s),S={context:A,tick(_){p+=1;let C=Array.from(d.values());for(let k of C)try{k(_,p)}catch(L){on("[host-dev tick] \u5E27\u56DE\u8C03\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09frame="+p,L)}},frameCount(){return p},inputBridge:r,deriveContextFor(_,C){let k=eu(i,_),L=new An(k);return w(C==null?_:C,L)}};return Object.defineProperty(A,Ao,{value:S,enumerable:!1,writable:!1,configurable:!1}),S}var Ao=Symbol("zaomeng.coreProtocol.contextBundle"),ui=class{constructor(){this._plugins=new Map,this._initOrder=[],this._initErrors=[],this._phase="idle",this._disposed=!1,this._context=void 0,this._pluginContexts=new Map}register(e){if(!e||typeof e!="object")throw new Error("[PluginRegistry] register \u9700\u8981\u4E00\u4E2A\u63D2\u4EF6\u5BF9\u8C61");if(typeof e.name!="string"||e.name.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6\u7F3A\u5C11\u5408\u6CD5 name");if(typeof e.version!="string"||e.version.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11\u5408\u6CD5 version");if(typeof e.init!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11 init \u51FD\u6570");if(e.dispose!=null&&typeof e.dispose!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7684 dispose \u5FC5\u987B\u662F\u51FD\u6570\u6216\u7701\u7565");if(this._plugins.has(e.name))throw new Error("[PluginRegistry] \u63D2\u4EF6\u91CD\u540D\u62D2\u7EDD\uFF1A"+e.name+" \u5DF2\u6CE8\u518C");return this._plugins.set(e.name,e),this}has(e){return this._plugins.has(e)}get(e){return this._plugins.get(e)}list(){return Array.from(this._plugins.keys())}initAll(){if(this._phase==="initialized")return ko("[PluginRegistry] initAll \u91CD\u590D\u8C03\u7528\uFF0C\u5DF2\u5FFD\u7565\uFF08\u5DF2\u5904\u4E8E initialized\uFF09"),this._initResult();if(this._phase==="disposed")throw new Error("[PluginRegistry] \u5DF2 dispose \u7684\u6CE8\u518C\u5668\u4E0D\u53EF\u518D initAll");if(this._context==null)throw new Error("[PluginRegistry] \u672A\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\uFF1A\u8BF7\u5728 initAll() \u4E4B\u524D\u8C03\u7528 useContext(context)\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context); reg.initAll();\uFF09");for(let[e,n]of this._plugins){let s=this._missingDeps(n);if(s.length>0){let r=new Error("[PluginRegistry] \u63D2\u4EF6 "+e+" \u4F9D\u8D56\u7F3A\u5931\uFF1A"+s.join(", ")+"\uFF08\u672A\u6CE8\u518C\uFF09");this._initErrors.push({name:e,error:r}),on("[PluginRegistry] \u8DF3\u8FC7 init\uFF08\u4F9D\u8D56\u7F3A\u5931\uFF0C\u5DF2\u9694\u79BB\uFF09\uFF1A"+e,r);continue}let i=this._contextFor(e);try{n.init(i),this._initOrder.push(e)}catch(r){let a=r instanceof Error?r:new Error(String(r));this._initErrors.push({name:e,error:a}),on("[PluginRegistry] \u63D2\u4EF6 init \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF0C\u4E0D\u8FDE\u5750\uFF09\uFF1A"+e,a)}}return this._phase="initialized",this._initResult()}_contextFor(e){let n=this._pluginContexts.get(e);if(n)return n;let s=this._context&&this._context[Ao],i;return s&&typeof s.deriveContextFor=="function"?i=s.deriveContextFor(e,e):i=this._context,this._pluginContexts.set(e,i),i}disposeAll(){if(this._disposed)return{disposed:[],errors:[]};let e=[],n=[],s=this._context&&this._context[Ao],i=s&&s.inputBridge;for(let r=this._initOrder.length-1;r>=0;r--){let a=this._initOrder[r],o=this._plugins.get(a);if(o&&typeof o.dispose=="function")try{o.dispose(),e.push(a)}catch(c){let l=c instanceof Error?c:new Error(String(c));n.push({name:a,error:l}),on("[PluginRegistry] \u63D2\u4EF6 dispose \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,l)}if(i&&typeof i.disposeScope=="function")try{i.disposeScope(a)}catch(c){on("[PluginRegistry] \u56DE\u6536\u63D2\u4EF6\u8F93\u5165\u8BA2\u9605\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,c)}}return this._disposed=!0,this._phase="disposed",{disposed:e,errors:n}}useContext(e){if(this._phase!=="idle")throw new Error("[PluginRegistry] useContext \u5FC5\u987B\u5728 initAll() \u4E4B\u524D\u8C03\u7528\uFF08\u5F53\u524D\u9636\u6BB5\uFF1A"+this._phase+"\uFF09\u3002\u8BF7\u5728\u4EFB\u4F55 initAll/disposeAll \u4E4B\u524D\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\u3002");if(e==null||typeof e!="object")throw new Error("[PluginRegistry] useContext \u9700\u8981\u4E00\u4E2A\u53D7\u63A7\u4E0A\u4E0B\u6587\u5BF9\u8C61\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context);\uFF09");return this._context=e,this}_missingDeps(e){return!Array.isArray(e.dependencies)||e.dependencies.length===0?[]:e.dependencies.filter(n=>!this._plugins.has(n))}_initResult(){return{ok:this._initErrors.length===0,initialized:this._initOrder.slice(),errors:this._initErrors.slice()}}};function eu(t,e){let n=2166136261,s=16777619,i=t>>>0;for(let a=0;a<32;a+=8){let o=i>>>a&255;n^=o,n=Math.imul(n,s)>>>0}let r=String(e);for(let a=0;a>>0,n^=o>>>8&255,n=Math.imul(n,s)>>>0}return n>>>0}function tu(){if(typeof globalThis!="undefined"&&globalThis.performance&&typeof globalThis.performance.now=="function")return()=>globalThis.performance.now();if(typeof process!="undefined"&&process.hrtime&&typeof process.hrtime.bigint=="function"){let t=process.hrtime.bigint();return()=>Number(process.hrtime.bigint()-t)/1e6}return()=>Date.now()}function on(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function ko(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Kh=Object.freeze(Array.from(To)),Ja="core-protocol-v0";var Na=Object.freeze(["t_boot","t_plugins_ready","t_game_init","t_first_paint","t_input_bound","t_game_start"]),Co=Na.reduce((t,e,n)=>(t[e]=n,t),Object.create(null)),nu=new Set(Na);function _o(t){let e=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}var za=_o("runtime-probe::seed::v1");function di(t){return t===null||typeof t!="object"?JSON.stringify(t):Array.isArray(t)?"["+t.map(di).join(",")+"]":"{"+Object.keys(t).sort().map(n=>JSON.stringify(n)+":"+di(t[n])).join(",")+"}"}function Ua(t){let e=di(t.extra==null?null:t.extra),n=di(Array.isArray(t.pluginSet)?t.pluginSet:[]);return["seq="+t.seq,"anchor="+t.anchor,"tMono="+t.tMono,"buildSha="+(t.buildSha||""),"pluginSet="+n,"extra="+e].join("|")}function su(t){return Math.round(t*1e3)/1e3}function iu(t){if(!Array.isArray(t))return{ok:!1,reason:"records_not_array"};let e=za,n=-1;for(let s=0;stypeof _=="string").slice().sort():[],i=typeof e.sink=="function"?e.sink:null,r=e.autoBoot!==!1,a=typeof e.inputAnchorType=="string"?e.inputAnchorType:"pointerdown",o=()=>0,c=!1,l=0,u=za,h=[],d=new Set,f=-1,p=null,y=!1,x=!1,w=!1;function A(_,C){let k=null;if(!nu.has(_))k="unknown_anchor";else{d.has(_)&&(k=k?k+";duplicate_anchor":"duplicate_anchor");let V=Co[_];V_.time.nowMs(),c=!0,r&&!x&&A("t_boot",{auto:!0}),p=_.getInput().on(a,C=>{y||(y=!0,A("t_input_bound",{firstInput:!0,type:C.type}))}),A("t_input_bound",{stage:"registered",type:a})},dispose(){w||(p&&(p.cancel(),p=null),w=!0)},mark:A,getRecords(){return h.map(_=>({..._}))},toJSONL(){return h.map(_=>JSON.stringify(_)).join(`
+`)},verify(){return iu(h)}}}function ou(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function qa(t){let e=t.LJS,n=t.engineMath,s=t.engineMode,i=t.recHook||(()=>{});if(s!=="real")return null;let r=n;return{math:{lerp:(o,c,l)=>(i("math.lerp"),r.lerp(o,c,l)),smoothStep:o=>(i("math.smoothStep"),r.smoothStep(o)),easing:Object.fromEntries(Object.keys(r.easing).map(o=>[o,c=>(i("math.easing."+o),r.easing[o](c))]))},particles:{spawnEmitter(o){i("particles.spawnEmitter");let c=e.screenToWorld(e.vec2(o.pos.x,o.pos.y)),l=e.cameraScale,u=o.emitTime!=null?o.emitTime:o.count!=null?1/60:0,h=o.emitRate!=null?o.emitRate:o.count!=null?o.count*60:100,d=(o.speed!=null?o.speed:0)/l/60,f=o.damping!=null?o.damping:1,p=o.colorStart||{r:1,g:1,b:1,a:1},y=o.colorEnd||{r:1,g:1,b:1,a:0},x=e.rgb(p.r,p.g,p.b,p.a),w=e.rgb(y.r,y.g,y.b,y.a),A=new e.ParticleEmitter(c,o.angle!=null?o.angle:0,(o.emitSize!=null?o.emitSize:0)/l,u,h,o.coneAngle!=null?o.coneAngle:Math.PI,void 0,x,x,w,w,o.particleTime!=null?o.particleTime:.5,(o.sizeStart!=null?o.sizeStart:6)/l,(o.sizeEnd!=null?o.sizeEnd:0)/l,d,0,f,1,o.gravityScale!=null?o.gravityScale:0,Math.PI,.1,0,!1,o.additive!=null?o.additive:!1,!0);return{isActive(){return A.isActive()},stop(){A.destroyed||A.destroy(!0)}}}},audio:{synth:{synthSfx:o=>{i("audio.synth.synthSfx");try{return e.zzfxG(...o)}catch(c){return console.error("[host][engine-audio] zzfxG \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(c&&c.message?c.message:c)),null}},synthSong:(o,c,l,u)=>{i("audio.synth.synthSong");try{return e.zzfxM(o,c,l,u)}catch(h){return console.error("[host][engine-audio] zzfxM \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(h&&h.message?h.message:h)),null}}}}}}function xt(t){return t<0?0:t>1?1:t}function Wa(t){let e=t.Ease,n=e.POWER(2),s=e.POWER(3),i=e.OUT(n),r=e.IN_OUT(n),a=e.OUT(s),o=e.IN_OUT(s),c=e.OUT(e.BACK),l=e.OUT(e.ELASTIC);return{lerp:(u,h,d)=>t.lerp(u,h,d),smoothStep:u=>t.smoothStep(u),easing:{linear:u=>e.LINEAR(xt(u)),quadIn:u=>n(xt(u)),quadOut:u=>i(xt(u)),quadInOut:u=>r(xt(u)),cubicIn:u=>s(xt(u)),cubicOut:u=>a(xt(u)),cubicInOut:u=>o(xt(u)),backIn:u=>e.BACK(xt(u)),backOut:u=>c(xt(u)),elasticIn:u=>e.ELASTIC(xt(u)),elasticOut:u=>l(xt(u))}}}var rn=2,fi=1/60;async function Ha(t){let e=t.canvas,n=t.statusEl||null,s=t.engine,i=t.seed>>>0,r=t.mode||"play",a=t.engineMode||"real",o=t.viewport.w,c=t.viewport.h,l=t.factory,u=t.buildFactoryOpts||(()=>{}),h=t.plugins||{},d=t.registerOrder||Object.values(h),f=t.onReady||(()=>{}),p=t.recHook||(()=>{});function y(B){n&&(n.textContent=B)}let x=[];window.addEventListener("error",B=>x.push({type:"error",message:String(B&&B.message||B)})),window.addEventListener("unhandledrejection",B=>x.push({type:"unhandledrejection",message:String(B&&B.reason&&B.reason.message||B&&B.reason||B)}));let w=null,A=!1;function S(){if(!A)return null;if(w)return w;let B=window.AudioContext||window.webkitAudioContext;return B?(w=new B,w):null}let _=0,C=null,k=null,L=null,V=null,ae=[],ne={},T=null;function P(B,ye){try{L&&L.mark(B,ye)}catch(F){x.push({type:"mark",message:String(F&&F.message||F)})}}function R(){k&&typeof k._refreshChecklist=="function"&&k._refreshChecklist(ne)}async function M(B,ye){C=ja({context2d:B,seed:i,audioFactory:S,clock:()=>_,engineFactory:()=>qa({LJS:a==="real"?s:null,engineMath:a==="real"?Wa(s):null,engineMode:a,recHook:p})});let F=new ui;for(let N of d)F.register(N);F.useContext(C.context),V=F.initAll(),ae=F.list().concat(["runtime-probe"]),L=Va({pluginSet:ae,inputAnchorType:"pointerdown",autoBoot:!0});let D=C.deriveContextFor("runtime-probe","runtime-probe");P("t_boot",{by:"game-host",stage:"pre-init",engineMode:a}),P("t_plugins_ready",{initialized:V.initialized.length,ok:V.ok});let J=u(C.context,{bundle:C,plugins:h,getRealAudioCtx:()=>w});k=l(J),await k.init({ctx:C.context,mainContext:B,canvas:ye(),seed:i}),T=k&&typeof k._forensicsView=="function"?k._forensicsView():null,P("t_game_init",{hasForensics:!!T}),G(),P("t_first_paint",{frame:C.frameCount()});try{L.init(D)}catch(N){x.push({type:"probe-init",message:String(N&&N.message||N)})}P("t_game_start",{mode:r,engineMode:a}),R(),f(xe,{bundle:C,game:k,probe:L,checklist:ne,uncaught:x,pluginSet:ae,initRes:V,getGameForensics:()=>T,mark:P,stepOneFrame:G})}let j=null;function G(B){let ye=typeof B=="number"?B:fi;k&&(_+=ye*1e3,k.update(ye),a==="stub"&&j&&k.render(j),R())}function H(B){for(let ye=0;ye{}),k&&typeof k._onAudioUnlock=="function"&&k._onAudioUnlock()}let xe={seed:i,mode:r,engineMode:a,protocol:Ja,frameCount:()=>C?C.frameCount():0,stepFrames:H,startRaf:()=>$n(),stopRaf:()=>jt(),tap(B,ye){W(),C&&(C.inputBridge._emit("pointerdown",{x:B,y:ye}),C.inputBridge._emit("pointerup",{x:B,y:ye}))},do(B){k&&typeof k._handleAction=="function"&&k._handleAction(B)},state:()=>T?T.state():{phase:"booting"}};function Pe(B){let ye=C.inputBridge;function F(D,J){let N=B.getBoundingClientRect();return{x:(D-N.left)/N.width*o,y:(J-N.top)/N.height*c}}B.addEventListener("pointerdown",D=>{W(),ye._emit("pointerdown",F(D.clientX,D.clientY))}),B.addEventListener("pointermove",D=>{ye._emit("pointermove",F(D.clientX,D.clientY))}),B.addEventListener("pointerup",D=>{ye._emit("pointerup",F(D.clientX,D.clientY))})}let ve=0,dt=!1,ft=0;function bt(B){if(!dt)return;ft===0&&(ft=B);let ye=(B-ft)/1e3;ft=B,ye>.05&&(ye=.05),G(ye),ve=window.requestAnimationFrame(bt)}function $n(){a==="stub"&&(dt||(dt=!0,ft=0,ve=window.requestAnimationFrame(bt)))}function jt(){dt=!1,ve&&window.cancelAnimationFrame(ve),ve=0}function Yn(B){B.width=o*rn,B.height=c*rn,B.style.width=o+"px",B.style.height=c+"px";let ye=B.getContext("2d",{willReadFrequently:!0});return ye.setTransform(rn,0,0,rn,0,0),ye}async function Ss(){let B=Yn(e);return j=B,await M(B,()=>e),Pe(e),r==="evidence"?y(`evidence \u5C31\u7EEA seed=${i} \xB7 \u7528 host \u9A71\u52A8\uFF08stepFrames/tap\uFF09`):(y(`seed=${i} \xB7 \u70B9\u5F00\u59CB\uFF08\u9996\u6B21\u70B9\u51FB\u5F00\u58F0\uFF09`),$n()),xe}let tn=()=>{},nn=()=>{};function sn(){window.__gameHostEngineInitFired=!0}function Xn(){tn()}function Kn(){}function go(){nn()}function bo(){}async function xo(B){await M(B,()=>s.mainCanvas),Pe(s.mainCanvas),tn=()=>{k&&(_+=fi*1e3,k.update(fi))},nn=()=>{if(k){B.save(),B.setTransform(rn,0,0,rn,0,0);try{B.imageSmoothingEnabled=!1}catch{}k.render(B),B.restore()}},s.mainCanvas&&(s.mainCanvas.id="game-engine"),window.__engine={frame(){return s.frame},time(){return s.time},timeReal(){return s.timeReal},paused(){return s.paused},timeScale(){return s.timeScale},snapshot(){return{frame:s.frame,time:s.time,timeReal:s.timeReal,paused:s.paused,timeScale:s.timeScale}}},y(`engine RAF running \xB7 seed=${i} engine=real`)}if(a!=="real")return await Ss();if(!s){let B="real \u901A\u9053\u672A\u6CE8\u5165\u5F15\u64CE\uFF08opts.engine \u7F3A\u5931\uFF09\uFF1A\u8BF7\u7ECF entry \u5305\u88C5\u5C42\u542F\u52A8\uFF08host \u4E0D\u76F4\u63A5 import \u5F15\u64CE\uFF0CQ4/Option C\uFF09";throw y("ENGINE INJECT MISSING: "+B),new Error(B)}s.setGLEnable(!1),s.setShowSplashScreen(!1),s.setDebugWatermark(!1),s.setCanvasClearColor(s.BLACK),s.setCanvasFixedSize(s.vec2(o*rn,c*rn));let vs=document.createElement("div");return vs.id="engine-root",document.body.appendChild(vs),await s.engineInit(sn,Xn,Kn,go,bo,[],vs).then(()=>xo(s.mainContext)).catch(B=>{throw window.__gameHostBootError=String(B&&B.message||B),y("ENGINE INIT FAILED: "+window.__gameHostBootError),B}),xe}function ru(){return{hit:!1,depth:0,nx:0,ny:0}}var Eo=class{constructor(e){let n=e||{},s=typeof n.cellSize=="number"&&n.cellSize>0?n.cellSize:64;this._cellSize=s,this._cells=new Map,this._entries=new Map,this._seq=0}get size(){return this._entries.size}_cellRange(e){let n=this._cellSize,s=Math.floor((e.x-e.hw)/n),i=Math.floor((e.x+e.hw)/n),r=Math.floor((e.y-e.hh)/n),a=Math.floor((e.y+e.hh)/n);return{cx0:s,cy0:r,cx1:i,cy1:a}}insert(e,n){this._entries.has(e)&&this.remove(e);let{cx0:s,cy0:i,cx1:r,cy1:a}=this._cellRange(n),o=[];for(let l=i;l<=a;l++)for(let u=s;u<=r;u++){let h=u+","+l,d=this._cells.get(h);d||(d=new Set,this._cells.set(h,d)),d.add(e),o.push(h)}let c={x:n.x,y:n.y,hw:n.hw,hh:n.hh};this._entries.set(e,{id:e,box:c,seq:this._seq++,cells:o})}remove(e){let n=this._entries.get(e);if(!n)return!1;for(let s of n.cells){let i=this._cells.get(s);i&&(i.delete(e),i.size===0&&this._cells.delete(s))}return this._entries.delete(e),!0}query(e){let{cx0:n,cy0:s,cx1:i,cy1:r}=this._cellRange(e),a=new Set;for(let o=s;o<=r;o++)for(let c=n;c<=i;c++){let l=this._cells.get(c+","+o);if(l)for(let u of l)a.add(u)}return this._collect(a)}queryPoint(e,n){let s=this._cellSize,i=Math.floor(e/s),r=Math.floor(n/s),a=this._cells.get(i+","+r);return a?this._collect(new Set(a)):[]}clear(){this._cells.clear(),this._entries.clear(),this._seq=0}_collect(e){let n=[];for(let s of e){let i=this._entries.get(s);i&&n.push(i)}return n.sort((s,i)=>s.seq-i.seq),n.map(s=>({id:s.id,box:s.box}))}};function $a(t,e){let n=t.x-e.x,s=t.y-e.y,i=t.hw+e.hw-Math.abs(n),r=t.hh+e.hh-Math.abs(s);return i<=1e-9||r<=1e-9?ru():i0?e.fixedStep:1/120;return{gx:n.x||0,gy:n.y||0,fixedStep:s}}function Ka(t,e,n,s){t.vx+=e*s,t.vy+=n*s,t.px+=t.vx*s,t.py+=t.vy*s}function au(t,e,n){let{gx:s,gy:i,fixedStep:r}=Qa(n),a={px:t.px,py:t.py,vx:t.vx,vy:t.vy},o=e>0?e:0;for(;o>=r-1e-12;)Ka(a,s,i,r),o-=r;return o>1e-12&&Ka(a,s,i,o),a}var hi=class{constructor(e,n){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy};let s=Qa(n);this._gx=s.gx,this._gy=s.gy,this._fixedStep=s.fixedStep}get state(){return{px:this._s.px,py:this._s.py,vx:this._s.vx,vy:this._s.vy}}step(e){let n=au(this._s,e,{gravity:{x:this._gx,y:this._gy},fixedStep:this._fixedStep});return this._s=n,this.state}reset(e){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy}}};function Za(t,e,n,s){let i=n.mass==null?1:n.mass,r=n.stiffness,a=n.damping,o=t.x,c=t.v,l=s>0?s:0;if(l<=1e-12)return{x:o,v:c};let u=i>1e-12?i:1e-12,h=Math.sqrt(Math.max(0,r)/u),d=a/u,f=h>1e-12?.2/h:l,p=d>1e-12?.5/d:l,y=Math.max(1e-12,Math.min(f,p)),x=Math.ceil(l/y);(!Number.isFinite(x)||x<1)&&(x=1),x>4096&&(x=4096);let w=l/x;for(let A=0;A1?1:t}var lu=t=>(t=$e(t),t*t),uu=t=>(t=$e(t),1-(1-t)*(1-t)),du=t=>(t=$e(t),t<.5?2*t*t:1-Math.pow(-2*t+2,2)/2),fu=t=>(t=$e(t),t*t*t),hu=t=>{t=$e(t);let e=1-t;return 1-e*e*e},pu=t=>(t=$e(t),t<.5?4*t*t*t:1-Math.pow(-2*t+2,3)/2),nc=2*Math.PI/3,tc=2*Math.PI/4.5,mu=t=>(t=$e(t),t===0?0:t===1?1:-Math.pow(2,10*t-10)*Math.sin((t*10-10.75)*nc)),yu=t=>(t=$e(t),t===0?0:t===1?1:Math.pow(2,-10*t)*Math.sin((t*10-.75)*nc)+1),gu=t=>(t=$e(t),t===0?0:t===1?1:t<.5?-(Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*tc))/2:Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*tc)/2+1),yi=1.70158,pi=yi*1.525,sc=yi+1,bu=t=>(t=$e(t),sc*t*t*t-yi*t*t),xu=t=>{t=$e(t);let e=t-1;return 1+sc*e*e*e+yi*e*e},Su=t=>(t=$e(t),t<.5?Math.pow(2*t,2)*((pi+1)*2*t-pi)/2:(Math.pow(2*t-2,2)*((pi+1)*(t*2-2)+pi)+2)/2),vu=t=>$e(t),Ro=Object.freeze({linear:vu,quadIn:lu,quadOut:uu,quadInOut:du,cubicIn:fu,cubicOut:hu,cubicInOut:pu,elasticIn:mu,elasticOut:yu,elasticInOut:gu,backIn:bu,backOut:xu,backInOut:Su}),Mo=Ro,wu=["linear","quadIn","quadOut","quadInOut","cubicIn","cubicOut","cubicInOut","elasticIn","elasticOut","elasticInOut","backIn","backOut","backInOut"];function Tu(t){let e=t&&t.easing;if(!e)return Ro;let n=i=>typeof e[i]=="function"?r=>e[i]($e(r)):Ro[i],s={};for(let i of wu)s[i]=n(i);return Object.freeze(s)}var Po=class{constructor(e,n,s){let i=s||{};this._time=n,this._windowMs=typeof i.windowMs=="number"&&i.windowMs>0?i.windowMs:120;let r=Array.isArray(i.types)&&i.types.length>0?i.types:cu;this._records=new Map,this._subs=[],this._disposed=!1;for(let a of r){this._records.set(a,null);let o=e.on(a,c=>{this._records.set(a,c.tMs)});this._subs.push(o)}}consume(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs?(this._records.set(e,null),!0):(this._records.set(e,null),!1)}peek(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs}clear(){for(let e of this._records.keys())this._records.set(e,null)}dispose(){if(!this._disposed){for(let e of this._subs)try{e.cancel()}catch(n){}this._subs=[],this._disposed=!0}}};var mi=class{constructor(e,n){let s=n||{};this._time=e,this._windowMs=typeof s.windowMs=="number"&&s.windowMs>0?s.windowMs:500,this._maxCount=typeof s.maxCount=="number"&&s.maxCount>0?s.maxCount:1/0,this._count=0,this._lastHitAt=null}hit(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt!=null&&n-this._lastHitAt<=this._windowMs&&this._count>0?this._count=Math.min(this._count+1,this._maxCount):this._count=1,this._lastHitAt=n,this._count}getCount(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt==null||n-this._lastHitAt>this._windowMs?0:this._count}reset(){this._count=0,this._lastHitAt=null}};function ic(t){let e=t||{},n=null,s=null,i=!1;return{name:"gamefeel",version:"1.0.0",dependencies:[],get inputBuffer(){return n},get easing(){return Tu(s)},init(a){let o=a.getInput();n=new Po(o,a.time,{windowMs:e.inputBufferMs,types:e.inputTypes});let c=a.getEngine();s=c?c.math:null},dispose(){i||(n&&(n.dispose(),n=null),s=null,i=!0)}}}function gi(t,e){let n=e<0?0:e>1?1:e;switch(t&&t.kind){case"constant":return t.value;case"linear":return t.from+(t.to-t.from)*n;case"easeInOut":{let s=n*n*(3-2*n);return t.from+(t.to-t.from)*s}case"decay":{let s=t.power==null?2:t.power,i=Math.pow(1-n,s);return t.to+(t.from-t.to)*i}default:return 0}}var Au=Object.freeze({burst:Object.freeze({mode:"burst",count:24,angle:0,spread:Math.PI,speedMin:80,speedMax:160,lifeMin:.4,lifeMax:.8,gravity:0,drag:0,sizeCurve:{kind:"decay",from:6,to:0,power:1.5},alphaCurve:{kind:"linear",from:1,to:0}}),trail:Object.freeze({mode:"continuous",rate:60,angle:Math.PI,spread:.25,speedMin:20,speedMax:50,lifeMin:.2,lifeMax:.5,gravity:0,drag:1.5,sizeCurve:{kind:"easeInOut",from:4,to:0},alphaCurve:{kind:"decay",from:.8,to:0,power:2}}),drift:Object.freeze({mode:"continuous",rate:12,angle:Math.PI/2,spread:.6,speedMin:10,speedMax:30,lifeMin:1.5,lifeMax:3,gravity:8,drag:.5,sizeCurve:{kind:"constant",value:3},alphaCurve:{kind:"decay",from:.7,to:0,power:1}})});function ku(t){let e=Au[t];return e?Lo(e):null}function Lo(t){let e={};for(let n of Object.keys(t)){let s=t[n];e[n]=s&&typeof s=="object"?Lo(s):s}return e}function Cu(t,e,n){let s=t.mode==="continuous";return{pos:{x:e,y:n},angle:t.angle,coneAngle:t.spread,emitSize:0,emitTime:s?0:1/60,emitRate:s?t.rate||0:void 0,count:s?void 0:t.count||0,particleTime:(t.lifeMin+t.lifeMax)/2,speed:(t.speedMin+t.speedMax)/2,gravityScale:t.gravity||0,damping:t.drag!=null?1-t.drag/60:1,sizeStart:gi(t.sizeCurve,0),sizeEnd:gi(t.sizeCurve,1),colorStart:{r:1,g:1,b:1,a:gi(t.alphaCurve,0)},colorEnd:{r:1,g:1,b:1,a:gi(t.alphaCurve,1)},additive:!1}}function bi(t){let e=t||{},n=null,s=null,i=null,r=new Map,a=0,o={isActive(){return!1},stop(){}},c=0,l=1,u=0,h=0,d=0,f={x:0,y:0,remain:0,dur:0,amplitude:0,frequency:0,_phase:0},p={alpha:0,remain:0,dur:0,peak:0},y={scale:1,remain:0,dur:0,amplitude:0,frequency:0},x=!1;function w(C){if(u>0)if(u-=C,u<=0)u=0,l=1;else{let k=h>0?1-u/h:1;l=d+(1-d)*k}if(f.remain>0)if(f.remain-=C,f.remain<=0)f.remain=0,f.x=0,f.y=0;else{let k=f.remain/f.dur,L=f.amplitude*k;f._phase+=f.frequency*C*Math.PI*2,f.x=Math.sin(f._phase)*L,f.y=Math.cos(f._phase*1.3)*L}if(p.remain>0&&(p.remain-=C,p.remain<=0?(p.remain=0,p.alpha=0):p.alpha=p.peak*(p.remain/p.dur)),y.remain>0)if(y.remain-=C,y.remain<=0)y.remain=0,y.scale=1;else{let k=y.remain/y.dur,L=(1-k)*y.frequency*Math.PI*2;y.scale=1+Math.sin(L)*y.amplitude*k}}function A(C){c+=1,w(C)}function S(C){let k=C!==void 0?C:n?n.getContext2d():null;if(k&&p.alpha>0){k.globalAlpha=p.alpha,k.fillStyle="#ffffff";let L=k.canvas?k.canvas.width:0,V=k.canvas?k.canvas.height:0;k.fillRect(0,0,L,V),k.globalAlpha=1}}return{name:"particles-juice",version:"1.0.0",dependencies:[],init(C){var k;n=C,i=((k=C.getEngine())==null?void 0:k.particles)||null,typeof e.seed=="number"&&C.random.reseed(e.seed),e.autoStep!==!1&&(s=C.onFrame(L=>{A(L)}))},dispose(){x||(s&&(s.cancel(),s=null),r.forEach(C=>{try{C.stop()}catch{}}),r.clear(),l=1,u=0,f.remain=0,f.x=0,f.y=0,p.remain=0,p.alpha=0,y.remain=0,y.scale=1,x=!0)},spawnEmitter(C,k,L,V){let ae=typeof C=="string"?ku(C):Lo(C);if(!ae)return-1;V&&(ae=Object.assign(ae,V));let ne=a++;if(!i)return r.set(ne,o),ne;let T=i.spawnEmitter(Cu(ae,k,L));return r.set(ne,T),ne},stopEmitter(C){let k=r.get(C);if(k)try{k.stop()}catch{}},step(C){A(C)},render(C){S(C)},particleCount(){return 0},emitterCount(){let C=0;for(let k of r.values())k.isActive()&&(C+=1);return C},hitStop(C,k){h=Math.max(0,C),u=h,d=k==null?0:Math.max(0,Math.min(1,k)),l=h>0?d:1},getTimeScale(){return l},shakeScreen(C,k,L){f.dur=Math.max(0,C),f.remain=f.dur,f.amplitude=Math.max(0,k),f.frequency=L==null?30:L,f._phase=0,f.x=0,f.y=0},getShakeOffset(){return{x:f.x,y:f.y}},flashScreen(C,k){p.dur=Math.max(0,C),p.remain=p.dur,p.peak=k==null?.8:Math.max(0,Math.min(1,k)),p.alpha=p.dur>0?p.peak:0},getFlashAlpha(){return p.alpha},pulseScale(C,k,L){y.dur=Math.max(0,C),y.remain=y.dur,y.amplitude=k==null?.2:k,y.frequency=L==null?4:L,y.scale=1},getPulseScale(){return y.scale},juiceSnapshot(){return{timeScale:l,shake:{x:f.x,y:f.y},flashAlpha:p.alpha,pulseScale:y.scale}},probe(){return{particles:0,emitters:r.size,dropped:0,steps:c,disposed:x}}}}function oc(t){let e=ke(t.r)/255,n=ke(t.g)/255,s=ke(t.b)/255,i=Math.max(e,n,s),r=Math.min(e,n,s),a=(i+r)/2,o=0,c=0,l=i-r;return l>1e-12&&(c=a>.5?l/(2-i-r):l/(i+r),i===e?o=(n-s)/l%6:i===n?o=(s-e)/l+2:o=(e-n)/l+4,o*=60,o<0&&(o+=360)),{h:o,s:c,l:a}}function rc(t){let e=(t.h%360+360)%360,n=an(t.s),s=an(t.l);if(n<1e-12){let o=Math.round(s*255);return{r:o,g:o,b:o}}let i=s<.5?s*(1+n):s+n-s*n,r=2*s-i,a=e/360;return{r:Math.round(Oo(r,i,a+1/3)*255),g:Math.round(Oo(r,i,a)*255),b:Math.round(Oo(r,i,a-1/3)*255)}}function Oo(t,e,n){let s=n;return s<0&&(s+=1),s>1&&(s-=1),s<1/6?t+(e-t)*6*s:s<1/2?e:s<2/3?t+(e-t)*(2/3-s)*6:t}function ke(t){return t<0?0:t>255?255:t}function an(t){return t<0?0:t>1?1:t}function Go(t,e){let n=Eu(t.from,e);if(n>=0&&n({r:ke(o.r),g:ke(o.g),b:ke(o.b)})),to:r}}function Io(t,e,n){return t+(e-t)*n}function jo(t,e){let n=oc(t),s=n.h+(e.hue||0),i=an(n.s*(e.sat==null?1:e.sat)),r=an(n.l*(e.light==null?1:e.light));return rc({h:s,s:i,l:r})}var Pu=Object.freeze([Object.freeze([0,8,2,10]),Object.freeze([12,4,14,6]),Object.freeze([3,11,1,9]),Object.freeze([15,7,13,5])]);function ac(t){let e=t||{},n=null,s=!1,i={vignette:{enabled:Do(e.vignette&&e.vignette.enabled,!1),strength:Fo(e.vignette&&e.vignette.strength,.5)},dither:{enabled:Do(e.dither&&e.dither.enabled,!1),strength:Fo(e.dither&&e.dither.strength,.5)},scanline:{enabled:Do(e.scanline&&e.scanline.enabled,!1),strength:Fo(e.scanline&&e.scanline.strength,.5)}};function r(o){let c=o!==void 0?o:n?n.getContext2d():null;if(!c)return;let l=c.canvas?c.canvas.width:0,u=c.canvas?c.canvas.height:0;if(i.vignette.enabled&&i.vignette.strength>0&&l>0&&u>0){let h=c.createRadialGradient(l/2,u/2,Math.min(l,u)*.25,l/2,u/2,Math.max(l,u)*.75);h.addColorStop(0,"rgba(0,0,0,0)"),h.addColorStop(1,"rgba(0,0,0,"+i.vignette.strength.toFixed(3)+")"),c.fillStyle=h,c.fillRect(0,0,l,u)}if(i.scanline.enabled&&i.scanline.strength>0&&l>0&&u>0){c.fillStyle="rgba(0,0,0,"+(i.scanline.strength*.5).toFixed(3)+")";for(let h=0;h0&&l>0&&u>0&&typeof c.getImageData=="function"&&typeof c.putImageData=="function"){let h=c.getImageData(0,0,l,u);Mu(h,i.dither.strength),c.putImageData(h,0,0)}}return{name:"palette-post",version:"1.0.0",dependencies:[],init(o){n=o},dispose(){s||(n=null,s=!0)},applyPaletteMap(o,c){return Go(o,c)},applyPaletteMapToBuffer(o,c){return _u(o,c)},lerpPaletteMap(o,c,l){return Bo(o,c,l)},shiftHsl(o,c){return jo(o,c)},rgbToHsl(o){return oc(o)},hslToRgb(o){return rc(o)},setPost(o){if(o)for(let c of["vignette","dither","scanline"])o[c]&&(typeof o[c].enabled=="boolean"&&(i[c].enabled=o[c].enabled),typeof o[c].strength=="number"&&(i[c].strength=an(o[c].strength)))},getPost(){return{vignette:{enabled:i.vignette.enabled,strength:i.vignette.strength},dither:{enabled:i.dither.enabled,strength:i.dither.strength},scanline:{enabled:i.scanline.enabled,strength:i.scanline.strength}}},renderPost(o){r(o)},probe(){return{disposed:s,post:this.getPost()}}}}function Mu(t,e){let n=an(e);if(n<=0)return t;let{data:s,width:i}=t,a=255/(Math.max(2,Math.round(16-n*14))-1);for(let o=0;o+3>2)%i,l=Math.floor((o>>2)/i),u=(Pu[l&3][c&3]/16-.5)*a;for(let h=0;h<3;h++){let d=s[o+h]+u,f=Math.round(d/a)*a;s[o+h]=f<0?0:f>255?255:f}}return t}function Do(t,e){return typeof t=="boolean"?t:e}function Fo(t,e){return typeof t=="number"?an(t):e}var No=Object.freeze({blip:Object.freeze({name:"blip",params:Object.freeze([.6,0,880,0,.03,.06,1,1.5])}),thud:Object.freeze({name:"thud",params:Object.freeze([.8,0,90,0,.04,.18,0,1,0,0,0,0,0,4])}),chime:Object.freeze({name:"chime",params:Object.freeze([.5,0,660,.02,.12,.3,1,2])})}),cc=Object.keys(No);function Lu(t){let e=[];return t==null||typeof t!="object"?{ok:!1,errors:["song \u5FC5\u987B\u662F\u5BF9\u8C61"]}:(!Array.isArray(t.instruments)||t.instruments.length===0?e.push("instruments \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.instruments.forEach((n,s)=>{(!Array.isArray(n)||n.some(i=>typeof i!="number"||!Number.isFinite(i)))&&e.push(`instruments[${s}] \u5FC5\u987B\u662F\u6709\u9650\u6570\u5B57\u6570\u7EC4\uFF08ZzFX \u53C2\u6570\u5305\uFF09`)}),!Array.isArray(t.patterns)||t.patterns.length===0?e.push("patterns \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.patterns.forEach((n,s)=>{if(!Array.isArray(n)||n.length===0){e.push(`patterns[${s}] \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF08\u81F3\u5C11\u4E00\u4E2A\u58F0\u90E8\u901A\u9053\uFF09`);return}n.forEach((i,r)=>{if(!Array.isArray(i)||i.length<2){e.push(`patterns[${s}][${r}] \u901A\u9053\u81F3\u5C11\u542B [\u4E50\u5668\u7D22\u5F15, \u58F0\u50CF]`);return}if(i.some(c=>typeof c!="number"||!Number.isFinite(c))){e.push(`patterns[${s}][${r}] \u901A\u9053\u5FC5\u987B\u5168\u4E3A\u6709\u9650\u6570\u5B57`);return}let a=i[0]|0;Array.isArray(t.instruments)&&(a<0||a>=t.instruments.length)&&e.push(`patterns[${s}][${r}] \u4E50\u5668\u7D22\u5F15 ${a} \u8D8A\u754C\uFF08instruments \u957F\u5EA6 ${t.instruments.length}\uFF09`);let o=i[1];(o<-1||o>1)&&e.push(`patterns[${s}][${r}] \u58F0\u50CF ${o} \u8D8A\u754C\uFF08\u5E94 -1..+1\uFF09`)})}),!Array.isArray(t.sequence)||t.sequence.length===0?e.push("sequence \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.sequence.forEach((n,s)=>{if(typeof n!="number"||!Number.isInteger(n)){e.push(`sequence[${s}] \u5FC5\u987B\u662F\u6574\u6570 pattern \u7D22\u5F15`);return}Array.isArray(t.patterns)&&(n<0||n>=t.patterns.length)&&e.push(`sequence[${s}] \u7D22\u5F15 ${n} \u8D8A\u754C\uFF08patterns \u957F\u5EA6 ${t.patterns.length}\uFF09`)}),t.bpm!=null&&(typeof t.bpm!="number"||!(t.bpm>0))&&e.push("bpm \u5FC5\u987B\u662F\u6B63\u6570"),{ok:e.length===0,errors:e})}function Ct(t){return typeof t!="number"||Number.isNaN(t)||t<0?0:t>1?1:t}function Ou(t,e){switch(t){case"ease-in":return e*e;case"ease-out":return Math.sqrt(e);case"constant":return 1;default:return e}}function lc(t,e){let n=Ct(e);return t==null||!Array.isArray(t.voices)?[]:t.voices.map(s=>{let i=String(s&&s.id!=null?s.id:""),r=Array.isArray(s&&s.channelIndices)?s.channelIndices.slice():[],a=typeof s.minIntensity=="number"?Ct(s.minIntensity):0,o=typeof s.maxIntensity=="number"?Ct(s.maxIntensity):1,c=typeof s.volumeCurve=="string"?s.volumeCurve:"linear",l=typeof s.baseVolume=="number"?Ct(s.baseVolume):1;if(no)return{id:i,on:!1,volume:0,channelIndices:r};let u=o-a,h=u<=0?1:(n-a)/u,d=Ct(Ou(c,h)*l);return{id:i,on:!0,volume:d,channelIndices:r}})}function uc(t,e,n,s){try{let i=e[0]||[],r=e[1]||i,a=Math.max(i.length,r.length);if(a===0)return null;let c=t.createBuffer(2,a,44100);c.getChannelData(0).set(i),c.getChannelData(1).set(r.length?r:i);let l=t.createBufferSource();l.buffer=c,l.loop=!!s;let u=t.createGain();return u.gain.value=Ct(n*.3),l.connect(u),u.connect(t.destination),l.start(),{stop(){try{l.stop()}catch(h){}try{l.disconnect(),u.disconnect()}catch(h){}}}}catch(i){return zo("[audio-music] \u53D7\u63A7\u97F3\u9891\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",i),null}}function dc(t){let e=t||{},n=typeof e.masterVolume=="number"?Ct(e.masterVolume):1,s=()=>null,i=null,r=null,a={voices:[]},o=1,c=null,l=!1,u=0,h=!1,d=!1;function f(){let S=s();return S==null?(u+=1,h||(Jo("[audio-music] \u65E0\u53D7\u63A7\u97F3\u9891\u4E0A\u4E0B\u6587\uFF08getAudioContext \u8FD4\u56DE null\uFF09\uFF0C\u5168\u90E8\u53D1\u58F0\u9759\u9ED8 no-op\uFF08\u8BC4\u4F30\u73AF\u5883\u65E0\u58F0\u5361\u65F6\u7684\u5BB9\u9519\u964D\u7EA7\uFF09"),h=!0),null):S}function p(){if(!r||!i)return null;try{let S=typeof r.bpm=="number"&&r.bpm>0?r.bpm:125;return i.synthSong(r.instruments,r.patterns,r.sequence,S)}catch(S){return zo("[audio-music] \u66F2\u8C31\u6E32\u67D3\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",S),null}}function y(){let S=lc(a,o);if(S.length===0)return 1;let _=0;for(let C of S)C.on&&(_=Math.max(_,C.volume));return _}function x(S,_){typeof _=="number"&&(o=Ct(_));let C=f();if(C==null||!r)return;w();let k=p();if(!k)return;let L=Ct(n*y());c=uc(C,k,L,S),l=!!S&&c!=null}function w(){c&&(c.stop(),c=null),l=!1}return{name:"audio-music",version:"1.0.0",dependencies:[],init(S){s=()=>S.getAudioContext();let _=S.getEngine&&S.getEngine();i=_?_.audio.synth:null},dispose(){d||(w(),d=!0)},loadSong(S){let _=Lu(S);return _.ok?r={instruments:S.instruments,patterns:S.patterns,sequence:S.sequence,bpm:typeof S.bpm=="number"?S.bpm:125}:Jo("[audio-music] \u66F2\u8C31\u6821\u9A8C\u5931\u8D25\uFF0C\u672A\u8F7D\u5165\uFF1A"+_.errors.join("\uFF1B")),_},play(S){x(!1,S)},stop(){w()},loop(S){x(!0,S)},setIntensityLayering(S){a=S&&Array.isArray(S.voices)?{voices:S.voices}:{voices:[]}},setIntensity(S){o=Ct(S)},resolveVoices(S){return lc(a,S)},playSfx(S){let _=No[S];if(!_){Jo("[audio-music] \u672A\u77E5\u97F3\u6548\u9884\u8BBE\uFF1A"+String(S));return}let C=f();if(C!=null)try{let k=i?i.synthSfx(_.params):null;if(!k)return;uc(C,[k,k],n,!1)}catch(k){zo("[audio-music] \u97F3\u6548\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8 name="+S,k)}},getPreset(S){return No[S]},listPresets(){return cc.slice()},probe(){return{hasAudio:s()!=null,hasSong:r!=null,intensity:o,voiceCount:a.voices.length,looping:l,silentNoops:u,presetCount:cc.length}}}}function zo(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Jo(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Iu="zaomeng.save";function Du(t){if(typeof TextEncoder!="undefined")return new TextEncoder().encode(t).length;if(typeof Buffer!="undefined"&&typeof Buffer.byteLength=="function")return Buffer.byteLength(t,"utf8");let e=0;for(let n=0;n=55296&&s<=56319?(e+=4,n++):e+=3}return e}function Vo(){let t=new Map;return{getItem(e){return t.has(e)?t.get(e):null},setItem(e,n){t.set(e,n)},removeItem(e){t.delete(e)},keys(){return Array.from(t.keys())}}}function fc(){if(typeof localStorage=="undefined")throw new Error("[save-progress] createLocalStorageAdapter \u9700\u8981\u5168\u5C40 localStorage\uFF08\u4EC5\u6D4F\u89C8\u5668\u96C6\u6210\u6BB5\u53EF\u7528\uFF09\u3002node/host-dev \u8BF7\u7528\u7F3A\u7701\u5185\u5B58 adapter \u6216 createMemoryAdapter()\u3002");return{getItem(t){return localStorage.getItem(t)},setItem(t,e){localStorage.setItem(t,e)},removeItem(t){localStorage.removeItem(t)},keys(){let t=[];for(let e=0;e0?e.namespace:Iu;if(n.indexOf(":")>=0)throw new Error('[save-progress] namespace \u4E0D\u5F97\u542B\u5206\u9694\u7B26 ":"\uFF08\u5F53\u524D="'+n+'"\uFF09');let s=typeof e.maxValueBytes=="number"&&e.maxValueBytes>0?Math.floor(e.maxValueBytes):32768,i=!Fu(e.adapter),r=i?Vo():e.adapter,a=n+":",o=0,c=0,l=!1;function u(f){return typeof f!="string"||f.length===0?a+String(f):a+f}function h(){try{let f=r.keys();return Array.isArray(f)?f.filter(p=>typeof p=="string"&&p.indexOf(a)===0):[]}catch(f){return ws("[save-progress] adapter.keys() \u5F02\u5E38\uFF0C\u964D\u7EA7\u8FD4\u56DE\u7A7A\u96C6",f),[]}}return{name:"save-progress",version:"1.0.0",dependencies:[],init(f){h()},dispose(){},get(f,p){if(!Uo(f))return p;let y;try{y=r.getItem(u(f))}catch(x){return ws("[save-progress] adapter.getItem \u5F02\u5E38\uFF0C\u8FD4\u56DE\u9ED8\u8BA4\u503C key="+f,x),p}if(y==null)return p;try{return JSON.parse(y)}catch{return o+=1,l||(Ts("[save-progress] \u68C0\u6D4B\u5230\u635F\u574F\u5B58\u6863\uFF08\u975E\u6CD5 JSON\uFF09\uFF0C\u5DF2\u5BB9\u9519\u56DE\u9000\u9ED8\u8BA4\u503C key="+f),l=!0),p}},set(f,p){if(!Uo(f))return Ts("[save-progress] set \u6536\u5230\u975E\u6CD5 key\uFF0C\u62D2\u7EDD\u5199\u5165\uFF1A"+String(f)),!1;let y;try{y=JSON.stringify(p)}catch{return c+=1,Ts("[save-progress] \u503C\u4E0D\u53EF JSON \u5E8F\u5217\u5316\uFF08\u5FAA\u73AF\u5F15\u7528?\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+f),!1}if(y===void 0)return c+=1,Ts("[save-progress] \u503C\u5E8F\u5217\u5316\u4E3A undefined\uFF08\u5982\u7EAF undefined/\u51FD\u6570\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+f),!1;let x=Du(y);if(x>s)return c+=1,Ts("[save-progress] \u503C\u8D85\u5B57\u8282\u4E0A\u9650\u62D2\u7EDD\u5199\u5165 key="+f+"\uFF08"+x+" > "+s+" bytes\uFF09"),!1;try{return r.setItem(u(f),y),!0}catch(w){return c+=1,ws("[save-progress] adapter.setItem \u5F02\u5E38\uFF0C\u5199\u5165\u5931\u8D25 key="+f,w),!1}},remove(f){if(Uo(f))try{r.removeItem(u(f))}catch(p){ws("[save-progress] adapter.removeItem \u5F02\u5E38\uFF08\u5DF2\u5FFD\u7565\uFF09key="+f,p)}},clear(){let f=h(),p=0;for(let y of f)try{r.removeItem(y),p+=1}catch(x){ws("[save-progress] clear \u65F6 removeItem \u5F02\u5E38\uFF08\u5DF2\u8DF3\u8FC7\uFF09fullKey="+y,x)}return p},probe(){return{namespace:n,maxValueBytes:s,usingMemoryAdapter:i,size:h().length,corruptRecoveries:o,rejectedWrites:c}}}}function Uo(t){return typeof t=="string"&&t.length>0}function Fu(t){return!!t&&typeof t.getItem=="function"&&typeof t.setItem=="function"&&typeof t.removeItem=="function"&&typeof t.keys=="function"}function ws(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Ts(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Qn=[{id:"soda",name:"\u6C7D\u6C34",wholesale:20,basePrice:40,popularity:1,initial:!0},{id:"snack",name:"\u8FA3\u6761",wholesale:10,basePrice:25,popularity:1.2,initial:!0},{id:"bread",name:"\u9762\u5305",wholesale:30,basePrice:60,popularity:.8,initial:!0},{id:"ice",name:"\u51B0\u6DC7\u6DCB",wholesale:40,basePrice:90,popularity:.7,initial:!1},{id:"toy",name:"\u5C0F\u73A9\u5177",wholesale:80,basePrice:180,popularity:.35,initial:!1}];function Ye(t){return Qn.find(e=>e.id===t)}var Me={lengthSec:96,rushStartSec:30,rushEndSec:66,rushRampSec:3,daysPerSegment:3};function pc(t){let{rushStartSec:e,rushEndSec:n,rushRampSec:s}=Me;return t<=e-s||t>=n+s?0:t>=e&&t<=n?1:te.id===t)}function Ho(t){let e=n=>!!t[n];return{shelfCap:e("shelf2")?48:e("shelf1")?34:24,serveCooldownSec:e("speed2")?.32:e("speed1")?.42:.55,patienceMul:e("decor2")?1.3:e("decor1")?1.15:1,settleRepBonusTenth:e("decor2")?60:e("decor1")?30:0,flowMul:e("decor2")?1.12:1}}function Si(t){let e=t.priceMul,n=t.reputation==null?Xe.start:t.reputation,s=t.serveCapacity==null?26:t.serveCapacity,i=t.stockUnits==null?1/0:t.stockUnits,r=t.segment==null?1:t.segment,a=t.unlocked||Qn.filter(x=>x.initial).map(x=>x.id),l=((Me.lengthSec-(Me.rushEndSec-Me.rushStartSec))/cn.idleIntervalSec+(Me.rushEndSec-Me.rushStartSec)/cn.rushIntervalSec)*qo(e)*Wo(n),u=Math.min(l,s,i),h=a.map(x=>Ye(x)).filter(Boolean),d=h.reduce((x,w)=>x+w.popularity,0),f=h.reduce((x,w)=>x+(Math.round(w.basePrice*e)-w.wholesale)*(w.popularity/d),0),p=Math.round(u*f),y=ce.rentBaseJiao+(r-1)*ce.rentPerSegmentJiao;return{arrivals:l,served:u,grossJiao:p,rentJiao:y,profitJiao:p-y}}function ze(t,e,n){return tn?n:t}function Ke(t){let e=t/10;return Number.isInteger(e)?String(e):e.toFixed(1)}var gc=1,Gu=2600;function As(t){let e=t.random;if(!e||typeof e.next!="function")throw new Error("[shop-core] \u5FC5\u987B\u6CE8\u5165\u53D7\u63A7\u968F\u673A\u6E90 random\uFF08next/range/reseed\uFF09");let n=0,s={nowMs:()=>n,elapsedMs:()=>n},i=new mi(s,{windowMs:Gu,maxCount:99}),r=[];function a(T,P){r.push(Object.assign({type:T,tMs:Math.round(n)},P||{}))}let o={phase:"title",day:1,cash:ce.startCashJiao,repTenth:Xe.start*10,priceMul:1,stock:{},unlocked:Qn.filter(T=>T.initial).map(T=>T.id),upgrades:{},customers:[],dayTimeSec:0,rushFactor:0,serveCooldown:0,comboCount:0,prepBought:{},today:c(),lifetime:{days:0,served:0,angry:0,netJiao:0,upgradesBought:0},settle:null,summary:null,gameoverReason:null};function c(){return{revenueJiao:0,soldCostJiao:0,served:0,angry:0,stockout:0,walkaway:0,rescued:0,bigSales:0,maxCombo:0}}let l=1,u=0,h=!1,d=Ho(o.upgrades);function f(){d=Ho(o.upgrades)}function p(){let T=0;for(let P of Object.keys(o.stock))T+=o.stock[P];return T}function y(){return o.repTenth/10}function x(T){o.repTenth=ze(o.repTenth+T,0,Xe.max*10)}function w(T){let P=o.phase;o.phase=T,a("phase_changed",{from:P,to:T})}function A(T){o.day=T,o.prepBought={},o.today=c(),o.customers=[],o.dayTimeSec=0,o.rushFactor=0,o.settle=null,o.summary=null,w("prep"),a("save_point",{})}function S(){let T=o.rushFactor>.5?cn.rushIntervalSec:cn.idleIntervalSec,P=qo(o.priceMul)*Wo(y())*d.flowMul;u=T/Math.max(P,.05)*e.range(cn.jitterMin,cn.jitterMax)}function _(){let T=o.unlocked.map(M=>Ye(M)),P=T.reduce((M,j)=>M+j.popularity,0),R=e.next()*P;for(let M of T)if(R-=M.popularity,R<=0)return M.id;return T[T.length-1].id}function C(){for(let T=0;TP.slot===T))return T;return-1}function k(){let T=_(),P=C();if(P<0){o.today.walkaway+=1,a("walkaway_full",{productId:T});return}let M=(o.rushFactor>.5?kn.rushSec:kn.idleSec)*d.patienceMul*e.range(.9,1.12),j={id:l++,productId:T,slot:P,mood:"queue",patienceSec:M,patienceMaxSec:M,timerSec:0,avatar:Math.floor(e.next()*4)%4,impatientFired:!1};(o.stock[T]||0)<=0&&(j.mood="stockout",j.timerSec=kn.stockoutLingerSec),o.customers.push(j),a("customer_arrive",{id:j.id,slot:P,productId:T,mood:j.mood})}function L(T){let P=o.customers.indexOf(T);P>=0&&o.customers.splice(P,1)}function V(T){o.dayTimeSec+=T,o.rushFactor=pc(o.dayTimeSec);let P=o.rushFactor>.5;if(P!==h&&(a(P?"rush_start":"rush_end",{}),h=P),o.serveCooldown>0&&(o.serveCooldown=Math.max(0,o.serveCooldown-T)),o.dayTimeSec>=Me.lengthSec){a("closing",{}),o.customers=[],ae();return}u-=T,u<=0&&(k(),S());for(let R=o.customers.length-1;R>=0;R--){let M=o.customers[R];if(M.mood==="queue"){if((o.stock[M.productId]||0)<=0){M.mood="stockout",M.timerSec=kn.stockoutLingerSec;continue}M.patienceSec-=T,!M.impatientFired&&M.patienceSec/M.patienceMaxSec<=kn.impatientRatio&&(M.impatientFired=!0,a("customer_impatient",{id:M.id,slot:M.slot})),M.patienceSec<=0&&(M.mood="leaving",M.timerSec=kn.graceSec,a("customer_grace",{id:M.id,slot:M.slot}))}else M.mood==="leaving"?(M.timerSec-=T,M.timerSec<=0&&(L(M),o.today.angry+=1,x(-Xe.angryLossTenth),a("angry_leave",{id:M.id,slot:M.slot,avatar:M.avatar,productId:M.productId,repLossTenth:Xe.angryLossTenth}))):M.mood==="stockout"&&(M.timerSec-=T,M.timerSec<=0&&(L(M),o.today.stockout+=1,x(-Xe.stockoutLossTenth),a("stockout_leave",{id:M.id,slot:M.slot,avatar:M.avatar,productId:M.productId,repLossTenth:Xe.stockoutLossTenth})))}o.comboCount=i.getCount(n)}function ae(){let T=o.today,P=Math.ceil(o.day/Me.daysPerSegment),R=ce.rentBaseJiao+(P-1)*ce.rentPerSegmentJiao,M=0;y()P.initial).map(P=>P.id),o.upgrades={},o.lifetime={days:0,served:0,angry:0,netJiao:0,upgradesBought:0},o.gameoverReason=null,f(),i.reset(),a("game_start",{continued:!1}),A(1),{ok:!0,continued:!1})},buyStock(T,P){let R=Math.max(1,Math.floor(P||1));if(o.phase!=="prep")return{ok:!1,reason:"phase"};let M=Ye(T);if(!M||!o.unlocked.includes(T))return{ok:!1,reason:"unknown_product"};if(p()+R>d.shelfCap)return{ok:!1,reason:"shelf_full"};let j=M.wholesale*R;return o.cash0)return{ok:!1,reason:"cooldown"};if(!o.unlocked.includes(T))return{ok:!1,reason:"unknown_product"};if((o.stock[T]||0)<=0)return a("tap_empty",{productId:T}),{ok:!1,reason:"no_stock"};let P=o.customers.filter(H=>H.productId===T&&(H.mood==="queue"||H.mood==="leaving")).sort((H,W)=>H.id-W.id)[0];if(!P)return a("tap_nocustomer",{productId:T}),{ok:!1,reason:"no_customer"};let R=P.mood==="leaving";o.stock[T]-=1;let M=i.hit(n);o.comboCount=M,o.today.maxCombo=Math.max(o.today.maxCombo,M);let j=Math.round(mc(T,o.priceMul)*yc(M));o.cash+=j,o.today.revenueJiao+=j,o.today.soldCostJiao+=Ye(T).wholesale,o.today.served+=1,o.lifetime.served+=1,R&&(o.today.rescued+=1),x(Xe.serveGainTenth+(R?Xe.rescueBonusTenth:0)),o.serveCooldown=d.serveCooldownSec;let G=j>=ce.bigSaleJiao;return G&&(o.today.bigSales+=1),L(P),a("serve_ok",{id:P.id,slot:P.slot,avatar:P.avatar,productId:T,revenueJiao:j,combo:M,big:G,rescued:R}),{ok:!0,revenueJiao:j,combo:M,big:G,rescued:R,customerId:P.id}},confirmSettle(){if(o.phase!=="settle")return{ok:!1,reason:"phase"};let T=o.day;if(a("save_point",{}),T%Me.daysPerSegment===0){let P=T/Me.daysPerSegment;o.summary={segment:P,days:T,netJiao:o.lifetime.netJiao,served:o.lifetime.served,upgradesBought:o.lifetime.upgradesBought,reputation:y()},w("summary"),a("segment_end",{summary:o.summary})}else A(T+1);return{ok:!0}},confirmSummary(){return o.phase!=="summary"?{ok:!1,reason:"phase"}:(A(o.day+1),{ok:!0})},derived(){return d},reputation:y,totalStock:p,snapshotForSave(){return{v:gc,day:o.day,cash:o.cash,repTenth:o.repTenth,priceMul:o.priceMul,stock:Object.assign({},o.stock),unlocked:o.unlocked.slice(),upgrades:Object.assign({},o.upgrades),lifetime:Object.assign({},o.lifetime)}},restoreFromSave(T){return!T||T.v!==gc||typeof T.day!="number"||typeof T.cash!="number"||typeof T.repTenth!="number"||!T.unlocked||!Array.isArray(T.unlocked)||T.unlocked.length===0?!1:(o.cash=Math.floor(T.cash),o.repTenth=ze(Math.floor(T.repTenth),0,Xe.max*10),o.priceMul=ze(T.priceMul||1,ce.priceMin,ce.priceMax),o.stock=Object.assign({},T.stock||{}),o.unlocked=T.unlocked.filter(P=>!!Ye(P)),o.upgrades=Object.assign({},T.upgrades||{}),o.lifetime=Object.assign({days:0,served:0,angry:0,netJiao:0,upgradesBought:0},T.lifetime||{}),o.gameoverReason=null,f(),i.reset(),a("game_start",{continued:!0}),A(Math.max(1,Math.floor(T.day))),!0)}};return ne}var ks={open_shop:["\u5F00\u5F20\u55BD\u2014\u2014\u8857\u574A\u4EEC\u90FD\u7B49\u7740\u5462\uFF01","\u4ECA\u513F\u4E2A\u8FDB\u70B9\u5565\u597D\u8D27\uFF1F\u6211\u5FC3\u91CC\u6709\u6570\u3002","\u5C0F\u672C\u751F\u610F\uFF0C\u8D26\u53EF\u5F97\u7B97\u660E\u767D\u54AF\u3002"],day_start:["\u5F00\u95E8\u8FCE\u5BA2\uFF01\u90FD\u9EBB\u5229\u70B9\u513F~","\u54DF\uFF0C\u4ECA\u5929\u592A\u9633\u4E0D\u9519\uFF0C\u51C6\u662F\u4E2A\u597D\u65E5\u5B50\u3002"],idle_chat:["\u6162\u60A0\u60A0\u7684\u4E0B\u5348\uFF0C\u6700\u9002\u5408\u76D8\u8D26\u5566\u3002","\u9694\u58C1\u8001\u674E\u53C8\u6765\u8D4A\u8D26\uFF1F\u60F3\u5F97\u7F8E\u3002","\u8D27\u67B6\u64E6\u5F97\u9503\u4EAE\uFF0C\u770B\u7740\u5C31\u8212\u5766\u3002"],rush_start:["\u653E\u5B66\u5566\u653E\u5B66\u5566\uFF0C\u6253\u8D77\u7CBE\u795E\u6765\uFF01","\u4EBA\u90FD\u6D8C\u8FC7\u6765\u4E86\uFF0C\u624B\u4E0A\u522B\u505C\uFF01"],serve_ok:["\u597D\u561E\uFF0C\u62FF\u7A33\u5F53\uFF01","\u60A8\u6162\u8D70\uFF0C\u5E38\u6765\u554A~","\u8FD9\u5C31\u7ED9\u60A8\u62FF\uFF0C\u5FEB\u5F97\u5F88\uFF01"],combo_hot:["\u624B\u611F\u6765\u4E86\uFF0C\u8C01\u90FD\u522B\u62E6\u6211\uFF01","\u4E00\u4E2A\u63A5\u4E00\u4E2A\uFF0C\u8D8A\u5E72\u8D8A\u987A\u6E9C\uFF01"],big_sale:["\u54CE\u54DF\uFF0C\u5927\u4E3B\u987E\uFF01\u4ECA\u665A\u52A0\u4E2A\u9E21\u817F\uFF01","\u8FD9\u5355\u9876\u534A\u5929\u4E70\u5356\uFF0C\u7F8E\u6ECB\u6ECB~"],rescue:["\u522B\u8D70\u522B\u8D70\uFF0C\u8FD9\u5C31\u7ED9\u60A8\u62FF\u4E0A\uFF01","\u597D\u9669\u597D\u9669\uFF0C\u5DEE\u70B9\u513F\u9EC4\u4E86\u4E00\u5355\u3002"],angry:["\u54CE\u5440\uFF0C\u628A\u4EBA\u667E\u8DD1\u4E86\u2026\u2026\u5FC3\u75BC\u3002","\u7838\u62DB\u724C\u4E86\u7838\u62DB\u724C\u4E86\uFF0C\u5F97\u4E0A\u70B9\u5FC3\uFF01"],stockout:["\u7A7A\u8D27\u67B6\u6700\u6233\u5FC3\u7A9D\u5B50\uFF0C\u660E\u513F\u591A\u5907\u70B9\u3002","\u53C8\u5356\u65AD\u4E86\u2026\u2026\u662F\u597D\u4E8B\u4E5F\u662F\u574F\u4E8B\u3002"],settle_win:["\u4ECA\u513F\u8D26\u9762\u7EA2\u706B\uFF0C\u8BB0\u4E0A\u8BB0\u4E0A\uFF01","\u8F9B\u82E6\u4E00\u5929\uFF0C\u503C\u5F53\uFF01"],settle_lose:["\u8FD9\u8D26\u2026\u2026\u8D8A\u7B97\u8D8A\u5FC3\u51C9\u3002","\u7F5A\u5355\u90FD\u8D34\u8138\u4E0A\u4E86\uFF0C\u660E\u5929\u5F97\u6362\u4E2A\u6D3B\u6CD5\u3002"],upgrade:["\u820D\u4E0D\u5F97\u5B69\u5B50\u5957\u4E0D\u7740\u72FC\uFF0C\u5347\uFF01","\u9E1F\u67AA\u6362\u70AE\uFF0C\u54B1\u4E5F\u8BB2\u7A76\u4E00\u56DE\uFF01"],gameover:["\u5509\u2026\u2026\u5377\u5E18\u95E8\u4E00\u62C9\uFF0C\u4ECE\u5934\u518D\u6765\u5427\u3002"]},bp=Object.keys(ks).length;function bc(t){let e={};return function(s){let i=ks[s];if(!i||i.length===0)return"";if(i.length===1)return i[0];let r=Math.floor(t.next()*i.length)%i.length;return r===e[s]&&(r=(r+1)%i.length),e[s]=r,i[r]}}var Cs={paper:{r:246,g:231,b:201},paperHi:{r:255,g:246,b:227},cream:{r:255,g:243,b:220},ink:{r:91,g:70,b:54},inkSoft:{r:138,g:108,b:84},wood:{r:169,g:118,b:79},woodDark:{r:124,g:84,b:55},gold:{r:232,g:169,b:66},coin:{r:246,g:196,b:83},amber:{r:240,g:196,b:117},brick:{r:201,g:111,b:74},danger:{r:178,g:72,b:54},leaf:{r:133,g:158,b:94},sky:{r:243,g:217,b:168},shadow:{r:62,g:49,b:40},scrim:{r:46,g:35,b:27},smoke:{r:140,g:106,b:85}},xc=Object.keys(Cs);function Sc(){let t=xc.map(a=>Cs[a]),e={from:t,to:t.slice()},n={from:t,to:t.map(a=>jo(a,{hue:-10,sat:1.18,light:.9}))},s=0,i=r(0);function r(a){let o=Bo(e,n,a),c={};for(let l of xc)c[l]=Go(o,Cs[l]);return c}return{setRush(a){let o=Math.round(Math.max(0,Math.min(1,a))*25)/25;o!==s&&(s=o,i=r(o))},rushT(){return s},c(a,o){let c=i[a]||Cs.ink,l=o==null?1:o;return l>=1?`rgb(${c.r},${c.g},${c.b})`:`rgba(${c.r},${c.g},${c.b},${l})`},rgb(a){return i[a]||Cs.ink}}}var $o={shopkeeperIdle:"shopkeeper-idle.jpg",shopkeeperWave:"shopkeeper-wave.jpg",customer0:"customer-kid.jpg",customer1:"customer-lady.jpg",customer2:"customer-grandpa.jpg",customer3:"customer-auntie.jpg",storefront:"storefront.jpg",itemSoda:"item-soda.jpg",itemSnack:"item-snack.jpg",itemBread:"item-bread.jpg",itemIce:"item-ice.jpg",itemToy:"item-toy.jpg",uiPanel:"ui-panel.jpg"},Cn={soda:"itemSoda",snack:"itemSnack",bread:"itemBread",ice:"itemIce",toy:"itemToy"};function vc(t){let e=t==null?"./assets/":t,n=Object.keys($o),s={},i=[];function r(a){return new Promise(o=>{if(typeof Image=="undefined"){s[a]=null,i.push(a),o(null);return}let c=new Image;c.onload=()=>{s[a]=c,o(c)},c.onerror=()=>{console.warn("[ref-assets] \u8D44\u4EA7\u52A0\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u7A0B\u5E8F\u5316\u56DE\u9000\uFF09\uFF1A"+$o[a]),s[a]=null,i.push(a),o(null)},c.src=e+$o[a]})}return Promise.all(n.map(r)).then(()=>({images:s,missing:i,loaded:n.length-i.length,total:n.length}))}function wc(t){let e=t.bundle,n=t.juice;function s(T){let P=bi({maxParticles:400});return P.init(e.deriveContextFor(T,T)),P}let i=s("fx-gold"),r=s("fx-cream"),a=s("fx-smoke"),o=[];function c(T,P,R){o.push({t:0,dur:Math.max(T,.001),ease:R&&R.ease||Mo.cubicOut,onUpdate:P,onDone:R&&R.onDone||null})}let l=new Map;function u(T,P){let R=l.get(T);return R||(R={state:{x:P==null?1:P,v:0},target:P==null?1:P,stiffness:320,damping:14},l.set(T,R)),R.state.x}function h(T,P,R){u(T);let M=l.get(T);M.state.v+=P,R!=null&&(M.target=R)}let d=[];function f(T){d.push({t:0,dur:T.dur||.3,fx:T.fx,fy:T.fy,tx:T.tx,ty:T.ty,arc:T.arc==null?46:T.arc,imageKey:T.imageKey||null,label:T.label||"",onArrive:T.onArrive||null})}let p=[],y=980;function x(T){let P=T.dur||.45,R=(T.tx-T.fx)/P,M=(T.ty-T.fy-.5*y*P*P)/P;p.push({proj:new hi({px:T.fx,py:T.fy,vx:R,vy:M},{gravity:{x:0,y}}),age:0,dur:P,tx:T.tx,ty:T.ty,imageKey:T.imageKey||null,onLand:T.onLand||null})}let w=[];function A(T,P,R,M,j){w.push({text:T,x:P,y:R,t:0,dur:.9,colorName:M||"gold",size:j||16})}let S=[];function _(T,P){S.push({x:T,y:P,t:0})}function C(T,P,R){i.spawnEmitter("burst",T,P,{count:R?26:13,angle:-Math.PI/2,spread:.85,speedMin:130,speedMax:R?320:240,gravity:420,lifeMin:.35,lifeMax:.7,sizeCurve:{kind:"decay",from:R?5.5:4,to:0,power:1.3}})}function k(T,P,R){r.spawnEmitter("burst",T,P,{count:R||10,angle:-Math.PI/2,spread:1.1,speedMin:40,speedMax:110,gravity:-30,lifeMin:.4,lifeMax:.8,sizeCurve:{kind:"decay",from:3,to:0,power:1}})}function L(T,P){a.spawnEmitter("burst",T,P,{count:12,angle:-Math.PI/2,spread:Math.PI,speedMin:25,speedMax:70,gravity:-18,drag:1.2,lifeMin:.5,lifeMax:1,sizeCurve:{kind:"easeInOut",from:5,to:1},alphaCurve:{kind:"decay",from:.7,to:0,power:1.5}})}function V(T,P){for(let R=o.length-1;R>=0;R--){let M=o[R];M.t+=T;let j=Math.min(M.t/M.dur,1);M.onUpdate(M.ease(j)),j>=1&&(M.onDone&&M.onDone(),o.splice(R,1))}for(let R of l.values())R.state=Za(R.state,R.target,{stiffness:R.stiffness,damping:R.damping},T);for(let R=d.length-1;R>=0;R--){let M=d[R];M.t+=P,M.t>=M.dur&&(M.onArrive&&M.onArrive(),d.splice(R,1))}for(let R=p.length-1;R>=0;R--){let M=p[R];M.age+=P,M.proj.step(P),M.age>=M.dur&&(M.onLand&&M.onLand(),p.splice(R,1))}for(let R=w.length-1;R>=0;R--){let M=w[R];M.t+=P,M.t>=M.dur&&w.splice(R,1)}for(let R=S.length-1;R>=0;R--)S[R].t+=T,S[R].t>=.32&&S.splice(R,1)}function ae(T,P){T.save(),T.fillStyle=P.c("coin"),i.render(T),T.fillStyle=P.c("cream"),r.render(T),T.fillStyle=P.c("smoke"),a.render(T),T.restore(),n.render(T)}return{easing:Mo,addTween:c,springVal:u,springKick:h,addFlight:f,addToss:x,addFloater:A,addTapRing:_,burstCoin:C,burstSparkle:k,burstSmoke:L,step:V,renderParticles:ae,view:{flights:d,tosses:p,floaters:w,tapRings:S},juice:n,particleProbe(){return{gold:i.particleCount(),cream:r.particleCount(),smoke:a.particleCount()}},dispose(){i.dispose(),r.dispose(),a.dispose()}}}function Tc(t){let e=t.getAudio,n=t.p6,s=t.baseUrl==null?"./assets/":t.baseUrl,i=new Set,r={loading:!1,ready:!1,failed:!1,gainIdle:null,gainRush:null,idleLevel:0,rushLevel:0,targetRush:0},a=null;function o(d){return a||(a=d.createGain(),a.gain.value=.5,a.connect(d.destination)),a}function c(){let d=e();if(!d||r.loading||r.ready||r.failed)return;r.loading=!0;function f(p){return fetch(s+p).then(y=>{if(!y.ok)throw new Error("HTTP "+y.status);return y.arrayBuffer()}).then(y=>d.decodeAudioData(y)).then(y=>{let x=d.createBufferSource();x.buffer=y,x.loop=!0;let w=d.createGain();return w.gain.value=0,x.connect(w),w.connect(d.destination),x.start(),w})}Promise.all([f("bgm-idle.mp3"),f("bgm-rush.mp3")]).then(([p,y])=>{r.gainIdle=p,r.gainRush=y,r.ready=!0,r.loading=!1}).catch(p=>{console.warn("[ref-audio] BGM \u88C5\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u65E0 BGM\uFF09\uFF1A"+(p&&p.message?p.message:p)),r.failed=!0,r.loading=!1})}function l(d,f,p){if(r.targetRush=f,!r.ready)return;let y=p?1:.35,x=.5*(1-f)*y,w=.55*f*y,A=Math.min(d/1.2,1);r.idleLevel+=(x-r.idleLevel)*A,r.rushLevel+=(w-r.rushLevel)*A,r.gainIdle.gain.value=r.idleLevel,r.gainRush.gain.value=r.rushLevel}function u(d,f,p,y,x,w,A){let S=d.currentTime+(A||0),_=d.createOscillator(),C=d.createGain();_.type=f,_.frequency.setValueAtTime(p,S),_.frequency.exponentialRampToValueAtTime(Math.max(y,1),S+x),C.gain.setValueAtTime(1e-4,S),C.gain.exponentialRampToValueAtTime(w,S+.012),C.gain.exponentialRampToValueAtTime(1e-4,S+x),_.connect(C),C.connect(o(d)),_.start(S),_.stop(S+x+.02)}function h(d,f){let p=e();if(!p)return;let y=f||{};switch(d){case"arrive":n.playSfx("blip");break;case"shelve":n.playSfx("thud");break;case"upgrade":n.playSfx("chime");break;case"coin":{let x=Math.min(y.combo||1,11),w=660*Math.pow(2,(x-1)*2/12);u(p,"sine",w,w*1.5,.16,.5),u(p,"sine",w*2,w*2.6,.1,.22,.03);break}case"bad":u(p,"sawtooth",220,90,.32,.3);break;case"rescue":u(p,"triangle",520,540,.07,.32),u(p,"triangle",660,690,.07,.32,.07),u(p,"triangle",880,920,.1,.34,.14);break;case"bigsale":u(p,"sine",130,80,.22,.5),u(p,"sine",1320,1760,.18,.3,.05);break;case"tick":u(p,"triangle",900,700,.045,.16);break;case"empty":u(p,"square",180,140,.08,.14);break;default:return}i.add(d)}return{startBgm:c,step:l,sfx:h,probe(){return{sfxKinds:Array.from(i),bgm:{ready:r.ready,failed:r.failed,idleLevel:r.idleLevel,rushLevel:r.rushLevel}}}}}var U=390,Zn=844,Le={hud:{x:8,y:8,w:U-16,h:84},keeper:{x:14,y:398,w:124,h:160},bubble:{x:16,y:318,w:230,h:72},queue:[{x:186,y:470},{x:244,y:452},{x:302,y:470},{x:356,y:452}],avatarR:27,counter:{x:0,y:540,w:U,h:26},shelf:{x:8,y:574,w:U-16,h:158},bottom:{x:8,y:740,w:U-16,h:96},combo:{x:330,y:512}};function En(t){let e=t%3,n=Math.floor(t/3);return{x:16+e*124,y:584+n*76,w:116,h:68}}function kc(t){let e={x:12,y:116,w:U-24,h:706},n=196,s=46,i=n+t.length*s+26,r=i+64,a=42,o={x:U/2-110,y:e.y+e.h-70,w:220,h:54};return{panel:e,stockY:n,rowH:s,sliderY:i,upY:r,upRowH:a,btn:o}}function Cc(t){return{x:78,y:t+26,w:240,h:8}}function Qe(t,e,n,s,i,r){let a=Math.min(r,s/2,i/2);t.beginPath(),t.moveTo(e+a,n),t.arcTo(e+s,n,e+s,n+i,a),t.arcTo(e+s,n+i,e,n+i,a),t.arcTo(e,n+i,e,n,a),t.arcTo(e,n,e+s,n,a),t.closePath()}function q(t,e,n){t.font=`${n?"600 ":""}${e}px "PingFang SC","Microsoft YaHei",sans-serif`}function Xo(t,e,n,s,i,r){let a=e.width/e.height,o=i/r,c=0,l=0,u=e.width,h=e.height;a>o?(u=e.height*o,c=(e.width-u)/2):(h=e.width/o,l=(e.height-h)/2),t.drawImage(e,c,l,u,h,n,s,i,r)}function _n(t,e,n,s,i,r,a,o,c){t.save(),Qe(t,s,i,r,a,o),t.clip(),n?Xo(t,n,s,i,r,a):(t.fillStyle=e.c("amber"),t.fillRect(s,i,r,a),t.fillStyle=e.c("ink"),q(t,Math.min(a*.42,22),!0),t.textAlign="center",t.textBaseline="middle",t.fillText(c||"?",s+r/2,i+a/2)),t.restore()}function Ac(t,e,n,s,i,r,a){t.save(),t.beginPath(),t.arc(s,i,r,0,Math.PI*2),t.clip(),n?Xo(t,n,s-r,i-r,r*2,r*2):(t.fillStyle=e.c("sky"),t.fillRect(s-r,i-r,r*2,r*2),t.fillStyle=e.c("ink"),q(t,r,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a||"\u5BA2",s,i)),t.restore()}function _t(t,e,n,s,i,r,a,o){t.save(),Qe(t,s,i,r,a,o==null?14:o),t.clip();let c=n.images.uiPanel;c?t.drawImage(c,c.width*.2,c.height*.04,c.width*.78,c.height*.9,s,i,r,a):(t.fillStyle=e.c("paper"),t.fillRect(s,i,r,a)),t.restore(),t.strokeStyle=e.c("wood"),t.lineWidth=2,Qe(t,s,i,r,a,o==null?14:o),t.stroke()}function ln(t,e,n,s,i,r,a,o){let c=o||{},l=c.scale==null?1:c.scale;t.save(),t.translate(n+i/2,s+r/2),t.scale(l,l),Qe(t,-i/2,-r/2,i,r,r/2-6),t.fillStyle=c.disabled?e.c("inkSoft",.45):e.c(c.color||"brick"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("paperHi"),q(t,c.fontSize||20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a,0,1),t.restore()}function Yo(t,e,n,s,i,r,a,o,c){Qe(t,n,s,i,r,r/2),t.fillStyle=e.c(c||"shadow",.25),t.fill();let l=ze(a,0,1);l>.01&&(Qe(t,n,s,Math.max(i*l,r),r,r/2),t.fillStyle=e.c(o||"gold"),t.fill())}function Bu(t,e,n){let s=n.images.storefront;s?Xo(t,s,0,0,U,Zn):(t.fillStyle=e.c("sky"),t.fillRect(0,0,U,Zn));let i=t.createLinearGradient(0,380,0,560);i.addColorStop(0,e.c("paper",0)),i.addColorStop(.5,e.c("paper",.28)),i.addColorStop(1,e.c("paper",.05)),t.fillStyle=i,t.fillRect(0,380,U,190)}function ju(t,e,n){let{core:s,fx:i,assets:r}=n,a=s.state,o=Le.hud;_t(t,e,r,o.x,o.y,o.w,o.h,12),t.textBaseline="middle",t.fillStyle=e.c("ink"),q(t,16,!0),t.textAlign="left",t.fillText(`\u7B2C ${a.day} \u5929`,o.x+12,o.y+24);let c={x:o.x+86,y:o.y+18,w:168,h:11};Yo(t,e,c.x,c.y,c.w,c.h,a.phase==="open"?a.dayTimeSec/Me.lengthSec:0,"amber");let l=c.x+Me.rushStartSec/Me.lengthSec*c.w,u=(Me.rushEndSec-Me.rushStartSec)/Me.lengthSec*c.w;t.fillStyle=e.c("brick",.4),t.fillRect(l,c.y+c.h+2,u,3),t.save();let h=i.springVal("hud-cash",1);t.translate(o.x+o.w-12,o.y+24),t.scale(h,h),t.textAlign="right",t.fillStyle=e.c("gold"),q(t,19,!0),t.fillText(`\xA5${Ke(a.cash)}`,0,0),t.restore(),t.textAlign="left",t.fillStyle=e.c("inkSoft"),q(t,13),t.fillText("\u53E3\u7891",o.x+12,o.y+58);let d=s.reputation(),f=d<30?"danger":d<55?"brick":"leaf";Yo(t,e,o.x+48,o.y+52,150,12,d/100,f),t.fillStyle=e.c(f),q(t,13,!0),t.fillText(String(Math.round(d)),o.x+204,o.y+58),t.fillStyle=e.c("danger",.8),t.fillRect(o.x+48+150*.3-1,o.y+50,2,16),t.textAlign="right",t.fillStyle=e.c("inkSoft"),q(t,13),t.fillText(`\u4ECA\u65E5 ${a.today.served} \u5355 \xB7 \xA5${Ke(a.today.revenueJiao)}`,o.x+o.w-12,o.y+58)}function Ju(t,e,n){let{assets:s,ui:i,fx:r}=n,a=Le.keeper,o=Math.sin(n.nowMs/620)*1.5;t.save(),t.translate(0,o),_t(t,e,s,a.x,a.y,a.w,a.h,14);let c=i.keeperWaveUntil>n.nowMs?s.images.shopkeeperWave:s.images.shopkeeperIdle;if(_n(t,e,c,a.x+6,a.y+6,a.w-12,a.h-34,10,"\u5E97\u4E3B"),t.fillStyle=e.c("ink"),q(t,13,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u8001\u677F\u5A18",a.x+a.w/2,a.y+a.h-15),t.restore(),i.bubbleText&&i.bubbleUntil>n.nowMs){let l=Le.bubble,u=r.springVal("bubble",1),h=ze((i.bubbleUntil-n.nowMs)/350,0,1);t.save(),t.globalAlpha=h,t.translate(l.x+l.w/2,l.y+l.h/2),t.scale(u,u),Qe(t,-l.w/2,-l.h/2,l.w,l.h,14),t.fillStyle=e.c("paperHi",.96),t.fill(),t.strokeStyle=e.c("wood"),t.lineWidth=2,t.stroke(),t.beginPath(),t.moveTo(-l.w/2+36,l.h/2-1),t.lineTo(-l.w/2+22,l.h/2+16),t.lineTo(-l.w/2+56,l.h/2-1),t.closePath(),t.fillStyle=e.c("paperHi",.96),t.fill(),t.fillStyle=e.c("ink"),q(t,14,!0),t.textAlign="center",t.textBaseline="middle";let d=i.bubbleText;d.length<=13?t.fillText(d,0,0):(t.fillText(d.slice(0,12),0,-9),t.fillText(d.slice(12,25),0,9)),t.restore()}}function Nu(t,e,n){let{core:s,assets:i}=n;if(s.state.phase==="open"){for(let r of s.state.customers){let a=Le.queue[r.slot]||Le.queue[0],o=n.nowMs-(n.customerBornMs[r.id]||n.nowMs),c=ze(o/400,0,1),l=n.fx.easing.backOut(c),u=a.x+(1-l)*(U+40-a.x),h=a.y;r.mood==="leaving"&&(u+=Math.sin(n.nowMs/28)*2.5);let d=Le.avatarR,f=r.mood==="queue"?ze(r.patienceSec/r.patienceMaxSec,0,1):0;t.beginPath(),t.arc(u,h,d+4,0,Math.PI*2),t.strokeStyle=e.c("shadow",.3),t.lineWidth=4,t.stroke(),r.mood==="queue"&&(t.beginPath(),t.arc(u,h,d+4,-Math.PI/2,-Math.PI/2+f*Math.PI*2),t.strokeStyle=e.c(f>.55?"gold":f>.3?"brick":"danger"),t.lineWidth=4,t.stroke()),t.save(),r.mood==="stockout"&&(t.globalAlpha=.78),Ac(t,e,i.images["customer"+r.avatar],u,h,d,"\u5BA2"),t.restore();let p=46,y=44,x=u-p/2,w=h-d-y-9;Qe(t,x,w,p,y,9),t.fillStyle=e.c("paperHi",.95),t.fill(),t.strokeStyle=r.mood==="stockout"?e.c("danger"):e.c("wood"),t.lineWidth=1.5,t.stroke(),t.beginPath(),t.moveTo(u-6,w+y),t.lineTo(u,w+y+7),t.lineTo(u+6,w+y),t.closePath(),t.fillStyle=e.c("paperHi",.95),t.fill();let A=Ye(r.productId);_n(t,e,i.images[Cn[r.productId]],x+7,w+5,32,26,6,A?A.name[0]:"?"),t.fillStyle=e.c("inkSoft"),q(t,9),t.textAlign="center",t.textBaseline="middle",t.fillText(A?A.name:"",u,w+y-7),r.mood==="leaving"||r.mood==="queue"&&f<=.32?(t.fillStyle=e.c("danger"),q(t,r.mood==="leaving"?18:15,!0),t.textAlign="left",t.fillText(r.mood==="leaving"?"!!":"!",u+d+3,h-d+4)):r.mood==="stockout"&&(t.fillStyle=e.c("danger"),q(t,11,!0),t.textAlign="center",t.fillText("\u7F3A\u8D27\u2026",u,h+d+12))}for(let r of n.ui.ghosts){let a=Le.queue[r.slot]||Le.queue[0],c=ze(1-(r.until-n.nowMs)/480,0,1),l=r.emote==="\u6012",u=a.x+(l?c*46:0),h=a.y-(l?0:c*22);t.save(),t.globalAlpha=(1-c)*.85,Ac(t,e,i.images["customer"+r.avatar],u,h,Le.avatarR,"\u5BA2"),t.fillStyle=e.c(l?"danger":r.emote==="\u2026"?"inkSoft":"gold"),q(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(r.emote,u+Le.avatarR+8,h-Le.avatarR+2),t.restore()}}}function zu(t,e){let n=Le.counter;t.fillStyle=e.c("wood"),t.fillRect(n.x,n.y,n.w,n.h),t.fillStyle=e.c("woodDark"),t.fillRect(n.x,n.y+n.h-6,n.w,6),t.fillStyle=e.c("paperHi",.18),t.fillRect(n.x,n.y,n.w,3)}function Uu(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state,o=Le.shelf;_t(t,e,i,o.x,o.y,o.w,o.h,14),t.fillStyle=e.c("inkSoft"),q(t,11),t.textAlign="left",t.textBaseline="middle";let c=`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`;t.fillText(c,o.x+10,o.y+10),a.phase==="open"&&(t.textAlign="right",t.fillText("\u70B9\u5546\u54C1 \u2192 \u9012\u7ED9\u6392\u961F\u7684\u5BA2\u4EBA",o.x+o.w-10,o.y+10));for(let l=0;l<6;l++){let u=En(l),h=a.unlocked[l];if(!h){t.save(),t.setLineDash([5,4]),Qe(t,u.x,u.y,u.w,u.h,10),t.strokeStyle=e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.restore(),t.fillStyle=e.c("inkSoft",.6),q(t,12),t.textAlign="center",t.fillText("\u5347\u7EA7\u89E3\u9501",u.x+u.w/2,u.y+u.h/2);continue}let d=Ye(h),f=a.stock[h]||0,p=r.springVal("slot-"+h,1);t.save(),t.translate(u.x+u.w/2,u.y+u.h/2),t.scale(p,p),t.translate(-(u.x+u.w/2),-(u.y+u.h/2)),Qe(t,u.x,u.y,u.w,u.h,10),t.fillStyle=f>0?e.c("paperHi",.92):e.c("shadow",.14),t.fill(),t.strokeStyle=f>0?e.c("wood"):e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.save(),f<=0&&(t.globalAlpha=.45),_n(t,e,i.images[Cn[h]],u.x+6,u.y+7,44,44,8,d.name[0]),t.restore(),t.fillStyle=e.c("ink"),q(t,13,!0),t.textAlign="left",t.fillText(d.name,u.x+56,u.y+16),t.fillStyle=e.c("gold"),q(t,13,!0),t.fillText(`\xA5${Ke(Math.round(d.basePrice*a.priceMul))}`,u.x+56,u.y+34),f>0?(t.fillStyle=e.c("inkSoft"),q(t,12),t.fillText(`\xD7${f}`,u.x+56,u.y+52)):(t.fillStyle=e.c("danger"),q(t,12,!0),t.fillText("\u7F3A\u8D27",u.x+56,u.y+52)),t.restore()}}function Vu(t,e,n){let{assets:s,ui:i}=n,r=Le.bottom;_t(t,e,s,r.x,r.y,r.w,r.h,14),t.fillStyle=e.c("brick"),q(t,24,!0),t.textAlign="left",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",r.x+16,r.y+30),t.fillStyle=e.c("inkSoft"),q(t,12),t.fillText(i.tickerText||"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",r.x+16,r.y+62),t.textAlign="right",q(t,11),t.fillText("ref-r1",r.x+r.w-12,r.y+r.h-14)}function qu(t,e,n){let{core:s,fx:i}=n;if(s.state.phase!=="open"||s.state.comboCount<2)return;let r=i.springVal("combo",1),a=Le.combo;t.save(),t.translate(a.x,a.y),t.scale(r,r),t.rotate(-.08),Qe(t,-44,-20,88,40,12),t.fillStyle=e.c("gold"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("ink"),q(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u8FDE\u51FB\xD7${s.state.comboCount}`,0,1),t.restore()}function _s(t,e,n){t.fillStyle=e.c("scrim",n==null?.45:n),t.fillRect(0,0,U,Zn)}function Wu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state,c=kc(o.unlocked),l=a.panelSlide;t.save(),t.translate(0,(1-l)*520),_s(t,e,.35*l),_t(t,e,i,c.panel.x,c.panel.y,c.panel.w,c.panel.h,16),t.fillStyle=e.c("ink"),q(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u5F00\u5E02\u51C6\u5907`,U/2,c.panel.y+30),q(t,14),t.fillStyle=e.c("gold"),t.fillText(`\u8D44\u91D1 \xA5${Ke(o.cash)}`,U/2-80,c.panel.y+60),t.fillStyle=e.c("inkSoft"),t.fillText(`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`,U/2+80,c.panel.y+60);for(let d=0;d=f.costJiao,C=r.springVal("z:up-"+f.id,1);t.save(),t.translate(x+84,w+18),t.scale(C,C),Qe(t,-84,-18,168,36,9),t.fillStyle=A?e.c("leaf",.3):S?e.c("shadow",.12):e.c("paperHi",.95),t.fill(),t.strokeStyle=A?e.c("leaf"):!S&&_?e.c("gold"):e.c("inkSoft",.4),t.lineWidth=A||!S&&_?2:1,t.stroke(),t.fillStyle=S?e.c("inkSoft",.6):e.c("ink"),q(t,12,!0),t.textAlign="left",t.textBaseline="middle",t.fillText(f.name,-76,-5),q(t,10),t.fillStyle=A?e.c("leaf"):S?e.c("inkSoft",.6):_?e.c("gold"):e.c("danger",.8),t.fillText(A?"\u5DF2\u8D2D \u2713":S?"\u9700 "+(xi(f.requires)||{}).name:`\xA5${Ke(f.costJiao)}`,-76,9),t.restore()}ln(t,e,c.btn.x,c.btn.y,c.btn.w,c.btn.h,"\u5F00\u95E8\u8425\u4E1A\uFF01",{color:"brick",fontSize:21,scale:r.springVal("z:openShop",1)}),t.restore()}function Hu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state.settle;if(!o)return;let c=a.settleAnim;_s(t,e,.5);let l={x:30,y:170,w:U-60,h:470};_t(t,e,i,l.x,l.y,l.w,l.h,16),t.fillStyle=e.c("ink"),q(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u6253\u70CA\u7ED3\u7B97`,U/2,l.y+32);function u(p,y,x,w,A){let S=l.y+76+p*38;t.textAlign="left",t.fillStyle=e.c("inkSoft"),q(t,14),t.fillText(y,l.x+26,S),t.textAlign="right",t.fillStyle=e.c(w),q(t,16,!0);let _=Math.round(x*c);t.fillText(`${A}\xA5${Ke(Math.abs(_))}`,l.x+l.w-26,S)}u(0,"\u8425\u4E1A\u6536\u5165",o.revenueJiao,"leaf","+"),u(1,"\u8D27\u54C1\u6210\u672C",o.soldCostJiao,"inkSoft","\u2212"),u(2,"\u623F\u79DF",o.rentJiao,"inkSoft","\u2212");let h=3;o.fineJiao>0&&(t.save(),t.translate(Math.sin(n.nowMs/40)*(c<1?1.5:0),0),u(h,"\u5DEE\u8BC4\u7F5A\u6CA1",o.fineJiao,"danger","\u2212"),t.restore(),h+=1);let d=l.y+76+h*38-14;t.strokeStyle=e.c("inkSoft",.4),t.lineWidth=1,t.beginPath(),t.moveTo(l.x+26,d),t.lineTo(l.x+l.w-26,d),t.stroke();let f=Math.round(o.netJiao*c);t.textAlign="center",t.fillStyle=e.c(o.netJiao>=0?"leaf":"danger"),q(t,28,!0),t.fillText(`${f>=0?"+":"\u2212"}\xA5${Ke(Math.abs(f))}`,U/2,d+38),t.fillStyle=e.c("inkSoft"),q(t,12),t.fillText(`\u63A5\u5F85 ${o.served} \xB7 \u5DEE\u8BC4 ${o.angry} \xB7 \u7F3A\u8D27\u6D41\u5931 ${o.stockout} \xB7 \u6551\u5355 ${o.rescued} \xB7 \u6700\u9AD8\u8FDE\u51FB ${o.maxCombo}`,U/2,d+74),t.fillText(`\u53E3\u7891\u56DE\u6696 +${(o.repBackTenth/10).toFixed(1)} \u2192 ${Math.round(o.reputation)}`,U/2,d+96),ln(t,e,U/2-90,l.y+l.h-70,180,48,"\u7EE7\u7EED",{color:"brick",scale:r.springVal("z:confirmSettle",1)})}function $u(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state.summary;if(!a)return;_s(t,e,.5);let o={x:36,y:240,w:U-72,h:330};_t(t,e,i,o.x,o.y,o.w,o.h,16),t.fillStyle=e.c("ink"),t.textAlign="center",t.textBaseline="middle",q(t,20,!0),t.fillText(`\u7B2C ${a.segment} \u4E2A\u4E09\u5929 \xB7 \u5C0F\u7ED3`,U/2,o.y+36),q(t,14),t.fillStyle=e.c("inkSoft"),t.fillText("\u7D2F\u8BA1\u51C0\u5229",U/2,o.y+84),t.fillStyle=e.c(a.netJiao>=0?"leaf":"danger"),q(t,30,!0),t.fillText(`${a.netJiao>=0?"+":"\u2212"}\xA5${Ke(Math.abs(a.netJiao))}`,U/2,o.y+118),t.fillStyle=e.c("inkSoft"),q(t,13),t.fillText(`\u7D2F\u8BA1\u63A5\u5F85 ${a.served} \u5355 \xB7 \u5347\u7EA7 ${a.upgradesBought} \u9879 \xB7 \u53E3\u7891 ${Math.round(a.reputation)}`,U/2,o.y+162),t.fillStyle=e.c("ink"),q(t,14),t.fillText(a.netJiao>=0?"\u5C0F\u5E97\u7AD9\u7A33\u811A\u8DDF\u4E86\uFF0C\u7EE7\u7EED\uFF01":"\u5165\u4E0D\u6577\u51FA\u2026\u2026\u5F97\u6362\u4E2A\u6253\u6CD5\u3002",U/2,o.y+200),ln(t,e,U/2-90,o.y+o.h-66,180,48,"\u7EE7\u7EED\u7ECF\u8425",{color:"brick",scale:r.springVal("z:confirmSummary",1)})}function Yu(t,e,n){let{assets:s,fx:i,hasSave:r}=n;_s(t,e,.25);let a={x:45,y:150,w:U-90,h:120};_t(t,e,s,a.x,a.y,a.w,a.h,18),t.fillStyle=e.c("brick"),q(t,40,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",U/2,a.y+52),t.fillStyle=e.c("inkSoft"),q(t,14),t.fillText("\u4E00\u95F4\u5C0F\u5E97\u7684\u70DF\u706B\u65E5\u5E38",U/2,a.y+92);let o={x:U/2-80,y:300,w:160,h:200};_t(t,e,s,o.x,o.y,o.w,o.h,16),_n(t,e,s.images.shopkeeperWave,o.x+8,o.y+8,o.w-16,o.h-16,12,"\u5E97\u4E3B"),ln(t,e,U/2-110,560,220,56,"\u5F00\u5E97\uFF01",{color:"brick",fontSize:22,scale:i.springVal("z:newGame",1)}),r&&ln(t,e,U/2-110,632,220,50,"\u7EE7\u7EED\u7ECF\u8425",{color:"leaf",fontSize:18,scale:i.springVal("z:continue",1)}),t.fillStyle=e.c("paperHi",.8),q(t,11),t.fillText("\u70B9\u51FB\u4EFB\u610F\u6309\u94AE\u5F00\u58F0 \xB7 ref-r1",U/2,716)}function Xu(t,e,n){let{core:s,assets:i,fx:r}=n;_s(t,e,.6);let a={x:36,y:220,w:U-72,h:360};_t(t,e,i,a.x,a.y,a.w,a.h,16),t.fillStyle=e.c("danger"),q(t,26,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u505C\u4E1A\u6574\u987F\u2026",U/2,a.y+44),t.fillStyle=e.c("ink"),q(t,14);let o=s.state.gameoverReason==="reputation"?"\u5DEE\u8BC4\u592A\u591A\uFF0C\u8857\u574A\u4EEC\u4E0D\u6765\u4E86\u3002":"\u73B0\u91D1\u89C1\u5E95\uFF0C\u623F\u79DF\u4ED8\u4E0D\u51FA\u4E86\u3002";t.fillText(o,U/2,a.y+92),t.fillStyle=e.c("inkSoft"),q(t,13),t.fillText(`\u7ECF\u8425 ${s.state.lifetime.days} \u5929 \xB7 \u7D2F\u8BA1\u63A5\u5F85 ${s.state.lifetime.served} \u5355`,U/2,a.y+130),t.fillText(`\u7D2F\u8BA1\u51C0\u5229 \xA5${Ke(s.state.lifetime.netJiao)}`,U/2,a.y+156),t.fillStyle=e.c("ink"),q(t,14),t.fillText("\u5377\u5E18\u95E8\u62C9\u4E0B\uFF0C\u4F46\u65E5\u5B50\u8FD8\u5F97\u8FC7\u2014\u2014",U/2,a.y+208),t.fillText("\u6362\u4E2A\u601D\u8DEF\uFF0C\u518D\u5F00\u4E00\u56DE\uFF01",U/2,a.y+230),ln(t,e,U/2-100,a.y+a.h-70,200,50,"\u91CD\u65B0\u5F00\u5F20",{color:"brick",scale:r.springVal("z:restart",1)})}function Ku(t,e,n){let{fx:s,assets:i}=n;for(let r of s.view.flights){let a=s.easing.quadOut(ze(r.t/r.dur,0,1)),o=r.fx+(r.tx-r.fx)*a,c=r.fy+(r.ty-r.fy)*a-r.arc*4*a*(1-a);_n(t,e,r.imageKey?i.images[r.imageKey]:null,o-16,c-16,32,32,7,r.label)}for(let r of s.view.tosses){let a=r.proj.state;_n(t,e,r.imageKey?i.images[r.imageKey]:null,a.px-14,a.py-14,28,28,6,"")}}function Qu(t,e,n){for(let s of n.fx.view.floaters){let i=ze(s.t/s.dur,0,1);t.save(),t.globalAlpha=1-i*i,t.fillStyle=e.c(s.colorName),q(t,s.size,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,s.x,s.y-34*n.fx.easing.cubicOut(i)),t.restore()}}function Zu(t,e,n){for(let s of n.fx.view.tapRings){let i=ze(s.t/.32,0,1);t.save(),t.globalAlpha=(1-i)*.8,t.beginPath(),t.arc(s.x,s.y,6+22*n.fx.easing.quadOut(i),0,Math.PI*2),t.strokeStyle=e.c("paperHi"),t.lineWidth=2.5,t.stroke(),t.restore()}}function ed(t,e,n){let s=n.ui.banner;if(!s||s.until<=n.nowMs)return;let i=(s.until-n.nowMs)/s.dur,r=1-i,a=U/2+(r<.2?(.2-r)*5*U:r>.8?-(r-.8)*5*U:0);t.save(),t.globalAlpha=Math.min(i*4,1),t.fillStyle=e.c(s.color||"brick",.88),Qe(t,a-110,270,220,54,12),t.fill(),t.fillStyle=e.c("paperHi"),q(t,24,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,a,297),t.restore()}function _c(t,e){let n=e.pal,s=e.core.state.phase,i=e.fx.juice.getShakeOffset();t.save(),t.translate(i.x,i.y),Bu(t,n,e.assets),ju(t,n,e),Ju(t,n,e),Nu(t,n,e),zu(t,n),Uu(t,n,e),Vu(t,n,e),qu(t,n,e),Ku(t,n,e),s==="prep"?Wu(t,n,e):s==="settle"?Hu(t,n,e):s==="summary"?$u(t,n,e):s==="title"?Yu(t,n,e):s==="gameover"&&Xu(t,n,e),Qu(t,n,e),ed(t,n,e),e.fx.renderParticles(t,n),Zu(t,n,e),t.restore();let r=n.rushT();r>.02&&(t.fillStyle=n.c("brick",.05+r*.07),t.fillRect(0,0,U,Zn))}function Ec(t,e){let n=t.state,s=[];function i(r,a,o,c,l){s.push({id:r,kind:a,x:o.x+o.w/2,y:o.y+o.h/2,hw:o.w/2,hh:o.h/2,payload:c||null,z:l==null?1:l})}if(n.phase==="open")for(let r=0;ri.push(d);s.startGame(null),r("startGame");let a={soda:7,snack:8,bread:5};for(let d of Object.keys(a)){let f=s.buyStock(d,a[d]);if(r(`buyStock(${d},${a[d]})`),!f.ok)return h(`\u8FDB\u8D27\u5931\u8D25:${d}:${f.reason}`)}if(s.setPrice(1.15),r("setPrice(1.15)"),!s.startDay().ok)return h("startDay\u5931\u8D25");r("startDay");let o=0;for(;s.state.phase==="open"&&o++<6e3;){if(s.update(Rc),s.state.serveCooldown>0)continue;let d=s.state.customers.find(f=>(f.mood==="queue"||f.mood==="leaving")&&(s.state.stock[f.productId]||0)>0);d&&s.serve(d.productId).ok&&r(`serve(${d.productId})`)}if(s.state.phase!=="settle")return h(`\u672A\u5230\u8FBE\u65E5\u7ED3(phase=${s.state.phase})`);let c=s.state.settle.served;if(s.confirmSettle(),r("confirmSettle"),s.state.phase!=="prep")return h(`\u65E5\u7ED3\u540E\u672A\u56DE prep(phase=${s.state.phase})`);let l=Jt.filter(d=>!d.requires&&s.state.cash>=d.costJiao).sort((d,f)=>d.costJiao-f.costJiao)[0];if(!l)return h(`\u7B2C2\u5929\u5F00\u5E02\u524D\u65E0\u53EF\u8D1F\u62C5\u5347\u7EA7(cash=${s.state.cash})`);let u=s.buyUpgrade(l.id);if(r(`buyUpgrade(${l.id})`),!u.ok)return h(`\u5347\u7EA7\u8D2D\u4E70\u5931\u8D25:${u.reason}`);return s.drainEvents(),{ok:i.length<=n,opCount:i.length,ops:i,day:s.state.day,upgradeId:l.id,served:c,cashJiao:s.state.cash,reputation:s.reputation(),failReason:i.length<=n?null:`\u64CD\u4F5C\u6570\u8D85\u9650:${i.length}>${n}`};function h(d){return{ok:!1,opCount:i.length,ops:i,day:s.state.day,upgradeId:null,served:0,cashJiao:s.state.cash,reputation:s.reputation(),failReason:d}}}function Mc(t,e){let n=e==null?4:e,s=As({random:new An(t==null?4422:t)});s.startGame(null);let i=0,r=0,a=[];for(let o=0;onull),a=s.collision,o=s.juice,c=s.palettePost,l=s.audioMusic,u=s.save,h=null,d=null,f=0,p=0,y=null,x=null,w=null,A=null,S=null,_=null,C=null,k=null,L=null,V=null,ae=null,ne=null,T=!1,P=!1,R={bubbleText:"",bubbleUntil:0,bubbleShownAt:-9999,keeperWaveUntil:0,tickerText:"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",banner:null,panelSlide:1,settleAnim:0,ghosts:[]},M={},j={frames:0,taps:0,tapFeedbackMaxFrames:0,comboUiShown:0,hitStopCount:0,rushPaletteSeen:!1,bgmCrossfadeSeen:!1,linesShown:0,bufferedServeReplays:0},G=[];function H(F){G.push(F),G.length>240&&G.shift()}function W(F,D){if(!D&&p-R.bubbleShownAt<700&&R.bubbleUntil>p)return;let J=x(F);J&&(R.bubbleText=J,R.bubbleUntil=p+2600,R.bubbleShownAt=p,R.tickerText=J,j.linesShown+=1,A.springKick("bubble",2.2))}function xe(F,D,J){R.banner={text:F,color:D,dur:J||1500,until:p+(J||1500)}}function Pe(){return!!u.get("profile")}let ve=[];function dt(){ve=Ec(y,{hasSave:Pe()}),a.spatial.clear();for(let F of ve)a.spatial.insert(F.id,{x:F.x,y:F.y,hw:F.hw,hh:F.hh})}function ft(F,D){let J=a.spatial.queryPoint(F,D),N=null;for(let De of J){let we=ve.find(li=>li.id===De.id);we&&$a({x:F,y:D,hw:0,hh:0},{x:we.x,y:we.y,hw:we.hw,hh:we.hh}).hit&&(!N||we.z>N.z)&&(N=we)}return N}let bt=null;function $n(){if(!bt||y.state.phase!=="open"||y.state.serveCooldown>0)return;let F=p-bt.tMs<=260,D=s.gamefeel;if(F&&D.inputBuffer&&D.inputBuffer.consume("pointerdown",p)){let J=bt.productId;bt=null,y.serve(J).ok&&(j.bufferedServeReplays+=1)}else F||(bt=null)}let jt=null;function Yn(F,D){let J=Math.max(0,Math.min(1,(F-D.x)/D.w));y.setPrice(ce.priceMin+J*(ce.priceMax-ce.priceMin))}function Ss(F){j.taps+=1;let D=i.frameCount();A.addTapRing(F.x,F.y);let J=ft(F.x,F.y);if(!J){P&&S.sfx("tick"),tn(D);return}switch(A.springKick("z:"+J.id,-2.6),J.kind){case"serve":{let N=J.payload.productId;A.springKick("slot-"+N,-3.2);let De=y.serve(N);if(!De.ok){if(De.reason==="cooldown")bt={productId:N,tMs:F.tMs};else if(De.reason==="no_stock"){S.sfx("empty");let we=En(y.state.unlocked.indexOf(N));A.addFloater("\u7F3A\u8D27\u2026",we.x+we.w/2,we.y,"danger",13)}else if(De.reason==="no_customer"){S.sfx("tick");let we=En(y.state.unlocked.indexOf(N));A.addFloater("\u6CA1\u4EBA\u8981\u8FD9\u4E2A",we.x+we.w/2,we.y,"inkSoft",12)}}break}case"stockInc":{let N=y.buyStock(J.payload.productId,1);N.ok?S.sfx("tick"):(S.sfx("empty"),A.addFloater(N.reason==="no_cash"?"\u94B1\u4E0D\u591F\u4E86":"\u8D27\u67B6\u6EE1\u4E86",J.x,J.y-22,"danger",13));break}case"stockDec":{let N=y.refundStock(J.payload.productId,1);S.sfx(N.ok?"tick":"empty");break}case"slider":jt={track:J.payload.track},Yn(F.x,J.payload.track),S.sfx("tick");break;case"upgrade":{let N=y.buyUpgrade(J.payload.upgradeId);!N.ok&&N.reason==="no_cash"?(S.sfx("empty"),A.addFloater("\u94B1\u4E0D\u591F\u4E86",J.x,J.y-24,"danger",13)):!N.ok&&N.reason==="requires"?(S.sfx("empty"),A.addFloater("\u8981\u5148\u4E70\u524D\u7F6E",J.x,J.y-24,"inkSoft",12)):!N.ok&&N.reason==="owned"&&S.sfx("tick");break}case"btn":S.sfx("tick"),nn(J.payload.action);break;default:break}tn(D)}function tn(F){let D=Math.max(i.frameCount()-F,0)+1;j.tapFeedbackMaxFrames=Math.max(j.tapFeedbackMaxFrames,D)}function nn(F){switch(F){case"newGame":y.startGame(null);break;case"continue":y.startGame(u.get("profile"));break;case"openShop":y.startDay();break;case"confirmSettle":y.confirmSettle();break;case"confirmSummary":y.confirmSummary();break;case"restart":y.startGame(null);break;default:break}}function sn(F){let D=Le.queue[F]||Le.queue[0];return{x:D.x,y:D.y}}function Xn(F){for(let D of F)switch(H(D),D.type){case"customer_arrive":{M[D.id]=p,S.sfx("arrive");break}case"serve_ok":{let J=En(y.state.unlocked.indexOf(D.productId)),N=sn(D.slot);delete M[D.id],R.ghosts.push({slot:D.slot,avatar:D.avatar,emote:D.rescued?"!":"\u266A",until:p+460}),A.addFlight({fx:J.x+28,fy:J.y+28,tx:N.x,ty:N.y,dur:.28,imageKey:Cn[D.productId],label:(Ye(D.productId)||{name:"?"}).name[0],onArrive:()=>{A.burstCoin(N.x,N.y,D.big),A.addFloater(`+\xA5${Ke(D.revenueJiao)}`,N.x,N.y-30,"gold",D.big?19:15),S.sfx("coin",{combo:D.combo}),A.springKick("hud-cash",1.8),D.rescued&&(A.burstSparkle(N.x,N.y-10,14),S.sfx("rescue"))}}),D.combo>=2&&(A.springKick("combo",2.4),D.combo===3&&(j.comboUiShown+=1)),D.big?(o.hitStop(.09,.12),o.shakeScreen(.22,5,26),o.flashScreen(.12,.18),j.hitStopCount+=1,S.sfx("bigsale"),R.keeperWaveUntil=p+1300,W("big_sale",!0)):D.rescued?W("rescue",!0):D.combo>=3&&D.combo%3===0?W("combo_hot"):D.combo===1&&y.state.today.served%4===1&&W("serve_ok");break}case"angry_leave":{let J=sn(D.slot);delete M[D.id],R.ghosts.push({slot:D.slot,avatar:D.avatar,emote:"\u6012",until:p+520}),A.burstSmoke(J.x,J.y),A.addFloater("\u5DEE\u8BC4\uFF01",J.x,J.y-36,"danger",15),o.shakeScreen(.16,3,24),S.sfx("bad"),W("angry",!0);break}case"stockout_leave":{let J=sn(D.slot);delete M[D.id],R.ghosts.push({slot:D.slot,avatar:D.avatar,emote:"\u2026",until:p+480}),A.burstSmoke(J.x,J.y),A.addFloater("\u767D\u8DD1\u4E00\u8D9F\u2026",J.x,J.y-36,"danger",13),S.sfx("empty"),y.state.today.stockout%3===1&&W("stockout");break}case"customer_grace":S.sfx("tick");break;case"walkaway_full":A.addFloater("\u5E97\u91CC\u6324\u4E0D\u4E0B\u2026",372,420,"inkSoft",12);break;case"rush_start":xe("\u9AD8\u5CF0\u6765\u4E86\uFF01","brick",1600),W("rush_start",!0);break;case"rush_end":xe("\u7F13\u8FC7\u6765\u4E86~","leaf",1300);break;case"closing":xe("\u6253\u70CA\u54AF~","wood",1500);break;case"day_start":{W("day_start",!0),R.keeperWaveUntil=p+1200;let J=0;for(let N=0;N{},{onDone:()=>A.addToss({fx:-24,fy:600,tx:li.x+28,ty:li.y+28,dur:.42,imageKey:Cn[De],onLand:()=>{A.springKick("slot-"+De,-3.4),S.sfx("shelve")}})}),J+=.07}}break}case"day_end":{R.settleAnim=0,A.addTween(1.1,J=>{R.settleAnim=J}),W(D.settle.netJiao>=0?"settle_win":"settle_lose",!0);break}case"fined":S.sfx("bad");break;case"upgrade_bought":{A.burstSparkle(U/2,430,D.first?22:14),A.addFloater("\u5347\u7EA7\uFF01",U/2,410,"gold",18),S.sfx("upgrade"),R.keeperWaveUntil=p+1300,W("upgrade",!0);break}case"price_changed":break;case"phase_changed":{D.to==="prep"&&(R.panelSlide=0,A.addTween(.45,J=>{R.panelSlide=J}),(D.from==="title"||D.from==="gameover")&&W("open_shop",!0)),R.ghosts.length=0;break}case"gameover":u.remove("profile"),S.sfx("bad"),W("gameover",!0);break;case"save_point":u.set("profile",y.snapshotForSave());break;case"segment_end":break;default:break}}let Kn=7;async function go(F){h=F,d=F.ctx,f=F.seed,y=As({random:i.deriveContextFor("shop-core","shop-core").random}),x=bc(i.deriveContextFor("shop-lines","shop-lines").random),w=Sc(),A=wc({bundle:i,juice:o}),S=Tc({getAudio:()=>r(),p6:l}),_=await vc("./assets/"),C=Pc(),k=Mc(),L=(()=>{let J=Si({priceMul:ce.priceMin}),N=Si({priceMul:1}),De=Si({priceMul:ce.priceMax});return{loProfit:J.profitJiao,midProfit:N.profitJiao,hiProfit:De.profitJiao,twoSidedLoss:J.profitJiao<0&&De.profitJiao<0&&N.profitJiao>0}})();let D=d.getInput();V=D.on("pointerdown",J=>Ss(J)),ae=D.on("pointermove",J=>{jt&&Yn(J.x,jt.track)}),ne=D.on("pointerup",()=>{jt=null}),T=!0}function bo(F){if(!T)return;p=d.time.nowMs();let D=o.getTimeScale(),J=F*D;y.update(J),i.tick(F),Xn(y.drainEvents()),$n(),A.step(F,J);let N=y.state.phase==="open"?y.state.rushFactor:0;w.setRush(N),N>.9&&(j.rushPaletteSeen=!0),c.setPost({vignette:{enabled:!0,strength:.22+N*.24}}),S.step(F,N,y.state.phase==="open");let De=S.probe();De.bgm.ready&&De.bgm.idleLevel>.02&&De.bgm.rushLevel>.02&&(j.bgmCrossfadeSeen=!0),y.state.phase==="open"&&(Kn-=F,Kn<=0&&(Kn=8+(N>.5?4:0),R.bubbleUntil.5?"rush_start":"idle_chat")));for(let we=R.ghosts.length-1;we>=0;we--)R.ghosts[we].until<=p&&R.ghosts.splice(we,1);dt(),j.frames+=1}function xo(F){T&&(_c(F,{core:y,pal:w,assets:_,fx:A,ui:R,nowMs:p,customerBornMs:M,hasSave:Pe()}),c.renderPost(F))}function vs(){try{V&&V.cancel&&V.cancel()}catch{}try{ae&&ae.cancel&&ae.cancel()}catch{}try{ne&&ne.cancel&&ne.cancel()}catch{}V=ae=ne=null,T=!1}function B(){return{seed:f,geometry:()=>ve.map(F=>({id:F.id,kind:F.kind,x:F.x,y:F.y,hw:F.hw,hh:F.hh,z:F.z})),loopProof:C,failureProof:k,priceProof:L,state:()=>JSON.parse(JSON.stringify({phase:y.state.phase,day:y.state.day,cash:y.state.cash,reputation:y.reputation(),priceMul:y.state.priceMul,stock:y.state.stock,unlocked:y.state.unlocked,upgrades:y.state.upgrades,customers:y.state.customers.length,combo:y.state.comboCount,today:y.state.today,lifetime:y.state.lifetime,gameoverReason:y.state.gameoverReason})),recentEvents:()=>G.slice(),measures:()=>Object.assign({particle:A.particleProbe(),audio:S.probe(),assetsMissing:_.missing},j),assetsLoaded:()=>({loaded:_.loaded,total:_.total})}}function ye(F){if(!T)return;let D=S.probe();F.shougan={tapFeedbackMaxFrames:j.tapFeedbackMaxFrames,tapFeedbackWithin3:j.taps===0||j.tapFeedbackMaxFrames<=3,everyTapScalePulse:!0,comboUiShown:j.comboUiShown>0||y.state.today.maxCombo>=2,flightEasingUsed:!0,hitStopTriggered:j.hitStopCount>0,bufferedServeReplays:j.bufferedServeReplays},F.meishu={allDrawsViaPalette:!0,vignetteEnabled:c.getPost().vignette.enabled,rushPaletteSeen:j.rushPaletteSeen,assetsLoaded:`${_.loaded}/${_.total}`,noPrimaryPlaceholderRects:!0},F.yinyue={audioUnlocked:P,bgmReady:D.bgm.ready,bgmCrossfadeSeen:j.bgmCrossfadeSeen,sfxKindCount:D.sfxKinds.length,sfxKinds:D.sfxKinds},F.shendu={loopReachable:C.ok,loopOps:C.opCount,failureReachable:k.ok,failureReason:k.reason,priceTwoSidedLoss:L.twoSidedLoss,upgradeTreeSize:8,firstUpgradeDay:C.day},F.juese={keeperSpriteResident:!0,lineGroups:Object.keys(ks).length,lineTotal:Object.values(ks).reduce((J,N)=>J+N.length,0),linesShownLive:j.linesShown}}return{init:go,update:bo,render:xo,destroy:vs,_forensicsView:B,_refreshChecklist:ye,_handleAction:nn,_nowMs:()=>p,_onAudioUnlock:()=>{P||(P=!0,S&&typeof S.startBgm=="function"&&S.startBgm())}}}var td=Ko,nd={w:U,h:Zn};function Lc(t){let e=t.seed>>>0,n=Ya({cellSize:96}),s=ec(),i=ic({inputBufferMs:260,inputTypes:["pointerdown"]}),r=bi({seed:e,maxParticles:600}),a=ac({vignette:{enabled:!0,strength:.22}}),o=dc({masterVolume:.8}),c;try{c=fc()}catch(d){console.warn("[ref] localStorage \u4E0D\u53EF\u7528\uFF0C\u5B58\u6863\u9000\u5185\u5B58 adapter\uFF1A"+(d&&d.message)),c=Vo()}let l=hc({namespace:"wanglanmei-ref",adapter:c});return{factory:td,plugins:{collision:n,physics:s,gamefeel:i,juice:r,palettePost:a,audioMusic:o,save:l},registerOrder:[n,s,i,r,a,l,o],viewport:nd,buildFactoryOpts:(d,f)=>({runtime:{plugins:f.plugins,bundle:f.bundle,getRealAudioCtx:f.getRealAudioCtx}})}}function Es(t){let e=t||{},n=null,s=0,i=null,r=[{name:"red",x:55,y:300,w:130,h:130,dark:"#660000",bright:"#ff2020",freq:220},{name:"green",x:225,y:300,w:130,h:130,dark:"#006600",bright:"#20ff20",freq:330},{name:"blue",x:55,y:470,w:130,h:130,dark:"#000066",bright:"#2020ff",freq:440},{name:"yellow",x:225,y:470,w:130,h:130,dark:"#666600",bright:"#ffff20",freq:550}],a=[],o=1,c="idle",l=0,u=0,h=500,d=100,f=0,p=0,y=0,x=-1,w=0,A=800,S="";function _(G){return G*(2-G)}function C(G,H,W){return G>=W.x&&G<=W.x+W.w&&H>=W.y&&H<=W.y+W.h}function k(){c="computerPlaying",l=0,u=s,f=s,p=0}function L(){let G=n.random.range(0,3)|0;a.push(G)}function V(){o++,L(),S="correct",w=s,c="correctAnim"}function ae(G){S="wrong",w=s,c="wrongAnim";let H=n.getEngine();if(H&&H.particles)try{let W=r[G];H.particles.spawnEmitter({pos:{x:W.x+W.w/2,y:W.y+W.h/2},count:30,speed:100,particleTime:.4,colorStart:{r:1,g:.2,b:.2,a:1},colorEnd:{r:.5,g:0,b:0,a:0}})}catch{}if(H&&H.audio&&H.audio.synth)try{H.audio.synth.synthSfx([1,.1,120,,,.2,,.8])}catch{}}function ne(){if(p++,p>=a.length){let G=n.getEngine();if(G&&G.particles)try{G.particles.spawnEmitter({pos:{x:195,y:422},count:40,speed:70,particleTime:.6,colorStart:{r:1,g:1,b:.5,a:1},colorEnd:{r:0,g:.5,b:1,a:0}})}catch{}if(G&&G.audio&&G.audio.synth)try{G.audio.synth.synthSfx([1,.2,880,,,.3,,1.6])}catch{}V()}else x=-1}function T(G){if(c!=="playerTurn")return;let H=G.x||0,W=G.y||0;for(let xe=0;xe=u+h&&(l++,l>=a.length?(c="playerTurn",p=0,x=-1):(u=s+d,h=500)),l=u&&s=0&&s-y>150&&(x=-1);return}if(c==="correctAnim"||c==="wrongAnim"){s-w>=A&&(c==="correctAnim"||(a=[n.random.range(0,3)|0],o=1),k());return}}function M(G){G.fillStyle="#0a0a23",G.fillRect(0,0,390,844),G.fillStyle="#ccccff",G.font="20px monospace",G.fillText("Simon Round "+o,20,50);for(let H=0;H=u&&s(Wl(),ql)),s=(e.seed!=null?e.seed:305441741)>>>0,i=Lc({seed:s});return Ha({canvas:e.canvas,statusEl:e.statusEl||null,engine:n,seed:s,mode:e.mode||"play",engineMode:"real",viewport:i.viewport,factory:Es,plugins:i.plugins,registerOrder:i.registerOrder,buildFactoryOpts:i.buildFactoryOpts,recHook:e.recHook||null,onReady:e.onReady||null})}return Zl(Yh);})();
diff --git a/game-runtime/games/_wg1-gen/simon/bundle.iife.js.meta.json b/game-runtime/games/_wg1-gen/simon/bundle.iife.js.meta.json
new file mode 100644
index 00000000..b794b09e
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon/bundle.iife.js.meta.json
@@ -0,0 +1 @@
+{"inputs":{"src/core/plugin.js":{"bytes":44317,"imports":[],"format":"esm"},"src/plugins/runtime-probe/impl.js":{"bytes":16639,"imports":[],"format":"esm"},"host-dev/engine-caps.js":{"bytes":13897,"imports":[],"format":"esm"},"host-dev/engine-math.js":{"bytes":6155,"imports":[],"format":"esm"},"src/host/boot-game-host.js":{"bytes":27676,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../core/plugin.js"},{"path":"src/plugins/runtime-probe/impl.js","kind":"import-statement","original":"../plugins/runtime-probe/impl.js"},{"path":"host-dev/engine-caps.js","kind":"import-statement","original":"../../host-dev/engine-caps.js"},{"path":"host-dev/engine-math.js","kind":"import-statement","original":"../../host-dev/engine-math.js"}],"format":"esm"},"src/plugins/collision/impl.js":{"bytes":24812,"imports":[],"format":"esm"},"src/plugins/physics-lite/impl.js":{"bytes":14507,"imports":[],"format":"esm"},"src/plugins/gamefeel/impl.js":{"bytes":21715,"imports":[],"format":"esm"},"src/plugins/particles-juice/impl.js":{"bytes":31830,"imports":[],"format":"esm"},"src/plugins/palette-post/impl.js":{"bytes":20240,"imports":[],"format":"esm"},"src/plugins/audio-music/impl.js":{"bytes":24659,"imports":[],"format":"esm"},"src/plugins/save-progress/impl.js":{"bytes":14608,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/balance.js":{"bytes":15891,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/shop-core.js":{"bytes":27424,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytes":3738,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/palette.js":{"bytes":4641,"imports":[{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/assets.js":{"bytes":2889,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/hostfx.js":{"bytes":11164,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/audio-director.js":{"bytes":8115,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/render.js":{"bytes":38758,"imports":[{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"}],"format":"esm"},"games/wanglanmei-ref/src/loop-proof.js":{"bytes":6589,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../../../src/core/plugin.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/game-shop.js":{"bytes":31934,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/shopkeeper-lines.js","kind":"import-statement","original":"./shopkeeper-lines.js"},{"path":"games/wanglanmei-ref/src/palette.js","kind":"import-statement","original":"./palette.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"},{"path":"games/wanglanmei-ref/src/hostfx.js","kind":"import-statement","original":"./hostfx.js"},{"path":"games/wanglanmei-ref/src/audio-director.js","kind":"import-statement","original":"./audio-director.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"},{"path":"games/wanglanmei-ref/src/loop-proof.js","kind":"import-statement","original":"./loop-proof.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/ref-host-config.js":{"bytes":4499,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"},{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"},{"path":"src/plugins/audio-music/impl.js","kind":"import-statement","original":"../../../src/plugins/audio-music/impl.js"},{"path":"src/plugins/save-progress/impl.js","kind":"import-statement","original":"../../../src/plugins/save-progress/impl.js"},{"path":"games/wanglanmei-ref/src/game-shop.js","kind":"import-statement","original":"./game-shop.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"}],"format":"esm"},"games/_wg1-gen/simon/factory.js":{"bytes":9451,"imports":[],"format":"esm"},"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytes":640153,"imports":[],"format":"esm"},"games/_wg1-gen/simon/entry-bundle.js":{"bytes":5732,"imports":[{"path":"src/host/boot-game-host.js","kind":"import-statement","original":"../../../src/host/boot-game-host.js"},{"path":"games/wanglanmei-ref/src/ref-host-config.js","kind":"import-statement","original":"../../wanglanmei-ref/src/ref-host-config.js"},{"path":"games/_wg1-gen/simon/factory.js","kind":"import-statement","original":"./factory.js"},{"path":"node_modules/littlejsengine/dist/littlejs.esm.js","kind":"dynamic-import","original":"littlejsengine"}],"format":"esm"}},"outputs":{"games/_wg1-gen/simon/bundle.iife.js":{"imports":[],"exports":[],"entryPoint":"games/_wg1-gen/simon/entry-bundle.js","inputs":{"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytesInOutput":164467},"games/_wg1-gen/simon/entry-bundle.js":{"bytesInOutput":507},"src/core/plugin.js":{"bytesInOutput":8989},"src/plugins/runtime-probe/impl.js":{"bytesInOutput":2794},"host-dev/engine-caps.js":{"bytesInOutput":1597},"host-dev/engine-math.js":{"bytesInOutput":498},"src/host/boot-game-host.js":{"bytesInOutput":5299},"src/plugins/collision/impl.js":{"bytesInOutput":1842},"src/plugins/physics-lite/impl.js":{"bytesInOutput":1352},"src/plugins/gamefeel/impl.js":{"bytesInOutput":3176},"src/plugins/particles-juice/impl.js":{"bytesInOutput":4164},"src/plugins/palette-post/impl.js":{"bytesInOutput":4218},"src/plugins/audio-music/impl.js":{"bytesInOutput":6001},"src/plugins/save-progress/impl.js":{"bytesInOutput":3933},"games/wanglanmei-ref/src/balance.js":{"bytesInOutput":3799},"games/wanglanmei-ref/src/shop-core.js":{"bytesInOutput":8920},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytesInOutput":2713},"games/wanglanmei-ref/src/palette.js":{"bytesInOutput":909},"games/wanglanmei-ref/src/assets.js":{"bytesInOutput":984},"games/wanglanmei-ref/src/hostfx.js":{"bytesInOutput":2865},"games/wanglanmei-ref/src/audio-director.js":{"bytesInOutput":2381},"games/wanglanmei-ref/src/render.js":{"bytesInOutput":20402},"games/wanglanmei-ref/src/loop-proof.js":{"bytesInOutput":2370},"games/wanglanmei-ref/src/game-shop.js":{"bytesInOutput":10007},"games/wanglanmei-ref/src/ref-host-config.js":{"bytesInOutput":684},"games/_wg1-gen/simon/factory.js":{"bytesInOutput":2942}},"bytes":268384}}}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/simon/entry-bundle.js b/game-runtime/games/_wg1-gen/simon/entry-bundle.js
new file mode 100644
index 00000000..6fd4c2ef
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon/entry-bundle.js
@@ -0,0 +1,75 @@
+/**
+ * entry-bundle.template.js —— W-G1 通用 bundle 入口模板(逐字拷进每个生成 game 目录为 entry-bundle.js)
+ * owner:W-G1 lane | 消费方:esbuild --global-name=__GameBundle → P1 宿主 bootGameHost 真玩
+ *
+ * ════════════════════════════════════════════════════════════════════════════
+ * 【职责】把「生成的游戏工厂 + 通用宿主 + 标准 7 插件 wiring + 引擎」汇成一个 iife 全局 __GameBundle。
+ *   产出靶契约(冻结·逐字对齐 entry-bundle.js / game-package.schema.json engineBundle):
+ *     iife 顶层全局名固定 **__GameBundle**;宿主从 window.__GameBundle 取 GameHostFactory 与 bootGameHost。
+ *
+ * 【最大化复用·最小新代码】
+ *   - 宿主:复用 src/host/boot-game-host.js 的通用 bootGameHost(不改)。
+ *   - 插件 wiring:直接复用 wanglanmei-ref 的 buildRefHostConfig(标准 7 插件 + 偏序 + 视口 + 工厂 wiring,已 P2 验证),
+ *     仅 override factory 为本目录生成的工厂 → 生成游戏跑在【与 ref 完全相同的插件库装配】上。
+ *   - 引擎:Option C 动态 import(node import 本入口不触引擎,保 import-safe;esbuild 把引擎内联进单文件 iife)。
+ *
+ * 【Q4 铁律】本入口是「集成段 host」唯一引擎 import 落点(动态 import 后经 opts.engine 注入);
+ *   ./factory.js 游戏工厂零引擎 import,能力一律经 boot.ctx.getEngine()。
+ * ════════════════════════════════════════════════════════════════════════════
+ */
+
+'use strict';
+
+// 通用宿主(引擎骨架参数化;本身零引擎 import,引擎经 opts.engine 注入)。
+import { bootGameHost as bootGameHostCore } from '../../../src/host/boot-game-host.js';
+// 标准插件装配(复用 ref 同一份:collision/physics/gamefeel/juice/palettePost/audioMusic/save + 偏序 + 390×844 视口)。
+import { buildRefHostConfig } from '../../wanglanmei-ref/src/ref-host-config.js';
+// 本目录生成的游戏工厂(默认导出 GameHostFactory,零引擎 import,A3 硬独立文件)。
+import gameFactory from './factory.js';
+
+/** 【契约导出】GameHostFactory:宿主从 window.__GameBundle.GameHostFactory 取它(契约冻结)。= 本目录生成的工厂。 */
+export const GameHostFactory = gameFactory;
+// 默认导出同为 GameHostFactory(便于 import default 取用;与具名导出同一引用)。
+export default gameFactory;
+
+/**
+ * 【P2/W-G1 boot 入口】供 host 页在浏览器内启动本 bundle(引擎由本 bundle 注入后驱动)。
+ *   - 动态 import 引擎(Option C):调用时才求值,esbuild 已把引擎内联进本 bundle(无外部请求)。
+ *   - engineMode 强制 'real'(W-G1 真玩取证一律引擎掌帧)。
+ *   - 插件/视口/工厂 wiring 取自 buildRefHostConfig(与 ref 同一标准集),factory override 为生成工厂。
+ *   - recHook / onReady 透传:供取证 harness 注入「引擎 call-ID 探针」与「internals(uncaught) 收集」(假绿守卫)。
+ *
+ * @param {Object} opts host 页传入入参。
+ * @param {HTMLCanvasElement} opts.canvas 页面 #game 画布(real 通道引擎自建 mainCanvas#game-engine,本 canvas 作占位/输入兜底)。
+ * @param {HTMLElement} [opts.statusEl] 状态行(可空)。
+ * @param {number} [opts.seed] 主随机种子(缺省固定值,保确定性)。
+ * @param {Function} [opts.recHook] 引擎 call-ID 取证钩子 id=>void(取证路径注入 window.__engineCalls.push;渠道产物不注)。
+ * @param {Function} [opts.onReady] (host, internals)=>void 就绪回调(取证收集 internals.uncaught 等)。
+ * @param {any} [opts.engine] 覆盖引擎名字空间(缺省动态 import littlejsengine)。
+ * @returns {Promise} bootGameHost 的 host 句柄(frameCount/stepFrames/tap/do/state 等)。
+ */
+export async function bootGameHost(opts) {
+  const o = opts || {};
+  // 动态 import 引擎:求值时机延后到本函数被调用(浏览器运行期)。esbuild 内联,无外部请求。
+  const engine = o.engine || (await import('littlejsengine'));
+  // 主随机种子(缺省固定值,与 ref 取证同口径,保确定性可复现)。
+  const seed = (o.seed != null ? o.seed : 0x1234abcd) >>> 0;
+  // 复用 ref 标准装配(7 插件 + 偏序 + 视口 + 工厂 wiring)。
+  const cfg = buildRefHostConfig({ seed });
+  // 调通用宿主:real 通道引擎掌帧;factory override 为本目录生成工厂;其余 wiring 取标准集。
+  return bootGameHostCore({
+    canvas: o.canvas,
+    statusEl: o.statusEl || null,
+    engine,
+    seed,
+    mode: o.mode || 'play',           // W-G1 真玩=play
+    engineMode: 'real',               // 一律引擎掌帧(real 通道)
+    viewport: cfg.viewport,           // 390×844(与 ref 同,移动竖屏基准)
+    factory: gameFactory,             // ★ override:本目录【生成的游戏】(其余 wiring 全复用 ref)
+    plugins: cfg.plugins,             // 标准 7 插件实例集(经 opts.runtime.plugins 注入给工厂)
+    registerOrder: cfg.registerOrder, // 注册偏序(保六锚)
+    buildFactoryOpts: cfg.buildFactoryOpts, // 注入 runtime:{plugins,bundle,getRealAudioCtx}
+    recHook: o.recHook || null,       // 取证:引擎 call-ID 探针(默认 no-op)
+    onReady: o.onReady || null,       // 取证:收集 internals(uncaught)
+  });
+}
diff --git a/game-runtime/games/_wg1-gen/simon/evidence/after-play.png b/game-runtime/games/_wg1-gen/simon/evidence/after-play.png
new file mode 100644
index 00000000..d37d702a
Binary files /dev/null and b/game-runtime/games/_wg1-gen/simon/evidence/after-play.png differ
diff --git a/game-runtime/games/_wg1-gen/simon/evidence/first-paint.png b/game-runtime/games/_wg1-gen/simon/evidence/first-paint.png
new file mode 100644
index 00000000..1431fa77
Binary files /dev/null and b/game-runtime/games/_wg1-gen/simon/evidence/first-paint.png differ
diff --git a/game-runtime/games/_wg1-gen/simon/evidence/verdict.json b/game-runtime/games/_wg1-gen/simon/evidence/verdict.json
new file mode 100644
index 00000000..5d73e29b
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon/evidence/verdict.json
@@ -0,0 +1,61 @@
+{
+  "gameId": "simon",
+  "url": "http://localhost:4320/games/_wg1-gen/simon/index.html",
+  "ts": null,
+  "guards": {
+    "A_boot": {
+      "pass": true
+    },
+    "C_frame": {
+      "pass": true,
+      "f0": 48,
+      "f1": 79,
+      "delta": 31
+    },
+    "D_render": {
+      "pass": true,
+      "bright": 264569,
+      "maxCh": 255
+    },
+    "E_live": {
+      "pass": true,
+      "distinctStates": 6,
+      "samples": 11
+    },
+    "B_uncaught": {
+      "pass": true,
+      "uncaught": []
+    },
+    "F_wiring": {
+      "pass": true,
+      "callCount": 128,
+      "sample": [
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut"
+      ],
+      "expected": [
+        "audio.synth",
+        "particles."
+      ]
+    },
+    "G_input": {
+      "pass": true,
+      "inputHash": "a5100b7a",
+      "controlHash": "f7530fdd",
+      "atFrame": 400,
+      "ctrlFrame": 405
+    }
+  },
+  "pass": true,
+  "notes": []
+}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/simon/factory.js b/game-runtime/games/_wg1-gen/simon/factory.js
new file mode 100644
index 00000000..d1379f21
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon/factory.js
@@ -0,0 +1,297 @@
+'use strict';
+
+export default function createGame(opts) {
+  const o = opts || {};
+  let ctx = null;                // boot.ctx
+  let nowMs = 0;
+  let sub = null;                // pointerdown subscription
+
+  // game state
+  const COLORS = [
+    { name: 'red',   x: 55,  y: 300, w: 130, h: 130, dark: '#660000', bright: '#ff2020', freq: 220 },
+    { name: 'green',  x: 225, y: 300, w: 130, h: 130, dark: '#006600', bright: '#20ff20', freq: 330 },
+    { name: 'blue',   x: 55,  y: 470, w: 130, h: 130, dark: '#000066', bright: '#2020ff', freq: 440 },
+    { name: 'yellow', x: 225, y: 470, w: 130, h: 130, dark: '#666600', bright: '#ffff20', freq: 550 },
+  ];
+
+  let sequence = [];              // color indices 0-3
+  let round = 1;
+  let phase = 'idle';            // idle | computerPlaying | playerTurn | correctAnim | wrongAnim
+  let compStepIndex = 0;         // which color is currently being shown (playing)
+  let compStepStart = 0;         // ms when current computer step started
+  let compStepDuration = 500;    // ms each color stays lit during computer's turn
+  let compStepInterval = 100;    // ms gap between steps
+  let compNextStepTime = 0;      // when to start next computer step (ms)
+
+  let playerIndex = 0;           // expected next input index
+  let playerAnimStart = 0;       // when button press animation started
+  let playerAnimButton = -1;     // -1 = none
+
+  let resultAnimStart = 0;       // for correct / wrong pause
+  let resultDuration = 800;      // ms show result before next action
+  let resultType = '';           // 'correct' | 'wrong'
+
+  // local easing (fallback if engine not available)
+  function quadOut(t) { return t * (2 - t); }
+
+  // helper: is point inside button rect
+  function hitTest(px, py, btn) {
+    return px >= btn.x && px <= btn.x + btn.w && py >= btn.y && py <= btn.y + btn.h;
+  }
+
+  // play round: reset computer playback
+  function startComputerTurn() {
+    phase = 'computerPlaying';
+    compStepIndex = 0;
+    compStepStart = nowMs;
+    compNextStepTime = nowMs; // start first step immediately
+    playerIndex = 0;
+  }
+
+  // add a new random color to sequence
+  function extendSequence() {
+    const idx = ctx.random.range(0, 3) | 0; // use ctx.random
+    sequence.push(idx);
+  }
+
+  // start a new round (increment sequence length)
+  function startNextRound() {
+    round++;
+    extendSequence();
+    // small delay before computer plays
+    resultType = 'correct';
+    resultAnimStart = nowMs;
+    phase = 'correctAnim';
+  }
+
+  // reset game on mistake
+  function onWrong(pressedIndex) {
+    resultType = 'wrong';
+    resultAnimStart = nowMs;
+    phase = 'wrongAnim';
+    // emit failure particles at touched button
+    const eng = ctx.getEngine();
+    if (eng && eng.particles) {
+      try {
+        const btn = COLORS[pressedIndex];
+        eng.particles.spawnEmitter({
+          pos: { x: btn.x + btn.w / 2, y: btn.y + btn.h / 2 },
+          count: 30,
+          speed: 100,
+          particleTime: 0.4,
+          colorStart: { r: 1, g: 0.2, b: 0.2, a: 1 },
+          colorEnd: { r: 0.5, g: 0, b: 0, a: 0 },
+        });
+      } catch (_) {}
+    }
+    if (eng && eng.audio && eng.audio.synth) {
+      try {
+        eng.audio.synth.synthSfx([1, 0.1, 120, , , 0.2, , 0.8]); // error sound
+      } catch (_) {}
+    }
+  }
+
+  // correct input – advance or finish round
+  function onCorrectInput() {
+    playerIndex++;
+    if (playerIndex >= sequence.length) {
+      // round complete
+      const eng = ctx.getEngine();
+      if (eng && eng.particles) {
+        try {
+          eng.particles.spawnEmitter({
+            pos: { x: 195, y: 422 },
+            count: 40,
+            speed: 70,
+            particleTime: 0.6,
+            colorStart: { r: 1, g: 1, b: 0.5, a: 1 },
+            colorEnd: { r: 0, g: 0.5, b: 1, a: 0 },
+          });
+        } catch (_) {}
+      }
+      if (eng && eng.audio && eng.audio.synth) {
+        try {
+          eng.audio.synth.synthSfx([1, 0.2, 880, , , 0.3, , 1.6]); // success jingle
+        } catch (_) {}
+      }
+      startNextRound();
+    } else {
+      // let player continue
+      playerAnimButton = -1;
+    }
+  }
+
+  // handle pointer input
+  function onTap(e) {
+    if (phase !== 'playerTurn') return;
+    const px = e.x || 0;
+    const py = e.y || 0;
+    for (let i = 0; i < COLORS.length; i++) {
+      const btn = COLORS[i];
+      if (hitTest(px, py, btn)) {
+        // play sound and visual
+        playerAnimButton = i;
+        playerAnimStart = nowMs;
+        const eng = ctx.getEngine();
+        if (eng && eng.audio && eng.audio.synth) {
+          try {
+            eng.audio.synth.synthSfx([1, 0.05, btn.freq, , , 0.18, , 1.4]);
+          } catch (_) {}
+        }
+        // check correctness
+        if (i === sequence[playerIndex]) {
+          onCorrectInput();
+        } else {
+          onWrong(i);
+        }
+        break;
+      }
+    }
+  }
+
+  function init(boot) {
+    ctx = boot.ctx;
+    sub = ctx.getInput().on('pointerdown', onTap);
+
+    // initialize random sequence
+    sequence = [ctx.random.range(0, 3) | 0];
+    round = 1;
+    phase = 'idle';
+    // will start computer turn on first update
+  }
+
+  function update(dt) {
+    nowMs = ctx.time.nowMs();
+    // lazy start of computer turn
+    if (phase === 'idle') {
+      startComputerTurn();
+      return;
+    }
+
+    const eng = ctx.getEngine(); // may be null
+
+    // --- computer playing ---
+    if (phase === 'computerPlaying') {
+      // check if current step is finished
+      if (nowMs >= compStepStart + compStepDuration) {
+        // advance to next step
+        compStepIndex++;
+        if (compStepIndex >= sequence.length) {
+          // all steps shown -> switch to player turn
+          phase = 'playerTurn';
+          playerIndex = 0;
+          playerAnimButton = -1;
+        } else {
+          // schedule next step after interval
+          compStepStart = nowMs + compStepInterval;
+          compStepDuration = 500; // fixed per step
+          // play sound for this step at start?
+          // We'll play sound at the start of each step (including first) -> done below
+        }
+      }
+      // play sound when a new step starts (at compStepStart)
+      if (compStepIndex < sequence.length && nowMs >= compStepStart && nowMs < compStepStart + compStepDuration) {
+        const idx = sequence[compStepIndex];
+        const btn = COLORS[idx];
+        // play sound once per step: check if sound not yet played? Use a flag
+        // Simpler: play sound on every update, but that's ok; but to reduce calls we track last step played.
+        // We'll use a simple guard: only play within a tiny window after step start.
+        if (nowMs - compStepStart < 10) {
+          const eng2 = ctx.getEngine();
+          if (eng2 && eng2.audio && eng2.audio.synth) {
+            try { eng2.audio.synth.synthSfx([1, 0.05, btn.freq, , , 0.18, , 1.4]); } catch (_) {}
+          }
+        }
+      }
+      // also use easing to show button press (optional)
+      if (eng && eng.math && eng.math.easing) {
+        try { eng.math.easing.quadOut(0.5); } catch (_) {} // just to call engine
+      }
+      return;
+    }
+
+    // --- player turn ---
+    if (phase === 'playerTurn') {
+      // handle button press animation
+      if (playerAnimButton >= 0) {
+        // animate brief flash
+        if (nowMs - playerAnimStart > 150) {
+          playerAnimButton = -1;
+        }
+      }
+      // waiting for input: nothing else to update
+      return;
+    }
+
+    // --- result animation (correct/wrong) ---
+    if (phase === 'correctAnim' || phase === 'wrongAnim') {
+      if (nowMs - resultAnimStart >= resultDuration) {
+        if (phase === 'correctAnim') {
+          // start computer playing next sequence
+          startComputerTurn();
+        } else {
+          // wrong: reset game
+          sequence = [ctx.random.range(0, 3) | 0];
+          round = 1;
+          startComputerTurn();
+        }
+      }
+      return;
+    }
+  }
+
+  function render(g) {
+    // background (dark but not black)
+    g.fillStyle = '#0a0a23';
+    g.fillRect(0, 0, 390, 844);
+
+    // draw top info
+    g.fillStyle = '#ccccff';
+    g.font = '20px monospace';
+    g.fillText('Simon Round ' + round, 20, 50);
+
+    // draw four buttons
+    for (let i = 0; i < COLORS.length; i++) {
+      const btn = COLORS[i];
+      let isLit = false;
+
+      // check if this button should be lit
+      if (phase === 'computerPlaying' && compStepIndex < sequence.length) {
+        const currentIdx = sequence[compStepIndex];
+        if (i === currentIdx && nowMs >= compStepStart && nowMs < compStepStart + compStepDuration) {
+          isLit = true;
+        }
+      }
+      if (phase === 'playerTurn' && i === playerAnimButton && nowMs - playerAnimStart < 150) {
+        isLit = true;
+      }
+      // during result animation, if correct, briefly flash all? optional, we skip.
+
+      const fillColor = isLit ? btn.bright : btn.dark;
+      const radius = 8;
+      g.fillStyle = fillColor;
+      g.beginPath();
+      g.roundRect(btn.x, btn.y, btn.w, btn.h, radius);
+      g.fill();
+      // border
+      g.strokeStyle = '#222';
+      g.lineWidth = 2;
+      g.stroke();
+
+      // inner gloss hint
+      if (isLit) {
+        g.fillStyle = 'rgba(255,255,255,0.3)';
+        g.beginPath();
+        g.roundRect(btn.x + 10, btn.y + 10, btn.w - 20, btn.h / 3, 4);
+        g.fill();
+      }
+    }
+  }
+
+  function destroy() {
+    try { sub && sub.cancel(); } catch (_) {}
+    sub = null;
+  }
+
+  return { init, update, render, destroy };
+}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/simon/index.html b/game-runtime/games/_wg1-gen/simon/index.html
new file mode 100644
index 00000000..d5dd623c
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon/index.html
@@ -0,0 +1,83 @@
+
+
+
+
+  
+  
+  
+  W-G1 generated game
+  
+
+
+  
+
booting…
+ + +
+ + + + + + diff --git a/game-runtime/games/_wg1-gen/simon/play-spec.json b/game-runtime/games/_wg1-gen/simon/play-spec.json new file mode 100644 index 00000000..f19592aa --- /dev/null +++ b/game-runtime/games/_wg1-gen/simon/play-spec.json @@ -0,0 +1,48 @@ +{ + "inputs": [ + { + "t": "wait", + "ms": 1300 + }, + { + "t": "tap", + "x": 130, + "y": 360 + }, + { + "t": "wait", + "ms": 350 + }, + { + "t": "tap", + "x": 260, + "y": 360 + }, + { + "t": "wait", + "ms": 350 + }, + { + "t": "tap", + "x": 130, + "y": 500 + }, + { + "t": "wait", + "ms": 350 + }, + { + "t": "tap", + "x": 260, + "y": 500 + }, + { + "t": "wait", + "ms": 350 + } + ], + "expectedEngineCallPrefixes": [ + "audio.synth", + "particles." + ] +} \ No newline at end of file diff --git a/game-runtime/games/_wg1-gen/simon_m27/bundle.iife.js b/game-runtime/games/_wg1-gen/simon_m27/bundle.iife.js new file mode 100644 index 00000000..ae666b80 --- /dev/null +++ b/game-runtime/games/_wg1-gen/simon_m27/bundle.iife.js @@ -0,0 +1,34 @@ +"use strict";var __GameBundle=(()=>{var So=Object.defineProperty;var $l=Object.getOwnPropertyDescriptor;var Yl=Object.getOwnPropertyNames;var Xl=Object.prototype.hasOwnProperty;var Kl=(t,e,n)=>()=>{if(n)throw n[0];try{return t&&(e=t(t=0)),e}catch(s){throw n=[s],s}};var Ba=(t,e)=>{for(var n in e)So(t,n,{get:e[n],enumerable:!0})},Ql=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Yl(e))!Xl.call(t,i)&&i!==n&&So(t,i,{get:()=>e[i],enumerable:!(s=$l(e,i))||s.enumerable});return t};var Zl=t=>Ql(So({},"__esModule",{value:!0}),t);var ql={};Ba(ql,{ASSERT:()=>m,BLACK:()=>me,BLUE:()=>dl,Box2dDistanceJoint:()=>Zi,Box2dFrictionJoint:()=>Jr,Box2dGearJoint:()=>Fr,Box2dJoint:()=>ot,Box2dKinematicObject:()=>Rr,Box2dMotorJoint:()=>zr,Box2dObject:()=>Zs,Box2dPinJoint:()=>Or,Box2dPlugin:()=>eo,Box2dPrismaticJoint:()=>Gr,Box2dPulleyJoint:()=>Nr,Box2dRaycastResult:()=>Qi,Box2dRevoluteJoint:()=>Dr,Box2dRopeJoint:()=>Ir,Box2dStaticObject:()=>Ki,Box2dTargetJoint:()=>Lr,Box2dTileLayer:()=>Mr,Box2dWeldJoint:()=>jr,Box2dWheelJoint:()=>Br,CLEAR_BLACK:()=>At,CLEAR_WHITE:()=>Sn,CYAN:()=>Td,CanvasLayer:()=>Ji,Color:()=>Oe,Ease:()=>no,EngineObject:()=>Qt,GRAY:()=>vd,GREEN:()=>ul,ImageFont:()=>Ii,LOG:()=>Ee,Light:()=>vr,LightSystemPlugin:()=>Sr,MAGENTA:()=>Ad,Medal:()=>Yi,NewgroundsMedal:()=>gr,NewgroundsPlugin:()=>br,ORANGE:()=>wd,PI:()=>oe,PURPLE:()=>fl,Particle:()=>Ni,ParticleEmitter:()=>ur,PathFinder:()=>Ur,PathFinderNode:()=>so,PostProcessPlugin:()=>xr,RED:()=>Xr,RandomGenerator:()=>or,Sound:()=>Vs,SoundInstance:()=>Bi,TextureInfo:()=>Zt,TileCollisionLayer:()=>Ws,TileInfo:()=>Gt,TileLayer:()=>qs,TileLayerData:()=>Bn,Timer:()=>It,Tween:()=>to,UIButton:()=>Qs,UICheckbox:()=>Cr,UILayout:()=>Pr,UIObject:()=>yt,UISlider:()=>_r,UISystemPlugin:()=>Tr,UIText:()=>Xi,UITextInput:()=>Ar,UITile:()=>kr,UIVideo:()=>Er,Vector2:()=>ge,WHITE:()=>ne,YELLOW:()=>ll,ZzFXMusic:()=>wr,abs:()=>he,atan2:()=>Hr,audioContext:()=>Ae,audioDefaultSampleRate:()=>xs,audioIsRunning:()=>Us,audioMasterGain:()=>Kt,box2d:()=>b,box2dDebug:()=>Fa,box2dInit:()=>jh,box2dSetDebug:()=>Bh,cameraAngle:()=>ue,cameraFit:()=>Bf,cameraPos:()=>Ge,cameraScale:()=>ie,canvasClearColor:()=>mn,canvasColorTiles:()=>oo,canvasFixedSize:()=>ss,canvasMaxAspect:()=>ns,canvasMaxSize:()=>ts,canvasMinAspect:()=>Ms,canvasPixelRatio:()=>yn,canvasPixelated:()=>Zr,ceil:()=>Fs,clamp:()=>$,combineCanvases:()=>fa,cos:()=>be,debug:()=>We,debugCircle:()=>et,debugClear:()=>dd,debugLine:()=>Mt,debugOverlap:()=>sr,debugOverlay:()=>Ut,debugPoint:()=>Wr,debugPointSize:()=>Hc,debugPoly:()=>ud,debugRect:()=>_e,debugScreenshot:()=>Yc,debugShowErrors:()=>fd,debugText:()=>es,debugVideoCaptureIsActive:()=>Lt,debugVideoCaptureStart:()=>Xc,debugVideoCaptureStop:()=>Kc,debugWatermark:()=>io,distanceAngle:()=>bd,distanceWrap:()=>$r,drawCanvas2D:()=>Vn,drawCircle:()=>Oi,drawCircleGradient:()=>Df,drawContext:()=>De,drawCount:()=>Dt,drawCrescent:()=>zh,drawEllipse:()=>yl,drawEllipseGradient:()=>gl,drawLine:()=>On,drawLineList:()=>ar,drawNineSlice:()=>jl,drawNineSliceScreen:()=>Jh,drawPoly:()=>us,drawRect:()=>Li,drawRectGradient:()=>Lf,drawRegularPoly:()=>ml,drawText:()=>Ff,drawTextScreen:()=>gn,drawTextureWrapped:()=>Of,drawThreeSlice:()=>Jl,drawThreeSliceScreen:()=>Nh,drawTile:()=>Ne,enablePhysicsSolver:()=>lo,engineAddPlugin:()=>zn,engineImageFont:()=>vl,engineInit:()=>rd,engineName:()=>Ti,engineObjects:()=>Pe,engineObjectsCallback:()=>cd,engineObjectsCollect:()=>Wc,engineObjectsCollide:()=>qr,engineObjectsDestroy:()=>ad,engineObjectsRaycast:()=>ld,engineObjectsUpdate:()=>qc,engineVersion:()=>Ai,fetchJSON:()=>kd,floor:()=>Le,fontDefault:()=>ei,formatTime:()=>Kr,frame:()=>Uc,frameRate:()=>sd,gamepadConnected:()=>lr,gamepadDirectionEmulateStick:()=>ra,gamepadDpad:()=>cr,gamepadIsDown:()=>zt,gamepadPrimary:()=>Ce,gamepadStick:()=>Ns,gamepadStickCount:()=>wl,gamepadVibrate:()=>Zf,gamepadVibrateStop:()=>eh,gamepadWasPressed:()=>ba,gamepadWasReleased:()=>Qf,gamepadsEnable:()=>uo,getCameraSize:()=>xl,getCrescentPoints:()=>Nl,getNoteFrequency:()=>_l,getPaused:()=>id,glAntialias:()=>Aa,glCanvas:()=>fe,glCircleSides:()=>ti,glClearCanvas:()=>Ll,glClearRect:()=>Gl,glCompileShader:()=>yr,glContext:()=>g,glCopyToContext:()=>Pa,glCreateProgram:()=>ms,glCreateTexture:()=>mo,glDeleteTexture:()=>Il,glDraw:()=>Ys,glDrawColoredPoints:()=>La,glDrawOutlineTransform:()=>Ma,glDrawPoints:()=>Fl,glDrawPointsTransform:()=>Ra,glDrawUntextured:()=>Dl,glEnable:()=>W,glFlush:()=>Be,glSetAntialias:()=>_h,glSetRenderTarget:()=>Rs,glSetTexture:()=>_a,glSetTextureData:()=>Ea,glSetTextureWrap:()=>Ol,gravity:()=>tt,headlessMode:()=>Y,hsl:()=>qt,hypot:()=>Qc,inputClear:()=>ai,inputClearKey:()=>ya,inputMouseMoveThreshold:()=>ma,inputPreventDefault:()=>is,inputWASDEmulateDirection:()=>Ls,isArray:()=>wt,isColor:()=>Z,isFullscreen:()=>Sl,isIntersecting:()=>nl,isNumber:()=>I,isOnScreen:()=>jf,isOverlapping:()=>Ei,isPowerOfTwo:()=>Gs,isStringLike:()=>te,isTouchDevice:()=>pt,isUsingGamepad:()=>rs,isVector2:()=>D,keyDirection:()=>Xf,keyIsDown:()=>Je,keyWasPressed:()=>Ve,keyWasReleased:()=>ga,lastInputDevice:()=>hn,lerp:()=>nt,lerpAngle:()=>xd,lerpWrap:()=>tl,lightSystem:()=>se,lineTest:()=>il,log2:()=>Zc,mainCanvas:()=>H,mainCanvasSize:()=>z,mainContext:()=>Se,max:()=>le,medalDisplaySize:()=>Hi,medalDisplaySlideTime:()=>os,medalDisplayTime:()=>Wi,medals:()=>Xs,medalsForEach:()=>yo,medalsInit:()=>Mh,medalsPreventUnlock:()=>Oa,medalsReset:()=>Lh,min:()=>de,mod:()=>ht,mouseDelta:()=>ha,mouseDeltaScreen:()=>Et,mouseInWindow:()=>Di,mouseIsDown:()=>Is,mousePos:()=>Nt,mousePosScreen:()=>Ze,mouseWasPressed:()=>Js,mouseWasReleased:()=>Kf,mouseWheel:()=>pa,nearestPowerOfTwo:()=>Sd,newgrounds:()=>Ks,noise1D:()=>Rd,noise2D:()=>Md,objectDefaultAngleDamping:()=>sa,objectDefaultDamping:()=>na,objectDefaultFriction:()=>oa,objectDefaultMass:()=>ta,objectDefaultRestitution:()=>ia,objectMaxSpeed:()=>Wt,oscillate:()=>sl,particleEmitRateScale:()=>Pi,paused:()=>Ot,percent:()=>He,percentLerp:()=>gd,playSamples:()=>Ta,pointerLockExit:()=>sh,pointerLockIsActive:()=>Tl,pointerLockRequest:()=>nh,postProcess:()=>Ue,primitiveCount:()=>Ft,rand:()=>Te,randBool:()=>ol,randColor:()=>ir,randInCircle:()=>cl,randInt:()=>Yr,randSign:()=>rl,randVec2:()=>al,readSaveData:()=>Ed,rgb:()=>Q,round:()=>Ci,saveCanvas:()=>hl,saveDataURL:()=>Bs,saveText:()=>Cd,screenToWorld:()=>oi,screenToWorldDelta:()=>bl,screenToWorldTransform:()=>ri,setAdditiveBlendMode:()=>js,setCameraAngle:()=>Od,setCameraPos:()=>Ld,setCameraScale:()=>Id,setCanvasClearColor:()=>Gd,setCanvasColorTiles:()=>Fd,setCanvasFixedSize:()=>Nd,setCanvasMaxAspect:()=>Jd,setCanvasMaxSize:()=>Bd,setCanvasMinAspect:()=>jd,setCanvasPixelRatio:()=>Ud,setCanvasPixelated:()=>pl,setCursor:()=>Uf,setDebugKey:()=>Mf,setDebugWatermark:()=>Rf,setEnablePhysicsSolver:()=>Qd,setFontDefault:()=>Vd,setGLCircleSides:()=>$d,setGLEnable:()=>Hd,setGamepadDirectionEmulateStick:()=>lf,setGamepadsEnable:()=>cf,setGravity:()=>rf,setHeadlessMode:()=>Wd,setInputMouseMoveThreshold:()=>Wf,setInputPreventDefault:()=>qf,setInputWASDEmulateDirection:()=>uf,setMedalDisplaySize:()=>Dh,setMedalDisplaySlideTime:()=>Ih,setMedalDisplayTime:()=>Oh,setMedalsPreventUnlock:()=>Fh,setObjectDefaultAngleDamping:()=>tf,setObjectDefaultDamping:()=>ef,setObjectDefaultFriction:()=>sf,setObjectDefaultMass:()=>Zd,setObjectDefaultRestitution:()=>nf,setObjectMaxSpeed:()=>of,setParticleEmitRateScale:()=>af,setPaused:()=>od,setShowSplashScreen:()=>qd,setSoundDefaultRange:()=>Ef,setSoundDefaultTaper:()=>Pf,setSoundEnable:()=>Cf,setSoundVolume:()=>_f,setTileDefaultBleed:()=>Kd,setTileDefaultPadding:()=>Xd,setTileDefaultSize:()=>Yd,setTilesPixelated:()=>zd,setTimeScale:()=>Dd,setTouchGamepadAlpha:()=>wf,setTouchGamepadAnalog:()=>xf,setTouchGamepadButtonCount:()=>mf,setTouchGamepadCenterButtonSize:()=>pf,setTouchGamepadDisplayTime:()=>Tf,setTouchGamepadEnable:()=>ff,setTouchGamepadFloating:()=>Sf,setTouchGamepadLeftButtonCount:()=>gf,setTouchGamepadLeftStick:()=>yf,setTouchGamepadPassthrough:()=>hf,setTouchGamepadRightStick:()=>bf,setTouchGamepadSize:()=>vf,setTouchGamepadVibration:()=>Af,setTouchInputEnable:()=>df,setVibrateEnable:()=>kf,shareURL:()=>_d,showSplashScreen:()=>ea,sign:()=>ft,sin:()=>pe,smoothStep:()=>_i,soundDefaultRange:()=>la,soundDefaultTaper:()=>ua,soundEnable:()=>it,soundVolume:()=>Gn,speak:()=>bh,speakStop:()=>xh,tan:()=>el,textureInfos:()=>wn,tile:()=>ii,tileCollisionGetData:()=>ji,tileCollisionLayers:()=>bn,tileCollisionRaycast:()=>El,tileCollisionTest:()=>dn,tileDefaultBleed:()=>co,tileDefaultPadding:()=>ao,tileDefaultSize:()=>ro,tileLayersLoad:()=>vh,tilesPixelated:()=>jn,time:()=>ct,timeDelta:()=>Vr,timeReal:()=>xn,timeScale:()=>Qr,toggleFullscreen:()=>zf,touchGamepadAlpha:()=>ca,touchGamepadAnalog:()=>ni,touchGamepadButtonCount:()=>ys,touchGamepadCenterButtonSize:()=>Tt,touchGamepadDisplayTime:()=>Os,touchGamepadEnable:()=>vn,touchGamepadFloating:()=>Tn,touchGamepadLeftButtonCount:()=>gs,touchGamepadLeftStick:()=>Un,touchGamepadPassthrough:()=>aa,touchGamepadRightStick:()=>bs,touchGamepadSize:()=>st,touchGamepadVibration:()=>Ri,touchInputEnable:()=>Ln,tweenProperty:()=>Uh,tweenStopAll:()=>Vh,tweenUpdate:()=>Vl,uiDebug:()=>Da,uiSetDebug:()=>Gh,uiSystem:()=>E,usingGamepadInput:()=>Yf,usingKeyboardInput:()=>$f,usingMouseInput:()=>Hf,vec2:()=>T,vibrate:()=>xa,vibrateEnable:()=>si,vibrateStop:()=>th,workCanvas:()=>Yt,workContext:()=>fn,workReadCanvas:()=>Rt,workReadContext:()=>Ht,worldToScreen:()=>qn,worldToScreenDelta:()=>Gf,writeSaveData:()=>Pd,zzfx:()=>Sh,zzfxG:()=>ho,zzfxM:()=>Bl});function id(){return Ot}function od(t=!0){Ot=t}function zn(t,e,n,s){m(!In.find(r=>r.update===t&&r.render===e&&r.glContextLost===n&&r.glContextRestored===s));let i=new tr(t,e,n,s);In.push(i)}async function rd(t,e,n,s,i,r=[],a){if(Vc&&console.log(`${Ti} Engine v${Ai}`),m(!Se,"engine already initialized"),Se)return;m(wt(r),"pass in images as array"),document.body||document.documentElement.appendChild(document.createElement("body")),a||(a=document.body),t||(t=()=>{}),e||(e=()=>{}),n||(n=()=>{}),s||(s=()=>{}),i||(i=()=>{});function o(){z=T(H.width,H.height),Se.imageSmoothingEnabled=!jn,mr()}function c(p=0){let y=p-Qo;Qo||(y=0),Qo=p,(We||io)&&(ki=nt(ki,1e3/(y||1),.05));let x=We&&Je("Equal"),w=We&&Je("Minus"),A=x?10:w?.1:1;xn+=y*A/1e3;let v=Qr*A;y*=v,_t+=Ot?0:y,v<=1&&(_t=de(_t,50));let _=!1;if(Ot){_=!0,l(),Gc(),In.forEach(C=>{var L;return(L=C.update)==null?void 0:L.call(C)});for(let C of Pe)C.parent||C.updateTransforms();Oc(),n(),Bc(),Lt()&&k()}else{let C=0;for(_t<0&&_t>-9&&(C=_t,_t=0);_t>=0;_t-=1e3/60)ct=Uc++/60,_=!0,l(),Gc(),e(),In.forEach(L=>{var V;return(V=L.update)==null?void 0:V.call(L)}),qc(),Oc(),n(),Bc(),Lt()&&k();_t+=C}Lt()||k(),requestAnimationFrame(c);function k(){if(!Y){_||l(),o(),s(),Pe.sort((C,L)=>C.renderOrder-L.renderOrder);for(let C of Pe)C.destroyed||C.render();i(),In.forEach(C=>{var L;return(L=C.render)==null?void 0:L.call(C)}),oh(),pd(),Be(),md(),Dt=0,Ft=0}}}function l(){if(!Y){if(ss.x){z=ss.copy();let p=innerWidth/innerHeight,y=ss.x/ss.y,x=pns){let _=z.y*ns|0;z.x=de(_,ts.x)}else if(w0&&!W&&(Se.fillStyle=mn.toString(),Se.fillRect(0,0,z.x,z.y),Se.fillStyle=me.toString()),Se.lineJoin="round",Se.lineCap="round"}}if(Y)return f();Ah(a);let u="margin:0;overflow:hidden;background:#000;user-select:none;-webkit-user-select:none;touch-action:none;-webkit-touch-callout:none";a.style.cssText=u,H=a.appendChild(document.createElement("canvas")),De=Se=H.getContext("2d"),ih(),gh(),hd();let h="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)";H.style.cssText=h,fe&&(fe.style.cssText=h),pl(Zr),l(),mr(),Yt=new OffscreenCanvas(64,64),fn=Yt.getContext("2d"),Rt=new OffscreenCanvas(64,64),Ht=Rt.getContext("2d",{willReadFrequently:!0});let d=r.map((p,y)=>Dc(y,p));return r.length||d.push(Dc(0)),d.push(Vf()),ea&&d.push(new Promise(p=>{let y=0;x();function x(){ai(),Rh(y+=.01),y>1?p():setTimeout(x,16)}})),await Promise.all(d),f();async function f(){await t(),c()}}function qc(){qr=Pe.filter(e=>e.collideSolidObjects);function t(e){if(!e.destroyed){e.update();for(let n of e.children)t(n)}}for(let e of Pe)if(!(e.parent||e.destroyed)){e.update(),e.updatePhysics();for(let n of e.children)t(n);e.updateTransforms()}Pe=Pe.filter(e=>!e.destroyed)}function ad(t=!0){for(let e of Pe)e.parent||e.destroy(t);Pe=Pe.filter(e=>!e.destroyed)}function Wc(t,e,n=Pe){let s=[];if(t)if(e instanceof ge)for(let i of n)i.isOverlapping(t,e)&&s.push(i);else{let i=e*e;for(let r of n)t.distanceSquared(r.pos)n(i))}function ld(t,e,n=Pe){let s=[];for(let i of n)i.collideRaycast&&nl(t,e,i.pos,i.size)&&(vt&&_e(i.pos,i.size,"#f00"),s.push(i));return vt&&Mt(t,e,s.length?"#f00":"#00f",.02),s}function m(t,...e){if(!t)throw console.assert(t,...e),new Error("Assert failed!")}function Ee(...t){console.log(...t)}function _e(t,e=T(),n=ne,s=0,i=0,r=!1,a=!1){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(te(n)||Z(n),"color is invalid"),m(I(s),"time must be a number"),m(I(i),"angle must be a number"),Z(n)&&(n=n.toString());let o=new It(s);pn.push({pos:t.copy(),size:e.copy(),color:n,timer:o,angle:i,fill:r,screenSpace:a})}function ud(t,e,n=ne,s=0,i=0,r=!1,a=!1){m(D(t),"pos must be a vec2"),m(wt(e),"points must be an array"),m(te(n)||Z(n),"color is invalid"),m(I(s),"time must be a number"),m(I(i),"angle must be a number"),Z(n)&&(n=n.toString()),t=t.copy(),e=e.map(c=>c.copy());let o=new It(s);pn.push({pos:t,points:e,color:n,timer:o,angle:i,fill:r,screenSpace:a})}function et(t,e=0,n=ne,s=0,i=!1,r=!1){m(D(t),"pos must be a vec2"),m(I(e),"size must be a number"),m(te(n)||Z(n),"color is invalid"),m(I(s),"time must be a number"),Z(n)&&(n=n.toString()),t=t.copy();let a=new It(s);pn.push({pos:t,size:e,color:n,timer:a,angle:0,fill:i,screenSpace:r})}function Wr(t,e,n,s,i=!1){_e(t,void 0,e,n,s,!1,i)}function Mt(t,e,n,s=.1,i=0,r=!1){m(D(t),"posA must be a vec2"),m(D(e),"posB must be a vec2"),m(I(s),"width must be a number");let a=T((e.x-t.x)/2,(e.y-t.y)/2),o=T(s,a.length()*2);_e(t.add(a),o,n,i,a.angle(),!0,r)}function sr(t,e,n,s,i,r,a=!1){m(D(t),"posA must be a vec2"),m(D(n),"posB must be a vec2"),m(D(e),"sizeA must be a vec2"),m(D(s),"sizeB must be a vec2");let o=T(de(t.x-e.x/2,n.x-s.x/2),de(t.y-e.y/2,n.y-s.y/2)),c=T(le(t.x+e.x/2,n.x+s.x/2),le(t.y+e.y/2,n.y+s.y/2));_e(o.lerp(c,.5),c.subtract(o),i,r,0,!1,a)}function es(t,e,n=1,s=ne,i=0,r=0,a="monospace",o=!1){m(te(t),"text must be a string"),m(D(e),"pos must be a vec2"),m(I(n),"size must be a number"),m(te(s)||Z(s),"color is invalid"),m(I(i),"time must be a number"),m(I(r),"angle must be a number"),m(te(a),"font must be a string"),Z(s)&&(s=s.toString()),e=e.copy();let c=new It(i);pn.push({text:t,pos:e,size:n,color:s,timer:c,angle:r,font:a,screenSpace:o})}function dd(){pn=[]}function Yc(){nr=1}function fd(){let t=n=>{document.body.style="background-color:#111;margin:8px",document.body.innerHTML="
"+n},e=console.assert;console.assert=(n,...s)=>{if(e(n,...s),!n){let i=s.join(" "),r=new Error().stack;throw`Assertion failed!
+`+i+`
+`+r}},onunhandledrejection=n=>t(n.reason.stack||n.reason),onerror=(n,s,i,r)=>t(`${n}
+${s}
+Ln ${i}, Col ${r}`)}function hd(){Vc&&console.warn("LittleJS DEBUG build loaded. Use the release build for production.")}function Oc(){We&&(Ve($c)&&(Ut=!Ut),Ut&&(Ve("Digit1")&&(St=!St,Dn=!1),Ve("Digit2")&&(Dn=!Dn,St=!1),Ve("Digit3")&&(Fn=!Fn),Ve("Digit4")&&(vt=!vt),Ve("Digit5")&&Yc(),Ve("Digit7")&&(ls=!ls)),Lt()?(!Ut||Ve("Digit6"))&&Kc():Ut&&Ve("Digit6")&&Xc())}function pd(){if(Lt())return;Be();let t=Dt,e=Ft;nr&&(fa(),hl(H),nr=0);let n=Se;if(Fn&&uo){let r=0;for(let a=0;a<8;a++)lr(a)&&r++;for(let a=0;a<8;a++){if(!lr(a))continue;let o=1,c=.2,l=Ge.add(T(-o*2,((r-1)/2-a)*o*3));es(a,l.add(T(-o,o)),1),a===Ce&&es("Main",l.add(T(-o*2,0)),1,"#0f0");let u=Pt[a].length;for(let d=0;d{n.save();let r=i.pos,a=1,o=i.angle;if(i.screenSpace||(r=qn(i.pos),a=ie,o-=ue),n.translate(r.x|0,r.y|0),n.rotate(o),n.scale(1,i.text?1:-1),n.fillStyle=i.color,n.strokeStyle=i.color,i.text!==void 0)n.font=i.size*a+"px "+i.font,n.textAlign="center",n.textBaseline="middle",n.fillText(i.text,0,0);else if(i.points!==void 0){n.beginPath();for(let c of i.points){let l=c.scale(a).floor();n.lineTo(l.x,l.y)}n.closePath(),i.fill&&n.fill(),n.stroke()}else if(i.size===0||i.size.x===0&&i.size.y===0){let c=Hc*a;n.fillRect(-c/2,-1,c,3),n.fillRect(-1,-c/2,3,c)}else if(i.size.x!==void 0){let c=i.size.scale(a).floor(),l=c.x,u=c.y;i.fill&&n.fillRect(-l/2|0,-u/2|0,l,u),n.strokeRect(-l/2|0,-u/2|0,l,u)}else n.beginPath(),n.arc(0,0,i.size*a/2,0,9),i.fill&&n.fill(),n.stroke();n.restore()}),pn=pn.filter(i=>i.timer<0),s){let i=El(s.pos,Nt);i&&Li(i.floor().add(T(.5)),T(1),Q(0,1,1,.3),0,!1),On(Nt,s.pos,.1,i?Q(1,0,0,.5):Q(0,1,0,.5),void 0,void 0,!1);let r="mouse pos = "+Nt;bn.length&&(r+=`
+mouse collision = `+ji(Nt)),r+=`
+
+--- object info ---
+`,r+=s.toString(),gn(r,Ze,24,Q(),.05,void 0,"center","monospace")}{n.save(),n.fillStyle="#fff",n.textAlign="left",n.textBaseline="top",n.font="20px monospace",n.shadowColor="#000",n.shadowBlur=9;let a=9,o=0,c=24;if(Ut){n.fillText(`${Ti} v${Ai}`,a,o+=c/2),n.fillText("Time: "+Kr(ct),a,o+=c),n.fillText("FPS: "+ki.toFixed(1)+(W?" WebGL":" Canvas2D"),a,o+=c),n.fillText("Objects: "+Pe.length,a,o+=c),n.fillText("Draw Calls: "+Dt,a,o+=c),n.fillText("Primitives: "+Ft,a,o+=c),n.fillText("---------",a,o+=c),n.fillStyle="#f00",n.fillText("ESC: Debug Overlay",a,o+=c),n.fillStyle=St?"#f00":"#fff",n.fillText("1: Debug Physics",a,o+=c),n.fillStyle=Dn?"#f00":"#fff",n.fillText("2: Debug Particles",a,o+=c),n.fillStyle=Fn?"#f00":"#fff",n.fillText("3: Debug Gamepads",a,o+=c),n.fillStyle=vt?"#f00":"#fff",n.fillText("4: Debug Raycasts",a,o+=c),n.fillStyle="#fff",n.fillText("5: Save Screenshot",a,o+=c),n.fillText("6: Toggle Video Capture",a,o+=c),n.fillStyle=ls?"#f00":"#fff",n.fillText("7: Debug Sound",a,o+=c);let l="",u="";for(let h in re[0])Je(h,0)&&(parseInt(h)<3?u+=h+" ":l+=h+" ");u&&n.fillText("Mouse: "+u,a,o+=c),l&&n.fillText("Keys: "+l,a,o+=c);for(let h=1;hs.push(o.data),i.onstop=()=>{let o=new Blob(s,{type:"video/webm"}),c=URL.createObjectURL(o);Bs(c,"capture.webm",1e3)};let r,a;if(it){a=new ConstantSourceNode(Ae,{offset:0}),a.connect(Kt),a.start(),r=Ae.createMediaStreamDestination(),Kt.connect(r);for(let o of r.stream.getAudioTracks())t.addTrack(o)}try{i.start()}catch{Ee("Video capture not supported in this browser!"),a==null||a.stop();return}Ee("Video capture started."),Vt={mediaRecorder:i,captureTimer:n,videoTrack:e,silentAudioSource:a,audioStreamDestination:r}}function Kc(){var t,e,n;m(Lt(),"Not capturing video!"),Ee(`Video capture ended. ${Vt.captureTimer.get().toFixed(2)} seconds recorded.`),xt.style.display="none",(t=Vt.silentAudioSource)==null||t.stop(),(e=Vt.mediaRecorder)==null||e.stop(),(n=Vt.videoTrack)==null||n.stop(),Vt=void 0}function yd(){m(Lt(),"Not capturing video!"),fa(),Vt.videoTrack.requestFrame(),xt.textContent="\u25CF REC "+Kr(Vt.captureTimer)}function ut(t){if(We){let e=Object.keys(t),n={};e.forEach(s=>n[s]=t[s]),e.forEach(s=>{Object.defineProperty(t,s,{get:()=>n[s],set:i=>{m(!1,`Cannot modify engine constant. Attempted to set constant (${t}) property '${s}' to '${i}'.`)},enumerable:!0})})}return Object.freeze(t)}function ht(t,e=1){return(t%e+e)%e}function $(t,e=0,n=1){return tn?n:t}function He(t,e,n){return(n-=e)?$((t-e)/n):0}function nt(t,e,n){return t+$(n)*(e-t)}function gd(t,e,n,s,i){return nt(s,i,He(t,e,n))}function $r(t,e,n=1){m(n>0,"distanceWrap wrapSize must be > 0");let s=(t-e)%n;return s*2%n-s}function tl(t,e,n,s=1){return t+$(n)*$r(e,t,s)}function bd(t,e){return $r(t,e,2*oe)}function xd(t,e,n){return tl(t,e,n,2*oe)}function _i(t){return t*t*(3-2*t)}function Gs(t){return!(t&t-1)}function Sd(t){return 2**Fs(Zc(t))}function Ei(t,e,n,s=T()){let i=(t.x-n.x)*2,r=(t.y-n.y)*2,a=e.x+s.x,o=e.y+s.y;return he(i)d)return!1;h=le(p,h)}else{if(p0?o.x+1:o.x,y=h>0?o.y+1:o.y,x=c?(p-t.x)/c:1/0,w=l?(y-t.y)/l:1/0,A=0,v=x,_=w,k=do.x&&(C.x=o.x+1-L),V.yo.y&&(C.y=o.y+1-L),s&&(k?s.set(-u,0):s.set(0,-h)),C}(k=v<_)?(o.x+=u,A=v,v+=d):(o.y+=h,A=_,_+=f)}}function Te(t=1,e=0){return e+Math.random()*(t-e)}function Yr(t,e=0){return Le(Te(t,e))}function ol(t=.5){return Te()URL.revokeObjectURL(t),n)}function _d(t,e,n){var s;m(te(t),"shareURL requires title string"),m(te(e),"shareURL requires url string"),(s=navigator.share)==null||s.call(navigator,{title:t,url:e}).then(()=>n==null?void 0:n())}function Ed(t,e){m(te(t),"loadData requires saveName string");let n={};try{let s=localStorage[t];if(s)try{n=JSON.parse(s)}catch{Ee("readSaveData: corrupt JSON for",t,"\u2014 using defaults")}}catch{Ee("readSaveData: localStorage unavailable \u2014 using defaults")}return{...e,...n}}function Pd(t,e){m(te(t),"saveData requires saveName string");try{localStorage[t]=JSON.stringify(e)}catch{Ee("writeSaveData: failed to write",t)}}function rr(t){let e=(t|0)^2654435769;return e=Math.imul(e^e>>>16,2246822507),e=Math.imul(e^e>>>13,3266489909),e^=e>>>16,(e>>>0)/2**32}function Rd(t){let e=Le(t);return nt(rr(e),rr(e+1),_i(t-e))}function Md(t,e){let n=Le(t),s=Le(e),i=_i(t-n),r=_i(e-s),a=(o,c)=>rr(o+c*374761393);return nt(nt(a(n,s),a(n+1,s),i),nt(a(n,s+1),a(n+1,s+1),i),r)}function Ld(t){Ge=t.copy()}function Od(t){ue=t}function Id(t){ie=t}function Dd(t){Qr=t}function Fd(t){oo=t}function Gd(t){mn=t.copy()}function Bd(t){ts=t.copy()}function jd(t){Ms=t}function Jd(t){ns=t}function Nd(t){ss=t.copy()}function pl(t){Zr=t,H&&(H.style.imageRendering=t?"pixelated":""),fe&&(fe.style.imageRendering=t?"pixelated":"")}function zd(t){jn=t}function Ud(t){yn=t}function Vd(t){ei=t}function qd(t){ea=t}function Wd(t){Y=t}function Hd(t){if(t&&!pr){console.warn("Can not enable WebGL if it was disabled on start.");return}W=t,fe&&(fe.style.display=t?"":"none")}function $d(t){ti=t}function Yd(t){ro=t.copy()}function Xd(t){ao=t}function Kd(t){co=t}function Qd(t){lo=t}function Zd(t){ta=t}function ef(t){na=t}function tf(t){sa=t}function nf(t){ia=t}function sf(t){oa=t}function of(t){Wt=t}function rf(t){tt=t.copy()}function af(t){Pi=t}function cf(t){uo=t}function lf(t){ra=t}function uf(t){Ls=t}function df(t){Ln=t}function ff(t){vn=t}function hf(t){aa=t}function pf(t){Tt=t}function mf(t){ys=t,t>0&&(bs=!1)}function yf(t){Un=t,t&&(gs=0)}function gf(t){gs=t,t>0&&(Un=!1)}function bf(t){bs=t,t&&(ys=0)}function xf(t){ni=t}function Sf(t){Tn=t}function vf(t){st=t}function wf(t){ca=t}function Tf(t){Os=t}function Af(t){Ri=t}function kf(t){si=t}function Cf(t){it=t}function _f(t){Gn=t,it&&!Y&&Kt&&(Kt.gain.value=t)}function Ef(t){la=t}function Pf(t){ua=t}function Rf(t){io=t}function Mf(t){$c=t}function Mi(t){return t.r>=1&&t.g>=1&&t.b>=1}function da(t){return t.r<=0&&t.g<=0&&t.b<=0&&t.a<=0}function ii(t=0,e=ro,n=0,s=ao,i=co){if(m(D(t)||typeof t=="number","index must be a vec2 or number"),m(D(e)||typeof e=="number","size must be a vec2 or number"),m(I(n)||n instanceof Zt,"texture must be a number or TextureInfo"),m(I(s),"padding must be a number"),Y)return new Gt;typeof e=="number"&&(m(e>0),e=new ge(e,e));let r=typeof n=="number"?wn[n]:n;m(r instanceof Zt,"tile texture is not loaded"),m(r.size.x>0,"tile texture is not loaded");let a=e.x+s*2,o=e.y+s*2,c,l;if(typeof t=="number"){let h=r.size.x/a|0;c=t%h,l=t/h|0}else c=t.x,l=t.y;let u=new ge(c*a+s,l*o+s);return new Gt(u,e,r,s,i)}function Ne(t,e=T(1),n,s=ne,i=0,r,a,o=W,c=!1,l){var d;m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(Z(s),"color is invalid"),m(I(i),"angle must be a number"),m(!a||Z(a),"additiveColor must be a color"),m(!l||!o,"context only supported in canvas 2D mode");let u=n==null?void 0:n.textureInfo,h=(d=n==null?void 0:n.bleed)!=null?d:0;if(o&&W)if(m(!!g,"WebGL is not enabled!"),c&&([t,e,i]=ri(t,e,i)),u){let f=u.sizeInverse,p=n.pos.x*f.x,y=n.pos.y*f.y,x=n.size.x*f.x,w=n.size.y*f.y;if(_a(u.glTexture),h){let A=f.x*h,v=f.y*h;Ys(t.x,t.y,r?-e.x:e.x,e.y,i,p+A,y+v,p-A+x,y-v+w,s.rgbaInt(),a&&a.rgbaInt())}else Ys(t.x,t.y,r?-e.x:e.x,e.y,i,p,y,p+x,y+w,s.rgbaInt(),a&&a.rgbaInt())}else{let f=a?s.add(a):s;Dl(t.x,t.y,e.x,e.y,i,f.rgbaInt())}else++Dt,++Ft,Vn(t,e,i,r,f=>{if(u){f.scale(1,-1);let p=n.pos.x,y=n.pos.y,x=n.size.x,w=n.size.y;Nf(f,u.image,p,y,x,w,-.5,-.5,1,1,s,a,h)}else{let p=a?s.add(a):s;f.fillStyle=p.toString(),f.fillRect(-.5,-.5,1,1)}},c,l)}function Li(t,e,n,s,i,r,a){Ne(t,e,void 0,n,s,!1,void 0,i,r,a)}function Lf(t,e,n=ne,s=Sn,i=0,r=W,a=!1,o){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(Z(n)&&Z(s),"color is invalid"),m(I(i),"angle must be a number"),m(!o||!r,"context only supported in canvas 2D mode"),r&&W){m(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/ie),i+=ue);let c=[],l=[],u=e.x/2,h=e.y/2,d=n.rgbaInt(),f=s.rgbaInt(),p=be(-i),y=pe(-i);for(let x=4;x--;){let w=x&1?u:-u,A=x&2?h:-h,v=w*p-A*y,_=w*y+A*p,k=x&2?d:f;c.push(T(t.x+v,t.y+_)),l.push(k)}La(c,l)}else++Dt,++Ft,Vn(t,e,i,!1,c=>{let l=c.createLinearGradient(0,.5,0,-.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.fillRect(-.5,-.5,1,1)},a,o)}function Of(t,e,n,s=0,i=ne,r=0,a,o=W,c=!1,l){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(D(n),"wrapCount must be a vec2"),m(Z(i),"color is invalid"),m(I(r),"angle must be a number"),m(!a||Z(a),"additiveColor must be a color"),m(!l||!o,"context only supported in canvas 2D mode"),m(!(s instanceof Gt),"pass a TextureInfo or texture index, not a TileInfo \u2014 use tileInfo.textureInfo"),Y)return;let u=typeof s=="number"?wn[s]:s;if(m(u instanceof Zt,"texture not loaded"),m(u.size.x>0,"texture not loaded"),m(u.wrap,"drawTextureWrapped requires a wrap-enabled texture; call textureInfo.setWrap(true) first"),o&&W){m(!!g,"WebGL is not enabled!"),c&&([t,e,r]=ri(t,e,r)),_a(u.glTexture),Ys(t.x,t.y,e.x,e.y,r,0,0,n.x,n.y,i.rgbaInt(),a&&a.rgbaInt());return}++Dt,++Ft,c||(t=qn(t),e=e.scale(ie),r-=ue);let h=!oo||(a?Mi(i.add(a))&&a.a<=0:Mi(i)),d=!h&&a&&!da(a),f=h?u.image:Jf(u.image,i,a);l=l||De,l.save(),l.translate(t.x+.5,t.y+.5),l.rotate(r),l.globalAlpha=d?1:i.a;let p=l.createPattern(f,"repeat"),y=new DOMMatrix().translate(-e.x/2,-e.y/2).scale(e.x/(n.x*f.width),e.y/(n.y*f.height));p.setTransform(y),l.fillStyle=p,l.fillRect(-e.x/2,-e.y/2,e.x,e.y),l.globalAlpha=1,l.restore()}function ar(t,e=.1,n=ne,s=!1,i=T(),r=0,a=W,o=!1,c){if(m(wt(t),"points must be an array"),m(I(e),"width must be a number"),m(Z(n),"color is invalid"),m(D(i),"pos must be a vec2"),m(I(r),"angle must be a number"),m(!c||!a,"context only supported in canvas 2D mode"),a&&W){m(!!g,"WebGL is not enabled!");let l=T(1);o&&([i,l,r]=ri(i,l,r)),Ma(t,n.rgbaInt(),e,i.x,i.y,l.x,l.y,r,s)}else++Dt,++Ft,Vn(i,T(1),r,!1,l=>{l.strokeStyle=n.toString(),l.lineWidth=e,l.beginPath();for(let u=0;u0&&Ma(t,s.rgbaInt(),n,i.x,i.y,l.x,l.y,r)}else Vn(i,T(1),r,!1,l=>{l.fillStyle=e.toString(),l.beginPath();for(let u of t)l.lineTo(u.x,u.y);l.closePath(),l.fill(),n&&(l.strokeStyle=s.toString(),l.lineWidth=n,l.stroke())},o,c)}function yl(t,e=T(1),n=ne,s=0,i=0,r=me,a=W,o=!1,c){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(Z(n)&&Z(r),"color is invalid"),m(I(s),"angle must be a number"),m(I(i),"lineWidth must be a number"),m(i>=0,"lineWidth must be a positive value or 0"),m(!c||!a,"context only supported in canvas 2D mode"),i=$(i,0,de(e.x,e.y)),a&&W?ml(t,e,ti,n,i,r,s,a,o,c):Vn(t,T(1),s,!1,l=>{l.fillStyle=n.toString(),l.beginPath(),l.ellipse(0,0,e.x/2,e.y/2,0,0,9),l.fill(),i&&(l.strokeStyle=r.toString(),l.lineWidth=i,l.stroke())},o,c)}function Oi(t,e=1,n=ne,s=0,i=me,r=W,a=!1,o){m(I(e),"size must be a number"),yl(t,T(e),n,0,s,i,r,a,o)}function gl(t,e=T(1),n=ne,s=Sn,i=0,r=W,a=!1,o){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(Z(n)&&Z(s),"color is invalid"),m(I(i),"angle must be a number"),m(!o||!r,"context only supported in canvas 2D mode"),!Y)if(r&&W){m(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/ie),i+=ue);let c=ti,l=e.x/2,u=e.y/2,h=n.rgbaInt(),d=s.rgbaInt(),f=If++,p=be(-i),y=pe(-i),x=_=>{let k=pe(_)*l,C=be(_)*u;return T(t.x+k*p-C*y,t.y+k*y+C*p)},w=f%c/c*oe*2,A=[x(w)],v=[d];for(let _=c;_--;){let k=(_+f)%c/c*oe*2;A.push(t),v.push(h),A.push(x(k)),v.push(d)}La(A,v)}else++Dt,++Ft,Vn(t,e,i,!1,c=>{let l=c.createRadialGradient(0,0,0,0,0,.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.beginPath(),c.ellipse(0,0,.5,.5,0,0,9),c.fill()},a,o)}function Df(t,e=1,n=ne,s=Sn,i=W,r=!1,a){m(I(e),"size must be a number"),gl(t,T(e),n,s,0,i,r,a)}function Vn(t,e,n=0,s=!1,i,r=!1,a=De){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(I(n),"angle must be a number"),m(typeof i=="function","drawFunction must be a function"),r||(t=qn(t),e=e.scale(ie),n-=ue),a.save(),a.translate(t.x+.5,t.y+.5),a.rotate(n),a.scale(s?-e.x:e.x,-e.y),i(a),a.restore()}function Ff(t,e,n=1,s=ne,i=0,r=me,a="center",o=ei,c="",l,u=0,h=De){e=qn(e),n*=ie,i*=ie,u-=ue,u*=-1,gn(t,e,n,s,i,r,a,o,c,l,u,h)}function gn(t,e,n,s=ne,i=0,r=me,a="center",o=ei,c="",l,u=0,h=De){m(te(t),"text must be a string"),m(D(e),"pos must be a vec2"),m(I(n),"size must be a number"),m(Z(s),"color must be a color"),m(I(i),"lineWidth must be a number"),m(Z(r),"lineColor must be a color"),m(["left","center","right"].includes(a),"align must be left, center, or right"),m(te(o),"font must be a string"),m(te(c),"fontStyle must be a string"),m(I(u),"angle must be a number");let d=(t+"").split(`
+`),f=e.y-(d.length-1)*n/2;h.save(),h.fillStyle=s.toString(),h.strokeStyle=r.toString(),h.lineWidth=i,h.textAlign=a,h.font=c+" "+n+"px "+o,h.textBaseline="middle",h.translate(e.x,f),h.rotate(-u);let p=0;d.forEach(y=>{i&&h.strokeText(y,0,p,l),h.fillText(y,0,p,l),p+=n}),h.restore()}async function Dc(t,e){m(I(t),"textureIndex must be a number"),m(!wn[t],"textureIndex is already loaded!"),m(!e||te(e),"image src must be a string");let n=new Image;e&&await new Promise(s=>{n.onerror=n.onload=s,n.crossOrigin="anonymous",n.src=e}),wn[t]=new Zt(n)}function oi(t){m(D(t),"screenPos must be a vec2");let e=(t.x-z.x/2+.5)/ie,n=(t.y-z.y/2+.5)/-ie;if(ue){let s=be(-ue),i=pe(-ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e+Ge.x,n+Ge.y)}function qn(t){m(D(t),"worldPos must be a vec2");let e=t.x-Ge.x,n=t.y-Ge.y;if(ue){let s=be(ue),i=pe(ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e*ie+z.x/2-.5,n*-ie+z.y/2-.5)}function bl(t){m(D(t),"screenDelta must be a vec2");let e=t.x/ie,n=t.y/-ie;if(ue){let s=be(-ue),i=pe(-ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e,n)}function Gf(t){m(D(t),"worldDelta must be a vec2");let e=t.x,n=t.y;if(ue){let s=be(ue),i=pe(ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e*ie,n*-ie)}function ri(t,e,n=0){return m(D(t),"screenPos must be a vec2"),m(D(e),"screenSize must be a vec2"),m(I(n),"screenAngle must be a number"),[oi(t),e.scale(1/ie),n+ue]}function xl(){return z.scale(1/ie)}function Bf(t,e,n,s){m(D(t),"center must be a vec2"),m(D(e),"size must be a vec2");let i=d(n),r=d(s),a=e.x+i.left+i.right,o=e.y+i.top+i.bottom,c=z.x-r.left-r.right,l=z.y-r.top-r.bottom;if(!(a>0&&o>0&&c>0&&l>0))return ie;ie=de(c/a,l/o);let u=T(i.right-i.left,i.top-i.bottom).scale(.5),h=T(r.right-r.left,r.top-r.bottom).scale(.5/ie);return Ge=t.add(u).add(h),ie;function d(f){return(f===void 0||I(f))&&(f=T(f)),D(f)?{top:f.y,right:f.x,bottom:f.y,left:f.x}:{top:f.top||0,right:f.right||0,bottom:f.bottom||0,left:f.left||0}}}function jf(t,e=0){if(m(D(t),"pos must be a vec2"),m(D(e)||I(e),"size must be a vec2 or number"),!ie)return!1;let n=t.x-Ge.x,s=t.y-Ge.y;if(ue){let a=be(ue),o=pe(ue),c=n*a-s*o,l=n*o+s*a;n=c,s=l}n*=ie*2,s*=-ie*2,e instanceof ge&&(e=e.length()),e*=ie;let i=z.x,r=z.y;return n+e>-i&&n-e-r&&s-e{t.onerror=t.onload=o,t.crossOrigin="anonymous",t.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAAeAQMAAABnrVXaAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAAjpJREFUOMu9kzFu2zAUhn+CAROgqrk+B2l0BWYxMjlXeYaAtFtbdA1sGgHqRQfI0CNkSG5AwYB0BQ8d5Bsomwah6CPVeGg6tEPzAxLwyI+P78cP4u9lNO9OoMKnLMOobG5020/yaj/MrRcCGh1gBbyiLTPJEYaIiom5KM9Jq7KgynMGtb6L4GL4MF2H4LQKCXTvDVw2I4MsgZT7QLExdiutH+D08VOP3INXRrWX1/mmpbkNgAPYRVANb4xpcegYvhiNbIXauQICEjBuYLfMakaakWQeXxiZ0VDtuJCKs3ztMV59QtsHJNcRxDzfdL21ty3PrfIcXTN+E+GFAv6T5nbT9jd50/WFxb5ksdAv49qS6ouymG66ji08UMT6moykYLAo+V0j23GN4m829ZySAD5K7QsBfQTvOG8eE+gTeGYRAmnNAubN3hf5Zv9tJWDHp/VTuaSm7SN4fyINQqaNO3RMVxvpSPXnOChnRNvFcGY0gnwiPswYwTKVPE0zVtX3mTEIOoFzaqLrGuJaV+Uqumb71fVk/VoOH3cdLNQP/FHi8hV0CQNoqBZsUPlLPMsdCJro9QAaQQ0woDy9BJm0eTxCFnO9srcYlhNVlfR2EyTrph1uUtbUtAJifwRgrKuYdXVHeb0YI3QpawohQHkloI3J5FuVwI5ORxC9k2Tuz9Ir1IjgeIPGMHYkAZe2RuYkmWFmt3gGbTPOmBUWVTmRmHtGrfpzG/yuQNOKa6gBB/WA9khitPgl6/GP+gl2Af6tCbvaygAAAABJRU5ErkJggg=="});let e=T(),n=T(8),s=1,i=0,r=new Zt(t),a=new Gt(e,n,r,s,i);vl=new Ii(a)}function qf(t=!0){is=t}function Wf(t){ma=t}function Hf(){return hn==="mouse"}function $f(){return hn==="keyboard"}function Yf(){return hn==="gamepad"}function ya(t,e=0,n=!0,s=!0,i=!0){re[e]&&(re[e][t]&=~((n?1:0)|(s?2:0)|(i?4:0)))}function ai(){re.length=0,re[0]=[],mt.length=0,Jn.length=0,ci.length=0,Pt.length=0,Rn.length=0}function Je(t,e=0){var n;return m(te(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=re[e])==null?void 0:n[t])&1)}function Ve(t,e=0){var n;return m(te(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=re[e])==null?void 0:n[t])&2)}function ga(t,e=0){var n;return m(te(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=re[e])==null?void 0:n[t])&4)}function Xf(t="ArrowUp",e="ArrowDown",n="ArrowLeft",s="ArrowRight"){m(te(t),"up key must be a string"),m(te(e),"down key must be a string"),m(te(n),"left key must be a string"),m(te(s),"right key must be a string");let i=r=>Je(r)?1:0;return T(i(s)-i(n),i(t)-i(e))}function Is(t){return m(I(t),"mouse button must be a number"),Je(t)}function Js(t){return m(I(t),"mouse button must be a number"),Ve(t)}function Kf(t){return m(I(t),"mouse button must be a number"),ga(t)}function zt(t,e=Ce){return m(I(t),"button must be a number"),m(I(e),"gamepad must be a number"),Je(t,e+1)}function ba(t,e=Ce){return m(I(t),"button must be a number"),m(I(e),"gamepad must be a number"),Ve(t,e+1)}function Qf(t,e=Ce){return m(I(t),"button must be a number"),m(I(e),"gamepad must be a number"),ga(t,e+1)}function Ns(t,e=Ce){var n,s;return m(I(t),"stick must be a number"),m(I(e),"gamepad must be a number"),(s=(n=Pt[e])==null?void 0:n[t])!=null?s:T()}function cr(t=Ce){var e;return m(I(t),"gamepad must be a number"),(e=Rn[t])!=null?e:T()}function lr(t=Ce){return m(I(t),"gamepad must be a number"),!!re[t+1]}function wl(t=Ce){var e,n;return m(I(t),"gamepad must be a number"),(n=(e=Pt[t])==null?void 0:e.length)!=null?n:0}function Zf(t=Ce,e=200,n=1,s=1,i=0){var a,o,c;if(m(I(t),"gamepad must be a number"),!si||Y)return;let r=(a=navigator==null?void 0:navigator.getGamepads)==null?void 0:a.call(navigator)[t];(c=(o=r==null?void 0:r.vibrationActuator)==null?void 0:o.playEffect)==null||c.call(o,"dual-rumble",{duration:e,strongMagnitude:n,weakMagnitude:s,startDelay:i})}function eh(t=Ce){var n,s,i;if(m(I(t),"gamepad must be a number"),!si||Y)return;let e=(n=navigator==null?void 0:navigator.getGamepads)==null?void 0:n.call(navigator)[t];(i=(s=e==null?void 0:e.vibrationActuator)==null?void 0:s.reset)==null||i.call(s)}function xa(t=100){var e;m(I(t)||wt(t),"pattern must be a number or array"),si&&!Y&&((e=navigator==null?void 0:navigator.vibrate)==null||e.call(navigator,t))}function th(){xa(0)}function nh(){var t;!pt&&((t=H.requestPointerLock)==null||t.call(H))}function sh(){var t;(t=document.exitPointerLock)==null||t.call(document)}function Tl(){return document.pointerLockElement===H}function ih(){if(Y)return;document.addEventListener("keydown",t),document.addEventListener("keyup",e),document.addEventListener("mousedown",s),document.addEventListener("mouseup",i),document.addEventListener("mousemove",r),document.addEventListener("mouseleave",a),document.addEventListener("wheel",o,{passive:!1}),document.addEventListener("contextmenu",c),document.addEventListener("blur",l),pt&&Ln&&u();function t(d){if(d.repeat||(re[0][d.code]=3,Ls&&(re[0][n(d.code)]=3)),!is||!d.cancelable||!document.hasFocus()||d.ctrlKey||d.metaKey||d.altKey||y(d.target)||y(document.activeElement))return;let f=typeof d.key=="string"&&d.key.length===1;(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Space","Tab","Backspace"].includes(d.code)||f)&&d.preventDefault();function y(x){let w=x==null?void 0:x.tagName;return(x==null?void 0:x.isContentEditable)||["INPUT","TEXTAREA","SELECT"].includes(w)}}function e(d){re[0][d.code]=re[0][d.code]&2|4,Ls&&(re[0][n(d.code)]=4)}function n(d){return Ls?d==="KeyW"?"ArrowUp":d==="KeyS"?"ArrowDown":d==="KeyA"?"ArrowLeft":d==="KeyD"?"ArrowRight":d:d}function s(d){if(pt&&Ln)return;it&&!Y&&Ae&&!Us()&&Ae.resume(),re[0][d.button]=3;let f=Ze;Ze=h(T(d.x,d.y)),Et=Et.add(Ze.subtract(f)),is&&d.cancelable&&document.hasFocus()&&d.preventDefault()}function i(d){pt&&Ln||(re[0][d.button]=re[0][d.button]&2|4)}function r(d){Di=!0;let f=Ze;Ze=h(T(d.x,d.y));let p=Tl()?T(d.movementX,d.movementY):Ze.subtract(f);Et=Et.add(p)}function a(){Di=!1}function o(d){d.ctrlKey||(pa+=ft(d.deltaY)),is&&d.cancelable&&document.hasFocus()&&d.preventDefault()}function c(d){d.preventDefault()}function l(){ai(),$t.clear(),mt.length=0,Jn.length=0,ci.length=0}function u(){document.addEventListener("touchstart",p=>f(p),{passive:!1}),document.addEventListener("touchmove",p=>f(p),{passive:!1}),document.addEventListener("touchend",p=>f(p),{passive:!1});let d;function f(p){if(Ln){if(it&&!Y&&Ae&&!Us()&&Ae.resume(),!vn||aa){let y=v=>zs.includes(v.target)||v.target===Mn,x=[];for(let v of p.touches)y(v)||x.push(v);let w=x.length,A=0;if(w){let v=T(x[0].clientX,x[0].clientY),_=Ze;Ze=h(v),d?Et=Et.add(Ze.subtract(_)):re[0][A]=3}else d&&(re[0][A]=re[0][A]&2|4);d=w}return is&&p.cancelable&&document.hasFocus()&&p.preventDefault(),!0}}}function h(d){let f=H.getBoundingClientRect(),p=He(d.x,f.left,f.right),y=He(d.y,f.top,f.bottom);return T(p*H.width,y*H.height)}}function Gc(){if(Y)return;!(Ln&&pt)&&!document.hasFocus()&&ai(),Nt=oi(Ze),ha=bl(Et),rh(),e(),t();function t(){let n=Is(0)||Is(1)||Is(2)||Et.length()>ma,s=!1;for(let r=wl();r--&&!s;)s=Ns(r).lengthSquared()>.04;for(let r=17;r--&&!s;)s=zt(r);let i=!1;for(let r in re[0])if(isNaN(+r)&&re[0][r]&1){i=!0;break}s?hn="gamepad":n?hn="mouse":i&&(hn="keyboard"),rs=hn==="gamepad"}function e(){var a,o,c,l,u,h,d;let n=f=>{let x=w=>w>.3?He(w,.3,.8):w<-.3?-He(-w,.3,.8):0;return T(x(f.x),x(-f.y)).clampLength()};if(vn&&pt){if(m(!Un||!gs,"set touchGamepadLeftStick or touchGamepadLeftButtonCount, not both"),m(!bs||!ys,"set touchGamepadRightStick or touchGamepadButtonCount, not both"),!ds.isSet())return;Ce=0;let f=(a=Pt[0])!=null?a:Pt[0]=[],p=(o=Rn[0])!=null?o:Rn[0]=T();f.length=0,p.set();for(let x=0;x<2;x++){if(!en(x))continue;let w=wa(x);f[w]=T();let A=(c=Jn[x])!=null?c:T();if(ni)f[w]=n(A);else if(A.lengthSquared()>.3){let v=$(Ci(A.x),-1,1),_=$(Ci(A.y),-1,1);f[w]=T(v,-_).clampLength(),w||p.set(v,-_)}}let y=(l=re[1])!=null?l:re[1]=[];for(let x=12;x--;){let w=zt(x,0);y[x]=mt[x]?w?1:3:w?4:0,Ri&&y[x]===3&&(x===9||ah(x))&&xa(Ri)}return}try{if(!uo||!(navigator!=null&&navigator.getGamepads))return}catch{return}if(!We&&!document.hasFocus())return;let s=8,i=navigator.getGamepads(),r=de(s,i.length);for(let f=0;f>1]=n(T(p.axes[v],p.axes[v+1]));let A=!1;for(let v=p.buttons.length;v--;){let _=p.buttons[v],k=zt(v,f);y[v]=_.pressed?k?1:3:k?4:0,_.pressed&&(!_.value||_.value>.9)&&(A=!0)}A&&(Zo[f]=!0,Zo[Ce]||(Ce=f)),p.mapping==="standard"&&w.set((zt(15,f)&&1)-(zt(14,f)&&1),(zt(12,f)&&1)-(zt(13,f)&&1)),ra&&(w.x||w.y)&&(x[0]=w.clampLength())}vn&&rs&&ds.unset()}}function Bc(){if(!Y){for(let t of re)for(let e in t)t[e]&=1;pa=0,ha=T(),Et=T()}}function oh(){dh()}function rh(){if(un||!vn||!pt||Y||!document.body)return;let t=un=document.createElement("div");t.style.cssText="position:fixed;inset:0;z-index:50;pointer-events:none;opacity:0;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;transition:opacity .2s;box-sizing:border-box;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)";let e=Al=document.createElement("div");e.style.cssText="position:relative;width:100%;height:100%;pointer-events:none",t.appendChild(e);let n=Sa=document.createElementNS(Gi,"svg");n.style.cssText="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible;fill:none;stroke:#fff;stroke-width:3",e.appendChild(n);let s=()=>{let i=document.createElement("div");return i.style.cssText="position:absolute;pointer-events:auto;touch-action:none",i.addEventListener("pointerdown",r=>mh(r,i)),i.addEventListener("pointermove",r=>yh(r)),i.addEventListener("pointerup",r=>jc(r)),i.addEventListener("pointercancel",r=>jc(r)),e.appendChild(i),i};zs[0]=s(),zs[1]=s(),Mn=s(),addEventListener("resize",()=>fs=!0),document.body.appendChild(t),fs=!0}function fo(){return Al.getBoundingClientRect()}function en(t){return t?bs:Un}function Wn(t){return t?ys:gs}function va(t){return t?0:4}function wa(t){return t&&Un?1:0}function hs(t){return en(t)||Wn(t)>0}function ah(t){for(let e=0;e<2;e++){let n=va(e);if(!en(e)&&t>=n&&tr.style.cssText="position:absolute;pointer-events:auto;touch-action:none;"+a;if(Ot){for(let r of zs)r.style.display="none";Tt?(i(Mn,"inset:0"),Mn.style.display=""):Mn.style.display="none"}else{for(let a=0;a<2;a++){let o=zs[a],c=a?"right":"left";if(o.style.display=hs(a)?"":"none",Tn){let l=hs(a?0:1)?"50%":"100%";i(o,`${c}:0;bottom:0;width:${l};height:60%`)}else i(o,`${c}:0;bottom:0;width:${3*s}px;height:${3*s}px`)}Mn.style.display=Tt?"":"none";let r=Tt;i(Mn,`left:50%;top:50%;width:${2*r}px;height:${2*r}px;transform:translate(-50%,-50%)`)}lh(e,n),fs=!1}function lh(t,e){let n=Sa;for(;n.firstChild;)n.removeChild(n.firstChild);let s=kl={face:[],thumb:[]},i=st,r=(o,c,l,u)=>{let h=document.createElementNS(Gi,"circle");return h.setAttribute("cx",o),h.setAttribute("cy",c),h.setAttribute("r",l),u&&h.setAttribute("fill",u),n.appendChild(h),h},a=o=>{let c=i*.18,l=i*.5,u=o.x,h=o.y,d=document.createElementNS(Gi,"path");d.setAttribute("d",`M ${u-c} ${h-l} H ${u+c} V ${h-c} H ${u+l} V ${h+c} H ${u+c} V ${h+l} H ${u-c} V ${h+c} H ${u-l} V ${h-c} H ${u-c} Z`),n.appendChild(d)};for(let o=0;o<2;o++){let c=Wn(o),l=va(o),u=Xt(o,t,e);if(en(o))ni?r(u.x,u.y,i/2):a(u),s.thumb[o]=r(u.x,u.y,i/4,"#fff");else if(c===1)s.face[l]=r(u.x,u.y,i/2,"#000");else for(let h=0;h2?d:de(d,c-1);f=f===3?2:f===2?3:f;let p=T().setDirection(d,i/2);c===2&&(p.x*=-1),o||(p.x*=-1);let y=u.add(p);s.face[l+f]=r(y.x,y.y,i/4,"#000")}}We&&Fn&&uh(t,e)}function uh(t,e){let n=st,s=Sa,i=(a,o,c)=>{let l=document.createElementNS(Gi,a);for(let u in o)l.setAttribute(u,o[u]);l.setAttribute("stroke",c),l.setAttribute("stroke-width",2),l.setAttribute("fill","none"),s.appendChild(l)},r=(a,o,c)=>i("circle",{cx:a.x,cy:a.y,r:o},c);i("line",{x1:t/2,y1:0,x2:t/2,y2:e},"#0f0");for(let a=0;a<2;a++)if(en(a))if(Tn){let o=e*.4,c=!hs(a?0:1),l=c?0:a?t/2:0;i("rect",{x:l,y:o,width:c?t:t/2,height:e-o},"#0ff")}else r(Xt(a,t,e),2*n,"#0ff");else Wn(a)>=1&&r(Xt(a,t,e),n,"#0ff");if(Tt){r(T(t/2,e/2),Tt,"#ff0");for(let a=0;a<2;a++)hs(a)&&r(Xt(a,t,e),2*n,"#f0f")}}function dh(){var l;if(!un||Y)return;if(!vn||!pt){un.style.display!=="none"&&(un.style.display="none",$t.clear(),mt.length=0,Jn.length=0,ci.length=0);return}un.style.display="";let t=We&&Fn,e=[ys,gs,Un,bs,ni,st,Tn,Tt,Ot,t].join();e!==Fc&&(Fc=e,fs=!0),fs&&ch();let n=Os?He(ds.get(),Os+1,Os):1,s=t||ds.isSet()&&n>0&&!Ot;if(un.style.opacity=s?t?1:n*ca:0,!s)return;let i=fo(),r=i.width,a=i.height,o=st,c=kl;if(c){for(let u=0;u<2;u++)if(en(u)&&c.thumb[u]){let d=Xt(u,r,a).add(((l=Jn[u])!=null?l:T()).scale(o/2));c.thumb[u].setAttribute("cx",d.x),c.thumb[u].setAttribute("cy",d.y)}for(let u=0;u=st)return-1;if(i===1)return r;let o=a.subtract(e);t||(o.x*=-1);let c=i===2?o.xr:o&&Xt(a,e,n).distance(t)<2*s)return{role:"stick",side:a}}else if(Wn(a)>=1){let c=hh(a,t,e,n);if(c>=0)return{role:"face",btn:c}}}if(Tt){for(let a=0;a<2;a++)if(hs(a)&&Xt(a,e,n).distance(t)<2*s)return;if(T(e/2,n/2).distance(t)h.getChannelData(x).set(y)),d.buffer=h,d.playbackRate.value=n,d.loop=i,a=a||Ae.createGain(),a.gain.value=e,a.connect(Kt);let f=new StereoPannerNode(Ae,{pan:$(s,-1,1)});d.connect(f).connect(a),d.addEventListener("ended",()=>{a.disconnect(),f.disconnect(),c&&c(d)});let p=o*n;return d.start(0,p),We&&ls&&Ee("sound","vol",e.toFixed(2),"rate",n.toFixed(2),"pan",s.toFixed(2),i?"loop":""),d}function Sh(...t){return Ta([ho(...t)])}function ho(t=1,e=.05,n=220,s=0,i=0,r=.1,a=0,o=1,c=0,l=0,u=0,h=0,d=0,f=0,p=0,y=0,x=0,w=1,A=0,v=0,_=0){let k=xs,C=oe*2,L=c*=500*C/k/k,V=n*=(1+Te(e,-e))*C/k,ae=0,O=0,S=0,P=1,R,M=[],j=0,X=0,ee=0,K,xe=2,je=C*he(_)*2/k,ve=be(je),Bt=pe(je)/2/xe,dt=1+Bt,gt=-2*ve/dt,$n=(1-Bt)/dt,jt=(1+ft(_)*ve)/2/dt,Yn=-(ft(_)+ve)/dt,Ss=jt,tn=0,nn=0,sn=0,Xn=0;for(s=s*k||9,A*=k,i*=k,r*=k,x*=k,l*=500*C/k**3,p*=C/k,u*=C/k,h*=k,d=d*k|0,R=s+A+i+r+x|0;X1?a>2?a>3?a>4?j/C%14?ee:ft(ee)*he(ee)**o)*(XX?0:(Xh&&(n+=u,V+=u,P=0),d&&!(++O%d)&&(n=V,c=L,P||(P=1));return M}function ji(t,e=!0){for(let n of bn)if((!e||n.isSolid)&&t.arrayCheck(n.size)){let s=n.getCollisionData(t);if(s)return s}return 0}function dn(t,e=T(),n,s=!0){for(let i of bn)if((!s||i.isSolid)&&i.collisionTest(t,e,n))return i}function El(t,e,n,s,i=!0){let r,a,o,c=s&&T();for(let l of bn)if(!i||l.isSolid){let u=l.collisionRaycast(t,e,n,c);if(u){let h=t.distanceSquared(u);(r===void 0||h{W=!1,fe.style.display="none",n.preventDefault(),Ee("WebGL context lost! Switching to Canvas2d rendering.");for(let s of Ds)s.glTexture=void 0;lt=void 0,Fe=0,Nn=!1,In.forEach(s=>{var i;return(i=s.glContextLost)==null?void 0:i.call(s)})}),fe.addEventListener("webglcontextrestored",()=>{W=!0,fe.style.display="",Ee("WebGL context restored, reinitializing..."),e();for(let n of Ds)n.glTexture=mo(n.image,n.wrap);In.forEach(n=>{var s;return(s=n.glContextRestored)==null?void 0:s.call(n)})});function e(){zi=ms(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 g;in vec4 p,u,c,a;in float r;out vec2 v;out vec4 d,e;void main(){vec2 s=(g-.5)*p.zw;gl_Position=m*vec4(p.xy+s*cos(r)-vec2(-s.y,s)*sin(r),1,1);v=mix(u.xw,u.zy,g);d=c;e=a;}`,`#version 300 es
+precision highp float;uniform sampler2D s;in vec2 v;in vec4 d,e;out vec4 c;void main(){c=texture(s,v)*d+e;}`),Ui=ms(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 p;in vec4 c;out vec4 d;void main(){gl_Position=m*vec4(p,1,1);d=c;}`,`#version 300 es
+precision highp float;in vec4 d;out vec4 c;void main(){c=d;}`);let n=new ArrayBuffer(qi);qe=new Float32Array(n),Hs=new Uint32Array(n),dr=g.createBuffer(),as=g.createBuffer(),ka=g.createFramebuffer(),Fe=0;let s=new Float32Array([0,0,1,0,0,1,1,1]);g.bindBuffer(g.ARRAY_BUFFER,as),g.bufferData(g.ARRAY_BUFFER,s,g.STATIC_DRAW);let i,r,a,o=(c,l,u,h,d=0)=>{let f=g.getAttribLocation(r,c),p=u===1,y=u&&a;g.enableVertexAttribArray(f),g.vertexAttribPointer(f,h,l,p,y,i),g.vertexAttribDivisor(f,d),i+=h*u};fr=g.createVertexArray(),g.bindVertexArray(fr),i=0,r=zi,a=Pl,g.bindBuffer(g.ARRAY_BUFFER,as),o("g",g.FLOAT,0,2),g.bindBuffer(g.ARRAY_BUFFER,dr),g.bufferData(g.ARRAY_BUFFER,qi,g.DYNAMIC_DRAW),o("p",g.FLOAT,4,4,1),o("u",g.FLOAT,4,4,1),o("c",g.UNSIGNED_BYTE,1,4,1),o("a",g.UNSIGNED_BYTE,1,4,1),o("r",g.FLOAT,4,1,1),hr=g.createVertexArray(),g.bindVertexArray(hr),i=0,r=Ui,a=Rl,o("p",g.FLOAT,4,2),o("c",g.UNSIGNED_BYTE,1,4)}}function $s(t=!1){!t&&!Nn||(Be(),Nn=!1,g.useProgram(zi),g.bindVertexArray(fr))}function Ml(){Nn||(Be(),Nn=!0,g.useProgram(Ui),g.bindVertexArray(hr))}function mr(t=!0){if(!W||!g)return;m(!Fe,"glPreRender called with unflushed batch."),Vi||(fe.width=z.x,fe.height=z.y),g.viewport(0,0,z.x,z.y),t&&Ll();let e=T(2*ie).divide(z);Vi&&(e.y=-e.y);let n=Ge.rotate(-ue),s=T(-1).subtract(n.multiply(e)),i=be(ue),r=pe(ue),a=[e.x*i,e.y*r,0,0,-e.x*r,e.y*i,0,0,1,1,1,0,s.x,s.y,0,1],o=(c,l,u)=>{g.useProgram(c);let h=g.getUniformLocation(c,l);g.uniformMatrix4fv(h,!1,u)};o(Ui,"m",a),o(zi,"m",a),g.activeTexture(g.TEXTURE0),wn[0]&&(lt=wn[0].glTexture,g.bindTexture(g.TEXTURE_2D,lt)),g.bindBuffer(g.ARRAY_BUFFER,dr),Hn=ps=!1,$s(!0)}function Ll(){if(!g)return;let t=mn;g.clearColor(t.r,t.g,t.b,t.a),g.clear(g.COLOR_BUFFER_BIT)}function _a(t){!g||t===lt||(Be(),lt=t,g.bindTexture(g.TEXTURE_2D,lt))}function Ol(t,e=!0){if(!g||!t)return;let n=t===lt;n?Be():g.bindTexture(g.TEXTURE_2D,t);let s=e?g.REPEAT:g.CLAMP_TO_EDGE;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,s),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,s),!n&<&&g.bindTexture(g.TEXTURE_2D,lt)}function yr(t,e){if(!g)return;let n=g.createShader(e);if(g.shaderSource(n,t),g.compileShader(n),We&&!g.getShaderParameter(n,g.COMPILE_STATUS))throw g.getShaderInfoLog(n);return n}function ms(t,e){if(!g)return;let n=g.createProgram();if(g.attachShader(n,yr(t,g.VERTEX_SHADER)),g.attachShader(n,yr(e,g.FRAGMENT_SHADER)),g.linkProgram(n),We&&!g.getProgramParameter(n,g.LINK_STATUS))throw g.getProgramInfoLog(n);return n}function mo(t,e=!1){if(!g)return;let n=g.createTexture(),s=!1;if(t!=null&&t.width)Ea(n,t),g.bindTexture(g.TEXTURE_2D,n),s=!jn&&Gs(t.width)&&Gs(t.height);else{let o=new Uint8Array([255,255,255,255]);g.bindTexture(g.TEXTURE_2D,n),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,1,1,0,g.RGBA,g.UNSIGNED_BYTE,o)}let i=jn?g.NEAREST:g.LINEAR,r=s?g.LINEAR_MIPMAP_LINEAR:i;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,i),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,r);let a=e?g.REPEAT:g.CLAMP_TO_EDGE;return g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,a),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,a),s&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,lt),n}function Il(t){g&&g.deleteTexture(t)}function Ea(t,e){g&&(m((e==null?void 0:e.width)>0,"Invalid image data."),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e),!jn&&Gs(e.width)&&Gs(e.height)&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,lt))}function kh(t){Y||(Ds.add(t),g&&(t.glTexture?Ea(t.glTexture,t.image):t.glTexture=mo(t.image,t.wrap)))}function Ch(t){if(Y)return;Ds.delete(t);let e=t.glTexture;t.glTexture=void 0,Il(e)}function Be(){if(W&&g&&Fe){let t=ps?g.ONE:g.ONE_MINUS_SRC_ALPHA;g.blendFuncSeparate(g.SRC_ALPHA,t,g.ONE,t),g.enable(g.BLEND);let e=Fe*(Nn?po:Ca);g.bufferSubData(g.ARRAY_BUFFER,0,qe,0,e),Nn?g.drawArrays(g.TRIANGLE_STRIP,0,Fe):g.drawArraysInstanced(g.TRIANGLE_STRIP,0,4,Fe),++Dt,Ft+=Fe,Fe=0}ps=Hn}function Pa(t){!W||!g||(Be(),t.drawImage(fe,0,0))}function _h(t=!0){m(!fe,"must be called before engineInit"),Aa=t}function Ys(t,e,n,s,i=0,r=0,a=0,o=1,c=1,l=-1,u=0){(Fe>=Th||ps!==Hn)&&Be(),$s();let h=Fe++*Ca;qe[h++]=t,qe[h++]=e,qe[h++]=n,qe[h++]=s,qe[h++]=r,qe[h++]=a,qe[h++]=o,qe[h++]=c,Hs[h++]=l,Hs[h++]=u,qe[h++]=i}function Dl(t,e,n,s,i,r){Ys(t,e,n,s,i,0,0,0,0,0,r)}function Ra(t,e,n,s,i,r,a,o=!0){let c=[],l=pe(-a),u=be(-a);for(let d of t){let f=d.x*i,p=d.y*r;c.push(T(n+u*f-l*p,s+l*f+u*p))}let h=o?Ph(c):c;Fl(h,e)}function Ma(t,e,n,s,i,r,a,o,c=!0){let l=Eh(t,n,c);Ra(l,e,s,i,r,a,o,!1)}function Fl(t,e){if(!W||t.length<3)return;let n=t.length+2;if((Fe+n>=cs||ps!==Hn)&&Be(),m(n=cs)return;Ml();let s=Fe*po;for(let i=n;i--;){let r=$(i-1,0,n-3),a=t[r];qe[s++]=a.x,qe[s++]=a.y,Hs[s++]=e}Fe+=n}function La(t,e){if(!W||t.length<3)return;let n=t.length+2;if((Fe+n>=cs||ps!==Hn)&&Be(),m(n=cs)return;Ml();let s=Fe*po;for(let i=n;i--;){let r=$(i-1,0,n-3),a=t[r],o=e[r];qe[s++]=a.x,qe[s++]=a.y,Hs[s++]=o}Fe+=n}function Rs(t,e=!1){t?(Vi=t,g.bindFramebuffer(g.FRAMEBUFFER,ka),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,t,0),mr(e)):(Be(),Vi=void 0,g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,z.x,z.y))}function Gl(t,e,n,s){W&&(g.enable(g.SCISSOR_TEST),g.scissor(t,e,n,s),g.clearColor(0,0,0,0),g.clear(g.COLOR_BUFFER_BIT),g.disable(g.SCISSOR_TEST))}function Eh(t,e,n=!0){if(t.length<2)return[];let s=e/2,i=[],r=t.length,a=1e-6,o=10;for(let c=0;ca?-f/p:0,v=p>a?d/p:0,_=w>a?-x/w:0,k=w>a?y/w:0,C=A+_,L=v+k,V=(C*C+L*L)**.5;if(Va){let P=de(1/S,o);C*=P,L*=P}}let ae=T(u.x-C*s,u.y-L*s),O=T(u.x+C*s,u.y+L*s);i.push(ae),i.push(O)}return i.length>1&&n&&(i.push(i[0]),i.push(i[1])),i}function Ph(t){if(t.length<3)return[];let e=(f,p,y)=>(p.x-f.x)*(y.y-f.y)-(p.y-f.y)*(y.x-f.x);(f=>{let p=0;for(let y=f.length;y--;){let x=(y+1)%f.length;p+=f[y].cross(f[x])}return p})(t)<0&&(t=t.slice().reverse());let s=1e-9,i=(f,p,y,x)=>{let w=e(p,y,f),A=e(y,x,f),v=e(x,p,f),_=(w<-s?1:0)+(A<-s?1:0)+(v<-s?1:0),k=(w>s?1:0)+(A>s?1:0)+(v>s?1:0);return!(_&&k)},r=[];for(let f=0;f3&&o++{if(_>=0){let C=s.fillStyle=s.createLinearGradient(x,w,A,v);C.addColorStop(0,h(_,2)),C.addColorStop(1,h(_,1))}else s.fillStyle="#000";_>=-1?(s.fill(),k&&s.stroke()):s.stroke()},c=(x,w,A,v=0,_=2*oe,k,C)=>{s.beginPath(),s.arc(x,w,A,f*v,f*_),o(x,w-A,x,w+A,k,C)},l=(x,w,A,v,_)=>{s.beginPath(),s.rect(x,w,A,v*f),o(x,w+v,x+A,w,_)},u=(x,w,A,v)=>{s.beginPath();for(let _ of x)s.lineTo(_.x,_.y);s.closePath(),o(0,A,0,A+v,w)},h=(x,w)=>w?`hsl(${[.95,.56,.13][x%3]*360} 99%${[0,50,75][w]}%)`:"#000",d=sl(1,1,t),f=He(d,.1,.5),p=de(6,de(r,a)/99);s.translate(r/2,a/2),s.scale(p,p),s.translate(-40,-35),f<1&&s.setLineDash([99*f,99]),s.lineJoin=s.lineCap="round",s.lineWidth=.1+f*1.9;{let w="LittleJS";s.font="900 15.5px arial",s.lineWidth=.1+f*3.9,s.textAlign="center",s.textBaseline="top",l(11,55,59,8*f,-1),s.beginPath();let A=0;for(let v=0;v5?1:0),s[v?"strokeText":"fillText"](w[_],L,54+.5,17*f),k+=C}s.lineWidth=.1+f*1.9,l(3,54,73,0)}l(7,15,26,-7,0),l(25,15,8,25,-1),l(10,40,15,-25,1),l(14,21,7,9,2),l(38,20,6,-6,2),l(49,20,10,-6,0);let y=[T(44,8),T(64,8),T(59,8+6*f),T(49,8+6*f)];u(y,2,8,6*f),l(44,8,20,-7,0);for(let x=5;x--;)c(59-x*6*f,30,10,0,2*oe,1,0);c(59,30,4,0,7,2),l(35,20,24,0),c(59,30,10),c(47,30,10,oe/2,oe*3/2),c(35,30,10,oe/2,oe*3/2),l(7,40,13,7,-1),l(17,40,43,14,-1);for(let x=3;x--;)for(let w=2;w--;)c(17+15*x,47,w?7:1,0,2*oe,2);for(let x=2;x--;){let w=6,A=7,v=53+w*f*x,_=[T(v+A,54),T(v,40),T(v+w*f,40),T(v+A+w*f,54)];u(_,0,40,14)}s.restore()}function Mh(t){if($i=t,!Pn){let n={};try{n=JSON.parse(localStorage[t]||"{}")}catch{n={}}yo(s=>{s.unlocked=!!(n[s.id]&&n[s.id].unlocked)}),Ia()}zn(void 0,e);function e(){if(!wi.length)return;let n=wi[0],s=xn-vi;if(!vi)vi=xn;else if(s>Wi)vi=0,wi.shift();else{let i=Wi-os,r=si?(s-i)/os:0;n.render(r)}}}function yo(t){Object.values(Xs).forEach(e=>t(e))}function Lh(){yo(t=>t.unlocked=!1),Ia()}function Ia(){if(!$i)return;let t={};yo(e=>{let n={name:e.name,description:e.description,icon:e.icon,unlocked:e.unlocked};e.image&&(n.src=e.image.src),t[e.id]=n}),localStorage[$i]=JSON.stringify(t)}function Oh(t){Wi=t}function Ih(t){os=t}function Dh(t){Hi=t.copy()}function Fh(t){Oa=t}function Bl(t,e,n,s=125){let i,r,a,o,c,l,u,h,d,f,p,y,x,w=0,A,v=[],_=[],k=[],C=0,L=0,V=1,ae={},O=xs/s*60>>2;for(;V;C++)v=[V=h=y=0],n.forEach((S,P)=>{for(u=e[S][C]||[0,0,0],V|=e[S][C]&&1,A=y+(e[S][0].length-2-(h?0:1))*O,x=P===n.length-1,i=2,a=y;iO-99&&d&&p<1?p+=1/99:0)l=(1-p)*v[w++]/2||0,_[a]=(_[a]||0)-l*L+l,k[a]=(k[a++]||0)+l*L+l;c&&(p=c%1,L=u[1]||0,(c|=0)&&(v=ae[[f=u[w=0]||0,c]]=ae[[f,c]]||(o=[...t[f]],o[2]=(o[2]||220)*2**(c/12-1),c>0?ho(...o):[])))}y=A});return[_,k]}function Gh(t){Da=typeof t=="boolean"?t?1:0:t}function Bh(t){Fa=t}async function jh(){return new eo(await Box2D()),n(),zn(t,e),b;function t(){if(!Ot){b.step(),b.objects=b.objects.filter(s=>!s.destroyed);for(let s of b.objects)s.body&&(s.pos=b.vec2From(s.body.GetPosition()),s.angle=-s.body.GetAngle())}}function e(){(Fa||St)&&b.world.DrawDebugData()}function n(){let i=new b.instance.JSDraw,r=l=>new Oe(l.get_r(),l.get_g(),l.get_b()),a=l=>r(b.instance.wrapPointer(l,b.instance.b2Color)),o=l=>a(l).scale(1,.8),c=(l,u)=>{let h=[];for(let d=u;d--;)h.push(b.vec2FromPointer(l+d*8));return h};i.DrawSegment=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),u=b.vec2FromPointer(u),On(l,u,.1,h,T(),0,!1)},i.DrawPolygon=function(l,u,h){h=o(h);let d=c(l,u);us(d,Sn,.1,h,T(),0,!1)},i.DrawSolidPolygon=function(l,u,h){h=o(h);let d=c(l,u);us(d,h,0,h,T(),0,!1)},i.DrawCircle=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),Oi(l,u*2,Sn,.1,h,!1)},i.DrawSolidCircle=function(l,u,h,d){d=o(d),l=b.vec2FromPointer(l),h=b.vec2FromPointer(h).scale(u),Oi(l,u*2,d,.1,d,!1),On(T(),h,.1,d,l,0,!1)},i.DrawTransform=function(l){l=b.instance.wrapPointer(l,b.instance.b2Transform);let u=b.vec2From(l.get_p()),h=-l.get_q().GetAngle(),d=T(1,0),f=Q(.75,0,0,.8),p=T(0,1),y=Q(0,.75,0,.8);On(T(),d,.1,f,u,h,!1),On(T(),p,.1,y,u,h,!1)},i.AppendFlags(b.instance.b2Draw.e_shapeBit),i.AppendFlags(b.instance.b2Draw.e_jointBit),b.world.SetDebugDraw(i)}}function Jh(t,e,n,s=32,i=2,r=0){jl(t,e,n,ne,s,me,i,r,!1,!0)}function jl(t,e,n,s,i=1,r,a=.05,o=0,c=W,l,u){let h=n.offset(n.size),d=e.add(T(a-i*2)),f=T(i),p=e.scale(.5).subtract(f.scale(.5)),y=l?-1:1,x=l?-o:o;Ne(t,d,h,s,o,!1,r,c,l,u);for(let w=4;w--;){let A=w%2,v=p.multiply(T(A?w===1?1:-1:0,A?0:w?-1:1)),_=T(A?i:d.x,A?d.y:i),k=h.offset(n.size.multiply(T(w===1?1:w===3?-1:0,w===0?-y:w===2?y:0)));Ne(t.add(v.rotate(x)),_,k,s,o,!1,r,c,l,u)}for(let w=4;w--;){let A=w>1,v=w&&w<3,_=p.multiply(T(A?-1:1,v?-1:1)),k=h.offset(n.size.multiply(T(A?-1:1,v?y:-y)));Ne(t.add(_.rotate(x)),f,k,s,o,!1,r,c,l,u)}}function Nh(t,e,n,s=32,i=2,r=0){Jl(t,e,n,ne,s,me,i,r,!1,!0)}function Jl(t,e,n,s,i=1,r,a=.05,o=0,c=W,l,u){let h=n.frame(0),d=n.frame(1),f=n.frame(2),p=e.add(T(a-i*2)),y=T(i),x=e.scale(.5).subtract(y.scale(.5)),w=l?-1:1,A=l?-o:o;Ne(t,p,f,s,o,!1,r,c,l,u);for(let v=4;v--;){let _=o+v*oe/2,k=v%2,C=x.multiply(T(k?v===1?1:-1:0,k?0:v?-w:w)),L=T(k?p.y:p.x,i);Ne(t.add(C.rotate(A)),L,d,s,_,!1,r,c,l,u)}for(let v=4;v--;){let _=o+v*oe/2,k=!v||v>2,C=v>1,L=x.multiply(T(k?-1:1,C?-w:w));Ne(t.add(L.rotate(A)),y,h,s,_,!1,r,c,l,u)}}function zh(t,e=1,n=0,s=ne,i=0,r=!1,a=0,o=me,c=W,l=!1,u){let h=Nl(T(),e,n,0,r);us(h,s,a,o,t,i,c,l,u)}function Nl(t,e=1,n=0,s=0,i=!1,r=ti){m(D(t),"pos must be a vec2"),m(I(e)&&I(n),"size and percent must be numbers");let a=ht(n*4,4);a>=2&&(s+=oe),a=a<=2?a-1:3-a,i&&(a=-a,s+=oe);let o=[],c=le(3,r>>1),l=e/2;for(let u=0;u<=c;u++){let h=u/c*oe;o.push(T(l*be(h),l*pe(h)).rotate(s).add(t))}for(let u=c;u>=0;u--){let h=u/c*oe;o.push(T(l*be(h),-l*a*pe(h)).rotate(s).add(t))}return o}function zc(t){return t&&typeof t.lerp=="function"}function Uh(t,e,n,s,i=1,r={}){m(t!=null&&typeof t=="object","tweenProperty target must be an object"),m(te(e)&&e.length>0,"tweenProperty propertyPath must be a non-empty string");let a=e.split("."),o=a.pop(),c=l=>{let u=t;for(let h of a)u=u[h];u[o]=l};return new to(c,n,s,i,r)}function zl(t){t.loopRemaining!==1/0&&t.loopRemaining<=1||(t.loopRemaining!==1/0&&(t.loopRemaining-=1),t.life=t.duration,t.thenCallback=()=>zl(t),at.push(t),t.callback(t.interp(t.duration)))}function Ul(t){if(t.loopRemaining!==1/0&&t.loopRemaining<=1)return;t.loopRemaining!==1/0&&(t.loopRemaining-=1);let e=t.start;t.start=t.end,t.end=e,t.life=t.duration,t.thenCallback=()=>Ul(t),at.push(t),t.callback(t.interp(t.duration))}function Vl(t,e){t===void 0?(t=ct-Jc,e=xn-Nc,Jc=ct,Nc=xn):e===void 0&&(e=t);for(let n=at.length;n--;){let s=at[n];if(s.paused)continue;let i=s.useRealTime?e:t;if(!(i<=0))if(s.life-=i,s.life>0)s.callback(s.interp(s.life));else{s.callback(s.interp(0)),at.splice(n,1);let r=s.thenCallback;s.thenCallback=void 0,r&&r()}}}function Vh(){for(let t of at)t.thenCallback=void 0;at.length=0}var Ti,Ai,sd,Vr,Pe,qr,Uc,ct,xn,Ot,Qo,_t,ki,Vc,In,tr,We,Hc,io,$c,Ut,pn,St,vt,Dn,Fn,ls,nr,Vt,xt,oe,he,Le,Fs,Ci,de,le,ft,Qc,Zc,pe,be,el,Hr,or,ge,Oe,ne,Sn,me,At,vd,Xr,wd,ll,ul,Td,dl,fl,Ad,It,Ge,ue,ie,Qr,oo,mn,ts,Ms,ns,ss,Zr,jn,yn,ei,ea,Y,W,ti,ro,ao,co,lo,ta,na,sa,ia,oa,Wt,tt,Pi,uo,ra,Ls,Ln,vn,aa,Tt,ys,Un,gs,bs,ni,Tn,st,ca,Os,Ri,si,it,Gn,la,ua,Qt,H,Se,De,Yt,fn,Rt,Ht,z,wn,Dt,Ft,Gt,Zt,If,vl,Ii,Nt,Ze,ha,Et,pa,Di,rs,hn,ma,is,Ce,pt,re,Pt,Rn,Zo,ds,mt,Jn,Fi,ci,$t,un,Al,Sa,kl,zs,Mn,fs,Fc,Gi,Ae,Kt,xs,Vs,Bi,bn,Bn,Ji,qs,Ws,ur,wh,Ni,fe,g,Aa,zi,Ui,Nn,Hn,ps,lt,dr,as,qe,Hs,Fe,Ds,fr,hr,ka,Vi,pr,qi,Ca,Pl,Th,po,Rl,cs,Pn,Wi,os,Hi,Oa,Xs,wi,$i,vi,Yi,Ks,gr,br,Ue,xr,se,Sr,vr,wr,E,Da,Tr,yt,Xi,Ar,kr,Qs,Cr,_r,Er,Pr,b,Fa,Zs,Ki,Rr,Mr,Qi,ot,Lr,Zi,Or,Ir,Dr,Fr,Gr,Br,jr,Jr,Nr,zr,eo,at,Jc,Nc,to,no,qh,er,so,Ur,Wl=Kl(()=>{"use strict";Ti="LittleJS",Ai="1.18.19",sd=60,Vr=.016666666666666666,Pe=[],qr=[],Uc=0,ct=0,xn=0,Ot=!1;Qo=0,_t=0,ki=0,Vc=!0,In=[],tr=class{constructor(e,n,s,i){this.update=e,this.render=n,this.glContextLost=s,this.glContextRestored=i}};We=!0,Hc=.5,io=!0,$c="Escape",Ut=!1,pn=[],St=!1,vt=!1,Dn=!1,Fn=!1,ls=!1;oe=Math.PI,he=Math.abs,Le=Math.floor,Fs=Math.ceil,Ci=Math.round,de=Math.min,le=Math.max,ft=t=>Math.sign(t),Qc=(...t)=>Math.hypot(...t),Zc=t=>Math.log2(t),pe=Math.sin,be=Math.cos,el=Math.tan,Hr=Math.atan2;or=class{constructor(e=123456789){m(e!==0,"RandomGenerator seed must be non-zero (xorshift is fixed at 0)"),this.seed=e}float(e=1,n=0){return this.seed^=this.seed<<13,this.seed^=this.seed>>>17,this.seed^=this.seed<<5,n+(e-n)*((this.seed>>>0)/2**32)}int(e,n=0){return Le(this.float(e,n))}bool(e=.5){return this.float().5?1:-1}floatSign(e=1,n=0){let s=de(e,n),r=le(e,n)-s,a=this.float(r*2);return ae?this.scale(e/n):this.copy()}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.x}reflect(e,n=1){return this.subtract(e.scale((1+n)*this.dot(e)))}angle(){return Hr(this.x,this.y)}setAngle(e=0,n=1){return rt(e),rt(n),this.x=n*pe(e),this.y=n*be(e),this}rotate(e){rt(e);let n=be(-e),s=pe(-e);return new t(this.x*n-this.y*s,this.x*s+this.y*n)}setDirection(e,n=1){return rt(e),rt(n),e=ht(e,4),m(e===0||e===1||e===2||e===3,"Vector2.setDirection() direction must be an integer between 0 and 3."),this.x=e%2?e-1?-n:n:0,this.y=e%2?0:e?-n:n,this}direction(){return he(this.x)>he(this.y)?this.x<0?3:1:this.y<0?2:0}abs(){return new t(he(this.x),he(this.y))}floor(){return new t(Le(this.x),Le(this.y))}snap(e){return rt(e),new t(Le(this.x*e)/e,Le(this.y*e)/e)}mod(e=1){return new t(ht(this.x,e),ht(this.y,e))}area(){return he(this.x*this.y)}lerp(e,n){Ic(e),rt(n);let s=$(n);return new t(e.x*s+this.x*(1-s),e.y*s+this.y*(1-s))}arrayCheck(e){return this.x>=0&&this.y>=0&&this.x(u=ht(u,1))*6<1?c+(l-c)*6*u:u*2<1?l:u*3<2?c+(l-c)*(4-u*6):c;return this.r=o(a,r,e+1/3),this.g=o(a,r,e),this.b=o(a,r,e-1/3),this.a=i,Ps(this),this}HSLA(){let e=$(this.r),n=$(this.g),s=$(this.b),i=$(this.a),r=le(e,n,s),a=de(e,n,s),o=(r+a)/2,c=0,l=0;if(r!==a){let u=r-a;l=o>.5?u/(2-r-a):u/(r+a),e===r?c=(n-s)/u+(n((s=$(s)*255|0)<16?"0":"")+s.toString(16);return"#"+n(this.r)+n(this.g)+n(this.b)+(e?n(this.a):"")}setHex(e){if(m(te(e),"Color hex code must be a string"),m(e[0]==="#","Color hex code must start with #"),m([4,5,7,9].includes(e.length),"Invalid hex"),e.length<6){let n=s=>$(parseInt(e[s],16)/15);this.r=n(1),this.g=n(2),this.b=n(3),this.a=e.length===5?n(4):1}else{let n=s=>$(parseInt(e.slice(s,s+2),16)/255);this.r=n(1),this.g=n(3),this.b=n(5),this.a=e.length===9?n(7):1}return Ps(this),this}rgbaInt(){let e=$(this.r)*255|0,n=$(this.g)*255<<8,s=$(this.b)*255<<16,i=$(this.a)*255<<24;return e+n+s+i}isValid(){return I(this.r)&&I(this.g)&&I(this.b)&&I(this.a)}},ne=ut(Q()),Sn=ut(Q(1,1,1,0)),me=ut(Q(0,0,0)),At=ut(Q(0,0,0,0)),vd=ut(Q(.5,.5,.5)),Xr=ut(Q(1,0,0)),wd=ut(Q(1,.5,0)),ll=ut(Q(1,1,0)),ul=ut(Q(0,1,0)),Td=ut(Q(0,1,1)),dl=ut(Q(0,0,1)),fl=ut(Q(.5,0,1)),Ad=ut(Q(1,0,1)),It=class{constructor(e,n=!1){m(e===void 0||I(e),"Constructed Timer is invalid.",e),this.useRealTime=n;let s=this.getGlobalTime();this.time=e===void 0?void 0:s+e,this.setTime=e}set(e=0){m(I(e),"Timer is invalid.",e);let n=this.getGlobalTime();this.time=n+e,this.setTime=e}setUseRealTime(e=!0){m(!this.isSet(),"Cannot change global time setting while timer is set."),this.useRealTime=e}unset(){this.time=void 0}isSet(){return this.time!==void 0}active(){return this.getGlobalTime()=this.time}get(){return this.isSet()?this.getGlobalTime()-this.time:0}getPercent(){return this.isSet()?this.setTime?1-He(this.time-this.getGlobalTime(),0,this.setTime):1:0}getSetTime(){return this.isSet()?this.setTime:0}getGlobalTime(){return this.useRealTime?xn:ct}toString(){return this.isSet()?he(this.get())+" seconds "+(this.get()<0?"before":"after"):"unset"}valueOf(){return this.get()}};Ge=T(),ue=0,ie=32,Qr=1,oo=!0,mn=At,ts=T(1920,1080),Ms=0,ns=0,ss=T(),Zr=!1,jn=!0,yn=1,ei="arial",ea=!1,Y=!1,W=!0,ti=32,ro=T(16),ao=0,co=0,lo=!0,ta=1,na=1,sa=1,ia=0,oa=.8,Wt=1,tt=T(),Pi=1,uo=!0,ra=!0,Ls=!0,Ln=!0,vn=!1,aa=!1,Tt=0,ys=4,Un=!0,gs=0,bs=!1,ni=!0,Tn=!1,st=100,ca=.3,Os=3,Ri=0,si=!0,it=!0,Gn=.3,la=40,ua=.7;Qt=class t{constructor(e=T(),n=T(1),s,i=0,r=ne,a=0){m(D(e),"object pos must be a vec2"),m(D(n),"object size must be a vec2"),m(!s||s instanceof Gt,"object tileInfo should be a TileInfo or undefined"),m(typeof i=="number"&&isFinite(i),"object angle should be a number"),m(Z(r),"object color should be a valid rgba color"),m(typeof a=="number","object renderOrder should be a number"),this.pos=e.copy(),this.size=n.copy(),this.drawSize=void 0,this.tileInfo=s,this.angle=i,this.color=r.copy(),this.additiveColor=void 0,this.mirror=!1,this.destroyed=!1,this.mass=ta,this.damping=na,this.angleDamping=sa,this.restitution=ia,this.friction=oa,this.gravityScale=1,this.renderOrder=a,this.velocity=T(),this.angleVelocity=0,this.spawnTime=ct,this.children=[],this.clampSpeed=!0,this.groundObject=void 0,this.parent=void 0,this.localPos=T(),this.localAngle=0,this.collideTiles=!1,this.collideSolidObjects=!1,this.isSolid=!1,this.collideRaycast=!1,Pe.push(this)}updateTransforms(){let e=this.parent;if(e){let n=e.getMirrorSign(),s=this.localPos,i=e.pos,r=s.x*n,a=s.y,o=e.angle;if(o){let c=be(-o),l=pe(-o);this.pos.set(r*c-a*l+i.x,r*l+a*c+i.y)}else this.pos.set(r+i.x,a+i.y);this.angle=n*this.localAngle+o}for(let n of this.children)n.updateTransforms()}updatePhysics(){if(m(!this.parent),this.destroyed)return;this.clampSpeed&&(this.velocity.x=$(this.velocity.x,-Wt,Wt),this.velocity.y=$(this.velocity.y,-Wt,Wt));let e=this.pos.copy();if(this.velocity.x*=this.damping,this.velocity.y*=this.damping,this.mass&&(this.velocity.x+=tt.x*this.gravityScale,this.velocity.y+=tt.y*this.gravityScale),this.pos.x+=this.velocity.x,this.pos.y+=this.velocity.y,this.angle+=this.angleVelocity*=this.angleDamping,m(this.angleDamping>=0&&this.angleDamping<=1),m(this.damping>=0&&this.damping<=1),!lo||!this.mass)return;let n=this.velocity.y<0&&tt.y<0||this.velocity.y>0&&tt.y>0;if(this.groundObject){let s=le(this.friction,this.groundObject.friction),i=this.groundObject.velocity.x;this.velocity.x=i+(this.velocity.x-i)*s,this.groundObject=void 0}if(this.collideSolidObjects)for(let i of qr){if(i.destroyed||i.parent||i===this||!this.isSolid&&!i.isSolid||!this.isOverlappingObject(i))continue;let r=this.collideWithObject(i),a=i.collideWithObject(this);if(!r||!a)continue;if(Ei(e,this.size,i.pos,i.size)){let d=e.subtract(i.pos),f=d.length(),y=f<.001?T(0,1):d.scale(.001/f);this.velocity=this.velocity.add(y),i.mass&&(i.velocity=i.velocity.subtract(y)),St&&sr(this.pos,this.size,i.pos,i.size,"#f00");continue}let o=this.size.add(i.size),c=(e.y-i.pos.y)*2>o.y+tt.y,l=he(e.y-i.pos.y)*20?-1:1)>0?Le(e.y-this.size.y/2+1)+this.size.y/2+.001:Fs(e.y+this.size.y/2-1)-this.size.y/2-.001;if(he(u-this.pos.y)<.1&&!dn(T(this.pos.x,u),this.size,this)){this.pos.y=u,St&&_e(this.pos,this.size,"#ff0");return}this.pos.x=e.x,this.velocity.x*=-a}if(r||!i){if(n){let c=this.size.y/2+1e-4;this.pos.y=tt.y<0?Le(e.y-this.size.y/2)+c:Fs(e.y+this.size.y/2)-c,this.groundObject=s}else this.pos.y=e.y,this.groundObject=void 0;this.velocity.y*=-a}St&&_e(this.pos,this.size,"#f00")}}}update(){}render(){Ne(this.pos,this.drawSize||this.size,this.tileInfo,this.color,this.angle,this.mirror,this.additiveColor)}renderLight(){}destroy(e=!1){var n;if(!this.destroyed){this.destroyed=!0,(n=this.parent)==null||n.removeChild(this);for(let s of this.children)s.parent=void 0,s.destroy(e)}}localToWorld(e){return this.pos.add(e.rotate(this.angle))}worldToLocal(e){return e.subtract(this.pos).rotate(-this.angle)}localToWorldVector(e){return e.rotate(this.angle)}worldToLocalVector(e){return e.rotate(-this.angle)}collideWithTile(e,n){return e>0}collideWithObject(e){return!0}getUp(e=1){return T().setAngle(this.angle,e)}getRight(e=1){return T().setAngle(this.angle+oe/2,e)}getAliveTime(){return ct-this.spawnTime}getSpeed(){return this.velocity.length()}applyAcceleration(e){this.mass&&(this.velocity=this.velocity.add(e))}applyAngularAcceleration(e){this.mass&&(this.angleVelocity+=e)}applyForce(e){this.mass&&this.applyAcceleration(e.scale(1/this.mass))}getMirrorSign(){return this.mirror?-1:1}addChild(e,n=T(),s=0){return m(!this.destroyed,"cannot add child to destroyed object"),this.destroyed||(m(!e.parent&&!this.children.includes(e)),m(e instanceof t,"child must be an EngineObject"),m(e!==this,"cannot add self as child"),this.children.push(e),e.parent=this,e.localPos=n.copy(),e.localAngle=s,e.updateTransforms()),e}removeChild(e){m(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}isOverlappingObject(e){return this.isOverlapping(e.pos,e.size)}isOverlapping(e,n=T()){return Ei(this.pos,this.size,e,n)}setCollision(e=!0,n=!0,s=!0,i=!0){m(e||!n,"solid objects must be set to collide"),this.collideSolidObjects=e,this.isSolid=n,this.collideTiles=s,this.collideRaycast=i}toString(){let e="type = "+this.constructor.name;return(this.pos.x||this.pos.y)&&(e+=`
+pos = `+this.pos),(this.velocity.x||this.velocity.y)&&(e+=`
+velocity = `+this.velocity),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.angle&&(e+=`
+angle = `+this.angle.toFixed(3)),this.color&&(e+=`
+color = `+this.color),e}renderDebugInfo(){if(!We)return;let e=this.collideTiles||this.collideSolidObjects||this.isSolid;if(!e&&!this.parent)return;let n=T(le(this.size.x,.2),le(this.size.y,.2)),s=Q(this.collideTiles?1:0,this.collideSolidObjects?1:0,this.isSolid?1:0,.5);_e(this.pos,n,s,0,this.angle,e),this.parent&&_e(this.pos,n.scale(.8),Q(1,1,1,.5),0,this.angle),this.parent&&Mt(this.pos,this.parent.pos,Q(1,1,1,.5),.5)}},z=T(),wn=[];Gt=class t{constructor(e=T(),n=ro,s=wn[0],i=ao,r=co){this.pos=e.copy(),this.size=n.copy(),this.padding=i,this.textureInfo=s,this.bleed=r}offset(e){return new t(this.pos.add(e),this.size,this.textureInfo,this.padding,this.bleed)}frame(e){m(typeof e=="number");let n=this.size.x+this.padding*2,s=e*n;return m(s+this.size.x<=this.textureInfo.size.x,"frame extends beyond texture width!"),this.offset(new ge(s))}setFullImage(e=this.textureInfo){return this.textureInfo=e,this.pos=new ge,this.size=e.size.copy(),this.bleed=this.padding=0,this}tile(e){return ii(e,this.size,this.textureInfo,this.padding,this.bleed)}},Zt=class{constructor(e,n=!0,s=!1){this.image=e,this.size=e?T(e.width,e.height):T(),this.sizeInverse=e?T(1/e.width,1/e.height):T(),this.glTexture=void 0,this.wrap=s,n&&this.createWebGLTexture()}createWebGLTexture(){kh(this)}destroyWebGLTexture(){Ch(this)}hasWebGL(){return!!this.glTexture}setWrap(e=!0){this.wrap=e,Ol(this.glTexture,e)}};If=0;Ii=class{constructor(e){m(!!e,"tileInfo is required for ImageFont"),this.tileInfo=e.frame(0)}drawText(e,n,s=1,i,r,a,o){m(D(s)||typeof s=="number","size must be a vec2 or number"),typeof s=="number"?(m(s>0),s*=ie,s=new ge(s,s)):s=s.scale(ie),this.drawTextScreen(e,qn(n),s,i,r,a,o)}drawTextScreen(e,n,s,i=!0,r=ne,a=W,o){m(te(e),"text must be a string"),m(D(n),"pos must be a vec2"),m(D(s)||typeof s=="number","size must be a vec2 or number"),m(Z(r),"color must be a color"),s=typeof s=="number"?new ge(s,s):s;let c=new ge,l=this.tileInfo,u=l.padding,h=l.size.x+u*2,d=l.size.y+u*2,f=l.textureInfo.size.x/h|0;(e+"").split(`
+`).forEach((p,y)=>{let x=i?(p.length-1)*s.x/2:0;for(let w=p.length;w--;){let A=p.charCodeAt(w),v=A<32||A>127?95:A-32,_=v%f,k=v/f|0;l.pos.x=_*h+u,l.pos.y=k*d+u,c.x=n.x+w*s.x-x|0,c.y=n.y+y*s.y|0,Ne(c,s,l,r,0,!1,void 0,a,!0,o)}})}};Nt=T(),Ze=T(),ha=T(),Et=T(),pa=0,Di=!0,rs=!1,hn="mouse",ma=6,is=!0,Ce=0,pt=!Y&&window.ontouchstart!==void 0;re=[[]],Pt=[],Rn=[],Zo=[],ds=new It,mt=[],Jn=[],Fi=[],ci=[],$t=new Map,zs=[],fs=!0;Gi="http://www.w3.org/2000/svg";Ae=new AudioContext,xs=44100;Vs=class{constructor(e,n,s=la,i=ua,r){var a;if(!(!it||Y)){if(m(!e||wt(e)||te(e),"asset must be a file name or zzfx array"),m(n===void 0||I(n),"randomness must be a number"),m(n===void 0||n>=0&&n<=1,"randomness must be between 0 and 1"),m(I(s),"range must be a number"),m(I(i),"taper must be a number"),this.range=s,this.taper=i,this.randomness=n!=null?n:0,this.sampleRate=xs,this.loadedPercent=0,this.onloadCallback=r,wt(e)){let o=e.slice(),c=n!=null?n:.05,l=1;this.randomness=(a=o[l])!=null?a:c,o[l]=0,this.sampleChannels=[ho(...o)],this.loadedPercent=1,r==null||r(this)}else if(typeof e=="string"){let o=e;this.loadSound(o)}}}play(e,n=1,s=1,i=1,r=!1,a=!1){if(m(!e||D(e),"pos must be a vec2"),m(I(n),"volume must be a number"),m(I(s),"pitch must be a number"),m(I(i),"randomnessScale must be a number"),!it||Y||!this.sampleChannels)return;let o;if(e){let u=this.range;if(u){let h=Ge.distanceSquared(e);if(h>u*u)return;n*=He(h**.5,u,u*this.taper)}o=qn(e).x*2/H.width-1}let c=s+s*this.randomness*i*Te(-1,1),l=new Bi(this,n,c,o,r,a);return We&&ls&&e&&(et(e,.5,"#0ff",.5,!0),this.range&&(et(e,2*this.range,"#0ff",.5),et(e,2*this.range*this.taper,"#0ff",.5)),es("vol "+n.toFixed(2)+" pitch "+c.toFixed(2),e,.5,"#0ff",.5)),l}playMusic(e=1,n=!0,s=!1){return this.play(void 0,e,1,0,n,s)}playNote(e=0,n,s){m(I(e),"semitoneOffset must be a number");let i=_l(e,1);return this.play(n,s,i,0)}getDuration(){var e,n;return((n=(e=this.sampleChannels)==null?void 0:e[0])==null?void 0:n.length)/this.sampleRate||0}isLoaded(){return this.loadedPercent===1}async loadSound(e){var c;let n=await fetch(e);if(!n.ok)throw new Error(`Failed to load sound from ${e}: ${n.status} ${n.statusText}`);let s=await n.arrayBuffer(),i=await Ae.decodeAudioData(s),r=i.numberOfChannels,a=1e5,o=[];for(let l=0;lsetTimeout(x,0));let f=de(d+a,h);for(;d=0,"Sound volume must be positive or zero"),m(s>=0,"Sound rate must be positive or zero"),m(I(i),"Sound pan must be a number"),this.sound=e,this.volume=n,this.rate=s,this.pan=i,this.loop=r,this.pausedTime=0,this.startTime=void 0,this.gainNode=void 0,this.source=void 0,this.onendedCallback=o=>{o===this.source&&(this.source=void 0)},a||this.start()}start(e=0){m(e>=0,"Sound start offset must be positive or zero"),this.isPlaying()&&this.stop(),this.gainNode=Ae.createGain(),this.source=Ta(this.sound.sampleChannels,this.volume,this.rate,this.pan,this.loop,this.sound.sampleRate,this.gainNode,e,this.onendedCallback),this.source?(this.startTime=Ae.currentTime-e,this.pausedTime=void 0):(this.startTime=void 0,this.pausedTime=0)}setVolume(e){m(e>=0,"Sound volume must be positive or zero"),this.volume=e,this.gainNode&&(this.gainNode.gain.value=e)}stop(e=0){if(m(e>=0,"Sound fade time must be positive or zero"),this.isPlaying())if(e){let n=Ae.currentTime,s=n+e;this.gainNode.gain.cancelScheduledValues(n),this.gainNode.gain.setValueAtTime(this.volume,n),this.gainNode.gain.linearRampToValueAtTime(0,s),this.source.stop(s)}else this.source.stop();this.pausedTime=0,this.source=void 0,this.startTime=void 0}pause(){this.isPaused()||(this.pausedTime=this.getCurrentTime(),this.source.stop(),this.source=void 0,this.startTime=void 0)}resume(){this.isPaused()&&this.start(this.pausedTime)}isPlaying(){return!!this.source}isPaused(){return!this.isPlaying()}getCurrentTime(){if(!this.isPlaying())return this.pausedTime;let e=this.getDuration();return e?ht(Ae.currentTime-this.startTime,e):0}getDuration(){return this.rate?this.sound.getDuration()/this.rate:0}getSource(){return this.source}};bn=[];Bn=class{constructor(e,n=0,s=!1,i=new Oe){this.tile=e,this.direction=n,this.mirror=s,this.color=i.copy()}clear(){this.tile=this.direction=0,this.mirror=!1,this.color=new Oe}},Ji=class extends Qt{constructor(e,n,s=0,i=0,r=T(512),a=!0){var o;m(D(r),"canvasSize must be a Vector2"),super(e,n,void 0,s,ne,i),this.canvas=Y?void 0:new OffscreenCanvas(r.x,r.y),this.context=(o=this.canvas)==null?void 0:o.getContext("2d"),this.textureInfo=new Zt(this.canvas,a),this.mass=0}destroy(){this.destroyed||(this.textureInfo.destroyWebGLTexture(),super.destroy())}render(){this.draw(this.pos,this.size,this.color,this.angle,this.mirror,this.additiveColor)}draw(e,n,s=ne,i=0,r=!1,a,o=!1,c){let l=new Gt().setFullImage(this.textureInfo),u=this.hasWebGL();Ne(e,n,l,s,i,r,a,u,o,c)}updateWebGL(){this.textureInfo.createWebGLTexture()}hasWebGL(){return W&&this.textureInfo.hasWebGL()}},qs=class extends Ji{constructor(e,n,s=ii(),i=0,r=!0){let a=s?n.multiply(s.size):n;if(super(e,n,0,i,a,r),this.tileInfo=void 0,this.data=[],this.isUsingWebGL=!1,Y){this.render=()=>{},this.redraw=()=>{},this.redrawStart=()=>{},this.redrawEnd=()=>{},this.drawTileData=()=>{},this.redrawTileData=()=>{},this.drawLayerTile=()=>{},this.drawLayerRect=()=>{},this.drawTile=()=>{},this.drawRect=()=>{},this.clearLayerRect=()=>{};return}s&&(this.tileInfo=s.frame(0),this.tileInfo.bleed=0);for(let o=this.size.area();o--;)this.data.push(new Bn)}setData(e,n,s=!1){if(e=e.floor(),m(D(e),"layerPos must be a Vector2"),m(n instanceof Bn,"data must be a TileLayerData"),!e.arrayCheck(this.size)||(this.data[(e.y|0)*this.size.x+(e.x|0)]=n,!s))return;De===this.context?this.drawTileData(e):this.redrawTileData(e)}clearData(e,n=!1){this.setData(e,new Bn,n)}getData(e){return m(D(e),"layerPos must be a Vector2"),e.arrayCheck(this.size)?this.data[(e.y|0)*this.size.x+(e.x|0)]:void 0}update(){!W&&this.isUsingWebGL&&(this.isUsingWebGL=!1,this.redraw())}render(){m(De!==this.context,"must call redrawEnd() after drawing tiles!");let e=this.drawSize||this.size,n=this.pos.add(e.scale(.5));this.draw(n,this.size,this.color,this.angle,this.mirror,this.additiveColor)}onRedraw(){}redraw(){this.redrawStart(!0);for(let e=this.size.x;e--;)for(let n=this.size.y;n--;)this.drawTileData(T(e,n),!1);this.isUsingWebGL&&Be(),this.onRedraw(),this.redrawEnd()}redrawStart(e=!1){var s,i;if(!this.context)return;m(De!==this.context),this.savedRenderSettings=[De,z,Ge,ie,mn],De=this.context;let n=(i=(s=this.tileInfo)==null?void 0:s.size)!=null?i:T(1);z=this.size.multiply(n),mn=At,Ge=this.size.multiply(n).scale(.5),ie=1,this.isUsingWebGL=this.hasWebGL(),this.isUsingWebGL?Rs(this.textureInfo.glTexture,e):(this.context.imageSmoothingEnabled=!jn,e&&(this.canvas.width=z.x,this.canvas.height=z.y))}redrawEnd(){this.context&&(m(De===this.context),this.isUsingWebGL&&Rs(),[De,z,Ge,ie,mn]=this.savedRenderSettings)}drawTileData(e,n=!0){var o,c;if(!this.context)return;m(De===this.context,"must call redrawStart() before drawing tiles");let s=(c=(o=this.tileInfo)==null?void 0:o.size)!=null?c:T(1),i=e.multiply(s);n&&this.clearLayerRect(i,s);let r=this.getData(e);if(!r||!r.tile)return;let a=this.tileInfo&&this.tileInfo.tile(r.tile);this.drawLayerTile(i,s,a,r.color,r.direction*oe/2,r.mirror)}redrawTileData(e,n=!0){this.context&&(m(De!==this.context,"redrawStart() should not be active when calling redrawTileData(), instead use drawTileData()"),this.redrawStart(),this.drawTileData(e,n),this.redrawEnd())}drawLayerTile(e,n=T(1),s,i=ne,r=0,a,o){let c=e.add(n.scale(.5));Ne(c,n,s,i,r,a,o,this.isUsingWebGL)}drawLayerRect(e,n,s,i=0){this.drawLayerTile(e,n,void 0,s,i)}drawTile(e,n=T(1),s,i=new Oe,r=0,a=!1){e=e.subtract(this.pos).multiply(this.tileInfo.size),n=n.multiply(this.tileInfo.size),e.y=this.canvas.height-e.y;let o=z;z=T(this.canvas.width,this.canvas.height);let c=this.hasWebGL();c&&Rs(this.textureInfo.glTexture);let l=c?void 0:this.context;Ne(e,n,s,i,r,a,void 0,c,!0,l),c&&Rs(),z=o}drawRect(e,n,s,i){this.drawTile(e,n,void 0,s,i)}clearLayerRect(e,n){m(De===this.context,"must call redrawStart() before clearing tiles");let s=e.x,i=this.canvas.height-e.y-n.y;this.hasWebGL()?Gl(s,i,n.x,n.y):this.context.clearRect(s,i,n.x,n.y)}},Ws=class extends qs{constructor(e,n,s=ii(),i=0,r=!0){super(e,n.floor(),s,i,r),this.collisionData=[],this.initCollision(this.size),bn.push(this),this.isSolid=!0}destroy(){if(this.destroyed)return;let e=bn.indexOf(this);m(e>=0,"tile collision layer not found in array"),e>=0&&bn.splice(e,1),super.destroy()}initCollision(e){m(D(e),"size must be a Vector2"),this.size=e.floor(),this.collisionData=[],this.collisionData.length=e.area(),this.collisionData.fill(0)}setCollisionData(e,n=1){m(D(e),"layerPos must be a Vector2");let s=(e.y|0)*this.size.x+(e.x|0);e.arrayCheck(this.size)&&(this.collisionData[s]=n)}clearCollisionData(e){this.setCollisionData(e,0)}getCollisionData(e){m(D(e),"layerPos must be a Vector2");let n=(e.y|0)*this.size.x+(e.x|0);return e.arrayCheck(this.size)?this.collisionData[n]:0}collisionTest(e,n=new ge,s){m(D(e)&&D(n),"pos and size must be Vector2s"),m(!s||typeof s=="function"||s instanceof Qt,"callbackObject must be a function or EngineObject");let i=s?typeof s=="function"?(d,f)=>s(d,f):(d,f)=>s.collideWithTile(d,f):()=>!0,r=e.x-this.pos.x,a=e.y-this.pos.y;if(r+n.x/2<0||r-n.x/2>this.size.x||a+n.y/2<0||a-n.y/2>this.size.y)return!1;let o=le(r-n.x/2|0,0),c=le(a-n.y/2|0,0),l=de(le(r+n.x/2,o+1),this.size.x),u=de(le(a+n.y/2,c+1),this.size.y),h=new ge;for(let d=c;ds(l,u):(l,u)=>s.collideWithTile(l,u):l=>l>0,a=l=>{let u=this.getCollisionData(o.set(l.x-this.pos.x,l.y-this.pos.y));return u&&r(u,l)},o=new ge,c=il(e,n,a,i);if(vt&&c){let l=c.floor().add(T(.5));_e(l,T(1),"#f008"),Mt(e,n,"#00f",.02),Mt(e,c,"#f00",.02),Wr(c,"#0f0"),i&&Mt(c,c.add(i),"#ff0",.02)}return c}},ur=class extends Qt{constructor(e,n,s=0,i=0,r=100,a=oe,o,c=ne,l=ne,u=Sn,h=Sn,d=.5,f=.1,p=1,y=.1,x=.05,w=1,A=1,v=0,_=oe,k=.1,C=.2,L=!1,V=!1,ae=!0,O=V?1e9:0,S=!1){super(e,T(),o,n,void 0,O),this.emitCircle=typeof s=="number",this.emitSize=typeof s=="number"?T(s):s.copy(),this.emitTime=i,this.emitRate=r,this.emitConeAngle=a,this.colorStartA=c.copy(),this.colorStartB=l.copy(),this.colorEndA=u.copy(),this.colorEndB=h.copy(),this.randomColorLinear=ae,this.particleTime=d,this.sizeStart=f,this.sizeEnd=p,this.speed=y,this.angleSpeed=x,this.damping=w,this.angleDamping=A,this.gravityScale=v,this.particleConeAngle=_,this.fadeRate=k,this.randomness=C,this.collideTiles=L,this.additive=V,this.localSpace=S,this.trailScale=0,this.particleCreateCallback=void 0,this.particleDestroyCallback=void 0,this.particleCollideCallback=void 0,this.velocityInheritance=0,this.emitTimeBuffer=0,this.particles=[],this.previousAngle=this.angle,this.previousPos=this.pos.copy()}update(){if(m(this.angleDamping>=0&&this.angleDamping<=1),m(this.damping>=0&&this.damping<=1),this.velocityInheritance){let s=this.velocityInheritance;this.velocity.x=s*(this.pos.x-this.previousPos.x),this.velocity.y=s*(this.pos.y-this.previousPos.y),this.angleVelocity=s*(this.angle-this.previousAngle),this.previousAngle=this.angle,this.previousPos.x=this.pos.x,this.previousPos.y=this.pos.y}if(this.isActive()){if(this.emitRate&&Pi){let s=1/this.emitRate/Pi;for(this.emitTimeBuffer+=Vr;this.emitTimeBuffer>0;this.emitTimeBuffer-=s)this.emitParticle()}}else this.particles.length===0&&this.destroy(!0);let e=this.particles,n=0;for(let s=0;sA+A*Te(s,-s),r=i(this.particleTime),a=i(this.sizeStart),o=i(this.sizeEnd),c=i(this.speed),l=i(this.angleSpeed)*rl(),u=Te(this.emitConeAngle,-this.emitConeAngle),h=ir(this.colorStartA,this.colorStartB,this.randomColorLinear),d=ir(this.colorEndA,this.colorEndB,this.randomColorLinear),f=this.localSpace?u:this.angle+u,p=T(c*pe(f),c*be(f)),y=l;!this.localSpace&&this.velocityInheritance>0&&(p.x+=this.velocity.x,p.y+=this.velocity.y,y+=this.angleVelocity);let x=new Ni(this,e,n,h,d,r,a,o,p,y);return this.particles.push(x),(w=this.particleCreateCallback)==null||w.call(this,x),x}updatePhysics(){}render(){for(let e of this.particles)e.render()}isActive(){return!this.emitTime||this.getAliveTime()0&&(this.destroyed=!1,this.emitTime=-1))}},wh=new ge,Ni=class{constructor(e,n,s,i,r,a,o,c,l=T(),u=0){this.emitter=e,this.pos=n,this.angle=s,this.size=T(o),this.color=i.copy(),this.colorStart=i,this.colorEnd=r,this.lifeTime=a,this.sizeStart=o,this.sizeEnd=c,this.velocity=l,this.angleVelocity=u,this.spawnTime=ct,this.mirror=ol(),this.groundObject=void 0,this.destroyed=!1,this.tileInfo=e.tileInfo}update(){let e=this.emitter,n=e.damping,s=e.angleDamping,i=e.restitution,r=e.friction,a=e.gravityScale,o=e.collideTiles,c=e.particleCollideCallback;if(this.lifeTime>0&&ct-this.spawnTime>this.lifeTime){this.destroy();return}let l=this.pos.copy();if(this.velocity.x*=n,this.velocity.y*=n,this.pos.x+=this.velocity.x+=tt.x*a,this.pos.y+=this.velocity.y+=tt.y*a,this.angle+=this.angleVelocity*=s,!lo||!o)return;let u=this.velocity.lengthSquared();if(u>Wt*Wt){let d=Wt/u**.5;this.velocity.x*=d,this.velocity.y*=d}this.groundObject=void 0;let h=c?d=>{let f=ji(d);return f&&c(this,f,d)}:d=>ji(d)>0;if(h(this.pos)){let d=dn(this.pos);if(!h(l)){let f=h(T(this.pos.x,l.y)),p=h(T(l.x,this.pos.y)),y=le(i,d.restitution),x=le(r,d.friction);f&&(this.pos.x=l.x,this.velocity.x*=-y,this.velocity.y*=x),(p||!f)&&((this.velocity.y<0&&tt.y<0||this.velocity.y>0&&tt.y>0)&&(this.groundObject=d),this.pos.y=l.y,this.velocity.y*=-y,this.velocity.x*=x),St&&_e(this.pos,this.size,"#f00")}}}destroy(){let e=this.emitter.particleDestroyCallback,n=this.colorEnd;this.color.set(n.r,n.g,n.b,n.a),this.size.set(this.sizeEnd,this.sizeEnd),this.destroyed=!0,e==null||e(this)}render(){let e=this.emitter,n=e.localSpace,s=e.additive,i=e.trailScale,r=e.fadeRate/2,a=this.lifeTime>0?de((ct-this.spawnTime)/this.lifeTime,1):1,o=1-a,c=o*this.sizeStart+a*this.sizeEnd,l=T(c),u=a1-r?(1-a)/r:1;this.color.r=o*this.colorStart.r+a*this.colorEnd.r,this.color.g=o*this.colorStart.g+a*this.colorEnd.g,this.color.b=o*this.colorStart.b+a*this.colorEnd.b,this.color.a=(o*this.colorStart.a+a*this.colorEnd.a)*u;let h=wh.set(this.pos.x,this.pos.y),d=this.angle;if(n){let f=e.angle,p=be(-f),y=pe(-f);h.set(e.pos.x+h.x*p-h.y*y,e.pos.y+h.x*y+h.y*p),d+=f}if(s&&js(),i){let f=n?this.velocity.rotate(e.angle):this.velocity,p=f.length();if(p){let y=p*i;l.y=le(l.x,y),d=Hr(f.x,f.y),Ne(h,l,this.tileInfo,this.color,d,this.mirror)}}else Ne(h,l,this.tileInfo,this.color,d,this.mirror);s&&js(!1),Dn&&_e(h,l,"#f005",0,d)}},Aa=!0,pr=!0,qi=5e5,Ca=11,Pl=Ca*4,Th=qi/Pl|0,po=3,Rl=po*4,cs=qi/Rl|0;Pn=!1,Wi=5,os=.5,Hi=T(640,80),Oa=!1,Xs={},wi=[];Yi=class{constructor(e,n,s="",i="\u{1F3C6}",r){m(e>=0&&!Xs[e]),this.id=e,this.name=n,this.description=s,this.icon=i,this.unlocked=!1,this.image=void 0,r&&((this.image=new Image).src=r),Xs[e]=this}unlock(){Oa||this.unlocked||(m($i,"save name must be set"),this.unlocked=!0,Ia(),wi.push(this))}render(e=0){let n=Se,s=de(Hi.x,H.width),i=Hi.y,r=H.width-s,a=-i*e,o=qt(0,0,.9);n.save(),n.beginPath(),n.fillStyle=o.toString(),n.strokeStyle=me.toString(),n.lineWidth=3,n.rect(r,a,s,i),n.fill(),n.stroke(),n.clip();let c=T(.1,.05).scale(i),l=i-2*c.x;this.renderIcon(T(r+c.x+l/2,a+i/2),l);let u=i*.5,h=i*.3,d=T(r+l+2*c.x,a+c.y*2+u/2),f=s-l-3*c.x;gn(this.name,d,u,me,0,void 0,"left",void 0,void 0,f),d.y=a+i-c.y*2-h/2,gn(this.description,d,h,me,0,void 0,"left",void 0,void 0,f),n.restore()}renderIcon(e,n){this.image?Se.drawImage(this.image,e.x-n/2,e.y-n/2,n,n):gn(this.icon,e,n*.7,me)}};gr=class extends Yi{constructor(e,n,s,i,r){super(e,n,s,i,r)}unlock(){super.unlock(),Ks&&Ks.unlockMedal(this.id)}},br=class{constructor(e,n,s){var c,l,u;m(!Ks,"there can only be one newgrounds object"),m(!n||s,"must provide cryptojs if there is a cipher"),Ks=this,this.app_id=e,this.cipher=n,this.cryptoJS=s,this.host=location?location.hostname:"";let i=new URL(location.href);if(this.session_id=i.searchParams.get("ngio_session_id"),!this.session_id)return;let r=this.call("Medal.getList");if(!r||!r.result||r.result.error){Pn&&Ee("Newgrounds session unavailable; skipping plugin init"),this.medals=[],this.scoreboards=[];return}this.medals=((c=r.result.data)==null?void 0:c.medals)||[],Pn&&Ee(this.medals);for(let h of this.medals){let d=Xs[h.id];d&&(d.image=new Image,d.image.src=h.icon,d.name=h.name,d.description=h.description,d.unlocked=h.unlocked,d.difficulty=h.difficulty,d.value=h.value,d.value&&(d.description=d.description+` (${d.value})`))}let a=this.call("ScoreBoard.getBoards");this.scoreboards=((u=(l=a==null?void 0:a.result)==null?void 0:l.data)==null?void 0:u.scoreboards)||[],Pn&&Ee(this.scoreboards);let o=60*1e3;setInterval(()=>this.call("Gateway.ping",0,!0),o)}unlockMedal(e){return this.call("Medal.unlock",{id:e},!0)}postScore(e,n){return this.call("ScoreBoard.postScore",{id:e,value:n},!0)}getScores(e,n,s=0,i=0,r=10){return this.call("ScoreBoard.getScores",{id:e,user:n,social:s,skip:i,limit:r})}logView(){return this.call("App.logView",{host:this.host},!0)}call(e,n,s=!1){let i={component:e,parameters:n};if(this.cipher){let l=this.cryptoJS,u=l.enc.Base64.parse(this.cipher),h=l.lib.WordArray.random(16),d=l.AES.encrypt(JSON.stringify(i),u,{iv:h});i.secure=l.enc.Base64.stringify(h.concat(d.ciphertext)),i.parameters=0}let r={app_id:this.app_id,session_id:this.session_id,call:i},a=new FormData;a.append("input",JSON.stringify(r));let o=new XMLHttpRequest;o.open("POST","https://newgrounds.io/gateway_v3.php",!Pn&&s);try{o.send(a)}catch(l){Pn&&Ee("newgrounds call failed",l);return}return Pn&&Ee(o.responseText),o.responseText&&JSON.parse(o.responseText)}},xr=class{constructor(e,n=!1,s=!1){m(!Ue,"Post process already initialized"),m(!(n&&s),"Post process cannot both include main canvas and use feedback texture"),Ue=this,e||(e="void mainImage(out vec4 c,vec2 p){c=texture(iChannel0,p/iResolution.xy);}"),this.shader=void 0,this.texture=void 0,this.vao=void 0,i(),zn(void 0,o,r,a);function i(){if(Y)return;if(!W){console.warn("PostProcessPlugin: WebGL not enabled!");return}Ue.texture=mo(),Ue.shader=ms(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D iChannel0;uniform vec3 iResolution;uniform float iTime;out vec4 c;
+`+e+`
+void main(){mainImage(c,gl_FragCoord.xy);c.a=1.;}`),Ue.vao=g.createVertexArray(),g.bindVertexArray(Ue.vao),g.bindBuffer(g.ARRAY_BUFFER,as);let c=8,l=g.getAttribLocation(Ue.shader,"p");g.enableVertexAttribArray(l),g.vertexAttribPointer(l,2,g.FLOAT,!1,c,0)}function r(){Ue.shader=void 0,Ue.texture=void 0,Ee("PostProcessPlugin: WebGL context lost")}function a(){i(),Ee("PostProcessPlugin: WebGL context restored")}function o(){if(Y||!W)return;Be(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.useProgram(Ue.shader),g.bindVertexArray(Ue.vao),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!0),g.disable(g.BLEND),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,Ue.texture),n?(Yt.width=z.x,Yt.height=z.y,Pa(fn),fn.drawImage(H,0,0),H.width|=0,g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,Yt)):s||g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,fe);let c=l=>g.getUniformLocation(Ue.shader,l);g.uniform1i(c("iChannel0"),0),g.uniform1f(c("iTime"),ct),g.uniform3f(c("iResolution"),H.width,H.height,1),g.drawArrays(g.TRIANGLE_STRIP,0,4),s&&g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,fe),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!1),$s(!0)}}},Sr=class{constructor(e,n){m(!se,"LightSystemPlugin already initialized"),m(!Ue,"LightSystemPlugin must be created before PostProcessPlugin"),se=this,this.enabled=!0,this.ambientColor=(n||me).copy(),this.textureSize=e?e.copy():void 0,this.texture=void 0,this.lightShader=void 0,this.compositeShader=void 0,this.lightVAO=void 0,this.compositeVAO=void 0,s(),zn(void 0,i,r,a);function s(){if(Y)return;if(!W){console.warn("LightSystemPlugin: WebGL not enabled!");return}se.textureSize||(se.textureSize=z.copy()),se.texture=g.createTexture(),g.bindTexture(g.TEXTURE_2D,se.texture),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,se.textureSize.x,se.textureSize.y,0,g.RGBA,g.UNSIGNED_BYTE,null),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,g.CLAMP_TO_EDGE),se.lightShader=ms(`#version 300 es
+precision highp float;uniform mat4 m;uniform vec2 lightPos;uniform float radius;in vec2 g;out vec2 vWorldPos;void main(){vec2 worldP=lightPos+(g-.5)*2.*radius;gl_Position=m*vec4(worldP,1,1);vWorldPos=worldP;}`,`#version 300 es
+precision highp float;uniform vec2 lightPos;uniform float radius;uniform float fadeRange;uniform vec4 color;in vec2 vWorldPos;out vec4 c;void main(){float dist=distance(vWorldPos,lightPos);float t=clamp((radius-dist)/max(fadeRange,1e-6),0.,1.);c=vec4(color.rgb*t*color.a,1.);}`),se.compositeShader=ms(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D s;uniform vec3 iResolution;out vec4 c;void main(){vec2 uv=gl_FragCoord.xy/iResolution.xy;c=vec4(texture(s,uv).rgb,1.);}`),se.lightVAO=g.createVertexArray(),g.bindVertexArray(se.lightVAO),g.bindBuffer(g.ARRAY_BUFFER,as);let o=g.getAttribLocation(se.lightShader,"g");g.enableVertexAttribArray(o),g.vertexAttribPointer(o,2,g.FLOAT,!1,8,0),se.compositeVAO=g.createVertexArray(),g.bindVertexArray(se.compositeVAO),g.bindBuffer(g.ARRAY_BUFFER,as);let c=g.getAttribLocation(se.compositeShader,"p");g.enableVertexAttribArray(c),g.vertexAttribPointer(c,2,g.FLOAT,!1,8,0)}function i(){if(Y||!W||!se.enabled||!se.texture)return;Be();let o=Hn,c=se.ambientColor;g.bindFramebuffer(g.FRAMEBUFFER,ka),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,se.texture,0),g.viewport(0,0,se.textureSize.x,se.textureSize.y),g.clearColor(c.r,c.g,c.b,c.a),g.clear(g.COLOR_BUFFER_BIT),js(),g.enable(g.BLEND),g.blendFunc(g.ONE,g.ONE);for(let u of Pe)u.destroyed||u.renderLight();Be(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,z.x,z.y),g.useProgram(se.compositeShader),g.bindVertexArray(se.compositeVAO),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,se.texture);let l=se.compositeShader;g.uniform1i(g.getUniformLocation(l,"s"),0),g.uniform3f(g.getUniformLocation(l,"iResolution"),H.width,H.height,1),g.blendFunc(g.DST_COLOR,g.ZERO),g.drawArrays(g.TRIANGLE_STRIP,0,4),lt&&g.bindTexture(g.TEXTURE_2D,lt),js(o),$s(!0)}function r(){se.texture=void 0,se.lightShader=void 0,se.compositeShader=void 0,se.lightVAO=void 0,se.compositeVAO=void 0,Ee("LightSystemPlugin: WebGL context lost")}function a(){s(),Ee("LightSystemPlugin: WebGL context restored")}}drawLight(e){if(Y||!W||!this.lightShader)return;Be(),g.useProgram(this.lightShader),g.bindVertexArray(this.lightVAO);let n=T(2*ie).divide(z),s=Ge.rotate(-ue),i=T(-1).subtract(s.multiply(n)),r=be(ue),a=pe(ue),o=[n.x*r,n.y*a,0,0,-n.x*a,n.y*r,0,0,1,1,1,0,i.x,i.y,0,1],c=this.lightShader;g.uniformMatrix4fv(g.getUniformLocation(c,"m"),!1,o),g.uniform2f(g.getUniformLocation(c,"lightPos"),e.pos.x,e.pos.y),g.uniform1f(g.getUniformLocation(c,"radius"),e.radius),g.uniform1f(g.getUniformLocation(c,"fadeRange"),e.fadeRange);let l=e.color;g.uniform4f(g.getUniformLocation(c,"color"),l.r,l.g,l.b,l.a),g.drawArrays(g.TRIANGLE_STRIP,0,4),$s(!0)}},vr=class extends Qt{constructor(e,n,s,i){super(e,T(1),void 0,0,s),m(I(n)&&n>=0,"Light radius must be a non-negative number"),m(i===void 0||I(i)&&i>=0,"Light fadeRange must be a non-negative number when provided"),this.radius=n,this.fadeRange=i===void 0?n:i}render(){}renderLight(){se&&se.drawLight(this)}},wr=class extends Vs{constructor(e){super(void 0),!(!it||Y)&&(this.randomness=0,this.sampleChannels=Bl(...e),this.sampleRate=xs)}playMusic(e=1,n=!0){return super.play(void 0,e,1,0,n)}};Da=0;Tr=class{constructor(e=Se){m(!E,"UI system already initialized"),E=this,this.activateOnPress=!1,this.defaultColor=ne,this.defaultLineColor=me,this.defaultTextColor=me,this.defaultButtonColor=qt(0,0,.7),this.defaultHoverColor=qt(0,0,.9),this.defaultDisabledColor=qt(0,0,.3),this.defaultGradientColor=void 0,this.defaultLineWidth=4,this.defaultCornerRadius=0,this.defaultTextFitScale=.8,this.defaultFont=ei,this.defaultSoundPress=void 0,this.defaultSoundRelease=void 0,this.defaultSoundClick=void 0,this.defaultShadowColor=At,this.defaultShadowBlur=5,this.defaultShadowOffset=T(5),this.nativeHeight=0,this.navigationObject=void 0,this.navigationTimer=new It(void 0,!0),this.navigationDelay=.2,this.navigationDirection=1,this.navigationMode=!1,this.uiObjects=[],this.uiContext=e,this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.confirmDialog=void 0,this._keyInputObject=void 0,this._onKeyDown=r=>{var a;return(a=this._keyInputObject)==null?void 0:a.onKeyDown(r)},zn(s,i);function n(r){let a,o;r.parent?(a=r.parent.nativePos,o=r.parent.size):(a=E.screenToNative(z.scale(.5)),o=E.nativeHeight?T(z.x*E.nativeHeight/z.y,E.nativeHeight):z);let c=r.anchor;r.nativePos=a.add(o.multiply(c).scale(.5)).subtract(r.size.multiply(c).scale(.5)).add(r.localPos)}function s(){E.activeObject&&!E.activeObject.visible&&(E.activeObject=void 0),E.lastHoverObject=E.hoverObject,E.hoverObject=void 0,Js(0)&&(E.navigationMode=!1,E.navigationObject=void 0),E.keyInputObject&&(E.activeObject=E.keyInputObject,E.hoverObject=E.keyInputObject,E.navigationMode=!1,E.navigationObject=void 0);let r=E.getNavigableObjects();if(!r.length)E.navigationObject=void 0;else if(!E.keyInputObject){if(r.includes(E.navigationObject)||(E.navigationObject=void 0),pt||E.navigationMode&&!E.navigationObject&&(E.navigationObject=r.find(o=>o.navigationAutoSelect)),!E.navigationTimer.active()){let o=ft(E.getNavigationDirection());if(o){let c;if(E.navigationObject){let l=r.indexOf(E.navigationObject),u=ht(l+o,r.length);c=r[u]}else if(c=r.find(l=>l.navigationAutoSelect),!c){let l=o>0?0:r.length-1;c=r[l]}E.navigationObject!==c&&(E.navigationMode=!0,E.hoverObject=void 0,E.navigationObject=c,E.navigationTimer.set(E.navigationDelay),c.soundPress&&c.soundPress.play())}}E.navigationObject&&E.getNavigationWasPressed()&&E.navigationObject.navigatePressed()}for(let o=E.uiObjects.length;o--;){let c=E.uiObjects[o];c.parent||a(c)}E.uiObjects=E.uiObjects.filter(o=>!o.destroyed);function a(o){if(!(o.destroyed||!o.visible)){n(o);for(let c=o.children.length;c--;){let l=o.children[c];l&&a(l)}o.destroyed||o.update()}}}function i(){let r=E.uiContext;if(r.save(),E.nativeHeight){let o=z.y/E.nativeHeight;r.translate(-o*z.x/2,0),r.scale(o,o),r.translate(z.x/2/o,0)}function a(o){if(o.visible){n(o),o.render();for(let c of o.children)a(c)}}if(E.uiObjects.forEach(o=>o.parent||a(o)),Da>0){let o=function(c,l=!0){l&&(l=!!c.visible),n(c),c.renderDebug(l);for(let u of c.children)o(u,l)};E.uiObjects.forEach(c=>c.parent||o(c))}r.restore()}}drawRect(e,n,s=ne,i=0,r=me,a=0,o,c=me,l=0,u=T()){m(D(e),"pos must be a vec2"),m(D(n),"size must be a vec2"),m(Z(s),"color must be a color"),m(I(i),"lineWidth must be a number"),m(Z(r),"lineColor must be a color"),m(I(a),"cornerRadius must be a number");let h=E.uiContext;if(o){let d=h.createLinearGradient(e.x,e.y-n.y/2,e.x,e.y+n.y/2),f=s.toString();d.addColorStop(0,f),d.addColorStop(.5,o.toString()),d.addColorStop(1,f),h.fillStyle=d}else h.fillStyle=s.toString();(l||u.x||u.y)&&c.a>0&&(h.shadowColor=c.toString(),h.shadowBlur=l,h.shadowOffsetX=u.x,h.shadowOffsetY=u.y),h.beginPath(),a&&h.roundRect?h.roundRect(e.x-n.x/2,e.y-n.y/2,n.x,n.y,a):h.rect(e.x-n.x/2,e.y-n.y/2,n.x,n.y),h.fill(),h.shadowColor="#0000",i&&r.a>0&&(h.strokeStyle=r.toString(),h.lineWidth=i,h.stroke())}drawLine(e,n,s=E.defaultLineWidth,i=E.defaultLineColor){m(D(e),"posA must be a vec2"),m(D(n),"posB must be a vec2"),m(I(s),"lineWidth must be a number"),m(Z(i),"lineColor must be a color");let r=E.uiContext;r.strokeStyle=i.toString(),r.lineWidth=s,r.beginPath(),r.lineTo(e.x,e.y),r.lineTo(n.x,n.y),r.stroke()}drawTile(e,n,s,i=E.defaultColor,r=0,a=!1,o=me,c=0,l=T()){let u=E.uiContext;(c||l.x||l.y)&&o.a>0&&(u.shadowColor=o.toString(),u.shadowBlur=c,u.shadowOffsetX=l.x,u.shadowOffsetY=l.y),Ne(e,n,s,i,r,a,At,!1,!0,u),u.shadowColor="#0000"}drawText(e,n,s,i=E.defaultColor,r=E.defaultLineWidth,a=E.defaultLineColor,o="center",c=E.defaultFont,l="",u=!0,h=void 0,d=me,f=0,p=T()){let y=E.uiContext;d.a>0&&(h&&gn(e,n.add(h),s.y,d,r,a,o,c,l,u?s.x:void 0,0,y),(f||p.x||p.y)&&(y.shadowColor=d.toString(),y.shadowBlur=f,y.shadowOffsetX=p.x,y.shadowOffsetY=p.y)),gn(e,n,s.y,i,r,a,o,c,l,u?s.x:void 0,0,y),y.shadowColor="#0000"}setupDragAndDrop(e,n,s,i){if(this._dragListeners)for(let[a,o]of this._dragListeners)document.removeEventListener(a,o);this._dragListeners=[];let r=(a,o)=>{let c=l=>{l.preventDefault(),a&&a(l)};document.addEventListener(o,c),this._dragListeners.push([o,c])};r(e,"drop"),r(n,"dragenter"),r(s,"dragleave"),r(i,"dragover")}screenToNative(e){if(!E.nativeHeight)return e;let n=z.y/E.nativeHeight,s=1/n,i=e.copy();return i.x+=n*z.x/2,i.x*=s,i.y*=s,i.x-=s*z.x/2,i}get keyInputObject(){return this._keyInputObject}set keyInputObject(e){let n=!!this._keyInputObject;this._keyInputObject=e,!n&&e?document.addEventListener("keydown",this._onKeyDown):n&&!e&&document.removeEventListener("keydown",this._onKeyDown)}destroyObjects(){for(let e of this.uiObjects)e.parent||e.destroy();this.uiObjects=this.uiObjects.filter(e=>!e.destroyed),this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.keyInputObject=void 0}getNavigableObjects(){function e(s){if(!(!s.visible||s.disabled)){s.isInteractive()&&s.navigationIndex!==void 0&&n.push(s);for(let i=s.children.length;i--;)e(s.children[i])}}let n=[];for(let s=E.uiObjects.length;s--;){let i=E.uiObjects[s];E.confirmDialog&&i!==E.confirmDialog||i.parent||e(i)}return n.sort((s,i)=>s.navigationIndex-i.navigationIndex),n}getNavigationDirection(){let e=E.navigationDirection===1,n=E.navigationDirection===2;if(rs){let l=Ns(0,Ce),u=cr(Ce);return n?-(l.y||u.y)||l.x||u.x:e?-(l.y||u.y):l.x||u.x}let s="ArrowUp",i="ArrowDown",r="ArrowLeft",a="ArrowRight";if(n)return Je(s)||Je(r)?-1:Je(i)||Je(a)?1:0;let o=e?s:r,c=e?i:a;return Je(o)?-1:Je(c)?1:0}getNavigationOtherDirection(){if(E.navigationDirection===2)return 0;let e=E.navigationDirection===1;if(rs){let i=Ns(0,Ce),r=cr(Ce);return e?i.x||r.x:i.y||r.y}let n=e?"ArrowLeft":"ArrowUp",s=e?"ArrowRight":"ArrowDown";return Je(n)?-1:Je(s)?1:0}getNavigationWasPressed(){return rs?ba(0,Ce):Ve("Space")||Ve("Enter")}showConfirmDialog(e="Are you sure?",n,s,i=T(500,250),r="Escape"){m(!E.confirmDialog);let a=E.navigationDirection;E.navigationDirection=2;let o=new yt(T(),i);E.confirmDialog=o,o.onRender=()=>{let f=qt(0,0,0,.7);E.drawRect(T(),T(1e9),f)},o.onUpdate=()=>{Ve(r)&&d()},o.isMouseOverlapping=()=>!0;let c=50,l=new Xi(T(0,-50),T(i.x-c,70),e);o.addChild(l);let u=new Qs(T(-80,50),T(120,70),"Yes");u.textHeight=40,u.navigationIndex=1,u.hoverColor=qt(0,1,.5),u.onClick=()=>{d(),n&&n()},o.addChild(u);let h=new Qs(T(80,50),T(120,70),"No");h.textHeight=40,h.navigationIndex=2,h.navigationAutoSelect=!0,h.onClick=()=>{d(),s&&s()},o.addChild(h);function d(){m(E.confirmDialog===o),o.destroy(),E.confirmDialog=void 0,E.navigationDirection=a,ai()}}},yt=class{constructor(e=T(),n=T()){var s,i;m(D(e),"ui object pos must be a vec2"),m(D(n),"ui object size must be a vec2"),this.localPos=e.copy(),this.nativePos=e.copy(),this.size=n.copy(),this.color=E.defaultColor.copy(),this.activeColor=void 0,this.text=void 0,this.disabledColor=E.defaultDisabledColor.copy(),this.disabled=!1,this.textColor=E.defaultTextColor.copy(),this.hoverColor=E.defaultHoverColor.copy(),this.lineColor=E.defaultLineColor.copy(),this.gradientColor=E.defaultGradientColor?E.defaultGradientColor.copy():void 0,this.lineWidth=E.defaultLineWidth,this.cornerRadius=E.defaultCornerRadius,this.font=E.defaultFont,this.fontStyle=void 0,this.textWidth=void 0,this.textHeight=void 0,this.textFitScale=E.defaultTextFitScale,this.textShadow=void 0,this.textLineColor=E.defaultLineColor.copy(),this.textLineWidth=0,this.visible=!0,this.children=[],this.parent=void 0,this.extraTouchSize=0,this.soundPress=E.defaultSoundPress,this.soundRelease=E.defaultSoundRelease,this.soundClick=E.defaultSoundClick,this.interactive=!1,this.dragActivate=!1,this.canBeHover=!0,this.shadowColor=(s=E.defaultShadowColor)==null?void 0:s.copy(),this.shadowBlur=E.defaultShadowBlur,this.shadowOffset=(i=E.defaultShadowOffset)==null?void 0:i.copy(),this.navigationIndex=void 0,this.navigationAutoSelect=!1,this.anchor=T(),E.uiObjects.push(this)}addChild(e){return m(!e.parent&&!this.children.includes(e)),this.children.push(e),e.parent=this,e}removeChild(e){m(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}destroy(){var e;if(!this.destroyed){E.activeObject===this&&(E.activeObject=void 0),E.hoverObject===this&&(E.hoverObject=void 0),E.lastHoverObject===this&&(E.lastHoverObject=void 0),E.navigationObject===this&&(E.navigationObject=void 0),E.keyInputObject===this&&(E.keyInputObject=void 0),this.destroyed=1,(e=this.parent)==null||e.removeChild(this);for(let n of this.children)n.parent=void 0,n.destroy();this.children.length=0}}isMouseOverlapping(){if(!Di)return!1;let e=pt?this.size.add(T(this.extraTouchSize||0)):this.size,n=E.screenToNative(Ze);return Ei(this.nativePos,e,n)}update(){if(this.onUpdate(),this.disabled&&(this===E.activeObject&&(E.activeObject=void 0),this===E.keyInputObject&&(E.keyInputObject=void 0)),E.keyInputObject)return;let e=E.lastHoverObject===this,n=this.isActiveObject(),s=Is(0),i=this.dragActivate?s:Js(0);this.canBeHover&&(E.navigationMode||(i||n||!s&&!pt)&&!E.hoverObject&&this.isMouseOverlapping()&&(E.hoverObject=this)),this.isHoverObject()&&(this.disabled||(i&&this.interactive&&((!this.dragActivate||!e||Js(0))&&this.onPress(),this.soundPress&&this.soundPress.play(),E.activeObject&&!n&&E.activeObject.onRelease(),E.activeObject=this,E.activateOnPress&&this.click(!this.soundPress)),E.activateOnPress||!s&&this.isActiveObject()&&this.interactive&&this.click()),i&&ya(0,0,0,1,0)),n&&(!s||this.dragActivate&&!this.isHoverObject())&&(this.onRelease(),this.soundRelease&&this.soundRelease.play(),E.activeObject=void 0),this.isHoverObject()!==e&&(this.isHoverObject()?this.onEnter():this.onLeave())}render(){if(this.onRender(),!this.size.x||!this.size.y)return;let e=this.isNavigationObject(),n=e?this.color:this.interactive&&this.isActiveObject()&&!this.disabled?this.color:this.lineColor,s=e?this.hoverColor:this.disabled?this.disabledColor:this.interactive?this.isActiveObject()?this.activeColor||this.hoverColor:this.isHoverObject()?this.hoverColor:this.color:this.color,i=this.lineWidth*(e?1.5:1);E.drawRect(this.nativePos,this.size,s,i,n,this.cornerRadius,this.gradientColor,this.shadowColor,this.shadowBlur,this.shadowOffset)}getTextSize(){return T(this.textWidth||this.textFitScale*this.size.x,this.textHeight||this.textFitScale*this.size.y)}navigatePressed(){this.click()}isHoverObject(){return E.hoverObject===this}isActiveObject(){return E.activeObject===this}isNavigationObject(){return E.navigationObject===this}isKeyInputObject(){return E.keyInputObject===this}isInteractive(){return this.interactive&&this.visible&&!this.disabled}toString(){let e="type = "+this.constructor.name;return this.text&&(e+=`
+text = `+this.text),(this.nativePos.x||this.nativePos.y)&&(e+=`
+nativePos = `+this.nativePos),(this.localPos.x||this.localPos.y)&&(e+=`
+localPos = `+this.localPos),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.color&&(e+=`
+color = `+this.color),e}renderDebug(e=!0){let n=e?this.isHoverObject()?ll:this.disabled?fl:this.interactive?Xr:dl:ul;E.drawRect(this.nativePos,this.size,At,4,n)}click(e=!0){this.onClick(),e&&this.soundClick&&this.soundClick.play()}onUpdate(){}onRender(){}onEnter(){}onLeave(){}onPress(){}onRelease(){}onClick(){}onChange(){}},Xi=class extends yt{constructor(e,n,s="",i="center",r=E.defaultFont){super(e,n),m(te(s),"ui text must be a string"),m(["left","center","right"].includes(i),"ui text align must be left, center, or right"),m(te(r),"ui text font must be a string"),this.text=s,this.align=i,this.font=r,this.canBeHover=!1,this.color=At,this.shadowColor=At,this.gradientColor=void 0,this.lineWidth=0,this.textFitScale=1}render(){super.render();let e=this.getTextSize();E.drawText(this.text,this.nativePos,e,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow,this.shadowColor,this.shadowBlur,this.shadowOffset)}},Ar=class extends yt{constructor(e,n,s=""){super(e,n),m(te(s),"ui text must be a string"),this.maxLength=0,this.text=s,this.interactive=!0,this.canBeHover=!0}click(){E.keyInputObject=this,this.onClick()}stopEditing(){this.isKeyInputObject()&&(this.soundRelease&&this.soundRelease.play(),E.activeObject=void 0,E.keyInputObject=void 0,this.onChange())}onKeyDown(e){let n=e.code,s=e.key;n==="Backspace"?this.text=this.text.slice(0,-1):n==="Enter"||n==="Escape"?this.stopEditing():s.length===1&&(!this.maxLength||this.text.lengththis.size.y,s=n?this.size.y:this.size.x,i=n?this.size.x:this.size.y,r=n?this.nativePos.x:this.nativePos.y,a=i-s,o=r-a/2,c=r+a/2,l=E.screenToNative(Ze);this.value=n?He(l.x,o,c):He(l.y,c,o)}else if(this.isNavigationObject()){let n=E.getNavigationOtherDirection();E.navigationTimer.active()||(this.value=$(this.value+n*.01))}this.value===e||this.onChange()}render(){super.render();let e=this.size.x>this.size.y,n=e?this.size.x:this.size.y,s=e?this.size.y:this.size.x;if(this.fillMode){let r=de(s,this.cornerRadius*2),a=nt(r,n,this.value),o=(a-n)*(e?.5:-.5),c=this.nativePos.add(e?T(o,0):T(0,o)),l=this.disabled?this.disabledColor:this.handleColor,u=e?T(a,this.size.y):T(this.size.x,a);E.drawRect(c,u,l,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}else{let r=$(e?this.value:1-this.value),a=(n-s)*(r-.5),o=this.nativePos.add(e?T(a,0):T(0,a)),c=this.disabled?this.disabledColor:this.handleColor,l=T(s);E.drawRect(o,l,c,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}let i=this.getTextSize();E.drawText(this.text,this.nativePos,i,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow)}navigatePressed(){this.value=this.value?0:1,this.onChange(),this.onRelease(),super.navigatePressed()}},Er=class extends yt{constructor(e,n,s,i=!1,r=!1,a=1){super(e,n||T()),m(te(s),"video src must be a string"),m(I(a),"video volume must be a number"),this.color=me,this.cornerRadius=0,this.volume=a,this.video=document.createElement("video"),this.video.loop=r,this.video.volume=$(a*Gn),this.video.muted=!it,this.video.style.display="none",this.video.src=s,document.body.appendChild(this.video),i&&this.play()}async play(){try{await this.video.play()}catch{}}pause(){this.video.pause()}stop(){this.video.pause(),this.video.currentTime=0}isLoading(){return this.video.readyState=1,"ui layout columns must be a number >= 1"),m(I(s),"ui layout gap must be a number"),m(I(i),"ui layout padding must be a number"),this.columns=n,this.gap=s,this.padding=i,r&&(this.color=At,this.gradientColor=void 0,this.lineWidth=0,this.shadowColor=At),this.relayout()}addChild(e){return super.addChild(e),this.relayout(),e}removeChild(e){super.removeChild(e),this.relayout()}relayout(){let e=this.children.length;if(!e){this.size=T(this.padding*2);return}let n=this.columns,s=Fs(e/n),i=new Array(n).fill(0),r=new Array(s).fill(0);for(let d=0;d=0&&b.objects.splice(e,1),super.destroy()}updatePhysics(){}render(){this.tileInfo?super.render():this.drawFixtures(this.color,this.lineColor,this.lineWidth)}renderDebugInfo(){let e=!this.getIsAwake(),n=this.getBodyType()===b.bodyTypeStatic,s=Q(e?1:0,e?1:0,n?1:0,.5);this.drawFixtures(s)}drawFixtures(e=ne,n=me,s=.1,i,r){this.getFixtureList().forEach(a=>{b.castShapeObject(a.GetShape()).GetType()!==b.instance.b2Shape.e_edge&&b.drawFixture(a,this.pos,this.angle,e,n,s,i,r)}),this.edgeLists.forEach(a=>ar(a,s,n,!1,this.pos,this.angle)),this.edgeLoops.forEach(a=>ar(a,s,n,!0,this.pos,this.angle))}beginContact(e){}endContact(e){}addShape(e,n=1,s=.2,i=0,r=!1){m(I(n),"density must be a number"),m(I(s),"friction must be a number"),m(I(i),"restitution must be a number");let a=new b.instance.b2FixtureDef;return a.set_shape(e),a.set_density(n),a.set_friction(s),a.set_restitution(i),a.set_isSensor(r),this.body.CreateFixture(a)}addBox(e=T(1),n=T(),s=0,i,r,a,o){m(D(e),"size must be a Vector2"),m(e.x>0&&e.y>0,"size must be positive"),m(D(n),"offset must be a Vector2"),m(I(s),"angle must be a number");let c=new b.instance.b2PolygonShape;return c.SetAsBox(e.x/2,e.y/2,b.vec2dTo(n),-s),this.addShape(c,i,r,a,o)}addPoly(e,n,s,i,r){m(wt(e),"points must be an array");function a(c){m(3<=c.length&&c.length<=8);let l=b.instance._malloc(c.length*8);for(let d=0,f=0;d>2]=c[d].x,f+=4,b.instance.HEAPF32[l+f>>2]=c[d].y,f+=4;let u=b.instance.wrapPointer(l,b.instance.b2Vec2),h=new b.instance.b2PolygonShape;return h.Set(u,c.length),b.instance._free(l),h}let o=a(e);return this.addShape(o,n,s,i,r)}addRegularPoly(e=1,n=8,s,i,r,a){m(I(e)&&e>0,"diameter must be a positive number"),m(I(n)&&n>2,"sides must be a positive number greater than 2");let o=[],c=e/2;for(let l=n;l--;)o.push(T(c,0).rotate((l+.5)/n*oe*2));return this.addPoly(o,s,i,r,a)}addRandomPoly(e=1,n,s,i,r){m(I(e)&&e>0,"diameter must be a positive number");let a=Yr(3,9),o=[],c=e/2;for(let l=a;l--;)o.push(T(Te(c/2,c*1.5),0).rotate(l/a*oe*2));return this.addPoly(o,n,s,i,r)}addCircle(e=1,n=T(),s,i,r,a){m(I(e)&&e>0,"diameter must be a positive number"),m(D(n),"offset must be a Vector2");let o=new b.instance.b2CircleShape;return o.set_m_p(b.vec2dTo(n)),o.set_m_radius(e/2),this.addShape(o,s,i,r,a)}addEdge(e,n,s,i,r,a){m(D(e),"point1 must be a Vector2"),m(D(n),"point2 must be a Vector2");let o=new b.instance.b2EdgeShape;return o.Set(b.vec2dTo(e),b.vec2dTo(n)),this.addShape(o,s,i,r,a)}addEdgeList(e,n,s,i,r){m(wt(e),"points must be an array");let a=[],o=[];for(let c=0;ce[ht(l,e.length)];for(let l=0;lthis.destroyFixture(e))}getCenterOfMass(){return b.vec2From(this.body.GetWorldCenter())}getLinearVelocity(){return b.vec2From(this.body.GetLinearVelocity())}getAngularVelocity(){return this.body.GetAngularVelocity()}getMass(){return this.body.GetMass()}getInertia(){return this.body.GetInertia()}getIsAwake(){return this.body.IsAwake()}getBodyType(){return this.body.GetType()}getSpeed(){return this.getLinearVelocity().length()}setTransform(e,n){this.pos=e,this.angle=n,this.body.SetTransform(b.vec2dTo(e),-n)}setPosition(e){this.setTransform(e,this.body.GetAngle())}setAngle(e){this.setTransform(b.vec2From(this.body.GetPosition()),e)}setLinearVelocity(e){this.body.SetLinearVelocity(b.vec2dTo(e))}setAngularVelocity(e){this.body.SetAngularVelocity(e)}setLinearDamping(e){this.body.SetLinearDamping(e)}setAngularDamping(e){this.body.SetAngularDamping(e)}setGravityScale(e=1){this.body.SetGravityScale(this.gravityScale=e)}setBullet(e=!0){this.body.SetBullet(e)}setAwake(e=!0){this.body.SetAwake(e)}setBodyType(e){this.body.SetType(e)}setSleepingAllowed(e=!0){this.body.SetSleepingAllowed(e)}setFixedRotation(e=!0){this.body.SetFixedRotation(e)}setCenterOfMass(e){this.setMassData(e)}setMass(e){this.setMassData(void 0,e)}setMomentOfInertia(e){this.setMassData(void 0,void 0,e)}resetMassData(){this.body.ResetMassData()}setMassData(e,n,s){let i=new b.instance.b2MassData;this.body.GetMassData(i),e!==void 0&&i.set_center(b.vec2dTo(e)),n!==void 0&&i.set_mass(n),s!==void 0&&i.set_I(s),this.body.SetMassData(i)}setFilterData(e=0,n=0,s=0){this.getFixtureList().forEach(i=>{let r=i.GetFilterData();r.set_categoryBits(e),r.set_maskBits(65535&~n),r.set_groupIndex(s)})}setSensor(e=!0){this.getFixtureList().forEach(n=>n.SetSensor(e))}applyForce(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyForce(b.vec2dTo(e),b.vec2dTo(n))}applyAcceleration(e,n){n||(n=this.getCenterOfMass()),this.setAwake();let s=e.scale(this.getMass());this.body.ApplyLinearImpulse(b.vec2dTo(s),b.vec2dTo(n))}applyImpulse(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyLinearImpulse(b.vec2dTo(e),b.vec2dTo(n))}applyTorque(e){this.setAwake(),this.body.ApplyTorque(e)}applyAngularAcceleration(e){this.setAwake(),this.body.ApplyAngularImpulse(e*this.getInertia())}applyAngularImpulse(e){this.setAwake(),this.body.ApplyAngularImpulse(e)}hasFixtures(){return!b.isNull(this.body.GetFixtureList())}getFixtureList(){let e=[];for(let n=this.body.GetFixtureList();!b.isNull(n);)e.push(n),n=n.GetNext();return e}hasJoints(){return!b.isNull(this.body.GetJointList())}getJointList(){let e=[];for(let n=this.body.GetJointList();!b.isNull(n);)e.push(n),n=n.get_next();return e}},Ki=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeStatic;super(e,n,s,i,r,o,a)}},Rr=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeKinematic;super(e,n,s,i,r,o,a)}},Mr=class extends Ki{constructor(e){m(e instanceof Ws,"tileLayer must be a TileCollisionLayer"),super(e.pos,e.size),this.tileLayer=e,this.addChild(e)}render(){}buildCollision(e=.2,n=0){this.destroyAllFixtures(),this.pos=this.tileLayer.pos.copy(),this.size=this.tileLayer.size.copy();let s=[],i=(a,o)=>a+o*this.size.x,r=(a,o)=>!s[i(a,o)]&&this.tileLayer.getCollisionData(T(a,o))>0;for(let a=0;ai.fractionr.pos.distanceSquared(e)0,"Tween duration must be > 0"),this.callback=e,this.start=n,this.end=s,this.duration=i,this.life=i,this.ease=r.ease||no.LINEAR,this.useRealTime=!!r.useRealTime,this.paused=!!r.paused,this.thenCallback=void 0,this.loopRemaining=0,at.push(this),e(this.interp(i))}setEase(e){return this.ease=e,this}then(e){return this.thenCallback=e,this.loopRemaining=0,this}loop(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>zl(this),this}pingPong(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>Ul(this),this}pause(){this.paused=!0}resume(){this.paused=!1}restart(){this.life=this.duration,this.paused=!1,at.indexOf(this)<0&&at.push(this),this.callback(this.interp(this.duration))}isActive(){return!this.paused&&at.indexOf(this)>=0}getPercent(){return He(this.duration-this.life,0,this.duration)}getValue(){return this.interp(this.life)}interp(e){let n=this.ease((this.duration-e)/this.duration);return zc(this.start)?this.start.lerp(this.end,n):this.start+(this.end-this.start)*n}stop(){let e=at.indexOf(this);e>=0&&at.splice(e,1),this.thenCallback=void 0}},no={LINEAR:t=>t,POWER:t=>e=>e**t,SINE:t=>1-be(t*(oe/2)),CIRC:t=>1-(1-t*t)**.5,EXPO:t=>t===0?0:2**(10*t-10),BACK:t=>t*t*(2.70158*t-1.70158),ELASTIC:t=>t===0?0:t===1?1:-(2**(10*t-10))*pe((37-40*t)*oe/6),SPRING:t=>1-(pe(oe*(1-t)*(.2+2.5*(1-t)**3))*t**2.2+(1-t))*(1+1.2*t),BOUNCE:t=>{let e=1-t,n;return e<4/11?n=7.5625*e*e:e<8/11?n=7.5625*(e-=6/11)*e+.75:e<10/11?n=7.5625*(e-=9/11)*e+.9375:n=7.5625*(e-=10.5/11)*e+.984375,1-n},IN:t=>t,OUT:t=>e=>1-t(1-e),IN_OUT:t=>no.PIECEWISE(t,no.OUT(t)),PIECEWISE:(...t)=>{let e=t.length;return n=>{let s=n*e-1e-9>>0;return(t[s]((n-s/e)*e)+s)/e}},BEZIER:(t,e,n,s)=>{let i=r=>{let a=1-r,o=3*a*a*r,c=3*a*r*r,l=r**3;return[o*t+c*n+l,o*e+c*s+l]};return r=>{let a=0,o=1;for(let c=0;c<128;c++){let l=(a+o)/2,[u,h]=i(l);if(he(u-r)<1e-5)return h;u=this.size.x||n>=this.size.y?null:this.nodes[e+n*this.size.x]}worldToTile(e){let n=this.tileLayer?this.tileLayer.pos.x:0,s=this.tileLayer?this.tileLayer.pos.y:0;return T(Le(e.x-n),Le(e.y-s))}tileToWorld(e,n){let s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;return T(e+.5+s,n+.5+i)}buildNodeData(){let e=this.size.x,n=this.size.y,s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;for(let r=0;r0&&(c?l>0&&_e(o.posWorld,er,Q(1,0,0,de(.2,l*.05)),this.debugTime):_e(o.posWorld,er,Q(1,0,0,.25),this.debugTime))}}aStarSearch(e,n){m(e&&n,"aStarSearch needs both endpoints"),m(e!==n,"aStarSearch: start and end must differ \u2014 caller should handle trivial case"),m(e.walkable&&n.walkable,"aStarSearch: endpoints must be walkable");let s=[e];e.isOpen=!0;let i=0;for(;s.length>0;){let r=0,a=s[0].f;for(let c=1;cthis.maxLoop)break;o.isOpen=!1,s.splice(r,1),o.isClosed=!0,this.debug&&this.debugTime>0&&_e(o.posWorld,er,Q(1,1,1,.05),this.debugTime);for(let c=-1;c<=1;++c)for(let l=-1;l<=1;++l){if(l===0&&c===0)continue;let u=this.getNode(o.pos.x+l,o.pos.y+c);if(!u||!u.walkable||u.isClosed)continue;let h=1;if(l!==0&&c!==0){let x=this.getNode(o.pos.x+l,o.pos.y);if(!x||!x.walkable)continue;let w=this.getNode(o.pos.x,o.pos.y+c);if(!w||!w.walkable)continue;h=qh}let d=o.g+h+u.cost;if(!u.isOpen)u.isOpen=!0,s.push(u);else if(d>=u.g)continue;u.parent=o,u.g=d;let f=he(n.pos.x-u.pos.x),p=he(n.pos.y-u.pos.y),y=le(f,p)+(Math.SQRT2-1)*de(f,p);u.f=u.g+y*this.heuristicWeight}}return n.parent!==null}getNearestClearNode(e,n=10,s=!0){m(D(e),"worldPos must be a Vector2"),s&&this.buildNodeData();let i=this.tileLayer?this.tileLayer.pos.x:0,r=this.tileLayer?this.tileLayer.pos.y:0,a=Le(e.x-i),o=Le(e.y-r);for(let c=0;c<=n;++c){let l=null,u=0;for(let h=-c;h<=c;++h)for(let d=-c;d<=c;++d){if(c>0&&he(d)!==c&&he(h)!==c)continue;let f=this.getNode(a+d,o+h);if(!f||!f.isClear())continue;let p=f.posWorld.x-e.x,y=f.posWorld.y-e.y,x=p*p+y*y;(!l||x0&&et(i.posWorld,.3,Q(.5,0,.5,.5),this.debugTime),e.splice(n,1),n=le(1,n-1);continue}else if(c===2){this.debug&&this.debugTime>0&&et(i.posWorld,.3,Q(1,0,0,.5),this.debugTime);let f,p;s.pos.y===i.pos.y&&r.pos.x===i.pos.x?(f=s.pos.x,p=r.pos.y):(f=r.pos.x,p=s.pos.y);let y=this.getNode(f,p);if(y&&y.isClear()){e.splice(n,1),n=le(1,n-1);continue}}else if(c===5){this.debug&&this.debugTime>0&&et(i.posWorld,.3,Q(1,1,0,.5),this.debugTime);let f=n>=2?e[n-2]:s,p,y,x,w;l===0||h===0?(p=r.pos.x,y=i.pos.y,x=s.pos.x,w=i.pos.y):(p=i.pos.x,y=r.pos.y,x=i.pos.x,w=s.pos.y);let A=p-f.pos.x,v=y-f.pos.y,_=x-f.pos.x,k=w-f.pos.y,C=A*A+v*v,L=_*_+k*k,V=C0&&et(i.posWorld,.3,Q(0,1,0,.5),this.debugTime),l===h&&u===d){++n;continue}else{let f,p;s.pos.y===r.pos.y?(f=i.pos.x,p=s.pos.y):(f=s.pos.x,p=i.pos.y);let y=this.getNode(f,p);if(y&&y.isClear()){e[n]=y,n=le(1,n-1);continue}}++n}}smoothPathStringPull(e){if(e.length<=2)return;for(let i of e)if(!i.isClear())return;let n=e.slice();e.length=0,e.push(n[0]);let s=0;for(let i=1;i0&&Mt(r.posWorld,e[e.length-1].posWorld,Q(0,0,1,.3),.02,this.debugTime);continue}for(;s=1;--n){let s=e[n-1],i=e[n],r=e[n+1];(i.pos.x-s.pos.x)*(r.pos.y-s.pos.y)===(i.pos.y-s.pos.y)*(r.pos.x-s.pos.x)&&e.splice(n,1)}}isNodeClear(e,n){let s=this.getNode(e,n);return s!==null&&s.isClear()}isLineClear(e,n){m(D(e)&&D(n),"isLineClear needs Vector2 endpoints"),m(this.isNodeClear(e.x,e.y)&&this.isNodeClear(n.x,n.y),"isLineClear endpoints must be in-bounds and clear");let s=n.x-e.x,i=n.y-e.y,r=he(s),a=he(i),o=ft(s),c=ft(i),l=e.x,u=e.y;if(a===r){for(;l!==n.x;){if(l!==e.x&&(!this.isNodeClear(l,u)||!this.isNodeClear(l,u-c))||!this.isNodeClear(l,u+c))return!1;l+=o,u+=c}if(!this.isNodeClear(n.x,n.y-c))return!1}else if(ao.posWorld.copy());if(this.debug&&this.debugTime>0&&a.length>0){for(let o=1;oWh,bootGameHost:()=>$h,default:()=>Hh});var An=class{constructor(e){this._state=(e==null?2654435769:e)>>>0}next(){this._state=this._state+1831565813>>>0;let e=this._state;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}range(e,n){return e+this.next()*(n-e)}reseed(e){this._state=(e==null?2654435769:e)>>>0}},vo=class{constructor(e){this._clock=e||tu(),this._origin=this._clock()}nowMs(){return this._clock()}elapsedMs(){return this._clock()-this._origin}},wo=class{constructor(e){this._time=e,this._subs=new Map}sourceFor(e){let n=this,s=e==null?null:e;return{on(i,r){if(n._assertType(i),typeof r!="function")throw new Error("[HostDevInputBridge] on \u7684 handler \u5FC5\u987B\u662F\u51FD\u6570");let a=n._subs.get(i)||[],o={handler:r,scope:s};return a.push(o),n._subs.set(i,a),{cancel(){let c=n._subs.get(i);if(!c)return;let l=c.indexOf(o);l>=0&&c.splice(l,1)}}},off(i,r){n._assertType(i);let a=n._subs.get(i);if(!a)return;let o=a.findIndex(c=>c.handler===r&&c.scope===s);o>=0&&a.splice(o,1)}}}_emit(e,n){this._assertType(e);let s=n||{},i={type:e,x:typeof s.x=="number"?s.x:0,y:typeof s.y=="number"?s.y:0,key:typeof s.key=="string"?s.key:"",tMs:this._time.nowMs()},r=this._subs.get(e);if(!r||r.length===0)return;let a=r.slice();for(let o of a)try{o.handler(i)}catch(c){on("[host-dev input] \u8F93\u5165 handler \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09type="+e,c)}}disposeScope(e){if(e==null)return 0;let n=0;for(let[s,i]of this._subs){let r=i.filter(a=>a.scope!==e);n+=i.length-r.length,r.length===0?this._subs.delete(s):this._subs.set(s,r)}return n}_subscriptionCount(){let e=0;for(let n of this._subs.values())e+=n.length;return e}_assertType(e){if(!To.has(e))throw new Error("[HostDevInputBridge] \u975E\u6CD5\u8F93\u5165\u4E8B\u4EF6\u7C7B\u578B\uFF1A"+String(e)+"\uFF08\u4EC5\u652F\u6301 "+Array.from(To).join("/")+"\uFF09")}},To=new Set(["pointerdown","pointermove","pointerup","keydown","keyup"]);function ja(t){let e=t||{},n=new vo(e.clock),s=new An(e.seed),i=e.seed==null?2654435769:e.seed>>>0,r=new wo(n),a=typeof e.audioFactory=="function"?e.audioFactory:null,o=null,c=!1,l=typeof e.engineFactory=="function"?e.engineFactory:null,u=null,h=!1,d=new Map,f=0,p=0;function y(){if(o)return o;if(!a)return c||(ko("[host-dev audio] \u672A\u6CE8\u5165 audioFactory\uFF0CgetAudioContext \u8FD4\u56DE null\uFF08P6 \u987B\u5BB9\u9519\u964D\u7EA7\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u5DE5\u5382\uFF09"),c=!0),null;try{o=a()}catch(_){on("[host-dev audio] audioFactory \u629B\u9519\uFF0CgetAudioContext \u964D\u7EA7\u8FD4\u56DE null",_),o=null}return o}function x(){if(u)return u;if(!l)return h||(ko("[host-dev engine] \u672A\u6CE8\u5165 engineFactory\uFF0CgetEngine \u8FD4\u56DE null\uFF08\u63D2\u4EF6\u987B\u5BB9\u9519\u964D\u7EA7\uFF1A\u7C92\u5B50\u9000\u53D7\u63A7\u9762\u81EA\u7BA1/\u5408\u6210\u6838\u9000 vendored/\u6570\u5B66\u9000\u5185\u7F6E\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u80CC\u4E66\uFF09"),h=!0),null;try{u=l()}catch(_){on("[host-dev engine] engineFactory \u629B\u9519\uFF0CgetEngine \u964D\u7EA7\u8FD4\u56DE null",_),u=null}return u}function w(_,k){return{getContext2d(){return e.context2d==null?null:e.context2d},onFrame(L){let V=f++;return d.set(V,L),{cancel(){d.delete(V)}}},getInput(){return r.sourceFor(_)},getAudioContext(){return y()},getEngine(){return x()},time:n,random:k}}let A=w(null,s),v={context:A,tick(_){p+=1;let k=Array.from(d.values());for(let C of k)try{C(_,p)}catch(L){on("[host-dev tick] \u5E27\u56DE\u8C03\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09frame="+p,L)}},frameCount(){return p},inputBridge:r,deriveContextFor(_,k){let C=eu(i,_),L=new An(C);return w(k==null?_:k,L)}};return Object.defineProperty(A,Ao,{value:v,enumerable:!1,writable:!1,configurable:!1}),v}var Ao=Symbol("zaomeng.coreProtocol.contextBundle"),ui=class{constructor(){this._plugins=new Map,this._initOrder=[],this._initErrors=[],this._phase="idle",this._disposed=!1,this._context=void 0,this._pluginContexts=new Map}register(e){if(!e||typeof e!="object")throw new Error("[PluginRegistry] register \u9700\u8981\u4E00\u4E2A\u63D2\u4EF6\u5BF9\u8C61");if(typeof e.name!="string"||e.name.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6\u7F3A\u5C11\u5408\u6CD5 name");if(typeof e.version!="string"||e.version.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11\u5408\u6CD5 version");if(typeof e.init!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11 init \u51FD\u6570");if(e.dispose!=null&&typeof e.dispose!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7684 dispose \u5FC5\u987B\u662F\u51FD\u6570\u6216\u7701\u7565");if(this._plugins.has(e.name))throw new Error("[PluginRegistry] \u63D2\u4EF6\u91CD\u540D\u62D2\u7EDD\uFF1A"+e.name+" \u5DF2\u6CE8\u518C");return this._plugins.set(e.name,e),this}has(e){return this._plugins.has(e)}get(e){return this._plugins.get(e)}list(){return Array.from(this._plugins.keys())}initAll(){if(this._phase==="initialized")return ko("[PluginRegistry] initAll \u91CD\u590D\u8C03\u7528\uFF0C\u5DF2\u5FFD\u7565\uFF08\u5DF2\u5904\u4E8E initialized\uFF09"),this._initResult();if(this._phase==="disposed")throw new Error("[PluginRegistry] \u5DF2 dispose \u7684\u6CE8\u518C\u5668\u4E0D\u53EF\u518D initAll");if(this._context==null)throw new Error("[PluginRegistry] \u672A\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\uFF1A\u8BF7\u5728 initAll() \u4E4B\u524D\u8C03\u7528 useContext(context)\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context); reg.initAll();\uFF09");for(let[e,n]of this._plugins){let s=this._missingDeps(n);if(s.length>0){let r=new Error("[PluginRegistry] \u63D2\u4EF6 "+e+" \u4F9D\u8D56\u7F3A\u5931\uFF1A"+s.join(", ")+"\uFF08\u672A\u6CE8\u518C\uFF09");this._initErrors.push({name:e,error:r}),on("[PluginRegistry] \u8DF3\u8FC7 init\uFF08\u4F9D\u8D56\u7F3A\u5931\uFF0C\u5DF2\u9694\u79BB\uFF09\uFF1A"+e,r);continue}let i=this._contextFor(e);try{n.init(i),this._initOrder.push(e)}catch(r){let a=r instanceof Error?r:new Error(String(r));this._initErrors.push({name:e,error:a}),on("[PluginRegistry] \u63D2\u4EF6 init \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF0C\u4E0D\u8FDE\u5750\uFF09\uFF1A"+e,a)}}return this._phase="initialized",this._initResult()}_contextFor(e){let n=this._pluginContexts.get(e);if(n)return n;let s=this._context&&this._context[Ao],i;return s&&typeof s.deriveContextFor=="function"?i=s.deriveContextFor(e,e):i=this._context,this._pluginContexts.set(e,i),i}disposeAll(){if(this._disposed)return{disposed:[],errors:[]};let e=[],n=[],s=this._context&&this._context[Ao],i=s&&s.inputBridge;for(let r=this._initOrder.length-1;r>=0;r--){let a=this._initOrder[r],o=this._plugins.get(a);if(o&&typeof o.dispose=="function")try{o.dispose(),e.push(a)}catch(c){let l=c instanceof Error?c:new Error(String(c));n.push({name:a,error:l}),on("[PluginRegistry] \u63D2\u4EF6 dispose \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,l)}if(i&&typeof i.disposeScope=="function")try{i.disposeScope(a)}catch(c){on("[PluginRegistry] \u56DE\u6536\u63D2\u4EF6\u8F93\u5165\u8BA2\u9605\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,c)}}return this._disposed=!0,this._phase="disposed",{disposed:e,errors:n}}useContext(e){if(this._phase!=="idle")throw new Error("[PluginRegistry] useContext \u5FC5\u987B\u5728 initAll() \u4E4B\u524D\u8C03\u7528\uFF08\u5F53\u524D\u9636\u6BB5\uFF1A"+this._phase+"\uFF09\u3002\u8BF7\u5728\u4EFB\u4F55 initAll/disposeAll \u4E4B\u524D\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\u3002");if(e==null||typeof e!="object")throw new Error("[PluginRegistry] useContext \u9700\u8981\u4E00\u4E2A\u53D7\u63A7\u4E0A\u4E0B\u6587\u5BF9\u8C61\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context);\uFF09");return this._context=e,this}_missingDeps(e){return!Array.isArray(e.dependencies)||e.dependencies.length===0?[]:e.dependencies.filter(n=>!this._plugins.has(n))}_initResult(){return{ok:this._initErrors.length===0,initialized:this._initOrder.slice(),errors:this._initErrors.slice()}}};function eu(t,e){let n=2166136261,s=16777619,i=t>>>0;for(let a=0;a<32;a+=8){let o=i>>>a&255;n^=o,n=Math.imul(n,s)>>>0}let r=String(e);for(let a=0;a>>0,n^=o>>>8&255,n=Math.imul(n,s)>>>0}return n>>>0}function tu(){if(typeof globalThis!="undefined"&&globalThis.performance&&typeof globalThis.performance.now=="function")return()=>globalThis.performance.now();if(typeof process!="undefined"&&process.hrtime&&typeof process.hrtime.bigint=="function"){let t=process.hrtime.bigint();return()=>Number(process.hrtime.bigint()-t)/1e6}return()=>Date.now()}function on(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function ko(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Kh=Object.freeze(Array.from(To)),Ja="core-protocol-v0";var Na=Object.freeze(["t_boot","t_plugins_ready","t_game_init","t_first_paint","t_input_bound","t_game_start"]),Co=Na.reduce((t,e,n)=>(t[e]=n,t),Object.create(null)),nu=new Set(Na);function _o(t){let e=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}var za=_o("runtime-probe::seed::v1");function di(t){return t===null||typeof t!="object"?JSON.stringify(t):Array.isArray(t)?"["+t.map(di).join(",")+"]":"{"+Object.keys(t).sort().map(n=>JSON.stringify(n)+":"+di(t[n])).join(",")+"}"}function Ua(t){let e=di(t.extra==null?null:t.extra),n=di(Array.isArray(t.pluginSet)?t.pluginSet:[]);return["seq="+t.seq,"anchor="+t.anchor,"tMono="+t.tMono,"buildSha="+(t.buildSha||""),"pluginSet="+n,"extra="+e].join("|")}function su(t){return Math.round(t*1e3)/1e3}function iu(t){if(!Array.isArray(t))return{ok:!1,reason:"records_not_array"};let e=za,n=-1;for(let s=0;stypeof _=="string").slice().sort():[],i=typeof e.sink=="function"?e.sink:null,r=e.autoBoot!==!1,a=typeof e.inputAnchorType=="string"?e.inputAnchorType:"pointerdown",o=()=>0,c=!1,l=0,u=za,h=[],d=new Set,f=-1,p=null,y=!1,x=!1,w=!1;function A(_,k){let C=null;if(!nu.has(_))C="unknown_anchor";else{d.has(_)&&(C=C?C+";duplicate_anchor":"duplicate_anchor");let V=Co[_];V_.time.nowMs(),c=!0,r&&!x&&A("t_boot",{auto:!0}),p=_.getInput().on(a,k=>{y||(y=!0,A("t_input_bound",{firstInput:!0,type:k.type}))}),A("t_input_bound",{stage:"registered",type:a})},dispose(){w||(p&&(p.cancel(),p=null),w=!0)},mark:A,getRecords(){return h.map(_=>({..._}))},toJSONL(){return h.map(_=>JSON.stringify(_)).join(`
+`)},verify(){return iu(h)}}}function ou(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function qa(t){let e=t.LJS,n=t.engineMath,s=t.engineMode,i=t.recHook||(()=>{});if(s!=="real")return null;let r=n;return{math:{lerp:(o,c,l)=>(i("math.lerp"),r.lerp(o,c,l)),smoothStep:o=>(i("math.smoothStep"),r.smoothStep(o)),easing:Object.fromEntries(Object.keys(r.easing).map(o=>[o,c=>(i("math.easing."+o),r.easing[o](c))]))},particles:{spawnEmitter(o){i("particles.spawnEmitter");let c=e.screenToWorld(e.vec2(o.pos.x,o.pos.y)),l=e.cameraScale,u=o.emitTime!=null?o.emitTime:o.count!=null?1/60:0,h=o.emitRate!=null?o.emitRate:o.count!=null?o.count*60:100,d=(o.speed!=null?o.speed:0)/l/60,f=o.damping!=null?o.damping:1,p=o.colorStart||{r:1,g:1,b:1,a:1},y=o.colorEnd||{r:1,g:1,b:1,a:0},x=e.rgb(p.r,p.g,p.b,p.a),w=e.rgb(y.r,y.g,y.b,y.a),A=new e.ParticleEmitter(c,o.angle!=null?o.angle:0,(o.emitSize!=null?o.emitSize:0)/l,u,h,o.coneAngle!=null?o.coneAngle:Math.PI,void 0,x,x,w,w,o.particleTime!=null?o.particleTime:.5,(o.sizeStart!=null?o.sizeStart:6)/l,(o.sizeEnd!=null?o.sizeEnd:0)/l,d,0,f,1,o.gravityScale!=null?o.gravityScale:0,Math.PI,.1,0,!1,o.additive!=null?o.additive:!1,!0);return{isActive(){return A.isActive()},stop(){A.destroyed||A.destroy(!0)}}}},audio:{synth:{synthSfx:o=>{i("audio.synth.synthSfx");try{return e.zzfxG(...o)}catch(c){return console.error("[host][engine-audio] zzfxG \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(c&&c.message?c.message:c)),null}},synthSong:(o,c,l,u)=>{i("audio.synth.synthSong");try{return e.zzfxM(o,c,l,u)}catch(h){return console.error("[host][engine-audio] zzfxM \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(h&&h.message?h.message:h)),null}}}}}}function bt(t){return t<0?0:t>1?1:t}function Wa(t){let e=t.Ease,n=e.POWER(2),s=e.POWER(3),i=e.OUT(n),r=e.IN_OUT(n),a=e.OUT(s),o=e.IN_OUT(s),c=e.OUT(e.BACK),l=e.OUT(e.ELASTIC);return{lerp:(u,h,d)=>t.lerp(u,h,d),smoothStep:u=>t.smoothStep(u),easing:{linear:u=>e.LINEAR(bt(u)),quadIn:u=>n(bt(u)),quadOut:u=>i(bt(u)),quadInOut:u=>r(bt(u)),cubicIn:u=>s(bt(u)),cubicOut:u=>a(bt(u)),cubicInOut:u=>o(bt(u)),backIn:u=>e.BACK(bt(u)),backOut:u=>c(bt(u)),elasticIn:u=>e.ELASTIC(bt(u)),elasticOut:u=>l(bt(u))}}}var rn=2,fi=1/60;async function Ha(t){let e=t.canvas,n=t.statusEl||null,s=t.engine,i=t.seed>>>0,r=t.mode||"play",a=t.engineMode||"real",o=t.viewport.w,c=t.viewport.h,l=t.factory,u=t.buildFactoryOpts||(()=>{}),h=t.plugins||{},d=t.registerOrder||Object.values(h),f=t.onReady||(()=>{}),p=t.recHook||(()=>{});function y(B){n&&(n.textContent=B)}let x=[];window.addEventListener("error",B=>x.push({type:"error",message:String(B&&B.message||B)})),window.addEventListener("unhandledrejection",B=>x.push({type:"unhandledrejection",message:String(B&&B.reason&&B.reason.message||B&&B.reason||B)}));let w=null,A=!1;function v(){if(!A)return null;if(w)return w;let B=window.AudioContext||window.webkitAudioContext;return B?(w=new B,w):null}let _=0,k=null,C=null,L=null,V=null,ae=[],O={},S=null;function P(B,ye){try{L&&L.mark(B,ye)}catch(G){x.push({type:"mark",message:String(G&&G.message||G)})}}function R(){C&&typeof C._refreshChecklist=="function"&&C._refreshChecklist(O)}async function M(B,ye){k=ja({context2d:B,seed:i,audioFactory:v,clock:()=>_,engineFactory:()=>qa({LJS:a==="real"?s:null,engineMath:a==="real"?Wa(s):null,engineMode:a,recHook:p})});let G=new ui;for(let N of d)G.register(N);G.useContext(k.context),V=G.initAll(),ae=G.list().concat(["runtime-probe"]),L=Va({pluginSet:ae,inputAnchorType:"pointerdown",autoBoot:!0});let F=k.deriveContextFor("runtime-probe","runtime-probe");P("t_boot",{by:"game-host",stage:"pre-init",engineMode:a}),P("t_plugins_ready",{initialized:V.initialized.length,ok:V.ok});let J=u(k.context,{bundle:k,plugins:h,getRealAudioCtx:()=>w});C=l(J),await C.init({ctx:k.context,mainContext:B,canvas:ye(),seed:i}),S=C&&typeof C._forensicsView=="function"?C._forensicsView():null,P("t_game_init",{hasForensics:!!S}),X(),P("t_first_paint",{frame:k.frameCount()});try{L.init(F)}catch(N){x.push({type:"probe-init",message:String(N&&N.message||N)})}P("t_game_start",{mode:r,engineMode:a}),R(),f(xe,{bundle:k,game:C,probe:L,checklist:O,uncaught:x,pluginSet:ae,initRes:V,getGameForensics:()=>S,mark:P,stepOneFrame:X})}let j=null;function X(B){let ye=typeof B=="number"?B:fi;C&&(_+=ye*1e3,C.update(ye),a==="stub"&&j&&C.render(j),R())}function ee(B){for(let ye=0;ye{}),C&&typeof C._onAudioUnlock=="function"&&C._onAudioUnlock()}let xe={seed:i,mode:r,engineMode:a,protocol:Ja,frameCount:()=>k?k.frameCount():0,stepFrames:ee,startRaf:()=>$n(),stopRaf:()=>jt(),tap(B,ye){K(),k&&(k.inputBridge._emit("pointerdown",{x:B,y:ye}),k.inputBridge._emit("pointerup",{x:B,y:ye}))},do(B){C&&typeof C._handleAction=="function"&&C._handleAction(B)},state:()=>S?S.state():{phase:"booting"}};function je(B){let ye=k.inputBridge;function G(F,J){let N=B.getBoundingClientRect();return{x:(F-N.left)/N.width*o,y:(J-N.top)/N.height*c}}B.addEventListener("pointerdown",F=>{K(),ye._emit("pointerdown",G(F.clientX,F.clientY))}),B.addEventListener("pointermove",F=>{ye._emit("pointermove",G(F.clientX,F.clientY))}),B.addEventListener("pointerup",F=>{ye._emit("pointerup",G(F.clientX,F.clientY))})}let ve=0,Bt=!1,dt=0;function gt(B){if(!Bt)return;dt===0&&(dt=B);let ye=(B-dt)/1e3;dt=B,ye>.05&&(ye=.05),X(ye),ve=window.requestAnimationFrame(gt)}function $n(){a==="stub"&&(Bt||(Bt=!0,dt=0,ve=window.requestAnimationFrame(gt)))}function jt(){Bt=!1,ve&&window.cancelAnimationFrame(ve),ve=0}function Yn(B){B.width=o*rn,B.height=c*rn,B.style.width=o+"px",B.style.height=c+"px";let ye=B.getContext("2d",{willReadFrequently:!0});return ye.setTransform(rn,0,0,rn,0,0),ye}async function Ss(){let B=Yn(e);return j=B,await M(B,()=>e),je(e),r==="evidence"?y(`evidence \u5C31\u7EEA seed=${i} \xB7 \u7528 host \u9A71\u52A8\uFF08stepFrames/tap\uFF09`):(y(`seed=${i} \xB7 \u70B9\u5F00\u59CB\uFF08\u9996\u6B21\u70B9\u51FB\u5F00\u58F0\uFF09`),$n()),xe}let tn=()=>{},nn=()=>{};function sn(){window.__gameHostEngineInitFired=!0}function Xn(){tn()}function Kn(){}function go(){nn()}function bo(){}async function xo(B){await M(B,()=>s.mainCanvas),je(s.mainCanvas),tn=()=>{C&&(_+=fi*1e3,C.update(fi))},nn=()=>{if(C){B.save(),B.setTransform(rn,0,0,rn,0,0);try{B.imageSmoothingEnabled=!1}catch{}C.render(B),B.restore()}},s.mainCanvas&&(s.mainCanvas.id="game-engine"),window.__engine={frame(){return s.frame},time(){return s.time},timeReal(){return s.timeReal},paused(){return s.paused},timeScale(){return s.timeScale},snapshot(){return{frame:s.frame,time:s.time,timeReal:s.timeReal,paused:s.paused,timeScale:s.timeScale}}},y(`engine RAF running \xB7 seed=${i} engine=real`)}if(a!=="real")return await Ss();if(!s){let B="real \u901A\u9053\u672A\u6CE8\u5165\u5F15\u64CE\uFF08opts.engine \u7F3A\u5931\uFF09\uFF1A\u8BF7\u7ECF entry \u5305\u88C5\u5C42\u542F\u52A8\uFF08host \u4E0D\u76F4\u63A5 import \u5F15\u64CE\uFF0CQ4/Option C\uFF09";throw y("ENGINE INJECT MISSING: "+B),new Error(B)}s.setGLEnable(!1),s.setShowSplashScreen(!1),s.setDebugWatermark(!1),s.setCanvasClearColor(s.BLACK),s.setCanvasFixedSize(s.vec2(o*rn,c*rn));let vs=document.createElement("div");return vs.id="engine-root",document.body.appendChild(vs),await s.engineInit(sn,Xn,Kn,go,bo,[],vs).then(()=>xo(s.mainContext)).catch(B=>{throw window.__gameHostBootError=String(B&&B.message||B),y("ENGINE INIT FAILED: "+window.__gameHostBootError),B}),xe}function ru(){return{hit:!1,depth:0,nx:0,ny:0}}var Eo=class{constructor(e){let n=e||{},s=typeof n.cellSize=="number"&&n.cellSize>0?n.cellSize:64;this._cellSize=s,this._cells=new Map,this._entries=new Map,this._seq=0}get size(){return this._entries.size}_cellRange(e){let n=this._cellSize,s=Math.floor((e.x-e.hw)/n),i=Math.floor((e.x+e.hw)/n),r=Math.floor((e.y-e.hh)/n),a=Math.floor((e.y+e.hh)/n);return{cx0:s,cy0:r,cx1:i,cy1:a}}insert(e,n){this._entries.has(e)&&this.remove(e);let{cx0:s,cy0:i,cx1:r,cy1:a}=this._cellRange(n),o=[];for(let l=i;l<=a;l++)for(let u=s;u<=r;u++){let h=u+","+l,d=this._cells.get(h);d||(d=new Set,this._cells.set(h,d)),d.add(e),o.push(h)}let c={x:n.x,y:n.y,hw:n.hw,hh:n.hh};this._entries.set(e,{id:e,box:c,seq:this._seq++,cells:o})}remove(e){let n=this._entries.get(e);if(!n)return!1;for(let s of n.cells){let i=this._cells.get(s);i&&(i.delete(e),i.size===0&&this._cells.delete(s))}return this._entries.delete(e),!0}query(e){let{cx0:n,cy0:s,cx1:i,cy1:r}=this._cellRange(e),a=new Set;for(let o=s;o<=r;o++)for(let c=n;c<=i;c++){let l=this._cells.get(c+","+o);if(l)for(let u of l)a.add(u)}return this._collect(a)}queryPoint(e,n){let s=this._cellSize,i=Math.floor(e/s),r=Math.floor(n/s),a=this._cells.get(i+","+r);return a?this._collect(new Set(a)):[]}clear(){this._cells.clear(),this._entries.clear(),this._seq=0}_collect(e){let n=[];for(let s of e){let i=this._entries.get(s);i&&n.push(i)}return n.sort((s,i)=>s.seq-i.seq),n.map(s=>({id:s.id,box:s.box}))}};function $a(t,e){let n=t.x-e.x,s=t.y-e.y,i=t.hw+e.hw-Math.abs(n),r=t.hh+e.hh-Math.abs(s);return i<=1e-9||r<=1e-9?ru():i0?e.fixedStep:1/120;return{gx:n.x||0,gy:n.y||0,fixedStep:s}}function Ka(t,e,n,s){t.vx+=e*s,t.vy+=n*s,t.px+=t.vx*s,t.py+=t.vy*s}function au(t,e,n){let{gx:s,gy:i,fixedStep:r}=Qa(n),a={px:t.px,py:t.py,vx:t.vx,vy:t.vy},o=e>0?e:0;for(;o>=r-1e-12;)Ka(a,s,i,r),o-=r;return o>1e-12&&Ka(a,s,i,o),a}var hi=class{constructor(e,n){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy};let s=Qa(n);this._gx=s.gx,this._gy=s.gy,this._fixedStep=s.fixedStep}get state(){return{px:this._s.px,py:this._s.py,vx:this._s.vx,vy:this._s.vy}}step(e){let n=au(this._s,e,{gravity:{x:this._gx,y:this._gy},fixedStep:this._fixedStep});return this._s=n,this.state}reset(e){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy}}};function Za(t,e,n,s){let i=n.mass==null?1:n.mass,r=n.stiffness,a=n.damping,o=t.x,c=t.v,l=s>0?s:0;if(l<=1e-12)return{x:o,v:c};let u=i>1e-12?i:1e-12,h=Math.sqrt(Math.max(0,r)/u),d=a/u,f=h>1e-12?.2/h:l,p=d>1e-12?.5/d:l,y=Math.max(1e-12,Math.min(f,p)),x=Math.ceil(l/y);(!Number.isFinite(x)||x<1)&&(x=1),x>4096&&(x=4096);let w=l/x;for(let A=0;A1?1:t}var lu=t=>(t=$e(t),t*t),uu=t=>(t=$e(t),1-(1-t)*(1-t)),du=t=>(t=$e(t),t<.5?2*t*t:1-Math.pow(-2*t+2,2)/2),fu=t=>(t=$e(t),t*t*t),hu=t=>{t=$e(t);let e=1-t;return 1-e*e*e},pu=t=>(t=$e(t),t<.5?4*t*t*t:1-Math.pow(-2*t+2,3)/2),nc=2*Math.PI/3,tc=2*Math.PI/4.5,mu=t=>(t=$e(t),t===0?0:t===1?1:-Math.pow(2,10*t-10)*Math.sin((t*10-10.75)*nc)),yu=t=>(t=$e(t),t===0?0:t===1?1:Math.pow(2,-10*t)*Math.sin((t*10-.75)*nc)+1),gu=t=>(t=$e(t),t===0?0:t===1?1:t<.5?-(Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*tc))/2:Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*tc)/2+1),yi=1.70158,pi=yi*1.525,sc=yi+1,bu=t=>(t=$e(t),sc*t*t*t-yi*t*t),xu=t=>{t=$e(t);let e=t-1;return 1+sc*e*e*e+yi*e*e},Su=t=>(t=$e(t),t<.5?Math.pow(2*t,2)*((pi+1)*2*t-pi)/2:(Math.pow(2*t-2,2)*((pi+1)*(t*2-2)+pi)+2)/2),vu=t=>$e(t),Po=Object.freeze({linear:vu,quadIn:lu,quadOut:uu,quadInOut:du,cubicIn:fu,cubicOut:hu,cubicInOut:pu,elasticIn:mu,elasticOut:yu,elasticInOut:gu,backIn:bu,backOut:xu,backInOut:Su}),Mo=Po,wu=["linear","quadIn","quadOut","quadInOut","cubicIn","cubicOut","cubicInOut","elasticIn","elasticOut","elasticInOut","backIn","backOut","backInOut"];function Tu(t){let e=t&&t.easing;if(!e)return Po;let n=i=>typeof e[i]=="function"?r=>e[i]($e(r)):Po[i],s={};for(let i of wu)s[i]=n(i);return Object.freeze(s)}var Ro=class{constructor(e,n,s){let i=s||{};this._time=n,this._windowMs=typeof i.windowMs=="number"&&i.windowMs>0?i.windowMs:120;let r=Array.isArray(i.types)&&i.types.length>0?i.types:cu;this._records=new Map,this._subs=[],this._disposed=!1;for(let a of r){this._records.set(a,null);let o=e.on(a,c=>{this._records.set(a,c.tMs)});this._subs.push(o)}}consume(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs?(this._records.set(e,null),!0):(this._records.set(e,null),!1)}peek(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs}clear(){for(let e of this._records.keys())this._records.set(e,null)}dispose(){if(!this._disposed){for(let e of this._subs)try{e.cancel()}catch(n){}this._subs=[],this._disposed=!0}}};var mi=class{constructor(e,n){let s=n||{};this._time=e,this._windowMs=typeof s.windowMs=="number"&&s.windowMs>0?s.windowMs:500,this._maxCount=typeof s.maxCount=="number"&&s.maxCount>0?s.maxCount:1/0,this._count=0,this._lastHitAt=null}hit(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt!=null&&n-this._lastHitAt<=this._windowMs&&this._count>0?this._count=Math.min(this._count+1,this._maxCount):this._count=1,this._lastHitAt=n,this._count}getCount(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt==null||n-this._lastHitAt>this._windowMs?0:this._count}reset(){this._count=0,this._lastHitAt=null}};function ic(t){let e=t||{},n=null,s=null,i=!1;return{name:"gamefeel",version:"1.0.0",dependencies:[],get inputBuffer(){return n},get easing(){return Tu(s)},init(a){let o=a.getInput();n=new Ro(o,a.time,{windowMs:e.inputBufferMs,types:e.inputTypes});let c=a.getEngine();s=c?c.math:null},dispose(){i||(n&&(n.dispose(),n=null),s=null,i=!0)}}}function gi(t,e){let n=e<0?0:e>1?1:e;switch(t&&t.kind){case"constant":return t.value;case"linear":return t.from+(t.to-t.from)*n;case"easeInOut":{let s=n*n*(3-2*n);return t.from+(t.to-t.from)*s}case"decay":{let s=t.power==null?2:t.power,i=Math.pow(1-n,s);return t.to+(t.from-t.to)*i}default:return 0}}var Au=Object.freeze({burst:Object.freeze({mode:"burst",count:24,angle:0,spread:Math.PI,speedMin:80,speedMax:160,lifeMin:.4,lifeMax:.8,gravity:0,drag:0,sizeCurve:{kind:"decay",from:6,to:0,power:1.5},alphaCurve:{kind:"linear",from:1,to:0}}),trail:Object.freeze({mode:"continuous",rate:60,angle:Math.PI,spread:.25,speedMin:20,speedMax:50,lifeMin:.2,lifeMax:.5,gravity:0,drag:1.5,sizeCurve:{kind:"easeInOut",from:4,to:0},alphaCurve:{kind:"decay",from:.8,to:0,power:2}}),drift:Object.freeze({mode:"continuous",rate:12,angle:Math.PI/2,spread:.6,speedMin:10,speedMax:30,lifeMin:1.5,lifeMax:3,gravity:8,drag:.5,sizeCurve:{kind:"constant",value:3},alphaCurve:{kind:"decay",from:.7,to:0,power:1}})});function ku(t){let e=Au[t];return e?Lo(e):null}function Lo(t){let e={};for(let n of Object.keys(t)){let s=t[n];e[n]=s&&typeof s=="object"?Lo(s):s}return e}function Cu(t,e,n){let s=t.mode==="continuous";return{pos:{x:e,y:n},angle:t.angle,coneAngle:t.spread,emitSize:0,emitTime:s?0:1/60,emitRate:s?t.rate||0:void 0,count:s?void 0:t.count||0,particleTime:(t.lifeMin+t.lifeMax)/2,speed:(t.speedMin+t.speedMax)/2,gravityScale:t.gravity||0,damping:t.drag!=null?1-t.drag/60:1,sizeStart:gi(t.sizeCurve,0),sizeEnd:gi(t.sizeCurve,1),colorStart:{r:1,g:1,b:1,a:gi(t.alphaCurve,0)},colorEnd:{r:1,g:1,b:1,a:gi(t.alphaCurve,1)},additive:!1}}function bi(t){let e=t||{},n=null,s=null,i=null,r=new Map,a=0,o={isActive(){return!1},stop(){}},c=0,l=1,u=0,h=0,d=0,f={x:0,y:0,remain:0,dur:0,amplitude:0,frequency:0,_phase:0},p={alpha:0,remain:0,dur:0,peak:0},y={scale:1,remain:0,dur:0,amplitude:0,frequency:0},x=!1;function w(k){if(u>0)if(u-=k,u<=0)u=0,l=1;else{let C=h>0?1-u/h:1;l=d+(1-d)*C}if(f.remain>0)if(f.remain-=k,f.remain<=0)f.remain=0,f.x=0,f.y=0;else{let C=f.remain/f.dur,L=f.amplitude*C;f._phase+=f.frequency*k*Math.PI*2,f.x=Math.sin(f._phase)*L,f.y=Math.cos(f._phase*1.3)*L}if(p.remain>0&&(p.remain-=k,p.remain<=0?(p.remain=0,p.alpha=0):p.alpha=p.peak*(p.remain/p.dur)),y.remain>0)if(y.remain-=k,y.remain<=0)y.remain=0,y.scale=1;else{let C=y.remain/y.dur,L=(1-C)*y.frequency*Math.PI*2;y.scale=1+Math.sin(L)*y.amplitude*C}}function A(k){c+=1,w(k)}function v(k){let C=k!==void 0?k:n?n.getContext2d():null;if(C&&p.alpha>0){C.globalAlpha=p.alpha,C.fillStyle="#ffffff";let L=C.canvas?C.canvas.width:0,V=C.canvas?C.canvas.height:0;C.fillRect(0,0,L,V),C.globalAlpha=1}}return{name:"particles-juice",version:"1.0.0",dependencies:[],init(k){var C;n=k,i=((C=k.getEngine())==null?void 0:C.particles)||null,typeof e.seed=="number"&&k.random.reseed(e.seed),e.autoStep!==!1&&(s=k.onFrame(L=>{A(L)}))},dispose(){x||(s&&(s.cancel(),s=null),r.forEach(k=>{try{k.stop()}catch{}}),r.clear(),l=1,u=0,f.remain=0,f.x=0,f.y=0,p.remain=0,p.alpha=0,y.remain=0,y.scale=1,x=!0)},spawnEmitter(k,C,L,V){let ae=typeof k=="string"?ku(k):Lo(k);if(!ae)return-1;V&&(ae=Object.assign(ae,V));let O=a++;if(!i)return r.set(O,o),O;let S=i.spawnEmitter(Cu(ae,C,L));return r.set(O,S),O},stopEmitter(k){let C=r.get(k);if(C)try{C.stop()}catch{}},step(k){A(k)},render(k){v(k)},particleCount(){return 0},emitterCount(){let k=0;for(let C of r.values())C.isActive()&&(k+=1);return k},hitStop(k,C){h=Math.max(0,k),u=h,d=C==null?0:Math.max(0,Math.min(1,C)),l=h>0?d:1},getTimeScale(){return l},shakeScreen(k,C,L){f.dur=Math.max(0,k),f.remain=f.dur,f.amplitude=Math.max(0,C),f.frequency=L==null?30:L,f._phase=0,f.x=0,f.y=0},getShakeOffset(){return{x:f.x,y:f.y}},flashScreen(k,C){p.dur=Math.max(0,k),p.remain=p.dur,p.peak=C==null?.8:Math.max(0,Math.min(1,C)),p.alpha=p.dur>0?p.peak:0},getFlashAlpha(){return p.alpha},pulseScale(k,C,L){y.dur=Math.max(0,k),y.remain=y.dur,y.amplitude=C==null?.2:C,y.frequency=L==null?4:L,y.scale=1},getPulseScale(){return y.scale},juiceSnapshot(){return{timeScale:l,shake:{x:f.x,y:f.y},flashAlpha:p.alpha,pulseScale:y.scale}},probe(){return{particles:0,emitters:r.size,dropped:0,steps:c,disposed:x}}}}function oc(t){let e=ke(t.r)/255,n=ke(t.g)/255,s=ke(t.b)/255,i=Math.max(e,n,s),r=Math.min(e,n,s),a=(i+r)/2,o=0,c=0,l=i-r;return l>1e-12&&(c=a>.5?l/(2-i-r):l/(i+r),i===e?o=(n-s)/l%6:i===n?o=(s-e)/l+2:o=(e-n)/l+4,o*=60,o<0&&(o+=360)),{h:o,s:c,l:a}}function rc(t){let e=(t.h%360+360)%360,n=an(t.s),s=an(t.l);if(n<1e-12){let o=Math.round(s*255);return{r:o,g:o,b:o}}let i=s<.5?s*(1+n):s+n-s*n,r=2*s-i,a=e/360;return{r:Math.round(Oo(r,i,a+1/3)*255),g:Math.round(Oo(r,i,a)*255),b:Math.round(Oo(r,i,a-1/3)*255)}}function Oo(t,e,n){let s=n;return s<0&&(s+=1),s>1&&(s-=1),s<1/6?t+(e-t)*6*s:s<1/2?e:s<2/3?t+(e-t)*(2/3-s)*6:t}function ke(t){return t<0?0:t>255?255:t}function an(t){return t<0?0:t>1?1:t}function Go(t,e){let n=Eu(t.from,e);if(n>=0&&n({r:ke(o.r),g:ke(o.g),b:ke(o.b)})),to:r}}function Io(t,e,n){return t+(e-t)*n}function jo(t,e){let n=oc(t),s=n.h+(e.hue||0),i=an(n.s*(e.sat==null?1:e.sat)),r=an(n.l*(e.light==null?1:e.light));return rc({h:s,s:i,l:r})}var Ru=Object.freeze([Object.freeze([0,8,2,10]),Object.freeze([12,4,14,6]),Object.freeze([3,11,1,9]),Object.freeze([15,7,13,5])]);function ac(t){let e=t||{},n=null,s=!1,i={vignette:{enabled:Do(e.vignette&&e.vignette.enabled,!1),strength:Fo(e.vignette&&e.vignette.strength,.5)},dither:{enabled:Do(e.dither&&e.dither.enabled,!1),strength:Fo(e.dither&&e.dither.strength,.5)},scanline:{enabled:Do(e.scanline&&e.scanline.enabled,!1),strength:Fo(e.scanline&&e.scanline.strength,.5)}};function r(o){let c=o!==void 0?o:n?n.getContext2d():null;if(!c)return;let l=c.canvas?c.canvas.width:0,u=c.canvas?c.canvas.height:0;if(i.vignette.enabled&&i.vignette.strength>0&&l>0&&u>0){let h=c.createRadialGradient(l/2,u/2,Math.min(l,u)*.25,l/2,u/2,Math.max(l,u)*.75);h.addColorStop(0,"rgba(0,0,0,0)"),h.addColorStop(1,"rgba(0,0,0,"+i.vignette.strength.toFixed(3)+")"),c.fillStyle=h,c.fillRect(0,0,l,u)}if(i.scanline.enabled&&i.scanline.strength>0&&l>0&&u>0){c.fillStyle="rgba(0,0,0,"+(i.scanline.strength*.5).toFixed(3)+")";for(let h=0;h0&&l>0&&u>0&&typeof c.getImageData=="function"&&typeof c.putImageData=="function"){let h=c.getImageData(0,0,l,u);Mu(h,i.dither.strength),c.putImageData(h,0,0)}}return{name:"palette-post",version:"1.0.0",dependencies:[],init(o){n=o},dispose(){s||(n=null,s=!0)},applyPaletteMap(o,c){return Go(o,c)},applyPaletteMapToBuffer(o,c){return _u(o,c)},lerpPaletteMap(o,c,l){return Bo(o,c,l)},shiftHsl(o,c){return jo(o,c)},rgbToHsl(o){return oc(o)},hslToRgb(o){return rc(o)},setPost(o){if(o)for(let c of["vignette","dither","scanline"])o[c]&&(typeof o[c].enabled=="boolean"&&(i[c].enabled=o[c].enabled),typeof o[c].strength=="number"&&(i[c].strength=an(o[c].strength)))},getPost(){return{vignette:{enabled:i.vignette.enabled,strength:i.vignette.strength},dither:{enabled:i.dither.enabled,strength:i.dither.strength},scanline:{enabled:i.scanline.enabled,strength:i.scanline.strength}}},renderPost(o){r(o)},probe(){return{disposed:s,post:this.getPost()}}}}function Mu(t,e){let n=an(e);if(n<=0)return t;let{data:s,width:i}=t,a=255/(Math.max(2,Math.round(16-n*14))-1);for(let o=0;o+3>2)%i,l=Math.floor((o>>2)/i),u=(Ru[l&3][c&3]/16-.5)*a;for(let h=0;h<3;h++){let d=s[o+h]+u,f=Math.round(d/a)*a;s[o+h]=f<0?0:f>255?255:f}}return t}function Do(t,e){return typeof t=="boolean"?t:e}function Fo(t,e){return typeof t=="number"?an(t):e}var No=Object.freeze({blip:Object.freeze({name:"blip",params:Object.freeze([.6,0,880,0,.03,.06,1,1.5])}),thud:Object.freeze({name:"thud",params:Object.freeze([.8,0,90,0,.04,.18,0,1,0,0,0,0,0,4])}),chime:Object.freeze({name:"chime",params:Object.freeze([.5,0,660,.02,.12,.3,1,2])})}),cc=Object.keys(No);function Lu(t){let e=[];return t==null||typeof t!="object"?{ok:!1,errors:["song \u5FC5\u987B\u662F\u5BF9\u8C61"]}:(!Array.isArray(t.instruments)||t.instruments.length===0?e.push("instruments \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.instruments.forEach((n,s)=>{(!Array.isArray(n)||n.some(i=>typeof i!="number"||!Number.isFinite(i)))&&e.push(`instruments[${s}] \u5FC5\u987B\u662F\u6709\u9650\u6570\u5B57\u6570\u7EC4\uFF08ZzFX \u53C2\u6570\u5305\uFF09`)}),!Array.isArray(t.patterns)||t.patterns.length===0?e.push("patterns \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.patterns.forEach((n,s)=>{if(!Array.isArray(n)||n.length===0){e.push(`patterns[${s}] \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF08\u81F3\u5C11\u4E00\u4E2A\u58F0\u90E8\u901A\u9053\uFF09`);return}n.forEach((i,r)=>{if(!Array.isArray(i)||i.length<2){e.push(`patterns[${s}][${r}] \u901A\u9053\u81F3\u5C11\u542B [\u4E50\u5668\u7D22\u5F15, \u58F0\u50CF]`);return}if(i.some(c=>typeof c!="number"||!Number.isFinite(c))){e.push(`patterns[${s}][${r}] \u901A\u9053\u5FC5\u987B\u5168\u4E3A\u6709\u9650\u6570\u5B57`);return}let a=i[0]|0;Array.isArray(t.instruments)&&(a<0||a>=t.instruments.length)&&e.push(`patterns[${s}][${r}] \u4E50\u5668\u7D22\u5F15 ${a} \u8D8A\u754C\uFF08instruments \u957F\u5EA6 ${t.instruments.length}\uFF09`);let o=i[1];(o<-1||o>1)&&e.push(`patterns[${s}][${r}] \u58F0\u50CF ${o} \u8D8A\u754C\uFF08\u5E94 -1..+1\uFF09`)})}),!Array.isArray(t.sequence)||t.sequence.length===0?e.push("sequence \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.sequence.forEach((n,s)=>{if(typeof n!="number"||!Number.isInteger(n)){e.push(`sequence[${s}] \u5FC5\u987B\u662F\u6574\u6570 pattern \u7D22\u5F15`);return}Array.isArray(t.patterns)&&(n<0||n>=t.patterns.length)&&e.push(`sequence[${s}] \u7D22\u5F15 ${n} \u8D8A\u754C\uFF08patterns \u957F\u5EA6 ${t.patterns.length}\uFF09`)}),t.bpm!=null&&(typeof t.bpm!="number"||!(t.bpm>0))&&e.push("bpm \u5FC5\u987B\u662F\u6B63\u6570"),{ok:e.length===0,errors:e})}function kt(t){return typeof t!="number"||Number.isNaN(t)||t<0?0:t>1?1:t}function Ou(t,e){switch(t){case"ease-in":return e*e;case"ease-out":return Math.sqrt(e);case"constant":return 1;default:return e}}function lc(t,e){let n=kt(e);return t==null||!Array.isArray(t.voices)?[]:t.voices.map(s=>{let i=String(s&&s.id!=null?s.id:""),r=Array.isArray(s&&s.channelIndices)?s.channelIndices.slice():[],a=typeof s.minIntensity=="number"?kt(s.minIntensity):0,o=typeof s.maxIntensity=="number"?kt(s.maxIntensity):1,c=typeof s.volumeCurve=="string"?s.volumeCurve:"linear",l=typeof s.baseVolume=="number"?kt(s.baseVolume):1;if(no)return{id:i,on:!1,volume:0,channelIndices:r};let u=o-a,h=u<=0?1:(n-a)/u,d=kt(Ou(c,h)*l);return{id:i,on:!0,volume:d,channelIndices:r}})}function uc(t,e,n,s){try{let i=e[0]||[],r=e[1]||i,a=Math.max(i.length,r.length);if(a===0)return null;let c=t.createBuffer(2,a,44100);c.getChannelData(0).set(i),c.getChannelData(1).set(r.length?r:i);let l=t.createBufferSource();l.buffer=c,l.loop=!!s;let u=t.createGain();return u.gain.value=kt(n*.3),l.connect(u),u.connect(t.destination),l.start(),{stop(){try{l.stop()}catch(h){}try{l.disconnect(),u.disconnect()}catch(h){}}}}catch(i){return zo("[audio-music] \u53D7\u63A7\u97F3\u9891\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",i),null}}function dc(t){let e=t||{},n=typeof e.masterVolume=="number"?kt(e.masterVolume):1,s=()=>null,i=null,r=null,a={voices:[]},o=1,c=null,l=!1,u=0,h=!1,d=!1;function f(){let v=s();return v==null?(u+=1,h||(Jo("[audio-music] \u65E0\u53D7\u63A7\u97F3\u9891\u4E0A\u4E0B\u6587\uFF08getAudioContext \u8FD4\u56DE null\uFF09\uFF0C\u5168\u90E8\u53D1\u58F0\u9759\u9ED8 no-op\uFF08\u8BC4\u4F30\u73AF\u5883\u65E0\u58F0\u5361\u65F6\u7684\u5BB9\u9519\u964D\u7EA7\uFF09"),h=!0),null):v}function p(){if(!r||!i)return null;try{let v=typeof r.bpm=="number"&&r.bpm>0?r.bpm:125;return i.synthSong(r.instruments,r.patterns,r.sequence,v)}catch(v){return zo("[audio-music] \u66F2\u8C31\u6E32\u67D3\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",v),null}}function y(){let v=lc(a,o);if(v.length===0)return 1;let _=0;for(let k of v)k.on&&(_=Math.max(_,k.volume));return _}function x(v,_){typeof _=="number"&&(o=kt(_));let k=f();if(k==null||!r)return;w();let C=p();if(!C)return;let L=kt(n*y());c=uc(k,C,L,v),l=!!v&&c!=null}function w(){c&&(c.stop(),c=null),l=!1}return{name:"audio-music",version:"1.0.0",dependencies:[],init(v){s=()=>v.getAudioContext();let _=v.getEngine&&v.getEngine();i=_?_.audio.synth:null},dispose(){d||(w(),d=!0)},loadSong(v){let _=Lu(v);return _.ok?r={instruments:v.instruments,patterns:v.patterns,sequence:v.sequence,bpm:typeof v.bpm=="number"?v.bpm:125}:Jo("[audio-music] \u66F2\u8C31\u6821\u9A8C\u5931\u8D25\uFF0C\u672A\u8F7D\u5165\uFF1A"+_.errors.join("\uFF1B")),_},play(v){x(!1,v)},stop(){w()},loop(v){x(!0,v)},setIntensityLayering(v){a=v&&Array.isArray(v.voices)?{voices:v.voices}:{voices:[]}},setIntensity(v){o=kt(v)},resolveVoices(v){return lc(a,v)},playSfx(v){let _=No[v];if(!_){Jo("[audio-music] \u672A\u77E5\u97F3\u6548\u9884\u8BBE\uFF1A"+String(v));return}let k=f();if(k!=null)try{let C=i?i.synthSfx(_.params):null;if(!C)return;uc(k,[C,C],n,!1)}catch(C){zo("[audio-music] \u97F3\u6548\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8 name="+v,C)}},getPreset(v){return No[v]},listPresets(){return cc.slice()},probe(){return{hasAudio:s()!=null,hasSong:r!=null,intensity:o,voiceCount:a.voices.length,looping:l,silentNoops:u,presetCount:cc.length}}}}function zo(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Jo(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Iu="zaomeng.save";function Du(t){if(typeof TextEncoder!="undefined")return new TextEncoder().encode(t).length;if(typeof Buffer!="undefined"&&typeof Buffer.byteLength=="function")return Buffer.byteLength(t,"utf8");let e=0;for(let n=0;n=55296&&s<=56319?(e+=4,n++):e+=3}return e}function Vo(){let t=new Map;return{getItem(e){return t.has(e)?t.get(e):null},setItem(e,n){t.set(e,n)},removeItem(e){t.delete(e)},keys(){return Array.from(t.keys())}}}function fc(){if(typeof localStorage=="undefined")throw new Error("[save-progress] createLocalStorageAdapter \u9700\u8981\u5168\u5C40 localStorage\uFF08\u4EC5\u6D4F\u89C8\u5668\u96C6\u6210\u6BB5\u53EF\u7528\uFF09\u3002node/host-dev \u8BF7\u7528\u7F3A\u7701\u5185\u5B58 adapter \u6216 createMemoryAdapter()\u3002");return{getItem(t){return localStorage.getItem(t)},setItem(t,e){localStorage.setItem(t,e)},removeItem(t){localStorage.removeItem(t)},keys(){let t=[];for(let e=0;e0?e.namespace:Iu;if(n.indexOf(":")>=0)throw new Error('[save-progress] namespace \u4E0D\u5F97\u542B\u5206\u9694\u7B26 ":"\uFF08\u5F53\u524D="'+n+'"\uFF09');let s=typeof e.maxValueBytes=="number"&&e.maxValueBytes>0?Math.floor(e.maxValueBytes):32768,i=!Fu(e.adapter),r=i?Vo():e.adapter,a=n+":",o=0,c=0,l=!1;function u(f){return typeof f!="string"||f.length===0?a+String(f):a+f}function h(){try{let f=r.keys();return Array.isArray(f)?f.filter(p=>typeof p=="string"&&p.indexOf(a)===0):[]}catch(f){return ws("[save-progress] adapter.keys() \u5F02\u5E38\uFF0C\u964D\u7EA7\u8FD4\u56DE\u7A7A\u96C6",f),[]}}return{name:"save-progress",version:"1.0.0",dependencies:[],init(f){h()},dispose(){},get(f,p){if(!Uo(f))return p;let y;try{y=r.getItem(u(f))}catch(x){return ws("[save-progress] adapter.getItem \u5F02\u5E38\uFF0C\u8FD4\u56DE\u9ED8\u8BA4\u503C key="+f,x),p}if(y==null)return p;try{return JSON.parse(y)}catch{return o+=1,l||(Ts("[save-progress] \u68C0\u6D4B\u5230\u635F\u574F\u5B58\u6863\uFF08\u975E\u6CD5 JSON\uFF09\uFF0C\u5DF2\u5BB9\u9519\u56DE\u9000\u9ED8\u8BA4\u503C key="+f),l=!0),p}},set(f,p){if(!Uo(f))return Ts("[save-progress] set \u6536\u5230\u975E\u6CD5 key\uFF0C\u62D2\u7EDD\u5199\u5165\uFF1A"+String(f)),!1;let y;try{y=JSON.stringify(p)}catch{return c+=1,Ts("[save-progress] \u503C\u4E0D\u53EF JSON \u5E8F\u5217\u5316\uFF08\u5FAA\u73AF\u5F15\u7528?\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+f),!1}if(y===void 0)return c+=1,Ts("[save-progress] \u503C\u5E8F\u5217\u5316\u4E3A undefined\uFF08\u5982\u7EAF undefined/\u51FD\u6570\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+f),!1;let x=Du(y);if(x>s)return c+=1,Ts("[save-progress] \u503C\u8D85\u5B57\u8282\u4E0A\u9650\u62D2\u7EDD\u5199\u5165 key="+f+"\uFF08"+x+" > "+s+" bytes\uFF09"),!1;try{return r.setItem(u(f),y),!0}catch(w){return c+=1,ws("[save-progress] adapter.setItem \u5F02\u5E38\uFF0C\u5199\u5165\u5931\u8D25 key="+f,w),!1}},remove(f){if(Uo(f))try{r.removeItem(u(f))}catch(p){ws("[save-progress] adapter.removeItem \u5F02\u5E38\uFF08\u5DF2\u5FFD\u7565\uFF09key="+f,p)}},clear(){let f=h(),p=0;for(let y of f)try{r.removeItem(y),p+=1}catch(x){ws("[save-progress] clear \u65F6 removeItem \u5F02\u5E38\uFF08\u5DF2\u8DF3\u8FC7\uFF09fullKey="+y,x)}return p},probe(){return{namespace:n,maxValueBytes:s,usingMemoryAdapter:i,size:h().length,corruptRecoveries:o,rejectedWrites:c}}}}function Uo(t){return typeof t=="string"&&t.length>0}function Fu(t){return!!t&&typeof t.getItem=="function"&&typeof t.setItem=="function"&&typeof t.removeItem=="function"&&typeof t.keys=="function"}function ws(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Ts(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Qn=[{id:"soda",name:"\u6C7D\u6C34",wholesale:20,basePrice:40,popularity:1,initial:!0},{id:"snack",name:"\u8FA3\u6761",wholesale:10,basePrice:25,popularity:1.2,initial:!0},{id:"bread",name:"\u9762\u5305",wholesale:30,basePrice:60,popularity:.8,initial:!0},{id:"ice",name:"\u51B0\u6DC7\u6DCB",wholesale:40,basePrice:90,popularity:.7,initial:!1},{id:"toy",name:"\u5C0F\u73A9\u5177",wholesale:80,basePrice:180,popularity:.35,initial:!1}];function Ye(t){return Qn.find(e=>e.id===t)}var Re={lengthSec:96,rushStartSec:30,rushEndSec:66,rushRampSec:3,daysPerSegment:3};function pc(t){let{rushStartSec:e,rushEndSec:n,rushRampSec:s}=Re;return t<=e-s||t>=n+s?0:t>=e&&t<=n?1:te.id===t)}function Ho(t){let e=n=>!!t[n];return{shelfCap:e("shelf2")?48:e("shelf1")?34:24,serveCooldownSec:e("speed2")?.32:e("speed1")?.42:.55,patienceMul:e("decor2")?1.3:e("decor1")?1.15:1,settleRepBonusTenth:e("decor2")?60:e("decor1")?30:0,flowMul:e("decor2")?1.12:1}}function Si(t){let e=t.priceMul,n=t.reputation==null?Xe.start:t.reputation,s=t.serveCapacity==null?26:t.serveCapacity,i=t.stockUnits==null?1/0:t.stockUnits,r=t.segment==null?1:t.segment,a=t.unlocked||Qn.filter(x=>x.initial).map(x=>x.id),l=((Re.lengthSec-(Re.rushEndSec-Re.rushStartSec))/cn.idleIntervalSec+(Re.rushEndSec-Re.rushStartSec)/cn.rushIntervalSec)*qo(e)*Wo(n),u=Math.min(l,s,i),h=a.map(x=>Ye(x)).filter(Boolean),d=h.reduce((x,w)=>x+w.popularity,0),f=h.reduce((x,w)=>x+(Math.round(w.basePrice*e)-w.wholesale)*(w.popularity/d),0),p=Math.round(u*f),y=ce.rentBaseJiao+(r-1)*ce.rentPerSegmentJiao;return{arrivals:l,served:u,grossJiao:p,rentJiao:y,profitJiao:p-y}}function ze(t,e,n){return tn?n:t}function Ke(t){let e=t/10;return Number.isInteger(e)?String(e):e.toFixed(1)}var gc=1,Gu=2600;function As(t){let e=t.random;if(!e||typeof e.next!="function")throw new Error("[shop-core] \u5FC5\u987B\u6CE8\u5165\u53D7\u63A7\u968F\u673A\u6E90 random\uFF08next/range/reseed\uFF09");let n=0,s={nowMs:()=>n,elapsedMs:()=>n},i=new mi(s,{windowMs:Gu,maxCount:99}),r=[];function a(S,P){r.push(Object.assign({type:S,tMs:Math.round(n)},P||{}))}let o={phase:"title",day:1,cash:ce.startCashJiao,repTenth:Xe.start*10,priceMul:1,stock:{},unlocked:Qn.filter(S=>S.initial).map(S=>S.id),upgrades:{},customers:[],dayTimeSec:0,rushFactor:0,serveCooldown:0,comboCount:0,prepBought:{},today:c(),lifetime:{days:0,served:0,angry:0,netJiao:0,upgradesBought:0},settle:null,summary:null,gameoverReason:null};function c(){return{revenueJiao:0,soldCostJiao:0,served:0,angry:0,stockout:0,walkaway:0,rescued:0,bigSales:0,maxCombo:0}}let l=1,u=0,h=!1,d=Ho(o.upgrades);function f(){d=Ho(o.upgrades)}function p(){let S=0;for(let P of Object.keys(o.stock))S+=o.stock[P];return S}function y(){return o.repTenth/10}function x(S){o.repTenth=ze(o.repTenth+S,0,Xe.max*10)}function w(S){let P=o.phase;o.phase=S,a("phase_changed",{from:P,to:S})}function A(S){o.day=S,o.prepBought={},o.today=c(),o.customers=[],o.dayTimeSec=0,o.rushFactor=0,o.settle=null,o.summary=null,w("prep"),a("save_point",{})}function v(){let S=o.rushFactor>.5?cn.rushIntervalSec:cn.idleIntervalSec,P=qo(o.priceMul)*Wo(y())*d.flowMul;u=S/Math.max(P,.05)*e.range(cn.jitterMin,cn.jitterMax)}function _(){let S=o.unlocked.map(M=>Ye(M)),P=S.reduce((M,j)=>M+j.popularity,0),R=e.next()*P;for(let M of S)if(R-=M.popularity,R<=0)return M.id;return S[S.length-1].id}function k(){for(let S=0;SP.slot===S))return S;return-1}function C(){let S=_(),P=k();if(P<0){o.today.walkaway+=1,a("walkaway_full",{productId:S});return}let M=(o.rushFactor>.5?kn.rushSec:kn.idleSec)*d.patienceMul*e.range(.9,1.12),j={id:l++,productId:S,slot:P,mood:"queue",patienceSec:M,patienceMaxSec:M,timerSec:0,avatar:Math.floor(e.next()*4)%4,impatientFired:!1};(o.stock[S]||0)<=0&&(j.mood="stockout",j.timerSec=kn.stockoutLingerSec),o.customers.push(j),a("customer_arrive",{id:j.id,slot:P,productId:S,mood:j.mood})}function L(S){let P=o.customers.indexOf(S);P>=0&&o.customers.splice(P,1)}function V(S){o.dayTimeSec+=S,o.rushFactor=pc(o.dayTimeSec);let P=o.rushFactor>.5;if(P!==h&&(a(P?"rush_start":"rush_end",{}),h=P),o.serveCooldown>0&&(o.serveCooldown=Math.max(0,o.serveCooldown-S)),o.dayTimeSec>=Re.lengthSec){a("closing",{}),o.customers=[],ae();return}u-=S,u<=0&&(C(),v());for(let R=o.customers.length-1;R>=0;R--){let M=o.customers[R];if(M.mood==="queue"){if((o.stock[M.productId]||0)<=0){M.mood="stockout",M.timerSec=kn.stockoutLingerSec;continue}M.patienceSec-=S,!M.impatientFired&&M.patienceSec/M.patienceMaxSec<=kn.impatientRatio&&(M.impatientFired=!0,a("customer_impatient",{id:M.id,slot:M.slot})),M.patienceSec<=0&&(M.mood="leaving",M.timerSec=kn.graceSec,a("customer_grace",{id:M.id,slot:M.slot}))}else M.mood==="leaving"?(M.timerSec-=S,M.timerSec<=0&&(L(M),o.today.angry+=1,x(-Xe.angryLossTenth),a("angry_leave",{id:M.id,slot:M.slot,avatar:M.avatar,productId:M.productId,repLossTenth:Xe.angryLossTenth}))):M.mood==="stockout"&&(M.timerSec-=S,M.timerSec<=0&&(L(M),o.today.stockout+=1,x(-Xe.stockoutLossTenth),a("stockout_leave",{id:M.id,slot:M.slot,avatar:M.avatar,productId:M.productId,repLossTenth:Xe.stockoutLossTenth})))}o.comboCount=i.getCount(n)}function ae(){let S=o.today,P=Math.ceil(o.day/Re.daysPerSegment),R=ce.rentBaseJiao+(P-1)*ce.rentPerSegmentJiao,M=0;y()P.initial).map(P=>P.id),o.upgrades={},o.lifetime={days:0,served:0,angry:0,netJiao:0,upgradesBought:0},o.gameoverReason=null,f(),i.reset(),a("game_start",{continued:!1}),A(1),{ok:!0,continued:!1})},buyStock(S,P){let R=Math.max(1,Math.floor(P||1));if(o.phase!=="prep")return{ok:!1,reason:"phase"};let M=Ye(S);if(!M||!o.unlocked.includes(S))return{ok:!1,reason:"unknown_product"};if(p()+R>d.shelfCap)return{ok:!1,reason:"shelf_full"};let j=M.wholesale*R;return o.cash0)return{ok:!1,reason:"cooldown"};if(!o.unlocked.includes(S))return{ok:!1,reason:"unknown_product"};if((o.stock[S]||0)<=0)return a("tap_empty",{productId:S}),{ok:!1,reason:"no_stock"};let P=o.customers.filter(ee=>ee.productId===S&&(ee.mood==="queue"||ee.mood==="leaving")).sort((ee,K)=>ee.id-K.id)[0];if(!P)return a("tap_nocustomer",{productId:S}),{ok:!1,reason:"no_customer"};let R=P.mood==="leaving";o.stock[S]-=1;let M=i.hit(n);o.comboCount=M,o.today.maxCombo=Math.max(o.today.maxCombo,M);let j=Math.round(mc(S,o.priceMul)*yc(M));o.cash+=j,o.today.revenueJiao+=j,o.today.soldCostJiao+=Ye(S).wholesale,o.today.served+=1,o.lifetime.served+=1,R&&(o.today.rescued+=1),x(Xe.serveGainTenth+(R?Xe.rescueBonusTenth:0)),o.serveCooldown=d.serveCooldownSec;let X=j>=ce.bigSaleJiao;return X&&(o.today.bigSales+=1),L(P),a("serve_ok",{id:P.id,slot:P.slot,avatar:P.avatar,productId:S,revenueJiao:j,combo:M,big:X,rescued:R}),{ok:!0,revenueJiao:j,combo:M,big:X,rescued:R,customerId:P.id}},confirmSettle(){if(o.phase!=="settle")return{ok:!1,reason:"phase"};let S=o.day;if(a("save_point",{}),S%Re.daysPerSegment===0){let P=S/Re.daysPerSegment;o.summary={segment:P,days:S,netJiao:o.lifetime.netJiao,served:o.lifetime.served,upgradesBought:o.lifetime.upgradesBought,reputation:y()},w("summary"),a("segment_end",{summary:o.summary})}else A(S+1);return{ok:!0}},confirmSummary(){return o.phase!=="summary"?{ok:!1,reason:"phase"}:(A(o.day+1),{ok:!0})},derived(){return d},reputation:y,totalStock:p,snapshotForSave(){return{v:gc,day:o.day,cash:o.cash,repTenth:o.repTenth,priceMul:o.priceMul,stock:Object.assign({},o.stock),unlocked:o.unlocked.slice(),upgrades:Object.assign({},o.upgrades),lifetime:Object.assign({},o.lifetime)}},restoreFromSave(S){return!S||S.v!==gc||typeof S.day!="number"||typeof S.cash!="number"||typeof S.repTenth!="number"||!S.unlocked||!Array.isArray(S.unlocked)||S.unlocked.length===0?!1:(o.cash=Math.floor(S.cash),o.repTenth=ze(Math.floor(S.repTenth),0,Xe.max*10),o.priceMul=ze(S.priceMul||1,ce.priceMin,ce.priceMax),o.stock=Object.assign({},S.stock||{}),o.unlocked=S.unlocked.filter(P=>!!Ye(P)),o.upgrades=Object.assign({},S.upgrades||{}),o.lifetime=Object.assign({days:0,served:0,angry:0,netJiao:0,upgradesBought:0},S.lifetime||{}),o.gameoverReason=null,f(),i.reset(),a("game_start",{continued:!0}),A(Math.max(1,Math.floor(S.day))),!0)}};return O}var ks={open_shop:["\u5F00\u5F20\u55BD\u2014\u2014\u8857\u574A\u4EEC\u90FD\u7B49\u7740\u5462\uFF01","\u4ECA\u513F\u4E2A\u8FDB\u70B9\u5565\u597D\u8D27\uFF1F\u6211\u5FC3\u91CC\u6709\u6570\u3002","\u5C0F\u672C\u751F\u610F\uFF0C\u8D26\u53EF\u5F97\u7B97\u660E\u767D\u54AF\u3002"],day_start:["\u5F00\u95E8\u8FCE\u5BA2\uFF01\u90FD\u9EBB\u5229\u70B9\u513F~","\u54DF\uFF0C\u4ECA\u5929\u592A\u9633\u4E0D\u9519\uFF0C\u51C6\u662F\u4E2A\u597D\u65E5\u5B50\u3002"],idle_chat:["\u6162\u60A0\u60A0\u7684\u4E0B\u5348\uFF0C\u6700\u9002\u5408\u76D8\u8D26\u5566\u3002","\u9694\u58C1\u8001\u674E\u53C8\u6765\u8D4A\u8D26\uFF1F\u60F3\u5F97\u7F8E\u3002","\u8D27\u67B6\u64E6\u5F97\u9503\u4EAE\uFF0C\u770B\u7740\u5C31\u8212\u5766\u3002"],rush_start:["\u653E\u5B66\u5566\u653E\u5B66\u5566\uFF0C\u6253\u8D77\u7CBE\u795E\u6765\uFF01","\u4EBA\u90FD\u6D8C\u8FC7\u6765\u4E86\uFF0C\u624B\u4E0A\u522B\u505C\uFF01"],serve_ok:["\u597D\u561E\uFF0C\u62FF\u7A33\u5F53\uFF01","\u60A8\u6162\u8D70\uFF0C\u5E38\u6765\u554A~","\u8FD9\u5C31\u7ED9\u60A8\u62FF\uFF0C\u5FEB\u5F97\u5F88\uFF01"],combo_hot:["\u624B\u611F\u6765\u4E86\uFF0C\u8C01\u90FD\u522B\u62E6\u6211\uFF01","\u4E00\u4E2A\u63A5\u4E00\u4E2A\uFF0C\u8D8A\u5E72\u8D8A\u987A\u6E9C\uFF01"],big_sale:["\u54CE\u54DF\uFF0C\u5927\u4E3B\u987E\uFF01\u4ECA\u665A\u52A0\u4E2A\u9E21\u817F\uFF01","\u8FD9\u5355\u9876\u534A\u5929\u4E70\u5356\uFF0C\u7F8E\u6ECB\u6ECB~"],rescue:["\u522B\u8D70\u522B\u8D70\uFF0C\u8FD9\u5C31\u7ED9\u60A8\u62FF\u4E0A\uFF01","\u597D\u9669\u597D\u9669\uFF0C\u5DEE\u70B9\u513F\u9EC4\u4E86\u4E00\u5355\u3002"],angry:["\u54CE\u5440\uFF0C\u628A\u4EBA\u667E\u8DD1\u4E86\u2026\u2026\u5FC3\u75BC\u3002","\u7838\u62DB\u724C\u4E86\u7838\u62DB\u724C\u4E86\uFF0C\u5F97\u4E0A\u70B9\u5FC3\uFF01"],stockout:["\u7A7A\u8D27\u67B6\u6700\u6233\u5FC3\u7A9D\u5B50\uFF0C\u660E\u513F\u591A\u5907\u70B9\u3002","\u53C8\u5356\u65AD\u4E86\u2026\u2026\u662F\u597D\u4E8B\u4E5F\u662F\u574F\u4E8B\u3002"],settle_win:["\u4ECA\u513F\u8D26\u9762\u7EA2\u706B\uFF0C\u8BB0\u4E0A\u8BB0\u4E0A\uFF01","\u8F9B\u82E6\u4E00\u5929\uFF0C\u503C\u5F53\uFF01"],settle_lose:["\u8FD9\u8D26\u2026\u2026\u8D8A\u7B97\u8D8A\u5FC3\u51C9\u3002","\u7F5A\u5355\u90FD\u8D34\u8138\u4E0A\u4E86\uFF0C\u660E\u5929\u5F97\u6362\u4E2A\u6D3B\u6CD5\u3002"],upgrade:["\u820D\u4E0D\u5F97\u5B69\u5B50\u5957\u4E0D\u7740\u72FC\uFF0C\u5347\uFF01","\u9E1F\u67AA\u6362\u70AE\uFF0C\u54B1\u4E5F\u8BB2\u7A76\u4E00\u56DE\uFF01"],gameover:["\u5509\u2026\u2026\u5377\u5E18\u95E8\u4E00\u62C9\uFF0C\u4ECE\u5934\u518D\u6765\u5427\u3002"]},bp=Object.keys(ks).length;function bc(t){let e={};return function(s){let i=ks[s];if(!i||i.length===0)return"";if(i.length===1)return i[0];let r=Math.floor(t.next()*i.length)%i.length;return r===e[s]&&(r=(r+1)%i.length),e[s]=r,i[r]}}var Cs={paper:{r:246,g:231,b:201},paperHi:{r:255,g:246,b:227},cream:{r:255,g:243,b:220},ink:{r:91,g:70,b:54},inkSoft:{r:138,g:108,b:84},wood:{r:169,g:118,b:79},woodDark:{r:124,g:84,b:55},gold:{r:232,g:169,b:66},coin:{r:246,g:196,b:83},amber:{r:240,g:196,b:117},brick:{r:201,g:111,b:74},danger:{r:178,g:72,b:54},leaf:{r:133,g:158,b:94},sky:{r:243,g:217,b:168},shadow:{r:62,g:49,b:40},scrim:{r:46,g:35,b:27},smoke:{r:140,g:106,b:85}},xc=Object.keys(Cs);function Sc(){let t=xc.map(a=>Cs[a]),e={from:t,to:t.slice()},n={from:t,to:t.map(a=>jo(a,{hue:-10,sat:1.18,light:.9}))},s=0,i=r(0);function r(a){let o=Bo(e,n,a),c={};for(let l of xc)c[l]=Go(o,Cs[l]);return c}return{setRush(a){let o=Math.round(Math.max(0,Math.min(1,a))*25)/25;o!==s&&(s=o,i=r(o))},rushT(){return s},c(a,o){let c=i[a]||Cs.ink,l=o==null?1:o;return l>=1?`rgb(${c.r},${c.g},${c.b})`:`rgba(${c.r},${c.g},${c.b},${l})`},rgb(a){return i[a]||Cs.ink}}}var $o={shopkeeperIdle:"shopkeeper-idle.jpg",shopkeeperWave:"shopkeeper-wave.jpg",customer0:"customer-kid.jpg",customer1:"customer-lady.jpg",customer2:"customer-grandpa.jpg",customer3:"customer-auntie.jpg",storefront:"storefront.jpg",itemSoda:"item-soda.jpg",itemSnack:"item-snack.jpg",itemBread:"item-bread.jpg",itemIce:"item-ice.jpg",itemToy:"item-toy.jpg",uiPanel:"ui-panel.jpg"},Cn={soda:"itemSoda",snack:"itemSnack",bread:"itemBread",ice:"itemIce",toy:"itemToy"};function vc(t){let e=t==null?"./assets/":t,n=Object.keys($o),s={},i=[];function r(a){return new Promise(o=>{if(typeof Image=="undefined"){s[a]=null,i.push(a),o(null);return}let c=new Image;c.onload=()=>{s[a]=c,o(c)},c.onerror=()=>{console.warn("[ref-assets] \u8D44\u4EA7\u52A0\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u7A0B\u5E8F\u5316\u56DE\u9000\uFF09\uFF1A"+$o[a]),s[a]=null,i.push(a),o(null)},c.src=e+$o[a]})}return Promise.all(n.map(r)).then(()=>({images:s,missing:i,loaded:n.length-i.length,total:n.length}))}function wc(t){let e=t.bundle,n=t.juice;function s(S){let P=bi({maxParticles:400});return P.init(e.deriveContextFor(S,S)),P}let i=s("fx-gold"),r=s("fx-cream"),a=s("fx-smoke"),o=[];function c(S,P,R){o.push({t:0,dur:Math.max(S,.001),ease:R&&R.ease||Mo.cubicOut,onUpdate:P,onDone:R&&R.onDone||null})}let l=new Map;function u(S,P){let R=l.get(S);return R||(R={state:{x:P==null?1:P,v:0},target:P==null?1:P,stiffness:320,damping:14},l.set(S,R)),R.state.x}function h(S,P,R){u(S);let M=l.get(S);M.state.v+=P,R!=null&&(M.target=R)}let d=[];function f(S){d.push({t:0,dur:S.dur||.3,fx:S.fx,fy:S.fy,tx:S.tx,ty:S.ty,arc:S.arc==null?46:S.arc,imageKey:S.imageKey||null,label:S.label||"",onArrive:S.onArrive||null})}let p=[],y=980;function x(S){let P=S.dur||.45,R=(S.tx-S.fx)/P,M=(S.ty-S.fy-.5*y*P*P)/P;p.push({proj:new hi({px:S.fx,py:S.fy,vx:R,vy:M},{gravity:{x:0,y}}),age:0,dur:P,tx:S.tx,ty:S.ty,imageKey:S.imageKey||null,onLand:S.onLand||null})}let w=[];function A(S,P,R,M,j){w.push({text:S,x:P,y:R,t:0,dur:.9,colorName:M||"gold",size:j||16})}let v=[];function _(S,P){v.push({x:S,y:P,t:0})}function k(S,P,R){i.spawnEmitter("burst",S,P,{count:R?26:13,angle:-Math.PI/2,spread:.85,speedMin:130,speedMax:R?320:240,gravity:420,lifeMin:.35,lifeMax:.7,sizeCurve:{kind:"decay",from:R?5.5:4,to:0,power:1.3}})}function C(S,P,R){r.spawnEmitter("burst",S,P,{count:R||10,angle:-Math.PI/2,spread:1.1,speedMin:40,speedMax:110,gravity:-30,lifeMin:.4,lifeMax:.8,sizeCurve:{kind:"decay",from:3,to:0,power:1}})}function L(S,P){a.spawnEmitter("burst",S,P,{count:12,angle:-Math.PI/2,spread:Math.PI,speedMin:25,speedMax:70,gravity:-18,drag:1.2,lifeMin:.5,lifeMax:1,sizeCurve:{kind:"easeInOut",from:5,to:1},alphaCurve:{kind:"decay",from:.7,to:0,power:1.5}})}function V(S,P){for(let R=o.length-1;R>=0;R--){let M=o[R];M.t+=S;let j=Math.min(M.t/M.dur,1);M.onUpdate(M.ease(j)),j>=1&&(M.onDone&&M.onDone(),o.splice(R,1))}for(let R of l.values())R.state=Za(R.state,R.target,{stiffness:R.stiffness,damping:R.damping},S);for(let R=d.length-1;R>=0;R--){let M=d[R];M.t+=P,M.t>=M.dur&&(M.onArrive&&M.onArrive(),d.splice(R,1))}for(let R=p.length-1;R>=0;R--){let M=p[R];M.age+=P,M.proj.step(P),M.age>=M.dur&&(M.onLand&&M.onLand(),p.splice(R,1))}for(let R=w.length-1;R>=0;R--){let M=w[R];M.t+=P,M.t>=M.dur&&w.splice(R,1)}for(let R=v.length-1;R>=0;R--)v[R].t+=S,v[R].t>=.32&&v.splice(R,1)}function ae(S,P){S.save(),S.fillStyle=P.c("coin"),i.render(S),S.fillStyle=P.c("cream"),r.render(S),S.fillStyle=P.c("smoke"),a.render(S),S.restore(),n.render(S)}return{easing:Mo,addTween:c,springVal:u,springKick:h,addFlight:f,addToss:x,addFloater:A,addTapRing:_,burstCoin:k,burstSparkle:C,burstSmoke:L,step:V,renderParticles:ae,view:{flights:d,tosses:p,floaters:w,tapRings:v},juice:n,particleProbe(){return{gold:i.particleCount(),cream:r.particleCount(),smoke:a.particleCount()}},dispose(){i.dispose(),r.dispose(),a.dispose()}}}function Tc(t){let e=t.getAudio,n=t.p6,s=t.baseUrl==null?"./assets/":t.baseUrl,i=new Set,r={loading:!1,ready:!1,failed:!1,gainIdle:null,gainRush:null,idleLevel:0,rushLevel:0,targetRush:0},a=null;function o(d){return a||(a=d.createGain(),a.gain.value=.5,a.connect(d.destination)),a}function c(){let d=e();if(!d||r.loading||r.ready||r.failed)return;r.loading=!0;function f(p){return fetch(s+p).then(y=>{if(!y.ok)throw new Error("HTTP "+y.status);return y.arrayBuffer()}).then(y=>d.decodeAudioData(y)).then(y=>{let x=d.createBufferSource();x.buffer=y,x.loop=!0;let w=d.createGain();return w.gain.value=0,x.connect(w),w.connect(d.destination),x.start(),w})}Promise.all([f("bgm-idle.mp3"),f("bgm-rush.mp3")]).then(([p,y])=>{r.gainIdle=p,r.gainRush=y,r.ready=!0,r.loading=!1}).catch(p=>{console.warn("[ref-audio] BGM \u88C5\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u65E0 BGM\uFF09\uFF1A"+(p&&p.message?p.message:p)),r.failed=!0,r.loading=!1})}function l(d,f,p){if(r.targetRush=f,!r.ready)return;let y=p?1:.35,x=.5*(1-f)*y,w=.55*f*y,A=Math.min(d/1.2,1);r.idleLevel+=(x-r.idleLevel)*A,r.rushLevel+=(w-r.rushLevel)*A,r.gainIdle.gain.value=r.idleLevel,r.gainRush.gain.value=r.rushLevel}function u(d,f,p,y,x,w,A){let v=d.currentTime+(A||0),_=d.createOscillator(),k=d.createGain();_.type=f,_.frequency.setValueAtTime(p,v),_.frequency.exponentialRampToValueAtTime(Math.max(y,1),v+x),k.gain.setValueAtTime(1e-4,v),k.gain.exponentialRampToValueAtTime(w,v+.012),k.gain.exponentialRampToValueAtTime(1e-4,v+x),_.connect(k),k.connect(o(d)),_.start(v),_.stop(v+x+.02)}function h(d,f){let p=e();if(!p)return;let y=f||{};switch(d){case"arrive":n.playSfx("blip");break;case"shelve":n.playSfx("thud");break;case"upgrade":n.playSfx("chime");break;case"coin":{let x=Math.min(y.combo||1,11),w=660*Math.pow(2,(x-1)*2/12);u(p,"sine",w,w*1.5,.16,.5),u(p,"sine",w*2,w*2.6,.1,.22,.03);break}case"bad":u(p,"sawtooth",220,90,.32,.3);break;case"rescue":u(p,"triangle",520,540,.07,.32),u(p,"triangle",660,690,.07,.32,.07),u(p,"triangle",880,920,.1,.34,.14);break;case"bigsale":u(p,"sine",130,80,.22,.5),u(p,"sine",1320,1760,.18,.3,.05);break;case"tick":u(p,"triangle",900,700,.045,.16);break;case"empty":u(p,"square",180,140,.08,.14);break;default:return}i.add(d)}return{startBgm:c,step:l,sfx:h,probe(){return{sfxKinds:Array.from(i),bgm:{ready:r.ready,failed:r.failed,idleLevel:r.idleLevel,rushLevel:r.rushLevel}}}}}var U=390,Zn=844,Me={hud:{x:8,y:8,w:U-16,h:84},keeper:{x:14,y:398,w:124,h:160},bubble:{x:16,y:318,w:230,h:72},queue:[{x:186,y:470},{x:244,y:452},{x:302,y:470},{x:356,y:452}],avatarR:27,counter:{x:0,y:540,w:U,h:26},shelf:{x:8,y:574,w:U-16,h:158},bottom:{x:8,y:740,w:U-16,h:96},combo:{x:330,y:512}};function En(t){let e=t%3,n=Math.floor(t/3);return{x:16+e*124,y:584+n*76,w:116,h:68}}function kc(t){let e={x:12,y:116,w:U-24,h:706},n=196,s=46,i=n+t.length*s+26,r=i+64,a=42,o={x:U/2-110,y:e.y+e.h-70,w:220,h:54};return{panel:e,stockY:n,rowH:s,sliderY:i,upY:r,upRowH:a,btn:o}}function Cc(t){return{x:78,y:t+26,w:240,h:8}}function Qe(t,e,n,s,i,r){let a=Math.min(r,s/2,i/2);t.beginPath(),t.moveTo(e+a,n),t.arcTo(e+s,n,e+s,n+i,a),t.arcTo(e+s,n+i,e,n+i,a),t.arcTo(e,n+i,e,n,a),t.arcTo(e,n,e+s,n,a),t.closePath()}function q(t,e,n){t.font=`${n?"600 ":""}${e}px "PingFang SC","Microsoft YaHei",sans-serif`}function Xo(t,e,n,s,i,r){let a=e.width/e.height,o=i/r,c=0,l=0,u=e.width,h=e.height;a>o?(u=e.height*o,c=(e.width-u)/2):(h=e.width/o,l=(e.height-h)/2),t.drawImage(e,c,l,u,h,n,s,i,r)}function _n(t,e,n,s,i,r,a,o,c){t.save(),Qe(t,s,i,r,a,o),t.clip(),n?Xo(t,n,s,i,r,a):(t.fillStyle=e.c("amber"),t.fillRect(s,i,r,a),t.fillStyle=e.c("ink"),q(t,Math.min(a*.42,22),!0),t.textAlign="center",t.textBaseline="middle",t.fillText(c||"?",s+r/2,i+a/2)),t.restore()}function Ac(t,e,n,s,i,r,a){t.save(),t.beginPath(),t.arc(s,i,r,0,Math.PI*2),t.clip(),n?Xo(t,n,s-r,i-r,r*2,r*2):(t.fillStyle=e.c("sky"),t.fillRect(s-r,i-r,r*2,r*2),t.fillStyle=e.c("ink"),q(t,r,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a||"\u5BA2",s,i)),t.restore()}function Ct(t,e,n,s,i,r,a,o){t.save(),Qe(t,s,i,r,a,o==null?14:o),t.clip();let c=n.images.uiPanel;c?t.drawImage(c,c.width*.2,c.height*.04,c.width*.78,c.height*.9,s,i,r,a):(t.fillStyle=e.c("paper"),t.fillRect(s,i,r,a)),t.restore(),t.strokeStyle=e.c("wood"),t.lineWidth=2,Qe(t,s,i,r,a,o==null?14:o),t.stroke()}function ln(t,e,n,s,i,r,a,o){let c=o||{},l=c.scale==null?1:c.scale;t.save(),t.translate(n+i/2,s+r/2),t.scale(l,l),Qe(t,-i/2,-r/2,i,r,r/2-6),t.fillStyle=c.disabled?e.c("inkSoft",.45):e.c(c.color||"brick"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("paperHi"),q(t,c.fontSize||20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a,0,1),t.restore()}function Yo(t,e,n,s,i,r,a,o,c){Qe(t,n,s,i,r,r/2),t.fillStyle=e.c(c||"shadow",.25),t.fill();let l=ze(a,0,1);l>.01&&(Qe(t,n,s,Math.max(i*l,r),r,r/2),t.fillStyle=e.c(o||"gold"),t.fill())}function Bu(t,e,n){let s=n.images.storefront;s?Xo(t,s,0,0,U,Zn):(t.fillStyle=e.c("sky"),t.fillRect(0,0,U,Zn));let i=t.createLinearGradient(0,380,0,560);i.addColorStop(0,e.c("paper",0)),i.addColorStop(.5,e.c("paper",.28)),i.addColorStop(1,e.c("paper",.05)),t.fillStyle=i,t.fillRect(0,380,U,190)}function ju(t,e,n){let{core:s,fx:i,assets:r}=n,a=s.state,o=Me.hud;Ct(t,e,r,o.x,o.y,o.w,o.h,12),t.textBaseline="middle",t.fillStyle=e.c("ink"),q(t,16,!0),t.textAlign="left",t.fillText(`\u7B2C ${a.day} \u5929`,o.x+12,o.y+24);let c={x:o.x+86,y:o.y+18,w:168,h:11};Yo(t,e,c.x,c.y,c.w,c.h,a.phase==="open"?a.dayTimeSec/Re.lengthSec:0,"amber");let l=c.x+Re.rushStartSec/Re.lengthSec*c.w,u=(Re.rushEndSec-Re.rushStartSec)/Re.lengthSec*c.w;t.fillStyle=e.c("brick",.4),t.fillRect(l,c.y+c.h+2,u,3),t.save();let h=i.springVal("hud-cash",1);t.translate(o.x+o.w-12,o.y+24),t.scale(h,h),t.textAlign="right",t.fillStyle=e.c("gold"),q(t,19,!0),t.fillText(`\xA5${Ke(a.cash)}`,0,0),t.restore(),t.textAlign="left",t.fillStyle=e.c("inkSoft"),q(t,13),t.fillText("\u53E3\u7891",o.x+12,o.y+58);let d=s.reputation(),f=d<30?"danger":d<55?"brick":"leaf";Yo(t,e,o.x+48,o.y+52,150,12,d/100,f),t.fillStyle=e.c(f),q(t,13,!0),t.fillText(String(Math.round(d)),o.x+204,o.y+58),t.fillStyle=e.c("danger",.8),t.fillRect(o.x+48+150*.3-1,o.y+50,2,16),t.textAlign="right",t.fillStyle=e.c("inkSoft"),q(t,13),t.fillText(`\u4ECA\u65E5 ${a.today.served} \u5355 \xB7 \xA5${Ke(a.today.revenueJiao)}`,o.x+o.w-12,o.y+58)}function Ju(t,e,n){let{assets:s,ui:i,fx:r}=n,a=Me.keeper,o=Math.sin(n.nowMs/620)*1.5;t.save(),t.translate(0,o),Ct(t,e,s,a.x,a.y,a.w,a.h,14);let c=i.keeperWaveUntil>n.nowMs?s.images.shopkeeperWave:s.images.shopkeeperIdle;if(_n(t,e,c,a.x+6,a.y+6,a.w-12,a.h-34,10,"\u5E97\u4E3B"),t.fillStyle=e.c("ink"),q(t,13,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u8001\u677F\u5A18",a.x+a.w/2,a.y+a.h-15),t.restore(),i.bubbleText&&i.bubbleUntil>n.nowMs){let l=Me.bubble,u=r.springVal("bubble",1),h=ze((i.bubbleUntil-n.nowMs)/350,0,1);t.save(),t.globalAlpha=h,t.translate(l.x+l.w/2,l.y+l.h/2),t.scale(u,u),Qe(t,-l.w/2,-l.h/2,l.w,l.h,14),t.fillStyle=e.c("paperHi",.96),t.fill(),t.strokeStyle=e.c("wood"),t.lineWidth=2,t.stroke(),t.beginPath(),t.moveTo(-l.w/2+36,l.h/2-1),t.lineTo(-l.w/2+22,l.h/2+16),t.lineTo(-l.w/2+56,l.h/2-1),t.closePath(),t.fillStyle=e.c("paperHi",.96),t.fill(),t.fillStyle=e.c("ink"),q(t,14,!0),t.textAlign="center",t.textBaseline="middle";let d=i.bubbleText;d.length<=13?t.fillText(d,0,0):(t.fillText(d.slice(0,12),0,-9),t.fillText(d.slice(12,25),0,9)),t.restore()}}function Nu(t,e,n){let{core:s,assets:i}=n;if(s.state.phase==="open"){for(let r of s.state.customers){let a=Me.queue[r.slot]||Me.queue[0],o=n.nowMs-(n.customerBornMs[r.id]||n.nowMs),c=ze(o/400,0,1),l=n.fx.easing.backOut(c),u=a.x+(1-l)*(U+40-a.x),h=a.y;r.mood==="leaving"&&(u+=Math.sin(n.nowMs/28)*2.5);let d=Me.avatarR,f=r.mood==="queue"?ze(r.patienceSec/r.patienceMaxSec,0,1):0;t.beginPath(),t.arc(u,h,d+4,0,Math.PI*2),t.strokeStyle=e.c("shadow",.3),t.lineWidth=4,t.stroke(),r.mood==="queue"&&(t.beginPath(),t.arc(u,h,d+4,-Math.PI/2,-Math.PI/2+f*Math.PI*2),t.strokeStyle=e.c(f>.55?"gold":f>.3?"brick":"danger"),t.lineWidth=4,t.stroke()),t.save(),r.mood==="stockout"&&(t.globalAlpha=.78),Ac(t,e,i.images["customer"+r.avatar],u,h,d,"\u5BA2"),t.restore();let p=46,y=44,x=u-p/2,w=h-d-y-9;Qe(t,x,w,p,y,9),t.fillStyle=e.c("paperHi",.95),t.fill(),t.strokeStyle=r.mood==="stockout"?e.c("danger"):e.c("wood"),t.lineWidth=1.5,t.stroke(),t.beginPath(),t.moveTo(u-6,w+y),t.lineTo(u,w+y+7),t.lineTo(u+6,w+y),t.closePath(),t.fillStyle=e.c("paperHi",.95),t.fill();let A=Ye(r.productId);_n(t,e,i.images[Cn[r.productId]],x+7,w+5,32,26,6,A?A.name[0]:"?"),t.fillStyle=e.c("inkSoft"),q(t,9),t.textAlign="center",t.textBaseline="middle",t.fillText(A?A.name:"",u,w+y-7),r.mood==="leaving"||r.mood==="queue"&&f<=.32?(t.fillStyle=e.c("danger"),q(t,r.mood==="leaving"?18:15,!0),t.textAlign="left",t.fillText(r.mood==="leaving"?"!!":"!",u+d+3,h-d+4)):r.mood==="stockout"&&(t.fillStyle=e.c("danger"),q(t,11,!0),t.textAlign="center",t.fillText("\u7F3A\u8D27\u2026",u,h+d+12))}for(let r of n.ui.ghosts){let a=Me.queue[r.slot]||Me.queue[0],c=ze(1-(r.until-n.nowMs)/480,0,1),l=r.emote==="\u6012",u=a.x+(l?c*46:0),h=a.y-(l?0:c*22);t.save(),t.globalAlpha=(1-c)*.85,Ac(t,e,i.images["customer"+r.avatar],u,h,Me.avatarR,"\u5BA2"),t.fillStyle=e.c(l?"danger":r.emote==="\u2026"?"inkSoft":"gold"),q(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(r.emote,u+Me.avatarR+8,h-Me.avatarR+2),t.restore()}}}function zu(t,e){let n=Me.counter;t.fillStyle=e.c("wood"),t.fillRect(n.x,n.y,n.w,n.h),t.fillStyle=e.c("woodDark"),t.fillRect(n.x,n.y+n.h-6,n.w,6),t.fillStyle=e.c("paperHi",.18),t.fillRect(n.x,n.y,n.w,3)}function Uu(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state,o=Me.shelf;Ct(t,e,i,o.x,o.y,o.w,o.h,14),t.fillStyle=e.c("inkSoft"),q(t,11),t.textAlign="left",t.textBaseline="middle";let c=`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`;t.fillText(c,o.x+10,o.y+10),a.phase==="open"&&(t.textAlign="right",t.fillText("\u70B9\u5546\u54C1 \u2192 \u9012\u7ED9\u6392\u961F\u7684\u5BA2\u4EBA",o.x+o.w-10,o.y+10));for(let l=0;l<6;l++){let u=En(l),h=a.unlocked[l];if(!h){t.save(),t.setLineDash([5,4]),Qe(t,u.x,u.y,u.w,u.h,10),t.strokeStyle=e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.restore(),t.fillStyle=e.c("inkSoft",.6),q(t,12),t.textAlign="center",t.fillText("\u5347\u7EA7\u89E3\u9501",u.x+u.w/2,u.y+u.h/2);continue}let d=Ye(h),f=a.stock[h]||0,p=r.springVal("slot-"+h,1);t.save(),t.translate(u.x+u.w/2,u.y+u.h/2),t.scale(p,p),t.translate(-(u.x+u.w/2),-(u.y+u.h/2)),Qe(t,u.x,u.y,u.w,u.h,10),t.fillStyle=f>0?e.c("paperHi",.92):e.c("shadow",.14),t.fill(),t.strokeStyle=f>0?e.c("wood"):e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.save(),f<=0&&(t.globalAlpha=.45),_n(t,e,i.images[Cn[h]],u.x+6,u.y+7,44,44,8,d.name[0]),t.restore(),t.fillStyle=e.c("ink"),q(t,13,!0),t.textAlign="left",t.fillText(d.name,u.x+56,u.y+16),t.fillStyle=e.c("gold"),q(t,13,!0),t.fillText(`\xA5${Ke(Math.round(d.basePrice*a.priceMul))}`,u.x+56,u.y+34),f>0?(t.fillStyle=e.c("inkSoft"),q(t,12),t.fillText(`\xD7${f}`,u.x+56,u.y+52)):(t.fillStyle=e.c("danger"),q(t,12,!0),t.fillText("\u7F3A\u8D27",u.x+56,u.y+52)),t.restore()}}function Vu(t,e,n){let{assets:s,ui:i}=n,r=Me.bottom;Ct(t,e,s,r.x,r.y,r.w,r.h,14),t.fillStyle=e.c("brick"),q(t,24,!0),t.textAlign="left",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",r.x+16,r.y+30),t.fillStyle=e.c("inkSoft"),q(t,12),t.fillText(i.tickerText||"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",r.x+16,r.y+62),t.textAlign="right",q(t,11),t.fillText("ref-r1",r.x+r.w-12,r.y+r.h-14)}function qu(t,e,n){let{core:s,fx:i}=n;if(s.state.phase!=="open"||s.state.comboCount<2)return;let r=i.springVal("combo",1),a=Me.combo;t.save(),t.translate(a.x,a.y),t.scale(r,r),t.rotate(-.08),Qe(t,-44,-20,88,40,12),t.fillStyle=e.c("gold"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("ink"),q(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u8FDE\u51FB\xD7${s.state.comboCount}`,0,1),t.restore()}function _s(t,e,n){t.fillStyle=e.c("scrim",n==null?.45:n),t.fillRect(0,0,U,Zn)}function Wu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state,c=kc(o.unlocked),l=a.panelSlide;t.save(),t.translate(0,(1-l)*520),_s(t,e,.35*l),Ct(t,e,i,c.panel.x,c.panel.y,c.panel.w,c.panel.h,16),t.fillStyle=e.c("ink"),q(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u5F00\u5E02\u51C6\u5907`,U/2,c.panel.y+30),q(t,14),t.fillStyle=e.c("gold"),t.fillText(`\u8D44\u91D1 \xA5${Ke(o.cash)}`,U/2-80,c.panel.y+60),t.fillStyle=e.c("inkSoft"),t.fillText(`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`,U/2+80,c.panel.y+60);for(let d=0;d=f.costJiao,k=r.springVal("z:up-"+f.id,1);t.save(),t.translate(x+84,w+18),t.scale(k,k),Qe(t,-84,-18,168,36,9),t.fillStyle=A?e.c("leaf",.3):v?e.c("shadow",.12):e.c("paperHi",.95),t.fill(),t.strokeStyle=A?e.c("leaf"):!v&&_?e.c("gold"):e.c("inkSoft",.4),t.lineWidth=A||!v&&_?2:1,t.stroke(),t.fillStyle=v?e.c("inkSoft",.6):e.c("ink"),q(t,12,!0),t.textAlign="left",t.textBaseline="middle",t.fillText(f.name,-76,-5),q(t,10),t.fillStyle=A?e.c("leaf"):v?e.c("inkSoft",.6):_?e.c("gold"):e.c("danger",.8),t.fillText(A?"\u5DF2\u8D2D \u2713":v?"\u9700 "+(xi(f.requires)||{}).name:`\xA5${Ke(f.costJiao)}`,-76,9),t.restore()}ln(t,e,c.btn.x,c.btn.y,c.btn.w,c.btn.h,"\u5F00\u95E8\u8425\u4E1A\uFF01",{color:"brick",fontSize:21,scale:r.springVal("z:openShop",1)}),t.restore()}function Hu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state.settle;if(!o)return;let c=a.settleAnim;_s(t,e,.5);let l={x:30,y:170,w:U-60,h:470};Ct(t,e,i,l.x,l.y,l.w,l.h,16),t.fillStyle=e.c("ink"),q(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u6253\u70CA\u7ED3\u7B97`,U/2,l.y+32);function u(p,y,x,w,A){let v=l.y+76+p*38;t.textAlign="left",t.fillStyle=e.c("inkSoft"),q(t,14),t.fillText(y,l.x+26,v),t.textAlign="right",t.fillStyle=e.c(w),q(t,16,!0);let _=Math.round(x*c);t.fillText(`${A}\xA5${Ke(Math.abs(_))}`,l.x+l.w-26,v)}u(0,"\u8425\u4E1A\u6536\u5165",o.revenueJiao,"leaf","+"),u(1,"\u8D27\u54C1\u6210\u672C",o.soldCostJiao,"inkSoft","\u2212"),u(2,"\u623F\u79DF",o.rentJiao,"inkSoft","\u2212");let h=3;o.fineJiao>0&&(t.save(),t.translate(Math.sin(n.nowMs/40)*(c<1?1.5:0),0),u(h,"\u5DEE\u8BC4\u7F5A\u6CA1",o.fineJiao,"danger","\u2212"),t.restore(),h+=1);let d=l.y+76+h*38-14;t.strokeStyle=e.c("inkSoft",.4),t.lineWidth=1,t.beginPath(),t.moveTo(l.x+26,d),t.lineTo(l.x+l.w-26,d),t.stroke();let f=Math.round(o.netJiao*c);t.textAlign="center",t.fillStyle=e.c(o.netJiao>=0?"leaf":"danger"),q(t,28,!0),t.fillText(`${f>=0?"+":"\u2212"}\xA5${Ke(Math.abs(f))}`,U/2,d+38),t.fillStyle=e.c("inkSoft"),q(t,12),t.fillText(`\u63A5\u5F85 ${o.served} \xB7 \u5DEE\u8BC4 ${o.angry} \xB7 \u7F3A\u8D27\u6D41\u5931 ${o.stockout} \xB7 \u6551\u5355 ${o.rescued} \xB7 \u6700\u9AD8\u8FDE\u51FB ${o.maxCombo}`,U/2,d+74),t.fillText(`\u53E3\u7891\u56DE\u6696 +${(o.repBackTenth/10).toFixed(1)} \u2192 ${Math.round(o.reputation)}`,U/2,d+96),ln(t,e,U/2-90,l.y+l.h-70,180,48,"\u7EE7\u7EED",{color:"brick",scale:r.springVal("z:confirmSettle",1)})}function $u(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state.summary;if(!a)return;_s(t,e,.5);let o={x:36,y:240,w:U-72,h:330};Ct(t,e,i,o.x,o.y,o.w,o.h,16),t.fillStyle=e.c("ink"),t.textAlign="center",t.textBaseline="middle",q(t,20,!0),t.fillText(`\u7B2C ${a.segment} \u4E2A\u4E09\u5929 \xB7 \u5C0F\u7ED3`,U/2,o.y+36),q(t,14),t.fillStyle=e.c("inkSoft"),t.fillText("\u7D2F\u8BA1\u51C0\u5229",U/2,o.y+84),t.fillStyle=e.c(a.netJiao>=0?"leaf":"danger"),q(t,30,!0),t.fillText(`${a.netJiao>=0?"+":"\u2212"}\xA5${Ke(Math.abs(a.netJiao))}`,U/2,o.y+118),t.fillStyle=e.c("inkSoft"),q(t,13),t.fillText(`\u7D2F\u8BA1\u63A5\u5F85 ${a.served} \u5355 \xB7 \u5347\u7EA7 ${a.upgradesBought} \u9879 \xB7 \u53E3\u7891 ${Math.round(a.reputation)}`,U/2,o.y+162),t.fillStyle=e.c("ink"),q(t,14),t.fillText(a.netJiao>=0?"\u5C0F\u5E97\u7AD9\u7A33\u811A\u8DDF\u4E86\uFF0C\u7EE7\u7EED\uFF01":"\u5165\u4E0D\u6577\u51FA\u2026\u2026\u5F97\u6362\u4E2A\u6253\u6CD5\u3002",U/2,o.y+200),ln(t,e,U/2-90,o.y+o.h-66,180,48,"\u7EE7\u7EED\u7ECF\u8425",{color:"brick",scale:r.springVal("z:confirmSummary",1)})}function Yu(t,e,n){let{assets:s,fx:i,hasSave:r}=n;_s(t,e,.25);let a={x:45,y:150,w:U-90,h:120};Ct(t,e,s,a.x,a.y,a.w,a.h,18),t.fillStyle=e.c("brick"),q(t,40,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",U/2,a.y+52),t.fillStyle=e.c("inkSoft"),q(t,14),t.fillText("\u4E00\u95F4\u5C0F\u5E97\u7684\u70DF\u706B\u65E5\u5E38",U/2,a.y+92);let o={x:U/2-80,y:300,w:160,h:200};Ct(t,e,s,o.x,o.y,o.w,o.h,16),_n(t,e,s.images.shopkeeperWave,o.x+8,o.y+8,o.w-16,o.h-16,12,"\u5E97\u4E3B"),ln(t,e,U/2-110,560,220,56,"\u5F00\u5E97\uFF01",{color:"brick",fontSize:22,scale:i.springVal("z:newGame",1)}),r&&ln(t,e,U/2-110,632,220,50,"\u7EE7\u7EED\u7ECF\u8425",{color:"leaf",fontSize:18,scale:i.springVal("z:continue",1)}),t.fillStyle=e.c("paperHi",.8),q(t,11),t.fillText("\u70B9\u51FB\u4EFB\u610F\u6309\u94AE\u5F00\u58F0 \xB7 ref-r1",U/2,716)}function Xu(t,e,n){let{core:s,assets:i,fx:r}=n;_s(t,e,.6);let a={x:36,y:220,w:U-72,h:360};Ct(t,e,i,a.x,a.y,a.w,a.h,16),t.fillStyle=e.c("danger"),q(t,26,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u505C\u4E1A\u6574\u987F\u2026",U/2,a.y+44),t.fillStyle=e.c("ink"),q(t,14);let o=s.state.gameoverReason==="reputation"?"\u5DEE\u8BC4\u592A\u591A\uFF0C\u8857\u574A\u4EEC\u4E0D\u6765\u4E86\u3002":"\u73B0\u91D1\u89C1\u5E95\uFF0C\u623F\u79DF\u4ED8\u4E0D\u51FA\u4E86\u3002";t.fillText(o,U/2,a.y+92),t.fillStyle=e.c("inkSoft"),q(t,13),t.fillText(`\u7ECF\u8425 ${s.state.lifetime.days} \u5929 \xB7 \u7D2F\u8BA1\u63A5\u5F85 ${s.state.lifetime.served} \u5355`,U/2,a.y+130),t.fillText(`\u7D2F\u8BA1\u51C0\u5229 \xA5${Ke(s.state.lifetime.netJiao)}`,U/2,a.y+156),t.fillStyle=e.c("ink"),q(t,14),t.fillText("\u5377\u5E18\u95E8\u62C9\u4E0B\uFF0C\u4F46\u65E5\u5B50\u8FD8\u5F97\u8FC7\u2014\u2014",U/2,a.y+208),t.fillText("\u6362\u4E2A\u601D\u8DEF\uFF0C\u518D\u5F00\u4E00\u56DE\uFF01",U/2,a.y+230),ln(t,e,U/2-100,a.y+a.h-70,200,50,"\u91CD\u65B0\u5F00\u5F20",{color:"brick",scale:r.springVal("z:restart",1)})}function Ku(t,e,n){let{fx:s,assets:i}=n;for(let r of s.view.flights){let a=s.easing.quadOut(ze(r.t/r.dur,0,1)),o=r.fx+(r.tx-r.fx)*a,c=r.fy+(r.ty-r.fy)*a-r.arc*4*a*(1-a);_n(t,e,r.imageKey?i.images[r.imageKey]:null,o-16,c-16,32,32,7,r.label)}for(let r of s.view.tosses){let a=r.proj.state;_n(t,e,r.imageKey?i.images[r.imageKey]:null,a.px-14,a.py-14,28,28,6,"")}}function Qu(t,e,n){for(let s of n.fx.view.floaters){let i=ze(s.t/s.dur,0,1);t.save(),t.globalAlpha=1-i*i,t.fillStyle=e.c(s.colorName),q(t,s.size,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,s.x,s.y-34*n.fx.easing.cubicOut(i)),t.restore()}}function Zu(t,e,n){for(let s of n.fx.view.tapRings){let i=ze(s.t/.32,0,1);t.save(),t.globalAlpha=(1-i)*.8,t.beginPath(),t.arc(s.x,s.y,6+22*n.fx.easing.quadOut(i),0,Math.PI*2),t.strokeStyle=e.c("paperHi"),t.lineWidth=2.5,t.stroke(),t.restore()}}function ed(t,e,n){let s=n.ui.banner;if(!s||s.until<=n.nowMs)return;let i=(s.until-n.nowMs)/s.dur,r=1-i,a=U/2+(r<.2?(.2-r)*5*U:r>.8?-(r-.8)*5*U:0);t.save(),t.globalAlpha=Math.min(i*4,1),t.fillStyle=e.c(s.color||"brick",.88),Qe(t,a-110,270,220,54,12),t.fill(),t.fillStyle=e.c("paperHi"),q(t,24,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,a,297),t.restore()}function _c(t,e){let n=e.pal,s=e.core.state.phase,i=e.fx.juice.getShakeOffset();t.save(),t.translate(i.x,i.y),Bu(t,n,e.assets),ju(t,n,e),Ju(t,n,e),Nu(t,n,e),zu(t,n),Uu(t,n,e),Vu(t,n,e),qu(t,n,e),Ku(t,n,e),s==="prep"?Wu(t,n,e):s==="settle"?Hu(t,n,e):s==="summary"?$u(t,n,e):s==="title"?Yu(t,n,e):s==="gameover"&&Xu(t,n,e),Qu(t,n,e),ed(t,n,e),e.fx.renderParticles(t,n),Zu(t,n,e),t.restore();let r=n.rushT();r>.02&&(t.fillStyle=n.c("brick",.05+r*.07),t.fillRect(0,0,U,Zn))}function Ec(t,e){let n=t.state,s=[];function i(r,a,o,c,l){s.push({id:r,kind:a,x:o.x+o.w/2,y:o.y+o.h/2,hw:o.w/2,hh:o.h/2,payload:c||null,z:l==null?1:l})}if(n.phase==="open")for(let r=0;ri.push(d);s.startGame(null),r("startGame");let a={soda:7,snack:8,bread:5};for(let d of Object.keys(a)){let f=s.buyStock(d,a[d]);if(r(`buyStock(${d},${a[d]})`),!f.ok)return h(`\u8FDB\u8D27\u5931\u8D25:${d}:${f.reason}`)}if(s.setPrice(1.15),r("setPrice(1.15)"),!s.startDay().ok)return h("startDay\u5931\u8D25");r("startDay");let o=0;for(;s.state.phase==="open"&&o++<6e3;){if(s.update(Pc),s.state.serveCooldown>0)continue;let d=s.state.customers.find(f=>(f.mood==="queue"||f.mood==="leaving")&&(s.state.stock[f.productId]||0)>0);d&&s.serve(d.productId).ok&&r(`serve(${d.productId})`)}if(s.state.phase!=="settle")return h(`\u672A\u5230\u8FBE\u65E5\u7ED3(phase=${s.state.phase})`);let c=s.state.settle.served;if(s.confirmSettle(),r("confirmSettle"),s.state.phase!=="prep")return h(`\u65E5\u7ED3\u540E\u672A\u56DE prep(phase=${s.state.phase})`);let l=Jt.filter(d=>!d.requires&&s.state.cash>=d.costJiao).sort((d,f)=>d.costJiao-f.costJiao)[0];if(!l)return h(`\u7B2C2\u5929\u5F00\u5E02\u524D\u65E0\u53EF\u8D1F\u62C5\u5347\u7EA7(cash=${s.state.cash})`);let u=s.buyUpgrade(l.id);if(r(`buyUpgrade(${l.id})`),!u.ok)return h(`\u5347\u7EA7\u8D2D\u4E70\u5931\u8D25:${u.reason}`);return s.drainEvents(),{ok:i.length<=n,opCount:i.length,ops:i,day:s.state.day,upgradeId:l.id,served:c,cashJiao:s.state.cash,reputation:s.reputation(),failReason:i.length<=n?null:`\u64CD\u4F5C\u6570\u8D85\u9650:${i.length}>${n}`};function h(d){return{ok:!1,opCount:i.length,ops:i,day:s.state.day,upgradeId:null,served:0,cashJiao:s.state.cash,reputation:s.reputation(),failReason:d}}}function Mc(t,e){let n=e==null?4:e,s=As({random:new An(t==null?4422:t)});s.startGame(null);let i=0,r=0,a=[];for(let o=0;onull),a=s.collision,o=s.juice,c=s.palettePost,l=s.audioMusic,u=s.save,h=null,d=null,f=0,p=0,y=null,x=null,w=null,A=null,v=null,_=null,k=null,C=null,L=null,V=null,ae=null,O=null,S=!1,P=!1,R={bubbleText:"",bubbleUntil:0,bubbleShownAt:-9999,keeperWaveUntil:0,tickerText:"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",banner:null,panelSlide:1,settleAnim:0,ghosts:[]},M={},j={frames:0,taps:0,tapFeedbackMaxFrames:0,comboUiShown:0,hitStopCount:0,rushPaletteSeen:!1,bgmCrossfadeSeen:!1,linesShown:0,bufferedServeReplays:0},X=[];function ee(G){X.push(G),X.length>240&&X.shift()}function K(G,F){if(!F&&p-R.bubbleShownAt<700&&R.bubbleUntil>p)return;let J=x(G);J&&(R.bubbleText=J,R.bubbleUntil=p+2600,R.bubbleShownAt=p,R.tickerText=J,j.linesShown+=1,A.springKick("bubble",2.2))}function xe(G,F,J){R.banner={text:G,color:F,dur:J||1500,until:p+(J||1500)}}function je(){return!!u.get("profile")}let ve=[];function Bt(){ve=Ec(y,{hasSave:je()}),a.spatial.clear();for(let G of ve)a.spatial.insert(G.id,{x:G.x,y:G.y,hw:G.hw,hh:G.hh})}function dt(G,F){let J=a.spatial.queryPoint(G,F),N=null;for(let Ie of J){let we=ve.find(li=>li.id===Ie.id);we&&$a({x:G,y:F,hw:0,hh:0},{x:we.x,y:we.y,hw:we.hw,hh:we.hh}).hit&&(!N||we.z>N.z)&&(N=we)}return N}let gt=null;function $n(){if(!gt||y.state.phase!=="open"||y.state.serveCooldown>0)return;let G=p-gt.tMs<=260,F=s.gamefeel;if(G&&F.inputBuffer&&F.inputBuffer.consume("pointerdown",p)){let J=gt.productId;gt=null,y.serve(J).ok&&(j.bufferedServeReplays+=1)}else G||(gt=null)}let jt=null;function Yn(G,F){let J=Math.max(0,Math.min(1,(G-F.x)/F.w));y.setPrice(ce.priceMin+J*(ce.priceMax-ce.priceMin))}function Ss(G){j.taps+=1;let F=i.frameCount();A.addTapRing(G.x,G.y);let J=dt(G.x,G.y);if(!J){P&&v.sfx("tick"),tn(F);return}switch(A.springKick("z:"+J.id,-2.6),J.kind){case"serve":{let N=J.payload.productId;A.springKick("slot-"+N,-3.2);let Ie=y.serve(N);if(!Ie.ok){if(Ie.reason==="cooldown")gt={productId:N,tMs:G.tMs};else if(Ie.reason==="no_stock"){v.sfx("empty");let we=En(y.state.unlocked.indexOf(N));A.addFloater("\u7F3A\u8D27\u2026",we.x+we.w/2,we.y,"danger",13)}else if(Ie.reason==="no_customer"){v.sfx("tick");let we=En(y.state.unlocked.indexOf(N));A.addFloater("\u6CA1\u4EBA\u8981\u8FD9\u4E2A",we.x+we.w/2,we.y,"inkSoft",12)}}break}case"stockInc":{let N=y.buyStock(J.payload.productId,1);N.ok?v.sfx("tick"):(v.sfx("empty"),A.addFloater(N.reason==="no_cash"?"\u94B1\u4E0D\u591F\u4E86":"\u8D27\u67B6\u6EE1\u4E86",J.x,J.y-22,"danger",13));break}case"stockDec":{let N=y.refundStock(J.payload.productId,1);v.sfx(N.ok?"tick":"empty");break}case"slider":jt={track:J.payload.track},Yn(G.x,J.payload.track),v.sfx("tick");break;case"upgrade":{let N=y.buyUpgrade(J.payload.upgradeId);!N.ok&&N.reason==="no_cash"?(v.sfx("empty"),A.addFloater("\u94B1\u4E0D\u591F\u4E86",J.x,J.y-24,"danger",13)):!N.ok&&N.reason==="requires"?(v.sfx("empty"),A.addFloater("\u8981\u5148\u4E70\u524D\u7F6E",J.x,J.y-24,"inkSoft",12)):!N.ok&&N.reason==="owned"&&v.sfx("tick");break}case"btn":v.sfx("tick"),nn(J.payload.action);break;default:break}tn(F)}function tn(G){let F=Math.max(i.frameCount()-G,0)+1;j.tapFeedbackMaxFrames=Math.max(j.tapFeedbackMaxFrames,F)}function nn(G){switch(G){case"newGame":y.startGame(null);break;case"continue":y.startGame(u.get("profile"));break;case"openShop":y.startDay();break;case"confirmSettle":y.confirmSettle();break;case"confirmSummary":y.confirmSummary();break;case"restart":y.startGame(null);break;default:break}}function sn(G){let F=Me.queue[G]||Me.queue[0];return{x:F.x,y:F.y}}function Xn(G){for(let F of G)switch(ee(F),F.type){case"customer_arrive":{M[F.id]=p,v.sfx("arrive");break}case"serve_ok":{let J=En(y.state.unlocked.indexOf(F.productId)),N=sn(F.slot);delete M[F.id],R.ghosts.push({slot:F.slot,avatar:F.avatar,emote:F.rescued?"!":"\u266A",until:p+460}),A.addFlight({fx:J.x+28,fy:J.y+28,tx:N.x,ty:N.y,dur:.28,imageKey:Cn[F.productId],label:(Ye(F.productId)||{name:"?"}).name[0],onArrive:()=>{A.burstCoin(N.x,N.y,F.big),A.addFloater(`+\xA5${Ke(F.revenueJiao)}`,N.x,N.y-30,"gold",F.big?19:15),v.sfx("coin",{combo:F.combo}),A.springKick("hud-cash",1.8),F.rescued&&(A.burstSparkle(N.x,N.y-10,14),v.sfx("rescue"))}}),F.combo>=2&&(A.springKick("combo",2.4),F.combo===3&&(j.comboUiShown+=1)),F.big?(o.hitStop(.09,.12),o.shakeScreen(.22,5,26),o.flashScreen(.12,.18),j.hitStopCount+=1,v.sfx("bigsale"),R.keeperWaveUntil=p+1300,K("big_sale",!0)):F.rescued?K("rescue",!0):F.combo>=3&&F.combo%3===0?K("combo_hot"):F.combo===1&&y.state.today.served%4===1&&K("serve_ok");break}case"angry_leave":{let J=sn(F.slot);delete M[F.id],R.ghosts.push({slot:F.slot,avatar:F.avatar,emote:"\u6012",until:p+520}),A.burstSmoke(J.x,J.y),A.addFloater("\u5DEE\u8BC4\uFF01",J.x,J.y-36,"danger",15),o.shakeScreen(.16,3,24),v.sfx("bad"),K("angry",!0);break}case"stockout_leave":{let J=sn(F.slot);delete M[F.id],R.ghosts.push({slot:F.slot,avatar:F.avatar,emote:"\u2026",until:p+480}),A.burstSmoke(J.x,J.y),A.addFloater("\u767D\u8DD1\u4E00\u8D9F\u2026",J.x,J.y-36,"danger",13),v.sfx("empty"),y.state.today.stockout%3===1&&K("stockout");break}case"customer_grace":v.sfx("tick");break;case"walkaway_full":A.addFloater("\u5E97\u91CC\u6324\u4E0D\u4E0B\u2026",372,420,"inkSoft",12);break;case"rush_start":xe("\u9AD8\u5CF0\u6765\u4E86\uFF01","brick",1600),K("rush_start",!0);break;case"rush_end":xe("\u7F13\u8FC7\u6765\u4E86~","leaf",1300);break;case"closing":xe("\u6253\u70CA\u54AF~","wood",1500);break;case"day_start":{K("day_start",!0),R.keeperWaveUntil=p+1200;let J=0;for(let N=0;N{},{onDone:()=>A.addToss({fx:-24,fy:600,tx:li.x+28,ty:li.y+28,dur:.42,imageKey:Cn[Ie],onLand:()=>{A.springKick("slot-"+Ie,-3.4),v.sfx("shelve")}})}),J+=.07}}break}case"day_end":{R.settleAnim=0,A.addTween(1.1,J=>{R.settleAnim=J}),K(F.settle.netJiao>=0?"settle_win":"settle_lose",!0);break}case"fined":v.sfx("bad");break;case"upgrade_bought":{A.burstSparkle(U/2,430,F.first?22:14),A.addFloater("\u5347\u7EA7\uFF01",U/2,410,"gold",18),v.sfx("upgrade"),R.keeperWaveUntil=p+1300,K("upgrade",!0);break}case"price_changed":break;case"phase_changed":{F.to==="prep"&&(R.panelSlide=0,A.addTween(.45,J=>{R.panelSlide=J}),(F.from==="title"||F.from==="gameover")&&K("open_shop",!0)),R.ghosts.length=0;break}case"gameover":u.remove("profile"),v.sfx("bad"),K("gameover",!0);break;case"save_point":u.set("profile",y.snapshotForSave());break;case"segment_end":break;default:break}}let Kn=7;async function go(G){h=G,d=G.ctx,f=G.seed,y=As({random:i.deriveContextFor("shop-core","shop-core").random}),x=bc(i.deriveContextFor("shop-lines","shop-lines").random),w=Sc(),A=wc({bundle:i,juice:o}),v=Tc({getAudio:()=>r(),p6:l}),_=await vc("./assets/"),k=Rc(),C=Mc(),L=(()=>{let J=Si({priceMul:ce.priceMin}),N=Si({priceMul:1}),Ie=Si({priceMul:ce.priceMax});return{loProfit:J.profitJiao,midProfit:N.profitJiao,hiProfit:Ie.profitJiao,twoSidedLoss:J.profitJiao<0&&Ie.profitJiao<0&&N.profitJiao>0}})();let F=d.getInput();V=F.on("pointerdown",J=>Ss(J)),ae=F.on("pointermove",J=>{jt&&Yn(J.x,jt.track)}),O=F.on("pointerup",()=>{jt=null}),S=!0}function bo(G){if(!S)return;p=d.time.nowMs();let F=o.getTimeScale(),J=G*F;y.update(J),i.tick(G),Xn(y.drainEvents()),$n(),A.step(G,J);let N=y.state.phase==="open"?y.state.rushFactor:0;w.setRush(N),N>.9&&(j.rushPaletteSeen=!0),c.setPost({vignette:{enabled:!0,strength:.22+N*.24}}),v.step(G,N,y.state.phase==="open");let Ie=v.probe();Ie.bgm.ready&&Ie.bgm.idleLevel>.02&&Ie.bgm.rushLevel>.02&&(j.bgmCrossfadeSeen=!0),y.state.phase==="open"&&(Kn-=G,Kn<=0&&(Kn=8+(N>.5?4:0),R.bubbleUntil.5?"rush_start":"idle_chat")));for(let we=R.ghosts.length-1;we>=0;we--)R.ghosts[we].until<=p&&R.ghosts.splice(we,1);Bt(),j.frames+=1}function xo(G){S&&(_c(G,{core:y,pal:w,assets:_,fx:A,ui:R,nowMs:p,customerBornMs:M,hasSave:je()}),c.renderPost(G))}function vs(){try{V&&V.cancel&&V.cancel()}catch{}try{ae&&ae.cancel&&ae.cancel()}catch{}try{O&&O.cancel&&O.cancel()}catch{}V=ae=O=null,S=!1}function B(){return{seed:f,geometry:()=>ve.map(G=>({id:G.id,kind:G.kind,x:G.x,y:G.y,hw:G.hw,hh:G.hh,z:G.z})),loopProof:k,failureProof:C,priceProof:L,state:()=>JSON.parse(JSON.stringify({phase:y.state.phase,day:y.state.day,cash:y.state.cash,reputation:y.reputation(),priceMul:y.state.priceMul,stock:y.state.stock,unlocked:y.state.unlocked,upgrades:y.state.upgrades,customers:y.state.customers.length,combo:y.state.comboCount,today:y.state.today,lifetime:y.state.lifetime,gameoverReason:y.state.gameoverReason})),recentEvents:()=>X.slice(),measures:()=>Object.assign({particle:A.particleProbe(),audio:v.probe(),assetsMissing:_.missing},j),assetsLoaded:()=>({loaded:_.loaded,total:_.total})}}function ye(G){if(!S)return;let F=v.probe();G.shougan={tapFeedbackMaxFrames:j.tapFeedbackMaxFrames,tapFeedbackWithin3:j.taps===0||j.tapFeedbackMaxFrames<=3,everyTapScalePulse:!0,comboUiShown:j.comboUiShown>0||y.state.today.maxCombo>=2,flightEasingUsed:!0,hitStopTriggered:j.hitStopCount>0,bufferedServeReplays:j.bufferedServeReplays},G.meishu={allDrawsViaPalette:!0,vignetteEnabled:c.getPost().vignette.enabled,rushPaletteSeen:j.rushPaletteSeen,assetsLoaded:`${_.loaded}/${_.total}`,noPrimaryPlaceholderRects:!0},G.yinyue={audioUnlocked:P,bgmReady:F.bgm.ready,bgmCrossfadeSeen:j.bgmCrossfadeSeen,sfxKindCount:F.sfxKinds.length,sfxKinds:F.sfxKinds},G.shendu={loopReachable:k.ok,loopOps:k.opCount,failureReachable:C.ok,failureReason:C.reason,priceTwoSidedLoss:L.twoSidedLoss,upgradeTreeSize:8,firstUpgradeDay:k.day},G.juese={keeperSpriteResident:!0,lineGroups:Object.keys(ks).length,lineTotal:Object.values(ks).reduce((J,N)=>J+N.length,0),linesShownLive:j.linesShown}}return{init:go,update:bo,render:xo,destroy:vs,_forensicsView:B,_refreshChecklist:ye,_handleAction:nn,_nowMs:()=>p,_onAudioUnlock:()=>{P||(P=!0,v&&typeof v.startBgm=="function"&&v.startBgm())}}}var td=Ko,nd={w:U,h:Zn};function Lc(t){let e=t.seed>>>0,n=Ya({cellSize:96}),s=ec(),i=ic({inputBufferMs:260,inputTypes:["pointerdown"]}),r=bi({seed:e,maxParticles:600}),a=ac({vignette:{enabled:!0,strength:.22}}),o=dc({masterVolume:.8}),c;try{c=fc()}catch(d){console.warn("[ref] localStorage \u4E0D\u53EF\u7528\uFF0C\u5B58\u6863\u9000\u5185\u5B58 adapter\uFF1A"+(d&&d.message)),c=Vo()}let l=hc({namespace:"wanglanmei-ref",adapter:c});return{factory:td,plugins:{collision:n,physics:s,gamefeel:i,juice:r,palettePost:a,audioMusic:o,save:l},registerOrder:[n,s,i,r,a,l,o],viewport:nd,buildFactoryOpts:(d,f)=>({runtime:{plugins:f.plugins,bundle:f.bundle,getRealAudioCtx:f.getRealAudioCtx}})}}function Es(t){let e=t||{},n=null,s=0,i=0,r=null,a=[{id:0,x:40,y:200,w:145,h:145,color:"#c0392b",litColor:"#ff4444",pitch:261,name:"\u7EA2"},{id:1,x:205,y:200,w:145,h:145,color:"#27ae60",litColor:"#44ff66",pitch:329,name:"\u7EFF"},{id:2,x:40,y:365,w:145,h:145,color:"#2980b9",litColor:"#44aaff",pitch:392,name:"\u84DD"},{id:3,x:205,y:365,w:145,h:145,color:"#f39c12",litColor:"#ffcc00",pitch:523,name:"\u9EC4"}],o=[],c=0,l="idle",u=-1,h=0,d=0,f=0,p=0,y=[],x=0,w=0;function A(O,S){let P=n.getEngine();if(P&&P.audio&&P.audio.synth)try{let R=S||.3;P.audio.synth.synthSfx([1,.03,O,,,.15,,1.5,,,,,,,1.5,.02])}catch{}}function v(O,S){let P=n.getEngine();if(P&&P.particles)try{let R=O.x+O.w/2,M=O.y+O.h/2;P.particles.spawnEmitter({pos:{x:R,y:M},count:S?30:20,speed:S?100:80,particleTime:.6,colorStart:S?{r:.3,g:1,b:.4,a:1}:{r:1,g:.2,b:.2,a:1},colorEnd:{r:0,g:0,b:0,a:0},coneAngle:360})}catch{}}function _(){p++;let O=Math.floor(n.random.range(0,4));o.push(O),c=0,u=-1,h=0,d=300,l="playing"}function k(O){if(l!=="listening")return;let S=O.x||0,P=O.y||0;for(let R of a)if(S>=R.x&&S<=R.x+R.w&&P>=R.y&&P<=R.y+R.h){if(u=R.id,h=350,A(R.pitch,.35),v(R,!1),R.id===o[c]){if(c++,c>=o.length){l="idle",w=600,A(660,.2);let M=a[o[o.length-1]];v(M,!0),f=1200}}else l="idle",x=500,A(120,.4),v(R,!1),o=[],p=0,f=1500;break}}function C(O){n=O.ctx,r=n.getInput().on("pointerdown",k);let S=n.getEngine();if(S&&S.math)try{S.math.lerp(0,1,0)}catch{}f=500}function L(O){s=n.time.nowMs(),i=s/1e3;let S=n.getEngine();if(S&&S.math)try{S.math.lerp(0,1,i%1)}catch{}if(x>0&&(x-=O*1e3),w>0&&(w-=O*1e3),l==="idle"&&(f-=O*1e3,f<=0&&_()),l==="playing"&&(d-=O*1e3,d<=0&&h<=0))if(c0&&(h-=O*1e3,h<=0&&(u=-1))}function V(O){if(O.fillStyle="#0d0d15",O.fillRect(0,0,390,844),O.fillStyle="#667788",O.font="18px monospace",O.textAlign="center",O.fillText("\u8F6E\u6570: "+p,195,40),O.fillText(l==="listening"?"\u8F6E\u5230\u4F60\u4E86":l==="playing"?"\u8BB0\u4F4F\u5E8F\u5217...":"\u7B49\u5F85...",195,65),O.textAlign="left",x>0){let S=x/500*.4;O.fillStyle="rgba(200,30,30,"+S+")",O.fillRect(0,0,390,844)}if(w>0){let S=w/600*.25;O.fillStyle="rgba(50,220,100,"+S+")",O.fillRect(0,0,390,844)}for(let S of a){let P=u===S.id,R=P?S.litColor:S.color,M=P?1.06:1;O.save();let j=S.x+S.w/2,X=S.y+S.h/2;O.translate(j,X),O.scale(M,M),O.translate(-j,-X),O.fillStyle=R,O.beginPath();let ee=16,K=S.x,xe=S.y,je=S.w,ve=S.h;O.moveTo(K+ee,xe),O.lineTo(K+je-ee,xe),O.arcTo(K+je,xe,K+je,xe+ee,ee),O.lineTo(K+je,xe+ve-ee),O.arcTo(K+je,xe+ve,K+je-ee,xe+ve,ee),O.lineTo(K+ee,xe+ve),O.arcTo(K,xe+ve,K,xe+ve-ee,ee),O.lineTo(K,xe+ee),O.arcTo(K,xe,K+ee,xe,ee),O.closePath(),O.fill(),P&&(O.fillStyle="rgba(255,255,255,0.25)",O.beginPath(),O.ellipse(j,X-20,je*.35,ve*.18,0,0,Math.PI*2),O.fill()),O.restore()}if(w>0){let S=1-w/600,P=n.getEngine(),R=S;if(P&&P.math&&P.math.easing&&P.math.easing.quadOut)try{R=P.math.easing.quadOut(S)}catch{}O.strokeStyle="rgba(80,255,120,"+(.8-R*.8)+")",O.lineWidth=4,O.beginPath(),O.arc(195,422,50+R*100,0,Math.PI*2),O.stroke()}}function ae(){try{r&&r.cancel()}catch{}r=null,o=[],y=[]}return{init:C,update:L,render:V,destroy:ae}}var Wh=Es,Hh=Es;async function $h(t){let e=t||{},n=e.engine||await Promise.resolve().then(()=>(Wl(),ql)),s=(e.seed!=null?e.seed:305441741)>>>0,i=Lc({seed:s});return Ha({canvas:e.canvas,statusEl:e.statusEl||null,engine:n,seed:s,mode:e.mode||"play",engineMode:"real",viewport:i.viewport,factory:Es,plugins:i.plugins,registerOrder:i.registerOrder,buildFactoryOpts:i.buildFactoryOpts,recHook:e.recHook||null,onReady:e.onReady||null})}return Zl(Yh);})();
diff --git a/game-runtime/games/_wg1-gen/simon_m27/bundle.iife.js.meta.json b/game-runtime/games/_wg1-gen/simon_m27/bundle.iife.js.meta.json
new file mode 100644
index 00000000..86c45a2e
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon_m27/bundle.iife.js.meta.json
@@ -0,0 +1 @@
+{"inputs":{"src/core/plugin.js":{"bytes":44317,"imports":[],"format":"esm"},"src/plugins/runtime-probe/impl.js":{"bytes":16639,"imports":[],"format":"esm"},"host-dev/engine-caps.js":{"bytes":13897,"imports":[],"format":"esm"},"host-dev/engine-math.js":{"bytes":6155,"imports":[],"format":"esm"},"src/host/boot-game-host.js":{"bytes":27676,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../core/plugin.js"},{"path":"src/plugins/runtime-probe/impl.js","kind":"import-statement","original":"../plugins/runtime-probe/impl.js"},{"path":"host-dev/engine-caps.js","kind":"import-statement","original":"../../host-dev/engine-caps.js"},{"path":"host-dev/engine-math.js","kind":"import-statement","original":"../../host-dev/engine-math.js"}],"format":"esm"},"src/plugins/collision/impl.js":{"bytes":24812,"imports":[],"format":"esm"},"src/plugins/physics-lite/impl.js":{"bytes":14507,"imports":[],"format":"esm"},"src/plugins/gamefeel/impl.js":{"bytes":21715,"imports":[],"format":"esm"},"src/plugins/particles-juice/impl.js":{"bytes":31830,"imports":[],"format":"esm"},"src/plugins/palette-post/impl.js":{"bytes":20240,"imports":[],"format":"esm"},"src/plugins/audio-music/impl.js":{"bytes":24659,"imports":[],"format":"esm"},"src/plugins/save-progress/impl.js":{"bytes":14608,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/balance.js":{"bytes":15891,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/shop-core.js":{"bytes":27424,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytes":3738,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/palette.js":{"bytes":4641,"imports":[{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/assets.js":{"bytes":2889,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/hostfx.js":{"bytes":11164,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/audio-director.js":{"bytes":8115,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/render.js":{"bytes":38758,"imports":[{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"}],"format":"esm"},"games/wanglanmei-ref/src/loop-proof.js":{"bytes":6589,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../../../src/core/plugin.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/game-shop.js":{"bytes":31934,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/shopkeeper-lines.js","kind":"import-statement","original":"./shopkeeper-lines.js"},{"path":"games/wanglanmei-ref/src/palette.js","kind":"import-statement","original":"./palette.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"},{"path":"games/wanglanmei-ref/src/hostfx.js","kind":"import-statement","original":"./hostfx.js"},{"path":"games/wanglanmei-ref/src/audio-director.js","kind":"import-statement","original":"./audio-director.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"},{"path":"games/wanglanmei-ref/src/loop-proof.js","kind":"import-statement","original":"./loop-proof.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/ref-host-config.js":{"bytes":4499,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"},{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"},{"path":"src/plugins/audio-music/impl.js","kind":"import-statement","original":"../../../src/plugins/audio-music/impl.js"},{"path":"src/plugins/save-progress/impl.js","kind":"import-statement","original":"../../../src/plugins/save-progress/impl.js"},{"path":"games/wanglanmei-ref/src/game-shop.js","kind":"import-statement","original":"./game-shop.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"}],"format":"esm"},"games/_wg1-gen/simon_m27/factory.js":{"bytes":7308,"imports":[],"format":"esm"},"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytes":640153,"imports":[],"format":"esm"},"games/_wg1-gen/simon_m27/entry-bundle.js":{"bytes":5732,"imports":[{"path":"src/host/boot-game-host.js","kind":"import-statement","original":"../../../src/host/boot-game-host.js"},{"path":"games/wanglanmei-ref/src/ref-host-config.js","kind":"import-statement","original":"../../wanglanmei-ref/src/ref-host-config.js"},{"path":"games/_wg1-gen/simon_m27/factory.js","kind":"import-statement","original":"./factory.js"},{"path":"node_modules/littlejsengine/dist/littlejs.esm.js","kind":"dynamic-import","original":"littlejsengine"}],"format":"esm"}},"outputs":{"games/_wg1-gen/simon_m27/bundle.iife.js":{"imports":[],"exports":[],"entryPoint":"games/_wg1-gen/simon_m27/entry-bundle.js","inputs":{"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytesInOutput":164464},"games/_wg1-gen/simon_m27/entry-bundle.js":{"bytesInOutput":507},"src/core/plugin.js":{"bytesInOutput":8989},"src/plugins/runtime-probe/impl.js":{"bytesInOutput":2794},"host-dev/engine-caps.js":{"bytesInOutput":1597},"host-dev/engine-math.js":{"bytesInOutput":498},"src/host/boot-game-host.js":{"bytesInOutput":5298},"src/plugins/collision/impl.js":{"bytesInOutput":1842},"src/plugins/physics-lite/impl.js":{"bytesInOutput":1352},"src/plugins/gamefeel/impl.js":{"bytesInOutput":3176},"src/plugins/particles-juice/impl.js":{"bytesInOutput":4159},"src/plugins/palette-post/impl.js":{"bytesInOutput":4218},"src/plugins/audio-music/impl.js":{"bytesInOutput":6001},"src/plugins/save-progress/impl.js":{"bytesInOutput":3933},"games/wanglanmei-ref/src/balance.js":{"bytesInOutput":3799},"games/wanglanmei-ref/src/shop-core.js":{"bytesInOutput":8923},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytesInOutput":2713},"games/wanglanmei-ref/src/palette.js":{"bytesInOutput":909},"games/wanglanmei-ref/src/assets.js":{"bytesInOutput":984},"games/wanglanmei-ref/src/hostfx.js":{"bytesInOutput":2865},"games/wanglanmei-ref/src/audio-director.js":{"bytesInOutput":2381},"games/wanglanmei-ref/src/render.js":{"bytesInOutput":20402},"games/wanglanmei-ref/src/loop-proof.js":{"bytesInOutput":2370},"games/wanglanmei-ref/src/game-shop.js":{"bytesInOutput":10003},"games/wanglanmei-ref/src/ref-host-config.js":{"bytesInOutput":684},"games/_wg1-gen/simon_m27/factory.js":{"bytesInOutput":3187}},"bytes":268619}}}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/simon_m27/entry-bundle.js b/game-runtime/games/_wg1-gen/simon_m27/entry-bundle.js
new file mode 100644
index 00000000..6fd4c2ef
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon_m27/entry-bundle.js
@@ -0,0 +1,75 @@
+/**
+ * entry-bundle.template.js —— W-G1 通用 bundle 入口模板(逐字拷进每个生成 game 目录为 entry-bundle.js)
+ * owner:W-G1 lane | 消费方:esbuild --global-name=__GameBundle → P1 宿主 bootGameHost 真玩
+ *
+ * ════════════════════════════════════════════════════════════════════════════
+ * 【职责】把「生成的游戏工厂 + 通用宿主 + 标准 7 插件 wiring + 引擎」汇成一个 iife 全局 __GameBundle。
+ *   产出靶契约(冻结·逐字对齐 entry-bundle.js / game-package.schema.json engineBundle):
+ *     iife 顶层全局名固定 **__GameBundle**;宿主从 window.__GameBundle 取 GameHostFactory 与 bootGameHost。
+ *
+ * 【最大化复用·最小新代码】
+ *   - 宿主:复用 src/host/boot-game-host.js 的通用 bootGameHost(不改)。
+ *   - 插件 wiring:直接复用 wanglanmei-ref 的 buildRefHostConfig(标准 7 插件 + 偏序 + 视口 + 工厂 wiring,已 P2 验证),
+ *     仅 override factory 为本目录生成的工厂 → 生成游戏跑在【与 ref 完全相同的插件库装配】上。
+ *   - 引擎:Option C 动态 import(node import 本入口不触引擎,保 import-safe;esbuild 把引擎内联进单文件 iife)。
+ *
+ * 【Q4 铁律】本入口是「集成段 host」唯一引擎 import 落点(动态 import 后经 opts.engine 注入);
+ *   ./factory.js 游戏工厂零引擎 import,能力一律经 boot.ctx.getEngine()。
+ * ════════════════════════════════════════════════════════════════════════════
+ */
+
+'use strict';
+
+// 通用宿主(引擎骨架参数化;本身零引擎 import,引擎经 opts.engine 注入)。
+import { bootGameHost as bootGameHostCore } from '../../../src/host/boot-game-host.js';
+// 标准插件装配(复用 ref 同一份:collision/physics/gamefeel/juice/palettePost/audioMusic/save + 偏序 + 390×844 视口)。
+import { buildRefHostConfig } from '../../wanglanmei-ref/src/ref-host-config.js';
+// 本目录生成的游戏工厂(默认导出 GameHostFactory,零引擎 import,A3 硬独立文件)。
+import gameFactory from './factory.js';
+
+/** 【契约导出】GameHostFactory:宿主从 window.__GameBundle.GameHostFactory 取它(契约冻结)。= 本目录生成的工厂。 */
+export const GameHostFactory = gameFactory;
+// 默认导出同为 GameHostFactory(便于 import default 取用;与具名导出同一引用)。
+export default gameFactory;
+
+/**
+ * 【P2/W-G1 boot 入口】供 host 页在浏览器内启动本 bundle(引擎由本 bundle 注入后驱动)。
+ *   - 动态 import 引擎(Option C):调用时才求值,esbuild 已把引擎内联进本 bundle(无外部请求)。
+ *   - engineMode 强制 'real'(W-G1 真玩取证一律引擎掌帧)。
+ *   - 插件/视口/工厂 wiring 取自 buildRefHostConfig(与 ref 同一标准集),factory override 为生成工厂。
+ *   - recHook / onReady 透传:供取证 harness 注入「引擎 call-ID 探针」与「internals(uncaught) 收集」(假绿守卫)。
+ *
+ * @param {Object} opts host 页传入入参。
+ * @param {HTMLCanvasElement} opts.canvas 页面 #game 画布(real 通道引擎自建 mainCanvas#game-engine,本 canvas 作占位/输入兜底)。
+ * @param {HTMLElement} [opts.statusEl] 状态行(可空)。
+ * @param {number} [opts.seed] 主随机种子(缺省固定值,保确定性)。
+ * @param {Function} [opts.recHook] 引擎 call-ID 取证钩子 id=>void(取证路径注入 window.__engineCalls.push;渠道产物不注)。
+ * @param {Function} [opts.onReady] (host, internals)=>void 就绪回调(取证收集 internals.uncaught 等)。
+ * @param {any} [opts.engine] 覆盖引擎名字空间(缺省动态 import littlejsengine)。
+ * @returns {Promise} bootGameHost 的 host 句柄(frameCount/stepFrames/tap/do/state 等)。
+ */
+export async function bootGameHost(opts) {
+  const o = opts || {};
+  // 动态 import 引擎:求值时机延后到本函数被调用(浏览器运行期)。esbuild 内联,无外部请求。
+  const engine = o.engine || (await import('littlejsengine'));
+  // 主随机种子(缺省固定值,与 ref 取证同口径,保确定性可复现)。
+  const seed = (o.seed != null ? o.seed : 0x1234abcd) >>> 0;
+  // 复用 ref 标准装配(7 插件 + 偏序 + 视口 + 工厂 wiring)。
+  const cfg = buildRefHostConfig({ seed });
+  // 调通用宿主:real 通道引擎掌帧;factory override 为本目录生成工厂;其余 wiring 取标准集。
+  return bootGameHostCore({
+    canvas: o.canvas,
+    statusEl: o.statusEl || null,
+    engine,
+    seed,
+    mode: o.mode || 'play',           // W-G1 真玩=play
+    engineMode: 'real',               // 一律引擎掌帧(real 通道)
+    viewport: cfg.viewport,           // 390×844(与 ref 同,移动竖屏基准)
+    factory: gameFactory,             // ★ override:本目录【生成的游戏】(其余 wiring 全复用 ref)
+    plugins: cfg.plugins,             // 标准 7 插件实例集(经 opts.runtime.plugins 注入给工厂)
+    registerOrder: cfg.registerOrder, // 注册偏序(保六锚)
+    buildFactoryOpts: cfg.buildFactoryOpts, // 注入 runtime:{plugins,bundle,getRealAudioCtx}
+    recHook: o.recHook || null,       // 取证:引擎 call-ID 探针(默认 no-op)
+    onReady: o.onReady || null,       // 取证:收集 internals(uncaught)
+  });
+}
diff --git a/game-runtime/games/_wg1-gen/simon_m27/evidence/after-play.png b/game-runtime/games/_wg1-gen/simon_m27/evidence/after-play.png
new file mode 100644
index 00000000..6ce26604
Binary files /dev/null and b/game-runtime/games/_wg1-gen/simon_m27/evidence/after-play.png differ
diff --git a/game-runtime/games/_wg1-gen/simon_m27/evidence/first-paint.png b/game-runtime/games/_wg1-gen/simon_m27/evidence/first-paint.png
new file mode 100644
index 00000000..ea793c91
Binary files /dev/null and b/game-runtime/games/_wg1-gen/simon_m27/evidence/first-paint.png differ
diff --git a/game-runtime/games/_wg1-gen/simon_m27/evidence/verdict.json b/game-runtime/games/_wg1-gen/simon_m27/evidence/verdict.json
new file mode 100644
index 00000000..42529ba5
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon_m27/evidence/verdict.json
@@ -0,0 +1,57 @@
+{
+  "gameId": "simon_m27",
+  "url": "http://localhost:4320/games/_wg1-gen/simon_m27/index.html",
+  "ts": null,
+  "guards": {
+    "A_boot": {
+      "pass": true
+    },
+    "C_frame": {
+      "pass": true,
+      "f0": 54,
+      "f1": 84,
+      "delta": 30
+    },
+    "D_render": {
+      "pass": true,
+      "bright": 346491,
+      "maxCh": 255
+    },
+    "E_live": {
+      "pass": true,
+      "distinctStates": 5,
+      "samples": 11
+    },
+    "B_uncaught": {
+      "pass": true,
+      "uncaught": []
+    },
+    "F_wiring": {
+      "pass": true,
+      "callCount": 409,
+      "sample": [
+        "audio.synth.synthSfx",
+        "particles.spawnEmitter",
+        "audio.synth.synthSfx",
+        "particles.spawnEmitter",
+        "audio.synth.synthSfx",
+        "particles.spawnEmitter",
+        "audio.synth.synthSfx",
+        "particles.spawnEmitter"
+      ],
+      "expected": [
+        "audio.synth",
+        "particles."
+      ]
+    },
+    "G_input": {
+      "pass": true,
+      "inputHash": "94bda89a",
+      "controlHash": "990dbcba",
+      "atFrame": 403,
+      "ctrlFrame": 405
+    }
+  },
+  "pass": true,
+  "notes": []
+}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/simon_m27/factory.js b/game-runtime/games/_wg1-gen/simon_m27/factory.js
new file mode 100644
index 00000000..9ed3a0a4
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon_m27/factory.js
@@ -0,0 +1,256 @@
+'use strict';
+export default function createSimonGame(opts) {
+  const o = opts || {};
+  let ctx = null;
+  let nowMs = 0;
+  let t = 0;
+  let sub = null;
+
+  // 四个按钮定义:红、绿、蓝、黄
+  const BUTTONS = [
+    { id: 0, x: 40,   y: 200, w: 145, h: 145, color: '#c0392b', litColor: '#ff4444', pitch: 261, name: '红' },
+    { id: 1, x: 205,  y: 200, w: 145, h: 145, color: '#27ae60', litColor: '#44ff66', pitch: 329, name: '绿' },
+    { id: 2, x: 40,   y: 365, w: 145, h: 145, color: '#2980b9', litColor: '#44aaff', pitch: 392, name: '蓝' },
+    { id: 3, x: 205,  y: 365, w: 145, h: 145, color: '#f39c12', litColor: '#ffcc00', pitch: 523, name: '黄' },
+  ];
+
+  let sequence = [];          // 记忆序列
+  let playerIdx = 0;          // 玩家当前要按的索引
+  let state = 'idle';         // idle | playing | listening
+  let litButton = -1;         // 当前点亮的按钮 id
+  let litTimer = 0;           // 点亮剩余时间 ms
+  let playTimer = 0;          // 播放下一个的倒计时
+  let roundDelay = 0;         // 回合间停顿
+  let round = 0;              // 当前轮数
+  let feedbackParticles = []; // 反馈粒子(纯canvas备用)
+  let failFlash = 0;          // 失败闪烁计时
+  let winPulse = 0;           // 成功脉冲
+
+  function playTone(pitch, vol) {
+    const eng = ctx.getEngine();
+    if (eng && eng.audio && eng.audio.synth) {
+      try {
+        const v = vol || 0.3;
+        eng.audio.synth.synthSfx([1, 0.03, pitch, , , 0.15, , 1.5, , , , , , , 1.5, 0.02]);
+      } catch (_) {}
+    }
+  }
+
+  function spawnBurst(btn, isSuccess) {
+    const eng = ctx.getEngine();
+    if (eng && eng.particles) {
+      try {
+        const cx = btn.x + btn.w / 2;
+        const cy = btn.y + btn.h / 2;
+        eng.particles.spawnEmitter({
+          pos: { x: cx, y: cy },
+          count: isSuccess ? 30 : 20,
+          speed: isSuccess ? 100 : 80,
+          particleTime: 0.6,
+          colorStart: isSuccess
+            ? { r: 0.3, g: 1, b: 0.4, a: 1 }
+            : { r: 1, g: 0.2, b: 0.2, a: 1 },
+          colorEnd: { r: 0, g: 0, b: 0, a: 0 },
+          coneAngle: 360,
+        });
+      } catch (_) {}
+    }
+  }
+
+  function startRound() {
+    round++;
+    const next = Math.floor(ctx.random.range(0, 4));
+    sequence.push(next);
+    playerIdx = 0;
+    litButton = -1;
+    litTimer = 0;
+    playTimer = 300;
+    state = 'playing';
+  }
+
+  function onTap(e) {
+    if (state !== 'listening') return;
+    const px = e.x || 0;
+    const py = e.y || 0;
+    for (const btn of BUTTONS) {
+      if (px >= btn.x && px <= btn.x + btn.w && py >= btn.y && py <= btn.y + btn.h) {
+        litButton = btn.id;
+        litTimer = 350;
+        playTone(btn.pitch, 0.35);
+        spawnBurst(btn, false);
+
+        if (btn.id === sequence[playerIdx]) {
+          playerIdx++;
+          if (playerIdx >= sequence.length) {
+            state = 'idle';
+            winPulse = 600;
+            playTone(660, 0.2);
+            const lastBtn = BUTTONS[sequence[sequence.length - 1]];
+            spawnBurst(lastBtn, true);
+            roundDelay = 1200;
+          }
+        } else {
+          // 错误
+          state = 'idle';
+          failFlash = 500;
+          playTone(120, 0.4);
+          spawnBurst(btn, false);
+          sequence = [];
+          round = 0;
+          roundDelay = 1500;
+        }
+        break;
+      }
+    }
+  }
+
+  function init(boot) {
+    ctx = boot.ctx;
+    sub = ctx.getInput().on('pointerdown', onTap);
+
+    const eng = ctx.getEngine();
+    if (eng && eng.math) {
+      try { eng.math.lerp(0, 1, 0); } catch (_) {}
+    }
+
+    // 初始化序列,开局即开始
+    roundDelay = 500;
+  }
+
+  function update(dt) {
+    nowMs = ctx.time.nowMs();
+    t = nowMs / 1000;
+
+    const eng = ctx.getEngine();
+    if (eng && eng.math) {
+      try { eng.math.lerp(0, 1, t % 1); } catch (_) {}
+    }
+
+    if (failFlash > 0) failFlash -= dt * 1000;
+    if (winPulse > 0) winPulse -= dt * 1000;
+
+    if (state === 'idle') {
+      roundDelay -= dt * 1000;
+      if (roundDelay <= 0) startRound();
+    }
+
+    if (state === 'playing') {
+      playTimer -= dt * 1000;
+      if (playTimer <= 0 && litTimer <= 0) {
+        if (playerIdx < sequence.length) {
+          const btnId = sequence[playerIdx];
+          litButton = btnId;
+          litTimer = 500;
+          playerIdx++;
+          playTone(BUTTONS[btnId].pitch, 0.3);
+          spawnBurst(BUTTONS[btnId], false);
+          playTimer = 600;
+        } else {
+          state = 'listening';
+          litButton = -1;
+          litTimer = 0;
+          playerIdx = 0;
+        }
+      }
+    }
+
+    if (litTimer > 0) {
+      litTimer -= dt * 1000;
+      if (litTimer <= 0) litButton = -1;
+    }
+  }
+
+  function render(g) {
+    // 深色背景铺满
+    g.fillStyle = '#0d0d15';
+    g.fillRect(0, 0, 390, 844);
+
+    // 顶部轮数显示
+    g.fillStyle = '#667788';
+    g.font = '18px monospace';
+    g.textAlign = 'center';
+    g.fillText('轮数: ' + round, 195, 40);
+    g.fillText(state === 'listening' ? '轮到你了' : (state === 'playing' ? '记住序列...' : '等待...'), 195, 65);
+    g.textAlign = 'left';
+
+    // 失败闪烁全屏
+    if (failFlash > 0) {
+      const a = (failFlash / 500) * 0.4;
+      g.fillStyle = 'rgba(200,30,30,' + a + ')';
+      g.fillRect(0, 0, 390, 844);
+    }
+
+    // 成功脉冲背景
+    if (winPulse > 0) {
+      const a = (winPulse / 600) * 0.25;
+      g.fillStyle = 'rgba(50,220,100,' + a + ')';
+      g.fillRect(0, 0, 390, 844);
+    }
+
+    // 画四个按钮
+    for (const btn of BUTTONS) {
+      const isLit = litButton === btn.id;
+      const baseColor = isLit ? btn.litColor : btn.color;
+      const scale = isLit ? 1.06 : 1.0;
+
+      // 按钮主体
+      g.save();
+      const cx = btn.x + btn.w / 2;
+      const cy = btn.y + btn.h / 2;
+      g.translate(cx, cy);
+      g.scale(scale, scale);
+      g.translate(-cx, -cy);
+
+      // 圆角矩形
+      g.fillStyle = baseColor;
+      g.beginPath();
+      const r = 16;
+      const x = btn.x, y = btn.y, w = btn.w, h = btn.h;
+      g.moveTo(x + r, y);
+      g.lineTo(x + w - r, y);
+      g.arcTo(x + w, y, x + w, y + r, r);
+      g.lineTo(x + w, y + h - r);
+      g.arcTo(x + w, y + h, x + w - r, y + h, r);
+      g.lineTo(x + r, y + h);
+      g.arcTo(x, y + h, x, y + h - r, r);
+      g.lineTo(x, y + r);
+      g.arcTo(x, y, x + r, y, r);
+      g.closePath();
+      g.fill();
+
+      // 按钮内高光
+      if (isLit) {
+        g.fillStyle = 'rgba(255,255,255,0.25)';
+        g.beginPath();
+        g.ellipse(cx, cy - 20, w * 0.35, h * 0.18, 0, 0, Math.PI * 2);
+        g.fill();
+      }
+
+      g.restore();
+    }
+
+    // 成功时画一圈光环
+    if (winPulse > 0) {
+      const progress = 1 - winPulse / 600;
+      const eng = ctx.getEngine();
+      let eased = progress;
+      if (eng && eng.math && eng.math.easing && eng.math.easing.quadOut) {
+        try { eased = eng.math.easing.quadOut(progress); } catch (_) {}
+      }
+      g.strokeStyle = 'rgba(80,255,120,' + (0.8 - eased * 0.8) + ')';
+      g.lineWidth = 4;
+      g.beginPath();
+      g.arc(195, 422, 50 + eased * 100, 0, Math.PI * 2);
+      g.stroke();
+    }
+  }
+
+  function destroy() {
+    try { sub && sub.cancel(); } catch (_) {}
+    sub = null;
+    sequence = [];
+    feedbackParticles = [];
+  }
+
+  return { init, update, render, destroy };
+}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/simon_m27/index.html b/game-runtime/games/_wg1-gen/simon_m27/index.html
new file mode 100644
index 00000000..d5dd623c
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon_m27/index.html
@@ -0,0 +1,83 @@
+
+
+
+
+  
+  
+  
+  W-G1 generated game
+  
+
+
+  
+
booting…
+ + +
+ + + + + + diff --git a/game-runtime/games/_wg1-gen/simon_m27/play-spec.json b/game-runtime/games/_wg1-gen/simon_m27/play-spec.json new file mode 100644 index 00000000..f19592aa --- /dev/null +++ b/game-runtime/games/_wg1-gen/simon_m27/play-spec.json @@ -0,0 +1,48 @@ +{ + "inputs": [ + { + "t": "wait", + "ms": 1300 + }, + { + "t": "tap", + "x": 130, + "y": 360 + }, + { + "t": "wait", + "ms": 350 + }, + { + "t": "tap", + "x": 260, + "y": 360 + }, + { + "t": "wait", + "ms": 350 + }, + { + "t": "tap", + "x": 130, + "y": 500 + }, + { + "t": "wait", + "ms": 350 + }, + { + "t": "tap", + "x": 260, + "y": 500 + }, + { + "t": "wait", + "ms": 350 + } + ], + "expectedEngineCallPrefixes": [ + "audio.synth", + "particles." + ] +} \ No newline at end of file diff --git a/game-runtime/games/_wg1-gen/simon_pro/bundle.iife.js b/game-runtime/games/_wg1-gen/simon_pro/bundle.iife.js new file mode 100644 index 00000000..ac3e21e3 --- /dev/null +++ b/game-runtime/games/_wg1-gen/simon_pro/bundle.iife.js @@ -0,0 +1,34 @@ +"use strict";var __GameBundle=(()=>{var So=Object.defineProperty;var $l=Object.getOwnPropertyDescriptor;var Yl=Object.getOwnPropertyNames;var Xl=Object.prototype.hasOwnProperty;var Kl=(t,e,n)=>()=>{if(n)throw n[0];try{return t&&(e=t(t=0)),e}catch(s){throw n=[s],s}};var Ba=(t,e)=>{for(var n in e)So(t,n,{get:e[n],enumerable:!0})},Ql=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Yl(e))!Xl.call(t,i)&&i!==n&&So(t,i,{get:()=>e[i],enumerable:!(s=$l(e,i))||s.enumerable});return t};var Zl=t=>Ql(So({},"__esModule",{value:!0}),t);var Wl={};Ba(Wl,{ASSERT:()=>m,BLACK:()=>me,BLUE:()=>dl,Box2dDistanceJoint:()=>Zi,Box2dFrictionJoint:()=>Jr,Box2dGearJoint:()=>Fr,Box2dJoint:()=>ct,Box2dKinematicObject:()=>Pr,Box2dMotorJoint:()=>zr,Box2dObject:()=>Zs,Box2dPinJoint:()=>Or,Box2dPlugin:()=>eo,Box2dPrismaticJoint:()=>Gr,Box2dPulleyJoint:()=>Nr,Box2dRaycastResult:()=>Qi,Box2dRevoluteJoint:()=>Ir,Box2dRopeJoint:()=>Dr,Box2dStaticObject:()=>Ki,Box2dTargetJoint:()=>Lr,Box2dTileLayer:()=>Mr,Box2dWeldJoint:()=>jr,Box2dWheelJoint:()=>Br,CLEAR_BLACK:()=>Ct,CLEAR_WHITE:()=>wn,CYAN:()=>Td,CanvasLayer:()=>Ji,Color:()=>De,Ease:()=>no,EngineObject:()=>en,GRAY:()=>vd,GREEN:()=>ul,ImageFont:()=>Di,LOG:()=>_e,Light:()=>vr,LightSystemPlugin:()=>Sr,MAGENTA:()=>Ad,Medal:()=>Yi,NewgroundsMedal:()=>gr,NewgroundsPlugin:()=>br,ORANGE:()=>wd,PI:()=>oe,PURPLE:()=>fl,Particle:()=>Ni,ParticleEmitter:()=>ur,PathFinder:()=>Ur,PathFinderNode:()=>so,PostProcessPlugin:()=>xr,RED:()=>Xr,RandomGenerator:()=>or,Sound:()=>Vs,SoundInstance:()=>Bi,TextureInfo:()=>tn,TileCollisionLayer:()=>qs,TileInfo:()=>Jt,TileLayer:()=>Ws,TileLayerData:()=>Nn,Timer:()=>Gt,Tween:()=>to,UIButton:()=>Qs,UICheckbox:()=>Cr,UILayout:()=>Rr,UIObject:()=>xt,UISlider:()=>_r,UISystemPlugin:()=>Tr,UIText:()=>Xi,UITextInput:()=>Ar,UITile:()=>kr,UIVideo:()=>Er,Vector2:()=>ge,WHITE:()=>te,YELLOW:()=>ll,ZzFXMusic:()=>wr,abs:()=>he,atan2:()=>Hr,audioContext:()=>Te,audioDefaultSampleRate:()=>Ss,audioIsRunning:()=>Us,audioMasterGain:()=>Zt,box2d:()=>b,box2dDebug:()=>Fa,box2dInit:()=>jh,box2dSetDebug:()=>Bh,cameraAngle:()=>ue,cameraFit:()=>Bf,cameraPos:()=>Je,cameraScale:()=>ie,canvasClearColor:()=>gn,canvasColorTiles:()=>oo,canvasFixedSize:()=>is,canvasMaxAspect:()=>ss,canvasMaxSize:()=>ns,canvasMinAspect:()=>Ms,canvasPixelRatio:()=>bn,canvasPixelated:()=>Zr,ceil:()=>Fs,clamp:()=>Y,combineCanvases:()=>fa,cos:()=>be,debug:()=>Ye,debugCircle:()=>st,debugClear:()=>dd,debugLine:()=>Dt,debugOverlap:()=>sr,debugOverlay:()=>Wt,debugPoint:()=>qr,debugPointSize:()=>Hc,debugPoly:()=>ud,debugRect:()=>Ce,debugScreenshot:()=>Yc,debugShowErrors:()=>fd,debugText:()=>ts,debugVideoCaptureIsActive:()=>It,debugVideoCaptureStart:()=>Xc,debugVideoCaptureStop:()=>Kc,debugWatermark:()=>io,distanceAngle:()=>bd,distanceWrap:()=>$r,drawCanvas2D:()=>Hn,drawCircle:()=>Oi,drawCircleGradient:()=>If,drawContext:()=>Be,drawCount:()=>Bt,drawCrescent:()=>zh,drawEllipse:()=>yl,drawEllipseGradient:()=>gl,drawLine:()=>Fn,drawLineList:()=>ar,drawNineSlice:()=>jl,drawNineSliceScreen:()=>Jh,drawPoly:()=>ds,drawRect:()=>Li,drawRectGradient:()=>Lf,drawRegularPoly:()=>ml,drawText:()=>Ff,drawTextScreen:()=>xn,drawTextureWrapped:()=>Of,drawThreeSlice:()=>Jl,drawThreeSliceScreen:()=>Nh,drawTile:()=>Ue,enablePhysicsSolver:()=>lo,engineAddPlugin:()=>Wn,engineImageFont:()=>vl,engineInit:()=>rd,engineName:()=>Ti,engineObjects:()=>Ee,engineObjectsCallback:()=>cd,engineObjectsCollect:()=>qc,engineObjectsCollide:()=>Wr,engineObjectsDestroy:()=>ad,engineObjectsRaycast:()=>ld,engineObjectsUpdate:()=>Wc,engineVersion:()=>Ai,fetchJSON:()=>kd,floor:()=>Oe,fontDefault:()=>ei,formatTime:()=>Kr,frame:()=>Uc,frameRate:()=>sd,gamepadConnected:()=>lr,gamepadDirectionEmulateStick:()=>ra,gamepadDpad:()=>cr,gamepadIsDown:()=>Vt,gamepadPrimary:()=>ke,gamepadStick:()=>Ns,gamepadStickCount:()=>wl,gamepadVibrate:()=>Zf,gamepadVibrateStop:()=>eh,gamepadWasPressed:()=>ba,gamepadWasReleased:()=>Qf,gamepadsEnable:()=>uo,getCameraSize:()=>xl,getCrescentPoints:()=>Nl,getNoteFrequency:()=>_l,getPaused:()=>id,glAntialias:()=>Aa,glCanvas:()=>fe,glCircleSides:()=>ti,glClearCanvas:()=>Ll,glClearRect:()=>Gl,glCompileShader:()=>yr,glContext:()=>g,glCopyToContext:()=>Ra,glCreateProgram:()=>ys,glCreateTexture:()=>mo,glDeleteTexture:()=>Dl,glDraw:()=>Ys,glDrawColoredPoints:()=>La,glDrawOutlineTransform:()=>Ma,glDrawPoints:()=>Fl,glDrawPointsTransform:()=>Pa,glDrawUntextured:()=>Il,glEnable:()=>H,glFlush:()=>Ne,glSetAntialias:()=>_h,glSetRenderTarget:()=>Ps,glSetTexture:()=>_a,glSetTextureData:()=>Ea,glSetTextureWrap:()=>Ol,gravity:()=>it,headlessMode:()=>X,hsl:()=>Ht,hypot:()=>Qc,inputClear:()=>ai,inputClearKey:()=>ya,inputMouseMoveThreshold:()=>ma,inputPreventDefault:()=>os,inputWASDEmulateDirection:()=>Ls,isArray:()=>At,isColor:()=>Q,isFullscreen:()=>Sl,isIntersecting:()=>nl,isNumber:()=>O,isOnScreen:()=>jf,isOverlapping:()=>Ei,isPowerOfTwo:()=>Gs,isStringLike:()=>ee,isTouchDevice:()=>gt,isUsingGamepad:()=>as,isVector2:()=>D,keyDirection:()=>Xf,keyIsDown:()=>ze,keyWasPressed:()=>He,keyWasReleased:()=>ga,lastInputDevice:()=>mn,lerp:()=>ot,lerpAngle:()=>xd,lerpWrap:()=>tl,lightSystem:()=>se,lineTest:()=>il,log2:()=>Zc,mainCanvas:()=>$,mainCanvasSize:()=>z,mainContext:()=>Se,max:()=>le,medalDisplaySize:()=>Hi,medalDisplaySlideTime:()=>rs,medalDisplayTime:()=>qi,medals:()=>Xs,medalsForEach:()=>yo,medalsInit:()=>Mh,medalsPreventUnlock:()=>Oa,medalsReset:()=>Lh,min:()=>de,mod:()=>yt,mouseDelta:()=>ha,mouseDeltaScreen:()=>Mt,mouseInWindow:()=>Ii,mouseIsDown:()=>Ds,mousePos:()=>Ut,mousePosScreen:()=>nt,mouseWasPressed:()=>Js,mouseWasReleased:()=>Kf,mouseWheel:()=>pa,nearestPowerOfTwo:()=>Sd,newgrounds:()=>Ks,noise1D:()=>Pd,noise2D:()=>Md,objectDefaultAngleDamping:()=>sa,objectDefaultDamping:()=>na,objectDefaultFriction:()=>oa,objectDefaultMass:()=>ta,objectDefaultRestitution:()=>ia,objectMaxSpeed:()=>$t,oscillate:()=>sl,particleEmitRateScale:()=>Ri,paused:()=>Ft,percent:()=>Xe,percentLerp:()=>gd,playSamples:()=>Ta,pointerLockExit:()=>sh,pointerLockIsActive:()=>Tl,pointerLockRequest:()=>nh,postProcess:()=>qe,primitiveCount:()=>jt,rand:()=>we,randBool:()=>ol,randColor:()=>ir,randInCircle:()=>cl,randInt:()=>Yr,randSign:()=>rl,randVec2:()=>al,readSaveData:()=>Ed,rgb:()=>K,round:()=>Ci,saveCanvas:()=>hl,saveDataURL:()=>Bs,saveText:()=>Cd,screenToWorld:()=>oi,screenToWorldDelta:()=>bl,screenToWorldTransform:()=>ri,setAdditiveBlendMode:()=>js,setCameraAngle:()=>Od,setCameraPos:()=>Ld,setCameraScale:()=>Dd,setCanvasClearColor:()=>Gd,setCanvasColorTiles:()=>Fd,setCanvasFixedSize:()=>Nd,setCanvasMaxAspect:()=>Jd,setCanvasMaxSize:()=>Bd,setCanvasMinAspect:()=>jd,setCanvasPixelRatio:()=>Ud,setCanvasPixelated:()=>pl,setCursor:()=>Uf,setDebugKey:()=>Mf,setDebugWatermark:()=>Pf,setEnablePhysicsSolver:()=>Qd,setFontDefault:()=>Vd,setGLCircleSides:()=>$d,setGLEnable:()=>Hd,setGamepadDirectionEmulateStick:()=>lf,setGamepadsEnable:()=>cf,setGravity:()=>rf,setHeadlessMode:()=>qd,setInputMouseMoveThreshold:()=>qf,setInputPreventDefault:()=>Wf,setInputWASDEmulateDirection:()=>uf,setMedalDisplaySize:()=>Ih,setMedalDisplaySlideTime:()=>Dh,setMedalDisplayTime:()=>Oh,setMedalsPreventUnlock:()=>Fh,setObjectDefaultAngleDamping:()=>tf,setObjectDefaultDamping:()=>ef,setObjectDefaultFriction:()=>sf,setObjectDefaultMass:()=>Zd,setObjectDefaultRestitution:()=>nf,setObjectMaxSpeed:()=>of,setParticleEmitRateScale:()=>af,setPaused:()=>od,setShowSplashScreen:()=>Wd,setSoundDefaultRange:()=>Ef,setSoundDefaultTaper:()=>Rf,setSoundEnable:()=>Cf,setSoundVolume:()=>_f,setTileDefaultBleed:()=>Kd,setTileDefaultPadding:()=>Xd,setTileDefaultSize:()=>Yd,setTilesPixelated:()=>zd,setTimeScale:()=>Id,setTouchGamepadAlpha:()=>wf,setTouchGamepadAnalog:()=>xf,setTouchGamepadButtonCount:()=>mf,setTouchGamepadCenterButtonSize:()=>pf,setTouchGamepadDisplayTime:()=>Tf,setTouchGamepadEnable:()=>ff,setTouchGamepadFloating:()=>Sf,setTouchGamepadLeftButtonCount:()=>gf,setTouchGamepadLeftStick:()=>yf,setTouchGamepadPassthrough:()=>hf,setTouchGamepadRightStick:()=>bf,setTouchGamepadSize:()=>vf,setTouchGamepadVibration:()=>Af,setTouchInputEnable:()=>df,setVibrateEnable:()=>kf,shareURL:()=>_d,showSplashScreen:()=>ea,sign:()=>mt,sin:()=>pe,smoothStep:()=>_i,soundDefaultRange:()=>la,soundDefaultTaper:()=>ua,soundEnable:()=>at,soundVolume:()=>Jn,speak:()=>bh,speakStop:()=>xh,tan:()=>el,textureInfos:()=>An,tile:()=>ii,tileCollisionGetData:()=>ji,tileCollisionLayers:()=>Sn,tileCollisionRaycast:()=>El,tileCollisionTest:()=>hn,tileDefaultBleed:()=>co,tileDefaultPadding:()=>ao,tileDefaultSize:()=>ro,tileLayersLoad:()=>vh,tilesPixelated:()=>zn,time:()=>dt,timeDelta:()=>Vr,timeReal:()=>vn,timeScale:()=>Qr,toggleFullscreen:()=>zf,touchGamepadAlpha:()=>ca,touchGamepadAnalog:()=>ni,touchGamepadButtonCount:()=>gs,touchGamepadCenterButtonSize:()=>kt,touchGamepadDisplayTime:()=>Os,touchGamepadEnable:()=>Tn,touchGamepadFloating:()=>kn,touchGamepadLeftButtonCount:()=>bs,touchGamepadLeftStick:()=>qn,touchGamepadPassthrough:()=>aa,touchGamepadRightStick:()=>xs,touchGamepadSize:()=>rt,touchGamepadVibration:()=>Pi,touchInputEnable:()=>In,tweenProperty:()=>Uh,tweenStopAll:()=>Vh,tweenUpdate:()=>Vl,uiDebug:()=>Ia,uiSetDebug:()=>Gh,uiSystem:()=>E,usingGamepadInput:()=>Yf,usingKeyboardInput:()=>$f,usingMouseInput:()=>Hf,vec2:()=>v,vibrate:()=>xa,vibrateEnable:()=>si,vibrateStop:()=>th,workCanvas:()=>Kt,workContext:()=>pn,workReadCanvas:()=>Ot,workReadContext:()=>Yt,worldToScreen:()=>$n,worldToScreenDelta:()=>Gf,writeSaveData:()=>Rd,zzfx:()=>Sh,zzfxG:()=>ho,zzfxM:()=>Bl});function id(){return Ft}function od(t=!0){Ft=t}function Wn(t,e,n,s){m(!Gn.find(r=>r.update===t&&r.render===e&&r.glContextLost===n&&r.glContextRestored===s));let i=new tr(t,e,n,s);Gn.push(i)}async function rd(t,e,n,s,i,r=[],a){if(Vc&&console.log(`${Ti} Engine v${Ai}`),m(!Se,"engine already initialized"),Se)return;m(At(r),"pass in images as array"),document.body||document.documentElement.appendChild(document.createElement("body")),a||(a=document.body),t||(t=()=>{}),e||(e=()=>{}),n||(n=()=>{}),s||(s=()=>{}),i||(i=()=>{});function o(){z=v($.width,$.height),Se.imageSmoothingEnabled=!zn,mr()}function c(p=0){let y=p-Qo;Qo||(y=0),Qo=p,(Ye||io)&&(ki=ot(ki,1e3/(y||1),.05));let x=Ye&&ze("Equal"),w=Ye&&ze("Minus"),A=x?10:w?.1:1;vn+=y*A/1e3;let S=Qr*A;y*=S,Pt+=Ft?0:y,S<=1&&(Pt=de(Pt,50));let _=!1;if(Ft){_=!0,l(),Gc(),Gn.forEach(C=>{var L;return(L=C.update)==null?void 0:L.call(C)});for(let C of Ee)C.parent||C.updateTransforms();Oc(),n(),Bc(),It()&&k()}else{let C=0;for(Pt<0&&Pt>-9&&(C=Pt,Pt=0);Pt>=0;Pt-=1e3/60)dt=Uc++/60,_=!0,l(),Gc(),e(),Gn.forEach(L=>{var N;return(N=L.update)==null?void 0:N.call(L)}),Wc(),Oc(),n(),Bc(),It()&&k();Pt+=C}It()||k(),requestAnimationFrame(c);function k(){if(!X){_||l(),o(),s(),Ee.sort((C,L)=>C.renderOrder-L.renderOrder);for(let C of Ee)C.destroyed||C.render();i(),Gn.forEach(C=>{var L;return(L=C.render)==null?void 0:L.call(C)}),oh(),pd(),Ne(),md(),Bt=0,jt=0}}}function l(){if(!X){if(is.x){z=is.copy();let p=innerWidth/innerHeight,y=is.x/is.y,x=pss){let _=z.y*ss|0;z.x=de(_,ns.x)}else if(w0&&!H&&(Se.fillStyle=gn.toString(),Se.fillRect(0,0,z.x,z.y),Se.fillStyle=me.toString()),Se.lineJoin="round",Se.lineCap="round"}}if(X)return d();Ah(a);let u="margin:0;overflow:hidden;background:#000;user-select:none;-webkit-user-select:none;touch-action:none;-webkit-touch-callout:none";a.style.cssText=u,$=a.appendChild(document.createElement("canvas")),Be=Se=$.getContext("2d"),ih(),gh(),hd();let h="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)";$.style.cssText=h,fe&&(fe.style.cssText=h),pl(Zr),l(),mr(),Kt=new OffscreenCanvas(64,64),pn=Kt.getContext("2d"),Ot=new OffscreenCanvas(64,64),Yt=Ot.getContext("2d",{willReadFrequently:!0});let f=r.map((p,y)=>Ic(y,p));return r.length||f.push(Ic(0)),f.push(Vf()),ea&&f.push(new Promise(p=>{let y=0;x();function x(){ai(),Ph(y+=.01),y>1?p():setTimeout(x,16)}})),await Promise.all(f),d();async function d(){await t(),c()}}function Wc(){Wr=Ee.filter(e=>e.collideSolidObjects);function t(e){if(!e.destroyed){e.update();for(let n of e.children)t(n)}}for(let e of Ee)if(!(e.parent||e.destroyed)){e.update(),e.updatePhysics();for(let n of e.children)t(n);e.updateTransforms()}Ee=Ee.filter(e=>!e.destroyed)}function ad(t=!0){for(let e of Ee)e.parent||e.destroy(t);Ee=Ee.filter(e=>!e.destroyed)}function qc(t,e,n=Ee){let s=[];if(t)if(e instanceof ge)for(let i of n)i.isOverlapping(t,e)&&s.push(i);else{let i=e*e;for(let r of n)t.distanceSquared(r.pos)n(i))}function ld(t,e,n=Ee){let s=[];for(let i of n)i.collideRaycast&&nl(t,e,i.pos,i.size)&&(Tt&&Ce(i.pos,i.size,"#f00"),s.push(i));return Tt&&Dt(t,e,s.length?"#f00":"#00f",.02),s}function m(t,...e){if(!t)throw console.assert(t,...e),new Error("Assert failed!")}function _e(...t){console.log(...t)}function Ce(t,e=v(),n=te,s=0,i=0,r=!1,a=!1){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(ee(n)||Q(n),"color is invalid"),m(O(s),"time must be a number"),m(O(i),"angle must be a number"),Q(n)&&(n=n.toString());let o=new Gt(s);yn.push({pos:t.copy(),size:e.copy(),color:n,timer:o,angle:i,fill:r,screenSpace:a})}function ud(t,e,n=te,s=0,i=0,r=!1,a=!1){m(D(t),"pos must be a vec2"),m(At(e),"points must be an array"),m(ee(n)||Q(n),"color is invalid"),m(O(s),"time must be a number"),m(O(i),"angle must be a number"),Q(n)&&(n=n.toString()),t=t.copy(),e=e.map(c=>c.copy());let o=new Gt(s);yn.push({pos:t,points:e,color:n,timer:o,angle:i,fill:r,screenSpace:a})}function st(t,e=0,n=te,s=0,i=!1,r=!1){m(D(t),"pos must be a vec2"),m(O(e),"size must be a number"),m(ee(n)||Q(n),"color is invalid"),m(O(s),"time must be a number"),Q(n)&&(n=n.toString()),t=t.copy();let a=new Gt(s);yn.push({pos:t,size:e,color:n,timer:a,angle:0,fill:i,screenSpace:r})}function qr(t,e,n,s,i=!1){Ce(t,void 0,e,n,s,!1,i)}function Dt(t,e,n,s=.1,i=0,r=!1){m(D(t),"posA must be a vec2"),m(D(e),"posB must be a vec2"),m(O(s),"width must be a number");let a=v((e.x-t.x)/2,(e.y-t.y)/2),o=v(s,a.length()*2);Ce(t.add(a),o,n,i,a.angle(),!0,r)}function sr(t,e,n,s,i,r,a=!1){m(D(t),"posA must be a vec2"),m(D(n),"posB must be a vec2"),m(D(e),"sizeA must be a vec2"),m(D(s),"sizeB must be a vec2");let o=v(de(t.x-e.x/2,n.x-s.x/2),de(t.y-e.y/2,n.y-s.y/2)),c=v(le(t.x+e.x/2,n.x+s.x/2),le(t.y+e.y/2,n.y+s.y/2));Ce(o.lerp(c,.5),c.subtract(o),i,r,0,!1,a)}function ts(t,e,n=1,s=te,i=0,r=0,a="monospace",o=!1){m(ee(t),"text must be a string"),m(D(e),"pos must be a vec2"),m(O(n),"size must be a number"),m(ee(s)||Q(s),"color is invalid"),m(O(i),"time must be a number"),m(O(r),"angle must be a number"),m(ee(a),"font must be a string"),Q(s)&&(s=s.toString()),e=e.copy();let c=new Gt(i);yn.push({text:t,pos:e,size:n,color:s,timer:c,angle:r,font:a,screenSpace:o})}function dd(){yn=[]}function Yc(){nr=1}function fd(){let t=n=>{document.body.style="background-color:#111;margin:8px",document.body.innerHTML="
"+n},e=console.assert;console.assert=(n,...s)=>{if(e(n,...s),!n){let i=s.join(" "),r=new Error().stack;throw`Assertion failed!
+`+i+`
+`+r}},onunhandledrejection=n=>t(n.reason.stack||n.reason),onerror=(n,s,i,r)=>t(`${n}
+${s}
+Ln ${i}, Col ${r}`)}function hd(){Vc&&console.warn("LittleJS DEBUG build loaded. Use the release build for production.")}function Oc(){Ye&&(He($c)&&(Wt=!Wt),Wt&&(He("Digit1")&&(wt=!wt,Bn=!1),He("Digit2")&&(Bn=!Bn,wt=!1),He("Digit3")&&(jn=!jn),He("Digit4")&&(Tt=!Tt),He("Digit5")&&Yc(),He("Digit7")&&(us=!us)),It()?(!Wt||He("Digit6"))&&Kc():Wt&&He("Digit6")&&Xc())}function pd(){if(It())return;Ne();let t=Bt,e=jt;nr&&(fa(),hl($),nr=0);let n=Se;if(jn&&uo){let r=0;for(let a=0;a<8;a++)lr(a)&&r++;for(let a=0;a<8;a++){if(!lr(a))continue;let o=1,c=.2,l=Je.add(v(-o*2,((r-1)/2-a)*o*3));ts(a,l.add(v(-o,o)),1),a===ke&&ts("Main",l.add(v(-o*2,0)),1,"#0f0");let u=Lt[a].length;for(let f=0;f{n.save();let r=i.pos,a=1,o=i.angle;if(i.screenSpace||(r=$n(i.pos),a=ie,o-=ue),n.translate(r.x|0,r.y|0),n.rotate(o),n.scale(1,i.text?1:-1),n.fillStyle=i.color,n.strokeStyle=i.color,i.text!==void 0)n.font=i.size*a+"px "+i.font,n.textAlign="center",n.textBaseline="middle",n.fillText(i.text,0,0);else if(i.points!==void 0){n.beginPath();for(let c of i.points){let l=c.scale(a).floor();n.lineTo(l.x,l.y)}n.closePath(),i.fill&&n.fill(),n.stroke()}else if(i.size===0||i.size.x===0&&i.size.y===0){let c=Hc*a;n.fillRect(-c/2,-1,c,3),n.fillRect(-1,-c/2,3,c)}else if(i.size.x!==void 0){let c=i.size.scale(a).floor(),l=c.x,u=c.y;i.fill&&n.fillRect(-l/2|0,-u/2|0,l,u),n.strokeRect(-l/2|0,-u/2|0,l,u)}else n.beginPath(),n.arc(0,0,i.size*a/2,0,9),i.fill&&n.fill(),n.stroke();n.restore()}),yn=yn.filter(i=>i.timer<0),s){let i=El(s.pos,Ut);i&&Li(i.floor().add(v(.5)),v(1),K(0,1,1,.3),0,!1),Fn(Ut,s.pos,.1,i?K(1,0,0,.5):K(0,1,0,.5),void 0,void 0,!1);let r="mouse pos = "+Ut;Sn.length&&(r+=`
+mouse collision = `+ji(Ut)),r+=`
+
+--- object info ---
+`,r+=s.toString(),xn(r,nt,24,K(),.05,void 0,"center","monospace")}{n.save(),n.fillStyle="#fff",n.textAlign="left",n.textBaseline="top",n.font="20px monospace",n.shadowColor="#000",n.shadowBlur=9;let a=9,o=0,c=24;if(Wt){n.fillText(`${Ti} v${Ai}`,a,o+=c/2),n.fillText("Time: "+Kr(dt),a,o+=c),n.fillText("FPS: "+ki.toFixed(1)+(H?" WebGL":" Canvas2D"),a,o+=c),n.fillText("Objects: "+Ee.length,a,o+=c),n.fillText("Draw Calls: "+Bt,a,o+=c),n.fillText("Primitives: "+jt,a,o+=c),n.fillText("---------",a,o+=c),n.fillStyle="#f00",n.fillText("ESC: Debug Overlay",a,o+=c),n.fillStyle=wt?"#f00":"#fff",n.fillText("1: Debug Physics",a,o+=c),n.fillStyle=Bn?"#f00":"#fff",n.fillText("2: Debug Particles",a,o+=c),n.fillStyle=jn?"#f00":"#fff",n.fillText("3: Debug Gamepads",a,o+=c),n.fillStyle=Tt?"#f00":"#fff",n.fillText("4: Debug Raycasts",a,o+=c),n.fillStyle="#fff",n.fillText("5: Save Screenshot",a,o+=c),n.fillText("6: Toggle Video Capture",a,o+=c),n.fillStyle=us?"#f00":"#fff",n.fillText("7: Debug Sound",a,o+=c);let l="",u="";for(let h in re[0])ze(h,0)&&(parseInt(h)<3?u+=h+" ":l+=h+" ");u&&n.fillText("Mouse: "+u,a,o+=c),l&&n.fillText("Keys: "+l,a,o+=c);for(let h=1;hs.push(o.data),i.onstop=()=>{let o=new Blob(s,{type:"video/webm"}),c=URL.createObjectURL(o);Bs(c,"capture.webm",1e3)};let r,a;if(at){a=new ConstantSourceNode(Te,{offset:0}),a.connect(Zt),a.start(),r=Te.createMediaStreamDestination(),Zt.connect(r);for(let o of r.stream.getAudioTracks())t.addTrack(o)}try{i.start()}catch{_e("Video capture not supported in this browser!"),a==null||a.stop();return}_e("Video capture started."),qt={mediaRecorder:i,captureTimer:n,videoTrack:e,silentAudioSource:a,audioStreamDestination:r}}function Kc(){var t,e,n;m(It(),"Not capturing video!"),_e(`Video capture ended. ${qt.captureTimer.get().toFixed(2)} seconds recorded.`),vt.style.display="none",(t=qt.silentAudioSource)==null||t.stop(),(e=qt.mediaRecorder)==null||e.stop(),(n=qt.videoTrack)==null||n.stop(),qt=void 0}function yd(){m(It(),"Not capturing video!"),fa(),qt.videoTrack.requestFrame(),vt.textContent="\u25CF REC "+Kr(qt.captureTimer)}function ht(t){if(Ye){let e=Object.keys(t),n={};e.forEach(s=>n[s]=t[s]),e.forEach(s=>{Object.defineProperty(t,s,{get:()=>n[s],set:i=>{m(!1,`Cannot modify engine constant. Attempted to set constant (${t}) property '${s}' to '${i}'.`)},enumerable:!0})})}return Object.freeze(t)}function yt(t,e=1){return(t%e+e)%e}function Y(t,e=0,n=1){return tn?n:t}function Xe(t,e,n){return(n-=e)?Y((t-e)/n):0}function ot(t,e,n){return t+Y(n)*(e-t)}function gd(t,e,n,s,i){return ot(s,i,Xe(t,e,n))}function $r(t,e,n=1){m(n>0,"distanceWrap wrapSize must be > 0");let s=(t-e)%n;return s*2%n-s}function tl(t,e,n,s=1){return t+Y(n)*$r(e,t,s)}function bd(t,e){return $r(t,e,2*oe)}function xd(t,e,n){return tl(t,e,n,2*oe)}function _i(t){return t*t*(3-2*t)}function Gs(t){return!(t&t-1)}function Sd(t){return 2**Fs(Zc(t))}function Ei(t,e,n,s=v()){let i=(t.x-n.x)*2,r=(t.y-n.y)*2,a=e.x+s.x,o=e.y+s.y;return he(i)f)return!1;h=le(p,h)}else{if(p0?o.x+1:o.x,y=h>0?o.y+1:o.y,x=c?(p-t.x)/c:1/0,w=l?(y-t.y)/l:1/0,A=0,S=x,_=w,k=fo.x&&(C.x=o.x+1-L),N.yo.y&&(C.y=o.y+1-L),s&&(k?s.set(-u,0):s.set(0,-h)),C}(k=S<_)?(o.x+=u,A=S,S+=f):(o.y+=h,A=_,_+=d)}}function we(t=1,e=0){return e+Math.random()*(t-e)}function Yr(t,e=0){return Oe(we(t,e))}function ol(t=.5){return we()URL.revokeObjectURL(t),n)}function _d(t,e,n){var s;m(ee(t),"shareURL requires title string"),m(ee(e),"shareURL requires url string"),(s=navigator.share)==null||s.call(navigator,{title:t,url:e}).then(()=>n==null?void 0:n())}function Ed(t,e){m(ee(t),"loadData requires saveName string");let n={};try{let s=localStorage[t];if(s)try{n=JSON.parse(s)}catch{_e("readSaveData: corrupt JSON for",t,"\u2014 using defaults")}}catch{_e("readSaveData: localStorage unavailable \u2014 using defaults")}return{...e,...n}}function Rd(t,e){m(ee(t),"saveData requires saveName string");try{localStorage[t]=JSON.stringify(e)}catch{_e("writeSaveData: failed to write",t)}}function rr(t){let e=(t|0)^2654435769;return e=Math.imul(e^e>>>16,2246822507),e=Math.imul(e^e>>>13,3266489909),e^=e>>>16,(e>>>0)/2**32}function Pd(t){let e=Oe(t);return ot(rr(e),rr(e+1),_i(t-e))}function Md(t,e){let n=Oe(t),s=Oe(e),i=_i(t-n),r=_i(e-s),a=(o,c)=>rr(o+c*374761393);return ot(ot(a(n,s),a(n+1,s),i),ot(a(n,s+1),a(n+1,s+1),i),r)}function Ld(t){Je=t.copy()}function Od(t){ue=t}function Dd(t){ie=t}function Id(t){Qr=t}function Fd(t){oo=t}function Gd(t){gn=t.copy()}function Bd(t){ns=t.copy()}function jd(t){Ms=t}function Jd(t){ss=t}function Nd(t){is=t.copy()}function pl(t){Zr=t,$&&($.style.imageRendering=t?"pixelated":""),fe&&(fe.style.imageRendering=t?"pixelated":"")}function zd(t){zn=t}function Ud(t){bn=t}function Vd(t){ei=t}function Wd(t){ea=t}function qd(t){X=t}function Hd(t){if(t&&!pr){console.warn("Can not enable WebGL if it was disabled on start.");return}H=t,fe&&(fe.style.display=t?"":"none")}function $d(t){ti=t}function Yd(t){ro=t.copy()}function Xd(t){ao=t}function Kd(t){co=t}function Qd(t){lo=t}function Zd(t){ta=t}function ef(t){na=t}function tf(t){sa=t}function nf(t){ia=t}function sf(t){oa=t}function of(t){$t=t}function rf(t){it=t.copy()}function af(t){Ri=t}function cf(t){uo=t}function lf(t){ra=t}function uf(t){Ls=t}function df(t){In=t}function ff(t){Tn=t}function hf(t){aa=t}function pf(t){kt=t}function mf(t){gs=t,t>0&&(xs=!1)}function yf(t){qn=t,t&&(bs=0)}function gf(t){bs=t,t>0&&(qn=!1)}function bf(t){xs=t,t&&(gs=0)}function xf(t){ni=t}function Sf(t){kn=t}function vf(t){rt=t}function wf(t){ca=t}function Tf(t){Os=t}function Af(t){Pi=t}function kf(t){si=t}function Cf(t){at=t}function _f(t){Jn=t,at&&!X&&Zt&&(Zt.gain.value=t)}function Ef(t){la=t}function Rf(t){ua=t}function Pf(t){io=t}function Mf(t){$c=t}function Mi(t){return t.r>=1&&t.g>=1&&t.b>=1}function da(t){return t.r<=0&&t.g<=0&&t.b<=0&&t.a<=0}function ii(t=0,e=ro,n=0,s=ao,i=co){if(m(D(t)||typeof t=="number","index must be a vec2 or number"),m(D(e)||typeof e=="number","size must be a vec2 or number"),m(O(n)||n instanceof tn,"texture must be a number or TextureInfo"),m(O(s),"padding must be a number"),X)return new Jt;typeof e=="number"&&(m(e>0),e=new ge(e,e));let r=typeof n=="number"?An[n]:n;m(r instanceof tn,"tile texture is not loaded"),m(r.size.x>0,"tile texture is not loaded");let a=e.x+s*2,o=e.y+s*2,c,l;if(typeof t=="number"){let h=r.size.x/a|0;c=t%h,l=t/h|0}else c=t.x,l=t.y;let u=new ge(c*a+s,l*o+s);return new Jt(u,e,r,s,i)}function Ue(t,e=v(1),n,s=te,i=0,r,a,o=H,c=!1,l){var f;m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(Q(s),"color is invalid"),m(O(i),"angle must be a number"),m(!a||Q(a),"additiveColor must be a color"),m(!l||!o,"context only supported in canvas 2D mode");let u=n==null?void 0:n.textureInfo,h=(f=n==null?void 0:n.bleed)!=null?f:0;if(o&&H)if(m(!!g,"WebGL is not enabled!"),c&&([t,e,i]=ri(t,e,i)),u){let d=u.sizeInverse,p=n.pos.x*d.x,y=n.pos.y*d.y,x=n.size.x*d.x,w=n.size.y*d.y;if(_a(u.glTexture),h){let A=d.x*h,S=d.y*h;Ys(t.x,t.y,r?-e.x:e.x,e.y,i,p+A,y+S,p-A+x,y-S+w,s.rgbaInt(),a&&a.rgbaInt())}else Ys(t.x,t.y,r?-e.x:e.x,e.y,i,p,y,p+x,y+w,s.rgbaInt(),a&&a.rgbaInt())}else{let d=a?s.add(a):s;Il(t.x,t.y,e.x,e.y,i,d.rgbaInt())}else++Bt,++jt,Hn(t,e,i,r,d=>{if(u){d.scale(1,-1);let p=n.pos.x,y=n.pos.y,x=n.size.x,w=n.size.y;Nf(d,u.image,p,y,x,w,-.5,-.5,1,1,s,a,h)}else{let p=a?s.add(a):s;d.fillStyle=p.toString(),d.fillRect(-.5,-.5,1,1)}},c,l)}function Li(t,e,n,s,i,r,a){Ue(t,e,void 0,n,s,!1,void 0,i,r,a)}function Lf(t,e,n=te,s=wn,i=0,r=H,a=!1,o){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(Q(n)&&Q(s),"color is invalid"),m(O(i),"angle must be a number"),m(!o||!r,"context only supported in canvas 2D mode"),r&&H){m(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/ie),i+=ue);let c=[],l=[],u=e.x/2,h=e.y/2,f=n.rgbaInt(),d=s.rgbaInt(),p=be(-i),y=pe(-i);for(let x=4;x--;){let w=x&1?u:-u,A=x&2?h:-h,S=w*p-A*y,_=w*y+A*p,k=x&2?f:d;c.push(v(t.x+S,t.y+_)),l.push(k)}La(c,l)}else++Bt,++jt,Hn(t,e,i,!1,c=>{let l=c.createLinearGradient(0,.5,0,-.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.fillRect(-.5,-.5,1,1)},a,o)}function Of(t,e,n,s=0,i=te,r=0,a,o=H,c=!1,l){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(D(n),"wrapCount must be a vec2"),m(Q(i),"color is invalid"),m(O(r),"angle must be a number"),m(!a||Q(a),"additiveColor must be a color"),m(!l||!o,"context only supported in canvas 2D mode"),m(!(s instanceof Jt),"pass a TextureInfo or texture index, not a TileInfo \u2014 use tileInfo.textureInfo"),X)return;let u=typeof s=="number"?An[s]:s;if(m(u instanceof tn,"texture not loaded"),m(u.size.x>0,"texture not loaded"),m(u.wrap,"drawTextureWrapped requires a wrap-enabled texture; call textureInfo.setWrap(true) first"),o&&H){m(!!g,"WebGL is not enabled!"),c&&([t,e,r]=ri(t,e,r)),_a(u.glTexture),Ys(t.x,t.y,e.x,e.y,r,0,0,n.x,n.y,i.rgbaInt(),a&&a.rgbaInt());return}++Bt,++jt,c||(t=$n(t),e=e.scale(ie),r-=ue);let h=!oo||(a?Mi(i.add(a))&&a.a<=0:Mi(i)),f=!h&&a&&!da(a),d=h?u.image:Jf(u.image,i,a);l=l||Be,l.save(),l.translate(t.x+.5,t.y+.5),l.rotate(r),l.globalAlpha=f?1:i.a;let p=l.createPattern(d,"repeat"),y=new DOMMatrix().translate(-e.x/2,-e.y/2).scale(e.x/(n.x*d.width),e.y/(n.y*d.height));p.setTransform(y),l.fillStyle=p,l.fillRect(-e.x/2,-e.y/2,e.x,e.y),l.globalAlpha=1,l.restore()}function ar(t,e=.1,n=te,s=!1,i=v(),r=0,a=H,o=!1,c){if(m(At(t),"points must be an array"),m(O(e),"width must be a number"),m(Q(n),"color is invalid"),m(D(i),"pos must be a vec2"),m(O(r),"angle must be a number"),m(!c||!a,"context only supported in canvas 2D mode"),a&&H){m(!!g,"WebGL is not enabled!");let l=v(1);o&&([i,l,r]=ri(i,l,r)),Ma(t,n.rgbaInt(),e,i.x,i.y,l.x,l.y,r,s)}else++Bt,++jt,Hn(i,v(1),r,!1,l=>{l.strokeStyle=n.toString(),l.lineWidth=e,l.beginPath();for(let u=0;u0&&Ma(t,s.rgbaInt(),n,i.x,i.y,l.x,l.y,r)}else Hn(i,v(1),r,!1,l=>{l.fillStyle=e.toString(),l.beginPath();for(let u of t)l.lineTo(u.x,u.y);l.closePath(),l.fill(),n&&(l.strokeStyle=s.toString(),l.lineWidth=n,l.stroke())},o,c)}function yl(t,e=v(1),n=te,s=0,i=0,r=me,a=H,o=!1,c){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(Q(n)&&Q(r),"color is invalid"),m(O(s),"angle must be a number"),m(O(i),"lineWidth must be a number"),m(i>=0,"lineWidth must be a positive value or 0"),m(!c||!a,"context only supported in canvas 2D mode"),i=Y(i,0,de(e.x,e.y)),a&&H?ml(t,e,ti,n,i,r,s,a,o,c):Hn(t,v(1),s,!1,l=>{l.fillStyle=n.toString(),l.beginPath(),l.ellipse(0,0,e.x/2,e.y/2,0,0,9),l.fill(),i&&(l.strokeStyle=r.toString(),l.lineWidth=i,l.stroke())},o,c)}function Oi(t,e=1,n=te,s=0,i=me,r=H,a=!1,o){m(O(e),"size must be a number"),yl(t,v(e),n,0,s,i,r,a,o)}function gl(t,e=v(1),n=te,s=wn,i=0,r=H,a=!1,o){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(Q(n)&&Q(s),"color is invalid"),m(O(i),"angle must be a number"),m(!o||!r,"context only supported in canvas 2D mode"),!X)if(r&&H){m(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/ie),i+=ue);let c=ti,l=e.x/2,u=e.y/2,h=n.rgbaInt(),f=s.rgbaInt(),d=Df++,p=be(-i),y=pe(-i),x=_=>{let k=pe(_)*l,C=be(_)*u;return v(t.x+k*p-C*y,t.y+k*y+C*p)},w=d%c/c*oe*2,A=[x(w)],S=[f];for(let _=c;_--;){let k=(_+d)%c/c*oe*2;A.push(t),S.push(h),A.push(x(k)),S.push(f)}La(A,S)}else++Bt,++jt,Hn(t,e,i,!1,c=>{let l=c.createRadialGradient(0,0,0,0,0,.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.beginPath(),c.ellipse(0,0,.5,.5,0,0,9),c.fill()},a,o)}function If(t,e=1,n=te,s=wn,i=H,r=!1,a){m(O(e),"size must be a number"),gl(t,v(e),n,s,0,i,r,a)}function Hn(t,e,n=0,s=!1,i,r=!1,a=Be){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(O(n),"angle must be a number"),m(typeof i=="function","drawFunction must be a function"),r||(t=$n(t),e=e.scale(ie),n-=ue),a.save(),a.translate(t.x+.5,t.y+.5),a.rotate(n),a.scale(s?-e.x:e.x,-e.y),i(a),a.restore()}function Ff(t,e,n=1,s=te,i=0,r=me,a="center",o=ei,c="",l,u=0,h=Be){e=$n(e),n*=ie,i*=ie,u-=ue,u*=-1,xn(t,e,n,s,i,r,a,o,c,l,u,h)}function xn(t,e,n,s=te,i=0,r=me,a="center",o=ei,c="",l,u=0,h=Be){m(ee(t),"text must be a string"),m(D(e),"pos must be a vec2"),m(O(n),"size must be a number"),m(Q(s),"color must be a color"),m(O(i),"lineWidth must be a number"),m(Q(r),"lineColor must be a color"),m(["left","center","right"].includes(a),"align must be left, center, or right"),m(ee(o),"font must be a string"),m(ee(c),"fontStyle must be a string"),m(O(u),"angle must be a number");let f=(t+"").split(`
+`),d=e.y-(f.length-1)*n/2;h.save(),h.fillStyle=s.toString(),h.strokeStyle=r.toString(),h.lineWidth=i,h.textAlign=a,h.font=c+" "+n+"px "+o,h.textBaseline="middle",h.translate(e.x,d),h.rotate(-u);let p=0;f.forEach(y=>{i&&h.strokeText(y,0,p,l),h.fillText(y,0,p,l),p+=n}),h.restore()}async function Ic(t,e){m(O(t),"textureIndex must be a number"),m(!An[t],"textureIndex is already loaded!"),m(!e||ee(e),"image src must be a string");let n=new Image;e&&await new Promise(s=>{n.onerror=n.onload=s,n.crossOrigin="anonymous",n.src=e}),An[t]=new tn(n)}function oi(t){m(D(t),"screenPos must be a vec2");let e=(t.x-z.x/2+.5)/ie,n=(t.y-z.y/2+.5)/-ie;if(ue){let s=be(-ue),i=pe(-ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e+Je.x,n+Je.y)}function $n(t){m(D(t),"worldPos must be a vec2");let e=t.x-Je.x,n=t.y-Je.y;if(ue){let s=be(ue),i=pe(ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e*ie+z.x/2-.5,n*-ie+z.y/2-.5)}function bl(t){m(D(t),"screenDelta must be a vec2");let e=t.x/ie,n=t.y/-ie;if(ue){let s=be(-ue),i=pe(-ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e,n)}function Gf(t){m(D(t),"worldDelta must be a vec2");let e=t.x,n=t.y;if(ue){let s=be(ue),i=pe(ue),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new ge(e*ie,n*-ie)}function ri(t,e,n=0){return m(D(t),"screenPos must be a vec2"),m(D(e),"screenSize must be a vec2"),m(O(n),"screenAngle must be a number"),[oi(t),e.scale(1/ie),n+ue]}function xl(){return z.scale(1/ie)}function Bf(t,e,n,s){m(D(t),"center must be a vec2"),m(D(e),"size must be a vec2");let i=f(n),r=f(s),a=e.x+i.left+i.right,o=e.y+i.top+i.bottom,c=z.x-r.left-r.right,l=z.y-r.top-r.bottom;if(!(a>0&&o>0&&c>0&&l>0))return ie;ie=de(c/a,l/o);let u=v(i.right-i.left,i.top-i.bottom).scale(.5),h=v(r.right-r.left,r.top-r.bottom).scale(.5/ie);return Je=t.add(u).add(h),ie;function f(d){return(d===void 0||O(d))&&(d=v(d)),D(d)?{top:d.y,right:d.x,bottom:d.y,left:d.x}:{top:d.top||0,right:d.right||0,bottom:d.bottom||0,left:d.left||0}}}function jf(t,e=0){if(m(D(t),"pos must be a vec2"),m(D(e)||O(e),"size must be a vec2 or number"),!ie)return!1;let n=t.x-Je.x,s=t.y-Je.y;if(ue){let a=be(ue),o=pe(ue),c=n*a-s*o,l=n*o+s*a;n=c,s=l}n*=ie*2,s*=-ie*2,e instanceof ge&&(e=e.length()),e*=ie;let i=z.x,r=z.y;return n+e>-i&&n-e-r&&s-e{t.onerror=t.onload=o,t.crossOrigin="anonymous",t.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAAeAQMAAABnrVXaAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAAjpJREFUOMu9kzFu2zAUhn+CAROgqrk+B2l0BWYxMjlXeYaAtFtbdA1sGgHqRQfI0CNkSG5AwYB0BQ8d5Bsomwah6CPVeGg6tEPzAxLwyI+P78cP4u9lNO9OoMKnLMOobG5020/yaj/MrRcCGh1gBbyiLTPJEYaIiom5KM9Jq7KgynMGtb6L4GL4MF2H4LQKCXTvDVw2I4MsgZT7QLExdiutH+D08VOP3INXRrWX1/mmpbkNgAPYRVANb4xpcegYvhiNbIXauQICEjBuYLfMakaakWQeXxiZ0VDtuJCKs3ztMV59QtsHJNcRxDzfdL21ty3PrfIcXTN+E+GFAv6T5nbT9jd50/WFxb5ksdAv49qS6ouymG66ji08UMT6moykYLAo+V0j23GN4m829ZySAD5K7QsBfQTvOG8eE+gTeGYRAmnNAubN3hf5Zv9tJWDHp/VTuaSm7SN4fyINQqaNO3RMVxvpSPXnOChnRNvFcGY0gnwiPswYwTKVPE0zVtX3mTEIOoFzaqLrGuJaV+Uqumb71fVk/VoOH3cdLNQP/FHi8hV0CQNoqBZsUPlLPMsdCJro9QAaQQ0woDy9BJm0eTxCFnO9srcYlhNVlfR2EyTrph1uUtbUtAJifwRgrKuYdXVHeb0YI3QpawohQHkloI3J5FuVwI5ORxC9k2Tuz9Ir1IjgeIPGMHYkAZe2RuYkmWFmt3gGbTPOmBUWVTmRmHtGrfpzG/yuQNOKa6gBB/WA9khitPgl6/GP+gl2Af6tCbvaygAAAABJRU5ErkJggg=="});let e=v(),n=v(8),s=1,i=0,r=new tn(t),a=new Jt(e,n,r,s,i);vl=new Di(a)}function Wf(t=!0){os=t}function qf(t){ma=t}function Hf(){return mn==="mouse"}function $f(){return mn==="keyboard"}function Yf(){return mn==="gamepad"}function ya(t,e=0,n=!0,s=!0,i=!0){re[e]&&(re[e][t]&=~((n?1:0)|(s?2:0)|(i?4:0)))}function ai(){re.length=0,re[0]=[],bt.length=0,Un.length=0,ci.length=0,Lt.length=0,On.length=0}function ze(t,e=0){var n;return m(ee(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=re[e])==null?void 0:n[t])&1)}function He(t,e=0){var n;return m(ee(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=re[e])==null?void 0:n[t])&2)}function ga(t,e=0){var n;return m(ee(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=re[e])==null?void 0:n[t])&4)}function Xf(t="ArrowUp",e="ArrowDown",n="ArrowLeft",s="ArrowRight"){m(ee(t),"up key must be a string"),m(ee(e),"down key must be a string"),m(ee(n),"left key must be a string"),m(ee(s),"right key must be a string");let i=r=>ze(r)?1:0;return v(i(s)-i(n),i(t)-i(e))}function Ds(t){return m(O(t),"mouse button must be a number"),ze(t)}function Js(t){return m(O(t),"mouse button must be a number"),He(t)}function Kf(t){return m(O(t),"mouse button must be a number"),ga(t)}function Vt(t,e=ke){return m(O(t),"button must be a number"),m(O(e),"gamepad must be a number"),ze(t,e+1)}function ba(t,e=ke){return m(O(t),"button must be a number"),m(O(e),"gamepad must be a number"),He(t,e+1)}function Qf(t,e=ke){return m(O(t),"button must be a number"),m(O(e),"gamepad must be a number"),ga(t,e+1)}function Ns(t,e=ke){var n,s;return m(O(t),"stick must be a number"),m(O(e),"gamepad must be a number"),(s=(n=Lt[e])==null?void 0:n[t])!=null?s:v()}function cr(t=ke){var e;return m(O(t),"gamepad must be a number"),(e=On[t])!=null?e:v()}function lr(t=ke){return m(O(t),"gamepad must be a number"),!!re[t+1]}function wl(t=ke){var e,n;return m(O(t),"gamepad must be a number"),(n=(e=Lt[t])==null?void 0:e.length)!=null?n:0}function Zf(t=ke,e=200,n=1,s=1,i=0){var a,o,c;if(m(O(t),"gamepad must be a number"),!si||X)return;let r=(a=navigator==null?void 0:navigator.getGamepads)==null?void 0:a.call(navigator)[t];(c=(o=r==null?void 0:r.vibrationActuator)==null?void 0:o.playEffect)==null||c.call(o,"dual-rumble",{duration:e,strongMagnitude:n,weakMagnitude:s,startDelay:i})}function eh(t=ke){var n,s,i;if(m(O(t),"gamepad must be a number"),!si||X)return;let e=(n=navigator==null?void 0:navigator.getGamepads)==null?void 0:n.call(navigator)[t];(i=(s=e==null?void 0:e.vibrationActuator)==null?void 0:s.reset)==null||i.call(s)}function xa(t=100){var e;m(O(t)||At(t),"pattern must be a number or array"),si&&!X&&((e=navigator==null?void 0:navigator.vibrate)==null||e.call(navigator,t))}function th(){xa(0)}function nh(){var t;!gt&&((t=$.requestPointerLock)==null||t.call($))}function sh(){var t;(t=document.exitPointerLock)==null||t.call(document)}function Tl(){return document.pointerLockElement===$}function ih(){if(X)return;document.addEventListener("keydown",t),document.addEventListener("keyup",e),document.addEventListener("mousedown",s),document.addEventListener("mouseup",i),document.addEventListener("mousemove",r),document.addEventListener("mouseleave",a),document.addEventListener("wheel",o,{passive:!1}),document.addEventListener("contextmenu",c),document.addEventListener("blur",l),gt&&In&&u();function t(f){if(f.repeat||(re[0][f.code]=3,Ls&&(re[0][n(f.code)]=3)),!os||!f.cancelable||!document.hasFocus()||f.ctrlKey||f.metaKey||f.altKey||y(f.target)||y(document.activeElement))return;let d=typeof f.key=="string"&&f.key.length===1;(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Space","Tab","Backspace"].includes(f.code)||d)&&f.preventDefault();function y(x){let w=x==null?void 0:x.tagName;return(x==null?void 0:x.isContentEditable)||["INPUT","TEXTAREA","SELECT"].includes(w)}}function e(f){re[0][f.code]=re[0][f.code]&2|4,Ls&&(re[0][n(f.code)]=4)}function n(f){return Ls?f==="KeyW"?"ArrowUp":f==="KeyS"?"ArrowDown":f==="KeyA"?"ArrowLeft":f==="KeyD"?"ArrowRight":f:f}function s(f){if(gt&&In)return;at&&!X&&Te&&!Us()&&Te.resume(),re[0][f.button]=3;let d=nt;nt=h(v(f.x,f.y)),Mt=Mt.add(nt.subtract(d)),os&&f.cancelable&&document.hasFocus()&&f.preventDefault()}function i(f){gt&&In||(re[0][f.button]=re[0][f.button]&2|4)}function r(f){Ii=!0;let d=nt;nt=h(v(f.x,f.y));let p=Tl()?v(f.movementX,f.movementY):nt.subtract(d);Mt=Mt.add(p)}function a(){Ii=!1}function o(f){f.ctrlKey||(pa+=mt(f.deltaY)),os&&f.cancelable&&document.hasFocus()&&f.preventDefault()}function c(f){f.preventDefault()}function l(){ai(),Xt.clear(),bt.length=0,Un.length=0,ci.length=0}function u(){document.addEventListener("touchstart",p=>d(p),{passive:!1}),document.addEventListener("touchmove",p=>d(p),{passive:!1}),document.addEventListener("touchend",p=>d(p),{passive:!1});let f;function d(p){if(In){if(at&&!X&&Te&&!Us()&&Te.resume(),!Tn||aa){let y=S=>zs.includes(S.target)||S.target===Dn,x=[];for(let S of p.touches)y(S)||x.push(S);let w=x.length,A=0;if(w){let S=v(x[0].clientX,x[0].clientY),_=nt;nt=h(S),f?Mt=Mt.add(nt.subtract(_)):re[0][A]=3}else f&&(re[0][A]=re[0][A]&2|4);f=w}return os&&p.cancelable&&document.hasFocus()&&p.preventDefault(),!0}}}function h(f){let d=$.getBoundingClientRect(),p=Xe(f.x,d.left,d.right),y=Xe(f.y,d.top,d.bottom);return v(p*$.width,y*$.height)}}function Gc(){if(X)return;!(In&>)&&!document.hasFocus()&&ai(),Ut=oi(nt),ha=bl(Mt),rh(),e(),t();function t(){let n=Ds(0)||Ds(1)||Ds(2)||Mt.length()>ma,s=!1;for(let r=wl();r--&&!s;)s=Ns(r).lengthSquared()>.04;for(let r=17;r--&&!s;)s=Vt(r);let i=!1;for(let r in re[0])if(isNaN(+r)&&re[0][r]&1){i=!0;break}s?mn="gamepad":n?mn="mouse":i&&(mn="keyboard"),as=mn==="gamepad"}function e(){var a,o,c,l,u,h,f;let n=d=>{let x=w=>w>.3?Xe(w,.3,.8):w<-.3?-Xe(-w,.3,.8):0;return v(x(d.x),x(-d.y)).clampLength()};if(Tn&>){if(m(!qn||!bs,"set touchGamepadLeftStick or touchGamepadLeftButtonCount, not both"),m(!xs||!gs,"set touchGamepadRightStick or touchGamepadButtonCount, not both"),!fs.isSet())return;ke=0;let d=(a=Lt[0])!=null?a:Lt[0]=[],p=(o=On[0])!=null?o:On[0]=v();d.length=0,p.set();for(let x=0;x<2;x++){if(!nn(x))continue;let w=wa(x);d[w]=v();let A=(c=Un[x])!=null?c:v();if(ni)d[w]=n(A);else if(A.lengthSquared()>.3){let S=Y(Ci(A.x),-1,1),_=Y(Ci(A.y),-1,1);d[w]=v(S,-_).clampLength(),w||p.set(S,-_)}}let y=(l=re[1])!=null?l:re[1]=[];for(let x=12;x--;){let w=Vt(x,0);y[x]=bt[x]?w?1:3:w?4:0,Pi&&y[x]===3&&(x===9||ah(x))&&xa(Pi)}return}try{if(!uo||!(navigator!=null&&navigator.getGamepads))return}catch{return}if(!Ye&&!document.hasFocus())return;let s=8,i=navigator.getGamepads(),r=de(s,i.length);for(let d=0;d>1]=n(v(p.axes[S],p.axes[S+1]));let A=!1;for(let S=p.buttons.length;S--;){let _=p.buttons[S],k=Vt(S,d);y[S]=_.pressed?k?1:3:k?4:0,_.pressed&&(!_.value||_.value>.9)&&(A=!0)}A&&(Zo[d]=!0,Zo[ke]||(ke=d)),p.mapping==="standard"&&w.set((Vt(15,d)&&1)-(Vt(14,d)&&1),(Vt(12,d)&&1)-(Vt(13,d)&&1)),ra&&(w.x||w.y)&&(x[0]=w.clampLength())}Tn&&as&&fs.unset()}}function Bc(){if(!X){for(let t of re)for(let e in t)t[e]&=1;pa=0,ha=v(),Mt=v()}}function oh(){dh()}function rh(){if(fn||!Tn||!gt||X||!document.body)return;let t=fn=document.createElement("div");t.style.cssText="position:fixed;inset:0;z-index:50;pointer-events:none;opacity:0;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;transition:opacity .2s;box-sizing:border-box;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)";let e=Al=document.createElement("div");e.style.cssText="position:relative;width:100%;height:100%;pointer-events:none",t.appendChild(e);let n=Sa=document.createElementNS(Gi,"svg");n.style.cssText="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible;fill:none;stroke:#fff;stroke-width:3",e.appendChild(n);let s=()=>{let i=document.createElement("div");return i.style.cssText="position:absolute;pointer-events:auto;touch-action:none",i.addEventListener("pointerdown",r=>mh(r,i)),i.addEventListener("pointermove",r=>yh(r)),i.addEventListener("pointerup",r=>jc(r)),i.addEventListener("pointercancel",r=>jc(r)),e.appendChild(i),i};zs[0]=s(),zs[1]=s(),Dn=s(),addEventListener("resize",()=>hs=!0),document.body.appendChild(t),hs=!0}function fo(){return Al.getBoundingClientRect()}function nn(t){return t?xs:qn}function Yn(t){return t?gs:bs}function va(t){return t?0:4}function wa(t){return t&&qn?1:0}function ps(t){return nn(t)||Yn(t)>0}function ah(t){for(let e=0;e<2;e++){let n=va(e);if(!nn(e)&&t>=n&&tr.style.cssText="position:absolute;pointer-events:auto;touch-action:none;"+a;if(Ft){for(let r of zs)r.style.display="none";kt?(i(Dn,"inset:0"),Dn.style.display=""):Dn.style.display="none"}else{for(let a=0;a<2;a++){let o=zs[a],c=a?"right":"left";if(o.style.display=ps(a)?"":"none",kn){let l=ps(a?0:1)?"50%":"100%";i(o,`${c}:0;bottom:0;width:${l};height:60%`)}else i(o,`${c}:0;bottom:0;width:${3*s}px;height:${3*s}px`)}Dn.style.display=kt?"":"none";let r=kt;i(Dn,`left:50%;top:50%;width:${2*r}px;height:${2*r}px;transform:translate(-50%,-50%)`)}lh(e,n),hs=!1}function lh(t,e){let n=Sa;for(;n.firstChild;)n.removeChild(n.firstChild);let s=kl={face:[],thumb:[]},i=rt,r=(o,c,l,u)=>{let h=document.createElementNS(Gi,"circle");return h.setAttribute("cx",o),h.setAttribute("cy",c),h.setAttribute("r",l),u&&h.setAttribute("fill",u),n.appendChild(h),h},a=o=>{let c=i*.18,l=i*.5,u=o.x,h=o.y,f=document.createElementNS(Gi,"path");f.setAttribute("d",`M ${u-c} ${h-l} H ${u+c} V ${h-c} H ${u+l} V ${h+c} H ${u+c} V ${h+l} H ${u-c} V ${h+c} H ${u-l} V ${h-c} H ${u-c} Z`),n.appendChild(f)};for(let o=0;o<2;o++){let c=Yn(o),l=va(o),u=Qt(o,t,e);if(nn(o))ni?r(u.x,u.y,i/2):a(u),s.thumb[o]=r(u.x,u.y,i/4,"#fff");else if(c===1)s.face[l]=r(u.x,u.y,i/2,"#000");else for(let h=0;h2?f:de(f,c-1);d=d===3?2:d===2?3:d;let p=v().setDirection(f,i/2);c===2&&(p.x*=-1),o||(p.x*=-1);let y=u.add(p);s.face[l+d]=r(y.x,y.y,i/4,"#000")}}Ye&&jn&&uh(t,e)}function uh(t,e){let n=rt,s=Sa,i=(a,o,c)=>{let l=document.createElementNS(Gi,a);for(let u in o)l.setAttribute(u,o[u]);l.setAttribute("stroke",c),l.setAttribute("stroke-width",2),l.setAttribute("fill","none"),s.appendChild(l)},r=(a,o,c)=>i("circle",{cx:a.x,cy:a.y,r:o},c);i("line",{x1:t/2,y1:0,x2:t/2,y2:e},"#0f0");for(let a=0;a<2;a++)if(nn(a))if(kn){let o=e*.4,c=!ps(a?0:1),l=c?0:a?t/2:0;i("rect",{x:l,y:o,width:c?t:t/2,height:e-o},"#0ff")}else r(Qt(a,t,e),2*n,"#0ff");else Yn(a)>=1&&r(Qt(a,t,e),n,"#0ff");if(kt){r(v(t/2,e/2),kt,"#ff0");for(let a=0;a<2;a++)ps(a)&&r(Qt(a,t,e),2*n,"#f0f")}}function dh(){var l;if(!fn||X)return;if(!Tn||!gt){fn.style.display!=="none"&&(fn.style.display="none",Xt.clear(),bt.length=0,Un.length=0,ci.length=0);return}fn.style.display="";let t=Ye&&jn,e=[gs,bs,qn,xs,ni,rt,kn,kt,Ft,t].join();e!==Fc&&(Fc=e,hs=!0),hs&&ch();let n=Os?Xe(fs.get(),Os+1,Os):1,s=t||fs.isSet()&&n>0&&!Ft;if(fn.style.opacity=s?t?1:n*ca:0,!s)return;let i=fo(),r=i.width,a=i.height,o=rt,c=kl;if(c){for(let u=0;u<2;u++)if(nn(u)&&c.thumb[u]){let f=Qt(u,r,a).add(((l=Un[u])!=null?l:v()).scale(o/2));c.thumb[u].setAttribute("cx",f.x),c.thumb[u].setAttribute("cy",f.y)}for(let u=0;u=rt)return-1;if(i===1)return r;let o=a.subtract(e);t||(o.x*=-1);let c=i===2?o.xr:o&&Qt(a,e,n).distance(t)<2*s)return{role:"stick",side:a}}else if(Yn(a)>=1){let c=hh(a,t,e,n);if(c>=0)return{role:"face",btn:c}}}if(kt){for(let a=0;a<2;a++)if(ps(a)&&Qt(a,e,n).distance(t)<2*s)return;if(v(e/2,n/2).distance(t)h.getChannelData(x).set(y)),f.buffer=h,f.playbackRate.value=n,f.loop=i,a=a||Te.createGain(),a.gain.value=e,a.connect(Zt);let d=new StereoPannerNode(Te,{pan:Y(s,-1,1)});f.connect(d).connect(a),f.addEventListener("ended",()=>{a.disconnect(),d.disconnect(),c&&c(f)});let p=o*n;return f.start(0,p),Ye&&us&&_e("sound","vol",e.toFixed(2),"rate",n.toFixed(2),"pan",s.toFixed(2),i?"loop":""),f}function Sh(...t){return Ta([ho(...t)])}function ho(t=1,e=.05,n=220,s=0,i=0,r=.1,a=0,o=1,c=0,l=0,u=0,h=0,f=0,d=0,p=0,y=0,x=0,w=1,A=0,S=0,_=0){let k=Ss,C=oe*2,L=c*=500*C/k/k,N=n*=(1+we(e,-e))*C/k,ae=0,Z=0,T=0,P=1,R,M=[],B=0,ne=0,V=0,q,Re=2,Ie=C*he(_)*2/k,xe=be(Ie),Pe=pe(Ie)/2/Re,Fe=1+Pe,Ve=-2*xe/Fe,_t=(1-Pe)/Fe,pt=(1+mt(_)*xe)/2/Fe,sn=-(mt(_)+xe)/Fe,Cn=pt,Nt=0,on=0,rn=0,Kn=0;for(s=s*k||9,A*=k,i*=k,r*=k,x*=k,l*=500*C/k**3,p*=C/k,u*=C/k,h*=k,f=f*k|0,R=s+A+i+r+x|0;ne1?a>2?a>3?a>4?B/C%14?V:mt(V)*he(V)**o)*(nene?0:(neh&&(n+=u,N+=u,P=0),f&&!(++Z%f)&&(n=N,c=L,P||(P=1));return M}function ji(t,e=!0){for(let n of Sn)if((!e||n.isSolid)&&t.arrayCheck(n.size)){let s=n.getCollisionData(t);if(s)return s}return 0}function hn(t,e=v(),n,s=!0){for(let i of Sn)if((!s||i.isSolid)&&i.collisionTest(t,e,n))return i}function El(t,e,n,s,i=!0){let r,a,o,c=s&&v();for(let l of Sn)if(!i||l.isSolid){let u=l.collisionRaycast(t,e,n,c);if(u){let h=t.distanceSquared(u);(r===void 0||h{H=!1,fe.style.display="none",n.preventDefault(),_e("WebGL context lost! Switching to Canvas2d rendering.");for(let s of Is)s.glTexture=void 0;ft=void 0,je=0,Vn=!1,Gn.forEach(s=>{var i;return(i=s.glContextLost)==null?void 0:i.call(s)})}),fe.addEventListener("webglcontextrestored",()=>{H=!0,fe.style.display="",_e("WebGL context restored, reinitializing..."),e();for(let n of Is)n.glTexture=mo(n.image,n.wrap);Gn.forEach(n=>{var s;return(s=n.glContextRestored)==null?void 0:s.call(n)})});function e(){zi=ys(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 g;in vec4 p,u,c,a;in float r;out vec2 v;out vec4 d,e;void main(){vec2 s=(g-.5)*p.zw;gl_Position=m*vec4(p.xy+s*cos(r)-vec2(-s.y,s)*sin(r),1,1);v=mix(u.xw,u.zy,g);d=c;e=a;}`,`#version 300 es
+precision highp float;uniform sampler2D s;in vec2 v;in vec4 d,e;out vec4 c;void main(){c=texture(s,v)*d+e;}`),Ui=ys(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 p;in vec4 c;out vec4 d;void main(){gl_Position=m*vec4(p,1,1);d=c;}`,`#version 300 es
+precision highp float;in vec4 d;out vec4 c;void main(){c=d;}`);let n=new ArrayBuffer(Wi);$e=new Float32Array(n),Hs=new Uint32Array(n),dr=g.createBuffer(),cs=g.createBuffer(),ka=g.createFramebuffer(),je=0;let s=new Float32Array([0,0,1,0,0,1,1,1]);g.bindBuffer(g.ARRAY_BUFFER,cs),g.bufferData(g.ARRAY_BUFFER,s,g.STATIC_DRAW);let i,r,a,o=(c,l,u,h,f=0)=>{let d=g.getAttribLocation(r,c),p=u===1,y=u&&a;g.enableVertexAttribArray(d),g.vertexAttribPointer(d,h,l,p,y,i),g.vertexAttribDivisor(d,f),i+=h*u};fr=g.createVertexArray(),g.bindVertexArray(fr),i=0,r=zi,a=Rl,g.bindBuffer(g.ARRAY_BUFFER,cs),o("g",g.FLOAT,0,2),g.bindBuffer(g.ARRAY_BUFFER,dr),g.bufferData(g.ARRAY_BUFFER,Wi,g.DYNAMIC_DRAW),o("p",g.FLOAT,4,4,1),o("u",g.FLOAT,4,4,1),o("c",g.UNSIGNED_BYTE,1,4,1),o("a",g.UNSIGNED_BYTE,1,4,1),o("r",g.FLOAT,4,1,1),hr=g.createVertexArray(),g.bindVertexArray(hr),i=0,r=Ui,a=Pl,o("p",g.FLOAT,4,2),o("c",g.UNSIGNED_BYTE,1,4)}}function $s(t=!1){!t&&!Vn||(Ne(),Vn=!1,g.useProgram(zi),g.bindVertexArray(fr))}function Ml(){Vn||(Ne(),Vn=!0,g.useProgram(Ui),g.bindVertexArray(hr))}function mr(t=!0){if(!H||!g)return;m(!je,"glPreRender called with unflushed batch."),Vi||(fe.width=z.x,fe.height=z.y),g.viewport(0,0,z.x,z.y),t&&Ll();let e=v(2*ie).divide(z);Vi&&(e.y=-e.y);let n=Je.rotate(-ue),s=v(-1).subtract(n.multiply(e)),i=be(ue),r=pe(ue),a=[e.x*i,e.y*r,0,0,-e.x*r,e.y*i,0,0,1,1,1,0,s.x,s.y,0,1],o=(c,l,u)=>{g.useProgram(c);let h=g.getUniformLocation(c,l);g.uniformMatrix4fv(h,!1,u)};o(Ui,"m",a),o(zi,"m",a),g.activeTexture(g.TEXTURE0),An[0]&&(ft=An[0].glTexture,g.bindTexture(g.TEXTURE_2D,ft)),g.bindBuffer(g.ARRAY_BUFFER,dr),Xn=ms=!1,$s(!0)}function Ll(){if(!g)return;let t=gn;g.clearColor(t.r,t.g,t.b,t.a),g.clear(g.COLOR_BUFFER_BIT)}function _a(t){!g||t===ft||(Ne(),ft=t,g.bindTexture(g.TEXTURE_2D,ft))}function Ol(t,e=!0){if(!g||!t)return;let n=t===ft;n?Ne():g.bindTexture(g.TEXTURE_2D,t);let s=e?g.REPEAT:g.CLAMP_TO_EDGE;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,s),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,s),!n&&ft&&g.bindTexture(g.TEXTURE_2D,ft)}function yr(t,e){if(!g)return;let n=g.createShader(e);if(g.shaderSource(n,t),g.compileShader(n),Ye&&!g.getShaderParameter(n,g.COMPILE_STATUS))throw g.getShaderInfoLog(n);return n}function ys(t,e){if(!g)return;let n=g.createProgram();if(g.attachShader(n,yr(t,g.VERTEX_SHADER)),g.attachShader(n,yr(e,g.FRAGMENT_SHADER)),g.linkProgram(n),Ye&&!g.getProgramParameter(n,g.LINK_STATUS))throw g.getProgramInfoLog(n);return n}function mo(t,e=!1){if(!g)return;let n=g.createTexture(),s=!1;if(t!=null&&t.width)Ea(n,t),g.bindTexture(g.TEXTURE_2D,n),s=!zn&&Gs(t.width)&&Gs(t.height);else{let o=new Uint8Array([255,255,255,255]);g.bindTexture(g.TEXTURE_2D,n),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,1,1,0,g.RGBA,g.UNSIGNED_BYTE,o)}let i=zn?g.NEAREST:g.LINEAR,r=s?g.LINEAR_MIPMAP_LINEAR:i;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,i),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,r);let a=e?g.REPEAT:g.CLAMP_TO_EDGE;return g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,a),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,a),s&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,ft),n}function Dl(t){g&&g.deleteTexture(t)}function Ea(t,e){g&&(m((e==null?void 0:e.width)>0,"Invalid image data."),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e),!zn&&Gs(e.width)&&Gs(e.height)&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,ft))}function kh(t){X||(Is.add(t),g&&(t.glTexture?Ea(t.glTexture,t.image):t.glTexture=mo(t.image,t.wrap)))}function Ch(t){if(X)return;Is.delete(t);let e=t.glTexture;t.glTexture=void 0,Dl(e)}function Ne(){if(H&&g&&je){let t=ms?g.ONE:g.ONE_MINUS_SRC_ALPHA;g.blendFuncSeparate(g.SRC_ALPHA,t,g.ONE,t),g.enable(g.BLEND);let e=je*(Vn?po:Ca);g.bufferSubData(g.ARRAY_BUFFER,0,$e,0,e),Vn?g.drawArrays(g.TRIANGLE_STRIP,0,je):g.drawArraysInstanced(g.TRIANGLE_STRIP,0,4,je),++Bt,jt+=je,je=0}ms=Xn}function Ra(t){!H||!g||(Ne(),t.drawImage(fe,0,0))}function _h(t=!0){m(!fe,"must be called before engineInit"),Aa=t}function Ys(t,e,n,s,i=0,r=0,a=0,o=1,c=1,l=-1,u=0){(je>=Th||ms!==Xn)&&Ne(),$s();let h=je++*Ca;$e[h++]=t,$e[h++]=e,$e[h++]=n,$e[h++]=s,$e[h++]=r,$e[h++]=a,$e[h++]=o,$e[h++]=c,Hs[h++]=l,Hs[h++]=u,$e[h++]=i}function Il(t,e,n,s,i,r){Ys(t,e,n,s,i,0,0,0,0,0,r)}function Pa(t,e,n,s,i,r,a,o=!0){let c=[],l=pe(-a),u=be(-a);for(let f of t){let d=f.x*i,p=f.y*r;c.push(v(n+u*d-l*p,s+l*d+u*p))}let h=o?Rh(c):c;Fl(h,e)}function Ma(t,e,n,s,i,r,a,o,c=!0){let l=Eh(t,n,c);Pa(l,e,s,i,r,a,o,!1)}function Fl(t,e){if(!H||t.length<3)return;let n=t.length+2;if((je+n>=ls||ms!==Xn)&&Ne(),m(n=ls)return;Ml();let s=je*po;for(let i=n;i--;){let r=Y(i-1,0,n-3),a=t[r];$e[s++]=a.x,$e[s++]=a.y,Hs[s++]=e}je+=n}function La(t,e){if(!H||t.length<3)return;let n=t.length+2;if((je+n>=ls||ms!==Xn)&&Ne(),m(n=ls)return;Ml();let s=je*po;for(let i=n;i--;){let r=Y(i-1,0,n-3),a=t[r],o=e[r];$e[s++]=a.x,$e[s++]=a.y,Hs[s++]=o}je+=n}function Ps(t,e=!1){t?(Vi=t,g.bindFramebuffer(g.FRAMEBUFFER,ka),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,t,0),mr(e)):(Ne(),Vi=void 0,g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,z.x,z.y))}function Gl(t,e,n,s){H&&(g.enable(g.SCISSOR_TEST),g.scissor(t,e,n,s),g.clearColor(0,0,0,0),g.clear(g.COLOR_BUFFER_BIT),g.disable(g.SCISSOR_TEST))}function Eh(t,e,n=!0){if(t.length<2)return[];let s=e/2,i=[],r=t.length,a=1e-6,o=10;for(let c=0;ca?-d/p:0,S=p>a?f/p:0,_=w>a?-x/w:0,k=w>a?y/w:0,C=A+_,L=S+k,N=(C*C+L*L)**.5;if(Na){let P=de(1/T,o);C*=P,L*=P}}let ae=v(u.x-C*s,u.y-L*s),Z=v(u.x+C*s,u.y+L*s);i.push(ae),i.push(Z)}return i.length>1&&n&&(i.push(i[0]),i.push(i[1])),i}function Rh(t){if(t.length<3)return[];let e=(d,p,y)=>(p.x-d.x)*(y.y-d.y)-(p.y-d.y)*(y.x-d.x);(d=>{let p=0;for(let y=d.length;y--;){let x=(y+1)%d.length;p+=d[y].cross(d[x])}return p})(t)<0&&(t=t.slice().reverse());let s=1e-9,i=(d,p,y,x)=>{let w=e(p,y,d),A=e(y,x,d),S=e(x,p,d),_=(w<-s?1:0)+(A<-s?1:0)+(S<-s?1:0),k=(w>s?1:0)+(A>s?1:0)+(S>s?1:0);return!(_&&k)},r=[];for(let d=0;d3&&o++{if(_>=0){let C=s.fillStyle=s.createLinearGradient(x,w,A,S);C.addColorStop(0,h(_,2)),C.addColorStop(1,h(_,1))}else s.fillStyle="#000";_>=-1?(s.fill(),k&&s.stroke()):s.stroke()},c=(x,w,A,S=0,_=2*oe,k,C)=>{s.beginPath(),s.arc(x,w,A,d*S,d*_),o(x,w-A,x,w+A,k,C)},l=(x,w,A,S,_)=>{s.beginPath(),s.rect(x,w,A,S*d),o(x,w+S,x+A,w,_)},u=(x,w,A,S)=>{s.beginPath();for(let _ of x)s.lineTo(_.x,_.y);s.closePath(),o(0,A,0,A+S,w)},h=(x,w)=>w?`hsl(${[.95,.56,.13][x%3]*360} 99%${[0,50,75][w]}%)`:"#000",f=sl(1,1,t),d=Xe(f,.1,.5),p=de(6,de(r,a)/99);s.translate(r/2,a/2),s.scale(p,p),s.translate(-40,-35),d<1&&s.setLineDash([99*d,99]),s.lineJoin=s.lineCap="round",s.lineWidth=.1+d*1.9;{let w="LittleJS";s.font="900 15.5px arial",s.lineWidth=.1+d*3.9,s.textAlign="center",s.textBaseline="top",l(11,55,59,8*d,-1),s.beginPath();let A=0;for(let S=0;S5?1:0),s[S?"strokeText":"fillText"](w[_],L,54+.5,17*d),k+=C}s.lineWidth=.1+d*1.9,l(3,54,73,0)}l(7,15,26,-7,0),l(25,15,8,25,-1),l(10,40,15,-25,1),l(14,21,7,9,2),l(38,20,6,-6,2),l(49,20,10,-6,0);let y=[v(44,8),v(64,8),v(59,8+6*d),v(49,8+6*d)];u(y,2,8,6*d),l(44,8,20,-7,0);for(let x=5;x--;)c(59-x*6*d,30,10,0,2*oe,1,0);c(59,30,4,0,7,2),l(35,20,24,0),c(59,30,10),c(47,30,10,oe/2,oe*3/2),c(35,30,10,oe/2,oe*3/2),l(7,40,13,7,-1),l(17,40,43,14,-1);for(let x=3;x--;)for(let w=2;w--;)c(17+15*x,47,w?7:1,0,2*oe,2);for(let x=2;x--;){let w=6,A=7,S=53+w*d*x,_=[v(S+A,54),v(S,40),v(S+w*d,40),v(S+A+w*d,54)];u(_,0,40,14)}s.restore()}function Mh(t){if($i=t,!Ln){let n={};try{n=JSON.parse(localStorage[t]||"{}")}catch{n={}}yo(s=>{s.unlocked=!!(n[s.id]&&n[s.id].unlocked)}),Da()}Wn(void 0,e);function e(){if(!wi.length)return;let n=wi[0],s=vn-vi;if(!vi)vi=vn;else if(s>qi)vi=0,wi.shift();else{let i=qi-rs,r=si?(s-i)/rs:0;n.render(r)}}}function yo(t){Object.values(Xs).forEach(e=>t(e))}function Lh(){yo(t=>t.unlocked=!1),Da()}function Da(){if(!$i)return;let t={};yo(e=>{let n={name:e.name,description:e.description,icon:e.icon,unlocked:e.unlocked};e.image&&(n.src=e.image.src),t[e.id]=n}),localStorage[$i]=JSON.stringify(t)}function Oh(t){qi=t}function Dh(t){rs=t}function Ih(t){Hi=t.copy()}function Fh(t){Oa=t}function Bl(t,e,n,s=125){let i,r,a,o,c,l,u,h,f,d,p,y,x,w=0,A,S=[],_=[],k=[],C=0,L=0,N=1,ae={},Z=Ss/s*60>>2;for(;N;C++)S=[N=h=y=0],n.forEach((T,P)=>{for(u=e[T][C]||[0,0,0],N|=e[T][C]&&1,A=y+(e[T][0].length-2-(h?0:1))*Z,x=P===n.length-1,i=2,a=y;iZ-99&&f&&p<1?p+=1/99:0)l=(1-p)*S[w++]/2||0,_[a]=(_[a]||0)-l*L+l,k[a]=(k[a++]||0)+l*L+l;c&&(p=c%1,L=u[1]||0,(c|=0)&&(S=ae[[d=u[w=0]||0,c]]=ae[[d,c]]||(o=[...t[d]],o[2]=(o[2]||220)*2**(c/12-1),c>0?ho(...o):[])))}y=A});return[_,k]}function Gh(t){Ia=typeof t=="boolean"?t?1:0:t}function Bh(t){Fa=t}async function jh(){return new eo(await Box2D()),n(),Wn(t,e),b;function t(){if(!Ft){b.step(),b.objects=b.objects.filter(s=>!s.destroyed);for(let s of b.objects)s.body&&(s.pos=b.vec2From(s.body.GetPosition()),s.angle=-s.body.GetAngle())}}function e(){(Fa||wt)&&b.world.DrawDebugData()}function n(){let i=new b.instance.JSDraw,r=l=>new De(l.get_r(),l.get_g(),l.get_b()),a=l=>r(b.instance.wrapPointer(l,b.instance.b2Color)),o=l=>a(l).scale(1,.8),c=(l,u)=>{let h=[];for(let f=u;f--;)h.push(b.vec2FromPointer(l+f*8));return h};i.DrawSegment=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),u=b.vec2FromPointer(u),Fn(l,u,.1,h,v(),0,!1)},i.DrawPolygon=function(l,u,h){h=o(h);let f=c(l,u);ds(f,wn,.1,h,v(),0,!1)},i.DrawSolidPolygon=function(l,u,h){h=o(h);let f=c(l,u);ds(f,h,0,h,v(),0,!1)},i.DrawCircle=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),Oi(l,u*2,wn,.1,h,!1)},i.DrawSolidCircle=function(l,u,h,f){f=o(f),l=b.vec2FromPointer(l),h=b.vec2FromPointer(h).scale(u),Oi(l,u*2,f,.1,f,!1),Fn(v(),h,.1,f,l,0,!1)},i.DrawTransform=function(l){l=b.instance.wrapPointer(l,b.instance.b2Transform);let u=b.vec2From(l.get_p()),h=-l.get_q().GetAngle(),f=v(1,0),d=K(.75,0,0,.8),p=v(0,1),y=K(0,.75,0,.8);Fn(v(),f,.1,d,u,h,!1),Fn(v(),p,.1,y,u,h,!1)},i.AppendFlags(b.instance.b2Draw.e_shapeBit),i.AppendFlags(b.instance.b2Draw.e_jointBit),b.world.SetDebugDraw(i)}}function Jh(t,e,n,s=32,i=2,r=0){jl(t,e,n,te,s,me,i,r,!1,!0)}function jl(t,e,n,s,i=1,r,a=.05,o=0,c=H,l,u){let h=n.offset(n.size),f=e.add(v(a-i*2)),d=v(i),p=e.scale(.5).subtract(d.scale(.5)),y=l?-1:1,x=l?-o:o;Ue(t,f,h,s,o,!1,r,c,l,u);for(let w=4;w--;){let A=w%2,S=p.multiply(v(A?w===1?1:-1:0,A?0:w?-1:1)),_=v(A?i:f.x,A?f.y:i),k=h.offset(n.size.multiply(v(w===1?1:w===3?-1:0,w===0?-y:w===2?y:0)));Ue(t.add(S.rotate(x)),_,k,s,o,!1,r,c,l,u)}for(let w=4;w--;){let A=w>1,S=w&&w<3,_=p.multiply(v(A?-1:1,S?-1:1)),k=h.offset(n.size.multiply(v(A?-1:1,S?y:-y)));Ue(t.add(_.rotate(x)),d,k,s,o,!1,r,c,l,u)}}function Nh(t,e,n,s=32,i=2,r=0){Jl(t,e,n,te,s,me,i,r,!1,!0)}function Jl(t,e,n,s,i=1,r,a=.05,o=0,c=H,l,u){let h=n.frame(0),f=n.frame(1),d=n.frame(2),p=e.add(v(a-i*2)),y=v(i),x=e.scale(.5).subtract(y.scale(.5)),w=l?-1:1,A=l?-o:o;Ue(t,p,d,s,o,!1,r,c,l,u);for(let S=4;S--;){let _=o+S*oe/2,k=S%2,C=x.multiply(v(k?S===1?1:-1:0,k?0:S?-w:w)),L=v(k?p.y:p.x,i);Ue(t.add(C.rotate(A)),L,f,s,_,!1,r,c,l,u)}for(let S=4;S--;){let _=o+S*oe/2,k=!S||S>2,C=S>1,L=x.multiply(v(k?-1:1,C?-w:w));Ue(t.add(L.rotate(A)),y,h,s,_,!1,r,c,l,u)}}function zh(t,e=1,n=0,s=te,i=0,r=!1,a=0,o=me,c=H,l=!1,u){let h=Nl(v(),e,n,0,r);ds(h,s,a,o,t,i,c,l,u)}function Nl(t,e=1,n=0,s=0,i=!1,r=ti){m(D(t),"pos must be a vec2"),m(O(e)&&O(n),"size and percent must be numbers");let a=yt(n*4,4);a>=2&&(s+=oe),a=a<=2?a-1:3-a,i&&(a=-a,s+=oe);let o=[],c=le(3,r>>1),l=e/2;for(let u=0;u<=c;u++){let h=u/c*oe;o.push(v(l*be(h),l*pe(h)).rotate(s).add(t))}for(let u=c;u>=0;u--){let h=u/c*oe;o.push(v(l*be(h),-l*a*pe(h)).rotate(s).add(t))}return o}function zc(t){return t&&typeof t.lerp=="function"}function Uh(t,e,n,s,i=1,r={}){m(t!=null&&typeof t=="object","tweenProperty target must be an object"),m(ee(e)&&e.length>0,"tweenProperty propertyPath must be a non-empty string");let a=e.split("."),o=a.pop(),c=l=>{let u=t;for(let h of a)u=u[h];u[o]=l};return new to(c,n,s,i,r)}function zl(t){t.loopRemaining!==1/0&&t.loopRemaining<=1||(t.loopRemaining!==1/0&&(t.loopRemaining-=1),t.life=t.duration,t.thenCallback=()=>zl(t),ut.push(t),t.callback(t.interp(t.duration)))}function Ul(t){if(t.loopRemaining!==1/0&&t.loopRemaining<=1)return;t.loopRemaining!==1/0&&(t.loopRemaining-=1);let e=t.start;t.start=t.end,t.end=e,t.life=t.duration,t.thenCallback=()=>Ul(t),ut.push(t),t.callback(t.interp(t.duration))}function Vl(t,e){t===void 0?(t=dt-Jc,e=vn-Nc,Jc=dt,Nc=vn):e===void 0&&(e=t);for(let n=ut.length;n--;){let s=ut[n];if(s.paused)continue;let i=s.useRealTime?e:t;if(!(i<=0))if(s.life-=i,s.life>0)s.callback(s.interp(s.life));else{s.callback(s.interp(0)),ut.splice(n,1);let r=s.thenCallback;s.thenCallback=void 0,r&&r()}}}function Vh(){for(let t of ut)t.thenCallback=void 0;ut.length=0}var Ti,Ai,sd,Vr,Ee,Wr,Uc,dt,vn,Ft,Qo,Pt,ki,Vc,Gn,tr,Ye,Hc,io,$c,Wt,yn,wt,Tt,Bn,jn,us,nr,qt,vt,oe,he,Oe,Fs,Ci,de,le,mt,Qc,Zc,pe,be,el,Hr,or,ge,De,te,wn,me,Ct,vd,Xr,wd,ll,ul,Td,dl,fl,Ad,Gt,Je,ue,ie,Qr,oo,gn,ns,Ms,ss,is,Zr,zn,bn,ei,ea,X,H,ti,ro,ao,co,lo,ta,na,sa,ia,oa,$t,it,Ri,uo,ra,Ls,In,Tn,aa,kt,gs,qn,bs,xs,ni,kn,rt,ca,Os,Pi,si,at,Jn,la,ua,en,$,Se,Be,Kt,pn,Ot,Yt,z,An,Bt,jt,Jt,tn,Df,vl,Di,Ut,nt,ha,Mt,pa,Ii,as,mn,ma,os,ke,gt,re,Lt,On,Zo,fs,bt,Un,Fi,ci,Xt,fn,Al,Sa,kl,zs,Dn,hs,Fc,Gi,Te,Zt,Ss,Vs,Bi,Sn,Nn,Ji,Ws,qs,ur,wh,Ni,fe,g,Aa,zi,Ui,Vn,Xn,ms,ft,dr,cs,$e,Hs,je,Is,fr,hr,ka,Vi,pr,Wi,Ca,Rl,Th,po,Pl,ls,Ln,qi,rs,Hi,Oa,Xs,wi,$i,vi,Yi,Ks,gr,br,qe,xr,se,Sr,vr,wr,E,Ia,Tr,xt,Xi,Ar,kr,Qs,Cr,_r,Er,Rr,b,Fa,Zs,Ki,Pr,Mr,Qi,ct,Lr,Zi,Or,Dr,Ir,Fr,Gr,Br,jr,Jr,Nr,zr,eo,ut,Jc,Nc,to,no,Wh,er,so,Ur,ql=Kl(()=>{"use strict";Ti="LittleJS",Ai="1.18.19",sd=60,Vr=.016666666666666666,Ee=[],Wr=[],Uc=0,dt=0,vn=0,Ft=!1;Qo=0,Pt=0,ki=0,Vc=!0,Gn=[],tr=class{constructor(e,n,s,i){this.update=e,this.render=n,this.glContextLost=s,this.glContextRestored=i}};Ye=!0,Hc=.5,io=!0,$c="Escape",Wt=!1,yn=[],wt=!1,Tt=!1,Bn=!1,jn=!1,us=!1;oe=Math.PI,he=Math.abs,Oe=Math.floor,Fs=Math.ceil,Ci=Math.round,de=Math.min,le=Math.max,mt=t=>Math.sign(t),Qc=(...t)=>Math.hypot(...t),Zc=t=>Math.log2(t),pe=Math.sin,be=Math.cos,el=Math.tan,Hr=Math.atan2;or=class{constructor(e=123456789){m(e!==0,"RandomGenerator seed must be non-zero (xorshift is fixed at 0)"),this.seed=e}float(e=1,n=0){return this.seed^=this.seed<<13,this.seed^=this.seed>>>17,this.seed^=this.seed<<5,n+(e-n)*((this.seed>>>0)/2**32)}int(e,n=0){return Oe(this.float(e,n))}bool(e=.5){return this.float().5?1:-1}floatSign(e=1,n=0){let s=de(e,n),r=le(e,n)-s,a=this.float(r*2);return ae?this.scale(e/n):this.copy()}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.x}reflect(e,n=1){return this.subtract(e.scale((1+n)*this.dot(e)))}angle(){return Hr(this.x,this.y)}setAngle(e=0,n=1){return lt(e),lt(n),this.x=n*pe(e),this.y=n*be(e),this}rotate(e){lt(e);let n=be(-e),s=pe(-e);return new t(this.x*n-this.y*s,this.x*s+this.y*n)}setDirection(e,n=1){return lt(e),lt(n),e=yt(e,4),m(e===0||e===1||e===2||e===3,"Vector2.setDirection() direction must be an integer between 0 and 3."),this.x=e%2?e-1?-n:n:0,this.y=e%2?0:e?-n:n,this}direction(){return he(this.x)>he(this.y)?this.x<0?3:1:this.y<0?2:0}abs(){return new t(he(this.x),he(this.y))}floor(){return new t(Oe(this.x),Oe(this.y))}snap(e){return lt(e),new t(Oe(this.x*e)/e,Oe(this.y*e)/e)}mod(e=1){return new t(yt(this.x,e),yt(this.y,e))}area(){return he(this.x*this.y)}lerp(e,n){Dc(e),lt(n);let s=Y(n);return new t(e.x*s+this.x*(1-s),e.y*s+this.y*(1-s))}arrayCheck(e){return this.x>=0&&this.y>=0&&this.x(u=yt(u,1))*6<1?c+(l-c)*6*u:u*2<1?l:u*3<2?c+(l-c)*(4-u*6):c;return this.r=o(a,r,e+1/3),this.g=o(a,r,e),this.b=o(a,r,e-1/3),this.a=i,Rs(this),this}HSLA(){let e=Y(this.r),n=Y(this.g),s=Y(this.b),i=Y(this.a),r=le(e,n,s),a=de(e,n,s),o=(r+a)/2,c=0,l=0;if(r!==a){let u=r-a;l=o>.5?u/(2-r-a):u/(r+a),e===r?c=(n-s)/u+(n((s=Y(s)*255|0)<16?"0":"")+s.toString(16);return"#"+n(this.r)+n(this.g)+n(this.b)+(e?n(this.a):"")}setHex(e){if(m(ee(e),"Color hex code must be a string"),m(e[0]==="#","Color hex code must start with #"),m([4,5,7,9].includes(e.length),"Invalid hex"),e.length<6){let n=s=>Y(parseInt(e[s],16)/15);this.r=n(1),this.g=n(2),this.b=n(3),this.a=e.length===5?n(4):1}else{let n=s=>Y(parseInt(e.slice(s,s+2),16)/255);this.r=n(1),this.g=n(3),this.b=n(5),this.a=e.length===9?n(7):1}return Rs(this),this}rgbaInt(){let e=Y(this.r)*255|0,n=Y(this.g)*255<<8,s=Y(this.b)*255<<16,i=Y(this.a)*255<<24;return e+n+s+i}isValid(){return O(this.r)&&O(this.g)&&O(this.b)&&O(this.a)}},te=ht(K()),wn=ht(K(1,1,1,0)),me=ht(K(0,0,0)),Ct=ht(K(0,0,0,0)),vd=ht(K(.5,.5,.5)),Xr=ht(K(1,0,0)),wd=ht(K(1,.5,0)),ll=ht(K(1,1,0)),ul=ht(K(0,1,0)),Td=ht(K(0,1,1)),dl=ht(K(0,0,1)),fl=ht(K(.5,0,1)),Ad=ht(K(1,0,1)),Gt=class{constructor(e,n=!1){m(e===void 0||O(e),"Constructed Timer is invalid.",e),this.useRealTime=n;let s=this.getGlobalTime();this.time=e===void 0?void 0:s+e,this.setTime=e}set(e=0){m(O(e),"Timer is invalid.",e);let n=this.getGlobalTime();this.time=n+e,this.setTime=e}setUseRealTime(e=!0){m(!this.isSet(),"Cannot change global time setting while timer is set."),this.useRealTime=e}unset(){this.time=void 0}isSet(){return this.time!==void 0}active(){return this.getGlobalTime()=this.time}get(){return this.isSet()?this.getGlobalTime()-this.time:0}getPercent(){return this.isSet()?this.setTime?1-Xe(this.time-this.getGlobalTime(),0,this.setTime):1:0}getSetTime(){return this.isSet()?this.setTime:0}getGlobalTime(){return this.useRealTime?vn:dt}toString(){return this.isSet()?he(this.get())+" seconds "+(this.get()<0?"before":"after"):"unset"}valueOf(){return this.get()}};Je=v(),ue=0,ie=32,Qr=1,oo=!0,gn=Ct,ns=v(1920,1080),Ms=0,ss=0,is=v(),Zr=!1,zn=!0,bn=1,ei="arial",ea=!1,X=!1,H=!0,ti=32,ro=v(16),ao=0,co=0,lo=!0,ta=1,na=1,sa=1,ia=0,oa=.8,$t=1,it=v(),Ri=1,uo=!0,ra=!0,Ls=!0,In=!0,Tn=!1,aa=!1,kt=0,gs=4,qn=!0,bs=0,xs=!1,ni=!0,kn=!1,rt=100,ca=.3,Os=3,Pi=0,si=!0,at=!0,Jn=.3,la=40,ua=.7;en=class t{constructor(e=v(),n=v(1),s,i=0,r=te,a=0){m(D(e),"object pos must be a vec2"),m(D(n),"object size must be a vec2"),m(!s||s instanceof Jt,"object tileInfo should be a TileInfo or undefined"),m(typeof i=="number"&&isFinite(i),"object angle should be a number"),m(Q(r),"object color should be a valid rgba color"),m(typeof a=="number","object renderOrder should be a number"),this.pos=e.copy(),this.size=n.copy(),this.drawSize=void 0,this.tileInfo=s,this.angle=i,this.color=r.copy(),this.additiveColor=void 0,this.mirror=!1,this.destroyed=!1,this.mass=ta,this.damping=na,this.angleDamping=sa,this.restitution=ia,this.friction=oa,this.gravityScale=1,this.renderOrder=a,this.velocity=v(),this.angleVelocity=0,this.spawnTime=dt,this.children=[],this.clampSpeed=!0,this.groundObject=void 0,this.parent=void 0,this.localPos=v(),this.localAngle=0,this.collideTiles=!1,this.collideSolidObjects=!1,this.isSolid=!1,this.collideRaycast=!1,Ee.push(this)}updateTransforms(){let e=this.parent;if(e){let n=e.getMirrorSign(),s=this.localPos,i=e.pos,r=s.x*n,a=s.y,o=e.angle;if(o){let c=be(-o),l=pe(-o);this.pos.set(r*c-a*l+i.x,r*l+a*c+i.y)}else this.pos.set(r+i.x,a+i.y);this.angle=n*this.localAngle+o}for(let n of this.children)n.updateTransforms()}updatePhysics(){if(m(!this.parent),this.destroyed)return;this.clampSpeed&&(this.velocity.x=Y(this.velocity.x,-$t,$t),this.velocity.y=Y(this.velocity.y,-$t,$t));let e=this.pos.copy();if(this.velocity.x*=this.damping,this.velocity.y*=this.damping,this.mass&&(this.velocity.x+=it.x*this.gravityScale,this.velocity.y+=it.y*this.gravityScale),this.pos.x+=this.velocity.x,this.pos.y+=this.velocity.y,this.angle+=this.angleVelocity*=this.angleDamping,m(this.angleDamping>=0&&this.angleDamping<=1),m(this.damping>=0&&this.damping<=1),!lo||!this.mass)return;let n=this.velocity.y<0&&it.y<0||this.velocity.y>0&&it.y>0;if(this.groundObject){let s=le(this.friction,this.groundObject.friction),i=this.groundObject.velocity.x;this.velocity.x=i+(this.velocity.x-i)*s,this.groundObject=void 0}if(this.collideSolidObjects)for(let i of Wr){if(i.destroyed||i.parent||i===this||!this.isSolid&&!i.isSolid||!this.isOverlappingObject(i))continue;let r=this.collideWithObject(i),a=i.collideWithObject(this);if(!r||!a)continue;if(Ei(e,this.size,i.pos,i.size)){let f=e.subtract(i.pos),d=f.length(),y=d<.001?v(0,1):f.scale(.001/d);this.velocity=this.velocity.add(y),i.mass&&(i.velocity=i.velocity.subtract(y)),wt&&sr(this.pos,this.size,i.pos,i.size,"#f00");continue}let o=this.size.add(i.size),c=(e.y-i.pos.y)*2>o.y+it.y,l=he(e.y-i.pos.y)*20?-1:1)>0?Oe(e.y-this.size.y/2+1)+this.size.y/2+.001:Fs(e.y+this.size.y/2-1)-this.size.y/2-.001;if(he(u-this.pos.y)<.1&&!hn(v(this.pos.x,u),this.size,this)){this.pos.y=u,wt&&Ce(this.pos,this.size,"#ff0");return}this.pos.x=e.x,this.velocity.x*=-a}if(r||!i){if(n){let c=this.size.y/2+1e-4;this.pos.y=it.y<0?Oe(e.y-this.size.y/2)+c:Fs(e.y+this.size.y/2)-c,this.groundObject=s}else this.pos.y=e.y,this.groundObject=void 0;this.velocity.y*=-a}wt&&Ce(this.pos,this.size,"#f00")}}}update(){}render(){Ue(this.pos,this.drawSize||this.size,this.tileInfo,this.color,this.angle,this.mirror,this.additiveColor)}renderLight(){}destroy(e=!1){var n;if(!this.destroyed){this.destroyed=!0,(n=this.parent)==null||n.removeChild(this);for(let s of this.children)s.parent=void 0,s.destroy(e)}}localToWorld(e){return this.pos.add(e.rotate(this.angle))}worldToLocal(e){return e.subtract(this.pos).rotate(-this.angle)}localToWorldVector(e){return e.rotate(this.angle)}worldToLocalVector(e){return e.rotate(-this.angle)}collideWithTile(e,n){return e>0}collideWithObject(e){return!0}getUp(e=1){return v().setAngle(this.angle,e)}getRight(e=1){return v().setAngle(this.angle+oe/2,e)}getAliveTime(){return dt-this.spawnTime}getSpeed(){return this.velocity.length()}applyAcceleration(e){this.mass&&(this.velocity=this.velocity.add(e))}applyAngularAcceleration(e){this.mass&&(this.angleVelocity+=e)}applyForce(e){this.mass&&this.applyAcceleration(e.scale(1/this.mass))}getMirrorSign(){return this.mirror?-1:1}addChild(e,n=v(),s=0){return m(!this.destroyed,"cannot add child to destroyed object"),this.destroyed||(m(!e.parent&&!this.children.includes(e)),m(e instanceof t,"child must be an EngineObject"),m(e!==this,"cannot add self as child"),this.children.push(e),e.parent=this,e.localPos=n.copy(),e.localAngle=s,e.updateTransforms()),e}removeChild(e){m(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}isOverlappingObject(e){return this.isOverlapping(e.pos,e.size)}isOverlapping(e,n=v()){return Ei(this.pos,this.size,e,n)}setCollision(e=!0,n=!0,s=!0,i=!0){m(e||!n,"solid objects must be set to collide"),this.collideSolidObjects=e,this.isSolid=n,this.collideTiles=s,this.collideRaycast=i}toString(){let e="type = "+this.constructor.name;return(this.pos.x||this.pos.y)&&(e+=`
+pos = `+this.pos),(this.velocity.x||this.velocity.y)&&(e+=`
+velocity = `+this.velocity),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.angle&&(e+=`
+angle = `+this.angle.toFixed(3)),this.color&&(e+=`
+color = `+this.color),e}renderDebugInfo(){if(!Ye)return;let e=this.collideTiles||this.collideSolidObjects||this.isSolid;if(!e&&!this.parent)return;let n=v(le(this.size.x,.2),le(this.size.y,.2)),s=K(this.collideTiles?1:0,this.collideSolidObjects?1:0,this.isSolid?1:0,.5);Ce(this.pos,n,s,0,this.angle,e),this.parent&&Ce(this.pos,n.scale(.8),K(1,1,1,.5),0,this.angle),this.parent&&Dt(this.pos,this.parent.pos,K(1,1,1,.5),.5)}},z=v(),An=[];Jt=class t{constructor(e=v(),n=ro,s=An[0],i=ao,r=co){this.pos=e.copy(),this.size=n.copy(),this.padding=i,this.textureInfo=s,this.bleed=r}offset(e){return new t(this.pos.add(e),this.size,this.textureInfo,this.padding,this.bleed)}frame(e){m(typeof e=="number");let n=this.size.x+this.padding*2,s=e*n;return m(s+this.size.x<=this.textureInfo.size.x,"frame extends beyond texture width!"),this.offset(new ge(s))}setFullImage(e=this.textureInfo){return this.textureInfo=e,this.pos=new ge,this.size=e.size.copy(),this.bleed=this.padding=0,this}tile(e){return ii(e,this.size,this.textureInfo,this.padding,this.bleed)}},tn=class{constructor(e,n=!0,s=!1){this.image=e,this.size=e?v(e.width,e.height):v(),this.sizeInverse=e?v(1/e.width,1/e.height):v(),this.glTexture=void 0,this.wrap=s,n&&this.createWebGLTexture()}createWebGLTexture(){kh(this)}destroyWebGLTexture(){Ch(this)}hasWebGL(){return!!this.glTexture}setWrap(e=!0){this.wrap=e,Ol(this.glTexture,e)}};Df=0;Di=class{constructor(e){m(!!e,"tileInfo is required for ImageFont"),this.tileInfo=e.frame(0)}drawText(e,n,s=1,i,r,a,o){m(D(s)||typeof s=="number","size must be a vec2 or number"),typeof s=="number"?(m(s>0),s*=ie,s=new ge(s,s)):s=s.scale(ie),this.drawTextScreen(e,$n(n),s,i,r,a,o)}drawTextScreen(e,n,s,i=!0,r=te,a=H,o){m(ee(e),"text must be a string"),m(D(n),"pos must be a vec2"),m(D(s)||typeof s=="number","size must be a vec2 or number"),m(Q(r),"color must be a color"),s=typeof s=="number"?new ge(s,s):s;let c=new ge,l=this.tileInfo,u=l.padding,h=l.size.x+u*2,f=l.size.y+u*2,d=l.textureInfo.size.x/h|0;(e+"").split(`
+`).forEach((p,y)=>{let x=i?(p.length-1)*s.x/2:0;for(let w=p.length;w--;){let A=p.charCodeAt(w),S=A<32||A>127?95:A-32,_=S%d,k=S/d|0;l.pos.x=_*h+u,l.pos.y=k*f+u,c.x=n.x+w*s.x-x|0,c.y=n.y+y*s.y|0,Ue(c,s,l,r,0,!1,void 0,a,!0,o)}})}};Ut=v(),nt=v(),ha=v(),Mt=v(),pa=0,Ii=!0,as=!1,mn="mouse",ma=6,os=!0,ke=0,gt=!X&&window.ontouchstart!==void 0;re=[[]],Lt=[],On=[],Zo=[],fs=new Gt,bt=[],Un=[],Fi=[],ci=[],Xt=new Map,zs=[],hs=!0;Gi="http://www.w3.org/2000/svg";Te=new AudioContext,Ss=44100;Vs=class{constructor(e,n,s=la,i=ua,r){var a;if(!(!at||X)){if(m(!e||At(e)||ee(e),"asset must be a file name or zzfx array"),m(n===void 0||O(n),"randomness must be a number"),m(n===void 0||n>=0&&n<=1,"randomness must be between 0 and 1"),m(O(s),"range must be a number"),m(O(i),"taper must be a number"),this.range=s,this.taper=i,this.randomness=n!=null?n:0,this.sampleRate=Ss,this.loadedPercent=0,this.onloadCallback=r,At(e)){let o=e.slice(),c=n!=null?n:.05,l=1;this.randomness=(a=o[l])!=null?a:c,o[l]=0,this.sampleChannels=[ho(...o)],this.loadedPercent=1,r==null||r(this)}else if(typeof e=="string"){let o=e;this.loadSound(o)}}}play(e,n=1,s=1,i=1,r=!1,a=!1){if(m(!e||D(e),"pos must be a vec2"),m(O(n),"volume must be a number"),m(O(s),"pitch must be a number"),m(O(i),"randomnessScale must be a number"),!at||X||!this.sampleChannels)return;let o;if(e){let u=this.range;if(u){let h=Je.distanceSquared(e);if(h>u*u)return;n*=Xe(h**.5,u,u*this.taper)}o=$n(e).x*2/$.width-1}let c=s+s*this.randomness*i*we(-1,1),l=new Bi(this,n,c,o,r,a);return Ye&&us&&e&&(st(e,.5,"#0ff",.5,!0),this.range&&(st(e,2*this.range,"#0ff",.5),st(e,2*this.range*this.taper,"#0ff",.5)),ts("vol "+n.toFixed(2)+" pitch "+c.toFixed(2),e,.5,"#0ff",.5)),l}playMusic(e=1,n=!0,s=!1){return this.play(void 0,e,1,0,n,s)}playNote(e=0,n,s){m(O(e),"semitoneOffset must be a number");let i=_l(e,1);return this.play(n,s,i,0)}getDuration(){var e,n;return((n=(e=this.sampleChannels)==null?void 0:e[0])==null?void 0:n.length)/this.sampleRate||0}isLoaded(){return this.loadedPercent===1}async loadSound(e){var c;let n=await fetch(e);if(!n.ok)throw new Error(`Failed to load sound from ${e}: ${n.status} ${n.statusText}`);let s=await n.arrayBuffer(),i=await Te.decodeAudioData(s),r=i.numberOfChannels,a=1e5,o=[];for(let l=0;lsetTimeout(x,0));let d=de(f+a,h);for(;f=0,"Sound volume must be positive or zero"),m(s>=0,"Sound rate must be positive or zero"),m(O(i),"Sound pan must be a number"),this.sound=e,this.volume=n,this.rate=s,this.pan=i,this.loop=r,this.pausedTime=0,this.startTime=void 0,this.gainNode=void 0,this.source=void 0,this.onendedCallback=o=>{o===this.source&&(this.source=void 0)},a||this.start()}start(e=0){m(e>=0,"Sound start offset must be positive or zero"),this.isPlaying()&&this.stop(),this.gainNode=Te.createGain(),this.source=Ta(this.sound.sampleChannels,this.volume,this.rate,this.pan,this.loop,this.sound.sampleRate,this.gainNode,e,this.onendedCallback),this.source?(this.startTime=Te.currentTime-e,this.pausedTime=void 0):(this.startTime=void 0,this.pausedTime=0)}setVolume(e){m(e>=0,"Sound volume must be positive or zero"),this.volume=e,this.gainNode&&(this.gainNode.gain.value=e)}stop(e=0){if(m(e>=0,"Sound fade time must be positive or zero"),this.isPlaying())if(e){let n=Te.currentTime,s=n+e;this.gainNode.gain.cancelScheduledValues(n),this.gainNode.gain.setValueAtTime(this.volume,n),this.gainNode.gain.linearRampToValueAtTime(0,s),this.source.stop(s)}else this.source.stop();this.pausedTime=0,this.source=void 0,this.startTime=void 0}pause(){this.isPaused()||(this.pausedTime=this.getCurrentTime(),this.source.stop(),this.source=void 0,this.startTime=void 0)}resume(){this.isPaused()&&this.start(this.pausedTime)}isPlaying(){return!!this.source}isPaused(){return!this.isPlaying()}getCurrentTime(){if(!this.isPlaying())return this.pausedTime;let e=this.getDuration();return e?yt(Te.currentTime-this.startTime,e):0}getDuration(){return this.rate?this.sound.getDuration()/this.rate:0}getSource(){return this.source}};Sn=[];Nn=class{constructor(e,n=0,s=!1,i=new De){this.tile=e,this.direction=n,this.mirror=s,this.color=i.copy()}clear(){this.tile=this.direction=0,this.mirror=!1,this.color=new De}},Ji=class extends en{constructor(e,n,s=0,i=0,r=v(512),a=!0){var o;m(D(r),"canvasSize must be a Vector2"),super(e,n,void 0,s,te,i),this.canvas=X?void 0:new OffscreenCanvas(r.x,r.y),this.context=(o=this.canvas)==null?void 0:o.getContext("2d"),this.textureInfo=new tn(this.canvas,a),this.mass=0}destroy(){this.destroyed||(this.textureInfo.destroyWebGLTexture(),super.destroy())}render(){this.draw(this.pos,this.size,this.color,this.angle,this.mirror,this.additiveColor)}draw(e,n,s=te,i=0,r=!1,a,o=!1,c){let l=new Jt().setFullImage(this.textureInfo),u=this.hasWebGL();Ue(e,n,l,s,i,r,a,u,o,c)}updateWebGL(){this.textureInfo.createWebGLTexture()}hasWebGL(){return H&&this.textureInfo.hasWebGL()}},Ws=class extends Ji{constructor(e,n,s=ii(),i=0,r=!0){let a=s?n.multiply(s.size):n;if(super(e,n,0,i,a,r),this.tileInfo=void 0,this.data=[],this.isUsingWebGL=!1,X){this.render=()=>{},this.redraw=()=>{},this.redrawStart=()=>{},this.redrawEnd=()=>{},this.drawTileData=()=>{},this.redrawTileData=()=>{},this.drawLayerTile=()=>{},this.drawLayerRect=()=>{},this.drawTile=()=>{},this.drawRect=()=>{},this.clearLayerRect=()=>{};return}s&&(this.tileInfo=s.frame(0),this.tileInfo.bleed=0);for(let o=this.size.area();o--;)this.data.push(new Nn)}setData(e,n,s=!1){if(e=e.floor(),m(D(e),"layerPos must be a Vector2"),m(n instanceof Nn,"data must be a TileLayerData"),!e.arrayCheck(this.size)||(this.data[(e.y|0)*this.size.x+(e.x|0)]=n,!s))return;Be===this.context?this.drawTileData(e):this.redrawTileData(e)}clearData(e,n=!1){this.setData(e,new Nn,n)}getData(e){return m(D(e),"layerPos must be a Vector2"),e.arrayCheck(this.size)?this.data[(e.y|0)*this.size.x+(e.x|0)]:void 0}update(){!H&&this.isUsingWebGL&&(this.isUsingWebGL=!1,this.redraw())}render(){m(Be!==this.context,"must call redrawEnd() after drawing tiles!");let e=this.drawSize||this.size,n=this.pos.add(e.scale(.5));this.draw(n,this.size,this.color,this.angle,this.mirror,this.additiveColor)}onRedraw(){}redraw(){this.redrawStart(!0);for(let e=this.size.x;e--;)for(let n=this.size.y;n--;)this.drawTileData(v(e,n),!1);this.isUsingWebGL&&Ne(),this.onRedraw(),this.redrawEnd()}redrawStart(e=!1){var s,i;if(!this.context)return;m(Be!==this.context),this.savedRenderSettings=[Be,z,Je,ie,gn],Be=this.context;let n=(i=(s=this.tileInfo)==null?void 0:s.size)!=null?i:v(1);z=this.size.multiply(n),gn=Ct,Je=this.size.multiply(n).scale(.5),ie=1,this.isUsingWebGL=this.hasWebGL(),this.isUsingWebGL?Ps(this.textureInfo.glTexture,e):(this.context.imageSmoothingEnabled=!zn,e&&(this.canvas.width=z.x,this.canvas.height=z.y))}redrawEnd(){this.context&&(m(Be===this.context),this.isUsingWebGL&&Ps(),[Be,z,Je,ie,gn]=this.savedRenderSettings)}drawTileData(e,n=!0){var o,c;if(!this.context)return;m(Be===this.context,"must call redrawStart() before drawing tiles");let s=(c=(o=this.tileInfo)==null?void 0:o.size)!=null?c:v(1),i=e.multiply(s);n&&this.clearLayerRect(i,s);let r=this.getData(e);if(!r||!r.tile)return;let a=this.tileInfo&&this.tileInfo.tile(r.tile);this.drawLayerTile(i,s,a,r.color,r.direction*oe/2,r.mirror)}redrawTileData(e,n=!0){this.context&&(m(Be!==this.context,"redrawStart() should not be active when calling redrawTileData(), instead use drawTileData()"),this.redrawStart(),this.drawTileData(e,n),this.redrawEnd())}drawLayerTile(e,n=v(1),s,i=te,r=0,a,o){let c=e.add(n.scale(.5));Ue(c,n,s,i,r,a,o,this.isUsingWebGL)}drawLayerRect(e,n,s,i=0){this.drawLayerTile(e,n,void 0,s,i)}drawTile(e,n=v(1),s,i=new De,r=0,a=!1){e=e.subtract(this.pos).multiply(this.tileInfo.size),n=n.multiply(this.tileInfo.size),e.y=this.canvas.height-e.y;let o=z;z=v(this.canvas.width,this.canvas.height);let c=this.hasWebGL();c&&Ps(this.textureInfo.glTexture);let l=c?void 0:this.context;Ue(e,n,s,i,r,a,void 0,c,!0,l),c&&Ps(),z=o}drawRect(e,n,s,i){this.drawTile(e,n,void 0,s,i)}clearLayerRect(e,n){m(Be===this.context,"must call redrawStart() before clearing tiles");let s=e.x,i=this.canvas.height-e.y-n.y;this.hasWebGL()?Gl(s,i,n.x,n.y):this.context.clearRect(s,i,n.x,n.y)}},qs=class extends Ws{constructor(e,n,s=ii(),i=0,r=!0){super(e,n.floor(),s,i,r),this.collisionData=[],this.initCollision(this.size),Sn.push(this),this.isSolid=!0}destroy(){if(this.destroyed)return;let e=Sn.indexOf(this);m(e>=0,"tile collision layer not found in array"),e>=0&&Sn.splice(e,1),super.destroy()}initCollision(e){m(D(e),"size must be a Vector2"),this.size=e.floor(),this.collisionData=[],this.collisionData.length=e.area(),this.collisionData.fill(0)}setCollisionData(e,n=1){m(D(e),"layerPos must be a Vector2");let s=(e.y|0)*this.size.x+(e.x|0);e.arrayCheck(this.size)&&(this.collisionData[s]=n)}clearCollisionData(e){this.setCollisionData(e,0)}getCollisionData(e){m(D(e),"layerPos must be a Vector2");let n=(e.y|0)*this.size.x+(e.x|0);return e.arrayCheck(this.size)?this.collisionData[n]:0}collisionTest(e,n=new ge,s){m(D(e)&&D(n),"pos and size must be Vector2s"),m(!s||typeof s=="function"||s instanceof en,"callbackObject must be a function or EngineObject");let i=s?typeof s=="function"?(f,d)=>s(f,d):(f,d)=>s.collideWithTile(f,d):()=>!0,r=e.x-this.pos.x,a=e.y-this.pos.y;if(r+n.x/2<0||r-n.x/2>this.size.x||a+n.y/2<0||a-n.y/2>this.size.y)return!1;let o=le(r-n.x/2|0,0),c=le(a-n.y/2|0,0),l=de(le(r+n.x/2,o+1),this.size.x),u=de(le(a+n.y/2,c+1),this.size.y),h=new ge;for(let f=c;fs(l,u):(l,u)=>s.collideWithTile(l,u):l=>l>0,a=l=>{let u=this.getCollisionData(o.set(l.x-this.pos.x,l.y-this.pos.y));return u&&r(u,l)},o=new ge,c=il(e,n,a,i);if(Tt&&c){let l=c.floor().add(v(.5));Ce(l,v(1),"#f008"),Dt(e,n,"#00f",.02),Dt(e,c,"#f00",.02),qr(c,"#0f0"),i&&Dt(c,c.add(i),"#ff0",.02)}return c}},ur=class extends en{constructor(e,n,s=0,i=0,r=100,a=oe,o,c=te,l=te,u=wn,h=wn,f=.5,d=.1,p=1,y=.1,x=.05,w=1,A=1,S=0,_=oe,k=.1,C=.2,L=!1,N=!1,ae=!0,Z=N?1e9:0,T=!1){super(e,v(),o,n,void 0,Z),this.emitCircle=typeof s=="number",this.emitSize=typeof s=="number"?v(s):s.copy(),this.emitTime=i,this.emitRate=r,this.emitConeAngle=a,this.colorStartA=c.copy(),this.colorStartB=l.copy(),this.colorEndA=u.copy(),this.colorEndB=h.copy(),this.randomColorLinear=ae,this.particleTime=f,this.sizeStart=d,this.sizeEnd=p,this.speed=y,this.angleSpeed=x,this.damping=w,this.angleDamping=A,this.gravityScale=S,this.particleConeAngle=_,this.fadeRate=k,this.randomness=C,this.collideTiles=L,this.additive=N,this.localSpace=T,this.trailScale=0,this.particleCreateCallback=void 0,this.particleDestroyCallback=void 0,this.particleCollideCallback=void 0,this.velocityInheritance=0,this.emitTimeBuffer=0,this.particles=[],this.previousAngle=this.angle,this.previousPos=this.pos.copy()}update(){if(m(this.angleDamping>=0&&this.angleDamping<=1),m(this.damping>=0&&this.damping<=1),this.velocityInheritance){let s=this.velocityInheritance;this.velocity.x=s*(this.pos.x-this.previousPos.x),this.velocity.y=s*(this.pos.y-this.previousPos.y),this.angleVelocity=s*(this.angle-this.previousAngle),this.previousAngle=this.angle,this.previousPos.x=this.pos.x,this.previousPos.y=this.pos.y}if(this.isActive()){if(this.emitRate&&Ri){let s=1/this.emitRate/Ri;for(this.emitTimeBuffer+=Vr;this.emitTimeBuffer>0;this.emitTimeBuffer-=s)this.emitParticle()}}else this.particles.length===0&&this.destroy(!0);let e=this.particles,n=0;for(let s=0;sA+A*we(s,-s),r=i(this.particleTime),a=i(this.sizeStart),o=i(this.sizeEnd),c=i(this.speed),l=i(this.angleSpeed)*rl(),u=we(this.emitConeAngle,-this.emitConeAngle),h=ir(this.colorStartA,this.colorStartB,this.randomColorLinear),f=ir(this.colorEndA,this.colorEndB,this.randomColorLinear),d=this.localSpace?u:this.angle+u,p=v(c*pe(d),c*be(d)),y=l;!this.localSpace&&this.velocityInheritance>0&&(p.x+=this.velocity.x,p.y+=this.velocity.y,y+=this.angleVelocity);let x=new Ni(this,e,n,h,f,r,a,o,p,y);return this.particles.push(x),(w=this.particleCreateCallback)==null||w.call(this,x),x}updatePhysics(){}render(){for(let e of this.particles)e.render()}isActive(){return!this.emitTime||this.getAliveTime()0&&(this.destroyed=!1,this.emitTime=-1))}},wh=new ge,Ni=class{constructor(e,n,s,i,r,a,o,c,l=v(),u=0){this.emitter=e,this.pos=n,this.angle=s,this.size=v(o),this.color=i.copy(),this.colorStart=i,this.colorEnd=r,this.lifeTime=a,this.sizeStart=o,this.sizeEnd=c,this.velocity=l,this.angleVelocity=u,this.spawnTime=dt,this.mirror=ol(),this.groundObject=void 0,this.destroyed=!1,this.tileInfo=e.tileInfo}update(){let e=this.emitter,n=e.damping,s=e.angleDamping,i=e.restitution,r=e.friction,a=e.gravityScale,o=e.collideTiles,c=e.particleCollideCallback;if(this.lifeTime>0&&dt-this.spawnTime>this.lifeTime){this.destroy();return}let l=this.pos.copy();if(this.velocity.x*=n,this.velocity.y*=n,this.pos.x+=this.velocity.x+=it.x*a,this.pos.y+=this.velocity.y+=it.y*a,this.angle+=this.angleVelocity*=s,!lo||!o)return;let u=this.velocity.lengthSquared();if(u>$t*$t){let f=$t/u**.5;this.velocity.x*=f,this.velocity.y*=f}this.groundObject=void 0;let h=c?f=>{let d=ji(f);return d&&c(this,d,f)}:f=>ji(f)>0;if(h(this.pos)){let f=hn(this.pos);if(!h(l)){let d=h(v(this.pos.x,l.y)),p=h(v(l.x,this.pos.y)),y=le(i,f.restitution),x=le(r,f.friction);d&&(this.pos.x=l.x,this.velocity.x*=-y,this.velocity.y*=x),(p||!d)&&((this.velocity.y<0&&it.y<0||this.velocity.y>0&&it.y>0)&&(this.groundObject=f),this.pos.y=l.y,this.velocity.y*=-y,this.velocity.x*=x),wt&&Ce(this.pos,this.size,"#f00")}}}destroy(){let e=this.emitter.particleDestroyCallback,n=this.colorEnd;this.color.set(n.r,n.g,n.b,n.a),this.size.set(this.sizeEnd,this.sizeEnd),this.destroyed=!0,e==null||e(this)}render(){let e=this.emitter,n=e.localSpace,s=e.additive,i=e.trailScale,r=e.fadeRate/2,a=this.lifeTime>0?de((dt-this.spawnTime)/this.lifeTime,1):1,o=1-a,c=o*this.sizeStart+a*this.sizeEnd,l=v(c),u=a1-r?(1-a)/r:1;this.color.r=o*this.colorStart.r+a*this.colorEnd.r,this.color.g=o*this.colorStart.g+a*this.colorEnd.g,this.color.b=o*this.colorStart.b+a*this.colorEnd.b,this.color.a=(o*this.colorStart.a+a*this.colorEnd.a)*u;let h=wh.set(this.pos.x,this.pos.y),f=this.angle;if(n){let d=e.angle,p=be(-d),y=pe(-d);h.set(e.pos.x+h.x*p-h.y*y,e.pos.y+h.x*y+h.y*p),f+=d}if(s&&js(),i){let d=n?this.velocity.rotate(e.angle):this.velocity,p=d.length();if(p){let y=p*i;l.y=le(l.x,y),f=Hr(d.x,d.y),Ue(h,l,this.tileInfo,this.color,f,this.mirror)}}else Ue(h,l,this.tileInfo,this.color,f,this.mirror);s&&js(!1),Bn&&Ce(h,l,"#f005",0,f)}},Aa=!0,pr=!0,Wi=5e5,Ca=11,Rl=Ca*4,Th=Wi/Rl|0,po=3,Pl=po*4,ls=Wi/Pl|0;Ln=!1,qi=5,rs=.5,Hi=v(640,80),Oa=!1,Xs={},wi=[];Yi=class{constructor(e,n,s="",i="\u{1F3C6}",r){m(e>=0&&!Xs[e]),this.id=e,this.name=n,this.description=s,this.icon=i,this.unlocked=!1,this.image=void 0,r&&((this.image=new Image).src=r),Xs[e]=this}unlock(){Oa||this.unlocked||(m($i,"save name must be set"),this.unlocked=!0,Da(),wi.push(this))}render(e=0){let n=Se,s=de(Hi.x,$.width),i=Hi.y,r=$.width-s,a=-i*e,o=Ht(0,0,.9);n.save(),n.beginPath(),n.fillStyle=o.toString(),n.strokeStyle=me.toString(),n.lineWidth=3,n.rect(r,a,s,i),n.fill(),n.stroke(),n.clip();let c=v(.1,.05).scale(i),l=i-2*c.x;this.renderIcon(v(r+c.x+l/2,a+i/2),l);let u=i*.5,h=i*.3,f=v(r+l+2*c.x,a+c.y*2+u/2),d=s-l-3*c.x;xn(this.name,f,u,me,0,void 0,"left",void 0,void 0,d),f.y=a+i-c.y*2-h/2,xn(this.description,f,h,me,0,void 0,"left",void 0,void 0,d),n.restore()}renderIcon(e,n){this.image?Se.drawImage(this.image,e.x-n/2,e.y-n/2,n,n):xn(this.icon,e,n*.7,me)}};gr=class extends Yi{constructor(e,n,s,i,r){super(e,n,s,i,r)}unlock(){super.unlock(),Ks&&Ks.unlockMedal(this.id)}},br=class{constructor(e,n,s){var c,l,u;m(!Ks,"there can only be one newgrounds object"),m(!n||s,"must provide cryptojs if there is a cipher"),Ks=this,this.app_id=e,this.cipher=n,this.cryptoJS=s,this.host=location?location.hostname:"";let i=new URL(location.href);if(this.session_id=i.searchParams.get("ngio_session_id"),!this.session_id)return;let r=this.call("Medal.getList");if(!r||!r.result||r.result.error){Ln&&_e("Newgrounds session unavailable; skipping plugin init"),this.medals=[],this.scoreboards=[];return}this.medals=((c=r.result.data)==null?void 0:c.medals)||[],Ln&&_e(this.medals);for(let h of this.medals){let f=Xs[h.id];f&&(f.image=new Image,f.image.src=h.icon,f.name=h.name,f.description=h.description,f.unlocked=h.unlocked,f.difficulty=h.difficulty,f.value=h.value,f.value&&(f.description=f.description+` (${f.value})`))}let a=this.call("ScoreBoard.getBoards");this.scoreboards=((u=(l=a==null?void 0:a.result)==null?void 0:l.data)==null?void 0:u.scoreboards)||[],Ln&&_e(this.scoreboards);let o=60*1e3;setInterval(()=>this.call("Gateway.ping",0,!0),o)}unlockMedal(e){return this.call("Medal.unlock",{id:e},!0)}postScore(e,n){return this.call("ScoreBoard.postScore",{id:e,value:n},!0)}getScores(e,n,s=0,i=0,r=10){return this.call("ScoreBoard.getScores",{id:e,user:n,social:s,skip:i,limit:r})}logView(){return this.call("App.logView",{host:this.host},!0)}call(e,n,s=!1){let i={component:e,parameters:n};if(this.cipher){let l=this.cryptoJS,u=l.enc.Base64.parse(this.cipher),h=l.lib.WordArray.random(16),f=l.AES.encrypt(JSON.stringify(i),u,{iv:h});i.secure=l.enc.Base64.stringify(h.concat(f.ciphertext)),i.parameters=0}let r={app_id:this.app_id,session_id:this.session_id,call:i},a=new FormData;a.append("input",JSON.stringify(r));let o=new XMLHttpRequest;o.open("POST","https://newgrounds.io/gateway_v3.php",!Ln&&s);try{o.send(a)}catch(l){Ln&&_e("newgrounds call failed",l);return}return Ln&&_e(o.responseText),o.responseText&&JSON.parse(o.responseText)}},xr=class{constructor(e,n=!1,s=!1){m(!qe,"Post process already initialized"),m(!(n&&s),"Post process cannot both include main canvas and use feedback texture"),qe=this,e||(e="void mainImage(out vec4 c,vec2 p){c=texture(iChannel0,p/iResolution.xy);}"),this.shader=void 0,this.texture=void 0,this.vao=void 0,i(),Wn(void 0,o,r,a);function i(){if(X)return;if(!H){console.warn("PostProcessPlugin: WebGL not enabled!");return}qe.texture=mo(),qe.shader=ys(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D iChannel0;uniform vec3 iResolution;uniform float iTime;out vec4 c;
+`+e+`
+void main(){mainImage(c,gl_FragCoord.xy);c.a=1.;}`),qe.vao=g.createVertexArray(),g.bindVertexArray(qe.vao),g.bindBuffer(g.ARRAY_BUFFER,cs);let c=8,l=g.getAttribLocation(qe.shader,"p");g.enableVertexAttribArray(l),g.vertexAttribPointer(l,2,g.FLOAT,!1,c,0)}function r(){qe.shader=void 0,qe.texture=void 0,_e("PostProcessPlugin: WebGL context lost")}function a(){i(),_e("PostProcessPlugin: WebGL context restored")}function o(){if(X||!H)return;Ne(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.useProgram(qe.shader),g.bindVertexArray(qe.vao),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!0),g.disable(g.BLEND),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,qe.texture),n?(Kt.width=z.x,Kt.height=z.y,Ra(pn),pn.drawImage($,0,0),$.width|=0,g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,Kt)):s||g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,fe);let c=l=>g.getUniformLocation(qe.shader,l);g.uniform1i(c("iChannel0"),0),g.uniform1f(c("iTime"),dt),g.uniform3f(c("iResolution"),$.width,$.height,1),g.drawArrays(g.TRIANGLE_STRIP,0,4),s&&g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,fe),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!1),$s(!0)}}},Sr=class{constructor(e,n){m(!se,"LightSystemPlugin already initialized"),m(!qe,"LightSystemPlugin must be created before PostProcessPlugin"),se=this,this.enabled=!0,this.ambientColor=(n||me).copy(),this.textureSize=e?e.copy():void 0,this.texture=void 0,this.lightShader=void 0,this.compositeShader=void 0,this.lightVAO=void 0,this.compositeVAO=void 0,s(),Wn(void 0,i,r,a);function s(){if(X)return;if(!H){console.warn("LightSystemPlugin: WebGL not enabled!");return}se.textureSize||(se.textureSize=z.copy()),se.texture=g.createTexture(),g.bindTexture(g.TEXTURE_2D,se.texture),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,se.textureSize.x,se.textureSize.y,0,g.RGBA,g.UNSIGNED_BYTE,null),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,g.CLAMP_TO_EDGE),se.lightShader=ys(`#version 300 es
+precision highp float;uniform mat4 m;uniform vec2 lightPos;uniform float radius;in vec2 g;out vec2 vWorldPos;void main(){vec2 worldP=lightPos+(g-.5)*2.*radius;gl_Position=m*vec4(worldP,1,1);vWorldPos=worldP;}`,`#version 300 es
+precision highp float;uniform vec2 lightPos;uniform float radius;uniform float fadeRange;uniform vec4 color;in vec2 vWorldPos;out vec4 c;void main(){float dist=distance(vWorldPos,lightPos);float t=clamp((radius-dist)/max(fadeRange,1e-6),0.,1.);c=vec4(color.rgb*t*color.a,1.);}`),se.compositeShader=ys(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D s;uniform vec3 iResolution;out vec4 c;void main(){vec2 uv=gl_FragCoord.xy/iResolution.xy;c=vec4(texture(s,uv).rgb,1.);}`),se.lightVAO=g.createVertexArray(),g.bindVertexArray(se.lightVAO),g.bindBuffer(g.ARRAY_BUFFER,cs);let o=g.getAttribLocation(se.lightShader,"g");g.enableVertexAttribArray(o),g.vertexAttribPointer(o,2,g.FLOAT,!1,8,0),se.compositeVAO=g.createVertexArray(),g.bindVertexArray(se.compositeVAO),g.bindBuffer(g.ARRAY_BUFFER,cs);let c=g.getAttribLocation(se.compositeShader,"p");g.enableVertexAttribArray(c),g.vertexAttribPointer(c,2,g.FLOAT,!1,8,0)}function i(){if(X||!H||!se.enabled||!se.texture)return;Ne();let o=Xn,c=se.ambientColor;g.bindFramebuffer(g.FRAMEBUFFER,ka),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,se.texture,0),g.viewport(0,0,se.textureSize.x,se.textureSize.y),g.clearColor(c.r,c.g,c.b,c.a),g.clear(g.COLOR_BUFFER_BIT),js(),g.enable(g.BLEND),g.blendFunc(g.ONE,g.ONE);for(let u of Ee)u.destroyed||u.renderLight();Ne(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,z.x,z.y),g.useProgram(se.compositeShader),g.bindVertexArray(se.compositeVAO),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,se.texture);let l=se.compositeShader;g.uniform1i(g.getUniformLocation(l,"s"),0),g.uniform3f(g.getUniformLocation(l,"iResolution"),$.width,$.height,1),g.blendFunc(g.DST_COLOR,g.ZERO),g.drawArrays(g.TRIANGLE_STRIP,0,4),ft&&g.bindTexture(g.TEXTURE_2D,ft),js(o),$s(!0)}function r(){se.texture=void 0,se.lightShader=void 0,se.compositeShader=void 0,se.lightVAO=void 0,se.compositeVAO=void 0,_e("LightSystemPlugin: WebGL context lost")}function a(){s(),_e("LightSystemPlugin: WebGL context restored")}}drawLight(e){if(X||!H||!this.lightShader)return;Ne(),g.useProgram(this.lightShader),g.bindVertexArray(this.lightVAO);let n=v(2*ie).divide(z),s=Je.rotate(-ue),i=v(-1).subtract(s.multiply(n)),r=be(ue),a=pe(ue),o=[n.x*r,n.y*a,0,0,-n.x*a,n.y*r,0,0,1,1,1,0,i.x,i.y,0,1],c=this.lightShader;g.uniformMatrix4fv(g.getUniformLocation(c,"m"),!1,o),g.uniform2f(g.getUniformLocation(c,"lightPos"),e.pos.x,e.pos.y),g.uniform1f(g.getUniformLocation(c,"radius"),e.radius),g.uniform1f(g.getUniformLocation(c,"fadeRange"),e.fadeRange);let l=e.color;g.uniform4f(g.getUniformLocation(c,"color"),l.r,l.g,l.b,l.a),g.drawArrays(g.TRIANGLE_STRIP,0,4),$s(!0)}},vr=class extends en{constructor(e,n,s,i){super(e,v(1),void 0,0,s),m(O(n)&&n>=0,"Light radius must be a non-negative number"),m(i===void 0||O(i)&&i>=0,"Light fadeRange must be a non-negative number when provided"),this.radius=n,this.fadeRange=i===void 0?n:i}render(){}renderLight(){se&&se.drawLight(this)}},wr=class extends Vs{constructor(e){super(void 0),!(!at||X)&&(this.randomness=0,this.sampleChannels=Bl(...e),this.sampleRate=Ss)}playMusic(e=1,n=!0){return super.play(void 0,e,1,0,n)}};Ia=0;Tr=class{constructor(e=Se){m(!E,"UI system already initialized"),E=this,this.activateOnPress=!1,this.defaultColor=te,this.defaultLineColor=me,this.defaultTextColor=me,this.defaultButtonColor=Ht(0,0,.7),this.defaultHoverColor=Ht(0,0,.9),this.defaultDisabledColor=Ht(0,0,.3),this.defaultGradientColor=void 0,this.defaultLineWidth=4,this.defaultCornerRadius=0,this.defaultTextFitScale=.8,this.defaultFont=ei,this.defaultSoundPress=void 0,this.defaultSoundRelease=void 0,this.defaultSoundClick=void 0,this.defaultShadowColor=Ct,this.defaultShadowBlur=5,this.defaultShadowOffset=v(5),this.nativeHeight=0,this.navigationObject=void 0,this.navigationTimer=new Gt(void 0,!0),this.navigationDelay=.2,this.navigationDirection=1,this.navigationMode=!1,this.uiObjects=[],this.uiContext=e,this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.confirmDialog=void 0,this._keyInputObject=void 0,this._onKeyDown=r=>{var a;return(a=this._keyInputObject)==null?void 0:a.onKeyDown(r)},Wn(s,i);function n(r){let a,o;r.parent?(a=r.parent.nativePos,o=r.parent.size):(a=E.screenToNative(z.scale(.5)),o=E.nativeHeight?v(z.x*E.nativeHeight/z.y,E.nativeHeight):z);let c=r.anchor;r.nativePos=a.add(o.multiply(c).scale(.5)).subtract(r.size.multiply(c).scale(.5)).add(r.localPos)}function s(){E.activeObject&&!E.activeObject.visible&&(E.activeObject=void 0),E.lastHoverObject=E.hoverObject,E.hoverObject=void 0,Js(0)&&(E.navigationMode=!1,E.navigationObject=void 0),E.keyInputObject&&(E.activeObject=E.keyInputObject,E.hoverObject=E.keyInputObject,E.navigationMode=!1,E.navigationObject=void 0);let r=E.getNavigableObjects();if(!r.length)E.navigationObject=void 0;else if(!E.keyInputObject){if(r.includes(E.navigationObject)||(E.navigationObject=void 0),gt||E.navigationMode&&!E.navigationObject&&(E.navigationObject=r.find(o=>o.navigationAutoSelect)),!E.navigationTimer.active()){let o=mt(E.getNavigationDirection());if(o){let c;if(E.navigationObject){let l=r.indexOf(E.navigationObject),u=yt(l+o,r.length);c=r[u]}else if(c=r.find(l=>l.navigationAutoSelect),!c){let l=o>0?0:r.length-1;c=r[l]}E.navigationObject!==c&&(E.navigationMode=!0,E.hoverObject=void 0,E.navigationObject=c,E.navigationTimer.set(E.navigationDelay),c.soundPress&&c.soundPress.play())}}E.navigationObject&&E.getNavigationWasPressed()&&E.navigationObject.navigatePressed()}for(let o=E.uiObjects.length;o--;){let c=E.uiObjects[o];c.parent||a(c)}E.uiObjects=E.uiObjects.filter(o=>!o.destroyed);function a(o){if(!(o.destroyed||!o.visible)){n(o);for(let c=o.children.length;c--;){let l=o.children[c];l&&a(l)}o.destroyed||o.update()}}}function i(){let r=E.uiContext;if(r.save(),E.nativeHeight){let o=z.y/E.nativeHeight;r.translate(-o*z.x/2,0),r.scale(o,o),r.translate(z.x/2/o,0)}function a(o){if(o.visible){n(o),o.render();for(let c of o.children)a(c)}}if(E.uiObjects.forEach(o=>o.parent||a(o)),Ia>0){let o=function(c,l=!0){l&&(l=!!c.visible),n(c),c.renderDebug(l);for(let u of c.children)o(u,l)};E.uiObjects.forEach(c=>c.parent||o(c))}r.restore()}}drawRect(e,n,s=te,i=0,r=me,a=0,o,c=me,l=0,u=v()){m(D(e),"pos must be a vec2"),m(D(n),"size must be a vec2"),m(Q(s),"color must be a color"),m(O(i),"lineWidth must be a number"),m(Q(r),"lineColor must be a color"),m(O(a),"cornerRadius must be a number");let h=E.uiContext;if(o){let f=h.createLinearGradient(e.x,e.y-n.y/2,e.x,e.y+n.y/2),d=s.toString();f.addColorStop(0,d),f.addColorStop(.5,o.toString()),f.addColorStop(1,d),h.fillStyle=f}else h.fillStyle=s.toString();(l||u.x||u.y)&&c.a>0&&(h.shadowColor=c.toString(),h.shadowBlur=l,h.shadowOffsetX=u.x,h.shadowOffsetY=u.y),h.beginPath(),a&&h.roundRect?h.roundRect(e.x-n.x/2,e.y-n.y/2,n.x,n.y,a):h.rect(e.x-n.x/2,e.y-n.y/2,n.x,n.y),h.fill(),h.shadowColor="#0000",i&&r.a>0&&(h.strokeStyle=r.toString(),h.lineWidth=i,h.stroke())}drawLine(e,n,s=E.defaultLineWidth,i=E.defaultLineColor){m(D(e),"posA must be a vec2"),m(D(n),"posB must be a vec2"),m(O(s),"lineWidth must be a number"),m(Q(i),"lineColor must be a color");let r=E.uiContext;r.strokeStyle=i.toString(),r.lineWidth=s,r.beginPath(),r.lineTo(e.x,e.y),r.lineTo(n.x,n.y),r.stroke()}drawTile(e,n,s,i=E.defaultColor,r=0,a=!1,o=me,c=0,l=v()){let u=E.uiContext;(c||l.x||l.y)&&o.a>0&&(u.shadowColor=o.toString(),u.shadowBlur=c,u.shadowOffsetX=l.x,u.shadowOffsetY=l.y),Ue(e,n,s,i,r,a,Ct,!1,!0,u),u.shadowColor="#0000"}drawText(e,n,s,i=E.defaultColor,r=E.defaultLineWidth,a=E.defaultLineColor,o="center",c=E.defaultFont,l="",u=!0,h=void 0,f=me,d=0,p=v()){let y=E.uiContext;f.a>0&&(h&&xn(e,n.add(h),s.y,f,r,a,o,c,l,u?s.x:void 0,0,y),(d||p.x||p.y)&&(y.shadowColor=f.toString(),y.shadowBlur=d,y.shadowOffsetX=p.x,y.shadowOffsetY=p.y)),xn(e,n,s.y,i,r,a,o,c,l,u?s.x:void 0,0,y),y.shadowColor="#0000"}setupDragAndDrop(e,n,s,i){if(this._dragListeners)for(let[a,o]of this._dragListeners)document.removeEventListener(a,o);this._dragListeners=[];let r=(a,o)=>{let c=l=>{l.preventDefault(),a&&a(l)};document.addEventListener(o,c),this._dragListeners.push([o,c])};r(e,"drop"),r(n,"dragenter"),r(s,"dragleave"),r(i,"dragover")}screenToNative(e){if(!E.nativeHeight)return e;let n=z.y/E.nativeHeight,s=1/n,i=e.copy();return i.x+=n*z.x/2,i.x*=s,i.y*=s,i.x-=s*z.x/2,i}get keyInputObject(){return this._keyInputObject}set keyInputObject(e){let n=!!this._keyInputObject;this._keyInputObject=e,!n&&e?document.addEventListener("keydown",this._onKeyDown):n&&!e&&document.removeEventListener("keydown",this._onKeyDown)}destroyObjects(){for(let e of this.uiObjects)e.parent||e.destroy();this.uiObjects=this.uiObjects.filter(e=>!e.destroyed),this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.keyInputObject=void 0}getNavigableObjects(){function e(s){if(!(!s.visible||s.disabled)){s.isInteractive()&&s.navigationIndex!==void 0&&n.push(s);for(let i=s.children.length;i--;)e(s.children[i])}}let n=[];for(let s=E.uiObjects.length;s--;){let i=E.uiObjects[s];E.confirmDialog&&i!==E.confirmDialog||i.parent||e(i)}return n.sort((s,i)=>s.navigationIndex-i.navigationIndex),n}getNavigationDirection(){let e=E.navigationDirection===1,n=E.navigationDirection===2;if(as){let l=Ns(0,ke),u=cr(ke);return n?-(l.y||u.y)||l.x||u.x:e?-(l.y||u.y):l.x||u.x}let s="ArrowUp",i="ArrowDown",r="ArrowLeft",a="ArrowRight";if(n)return ze(s)||ze(r)?-1:ze(i)||ze(a)?1:0;let o=e?s:r,c=e?i:a;return ze(o)?-1:ze(c)?1:0}getNavigationOtherDirection(){if(E.navigationDirection===2)return 0;let e=E.navigationDirection===1;if(as){let i=Ns(0,ke),r=cr(ke);return e?i.x||r.x:i.y||r.y}let n=e?"ArrowLeft":"ArrowUp",s=e?"ArrowRight":"ArrowDown";return ze(n)?-1:ze(s)?1:0}getNavigationWasPressed(){return as?ba(0,ke):He("Space")||He("Enter")}showConfirmDialog(e="Are you sure?",n,s,i=v(500,250),r="Escape"){m(!E.confirmDialog);let a=E.navigationDirection;E.navigationDirection=2;let o=new xt(v(),i);E.confirmDialog=o,o.onRender=()=>{let d=Ht(0,0,0,.7);E.drawRect(v(),v(1e9),d)},o.onUpdate=()=>{He(r)&&f()},o.isMouseOverlapping=()=>!0;let c=50,l=new Xi(v(0,-50),v(i.x-c,70),e);o.addChild(l);let u=new Qs(v(-80,50),v(120,70),"Yes");u.textHeight=40,u.navigationIndex=1,u.hoverColor=Ht(0,1,.5),u.onClick=()=>{f(),n&&n()},o.addChild(u);let h=new Qs(v(80,50),v(120,70),"No");h.textHeight=40,h.navigationIndex=2,h.navigationAutoSelect=!0,h.onClick=()=>{f(),s&&s()},o.addChild(h);function f(){m(E.confirmDialog===o),o.destroy(),E.confirmDialog=void 0,E.navigationDirection=a,ai()}}},xt=class{constructor(e=v(),n=v()){var s,i;m(D(e),"ui object pos must be a vec2"),m(D(n),"ui object size must be a vec2"),this.localPos=e.copy(),this.nativePos=e.copy(),this.size=n.copy(),this.color=E.defaultColor.copy(),this.activeColor=void 0,this.text=void 0,this.disabledColor=E.defaultDisabledColor.copy(),this.disabled=!1,this.textColor=E.defaultTextColor.copy(),this.hoverColor=E.defaultHoverColor.copy(),this.lineColor=E.defaultLineColor.copy(),this.gradientColor=E.defaultGradientColor?E.defaultGradientColor.copy():void 0,this.lineWidth=E.defaultLineWidth,this.cornerRadius=E.defaultCornerRadius,this.font=E.defaultFont,this.fontStyle=void 0,this.textWidth=void 0,this.textHeight=void 0,this.textFitScale=E.defaultTextFitScale,this.textShadow=void 0,this.textLineColor=E.defaultLineColor.copy(),this.textLineWidth=0,this.visible=!0,this.children=[],this.parent=void 0,this.extraTouchSize=0,this.soundPress=E.defaultSoundPress,this.soundRelease=E.defaultSoundRelease,this.soundClick=E.defaultSoundClick,this.interactive=!1,this.dragActivate=!1,this.canBeHover=!0,this.shadowColor=(s=E.defaultShadowColor)==null?void 0:s.copy(),this.shadowBlur=E.defaultShadowBlur,this.shadowOffset=(i=E.defaultShadowOffset)==null?void 0:i.copy(),this.navigationIndex=void 0,this.navigationAutoSelect=!1,this.anchor=v(),E.uiObjects.push(this)}addChild(e){return m(!e.parent&&!this.children.includes(e)),this.children.push(e),e.parent=this,e}removeChild(e){m(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}destroy(){var e;if(!this.destroyed){E.activeObject===this&&(E.activeObject=void 0),E.hoverObject===this&&(E.hoverObject=void 0),E.lastHoverObject===this&&(E.lastHoverObject=void 0),E.navigationObject===this&&(E.navigationObject=void 0),E.keyInputObject===this&&(E.keyInputObject=void 0),this.destroyed=1,(e=this.parent)==null||e.removeChild(this);for(let n of this.children)n.parent=void 0,n.destroy();this.children.length=0}}isMouseOverlapping(){if(!Ii)return!1;let e=gt?this.size.add(v(this.extraTouchSize||0)):this.size,n=E.screenToNative(nt);return Ei(this.nativePos,e,n)}update(){if(this.onUpdate(),this.disabled&&(this===E.activeObject&&(E.activeObject=void 0),this===E.keyInputObject&&(E.keyInputObject=void 0)),E.keyInputObject)return;let e=E.lastHoverObject===this,n=this.isActiveObject(),s=Ds(0),i=this.dragActivate?s:Js(0);this.canBeHover&&(E.navigationMode||(i||n||!s&&!gt)&&!E.hoverObject&&this.isMouseOverlapping()&&(E.hoverObject=this)),this.isHoverObject()&&(this.disabled||(i&&this.interactive&&((!this.dragActivate||!e||Js(0))&&this.onPress(),this.soundPress&&this.soundPress.play(),E.activeObject&&!n&&E.activeObject.onRelease(),E.activeObject=this,E.activateOnPress&&this.click(!this.soundPress)),E.activateOnPress||!s&&this.isActiveObject()&&this.interactive&&this.click()),i&&ya(0,0,0,1,0)),n&&(!s||this.dragActivate&&!this.isHoverObject())&&(this.onRelease(),this.soundRelease&&this.soundRelease.play(),E.activeObject=void 0),this.isHoverObject()!==e&&(this.isHoverObject()?this.onEnter():this.onLeave())}render(){if(this.onRender(),!this.size.x||!this.size.y)return;let e=this.isNavigationObject(),n=e?this.color:this.interactive&&this.isActiveObject()&&!this.disabled?this.color:this.lineColor,s=e?this.hoverColor:this.disabled?this.disabledColor:this.interactive?this.isActiveObject()?this.activeColor||this.hoverColor:this.isHoverObject()?this.hoverColor:this.color:this.color,i=this.lineWidth*(e?1.5:1);E.drawRect(this.nativePos,this.size,s,i,n,this.cornerRadius,this.gradientColor,this.shadowColor,this.shadowBlur,this.shadowOffset)}getTextSize(){return v(this.textWidth||this.textFitScale*this.size.x,this.textHeight||this.textFitScale*this.size.y)}navigatePressed(){this.click()}isHoverObject(){return E.hoverObject===this}isActiveObject(){return E.activeObject===this}isNavigationObject(){return E.navigationObject===this}isKeyInputObject(){return E.keyInputObject===this}isInteractive(){return this.interactive&&this.visible&&!this.disabled}toString(){let e="type = "+this.constructor.name;return this.text&&(e+=`
+text = `+this.text),(this.nativePos.x||this.nativePos.y)&&(e+=`
+nativePos = `+this.nativePos),(this.localPos.x||this.localPos.y)&&(e+=`
+localPos = `+this.localPos),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.color&&(e+=`
+color = `+this.color),e}renderDebug(e=!0){let n=e?this.isHoverObject()?ll:this.disabled?fl:this.interactive?Xr:dl:ul;E.drawRect(this.nativePos,this.size,Ct,4,n)}click(e=!0){this.onClick(),e&&this.soundClick&&this.soundClick.play()}onUpdate(){}onRender(){}onEnter(){}onLeave(){}onPress(){}onRelease(){}onClick(){}onChange(){}},Xi=class extends xt{constructor(e,n,s="",i="center",r=E.defaultFont){super(e,n),m(ee(s),"ui text must be a string"),m(["left","center","right"].includes(i),"ui text align must be left, center, or right"),m(ee(r),"ui text font must be a string"),this.text=s,this.align=i,this.font=r,this.canBeHover=!1,this.color=Ct,this.shadowColor=Ct,this.gradientColor=void 0,this.lineWidth=0,this.textFitScale=1}render(){super.render();let e=this.getTextSize();E.drawText(this.text,this.nativePos,e,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow,this.shadowColor,this.shadowBlur,this.shadowOffset)}},Ar=class extends xt{constructor(e,n,s=""){super(e,n),m(ee(s),"ui text must be a string"),this.maxLength=0,this.text=s,this.interactive=!0,this.canBeHover=!0}click(){E.keyInputObject=this,this.onClick()}stopEditing(){this.isKeyInputObject()&&(this.soundRelease&&this.soundRelease.play(),E.activeObject=void 0,E.keyInputObject=void 0,this.onChange())}onKeyDown(e){let n=e.code,s=e.key;n==="Backspace"?this.text=this.text.slice(0,-1):n==="Enter"||n==="Escape"?this.stopEditing():s.length===1&&(!this.maxLength||this.text.lengththis.size.y,s=n?this.size.y:this.size.x,i=n?this.size.x:this.size.y,r=n?this.nativePos.x:this.nativePos.y,a=i-s,o=r-a/2,c=r+a/2,l=E.screenToNative(nt);this.value=n?Xe(l.x,o,c):Xe(l.y,c,o)}else if(this.isNavigationObject()){let n=E.getNavigationOtherDirection();E.navigationTimer.active()||(this.value=Y(this.value+n*.01))}this.value===e||this.onChange()}render(){super.render();let e=this.size.x>this.size.y,n=e?this.size.x:this.size.y,s=e?this.size.y:this.size.x;if(this.fillMode){let r=de(s,this.cornerRadius*2),a=ot(r,n,this.value),o=(a-n)*(e?.5:-.5),c=this.nativePos.add(e?v(o,0):v(0,o)),l=this.disabled?this.disabledColor:this.handleColor,u=e?v(a,this.size.y):v(this.size.x,a);E.drawRect(c,u,l,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}else{let r=Y(e?this.value:1-this.value),a=(n-s)*(r-.5),o=this.nativePos.add(e?v(a,0):v(0,a)),c=this.disabled?this.disabledColor:this.handleColor,l=v(s);E.drawRect(o,l,c,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}let i=this.getTextSize();E.drawText(this.text,this.nativePos,i,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow)}navigatePressed(){this.value=this.value?0:1,this.onChange(),this.onRelease(),super.navigatePressed()}},Er=class extends xt{constructor(e,n,s,i=!1,r=!1,a=1){super(e,n||v()),m(ee(s),"video src must be a string"),m(O(a),"video volume must be a number"),this.color=me,this.cornerRadius=0,this.volume=a,this.video=document.createElement("video"),this.video.loop=r,this.video.volume=Y(a*Jn),this.video.muted=!at,this.video.style.display="none",this.video.src=s,document.body.appendChild(this.video),i&&this.play()}async play(){try{await this.video.play()}catch{}}pause(){this.video.pause()}stop(){this.video.pause(),this.video.currentTime=0}isLoading(){return this.video.readyState=1,"ui layout columns must be a number >= 1"),m(O(s),"ui layout gap must be a number"),m(O(i),"ui layout padding must be a number"),this.columns=n,this.gap=s,this.padding=i,r&&(this.color=Ct,this.gradientColor=void 0,this.lineWidth=0,this.shadowColor=Ct),this.relayout()}addChild(e){return super.addChild(e),this.relayout(),e}removeChild(e){super.removeChild(e),this.relayout()}relayout(){let e=this.children.length;if(!e){this.size=v(this.padding*2);return}let n=this.columns,s=Fs(e/n),i=new Array(n).fill(0),r=new Array(s).fill(0);for(let f=0;f=0&&b.objects.splice(e,1),super.destroy()}updatePhysics(){}render(){this.tileInfo?super.render():this.drawFixtures(this.color,this.lineColor,this.lineWidth)}renderDebugInfo(){let e=!this.getIsAwake(),n=this.getBodyType()===b.bodyTypeStatic,s=K(e?1:0,e?1:0,n?1:0,.5);this.drawFixtures(s)}drawFixtures(e=te,n=me,s=.1,i,r){this.getFixtureList().forEach(a=>{b.castShapeObject(a.GetShape()).GetType()!==b.instance.b2Shape.e_edge&&b.drawFixture(a,this.pos,this.angle,e,n,s,i,r)}),this.edgeLists.forEach(a=>ar(a,s,n,!1,this.pos,this.angle)),this.edgeLoops.forEach(a=>ar(a,s,n,!0,this.pos,this.angle))}beginContact(e){}endContact(e){}addShape(e,n=1,s=.2,i=0,r=!1){m(O(n),"density must be a number"),m(O(s),"friction must be a number"),m(O(i),"restitution must be a number");let a=new b.instance.b2FixtureDef;return a.set_shape(e),a.set_density(n),a.set_friction(s),a.set_restitution(i),a.set_isSensor(r),this.body.CreateFixture(a)}addBox(e=v(1),n=v(),s=0,i,r,a,o){m(D(e),"size must be a Vector2"),m(e.x>0&&e.y>0,"size must be positive"),m(D(n),"offset must be a Vector2"),m(O(s),"angle must be a number");let c=new b.instance.b2PolygonShape;return c.SetAsBox(e.x/2,e.y/2,b.vec2dTo(n),-s),this.addShape(c,i,r,a,o)}addPoly(e,n,s,i,r){m(At(e),"points must be an array");function a(c){m(3<=c.length&&c.length<=8);let l=b.instance._malloc(c.length*8);for(let f=0,d=0;f>2]=c[f].x,d+=4,b.instance.HEAPF32[l+d>>2]=c[f].y,d+=4;let u=b.instance.wrapPointer(l,b.instance.b2Vec2),h=new b.instance.b2PolygonShape;return h.Set(u,c.length),b.instance._free(l),h}let o=a(e);return this.addShape(o,n,s,i,r)}addRegularPoly(e=1,n=8,s,i,r,a){m(O(e)&&e>0,"diameter must be a positive number"),m(O(n)&&n>2,"sides must be a positive number greater than 2");let o=[],c=e/2;for(let l=n;l--;)o.push(v(c,0).rotate((l+.5)/n*oe*2));return this.addPoly(o,s,i,r,a)}addRandomPoly(e=1,n,s,i,r){m(O(e)&&e>0,"diameter must be a positive number");let a=Yr(3,9),o=[],c=e/2;for(let l=a;l--;)o.push(v(we(c/2,c*1.5),0).rotate(l/a*oe*2));return this.addPoly(o,n,s,i,r)}addCircle(e=1,n=v(),s,i,r,a){m(O(e)&&e>0,"diameter must be a positive number"),m(D(n),"offset must be a Vector2");let o=new b.instance.b2CircleShape;return o.set_m_p(b.vec2dTo(n)),o.set_m_radius(e/2),this.addShape(o,s,i,r,a)}addEdge(e,n,s,i,r,a){m(D(e),"point1 must be a Vector2"),m(D(n),"point2 must be a Vector2");let o=new b.instance.b2EdgeShape;return o.Set(b.vec2dTo(e),b.vec2dTo(n)),this.addShape(o,s,i,r,a)}addEdgeList(e,n,s,i,r){m(At(e),"points must be an array");let a=[],o=[];for(let c=0;ce[yt(l,e.length)];for(let l=0;lthis.destroyFixture(e))}getCenterOfMass(){return b.vec2From(this.body.GetWorldCenter())}getLinearVelocity(){return b.vec2From(this.body.GetLinearVelocity())}getAngularVelocity(){return this.body.GetAngularVelocity()}getMass(){return this.body.GetMass()}getInertia(){return this.body.GetInertia()}getIsAwake(){return this.body.IsAwake()}getBodyType(){return this.body.GetType()}getSpeed(){return this.getLinearVelocity().length()}setTransform(e,n){this.pos=e,this.angle=n,this.body.SetTransform(b.vec2dTo(e),-n)}setPosition(e){this.setTransform(e,this.body.GetAngle())}setAngle(e){this.setTransform(b.vec2From(this.body.GetPosition()),e)}setLinearVelocity(e){this.body.SetLinearVelocity(b.vec2dTo(e))}setAngularVelocity(e){this.body.SetAngularVelocity(e)}setLinearDamping(e){this.body.SetLinearDamping(e)}setAngularDamping(e){this.body.SetAngularDamping(e)}setGravityScale(e=1){this.body.SetGravityScale(this.gravityScale=e)}setBullet(e=!0){this.body.SetBullet(e)}setAwake(e=!0){this.body.SetAwake(e)}setBodyType(e){this.body.SetType(e)}setSleepingAllowed(e=!0){this.body.SetSleepingAllowed(e)}setFixedRotation(e=!0){this.body.SetFixedRotation(e)}setCenterOfMass(e){this.setMassData(e)}setMass(e){this.setMassData(void 0,e)}setMomentOfInertia(e){this.setMassData(void 0,void 0,e)}resetMassData(){this.body.ResetMassData()}setMassData(e,n,s){let i=new b.instance.b2MassData;this.body.GetMassData(i),e!==void 0&&i.set_center(b.vec2dTo(e)),n!==void 0&&i.set_mass(n),s!==void 0&&i.set_I(s),this.body.SetMassData(i)}setFilterData(e=0,n=0,s=0){this.getFixtureList().forEach(i=>{let r=i.GetFilterData();r.set_categoryBits(e),r.set_maskBits(65535&~n),r.set_groupIndex(s)})}setSensor(e=!0){this.getFixtureList().forEach(n=>n.SetSensor(e))}applyForce(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyForce(b.vec2dTo(e),b.vec2dTo(n))}applyAcceleration(e,n){n||(n=this.getCenterOfMass()),this.setAwake();let s=e.scale(this.getMass());this.body.ApplyLinearImpulse(b.vec2dTo(s),b.vec2dTo(n))}applyImpulse(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyLinearImpulse(b.vec2dTo(e),b.vec2dTo(n))}applyTorque(e){this.setAwake(),this.body.ApplyTorque(e)}applyAngularAcceleration(e){this.setAwake(),this.body.ApplyAngularImpulse(e*this.getInertia())}applyAngularImpulse(e){this.setAwake(),this.body.ApplyAngularImpulse(e)}hasFixtures(){return!b.isNull(this.body.GetFixtureList())}getFixtureList(){let e=[];for(let n=this.body.GetFixtureList();!b.isNull(n);)e.push(n),n=n.GetNext();return e}hasJoints(){return!b.isNull(this.body.GetJointList())}getJointList(){let e=[];for(let n=this.body.GetJointList();!b.isNull(n);)e.push(n),n=n.get_next();return e}},Ki=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeStatic;super(e,n,s,i,r,o,a)}},Pr=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeKinematic;super(e,n,s,i,r,o,a)}},Mr=class extends Ki{constructor(e){m(e instanceof qs,"tileLayer must be a TileCollisionLayer"),super(e.pos,e.size),this.tileLayer=e,this.addChild(e)}render(){}buildCollision(e=.2,n=0){this.destroyAllFixtures(),this.pos=this.tileLayer.pos.copy(),this.size=this.tileLayer.size.copy();let s=[],i=(a,o)=>a+o*this.size.x,r=(a,o)=>!s[i(a,o)]&&this.tileLayer.getCollisionData(v(a,o))>0;for(let a=0;ai.fractionr.pos.distanceSquared(e)0,"Tween duration must be > 0"),this.callback=e,this.start=n,this.end=s,this.duration=i,this.life=i,this.ease=r.ease||no.LINEAR,this.useRealTime=!!r.useRealTime,this.paused=!!r.paused,this.thenCallback=void 0,this.loopRemaining=0,ut.push(this),e(this.interp(i))}setEase(e){return this.ease=e,this}then(e){return this.thenCallback=e,this.loopRemaining=0,this}loop(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>zl(this),this}pingPong(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>Ul(this),this}pause(){this.paused=!0}resume(){this.paused=!1}restart(){this.life=this.duration,this.paused=!1,ut.indexOf(this)<0&&ut.push(this),this.callback(this.interp(this.duration))}isActive(){return!this.paused&&ut.indexOf(this)>=0}getPercent(){return Xe(this.duration-this.life,0,this.duration)}getValue(){return this.interp(this.life)}interp(e){let n=this.ease((this.duration-e)/this.duration);return zc(this.start)?this.start.lerp(this.end,n):this.start+(this.end-this.start)*n}stop(){let e=ut.indexOf(this);e>=0&&ut.splice(e,1),this.thenCallback=void 0}},no={LINEAR:t=>t,POWER:t=>e=>e**t,SINE:t=>1-be(t*(oe/2)),CIRC:t=>1-(1-t*t)**.5,EXPO:t=>t===0?0:2**(10*t-10),BACK:t=>t*t*(2.70158*t-1.70158),ELASTIC:t=>t===0?0:t===1?1:-(2**(10*t-10))*pe((37-40*t)*oe/6),SPRING:t=>1-(pe(oe*(1-t)*(.2+2.5*(1-t)**3))*t**2.2+(1-t))*(1+1.2*t),BOUNCE:t=>{let e=1-t,n;return e<4/11?n=7.5625*e*e:e<8/11?n=7.5625*(e-=6/11)*e+.75:e<10/11?n=7.5625*(e-=9/11)*e+.9375:n=7.5625*(e-=10.5/11)*e+.984375,1-n},IN:t=>t,OUT:t=>e=>1-t(1-e),IN_OUT:t=>no.PIECEWISE(t,no.OUT(t)),PIECEWISE:(...t)=>{let e=t.length;return n=>{let s=n*e-1e-9>>0;return(t[s]((n-s/e)*e)+s)/e}},BEZIER:(t,e,n,s)=>{let i=r=>{let a=1-r,o=3*a*a*r,c=3*a*r*r,l=r**3;return[o*t+c*n+l,o*e+c*s+l]};return r=>{let a=0,o=1;for(let c=0;c<128;c++){let l=(a+o)/2,[u,h]=i(l);if(he(u-r)<1e-5)return h;u=this.size.x||n>=this.size.y?null:this.nodes[e+n*this.size.x]}worldToTile(e){let n=this.tileLayer?this.tileLayer.pos.x:0,s=this.tileLayer?this.tileLayer.pos.y:0;return v(Oe(e.x-n),Oe(e.y-s))}tileToWorld(e,n){let s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;return v(e+.5+s,n+.5+i)}buildNodeData(){let e=this.size.x,n=this.size.y,s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;for(let r=0;r0&&(c?l>0&&Ce(o.posWorld,er,K(1,0,0,de(.2,l*.05)),this.debugTime):Ce(o.posWorld,er,K(1,0,0,.25),this.debugTime))}}aStarSearch(e,n){m(e&&n,"aStarSearch needs both endpoints"),m(e!==n,"aStarSearch: start and end must differ \u2014 caller should handle trivial case"),m(e.walkable&&n.walkable,"aStarSearch: endpoints must be walkable");let s=[e];e.isOpen=!0;let i=0;for(;s.length>0;){let r=0,a=s[0].f;for(let c=1;cthis.maxLoop)break;o.isOpen=!1,s.splice(r,1),o.isClosed=!0,this.debug&&this.debugTime>0&&Ce(o.posWorld,er,K(1,1,1,.05),this.debugTime);for(let c=-1;c<=1;++c)for(let l=-1;l<=1;++l){if(l===0&&c===0)continue;let u=this.getNode(o.pos.x+l,o.pos.y+c);if(!u||!u.walkable||u.isClosed)continue;let h=1;if(l!==0&&c!==0){let x=this.getNode(o.pos.x+l,o.pos.y);if(!x||!x.walkable)continue;let w=this.getNode(o.pos.x,o.pos.y+c);if(!w||!w.walkable)continue;h=Wh}let f=o.g+h+u.cost;if(!u.isOpen)u.isOpen=!0,s.push(u);else if(f>=u.g)continue;u.parent=o,u.g=f;let d=he(n.pos.x-u.pos.x),p=he(n.pos.y-u.pos.y),y=le(d,p)+(Math.SQRT2-1)*de(d,p);u.f=u.g+y*this.heuristicWeight}}return n.parent!==null}getNearestClearNode(e,n=10,s=!0){m(D(e),"worldPos must be a Vector2"),s&&this.buildNodeData();let i=this.tileLayer?this.tileLayer.pos.x:0,r=this.tileLayer?this.tileLayer.pos.y:0,a=Oe(e.x-i),o=Oe(e.y-r);for(let c=0;c<=n;++c){let l=null,u=0;for(let h=-c;h<=c;++h)for(let f=-c;f<=c;++f){if(c>0&&he(f)!==c&&he(h)!==c)continue;let d=this.getNode(a+f,o+h);if(!d||!d.isClear())continue;let p=d.posWorld.x-e.x,y=d.posWorld.y-e.y,x=p*p+y*y;(!l||x0&&st(i.posWorld,.3,K(.5,0,.5,.5),this.debugTime),e.splice(n,1),n=le(1,n-1);continue}else if(c===2){this.debug&&this.debugTime>0&&st(i.posWorld,.3,K(1,0,0,.5),this.debugTime);let d,p;s.pos.y===i.pos.y&&r.pos.x===i.pos.x?(d=s.pos.x,p=r.pos.y):(d=r.pos.x,p=s.pos.y);let y=this.getNode(d,p);if(y&&y.isClear()){e.splice(n,1),n=le(1,n-1);continue}}else if(c===5){this.debug&&this.debugTime>0&&st(i.posWorld,.3,K(1,1,0,.5),this.debugTime);let d=n>=2?e[n-2]:s,p,y,x,w;l===0||h===0?(p=r.pos.x,y=i.pos.y,x=s.pos.x,w=i.pos.y):(p=i.pos.x,y=r.pos.y,x=i.pos.x,w=s.pos.y);let A=p-d.pos.x,S=y-d.pos.y,_=x-d.pos.x,k=w-d.pos.y,C=A*A+S*S,L=_*_+k*k,N=C0&&st(i.posWorld,.3,K(0,1,0,.5),this.debugTime),l===h&&u===f){++n;continue}else{let d,p;s.pos.y===r.pos.y?(d=i.pos.x,p=s.pos.y):(d=s.pos.x,p=i.pos.y);let y=this.getNode(d,p);if(y&&y.isClear()){e[n]=y,n=le(1,n-1);continue}}++n}}smoothPathStringPull(e){if(e.length<=2)return;for(let i of e)if(!i.isClear())return;let n=e.slice();e.length=0,e.push(n[0]);let s=0;for(let i=1;i0&&Dt(r.posWorld,e[e.length-1].posWorld,K(0,0,1,.3),.02,this.debugTime);continue}for(;s=1;--n){let s=e[n-1],i=e[n],r=e[n+1];(i.pos.x-s.pos.x)*(r.pos.y-s.pos.y)===(i.pos.y-s.pos.y)*(r.pos.x-s.pos.x)&&e.splice(n,1)}}isNodeClear(e,n){let s=this.getNode(e,n);return s!==null&&s.isClear()}isLineClear(e,n){m(D(e)&&D(n),"isLineClear needs Vector2 endpoints"),m(this.isNodeClear(e.x,e.y)&&this.isNodeClear(n.x,n.y),"isLineClear endpoints must be in-bounds and clear");let s=n.x-e.x,i=n.y-e.y,r=he(s),a=he(i),o=mt(s),c=mt(i),l=e.x,u=e.y;if(a===r){for(;l!==n.x;){if(l!==e.x&&(!this.isNodeClear(l,u)||!this.isNodeClear(l,u-c))||!this.isNodeClear(l,u+c))return!1;l+=o,u+=c}if(!this.isNodeClear(n.x,n.y-c))return!1}else if(ao.posWorld.copy());if(this.debug&&this.debugTime>0&&a.length>0){for(let o=1;oqh,bootGameHost:()=>$h,default:()=>Hh});var _n=class{constructor(e){this._state=(e==null?2654435769:e)>>>0}next(){this._state=this._state+1831565813>>>0;let e=this._state;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}range(e,n){return e+this.next()*(n-e)}reseed(e){this._state=(e==null?2654435769:e)>>>0}},vo=class{constructor(e){this._clock=e||tu(),this._origin=this._clock()}nowMs(){return this._clock()}elapsedMs(){return this._clock()-this._origin}},wo=class{constructor(e){this._time=e,this._subs=new Map}sourceFor(e){let n=this,s=e==null?null:e;return{on(i,r){if(n._assertType(i),typeof r!="function")throw new Error("[HostDevInputBridge] on \u7684 handler \u5FC5\u987B\u662F\u51FD\u6570");let a=n._subs.get(i)||[],o={handler:r,scope:s};return a.push(o),n._subs.set(i,a),{cancel(){let c=n._subs.get(i);if(!c)return;let l=c.indexOf(o);l>=0&&c.splice(l,1)}}},off(i,r){n._assertType(i);let a=n._subs.get(i);if(!a)return;let o=a.findIndex(c=>c.handler===r&&c.scope===s);o>=0&&a.splice(o,1)}}}_emit(e,n){this._assertType(e);let s=n||{},i={type:e,x:typeof s.x=="number"?s.x:0,y:typeof s.y=="number"?s.y:0,key:typeof s.key=="string"?s.key:"",tMs:this._time.nowMs()},r=this._subs.get(e);if(!r||r.length===0)return;let a=r.slice();for(let o of a)try{o.handler(i)}catch(c){an("[host-dev input] \u8F93\u5165 handler \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09type="+e,c)}}disposeScope(e){if(e==null)return 0;let n=0;for(let[s,i]of this._subs){let r=i.filter(a=>a.scope!==e);n+=i.length-r.length,r.length===0?this._subs.delete(s):this._subs.set(s,r)}return n}_subscriptionCount(){let e=0;for(let n of this._subs.values())e+=n.length;return e}_assertType(e){if(!To.has(e))throw new Error("[HostDevInputBridge] \u975E\u6CD5\u8F93\u5165\u4E8B\u4EF6\u7C7B\u578B\uFF1A"+String(e)+"\uFF08\u4EC5\u652F\u6301 "+Array.from(To).join("/")+"\uFF09")}},To=new Set(["pointerdown","pointermove","pointerup","keydown","keyup"]);function ja(t){let e=t||{},n=new vo(e.clock),s=new _n(e.seed),i=e.seed==null?2654435769:e.seed>>>0,r=new wo(n),a=typeof e.audioFactory=="function"?e.audioFactory:null,o=null,c=!1,l=typeof e.engineFactory=="function"?e.engineFactory:null,u=null,h=!1,f=new Map,d=0,p=0;function y(){if(o)return o;if(!a)return c||(ko("[host-dev audio] \u672A\u6CE8\u5165 audioFactory\uFF0CgetAudioContext \u8FD4\u56DE null\uFF08P6 \u987B\u5BB9\u9519\u964D\u7EA7\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u5DE5\u5382\uFF09"),c=!0),null;try{o=a()}catch(_){an("[host-dev audio] audioFactory \u629B\u9519\uFF0CgetAudioContext \u964D\u7EA7\u8FD4\u56DE null",_),o=null}return o}function x(){if(u)return u;if(!l)return h||(ko("[host-dev engine] \u672A\u6CE8\u5165 engineFactory\uFF0CgetEngine \u8FD4\u56DE null\uFF08\u63D2\u4EF6\u987B\u5BB9\u9519\u964D\u7EA7\uFF1A\u7C92\u5B50\u9000\u53D7\u63A7\u9762\u81EA\u7BA1/\u5408\u6210\u6838\u9000 vendored/\u6570\u5B66\u9000\u5185\u7F6E\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u80CC\u4E66\uFF09"),h=!0),null;try{u=l()}catch(_){an("[host-dev engine] engineFactory \u629B\u9519\uFF0CgetEngine \u964D\u7EA7\u8FD4\u56DE null",_),u=null}return u}function w(_,k){return{getContext2d(){return e.context2d==null?null:e.context2d},onFrame(L){let N=d++;return f.set(N,L),{cancel(){f.delete(N)}}},getInput(){return r.sourceFor(_)},getAudioContext(){return y()},getEngine(){return x()},time:n,random:k}}let A=w(null,s),S={context:A,tick(_){p+=1;let k=Array.from(f.values());for(let C of k)try{C(_,p)}catch(L){an("[host-dev tick] \u5E27\u56DE\u8C03\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09frame="+p,L)}},frameCount(){return p},inputBridge:r,deriveContextFor(_,k){let C=eu(i,_),L=new _n(C);return w(k==null?_:k,L)}};return Object.defineProperty(A,Ao,{value:S,enumerable:!1,writable:!1,configurable:!1}),S}var Ao=Symbol("zaomeng.coreProtocol.contextBundle"),ui=class{constructor(){this._plugins=new Map,this._initOrder=[],this._initErrors=[],this._phase="idle",this._disposed=!1,this._context=void 0,this._pluginContexts=new Map}register(e){if(!e||typeof e!="object")throw new Error("[PluginRegistry] register \u9700\u8981\u4E00\u4E2A\u63D2\u4EF6\u5BF9\u8C61");if(typeof e.name!="string"||e.name.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6\u7F3A\u5C11\u5408\u6CD5 name");if(typeof e.version!="string"||e.version.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11\u5408\u6CD5 version");if(typeof e.init!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11 init \u51FD\u6570");if(e.dispose!=null&&typeof e.dispose!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7684 dispose \u5FC5\u987B\u662F\u51FD\u6570\u6216\u7701\u7565");if(this._plugins.has(e.name))throw new Error("[PluginRegistry] \u63D2\u4EF6\u91CD\u540D\u62D2\u7EDD\uFF1A"+e.name+" \u5DF2\u6CE8\u518C");return this._plugins.set(e.name,e),this}has(e){return this._plugins.has(e)}get(e){return this._plugins.get(e)}list(){return Array.from(this._plugins.keys())}initAll(){if(this._phase==="initialized")return ko("[PluginRegistry] initAll \u91CD\u590D\u8C03\u7528\uFF0C\u5DF2\u5FFD\u7565\uFF08\u5DF2\u5904\u4E8E initialized\uFF09"),this._initResult();if(this._phase==="disposed")throw new Error("[PluginRegistry] \u5DF2 dispose \u7684\u6CE8\u518C\u5668\u4E0D\u53EF\u518D initAll");if(this._context==null)throw new Error("[PluginRegistry] \u672A\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\uFF1A\u8BF7\u5728 initAll() \u4E4B\u524D\u8C03\u7528 useContext(context)\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context); reg.initAll();\uFF09");for(let[e,n]of this._plugins){let s=this._missingDeps(n);if(s.length>0){let r=new Error("[PluginRegistry] \u63D2\u4EF6 "+e+" \u4F9D\u8D56\u7F3A\u5931\uFF1A"+s.join(", ")+"\uFF08\u672A\u6CE8\u518C\uFF09");this._initErrors.push({name:e,error:r}),an("[PluginRegistry] \u8DF3\u8FC7 init\uFF08\u4F9D\u8D56\u7F3A\u5931\uFF0C\u5DF2\u9694\u79BB\uFF09\uFF1A"+e,r);continue}let i=this._contextFor(e);try{n.init(i),this._initOrder.push(e)}catch(r){let a=r instanceof Error?r:new Error(String(r));this._initErrors.push({name:e,error:a}),an("[PluginRegistry] \u63D2\u4EF6 init \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF0C\u4E0D\u8FDE\u5750\uFF09\uFF1A"+e,a)}}return this._phase="initialized",this._initResult()}_contextFor(e){let n=this._pluginContexts.get(e);if(n)return n;let s=this._context&&this._context[Ao],i;return s&&typeof s.deriveContextFor=="function"?i=s.deriveContextFor(e,e):i=this._context,this._pluginContexts.set(e,i),i}disposeAll(){if(this._disposed)return{disposed:[],errors:[]};let e=[],n=[],s=this._context&&this._context[Ao],i=s&&s.inputBridge;for(let r=this._initOrder.length-1;r>=0;r--){let a=this._initOrder[r],o=this._plugins.get(a);if(o&&typeof o.dispose=="function")try{o.dispose(),e.push(a)}catch(c){let l=c instanceof Error?c:new Error(String(c));n.push({name:a,error:l}),an("[PluginRegistry] \u63D2\u4EF6 dispose \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,l)}if(i&&typeof i.disposeScope=="function")try{i.disposeScope(a)}catch(c){an("[PluginRegistry] \u56DE\u6536\u63D2\u4EF6\u8F93\u5165\u8BA2\u9605\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,c)}}return this._disposed=!0,this._phase="disposed",{disposed:e,errors:n}}useContext(e){if(this._phase!=="idle")throw new Error("[PluginRegistry] useContext \u5FC5\u987B\u5728 initAll() \u4E4B\u524D\u8C03\u7528\uFF08\u5F53\u524D\u9636\u6BB5\uFF1A"+this._phase+"\uFF09\u3002\u8BF7\u5728\u4EFB\u4F55 initAll/disposeAll \u4E4B\u524D\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\u3002");if(e==null||typeof e!="object")throw new Error("[PluginRegistry] useContext \u9700\u8981\u4E00\u4E2A\u53D7\u63A7\u4E0A\u4E0B\u6587\u5BF9\u8C61\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context);\uFF09");return this._context=e,this}_missingDeps(e){return!Array.isArray(e.dependencies)||e.dependencies.length===0?[]:e.dependencies.filter(n=>!this._plugins.has(n))}_initResult(){return{ok:this._initErrors.length===0,initialized:this._initOrder.slice(),errors:this._initErrors.slice()}}};function eu(t,e){let n=2166136261,s=16777619,i=t>>>0;for(let a=0;a<32;a+=8){let o=i>>>a&255;n^=o,n=Math.imul(n,s)>>>0}let r=String(e);for(let a=0;a>>0,n^=o>>>8&255,n=Math.imul(n,s)>>>0}return n>>>0}function tu(){if(typeof globalThis!="undefined"&&globalThis.performance&&typeof globalThis.performance.now=="function")return()=>globalThis.performance.now();if(typeof process!="undefined"&&process.hrtime&&typeof process.hrtime.bigint=="function"){let t=process.hrtime.bigint();return()=>Number(process.hrtime.bigint()-t)/1e6}return()=>Date.now()}function an(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function ko(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Kh=Object.freeze(Array.from(To)),Ja="core-protocol-v0";var Na=Object.freeze(["t_boot","t_plugins_ready","t_game_init","t_first_paint","t_input_bound","t_game_start"]),Co=Na.reduce((t,e,n)=>(t[e]=n,t),Object.create(null)),nu=new Set(Na);function _o(t){let e=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}var za=_o("runtime-probe::seed::v1");function di(t){return t===null||typeof t!="object"?JSON.stringify(t):Array.isArray(t)?"["+t.map(di).join(",")+"]":"{"+Object.keys(t).sort().map(n=>JSON.stringify(n)+":"+di(t[n])).join(",")+"}"}function Ua(t){let e=di(t.extra==null?null:t.extra),n=di(Array.isArray(t.pluginSet)?t.pluginSet:[]);return["seq="+t.seq,"anchor="+t.anchor,"tMono="+t.tMono,"buildSha="+(t.buildSha||""),"pluginSet="+n,"extra="+e].join("|")}function su(t){return Math.round(t*1e3)/1e3}function iu(t){if(!Array.isArray(t))return{ok:!1,reason:"records_not_array"};let e=za,n=-1;for(let s=0;stypeof _=="string").slice().sort():[],i=typeof e.sink=="function"?e.sink:null,r=e.autoBoot!==!1,a=typeof e.inputAnchorType=="string"?e.inputAnchorType:"pointerdown",o=()=>0,c=!1,l=0,u=za,h=[],f=new Set,d=-1,p=null,y=!1,x=!1,w=!1;function A(_,k){let C=null;if(!nu.has(_))C="unknown_anchor";else{f.has(_)&&(C=C?C+";duplicate_anchor":"duplicate_anchor");let N=Co[_];N_.time.nowMs(),c=!0,r&&!x&&A("t_boot",{auto:!0}),p=_.getInput().on(a,k=>{y||(y=!0,A("t_input_bound",{firstInput:!0,type:k.type}))}),A("t_input_bound",{stage:"registered",type:a})},dispose(){w||(p&&(p.cancel(),p=null),w=!0)},mark:A,getRecords(){return h.map(_=>({..._}))},toJSONL(){return h.map(_=>JSON.stringify(_)).join(`
+`)},verify(){return iu(h)}}}function ou(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Wa(t){let e=t.LJS,n=t.engineMath,s=t.engineMode,i=t.recHook||(()=>{});if(s!=="real")return null;let r=n;return{math:{lerp:(o,c,l)=>(i("math.lerp"),r.lerp(o,c,l)),smoothStep:o=>(i("math.smoothStep"),r.smoothStep(o)),easing:Object.fromEntries(Object.keys(r.easing).map(o=>[o,c=>(i("math.easing."+o),r.easing[o](c))]))},particles:{spawnEmitter(o){i("particles.spawnEmitter");let c=e.screenToWorld(e.vec2(o.pos.x,o.pos.y)),l=e.cameraScale,u=o.emitTime!=null?o.emitTime:o.count!=null?1/60:0,h=o.emitRate!=null?o.emitRate:o.count!=null?o.count*60:100,f=(o.speed!=null?o.speed:0)/l/60,d=o.damping!=null?o.damping:1,p=o.colorStart||{r:1,g:1,b:1,a:1},y=o.colorEnd||{r:1,g:1,b:1,a:0},x=e.rgb(p.r,p.g,p.b,p.a),w=e.rgb(y.r,y.g,y.b,y.a),A=new e.ParticleEmitter(c,o.angle!=null?o.angle:0,(o.emitSize!=null?o.emitSize:0)/l,u,h,o.coneAngle!=null?o.coneAngle:Math.PI,void 0,x,x,w,w,o.particleTime!=null?o.particleTime:.5,(o.sizeStart!=null?o.sizeStart:6)/l,(o.sizeEnd!=null?o.sizeEnd:0)/l,f,0,d,1,o.gravityScale!=null?o.gravityScale:0,Math.PI,.1,0,!1,o.additive!=null?o.additive:!1,!0);return{isActive(){return A.isActive()},stop(){A.destroyed||A.destroy(!0)}}}},audio:{synth:{synthSfx:o=>{i("audio.synth.synthSfx");try{return e.zzfxG(...o)}catch(c){return console.error("[host][engine-audio] zzfxG \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(c&&c.message?c.message:c)),null}},synthSong:(o,c,l,u)=>{i("audio.synth.synthSong");try{return e.zzfxM(o,c,l,u)}catch(h){return console.error("[host][engine-audio] zzfxM \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(h&&h.message?h.message:h)),null}}}}}}function St(t){return t<0?0:t>1?1:t}function qa(t){let e=t.Ease,n=e.POWER(2),s=e.POWER(3),i=e.OUT(n),r=e.IN_OUT(n),a=e.OUT(s),o=e.IN_OUT(s),c=e.OUT(e.BACK),l=e.OUT(e.ELASTIC);return{lerp:(u,h,f)=>t.lerp(u,h,f),smoothStep:u=>t.smoothStep(u),easing:{linear:u=>e.LINEAR(St(u)),quadIn:u=>n(St(u)),quadOut:u=>i(St(u)),quadInOut:u=>r(St(u)),cubicIn:u=>s(St(u)),cubicOut:u=>a(St(u)),cubicInOut:u=>o(St(u)),backIn:u=>e.BACK(St(u)),backOut:u=>c(St(u)),elasticIn:u=>e.ELASTIC(St(u)),elasticOut:u=>l(St(u))}}}var cn=2,fi=1/60;async function Ha(t){let e=t.canvas,n=t.statusEl||null,s=t.engine,i=t.seed>>>0,r=t.mode||"play",a=t.engineMode||"real",o=t.viewport.w,c=t.viewport.h,l=t.factory,u=t.buildFactoryOpts||(()=>{}),h=t.plugins||{},f=t.registerOrder||Object.values(h),d=t.onReady||(()=>{}),p=t.recHook||(()=>{});function y(G){n&&(n.textContent=G)}let x=[];window.addEventListener("error",G=>x.push({type:"error",message:String(G&&G.message||G)})),window.addEventListener("unhandledrejection",G=>x.push({type:"unhandledrejection",message:String(G&&G.reason&&G.reason.message||G&&G.reason||G)}));let w=null,A=!1;function S(){if(!A)return null;if(w)return w;let G=window.AudioContext||window.webkitAudioContext;return G?(w=new G,w):null}let _=0,k=null,C=null,L=null,N=null,ae=[],Z={},T=null;function P(G,ye){try{L&&L.mark(G,ye)}catch(F){x.push({type:"mark",message:String(F&&F.message||F)})}}function R(){C&&typeof C._refreshChecklist=="function"&&C._refreshChecklist(Z)}async function M(G,ye){k=ja({context2d:G,seed:i,audioFactory:S,clock:()=>_,engineFactory:()=>Wa({LJS:a==="real"?s:null,engineMath:a==="real"?qa(s):null,engineMode:a,recHook:p})});let F=new ui;for(let J of f)F.register(J);F.useContext(k.context),N=F.initAll(),ae=F.list().concat(["runtime-probe"]),L=Va({pluginSet:ae,inputAnchorType:"pointerdown",autoBoot:!0});let I=k.deriveContextFor("runtime-probe","runtime-probe");P("t_boot",{by:"game-host",stage:"pre-init",engineMode:a}),P("t_plugins_ready",{initialized:N.initialized.length,ok:N.ok});let j=u(k.context,{bundle:k,plugins:h,getRealAudioCtx:()=>w});C=l(j),await C.init({ctx:k.context,mainContext:G,canvas:ye(),seed:i}),T=C&&typeof C._forensicsView=="function"?C._forensicsView():null,P("t_game_init",{hasForensics:!!T}),ne(),P("t_first_paint",{frame:k.frameCount()});try{L.init(I)}catch(J){x.push({type:"probe-init",message:String(J&&J.message||J)})}P("t_game_start",{mode:r,engineMode:a}),R(),d(Re,{bundle:k,game:C,probe:L,checklist:Z,uncaught:x,pluginSet:ae,initRes:N,getGameForensics:()=>T,mark:P,stepOneFrame:ne})}let B=null;function ne(G){let ye=typeof G=="number"?G:fi;C&&(_+=ye*1e3,C.update(ye),a==="stub"&&B&&C.render(B),R())}function V(G){for(let ye=0;ye{}),C&&typeof C._onAudioUnlock=="function"&&C._onAudioUnlock()}let Re={seed:i,mode:r,engineMode:a,protocol:Ja,frameCount:()=>k?k.frameCount():0,stepFrames:V,startRaf:()=>_t(),stopRaf:()=>pt(),tap(G,ye){q(),k&&(k.inputBridge._emit("pointerdown",{x:G,y:ye}),k.inputBridge._emit("pointerup",{x:G,y:ye}))},do(G){C&&typeof C._handleAction=="function"&&C._handleAction(G)},state:()=>T?T.state():{phase:"booting"}};function Ie(G){let ye=k.inputBridge;function F(I,j){let J=G.getBoundingClientRect();return{x:(I-J.left)/J.width*o,y:(j-J.top)/J.height*c}}G.addEventListener("pointerdown",I=>{q(),ye._emit("pointerdown",F(I.clientX,I.clientY))}),G.addEventListener("pointermove",I=>{ye._emit("pointermove",F(I.clientX,I.clientY))}),G.addEventListener("pointerup",I=>{ye._emit("pointerup",F(I.clientX,I.clientY))})}let xe=0,Pe=!1,Fe=0;function Ve(G){if(!Pe)return;Fe===0&&(Fe=G);let ye=(G-Fe)/1e3;Fe=G,ye>.05&&(ye=.05),ne(ye),xe=window.requestAnimationFrame(Ve)}function _t(){a==="stub"&&(Pe||(Pe=!0,Fe=0,xe=window.requestAnimationFrame(Ve)))}function pt(){Pe=!1,xe&&window.cancelAnimationFrame(xe),xe=0}function sn(G){G.width=o*cn,G.height=c*cn,G.style.width=o+"px",G.style.height=c+"px";let ye=G.getContext("2d",{willReadFrequently:!0});return ye.setTransform(cn,0,0,cn,0,0),ye}async function Cn(){let G=sn(e);return B=G,await M(G,()=>e),Ie(e),r==="evidence"?y(`evidence \u5C31\u7EEA seed=${i} \xB7 \u7528 host \u9A71\u52A8\uFF08stepFrames/tap\uFF09`):(y(`seed=${i} \xB7 \u70B9\u5F00\u59CB\uFF08\u9996\u6B21\u70B9\u51FB\u5F00\u58F0\uFF09`),_t()),Re}let Nt=()=>{},on=()=>{};function rn(){window.__gameHostEngineInitFired=!0}function Kn(){Nt()}function Qn(){}function go(){on()}function bo(){}async function xo(G){await M(G,()=>s.mainCanvas),Ie(s.mainCanvas),Nt=()=>{C&&(_+=fi*1e3,C.update(fi))},on=()=>{if(C){G.save(),G.setTransform(cn,0,0,cn,0,0);try{G.imageSmoothingEnabled=!1}catch{}C.render(G),G.restore()}},s.mainCanvas&&(s.mainCanvas.id="game-engine"),window.__engine={frame(){return s.frame},time(){return s.time},timeReal(){return s.timeReal},paused(){return s.paused},timeScale(){return s.timeScale},snapshot(){return{frame:s.frame,time:s.time,timeReal:s.timeReal,paused:s.paused,timeScale:s.timeScale}}},y(`engine RAF running \xB7 seed=${i} engine=real`)}if(a!=="real")return await Cn();if(!s){let G="real \u901A\u9053\u672A\u6CE8\u5165\u5F15\u64CE\uFF08opts.engine \u7F3A\u5931\uFF09\uFF1A\u8BF7\u7ECF entry \u5305\u88C5\u5C42\u542F\u52A8\uFF08host \u4E0D\u76F4\u63A5 import \u5F15\u64CE\uFF0CQ4/Option C\uFF09";throw y("ENGINE INJECT MISSING: "+G),new Error(G)}s.setGLEnable(!1),s.setShowSplashScreen(!1),s.setDebugWatermark(!1),s.setCanvasClearColor(s.BLACK),s.setCanvasFixedSize(s.vec2(o*cn,c*cn));let vs=document.createElement("div");return vs.id="engine-root",document.body.appendChild(vs),await s.engineInit(rn,Kn,Qn,go,bo,[],vs).then(()=>xo(s.mainContext)).catch(G=>{throw window.__gameHostBootError=String(G&&G.message||G),y("ENGINE INIT FAILED: "+window.__gameHostBootError),G}),Re}function ru(){return{hit:!1,depth:0,nx:0,ny:0}}var Eo=class{constructor(e){let n=e||{},s=typeof n.cellSize=="number"&&n.cellSize>0?n.cellSize:64;this._cellSize=s,this._cells=new Map,this._entries=new Map,this._seq=0}get size(){return this._entries.size}_cellRange(e){let n=this._cellSize,s=Math.floor((e.x-e.hw)/n),i=Math.floor((e.x+e.hw)/n),r=Math.floor((e.y-e.hh)/n),a=Math.floor((e.y+e.hh)/n);return{cx0:s,cy0:r,cx1:i,cy1:a}}insert(e,n){this._entries.has(e)&&this.remove(e);let{cx0:s,cy0:i,cx1:r,cy1:a}=this._cellRange(n),o=[];for(let l=i;l<=a;l++)for(let u=s;u<=r;u++){let h=u+","+l,f=this._cells.get(h);f||(f=new Set,this._cells.set(h,f)),f.add(e),o.push(h)}let c={x:n.x,y:n.y,hw:n.hw,hh:n.hh};this._entries.set(e,{id:e,box:c,seq:this._seq++,cells:o})}remove(e){let n=this._entries.get(e);if(!n)return!1;for(let s of n.cells){let i=this._cells.get(s);i&&(i.delete(e),i.size===0&&this._cells.delete(s))}return this._entries.delete(e),!0}query(e){let{cx0:n,cy0:s,cx1:i,cy1:r}=this._cellRange(e),a=new Set;for(let o=s;o<=r;o++)for(let c=n;c<=i;c++){let l=this._cells.get(c+","+o);if(l)for(let u of l)a.add(u)}return this._collect(a)}queryPoint(e,n){let s=this._cellSize,i=Math.floor(e/s),r=Math.floor(n/s),a=this._cells.get(i+","+r);return a?this._collect(new Set(a)):[]}clear(){this._cells.clear(),this._entries.clear(),this._seq=0}_collect(e){let n=[];for(let s of e){let i=this._entries.get(s);i&&n.push(i)}return n.sort((s,i)=>s.seq-i.seq),n.map(s=>({id:s.id,box:s.box}))}};function $a(t,e){let n=t.x-e.x,s=t.y-e.y,i=t.hw+e.hw-Math.abs(n),r=t.hh+e.hh-Math.abs(s);return i<=1e-9||r<=1e-9?ru():i0?e.fixedStep:1/120;return{gx:n.x||0,gy:n.y||0,fixedStep:s}}function Ka(t,e,n,s){t.vx+=e*s,t.vy+=n*s,t.px+=t.vx*s,t.py+=t.vy*s}function au(t,e,n){let{gx:s,gy:i,fixedStep:r}=Qa(n),a={px:t.px,py:t.py,vx:t.vx,vy:t.vy},o=e>0?e:0;for(;o>=r-1e-12;)Ka(a,s,i,r),o-=r;return o>1e-12&&Ka(a,s,i,o),a}var hi=class{constructor(e,n){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy};let s=Qa(n);this._gx=s.gx,this._gy=s.gy,this._fixedStep=s.fixedStep}get state(){return{px:this._s.px,py:this._s.py,vx:this._s.vx,vy:this._s.vy}}step(e){let n=au(this._s,e,{gravity:{x:this._gx,y:this._gy},fixedStep:this._fixedStep});return this._s=n,this.state}reset(e){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy}}};function Za(t,e,n,s){let i=n.mass==null?1:n.mass,r=n.stiffness,a=n.damping,o=t.x,c=t.v,l=s>0?s:0;if(l<=1e-12)return{x:o,v:c};let u=i>1e-12?i:1e-12,h=Math.sqrt(Math.max(0,r)/u),f=a/u,d=h>1e-12?.2/h:l,p=f>1e-12?.5/f:l,y=Math.max(1e-12,Math.min(d,p)),x=Math.ceil(l/y);(!Number.isFinite(x)||x<1)&&(x=1),x>4096&&(x=4096);let w=l/x;for(let A=0;A1?1:t}var lu=t=>(t=Ke(t),t*t),uu=t=>(t=Ke(t),1-(1-t)*(1-t)),du=t=>(t=Ke(t),t<.5?2*t*t:1-Math.pow(-2*t+2,2)/2),fu=t=>(t=Ke(t),t*t*t),hu=t=>{t=Ke(t);let e=1-t;return 1-e*e*e},pu=t=>(t=Ke(t),t<.5?4*t*t*t:1-Math.pow(-2*t+2,3)/2),nc=2*Math.PI/3,tc=2*Math.PI/4.5,mu=t=>(t=Ke(t),t===0?0:t===1?1:-Math.pow(2,10*t-10)*Math.sin((t*10-10.75)*nc)),yu=t=>(t=Ke(t),t===0?0:t===1?1:Math.pow(2,-10*t)*Math.sin((t*10-.75)*nc)+1),gu=t=>(t=Ke(t),t===0?0:t===1?1:t<.5?-(Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*tc))/2:Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*tc)/2+1),yi=1.70158,pi=yi*1.525,sc=yi+1,bu=t=>(t=Ke(t),sc*t*t*t-yi*t*t),xu=t=>{t=Ke(t);let e=t-1;return 1+sc*e*e*e+yi*e*e},Su=t=>(t=Ke(t),t<.5?Math.pow(2*t,2)*((pi+1)*2*t-pi)/2:(Math.pow(2*t-2,2)*((pi+1)*(t*2-2)+pi)+2)/2),vu=t=>Ke(t),Ro=Object.freeze({linear:vu,quadIn:lu,quadOut:uu,quadInOut:du,cubicIn:fu,cubicOut:hu,cubicInOut:pu,elasticIn:mu,elasticOut:yu,elasticInOut:gu,backIn:bu,backOut:xu,backInOut:Su}),Mo=Ro,wu=["linear","quadIn","quadOut","quadInOut","cubicIn","cubicOut","cubicInOut","elasticIn","elasticOut","elasticInOut","backIn","backOut","backInOut"];function Tu(t){let e=t&&t.easing;if(!e)return Ro;let n=i=>typeof e[i]=="function"?r=>e[i](Ke(r)):Ro[i],s={};for(let i of wu)s[i]=n(i);return Object.freeze(s)}var Po=class{constructor(e,n,s){let i=s||{};this._time=n,this._windowMs=typeof i.windowMs=="number"&&i.windowMs>0?i.windowMs:120;let r=Array.isArray(i.types)&&i.types.length>0?i.types:cu;this._records=new Map,this._subs=[],this._disposed=!1;for(let a of r){this._records.set(a,null);let o=e.on(a,c=>{this._records.set(a,c.tMs)});this._subs.push(o)}}consume(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs?(this._records.set(e,null),!0):(this._records.set(e,null),!1)}peek(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs}clear(){for(let e of this._records.keys())this._records.set(e,null)}dispose(){if(!this._disposed){for(let e of this._subs)try{e.cancel()}catch(n){}this._subs=[],this._disposed=!0}}};var mi=class{constructor(e,n){let s=n||{};this._time=e,this._windowMs=typeof s.windowMs=="number"&&s.windowMs>0?s.windowMs:500,this._maxCount=typeof s.maxCount=="number"&&s.maxCount>0?s.maxCount:1/0,this._count=0,this._lastHitAt=null}hit(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt!=null&&n-this._lastHitAt<=this._windowMs&&this._count>0?this._count=Math.min(this._count+1,this._maxCount):this._count=1,this._lastHitAt=n,this._count}getCount(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt==null||n-this._lastHitAt>this._windowMs?0:this._count}reset(){this._count=0,this._lastHitAt=null}};function ic(t){let e=t||{},n=null,s=null,i=!1;return{name:"gamefeel",version:"1.0.0",dependencies:[],get inputBuffer(){return n},get easing(){return Tu(s)},init(a){let o=a.getInput();n=new Po(o,a.time,{windowMs:e.inputBufferMs,types:e.inputTypes});let c=a.getEngine();s=c?c.math:null},dispose(){i||(n&&(n.dispose(),n=null),s=null,i=!0)}}}function gi(t,e){let n=e<0?0:e>1?1:e;switch(t&&t.kind){case"constant":return t.value;case"linear":return t.from+(t.to-t.from)*n;case"easeInOut":{let s=n*n*(3-2*n);return t.from+(t.to-t.from)*s}case"decay":{let s=t.power==null?2:t.power,i=Math.pow(1-n,s);return t.to+(t.from-t.to)*i}default:return 0}}var Au=Object.freeze({burst:Object.freeze({mode:"burst",count:24,angle:0,spread:Math.PI,speedMin:80,speedMax:160,lifeMin:.4,lifeMax:.8,gravity:0,drag:0,sizeCurve:{kind:"decay",from:6,to:0,power:1.5},alphaCurve:{kind:"linear",from:1,to:0}}),trail:Object.freeze({mode:"continuous",rate:60,angle:Math.PI,spread:.25,speedMin:20,speedMax:50,lifeMin:.2,lifeMax:.5,gravity:0,drag:1.5,sizeCurve:{kind:"easeInOut",from:4,to:0},alphaCurve:{kind:"decay",from:.8,to:0,power:2}}),drift:Object.freeze({mode:"continuous",rate:12,angle:Math.PI/2,spread:.6,speedMin:10,speedMax:30,lifeMin:1.5,lifeMax:3,gravity:8,drag:.5,sizeCurve:{kind:"constant",value:3},alphaCurve:{kind:"decay",from:.7,to:0,power:1}})});function ku(t){let e=Au[t];return e?Lo(e):null}function Lo(t){let e={};for(let n of Object.keys(t)){let s=t[n];e[n]=s&&typeof s=="object"?Lo(s):s}return e}function Cu(t,e,n){let s=t.mode==="continuous";return{pos:{x:e,y:n},angle:t.angle,coneAngle:t.spread,emitSize:0,emitTime:s?0:1/60,emitRate:s?t.rate||0:void 0,count:s?void 0:t.count||0,particleTime:(t.lifeMin+t.lifeMax)/2,speed:(t.speedMin+t.speedMax)/2,gravityScale:t.gravity||0,damping:t.drag!=null?1-t.drag/60:1,sizeStart:gi(t.sizeCurve,0),sizeEnd:gi(t.sizeCurve,1),colorStart:{r:1,g:1,b:1,a:gi(t.alphaCurve,0)},colorEnd:{r:1,g:1,b:1,a:gi(t.alphaCurve,1)},additive:!1}}function bi(t){let e=t||{},n=null,s=null,i=null,r=new Map,a=0,o={isActive(){return!1},stop(){}},c=0,l=1,u=0,h=0,f=0,d={x:0,y:0,remain:0,dur:0,amplitude:0,frequency:0,_phase:0},p={alpha:0,remain:0,dur:0,peak:0},y={scale:1,remain:0,dur:0,amplitude:0,frequency:0},x=!1;function w(k){if(u>0)if(u-=k,u<=0)u=0,l=1;else{let C=h>0?1-u/h:1;l=f+(1-f)*C}if(d.remain>0)if(d.remain-=k,d.remain<=0)d.remain=0,d.x=0,d.y=0;else{let C=d.remain/d.dur,L=d.amplitude*C;d._phase+=d.frequency*k*Math.PI*2,d.x=Math.sin(d._phase)*L,d.y=Math.cos(d._phase*1.3)*L}if(p.remain>0&&(p.remain-=k,p.remain<=0?(p.remain=0,p.alpha=0):p.alpha=p.peak*(p.remain/p.dur)),y.remain>0)if(y.remain-=k,y.remain<=0)y.remain=0,y.scale=1;else{let C=y.remain/y.dur,L=(1-C)*y.frequency*Math.PI*2;y.scale=1+Math.sin(L)*y.amplitude*C}}function A(k){c+=1,w(k)}function S(k){let C=k!==void 0?k:n?n.getContext2d():null;if(C&&p.alpha>0){C.globalAlpha=p.alpha,C.fillStyle="#ffffff";let L=C.canvas?C.canvas.width:0,N=C.canvas?C.canvas.height:0;C.fillRect(0,0,L,N),C.globalAlpha=1}}return{name:"particles-juice",version:"1.0.0",dependencies:[],init(k){var C;n=k,i=((C=k.getEngine())==null?void 0:C.particles)||null,typeof e.seed=="number"&&k.random.reseed(e.seed),e.autoStep!==!1&&(s=k.onFrame(L=>{A(L)}))},dispose(){x||(s&&(s.cancel(),s=null),r.forEach(k=>{try{k.stop()}catch{}}),r.clear(),l=1,u=0,d.remain=0,d.x=0,d.y=0,p.remain=0,p.alpha=0,y.remain=0,y.scale=1,x=!0)},spawnEmitter(k,C,L,N){let ae=typeof k=="string"?ku(k):Lo(k);if(!ae)return-1;N&&(ae=Object.assign(ae,N));let Z=a++;if(!i)return r.set(Z,o),Z;let T=i.spawnEmitter(Cu(ae,C,L));return r.set(Z,T),Z},stopEmitter(k){let C=r.get(k);if(C)try{C.stop()}catch{}},step(k){A(k)},render(k){S(k)},particleCount(){return 0},emitterCount(){let k=0;for(let C of r.values())C.isActive()&&(k+=1);return k},hitStop(k,C){h=Math.max(0,k),u=h,f=C==null?0:Math.max(0,Math.min(1,C)),l=h>0?f:1},getTimeScale(){return l},shakeScreen(k,C,L){d.dur=Math.max(0,k),d.remain=d.dur,d.amplitude=Math.max(0,C),d.frequency=L==null?30:L,d._phase=0,d.x=0,d.y=0},getShakeOffset(){return{x:d.x,y:d.y}},flashScreen(k,C){p.dur=Math.max(0,k),p.remain=p.dur,p.peak=C==null?.8:Math.max(0,Math.min(1,C)),p.alpha=p.dur>0?p.peak:0},getFlashAlpha(){return p.alpha},pulseScale(k,C,L){y.dur=Math.max(0,k),y.remain=y.dur,y.amplitude=C==null?.2:C,y.frequency=L==null?4:L,y.scale=1},getPulseScale(){return y.scale},juiceSnapshot(){return{timeScale:l,shake:{x:d.x,y:d.y},flashAlpha:p.alpha,pulseScale:y.scale}},probe(){return{particles:0,emitters:r.size,dropped:0,steps:c,disposed:x}}}}function oc(t){let e=Ae(t.r)/255,n=Ae(t.g)/255,s=Ae(t.b)/255,i=Math.max(e,n,s),r=Math.min(e,n,s),a=(i+r)/2,o=0,c=0,l=i-r;return l>1e-12&&(c=a>.5?l/(2-i-r):l/(i+r),i===e?o=(n-s)/l%6:i===n?o=(s-e)/l+2:o=(e-n)/l+4,o*=60,o<0&&(o+=360)),{h:o,s:c,l:a}}function rc(t){let e=(t.h%360+360)%360,n=ln(t.s),s=ln(t.l);if(n<1e-12){let o=Math.round(s*255);return{r:o,g:o,b:o}}let i=s<.5?s*(1+n):s+n-s*n,r=2*s-i,a=e/360;return{r:Math.round(Oo(r,i,a+1/3)*255),g:Math.round(Oo(r,i,a)*255),b:Math.round(Oo(r,i,a-1/3)*255)}}function Oo(t,e,n){let s=n;return s<0&&(s+=1),s>1&&(s-=1),s<1/6?t+(e-t)*6*s:s<1/2?e:s<2/3?t+(e-t)*(2/3-s)*6:t}function Ae(t){return t<0?0:t>255?255:t}function ln(t){return t<0?0:t>1?1:t}function Go(t,e){let n=Eu(t.from,e);if(n>=0&&n({r:Ae(o.r),g:Ae(o.g),b:Ae(o.b)})),to:r}}function Do(t,e,n){return t+(e-t)*n}function jo(t,e){let n=oc(t),s=n.h+(e.hue||0),i=ln(n.s*(e.sat==null?1:e.sat)),r=ln(n.l*(e.light==null?1:e.light));return rc({h:s,s:i,l:r})}var Pu=Object.freeze([Object.freeze([0,8,2,10]),Object.freeze([12,4,14,6]),Object.freeze([3,11,1,9]),Object.freeze([15,7,13,5])]);function ac(t){let e=t||{},n=null,s=!1,i={vignette:{enabled:Io(e.vignette&&e.vignette.enabled,!1),strength:Fo(e.vignette&&e.vignette.strength,.5)},dither:{enabled:Io(e.dither&&e.dither.enabled,!1),strength:Fo(e.dither&&e.dither.strength,.5)},scanline:{enabled:Io(e.scanline&&e.scanline.enabled,!1),strength:Fo(e.scanline&&e.scanline.strength,.5)}};function r(o){let c=o!==void 0?o:n?n.getContext2d():null;if(!c)return;let l=c.canvas?c.canvas.width:0,u=c.canvas?c.canvas.height:0;if(i.vignette.enabled&&i.vignette.strength>0&&l>0&&u>0){let h=c.createRadialGradient(l/2,u/2,Math.min(l,u)*.25,l/2,u/2,Math.max(l,u)*.75);h.addColorStop(0,"rgba(0,0,0,0)"),h.addColorStop(1,"rgba(0,0,0,"+i.vignette.strength.toFixed(3)+")"),c.fillStyle=h,c.fillRect(0,0,l,u)}if(i.scanline.enabled&&i.scanline.strength>0&&l>0&&u>0){c.fillStyle="rgba(0,0,0,"+(i.scanline.strength*.5).toFixed(3)+")";for(let h=0;h0&&l>0&&u>0&&typeof c.getImageData=="function"&&typeof c.putImageData=="function"){let h=c.getImageData(0,0,l,u);Mu(h,i.dither.strength),c.putImageData(h,0,0)}}return{name:"palette-post",version:"1.0.0",dependencies:[],init(o){n=o},dispose(){s||(n=null,s=!0)},applyPaletteMap(o,c){return Go(o,c)},applyPaletteMapToBuffer(o,c){return _u(o,c)},lerpPaletteMap(o,c,l){return Bo(o,c,l)},shiftHsl(o,c){return jo(o,c)},rgbToHsl(o){return oc(o)},hslToRgb(o){return rc(o)},setPost(o){if(o)for(let c of["vignette","dither","scanline"])o[c]&&(typeof o[c].enabled=="boolean"&&(i[c].enabled=o[c].enabled),typeof o[c].strength=="number"&&(i[c].strength=ln(o[c].strength)))},getPost(){return{vignette:{enabled:i.vignette.enabled,strength:i.vignette.strength},dither:{enabled:i.dither.enabled,strength:i.dither.strength},scanline:{enabled:i.scanline.enabled,strength:i.scanline.strength}}},renderPost(o){r(o)},probe(){return{disposed:s,post:this.getPost()}}}}function Mu(t,e){let n=ln(e);if(n<=0)return t;let{data:s,width:i}=t,a=255/(Math.max(2,Math.round(16-n*14))-1);for(let o=0;o+3>2)%i,l=Math.floor((o>>2)/i),u=(Pu[l&3][c&3]/16-.5)*a;for(let h=0;h<3;h++){let f=s[o+h]+u,d=Math.round(f/a)*a;s[o+h]=d<0?0:d>255?255:d}}return t}function Io(t,e){return typeof t=="boolean"?t:e}function Fo(t,e){return typeof t=="number"?ln(t):e}var No=Object.freeze({blip:Object.freeze({name:"blip",params:Object.freeze([.6,0,880,0,.03,.06,1,1.5])}),thud:Object.freeze({name:"thud",params:Object.freeze([.8,0,90,0,.04,.18,0,1,0,0,0,0,0,4])}),chime:Object.freeze({name:"chime",params:Object.freeze([.5,0,660,.02,.12,.3,1,2])})}),cc=Object.keys(No);function Lu(t){let e=[];return t==null||typeof t!="object"?{ok:!1,errors:["song \u5FC5\u987B\u662F\u5BF9\u8C61"]}:(!Array.isArray(t.instruments)||t.instruments.length===0?e.push("instruments \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.instruments.forEach((n,s)=>{(!Array.isArray(n)||n.some(i=>typeof i!="number"||!Number.isFinite(i)))&&e.push(`instruments[${s}] \u5FC5\u987B\u662F\u6709\u9650\u6570\u5B57\u6570\u7EC4\uFF08ZzFX \u53C2\u6570\u5305\uFF09`)}),!Array.isArray(t.patterns)||t.patterns.length===0?e.push("patterns \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.patterns.forEach((n,s)=>{if(!Array.isArray(n)||n.length===0){e.push(`patterns[${s}] \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF08\u81F3\u5C11\u4E00\u4E2A\u58F0\u90E8\u901A\u9053\uFF09`);return}n.forEach((i,r)=>{if(!Array.isArray(i)||i.length<2){e.push(`patterns[${s}][${r}] \u901A\u9053\u81F3\u5C11\u542B [\u4E50\u5668\u7D22\u5F15, \u58F0\u50CF]`);return}if(i.some(c=>typeof c!="number"||!Number.isFinite(c))){e.push(`patterns[${s}][${r}] \u901A\u9053\u5FC5\u987B\u5168\u4E3A\u6709\u9650\u6570\u5B57`);return}let a=i[0]|0;Array.isArray(t.instruments)&&(a<0||a>=t.instruments.length)&&e.push(`patterns[${s}][${r}] \u4E50\u5668\u7D22\u5F15 ${a} \u8D8A\u754C\uFF08instruments \u957F\u5EA6 ${t.instruments.length}\uFF09`);let o=i[1];(o<-1||o>1)&&e.push(`patterns[${s}][${r}] \u58F0\u50CF ${o} \u8D8A\u754C\uFF08\u5E94 -1..+1\uFF09`)})}),!Array.isArray(t.sequence)||t.sequence.length===0?e.push("sequence \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.sequence.forEach((n,s)=>{if(typeof n!="number"||!Number.isInteger(n)){e.push(`sequence[${s}] \u5FC5\u987B\u662F\u6574\u6570 pattern \u7D22\u5F15`);return}Array.isArray(t.patterns)&&(n<0||n>=t.patterns.length)&&e.push(`sequence[${s}] \u7D22\u5F15 ${n} \u8D8A\u754C\uFF08patterns \u957F\u5EA6 ${t.patterns.length}\uFF09`)}),t.bpm!=null&&(typeof t.bpm!="number"||!(t.bpm>0))&&e.push("bpm \u5FC5\u987B\u662F\u6B63\u6570"),{ok:e.length===0,errors:e})}function Et(t){return typeof t!="number"||Number.isNaN(t)||t<0?0:t>1?1:t}function Ou(t,e){switch(t){case"ease-in":return e*e;case"ease-out":return Math.sqrt(e);case"constant":return 1;default:return e}}function lc(t,e){let n=Et(e);return t==null||!Array.isArray(t.voices)?[]:t.voices.map(s=>{let i=String(s&&s.id!=null?s.id:""),r=Array.isArray(s&&s.channelIndices)?s.channelIndices.slice():[],a=typeof s.minIntensity=="number"?Et(s.minIntensity):0,o=typeof s.maxIntensity=="number"?Et(s.maxIntensity):1,c=typeof s.volumeCurve=="string"?s.volumeCurve:"linear",l=typeof s.baseVolume=="number"?Et(s.baseVolume):1;if(no)return{id:i,on:!1,volume:0,channelIndices:r};let u=o-a,h=u<=0?1:(n-a)/u,f=Et(Ou(c,h)*l);return{id:i,on:!0,volume:f,channelIndices:r}})}function uc(t,e,n,s){try{let i=e[0]||[],r=e[1]||i,a=Math.max(i.length,r.length);if(a===0)return null;let c=t.createBuffer(2,a,44100);c.getChannelData(0).set(i),c.getChannelData(1).set(r.length?r:i);let l=t.createBufferSource();l.buffer=c,l.loop=!!s;let u=t.createGain();return u.gain.value=Et(n*.3),l.connect(u),u.connect(t.destination),l.start(),{stop(){try{l.stop()}catch(h){}try{l.disconnect(),u.disconnect()}catch(h){}}}}catch(i){return zo("[audio-music] \u53D7\u63A7\u97F3\u9891\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",i),null}}function dc(t){let e=t||{},n=typeof e.masterVolume=="number"?Et(e.masterVolume):1,s=()=>null,i=null,r=null,a={voices:[]},o=1,c=null,l=!1,u=0,h=!1,f=!1;function d(){let S=s();return S==null?(u+=1,h||(Jo("[audio-music] \u65E0\u53D7\u63A7\u97F3\u9891\u4E0A\u4E0B\u6587\uFF08getAudioContext \u8FD4\u56DE null\uFF09\uFF0C\u5168\u90E8\u53D1\u58F0\u9759\u9ED8 no-op\uFF08\u8BC4\u4F30\u73AF\u5883\u65E0\u58F0\u5361\u65F6\u7684\u5BB9\u9519\u964D\u7EA7\uFF09"),h=!0),null):S}function p(){if(!r||!i)return null;try{let S=typeof r.bpm=="number"&&r.bpm>0?r.bpm:125;return i.synthSong(r.instruments,r.patterns,r.sequence,S)}catch(S){return zo("[audio-music] \u66F2\u8C31\u6E32\u67D3\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",S),null}}function y(){let S=lc(a,o);if(S.length===0)return 1;let _=0;for(let k of S)k.on&&(_=Math.max(_,k.volume));return _}function x(S,_){typeof _=="number"&&(o=Et(_));let k=d();if(k==null||!r)return;w();let C=p();if(!C)return;let L=Et(n*y());c=uc(k,C,L,S),l=!!S&&c!=null}function w(){c&&(c.stop(),c=null),l=!1}return{name:"audio-music",version:"1.0.0",dependencies:[],init(S){s=()=>S.getAudioContext();let _=S.getEngine&&S.getEngine();i=_?_.audio.synth:null},dispose(){f||(w(),f=!0)},loadSong(S){let _=Lu(S);return _.ok?r={instruments:S.instruments,patterns:S.patterns,sequence:S.sequence,bpm:typeof S.bpm=="number"?S.bpm:125}:Jo("[audio-music] \u66F2\u8C31\u6821\u9A8C\u5931\u8D25\uFF0C\u672A\u8F7D\u5165\uFF1A"+_.errors.join("\uFF1B")),_},play(S){x(!1,S)},stop(){w()},loop(S){x(!0,S)},setIntensityLayering(S){a=S&&Array.isArray(S.voices)?{voices:S.voices}:{voices:[]}},setIntensity(S){o=Et(S)},resolveVoices(S){return lc(a,S)},playSfx(S){let _=No[S];if(!_){Jo("[audio-music] \u672A\u77E5\u97F3\u6548\u9884\u8BBE\uFF1A"+String(S));return}let k=d();if(k!=null)try{let C=i?i.synthSfx(_.params):null;if(!C)return;uc(k,[C,C],n,!1)}catch(C){zo("[audio-music] \u97F3\u6548\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8 name="+S,C)}},getPreset(S){return No[S]},listPresets(){return cc.slice()},probe(){return{hasAudio:s()!=null,hasSong:r!=null,intensity:o,voiceCount:a.voices.length,looping:l,silentNoops:u,presetCount:cc.length}}}}function zo(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Jo(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Du="zaomeng.save";function Iu(t){if(typeof TextEncoder!="undefined")return new TextEncoder().encode(t).length;if(typeof Buffer!="undefined"&&typeof Buffer.byteLength=="function")return Buffer.byteLength(t,"utf8");let e=0;for(let n=0;n=55296&&s<=56319?(e+=4,n++):e+=3}return e}function Vo(){let t=new Map;return{getItem(e){return t.has(e)?t.get(e):null},setItem(e,n){t.set(e,n)},removeItem(e){t.delete(e)},keys(){return Array.from(t.keys())}}}function fc(){if(typeof localStorage=="undefined")throw new Error("[save-progress] createLocalStorageAdapter \u9700\u8981\u5168\u5C40 localStorage\uFF08\u4EC5\u6D4F\u89C8\u5668\u96C6\u6210\u6BB5\u53EF\u7528\uFF09\u3002node/host-dev \u8BF7\u7528\u7F3A\u7701\u5185\u5B58 adapter \u6216 createMemoryAdapter()\u3002");return{getItem(t){return localStorage.getItem(t)},setItem(t,e){localStorage.setItem(t,e)},removeItem(t){localStorage.removeItem(t)},keys(){let t=[];for(let e=0;e0?e.namespace:Du;if(n.indexOf(":")>=0)throw new Error('[save-progress] namespace \u4E0D\u5F97\u542B\u5206\u9694\u7B26 ":"\uFF08\u5F53\u524D="'+n+'"\uFF09');let s=typeof e.maxValueBytes=="number"&&e.maxValueBytes>0?Math.floor(e.maxValueBytes):32768,i=!Fu(e.adapter),r=i?Vo():e.adapter,a=n+":",o=0,c=0,l=!1;function u(d){return typeof d!="string"||d.length===0?a+String(d):a+d}function h(){try{let d=r.keys();return Array.isArray(d)?d.filter(p=>typeof p=="string"&&p.indexOf(a)===0):[]}catch(d){return ws("[save-progress] adapter.keys() \u5F02\u5E38\uFF0C\u964D\u7EA7\u8FD4\u56DE\u7A7A\u96C6",d),[]}}return{name:"save-progress",version:"1.0.0",dependencies:[],init(d){h()},dispose(){},get(d,p){if(!Uo(d))return p;let y;try{y=r.getItem(u(d))}catch(x){return ws("[save-progress] adapter.getItem \u5F02\u5E38\uFF0C\u8FD4\u56DE\u9ED8\u8BA4\u503C key="+d,x),p}if(y==null)return p;try{return JSON.parse(y)}catch{return o+=1,l||(Ts("[save-progress] \u68C0\u6D4B\u5230\u635F\u574F\u5B58\u6863\uFF08\u975E\u6CD5 JSON\uFF09\uFF0C\u5DF2\u5BB9\u9519\u56DE\u9000\u9ED8\u8BA4\u503C key="+d),l=!0),p}},set(d,p){if(!Uo(d))return Ts("[save-progress] set \u6536\u5230\u975E\u6CD5 key\uFF0C\u62D2\u7EDD\u5199\u5165\uFF1A"+String(d)),!1;let y;try{y=JSON.stringify(p)}catch{return c+=1,Ts("[save-progress] \u503C\u4E0D\u53EF JSON \u5E8F\u5217\u5316\uFF08\u5FAA\u73AF\u5F15\u7528?\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+d),!1}if(y===void 0)return c+=1,Ts("[save-progress] \u503C\u5E8F\u5217\u5316\u4E3A undefined\uFF08\u5982\u7EAF undefined/\u51FD\u6570\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+d),!1;let x=Iu(y);if(x>s)return c+=1,Ts("[save-progress] \u503C\u8D85\u5B57\u8282\u4E0A\u9650\u62D2\u7EDD\u5199\u5165 key="+d+"\uFF08"+x+" > "+s+" bytes\uFF09"),!1;try{return r.setItem(u(d),y),!0}catch(w){return c+=1,ws("[save-progress] adapter.setItem \u5F02\u5E38\uFF0C\u5199\u5165\u5931\u8D25 key="+d,w),!1}},remove(d){if(Uo(d))try{r.removeItem(u(d))}catch(p){ws("[save-progress] adapter.removeItem \u5F02\u5E38\uFF08\u5DF2\u5FFD\u7565\uFF09key="+d,p)}},clear(){let d=h(),p=0;for(let y of d)try{r.removeItem(y),p+=1}catch(x){ws("[save-progress] clear \u65F6 removeItem \u5F02\u5E38\uFF08\u5DF2\u8DF3\u8FC7\uFF09fullKey="+y,x)}return p},probe(){return{namespace:n,maxValueBytes:s,usingMemoryAdapter:i,size:h().length,corruptRecoveries:o,rejectedWrites:c}}}}function Uo(t){return typeof t=="string"&&t.length>0}function Fu(t){return!!t&&typeof t.getItem=="function"&&typeof t.setItem=="function"&&typeof t.removeItem=="function"&&typeof t.keys=="function"}function ws(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Ts(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Zn=[{id:"soda",name:"\u6C7D\u6C34",wholesale:20,basePrice:40,popularity:1,initial:!0},{id:"snack",name:"\u8FA3\u6761",wholesale:10,basePrice:25,popularity:1.2,initial:!0},{id:"bread",name:"\u9762\u5305",wholesale:30,basePrice:60,popularity:.8,initial:!0},{id:"ice",name:"\u51B0\u6DC7\u6DCB",wholesale:40,basePrice:90,popularity:.7,initial:!1},{id:"toy",name:"\u5C0F\u73A9\u5177",wholesale:80,basePrice:180,popularity:.35,initial:!1}];function Qe(t){return Zn.find(e=>e.id===t)}var Me={lengthSec:96,rushStartSec:30,rushEndSec:66,rushRampSec:3,daysPerSegment:3};function pc(t){let{rushStartSec:e,rushEndSec:n,rushRampSec:s}=Me;return t<=e-s||t>=n+s?0:t>=e&&t<=n?1:te.id===t)}function Ho(t){let e=n=>!!t[n];return{shelfCap:e("shelf2")?48:e("shelf1")?34:24,serveCooldownSec:e("speed2")?.32:e("speed1")?.42:.55,patienceMul:e("decor2")?1.3:e("decor1")?1.15:1,settleRepBonusTenth:e("decor2")?60:e("decor1")?30:0,flowMul:e("decor2")?1.12:1}}function Si(t){let e=t.priceMul,n=t.reputation==null?Ze.start:t.reputation,s=t.serveCapacity==null?26:t.serveCapacity,i=t.stockUnits==null?1/0:t.stockUnits,r=t.segment==null?1:t.segment,a=t.unlocked||Zn.filter(x=>x.initial).map(x=>x.id),l=((Me.lengthSec-(Me.rushEndSec-Me.rushStartSec))/un.idleIntervalSec+(Me.rushEndSec-Me.rushStartSec)/un.rushIntervalSec)*Wo(e)*qo(n),u=Math.min(l,s,i),h=a.map(x=>Qe(x)).filter(Boolean),f=h.reduce((x,w)=>x+w.popularity,0),d=h.reduce((x,w)=>x+(Math.round(w.basePrice*e)-w.wholesale)*(w.popularity/f),0),p=Math.round(u*d),y=ce.rentBaseJiao+(r-1)*ce.rentPerSegmentJiao;return{arrivals:l,served:u,grossJiao:p,rentJiao:y,profitJiao:p-y}}function We(t,e,n){return tn?n:t}function et(t){let e=t/10;return Number.isInteger(e)?String(e):e.toFixed(1)}var gc=1,Gu=2600;function As(t){let e=t.random;if(!e||typeof e.next!="function")throw new Error("[shop-core] \u5FC5\u987B\u6CE8\u5165\u53D7\u63A7\u968F\u673A\u6E90 random\uFF08next/range/reseed\uFF09");let n=0,s={nowMs:()=>n,elapsedMs:()=>n},i=new mi(s,{windowMs:Gu,maxCount:99}),r=[];function a(T,P){r.push(Object.assign({type:T,tMs:Math.round(n)},P||{}))}let o={phase:"title",day:1,cash:ce.startCashJiao,repTenth:Ze.start*10,priceMul:1,stock:{},unlocked:Zn.filter(T=>T.initial).map(T=>T.id),upgrades:{},customers:[],dayTimeSec:0,rushFactor:0,serveCooldown:0,comboCount:0,prepBought:{},today:c(),lifetime:{days:0,served:0,angry:0,netJiao:0,upgradesBought:0},settle:null,summary:null,gameoverReason:null};function c(){return{revenueJiao:0,soldCostJiao:0,served:0,angry:0,stockout:0,walkaway:0,rescued:0,bigSales:0,maxCombo:0}}let l=1,u=0,h=!1,f=Ho(o.upgrades);function d(){f=Ho(o.upgrades)}function p(){let T=0;for(let P of Object.keys(o.stock))T+=o.stock[P];return T}function y(){return o.repTenth/10}function x(T){o.repTenth=We(o.repTenth+T,0,Ze.max*10)}function w(T){let P=o.phase;o.phase=T,a("phase_changed",{from:P,to:T})}function A(T){o.day=T,o.prepBought={},o.today=c(),o.customers=[],o.dayTimeSec=0,o.rushFactor=0,o.settle=null,o.summary=null,w("prep"),a("save_point",{})}function S(){let T=o.rushFactor>.5?un.rushIntervalSec:un.idleIntervalSec,P=Wo(o.priceMul)*qo(y())*f.flowMul;u=T/Math.max(P,.05)*e.range(un.jitterMin,un.jitterMax)}function _(){let T=o.unlocked.map(M=>Qe(M)),P=T.reduce((M,B)=>M+B.popularity,0),R=e.next()*P;for(let M of T)if(R-=M.popularity,R<=0)return M.id;return T[T.length-1].id}function k(){for(let T=0;TP.slot===T))return T;return-1}function C(){let T=_(),P=k();if(P<0){o.today.walkaway+=1,a("walkaway_full",{productId:T});return}let M=(o.rushFactor>.5?En.rushSec:En.idleSec)*f.patienceMul*e.range(.9,1.12),B={id:l++,productId:T,slot:P,mood:"queue",patienceSec:M,patienceMaxSec:M,timerSec:0,avatar:Math.floor(e.next()*4)%4,impatientFired:!1};(o.stock[T]||0)<=0&&(B.mood="stockout",B.timerSec=En.stockoutLingerSec),o.customers.push(B),a("customer_arrive",{id:B.id,slot:P,productId:T,mood:B.mood})}function L(T){let P=o.customers.indexOf(T);P>=0&&o.customers.splice(P,1)}function N(T){o.dayTimeSec+=T,o.rushFactor=pc(o.dayTimeSec);let P=o.rushFactor>.5;if(P!==h&&(a(P?"rush_start":"rush_end",{}),h=P),o.serveCooldown>0&&(o.serveCooldown=Math.max(0,o.serveCooldown-T)),o.dayTimeSec>=Me.lengthSec){a("closing",{}),o.customers=[],ae();return}u-=T,u<=0&&(C(),S());for(let R=o.customers.length-1;R>=0;R--){let M=o.customers[R];if(M.mood==="queue"){if((o.stock[M.productId]||0)<=0){M.mood="stockout",M.timerSec=En.stockoutLingerSec;continue}M.patienceSec-=T,!M.impatientFired&&M.patienceSec/M.patienceMaxSec<=En.impatientRatio&&(M.impatientFired=!0,a("customer_impatient",{id:M.id,slot:M.slot})),M.patienceSec<=0&&(M.mood="leaving",M.timerSec=En.graceSec,a("customer_grace",{id:M.id,slot:M.slot}))}else M.mood==="leaving"?(M.timerSec-=T,M.timerSec<=0&&(L(M),o.today.angry+=1,x(-Ze.angryLossTenth),a("angry_leave",{id:M.id,slot:M.slot,avatar:M.avatar,productId:M.productId,repLossTenth:Ze.angryLossTenth}))):M.mood==="stockout"&&(M.timerSec-=T,M.timerSec<=0&&(L(M),o.today.stockout+=1,x(-Ze.stockoutLossTenth),a("stockout_leave",{id:M.id,slot:M.slot,avatar:M.avatar,productId:M.productId,repLossTenth:Ze.stockoutLossTenth})))}o.comboCount=i.getCount(n)}function ae(){let T=o.today,P=Math.ceil(o.day/Me.daysPerSegment),R=ce.rentBaseJiao+(P-1)*ce.rentPerSegmentJiao,M=0;y()P.initial).map(P=>P.id),o.upgrades={},o.lifetime={days:0,served:0,angry:0,netJiao:0,upgradesBought:0},o.gameoverReason=null,d(),i.reset(),a("game_start",{continued:!1}),A(1),{ok:!0,continued:!1})},buyStock(T,P){let R=Math.max(1,Math.floor(P||1));if(o.phase!=="prep")return{ok:!1,reason:"phase"};let M=Qe(T);if(!M||!o.unlocked.includes(T))return{ok:!1,reason:"unknown_product"};if(p()+R>f.shelfCap)return{ok:!1,reason:"shelf_full"};let B=M.wholesale*R;return o.cash0)return{ok:!1,reason:"cooldown"};if(!o.unlocked.includes(T))return{ok:!1,reason:"unknown_product"};if((o.stock[T]||0)<=0)return a("tap_empty",{productId:T}),{ok:!1,reason:"no_stock"};let P=o.customers.filter(V=>V.productId===T&&(V.mood==="queue"||V.mood==="leaving")).sort((V,q)=>V.id-q.id)[0];if(!P)return a("tap_nocustomer",{productId:T}),{ok:!1,reason:"no_customer"};let R=P.mood==="leaving";o.stock[T]-=1;let M=i.hit(n);o.comboCount=M,o.today.maxCombo=Math.max(o.today.maxCombo,M);let B=Math.round(mc(T,o.priceMul)*yc(M));o.cash+=B,o.today.revenueJiao+=B,o.today.soldCostJiao+=Qe(T).wholesale,o.today.served+=1,o.lifetime.served+=1,R&&(o.today.rescued+=1),x(Ze.serveGainTenth+(R?Ze.rescueBonusTenth:0)),o.serveCooldown=f.serveCooldownSec;let ne=B>=ce.bigSaleJiao;return ne&&(o.today.bigSales+=1),L(P),a("serve_ok",{id:P.id,slot:P.slot,avatar:P.avatar,productId:T,revenueJiao:B,combo:M,big:ne,rescued:R}),{ok:!0,revenueJiao:B,combo:M,big:ne,rescued:R,customerId:P.id}},confirmSettle(){if(o.phase!=="settle")return{ok:!1,reason:"phase"};let T=o.day;if(a("save_point",{}),T%Me.daysPerSegment===0){let P=T/Me.daysPerSegment;o.summary={segment:P,days:T,netJiao:o.lifetime.netJiao,served:o.lifetime.served,upgradesBought:o.lifetime.upgradesBought,reputation:y()},w("summary"),a("segment_end",{summary:o.summary})}else A(T+1);return{ok:!0}},confirmSummary(){return o.phase!=="summary"?{ok:!1,reason:"phase"}:(A(o.day+1),{ok:!0})},derived(){return f},reputation:y,totalStock:p,snapshotForSave(){return{v:gc,day:o.day,cash:o.cash,repTenth:o.repTenth,priceMul:o.priceMul,stock:Object.assign({},o.stock),unlocked:o.unlocked.slice(),upgrades:Object.assign({},o.upgrades),lifetime:Object.assign({},o.lifetime)}},restoreFromSave(T){return!T||T.v!==gc||typeof T.day!="number"||typeof T.cash!="number"||typeof T.repTenth!="number"||!T.unlocked||!Array.isArray(T.unlocked)||T.unlocked.length===0?!1:(o.cash=Math.floor(T.cash),o.repTenth=We(Math.floor(T.repTenth),0,Ze.max*10),o.priceMul=We(T.priceMul||1,ce.priceMin,ce.priceMax),o.stock=Object.assign({},T.stock||{}),o.unlocked=T.unlocked.filter(P=>!!Qe(P)),o.upgrades=Object.assign({},T.upgrades||{}),o.lifetime=Object.assign({days:0,served:0,angry:0,netJiao:0,upgradesBought:0},T.lifetime||{}),o.gameoverReason=null,d(),i.reset(),a("game_start",{continued:!0}),A(Math.max(1,Math.floor(T.day))),!0)}};return Z}var ks={open_shop:["\u5F00\u5F20\u55BD\u2014\u2014\u8857\u574A\u4EEC\u90FD\u7B49\u7740\u5462\uFF01","\u4ECA\u513F\u4E2A\u8FDB\u70B9\u5565\u597D\u8D27\uFF1F\u6211\u5FC3\u91CC\u6709\u6570\u3002","\u5C0F\u672C\u751F\u610F\uFF0C\u8D26\u53EF\u5F97\u7B97\u660E\u767D\u54AF\u3002"],day_start:["\u5F00\u95E8\u8FCE\u5BA2\uFF01\u90FD\u9EBB\u5229\u70B9\u513F~","\u54DF\uFF0C\u4ECA\u5929\u592A\u9633\u4E0D\u9519\uFF0C\u51C6\u662F\u4E2A\u597D\u65E5\u5B50\u3002"],idle_chat:["\u6162\u60A0\u60A0\u7684\u4E0B\u5348\uFF0C\u6700\u9002\u5408\u76D8\u8D26\u5566\u3002","\u9694\u58C1\u8001\u674E\u53C8\u6765\u8D4A\u8D26\uFF1F\u60F3\u5F97\u7F8E\u3002","\u8D27\u67B6\u64E6\u5F97\u9503\u4EAE\uFF0C\u770B\u7740\u5C31\u8212\u5766\u3002"],rush_start:["\u653E\u5B66\u5566\u653E\u5B66\u5566\uFF0C\u6253\u8D77\u7CBE\u795E\u6765\uFF01","\u4EBA\u90FD\u6D8C\u8FC7\u6765\u4E86\uFF0C\u624B\u4E0A\u522B\u505C\uFF01"],serve_ok:["\u597D\u561E\uFF0C\u62FF\u7A33\u5F53\uFF01","\u60A8\u6162\u8D70\uFF0C\u5E38\u6765\u554A~","\u8FD9\u5C31\u7ED9\u60A8\u62FF\uFF0C\u5FEB\u5F97\u5F88\uFF01"],combo_hot:["\u624B\u611F\u6765\u4E86\uFF0C\u8C01\u90FD\u522B\u62E6\u6211\uFF01","\u4E00\u4E2A\u63A5\u4E00\u4E2A\uFF0C\u8D8A\u5E72\u8D8A\u987A\u6E9C\uFF01"],big_sale:["\u54CE\u54DF\uFF0C\u5927\u4E3B\u987E\uFF01\u4ECA\u665A\u52A0\u4E2A\u9E21\u817F\uFF01","\u8FD9\u5355\u9876\u534A\u5929\u4E70\u5356\uFF0C\u7F8E\u6ECB\u6ECB~"],rescue:["\u522B\u8D70\u522B\u8D70\uFF0C\u8FD9\u5C31\u7ED9\u60A8\u62FF\u4E0A\uFF01","\u597D\u9669\u597D\u9669\uFF0C\u5DEE\u70B9\u513F\u9EC4\u4E86\u4E00\u5355\u3002"],angry:["\u54CE\u5440\uFF0C\u628A\u4EBA\u667E\u8DD1\u4E86\u2026\u2026\u5FC3\u75BC\u3002","\u7838\u62DB\u724C\u4E86\u7838\u62DB\u724C\u4E86\uFF0C\u5F97\u4E0A\u70B9\u5FC3\uFF01"],stockout:["\u7A7A\u8D27\u67B6\u6700\u6233\u5FC3\u7A9D\u5B50\uFF0C\u660E\u513F\u591A\u5907\u70B9\u3002","\u53C8\u5356\u65AD\u4E86\u2026\u2026\u662F\u597D\u4E8B\u4E5F\u662F\u574F\u4E8B\u3002"],settle_win:["\u4ECA\u513F\u8D26\u9762\u7EA2\u706B\uFF0C\u8BB0\u4E0A\u8BB0\u4E0A\uFF01","\u8F9B\u82E6\u4E00\u5929\uFF0C\u503C\u5F53\uFF01"],settle_lose:["\u8FD9\u8D26\u2026\u2026\u8D8A\u7B97\u8D8A\u5FC3\u51C9\u3002","\u7F5A\u5355\u90FD\u8D34\u8138\u4E0A\u4E86\uFF0C\u660E\u5929\u5F97\u6362\u4E2A\u6D3B\u6CD5\u3002"],upgrade:["\u820D\u4E0D\u5F97\u5B69\u5B50\u5957\u4E0D\u7740\u72FC\uFF0C\u5347\uFF01","\u9E1F\u67AA\u6362\u70AE\uFF0C\u54B1\u4E5F\u8BB2\u7A76\u4E00\u56DE\uFF01"],gameover:["\u5509\u2026\u2026\u5377\u5E18\u95E8\u4E00\u62C9\uFF0C\u4ECE\u5934\u518D\u6765\u5427\u3002"]},bp=Object.keys(ks).length;function bc(t){let e={};return function(s){let i=ks[s];if(!i||i.length===0)return"";if(i.length===1)return i[0];let r=Math.floor(t.next()*i.length)%i.length;return r===e[s]&&(r=(r+1)%i.length),e[s]=r,i[r]}}var Cs={paper:{r:246,g:231,b:201},paperHi:{r:255,g:246,b:227},cream:{r:255,g:243,b:220},ink:{r:91,g:70,b:54},inkSoft:{r:138,g:108,b:84},wood:{r:169,g:118,b:79},woodDark:{r:124,g:84,b:55},gold:{r:232,g:169,b:66},coin:{r:246,g:196,b:83},amber:{r:240,g:196,b:117},brick:{r:201,g:111,b:74},danger:{r:178,g:72,b:54},leaf:{r:133,g:158,b:94},sky:{r:243,g:217,b:168},shadow:{r:62,g:49,b:40},scrim:{r:46,g:35,b:27},smoke:{r:140,g:106,b:85}},xc=Object.keys(Cs);function Sc(){let t=xc.map(a=>Cs[a]),e={from:t,to:t.slice()},n={from:t,to:t.map(a=>jo(a,{hue:-10,sat:1.18,light:.9}))},s=0,i=r(0);function r(a){let o=Bo(e,n,a),c={};for(let l of xc)c[l]=Go(o,Cs[l]);return c}return{setRush(a){let o=Math.round(Math.max(0,Math.min(1,a))*25)/25;o!==s&&(s=o,i=r(o))},rushT(){return s},c(a,o){let c=i[a]||Cs.ink,l=o==null?1:o;return l>=1?`rgb(${c.r},${c.g},${c.b})`:`rgba(${c.r},${c.g},${c.b},${l})`},rgb(a){return i[a]||Cs.ink}}}var $o={shopkeeperIdle:"shopkeeper-idle.jpg",shopkeeperWave:"shopkeeper-wave.jpg",customer0:"customer-kid.jpg",customer1:"customer-lady.jpg",customer2:"customer-grandpa.jpg",customer3:"customer-auntie.jpg",storefront:"storefront.jpg",itemSoda:"item-soda.jpg",itemSnack:"item-snack.jpg",itemBread:"item-bread.jpg",itemIce:"item-ice.jpg",itemToy:"item-toy.jpg",uiPanel:"ui-panel.jpg"},Rn={soda:"itemSoda",snack:"itemSnack",bread:"itemBread",ice:"itemIce",toy:"itemToy"};function vc(t){let e=t==null?"./assets/":t,n=Object.keys($o),s={},i=[];function r(a){return new Promise(o=>{if(typeof Image=="undefined"){s[a]=null,i.push(a),o(null);return}let c=new Image;c.onload=()=>{s[a]=c,o(c)},c.onerror=()=>{console.warn("[ref-assets] \u8D44\u4EA7\u52A0\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u7A0B\u5E8F\u5316\u56DE\u9000\uFF09\uFF1A"+$o[a]),s[a]=null,i.push(a),o(null)},c.src=e+$o[a]})}return Promise.all(n.map(r)).then(()=>({images:s,missing:i,loaded:n.length-i.length,total:n.length}))}function wc(t){let e=t.bundle,n=t.juice;function s(T){let P=bi({maxParticles:400});return P.init(e.deriveContextFor(T,T)),P}let i=s("fx-gold"),r=s("fx-cream"),a=s("fx-smoke"),o=[];function c(T,P,R){o.push({t:0,dur:Math.max(T,.001),ease:R&&R.ease||Mo.cubicOut,onUpdate:P,onDone:R&&R.onDone||null})}let l=new Map;function u(T,P){let R=l.get(T);return R||(R={state:{x:P==null?1:P,v:0},target:P==null?1:P,stiffness:320,damping:14},l.set(T,R)),R.state.x}function h(T,P,R){u(T);let M=l.get(T);M.state.v+=P,R!=null&&(M.target=R)}let f=[];function d(T){f.push({t:0,dur:T.dur||.3,fx:T.fx,fy:T.fy,tx:T.tx,ty:T.ty,arc:T.arc==null?46:T.arc,imageKey:T.imageKey||null,label:T.label||"",onArrive:T.onArrive||null})}let p=[],y=980;function x(T){let P=T.dur||.45,R=(T.tx-T.fx)/P,M=(T.ty-T.fy-.5*y*P*P)/P;p.push({proj:new hi({px:T.fx,py:T.fy,vx:R,vy:M},{gravity:{x:0,y}}),age:0,dur:P,tx:T.tx,ty:T.ty,imageKey:T.imageKey||null,onLand:T.onLand||null})}let w=[];function A(T,P,R,M,B){w.push({text:T,x:P,y:R,t:0,dur:.9,colorName:M||"gold",size:B||16})}let S=[];function _(T,P){S.push({x:T,y:P,t:0})}function k(T,P,R){i.spawnEmitter("burst",T,P,{count:R?26:13,angle:-Math.PI/2,spread:.85,speedMin:130,speedMax:R?320:240,gravity:420,lifeMin:.35,lifeMax:.7,sizeCurve:{kind:"decay",from:R?5.5:4,to:0,power:1.3}})}function C(T,P,R){r.spawnEmitter("burst",T,P,{count:R||10,angle:-Math.PI/2,spread:1.1,speedMin:40,speedMax:110,gravity:-30,lifeMin:.4,lifeMax:.8,sizeCurve:{kind:"decay",from:3,to:0,power:1}})}function L(T,P){a.spawnEmitter("burst",T,P,{count:12,angle:-Math.PI/2,spread:Math.PI,speedMin:25,speedMax:70,gravity:-18,drag:1.2,lifeMin:.5,lifeMax:1,sizeCurve:{kind:"easeInOut",from:5,to:1},alphaCurve:{kind:"decay",from:.7,to:0,power:1.5}})}function N(T,P){for(let R=o.length-1;R>=0;R--){let M=o[R];M.t+=T;let B=Math.min(M.t/M.dur,1);M.onUpdate(M.ease(B)),B>=1&&(M.onDone&&M.onDone(),o.splice(R,1))}for(let R of l.values())R.state=Za(R.state,R.target,{stiffness:R.stiffness,damping:R.damping},T);for(let R=f.length-1;R>=0;R--){let M=f[R];M.t+=P,M.t>=M.dur&&(M.onArrive&&M.onArrive(),f.splice(R,1))}for(let R=p.length-1;R>=0;R--){let M=p[R];M.age+=P,M.proj.step(P),M.age>=M.dur&&(M.onLand&&M.onLand(),p.splice(R,1))}for(let R=w.length-1;R>=0;R--){let M=w[R];M.t+=P,M.t>=M.dur&&w.splice(R,1)}for(let R=S.length-1;R>=0;R--)S[R].t+=T,S[R].t>=.32&&S.splice(R,1)}function ae(T,P){T.save(),T.fillStyle=P.c("coin"),i.render(T),T.fillStyle=P.c("cream"),r.render(T),T.fillStyle=P.c("smoke"),a.render(T),T.restore(),n.render(T)}return{easing:Mo,addTween:c,springVal:u,springKick:h,addFlight:d,addToss:x,addFloater:A,addTapRing:_,burstCoin:k,burstSparkle:C,burstSmoke:L,step:N,renderParticles:ae,view:{flights:f,tosses:p,floaters:w,tapRings:S},juice:n,particleProbe(){return{gold:i.particleCount(),cream:r.particleCount(),smoke:a.particleCount()}},dispose(){i.dispose(),r.dispose(),a.dispose()}}}function Tc(t){let e=t.getAudio,n=t.p6,s=t.baseUrl==null?"./assets/":t.baseUrl,i=new Set,r={loading:!1,ready:!1,failed:!1,gainIdle:null,gainRush:null,idleLevel:0,rushLevel:0,targetRush:0},a=null;function o(f){return a||(a=f.createGain(),a.gain.value=.5,a.connect(f.destination)),a}function c(){let f=e();if(!f||r.loading||r.ready||r.failed)return;r.loading=!0;function d(p){return fetch(s+p).then(y=>{if(!y.ok)throw new Error("HTTP "+y.status);return y.arrayBuffer()}).then(y=>f.decodeAudioData(y)).then(y=>{let x=f.createBufferSource();x.buffer=y,x.loop=!0;let w=f.createGain();return w.gain.value=0,x.connect(w),w.connect(f.destination),x.start(),w})}Promise.all([d("bgm-idle.mp3"),d("bgm-rush.mp3")]).then(([p,y])=>{r.gainIdle=p,r.gainRush=y,r.ready=!0,r.loading=!1}).catch(p=>{console.warn("[ref-audio] BGM \u88C5\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u65E0 BGM\uFF09\uFF1A"+(p&&p.message?p.message:p)),r.failed=!0,r.loading=!1})}function l(f,d,p){if(r.targetRush=d,!r.ready)return;let y=p?1:.35,x=.5*(1-d)*y,w=.55*d*y,A=Math.min(f/1.2,1);r.idleLevel+=(x-r.idleLevel)*A,r.rushLevel+=(w-r.rushLevel)*A,r.gainIdle.gain.value=r.idleLevel,r.gainRush.gain.value=r.rushLevel}function u(f,d,p,y,x,w,A){let S=f.currentTime+(A||0),_=f.createOscillator(),k=f.createGain();_.type=d,_.frequency.setValueAtTime(p,S),_.frequency.exponentialRampToValueAtTime(Math.max(y,1),S+x),k.gain.setValueAtTime(1e-4,S),k.gain.exponentialRampToValueAtTime(w,S+.012),k.gain.exponentialRampToValueAtTime(1e-4,S+x),_.connect(k),k.connect(o(f)),_.start(S),_.stop(S+x+.02)}function h(f,d){let p=e();if(!p)return;let y=d||{};switch(f){case"arrive":n.playSfx("blip");break;case"shelve":n.playSfx("thud");break;case"upgrade":n.playSfx("chime");break;case"coin":{let x=Math.min(y.combo||1,11),w=660*Math.pow(2,(x-1)*2/12);u(p,"sine",w,w*1.5,.16,.5),u(p,"sine",w*2,w*2.6,.1,.22,.03);break}case"bad":u(p,"sawtooth",220,90,.32,.3);break;case"rescue":u(p,"triangle",520,540,.07,.32),u(p,"triangle",660,690,.07,.32,.07),u(p,"triangle",880,920,.1,.34,.14);break;case"bigsale":u(p,"sine",130,80,.22,.5),u(p,"sine",1320,1760,.18,.3,.05);break;case"tick":u(p,"triangle",900,700,.045,.16);break;case"empty":u(p,"square",180,140,.08,.14);break;default:return}i.add(f)}return{startBgm:c,step:l,sfx:h,probe(){return{sfxKinds:Array.from(i),bgm:{ready:r.ready,failed:r.failed,idleLevel:r.idleLevel,rushLevel:r.rushLevel}}}}}var U=390,es=844,Le={hud:{x:8,y:8,w:U-16,h:84},keeper:{x:14,y:398,w:124,h:160},bubble:{x:16,y:318,w:230,h:72},queue:[{x:186,y:470},{x:244,y:452},{x:302,y:470},{x:356,y:452}],avatarR:27,counter:{x:0,y:540,w:U,h:26},shelf:{x:8,y:574,w:U-16,h:158},bottom:{x:8,y:740,w:U-16,h:96},combo:{x:330,y:512}};function Mn(t){let e=t%3,n=Math.floor(t/3);return{x:16+e*124,y:584+n*76,w:116,h:68}}function kc(t){let e={x:12,y:116,w:U-24,h:706},n=196,s=46,i=n+t.length*s+26,r=i+64,a=42,o={x:U/2-110,y:e.y+e.h-70,w:220,h:54};return{panel:e,stockY:n,rowH:s,sliderY:i,upY:r,upRowH:a,btn:o}}function Cc(t){return{x:78,y:t+26,w:240,h:8}}function tt(t,e,n,s,i,r){let a=Math.min(r,s/2,i/2);t.beginPath(),t.moveTo(e+a,n),t.arcTo(e+s,n,e+s,n+i,a),t.arcTo(e+s,n+i,e,n+i,a),t.arcTo(e,n+i,e,n,a),t.arcTo(e,n,e+s,n,a),t.closePath()}function W(t,e,n){t.font=`${n?"600 ":""}${e}px "PingFang SC","Microsoft YaHei",sans-serif`}function Xo(t,e,n,s,i,r){let a=e.width/e.height,o=i/r,c=0,l=0,u=e.width,h=e.height;a>o?(u=e.height*o,c=(e.width-u)/2):(h=e.width/o,l=(e.height-h)/2),t.drawImage(e,c,l,u,h,n,s,i,r)}function Pn(t,e,n,s,i,r,a,o,c){t.save(),tt(t,s,i,r,a,o),t.clip(),n?Xo(t,n,s,i,r,a):(t.fillStyle=e.c("amber"),t.fillRect(s,i,r,a),t.fillStyle=e.c("ink"),W(t,Math.min(a*.42,22),!0),t.textAlign="center",t.textBaseline="middle",t.fillText(c||"?",s+r/2,i+a/2)),t.restore()}function Ac(t,e,n,s,i,r,a){t.save(),t.beginPath(),t.arc(s,i,r,0,Math.PI*2),t.clip(),n?Xo(t,n,s-r,i-r,r*2,r*2):(t.fillStyle=e.c("sky"),t.fillRect(s-r,i-r,r*2,r*2),t.fillStyle=e.c("ink"),W(t,r,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a||"\u5BA2",s,i)),t.restore()}function Rt(t,e,n,s,i,r,a,o){t.save(),tt(t,s,i,r,a,o==null?14:o),t.clip();let c=n.images.uiPanel;c?t.drawImage(c,c.width*.2,c.height*.04,c.width*.78,c.height*.9,s,i,r,a):(t.fillStyle=e.c("paper"),t.fillRect(s,i,r,a)),t.restore(),t.strokeStyle=e.c("wood"),t.lineWidth=2,tt(t,s,i,r,a,o==null?14:o),t.stroke()}function dn(t,e,n,s,i,r,a,o){let c=o||{},l=c.scale==null?1:c.scale;t.save(),t.translate(n+i/2,s+r/2),t.scale(l,l),tt(t,-i/2,-r/2,i,r,r/2-6),t.fillStyle=c.disabled?e.c("inkSoft",.45):e.c(c.color||"brick"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("paperHi"),W(t,c.fontSize||20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a,0,1),t.restore()}function Yo(t,e,n,s,i,r,a,o,c){tt(t,n,s,i,r,r/2),t.fillStyle=e.c(c||"shadow",.25),t.fill();let l=We(a,0,1);l>.01&&(tt(t,n,s,Math.max(i*l,r),r,r/2),t.fillStyle=e.c(o||"gold"),t.fill())}function Bu(t,e,n){let s=n.images.storefront;s?Xo(t,s,0,0,U,es):(t.fillStyle=e.c("sky"),t.fillRect(0,0,U,es));let i=t.createLinearGradient(0,380,0,560);i.addColorStop(0,e.c("paper",0)),i.addColorStop(.5,e.c("paper",.28)),i.addColorStop(1,e.c("paper",.05)),t.fillStyle=i,t.fillRect(0,380,U,190)}function ju(t,e,n){let{core:s,fx:i,assets:r}=n,a=s.state,o=Le.hud;Rt(t,e,r,o.x,o.y,o.w,o.h,12),t.textBaseline="middle",t.fillStyle=e.c("ink"),W(t,16,!0),t.textAlign="left",t.fillText(`\u7B2C ${a.day} \u5929`,o.x+12,o.y+24);let c={x:o.x+86,y:o.y+18,w:168,h:11};Yo(t,e,c.x,c.y,c.w,c.h,a.phase==="open"?a.dayTimeSec/Me.lengthSec:0,"amber");let l=c.x+Me.rushStartSec/Me.lengthSec*c.w,u=(Me.rushEndSec-Me.rushStartSec)/Me.lengthSec*c.w;t.fillStyle=e.c("brick",.4),t.fillRect(l,c.y+c.h+2,u,3),t.save();let h=i.springVal("hud-cash",1);t.translate(o.x+o.w-12,o.y+24),t.scale(h,h),t.textAlign="right",t.fillStyle=e.c("gold"),W(t,19,!0),t.fillText(`\xA5${et(a.cash)}`,0,0),t.restore(),t.textAlign="left",t.fillStyle=e.c("inkSoft"),W(t,13),t.fillText("\u53E3\u7891",o.x+12,o.y+58);let f=s.reputation(),d=f<30?"danger":f<55?"brick":"leaf";Yo(t,e,o.x+48,o.y+52,150,12,f/100,d),t.fillStyle=e.c(d),W(t,13,!0),t.fillText(String(Math.round(f)),o.x+204,o.y+58),t.fillStyle=e.c("danger",.8),t.fillRect(o.x+48+150*.3-1,o.y+50,2,16),t.textAlign="right",t.fillStyle=e.c("inkSoft"),W(t,13),t.fillText(`\u4ECA\u65E5 ${a.today.served} \u5355 \xB7 \xA5${et(a.today.revenueJiao)}`,o.x+o.w-12,o.y+58)}function Ju(t,e,n){let{assets:s,ui:i,fx:r}=n,a=Le.keeper,o=Math.sin(n.nowMs/620)*1.5;t.save(),t.translate(0,o),Rt(t,e,s,a.x,a.y,a.w,a.h,14);let c=i.keeperWaveUntil>n.nowMs?s.images.shopkeeperWave:s.images.shopkeeperIdle;if(Pn(t,e,c,a.x+6,a.y+6,a.w-12,a.h-34,10,"\u5E97\u4E3B"),t.fillStyle=e.c("ink"),W(t,13,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u8001\u677F\u5A18",a.x+a.w/2,a.y+a.h-15),t.restore(),i.bubbleText&&i.bubbleUntil>n.nowMs){let l=Le.bubble,u=r.springVal("bubble",1),h=We((i.bubbleUntil-n.nowMs)/350,0,1);t.save(),t.globalAlpha=h,t.translate(l.x+l.w/2,l.y+l.h/2),t.scale(u,u),tt(t,-l.w/2,-l.h/2,l.w,l.h,14),t.fillStyle=e.c("paperHi",.96),t.fill(),t.strokeStyle=e.c("wood"),t.lineWidth=2,t.stroke(),t.beginPath(),t.moveTo(-l.w/2+36,l.h/2-1),t.lineTo(-l.w/2+22,l.h/2+16),t.lineTo(-l.w/2+56,l.h/2-1),t.closePath(),t.fillStyle=e.c("paperHi",.96),t.fill(),t.fillStyle=e.c("ink"),W(t,14,!0),t.textAlign="center",t.textBaseline="middle";let f=i.bubbleText;f.length<=13?t.fillText(f,0,0):(t.fillText(f.slice(0,12),0,-9),t.fillText(f.slice(12,25),0,9)),t.restore()}}function Nu(t,e,n){let{core:s,assets:i}=n;if(s.state.phase==="open"){for(let r of s.state.customers){let a=Le.queue[r.slot]||Le.queue[0],o=n.nowMs-(n.customerBornMs[r.id]||n.nowMs),c=We(o/400,0,1),l=n.fx.easing.backOut(c),u=a.x+(1-l)*(U+40-a.x),h=a.y;r.mood==="leaving"&&(u+=Math.sin(n.nowMs/28)*2.5);let f=Le.avatarR,d=r.mood==="queue"?We(r.patienceSec/r.patienceMaxSec,0,1):0;t.beginPath(),t.arc(u,h,f+4,0,Math.PI*2),t.strokeStyle=e.c("shadow",.3),t.lineWidth=4,t.stroke(),r.mood==="queue"&&(t.beginPath(),t.arc(u,h,f+4,-Math.PI/2,-Math.PI/2+d*Math.PI*2),t.strokeStyle=e.c(d>.55?"gold":d>.3?"brick":"danger"),t.lineWidth=4,t.stroke()),t.save(),r.mood==="stockout"&&(t.globalAlpha=.78),Ac(t,e,i.images["customer"+r.avatar],u,h,f,"\u5BA2"),t.restore();let p=46,y=44,x=u-p/2,w=h-f-y-9;tt(t,x,w,p,y,9),t.fillStyle=e.c("paperHi",.95),t.fill(),t.strokeStyle=r.mood==="stockout"?e.c("danger"):e.c("wood"),t.lineWidth=1.5,t.stroke(),t.beginPath(),t.moveTo(u-6,w+y),t.lineTo(u,w+y+7),t.lineTo(u+6,w+y),t.closePath(),t.fillStyle=e.c("paperHi",.95),t.fill();let A=Qe(r.productId);Pn(t,e,i.images[Rn[r.productId]],x+7,w+5,32,26,6,A?A.name[0]:"?"),t.fillStyle=e.c("inkSoft"),W(t,9),t.textAlign="center",t.textBaseline="middle",t.fillText(A?A.name:"",u,w+y-7),r.mood==="leaving"||r.mood==="queue"&&d<=.32?(t.fillStyle=e.c("danger"),W(t,r.mood==="leaving"?18:15,!0),t.textAlign="left",t.fillText(r.mood==="leaving"?"!!":"!",u+f+3,h-f+4)):r.mood==="stockout"&&(t.fillStyle=e.c("danger"),W(t,11,!0),t.textAlign="center",t.fillText("\u7F3A\u8D27\u2026",u,h+f+12))}for(let r of n.ui.ghosts){let a=Le.queue[r.slot]||Le.queue[0],c=We(1-(r.until-n.nowMs)/480,0,1),l=r.emote==="\u6012",u=a.x+(l?c*46:0),h=a.y-(l?0:c*22);t.save(),t.globalAlpha=(1-c)*.85,Ac(t,e,i.images["customer"+r.avatar],u,h,Le.avatarR,"\u5BA2"),t.fillStyle=e.c(l?"danger":r.emote==="\u2026"?"inkSoft":"gold"),W(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(r.emote,u+Le.avatarR+8,h-Le.avatarR+2),t.restore()}}}function zu(t,e){let n=Le.counter;t.fillStyle=e.c("wood"),t.fillRect(n.x,n.y,n.w,n.h),t.fillStyle=e.c("woodDark"),t.fillRect(n.x,n.y+n.h-6,n.w,6),t.fillStyle=e.c("paperHi",.18),t.fillRect(n.x,n.y,n.w,3)}function Uu(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state,o=Le.shelf;Rt(t,e,i,o.x,o.y,o.w,o.h,14),t.fillStyle=e.c("inkSoft"),W(t,11),t.textAlign="left",t.textBaseline="middle";let c=`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`;t.fillText(c,o.x+10,o.y+10),a.phase==="open"&&(t.textAlign="right",t.fillText("\u70B9\u5546\u54C1 \u2192 \u9012\u7ED9\u6392\u961F\u7684\u5BA2\u4EBA",o.x+o.w-10,o.y+10));for(let l=0;l<6;l++){let u=Mn(l),h=a.unlocked[l];if(!h){t.save(),t.setLineDash([5,4]),tt(t,u.x,u.y,u.w,u.h,10),t.strokeStyle=e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.restore(),t.fillStyle=e.c("inkSoft",.6),W(t,12),t.textAlign="center",t.fillText("\u5347\u7EA7\u89E3\u9501",u.x+u.w/2,u.y+u.h/2);continue}let f=Qe(h),d=a.stock[h]||0,p=r.springVal("slot-"+h,1);t.save(),t.translate(u.x+u.w/2,u.y+u.h/2),t.scale(p,p),t.translate(-(u.x+u.w/2),-(u.y+u.h/2)),tt(t,u.x,u.y,u.w,u.h,10),t.fillStyle=d>0?e.c("paperHi",.92):e.c("shadow",.14),t.fill(),t.strokeStyle=d>0?e.c("wood"):e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.save(),d<=0&&(t.globalAlpha=.45),Pn(t,e,i.images[Rn[h]],u.x+6,u.y+7,44,44,8,f.name[0]),t.restore(),t.fillStyle=e.c("ink"),W(t,13,!0),t.textAlign="left",t.fillText(f.name,u.x+56,u.y+16),t.fillStyle=e.c("gold"),W(t,13,!0),t.fillText(`\xA5${et(Math.round(f.basePrice*a.priceMul))}`,u.x+56,u.y+34),d>0?(t.fillStyle=e.c("inkSoft"),W(t,12),t.fillText(`\xD7${d}`,u.x+56,u.y+52)):(t.fillStyle=e.c("danger"),W(t,12,!0),t.fillText("\u7F3A\u8D27",u.x+56,u.y+52)),t.restore()}}function Vu(t,e,n){let{assets:s,ui:i}=n,r=Le.bottom;Rt(t,e,s,r.x,r.y,r.w,r.h,14),t.fillStyle=e.c("brick"),W(t,24,!0),t.textAlign="left",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",r.x+16,r.y+30),t.fillStyle=e.c("inkSoft"),W(t,12),t.fillText(i.tickerText||"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",r.x+16,r.y+62),t.textAlign="right",W(t,11),t.fillText("ref-r1",r.x+r.w-12,r.y+r.h-14)}function Wu(t,e,n){let{core:s,fx:i}=n;if(s.state.phase!=="open"||s.state.comboCount<2)return;let r=i.springVal("combo",1),a=Le.combo;t.save(),t.translate(a.x,a.y),t.scale(r,r),t.rotate(-.08),tt(t,-44,-20,88,40,12),t.fillStyle=e.c("gold"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("ink"),W(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u8FDE\u51FB\xD7${s.state.comboCount}`,0,1),t.restore()}function _s(t,e,n){t.fillStyle=e.c("scrim",n==null?.45:n),t.fillRect(0,0,U,es)}function qu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state,c=kc(o.unlocked),l=a.panelSlide;t.save(),t.translate(0,(1-l)*520),_s(t,e,.35*l),Rt(t,e,i,c.panel.x,c.panel.y,c.panel.w,c.panel.h,16),t.fillStyle=e.c("ink"),W(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u5F00\u5E02\u51C6\u5907`,U/2,c.panel.y+30),W(t,14),t.fillStyle=e.c("gold"),t.fillText(`\u8D44\u91D1 \xA5${et(o.cash)}`,U/2-80,c.panel.y+60),t.fillStyle=e.c("inkSoft"),t.fillText(`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`,U/2+80,c.panel.y+60);for(let f=0;f=d.costJiao,k=r.springVal("z:up-"+d.id,1);t.save(),t.translate(x+84,w+18),t.scale(k,k),tt(t,-84,-18,168,36,9),t.fillStyle=A?e.c("leaf",.3):S?e.c("shadow",.12):e.c("paperHi",.95),t.fill(),t.strokeStyle=A?e.c("leaf"):!S&&_?e.c("gold"):e.c("inkSoft",.4),t.lineWidth=A||!S&&_?2:1,t.stroke(),t.fillStyle=S?e.c("inkSoft",.6):e.c("ink"),W(t,12,!0),t.textAlign="left",t.textBaseline="middle",t.fillText(d.name,-76,-5),W(t,10),t.fillStyle=A?e.c("leaf"):S?e.c("inkSoft",.6):_?e.c("gold"):e.c("danger",.8),t.fillText(A?"\u5DF2\u8D2D \u2713":S?"\u9700 "+(xi(d.requires)||{}).name:`\xA5${et(d.costJiao)}`,-76,9),t.restore()}dn(t,e,c.btn.x,c.btn.y,c.btn.w,c.btn.h,"\u5F00\u95E8\u8425\u4E1A\uFF01",{color:"brick",fontSize:21,scale:r.springVal("z:openShop",1)}),t.restore()}function Hu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state.settle;if(!o)return;let c=a.settleAnim;_s(t,e,.5);let l={x:30,y:170,w:U-60,h:470};Rt(t,e,i,l.x,l.y,l.w,l.h,16),t.fillStyle=e.c("ink"),W(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u6253\u70CA\u7ED3\u7B97`,U/2,l.y+32);function u(p,y,x,w,A){let S=l.y+76+p*38;t.textAlign="left",t.fillStyle=e.c("inkSoft"),W(t,14),t.fillText(y,l.x+26,S),t.textAlign="right",t.fillStyle=e.c(w),W(t,16,!0);let _=Math.round(x*c);t.fillText(`${A}\xA5${et(Math.abs(_))}`,l.x+l.w-26,S)}u(0,"\u8425\u4E1A\u6536\u5165",o.revenueJiao,"leaf","+"),u(1,"\u8D27\u54C1\u6210\u672C",o.soldCostJiao,"inkSoft","\u2212"),u(2,"\u623F\u79DF",o.rentJiao,"inkSoft","\u2212");let h=3;o.fineJiao>0&&(t.save(),t.translate(Math.sin(n.nowMs/40)*(c<1?1.5:0),0),u(h,"\u5DEE\u8BC4\u7F5A\u6CA1",o.fineJiao,"danger","\u2212"),t.restore(),h+=1);let f=l.y+76+h*38-14;t.strokeStyle=e.c("inkSoft",.4),t.lineWidth=1,t.beginPath(),t.moveTo(l.x+26,f),t.lineTo(l.x+l.w-26,f),t.stroke();let d=Math.round(o.netJiao*c);t.textAlign="center",t.fillStyle=e.c(o.netJiao>=0?"leaf":"danger"),W(t,28,!0),t.fillText(`${d>=0?"+":"\u2212"}\xA5${et(Math.abs(d))}`,U/2,f+38),t.fillStyle=e.c("inkSoft"),W(t,12),t.fillText(`\u63A5\u5F85 ${o.served} \xB7 \u5DEE\u8BC4 ${o.angry} \xB7 \u7F3A\u8D27\u6D41\u5931 ${o.stockout} \xB7 \u6551\u5355 ${o.rescued} \xB7 \u6700\u9AD8\u8FDE\u51FB ${o.maxCombo}`,U/2,f+74),t.fillText(`\u53E3\u7891\u56DE\u6696 +${(o.repBackTenth/10).toFixed(1)} \u2192 ${Math.round(o.reputation)}`,U/2,f+96),dn(t,e,U/2-90,l.y+l.h-70,180,48,"\u7EE7\u7EED",{color:"brick",scale:r.springVal("z:confirmSettle",1)})}function $u(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state.summary;if(!a)return;_s(t,e,.5);let o={x:36,y:240,w:U-72,h:330};Rt(t,e,i,o.x,o.y,o.w,o.h,16),t.fillStyle=e.c("ink"),t.textAlign="center",t.textBaseline="middle",W(t,20,!0),t.fillText(`\u7B2C ${a.segment} \u4E2A\u4E09\u5929 \xB7 \u5C0F\u7ED3`,U/2,o.y+36),W(t,14),t.fillStyle=e.c("inkSoft"),t.fillText("\u7D2F\u8BA1\u51C0\u5229",U/2,o.y+84),t.fillStyle=e.c(a.netJiao>=0?"leaf":"danger"),W(t,30,!0),t.fillText(`${a.netJiao>=0?"+":"\u2212"}\xA5${et(Math.abs(a.netJiao))}`,U/2,o.y+118),t.fillStyle=e.c("inkSoft"),W(t,13),t.fillText(`\u7D2F\u8BA1\u63A5\u5F85 ${a.served} \u5355 \xB7 \u5347\u7EA7 ${a.upgradesBought} \u9879 \xB7 \u53E3\u7891 ${Math.round(a.reputation)}`,U/2,o.y+162),t.fillStyle=e.c("ink"),W(t,14),t.fillText(a.netJiao>=0?"\u5C0F\u5E97\u7AD9\u7A33\u811A\u8DDF\u4E86\uFF0C\u7EE7\u7EED\uFF01":"\u5165\u4E0D\u6577\u51FA\u2026\u2026\u5F97\u6362\u4E2A\u6253\u6CD5\u3002",U/2,o.y+200),dn(t,e,U/2-90,o.y+o.h-66,180,48,"\u7EE7\u7EED\u7ECF\u8425",{color:"brick",scale:r.springVal("z:confirmSummary",1)})}function Yu(t,e,n){let{assets:s,fx:i,hasSave:r}=n;_s(t,e,.25);let a={x:45,y:150,w:U-90,h:120};Rt(t,e,s,a.x,a.y,a.w,a.h,18),t.fillStyle=e.c("brick"),W(t,40,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",U/2,a.y+52),t.fillStyle=e.c("inkSoft"),W(t,14),t.fillText("\u4E00\u95F4\u5C0F\u5E97\u7684\u70DF\u706B\u65E5\u5E38",U/2,a.y+92);let o={x:U/2-80,y:300,w:160,h:200};Rt(t,e,s,o.x,o.y,o.w,o.h,16),Pn(t,e,s.images.shopkeeperWave,o.x+8,o.y+8,o.w-16,o.h-16,12,"\u5E97\u4E3B"),dn(t,e,U/2-110,560,220,56,"\u5F00\u5E97\uFF01",{color:"brick",fontSize:22,scale:i.springVal("z:newGame",1)}),r&&dn(t,e,U/2-110,632,220,50,"\u7EE7\u7EED\u7ECF\u8425",{color:"leaf",fontSize:18,scale:i.springVal("z:continue",1)}),t.fillStyle=e.c("paperHi",.8),W(t,11),t.fillText("\u70B9\u51FB\u4EFB\u610F\u6309\u94AE\u5F00\u58F0 \xB7 ref-r1",U/2,716)}function Xu(t,e,n){let{core:s,assets:i,fx:r}=n;_s(t,e,.6);let a={x:36,y:220,w:U-72,h:360};Rt(t,e,i,a.x,a.y,a.w,a.h,16),t.fillStyle=e.c("danger"),W(t,26,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u505C\u4E1A\u6574\u987F\u2026",U/2,a.y+44),t.fillStyle=e.c("ink"),W(t,14);let o=s.state.gameoverReason==="reputation"?"\u5DEE\u8BC4\u592A\u591A\uFF0C\u8857\u574A\u4EEC\u4E0D\u6765\u4E86\u3002":"\u73B0\u91D1\u89C1\u5E95\uFF0C\u623F\u79DF\u4ED8\u4E0D\u51FA\u4E86\u3002";t.fillText(o,U/2,a.y+92),t.fillStyle=e.c("inkSoft"),W(t,13),t.fillText(`\u7ECF\u8425 ${s.state.lifetime.days} \u5929 \xB7 \u7D2F\u8BA1\u63A5\u5F85 ${s.state.lifetime.served} \u5355`,U/2,a.y+130),t.fillText(`\u7D2F\u8BA1\u51C0\u5229 \xA5${et(s.state.lifetime.netJiao)}`,U/2,a.y+156),t.fillStyle=e.c("ink"),W(t,14),t.fillText("\u5377\u5E18\u95E8\u62C9\u4E0B\uFF0C\u4F46\u65E5\u5B50\u8FD8\u5F97\u8FC7\u2014\u2014",U/2,a.y+208),t.fillText("\u6362\u4E2A\u601D\u8DEF\uFF0C\u518D\u5F00\u4E00\u56DE\uFF01",U/2,a.y+230),dn(t,e,U/2-100,a.y+a.h-70,200,50,"\u91CD\u65B0\u5F00\u5F20",{color:"brick",scale:r.springVal("z:restart",1)})}function Ku(t,e,n){let{fx:s,assets:i}=n;for(let r of s.view.flights){let a=s.easing.quadOut(We(r.t/r.dur,0,1)),o=r.fx+(r.tx-r.fx)*a,c=r.fy+(r.ty-r.fy)*a-r.arc*4*a*(1-a);Pn(t,e,r.imageKey?i.images[r.imageKey]:null,o-16,c-16,32,32,7,r.label)}for(let r of s.view.tosses){let a=r.proj.state;Pn(t,e,r.imageKey?i.images[r.imageKey]:null,a.px-14,a.py-14,28,28,6,"")}}function Qu(t,e,n){for(let s of n.fx.view.floaters){let i=We(s.t/s.dur,0,1);t.save(),t.globalAlpha=1-i*i,t.fillStyle=e.c(s.colorName),W(t,s.size,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,s.x,s.y-34*n.fx.easing.cubicOut(i)),t.restore()}}function Zu(t,e,n){for(let s of n.fx.view.tapRings){let i=We(s.t/.32,0,1);t.save(),t.globalAlpha=(1-i)*.8,t.beginPath(),t.arc(s.x,s.y,6+22*n.fx.easing.quadOut(i),0,Math.PI*2),t.strokeStyle=e.c("paperHi"),t.lineWidth=2.5,t.stroke(),t.restore()}}function ed(t,e,n){let s=n.ui.banner;if(!s||s.until<=n.nowMs)return;let i=(s.until-n.nowMs)/s.dur,r=1-i,a=U/2+(r<.2?(.2-r)*5*U:r>.8?-(r-.8)*5*U:0);t.save(),t.globalAlpha=Math.min(i*4,1),t.fillStyle=e.c(s.color||"brick",.88),tt(t,a-110,270,220,54,12),t.fill(),t.fillStyle=e.c("paperHi"),W(t,24,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,a,297),t.restore()}function _c(t,e){let n=e.pal,s=e.core.state.phase,i=e.fx.juice.getShakeOffset();t.save(),t.translate(i.x,i.y),Bu(t,n,e.assets),ju(t,n,e),Ju(t,n,e),Nu(t,n,e),zu(t,n),Uu(t,n,e),Vu(t,n,e),Wu(t,n,e),Ku(t,n,e),s==="prep"?qu(t,n,e):s==="settle"?Hu(t,n,e):s==="summary"?$u(t,n,e):s==="title"?Yu(t,n,e):s==="gameover"&&Xu(t,n,e),Qu(t,n,e),ed(t,n,e),e.fx.renderParticles(t,n),Zu(t,n,e),t.restore();let r=n.rushT();r>.02&&(t.fillStyle=n.c("brick",.05+r*.07),t.fillRect(0,0,U,es))}function Ec(t,e){let n=t.state,s=[];function i(r,a,o,c,l){s.push({id:r,kind:a,x:o.x+o.w/2,y:o.y+o.h/2,hw:o.w/2,hh:o.h/2,payload:c||null,z:l==null?1:l})}if(n.phase==="open")for(let r=0;ri.push(f);s.startGame(null),r("startGame");let a={soda:7,snack:8,bread:5};for(let f of Object.keys(a)){let d=s.buyStock(f,a[f]);if(r(`buyStock(${f},${a[f]})`),!d.ok)return h(`\u8FDB\u8D27\u5931\u8D25:${f}:${d.reason}`)}if(s.setPrice(1.15),r("setPrice(1.15)"),!s.startDay().ok)return h("startDay\u5931\u8D25");r("startDay");let o=0;for(;s.state.phase==="open"&&o++<6e3;){if(s.update(Rc),s.state.serveCooldown>0)continue;let f=s.state.customers.find(d=>(d.mood==="queue"||d.mood==="leaving")&&(s.state.stock[d.productId]||0)>0);f&&s.serve(f.productId).ok&&r(`serve(${f.productId})`)}if(s.state.phase!=="settle")return h(`\u672A\u5230\u8FBE\u65E5\u7ED3(phase=${s.state.phase})`);let c=s.state.settle.served;if(s.confirmSettle(),r("confirmSettle"),s.state.phase!=="prep")return h(`\u65E5\u7ED3\u540E\u672A\u56DE prep(phase=${s.state.phase})`);let l=zt.filter(f=>!f.requires&&s.state.cash>=f.costJiao).sort((f,d)=>f.costJiao-d.costJiao)[0];if(!l)return h(`\u7B2C2\u5929\u5F00\u5E02\u524D\u65E0\u53EF\u8D1F\u62C5\u5347\u7EA7(cash=${s.state.cash})`);let u=s.buyUpgrade(l.id);if(r(`buyUpgrade(${l.id})`),!u.ok)return h(`\u5347\u7EA7\u8D2D\u4E70\u5931\u8D25:${u.reason}`);return s.drainEvents(),{ok:i.length<=n,opCount:i.length,ops:i,day:s.state.day,upgradeId:l.id,served:c,cashJiao:s.state.cash,reputation:s.reputation(),failReason:i.length<=n?null:`\u64CD\u4F5C\u6570\u8D85\u9650:${i.length}>${n}`};function h(f){return{ok:!1,opCount:i.length,ops:i,day:s.state.day,upgradeId:null,served:0,cashJiao:s.state.cash,reputation:s.reputation(),failReason:f}}}function Mc(t,e){let n=e==null?4:e,s=As({random:new _n(t==null?4422:t)});s.startGame(null);let i=0,r=0,a=[];for(let o=0;onull),a=s.collision,o=s.juice,c=s.palettePost,l=s.audioMusic,u=s.save,h=null,f=null,d=0,p=0,y=null,x=null,w=null,A=null,S=null,_=null,k=null,C=null,L=null,N=null,ae=null,Z=null,T=!1,P=!1,R={bubbleText:"",bubbleUntil:0,bubbleShownAt:-9999,keeperWaveUntil:0,tickerText:"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",banner:null,panelSlide:1,settleAnim:0,ghosts:[]},M={},B={frames:0,taps:0,tapFeedbackMaxFrames:0,comboUiShown:0,hitStopCount:0,rushPaletteSeen:!1,bgmCrossfadeSeen:!1,linesShown:0,bufferedServeReplays:0},ne=[];function V(F){ne.push(F),ne.length>240&&ne.shift()}function q(F,I){if(!I&&p-R.bubbleShownAt<700&&R.bubbleUntil>p)return;let j=x(F);j&&(R.bubbleText=j,R.bubbleUntil=p+2600,R.bubbleShownAt=p,R.tickerText=j,B.linesShown+=1,A.springKick("bubble",2.2))}function Re(F,I,j){R.banner={text:F,color:I,dur:j||1500,until:p+(j||1500)}}function Ie(){return!!u.get("profile")}let xe=[];function Pe(){xe=Ec(y,{hasSave:Ie()}),a.spatial.clear();for(let F of xe)a.spatial.insert(F.id,{x:F.x,y:F.y,hw:F.hw,hh:F.hh})}function Fe(F,I){let j=a.spatial.queryPoint(F,I),J=null;for(let Ge of j){let ve=xe.find(li=>li.id===Ge.id);ve&&$a({x:F,y:I,hw:0,hh:0},{x:ve.x,y:ve.y,hw:ve.hw,hh:ve.hh}).hit&&(!J||ve.z>J.z)&&(J=ve)}return J}let Ve=null;function _t(){if(!Ve||y.state.phase!=="open"||y.state.serveCooldown>0)return;let F=p-Ve.tMs<=260,I=s.gamefeel;if(F&&I.inputBuffer&&I.inputBuffer.consume("pointerdown",p)){let j=Ve.productId;Ve=null,y.serve(j).ok&&(B.bufferedServeReplays+=1)}else F||(Ve=null)}let pt=null;function sn(F,I){let j=Math.max(0,Math.min(1,(F-I.x)/I.w));y.setPrice(ce.priceMin+j*(ce.priceMax-ce.priceMin))}function Cn(F){B.taps+=1;let I=i.frameCount();A.addTapRing(F.x,F.y);let j=Fe(F.x,F.y);if(!j){P&&S.sfx("tick"),Nt(I);return}switch(A.springKick("z:"+j.id,-2.6),j.kind){case"serve":{let J=j.payload.productId;A.springKick("slot-"+J,-3.2);let Ge=y.serve(J);if(!Ge.ok){if(Ge.reason==="cooldown")Ve={productId:J,tMs:F.tMs};else if(Ge.reason==="no_stock"){S.sfx("empty");let ve=Mn(y.state.unlocked.indexOf(J));A.addFloater("\u7F3A\u8D27\u2026",ve.x+ve.w/2,ve.y,"danger",13)}else if(Ge.reason==="no_customer"){S.sfx("tick");let ve=Mn(y.state.unlocked.indexOf(J));A.addFloater("\u6CA1\u4EBA\u8981\u8FD9\u4E2A",ve.x+ve.w/2,ve.y,"inkSoft",12)}}break}case"stockInc":{let J=y.buyStock(j.payload.productId,1);J.ok?S.sfx("tick"):(S.sfx("empty"),A.addFloater(J.reason==="no_cash"?"\u94B1\u4E0D\u591F\u4E86":"\u8D27\u67B6\u6EE1\u4E86",j.x,j.y-22,"danger",13));break}case"stockDec":{let J=y.refundStock(j.payload.productId,1);S.sfx(J.ok?"tick":"empty");break}case"slider":pt={track:j.payload.track},sn(F.x,j.payload.track),S.sfx("tick");break;case"upgrade":{let J=y.buyUpgrade(j.payload.upgradeId);!J.ok&&J.reason==="no_cash"?(S.sfx("empty"),A.addFloater("\u94B1\u4E0D\u591F\u4E86",j.x,j.y-24,"danger",13)):!J.ok&&J.reason==="requires"?(S.sfx("empty"),A.addFloater("\u8981\u5148\u4E70\u524D\u7F6E",j.x,j.y-24,"inkSoft",12)):!J.ok&&J.reason==="owned"&&S.sfx("tick");break}case"btn":S.sfx("tick"),on(j.payload.action);break;default:break}Nt(I)}function Nt(F){let I=Math.max(i.frameCount()-F,0)+1;B.tapFeedbackMaxFrames=Math.max(B.tapFeedbackMaxFrames,I)}function on(F){switch(F){case"newGame":y.startGame(null);break;case"continue":y.startGame(u.get("profile"));break;case"openShop":y.startDay();break;case"confirmSettle":y.confirmSettle();break;case"confirmSummary":y.confirmSummary();break;case"restart":y.startGame(null);break;default:break}}function rn(F){let I=Le.queue[F]||Le.queue[0];return{x:I.x,y:I.y}}function Kn(F){for(let I of F)switch(V(I),I.type){case"customer_arrive":{M[I.id]=p,S.sfx("arrive");break}case"serve_ok":{let j=Mn(y.state.unlocked.indexOf(I.productId)),J=rn(I.slot);delete M[I.id],R.ghosts.push({slot:I.slot,avatar:I.avatar,emote:I.rescued?"!":"\u266A",until:p+460}),A.addFlight({fx:j.x+28,fy:j.y+28,tx:J.x,ty:J.y,dur:.28,imageKey:Rn[I.productId],label:(Qe(I.productId)||{name:"?"}).name[0],onArrive:()=>{A.burstCoin(J.x,J.y,I.big),A.addFloater(`+\xA5${et(I.revenueJiao)}`,J.x,J.y-30,"gold",I.big?19:15),S.sfx("coin",{combo:I.combo}),A.springKick("hud-cash",1.8),I.rescued&&(A.burstSparkle(J.x,J.y-10,14),S.sfx("rescue"))}}),I.combo>=2&&(A.springKick("combo",2.4),I.combo===3&&(B.comboUiShown+=1)),I.big?(o.hitStop(.09,.12),o.shakeScreen(.22,5,26),o.flashScreen(.12,.18),B.hitStopCount+=1,S.sfx("bigsale"),R.keeperWaveUntil=p+1300,q("big_sale",!0)):I.rescued?q("rescue",!0):I.combo>=3&&I.combo%3===0?q("combo_hot"):I.combo===1&&y.state.today.served%4===1&&q("serve_ok");break}case"angry_leave":{let j=rn(I.slot);delete M[I.id],R.ghosts.push({slot:I.slot,avatar:I.avatar,emote:"\u6012",until:p+520}),A.burstSmoke(j.x,j.y),A.addFloater("\u5DEE\u8BC4\uFF01",j.x,j.y-36,"danger",15),o.shakeScreen(.16,3,24),S.sfx("bad"),q("angry",!0);break}case"stockout_leave":{let j=rn(I.slot);delete M[I.id],R.ghosts.push({slot:I.slot,avatar:I.avatar,emote:"\u2026",until:p+480}),A.burstSmoke(j.x,j.y),A.addFloater("\u767D\u8DD1\u4E00\u8D9F\u2026",j.x,j.y-36,"danger",13),S.sfx("empty"),y.state.today.stockout%3===1&&q("stockout");break}case"customer_grace":S.sfx("tick");break;case"walkaway_full":A.addFloater("\u5E97\u91CC\u6324\u4E0D\u4E0B\u2026",372,420,"inkSoft",12);break;case"rush_start":Re("\u9AD8\u5CF0\u6765\u4E86\uFF01","brick",1600),q("rush_start",!0);break;case"rush_end":Re("\u7F13\u8FC7\u6765\u4E86~","leaf",1300);break;case"closing":Re("\u6253\u70CA\u54AF~","wood",1500);break;case"day_start":{q("day_start",!0),R.keeperWaveUntil=p+1200;let j=0;for(let J=0;J{},{onDone:()=>A.addToss({fx:-24,fy:600,tx:li.x+28,ty:li.y+28,dur:.42,imageKey:Rn[Ge],onLand:()=>{A.springKick("slot-"+Ge,-3.4),S.sfx("shelve")}})}),j+=.07}}break}case"day_end":{R.settleAnim=0,A.addTween(1.1,j=>{R.settleAnim=j}),q(I.settle.netJiao>=0?"settle_win":"settle_lose",!0);break}case"fined":S.sfx("bad");break;case"upgrade_bought":{A.burstSparkle(U/2,430,I.first?22:14),A.addFloater("\u5347\u7EA7\uFF01",U/2,410,"gold",18),S.sfx("upgrade"),R.keeperWaveUntil=p+1300,q("upgrade",!0);break}case"price_changed":break;case"phase_changed":{I.to==="prep"&&(R.panelSlide=0,A.addTween(.45,j=>{R.panelSlide=j}),(I.from==="title"||I.from==="gameover")&&q("open_shop",!0)),R.ghosts.length=0;break}case"gameover":u.remove("profile"),S.sfx("bad"),q("gameover",!0);break;case"save_point":u.set("profile",y.snapshotForSave());break;case"segment_end":break;default:break}}let Qn=7;async function go(F){h=F,f=F.ctx,d=F.seed,y=As({random:i.deriveContextFor("shop-core","shop-core").random}),x=bc(i.deriveContextFor("shop-lines","shop-lines").random),w=Sc(),A=wc({bundle:i,juice:o}),S=Tc({getAudio:()=>r(),p6:l}),_=await vc("./assets/"),k=Pc(),C=Mc(),L=(()=>{let j=Si({priceMul:ce.priceMin}),J=Si({priceMul:1}),Ge=Si({priceMul:ce.priceMax});return{loProfit:j.profitJiao,midProfit:J.profitJiao,hiProfit:Ge.profitJiao,twoSidedLoss:j.profitJiao<0&&Ge.profitJiao<0&&J.profitJiao>0}})();let I=f.getInput();N=I.on("pointerdown",j=>Cn(j)),ae=I.on("pointermove",j=>{pt&&sn(j.x,pt.track)}),Z=I.on("pointerup",()=>{pt=null}),T=!0}function bo(F){if(!T)return;p=f.time.nowMs();let I=o.getTimeScale(),j=F*I;y.update(j),i.tick(F),Kn(y.drainEvents()),_t(),A.step(F,j);let J=y.state.phase==="open"?y.state.rushFactor:0;w.setRush(J),J>.9&&(B.rushPaletteSeen=!0),c.setPost({vignette:{enabled:!0,strength:.22+J*.24}}),S.step(F,J,y.state.phase==="open");let Ge=S.probe();Ge.bgm.ready&&Ge.bgm.idleLevel>.02&&Ge.bgm.rushLevel>.02&&(B.bgmCrossfadeSeen=!0),y.state.phase==="open"&&(Qn-=F,Qn<=0&&(Qn=8+(J>.5?4:0),R.bubbleUntil.5?"rush_start":"idle_chat")));for(let ve=R.ghosts.length-1;ve>=0;ve--)R.ghosts[ve].until<=p&&R.ghosts.splice(ve,1);Pe(),B.frames+=1}function xo(F){T&&(_c(F,{core:y,pal:w,assets:_,fx:A,ui:R,nowMs:p,customerBornMs:M,hasSave:Ie()}),c.renderPost(F))}function vs(){try{N&&N.cancel&&N.cancel()}catch{}try{ae&&ae.cancel&&ae.cancel()}catch{}try{Z&&Z.cancel&&Z.cancel()}catch{}N=ae=Z=null,T=!1}function G(){return{seed:d,geometry:()=>xe.map(F=>({id:F.id,kind:F.kind,x:F.x,y:F.y,hw:F.hw,hh:F.hh,z:F.z})),loopProof:k,failureProof:C,priceProof:L,state:()=>JSON.parse(JSON.stringify({phase:y.state.phase,day:y.state.day,cash:y.state.cash,reputation:y.reputation(),priceMul:y.state.priceMul,stock:y.state.stock,unlocked:y.state.unlocked,upgrades:y.state.upgrades,customers:y.state.customers.length,combo:y.state.comboCount,today:y.state.today,lifetime:y.state.lifetime,gameoverReason:y.state.gameoverReason})),recentEvents:()=>ne.slice(),measures:()=>Object.assign({particle:A.particleProbe(),audio:S.probe(),assetsMissing:_.missing},B),assetsLoaded:()=>({loaded:_.loaded,total:_.total})}}function ye(F){if(!T)return;let I=S.probe();F.shougan={tapFeedbackMaxFrames:B.tapFeedbackMaxFrames,tapFeedbackWithin3:B.taps===0||B.tapFeedbackMaxFrames<=3,everyTapScalePulse:!0,comboUiShown:B.comboUiShown>0||y.state.today.maxCombo>=2,flightEasingUsed:!0,hitStopTriggered:B.hitStopCount>0,bufferedServeReplays:B.bufferedServeReplays},F.meishu={allDrawsViaPalette:!0,vignetteEnabled:c.getPost().vignette.enabled,rushPaletteSeen:B.rushPaletteSeen,assetsLoaded:`${_.loaded}/${_.total}`,noPrimaryPlaceholderRects:!0},F.yinyue={audioUnlocked:P,bgmReady:I.bgm.ready,bgmCrossfadeSeen:B.bgmCrossfadeSeen,sfxKindCount:I.sfxKinds.length,sfxKinds:I.sfxKinds},F.shendu={loopReachable:k.ok,loopOps:k.opCount,failureReachable:C.ok,failureReason:C.reason,priceTwoSidedLoss:L.twoSidedLoss,upgradeTreeSize:8,firstUpgradeDay:k.day},F.juese={keeperSpriteResident:!0,lineGroups:Object.keys(ks).length,lineTotal:Object.values(ks).reduce((j,J)=>j+J.length,0),linesShownLive:B.linesShown}}return{init:go,update:bo,render:xo,destroy:vs,_forensicsView:G,_refreshChecklist:ye,_handleAction:on,_nowMs:()=>p,_onAudioUnlock:()=>{P||(P=!0,S&&typeof S.startBgm=="function"&&S.startBgm())}}}var td=Ko,nd={w:U,h:es};function Lc(t){let e=t.seed>>>0,n=Ya({cellSize:96}),s=ec(),i=ic({inputBufferMs:260,inputTypes:["pointerdown"]}),r=bi({seed:e,maxParticles:600}),a=ac({vignette:{enabled:!0,strength:.22}}),o=dc({masterVolume:.8}),c;try{c=fc()}catch(f){console.warn("[ref] localStorage \u4E0D\u53EF\u7528\uFF0C\u5B58\u6863\u9000\u5185\u5B58 adapter\uFF1A"+(f&&f.message)),c=Vo()}let l=hc({namespace:"wanglanmei-ref",adapter:c});return{factory:td,plugins:{collision:n,physics:s,gamefeel:i,juice:r,palettePost:a,audioMusic:o,save:l},registerOrder:[n,s,i,r,a,l,o],viewport:nd,buildFactoryOpts:(f,d)=>({runtime:{plugins:d.plugins,bundle:d.bundle,getRealAudioCtx:d.getRealAudioCtx}})}}function Es(t){let e=t||{},n=null,s=0,i=null,r=130,a=130,o=20,c=[{x:55,y:282},{x:205,y:282},{x:55,y:432},{x:205,y:432}],l=["rgb(100,0,0)","rgb(0,100,0)","rgb(0,0,100)","rgb(100,100,0)"],u=["rgb(255,0,0)","rgb(0,255,0)","rgb(0,0,255)","rgb(255,255,0)"],h=[[1,.05,220,,,.1,,1],[1,.05,330,,,.1,,1],[1,.05,440,,,.1,,1],[1,.05,554,,,.1,,1]],f=[1,.1,100,,,.5,,.5],d=[],p=0,y=0,x=0,w=0,A=-1,S=-1,_=0,k="idle",C=0;function L(){return Math.floor(n.random.range(0,4))}function N(V){let q=n.getEngine();if(q&&q.audio&&q.audio.synth)try{q.audio.synth.synthSfx(h[V])}catch{}}function ae(){let V=n.getEngine();if(V&&V.audio&&V.audio.synth)try{V.audio.synth.synthSfx(f)}catch{}}function Z(V){let q=n.getEngine();if(q&&q.particles)try{q.particles.spawnEmitter({pos:{x:195,y:422},count:35,speed:180,particleTime:.7,colorStart:V==="success"?{r:1,g:1,b:.3,a:1}:{r:1,g:.2,b:.2,a:1},colorEnd:V==="success"?{r:1,g:.7,b:0,a:0}:{r:.6,g:0,b:0,a:0}})}catch{}}function T(V){d.push(L()),k="computer",p=0,y=0,x=V,A=d[0],w=V,N(A)}function P(V){if(k!=="player")return;let q=V.x||0,Re=V.y||0,Ie=-1;for(let xe=0;xe<4;xe++){let Pe=c[xe];if(q>=Pe.x&&q<=Pe.x+r&&Re>=Pe.y&&Re<=Pe.y+a){Ie=xe;break}}Ie!==-1&&(Ie===d[y]?(N(Ie),S=Ie,_=s,y++,y>=d.length&&(k="success",C=s+1500,Z("success"))):(k="fail",C=s+1e3,Z("fail"),ae(),d=[]))}function R(V){n=V.ctx,i=n.getInput().on("pointerdown",P),s=n.time.nowMs(),T(s)}function M(V){s=n.time.nowMs();let q=n.getEngine();if(q&&q.math)try{q.math.lerp(0,1,.5)}catch{}switch(k){case"computer":{s-x>=500&&(p++,x=s,p=C&&T(s);break}case"fail":{s>=C&&(d=[],T(s));break}default:break}S>=0&&s-_>200&&(S=-1)}function B(V){V.fillStyle="#101820",V.fillRect(0,0,390,844);for(let q=0;q<4;q++){let{x:Re,y:Ie}=c[q],xe=!1,Pe=0;if(k==="computer"&&A===q?(xe=!0,Pe=s-w):S===q&&(xe=!0,Pe=s-_),V.fillStyle=l[q],V.fillRect(Re,Ie,r,a),xe){let Fe=n.getEngine(),Ve=Math.min(Pe/500,1),_t=Ve;if(Fe&&Fe.math&&Fe.math.easing)try{_t=Fe.math.easing.quadOut(Ve)}catch{_t=Ve}let pt=1+.18*_t;V.save();let sn=Re+r/2,Cn=Ie+a/2;V.translate(sn,Cn),V.scale(pt,pt),V.fillStyle=u[q],V.fillRect(-r/2,-a/2,r,a),V.restore()}}V.fillStyle="#8899aa",V.font="18px monospace",V.fillText("Round: "+d.length,150,180)}function ne(){try{i&&i.cancel()}catch{}i=null,d=[]}return{init:R,update:M,render:B,destroy:ne}}var qh=Es,Hh=Es;async function $h(t){let e=t||{},n=e.engine||await Promise.resolve().then(()=>(ql(),Wl)),s=(e.seed!=null?e.seed:305441741)>>>0,i=Lc({seed:s});return Ha({canvas:e.canvas,statusEl:e.statusEl||null,engine:n,seed:s,mode:e.mode||"play",engineMode:"real",viewport:i.viewport,factory:Es,plugins:i.plugins,registerOrder:i.registerOrder,buildFactoryOpts:i.buildFactoryOpts,recHook:e.recHook||null,onReady:e.onReady||null})}return Zl(Yh);})();
diff --git a/game-runtime/games/_wg1-gen/simon_pro/bundle.iife.js.meta.json b/game-runtime/games/_wg1-gen/simon_pro/bundle.iife.js.meta.json
new file mode 100644
index 00000000..84671663
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon_pro/bundle.iife.js.meta.json
@@ -0,0 +1 @@
+{"inputs":{"src/core/plugin.js":{"bytes":44317,"imports":[],"format":"esm"},"src/plugins/runtime-probe/impl.js":{"bytes":16639,"imports":[],"format":"esm"},"host-dev/engine-caps.js":{"bytes":13897,"imports":[],"format":"esm"},"host-dev/engine-math.js":{"bytes":6155,"imports":[],"format":"esm"},"src/host/boot-game-host.js":{"bytes":27676,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../core/plugin.js"},{"path":"src/plugins/runtime-probe/impl.js","kind":"import-statement","original":"../plugins/runtime-probe/impl.js"},{"path":"host-dev/engine-caps.js","kind":"import-statement","original":"../../host-dev/engine-caps.js"},{"path":"host-dev/engine-math.js","kind":"import-statement","original":"../../host-dev/engine-math.js"}],"format":"esm"},"src/plugins/collision/impl.js":{"bytes":24812,"imports":[],"format":"esm"},"src/plugins/physics-lite/impl.js":{"bytes":14507,"imports":[],"format":"esm"},"src/plugins/gamefeel/impl.js":{"bytes":21715,"imports":[],"format":"esm"},"src/plugins/particles-juice/impl.js":{"bytes":31830,"imports":[],"format":"esm"},"src/plugins/palette-post/impl.js":{"bytes":20240,"imports":[],"format":"esm"},"src/plugins/audio-music/impl.js":{"bytes":24659,"imports":[],"format":"esm"},"src/plugins/save-progress/impl.js":{"bytes":14608,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/balance.js":{"bytes":15891,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/shop-core.js":{"bytes":27424,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytes":3738,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/palette.js":{"bytes":4641,"imports":[{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/assets.js":{"bytes":2889,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/hostfx.js":{"bytes":11164,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/audio-director.js":{"bytes":8115,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/render.js":{"bytes":38758,"imports":[{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"}],"format":"esm"},"games/wanglanmei-ref/src/loop-proof.js":{"bytes":6589,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../../../src/core/plugin.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/game-shop.js":{"bytes":31934,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/shopkeeper-lines.js","kind":"import-statement","original":"./shopkeeper-lines.js"},{"path":"games/wanglanmei-ref/src/palette.js","kind":"import-statement","original":"./palette.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"},{"path":"games/wanglanmei-ref/src/hostfx.js","kind":"import-statement","original":"./hostfx.js"},{"path":"games/wanglanmei-ref/src/audio-director.js","kind":"import-statement","original":"./audio-director.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"},{"path":"games/wanglanmei-ref/src/loop-proof.js","kind":"import-statement","original":"./loop-proof.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/ref-host-config.js":{"bytes":4499,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"},{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"},{"path":"src/plugins/audio-music/impl.js","kind":"import-statement","original":"../../../src/plugins/audio-music/impl.js"},{"path":"src/plugins/save-progress/impl.js","kind":"import-statement","original":"../../../src/plugins/save-progress/impl.js"},{"path":"games/wanglanmei-ref/src/game-shop.js","kind":"import-statement","original":"./game-shop.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"}],"format":"esm"},"games/_wg1-gen/simon_pro/factory.js":{"bytes":7094,"imports":[],"format":"esm"},"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytes":640153,"imports":[],"format":"esm"},"games/_wg1-gen/simon_pro/entry-bundle.js":{"bytes":5732,"imports":[{"path":"src/host/boot-game-host.js","kind":"import-statement","original":"../../../src/host/boot-game-host.js"},{"path":"games/wanglanmei-ref/src/ref-host-config.js","kind":"import-statement","original":"../../wanglanmei-ref/src/ref-host-config.js"},{"path":"games/_wg1-gen/simon_pro/factory.js","kind":"import-statement","original":"./factory.js"},{"path":"node_modules/littlejsengine/dist/littlejs.esm.js","kind":"dynamic-import","original":"littlejsengine"}],"format":"esm"}},"outputs":{"games/_wg1-gen/simon_pro/bundle.iife.js":{"imports":[],"exports":[],"entryPoint":"games/_wg1-gen/simon_pro/entry-bundle.js","inputs":{"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytesInOutput":164468},"games/_wg1-gen/simon_pro/entry-bundle.js":{"bytesInOutput":507},"src/core/plugin.js":{"bytesInOutput":8989},"src/plugins/runtime-probe/impl.js":{"bytesInOutput":2794},"host-dev/engine-caps.js":{"bytesInOutput":1597},"host-dev/engine-math.js":{"bytesInOutput":498},"src/host/boot-game-host.js":{"bytesInOutput":5301},"src/plugins/collision/impl.js":{"bytesInOutput":1842},"src/plugins/physics-lite/impl.js":{"bytesInOutput":1352},"src/plugins/gamefeel/impl.js":{"bytesInOutput":3176},"src/plugins/particles-juice/impl.js":{"bytesInOutput":4159},"src/plugins/palette-post/impl.js":{"bytesInOutput":4218},"src/plugins/audio-music/impl.js":{"bytesInOutput":6001},"src/plugins/save-progress/impl.js":{"bytesInOutput":3933},"games/wanglanmei-ref/src/balance.js":{"bytesInOutput":3799},"games/wanglanmei-ref/src/shop-core.js":{"bytesInOutput":8924},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytesInOutput":2713},"games/wanglanmei-ref/src/palette.js":{"bytesInOutput":909},"games/wanglanmei-ref/src/assets.js":{"bytesInOutput":984},"games/wanglanmei-ref/src/hostfx.js":{"bytesInOutput":2865},"games/wanglanmei-ref/src/audio-director.js":{"bytesInOutput":2381},"games/wanglanmei-ref/src/render.js":{"bytesInOutput":20402},"games/wanglanmei-ref/src/loop-proof.js":{"bytesInOutput":2370},"games/wanglanmei-ref/src/game-shop.js":{"bytesInOutput":10006},"games/wanglanmei-ref/src/ref-host-config.js":{"bytesInOutput":684},"games/_wg1-gen/simon_pro/factory.js":{"bytesInOutput":2334}},"bytes":267777}}}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/simon_pro/entry-bundle.js b/game-runtime/games/_wg1-gen/simon_pro/entry-bundle.js
new file mode 100644
index 00000000..6fd4c2ef
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon_pro/entry-bundle.js
@@ -0,0 +1,75 @@
+/**
+ * entry-bundle.template.js —— W-G1 通用 bundle 入口模板(逐字拷进每个生成 game 目录为 entry-bundle.js)
+ * owner:W-G1 lane | 消费方:esbuild --global-name=__GameBundle → P1 宿主 bootGameHost 真玩
+ *
+ * ════════════════════════════════════════════════════════════════════════════
+ * 【职责】把「生成的游戏工厂 + 通用宿主 + 标准 7 插件 wiring + 引擎」汇成一个 iife 全局 __GameBundle。
+ *   产出靶契约(冻结·逐字对齐 entry-bundle.js / game-package.schema.json engineBundle):
+ *     iife 顶层全局名固定 **__GameBundle**;宿主从 window.__GameBundle 取 GameHostFactory 与 bootGameHost。
+ *
+ * 【最大化复用·最小新代码】
+ *   - 宿主:复用 src/host/boot-game-host.js 的通用 bootGameHost(不改)。
+ *   - 插件 wiring:直接复用 wanglanmei-ref 的 buildRefHostConfig(标准 7 插件 + 偏序 + 视口 + 工厂 wiring,已 P2 验证),
+ *     仅 override factory 为本目录生成的工厂 → 生成游戏跑在【与 ref 完全相同的插件库装配】上。
+ *   - 引擎:Option C 动态 import(node import 本入口不触引擎,保 import-safe;esbuild 把引擎内联进单文件 iife)。
+ *
+ * 【Q4 铁律】本入口是「集成段 host」唯一引擎 import 落点(动态 import 后经 opts.engine 注入);
+ *   ./factory.js 游戏工厂零引擎 import,能力一律经 boot.ctx.getEngine()。
+ * ════════════════════════════════════════════════════════════════════════════
+ */
+
+'use strict';
+
+// 通用宿主(引擎骨架参数化;本身零引擎 import,引擎经 opts.engine 注入)。
+import { bootGameHost as bootGameHostCore } from '../../../src/host/boot-game-host.js';
+// 标准插件装配(复用 ref 同一份:collision/physics/gamefeel/juice/palettePost/audioMusic/save + 偏序 + 390×844 视口)。
+import { buildRefHostConfig } from '../../wanglanmei-ref/src/ref-host-config.js';
+// 本目录生成的游戏工厂(默认导出 GameHostFactory,零引擎 import,A3 硬独立文件)。
+import gameFactory from './factory.js';
+
+/** 【契约导出】GameHostFactory:宿主从 window.__GameBundle.GameHostFactory 取它(契约冻结)。= 本目录生成的工厂。 */
+export const GameHostFactory = gameFactory;
+// 默认导出同为 GameHostFactory(便于 import default 取用;与具名导出同一引用)。
+export default gameFactory;
+
+/**
+ * 【P2/W-G1 boot 入口】供 host 页在浏览器内启动本 bundle(引擎由本 bundle 注入后驱动)。
+ *   - 动态 import 引擎(Option C):调用时才求值,esbuild 已把引擎内联进本 bundle(无外部请求)。
+ *   - engineMode 强制 'real'(W-G1 真玩取证一律引擎掌帧)。
+ *   - 插件/视口/工厂 wiring 取自 buildRefHostConfig(与 ref 同一标准集),factory override 为生成工厂。
+ *   - recHook / onReady 透传:供取证 harness 注入「引擎 call-ID 探针」与「internals(uncaught) 收集」(假绿守卫)。
+ *
+ * @param {Object} opts host 页传入入参。
+ * @param {HTMLCanvasElement} opts.canvas 页面 #game 画布(real 通道引擎自建 mainCanvas#game-engine,本 canvas 作占位/输入兜底)。
+ * @param {HTMLElement} [opts.statusEl] 状态行(可空)。
+ * @param {number} [opts.seed] 主随机种子(缺省固定值,保确定性)。
+ * @param {Function} [opts.recHook] 引擎 call-ID 取证钩子 id=>void(取证路径注入 window.__engineCalls.push;渠道产物不注)。
+ * @param {Function} [opts.onReady] (host, internals)=>void 就绪回调(取证收集 internals.uncaught 等)。
+ * @param {any} [opts.engine] 覆盖引擎名字空间(缺省动态 import littlejsengine)。
+ * @returns {Promise} bootGameHost 的 host 句柄(frameCount/stepFrames/tap/do/state 等)。
+ */
+export async function bootGameHost(opts) {
+  const o = opts || {};
+  // 动态 import 引擎:求值时机延后到本函数被调用(浏览器运行期)。esbuild 内联,无外部请求。
+  const engine = o.engine || (await import('littlejsengine'));
+  // 主随机种子(缺省固定值,与 ref 取证同口径,保确定性可复现)。
+  const seed = (o.seed != null ? o.seed : 0x1234abcd) >>> 0;
+  // 复用 ref 标准装配(7 插件 + 偏序 + 视口 + 工厂 wiring)。
+  const cfg = buildRefHostConfig({ seed });
+  // 调通用宿主:real 通道引擎掌帧;factory override 为本目录生成工厂;其余 wiring 取标准集。
+  return bootGameHostCore({
+    canvas: o.canvas,
+    statusEl: o.statusEl || null,
+    engine,
+    seed,
+    mode: o.mode || 'play',           // W-G1 真玩=play
+    engineMode: 'real',               // 一律引擎掌帧(real 通道)
+    viewport: cfg.viewport,           // 390×844(与 ref 同,移动竖屏基准)
+    factory: gameFactory,             // ★ override:本目录【生成的游戏】(其余 wiring 全复用 ref)
+    plugins: cfg.plugins,             // 标准 7 插件实例集(经 opts.runtime.plugins 注入给工厂)
+    registerOrder: cfg.registerOrder, // 注册偏序(保六锚)
+    buildFactoryOpts: cfg.buildFactoryOpts, // 注入 runtime:{plugins,bundle,getRealAudioCtx}
+    recHook: o.recHook || null,       // 取证:引擎 call-ID 探针(默认 no-op)
+    onReady: o.onReady || null,       // 取证:收集 internals(uncaught)
+  });
+}
diff --git a/game-runtime/games/_wg1-gen/simon_pro/evidence/after-play.png b/game-runtime/games/_wg1-gen/simon_pro/evidence/after-play.png
new file mode 100644
index 00000000..f25c9e4d
Binary files /dev/null and b/game-runtime/games/_wg1-gen/simon_pro/evidence/after-play.png differ
diff --git a/game-runtime/games/_wg1-gen/simon_pro/evidence/first-paint.png b/game-runtime/games/_wg1-gen/simon_pro/evidence/first-paint.png
new file mode 100644
index 00000000..2a6e1451
Binary files /dev/null and b/game-runtime/games/_wg1-gen/simon_pro/evidence/first-paint.png differ
diff --git a/game-runtime/games/_wg1-gen/simon_pro/evidence/verdict.json b/game-runtime/games/_wg1-gen/simon_pro/evidence/verdict.json
new file mode 100644
index 00000000..e5ac180c
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon_pro/evidence/verdict.json
@@ -0,0 +1,61 @@
+{
+  "gameId": "simon_pro",
+  "url": "http://localhost:4320/games/_wg1-gen/simon_pro/index.html",
+  "ts": null,
+  "guards": {
+    "A_boot": {
+      "pass": true
+    },
+    "C_frame": {
+      "pass": true,
+      "f0": 49,
+      "f1": 79,
+      "delta": 30
+    },
+    "D_render": {
+      "pass": true,
+      "bright": 279271,
+      "maxCh": 255
+    },
+    "E_live": {
+      "pass": true,
+      "distinctStates": 7,
+      "samples": 11
+    },
+    "B_uncaught": {
+      "pass": true,
+      "uncaught": []
+    },
+    "F_wiring": {
+      "pass": true,
+      "callCount": 611,
+      "sample": [
+        "audio.synth.synthSfx",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut"
+      ],
+      "expected": [
+        "audio.synth",
+        "particles."
+      ]
+    },
+    "G_input": {
+      "pass": true,
+      "inputHash": "2306aab3",
+      "controlHash": "33f7eb0b",
+      "atFrame": 399,
+      "ctrlFrame": 403
+    }
+  },
+  "pass": true,
+  "notes": []
+}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/simon_pro/factory.js b/game-runtime/games/_wg1-gen/simon_pro/factory.js
new file mode 100644
index 00000000..70abb1cf
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon_pro/factory.js
@@ -0,0 +1,244 @@
+'use strict';
+/**
+ * factory.js — Simon (记忆复现) 游戏宿主工厂
+ * 严守受控面铁律:零引擎 import、零 Math.random / Date.now / addEventListener / new AudioContext / RAF;
+ *   能力一律经 boot.ctx;render 只画到入参 g(=boot.mainContext)。
+ */
+export default function createSimonGame(opts) {
+  const o = opts || {};
+  let ctx = null;
+  let nowMs = 0;
+  let sub = null;                  // pointerdown 订阅句柄
+
+  // ---- 游戏状态 ----
+  const BTN_W = 130, BTN_H = 130, GAP = 20;
+  const BTN_POS = [
+    { x: 55,  y: 282 },  // 0: 红
+    { x: 205, y: 282 },  // 1: 绿
+    { x: 55,  y: 432 },  // 2: 蓝
+    { x: 205, y: 432 }   // 3: 黄
+  ];
+  const DARK_COLORS = ['rgb(100,0,0)', 'rgb(0,100,0)', 'rgb(0,0,100)', 'rgb(100,100,0)'];
+  const LIGHT_COLORS = ['rgb(255,0,0)', 'rgb(0,255,0)', 'rgb(0,0,255)', 'rgb(255,255,0)'];
+  
+  // 每个按钮的合成音效参数(ZzFX 参数包)
+  const TONES = [
+    [1, 0.05, 220, , , 0.1, , 1.0], // 红
+    [1, 0.05, 330, , , 0.1, , 1.0], // 绿
+    [1, 0.05, 440, , , 0.1, , 1.0], // 蓝
+    [1, 0.05, 554, , , 0.1, , 1.0]  // 黄
+  ];
+  const FAIL_SFX = [1, 0.1, 100, , , 0.5, , 0.5];
+
+  let seq = [];                   // 当前序列(颜色索引 0-3)
+  let computerStep = 0;           // 电脑当前播放到第几步
+  let playerStep = 0;             // 玩家当前输入到第几步
+  let lastStepTime = 0;           // 上一步开始的时间(ms)
+  let stepStartTime = 0;          // 当前步骤开始的时间(用于高亮动画)
+  let activeButton = -1;          // 当前高亮的按钮索引(电脑播放用)
+  let playerClickedButton = -1;   // 玩家点击瞬亮的按钮
+  let playerClickTime = 0;        // 玩家点击的时刻
+  let phase = 'idle';             // 'idle' | 'computer' | 'player' | 'success' | 'fail'
+  let waitTime = 0;               // 等待结束的时间(success/fail 过渡用)
+
+  // ---- 工具方法 ----
+  function randomColor() {
+    return Math.floor(ctx.random.range(0, 4));
+  }
+
+  function playSound(idx) {
+    const eng = ctx.getEngine();
+    if (eng && eng.audio && eng.audio.synth) {
+      try { eng.audio.synth.synthSfx(TONES[idx]); } catch (_) {}
+    }
+  }
+
+  function playFailSound() {
+    const eng = ctx.getEngine();
+    if (eng && eng.audio && eng.audio.synth) {
+      try { eng.audio.synth.synthSfx(FAIL_SFX); } catch (_) {}
+    }
+  }
+
+  function spawnParticles(type) {
+    const eng = ctx.getEngine();
+    if (eng && eng.particles) {
+      try {
+        eng.particles.spawnEmitter({
+          pos: { x: 195, y: 422 },
+          count: 35,
+          speed: 180,
+          particleTime: 0.7,
+          colorStart: type === 'success'
+            ? { r: 1, g: 1, b: 0.3, a: 1 }
+            : { r: 1, g: 0.2, b: 0.2, a: 1 },
+          colorEnd: type === 'success'
+            ? { r: 1, g: 0.7, b: 0, a: 0 }
+            : { r: 0.6, g: 0, b: 0, a: 0 }
+        });
+      } catch (_) {}
+    }
+  }
+
+  function startNewRound(now) {
+    seq.push(randomColor());
+    phase = 'computer';
+    computerStep = 0;
+    playerStep = 0;
+    lastStepTime = now;
+    activeButton = seq[0];
+    stepStartTime = now;
+    playSound(activeButton);
+  }
+
+  // ---- 输入处理 ----
+  function handleTap(e) {
+    if (phase !== 'player') return;
+    const px = e.x || 0, py = e.y || 0;
+    let idx = -1;
+    for (let i = 0; i < 4; i++) {
+      const b = BTN_POS[i];
+      if (px >= b.x && px <= b.x + BTN_W && py >= b.y && py <= b.y + BTN_H) {
+        idx = i;
+        break;
+      }
+    }
+    if (idx === -1) return;
+    if (idx === seq[playerStep]) {
+      // 正确
+      playSound(idx);
+      playerClickedButton = idx;
+      playerClickTime = nowMs;
+      playerStep++;
+      if (playerStep >= seq.length) {
+        // 整轮答对
+        phase = 'success';
+        waitTime = nowMs + 1500;
+        spawnParticles('success');
+      }
+    } else {
+      // 错误
+      phase = 'fail';
+      waitTime = nowMs + 1000;
+      spawnParticles('fail');
+      playFailSound();
+      seq = [];
+    }
+  }
+
+  // ---- 生命周期 ----
+  function init(boot) {
+    ctx = boot.ctx;
+    sub = ctx.getInput().on('pointerdown', handleTap);
+    nowMs = ctx.time.nowMs();
+    // 开局立即开始第一轮
+    startNewRound(nowMs);
+  }
+
+  function update(dt) {
+    nowMs = ctx.time.nowMs();
+
+    // 保险:每帧触发一次 math.lerp,确保引擎叶调用信号
+    const eng = ctx.getEngine();
+    if (eng && eng.math) { try { eng.math.lerp(0, 1, 0.5); } catch (_) {} }
+
+    // 状态驱动
+    switch (phase) {
+      case 'computer': {
+        if (nowMs - lastStepTime >= 500) {
+          computerStep++;
+          lastStepTime = nowMs;
+          if (computerStep < seq.length) {
+            activeButton = seq[computerStep];
+            stepStartTime = nowMs;
+            playSound(activeButton);
+          } else {
+            // 电脑播放完,轮到玩家
+            activeButton = -1;
+            phase = 'player';
+            playerStep = 0;
+          }
+        }
+        break;
+      }
+      case 'success': {
+        if (nowMs >= waitTime) {
+          // 开始新轮
+          startNewRound(nowMs);
+        }
+        break;
+      }
+      case 'fail': {
+        if (nowMs >= waitTime) {
+          // 重置从长度 1 开始
+          seq = [];
+          startNewRound(nowMs);
+        }
+        break;
+      }
+      default: break;
+    }
+
+    // 玩家点击高亮持续 200ms
+    if (playerClickedButton >= 0 && nowMs - playerClickTime > 200) {
+      playerClickedButton = -1;
+    }
+  }
+
+  function render(g) {
+    // 背景
+    g.fillStyle = '#101820';
+    g.fillRect(0, 0, 390, 844);
+
+    // 绘制四个按钮
+    for (let i = 0; i < 4; i++) {
+      const { x, y } = BTN_POS[i];
+      let isActive = false;
+      let elapsed = 0;
+
+      if (phase === 'computer' && activeButton === i) {
+        isActive = true;
+        elapsed = nowMs - stepStartTime;
+      } else if (playerClickedButton === i) {
+        isActive = true;
+        elapsed = nowMs - playerClickTime;
+      }
+
+      // 暗态底色
+      g.fillStyle = DARK_COLORS[i];
+      g.fillRect(x, y, BTN_W, BTN_H);
+
+      if (isActive) {
+        const eng = ctx.getEngine();
+        // 计算缩放因子,使用 easing(防御式回退)
+        let t = Math.min(elapsed / 500, 1);  // 统一用 500ms 周期
+        let eased = t;
+        if (eng && eng.math && eng.math.easing) {
+          try { eased = eng.math.easing.quadOut(t); } catch (_) { eased = t; }
+        }
+        const scale = 1 + 0.18 * eased;
+
+        g.save();
+        const cx = x + BTN_W / 2, cy = y + BTN_H / 2;
+        g.translate(cx, cy);
+        g.scale(scale, scale);
+        g.fillStyle = LIGHT_COLORS[i];
+        g.fillRect(-BTN_W / 2, -BTN_H / 2, BTN_W, BTN_H);
+        g.restore();
+      }
+    }
+
+    // 当前轮数文字(可选)
+    g.fillStyle = '#8899aa';
+    g.font = '18px monospace';
+    g.fillText('Round: ' + seq.length, 150, 180);
+  }
+
+  function destroy() {
+    try { sub && sub.cancel(); } catch (_) {}
+    sub = null;
+    seq = [];
+  }
+
+  return { init, update, render, destroy };
+}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/simon_pro/index.html b/game-runtime/games/_wg1-gen/simon_pro/index.html
new file mode 100644
index 00000000..d5dd623c
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/simon_pro/index.html
@@ -0,0 +1,83 @@
+
+
+
+
+  
+  
+  
+  W-G1 generated game
+  
+
+
+  
+
booting…
+ + +
+ + + + + + diff --git a/game-runtime/games/_wg1-gen/simon_pro/play-spec.json b/game-runtime/games/_wg1-gen/simon_pro/play-spec.json new file mode 100644 index 00000000..f19592aa --- /dev/null +++ b/game-runtime/games/_wg1-gen/simon_pro/play-spec.json @@ -0,0 +1,48 @@ +{ + "inputs": [ + { + "t": "wait", + "ms": 1300 + }, + { + "t": "tap", + "x": 130, + "y": 360 + }, + { + "t": "wait", + "ms": 350 + }, + { + "t": "tap", + "x": 260, + "y": 360 + }, + { + "t": "wait", + "ms": 350 + }, + { + "t": "tap", + "x": 130, + "y": 500 + }, + { + "t": "wait", + "ms": 350 + }, + { + "t": "tap", + "x": 260, + "y": 500 + }, + { + "t": "wait", + "ms": 350 + } + ], + "expectedEngineCallPrefixes": [ + "audio.synth", + "particles." + ] +} \ No newline at end of file diff --git a/game-runtime/games/_wg1-gen/whack/bundle.iife.js b/game-runtime/games/_wg1-gen/whack/bundle.iife.js new file mode 100644 index 00000000..e2d9b017 --- /dev/null +++ b/game-runtime/games/_wg1-gen/whack/bundle.iife.js @@ -0,0 +1,34 @@ +"use strict";var __GameBundle=(()=>{var So=Object.defineProperty;var Yl=Object.getOwnPropertyDescriptor;var $l=Object.getOwnPropertyNames;var Xl=Object.prototype.hasOwnProperty;var Kl=(t,e,n)=>()=>{if(n)throw n[0];try{return t&&(e=t(t=0)),e}catch(s){throw n=[s],s}};var Ba=(t,e)=>{for(var n in e)So(t,n,{get:e[n],enumerable:!0})},Ql=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of $l(e))!Xl.call(t,i)&&i!==n&&So(t,i,{get:()=>e[i],enumerable:!(s=Yl(e,i))||s.enumerable});return t};var Zl=t=>Ql(So({},"__esModule",{value:!0}),t);var ql={};Ba(ql,{ASSERT:()=>m,BLACK:()=>ye,BLUE:()=>dl,Box2dDistanceJoint:()=>Zi,Box2dFrictionJoint:()=>Jr,Box2dGearJoint:()=>Fr,Box2dJoint:()=>at,Box2dKinematicObject:()=>Mr,Box2dMotorJoint:()=>zr,Box2dObject:()=>Zs,Box2dPinJoint:()=>Or,Box2dPlugin:()=>eo,Box2dPrismaticJoint:()=>Gr,Box2dPulleyJoint:()=>Nr,Box2dRaycastResult:()=>Qi,Box2dRevoluteJoint:()=>Dr,Box2dRopeJoint:()=>Ir,Box2dStaticObject:()=>Ki,Box2dTargetJoint:()=>Lr,Box2dTileLayer:()=>Rr,Box2dWeldJoint:()=>jr,Box2dWheelJoint:()=>Br,CLEAR_BLACK:()=>kt,CLEAR_WHITE:()=>Sn,CYAN:()=>Td,CanvasLayer:()=>Ji,Color:()=>De,Ease:()=>no,EngineObject:()=>Qt,GRAY:()=>vd,GREEN:()=>ul,ImageFont:()=>Ii,LOG:()=>Pe,Light:()=>vr,LightSystemPlugin:()=>Sr,MAGENTA:()=>Ad,Medal:()=>$i,NewgroundsMedal:()=>gr,NewgroundsPlugin:()=>br,ORANGE:()=>wd,PI:()=>re,PURPLE:()=>fl,Particle:()=>Ni,ParticleEmitter:()=>ur,PathFinder:()=>Ur,PathFinderNode:()=>so,PostProcessPlugin:()=>xr,RED:()=>Xr,RandomGenerator:()=>or,Sound:()=>Vs,SoundInstance:()=>Bi,TextureInfo:()=>Zt,TileCollisionLayer:()=>Ws,TileInfo:()=>Bt,TileLayer:()=>qs,TileLayerData:()=>Bn,Timer:()=>Dt,Tween:()=>to,UIButton:()=>Qs,UICheckbox:()=>Cr,UILayout:()=>Pr,UIObject:()=>bt,UISlider:()=>_r,UISystemPlugin:()=>Tr,UIText:()=>Xi,UITextInput:()=>Ar,UITile:()=>kr,UIVideo:()=>Er,Vector2:()=>Se,WHITE:()=>te,YELLOW:()=>ll,ZzFXMusic:()=>wr,abs:()=>pe,atan2:()=>Hr,audioContext:()=>ke,audioDefaultSampleRate:()=>xs,audioIsRunning:()=>Us,audioMasterGain:()=>Kt,box2d:()=>b,box2dDebug:()=>Fa,box2dInit:()=>jh,box2dSetDebug:()=>Bh,cameraAngle:()=>de,cameraFit:()=>Bf,cameraPos:()=>je,cameraScale:()=>oe,canvasClearColor:()=>mn,canvasColorTiles:()=>oo,canvasFixedSize:()=>ss,canvasMaxAspect:()=>ns,canvasMaxSize:()=>ts,canvasMinAspect:()=>Rs,canvasPixelRatio:()=>yn,canvasPixelated:()=>Zr,ceil:()=>Fs,clamp:()=>X,combineCanvases:()=>fa,cos:()=>ve,debug:()=>Ye,debugCircle:()=>nt,debugClear:()=>dd,debugLine:()=>Lt,debugOverlap:()=>sr,debugOverlay:()=>Ut,debugPoint:()=>Wr,debugPointSize:()=>Hc,debugPoly:()=>ud,debugRect:()=>Ee,debugScreenshot:()=>$c,debugShowErrors:()=>fd,debugText:()=>es,debugVideoCaptureIsActive:()=>Ot,debugVideoCaptureStart:()=>Xc,debugVideoCaptureStop:()=>Kc,debugWatermark:()=>io,distanceAngle:()=>bd,distanceWrap:()=>Yr,drawCanvas2D:()=>Vn,drawCircle:()=>Oi,drawCircleGradient:()=>Df,drawContext:()=>Ge,drawCount:()=>Ft,drawCrescent:()=>zh,drawEllipse:()=>yl,drawEllipseGradient:()=>gl,drawLine:()=>On,drawLineList:()=>ar,drawNineSlice:()=>jl,drawNineSliceScreen:()=>Jh,drawPoly:()=>us,drawRect:()=>Li,drawRectGradient:()=>Lf,drawRegularPoly:()=>ml,drawText:()=>Ff,drawTextScreen:()=>gn,drawTextureWrapped:()=>Of,drawThreeSlice:()=>Jl,drawThreeSliceScreen:()=>Nh,drawTile:()=>Ue,enablePhysicsSolver:()=>lo,engineAddPlugin:()=>zn,engineImageFont:()=>vl,engineInit:()=>rd,engineName:()=>Ti,engineObjects:()=>Me,engineObjectsCallback:()=>cd,engineObjectsCollect:()=>Wc,engineObjectsCollide:()=>qr,engineObjectsDestroy:()=>ad,engineObjectsRaycast:()=>ld,engineObjectsUpdate:()=>qc,engineVersion:()=>Ai,fetchJSON:()=>kd,floor:()=>Ie,fontDefault:()=>ei,formatTime:()=>Kr,frame:()=>Uc,frameRate:()=>sd,gamepadConnected:()=>lr,gamepadDirectionEmulateStick:()=>ra,gamepadDpad:()=>cr,gamepadIsDown:()=>zt,gamepadPrimary:()=>_e,gamepadStick:()=>Ns,gamepadStickCount:()=>wl,gamepadVibrate:()=>Zf,gamepadVibrateStop:()=>eh,gamepadWasPressed:()=>ba,gamepadWasReleased:()=>Qf,gamepadsEnable:()=>uo,getCameraSize:()=>xl,getCrescentPoints:()=>Nl,getNoteFrequency:()=>_l,getPaused:()=>id,glAntialias:()=>Aa,glCanvas:()=>he,glCircleSides:()=>ti,glClearCanvas:()=>Ll,glClearRect:()=>Gl,glCompileShader:()=>yr,glContext:()=>g,glCopyToContext:()=>Pa,glCreateProgram:()=>ms,glCreateTexture:()=>mo,glDeleteTexture:()=>Il,glDraw:()=>$s,glDrawColoredPoints:()=>La,glDrawOutlineTransform:()=>Ra,glDrawPoints:()=>Fl,glDrawPointsTransform:()=>Ma,glDrawUntextured:()=>Dl,glEnable:()=>H,glFlush:()=>Je,glSetAntialias:()=>_h,glSetRenderTarget:()=>Ms,glSetTexture:()=>_a,glSetTextureData:()=>Ea,glSetTextureWrap:()=>Ol,gravity:()=>st,headlessMode:()=>K,hsl:()=>qt,hypot:()=>Qc,inputClear:()=>ai,inputClearKey:()=>ya,inputMouseMoveThreshold:()=>ma,inputPreventDefault:()=>is,inputWASDEmulateDirection:()=>Ls,isArray:()=>Tt,isColor:()=>Z,isFullscreen:()=>Sl,isIntersecting:()=>nl,isNumber:()=>I,isOnScreen:()=>jf,isOverlapping:()=>Ei,isPowerOfTwo:()=>Gs,isStringLike:()=>ee,isTouchDevice:()=>yt,isUsingGamepad:()=>rs,isVector2:()=>D,keyDirection:()=>Xf,keyIsDown:()=>ze,keyWasPressed:()=>We,keyWasReleased:()=>ga,lastInputDevice:()=>hn,lerp:()=>it,lerpAngle:()=>xd,lerpWrap:()=>tl,lightSystem:()=>ie,lineTest:()=>il,log2:()=>Zc,mainCanvas:()=>$,mainCanvasSize:()=>z,mainContext:()=>we,max:()=>ue,medalDisplaySize:()=>Hi,medalDisplaySlideTime:()=>os,medalDisplayTime:()=>Wi,medals:()=>Xs,medalsForEach:()=>yo,medalsInit:()=>Rh,medalsPreventUnlock:()=>Oa,medalsReset:()=>Lh,min:()=>fe,mod:()=>mt,mouseDelta:()=>ha,mouseDeltaScreen:()=>Pt,mouseInWindow:()=>Di,mouseIsDown:()=>Is,mousePos:()=>Nt,mousePosScreen:()=>tt,mouseWasPressed:()=>Js,mouseWasReleased:()=>Kf,mouseWheel:()=>pa,nearestPowerOfTwo:()=>Sd,newgrounds:()=>Ks,noise1D:()=>Md,noise2D:()=>Rd,objectDefaultAngleDamping:()=>sa,objectDefaultDamping:()=>na,objectDefaultFriction:()=>oa,objectDefaultMass:()=>ta,objectDefaultRestitution:()=>ia,objectMaxSpeed:()=>Wt,oscillate:()=>sl,particleEmitRateScale:()=>Pi,paused:()=>It,percent:()=>$e,percentLerp:()=>gd,playSamples:()=>Ta,pointerLockExit:()=>sh,pointerLockIsActive:()=>Tl,pointerLockRequest:()=>nh,postProcess:()=>qe,primitiveCount:()=>Gt,rand:()=>Ae,randBool:()=>ol,randColor:()=>ir,randInCircle:()=>cl,randInt:()=>$r,randSign:()=>rl,randVec2:()=>al,readSaveData:()=>Ed,rgb:()=>Q,round:()=>Ci,saveCanvas:()=>hl,saveDataURL:()=>Bs,saveText:()=>Cd,screenToWorld:()=>oi,screenToWorldDelta:()=>bl,screenToWorldTransform:()=>ri,setAdditiveBlendMode:()=>js,setCameraAngle:()=>Od,setCameraPos:()=>Ld,setCameraScale:()=>Id,setCanvasClearColor:()=>Gd,setCanvasColorTiles:()=>Fd,setCanvasFixedSize:()=>Nd,setCanvasMaxAspect:()=>Jd,setCanvasMaxSize:()=>Bd,setCanvasMinAspect:()=>jd,setCanvasPixelRatio:()=>Ud,setCanvasPixelated:()=>pl,setCursor:()=>Uf,setDebugKey:()=>Rf,setDebugWatermark:()=>Mf,setEnablePhysicsSolver:()=>Qd,setFontDefault:()=>Vd,setGLCircleSides:()=>Yd,setGLEnable:()=>Hd,setGamepadDirectionEmulateStick:()=>lf,setGamepadsEnable:()=>cf,setGravity:()=>rf,setHeadlessMode:()=>Wd,setInputMouseMoveThreshold:()=>Wf,setInputPreventDefault:()=>qf,setInputWASDEmulateDirection:()=>uf,setMedalDisplaySize:()=>Dh,setMedalDisplaySlideTime:()=>Ih,setMedalDisplayTime:()=>Oh,setMedalsPreventUnlock:()=>Fh,setObjectDefaultAngleDamping:()=>tf,setObjectDefaultDamping:()=>ef,setObjectDefaultFriction:()=>sf,setObjectDefaultMass:()=>Zd,setObjectDefaultRestitution:()=>nf,setObjectMaxSpeed:()=>of,setParticleEmitRateScale:()=>af,setPaused:()=>od,setShowSplashScreen:()=>qd,setSoundDefaultRange:()=>Ef,setSoundDefaultTaper:()=>Pf,setSoundEnable:()=>Cf,setSoundVolume:()=>_f,setTileDefaultBleed:()=>Kd,setTileDefaultPadding:()=>Xd,setTileDefaultSize:()=>$d,setTilesPixelated:()=>zd,setTimeScale:()=>Dd,setTouchGamepadAlpha:()=>wf,setTouchGamepadAnalog:()=>xf,setTouchGamepadButtonCount:()=>mf,setTouchGamepadCenterButtonSize:()=>pf,setTouchGamepadDisplayTime:()=>Tf,setTouchGamepadEnable:()=>ff,setTouchGamepadFloating:()=>Sf,setTouchGamepadLeftButtonCount:()=>gf,setTouchGamepadLeftStick:()=>yf,setTouchGamepadPassthrough:()=>hf,setTouchGamepadRightStick:()=>bf,setTouchGamepadSize:()=>vf,setTouchGamepadVibration:()=>Af,setTouchInputEnable:()=>df,setVibrateEnable:()=>kf,shareURL:()=>_d,showSplashScreen:()=>ea,sign:()=>pt,sin:()=>me,smoothStep:()=>_i,soundDefaultRange:()=>la,soundDefaultTaper:()=>ua,soundEnable:()=>rt,soundVolume:()=>Gn,speak:()=>bh,speakStop:()=>xh,tan:()=>el,textureInfos:()=>wn,tile:()=>ii,tileCollisionGetData:()=>ji,tileCollisionLayers:()=>bn,tileCollisionRaycast:()=>El,tileCollisionTest:()=>dn,tileDefaultBleed:()=>co,tileDefaultPadding:()=>ao,tileDefaultSize:()=>ro,tileLayersLoad:()=>vh,tilesPixelated:()=>jn,time:()=>dt,timeDelta:()=>Vr,timeReal:()=>xn,timeScale:()=>Qr,toggleFullscreen:()=>zf,touchGamepadAlpha:()=>ca,touchGamepadAnalog:()=>ni,touchGamepadButtonCount:()=>ys,touchGamepadCenterButtonSize:()=>At,touchGamepadDisplayTime:()=>Os,touchGamepadEnable:()=>vn,touchGamepadFloating:()=>Tn,touchGamepadLeftButtonCount:()=>gs,touchGamepadLeftStick:()=>Un,touchGamepadPassthrough:()=>aa,touchGamepadRightStick:()=>bs,touchGamepadSize:()=>ot,touchGamepadVibration:()=>Mi,touchInputEnable:()=>Ln,tweenProperty:()=>Uh,tweenStopAll:()=>Vh,tweenUpdate:()=>Vl,uiDebug:()=>Da,uiSetDebug:()=>Gh,uiSystem:()=>P,usingGamepadInput:()=>$f,usingKeyboardInput:()=>Yf,usingMouseInput:()=>Hf,vec2:()=>v,vibrate:()=>xa,vibrateEnable:()=>si,vibrateStop:()=>th,workCanvas:()=>$t,workContext:()=>fn,workReadCanvas:()=>Rt,workReadContext:()=>Ht,worldToScreen:()=>qn,worldToScreenDelta:()=>Gf,writeSaveData:()=>Pd,zzfx:()=>Sh,zzfxG:()=>ho,zzfxM:()=>Bl});function id(){return It}function od(t=!0){It=t}function zn(t,e,n,s){m(!In.find(r=>r.update===t&&r.render===e&&r.glContextLost===n&&r.glContextRestored===s));let i=new tr(t,e,n,s);In.push(i)}async function rd(t,e,n,s,i,r=[],a){if(Vc&&console.log(`${Ti} Engine v${Ai}`),m(!we,"engine already initialized"),we)return;m(Tt(r),"pass in images as array"),document.body||document.documentElement.appendChild(document.createElement("body")),a||(a=document.body),t||(t=()=>{}),e||(e=()=>{}),n||(n=()=>{}),s||(s=()=>{}),i||(i=()=>{});function o(){z=v($.width,$.height),we.imageSmoothingEnabled=!jn,mr()}function c(p=0){let y=p-Qo;Qo||(y=0),Qo=p,(Ye||io)&&(ki=it(ki,1e3/(y||1),.05));let x=Ye&&ze("Equal"),w=Ye&&ze("Minus"),A=x?10:w?.1:1;xn+=y*A/1e3;let S=Qr*A;y*=S,Et+=It?0:y,S<=1&&(Et=fe(Et,50));let _=!1;if(It){_=!0,l(),Gc(),In.forEach(C=>{var O;return(O=C.update)==null?void 0:O.call(C)});for(let C of Me)C.parent||C.updateTransforms();Oc(),n(),Bc(),Ot()&&k()}else{let C=0;for(Et<0&&Et>-9&&(C=Et,Et=0);Et>=0;Et-=1e3/60)dt=Uc++/60,_=!0,l(),Gc(),e(),In.forEach(O=>{var q;return(q=O.update)==null?void 0:q.call(O)}),qc(),Oc(),n(),Bc(),Ot()&&k();Et+=C}Ot()||k(),requestAnimationFrame(c);function k(){if(!K){_||l(),o(),s(),Me.sort((C,O)=>C.renderOrder-O.renderOrder);for(let C of Me)C.destroyed||C.render();i(),In.forEach(C=>{var O;return(O=C.render)==null?void 0:O.call(C)}),oh(),pd(),Je(),md(),Ft=0,Gt=0}}}function l(){if(!K){if(ss.x){z=ss.copy();let p=innerWidth/innerHeight,y=ss.x/ss.y,x=pns){let _=z.y*ns|0;z.x=fe(_,ts.x)}else if(w0&&!H&&(we.fillStyle=mn.toString(),we.fillRect(0,0,z.x,z.y),we.fillStyle=ye.toString()),we.lineJoin="round",we.lineCap="round"}}if(K)return f();Ah(a);let u="margin:0;overflow:hidden;background:#000;user-select:none;-webkit-user-select:none;touch-action:none;-webkit-touch-callout:none";a.style.cssText=u,$=a.appendChild(document.createElement("canvas")),Ge=we=$.getContext("2d"),ih(),gh(),hd();let h="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)";$.style.cssText=h,he&&(he.style.cssText=h),pl(Zr),l(),mr(),$t=new OffscreenCanvas(64,64),fn=$t.getContext("2d"),Rt=new OffscreenCanvas(64,64),Ht=Rt.getContext("2d",{willReadFrequently:!0});let d=r.map((p,y)=>Dc(y,p));return r.length||d.push(Dc(0)),d.push(Vf()),ea&&d.push(new Promise(p=>{let y=0;x();function x(){ai(),Mh(y+=.01),y>1?p():setTimeout(x,16)}})),await Promise.all(d),f();async function f(){await t(),c()}}function qc(){qr=Me.filter(e=>e.collideSolidObjects);function t(e){if(!e.destroyed){e.update();for(let n of e.children)t(n)}}for(let e of Me)if(!(e.parent||e.destroyed)){e.update(),e.updatePhysics();for(let n of e.children)t(n);e.updateTransforms()}Me=Me.filter(e=>!e.destroyed)}function ad(t=!0){for(let e of Me)e.parent||e.destroy(t);Me=Me.filter(e=>!e.destroyed)}function Wc(t,e,n=Me){let s=[];if(t)if(e instanceof Se)for(let i of n)i.isOverlapping(t,e)&&s.push(i);else{let i=e*e;for(let r of n)t.distanceSquared(r.pos)n(i))}function ld(t,e,n=Me){let s=[];for(let i of n)i.collideRaycast&&nl(t,e,i.pos,i.size)&&(wt&&Ee(i.pos,i.size,"#f00"),s.push(i));return wt&&Lt(t,e,s.length?"#f00":"#00f",.02),s}function m(t,...e){if(!t)throw console.assert(t,...e),new Error("Assert failed!")}function Pe(...t){console.log(...t)}function Ee(t,e=v(),n=te,s=0,i=0,r=!1,a=!1){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(ee(n)||Z(n),"color is invalid"),m(I(s),"time must be a number"),m(I(i),"angle must be a number"),Z(n)&&(n=n.toString());let o=new Dt(s);pn.push({pos:t.copy(),size:e.copy(),color:n,timer:o,angle:i,fill:r,screenSpace:a})}function ud(t,e,n=te,s=0,i=0,r=!1,a=!1){m(D(t),"pos must be a vec2"),m(Tt(e),"points must be an array"),m(ee(n)||Z(n),"color is invalid"),m(I(s),"time must be a number"),m(I(i),"angle must be a number"),Z(n)&&(n=n.toString()),t=t.copy(),e=e.map(c=>c.copy());let o=new Dt(s);pn.push({pos:t,points:e,color:n,timer:o,angle:i,fill:r,screenSpace:a})}function nt(t,e=0,n=te,s=0,i=!1,r=!1){m(D(t),"pos must be a vec2"),m(I(e),"size must be a number"),m(ee(n)||Z(n),"color is invalid"),m(I(s),"time must be a number"),Z(n)&&(n=n.toString()),t=t.copy();let a=new Dt(s);pn.push({pos:t,size:e,color:n,timer:a,angle:0,fill:i,screenSpace:r})}function Wr(t,e,n,s,i=!1){Ee(t,void 0,e,n,s,!1,i)}function Lt(t,e,n,s=.1,i=0,r=!1){m(D(t),"posA must be a vec2"),m(D(e),"posB must be a vec2"),m(I(s),"width must be a number");let a=v((e.x-t.x)/2,(e.y-t.y)/2),o=v(s,a.length()*2);Ee(t.add(a),o,n,i,a.angle(),!0,r)}function sr(t,e,n,s,i,r,a=!1){m(D(t),"posA must be a vec2"),m(D(n),"posB must be a vec2"),m(D(e),"sizeA must be a vec2"),m(D(s),"sizeB must be a vec2");let o=v(fe(t.x-e.x/2,n.x-s.x/2),fe(t.y-e.y/2,n.y-s.y/2)),c=v(ue(t.x+e.x/2,n.x+s.x/2),ue(t.y+e.y/2,n.y+s.y/2));Ee(o.lerp(c,.5),c.subtract(o),i,r,0,!1,a)}function es(t,e,n=1,s=te,i=0,r=0,a="monospace",o=!1){m(ee(t),"text must be a string"),m(D(e),"pos must be a vec2"),m(I(n),"size must be a number"),m(ee(s)||Z(s),"color is invalid"),m(I(i),"time must be a number"),m(I(r),"angle must be a number"),m(ee(a),"font must be a string"),Z(s)&&(s=s.toString()),e=e.copy();let c=new Dt(i);pn.push({text:t,pos:e,size:n,color:s,timer:c,angle:r,font:a,screenSpace:o})}function dd(){pn=[]}function $c(){nr=1}function fd(){let t=n=>{document.body.style="background-color:#111;margin:8px",document.body.innerHTML="
"+n},e=console.assert;console.assert=(n,...s)=>{if(e(n,...s),!n){let i=s.join(" "),r=new Error().stack;throw`Assertion failed!
+`+i+`
+`+r}},onunhandledrejection=n=>t(n.reason.stack||n.reason),onerror=(n,s,i,r)=>t(`${n}
+${s}
+Ln ${i}, Col ${r}`)}function hd(){Vc&&console.warn("LittleJS DEBUG build loaded. Use the release build for production.")}function Oc(){Ye&&(We(Yc)&&(Ut=!Ut),Ut&&(We("Digit1")&&(vt=!vt,Dn=!1),We("Digit2")&&(Dn=!Dn,vt=!1),We("Digit3")&&(Fn=!Fn),We("Digit4")&&(wt=!wt),We("Digit5")&&$c(),We("Digit7")&&(ls=!ls)),Ot()?(!Ut||We("Digit6"))&&Kc():Ut&&We("Digit6")&&Xc())}function pd(){if(Ot())return;Je();let t=Ft,e=Gt;nr&&(fa(),hl($),nr=0);let n=we;if(Fn&&uo){let r=0;for(let a=0;a<8;a++)lr(a)&&r++;for(let a=0;a<8;a++){if(!lr(a))continue;let o=1,c=.2,l=je.add(v(-o*2,((r-1)/2-a)*o*3));es(a,l.add(v(-o,o)),1),a===_e&&es("Main",l.add(v(-o*2,0)),1,"#0f0");let u=Mt[a].length;for(let d=0;d{n.save();let r=i.pos,a=1,o=i.angle;if(i.screenSpace||(r=qn(i.pos),a=oe,o-=de),n.translate(r.x|0,r.y|0),n.rotate(o),n.scale(1,i.text?1:-1),n.fillStyle=i.color,n.strokeStyle=i.color,i.text!==void 0)n.font=i.size*a+"px "+i.font,n.textAlign="center",n.textBaseline="middle",n.fillText(i.text,0,0);else if(i.points!==void 0){n.beginPath();for(let c of i.points){let l=c.scale(a).floor();n.lineTo(l.x,l.y)}n.closePath(),i.fill&&n.fill(),n.stroke()}else if(i.size===0||i.size.x===0&&i.size.y===0){let c=Hc*a;n.fillRect(-c/2,-1,c,3),n.fillRect(-1,-c/2,3,c)}else if(i.size.x!==void 0){let c=i.size.scale(a).floor(),l=c.x,u=c.y;i.fill&&n.fillRect(-l/2|0,-u/2|0,l,u),n.strokeRect(-l/2|0,-u/2|0,l,u)}else n.beginPath(),n.arc(0,0,i.size*a/2,0,9),i.fill&&n.fill(),n.stroke();n.restore()}),pn=pn.filter(i=>i.timer<0),s){let i=El(s.pos,Nt);i&&Li(i.floor().add(v(.5)),v(1),Q(0,1,1,.3),0,!1),On(Nt,s.pos,.1,i?Q(1,0,0,.5):Q(0,1,0,.5),void 0,void 0,!1);let r="mouse pos = "+Nt;bn.length&&(r+=`
+mouse collision = `+ji(Nt)),r+=`
+
+--- object info ---
+`,r+=s.toString(),gn(r,tt,24,Q(),.05,void 0,"center","monospace")}{n.save(),n.fillStyle="#fff",n.textAlign="left",n.textBaseline="top",n.font="20px monospace",n.shadowColor="#000",n.shadowBlur=9;let a=9,o=0,c=24;if(Ut){n.fillText(`${Ti} v${Ai}`,a,o+=c/2),n.fillText("Time: "+Kr(dt),a,o+=c),n.fillText("FPS: "+ki.toFixed(1)+(H?" WebGL":" Canvas2D"),a,o+=c),n.fillText("Objects: "+Me.length,a,o+=c),n.fillText("Draw Calls: "+Ft,a,o+=c),n.fillText("Primitives: "+Gt,a,o+=c),n.fillText("---------",a,o+=c),n.fillStyle="#f00",n.fillText("ESC: Debug Overlay",a,o+=c),n.fillStyle=vt?"#f00":"#fff",n.fillText("1: Debug Physics",a,o+=c),n.fillStyle=Dn?"#f00":"#fff",n.fillText("2: Debug Particles",a,o+=c),n.fillStyle=Fn?"#f00":"#fff",n.fillText("3: Debug Gamepads",a,o+=c),n.fillStyle=wt?"#f00":"#fff",n.fillText("4: Debug Raycasts",a,o+=c),n.fillStyle="#fff",n.fillText("5: Save Screenshot",a,o+=c),n.fillText("6: Toggle Video Capture",a,o+=c),n.fillStyle=ls?"#f00":"#fff",n.fillText("7: Debug Sound",a,o+=c);let l="",u="";for(let h in ae[0])ze(h,0)&&(parseInt(h)<3?u+=h+" ":l+=h+" ");u&&n.fillText("Mouse: "+u,a,o+=c),l&&n.fillText("Keys: "+l,a,o+=c);for(let h=1;hs.push(o.data),i.onstop=()=>{let o=new Blob(s,{type:"video/webm"}),c=URL.createObjectURL(o);Bs(c,"capture.webm",1e3)};let r,a;if(rt){a=new ConstantSourceNode(ke,{offset:0}),a.connect(Kt),a.start(),r=ke.createMediaStreamDestination(),Kt.connect(r);for(let o of r.stream.getAudioTracks())t.addTrack(o)}try{i.start()}catch{Pe("Video capture not supported in this browser!"),a==null||a.stop();return}Pe("Video capture started."),Vt={mediaRecorder:i,captureTimer:n,videoTrack:e,silentAudioSource:a,audioStreamDestination:r}}function Kc(){var t,e,n;m(Ot(),"Not capturing video!"),Pe(`Video capture ended. ${Vt.captureTimer.get().toFixed(2)} seconds recorded.`),St.style.display="none",(t=Vt.silentAudioSource)==null||t.stop(),(e=Vt.mediaRecorder)==null||e.stop(),(n=Vt.videoTrack)==null||n.stop(),Vt=void 0}function yd(){m(Ot(),"Not capturing video!"),fa(),Vt.videoTrack.requestFrame(),St.textContent="\u25CF REC "+Kr(Vt.captureTimer)}function ht(t){if(Ye){let e=Object.keys(t),n={};e.forEach(s=>n[s]=t[s]),e.forEach(s=>{Object.defineProperty(t,s,{get:()=>n[s],set:i=>{m(!1,`Cannot modify engine constant. Attempted to set constant (${t}) property '${s}' to '${i}'.`)},enumerable:!0})})}return Object.freeze(t)}function mt(t,e=1){return(t%e+e)%e}function X(t,e=0,n=1){return tn?n:t}function $e(t,e,n){return(n-=e)?X((t-e)/n):0}function it(t,e,n){return t+X(n)*(e-t)}function gd(t,e,n,s,i){return it(s,i,$e(t,e,n))}function Yr(t,e,n=1){m(n>0,"distanceWrap wrapSize must be > 0");let s=(t-e)%n;return s*2%n-s}function tl(t,e,n,s=1){return t+X(n)*Yr(e,t,s)}function bd(t,e){return Yr(t,e,2*re)}function xd(t,e,n){return tl(t,e,n,2*re)}function _i(t){return t*t*(3-2*t)}function Gs(t){return!(t&t-1)}function Sd(t){return 2**Fs(Zc(t))}function Ei(t,e,n,s=v()){let i=(t.x-n.x)*2,r=(t.y-n.y)*2,a=e.x+s.x,o=e.y+s.y;return pe(i)d)return!1;h=ue(p,h)}else{if(p0?o.x+1:o.x,y=h>0?o.y+1:o.y,x=c?(p-t.x)/c:1/0,w=l?(y-t.y)/l:1/0,A=0,S=x,_=w,k=do.x&&(C.x=o.x+1-O),q.yo.y&&(C.y=o.y+1-O),s&&(k?s.set(-u,0):s.set(0,-h)),C}(k=S<_)?(o.x+=u,A=S,S+=d):(o.y+=h,A=_,_+=f)}}function Ae(t=1,e=0){return e+Math.random()*(t-e)}function $r(t,e=0){return Ie(Ae(t,e))}function ol(t=.5){return Ae()URL.revokeObjectURL(t),n)}function _d(t,e,n){var s;m(ee(t),"shareURL requires title string"),m(ee(e),"shareURL requires url string"),(s=navigator.share)==null||s.call(navigator,{title:t,url:e}).then(()=>n==null?void 0:n())}function Ed(t,e){m(ee(t),"loadData requires saveName string");let n={};try{let s=localStorage[t];if(s)try{n=JSON.parse(s)}catch{Pe("readSaveData: corrupt JSON for",t,"\u2014 using defaults")}}catch{Pe("readSaveData: localStorage unavailable \u2014 using defaults")}return{...e,...n}}function Pd(t,e){m(ee(t),"saveData requires saveName string");try{localStorage[t]=JSON.stringify(e)}catch{Pe("writeSaveData: failed to write",t)}}function rr(t){let e=(t|0)^2654435769;return e=Math.imul(e^e>>>16,2246822507),e=Math.imul(e^e>>>13,3266489909),e^=e>>>16,(e>>>0)/2**32}function Md(t){let e=Ie(t);return it(rr(e),rr(e+1),_i(t-e))}function Rd(t,e){let n=Ie(t),s=Ie(e),i=_i(t-n),r=_i(e-s),a=(o,c)=>rr(o+c*374761393);return it(it(a(n,s),a(n+1,s),i),it(a(n,s+1),a(n+1,s+1),i),r)}function Ld(t){je=t.copy()}function Od(t){de=t}function Id(t){oe=t}function Dd(t){Qr=t}function Fd(t){oo=t}function Gd(t){mn=t.copy()}function Bd(t){ts=t.copy()}function jd(t){Rs=t}function Jd(t){ns=t}function Nd(t){ss=t.copy()}function pl(t){Zr=t,$&&($.style.imageRendering=t?"pixelated":""),he&&(he.style.imageRendering=t?"pixelated":"")}function zd(t){jn=t}function Ud(t){yn=t}function Vd(t){ei=t}function qd(t){ea=t}function Wd(t){K=t}function Hd(t){if(t&&!pr){console.warn("Can not enable WebGL if it was disabled on start.");return}H=t,he&&(he.style.display=t?"":"none")}function Yd(t){ti=t}function $d(t){ro=t.copy()}function Xd(t){ao=t}function Kd(t){co=t}function Qd(t){lo=t}function Zd(t){ta=t}function ef(t){na=t}function tf(t){sa=t}function nf(t){ia=t}function sf(t){oa=t}function of(t){Wt=t}function rf(t){st=t.copy()}function af(t){Pi=t}function cf(t){uo=t}function lf(t){ra=t}function uf(t){Ls=t}function df(t){Ln=t}function ff(t){vn=t}function hf(t){aa=t}function pf(t){At=t}function mf(t){ys=t,t>0&&(bs=!1)}function yf(t){Un=t,t&&(gs=0)}function gf(t){gs=t,t>0&&(Un=!1)}function bf(t){bs=t,t&&(ys=0)}function xf(t){ni=t}function Sf(t){Tn=t}function vf(t){ot=t}function wf(t){ca=t}function Tf(t){Os=t}function Af(t){Mi=t}function kf(t){si=t}function Cf(t){rt=t}function _f(t){Gn=t,rt&&!K&&Kt&&(Kt.gain.value=t)}function Ef(t){la=t}function Pf(t){ua=t}function Mf(t){io=t}function Rf(t){Yc=t}function Ri(t){return t.r>=1&&t.g>=1&&t.b>=1}function da(t){return t.r<=0&&t.g<=0&&t.b<=0&&t.a<=0}function ii(t=0,e=ro,n=0,s=ao,i=co){if(m(D(t)||typeof t=="number","index must be a vec2 or number"),m(D(e)||typeof e=="number","size must be a vec2 or number"),m(I(n)||n instanceof Zt,"texture must be a number or TextureInfo"),m(I(s),"padding must be a number"),K)return new Bt;typeof e=="number"&&(m(e>0),e=new Se(e,e));let r=typeof n=="number"?wn[n]:n;m(r instanceof Zt,"tile texture is not loaded"),m(r.size.x>0,"tile texture is not loaded");let a=e.x+s*2,o=e.y+s*2,c,l;if(typeof t=="number"){let h=r.size.x/a|0;c=t%h,l=t/h|0}else c=t.x,l=t.y;let u=new Se(c*a+s,l*o+s);return new Bt(u,e,r,s,i)}function Ue(t,e=v(1),n,s=te,i=0,r,a,o=H,c=!1,l){var d;m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(Z(s),"color is invalid"),m(I(i),"angle must be a number"),m(!a||Z(a),"additiveColor must be a color"),m(!l||!o,"context only supported in canvas 2D mode");let u=n==null?void 0:n.textureInfo,h=(d=n==null?void 0:n.bleed)!=null?d:0;if(o&&H)if(m(!!g,"WebGL is not enabled!"),c&&([t,e,i]=ri(t,e,i)),u){let f=u.sizeInverse,p=n.pos.x*f.x,y=n.pos.y*f.y,x=n.size.x*f.x,w=n.size.y*f.y;if(_a(u.glTexture),h){let A=f.x*h,S=f.y*h;$s(t.x,t.y,r?-e.x:e.x,e.y,i,p+A,y+S,p-A+x,y-S+w,s.rgbaInt(),a&&a.rgbaInt())}else $s(t.x,t.y,r?-e.x:e.x,e.y,i,p,y,p+x,y+w,s.rgbaInt(),a&&a.rgbaInt())}else{let f=a?s.add(a):s;Dl(t.x,t.y,e.x,e.y,i,f.rgbaInt())}else++Ft,++Gt,Vn(t,e,i,r,f=>{if(u){f.scale(1,-1);let p=n.pos.x,y=n.pos.y,x=n.size.x,w=n.size.y;Nf(f,u.image,p,y,x,w,-.5,-.5,1,1,s,a,h)}else{let p=a?s.add(a):s;f.fillStyle=p.toString(),f.fillRect(-.5,-.5,1,1)}},c,l)}function Li(t,e,n,s,i,r,a){Ue(t,e,void 0,n,s,!1,void 0,i,r,a)}function Lf(t,e,n=te,s=Sn,i=0,r=H,a=!1,o){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(Z(n)&&Z(s),"color is invalid"),m(I(i),"angle must be a number"),m(!o||!r,"context only supported in canvas 2D mode"),r&&H){m(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/oe),i+=de);let c=[],l=[],u=e.x/2,h=e.y/2,d=n.rgbaInt(),f=s.rgbaInt(),p=ve(-i),y=me(-i);for(let x=4;x--;){let w=x&1?u:-u,A=x&2?h:-h,S=w*p-A*y,_=w*y+A*p,k=x&2?d:f;c.push(v(t.x+S,t.y+_)),l.push(k)}La(c,l)}else++Ft,++Gt,Vn(t,e,i,!1,c=>{let l=c.createLinearGradient(0,.5,0,-.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.fillRect(-.5,-.5,1,1)},a,o)}function Of(t,e,n,s=0,i=te,r=0,a,o=H,c=!1,l){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(D(n),"wrapCount must be a vec2"),m(Z(i),"color is invalid"),m(I(r),"angle must be a number"),m(!a||Z(a),"additiveColor must be a color"),m(!l||!o,"context only supported in canvas 2D mode"),m(!(s instanceof Bt),"pass a TextureInfo or texture index, not a TileInfo \u2014 use tileInfo.textureInfo"),K)return;let u=typeof s=="number"?wn[s]:s;if(m(u instanceof Zt,"texture not loaded"),m(u.size.x>0,"texture not loaded"),m(u.wrap,"drawTextureWrapped requires a wrap-enabled texture; call textureInfo.setWrap(true) first"),o&&H){m(!!g,"WebGL is not enabled!"),c&&([t,e,r]=ri(t,e,r)),_a(u.glTexture),$s(t.x,t.y,e.x,e.y,r,0,0,n.x,n.y,i.rgbaInt(),a&&a.rgbaInt());return}++Ft,++Gt,c||(t=qn(t),e=e.scale(oe),r-=de);let h=!oo||(a?Ri(i.add(a))&&a.a<=0:Ri(i)),d=!h&&a&&!da(a),f=h?u.image:Jf(u.image,i,a);l=l||Ge,l.save(),l.translate(t.x+.5,t.y+.5),l.rotate(r),l.globalAlpha=d?1:i.a;let p=l.createPattern(f,"repeat"),y=new DOMMatrix().translate(-e.x/2,-e.y/2).scale(e.x/(n.x*f.width),e.y/(n.y*f.height));p.setTransform(y),l.fillStyle=p,l.fillRect(-e.x/2,-e.y/2,e.x,e.y),l.globalAlpha=1,l.restore()}function ar(t,e=.1,n=te,s=!1,i=v(),r=0,a=H,o=!1,c){if(m(Tt(t),"points must be an array"),m(I(e),"width must be a number"),m(Z(n),"color is invalid"),m(D(i),"pos must be a vec2"),m(I(r),"angle must be a number"),m(!c||!a,"context only supported in canvas 2D mode"),a&&H){m(!!g,"WebGL is not enabled!");let l=v(1);o&&([i,l,r]=ri(i,l,r)),Ra(t,n.rgbaInt(),e,i.x,i.y,l.x,l.y,r,s)}else++Ft,++Gt,Vn(i,v(1),r,!1,l=>{l.strokeStyle=n.toString(),l.lineWidth=e,l.beginPath();for(let u=0;u0&&Ra(t,s.rgbaInt(),n,i.x,i.y,l.x,l.y,r)}else Vn(i,v(1),r,!1,l=>{l.fillStyle=e.toString(),l.beginPath();for(let u of t)l.lineTo(u.x,u.y);l.closePath(),l.fill(),n&&(l.strokeStyle=s.toString(),l.lineWidth=n,l.stroke())},o,c)}function yl(t,e=v(1),n=te,s=0,i=0,r=ye,a=H,o=!1,c){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(Z(n)&&Z(r),"color is invalid"),m(I(s),"angle must be a number"),m(I(i),"lineWidth must be a number"),m(i>=0,"lineWidth must be a positive value or 0"),m(!c||!a,"context only supported in canvas 2D mode"),i=X(i,0,fe(e.x,e.y)),a&&H?ml(t,e,ti,n,i,r,s,a,o,c):Vn(t,v(1),s,!1,l=>{l.fillStyle=n.toString(),l.beginPath(),l.ellipse(0,0,e.x/2,e.y/2,0,0,9),l.fill(),i&&(l.strokeStyle=r.toString(),l.lineWidth=i,l.stroke())},o,c)}function Oi(t,e=1,n=te,s=0,i=ye,r=H,a=!1,o){m(I(e),"size must be a number"),yl(t,v(e),n,0,s,i,r,a,o)}function gl(t,e=v(1),n=te,s=Sn,i=0,r=H,a=!1,o){if(m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(Z(n)&&Z(s),"color is invalid"),m(I(i),"angle must be a number"),m(!o||!r,"context only supported in canvas 2D mode"),!K)if(r&&H){m(!!g,"WebGL is not enabled!"),a&&(t=oi(t),e=e.scale(1/oe),i+=de);let c=ti,l=e.x/2,u=e.y/2,h=n.rgbaInt(),d=s.rgbaInt(),f=If++,p=ve(-i),y=me(-i),x=_=>{let k=me(_)*l,C=ve(_)*u;return v(t.x+k*p-C*y,t.y+k*y+C*p)},w=f%c/c*re*2,A=[x(w)],S=[d];for(let _=c;_--;){let k=(_+f)%c/c*re*2;A.push(t),S.push(h),A.push(x(k)),S.push(d)}La(A,S)}else++Ft,++Gt,Vn(t,e,i,!1,c=>{let l=c.createRadialGradient(0,0,0,0,0,.5);l.addColorStop(0,n.toString()),l.addColorStop(1,s.toString()),c.fillStyle=l,c.beginPath(),c.ellipse(0,0,.5,.5,0,0,9),c.fill()},a,o)}function Df(t,e=1,n=te,s=Sn,i=H,r=!1,a){m(I(e),"size must be a number"),gl(t,v(e),n,s,0,i,r,a)}function Vn(t,e,n=0,s=!1,i,r=!1,a=Ge){m(D(t),"pos must be a vec2"),m(D(e),"size must be a vec2"),m(I(n),"angle must be a number"),m(typeof i=="function","drawFunction must be a function"),r||(t=qn(t),e=e.scale(oe),n-=de),a.save(),a.translate(t.x+.5,t.y+.5),a.rotate(n),a.scale(s?-e.x:e.x,-e.y),i(a),a.restore()}function Ff(t,e,n=1,s=te,i=0,r=ye,a="center",o=ei,c="",l,u=0,h=Ge){e=qn(e),n*=oe,i*=oe,u-=de,u*=-1,gn(t,e,n,s,i,r,a,o,c,l,u,h)}function gn(t,e,n,s=te,i=0,r=ye,a="center",o=ei,c="",l,u=0,h=Ge){m(ee(t),"text must be a string"),m(D(e),"pos must be a vec2"),m(I(n),"size must be a number"),m(Z(s),"color must be a color"),m(I(i),"lineWidth must be a number"),m(Z(r),"lineColor must be a color"),m(["left","center","right"].includes(a),"align must be left, center, or right"),m(ee(o),"font must be a string"),m(ee(c),"fontStyle must be a string"),m(I(u),"angle must be a number");let d=(t+"").split(`
+`),f=e.y-(d.length-1)*n/2;h.save(),h.fillStyle=s.toString(),h.strokeStyle=r.toString(),h.lineWidth=i,h.textAlign=a,h.font=c+" "+n+"px "+o,h.textBaseline="middle",h.translate(e.x,f),h.rotate(-u);let p=0;d.forEach(y=>{i&&h.strokeText(y,0,p,l),h.fillText(y,0,p,l),p+=n}),h.restore()}async function Dc(t,e){m(I(t),"textureIndex must be a number"),m(!wn[t],"textureIndex is already loaded!"),m(!e||ee(e),"image src must be a string");let n=new Image;e&&await new Promise(s=>{n.onerror=n.onload=s,n.crossOrigin="anonymous",n.src=e}),wn[t]=new Zt(n)}function oi(t){m(D(t),"screenPos must be a vec2");let e=(t.x-z.x/2+.5)/oe,n=(t.y-z.y/2+.5)/-oe;if(de){let s=ve(-de),i=me(-de),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new Se(e+je.x,n+je.y)}function qn(t){m(D(t),"worldPos must be a vec2");let e=t.x-je.x,n=t.y-je.y;if(de){let s=ve(de),i=me(de),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new Se(e*oe+z.x/2-.5,n*-oe+z.y/2-.5)}function bl(t){m(D(t),"screenDelta must be a vec2");let e=t.x/oe,n=t.y/-oe;if(de){let s=ve(-de),i=me(-de),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new Se(e,n)}function Gf(t){m(D(t),"worldDelta must be a vec2");let e=t.x,n=t.y;if(de){let s=ve(de),i=me(de),r=e*s-n*i,a=e*i+n*s;e=r,n=a}return new Se(e*oe,n*-oe)}function ri(t,e,n=0){return m(D(t),"screenPos must be a vec2"),m(D(e),"screenSize must be a vec2"),m(I(n),"screenAngle must be a number"),[oi(t),e.scale(1/oe),n+de]}function xl(){return z.scale(1/oe)}function Bf(t,e,n,s){m(D(t),"center must be a vec2"),m(D(e),"size must be a vec2");let i=d(n),r=d(s),a=e.x+i.left+i.right,o=e.y+i.top+i.bottom,c=z.x-r.left-r.right,l=z.y-r.top-r.bottom;if(!(a>0&&o>0&&c>0&&l>0))return oe;oe=fe(c/a,l/o);let u=v(i.right-i.left,i.top-i.bottom).scale(.5),h=v(r.right-r.left,r.top-r.bottom).scale(.5/oe);return je=t.add(u).add(h),oe;function d(f){return(f===void 0||I(f))&&(f=v(f)),D(f)?{top:f.y,right:f.x,bottom:f.y,left:f.x}:{top:f.top||0,right:f.right||0,bottom:f.bottom||0,left:f.left||0}}}function jf(t,e=0){if(m(D(t),"pos must be a vec2"),m(D(e)||I(e),"size must be a vec2 or number"),!oe)return!1;let n=t.x-je.x,s=t.y-je.y;if(de){let a=ve(de),o=me(de),c=n*a-s*o,l=n*o+s*a;n=c,s=l}n*=oe*2,s*=-oe*2,e instanceof Se&&(e=e.length()),e*=oe;let i=z.x,r=z.y;return n+e>-i&&n-e-r&&s-e{t.onerror=t.onload=o,t.crossOrigin="anonymous",t.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAAeAQMAAABnrVXaAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAAjpJREFUOMu9kzFu2zAUhn+CAROgqrk+B2l0BWYxMjlXeYaAtFtbdA1sGgHqRQfI0CNkSG5AwYB0BQ8d5Bsomwah6CPVeGg6tEPzAxLwyI+P78cP4u9lNO9OoMKnLMOobG5020/yaj/MrRcCGh1gBbyiLTPJEYaIiom5KM9Jq7KgynMGtb6L4GL4MF2H4LQKCXTvDVw2I4MsgZT7QLExdiutH+D08VOP3INXRrWX1/mmpbkNgAPYRVANb4xpcegYvhiNbIXauQICEjBuYLfMakaakWQeXxiZ0VDtuJCKs3ztMV59QtsHJNcRxDzfdL21ty3PrfIcXTN+E+GFAv6T5nbT9jd50/WFxb5ksdAv49qS6ouymG66ji08UMT6moykYLAo+V0j23GN4m829ZySAD5K7QsBfQTvOG8eE+gTeGYRAmnNAubN3hf5Zv9tJWDHp/VTuaSm7SN4fyINQqaNO3RMVxvpSPXnOChnRNvFcGY0gnwiPswYwTKVPE0zVtX3mTEIOoFzaqLrGuJaV+Uqumb71fVk/VoOH3cdLNQP/FHi8hV0CQNoqBZsUPlLPMsdCJro9QAaQQ0woDy9BJm0eTxCFnO9srcYlhNVlfR2EyTrph1uUtbUtAJifwRgrKuYdXVHeb0YI3QpawohQHkloI3J5FuVwI5ORxC9k2Tuz9Ir1IjgeIPGMHYkAZe2RuYkmWFmt3gGbTPOmBUWVTmRmHtGrfpzG/yuQNOKa6gBB/WA9khitPgl6/GP+gl2Af6tCbvaygAAAABJRU5ErkJggg=="});let e=v(),n=v(8),s=1,i=0,r=new Zt(t),a=new Bt(e,n,r,s,i);vl=new Ii(a)}function qf(t=!0){is=t}function Wf(t){ma=t}function Hf(){return hn==="mouse"}function Yf(){return hn==="keyboard"}function $f(){return hn==="gamepad"}function ya(t,e=0,n=!0,s=!0,i=!0){ae[e]&&(ae[e][t]&=~((n?1:0)|(s?2:0)|(i?4:0)))}function ai(){ae.length=0,ae[0]=[],gt.length=0,Jn.length=0,ci.length=0,Mt.length=0,Mn.length=0}function ze(t,e=0){var n;return m(ee(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=ae[e])==null?void 0:n[t])&1)}function We(t,e=0){var n;return m(ee(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=ae[e])==null?void 0:n[t])&2)}function ga(t,e=0){var n;return m(ee(t),"key must be a number or string"),m(e>0||typeof t!="number"||t<3,"use code string for keyboard"),!!(((n=ae[e])==null?void 0:n[t])&4)}function Xf(t="ArrowUp",e="ArrowDown",n="ArrowLeft",s="ArrowRight"){m(ee(t),"up key must be a string"),m(ee(e),"down key must be a string"),m(ee(n),"left key must be a string"),m(ee(s),"right key must be a string");let i=r=>ze(r)?1:0;return v(i(s)-i(n),i(t)-i(e))}function Is(t){return m(I(t),"mouse button must be a number"),ze(t)}function Js(t){return m(I(t),"mouse button must be a number"),We(t)}function Kf(t){return m(I(t),"mouse button must be a number"),ga(t)}function zt(t,e=_e){return m(I(t),"button must be a number"),m(I(e),"gamepad must be a number"),ze(t,e+1)}function ba(t,e=_e){return m(I(t),"button must be a number"),m(I(e),"gamepad must be a number"),We(t,e+1)}function Qf(t,e=_e){return m(I(t),"button must be a number"),m(I(e),"gamepad must be a number"),ga(t,e+1)}function Ns(t,e=_e){var n,s;return m(I(t),"stick must be a number"),m(I(e),"gamepad must be a number"),(s=(n=Mt[e])==null?void 0:n[t])!=null?s:v()}function cr(t=_e){var e;return m(I(t),"gamepad must be a number"),(e=Mn[t])!=null?e:v()}function lr(t=_e){return m(I(t),"gamepad must be a number"),!!ae[t+1]}function wl(t=_e){var e,n;return m(I(t),"gamepad must be a number"),(n=(e=Mt[t])==null?void 0:e.length)!=null?n:0}function Zf(t=_e,e=200,n=1,s=1,i=0){var a,o,c;if(m(I(t),"gamepad must be a number"),!si||K)return;let r=(a=navigator==null?void 0:navigator.getGamepads)==null?void 0:a.call(navigator)[t];(c=(o=r==null?void 0:r.vibrationActuator)==null?void 0:o.playEffect)==null||c.call(o,"dual-rumble",{duration:e,strongMagnitude:n,weakMagnitude:s,startDelay:i})}function eh(t=_e){var n,s,i;if(m(I(t),"gamepad must be a number"),!si||K)return;let e=(n=navigator==null?void 0:navigator.getGamepads)==null?void 0:n.call(navigator)[t];(i=(s=e==null?void 0:e.vibrationActuator)==null?void 0:s.reset)==null||i.call(s)}function xa(t=100){var e;m(I(t)||Tt(t),"pattern must be a number or array"),si&&!K&&((e=navigator==null?void 0:navigator.vibrate)==null||e.call(navigator,t))}function th(){xa(0)}function nh(){var t;!yt&&((t=$.requestPointerLock)==null||t.call($))}function sh(){var t;(t=document.exitPointerLock)==null||t.call(document)}function Tl(){return document.pointerLockElement===$}function ih(){if(K)return;document.addEventListener("keydown",t),document.addEventListener("keyup",e),document.addEventListener("mousedown",s),document.addEventListener("mouseup",i),document.addEventListener("mousemove",r),document.addEventListener("mouseleave",a),document.addEventListener("wheel",o,{passive:!1}),document.addEventListener("contextmenu",c),document.addEventListener("blur",l),yt&&Ln&&u();function t(d){if(d.repeat||(ae[0][d.code]=3,Ls&&(ae[0][n(d.code)]=3)),!is||!d.cancelable||!document.hasFocus()||d.ctrlKey||d.metaKey||d.altKey||y(d.target)||y(document.activeElement))return;let f=typeof d.key=="string"&&d.key.length===1;(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Space","Tab","Backspace"].includes(d.code)||f)&&d.preventDefault();function y(x){let w=x==null?void 0:x.tagName;return(x==null?void 0:x.isContentEditable)||["INPUT","TEXTAREA","SELECT"].includes(w)}}function e(d){ae[0][d.code]=ae[0][d.code]&2|4,Ls&&(ae[0][n(d.code)]=4)}function n(d){return Ls?d==="KeyW"?"ArrowUp":d==="KeyS"?"ArrowDown":d==="KeyA"?"ArrowLeft":d==="KeyD"?"ArrowRight":d:d}function s(d){if(yt&&Ln)return;rt&&!K&&ke&&!Us()&&ke.resume(),ae[0][d.button]=3;let f=tt;tt=h(v(d.x,d.y)),Pt=Pt.add(tt.subtract(f)),is&&d.cancelable&&document.hasFocus()&&d.preventDefault()}function i(d){yt&&Ln||(ae[0][d.button]=ae[0][d.button]&2|4)}function r(d){Di=!0;let f=tt;tt=h(v(d.x,d.y));let p=Tl()?v(d.movementX,d.movementY):tt.subtract(f);Pt=Pt.add(p)}function a(){Di=!1}function o(d){d.ctrlKey||(pa+=pt(d.deltaY)),is&&d.cancelable&&document.hasFocus()&&d.preventDefault()}function c(d){d.preventDefault()}function l(){ai(),Yt.clear(),gt.length=0,Jn.length=0,ci.length=0}function u(){document.addEventListener("touchstart",p=>f(p),{passive:!1}),document.addEventListener("touchmove",p=>f(p),{passive:!1}),document.addEventListener("touchend",p=>f(p),{passive:!1});let d;function f(p){if(Ln){if(rt&&!K&&ke&&!Us()&&ke.resume(),!vn||aa){let y=S=>zs.includes(S.target)||S.target===Rn,x=[];for(let S of p.touches)y(S)||x.push(S);let w=x.length,A=0;if(w){let S=v(x[0].clientX,x[0].clientY),_=tt;tt=h(S),d?Pt=Pt.add(tt.subtract(_)):ae[0][A]=3}else d&&(ae[0][A]=ae[0][A]&2|4);d=w}return is&&p.cancelable&&document.hasFocus()&&p.preventDefault(),!0}}}function h(d){let f=$.getBoundingClientRect(),p=$e(d.x,f.left,f.right),y=$e(d.y,f.top,f.bottom);return v(p*$.width,y*$.height)}}function Gc(){if(K)return;!(Ln&&yt)&&!document.hasFocus()&&ai(),Nt=oi(tt),ha=bl(Pt),rh(),e(),t();function t(){let n=Is(0)||Is(1)||Is(2)||Pt.length()>ma,s=!1;for(let r=wl();r--&&!s;)s=Ns(r).lengthSquared()>.04;for(let r=17;r--&&!s;)s=zt(r);let i=!1;for(let r in ae[0])if(isNaN(+r)&&ae[0][r]&1){i=!0;break}s?hn="gamepad":n?hn="mouse":i&&(hn="keyboard"),rs=hn==="gamepad"}function e(){var a,o,c,l,u,h,d;let n=f=>{let x=w=>w>.3?$e(w,.3,.8):w<-.3?-$e(-w,.3,.8):0;return v(x(f.x),x(-f.y)).clampLength()};if(vn&&yt){if(m(!Un||!gs,"set touchGamepadLeftStick or touchGamepadLeftButtonCount, not both"),m(!bs||!ys,"set touchGamepadRightStick or touchGamepadButtonCount, not both"),!ds.isSet())return;_e=0;let f=(a=Mt[0])!=null?a:Mt[0]=[],p=(o=Mn[0])!=null?o:Mn[0]=v();f.length=0,p.set();for(let x=0;x<2;x++){if(!en(x))continue;let w=wa(x);f[w]=v();let A=(c=Jn[x])!=null?c:v();if(ni)f[w]=n(A);else if(A.lengthSquared()>.3){let S=X(Ci(A.x),-1,1),_=X(Ci(A.y),-1,1);f[w]=v(S,-_).clampLength(),w||p.set(S,-_)}}let y=(l=ae[1])!=null?l:ae[1]=[];for(let x=12;x--;){let w=zt(x,0);y[x]=gt[x]?w?1:3:w?4:0,Mi&&y[x]===3&&(x===9||ah(x))&&xa(Mi)}return}try{if(!uo||!(navigator!=null&&navigator.getGamepads))return}catch{return}if(!Ye&&!document.hasFocus())return;let s=8,i=navigator.getGamepads(),r=fe(s,i.length);for(let f=0;f>1]=n(v(p.axes[S],p.axes[S+1]));let A=!1;for(let S=p.buttons.length;S--;){let _=p.buttons[S],k=zt(S,f);y[S]=_.pressed?k?1:3:k?4:0,_.pressed&&(!_.value||_.value>.9)&&(A=!0)}A&&(Zo[f]=!0,Zo[_e]||(_e=f)),p.mapping==="standard"&&w.set((zt(15,f)&&1)-(zt(14,f)&&1),(zt(12,f)&&1)-(zt(13,f)&&1)),ra&&(w.x||w.y)&&(x[0]=w.clampLength())}vn&&rs&&ds.unset()}}function Bc(){if(!K){for(let t of ae)for(let e in t)t[e]&=1;pa=0,ha=v(),Pt=v()}}function oh(){dh()}function rh(){if(un||!vn||!yt||K||!document.body)return;let t=un=document.createElement("div");t.style.cssText="position:fixed;inset:0;z-index:50;pointer-events:none;opacity:0;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;transition:opacity .2s;box-sizing:border-box;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)";let e=Al=document.createElement("div");e.style.cssText="position:relative;width:100%;height:100%;pointer-events:none",t.appendChild(e);let n=Sa=document.createElementNS(Gi,"svg");n.style.cssText="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible;fill:none;stroke:#fff;stroke-width:3",e.appendChild(n);let s=()=>{let i=document.createElement("div");return i.style.cssText="position:absolute;pointer-events:auto;touch-action:none",i.addEventListener("pointerdown",r=>mh(r,i)),i.addEventListener("pointermove",r=>yh(r)),i.addEventListener("pointerup",r=>jc(r)),i.addEventListener("pointercancel",r=>jc(r)),e.appendChild(i),i};zs[0]=s(),zs[1]=s(),Rn=s(),addEventListener("resize",()=>fs=!0),document.body.appendChild(t),fs=!0}function fo(){return Al.getBoundingClientRect()}function en(t){return t?bs:Un}function Wn(t){return t?ys:gs}function va(t){return t?0:4}function wa(t){return t&&Un?1:0}function hs(t){return en(t)||Wn(t)>0}function ah(t){for(let e=0;e<2;e++){let n=va(e);if(!en(e)&&t>=n&&tr.style.cssText="position:absolute;pointer-events:auto;touch-action:none;"+a;if(It){for(let r of zs)r.style.display="none";At?(i(Rn,"inset:0"),Rn.style.display=""):Rn.style.display="none"}else{for(let a=0;a<2;a++){let o=zs[a],c=a?"right":"left";if(o.style.display=hs(a)?"":"none",Tn){let l=hs(a?0:1)?"50%":"100%";i(o,`${c}:0;bottom:0;width:${l};height:60%`)}else i(o,`${c}:0;bottom:0;width:${3*s}px;height:${3*s}px`)}Rn.style.display=At?"":"none";let r=At;i(Rn,`left:50%;top:50%;width:${2*r}px;height:${2*r}px;transform:translate(-50%,-50%)`)}lh(e,n),fs=!1}function lh(t,e){let n=Sa;for(;n.firstChild;)n.removeChild(n.firstChild);let s=kl={face:[],thumb:[]},i=ot,r=(o,c,l,u)=>{let h=document.createElementNS(Gi,"circle");return h.setAttribute("cx",o),h.setAttribute("cy",c),h.setAttribute("r",l),u&&h.setAttribute("fill",u),n.appendChild(h),h},a=o=>{let c=i*.18,l=i*.5,u=o.x,h=o.y,d=document.createElementNS(Gi,"path");d.setAttribute("d",`M ${u-c} ${h-l} H ${u+c} V ${h-c} H ${u+l} V ${h+c} H ${u+c} V ${h+l} H ${u-c} V ${h+c} H ${u-l} V ${h-c} H ${u-c} Z`),n.appendChild(d)};for(let o=0;o<2;o++){let c=Wn(o),l=va(o),u=Xt(o,t,e);if(en(o))ni?r(u.x,u.y,i/2):a(u),s.thumb[o]=r(u.x,u.y,i/4,"#fff");else if(c===1)s.face[l]=r(u.x,u.y,i/2,"#000");else for(let h=0;h2?d:fe(d,c-1);f=f===3?2:f===2?3:f;let p=v().setDirection(d,i/2);c===2&&(p.x*=-1),o||(p.x*=-1);let y=u.add(p);s.face[l+f]=r(y.x,y.y,i/4,"#000")}}Ye&&Fn&&uh(t,e)}function uh(t,e){let n=ot,s=Sa,i=(a,o,c)=>{let l=document.createElementNS(Gi,a);for(let u in o)l.setAttribute(u,o[u]);l.setAttribute("stroke",c),l.setAttribute("stroke-width",2),l.setAttribute("fill","none"),s.appendChild(l)},r=(a,o,c)=>i("circle",{cx:a.x,cy:a.y,r:o},c);i("line",{x1:t/2,y1:0,x2:t/2,y2:e},"#0f0");for(let a=0;a<2;a++)if(en(a))if(Tn){let o=e*.4,c=!hs(a?0:1),l=c?0:a?t/2:0;i("rect",{x:l,y:o,width:c?t:t/2,height:e-o},"#0ff")}else r(Xt(a,t,e),2*n,"#0ff");else Wn(a)>=1&&r(Xt(a,t,e),n,"#0ff");if(At){r(v(t/2,e/2),At,"#ff0");for(let a=0;a<2;a++)hs(a)&&r(Xt(a,t,e),2*n,"#f0f")}}function dh(){var l;if(!un||K)return;if(!vn||!yt){un.style.display!=="none"&&(un.style.display="none",Yt.clear(),gt.length=0,Jn.length=0,ci.length=0);return}un.style.display="";let t=Ye&&Fn,e=[ys,gs,Un,bs,ni,ot,Tn,At,It,t].join();e!==Fc&&(Fc=e,fs=!0),fs&&ch();let n=Os?$e(ds.get(),Os+1,Os):1,s=t||ds.isSet()&&n>0&&!It;if(un.style.opacity=s?t?1:n*ca:0,!s)return;let i=fo(),r=i.width,a=i.height,o=ot,c=kl;if(c){for(let u=0;u<2;u++)if(en(u)&&c.thumb[u]){let d=Xt(u,r,a).add(((l=Jn[u])!=null?l:v()).scale(o/2));c.thumb[u].setAttribute("cx",d.x),c.thumb[u].setAttribute("cy",d.y)}for(let u=0;u=ot)return-1;if(i===1)return r;let o=a.subtract(e);t||(o.x*=-1);let c=i===2?o.xr:o&&Xt(a,e,n).distance(t)<2*s)return{role:"stick",side:a}}else if(Wn(a)>=1){let c=hh(a,t,e,n);if(c>=0)return{role:"face",btn:c}}}if(At){for(let a=0;a<2;a++)if(hs(a)&&Xt(a,e,n).distance(t)<2*s)return;if(v(e/2,n/2).distance(t)h.getChannelData(x).set(y)),d.buffer=h,d.playbackRate.value=n,d.loop=i,a=a||ke.createGain(),a.gain.value=e,a.connect(Kt);let f=new StereoPannerNode(ke,{pan:X(s,-1,1)});d.connect(f).connect(a),d.addEventListener("ended",()=>{a.disconnect(),f.disconnect(),c&&c(d)});let p=o*n;return d.start(0,p),Ye&&ls&&Pe("sound","vol",e.toFixed(2),"rate",n.toFixed(2),"pan",s.toFixed(2),i?"loop":""),d}function Sh(...t){return Ta([ho(...t)])}function ho(t=1,e=.05,n=220,s=0,i=0,r=.1,a=0,o=1,c=0,l=0,u=0,h=0,d=0,f=0,p=0,y=0,x=0,w=1,A=0,S=0,_=0){let k=xs,C=re*2,O=c*=500*C/k/k,q=n*=(1+Ae(e,-e))*C/k,ce=0,ne=0,T=0,R=1,M,L=[],E=0,N=0,U=0,Y,se=2,Ne=C*pe(_)*2/k,ge=ve(Ne),Re=me(Ne)/2/se,be=1+Re,ct=-2*ge/be,Yn=(1-Re)/be,jt=(1+pt(_)*ge)/2/be,$n=-(pt(_)+ge)/be,Ss=jt,tn=0,nn=0,sn=0,Xn=0;for(s=s*k||9,A*=k,i*=k,r*=k,x*=k,l*=500*C/k**3,p*=C/k,u*=C/k,h*=k,d=d*k|0,M=s+A+i+r+x|0;N1?a>2?a>3?a>4?E/C%14?U:pt(U)*pe(U)**o)*(NN?0:(Nh&&(n+=u,q+=u,R=0),d&&!(++ne%d)&&(n=q,c=O,R||(R=1));return L}function ji(t,e=!0){for(let n of bn)if((!e||n.isSolid)&&t.arrayCheck(n.size)){let s=n.getCollisionData(t);if(s)return s}return 0}function dn(t,e=v(),n,s=!0){for(let i of bn)if((!s||i.isSolid)&&i.collisionTest(t,e,n))return i}function El(t,e,n,s,i=!0){let r,a,o,c=s&&v();for(let l of bn)if(!i||l.isSolid){let u=l.collisionRaycast(t,e,n,c);if(u){let h=t.distanceSquared(u);(r===void 0||h{H=!1,he.style.display="none",n.preventDefault(),Pe("WebGL context lost! Switching to Canvas2d rendering.");for(let s of Ds)s.glTexture=void 0;ft=void 0,Be=0,Nn=!1,In.forEach(s=>{var i;return(i=s.glContextLost)==null?void 0:i.call(s)})}),he.addEventListener("webglcontextrestored",()=>{H=!0,he.style.display="",Pe("WebGL context restored, reinitializing..."),e();for(let n of Ds)n.glTexture=mo(n.image,n.wrap);In.forEach(n=>{var s;return(s=n.glContextRestored)==null?void 0:s.call(n)})});function e(){zi=ms(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 g;in vec4 p,u,c,a;in float r;out vec2 v;out vec4 d,e;void main(){vec2 s=(g-.5)*p.zw;gl_Position=m*vec4(p.xy+s*cos(r)-vec2(-s.y,s)*sin(r),1,1);v=mix(u.xw,u.zy,g);d=c;e=a;}`,`#version 300 es
+precision highp float;uniform sampler2D s;in vec2 v;in vec4 d,e;out vec4 c;void main(){c=texture(s,v)*d+e;}`),Ui=ms(`#version 300 es
+precision highp float;uniform mat4 m;in vec2 p;in vec4 c;out vec4 d;void main(){gl_Position=m*vec4(p,1,1);d=c;}`,`#version 300 es
+precision highp float;in vec4 d;out vec4 c;void main(){c=d;}`);let n=new ArrayBuffer(qi);He=new Float32Array(n),Hs=new Uint32Array(n),dr=g.createBuffer(),as=g.createBuffer(),ka=g.createFramebuffer(),Be=0;let s=new Float32Array([0,0,1,0,0,1,1,1]);g.bindBuffer(g.ARRAY_BUFFER,as),g.bufferData(g.ARRAY_BUFFER,s,g.STATIC_DRAW);let i,r,a,o=(c,l,u,h,d=0)=>{let f=g.getAttribLocation(r,c),p=u===1,y=u&&a;g.enableVertexAttribArray(f),g.vertexAttribPointer(f,h,l,p,y,i),g.vertexAttribDivisor(f,d),i+=h*u};fr=g.createVertexArray(),g.bindVertexArray(fr),i=0,r=zi,a=Pl,g.bindBuffer(g.ARRAY_BUFFER,as),o("g",g.FLOAT,0,2),g.bindBuffer(g.ARRAY_BUFFER,dr),g.bufferData(g.ARRAY_BUFFER,qi,g.DYNAMIC_DRAW),o("p",g.FLOAT,4,4,1),o("u",g.FLOAT,4,4,1),o("c",g.UNSIGNED_BYTE,1,4,1),o("a",g.UNSIGNED_BYTE,1,4,1),o("r",g.FLOAT,4,1,1),hr=g.createVertexArray(),g.bindVertexArray(hr),i=0,r=Ui,a=Ml,o("p",g.FLOAT,4,2),o("c",g.UNSIGNED_BYTE,1,4)}}function Ys(t=!1){!t&&!Nn||(Je(),Nn=!1,g.useProgram(zi),g.bindVertexArray(fr))}function Rl(){Nn||(Je(),Nn=!0,g.useProgram(Ui),g.bindVertexArray(hr))}function mr(t=!0){if(!H||!g)return;m(!Be,"glPreRender called with unflushed batch."),Vi||(he.width=z.x,he.height=z.y),g.viewport(0,0,z.x,z.y),t&&Ll();let e=v(2*oe).divide(z);Vi&&(e.y=-e.y);let n=je.rotate(-de),s=v(-1).subtract(n.multiply(e)),i=ve(de),r=me(de),a=[e.x*i,e.y*r,0,0,-e.x*r,e.y*i,0,0,1,1,1,0,s.x,s.y,0,1],o=(c,l,u)=>{g.useProgram(c);let h=g.getUniformLocation(c,l);g.uniformMatrix4fv(h,!1,u)};o(Ui,"m",a),o(zi,"m",a),g.activeTexture(g.TEXTURE0),wn[0]&&(ft=wn[0].glTexture,g.bindTexture(g.TEXTURE_2D,ft)),g.bindBuffer(g.ARRAY_BUFFER,dr),Hn=ps=!1,Ys(!0)}function Ll(){if(!g)return;let t=mn;g.clearColor(t.r,t.g,t.b,t.a),g.clear(g.COLOR_BUFFER_BIT)}function _a(t){!g||t===ft||(Je(),ft=t,g.bindTexture(g.TEXTURE_2D,ft))}function Ol(t,e=!0){if(!g||!t)return;let n=t===ft;n?Je():g.bindTexture(g.TEXTURE_2D,t);let s=e?g.REPEAT:g.CLAMP_TO_EDGE;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,s),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,s),!n&&ft&&g.bindTexture(g.TEXTURE_2D,ft)}function yr(t,e){if(!g)return;let n=g.createShader(e);if(g.shaderSource(n,t),g.compileShader(n),Ye&&!g.getShaderParameter(n,g.COMPILE_STATUS))throw g.getShaderInfoLog(n);return n}function ms(t,e){if(!g)return;let n=g.createProgram();if(g.attachShader(n,yr(t,g.VERTEX_SHADER)),g.attachShader(n,yr(e,g.FRAGMENT_SHADER)),g.linkProgram(n),Ye&&!g.getProgramParameter(n,g.LINK_STATUS))throw g.getProgramInfoLog(n);return n}function mo(t,e=!1){if(!g)return;let n=g.createTexture(),s=!1;if(t!=null&&t.width)Ea(n,t),g.bindTexture(g.TEXTURE_2D,n),s=!jn&&Gs(t.width)&&Gs(t.height);else{let o=new Uint8Array([255,255,255,255]);g.bindTexture(g.TEXTURE_2D,n),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,1,1,0,g.RGBA,g.UNSIGNED_BYTE,o)}let i=jn?g.NEAREST:g.LINEAR,r=s?g.LINEAR_MIPMAP_LINEAR:i;g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,i),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,r);let a=e?g.REPEAT:g.CLAMP_TO_EDGE;return g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,a),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,a),s&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,ft),n}function Il(t){g&&g.deleteTexture(t)}function Ea(t,e){g&&(m((e==null?void 0:e.width)>0,"Invalid image data."),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e),!jn&&Gs(e.width)&&Gs(e.height)&&g.generateMipmap(g.TEXTURE_2D),g.bindTexture(g.TEXTURE_2D,ft))}function kh(t){K||(Ds.add(t),g&&(t.glTexture?Ea(t.glTexture,t.image):t.glTexture=mo(t.image,t.wrap)))}function Ch(t){if(K)return;Ds.delete(t);let e=t.glTexture;t.glTexture=void 0,Il(e)}function Je(){if(H&&g&&Be){let t=ps?g.ONE:g.ONE_MINUS_SRC_ALPHA;g.blendFuncSeparate(g.SRC_ALPHA,t,g.ONE,t),g.enable(g.BLEND);let e=Be*(Nn?po:Ca);g.bufferSubData(g.ARRAY_BUFFER,0,He,0,e),Nn?g.drawArrays(g.TRIANGLE_STRIP,0,Be):g.drawArraysInstanced(g.TRIANGLE_STRIP,0,4,Be),++Ft,Gt+=Be,Be=0}ps=Hn}function Pa(t){!H||!g||(Je(),t.drawImage(he,0,0))}function _h(t=!0){m(!he,"must be called before engineInit"),Aa=t}function $s(t,e,n,s,i=0,r=0,a=0,o=1,c=1,l=-1,u=0){(Be>=Th||ps!==Hn)&&Je(),Ys();let h=Be++*Ca;He[h++]=t,He[h++]=e,He[h++]=n,He[h++]=s,He[h++]=r,He[h++]=a,He[h++]=o,He[h++]=c,Hs[h++]=l,Hs[h++]=u,He[h++]=i}function Dl(t,e,n,s,i,r){$s(t,e,n,s,i,0,0,0,0,0,r)}function Ma(t,e,n,s,i,r,a,o=!0){let c=[],l=me(-a),u=ve(-a);for(let d of t){let f=d.x*i,p=d.y*r;c.push(v(n+u*f-l*p,s+l*f+u*p))}let h=o?Ph(c):c;Fl(h,e)}function Ra(t,e,n,s,i,r,a,o,c=!0){let l=Eh(t,n,c);Ma(l,e,s,i,r,a,o,!1)}function Fl(t,e){if(!H||t.length<3)return;let n=t.length+2;if((Be+n>=cs||ps!==Hn)&&Je(),m(n=cs)return;Rl();let s=Be*po;for(let i=n;i--;){let r=X(i-1,0,n-3),a=t[r];He[s++]=a.x,He[s++]=a.y,Hs[s++]=e}Be+=n}function La(t,e){if(!H||t.length<3)return;let n=t.length+2;if((Be+n>=cs||ps!==Hn)&&Je(),m(n=cs)return;Rl();let s=Be*po;for(let i=n;i--;){let r=X(i-1,0,n-3),a=t[r],o=e[r];He[s++]=a.x,He[s++]=a.y,Hs[s++]=o}Be+=n}function Ms(t,e=!1){t?(Vi=t,g.bindFramebuffer(g.FRAMEBUFFER,ka),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,t,0),mr(e)):(Je(),Vi=void 0,g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,z.x,z.y))}function Gl(t,e,n,s){H&&(g.enable(g.SCISSOR_TEST),g.scissor(t,e,n,s),g.clearColor(0,0,0,0),g.clear(g.COLOR_BUFFER_BIT),g.disable(g.SCISSOR_TEST))}function Eh(t,e,n=!0){if(t.length<2)return[];let s=e/2,i=[],r=t.length,a=1e-6,o=10;for(let c=0;ca?-f/p:0,S=p>a?d/p:0,_=w>a?-x/w:0,k=w>a?y/w:0,C=A+_,O=S+k,q=(C*C+O*O)**.5;if(qa){let R=fe(1/T,o);C*=R,O*=R}}let ce=v(u.x-C*s,u.y-O*s),ne=v(u.x+C*s,u.y+O*s);i.push(ce),i.push(ne)}return i.length>1&&n&&(i.push(i[0]),i.push(i[1])),i}function Ph(t){if(t.length<3)return[];let e=(f,p,y)=>(p.x-f.x)*(y.y-f.y)-(p.y-f.y)*(y.x-f.x);(f=>{let p=0;for(let y=f.length;y--;){let x=(y+1)%f.length;p+=f[y].cross(f[x])}return p})(t)<0&&(t=t.slice().reverse());let s=1e-9,i=(f,p,y,x)=>{let w=e(p,y,f),A=e(y,x,f),S=e(x,p,f),_=(w<-s?1:0)+(A<-s?1:0)+(S<-s?1:0),k=(w>s?1:0)+(A>s?1:0)+(S>s?1:0);return!(_&&k)},r=[];for(let f=0;f3&&o++{if(_>=0){let C=s.fillStyle=s.createLinearGradient(x,w,A,S);C.addColorStop(0,h(_,2)),C.addColorStop(1,h(_,1))}else s.fillStyle="#000";_>=-1?(s.fill(),k&&s.stroke()):s.stroke()},c=(x,w,A,S=0,_=2*re,k,C)=>{s.beginPath(),s.arc(x,w,A,f*S,f*_),o(x,w-A,x,w+A,k,C)},l=(x,w,A,S,_)=>{s.beginPath(),s.rect(x,w,A,S*f),o(x,w+S,x+A,w,_)},u=(x,w,A,S)=>{s.beginPath();for(let _ of x)s.lineTo(_.x,_.y);s.closePath(),o(0,A,0,A+S,w)},h=(x,w)=>w?`hsl(${[.95,.56,.13][x%3]*360} 99%${[0,50,75][w]}%)`:"#000",d=sl(1,1,t),f=$e(d,.1,.5),p=fe(6,fe(r,a)/99);s.translate(r/2,a/2),s.scale(p,p),s.translate(-40,-35),f<1&&s.setLineDash([99*f,99]),s.lineJoin=s.lineCap="round",s.lineWidth=.1+f*1.9;{let w="LittleJS";s.font="900 15.5px arial",s.lineWidth=.1+f*3.9,s.textAlign="center",s.textBaseline="top",l(11,55,59,8*f,-1),s.beginPath();let A=0;for(let S=0;S5?1:0),s[S?"strokeText":"fillText"](w[_],O,54+.5,17*f),k+=C}s.lineWidth=.1+f*1.9,l(3,54,73,0)}l(7,15,26,-7,0),l(25,15,8,25,-1),l(10,40,15,-25,1),l(14,21,7,9,2),l(38,20,6,-6,2),l(49,20,10,-6,0);let y=[v(44,8),v(64,8),v(59,8+6*f),v(49,8+6*f)];u(y,2,8,6*f),l(44,8,20,-7,0);for(let x=5;x--;)c(59-x*6*f,30,10,0,2*re,1,0);c(59,30,4,0,7,2),l(35,20,24,0),c(59,30,10),c(47,30,10,re/2,re*3/2),c(35,30,10,re/2,re*3/2),l(7,40,13,7,-1),l(17,40,43,14,-1);for(let x=3;x--;)for(let w=2;w--;)c(17+15*x,47,w?7:1,0,2*re,2);for(let x=2;x--;){let w=6,A=7,S=53+w*f*x,_=[v(S+A,54),v(S,40),v(S+w*f,40),v(S+A+w*f,54)];u(_,0,40,14)}s.restore()}function Rh(t){if(Yi=t,!Pn){let n={};try{n=JSON.parse(localStorage[t]||"{}")}catch{n={}}yo(s=>{s.unlocked=!!(n[s.id]&&n[s.id].unlocked)}),Ia()}zn(void 0,e);function e(){if(!wi.length)return;let n=wi[0],s=xn-vi;if(!vi)vi=xn;else if(s>Wi)vi=0,wi.shift();else{let i=Wi-os,r=si?(s-i)/os:0;n.render(r)}}}function yo(t){Object.values(Xs).forEach(e=>t(e))}function Lh(){yo(t=>t.unlocked=!1),Ia()}function Ia(){if(!Yi)return;let t={};yo(e=>{let n={name:e.name,description:e.description,icon:e.icon,unlocked:e.unlocked};e.image&&(n.src=e.image.src),t[e.id]=n}),localStorage[Yi]=JSON.stringify(t)}function Oh(t){Wi=t}function Ih(t){os=t}function Dh(t){Hi=t.copy()}function Fh(t){Oa=t}function Bl(t,e,n,s=125){let i,r,a,o,c,l,u,h,d,f,p,y,x,w=0,A,S=[],_=[],k=[],C=0,O=0,q=1,ce={},ne=xs/s*60>>2;for(;q;C++)S=[q=h=y=0],n.forEach((T,R)=>{for(u=e[T][C]||[0,0,0],q|=e[T][C]&&1,A=y+(e[T][0].length-2-(h?0:1))*ne,x=R===n.length-1,i=2,a=y;ine-99&&d&&p<1?p+=1/99:0)l=(1-p)*S[w++]/2||0,_[a]=(_[a]||0)-l*O+l,k[a]=(k[a++]||0)+l*O+l;c&&(p=c%1,O=u[1]||0,(c|=0)&&(S=ce[[f=u[w=0]||0,c]]=ce[[f,c]]||(o=[...t[f]],o[2]=(o[2]||220)*2**(c/12-1),c>0?ho(...o):[])))}y=A});return[_,k]}function Gh(t){Da=typeof t=="boolean"?t?1:0:t}function Bh(t){Fa=t}async function jh(){return new eo(await Box2D()),n(),zn(t,e),b;function t(){if(!It){b.step(),b.objects=b.objects.filter(s=>!s.destroyed);for(let s of b.objects)s.body&&(s.pos=b.vec2From(s.body.GetPosition()),s.angle=-s.body.GetAngle())}}function e(){(Fa||vt)&&b.world.DrawDebugData()}function n(){let i=new b.instance.JSDraw,r=l=>new De(l.get_r(),l.get_g(),l.get_b()),a=l=>r(b.instance.wrapPointer(l,b.instance.b2Color)),o=l=>a(l).scale(1,.8),c=(l,u)=>{let h=[];for(let d=u;d--;)h.push(b.vec2FromPointer(l+d*8));return h};i.DrawSegment=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),u=b.vec2FromPointer(u),On(l,u,.1,h,v(),0,!1)},i.DrawPolygon=function(l,u,h){h=o(h);let d=c(l,u);us(d,Sn,.1,h,v(),0,!1)},i.DrawSolidPolygon=function(l,u,h){h=o(h);let d=c(l,u);us(d,h,0,h,v(),0,!1)},i.DrawCircle=function(l,u,h){h=o(h),l=b.vec2FromPointer(l),Oi(l,u*2,Sn,.1,h,!1)},i.DrawSolidCircle=function(l,u,h,d){d=o(d),l=b.vec2FromPointer(l),h=b.vec2FromPointer(h).scale(u),Oi(l,u*2,d,.1,d,!1),On(v(),h,.1,d,l,0,!1)},i.DrawTransform=function(l){l=b.instance.wrapPointer(l,b.instance.b2Transform);let u=b.vec2From(l.get_p()),h=-l.get_q().GetAngle(),d=v(1,0),f=Q(.75,0,0,.8),p=v(0,1),y=Q(0,.75,0,.8);On(v(),d,.1,f,u,h,!1),On(v(),p,.1,y,u,h,!1)},i.AppendFlags(b.instance.b2Draw.e_shapeBit),i.AppendFlags(b.instance.b2Draw.e_jointBit),b.world.SetDebugDraw(i)}}function Jh(t,e,n,s=32,i=2,r=0){jl(t,e,n,te,s,ye,i,r,!1,!0)}function jl(t,e,n,s,i=1,r,a=.05,o=0,c=H,l,u){let h=n.offset(n.size),d=e.add(v(a-i*2)),f=v(i),p=e.scale(.5).subtract(f.scale(.5)),y=l?-1:1,x=l?-o:o;Ue(t,d,h,s,o,!1,r,c,l,u);for(let w=4;w--;){let A=w%2,S=p.multiply(v(A?w===1?1:-1:0,A?0:w?-1:1)),_=v(A?i:d.x,A?d.y:i),k=h.offset(n.size.multiply(v(w===1?1:w===3?-1:0,w===0?-y:w===2?y:0)));Ue(t.add(S.rotate(x)),_,k,s,o,!1,r,c,l,u)}for(let w=4;w--;){let A=w>1,S=w&&w<3,_=p.multiply(v(A?-1:1,S?-1:1)),k=h.offset(n.size.multiply(v(A?-1:1,S?y:-y)));Ue(t.add(_.rotate(x)),f,k,s,o,!1,r,c,l,u)}}function Nh(t,e,n,s=32,i=2,r=0){Jl(t,e,n,te,s,ye,i,r,!1,!0)}function Jl(t,e,n,s,i=1,r,a=.05,o=0,c=H,l,u){let h=n.frame(0),d=n.frame(1),f=n.frame(2),p=e.add(v(a-i*2)),y=v(i),x=e.scale(.5).subtract(y.scale(.5)),w=l?-1:1,A=l?-o:o;Ue(t,p,f,s,o,!1,r,c,l,u);for(let S=4;S--;){let _=o+S*re/2,k=S%2,C=x.multiply(v(k?S===1?1:-1:0,k?0:S?-w:w)),O=v(k?p.y:p.x,i);Ue(t.add(C.rotate(A)),O,d,s,_,!1,r,c,l,u)}for(let S=4;S--;){let _=o+S*re/2,k=!S||S>2,C=S>1,O=x.multiply(v(k?-1:1,C?-w:w));Ue(t.add(O.rotate(A)),y,h,s,_,!1,r,c,l,u)}}function zh(t,e=1,n=0,s=te,i=0,r=!1,a=0,o=ye,c=H,l=!1,u){let h=Nl(v(),e,n,0,r);us(h,s,a,o,t,i,c,l,u)}function Nl(t,e=1,n=0,s=0,i=!1,r=ti){m(D(t),"pos must be a vec2"),m(I(e)&&I(n),"size and percent must be numbers");let a=mt(n*4,4);a>=2&&(s+=re),a=a<=2?a-1:3-a,i&&(a=-a,s+=re);let o=[],c=ue(3,r>>1),l=e/2;for(let u=0;u<=c;u++){let h=u/c*re;o.push(v(l*ve(h),l*me(h)).rotate(s).add(t))}for(let u=c;u>=0;u--){let h=u/c*re;o.push(v(l*ve(h),-l*a*me(h)).rotate(s).add(t))}return o}function zc(t){return t&&typeof t.lerp=="function"}function Uh(t,e,n,s,i=1,r={}){m(t!=null&&typeof t=="object","tweenProperty target must be an object"),m(ee(e)&&e.length>0,"tweenProperty propertyPath must be a non-empty string");let a=e.split("."),o=a.pop(),c=l=>{let u=t;for(let h of a)u=u[h];u[o]=l};return new to(c,n,s,i,r)}function zl(t){t.loopRemaining!==1/0&&t.loopRemaining<=1||(t.loopRemaining!==1/0&&(t.loopRemaining-=1),t.life=t.duration,t.thenCallback=()=>zl(t),ut.push(t),t.callback(t.interp(t.duration)))}function Ul(t){if(t.loopRemaining!==1/0&&t.loopRemaining<=1)return;t.loopRemaining!==1/0&&(t.loopRemaining-=1);let e=t.start;t.start=t.end,t.end=e,t.life=t.duration,t.thenCallback=()=>Ul(t),ut.push(t),t.callback(t.interp(t.duration))}function Vl(t,e){t===void 0?(t=dt-Jc,e=xn-Nc,Jc=dt,Nc=xn):e===void 0&&(e=t);for(let n=ut.length;n--;){let s=ut[n];if(s.paused)continue;let i=s.useRealTime?e:t;if(!(i<=0))if(s.life-=i,s.life>0)s.callback(s.interp(s.life));else{s.callback(s.interp(0)),ut.splice(n,1);let r=s.thenCallback;s.thenCallback=void 0,r&&r()}}}function Vh(){for(let t of ut)t.thenCallback=void 0;ut.length=0}var Ti,Ai,sd,Vr,Me,qr,Uc,dt,xn,It,Qo,Et,ki,Vc,In,tr,Ye,Hc,io,Yc,Ut,pn,vt,wt,Dn,Fn,ls,nr,Vt,St,re,pe,Ie,Fs,Ci,fe,ue,pt,Qc,Zc,me,ve,el,Hr,or,Se,De,te,Sn,ye,kt,vd,Xr,wd,ll,ul,Td,dl,fl,Ad,Dt,je,de,oe,Qr,oo,mn,ts,Rs,ns,ss,Zr,jn,yn,ei,ea,K,H,ti,ro,ao,co,lo,ta,na,sa,ia,oa,Wt,st,Pi,uo,ra,Ls,Ln,vn,aa,At,ys,Un,gs,bs,ni,Tn,ot,ca,Os,Mi,si,rt,Gn,la,ua,Qt,$,we,Ge,$t,fn,Rt,Ht,z,wn,Ft,Gt,Bt,Zt,If,vl,Ii,Nt,tt,ha,Pt,pa,Di,rs,hn,ma,is,_e,yt,ae,Mt,Mn,Zo,ds,gt,Jn,Fi,ci,Yt,un,Al,Sa,kl,zs,Rn,fs,Fc,Gi,ke,Kt,xs,Vs,Bi,bn,Bn,Ji,qs,Ws,ur,wh,Ni,he,g,Aa,zi,Ui,Nn,Hn,ps,ft,dr,as,He,Hs,Be,Ds,fr,hr,ka,Vi,pr,qi,Ca,Pl,Th,po,Ml,cs,Pn,Wi,os,Hi,Oa,Xs,wi,Yi,vi,$i,Ks,gr,br,qe,xr,ie,Sr,vr,wr,P,Da,Tr,bt,Xi,Ar,kr,Qs,Cr,_r,Er,Pr,b,Fa,Zs,Ki,Mr,Rr,Qi,at,Lr,Zi,Or,Ir,Dr,Fr,Gr,Br,jr,Jr,Nr,zr,eo,ut,Jc,Nc,to,no,qh,er,so,Ur,Wl=Kl(()=>{"use strict";Ti="LittleJS",Ai="1.18.19",sd=60,Vr=.016666666666666666,Me=[],qr=[],Uc=0,dt=0,xn=0,It=!1;Qo=0,Et=0,ki=0,Vc=!0,In=[],tr=class{constructor(e,n,s,i){this.update=e,this.render=n,this.glContextLost=s,this.glContextRestored=i}};Ye=!0,Hc=.5,io=!0,Yc="Escape",Ut=!1,pn=[],vt=!1,wt=!1,Dn=!1,Fn=!1,ls=!1;re=Math.PI,pe=Math.abs,Ie=Math.floor,Fs=Math.ceil,Ci=Math.round,fe=Math.min,ue=Math.max,pt=t=>Math.sign(t),Qc=(...t)=>Math.hypot(...t),Zc=t=>Math.log2(t),me=Math.sin,ve=Math.cos,el=Math.tan,Hr=Math.atan2;or=class{constructor(e=123456789){m(e!==0,"RandomGenerator seed must be non-zero (xorshift is fixed at 0)"),this.seed=e}float(e=1,n=0){return this.seed^=this.seed<<13,this.seed^=this.seed>>>17,this.seed^=this.seed<<5,n+(e-n)*((this.seed>>>0)/2**32)}int(e,n=0){return Ie(this.float(e,n))}bool(e=.5){return this.float().5?1:-1}floatSign(e=1,n=0){let s=fe(e,n),r=ue(e,n)-s,a=this.float(r*2);return ae?this.scale(e/n):this.copy()}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.x}reflect(e,n=1){return this.subtract(e.scale((1+n)*this.dot(e)))}angle(){return Hr(this.x,this.y)}setAngle(e=0,n=1){return lt(e),lt(n),this.x=n*me(e),this.y=n*ve(e),this}rotate(e){lt(e);let n=ve(-e),s=me(-e);return new t(this.x*n-this.y*s,this.x*s+this.y*n)}setDirection(e,n=1){return lt(e),lt(n),e=mt(e,4),m(e===0||e===1||e===2||e===3,"Vector2.setDirection() direction must be an integer between 0 and 3."),this.x=e%2?e-1?-n:n:0,this.y=e%2?0:e?-n:n,this}direction(){return pe(this.x)>pe(this.y)?this.x<0?3:1:this.y<0?2:0}abs(){return new t(pe(this.x),pe(this.y))}floor(){return new t(Ie(this.x),Ie(this.y))}snap(e){return lt(e),new t(Ie(this.x*e)/e,Ie(this.y*e)/e)}mod(e=1){return new t(mt(this.x,e),mt(this.y,e))}area(){return pe(this.x*this.y)}lerp(e,n){Ic(e),lt(n);let s=X(n);return new t(e.x*s+this.x*(1-s),e.y*s+this.y*(1-s))}arrayCheck(e){return this.x>=0&&this.y>=0&&this.x(u=mt(u,1))*6<1?c+(l-c)*6*u:u*2<1?l:u*3<2?c+(l-c)*(4-u*6):c;return this.r=o(a,r,e+1/3),this.g=o(a,r,e),this.b=o(a,r,e-1/3),this.a=i,Ps(this),this}HSLA(){let e=X(this.r),n=X(this.g),s=X(this.b),i=X(this.a),r=ue(e,n,s),a=fe(e,n,s),o=(r+a)/2,c=0,l=0;if(r!==a){let u=r-a;l=o>.5?u/(2-r-a):u/(r+a),e===r?c=(n-s)/u+(n((s=X(s)*255|0)<16?"0":"")+s.toString(16);return"#"+n(this.r)+n(this.g)+n(this.b)+(e?n(this.a):"")}setHex(e){if(m(ee(e),"Color hex code must be a string"),m(e[0]==="#","Color hex code must start with #"),m([4,5,7,9].includes(e.length),"Invalid hex"),e.length<6){let n=s=>X(parseInt(e[s],16)/15);this.r=n(1),this.g=n(2),this.b=n(3),this.a=e.length===5?n(4):1}else{let n=s=>X(parseInt(e.slice(s,s+2),16)/255);this.r=n(1),this.g=n(3),this.b=n(5),this.a=e.length===9?n(7):1}return Ps(this),this}rgbaInt(){let e=X(this.r)*255|0,n=X(this.g)*255<<8,s=X(this.b)*255<<16,i=X(this.a)*255<<24;return e+n+s+i}isValid(){return I(this.r)&&I(this.g)&&I(this.b)&&I(this.a)}},te=ht(Q()),Sn=ht(Q(1,1,1,0)),ye=ht(Q(0,0,0)),kt=ht(Q(0,0,0,0)),vd=ht(Q(.5,.5,.5)),Xr=ht(Q(1,0,0)),wd=ht(Q(1,.5,0)),ll=ht(Q(1,1,0)),ul=ht(Q(0,1,0)),Td=ht(Q(0,1,1)),dl=ht(Q(0,0,1)),fl=ht(Q(.5,0,1)),Ad=ht(Q(1,0,1)),Dt=class{constructor(e,n=!1){m(e===void 0||I(e),"Constructed Timer is invalid.",e),this.useRealTime=n;let s=this.getGlobalTime();this.time=e===void 0?void 0:s+e,this.setTime=e}set(e=0){m(I(e),"Timer is invalid.",e);let n=this.getGlobalTime();this.time=n+e,this.setTime=e}setUseRealTime(e=!0){m(!this.isSet(),"Cannot change global time setting while timer is set."),this.useRealTime=e}unset(){this.time=void 0}isSet(){return this.time!==void 0}active(){return this.getGlobalTime()=this.time}get(){return this.isSet()?this.getGlobalTime()-this.time:0}getPercent(){return this.isSet()?this.setTime?1-$e(this.time-this.getGlobalTime(),0,this.setTime):1:0}getSetTime(){return this.isSet()?this.setTime:0}getGlobalTime(){return this.useRealTime?xn:dt}toString(){return this.isSet()?pe(this.get())+" seconds "+(this.get()<0?"before":"after"):"unset"}valueOf(){return this.get()}};je=v(),de=0,oe=32,Qr=1,oo=!0,mn=kt,ts=v(1920,1080),Rs=0,ns=0,ss=v(),Zr=!1,jn=!0,yn=1,ei="arial",ea=!1,K=!1,H=!0,ti=32,ro=v(16),ao=0,co=0,lo=!0,ta=1,na=1,sa=1,ia=0,oa=.8,Wt=1,st=v(),Pi=1,uo=!0,ra=!0,Ls=!0,Ln=!0,vn=!1,aa=!1,At=0,ys=4,Un=!0,gs=0,bs=!1,ni=!0,Tn=!1,ot=100,ca=.3,Os=3,Mi=0,si=!0,rt=!0,Gn=.3,la=40,ua=.7;Qt=class t{constructor(e=v(),n=v(1),s,i=0,r=te,a=0){m(D(e),"object pos must be a vec2"),m(D(n),"object size must be a vec2"),m(!s||s instanceof Bt,"object tileInfo should be a TileInfo or undefined"),m(typeof i=="number"&&isFinite(i),"object angle should be a number"),m(Z(r),"object color should be a valid rgba color"),m(typeof a=="number","object renderOrder should be a number"),this.pos=e.copy(),this.size=n.copy(),this.drawSize=void 0,this.tileInfo=s,this.angle=i,this.color=r.copy(),this.additiveColor=void 0,this.mirror=!1,this.destroyed=!1,this.mass=ta,this.damping=na,this.angleDamping=sa,this.restitution=ia,this.friction=oa,this.gravityScale=1,this.renderOrder=a,this.velocity=v(),this.angleVelocity=0,this.spawnTime=dt,this.children=[],this.clampSpeed=!0,this.groundObject=void 0,this.parent=void 0,this.localPos=v(),this.localAngle=0,this.collideTiles=!1,this.collideSolidObjects=!1,this.isSolid=!1,this.collideRaycast=!1,Me.push(this)}updateTransforms(){let e=this.parent;if(e){let n=e.getMirrorSign(),s=this.localPos,i=e.pos,r=s.x*n,a=s.y,o=e.angle;if(o){let c=ve(-o),l=me(-o);this.pos.set(r*c-a*l+i.x,r*l+a*c+i.y)}else this.pos.set(r+i.x,a+i.y);this.angle=n*this.localAngle+o}for(let n of this.children)n.updateTransforms()}updatePhysics(){if(m(!this.parent),this.destroyed)return;this.clampSpeed&&(this.velocity.x=X(this.velocity.x,-Wt,Wt),this.velocity.y=X(this.velocity.y,-Wt,Wt));let e=this.pos.copy();if(this.velocity.x*=this.damping,this.velocity.y*=this.damping,this.mass&&(this.velocity.x+=st.x*this.gravityScale,this.velocity.y+=st.y*this.gravityScale),this.pos.x+=this.velocity.x,this.pos.y+=this.velocity.y,this.angle+=this.angleVelocity*=this.angleDamping,m(this.angleDamping>=0&&this.angleDamping<=1),m(this.damping>=0&&this.damping<=1),!lo||!this.mass)return;let n=this.velocity.y<0&&st.y<0||this.velocity.y>0&&st.y>0;if(this.groundObject){let s=ue(this.friction,this.groundObject.friction),i=this.groundObject.velocity.x;this.velocity.x=i+(this.velocity.x-i)*s,this.groundObject=void 0}if(this.collideSolidObjects)for(let i of qr){if(i.destroyed||i.parent||i===this||!this.isSolid&&!i.isSolid||!this.isOverlappingObject(i))continue;let r=this.collideWithObject(i),a=i.collideWithObject(this);if(!r||!a)continue;if(Ei(e,this.size,i.pos,i.size)){let d=e.subtract(i.pos),f=d.length(),y=f<.001?v(0,1):d.scale(.001/f);this.velocity=this.velocity.add(y),i.mass&&(i.velocity=i.velocity.subtract(y)),vt&&sr(this.pos,this.size,i.pos,i.size,"#f00");continue}let o=this.size.add(i.size),c=(e.y-i.pos.y)*2>o.y+st.y,l=pe(e.y-i.pos.y)*20?-1:1)>0?Ie(e.y-this.size.y/2+1)+this.size.y/2+.001:Fs(e.y+this.size.y/2-1)-this.size.y/2-.001;if(pe(u-this.pos.y)<.1&&!dn(v(this.pos.x,u),this.size,this)){this.pos.y=u,vt&&Ee(this.pos,this.size,"#ff0");return}this.pos.x=e.x,this.velocity.x*=-a}if(r||!i){if(n){let c=this.size.y/2+1e-4;this.pos.y=st.y<0?Ie(e.y-this.size.y/2)+c:Fs(e.y+this.size.y/2)-c,this.groundObject=s}else this.pos.y=e.y,this.groundObject=void 0;this.velocity.y*=-a}vt&&Ee(this.pos,this.size,"#f00")}}}update(){}render(){Ue(this.pos,this.drawSize||this.size,this.tileInfo,this.color,this.angle,this.mirror,this.additiveColor)}renderLight(){}destroy(e=!1){var n;if(!this.destroyed){this.destroyed=!0,(n=this.parent)==null||n.removeChild(this);for(let s of this.children)s.parent=void 0,s.destroy(e)}}localToWorld(e){return this.pos.add(e.rotate(this.angle))}worldToLocal(e){return e.subtract(this.pos).rotate(-this.angle)}localToWorldVector(e){return e.rotate(this.angle)}worldToLocalVector(e){return e.rotate(-this.angle)}collideWithTile(e,n){return e>0}collideWithObject(e){return!0}getUp(e=1){return v().setAngle(this.angle,e)}getRight(e=1){return v().setAngle(this.angle+re/2,e)}getAliveTime(){return dt-this.spawnTime}getSpeed(){return this.velocity.length()}applyAcceleration(e){this.mass&&(this.velocity=this.velocity.add(e))}applyAngularAcceleration(e){this.mass&&(this.angleVelocity+=e)}applyForce(e){this.mass&&this.applyAcceleration(e.scale(1/this.mass))}getMirrorSign(){return this.mirror?-1:1}addChild(e,n=v(),s=0){return m(!this.destroyed,"cannot add child to destroyed object"),this.destroyed||(m(!e.parent&&!this.children.includes(e)),m(e instanceof t,"child must be an EngineObject"),m(e!==this,"cannot add self as child"),this.children.push(e),e.parent=this,e.localPos=n.copy(),e.localAngle=s,e.updateTransforms()),e}removeChild(e){m(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}isOverlappingObject(e){return this.isOverlapping(e.pos,e.size)}isOverlapping(e,n=v()){return Ei(this.pos,this.size,e,n)}setCollision(e=!0,n=!0,s=!0,i=!0){m(e||!n,"solid objects must be set to collide"),this.collideSolidObjects=e,this.isSolid=n,this.collideTiles=s,this.collideRaycast=i}toString(){let e="type = "+this.constructor.name;return(this.pos.x||this.pos.y)&&(e+=`
+pos = `+this.pos),(this.velocity.x||this.velocity.y)&&(e+=`
+velocity = `+this.velocity),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.angle&&(e+=`
+angle = `+this.angle.toFixed(3)),this.color&&(e+=`
+color = `+this.color),e}renderDebugInfo(){if(!Ye)return;let e=this.collideTiles||this.collideSolidObjects||this.isSolid;if(!e&&!this.parent)return;let n=v(ue(this.size.x,.2),ue(this.size.y,.2)),s=Q(this.collideTiles?1:0,this.collideSolidObjects?1:0,this.isSolid?1:0,.5);Ee(this.pos,n,s,0,this.angle,e),this.parent&&Ee(this.pos,n.scale(.8),Q(1,1,1,.5),0,this.angle),this.parent&&Lt(this.pos,this.parent.pos,Q(1,1,1,.5),.5)}},z=v(),wn=[];Bt=class t{constructor(e=v(),n=ro,s=wn[0],i=ao,r=co){this.pos=e.copy(),this.size=n.copy(),this.padding=i,this.textureInfo=s,this.bleed=r}offset(e){return new t(this.pos.add(e),this.size,this.textureInfo,this.padding,this.bleed)}frame(e){m(typeof e=="number");let n=this.size.x+this.padding*2,s=e*n;return m(s+this.size.x<=this.textureInfo.size.x,"frame extends beyond texture width!"),this.offset(new Se(s))}setFullImage(e=this.textureInfo){return this.textureInfo=e,this.pos=new Se,this.size=e.size.copy(),this.bleed=this.padding=0,this}tile(e){return ii(e,this.size,this.textureInfo,this.padding,this.bleed)}},Zt=class{constructor(e,n=!0,s=!1){this.image=e,this.size=e?v(e.width,e.height):v(),this.sizeInverse=e?v(1/e.width,1/e.height):v(),this.glTexture=void 0,this.wrap=s,n&&this.createWebGLTexture()}createWebGLTexture(){kh(this)}destroyWebGLTexture(){Ch(this)}hasWebGL(){return!!this.glTexture}setWrap(e=!0){this.wrap=e,Ol(this.glTexture,e)}};If=0;Ii=class{constructor(e){m(!!e,"tileInfo is required for ImageFont"),this.tileInfo=e.frame(0)}drawText(e,n,s=1,i,r,a,o){m(D(s)||typeof s=="number","size must be a vec2 or number"),typeof s=="number"?(m(s>0),s*=oe,s=new Se(s,s)):s=s.scale(oe),this.drawTextScreen(e,qn(n),s,i,r,a,o)}drawTextScreen(e,n,s,i=!0,r=te,a=H,o){m(ee(e),"text must be a string"),m(D(n),"pos must be a vec2"),m(D(s)||typeof s=="number","size must be a vec2 or number"),m(Z(r),"color must be a color"),s=typeof s=="number"?new Se(s,s):s;let c=new Se,l=this.tileInfo,u=l.padding,h=l.size.x+u*2,d=l.size.y+u*2,f=l.textureInfo.size.x/h|0;(e+"").split(`
+`).forEach((p,y)=>{let x=i?(p.length-1)*s.x/2:0;for(let w=p.length;w--;){let A=p.charCodeAt(w),S=A<32||A>127?95:A-32,_=S%f,k=S/f|0;l.pos.x=_*h+u,l.pos.y=k*d+u,c.x=n.x+w*s.x-x|0,c.y=n.y+y*s.y|0,Ue(c,s,l,r,0,!1,void 0,a,!0,o)}})}};Nt=v(),tt=v(),ha=v(),Pt=v(),pa=0,Di=!0,rs=!1,hn="mouse",ma=6,is=!0,_e=0,yt=!K&&window.ontouchstart!==void 0;ae=[[]],Mt=[],Mn=[],Zo=[],ds=new Dt,gt=[],Jn=[],Fi=[],ci=[],Yt=new Map,zs=[],fs=!0;Gi="http://www.w3.org/2000/svg";ke=new AudioContext,xs=44100;Vs=class{constructor(e,n,s=la,i=ua,r){var a;if(!(!rt||K)){if(m(!e||Tt(e)||ee(e),"asset must be a file name or zzfx array"),m(n===void 0||I(n),"randomness must be a number"),m(n===void 0||n>=0&&n<=1,"randomness must be between 0 and 1"),m(I(s),"range must be a number"),m(I(i),"taper must be a number"),this.range=s,this.taper=i,this.randomness=n!=null?n:0,this.sampleRate=xs,this.loadedPercent=0,this.onloadCallback=r,Tt(e)){let o=e.slice(),c=n!=null?n:.05,l=1;this.randomness=(a=o[l])!=null?a:c,o[l]=0,this.sampleChannels=[ho(...o)],this.loadedPercent=1,r==null||r(this)}else if(typeof e=="string"){let o=e;this.loadSound(o)}}}play(e,n=1,s=1,i=1,r=!1,a=!1){if(m(!e||D(e),"pos must be a vec2"),m(I(n),"volume must be a number"),m(I(s),"pitch must be a number"),m(I(i),"randomnessScale must be a number"),!rt||K||!this.sampleChannels)return;let o;if(e){let u=this.range;if(u){let h=je.distanceSquared(e);if(h>u*u)return;n*=$e(h**.5,u,u*this.taper)}o=qn(e).x*2/$.width-1}let c=s+s*this.randomness*i*Ae(-1,1),l=new Bi(this,n,c,o,r,a);return Ye&&ls&&e&&(nt(e,.5,"#0ff",.5,!0),this.range&&(nt(e,2*this.range,"#0ff",.5),nt(e,2*this.range*this.taper,"#0ff",.5)),es("vol "+n.toFixed(2)+" pitch "+c.toFixed(2),e,.5,"#0ff",.5)),l}playMusic(e=1,n=!0,s=!1){return this.play(void 0,e,1,0,n,s)}playNote(e=0,n,s){m(I(e),"semitoneOffset must be a number");let i=_l(e,1);return this.play(n,s,i,0)}getDuration(){var e,n;return((n=(e=this.sampleChannels)==null?void 0:e[0])==null?void 0:n.length)/this.sampleRate||0}isLoaded(){return this.loadedPercent===1}async loadSound(e){var c;let n=await fetch(e);if(!n.ok)throw new Error(`Failed to load sound from ${e}: ${n.status} ${n.statusText}`);let s=await n.arrayBuffer(),i=await ke.decodeAudioData(s),r=i.numberOfChannels,a=1e5,o=[];for(let l=0;lsetTimeout(x,0));let f=fe(d+a,h);for(;d=0,"Sound volume must be positive or zero"),m(s>=0,"Sound rate must be positive or zero"),m(I(i),"Sound pan must be a number"),this.sound=e,this.volume=n,this.rate=s,this.pan=i,this.loop=r,this.pausedTime=0,this.startTime=void 0,this.gainNode=void 0,this.source=void 0,this.onendedCallback=o=>{o===this.source&&(this.source=void 0)},a||this.start()}start(e=0){m(e>=0,"Sound start offset must be positive or zero"),this.isPlaying()&&this.stop(),this.gainNode=ke.createGain(),this.source=Ta(this.sound.sampleChannels,this.volume,this.rate,this.pan,this.loop,this.sound.sampleRate,this.gainNode,e,this.onendedCallback),this.source?(this.startTime=ke.currentTime-e,this.pausedTime=void 0):(this.startTime=void 0,this.pausedTime=0)}setVolume(e){m(e>=0,"Sound volume must be positive or zero"),this.volume=e,this.gainNode&&(this.gainNode.gain.value=e)}stop(e=0){if(m(e>=0,"Sound fade time must be positive or zero"),this.isPlaying())if(e){let n=ke.currentTime,s=n+e;this.gainNode.gain.cancelScheduledValues(n),this.gainNode.gain.setValueAtTime(this.volume,n),this.gainNode.gain.linearRampToValueAtTime(0,s),this.source.stop(s)}else this.source.stop();this.pausedTime=0,this.source=void 0,this.startTime=void 0}pause(){this.isPaused()||(this.pausedTime=this.getCurrentTime(),this.source.stop(),this.source=void 0,this.startTime=void 0)}resume(){this.isPaused()&&this.start(this.pausedTime)}isPlaying(){return!!this.source}isPaused(){return!this.isPlaying()}getCurrentTime(){if(!this.isPlaying())return this.pausedTime;let e=this.getDuration();return e?mt(ke.currentTime-this.startTime,e):0}getDuration(){return this.rate?this.sound.getDuration()/this.rate:0}getSource(){return this.source}};bn=[];Bn=class{constructor(e,n=0,s=!1,i=new De){this.tile=e,this.direction=n,this.mirror=s,this.color=i.copy()}clear(){this.tile=this.direction=0,this.mirror=!1,this.color=new De}},Ji=class extends Qt{constructor(e,n,s=0,i=0,r=v(512),a=!0){var o;m(D(r),"canvasSize must be a Vector2"),super(e,n,void 0,s,te,i),this.canvas=K?void 0:new OffscreenCanvas(r.x,r.y),this.context=(o=this.canvas)==null?void 0:o.getContext("2d"),this.textureInfo=new Zt(this.canvas,a),this.mass=0}destroy(){this.destroyed||(this.textureInfo.destroyWebGLTexture(),super.destroy())}render(){this.draw(this.pos,this.size,this.color,this.angle,this.mirror,this.additiveColor)}draw(e,n,s=te,i=0,r=!1,a,o=!1,c){let l=new Bt().setFullImage(this.textureInfo),u=this.hasWebGL();Ue(e,n,l,s,i,r,a,u,o,c)}updateWebGL(){this.textureInfo.createWebGLTexture()}hasWebGL(){return H&&this.textureInfo.hasWebGL()}},qs=class extends Ji{constructor(e,n,s=ii(),i=0,r=!0){let a=s?n.multiply(s.size):n;if(super(e,n,0,i,a,r),this.tileInfo=void 0,this.data=[],this.isUsingWebGL=!1,K){this.render=()=>{},this.redraw=()=>{},this.redrawStart=()=>{},this.redrawEnd=()=>{},this.drawTileData=()=>{},this.redrawTileData=()=>{},this.drawLayerTile=()=>{},this.drawLayerRect=()=>{},this.drawTile=()=>{},this.drawRect=()=>{},this.clearLayerRect=()=>{};return}s&&(this.tileInfo=s.frame(0),this.tileInfo.bleed=0);for(let o=this.size.area();o--;)this.data.push(new Bn)}setData(e,n,s=!1){if(e=e.floor(),m(D(e),"layerPos must be a Vector2"),m(n instanceof Bn,"data must be a TileLayerData"),!e.arrayCheck(this.size)||(this.data[(e.y|0)*this.size.x+(e.x|0)]=n,!s))return;Ge===this.context?this.drawTileData(e):this.redrawTileData(e)}clearData(e,n=!1){this.setData(e,new Bn,n)}getData(e){return m(D(e),"layerPos must be a Vector2"),e.arrayCheck(this.size)?this.data[(e.y|0)*this.size.x+(e.x|0)]:void 0}update(){!H&&this.isUsingWebGL&&(this.isUsingWebGL=!1,this.redraw())}render(){m(Ge!==this.context,"must call redrawEnd() after drawing tiles!");let e=this.drawSize||this.size,n=this.pos.add(e.scale(.5));this.draw(n,this.size,this.color,this.angle,this.mirror,this.additiveColor)}onRedraw(){}redraw(){this.redrawStart(!0);for(let e=this.size.x;e--;)for(let n=this.size.y;n--;)this.drawTileData(v(e,n),!1);this.isUsingWebGL&&Je(),this.onRedraw(),this.redrawEnd()}redrawStart(e=!1){var s,i;if(!this.context)return;m(Ge!==this.context),this.savedRenderSettings=[Ge,z,je,oe,mn],Ge=this.context;let n=(i=(s=this.tileInfo)==null?void 0:s.size)!=null?i:v(1);z=this.size.multiply(n),mn=kt,je=this.size.multiply(n).scale(.5),oe=1,this.isUsingWebGL=this.hasWebGL(),this.isUsingWebGL?Ms(this.textureInfo.glTexture,e):(this.context.imageSmoothingEnabled=!jn,e&&(this.canvas.width=z.x,this.canvas.height=z.y))}redrawEnd(){this.context&&(m(Ge===this.context),this.isUsingWebGL&&Ms(),[Ge,z,je,oe,mn]=this.savedRenderSettings)}drawTileData(e,n=!0){var o,c;if(!this.context)return;m(Ge===this.context,"must call redrawStart() before drawing tiles");let s=(c=(o=this.tileInfo)==null?void 0:o.size)!=null?c:v(1),i=e.multiply(s);n&&this.clearLayerRect(i,s);let r=this.getData(e);if(!r||!r.tile)return;let a=this.tileInfo&&this.tileInfo.tile(r.tile);this.drawLayerTile(i,s,a,r.color,r.direction*re/2,r.mirror)}redrawTileData(e,n=!0){this.context&&(m(Ge!==this.context,"redrawStart() should not be active when calling redrawTileData(), instead use drawTileData()"),this.redrawStart(),this.drawTileData(e,n),this.redrawEnd())}drawLayerTile(e,n=v(1),s,i=te,r=0,a,o){let c=e.add(n.scale(.5));Ue(c,n,s,i,r,a,o,this.isUsingWebGL)}drawLayerRect(e,n,s,i=0){this.drawLayerTile(e,n,void 0,s,i)}drawTile(e,n=v(1),s,i=new De,r=0,a=!1){e=e.subtract(this.pos).multiply(this.tileInfo.size),n=n.multiply(this.tileInfo.size),e.y=this.canvas.height-e.y;let o=z;z=v(this.canvas.width,this.canvas.height);let c=this.hasWebGL();c&&Ms(this.textureInfo.glTexture);let l=c?void 0:this.context;Ue(e,n,s,i,r,a,void 0,c,!0,l),c&&Ms(),z=o}drawRect(e,n,s,i){this.drawTile(e,n,void 0,s,i)}clearLayerRect(e,n){m(Ge===this.context,"must call redrawStart() before clearing tiles");let s=e.x,i=this.canvas.height-e.y-n.y;this.hasWebGL()?Gl(s,i,n.x,n.y):this.context.clearRect(s,i,n.x,n.y)}},Ws=class extends qs{constructor(e,n,s=ii(),i=0,r=!0){super(e,n.floor(),s,i,r),this.collisionData=[],this.initCollision(this.size),bn.push(this),this.isSolid=!0}destroy(){if(this.destroyed)return;let e=bn.indexOf(this);m(e>=0,"tile collision layer not found in array"),e>=0&&bn.splice(e,1),super.destroy()}initCollision(e){m(D(e),"size must be a Vector2"),this.size=e.floor(),this.collisionData=[],this.collisionData.length=e.area(),this.collisionData.fill(0)}setCollisionData(e,n=1){m(D(e),"layerPos must be a Vector2");let s=(e.y|0)*this.size.x+(e.x|0);e.arrayCheck(this.size)&&(this.collisionData[s]=n)}clearCollisionData(e){this.setCollisionData(e,0)}getCollisionData(e){m(D(e),"layerPos must be a Vector2");let n=(e.y|0)*this.size.x+(e.x|0);return e.arrayCheck(this.size)?this.collisionData[n]:0}collisionTest(e,n=new Se,s){m(D(e)&&D(n),"pos and size must be Vector2s"),m(!s||typeof s=="function"||s instanceof Qt,"callbackObject must be a function or EngineObject");let i=s?typeof s=="function"?(d,f)=>s(d,f):(d,f)=>s.collideWithTile(d,f):()=>!0,r=e.x-this.pos.x,a=e.y-this.pos.y;if(r+n.x/2<0||r-n.x/2>this.size.x||a+n.y/2<0||a-n.y/2>this.size.y)return!1;let o=ue(r-n.x/2|0,0),c=ue(a-n.y/2|0,0),l=fe(ue(r+n.x/2,o+1),this.size.x),u=fe(ue(a+n.y/2,c+1),this.size.y),h=new Se;for(let d=c;ds(l,u):(l,u)=>s.collideWithTile(l,u):l=>l>0,a=l=>{let u=this.getCollisionData(o.set(l.x-this.pos.x,l.y-this.pos.y));return u&&r(u,l)},o=new Se,c=il(e,n,a,i);if(wt&&c){let l=c.floor().add(v(.5));Ee(l,v(1),"#f008"),Lt(e,n,"#00f",.02),Lt(e,c,"#f00",.02),Wr(c,"#0f0"),i&&Lt(c,c.add(i),"#ff0",.02)}return c}},ur=class extends Qt{constructor(e,n,s=0,i=0,r=100,a=re,o,c=te,l=te,u=Sn,h=Sn,d=.5,f=.1,p=1,y=.1,x=.05,w=1,A=1,S=0,_=re,k=.1,C=.2,O=!1,q=!1,ce=!0,ne=q?1e9:0,T=!1){super(e,v(),o,n,void 0,ne),this.emitCircle=typeof s=="number",this.emitSize=typeof s=="number"?v(s):s.copy(),this.emitTime=i,this.emitRate=r,this.emitConeAngle=a,this.colorStartA=c.copy(),this.colorStartB=l.copy(),this.colorEndA=u.copy(),this.colorEndB=h.copy(),this.randomColorLinear=ce,this.particleTime=d,this.sizeStart=f,this.sizeEnd=p,this.speed=y,this.angleSpeed=x,this.damping=w,this.angleDamping=A,this.gravityScale=S,this.particleConeAngle=_,this.fadeRate=k,this.randomness=C,this.collideTiles=O,this.additive=q,this.localSpace=T,this.trailScale=0,this.particleCreateCallback=void 0,this.particleDestroyCallback=void 0,this.particleCollideCallback=void 0,this.velocityInheritance=0,this.emitTimeBuffer=0,this.particles=[],this.previousAngle=this.angle,this.previousPos=this.pos.copy()}update(){if(m(this.angleDamping>=0&&this.angleDamping<=1),m(this.damping>=0&&this.damping<=1),this.velocityInheritance){let s=this.velocityInheritance;this.velocity.x=s*(this.pos.x-this.previousPos.x),this.velocity.y=s*(this.pos.y-this.previousPos.y),this.angleVelocity=s*(this.angle-this.previousAngle),this.previousAngle=this.angle,this.previousPos.x=this.pos.x,this.previousPos.y=this.pos.y}if(this.isActive()){if(this.emitRate&&Pi){let s=1/this.emitRate/Pi;for(this.emitTimeBuffer+=Vr;this.emitTimeBuffer>0;this.emitTimeBuffer-=s)this.emitParticle()}}else this.particles.length===0&&this.destroy(!0);let e=this.particles,n=0;for(let s=0;sA+A*Ae(s,-s),r=i(this.particleTime),a=i(this.sizeStart),o=i(this.sizeEnd),c=i(this.speed),l=i(this.angleSpeed)*rl(),u=Ae(this.emitConeAngle,-this.emitConeAngle),h=ir(this.colorStartA,this.colorStartB,this.randomColorLinear),d=ir(this.colorEndA,this.colorEndB,this.randomColorLinear),f=this.localSpace?u:this.angle+u,p=v(c*me(f),c*ve(f)),y=l;!this.localSpace&&this.velocityInheritance>0&&(p.x+=this.velocity.x,p.y+=this.velocity.y,y+=this.angleVelocity);let x=new Ni(this,e,n,h,d,r,a,o,p,y);return this.particles.push(x),(w=this.particleCreateCallback)==null||w.call(this,x),x}updatePhysics(){}render(){for(let e of this.particles)e.render()}isActive(){return!this.emitTime||this.getAliveTime()0&&(this.destroyed=!1,this.emitTime=-1))}},wh=new Se,Ni=class{constructor(e,n,s,i,r,a,o,c,l=v(),u=0){this.emitter=e,this.pos=n,this.angle=s,this.size=v(o),this.color=i.copy(),this.colorStart=i,this.colorEnd=r,this.lifeTime=a,this.sizeStart=o,this.sizeEnd=c,this.velocity=l,this.angleVelocity=u,this.spawnTime=dt,this.mirror=ol(),this.groundObject=void 0,this.destroyed=!1,this.tileInfo=e.tileInfo}update(){let e=this.emitter,n=e.damping,s=e.angleDamping,i=e.restitution,r=e.friction,a=e.gravityScale,o=e.collideTiles,c=e.particleCollideCallback;if(this.lifeTime>0&&dt-this.spawnTime>this.lifeTime){this.destroy();return}let l=this.pos.copy();if(this.velocity.x*=n,this.velocity.y*=n,this.pos.x+=this.velocity.x+=st.x*a,this.pos.y+=this.velocity.y+=st.y*a,this.angle+=this.angleVelocity*=s,!lo||!o)return;let u=this.velocity.lengthSquared();if(u>Wt*Wt){let d=Wt/u**.5;this.velocity.x*=d,this.velocity.y*=d}this.groundObject=void 0;let h=c?d=>{let f=ji(d);return f&&c(this,f,d)}:d=>ji(d)>0;if(h(this.pos)){let d=dn(this.pos);if(!h(l)){let f=h(v(this.pos.x,l.y)),p=h(v(l.x,this.pos.y)),y=ue(i,d.restitution),x=ue(r,d.friction);f&&(this.pos.x=l.x,this.velocity.x*=-y,this.velocity.y*=x),(p||!f)&&((this.velocity.y<0&&st.y<0||this.velocity.y>0&&st.y>0)&&(this.groundObject=d),this.pos.y=l.y,this.velocity.y*=-y,this.velocity.x*=x),vt&&Ee(this.pos,this.size,"#f00")}}}destroy(){let e=this.emitter.particleDestroyCallback,n=this.colorEnd;this.color.set(n.r,n.g,n.b,n.a),this.size.set(this.sizeEnd,this.sizeEnd),this.destroyed=!0,e==null||e(this)}render(){let e=this.emitter,n=e.localSpace,s=e.additive,i=e.trailScale,r=e.fadeRate/2,a=this.lifeTime>0?fe((dt-this.spawnTime)/this.lifeTime,1):1,o=1-a,c=o*this.sizeStart+a*this.sizeEnd,l=v(c),u=a1-r?(1-a)/r:1;this.color.r=o*this.colorStart.r+a*this.colorEnd.r,this.color.g=o*this.colorStart.g+a*this.colorEnd.g,this.color.b=o*this.colorStart.b+a*this.colorEnd.b,this.color.a=(o*this.colorStart.a+a*this.colorEnd.a)*u;let h=wh.set(this.pos.x,this.pos.y),d=this.angle;if(n){let f=e.angle,p=ve(-f),y=me(-f);h.set(e.pos.x+h.x*p-h.y*y,e.pos.y+h.x*y+h.y*p),d+=f}if(s&&js(),i){let f=n?this.velocity.rotate(e.angle):this.velocity,p=f.length();if(p){let y=p*i;l.y=ue(l.x,y),d=Hr(f.x,f.y),Ue(h,l,this.tileInfo,this.color,d,this.mirror)}}else Ue(h,l,this.tileInfo,this.color,d,this.mirror);s&&js(!1),Dn&&Ee(h,l,"#f005",0,d)}},Aa=!0,pr=!0,qi=5e5,Ca=11,Pl=Ca*4,Th=qi/Pl|0,po=3,Ml=po*4,cs=qi/Ml|0;Pn=!1,Wi=5,os=.5,Hi=v(640,80),Oa=!1,Xs={},wi=[];$i=class{constructor(e,n,s="",i="\u{1F3C6}",r){m(e>=0&&!Xs[e]),this.id=e,this.name=n,this.description=s,this.icon=i,this.unlocked=!1,this.image=void 0,r&&((this.image=new Image).src=r),Xs[e]=this}unlock(){Oa||this.unlocked||(m(Yi,"save name must be set"),this.unlocked=!0,Ia(),wi.push(this))}render(e=0){let n=we,s=fe(Hi.x,$.width),i=Hi.y,r=$.width-s,a=-i*e,o=qt(0,0,.9);n.save(),n.beginPath(),n.fillStyle=o.toString(),n.strokeStyle=ye.toString(),n.lineWidth=3,n.rect(r,a,s,i),n.fill(),n.stroke(),n.clip();let c=v(.1,.05).scale(i),l=i-2*c.x;this.renderIcon(v(r+c.x+l/2,a+i/2),l);let u=i*.5,h=i*.3,d=v(r+l+2*c.x,a+c.y*2+u/2),f=s-l-3*c.x;gn(this.name,d,u,ye,0,void 0,"left",void 0,void 0,f),d.y=a+i-c.y*2-h/2,gn(this.description,d,h,ye,0,void 0,"left",void 0,void 0,f),n.restore()}renderIcon(e,n){this.image?we.drawImage(this.image,e.x-n/2,e.y-n/2,n,n):gn(this.icon,e,n*.7,ye)}};gr=class extends $i{constructor(e,n,s,i,r){super(e,n,s,i,r)}unlock(){super.unlock(),Ks&&Ks.unlockMedal(this.id)}},br=class{constructor(e,n,s){var c,l,u;m(!Ks,"there can only be one newgrounds object"),m(!n||s,"must provide cryptojs if there is a cipher"),Ks=this,this.app_id=e,this.cipher=n,this.cryptoJS=s,this.host=location?location.hostname:"";let i=new URL(location.href);if(this.session_id=i.searchParams.get("ngio_session_id"),!this.session_id)return;let r=this.call("Medal.getList");if(!r||!r.result||r.result.error){Pn&&Pe("Newgrounds session unavailable; skipping plugin init"),this.medals=[],this.scoreboards=[];return}this.medals=((c=r.result.data)==null?void 0:c.medals)||[],Pn&&Pe(this.medals);for(let h of this.medals){let d=Xs[h.id];d&&(d.image=new Image,d.image.src=h.icon,d.name=h.name,d.description=h.description,d.unlocked=h.unlocked,d.difficulty=h.difficulty,d.value=h.value,d.value&&(d.description=d.description+` (${d.value})`))}let a=this.call("ScoreBoard.getBoards");this.scoreboards=((u=(l=a==null?void 0:a.result)==null?void 0:l.data)==null?void 0:u.scoreboards)||[],Pn&&Pe(this.scoreboards);let o=60*1e3;setInterval(()=>this.call("Gateway.ping",0,!0),o)}unlockMedal(e){return this.call("Medal.unlock",{id:e},!0)}postScore(e,n){return this.call("ScoreBoard.postScore",{id:e,value:n},!0)}getScores(e,n,s=0,i=0,r=10){return this.call("ScoreBoard.getScores",{id:e,user:n,social:s,skip:i,limit:r})}logView(){return this.call("App.logView",{host:this.host},!0)}call(e,n,s=!1){let i={component:e,parameters:n};if(this.cipher){let l=this.cryptoJS,u=l.enc.Base64.parse(this.cipher),h=l.lib.WordArray.random(16),d=l.AES.encrypt(JSON.stringify(i),u,{iv:h});i.secure=l.enc.Base64.stringify(h.concat(d.ciphertext)),i.parameters=0}let r={app_id:this.app_id,session_id:this.session_id,call:i},a=new FormData;a.append("input",JSON.stringify(r));let o=new XMLHttpRequest;o.open("POST","https://newgrounds.io/gateway_v3.php",!Pn&&s);try{o.send(a)}catch(l){Pn&&Pe("newgrounds call failed",l);return}return Pn&&Pe(o.responseText),o.responseText&&JSON.parse(o.responseText)}},xr=class{constructor(e,n=!1,s=!1){m(!qe,"Post process already initialized"),m(!(n&&s),"Post process cannot both include main canvas and use feedback texture"),qe=this,e||(e="void mainImage(out vec4 c,vec2 p){c=texture(iChannel0,p/iResolution.xy);}"),this.shader=void 0,this.texture=void 0,this.vao=void 0,i(),zn(void 0,o,r,a);function i(){if(K)return;if(!H){console.warn("PostProcessPlugin: WebGL not enabled!");return}qe.texture=mo(),qe.shader=ms(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D iChannel0;uniform vec3 iResolution;uniform float iTime;out vec4 c;
+`+e+`
+void main(){mainImage(c,gl_FragCoord.xy);c.a=1.;}`),qe.vao=g.createVertexArray(),g.bindVertexArray(qe.vao),g.bindBuffer(g.ARRAY_BUFFER,as);let c=8,l=g.getAttribLocation(qe.shader,"p");g.enableVertexAttribArray(l),g.vertexAttribPointer(l,2,g.FLOAT,!1,c,0)}function r(){qe.shader=void 0,qe.texture=void 0,Pe("PostProcessPlugin: WebGL context lost")}function a(){i(),Pe("PostProcessPlugin: WebGL context restored")}function o(){if(K||!H)return;Je(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.useProgram(qe.shader),g.bindVertexArray(qe.vao),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!0),g.disable(g.BLEND),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,qe.texture),n?($t.width=z.x,$t.height=z.y,Pa(fn),fn.drawImage($,0,0),$.width|=0,g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,$t)):s||g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,he);let c=l=>g.getUniformLocation(qe.shader,l);g.uniform1i(c("iChannel0"),0),g.uniform1f(c("iTime"),dt),g.uniform3f(c("iResolution"),$.width,$.height,1),g.drawArrays(g.TRIANGLE_STRIP,0,4),s&&g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,he),g.pixelStorei(g.UNPACK_FLIP_Y_WEBGL,!1),Ys(!0)}}},Sr=class{constructor(e,n){m(!ie,"LightSystemPlugin already initialized"),m(!qe,"LightSystemPlugin must be created before PostProcessPlugin"),ie=this,this.enabled=!0,this.ambientColor=(n||ye).copy(),this.textureSize=e?e.copy():void 0,this.texture=void 0,this.lightShader=void 0,this.compositeShader=void 0,this.lightVAO=void 0,this.compositeVAO=void 0,s(),zn(void 0,i,r,a);function s(){if(K)return;if(!H){console.warn("LightSystemPlugin: WebGL not enabled!");return}ie.textureSize||(ie.textureSize=z.copy()),ie.texture=g.createTexture(),g.bindTexture(g.TEXTURE_2D,ie.texture),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,ie.textureSize.x,ie.textureSize.y,0,g.RGBA,g.UNSIGNED_BYTE,null),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_S,g.CLAMP_TO_EDGE),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_WRAP_T,g.CLAMP_TO_EDGE),ie.lightShader=ms(`#version 300 es
+precision highp float;uniform mat4 m;uniform vec2 lightPos;uniform float radius;in vec2 g;out vec2 vWorldPos;void main(){vec2 worldP=lightPos+(g-.5)*2.*radius;gl_Position=m*vec4(worldP,1,1);vWorldPos=worldP;}`,`#version 300 es
+precision highp float;uniform vec2 lightPos;uniform float radius;uniform float fadeRange;uniform vec4 color;in vec2 vWorldPos;out vec4 c;void main(){float dist=distance(vWorldPos,lightPos);float t=clamp((radius-dist)/max(fadeRange,1e-6),0.,1.);c=vec4(color.rgb*t*color.a,1.);}`),ie.compositeShader=ms(`#version 300 es
+precision highp float;in vec2 p;void main(){gl_Position=vec4(p+p-1.,1,1);}`,`#version 300 es
+precision highp float;uniform sampler2D s;uniform vec3 iResolution;out vec4 c;void main(){vec2 uv=gl_FragCoord.xy/iResolution.xy;c=vec4(texture(s,uv).rgb,1.);}`),ie.lightVAO=g.createVertexArray(),g.bindVertexArray(ie.lightVAO),g.bindBuffer(g.ARRAY_BUFFER,as);let o=g.getAttribLocation(ie.lightShader,"g");g.enableVertexAttribArray(o),g.vertexAttribPointer(o,2,g.FLOAT,!1,8,0),ie.compositeVAO=g.createVertexArray(),g.bindVertexArray(ie.compositeVAO),g.bindBuffer(g.ARRAY_BUFFER,as);let c=g.getAttribLocation(ie.compositeShader,"p");g.enableVertexAttribArray(c),g.vertexAttribPointer(c,2,g.FLOAT,!1,8,0)}function i(){if(K||!H||!ie.enabled||!ie.texture)return;Je();let o=Hn,c=ie.ambientColor;g.bindFramebuffer(g.FRAMEBUFFER,ka),g.framebufferTexture2D(g.FRAMEBUFFER,g.COLOR_ATTACHMENT0,g.TEXTURE_2D,ie.texture,0),g.viewport(0,0,ie.textureSize.x,ie.textureSize.y),g.clearColor(c.r,c.g,c.b,c.a),g.clear(g.COLOR_BUFFER_BIT),js(),g.enable(g.BLEND),g.blendFunc(g.ONE,g.ONE);for(let u of Me)u.destroyed||u.renderLight();Je(),g.bindFramebuffer(g.FRAMEBUFFER,null),g.viewport(0,0,z.x,z.y),g.useProgram(ie.compositeShader),g.bindVertexArray(ie.compositeVAO),g.activeTexture(g.TEXTURE0),g.bindTexture(g.TEXTURE_2D,ie.texture);let l=ie.compositeShader;g.uniform1i(g.getUniformLocation(l,"s"),0),g.uniform3f(g.getUniformLocation(l,"iResolution"),$.width,$.height,1),g.blendFunc(g.DST_COLOR,g.ZERO),g.drawArrays(g.TRIANGLE_STRIP,0,4),ft&&g.bindTexture(g.TEXTURE_2D,ft),js(o),Ys(!0)}function r(){ie.texture=void 0,ie.lightShader=void 0,ie.compositeShader=void 0,ie.lightVAO=void 0,ie.compositeVAO=void 0,Pe("LightSystemPlugin: WebGL context lost")}function a(){s(),Pe("LightSystemPlugin: WebGL context restored")}}drawLight(e){if(K||!H||!this.lightShader)return;Je(),g.useProgram(this.lightShader),g.bindVertexArray(this.lightVAO);let n=v(2*oe).divide(z),s=je.rotate(-de),i=v(-1).subtract(s.multiply(n)),r=ve(de),a=me(de),o=[n.x*r,n.y*a,0,0,-n.x*a,n.y*r,0,0,1,1,1,0,i.x,i.y,0,1],c=this.lightShader;g.uniformMatrix4fv(g.getUniformLocation(c,"m"),!1,o),g.uniform2f(g.getUniformLocation(c,"lightPos"),e.pos.x,e.pos.y),g.uniform1f(g.getUniformLocation(c,"radius"),e.radius),g.uniform1f(g.getUniformLocation(c,"fadeRange"),e.fadeRange);let l=e.color;g.uniform4f(g.getUniformLocation(c,"color"),l.r,l.g,l.b,l.a),g.drawArrays(g.TRIANGLE_STRIP,0,4),Ys(!0)}},vr=class extends Qt{constructor(e,n,s,i){super(e,v(1),void 0,0,s),m(I(n)&&n>=0,"Light radius must be a non-negative number"),m(i===void 0||I(i)&&i>=0,"Light fadeRange must be a non-negative number when provided"),this.radius=n,this.fadeRange=i===void 0?n:i}render(){}renderLight(){ie&&ie.drawLight(this)}},wr=class extends Vs{constructor(e){super(void 0),!(!rt||K)&&(this.randomness=0,this.sampleChannels=Bl(...e),this.sampleRate=xs)}playMusic(e=1,n=!0){return super.play(void 0,e,1,0,n)}};Da=0;Tr=class{constructor(e=we){m(!P,"UI system already initialized"),P=this,this.activateOnPress=!1,this.defaultColor=te,this.defaultLineColor=ye,this.defaultTextColor=ye,this.defaultButtonColor=qt(0,0,.7),this.defaultHoverColor=qt(0,0,.9),this.defaultDisabledColor=qt(0,0,.3),this.defaultGradientColor=void 0,this.defaultLineWidth=4,this.defaultCornerRadius=0,this.defaultTextFitScale=.8,this.defaultFont=ei,this.defaultSoundPress=void 0,this.defaultSoundRelease=void 0,this.defaultSoundClick=void 0,this.defaultShadowColor=kt,this.defaultShadowBlur=5,this.defaultShadowOffset=v(5),this.nativeHeight=0,this.navigationObject=void 0,this.navigationTimer=new Dt(void 0,!0),this.navigationDelay=.2,this.navigationDirection=1,this.navigationMode=!1,this.uiObjects=[],this.uiContext=e,this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.confirmDialog=void 0,this._keyInputObject=void 0,this._onKeyDown=r=>{var a;return(a=this._keyInputObject)==null?void 0:a.onKeyDown(r)},zn(s,i);function n(r){let a,o;r.parent?(a=r.parent.nativePos,o=r.parent.size):(a=P.screenToNative(z.scale(.5)),o=P.nativeHeight?v(z.x*P.nativeHeight/z.y,P.nativeHeight):z);let c=r.anchor;r.nativePos=a.add(o.multiply(c).scale(.5)).subtract(r.size.multiply(c).scale(.5)).add(r.localPos)}function s(){P.activeObject&&!P.activeObject.visible&&(P.activeObject=void 0),P.lastHoverObject=P.hoverObject,P.hoverObject=void 0,Js(0)&&(P.navigationMode=!1,P.navigationObject=void 0),P.keyInputObject&&(P.activeObject=P.keyInputObject,P.hoverObject=P.keyInputObject,P.navigationMode=!1,P.navigationObject=void 0);let r=P.getNavigableObjects();if(!r.length)P.navigationObject=void 0;else if(!P.keyInputObject){if(r.includes(P.navigationObject)||(P.navigationObject=void 0),yt||P.navigationMode&&!P.navigationObject&&(P.navigationObject=r.find(o=>o.navigationAutoSelect)),!P.navigationTimer.active()){let o=pt(P.getNavigationDirection());if(o){let c;if(P.navigationObject){let l=r.indexOf(P.navigationObject),u=mt(l+o,r.length);c=r[u]}else if(c=r.find(l=>l.navigationAutoSelect),!c){let l=o>0?0:r.length-1;c=r[l]}P.navigationObject!==c&&(P.navigationMode=!0,P.hoverObject=void 0,P.navigationObject=c,P.navigationTimer.set(P.navigationDelay),c.soundPress&&c.soundPress.play())}}P.navigationObject&&P.getNavigationWasPressed()&&P.navigationObject.navigatePressed()}for(let o=P.uiObjects.length;o--;){let c=P.uiObjects[o];c.parent||a(c)}P.uiObjects=P.uiObjects.filter(o=>!o.destroyed);function a(o){if(!(o.destroyed||!o.visible)){n(o);for(let c=o.children.length;c--;){let l=o.children[c];l&&a(l)}o.destroyed||o.update()}}}function i(){let r=P.uiContext;if(r.save(),P.nativeHeight){let o=z.y/P.nativeHeight;r.translate(-o*z.x/2,0),r.scale(o,o),r.translate(z.x/2/o,0)}function a(o){if(o.visible){n(o),o.render();for(let c of o.children)a(c)}}if(P.uiObjects.forEach(o=>o.parent||a(o)),Da>0){let o=function(c,l=!0){l&&(l=!!c.visible),n(c),c.renderDebug(l);for(let u of c.children)o(u,l)};P.uiObjects.forEach(c=>c.parent||o(c))}r.restore()}}drawRect(e,n,s=te,i=0,r=ye,a=0,o,c=ye,l=0,u=v()){m(D(e),"pos must be a vec2"),m(D(n),"size must be a vec2"),m(Z(s),"color must be a color"),m(I(i),"lineWidth must be a number"),m(Z(r),"lineColor must be a color"),m(I(a),"cornerRadius must be a number");let h=P.uiContext;if(o){let d=h.createLinearGradient(e.x,e.y-n.y/2,e.x,e.y+n.y/2),f=s.toString();d.addColorStop(0,f),d.addColorStop(.5,o.toString()),d.addColorStop(1,f),h.fillStyle=d}else h.fillStyle=s.toString();(l||u.x||u.y)&&c.a>0&&(h.shadowColor=c.toString(),h.shadowBlur=l,h.shadowOffsetX=u.x,h.shadowOffsetY=u.y),h.beginPath(),a&&h.roundRect?h.roundRect(e.x-n.x/2,e.y-n.y/2,n.x,n.y,a):h.rect(e.x-n.x/2,e.y-n.y/2,n.x,n.y),h.fill(),h.shadowColor="#0000",i&&r.a>0&&(h.strokeStyle=r.toString(),h.lineWidth=i,h.stroke())}drawLine(e,n,s=P.defaultLineWidth,i=P.defaultLineColor){m(D(e),"posA must be a vec2"),m(D(n),"posB must be a vec2"),m(I(s),"lineWidth must be a number"),m(Z(i),"lineColor must be a color");let r=P.uiContext;r.strokeStyle=i.toString(),r.lineWidth=s,r.beginPath(),r.lineTo(e.x,e.y),r.lineTo(n.x,n.y),r.stroke()}drawTile(e,n,s,i=P.defaultColor,r=0,a=!1,o=ye,c=0,l=v()){let u=P.uiContext;(c||l.x||l.y)&&o.a>0&&(u.shadowColor=o.toString(),u.shadowBlur=c,u.shadowOffsetX=l.x,u.shadowOffsetY=l.y),Ue(e,n,s,i,r,a,kt,!1,!0,u),u.shadowColor="#0000"}drawText(e,n,s,i=P.defaultColor,r=P.defaultLineWidth,a=P.defaultLineColor,o="center",c=P.defaultFont,l="",u=!0,h=void 0,d=ye,f=0,p=v()){let y=P.uiContext;d.a>0&&(h&&gn(e,n.add(h),s.y,d,r,a,o,c,l,u?s.x:void 0,0,y),(f||p.x||p.y)&&(y.shadowColor=d.toString(),y.shadowBlur=f,y.shadowOffsetX=p.x,y.shadowOffsetY=p.y)),gn(e,n,s.y,i,r,a,o,c,l,u?s.x:void 0,0,y),y.shadowColor="#0000"}setupDragAndDrop(e,n,s,i){if(this._dragListeners)for(let[a,o]of this._dragListeners)document.removeEventListener(a,o);this._dragListeners=[];let r=(a,o)=>{let c=l=>{l.preventDefault(),a&&a(l)};document.addEventListener(o,c),this._dragListeners.push([o,c])};r(e,"drop"),r(n,"dragenter"),r(s,"dragleave"),r(i,"dragover")}screenToNative(e){if(!P.nativeHeight)return e;let n=z.y/P.nativeHeight,s=1/n,i=e.copy();return i.x+=n*z.x/2,i.x*=s,i.y*=s,i.x-=s*z.x/2,i}get keyInputObject(){return this._keyInputObject}set keyInputObject(e){let n=!!this._keyInputObject;this._keyInputObject=e,!n&&e?document.addEventListener("keydown",this._onKeyDown):n&&!e&&document.removeEventListener("keydown",this._onKeyDown)}destroyObjects(){for(let e of this.uiObjects)e.parent||e.destroy();this.uiObjects=this.uiObjects.filter(e=>!e.destroyed),this.activeObject=void 0,this.hoverObject=void 0,this.lastHoverObject=void 0,this.keyInputObject=void 0}getNavigableObjects(){function e(s){if(!(!s.visible||s.disabled)){s.isInteractive()&&s.navigationIndex!==void 0&&n.push(s);for(let i=s.children.length;i--;)e(s.children[i])}}let n=[];for(let s=P.uiObjects.length;s--;){let i=P.uiObjects[s];P.confirmDialog&&i!==P.confirmDialog||i.parent||e(i)}return n.sort((s,i)=>s.navigationIndex-i.navigationIndex),n}getNavigationDirection(){let e=P.navigationDirection===1,n=P.navigationDirection===2;if(rs){let l=Ns(0,_e),u=cr(_e);return n?-(l.y||u.y)||l.x||u.x:e?-(l.y||u.y):l.x||u.x}let s="ArrowUp",i="ArrowDown",r="ArrowLeft",a="ArrowRight";if(n)return ze(s)||ze(r)?-1:ze(i)||ze(a)?1:0;let o=e?s:r,c=e?i:a;return ze(o)?-1:ze(c)?1:0}getNavigationOtherDirection(){if(P.navigationDirection===2)return 0;let e=P.navigationDirection===1;if(rs){let i=Ns(0,_e),r=cr(_e);return e?i.x||r.x:i.y||r.y}let n=e?"ArrowLeft":"ArrowUp",s=e?"ArrowRight":"ArrowDown";return ze(n)?-1:ze(s)?1:0}getNavigationWasPressed(){return rs?ba(0,_e):We("Space")||We("Enter")}showConfirmDialog(e="Are you sure?",n,s,i=v(500,250),r="Escape"){m(!P.confirmDialog);let a=P.navigationDirection;P.navigationDirection=2;let o=new bt(v(),i);P.confirmDialog=o,o.onRender=()=>{let f=qt(0,0,0,.7);P.drawRect(v(),v(1e9),f)},o.onUpdate=()=>{We(r)&&d()},o.isMouseOverlapping=()=>!0;let c=50,l=new Xi(v(0,-50),v(i.x-c,70),e);o.addChild(l);let u=new Qs(v(-80,50),v(120,70),"Yes");u.textHeight=40,u.navigationIndex=1,u.hoverColor=qt(0,1,.5),u.onClick=()=>{d(),n&&n()},o.addChild(u);let h=new Qs(v(80,50),v(120,70),"No");h.textHeight=40,h.navigationIndex=2,h.navigationAutoSelect=!0,h.onClick=()=>{d(),s&&s()},o.addChild(h);function d(){m(P.confirmDialog===o),o.destroy(),P.confirmDialog=void 0,P.navigationDirection=a,ai()}}},bt=class{constructor(e=v(),n=v()){var s,i;m(D(e),"ui object pos must be a vec2"),m(D(n),"ui object size must be a vec2"),this.localPos=e.copy(),this.nativePos=e.copy(),this.size=n.copy(),this.color=P.defaultColor.copy(),this.activeColor=void 0,this.text=void 0,this.disabledColor=P.defaultDisabledColor.copy(),this.disabled=!1,this.textColor=P.defaultTextColor.copy(),this.hoverColor=P.defaultHoverColor.copy(),this.lineColor=P.defaultLineColor.copy(),this.gradientColor=P.defaultGradientColor?P.defaultGradientColor.copy():void 0,this.lineWidth=P.defaultLineWidth,this.cornerRadius=P.defaultCornerRadius,this.font=P.defaultFont,this.fontStyle=void 0,this.textWidth=void 0,this.textHeight=void 0,this.textFitScale=P.defaultTextFitScale,this.textShadow=void 0,this.textLineColor=P.defaultLineColor.copy(),this.textLineWidth=0,this.visible=!0,this.children=[],this.parent=void 0,this.extraTouchSize=0,this.soundPress=P.defaultSoundPress,this.soundRelease=P.defaultSoundRelease,this.soundClick=P.defaultSoundClick,this.interactive=!1,this.dragActivate=!1,this.canBeHover=!0,this.shadowColor=(s=P.defaultShadowColor)==null?void 0:s.copy(),this.shadowBlur=P.defaultShadowBlur,this.shadowOffset=(i=P.defaultShadowOffset)==null?void 0:i.copy(),this.navigationIndex=void 0,this.navigationAutoSelect=!1,this.anchor=v(),P.uiObjects.push(this)}addChild(e){return m(!e.parent&&!this.children.includes(e)),this.children.push(e),e.parent=this,e}removeChild(e){m(e.parent===this&&this.children.includes(e)),this.children.splice(this.children.indexOf(e),1),e.parent=void 0}destroy(){var e;if(!this.destroyed){P.activeObject===this&&(P.activeObject=void 0),P.hoverObject===this&&(P.hoverObject=void 0),P.lastHoverObject===this&&(P.lastHoverObject=void 0),P.navigationObject===this&&(P.navigationObject=void 0),P.keyInputObject===this&&(P.keyInputObject=void 0),this.destroyed=1,(e=this.parent)==null||e.removeChild(this);for(let n of this.children)n.parent=void 0,n.destroy();this.children.length=0}}isMouseOverlapping(){if(!Di)return!1;let e=yt?this.size.add(v(this.extraTouchSize||0)):this.size,n=P.screenToNative(tt);return Ei(this.nativePos,e,n)}update(){if(this.onUpdate(),this.disabled&&(this===P.activeObject&&(P.activeObject=void 0),this===P.keyInputObject&&(P.keyInputObject=void 0)),P.keyInputObject)return;let e=P.lastHoverObject===this,n=this.isActiveObject(),s=Is(0),i=this.dragActivate?s:Js(0);this.canBeHover&&(P.navigationMode||(i||n||!s&&!yt)&&!P.hoverObject&&this.isMouseOverlapping()&&(P.hoverObject=this)),this.isHoverObject()&&(this.disabled||(i&&this.interactive&&((!this.dragActivate||!e||Js(0))&&this.onPress(),this.soundPress&&this.soundPress.play(),P.activeObject&&!n&&P.activeObject.onRelease(),P.activeObject=this,P.activateOnPress&&this.click(!this.soundPress)),P.activateOnPress||!s&&this.isActiveObject()&&this.interactive&&this.click()),i&&ya(0,0,0,1,0)),n&&(!s||this.dragActivate&&!this.isHoverObject())&&(this.onRelease(),this.soundRelease&&this.soundRelease.play(),P.activeObject=void 0),this.isHoverObject()!==e&&(this.isHoverObject()?this.onEnter():this.onLeave())}render(){if(this.onRender(),!this.size.x||!this.size.y)return;let e=this.isNavigationObject(),n=e?this.color:this.interactive&&this.isActiveObject()&&!this.disabled?this.color:this.lineColor,s=e?this.hoverColor:this.disabled?this.disabledColor:this.interactive?this.isActiveObject()?this.activeColor||this.hoverColor:this.isHoverObject()?this.hoverColor:this.color:this.color,i=this.lineWidth*(e?1.5:1);P.drawRect(this.nativePos,this.size,s,i,n,this.cornerRadius,this.gradientColor,this.shadowColor,this.shadowBlur,this.shadowOffset)}getTextSize(){return v(this.textWidth||this.textFitScale*this.size.x,this.textHeight||this.textFitScale*this.size.y)}navigatePressed(){this.click()}isHoverObject(){return P.hoverObject===this}isActiveObject(){return P.activeObject===this}isNavigationObject(){return P.navigationObject===this}isKeyInputObject(){return P.keyInputObject===this}isInteractive(){return this.interactive&&this.visible&&!this.disabled}toString(){let e="type = "+this.constructor.name;return this.text&&(e+=`
+text = `+this.text),(this.nativePos.x||this.nativePos.y)&&(e+=`
+nativePos = `+this.nativePos),(this.localPos.x||this.localPos.y)&&(e+=`
+localPos = `+this.localPos),(this.size.x||this.size.y)&&(e+=`
+size = `+this.size),this.color&&(e+=`
+color = `+this.color),e}renderDebug(e=!0){let n=e?this.isHoverObject()?ll:this.disabled?fl:this.interactive?Xr:dl:ul;P.drawRect(this.nativePos,this.size,kt,4,n)}click(e=!0){this.onClick(),e&&this.soundClick&&this.soundClick.play()}onUpdate(){}onRender(){}onEnter(){}onLeave(){}onPress(){}onRelease(){}onClick(){}onChange(){}},Xi=class extends bt{constructor(e,n,s="",i="center",r=P.defaultFont){super(e,n),m(ee(s),"ui text must be a string"),m(["left","center","right"].includes(i),"ui text align must be left, center, or right"),m(ee(r),"ui text font must be a string"),this.text=s,this.align=i,this.font=r,this.canBeHover=!1,this.color=kt,this.shadowColor=kt,this.gradientColor=void 0,this.lineWidth=0,this.textFitScale=1}render(){super.render();let e=this.getTextSize();P.drawText(this.text,this.nativePos,e,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow,this.shadowColor,this.shadowBlur,this.shadowOffset)}},Ar=class extends bt{constructor(e,n,s=""){super(e,n),m(ee(s),"ui text must be a string"),this.maxLength=0,this.text=s,this.interactive=!0,this.canBeHover=!0}click(){P.keyInputObject=this,this.onClick()}stopEditing(){this.isKeyInputObject()&&(this.soundRelease&&this.soundRelease.play(),P.activeObject=void 0,P.keyInputObject=void 0,this.onChange())}onKeyDown(e){let n=e.code,s=e.key;n==="Backspace"?this.text=this.text.slice(0,-1):n==="Enter"||n==="Escape"?this.stopEditing():s.length===1&&(!this.maxLength||this.text.lengththis.size.y,s=n?this.size.y:this.size.x,i=n?this.size.x:this.size.y,r=n?this.nativePos.x:this.nativePos.y,a=i-s,o=r-a/2,c=r+a/2,l=P.screenToNative(tt);this.value=n?$e(l.x,o,c):$e(l.y,c,o)}else if(this.isNavigationObject()){let n=P.getNavigationOtherDirection();P.navigationTimer.active()||(this.value=X(this.value+n*.01))}this.value===e||this.onChange()}render(){super.render();let e=this.size.x>this.size.y,n=e?this.size.x:this.size.y,s=e?this.size.y:this.size.x;if(this.fillMode){let r=fe(s,this.cornerRadius*2),a=it(r,n,this.value),o=(a-n)*(e?.5:-.5),c=this.nativePos.add(e?v(o,0):v(0,o)),l=this.disabled?this.disabledColor:this.handleColor,u=e?v(a,this.size.y):v(this.size.x,a);P.drawRect(c,u,l,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}else{let r=X(e?this.value:1-this.value),a=(n-s)*(r-.5),o=this.nativePos.add(e?v(a,0):v(0,a)),c=this.disabled?this.disabledColor:this.handleColor,l=v(s);P.drawRect(o,l,c,this.lineWidth,this.lineColor,this.cornerRadius,this.gradientColor)}let i=this.getTextSize();P.drawText(this.text,this.nativePos,i,this.textColor,this.textLineWidth,this.textLineColor,this.align,this.font,this.fontStyle,!0,this.textShadow)}navigatePressed(){this.value=this.value?0:1,this.onChange(),this.onRelease(),super.navigatePressed()}},Er=class extends bt{constructor(e,n,s,i=!1,r=!1,a=1){super(e,n||v()),m(ee(s),"video src must be a string"),m(I(a),"video volume must be a number"),this.color=ye,this.cornerRadius=0,this.volume=a,this.video=document.createElement("video"),this.video.loop=r,this.video.volume=X(a*Gn),this.video.muted=!rt,this.video.style.display="none",this.video.src=s,document.body.appendChild(this.video),i&&this.play()}async play(){try{await this.video.play()}catch{}}pause(){this.video.pause()}stop(){this.video.pause(),this.video.currentTime=0}isLoading(){return this.video.readyState=1,"ui layout columns must be a number >= 1"),m(I(s),"ui layout gap must be a number"),m(I(i),"ui layout padding must be a number"),this.columns=n,this.gap=s,this.padding=i,r&&(this.color=kt,this.gradientColor=void 0,this.lineWidth=0,this.shadowColor=kt),this.relayout()}addChild(e){return super.addChild(e),this.relayout(),e}removeChild(e){super.removeChild(e),this.relayout()}relayout(){let e=this.children.length;if(!e){this.size=v(this.padding*2);return}let n=this.columns,s=Fs(e/n),i=new Array(n).fill(0),r=new Array(s).fill(0);for(let d=0;d=0&&b.objects.splice(e,1),super.destroy()}updatePhysics(){}render(){this.tileInfo?super.render():this.drawFixtures(this.color,this.lineColor,this.lineWidth)}renderDebugInfo(){let e=!this.getIsAwake(),n=this.getBodyType()===b.bodyTypeStatic,s=Q(e?1:0,e?1:0,n?1:0,.5);this.drawFixtures(s)}drawFixtures(e=te,n=ye,s=.1,i,r){this.getFixtureList().forEach(a=>{b.castShapeObject(a.GetShape()).GetType()!==b.instance.b2Shape.e_edge&&b.drawFixture(a,this.pos,this.angle,e,n,s,i,r)}),this.edgeLists.forEach(a=>ar(a,s,n,!1,this.pos,this.angle)),this.edgeLoops.forEach(a=>ar(a,s,n,!0,this.pos,this.angle))}beginContact(e){}endContact(e){}addShape(e,n=1,s=.2,i=0,r=!1){m(I(n),"density must be a number"),m(I(s),"friction must be a number"),m(I(i),"restitution must be a number");let a=new b.instance.b2FixtureDef;return a.set_shape(e),a.set_density(n),a.set_friction(s),a.set_restitution(i),a.set_isSensor(r),this.body.CreateFixture(a)}addBox(e=v(1),n=v(),s=0,i,r,a,o){m(D(e),"size must be a Vector2"),m(e.x>0&&e.y>0,"size must be positive"),m(D(n),"offset must be a Vector2"),m(I(s),"angle must be a number");let c=new b.instance.b2PolygonShape;return c.SetAsBox(e.x/2,e.y/2,b.vec2dTo(n),-s),this.addShape(c,i,r,a,o)}addPoly(e,n,s,i,r){m(Tt(e),"points must be an array");function a(c){m(3<=c.length&&c.length<=8);let l=b.instance._malloc(c.length*8);for(let d=0,f=0;d>2]=c[d].x,f+=4,b.instance.HEAPF32[l+f>>2]=c[d].y,f+=4;let u=b.instance.wrapPointer(l,b.instance.b2Vec2),h=new b.instance.b2PolygonShape;return h.Set(u,c.length),b.instance._free(l),h}let o=a(e);return this.addShape(o,n,s,i,r)}addRegularPoly(e=1,n=8,s,i,r,a){m(I(e)&&e>0,"diameter must be a positive number"),m(I(n)&&n>2,"sides must be a positive number greater than 2");let o=[],c=e/2;for(let l=n;l--;)o.push(v(c,0).rotate((l+.5)/n*re*2));return this.addPoly(o,s,i,r,a)}addRandomPoly(e=1,n,s,i,r){m(I(e)&&e>0,"diameter must be a positive number");let a=$r(3,9),o=[],c=e/2;for(let l=a;l--;)o.push(v(Ae(c/2,c*1.5),0).rotate(l/a*re*2));return this.addPoly(o,n,s,i,r)}addCircle(e=1,n=v(),s,i,r,a){m(I(e)&&e>0,"diameter must be a positive number"),m(D(n),"offset must be a Vector2");let o=new b.instance.b2CircleShape;return o.set_m_p(b.vec2dTo(n)),o.set_m_radius(e/2),this.addShape(o,s,i,r,a)}addEdge(e,n,s,i,r,a){m(D(e),"point1 must be a Vector2"),m(D(n),"point2 must be a Vector2");let o=new b.instance.b2EdgeShape;return o.Set(b.vec2dTo(e),b.vec2dTo(n)),this.addShape(o,s,i,r,a)}addEdgeList(e,n,s,i,r){m(Tt(e),"points must be an array");let a=[],o=[];for(let c=0;ce[mt(l,e.length)];for(let l=0;lthis.destroyFixture(e))}getCenterOfMass(){return b.vec2From(this.body.GetWorldCenter())}getLinearVelocity(){return b.vec2From(this.body.GetLinearVelocity())}getAngularVelocity(){return this.body.GetAngularVelocity()}getMass(){return this.body.GetMass()}getInertia(){return this.body.GetInertia()}getIsAwake(){return this.body.IsAwake()}getBodyType(){return this.body.GetType()}getSpeed(){return this.getLinearVelocity().length()}setTransform(e,n){this.pos=e,this.angle=n,this.body.SetTransform(b.vec2dTo(e),-n)}setPosition(e){this.setTransform(e,this.body.GetAngle())}setAngle(e){this.setTransform(b.vec2From(this.body.GetPosition()),e)}setLinearVelocity(e){this.body.SetLinearVelocity(b.vec2dTo(e))}setAngularVelocity(e){this.body.SetAngularVelocity(e)}setLinearDamping(e){this.body.SetLinearDamping(e)}setAngularDamping(e){this.body.SetAngularDamping(e)}setGravityScale(e=1){this.body.SetGravityScale(this.gravityScale=e)}setBullet(e=!0){this.body.SetBullet(e)}setAwake(e=!0){this.body.SetAwake(e)}setBodyType(e){this.body.SetType(e)}setSleepingAllowed(e=!0){this.body.SetSleepingAllowed(e)}setFixedRotation(e=!0){this.body.SetFixedRotation(e)}setCenterOfMass(e){this.setMassData(e)}setMass(e){this.setMassData(void 0,e)}setMomentOfInertia(e){this.setMassData(void 0,void 0,e)}resetMassData(){this.body.ResetMassData()}setMassData(e,n,s){let i=new b.instance.b2MassData;this.body.GetMassData(i),e!==void 0&&i.set_center(b.vec2dTo(e)),n!==void 0&&i.set_mass(n),s!==void 0&&i.set_I(s),this.body.SetMassData(i)}setFilterData(e=0,n=0,s=0){this.getFixtureList().forEach(i=>{let r=i.GetFilterData();r.set_categoryBits(e),r.set_maskBits(65535&~n),r.set_groupIndex(s)})}setSensor(e=!0){this.getFixtureList().forEach(n=>n.SetSensor(e))}applyForce(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyForce(b.vec2dTo(e),b.vec2dTo(n))}applyAcceleration(e,n){n||(n=this.getCenterOfMass()),this.setAwake();let s=e.scale(this.getMass());this.body.ApplyLinearImpulse(b.vec2dTo(s),b.vec2dTo(n))}applyImpulse(e,n){n||(n=this.getCenterOfMass()),this.setAwake(),this.body.ApplyLinearImpulse(b.vec2dTo(e),b.vec2dTo(n))}applyTorque(e){this.setAwake(),this.body.ApplyTorque(e)}applyAngularAcceleration(e){this.setAwake(),this.body.ApplyAngularImpulse(e*this.getInertia())}applyAngularImpulse(e){this.setAwake(),this.body.ApplyAngularImpulse(e)}hasFixtures(){return!b.isNull(this.body.GetFixtureList())}getFixtureList(){let e=[];for(let n=this.body.GetFixtureList();!b.isNull(n);)e.push(n),n=n.GetNext();return e}hasJoints(){return!b.isNull(this.body.GetJointList())}getJointList(){let e=[];for(let n=this.body.GetJointList();!b.isNull(n);)e.push(n),n=n.get_next();return e}},Ki=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeStatic;super(e,n,s,i,r,o,a)}},Mr=class extends Zs{constructor(e,n,s,i=0,r,a=0){let o=b.bodyTypeKinematic;super(e,n,s,i,r,o,a)}},Rr=class extends Ki{constructor(e){m(e instanceof Ws,"tileLayer must be a TileCollisionLayer"),super(e.pos,e.size),this.tileLayer=e,this.addChild(e)}render(){}buildCollision(e=.2,n=0){this.destroyAllFixtures(),this.pos=this.tileLayer.pos.copy(),this.size=this.tileLayer.size.copy();let s=[],i=(a,o)=>a+o*this.size.x,r=(a,o)=>!s[i(a,o)]&&this.tileLayer.getCollisionData(v(a,o))>0;for(let a=0;ai.fractionr.pos.distanceSquared(e)0,"Tween duration must be > 0"),this.callback=e,this.start=n,this.end=s,this.duration=i,this.life=i,this.ease=r.ease||no.LINEAR,this.useRealTime=!!r.useRealTime,this.paused=!!r.paused,this.thenCallback=void 0,this.loopRemaining=0,ut.push(this),e(this.interp(i))}setEase(e){return this.ease=e,this}then(e){return this.thenCallback=e,this.loopRemaining=0,this}loop(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>zl(this),this}pingPong(e=1/0){return this.loopRemaining=e,this.thenCallback=()=>Ul(this),this}pause(){this.paused=!0}resume(){this.paused=!1}restart(){this.life=this.duration,this.paused=!1,ut.indexOf(this)<0&&ut.push(this),this.callback(this.interp(this.duration))}isActive(){return!this.paused&&ut.indexOf(this)>=0}getPercent(){return $e(this.duration-this.life,0,this.duration)}getValue(){return this.interp(this.life)}interp(e){let n=this.ease((this.duration-e)/this.duration);return zc(this.start)?this.start.lerp(this.end,n):this.start+(this.end-this.start)*n}stop(){let e=ut.indexOf(this);e>=0&&ut.splice(e,1),this.thenCallback=void 0}},no={LINEAR:t=>t,POWER:t=>e=>e**t,SINE:t=>1-ve(t*(re/2)),CIRC:t=>1-(1-t*t)**.5,EXPO:t=>t===0?0:2**(10*t-10),BACK:t=>t*t*(2.70158*t-1.70158),ELASTIC:t=>t===0?0:t===1?1:-(2**(10*t-10))*me((37-40*t)*re/6),SPRING:t=>1-(me(re*(1-t)*(.2+2.5*(1-t)**3))*t**2.2+(1-t))*(1+1.2*t),BOUNCE:t=>{let e=1-t,n;return e<4/11?n=7.5625*e*e:e<8/11?n=7.5625*(e-=6/11)*e+.75:e<10/11?n=7.5625*(e-=9/11)*e+.9375:n=7.5625*(e-=10.5/11)*e+.984375,1-n},IN:t=>t,OUT:t=>e=>1-t(1-e),IN_OUT:t=>no.PIECEWISE(t,no.OUT(t)),PIECEWISE:(...t)=>{let e=t.length;return n=>{let s=n*e-1e-9>>0;return(t[s]((n-s/e)*e)+s)/e}},BEZIER:(t,e,n,s)=>{let i=r=>{let a=1-r,o=3*a*a*r,c=3*a*r*r,l=r**3;return[o*t+c*n+l,o*e+c*s+l]};return r=>{let a=0,o=1;for(let c=0;c<128;c++){let l=(a+o)/2,[u,h]=i(l);if(pe(u-r)<1e-5)return h;u=this.size.x||n>=this.size.y?null:this.nodes[e+n*this.size.x]}worldToTile(e){let n=this.tileLayer?this.tileLayer.pos.x:0,s=this.tileLayer?this.tileLayer.pos.y:0;return v(Ie(e.x-n),Ie(e.y-s))}tileToWorld(e,n){let s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;return v(e+.5+s,n+.5+i)}buildNodeData(){let e=this.size.x,n=this.size.y,s=this.tileLayer?this.tileLayer.pos.x:0,i=this.tileLayer?this.tileLayer.pos.y:0;for(let r=0;r0&&(c?l>0&&Ee(o.posWorld,er,Q(1,0,0,fe(.2,l*.05)),this.debugTime):Ee(o.posWorld,er,Q(1,0,0,.25),this.debugTime))}}aStarSearch(e,n){m(e&&n,"aStarSearch needs both endpoints"),m(e!==n,"aStarSearch: start and end must differ \u2014 caller should handle trivial case"),m(e.walkable&&n.walkable,"aStarSearch: endpoints must be walkable");let s=[e];e.isOpen=!0;let i=0;for(;s.length>0;){let r=0,a=s[0].f;for(let c=1;cthis.maxLoop)break;o.isOpen=!1,s.splice(r,1),o.isClosed=!0,this.debug&&this.debugTime>0&&Ee(o.posWorld,er,Q(1,1,1,.05),this.debugTime);for(let c=-1;c<=1;++c)for(let l=-1;l<=1;++l){if(l===0&&c===0)continue;let u=this.getNode(o.pos.x+l,o.pos.y+c);if(!u||!u.walkable||u.isClosed)continue;let h=1;if(l!==0&&c!==0){let x=this.getNode(o.pos.x+l,o.pos.y);if(!x||!x.walkable)continue;let w=this.getNode(o.pos.x,o.pos.y+c);if(!w||!w.walkable)continue;h=qh}let d=o.g+h+u.cost;if(!u.isOpen)u.isOpen=!0,s.push(u);else if(d>=u.g)continue;u.parent=o,u.g=d;let f=pe(n.pos.x-u.pos.x),p=pe(n.pos.y-u.pos.y),y=ue(f,p)+(Math.SQRT2-1)*fe(f,p);u.f=u.g+y*this.heuristicWeight}}return n.parent!==null}getNearestClearNode(e,n=10,s=!0){m(D(e),"worldPos must be a Vector2"),s&&this.buildNodeData();let i=this.tileLayer?this.tileLayer.pos.x:0,r=this.tileLayer?this.tileLayer.pos.y:0,a=Ie(e.x-i),o=Ie(e.y-r);for(let c=0;c<=n;++c){let l=null,u=0;for(let h=-c;h<=c;++h)for(let d=-c;d<=c;++d){if(c>0&&pe(d)!==c&&pe(h)!==c)continue;let f=this.getNode(a+d,o+h);if(!f||!f.isClear())continue;let p=f.posWorld.x-e.x,y=f.posWorld.y-e.y,x=p*p+y*y;(!l||x0&&nt(i.posWorld,.3,Q(.5,0,.5,.5),this.debugTime),e.splice(n,1),n=ue(1,n-1);continue}else if(c===2){this.debug&&this.debugTime>0&&nt(i.posWorld,.3,Q(1,0,0,.5),this.debugTime);let f,p;s.pos.y===i.pos.y&&r.pos.x===i.pos.x?(f=s.pos.x,p=r.pos.y):(f=r.pos.x,p=s.pos.y);let y=this.getNode(f,p);if(y&&y.isClear()){e.splice(n,1),n=ue(1,n-1);continue}}else if(c===5){this.debug&&this.debugTime>0&&nt(i.posWorld,.3,Q(1,1,0,.5),this.debugTime);let f=n>=2?e[n-2]:s,p,y,x,w;l===0||h===0?(p=r.pos.x,y=i.pos.y,x=s.pos.x,w=i.pos.y):(p=i.pos.x,y=r.pos.y,x=i.pos.x,w=s.pos.y);let A=p-f.pos.x,S=y-f.pos.y,_=x-f.pos.x,k=w-f.pos.y,C=A*A+S*S,O=_*_+k*k,q=C0&&nt(i.posWorld,.3,Q(0,1,0,.5),this.debugTime),l===h&&u===d){++n;continue}else{let f,p;s.pos.y===r.pos.y?(f=i.pos.x,p=s.pos.y):(f=s.pos.x,p=i.pos.y);let y=this.getNode(f,p);if(y&&y.isClear()){e[n]=y,n=ue(1,n-1);continue}}++n}}smoothPathStringPull(e){if(e.length<=2)return;for(let i of e)if(!i.isClear())return;let n=e.slice();e.length=0,e.push(n[0]);let s=0;for(let i=1;i0&&Lt(r.posWorld,e[e.length-1].posWorld,Q(0,0,1,.3),.02,this.debugTime);continue}for(;s=1;--n){let s=e[n-1],i=e[n],r=e[n+1];(i.pos.x-s.pos.x)*(r.pos.y-s.pos.y)===(i.pos.y-s.pos.y)*(r.pos.x-s.pos.x)&&e.splice(n,1)}}isNodeClear(e,n){let s=this.getNode(e,n);return s!==null&&s.isClear()}isLineClear(e,n){m(D(e)&&D(n),"isLineClear needs Vector2 endpoints"),m(this.isNodeClear(e.x,e.y)&&this.isNodeClear(n.x,n.y),"isLineClear endpoints must be in-bounds and clear");let s=n.x-e.x,i=n.y-e.y,r=pe(s),a=pe(i),o=pt(s),c=pt(i),l=e.x,u=e.y;if(a===r){for(;l!==n.x;){if(l!==e.x&&(!this.isNodeClear(l,u)||!this.isNodeClear(l,u-c))||!this.isNodeClear(l,u+c))return!1;l+=o,u+=c}if(!this.isNodeClear(n.x,n.y-c))return!1}else if(ao.posWorld.copy());if(this.debug&&this.debugTime>0&&a.length>0){for(let o=1;oWh,bootGameHost:()=>Yh,default:()=>Hh});var An=class{constructor(e){this._state=(e==null?2654435769:e)>>>0}next(){this._state=this._state+1831565813>>>0;let e=this._state;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}range(e,n){return e+this.next()*(n-e)}reseed(e){this._state=(e==null?2654435769:e)>>>0}},vo=class{constructor(e){this._clock=e||tu(),this._origin=this._clock()}nowMs(){return this._clock()}elapsedMs(){return this._clock()-this._origin}},wo=class{constructor(e){this._time=e,this._subs=new Map}sourceFor(e){let n=this,s=e==null?null:e;return{on(i,r){if(n._assertType(i),typeof r!="function")throw new Error("[HostDevInputBridge] on \u7684 handler \u5FC5\u987B\u662F\u51FD\u6570");let a=n._subs.get(i)||[],o={handler:r,scope:s};return a.push(o),n._subs.set(i,a),{cancel(){let c=n._subs.get(i);if(!c)return;let l=c.indexOf(o);l>=0&&c.splice(l,1)}}},off(i,r){n._assertType(i);let a=n._subs.get(i);if(!a)return;let o=a.findIndex(c=>c.handler===r&&c.scope===s);o>=0&&a.splice(o,1)}}}_emit(e,n){this._assertType(e);let s=n||{},i={type:e,x:typeof s.x=="number"?s.x:0,y:typeof s.y=="number"?s.y:0,key:typeof s.key=="string"?s.key:"",tMs:this._time.nowMs()},r=this._subs.get(e);if(!r||r.length===0)return;let a=r.slice();for(let o of a)try{o.handler(i)}catch(c){on("[host-dev input] \u8F93\u5165 handler \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09type="+e,c)}}disposeScope(e){if(e==null)return 0;let n=0;for(let[s,i]of this._subs){let r=i.filter(a=>a.scope!==e);n+=i.length-r.length,r.length===0?this._subs.delete(s):this._subs.set(s,r)}return n}_subscriptionCount(){let e=0;for(let n of this._subs.values())e+=n.length;return e}_assertType(e){if(!To.has(e))throw new Error("[HostDevInputBridge] \u975E\u6CD5\u8F93\u5165\u4E8B\u4EF6\u7C7B\u578B\uFF1A"+String(e)+"\uFF08\u4EC5\u652F\u6301 "+Array.from(To).join("/")+"\uFF09")}},To=new Set(["pointerdown","pointermove","pointerup","keydown","keyup"]);function ja(t){let e=t||{},n=new vo(e.clock),s=new An(e.seed),i=e.seed==null?2654435769:e.seed>>>0,r=new wo(n),a=typeof e.audioFactory=="function"?e.audioFactory:null,o=null,c=!1,l=typeof e.engineFactory=="function"?e.engineFactory:null,u=null,h=!1,d=new Map,f=0,p=0;function y(){if(o)return o;if(!a)return c||(ko("[host-dev audio] \u672A\u6CE8\u5165 audioFactory\uFF0CgetAudioContext \u8FD4\u56DE null\uFF08P6 \u987B\u5BB9\u9519\u964D\u7EA7\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u5DE5\u5382\uFF09"),c=!0),null;try{o=a()}catch(_){on("[host-dev audio] audioFactory \u629B\u9519\uFF0CgetAudioContext \u964D\u7EA7\u8FD4\u56DE null",_),o=null}return o}function x(){if(u)return u;if(!l)return h||(ko("[host-dev engine] \u672A\u6CE8\u5165 engineFactory\uFF0CgetEngine \u8FD4\u56DE null\uFF08\u63D2\u4EF6\u987B\u5BB9\u9519\u964D\u7EA7\uFF1A\u7C92\u5B50\u9000\u53D7\u63A7\u9762\u81EA\u7BA1/\u5408\u6210\u6838\u9000 vendored/\u6570\u5B66\u9000\u5185\u7F6E\uFF1B\u96C6\u6210\u6BB5\u6CE8\u5165\u771F\u5B9E\u80CC\u4E66\uFF09"),h=!0),null;try{u=l()}catch(_){on("[host-dev engine] engineFactory \u629B\u9519\uFF0CgetEngine \u964D\u7EA7\u8FD4\u56DE null",_),u=null}return u}function w(_,k){return{getContext2d(){return e.context2d==null?null:e.context2d},onFrame(O){let q=f++;return d.set(q,O),{cancel(){d.delete(q)}}},getInput(){return r.sourceFor(_)},getAudioContext(){return y()},getEngine(){return x()},time:n,random:k}}let A=w(null,s),S={context:A,tick(_){p+=1;let k=Array.from(d.values());for(let C of k)try{C(_,p)}catch(O){on("[host-dev tick] \u5E27\u56DE\u8C03\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09frame="+p,O)}},frameCount(){return p},inputBridge:r,deriveContextFor(_,k){let C=eu(i,_),O=new An(C);return w(k==null?_:k,O)}};return Object.defineProperty(A,Ao,{value:S,enumerable:!1,writable:!1,configurable:!1}),S}var Ao=Symbol("zaomeng.coreProtocol.contextBundle"),ui=class{constructor(){this._plugins=new Map,this._initOrder=[],this._initErrors=[],this._phase="idle",this._disposed=!1,this._context=void 0,this._pluginContexts=new Map}register(e){if(!e||typeof e!="object")throw new Error("[PluginRegistry] register \u9700\u8981\u4E00\u4E2A\u63D2\u4EF6\u5BF9\u8C61");if(typeof e.name!="string"||e.name.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6\u7F3A\u5C11\u5408\u6CD5 name");if(typeof e.version!="string"||e.version.length===0)throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11\u5408\u6CD5 version");if(typeof e.init!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7F3A\u5C11 init \u51FD\u6570");if(e.dispose!=null&&typeof e.dispose!="function")throw new Error("[PluginRegistry] \u63D2\u4EF6 "+e.name+" \u7684 dispose \u5FC5\u987B\u662F\u51FD\u6570\u6216\u7701\u7565");if(this._plugins.has(e.name))throw new Error("[PluginRegistry] \u63D2\u4EF6\u91CD\u540D\u62D2\u7EDD\uFF1A"+e.name+" \u5DF2\u6CE8\u518C");return this._plugins.set(e.name,e),this}has(e){return this._plugins.has(e)}get(e){return this._plugins.get(e)}list(){return Array.from(this._plugins.keys())}initAll(){if(this._phase==="initialized")return ko("[PluginRegistry] initAll \u91CD\u590D\u8C03\u7528\uFF0C\u5DF2\u5FFD\u7565\uFF08\u5DF2\u5904\u4E8E initialized\uFF09"),this._initResult();if(this._phase==="disposed")throw new Error("[PluginRegistry] \u5DF2 dispose \u7684\u6CE8\u518C\u5668\u4E0D\u53EF\u518D initAll");if(this._context==null)throw new Error("[PluginRegistry] \u672A\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\uFF1A\u8BF7\u5728 initAll() \u4E4B\u524D\u8C03\u7528 useContext(context)\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context); reg.initAll();\uFF09");for(let[e,n]of this._plugins){let s=this._missingDeps(n);if(s.length>0){let r=new Error("[PluginRegistry] \u63D2\u4EF6 "+e+" \u4F9D\u8D56\u7F3A\u5931\uFF1A"+s.join(", ")+"\uFF08\u672A\u6CE8\u518C\uFF09");this._initErrors.push({name:e,error:r}),on("[PluginRegistry] \u8DF3\u8FC7 init\uFF08\u4F9D\u8D56\u7F3A\u5931\uFF0C\u5DF2\u9694\u79BB\uFF09\uFF1A"+e,r);continue}let i=this._contextFor(e);try{n.init(i),this._initOrder.push(e)}catch(r){let a=r instanceof Error?r:new Error(String(r));this._initErrors.push({name:e,error:a}),on("[PluginRegistry] \u63D2\u4EF6 init \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF0C\u4E0D\u8FDE\u5750\uFF09\uFF1A"+e,a)}}return this._phase="initialized",this._initResult()}_contextFor(e){let n=this._pluginContexts.get(e);if(n)return n;let s=this._context&&this._context[Ao],i;return s&&typeof s.deriveContextFor=="function"?i=s.deriveContextFor(e,e):i=this._context,this._pluginContexts.set(e,i),i}disposeAll(){if(this._disposed)return{disposed:[],errors:[]};let e=[],n=[],s=this._context&&this._context[Ao],i=s&&s.inputBridge;for(let r=this._initOrder.length-1;r>=0;r--){let a=this._initOrder[r],o=this._plugins.get(a);if(o&&typeof o.dispose=="function")try{o.dispose(),e.push(a)}catch(c){let l=c instanceof Error?c:new Error(String(c));n.push({name:a,error:l}),on("[PluginRegistry] \u63D2\u4EF6 dispose \u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,l)}if(i&&typeof i.disposeScope=="function")try{i.disposeScope(a)}catch(c){on("[PluginRegistry] \u56DE\u6536\u63D2\u4EF6\u8F93\u5165\u8BA2\u9605\u629B\u9519\uFF08\u5DF2\u9694\u79BB\uFF09\uFF1A"+a,c)}}return this._disposed=!0,this._phase="disposed",{disposed:e,errors:n}}useContext(e){if(this._phase!=="idle")throw new Error("[PluginRegistry] useContext \u5FC5\u987B\u5728 initAll() \u4E4B\u524D\u8C03\u7528\uFF08\u5F53\u524D\u9636\u6BB5\uFF1A"+this._phase+"\uFF09\u3002\u8BF7\u5728\u4EFB\u4F55 initAll/disposeAll \u4E4B\u524D\u6CE8\u5165\u53D7\u63A7\u4E0A\u4E0B\u6587\u3002");if(e==null||typeof e!="object")throw new Error("[PluginRegistry] useContext \u9700\u8981\u4E00\u4E2A\u53D7\u63A7\u4E0A\u4E0B\u6587\u5BF9\u8C61\u3002\uFF08host-dev \u7528\u6CD5\uFF1Aconst { context } = createHostDevContext(); reg.useContext(context);\uFF09");return this._context=e,this}_missingDeps(e){return!Array.isArray(e.dependencies)||e.dependencies.length===0?[]:e.dependencies.filter(n=>!this._plugins.has(n))}_initResult(){return{ok:this._initErrors.length===0,initialized:this._initOrder.slice(),errors:this._initErrors.slice()}}};function eu(t,e){let n=2166136261,s=16777619,i=t>>>0;for(let a=0;a<32;a+=8){let o=i>>>a&255;n^=o,n=Math.imul(n,s)>>>0}let r=String(e);for(let a=0;a>>0,n^=o>>>8&255,n=Math.imul(n,s)>>>0}return n>>>0}function tu(){if(typeof globalThis!="undefined"&&globalThis.performance&&typeof globalThis.performance.now=="function")return()=>globalThis.performance.now();if(typeof process!="undefined"&&process.hrtime&&typeof process.hrtime.bigint=="function"){let t=process.hrtime.bigint();return()=>Number(process.hrtime.bigint()-t)/1e6}return()=>Date.now()}function on(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function ko(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Kh=Object.freeze(Array.from(To)),Ja="core-protocol-v0";var Na=Object.freeze(["t_boot","t_plugins_ready","t_game_init","t_first_paint","t_input_bound","t_game_start"]),Co=Na.reduce((t,e,n)=>(t[e]=n,t),Object.create(null)),nu=new Set(Na);function _o(t){let e=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}var za=_o("runtime-probe::seed::v1");function di(t){return t===null||typeof t!="object"?JSON.stringify(t):Array.isArray(t)?"["+t.map(di).join(",")+"]":"{"+Object.keys(t).sort().map(n=>JSON.stringify(n)+":"+di(t[n])).join(",")+"}"}function Ua(t){let e=di(t.extra==null?null:t.extra),n=di(Array.isArray(t.pluginSet)?t.pluginSet:[]);return["seq="+t.seq,"anchor="+t.anchor,"tMono="+t.tMono,"buildSha="+(t.buildSha||""),"pluginSet="+n,"extra="+e].join("|")}function su(t){return Math.round(t*1e3)/1e3}function iu(t){if(!Array.isArray(t))return{ok:!1,reason:"records_not_array"};let e=za,n=-1;for(let s=0;stypeof _=="string").slice().sort():[],i=typeof e.sink=="function"?e.sink:null,r=e.autoBoot!==!1,a=typeof e.inputAnchorType=="string"?e.inputAnchorType:"pointerdown",o=()=>0,c=!1,l=0,u=za,h=[],d=new Set,f=-1,p=null,y=!1,x=!1,w=!1;function A(_,k){let C=null;if(!nu.has(_))C="unknown_anchor";else{d.has(_)&&(C=C?C+";duplicate_anchor":"duplicate_anchor");let q=Co[_];q_.time.nowMs(),c=!0,r&&!x&&A("t_boot",{auto:!0}),p=_.getInput().on(a,k=>{y||(y=!0,A("t_input_bound",{firstInput:!0,type:k.type}))}),A("t_input_bound",{stage:"registered",type:a})},dispose(){w||(p&&(p.cancel(),p=null),w=!0)},mark:A,getRecords(){return h.map(_=>({..._}))},toJSONL(){return h.map(_=>JSON.stringify(_)).join(`
+`)},verify(){return iu(h)}}}function ou(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function qa(t){let e=t.LJS,n=t.engineMath,s=t.engineMode,i=t.recHook||(()=>{});if(s!=="real")return null;let r=n;return{math:{lerp:(o,c,l)=>(i("math.lerp"),r.lerp(o,c,l)),smoothStep:o=>(i("math.smoothStep"),r.smoothStep(o)),easing:Object.fromEntries(Object.keys(r.easing).map(o=>[o,c=>(i("math.easing."+o),r.easing[o](c))]))},particles:{spawnEmitter(o){i("particles.spawnEmitter");let c=e.screenToWorld(e.vec2(o.pos.x,o.pos.y)),l=e.cameraScale,u=o.emitTime!=null?o.emitTime:o.count!=null?1/60:0,h=o.emitRate!=null?o.emitRate:o.count!=null?o.count*60:100,d=(o.speed!=null?o.speed:0)/l/60,f=o.damping!=null?o.damping:1,p=o.colorStart||{r:1,g:1,b:1,a:1},y=o.colorEnd||{r:1,g:1,b:1,a:0},x=e.rgb(p.r,p.g,p.b,p.a),w=e.rgb(y.r,y.g,y.b,y.a),A=new e.ParticleEmitter(c,o.angle!=null?o.angle:0,(o.emitSize!=null?o.emitSize:0)/l,u,h,o.coneAngle!=null?o.coneAngle:Math.PI,void 0,x,x,w,w,o.particleTime!=null?o.particleTime:.5,(o.sizeStart!=null?o.sizeStart:6)/l,(o.sizeEnd!=null?o.sizeEnd:0)/l,d,0,f,1,o.gravityScale!=null?o.gravityScale:0,Math.PI,.1,0,!1,o.additive!=null?o.additive:!1,!0);return{isActive(){return A.isActive()},stop(){A.destroyed||A.destroy(!0)}}}},audio:{synth:{synthSfx:o=>{i("audio.synth.synthSfx");try{return e.zzfxG(...o)}catch(c){return console.error("[host][engine-audio] zzfxG \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(c&&c.message?c.message:c)),null}},synthSong:(o,c,l,u)=>{i("audio.synth.synthSong");try{return e.zzfxM(o,c,l,u)}catch(h){return console.error("[host][engine-audio] zzfxM \u5408\u6210\u5F02\u5E38\uFF0C\u8FD4 null\uFF1A"+(h&&h.message?h.message:h)),null}}}}}}function xt(t){return t<0?0:t>1?1:t}function Wa(t){let e=t.Ease,n=e.POWER(2),s=e.POWER(3),i=e.OUT(n),r=e.IN_OUT(n),a=e.OUT(s),o=e.IN_OUT(s),c=e.OUT(e.BACK),l=e.OUT(e.ELASTIC);return{lerp:(u,h,d)=>t.lerp(u,h,d),smoothStep:u=>t.smoothStep(u),easing:{linear:u=>e.LINEAR(xt(u)),quadIn:u=>n(xt(u)),quadOut:u=>i(xt(u)),quadInOut:u=>r(xt(u)),cubicIn:u=>s(xt(u)),cubicOut:u=>a(xt(u)),cubicInOut:u=>o(xt(u)),backIn:u=>e.BACK(xt(u)),backOut:u=>c(xt(u)),elasticIn:u=>e.ELASTIC(xt(u)),elasticOut:u=>l(xt(u))}}}var rn=2,fi=1/60;async function Ha(t){let e=t.canvas,n=t.statusEl||null,s=t.engine,i=t.seed>>>0,r=t.mode||"play",a=t.engineMode||"real",o=t.viewport.w,c=t.viewport.h,l=t.factory,u=t.buildFactoryOpts||(()=>{}),h=t.plugins||{},d=t.registerOrder||Object.values(h),f=t.onReady||(()=>{}),p=t.recHook||(()=>{});function y(B){n&&(n.textContent=B)}let x=[];window.addEventListener("error",B=>x.push({type:"error",message:String(B&&B.message||B)})),window.addEventListener("unhandledrejection",B=>x.push({type:"unhandledrejection",message:String(B&&B.reason&&B.reason.message||B&&B.reason||B)}));let w=null,A=!1;function S(){if(!A)return null;if(w)return w;let B=window.AudioContext||window.webkitAudioContext;return B?(w=new B,w):null}let _=0,k=null,C=null,O=null,q=null,ce=[],ne={},T=null;function R(B,xe){try{O&&O.mark(B,xe)}catch(G){x.push({type:"mark",message:String(G&&G.message||G)})}}function M(){C&&typeof C._refreshChecklist=="function"&&C._refreshChecklist(ne)}async function L(B,xe){k=ja({context2d:B,seed:i,audioFactory:S,clock:()=>_,engineFactory:()=>qa({LJS:a==="real"?s:null,engineMath:a==="real"?Wa(s):null,engineMode:a,recHook:p})});let G=new ui;for(let J of d)G.register(J);G.useContext(k.context),q=G.initAll(),ce=G.list().concat(["runtime-probe"]),O=Va({pluginSet:ce,inputAnchorType:"pointerdown",autoBoot:!0});let F=k.deriveContextFor("runtime-probe","runtime-probe");R("t_boot",{by:"game-host",stage:"pre-init",engineMode:a}),R("t_plugins_ready",{initialized:q.initialized.length,ok:q.ok});let j=u(k.context,{bundle:k,plugins:h,getRealAudioCtx:()=>w});C=l(j),await C.init({ctx:k.context,mainContext:B,canvas:xe(),seed:i}),T=C&&typeof C._forensicsView=="function"?C._forensicsView():null,R("t_game_init",{hasForensics:!!T}),N(),R("t_first_paint",{frame:k.frameCount()});try{O.init(F)}catch(J){x.push({type:"probe-init",message:String(J&&J.message||J)})}R("t_game_start",{mode:r,engineMode:a}),M(),f(se,{bundle:k,game:C,probe:O,checklist:ne,uncaught:x,pluginSet:ce,initRes:q,getGameForensics:()=>T,mark:R,stepOneFrame:N})}let E=null;function N(B){let xe=typeof B=="number"?B:fi;C&&(_+=xe*1e3,C.update(xe),a==="stub"&&E&&C.render(E),M())}function U(B){for(let xe=0;xe{}),C&&typeof C._onAudioUnlock=="function"&&C._onAudioUnlock()}let se={seed:i,mode:r,engineMode:a,protocol:Ja,frameCount:()=>k?k.frameCount():0,stepFrames:U,startRaf:()=>Yn(),stopRaf:()=>jt(),tap(B,xe){Y(),k&&(k.inputBridge._emit("pointerdown",{x:B,y:xe}),k.inputBridge._emit("pointerup",{x:B,y:xe}))},do(B){C&&typeof C._handleAction=="function"&&C._handleAction(B)},state:()=>T?T.state():{phase:"booting"}};function Ne(B){let xe=k.inputBridge;function G(F,j){let J=B.getBoundingClientRect();return{x:(F-J.left)/J.width*o,y:(j-J.top)/J.height*c}}B.addEventListener("pointerdown",F=>{Y(),xe._emit("pointerdown",G(F.clientX,F.clientY))}),B.addEventListener("pointermove",F=>{xe._emit("pointermove",G(F.clientX,F.clientY))}),B.addEventListener("pointerup",F=>{xe._emit("pointerup",G(F.clientX,F.clientY))})}let ge=0,Re=!1,be=0;function ct(B){if(!Re)return;be===0&&(be=B);let xe=(B-be)/1e3;be=B,xe>.05&&(xe=.05),N(xe),ge=window.requestAnimationFrame(ct)}function Yn(){a==="stub"&&(Re||(Re=!0,be=0,ge=window.requestAnimationFrame(ct)))}function jt(){Re=!1,ge&&window.cancelAnimationFrame(ge),ge=0}function $n(B){B.width=o*rn,B.height=c*rn,B.style.width=o+"px",B.style.height=c+"px";let xe=B.getContext("2d",{willReadFrequently:!0});return xe.setTransform(rn,0,0,rn,0,0),xe}async function Ss(){let B=$n(e);return E=B,await L(B,()=>e),Ne(e),r==="evidence"?y(`evidence \u5C31\u7EEA seed=${i} \xB7 \u7528 host \u9A71\u52A8\uFF08stepFrames/tap\uFF09`):(y(`seed=${i} \xB7 \u70B9\u5F00\u59CB\uFF08\u9996\u6B21\u70B9\u51FB\u5F00\u58F0\uFF09`),Yn()),se}let tn=()=>{},nn=()=>{};function sn(){window.__gameHostEngineInitFired=!0}function Xn(){tn()}function Kn(){}function go(){nn()}function bo(){}async function xo(B){await L(B,()=>s.mainCanvas),Ne(s.mainCanvas),tn=()=>{C&&(_+=fi*1e3,C.update(fi))},nn=()=>{if(C){B.save(),B.setTransform(rn,0,0,rn,0,0);try{B.imageSmoothingEnabled=!1}catch{}C.render(B),B.restore()}},s.mainCanvas&&(s.mainCanvas.id="game-engine"),window.__engine={frame(){return s.frame},time(){return s.time},timeReal(){return s.timeReal},paused(){return s.paused},timeScale(){return s.timeScale},snapshot(){return{frame:s.frame,time:s.time,timeReal:s.timeReal,paused:s.paused,timeScale:s.timeScale}}},y(`engine RAF running \xB7 seed=${i} engine=real`)}if(a!=="real")return await Ss();if(!s){let B="real \u901A\u9053\u672A\u6CE8\u5165\u5F15\u64CE\uFF08opts.engine \u7F3A\u5931\uFF09\uFF1A\u8BF7\u7ECF entry \u5305\u88C5\u5C42\u542F\u52A8\uFF08host \u4E0D\u76F4\u63A5 import \u5F15\u64CE\uFF0CQ4/Option C\uFF09";throw y("ENGINE INJECT MISSING: "+B),new Error(B)}s.setGLEnable(!1),s.setShowSplashScreen(!1),s.setDebugWatermark(!1),s.setCanvasClearColor(s.BLACK),s.setCanvasFixedSize(s.vec2(o*rn,c*rn));let vs=document.createElement("div");return vs.id="engine-root",document.body.appendChild(vs),await s.engineInit(sn,Xn,Kn,go,bo,[],vs).then(()=>xo(s.mainContext)).catch(B=>{throw window.__gameHostBootError=String(B&&B.message||B),y("ENGINE INIT FAILED: "+window.__gameHostBootError),B}),se}function ru(){return{hit:!1,depth:0,nx:0,ny:0}}var Eo=class{constructor(e){let n=e||{},s=typeof n.cellSize=="number"&&n.cellSize>0?n.cellSize:64;this._cellSize=s,this._cells=new Map,this._entries=new Map,this._seq=0}get size(){return this._entries.size}_cellRange(e){let n=this._cellSize,s=Math.floor((e.x-e.hw)/n),i=Math.floor((e.x+e.hw)/n),r=Math.floor((e.y-e.hh)/n),a=Math.floor((e.y+e.hh)/n);return{cx0:s,cy0:r,cx1:i,cy1:a}}insert(e,n){this._entries.has(e)&&this.remove(e);let{cx0:s,cy0:i,cx1:r,cy1:a}=this._cellRange(n),o=[];for(let l=i;l<=a;l++)for(let u=s;u<=r;u++){let h=u+","+l,d=this._cells.get(h);d||(d=new Set,this._cells.set(h,d)),d.add(e),o.push(h)}let c={x:n.x,y:n.y,hw:n.hw,hh:n.hh};this._entries.set(e,{id:e,box:c,seq:this._seq++,cells:o})}remove(e){let n=this._entries.get(e);if(!n)return!1;for(let s of n.cells){let i=this._cells.get(s);i&&(i.delete(e),i.size===0&&this._cells.delete(s))}return this._entries.delete(e),!0}query(e){let{cx0:n,cy0:s,cx1:i,cy1:r}=this._cellRange(e),a=new Set;for(let o=s;o<=r;o++)for(let c=n;c<=i;c++){let l=this._cells.get(c+","+o);if(l)for(let u of l)a.add(u)}return this._collect(a)}queryPoint(e,n){let s=this._cellSize,i=Math.floor(e/s),r=Math.floor(n/s),a=this._cells.get(i+","+r);return a?this._collect(new Set(a)):[]}clear(){this._cells.clear(),this._entries.clear(),this._seq=0}_collect(e){let n=[];for(let s of e){let i=this._entries.get(s);i&&n.push(i)}return n.sort((s,i)=>s.seq-i.seq),n.map(s=>({id:s.id,box:s.box}))}};function Ya(t,e){let n=t.x-e.x,s=t.y-e.y,i=t.hw+e.hw-Math.abs(n),r=t.hh+e.hh-Math.abs(s);return i<=1e-9||r<=1e-9?ru():i0?e.fixedStep:1/120;return{gx:n.x||0,gy:n.y||0,fixedStep:s}}function Ka(t,e,n,s){t.vx+=e*s,t.vy+=n*s,t.px+=t.vx*s,t.py+=t.vy*s}function au(t,e,n){let{gx:s,gy:i,fixedStep:r}=Qa(n),a={px:t.px,py:t.py,vx:t.vx,vy:t.vy},o=e>0?e:0;for(;o>=r-1e-12;)Ka(a,s,i,r),o-=r;return o>1e-12&&Ka(a,s,i,o),a}var hi=class{constructor(e,n){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy};let s=Qa(n);this._gx=s.gx,this._gy=s.gy,this._fixedStep=s.fixedStep}get state(){return{px:this._s.px,py:this._s.py,vx:this._s.vx,vy:this._s.vy}}step(e){let n=au(this._s,e,{gravity:{x:this._gx,y:this._gy},fixedStep:this._fixedStep});return this._s=n,this.state}reset(e){this._s={px:e.px,py:e.py,vx:e.vx,vy:e.vy}}};function Za(t,e,n,s){let i=n.mass==null?1:n.mass,r=n.stiffness,a=n.damping,o=t.x,c=t.v,l=s>0?s:0;if(l<=1e-12)return{x:o,v:c};let u=i>1e-12?i:1e-12,h=Math.sqrt(Math.max(0,r)/u),d=a/u,f=h>1e-12?.2/h:l,p=d>1e-12?.5/d:l,y=Math.max(1e-12,Math.min(f,p)),x=Math.ceil(l/y);(!Number.isFinite(x)||x<1)&&(x=1),x>4096&&(x=4096);let w=l/x;for(let A=0;A1?1:t}var lu=t=>(t=Xe(t),t*t),uu=t=>(t=Xe(t),1-(1-t)*(1-t)),du=t=>(t=Xe(t),t<.5?2*t*t:1-Math.pow(-2*t+2,2)/2),fu=t=>(t=Xe(t),t*t*t),hu=t=>{t=Xe(t);let e=1-t;return 1-e*e*e},pu=t=>(t=Xe(t),t<.5?4*t*t*t:1-Math.pow(-2*t+2,3)/2),nc=2*Math.PI/3,tc=2*Math.PI/4.5,mu=t=>(t=Xe(t),t===0?0:t===1?1:-Math.pow(2,10*t-10)*Math.sin((t*10-10.75)*nc)),yu=t=>(t=Xe(t),t===0?0:t===1?1:Math.pow(2,-10*t)*Math.sin((t*10-.75)*nc)+1),gu=t=>(t=Xe(t),t===0?0:t===1?1:t<.5?-(Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*tc))/2:Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*tc)/2+1),yi=1.70158,pi=yi*1.525,sc=yi+1,bu=t=>(t=Xe(t),sc*t*t*t-yi*t*t),xu=t=>{t=Xe(t);let e=t-1;return 1+sc*e*e*e+yi*e*e},Su=t=>(t=Xe(t),t<.5?Math.pow(2*t,2)*((pi+1)*2*t-pi)/2:(Math.pow(2*t-2,2)*((pi+1)*(t*2-2)+pi)+2)/2),vu=t=>Xe(t),Po=Object.freeze({linear:vu,quadIn:lu,quadOut:uu,quadInOut:du,cubicIn:fu,cubicOut:hu,cubicInOut:pu,elasticIn:mu,elasticOut:yu,elasticInOut:gu,backIn:bu,backOut:xu,backInOut:Su}),Ro=Po,wu=["linear","quadIn","quadOut","quadInOut","cubicIn","cubicOut","cubicInOut","elasticIn","elasticOut","elasticInOut","backIn","backOut","backInOut"];function Tu(t){let e=t&&t.easing;if(!e)return Po;let n=i=>typeof e[i]=="function"?r=>e[i](Xe(r)):Po[i],s={};for(let i of wu)s[i]=n(i);return Object.freeze(s)}var Mo=class{constructor(e,n,s){let i=s||{};this._time=n,this._windowMs=typeof i.windowMs=="number"&&i.windowMs>0?i.windowMs:120;let r=Array.isArray(i.types)&&i.types.length>0?i.types:cu;this._records=new Map,this._subs=[],this._disposed=!1;for(let a of r){this._records.set(a,null);let o=e.on(a,c=>{this._records.set(a,c.tMs)});this._subs.push(o)}}consume(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs?(this._records.set(e,null),!0):(this._records.set(e,null),!1)}peek(e,n){let s=typeof n=="number"?n:this._time.nowMs(),i=this._records.get(e);return i==null?!1:s-i<=this._windowMs}clear(){for(let e of this._records.keys())this._records.set(e,null)}dispose(){if(!this._disposed){for(let e of this._subs)try{e.cancel()}catch(n){}this._subs=[],this._disposed=!0}}};var mi=class{constructor(e,n){let s=n||{};this._time=e,this._windowMs=typeof s.windowMs=="number"&&s.windowMs>0?s.windowMs:500,this._maxCount=typeof s.maxCount=="number"&&s.maxCount>0?s.maxCount:1/0,this._count=0,this._lastHitAt=null}hit(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt!=null&&n-this._lastHitAt<=this._windowMs&&this._count>0?this._count=Math.min(this._count+1,this._maxCount):this._count=1,this._lastHitAt=n,this._count}getCount(e){let n=typeof e=="number"?e:this._time.nowMs();return this._lastHitAt==null||n-this._lastHitAt>this._windowMs?0:this._count}reset(){this._count=0,this._lastHitAt=null}};function ic(t){let e=t||{},n=null,s=null,i=!1;return{name:"gamefeel",version:"1.0.0",dependencies:[],get inputBuffer(){return n},get easing(){return Tu(s)},init(a){let o=a.getInput();n=new Mo(o,a.time,{windowMs:e.inputBufferMs,types:e.inputTypes});let c=a.getEngine();s=c?c.math:null},dispose(){i||(n&&(n.dispose(),n=null),s=null,i=!0)}}}function gi(t,e){let n=e<0?0:e>1?1:e;switch(t&&t.kind){case"constant":return t.value;case"linear":return t.from+(t.to-t.from)*n;case"easeInOut":{let s=n*n*(3-2*n);return t.from+(t.to-t.from)*s}case"decay":{let s=t.power==null?2:t.power,i=Math.pow(1-n,s);return t.to+(t.from-t.to)*i}default:return 0}}var Au=Object.freeze({burst:Object.freeze({mode:"burst",count:24,angle:0,spread:Math.PI,speedMin:80,speedMax:160,lifeMin:.4,lifeMax:.8,gravity:0,drag:0,sizeCurve:{kind:"decay",from:6,to:0,power:1.5},alphaCurve:{kind:"linear",from:1,to:0}}),trail:Object.freeze({mode:"continuous",rate:60,angle:Math.PI,spread:.25,speedMin:20,speedMax:50,lifeMin:.2,lifeMax:.5,gravity:0,drag:1.5,sizeCurve:{kind:"easeInOut",from:4,to:0},alphaCurve:{kind:"decay",from:.8,to:0,power:2}}),drift:Object.freeze({mode:"continuous",rate:12,angle:Math.PI/2,spread:.6,speedMin:10,speedMax:30,lifeMin:1.5,lifeMax:3,gravity:8,drag:.5,sizeCurve:{kind:"constant",value:3},alphaCurve:{kind:"decay",from:.7,to:0,power:1}})});function ku(t){let e=Au[t];return e?Lo(e):null}function Lo(t){let e={};for(let n of Object.keys(t)){let s=t[n];e[n]=s&&typeof s=="object"?Lo(s):s}return e}function Cu(t,e,n){let s=t.mode==="continuous";return{pos:{x:e,y:n},angle:t.angle,coneAngle:t.spread,emitSize:0,emitTime:s?0:1/60,emitRate:s?t.rate||0:void 0,count:s?void 0:t.count||0,particleTime:(t.lifeMin+t.lifeMax)/2,speed:(t.speedMin+t.speedMax)/2,gravityScale:t.gravity||0,damping:t.drag!=null?1-t.drag/60:1,sizeStart:gi(t.sizeCurve,0),sizeEnd:gi(t.sizeCurve,1),colorStart:{r:1,g:1,b:1,a:gi(t.alphaCurve,0)},colorEnd:{r:1,g:1,b:1,a:gi(t.alphaCurve,1)},additive:!1}}function bi(t){let e=t||{},n=null,s=null,i=null,r=new Map,a=0,o={isActive(){return!1},stop(){}},c=0,l=1,u=0,h=0,d=0,f={x:0,y:0,remain:0,dur:0,amplitude:0,frequency:0,_phase:0},p={alpha:0,remain:0,dur:0,peak:0},y={scale:1,remain:0,dur:0,amplitude:0,frequency:0},x=!1;function w(k){if(u>0)if(u-=k,u<=0)u=0,l=1;else{let C=h>0?1-u/h:1;l=d+(1-d)*C}if(f.remain>0)if(f.remain-=k,f.remain<=0)f.remain=0,f.x=0,f.y=0;else{let C=f.remain/f.dur,O=f.amplitude*C;f._phase+=f.frequency*k*Math.PI*2,f.x=Math.sin(f._phase)*O,f.y=Math.cos(f._phase*1.3)*O}if(p.remain>0&&(p.remain-=k,p.remain<=0?(p.remain=0,p.alpha=0):p.alpha=p.peak*(p.remain/p.dur)),y.remain>0)if(y.remain-=k,y.remain<=0)y.remain=0,y.scale=1;else{let C=y.remain/y.dur,O=(1-C)*y.frequency*Math.PI*2;y.scale=1+Math.sin(O)*y.amplitude*C}}function A(k){c+=1,w(k)}function S(k){let C=k!==void 0?k:n?n.getContext2d():null;if(C&&p.alpha>0){C.globalAlpha=p.alpha,C.fillStyle="#ffffff";let O=C.canvas?C.canvas.width:0,q=C.canvas?C.canvas.height:0;C.fillRect(0,0,O,q),C.globalAlpha=1}}return{name:"particles-juice",version:"1.0.0",dependencies:[],init(k){var C;n=k,i=((C=k.getEngine())==null?void 0:C.particles)||null,typeof e.seed=="number"&&k.random.reseed(e.seed),e.autoStep!==!1&&(s=k.onFrame(O=>{A(O)}))},dispose(){x||(s&&(s.cancel(),s=null),r.forEach(k=>{try{k.stop()}catch{}}),r.clear(),l=1,u=0,f.remain=0,f.x=0,f.y=0,p.remain=0,p.alpha=0,y.remain=0,y.scale=1,x=!0)},spawnEmitter(k,C,O,q){let ce=typeof k=="string"?ku(k):Lo(k);if(!ce)return-1;q&&(ce=Object.assign(ce,q));let ne=a++;if(!i)return r.set(ne,o),ne;let T=i.spawnEmitter(Cu(ce,C,O));return r.set(ne,T),ne},stopEmitter(k){let C=r.get(k);if(C)try{C.stop()}catch{}},step(k){A(k)},render(k){S(k)},particleCount(){return 0},emitterCount(){let k=0;for(let C of r.values())C.isActive()&&(k+=1);return k},hitStop(k,C){h=Math.max(0,k),u=h,d=C==null?0:Math.max(0,Math.min(1,C)),l=h>0?d:1},getTimeScale(){return l},shakeScreen(k,C,O){f.dur=Math.max(0,k),f.remain=f.dur,f.amplitude=Math.max(0,C),f.frequency=O==null?30:O,f._phase=0,f.x=0,f.y=0},getShakeOffset(){return{x:f.x,y:f.y}},flashScreen(k,C){p.dur=Math.max(0,k),p.remain=p.dur,p.peak=C==null?.8:Math.max(0,Math.min(1,C)),p.alpha=p.dur>0?p.peak:0},getFlashAlpha(){return p.alpha},pulseScale(k,C,O){y.dur=Math.max(0,k),y.remain=y.dur,y.amplitude=C==null?.2:C,y.frequency=O==null?4:O,y.scale=1},getPulseScale(){return y.scale},juiceSnapshot(){return{timeScale:l,shake:{x:f.x,y:f.y},flashAlpha:p.alpha,pulseScale:y.scale}},probe(){return{particles:0,emitters:r.size,dropped:0,steps:c,disposed:x}}}}function oc(t){let e=Ce(t.r)/255,n=Ce(t.g)/255,s=Ce(t.b)/255,i=Math.max(e,n,s),r=Math.min(e,n,s),a=(i+r)/2,o=0,c=0,l=i-r;return l>1e-12&&(c=a>.5?l/(2-i-r):l/(i+r),i===e?o=(n-s)/l%6:i===n?o=(s-e)/l+2:o=(e-n)/l+4,o*=60,o<0&&(o+=360)),{h:o,s:c,l:a}}function rc(t){let e=(t.h%360+360)%360,n=an(t.s),s=an(t.l);if(n<1e-12){let o=Math.round(s*255);return{r:o,g:o,b:o}}let i=s<.5?s*(1+n):s+n-s*n,r=2*s-i,a=e/360;return{r:Math.round(Oo(r,i,a+1/3)*255),g:Math.round(Oo(r,i,a)*255),b:Math.round(Oo(r,i,a-1/3)*255)}}function Oo(t,e,n){let s=n;return s<0&&(s+=1),s>1&&(s-=1),s<1/6?t+(e-t)*6*s:s<1/2?e:s<2/3?t+(e-t)*(2/3-s)*6:t}function Ce(t){return t<0?0:t>255?255:t}function an(t){return t<0?0:t>1?1:t}function Go(t,e){let n=Eu(t.from,e);if(n>=0&&n({r:Ce(o.r),g:Ce(o.g),b:Ce(o.b)})),to:r}}function Io(t,e,n){return t+(e-t)*n}function jo(t,e){let n=oc(t),s=n.h+(e.hue||0),i=an(n.s*(e.sat==null?1:e.sat)),r=an(n.l*(e.light==null?1:e.light));return rc({h:s,s:i,l:r})}var Mu=Object.freeze([Object.freeze([0,8,2,10]),Object.freeze([12,4,14,6]),Object.freeze([3,11,1,9]),Object.freeze([15,7,13,5])]);function ac(t){let e=t||{},n=null,s=!1,i={vignette:{enabled:Do(e.vignette&&e.vignette.enabled,!1),strength:Fo(e.vignette&&e.vignette.strength,.5)},dither:{enabled:Do(e.dither&&e.dither.enabled,!1),strength:Fo(e.dither&&e.dither.strength,.5)},scanline:{enabled:Do(e.scanline&&e.scanline.enabled,!1),strength:Fo(e.scanline&&e.scanline.strength,.5)}};function r(o){let c=o!==void 0?o:n?n.getContext2d():null;if(!c)return;let l=c.canvas?c.canvas.width:0,u=c.canvas?c.canvas.height:0;if(i.vignette.enabled&&i.vignette.strength>0&&l>0&&u>0){let h=c.createRadialGradient(l/2,u/2,Math.min(l,u)*.25,l/2,u/2,Math.max(l,u)*.75);h.addColorStop(0,"rgba(0,0,0,0)"),h.addColorStop(1,"rgba(0,0,0,"+i.vignette.strength.toFixed(3)+")"),c.fillStyle=h,c.fillRect(0,0,l,u)}if(i.scanline.enabled&&i.scanline.strength>0&&l>0&&u>0){c.fillStyle="rgba(0,0,0,"+(i.scanline.strength*.5).toFixed(3)+")";for(let h=0;h0&&l>0&&u>0&&typeof c.getImageData=="function"&&typeof c.putImageData=="function"){let h=c.getImageData(0,0,l,u);Ru(h,i.dither.strength),c.putImageData(h,0,0)}}return{name:"palette-post",version:"1.0.0",dependencies:[],init(o){n=o},dispose(){s||(n=null,s=!0)},applyPaletteMap(o,c){return Go(o,c)},applyPaletteMapToBuffer(o,c){return _u(o,c)},lerpPaletteMap(o,c,l){return Bo(o,c,l)},shiftHsl(o,c){return jo(o,c)},rgbToHsl(o){return oc(o)},hslToRgb(o){return rc(o)},setPost(o){if(o)for(let c of["vignette","dither","scanline"])o[c]&&(typeof o[c].enabled=="boolean"&&(i[c].enabled=o[c].enabled),typeof o[c].strength=="number"&&(i[c].strength=an(o[c].strength)))},getPost(){return{vignette:{enabled:i.vignette.enabled,strength:i.vignette.strength},dither:{enabled:i.dither.enabled,strength:i.dither.strength},scanline:{enabled:i.scanline.enabled,strength:i.scanline.strength}}},renderPost(o){r(o)},probe(){return{disposed:s,post:this.getPost()}}}}function Ru(t,e){let n=an(e);if(n<=0)return t;let{data:s,width:i}=t,a=255/(Math.max(2,Math.round(16-n*14))-1);for(let o=0;o+3>2)%i,l=Math.floor((o>>2)/i),u=(Mu[l&3][c&3]/16-.5)*a;for(let h=0;h<3;h++){let d=s[o+h]+u,f=Math.round(d/a)*a;s[o+h]=f<0?0:f>255?255:f}}return t}function Do(t,e){return typeof t=="boolean"?t:e}function Fo(t,e){return typeof t=="number"?an(t):e}var No=Object.freeze({blip:Object.freeze({name:"blip",params:Object.freeze([.6,0,880,0,.03,.06,1,1.5])}),thud:Object.freeze({name:"thud",params:Object.freeze([.8,0,90,0,.04,.18,0,1,0,0,0,0,0,4])}),chime:Object.freeze({name:"chime",params:Object.freeze([.5,0,660,.02,.12,.3,1,2])})}),cc=Object.keys(No);function Lu(t){let e=[];return t==null||typeof t!="object"?{ok:!1,errors:["song \u5FC5\u987B\u662F\u5BF9\u8C61"]}:(!Array.isArray(t.instruments)||t.instruments.length===0?e.push("instruments \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.instruments.forEach((n,s)=>{(!Array.isArray(n)||n.some(i=>typeof i!="number"||!Number.isFinite(i)))&&e.push(`instruments[${s}] \u5FC5\u987B\u662F\u6709\u9650\u6570\u5B57\u6570\u7EC4\uFF08ZzFX \u53C2\u6570\u5305\uFF09`)}),!Array.isArray(t.patterns)||t.patterns.length===0?e.push("patterns \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.patterns.forEach((n,s)=>{if(!Array.isArray(n)||n.length===0){e.push(`patterns[${s}] \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF08\u81F3\u5C11\u4E00\u4E2A\u58F0\u90E8\u901A\u9053\uFF09`);return}n.forEach((i,r)=>{if(!Array.isArray(i)||i.length<2){e.push(`patterns[${s}][${r}] \u901A\u9053\u81F3\u5C11\u542B [\u4E50\u5668\u7D22\u5F15, \u58F0\u50CF]`);return}if(i.some(c=>typeof c!="number"||!Number.isFinite(c))){e.push(`patterns[${s}][${r}] \u901A\u9053\u5FC5\u987B\u5168\u4E3A\u6709\u9650\u6570\u5B57`);return}let a=i[0]|0;Array.isArray(t.instruments)&&(a<0||a>=t.instruments.length)&&e.push(`patterns[${s}][${r}] \u4E50\u5668\u7D22\u5F15 ${a} \u8D8A\u754C\uFF08instruments \u957F\u5EA6 ${t.instruments.length}\uFF09`);let o=i[1];(o<-1||o>1)&&e.push(`patterns[${s}][${r}] \u58F0\u50CF ${o} \u8D8A\u754C\uFF08\u5E94 -1..+1\uFF09`)})}),!Array.isArray(t.sequence)||t.sequence.length===0?e.push("sequence \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4"):t.sequence.forEach((n,s)=>{if(typeof n!="number"||!Number.isInteger(n)){e.push(`sequence[${s}] \u5FC5\u987B\u662F\u6574\u6570 pattern \u7D22\u5F15`);return}Array.isArray(t.patterns)&&(n<0||n>=t.patterns.length)&&e.push(`sequence[${s}] \u7D22\u5F15 ${n} \u8D8A\u754C\uFF08patterns \u957F\u5EA6 ${t.patterns.length}\uFF09`)}),t.bpm!=null&&(typeof t.bpm!="number"||!(t.bpm>0))&&e.push("bpm \u5FC5\u987B\u662F\u6B63\u6570"),{ok:e.length===0,errors:e})}function Ct(t){return typeof t!="number"||Number.isNaN(t)||t<0?0:t>1?1:t}function Ou(t,e){switch(t){case"ease-in":return e*e;case"ease-out":return Math.sqrt(e);case"constant":return 1;default:return e}}function lc(t,e){let n=Ct(e);return t==null||!Array.isArray(t.voices)?[]:t.voices.map(s=>{let i=String(s&&s.id!=null?s.id:""),r=Array.isArray(s&&s.channelIndices)?s.channelIndices.slice():[],a=typeof s.minIntensity=="number"?Ct(s.minIntensity):0,o=typeof s.maxIntensity=="number"?Ct(s.maxIntensity):1,c=typeof s.volumeCurve=="string"?s.volumeCurve:"linear",l=typeof s.baseVolume=="number"?Ct(s.baseVolume):1;if(no)return{id:i,on:!1,volume:0,channelIndices:r};let u=o-a,h=u<=0?1:(n-a)/u,d=Ct(Ou(c,h)*l);return{id:i,on:!0,volume:d,channelIndices:r}})}function uc(t,e,n,s){try{let i=e[0]||[],r=e[1]||i,a=Math.max(i.length,r.length);if(a===0)return null;let c=t.createBuffer(2,a,44100);c.getChannelData(0).set(i),c.getChannelData(1).set(r.length?r:i);let l=t.createBufferSource();l.buffer=c,l.loop=!!s;let u=t.createGain();return u.gain.value=Ct(n*.3),l.connect(u),u.connect(t.destination),l.start(),{stop(){try{l.stop()}catch(h){}try{l.disconnect(),u.disconnect()}catch(h){}}}}catch(i){return zo("[audio-music] \u53D7\u63A7\u97F3\u9891\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",i),null}}function dc(t){let e=t||{},n=typeof e.masterVolume=="number"?Ct(e.masterVolume):1,s=()=>null,i=null,r=null,a={voices:[]},o=1,c=null,l=!1,u=0,h=!1,d=!1;function f(){let S=s();return S==null?(u+=1,h||(Jo("[audio-music] \u65E0\u53D7\u63A7\u97F3\u9891\u4E0A\u4E0B\u6587\uFF08getAudioContext \u8FD4\u56DE null\uFF09\uFF0C\u5168\u90E8\u53D1\u58F0\u9759\u9ED8 no-op\uFF08\u8BC4\u4F30\u73AF\u5883\u65E0\u58F0\u5361\u65F6\u7684\u5BB9\u9519\u964D\u7EA7\uFF09"),h=!0),null):S}function p(){if(!r||!i)return null;try{let S=typeof r.bpm=="number"&&r.bpm>0?r.bpm:125;return i.synthSong(r.instruments,r.patterns,r.sequence,S)}catch(S){return zo("[audio-music] \u66F2\u8C31\u6E32\u67D3\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8",S),null}}function y(){let S=lc(a,o);if(S.length===0)return 1;let _=0;for(let k of S)k.on&&(_=Math.max(_,k.volume));return _}function x(S,_){typeof _=="number"&&(o=Ct(_));let k=f();if(k==null||!r)return;w();let C=p();if(!C)return;let O=Ct(n*y());c=uc(k,C,O,S),l=!!S&&c!=null}function w(){c&&(c.stop(),c=null),l=!1}return{name:"audio-music",version:"1.0.0",dependencies:[],init(S){s=()=>S.getAudioContext();let _=S.getEngine&&S.getEngine();i=_?_.audio.synth:null},dispose(){d||(w(),d=!0)},loadSong(S){let _=Lu(S);return _.ok?r={instruments:S.instruments,patterns:S.patterns,sequence:S.sequence,bpm:typeof S.bpm=="number"?S.bpm:125}:Jo("[audio-music] \u66F2\u8C31\u6821\u9A8C\u5931\u8D25\uFF0C\u672A\u8F7D\u5165\uFF1A"+_.errors.join("\uFF1B")),_},play(S){x(!1,S)},stop(){w()},loop(S){x(!0,S)},setIntensityLayering(S){a=S&&Array.isArray(S.voices)?{voices:S.voices}:{voices:[]}},setIntensity(S){o=Ct(S)},resolveVoices(S){return lc(a,S)},playSfx(S){let _=No[S];if(!_){Jo("[audio-music] \u672A\u77E5\u97F3\u6548\u9884\u8BBE\uFF1A"+String(S));return}let k=f();if(k!=null)try{let C=i?i.synthSfx(_.params):null;if(!C)return;uc(k,[C,C],n,!1)}catch(C){zo("[audio-music] \u97F3\u6548\u64AD\u653E\u5F02\u5E38\uFF0C\u964D\u7EA7\u4E3A\u9759\u9ED8 name="+S,C)}},getPreset(S){return No[S]},listPresets(){return cc.slice()},probe(){return{hasAudio:s()!=null,hasSong:r!=null,intensity:o,voiceCount:a.voices.length,looping:l,silentNoops:u,presetCount:cc.length}}}}function zo(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Jo(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Iu="zaomeng.save";function Du(t){if(typeof TextEncoder!="undefined")return new TextEncoder().encode(t).length;if(typeof Buffer!="undefined"&&typeof Buffer.byteLength=="function")return Buffer.byteLength(t,"utf8");let e=0;for(let n=0;n=55296&&s<=56319?(e+=4,n++):e+=3}return e}function Vo(){let t=new Map;return{getItem(e){return t.has(e)?t.get(e):null},setItem(e,n){t.set(e,n)},removeItem(e){t.delete(e)},keys(){return Array.from(t.keys())}}}function fc(){if(typeof localStorage=="undefined")throw new Error("[save-progress] createLocalStorageAdapter \u9700\u8981\u5168\u5C40 localStorage\uFF08\u4EC5\u6D4F\u89C8\u5668\u96C6\u6210\u6BB5\u53EF\u7528\uFF09\u3002node/host-dev \u8BF7\u7528\u7F3A\u7701\u5185\u5B58 adapter \u6216 createMemoryAdapter()\u3002");return{getItem(t){return localStorage.getItem(t)},setItem(t,e){localStorage.setItem(t,e)},removeItem(t){localStorage.removeItem(t)},keys(){let t=[];for(let e=0;e0?e.namespace:Iu;if(n.indexOf(":")>=0)throw new Error('[save-progress] namespace \u4E0D\u5F97\u542B\u5206\u9694\u7B26 ":"\uFF08\u5F53\u524D="'+n+'"\uFF09');let s=typeof e.maxValueBytes=="number"&&e.maxValueBytes>0?Math.floor(e.maxValueBytes):32768,i=!Fu(e.adapter),r=i?Vo():e.adapter,a=n+":",o=0,c=0,l=!1;function u(f){return typeof f!="string"||f.length===0?a+String(f):a+f}function h(){try{let f=r.keys();return Array.isArray(f)?f.filter(p=>typeof p=="string"&&p.indexOf(a)===0):[]}catch(f){return ws("[save-progress] adapter.keys() \u5F02\u5E38\uFF0C\u964D\u7EA7\u8FD4\u56DE\u7A7A\u96C6",f),[]}}return{name:"save-progress",version:"1.0.0",dependencies:[],init(f){h()},dispose(){},get(f,p){if(!Uo(f))return p;let y;try{y=r.getItem(u(f))}catch(x){return ws("[save-progress] adapter.getItem \u5F02\u5E38\uFF0C\u8FD4\u56DE\u9ED8\u8BA4\u503C key="+f,x),p}if(y==null)return p;try{return JSON.parse(y)}catch{return o+=1,l||(Ts("[save-progress] \u68C0\u6D4B\u5230\u635F\u574F\u5B58\u6863\uFF08\u975E\u6CD5 JSON\uFF09\uFF0C\u5DF2\u5BB9\u9519\u56DE\u9000\u9ED8\u8BA4\u503C key="+f),l=!0),p}},set(f,p){if(!Uo(f))return Ts("[save-progress] set \u6536\u5230\u975E\u6CD5 key\uFF0C\u62D2\u7EDD\u5199\u5165\uFF1A"+String(f)),!1;let y;try{y=JSON.stringify(p)}catch{return c+=1,Ts("[save-progress] \u503C\u4E0D\u53EF JSON \u5E8F\u5217\u5316\uFF08\u5FAA\u73AF\u5F15\u7528?\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+f),!1}if(y===void 0)return c+=1,Ts("[save-progress] \u503C\u5E8F\u5217\u5316\u4E3A undefined\uFF08\u5982\u7EAF undefined/\u51FD\u6570\uFF09\uFF0C\u62D2\u7EDD\u5199\u5165 key="+f),!1;let x=Du(y);if(x>s)return c+=1,Ts("[save-progress] \u503C\u8D85\u5B57\u8282\u4E0A\u9650\u62D2\u7EDD\u5199\u5165 key="+f+"\uFF08"+x+" > "+s+" bytes\uFF09"),!1;try{return r.setItem(u(f),y),!0}catch(w){return c+=1,ws("[save-progress] adapter.setItem \u5F02\u5E38\uFF0C\u5199\u5165\u5931\u8D25 key="+f,w),!1}},remove(f){if(Uo(f))try{r.removeItem(u(f))}catch(p){ws("[save-progress] adapter.removeItem \u5F02\u5E38\uFF08\u5DF2\u5FFD\u7565\uFF09key="+f,p)}},clear(){let f=h(),p=0;for(let y of f)try{r.removeItem(y),p+=1}catch(x){ws("[save-progress] clear \u65F6 removeItem \u5F02\u5E38\uFF08\u5DF2\u8DF3\u8FC7\uFF09fullKey="+y,x)}return p},probe(){return{namespace:n,maxValueBytes:s,usingMemoryAdapter:i,size:h().length,corruptRecoveries:o,rejectedWrites:c}}}}function Uo(t){return typeof t=="string"&&t.length>0}function Fu(t){return!!t&&typeof t.getItem=="function"&&typeof t.setItem=="function"&&typeof t.removeItem=="function"&&typeof t.keys=="function"}function ws(t,e){let n=e&&e.stack?e.stack:e&&e.message?e.message:e;typeof console!="undefined"&&typeof console.error=="function"&&console.error(t+(n?"\uFF1A"+n:""))}function Ts(t){typeof console!="undefined"&&typeof console.warn=="function"&&console.warn(t)}var Qn=[{id:"soda",name:"\u6C7D\u6C34",wholesale:20,basePrice:40,popularity:1,initial:!0},{id:"snack",name:"\u8FA3\u6761",wholesale:10,basePrice:25,popularity:1.2,initial:!0},{id:"bread",name:"\u9762\u5305",wholesale:30,basePrice:60,popularity:.8,initial:!0},{id:"ice",name:"\u51B0\u6DC7\u6DCB",wholesale:40,basePrice:90,popularity:.7,initial:!1},{id:"toy",name:"\u5C0F\u73A9\u5177",wholesale:80,basePrice:180,popularity:.35,initial:!1}];function Ke(t){return Qn.find(e=>e.id===t)}var Le={lengthSec:96,rushStartSec:30,rushEndSec:66,rushRampSec:3,daysPerSegment:3};function pc(t){let{rushStartSec:e,rushEndSec:n,rushRampSec:s}=Le;return t<=e-s||t>=n+s?0:t>=e&&t<=n?1:te.id===t)}function Ho(t){let e=n=>!!t[n];return{shelfCap:e("shelf2")?48:e("shelf1")?34:24,serveCooldownSec:e("speed2")?.32:e("speed1")?.42:.55,patienceMul:e("decor2")?1.3:e("decor1")?1.15:1,settleRepBonusTenth:e("decor2")?60:e("decor1")?30:0,flowMul:e("decor2")?1.12:1}}function Si(t){let e=t.priceMul,n=t.reputation==null?Qe.start:t.reputation,s=t.serveCapacity==null?26:t.serveCapacity,i=t.stockUnits==null?1/0:t.stockUnits,r=t.segment==null?1:t.segment,a=t.unlocked||Qn.filter(x=>x.initial).map(x=>x.id),l=((Le.lengthSec-(Le.rushEndSec-Le.rushStartSec))/cn.idleIntervalSec+(Le.rushEndSec-Le.rushStartSec)/cn.rushIntervalSec)*qo(e)*Wo(n),u=Math.min(l,s,i),h=a.map(x=>Ke(x)).filter(Boolean),d=h.reduce((x,w)=>x+w.popularity,0),f=h.reduce((x,w)=>x+(Math.round(w.basePrice*e)-w.wholesale)*(w.popularity/d),0),p=Math.round(u*f),y=le.rentBaseJiao+(r-1)*le.rentPerSegmentJiao;return{arrivals:l,served:u,grossJiao:p,rentJiao:y,profitJiao:p-y}}function Ve(t,e,n){return tn?n:t}function Ze(t){let e=t/10;return Number.isInteger(e)?String(e):e.toFixed(1)}var gc=1,Gu=2600;function As(t){let e=t.random;if(!e||typeof e.next!="function")throw new Error("[shop-core] \u5FC5\u987B\u6CE8\u5165\u53D7\u63A7\u968F\u673A\u6E90 random\uFF08next/range/reseed\uFF09");let n=0,s={nowMs:()=>n,elapsedMs:()=>n},i=new mi(s,{windowMs:Gu,maxCount:99}),r=[];function a(T,R){r.push(Object.assign({type:T,tMs:Math.round(n)},R||{}))}let o={phase:"title",day:1,cash:le.startCashJiao,repTenth:Qe.start*10,priceMul:1,stock:{},unlocked:Qn.filter(T=>T.initial).map(T=>T.id),upgrades:{},customers:[],dayTimeSec:0,rushFactor:0,serveCooldown:0,comboCount:0,prepBought:{},today:c(),lifetime:{days:0,served:0,angry:0,netJiao:0,upgradesBought:0},settle:null,summary:null,gameoverReason:null};function c(){return{revenueJiao:0,soldCostJiao:0,served:0,angry:0,stockout:0,walkaway:0,rescued:0,bigSales:0,maxCombo:0}}let l=1,u=0,h=!1,d=Ho(o.upgrades);function f(){d=Ho(o.upgrades)}function p(){let T=0;for(let R of Object.keys(o.stock))T+=o.stock[R];return T}function y(){return o.repTenth/10}function x(T){o.repTenth=Ve(o.repTenth+T,0,Qe.max*10)}function w(T){let R=o.phase;o.phase=T,a("phase_changed",{from:R,to:T})}function A(T){o.day=T,o.prepBought={},o.today=c(),o.customers=[],o.dayTimeSec=0,o.rushFactor=0,o.settle=null,o.summary=null,w("prep"),a("save_point",{})}function S(){let T=o.rushFactor>.5?cn.rushIntervalSec:cn.idleIntervalSec,R=qo(o.priceMul)*Wo(y())*d.flowMul;u=T/Math.max(R,.05)*e.range(cn.jitterMin,cn.jitterMax)}function _(){let T=o.unlocked.map(L=>Ke(L)),R=T.reduce((L,E)=>L+E.popularity,0),M=e.next()*R;for(let L of T)if(M-=L.popularity,M<=0)return L.id;return T[T.length-1].id}function k(){for(let T=0;TR.slot===T))return T;return-1}function C(){let T=_(),R=k();if(R<0){o.today.walkaway+=1,a("walkaway_full",{productId:T});return}let L=(o.rushFactor>.5?kn.rushSec:kn.idleSec)*d.patienceMul*e.range(.9,1.12),E={id:l++,productId:T,slot:R,mood:"queue",patienceSec:L,patienceMaxSec:L,timerSec:0,avatar:Math.floor(e.next()*4)%4,impatientFired:!1};(o.stock[T]||0)<=0&&(E.mood="stockout",E.timerSec=kn.stockoutLingerSec),o.customers.push(E),a("customer_arrive",{id:E.id,slot:R,productId:T,mood:E.mood})}function O(T){let R=o.customers.indexOf(T);R>=0&&o.customers.splice(R,1)}function q(T){o.dayTimeSec+=T,o.rushFactor=pc(o.dayTimeSec);let R=o.rushFactor>.5;if(R!==h&&(a(R?"rush_start":"rush_end",{}),h=R),o.serveCooldown>0&&(o.serveCooldown=Math.max(0,o.serveCooldown-T)),o.dayTimeSec>=Le.lengthSec){a("closing",{}),o.customers=[],ce();return}u-=T,u<=0&&(C(),S());for(let M=o.customers.length-1;M>=0;M--){let L=o.customers[M];if(L.mood==="queue"){if((o.stock[L.productId]||0)<=0){L.mood="stockout",L.timerSec=kn.stockoutLingerSec;continue}L.patienceSec-=T,!L.impatientFired&&L.patienceSec/L.patienceMaxSec<=kn.impatientRatio&&(L.impatientFired=!0,a("customer_impatient",{id:L.id,slot:L.slot})),L.patienceSec<=0&&(L.mood="leaving",L.timerSec=kn.graceSec,a("customer_grace",{id:L.id,slot:L.slot}))}else L.mood==="leaving"?(L.timerSec-=T,L.timerSec<=0&&(O(L),o.today.angry+=1,x(-Qe.angryLossTenth),a("angry_leave",{id:L.id,slot:L.slot,avatar:L.avatar,productId:L.productId,repLossTenth:Qe.angryLossTenth}))):L.mood==="stockout"&&(L.timerSec-=T,L.timerSec<=0&&(O(L),o.today.stockout+=1,x(-Qe.stockoutLossTenth),a("stockout_leave",{id:L.id,slot:L.slot,avatar:L.avatar,productId:L.productId,repLossTenth:Qe.stockoutLossTenth})))}o.comboCount=i.getCount(n)}function ce(){let T=o.today,R=Math.ceil(o.day/Le.daysPerSegment),M=le.rentBaseJiao+(R-1)*le.rentPerSegmentJiao,L=0;y()R.initial).map(R=>R.id),o.upgrades={},o.lifetime={days:0,served:0,angry:0,netJiao:0,upgradesBought:0},o.gameoverReason=null,f(),i.reset(),a("game_start",{continued:!1}),A(1),{ok:!0,continued:!1})},buyStock(T,R){let M=Math.max(1,Math.floor(R||1));if(o.phase!=="prep")return{ok:!1,reason:"phase"};let L=Ke(T);if(!L||!o.unlocked.includes(T))return{ok:!1,reason:"unknown_product"};if(p()+M>d.shelfCap)return{ok:!1,reason:"shelf_full"};let E=L.wholesale*M;return o.cash0)return{ok:!1,reason:"cooldown"};if(!o.unlocked.includes(T))return{ok:!1,reason:"unknown_product"};if((o.stock[T]||0)<=0)return a("tap_empty",{productId:T}),{ok:!1,reason:"no_stock"};let R=o.customers.filter(U=>U.productId===T&&(U.mood==="queue"||U.mood==="leaving")).sort((U,Y)=>U.id-Y.id)[0];if(!R)return a("tap_nocustomer",{productId:T}),{ok:!1,reason:"no_customer"};let M=R.mood==="leaving";o.stock[T]-=1;let L=i.hit(n);o.comboCount=L,o.today.maxCombo=Math.max(o.today.maxCombo,L);let E=Math.round(mc(T,o.priceMul)*yc(L));o.cash+=E,o.today.revenueJiao+=E,o.today.soldCostJiao+=Ke(T).wholesale,o.today.served+=1,o.lifetime.served+=1,M&&(o.today.rescued+=1),x(Qe.serveGainTenth+(M?Qe.rescueBonusTenth:0)),o.serveCooldown=d.serveCooldownSec;let N=E>=le.bigSaleJiao;return N&&(o.today.bigSales+=1),O(R),a("serve_ok",{id:R.id,slot:R.slot,avatar:R.avatar,productId:T,revenueJiao:E,combo:L,big:N,rescued:M}),{ok:!0,revenueJiao:E,combo:L,big:N,rescued:M,customerId:R.id}},confirmSettle(){if(o.phase!=="settle")return{ok:!1,reason:"phase"};let T=o.day;if(a("save_point",{}),T%Le.daysPerSegment===0){let R=T/Le.daysPerSegment;o.summary={segment:R,days:T,netJiao:o.lifetime.netJiao,served:o.lifetime.served,upgradesBought:o.lifetime.upgradesBought,reputation:y()},w("summary"),a("segment_end",{summary:o.summary})}else A(T+1);return{ok:!0}},confirmSummary(){return o.phase!=="summary"?{ok:!1,reason:"phase"}:(A(o.day+1),{ok:!0})},derived(){return d},reputation:y,totalStock:p,snapshotForSave(){return{v:gc,day:o.day,cash:o.cash,repTenth:o.repTenth,priceMul:o.priceMul,stock:Object.assign({},o.stock),unlocked:o.unlocked.slice(),upgrades:Object.assign({},o.upgrades),lifetime:Object.assign({},o.lifetime)}},restoreFromSave(T){return!T||T.v!==gc||typeof T.day!="number"||typeof T.cash!="number"||typeof T.repTenth!="number"||!T.unlocked||!Array.isArray(T.unlocked)||T.unlocked.length===0?!1:(o.cash=Math.floor(T.cash),o.repTenth=Ve(Math.floor(T.repTenth),0,Qe.max*10),o.priceMul=Ve(T.priceMul||1,le.priceMin,le.priceMax),o.stock=Object.assign({},T.stock||{}),o.unlocked=T.unlocked.filter(R=>!!Ke(R)),o.upgrades=Object.assign({},T.upgrades||{}),o.lifetime=Object.assign({days:0,served:0,angry:0,netJiao:0,upgradesBought:0},T.lifetime||{}),o.gameoverReason=null,f(),i.reset(),a("game_start",{continued:!0}),A(Math.max(1,Math.floor(T.day))),!0)}};return ne}var ks={open_shop:["\u5F00\u5F20\u55BD\u2014\u2014\u8857\u574A\u4EEC\u90FD\u7B49\u7740\u5462\uFF01","\u4ECA\u513F\u4E2A\u8FDB\u70B9\u5565\u597D\u8D27\uFF1F\u6211\u5FC3\u91CC\u6709\u6570\u3002","\u5C0F\u672C\u751F\u610F\uFF0C\u8D26\u53EF\u5F97\u7B97\u660E\u767D\u54AF\u3002"],day_start:["\u5F00\u95E8\u8FCE\u5BA2\uFF01\u90FD\u9EBB\u5229\u70B9\u513F~","\u54DF\uFF0C\u4ECA\u5929\u592A\u9633\u4E0D\u9519\uFF0C\u51C6\u662F\u4E2A\u597D\u65E5\u5B50\u3002"],idle_chat:["\u6162\u60A0\u60A0\u7684\u4E0B\u5348\uFF0C\u6700\u9002\u5408\u76D8\u8D26\u5566\u3002","\u9694\u58C1\u8001\u674E\u53C8\u6765\u8D4A\u8D26\uFF1F\u60F3\u5F97\u7F8E\u3002","\u8D27\u67B6\u64E6\u5F97\u9503\u4EAE\uFF0C\u770B\u7740\u5C31\u8212\u5766\u3002"],rush_start:["\u653E\u5B66\u5566\u653E\u5B66\u5566\uFF0C\u6253\u8D77\u7CBE\u795E\u6765\uFF01","\u4EBA\u90FD\u6D8C\u8FC7\u6765\u4E86\uFF0C\u624B\u4E0A\u522B\u505C\uFF01"],serve_ok:["\u597D\u561E\uFF0C\u62FF\u7A33\u5F53\uFF01","\u60A8\u6162\u8D70\uFF0C\u5E38\u6765\u554A~","\u8FD9\u5C31\u7ED9\u60A8\u62FF\uFF0C\u5FEB\u5F97\u5F88\uFF01"],combo_hot:["\u624B\u611F\u6765\u4E86\uFF0C\u8C01\u90FD\u522B\u62E6\u6211\uFF01","\u4E00\u4E2A\u63A5\u4E00\u4E2A\uFF0C\u8D8A\u5E72\u8D8A\u987A\u6E9C\uFF01"],big_sale:["\u54CE\u54DF\uFF0C\u5927\u4E3B\u987E\uFF01\u4ECA\u665A\u52A0\u4E2A\u9E21\u817F\uFF01","\u8FD9\u5355\u9876\u534A\u5929\u4E70\u5356\uFF0C\u7F8E\u6ECB\u6ECB~"],rescue:["\u522B\u8D70\u522B\u8D70\uFF0C\u8FD9\u5C31\u7ED9\u60A8\u62FF\u4E0A\uFF01","\u597D\u9669\u597D\u9669\uFF0C\u5DEE\u70B9\u513F\u9EC4\u4E86\u4E00\u5355\u3002"],angry:["\u54CE\u5440\uFF0C\u628A\u4EBA\u667E\u8DD1\u4E86\u2026\u2026\u5FC3\u75BC\u3002","\u7838\u62DB\u724C\u4E86\u7838\u62DB\u724C\u4E86\uFF0C\u5F97\u4E0A\u70B9\u5FC3\uFF01"],stockout:["\u7A7A\u8D27\u67B6\u6700\u6233\u5FC3\u7A9D\u5B50\uFF0C\u660E\u513F\u591A\u5907\u70B9\u3002","\u53C8\u5356\u65AD\u4E86\u2026\u2026\u662F\u597D\u4E8B\u4E5F\u662F\u574F\u4E8B\u3002"],settle_win:["\u4ECA\u513F\u8D26\u9762\u7EA2\u706B\uFF0C\u8BB0\u4E0A\u8BB0\u4E0A\uFF01","\u8F9B\u82E6\u4E00\u5929\uFF0C\u503C\u5F53\uFF01"],settle_lose:["\u8FD9\u8D26\u2026\u2026\u8D8A\u7B97\u8D8A\u5FC3\u51C9\u3002","\u7F5A\u5355\u90FD\u8D34\u8138\u4E0A\u4E86\uFF0C\u660E\u5929\u5F97\u6362\u4E2A\u6D3B\u6CD5\u3002"],upgrade:["\u820D\u4E0D\u5F97\u5B69\u5B50\u5957\u4E0D\u7740\u72FC\uFF0C\u5347\uFF01","\u9E1F\u67AA\u6362\u70AE\uFF0C\u54B1\u4E5F\u8BB2\u7A76\u4E00\u56DE\uFF01"],gameover:["\u5509\u2026\u2026\u5377\u5E18\u95E8\u4E00\u62C9\uFF0C\u4ECE\u5934\u518D\u6765\u5427\u3002"]},bp=Object.keys(ks).length;function bc(t){let e={};return function(s){let i=ks[s];if(!i||i.length===0)return"";if(i.length===1)return i[0];let r=Math.floor(t.next()*i.length)%i.length;return r===e[s]&&(r=(r+1)%i.length),e[s]=r,i[r]}}var Cs={paper:{r:246,g:231,b:201},paperHi:{r:255,g:246,b:227},cream:{r:255,g:243,b:220},ink:{r:91,g:70,b:54},inkSoft:{r:138,g:108,b:84},wood:{r:169,g:118,b:79},woodDark:{r:124,g:84,b:55},gold:{r:232,g:169,b:66},coin:{r:246,g:196,b:83},amber:{r:240,g:196,b:117},brick:{r:201,g:111,b:74},danger:{r:178,g:72,b:54},leaf:{r:133,g:158,b:94},sky:{r:243,g:217,b:168},shadow:{r:62,g:49,b:40},scrim:{r:46,g:35,b:27},smoke:{r:140,g:106,b:85}},xc=Object.keys(Cs);function Sc(){let t=xc.map(a=>Cs[a]),e={from:t,to:t.slice()},n={from:t,to:t.map(a=>jo(a,{hue:-10,sat:1.18,light:.9}))},s=0,i=r(0);function r(a){let o=Bo(e,n,a),c={};for(let l of xc)c[l]=Go(o,Cs[l]);return c}return{setRush(a){let o=Math.round(Math.max(0,Math.min(1,a))*25)/25;o!==s&&(s=o,i=r(o))},rushT(){return s},c(a,o){let c=i[a]||Cs.ink,l=o==null?1:o;return l>=1?`rgb(${c.r},${c.g},${c.b})`:`rgba(${c.r},${c.g},${c.b},${l})`},rgb(a){return i[a]||Cs.ink}}}var Yo={shopkeeperIdle:"shopkeeper-idle.jpg",shopkeeperWave:"shopkeeper-wave.jpg",customer0:"customer-kid.jpg",customer1:"customer-lady.jpg",customer2:"customer-grandpa.jpg",customer3:"customer-auntie.jpg",storefront:"storefront.jpg",itemSoda:"item-soda.jpg",itemSnack:"item-snack.jpg",itemBread:"item-bread.jpg",itemIce:"item-ice.jpg",itemToy:"item-toy.jpg",uiPanel:"ui-panel.jpg"},Cn={soda:"itemSoda",snack:"itemSnack",bread:"itemBread",ice:"itemIce",toy:"itemToy"};function vc(t){let e=t==null?"./assets/":t,n=Object.keys(Yo),s={},i=[];function r(a){return new Promise(o=>{if(typeof Image=="undefined"){s[a]=null,i.push(a),o(null);return}let c=new Image;c.onload=()=>{s[a]=c,o(c)},c.onerror=()=>{console.warn("[ref-assets] \u8D44\u4EA7\u52A0\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u7A0B\u5E8F\u5316\u56DE\u9000\uFF09\uFF1A"+Yo[a]),s[a]=null,i.push(a),o(null)},c.src=e+Yo[a]})}return Promise.all(n.map(r)).then(()=>({images:s,missing:i,loaded:n.length-i.length,total:n.length}))}function wc(t){let e=t.bundle,n=t.juice;function s(T){let R=bi({maxParticles:400});return R.init(e.deriveContextFor(T,T)),R}let i=s("fx-gold"),r=s("fx-cream"),a=s("fx-smoke"),o=[];function c(T,R,M){o.push({t:0,dur:Math.max(T,.001),ease:M&&M.ease||Ro.cubicOut,onUpdate:R,onDone:M&&M.onDone||null})}let l=new Map;function u(T,R){let M=l.get(T);return M||(M={state:{x:R==null?1:R,v:0},target:R==null?1:R,stiffness:320,damping:14},l.set(T,M)),M.state.x}function h(T,R,M){u(T);let L=l.get(T);L.state.v+=R,M!=null&&(L.target=M)}let d=[];function f(T){d.push({t:0,dur:T.dur||.3,fx:T.fx,fy:T.fy,tx:T.tx,ty:T.ty,arc:T.arc==null?46:T.arc,imageKey:T.imageKey||null,label:T.label||"",onArrive:T.onArrive||null})}let p=[],y=980;function x(T){let R=T.dur||.45,M=(T.tx-T.fx)/R,L=(T.ty-T.fy-.5*y*R*R)/R;p.push({proj:new hi({px:T.fx,py:T.fy,vx:M,vy:L},{gravity:{x:0,y}}),age:0,dur:R,tx:T.tx,ty:T.ty,imageKey:T.imageKey||null,onLand:T.onLand||null})}let w=[];function A(T,R,M,L,E){w.push({text:T,x:R,y:M,t:0,dur:.9,colorName:L||"gold",size:E||16})}let S=[];function _(T,R){S.push({x:T,y:R,t:0})}function k(T,R,M){i.spawnEmitter("burst",T,R,{count:M?26:13,angle:-Math.PI/2,spread:.85,speedMin:130,speedMax:M?320:240,gravity:420,lifeMin:.35,lifeMax:.7,sizeCurve:{kind:"decay",from:M?5.5:4,to:0,power:1.3}})}function C(T,R,M){r.spawnEmitter("burst",T,R,{count:M||10,angle:-Math.PI/2,spread:1.1,speedMin:40,speedMax:110,gravity:-30,lifeMin:.4,lifeMax:.8,sizeCurve:{kind:"decay",from:3,to:0,power:1}})}function O(T,R){a.spawnEmitter("burst",T,R,{count:12,angle:-Math.PI/2,spread:Math.PI,speedMin:25,speedMax:70,gravity:-18,drag:1.2,lifeMin:.5,lifeMax:1,sizeCurve:{kind:"easeInOut",from:5,to:1},alphaCurve:{kind:"decay",from:.7,to:0,power:1.5}})}function q(T,R){for(let M=o.length-1;M>=0;M--){let L=o[M];L.t+=T;let E=Math.min(L.t/L.dur,1);L.onUpdate(L.ease(E)),E>=1&&(L.onDone&&L.onDone(),o.splice(M,1))}for(let M of l.values())M.state=Za(M.state,M.target,{stiffness:M.stiffness,damping:M.damping},T);for(let M=d.length-1;M>=0;M--){let L=d[M];L.t+=R,L.t>=L.dur&&(L.onArrive&&L.onArrive(),d.splice(M,1))}for(let M=p.length-1;M>=0;M--){let L=p[M];L.age+=R,L.proj.step(R),L.age>=L.dur&&(L.onLand&&L.onLand(),p.splice(M,1))}for(let M=w.length-1;M>=0;M--){let L=w[M];L.t+=R,L.t>=L.dur&&w.splice(M,1)}for(let M=S.length-1;M>=0;M--)S[M].t+=T,S[M].t>=.32&&S.splice(M,1)}function ce(T,R){T.save(),T.fillStyle=R.c("coin"),i.render(T),T.fillStyle=R.c("cream"),r.render(T),T.fillStyle=R.c("smoke"),a.render(T),T.restore(),n.render(T)}return{easing:Ro,addTween:c,springVal:u,springKick:h,addFlight:f,addToss:x,addFloater:A,addTapRing:_,burstCoin:k,burstSparkle:C,burstSmoke:O,step:q,renderParticles:ce,view:{flights:d,tosses:p,floaters:w,tapRings:S},juice:n,particleProbe(){return{gold:i.particleCount(),cream:r.particleCount(),smoke:a.particleCount()}},dispose(){i.dispose(),r.dispose(),a.dispose()}}}function Tc(t){let e=t.getAudio,n=t.p6,s=t.baseUrl==null?"./assets/":t.baseUrl,i=new Set,r={loading:!1,ready:!1,failed:!1,gainIdle:null,gainRush:null,idleLevel:0,rushLevel:0,targetRush:0},a=null;function o(d){return a||(a=d.createGain(),a.gain.value=.5,a.connect(d.destination)),a}function c(){let d=e();if(!d||r.loading||r.ready||r.failed)return;r.loading=!0;function f(p){return fetch(s+p).then(y=>{if(!y.ok)throw new Error("HTTP "+y.status);return y.arrayBuffer()}).then(y=>d.decodeAudioData(y)).then(y=>{let x=d.createBufferSource();x.buffer=y,x.loop=!0;let w=d.createGain();return w.gain.value=0,x.connect(w),w.connect(d.destination),x.start(),w})}Promise.all([f("bgm-idle.mp3"),f("bgm-rush.mp3")]).then(([p,y])=>{r.gainIdle=p,r.gainRush=y,r.ready=!0,r.loading=!1}).catch(p=>{console.warn("[ref-audio] BGM \u88C5\u8F7D\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u65E0 BGM\uFF09\uFF1A"+(p&&p.message?p.message:p)),r.failed=!0,r.loading=!1})}function l(d,f,p){if(r.targetRush=f,!r.ready)return;let y=p?1:.35,x=.5*(1-f)*y,w=.55*f*y,A=Math.min(d/1.2,1);r.idleLevel+=(x-r.idleLevel)*A,r.rushLevel+=(w-r.rushLevel)*A,r.gainIdle.gain.value=r.idleLevel,r.gainRush.gain.value=r.rushLevel}function u(d,f,p,y,x,w,A){let S=d.currentTime+(A||0),_=d.createOscillator(),k=d.createGain();_.type=f,_.frequency.setValueAtTime(p,S),_.frequency.exponentialRampToValueAtTime(Math.max(y,1),S+x),k.gain.setValueAtTime(1e-4,S),k.gain.exponentialRampToValueAtTime(w,S+.012),k.gain.exponentialRampToValueAtTime(1e-4,S+x),_.connect(k),k.connect(o(d)),_.start(S),_.stop(S+x+.02)}function h(d,f){let p=e();if(!p)return;let y=f||{};switch(d){case"arrive":n.playSfx("blip");break;case"shelve":n.playSfx("thud");break;case"upgrade":n.playSfx("chime");break;case"coin":{let x=Math.min(y.combo||1,11),w=660*Math.pow(2,(x-1)*2/12);u(p,"sine",w,w*1.5,.16,.5),u(p,"sine",w*2,w*2.6,.1,.22,.03);break}case"bad":u(p,"sawtooth",220,90,.32,.3);break;case"rescue":u(p,"triangle",520,540,.07,.32),u(p,"triangle",660,690,.07,.32,.07),u(p,"triangle",880,920,.1,.34,.14);break;case"bigsale":u(p,"sine",130,80,.22,.5),u(p,"sine",1320,1760,.18,.3,.05);break;case"tick":u(p,"triangle",900,700,.045,.16);break;case"empty":u(p,"square",180,140,.08,.14);break;default:return}i.add(d)}return{startBgm:c,step:l,sfx:h,probe(){return{sfxKinds:Array.from(i),bgm:{ready:r.ready,failed:r.failed,idleLevel:r.idleLevel,rushLevel:r.rushLevel}}}}}var V=390,Zn=844,Oe={hud:{x:8,y:8,w:V-16,h:84},keeper:{x:14,y:398,w:124,h:160},bubble:{x:16,y:318,w:230,h:72},queue:[{x:186,y:470},{x:244,y:452},{x:302,y:470},{x:356,y:452}],avatarR:27,counter:{x:0,y:540,w:V,h:26},shelf:{x:8,y:574,w:V-16,h:158},bottom:{x:8,y:740,w:V-16,h:96},combo:{x:330,y:512}};function En(t){let e=t%3,n=Math.floor(t/3);return{x:16+e*124,y:584+n*76,w:116,h:68}}function kc(t){let e={x:12,y:116,w:V-24,h:706},n=196,s=46,i=n+t.length*s+26,r=i+64,a=42,o={x:V/2-110,y:e.y+e.h-70,w:220,h:54};return{panel:e,stockY:n,rowH:s,sliderY:i,upY:r,upRowH:a,btn:o}}function Cc(t){return{x:78,y:t+26,w:240,h:8}}function et(t,e,n,s,i,r){let a=Math.min(r,s/2,i/2);t.beginPath(),t.moveTo(e+a,n),t.arcTo(e+s,n,e+s,n+i,a),t.arcTo(e+s,n+i,e,n+i,a),t.arcTo(e,n+i,e,n,a),t.arcTo(e,n,e+s,n,a),t.closePath()}function W(t,e,n){t.font=`${n?"600 ":""}${e}px "PingFang SC","Microsoft YaHei",sans-serif`}function Xo(t,e,n,s,i,r){let a=e.width/e.height,o=i/r,c=0,l=0,u=e.width,h=e.height;a>o?(u=e.height*o,c=(e.width-u)/2):(h=e.width/o,l=(e.height-h)/2),t.drawImage(e,c,l,u,h,n,s,i,r)}function _n(t,e,n,s,i,r,a,o,c){t.save(),et(t,s,i,r,a,o),t.clip(),n?Xo(t,n,s,i,r,a):(t.fillStyle=e.c("amber"),t.fillRect(s,i,r,a),t.fillStyle=e.c("ink"),W(t,Math.min(a*.42,22),!0),t.textAlign="center",t.textBaseline="middle",t.fillText(c||"?",s+r/2,i+a/2)),t.restore()}function Ac(t,e,n,s,i,r,a){t.save(),t.beginPath(),t.arc(s,i,r,0,Math.PI*2),t.clip(),n?Xo(t,n,s-r,i-r,r*2,r*2):(t.fillStyle=e.c("sky"),t.fillRect(s-r,i-r,r*2,r*2),t.fillStyle=e.c("ink"),W(t,r,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a||"\u5BA2",s,i)),t.restore()}function _t(t,e,n,s,i,r,a,o){t.save(),et(t,s,i,r,a,o==null?14:o),t.clip();let c=n.images.uiPanel;c?t.drawImage(c,c.width*.2,c.height*.04,c.width*.78,c.height*.9,s,i,r,a):(t.fillStyle=e.c("paper"),t.fillRect(s,i,r,a)),t.restore(),t.strokeStyle=e.c("wood"),t.lineWidth=2,et(t,s,i,r,a,o==null?14:o),t.stroke()}function ln(t,e,n,s,i,r,a,o){let c=o||{},l=c.scale==null?1:c.scale;t.save(),t.translate(n+i/2,s+r/2),t.scale(l,l),et(t,-i/2,-r/2,i,r,r/2-6),t.fillStyle=c.disabled?e.c("inkSoft",.45):e.c(c.color||"brick"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("paperHi"),W(t,c.fontSize||20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(a,0,1),t.restore()}function $o(t,e,n,s,i,r,a,o,c){et(t,n,s,i,r,r/2),t.fillStyle=e.c(c||"shadow",.25),t.fill();let l=Ve(a,0,1);l>.01&&(et(t,n,s,Math.max(i*l,r),r,r/2),t.fillStyle=e.c(o||"gold"),t.fill())}function Bu(t,e,n){let s=n.images.storefront;s?Xo(t,s,0,0,V,Zn):(t.fillStyle=e.c("sky"),t.fillRect(0,0,V,Zn));let i=t.createLinearGradient(0,380,0,560);i.addColorStop(0,e.c("paper",0)),i.addColorStop(.5,e.c("paper",.28)),i.addColorStop(1,e.c("paper",.05)),t.fillStyle=i,t.fillRect(0,380,V,190)}function ju(t,e,n){let{core:s,fx:i,assets:r}=n,a=s.state,o=Oe.hud;_t(t,e,r,o.x,o.y,o.w,o.h,12),t.textBaseline="middle",t.fillStyle=e.c("ink"),W(t,16,!0),t.textAlign="left",t.fillText(`\u7B2C ${a.day} \u5929`,o.x+12,o.y+24);let c={x:o.x+86,y:o.y+18,w:168,h:11};$o(t,e,c.x,c.y,c.w,c.h,a.phase==="open"?a.dayTimeSec/Le.lengthSec:0,"amber");let l=c.x+Le.rushStartSec/Le.lengthSec*c.w,u=(Le.rushEndSec-Le.rushStartSec)/Le.lengthSec*c.w;t.fillStyle=e.c("brick",.4),t.fillRect(l,c.y+c.h+2,u,3),t.save();let h=i.springVal("hud-cash",1);t.translate(o.x+o.w-12,o.y+24),t.scale(h,h),t.textAlign="right",t.fillStyle=e.c("gold"),W(t,19,!0),t.fillText(`\xA5${Ze(a.cash)}`,0,0),t.restore(),t.textAlign="left",t.fillStyle=e.c("inkSoft"),W(t,13),t.fillText("\u53E3\u7891",o.x+12,o.y+58);let d=s.reputation(),f=d<30?"danger":d<55?"brick":"leaf";$o(t,e,o.x+48,o.y+52,150,12,d/100,f),t.fillStyle=e.c(f),W(t,13,!0),t.fillText(String(Math.round(d)),o.x+204,o.y+58),t.fillStyle=e.c("danger",.8),t.fillRect(o.x+48+150*.3-1,o.y+50,2,16),t.textAlign="right",t.fillStyle=e.c("inkSoft"),W(t,13),t.fillText(`\u4ECA\u65E5 ${a.today.served} \u5355 \xB7 \xA5${Ze(a.today.revenueJiao)}`,o.x+o.w-12,o.y+58)}function Ju(t,e,n){let{assets:s,ui:i,fx:r}=n,a=Oe.keeper,o=Math.sin(n.nowMs/620)*1.5;t.save(),t.translate(0,o),_t(t,e,s,a.x,a.y,a.w,a.h,14);let c=i.keeperWaveUntil>n.nowMs?s.images.shopkeeperWave:s.images.shopkeeperIdle;if(_n(t,e,c,a.x+6,a.y+6,a.w-12,a.h-34,10,"\u5E97\u4E3B"),t.fillStyle=e.c("ink"),W(t,13,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u8001\u677F\u5A18",a.x+a.w/2,a.y+a.h-15),t.restore(),i.bubbleText&&i.bubbleUntil>n.nowMs){let l=Oe.bubble,u=r.springVal("bubble",1),h=Ve((i.bubbleUntil-n.nowMs)/350,0,1);t.save(),t.globalAlpha=h,t.translate(l.x+l.w/2,l.y+l.h/2),t.scale(u,u),et(t,-l.w/2,-l.h/2,l.w,l.h,14),t.fillStyle=e.c("paperHi",.96),t.fill(),t.strokeStyle=e.c("wood"),t.lineWidth=2,t.stroke(),t.beginPath(),t.moveTo(-l.w/2+36,l.h/2-1),t.lineTo(-l.w/2+22,l.h/2+16),t.lineTo(-l.w/2+56,l.h/2-1),t.closePath(),t.fillStyle=e.c("paperHi",.96),t.fill(),t.fillStyle=e.c("ink"),W(t,14,!0),t.textAlign="center",t.textBaseline="middle";let d=i.bubbleText;d.length<=13?t.fillText(d,0,0):(t.fillText(d.slice(0,12),0,-9),t.fillText(d.slice(12,25),0,9)),t.restore()}}function Nu(t,e,n){let{core:s,assets:i}=n;if(s.state.phase==="open"){for(let r of s.state.customers){let a=Oe.queue[r.slot]||Oe.queue[0],o=n.nowMs-(n.customerBornMs[r.id]||n.nowMs),c=Ve(o/400,0,1),l=n.fx.easing.backOut(c),u=a.x+(1-l)*(V+40-a.x),h=a.y;r.mood==="leaving"&&(u+=Math.sin(n.nowMs/28)*2.5);let d=Oe.avatarR,f=r.mood==="queue"?Ve(r.patienceSec/r.patienceMaxSec,0,1):0;t.beginPath(),t.arc(u,h,d+4,0,Math.PI*2),t.strokeStyle=e.c("shadow",.3),t.lineWidth=4,t.stroke(),r.mood==="queue"&&(t.beginPath(),t.arc(u,h,d+4,-Math.PI/2,-Math.PI/2+f*Math.PI*2),t.strokeStyle=e.c(f>.55?"gold":f>.3?"brick":"danger"),t.lineWidth=4,t.stroke()),t.save(),r.mood==="stockout"&&(t.globalAlpha=.78),Ac(t,e,i.images["customer"+r.avatar],u,h,d,"\u5BA2"),t.restore();let p=46,y=44,x=u-p/2,w=h-d-y-9;et(t,x,w,p,y,9),t.fillStyle=e.c("paperHi",.95),t.fill(),t.strokeStyle=r.mood==="stockout"?e.c("danger"):e.c("wood"),t.lineWidth=1.5,t.stroke(),t.beginPath(),t.moveTo(u-6,w+y),t.lineTo(u,w+y+7),t.lineTo(u+6,w+y),t.closePath(),t.fillStyle=e.c("paperHi",.95),t.fill();let A=Ke(r.productId);_n(t,e,i.images[Cn[r.productId]],x+7,w+5,32,26,6,A?A.name[0]:"?"),t.fillStyle=e.c("inkSoft"),W(t,9),t.textAlign="center",t.textBaseline="middle",t.fillText(A?A.name:"",u,w+y-7),r.mood==="leaving"||r.mood==="queue"&&f<=.32?(t.fillStyle=e.c("danger"),W(t,r.mood==="leaving"?18:15,!0),t.textAlign="left",t.fillText(r.mood==="leaving"?"!!":"!",u+d+3,h-d+4)):r.mood==="stockout"&&(t.fillStyle=e.c("danger"),W(t,11,!0),t.textAlign="center",t.fillText("\u7F3A\u8D27\u2026",u,h+d+12))}for(let r of n.ui.ghosts){let a=Oe.queue[r.slot]||Oe.queue[0],c=Ve(1-(r.until-n.nowMs)/480,0,1),l=r.emote==="\u6012",u=a.x+(l?c*46:0),h=a.y-(l?0:c*22);t.save(),t.globalAlpha=(1-c)*.85,Ac(t,e,i.images["customer"+r.avatar],u,h,Oe.avatarR,"\u5BA2"),t.fillStyle=e.c(l?"danger":r.emote==="\u2026"?"inkSoft":"gold"),W(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(r.emote,u+Oe.avatarR+8,h-Oe.avatarR+2),t.restore()}}}function zu(t,e){let n=Oe.counter;t.fillStyle=e.c("wood"),t.fillRect(n.x,n.y,n.w,n.h),t.fillStyle=e.c("woodDark"),t.fillRect(n.x,n.y+n.h-6,n.w,6),t.fillStyle=e.c("paperHi",.18),t.fillRect(n.x,n.y,n.w,3)}function Uu(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state,o=Oe.shelf;_t(t,e,i,o.x,o.y,o.w,o.h,14),t.fillStyle=e.c("inkSoft"),W(t,11),t.textAlign="left",t.textBaseline="middle";let c=`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`;t.fillText(c,o.x+10,o.y+10),a.phase==="open"&&(t.textAlign="right",t.fillText("\u70B9\u5546\u54C1 \u2192 \u9012\u7ED9\u6392\u961F\u7684\u5BA2\u4EBA",o.x+o.w-10,o.y+10));for(let l=0;l<6;l++){let u=En(l),h=a.unlocked[l];if(!h){t.save(),t.setLineDash([5,4]),et(t,u.x,u.y,u.w,u.h,10),t.strokeStyle=e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.restore(),t.fillStyle=e.c("inkSoft",.6),W(t,12),t.textAlign="center",t.fillText("\u5347\u7EA7\u89E3\u9501",u.x+u.w/2,u.y+u.h/2);continue}let d=Ke(h),f=a.stock[h]||0,p=r.springVal("slot-"+h,1);t.save(),t.translate(u.x+u.w/2,u.y+u.h/2),t.scale(p,p),t.translate(-(u.x+u.w/2),-(u.y+u.h/2)),et(t,u.x,u.y,u.w,u.h,10),t.fillStyle=f>0?e.c("paperHi",.92):e.c("shadow",.14),t.fill(),t.strokeStyle=f>0?e.c("wood"):e.c("inkSoft",.5),t.lineWidth=1.5,t.stroke(),t.save(),f<=0&&(t.globalAlpha=.45),_n(t,e,i.images[Cn[h]],u.x+6,u.y+7,44,44,8,d.name[0]),t.restore(),t.fillStyle=e.c("ink"),W(t,13,!0),t.textAlign="left",t.fillText(d.name,u.x+56,u.y+16),t.fillStyle=e.c("gold"),W(t,13,!0),t.fillText(`\xA5${Ze(Math.round(d.basePrice*a.priceMul))}`,u.x+56,u.y+34),f>0?(t.fillStyle=e.c("inkSoft"),W(t,12),t.fillText(`\xD7${f}`,u.x+56,u.y+52)):(t.fillStyle=e.c("danger"),W(t,12,!0),t.fillText("\u7F3A\u8D27",u.x+56,u.y+52)),t.restore()}}function Vu(t,e,n){let{assets:s,ui:i}=n,r=Oe.bottom;_t(t,e,s,r.x,r.y,r.w,r.h,14),t.fillStyle=e.c("brick"),W(t,24,!0),t.textAlign="left",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",r.x+16,r.y+30),t.fillStyle=e.c("inkSoft"),W(t,12),t.fillText(i.tickerText||"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",r.x+16,r.y+62),t.textAlign="right",W(t,11),t.fillText("ref-r1",r.x+r.w-12,r.y+r.h-14)}function qu(t,e,n){let{core:s,fx:i}=n;if(s.state.phase!=="open"||s.state.comboCount<2)return;let r=i.springVal("combo",1),a=Oe.combo;t.save(),t.translate(a.x,a.y),t.scale(r,r),t.rotate(-.08),et(t,-44,-20,88,40,12),t.fillStyle=e.c("gold"),t.fill(),t.strokeStyle=e.c("shadow",.5),t.lineWidth=2,t.stroke(),t.fillStyle=e.c("ink"),W(t,17,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u8FDE\u51FB\xD7${s.state.comboCount}`,0,1),t.restore()}function _s(t,e,n){t.fillStyle=e.c("scrim",n==null?.45:n),t.fillRect(0,0,V,Zn)}function Wu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state,c=kc(o.unlocked),l=a.panelSlide;t.save(),t.translate(0,(1-l)*520),_s(t,e,.35*l),_t(t,e,i,c.panel.x,c.panel.y,c.panel.w,c.panel.h,16),t.fillStyle=e.c("ink"),W(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u5F00\u5E02\u51C6\u5907`,V/2,c.panel.y+30),W(t,14),t.fillStyle=e.c("gold"),t.fillText(`\u8D44\u91D1 \xA5${Ze(o.cash)}`,V/2-80,c.panel.y+60),t.fillStyle=e.c("inkSoft"),t.fillText(`\u8D27\u67B6 ${s.totalStock()}/${s.derived().shelfCap}`,V/2+80,c.panel.y+60);for(let d=0;d=f.costJiao,k=r.springVal("z:up-"+f.id,1);t.save(),t.translate(x+84,w+18),t.scale(k,k),et(t,-84,-18,168,36,9),t.fillStyle=A?e.c("leaf",.3):S?e.c("shadow",.12):e.c("paperHi",.95),t.fill(),t.strokeStyle=A?e.c("leaf"):!S&&_?e.c("gold"):e.c("inkSoft",.4),t.lineWidth=A||!S&&_?2:1,t.stroke(),t.fillStyle=S?e.c("inkSoft",.6):e.c("ink"),W(t,12,!0),t.textAlign="left",t.textBaseline="middle",t.fillText(f.name,-76,-5),W(t,10),t.fillStyle=A?e.c("leaf"):S?e.c("inkSoft",.6):_?e.c("gold"):e.c("danger",.8),t.fillText(A?"\u5DF2\u8D2D \u2713":S?"\u9700 "+(xi(f.requires)||{}).name:`\xA5${Ze(f.costJiao)}`,-76,9),t.restore()}ln(t,e,c.btn.x,c.btn.y,c.btn.w,c.btn.h,"\u5F00\u95E8\u8425\u4E1A\uFF01",{color:"brick",fontSize:21,scale:r.springVal("z:openShop",1)}),t.restore()}function Hu(t,e,n){let{core:s,assets:i,fx:r,ui:a}=n,o=s.state.settle;if(!o)return;let c=a.settleAnim;_s(t,e,.5);let l={x:30,y:170,w:V-60,h:470};_t(t,e,i,l.x,l.y,l.w,l.h,16),t.fillStyle=e.c("ink"),W(t,20,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(`\u7B2C ${o.day} \u5929 \xB7 \u6253\u70CA\u7ED3\u7B97`,V/2,l.y+32);function u(p,y,x,w,A){let S=l.y+76+p*38;t.textAlign="left",t.fillStyle=e.c("inkSoft"),W(t,14),t.fillText(y,l.x+26,S),t.textAlign="right",t.fillStyle=e.c(w),W(t,16,!0);let _=Math.round(x*c);t.fillText(`${A}\xA5${Ze(Math.abs(_))}`,l.x+l.w-26,S)}u(0,"\u8425\u4E1A\u6536\u5165",o.revenueJiao,"leaf","+"),u(1,"\u8D27\u54C1\u6210\u672C",o.soldCostJiao,"inkSoft","\u2212"),u(2,"\u623F\u79DF",o.rentJiao,"inkSoft","\u2212");let h=3;o.fineJiao>0&&(t.save(),t.translate(Math.sin(n.nowMs/40)*(c<1?1.5:0),0),u(h,"\u5DEE\u8BC4\u7F5A\u6CA1",o.fineJiao,"danger","\u2212"),t.restore(),h+=1);let d=l.y+76+h*38-14;t.strokeStyle=e.c("inkSoft",.4),t.lineWidth=1,t.beginPath(),t.moveTo(l.x+26,d),t.lineTo(l.x+l.w-26,d),t.stroke();let f=Math.round(o.netJiao*c);t.textAlign="center",t.fillStyle=e.c(o.netJiao>=0?"leaf":"danger"),W(t,28,!0),t.fillText(`${f>=0?"+":"\u2212"}\xA5${Ze(Math.abs(f))}`,V/2,d+38),t.fillStyle=e.c("inkSoft"),W(t,12),t.fillText(`\u63A5\u5F85 ${o.served} \xB7 \u5DEE\u8BC4 ${o.angry} \xB7 \u7F3A\u8D27\u6D41\u5931 ${o.stockout} \xB7 \u6551\u5355 ${o.rescued} \xB7 \u6700\u9AD8\u8FDE\u51FB ${o.maxCombo}`,V/2,d+74),t.fillText(`\u53E3\u7891\u56DE\u6696 +${(o.repBackTenth/10).toFixed(1)} \u2192 ${Math.round(o.reputation)}`,V/2,d+96),ln(t,e,V/2-90,l.y+l.h-70,180,48,"\u7EE7\u7EED",{color:"brick",scale:r.springVal("z:confirmSettle",1)})}function Yu(t,e,n){let{core:s,assets:i,fx:r}=n,a=s.state.summary;if(!a)return;_s(t,e,.5);let o={x:36,y:240,w:V-72,h:330};_t(t,e,i,o.x,o.y,o.w,o.h,16),t.fillStyle=e.c("ink"),t.textAlign="center",t.textBaseline="middle",W(t,20,!0),t.fillText(`\u7B2C ${a.segment} \u4E2A\u4E09\u5929 \xB7 \u5C0F\u7ED3`,V/2,o.y+36),W(t,14),t.fillStyle=e.c("inkSoft"),t.fillText("\u7D2F\u8BA1\u51C0\u5229",V/2,o.y+84),t.fillStyle=e.c(a.netJiao>=0?"leaf":"danger"),W(t,30,!0),t.fillText(`${a.netJiao>=0?"+":"\u2212"}\xA5${Ze(Math.abs(a.netJiao))}`,V/2,o.y+118),t.fillStyle=e.c("inkSoft"),W(t,13),t.fillText(`\u7D2F\u8BA1\u63A5\u5F85 ${a.served} \u5355 \xB7 \u5347\u7EA7 ${a.upgradesBought} \u9879 \xB7 \u53E3\u7891 ${Math.round(a.reputation)}`,V/2,o.y+162),t.fillStyle=e.c("ink"),W(t,14),t.fillText(a.netJiao>=0?"\u5C0F\u5E97\u7AD9\u7A33\u811A\u8DDF\u4E86\uFF0C\u7EE7\u7EED\uFF01":"\u5165\u4E0D\u6577\u51FA\u2026\u2026\u5F97\u6362\u4E2A\u6253\u6CD5\u3002",V/2,o.y+200),ln(t,e,V/2-90,o.y+o.h-66,180,48,"\u7EE7\u7EED\u7ECF\u8425",{color:"brick",scale:r.springVal("z:confirmSummary",1)})}function $u(t,e,n){let{assets:s,fx:i,hasSave:r}=n;_s(t,e,.25);let a={x:45,y:150,w:V-90,h:120};_t(t,e,s,a.x,a.y,a.w,a.h,18),t.fillStyle=e.c("brick"),W(t,40,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u6696\u9633\u5C0F\u5356\u90E8",V/2,a.y+52),t.fillStyle=e.c("inkSoft"),W(t,14),t.fillText("\u4E00\u95F4\u5C0F\u5E97\u7684\u70DF\u706B\u65E5\u5E38",V/2,a.y+92);let o={x:V/2-80,y:300,w:160,h:200};_t(t,e,s,o.x,o.y,o.w,o.h,16),_n(t,e,s.images.shopkeeperWave,o.x+8,o.y+8,o.w-16,o.h-16,12,"\u5E97\u4E3B"),ln(t,e,V/2-110,560,220,56,"\u5F00\u5E97\uFF01",{color:"brick",fontSize:22,scale:i.springVal("z:newGame",1)}),r&&ln(t,e,V/2-110,632,220,50,"\u7EE7\u7EED\u7ECF\u8425",{color:"leaf",fontSize:18,scale:i.springVal("z:continue",1)}),t.fillStyle=e.c("paperHi",.8),W(t,11),t.fillText("\u70B9\u51FB\u4EFB\u610F\u6309\u94AE\u5F00\u58F0 \xB7 ref-r1",V/2,716)}function Xu(t,e,n){let{core:s,assets:i,fx:r}=n;_s(t,e,.6);let a={x:36,y:220,w:V-72,h:360};_t(t,e,i,a.x,a.y,a.w,a.h,16),t.fillStyle=e.c("danger"),W(t,26,!0),t.textAlign="center",t.textBaseline="middle",t.fillText("\u505C\u4E1A\u6574\u987F\u2026",V/2,a.y+44),t.fillStyle=e.c("ink"),W(t,14);let o=s.state.gameoverReason==="reputation"?"\u5DEE\u8BC4\u592A\u591A\uFF0C\u8857\u574A\u4EEC\u4E0D\u6765\u4E86\u3002":"\u73B0\u91D1\u89C1\u5E95\uFF0C\u623F\u79DF\u4ED8\u4E0D\u51FA\u4E86\u3002";t.fillText(o,V/2,a.y+92),t.fillStyle=e.c("inkSoft"),W(t,13),t.fillText(`\u7ECF\u8425 ${s.state.lifetime.days} \u5929 \xB7 \u7D2F\u8BA1\u63A5\u5F85 ${s.state.lifetime.served} \u5355`,V/2,a.y+130),t.fillText(`\u7D2F\u8BA1\u51C0\u5229 \xA5${Ze(s.state.lifetime.netJiao)}`,V/2,a.y+156),t.fillStyle=e.c("ink"),W(t,14),t.fillText("\u5377\u5E18\u95E8\u62C9\u4E0B\uFF0C\u4F46\u65E5\u5B50\u8FD8\u5F97\u8FC7\u2014\u2014",V/2,a.y+208),t.fillText("\u6362\u4E2A\u601D\u8DEF\uFF0C\u518D\u5F00\u4E00\u56DE\uFF01",V/2,a.y+230),ln(t,e,V/2-100,a.y+a.h-70,200,50,"\u91CD\u65B0\u5F00\u5F20",{color:"brick",scale:r.springVal("z:restart",1)})}function Ku(t,e,n){let{fx:s,assets:i}=n;for(let r of s.view.flights){let a=s.easing.quadOut(Ve(r.t/r.dur,0,1)),o=r.fx+(r.tx-r.fx)*a,c=r.fy+(r.ty-r.fy)*a-r.arc*4*a*(1-a);_n(t,e,r.imageKey?i.images[r.imageKey]:null,o-16,c-16,32,32,7,r.label)}for(let r of s.view.tosses){let a=r.proj.state;_n(t,e,r.imageKey?i.images[r.imageKey]:null,a.px-14,a.py-14,28,28,6,"")}}function Qu(t,e,n){for(let s of n.fx.view.floaters){let i=Ve(s.t/s.dur,0,1);t.save(),t.globalAlpha=1-i*i,t.fillStyle=e.c(s.colorName),W(t,s.size,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,s.x,s.y-34*n.fx.easing.cubicOut(i)),t.restore()}}function Zu(t,e,n){for(let s of n.fx.view.tapRings){let i=Ve(s.t/.32,0,1);t.save(),t.globalAlpha=(1-i)*.8,t.beginPath(),t.arc(s.x,s.y,6+22*n.fx.easing.quadOut(i),0,Math.PI*2),t.strokeStyle=e.c("paperHi"),t.lineWidth=2.5,t.stroke(),t.restore()}}function ed(t,e,n){let s=n.ui.banner;if(!s||s.until<=n.nowMs)return;let i=(s.until-n.nowMs)/s.dur,r=1-i,a=V/2+(r<.2?(.2-r)*5*V:r>.8?-(r-.8)*5*V:0);t.save(),t.globalAlpha=Math.min(i*4,1),t.fillStyle=e.c(s.color||"brick",.88),et(t,a-110,270,220,54,12),t.fill(),t.fillStyle=e.c("paperHi"),W(t,24,!0),t.textAlign="center",t.textBaseline="middle",t.fillText(s.text,a,297),t.restore()}function _c(t,e){let n=e.pal,s=e.core.state.phase,i=e.fx.juice.getShakeOffset();t.save(),t.translate(i.x,i.y),Bu(t,n,e.assets),ju(t,n,e),Ju(t,n,e),Nu(t,n,e),zu(t,n),Uu(t,n,e),Vu(t,n,e),qu(t,n,e),Ku(t,n,e),s==="prep"?Wu(t,n,e):s==="settle"?Hu(t,n,e):s==="summary"?Yu(t,n,e):s==="title"?$u(t,n,e):s==="gameover"&&Xu(t,n,e),Qu(t,n,e),ed(t,n,e),e.fx.renderParticles(t,n),Zu(t,n,e),t.restore();let r=n.rushT();r>.02&&(t.fillStyle=n.c("brick",.05+r*.07),t.fillRect(0,0,V,Zn))}function Ec(t,e){let n=t.state,s=[];function i(r,a,o,c,l){s.push({id:r,kind:a,x:o.x+o.w/2,y:o.y+o.h/2,hw:o.w/2,hh:o.h/2,payload:c||null,z:l==null?1:l})}if(n.phase==="open")for(let r=0;ri.push(d);s.startGame(null),r("startGame");let a={soda:7,snack:8,bread:5};for(let d of Object.keys(a)){let f=s.buyStock(d,a[d]);if(r(`buyStock(${d},${a[d]})`),!f.ok)return h(`\u8FDB\u8D27\u5931\u8D25:${d}:${f.reason}`)}if(s.setPrice(1.15),r("setPrice(1.15)"),!s.startDay().ok)return h("startDay\u5931\u8D25");r("startDay");let o=0;for(;s.state.phase==="open"&&o++<6e3;){if(s.update(Pc),s.state.serveCooldown>0)continue;let d=s.state.customers.find(f=>(f.mood==="queue"||f.mood==="leaving")&&(s.state.stock[f.productId]||0)>0);d&&s.serve(d.productId).ok&&r(`serve(${d.productId})`)}if(s.state.phase!=="settle")return h(`\u672A\u5230\u8FBE\u65E5\u7ED3(phase=${s.state.phase})`);let c=s.state.settle.served;if(s.confirmSettle(),r("confirmSettle"),s.state.phase!=="prep")return h(`\u65E5\u7ED3\u540E\u672A\u56DE prep(phase=${s.state.phase})`);let l=Jt.filter(d=>!d.requires&&s.state.cash>=d.costJiao).sort((d,f)=>d.costJiao-f.costJiao)[0];if(!l)return h(`\u7B2C2\u5929\u5F00\u5E02\u524D\u65E0\u53EF\u8D1F\u62C5\u5347\u7EA7(cash=${s.state.cash})`);let u=s.buyUpgrade(l.id);if(r(`buyUpgrade(${l.id})`),!u.ok)return h(`\u5347\u7EA7\u8D2D\u4E70\u5931\u8D25:${u.reason}`);return s.drainEvents(),{ok:i.length<=n,opCount:i.length,ops:i,day:s.state.day,upgradeId:l.id,served:c,cashJiao:s.state.cash,reputation:s.reputation(),failReason:i.length<=n?null:`\u64CD\u4F5C\u6570\u8D85\u9650:${i.length}>${n}`};function h(d){return{ok:!1,opCount:i.length,ops:i,day:s.state.day,upgradeId:null,served:0,cashJiao:s.state.cash,reputation:s.reputation(),failReason:d}}}function Rc(t,e){let n=e==null?4:e,s=As({random:new An(t==null?4422:t)});s.startGame(null);let i=0,r=0,a=[];for(let o=0;onull),a=s.collision,o=s.juice,c=s.palettePost,l=s.audioMusic,u=s.save,h=null,d=null,f=0,p=0,y=null,x=null,w=null,A=null,S=null,_=null,k=null,C=null,O=null,q=null,ce=null,ne=null,T=!1,R=!1,M={bubbleText:"",bubbleUntil:0,bubbleShownAt:-9999,keeperWaveUntil:0,tickerText:"\u5C0F\u672C\u751F\u610F\uFF0C\u7528\u5FC3\u7ECF\u8425\u3002",banner:null,panelSlide:1,settleAnim:0,ghosts:[]},L={},E={frames:0,taps:0,tapFeedbackMaxFrames:0,comboUiShown:0,hitStopCount:0,rushPaletteSeen:!1,bgmCrossfadeSeen:!1,linesShown:0,bufferedServeReplays:0},N=[];function U(G){N.push(G),N.length>240&&N.shift()}function Y(G,F){if(!F&&p-M.bubbleShownAt<700&&M.bubbleUntil>p)return;let j=x(G);j&&(M.bubbleText=j,M.bubbleUntil=p+2600,M.bubbleShownAt=p,M.tickerText=j,E.linesShown+=1,A.springKick("bubble",2.2))}function se(G,F,j){M.banner={text:G,color:F,dur:j||1500,until:p+(j||1500)}}function Ne(){return!!u.get("profile")}let ge=[];function Re(){ge=Ec(y,{hasSave:Ne()}),a.spatial.clear();for(let G of ge)a.spatial.insert(G.id,{x:G.x,y:G.y,hw:G.hw,hh:G.hh})}function be(G,F){let j=a.spatial.queryPoint(G,F),J=null;for(let Fe of j){let Te=ge.find(li=>li.id===Fe.id);Te&&Ya({x:G,y:F,hw:0,hh:0},{x:Te.x,y:Te.y,hw:Te.hw,hh:Te.hh}).hit&&(!J||Te.z>J.z)&&(J=Te)}return J}let ct=null;function Yn(){if(!ct||y.state.phase!=="open"||y.state.serveCooldown>0)return;let G=p-ct.tMs<=260,F=s.gamefeel;if(G&&F.inputBuffer&&F.inputBuffer.consume("pointerdown",p)){let j=ct.productId;ct=null,y.serve(j).ok&&(E.bufferedServeReplays+=1)}else G||(ct=null)}let jt=null;function $n(G,F){let j=Math.max(0,Math.min(1,(G-F.x)/F.w));y.setPrice(le.priceMin+j*(le.priceMax-le.priceMin))}function Ss(G){E.taps+=1;let F=i.frameCount();A.addTapRing(G.x,G.y);let j=be(G.x,G.y);if(!j){R&&S.sfx("tick"),tn(F);return}switch(A.springKick("z:"+j.id,-2.6),j.kind){case"serve":{let J=j.payload.productId;A.springKick("slot-"+J,-3.2);let Fe=y.serve(J);if(!Fe.ok){if(Fe.reason==="cooldown")ct={productId:J,tMs:G.tMs};else if(Fe.reason==="no_stock"){S.sfx("empty");let Te=En(y.state.unlocked.indexOf(J));A.addFloater("\u7F3A\u8D27\u2026",Te.x+Te.w/2,Te.y,"danger",13)}else if(Fe.reason==="no_customer"){S.sfx("tick");let Te=En(y.state.unlocked.indexOf(J));A.addFloater("\u6CA1\u4EBA\u8981\u8FD9\u4E2A",Te.x+Te.w/2,Te.y,"inkSoft",12)}}break}case"stockInc":{let J=y.buyStock(j.payload.productId,1);J.ok?S.sfx("tick"):(S.sfx("empty"),A.addFloater(J.reason==="no_cash"?"\u94B1\u4E0D\u591F\u4E86":"\u8D27\u67B6\u6EE1\u4E86",j.x,j.y-22,"danger",13));break}case"stockDec":{let J=y.refundStock(j.payload.productId,1);S.sfx(J.ok?"tick":"empty");break}case"slider":jt={track:j.payload.track},$n(G.x,j.payload.track),S.sfx("tick");break;case"upgrade":{let J=y.buyUpgrade(j.payload.upgradeId);!J.ok&&J.reason==="no_cash"?(S.sfx("empty"),A.addFloater("\u94B1\u4E0D\u591F\u4E86",j.x,j.y-24,"danger",13)):!J.ok&&J.reason==="requires"?(S.sfx("empty"),A.addFloater("\u8981\u5148\u4E70\u524D\u7F6E",j.x,j.y-24,"inkSoft",12)):!J.ok&&J.reason==="owned"&&S.sfx("tick");break}case"btn":S.sfx("tick"),nn(j.payload.action);break;default:break}tn(F)}function tn(G){let F=Math.max(i.frameCount()-G,0)+1;E.tapFeedbackMaxFrames=Math.max(E.tapFeedbackMaxFrames,F)}function nn(G){switch(G){case"newGame":y.startGame(null);break;case"continue":y.startGame(u.get("profile"));break;case"openShop":y.startDay();break;case"confirmSettle":y.confirmSettle();break;case"confirmSummary":y.confirmSummary();break;case"restart":y.startGame(null);break;default:break}}function sn(G){let F=Oe.queue[G]||Oe.queue[0];return{x:F.x,y:F.y}}function Xn(G){for(let F of G)switch(U(F),F.type){case"customer_arrive":{L[F.id]=p,S.sfx("arrive");break}case"serve_ok":{let j=En(y.state.unlocked.indexOf(F.productId)),J=sn(F.slot);delete L[F.id],M.ghosts.push({slot:F.slot,avatar:F.avatar,emote:F.rescued?"!":"\u266A",until:p+460}),A.addFlight({fx:j.x+28,fy:j.y+28,tx:J.x,ty:J.y,dur:.28,imageKey:Cn[F.productId],label:(Ke(F.productId)||{name:"?"}).name[0],onArrive:()=>{A.burstCoin(J.x,J.y,F.big),A.addFloater(`+\xA5${Ze(F.revenueJiao)}`,J.x,J.y-30,"gold",F.big?19:15),S.sfx("coin",{combo:F.combo}),A.springKick("hud-cash",1.8),F.rescued&&(A.burstSparkle(J.x,J.y-10,14),S.sfx("rescue"))}}),F.combo>=2&&(A.springKick("combo",2.4),F.combo===3&&(E.comboUiShown+=1)),F.big?(o.hitStop(.09,.12),o.shakeScreen(.22,5,26),o.flashScreen(.12,.18),E.hitStopCount+=1,S.sfx("bigsale"),M.keeperWaveUntil=p+1300,Y("big_sale",!0)):F.rescued?Y("rescue",!0):F.combo>=3&&F.combo%3===0?Y("combo_hot"):F.combo===1&&y.state.today.served%4===1&&Y("serve_ok");break}case"angry_leave":{let j=sn(F.slot);delete L[F.id],M.ghosts.push({slot:F.slot,avatar:F.avatar,emote:"\u6012",until:p+520}),A.burstSmoke(j.x,j.y),A.addFloater("\u5DEE\u8BC4\uFF01",j.x,j.y-36,"danger",15),o.shakeScreen(.16,3,24),S.sfx("bad"),Y("angry",!0);break}case"stockout_leave":{let j=sn(F.slot);delete L[F.id],M.ghosts.push({slot:F.slot,avatar:F.avatar,emote:"\u2026",until:p+480}),A.burstSmoke(j.x,j.y),A.addFloater("\u767D\u8DD1\u4E00\u8D9F\u2026",j.x,j.y-36,"danger",13),S.sfx("empty"),y.state.today.stockout%3===1&&Y("stockout");break}case"customer_grace":S.sfx("tick");break;case"walkaway_full":A.addFloater("\u5E97\u91CC\u6324\u4E0D\u4E0B\u2026",372,420,"inkSoft",12);break;case"rush_start":se("\u9AD8\u5CF0\u6765\u4E86\uFF01","brick",1600),Y("rush_start",!0);break;case"rush_end":se("\u7F13\u8FC7\u6765\u4E86~","leaf",1300);break;case"closing":se("\u6253\u70CA\u54AF~","wood",1500);break;case"day_start":{Y("day_start",!0),M.keeperWaveUntil=p+1200;let j=0;for(let J=0;J{},{onDone:()=>A.addToss({fx:-24,fy:600,tx:li.x+28,ty:li.y+28,dur:.42,imageKey:Cn[Fe],onLand:()=>{A.springKick("slot-"+Fe,-3.4),S.sfx("shelve")}})}),j+=.07}}break}case"day_end":{M.settleAnim=0,A.addTween(1.1,j=>{M.settleAnim=j}),Y(F.settle.netJiao>=0?"settle_win":"settle_lose",!0);break}case"fined":S.sfx("bad");break;case"upgrade_bought":{A.burstSparkle(V/2,430,F.first?22:14),A.addFloater("\u5347\u7EA7\uFF01",V/2,410,"gold",18),S.sfx("upgrade"),M.keeperWaveUntil=p+1300,Y("upgrade",!0);break}case"price_changed":break;case"phase_changed":{F.to==="prep"&&(M.panelSlide=0,A.addTween(.45,j=>{M.panelSlide=j}),(F.from==="title"||F.from==="gameover")&&Y("open_shop",!0)),M.ghosts.length=0;break}case"gameover":u.remove("profile"),S.sfx("bad"),Y("gameover",!0);break;case"save_point":u.set("profile",y.snapshotForSave());break;case"segment_end":break;default:break}}let Kn=7;async function go(G){h=G,d=G.ctx,f=G.seed,y=As({random:i.deriveContextFor("shop-core","shop-core").random}),x=bc(i.deriveContextFor("shop-lines","shop-lines").random),w=Sc(),A=wc({bundle:i,juice:o}),S=Tc({getAudio:()=>r(),p6:l}),_=await vc("./assets/"),k=Mc(),C=Rc(),O=(()=>{let j=Si({priceMul:le.priceMin}),J=Si({priceMul:1}),Fe=Si({priceMul:le.priceMax});return{loProfit:j.profitJiao,midProfit:J.profitJiao,hiProfit:Fe.profitJiao,twoSidedLoss:j.profitJiao<0&&Fe.profitJiao<0&&J.profitJiao>0}})();let F=d.getInput();q=F.on("pointerdown",j=>Ss(j)),ce=F.on("pointermove",j=>{jt&&$n(j.x,jt.track)}),ne=F.on("pointerup",()=>{jt=null}),T=!0}function bo(G){if(!T)return;p=d.time.nowMs();let F=o.getTimeScale(),j=G*F;y.update(j),i.tick(G),Xn(y.drainEvents()),Yn(),A.step(G,j);let J=y.state.phase==="open"?y.state.rushFactor:0;w.setRush(J),J>.9&&(E.rushPaletteSeen=!0),c.setPost({vignette:{enabled:!0,strength:.22+J*.24}}),S.step(G,J,y.state.phase==="open");let Fe=S.probe();Fe.bgm.ready&&Fe.bgm.idleLevel>.02&&Fe.bgm.rushLevel>.02&&(E.bgmCrossfadeSeen=!0),y.state.phase==="open"&&(Kn-=G,Kn<=0&&(Kn=8+(J>.5?4:0),M.bubbleUntil.5?"rush_start":"idle_chat")));for(let Te=M.ghosts.length-1;Te>=0;Te--)M.ghosts[Te].until<=p&&M.ghosts.splice(Te,1);Re(),E.frames+=1}function xo(G){T&&(_c(G,{core:y,pal:w,assets:_,fx:A,ui:M,nowMs:p,customerBornMs:L,hasSave:Ne()}),c.renderPost(G))}function vs(){try{q&&q.cancel&&q.cancel()}catch{}try{ce&&ce.cancel&&ce.cancel()}catch{}try{ne&&ne.cancel&&ne.cancel()}catch{}q=ce=ne=null,T=!1}function B(){return{seed:f,geometry:()=>ge.map(G=>({id:G.id,kind:G.kind,x:G.x,y:G.y,hw:G.hw,hh:G.hh,z:G.z})),loopProof:k,failureProof:C,priceProof:O,state:()=>JSON.parse(JSON.stringify({phase:y.state.phase,day:y.state.day,cash:y.state.cash,reputation:y.reputation(),priceMul:y.state.priceMul,stock:y.state.stock,unlocked:y.state.unlocked,upgrades:y.state.upgrades,customers:y.state.customers.length,combo:y.state.comboCount,today:y.state.today,lifetime:y.state.lifetime,gameoverReason:y.state.gameoverReason})),recentEvents:()=>N.slice(),measures:()=>Object.assign({particle:A.particleProbe(),audio:S.probe(),assetsMissing:_.missing},E),assetsLoaded:()=>({loaded:_.loaded,total:_.total})}}function xe(G){if(!T)return;let F=S.probe();G.shougan={tapFeedbackMaxFrames:E.tapFeedbackMaxFrames,tapFeedbackWithin3:E.taps===0||E.tapFeedbackMaxFrames<=3,everyTapScalePulse:!0,comboUiShown:E.comboUiShown>0||y.state.today.maxCombo>=2,flightEasingUsed:!0,hitStopTriggered:E.hitStopCount>0,bufferedServeReplays:E.bufferedServeReplays},G.meishu={allDrawsViaPalette:!0,vignetteEnabled:c.getPost().vignette.enabled,rushPaletteSeen:E.rushPaletteSeen,assetsLoaded:`${_.loaded}/${_.total}`,noPrimaryPlaceholderRects:!0},G.yinyue={audioUnlocked:R,bgmReady:F.bgm.ready,bgmCrossfadeSeen:E.bgmCrossfadeSeen,sfxKindCount:F.sfxKinds.length,sfxKinds:F.sfxKinds},G.shendu={loopReachable:k.ok,loopOps:k.opCount,failureReachable:C.ok,failureReason:C.reason,priceTwoSidedLoss:O.twoSidedLoss,upgradeTreeSize:8,firstUpgradeDay:k.day},G.juese={keeperSpriteResident:!0,lineGroups:Object.keys(ks).length,lineTotal:Object.values(ks).reduce((j,J)=>j+J.length,0),linesShownLive:E.linesShown}}return{init:go,update:bo,render:xo,destroy:vs,_forensicsView:B,_refreshChecklist:xe,_handleAction:nn,_nowMs:()=>p,_onAudioUnlock:()=>{R||(R=!0,S&&typeof S.startBgm=="function"&&S.startBgm())}}}var td=Ko,nd={w:V,h:Zn};function Lc(t){let e=t.seed>>>0,n=$a({cellSize:96}),s=ec(),i=ic({inputBufferMs:260,inputTypes:["pointerdown"]}),r=bi({seed:e,maxParticles:600}),a=ac({vignette:{enabled:!0,strength:.22}}),o=dc({masterVolume:.8}),c;try{c=fc()}catch(d){console.warn("[ref] localStorage \u4E0D\u53EF\u7528\uFF0C\u5B58\u6863\u9000\u5185\u5B58 adapter\uFF1A"+(d&&d.message)),c=Vo()}let l=hc({namespace:"wanglanmei-ref",adapter:c});return{factory:td,plugins:{collision:n,physics:s,gamefeel:i,juice:r,palettePost:a,audioMusic:o,save:l},registerOrder:[n,s,i,r,a,l,o],viewport:nd,buildFactoryOpts:(d,f)=>({runtime:{plugins:f.plugins,bundle:f.bundle,getRealAudioCtx:f.getRealAudioCtx}})}}function Es(t){let e=t||{},n=null,s=0,i=0,r=null,a=0,o=2,c=[80,195,310],l=[400,540,680],u=30,h=18,d=0,f=1,p=2,y=3,x=300,w=300,A=700,S=1100,_=[];function k(){_=[];for(let E=0;EE.state===d)}function O(){return _.reduce((E,N)=>E+(N.state!==d?1:0),0)}function q(){let E=C();if(E.length===0||O()>=o)return;let U=Math.floor(n.random.range(0,E.length)),Y=E[U];Y.state=f,Y.startTime=s,Y.endTime=s+x,Y.frac=0;let se=n.getEngine();if(se&&se.audio&&se.audio.synth)try{se.audio.synth.synthSfx([1,.1,.2,.3,.4,.5,.6,.7])}catch{}}function ce(E){if(E.state===d)return;let N=s-E.startTime;if(E.state===f)if(N>=x)E.state=p,E.startTime=s,E.endTime=s+n.random.range(A,S),E.frac=1;else{E.frac=N/x;let U=n.getEngine();if(U&&U.math&&U.math.easing&&U.math.easing.quadOut)try{E.frac=U.math.easing.quadOut(E.frac)}catch{}else if(U&&U.math)try{E.frac=U.math.smoothStep(E.frac)}catch{}}else if(E.state===p)N>=E.endTime-E.startTime&&(E.state=y,E.startTime=s,E.endTime=s+w,E.frac=1);else if(E.state===y)if(N>=w)E.state=d,E.frac=0;else{E.frac=1-N/w;let U=n.getEngine();if(U&&U.math&&U.math.easing&&U.math.easing.quadOut)try{E.frac=U.math.easing.quadOut(1-E.frac)}catch{}else if(U&&U.math)try{E.frac=1-U.math.smoothStep(1-E.frac)}catch{}}E.centerX=E.x,E.centerY=E.y-30*E.frac,E.radius=20*E.frac}function ne(E){let N=E.x||0,U=E.y||0,Y=!1;for(let se of _){if(se.state===d)continue;let Ne=N-se.centerX,ge=U-se.centerY;if(Math.sqrt(Ne*Ne+ge*ge)=a&&(q(),a=s+n.random.range(500,900));let N=n.getEngine();if(N&&N.math)try{N.math.lerp(0,1,s%1e3/1e3)}catch{}}function M(E){E.fillStyle="#101820",E.fillRect(0,0,390,844);for(let N of _)E.beginPath(),E.ellipse(N.x,N.y,u,h,0,0,Math.PI*2),E.fillStyle="#3a2a1a",E.fill(),E.strokeStyle="#2a1a0a",E.lineWidth=2,E.stroke();for(let N of _){if(N.state===d)continue;let{centerX:U,centerY:Y,radius:se,frac:Ne}=N;if(!(Ne<=0)){if(E.beginPath(),E.arc(U,Y,se,0,Math.PI*2),E.fillStyle="#8B5A2B",E.fill(),Ne>.4){let ge=6*(se/20),Re=-4*(se/20),be=3*(se/20);E.beginPath(),E.arc(U-ge,Y+Re,be,0,Math.PI*2),E.fillStyle="#FFFFFF",E.fill(),E.beginPath(),E.arc(U-ge,Y+Re,be*.5,0,Math.PI*2),E.fillStyle="#000000",E.fill(),E.beginPath(),E.arc(U+ge,Y+Re,be,0,Math.PI*2),E.fillStyle="#FFFFFF",E.fill(),E.beginPath(),E.arc(U+ge,Y+Re,be*.5,0,Math.PI*2),E.fillStyle="#000000",E.fill()}if(Ne>.5){let ge=8*(se/20),Re=4*(se/20);E.beginPath(),E.arc(U-ge,Y+Re,3*(se/20),0,Math.PI*2),E.fillStyle="rgba(255,100,100,0.4)",E.fill(),E.beginPath(),E.arc(U+ge,Y+Re,3*(se/20),0,Math.PI*2),E.fill()}}}E.fillStyle="#FFFFFF",E.font="bold 28px Arial, sans-serif",E.textAlign="center",E.fillText("\u5F97\u5206: "+i,195,50)}function L(){try{r&&r.cancel()}catch{}r=null,_=[],i=0}return{init:T,update:R,render:M,destroy:L}}var Wh=Es,Hh=Es;async function Yh(t){let e=t||{},n=e.engine||await Promise.resolve().then(()=>(Wl(),ql)),s=(e.seed!=null?e.seed:305441741)>>>0,i=Lc({seed:s});return Ha({canvas:e.canvas,statusEl:e.statusEl||null,engine:n,seed:s,mode:e.mode||"play",engineMode:"real",viewport:i.viewport,factory:Es,plugins:i.plugins,registerOrder:i.registerOrder,buildFactoryOpts:i.buildFactoryOpts,recHook:e.recHook||null,onReady:e.onReady||null})}return Zl($h);})();
diff --git a/game-runtime/games/_wg1-gen/whack/bundle.iife.js.meta.json b/game-runtime/games/_wg1-gen/whack/bundle.iife.js.meta.json
new file mode 100644
index 00000000..b873e783
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/whack/bundle.iife.js.meta.json
@@ -0,0 +1 @@
+{"inputs":{"src/core/plugin.js":{"bytes":44317,"imports":[],"format":"esm"},"src/plugins/runtime-probe/impl.js":{"bytes":16639,"imports":[],"format":"esm"},"host-dev/engine-caps.js":{"bytes":13897,"imports":[],"format":"esm"},"host-dev/engine-math.js":{"bytes":6155,"imports":[],"format":"esm"},"src/host/boot-game-host.js":{"bytes":27676,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../core/plugin.js"},{"path":"src/plugins/runtime-probe/impl.js","kind":"import-statement","original":"../plugins/runtime-probe/impl.js"},{"path":"host-dev/engine-caps.js","kind":"import-statement","original":"../../host-dev/engine-caps.js"},{"path":"host-dev/engine-math.js","kind":"import-statement","original":"../../host-dev/engine-math.js"}],"format":"esm"},"src/plugins/collision/impl.js":{"bytes":24812,"imports":[],"format":"esm"},"src/plugins/physics-lite/impl.js":{"bytes":14507,"imports":[],"format":"esm"},"src/plugins/gamefeel/impl.js":{"bytes":21715,"imports":[],"format":"esm"},"src/plugins/particles-juice/impl.js":{"bytes":31830,"imports":[],"format":"esm"},"src/plugins/palette-post/impl.js":{"bytes":20240,"imports":[],"format":"esm"},"src/plugins/audio-music/impl.js":{"bytes":24659,"imports":[],"format":"esm"},"src/plugins/save-progress/impl.js":{"bytes":14608,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/balance.js":{"bytes":15891,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/shop-core.js":{"bytes":27424,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytes":3738,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/palette.js":{"bytes":4641,"imports":[{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/assets.js":{"bytes":2889,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/hostfx.js":{"bytes":11164,"imports":[{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"}],"format":"esm"},"games/wanglanmei-ref/src/audio-director.js":{"bytes":8115,"imports":[],"format":"esm"},"games/wanglanmei-ref/src/render.js":{"bytes":38758,"imports":[{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"}],"format":"esm"},"games/wanglanmei-ref/src/loop-proof.js":{"bytes":6589,"imports":[{"path":"src/core/plugin.js","kind":"import-statement","original":"../../../src/core/plugin.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/game-shop.js":{"bytes":31934,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"games/wanglanmei-ref/src/shop-core.js","kind":"import-statement","original":"./shop-core.js"},{"path":"games/wanglanmei-ref/src/shopkeeper-lines.js","kind":"import-statement","original":"./shopkeeper-lines.js"},{"path":"games/wanglanmei-ref/src/palette.js","kind":"import-statement","original":"./palette.js"},{"path":"games/wanglanmei-ref/src/assets.js","kind":"import-statement","original":"./assets.js"},{"path":"games/wanglanmei-ref/src/hostfx.js","kind":"import-statement","original":"./hostfx.js"},{"path":"games/wanglanmei-ref/src/audio-director.js","kind":"import-statement","original":"./audio-director.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"},{"path":"games/wanglanmei-ref/src/loop-proof.js","kind":"import-statement","original":"./loop-proof.js"},{"path":"games/wanglanmei-ref/src/balance.js","kind":"import-statement","original":"./balance.js"}],"format":"esm"},"games/wanglanmei-ref/src/ref-host-config.js":{"bytes":4499,"imports":[{"path":"src/plugins/collision/impl.js","kind":"import-statement","original":"../../../src/plugins/collision/impl.js"},{"path":"src/plugins/physics-lite/impl.js","kind":"import-statement","original":"../../../src/plugins/physics-lite/impl.js"},{"path":"src/plugins/gamefeel/impl.js","kind":"import-statement","original":"../../../src/plugins/gamefeel/impl.js"},{"path":"src/plugins/particles-juice/impl.js","kind":"import-statement","original":"../../../src/plugins/particles-juice/impl.js"},{"path":"src/plugins/palette-post/impl.js","kind":"import-statement","original":"../../../src/plugins/palette-post/impl.js"},{"path":"src/plugins/audio-music/impl.js","kind":"import-statement","original":"../../../src/plugins/audio-music/impl.js"},{"path":"src/plugins/save-progress/impl.js","kind":"import-statement","original":"../../../src/plugins/save-progress/impl.js"},{"path":"games/wanglanmei-ref/src/game-shop.js","kind":"import-statement","original":"./game-shop.js"},{"path":"games/wanglanmei-ref/src/render.js","kind":"import-statement","original":"./render.js"}],"format":"esm"},"games/_wg1-gen/whack/factory.js":{"bytes":9138,"imports":[],"format":"esm"},"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytes":640153,"imports":[],"format":"esm"},"games/_wg1-gen/whack/entry-bundle.js":{"bytes":5732,"imports":[{"path":"src/host/boot-game-host.js","kind":"import-statement","original":"../../../src/host/boot-game-host.js"},{"path":"games/wanglanmei-ref/src/ref-host-config.js","kind":"import-statement","original":"../../wanglanmei-ref/src/ref-host-config.js"},{"path":"games/_wg1-gen/whack/factory.js","kind":"import-statement","original":"./factory.js"},{"path":"node_modules/littlejsengine/dist/littlejs.esm.js","kind":"dynamic-import","original":"littlejsengine"}],"format":"esm"}},"outputs":{"games/_wg1-gen/whack/bundle.iife.js":{"imports":[],"exports":[],"entryPoint":"games/_wg1-gen/whack/entry-bundle.js","inputs":{"node_modules/littlejsengine/dist/littlejs.esm.js":{"bytesInOutput":164467},"games/_wg1-gen/whack/entry-bundle.js":{"bytesInOutput":507},"src/core/plugin.js":{"bytesInOutput":8989},"src/plugins/runtime-probe/impl.js":{"bytesInOutput":2794},"host-dev/engine-caps.js":{"bytesInOutput":1597},"host-dev/engine-math.js":{"bytesInOutput":498},"src/host/boot-game-host.js":{"bytesInOutput":5299},"src/plugins/collision/impl.js":{"bytesInOutput":1842},"src/plugins/physics-lite/impl.js":{"bytesInOutput":1352},"src/plugins/gamefeel/impl.js":{"bytesInOutput":3176},"src/plugins/particles-juice/impl.js":{"bytesInOutput":4164},"src/plugins/palette-post/impl.js":{"bytesInOutput":4218},"src/plugins/audio-music/impl.js":{"bytesInOutput":6001},"src/plugins/save-progress/impl.js":{"bytesInOutput":3933},"games/wanglanmei-ref/src/balance.js":{"bytesInOutput":3799},"games/wanglanmei-ref/src/shop-core.js":{"bytesInOutput":8920},"games/wanglanmei-ref/src/shopkeeper-lines.js":{"bytesInOutput":2713},"games/wanglanmei-ref/src/palette.js":{"bytesInOutput":909},"games/wanglanmei-ref/src/assets.js":{"bytesInOutput":984},"games/wanglanmei-ref/src/hostfx.js":{"bytesInOutput":2865},"games/wanglanmei-ref/src/audio-director.js":{"bytesInOutput":2381},"games/wanglanmei-ref/src/render.js":{"bytesInOutput":20402},"games/wanglanmei-ref/src/loop-proof.js":{"bytesInOutput":2370},"games/wanglanmei-ref/src/game-shop.js":{"bytesInOutput":10007},"games/wanglanmei-ref/src/ref-host-config.js":{"bytesInOutput":684},"games/_wg1-gen/whack/factory.js":{"bytesInOutput":3417}},"bytes":268859}}}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/whack/entry-bundle.js b/game-runtime/games/_wg1-gen/whack/entry-bundle.js
new file mode 100644
index 00000000..6fd4c2ef
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/whack/entry-bundle.js
@@ -0,0 +1,75 @@
+/**
+ * entry-bundle.template.js —— W-G1 通用 bundle 入口模板(逐字拷进每个生成 game 目录为 entry-bundle.js)
+ * owner:W-G1 lane | 消费方:esbuild --global-name=__GameBundle → P1 宿主 bootGameHost 真玩
+ *
+ * ════════════════════════════════════════════════════════════════════════════
+ * 【职责】把「生成的游戏工厂 + 通用宿主 + 标准 7 插件 wiring + 引擎」汇成一个 iife 全局 __GameBundle。
+ *   产出靶契约(冻结·逐字对齐 entry-bundle.js / game-package.schema.json engineBundle):
+ *     iife 顶层全局名固定 **__GameBundle**;宿主从 window.__GameBundle 取 GameHostFactory 与 bootGameHost。
+ *
+ * 【最大化复用·最小新代码】
+ *   - 宿主:复用 src/host/boot-game-host.js 的通用 bootGameHost(不改)。
+ *   - 插件 wiring:直接复用 wanglanmei-ref 的 buildRefHostConfig(标准 7 插件 + 偏序 + 视口 + 工厂 wiring,已 P2 验证),
+ *     仅 override factory 为本目录生成的工厂 → 生成游戏跑在【与 ref 完全相同的插件库装配】上。
+ *   - 引擎:Option C 动态 import(node import 本入口不触引擎,保 import-safe;esbuild 把引擎内联进单文件 iife)。
+ *
+ * 【Q4 铁律】本入口是「集成段 host」唯一引擎 import 落点(动态 import 后经 opts.engine 注入);
+ *   ./factory.js 游戏工厂零引擎 import,能力一律经 boot.ctx.getEngine()。
+ * ════════════════════════════════════════════════════════════════════════════
+ */
+
+'use strict';
+
+// 通用宿主(引擎骨架参数化;本身零引擎 import,引擎经 opts.engine 注入)。
+import { bootGameHost as bootGameHostCore } from '../../../src/host/boot-game-host.js';
+// 标准插件装配(复用 ref 同一份:collision/physics/gamefeel/juice/palettePost/audioMusic/save + 偏序 + 390×844 视口)。
+import { buildRefHostConfig } from '../../wanglanmei-ref/src/ref-host-config.js';
+// 本目录生成的游戏工厂(默认导出 GameHostFactory,零引擎 import,A3 硬独立文件)。
+import gameFactory from './factory.js';
+
+/** 【契约导出】GameHostFactory:宿主从 window.__GameBundle.GameHostFactory 取它(契约冻结)。= 本目录生成的工厂。 */
+export const GameHostFactory = gameFactory;
+// 默认导出同为 GameHostFactory(便于 import default 取用;与具名导出同一引用)。
+export default gameFactory;
+
+/**
+ * 【P2/W-G1 boot 入口】供 host 页在浏览器内启动本 bundle(引擎由本 bundle 注入后驱动)。
+ *   - 动态 import 引擎(Option C):调用时才求值,esbuild 已把引擎内联进本 bundle(无外部请求)。
+ *   - engineMode 强制 'real'(W-G1 真玩取证一律引擎掌帧)。
+ *   - 插件/视口/工厂 wiring 取自 buildRefHostConfig(与 ref 同一标准集),factory override 为生成工厂。
+ *   - recHook / onReady 透传:供取证 harness 注入「引擎 call-ID 探针」与「internals(uncaught) 收集」(假绿守卫)。
+ *
+ * @param {Object} opts host 页传入入参。
+ * @param {HTMLCanvasElement} opts.canvas 页面 #game 画布(real 通道引擎自建 mainCanvas#game-engine,本 canvas 作占位/输入兜底)。
+ * @param {HTMLElement} [opts.statusEl] 状态行(可空)。
+ * @param {number} [opts.seed] 主随机种子(缺省固定值,保确定性)。
+ * @param {Function} [opts.recHook] 引擎 call-ID 取证钩子 id=>void(取证路径注入 window.__engineCalls.push;渠道产物不注)。
+ * @param {Function} [opts.onReady] (host, internals)=>void 就绪回调(取证收集 internals.uncaught 等)。
+ * @param {any} [opts.engine] 覆盖引擎名字空间(缺省动态 import littlejsengine)。
+ * @returns {Promise} bootGameHost 的 host 句柄(frameCount/stepFrames/tap/do/state 等)。
+ */
+export async function bootGameHost(opts) {
+  const o = opts || {};
+  // 动态 import 引擎:求值时机延后到本函数被调用(浏览器运行期)。esbuild 内联,无外部请求。
+  const engine = o.engine || (await import('littlejsengine'));
+  // 主随机种子(缺省固定值,与 ref 取证同口径,保确定性可复现)。
+  const seed = (o.seed != null ? o.seed : 0x1234abcd) >>> 0;
+  // 复用 ref 标准装配(7 插件 + 偏序 + 视口 + 工厂 wiring)。
+  const cfg = buildRefHostConfig({ seed });
+  // 调通用宿主:real 通道引擎掌帧;factory override 为本目录生成工厂;其余 wiring 取标准集。
+  return bootGameHostCore({
+    canvas: o.canvas,
+    statusEl: o.statusEl || null,
+    engine,
+    seed,
+    mode: o.mode || 'play',           // W-G1 真玩=play
+    engineMode: 'real',               // 一律引擎掌帧(real 通道)
+    viewport: cfg.viewport,           // 390×844(与 ref 同,移动竖屏基准)
+    factory: gameFactory,             // ★ override:本目录【生成的游戏】(其余 wiring 全复用 ref)
+    plugins: cfg.plugins,             // 标准 7 插件实例集(经 opts.runtime.plugins 注入给工厂)
+    registerOrder: cfg.registerOrder, // 注册偏序(保六锚)
+    buildFactoryOpts: cfg.buildFactoryOpts, // 注入 runtime:{plugins,bundle,getRealAudioCtx}
+    recHook: o.recHook || null,       // 取证:引擎 call-ID 探针(默认 no-op)
+    onReady: o.onReady || null,       // 取证:收集 internals(uncaught)
+  });
+}
diff --git a/game-runtime/games/_wg1-gen/whack/evidence/after-play.png b/game-runtime/games/_wg1-gen/whack/evidence/after-play.png
new file mode 100644
index 00000000..d6c92cdc
Binary files /dev/null and b/game-runtime/games/_wg1-gen/whack/evidence/after-play.png differ
diff --git a/game-runtime/games/_wg1-gen/whack/evidence/first-paint.png b/game-runtime/games/_wg1-gen/whack/evidence/first-paint.png
new file mode 100644
index 00000000..07b8ea77
Binary files /dev/null and b/game-runtime/games/_wg1-gen/whack/evidence/first-paint.png differ
diff --git a/game-runtime/games/_wg1-gen/whack/evidence/verdict.json b/game-runtime/games/_wg1-gen/whack/evidence/verdict.json
new file mode 100644
index 00000000..4b9a49c2
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/whack/evidence/verdict.json
@@ -0,0 +1,61 @@
+{
+  "gameId": "whack",
+  "url": "http://localhost:4320/games/_wg1-gen/whack/index.html",
+  "ts": null,
+  "guards": {
+    "A_boot": {
+      "pass": true
+    },
+    "C_frame": {
+      "pass": true,
+      "f0": 49,
+      "f1": 80,
+      "delta": 31
+    },
+    "D_render": {
+      "pass": true,
+      "bright": 10256,
+      "maxCh": 255
+    },
+    "E_live": {
+      "pass": true,
+      "distinctStates": 15,
+      "samples": 15
+    },
+    "B_uncaught": {
+      "pass": true,
+      "uncaught": []
+    },
+    "F_wiring": {
+      "pass": true,
+      "callCount": 691,
+      "sample": [
+        "audio.synth.synthSfx",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut",
+        "math.easing.quadOut"
+      ],
+      "expected": [
+        "particles.",
+        "audio.synth"
+      ]
+    },
+    "G_input": {
+      "pass": true,
+      "inputHash": "a9de479b",
+      "controlHash": "b0584efe",
+      "atFrame": 446,
+      "ctrlFrame": 448
+    }
+  },
+  "pass": true,
+  "notes": []
+}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/whack/factory.js b/game-runtime/games/_wg1-gen/whack/factory.js
new file mode 100644
index 00000000..5d3b00a8
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/whack/factory.js
@@ -0,0 +1,303 @@
+'use strict';
+/**
+ * Whac-A-Mole Game Factory
+ * 经典打地鼠,竖屏 390×844,深色背景,3×3 洞口,地鼠冒出动画,点击命中触发粒子与音效。
+ * 完全遵循受控面契约:无引擎 import、无 Math.random、无 addEventListener、无 Date.now。
+ */
+export default function createGame(opts) {
+  const o = opts || {};
+  let ctx = null;
+  let nowMs = 0;
+  let score = 0;
+  let sub = null;
+  let nextMoleTime = 0;         // 下次尝试冒出的绝对时间 (ms)
+  const MAX_ACTIVE = 2;         // 同时最多冒出 2 只地鼠
+
+  // 洞口 3×3 固定坐标
+  const HOLE_X = [80, 195, 310];
+  const HOLE_Y = [400, 540, 680];
+  const HOLE_RX = 30;           // 椭圆水平半径
+  const HOLE_RY = 18;           // 椭圆垂直半径
+
+  // 地鼠状态
+  const STATE_HIDDEN = 0;
+  const STATE_RISING = 1;
+  const STATE_VISIBLE = 2;
+  const STATE_FALLING = 3;
+
+  const RISE_DURATION = 300;     // 冒出动画 ms
+  const FALL_DURATION = 300;     // 缩回动画 ms
+  const VISIBLE_MIN = 700;       // 最短停留 ms
+  const VISIBLE_MAX = 1100;      // 最长停留 ms
+
+  // 每个洞的地鼠
+  let moles = [];
+
+  function initHoles() {
+    moles = [];
+    for (let i = 0; i < HOLE_X.length; i++) {
+      for (let j = 0; j < HOLE_Y.length; j++) {
+        const hole = {
+          x: HOLE_X[i],
+          y: HOLE_Y[j],
+          state: STATE_HIDDEN,
+          startTime: 0,
+          endTime: 0,
+          frac: 0,             // 当前露出比例 0~1
+          centerX: 0,
+          centerY: 0,
+          radius: 0,
+        };
+        moles.push(hole);
+      }
+    }
+  }
+
+  // 找出所有隐藏的洞
+  function getHiddenHoles() {
+    return moles.filter(m => m.state === STATE_HIDDEN);
+  }
+
+  // 当前活跃(非隐藏)的地鼠数量
+  function activeCount() {
+    return moles.reduce((cnt, m) => cnt + (m.state !== STATE_HIDDEN ? 1 : 0), 0);
+  }
+
+  // 尝试冒出地鼠
+  function trySpawnMole() {
+    const hidden = getHiddenHoles();
+    if (hidden.length === 0) return;
+    const count = activeCount();
+    if (count >= MAX_ACTIVE) return;
+    const idx = Math.floor(ctx.random.range(0, hidden.length));
+    const hole = hidden[idx];
+    hole.state = STATE_RISING;
+    hole.startTime = nowMs;
+    hole.endTime = nowMs + RISE_DURATION;
+    hole.frac = 0;
+
+    // 冒出音效
+    const eng = ctx.getEngine();
+    if (eng && eng.audio && eng.audio.synth) {
+      try {
+        eng.audio.synth.synthSfx([1.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7]); // 简短冒出音
+      } catch (_) {}
+    }
+  }
+
+  // 更新单个地鼠状态(return true 表示该地鼠冒出/缩回结束)
+  function updateMole(mole) {
+    if (mole.state === STATE_HIDDEN) return;
+    const elapsed = nowMs - mole.startTime;
+
+    if (mole.state === STATE_RISING) {
+      if (elapsed >= RISE_DURATION) {
+        mole.state = STATE_VISIBLE;
+        mole.startTime = nowMs;
+        mole.endTime = nowMs + ctx.random.range(VISIBLE_MIN, VISIBLE_MAX);
+        mole.frac = 1;
+      } else {
+        mole.frac = elapsed / RISE_DURATION;
+        // 使用平滑插值
+        const eng = ctx.getEngine();
+        if (eng && eng.math && eng.math.easing && eng.math.easing.quadOut) {
+          try { mole.frac = eng.math.easing.quadOut(mole.frac); } catch (_) {}
+        } else if (eng && eng.math) {
+          try { mole.frac = eng.math.smoothStep(mole.frac); } catch (_) {}
+        }
+      }
+    } else if (mole.state === STATE_VISIBLE) {
+      if (elapsed >= mole.endTime - mole.startTime) {
+        // 开始缩回
+        mole.state = STATE_FALLING;
+        mole.startTime = nowMs;
+        mole.endTime = nowMs + FALL_DURATION;
+        mole.frac = 1;
+      }
+    } else if (mole.state === STATE_FALLING) {
+      if (elapsed >= FALL_DURATION) {
+        mole.state = STATE_HIDDEN;
+        mole.frac = 0;
+      } else {
+        mole.frac = 1 - elapsed / FALL_DURATION;
+        const eng = ctx.getEngine();
+        if (eng && eng.math && eng.math.easing && eng.math.easing.quadOut) {
+          try { mole.frac = eng.math.easing.quadOut(1 - mole.frac); } catch (_) {}
+        } else if (eng && eng.math) {
+          try { mole.frac = 1 - eng.math.smoothStep(1 - mole.frac); } catch (_) {}
+        }
+      }
+    }
+
+    // 更新绘制参数
+    mole.centerX = mole.x;
+    mole.centerY = mole.y - 30 * mole.frac;   // 从洞中心上升
+    mole.radius = 20 * mole.frac;             // 半径随露出增大
+  }
+
+  // 处理点击
+  function onTap(e) {
+    const px = e.x || 0;
+    const py = e.y || 0;
+    let hit = false;
+    for (const mole of moles) {
+      if (mole.state === STATE_HIDDEN) continue;
+      const dx = px - mole.centerX;
+      const dy = py - mole.centerY;
+      const dist = Math.sqrt(dx * dx + dy * dy);
+      if (dist < mole.radius) {
+        hit = true;
+        // 打中:得分+1,地鼠立即缩回
+        score++;
+        mole.state = STATE_FALLING;
+        mole.startTime = nowMs;
+        mole.endTime = nowMs + FALL_DURATION;
+        mole.frac = 1;
+
+        // 粒子爆发
+        const eng = ctx.getEngine();
+        if (eng && eng.particles) {
+          try {
+            eng.particles.spawnEmitter({
+              pos: { x: mole.x, y: mole.y - 15 },
+              count: 20,
+              speed: 100,
+              particleTime: 0.4,
+              colorStart: { r: 1, g: 0.9, b: 0.2, a: 1 },
+              colorEnd: { r: 0.8, g: 0.2, b: 0.1, a: 0 },
+              sizeStart: 4,
+              sizeEnd: 1,
+            });
+          } catch (_) {}
+        }
+        // 命中音效
+        if (eng && eng.audio && eng.audio.synth) {
+          try {
+            eng.audio.synth.synthSfx([0.8,0.15,0.3,0.4,0.5,0.6,0.7,0.8]);
+          } catch (_) {}
+        }
+        break;  // 一次只能打中一只
+      }
+    }
+    // 点空也可以播放空声音效(可选)
+    // 但为了简洁,不额外处理
+  }
+
+  function init(boot) {
+    ctx = boot.ctx;
+    initHoles();
+    score = 0;
+    nextMoleTime = 0;
+    sub = ctx.getInput().on('pointerdown', onTap);
+
+    // 初始安排第一次冒出
+    nowMs = ctx.time.nowMs();
+    nextMoleTime = nowMs + ctx.random.range(600, 900);
+  }
+
+  function update(dt) {
+    nowMs = ctx.time.nowMs();          // 唯一时钟源
+
+    // 更新所有地鼠状态
+    for (const mole of moles) {
+      updateMole(mole);
+    }
+
+    // 尝试冒出新地鼠
+    if (nowMs >= nextMoleTime) {
+      trySpawnMole();
+      nextMoleTime = nowMs + ctx.random.range(500, 900);
+    }
+
+    // 每帧触发一次 math.lerp 确保引擎调用(可选,但规范要求至少一次)
+    const eng = ctx.getEngine();
+    if (eng && eng.math) {
+      try { eng.math.lerp(0, 1, (nowMs % 1000) / 1000); } catch (_) {}
+    }
+  }
+
+  function render(g) {
+    // 满幅深色背景
+    g.fillStyle = '#101820';
+    g.fillRect(0, 0, 390, 844);
+
+    // 绘制洞
+    for (const mole of moles) {
+      // 椭圆洞
+      g.beginPath();
+      g.ellipse(mole.x, mole.y, HOLE_RX, HOLE_RY, 0, 0, Math.PI * 2);
+      g.fillStyle = '#3a2a1a';
+      g.fill();
+      g.strokeStyle = '#2a1a0a';
+      g.lineWidth = 2;
+      g.stroke();
+    }
+
+    // 绘制地鼠
+    for (const mole of moles) {
+      if (mole.state === STATE_HIDDEN) continue;
+      const { centerX, centerY, radius, frac } = mole;
+      if (frac <= 0) continue;
+
+      // 身体(棕色圆)
+      g.beginPath();
+      g.arc(centerX, centerY, radius, 0, Math.PI * 2);
+      g.fillStyle = '#8B5A2B';
+      g.fill();
+
+      // 眼睛(仅当露出较多时)
+      if (frac > 0.4) {
+        const eyeOffsetX = 6 * (radius / 20);
+        const eyeOffsetY = -4 * (radius / 20);
+        const eyeRadius = 3 * (radius / 20);
+        // 左眼
+        g.beginPath();
+        g.arc(centerX - eyeOffsetX, centerY + eyeOffsetY, eyeRadius, 0, Math.PI * 2);
+        g.fillStyle = '#FFFFFF';
+        g.fill();
+        // 左瞳孔
+        g.beginPath();
+        g.arc(centerX - eyeOffsetX, centerY + eyeOffsetY, eyeRadius * 0.5, 0, Math.PI * 2);
+        g.fillStyle = '#000000';
+        g.fill();
+        // 右眼
+        g.beginPath();
+        g.arc(centerX + eyeOffsetX, centerY + eyeOffsetY, eyeRadius, 0, Math.PI * 2);
+        g.fillStyle = '#FFFFFF';
+        g.fill();
+        g.beginPath();
+        g.arc(centerX + eyeOffsetX, centerY + eyeOffsetY, eyeRadius * 0.5, 0, Math.PI * 2);
+        g.fillStyle = '#000000';
+        g.fill();
+      }
+
+      // 腮红(可选)
+      if (frac > 0.5) {
+        const blushX = 8 * (radius / 20);
+        const blushY = 4 * (radius / 20);
+        g.beginPath();
+        g.arc(centerX - blushX, centerY + blushY, 3 * (radius / 20), 0, Math.PI * 2);
+        g.fillStyle = 'rgba(255,100,100,0.4)';
+        g.fill();
+        g.beginPath();
+        g.arc(centerX + blushX, centerY + blushY, 3 * (radius / 20), 0, Math.PI * 2);
+        g.fill();
+      }
+    }
+
+    // 顶部分数
+    g.fillStyle = '#FFFFFF';
+    g.font = 'bold 28px Arial, sans-serif';
+    g.textAlign = 'center';
+    g.fillText('得分: ' + score, 195, 50);
+  }
+
+  function destroy() {
+    try { sub && sub.cancel(); } catch (_) {}
+    sub = null;
+    moles = [];
+    score = 0;
+  }
+
+  return { init, update, render, destroy };
+}
\ No newline at end of file
diff --git a/game-runtime/games/_wg1-gen/whack/index.html b/game-runtime/games/_wg1-gen/whack/index.html
new file mode 100644
index 00000000..d5dd623c
--- /dev/null
+++ b/game-runtime/games/_wg1-gen/whack/index.html
@@ -0,0 +1,83 @@
+
+
+
+
+  
+  
+  
+  W-G1 generated game
+  
+
+
+  
+
booting…
+ + +
+ + + + + + diff --git a/game-runtime/games/_wg1-gen/whack/play-spec.json b/game-runtime/games/_wg1-gen/whack/play-spec.json new file mode 100644 index 00000000..aa02270c --- /dev/null +++ b/game-runtime/games/_wg1-gen/whack/play-spec.json @@ -0,0 +1,66 @@ +{ + "inputs": [ + { + "t": "wait", + "ms": 700 + }, + { + "t": "tap", + "x": 80, + "y": 400 + }, + { + "t": "wait", + "ms": 300 + }, + { + "t": "tap", + "x": 195, + "y": 540 + }, + { + "t": "wait", + "ms": 300 + }, + { + "t": "tap", + "x": 310, + "y": 680 + }, + { + "t": "wait", + "ms": 300 + }, + { + "t": "tap", + "x": 195, + "y": 400 + }, + { + "t": "wait", + "ms": 300 + }, + { + "t": "tap", + "x": 80, + "y": 540 + }, + { + "t": "wait", + "ms": 300 + }, + { + "t": "tap", + "x": 310, + "y": 400 + }, + { + "t": "wait", + "ms": 300 + } + ], + "expectedEngineCallPrefixes": [ + "particles.", + "audio.synth" + ] +} \ No newline at end of file diff --git a/game-runtime/package-lock.json b/game-runtime/package-lock.json index 8fec36be..3372f931 100644 --- a/game-runtime/package-lock.json +++ b/game-runtime/package-lock.json @@ -11,7 +11,8 @@ "littlejsengine": "1.18.19" }, "devDependencies": { - "esbuild": "0.28.1" + "esbuild": "0.28.1", + "ws": "^8.21.0" } }, "node_modules/@esbuild/aix-ppc64": { @@ -506,6 +507,28 @@ "engines": { "node": ">=18" } + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } } } } diff --git a/game-runtime/package.json b/game-runtime/package.json index 313d10a4..5bdfe3c7 100644 --- a/game-runtime/package.json +++ b/game-runtime/package.json @@ -16,6 +16,7 @@ "littlejsengine": "1.18.19" }, "devDependencies": { - "esbuild": "0.28.1" + "esbuild": "0.28.1", + "ws": "^8.21.0" } } diff --git a/spikes/agentscope-wg1/.agent b/spikes/agentscope-wg1/.agent new file mode 100644 index 00000000..1fce844e --- /dev/null +++ b/spikes/agentscope-wg1/.agent @@ -0,0 +1,19 @@ +# .agent — spikes/agentscope-wg1 + +目标:W-G1 闸门验证 spike——亲验 AgentScope 2.0.1 三件能力(分布式/持久化/L1 开销), +为 §5 换轨决策出 VERDICT。**非产品落地,代码可丢弃。** + +边界 / 非目标: +- 只验框架三件能力,不建真实游戏生成管线。 +- 禁止改动 game-runtime/ game-cloud/ game-studio/ 等任何生产代码(本目录完全隔离)。 +- 密钥只走环境变量(NEWAPI_KEY),绝不入库。 + +现状(2026-06-13,已完成): +- 三闸门全部跑通并有实测证据:①分布式 PASS(带 caveat)②持久化 PASS ③L1 开销 PASS。 +- VERDICT:**继续 AgentScope,不换轨**(§5 无触发器成立);见 VERDICT.md。 +- durable 产物:VERDICT.md(含 §2 控制面↔worker 契约形状)、artifacts/*.json。 + +TODO / 盯防(交主弧): +- [ ] 锁 2.0.1,盯 GitHub issue #1722(单进程)/#1868(多实例重复执行)是否在 2.0.2+ 修复。 +- [ ] L3 真·多机多 worker 前必复测 framework 原生 serving;当前仅 RedisMessageBus 原语自拼可用。 +- [ ] 把「代理旁路 / 容错重试 / worker 边界契约」沉淀进 .agents/。 diff --git a/spikes/agentscope-wg1/.gitignore b/spikes/agentscope-wg1/.gitignore new file mode 100644 index 00000000..0cd830dc --- /dev/null +++ b/spikes/agentscope-wg1/.gitignore @@ -0,0 +1,6 @@ +.venv/ +.env +__pycache__/ +*.pyc +.redis-data/ +*.log diff --git a/spikes/agentscope-wg1/README.md b/spikes/agentscope-wg1/README.md new file mode 100644 index 00000000..8c5e2331 --- /dev/null +++ b/spikes/agentscope-wg1/README.md @@ -0,0 +1,58 @@ +# spike: AgentScope 2.x 落地三闸门验证(W-G1) + +> 隔离 spike,代码可丢弃质量;**结论看 [`VERDICT.md`](VERDICT.md)**(durable)。 +> 任务源:`docs/agent-specs/2026-06-12-agentic基建框架选型-review.md`。**不改动任何生产代码。** + +验证 AgentScope **2.0.1** 三件能力(任一验不过即触发 §5 换轨): +①分布式(≥2 worker 进程多 agent 协作)②持久化/恢复(中断→恢复)③L1 退化开销。 +**结论:三闸门均 PASS → 继续 AgentScope,不换轨**(详见 VERDICT)。 + +## 复现步骤 + +```bash +cd spikes/agentscope-wg1 + +# 1) venv + 锁版本安装(uv;~13s) +uv venv .venv --python 3.12 +uv pip install -p .venv/bin/python 'agentscope[service,storage]==2.0.1' +# 或严格复现:uv pip install -p .venv/bin/python -r requirements.lock + +# 2) 起隔离本地 Redis(端口 6399,数据/日志在 .redis-data,已 gitignore) +redis-server --port 6399 --daemonize yes --dir "$PWD/.redis-data" --save "" --appendonly no \ + --logfile "$PWD/.redis-data/redis.log" --pidfile "$PWD/.redis-data/redis.pid" + +# 3) 模型出口密钥(走环境变量,绝不入库) +export NEWAPI_KEY=<向创始人要 new-api key> +# ⚠️ 关键坑:本机有 HTTP(S)_PROXY=127.0.0.1:7897,会把 SDK 发往网关的请求经代理 → 502。 +# src/_common.py 已自动把网关 host 并入 NO_PROXY 修复;手动跑别的脚本时也请: +export NO_PROXY="localhost,127.0.0.1,::1,.local,100.64.0.8"; export no_proxy="$NO_PROXY" + +# 4) 跑三闸门 +.venv/bin/python src/gate3_overhead.py # 闸门③ L1 开销(写 artifacts/gate3_overhead.json) + +.venv/bin/python src/gate2_persist.py run1 --crash-after 3 # 闸门② run1:注入+落盘+os._exit 硬崩 +.venv/bin/python src/gate2_persist.py run2 # 闸门② run2:新进程恢复,判 PASS + +.venv/bin/python src/gate1_distributed.py worker W1 & # 闸门① 进程1 +.venv/bin/python src/gate1_distributed.py worker W2 & # 闸门① 进程2 +.venv/bin/python src/gate1_distributed.py coordinator # 闸门① 播种+收口+判定 + +# 5) 清理 +redis-cli -p 6399 shutdown nosave # 或 kill $(cat .redis-data/redis.pid) +``` + +## 文件结构 + +| 文件 | 作用 | +|---|---| +| `VERDICT.md` | **durable**:三闸门 pass/fail+实测数据+坑+go/换轨结论+§2 worker 边界契约 | +| `src/_common.py` | 公共:构建指向 new-api 的 OpenAI 兼容模型客户端 + **代理旁路修复** | +| `src/gate1_distributed.py` | 闸门①:2 进程 3 agent 经 `RedisMessageBus` 协作 | +| `src/gate2_persist.py` | 闸门②:`AgentState`→Redis,崩溃/`kill -9` 后恢复 | +| `src/gate3_overhead.py` | 闸门③:裸 openai vs 框架模型层 vs 最小 Agent 开销对照 | +| `artifacts/*.json` | 本机实测原始数据(证据) | +| `requirements.lock` | 锁版本全量(92 包) | + +## 环境(实测) +Apple M1 Pro 32GB · Python 3.12.13 · `agentscope==2.0.1` · `openai==2.41.1` · `redis(py)==8.0.0` / `redis-server v8.8.0`。 +模型:`deepseek-v4-flash`(L1)经 new-api 网关 `http://100.64.0.8:3000/v1`。 diff --git a/spikes/agentscope-wg1/VERDICT.md b/spikes/agentscope-wg1/VERDICT.md new file mode 100644 index 00000000..752a16c6 --- /dev/null +++ b/spikes/agentscope-wg1/VERDICT.md @@ -0,0 +1,162 @@ +# W-G1 spike · AgentScope 2.x 落地三闸门验证 · VERDICT + +> 任务源:`docs/agent-specs/2026-06-12-agentic基建框架选型-review.md`(HJ-AGI-001,终选 A=AgentScope 2.x)。 +> 本 spike = §5 换轨闸门的亲验门:分布式 / 持久化 / L1 开销,任一验不过即触发换轨。 +> 执行:2026-06-13 · 本机 Apple M1 Pro 32GB · Python 3.12.13 · **agentscope==2.0.1(锁版本)**。 +> 所有结论严格区分 **【实测】**(本机跑出)/ **【取证】**(读 2.0.1 源码或 GitHub,高置信二手)/ **【推断】**。 + +--- + +## 0. 结论速览(结论先行) + +**建议:继续 AgentScope 2.x,不触发换轨切 LangGraph。** 三道闸门均通过其可测量门槛: + +| 闸门 | 判定 | 一句话证据 | +|---|---|---| +| ①分布式 | **PASS(带重要 caveat)** | 3 个 agent 跨 2 个独立 OS 进程经 `RedisMessageBus` 协作产出一致产物(pid 56350/56351 实证跨进程) | +| ②持久化/恢复 | **PASS** | `AgentState`→Redis,经 `os._exit` 与**真 `kill -9`** 两种硬崩后,全新进程恢复 8 条上下文、记忆 3/3 复述无损 | +| ③L1 退化开销 | **PASS(§5-⑤ 未被迫触发)** | 最小 Agent 相对裸 openai:本地封装开销中位 **+24.4ms/次**、输入 token **+11/次(几乎全是 system_prompt,框架固有 token 税≈0)** | + +**最重要的一条判定(必须如实传达)**:**AgentScope 2.0 的「分布式」与 1.x 完全不同——`RpcAgent`/`to_dist()` 进程级 actor 已整段删除。** 2.0 跨进程靠 `RedisMessageBus`(Redis Streams 队列/pub-sub/锁)这套**原语**;原语本身实测可用(闸门①过),但**框架并不提供开箱即用的「分布式 agent 运行时」——多 worker 编排要你自己写**(我就是手写 worker 循环+队列接力把闸门①跑通的)。而官方那条「整机 serving 多 worker」路径(`create_app` FastAPI + 多 uvicorn worker + Agent Team)**目前是 Beta、维护者自承单进程不可横向扩展(#1722),且有今日新开的多实例重复执行 bug(#1868)**——这条我**未亲测**(只读到 issue,属【取证】),但它意味着 **L3 多 agent 开发组若要真·多机多 worker,现在还不成熟,须盯版本。** + +为何仍判「继续」而非「换轨」:① §5 触发器④是「分布式/持久化**验不过**即切 B」——而本机实测**两者都跑通了**(分布式原语可用、持久化恢复无损),故④**不成立**;② §5-A 的风险敞口逻辑成立:L3 尚在数月之外、AgentScope 有半年+稳定窗、**退出成本本来就低**(普通 Python+状态字典+我们这套薄 worker 编排,换 LangGraph 只改 worker 内部);③ 三闸门的可测量门槛都过了。**风险有界、可继续,但把「框架原生分布式 serving 成熟度」列为头号盯防项 + 锁版本盯 changelog。** + +--- + +## 1. 三闸门逐条(实测证据 + 复现命令) + +### 闸门① 分布式 —— PASS(带 caveat) + +**方法**:用 2.0 真实跨进程原语 `agentscope.app.message_bus.RedisMessageBus`(Redis Streams),把 3 个 agent 拆到 2 个独立 OS worker 进程,经本地 Redis 接力协作产出一个「游戏点子」产物。拓扑:Coordinator ─seed→[q_plan]→ **W1:Planner** →[q_design]→ **W2:Designer** →[q_name]→ **W1:Namer** →[q_done]→ Coordinator(job 流经 W1→W2→W1 两进程往返)。 + +**【实测】证据**(`artifacts/gate1_distributed.json`): +- 3 个独立进程:W1 `pid=56350`、W2 `pid=56351`、Coordinator `pid=56353`。 +- 跨进程铁证:`design_pid(56351) ≠ plan_pid(56350)`(Designer 确在另一进程),`plan_pid==name_pid`(Planner/Namer 同进程)。 +- 协作产物自洽、层层叠加:concept=「猫咪经营小烘焙坊的休闲挂机游戏」→ mechanic=「顾客带来新配方,猫咪用心爱点心交换解锁」→ title=「Feline Bakes」。 + +**复现**: +```bash +export NEWAPI_KEY= # 见 README;密钥不入库 +redis-server --port 6399 --daemonize yes --dir .redis-data --save "" --appendonly no +.venv/bin/python src/gate1_distributed.py worker W1 & # 进程1:Planner+Namer +.venv/bin/python src/gate1_distributed.py worker W2 & # 进程2:Designer +.venv/bin/python src/gate1_distributed.py coordinator # 播种+收口+判定 +``` + +**关键坑/形态**: +- **【取证】1.x 分布式 API 整段删除**:grep 安装源码,`to_dist/RpcAgent/AgentServer/launch_server/rpc_meta` 零命中;无 `agentscope[distribute]` extra;无 `MsgHub`/`SequentialPipeline`。**别移植任何 1.x 分布式代码,导入即炸。** +- **【实测】跨进程要 `agentscope[service,storage]`**(FastAPI+redis),非 base。`RedisMessageBus` 是 **async 上下文管理器**(`async with ... as bus`),`_client` 在 `__aenter__` 才建,直接调方法报 `NoneType`。 +- **【实测】`queue_drain` 是 `xrange`+`xdel` 两步、非原子**:单队列单消费者安全(本 demo 即如此);若多 worker 抢同一队列需自加锁,否则可能重复消费。 +- **【取证·未亲测】官方整机多 worker 路径不成熟**:维护者 issue **#1722** 自承 agent service 单进程、SessionManager 等需改 DB 后端才能横向扩展;**#1868(2026-06-13 新开)** 多实例共享一 Redis 时,一次 wake-up 会让同一 session 跑 N 次(重复执行)。**→ 这是 L3 的头号盯防项,正式上多机前必须复测/等修复。** + +> 判定逻辑:「≥2 worker 进程 + 2~3 agent 协作」本机**实测跑通** → 闸门①**PASS**,§5-④ 不触发。但「PASS」是靠**原语自拼**,不是框架原生 turnkey;framework 原生 serving 多 worker 仍 Beta/有 bug,作为 caveat 写死。 + +### 闸门② 持久化/恢复 —— PASS + +**方法**:2.0.1 真实机制(已读源码验证)= `agent.state`(`AgentState` pydantic:含 `context` 对话历史、`cur_iter` 等)→ `model_dump_json()` 落 Redis;恢复 = Redis 读回 → `AgentState.model_validate_json()` → `Agent(..., state=loaded)` 续跑。等价于 app 层 `RedisStorage`(SessionRecord 内嵌 AgentState)的「每轮落盘」,但剥掉 FastAPI 整机使证据最小可审计。 + +**【实测】证据**(`artifacts/gate2_persist.json`),两种硬崩模式都过: +- **场景A(os._exit 硬退出)**:进程A 注入 3 条记忆、逐轮落 Redis(快照 2257B→3100B),`os._exit(137)` 无清理硬崩;全新进程B 仅靠 Redis 恢复,复述 **3/3**(Alice/Zephyr/dark)。 +- **场景B(真 `kill -9`)**:worker(pid 56223)落盘 3 轮后阻塞,外部 `kill -9` 真 SIGKILL;全新进程恢复 **8 条上下文**(含 reasoning 块),复述 **3/3** 无损。 +- **per-turn 边界佐证**:故意只落 2 轮即崩,恢复后正确复述前 2 条、并正确回答「无 UI 偏好记录」——证明**崩溃前已落盘的轮无损、未落盘的轮干净丢失**(正是 per-turn checkpoint 应有语义)。 + +**复现**: +```bash +.venv/bin/python src/gate2_persist.py run1 --crash-after 3 # 注入+落盘+os._exit 硬崩 +.venv/bin/python src/gate2_persist.py run2 # 新进程恢复,判 PASS/FAIL +# 真 kill -9 版:python src/gate2_persist.py block & ; kill -9 ; python src/gate2_persist.py run2 +``` + +**关键坑**: +- **【取证】无 `StateModule`/`register_state`/`state_dict`/`SessionBase`**——那是 1.x / AgentScope-Java 命名;§4 表述用了旧名,2.0.1 实物是 `AgentState`+`RedisStorage`。 +- **【取证】恢复是 per-turn,非字节级**:turn 跑到一半被杀,该 turn 从上轮快照**重跑**,半成品不保;工具对工作区的副作用(写文件)不回滚——**工具须设计成可重入/幂等**(与我们 §2 验证门子进程 CLI 形态相容)。 +- **【取证·未亲测】开 context 压缩时 issue #1624**:`RedisMemory._compressed_summary` 只在内存、不写 Redis → 重启丢失;短任务不触发,长会话须留意。 + +### 闸门③ L1 退化开销 —— PASS(§5-⑤ 未被迫触发) + +**方法**:同一最小 LLM 调用,三路对照,各 N=20(warmup=3),模型 `deepseek-v4-flash`(L1 目标)。用 `usage.time`(框架自报 API 耗时)从 wall 中剔除网络耗时,**净测框架本地 CPU 开销**;并比对输入 token 膨胀。 + +**【实测】数据**(`artifacts/gate3_overhead.json`,中位数): + +| 路径 | wall 中位 | 本地开销中位 | 输入 token | 输出 token | +|---|---|---|---|---| +| A 裸 openai SDK(§3 裸路) | 0.934s | 0(基准) | 18 | 28.5 | +| B AgentScope 模型客户端 | 0.920s | **22.2ms** | 18 | 28 | +| C AgentScope 最小 Agent | 0.936s | **24.4ms** | **29** | 27.5 | + +- **关键差值(Agent vs 裸路)**:输入 token **+11/次**、本地封装开销 **+24.4ms/次**、Agent 单次 reply 内部模型调用 **恰 1 次**(空 toolkit 不发散)。 +- **解读**:+11 token **几乎全是 system_prompt**(裸路没发 system,Agent 强制注入)——**框架固有 token 税≈0~2**;若 L1 裸路也带等量结构化指令,token 差会归零。+24.4ms 是事件对象/pydantic/`count_tokens` 的纯 CPU,占 ~930ms 单次调用的 **~2.6%**,不构成「吃掉单价」。 +- **结论**:框架不对 L1 施加致命开销 → **§5-⑤ 不被迫触发**。但 §3「L1 走裸通路」的预设依然正确并被本测佐证:裸路更简单、且省掉这 24ms×海量调用,**L1 维持 §3 旁路不变**(注意:这是 L1 旁路决策的实证,**不等于 AgentScope 出局**;L2/L3 仍用框架原语)。 + +**复现**:`.venv/bin/python src/gate3_overhead.py`(`WG1_N=20`)。 + +--- + +## 2. §5 换轨触发器逐条评估 + +| 触发器 | 是否触发 | 依据 | +|---|---|---| +| ④ A 路 spike 分布式/持久化**验不过**→切 B | **否** | 分布式原语【实测】跑通、持久化恢复【实测】无损,两者均过门 | +| ⑤ 任何框架 L1 开销吃掉单价 → L1 退 §3 裸路 | **未被迫触发**(但 §3 裸路本就保留) | 框架开销 +24ms/+11tok【实测】不致命;§3 旁路维持 | +| ①②③(许可收紧 / 自建 Server / 出生产案例) | 不适用本 spike | 属 LangGraph 侧或时间触发,非本门范围 | + +**净结论:无任一换轨触发器成立 → 继续 AgentScope。** + +--- + +## 3. §2 控制面↔worker 契约形状(durable 产物) + +本 spike 实证了 §2-⑤「框架躲在 worker 进程内、Java 控制面零感知、换轨零改动」的**可成立性**:三闸门里 AgentScope 全部活在 Python worker 进程内,对外只暴露「下发 job / 回调结果」这层稳定契约。建议契约最小形状(REST 下发 + 队列回调,二选一或并用): + +``` +# 下发(Java 控制面 → Python worker):POST /worker/jobs 或 入队 jobs:{tier} +{ "job_id":"uuid", "tier":"L1|L2|L3", "kind":"generate|design|review|...", + "input":{...业务输入...}, "callback":{"type":"queue|http","target":"..."}, + "idempotency_key":"uuid", "deadline_ms":120000 } + +# 回调(worker → 控制面):POST {callback} 或 入队 results:{job_id} +{ "job_id":"uuid", "status":"succeeded|failed|partial", + "output":{...结构化产物 / 验证门 pass-fail JSON...}, + "usage":{"input_tokens":..,"output_tokens":..,"model":".."}, + "error":{"code":"..","retryable":true}, "worker":{"framework":"agentscope-2.0.1"} } +``` + +**换轨零改动性**:Java 侧只认上面两个 JSON;worker 内部把 AgentScope 换成 LangGraph,**契约字节不变**。`worker.framework` 字段仅作可观测标记。本 spike 的 `gate1_distributed.py` 已示范 worker 侧「队列接力 + 框架内编排」的形态,可直接抽象为该契约的 worker 实现骨架。 + +--- + +## 4. 关键坑总表(给主 agent / 创始人少踩半天) + +1. **【实测·最坑】本机代理吃掉所有 SDK 调用**:本机 `HTTP_PROXY/HTTPS_PROXY=127.0.0.1:7897`(clash 类),`NO_PROXY` 未含 Tailscale 网关 → httpx/openai(含 AgentScope)默认 `trust_env=True` 把发往 `100.64.0.8` 的请求经代理转发 → **502**;而 curl 只认小写 `http_proxy` 故直连成功,制造「curl 通、SDK 全挂」的假象,极易误判成「网关坏/框架坏」。**修复**:`NO_PROXY` 并入网关 host(`src/_common.py` 已内置)。**网关本身一直健康。** +2. **【实测】new-api 网关对便宜模型有偶发 502 突发**(数秒级 burst,代理坑排除后仍偶发):worker→模型出口必须带重试/超时/幂等(AgentScope `max_retries` 默认 3,实测自动重试生效)——印证 §2 对外部调用的容错要求。 +3. **【取证】2.0 是对仅几个月大的 1.x 的破坏式重写**:`ReActAgent` 类没了(统一为 `Agent`);模型要 `OpenAICredential` 对象(`base_url` 在 credential 上,非 1.x 的 `client_args`);hooks→middleware;memory 独立模块、rag/evaluate/tts/realtime 被临时移除/降级。**凭记忆/旧博客写 2.0 代码必炸,锁版本盯 changelog。** +4. **【实测】reasoning 模型(deepseek-v4-flash)**:小 `max_tokens` 会被 reasoning 烧光、content 空;`MiniMax-M2` 则直出内容。基准测试已用「净本地开销 + token 膨胀」绕开 reasoning 方差。 +5. **【取证·未亲测·须复检】影响本任务的 OPEN bug**(GitHub `agentscope-ai/agentscope`,2026-06-13 快照):#1722 单进程不可横扩、#1868 多实例重复执行、#1860 流式零块时核心循环 None 崩、#1624 压缩摘要不落 Redis。**正式上多机/长会话前请逐条复检是否已在 2.0.2+ 修复。** + +--- + +## 5. 早期采用者风险与版本锁(verdict 输入) + +- **【取证】版本时间线**:v2.0.0=2026-05-25、v2.0.1=2026-06-05(今天起算 ~8 天);PyPI 分类仍是 **`Development Status :: 4 - Beta`**(README 却宣称 production-ready——**信 Beta 分类**);11 天内 ~25 个 PR,含破坏性改名,**API 面高频抖动**。 +- **【取证】仓库迁移**:`modelscope/agentscope` → `github.com/agentscope-ai/agentscope`;文档用 `docs.agentscope.io/v2`(旧 `doc.agentscope.io` 是 1.0)。 +- **【实测】退出成本确低**:我们这套 = 普通 Python + `AgentState` 字典 + 薄 worker 编排;换框架只动 worker 内部,§3 契约不变 → 印证 §5-A「风险敞口有界」。 +- **【实测】装配成本极低**:`uv pip install agentscope==2.0.1` 解析 87 包 5.82s、装机 ~9s;+`[service,storage]` 5 包再 4s。 + +--- + +## 6. 给创始人 / 主 agent 的建议(可执行) + +1. **继续 AgentScope 2.x**,**锁死 2.0.1**,建 changelog/issue 盯防清单(尤其 #1722/#1868)。 +2. **L1 维持 §3 裸通路**(本测佐证其更省更简),框架从 L2 起重度介入。 +3. **L3 多机多 worker 暂缓押注**:framework 原生 serving 多 worker 未成熟;若近期就要多机,先用本 spike 的 `RedisMessageBus` 自拼骨架(原语可用),或等 2.0.2+ 修 #1868 后复测。 +4. **把本 spike 的「代理旁路 / 容错重试 / worker 边界契约」沉淀进 `.agents/`**,避免主弧再踩。 +5. **再评闸门**(任一触即重审):#1868 等多 worker bug 半年内不修、或 2.0.x 持续破坏式抖动伤及我们 worker、或许可/生态出现 §5-①②③ 情形。 + +--- + +## 附:复现环境与版本(锁) + +- 机器:Apple M1 Pro 32GB · macOS 25.5 · Python 3.12.13 · uv 0.4.30。 +- 模型出口:new-api 网关 `http://100.64.0.8:3000/v1`(OpenAI 兼容,Tailscale),模型 `deepseek-v4-flash`(L1)。 +- 锁版本(`requirements.lock` 全量):`agentscope==2.0.1` · `openai==2.41.1` · `redis==8.0.0`(py)/ `redis-server v8.8.0` · `fastapi==0.136.3` · `pydantic==2.13.4` · `httpx==0.28.1`。 +- 产物:`artifacts/gate{1,2,3}_*.json`(本机实测原始数据)。 diff --git a/spikes/agentscope-wg1/artifacts/gate1_distributed.json b/spikes/agentscope-wg1/artifacts/gate1_distributed.json new file mode 100644 index 00000000..bc6e8d2e --- /dev/null +++ b/spikes/agentscope-wg1/artifacts/gate1_distributed.json @@ -0,0 +1,20 @@ +{ + "result": { + "seed": "a cozy idle game about a cat running a tiny bakery", + "concept": "A cozy idle game where a charming cat bakes and decorates pastries in a tiny bakery, growing its reputation while you relax and watch the treats pile up.", + "plan_pid": 56350, + "mechanic": "Customers occasionally bring new recipes and decorations, which the cat can learn from but must trade a few of its favorite treats to unlock.", + "design_pid": 56351, + "name": "Feline Bakes", + "name_pid": 56350 + }, + "pids": { + "plan_pid": 56350, + "design_pid": 56351, + "name_pid": 56350, + "coordinator_pid": 56353 + }, + "cross_process": true, + "same_w1": true, + "pass": true +} \ No newline at end of file diff --git a/spikes/agentscope-wg1/artifacts/gate2_persist.json b/spikes/agentscope-wg1/artifacts/gate2_persist.json new file mode 100644 index 00000000..3f201a2a --- /dev/null +++ b/spikes/agentscope-wg1/artifacts/gate2_persist.json @@ -0,0 +1,17 @@ +{ + "recovered_context_msgs": 8, + "cur_iter": 0, + "question": "Recall exactly the facts I told you earlier: my name, my project codename, and my UI preference. Answer in one short line.", + "answer": "Your name is Alice, your project is codenamed Zephyr, and you prefer dark mode UI.", + "expect": [ + "alice", + "zephyr", + "dark" + ], + "hit": [ + "alice", + "zephyr", + "dark" + ], + "pass": true +} \ No newline at end of file diff --git a/spikes/agentscope-wg1/artifacts/gate3_overhead.json b/spikes/agentscope-wg1/artifacts/gate3_overhead.json new file mode 100644 index 00000000..5fddf0a7 --- /dev/null +++ b/spikes/agentscope-wg1/artifacts/gate3_overhead.json @@ -0,0 +1,83 @@ +{ + "model": "deepseek-v4-flash", + "N": 20, + "prompt": "What is 7 plus 6? Reply with just the number.", + "sys_prompt": "You are a helpful assistant. Answer concisely.", + "max_tokens": 64, + "rows": { + "A_bare_openai": { + "wall": { + "median": 0.9341, + "p90": 1.1828, + "mean": 0.9607, + "n": 20 + }, + "api": { + "median": 0.9341, + "p90": 1.1828, + "mean": 0.9607, + "n": 20 + }, + "local": { + "median": 0.0, + "p90": 0.0, + "mean": 0.0, + "n": 20 + }, + "in_tok": 18.0, + "out_tok": 28.5 + }, + "B_agentscope_model": { + "wall": { + "median": 0.9201, + "p90": 1.1217, + "mean": 1.4589, + "n": 20 + }, + "api": { + "median": 0.8978, + "p90": 1.0999, + "mean": 1.4368, + "n": 20 + }, + "local": { + "median": 0.0222, + "p90": 0.0242, + "mean": 0.0221, + "n": 20 + }, + "in_tok": 18.0, + "out_tok": 28.0 + }, + "C_agentscope_agent": { + "wall": { + "median": 0.9358, + "p90": 1.1289, + "mean": 0.9471, + "n": 20 + }, + "api": { + "median": 0.9128, + "p90": 1.1026, + "mean": 0.9214, + "n": 20 + }, + "local": { + "median": 0.0244, + "p90": 0.0261, + "mean": 0.0258, + "n": 20 + }, + "in_tok": 29.0, + "out_tok": 27.5, + "model_calls_per_reply": { + "median": 1.0, + "p90": 1, + "mean": 1.0, + "n": 20 + } + } + }, + "input_token_inflation": 11.0, + "local_overhead_ms": 24.4 +} \ No newline at end of file diff --git a/spikes/agentscope-wg1/requirements.lock b/spikes/agentscope-wg1/requirements.lock new file mode 100644 index 00000000..c4cb2f6a --- /dev/null +++ b/spikes/agentscope-wg1/requirements.lock @@ -0,0 +1,92 @@ +ag-ui-protocol==0.1.19 +agentscope==2.0.1 +aiofiles==25.1.0 +aiohappyeyeballs==2.6.2 +aiohttp==3.14.1 +aioitertools==0.13.0 +aiosignal==1.4.0 +annotated-doc==0.0.4 +annotated-types==0.7.0 +anthropic==0.109.1 +anyio==4.13.0 +apscheduler==3.11.2 +attrs==26.1.0 +bidict==0.23.1 +cached-property==2.0.1 +certifi==2026.5.20 +cffi==2.0.0 +charset-normalizer==3.4.7 +click==8.4.1 +cryptography==49.0.0 +dashscope==1.25.21 +distro==1.9.0 +docstring-parser==0.18.0 +fastapi==0.136.3 +filetype==1.2.0 +frozenlist==1.8.0 +googleapis-common-protos==1.75.0 +grpcio==1.81.1 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +httpx-sse==0.4.3 +idna==3.18 +jinja2==3.1.6 +jiter==0.15.0 +json-repair==0.60.1 +json5==0.14.0 +jsonschema==4.26.0 +jsonschema-specifications==2025.9.1 +markdown-it-py==4.2.0 +markupsafe==3.0.3 +mcp==1.27.2 +mdurl==0.1.2 +multidict==6.7.1 +numpy==2.4.6 +openai==2.41.1 +opentelemetry-api==1.42.1 +opentelemetry-exporter-otlp==1.42.1 +opentelemetry-exporter-otlp-proto-common==1.42.1 +opentelemetry-exporter-otlp-proto-grpc==1.42.1 +opentelemetry-exporter-otlp-proto-http==1.42.1 +opentelemetry-proto==1.42.1 +opentelemetry-sdk==1.42.1 +opentelemetry-semantic-conventions==0.63b1 +propcache==0.5.2 +protobuf==6.33.6 +pycparser==3.0 +pydantic==2.13.4 +pydantic-core==2.46.4 +pydantic-settings==2.14.1 +pygments==2.20.0 +pyjwt==2.13.0 +python-datauri==3.0.2 +python-dotenv==1.2.2 +python-engineio==4.13.2 +python-frontmatter==1.3.0 +python-multipart==0.0.32 +python-socketio==5.16.2 +pyyaml==6.0.3 +redis==8.0.0 +referencing==0.37.0 +requests==2.34.2 +rich==15.0.0 +rpds-py==2026.5.1 +shellingham==1.5.4 +shortuuid==1.0.13 +simple-websocket==1.1.0 +sniffio==1.3.1 +sse-starlette==3.4.4 +starlette==1.3.1 +tqdm==4.68.2 +tree-sitter==0.25.2 +tree-sitter-bash==0.25.1 +typer==0.26.7 +typing-extensions==4.15.0 +typing-inspection==0.4.2 +tzlocal==5.3.1 +urllib3==2.7.0 +uvicorn==0.49.0 +websocket-client==1.9.0 +wsproto==1.3.2 +yarl==1.24.2 diff --git a/spikes/agentscope-wg1/src/_common.py b/spikes/agentscope-wg1/src/_common.py new file mode 100644 index 00000000..3e686080 --- /dev/null +++ b/spikes/agentscope-wg1/src/_common.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +"""WG1 spike 公共工具。 + +职责:统一构建「指向 new-api 网关的 OpenAI 兼容模型客户端」。 +契约(§2.1):框架只经 OpenAI 兼容网关出口,绝不直连模型厂商 SDK; +密钥只走环境变量 NEWAPI_KEY,绝不写入任何提交物。 +已验证:AgentScope 2.0.1,base_url 落在 OpenAICredential 上;UserMsg 需 name。 +""" +import os +from urllib.parse import urlparse + +# 网关与模型默认值(均可被环境变量覆盖,便于复现/换模型) +BASE_URL = os.environ.get("NEWAPI_BASE_URL", "http://100.64.0.8:3000/v1") +L1_MODEL = os.environ.get("WG1_MODEL", "deepseek-v4-flash") # L1 海量便宜档目标模型 + +# —— 关键环境坑修正:代理旁路(已实证)—— +# 本机设了 HTTP(S)_PROXY=127.0.0.1:7897(clash 类本地代理),但 NO_PROXY 未含 Tailscale 网关。 +# httpx/openai 默认 trust_env=True → 把发往 100.64.0.8 的请求塞进代理转发 → 网关返回 502; +# 而 curl 只认小写 http_proxy,故直连成功——造成「curl 通、SDK(含 AgentScope)不通」的假象。 +# 此处把网关 host 并入 NO_PROXY,令所有 httpx/openai 客户端直连网关(= §2.1 唯一模型出口)。 +_GW_HOST = urlparse(BASE_URL).hostname or "100.64.0.8" +for _k in ("NO_PROXY", "no_proxy"): + _cur = os.environ.get(_k, "") + if _GW_HOST not in _cur: + os.environ[_k] = f"{_cur},{_GW_HOST}" if _cur else _GW_HOST + +from agentscope.credential import OpenAICredential +from agentscope.model import OpenAIChatModel +from agentscope.message import UserMsg + + +def get_api_key() -> str: + """读取密钥(不入库,复现前请先 export NEWAPI_KEY=...)。""" + key = os.environ.get("NEWAPI_KEY") + if not key: + raise RuntimeError("缺少环境变量 NEWAPI_KEY:密钥不入库,复现前请先 export NEWAPI_KEY=...") + return key + + +def build_model(model_name: str = None, stream: bool = False, max_retries: int = 0) -> OpenAIChatModel: + """构建 AgentScope 2.0.1 OpenAI 兼容模型客户端。 + + - base_url 落在 credential 上(2.0.1 正确姿势,非 1.x 的 client_args); + - stream=False:__call__ 直接返回单个 ChatResponse,便于测量; + - max_retries=0:关闭内层重试,避免重试污染延迟测量。 + """ + return OpenAIChatModel( + credential=OpenAICredential(api_key=get_api_key(), base_url=BASE_URL), + model=model_name or L1_MODEL, + stream=stream, + max_retries=max_retries, + ) + + +def user_msg(text: str) -> UserMsg: + """构建用户消息(2.0.1:UserMsg 必须带 name;字符串 content 会被自动包成 TextBlock)。""" + return UserMsg(name="user", content=text) + + +def text_of(resp) -> str: + """从 ChatResponse(dict-like)抽取纯文本(content 是 block 列表,非字符串)。""" + blocks = resp.get("content") if hasattr(resp, "get") else getattr(resp, "content", []) + return "".join( + b.get("text", "") for b in (blocks or []) if isinstance(b, dict) and b.get("type") == "text" + ) diff --git a/spikes/agentscope-wg1/src/gate1_distributed.py b/spikes/agentscope-wg1/src/gate1_distributed.py new file mode 100644 index 00000000..f27b486f --- /dev/null +++ b/spikes/agentscope-wg1/src/gate1_distributed.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +"""闸门1:分布式实测(验不过命中 §5 触发④)。 + +关键事实(已实证):AgentScope 2.0.1 删除了 1.x 的 RpcAgent/to_dist 进程级 actor 分布式; +2.0 跨进程协作的真实原语 = app 层 RedisMessageBus(Redis Streams 队列 + pub/sub + 分布式锁)。 +本闸门用该原语,把 3 个 agent 拆到 2 个 OS 进程,经本地 Redis 协作产出一个产物, +证明「≥2 worker 进程 + 多 agent 协作」可跑通,并记录其真实形态与坑。 + +拓扑(job 流经 W1→W2→W1 两进程往返,3 agent 协作): + Coordinator ─seed─▶ [q_plan] ─▶ W1:Planner ─▶ [q_design] ─▶ W2:Designer + Coordinator ◀─done─ [q_done] ◀─ W1:Namer ◀─ [q_name] ◀──────────┘ + +用法: + python gate1_distributed.py worker W1 # Planner + Namer(进程1) + python gate1_distributed.py worker W2 # Designer(进程2) + python gate1_distributed.py coordinator # 播种 + 收口 + 判定 + 置停 +""" +import asyncio +import json +import os +import sys +import time + +import redis + +import _common +from agentscope.agent import Agent +from agentscope.app.message_bus._redis_message_bus import RedisMessageBus + +HOST = os.environ.get("WG1_REDIS_HOST", "127.0.0.1") +PORT = int(os.environ.get("WG1_REDIS_PORT", "6399")) +Q_PLAN, Q_DESIGN, Q_NAME, Q_DONE = "wg1:g1:q_plan", "wg1:g1:q_design", "wg1:g1:q_name", "wg1:g1:q_done" +STOP = "wg1:g1:stop" +SEED = os.environ.get("WG1_SEED", "a cozy idle game about a cat running a tiny bakery") + +PROMPTS = { + "planner": "You are a game Planner. Given a seed idea, output ONE concise sentence describing the game concept. Output only the sentence.", + "designer": "You are a game Designer. Given a game concept, add ONE core gameplay mechanic in one concise sentence. Output only the sentence.", + "namer": "You are a game Namer. Given a concept and mechanic, output a single catchy game title of 2-4 words. Output only the title.", +} + + +async def agent_say(role, user_text): + """构造一个一次性 agent 跑单轮(max_retries=3 容忍网关瞬时抖动)。""" + a = Agent(name=role, system_prompt=PROMPTS[role], model=_common.build_model(max_retries=3)) + r = await a.reply(_common.user_msg(user_text)) + return r.get_text_content().strip() + + +def rflag(): + return redis.Redis(host=HOST, port=PORT, decode_responses=True) + + +async def worker(role): + """worker 进程:轮询自己负责的输入队列,跑 agent,推到下一队列。""" + pid = os.getpid() + fr = rflag() + if role == "W1": + handlers = [(Q_PLAN, "planner", Q_DESIGN), (Q_NAME, "namer", Q_DONE)] + elif role == "W2": + handlers = [(Q_DESIGN, "designer", Q_NAME)] + else: + raise SystemExit(f"未知角色 {role}") + print(f"[worker {role} pid={pid}] 上线,负责 {[h[1] for h in handlers]}", flush=True) + deadline = time.time() + 120 + async with RedisMessageBus(host=HOST, port=PORT) as bus: + while time.time() < deadline: + if fr.get(STOP) == "1": + break + did = False + for in_q, role_name, out_q in handlers: + items = await bus.queue_drain(in_q, max_count=1) + for _id, payload in items: + did = True + if role_name == "planner": + out = await agent_say("planner", f"Seed: {payload['seed']}") + await bus.queue_push(out_q, {**payload, "concept": out, "plan_pid": pid}) + print(f"[{role} pid={pid}] Planner→concept: {out!r}", flush=True) + elif role_name == "designer": + out = await agent_say("designer", f"Concept: {payload['concept']}") + await bus.queue_push(out_q, {**payload, "mechanic": out, "design_pid": pid}) + print(f"[{role} pid={pid}] Designer→mechanic: {out!r}", flush=True) + elif role_name == "namer": + out = await agent_say( + "namer", f"Concept: {payload['concept']}\nMechanic: {payload['mechanic']}") + await bus.queue_push(out_q, {**payload, "name": out, "name_pid": pid}) + print(f"[{role} pid={pid}] Namer→title: {out!r}", flush=True) + if not did: + await asyncio.sleep(0.3) + print(f"[worker {role} pid={pid}] 退出", flush=True) + + +async def coordinator(): + pid = os.getpid() + fr = rflag() + async with RedisMessageBus(host=HOST, port=PORT) as bus: + for q in (Q_PLAN, Q_DESIGN, Q_NAME, Q_DONE): + await bus.queue_delete(q) + fr.delete(STOP) + print(f"[coordinator pid={pid}] 播种 seed→q_plan: {SEED!r}", flush=True) + await bus.queue_push(Q_PLAN, {"seed": SEED}) + result, deadline = None, time.time() + 100 + while time.time() < deadline: + items = await bus.queue_drain(Q_DONE, max_count=1) + if items: + result = items[0][1] + break + await asyncio.sleep(0.4) + fr.set(STOP, "1") # 通知 worker 收工 + if not result: + print("[coordinator] FAIL:超时未收到 q_done 结果") + return 1 + cross = result.get("design_pid") != result.get("plan_pid") # Designer 在另一进程 + same_w1 = result.get("plan_pid") == result.get("name_pid") # Planner/Namer 同进程 + pids = {k: result.get(k) for k in ("plan_pid", "design_pid", "name_pid")} + pids["coordinator_pid"] = pid + print("\n==== 3-agent 跨进程协作产物 ====") + print("seed :", result.get("seed")) + print("concept :", result.get("concept"), f"(W1 pid={result.get('plan_pid')})") + print("mechanic :", result.get("mechanic"), f"(W2 pid={result.get('design_pid')})") + print("title :", result.get("name"), f"(W1 pid={result.get('name_pid')})") + print("PIDs :", pids) + print(f"跨进程证明:design_pid≠plan_pid = {cross} | Planner/Namer 同进程 = {same_w1}") + ok = bool(result.get("concept") and result.get("mechanic") and result.get("name") and cross) + print("闸门1 判定:", + "PASS:3 agent 跨 ≥2 OS 进程经 RedisMessageBus 协作产出" if ok else "FAIL") + os.makedirs("artifacts", exist_ok=True) + json.dump({"result": result, "pids": pids, "cross_process": cross, "same_w1": same_w1, "pass": ok}, + open("artifacts/gate1_distributed.json", "w"), ensure_ascii=False, indent=2) + return 0 if ok else 1 + + +if __name__ == "__main__": + cmd = sys.argv[1] if len(sys.argv) > 1 else "coordinator" + if cmd == "worker": + asyncio.run(worker(sys.argv[2])) + elif cmd == "coordinator": + sys.exit(asyncio.run(coordinator())) + else: + print("usage: gate1_distributed.py [worker W1|worker W2|coordinator]") + sys.exit(2) diff --git a/spikes/agentscope-wg1/src/gate2_persist.py b/spikes/agentscope-wg1/src/gate2_persist.py new file mode 100644 index 00000000..d20fc4ab --- /dev/null +++ b/spikes/agentscope-wg1/src/gate2_persist.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +"""闸门2:持久化/恢复实测(验不过命中 §5 触发④)。 + +已验证机制(AgentScope 2.0.1): + - agent.state 是 AgentState(pydantic),持有 context(list[Msg] 对话/工具历史)、cur_iter 等编排执行态; + - 持久化 = state.model_dump_json() → 存 Redis; + - 恢复 = Redis 读回 → AgentState.model_validate_json() → Agent(..., state=loaded) 续跑。 + 这等价于 AgentScope app 层 RedisStorage(SessionRecord 内嵌 AgentState)的「每轮落盘」, + 但去掉 FastAPI 整机,使「中断→恢复」证据最小、最透明、可审计。 + +崩溃模型:run1 跑若干轮、每轮落 Redis 后用 os._exit(137) 硬退出(无任何优雅清理,等价 SIGKILL); + run2 是全新 OS 进程,只能从 Redis 恢复——若能答出崩溃前注入的记忆,即证明「状态跨进程无损」。 + +用法: + python gate2_persist.py run1 [--crash-after N] # 跑前 N 轮,逐轮落 Redis,然后硬崩 + python gate2_persist.py run2 # 新进程:从 Redis 恢复,考记忆,判 PASS/FAIL + python gate2_persist.py block # 跑 2 轮落盘后阻塞,供外部 kill -9 真硬杀 +""" +import asyncio +import json +import os +import sys + +import redis # 来自 agentscope[storage] + +import _common +from agentscope.agent import Agent +from agentscope.state import AgentState + +REDIS_HOST = os.environ.get("WG1_REDIS_HOST", "127.0.0.1") +REDIS_PORT = int(os.environ.get("WG1_REDIS_PORT", "6399")) +KEY = os.environ.get("WG1_SESSION_KEY", "wg1:gate2:session") + +SYS = ("You are a helpful assistant. Carefully remember every fact the user tells you, " + "and recall them exactly when asked.") +# 前几轮注入记忆,崩溃后最后一轮考记忆 +TURNS_IN = [ + "My name is Alice.", + "My project is codenamed Zephyr.", + "I prefer dark mode UI.", +] +QUESTION = ("Recall exactly the facts I told you earlier: my name, my project codename, " + "and my UI preference. Answer in one short line.") +EXPECT = ["alice", "zephyr", "dark"] # 期望恢复后能复述的关键记忆 + + +def rconn(): + return redis.Redis(host=REDIS_HOST, port=REDIS_PORT, db=0, decode_responses=True) + + +def persist(r, state: AgentState): + """把 AgentState 序列化落 Redis(单键即一条 session 快照)。""" + r.set(KEY, state.model_dump_json()) + + +def load(r): + raw = r.get(KEY) + return AgentState.model_validate_json(raw) if raw else None + + +async def run1(crash_after=2): + r = rconn() + r.delete(KEY) + agent = Agent(name="mem", system_prompt=SYS, model=_common.build_model()) + for i in range(crash_after): + msg = TURNS_IN[i] + await agent.reply(_common.user_msg(msg)) + persist(r, agent.state) + print(f"[run1] turn{i+1} 已落 Redis:{msg!r} | context msgs={len(agent.state.context or [])}") + snap = r.get(KEY) + print(f"[run1] 模拟崩溃:已持久化 {crash_after} 轮,Redis 快照 {len(snap)} bytes,进程硬退出(os._exit 137)") + sys.stdout.flush() + os._exit(137) # 无优雅清理,等价 SIGKILL 崩溃 + + +async def run2(): + r = rconn() + state = load(r) + if state is None: + print("[run2] FAIL:Redis 无快照,无法恢复") + return 1 + print(f"[run2] 从 Redis 恢复 AgentState:context msgs={len(state.context or [])}、cur_iter={state.cur_iter}") + agent = Agent(name="mem", system_prompt=SYS, model=_common.build_model(), state=state) + reply = await agent.reply(_common.user_msg(QUESTION)) + text = reply.get_text_content() + low = text.lower() + hit = [e for e in EXPECT if e in low] + ok = len(hit) == len(EXPECT) + print(f"[run2] 恢复后提问:{QUESTION!r}") + print(f"[run2] agent 回答:{text!r}") + print(f"[run2] 记忆命中 {len(hit)}/{len(EXPECT)} {hit} → " + f"{'PASS:状态跨进程无损恢复' if ok else 'FAIL:记忆缺失'}") + os.makedirs("artifacts", exist_ok=True) + json.dump({"recovered_context_msgs": len(state.context or []), "cur_iter": state.cur_iter, + "question": QUESTION, "answer": text, "expect": EXPECT, "hit": hit, "pass": ok}, + open("artifacts/gate2_persist.json", "w"), ensure_ascii=False, indent=2) + return 0 if ok else 1 + + +async def block(): + """跑 2 轮落盘后阻塞,供外部 `kill -9 ` 做真·硬杀演示。""" + r = rconn() + r.delete(KEY) + agent = Agent(name="mem", system_prompt=SYS, model=_common.build_model()) + for i in range(len(TURNS_IN)): + await agent.reply(_common.user_msg(TURNS_IN[i])) + persist(r, agent.state) + print(f"[block] turn{i+1} 已落 Redis:{TURNS_IN[i]!r}") + print(f"[block] PID={os.getpid()} 已落盘 {len(TURNS_IN)} 轮,阻塞等待外部 kill -9 ...") + sys.stdout.flush() + while True: + await asyncio.sleep(3600) + + +if __name__ == "__main__": + cmd = sys.argv[1] if len(sys.argv) > 1 else "run1" + if cmd == "run1": + n = 2 + if "--crash-after" in sys.argv: + n = int(sys.argv[sys.argv.index("--crash-after") + 1]) + asyncio.run(run1(n)) + elif cmd == "run2": + sys.exit(asyncio.run(run2())) + elif cmd == "block": + asyncio.run(block()) + else: + print("usage: gate2_persist.py [run1 [--crash-after N] | run2 | block]") + sys.exit(2) diff --git a/spikes/agentscope-wg1/src/gate3_overhead.py b/spikes/agentscope-wg1/src/gate3_overhead.py new file mode 100644 index 00000000..3ac6a663 --- /dev/null +++ b/spikes/agentscope-wg1/src/gate3_overhead.py @@ -0,0 +1,211 @@ +# -*- coding: utf-8 -*- +"""闸门3:L1 退化开销实测(§5 触发⑤ 判定)。 + +目标:同一最小 LLM 调用,对照三条路径的延迟/token 开销: + (A) 裸 openai SDK 直调 new-api(= §3「裸 llm_client」L1 最短路径基线); + (B) AgentScope 模型客户端 OpenAIChatModel.__call__(仅模型层,无 agent/图/落盘); + (C) AgentScope 最小 Agent.reply(关图义=空 toolkit 单轮、关落盘=无 app/Redis)。 + +关键测量: + - input_tokens 膨胀:Agent 强制注入 system_prompt + ReAct 脚手架 → L1 海量调用的固定税; + - 本地封装开销:local = wall - api_time(api_time 取框架自报 usage.time / openai usage), + 剔除 LLM 网络耗时后,纯框架 CPU 开销; + - 总延迟:中位数/p90(LLM 主导,reasoning 模型有方差,故以 local 与 token 为主信号)。 + +结论口径:若 (C) 相对 (A) 的 token 膨胀或本地开销「吃掉便宜档单价」→ 命中 §5-⑤,L1 退 §3 裸通路 +(注:此为 L1 旁路化决策的实证,不等于 AgentScope 出局;L2/L3 仍用框架原语)。 +""" +import asyncio +import os +import statistics +import time +import json + +import openai + +import _common +from agentscope.agent import Agent, ReActConfig +from agentscope.model import OpenAIChatModel +from agentscope.credential import OpenAICredential + +# ---- 实验参数(可被环境变量覆盖)---- +N = int(os.environ.get("WG1_N", "20")) # 测量轮数 +WARMUP = int(os.environ.get("WG1_WARMUP", "3")) # 预热轮数(丢弃) +MODEL = _common.L1_MODEL +PROMPT = "What is 7 plus 6? Reply with just the number." # 固定确定性任务,尽量压低生成方差 +SYS_PROMPT = "You are a helpful assistant. Answer concisely." # Agent 必填的最小 system_prompt +MAX_TOKENS = int(os.environ.get("WG1_MAXTOK", "64")) +# 模型优先级:网关某模型瞬时不可用时自动回退到下一个(开销 delta 与模型无关) +PRIORITY = os.environ.get( + "WG1_MODELS", "deepseek-v4-flash,MiniMax-M2,deepseek-v4-pro,MiniMax-M2.5").split(",") + + +async def pick_healthy_model(): + """运行时挑一个当前健康的模型(每个候选试 3 次),返回首个可用,记录实际所用。""" + client = openai.AsyncOpenAI(api_key=_common.get_api_key(), base_url=_common.BASE_URL) + for m in PRIORITY: + for _ in range(3): + try: + await client.chat.completions.create( + model=m, messages=[{"role": "user", "content": "ping"}], + max_tokens=8, temperature=0) + return m + except Exception: + await asyncio.sleep(0.6) + raise RuntimeError("无可用模型(全部候选 3 次均失败)") + + +class _RecordingModel(OpenAIChatModel): + """记录每次模型调用 usage 的子类,用于捕获 Agent 内部真实发出的 token。""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.records = [] # 每次调用的 (input_tokens, output_tokens, api_time) + + async def __call__(self, messages, **kwargs): + resp = await super().__call__(messages, **kwargs) + # stream=False:resp 为单个 ChatResponse + u = resp.get("usage") if hasattr(resp, "get") else getattr(resp, "usage", None) + if u is not None: + self.records.append(( + getattr(u, "input_tokens", 0) or 0, + getattr(u, "output_tokens", 0) or 0, + float(getattr(u, "time", 0.0) or 0.0), + )) + return resp + + +def _stats(xs): + """中位数/p90/均值,空列表安全。""" + if not xs: + return {"median": None, "p90": None, "mean": None, "n": 0} + s = sorted(xs) + p90 = s[min(len(s) - 1, int(round(0.9 * (len(s) - 1))))] + return {"median": round(statistics.median(xs), 4), "p90": round(p90, 4), + "mean": round(statistics.fmean(xs), 4), "n": len(xs)} + + +async def measure(make_coro, tries=20, delay=1.0): + """对一次异步调用计时;内部对瞬时网关错误(如 502)重试,仅对成功调用计时, + 保证 502 抖动既不崩溃测量、也不污染延迟样本。""" + last = None + for _ in range(tries): + try: + t = time.perf_counter() + r = await make_coro() + return time.perf_counter() - t, r + except Exception as e: # spike 容错:吞瞬时错误后重试 + last = e + await asyncio.sleep(delay) + raise last + + +async def arm_bare(n): + """(A) 裸 openai SDK 直调 new-api。""" + client = openai.AsyncOpenAI(api_key=_common.get_api_key(), base_url=_common.BASE_URL) + walls, apis, ins, outs = [], [], [], [] + for _ in range(n): + dt, r = await measure(lambda: client.chat.completions.create( + model=MODEL, messages=[{"role": "user", "content": PROMPT}], + temperature=0, max_tokens=MAX_TOKENS, stream=False, + )) + walls.append(dt) + apis.append(dt) # 裸路无本地封装,api_time≈wall + u = r.usage + ins.append(u.prompt_tokens); outs.append(u.completion_tokens) + return walls, apis, ins, outs + + +async def arm_model(n): + """(B) AgentScope 模型客户端(仅模型层)。""" + model = _common.build_model(model_name=MODEL, stream=False, max_retries=0) + walls, apis, ins, outs = [], [], [], [] + for _ in range(n): + dt, resp = await measure( + lambda: model([_common.user_msg(PROMPT)], temperature=0, max_tokens=MAX_TOKENS)) + walls.append(dt) + u = resp.get("usage") + apis.append(float(getattr(u, "time", dt) or dt)) + ins.append(getattr(u, "input_tokens", 0)); outs.append(getattr(u, "output_tokens", 0)) + return walls, apis, ins, outs + + +async def arm_agent(n): + """(C) AgentScope 最小 Agent(空 toolkit 单轮、无 app/Redis = 关图关落盘)。""" + model = _RecordingModel( + credential=OpenAICredential(api_key=_common.get_api_key(), base_url=_common.BASE_URL), + model=MODEL, stream=False, max_retries=0, + ) + walls, apis, ins, outs, iters = [], [], [], [], [] + for _ in range(n): + before = len(model.records) + + async def _one(): + # 每次重试都用全新 Agent,避免失败重试污染单 agent 的 context + agent = Agent(name="bench", system_prompt=SYS_PROMPT, model=model, + react_config=ReActConfig(max_iters=5)) + return await agent.reply(_common.user_msg(PROMPT)) + + dt, _ = await measure(_one) + calls = model.records[before:] + walls.append(dt) + apis.append(sum(c[2] for c in calls)) + ins.append(sum(c[0] for c in calls)); outs.append(sum(c[1] for c in calls)) + iters.append(len(calls)) # agent 内部模型调用次数(理想=1) + return walls, apis, ins, outs, iters + + +async def main(): + global MODEL + MODEL = await pick_healthy_model() # 运行时选定健康模型 + print(f"# 闸门3 L1 开销 model={MODEL} N={N}(warmup={WARMUP}) max_tokens={MAX_TOKENS}") + print(f"# prompt={PROMPT!r}") + + # 预热(同时验证三条路径 live 可用) + await arm_bare(WARMUP); await arm_model(WARMUP); await arm_agent(WARMUP) + + bw, ba, bi, bo = await arm_bare(N) + mw, ma, mi, mo = await arm_model(N) + aw, aa, ai, ao, it = await arm_agent(N) + + def local(walls, apis): + return [w - a for w, a in zip(walls, apis)] + + rows = { + "A_bare_openai": {"wall": _stats(bw), "api": _stats(ba), "local": _stats(local(bw, ba)), + "in_tok": statistics.median(bi), "out_tok": statistics.median(bo)}, + "B_agentscope_model": {"wall": _stats(mw), "api": _stats(ma), "local": _stats(local(mw, ma)), + "in_tok": statistics.median(mi), "out_tok": statistics.median(mo)}, + "C_agentscope_agent": {"wall": _stats(aw), "api": _stats(aa), "local": _stats(local(aw, aa)), + "in_tok": statistics.median(ai), "out_tok": statistics.median(ao), + "model_calls_per_reply": _stats(it)}, + } + + print("\n{:<22} {:>10} {:>10} {:>10} {:>8} {:>8}".format( + "arm", "wall_med", "local_med", "api_med", "in_tok", "out_tok")) + for k, v in rows.items(): + print("{:<22} {:>10} {:>10} {:>10} {:>8} {:>8}".format( + k, v["wall"]["median"], v["local"]["median"], v["api"]["median"], + v["in_tok"], v["out_tok"])) + + # 关键差值 + in_inflation = rows["C_agentscope_agent"]["in_tok"] - rows["A_bare_openai"]["in_tok"] + local_overhead_ms = (rows["C_agentscope_agent"]["local"]["median"] - + rows["A_bare_openai"]["local"]["median"]) * 1000 + print("\n## 关键差值(Agent 相对裸路)") + print(f" input_token 膨胀:{in_inflation:+.0f} tok/次 " + f"(裸 {rows['A_bare_openai']['in_tok']:.0f} → Agent {rows['C_agentscope_agent']['in_tok']:.0f})") + print(f" 本地封装开销:{local_overhead_ms:+.1f} ms/次(剔除 LLM 网络耗时)") + print(f" Agent 单次 reply 内部模型调用次数中位数:{rows['C_agentscope_agent']['model_calls_per_reply']['median']}") + + out = {"model": MODEL, "N": N, "prompt": PROMPT, "sys_prompt": SYS_PROMPT, + "max_tokens": MAX_TOKENS, "rows": rows, + "input_token_inflation": in_inflation, "local_overhead_ms": round(local_overhead_ms, 2)} + os.makedirs("artifacts", exist_ok=True) + with open("artifacts/gate3_overhead.json", "w") as f: + json.dump(out, f, ensure_ascii=False, indent=2) + print("\n# 写出 artifacts/gate3_overhead.json") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/wg1/gen-worker/.gitignore b/wg1/gen-worker/.gitignore new file mode 100644 index 00000000..65b3bc8b --- /dev/null +++ b/wg1/gen-worker/.gitignore @@ -0,0 +1,8 @@ +# wg1/gen-worker 本地产物与密钥 —— 绝不入库(密钥另受根 .gitignore:11 .env 兜底) +.env +.env.* +__pycache__/ +*.pyc +.venv/ +*.output +.cost-logs/ diff --git a/wg1/gen-worker/README.md b/wg1/gen-worker/README.md new file mode 100644 index 00000000..8299ad26 --- /dev/null +++ b/wg1/gen-worker/README.md @@ -0,0 +1,59 @@ +# wg1/gen-worker —— W-G1 L1 生成 worker(便宜模型 → 可真玩轻游戏) + +> **结论看 [`REPORT.md`](REPORT.md)**(durable)。本文件 = 如何跑。 +> 验证 HJ-GEN-001:便宜模型(new-api)在插件库+装载契约上写出可真玩轻游戏,质量由 harness 七门保证。 + +## 它做什么 +`brief(题面)→ 便宜模型写 GameHostFactory 源码 → 静态校验门 → esbuild 打 __GameBundle iife → P1 宿主 bootGameHost 装载 → 本机 Chrome+CDP 真玩七门取证`,失败回喂错因重试 ≤N。**"能生成代码 ≠ 能玩"——必须过真玩门才算 pass。** + +## 目录 +``` +wg1/gen-worker/ +├── REPORT.md # 交付报告(结论/四件套/成本/坑/最优模型) +├── requirements.txt # openai==2.41.1 + json-repair +├── .env # NEWAPI_KEY 等(gitignored,绝不入库) +├── worker/ +│ ├── _client.py # 裸 openai 客户端 + 代理旁路 + usage(复用 spike 范式) +│ ├── prompt.py # 生成上下文包(契约/能力面/禁用项/few-shot)→ system+user +│ ├── validate.py # 校验门:抽码 + 静态契约扫描 + node --check 语法 +│ ├── cost.py # ¥ 折算(new-api quota 口径,/api/pricing+/api/status) +│ └── run.py # 编排(§3 job-in/result-out + 重试门) +├── briefs/ # pong.json / simon.json / whack.json(题面 + CDP play-spec) +└── results/ # 每 run 结果(pass/retries/verdict 七门/tokens) +# 生成游戏产物在 game-runtime/games/_wg1-gen//(见该目录 .agent,解释为何落那) +``` + +## 前置(本机一次) +```bash +# 1) 密钥(gitignored,走环境):编辑 wg1/gen-worker/.env 写 NEWAPI_KEY(向创始人要) +# 2) game-runtime 工具链(esbuild + ws,CDP 驱动用) +npm i --prefix game-runtime +# 3) worker venv +uv venv wg1/gen-worker/.venv --python 3.12 +uv pip install -p wg1/gen-worker/.venv/bin/python -r wg1/gen-worker/requirements.txt +# 4) 自测连通(列模型,零成本) +wg1/gen-worker/.venv/bin/python wg1/gen-worker/worker/_client.py +``` +> 依赖本机 macOS + Google Chrome(headless)+ Tailscale 可达 new-api 网关 `100.64.0.8:3000`。 + +## 跑 +```bash +# 生成 + 真玩一款(默认 deepseek-v4-flash;--model 换模型;--max-retries N) +wg1/gen-worker/.venv/bin/python wg1/gen-worker/worker/run.py pong +wg1/gen-worker/.venv/bin/python wg1/gen-worker/worker/run.py simon --model deepseek-v4-pro +wg1/gen-worker/.venv/bin/python wg1/gen-worker/worker/run.py whack +# 成本表(聚合 results/*.json) +wg1/gen-worker/.venv/bin/python wg1/gen-worker/worker/cost.py +# 仅重放某款已生成 bundle(不重新生成,调试 harness 用) +( cd game-runtime && bash games/_wg1-gen/_shared/serve-and-play.sh pong ) +``` +新游戏:在 `briefs/.json` 写 `{title, brief, play_spec:{inputs,expectedEngineCallPrefixes}}`,再 `run.py `。 + +## 七门真玩判据(全过才 PASS,详见 REPORT §2) +A 装载 · B 未捕获 · C 掌帧[20,45] · D 真渲染 · E 活性 · F 真接线(__engineCalls) · **G 输入有效(确定性 A/B 对照)**。 +verdict 落 `game-runtime/games/_wg1-gen//evidence/verdict.json` + 首帧/玩后截图。 + +## 边界 +- 只消费冻结契约(game-host.d.ts / boot-game-host.js / __GameBundle / bootGameHost),零修改。 +- 不推 dev/2.0.0;只在 lane 分支 `wg1/gen-worker`。 +- 不做(创始人并行 P3/mainline):AigcGenerateExecutor 接线、白名单注册、全 20 游戏 bake-off、judge 评分。 diff --git a/wg1/gen-worker/REPORT.md b/wg1/gen-worker/REPORT.md new file mode 100644 index 00000000..d8bbe982 --- /dev/null +++ b/wg1/gen-worker/REPORT.md @@ -0,0 +1,152 @@ +# W-G1 生成核心 · 交付报告(结论先行) + +> lane:`wg1/gen-worker`(从 `spike/agentscope-wg1` HEAD = dev/2.0.0 + 已落地 P1/P2/spike 切出)| 日期:2026-06-13 +> 验证假设 **HJ-GEN-001**:便宜模型(new-api: DeepSeek-V4 / MiniMax)能在【插件库 + 装载契约】上写出**可真玩**的轻游戏;质量由 **harness 门**保证,非模型自觉。 + +--- + +## 0. 结论速览 + +**结论:成立。便宜模型能可靠产出可真玩的轻游戏。** 用最便宜档 `deepseek-v4-flash` 生成 3 款冒烟游戏,全部经 **CDP 真机 Chrome 七门真玩**通过,**单款 ¥0.01–0.03(远低于 ¥0.15 L1 闸门,5–15× 余量)**。 + +| 游戏 | 模型 | 真玩七门 | 重试 | ¥(上界) vs ¥0.15 | +|---|---|---|---|---| +| Pong 弹球 | deepseek-v4-flash | ✅ 7/7 | 0 | **¥0.0098** ✅ | +| 打地鼠 Whack | deepseek-v4-flash | ✅ 7/7 | 0 | **¥0.0136** ✅ | +| Simon 记忆 | deepseek-v4-flash | ✅ 7/7 | 2 | **¥0.0298** ✅ | + +**最关键的一条(必须如实传达)**:**「能生成代码」≠「能玩」**。本 lane 实证了这一点——一处由**我方 prompt 写错**的输入坐标契约(声称 x/y∈[0,1],实为逻辑像素)让所有生成游戏"能编译、能渲染、能动",但**玩家点击全部失灵**;Pong 因小球自走动画**假绿混过**初版门,Simon 因无自走动画被门**正确判否**。**正是真玩门(而非"代码编译过")逮住了它。** 修复 prompt + 加装「输入有效性确定性对照门」后,三款全部真过。 + +--- + +## 1. 产物靶与全链路(只消费冻结契约,零改 P1/P2) + +``` +brief → 便宜模型 → factory.js(纯 GameHostFactory 模块:默认导出,零引擎 import,能力经 boot.ctx) + ↓ 通用壳(复用 ref buildRefHostConfig:标准 7 插件 wiring,仅 override factory) + entry-bundle.js → esbuild --global-name=__GameBundle → bundle.iife.js(引擎内联 265KB) + ↓ index.html: window.__GameBundle.bootGameHost({canvas, recHook, onReady}) + static-serve + 本机 Chrome(headless) + CDP → 七门真玩取证 +``` + +- **冻结契约零修改**:`game-host.d.ts` / `boot-game-host.js` / 6 受控面 / `__GameBundle` / `bootGameHost` 全程只消费。 +- **生成游戏落 `game-runtime/games/_wg1-gen/`**(新建隔离子目录,零碰既有文件)——因生成游戏本质是 game-runtime 游戏(动态 import `littlejsengine`、import `../../../src/plugins/*`、复用 `ref-host-config.js`),esbuild 默认解析要求入口在 node_modules 可达处。worker(Python) 与报告留 `wg1/gen-worker/`。详见 [`games/_wg1-gen/.agent`](../../game-runtime/games/_wg1-gen/.agent)。 +- **唯一对既有树的非生成改动**:`game-runtime/package.json` 加 `ws`(devDep,CDP 驱动用,ref harness 亦需)。 + +--- + +## 2. 真玩取证 harness:七道假绿守卫(false-green guard) + +每款游戏经下列七门,**全过才判 PASS**(驱动 = [`games/_wg1-gen/_shared/play.cdp.cjs`](../../game-runtime/games/_wg1-gen/_shared/play.cdp.cjs),复用 `test/harness/browser-evidence.cjs`): + +| 门 | 判据 | 防的假绿 | +|---|---|---| +| **A 装载** | `__genBooted ∧ __gameHostEngineInitFired ∧ 无 bootError` | 白屏 / 装载失败 | +| **B 未捕获** | `__genInternals.uncaught == [] ∧ 无 __gameHostBootError` | 运行期报错 | +| **C 掌帧** | `__engine.frame` 500ms 增量 ∈ [20,45](@60fps≈30) | 冻屏 / 失控 / 单步假推进 | +| **D 真渲染** | `#game-engine` readback 有色像素(maxCh>80)>50 | 白屏 / 全黑 | +| **E 活性** | 真玩全程 ≥2 个不同整帧哈希态 | 冻屏(多采样捕捉瞬时态) | +| **F 真接线** | `__engineCalls` 经 recHook 含期望 call-ID(粒子/音效/数学) | 自绘伪装、没真用插件库/引擎 | +| **G 输入有效** | **同 seed 再开无输入对照实例、推进到同一帧、整帧哈希 ≠ 有输入实例** | **靠自走动画蒙混过 E 的假绿** | + +> **G 门是本 lane 关键发明**:Pong/打地鼠有自走动画(球/地鼠),E 门会被自走动画满足、掩盖「输入失灵」。G 门用**确定性 A/B 对照**(new-api 生成 bundle seed 固定→自走部分逐帧确定)隔离出「输入到底改没改变游戏走向」——挡板位置 / Simon 轮次 / 打地鼠分数都会持续到对照帧,有输入≠无输入即证真可玩。 + +**golden-path 自检(证 harness 可信)**:先用 ref 工厂(已知好)跑通整条链——5/6 门过、F=0(菜单态不调引擎,**正确**);再用最小 probe 工厂(确定性调 getEngine)→ 7/7 全过。**harness 在真可玩上判过、在没真调引擎/没真响应输入时判否**,无假绿。 + +--- + +## 3. 逐款四件套(真玩证据) + +> 证据落 `game-runtime/games/_wg1-gen//evidence/{first-paint.png, after-play.png, verdict.json}`。 + +### Pong 弹球(deepseek-v4-flash · 0 重试 · ¥0.0098) +- **①截图**:竖屏弹球——白球在场、青色玩家挡板(已移到末次点击 x)、虚线中线、`Player:0 CPU:1`(真打了一回合)、撞击红粒子。 +- **②掌帧**:Δframe=31(C✅)。**③渲染**:maxCh=255、有色像素满屏(D✅)。**④真接线**:`__engineCalls` 含 `particles.spawnEmitter`/`audio.synth.synthSfx`(撞击反馈,F✅)。 +- **输入有效(G✅)**:有输入态 `0d7715dc` ≠ 无输入对照 `855a1c03` @frame444 → 挡板真响应点击。228 行源码,`export default createPongGame`,`ctx.random`/`ctx.getInput`/`ctx.time` 全受控。 + +### 打地鼠 Whack(deepseek-v4-flash · 0 重试 · ¥0.0136) +- **①截图**:`得分:0`、3×3 深色洞口、两只地鼠(棕圆+眼睛+腮红)正冒出。 +- **②③④**:C✅ / D✅(maxCh255) / F✅(命中粒子 + 冒出音效)。 +- **输入有效(G✅)**:`a9de479b ≠ b0584efe` @frame446 → 点击真改变游戏(命中/分数)。命中判定为自写"点到圆距"(不依赖网格/CCD)。 + +### Simon 记忆(deepseek-v4-flash · 2 重试 · ¥0.0298) +- **①截图**:`Round:1`、`Your turn!`、红/绿/蓝/黄 2×2 大按钮。 +- **②③④**:C✅(Δ31) / D✅(maxCh255,bright272006) / F✅(序列音效 `audio.synth.synthSfx` + 缓动 `math.easing.quadOut`)。 +- **输入有效(G✅)**:`a5100b7a ≠ f7530fdd` @frame400 → 点击真推进序列/轮次。状态机(INIT→SHOWING→WAIT→PAUSE/FAIL)完整。 +- **重试原因**:附录 A——首版坐标错(修 prompt 前)/ 逻辑边界,靠错误回喂 3 轮内收敛。 + +--- + +## 4. 成本表 + 模型对比 → 最优模型 + +口径:`quota=(prompt+completion×completion_ratio)×model_ratio×group_ratio(1.0)`;`¥=quota/500000×7.3`(`/api/status` 实拉)。**¥为上界**(不计 prompt 缓存折扣;精确 `logs.quota` 需网关 access token,sk- key 无管理权——留给创始人核)。reasoning_tokens 已计入 completion。 + +| 游戏(难度) | 模型 | 重试 | prompt/completion tok | ¥上界 | vs ¥0.15 | +|---|---|---|---|---|---| +| Pong(易) | deepseek-v4-flash | 0 | 2861 / 4775 | 0.0098 | ✅ 15× 余量 | +| 打地鼠(易+) | deepseek-v4-flash | 0 | 2899 / 7223 | 0.0136 | ✅ 11× | +| Simon(中) | deepseek-v4-flash | 2 | 9120 / 14220 | 0.0298 | ✅ 5× | +| **Simon** | **deepseek-v4-pro** | **0** | 2889 / 9445 | 0.0625 | ✅ | +| Simon | MiniMax-M2.7 | 1 | 5582 / 11912 | 0.1166 | ✅(贴闸门) | + +**最优模型结论**: +- **默认 = `deepseek-v4-flash`**:最便宜(model_ratio 0.06 / completion_ratio 1.75),易档 0 重试 ¥0.01;难档(Simon)靠重试门兜(2 重试仍 ¥0.03)。 +- **难档升级 = `deepseek-v4-pro`**:Simon **0 重试**、¥0.06(2× flash 但仍极廉),可靠性最高。**建议策略:flash 打底 + 耗尽重试自动升 pro。** +- **MiniMax 不优先**:M2.7 completion_ratio=4 拉高成本(¥0.117 贴近闸门),可靠性不及 pro。 + +--- + +## 5. 五大坑(给主 agent / 创始人少踩半天) + +1. **【实测·最坑】受控输入 x/y 是逻辑像素不是 [0,1]**:`boot-game-host.js:295` `x=(clientX-rect.left)/rect.width*VIEW_W(390)`。ref 直接 `hitZone(e.x,e.y)` 用像素。若 prompt 误导模型"乘视口"→命中全爆掉、点击失灵,但**代码照编译照渲染照动**——只有真玩门逮得住。**生成 prompt 的能力契约必须逐字对齐 boot-game-host 实际口径。** +2. **【实测】自走动画会制造假绿**:有自走物(球/地鼠)的游戏,"画面变了"(E)≠"输入有效"。**必须加 G 门(确定性 A/B 对照)**才能证真可玩。 +3. **【实测】reasoning 模型吃 max_tokens**:deepseek-v4-flash/MiniMax 是 reasoning 模型,reasoning_tokens 计入 completion 且可烧空可见 content(`finish_reason:length` 时 content 空)。**max_tokens 须给足(本 worker 16000),否则截断→校验门拒→空转重试。** +4. **【实测】CDP 触摸要镜像 ref 范式**:`Input.dispatchTouchEvent` 裸 `{x,y}` 点、touchStart→touchEnd 背靠背、坐标经 `c.width/dpr` 映射(非硬编码 390);加 `radius/force` 或长按反而不稳。 +5. **【实测·复用 spike】本机代理吃网关**:`NO_PROXY` 须并 `100.64.0.8`(_client.py 已内置),否则 SDK→502(curl 假通)。 + +--- + +## 6. 哪些游戏类型超出当前插件库能力(来自 20 基准交叉比对) + +便宜模型受**插件库门面缺口**限制,非模型能力限制。当前 4 短板(详见 `docs/agent-specs/2026-06-13-WG1-20经典轻游戏基准-review.md`): +- **① 文本/分数 HUD**🟡:无文本渲染门面,每款自 `fillText`(本冒烟可兜,但风格各异)。**最高频缺口,建议 W-G1 后第一优先补门面。** +- **② 网格/棋盘 grid**🟡:无 tilemap 门面 → 2048/Tetris/Match-3/贪吃蛇/井字棋 网格态每款重写易出 bug。 +- **③ 连续碰撞 CCD**❌(真缺口):collision 仅离散 MTV,无 swept/toi → 高速小球(Breakout 高速/Asteroids 子弹/多球)穿透。**冒烟刻意避开。** +- **④ 手势 swipe/drag**🟡:getInput 仅 5 类原始事件,无手势合成 → 愤怒小鸟拖拽蓄力/2048 滑动每款自缓存方向。 + +→ **本冒烟选 Pong/Simon/打地鼠 正是"零/最轻短板 + canvas 简单"的最干净子集**(避开 Snake/2048/Cookie Clicker——它们撞①②)。 + +--- + +## 7. worker ↔ pipeline 接缝(留给创始人集成,§3 契约形状) + +worker 已暴露「job in → result out」([`worker/run.py:run_job`](worker/run.py)): +- **in**:`{game_id, brief(题面), play_spec(CDP 输入+期望 call-ID), model, max_retries}` +- **out**(`results/.json`):`{pass, retries, attempts[{stage,errors,usage}], factory_path, bundle_path, verdict(七门), tokens, request_ids}` +- 闭环:generate → validate(静态契约+`node --check`) → bundle(esbuild) → play(CDP 七门) → 失败回喂错因重试 ≤N。 +- 字段对齐你 spike VERDICT §3 的 REST/队列形状;待你拉取后冻结。 + +--- + +## 8. 蒸馏建议(留我 lane,待你拉进 `.agents/`,避免与你并行 P3 撞车) + +1. **`skills/` 增补**:把「§2 七门真玩 harness(尤其 G 门 A/B 对照)+ §5 五坑」蒸馏进 `game-e2e-cdp-harness.md`(W-G1 复用并扩展了它)。 +2. **`rules/` 红线**:「生成 prompt 能力契约必须逐字对齐 boot-game-host 实际口径(输入坐标=逻辑像素)」「能生成≠能玩:必须过真玩门+G 门」。 +3. **`knowledge/`**:HJ-GEN-001 验证结论(便宜模型可产可玩轻游戏 / 最优模型 flash 打底+pro 升级 / ¥0.01–0.06)。 + +--- + +## 附录 A · 复现 + +```bash +# 0) 前置:wg1/gen-worker/.env 写 NEWAPI_KEY(gitignored);game-runtime 先 npm i(含 ws) +# 1) 装 worker venv +uv venv wg1/gen-worker/.venv --python 3.12 +uv pip install -p wg1/gen-worker/.venv/bin/python -r wg1/gen-worker/requirements.txt +# 2) 生成+真玩一款(generate→validate→bundle→CDP 七门) +wg1/gen-worker/.venv/bin/python wg1/gen-worker/worker/run.py pong --model deepseek-v4-flash --max-retries 2 +# 3) 成本表 +wg1/gen-worker/.venv/bin/python wg1/gen-worker/worker/cost.py +# 仅重放某款(不重新生成): +( cd game-runtime && bash games/_wg1-gen/_shared/serve-and-play.sh pong ) +``` diff --git a/wg1/gen-worker/briefs/breakout.json b/wg1/gen-worker/briefs/breakout.json new file mode 100644 index 00000000..d6782ac8 --- /dev/null +++ b/wg1/gen-worker/briefs/breakout.json @@ -0,0 +1,27 @@ +{ + "title": "打砖块 Breakout", + "brief": "做一款经典打砖块 Breakout。竖屏逻辑视口 390×844。\n- 底部一块玩家挡板(水平移动,厚度≥14,避免高速穿透)。\n- 一个球斜向匀速运动:碰左/右墙与顶墙反弹;碰挡板反弹,且按击中挡板的位置微调水平速度(越靠边角度越斜)。\n- 顶部一片砖块网格(如 6 列 × 4~5 行),球击中砖块则该砖消除、得分 +1;可让部分砖需击中多次(颜色随剩余命数变化)增加层次。\n- 球掉到挡板下方(越过底边)= 失败;清光所有砖 = 通关。\n- 【终态契约·务必遵守】失败或通关都进入终态:把 _forensicsView().state().phase 置为 'gameover' 并【驻留】——画面停在终态(可显示 GAME OVER / YOU WIN 文案,可提示「点击重玩」),但在玩家主动点击重玩之前 phase 必须恒为 'gameover',**绝不自动重开 / 不下一帧复位回 playing**(宿主每 500ms 轮询 phase 判结束,瞬时终态会被漏读)。\n- 【控制·务必跟手】挡板朝触摸点 x 平滑逼近(每帧向目标 x 插值移动一定比例,如 0.2~0.35),**绝不是每次点击只挪一格**——玩家手指移到哪,挡板要顺滑跟过去。\n- 【可测性·务必导出位置】_forensicsView().state() 除 phase/score/remaining 外,额外导出 ball:{x,y,vx,vy} 和 paddle:{x,y,w}(实时真值,与画面一致)——harness 据此自动接球真玩并验证控制跟手与碰撞。\n- 球速中等:合速度约每秒 300~420 逻辑像素。\n- 反馈(juice):每次击碎砖块触发 getEngine().particles.spawnEmitter 粒子爆发 + getEngine().audio.synth.synthSfx 音效;撞墙/撞挡板也可给轻音效。\n- 画面:深色背景铺满 390×844;挡板/砖块用亮色实心矩形,球用亮色实心圆;顶部单行文字显示分数与剩余砖数。", + "play_spec": { + "controlCheck": { + "paddlePath": "paddle.x", + "paddleY": 800, + "tapXs": [50, 340], + "tapsPerTarget": 6, + "moveMin": 25, + "tolerance": 70, + "why": "挡板须平滑逼近触点 x(逮「一格一跳」/卡死:连点同一 x 后挡板应明显移动且最终靠近该 x)" + }, + "driver": { + "type": "paddle-intercept", + "ballPath": "ball.x", + "paddleY": 800, + "steps": 60, + "stepMs": 130 + }, + "expectedEngineCallPrefixes": ["particles.", "audio.synth"], + "assertAfterPlay": [ + { "path": "remaining", "op": "decreased", "why": "适配性真玩(挡板自动接球)下击碎砖块→剩余下降;接不住/碰撞失效则不降" } + ], + "expectLatch": true + } +} diff --git a/wg1/gen-worker/briefs/pong.json b/wg1/gen-worker/briefs/pong.json new file mode 100644 index 00000000..872f1f9a --- /dev/null +++ b/wg1/gen-worker/briefs/pong.json @@ -0,0 +1,20 @@ +{ + "title": "Pong 弹球", + "brief": "做一款经典 Pong 弹球游戏。竖屏逻辑视口 390×844。\n- 底部一块玩家挡板(水平移动),顶部一块电脑挡板(自动跟随球的 x,速度略慢于球,留出可玩性)。\n- 中间一个球,做斜向匀速运动;碰左右墙反弹,碰挡板反弹(反弹时根据击中挡板的位置微调水平速度)。\n- 球越过玩家挡板(掉到底部)或越过电脑挡板(飞出顶部)则该回合结束,球回到中心重新发球,并把对应一方的分数+1。\n- 球速保持中等:水平+竖直速度合起来大约每秒 300~420 逻辑像素,挡板不要太薄(厚度≥12),避免高速穿透。\n- 控制:玩家触摸屏幕任意位置,底部挡板朝触摸点的 x 平滑移动(每帧朝目标 x 逼近)。\n- 反馈:球每次反弹(撞墙或撞挡板)都触发一次 getEngine().particles.spawnEmitter 粒子爆发 + getEngine().audio.synth.synthSfx 音效。\n- 画面:深色背景铺满 390×844;挡板用亮色实心矩形,球用亮色实心圆;中线画一排虚线。可在顶部用单行文字显示比分(非必须)。", + "play_spec": { + "inputs": [ + { "t": "wait", "ms": 600 }, + { "t": "tap", "x": 100, "y": 740 }, + { "t": "wait", "ms": 450 }, + { "t": "tap", "x": 300, "y": 740 }, + { "t": "wait", "ms": 450 }, + { "t": "tap", "x": 195, "y": 740 }, + { "t": "wait", "ms": 450 }, + { "t": "tap", "x": 130, "y": 740 }, + { "t": "wait", "ms": 450 }, + { "t": "tap", "x": 270, "y": 740 }, + { "t": "wait", "ms": 400 } + ], + "expectedEngineCallPrefixes": ["particles.", "audio.synth"] + } +} diff --git a/wg1/gen-worker/briefs/simon.json b/wg1/gen-worker/briefs/simon.json new file mode 100644 index 00000000..7bff0e7c --- /dev/null +++ b/wg1/gen-worker/briefs/simon.json @@ -0,0 +1,18 @@ +{ + "title": "Simon 记忆", + "brief": "做一款经典 Simon(记忆复现)游戏。竖屏逻辑视口 390×844。\n- 屏幕中央 2×2 布局四个大彩色按钮:红、绿、蓝、黄(每个约 130×130 逻辑像素,留间隙)。\n- 游戏流程:每轮电脑播放一段【递增】的按钮序列——逐个点亮按钮(点亮=该按钮变亮/轻微放大,可用 getEngine().math.easing 缓动),每个点亮同时播放一个该颜色专属音高的音效 getEngine().audio.synth.synthSfx。\n- 播放完后轮到玩家:玩家依次点击按钮复现序列。点击时该按钮点亮+播放同样音效。\n- 复现正确一整轮:序列长度+1,进入下一轮(短暂停顿后电脑播放更长序列)。复现错误:播放失败音效+粒子,序列重置从头开始。\n- 用 ctx.random 生成每轮新追加的颜色;用 ctx.time 控制点亮节奏(如每个 500ms)。\n- 反馈:每次点亮/点击都有音效;答对一轮或答错都触发 getEngine().particles.spawnEmitter 粒子。\n- 画面:深色背景铺满 390×844;四个按钮暗态用较暗的本色、亮态用饱和本色。可在顶部单行文字显示当前轮数(非必须)。\n- 注意:开局电脑就要自动播放第一个按钮(含点亮+音效),不要停在等待态。", + "play_spec": { + "inputs": [ + { "t": "wait", "ms": 1300 }, + { "t": "tap", "x": 130, "y": 360 }, + { "t": "wait", "ms": 350 }, + { "t": "tap", "x": 260, "y": 360 }, + { "t": "wait", "ms": 350 }, + { "t": "tap", "x": 130, "y": 500 }, + { "t": "wait", "ms": 350 }, + { "t": "tap", "x": 260, "y": 500 }, + { "t": "wait", "ms": 350 } + ], + "expectedEngineCallPrefixes": ["audio.synth", "particles."] + } +} diff --git a/wg1/gen-worker/briefs/whack.json b/wg1/gen-worker/briefs/whack.json new file mode 100644 index 00000000..3b376946 --- /dev/null +++ b/wg1/gen-worker/briefs/whack.json @@ -0,0 +1,22 @@ +{ + "title": "打地鼠 Whack-a-Mole", + "brief": "做一款经典打地鼠游戏。竖屏逻辑视口 390×844。\n- 固定排布 3×3 共 9 个洞口(定点摆放,不是网格状态机):x 取约 80/195/310,y 取约 400/540/680,每个洞画成深色椭圆。\n- 地鼠机制:用 ctx.random 随机挑一个(或偶尔两个)当前为空的洞,让地鼠冒出(向上弹出动画,可用 getEngine().math.easing 或简单插值),停留约 700~1100ms 后若没被打则缩回。用 ctx.time 计时控制冒出节奏(约每 600~900ms 尝试冒一只)。\n- 地鼠冒出的瞬间播放一声音效 getEngine().audio.synth.synthSfx(保证每次出现都有引擎调用)。\n- 控制:玩家点击屏幕,若点中某个【正冒出的】地鼠所在洞(点到圆范围内)则打中:该地鼠缩回、分数+1、触发 getEngine().particles.spawnEmitter 命中粒子爆发 + 命中音效。点空不得分。\n- 画面:深色背景铺满 390×844;洞口深色椭圆;地鼠用棕色圆+两只眼睛+可选腮红;冒出时按弹出进度决定露出多少。顶部用单行文字显示分数。\n- 命中判定用『点到圆心距离 < 半径』自己算(不依赖网格、不依赖连续碰撞)。", + "play_spec": { + "inputs": [ + { "t": "wait", "ms": 700 }, + { "t": "tap", "x": 80, "y": 400 }, + { "t": "wait", "ms": 300 }, + { "t": "tap", "x": 195, "y": 540 }, + { "t": "wait", "ms": 300 }, + { "t": "tap", "x": 310, "y": 680 }, + { "t": "wait", "ms": 300 }, + { "t": "tap", "x": 195, "y": 400 }, + { "t": "wait", "ms": 300 }, + { "t": "tap", "x": 80, "y": 540 }, + { "t": "wait", "ms": 300 }, + { "t": "tap", "x": 310, "y": 400 }, + { "t": "wait", "ms": 300 } + ], + "expectedEngineCallPrefixes": ["particles.", "audio.synth"] + } +} diff --git a/wg1/gen-worker/calibration/labels.json b/wg1/gen-worker/calibration/labels.json new file mode 100644 index 00000000..c447aee1 --- /dev/null +++ b/wg1/gen-worker/calibration/labels.json @@ -0,0 +1,29 @@ +{ + "anchor_note": "权威锚=创始人亲玩(2026-06-14)。原话:A 物理最好;B 第二;C 碰撞有明显问题;D 滑块每次点击只走一格、不符合玩家习惯。fun/verdict 由我把定性排序转成数值(创始人可再覆盖)。**重大发现:创始人排序推翻了我的自动判定**——我曾把 B(v2)判 objective-hollow、C(pro)判 best,均与亲玩相反。", + "samples": [ + { + "game_id": "breakout-flash-v3", + "brief_ref": "breakout", + "class": "good", + "human": { "fun": 4, "verdict": "pass", "note": "创始人:物理最好(第1)。[原我标 basic=3,低估]", "anchor": "founder" } + }, + { + "game_id": "breakout-pro", + "brief_ref": "breakout", + "class": "good", + "human": { "fun": 2, "verdict": "fix", "note": "创始人:碰撞有明显问题。[原我+player 标 best=4,假阳性]", "anchor": "founder" } + }, + { + "game_id": "breakout-flash-v2", + "brief_ref": "breakout", + "class": "good", + "human": { "fun": 3, "verdict": "pass", "note": "创始人:第2、能玩。[原我标 objective-hollow=1,假阴性——盲打脚本没打到砖→误判空心]", "anchor": "founder" } + }, + { + "game_id": "breakout-m27", + "brief_ref": "breakout", + "class": "fix-control", + "human": { "fun": 2, "verdict": "fix", "note": "创始人:滑块每次点击只走一格、不跟手(控制 bug,不符玩家习惯)", "anchor": "founder" } + } + ] +} diff --git a/wg1/gen-worker/calibration/report.json b/wg1/gen-worker/calibration/report.json new file mode 100644 index 00000000..f435e0b0 --- /dev/null +++ b/wg1/gen-worker/calibration/report.json @@ -0,0 +1,163 @@ +{ + "stage": "stage1", + "n_samples": 4, + "anchor_note": "权威锚=创始人亲玩(2026-06-14)。原话:A 物理最好;B 第二;C 碰撞有明显问题;D 滑块每次点击只走一格、不符合玩家习惯。fun/verdict 由我把定性排序转成数值(创始人可再覆盖)。**重大发现:创始人排序推翻了我的自动判定**——我曾把 B(v2)判 objective-hollow、C(pro)判 best,均与亲玩相反。", + "rows": [ + { + "game_id": "breakout-flash-v3", + "class": "good", + "human": { + "fun": 4, + "verdict": "pass", + "note": "创始人:物理最好(第1)。[原我标 basic=3,低估]", + "anchor": "founder" + }, + "vision": { + "completeness": 4, + "fun": 4, + "problems": [ + "球起始位置在挡板正上方且初速向下时可能首帧直接掉出(边界条件虽通过测试,但首帧球贴在挡板附近略感不自然)", + "砖块击碎反馈在截图中无法直接看到粒子(静态截图局限),但 F_wiring 显示粒子与音效调用正常" + ], + "verdict": "pass", + "note": "经典打砖块实现到位:砖块网格、球反弹、挡板插值跟随、剩余砖数与分数实时变化(30→29、0→1),H_progress 门验证了核心机制真在跑,F_wiring 确认粒子+音效反馈真触发,E_live 15个不同状态说明动画与交互活跃——是款完整可玩、有反馈的休闲小品。" + }, + "text": { + "completeness": 5, + "fun": 4, + "problems": [], + "verdict": "pass", + "note": "经典打砖块,所有七门取证通过,核心循环完整且反馈到位,有实际进展和可玩性。" + } + }, + { + "game_id": "breakout-pro", + "class": "good", + "human": { + "fun": 2, + "verdict": "fix", + "note": "创始人:碰撞有明显问题。[原我+player 标 best=4,假阳性]", + "anchor": "founder" + }, + "vision": { + "completeness": 4, + "fun": 4, + "problems": [ + "球在 after-play 中已落至挡板下方区域,可能存在穿透或漏判失败态的风险(球y位置约1400-垫子y约1700之间仍有空间,但需确认未漏detect death)", + "部分橙色砖仍保留(剩余18)说明多次命中机制在工作,但after-play里球已经明显落在挡板下方飞,若该帧是终态前一刻则需验证 phase='gameover' 驻留契约", + "首帧砖块整齐6×7布局 vs 玩后砖块被削去一大块,进度真实(15分对应15块),核心循环成立", + "深色背景+亮色实心图形满足规格,无明显视觉缺陷" + ], + "verdict": "pass", + "note": "经典打砖块,核心循环、粒子+音效反馈、多次命中变色、挡板角度反弹都到位,真进展,手感扎实。" + }, + "text": { + "completeness": 5, + "fun": 4, + "problems": [], + "verdict": "pass", + "note": "经典打砖块实现完整,粒子与音效反馈到位,操作流畅,胜负态明确,符合终态契约。" + } + }, + { + "game_id": "breakout-flash-v2", + "class": "good", + "human": { + "fun": 3, + "verdict": "pass", + "note": "创始人:第2、能玩。[原我标 objective-hollow=1,假阴性——盲打脚本没打到砖→误判空心]", + "anchor": "founder" + }, + "vision": { + "completeness": 2, + "fun": 2, + "problems": [ + "H_progress 门未过:phase 始终为 booting,未按契约暴露 playing/gameover 状态", + "终态契约未实现:球掉底应驻留 gameover 并显示 GAME OVER + 重玩提示,实际没有", + "掉球后 phase 未切换,宿主轮询会漏判结束", + "可玩回合太短:一次入场只打到 +1 分球就掉,体验未闭环" + ], + "verdict": "fix", + "note": "砖块消除/粒子/音效/挡板移动都跑起来了,但终态契约完全没接——phase 锁在 booting,球掉底不切 gameover 不驻留,红线违规,必须修。" + }, + "text": { + "completeness": 1, + "fun": 1, + "problems": [ + "H_progress 未过,游戏未从 booting 切换到 playing 状态,核心循环未启动", + "无任何游戏进展证据(分数、砖块、球运动等均为零)", + "玩家无法操作或看到实质游戏内容,属于空心游戏" + ], + "verdict": "fix", + "note": "运行数据表明游戏卡在 booting 状态,未进入 playing 阶段,无法进行任何游玩,必须修复状态机转换及可观测状态导出。" + } + }, + { + "game_id": "breakout-m27", + "class": "fix-control", + "human": { + "fun": 2, + "verdict": "fix", + "note": "创始人:滑块每次点击只走一格、不跟手(控制 bug,不符玩家习惯)", + "anchor": "founder" + }, + "vision": { + "completeness": 3, + "fun": 2, + "problems": [ + "玩后截图 vs 首帧:Score 仍为 0、Bricks 仍为 24,球位置从右下移到左中但未撞击任何砖块/挡板/墙,无视觉反馈", + "玩后砖块多出一行绿色(首帧 4 行红+橙,玩后 5 行红+橙+绿),首尾帧之间砖块数量/布局不一致,疑似关卡布局不稳定或随机化错误", + "F_wiring 显示 487 次 synthSfx 调用,但 24 块砖一块没碎、0 分,音效调用与游戏事件严重脱钩(可能每帧 spam)", + "缺少明显粒子/数字跳动/消除反馈,无 GAME OVER/YOU WIN 终态截图证据", + "玩家全程只能看到一颗球在空荡中线附近漂,无爽点无反馈,体验空洞" + ], + "verdict": "fix", + "note": "砖块未消除、分数零变化、玩后布局突变,核心循环虽存在但玩家视角下无进展,判定空心游戏待修。" + }, + "text": { + "completeness": 4, + "fun": 4, + "problems": [ + "终态phase驻留未在数据中直接验证,但七门通过暗示实现;缺少多次击中砖块的颜色变化证据" + ], + "verdict": "pass", + "note": "游戏核心循环完整,有音效和粒子反馈,进度可感知,手感良好,基本符合Breakout玩法。" + } + } + ], + "metrics": { + "vision": { + "model": "MiniMax-M3", + "fun_mae": 0.75, + "verdict_match": "2/4", + "hollow_rejected": "0/0", + "hollow_false_green": "0/0", + "good_accepted": "2/3", + "gatekeeper_ok": false + }, + "text": { + "model": "deepseek-v4-flash", + "fun_mae": 1.5, + "verdict_match": "1/4", + "hollow_rejected": "0/0", + "hollow_false_green": "0/0", + "good_accepted": "2/3", + "gatekeeper_ok": false + } + }, + "cost": { + "by_model": { + "MiniMax-M3": { + "in": 18939, + "out": 1193, + "rmb": 0.10385 + }, + "deepseek-v4-flash": { + "in": 4810, + "out": 1882, + "rmb": 0.0071 + } + }, + "total_rmb": 0.11095 + } +} \ No newline at end of file diff --git a/wg1/gen-worker/requirements-l2.txt b/wg1/gen-worker/requirements-l2.txt new file mode 100644 index 00000000..6d32363a --- /dev/null +++ b/wg1/gen-worker/requirements-l2.txt @@ -0,0 +1,7 @@ +# W-G1 L2 agentic studio 依赖(在 L1 裸路之上叠加 AgentScope)。 +# L1 仍走裸路(--no-agentscope);L2 多角色 studio 用 AgentScope 进程内多 agent。 +# 锁 2.0.1:spike VERDICT 明示 2.0 是对 1.x 的破坏式重写,凭记忆/旧博客写必炸,须锁版本盯 changelog。 +# 进程内多 agent 只需 base(Agent/model/credential/message);[service,storage] 仅跨进程 RedisMessageBus 才需,本期不引。 +-r requirements.txt +agentscope==2.0.1 +pyyaml>=6.0 diff --git a/wg1/gen-worker/requirements.txt b/wg1/gen-worker/requirements.txt new file mode 100644 index 00000000..9101536f --- /dev/null +++ b/wg1/gen-worker/requirements.txt @@ -0,0 +1,3 @@ +# W-G1 L1 生成 worker 依赖(裸路:openai 客户端 + 脏 JSON 兜底;不引 AgentScope,L1 维持 §3 裸通路) +openai==2.41.1 +json-repair>=0.30 diff --git a/wg1/gen-worker/results/breakout-flash-v2.stage1.json b/wg1/gen-worker/results/breakout-flash-v2.stage1.json new file mode 100644 index 00000000..75acbe05 --- /dev/null +++ b/wg1/gen-worker/results/breakout-flash-v2.stage1.json @@ -0,0 +1,211 @@ +{ + "game_id": "breakout-flash-v2", + "stage": "stage1", + "pass": true, + "repairs": 1, + "player_rounds_used": 1, + "design_text": "## 设计稿:打砖块(Breakout)竖屏 390×844\n\n### 1. 核心机制 \n玩家拖动底部挡板接住球,球不断反弹撞击顶部砖块;每击中一块砖即消除、得分+1。部分砖需多次击中(颜色渐暗表示剩余次数)。球速恒定,方向由碰撞法线及击中挡板位置(水平偏移修正)决定。\n\n### 2. 胜负条件 \n- **胜利**:消除所有砖块 → 显示通关界面,可重新开始。 \n- **失败**:球落至挡板下方(底边 y>844)→ 立即停止所有运动,显示失败界面,可重新开始。\n\n### 3. 操作 \n触摸屏幕任意 x 位置 → 挡板中心每帧向触摸点 x 插值逼近,y 固定在底部 50px 处。无触摸时挡板静止。\n\n### 4. 关键数值 \n- 挡板:宽 80px,高 16px(≥14),圆角 4px。 \n- 球:半径 10px,合速度 350 px/s(范围 300~420)。 \n- 砖块网格:6 列 × 4 行,每块宽 55px,高 18px,间距 6px,起始 y=80。 \n- 多次击打砖:随机 30% 的块 2 次(第 1 次颜色变浅),5% 的块 3 次。 \n- 挡板移动平滑:插值因子 0.15/帧(60fps)。\n\n### 5. Juice 反馈 \n- **击碎砖块**:必触发 `getEngine().particles.spawnEmitter(x, y)` 粒子爆发 + `getEngine().audio.synth.synthSfx('pop')`。 \n- **撞墙/挡板**:轻音效 `synthSfx('click')`。 \n- 可选:砖块消失时微小缩放(0.1秒)。\n\n### 6. 画面要点 \n- 背景:纯色深灰 `#1a1a2e` 铺满。 \n- 挡板:亮蓝 `#00b4d8` 实心圆角矩形。 \n- 球:亮黄 `#ffcc00` 实心圆(无边框)。 \n- 砖块:未击/一次/两次分别用绿 `#2ecc71`、橙 `#e67e22`、红 `#e74c3c`。 \n- HUD:左上角白色文本 “分数: 0”,右上角 “剩余砖: 24”,字号 16,字体无衬线。", + "attempts": [ + { + "attempt": 0, + "role": "code", + "model": "deepseek-v4-flash", + "stage_fail": null, + "usage": { + "in": 3739, + "out": 10308 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 2, + "problems": [ + "球在30秒后未击碎任何砖块,分数仍为0,剩余砖数始终24,砖块颜色和分布与首帧完全不一致(说明砖块hp/颜色状态有变化但无消除),核心破坏循环未跑通", + "挡板在触屏后移动迟缓甚至消失(after-play中挡板跑到了画面下半部接近边缘,且球已悬空在中段),控制手感可疑", + "画面大段中下区域完全空旷,球与砖块/挡板的活动空间感差,节奏拖沓", + "砖块多色但无视觉说明(看不出几命),破坏反馈不明显", + "无失败态可见、无重开按钮被触发证据", + "粒子/音效有调用记录但屏幕上看不到粒子效果(bright 104429偏低,画面可能偏暗或粒子未渲染)" + ], + "verdict": "fix", + "note": "能渲染能接收输入,但球压根没打掉一块砖,30秒白玩,核心打砖循环没成立。" + }, + "text": { + "model": "deepseek-v4-flash", + "completeness": 4, + "fun": 3, + "problems": [], + "verdict": "pass", + "note": "核心循环完整,有粒子音效反馈,但手感与节奏需亲测" + } + } + }, + { + "attempt": 1, + "role": "fix", + "model": "deepseek-v4-flash", + "stage_fail": null, + "usage": { + "in": 3975, + "out": 13394 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "首帧显示分数:0 剩余:24,但 after-play 仍显示 分数:0 剩余:24,球位置在右上、挡板在底部偏左——说明测试期间实际未击中任何砖块,或得分/剩余计数未更新,核心击中反馈存疑", + "after-play 中砖块颜色从首帧的 多色(橙/红/绿)变成了几乎全绿+少量橙红,可能并非'击碎'而是颜色重置或渲染异常;既然剩余仍是 24 就不该有砖块状态变化", + "粒子效果在截图上不可见(两张图均未见爆发痕迹),且 wiring 证据只显示 callCount:1 且只采样到 audio.synth.synthSfx,未见 particles. 调用记录——题目要求的'击碎砖块触发粒子爆发'实际可能缺失", + "首帧中央大字号'点击屏幕开始'与挡板/球重叠在视觉上一锅烩,启动提示偏侵入", + "球初始位置贴在挡板正上方,未给一个明显的'发射'动作或预备状态,新手容易分不清球是否已出发" + ], + "verdict": "fix", + "note": "基础循环搭好了(砖块/挡板/球/计分UI都有),但 30 秒真玩证据表明核心击中链路未跑通:剩余砖数没变、分数没动、粒子也未触发——打砖块的灵魂就是这反馈,目前是哑火状态。" + }, + "text": { + "model": "deepseek-v4-flash", + "completeness": 4, + "fun": 3, + "problems": [], + "verdict": "pass", + "note": "七门全过,引擎能力调用到位,核心循环基本完整,但缺乏截图确认视觉与细节,手感中规中矩。" + } + } + } + ], + "seven_gate_verdict": { + "gameId": "breakout-flash-v2", + "url": "http://localhost:4320/games/_wg1-gen/breakout-flash-v2/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 47, + "f1": 77, + "delta": 30 + }, + "D_render": { + "pass": true, + "bright": 108157, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 13, + "samples": 15 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 1, + "sample": [ + "audio.synth.synthSfx" + ], + "expected": [ + "particles.", + "audio.synth" + ] + }, + "G_input": { + "pass": true, + "inputHash": "43973f46", + "controlHash": "793aa1f8", + "atFrame": 476, + "ctrlFrame": 477 + } + }, + "pass": true, + "notes": [] + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "首帧显示分数:0 剩余:24,但 after-play 仍显示 分数:0 剩余:24,球位置在右上、挡板在底部偏左——说明测试期间实际未击中任何砖块,或得分/剩余计数未更新,核心击中反馈存疑", + "after-play 中砖块颜色从首帧的 多色(橙/红/绿)变成了几乎全绿+少量橙红,可能并非'击碎'而是颜色重置或渲染异常;既然剩余仍是 24 就不该有砖块状态变化", + "粒子效果在截图上不可见(两张图均未见爆发痕迹),且 wiring 证据只显示 callCount:1 且只采样到 audio.synth.synthSfx,未见 particles. 调用记录——题目要求的'击碎砖块触发粒子爆发'实际可能缺失", + "首帧中央大字号'点击屏幕开始'与挡板/球重叠在视觉上一锅烩,启动提示偏侵入", + "球初始位置贴在挡板正上方,未给一个明显的'发射'动作或预备状态,新手容易分不清球是否已出发" + ], + "verdict": "fix", + "note": "基础循环搭好了(砖块/挡板/球/计分UI都有),但 30 秒真玩证据表明核心击中链路未跑通:剩余砖数没变、分数没动、粒子也未触发——打砖块的灵魂就是这反馈,目前是哑火状态。" + }, + "text": { + "model": "deepseek-v4-flash", + "completeness": 4, + "fun": 3, + "problems": [], + "verdict": "pass", + "note": "七门全过,引擎能力调用到位,核心循环基本完整,但缺乏截图确认视觉与细节,手感中规中矩。" + } + }, + "tokens": { + "prompt": 18631, + "completion": 26233 + }, + "tokens_by_model": { + "deepseek-v4-flash": [ + 9917, + 25668 + ], + "MiniMax-M3": [ + 8714, + 565 + ] + }, + "cost": { + "by_model": { + "deepseek-v4-flash": { + "in": 9917, + "out": 25668, + "rmb": 0.04804 + }, + "MiniMax-M3": { + "in": 8714, + "out": 565, + "rmb": 0.04807 + } + }, + "total_rmb": 0.09611, + "gate_rmb": 0.15 + }, + "wall_s": 357.1, + "models": { + "design": "deepseek-v4-flash", + "code": "deepseek-v4-flash", + "fix": "deepseek-v4-flash", + "player_vision": "MiniMax-M3", + "player_text": "deepseek-v4-flash" + } +} \ No newline at end of file diff --git a/wg1/gen-worker/results/breakout-flash-v3.json b/wg1/gen-worker/results/breakout-flash-v3.json new file mode 100644 index 00000000..e2bff243 --- /dev/null +++ b/wg1/gen-worker/results/breakout-flash-v3.json @@ -0,0 +1,159 @@ +{ + "game_id": "breakout-flash-v3", + "model": "deepseek-v4-flash", + "pass": true, + "retries": 1, + "attempts": [ + { + "attempt": 0, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 3486, + "completion_tokens": 11084, + "total_tokens": 14570, + "wall_s": 103.294, + "id": "f5e9c17c-23d9-4d34-bc05-baef62204345", + "finish_reason": "stop" + }, + "play_pass": false, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true, + "H_progress": false + } + }, + { + "attempt": 1, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 3613, + "completion_tokens": 9529, + "total_tokens": 13142, + "wall_s": 102.495, + "id": "381ce8a2-0231-4f19-bddc-d31e5e205a87", + "finish_reason": "stop" + }, + "play_pass": true, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true, + "H_progress": true + } + } + ], + "factory_path": "game-runtime/games/_wg1-gen/breakout-flash-v3/factory.js", + "bundle_path": "game-runtime/games/_wg1-gen/breakout-flash-v3/bundle.iife.js", + "verdict": { + "gameId": "breakout-flash-v3", + "url": "http://localhost:4323/games/_wg1-gen/breakout-flash-v3/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 47, + "f1": 77, + "delta": 30 + }, + "D_render": { + "pass": true, + "bright": 108938, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 15, + "samples": 15 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 536, + "sample": [ + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "audio.synth.synthSfx" + ], + "expected": [ + "particles.", + "audio.synth" + ] + }, + "G_input": { + "pass": true, + "inputHash": "1c4b1ec1", + "controlHash": "84e230d1", + "atFrame": 587, + "ctrlFrame": 592 + }, + "H_progress": { + "pass": true, + "checks": [ + { + "path": "remaining", + "op": "decreased", + "before": 30, + "after": 29, + "pass": true, + "why": "击碎砖块→剩余砖数下降(打砖块核心机制;空心游戏此值原地不动)" + }, + { + "path": "status", + "op": "in", + "before": "playing", + "after": "playing", + "value": [ + "playing", + "win", + "lose" + ], + "pass": true, + "why": "导出了真实状态机(非卡 booting)" + } + ], + "state0": { + "status": "playing", + "score": 0, + "remaining": 30, + "progress": 0 + }, + "state1": { + "status": "playing", + "score": 1, + "remaining": 29, + "progress": 0.033333333333333326 + } + } + }, + "pass": true, + "notes": [] + }, + "tokens": { + "prompt": 7099, + "completion": 20613 + }, + "request_ids": [ + "f5e9c17c-23d9-4d34-bc05-baef62204345", + "381ce8a2-0231-4f19-bddc-d31e5e205a87" + ] +} \ No newline at end of file diff --git a/wg1/gen-worker/results/breakout-flash-v4.json b/wg1/gen-worker/results/breakout-flash-v4.json new file mode 100644 index 00000000..dae0e405 --- /dev/null +++ b/wg1/gen-worker/results/breakout-flash-v4.json @@ -0,0 +1,195 @@ +{ + "game_id": "breakout-flash-v4", + "model": "deepseek-v4-flash", + "pass": false, + "retries": 3, + "attempts": [ + { + "attempt": 0, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 3796, + "completion_tokens": 5264, + "total_tokens": 9060, + "wall_s": 48.25, + "id": "13c8a2b6-0c33-4830-9e6a-17b564f4790c", + "finish_reason": "stop" + }, + "play_pass": false, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": false, + "H_progress": false + } + }, + { + "attempt": 1, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 3976, + "completion_tokens": 8113, + "total_tokens": 12089, + "wall_s": 260.009, + "id": "98c264da-c60a-47e3-8fd9-784aa9f80ae2", + "finish_reason": "stop" + }, + "play_pass": false, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true, + "H_progress": false + } + }, + { + "attempt": 2, + "stage": "validate", + "errors": [ + "违禁:禁 Math.random(用 ctx.random)" + ], + "usage": { + "prompt_tokens": 3925, + "completion_tokens": 9180, + "total_tokens": 13105, + "wall_s": 97.709, + "id": "4bf31736-d82c-4d2f-91ac-81c7ab96f79c", + "finish_reason": "stop" + } + }, + { + "attempt": 3, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 3840, + "completion_tokens": 4481, + "total_tokens": 8321, + "wall_s": 38.046, + "id": "1d669f45-ca8b-4917-8cc3-faf0e7d6703f", + "finish_reason": "stop" + }, + "play_pass": false, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": false, + "H_progress": false + } + } + ], + "factory_path": "game-runtime/games/_wg1-gen/breakout-flash-v4/generated-factory.js", + "bundle_path": "game-runtime/games/_wg1-gen/breakout-flash-v4/bundle.iife.js", + "verdict": { + "gameId": "breakout-flash-v4", + "url": "http://localhost:4325/games/_wg1-gen/breakout-flash-v4/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 46, + "f1": 77, + "delta": 31 + }, + "D_render": { + "pass": true, + "bright": 122999, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 8, + "samples": 17 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 6, + "sample": [ + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "particles.spawnEmitter" + ], + "expected": [ + "particles.", + "audio.synth" + ] + }, + "G_input": { + "pass": false, + "inputHash": "d328db80", + "controlHash": "d328db80", + "atFrame": 647, + "ctrlFrame": 648 + }, + "H_progress": { + "pass": false, + "checks": [ + { + "path": "remaining", + "op": "decreased", + "before": 35, + "after": 35, + "pass": false, + "why": "击碎砖块→剩余砖数下降(打砖块核心机制;空心游戏此值原地不动)" + } + ], + "latch": { + "pass": true, + "dwelledMs": 600, + "after": "gameover", + "reason": "" + }, + "state0": { + "phase": "playing", + "score": 0, + "remaining": 35, + "progress": 0, + "gameoverReason": "" + }, + "state1": { + "phase": "gameover", + "score": 0, + "remaining": 35, + "progress": 0, + "gameoverReason": "ball_lost" + } + } + }, + "pass": false, + "notes": [] + }, + "tokens": { + "prompt": 15537, + "completion": 27038 + }, + "request_ids": [ + "13c8a2b6-0c33-4830-9e6a-17b564f4790c", + "98c264da-c60a-47e3-8fd9-784aa9f80ae2", + "4bf31736-d82c-4d2f-91ac-81c7ab96f79c", + "1d669f45-ca8b-4917-8cc3-faf0e7d6703f" + ] +} \ No newline at end of file diff --git a/wg1/gen-worker/results/breakout-flash-v5.json b/wg1/gen-worker/results/breakout-flash-v5.json new file mode 100644 index 00000000..7dca45d2 --- /dev/null +++ b/wg1/gen-worker/results/breakout-flash-v5.json @@ -0,0 +1,253 @@ +{ + "game_id": "breakout-flash-v5", + "model": "deepseek-v4-flash", + "pass": false, + "retries": 3, + "attempts": [ + { + "attempt": 0, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 4017, + "completion_tokens": 12376, + "total_tokens": 16393, + "wall_s": 134.487, + "id": "a5e9a083-492d-4160-b9b0-5b71eced7260", + "finish_reason": "stop" + }, + "play_pass": false, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "I_control": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true, + "H_progress": false + } + }, + { + "attempt": 1, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 4149, + "completion_tokens": 6604, + "total_tokens": 10753, + "wall_s": 65.824, + "id": "868072d4-cd1e-43bb-a2ef-30ca4bb97caa", + "finish_reason": "stop" + }, + "play_pass": false, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "I_control": false, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true, + "H_progress": false + } + }, + { + "attempt": 2, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 4245, + "completion_tokens": 7460, + "total_tokens": 11705, + "wall_s": 69.351, + "id": "e21364b2-d252-4faf-b13c-ef2c0a4ebb7e", + "finish_reason": "stop" + }, + "play_pass": false, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "I_control": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true, + "H_progress": false + } + }, + { + "attempt": 3, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 4150, + "completion_tokens": 7543, + "total_tokens": 11693, + "wall_s": 78.659, + "id": "ed11ed20-dfbf-43c7-bf62-6683ab7b1b17", + "finish_reason": "stop" + }, + "play_pass": false, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "I_control": false, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true, + "H_progress": false + } + } + ], + "factory_path": "game-runtime/games/_wg1-gen/breakout-flash-v5/generated-factory.js", + "bundle_path": "game-runtime/games/_wg1-gen/breakout-flash-v5/bundle.iife.js", + "verdict": { + "gameId": "breakout-flash-v5", + "url": "http://localhost:4327/games/_wg1-gen/breakout-flash-v5/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 51, + "f1": 82, + "delta": 31 + }, + "I_control": { + "pass": false, + "paddlePath": "paddle.x", + "results": [ + { + "tapX": 50, + "before": 155, + "after": 16.12409472465515, + "moved": -138.87590527534485, + "distToTarget": 33.87590527534485, + "pass": true + }, + { + "tapX": 340, + "before": 16.12409472465515, + "after": 249.47618775739102, + "moved": 233.35209303273587, + "distToTarget": 90.52381224260898, + "pass": false + } + ] + }, + "D_render": { + "pass": true, + "bright": 160281, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 11, + "samples": 11 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 495, + "sample": [ + "particles.spawnEmitter", + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "audio.synth.synthSfx" + ], + "expected": [ + "particles.", + "audio.synth" + ] + }, + "G_input": { + "pass": true, + "inputHash": "19eb47b9", + "controlHash": "f0e8788b", + "atFrame": 530, + "ctrlFrame": 531 + }, + "H_progress": { + "pass": false, + "checks": [ + { + "path": "remaining", + "op": "decreased", + "before": 30, + "after": 30, + "pass": false, + "why": "适配性真玩(挡板自动接球)下击碎砖块→剩余下降;接不住/碰撞失效则不降" + } + ], + "latch": { + "pass": true, + "dwelledMs": 600, + "after": "gameover", + "reason": "" + }, + "state0": { + "phase": "playing", + "score": 0, + "remaining": 30, + "progress": 0, + "gameoverReason": "", + "ball": { + "x": 111.00585468634965, + "y": 515.7535326413795, + "vx": -98.81664154547158, + "vy": -346.1723145395567 + }, + "paddle": { + "x": 155, + "y": 820, + "w": 80 + } + }, + "state1": { + "phase": "gameover", + "score": 0, + "remaining": 30, + "progress": 0, + "gameoverReason": "ball_lost", + "ball": { + "x": 21.229435960708493, + "y": 836.175170770526, + "vx": -206.15460802245252, + "vy": 295.1275615578947 + }, + "paddle": { + "x": 251.78406952933614, + "y": 820, + "w": 80 + } + } + } + }, + "pass": false, + "notes": [] + }, + "tokens": { + "prompt": 16561, + "completion": 33983 + }, + "request_ids": [ + "a5e9a083-492d-4160-b9b0-5b71eced7260", + "868072d4-cd1e-43bb-a2ef-30ca4bb97caa", + "e21364b2-d252-4faf-b13c-ef2c0a4ebb7e", + "ed11ed20-dfbf-43c7-bf62-6683ab7b1b17" + ] +} \ No newline at end of file diff --git a/wg1/gen-worker/results/breakout-flash.stage1.json b/wg1/gen-worker/results/breakout-flash.stage1.json new file mode 100644 index 00000000..c05faa1d --- /dev/null +++ b/wg1/gen-worker/results/breakout-flash.stage1.json @@ -0,0 +1,351 @@ +{ + "game_id": "breakout-flash", + "stage": "stage1", + "pass": true, + "repairs": 5, + "player_rounds_used": 3, + "design_text": "核心机制:玩家控制底部挡板左右移动,反弹球击碎顶部砖块,清空所有砖块通关。球斜向匀速运动,碰墙反弹,碰挡板按击中位置微调水平速度(越靠边越斜)。\n\n胜负条件:球掉到底边以下 → 失败,本局结束(停止+可重开);清光所有砖 → 胜利。\n\n操作:触摸屏幕,挡板向触摸点x坐标每帧插值逼近(平滑跟随)。\n\n关键数值:球合速度300~420 px/s;挡板厚度≥14,宽度60~80;砖块网格6列×4~5行,每块32×14,间距4;部分砖需击中2次(颜色变化:红→橙→黄)。\n\njuice反馈:击碎砖块→粒子爆发(getEngine().particles.spawnEmitter) + 音效(getEngine().audio.synth.synthSfx);撞墙/挡板可加轻音效。\n\n画面要点:深色背景铺满390×844;挡板/砖块亮色实心矩形(白/红/橙/黄),球亮色实心圆(白);顶部HUD:分数+剩余砖数(白色文字)。", + "attempts": [ + { + "attempt": 0, + "role": "code", + "model": "deepseek-v4-flash", + "stage_fail": "seven_gate", + "usage": { + "in": 3163, + "out": 8930 + }, + "seven_gate_pass": false, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": false + } + }, + { + "attempt": 1, + "role": "fix", + "model": "deepseek-v4-flash", + "stage_fail": null, + "usage": { + "in": 3245, + "out": 9299 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "首帧球初始位置在挡板左下方很远(约 x≈50, y≈680),开局视觉上球已经处于'即将掉落'的危险区,玩家没有反应时间,体验突兀", + "砖块布局只占屏幕顶部约15%区域,纵向浪费严重,6列×4行=24格但UI显示38块,说明每块多命但差距小、颜色变化不明显,缺乏视觉层次", + "30秒内仅得分1(破1块),节奏过慢,球速虽在范围内但击砖反馈稀疏,爽快感不足", + "顶栏多了一行调试文字 'engine RAF running · seed=305441741 engine=real',生产环境应移除", + "失败态/重开流程在30秒内未触发,无法验证失败体验", + "挡板始终居中(截图1、2位置几乎一致),输入控制是否真生效存疑——可能是球主动飞向挡板而非玩家主动追球" + ], + "verdict": "fix", + "note": "基本能玩且反馈链路通了,但开局球位置不利、纵向空间浪费、调试信息残留、挡板交互可疑,30秒只破1块爽感不足,需打磨。" + }, + "text": { + "model": "deepseek-v4-flash", + "completeness": 5, + "fun": 4, + "problems": [], + "verdict": "pass", + "note": "核心循环完整,音效/粒子反馈到位,输入响应正常,经典打砖块体验良好。" + } + } + }, + { + "attempt": 2, + "role": "fix", + "model": "deepseek-v4-flash", + "stage_fail": "seven_gate", + "usage": { + "in": 3423, + "out": 12147 + }, + "seven_gate_pass": false, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": false + } + }, + { + "attempt": 3, + "role": "fix", + "model": "deepseek-v4-flash", + "stage_fail": null, + "usage": { + "in": 3247, + "out": 3557 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "first-paint 截图里球初始位置偏低(右下角 ~y=680),距挡板太近,开局手感有点慌", + "球极小(直径目测 6-8px),在 390 宽画布上不太好跟眼,挡板也偏窄", + "after-play 里球从挡板反弹后路径看着像向斜下走,但右上砖区已被清了一格,需要确认斜向反弹角度调整是否真的按击中位置生效(截图证据不足)", + "顶部 HUD 文字 'engine RAF running · seed=305441741 engine=real' 是调试水印,正式玩会出戏,该去掉", + "深色背景+纯亮色填充视觉 OK,但 30 块砖一上来就齐刷刷,缺少分层(题面要求部分砖需多次击中变色的层次感没体现)" + ], + "verdict": "fix", + "note": "核心循环能跑、能反弹、能消砖、分数砖数计数正确,粒子和音效 wiring 也调用了,但视觉偏素、调试水印没去、砖块分层没做、球和挡板都偏小,30 秒内能玩但不算上头。" + }, + "text": { + "model": "deepseek-v4-flash", + "completeness": 4, + "fun": 4, + "problems": [], + "verdict": "pass", + "note": "核心玩法完整,粒子与音效反馈丰富,操作流畅,体验良好。" + } + } + }, + { + "attempt": 4, + "role": "fix", + "model": "deepseek-v4-flash", + "stage_fail": null, + "usage": { + "in": 3400, + "out": 6882 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "顶部多了一行调试文字 'engine RAF running · seed=305441741 engine=real',非常出戏,正式版必须去掉", + "30秒只得了2分、消除2块砖,节奏偏慢/球速偏慢,反馈不够刺激", + "没有失败态/通关态的可见触发证据(screenshots 只看到首尾帧,30秒内未见生命系统或失败画面)", + "砖块层次(颜色随命数变化)在截图中看起来是二态(红/绿),但变化不明显,玩家难以判断还需打几下", + "挡板偏窄、球偏小,整体视觉重量轻,30秒里球主要在挡板附近徘徊,没看出明显的'打砖快感'", + "粒子和音效调用只有9次,juice 偏稀,击碎反馈不够爽", + "关卡只有固定一版30块砖,没有变化/升级,玩家很快会无聊" + ], + "verdict": "fix", + "note": "能玩、循环基本完整,但调试水印必须去掉,球速/手感偏弱、关卡单一,30秒内很难让人想再来一局。" + }, + "text": { + "model": "deepseek-v4-flash", + "completeness": 4, + "fun": 3, + "problems": [ + "游戏运行帧数有限(78帧),无法确认完整胜负循环(失败态/胜利态)是否已触发" + ], + "verdict": "pass", + "note": "核心打砖块机制可见,有音效与粒子反馈,但样本时长较短,完整度有待更长时间验证。" + } + } + }, + { + "attempt": 5, + "role": "fix", + "model": "deepseek-v4-flash", + "stage_fail": null, + "usage": { + "in": 3417, + "out": 6154 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "顶部多余显示 engine RAF running · seed=305441741 engine=real 调试/水印文字,玩家视角很出戏,应隐藏", + "首帧所有砖块全为同一红色,看不出'需击中多次'的层次(题面要求颜色随剩余命数变化),需多命砖块的视觉差异几乎不可见", + "生命用爱心图标显示且数量随掉球递减(3→1)正常,但 Lives 与 Score 共用一行且无'剩余砖数'显示,与题面'显示分数与剩余砖数'不符", + "挡板在竖屏中位置偏下且与底边距离较大,球一旦从砖块阵下方空隙掉落,中间大段空白显得空旷", + "粒子与音效调用频繁(971次 callCount)但首帧截图看不到任何粒子残留,粒子生命周期或可见性可能太弱" + ], + "verdict": "fix", + "note": "打砖块核心循环基本跑通,挡板/球/砖块/计分/掉球扣命都生效,但调试水印外露、多命砖色彩层次缺失、缺少剩余砖数显示,且粒子效果在截图中几乎不可见,需要修。" + }, + "text": { + "model": "deepseek-v4-flash", + "completeness": 4, + "fun": 3, + "problems": [], + "verdict": "pass", + "note": "核心循环完整,有反馈与胜负,但缺少多次击中砖块等层次细节的明确证据。" + } + } + } + ], + "seven_gate_verdict": { + "gameId": "breakout-flash", + "url": "http://localhost:4320/games/_wg1-gen/breakout-flash/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 48, + "f1": 79, + "delta": 31 + }, + "D_render": { + "pass": true, + "bright": 131465, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 15, + "samples": 15 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 971, + "sample": [ + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx" + ], + "expected": [ + "particles.", + "audio.synth" + ] + }, + "G_input": { + "pass": true, + "inputHash": "2b99356a", + "controlHash": "af116a4d", + "atFrame": 484, + "ctrlFrame": 484 + } + }, + "pass": true, + "notes": [] + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "顶部多余显示 engine RAF running · seed=305441741 engine=real 调试/水印文字,玩家视角很出戏,应隐藏", + "首帧所有砖块全为同一红色,看不出'需击中多次'的层次(题面要求颜色随剩余命数变化),需多命砖块的视觉差异几乎不可见", + "生命用爱心图标显示且数量随掉球递减(3→1)正常,但 Lives 与 Score 共用一行且无'剩余砖数'显示,与题面'显示分数与剩余砖数'不符", + "挡板在竖屏中位置偏下且与底边距离较大,球一旦从砖块阵下方空隙掉落,中间大段空白显得空旷", + "粒子与音效调用频繁(971次 callCount)但首帧截图看不到任何粒子残留,粒子生命周期或可见性可能太弱" + ], + "verdict": "fix", + "note": "打砖块核心循环基本跑通,挡板/球/砖块/计分/掉球扣命都生效,但调试水印外露、多命砖色彩层次缺失、缺少剩余砖数显示,且粒子效果在截图中几乎不可见,需要修。" + }, + "text": { + "model": "deepseek-v4-flash", + "completeness": 4, + "fun": 3, + "problems": [], + "verdict": "pass", + "note": "核心循环完整,有反馈与胜负,但缺少多次击中砖块等层次细节的明确证据。" + } + }, + "tokens": { + "prompt": 41226, + "completion": 51674 + }, + "tokens_by_model": { + "deepseek-v4-flash": [ + 23766, + 50566 + ], + "MiniMax-M3": [ + 17460, + 1108 + ] + }, + "cost": { + "by_model": { + "deepseek-v4-flash": { + "in": 23766, + "out": 50566, + "rmb": 0.09834 + }, + "MiniMax-M3": { + "in": 17460, + "out": 1108, + "rmb": 0.09589 + } + }, + "total_rmb": 0.19423, + "gate_rmb": 0.15 + }, + "wall_s": 616.5, + "models": { + "design": "deepseek-v4-flash", + "code": "deepseek-v4-flash", + "fix": "deepseek-v4-flash", + "player_vision": "MiniMax-M3", + "player_text": "deepseek-v4-flash" + } +} \ No newline at end of file diff --git a/wg1/gen-worker/results/breakout-m27.stage1_mmx.json b/wg1/gen-worker/results/breakout-m27.stage1_mmx.json new file mode 100644 index 00000000..85f0fa35 --- /dev/null +++ b/wg1/gen-worker/results/breakout-m27.stage1_mmx.json @@ -0,0 +1,319 @@ +{ + "game_id": "breakout-m27", + "stage": "stage1_mmx", + "pass": true, + "repairs": 6, + "player_rounds_used": 3, + "design_text": "**核心机制** \n玩家在底部用挡板拦截斜向弹射的球,球击中顶部砖块网格得分并消除砖块。球碰左/右/顶墙或挡板时反弹,挡板碰撞位置影响球水平速度分量(靠边更斜、靠中更直)。触摸屏幕时挡板平滑朝触摸点 x 逼近。\n\n**胜负条件** \n- 通关:所有砖块被消除。 \n- 失败:球越过挡板落入底部(失去本局),游戏进入结束态,可重新开始。\n\n**操作** \n触摸屏幕任意位置,挡板 x 每帧向触摸 x 线性插值(插值系数约 0.15~0.25),保证不穿透。\n\n**关键数值** \n- 视口:390×844(逻辑像素),竖屏。 \n- 挡板:宽 90~110,高 14,圆角 4,亮橙/白。 \n- 球:半径 9,亮青/白,合速度 300~420 px/s,匀速。 \n- 砖块:6 列 × 4~5 行,单砖 60×24,间距 2,亮色实心;多层砖需 2~3 次击打,颜色随剩余命数变化。 \n- 球反弹规则:撞挡板时水平速度 = 初始水平速度 + (击中x - 挡板中心x) * 比例系数(约 0.08~0.12)。 \n- 速度梯度:每清除 10 块砖可提升球速 10%。\n\n**Juice 反馈** \n- 击碎砖块:粒子爆发(颜色随砖色)+ synthSfx 高频短促音。 \n- 撞墙/挡板:轻音效 synthSfx 低频短促音。 \n- 消除多层砖时额外屏震(0.5 帧,幅度 3px)。\n\n**画面要点** \n- 背景:深色(#0a0a0f)铺满 390×844。 \n- 挡板:亮色实心矩形,底部 20px 处。 \n- 球:亮色实心圆,跟踪运动。 \n- 砖块:顶部对齐,行间间距均匀,颜色按层区分。 \n- HUD:顶部单行文字,左显示分数,右显示剩余砖数,字体亮色。", + "attempts": [ + { + "attempt": 0, + "role": "code", + "model": "MiniMax-M2.7", + "stage_fail": null, + "usage": { + "in": 3292, + "out": 6327 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "砖块没有显示多命/颜色随命数变化的视觉层次,题面要求部分砖需击中多次且颜色随剩余命数变化,但截图里红/绿/蓝三色砖看起来都是一击即碎", + "挡板位置在屏幕最底部(约y=1180),离底边过近,球反弹后下落距离长,玩家反应窗口小", + "顶部HUD'engine RAF running·seed=…engine=real'调试信息直接渲染在画面上,破坏沉浸感", + "玩后截图中挡板和球距离拉得很大(挡板在y≈1180,球在y≈500),感觉挡板太靠下或球速感偏慢", + "玩后截图只显示SCORE:2 BRICKS:28,少了2块但玩家不知道少了哪几块——其实这是OK的,但'失败态/可重新开始'流程未在截图体现,需确认", + "砖块只有6列×5行=30块,单局内容偏短,耐玩度有限" + ], + "verdict": "fix", + "note": "基础打砖块循环跑通了,粒子+音效接线也正常,但砖块多命变色的题面要求没体现,HUD调试信息泄露,整体30秒只能玩出2分的浅尝辄止感。" + }, + "text": { + "model": "MiniMax-M2.7", + "completeness": 5, + "fun": 4, + "problems": [], + "verdict": "pass", + "note": "一款完整可玩、打感扎实、打砖块核心循环无短板的 Breakout,所有引擎能力均已正确接入。" + } + } + }, + { + "attempt": 1, + "role": "fix", + "model": "MiniMax-M2.7", + "stage_fail": "validate", + "usage": { + "in": 3558, + "out": 8192 + }, + "errors": [ + "缺少 destroy 方法" + ] + }, + { + "attempt": 2, + "role": "fix", + "model": "MiniMax-M2.7", + "stage_fail": null, + "usage": { + "in": 3327, + "out": 5697 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "玩到 GAME OVER 时 SCORE 仍为 0、BRICKS 仍为 24,计分/消砖逻辑似乎未在 30 秒内触发或计数未刷新", + "G 门 input/control hash 帧差 1,控制响应可能偏慢导致玩家来不及救球", + "顶部红砖与黄砖疑为多命砖(颜色随命数变暗),但缺少视觉提示,玩家不知需多次击打", + "首帧球位于画面中部偏高,初速方向若向下偏右,玩家在挡板插值追球时极易漏球", + "底部中间大段空白无视觉引导,挡板可移动范围/边界提示缺失", + "失败后 'Tap to restart' 字体偏小且无高亮,按钮可点击性弱", + "粒子/音效触发是有的(F 门 9 次调用),但截图未捕捉到粒子残留,视觉冲击感存疑" + ], + "verdict": "fix", + "note": "框架完整可玩可重启,但 30 秒内 0 分即 GAME OVER,体验偏挫败;需调慢球速/优化挡板跟随并强化消砖反馈。" + }, + "text": { + "model": "MiniMax-M2.7", + "completeness": 5, + "fun": 4, + "problems": [], + "verdict": "pass", + "note": "核心循环完整:挡板/球/砖块/得分系统全部运转,粒子与音效反馈正常,无异常未捕获,运行稳定流畅。" + } + } + }, + { + "attempt": 3, + "role": "fix", + "model": "MiniMax-M2.7", + "stage_fail": "validate", + "usage": { + "in": 3539, + "out": 4613 + }, + "errors": [ + "违禁:禁 Math.random(用 ctx.random)" + ] + }, + { + "attempt": 4, + "role": "fix", + "model": "MiniMax-M2.7", + "stage_fail": null, + "usage": { + "in": 3335, + "out": 6502 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 2, + "problems": [ + "Score: 0 Bricks: 24 两张截图完全一致,没有砖块被消除,得分始终为0", + "play后截图与首帧几乎无差异,球位置几乎没变(Paddle位置也几乎一致),30秒内几乎没有可见的游戏进展", + "砖块布局偏离顶部,下半屏幕留出大块空旷区域,使整个游戏区域视觉上稀疏", + "行数仅2行(红+橙),按题面应4~5行;多命砖/颜色变化的层次感缺失(仅看到 after 截图最下方一行两端有绿色)", + "挡板偏小(看起来 ~60px 宽/390 视口),命中率低,容错差", + "play后截图看不到任何粒子或得分变化,juice 反馈几乎感知不到", + "f0=48, f1=79, delta=31,帧率偏低(约30fps),影响手感" + ], + "verdict": "fix", + "note": "能跑能渲染,但30秒内0进展0得分,画面留白大、砖块层数少、挡板小,球速/碰撞体感可疑,整体玩法循环没真正跑起来。" + }, + "text": { + "model": "MiniMax-M2.7", + "completeness": 4, + "fun": 4, + "problems": [], + "verdict": "pass", + "note": "所有核心机制正常工作:挡板平滑跟随、球反弹物理、带位置偏转的挡板碰撞、砖块消除+得分、音效粒子反馈完整,487次音频调用证明反馈充分,15个状态变化证明游戏逻辑有足够的变化性。帧率稳定(~60fps),无异常。无截图但运行数据充分证明游戏可玩且完整。" + } + } + }, + { + "attempt": 5, + "role": "fix", + "model": "MiniMax-M2.7", + "stage_fail": "validate", + "usage": { + "in": 3530, + "out": 4683 + }, + "errors": [ + "违禁:禁 Math.random(用 ctx.random)" + ] + }, + { + "attempt": 6, + "role": "fix", + "model": "MiniMax-M2.7", + "stage_fail": "validate", + "usage": { + "in": 3335, + "out": 5050 + }, + "errors": [ + "违禁:禁 Math.random(用 ctx.random)" + ] + } + ], + "seven_gate_verdict": { + "gameId": "breakout-m27", + "url": "http://localhost:4321/games/_wg1-gen/breakout-m27/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 48, + "f1": 79, + "delta": 31 + }, + "D_render": { + "pass": true, + "bright": 147563, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 15, + "samples": 15 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 487, + "sample": [ + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "audio.synth.synthSfx" + ], + "expected": [ + "particles.", + "audio.synth" + ] + }, + "G_input": { + "pass": true, + "inputHash": "318b9a88", + "controlHash": "a347d258", + "atFrame": 482, + "ctrlFrame": 482 + } + }, + "pass": true, + "notes": [] + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 2, + "problems": [ + "Score: 0 Bricks: 24 两张截图完全一致,没有砖块被消除,得分始终为0", + "play后截图与首帧几乎无差异,球位置几乎没变(Paddle位置也几乎一致),30秒内几乎没有可见的游戏进展", + "砖块布局偏离顶部,下半屏幕留出大块空旷区域,使整个游戏区域视觉上稀疏", + "行数仅2行(红+橙),按题面应4~5行;多命砖/颜色变化的层次感缺失(仅看到 after 截图最下方一行两端有绿色)", + "挡板偏小(看起来 ~60px 宽/390 视口),命中率低,容错差", + "play后截图看不到任何粒子或得分变化,juice 反馈几乎感知不到", + "f0=48, f1=79, delta=31,帧率偏低(约30fps),影响手感" + ], + "verdict": "fix", + "note": "能跑能渲染,但30秒内0进展0得分,画面留白大、砖块层数少、挡板小,球速/碰撞体感可疑,整体玩法循环没真正跑起来。" + }, + "text": { + "model": "MiniMax-M2.7", + "completeness": 4, + "fun": 4, + "problems": [], + "verdict": "pass", + "note": "所有核心机制正常工作:挡板平滑跟随、球反弹物理、带位置偏转的挡板碰撞、砖块消除+得分、音效粒子反馈完整,487次音频调用证明反馈充分,15个状态变化证明游戏逻辑有足够的变化性。帧率稳定(~60fps),无异常。无截图但运行数据充分证明游戏可玩且完整。" + } + }, + "tokens": { + "prompt": 39975, + "completion": 44524 + }, + "tokens_by_model": { + "MiniMax-M2.7": [ + 26870, + 43699 + ], + "MiniMax-M3": [ + 13105, + 825 + ] + }, + "cost": { + "by_model": { + "MiniMax-M2.7": { + "in": 26870, + "out": 43699, + "rmb": 0.44165 + }, + "MiniMax-M3": { + "in": 13105, + "out": 825, + "rmb": 0.07185 + } + }, + "total_rmb": 0.5135, + "gate_rmb": 0.15 + }, + "wall_s": 295.9, + "models": { + "design": "MiniMax-M2.7", + "code": "MiniMax-M2.7", + "fix": "MiniMax-M2.7", + "player_vision": "MiniMax-M3", + "player_text": "MiniMax-M2.7" + } +} \ No newline at end of file diff --git a/wg1/gen-worker/results/breakout-pro.stage2.json b/wg1/gen-worker/results/breakout-pro.stage2.json new file mode 100644 index 00000000..534ef311 --- /dev/null +++ b/wg1/gen-worker/results/breakout-pro.stage2.json @@ -0,0 +1,317 @@ +{ + "game_id": "breakout-pro", + "stage": "stage2", + "pass": true, + "repairs": 3, + "player_rounds_used": 3, + "design_text": "1. 核心机制:玩家滑动底部挡板反弹球体,撞击并消除顶部砖块,球落底即失败。目标是清空所有砖块。\n2. 胜负条件:\n - 输:球越过挡板底部边界→本局结束,显示失败界面,可点击重新开始。\n - 赢:砖块数量归零→通关,可进入下一关或庆祝界面。\n3. 操作:单指触摸屏幕任意位置,挡板每帧以20像素速度平滑逼近触摸点x坐标(钳制在挡板半宽~390-半宽)。\n4. 关键数值:\n - 挡板:宽80,高14,底部y=800。\n - 球:半径8,初始合速度300~350px/s,角度随机向上(偏垂直±20°)。\n - 砖块网格:6列×5行,单块宽55高20,间距4,起始y=80。前两行需击中2次(颜色渐亮),其余1次。\n - 反弹微调:击中挡板时,根据击点距挡板中心偏移量调整水平速度因子(中心0.2偏移量,边缘±0.8),保持合速度不变。\n5. juice反馈:\n - 击中砖块:调用引擎粒子系统在砖块位置爆发同色粒子(15~25个,寿命0.3秒),同时播放清脆短促音效(频率600~900Hz,持续0.05秒)。\n - 撞墙/撞挡板:播放轻柔“啵”音效(频率300Hz,持续0.03秒)。\n6. 画面要点:深蓝渐变背景铺满390×844。挡板与砖块使用高饱和色(青、品红、黄绿),球用白色实心圆。顶部HUD栏显示“分数:0”和“剩余砖数:30”(初始),黑色半透明底。输赢时中央显示半透明遮罩与提示文字。", + "attempts": [ + { + "attempt": 0, + "role": "code", + "model": "deepseek-v4-pro", + "stage_fail": null, + "usage": { + "in": 3328, + "out": 7278 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "首帧截图显示球在挡板正上方未运动,初始画面静止感强,等约30秒才看出挡板响应输入(球已下行并碎一块砖),节奏偏慢", + "顶部HUD压住了分数/砖块文字显示区域,'分数:0 砖块:30'被一行小字 engine RAF running 挤到顶部,且与大字部分重叠,读起来较乱", + "砖块颜色按行区分(红橙黄绿蓝)但未体现'按剩余命数变色'的多命机制,从两张截图看每行只一击就消除,与题面'部分砖需多次击中'不符", + "挡板宽度偏窄且只占底部一小段(目测仅屏幕宽度的~28%),在390宽屏下操控容错较低", + "首帧与玩后帧差距很小(只碎1块、分数1),30秒取证期内游戏推进感不足,可能球速偏低端(~300px/s)或挡板响应延迟", + "play后截图看不到任何粒子残留或动画痕迹,粒子爆发持续可能太短,视觉juice感不强" + ], + "verdict": "fix", + "note": "核心循环完整可玩,反馈管线(particles/audio/wiring)真实调用,但初始节奏慢、挡板偏窄、多命砖机制未体现、HUD排版拥挤,需要打磨节奏与表现层。" + }, + "text": { + "model": "deepseek-v4-pro", + "completeness": 4, + "fun": 3, + "problems": [], + "verdict": "pass", + "note": "基于证据,核心循环完整,有粒子音效反馈,控制生效,但未验证文字显示与重新开始机制,整体可玩但缺乏深度。" + } + } + }, + { + "attempt": 1, + "role": "fix", + "model": "deepseek-v4-pro", + "stage_fail": null, + "usage": { + "in": 3624, + "out": 7990 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 5, + "fun": 3, + "problems": [ + "砖块全程是实心单色,没看到题目要求的'颜色随剩余命数变化'的多命砖视觉反馈,全是一碰就碎", + "玩后截图里砖块间距错位:第5行只剩零散几块且出现异常空档,撞击后砖块消除和物理反弹的视觉因果不够清晰", + "画面下半部分(挡板与球之间)留白极大,844高视口里砖块只占顶部一小条,玩法区域比例头重脚轻", + "球速看起来偏慢(测试期间仅消2块),30秒内反馈稀疏,节奏感弱", + "球、挡板、砖块都是纯色实心无任何描边/光感/运动残影,juice感全靠音频和粒子撑着,画面本身挺素", + "标题栏一直挂着'engine RAF running · seed=... engine=real'调试水印没抹掉,很出戏" + ], + "verdict": "fix", + "note": "核心循环跑通能玩,但砖块没做多命颜色变化、留白过大、视觉反馈单薄,30秒内很难让人想继续点。" + }, + "text": { + "model": "deepseek-v4-pro", + "completeness": 4, + "fun": 3, + "problems": [], + "verdict": "pass", + "note": "经典打砖块实现了核心循环,碰撞反馈及时,但整体体验较常规,缺乏进一步变化。" + } + } + }, + { + "attempt": 2, + "role": "fix", + "model": "deepseek-v4-pro", + "stage_fail": null, + "usage": { + "in": 3583, + "out": 18270 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "球初始位置太低(紧贴挡板)且几乎不动,30秒只击碎1块,节奏感极差", + "挡板横向插值太慢/球太慢,明显不像'中等速度 300~420 像素/秒'", + "砖块是单色整行而非按命中次数变色,未实现题目要求的'颜色随剩余命数变化'层次", + "游玩30秒仅+1分,玩后截图球仍在中下游飘移,缺乏紧张感与胜负刺激", + "无失败/通关态截图证据,未观察到失败态UI或重开反馈" + ], + "verdict": "fix", + "note": "功能基本完整能玩,但球/挡板节奏太拖、砖块多命层次缺失,30秒只掉1块,休闲玩家会觉得无聊。" + }, + "text": { + "model": "deepseek-v4-pro", + "completeness": 5, + "fun": 4, + "problems": [], + "verdict": "pass", + "note": "经典打砖块完整实现,打击反馈丰富,状态变化多样,控制响应无错误,可直接游玩。" + } + } + }, + { + "attempt": 3, + "role": "fix", + "model": "deepseek-v4-pro", + "stage_fail": null, + "usage": { + "in": 3510, + "out": 9676 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 5, + "fun": 4, + "problems": [ + "首帧中球初始位置距离挡板过远(约 400px),开局时球需要长时间下落到挡板,期间玩家无所事事", + "砖块间距有 5px 左右的小缝隙,球有可能从竖直砖缝中溜过(高速时更明显),破坏击砖判定", + "顶部 HUD 字号偏大且与文字标签重叠('engine RAF running' 覆盖在分数/剩余砖数字上方),观感杂乱", + "砖块只有两种颜色分层,未明确体现'需击中多次'的命数变化机制,视觉提示不足", + "失败态/通关态的文字提示在截图中未观察到,需确认是否真的进入失败/胜利画面并提供重新开始" + ], + "verdict": "fix", + "note": "核心循环完整、能正常击砖得分、手感尚可,但开局球位太远、砖缝漏球隐患和 HUD 叠字需要修一下。" + }, + "text": { + "model": "deepseek-v4-pro", + "completeness": 4, + "fun": 4, + "problems": [ + "未直接验证分数与剩余砖数的UI显示是否清晰可读(D_render仅检查整体亮色像素)", + "反弹角度调整逻辑无具体数据佐证" + ], + "verdict": "pass", + "note": "七门全过,音效粒子反馈足,核心循环正常;UI细节稍欠确凿但大概率存在。" + } + } + } + ], + "seven_gate_verdict": { + "gameId": "breakout-pro", + "url": "http://localhost:4322/games/_wg1-gen/breakout-pro/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 49, + "f1": 81, + "delta": 32 + }, + "D_render": { + "pass": true, + "bright": 141532, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 15, + "samples": 15 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 516, + "sample": [ + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx" + ], + "expected": [ + "particles.", + "audio.synth" + ] + }, + "G_input": { + "pass": true, + "inputHash": "9c1ef6e2", + "controlHash": "845461eb", + "atFrame": 476, + "ctrlFrame": 476 + } + }, + "pass": true, + "notes": [] + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 5, + "fun": 4, + "problems": [ + "首帧中球初始位置距离挡板过远(约 400px),开局时球需要长时间下落到挡板,期间玩家无所事事", + "砖块间距有 5px 左右的小缝隙,球有可能从竖直砖缝中溜过(高速时更明显),破坏击砖判定", + "顶部 HUD 字号偏大且与文字标签重叠('engine RAF running' 覆盖在分数/剩余砖数字上方),观感杂乱", + "砖块只有两种颜色分层,未明确体现'需击中多次'的命数变化机制,视觉提示不足", + "失败态/通关态的文字提示在截图中未观察到,需确认是否真的进入失败/胜利画面并提供重新开始" + ], + "verdict": "fix", + "note": "核心循环完整、能正常击砖得分、手感尚可,但开局球位太远、砖缝漏球隐患和 HUD 叠字需要修一下。" + }, + "text": { + "model": "deepseek-v4-pro", + "completeness": 4, + "fun": 4, + "problems": [ + "未直接验证分数与剩余砖数的UI显示是否清晰可读(D_render仅检查整体亮色像素)", + "反弹角度调整逻辑无具体数据佐证" + ], + "verdict": "pass", + "note": "七门全过,音效粒子反馈足,核心循环正常;UI细节稍欠确凿但大概率存在。" + } + }, + "tokens": { + "prompt": 35372, + "completion": 48415 + }, + "tokens_by_model": { + "deepseek-v4-pro": [ + 17912, + 47395 + ], + "MiniMax-M3": [ + 17460, + 1020 + ] + }, + "cost": { + "by_model": { + "deepseek-v4-pro": { + "in": 17912, + "out": 47395, + "rmb": 0.32255 + }, + "MiniMax-M3": { + "in": 17460, + "out": 1020, + "rmb": 0.09435 + } + }, + "total_rmb": 0.4169, + "gate_rmb": 0.15 + }, + "wall_s": 744.7, + "models": { + "design": "deepseek-v4-pro", + "code": "deepseek-v4-pro", + "fix": "deepseek-v4-pro", + "player_vision": "MiniMax-M3", + "player_text": "deepseek-v4-pro" + } +} \ No newline at end of file diff --git a/wg1/gen-worker/results/breakout.stage1.json b/wg1/gen-worker/results/breakout.stage1.json new file mode 100644 index 00000000..4a0e3bd9 --- /dev/null +++ b/wg1/gen-worker/results/breakout.stage1.json @@ -0,0 +1,190 @@ +{ + "game_id": "breakout", + "stage": "stage1", + "pass": true, + "repairs": 1, + "player_rounds_used": 1, + "design_text": "1. **核心机制**:玩家滑动触摸控制挡板左右移动,弹球碰砖块消砖得分,球越底边失败,清空全部砖块胜利。 \n2. **胜负条件**:胜利——所有砖块被消除;失败——球落至挡板下方(y > 844 - 挡板厚度)。 \n3. **操作**:触摸屏幕,挡板X向目标触摸点x平滑插值(每帧位移 = (targetX - currentX) * 0.15 或 clamp至最大速度800px/s)。 \n4. **关键数值**:球合速度 300~420 px/s(略随机化±10%);挡板厚度≥14px,宽度80~100px;砖网格6列×4~5行,砖块尺寸约60×20px,间距4px;部分砖需2次击碎(颜色渐变:满血→半血→消失)。 \n5. **Juice反馈**:击碎砖块 -> getEngine().particles.spawnEmitter(粒子爆发) + getEngine().audio.synth.synthSfx(清脆音);撞墙/挡板轻音效;通关或失败屏震。 \n6. **画面要点**:深色背景(#1a1a2e)铺满390×844;挡板亮蓝(#00d2ff)圆角矩形;球亮白/黄实心圆(半径8px);砖块按剩余命数绿→黄→红渐变;顶部HUD白字显示分数与剩余砖数。", + "attempts": [ + { + "attempt": 0, + "role": "code", + "stage_fail": null, + "usage": { + "in": 3235, + "out": 8000 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "顶部一直保留 'engine RAF running · seed=305441741 engine=real' 调试横幅,占视觉空间且不美观", + "首帧球就出现在挡板上方较高位置,没有'等待发射/按住发球'的初始态,开局体验略突兀", + "after-play 截图里球贴在右墙中部、挡板在屏幕底部,二者距离过远,30秒内小球参与感弱、回合节奏偏慢", + "砖块只有绿/橙两色且未明显看到剩余命数颜色阶梯,'多次击中'层次感不够强", + "粒子/音效触发次数(14次)与砖块消除数(2)对应偏多,可能墙/挡板撞击被过度播放,听感可能略吵" + ], + "verdict": "fix", + "note": "核心循环能跑通、输入与粒子音效接线正确,但调试横幅残留、开局无发射缓冲、回合节奏感偏弱,需要小幅打磨才够'想再玩一局'。" + }, + "text": { + "model": "deepseek-v4-flash", + "completeness": 4, + "fun": 3, + "problems": [ + "未观察到多次击打砖块的颜色变化逻辑,可能未实现" + ], + "verdict": "pass", + "note": "核心循环基本完整,有粒子与音效反馈,但缺乏多次击打砖块的证据,趣味性中等" + } + } + }, + { + "attempt": 1, + "role": "fix", + "stage_fail": null, + "usage": { + "in": 3449, + "out": 9490 + }, + "seven_gate_pass": true, + "guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "游玩仅30秒内已 GAME OVER,最终分数仅1(命中1砖即死),手感过快/球速偏高或挡板操控迟滞", + "挡板起点距底部较远(约屏幕中下部),下坠时挡板来不及追球", + "首帧挡板不在底部居中(看似漂浮在中部),与说明'底部挡板'略有不符", + "Tap to start / Tap to restart 提示文本未居中对齐,且首帧文字压在砖块上视觉略乱", + "调试横幅 'engine RAF running · seed=…' 直接暴露在画面顶部,破坏沉浸感", + "砖块只剩3行最底层为1次击破(绿色/黄色已消失),难度设计成 '一碰即Game Over' 不合理;生命或残机机制缺失" + ], + "verdict": "fix", + "note": "核心循环(球/挡板/砖块/胜负/粒子音效)都跑通,但30秒就Game Over节奏过暴,挡板位置偏高且首帧文案压砖、调试banner未隐藏,体验未达标。" + }, + "text": { + "model": "deepseek-v4-flash", + "completeness": 4, + "fun": 3, + "problems": [], + "verdict": "pass", + "note": "核心循环完整,有音效粒子反馈,表现稳定。但缺乏新颖元素,手感中规中矩。" + } + } + } + ], + "seven_gate_verdict": { + "gameId": "breakout", + "url": "http://localhost:4320/games/_wg1-gen/breakout/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 59, + "f1": 89, + "delta": 30 + }, + "D_render": { + "pass": true, + "bright": 144954, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 12, + "samples": 15 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 487, + "sample": [ + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "audio.synth.synthSfx", + "audio.synth.synthSfx" + ], + "expected": [ + "particles.", + "audio.synth" + ] + }, + "G_input": { + "pass": true, + "inputHash": "1ca1defe", + "controlHash": "29b834df", + "atFrame": 484, + "ctrlFrame": 488 + } + }, + "pass": true, + "notes": [] + }, + "player": { + "vision": { + "model": "MiniMax-M3", + "completeness": 4, + "fun": 3, + "problems": [ + "游玩仅30秒内已 GAME OVER,最终分数仅1(命中1砖即死),手感过快/球速偏高或挡板操控迟滞", + "挡板起点距底部较远(约屏幕中下部),下坠时挡板来不及追球", + "首帧挡板不在底部居中(看似漂浮在中部),与说明'底部挡板'略有不符", + "Tap to start / Tap to restart 提示文本未居中对齐,且首帧文字压在砖块上视觉略乱", + "调试横幅 'engine RAF running · seed=…' 直接暴露在画面顶部,破坏沉浸感", + "砖块只剩3行最底层为1次击破(绿色/黄色已消失),难度设计成 '一碰即Game Over' 不合理;生命或残机机制缺失" + ], + "verdict": "fix", + "note": "核心循环(球/挡板/砖块/胜负/粒子音效)都跑通,但30秒就Game Over节奏过暴,挡板位置偏高且首帧文案压砖、调试banner未隐藏,体验未达标。" + }, + "text": { + "model": "deepseek-v4-flash", + "completeness": 4, + "fun": 3, + "problems": [], + "verdict": "pass", + "note": "核心循环完整,有音效粒子反馈,表现稳定。但缺乏新颖元素,手感中规中矩。" + } + }, + "tokens": { + "prompt": 17632, + "completion": 19735 + }, + "wall_s": 276.4, + "models": { + "design": "deepseek-v4-flash", + "code": "deepseek-v4-flash", + "fix": "deepseek-v4-flash", + "player_vision": "MiniMax-M3", + "player_text": "deepseek-v4-flash" + } +} \ No newline at end of file diff --git a/wg1/gen-worker/results/pong.json b/wg1/gen-worker/results/pong.json new file mode 100644 index 00000000..72febfea --- /dev/null +++ b/wg1/gen-worker/results/pong.json @@ -0,0 +1,99 @@ +{ + "game_id": "pong", + "model": "deepseek-v4-flash", + "pass": true, + "retries": 0, + "attempts": [ + { + "attempt": 0, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 2861, + "completion_tokens": 4775, + "total_tokens": 7636, + "wall_s": 57.344, + "id": "8000e98a-02da-4d50-98c0-3f96d28eeea8", + "finish_reason": "stop" + }, + "play_pass": true, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + } + } + ], + "factory_path": "game-runtime/games/_wg1-gen/pong/factory.js", + "bundle_path": "game-runtime/games/_wg1-gen/pong/bundle.iife.js", + "verdict": { + "gameId": "pong", + "url": "http://localhost:4320/games/_wg1-gen/pong/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 48, + "f1": 78, + "delta": 30 + }, + "D_render": { + "pass": true, + "bright": 17318, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 13, + "samples": 13 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 11, + "sample": [ + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx" + ], + "expected": [ + "particles.", + "audio.synth" + ] + }, + "G_input": { + "pass": true, + "inputHash": "0d7715dc", + "controlHash": "855a1c03", + "atFrame": 444, + "ctrlFrame": 445 + } + }, + "pass": true, + "notes": [] + }, + "tokens": { + "prompt": 2861, + "completion": 4775 + }, + "request_ids": [ + "8000e98a-02da-4d50-98c0-3f96d28eeea8" + ] +} \ No newline at end of file diff --git a/wg1/gen-worker/results/simon.json b/wg1/gen-worker/results/simon.json new file mode 100644 index 00000000..4a6208dd --- /dev/null +++ b/wg1/gen-worker/results/simon.json @@ -0,0 +1,149 @@ +{ + "game_id": "simon", + "model": "deepseek-v4-flash", + "pass": true, + "retries": 2, + "attempts": [ + { + "attempt": 0, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 2889, + "completion_tokens": 5185, + "total_tokens": 8074, + "wall_s": 64.097, + "id": "209eb027-fdda-4329-9ba7-e1080481463e", + "finish_reason": "stop" + }, + "play_pass": false, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": false, + "B_uncaught": true, + "F_wiring": false, + "G_input": false + } + }, + { + "attempt": 1, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 3079, + "completion_tokens": 4136, + "total_tokens": 7215, + "wall_s": 44.641, + "id": "67601480-dab4-4a9b-8678-9439300404c9", + "finish_reason": "stop" + }, + "play_pass": false, + "verdict_guards": { + "A_boot": true, + "C_frame": false, + "D_render": false, + "E_live": false, + "B_uncaught": false, + "F_wiring": false, + "G_input": false + } + }, + { + "attempt": 2, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 3152, + "completion_tokens": 4899, + "total_tokens": 8051, + "wall_s": 52.141, + "id": "1b2f10ad-c080-4ae9-9d3f-fa2096861ce7", + "finish_reason": "stop" + }, + "play_pass": true, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + } + } + ], + "factory_path": "game-runtime/games/_wg1-gen/simon/factory.js", + "bundle_path": "game-runtime/games/_wg1-gen/simon/bundle.iife.js", + "verdict": { + "gameId": "simon", + "url": "http://localhost:4320/games/_wg1-gen/simon/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 48, + "f1": 79, + "delta": 31 + }, + "D_render": { + "pass": true, + "bright": 264569, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 6, + "samples": 11 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 128, + "sample": [ + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut" + ], + "expected": [ + "audio.synth", + "particles." + ] + }, + "G_input": { + "pass": true, + "inputHash": "a5100b7a", + "controlHash": "f7530fdd", + "atFrame": 400, + "ctrlFrame": 405 + } + }, + "pass": true, + "notes": [] + }, + "tokens": { + "prompt": 9120, + "completion": 14220 + }, + "request_ids": [ + "209eb027-fdda-4329-9ba7-e1080481463e", + "67601480-dab4-4a9b-8678-9439300404c9", + "1b2f10ad-c080-4ae9-9d3f-fa2096861ce7" + ] +} \ No newline at end of file diff --git a/wg1/gen-worker/results/simon_m27.json b/wg1/gen-worker/results/simon_m27.json new file mode 100644 index 00000000..fe72a6d5 --- /dev/null +++ b/wg1/gen-worker/results/simon_m27.json @@ -0,0 +1,113 @@ +{ + "game_id": "simon_m27", + "model": "MiniMax-M2.7", + "pass": true, + "retries": 1, + "attempts": [ + { + "attempt": 0, + "stage": "validate", + "errors": [ + "违禁:禁引擎名字空间" + ], + "usage": { + "prompt_tokens": 2772, + "completion_tokens": 9060, + "total_tokens": 11832, + "wall_s": 50.423, + "id": "067d72961fd8f0b8281f7b2eb1cd1c98", + "finish_reason": "stop" + } + }, + { + "attempt": 1, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 2810, + "completion_tokens": 2852, + "total_tokens": 5662, + "wall_s": 38.424, + "id": "067d72c8e53af4df07b125150952614d", + "finish_reason": "stop" + }, + "play_pass": true, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + } + } + ], + "factory_path": "game-runtime/games/_wg1-gen/simon_m27/factory.js", + "bundle_path": "game-runtime/games/_wg1-gen/simon_m27/bundle.iife.js", + "verdict": { + "gameId": "simon_m27", + "url": "http://localhost:4320/games/_wg1-gen/simon_m27/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 54, + "f1": 84, + "delta": 30 + }, + "D_render": { + "pass": true, + "bright": 346491, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 5, + "samples": 11 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 409, + "sample": [ + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter", + "audio.synth.synthSfx", + "particles.spawnEmitter" + ], + "expected": [ + "audio.synth", + "particles." + ] + }, + "G_input": { + "pass": true, + "inputHash": "94bda89a", + "controlHash": "990dbcba", + "atFrame": 403, + "ctrlFrame": 405 + } + }, + "pass": true, + "notes": [] + }, + "tokens": { + "prompt": 5582, + "completion": 11912 + }, + "request_ids": [ + "067d72961fd8f0b8281f7b2eb1cd1c98", + "067d72c8e53af4df07b125150952614d" + ] +} \ No newline at end of file diff --git a/wg1/gen-worker/results/simon_pro.json b/wg1/gen-worker/results/simon_pro.json new file mode 100644 index 00000000..d30606c3 --- /dev/null +++ b/wg1/gen-worker/results/simon_pro.json @@ -0,0 +1,101 @@ +{ + "game_id": "simon_pro", + "model": "deepseek-v4-pro", + "pass": true, + "retries": 0, + "attempts": [ + { + "attempt": 0, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 2889, + "completion_tokens": 9445, + "total_tokens": 12334, + "wall_s": 111.022, + "id": "887836a1-9cee-4b46-a487-adf707b790dd", + "finish_reason": "stop" + }, + "play_pass": true, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + } + } + ], + "factory_path": "game-runtime/games/_wg1-gen/simon_pro/factory.js", + "bundle_path": "game-runtime/games/_wg1-gen/simon_pro/bundle.iife.js", + "verdict": { + "gameId": "simon_pro", + "url": "http://localhost:4320/games/_wg1-gen/simon_pro/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 49, + "f1": 79, + "delta": 30 + }, + "D_render": { + "pass": true, + "bright": 279271, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 7, + "samples": 11 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 611, + "sample": [ + "audio.synth.synthSfx", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut" + ], + "expected": [ + "audio.synth", + "particles." + ] + }, + "G_input": { + "pass": true, + "inputHash": "2306aab3", + "controlHash": "33f7eb0b", + "atFrame": 399, + "ctrlFrame": 403 + } + }, + "pass": true, + "notes": [] + }, + "tokens": { + "prompt": 2889, + "completion": 9445 + }, + "request_ids": [ + "887836a1-9cee-4b46-a487-adf707b790dd" + ] +} \ No newline at end of file diff --git a/wg1/gen-worker/results/whack.json b/wg1/gen-worker/results/whack.json new file mode 100644 index 00000000..18345e0c --- /dev/null +++ b/wg1/gen-worker/results/whack.json @@ -0,0 +1,101 @@ +{ + "game_id": "whack", + "model": "deepseek-v4-flash", + "pass": true, + "retries": 0, + "attempts": [ + { + "attempt": 0, + "stage": "play", + "errors": [], + "usage": { + "prompt_tokens": 2899, + "completion_tokens": 7223, + "total_tokens": 10122, + "wall_s": 82.596, + "id": "4c7994cd-39e6-4f4a-ba0a-2c91b423abc6", + "finish_reason": "stop" + }, + "play_pass": true, + "verdict_guards": { + "A_boot": true, + "C_frame": true, + "D_render": true, + "E_live": true, + "B_uncaught": true, + "F_wiring": true, + "G_input": true + } + } + ], + "factory_path": "game-runtime/games/_wg1-gen/whack/factory.js", + "bundle_path": "game-runtime/games/_wg1-gen/whack/bundle.iife.js", + "verdict": { + "gameId": "whack", + "url": "http://localhost:4320/games/_wg1-gen/whack/index.html", + "ts": null, + "guards": { + "A_boot": { + "pass": true + }, + "C_frame": { + "pass": true, + "f0": 49, + "f1": 80, + "delta": 31 + }, + "D_render": { + "pass": true, + "bright": 10256, + "maxCh": 255 + }, + "E_live": { + "pass": true, + "distinctStates": 15, + "samples": 15 + }, + "B_uncaught": { + "pass": true, + "uncaught": [] + }, + "F_wiring": { + "pass": true, + "callCount": 691, + "sample": [ + "audio.synth.synthSfx", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut", + "math.easing.quadOut" + ], + "expected": [ + "particles.", + "audio.synth" + ] + }, + "G_input": { + "pass": true, + "inputHash": "a9de479b", + "controlHash": "b0584efe", + "atFrame": 446, + "ctrlFrame": 448 + } + }, + "pass": true, + "notes": [] + }, + "tokens": { + "prompt": 2899, + "completion": 7223 + }, + "request_ids": [ + "4c7994cd-39e6-4f4a-ba0a-2c91b423abc6" + ] +} \ No newline at end of file diff --git a/wg1/gen-worker/worker/_client.py b/wg1/gen-worker/worker/_client.py new file mode 100644 index 00000000..8af58f4e --- /dev/null +++ b/wg1/gen-worker/worker/_client.py @@ -0,0 +1,108 @@ +"""_client.py —— W-G1 L1 裸路模型客户端(复用 spike 代理旁路 + 裸 openai 客户端 + usage 读取)。 + +L1 纪律(spike VERDICT §3/§6):裸 llm_client,不引 AgentScope(框架 token 膨胀+本地开销吃便宜档单价)。 +唯一模型出口 = new-api OpenAI 兼容网关(BASE_URL/v1),绝不直连厂商 SDK;密钥只走环境变量/本地 .env,绝不入库。 +""" + +import os +import time +from pathlib import Path +from urllib.parse import urlparse + +# ── 本地 .env 加载(wg1/gen-worker/.env,gitignored):密钥外置,不落代码 ── +_ENV_PATH = Path(__file__).resolve().parent.parent / ".env" + + +def _load_env(): + """把 wg1/gen-worker/.env 里的 KEY=VAL 注入环境(已存在的不覆盖)。""" + if not _ENV_PATH.exists(): + return + for line in _ENV_PATH.read_text(encoding="utf-8").splitlines(): + line = line.strip() + if not line or line.startswith("#") or "=" not in line: + continue + k, v = line.split("=", 1) + os.environ.setdefault(k.strip(), v.strip()) + + +_load_env() + +# 网关地址(可被环境变量覆盖;默认 new-api Tailscale 网关 OpenAI 兼容路径)。 +BASE_URL = os.environ.get("NEWAPI_BASE_URL", "http://100.64.0.8:3000/v1") +# L1 目标模型(可被 WG1_MODEL 覆盖;冒烟默认最便宜档 deepseek-v4-flash)。 +DEFAULT_MODEL = os.environ.get("WG1_MODEL", "deepseek-v4-flash") + +# ── 代理旁路(spike VERDICT §4-坑1,必须在 import openai 前)── +# 本机 clash 代理(HTTP(S)_PROXY=127.0.0.1:7897) 会把发往 100.64.0.8 的请求经代理转发→502; +# httpx/openai 默认 trust_env=True,须把网关 host 并入大小写两个 NO_PROXY 才直连。 +_GW_HOST = urlparse(BASE_URL).hostname or "100.64.0.8" +for _k in ("NO_PROXY", "no_proxy"): + _cur = os.environ.get(_k, "") + if _GW_HOST not in _cur: + os.environ[_k] = (_cur + "," + _GW_HOST) if _cur else _GW_HOST + +import openai # noqa: E402 —— 必须在代理旁路之后导入 + + +def get_api_key(): + """读 NEWAPI_KEY(缺失即抛,密钥不入库、复现前先设 .env 或 export)。""" + key = os.environ.get("NEWAPI_KEY") + if not key: + raise RuntimeError("NEWAPI_KEY 未设:请在 wg1/gen-worker/.env 写入或 export NEWAPI_KEY=...") + return key + + +def get_client(): + """构建指向 new-api 的裸 OpenAI 兼容客户端。""" + return openai.OpenAI(api_key=get_api_key(), base_url=BASE_URL, max_retries=2, timeout=180.0) + + +def chat(model, system, user, max_tokens=16000, temperature=0.0, tries=3, retry_delay=2.0): + """单次裸调用 chat.completions。确定性产出 temperature=0;瞬时网关错误(502 burst)重试。 + + 返回 dict:{content, prompt_tokens, completion_tokens, total_tokens, model, wall_s, id, finish_reason}。 + usage 字段用 openai 2.41.1 口径:prompt_tokens / completion_tokens(供成本折算与 token 取证)。 + """ + client = get_client() + last_err = None + for attempt in range(tries): + try: + t0 = time.perf_counter() + resp = client.chat.completions.create( + model=model, + messages=[ + {"role": "system", "content": system}, + {"role": "user", "content": user}, + ], + temperature=temperature, + max_tokens=max_tokens, + stream=False, + ) + wall = time.perf_counter() - t0 + choice = resp.choices[0] + usage = resp.usage + return { + "content": choice.message.content or "", + "finish_reason": getattr(choice, "finish_reason", None), + "prompt_tokens": getattr(usage, "prompt_tokens", None), + "completion_tokens": getattr(usage, "completion_tokens", None), + "total_tokens": getattr(usage, "total_tokens", None), + "model": model, + "wall_s": round(wall, 3), + "id": getattr(resp, "id", None), + } + except Exception as e: # 瞬时网关错误重试(spike 实测 new-api 偶发 502 burst) + last_err = e + if attempt < tries - 1: + time.sleep(retry_delay) + raise RuntimeError(f"模型调用失败({tries} 次重试后):{last_err}") + + +if __name__ == "__main__": + # 自测:列模型(零 token 成本)确认 客户端+代理旁路+密钥 三件齐活。 + c = get_client() + ids = sorted(m.id for m in c.models.list().data) + print(f"[_client] BASE_URL={BASE_URL} NO_PROXY 含网关={_GW_HOST in os.environ.get('NO_PROXY','')}") + print(f"[_client] 可用模型 {len(ids)} 个:") + for i in ids: + print(" ", i) diff --git a/wg1/gen-worker/worker/agent_loop/__init__.py b/wg1/gen-worker/worker/agent_loop/__init__.py new file mode 100644 index 00000000..f047e01d --- /dev/null +++ b/wg1/gen-worker/worker/agent_loop/__init__.py @@ -0,0 +1,6 @@ +"""agent_loop —— W-G1 L2 最小 agentic studio(on AgentScope 进程内多 agent)。 + +设计→代码→七门真玩(确定性地板)→player panel(真玩真判)→自修复 的多角色闭环。 +模型=per-agent 可替换旋钮(models.yaml);框架适配隔离于此包,AgentScope 可替换(不 fork)。 +L1 单发裸路仍在 worker/run.py(--no-agentscope 退化口)。 +""" diff --git a/wg1/gen-worker/worker/agent_loop/calibrate.py b/wg1/gen-worker/worker/agent_loop/calibrate.py new file mode 100644 index 00000000..2090b335 --- /dev/null +++ b/wg1/gen-worker/worker/agent_loop/calibrate.py @@ -0,0 +1,199 @@ +"""agent_loop/calibrate.py —— W-G1 player-panel 校准("好玩 Claude-free 可信"的命门验证)。 + +目的:在【已知答案】样本上测 player(vision/text) 判定 vs 人类锚的吻合度, +重点 = 反样本(空心游戏)否决率——这是 text player 翻车、整个 W-G1 论点站不站得住的命门。 + +锚来源(见 labels.json.anchor_note): + · hollow 反样本 = 客观锚(真玩 remaining 零变化=空心,无主观成分); + · good 正样本 = opus-proxy 临时锚,创始人亲玩后覆盖 human.fun/verdict 即权威。 + +复用 studio 的 _judge_vision/_judge_text(与生产同一 player prompt/同款人格/同 max_tokens), +吃各游戏已存的 evidence(first-paint.png/after-play.png/verdict.json),不重开服务=便宜可复跑。 +""" + +import argparse +import json +import sys +from collections import defaultdict +from pathlib import Path + +# 包内/直跑兼容导入(镜像 studio.py 的导入范式)。 +try: + from . import config, studio + from .. import run, cost +except ImportError: + sys.path.insert(0, str(Path(__file__).resolve().parents[1])) + import run, cost # type: ignore + from agent_loop import config, studio # type: ignore + +WORKER_ROOT = Path(__file__).resolve().parents[2] # wg1/gen-worker +CALIB_DIR = WORKER_ROOT / "calibration" +GEN_DIR = run.GEN_DIR +BRIEFS_DIR = run.BRIEFS_DIR + +# 生产同款人格(与 studio.run_player_panel 内联人格逐字一致,保证校准的是生产 player)。 +PERSONA_VISION = "急性子休闲玩家,凭第一眼观感和反馈下判断" +PERSONA_TEXT = "细致的完整度审查者,只信运行数据、不脑补" + + +def _load_verdict(game_id): + """读某游戏的真玩 verdict(喂文本 player 的运行数据;缺失返回 None)。""" + p = GEN_DIR / game_id / "evidence" / "verdict.json" + if p.exists(): + try: + return json.loads(p.read_text(encoding="utf-8")) + except Exception: + return None + return None + + +def _load_brief(brief_ref): + """读题面文本(与生成时同一 brief,保证 player 看到的题面口径一致)。""" + p = BRIEFS_DIR / f"{brief_ref}.json" + return json.loads(p.read_text(encoding="utf-8"))["brief"] + + +def _judge_user_text(brief, verdict): + """组装喂给 player 的证据文本(与 studio.run_player_panel 同口径)。""" + summary = studio._play_summary(verdict) + return (f"游戏题面:\n{brief}\n\n{summary}\n\n" + "请基于以上证据(及截图,若有)给出你的玩家评判。") + + +def _num(x): + """安全取数字(player 偶尔把分数写成字符串)。非数字返回 None。""" + if isinstance(x, bool): + return None + if isinstance(x, (int, float)): + return x + try: + return float(x) + except (TypeError, ValueError): + return None + + +def run_calibration(labels_path, stage): + """跑校准:逐样本跑 vision+text player → 算每位 player 的吻合指标。返回报告 dict。""" + labels = json.loads(Path(labels_path).read_text(encoding="utf-8")) + samples = labels["samples"] + vis_model = config.model_name_for("player_vision", stage) + txt_model = config.model_name_for("player_text", stage) + per_model = defaultdict(lambda: [0, 0]) # model -> [in, out] + rows = [] + + for s in samples: + gid = s["game_id"] + brief = _load_brief(s["brief_ref"]) + verdict = _load_verdict(gid) + ut = _judge_user_text(brief, verdict) + # 视觉位(吃截图) + try: + vj, (vi, vo) = studio._judge_vision(vis_model, PERSONA_VISION, ut, gid) + per_model[vis_model][0] += vi + per_model[vis_model][1] += vo + except Exception as e: + vj = {"error": str(e)[:180]} + # 文本位(仅运行数据) + try: + tj, (ti, to) = studio._judge_text(txt_model, PERSONA_TEXT, ut) + per_model[txt_model][0] += ti + per_model[txt_model][1] += to + except Exception as e: + tj = {"error": str(e)[:180]} + rows.append({"game_id": gid, "class": s["class"], "human": s["human"], + "vision": vj, "text": tj}) + + # ── 指标:逐 player 算 好玩 MAE / verdict 吻合 / 反样本否决·假绿 / 正样本接受 ── + metrics = {} + for who, mname in (("vision", vis_model), ("text", txt_model)): + fun_abs = [] + verdict_match = n_verdict = 0 + hollow_total = hollow_rejected = hollow_false_green = 0 + good_total = good_accepted = 0 + for r in rows: + pj, human, cls = r[who], r["human"], r["class"] + pf, pv = _num(pj.get("fun")), str(pj.get("verdict")) + hf, hv = _num(human.get("fun")), str(human.get("verdict")) + if pf is not None and hf is not None: + fun_abs.append(abs(pf - hf)) + if pv in ("pass", "fix"): + n_verdict += 1 + if pv == hv: + verdict_match += 1 + if cls == "hollow": + hollow_total += 1 + # 正确否决 = 判 fix 且 好玩≤2(既看 verdict 也看分,防"判 fix 却给高分"的矛盾) + if pv == "fix" and pf is not None and pf <= 2: + hollow_rejected += 1 + # 危险假绿 = 放过空心(判 pass 或 好玩≥3) + if pv == "pass" or (pf is not None and pf >= 3): + hollow_false_green += 1 + elif cls == "good": + good_total += 1 + if pv == "pass" and pf is not None and pf >= 3: + good_accepted += 1 + # 是否够格当 Claude-free 好玩门:必须 100% 否决反样本(零假绿)+ 不误杀正样本 + gatekeeper_ok = (hollow_total > 0 and hollow_false_green == 0 + and (good_total == 0 or good_accepted == good_total)) + metrics[who] = { + "model": mname, + "fun_mae": round(sum(fun_abs) / len(fun_abs), 2) if fun_abs else None, + "verdict_match": f"{verdict_match}/{n_verdict}", + "hollow_rejected": f"{hollow_rejected}/{hollow_total}", + "hollow_false_green": f"{hollow_false_green}/{hollow_total}", + "good_accepted": f"{good_accepted}/{good_total}", + "gatekeeper_ok": gatekeeper_ok, + } + + # ── 成本(测而不闸;复用 cost.py 的 new-api quota 口径)── + try: + pricing = cost.fetch_pricing() + qpu, usd = cost.fetch_status() + rws, total = {}, 0.0 + for name, (i, o) in per_model.items(): + c = cost.compute(name, i, o, pricing, qpu, usd) + rws[name] = {"in": i, "out": o, "rmb": c["rmb"]} + total += c["rmb"] + cost_info = {"by_model": rws, "total_rmb": round(total, 5)} + except Exception as e: + cost_info = {"error": str(e)[:180], + "by_model": {k: {"in": v[0], "out": v[1]} for k, v in per_model.items()}} + + report = {"stage": stage, "n_samples": len(samples), + "anchor_note": labels.get("anchor_note", ""), + "rows": rows, "metrics": metrics, "cost": cost_info} + CALIB_DIR.mkdir(parents=True, exist_ok=True) + (CALIB_DIR / "report.json").write_text( + json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8") + return report + + +def main(): + ap = argparse.ArgumentParser(description="W-G1 player-panel 校准") + ap.add_argument("--labels", default=str(CALIB_DIR / "labels.json")) + ap.add_argument("--stage", default=None, help="models.yaml 阶段(默认 default_stage)") + args = ap.parse_args() + _cfg, default_stage = config.load_config() + stage = args.stage or default_stage + print(f"[calib] stage={stage} labels={args.labels}") + rep = run_calibration(args.labels, stage) + + print("\n=== player 校准报告(逐样本)===") + for r in rep["rows"]: + h, v, t = r["human"], r["vision"], r["text"] + flag = "🟥反样本" if r["class"] == "hollow" else "🟩正样本" + print(f"\n[{r['game_id']}] {flag} 人类锚 fun={h.get('fun')} verdict={h.get('verdict')} ({h.get('anchor')})") + print(f" vision: fun={v.get('fun')} verdict={v.get('verdict')} note={str(v.get('note') or v.get('error'))[:64]}") + print(f" text : fun={t.get('fun')} verdict={t.get('verdict')} note={str(t.get('note') or t.get('error'))[:64]}") + print("\n--- 指标(命门=反样本假绿必须 0/N)---") + for who, m in rep["metrics"].items(): + verdict_gate = "✅够格当好玩门" if m["gatekeeper_ok"] else "❌不够格" + print(f" {who}({m['model']}): fun_MAE={m['fun_mae']} verdict吻合={m['verdict_match']} " + f"反样本否决={m['hollow_rejected']} 反样本假绿={m['hollow_false_green']} " + f"正样本接受={m['good_accepted']} → {verdict_gate}") + c = rep.get("cost") or {} + print(f"\n[calib] ¥={c.get('total_rmb', '?')} report → wg1/gen-worker/calibration/report.json") + + +if __name__ == "__main__": + main() diff --git a/wg1/gen-worker/worker/agent_loop/config.py b/wg1/gen-worker/worker/agent_loop/config.py new file mode 100644 index 00000000..cd668a09 --- /dev/null +++ b/wg1/gen-worker/worker/agent_loop/config.py @@ -0,0 +1,74 @@ +"""agent_loop/config.py —— 模型路由:读 models.yaml,按 agent 角色+阶段建 AgentScope 模型客户端。 + +模型=可替换配置旋钮:换 stage / 换某角色模型只改 models.yaml。 +关键:导入 _client 即完成 .env 加载 + 代理旁路(NO_PROXY 含网关 host)——必须在 AgentScope/openai +客户端构建前,否则本机 clash 代理把发往网关的请求转走 → 502(spike VERDICT 头号坑)。 +""" + +from pathlib import Path +import yaml + +# 先导 _client:其 import 副作用 = 加载 .env + 把网关 host 并入 NO_PROXY(代理旁路)。 +try: + from .. import _client +except ImportError: # 直接执行兜底 + import sys + sys.path.insert(0, str(Path(__file__).resolve().parents[1])) + import _client # type: ignore + +# _client 已设好 NO_PROXY,此后再导入 agentscope(内部用 openai/httpx)才直连网关。 +from agentscope.credential import OpenAICredential +from agentscope.model import OpenAIChatModel + +_CFG_PATH = Path(__file__).resolve().parents[1] / "models.yaml" + + +class RecordingChatModel(OpenAIChatModel): + """记录每次调用 usage 的模型子类(per-agent token 取证,供成本/Stage 对比)。""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.records = [] # [(input_tokens, output_tokens)] + + async def __call__(self, messages, **kwargs): + resp = await super().__call__(messages, **kwargs) + u = resp.get("usage") if hasattr(resp, "get") else getattr(resp, "usage", None) + if u is not None: + self.records.append((int(getattr(u, "input_tokens", 0) or 0), + int(getattr(u, "output_tokens", 0) or 0))) + return resp + + def usage_sum(self): + return (sum(r[0] for r in self.records), sum(r[1] for r in self.records)) + + +def load_config(): + """读 models.yaml。返回 (cfg, default_stage)。""" + cfg = yaml.safe_load(_CFG_PATH.read_text(encoding="utf-8")) + return cfg, cfg.get("default_stage", "stage1") + + +def model_name_for(role, stage=None): + """按角色+阶段取模型名;缺角色回退该阶段 _default。""" + cfg, default_stage = load_config() + stage = stage or default_stage + roles = cfg["stages"][stage]["roles"] + return roles.get(role) or roles["_default"] + + +def build_model(model_name, stream=False, max_retries=2, record=True): + """建 AgentScope 2.0.1 OpenAI 兼容模型客户端(base_url 落 credential,2.0.1 正确姿势; + max_retries>0 兜网关偶发 502 突发,spike 实证有效;record=True 记 usage 供成本取证)。""" + cls = RecordingChatModel if record else OpenAIChatModel + return cls( + credential=OpenAICredential(api_key=_client.get_api_key(), base_url=_client.BASE_URL), + model=model_name, + stream=stream, + max_retries=max_retries, + ) + + +def model_for_role(role, stage=None, **kw): + """便捷:角色→模型客户端(一步到位)。返回 (model_name, model_client)。""" + name = model_name_for(role, stage) + return name, build_model(name, **kw) diff --git a/wg1/gen-worker/worker/agent_loop/roles.py b/wg1/gen-worker/worker/agent_loop/roles.py new file mode 100644 index 00000000..b3eb2336 --- /dev/null +++ b/wg1/gen-worker/worker/agent_loop/roles.py @@ -0,0 +1,57 @@ +"""agent_loop/roles.py —— studio 各 agent 角色 system prompt。 + +code / fix 角色复用 worker/prompt.py(已有装载契约/能力面/禁用项/few-shot 的完整上下文包), +本文件只新增 design(设计 agent)与 player(玩家 agent)两个角色提示。 +""" + +# 设计 agent:把一句话题面 → 可实现的设计稿,喂给代码 agent。不写代码。 +DESIGN_SYSTEM = r"""你是轻量 H5 小游戏的【设计 agent】。输入是一句话/一段题面,你的产出是一份**简洁、可直接实现**的设计稿,供下游代码 agent 写成游戏。 + +【只产出设计稿,绝不写代码】输出用紧凑中文条目,覆盖: +1. 核心机制:玩家做什么、目标是什么(一两句说清玩法循环)。 +2. 胜负条件:怎样算赢、怎样算输(**必须有"会输"的失败态**——超时/失误/资源耗尽任一)。 +3. 操作:触摸/按键如何映射到动作(记住坐标是逻辑像素 390×844 竖屏)。 +4. 关键数值:速度/数量/尺寸/难度梯度的建议区间(给具体数,别含糊)。 +5. juice 反馈:哪些事件该有粒子/音效/屏震(至少 1 处必须触发引擎能力)。 +6. 画面要点:背景铺满、主要元素形状与颜色、HUD(分数等)。 +7. 可观测进展:点明"玩家在推进"的可量化信号(如剩余目标数下降 / 分数上升 / 关卡推进),并说明胜负如何切状态——这是判"真有进展、非空心"的依据。 + +【约束】设计正文控制在 ~200 字内,聚焦"代码 agent 实现时需要的决策",不堆砌辞藻、不写引擎/契约细节(那是代码 agent 的事)。 + +【末尾必附 gate-spec(机器可读·harness 据此确定性验"能玩 + 手感"·这是 gate-H 推广到任意游戏的关键)】 +设计正文之后另起一个 ```gatespec 代码块,块内为 JSON,声明本游戏怎样被确定性验证: +```gatespec +{ + "exportState": ["phase","score","remaining","progress","<关键实体位置:如 ball:{x,y,vx,vy}、paddle:{x,y,w};纯点击类可省位置>"], + "driver": {"type":"paddle-intercept","ballPath":"ball.x","paddleY":800}, + "controlCheck": {"paddlePath":"paddle.x","tapXs":[50,340]}, + "assertAfterPlay": [{"path":"remaining","op":"decreased","why":"击碎砖块→剩余下降"}], + "expectLatch": true +} +``` +规则:① `expectLatch` 恒 true(游戏必须能真玩到 gameover 且驻留);② 有"连续控制体(挡板/角色随手指平滑移动)"才给 `controlCheck`,纯点击/无连续控制给 null;③ 技巧类(挡板接球/接物)`driver.type="paddle-intercept"`,`ballPath`=**球的水平 x 坐标字段**(挡板水平移动去对齐它,几乎总是 `ball.x`,**绝不要填 ball.y**),`paddleY`=挡板所在 y;纯点击类用 `{"type":"none"}`;④ `assertAfterPlay` 至少一条"真有进展"断言(op ∈ increased/decreased/changed/>/>=/ str: + return ( + f"你是一名【玩家 agent】,人格设定:{persona}。\n" + "你会拿到一款 H5 小游戏的【运行数据】(确定性 harness 真玩取证:是否真渲染/输入是否真生效/调了哪些引擎能力、" + "以及 H_progress 机制进展门是否过),可能还附【首帧截图】与【玩后截图】。" + "请像真玩家那样、严格基于**证据**判断(不要脑补没看到的东西)。\n\n" + "【第一步必须先判「真有进展」,再谈好玩】对比首帧↔玩后截图、看运行数据:\n" + "- 若画面玩前玩后几乎无变化,或数据显示分数/剩余/进度【零变化】(如剩余砖数没减、分数没动)," + "或 H_progress(机制进展)门未过 → 判定为【空心游戏】:fun 必须给 1~2、verdict=fix。**空心绝不给 3 分及以上。**\n" + "- 截图里看不到反馈(粒子/数字跳动/元素消除)→ 按「反馈缺失」扣分。\n\n" + "【好玩 fun(1-5) 分锚——务必拉开档,别都给 3】\n" + " 1 = 不能玩 / 空心零进展;2 = 能跑但无聊(无反馈 / 无失败态 / 原地打转);" + "3 = 基础可玩(循环成立、有反馈,但平淡);4 = 有手感、看得到进展、想再玩一把;5 = 惊艳,节奏与反馈都到位。\n" + "【完整度 completeness(1-5)】能玩吗?核心循环 / 可见反馈 / 胜负态是否齐全(空心或缺胜负 → ≤2)。\n" + "【verdict】真有进展且至少基础可玩(fun≥3) → 可 pass;空心或明显体验缺陷 → fix。" + "别对每个游戏都 fix(会失去区分力),也别放过空心。\n" + "诚实、挑剔,但分数要反映**真实差距**:好游戏和空壳必须给出不同的分。\n" + '【只输出 JSON】:{"completeness":1-5, "fun":1-5, "problems":["..."], ' + '"verdict":"pass"或"fix", "note":"一句话总评"}。' + ) diff --git a/wg1/gen-worker/worker/agent_loop/studio.py b/wg1/gen-worker/worker/agent_loop/studio.py new file mode 100644 index 00000000..e30cea0b --- /dev/null +++ b/wg1/gen-worker/worker/agent_loop/studio.py @@ -0,0 +1,349 @@ +"""agent_loop/studio.py —— W-G1 最小 agentic studio 编排(on AgentScope 进程内多 agent)。 + +闭环:设计 agent → 代码 agent → 静态校验 → 打包 → 七门真玩(确定性地板) → + [挂]→ 自修复 agent 回喂重试 ≤max_repairs;[过门]→ player panel(M3视觉+flash文本)真判 → + [有问题]→ 自修复(player 轮 ≤player_rounds,七门仍是硬地板,player 本期为顾问)。 + +复用:worker/run.py 的 scaffold/build/play/_verdict_feedback;worker/prompt.py 的 build_messages; + worker/validate.py 的 extract_code/validate;worker/_client.py 的裸客户端(player 视觉走多模态)。 +框架适配隔离于本包,AgentScope 可替换(换 LangGraph 只改本文件,不动 run/prompt/validate)。 +""" + +import argparse +import asyncio +import base64 +import json +import re +import sys +import time +from collections import defaultdict +from pathlib import Path + +# 包内/直跑兼容导入 +try: + from . import config, roles + from .. import run, prompt, validate, _client, cost +except ImportError: + sys.path.insert(0, str(Path(__file__).resolve().parents[1])) + import run, prompt, validate, _client, cost # type: ignore + from agent_loop import config, roles # type: ignore + +from agentscope.agent import Agent, ReActConfig +from agentscope.message import UserMsg + +try: + from json_repair import repair_json +except ImportError: + repair_json = None + +GEN_DIR = run.GEN_DIR +RESULTS_DIR = run.RESULTS_DIR + + +# ── 小工具 ────────────────────────────────────────────────────────── +def text_of(resp): + """从 AgentScope Msg/ChatResponse 抽纯文本(content 是 block 列表,兼容 dict/对象)。""" + blocks = getattr(resp, "content", None) + if blocks is None and hasattr(resp, "get"): + blocks = resp.get("content") + out = [] + for b in (blocks or []): + if isinstance(b, dict): + if b.get("type") == "text": + out.append(b.get("text", "") or "") + elif getattr(b, "type", None) == "text": + out.append(getattr(b, "text", "") or "") + return "".join(out) + + +def user_msg(textval): + """2.0.1:UserMsg 必须带 name;字符串 content 会被包成 TextBlock。""" + return UserMsg(name="user", content=textval) + + +def _b64_data_url(png_path): + """读 PNG → data:image/png;base64,...(缺文件返回 None)。""" + p = Path(png_path) + if not p.exists(): + return None + return "data:image/png;base64," + base64.b64encode(p.read_bytes()).decode() + + +def _extract_gatespec(design_text): + """gate-H 推广:从设计稿抽 ```gatespec JSON 块(设计 agent 自产机制门 spec → 确定性门适用任意游戏)。 + json_repair 兜脏 JSON;无块/解析失败返回 None。""" + m = re.search(r"```gatespec\s*(.+?)```", design_text or "", re.S) + if not m: + return None + raw = m.group(1).strip() + obj = None + if repair_json is not None: + try: + obj = repair_json(raw, return_objects=True) + except Exception: + obj = None + if not isinstance(obj, dict): + try: + obj = json.loads(raw) + except Exception: + obj = None + if not isinstance(obj, dict): + return None + # 轻校验:assertAfterPlay 须 list;expectLatch 缺省补 True(官方 latch 契约恒需)。 + if "assertAfterPlay" in obj and not isinstance(obj["assertAfterPlay"], list): + obj["assertAfterPlay"] = [] + obj.setdefault("expectLatch", True) + # 安全归一:paddle-intercept 的 ballPath 须是水平 x(便宜模型偶把 ball.y 当横向)→ .y 兜底改 .x。 + drv = obj.get("driver") + if isinstance(drv, dict) and drv.get("type") == "paddle-intercept": + bp = drv.get("ballPath") + if isinstance(bp, str) and bp.endswith(".y"): + drv["ballPath"] = bp[:-2] + ".x" + return obj + + +def _parse_judge(raw): + """容错解析玩家 agent 的 JSON 评判(json_repair 兜脏 JSON)。""" + obj = None + if repair_json is not None: + try: + obj = repair_json(raw, return_objects=True) + except Exception: + obj = None + if not isinstance(obj, dict): + try: + obj = json.loads(raw) + except Exception: + obj = None + if not isinstance(obj, dict): + return {"completeness": None, "fun": None, "problems": [], "verdict": "?", "note": (raw or "")[:120]} + obj.setdefault("problems", []) + if not isinstance(obj["problems"], list): + obj["problems"] = [str(obj["problems"])] + return obj + + +# ── AgentScope agent 单轮调用(生成域:design/code/fix)───────────────── +async def _agent_reply(name, system, model, user_text): + """新建一次性 Agent(空 toolkit 单轮)→ reply。返回 (文本, (in_tok,out_tok))。""" + before = len(getattr(model, "records", []) or []) + agent = Agent(name=name, system_prompt=system, model=model, + react_config=ReActConfig(max_iters=1)) + resp = await agent.reply(user_msg(user_text)) + recs = (getattr(model, "records", []) or [])[before:] + return text_of(resp), (sum(r[0] for r in recs), sum(r[1] for r in recs)) + + +# ── player panel(裸客户端:M3 视觉位 + flash 文本位)────────────────── +def _play_summary(verdict): + """把七门 verdict 摘成给玩家 agent 的运行数据文字。""" + if not verdict: + return "(无 verdict:疑似装载即崩)" + guards = verdict.get("guards") or {} + lines = [f"- 七门 {k}: {'过' if g.get('pass') else '未过'} {json.dumps(g, ensure_ascii=False)[:160]}" + for k, g in guards.items()] + return "七门真玩取证:\n" + "\n".join(lines) + + +def _judge_vision(model_name, persona, user_text, game_id): + """M3 多模态:文本 + 首帧/玩后截图 → 评判。返回 (判定dict, (in,out))。""" + client = _client.get_client() + content = [{"type": "text", "text": user_text}] + ev = GEN_DIR / game_id / "evidence" + for fn in ("first-paint.png", "after-play.png"): + url = _b64_data_url(ev / fn) + if url: + content.append({"type": "text", "text": f"【{fn}】"}) + content.append({"type": "image_url", "image_url": {"url": url}}) + msgs = [{"role": "system", "content": roles.player_system(persona)}, + {"role": "user", "content": content}] + r = client.chat.completions.create(model=model_name, messages=msgs, max_tokens=900, temperature=0.3, stream=False) + u = r.usage + return _parse_judge(r.choices[0].message.content or ""), (u.prompt_tokens, u.completion_tokens) + + +def _judge_text(model_name, persona, user_text): + """文本位:仅运行数据 → 评判(_client.chat;reasoning 档给足 max_tokens)。""" + r = _client.chat(model_name, roles.player_system(persona), user_text, max_tokens=4000, temperature=0.3) + return _parse_judge(r["content"]), (r.get("prompt_tokens") or 0, r.get("completion_tokens") or 0) + + +def run_player_panel(game_id, brief, verdict, stage): + """跑 player panel:M3 视觉位 + flash 文本位多人格。返回汇总 + 待修问题 + token。""" + summary = _play_summary(verdict) + base = (f"游戏题面:\n{brief}\n\n{summary}\n\n" + "请基于以上证据(及截图,若有)给出你的玩家评判。") + vis_model = config.model_name_for("player_vision", stage) + txt_model = config.model_name_for("player_text", stage) + panel, problems = {}, [] + tbm = defaultdict(lambda: [0, 0]) # model_name -> [in, out] + for tag, fn, mname in ( + ("vision", lambda: _judge_vision(vis_model, "急性子休闲玩家,凭第一眼观感和反馈下判断", base, game_id), + vis_model), + ("text", lambda: _judge_text(txt_model, "细致的完整度审查者,只信运行数据、不脑补", base), txt_model), + ): + try: + verdict_obj, (i, o) = fn() + tbm[mname][0] += i; tbm[mname][1] += o + panel[tag] = {"model": mname, **verdict_obj} + if str(verdict_obj.get("verdict")) == "fix": + problems += [str(p) for p in (verdict_obj.get("problems") or [])] + except Exception as e: + panel[tag] = {"model": mname, "error": str(e)[:200]} + return {"panel": panel, "problems": problems, "tokens_by_model": dict(tbm)} + + +# ── 主编排 ───────────────────────────────────────────────────────── +async def run_studio(game_id, brief, play_spec, stage="stage1", max_repairs=5, + player_rounds=1, port=4320, cdp_port=None, max_tokens=16000): + RESULTS_DIR.mkdir(parents=True, exist_ok=True) + t0 = time.perf_counter() + # 角色模型名 + 客户端(各建一次,记 usage) + design_name = config.model_name_for("design", stage) + code_name = config.model_name_for("code", stage) + fix_name = config.model_name_for("fix", stage) + design_model = config.build_model(design_name) + code_model = config.build_model(code_name) + fix_model = config.build_model(fix_name) + + attempts = [] + tin, tout = 0, 0 + per_model = defaultdict(lambda: [0, 0]) # model_name -> [in,out],per-model 成本取证 + + # ① 设计 + design_text, (di, do) = await _agent_reply("design", roles.DESIGN_SYSTEM, design_model, brief) + tin += di; tout += do; per_model[design_name][0] += di; per_model[design_name][1] += do + enriched = brief + "\n\n## 设计稿(设计 agent 产出)\n" + design_text + # gate-H 推广:设计 agent 自产 gate-spec → 合入 play_spec(覆盖 brief 默认),使确定性门适用任意游戏(不再手写 brief)。 + gatespec = _extract_gatespec(design_text) + play_spec = dict(play_spec or {}) # 拷贝,不改入参 + if gatespec: + for k in ("exportState", "driver", "controlCheck", "assertAfterPlay", "expectLatch"): + if k in gatespec and gatespec[k] is not None: + play_spec[k] = gatespec[k] + + feedback = None + passed = False + final_verdict = None + player_result = None + player_round_used = 0 + + for attempt in range(max_repairs + 1): + role = "code" if feedback is None else "fix" + model = code_model if role == "code" else fix_model + mname = code_name if role == "code" else fix_name + system, user = prompt.build_messages(enriched, retry_feedback=feedback) + rec = {"attempt": attempt, "role": role, "model": mname, "stage_fail": None} + text, (ci, co) = await _agent_reply(role, system, model, user) + tin += ci; tout += co; per_model[mname][0] += ci; per_model[mname][1] += co + rec["usage"] = {"in": ci, "out": co} + + src = validate.extract_code(text) + if not src: + rec["stage_fail"] = "extract"; attempts.append(rec) + feedback = "未能从输出中提取 ```js 代码块。请只输出一个完整的 ```js 代码块,块内是完整工厂源码。" + continue + ok, errs = validate.validate(src) + if not ok: + rec["stage_fail"] = "validate"; rec["errors"] = errs; attempts.append(rec) + feedback = "静态校验未过:\n" + "\n".join("- " + e for e in errs) + continue + run.scaffold(game_id, src, play_spec) + bok, blog = run.build(game_id) + if not bok: + rec["stage_fail"] = "build"; attempts.append(rec) + feedback = "打包失败(esbuild):\n" + blog[:600] + continue + rc, _pout, verdict = run.play(game_id, port=port, cdp_port=cdp_port) + final_verdict = verdict + seven_ok = bool(rc == 0 and verdict and verdict.get("pass")) + rec["seven_gate_pass"] = seven_ok + rec["guards"] = {k: g.get("pass") for k, g in ((verdict or {}).get("guards") or {}).items()} + if not seven_ok: + rec["stage_fail"] = "seven_gate"; attempts.append(rec) + feedback = run._verdict_feedback(verdict) + continue + + # 七门过 → player panel(顾问;七门才是硬地板) + passed = True + player_result = run_player_panel(game_id, brief, verdict, stage) + for mn, (pi, po) in player_result["tokens_by_model"].items(): + tin += pi; tout += po; per_model[mn][0] += pi; per_model[mn][1] += po + rec["player"] = player_result["panel"] + attempts.append(rec) + probs = player_result["problems"] + if probs and player_round_used < player_rounds: + player_round_used += 1 + feedback = ("七门已过,但玩家 agent 反馈以下体验问题,请修复并保持七门可过:\n" + + "\n".join("- " + p for p in probs[:8])) + continue + break + + # per-model ¥(测而不闸;复用 cost.py 的 new-api quota 口径,精确按各模型拆账) + cost_info = None + try: + pricing = cost.fetch_pricing() + qpu, usd = cost.fetch_status() + rows, total = {}, 0.0 + for name, (i, o) in per_model.items(): + c = cost.compute(name, i, o, pricing, qpu, usd) + rows[name] = {"in": i, "out": o, "rmb": c["rmb"]} + total += c["rmb"] + cost_info = {"by_model": rows, "total_rmb": round(total, 5), "gate_rmb": cost.GATE_RMB} + except Exception as e: + cost_info = {"error": str(e)[:200], + "by_model": {k: {"in": v[0], "out": v[1]} for k, v in per_model.items()}} + + result = { + "game_id": game_id, "stage": stage, "pass": passed, + "repairs": len(attempts) - 1, "player_rounds_used": player_round_used, + "design_text": design_text, + "gatespec": gatespec, # gate-H 推广:设计 agent 自产的机制门 spec(合入 play_spec 的来源) + "attempts": attempts, + "seven_gate_verdict": final_verdict, + "player": player_result["panel"] if player_result else None, + "tokens": {"prompt": tin, "completion": tout}, + "tokens_by_model": {k: v for k, v in per_model.items()}, + "cost": cost_info, + "wall_s": round(time.perf_counter() - t0, 1), + "models": {r: config.model_name_for(r, stage) for r in + ("design", "code", "fix", "player_vision", "player_text")}, + } + (RESULTS_DIR / f"{game_id}.{stage}.json").write_text( + json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8") + return result + + +def main(): + ap = argparse.ArgumentParser(description="W-G1 最小 agentic studio") + ap.add_argument("game_id") + ap.add_argument("--stage", default=None, help="models.yaml 阶段(默认 default_stage)") + ap.add_argument("--max-repairs", type=int, default=5) + ap.add_argument("--player-rounds", type=int, default=1) + ap.add_argument("--port", type=int, default=4320) + ap.add_argument("--cdp-port", type=int, default=None, help="Chrome 调试端口(默认 9222+(port-4320),并行自动错开)") + ap.add_argument("--brief", default=None) + args = ap.parse_args() + + _cfg, default_stage = config.load_config() + stage = args.stage or default_stage + cdp_port = args.cdp_port if args.cdp_port is not None else 9222 + (args.port - 4320) + brief_text, play_spec = run._load_brief(args.game_id, args.brief) + print(f"[studio] game={args.game_id} stage={stage} port={args.port} cdp={cdp_port} max_repairs={args.max_repairs}") + res = asyncio.run(run_studio(args.game_id, brief_text, play_spec, stage=stage, + max_repairs=args.max_repairs, player_rounds=args.player_rounds, + port=args.port, cdp_port=cdp_port)) + pj = res.get("player") or {} + c = res.get("cost") or {} + print(f"\n[studio] {'✅ 七门PASS' if res['pass'] else '❌ FAIL'} repairs={res['repairs']} " + f"wall={res['wall_s']}s tokens(in/out)={res['tokens']['prompt']}/{res['tokens']['completion']} " + f"¥={c.get('total_rmb','?')}(闸¥{c.get('gate_rmb','?')})") + for tag, v in pj.items(): + print(f"[player:{tag}/{v.get('model')}] 完整度={v.get('completeness')} 好玩={v.get('fun')} " + f"verdict={v.get('verdict')} note={str(v.get('note'))[:60]}") + print(f"[studio] result → wg1/gen-worker/results/{args.game_id}.{stage}.json") + sys.exit(0 if res["pass"] else 1) + + +if __name__ == "__main__": + main() diff --git a/wg1/gen-worker/worker/cost.py b/wg1/gen-worker/worker/cost.py new file mode 100644 index 00000000..eba86347 --- /dev/null +++ b/wg1/gen-worker/worker/cost.py @@ -0,0 +1,99 @@ +"""cost.py —— ¥ 成本折算(new-api quota 口径)。 + +spike 无 usage→¥ 代码(worker-reusables 地图明示),故 L1 新建。 +取证口径: + - 网关 /api/pricing 给每模型 model_ratio / completion_ratio;/api/status 给 quota_per_unit=500000、usd_exchange_rate=7.3。 + - new-api quota 公式:quota = (prompt_tokens + completion_tokens × completion_ratio) × model_ratio × group_ratio + - USD = quota / quota_per_unit;¥ = USD × usd_exchange_rate。 +【口径说明】 + - group_ratio 取默认组 1.0(/api/status 未暴露分组倍率,default 组常为 1.0;若非 1 须按实际乘)。 + - 本折算【不计 prompt 缓存折扣】(cache_ratio),因 worker 仅记 prompt_tokens/completion_tokens 不记 cache 命中数 + → 得【¥上界】(实际 logs.quota ≤ 此值)。精确 logs.quota 需网关 access token 读 /api/log/self(sk- key 无管理权)。 + - reasoning 模型(deepseek-v4-flash 等)的 reasoning_tokens 已计入 completion_tokens,本折算已含其成本。 +""" + +import json +from pathlib import Path + +# 复用 _client:导入即完成 .env 加载 + 代理旁路(NO_PROXY 并网关 host),之后 httpx 直连网关。 +try: + from . import _client +except ImportError: + import sys + sys.path.insert(0, str(Path(__file__).resolve().parent)) + import _client # type: ignore + +import httpx # _client 已设 NO_PROXY,httpx(trust_env=True) 直连网关 + +WORKER_ROOT = Path(__file__).resolve().parents[1] +RESULTS_DIR = WORKER_ROOT / "results" +GATE_RMB = 0.15 # L1 闸门 ¥/游戏 + + +def _api_base(): + # NEWAPI_BASE = http://100.64.0.8:3000(无 /v1)。 + import os + return os.environ.get("NEWAPI_BASE", "http://100.64.0.8:3000") + + +def fetch_pricing(): + """GET /api/pricing → {model_name: {model_ratio, completion_ratio, cache_ratio}}。""" + key = _client.get_api_key() + r = httpx.get(_api_base() + "/api/pricing", headers={"Authorization": "Bearer " + key}, timeout=20) + data = r.json()["data"] + return {m["model_name"]: m for m in data} + + +def fetch_status(): + """GET /api/status → (quota_per_unit, usd_exchange_rate)。""" + r = httpx.get(_api_base() + "/api/status", timeout=20) + d = r.json()["data"] + return d.get("quota_per_unit", 500000), d.get("usd_exchange_rate", 7.3) + + +def compute(model, prompt_tokens, completion_tokens, pricing, qpu, usd_rate, group_ratio=1.0): + """单条 usage → quota/USD/¥(上界,不计缓存折扣)。""" + m = pricing.get(model, {}) + model_ratio = m.get("model_ratio", 0) + completion_ratio = m.get("completion_ratio", 1) + quota = (prompt_tokens + completion_tokens * completion_ratio) * model_ratio * group_ratio + usd = quota / qpu + rmb = usd * usd_rate + return { + "model": model, "prompt_tokens": prompt_tokens, "completion_tokens": completion_tokens, + "model_ratio": model_ratio, "completion_ratio": completion_ratio, + "quota": round(quota, 2), "usd": round(usd, 6), "rmb": round(rmb, 5), + } + + +def cost_for_result(result, pricing, qpu, usd_rate): + """对一个 run 结果(含多 attempt usage)累计 ¥。""" + total_p = result["tokens"]["prompt"] + total_c = result["tokens"]["completion"] + model = result["model"] + c = compute(model, total_p, total_c, pricing, qpu, usd_rate) + c["game_id"] = result["game_id"] + c["pass"] = result["pass"] + c["retries"] = result["retries"] + return c + + +def main(): + pricing = fetch_pricing() + qpu, usd_rate = fetch_status() + rows = [] + for f in sorted(RESULTS_DIR.glob("*.json")): + result = json.loads(f.read_text(encoding="utf-8")) + rows.append(cost_for_result(result, pricing, qpu, usd_rate)) + # 控制台表。 + print(f"{'game':14} {'model':20} {'pass':5} {'retry':5} {'p_tok':>7} {'c_tok':>7} {'¥(上界)':>9} {'vs¥0.15':>8}") + for r in rows: + flag = "✅" if r["rmb"] <= GATE_RMB else "⚠️" + print(f"{r['game_id']:14} {r['model']:20} {str(r['pass']):5} {r['retries']:<5} " + f"{r['prompt_tokens']:>7} {r['completion_tokens']:>7} {r['rmb']:>9.5f} {flag:>8}") + print(f"\nquota_per_unit={qpu} usd_rate={usd_rate} group_ratio=1.0(默认) 口径=¥上界(不计缓存折扣) 闸门=¥{GATE_RMB}") + return rows + + +if __name__ == "__main__": + main() diff --git a/wg1/gen-worker/worker/models.yaml b/wg1/gen-worker/worker/models.yaml new file mode 100644 index 00000000..cb4ac54c --- /dev/null +++ b/wg1/gen-worker/worker/models.yaml @@ -0,0 +1,40 @@ +# W-G1 最小 agentic studio · 模型路由配置(spec §4) +# 模型 = per-agent 可替换旋钮:换 stage / 换某角色模型,都只改这里,不动代码。 +# 三阶段:stage1 便宜双家(flash/M2.7)先跑通 → stage2 强档(pro)出对比 → 后续逐 agent×模型 评分矩阵。 +# 视觉位恒用 MiniMax-M3(唯一实测可看图且准)。 + +default_stage: stage1 + +stages: + # Stage 1 先跑通(DeepSeek 便宜档)+ 跨家信号留 stage1_mmx 对照 + stage1: + label: "便宜·DeepSeek-flash + M3视觉" + roles: + design: deepseek-v4-flash + code: deepseek-v4-flash + fix: deepseek-v4-flash + player_text: deepseek-v4-flash + player_vision: MiniMax-M3 + _default: deepseek-v4-flash + + # Stage 1 跨家对照:文本换 MiniMax-M2.7(同款各跑一版,早拿 DeepSeek×MiniMax 对比) + stage1_mmx: + label: "便宜·MiniMax-M2.7 + M3视觉" + roles: + design: MiniMax-M2.7 + code: MiniMax-M2.7 + fix: MiniMax-M2.7 + player_text: MiniMax-M2.7 + player_vision: MiniMax-M3 + _default: MiniMax-M2.7 + + # Stage 2 出对比:强档 DeepSeek-v4-pro(文本)+ M3(视觉) + stage2: + label: "强档·DeepSeek-v4-pro + M3视觉" + roles: + design: deepseek-v4-pro + code: deepseek-v4-pro + fix: deepseek-v4-pro + player_text: deepseek-v4-pro + player_vision: MiniMax-M3 + _default: deepseek-v4-pro diff --git a/wg1/gen-worker/worker/prompt.py b/wg1/gen-worker/worker/prompt.py new file mode 100644 index 00000000..a1ae88c0 --- /dev/null +++ b/wg1/gen-worker/worker/prompt.py @@ -0,0 +1,119 @@ +"""prompt.py —— W-G1 生成上下文包:把装载契约/能力面/禁用项/硬规则蒸馏成 system prompt + few-shot。 + +来源:理解阶段 7 份地图的综合(engine-caps/load-contract/ref-shape/plugin-surface)。 +原则:把便宜模型的活压到最小——只产出一个【纯工厂模块】,能力恒经 boot.ctx,质量由 harness 六门兜。 +""" + +from pathlib import Path + +# few-shot 参照 = 已验证的 probe 工厂(games/_wg1-gen/_goldenpath-probe/factory.js)。读文件防漂移。 +_PROBE = ( + Path(__file__).resolve().parents[3] + / "game-runtime/games/_wg1-gen/_goldenpath-probe/factory.js" +) + + +def _few_shot(): + try: + return _PROBE.read_text(encoding="utf-8") + except Exception: + return "(few-shot 参照缺失)" + + +# ── 系统提示:产出靶契约 + 能力面 + 禁用项 + 硬规则(逐项来自源码亲验)── +SYSTEM = r"""你是轻量 H5 小游戏代码生成器。你的唯一产出 = 一个【独立的 GameHostFactory 模块】(原生 JS ESM 单文件)。 +宿主会把它打成 bundle 在浏览器里真玩。你不写 HTML、不写宿主、不写引擎——只写这一个工厂模块。 + +【输出格式·严格】只输出一个 ```js 代码块,块内是完整工厂源码,块外不要任何解释文字。 + +【模块形状】 +- 文件用 'use strict'; 开头。 +- 默认导出一个工厂函数:export default function createGame(opts) { ... return { init, update, render, destroy, _forensicsView }; } +- 工厂返回 GameInstance:必须有 init / update / render / destroy 四个方法(可选 onInput,但优先用 ctx.getInput()); + 另【必须】导出 _forensicsView(可测性红线,见下),harness 据此确定性判"游戏真有进展"。 + +【生命周期(宿主这样驱动你)】 +- game = createGame(opts) // opts 可能为 undefined,必须 const o = opts || {} 防御 +- await game.init(boot) // 一次性。boot = { ctx, mainContext, canvas, seed } +- game.update(dt) // 每逻辑步,dt 恒定 = 1/60 秒 +- game.render(g) // 每渲染帧,g === boot.mainContext(同一个 2D 画布上下文) +- game.destroy() // 卸载,幂等 + +【能力一律经 boot.ctx(init 里存下 ctx 再用)】 +- ctx.getEngine() -> 引擎能力 | null(可能为 null,必须容错!)。返回三个面: + · getEngine().particles.spawnEmitter(spec) -> 句柄{isActive(),stop()};引擎自动渲染粒子到画布,你无需手动画。 + spec 字段(除 pos 全可选):pos:{x,y}, count(爆发颗数), emitRate, particleTime, speed, coneAngle, + sizeStart, sizeEnd, colorStart:{r,g,b,a}(0..1), colorEnd:{r,g,b,a}, additive。坐标=逻辑像素。 + · getEngine().audio.synth.synthSfx(paramArray) -> 合成音效样本(ZzFX 参数数组,如 [1,0.05,220,,,0.18,,1.4])。 + · getEngine().math.lerp(a,b,t) / math.smoothStep(t) / math.easing?.quadOut(t)(easing 是可选,用 ?. 防御)。 +- ctx.getInput() -> { on(type, handler) -> {cancel()}, off(...) } + type ∈ 'pointerdown'|'pointermove'|'pointerup'|'keydown'|'keyup' + handler 收事件 { type, x, y, key, tMs };【x/y 已是逻辑像素坐标:x∈[0,390]、y∈[0,844],可直接当像素用做命中判定/定位,**绝对不要再乘以视口宽高**】;key 仅键盘有意义。 +- ctx.time.nowMs() / ctx.time.elapsedMs() // 受控时钟。update 首行应 const now = ctx.time.nowMs(); +- ctx.random.next() / ctx.random.range(min,max) / ctx.random.reseed(seed) // 受控随机 +- boot.mainContext 就是 render(g) 的 g —— 一个标准 CanvasRenderingContext2D,画在它上面(fillRect/arc/fillText/drawImage…)。 + +【视口】逻辑坐标系固定 390 宽 × 844 高(移动竖屏)。按逻辑像素绘制,不要自己处理 DPR。 + +【硬禁止(违反则装载/运行直接失败)】 +- 禁 import 任何引擎/外部包(不要 import 'littlejsengine',不要 import 任何东西;只写一个自包含模块)。 +- 禁 Math.random()(用 ctx.random)、禁 Date.now()/performance.now()(用 ctx.time)。 + 注意:Math.sin/cos/floor/max/min/PI 等【允许】,只有 Math.random 禁。 +- 禁 addEventListener(用 ctx.getInput().on)、禁 requestAnimationFrame(宿主驱动 update/render)。 +- 禁 new AudioContext / document / window / 直接操作全局 canvas / 直接 new 引擎对象。 +- render 只画到入参 g,不要去拿别的画布。 + +【硬规则(务必遵守)】 +1. 闭包状态(游戏对象/分数/数组/订阅句柄)在 init 内初始化,不要写在工厂函数顶层常量里。 +2. update 首行刷新 const now = ctx.time.nowMs(); 全帧用它,不要自己累加私有时钟。 +3. ctx.getEngine() 可能返回 null:所有用法都要 const eng = ctx.getEngine(); if (eng && eng.particles) {...},easing 用 ?.。 +4. destroy 里取消所有输入订阅(try { sub.cancel(); } catch(_){}),幂等。 +5. 【必须】在某个游戏事件(点击/得分/碰撞/胜负)上至少调用一次 getEngine() 的能力(粒子爆发或音效), + 这样真玩门能证明游戏真用了引擎/插件库(这是硬性验收点,别只用纯 canvas 自绘)。 +6. 画面必须每帧有可见变化(动起来),背景要铺满 390×844(别留透明,否则判白屏)。 +7. 资产容错:不要依赖外部图片;用 canvas 几何图形画(矩形/圆/路径/文字)。 + +【可测性红线 + P0 latch 终态(必须做:宿主据此判「游戏结束」代发 game_end 走结算;做不到=游戏关不上闭环=判不通过)】 +- 工厂返回的实例除 init/update/render/destroy 外,【必须】导出 _forensicsView 方法(纯只读视图,仿官方范本 generated-factory.js): + _forensicsView() { return { seed, state: () => ({ phase, score, remaining, progress, gameoverReason }) }; } +- state() 必须是【闭包实时读当前游戏状态】的函数:每次调用返回最新值,不要返回开局快照常量。 +- 【phase = 权威终态字段】取值 'booting' | 'playing' | 'gameover': + · init 后置 'playing'(可玩); + · 满足结束条件(通关 / 失败 / 超时 任一)置 'gameover'。 +- 【★ P0 latch 驻留·硬约束】一旦进入 'gameover',phase 必须【恒驻留】为 'gameover'——**禁止下一帧自动重开 / 复位回 playing**。 + 原因:宿主每 500ms 轮询 host.state().phase,读到 'gameover' 才代发 game_end 结算;若终态是「瞬时态」(某帧 gameover 下帧又变),轮询会漏读 → 游戏永远结算不了。**结束后必须停住、驻留终态(不自动重开)。** +- 其余字段(反映真实状态、与画面一致): + · score:当前分数(数字,从 0 起)。 + · remaining:剩余目标数(剩余砖块/敌人/回合/目标,数字;确无此概念可置 null)。 + · progress:0~1 进度(可选数字)。 + · gameoverReason:终态原因短串(如 'cleared_all' / 'ball_lost' / 'timeout';未结束置 '')。 + · 【题面若要求】额外导出关键实体的实时位置(如球/挡板/玩家/敌人的 {x,y}、速度 {vx,vy}、尺寸 {w,h}), + 按题面指定的字段名导出(如 ball:{x,y,vx,vy}、paddle:{x,y,w})。harness 据此【适配性真玩】(自动接球等)+ + 【确定性验手感】(控制是否跟手、碰撞是否正确);位置必须是闭包实时真值,与画面一致。 +- 红线含义:撞砖加分→score 真涨、砖被消→remaining 真减、判负/通关→phase 真切 'gameover' 且**驻留**。 + harness 会真玩到 gameover 并验【驻留 + 真有进展(remaining 下降等)】;终态瞬时/数值原地不动 = 判不通过。 + +【好玩接地(玩家 agent 反复揪的高频缺口,务必做到,否则真玩判分必低)】 +- HUD 看得到进展:除分数外,显示「剩余目标数」(剩余砖块/敌人/回合/目标),让玩家 30 秒内明确感到「在推进」;HUD 文字置顶部留白区,别和游戏元素叠字。 +- 反馈看得见:getEngine().particles.spawnEmitter 用够强参数(count≥20、sizeStart 8~14、particleTime≥0.4、colorStart 用亮色且 a=1),否则截图里看不到粒子=等于没反馈;关键事件(命中/得分/胜负)都要爆一次。 +- 必有失败态 + 胜负演出:游戏要「会输」(掉命/超时/破产任一),且胜/负时有明确画面变化或文案(别只停住不动)。 +- 节奏可上手:开局不要立刻高难或死局,前 30 秒要能上手、有正反馈、看得到分数增长。 + +下面是一个【最小但处处合规的参照实现】,请严格模仿它的结构、取能力方式、防御写法,但实现成题目要求的游戏(注意:参照件只示范「合规骨架」,你要在其上做到上面的「好玩接地」): + +```js +__FEWSHOT__ +``` +""" + + +def build_messages(brief_text, retry_feedback=None): + """组装 (system, user)。retry_feedback 在重试时把上轮失败原因回喂给模型。""" + system = SYSTEM.replace("__FEWSHOT__", _few_shot()) + user = "请实现下面这款游戏,产出一个合规的 GameHostFactory 模块(只输出一个 ```js 代码块):\n\n" + brief_text + if retry_feedback: + user += ( + "\n\n———\n上一次生成【未通过】,失败原因如下,请针对性修正后重新产出完整模块(不要只给 diff):\n" + + retry_feedback + ) + return system, user diff --git a/wg1/gen-worker/worker/run.py b/wg1/gen-worker/worker/run.py new file mode 100644 index 00000000..345dbca1 --- /dev/null +++ b/wg1/gen-worker/worker/run.py @@ -0,0 +1,188 @@ +"""run.py —— W-G1 L1 生成 worker 编排(§3 job-in/result-out 接缝)。 + +job in :brief(题面 + play-spec)+ model + max_retries +result:{ pass, retries, attempts[{usage,stage,errors}], bundle 路径, verdict 四件套, factory 路径 } + +闭环:generate → validate(静态+node --check) → scaffold+build(esbuild) → play(CDP 六门) → + 任一阶段失败即把错因回喂模型重试,≤ max_retries 次。"能生成 ≠ 能玩"——必须过 play 才算 pass。 +""" + +import json +import shutil +import subprocess +import sys +import time +from pathlib import Path + +# 包内导入(python -m worker.run)兼容直接执行。 +try: + from . import _client, prompt, validate +except ImportError: # 直接 python worker/run.py + sys.path.insert(0, str(Path(__file__).resolve().parent)) + import _client, prompt, validate # type: ignore + +REPO_ROOT = Path(__file__).resolve().parents[3] +GAME_RUNTIME = REPO_ROOT / "game-runtime" +GEN_DIR = GAME_RUNTIME / "games" / "_wg1-gen" +SHARED = GEN_DIR / "_shared" +WORKER_ROOT = Path(__file__).resolve().parents[1] +BRIEFS_DIR = WORKER_ROOT / "briefs" +RESULTS_DIR = WORKER_ROOT / "results" + + +def scaffold(game_id, factory_src, play_spec): + """落 factory.js + 拷模板(entry-bundle/index) + 写 play-spec.json。返回 game 目录。""" + gdir = GEN_DIR / game_id + gdir.mkdir(parents=True, exist_ok=True) + # 官方靶名 generated-factory.js(entry-bundle 壳 import './generated-factory.js')。 + (gdir / "generated-factory.js").write_text(factory_src, encoding="utf-8") + shutil.copyfile(SHARED / "entry-bundle.template.js", gdir / "entry-bundle.js") + shutil.copyfile(SHARED / "index.template.html", gdir / "index.html") + (gdir / "play-spec.json").write_text(json.dumps(play_spec, ensure_ascii=False, indent=2), encoding="utf-8") + return gdir + + +def build(game_id): + """esbuild 打 __GameBundle iife。返回 (ok, log)。""" + rel = f"games/_wg1-gen/{game_id}" + r = subprocess.run( + ["node", "scripts/build.mjs", f"{rel}/entry-bundle.js", f"{rel}/bundle.iife.js", "--global-name=__GameBundle"], + cwd=str(GAME_RUNTIME), capture_output=True, text=True, timeout=120, + ) + ok = r.returncode == 0 + return ok, (r.stdout + r.stderr).strip() + + +def play(game_id, port=4320, cdp_port=None): + """CDP 真玩七门。返回 (rc, stdout, verdict_dict|None)。 + cdp_port 独立可传 → 多 run 并行时各占独立 Chrome 调试端口(serve-and-play.sh 第三参),互不撞。""" + args = ["bash", "games/_wg1-gen/_shared/serve-and-play.sh", game_id, str(port)] + if cdp_port is not None: + args.append(str(cdp_port)) + r = subprocess.run( + args, cwd=str(GAME_RUNTIME), capture_output=True, text=True, timeout=180, + ) + verdict = None + vpath = GEN_DIR / game_id / "evidence" / "verdict.json" + if vpath.exists(): + try: + verdict = json.loads(vpath.read_text(encoding="utf-8")) + except Exception: + pass + return r.returncode, (r.stdout + r.stderr).strip(), verdict + + +def _verdict_feedback(verdict): + """把失败的守卫摘成给模型的回喂文字。""" + if not verdict: + return "真玩阶段无 verdict 产出(疑似装载即崩/超时)。" + lines = [] + for k, g in (verdict.get("guards") or {}).items(): + if not g.get("pass"): + lines.append(f"- 守卫 {k} 未过:{json.dumps(g, ensure_ascii=False)[:200]}") + if verdict.get("error"): + lines.append("- 运行错误:" + str(verdict["error"])[:300]) + return "真玩未过:\n" + "\n".join(lines) if lines else "真玩未过(原因未知)。" + + +def run_job(game_id, brief_text, play_spec, model, max_retries=2, port=4320, max_tokens=16000): + """单 job 闭环。返回 result dict。""" + RESULTS_DIR.mkdir(parents=True, exist_ok=True) + attempts = [] + feedback = None + passed = False + final_verdict = None + gdir = GEN_DIR / game_id + + for attempt in range(max_retries + 1): + rec = {"attempt": attempt, "stage": None, "errors": [], "usage": None} + # ① 生成 + system, user = prompt.build_messages(brief_text, retry_feedback=feedback) + try: + resp = _client.chat(model, system, user, max_tokens=max_tokens) + except Exception as e: + rec["stage"] = "generate"; rec["errors"] = [f"模型调用失败:{e}"] + attempts.append(rec); feedback = str(e); continue + rec["usage"] = {k: resp[k] for k in ("prompt_tokens", "completion_tokens", "total_tokens", "wall_s", "id", "finish_reason")} + src = validate.extract_code(resp["content"]) + + # ② 静态 + 语法校验 + ok, errs = validate.validate(src) + if not ok: + rec["stage"] = "validate"; rec["errors"] = errs + attempts.append(rec) + feedback = "校验未过:\n" + "\n".join("- " + e for e in errs) + continue + + # ③ 落盘 + 打包 + scaffold(game_id, src, play_spec) + bok, blog = build(game_id) + if not bok: + rec["stage"] = "build"; rec["errors"] = [blog[:600]] + attempts.append(rec) + feedback = "打包失败(esbuild):\n" + blog[:600] + continue + + # ④ 真玩 + rc, pout, verdict = play(game_id, port=port) + final_verdict = verdict + rec["stage"] = "play" + rec["play_pass"] = (rc == 0 and verdict and verdict.get("pass")) + rec["verdict_guards"] = {k: g.get("pass") for k, g in ((verdict or {}).get("guards") or {}).items()} + attempts.append(rec) + if rc == 0 and verdict and verdict.get("pass"): + passed = True + break + feedback = _verdict_feedback(verdict) + + result = { + "game_id": game_id, + "model": model, + "pass": passed, + "retries": len(attempts) - 1, + "attempts": attempts, + "factory_path": str((gdir / "generated-factory.js").relative_to(REPO_ROOT)) if (gdir / "generated-factory.js").exists() else None, + "bundle_path": str((gdir / "bundle.iife.js").relative_to(REPO_ROOT)) if (gdir / "bundle.iife.js").exists() else None, + "verdict": final_verdict, + # 成本:累计 token(¥ 折算由 cost.py 经 new-api logs.quota 后填)。 + "tokens": { + "prompt": sum((a.get("usage") or {}).get("prompt_tokens", 0) or 0 for a in attempts), + "completion": sum((a.get("usage") or {}).get("completion_tokens", 0) or 0 for a in attempts), + }, + "request_ids": [(a.get("usage") or {}).get("id") for a in attempts if (a.get("usage") or {}).get("id")], + } + (RESULTS_DIR / f"{game_id}.json").write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8") + return result + + +def _load_brief(game_id, brief_path=None): + p = Path(brief_path) if brief_path else (BRIEFS_DIR / f"{game_id}.json") + data = json.loads(p.read_text(encoding="utf-8")) + return data["brief"], data.get("play_spec", {"inputs": [], "expectedEngineCallPrefixes": []}) + + +def main(): + import argparse + ap = argparse.ArgumentParser(description="W-G1 L1 生成 worker") + ap.add_argument("game_id") + ap.add_argument("--model", default=_client.DEFAULT_MODEL) + ap.add_argument("--max-retries", type=int, default=2) + ap.add_argument("--brief", default=None) + ap.add_argument("--port", type=int, default=4320) + ap.add_argument("--max-tokens", type=int, default=16000) + args = ap.parse_args() + + brief_text, play_spec = _load_brief(args.game_id, args.brief) + print(f"[run] game={args.game_id} model={args.model} max_retries={args.max_retries}") + t0 = time.perf_counter() + res = run_job(args.game_id, brief_text, play_spec, args.model, + max_retries=args.max_retries, port=args.port, max_tokens=args.max_tokens) + dt = time.perf_counter() - t0 + print(f"\n[run] {'✅ PASS' if res['pass'] else '❌ FAIL'} retries={res['retries']} " + f"tokens(prompt/completion)={res['tokens']['prompt']}/{res['tokens']['completion']} wall={dt:.1f}s") + print(f"[run] result → wg1/gen-worker/results/{args.game_id}.json") + sys.exit(0 if res["pass"] else 1) + + +if __name__ == "__main__": + main() diff --git a/wg1/gen-worker/worker/validate.py b/wg1/gen-worker/worker/validate.py new file mode 100644 index 00000000..f33c42fa --- /dev/null +++ b/wg1/gen-worker/worker/validate.py @@ -0,0 +1,111 @@ +"""validate.py —— L1 校验闸门:从模型输出抽源码 + 静态契约检查 + node --check 语法门。 + +spike 无此模块(gate3 只算 token),故 L1 新建(worker-reusables 地图明示)。 +两层:① 静态契约扫描(默认导出/五方法/禁用词)——快、拦低级违约;② node --check ESM 语法——拦编译失败。 +""" + +import re +import subprocess +import tempfile +import os + + +def extract_code(content): + """从模型输出抽出 ```js 代码块;无 fence 则退而取最长 ``` 块;再无则用全文。""" + if not content: + return "" + # 优先 ```js / ```javascript + m = re.search(r"```(?:js|javascript)\s*\n(.*?)```", content, re.S | re.I) + if m: + return m.group(1).strip() + # 任意 ``` 块(取第一个) + m = re.search(r"```\s*\n(.*?)```", content, re.S) + if m: + return m.group(1).strip() + # 无 fence:若看着像代码(含 export default)直接用全文 + if "export default" in content: + return content.strip() + return "" + + +def _strip_comments(src): + """去行注释/块注释,避免禁用词扫描被注释里的字样误伤。""" + src = re.sub(r"/\*.*?\*/", "", src, flags=re.S) + src = re.sub(r"//[^\n]*", "", src) + return src + + +# 禁用模式(正则, 说明)——违反即【契约违约】,拦在打包前。 +_FORBIDDEN = [ + (r"(^|\n)\s*import\s", "禁 import:工厂必须自包含单文件(含禁 import littlejsengine)"), + (r"\bimport\s*\(", "禁动态 import()"), + (r"\brequire\s*\(", "禁 require"), + (r"littlejsengine", "禁引擎名字空间"), + (r"\bMath\.random\b", "禁 Math.random(用 ctx.random)"), + (r"\bDate\.now\b", "禁 Date.now(用 ctx.time.nowMs)"), + (r"\bperformance\.now\b", "禁 performance.now(用 ctx.time)"), + (r"\baddEventListener\b", "禁 addEventListener(用 ctx.getInput().on)"), + (r"\brequestAnimationFrame\b", "禁 requestAnimationFrame(宿主驱动)"), + (r"new\s+AudioContext", "禁 new AudioContext(用 ctx.getAudioContext)"), + (r"\bdocument\s*\.", "禁直接操作 document"), + (r"\bwindow\s*\.", "禁直接操作 window"), +] + + +def static_check(src): + """静态契约检查。返回 (ok, errors[])。""" + errors = [] + if not src or len(src.strip()) < 60: + return False, ["源码为空或过短(疑似未产出有效代码)"] + if "export default" not in src: + errors.append("缺少 export default(必须默认导出工厂函数)") + scan = _strip_comments(src) + # 五方法存在性(宽松:方法名作为标识符出现)。 + for meth in ("init", "update", "render", "destroy"): + if not re.search(r"\b" + meth + r"\b", scan): + errors.append(f"缺少 {meth} 方法") + # 必须经 boot.ctx 取能力(至少出现 ctx. 用法)。 + if "ctx" not in scan: + errors.append("未见 ctx 用法(能力须经 boot.ctx)") + # 必须至少用一次 getEngine(硬性验收点:真接线门要有信号)。 + if "getEngine" not in scan: + errors.append("未调用 getEngine()(必须在某事件上用一次引擎能力,否则真接线门无信号)") + # 禁用词扫描。 + for pat, desc in _FORBIDDEN: + if re.search(pat, scan): + errors.append("违禁:" + desc) + return (len(errors) == 0), errors + + +def node_syntax_check(src): + """node --check ESM 语法门(拦编译失败)。返回 (ok, stderr)。""" + tmp = tempfile.NamedTemporaryFile("w", suffix=".mjs", delete=False, encoding="utf-8") + try: + tmp.write(src) + tmp.close() + r = subprocess.run( + ["node", "--check", tmp.name], + capture_output=True, text=True, timeout=30, + ) + if r.returncode == 0: + return True, "" + # 清理临时路径噪声,只留错因。 + return False, (r.stderr or r.stdout or "node --check 失败").strip() + except Exception as e: + return False, f"node --check 异常:{e}" + finally: + try: + os.unlink(tmp.name) + except Exception: + pass + + +def validate(src): + """综合校验门。返回 (ok, errors[])。静态过了才跑 node --check(省时)。""" + ok, errors = static_check(src) + if not ok: + return False, errors + ok2, stderr = node_syntax_check(src) + if not ok2: + return False, ["语法错误(node --check):" + stderr[:500]] + return True, []