adventure: T6 Phylactery Verses + stackable-rebirth engine primitive (P8)

The second Layer-2 postgame boss mechanic, and the first stateful in-combat one.
Valdris ("boss_valdris_ascendant", the Ossuary Ascendant) is bound to three
Verses hidden on the zone's secret nodes: every Verse the player finds and walks
before the fight unbinds one rebirth, every Verse they skip leaves it armed. A
full-clear explorer strips all three and fights a mortal lich; a speedrunner who
blows past the secrets fights a god who will not stay down.

New engine primitive: stackable rebirth. The stock survive_at_1 is a one-shot
1-HP stay; Valdris needs several rebirths that each restore a real pool.
combatState/CombatStatuses gain EnemyReviveCharges/EnemyReviveHP (round-tripped
through the turn engine so a suspend/resume keeps the live count), and enemyDown
consumes a charge after the survive_at_1 check, reviving to 25% of the
party-scaled max and emitting a phylactery_rebirth event. Zero for every
non-Valdris fight.

Unlike Greed Tax (a pure per-round recompute in applyBossRunModifiers), rebirths
are spent mid-fight, so the charge count is seeded ONCE at session creation
(seedBossRunStatuses, from unvisited secret Verses) and never re-derived on the
per-round enemy rebuild. Seeded from handleFightCmd after startPartyCombatSession.

Sim A/B (millenia, n=120 L20 party+Pete+pets, same binary, control neuters the
dispatch): mortal end (verses found) fighter 42.5% -- reproduces the deployed P7
ossuary baseline, confirming the mechanic doesn't touch the validated full-clear
path -- and the god end (0 verses) fighter 12.5%, a deadly-but-beatable flex arm.
The sim walks 0 verses (autopilot takes the first unlocked fork; Verses are
behind Perception locks), so the A/B brackets the whole player-agency gradient.

Claude-Session: https://claude.ai/code/session_0156WqjgsbmSY2U8eQ3Kkb1s
This commit is contained in:
prosolis
2026-07-16 08:04:19 -07:00
parent fc9e055083
commit 686434f8e3
7 changed files with 239 additions and 0 deletions

View File

@@ -119,6 +119,17 @@ func (p *AdventurePlugin) handleFightCmd(ctx MessageContext) error {
return p.replyDM(ctx, "Couldn't start the fight: "+err.Error())
}
// Layer-2 boss state that is spent mid-fight (Valdris's Phylactery Verses)
// is seeded onto the fresh session ONCE, from the route the player walked to
// get here — not on the per-round rebuild, which would resurrect spent
// rebirths. enemyHP is the party-scaled pool persisted above. No-op for every
// non-hooked enemy.
if seedBossRunStatuses(sess, monster.ID, enemyHP, run) {
if err := saveCombatSession(sess); err != nil {
return p.replyDM(ctx, "Couldn't start the fight: "+err.Error())
}
}
var b strings.Builder
if isBoss {
if line := composeBossEntry(zone.ID, run.RunID, run.CurrentRoom); line != "" {