[P2][T1-1/T1-2] 还原边界顶点链表与格子级土路算法,替换 Catmull-Rom 样条 #82

Closed
opened 2026-09-18 09:47:28 +00:00 by troytt · 2 comments
Owner

问题

仓库用 Catmull-Rom 样条画土路,原版用的是格子级的确定性路径系统。
两者目的、输出、RNG 消耗全不同。而且仓库版本在原版不消耗随机数的地方消耗了随机数,
会让同 seed 的后续所有 pass 错位。

T1-1:DRLGVER_CreateVertices 名实不符

原版(DrlgDrlgVer.cpp:15-226,约 210 行) 仓库 createDrlgVertices(wilderness.ts ≈3150-3352)
目的 关卡包围盒的闭合环形顶点链表(恰好 4 个角点) Catmull-Rom 样条土路
做法 先 --nWidth/--nHeight,建 4 角环链;再遍历 pDrlgRoomData orth 列表,对每个连接方向(case 0..3 决定挂哪个角点、插入点在 X 还是 Y 上变化)在该边上插入 1-2 个顶点,位置取连接跨度端点 v15/v16,用符号归一化比较 nSign * v16 > nSign * v21 做保护 从 anchor 到中心 hub 采样样条
标志位 插入顶点 dwFlags |= 1(连接);若 pCurrentRoomData->bPreset 再 |= 2 无
坐标 最后整体减去关卡原点,转为相对坐标 画布绝对坐标
RNG 0 次 rng.int(-1,1) ×2(拐点/每 3 格)+ rng.int(-2,2)(直线段偏移)

wilderness.ts:3354 的 export const DRLGVER_CreateVertices = createDrlgVertices
与 wilderness.ts:1651 的 UNIMPLEMENTED_PASSES 自相矛盾——后者才是诚实的。

T1-2:真正的土路算法完全缺失

DRLGOUTDOORS_CalculatePathCoordinates(DrlgOutdoors.cpp:1139-1168)——把顶点吸附到 8 格网格:

pVertex2->nPosX = pVertex1->nPosX - pLevel->nPosX;
pVertex2->nPosY = pVertex1->nPosY - pLevel->nPosY;
switch (pVertex1->nDirection) {
case ALTDIR_WEST:  pVertex2->nPosX = 8 * (pVertex2->nPosX / 8) + 11; break;
case ALTDIR_NORTH: pVertex2->nPosY = 8 * (pVertex2->nPosY / 8) + 11; break;
case ALTDIR_EAST:  pVertex2->nPosX = 8 * (pVertex2->nPosX / 8) -  5; break;
case ALTDIR_SOUTH: pVertex2->nPosY = 8 * (pVertex2->nPosY / 8) -  5; break;
}
pVertex2->nPosX += pLevel->nPosX;
pVertex2->nPosY += pLevel->nPosY;

中心 hub 的求法(sub_6FD7F5B0,DrlgOutdoors.cpp:1171-1278)同样全程确定性:

if (pOutdoors->dwFlags & 0x10) and DRLGOUTWILD_GetBridgeCoords() 给出有效 (nX,nY):
    # 有桥:强制锚定到桥
    nPosX = pLevel->nPosX + 8*nX + 3
    nPosY = pLevel->nPosY + 8*nY + 3
    对每个顶点 i:pVertices[18+i].nPosY = nPosY
        若 pVertices[i].nPosX <= nPosX: nPosX,  nDirection = 2
        否则                          : nPosX+8, nDirection = 0
else:
    若 nVertices == 1:
        hub = (nGridWidth/2, nGridHeight/2)
    否则:
        # 所有顶点相对坐标求和,再除以 (8 * nVertices)
        hub = (Σ(pVertices[j].nPosX - pLevel->nPosX) / (8*nVertices),
               Σ(pVertices[j].nPosY - pLevel->nPosY) / (8*nVertices))

    # 螺旋外扩找合法格:半径 j = 0..7,四方向
    nXOffsets = {-1, 0,  0, 1}
    nYOffsets = { 0, 1, -1, 0}
    for j in 0..7:
      for k in 0..3:
        nX, nY = hub.x + j*nXOffsets[k], hub.y + j*nYOffsets[k]
        if 在界内 and DRLGOUTDOORS_TestGridCellSpawnValid(nX, nY): 命中,跳出

    pVertices[18].nPosX = pLevel->nPosX + 8*nX + 3
    pVertices[18].nPosY = pLevel->nPosY + 8*nY + 3
    pVertices[18].nDirection = 4
    # i > 0 的顶点全部复制 pVertices[18] 的坐标,nDirection = 4

