Files
settled-reach/server/src/test_world/rooms/crowd_plaza.rs
T
jpmschweitzerandClaude Opus 4.6 273d29f26f feat(simulation): sprint 10 — hub teleport, confrontation response, walk-away phase 2, gauntlet rooms 4-7, blocked_entities debug field
#491: PlayerAction::TeleportToHub — moves player to hub spawn, clears
dialogue/monologue/interaction buffer, Gauntlet-only with log warning.
#520: ConfrontationDelivered event — Tier 2 animation shift, relationship
state decrement (D-033), monologue spike emission.
#519: Walk-away Phase 2 — NPC animation shift + routine deviation on
dialogue exit (D-064).
#498: Four new Gauntlet rooms — Interaction Gallery, Fog Theater, Crowd
Plaza, Dialogue Room with constants and wiring.
#514: blocked_entities Vec<u64> on ObserverSnapshot, protocol v9.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 12:58:14 +01:00

86 lines
2.9 KiB
Rust

//! Crowd Plaza — Room 7 (32x32)
//!
//! Density stress test room. 15 NPCs in a 5x3 grid to test perception,
//! snapshot, and tick-budget performance under high entity density.
//! Validates D-026 tick budget holds with many visible entities.
//!
//! Observer position: (16, 16) relative = (96, 94) absolute, facing West.
//!
//! Entities (StableId 34-48):
//! crowd_npc_00..crowd_npc_14 — 15 NPCs in a 5-column x 3-row grid
//! Grid starts at rel (4, 4) = abs (84, 82), spacing: 5x cols, 8y rows.
use bevy_app::prelude::*;
use crate::knowledge::registry::{EntityRegistry, StableEntityId};
use crate::npc::{Contentment, Npc, ToleranceThreshold, Want, WantKind};
use crate::simulation::interaction::Interactable;
use crate::simulation::movement::TilePosition;
use crate::simulation::path_follow::MovementSpeed;
/// Room origin (top-left corner including walls).
const ORIGIN_X: i32 = 80;
const ORIGIN_Y: i32 = 78;
/// Grid layout constants.
const GRID_COLS: usize = 5;
const GRID_ROWS: usize = 3;
const GRID_START_X: i32 = 4;
const GRID_START_Y: i32 = 4;
const GRID_SPACING_X: i32 = 5;
const GRID_SPACING_Y: i32 = 8;
/// WantKind cycle for variety across 15 NPCs.
const WANT_CYCLE: &[WantKind] = &[
WantKind::Wealth,
WantKind::Safety,
WantKind::Knowledge,
WantKind::Connection,
WantKind::Power,
WantKind::Freedom,
WantKind::Justice,
WantKind::Revenge,
WantKind::Happiness,
];
/// Spawn Crowd Plaza entities in canonical order (StableId 34-48).
pub fn spawn_entities(app: &mut App, registry: &mut EntityRegistry) {
let mut index = 0usize;
for row in 0..GRID_ROWS {
for col in 0..GRID_COLS {
let rx = GRID_START_X + col as i32 * GRID_SPACING_X;
let ry = GRID_START_Y + row as i32 * GRID_SPACING_Y;
let pos = TilePosition::new(ORIGIN_X + rx, ORIGIN_Y + ry, 0);
let want_kind = WANT_CYCLE[index % WANT_CYCLE.len()];
let entity = app
.world_mut()
.spawn((
Npc,
Interactable,
pos,
Want {
primary: want_kind,
intensity: ((index % 8) + 2) as u8, // 2-9 range
description: format!("Crowd Plaza NPC #{:02}", index),
},
Contentment {
level: (index as i16 * 7 - 50).clamp(-100, 100),
},
ToleranceThreshold {
current_stress: (index as i16 * 5) % 80,
threshold: 40 + (index as i16 % 4) * 10,
},
MovementSpeed::default(),
))
.id();
let sid = registry.register(entity);
app.world_mut()
.entity_mut(entity)
.insert(StableEntityId(sid));
index += 1;
}
}
}