From a1db1cc672f19ba64a9d44a1f56635b53794a0cd Mon Sep 17 00:00:00 2001 From: Brian Fertig Date: Thu, 3 Sep 2026 22:41:06 -0600 Subject: [PATCH] Give the home world a real name from the bank, and show object names on the compass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two small naming/labeling fixes: 1. The home planet was always the generic "Terra". It now takes the first name off the STARTING system's planet-name deck (SystemGenerator), so it reads as a real place and can never clash with one of that system's planets. Stored as content.homeName (only the starting system has one); the old planets.homeName stays as a fallback. Used for the compass home chip and the tether anchor label. 2. Confirmed/sharpened the compass name tag: each discovered off-screen object's arrow chip already renders TYPE + NAME — now the home world shows its bank name too (e.g. "HOME WORLD · ESHKAELURA"). Co-Authored-By: Claude Opus 4.8 --- README.md | 11 +++++++---- dev/galaxy.test.mjs | 12 ++++++++++++ docs/PROJECT_NOTES.md | 7 +++++-- js/galaxy/SystemGenerator.js | 12 ++++++++++-- js/scenes/GameScene.js | 9 +++++++-- 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1d16ad1..8c8da3a 100644 --- a/README.md +++ b/README.md @@ -52,12 +52,15 @@ python3 -m http.server 8080 - Game screen with a top-down ship (real spritesheet art — frame 0 of `assets/images/ships-player.png`, see `data/ship.json`): **click anywhere to fly there** in the current system's open space (system boundaries/jumps come next). - Discovered worlds get a screen-edge arrow + name tag; **clicking the + Discovered worlds get a screen-edge arrow + a name tag showing the + world's **name** (e.g. `HOME WORLD · ESHKAELURA`); **clicking the name tag autopilots the ship there** (it arrives on the keep-out rim, facing the world) -- **The home planet** — the player's Terran world — in the system you - start in: a 1024 px disc rendered 1:1 from the `assets/images/planets.png` - spritesheet. Which Terran face it shows (frames 0–2) is a +- **The home planet** — the player's world — in the system you start in: + a 1024 px disc rendered 1:1 from the `assets/images/planets.png` + spritesheet, with a **proper name drawn from the planet name bank** (the + first name off the starting system's deck, so it never clashes with one + of the other worlds). Which Terran face it shows (frames 0–2) is a seed-deterministic pick, so the same galaxy always yields the same home world. The ship spawns ~150 px (edge-to-edge) off its rim in a seed-derived direction, may fly in as close as 50 px from the rim, and diff --git a/dev/galaxy.test.mjs b/dev/galaxy.test.mjs index 7f20d66..d679d85 100644 --- a/dev/galaxy.test.mjs +++ b/dev/galaxy.test.mjs @@ -326,6 +326,18 @@ let big; }); check('within a system: planet names & station names are all distinct', noDupOk); + // The starting system's HOME world gets a bank name distinct from its + // planets; only the starting system has one. + const homeRec = big2.currentSystem(); + const homeC = big2.ensureContent(homeRec.id); + check( + 'starting system has a home-world bank name, distinct from its planets', + typeof homeC.homeName === 'string' && homeC.homeName.length > 0 && + !homeC.planets.some((p) => p.name === homeC.homeName), + ); + const nonHomeRec = big2.records.find((r) => r.id !== homeRec.id); + check('other systems have no home world', !('homeName' in big2.ensureContent(nonHomeRec.id))); + // Lazy === eager still holds with the lived-in layer (spot check). const fresh2 = Galaxy.create(SEED); check('settlements: lazy content === content from a fresh galaxy', deepEq(fresh2.ensureContent(big2.records[0].id).settlements, big2.ensureContent(big2.records[0].id).settlements)); diff --git a/docs/PROJECT_NOTES.md b/docs/PROJECT_NOTES.md index ebd22ae..c0c72bd 100644 --- a/docs/PROJECT_NOTES.md +++ b/docs/PROJECT_NOTES.md @@ -160,8 +160,11 @@ unclaimed". Model & seams: more bodies than the bank holds (impossible at these sizes). The decks are dealt from dedicated derived streams (`Rng.derive(seed,'system',id,'names', 'planets'|'stations')`) so they stay order-independent (lazy === eager). - The home world keeps its configured name (`planets.homeName`), and stars / - the galaxy are still synthesised from syllable pools (unbounded). + The **home world** (the player's planet, in the starting system only) takes + the first name off that system's planet deck — so it gets a real bank name + too, never clashing with one of the planets (`content.homeName`; the old + `planets.homeName` is now just a fallback). Stars and the galaxy are still + synthesised from syllable pools (unbounded). ## The current system is a place, not just a dossier (discovery + compass) diff --git a/js/galaxy/SystemGenerator.js b/js/galaxy/SystemGenerator.js index 415b782..9186ec4 100644 --- a/js/galaxy/SystemGenerator.js +++ b/js/galaxy/SystemGenerator.js @@ -68,6 +68,12 @@ export function generateSystemContent(galaxy, record, typeDefs = null) { const planetDeck = NameGenerator.planetDeck( Rng.derive(galaxy.seed, 'system', record.id, 'names', 'planets') ); + // The player's home world sits at the origin of the STARTING system and is + // not one of the generated planets. It takes the first name off that + // system's deck so it can never clash with a planet; the planets then draw + // from the rest of the deck (all distinct within the system). + const isHome = record.id === galaxy?.currentSystemId; + const homeName = isHome ? planetDeck[0] : null; const planets = []; for (let i = 1; i <= count; i++) { const pclass = rng.weighted(classWeights, 'rocky'); @@ -77,7 +83,7 @@ export function generateSystemContent(galaxy, record, typeDefs = null) { moons = pclass === 'gas' || pclass === 'ice' ? rng.int(1, 6) : rng.int(0, 2); } planets.push({ - name: planetDeck[(i - 1) % planetDeck.length], + name: planetDeck[(isHome ? i : i - 1) % planetDeck.length], ordinal: i, class: pclass, moons, @@ -105,7 +111,7 @@ export function generateSystemContent(galaxy, record, typeDefs = null) { }; const hazard = rng.chance(attr.hazard ?? 0.1); - return { + const content = { name: record.name, type: record.type, star, @@ -114,6 +120,8 @@ export function generateSystemContent(galaxy, record, typeDefs = null) { belt, hazard, }; + if (isHome) content.homeName = homeName; // the player's home world (starting system only) + return content; } /** diff --git a/js/scenes/GameScene.js b/js/scenes/GameScene.js index bc1776f..2497afd 100644 --- a/js/scenes/GameScene.js +++ b/js/scenes/GameScene.js @@ -83,6 +83,11 @@ export class GameScene extends Phaser.Scene { this.ensureGalaxy(); this.systemRecord = this.galaxy.currentSystem(); this.systemContent = this.galaxy.ensureContent(this.systemRecord.id); + // The home world's name — dealt from the planet name bank by the + // generator (the starting system is the only one with a home world), so + // it reads as a real place rather than a generic "Terra". Fallback keeps + // the old configured name if the bank is ever unavailable. + this.homeWorldName = this.systemContent.homeName || config.get('planets.homeName', 'Terra'); this.createSystemHud(); // The home planet — the player's Terran world, always present in the @@ -158,7 +163,7 @@ export class GameScene extends Phaser.Scene { config.get('tether.homeId', 'home'), 0, 0, // home world's center (it sits at the system origin) config.get('tether.homeLevel', 1), - config.get('tether.homeLabel', '') || config.get('planets.homeName', 'Terra'), + config.get('tether.homeLabel', '') || this.homeWorldName, ); this.tetherToastAt = null; this.refreshTetherHud(); @@ -468,7 +473,7 @@ export class GameScene extends Phaser.Scene { y: this.planet.y, radius: this.planet.radius, typeLabel: config.get('planets.homeTypeLabel', 'Home World'), - name: config.get('planets.homeName', 'Terra'), + name: this.homeWorldName, }); for (const p of this.systemPlanets) { out.push({