[P3][T22] 新增 loot.html + src/loot.ts:掉落模拟器 / 概率表双 Tab #110

Closed
opened 2026-09-18 10:50:54 +00:00 by troytt · 1 comment
Owner

问题

TC 树有 852 个节点 + 100 个虚拟节点,展开后的概率靠人眼是算不明白的。需要一个工具页:

  1. 开发时验证 T-13 / T-14 的实现对不对
  2. 玩家侧查「这东西从哪掉、概率多少」

设计

沿用 arena.html + src/arena.ts 的既有模式(M9 战斗测试台),同一套暗金配色。在 vite.config.ts 的 rollupOptions.input 里加一个 loot 入口(现有 5 个:index / walk / net / acts / arena)。

              ┌─ 输入 ─────────────────────────┐
              │ 怪物 / TC 名                    │
              │ 难度 · 区域等级                 │
              │ 队伍人数 · MF                   │
              └───────────┬────────────────────┘
                          │
           ┌──────────────┴──────────────┐
           ▼                             ▼
  ┌─ Tab 1 · 蒙特卡洛模拟器 ─┐  ┌─ Tab 2 · 精确概率表 ──┐
  │ 跑 N 次真实掉落流程       │  │ 解析式展开 TC 树       │
  │   ↓                      │  │   ↓                    │
  │ 掉落物列表                │  │ 叶子物品 × 精确概率     │
  │ 品质分布直方图            │  │ 反查:某物品从哪些怪掉  │
  │ 稀有物品期望次数          │  │                        │
  └──────────────────────────┘  └────────────────────────┘

Tab 1 · 模拟器

选怪物 / 难度 / 区域等级 / 队伍人数 / MF,跑 N 次(1k ~ 1M)真实掉落流程(走 T-13 → T-14 → T-24 → T-15 的完整链路),输出:

  • 掉落物清单(按品质着色)
  • 品质分布直方图(normal / superior / magic / rare / set / unique)
  • 稀有物品的期望次数与实际次数

Tab 2 · 概率表

同样的输入,但不掷骰子 —— 解析式地展开 TC 树,算出每个叶子物品的精确概率。

支持反查:给定物品(如 Shako / uap),列出所有能掉它的 TC 与概率。

实现要求

  1. 新建 loot.html + src/loot.ts,在 vite.config.ts 注册入口。
  2. Tab 1 复用生产代码路径(不要另写一份简化版,否则失去验证意义)。
  3. Tab 2 实现解析式展开:递归下降累乘概率,遇到 Picks<0 按确定性枚举处理。
  4. 大样本模拟要能中断 / 显示进度,不能卡死 UI(建议 Web Worker 或分帧)。
  5. 反查功能需要先建「物品 → [TC, 概率]」的倒排索引。

陷阱

[!IMPORTANT]
两个 Tab 必须互为验证 —— 蒙特卡洛的收敛值必须落在解析概率的置信区间内。这是 T-13 / T-14 最强的回归测试,建议在 T-21 里加一条自动断言,而不只是人眼看。

[!CAUTION]
Tab 2 的解析展开遇到 Picks > 1 时,「至少掉一次 X 的概率」不等于「单次概率 × Picks」。要正确处理独立重复抽样的概率合成(1 - (1-p)^picks),否则概率会算超��� 1。

[!WARNING]
Picks < 0 的节点是确定性的,概率恒为 1(掉 ProbN 次)。不要套用随机分支的公式。

[!NOTE]
模拟器用固定 seed 时应可复现 —— 这对 debug 很重要。UI 上给个「seed」输入框。

验收标准

  • loot.html 入口注册成功,npm run build 产出该页
  • Tab 1 能跑 1k ~ 1M 次模拟,UI 不卡死,可中断
  • Tab 2 的解析概率与手算一致(用 Act 1 H2H A 的概率树验证)
  • 两个 Tab 对同一输入的结果落在置信区间内(选「Act 1 H2H A / 噩梦 / 1 人 / 0 MF」人工确认)
  • 反查功能:输入 Shako 能列出所有来源 TC 与概率
  • Picks > 1 的概率合成正确(不会出现 > 1 的概率)
  • 固定 seed 可复现
  • npm run typecheck 0 error
  • npx vitest run 全绿
  • npx tsx scripts/verify-items.ts 新增断言通过

溯源

参考 arena.html + src/arena.ts(M9 战斗测试台)为模板;概率数据来自 T-13 / T-14 的实现
本 issue 结论强度 工具页,无金标准约束;但其输出必须与 T-13/T-14 的金标准实现一致

[!WARNING]
D2MOO 是 1.10f,不是本项目的金标准。 它只能作线索使用。任何涉及常量、列序、整数截断位置或 RNG 消耗次数的结论,都必须回到 1.13c 的表格或 DLL 复核后再落地。

