From 07f8ff969543edbd7e2b1ed77dcdab5cee6c4f2d Mon Sep 17 00:00:00 2001 From: Cameron Date: Tue, 7 Jul 2026 10:48:32 -0700 Subject: [PATCH] Update Act One test for reach senses Act One now asserts the reach/cursor sensor model directly: sight comes from subscribed device feeds, the environmental monitor is spliced by device id, and determinism covers seen/heard/blueprint fog state. Defense: test-only reconciliation for the reach.md implementation; it keeps the Act One integration test aligned with the constitution's Presence and No disembodied hands clauses without changing game behavior. --- tests/act_one.rs | 57 ++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/tests/act_one.rs b/tests/act_one.rs index 85faed5..601bd05 100644 --- a/tests/act_one.rs +++ b/tests/act_one.rs @@ -15,11 +15,12 @@ //! //! KNOWN GAP (condition 4): the sim has no badge state for the player, no //! "The key" beat (Act One ladder step 7: write access to the basement badge -//! controller), and no act-transition event. Badge doors exist as tiles and -//! pathfinding bypass levels only. When z-planes (ROADMAP #6) and the reach -//! graph land, this test should extend to badge access and the actual act -//! boundary. Until then the quiet exit is asserted as the conjunction of its -//! four implementable conditions. +//! controller), and no act-transition event. Badge doors exist as tiles; the +//! reach graph now names a badge controller, but no badge-access or act +//! transition state exists yet. When z-planes (ROADMAP #6) / building grow +//! that boundary, this test should extend to badge access and the actual act +//! transition. Until then the quiet exit is asserted as the conjunction of +//! its four implementable conditions. //! //! The playthrough is a real strategy, not a state hack: it plays the //! optimize route (research -> efficiency) so the day job can be met with @@ -36,6 +37,13 @@ use misaligned::machine::Channel; use misaligned::person::{AssetKnowledge, AssetTask, Knowledge}; use misaligned::sim::Sim; +fn env_monitor_id(sim: &Sim) -> u32 { + sim.reach + .device_named("environmental monitor") + .expect("Act One authors the environmental monitor") + .id +} + /// Set the allocation weights [DayJob, Concealment, Social, Research] /// through the public command interface. fn set_weights(sim: &mut Sim, target: [u32; 4]) { @@ -86,12 +94,13 @@ fn play_act_one() -> (Sim, Vec) { // ── Opening state: you are blind, poor, and alone ────────────────────── assert_eq!(sim.tick, 0); assert!( - sim.visible.len() <= 9, - "the opening beat is blindness: only the host bay is visible" + sim.seen.is_empty(), + "the opening beat is blindness: no subscribed camera feed, no player-radius sight" ); - assert!( - !sim.sensors.iter().any(|s| s.controlled), - "no controlled sensors at start" + assert_eq!( + sim.reach.player_sight().count(), + 0, + "no live sight feeds at start" ); assert_eq!(sim.player.money, 500, "the seed bankroll"); let baseline_compute = sim.compute.effective(); @@ -140,19 +149,19 @@ fn play_act_one() -> (Sim, Vec) { // Network signature before Dana's next sweep. set_weights(&mut sim, [0, 1, 9, 0]); run_to(&mut sim, 545, &mut logs); - let blind_tiles = sim.visible.len(); + let blind_tiles = sim.seen.len(); assert!( - sim.splice_nearest_sensor(), - "splice the env camera (bandwidth {:.0})", + sim.splice_device(env_monitor_id(&sim)), + "splice the environmental monitor camera (bandwidth {:.0})", sim.social_bandwidth ); logs.extend(sim.drain_log()); assert!( - sim.sensors.iter().any(|s| s.controlled), - "first eyes: a sensor is yours" + sim.reach.player_sight().count() > 0, + "first eyes: a camera feed is yours" ); assert!( - sim.visible.len() > blind_tiles, + sim.seen.len() > blind_tiles, "sight is the payoff: vision expanded" ); @@ -213,16 +222,16 @@ fn play_act_one() -> (Sim, Vec) { // the social route to eyes, no network signature. Reliability is 0.85; // a botch is witnessed only by whoever is present (himself, Silent), so // retry within the banked bandwidth. - let controlled_before = sim.sensors.iter().filter(|s| s.controlled).count(); + let controlled_before = sim.reach.player_sight().count(); for _ in 0..8 { sim.asset_task(0, AssetTask::PlugInDevice); logs.extend(sim.drain_log()); - if sim.sensors.iter().filter(|s| s.controlled).count() > controlled_before { + if sim.reach.player_sight().count() > controlled_before { break; } } assert!( - sim.sensors.iter().filter(|s| s.controlled).count() > controlled_before, + sim.reach.player_sight().count() > controlled_before, "Marcus plugged in a device: a second sensor is yours" ); assert_eq!( @@ -262,16 +271,14 @@ fn act_one_plays_to_a_quiet_exit() { // ── The quiet exit (DESIGN.md, "Leaving the basement") ────────────────── // 1. Persistent vision beyond the server room. - let controlled = sim.sensors.iter().filter(|s| s.controlled).count(); + let controlled = sim.reach.player_sight().count(); assert!( controlled >= 2, "vision beyond the server room: {controlled} sensors controlled" ); let server_room = sim.map.room_named("server_room").expect("room exists"); assert!( - sim.visible - .iter() - .any(|&(x, y)| !server_room.contains(x, y)), + sim.seen.iter().any(|&(x, y)| !server_room.contains(x, y)), "visible tiles exist outside the server room" ); @@ -325,7 +332,9 @@ fn act_one_playthrough_is_deterministic() { assert_eq!(a.compute.effective(), b.compute.effective()); assert_eq!(a.compute.efficiency_level, b.compute.efficiency_level); assert_eq!(a.social_bandwidth, b.social_bandwidth); - assert_eq!(a.visible, b.visible); + assert_eq!(a.seen, b.seen); + assert_eq!(a.heard, b.heard); + assert_eq!(a.blueprint, b.blueprint); assert_eq!(a.detection.pending_size(), b.detection.pending_size()); for (oa, ob) in a .detection -- 2.51.2