docs(diagrams): add decision diagrams across all domains
16 d2 diagrams covering architecture (IPC bridge, system tiers, testability, audio bus), data flow (perception, dialogue, eavesdrop pipelines), entity (knowledge graph, NPC generation, dialogue tags), state (simulation tiers, movement stances, knowledge confidence), and UI (HUD layout, interaction flow, fog layers). PNG output for universal viewer compatibility. Removes test SVG from font debugging. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@@ -0,0 +1,121 @@
|
||||
# Audio Architecture — D-068, D-073
|
||||
# 5-bus audio system with zone crossfade and AudioManager singleton.
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
direction: down
|
||||
|
||||
server_event: Rust Server\n(ObserverSnapshot) {
|
||||
shape: hexagon
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
zone_id: zone_id per tile {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
sound_events: sound events {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
manager: AudioManager\n(GDScript autoload singleton) {
|
||||
shape: hexagon
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
registry: Directory-scan registry\n(res://audio/ on startup) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
crossfade: Zone crossfade\n1.5-2s tween on zone_id change {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
buses: 5-Bus Mixer {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
music: Bus 1 — Music\n(reserved · empty v0.1) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 5
|
||||
}
|
||||
ambient: Bus 2 — Ambient\n(station hum + zone overlays) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
world_sfx: Bus 3 — World SFX\n(NPC footsteps · doors · env events) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
player_actions: Bus 4 — Player Actions\n(footsteps · future: combat · items) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
ui_sounds: Bus 5 — UI Sounds\n(cursor hover · implant open · chimes) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
sliders: Player Volume Sliders\n(1 per bus · in Settings) {
|
||||
shape: queue
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
dips: Audio Dip Profiles (D-069) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
dialogue_dip: Dialogue\nAmbient -6 to -8dB · 300ms in {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
confrontation_dip: Confrontation\nAmbient -10 to -12dB + LPF · 500ms in {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
listen_boost: ListeningFocus\nWorld SFX +2 to +3dB\n(stationary 30+ ticks) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
server_event.zone_id -> manager.crossfade: "zone change" { style.stroke: ${color-accent} }
|
||||
server_event.sound_events -> manager: "typed events" { style.stroke: ${color-stroke} }
|
||||
manager.registry -> manager.crossfade: "filename → AudioStream" { style.stroke: ${color-stroke} }
|
||||
manager -> buses.ambient: "loop" { style.stroke: ${color-accent} }
|
||||
manager -> buses.world_sfx: "event" { style.stroke: ${color-stroke} }
|
||||
manager -> buses.player_actions: "event" { style.stroke: ${color-stroke} }
|
||||
manager -> buses.ui_sounds: "event" { style.stroke: ${color-stroke} }
|
||||
sliders -> buses: "proportional volume" { style.stroke: ${color-stroke} }
|
||||
dips -> buses.ambient: "proportional dip" { style.stroke: ${color-stroke}; style.stroke-dash: 4 }
|
||||
dips -> buses.world_sfx: "proportional dip" { style.stroke: ${color-stroke}; style.stroke-dash: 4 }
|
||||
|
After Width: | Height: | Size: 568 KiB |
@@ -0,0 +1,146 @@
|
||||
# IPC Bridge Architecture — D-020
|
||||
# Godot client + Rust simulation server via subprocess/IPC
|
||||
# Single-player: subprocess + local socket. Multiplayer: TCP (same protocol).
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
direction: right
|
||||
|
||||
godot: Godot Client {
|
||||
shape: hexagon
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
renderer: Renderer {
|
||||
style.fill: ${color-dim}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
ui: UI + HUD {
|
||||
style.fill: ${color-dim}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
audio: AudioManager {
|
||||
style.fill: ${color-dim}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
input: Input Capture {
|
||||
style.fill: ${color-dim}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
bridge_client: SimBridge (LocalBridge / NetworkBridge) {
|
||||
style.fill: ${color-dim}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke: ${color-accent}
|
||||
}
|
||||
}
|
||||
|
||||
transport: Transport Layer {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
sp: Single-player\nUnix socket / localhost TCP {
|
||||
style.fill: ${color-bg}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
mp: Multiplayer\nRemote TCP {
|
||||
style.fill: ${color-bg}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
}
|
||||
|
||||
rust: Rust Simulation Server {
|
||||
shape: hexagon
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
bridge_server: SimBridge (recv end) {
|
||||
style.fill: ${color-dim}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke: ${color-accent}
|
||||
}
|
||||
ecs: bevy_ecs World {
|
||||
style.fill: ${color-dim}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
perception: Perception System {
|
||||
style.fill: ${color-dim}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
ai: AI + Storyteller {
|
||||
style.fill: ${color-dim}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
kg: Knowledge Graph {
|
||||
style.fill: ${color-dim}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
}
|
||||
|
||||
msgpack_out: PlayerInput (MessagePack) {
|
||||
shape: queue
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
msgpack_in: ObserverSnapshot (MessagePack) {
|
||||
shape: queue
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
godot.input -> msgpack_out: "semantic actions\n(MoveNorth, Interact, UsePerceptionMode)" {
|
||||
style.stroke: ${color-accent}
|
||||
}
|
||||
msgpack_out -> godot.bridge_client
|
||||
godot.bridge_client -> transport.sp: "single-player" {
|
||||
style.stroke: ${color-accent}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
godot.bridge_client -> transport.mp: "multiplayer" {
|
||||
style.stroke: ${color-accent}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
transport.sp -> rust.bridge_server {
|
||||
style.stroke: ${color-accent}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
transport.mp -> rust.bridge_server {
|
||||
style.stroke: ${color-accent}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
rust.bridge_server -> rust.ecs: "dispatch input" {
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
rust.ecs -> rust.perception
|
||||
rust.ecs -> rust.ai
|
||||
rust.ecs -> rust.kg
|
||||
rust.ecs -> msgpack_in: "ObserverSnapshot\n(entities, fog, sound events,\nmonologue triggers, HUD widgets)" {
|
||||
style.stroke: ${color-accent}
|
||||
}
|
||||
msgpack_in -> godot.bridge_client
|
||||
godot.bridge_client -> godot.renderer
|
||||
godot.bridge_client -> godot.ui
|
||||
godot.bridge_client -> godot.audio
|
||||
|
After Width: | Height: | Size: 1.0 MiB |
@@ -0,0 +1,133 @@
|
||||
# Simulation Tiers + Multiplayer-Ready Principles — D-026, D-010, D-009
|
||||
# Four simulation tiers with LRU eviction.
|
||||
# D-010: four non-negotiable architectural principles embedded as annotations.
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
direction: down
|
||||
|
||||
principles: Architectural Principles (D-010) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.border-radius: 4
|
||||
|
||||
p1: Client-Server Separation\neven in single-player {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
p2: Information Boundaries\nas first-class system {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
p3: No Baked Player Identity\n"characters, some player-controlled" {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
p4: Deterministic Simulation\ntimestamped input events {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
tiers: Simulation Tiers (D-026) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.border-radius: 4
|
||||
|
||||
active: Tier 1 — Active {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.bold: true
|
||||
}
|
||||
background: Tier 2 — Background {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
saved: Tier 3 — State-Saved {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
ungenerated: Tier 4 — Ungenerated {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 5
|
||||
}
|
||||
}
|
||||
|
||||
active_detail: 30-80 NPCs\nFull sim · 10-20 ticks/sec\nScope tags keep NPCs here {
|
||||
shape: page
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
background_detail: 500-2,000 NPCs\nState machine · 1 tick/game-minute\n(schedule · mood · relationships · job) {
|
||||
shape: page
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
saved_detail: 10,000+ NPCs\nFrozen serialized structs ~1-2KB\nReactivate on player return ~2-5ms {
|
||||
shape: page
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
eviction: LRU Eviction\n(interaction-timestamp priority queue) {
|
||||
shape: diamond
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
tiers.active -> active_detail {
|
||||
style.stroke: ${color-accent}
|
||||
}
|
||||
tiers.background -> background_detail {
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
tiers.saved -> saved_detail {
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
|
||||
tiers.active -> tiers.background: "evict (LRU)" {
|
||||
style.stroke: ${color-accent}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
tiers.background -> tiers.active: "player proximity\nor scope tag" {
|
||||
style.stroke: ${color-accent}
|
||||
}
|
||||
tiers.background -> tiers.saved: "evict (LRU)" {
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
tiers.saved -> tiers.background: "player return" {
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
tiers.ungenerated -> tiers.saved: "player approach\n(generated ahead of arrival)" {
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
|
||||
eviction -> tiers {
|
||||
style.stroke: ${color-accent}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
|
After Width: | Height: | Size: 547 KiB |
@@ -1,97 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" data-d2-version="0.7.1" preserveAspectRatio="xMinYMin meet" viewBox="0 0 712 274"><svg class="d2-1525458463 d2-svg" width="712" height="274" viewBox="-101 -86 712 274"><rect x="-101.000000" y="-86.000000" width="712.000000" height="274.000000" rx="0.000000" fill="#1E1E2E" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
|
||||
.d2-1525458463 .text-bold {
|
||||
font-family: sans-serif; font-weight: bold;
|
||||
}
|
||||
|
||||
.d2-1525458463 .text-italic {
|
||||
font-family: sans-serif; font-style: italic;
|
||||
}
|
||||
]]></style><style type="text/css"><![CDATA[.shape {
|
||||
shape-rendering: geometricPrecision;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
.connection {
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
.blend {
|
||||
mix-blend-mode: multiply;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.d2-1525458463 .fill-N1{fill:#CDD6F4;}
|
||||
.d2-1525458463 .fill-N2{fill:#BAC2DE;}
|
||||
.d2-1525458463 .fill-N3{fill:#A6ADC8;}
|
||||
.d2-1525458463 .fill-N4{fill:#585B70;}
|
||||
.d2-1525458463 .fill-N5{fill:#45475A;}
|
||||
.d2-1525458463 .fill-N6{fill:#313244;}
|
||||
.d2-1525458463 .fill-N7{fill:#1E1E2E;}
|
||||
.d2-1525458463 .fill-B1{fill:#CBA6f7;}
|
||||
.d2-1525458463 .fill-B2{fill:#CBA6f7;}
|
||||
.d2-1525458463 .fill-B3{fill:#6C7086;}
|
||||
.d2-1525458463 .fill-B4{fill:#585B70;}
|
||||
.d2-1525458463 .fill-B5{fill:#45475A;}
|
||||
.d2-1525458463 .fill-B6{fill:#313244;}
|
||||
.d2-1525458463 .fill-AA2{fill:#f38BA8;}
|
||||
.d2-1525458463 .fill-AA4{fill:#45475A;}
|
||||
.d2-1525458463 .fill-AA5{fill:#313244;}
|
||||
.d2-1525458463 .fill-AB4{fill:#45475A;}
|
||||
.d2-1525458463 .fill-AB5{fill:#313244;}
|
||||
.d2-1525458463 .stroke-N1{stroke:#CDD6F4;}
|
||||
.d2-1525458463 .stroke-N2{stroke:#BAC2DE;}
|
||||
.d2-1525458463 .stroke-N3{stroke:#A6ADC8;}
|
||||
.d2-1525458463 .stroke-N4{stroke:#585B70;}
|
||||
.d2-1525458463 .stroke-N5{stroke:#45475A;}
|
||||
.d2-1525458463 .stroke-N6{stroke:#313244;}
|
||||
.d2-1525458463 .stroke-N7{stroke:#1E1E2E;}
|
||||
.d2-1525458463 .stroke-B1{stroke:#CBA6f7;}
|
||||
.d2-1525458463 .stroke-B2{stroke:#CBA6f7;}
|
||||
.d2-1525458463 .stroke-B3{stroke:#6C7086;}
|
||||
.d2-1525458463 .stroke-B4{stroke:#585B70;}
|
||||
.d2-1525458463 .stroke-B5{stroke:#45475A;}
|
||||
.d2-1525458463 .stroke-B6{stroke:#313244;}
|
||||
.d2-1525458463 .stroke-AA2{stroke:#f38BA8;}
|
||||
.d2-1525458463 .stroke-AA4{stroke:#45475A;}
|
||||
.d2-1525458463 .stroke-AA5{stroke:#313244;}
|
||||
.d2-1525458463 .stroke-AB4{stroke:#45475A;}
|
||||
.d2-1525458463 .stroke-AB5{stroke:#313244;}
|
||||
.d2-1525458463 .background-color-N1{background-color:#CDD6F4;}
|
||||
.d2-1525458463 .background-color-N2{background-color:#BAC2DE;}
|
||||
.d2-1525458463 .background-color-N3{background-color:#A6ADC8;}
|
||||
.d2-1525458463 .background-color-N4{background-color:#585B70;}
|
||||
.d2-1525458463 .background-color-N5{background-color:#45475A;}
|
||||
.d2-1525458463 .background-color-N6{background-color:#313244;}
|
||||
.d2-1525458463 .background-color-N7{background-color:#1E1E2E;}
|
||||
.d2-1525458463 .background-color-B1{background-color:#CBA6f7;}
|
||||
.d2-1525458463 .background-color-B2{background-color:#CBA6f7;}
|
||||
.d2-1525458463 .background-color-B3{background-color:#6C7086;}
|
||||
.d2-1525458463 .background-color-B4{background-color:#585B70;}
|
||||
.d2-1525458463 .background-color-B5{background-color:#45475A;}
|
||||
.d2-1525458463 .background-color-B6{background-color:#313244;}
|
||||
.d2-1525458463 .background-color-AA2{background-color:#f38BA8;}
|
||||
.d2-1525458463 .background-color-AA4{background-color:#45475A;}
|
||||
.d2-1525458463 .background-color-AA5{background-color:#313244;}
|
||||
.d2-1525458463 .background-color-AB4{background-color:#45475A;}
|
||||
.d2-1525458463 .background-color-AB5{background-color:#313244;}
|
||||
.d2-1525458463 .color-N1{color:#CDD6F4;}
|
||||
.d2-1525458463 .color-N2{color:#BAC2DE;}
|
||||
.d2-1525458463 .color-N3{color:#A6ADC8;}
|
||||
.d2-1525458463 .color-N4{color:#585B70;}
|
||||
.d2-1525458463 .color-N5{color:#45475A;}
|
||||
.d2-1525458463 .color-N6{color:#313244;}
|
||||
.d2-1525458463 .color-N7{color:#1E1E2E;}
|
||||
.d2-1525458463 .color-B1{color:#CBA6f7;}
|
||||
.d2-1525458463 .color-B2{color:#CBA6f7;}
|
||||
.d2-1525458463 .color-B3{color:#6C7086;}
|
||||
.d2-1525458463 .color-B4{color:#585B70;}
|
||||
.d2-1525458463 .color-B5{color:#45475A;}
|
||||
.d2-1525458463 .color-B6{color:#313244;}
|
||||
.d2-1525458463 .color-AA2{color:#f38BA8;}
|
||||
.d2-1525458463 .color-AA4{color:#45475A;}
|
||||
.d2-1525458463 .color-AA5{color:#313244;}
|
||||
.d2-1525458463 .color-AB4{color:#45475A;}
|
||||
.d2-1525458463 .color-AB5{color:#313244;}.appendix text.text{fill:#CDD6F4}.md{--color-fg-default:#CDD6F4;--color-fg-muted:#BAC2DE;--color-fg-subtle:#A6ADC8;--color-canvas-default:#1E1E2E;--color-canvas-subtle:#313244;--color-border-default:#CBA6f7;--color-border-muted:#CBA6f7;--color-neutral-muted:#313244;--color-accent-fg:#CBA6f7;--color-accent-emphasis:#CBA6f7;--color-attention-subtle:#BAC2DE;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-normal-d2-1525458463);mix-blend-mode:color-burn}.sketch-overlay-B2{fill:url(#streaks-normal-d2-1525458463);mix-blend-mode:color-burn}.sketch-overlay-B3{fill:url(#streaks-dark-d2-1525458463);mix-blend-mode:overlay}.sketch-overlay-B4{fill:url(#streaks-dark-d2-1525458463);mix-blend-mode:overlay}.sketch-overlay-B5{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-B6{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-AA2{fill:url(#streaks-normal-d2-1525458463);mix-blend-mode:color-burn}.sketch-overlay-AA4{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-AA5{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-AB4{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-AB5{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-N1{fill:url(#streaks-normal-d2-1525458463);mix-blend-mode:color-burn}.sketch-overlay-N2{fill:url(#streaks-normal-d2-1525458463);mix-blend-mode:color-burn}.sketch-overlay-N3{fill:url(#streaks-normal-d2-1525458463);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-dark-d2-1525458463);mix-blend-mode:overlay}.sketch-overlay-N5{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-N6{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.sketch-overlay-N7{fill:url(#streaks-darker-d2-1525458463);mix-blend-mode:lighten}.light-code{display: none}.dark-code{display: block}]]></style><g class="Y2xpZW50"><g class="shape" ><path d="M 43 17 L 0 51 L 43 86 L 128 86 L 171 51 L 128 17 Z" stroke="#CBA6f7" fill="#45475A" class=" stroke-B1 fill-N5" style="stroke-width:2;" /></g><text x="85.500000" y="57.000000" fill="#CDD6F4" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Godot Client</text></g><g class="c2VydmVy"><g class="shape" ><path d="M 389 17 L 349 51 L 389 86 L 470 86 L 510 51 L 470 17 Z" stroke="#CBA6f7" fill="#45475A" class=" stroke-B1 fill-N5" style="stroke-width:2;" /></g><text x="429.500000" y="57.000000" fill="#CDD6F4" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Rust Server</text></g><g class="KGNsaWVudCAtJmd0OyBzZXJ2ZXIpWzBd"><marker id="mk-d2-1525458463-3488378134" markerWidth="10.000000" markerHeight="12.000000" refX="7.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" fill="#CBA6f7" class="connection fill-B1" stroke-width="2" /> </marker><path d="M 157.969089 38.649729 C 239.199997 24.200001 280.600006 24.200001 359.063000 38.292869" stroke="#CBA6f7" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-1525458463-3488378134)" mask="url(#d2-1525458463)" /><text x="259.500000" y="30.000000" fill="#BAC2DE" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">stdin IPC</text></g><g class="KHNlcnZlciAtJmd0OyBjbGllbnQpWzBd"><path d="M 361.031500 63.353566 C 280.600006 77.800003 239.199997 77.800003 159.938177 63.700541" stroke="#CBA6f7" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-d2-1525458463-3488378134)" mask="url(#d2-1525458463)" /><text x="259.500000" y="83.000000" fill="#BAC2DE" class="text-italic fill-N2" style="text-anchor:middle;font-size:16px">stdout IPC</text></g><mask id="d2-1525458463" maskUnits="userSpaceOnUse" x="-101" y="-86" width="712" height="274">
|
||||
<rect x="-101" y="-86" width="712" height="274" fill="white"></rect>
|
||||
<rect x="228.000000" y="14.000000" width="63" height="21" fill="black"></rect>
|
||||
<rect x="223.000000" y="67.000000" width="73" height="21" fill="black"></rect>
|
||||
</mask></svg></svg>
|
||||
|
Before Width: | Height: | Size: 8.3 KiB |
@@ -0,0 +1,126 @@
|
||||
# Testability Architecture — D-030
|
||||
# Three-layer IPC testing, test runner tooling, and phase priorities.
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
direction: down
|
||||
|
||||
runners: Test Runners {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
rust_runner: cargo nextest\n(Rust) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
godot_runner: gdUnit4\n(Godot) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
wrapper: bash wrapper scripts\n(tests/ directory) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
output: Test Output {
|
||||
shape: page
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
ipc_layers: IPC Test Layers {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
l1: Layer 1 — Fixture Serialization\nRoundtrip (fast · every edit) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.bold: true
|
||||
}
|
||||
l2: Layer 2 — Mock Subprocess Protocol\nState machine (medium · every PR) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l3: Layer 3 — Real Subprocess Integration\n(slow · daily / pre-merge) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
}
|
||||
|
||||
phases: Test Phases {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
ph1: Phase 1 (Sprint 1-2)\nInfra + collision / pathfinding / time {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
ph2: Phase 2 (Sprint 3-4)\nMonologue pipeline + info boundary negatives {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
ph3: Phase 3 (Sprint 5+)\nCauseChain + divergent snapshots {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
}
|
||||
|
||||
constraints: Production Code Constraints {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
c1: No cfg(test) in production code {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
c2: ECS World setup replaces mock injection {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
c3: CauseChain = production component\n(monologue provenance + debugging) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
c4: Deterministic replay (D-010 P4)\nSimulationTime · SimRng · InputQueue injectable {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
runners.rust_runner -> output: "JSON summary\n+ JUnit XML (CI)" { style.stroke: ${color-stroke} }
|
||||
runners.godot_runner -> output: "JSON summary\n+ JUnit XML (CI)" { style.stroke: ${color-stroke} }
|
||||
runners.wrapper -> runners.rust_runner
|
||||
runners.wrapper -> runners.godot_runner
|
||||
|
||||
ipc_layers.l1 -> ipc_layers.l2: "gates" { style.stroke: ${color-accent} }
|
||||
ipc_layers.l2 -> ipc_layers.l3: "gates" { style.stroke: ${color-accent} }
|
||||
|
||||
phases.ph1 -> phases.ph2: "unblocks" { style.stroke: ${color-stroke} }
|
||||
phases.ph2 -> phases.ph3: "unblocks" { style.stroke: ${color-stroke} }
|
||||
|
After Width: | Height: | Size: 437 KiB |
@@ -0,0 +1,171 @@
|
||||
# Dialogue Pipeline — D-028, D-062, D-063, D-064, D-075
|
||||
# Four relational layers, two-phase verb computation, invisible locks,
|
||||
# confrontation weight, walk-away consequences.
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
direction: down
|
||||
|
||||
player_action: Player Initiates Interaction {
|
||||
shape: oval
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
verb_phase1: Phase 1 — Simulation\n(no KnowledgeGraph read) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.border-radius: 4
|
||||
|
||||
object_type: ObjectType component\n→ max possible verb set {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
verb_phase2: Phase 2 — Observer\n(reads KnowledgeGraph) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.border-radius: 4
|
||||
|
||||
kg_filter: Filter by KG confidence\n(Confront requires KnowsDetails+) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
poi_flip: POI priority flip\n+ contradiction markers {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
archetype_filter: Archetype filter rules\n(same crate: smuggler→Stash · detective→Flag) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
layer_filter: Four Relational Layers (D-028) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
l1: Layer 1 — Access Tier\n(RelationshipState only) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l2: Layer 2 — Relationship History\n(interaction log: greeting + topic) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l3: Layer 3 — Trust-gated Gossip\n(RelationshipState AND KnowledgeConfidence — D-075) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l4: Layer 4 — Unprompted Disclosure\n(weighted by trust + mood) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
invisible_locks: Invisible Locked Options (D-062) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.border-radius: 4
|
||||
|
||||
rule: Locked options = completely invisible\nNo grayed-out · no lock icons · no hints {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
reveal: New options appearing on repeat visits\n= the reward (dopamine) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
confrontation: Confrontation Weight (D-063) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.border-radius: 4
|
||||
|
||||
voice: Written in character's internal voice\n(italicized first-person) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
monologue_beat: Pre-delivery monologue beat\n1-2s: "No taking it back." {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
world_reacts: World reacts\n(NPC Tier 2 anim · D-033 fade · monologue spikes) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
walk_away: Walk-away (D-064)\nWASD during conversation {
|
||||
shape: diamond
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
walk_away_phases: Walk-away Consequences {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
immediate: 1 — Dialogue fades 300ms\n(no close button) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
npc_reacts: 2 — NPC reacts\n(animation · may call after player) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
kg_record: 3 — KG records incompleteness\n(per-seed tolerance: no universal safe-to-leave rules) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
player_action -> verb_phase1
|
||||
verb_phase1 -> verb_phase2: "max verb set" { style.stroke: ${color-accent} }
|
||||
verb_phase2 -> layer_filter: "filtered verb set" { style.stroke: ${color-accent} }
|
||||
layer_filter.l1 -> layer_filter.l2
|
||||
layer_filter.l2 -> layer_filter.l3
|
||||
layer_filter.l3 -> layer_filter.l4
|
||||
layer_filter -> invisible_locks: "visible options only\n(max 3 shown)" {
|
||||
style.stroke: ${color-accent}
|
||||
}
|
||||
invisible_locks -> confrontation: "if Confront option present" {
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
invisible_locks -> walk_away
|
||||
walk_away -> walk_away_phases.immediate
|
||||
walk_away_phases.immediate -> walk_away_phases.npc_reacts
|
||||
walk_away_phases.npc_reacts -> walk_away_phases.kg_record
|
||||
|
After Width: | Height: | Size: 856 KiB |
@@ -0,0 +1,162 @@
|
||||
# Eavesdrop Pipeline — D-071, D-072, D-078
|
||||
# Overheard NPC-to-NPC conversation: occlusion filter (server-authoritative),
|
||||
# ListeningFocus boost, passive dialogue panel, dual-channel principle.
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
direction: down
|
||||
|
||||
npc_convo: NPC-to-NPC Conversation\n(authored at full fidelity by copy team) {
|
||||
shape: oval
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
murmur: Universal Murmur Asset (D-072)\nsingle asset plays everywhere {
|
||||
shape: package
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
zone_ambient: Zone Ambient Level {
|
||||
shape: diamond
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
conspicuousness: Conversation Conspicuousness {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
bar: Bar (high ambient)\nhidden in murmur, needs proximity {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
workplace: Workplace (moderate)\nsemi-conspicuous, distance-dependent {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
corridor: Corridor (low ambient)\nconspicuous, audible from distance {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
server_occlusion: Server-side Occlusion Filter (D-078)\nper-word probability roll {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.border-radius: 4
|
||||
|
||||
factors: Factors: distance · ambient noise\n· ListeningFocus stance {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
stochastic: Stochastic per word\n(same scene can yield different fragments) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
seeded: Seedable RNG per tick\n→ deterministic replay (D-010) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
listen_focus: ListeningFocus Boost (D-071)\nWorld SFX +2 to +3dB\nstationary 30+ ticks {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.border-radius: 4
|
||||
}
|
||||
|
||||
no_ambient_dip: No Ambient Dip for Eavesdrop\n(opposite of direct conversation dip) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
|
||||
occluded_text: Pre-occluded text\n(words → "..." per roll) {
|
||||
shape: page
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
passive_panel: Passive Dialogue Panel (D-078)\n(D-061 box, read-only) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.border-radius: 4
|
||||
|
||||
speaker_label: Speaker format (e.g. Kael to Mira) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
reduced_opacity: Reduced opacity (0.9)\nvs active dialogue {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
no_responses: No response options {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
monologue_channel: Monologue Channel\n(D-016 — separate pipeline) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
witness_trigger: witness_interaction trigger\n→ character's reaction {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
separate: Character reaction\n(thought · never quoted speech) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
kg_entry: KnowledgeGraph entry\n(KnowsOf confidence unless\nListeningFocus + proximity → KnowsDetails) {
|
||||
shape: cylinder
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
npc_convo -> murmur: "audio" { style.stroke: ${color-stroke} }
|
||||
npc_convo -> zone_ambient: "text goes through" { style.stroke: ${color-accent} }
|
||||
murmur -> zone_ambient: "conspicuousness shaped by" { style.stroke: ${color-stroke} }
|
||||
zone_ambient -> conspicuousness
|
||||
zone_ambient -> server_occlusion: "noise penalty" { style.stroke: ${color-stroke} }
|
||||
listen_focus -> server_occlusion: "probability curve shift" { style.stroke: ${color-accent} }
|
||||
no_ambient_dip -> listen_focus: "instead of dip" { style.stroke: ${color-stroke}; style.stroke-dash: 4 }
|
||||
server_occlusion -> occluded_text: "pre-occluded text sent to client" { style.stroke: ${color-accent} }
|
||||
occluded_text -> passive_panel: "client renders exactly what it receives" { style.stroke: ${color-accent} }
|
||||
passive_panel -> monologue_channel: "triggers witness_interaction" {
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
passive_panel -> kg_entry: "overheard info enters KG" { style.stroke: ${color-accent} }
|
||||
|
After Width: | Height: | Size: 826 KiB |
@@ -0,0 +1,185 @@
|
||||
# Perception Pipeline — D-011, D-017, D-018, D-019, D-059, D-060, D-067
|
||||
# From simulation ECS through to rendered fog and monologue.
|
||||
# Covers: fog of perception, LOS (D-035), perception modes, three-range sound,
|
||||
# fog layers, cognitive delay, recognition chime.
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
direction: down
|
||||
|
||||
world: ECS World State {
|
||||
shape: hexagon
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
los: LOS System\n(Albert Ford symmetric shadowcasting — D-035) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.border-radius: 4
|
||||
|
||||
fov: compute_fov(is_opaque, origin, range, z)\n→ VisibilityMap {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
symmetry: Symmetry guarantee:\nif A sees B → B sees A {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
perception_modes: Perception Modes (D-017) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
natural: Natural Vision\n(walls block, cone model) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
thermal: Thermal\n(heat through walls, no identity) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
camera: Camera Feeds\n(remote, spoofable) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
unisphere: Unisphere Tracking\n(known inserts, maskable) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
audio_analysis: Audio Analysis\n(signatures, no visual) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
}
|
||||
|
||||
sound: Sound System (D-018)\nThree-Range Model {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
close: Close (in/near LOS)\nHigh accuracy · stereo audio {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
medium: Medium (outside LOS)\nVisual indicators at fog edge + monologue {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
long: Long (across map)\nInsert notifications · spoofable {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
}
|
||||
|
||||
snapshot: ObserverSnapshot {
|
||||
shape: queue
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
kg_read: KnowledgeGraph read\n(per-character — what THIS observer knows) {
|
||||
shape: cylinder
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
fog: Fog Rendering (D-059)\n5-layer shader system {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
clear: Clear (vision cone)\nsoft gradient 6-8 sim tiles {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
light_fog: Light Fog (peripheral)\ndesaturated 40-50%, Perlin noise {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
deep_fog: Deep Fog (explored)\nnear-monochrome + zone tint {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
unexplored_maps: Unexplored (has maps)\ngeometric wireframe outlines {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
unexplored_dark: Unexplored (no maps)\nsolid near-black {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
recognition: Fog Entity Recognition {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
chime: Recognition chime fires (D-067)\nat ONSET of cognitive delay {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
delay: Cognitive delay (D-060)\n0.6s base · 0.3s for anomaly {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
monologue_fire: Monologue fires DURING delay\n"Those footsteps... that's Kael's walk" {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
transition: Grey blob → D-033 color\n+ silhouette over 0.3s {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
world -> los: "entity positions + opaque tiles" { style.stroke: ${color-accent} }
|
||||
world -> sound: "sound events" { style.stroke: ${color-stroke} }
|
||||
los -> perception_modes: "VisibilityMap" { style.stroke: ${color-accent} }
|
||||
perception_modes -> snapshot: "observer query result\n(what this sensor reveals)" {
|
||||
style.stroke: ${color-accent}
|
||||
}
|
||||
sound -> snapshot: "sound events" { style.stroke: ${color-stroke} }
|
||||
kg_read -> snapshot: "per-entity recognition data" { style.stroke: ${color-accent} }
|
||||
snapshot -> fog: "visible entities + fog state" { style.stroke: ${color-accent} }
|
||||
snapshot -> recognition: "heard/sensed entity not in LOS" { style.stroke: ${color-stroke} }
|
||||
recognition.chime -> recognition.delay: "concurrent" { style.stroke: ${color-accent} }
|
||||
recognition.delay -> recognition.monologue_fire
|
||||
recognition.delay -> recognition.transition
|
||||
|
After Width: | Height: | Size: 912 KiB |
@@ -0,0 +1,101 @@
|
||||
# Dialogue + Monologue Tag Taxonomy — D-035, D-028
|
||||
# Converged tag schema for tagged line pools.
|
||||
# Structural tags (required), selection tags (recommended), monologue additions.
|
||||
# Includes Sprint 8 + 14 + 15 amendments.
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
dialogue_line: Dialogue Line {
|
||||
shape: sql_table
|
||||
id: "{npc-slug}_{d|m}_{###}" {constraint: primary_key}
|
||||
text: String
|
||||
role: enum (template-defined role)
|
||||
access: list<enum> (public · insider · authority · peer · hostile)
|
||||
trust: enum (surface · real · secret)
|
||||
situation: list<enum> (14 situations)
|
||||
topic: list<enum> (9 topics — optional)
|
||||
mood: list<enum> (8 moods — optional)
|
||||
tags: list<string> (freeform — optional)
|
||||
}
|
||||
|
||||
monologue_line: Monologue Line {
|
||||
shape: sql_table
|
||||
id: "{npc-slug}_m_{s|d}_{###}" {constraint: primary_key}
|
||||
character: enum (smuggler · detective) {constraint: not_null}
|
||||
trigger: enum (9 triggers) {constraint: not_null}
|
||||
prerequisite: map or null
|
||||
dual_lens: map (authoring-only)
|
||||
notes: String (authoring-only)
|
||||
}
|
||||
|
||||
access_values: AccessTier values {
|
||||
shape: sql_table
|
||||
public: Public — default, anyone
|
||||
insider: Insider — social network member
|
||||
authority: Authority — institutional role
|
||||
peer: Peer — known colleague
|
||||
hostile: Hostile — adversarial context
|
||||
}
|
||||
|
||||
trust_values: TrustTier values {
|
||||
shape: sql_table
|
||||
surface: Surface — any relationship + any confidence
|
||||
real: Real — (Friendly|Known) + KnowsOf+
|
||||
secret: Secret — Friendly + KnowsDetails+
|
||||
}
|
||||
|
||||
situation_values: Situation (14) {
|
||||
shape: sql_table
|
||||
s1: first_meeting
|
||||
s2: regular_contact
|
||||
s3: after_conflict
|
||||
s4: work_context
|
||||
s5: social_context
|
||||
s6: private_context
|
||||
s7: witnessed_something
|
||||
s8: under_suspicion
|
||||
s9: post_confrontation
|
||||
s10: trust_broken
|
||||
s11: urgent
|
||||
s12: relaxed
|
||||
s13: farewell
|
||||
s14: greeting
|
||||
}
|
||||
|
||||
mood_values: Mood (8) {
|
||||
shape: sql_table
|
||||
m1: anxious
|
||||
m2: frustrated
|
||||
m3: content
|
||||
m4: suspicious
|
||||
m5: warm
|
||||
m6: hostile
|
||||
m7: relieved
|
||||
m8: focused
|
||||
}
|
||||
|
||||
trigger_values: Monologue Triggers (9) {
|
||||
shape: sql_table
|
||||
t1: enter_location
|
||||
t2: observe_npc
|
||||
t3: hear_sound
|
||||
t4: observe_anomaly
|
||||
t5: post_conversation
|
||||
t6: discover_evidence
|
||||
t7: witness_interaction
|
||||
t8: time_idle
|
||||
t9: return_visit
|
||||
}
|
||||
|
||||
dialogue_line -> access_values: "access field" { style.stroke: ${color-accent} }
|
||||
dialogue_line -> trust_values: "trust field" { style.stroke: ${color-accent} }
|
||||
dialogue_line -> situation_values: "situation field" { style.stroke: ${color-stroke} }
|
||||
dialogue_line -> mood_values: "mood field" { style.stroke: ${color-stroke} }
|
||||
monologue_line -> dialogue_line: "extends" { style.stroke: ${color-accent} }
|
||||
monologue_line -> trigger_values: "trigger field" { style.stroke: ${color-accent} }
|
||||
|
After Width: | Height: | Size: 753 KiB |
@@ -0,0 +1,88 @@
|
||||
# Knowledge Graph Data Model — D-041
|
||||
# Per-entity bevy_ecs Component with BTreeMap storage.
|
||||
# Confidence hierarchy, knowledge state, knowledge source, event-driven updates.
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
KnowledgeGraph: KnowledgeGraph {
|
||||
shape: sql_table
|
||||
entity_knowledge: BTreeMap<StableId, EntityKnowledge>
|
||||
fact_knowledge: BTreeMap<FactId, FactKnowledge>
|
||||
}
|
||||
|
||||
EntityKnowledge: EntityKnowledge {
|
||||
shape: sql_table
|
||||
stable_id: StableId(u64) {constraint: foreign_key}
|
||||
confidence: KnowledgeConfidence
|
||||
state: KnowledgeState
|
||||
source: KnowledgeSource
|
||||
last_observed_tick: u64
|
||||
}
|
||||
|
||||
FactKnowledge: FactKnowledge {
|
||||
shape: sql_table
|
||||
fact_id: FactId {constraint: primary_key}
|
||||
confidence: KnowledgeConfidence
|
||||
state: KnowledgeState
|
||||
source: KnowledgeSource
|
||||
last_observed_tick: u64
|
||||
}
|
||||
|
||||
KnowledgeConfidence: KnowledgeConfidence {
|
||||
shape: sql_table
|
||||
direct: Direct — currently in LOS
|
||||
knows_details: KnowsDetails — actionable (secret tier)
|
||||
knows_of: KnowsOf — involved in Y (real tier)
|
||||
suspects: Suspects — something off (surface tier)
|
||||
}
|
||||
|
||||
KnowledgeState: KnowledgeState {
|
||||
shape: sql_table
|
||||
active: Active — believed true
|
||||
contradicted: Contradicted — conflict detected (Sprint 3+)
|
||||
stale: Stale — aged beyond threshold (Sprint 3+)
|
||||
}
|
||||
|
||||
KnowledgeSource: KnowledgeSource {
|
||||
shape: sql_table
|
||||
direct_observation: DirectObservation
|
||||
heard: Heard
|
||||
told_by: ToldBy (Sprint 3+)
|
||||
inferred: Inferred (Sprint 3+)
|
||||
background: Background
|
||||
}
|
||||
|
||||
EntityRegistry: EntityRegistry {
|
||||
shape: sql_table
|
||||
stable_to_entity: BTreeMap<StableId, Entity>
|
||||
entity_to_stable: BTreeMap<Entity, StableId>
|
||||
}
|
||||
|
||||
KnowledgeEventQueue: KnowledgeEventQueue\n(bevy_ecs Resource) {
|
||||
shape: queue
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
KnowledgeGraph -> EntityKnowledge: "contains many"
|
||||
KnowledgeGraph -> FactKnowledge: "contains many"
|
||||
EntityKnowledge -> KnowledgeConfidence: "uses"
|
||||
EntityKnowledge -> KnowledgeState: "uses"
|
||||
EntityKnowledge -> KnowledgeSource: "uses"
|
||||
FactKnowledge -> KnowledgeConfidence: "uses"
|
||||
FactKnowledge -> KnowledgeState: "uses"
|
||||
FactKnowledge -> KnowledgeSource: "uses"
|
||||
EntityKnowledge -> EntityRegistry: "StableId lookup" {
|
||||
style.stroke: ${color-accent}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
KnowledgeEventQueue -> KnowledgeGraph: "drained each tick\n→ writes components" {
|
||||
style.stroke: ${color-accent}
|
||||
}
|
||||
|
After Width: | Height: | Size: 667 KiB |
@@ -0,0 +1,154 @@
|
||||
# NPC Generation Model — D-024, D-025
|
||||
# 10 axes + combat component. Social site / functional cluster as atomic template unit.
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
direction: right
|
||||
|
||||
npc: NPC (generated) {
|
||||
shape: person
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
essential: 7 Essential Axes {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
want: Want {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
secret: Secret / Vulnerability {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
relationships: Relationships (1-3) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
tolerance: Tolerance Threshold {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
routine: Daily Routine {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
info_inv: Information Inventory {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
contentment: Contentment {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
supporting: 3 Supporting Axes {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
personality: Personality Traits (2-3) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
tell: Tell System {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
skills: Skill Set {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
combat_comp: CombatCapability\n(optional ECS component) {
|
||||
shape: package
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
|
||||
key_interactions: Key Contradiction Interactions {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
i1: Want × Secret {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
i2: Routine × Secret {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
i3: Tolerance × Relationships {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
i4: Want × Relationships {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
i5: Personality × Tolerance {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
social_site: Social Site\n(atomic Tier 2 template unit) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
group: Social Group (4-8 NPCs)\n2+ triangles + 1 cross-template triangle {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
cluster: Functional Cluster\n15-40 tiles, internal sightlines {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
ownership: NPC Ownership\nowned by 1 template, referenced by others {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
npc -> essential: "generated with" { style.stroke: ${color-accent} }
|
||||
npc -> supporting: "generated with" { style.stroke: ${color-stroke} }
|
||||
supporting.skills -> combat_comp: "combat tag → component" {
|
||||
style.stroke: ${color-accent}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
essential -> key_interactions: "produces" { style.stroke: ${color-stroke} }
|
||||
npc -> social_site: "placed in" { style.stroke: ${color-accent} }
|
||||
|
After Width: | Height: | Size: 634 KiB |
@@ -0,0 +1,152 @@
|
||||
# Knowledge Confidence State Machine — D-041
|
||||
# 4-level confidence hierarchy with state tracking and decay.
|
||||
# Maps to dialogue trust tiers (D-075) and fog recognition (D-059).
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
none: No Knowledge\n(entity unknown) {
|
||||
shape: oval
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
suspects: Suspects\n"something off" {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
knows_of: KnowsOf\n"X is involved in Y" {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
knows_details: KnowsDetails\n"actionable detail" {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
direct: Direct\n"currently in LOS" {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.bold: true
|
||||
}
|
||||
|
||||
dialogue_gates: Dialogue Trust Gate (D-075) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
surface: Surface tier\n(any confidence) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
real: Real tier\n(KnowsOf+ AND Friendly/Known) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
secret: Secret tier\n(KnowsDetails+ AND Friendly) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
fog_gate: Fog Recognition (D-059) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
recognized: Recognized entity\n(D-033 color + silhouette) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
unrecognized: Grey blob\n(no identity) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
knowledge_states: KnowledgeState {
|
||||
shape: package
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
active: Active (Sprint 2) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
contradicted: Contradicted (Sprint 3+)\nToldBy conflicts DirectObservation {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
stale: Stale (Sprint 3+)\naged past DecayThreshold {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
}
|
||||
|
||||
none -> suspects: "observe anomaly\nor receive tip" {
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
suspects -> knows_of: "further observation\nor testimony" {
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
knows_of -> knows_details: "direct evidence\nor confrontation" {
|
||||
style.stroke: ${color-accent}
|
||||
}
|
||||
knows_details -> direct: "enter LOS" {
|
||||
style.stroke: ${color-accent}
|
||||
}
|
||||
direct -> knows_details: "exit LOS" {
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
|
||||
# Decay path (D-041: once per game-minute)
|
||||
knows_details -> knows_of: "decay\n(last_observed_tick age)" {
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
knows_of -> suspects: "decay" {
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
|
||||
suspects -> dialogue_gates.surface
|
||||
knows_of -> dialogue_gates.real
|
||||
knows_details -> dialogue_gates.secret
|
||||
|
||||
suspects -> fog_gate.unrecognized
|
||||
knows_of -> fog_gate.recognized
|
||||
knows_details -> fog_gate.recognized
|
||||
|
||||
knows_details -> knowledge_states.contradicted: "ToldBy vs DirectObservation\n(Sprint 3+)" {
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
knows_of -> knowledge_states.stale: "decay (Sprint 3+)" {
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
none -> knowledge_states.active
|
||||
|
After Width: | Height: | Size: 638 KiB |
@@ -0,0 +1,111 @@
|
||||
# Movement Stance State Machine — D-053, D-054, D-055
|
||||
# Toggle ladder: Sprint / Walk / Careful / Crouch / (Prone future).
|
||||
# Server-authoritative tile-based movement. Client Tween interpolation.
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
sprint: Sprint {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.bold: true
|
||||
}
|
||||
|
||||
sprint_detail: 1 tile/tick · loud footsteps\nMonologue 40% (urgent only)\nInteraction buffer CLEARED (D-055)\nSprint double-take: anomaly monologue fires retroactively {
|
||||
shape: page
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
walk: Walk\n(default stance) {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
walk_detail: 1 tile/2 ticks · normal footsteps\nMonologue 100%\nDefault — MovementProfile component {
|
||||
shape: page
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
careful: Careful {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
careful_detail: 1 tile/3 ticks · quiet footsteps\nMonologue 150% + tell notice bonus\nListeningFocus accumulates (stationary_ticks)\nEavesdrop bonus: ListeningFocus +2-3dB (D-071) {
|
||||
shape: page
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
crouch: Crouch {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
crouch_detail: 1 tile/4 ticks · very quiet\nUses Prone/Seated occupancy layer (D-054) {
|
||||
shape: page
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
prone: Prone\n(future) {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 5
|
||||
}
|
||||
|
||||
tile_occupancy: TilePresence (D-054)\nSame-tile occupancy layers {
|
||||
shape: package
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
standing: Standing {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
prone_layer: Prone / Seated {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
fixture_layer: Fixture {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
sprint -> sprint_detail
|
||||
walk -> walk_detail
|
||||
careful -> careful_detail
|
||||
crouch -> crouch_detail
|
||||
|
||||
sprint -> walk: "toggle" { style.stroke: ${color-accent} }
|
||||
walk -> sprint: "toggle" { style.stroke: ${color-accent} }
|
||||
walk -> careful: "toggle" { style.stroke: ${color-stroke} }
|
||||
careful -> walk: "toggle" { style.stroke: ${color-stroke} }
|
||||
careful -> crouch: "toggle" { style.stroke: ${color-stroke} }
|
||||
crouch -> careful: "toggle" { style.stroke: ${color-stroke} }
|
||||
crouch -> prone: "toggle (future)" { style.stroke: ${color-stroke}; style.stroke-dash: 4 }
|
||||
prone -> crouch: "toggle-out only" { style.stroke: ${color-stroke}; style.stroke-dash: 4 }
|
||||
|
||||
crouch -> tile_occupancy.prone_layer: "occupies" { style.stroke: ${color-stroke} }
|
||||
walk -> tile_occupancy.standing: "occupies" { style.stroke: ${color-stroke} }
|
||||
|
After Width: | Height: | Size: 456 KiB |
@@ -0,0 +1,96 @@
|
||||
# NPC Simulation Tier State Machine — D-026
|
||||
# bevy_ecs dynamic component add/remove makes tier transitions seamless.
|
||||
# Scope tags keep NPCs in Active tier.
|
||||
|
||||
vars: {
|
||||
color-bg: "#2a3040"
|
||||
color-stroke: "#333340"
|
||||
color-text: "#c8d0e0"
|
||||
color-accent: "#c8d8f0"
|
||||
color-dim: "#1a1e24"
|
||||
}
|
||||
|
||||
ungenerated: Tier 4\nUngenerated {
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 5
|
||||
}
|
||||
|
||||
state_saved: Tier 3\nState-Saved\n~1-2KB frozen struct {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
background: Tier 2\nBackground\n500-2,000 NPCs {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
active: Tier 1\nActive\n30-80 NPCs · full sim {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
style.bold: true
|
||||
}
|
||||
|
||||
scope_tags: Scope Tags (prevent eviction) {
|
||||
shape: package
|
||||
style.fill: ${color-dim}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
neighborhood: neighborhood {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
active_quest: active-quest {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
colleague: colleague {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
known_contact: known-contact {
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
lru: LRU Priority Queue\n(interaction-timestamp) {
|
||||
shape: diamond
|
||||
style.fill: ${color-bg}
|
||||
style.stroke: ${color-accent}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
ungenerated -> state_saved: "player approach\n(generated ahead)" {
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
state_saved -> background: "player return\n(~2-5ms reactivation)" {
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
background -> state_saved: "LRU eviction" {
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
background -> active: "player proximity\nor scope tag match" {
|
||||
style.stroke: ${color-accent}
|
||||
}
|
||||
active -> background: "LRU eviction\n(no scope tag)" {
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
scope_tags -> active: "prevents eviction" {
|
||||
style.stroke: ${color-accent}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
lru -> active: "manages" { style.stroke: ${color-accent} }
|
||||
lru -> background: "manages" { style.stroke: ${color-stroke} }
|
||||
|
After Width: | Height: | Size: 354 KiB |
@@ -0,0 +1,108 @@
|
||||
# Fog System — Five Layers + Entity Rendering in Fog — D-059
|
||||
# Shader-based, knowledge-graph-driven. Covers all five fog states
|
||||
# and the entity types rendered within fogged areas.
|
||||
|
||||
vars: {
|
||||
color-screen: "#1a1e24"
|
||||
color-panel: "#2a3040"
|
||||
color-text: "#c8d0e0"
|
||||
color-nav: "#c8d8f0"
|
||||
color-stroke: "#333340"
|
||||
}
|
||||
|
||||
direction: right
|
||||
|
||||
kg_read: KnowledgeGraph\n(per character — D-041) {
|
||||
shape: cylinder
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
fog_layers: Five Fog Layers {
|
||||
style.fill: ${color-screen}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
l1: Layer 1 — Clear (vision cone)\nSoft gradient edge 6-8 sim tiles\n(= 3-4 visual tiles per D-066)\nNo hard line · Darkwood approach {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
style.bold: true
|
||||
}
|
||||
l2: Layer 2 — Light Fog (peripheral)\nDesaturated 40-50% · brightness -30%\nAnimated Perlin noise (8-10s cycle)\nD-033 entity colors visible but reduced {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l3: Layer 3 — Deep Fog (explored)\nNear-monochrome + ~10% zone tint\n(bar=warm dark · hub=cool dark)\nMore pronounced noise (15-20s cycle)\nzone_id from ObserverSnapshot (D-077) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l4: Layer 4 — Unexplored (has maps)\nGeometric wireframe outlines\nInsert data aesthetic {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l5: Layer 5 — Unexplored (no maps)\nSolid near-black\nInformation zero {
|
||||
style.fill: ${color-screen}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
fog_entities: Entities in Fog {
|
||||
style.fill: ${color-screen}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
sound_ping: Sound Ping\n2-3 concentric expanding rings\n(sonar-style · insert white-blue)\nLoud=3 rings bright · quiet=1 ring faint\nFade over 1.5s {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
recognized: Recognized Entity\nD-033 color glow + silhouette feature\n(e.g. identifying clothing detail)\n0.8s breathing pulse\n+/-0.5 tile position drift {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
unrecognized: Unrecognized Entity\nneutral grey blob\nno silhouette · no identity {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
divergence: "Same fog, different information per character\nSmuggler: recognizes dock workers = green icons\nDetective: same entities = grey blobs\n\nFog is not darkness —\nit is the absence of your attention." {
|
||||
shape: page
|
||||
style.fill: ${color-screen}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
style.italic: true
|
||||
}
|
||||
|
||||
perf: Performance Budget\n<1ms/frame total\nVision cone = PointLight2D\nFog = CanvasGroup noise shader (Layer 5)\nSound pings = 0-5 sprites\nEntity ghosts = 0-10 sprites typical {
|
||||
shape: package
|
||||
style.fill: ${color-screen}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
|
||||
kg_read -> fog_layers: "determines entity recognition\n(which observer sees which entities)" {
|
||||
style.stroke: ${color-nav}
|
||||
}
|
||||
kg_read -> fog_entities.recognized: "KnowsOf+ → recognized" {
|
||||
style.stroke: ${color-nav}
|
||||
}
|
||||
kg_read -> fog_entities.unrecognized: "Suspects / none → blob" {
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
fog_layers -> fog_entities: "entities rendered within fog state" {
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
fog_layers -> divergence: "same shader, per-character KG" {
|
||||
style.stroke: ${color-nav}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
fog_layers -> perf
|
||||
|
After Width: | Height: | Size: 766 KiB |
@@ -0,0 +1,146 @@
|
||||
# HUD Layout and Z-Stack — D-049, D-048, D-061, D-076
|
||||
# 8-layer z-stack, insert overlay, dialogue box constraints.
|
||||
# Dual-scale grid context: 64x64px visual tiles (D-066).
|
||||
|
||||
vars: {
|
||||
color-screen: "#1a1e24"
|
||||
color-panel: "#2a3040"
|
||||
color-text: "#c8d0e0"
|
||||
color-nav: "#c8d8f0"
|
||||
color-stroke: "#333340"
|
||||
}
|
||||
|
||||
direction: down
|
||||
|
||||
zstack: Rendering Z-Stack (D-049)\n8 layers — bottom to top {
|
||||
style.fill: ${color-screen}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
l0: Layer 0 — Floor Tiles\n(zone identity · movement surface) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l1: Layer 1 — Floor Objects\n(cosmetic · walked over) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l2: Layer 2 — Furniture / Placed Objects\n(y-sorted with entities) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l3: Layer 3 — Entity Sprites\n(y-sorted · D-033 relationship color\n24x32px footprint in 64x64 tile) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l4: Layer 4 — Overhead / Wall Tops\n(pipes · ducts · fixtures · signage\nsemi-transparent partial occlusion) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l5: Layer 5 — Fog of Perception\n(vision cone mask · fog shader\naffects layers 0-4) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l6: Layer 6 — Insert Overlay\n(lattice HUD · bloom-rendered\nNOT affected by fog\nInteraction labels render here) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
l7: Layer 7 — Monologue / UI\n(always visible · top of stack\nDialogue box and response options) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
style.bold: true
|
||||
}
|
||||
}
|
||||
|
||||
insert_overlay: Insert Overlay Design (D-048) {
|
||||
style.fill: ${color-screen}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
bloom: Soft bloom shader\n~2-3px gaussian · ~40% blend {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
smuggler_overlay: Smuggler\nthinner · sparser (baseline lattice) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
detective_overlay: Detective\ndenser · crisper (augmented lattice) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
insert_off: Insert OFF behavior (OQ-07)\nCursor shape changes\nInteraction labels hidden {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
}
|
||||
|
||||
dialogue_box: Dialogue Box (D-061, D-076) {
|
||||
style.fill: ${color-screen}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
position: Bottom of screen\nmax 20% height {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
max_width: Max-width 1200px\n(centered · ~62% of 1920px) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
log: Unified conversation log\n(active + overheard — chronological) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
speaker_format: Speaker to Target format\nper-character name colours {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
responses: Response options below log\nmax 3 visible {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
no_portraits: No portraits\n(NPC is on screen) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
timeout: Entry timeout\n15s + 3s fade (configurable) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
monologue_position: Monologue floats ABOVE dialogue box\n(z-layer 7 — spatial separation\ncharacter thinks while NPC speaks) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
style.border-radius: 4
|
||||
}
|
||||
|
||||
zstack.l5 -> insert_overlay: "does NOT affect" {
|
||||
style.stroke: ${color-nav}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
zstack.l6 -> insert_overlay: "rendered at" { style.stroke: ${color-nav} }
|
||||
zstack.l7 -> dialogue_box: "rendered at" { style.stroke: ${color-nav} }
|
||||
dialogue_box -> monologue_position: "monologue above" { style.stroke: ${color-nav} }
|
||||
|
After Width: | Height: | Size: 678 KiB |
@@ -0,0 +1,153 @@
|
||||
# Interaction UI Flow — D-056, D-057, D-058
|
||||
# Cursor states, entity interaction list, world radial menu.
|
||||
# All insert-styled: geometric, bloom, diegetic.
|
||||
|
||||
vars: {
|
||||
color-screen: "#1a1e24"
|
||||
color-panel: "#2a3040"
|
||||
color-text: "#c8d0e0"
|
||||
color-nav: "#c8d8f0"
|
||||
color-stroke: "#333340"
|
||||
}
|
||||
|
||||
direction: down
|
||||
|
||||
cursor: Cursor States (D-056)\n(insert's own interface element · z-layer 7) {
|
||||
style.fill: ${color-screen}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
default_cursor: Default\n4 thin inward ticks + bloom\nWhite-blue · barely visible {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
entity_hover: Entity Hover\nTicks expand outward (150ms)\nCorner brackets · D-033 relationship color\nVerb tooltip in insert styling {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
object_hover: Object Hover\nTicks rotate 45° → X-shape\nMuted grey (amber if flagged) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
weapon_aim: Weapon Aim\nTicks extend · center gap widens\nLines 1 to 2px · warm white\nNO bloom · D-033 tint on target {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
cursor_rules: Cursor Rules {
|
||||
style.fill: ${color-screen}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
los_trigger: Changes on LOS · not just proximity {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
range: Interaction range ~2 sim tiles (= 1m) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
weapon_suppress: Weapon mode suppresses interaction prompts\n(unless Shift held) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
insert_off: Insert OFF: cursor shape still changes\n(body reacts) · verb labels hidden\n(insert doesn't process targets) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
}
|
||||
|
||||
entity_list: Entity Interaction List (D-057)\n(left-click on entity) {
|
||||
style.fill: ${color-screen}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
format: Compact vertical list\nanchored to entity position\n2-4 options max {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
new_glow: New options: gradient glow background\n(knowledge change signal) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
z_layer: Labels on z-layer 6\n(insert data — hidden if insert off) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
phase1: Phase 1 (simulation): max verb set\nfrom ObjectType component {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
phase2: Phase 2 (observer): filter by KG\narchetype variation · POI flip {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
world_menu: World Radial Menu (D-058)\n(right-click) {
|
||||
style.fill: ${color-screen}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
|
||||
v01_spokes: v0.1: 2 spokes\nObserve (eye) · Insert (phone) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-nav}
|
||||
style.font-color: ${color-text}
|
||||
style.bold: true
|
||||
}
|
||||
future_spokes: Future: up to 6 spokes\n+ Comms (signal) · Wait (clock) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
input: Drag-release (power users)\nClick-click (newcomers) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
why_radial: Fixed categories → spatial memory\n(unlike entity verbs which vary by knowledge) {
|
||||
style.fill: ${color-panel}
|
||||
style.stroke: ${color-stroke}
|
||||
style.font-color: ${color-text}
|
||||
}
|
||||
}
|
||||
|
||||
cursor.default_cursor -> cursor.entity_hover: "entity in LOS\n+ proximity" {
|
||||
style.stroke: ${color-nav}
|
||||
}
|
||||
cursor.default_cursor -> cursor.object_hover: "object in LOS\n+ proximity" {
|
||||
style.stroke: ${color-stroke}
|
||||
}
|
||||
cursor.entity_hover -> cursor.weapon_aim: "weapon selected" {
|
||||
style.stroke: ${color-nav}
|
||||
}
|
||||
cursor.weapon_aim -> cursor.entity_hover: "weapon deselected" {
|
||||
style.stroke: ${color-stroke}
|
||||
style.stroke-dash: 4
|
||||
}
|
||||
|
||||
cursor.entity_hover -> entity_list: "left-click\n→ shows interaction list" {
|
||||
style.stroke: ${color-nav}
|
||||
}
|
||||
cursor.default_cursor -> world_menu: "right-click\n→ opens radial" {
|
||||
style.stroke: ${color-nav}
|
||||
}
|
||||
|
||||
cursor -> cursor_rules
|
||||
entity_list.phase1 -> entity_list.phase2: "filtered" { style.stroke: ${color-nav} }
|
||||
|
After Width: | Height: | Size: 868 KiB |