## 问题 TC 树有 852 个节点 + 100 个虚拟节点,展开后的概率靠人眼是算不明白的。需要一个工具页: 1. **开发时**验证 T-13 / T-14 的实现对不对 2. **玩家侧**查「这东西从哪掉、概率多少」 ## 设计 沿用 [`arena.html`](https://git.projectdiablo2.cn/troytt/diablo2-web/src/branch/main/arena.html) + `src/arena.ts` 的既有模式(M9 战斗测试台),同一套暗金配色。在 [`vite.config.ts`](https://git.projectdiablo2.cn/troytt/diablo2-web/src/branch/main/vite.config.ts) 的 `rollupOptions.input` 里加一个 `loot` 入口(现有 5 个:`index / walk / net / acts / arena`)。 ``` ┌─ 输入 ─────────────────────────┐ │ 怪物 / TC 名 │ │ 难度 · 区域等级 │ │ 队伍人数 · MF │ └───────────┬────────────────────┘ │ ┌──────────────┴──────────────┐ ▼ ▼ ┌─ Tab 1 · 蒙特卡洛模拟器 ─┐ ┌─ Tab 2 · 精确概率表 ──┐ │ 跑 N 次真实掉落流程 │ │ 解析式展开 TC 树 │ │ ↓ │ │ ↓ │ │ 掉落物列表 │ │ 叶子物品 × 精确概率 │ │ 品质分布直方图 │ │ 反查:某物品从哪些怪掉 │ │ 稀有物品期望次数 │ │ │ └──────────────────────────┘ └────────────────────────┘ ``` ### Tab 1 · 模拟器 选怪物 / 难度 / 区域等级 / 队伍人数 / MF,跑 N 次(1k ~ 1M)**真实掉落流程**(走 T-13 → T-14 → T-24 → T-15 的完整链路),输出: - 掉落物清单(按品质着色) - 品质分布直方图(normal / superior / magic / rare / set / unique) - 稀有物品的期望次数与实际次数 ### Tab 2 · 概率表 同样的输入,但**不掷骰子** —— 解析式地展开 TC 树,算出每个叶子物品的精确概率。 支持**反查**:给定物品(如 Shako / `uap`),列出所有能掉它的 TC 与概率。 ## 实现要求 1. 新建 `loot.html` + `src/loot.ts`,在 `vite.config.ts` 注册入口。 2. Tab 1 复用生产代码路径(**不要另写一份简化版**,否则失去验证意义)。 3. Tab 2 实现解析式展开:递归下降累乘概率,遇到 `Picks<0` 按确定性枚举处理。 4. 大样本模拟要能中断 / 显示进度,不能卡死 UI(建议 Web Worker 或分帧)。 5. 反查功能需要先建「物品 → [TC, 概率]」的倒排索引。 ## 陷阱 > [!IMPORTANT] > **两个 Tab 必须互为验证** —— 蒙特卡洛的收敛值必须落在解析概率的置信区间内。这是 T-13 / T-14 最强的回归测试,**建议在 T-21 里加一条自动断言**,而不只是人眼看。 > [!CAUTION] > Tab 2 的解析展开遇到 `Picks > 1` 时,「至少掉一次 X 的概率」不等于「单次概率 × Picks」。要正确处理独立重复抽样的概率合成(`1 - (1-p)^picks`),否则概率会算超��� 1。 > [!WARNING] > `Picks < 0` 的节点是**确定性**的,概率恒为 1(掉 `ProbN` 次)。不要套用随机分支的公式。 > [!NOTE] > 模拟器用固定 seed 时应可复现 —— 这对 debug 很重要。UI 上给个「seed」输入框。 ## 验收标准 - [ ] `loot.html` 入口注册成功,`npm run build` 产出该页 - [ ] Tab 1 能跑 1k ~ 1M 次模拟,UI 不卡死,可中断 - [ ] Tab 2 的解析概率与手算一致(用 `Act 1 H2H A` 的概率树验证) - [ ] 两个 Tab 对同一输入的结果落在置信区间内(选「Act 1 H2H A / 噩梦 / 1 人 / 0 MF」人工确认) - [ ] 反查功能:输入 Shako 能列出所有来源 TC 与概率 - [ ] `Picks > 1` 的概率合成正确(不会出现 > 1 的概率) - [ ] 固定 seed 可复现 - [ ] `npm run typecheck` 0 error - [ ] `npx vitest run` 全绿 - [ ] `npx tsx scripts/verify-items.ts` 新增断言通过 --- ### 溯源 | | | |---|---| | 参考 | `arena.html` + `src/arena.ts`(M9 战斗测试台)为模板;概率数据来自 T-13 / T-14 的实现 | | 本 issue 结论强度 | 工具页,无金标准约束;但其输出**必须与 T-13/T-14 的金标准实现一致** | > [!WARNING] > **D2MOO 是 1.10f,不是本项目的金标准。** 它只能作线索使用。任何涉及常量、列序、整数截断位置或 RNG 消耗次数的结论,都必须回到 1.13c 的表格或 DLL 复核后再落地。
troytt added this to the [M10] 真实物品系统:500 基础物品、1000 词缀、TreasureClassEx 掉落树 milestone 2026-09-18 10:50:54 +00:00
Author
Owner

已完成 loot.html + src/loot.ts:蒙特卡洛掉落模拟器(分帧运行/品质直方图/掉落明细)与解析式精确概率表(独立抽样合成/反查物品出处),以及 vite.config.ts 入口集成,合并入 main (commit 6a85c96)。

已完成 loot.html + src/loot.ts:蒙特卡洛掉落模拟器(分帧运行/品质直方图/掉落明细)与解析式精确概率表(独立抽样合成/反查物品出处),以及 vite.config.ts 入口集成,合并入 main (commit 6a85c96)。
Sign in to join this conversation.
No Label
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: troytt/diablo2-web#110
No description provided.