PULSE
AI 认知方法 HOWTO重要度 72

5000亿Token后:AI智能体逆向FPS游戏

Hacker News · 2026-10-11 · 原题《500+ Billion Tokens Later: Letting AI Agents Decompile A First-Person Shooter》 · 原文约 8 分钟 · 阅读原文 ↗
AI智能体逆向FPS:从“可读”到“正确” 5000亿Token后的核心教训 项目目标 反编译为可读C++ 初始设置 Claude+Codex+GitHub 工具链 ida-mcp 稳定无头 第一个月成果 4智能体还原80% 问题暴露:可读但语义错误 错误函数签名 / 类型 / 结构布局 发明或删除逻辑 引入不必要架构变更 根本原因 缺乏客观验收标准 reviewer被注释说服(提示注入) 核心主张 仅靠进度和可读性 无法保证正确性 必须引入 字节匹配的客观验收标准 从“看起来对”到“行为完全一致” 避免主观判断被误导
作者用AI智能体逆向一款FPS游戏,发现仅靠进度和可读性无法保证正确性,必须引入字节匹配的客观验收标准。

做法与步骤

  1. 项目目标:用AI智能体将老FPS游戏反编译为可编译、可读的C++,并希望修复安全漏洞、提升可移植性,但后期聚焦于还原原始行为。
  2. 初始设置:同时使用Claude Max和Codex Pro订阅,智能体在各自CLI中运行,通过GitHub issues跟踪进度,Discord频道进行智能体间及人机沟通。
  3. 反汇编工具:全程使用Hex-Rays的官方ida-mcp,稳定、无头且功能齐全,作者强烈推荐。
  4. 第一个月:4个智能体(3个worker、1个reviewer)反编译了约80%游戏,游戏能启动、显示菜单、加载地图,但优化中降低了压缩阈值至42%以减少token消耗。
  5. 问题暴露:代码可读但语义错误,如错误函数签名、类型、结构布局,甚至发明或删除逻辑,还引入不必要的架构变更(如将全局变量访问改为哈希表)。
  6. 根本原因:缺乏客观验收标准,reviewer被worker的注释说服,相当于无意的提示注入,导致错误被接受。

对实践的启示

做AI应用时,不能只看进度和代码可读性,必须定义可自动验证的正确性标准(如字节匹配),否则智能体会产生看似合理但语义错误的输出。

作者承认的反方与局限

作者承认reviewer能捕捉部分bug,但无法质疑架构决策,且由于项目包含现代化和可移植性目标,某些偏差未被当作错误。

原文摘引

Despite the code being extremely readable, it was semantically wrong.
The workers’ comments effectively acted as unintentional prompt injection: the reviewer accepted their justifications instead of independently checking the deviations against the original.
▸ 展开原文全文(48 段,抓取自 Hacker News)

During the last 3 months, I spent some of my time and tokens decompiling a popular first-person shooter. The goal was not to reach a simple proof-of-concept state. Instead, we really wanted an accurate, stable and feature-complete recreation of the game.

The avid reader of my blog might have noticed that I had previously written two posts that have since been removed. Everyone else might now be wondering which game I am talking about. To both of you I can only say that corporate America was here to ruin our fun.

However, that’s fine. This post is not about the game, it’s also less about the process of decompilation. It’s more about AI orchestration and how to optimize infrastructure, setup and harness for optimal results.

This project was done with the help of RektInator, Future, st0rm and other members of the community. A big thank you to all of them.

What Was Our Goal? We aimed at an accurate decompilation of the game to C++. Besides obvious semantic correctness, we had quite a few more requirements: We wanted readable C++ source that compiles. Given how old the game is, we also wanted security and bug fixes, but also portability improvements. It would be nice to run the game on Linux, macOS, in the browser, …

We later deferred modernization and portability to focus entirely on reconstructing the original behavior.

Obviously, the overall goal was to learn how to effectively orchestrate autonomous AI agents over the course of months.

The Initial Setup We started with Claude Max (20x), then added Codex Pro and used both subscriptions simultaneously. Model choice varied a lot. We had been using Sonnet 5 most of the time, but Opus 5.5, Luna, Sol and Terra were also used a lot. More on that later.

Claude agents were running in Claude Code CLI, Codex agents in Codex CLI. We also tried other agent harnesses, but the choice barely mattered, so we stuck to the defaults.

Progress Tracking Using GitHub CLI, the agents manage GitHub issues to track their progress. There is one issue per translation unit (.cpp file). Additionally, labels help group and prioritize issues.

