Skip to content

Fly a seat nobody is in, and hand it over when someone arrives (milestone 9a: AI backfill) - #31

Merged
sbddesign merged 1 commit into
mainfrom
feat/ai-backfill
Sep 6, 2026
Merged

sbddesign merged 1 commit into
mainfrom
feat/ai-backfill

Conversation

@sbddesign

Copy link
Copy Markdown
Contributor

Milestone 9, part A. A host's seat with no peer in it used to fly a neutral stick in a straight line — before anyone joined, or after a player dropped, forever: a ghost the squadron shot for free, and the thing your ship on the host turns into the moment the link drops. Now the seat is flown.

What it does

  • src/game/autopilot.ts — the pilot of a seat nobody has taken. A proportional controller with a seeded jink that steers from the same RunSnapshot a scripted pilot gets (bearing and range to the lock, hull, heat, pod bearings): fires down its nose inside a 0.35 rad cone within 900 units, opens the throttle beyond 260 and backs off inside 170, wanders while closing so two wingmen do not fly one line, detours to a repair pod under 40 % hull, turns hard off the star, and circles at cruise when nothing is locked rather than flying out of the arena. It sees nothing a console cannot and produces the same Controls a keyboard does; aim is null and spread is zero and seat admission drops them anyway. It is not EnemyPilot, and it is meant to hold a seat rather than win the match for whoever takes it.
  • net/session.tscreateHost flies every peer-less seat on its autopilot (HostOptions.backfill, default on; HostStats.backfilled counts the ticks). A peer that arrives takes the seat over mid-flight: accept seeds the seat's throttle hold from what the autopilot was flying, so the peer's first intents ramp from there instead of from launch throttle and the hull does not lurch on the handover tick. A peer that drops hands the seat back the next tick — accept already gave a human any peer-less seat, so this is what makes "an arriving human takes a seat that is already flying" (the Roster design note) true today.
  • core/rng.tsSTREAM.wingman, offset by seat, so a seed replays the same match whether or not anyone joined.

What it deliberately does not do

  • Mirrors do not know a seat is AI: the kill feed reads P2 DOWN either way. A bot bit in the snapshot seat flags is a follow-up once there is a spare bit worth spending.
  • No merge of the enemy squadron into the roster (queue → seat assignment, win-rule rewrite). Bigger than what it buys right now.
  • The lobby (hull choice on HELLO, LOBBY frame, WING panel, seat count from the URL) is part B.

Evidence

  • simcheck 618 → 629: the autopilot was flying, armed and at speed when a peer arrived; a peer-less seat fires and lands hits over 20 s, never leaves the arena, is every tick backfilled and none held, replays byte-identical from its seed, holds still with backfill off (and that is a different match); a peer that arrives takes over without a single autopilot shot after, ramps from the autopilot's throttle within one tick's rate, and the hull never moves more than one tick's travel across the handover; a peer that drops hands the seat back.
  • Mutation gate: five new mutants (empty seat holds instead of being flown; autopilot keeps flying a taken seat; takeover starts from launch throttle; autopilot never fires; autopilot steers away from its target), all caught; full gate 120/120 caught, 0 survived, 0 not testable, at 2bd4e69. (The first run at 4b1830a had the takeover mutant survive: the test handed the seat over to a wreck, whose stale throttle could not see the hold. It now hands over to a flying, armed seat and bounds the throttle step across the whole window; the mutant fails by hand with a 0.40 step where the rate allows 0.019.).
  • Balance contract holds; single-seat recorded baseline unchanged (no seat to backfill); typecheck + build clean.

Try it

Open ?host and launch alone: seat 2 fights beside you. Share the code; the joiner takes that ship over where it is. Close the joiner's tab: the ship keeps fighting on the host, and RETRY puts the joiner back in it.

🤖 Generated with Claude Code

A host's seat with no peer flew a neutral stick in a straight line — before
anyone joined, or after a player dropped, forever. Now the seat's autopilot
flies it from the same RunSnapshot a scripted pilot gets, through the same
seat admission a peer gets, seeded per seat so a seed replays the same match.
A peer that arrives takes the seat over mid-flight, ramping from the throttle
the autopilot held so the hull does not lurch; one that drops hands it back.

simcheck: a peer-less seat scores hits, never leaves the arena, replays from
its seed, holds still with backfill off, is taken over without a shot from
the autopilot after or a jump across the handover, and is handed back on a
drop (618 -> 628). Five mutants on the takeover, the hold, the trigger and
the steer.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Stephen DeLorme <stephen@d.elor.me>
@vercel

vercel Bot commented Sep 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
neon-orbit Ready Ready Preview Sep 4, 2026 9:04pm UTC

Request Review

@sbddesign
sbddesign merged commit 6a73896 into main Sep 6, 2026
4 checks passed

This branch was successfully deployed

1 active deployment
Preview 2bd4e69c Deployed Sep 4, 2026 by vercel[bot]
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