not-tonight/docs/BUILD_PLAN.md
2026-07-19 16:20:53 +10:00

117 lines
6.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# NOT TONIGHT — Build Plan & Technical Architecture
*Read [GAME_DESIGN.md](GAME_DESIGN.md) first. This doc is the engineering plan the
lanes execute. Contract details live in [CONTRACTS.md](CONTRACTS.md).*
## 1. Stack (decided — don't relitigate)
| Choice | What | Why |
|---|---|---|
| Engine | **Phaser 3 (latest 3.x)** | Scenes map 1:1 to game phases; tweens, input, Light2D for the flashlight cone; huge ecosystem |
| Language | **TypeScript, strict** | Multiple parallel lanes NEED typed contracts; the rules engine is pure typed functions |
| Build | **Vite** | Instant dev server, static build output |
| Tests | **Vitest** | Rules engine, patron generator, ID validity, clock — all pure logic, all unit-testable |
| Audio | **Raw WebAudio** (no Howler) | The low-pass-filter-as-location trick and the beat-clock need direct node graph access |
| Saves | localStorage | No backend. Ever. |
| Art (v0.x) | **Runtime paper-doll renderer** | Patrons are layered data (see design §4.1); placeholder layers are coloured-pixel shapes drawn to a texture. Real pixel-art layers swap in later behind the SAME layer contract |
| Deploy | Static `dist/` | Eventually → partly.party games VPS. Not a v0.1 concern |
## 2. Repo layout (ownership boundaries = merge-conflict avoidance)
```
src/
core/ # LANE-0 then frozen: EventBus, GameClock, SeededRNG, GameState, save
data/ # LANE-0 then frozen-ish: types + static config (venues, nights, rules, archetypes)
patrons/ # LANE-0: generator, paper-doll renderer, memory/regulars
rules/ # dress-code engine, ID validator, sobriety logic (pure functions ONLY)
scenes/
door/ # LANE-DOOR owns
floor/ # LANE-FLOOR owns
shared/ # Boot, Menu, NightSummary, HUD — LANE-0 stubs, integration fills
audio/ # LANE-JUICE owns: techno engine, sfx synth
ui/ # LANE-JUICE owns: stamp, phone, dialogue box, clicker widgets
tests/ # mirrors src/; every lane adds tests for its pure logic
docs/ # design + this plan + CONTRACTS.md
lanes/ # lane instruction files
LANEHANDOVER.md
```
**Rule: a lane commits only inside its owned directories + its tests + LANEHANDOVER.md.**
Changes to `core/`, `data/` types, or `CONTRACTS.md` after Phase 0 require a
CONTRACT CHANGE REQUEST in the handover file and reviewer sign-off — never just do it.
## 3. Phases
### Phase 0 — Scaffold & Contracts — ✅ DONE 2026-07-19 (executed by Fable)
`lanes/LANE0_SCAFFOLD.md`. Delivered: strict-TS Vite+Phaser scaffold, all
CONTRACTS.md types in `src/data/types.ts`, core systems (`SeededRNG`, `EventBus`,
`GameClock`+`ageOn`, `Meters`, `StubBeatClock`, `save`), patron generator +
paper-doll renderer (pure `dollPlan` + Phaser `renderDoll`), 49 unit tests, and
the Patron Parade demo verified in-browser. See the LANE-0 SESSION block in
LANEHANDOVER.md for API notes Phase-1 lanes must read.
### Phase 1 — Parallel lanes (after Phase 0 review passes)
Three lanes run concurrently on separate branches/worktrees:
- **LANE-DOOR** (`lanes/LANE_DOOR.md`) — the Door scene, full v0.1 loop: queue, ID
minigame, dress-code stamps, clicker, Dazza texts, verdicts, Vibe/Aggro wiring.
*This is the v0.1 critical path — the game is shippable with only this lane done.*
- **LANE-FLOOR** (`lanes/LANE_FLOOR.md`) — top-down Floor scene: patrol movement,
flashlight/UV cone, drunk detection, Cut-Off dialogue, pat-down minigame, toilet
rhythm game (against a stub beat clock until integration).
- **LANE-JUICE** (`lanes/LANE_JUICE.md`) — WebAudio techno engine + low-pass
location filter + beat clock; SFX synth (stamp, thud, static, clicker); reusable
UI widgets (stamp, phone, dialogue). Develops against its own demo scenes.
Lanes talk ONLY through the event bus + contracts. No lane imports another lane's
scene code. Beat sync example: audio engine emits `beat:tick` on the bus; the toilet
rhythm game consumes `beat:tick`; until integration, LANE-FLOOR uses the
`StubBeatClock` from core (same event, fixed 128 BPM).
### Phase 2 — Integration (ONE lane, sequential)
Night flow state machine (Door ⇄ Floor interleave, radio pulls, Last Drinks,
Summary), real audio engine replaces stubs, save/progression, Kayden-at-door
simulation while player is on Floor. Playtest pass: one full night start→summary.
### Phase 3 — Content & polish (parallelizable again)
Archetypes, scripted moral encounters, inspector, incident report memory, regulars,
venues 24, real pixel art swapped into the paper-doll layer slots, MODELBEAST-
assisted art generation if useful.
### Phase 4 — The role ladder (design §6; future, do not start)
Glassie, bartender, DJ roles + roster board. Not scoped yet — but it imposes ONE
rule on every earlier phase: **the simulation is role-agnostic.** Crowd sim, patron
state, meters, and incidents must never assume the player is security — the player
is just an entity with a verb-set reading shared state. If you're about to hard-code
"the player" into a sim system (e.g. "patrons only get cut off by the player"),
model it as an actor capability instead (NPC staff already need this — Kayden works
the door while you're on the floor). The DJ role will drive the TechnoEngine
directly, so LANE-JUICE keeps track parameters (BPM, layer intensities) externally
settable rather than hard-coded.
## 4. Coordination protocol (all lanes)
1. **Branches:** each lane works on `lane/<name>` (e.g. `lane/door`), pushed to
origin (`ssh://git@100.71.119.27:222/monster/not-tonight.git`). Never push main.
On one machine, use worktrees: `git worktree add ../not-tonight-door lane/door`.
2. **Handover:** every work session APPENDS a session block to `LANEHANDOVER.md`
(template inside it) and pushes. This is how the reviewer (Fable) sees state.
3. **Review gate:** reviewer reads handovers + diffs, replies with a REVIEW block in
the same file (or a fresh lane instruction file), merges approved lanes to main.
4. **Contract changes:** request-only via handover. If blocked >30 min on a contract
ambiguity, write the question in the handover, make the smallest local stub that
unblocks you, mark it `// TODO(contract):`, and continue.
5. **Definition of done for any session:** compiles (`npm run build`), tests green
(`npm test`), demo scene for your lane runs (`npm run dev`), handover written.
## 5. Milestone acceptance
- **M0 (Phase 0):** `npm run dev` shows Patron Parade; ≥25 unit tests green covering
RNG determinism (same seed → same patrons), ID validity math, layer rendering data.
- **M1 (v0.1):** One full Door-only night playable start→summary; a stranger can
understand it with no explanation; fail states (Vibe 0, Aggro 100) both reachable.
- **M2 (v0.2):** Full night with ≥2 forced Floor interludes; toilet game verifiably
on-beat (log beat timestamps vs hit timestamps in tests).
- **M3 (v0.3):** 3-night run with persistence; an incident-report lie can bite you a
night later.