From 252fcaadc2d44c3f515047cb0793923f691ea48d Mon Sep 17 00:00:00 2001 From: Chris Guidry Date: Wed, 5 Aug 2026 08:00:46 -0400 Subject: [PATCH] Reset the campaign recorder's narration between turns CampaignListener cleared its input and speaker at turn start but never its narration, so every delta appended to one buffer for the whole session and each done wrote the whole running history to the transcript. Every turn re-appended every earlier turn's narration, so a multi-turn session grew the transcript unboundedly and drowned the player's own lines in a full copy of the conversation. turn_start now clears the narration buffer the way the scanner clears its own, and a two-turn test guards it. --- src/bus.rs | 5 +++++ src/bus_tests.rs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/bus.rs b/src/bus.rs index 97a7307..f0a6e57 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -183,6 +183,11 @@ impl Listener for CampaignListener { fn turn_start(&mut self, input: &str, speaker: Speaker) { self.input = input.to_string(); self.speaker = speaker; + // Clear last turn's narration. `delta` appends to this all turn + // long, and `done` writes it whole, so without the reset every + // turn would replay every earlier turn's narration into the + // transcript, growing it unboundedly. + self.narration.clear(); } fn delta(&mut self, text: &str) -> Flow { diff --git a/src/bus_tests.rs b/src/bus_tests.rs index 2ab2307..c87a857 100644 --- a/src/bus_tests.rs +++ b/src/bus_tests.rs @@ -363,3 +363,36 @@ fn default_listener_methods_do_not_panic() { bus.cancelled("partial"); bus.failed("error"); } + +#[test] +fn campaign_listener_does_not_replay_earlier_turns_narration() { + use crate::campaign::Campaign; + use crate::campaign::GameTime; + + let dir = tempfile::TempDir::new().unwrap(); + let campaign = Campaign::open(dir.path()).unwrap(); + let mut bus = TurnBus::new(); + bus.add(Box::new(CampaignListener::new(Some(campaign)))); + + // First turn. + bus.turn_start("I wake up.", Speaker::Player); + let _ = bus.delta("You wake in a cold cell."); + bus.done("You wake in a cold cell."); + + // Second turn, later that day. Without the reset in turn_start, this + // would re-append the first turn's narration before its own. + let campaign = Campaign::open(dir.path()).unwrap(); + campaign + .mark(GameTime::parse("#d1-0900").unwrap(), "time passes", None) + .unwrap(); + bus.turn_start("I sit up.", Speaker::Player); + let _ = bus.delta("The bars are iron."); + bus.done("The bars are iron."); + + let campaign = Campaign::open(dir.path()).unwrap(); + let sections = campaign.transcript_entries().unwrap(); + let bodies: Vec = sections.into_iter().map(|e| e.body).collect(); + assert_eq!(bodies.len(), 2); + assert_eq!(bodies[0], "player> I wake up.\n\nYou wake in a cold cell."); + assert_eq!(bodies[1], "player> I sit up.\n\nThe bars are iron."); +} -- 2.51.2