--- title: "Sprint 22 — Client Briefing" description: "Fix fog system blocky edges, entanglement ratio configuration, seed-based variation" type: sprint status: archived sprint: 22 team: "client" --- # Sprint 22: Wire — Client Tasks **Goal:** Fix the fog regression, wire the authored Sova content into a production population and triangle set, and activate the contamination pacing layer that gives the vertical slice its 30-minute shape. **Branch:** `client` **Agents:** Stig (UI dev), Tyre (arch), Hoshe (QA) ## New Tickets | # | Title | Blocked by | |---|-------|------------| | #569 | Fix fog system: blocky edges and zero visibility in explored areas | — | | #175 | Entanglement ratio configuration | — | | #178 | Seed-based variation | #175 | Use `tooling/db/ticket show ` for full details on any ticket. ## Key Decisions - `decisions/perception.md` — D-011 (fog of perception, non-negotiable), D-015 (vision cone, 120° forward arc, physiological basis), D-059 (fog shader spec: 3 visual states, smooth gradients, explored-tile overlay), D-066 (dual-scale grid: gradient edge = 6-8 sim tiles) - `decisions/content.md` — D-029 (population entanglement ratio 30/50/20, variable per seed) - `decisions/architecture.md` — D-010 (deterministic simulation, seed-based repeatability), D-020 (client is a dumb renderer — reads ObserverSnapshot, sends PlayerInput) ## Notes **#569 — Fix fog system: blocky edges and zero visibility in explored areas** - This ticket carries over uncommitted changes already on `main`. The server-side changes (vision_cone.rs simplification to Forward-only, test updates) passed CI and are green. The client-side changes (fog.gdshader, fog_state.gd) are the failing part — two persistent visual regressions: 1. **Blocky stair-stepped edges** at the vision cone boundary — tile-sized steps instead of a smooth gradient. 2. **Zero visibility in explored areas** — previously seen tiles appear near-black instead of showing art through a light overlay. - **Spec (D-059 + D-015 + D-066):** Three visual states: - **Forward cone (clear):** Nearly transparent, 6-8 sim tile soft gradient at the cone boundary. No tile-stepping. - **Explored (light fog):** ~25-30% opacity overlay. ALL underlying art, sprites, furniture, NPCs visible. Subtle animated Perlin noise (8-10s cycle). Exploration memory is permanent — once seen, always shown in this state. - **Unexplored:** Solid near-black `#12141a`. No art, no information. - **Files to work in:** - `client/shaders/fog.gdshader` — the Gaussian blur kernel (7x7, sigma 2.0) is already there. The issue is likely in the `smoothstep` clarity ramp or the `exp_fade` blend. The `fog_alpha` at 0.28 may be too low for explored tiles when `vis = 0`. - `client/scripts/autoloads/fog_state.gd` — grow-only bounds and exploration preservation are in place. Check that `EXP_EXPLORED = 128` is being written correctly for tiles that leave the forward cone. - **Diagnostic approach:** Add a temporary debug mode that renders the `exploration_tex` raw (bypassing fog) to verify the texture is being populated correctly before debugging the shader blend. If explored tiles are showing `EXP_UNEXPLORED = 0` when they should be `EXP_EXPLORED = 128`, the bug is in `fog_state.gd`. If they're correct in the texture but invisible in the render, the bug is in the shader. - **Smooth gradient:** The 7x7 Gaussian is in `sample_visibility()`. The `smoothstep(0.0, 0.85, vis)` ramp controls the gradient width. Try `smoothstep(0.1, 0.9, vis)` for a wider soft zone. The D-066 spec says 6-8 sim tiles — at tile_size pixels per tile, the blur kernel needs to spread across that many tiles in UV space. - **Acceptance (all must pass):** - Forward cone edge has a smooth 6-8 tile gradient — no visible tile-stepping at any camera zoom. - Explored tiles outside the cone show underlying art at approximately 25-30% fog overlay. - Explored tiles never revert to unexplored black when the player turns or moves. - Unexplored tiles are solid `#12141a`. - Transitions between all three states are smooth. - Server tests remain green (`cargo test -p server`). - Visual QA sign-off from Araminta before PR merge (she owns #563 which depends on this landing first). **#175 — Entanglement ratio configuration** - Server-side resource. The 30/50/20 flat/mundane/intrigue split (D-029) needs to be a configurable resource that `#176` (NPC pool generation on the server team) can read. - This ticket is assigned to the client team because the configuration surface is a client-facing concern — the seed screen / character selection will eventually expose this to the player, and the config needs to be representable in the ObserverSnapshot or startup protocol. - For v0.1: implement `EntanglementConfig` as a `Resource` in the server (coordinate with Dudley on the struct definition — server team's #176 will consume it). The client side of this ticket is: add a `world_seed: u64` field to the session startup message (if not already present in the IPC handshake), so the server can seed `SimRng` deterministically from it. - Check `server/src/bridge/types.rs` for the existing startup/handshake message structure. The seed should flow: character selection screen (client) → startup IPC message → server reads seed → `SimRng::from_seed(seed)` → `EntanglementConfig` sampled from seeded RNG. - Coordinate with server team: they own the `EntanglementConfig` struct and its consumption in #176. Client team owns the seed-carrying protocol field and any UI stub. - Acceptance: the startup IPC message carries a `world_seed` field; server logs confirm it is received and used to seed `SimRng`. **#178 — Seed-based variation** - Depends on #175. Per D-029: entanglement rate varies per seed to prevent player metagaming calibration across playthroughs. - The variation is seeded in `EntanglementConfig` at startup: `flat_ratio`, `mundane_ratio`, `intrigue_ratio` are not hardcoded 30/50/20 but sampled from the seeded RNG within a range (e.g., flat: 25-35%, mundane: 45-55%, intrigue: 15-25%). The exact ranges should keep the ratios summing to 100% and maintain the intent of D-029 (majority unentangled, minority intrigue). - This ticket: implement the seeded sampling of `EntanglementConfig` values from `SimRng`. Wire it so two game starts with the same `world_seed` produce identical `EntanglementConfig`, and different seeds produce observably different ratios. - Acceptance: a test asserts that `EntanglementConfig::from_rng(seed_A) != EntanglementConfig::from_rng(seed_B)` for at least 90% of random seed pairs, AND `EntanglementConfig::from_rng(seed_A) == EntanglementConfig::from_rng(seed_A)` (deterministic). ## Dependency Chain ``` #569 (fog fix) — standalone, start immediately [Araminta's #563 blocks on this — do not merge #563 until #569 is in review] #175 (entanglement ratio config) — standalone, coordinate with server team on struct definition → #178 (seed-based variation) ``` ## PR Workflow When ready to submit, create a PR with `tea` CLI: ```bash tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "fix(client): Sprint 22 — fog rendering and seed config" --description "body" --base main --head client ```