feat(web): render canonical living hedge maze walls
This commit is contained in:
@@ -2591,3 +2591,263 @@ The following planning-time request defines this milestone:
|
||||
breach variants, and the density and palette defined in `docs/UI_STYLE.md`.
|
||||
This satisfies the required owner review. Runtime integration remains a
|
||||
separately planned milestone.
|
||||
|
||||
## Milestone 024 — Runtime living hedge rendering
|
||||
|
||||
**Status:** `IN_PROGRESS`
|
||||
|
||||
### Objective
|
||||
|
||||
Replace the maze's simple green wall strokes and provisional perseverance
|
||||
damage styling with the project-owner-approved Milestone 023 living-hedge SVG
|
||||
family, so intact walls, impacts, and permanent breakthroughs form one varied,
|
||||
legible top-down environment on player and observer screens without changing
|
||||
authoritative gameplay or exposing hidden state.
|
||||
|
||||
### Scope
|
||||
|
||||
- Do not start this milestone until every preceding milestone is `COMPLETE`.
|
||||
Use only the intact families, impact sequence, breakthrough frame, breached
|
||||
variants, density, and palette approved in Milestone 023. Any substantive art
|
||||
redesign requires returning to a separately planned sample-review milestone.
|
||||
- Reconcile `docs/UI_STYLE.md`, `docs/PLAYER_UI.md`, and `ARCHITECTURE.md` with
|
||||
the runtime hedge-rendering contract before changing browser assets.
|
||||
- Derive a compact runtime SVG sprite from
|
||||
`docs/hedge-sample-library.svg`; keep the review source untouched and do not
|
||||
make runtime pages depend on files under `docs/`. Preserve stable semantic
|
||||
symbol identifiers where practical and remove comparison-sheet-only content.
|
||||
- Package the runtime sprite locally with the compressed web application. Do
|
||||
not add remote images, fonts, libraries, network requests, embedded raster
|
||||
data, or runtime SVG scripts.
|
||||
- Replace the four solid CSS cell borders with a dedicated decorative edge
|
||||
layer that draws each server-provided closed wall once. Canonicalize shared
|
||||
edges so two adjacent visible cells do not produce doubled foliage, darker
|
||||
overlaps, seams, or inconsistent variants.
|
||||
- Draw walls at projection boundaries only from the current server-provided
|
||||
cell and passage bits. Do not assume what lies beyond an unseen edge, fill
|
||||
unknown space, retain an explored map, or generate decorative geometry for
|
||||
cells absent from the current projection.
|
||||
- Select among the six approved intact variants with a documented deterministic
|
||||
function of the currently visible canonical wall edge and orientation. The
|
||||
same edge must keep its variant across rerenders and appear consistently to
|
||||
both players and observers when their approved projections include it, with
|
||||
no new protocol or authoritative game-state field.
|
||||
- Rotate or mirror approved symbols for north, east, south, and west while
|
||||
preserving their shared-edge center, non-directional lighting, foliage
|
||||
thickness, and joins. Compose approved corner, crossing, and end treatments
|
||||
only from wall edges explicitly present in the received projection.
|
||||
- Preserve exact maze geometry and hit testing. Decorative foliage may extend
|
||||
visually into neighboring cells by a bounded amount, but it cannot change
|
||||
traversability, pointer targets, player focal-point calculation, map bounds,
|
||||
projection translation, or page overflow.
|
||||
- Keep hedge artwork behind players, keys, doors, artifacts, landmarks, and
|
||||
interaction feedback. Leaves and branches must remain recognizable at 34,
|
||||
40, and 46 CSS-pixel cells without obscuring the passage center or reducing
|
||||
object and player contrast.
|
||||
- Connect Milestone 022 server-approved impact stages one through four to the
|
||||
matching approved static SVG frames on the exact visible wall that received
|
||||
the impact. Preserve the existing bounded timer, event correlation,
|
||||
deduplication, and cleanup behavior; the browser never increments damage or
|
||||
predicts a breakthrough locally.
|
||||
- Present the approved breakthrough frame only when justified by the matching
|
||||
authoritative response and transition to one of the approved permanent
|
||||
breached variants when the received `opened` passage state changes. Derive
|
||||
this transition only from current and immediately preceding visible
|
||||
server-approved state, held in bounded memory and discarded on projection
|
||||
replacement or reset.
|
||||
- Render one canonical permanent breach decoration for a shared opened edge so
|
||||
the gap aligns from both adjacent cells and from both traversal directions.
|
||||
Breached foliage must remain visible while the opened edge is in the current
|
||||
projection and disappear when that edge is no longer projected.
|
||||
- Preserve reduced-motion behavior by using the approved static impact frames
|
||||
and an immediate permanent breach state, with no shaking, swaying, moving
|
||||
leaves, or travel animation. Normal motion may use restrained transforms of
|
||||
the approved shapes but must not allocate unbounded particles or DOM nodes.
|
||||
- Use bounded reusable DOM or CSS structures. A rerender must have a documented
|
||||
maximum number of hedge elements derived from the maximum visible projection,
|
||||
remove obsolete edges, and never accumulate duplicate SVG instances,
|
||||
animation timers, styles, or event listeners.
|
||||
- Apply the same hedge family to the observer's full-map renderer without
|
||||
changing its read-only behavior, pan or zoom controls, minimum viewport, or
|
||||
authoritative snapshot contents. At overview zoom levels, simplify details
|
||||
gracefully while retaining continuous wall and breached-gap silhouettes.
|
||||
- Preserve Russian player-facing copy, Milestone 020 visual feedback,
|
||||
Milestone 021 focal-point positioning, Milestone 022 game rules, offline
|
||||
operation, accessibility, and existing firmware and filesystem budgets.
|
||||
|
||||
### Deliverables
|
||||
|
||||
- Updated runtime hedge-rendering, layering, variation, projection-safety, and
|
||||
reduced-motion contracts in canonical and supporting documentation.
|
||||
- Optimized local runtime SVG sprite derived reproducibly from the approved
|
||||
Milestone 023 source, with deterministic size and dependency validation.
|
||||
- A deduplicated decorative edge renderer for player and observer maps using
|
||||
the six intact hedge variants and approved joins and end treatments.
|
||||
- Runtime wiring for the four approved impact stages, breakthrough frame, and
|
||||
three deterministic permanent breached variants.
|
||||
- Deterministic browser tests, asset checks, host regression results, size
|
||||
evidence, and representative mobile, desktop, observer, and physical-device
|
||||
visual verification.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
1. Every closed edge in the received player or observer projection is rendered
|
||||
with an approved living-hedge SVG variant rather than a solid CSS green
|
||||
border. Visible leaves, twigs, irregular foliage, depth tones, and outline
|
||||
remain recognizable at supported gameplay scales. Horizontal and vertical
|
||||
hedge center lines coincide with their authoritative cell edges, never pass
|
||||
through cell centers, and leave open floor at least as clear as the former
|
||||
solid green wall presentation.
|
||||
2. Every visible shared wall has exactly one canonical decorative edge. Adjacent
|
||||
cells, full rerenders, projection updates, and observer zoom changes produce
|
||||
no doubled foliage, dark overlap, seam, flicker, or mismatched variant.
|
||||
3. The documented deterministic selection maps canonical visible wall edges to
|
||||
all six approved intact variants with representative distribution. The same
|
||||
edge and orientation produce the same variant across rerenders and roles,
|
||||
while no random state, hidden topology, or new protocol field is required.
|
||||
4. North, east, south, and west walls plus continuous runs, corners, crossings,
|
||||
exposed ends, and projection boundaries align to within one CSS pixel at 34,
|
||||
40, and 46 CSS-pixel cells and at representative device pixel ratios.
|
||||
5. The edge layer is derived exclusively from cells and passage/opened bits in
|
||||
the current server-approved projection. Tests confirm no unknown cell,
|
||||
missing edge, hidden route, remote breach, or explored-map decoration is
|
||||
inferred, retained, serialized, or rendered.
|
||||
6. Hedge artwork does not alter authoritative movement, wall collision,
|
||||
visibility, object pickup, exits, results, input hit targets, observer
|
||||
read-only behavior, or player focal positioning. No gameplay or protocol
|
||||
contract changes are introduced.
|
||||
7. Players, keys, exits, artifacts, landmarks, controls, and feedback remain
|
||||
above the hedge layer and clearly legible in normal color, grayscale, and
|
||||
representative color-vision checks. Decorative overhang creates no page or
|
||||
map-shell overflow and captures no pointer input.
|
||||
8. Each server-approved perseverance impact selects the matching approved stage
|
||||
on the exact currently visible wall. Stages do not advance from local input,
|
||||
duplicate or reordered messages, impacts on another edge, or events outside
|
||||
the current projection.
|
||||
9. A matching fifth-impact transition briefly uses the approved breakthrough
|
||||
frame in normal-motion mode and settles on one approved permanent breached
|
||||
variant from the next authoritative opened-edge projection. The visual gap
|
||||
aligns bidirectionally and cannot be mistaken for a closed wall.
|
||||
10. All three approved breached variants appear through a stable deterministic
|
||||
mapping. They remain visible only while their authoritative opened edge is
|
||||
projected, survive ordinary rerenders without changing variant, and leave
|
||||
no stale decoration after reset, match end, disconnect, or projection loss.
|
||||
11. Reduced-motion mode uses static impact stages and changes immediately to the
|
||||
permanent breach without maze shake, foliage sway, moving leaf fragments,
|
||||
or breakthrough travel animation. Meaning does not depend on motion, sound,
|
||||
vibration, text, or green hue alone.
|
||||
12. The renderer has a tested fixed upper bound for hedge elements, transient
|
||||
effects, timers, and memory based on the maximum supported projection.
|
||||
Repeated snapshots and impacts do not accumulate nodes, listeners, styles,
|
||||
or timers, and obsolete edge elements are removed deterministically.
|
||||
13. Observer rendering uses the same approved family and canonical edge logic,
|
||||
keeps full-map pan and zoom responsive, and preserves continuous intact and
|
||||
breached silhouettes at overview and inspection scales.
|
||||
14. Automated browser tests cover variant selection, shared-edge deduplication,
|
||||
every orientation and join, projection boundaries, hidden-state isolation,
|
||||
layering, impact and breach transitions, cleanup, reduced motion, observer
|
||||
zoom, supported cell sizes, and zero viewport overflow.
|
||||
15. The runtime SVG is local, valid, script-free, raster-free, deterministically
|
||||
generated, and included in web-asset reproducibility checks. All host tests
|
||||
pass, compressed web assets remain within the 1.5 MiB budget and LittleFS
|
||||
partition, and firmware remains within the factory partition.
|
||||
16. The project owner confirms on representative mobile and observer screens
|
||||
that the maze resembles a varied living hedge from above, repetition is not
|
||||
distracting, leaves and branches are visible, objects remain easy to find,
|
||||
impacts visibly damage the correct bush, and permanent openings are clear,
|
||||
or explicitly approves a documented evidence deviation.
|
||||
|
||||
### Evidence
|
||||
|
||||
The following planning-time state defines this milestone:
|
||||
|
||||
- On 2026-09-10, the project owner requested a separate future milestone to
|
||||
integrate the living-hedge samples generated and approved by Milestone 023.
|
||||
The approved review source contains six intact variants, four impact stages,
|
||||
one breakthrough frame, three permanent breach variants, and topology
|
||||
examples, but remains outside runtime assets at planning time.
|
||||
- Runtime SVG derivation, browser integration, tests, resource measurements,
|
||||
physical-device verification, and owner acceptance are deferred to this
|
||||
milestone. No implementation was performed while creating the plan.
|
||||
- 2026-09-11 implementation evidence: the local `web/hedges.svg` runtime
|
||||
sprite contains the approved intact, impact, breakthrough, and breach
|
||||
symbols. Player and observer maps derive a bounded canonical hedge-edge list
|
||||
only from their current projections; a full 32 by 32 projection is bounded
|
||||
to 2,112 edge elements. The renderer uses deterministic edge hashes and one
|
||||
restartable breakthrough timer, with immediate reduced-motion settlement.
|
||||
- 2026-09-11 verification: `bash scripts/run_host_tests.sh` passed. `node
|
||||
--test test/web/test_player_app.js test/web/test_hedge_svg.js` passed all 26
|
||||
browser tests. `python3 scripts/verify_web_assets.py` passed with a 29,912 /
|
||||
1,572,864 byte compressed payload.
|
||||
- 2026-09-11 skipped check: `pio run` could not acquire
|
||||
`/home/sasa/.platformio/platforms.lock` because the global PlatformIO home
|
||||
is read-only. Firmware size verification, physical-device visual testing,
|
||||
and project-owner mobile and observer acceptance remain required. Milestone
|
||||
024 therefore remains `IN_PROGRESS`.
|
||||
- 2026-09-11 user-run verification: `./scripts/run_host_tests.sh` passed all
|
||||
host and bundled player browser checks; `node --test
|
||||
test/web/test_player_app.js test/web/test_hedge_svg.js` passed all 26 tests;
|
||||
and `python3 ./scripts/verify_web_assets.py` confirmed deterministic assets
|
||||
at 29,912 / 1,572,864 bytes.
|
||||
- 2026-09-11 physical-device diagnostic: host `192.168.1.103/24` reached the
|
||||
connected ESP at `192.168.1.50` with two ICMP replies and no packet loss, but
|
||||
`curl --noproxy '*' http://192.168.1.50/health` was refused on TCP port 80.
|
||||
The device is reachable but its HTTP server is not listening; no flash or
|
||||
reset was performed. Physical visual acceptance remains pending.
|
||||
- 2026-09-11 physical-device repair and verification: boot logs identified
|
||||
`ESP_ERR_HTTPD_HANDLERS_FULL` after adding the hedge sprite route. The
|
||||
bounded URI handler capacity was raised from 13 to 14. A writable temporary
|
||||
PlatformIO home built and uploaded the application and LittleFS image through
|
||||
`/dev/ttyACM0` to the ESP32-C6FH4; every upload hash was verified. Firmware
|
||||
uses 1,029,600 / 2,097,152 factory bytes (49.1% flash) and 59,940 / 327,680
|
||||
bytes RAM (18.3%); LittleFS uses 2,031,616 / 2,031,616 bytes. After reboot,
|
||||
`GET /health` returned `200` with `{"status":"serving","healthy":true,`
|
||||
`"version":"0.14.0","errorCode":0}`, while GET requests for `/` and
|
||||
`/hedges.svg` both returned `200` (3,378 and 1,106 bytes respectively).
|
||||
Project-owner visual acceptance of the mobile and observer hedge rendering
|
||||
remains required before the milestone can become `COMPLETE`.
|
||||
- 2026-09-11 project-owner mobile review rejected the first runtime hedge
|
||||
presentation because foliage obscured the wall boundaries and made open
|
||||
routes substantially harder to understand than the former green strokes.
|
||||
The corrective contract limits foliage to 20% of a cell, adds a continuous
|
||||
high-contrast spine only to closed edges, and raises the contrast of the
|
||||
inset cell floor. Repeat physical-device visual acceptance remains required.
|
||||
- 2026-09-11 corrective verification: a local rendered maze preview confirmed
|
||||
that the continuous spine restores exact closed-edge continuity while opened
|
||||
edges remain uninterrupted passages. `node --test
|
||||
test/web/test_player_app.js test/web/test_hedge_svg.js` passed all 26 tests,
|
||||
`bash scripts/run_host_tests.sh` passed, and web-asset reproducibility passed
|
||||
at 30,012 / 1,572,864 compressed bytes. A clean PlatformIO build passed with
|
||||
firmware at 1,029,600 / 2,097,152 bytes and RAM at 59,940 / 327,680 bytes;
|
||||
`pio run -t buildfs` also passed for the 2,031,616-byte LittleFS image.
|
||||
- 2026-09-11 deployment was not attempted because no `/dev/ttyACM*` or
|
||||
`/dev/ttyUSB*` device was present and the ESP HTTP endpoint at
|
||||
`192.168.1.50:80` was unreachable from the host. The already-open browser tab
|
||||
still shows its previously loaded assets. Upload and repeat project-owner
|
||||
mobile visual acceptance remain required, so Milestone 024 stays
|
||||
`IN_PROGRESS`.
|
||||
- 2026-09-11 repeat project-owner review rejected the first readability
|
||||
correction: its added bright spine and emphasized floor insets produced a
|
||||
confusing rectangular grid, while the player still appeared to stand on a
|
||||
hedge. Browser geometry inspection found two root causes: rotating a
|
||||
horizontal SVG wrapper into a vertical edge left its center displaced by
|
||||
half a cell on both axes, and SVG instances had no `160 x 40` view box, so
|
||||
source-coordinate foliage overflowed far beyond its owning cell edge. The
|
||||
next correction removes the spine and floor emphasis, restores the quiet cell
|
||||
surface, constrains every SVG to one edge, and aligns vertical wrapper centers
|
||||
with authoritative boundaries. Repeat physical-device visual acceptance
|
||||
remains required.
|
||||
- 2026-09-11 second corrective verification: a rendered 7 by 7 maze at the
|
||||
minimum gameplay cell scale showed each `160 x 40` hedge constrained to one
|
||||
edge, vertical and horizontal centers aligned, the player wholly inside its
|
||||
cell, and continuous open-floor routes without the rejected rectangular
|
||||
overlay. `bash scripts/run_host_tests.sh` passed, including all bundled
|
||||
browser checks, and web-asset reproducibility passed at 29,979 / 1,572,864
|
||||
compressed bytes. A clean PlatformIO build passed with firmware at
|
||||
1,029,600 / 2,097,152 bytes and RAM at 59,940 / 327,680 bytes; the configured
|
||||
2,031,616-byte LittleFS image also built successfully.
|
||||
- 2026-09-11 the corrected image could not be uploaded from this environment:
|
||||
no `/dev/ttyACM*` or `/dev/ttyUSB*` device was present and the ESP HTTP
|
||||
endpoint remained unreachable from the host. The physical page still needs
|
||||
the new filesystem image and repeat project-owner visual acceptance, so
|
||||
Milestone 024 remains `IN_PROGRESS`.
|
||||
|
||||
Reference in New Issue
Block a user