Files
Ransom-s-wake/docs/superpowers/plans/2026-10-06-terrain-varied-landforms.md
T
2026-10-06 21:33:57 +02:00

4.6 KiB

Formes de relief variées — Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Extend the bake tool with polyline canyons, noise-edged outcrops, boulder fields, polyline escarpments and a strata modifier, then bake a terrain_showcase site that demonstrates all five reference landforms and is covered by geometric contract tests.

Architecture: tools/site_terrain_baker.gd gains a Modifier phase (after the primitive sum, with the local gradient) and a per-primitive material override hook. New primitives are nested classes next to the existing ones. A new recipe tools/sites/terrain_showcase_recipe.gd and its baked content/sites/terrain_showcase*.{tres,res} are the demonstration site. Nothing under game/ changes.

Tech Stack: Godot 4.7.2 headless, GDScript, bash scripts/quality_gate.sh.

Spec: docs/briefs/terrain-varied-landforms.md.

Global Constraints

  • Godot binary (Git Bash): export GODOT_BIN="/c/Users/olivi/Downloads/Godot_v4.7.2-stable_win64.exe/Godot_v4.7.2-stable_win64_console.exe"; ripgrep: export PATH="$PATH:/c/Users/olivi/AppData/Local/Programs/Microsoft VS Code/resources/app/node_modules/@vscode/ripgrep/bin".
  • tools/ depends on game/domain/ only; nothing under game/ or content/ references res://tools/ (architecture check).
  • Determinism: every random element is a seeded FastNoiseLite or RandomNumberGenerator; the same recipe bakes byte-identical arrays.
  • content/sites/zone1_vigilant_terrain.res must not change (re-bake and git diff --stat empty for it).
  • Test runners: TEST_COUNT equals the number of _expect calls.
  • Never hand-edit .tres/.res.
  • Commits end with Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>.

Tasks

Task 1: Modifier phase and per-primitive material hook

  • Primitive.material_at(x, z) -> int returning NO_MATERIAL := -1.
  • Modifier.modify(x, z, elevation, gradient: Vector2) -> float.
  • Recipe.modifiers: Array[Modifier].
  • bake() order: sum → modifiers (gradient by central differences on the current array) → floor → slope material → primitive material → patches.
  • Unit tests: a modifier that adds 1 m everywhere shifts the field; a primitive forcing ROCK on a flat plane wins over the slope rule; zone 1 recipe bakes identical to the checked-in .res.

Task 2: Canyon and Escarpment (polyline primitives)

  • Shared static distance_to_path(point, path) -> float, arc_position(point, path) -> Vector2(along_m, total_m) and signed_distance_to_path (sign from the nearest segment's cross product, positive on the right of travel).
  • Edge noise: FastNoiseLite seeded, TYPE_SIMPLEX_SMOOTH, frequency 0.05, amplitude edge_amplitude_m.
  • Tests: Canyon depth on the flat floor, zero far away, follows a corner, closes over one half-width at the ends; Escarpment right side lower by drop_m, left side unchanged.

Task 3: Outcrop and BoulderField

  • Outcrop: e = (sqrt((dx/rx)² + (dz/rz)²) - 1) * mean_radius + noise, delta = height * (1 - smoothstep(-wall_width, 0, e)), rock where delta > 0.3 * height and rock_top.
  • BoulderField: RandomNumberGenerator seeded; disc sampling r = radius * sqrt(u), angle TAU * v; per boulder h = r_b * height_ratio, profile h * sqrt(max(0, 1 - (d / r_b)²)); combine by maxf; early reject outside radius + max_r; rock where profile > 0.
  • Tests: plateau height, rock on top, zero at two radii; boulder field deterministic, zero outside, rock on a boulder, two overlapping boulders do not sum.

Task 4: Strata modifier

  • Formula from the brief §4.3. Tests: a 45° plane with 2 m layers and sharpness 0.9 produces at least two flat runs (|gradient| < 0.1) on a transect; a flat plane is unchanged; sharpness 0 is identity.

Task 5: terrain_showcase recipe, bake, registry

  • Recipe per brief §5; bake_site_terrain.gd RECIPES gains terrain_showcase; bake; preview PNG under docs/briefs/captures/.
  • Verify zone 1 re-bake identical.

Task 6: Contract and integration tests for the showcase

  • tests/contract/run_site_content_tests.gd: new _test_showcase_content() per brief §6.
  • tests/integration/run_site_terrain_integration.gd: showcase loads < 3 s, canyon ray lower than mesa ray, scan reads rock and sand.
  • Foundation test: select_dive_site on the showcase is not required.

Task 7: Docs

  • ADR 0012 amendment, content/README.md, tests/README.md, technical plan status line, brief status.
  • Full gate green.