Skip to content

Movers step 2: Movers panel, looping routes, encounter cadence - #184

Merged
wvaske merged 2 commits into
mainfrom
movers-step2-tab
Oct 24, 2026
Merged

wvaske merged 2 commits into
mainfrom
movers-step2-tab

Conversation

@wvaske

@wvaske wvaske commented Oct 24, 2026

Copy link
Copy Markdown
Owner

Step 2 of the movers plan.

  • Movers panel (DM only, between Party and History): every NPC token on every map with location, journey/ETA, mode + pace, encounter cadence, posting note; Route / Halt / Loop / Shown actions; rows on other maps switch the view and fly to the token. Backed by a DM-only CampaignState.movers summary (runtime.moverSummaries()), empty for players.
  • Groups: retinues carry a kind (retinue / army / band / caravan / beast / other); storage key unchanged.
  • Loops: token.route stores waypoints + loop; at the end of a looping route the mover re-plans the circuit from where it stands and keeps walking on that tick.
  • Encounter cadence: encounterEveryMiles rolls rollEncounter on the terrain table every N miles, logged DM-only (data.traveller); never halts the mover. Counters restored by undo.
  • Tests: 3 new cases in retinue-travel.test.ts; suite green (shared 129, server 330).

🤖 Generated with Claude Code

Step 2 of the movers plan. A DM-only Movers panel between Party and
History lists every NPC token on every map (new DM-only
`CampaignState.movers` from `runtime.moverSummaries()`): where it stands,
its journey and ETA, mode and pace, encounter cadence and posting note,
with Route / Halt / Loop / Shown actions. A row on another map switches
the view and flies to the token.

Retinues gain a `kind` (retinue, army, band, caravan, beast, other) so the
same grouping serves armies and roaming encounters. `token.route` keeps
its waypoints and a `loop` flag: a looping mover re-plans the circuit at
the end and keeps walking on the same tick. `encounterEveryMiles` rolls on
the terrain's encounter table every N miles of travel, logged DM-only; the
mover is not halted. Undo restores both counters.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-24T22:41:22.015075Z ecc8770 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@wvaske
wvaske merged commit 6a7f991 into main Oct 24, 2026
1 check passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ecc87707f7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +137 to +142
if (remaining.length === 0 && token.loop && token.waypoints.length && !looped) {
const again = planRoute(runtime, map, { ...token, q: cur.q, r: cur.r }, token.waypoints);
if (again.length) {
remaining = again;
looped = true;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Replan every completed patrol circuit

When one clock advance contains enough travel time to finish both the original route and the first replanned circuit, !looped prevents another replan. The token is then persisted with an empty route, and future advances skip it at the token.route.length === 0 guard, permanently stopping a mover still marked as looping. Continue replanning completed circuits while credit remains, with a guard only for routes that cannot produce any steps.

Useful? React with 👍 / 👎.

Comment on lines +122 to +123
if (miles >= token.encounterEveryMiles) {
miles = 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve excess distance after encounter checks

For cadences that are not exact multiples of milesPerHex, resetting miles to zero discards distance already traveled beyond the threshold. For example, 6-mile hexes with a 10-mile cadence check at mile 12 and then forget the extra 2 miles, producing checks every 12 miles rather than carrying progress toward the next 10-mile threshold; cadences smaller than one hex can also require multiple checks. Subtract the threshold and retain the remainder, repeating as needed.

Useful? React with 👍 / 👎.

Comment on lines +83 to +84
if (m.mapId !== activeMapId) send({ kind: 'view.map', mapId: m.mapId });
focusToken({ id: m.tokenId, q: m.q, r: m.r });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Defer focusing until the requested map arrives

When a mover is on another map, view.map only requests an asynchronous snapshot, while focusToken immediately emits a focus request against the currently loaded map. CanvasEngine consumes and clears that request synchronously, and the later map snapshot performs its normal recenter, so the advertised cross-map row action switches maps but does not fly to the mover. Retain the requested focus until the snapshot with m.mapId is active.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant