mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 16:42:41 +00:00
159daf8fc87ceb77c521491226cafd6fda889db7
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
159daf8fc8 |
Phase 2b (lever): wounded-entrant surprise-nick clamp
The post-2a tier-lethality trace showed the remaining 0% completion was driven by chained surprise-round nicks on already-wounded fighters, not by the elites themselves. Pattern from the trace: fight day=5 Hobgoblin Warchief: hp_pre=24 → hp_post=14 WON fight day=5 Goblin Archer: nick=6, hp_pre=8 → hp_post=0 LOST The Warchief left the fighter at HP 14; the Goblin Archer's surprise nick (6 HP) dropped them to 8 before combat resolved — and a standard goblin then finished a fighter who should have survived. Same shape at T2 (Dire Wolf nick 4 on hp=3), T3 (Fire Elemental nick 4 on hp=5), T4-T5. The nick was acting as a hidden cascade multiplier, pre-empting the combat engine on wounded entries. clampSurpriseNick caps the nick at max(1, hpCurrent/5) when the fighter enters wounded (HPCurrent < HPMax); at full HP the raw nick stands. The existing 'nick < HPCurrent' KO-guard is preserved as a backstop. /5 is the wounded-fighter lethality knob; tighter (/10) is gentler, looser (/3) re-opens the cascade. Live caller (runHarvestInterrupt) and harness (runHarnessFight) both route through the new helper so the sim measures the same lever the live caller applies. Matrix delta is mild (encs +0.1-0.2 per cell, completion% still 0%) but the tier-lethality trace stretches substantively: T1 trial 0 ran 5→8 encs / 5→7 days, T3 trial 1 saw a fighter survive multiple chained interrupts at low HP that pre-2b would have ended on nick alone. The remaining deaths are now legible as elite-one-shot fights on fresh entries (Warchief, Green Hag, Roper, Young Red Dragon) — that's the Phase 2c roster-gate signal. Push-back on the original lever-order: the Phase 2a recap put roster gate first, but the trace fingerprint named the wounded-entry nick as the dominant cause-of-death in 4 of 5 tier traces. Doing nick-cap first keeps Phase 2c's diagnostic clean and avoids re-tuning rosters after another lever changes the shape under us. Pre-existing failures unrelated to this change: - TestAdv2Scenario_ZoneRunGoblinWarrens (advance regression, prior) - TestMageSpellbookLineInRender (render assertion, prior) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
04aa887d18 |
Phase 2a (lever): expedition retreat semantics split
Phase 2 diagnostics named the InterruptElite bracket as the likely
first lever; tier-walking the lethality probe at the matrix cadence
told a different story. Phase 1's uniform-0% baseline isn't an
elite-bracket calibration issue at all — every tier reads 0% because
the engine's TimedOut contract was being ignored by every expedition
caller.
combat_engine.go:451 says: "Timeout = retreat, not lethal blow.
Caller treats a timeout loss as 'fight ended, no character death'".
But runHarvestInterrupt / tryPatrolEncounter / resolveCombatRoom all
called abandonZoneRun + retireAllRegionRuns on any !PlayerWon —
ending the expedition outright on a retreat. The retreat flavor line
("X outlasts you. You retreat from the expedition, wounded but alive")
was already in the code, just stapled to an actual run-abort.
Splits the policy by caller:
• runHarvestInterrupt — autopilot daytime interrupt. TimedOut →
retreat: threat +5, HP carries over, run continues, harvest slot
forfeit (no kill / loot). HP<=0 still ends the run + marks dead.
• tryPatrolEncounter — !advance pre-room patrol roll. Same
retreat policy: patrols don't gate progress, so retreating from
one and walking into the next room is the right shape.
• resolveCombatRoom — !advance room/elite combat. Unchanged —
this path gates room progression; a retreat has nowhere to go, so
any loss still ends the run. (Manual zone runs were always
intended to end here.)
Harness mirrored: daytime interrupt timeout → carry HP + threat bump
+ continue day; night-encounter loss → terminate (mirrors
resolveCombatRoom, since live night encounters defer to !advance).
retreatThreatBump = 5 is the per-retreat threat penalty. Low enough
not to compound brutally with chained retreats, high enough that 3–4
retreats noticeably walks the threat clock toward Stirring. Easy to
dial in Phase 3 if zones go off-band.
Phase 1 matrix after the change still reads 0% completion at every
cell — but the encounter counts and survival shape are dramatically
different (T4 underdark 3.6→7.5 encs; T3 underforge trial saw 18
encounters across 10 days where the pre-change run died on day 2/3).
Adds TestExpeditionBalance_Phase2_TierLethality, a tier-walking
companion to the T1/rolls=1 probe, that traces every fight at the
matrix cadence across one zone per tier — the actual Phase 2b lever
work picks from this data, not the old T1-only probe.
The remaining 0% is now legibly driven by tier-disproportionate elite
rosters (Hobgoblin Warchief at T1, Green Hag at T2, Roper/Helmed
Horror higher up) that one-shot or two-shot tier-appropriate
fighters. Phase 2b's lever shortlist:
1. Roster gate / SpawnWeight tuning to dilute over-tier elites.
2. Surprise-nick floor reduction on chained interrupts (carryover
HP + nick is the death-spiral fingerprint at T1 specifically).
3. Per-day cadence reduction if 1+2 don't carry T1 to band.
Pre-existing test failures (TestAdv2Scenario_ZoneRunGoblinWarrens,
TestMageSpellbookLineInRender) verified to fail identically on HEAD;
no new test regressions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
0f09a421bc |
Phase 2 (diag): cadence sweep, gear-tier fix, lethality probe
Three Phase 2 diagnostic artifacts. No tuning knob has moved on
production code yet — these tests calibrate the harness and surface
the real first lever for next session.
1) Cadence calibration sweep
TestExpeditionBalance_Phase2_CadenceCalibration sweeps
HarvestRollsPerDay ∈ {1,2,3,4} across the full Phase 1 matrix and
logs per-cell + per-tier completion. Required a new
HarvestRollsPerDay field on expeditionBalanceProfile so cells can
override the package-default constant. Finding: cadence is NOT the
dominant lever — at rolls=1 the T1 cell only reaches 2%, with
bimodal hp_left (100% survivors / 0% deaths). Killed the cadence
hypothesis from Phase 1's commit message.
2) Gear-tier centerline fix
phase1TierCenterline bumped for T3/T4/T5 (8→9, 11→13, 15→17). The
shared gearTier ladder (5/9/13/17 boundaries) was placing T3/T4/T5
centerlines one gear bracket *below* the zone's tier, so those
cells fought with under-spec'd weapons/armor. New centerlines are
the lowest level in each tier's design-doc range where gearTier ==
tier. All centerlines still inside their design-doc ranges. Effect
in the sweep at rolls=1: underforge T3 1.0% → 10.5% comp, underdark
T4 flipped from pure combat-death to 14% starve (i.e. fighter now
survives combat, runs out of food). Real bug, but small — the
structural lethality problem remains.
3) Lethality probe + traceFight hook
TestExpeditionBalance_Phase2_LethalityProbe runs 5 trials at the
cleanest cell (T1 goblin_warrens L3 fighter, rolls=1) with a new
optional traceFight hook on expeditionHarness that logs
monster/AC/atk/HP-pre/HP-post/outcome per fight. Hook is nil in
production runs, zero cost when unused. Finding: at T1, the
InterruptElite branch keeps drawing Hobgoblin Warchief (AC 18,
atk +5) from goblin_warrens' elite roster, and an L3 fighter has
~coin-flip odds against a CR-6-ish elite. One bad draw = dead;
that's the bimodal hp_left fingerprint from the sweep. Non-elite
draws (Worg, AC 13) play out as normal multi-round combats and
are winnable.
Next-session lever choices, in order of suspected impact:
- Roster gate: Hobgoblin Warchief out of (or weighted down in)
the T1 elite pool — it's tier-disproportionate for goblin_warrens.
- InterruptElite threshold: rarer elite-bracket draws at low threat
so a single d20 swing doesn't equal expedition end.
- Tier-floor cap on already-over-tier bestiary entries.
Plan doc: gogobee_expedition_difficulty.md §Phase 2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
53d1608490 |
Phase 0: expedition-difficulty sim harness spike
New file internal/plugin/expedition_balance.go — sibling to dnd_class_balance.go, no dnd_ prefix per feedback_avoid_dnd_naming. Plan doc: gogobee_expedition_difficulty.md. Critical de-risk settled: clock-injection seam. The harness does not run the wall-clock tickers (expeditionBriefingTicker @ 06:00, expeditionRecapTicker @ 21:00, expedition_ambient @ 3h) and does not inject a virtual time.Now. Instead, advanceExpeditionOneDay reimplements the morning→day→night pipeline by calling the math-pure helpers directly: applyDailyBurn, dailyThreatDrift, resolveCombatInterrupt, resolveWanderingCheck, simulateCombatWithRNG. No DB, no goroutines, no clock. Phase 0 trade-offs (documented in the file header): - Boss completion deferred; survive-N-days is the proxy. - Per-region zones, loot/XP, pardon/Sovereign, babysit, temporal stack effects all skipped — Phase 1+ scope. - Encounter cadence (harnessHarvestRollsPerDay=4) is a placeholder to be calibrated against live traces in Phase 1. Tests: - TestExpeditionBalance_Phase0_Spike — T2 Crypt Valdris × L5 Fighter, 100 trials, asserts only degenerate sentinels (no 0%/100%, days>0, days<=cap). Runs in <3s. - TestExpeditionBalance_Phase0_SeedSpread — confirms the RNG seam is actually wired by showing two distinct seeds produce different trials. Full byte-for-byte reproducibility under same seed is not asserted at Phase 0; surpriseRoundNick + pickWanderingMonster draw from package-global rand (same caveat as class balance). Spike numbers (calibration baseline, NOT a target): 1% completion, 99% deaths, median 4 days, ~6 encounters. The headline death rate is loud but expected — Phase 1's full matrix will diagnose whether it's HP-carryover punishment, bestiary-vs-abstract-monster delta, or kit ladder mismatch. Phase 2 is where the centerline gets tuned. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |