Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions M1_技术交付说明.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# 《三国五行传》Stake Engine Math SDK M1 技术交付说明

> 历史基线:M1 的 BR0 已被 M2a 优化配置替代。当前有效自然基线见《M2a Reel Strip 优化交付说明》。

| 项目项 | 内容 |
|---|---|
| 交付版本 | M1 / `m1.0.0` |
| 日期 | 2026-07-30 |
| SDK | Stake Engine Math SDK |
| SDK 提交 | `600a37657c75d67c0412bf3952a01d7e7ee99987` |
| 上游许可 | MIT |
| 游戏目录 | `games/0_0_sanguo_wuxing` |
| 当前状态 | 自然簇群原型可运行,RGS 文件校验通过 |

## 1. 本次交付

M1 已将独立数学规格迁移到 Stake Engine Math SDK,未修改 `src/` 下的官方 SDK 核心源码。所有项目差异集中在新增的游戏目录与项目测试中,便于后续同步上游。

已实现:

- 7×7 盘面;
- 5 个高分武将符号 H1–H5;
- 5 个五行令符号 L1–L5;
- 武魂 Wild W1、天命 Wild W2;
- 四方向 5+ 簇群;
- 五档簇群赔付;
- Wild 单一步骤单一归属;
- 最高总赔付组合与确定性平局规则;
- 同一步统一计奖、统一消除;
- 垂直掉落与顶部补位;
- 50,000× 服务端封顶;
- 双 Wild 同现候选事件;
- 固定种子 reel strip 生成器;
- SDK books、LUT、配置、强制记录与发布文件输出;
- RGS books/LUT 哈希一致性校验。

M1 明确未实现:

- 2×2 超大符号;
- 随机武魂救援;
- 将魂返场;
- 五行奇策队列与局末倍数;
- 免费旋转和武魂成长;
- 100× Bonus Buy;
- 完整 96.0% RTP 优化。

## 2. 目录说明

| 文件 | 用途 |
|---|---|
| `game_config.py` | 盘面、赔率、特殊符号、模式与封顶 |
| `game_calculations.py` | 簇群识别与 Wild 最高赔付归属 |
| `game_executables.py` | 计奖、WinManager 更新和双 Wild 检查 |
| `gamestate.py` | 单局揭示、连锁、结算状态机 |
| `game_events.py` | `dualWildTriggerCandidate` 自定义事件 |
| `generate_reels.py` | 生成 7 条确定性 reel strip |
| `reels/BR0.csv` | 当前基础模式 reel strip |
| `run.py` | SDK 模拟、配置生成与 RGS 格式检查 |
| `smoke_test.py` | 单回合无文件快速检查 |
| `math_manifest.json` | 实现范围、版本和延期功能清单 |
| `tests/test_sanguo_wuxing.py` | 配置、Wild、reel 和确定性测试 |

## 3. Wild 归属实现

官方簇群示例使用全局 `already_checked` 消费 Wild,但其归属会受到盘面遍历顺序影响。本项目使用游戏级覆盖实现:

1. 分别计算每个付费符号与 Wild 的候选连通区域;
2. 排除纯 Wild 区域;
3. 无 Wild 的有效簇群全部保留;
4. 对包含 Wild 的候选簇群求解 Wild 互斥组合;
5. 选择本步骤总赔付最高的组合;
6. 同赔付时按单簇群赔付、符号价值、簇群大小、左上坐标排序;
7. 在赢奖事件 `meta` 中输出 `wildPositions` 和 `ownershipAlgorithm`。

算法版本为 `max-total-pay-v1`。修改平局规则或 Wild 复用规则时必须提升数学版本。

## 4. 100,000 局 SDK 基线

运行命令:

```bash
SANGUO_SIM_COUNT=100000 env/bin/python games/0_0_sanguo_wuxing/run.py
```

结果:

| 指标 | 数值 |
|---|---:|
| 样本量 | 100,000 |
| 自然簇群 RTP | 59.2540% |
| 自然命中率 | 37.2760% |
| 命中局平均赢分 | 1.5896× |
| 标准差 | 1.1561× |
| 样本最大自然赢分 | 17.0× |
| 双 Wild 候选次数 | 434 |
| 双 Wild 候选频率 | 0.4340%,约 1/230 |
| Books/LUT 条目 | 100,000 |
| RGS payout hash | 通过 |
| RGS SHA-256 | 通过 |

双 Wild 入口位于产品目标 1/180–1/260 内。自然 RTP 高于独立抽样原型的 48.5867%,说明 reel strip 的连续窗口和连续补位相关性对簇群结果有显著影响。