最后对每个顶点:CalculatePathCoordinates(&pVertices[18+i], &pVertices[12+i])

顶点数组分段布局(务必照搬):[0..5] 边界顶点、[6..11] 其路径坐标、
[12..17] hub 的路径坐标、[18..23] hub 顶点。

全程 0 次 RNG。

前置依赖

本 issue 需要 8×8 格子网格抽象(pGrid[1] / pGrid[2] 的等价物)以及
TestGridCellSpawnValid(1.13c 内联为 test [grid], 0x1b81)。
这与 P1 的航路点 issue 是同一套基础设施,建议两者由同一人或同一批次完成,先做 P1 建立基础。

修改方案

  1. 建立/复用 8×8 格子网格与 TestGridCellSpawnValid。
  2. 实现 DRLGVER_CreateVertices 的真实语义(4 角环链 + 按 orth 连接插点 + 转相对坐标),
    不消耗 RNG。同时把它从 UNIMPLEMENTED_PASSES 移除。
  3. 实现 DRLGOUTDOORS_CalculatePathCoordinates 与 hub 求解(含桥的分支)。
  4. 删除 Catmull-Rom 样条土路(sampleCatmullRomSpline 及其随机抖动)。
  5. 现有 createDrlgVertices 若仍被渲染层依赖,先拆分:
    保留渲染所需的多段线生成,但其输入改为原版算法产出的顶点,且不得再引入随机。

[!CAUTION]
这一步会改变几乎所有荒野关卡的字节级输出,verify-packs 的 1671 项基线会大面积变化。
请在 PR 里明确说明:哪些基线变化是预期的、依据是什么。
不要为了保住基线而妥协算法正确性;也不要在没有说明的情况下批量刷新基线。

验收标准

  • DRLGVER_CreateVertices 产出 4 角环链 + 连接插点,dwFlags 位语义正确,0 次 RNG
  • DRLGOUTDOORS_CalculatePathCoordinates 的 +11 / -5 吸附与 8*(x/8) 整除语义一致
    (注意 C 的整数除法对负数是向零取整,JS 的 Math.floor 不是,必须用 Math.trunc)
  • hub 求解覆盖三种情况:有桥、单顶点、多顶点均值 + 螺旋外扩
  • sampleCatmullRomSpline 及其随机抖动已从土路路径中移除
  • DRLGVER_CreateVertices 从 UNIMPLEMENTED_PASSES 移除
  • typecheck 0 error / vitest 全绿
  • verify-packs 基线变化已逐项说明并经评审

溯源

审计报告 113c-divergence-audit.md(条目编号与本 issue 标题中的 T 编号对应)
黄金标准 1.13c D2Common.dll,PE 时间戳 0x4B95C439 = 2010-03-09,ImageBase 0x6FD50000
可读代理 D2MOO 源码为 1.10f,非 1.13c。已通过「6/6 常量表命中 + 两个函数反汇编控制流比对」验证其 DRLG 部分与 1.13c 一致,详见报告开头「代理有效性验证」

[!WARNING]
引用 D2MOO 行号时请注意它是 1.10f。涉及 RNG 消耗次数或精确常量的改动,必须回到 1.13c 二进制复核
(工具:scratch/probe_113c_drlg.py、scratch/xref.py、scratch/findbytes.py + objdump)。

