Bundle of uncommitted working-tree edits across combat engine, expedition
cycle, flavor pools, and TwinBee/zone narration. Includes new files:
combat_debug.go, dnd_boss_consumables.go, dnd_dex_floor.go, plus
CHANGES_24H.md and REBALANCE_NOTES.md scratch notes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Harvest tables (expedition + standalone) now keyed by node_id; legacy
room-idx entries auto-migrate via read-fallback + drop-on-save.
- Narration salts swapped from run.CurrentRoom to narrationCadence(run)
(= len(visited_nodes)-1) so flavor pickers survive G9 column drop.
- !zone map renders the graph (BFS by PosX/PosY) when the gate is on:
✓/▶/· status, ╳ for locked-only edges, secrets hidden until visited.
- Region-boundary hook in graph advance/!zone go updates expedition
CurrentRegion + visited list when from/to nodes differ — without
burning supplies or retiring runs (the graph IS the run state).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GM→DM rename across docs and code (GMNarrationType→DMNarrationType,
GMState→DMState, narration constants, comments) so the system reads as
"Dungeon Master" everywhere. Player-visible "GM mood" wording stays
where it appears in flavor.
Streamed zone/expedition combat: zone advance now stages patrol →
patrol play-by-play → patrol resolution → room intro → room play-by-play
→ final outcome through sendZoneCombatMessages with 2–3s pacing
(arena keeps its 5–8s window). Combat narrative lines pick up a compact
d20-vs-AC roll annotation for hit/crit/miss/block events.
Combat outcome polish: dndHPSnapshot lets narration show sheet HP
rather than legacy combat-engine HP, and markAdventureDead clears the
zombie state where hp_current was 0 but the legacy alive flag stayed
true after a D&D-layer KO.
Adv 2.0 announcement (ADVENTURE_2.0_ANNOUNCEMENT.md), README rewrite
covering the new layer, and adv2_scenario_test.go — a full
zone-run + expedition + harvest playthrough against a copy of the prod
DB asserting persisted state end-to-end.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
High-priority fixes from the multi-agent audit of Adventure 2.0:
- Phase 11 nil-deref cluster: zoneOrFallback() helper replaces 8 unsafe
getZone(_) sites in dnd_zone_cmd.go. Corrupted zone IDs render a
placeholder instead of panicking.
- Briefing/recap idempotency: deliverBriefing/deliverRecap now claim
the rollover via a conditional UPDATE. Double-fires from clock skew
or restart become no-ops; supply burn and day++ no longer reapply.
- Graceful ticker shutdown: AdventurePlugin gains stopCh + Stop(); all
11 background tickers now select on stopCh in addition to ticker.C.
- Mood decay (§3.2): math.Round(elapsed*2) replaces int() truncation
so sub-hour gaps decay correctly.
- 24h auto-abandon (§4.3): getActiveZoneRun returns clean slate and
abandons stale runs whose LastActionAt is over 24h old.
- Respec / auto-migrate orphan cleanup: !respec and the auto-migrated
draft wipe now abandon active zone runs and expeditions before
deleting the dnd_character row.
- Phase R combat-link: applyBossDefeatThreat now wired from
resolveBossRoom (-20 threat); applyRoomCombatThreatForUser adds
+5/+8 from non-boss/elite kills (§8.1).
- Starvation → forced extraction: briefing-time check forces extract
with §10.2 coin tax when supplies hit zero.
- GMNat20/Nat1 narration wired into resolveCombatRoom and
resolveBossRoom (nat-20 takes precedence over nat-1).
- Treasure-undo race: LoadAndDelete on both timer-fire and `undo`
paths so only one side wins.
- Battle Master: Disarming, Menacing, Parry maneuvers added (3 → 6
of 10). Remaining 4 (Pushing, Goading, Riposte, Commander's Strike)
documented inline as needing ally/reaction mechanics the engine
doesn't model.
- Threat-70 warning: tracked in RegionState["siege_warning_fired"]
so a drop-and-recross doesn't re-fire the beat.
- region_state JSON decode error now logged via slog.Warn instead
of silently discarded.
Failing TestProdDB_DnDLayer fixed via option (a): track migrated
characters and only run round-trip / idempotency assertions on those,
skipping pre-existing prod-DB rows accumulated from live bot use.
New tests in dnd_audit_phase_R7_test.go cover: 24h auto-abandon,
briefing double-fire idempotency, threat-70 warning idempotency,
multi-region extract→resume state preservation, and starvation
forced-extraction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a TwinBee aside on room entry when GM mood sits at the extreme
bands (≤19 hostile, ≥80 effusive). Mid-bands stay silent — the aside is
strictly extra flavor, never replacing core narration. Two new pools
(MoodAsidesHostile, MoodAsidesEffusive) live alongside the existing
TwinBee voice in twinbee_gm_flavor.go. Wired into zoneCmdEnter and
zoneCmdAdvance; the advance path reloads the run so post-combat
nat20/nat1 deltas are reflected before band lookup.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires the prewritten flavor.TauntResponses and flavor.ComplimentResponses
pools to the existing MoodEventTaunt (-10) / MoodEventCompliment (+5)
mood deltas. Both subcommands require an active run and report the new
mood band after applying the delta. Deterministic line selection per
(runID, roomIdx) so repeated taunts in the same room are stable.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires the eight prewritten *PhaseTwoLines pools (Valdris / HollowKing /
Aldric / Thyrak / Ilvaras / Thornmother / Infernax / Belaxath) into
resolveBossRoom. When the combat event log shows enemy HP crossing the
zone's PhaseTwoAt threshold, a TwinBee phase-two callout is injected
between the boss-stat header and the win/loss line. Bosses without a
phase-two transition (Grol, Aboleth) are unaffected.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds zone_underdark, zone_feywild_crossing, zone_dragons_lair, and
zone_abyss_portal flavor files with elite-room intros, boss-entry
pools (where canonical twinbee_gm_flavor.go didn't already ship one),
boss ability callouts, and zone-specific lore. Wires the four pools
into zoneRoomEntryPool / bossEntryPool / bossSignaturePool /
eliteRoomEntryPool / zoneLorePool, and replaces the now-obsolete
"unflavored zone" assertions with Tier 4-5 positive routing tests.
RoomEntryUnderdark, RoomEntryDragonsLair, BossEntryInfernax, and
BossEntryBelaxath are reused verbatim from twinbee_gm_flavor.go per
the canonical-flavor-first rule.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New additive flavor files (zone_manor_blackspire_flavor.go,
zone_underforge_flavor.go) with elite-room intros, boss ability
callouts, and zone lore. Manor reuses RoomEntryHauntedManor from
twinbee_gm_flavor.go; Underforge had no canonical RoomEntry/BossEntry
pools yet, so both are defined in the new zone file.
Aldric Blackspire: Multiattack (life drain) / Charm / Children of the
Night / Mist Form / Phase Two
Emberlord Thyrak: Molten Strike / Forge Breath / Living Forge /
Construct Resilience / Phase Two
Wires zoneRoomEntryPool, bossEntryPool, zoneLorePool,
bossSignaturePool, and eliteRoomEntryPool to the new tier-3 pools.
Adds Tier 3 routing tests for boss-entry, elite line, lore, and
room-entry overlays.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New additive flavor files (zone_forest_shadows_flavor.go,
zone_sunken_temple_flavor.go) with elite-room intros, boss ability
callouts, and zone lore. Reuses existing RoomEntryForestShadows and
BossEntryHollowKing from twinbee_gm_flavor.go. The Sunken Temple had
no canonical RoomEntry/BossEntry pools yet, so both are defined in the
new zone file.
Hollow King: Corrupting Aura / Root Surge / Devour Light / Phase Two
Dreaming Aboleth: Tentacle Multiattack / Enslave / Mucus Cloud /
Legendary Actions
Wires zoneRoomEntryPool, bossEntryPool, zoneLorePool,
bossSignaturePool, and eliteRoomEntryPool to the new tier-2 pools.
Updates the D2b "no callout pool" test to use Dragon's Lair (still
unflavored) and adds Tier 2 routing tests for boss-entry, elite line,
lore, and room-entry overlays.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New additive flavor files (zone_goblin_warrens_flavor.go,
zone_crypt_valdris_flavor.go) with elite-room intros, boss ability
callouts (Grol: Surprise Attack / Heart of Hruggek / Terrifying Roar;
Valdris: Corrupting Touch / Legendary Resistance / Call of the Grave /
Phase Two), and zone-specific lore deep-dives. Existing
twinbee_gm_flavor.go is untouched per the protected-files contract.
Wires three narration helpers in dnd_zone_narration.go:
composeBossEntry — boss-entry render plus a one-line ability callout
eliteRoomEntryLine — elite-room atmospheric prefix
zoneLorePool — zone-specific !lore pool with generic fallback
Boss-entry callsite in dnd_zone_cmd.go now uses composeBossEntry; the
elite branch of resolveCombatRoom prefixes with the zone's elite line.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires the existing internal/flavor TwinBee GM pools into the !zone
state machine. Adds GMNarrationType, mood band derivation, the §3.2
mood-event delta table, and ±2/hr passive decay toward 50. Zone enter
narrates the entry room; advance narrates each subsequent room (boss
rooms use the named BossEntry* pools, completion uses ZoneComplete
and applies MoodEventZoneComplete). Line selection is deterministic
on (runID, roomIdx) so repeat reads render the same prose.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>