Show HN:我制作了一款基于战术地图的二战潜艇模拟器(公开测试版)
摘要
作者宣布了一款名为 Silent Shark 的基于战术地图的二战潜艇模拟器,目前处于公开测试阶段。该模拟器使用 Vite/TypeScript 构建,专注于水听器监听、航向估计和潜望镜目标识别,计划在 Steam、iOS 和 Android 上全面发布。
I've seen quite a few simming discussions on HN, so thought some of you might like this - I've created a map-centered, tactical submarine simulator and it's been a blast to make.<p>I grew up playing Silent Service II on Atari ST with my dad, then got into Silent Hunter IV in the 2000s, and most recently have been loving the more recent UBoat. In each case, the part I always enjoy the most is the plotting and charting aspect - essentially beating uncertain estimates with geometry.<p>So I decided to see how far I could get making my own sim that focused nearly entirely on that aspect. You listen on the hydrophone, estimate course and speed, identify ships through the periscope to get the mast height, use a working stadimeter for range estimates, and then try to build a good enough firing solution before getting discovered and hunted by any escorts.<p>Things I'm particularly proud of are the working stadimeter, the dynamic music (Holst Mars stings when your torpedo is nearing a ship), and pretty intelligent destroyer logic. I've found great reference materials online and have modeled several of the gauges directly after actual submarine instruments.<p>Tech-wise it’s a Vite/TypeScript app which enables me to offer the whole free version of the app as a browser version.<p>The Steam page is here => <a href="https://store.steampowered.com/app/4705650" rel="nofollow">https://store.steampowered.com/app/4705650</a><p>The landing page is here => <a href="https://silentshark.app" rel="nofollow">https://silentshark.app</a><p>I plan on releasing a full version soonish, including a WWII campaign with progression, patrol zones, and much more on Steam (PC, Mac, Linux/Steam Deck), App Store (iPhone, iPad, Mac), and Play Store (Android).<p>Would highly appreciate any feedback anyone has!
相似文章
@dangreenheck: Three.js Water Pro 让在浏览器中实现《Subnautica》成为现实。重写了光照模型,使得光反射…
Three.js Water Pro 更新重写了光照模型,基于物理的折射和衰减实现逼真的海底反射,使得类似《Subnautica》的水下浏览器游戏成为可能。
Show HN:我逆向工程了《Test Drive III》(1990年DOS游戏)的世界地图
对1990年DOS游戏《Test Drive III》的地图进行了逆向工程和提取,提供了在线查看器和OBJ导出功能。该项目包含文件格式规范及提取工具。
# 我厌倦了"保姆式"管理我的AI。于是我花了6个月时间构建了一个C++20自主软件工厂,让它在我睡觉时也能持续交付 大约一年前,我和大多数开发者一样使用AI辅助编码——在IDE里接受建议,偶尔请它帮我解释某段代码,或者让它生成一些样板代码。这还不错,但我发现自己一直在做的事情本质上是:**充当AI的执行层**。 我来决定做什么。AI来建议怎么做。我来评估建议。我来运行代码。我来解读错误信息。然后我再把结果喂回给AI,整个循环重新开始。 每次会话都让我觉得自己更像一个翻译,而不是一个开发者。 --- ## 打破循环 我开始思考:为什么AI不能自己关闭这个循环? 不是"下一行代码建议"那种意义上的自主——而是真正的**任务级自主**:接收一个高层规格说明,然后自主规划、实现、测试并交付完整的软件组件,无需手把手指导。 挑战在于,这需要的不仅仅是一个更好的提示词。它需要一个具备真实内存、真实工具访问权限和真实决策能力的**架构**。 我花了6个月时间构建它。用C++20编写。这就是我学到的东西。 --- ## 架构概览 我将整个系统称为**自主软件工厂(Autonomous Software House,ASH)**。其核心思想是:你提供一个意图(以自然语言、工单或规格文档的形式),系统负责将其转化为可工作的软件。 系统由五个主要层次组成: ``` ┌─────────────────────────────────────┐ │ 意图接收层 │ │ (自然语言 → 结构化任务) │ ├─────────────────────────────────────┤ │ 规划与分解层 │ │ (任务 → 有序子任务图) │ ├─────────────────────────────────────┤ │ 执行层 │ │ (子任务 → 代码/测试/文档) │ ├─────────────────────────────────────┤ │ 验证层 │ │ (输出 → 通过/失败 + 诊断) │ ├─────────────────────────────────────┤ │ 内存与上下文层 │ │ (跨会话持久状态) │ └─────────────────────────────────────┘ ``` 让我逐层分解。 --- ## 第一层:意图接收 大多数AI工具在这一步就已经失败了。它们要求你用AI能理解的方式来表达你的意图,而不是反过来。 ASH的意图接收器会将模糊的高层描述转化为结构化的**任务规格(TaskSpec)**: ```cpp struct TaskSpec { std::string id; std::string intent; // 原始自然语言描述 std::vector<std::string> acceptance_criteria; std::map<std::string, std::string> constraints; Priority priority; std::optional<std::string> parent_task_id; // 从意图推断出的字段 TaskType inferred_type; // FEATURE / BUGFIX / REFACTOR / TEST std::vector<std::string> inferred_dependencies; ConfidenceScore intent_confidence; }; ``` 关键设计决策:系统存储**原始意图**以及解析后的结构。当后续层次需要消歧时,它们可以回溯到原始表述,而不是在已经经过转化的描述上继续操作。 意图接收器还会检测**欠规格说明**——它不是在遇到歧义时直接执行,而是生成澄清问题,并在继续之前等待答复。这消除了大量由于AI对不明确指令做出假设而导致的"错误方向"执行。 --- ## 第二层:规划与分解 这是最有趣的层,也是最难做好的层。 给定一个`TaskSpec`,规划器需要生成一个可执行的子任务图。挑战在于:子任务必须足够细粒度,以便可以独立执行,同时又必须足够高层,以便有意义地组合。 我使用了一个**递归分解策略**,配合复杂度预算: ```cpp class TaskPlanner { public: SubTaskGraph decompose(const TaskSpec& spec) { auto initial_plan = llm_client_.plan(spec); SubTaskGraph graph; for (auto& subtask : initial_plan.subtasks) { if (estimate_complexity(subtask) > complexity_budget_) { // 递归分解过于复杂的子任务 auto sub_graph = decompose(subtask); graph.merge(sub_graph); } else { graph.add_node(subtask); } } // 推断依赖关系 dependency_analyzer_.annotate(graph); // 检测循环依赖(不能存在) if (graph.has_cycles()) { graph = cycle_resolver_.resolve(graph); } return graph; } private: float estimate_complexity(const SubTask& task); LLMClient llm_client_; DependencyAnalyzer dependency_analyzer_; CycleResolver cycle_resolver_; float complexity_budget_ = 0.7f; // 可调参数 }; ``` `complexity_budget_`参数是系统中最重要的可调旋钮之一。设置过高,你会得到执行失败的庞大单体子任务。设置过低,你会得到过于细碎、难以整合的任务碎片。 我最终针对不同任务类型采用了不同的预算值:功能实现用0.7,bug修复用0.5,重构用0.8。 --- ## 第三层:执行层 这是代码真正生成的地方。执行层为每个子任务维护一个独立的上下文窗口,同时通过共享的内存层(见下文)保持对全局项目状态的感知。 ```cpp class ExecutionAgent { public: ExecutionResult execute(const SubTask& task, const ProjectContext& context) { // 构建执行上下文 auto exec_context = build_context(task, context); // 生成初始实现 auto implementation = llm_client_.implement(task, exec_context); // 自我评审循环 for (int attempt = 0; attempt < max_attempts_; ++attempt) { auto review = self_review(implementation, task); if (review.is_acceptable()) { break; } // 根据评审意见修改实现 implementation = llm_client_.revise( implementation, review.critique, exec_context ); } return ExecutionResult{ .implementation = implementation, .confidence = calculate_confidence(implementation, task), .side_effects = detect_side_effects(implementation, context) }; } private: ExecutionContext build_context(const SubTask& task, const ProjectContext& context); ReviewResult self_review(const Implementation& impl, const SubTask& task); LLMClient llm_client_; int max_attempts_ = 3; }; ``` **自我评审循环**是这里的关键创新。执行智能体不仅生成代码——它还用一个独立的提示词来评审自己的输出,专门检查: - 对任务规格的符合性 - 边界条件处理 - 与已知项目约定的一致性 - 潜在的副作用 这将"第一次尝试"的验证通过率从约40%提升到约75%。 --- ## 第四层:验证层 即使有了自我评审,生成的代码也经常无法通过验证。验证层负责实际运行代码并解读结果。 关键洞察:**错误消息本身就是数据**。大多数AI工具在遇到编译错误或测试失败时会崩溃退出。ASH将这些错误解析为结构化的诊断信息,并将其反馈回执行层: ```cpp struct ValidationResult { bool passed; std::vector<Diagnostic> diagnostics; CoverageReport coverage; PerformanceProfile performance; // 关键:将失败原因分类 FailureCategory failure_category; std::string remediation_hint; }; enum class FailureCategory { COMPILATION_ERROR, RUNTIME_ERROR, TEST_ASSERTION_FAILURE, PERFORMANCE_REGRESSION, COVERAGE_INSUFFICIENT, STYLE_VIOLATION }; ``` 对失败原因进行分类改变了执行层的修复方式。`COMPILATION_ERROR`通常意味着语法问题——执行层会专注于修复语法。`TEST_ASSERTION_FAILURE`通常意味着逻辑问题——执行层会重新检查其对任务规格的理解。 --- ## 第五层:内存与上下文 这是整个架构中最难解释的层,但可以说是最重要的层。 LLM的一个基本限制是上下文窗口。对于需要数百个文件和数千行代码的真实项目,你不可能将整个代码库塞入每一次LLM调用。 ASH使用了一个**分层内存系统**: ```cpp class MemorySystem { public: // 工作内存:当前任务的即时上下文 WorkingMemory working; // 情景记忆:最近操作的历史记录 EpisodicMemory episodic; // 语义记忆:项目知识(架构、约定、模式) SemanticMemory semantic; // 程序记忆:已知有效的操作序列 ProceduralMemory procedural; // 为给定任务检索相关上下文 RelevantContext retrieve_for_task(const SubTask& task) { return retriever_.query( task, working, episodic, semantic, procedural ); } private: ContextRetriever retriever_; }; ``` 语义记忆存储经过编码的项目知识: ```cpp struct ProjectKnowledge { std::string architecture_summary; std::vector<CodingConvention> conventions; std::map<std::string, ModuleInterface> module_interfaces; std::vector<DesignPattern> established_patterns; std::vector<KnownPitfall> known_pitfalls; }; ``` `known_pitfalls`字段特别有价值。每当验证失败并且根本原因被诊断出来时,该失败就会被编码为一个已知陷阱,并存储在语义记忆中。未来的执行不会重蹈覆辙。 --- ## 实际效果如何? 经过6个月的迭代,系统在以下方面表现良好: **✅ 运行良好的场景:** - 具有明确接口的独立模块 - 跟随已建立模式的功能添加 - 有清晰错误信息的Bug修复 - 有明确目标的重构 - 测试编写 **⚠️ 仍需人工参与的场景:** - 涉及多个系统的架构决策 - 具有外部依赖的性能优化 - 安全敏感代码(我会审查每一处) - 业务逻辑需要领域专家知识的场景 **❌ 尚未奏效的场景:** - 跨代码库进行大规模重构 - 调试非确定性问题(竞态条件等) - 需要创意权衡的设计工作 吞吐量方面:在一个良好运作的夜晚,系统能够处理8-12个票据(ticket),从规格说明到通过验证的代码。并非所有这些都能在第一次尝试时合并——我通常会在早上进行一次审查会话——但这比我一个人手动处理要多得多。 --- ## 为什么选择C++20? 这个选择引发了一些问题,所以值得解释一下。 原因主要有以下几点: 1. **协程**:C++20的协程对于管理并发智能体任务的执行流程非常合适。执行智能体可以在等待LLM响应时挂起,而不会阻塞整个系统。 2. **概念(Concepts)**:C++20的概念让我能够表达精确的类型约束,这在处理多种类型的任务、结果和上下文时非常有价值。 3. **Ranges**:对于许多数据转换操作,ranges库使代码更具表达力且不易出错。 4. **性能**:整个系统的大部分时间都在等待LLM API响应,所以性能并不是主要因素——但对于内存操作和上下文检索,低延迟确实很重要。 我不是说C++20是实现此类系统的唯一合理选择。但它对我来说效果很好。 --- ## 我学到的最重要的东西 **1. AI自主性的瓶颈是上下文,而不是能力** 现代LLM足够聪明,可以完成大多数编码任务。让它们失败的是缺乏上下文——不了解项目约定、不了解最近的变更、不了解代码库的整体架构。解决上下文问题比提升模型能力更有影响力。 **2. 失败是数据,而不是异常** 大多数AI编码工具将失败视为需要处理的错误,而不是需要学习的信息。当你开始将失败作为数据捕获和存储时,系统会随着时间推移变得更加可靠。 **3. 欠规格说明比过度规格说明更危险** 我的直觉是要尽可能地欠规格说明任务,让AI去填补细节。这是错误的。欠规格说明的任务会产生技术上可行但业务上错误的实现。现在系统在开始执行之前会主动探测欠规格说明的情况。 **4. 分层内存比更大的上下文窗口更重要** 当更大的上下文窗口开始普及时,我以为这会解决我的上下文问题。在某种程度上确实有帮助,但分层内存系统——它能够精确检索相关上下文,而不是将一切都塞入窗口——的效果要好得多。 **5. 人工监督仍然是必要的,但位置不同了** 我并没有消除人工监督。我改变了它的位置:从实时监督(保姆式)变为异步审查(编辑式)。这在主观体验上是一个巨大的改变。 --- ## 下一步 我目前正在研究的问题: - **多智能体协调**:多个执行智能体并行处理同一代码库上的独立任务,而不会产生冲突 - **更好的副作用检测**:当一个实现对系统其他部分产生意外影响时 - **规格说明生成**:将高层路线图条目自动分解为可操作的任务规格 如果有人正在构建类似的系统,我很乐意交流。这个领域移动得非常快,我在这里分享的很多内容可能在6个月后就会显得过时——但底层原则,关于上下文、失败学习和异步监督的原则,我认为会比较持久。 --- *如果你想深入了解某个特定层次,或者想讨论C++20实现的具体细节,请在评论中告诉我。*
# Neon Sovereign Neon Sovereign 是一款原生 C++20/Vulkan 自主软件开发工作站,通过多智能体集群端到端执行软件开发任务,使用 Ollama/GGUF 在本地运行 LLM 权重,无需依赖任何云服务。目前该项目正式进入 Active Alpha 阶段,创建者正在寻找系统工程师和早期测试人员。
Ask HN: 你正在做什么项目?(2026 年 5 月)
这是一个 Hacker News 社区讨论串,开发者在此分享他们当前的项目,包括名为 Clipper 的 Docker 镜像优化工具、名为 RVW 的持续学习 Transformer 变体、名为 Rankr 的排名应用,以及名为 Webhound 的 AI 深度研究工具。
@_jonatantos: 更新后的设置:- warp (terminal) - hermes (harness) - codex / claude / zai / deepseek - raycast (spotlight) - obsidian …
开发者分享了其更新后的设置,包括多个AI模型(Codex、Claude、Zai、DeepSeek)、终端工具和效率应用,并提到了对Devin的测试。