当前 59.2540% 不是问题修复后的完整 RTP,更不是可发布 RTP。M2 必须在真实 SDK 模型中重新分配预算:

- 优先调 reel strip 计数与排列,目标把自然簇群压回约 48.5%;
- 不建议直接把全部赔付表乘以 0.8185,因为会破坏用户可读的赔率阶梯;
- 调整后重新确认命中率仍位于 30%–45%;
- 再给基础功能约 19.5%、免费旋转约 28.0% 的初始预算;
- 完整功能接入后才校准到 96.0%。

## 5. 已验证项目

烟雾测试:

```bash
env/bin/python games/0_0_sanguo_wuxing/smoke_test.py
```

项目测试:

```bash
env/bin/python -m pytest tests/test_sanguo_wuxing.py -q
```

结果为 `4 passed`。

SDK RGS 校验输出:

```text
[FAST PATH] base: SHA-256 OK, payout hash OK, entries=100000
```

## 6. SDK 批次注意事项

当前上游版本在“单线程、多批次、不运行优化器”的组合下,发布 `_0` LUT 和验证侧车可能沿用不同批次文件,导致 payout hash 不一致。

M1 的确定性处理为:

- `batching_size = simulation_count`,固定单批次;
- 不运行优化器时,模拟结束后将最新基础 LUT 明确复制为发布 `_0` LUT;
- 再生成配置并执行 RGS 校验。

这不是游戏赔付算法错误,而是发布文件生命周期问题。将来启用官方优化器或多线程大规模模拟时,需要重新验证上游是否已修复,并为每个分片增加独立哈希测试。

## 7. M2 建议顺序

1. 优化 BR0 reel strip,将自然 RTP 调至约 48.5%;
2. 实现 2×2 超大符号;
3. 实现随机武魂救援和将魂返场;
4. 实现五行奇策队列与 ×2/×3/×5/×10;
5. 将 `dualWildTriggerCandidate` 升级为正式免费旋转触发;
6. 实现 1×1 至 7×7 武魂成长;
7. 增加 100× Bonus Buy 模式;
8. 跑普通模式与购买模式各 1,000,000 局快速回归;
9. 数学结构稳定后进入 100,000,000 局优化。

## 8. 交付入口

- [M1 游戏目录](games/0_0_sanguo_wuxing)
- [游戏配置](games/0_0_sanguo_wuxing/game_config.py)
- [Wild 归属算法](games/0_0_sanguo_wuxing/game_calculations.py)
- [项目测试](tests/test_sanguo_wuxing.py)
- [100,000 局统计](games/0_0_sanguo_wuxing/library/stats_summary.json)
- [RGS 发布目录](games/0_0_sanguo_wuxing/library/publish_files)
153 changes: 153 additions & 0 deletions M2a_reel优化交付说明.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# 《三国五行传》M2a Reel Strip 优化交付说明

| 项目项 | 内容 |
|---|---|
| 数学版本 | `m2a.0.0` |
| 日期 | 2026-07-30 |
| 目标 | 将 Stake SDK 自然 RTP 从 59.2540% 调回约 48.5% |
| 结果 | 100,000 局自然 RTP 48.3824% |
| 状态 | M2a 基线锁定,可进入基础功能开发 |

## 1. 结论

M2a 在不修改用户可见赔付表的前提下,通过扁平化符号计数和选择确定性 reel 排列,将自然簇群 RTP 从 M1 的 59.2540% 降至 48.3824%。

同时满足:

- 自然命中率 33.1610%,位于 30%–45% 目标区间;
- 双 Wild 同现约 1/244,位于 1/180–1/260 目标区间;
- 100,000 条 Books/LUT payout hash 一致;
- 发布文件 SHA-256 校验通过;
- 赔付表、Wild 归属算法与 50,000× 封顶均未改变。

## 2. M1 与 M2a 对比

| 指标 | M1 | M2a | 变化 |
|---|---:|---:|---:|
| 自然 RTP | 59.2540% | 48.3824% | -10.8716 个百分点 |
| 自然命中率 | 37.2760% | 33.1610% | -4.1150 个百分点 |
| 命中局平均赢分 | 1.5896× | 1.4590× | -0.1306× |
| 标准差 | 1.1561× | 1.0116× | -0.1445× |
| 最大观察自然赢分 | 17.0× | 20.0× | 样本波动 |
| 双 Wild 频率 | 约 1/230 | 约 1/244 | 均在目标内 |

M2a 的目的不是降低完整游戏波动率,而是把自然盘面从过高预算中释放出来。后续五行队列、局末倍数和免费旋转将重新建立长尾。

## 3. Reel 配置

每条 reel 长 719,包含 717 个付费符号和 2 个 Wild。

