Files
security-game/docs/architecture.md
T
zwitschi 1ee32215b0
Full build / Import + headless tests (push) Successful in 38s
Full build / Full desktop build + optional release (push) Skipped
Detail the NPC avatars and finish the realism follow-ups
Blender library
- Rebuild the face: sclera, iris and upper lid per eye, brow ridge, cheekbones,
  nose bridge and tip, ears with lobes, split upper/lower lips.
- Give each hand four fingers plus a thumb and end every sleeve in a cuff ring.
- Raise CHAR_MAX_VERTS 4000 -> 5000 (16 avatars still cost ~6.9 ms of a 50 ms
  frame), decimate the body to 26 %; characters are now 3,974-5,026 tris and
  3,744-4,807 verts. Rebuild all 8 variants and re-bake their AO maps.

Capture tooling
- Add a `portrait` stage to capture_realism.gd: freeze one NPC, park the crowd
  out of frame, stand the subject on open sidewalk, turn it into the camera and
  put the guard on the sunlit side. New --portrait-type=N picks the role.
- Add the npc_portrait_day concept and map the shot to it, so avatar detail is
  scored against a portrait instead of a wide street frame.

Flashlight
- Drop the fake additive beam (Materials.light_beam + the cone mesh): on GL
  Compatibility a first-person camera inside the cone renders it as a filled
  disc with a bright far ring. Keep the tight spot (14 deg, 20 m, energy 4.2)
  and its headless test; the visible shaft is now planned behind a Forward+
  preset.

Docs and task tracking
- Move the finished realism follow-ups (ground exposure, flashlight, NPC detail,
  judge re-check) to DONE.md and expand TODO.md with step-by-step plans for NPC
  gear fit, venue geometry plus the committed gallery, and the Forward+ preset.
- Record the decisions, gotchas and portrait recipe in MEMORY.md; update the
  Blender contract, the concept README and the capture section of README.md.
- Refresh the gallery captures affected by the avatar rebuild.

Checks: headless 228/228, Python 86/86, blender_assets audit exit 0,
scene_concepts audit all GOOD, screen_designs compare 11 good / 0 bad,
smoke_npc_budget OK, boot clean (only the known headless mesh warning).
2026-11-01 17:46:25 +01:00

