fix(@projects/@magic-civilization): 🐛 remove hydrology rendering

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-05-01 00:22:00 -04:00
parent fcf4b402be
commit 0e92eec0b4

View file

@ -12,13 +12,11 @@ import {
import { classifyTerrain, TERRAIN_MAP } from "../../utils/worldGen/terrain";
import type { GridCell } from "../../utils/worldGen/terrain";
import { WhittakerPlot } from "./WhittakerPlot";
// TODO(p1-46): replace deleted floraSpecies.ts with WASM bindings (WasmFloraIndex / tileFloraJson)
// floraSpecies.ts deleted by p1-48 per Rail 1 — no TS reimplementation permitted.
// TODO(p1-46): replace deleted faunaSpecies.ts with WASM bindings (WasmFaunaIndex / tileFaunaJson)
// faunaSpecies.ts deleted by p1-49 per Rail 1 — no TS reimplementation permitted.
// TODO(p1-46): replace with WASM bindings — hydrology.ts deleted per Rail 1 (p1-47)
type HydroState = Record<string, never>;
const computeHydrology = (_grid: unknown): HydroState[][] => [];
// Wave-E TODO (p1-46): wire WasmFloraIndex / WasmFaunaIndex / tileHydrologyJson
// from the api-wasm bundle once p1-52 lands the build fix. Until then, the
// integrated Lab renders only the layers whose impl lives entirely in the
// design app (biome classifier + minerals + Whittaker plot + flora glyphs).
// Per-layer playgrounds for hydrology, ecology, etc. live at /world-gen/<layer>.
// ── Canvas layout constants ───────────────────────────────────────────────────
@ -58,18 +56,14 @@ for (const mod of Object.values(DEPOSIT_MODS)) {
type LabState = {
elevation: number; moisture: number; temp: number; ridginess: number;
floraOn: boolean; floraDensity: number;
mineralsOn: boolean; mineralRichness: number;
faunaOn: boolean; faunaActivity: number;
hydrologyOn: boolean;
floraOn: boolean; floraDensity: number;
mineralsOn: boolean; mineralRichness: number;
};
const DEFAULT: LabState = {
elevation: 0.65, moisture: 0.72, temp: 0.72, ridginess: 0.30,
floraOn: true, floraDensity: 1.0,
mineralsOn: false, mineralRichness: 0.5,
faunaOn: false, faunaActivity: 0.5,
hydrologyOn: false,
};
// ── Drawing helpers ───────────────────────────────────────────────────────────
@ -246,54 +240,6 @@ function buildGrid(st: LabState): GridCell[][] {
// ── Canvas render ─────────────────────────────────────────────────────────────
function drawRiverPass(
ctx: CanvasRenderingContext2D,
grid: GridCell[][],
hydro: HydroState[][]
): void {
// Flat-top hex neighbor offset tables (matching hydrology.ts)
const EVEN_OFF: [number, number][] = [
[ 1, 1], [ 1, 0], [ 0, -1], [-1, 0], [-1, 1], [ 0, 1],
];
const ODD_OFF: [number, number][] = [
[ 1, 0], [ 1, -1], [ 0, -1], [-1, -1], [-1, 0], [ 0, 1],
];
const rows = grid.length;
const cols = grid[0]?.length ?? 0;
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
const h = hydro[r][c];
if (!h.isRiver || h.flowOut === null) continue;
const offsets = c % 2 === 1 ? ODD_OFF : EVEN_OFF;
const [dc, dr] = offsets[h.flowOut];
const nr = r + dr, nc = c + dc;
if (nr < 0 || nr >= rows || nc < 0 || nc >= cols) continue;
const { x: x0, y: y0 } = hexToPixel(c, r, HEX_SIZE);
const { x: x1, y: y1 } = hexToPixel(nc, nr, HEX_SIZE);
const streamW = 0.8 + Math.log2(h.drainageArea + 1) * 0.7;
const blueT = Math.min(1, h.streamOrder / 5);
const r_ = Math.round(120 + (1 - blueT) * 80);
const g_ = Math.round(180 + (1 - blueT) * 30);
const b_ = 255;
ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.quadraticCurveTo(
(x0 + x1) / 2 + (y1 - y0) * 0.15,
(y0 + y1) / 2 - (x1 - x0) * 0.15,
x1, y1
);
ctx.strokeStyle = `rgba(${r_},${g_},${b_},0.65)`;
ctx.lineWidth = streamW;
ctx.lineCap = "round";
ctx.stroke();
}
}
}
function renderCanvas(ctx: CanvasRenderingContext2D, grid: GridCell[][], st: LabState): void {
ctx.clearRect(0, 0, CANVAS_W, CANVAS_H);
@ -323,13 +269,7 @@ function renderCanvas(ctx: CanvasRenderingContext2D, grid: GridCell[][], st: Lab
}
}
// 3. Hydrology: river bezier pass
if (st.hydrologyOn) {
const hydro = computeHydrology(grid);
drawRiverPass(ctx, grid, hydro);
}
// 4. Flora — three global Poisson passes: ground → understory → canopy
// 3. Flora — three global Poisson passes: ground → understory → canopy
if (st.floraOn) {
const bigR = Math.hypot(CANVAS_W, CANVAS_H) / 2 + 20;
const ccx = CANVAS_W / 2, ccy = CANVAS_H / 2;
@ -371,15 +311,7 @@ function renderCanvas(ctx: CanvasRenderingContext2D, grid: GridCell[][], st: Lab
}
}
// 5. Fauna — species-driven glyphs
if (st.faunaOn) {
for (let row = 0; row < ROWS; row++) {
for (let col = 0; col < COLS; col++) {
// TODO(p1-46): replace with WasmFaunaIndex.tileFaunaJson() call
void grid[row][col]; void hexToPixel(col, row, HEX_SIZE);
}
}
}
// Fauna pass returns in Wave E (p1-46) when WASM bindings land.
}
// ── Styled components ─────────────────────────────────────────────────────────
@ -542,11 +474,6 @@ const StatPill = styled.span<{ $hi: boolean }>`
color: ${p => p.$hi ? "#8bc96a" : "inherit"};
`;
const InfoRow = styled.div`
font-family: ${t.font.mono};
font-size: 11px;
color: ${t.text.muted};
`;
// ── SliderControl ─────────────────────────────────────────────────────────────
@ -581,11 +508,6 @@ export function Lab(): React.ReactElement {
const terrainId = classifyTerrain(Math.max(0.35, st.elevation), st.moisture, cold, 0.0, st.ridginess);
const terrain = TERRAIN_MAP.get(terrainId);
// TODO(p1-46): replace with WasmFaunaIndex.tileFaunaJson() call
const faunaNames: string[] = [];
// TODO(p1-46): replace with WasmFloraIndex.tileFloraJson() — flora layer display deferred to Wave E
useEffect(() => {
const ctx = canvasRef.current?.getContext("2d");
if (!ctx) return;
@ -597,9 +519,10 @@ export function Lab(): React.ReactElement {
<PageHeader>
<PageTitle>Terrain Dimensions Lab</PageTitle>
<PageSub>
Adjust biome levers to navigate the parameter space. Toggle overlays to stack
minerals, flora (ground understory canopy), and fauna glyphs. Flora renders
as a continuous cross-tile point cloud trees straddle hex borders naturally.
Integrated view of the layered Earth model: biome classifier + minerals + flora
(ground understory canopy) + Whittaker T×P plot. Hydrology, fauna, and
species-driven flora overlays return in Wave E once `p1-52` lands the WASM
bundle. For dedicated layer playgrounds see /world-gen/&lt;layer&gt;.
</PageSub>
</PageHeader>
@ -631,19 +554,6 @@ export function Lab(): React.ReactElement {
<SliderControl label="Richness" value={st.mineralRichness} min={0.1} max={1.0} step={0.05} onChange={v => set({ mineralRichness: v })} />
)}
</ToggleRow>
<ToggleRow>
<ToggleBtn $on={st.faunaOn} onClick={() => set({ faunaOn: !st.faunaOn })}>
<ToggleDot $on={st.faunaOn} /> Fauna
</ToggleBtn>
{st.faunaOn && (
<SliderControl label="Activity" value={st.faunaActivity} min={0.1} max={1.0} step={0.05} onChange={v => set({ faunaActivity: v })} />
)}
</ToggleRow>
<ToggleRow>
<ToggleBtn $on={st.hydrologyOn} onClick={() => set({ hydrologyOn: !st.hydrologyOn })}>
<ToggleDot $on={st.hydrologyOn} /> Hydrology
</ToggleBtn>
</ToggleRow>
</ControlGroup>
</Controls>
@ -663,27 +573,6 @@ export function Lab(): React.ReactElement {
<span>Def +{terrain.defense_bonus}%</span>
<span>Move ×{terrain.movement_cost}</span>
</InfoStats>
{/* TODO(p1-46): flora layer rendering restore when WasmFloraIndex is wired
{hasFlora && (
<>
{floraCanopy.length > 0 && (
<InfoRow>Canopy · {floraCanopy.join(" · ")}</InfoRow>
)}
{floraUnderstory.length > 0 && (
<InfoRow>Understory · {floraUnderstory.join(" · ")}</InfoRow>
)}
{floraGround.length > 0 && (
<InfoRow>Ground · {floraGround.join(" · ")}</InfoRow>
)}
{floraFungal.length > 0 && (
<InfoRow>Fungi · {floraFungal.join(" · ")}</InfoRow>
)}
</>
)}
*/}
{faunaNames.length > 0 && (
<InfoRow>Fauna · {faunaNames.join(" · ")}</InfoRow>
)}
</InfoCard>
)}
</CanvasWrap>