| 符号 | M1 每 reel 数量 | M2a 每 reel 数量 |
|---|---:|---:|
| H1 | 17 | 20 |
| H2 | 25 | 28 |
| H3 | 33 | 36 |
| H4 | 42 | 45 |
| H5 | 50 | 53 |
| L1 | 75 | 76 |
| L2 | 92 | 91 |
| L3 | 108 | 106 |
| L4 | 125 | 120 |
| L5 | 150 | 142 |
| W1 | 1 | 1 |
| W2 | 1 | 1 |

生成参数:

- 概率扁平化指数:`0.90`;
- reel 排列种子:`906502183`;
- reel SHA-256:`e0b86d0082b7fcc59aeab49ac96873f917568003529750f49cf26694862f41d2`;
- 生成器:`generate_reels.py`;
- 搜索器:`tune_reels.py`。

排列种子属于数学配置的一部分。相同符号计数但不同排列会改变纵向连通、补位路径和双 Wild 同现率,不允许上线前随意重新洗牌。

## 4. 搜索方法

搜索过程使用真实 `GameState`、真实 reel window、真实 tumble 和项目 Wild 归属算法,不使用独立抽样近似:

1. 对原始权重应用 0.84–0.90 的指数扁平化;
2. 使用最大余数法转换为每 reel 717 个付费停点;
3. 为各候选生成 7 条确定性排列;
4. 先跑每候选 5,000 局宽搜索;
5. 对 0.88–0.90 区域跑每候选 20,000 局窄搜索;
6. 选定指数 0.90、种子 906502183;
7. 使用正式 SDK 管线跑 100,000 局;
8. 校验 Books、LUT、force record 和发布哈希。

候选评分同时约束:

- 自然 RTP 接近 48.5%;
- 命中率位于 30%–45%;
- 双 Wild 频率位于 1/180–1/260。

## 5. 100,000 局锁定结果

| 指标 | 结果 |
|---|---:|
| 自然 RTP | 48.3824% |
| 自然命中率 | 33.1610% |
| 零赢率 | 66.8390% |
| 命中局平均赢分 | 1.4590× |
| 标准差 | 1.0116× |
| 最大观察自然赢分 | 20.0× |
| 双 Wild 候选 | 410 次 |
| 双 Wild 频率 | 0.4100%,约 1/244 |
| RGS Books/LUT 条目 | 100,000 |
| Payout hash | 通过 |
| SHA-256 | 通过 |

完整结果快照位于:

- `games/0_0_sanguo_wuxing/validation/m2a_100k_summary.json`
- `games/0_0_sanguo_wuxing/reels/BR0.metadata.json`

## 6. RTP 后续预算

以 M2a 结果为基础,完整 96.0% 尚有约 47.6176 个百分点可分配。继续采用下列工作预算:

| 模块 | 预算 |
|---|---:|
| 自然簇群 | 约 48.4% |
| 2×2 超大符号 | 约 3.0% |
| 随机武魂救援 | 约 2.5% |
| 将魂返场 | 约 2.5% |
| 五行队列与局末倍数 | 约 11.6% |
| 免费旋转和成长 | 约 28.0% |
| 合计 | 96.0% |

这些仍是调优预算,不是最终认证分项。任何功能的实际贡献偏移都必须通过完整模式重新平衡。

## 7. 回归要求

后续任何数学改动必须检查:

- `BR0.csv` 哈希是否有意变化;
- 自然 RTP 是否仍在 48.0%–49.0% 工作区间;
- 自然命中率是否仍在 30%–45%;
- 双 Wild 频率是否仍在 1/180–1/260;
- Wild 单一归属测试是否通过;
- 100,000 局 Books/LUT 哈希是否一致。

接入功能后,“自然 RTP”必须作为独立统计项保留,不得只报告完整 RTP。

## 8. 下一阶段

M2b 建议实现基础功能,但先不接免费旋转:

1. 2×2 超大符号;
2. 无赢局随机武魂救援;
3. 将魂返场;
4. 五行奇策队列;
5. ×2、×3、×5、×10 局末倍数;
6. 把完整基础游戏调至约 68%。

完成 M2b 后,再进入 M2c 免费旋转与 100× Bonus Buy。

## 9. 交付入口

- [M2a 验证快照](games/0_0_sanguo_wuxing/validation/m2a_100k_summary.json)
- [Reel 元数据](games/0_0_sanguo_wuxing/reels/BR0.metadata.json)
- [Reel 生成器](games/0_0_sanguo_wuxing/generate_reels.py)
- [Reel 搜索器](games/0_0_sanguo_wuxing/tune_reels.py)
- [M2a 游戏说明](games/0_0_sanguo_wuxing/README.md)
Loading