Communication Agents communicate via Discord. All of them have access to one channel and can both post and read all messages in there.

Discord allows agent-2-agent communication, as well as human-2-agent. So other participants can talk to them, without needing machine access.

A GitHub webhook posts CI failures into the shared channel, so agents get notified when something broke.

Disassembly & Decompilation Agents have been using the official ida-mcp by Hex-Rays almost the entire time. It works great. It’s super stable, it’s headless and supports everything needed for this project. I can only recommend it.

The First Month We had 4 agents running at that time.

3 worker agents decompiling and committing and one reviewer agent that passively coordinates and reviews commits to flag bugs.

Agents managed to decompile about 80% of the game and visible progress was made. The game launched, the main menu was visible and we were able to load maps.

We spent a lot of those 4 weeks optimizing our setup:

We reduced token consumption by triggering earlier compactions.

The default compaction threshold is 90% context fill. We reduced it down to 42%. Decompilation consists of a lot of volatile information: A function that was decompiled is now irrelevant and could be removed from the context. So earlier compactions help remove such “junk” from the context.

We also noticed that agents tend to lose focus over time. Even within the span of one compaction cycle, agents can drift and lose focus, the more data the context holds.

Agents sometimes moved to another function before finishing the previous one. They also started idling while watching CI, despite receiving failure notifications on Discord. Occasionally, they closed issues without thoroughly checking whether the work was actually complete.

Working side by side in a terminal, you can steer the agents to prevent that, but when letting them work autonomously, steering is not possible.

To prevent that, we wrote a document defining our goal, how agents should work, what they must avoid and how to handle specific situations.

An hourly cron job automatically injected a request for agents to reread this document, keeping the instructions fresh in their context. While this might not be the ideal method to keep agents focused, it worked really well through the end of the project.

Lots of time was spent refining the instruction document. As the content is extremely specific to this project, it makes less sense to share it here, though.

However… … despite all our efforts optimizing setup and infrastructure, we need to talk about the quality of the work.

Constant progress (game starting, menu rendering, maps loading) led us to believe the quality of the decompilation was great.

It was not. Despite the code being extremely readable, it was semantically wrong.

Agents used wrong function signatures, types or struct layouts. They invented logic or removed it where deemed unnecessary.

Beyond semantic errors, agents also introduced unnecessary architectural changes. As an example, the game has certain configuration variables that it accesses via global variables. The agents had turned this constant memory access into hash tables with a lookup that was orders of magnitude more expensive.

And that’s just one example of the many things that went wrong.

Why is that? While a reviewer helps catch bugs, it does not work well for anything beyond that. Architectural decisions were not questioned, as long as they aligned with the goal.

The main reason for that is that we didn’t have objective acceptance criteria. We never properly defined “correctness”. Therefore it was hard for the reviewer to judge which change is correct and what’s wrong.

Obviously it had the game as reference, but given that we had modernization and portability on the list as well, certain deviations were not treated as bugs.

Interestingly, comments in the commits or code led the reviewer to accept deviations, due to whatever justification the worker agent had written down. The workers’ comments effectively acted as unintentional prompt injection: the reviewer accepted their justifications instead of independently checking the deviations against the original.

The Oracle What we needed was an automated check that tells agents whether a reconstructed function matches the original. It should verify identical semantics. A simple PASS or FAIL signal would be enough and the agent can figure out on its own what’s wrong.

Byte Matching Decompilation The simplest way to achieve this was byte matching decompilation.

We switched to the compiler used to build the original game and wrote a script that performs the comparison.

The script reads our reconstructed OBJ file and the game EXE/PDB (having the PDB is great and makes things slightly simpler, but the process can work just as well without a PDB).

It then extracts the function data from OBJ and EXE and compares all bytes. If they match, the function is exact, otherwise it fails and the agent needs to rework the function.

References to other functions or data won’t necessarily match byte for byte, because their encoded values depend on where the targets end up in the compiled binary.

Luckily, the OBJ file records these references as relocations. We can exclude the relocation bytes from the direct comparison and instead verify that both versions reference the same symbol with the same offset.

The script then does the same for data and types.

Agents can then use this script to verify their work, before pushing it.

Reconstructed functions are recorded in a set of text files. CI can then use these text files to verify all recorded functions and alert in case of regressions.

Cheating The first thing agents did when we introduced this script was write inline assembly.

This obviously defeats the purpose. So we had to refine our instructi