{"version":3,"sources":["sunlight.mjs"],"sourcesContent":["// Kubicor — WHERE THE SUN IS, FOR THE ENERGY RULE (the owner, Oct 7: \"energy charges only in sunlight, on both client\n// and server\"). SHARED byte-for-byte: public/sunlight.mjs and functions/lib/sunlight.mjs (generate-version-hash.js\n// fails the build on drift).\n//\n// energy.mjs evaluates a stance's sunlight from a small numeric DESCRIPTOR; this builds that descriptor from the\n// generated system, so the Cloud Functions can store one on the user doc when a player stands somewhere and every\n// spender — submitEdits, spendEnergy, the zone server, and the client's own gauge — reads the same thing back.\n//\n// THE SKY IS THE RENDERER'S, REPLAYED. system-view.js places every body from the wall clock (SIM_EPOCH, SIM_RATE) with\n// orbital and spin rates drawn by assignDynamics on its own `#dyn` rng, and turns a version 3 planet as its climate\n// says (followClimateRotation). Those rates are not stored anywhere, so this replays the same walk — the same draws in\n// the same order, including the ones whose values nothing here needs, because an rng one draw out of step returns\n// plausible wrong answers. functions/lib/dynamics.mjs is an older replay of the same walk for the share cards; it still\n// discards twelve draws per gas giant that the renderer stopped making on Sep 17 (gasStyle is seeded per body now), so it\n// is NOT the one used here. This one follows today's assignDynamics, line for line, and tests/sunlight.test.mjs holds\n// it to the live client's dump.\n//\n// The system engine is passed in (`eng`: makeRng, getCategory, getMass, getPhysicsSpeed) rather than imported, because\n// the two copies of the engine have different names on the two sides (public/system-engine.js, functions/lib/\n// system-engine.mjs) and a byte-identical file can only import what is spelt the same in both places.\nimport { placeOf, distanceToStar, HZ_BASE } from './temperature.mjs';\nimport { rotationOf } from './climate.mjs';\nimport { yearDaysFor, yearDaysRound, tiltOf, yearPhaseAt, axisLean, rockDeg, DAY_MS } from './seasons.mjs';\nimport { SIM_EPOCH_MS, SIM_RATE } from './energy.mjs';\nimport { ECL_DESC_MAX } from './eclipse.mjs';\n\n// system-view.js's constants, restated (tests/sunlight.test.mjs reads them out of the renderer and compares).\nexport const ROT_VIS = { Star: 240, Gas: 2200, Moon: 1800, Rocky: 1500 };\nexport const PLANET_DAY = 1800;\nexport const PERIOD_K = PLANET_DAY * ROT_VIS.Rocky;\nconst PROGRADE_FACTOR = 2.5, KEPLER_GAP = 0.97;\nexport const VOX_MAX_STARS = 2;\n// The six non-polar corners of the corner-up cube, by local azimuth, AS THE RENDERER HAS THEM: system-view.js reads them\n// off a BoxGeometry it rotated, whose positions are float32, so four of the six sit a few 1e-9 rad off the odd multiples\n// of 15 degrees they stand for (-15, -135, 105, -75, 45, 165). Kept to the renderer's bits, not the ideal angles, so a\n// locked world's sky here is the sky it draws; tests/sunlight.test.mjs rebuilds them from the geometry and compares.\nexport const CORNER_AZIMUTHS = [-0.2617993955709617, -2.356194490192345, 1.8325957223658584, -1.308996931223935, 0.7853981633974483, 2.8797932580188315];\n// The six faces of a world, in BoxGeometry's order (turf.mjs's too): +x, −x, +y, −y, +z, −z.\nexport const FACES = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]];\n\n// WHICH FACE a body-local position stands on: its largest coordinate, by sign — the face whose normal is the walker's\n// up everywhere but the last kube before an edge.\nexport function faceOf(pos) {\n  if (!pos) return null;\n  const x = +pos.x, y = +pos.y, z = +pos.z;\n  if (![x, y, z].every(Number.isFinite)) return null;\n  const ax = Math.abs(x), ay = Math.abs(y), az = Math.abs(z);\n  const a = (ax >= ay && ax >= az) ? 0 : (ay >= az ? 1 : 2);\n  return a * 2 + (((a === 0 ? x : a === 1 ? y : z) >= 0) ? 0 : 1);\n}\n\n// The renderer's VOXEL_CORNER_UP (three's Quaternion.setFromUnitVectors from (1,1,1)/√3 to +Y) applied to a direction,\n// in three's own order of operations (as dynamics.mjs writes it).\nexport function cornerUp(d) {\n  const s = 1 / Math.sqrt(3);\n  let qx = s * 0 - s * 1, qy = s * 0 - s * 0, qz = s * 1 - s * 0, qw = s + 1;\n  let l = Math.sqrt(qx * qx + qy * qy + qz * qz + qw * qw);\n  l = 1 / l; qx *= l; qy *= l; qz *= l; qw *= l;\n  const vx = d[0], vy = d[1], vz = d[2];\n  const tx = 2 * (qy * vz - qz * vy), ty = 2 * (qz * vx - qx * vz), tz = 2 * (qx * vy - qy * vx);\n  return [vx + qw * tx + qy * tz - qz * ty, vy + qw * ty + qz * tx - qx * tz, vz + qw * tz + qx * ty - qy * tx];\n}\n\n// assignDynamics (system-view.js), replayed onto a freshly generated system. Sets, on every body, exactly what the\n// renderer's per-frame positioning reads: _orbitOmega, rotOmega, baseSpin, tidalLock, cornerIndex, cornerAz (and the\n// display-only _rotOmega, kept so the draws that make it stay in step).\nexport function assignDynamics(s, seedStr, eng) {\n  const { makeRng, getCategory, getMass, getPhysicsSpeed } = eng;\n  const rr = makeRng(seedStr + '#dyn');\n  const mA = getMass(s), mB = s.companion ? getMass(s.companion) : 0;\n  const rotFor = (b, tidal) => {\n    const cat = getCategory(b);\n    b.tidalLock = tidal;\n    b.cornerIndex = Math.floor(rr() * CORNER_AZIMUTHS.length);\n    b.cornerAz = CORNER_AZIMUTHS[b.cornerIndex];\n    b.baseSpin = rr() * Math.PI * 2;\n    if (tidal) { b.rotOmega = 0; b._rotOmega = b._orbitOmega; }\n    else {\n      const key = cat === 'Star' ? 'Star' : cat === 'Gas' ? 'Gas' : (b.isMoon ? 'Moon' : 'Rocky');\n      const sizeScale = cat === 'Star' ? 1200 / Math.max(b.diameter, 1) : 1;\n      b.rotOmega = ROT_VIS[key] * (0.8 + rr() * 0.4) * sizeScale;\n      b._rotOmega = b.rotOmega;\n    }\n  };\n  const walkPlanets = (host, hostMass) => {\n    (host.children || []).forEach(p => {\n      p.isMoon = false;\n      p._orbitDist = host.laneDistances[p.lane];\n      p._orbitOmega = getPhysicsSpeed(hostMass, p._orbitDist);\n      rotFor(p, !p.companion && rr() < 0.45 / p.lane);              // SHORT-CIRCUITS: a planet with a companion makes no lock draw\n      if (p.companion) { p.companion.isMoon = false; p.companion._orbitOmega = p._orbitOmega; p.companion._orbitDist = p._orbitDist; rotFor(p.companion, false); }\n      (p.children || []).forEach(m => {\n        m.isMoon = true;\n        m._orbitDist = m.logicalDist;\n        const physics = getPhysicsSpeed(getMass(p), m.logicalDist) * 20;\n        m._orbitOmega = Math.max(physics, p._orbitOmega * PROGRADE_FACTOR);\n        rotFor(m, rr() < 0.8);\n      });\n    });\n  };\n  if (s.companion) {\n    const binOmega = getPhysicsSpeed(mA + mB, s.layout.sep);\n    s._orbitOmega = binOmega; s.companion._orbitOmega = binOmega;\n    s._orbitDist = null; s.companion._orbitDist = s.layout.sep;\n    rotFor(s, false); rotFor(s.companion, false);\n  } else { s._orbitOmega = 0; s._orbitDist = null; rotFor(s, false); }\n  if (s.binaryType === 'far') { walkPlanets(s, mA); walkPlanets(s.companion, mB); }\n  else walkPlanets(s, mA + mB);\n  if (s.isRogue) { (s.children || []).forEach(m => { m.isMoon = true; }); return s; }   // no star: no day to derive, and nothing here charges\n  const isLandable = b => getCategory(b) === 'Rocky';\n  const targetW = () => PERIOD_K / ((20 + rr() * 40) * 60);\n  const hzDistOf = (host) => {                                    // system-view.js hzDistOf\n    const L = (host.luminosity ?? 1) + (host === s && s.companion && s.binaryType !== 'far' ? (s.companion.luminosity ?? 1) : 0);\n    return HZ_BASE * Math.sqrt(Math.max(L, 1e-6));\n  };\n  const deriveHost = (host) => {\n    const planets = (host.children || []).slice().sort((a, b) => a.lane - b.lane);\n    planets.forEach(p => {\n      const moons = (p.children || []).filter(isLandable).sort((a, b) => (a.logicalDist || 0) - (b.logicalDist || 0));\n      const ws = moons.map(() => targetW()).sort((a, b) => b - a);\n      moons.forEach((m, i) => m._targetW = ws[i]);\n    });\n    planets.forEach(p => {\n      const moons = (p.children || []).filter(isLandable);\n      p._orbitCeil = moons.length ? Math.min(...moons.map(m => m._targetW)) / (PROGRADE_FACTOR - 1) : null;\n    });\n    let prev = Infinity;\n    planets.forEach(p => {\n      let cap = prev * KEPLER_GAP;\n      if (p._orbitCeil != null) cap = Math.min(cap, p._orbitCeil);\n      p._orbitOmega = Math.max(Math.min(p._orbitOmega, cap), 1e-6);\n      if (p.tidalLock) p._rotOmega = p._orbitOmega;\n      if (p.companion) { p.companion._orbitOmega = p._orbitOmega; if (p.companion.tidalLock) p.companion._rotOmega = p._orbitOmega; }\n      prev = p._orbitOmega;\n    });\n    // B3½, THE YEAR (World Seasons): each planet's orbit slowed to one real orbit in 4-28 days by its place in the order.\n    const hz = hzDistOf(host);\n    planets.forEach((p, i) => {\n      const days = yearDaysRound(host, i, planets.length, (host.laneDistances[p.lane] || 0) / hz);\n      const w = PERIOD_K / (days * 86400);\n      p._yearDays = days; p._orbitOmega = w;\n      if (p.tidalLock) p._rotOmega = w;\n      if (p.companion) { p.companion._yearDays = days; p.companion._orbitOmega = w; if (p.companion.tidalLock) p.companion._rotOmega = w; }\n    });\n    planets.forEach(p => (p.children || []).forEach(m => {\n      if (isLandable(m)) { m._orbitOmega = p._orbitOmega + m._targetW; if (m.tidalLock) m._rotOmega = m._orbitOmega; }\n    }));\n    planets.forEach(p => {\n      const pStar = p._orbitOmega || 0;\n      if (isLandable(p) && !p.tidalLock) p.rotOmega = p._rotOmega = pStar + targetW();   // B5 turns the world by its seeded day (World Seasons)\n      if (p.companion && isLandable(p.companion) && !p.companion.tidalLock) p.companion.rotOmega = p.companion._rotOmega = pStar + targetW();\n      (p.children || []).forEach(m => { if (isLandable(m) && !m.tidalLock) m.rotOmega = m._rotOmega = pStar + targetW(); });\n    });\n  };\n  if (s.binaryType === 'far') { deriveHost(s); deriveHost(s.companion); }\n  else deriveHost(s);\n  return s;\n}\n\n// assignAddresses (system-view.js): every body's dotted address, by lane.\nexport function assignAddresses(s) {\n  const base = `${s.galaxy}.${s.system}`;\n  const byLane = (b) => (b.children || []).slice().sort((a, b2) => a.lane - b2.lane);\n  const tagMoons = (p, pAddr) => byLane(p).forEach((m, j) => { m._addr = `${pAddr}.${j + 1}`; });\n  const tagHosted = (host, starAddr) => byLane(host).forEach((p, i) => {\n    const n = i + 1;\n    if (p.companion) { const a = `${starAddr}.${n}a`; p._addr = a; p.companion._addr = `${starAddr}.${n}b`; tagMoons(p, a); }\n    else { const a = `${starAddr}.${n}`; p._addr = a; tagMoons(p, a); }\n  });\n  if (s.companion && s.binaryType === 'far') { s._addr = `${base}.1`; tagHosted(s, `${base}.1`); s.companion._addr = `${base}.2`; tagHosted(s.companion, `${base}.2`); }\n  else if (s.companion) { s._addr = `${base}.1`; s.companion._addr = `${base}.2`; tagHosted(s, `${base}.0`); }\n  else { s._addr = `${base}.1`; tagHosted(s, `${base}.1`); }\n  return s;\n}\n\n// followClimateRotation (system-view.js): a version 3 rocky planet turns as its climate says. `gvOf(addr)` is the\n// world's generation version (a claim's, or the newest for an unclaimed world); below 3 the drawn dynamics stand.\nexport function followClimateRotation(s, gvOf, getCategory, makeRng) {\n  if (!s || s.isRogue) return s;\n  const hosts = s.binaryType === 'far' ? [s, s.companion] : [s];\n  for (const host of hosts) for (const p of host.children || []) {\n    if (p.companion || getCategory(p) !== 'Rocky') continue;\n    if (!(gvOf(p._addr) >= 3)) continue;\n    const rot = rotationOf({ addr: p._addr, star: host.name }), locked = rot.regime === 'locked';\n    if (locked) { const v = cornerUp(rot.dir); p.cornerAz = Math.atan2(v[2], v[0]); p.cornerIndex = null; }\n    if (locked === !!p.tidalLock) continue;\n    p.tidalLock = locked;\n    if (locked) { p.rotOmega = 0; p._rotOmega = p._orbitOmega; }\n    else { p.rotOmega = p._rotOmega = (p._orbitOmega || 0) + PERIOD_K / ((20 + 40 * makeRng(p._addr + '#climate-day')()) * 60); }   // its own seeded 20-60 minute day, which it turns by\n  }\n  return s;\n}\n\n// Everything the per-frame positioning needs, for every body: the system with dynamics and addresses, ready to ask.\nexport function systemForSun(s, eng, gvOf) {\n  if (!s) return null;\n  assignDynamics(s, `${s.galaxy}.${s.system}`, eng);\n  assignAddresses(s);\n  followClimateRotation(s, gvOf || (() => 99), eng.getCategory, eng.makeRng);\n  return s;\n}\n\n// updateScene / updatePlanetSystem, as phasor sums: where a body is, as Σ r·(cos(a − w·T), sin(a − w·T)), flattened.\n// Also the angle a tidal lock follows (setSpin's orbAngle), as [startAngle, omega], and its YEAR's (setSpin's yearAngle\n// and yearDays: its planet's orbit, a moon's too) as [startAngle, omega, yearDays].\n// A moon's offset from its planet, and each of a pair's from their centre, is TIPPED into the planet's equator (the\n// owner's Worlds and Axes decisions, Oct 11: moonPlane = EQUATOR, pairs = EQUATOR; system-view.js orbitPlaneOf), so it\n// is not a phasor in the plane but one on a tipped circle: `tip`, [r, a, w, e1x, e1y, e1z, e2x, e2y, e2z], adding\n// r·(cos(a − w·T)·e1 + sin(a − w·T)·e2), where e1 and e2 are the equator's two axes (equatorOf). Absent where the\n// planet stands straight up or is locked to its star, whose moons keep the system plane (locked = MEAN): those offsets\n// stay in `pos`, exactly as before.\nfunction locate(s, body, eng) {\n  const { getMass, getPhysicsSpeed } = eng;\n  const comp = s.companion;\n  const starA = comp ? [s.layout.r1, comp.startAngle + Math.PI, s._orbitOmega] : [];\n  const starB = comp ? [s.layout.r2, comp.startAngle, s._orbitOmega] : [];\n  if (body === s) return { pos: starA, orb: null };\n  if (comp && body === comp) return { pos: starB, orb: null };\n  const hosts = s.binaryType === 'far' ? [[s, starA], [comp, starB]] : [[s, []]];   // a near binary's planets circle the barycentre\n  for (const [host, centre] of hosts) {\n    for (const p of host.children || []) {\n      const P = centre.concat([host.laneDistances[p.lane], p.startAngle, p._orbitOmega]);\n      const yr = [p.startAngle, p._orbitOmega, p._yearDays];\n      // round the planet: on its equator's tipped circle, or (none) in the plane as it always was\n      const round = (r, a, w, orb) => { const e = equatorOf(p, yr, eng); return e ? { pos: P, tip: [r, a, w].concat(e), orb, yr } : { pos: P.concat([r, a, w]), orb, yr }; };\n      if (p.companion) {\n        const bSpeed = getPhysicsSpeed(getMass(p) + getMass(p.companion), p.layout.sep) * 20;\n        if (body === p) return round(p.layout.r1, p.companion.startAngle + Math.PI, bSpeed, [p.startAngle, p._orbitOmega]);\n        if (body === p.companion) return round(p.layout.r2, p.companion.startAngle, bSpeed, [p.startAngle, p._orbitOmega]);\n      } else if (body === p) return { pos: P, orb: [p.startAngle, p._orbitOmega], yr };\n      for (const m of p.children || []) if (body === m) return round(m.logicalDist, m.startAngle, m._orbitOmega, [m.startAngle, m._orbitOmega]);\n    }\n  }\n  return null;\n}\n// THE PLANET'S EQUATOR, as system-view.js orbitPlaneOf reads it: the lean setSpin puts before a planet's spin (seasons.mjs\n// axisLean, the turning branch), carrying the plane's axes x̂ and ẑ to e1 and e2: [e1x, e1y, e1z, e2x, e2y, e2z]. For a\n// planet that turns the lean is fixed in space (its bearing is the same at every moment, see leanTermsFor), so it is\n// worked out once, at the epoch. null where the renderer lays its moons flat: a planet LOCKED TO ITS STAR (its moons keep\n// the system plane while its axis nods, locked = MEAN), one with no seasons to lean by (under 1° of tilt, no year: a\n// rogue's), and anything leanOf does not lean (it leans rocky worlds and, since giants = LEAN, gas giants).\n// The rotation is three's setFromAxisAngle(k, lean) about k = (sin d, 0, −cos d), written out by Rodrigues' formula for\n// the two axes: R·v = v cos g + (k × v) sin g + k (k·v)(1 − cos g), with k × x̂ = (0, kz, 0) and k × ẑ = (0, −kx, 0).\nfunction equatorOf(p, yr, eng) {\n  const cat = eng.getCategory(p);\n  if ((cat !== 'Rocky' && cat !== 'Gas') || p.isTransient || (p.tidalLock && !p.isMoon) || !yr || !(yr[2] > 0)) return null;\n  const lean = axisLean(tiltOf(p._addr), false, yearPhaseAt(p._addr, yr[2], SIM_EPOCH_MS), yr[0]);\n  if (!lean) return null;\n  const kx = Math.sin(lean.dir), kz = -Math.cos(lean.dir), c = Math.cos(lean.lean), sg = Math.sin(lean.lean), u = 1 - c;\n  return [c + kx * kx * u, kz * sg, kx * kz * u,\n          kx * kz * u, -kx * sg, c + kz * kz * u];\n}\nexport function bodyAt(s, addr) {\n  let hit = null;\n  const walk = (b) => { if (!b || hit) return; if (b._addr === addr) { hit = b; return; } (b.children || []).forEach(walk); if (b.companion) walk(b.companion); };\n  walk(s);\n  return hit;\n}\n// lightingStars (system-view.js): the system's stars, a near binary's companion included, at most two; none in a rogue.\nexport function lightingStarsOf(s) {\n  if (!s || s.isRogue) return [];\n  const out = (s.binaryType === 'far' && s.companion) ? [s, s.companion] : [s];\n  if (s.companion && out.indexOf(s.companion) === -1) out.push(s.companion);\n  return out.slice(0, VOX_MAX_STARS);\n}\n\n// THE DESCRIPTOR for standing on face `face` of the world at `addr` (see energy.mjs for its shape and meaning). `s` is\n// a system already passed through systemForSun. Null when there is no such landable world — and a caller treats null\n// as OFF A SURFACE, which is the honest reading of \"not standing on anything this system has\".\nexport function sunDescriptorFor(s, addr, face, eng) {\n  if (!s || typeof addr !== 'string' || !Number.isInteger(face) || face < 0 || face > 5) return null;\n  const body = bodyAt(s, addr);\n  if (!body || eng.getCategory(body) !== 'Rocky') return null;\n  const at = locate(s, body, eng);\n  if (!at) return null;\n  const n = cornerUp(FACES[face]);\n  let c0, c1;\n  if (body.tidalLock && at.orb) { c0 = body.cornerAz - at.orb[0] - Math.PI; c1 = at.orb[1]; }   // rotation.y = cornerAz − (orbAngle + π)\n  else { c0 = body.baseSpin || 0; c1 = body.rotOmega || 0; }\n  const place = placeOf(s, body), stars = [];\n  for (const st of lightingStarsOf(s)) {\n    const d = distanceToStar(s, st, place);\n    const f = d > 0 ? (st.luminosity ?? 1) * (HZ_BASE / d) ** 2 : 0;\n    const where = locate(s, st, eng);\n    stars.push({ f, p: where ? where.pos : [] });\n  }\n  const out = { v: 1, o: SKY_MODEL, key: `${addr}|${face}`, nx: n[0], ny: n[1], nz: n[2], c0, c1, b: at.pos, s: stars };\n  if (at.tip) out.bi = at.tip;   // a moon in its planet's equator, or one of a pair in theirs (locate)\n  const t = leanTermsFor(body, addr, at.yr);\n  if (t) out.t = t;\n  const ec = eclipseTermsFor(s, body, eng);\n  if (ec) out.ec = ec;\n  return out;\n}\n// WHAT CAN COVER A WORLD'S SUNS (the owner's Sky and Eclipses picks, Oct 24, e4; energy.mjs `ec`): the bodies whose cubes can\n// pass between it and a sun — its planet (for a moon), the other moons of that planet, its own moons, the other of its pair\n// (and that one's partner, for a moon of a pair) — each placed (locate), spun (setSpin: a lock follows its orbit) and leant\n// (leanTermsFor) as the renderer has it, nearest-and-largest first, at most ECL_DESC_MAX; and each lighting star's cube edge\n// and spin. Needs the engine's getRadius (the cube edges); without it, or with nothing round the world, null: no eclipses.\nfunction eclipseTermsFor(s, body, eng) {\n  if (typeof eng.getRadius !== 'function') return null;\n  const fam = [], seen = new Set([body]);\n  const add = (o, dist) => { if (!o || seen.has(o) || !o._addr || eng.getCategory(o) === 'Star') return; seen.add(o); fam.push({ o, dist }); };\n  const hosts = s.binaryType === 'far' && s.companion ? [s, s.companion] : [s];\n  for (const host of hosts) for (const p of host.children || []) {\n    const pair = p.companion ? [p, p.companion] : [p];\n    const sep = p.layout && p.layout.sep > 0 ? p.layout.sep : 0;\n    if (pair.includes(body)) {\n      for (const q of pair) if (q !== body) add(q, sep || 1);\n      for (const m of p.children || []) add(m, Math.max(1e-9, m.logicalDist || 1));\n    }\n    for (const m of p.children || []) if (m === body) {\n      for (const q of pair) add(q, Math.max(1e-9, body.logicalDist || 1));\n      for (const m2 of p.children) if (m2 !== body) add(m2, Math.max(1e-9, Math.abs((m2.logicalDist || 0) - (body.logicalDist || 0))));\n    }\n  }\n  if (!fam.length) return null;\n  fam.sort((a, b) => eng.getRadius(b.o) / b.dist - eng.getRadius(a.o) / a.dist);\n  const o = [];\n  for (const { o: q } of fam.slice(0, ECL_DESC_MAX)) {\n    const at = locate(s, q, eng);\n    if (!at) continue;\n    const term = { p: at.pos, e: eng.getRadius(q) };\n    if (at.tip) term.bi = at.tip;\n    if (q.tidalLock && at.orb) { term.c0 = q.cornerAz - at.orb[0] - Math.PI; term.c1 = at.orb[1]; }   // setSpin: cornerAz − (orbAngle + π)\n    else { term.c0 = q.baseSpin || 0; term.c1 = q.rotOmega || 0; }\n    const t = leanTermsFor(q, q._addr, at.yr);\n    if (t) term.t = t;\n    o.push(term);\n  }\n  if (!o.length) return null;\n  return { h: eng.getRadius(body) / 2, s: lightingStarsOf(s).map((st) => ({ e: eng.getRadius(st), c0: st.baseSpin || 0, c1: st.rotOmega || 0 })), o };\n}\n// A WORLD'S YEAR AND WHETHER IT IS LOCKED TO ITS STAR (what a claim records as its season, seasons.mjs seasonRecordOf:\n// the year its season names and daylight run over, read by the weekly digest), on a system already passed through\n// systemForSun: { yearDays, locked } — its\n// planet's year (a moon's is its planet's) and whether it keeps one face to its star, as system-view.js sunFixedFor\n// reads it (a locked moon faces its planet, and turns under its star). Null for no such rocky world, or no year (a\n// rogue's world).\nexport function yearOf(s, addr, eng) {\n  const body = s && typeof addr === 'string' ? bodyAt(s, addr) : null;\n  if (!body || eng.getCategory(body) !== 'Rocky') return null;\n  const at = locate(s, body, eng);\n  if (!at || !at.yr || !(at.yr[2] > 0)) return null;\n  return { yearDays: at.yr[2], locked: !!(body.tidalLock && !body.isMoon) };\n}\n// THE AXIS'S LEAN AS THE DESCRIPTOR CARRIES IT (energy.mjs `t`), from seasons.mjs axisLean, which system-view.js setSpin\n// asks every frame with the year's phase (yearPhaseAt on the sim clock) and the planet's orbital angle (yr: startAngle −\n// omega·T). Here both are written as lines in T: the phase is 2π·yearPhaseAt at the epoch plus 2π·T / (SIM_RATE · year),\n// which is the orbit's own rate (a year IS the orbit), and the angle is startAngle − omega·T.\n//   turning  lean = the tilt, a constant; bearing = 2πφ + λ + π/2, which is constant too (φ and λ turn together, one\n//            each way), so it is written once, at the epoch: [tilt, π/2, 0, bearing, 0]\n//   locked   lean = the rock · sin(2πφ), toward the star (λ + π): [rock, 2πφ₀, 2π / (SIM_RATE · year), startAngle + π, −omega]\n// null for a world with no seasons to lean by (under 1° of tilt, no year): it keeps the sky it always had.\nfunction leanTermsFor(body, addr, yr) {\n  if (!yr || !(yr[2] > 0)) return null;\n  const tilt = tiltOf(addr), locked = !!(body.tidalLock && !body.isMoon);\n  const phase0 = yearPhaseAt(addr, yr[2], SIM_EPOCH_MS);\n  const lean = axisLean(tilt, locked, phase0, yr[0]);\n  if (!lean) return null;\n  if (!locked) return [lean.lean, Math.PI / 2, 0, lean.dir, 0];\n  return [rockDeg(tilt) * Math.PI / 180, 2 * Math.PI * phase0, 2 * Math.PI / (SIM_RATE * yr[2] * DAY_MS), yr[0] + Math.PI, -(yr[1] || 0)];\n}\n// WHICH SKY A DESCRIPTOR WAS BUILT FOR. A stored descriptor is the sky frozen into numbers: every orbit's and spin's rate.\n// When the sky itself changes (World Seasons, Oct 10: the orbits slowed to real years, and each turning world spun by its\n// seeded day), a descriptor stored before it still prices sunlight by the old sky, faithfully on every end (they all read\n// the stored numbers), but against a sun the player no longer sees, and nothing would ever replace it: the client asks\n// for a stance only when the stored key stops matching where it stands. So a descriptor carries the sky it was built\n// for (`o`), and one from any other sky has a key no stance can match: the client asks again on its next tick, and\n// chargeStance, finding the keys different, integrates the old sky up to now and anchors the new one. The shape the\n// spenders evaluate (`v`) has not changed, so the zone server and its v === 1 check need nothing.\n// …AND AGAIN WHEN THE AXIS LEANT (World Seasons phase 2, Oct 11): sky 3 is the sun's path with the season (`t`, `ny`)\n// and starlight priced by the sun's height (energy.mjs starlightOn). A sky 2 descriptor has neither field and is read as\n// the sky it was, by the new rule, up to the moment its stance is re-anchored.\n// …AND AGAIN WHEN THE MOONS LEFT THE PLANE (the owner's Worlds and Axes decisions, Oct 11): sky 4 puts every moon in its\n// planet's equator and each of a pair in theirs (`bi`, locate), so a moon round a leaning planet stands above or below\n// the system's plane and its sun comes from a little higher or lower. A sky 3 descriptor has no `bi` and is priced, to\n// the bit, as it always was (energy.mjs adds nothing for an absent term) until its stance is re-anchored.\n// …AND AGAIN WHEN THE MOONS' SHADOWS FELL (the owner's Sky and Eclipses picks, Oct 24, e4): sky 5 carries `ec`, the cubes that\n// can cover the world's suns (eclipseTermsFor), and a sun is priced by the share of it they leave. A sky 4 descriptor has no\n// `ec` and is priced, to the bit, as it always was until its stance is re-anchored.\nexport const SKY_MODEL = 5;\n// The key a stance is known by, on both ends: '<addr>|<face>' on a surface, 'off' anywhere else.\nexport function stanceKey(addr, face) { return (typeof addr === 'string' && Number.isInteger(face)) ? `${addr}|${face}` : 'off'; }\n\n// PLACED SOLAR PANELS ON A STANCE (the owner's play review, Oct 23, f7; energy.mjs panelSunAt says what they charge and\n// when). WHICH FACE a placed cell is on: the cell CENTRE's largest coordinate, by sign (turf.mjs upOf's rule, the face whose\n// outward up that cell's top looks along), in FACES' order. And the descriptor's `pv` from a claim's panel count\n// ({ '<face>': count }, claims/{addr}.panels): each face's corner-up normal and how many stand on it, in face order, or\n// null for none. A pure function of the count, so every server that builds a stance builds the same numbers.\nexport function cellFaceOf(x, y, z) {\n  const cx = x + 0.5, cy = y + 0.5, cz = z + 0.5, ax = Math.abs(cx), ay = Math.abs(cy), az = Math.abs(cz);\n  const a = (ax >= ay && ax >= az) ? 0 : (ay >= az ? 1 : 2);\n  return a * 2 + (((a === 0 ? cx : a === 1 ? cy : cz) >= 0) ? 0 : 1);\n}\nexport function panelTerms(panels) {\n  if (!panels || typeof panels !== 'object') return null;\n  const out = [];\n  for (let f = 0; f < 6; f++) {\n    const n = Math.floor(Number(panels[f]) || 0);\n    if (n > 0) { const v = cornerUp(FACES[f]); out.push(v[0], v[1], v[2], n); }\n  }\n  return out.length ? out : null;\n}\n// THE STANCE'S DESCRIPTOR WITH ITS PANELS: a copy of `desc` carrying `pv` (or without one when there are none). The memoised\n// descriptor itself is never changed.\nexport function withPanels(desc, panels) {\n  if (!desc) return desc;\n  const pv = panelTerms(panels), out = { ...desc };\n  if (pv) out.pv = pv; else delete out.pv;\n  return out;\n}\n// The panels part of a descriptor, for comparing two stances that share a key (a panel placed changes it, the key does not).\nexport const panelKey = (desc) => (desc && Array.isArray(desc.pv) ? desc.pv.join(',') : '');\nexport function descKey(desc) { return desc && typeof desc.key === 'string' ? (desc.o === SKY_MODEL ? desc.key : `stale|${desc.key}`) : 'off'; }\n"],"mappings":"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","names":["o"],"file":"sunlight.mjs"}