mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 08:32:41 +00:00
J3 D8-f #2: T4 difficulty lift (leaders-define-band) + feywild fork1 soft-lock fix
T4 monster tuning so martial leaders land in the 60-75% band (underdark 59/80, feywild 65/84 at L10/L12, n=50); casters trail (class-side gap that monster tuning provably can't compress -- Pass 1 showed casters pinned at 0% while martials moved). T5 deferred (walls everyone at its L12 floor; needs an L15-16 corpus). - dnd_bestiary.go: underdark elite/boss HP+AC up + caster-lethal proc cuts (mind_flayer/drow_mage/roper); feywild HP+AC up. - bestiary_srd.go: feywild multiattack profiles (fomorian/night_hag/green_hag) + Thornmother 2->3 lashes -- HP/AC alone didn't move feywild's low-damage roster; multiattack is what pulls facerolling martials into band. - zone_graph_feywild_crossing.go: free fork1's marsh edge. fork1 was the only fork in the game with every exit skill-locked (CHA+Perception, no LockNone) and deterministic no-retry rolls -- a prod SOFT-LOCK stranding ~60% of players (low CHA+WIS). Kept grove's CHA bargain as a bonus route. - expedition_sim.go: firstUnlockedForkChoice -- sim fork policy picks the first unlocked option instead of blind 'go 1' (which looped forever on locked forks); halts fork_all_locked if none. - tests: graph-wide TestZoneGraphs_NoSoftLockedFork + fork1 free-path guard. Writeup: sim_results/d8f_findings.md
This commit is contained in:
@@ -55,16 +55,23 @@ func TestFeywildCrossingGraph_PartialOverlap(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestFeywildCrossingGraph_NoFreeChoiceAtFork1 captures the design
|
||||
// intent: both fork1 outgoing edges are locked. The player must succeed
|
||||
// at CHA or Perception to enter; no LockNone fallback.
|
||||
func TestFeywildCrossingGraph_NoFreeChoiceAtFork1(t *testing.T) {
|
||||
// TestFeywildCrossingGraph_Fork1HasFreePath guards the no-soft-lock
|
||||
// invariant: fork1 must offer at least one LockNone exit. The original
|
||||
// design locked BOTH edges (CHA + Perception) with no fallback — fork
|
||||
// rolls are deterministic with no retry, so a character failing both was
|
||||
// permanently stranded (D8-f part 2 found this stranded ~60% of runs).
|
||||
// Every other zone fork has a free path; fork1 must too.
|
||||
func TestFeywildCrossingGraph_Fork1HasFreePath(t *testing.T) {
|
||||
g := zoneFeywildCrossingGraph()
|
||||
free := 0
|
||||
for _, e := range g.outgoingEdges("feywild_crossing.fork1") {
|
||||
if e.Lock == LockNone {
|
||||
t.Errorf("fork1 has unlocked edge to %s — expected all locked", e.To)
|
||||
if e.Lock == LockNone || e.Lock == "" {
|
||||
free++
|
||||
}
|
||||
}
|
||||
if free == 0 {
|
||||
t.Error("fork1 has no free (LockNone) exit — soft-lock: a player failing every skill check is permanently stranded")
|
||||
}
|
||||
}
|
||||
|
||||
// TestFeywildCrossingGraph_FirstCHALock confirms this zone uses
|
||||
|
||||
Reference in New Issue
Block a user