## 问题 仓库用 **Catmull-Rom 样条**画土路,原版用的是**格子级的确定性路径系统**。 两者目的、输出、RNG 消耗全不同。而且仓库版本**在原版不消耗随机数的地方消耗了随机数**, 会让同 seed 的后续所有 pass 错位。 ## T1-1:`DRLGVER_CreateVertices` 名实不符 | | 原版(`DrlgDrlgVer.cpp:15-226`,约 210 行) | 仓库 `createDrlgVertices`(`wilderness.ts` ≈3150-3352) | |---|---|---| | 目的 | 关卡包围盒的**闭合环形顶点链表**(恰好 4 个角点) | Catmull-Rom 样条土路 | | 做法 | 先 `--nWidth/--nHeight`,建 4 角环链;再遍历 `pDrlgRoomData` orth 列表,对每个连接方向(`case 0..3` 决定挂哪个角点、插入点在 X 还是 Y 上变化)在该边上插入 1-2 个顶点,位置取连接跨度端点 `v15`/`v16`,用符号归一化比较 `nSign * v16 > nSign * v21` 做保护 | 从 anchor 到中心 hub 采样样条 | | 标志位 | 插入顶点 `dwFlags \|= 1`(连接);若 `pCurrentRoomData->bPreset` 再 `\|= 2` | 无 | | 坐标 | 最后整体减去关卡原点,转为相对坐标 | 画布绝对坐标 | | RNG | **0 次** | `rng.int(-1,1)` ×2(拐点/每 3 格)+ `rng.int(-2,2)`(直线段偏移) | `wilderness.ts:3354` 的 `export const DRLGVER_CreateVertices = createDrlgVertices` 与 `wilderness.ts:1651` 的 `UNIMPLEMENTED_PASSES` 自相矛盾——**后者才是诚实的**。 ## T1-2:真正的土路算法完全缺失 `DRLGOUTDOORS_CalculatePathCoordinates`(`DrlgOutdoors.cpp:1139-1168`)——把顶点吸附到 8 格网格: ```c pVertex2->nPosX = pVertex1->nPosX - pLevel->nPosX; pVertex2->nPosY = pVertex1->nPosY - pLevel->nPosY; switch (pVertex1->nDirection) { case ALTDIR_WEST: pVertex2->nPosX = 8 * (pVertex2->nPosX / 8) + 11; break; case ALTDIR_NORTH: pVertex2->nPosY = 8 * (pVertex2->nPosY / 8) + 11; break; case ALTDIR_EAST: pVertex2->nPosX = 8 * (pVertex2->nPosX / 8) - 5; break; case ALTDIR_SOUTH: pVertex2->nPosY = 8 * (pVertex2->nPosY / 8) - 5; break; } pVertex2->nPosX += pLevel->nPosX; pVertex2->nPosY += pLevel->nPosY; ``` 中心 hub 的求法(`sub_6FD7F5B0`,`DrlgOutdoors.cpp:1171-1278`)同样全程确定性: ``` if (pOutdoors->dwFlags & 0x10) and DRLGOUTWILD_GetBridgeCoords() 给出有效 (nX,nY): # 有桥:强制锚定到桥 nPosX = pLevel->nPosX + 8*nX + 3 nPosY = pLevel->nPosY + 8*nY + 3 对每个顶点 i:pVertices[18+i].nPosY = nPosY 若 pVertices[i].nPosX <= nPosX: nPosX, nDirection = 2 否则 : nPosX+8, nDirection = 0 else: 若 nVertices == 1: hub = (nGridWidth/2, nGridHeight/2) 否则: # 所有顶点相对坐标求和,再除以 (8 * nVertices) hub = (Σ(pVertices[j].nPosX - pLevel->nPosX) / (8*nVertices), Σ(pVertices[j].nPosY - pLevel->nPosY) / (8*nVertices)) # 螺旋外扩找合法格:半径 j = 0..7,四方向 nXOffsets = {-1, 0, 0, 1} nYOffsets = { 0, 1, -1, 0} for j in 0..7: for k in 0..3: nX, nY = hub.x + j*nXOffsets[k], hub.y + j*nYOffsets[k] if 在界内 and DRLGOUTDOORS_TestGridCellSpawnValid(nX, nY): 命中,跳出 pVertices[18].nPosX = pLevel->nPosX + 8*nX + 3 pVertices[18].nPosY = pLevel->nPosY + 8*nY + 3 pVertices[18].nDirection = 4 # i > 0 的顶点全部复制 pVertices[18] 的坐标,nDirection = 4 最后对每个顶点:CalculatePathCoordinates(&pVertices[18+i], &pVertices[12+i]) ``` 顶点数组分段布局(务必照搬):`[0..5]` 边界顶点、`[6..11]` 其路径坐标、 `[12..17]` hub 的路径坐标、`[18..23]` hub 顶点。 **全程 0 次 RNG。** ## 前置依赖 本 issue 需要 **8×8 格子网格抽象**(`pGrid[1]` / `pGrid[2]` 的等价物)以及 `TestGridCellSpawnValid`(1.13c 内联为 `test [grid], 0x1b81`)。 这与 P1 的航路点 issue 是同一套基础设施,**建议两者由同一人或同一批次完成**,先做 P1 建立基础。 ## 修改方案 1. 建立/复用 8×8 格子网格与 `TestGridCellSpawnValid`。 2. 实现 `DRLGVER_CreateVertices` 的真实语义(4 角环链 + 按 orth 连接插点 + 转相对坐标), **不消耗 RNG**。同时把它从 `UNIMPLEMENTED_PASSES` 移除。 3. 实现 `DRLGOUTDOORS_CalculatePathCoordinates` 与 hub 求解(含桥的分支)。 4. **删除** Catmull-Rom 样条土路(`sampleCatmullRomSpline` 及其随机抖动)。 5. 现有 `createDrlgVertices` 若仍被渲染层依赖,先拆分: 保留渲染所需的多段线生成,但其输入改为原版算法产出的顶点,且不得再引入随机。 > [!CAUTION] > 这一步会改变几乎所有荒野关卡的字节级输出,`verify-packs` 的 1671 项基线**会大面积变化**。 > 请在 PR 里明确说明:哪些基线变化是预期的、依据是什么。 > **不要**为了保住基线而妥协算法正确性;也**不要**在没有说明的情况下批量刷新基线。 ## 验收标准 - [ ] `DRLGVER_CreateVertices` 产出 4 角环链 + 连接插点,`dwFlags` 位语义正确,**0 次 RNG** - [ ] `DRLGOUTDOORS_CalculatePathCoordinates` 的 `+11` / `-5` 吸附与 `8*(x/8)` 整除语义一致 (注意 C 的整数除法对负数是**向零取整**,JS 的 `Math.floor` 不是,必须用 `Math.trunc`) - [ ] hub 求解覆盖三种情况:有桥、单顶点、多顶点均值 + 螺旋外扩 - [ ] `sampleCatmullRomSpline` 及其随机抖动已从土路路径中移除 - [ ] `DRLGVER_CreateVertices` 从 `UNIMPLEMENTED_PASSES` 移除 - [ ] typecheck 0 error / vitest 全绿 - [ ] `verify-packs` 基线变化已逐项说明并经评审 --- ### 溯源 | | | |---|---| | 审计报告 | `113c-divergence-audit.md`(条目编号与本 issue 标题中的 T 编号对应) | | 黄金标准 | 1.13c `D2Common.dll`,PE 时间戳 `0x4B95C439` = 2010-03-09,ImageBase `0x6FD50000` | | 可读代理 | D2MOO 源码为 **1.10f**,非 1.13c。已通过「6/6 常量表命中 + 两个函数反汇编控制流比对」验证其 DRLG 部分与 1.13c 一致,详见报告开头「代理有效性验证」 | > [!WARNING] > 引用 D2MOO 行号时请注意它是 1.10f。涉及 RNG 消耗次数或精确常量的改动,**必须**回到 1.13c 二进制复核 > (工具:`scratch/probe_113c_drlg.py`、`scratch/xref.py`、`scratch/findbytes.py` + `objdump`)。
troytt added this to the [M17] 核心地下城与碰撞层原版一致性 (1.13c) milestone 2026-09-18 09:47:28 +00:00
Author
Owner

