25+ years of pathfinding problems with C++

Lobsters Hottest News

Summary

The Engineering Director of Age of Empires provides an in-depth analysis of the technical debt in the series' pathfinding system over the past 25 years, pointing out that legacy code, dynamic map mechanics, and floating-point errors caused by SIMD instruction sets replacing x87 extended precision are the root causes of classic bugs such as units clipping through walls.

<p><a href="https://lobste.rs/s/mi6vac/25_years_pathfinding_problems_with_c">Comments</a></p>
Original Article Export to Word Export to PDF
View Cached Full Text

Cached at: 05/11/26, 01:08 PM

TL;DR: The C++ pathfinding system in the 25-year-old *Age of Empires* series is deeply affected by dynamic map mechanics, lost knowledge in legacy code, and floating-point precision errors arising from SIMD instruction sets replacing the 80-bit x87 extended precision. These issues make classic problems like units clipping through walls extremely hard to fully eliminate. ## Background and Community Feedback I'm Ry, Engineering Director at Forgotten Empires and a long-time fan of *Age of Empires*. My daily work largely revolves around a codebase older than I am, spanning most classic remasters and some development for *Age of Empires 4*. This article focuses mainly on *Age of Empires 2* and its HD/Definitive editions. Feedback on pathfinding is almost entirely negative—but understandably so. The most valuable reports often include comparisons to the original or a previous version, helping us quickly identify regressions. It's even better if players can provide reproducible cases. *Age of Empires* uses deterministic simulation with replay support. When players attach a recorded game and point to the exact moment of the issue, we get a perfect reproduction environment, drastically reducing debugging cost. ## Unique Complexity of *Age of Empires* Pathfinding The pathfinding in *Age of Empires* is far from conventional. Units collide with each other while moving, stop, and replan their paths. The system strictly forbids pushing or overlapping (except for friendly units within a formation). The formation system introduces a second layer of movement logic, and the interaction between the two dramatically increases complexity. On top of that, maps are completely random and dynamically changing; any building or terrain can be altered at any time. The system is partially grid-based: units are not locked to tiles, but obstacles like buildings and water are strictly grid-aligned. ## Why Not Simply Copy *StarCraft 2*? *StarCraft 2*'s pathfinding is widely praised, largely because Blizzard simplified the problem: they used fixed maps, adopted steering behaviors, and allowed units to slightly overlap and slide past each other. This design is visually smooth and generally feels better to players. However, the *Age of Empires* team couldn't just adopt that approach. We're working on remasters and definitive editions, not a brand-new game. Adapting *StarCraft 2*'s pathfinding logic would require rewriting most of the low-level game code. For *Age of Mythology: Retold*, we did experiment with Boy's algorithm, but results were mixed. More importantly, while the community complains about pathfinding, they also rely on the unique tactical gameplay it creates. For instance, one player used a controller to emulate mouse input and precisely moved a fishing boat to block a knight charge at the last moment, saving the game. With "smoother" pathfinding, such brilliant micro moments would vanish. ## 25+ Years of Code and Lost Knowledge This C++ codebase is over 25 years old. The original developers have all left the team, leaving behind only a handful of online articles, code comments, and log entries. By legacy-code standards, the documentation is decent, but the development span covers over two decades, multiple teams, and the pathfinding system has been modified again and again. Even trickier: we lost the source code change history when we inherited the code, making it impossible to trace the intent behind early edits. The community once optimized pathfinding by reverse-engineering the executable and directly patching the assembly code, and that version was hailed as the "gold standard" by players. However, the developer of that patch vanished without a trace, so we never obtained the changes—putting us at a disadvantage from the start. Internally, we constantly find ourselves in a loop of "fix one bug, introduce three regressions." Moreover, the code is full of undocumented "ritualistic programming": certain functions must be called in a specific order, or connected systems silently fail, forcing developers to rely on rote memorization. ## Short-Distance Pathfinding Algorithm Uncovered The full pathfinding system is massive; here I'll break down only the short-distance algorithm, which accounts for about 10% of the logic. The algorithm has no formal documentation but ran efficiently on 1999-era hardware and worked most of the time. Its core flow: 1. **Collect obstacles**: Define a rectangular search area between start A and target B, extract all axis-aligned rectangular obstacles. 2. **Shrink space**: Shrink the pathfinding unit to a point, then inflate that volume onto all obstacles, reducing obstacle avoidance to point-vs-rectangles. 3. **Build convex hulls**: Use the Gift Wrapping Algorithm to construct one or more convex hulls around the obstacles. 4. **Escape and ray tests**: If start and target lie in different hulls, fire rays from the start in the four cardinal directions. If a ray hits an obstacle, it bounces sideways until it escapes the current hull. 5. **Hug edges**: After escaping, the unit moves along the convex hull’s edges. At each vertex, a ray is fired toward the target; if blocked, it continues hugging edges and retesting until reaching the target. 6. **Smooth path**: Redundant waypoints are removed via brute-force testing to ensure the new path does not overlap obstacles. **Edge cases**: If start and target are in the same or different hulls, the system essentially performs a bi-directional search, firing rays from both ends to escape hulls and then connecting the paths. If a hull exceeds the search area, the area is expanded and the process retried. If the unit is completely surrounded (no path), the search area is enlarged and random attempts are made within array bounds, with a maximum of 64 iterations or until all unvisited vertices are exhausted. Long-distance pathfinding uses an A* algorithm over intermediate navigation points (an early form of hierarchical pathfinding), which is extremely fast and was key to maintaining overall performance back then. ## Floating-Point Precision Disaster and Wall-Clipping Bugs The algorithm has a classic flaw: units occasionally walk right through walls or buildings. This is a textbook case of geometric precision errors. When building the convex hull with the Gift Wrapping Algorithm, it must decide whether three points make a "left turn" or "right turn." When points are extremely close or nearly collinear, insufficient floating-point precision can cause a wrong turn decision. That erroneous result can make the convex hull fail to fully enclose the obstacle, instead cutting into it and generating a path straight through the wall. *Age of Empires 2*, *Age of Empires 3*, and *Age of Mythology* all suffer from this, and recently the frequency has strangely increased. The original developers tried removing points that were too close together, but that didn't cover all cases. During *Age of Empires 3: Definitive Edition* development, one developer upgraded `float` to `double` (64-bit), which improved precision and reduced the bug's occurrence, but still failed to eliminate it. Other games with similar geometry algorithms have commonly run into the same wall-clipping phenomenon. ## SIMD Instruction Sets and the Trade‑off of 80‑bit Extended Precision While debugging *Age of Mythology: Extended Edition*, I manually turned off compiler optimizations, which incidentally disabled SIMD instruction sets and forced the compiler to fall back to IA32 instructions. To my surprise, the wall‑clipping bug vanished completely. The root cause is **80‑bit extended floating‑point precision**. The early x87 FPU hardware kept extra precision during intermediate calculations using ultra‑wide registers. As SIMD technology spread, architectural choices traded away that extended precision for performance. This trade‑off makes precision state unpredictable: the moment an intermediate result is stored into a temporary variable or a register is spilled, the extra precision is lost instantly. For the Gift Wrapping Algorithm, which is extremely sensitive to collinearity checks, such tiny precision fluctuations are enough to cause a left‑turn/right‑turn misjudgment, leading to a malformed convex hull. When developers moved to SIMD to chase performance, they likely didn't realize the profound impact of precision sacrifice on geometric algorithms. That's why many old games see ancient bugs reappear on modern compilers or architectures. The pathfinding problem isn't just a challenge of algorithm design—it's a tapestry woven from hardware evolution, compiler behavior, and over two decades of code debt. Source: https://www.youtube.com/watch?v=lEBQveBCtKY