227 lines
17 KiB
Markdown
Raw 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.
# Architecture
This document follows the structure of the arc42 architecture documentation template.
## 1. Introduction and Goals
### Functional goals
- Simulate believable security work at multiple public-facing venues.
- Provide clear, low-pressure deterrence options before verbal or physical escalation.
- Make access verification a meaningful gameplay decision.
- Support distinct NPC behaviors and scenario events.
- Make emergency response rare, consequential, and justified by observable danger.
- Provide shift-level feedback so players can learn from decisions.
### Quality goals
- **Clarity:** Players should understand why an NPC is allowed, denied, or escalated.
- **Extensibility:** New venues should reuse shared systems and primarily provide configuration and content.
- **Testability:** Rules and outcomes should be testable without rendering or real-time input.
- **Consistency:** Similar situations should follow predictable venue and escalation rules.
- **Respectful representation:** Mental-health crises and public interactions should not be reduced to stereotypes or treated as automatic threats.
- **Realism:** The game world should look like the real world and NPC behaviors should feel consistent and believable within the established setting.
## 2. Constraints
- The first implementation should be small enough for a playable vertical slice.
- The engine is Godot 4 with GDScript; a playable prototype vertical slice is implemented.
- Venue-specific policies must be configurable rather than hard-coded into individual NPCs.
- The game must preserve the de-escalation-first design described in [`PLAN.md`](../PLAN.md).
- The project uses the repository workflow described in [`AGENTS.md`](../AGENTS.md).
- The project follows [Semantic Versioning](https://semver.org/) (`MAJOR.MINOR.PATCH`).
### Version management
- **MAJOR** — incompatible changes to the game's core systems, save format, or public-facing behavior.
- **MINOR** — new venues, NPC archetypes, systems, or features that are backward compatible.
- **PATCH** — bug fixes and small polish that do not change behavior.
The single source of truth for the version is `config/version` in `project.godot` (currently `0.6.0`). Each release is tagged in git as `v<version>` (e.g. `v0.6.0`). The `0.x` series is pre-1.0, so MINOR bumps may introduce breaking changes while the prototype is still stabilizing. `tools/build_releases.sh` and `tools/publish_release.sh` read the version from `project.godot`, so bumping it there is the only required step before a release. The full bump checklist lives in [`RELEASING.md`](RELEASING.md).
## 3. Context and Scope
The player interacts with NPCs, venue entrances, access artifacts, equipment, staff, and response services. The game itself owns the simulated world, rules, scoring, events, and shift review. External services are currently out of scope; radio, body camera, and emergency response are simulated systems.
## 4. Solution Strategy
- Use a shared simulation core with venue-specific scenario data.
- Represent NPC behavior using state machines or behavior trees with configurable traits.
- Model escalation as explicit, auditable state transitions.
- Separate access verification from NPC identity and presentation details.
- Keep scoring and reputation event-driven so every action can be reviewed.
- Use authored scenario events alongside procedural routine traffic.
- Make the first playable target one venue and one complete shift before adding breadth.
## 5. Building Block View
### Level 1: Major components
- **Presentation layer:** Camera, UI, prompts, interaction feedback, queues, and shift review.
- **Input and interaction layer:** Player gestures, dialogue choices, access checks, equipment use, and radio controls.
- **Simulation layer:** NPC movement, perception, intent, navigation, crowd behavior, and venue state.
- **Rules layer:** Access policy, escalation policy, prohibited items, response thresholds, and venue configuration.
- **Incident layer:** Incident lifecycle, evidence, radio reports, consequences, reputation, and review.
- **Content layer:** Venue definitions, NPC profiles, dialogue, events, visual/audio assets, and shift schedules.
### Level 2: Key components
- `ShiftCoordinator` starts, advances, and ends a shift.
- `VenueScenario` provides venue rules, locations, event pools, and access policies.
- `NPCController` manages an NPC’s intent, movement, compliance, and reaction.
- `InteractionSystem` resolves gestures, dialogue, warnings, and physical positioning.
- `AccessVerifier` evaluates recognition, wristbands, IDs, tickets, credentials, and guest lists.
- `EscalationManager` tracks the current response level and available actions.
- `RadioSystem` receives reports and schedules security or emergency responses.
- `IncidentRecorder` stores actions, observations, evidence, and outcomes.
- `ReputationEvaluator` converts incidents and shift outcomes into performance feedback.
- `CrowdSystem` models queues, attention, congestion, and public reaction.
- `ShiftReview` presents decisions, consequences, and improvement opportunities.
- `SurfaceMaterials` (`src/game/materials.gd`) holds the surface profiles, textured albedo/normal recipes, baked-AO wiring, glass/emissive recipes, and the environment tune-up (tonemapping, glow, fog, grading) that the phase lighting applies.
- `WorldBuilder` assembles the procedural venue, prefers the Blender prop library in `assets/models/blender/props/`, and falls back to `assets/models/generated/` or primitives. It also wires the phase-driven library emissives and street dressing.
- `src/game/ui/art.gd` loads runtime UI/scene art from `assets/images/ui/` and `assets/images/scenes/`, with null fallbacks so panels keep their procedural layouts.
- `tools/model_pipeline.py` builds and audits the street-prop `.glb` models and packs their colour atlases.
- `tools/npc_pipeline.py` builds and audits the skinned NPC base model (`assets/models/generated/npc_base.glb`) and its per-slot material maps, with an optional AI fabric override (ADR-0013).
- `tools/blender_assets.py` builds, renders and audits the Blender asset library (`assets/models/blender/{npc,npc_gear,props}/` + `manifest.json`): NPC character variants that are drop-in for `npc_base`, attach-point gear, and street/venue props. `NpcAvatar` selects variants/gear by role/seed and `WorldBuilder` loads the prop replacements and new street dressing, with procedural fallbacks (see `docs/blender-assets.md`).
- `tools/scene_concepts.py` generates realism-pass references (`docs/screens/concepts/`), skyline backdrops and surface tiles (raw `assets/textures/ai/v2/raw/` → candidates `assets/textures/ai/game_ready/v2/`), promotes the validated ones to the tracked `v2/picks/` that `SurfaceMaterials`/`WorldBuilder` preload, audits them, and scores `src/test/capture_realism.gd` A/B captures (five stages, runtime texture swaps) against the concepts (`docs/screens/realism/<run>/`).
- `tools/asset_pipeline.py` generates and audits role-aware textures; `tools/screen_designs.py` generates screen references and judges captures; `tools/check_screenshots.sh` renders the staged gallery and runs the compare gate.
Confirmed game assets live in `assets/textures/ai/game_ready/` (audited surface, UI, and card textures), `assets/models/generated/` (prop and NPC `.glb` models plus their texture atlases), and `assets/textures/npc/` (NPC material maps and `palette.json`). Development-only outputs — AI concept sheets, Blender sources, raw AI fabrics — are gitignored and regenerated by the tools.
### Asset storage conventions
The canonical rules live in [ADR-0014](adr/0014-runtime-image-root.md). In short:
| Location | Contents | Loaded at runtime? |
| --- | --- | --- |
| `assets/images/ui/` | Composed screen/panel art (start menu, HUD chrome, mockup-derived backgrounds) | Yes |
| `assets/images/scenes/` | Composed full-frame scene/background art | Yes |
| `assets/textures/ai/game_ready/` (+ `v2/`) | Tiled/PBR surface textures, model maps, skyline strips | Yes, as materials |
| `assets/models/generated/`, `assets/models/blender/` | 3D props/characters and manifests | Yes |
| `docs/screens/designs/`, `docs/screens/concepts/` | Reference mockups and art-direction sets | No (reference only) |
| `docs/screenshots/`, `docs/screens/realism/` | README/catalogue captures and QA reports | No (generated QA) |
| `assets/textures/ai/v2/raw/`, Blender `.blend` sources | Raw AI output / editable sources | No (gitignored or `.gdignore`d) |
When reference art becomes runtime art, copy or process it into `assets/images/` with a
new descriptive name (never overwrite an existing image) and keep a procedural fallback
in code.
## 6. Runtime View
### Routine interaction
1. An NPC selects or receives an intent such as taking a photo, entering, waiting, or trespassing.
2. The player observes the NPC and chooses whether to intervene.
3. A gesture or verbal interaction changes the NPC’s state.
4. The NPC complies, negotiates, refuses, or escalates.
5. The rules layer validates access and determines available next actions.
6. The incident recorder stores the interaction.
7. Reputation and crowd systems react to the outcome.
### Access check
1. The player stops or receives an approaching person.
2. The player recognizes the person or inspects a wristband, ID, credential, ticket, or guest-list record.
3. The access verifier checks the artifact against the venue policy.
4. The player admits, redirects, holds, or refuses entry.
5. The decision is recorded for shift review.
### Emergency response
1. NPC behavior crosses the configured immediate-threat threshold.
2. The player holds and confirms the emergency-radio action.
3. The player submits a concise report describing location and behavior.
4. The response system dispatches an appropriate responder.
5. Crowd, venue, reputation, and incident systems apply consequences.
6. The shift review evaluates whether the call was justified.
## 7. Deployment View
The game is a single-player local client containing presentation, simulation, rules, content, and persistence for local settings and shift results. No online backend is required. A non-threaded Web export ships alongside the desktop builds and can be served from any static host without special headers.
Future options include external analytics, cloud saves, or replay sharing, but they are not part of the current architecture.
### CI/CD build pipeline
A continuous-integration pipeline keeps the headless test suite green on every change and publishes tagged releases.
- **Workflow:** `.gitea/workflows/build.yml` runs on pushes, pull requests, tags, and manual dispatches. The `checks` job installs Godot 4.3, imports the project, and runs `res://src/test/test_runner.gd`; it fails on a non-zero exit code or any `SCRIPT ERROR` in the output.
- **Build job:** runs for tags and manual dispatches. It installs export templates, exports Linux/Windows/macOS and the non-threaded Web build, packages the NSIS installer and Linux AppImage, verifies the installer contents, and uploads the artifacts.
- **Publish job:** tag builds call `tools/publish_release.sh` to create the Gitea release and upload the six artifacts. The script uses `GITEA_TOKEN` when configured and otherwise reuses the runner's checkout extraheader credentials.
- **Hosting:** the repository lives on Gitea (`https://git.allucanget.biz/zwitschi/security-game`). Export templates must match the pinned Godot version; macOS builds are unsigned and need quarantine guidance or notarization for wider distribution.
### Release management
Releases are produced from a tagged commit and published to the repository host's release page, where the README "Downloads" links point.
- `export_presets.cfg` — committed Linux, Windows, macOS, and Web export presets so builds are reproducible.
- `tools/build_releases.sh` — exports the desktop binaries and Web zip into `build/`, named `gig-line-<platform>-<version>.<ext>`.
- `tools/publish_release.sh` — creates a release and uploads the artifacts via the Gitea API, using `GITEA_TOKEN` or the checkout extraheader fallback.
- Packaging — NSIS builds the Windows installer; `packaging/linux/build_appimage.sh` builds the AppImage.
- [`RELEASING.md`](RELEASING.md) — step-by-step guide and release checklist.
The release process is: bump the version, run the full test suite and `tools/check_screenshots.sh`, run `tools/build_releases.sh`, tag and push (CI publishes), then verify the README "Downloads" links and the six artifacts.
## 8. Cross-Cutting Concepts
- **Event-based incident recording:** Important actions emit records consumed by evidence, reputation, and review systems.
- **Data-driven venue rules:** Access, escalation, equipment, and event differences live in scenario data.
- **State transitions:** NPCs, incidents, and shifts expose explicit states for debugging and testing.
- **Accessibility:** Input alternatives should exist for gestures, dialogue, visual alerts, and audio cues.
- **Safety and proportionality:** The rules layer prevents ordinary noncompliance from automatically becoming a violent encounter.
- **Determinism where useful:** Scenario tests should be able to use fixed seeds and scripted NPC behavior.
- **Localization:** Dialogue and prompts should be externalized from logic.
- **Observability:** Debug overlays show NPC intent, access status, escalation level, active incidents, and response timers during development.
- **Visual regression:** Staged captures are compared against the runtime reference art (`screen_designs.py compare`) and optionally judged by a vision model; `tools/check_screenshots.sh` makes the pass repeatable.
## 9. Architecture Decisions
Architecture decisions are recorded as ADRs:
- [ADR-0001: Venue-driven simulation architecture](adr/0001-venue-driven-simulation-architecture.md)
- [ADR-0002: De-escalation-first escalation model](adr/0002-de-escalation-first-escalation-model.md)
- [ADR-0003: Explicit access-verification system](adr/0003-explicit-access-verification-system.md)
- [ADR-0004: Local single-player first](adr/0004-local-single-player-first.md)
- [ADR-0005: Event-based incident recording](adr/0005-event-based-incident-recording.md)
- [ADR-0006: Godot 4 with GDScript](adr/0006-godot-4-gdscript.md)
- [ADR-0007: Locomotion and input layers](adr/0007-locomotion-and-input-layers.md)
- [ADR-0008: Cone focus and focus circle](adr/0008-cone-focus-and-head-ring.md)
- [ADR-0009: Radial action menu](adr/0009-radial-action-menu.md)
- [ADR-0010: Procedural NPC presentation](adr/0010-procedural-npc-presentation.md)
- [ADR-0011: Aim-free selection and precision walk](adr/0011-aim-free-selection-and-precision-walk.md)
- [ADR-0012: Surface materials and generated props](adr/0012-surface-materials-and-generated-props.md)
- [ADR-0013: Blender-authored NPC characters and baked materials](adr/0013-blender-authored-npc-characters.md)
- [ADR-0014: Canonical runtime image root and image conventions](adr/0014-runtime-image-root.md)
## 10. Quality Requirements
| Requirement | Target |
| --- | --- |
| Player comprehension | Players can identify the reason for an access or escalation decision through UI and feedback. |
| Response proportionality | Routine NPC behavior should be resolvable without emergency response. |
| Extensibility | A new venue can be added primarily through scenario data and content. |
| Performance | The target venue should support a believable crowd without harming input or simulation responsiveness. |
| Testability | Access and escalation rules can be tested independently of presentation. |
| Accessibility | Core actions are available through clear input alternatives and readable feedback. |
## 11. Risks and Technical Debt
- NPC behavior may feel artificial if traits and reactions are too deterministic.
- Crowd simulation may become expensive around busy studio or comedy-club entrances.
- Access verification can become frustrating if the UI does not clearly show what the player is checking.
- Emergency response can overshadow the core game if it is too powerful or too frequent.
- Mental-health-crisis scenarios require careful writing, playtesting, and respectful presentation.
- The choice of engine may affect navigation, crowd scale, tooling, and content authoring.
- Reference mockups can outpace the runtime art style; compare/judge catch gross drift but not composition errors, so the staged gallery needs human review after large visual changes.
## 12. Glossary
- **Access artifact:** A wristband, ID, ticket, credential, or other item used to verify entry.
- **Authorized person:** Someone permitted to enter under the current venue policy.
- **Door person:** The entrance security worker in The Joke Shop scenario.
- **Incident:** A recorded interaction or event requiring player judgment.
- **NPC:** Non-player character.
- **Scenario:** A venue-specific configuration of rules, content, locations, and events.
- **Shift:** One playable work period, normally 10–15 minutes.
- **Simple deterrence:** A low-pressure gesture such as raising a hand, making eye contact, or pointing.