Auto-walk: gate on fork/rest, slow cadence, credit DnD streak

Four fixes for the auto-walk loop that was re-clearing the same room
every 15 min while a fork was pending, ignoring the rest lockout, and
not counting expedition activity toward the daily streak:

- advanceOnceWithOpts / runAutopilotWalk now short-circuit to stopFork
  when NodeChoices has a pending fork. Stops phantom kills + duplicate
  loot drops + fork re-prompts on the same cleared room.
- fireExpeditionAutoRuns honors restingLockoutRemaining so the
  background ticker no longer walks through a long rest.
- autoRunCooldown 15m -> 2h, autoRunTickInterval 5m -> 15m. Auto-walk
  DMs are now a once-in-a-while ping, not a steady drip.
- markActedToday + HasActedToday recognise LastActionDate. Wired into
  !rest short/long, !expedition start/abandon, !extract, foreground
  !zone advance, and !zone go so DnD-side activity credits the streak
  even when the expedition ends before midnight.

(cherry picked from commit 9e27fd8257a4c92150ad584b393bf5a72270b82c)
This commit is contained in:
prosolis
2026-05-18 17:16:04 -07:00
parent e4518c9c39
commit 01d2329993
7 changed files with 76 additions and 5 deletions

View File

@@ -308,6 +308,9 @@ func (p *AdventurePlugin) zoneCmdMap(ctx MessageContext) error {
b.WriteString(renderZoneGraphMap(g, run))
b.WriteString("\n```\n")
b.WriteString("_E=Entry ?=Exploration T=Trap ★=Elite ☠=Boss ⚿=Secret · ✓ cleared ▶ here · pending locked_")
if path := renderVisitedPath(g, run); path != "" {
b.WriteString("\n**Path:** " + path)
}
return p.SendDM(ctx.Sender, b.String())
}
// No registered graph (defensive — every zone has one post-G8).
@@ -455,8 +458,23 @@ func (p *AdventurePlugin) advanceOnceWithOpts(ctx MessageContext, compact bool)
reason: stopBlocked,
}, nil
}
// compact==true is the background auto-walk path; only credit
// player-initiated advances toward the daily streak.
if !compact {
markActedToday(ctx.Sender)
}
_ = applyMoodDecayIfStale(run)
zone := zoneOrFallback(run.ZoneID)
// A pending fork means advanceTransitionGraph already cleared the
// current room and stopped — re-running resolveRoom would re-fire
// combat and re-drop loot on the same room. Re-emit the fork prompt
// and let the caller surface it; the player commits via !zone go <n>.
if pf, derr := decodePendingFork(run.NodeChoices); derr == nil && pf != nil {
return advanceResult{
final: renderForkPrompt(zone, *pf),
reason: stopFork,
}, nil
}
prev := run.CurrentRoomType()
prevIdx := run.CurrentRoom