# Transfer Window: the physics

This is what the game computes, what it simplifies and what it invents. The code
is `sky.js` (where things are), `transfer.js` (route estimates and burns),
`nbody.js`, `flight-route.js` and `flight-free.js` (verified trajectories),
and `engine.js` (the ship and the economy). The numbers below come from the node tests named at
the end.

## Where things are

Frame: heliocentric, ecliptic and mean equinox of J2000. Ephemeris vectors use AU
and AU/day. The adaptive trajectory integrator uses kilometres, kilometres per
second and seconds, switching to local planet-centred coordinates near a world
to retain precision. Gravitational constants use km³/s².

Time: a Julian date is `ms / 86400000 + 2440587.5`. The game treats UTC as TDB
and ignores the 69 s between them. A career starts at UTC midnight of the local
calendar date (or of `?from=YYYY-MM-DD`), clamped to 1 Jan 2026 - 31 Dec 2044, so
a five-year career stays inside the range the planet elements are fitted for.
Day N of a career is that date plus N days.

- **Mercury, Venus, Earth-Moon barycentre, Mars, Jupiter and Ceres** use
  offline [NASA JPL Horizons geometric vectors](https://ssd-api.jpl.nasa.gov/doc/horizons.html).
  The planetary source is DE441; Ceres uses JPL's small-body solution. The
  fetched headers, query settings and source hashes are recorded in
  `data/ephemeris-provenance.json`.
- **The Moon** uses Horizons geocentric vectors. **Earth** is the barycentre
  minus 0.0121506 of the Moon's geocentric vector.
- To fit the mobile download budget, the vectors are stored as scaled 16-bit
  corrections to analytic reference curves: JPL Table 1, the Moon series and
  the yearly Ceres elements. Cubic Hermite interpolation reconstructs the
  correction; velocity is the derivative of the same corrected position.
  Ceres has additional knots at the annual reference-curve boundaries.
  The tables cover 2024–2055, including a margin around playable careers.
  Dates outside a table's range are refused rather than extrapolated.
- **The asteroid belt** is scenery: 1,454 main-belt asteroids brighter than
  H 11.6 from JPL's Small-Body Database, Ceres excluded. Each follows a
  Sun-only orbit.

The original annual 2026–2049 accuracy targets are restored in `test-sky.js`.
An additional 576 independent Horizons vectors at fractional dates between
bake nodes must stay within 50 km and 1 m/s, including the Moon and Ceres.
These are measured interpolation bounds on those dates, not a navigation
accuracy guarantee. The reference curves alone missed the original targets;
they are no longer used without the Horizons correction.

Gravitational parameters come from the Horizons headers. Jupiter's barycentre
header has none, so Jupiter uses DE440's GM for its system, 126,712,764.1 km³/s².

## Routes

The chart first estimates a route using patched conics. A selected route must
then pass numerical verification before Launch becomes available. The ship feels
the Sun, Mercury, Venus, Earth, Moon, Mars, Jupiter and Ceres throughout the
verified flight. The planets follow prescribed ephemerides; this is a restricted
many-body ship simulation, not a mutually integrated Solar System.

- **Lambert**: single revolution, prograde, universal variables (Curtis,
  Algorithm 5.2). It refuses near-0° and near-360° transfers and any path whose
  perihelion is inside 0.25 AU (the heat limit).
- **Burns at the planets (the Oberth effect)**: with v∞ the speed left over
  outside the planet's pull, a burn from a parking orbit of radius rp costs
  `√(v∞² + 2μ/rp) − √(μ/rp)`. Parking altitudes: Mercury 200 km, Venus 300,
  Earth 400, Mars 300, Ceres 200. Leaving 400 km Earth orbit for a Hohmann
  transfer to Mars costs 3.57 km/s; settling into 300 km Mars orbit, 2.09.
- **The route chart**: 27 flight times per pair, from 0.3 to 1.6 times the
  Hohmann time (at least 20 days), against departure days. A full chart of up to
  9,720 cells takes about 15 ms in node on beast.
- **Windows** (`data/windows.js`) and the cheapest-route curve
  (`data/mincurve.js`) were scanned at 2-day steps from 1 Jul 2025 to
  31 Dec 2050 by `tools/bake-transfer-windows.mjs`, from the same code. A window is a
  local minimum of the cheapest Δv that is the lowest within ±60 days and has a
  rise of at least 1 km/s within ±120 days. The real Earth→Mars window of this
  synod opens on 1 Nov 2026 at 5.65 km/s and 311 days.
- **Verified routes**: an adaptive Dormand–Prince 5(4) integrator and iterated
  arrival targeting refine the estimated flight. A correction is limited to
  0.3 km/s; the actual destination periapsis must lie within 50 km of the intended
  parking altitude. The recorded arrival date, correction and burns determine
  launch affordability and contract deadlines. A failed cell can try at most
  eight neighboring cells; it cannot silently become a launchable estimate.
- **Free flight**: the burn arrow sets v∞ in the port's prograde, radial
  (outward) and normal directions. The full force model can produce a gravity
  assist without spending propellant at the encounter. An offered course
  correction, limited to 2 km/s, remains a separate explicit action and is
  numerically verified. Without a selected destination, the first qualifying
  pass is offered; a later, closer pass cannot replace it. The home world's
  initial 30 days are excluded from that encounter search.
- **Escape**: a path is gone once it is unbound from the Sun and past 3.3 AU,
  outside Ceres's aphelion and the outer belt. From each port's parking orbit the
  least prograde burn that leaves is about 8.8 km/s from Earth, 7.9 from Mars,
  6.9 from Ceres, 10.6 from Venus and 20 from Mercury (it varies a little with
  the date).

## The ship

| | |
|---|---|
| Drive exhaust speed | **15.5 km/s** (about 1,580 s specific impulse). Invented: a nuclear drive that has been studied but never flown. The one number the game makes up. |
| Dry mass | 30 t. Upgrades weigh nothing. |
| Propellant | 60 t tank, 96 t with drop tanks or the refit; a new career starts with 36 t |
| Crates | metals 1 t, water ice 1 t, food 0.5 t, tech 0.25 t, contract crates 0.5 t |
| Reach | `15.5 · ln((30 + propellant + cargo) / (30 + cargo))` km/s: 12.2 with 36 t and an empty hold, 17.0 with 60 t, 22.2 with 96 t |

Burns are instant. Propellant for a route is `m0 · (1 − e^(−Δv/15.5))` on the
whole wet mass; burns in a row with nothing dropped between them add up to one
burn of their sum. Station tugs line up your parking orbit with the departure
before you leave, so its orientation costs nothing.

## The economy

- Propellant costs **4 cr per tonne**, times 0.75 at Earth, times a daily factor
  between 0.9 and 1.1.
- A contract pays `(800 + 180 × the Δv of the pair's next window + 95 × crates)`,
  times 0.85-1.15, rounded to 10 cr. Its deadline is the next window's departure
  plus its flight time plus 45-150 days. A destination whose next window costs
  more than the drop-tank reach (22.2 km/s) is never offered.
- Goods prices, the 15,000 cr refit, cargo pods (4,500) and drop tanks (3,500)
  are the original game's.

**Current tuning and evidence (2026-10-06).** Propellant is 4 cr/t,
the contract coefficient is 180, deadline slack is 45–150 days and exhaust
speed is 15.5 km/s. All 96 specified careers escape using actual verified
flights: median1011.723days, slowest1698.939, longest inability to leave100days.
These satisfy the unchanged win, pacing, five-year and availability gates.
An additional16 held-out careers also win (median866.963, slowest1559.268,
longest inability88days); their dates/seeds are in the balance checkpoint.
These are sampled results, not a proof for every player strategy or seed.

The economy test uses real flight verification by default. `PHYSICAL=0`
retains the old conic diagnostic and unchanged assertions; with these settings
it wins95/96 and its median987 misses the target. Estimated arrivals therefore
cannot certify the full-gravity game's economy.

The paired reward/deadline change follows rejected isolated tuning trials.
No winning bot was deliberately slowed; goods prices, refit cost, ship drive
and five-year limit remain unchanged. Existing accepted contracts retain their
saved terms; newly posted work uses these settings.

## What is simplified or scenery

- The inexpensive route grid and traffic arcs are patched-conic estimates.
  Actual launches and free flights use the numerical force model. Ephemeris
  accuracy is still limited by the published approximate elements described
  above; small integration error does not imply mission-navigation accuracy.
- Burns are instant; finite burns and their losses are left out.
- The asteroids and the other freighters follow simple orbits around the Sun and
  pull on nothing. Freighters leave on real windows: three for a window under
  8 km/s, two under 12, one up to 16.5. That keeps 8-34 in flight on any day
  2026-2049.
- The system view is three-dimensional with enlarged planet discs for
  visibility. Distances and local orbit geometry retain physical scale.
  The SVG fallback uses the same projection. The camera and visual particles
  do not change numerical flight outcomes.

## Names and saves

The ports are Mercury, Venus, Earth, Mars and Ceres, and the code uses those
names as ids. Before the real system the game had fictional stations; an older
save is converted on load: cinder → mercury, verdance → venus, harbor → earth,
rime → mars, vesper → ceres; fuel units become tonnes (× 6: a 10-unit tank is
60 t, a 16-unit tank 96 t); the career starts on today's date. Saves are schema
version 2 under `tw-sol-current`.

## Tests

From the repository root, in node: `escape/test-sky.js` (ephemeris against
Horizons, dates, velocities, the belt), `escape/test-transfer.js` (Kepler,
Lambert, the real windows, the bakes, traffic), `escape/test-physics.js`
(conservation, the Oberth burn against an integrated hyperbola, the rocket
equation, launch guards), `escape/test-routes.js` (228 monthly start dates: every
pair reachable, Mercury↔Ceres labelled, escape from every port, no port stranded
for more than 200 days), `escape/test-economy.js` (the planning bot) and
`escape/test-worker.js` (the route worker). Numbers describe this model, not a
real mission's.

## Full-gravity verification

`test-nbody-core.js` checks conservation, reversible frame conversion,
determinism and defensive ephemeris-cache copies. `test-flight-route.js` verifies
60 real routes and arrival altitude; the 2026-10-06 optimized run measured
83.5 ms median and 222 ms maximum verification on Beast. These timings are
machine-specific, not a guarantee on every phone.

`test-flight-free.js`, `test-flight-flyby.js` and
`test-flight-encounters.js` cover free flight, heat/escape termination,
gravity assists, explicit correction and earliest encounter selection.
The strong-bend example and the low-cost Venus-to-Mercury correction example
currently use separate trajectories. They do not establish the combined scenario. After a bounded 3,426-candidate
search found no combined winner, the integration owner adopted the specification's
explicit M2 fallback: report that part unmet, retain the mandatory visible bend,
and omit Help's claim that it can be a cheaper way elsewhere.

`test-flight-worker.cjs` exercises the real worker, stale-result cancellation
and bounded adjacent-cell recovery. Flight output includes dense local
departure/arrival arcs and bounded system samples; stored trajectories, rather
than a new random integration, restore an interrupted playback.
