The rewrite (D-049) starts from a clean slate; this commit is the reference implementation of the graduated design. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
57 lines
5.2 KiB
Markdown
57 lines
5.2 KiB
Markdown
# MapGenerator.cs - Architecture & Historical Decisions
|
||
|
||
**Date:** March 2026
|
||
**Purpose:** Generates the 2D topographical blueprint (Topography, Biomes, Cities, and Road Networks)
|
||
to be parsed and translated into a 3D Voxel World.
|
||
|
||
> ⚠ **Historical document — read it as a record of decisions, not as current spec.** It was written
|
||
> when the map was 4096², and references to that size throughout should be read as "the map size of
|
||
> the day". **Map size is now config-driven** (`MapProfile` in `ServerConfig.json`; 8192 by default),
|
||
> and the reasoning it describes — scaling everything off `MapSize` rather than hardcoding — is
|
||
> exactly what makes that work.
|
||
>
|
||
> For the current behaviour see `Tools/Scripts/README.md`. For design rationale and the decisions
|
||
> behind the project, see the design vault.
|
||
|
||
---
|
||
|
||
## 1. Topography & The Impact Crater
|
||
* **Base Generation:** Uses `FastNoiseLite` to generate standard heightmaps and temperature maps, which drive dynamic biomes.
|
||
* **Dynamic Sea Level:** Sea level is calculated based on the temperature map (simulating ice caps/equatorial swelling).
|
||
* **The Crater:** A massive (radius 400) blast zone is forced along the northern coast. Surrounding it is a `Biome.Wasteland` with a noise-driven "fray" on its borders.
|
||
* **Design Choice:** We allowed the crater to occasionally spawn slightly inland rather than strictly on the beach. This creates natural topographical "pinch points" that will result in highly memorable, claustrophobic 3D driving mechanics.
|
||
|
||
## 2. City Placement & The Capitol Tether
|
||
* **The Challenge:** The Capitol City must spawn inside the radioactive Wasteland, but it MUST be connected to the contiguous mainland for the A* highway to reach it. Early iterations spawned the Capitol underwater or stranded it on offshore islands caused by the Wasteland noise bleeding over the ocean.
|
||
* **The Solution (Smart Tiered Spawner):** We abandoned a rigid `while` loop in favor of a tiered attempt system.
|
||
* **Tier 1:** Searches for ideal (Wasteland + Coastal + Mainland).
|
||
* **Tier 2:** Relaxes the coastal requirement.
|
||
* **Tier 3:** Scans the entire array for the closest valid pixel to the impact center.
|
||
* **Tier 4 (Doomsday):** Walks strictly south until it hits the mainland.
|
||
|
||
## 3. The Pathfinding Wars (A* Road Optimization)
|
||
The road network generation was the hardest logistical hurdle. Standard grid-based `AStarGrid2D` math does not scale cleanly to a 4096 map.
|
||
|
||
### Phase 1: The 16-Minute Bottleneck
|
||
* **The Flaw:** To force the highway to create a large loop connecting our 3 Hubs, we used an `ApplyRepulsion` function that penalized pixels in a 400px radius around the first drawn road.
|
||
* **The Math:** Repelling a 2,000-point path with a 400px radius resulted in over **1.3 Billion** nested loop iterations. The CPU choked, and generation took 11–16 minutes.
|
||
* **The Result:** Unusable generation times, extreme stair-stepping (zig-zagging), and roads cutting straight over mountains.
|
||
|
||
### Phase 2: The Speedrun & The Double-Back
|
||
* **The Flaw:** We ripped out the repulsion completely to save CPU time, dropping the render to **1 minute**.
|
||
* **The Result:** Because A* is deterministic, the pathfinder just used the exact same pixels to return to the start, completely breaking the 3-point loop and causing the highway to double back on itself.
|
||
|
||
### Phase 3: The Over-Engineered Spaghetti (The LLM Trap)
|
||
* **The Flaw:** We brought in an external LLM to fix the pathing. It introduced a "Midland Sweet Spot" to force roads off the coast, and a "Daisy-Chain" mechanic for branch roads.
|
||
* **The Result:** The highway started tracing narrow elevation contour lines like a drunk driver. The branch roads turned into a game of "Snake," meandering wildly to connect to each other instead of taking logical paths to the highway. Furthermore, adding a soft weight to the crater combined with our loop repulsion created a "Wasteland Phobia" where the A* algorithm mathematically folded and refused to complete the loop.
|
||
|
||
### Phase 4: The Tactical Revert (Our Final State)
|
||
We executed a deliberate tactical revert, stripping out the over-engineered LLM spaghetti and keeping only robust, simple math:
|
||
1. **Direct Branches:** Black roads path directly to the closest highway pixel. No daisy-chaining.
|
||
2. **The Iron Curtain Repulsion:** We restored a `+10000f` penalty to old highway segments with a radius of 120px to physically force the 3-point loop. We optimized it by only applying the penalty to every `step` (half the radius) pixel. Render time remains at ~1 minute.
|
||
3. **Simple Elevation Weights:** Instead of a complex U-curve, we use `Mathf.Pow(normalizedElevation, 3.0f) * 400.0f` to aggressively punish mountains, and a flat `+15.0f` penalty to gently push roads off the beach sand.
|
||
|
||
## 4. The AAA Smoothing Pipeline
|
||
Standard A* creates jagged, octagonal stair-steps that look terrible in a 3D voxel world. We completely eradicated this using a 2-step geometric smoothing pipeline:
|
||
1. **Ramer-Douglas-Peucker (RDP):** Decimates the raw A* path, removing thousands of useless straight-line grid points and leaving only the major turns.
|
||
2. **Chaikin's Algorithm:** Performs 4 passes of corner-cutting on the decimated points, resulting in buttery-smooth, sweeping, AAA-style highway curves ready for 3D mesh generation.
|