Add The Frontier, a second setting, and a picker to choose between them
Cold Fork is a freight yard: 29 events across two stages, a four-day cycle, and its own relationship and skill vocabulary. src/engine/ was not touched. Adding it needed three changes outside the engine: one save slot per pack, app.js holding the current pack, and turn.js no longer naming the mailroom (DECISIONS #34). build.js now handles imports wrapped across lines. A conformance suite runs over every registered pack. DECISIONS #35 records three calls on open questions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RxdJFbLq1rBKsUeticGV1g
This commit is contained in:
co-authored by
Claude Opus 5
parent
4957c24e31
commit
7f20be83e8
@@ -0,0 +1,64 @@
|
||||
// Choosing a setting.
|
||||
//
|
||||
// A setting is a content pack, and this screen is the whole of the interface's
|
||||
// knowledge about there being more than one: it reads `name`, `blurb` and the
|
||||
// stage titles off each pack and knows nothing else about any of them. Adding
|
||||
// a third pack changes this file not at all.
|
||||
//
|
||||
// Each pack keeps its own save slot, so switching is not destructive and the
|
||||
// screen says so — a run in progress is reported with the turn it is on.
|
||||
|
||||
import { h } from '../dom.js';
|
||||
|
||||
export function packsScreen(packs, { currentPackId, runs, canGoBack }, actions) {
|
||||
return h('div', { class: 'screen screen--packs' },
|
||||
h('header', { class: 'packs__head' },
|
||||
h('p', { class: 'packs__eyebrow' }, 'The Ladder'),
|
||||
h('h1', { class: 'packs__title' }, 'Choose a setting'),
|
||||
h('p', { class: 'packs__subtitle' },
|
||||
'The same game underneath. Each setting keeps its own run, so you can ' +
|
||||
'move between them without losing either.'),
|
||||
),
|
||||
|
||||
h('ul', { class: 'packs__list' },
|
||||
packs.map((pack, index) => {
|
||||
const run = runs[pack.id];
|
||||
const current = pack.id === currentPackId;
|
||||
return h('li', { class: `packs__item${current ? ' packs__item--current' : ''}` },
|
||||
h('h2', { class: 'packs__name' }, pack.name),
|
||||
pack.blurb && h('p', { class: 'packs__blurb' }, pack.blurb),
|
||||
h('p', { class: 'packs__state' }, runLine(pack, run, current)),
|
||||
h('button', {
|
||||
class: current ? 'button' : 'button button--quiet',
|
||||
// The setting the player is already in, or failing that the first
|
||||
// one, is what Enter takes — the same keyboard contract as
|
||||
// everywhere else.
|
||||
dataset: (current || (!currentPackId && index === 0)) ? { autofocus: 'true' } : undefined,
|
||||
onClick: () => actions.onChoosePack(pack.id),
|
||||
}, buttonLabel(run, current)),
|
||||
);
|
||||
}),
|
||||
),
|
||||
|
||||
canGoBack && h('footer', { class: 'controls' },
|
||||
h('button', { class: 'button button--quiet', onClick: actions.onResume }, 'Back'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function runLine(pack, run, current) {
|
||||
const unit = pack.turnUnit ?? 'turn';
|
||||
if (!run) return 'Not started.';
|
||||
const title = pack.stages?.[run.stage]?.title ?? run.stage;
|
||||
const where = `${capitalize(unit)} ${run.turn}, ${title}`;
|
||||
return current ? `${where} — where you are now.` : `${where}, saved.`;
|
||||
}
|
||||
|
||||
function buttonLabel(run, current) {
|
||||
if (current) return 'Keep playing';
|
||||
return run ? 'Go back to this run' : 'Start here';
|
||||
}
|
||||
|
||||
const capitalize = (word) => word.charAt(0).toUpperCase() + word.slice(1);
|
||||
|
||||
export default packsScreen;
|
||||
Reference in New Issue
Block a user