Similar Articles

@AYi_AInotes: 卧槽,有大神直接用Claude Code,复刻出一整套完整游戏开发工作室。 GitHub 1.8万stars,免费开源,项目名叫Claude Code Game Studios, 48个AI智能体1:1还原线下工作室全岗位,从创意总监到关…

X AI KOLs Timeline

卧槽,有大神直接用Claude Code,复刻出一整套完整游戏开发工作室。 GitHub 1.8万stars,免费开源,项目名叫Claude Code Game Studios, 48个AI智能体1:1还原线下工作室全岗位,从创意总监到关卡设计师全覆盖。 36条斜杠指令一键启动全流程,适配Godot Unity Unreal三大游戏引擎。 自带自动化校验钩子、分路径编码规则、28套行业标准文档模板,架构拉满。 所有AI只做梳理方案不擅自操作,决策权全程握在自己手里。 克隆仓库一键启动,MIT开源可商用,凭空拥有一支专业游戏开发团队。 老规矩GitHub地址评论区自取!

@lxfater: Researchers from Tsinghua University have surpassed the algorithm Google Maps has used for 41 years. From 1984 to the present, no one had managed to do so in 41 years. That algorithm is called Dijkstra. It doesn't matter if you haven't heard of it; you use it every day. However, it has been stuck for 40 years without breakthrough because of a mathematical sorting barrier standing in the way...

X AI KOLs Timeline

Researchers from Tsinghua University have developed a new shortest-path algorithm with O(m log^{2/3} n) complexity, surpassing Dijkstra's algorithm, which had been considered theoretically optimal for 41 years.

Interesting Map Geometry and Mathematics

Hacker News Top

Ultima Ratio Regum 0.11 Update #57 discusses solving an edge case in procedural map generation where damage spreading could leave map clues floating isolated. The developer explores computational challenges with flood-fill algorithms and organic damage propagation techniques.

How Rockstar fit an entire city into PlayStation 2 memory

Lobsters Hottest

The article provides a detailed analysis of how Rockstar achieved a seamless open world in GTA III on the PlayStation 2 with only 32MB of RAM through streaming loading, LOD, memory fragmentation management, and disc layout optimization, setting a benchmark for the industry.