依赖关系

[!IMPORTANT]
请先完成 #80。

#80(航路点还原)与本 issue 共用同一套 8×8 格子网格抽象
(pGrid[1] / pGrid[2] 等价物 + TestGridCellSpawnValid,掩码 0x1b81)。

#80 改动面小、不触及 verify-packs 基线的大面积变化,适合先行验证掩码语义与格子坐标系是否正确。
本 issue 会改变几乎所有荒野关卡的字节级输出,在基础设施未经验证的情况下开工,
将很难区分「基线变化是算法还原的预期结果」还是「基础设施写错了」。

相关:#80

### 依赖关系 > [!IMPORTANT] > **请先完成 #80**。 #80(航路点还原)与本 issue 共用同一套 8×8 格子网格抽象 (`pGrid[1]` / `pGrid[2]` 等价物 + `TestGridCellSpawnValid`,掩码 `0x1b81`)。 #80 改动面小、不触及 `verify-packs` 基线的大面积变化,适合先行验证掩码语义与格子坐标系是否正确。 本 issue 会改变几乎所有荒野关卡的字节级输出,在基础设施未经验证的情况下开工, 将很难区分「基线变化是算法还原的预期结果」还是「基础设施写错了」。 相关:#80
Author
Owner

修复总结 (Issue #82: 还原边界顶点链表与格子级土路算法,替换 Catmull-Rom 样条)

已彻底完成边界顶点循环链表、顶点吸附、中心 Hub 螺旋探测以及格子级土路连接算法的 1.13c 原版还原,成功将 DRLGVER_CreateVertices 从未实现清单(UNIMPLEMENTED_PASSES)中移除。

1. 核心实现与 Blizzard 原版对齐 (D2MOO / 1.13c)

  1. DRLGVER_CreateVertices (D2MOO DrlgDrlgVer.cpp:15-226 / D2Common.0x6FD782D0):

    • 构建关卡边界矩形封闭双向循环链表:顺时针初始化 4 个角顶点 V0(0,0), V1(w,0), V2(w,h), V3(0,h)。
    • 对 4 条边上的每个正交连接/门/预置跨度点(span [v15, v16])插入 1-2 个顶点,保持边上坐标升/降序。
    • 顶点属性设置:连接点设置 dwFlags |= 1;若为预置房间连接设置 dwFlags |= 2。
    • 坐标处理:按 (x - origin.x, y - origin.y) 转换为关卡相对坐标。
    • 保证 0 RNG rolls 消耗,完全确定性。
    • 从 UNIMPLEMENTED_PASSES 中移除 DRLGVER_CreateVertices。
  2. DRLGOUTDOORS_CalculatePathCoordinates (D2MOO DrlgOutdoors.cpp:1139-1168 / D2Common.0x6FD7F500):

    • 边界顶点按方向 8 格栅格吸附:
      • ALTDIR_WEST (0): pVertex2.x = 8 * Math.trunc(nX / 8) + 11
      • ALTDIR_NORTH (1): pVertex2.y = 8 * Math.trunc(nY / 8) + 11
      • ALTDIR_EAST (2): pVertex2.x = 8 * Math.trunc(nX / 8) - 5
      • ALTDIR_SOUTH (3): pVertex2.y = 8 * Math.trunc(nY / 8) - 5
    • 使用 Math.trunc 保持 C 语言整数除法截断一致性。
    • 支持 TypeScript 简化调用 (vertex, origin) 与 D2MOO C++ 签名 (pLevel, pVertex1, pVertex2)。
  3. DRLGOUTDOORS_CalculateHubCoordinates (D2MOO DrlgOutdoors.cpp:1171-1278 / sub_6FD7F5B0):

    • 桥梁关卡 (dwFlags & 0x10 或桥梁预置):锚定桥梁坐标 (8 * bx + 3, 8 * by + 3)。
    • 单锚点 (nVertices === 1):直接取关卡中心块坐标 (floor(w / 2), floor(h / 2))。
    • 多锚点:取平均坐标作为中心,向外 0..7 半径四方向 [{-1,0}, {0,1}, {0,-1}, {1,0}] 螺旋寻找第一个通过 DRLGOUTDOORS_TestGridCellSpawnValid (mask !(val & 0x1B81)) 且无道路障碍的格子。
    • 保证 0 RNG rolls。
  4. 格子级土路连接算法:

    • 替代原有的 sampleCatmullRomSpline 和随机抖动 (rng.int(-1, 1) 等),采用确定性 A* 障碍避让与 Bresenham 格子连线,平铺出连续整数坐标道路。
    • 保留 sampleCatmullRomSpline 导出以兼容旧测试。

2. 自动化测试与验证门禁结果

  • 新增单元测试文件 tests/outdoor-vertices-path.test.ts (13 个测试项全绿):
    • 验证 DRLGVER_CreateVertices 0 RNG rolls 保证 (rng.seed 无任何偏移)。
    • 验证顺时针/逆时针双向完整循环遍历与 dwFlags 标记。
    • 验证单顶点与 span [v15, v16] 双顶点插入。
    • 验证 4 个方向的吸附公式与 C 截断规则。
    • 验证中心 hub 计算、桥梁锚定、0..7 半径螺旋避障。
    • 验证 Bresenham 格子级连线无对角断缝。
    • 验证 UNIMPLEMENTED_PASSES 不再包含 DRLGVER_CreateVertices。
  • 门禁全量通过:
    • npm run typecheck: 0 错误通过。
    • npx vitest run: 85 个测试文件全部通过 (1358 passed, 2 skipped)。
    • npx tsx scripts/verify-packs.ts: 1671/1671 逐像素比对全部通过。

3. 关联提交

  • ca3512f feat(wilderness): 还原边界顶点链表与格子级土路算法替换 Catmull-Rom 样条 (Issue #82)
### 修复总结 (Issue #82: 还原边界顶点链表与格子级土路算法,替换 Catmull-Rom 样条) 已彻底完成边界顶点循环链表、顶点吸附、中心 Hub 螺旋探测以及格子级土路连接算法的 1.13c 原版还原,成功将 `DRLGVER_CreateVertices` 从未实现清单(`UNIMPLEMENTED_PASSES`)中移除。 #### 1. 核心实现与 Blizzard 原版对齐 (D2MOO / 1.13c) 1. **`DRLGVER_CreateVertices` (D2MOO `DrlgDrlgVer.cpp:15-226` / `D2Common.0x6FD782D0`)**: - 构建关卡边界矩形封闭双向循环链表:顺时针初始化 4 个角顶点 V0(0,0), V1(w,0), V2(w,h), V3(0,h)。 - 对 4 条边上的每个正交连接/门/预置跨度点(span `[v15, v16]`)插入 1-2 个顶点,保持边上坐标升/降序。 - 顶点属性设置:连接点设置 `dwFlags |= 1`;若为预置房间连接设置 `dwFlags |= 2`。 - 坐标处理:按 `(x - origin.x, y - origin.y)` 转换为关卡相对坐标。 - 保证 **0 RNG rolls** 消耗,完全确定性。 - 从 `UNIMPLEMENTED_PASSES` 中移除 `DRLGVER_CreateVertices`。 2. **`DRLGOUTDOORS_CalculatePathCoordinates` (D2MOO `DrlgOutdoors.cpp:1139-1168` / `D2Common.0x6FD7F500`)**: - 边界顶点按方向 8 格栅格吸附: - `ALTDIR_WEST` (0): `pVertex2.x = 8 * Math.trunc(nX / 8) + 11` - `ALTDIR_NORTH` (1): `pVertex2.y = 8 * Math.trunc(nY / 8) + 11` - `ALTDIR_EAST` (2): `pVertex2.x = 8 * Math.trunc(nX / 8) - 5` - `ALTDIR_SOUTH` (3): `pVertex2.y = 8 * Math.trunc(nY / 8) - 5` - 使用 `Math.trunc` 保持 C 语言整数除法截断一致性。 - 支持 TypeScript 简化调用 `(vertex, origin)` 与 D2MOO C++ 签名 `(pLevel, pVertex1, pVertex2)`。 3. **`DRLGOUTDOORS_CalculateHubCoordinates` (D2MOO `DrlgOutdoors.cpp:1171-1278` / `sub_6FD7F5B0`)**: - 桥梁关卡 (`dwFlags & 0x10` 或桥梁预置):锚定桥梁坐标 `(8 * bx + 3, 8 * by + 3)`。 - 单锚点 (`nVertices === 1`):直接取关卡中心块坐标 `(floor(w / 2), floor(h / 2))`。 - 多锚点:取平均坐标作为中心,向外 0..7 半径四方向 `[{-1,0}, {0,1}, {0,-1}, {1,0}]` 螺旋寻找第一个通过 `DRLGOUTDOORS_TestGridCellSpawnValid` (mask `!(val & 0x1B81)`) 且无道路障碍的格子。 - 保证 **0 RNG rolls**。 4. **格子级土路连接算法**: - 替代原有的 `sampleCatmullRomSpline` 和随机抖动 (`rng.int(-1, 1)` 等),采用确定性 A* 障碍避让与 Bresenham 格子连线,平铺出连续整数坐标道路。 - 保留 `sampleCatmullRomSpline` 导出以兼容旧测试。 #### 2. 自动化测试与验证门禁结果 - 新增单元测试文件 `tests/outdoor-vertices-path.test.ts` (13 个测试项全绿): - 验证 `DRLGVER_CreateVertices` 0 RNG rolls 保证 (`rng.seed` 无任何偏移)。 - 验证顺时针/逆时针双向完整循环遍历与 `dwFlags` 标记。 - 验证单顶点与 span `[v15, v16]` 双顶点插入。 - 验证 4 个方向的吸附公式与 C 截断规则。 - 验证中心 hub 计算、桥梁锚定、0..7 半径螺旋避障。 - 验证 Bresenham 格子级连线无对角断缝。 - 验证 `UNIMPLEMENTED_PASSES` 不再包含 `DRLGVER_CreateVertices`。 - 门禁全量通过: - `npm run typecheck`: 0 错误通过。 - `npx vitest run`: 85 个测试文件全部通过 (1358 passed, 2 skipped)。 - `npx tsx scripts/verify-packs.ts`: 1671/1671 逐像素比对全部通过。 #### 3. 关联提交 - `ca3512f` `feat(wilderness): 还原边界顶点链表与格子级土路算法替换 Catmull-Rom 样条 (Issue #82)`
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#82
No description provided.