DQIX/BattleEmulator

GitHub: DQIX/BattleEmulator

这是一个基于优化算法的《勇者斗恶龙IX》单人战斗模拟器,用于寻找RTA速通中的最快胜利路径。

Stars: 0 | Forks: 2

## DQIX 单人旅行战斗模拟器 ![DQIX 战斗模拟器](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/e1bda0c95e122014.svg) ![DQIX 战斗模拟器](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/0a52fbfef3122015.svg) - 高度优化的算法组合优化 - 使用 C++ 编写 - 100% 开源 - MIT 许可证 - 使用 git 分支进行独立管理 - 面向 RTA 玩家 ## 免责声明 本项目不发布或包含任何受版权保护的游戏数据。
我们的战斗模拟器旨在避免包含任何受版权保护的数据。
避免在战斗模拟器上发生冲突的条款和条件可以 [在此查看](https://www.dropbox.com/scl/fi/ljf4ij06fux9s2527dnyp/DQ9_BattleEmu_Readme.txt?rlkey=o5xmzegriye8krmni3ma7zg82&st=1x0aowuh&dl=0)(日文) ## RTA 图表与参数解析器输入方法 https://note.com/zeppeki0711/n/neac461916cc8 # 快速开始 ## 在线试用! 在浏览器中使用您 CPU 运行战斗模拟器!
## 在 Windows11 上使用 Clion 1. 克隆项目 2. 在 Clion 中打开项目 3. 切换分支 4. 使用参数运行项目 5. 尽情享受! ## 贡献 ### 您需要准备 - JetBrains Clion(免费!)或 Visual Studio Code 2026 C++ 模式 - 带 Lua 脚本的 DeSmuME Nightly - [lua51.dll](https://sourceforge.net/projects/luabinaries/files/5.1.5/Tools%20Executables/lua-5.1.5_Win64_bin.zip/download) - git - [Ghidra](https://github.com/DQIX/dqix-functions/issues/2) - [Ctable_jp.lua](https://github.com/DQIX/desmume-scripts/blob/main/jpn/Ctable_jp.lua) - DQ9 日版 ROM - Boss 存档数据 有兴趣贡献吗?在 Twitter 上联系我们! https://x.com/Daisuke76897125 ## 分支 本仓库通过分支管理战斗模拟器
请注意 v6 🔍⚡ 优于 v7 💥🐎 并已弃用 | 分支 | Boss | 目标   | 优化器 | |:------------------------------------------------------------------------------------------------:|:----------------:|------------------------------------------------------------------------------------------------------------------------------|-----------| | [reokonn_lv8_new_arugo](https://github.com/DQIX/BattleEmulator/tree/reokonn_lv8_new_arugo) | Wight Knight | [吟游诗人 lv8](https://github.com/DQIX/BattleEmulator/blob/reokonn_lv8_new_arugo/image/reokonn_lv8_v3.png) | v6 🔍🕛 | | [reokonn_lv8_new_arugo_v2](https://github.com/DQIX/BattleEmulator/tree/reokonn_lv8_new_arugo_v2) | Wight Knight | [吟游诗人 lv8](https://github.com/DQIX/BattleEmulator/blob/reokonn_lv8_new_arugo_v2/image/reokonn_lv8_v3.png) | v7 💥🐎 | | [yo2_lv5_algorithm_v4](https://github.com/DQIX/BattleEmulator/tree/yo2_lv5_algorithm_v4) | Morag | [吟游诗人 lv10](https://github.com/DQIX/BattleEmulator/blob/yo2_lv5_algorithm_v4/image/isilyudaru_lv10.png) | v6 🔍🕛 | | [yo2_lv5_algorithm_v2](https://github.com/DQIX/BattleEmulator/tree/yo2_lv5_new_arugo_v2) | Morag | [吟游诗人 lv10](https://github.com/DQIX/BattleEmulator/blob/yo2_lv5_new_arugo_v2/image/isilyudaru_lv10.png) | v7 💥🐎 | | [bilyouma_new_arugo](https://github.com/DQIX/BattleEmulator/tree/bilyouma_new_arugo) | Ragin' Contagion | [吟游诗人 lv15 sp22](https://github.com/DQIX/BattleEmulator/blob/bilyouma_new_arugo/image/bilyouma_metaru1_lv15_sp22.png) | v6 🔍⚡ | | [bilyouma_new_arugo_v2](https://github.com/DQIX/BattleEmulator/tree/bilyouma_new_arugo_v2) | Ragin' Contagion | [吟游诗人 lv15 sp22](https://github.com/DQIX/BattleEmulator/blob/bilyouma_new_arugo_v2/image/bilyouma_metaru1_lv15_sp22.png) | v7 💥🐎 | | [zilyadama_new_arugo](https://github.com/DQIX/BattleEmulator/tree/zilyadama_new_arugo) | Master of Nu'un | lv16_sp22_tamahagane_atk123_def86 或 lv16_sp22_tamahagane_atk123_def86 | v6 🔍⚡ | | [nusisama1_v2_new_arugo](https://github.com/DQIX/BattleEmulator/tree/nusisama1_v2_new_arugo) | Lleviathan | lv17_sp22_tamahane_atk125_def93 或 lv17_sp22_hagane_atk108_def93 | v6 🔍⚡ | | [zuo_v2_new_arugo](https://github.com/DQIX/BattleEmulator/tree/zuo_v2_new_arugo) | Tyrantula | n/a | v6 🔍⚡ | | [anonn_new_arugo](https://github.com/DQIX/BattleEmulator/tree/anonn_new_arugo) | Grand Lizzier | n/a | v6 🔍⚡ | | [erugiosu_new_arugo](https://github.com/DQIX/BattleEmulator/tree/erugiosu_new_arugo) | Corvus | n/a | v6 🔍⚡ | ## 优化算法 | 版本 | 使用 | 描述 | |:-------:|:-----------------:|---------------------------------------------------------------------------------------| | v2 🦍 | 最佳优先搜索 | 为与旧版战斗模拟器兼容而用于 Corvus | | v4 🔍 | A* 算法 | 远优于 v2。移植时维护成本相当高。最大 200 万 | | v6 🔍🕛 | A* 算法+ | 旧版 v6 | | v6 🔍⚡ | A* 算法+ | 降低了维护成本的 A* 算法 | | v7 💥🐎 | 暴力搜索+光束搜索 | 基于 5 回合暴力搜索 + 光束搜索算法。因输给 v6 而中止。 | ## 基准测试 * x86_64: i7 14700F 4.5Ghz, windows11 25h2, 使用 msbuild -O3 * webassembly: Brave -O3 ### 每秒回合数 | 分支 | Boss | BruteForcer x86_64 | searcher x86_64 | BruteForcer Webassembly | searcher Webassembly | |:----------------------:|:---------------:|:------------------:|:---------------:|:-----------------------:|:--------------------:| | reokonn_lv8_new_arugo | Wight Knight | 17,074,700 | 2,544,600 | 16,350,000 | 1,830,000 | | yo2_lv5_algorithm_v4 | Morag | 19,800,800 | 1,187,300 | 15,310,000 | 840,000 | | bilyouma_new_arugo | Ragin' Contagio | 14,676,800 | 1,963,200 | 13,340,000 | 1,710,000 | | zilyadama_new_arugo | Master of Nu'un | 24,663,100 | 1,407,700 | 15,180,000 | 1,150,000 | | nusisama1_v2_new_arugo | Lleviathan | 23,277,000 | 1,462,900 | 15,400,000 | 1,170,000 | ### 每回合周期数 | 分支 | Boss | BruteForcer x86_64 | searcher x86_64 | BruteForcer Webassembly | searcher Webassembly | |:----------------------:|:---------------:|:------------------:|:---------------:|:-----------------------:|:--------------------:| | reokonn_lv8_new_arugo | Wight Knight | 263.55 | 1,768.45 | 275.23 | 2,459.02 | | yo2_lv5_algorithm_v4 | Morag | 227.26 | 3,790.11 | 293.93 | 5,357.14 | | bilyouma_new_arugo | Ragin' Contagio | 306.61 | 2,292.18 | 337.33 | 2,631.58 | | zilyadama_new_arugo | Master of Nu'un | 182.46 | 3,196.70 | 296.44 | 3,913.04 | | nusisama1_v2_new_arugo | Lleviathan | 193.32 | 3,076.08 | 292.21 | 3,846.15 | ## 已知问题 ### 战斗模拟器中的随机数缩放在数学上不完全精确。 出于性能原因,战斗模拟器使用以下基于整数的公式缩放随机值: ``` $$ ((\text{seed} \gg 32) \cdot \text{max}) \gg 32 $$ ``` 数学上理想的形式应该是: ``` $$ ((\text{seed} \gg 32) / 4294967295) \cdot \text{max} $$ ``` 由于实现使用整数位移而非精确除法, 会产生微小的量化误差。最大偏差小于 $`1 / 2^{32}`$。 这是因为实现实际上除以 $`2^{32}`$ 而非 $`2^{32} - 1`$。 为保持一致性,常量 $`2^{32}`$ 也用于其他随机数计算。 ### 战斗模拟器之间没有版本匹配标准 战斗模拟器本质上是开发时最新实现的快照,没有 自动同步版本的机制。 例如,[erugiosu](https://github.com/DQIX/BattleEmulator/tree/erugiosu) 显著过时且不 支持最新算法。即使在 _new_arugo 系列内部,也存在多个内部版本。 通常,较新版本倾向于具有改进的处理速度和更精细的算法。当版本之间的 差距过大时,有时会进行重新实现以弥合版本差异。 ## 寻求帮助 - [ ] 一个始终输出最优解且不使用启发式方法的算法 - [ ] 更多剧情 Boss 战斗模拟器的精确实现 - [ ] 能够腾出大量时间和人力进行调试的人 ## 问答 ### 战斗模拟器针对哪些地区? 仅针对日本版进行定位和测试 ### 为什么免费开源? 感谢那些投入了大量个人时间和金钱来 使战斗模拟器准确运行的志愿者,它得以免费提供 ### 为什么是 C++? 选择 C++ 是因为它是最快的语言,并且允许高度优化的算法
正是由于 C++,暴力搜索才能在 1 秒内完成
### 你如何在 1 秒内管理 48 位的暴力搜索? DQ9 中 C 表的初始种子基于游戏启动时开始的计时器。
这会产生 $`2^{48}`$ 种可能的组合,并且大约每秒递增 520,000 次。
48 位计数器的结构如下:
- 低 16 位来自 CPU 定时器 1。
- 高 32 位来自软件定时器。
实际上,高 32 位的软件定时器每秒大约增加 7.920 次。
然而,为简单起见,这可以近似为恰好每秒 8.0000 次递增:

``` \frac{1}{8.0000} = 0.125 ```
测量值 7.920 可以解释为考虑人类计时误差和实际测量条件下的现实世界有效频率。

由于完整的 48 位值由高 32 位和低 16 位组合而成,因此总递增速率为:

使用理想化值:

``` 8.0000 \times 2^{16} = 524{,}288 ```
使用观测值:

``` 7.920 \times 2^{16} = 519{,}045.12 ```
两个结果都接近前面提到的每秒约 520,000 次递增的数字。

在简化的 8.0000 假设下,近似的当前种子可以写为:

``` \left\lfloor \text{totalSeconds} \times (8.0000 \times 2^{16}) \right\rfloor ```
或等效地:

``` \left\lfloor \text{totalSeconds} \times 524{,}288 \right\rfloor ```
这种近似使常数 0.125 成为高定时器频率的简洁倒数表示,而 7.920 代表在实际条件下经验观测到的有效速率。
### 在速通中使用这个合法吗? 大约在 2024 年,战斗模拟器被私下和非官方使用。 经过社区讨论,截至 2026 年,其使用仅限于 [CTable 规范](https://www.speedrun.com/ja-JP/dq9?h=Any_Hero_Only-Japanese-Console-yes&x=q25p44gd-0nwgp5r8.1dk6kj4l-rn1gpw1n.qyz7zz41-ylq4dpvn.lx5wxzr1)。 由于尚未实现四人小队运行的战斗模拟器,目前仅允许用于单人运行的 CTable 规范。 ### 为什么没有开发四人小队战斗模拟器? * 对于小队战斗,第一个队员之后的所有角色都需要复制 AI 行为系统,该系统作为一个巨大的函数实现。 * 游戏在友方治疗、某些能力、连锁攻击及类似情况下,会逻辑性地决定使用自由相机还是固定相机,而这种行为不会泄露到 RNG 中。 * 因此,必须反编译并理解大量复杂的关联代码,而从来没有人完全解决过。 * 自由相机使用的决策逻辑并非仅由战斗伤害计算器控制。它依赖于一个庞大的互联系统集合,理解这些系统需要大量时间。 * 相比之下,单人战斗模拟器具有高度确定性,没有不稳定的 RNG 消耗,并且行为一致,这使得为单人运行开发战斗模拟器成为可能。 基于这些原因,从未开发过四人小队战斗模拟器。 ### 如何向视觉识别系统输入视频? 视觉识别系统使用浏览器摄像头 API,并通过 OBS 虚拟摄像头接收输入。 游戏画面必须使用日本的伪 Nitro 采集设备捕获并以固定布局显示。 要启动视觉识别系统,需要在浏览器前端进行多次点击。 ### 为什么使用暴力搜索来识别种子? 如上所述,本仓库使用带有提前退出的暴力搜索来高效识别种子。 RNG 表基于 64 位 LCG,这使得彩虹表等方法不切实际。顺序存储 访问将成为瓶颈,并且任何错误修复或实现更改都需要重建整个表。 这导致可维护性差和工作流程效率低下。 此外,每秒大约有 519,045 个可能的种子候选项。如果将这些量化为与伤害值匹配的查找表, 所需的存储大小很容易达到 TB 级别。 由于现代 CPU 可以极快地处理暴力搜索,因此带有激进提前终止的直接枚举 是目前最实用、可维护且最快的解决方案。 ### 为什么搜索算法这么慢? 战斗模拟器每秒可执行 1300 万到 1700 万次,但 v4 和 v6 的搜索算法基于 一个非常慢的优先队列。
即使使用了 malloc 和使用源代码中存在的 LinearIdPool.h 进行固定内存分配等优化, 也无法克服极慢的速度。
在 v7 中,搜索算法切换为暴力搜索,使其能够达到每秒 1700 万回合,但由于 使用了启发式方法,它无法超越 A*(v6),因此被放弃。
### 为什么每个战斗模拟器的 API 不同? 战斗模拟器始于不完整状态,逐渐融入了各种技术和符合人体工程学的 API, 并且由于不可能同时将想法部署到每个分支,因此产生了实现上的差异。
### 为什么每个分支一个 Boss? 尽管许多战斗机制是共享的,并且在技术上可以组合成一个可执行文件,但这样做将 需要外部化大量依赖于战斗的参数。完全通用化和完整的战斗系统反编译将显著增加代码大小,并模糊模拟器与原始 游戏逻辑之间的界限。
通过将每个 Boss 隔离到一个分支中,每个 Boss 可以独立维护自己的 constexpr 值、常量、动作选择逻辑 和参数解析器。每个分支有效地成为一个独立的黑盒。
这种分离极大地简化了维护,减少了 Boss 之间的意外交叉影响,并允许 特定于 Boss 的优化而不增加整体结构复杂性。
模拟器严格专注于精确的 RNG 位置跟踪和伤害计算。通过忽略无关的游戏 系统,它同时保持了紧凑性和执行速度。
### 为什么不使用机器学习? 机器学习主要用于当你需要在不知道未来的情况下做出良好决策时。 这里的情况并非如此。在本项目中,未来的结果可以通过模拟精确预知,因此问题更适合被 视为组合优化:搜索大量的可能动作序列并找到最快的获胜路线。由于通过模拟可以预知未来,搜索算法比机器学习更适合。 ### 为什么不使用光束搜索? 光束搜索会较早丢弃分支以保持搜索快速。这听起来不错,但它可能会移除现在看起来较弱但 未来变得非常强的路径,例如依赖于未来暴击或有利 RNG 变化的路线。 由于这个原因,光束搜索在实践中无法超越 A*,因此不被使用。 ### 为什么不使用真实硬件的内存读取? 因为那是作弊。 ### 为什么使用 C++ 而不是 Rust 或 C? 因为项目所有者最精通 C++。 它也提供了重度优化所需的速度和底层控制,因此是开发的实用选择。 ## 术语表 ### LCG https://en.wikipedia.org/wiki/Linear_congruential_generator ### CTable 这是游戏中的第三个随机数,与第二个随机数(表 B)共享处理。 更新公式如下: ``` \text{前の乱数} \times \text{0x5d588b656c078965} + \text{0x269ec3}\mod 2^{64} ``` ### 百分比 (getPercent) 游戏内部使用以下公式计算 \[0, max-1\] 范围内的整数: ``` \left\lfloor \frac{\text{seed} \gg 32}{2^{32} - 1} \times \text{max} \right\rfloor ``` 这通过除以 $2^{32} - 1$ 并乘以 `max`,将 `seed >> 32` 缩放为 \[0, max-1\] 范围内的整数。 战斗模拟器仅使用整数算术近似计算,消除了除法: ``` \left\lfloor \frac{(\text{seed} \gg 32) \times \text{max}}{2^{32}} \right\rfloor ``` 除以 $2^{32}$ 等价于右移 32 位: ``` \left( (\text{seed} \gg 32) \times \text{max} \right) \gg 32 ``` 这以最大偏差 $1 / 2^{32}$ 的代价完全消除了昂贵的除法。(另见:已知问题) ### 旋转动作 某些 Boss 使用的一种分支机制,跨越 3 个回合,每个回合有 2 个分支由 50% 概率决定,在整个旋转过程中产生 6 种可能结果。 优化实现如下: ``` int BattleEmulator::FUN_0208aecc(int* position, uint64_t* nowState) { // Extract current pre-state from bits [4:7] of the global state uint8_t pre = ((*nowState >> 4) & 0xF); if (pre == 3) { pre = 0; } // Take the lowest 1 bit from the LCG output uint8_t lcgBit = lcg::getSeed(position); // Compute branch output: pre * 2 + lcgBit ∈ {0, 1, 2, 3, 4, 5} auto output = static_cast(pre * 2 + lcgBit); assert(output <= 6); // Advance pre-state for the next turn uint8_t next = pre + 1; *nowState = (*nowState & ~0xF0) | (static_cast(next) << 4); return output; } ``` **工作原理:** 原始游戏代码读取 LCG 输出的最低 1 位来做出 50/50 的分支决策,然后将其与存储在 `nowState` 位 [4:7] 中的回合计数器(`pre`)组合以产生最终动作索引。 输出计算为 `pre * 2 + lcgBit`,在 3 回合周期中产生 6 种不同的结果: | 回合 (pre) | lcgBit = 0 | lcgBit = 1 | |:---:|:---:|:---:| | 0 | 0 | 1 | | 1 | 2 | 3 | | 2 | 4 | 5 | nowState 是一个 64 位整数,表示完整的战斗模拟器状态。前状态存储在位 [4:7] 中,并在每个回合递增。 此函数仅返回当前回合应使用动作表的哪个索引。 该索引是否对应跳转到另一个表完全取决于动作表的内容。 如果发生跳转,Boss 的动作表会更改,旋转自然结束。如果第 3 回合没有发生跳转,pre 在下一次调用开始时重置为 0,从头开始继续旋转。 ## 流程图 ``` flowchart TD subgraph Browser["Browser"] direction TB subgraph DOM["Browser DOM layer\nindex.html panels"] direction TB DOMNOTE["Static HTML / CSS panels\napp.js does not contain all markup\nit binds to existing DOM elements"] P_TIMER["panel-auto-timer\n#autoTimerPreview\n#autoTimerStartButton\n#autoTimerUseButton\n#autoTimerResetButton\n#autoTimerFractionInput\n#autoTimerStatus"] P_EMU["panel-emulator\n#emulatorSelect\n#emulatorStatus\n#offsetSeconds\n#searchRangeSeconds\n#emulatorMeta"] P_INPUT["panel-input\n#threads\n#runButton\n#actionInput"] P_DUMP["panel-dump\n#seedState\n#dumpOutput"] P_VISION["panel-vision\n#visionCameraSelect\n#visionInspectRate\n#visionPermissionButton\n#visionConnectButton\n#visionOverlay\n#visionMatches\n#visionEncodedPayload"] P_VISION_HISTORY["panel-vision-history\n#visionHistoryBody\nrecognized actions table"] P_MEMO["panel-ledger-table / Seed Memo\n#memoTableBody\n#memoRowTemplate\n#memoCopyMarkdown\n#memoCopyCsv\nnote inputs / copy URL links"] DOMNOTE --> P_TIMER DOMNOTE --> P_EMU DOMNOTE --> P_INPUT DOMNOTE --> P_DUMP DOMNOTE --> P_VISION DOMNOTE --> P_VISION_HISTORY DOMNOTE --> P_MEMO end subgraph AppJS["Application controller [app.js]"] direction TB APPNOTE["app.js responsibilities\n────────────────\nquery DOM elements\nbind event listeners\nmanage state\ni18n / URL overrides\nload manifest\nprefetch emulator.js text\nsplit work across Workers\nrender results"] UI["UI Orchestrator\nEmulator selector\nAction input\nOffset / Range\nRun Search\nDump Table updates"] STATE["App state\nselected emulator\nlatest seed result\nworker jobs\ntimer anchor\nvision bridge payload"] MEMOCTL["Seed Memo controller\nowned by app.js\nsave only when a single seed is found\nrender memo rows\ncopy Markdown / CSV\ncopy URL\neditable note field"] LS["localStorage\nSeed Memo\nup to 200 entries"] APPNOTE --> UI APPNOTE --> STATE STATE --> MEMOCTL MEMOCTL <--> LS end subgraph Timer["Auto Timer subsystem\ncontrolled by app.js + DOM panel"] direction TB T1["Start Timer\nperformance.now anchor"] T2["Tick loop\nsetTimeout ~1s"] T3["Use Current Time\ninject hh mm ss"] T4["Auto-correction\nseed drift feedback"] T1 --> T2 --> T3 T3 -.seed found.-> T4 end Cache["Module cache\nMap: url → jsText\n\napp.js prefetches emulator.js\nbut does not execute C++"] subgraph WorkerPool["Web Worker pool [worker.js]\nN threads"] direction TB WPIN["Worker message API\nprepare / bruteforce / search"] subgraph EvalLayer["Dynamic emulator loader\ninside each Worker"] direction TB EVAL["eval(jsText)\n\nforce-loads prebuilt\nEmscripten SINGLE_FILE glue JS"] MOD["Emscripten Module instance\nper worker"] WASM["Wasm runtime / exports\ncreated after eval"] EVAL --> MOD --> WASM end W1["Worker 1\nBruteForce"] W2["Worker 2\nBruteForce"] WN["Worker N …"] WS["Winner worker\nA* Search"] WPIN --> EVAL WASM --> W1 WASM --> W2 WASM --> WN WASM --> WS end subgraph Vision["Vision subsystem [vision.js]\nDOM-backed camera console"] direction TB CAM["Camera\ngetUserMedia\n1920×1080"] FRAME["Frame loop\nrequestVideoFrameCallback\nor rAF, 1–12 fps"] PROC["Processing canvas\n958×718 rescale"] subgraph Matcher["Template Matcher"] direction TB GPU["WebGpuTemplateMatcher\nWGSL compute shader\n1 submit + 1 mapAsync"] CPU["CpuTemplateMatcher\nJS fallback"] end DAMAGE["Damage recognizer\ndigit template match\nCPU, white-mask IoU"] CAND["pickCandidate\n4 slots: main/sub/ally/target\n→ action rule table"] ACCEPT["acceptCandidate\nstate machine:\nActionTaken / sleeping\n/ slept / daibougilyo"] HISTORY["Turn history\nturn x slot x actionId x damage"] BRIDGE["BattleEmulatorBridge\nwindow.postMessage\nbase64url JSON"] ASSETS["vision-assets.json\npre-baked binary masks\nfor templates + digits"] CAM --> FRAME --> PROC PROC --> Matcher PROC --> DAMAGE Matcher --> CAND DAMAGE --> ACCEPT CAND --> ACCEPT ACCEPT --> HISTORY HISTORY --> BRIDGE ASSETS -.load on connect.-> Matcher end DOM <-->|querySelector / input events / render| AppJS P_TIMER <-->|buttons / fraction / status| Timer P_MEMO <-->|render rows / note edits / copy actions| MEMOCTL P_VISION <-->|camera controls / overlay / bridge payload| Vision P_VISION_HISTORY <-->|render accepted actions| HISTORY end subgraph Static["Static hosting"] direction TB STATICNOTE["Static hosting / public assets\npublished by GitHub Pages\nprebuilt before deployment"] Manifest["public/emulators.json\n\nread at runtime as:\nfetch('emulators.json', cache: 'no-store')\n\ncontains emulator entries\nname / url / meta"] WasmJS["public/branches/.../emulator.js\n\nexample:\npublic/branches/bilyouma_new_arugo_v8/\nbilyouma_v8/emulator.js\n\nprebuilt Emscripten SINGLE_FILE JS\nper boss / branch"] STATICNOTE --> Manifest STATICNOTE --> WasmJS end subgraph CppCore["C++ core"] direction TB CPPNOTE["C++ core compiled into Wasm\nbundled inside emulator.js\nnot called directly by app.js\nexecuted only through Worker eval + Wasm exports"] BE["BattleEmulator::Main\nLCG RNG + damage"] IB["InputBuilder\n→ ResultStructure"] AO["ActionOptimizer\nA* search"] CC["EnhancedCostCalculator\ng / h cost"] HC["EnhancedHashCalculator"] LCG["lcg\n64-bit LCG"] CPPNOTE --> BE CPPNOTE --> IB CPPNOTE --> AO BE --> LCG IB --> BE AO --> BE AO --> CC AO --> HC end UI -- "loadManifest()" --> Manifest Manifest -- "emulator list" --> UI UI -- "fetch selected / likely emulator url\nas text" --> WasmJS WasmJS -- "jsText" --> Cache UI -- "computeSeedRange / splitRange" --> WorkerPool Cache -- "postMessage jsText\nselected emulator" --> WorkerPool WorkerPool -- "prepare complete\nbruteforce progress\nfound seed\nsearch result\ndump table" --> UI WASM -. "exports call into compiled code" .-> CppCore CppCore -. "runs inside Wasm runtime" .-> WASM Timer --> STATE STATE -- "latest confirmed seed / drift" --> T4 UI --> MEMOCTL BRIDGE -- "applyVisionBattleFormat\nwindow global / app.js handler" --> UI classDef dom fill:#f8fafc,stroke:#64748b,color:#0f172a classDef app fill:#ecfeff,stroke:#0891b2,color:#164e63 classDef cpp fill:#dbeafe,stroke:#3b82f6,color:#1e3a8a classDef worker fill:#fef9c3,stroke:#ca8a04,color:#713f12 classDef static fill:#f0fdf4,stroke:#16a34a,color:#14532d classDef timer fill:#fdf4ff,stroke:#a855f7,color:#4a044e classDef memo fill:#fff7ed,stroke:#ea580c,color:#7c2d12 classDef vision fill:#f0f9ff,stroke:#0ea5e9,color:#0c4a6e classDef eval fill:#fee2e2,stroke:#dc2626,color:#7f1d1d classDef runtime fill:#ede9fe,stroke:#7c3aed,color:#3b0764 classDef note fill:#ffffff,stroke:#94a3b8,color:#334155,stroke-dasharray: 4 3 class DOMNOTE,P_TIMER,P_EMU,P_INPUT,P_DUMP,P_VISION,P_VISION_HISTORY,P_MEMO dom class APPNOTE,UI,STATE app class BE,IB,AO,CC,HC,LCG,CPPNOTE cpp class W1,W2,WN,WS,WPIN worker class Manifest,WasmJS,STATICNOTE static class T1,T2,T3,T4 timer class MEMOCTL,LS memo class CAM,FRAME,PROC,GPU,CPU,DAMAGE,CAND,ACCEPT,HISTORY,BRIDGE,ASSETS vision class EVAL eval class MOD,WASM runtime ``` ## 本仓库的官方图像规则 禁止转载或分发本页面使用的、由株式会社史克威尔艾尼克斯等共同作者拥有权利的图像。
标签:AI工具, C++, Dragon Quest IX, Git, Lua脚本, RTA, 云资产清单, 代码示例, 实时攻击优化, 开源, 快速通关, 性能优化, 战斗模拟器, 战斗路径, 数据分析, 数据擦除, 检测绕过, 模拟器工具, 模拟器开发, 游戏优化, 游戏模拟, 游戏辅助, 算法优化, 组合优化, 脚本编程, 自定义脚本, 路径规划, 软件开发, 逆向工程