Force starting system to be a Main Sequence star
- Add `startingSystem.type` config (default "main") that overrides the zone-mixed roll at roster build in Galaxy.js - Update SystemGenerator doc comment to note the home star class now rolls from the main-sequence table (G/K/M) - Add tests asserting the starting system is always type "main" across all policies - Update data/galaxy.json comment and PROJECT_NOTES.md to document the new rule
This commit is contained in:
parent
6dc0e99dee
commit
f470250721
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"_comment": "Galaxy shape + scale (js/galaxy/Galaxy.js). systemCount = total star systems (the starting system is one of them). layout.field = the galaxy is a seeded WIDE (2:1) field of stars (center at the world origin, ±width/2 in x, ±height/2 in y — the 2:1 shape matches the map plate, js/ui/MapWindow.js at the 1280×720 design size, so the fully-zoomed-out galaxy fills the plate): Bridson Poisson-disk sampling keeps every pair of systems at least minSpacing·√(width·height/systemCount) apart — an even, organic field (no clumps, no voids, not a grid). startingSystem: policy 'corner' puts the player's home in the star NEAREST the configured corner (corner: NE/NW/SE/SW, screen orientation — SE = lower right); 'center' (nearest the origin) and 'random' still work. distribution.zones slices the HOME→FAR diagonal into named zones (d: 0 at the home corner, 1 at the opposite corner); distribution.zoneMix multiplies each type's distribution.weight PER ZONE (the old per-type radiusBand is gone — type flavor is regional now). settlements.gradient = free-space settlement density by diagonal position (d 0 = home corner, 1 = far corner): chance = 1 − d×falloff, floored at floor (js/galaxy/SystemGenerator.js → settlementDensity).",
|
||||
"_comment": "Galaxy shape + scale (js/galaxy/Galaxy.js). systemCount = total star systems (the starting system is one of them). layout.field = the galaxy is a seeded WIDE (2:1) field of stars (center at the world origin, ±width/2 in x, ±height/2 in y — the 2:1 shape matches the map plate, js/ui/MapWindow.js at the 1280×720 design size, so the fully-zoomed-out galaxy fills the plate): Bridson Poisson-disk sampling keeps every pair of systems at least minSpacing·√(width·height/systemCount) apart — an even, organic field (no clumps, no voids, not a grid). startingSystem: policy 'corner' puts the player's home in the star NEAREST the configured corner (corner: NE/NW/SE/SW, screen orientation — SE = lower right); 'center' (nearest the origin) and 'random' still work. startingSystem.type FORCES the starting system's archetype (default 'main' — a Main Sequence star, data/systems.json → types.main: the player's home is an ordinary star; the record's zone-mixed roll is overridden at roster build, js/galaxy/Galaxy.js). distribution.zones slices the HOME→FAR diagonal into named zones (d: 0 at the home corner, 1 at the opposite corner); distribution.zoneMix multiplies each type's distribution.weight PER ZONE (the old per-type radiusBand is gone — type flavor is regional now). settlements.gradient = free-space settlement density by diagonal position (d 0 = home corner, 1 = far corner): chance = 1 − d×falloff, floored at floor (js/galaxy/SystemGenerator.js → settlementDensity).",
|
||||
"systemCount": 90,
|
||||
"layout": {
|
||||
"field": {
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
"far": { "main": 0.85, "redDwarf": 0.55, "binary": 1.1, "habitable": 0.25, "nebula": 1.8, "void": 2.6 }
|
||||
}
|
||||
},
|
||||
"startingSystem": { "policy": "corner", "corner": "SE" },
|
||||
"startingSystem": { "policy": "corner", "corner": "SE", "type": "main" },
|
||||
"settlements": {
|
||||
"gradient": { "falloff": 0.7, "floor": 0.22 }
|
||||
},
|
||||
|
|
|
|||
|
|
@ -196,6 +196,14 @@ let big;
|
|||
'corner policy: the home system sits in the NEAR zone (d ≈ 0 at the home corner)',
|
||||
big.currentSystem().zone === zoneCfg[0]?.name,
|
||||
);
|
||||
// The starting system is ALWAYS a Main Sequence system (data/galaxy.json
|
||||
// → startingSystem.type, default 'main' — the player's home is an
|
||||
// ordinary star): whatever the zone mix rolled, the record is overridden
|
||||
// to 'main' at roster build.
|
||||
check(
|
||||
'starting system is always a Main Sequence system (type "main")',
|
||||
big.currentSystem().type === 'main' && config.get('systems.types.main.label', '') === 'Main Sequence',
|
||||
);
|
||||
|
||||
// Lazy contents: the global OBJECT-COMPOSITION rule across the WHOLE
|
||||
// galaxy (data/systems.json → objectCount: 0/2/3/4/5 objects, ≈ 10%
|
||||
|
|
@ -295,6 +303,13 @@ let big;
|
|||
.slice()
|
||||
.sort((a, b) => (a.x + halfNWx) ** 2 + (a.y + halfNWy) ** 2 - ((b.x + halfNWx) ** 2 + (b.y + halfNWy) ** 2))[0].id;
|
||||
check('corner policy honors the configured corner (NW)', nw.currentSystemId === trueNW);
|
||||
|
||||
// The Main Sequence home rule holds for EVERY starting policy (the
|
||||
// default 'main' applies — none of these override startingSystem.type).
|
||||
check(
|
||||
'every starting policy still yields a Main Sequence home',
|
||||
[randomPolicy, center, nw].every((gg) => gg.currentSystem().type === 'main'),
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -152,7 +152,10 @@ menu (displayed, editable, rerollable; same seed ⇒ same galaxy).
|
|||
|
||||
The player's **current system** starts at `galaxy.currentSystem()`
|
||||
(`startingSystem.policy`: `corner` (default — the home corner, SE),
|
||||
`center`, or `random`). Jumping between systems
|
||||
`center`, or `random`). Its **type is fixed**: the starting system is
|
||||
always a Main Sequence system (`startingSystem.type`, default `'main'`
|
||||
— data/systems.json → types.main), so the player's home is an ordinary
|
||||
star. Jumping between systems
|
||||
now has its NETWORK (see "Jump gates" below — `data/gates.json` +
|
||||
`js/galaxy/JumpNetwork.js`, built on `galaxy.neighborsOf(id)` and the
|
||||
spatial hash); the in-flight jump drive is the next mechanic on top.
|
||||
|
|
|
|||
|
|
@ -39,7 +39,10 @@ const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|||
* - the player's HOME system sits in the star nearest the configured
|
||||
* corner (startingSystem: policy "corner", corner NE/NW/SE/SW,
|
||||
* screen orientation — SE = lower right); "center" / "random" still
|
||||
* work; the HOME→FAR diagonal is the galaxy's progression axis:
|
||||
* work; its TYPE is always "main" (Main Sequence —
|
||||
* startingSystem.type, the player's home is an ordinary star; the
|
||||
* zone-mixed roll is overridden at roster build); the HOME→FAR
|
||||
* diagonal is the galaxy's progression axis:
|
||||
* each record carries `d` (0 at the home corner, 1 at the opposite
|
||||
* corner) and its `zone` (near/middle/far, distribution.zones);
|
||||
* - types mix PER ZONE (distribution.zoneMix × the type's global
|
||||
|
|
@ -200,6 +203,23 @@ export class Galaxy {
|
|||
// the player from here on (jumps, saves); the home rules must not.
|
||||
this.homeSystemId = this.currentSystemId;
|
||||
|
||||
// The starting system is ALWAYS a MAIN SEQUENCE system (data/galaxy.json
|
||||
// → startingSystem.type, default 'main' — data/systems.json → types.main,
|
||||
// "Main Sequence"): the player's home is an ordinary star. Its type was
|
||||
// rolled from the zone mix above like every other record; override it
|
||||
// here — before the frame passes read it — so the dossier ("Main
|
||||
// Sequence system · star G"), the map plate, and the generated content
|
||||
// all agree.
|
||||
const forcedType = String(start.type ?? 'main');
|
||||
const homeRec = this.byId.get(this.currentSystemId);
|
||||
if (homeRec && this.typeDefs[forcedType]) {
|
||||
if (homeRec.type !== forcedType) homeRec.type = forcedType;
|
||||
} else {
|
||||
console.warn(
|
||||
`[orbit] startingSystem.type "${forcedType}" is not a defined system type — the starting system keeps its rolled type`,
|
||||
);
|
||||
}
|
||||
|
||||
// Spatial hash for fast neighbor queries (jump ranges, proximity rules,
|
||||
// the eventual star map).
|
||||
const area = W * H;
|
||||
|
|
|
|||
|
|
@ -55,7 +55,11 @@ const DEG = Math.PI / 180;
|
|||
* station: five objects (the home world + four) cannot sit 6400..10240 px
|
||||
* apart — the tightest 5-point spacing needs a max/min ratio ≥ φ ≈ 1.618,
|
||||
* which the home band 10240/6400 = 1.6 cannot give — so the home system
|
||||
* stays a ≤ 4-object configuration (see layoutSystem).
|
||||
* stays a ≤ 4-object configuration (see layoutSystem). Its TYPE is also
|
||||
* fixed: always 'main' (Main Sequence — the player's home is an ordinary
|
||||
* star; Galaxy.js forces it at roster build, data/galaxy.json →
|
||||
* startingSystem.type), so its star class rolls from the main-sequence
|
||||
* table (G/K/M).
|
||||
*
|
||||
* LAYOUT (data/planets.json → solarSystem) — the SOLAR SYSTEM BAND: every
|
||||
* PAIR of layout objects (planets and free-space stations — the central
|
||||
|
|
|
|||
Loading…
Reference in New Issue