Track becomes a deck card, Departments become decks, and trains must be made up to leave, industry restrictions enforced, update display and add a new game button
This commit is contained in:
+64
-16
@@ -254,25 +254,50 @@ function render(): void {
|
||||
$('hand').innerHTML = f.hand.length
|
||||
? f.hand.map((h, i) => cardRow(h, f.handWhat[i] ?? '', canPlay[i] ?? null)).join('')
|
||||
: '<span class="dim">empty</span>';
|
||||
// Reference, not choices: the Department cards are three FACE-UP CARDS, not three decks — there
|
||||
// is nothing underneath them. Drawn like the hand so they read as cards, dashed and unlit so they
|
||||
// do not read as clickable.
|
||||
$('depts').innerHTML = f.departments.length
|
||||
? f.departments.map((d, i) => cardRow(d, f.departmentsWhat[i] ?? '', null)).join('')
|
||||
: '<span class="dim">none</span>';
|
||||
/**
|
||||
* THE THREE DEPARTMENT PILES, and how deep each one is.
|
||||
*
|
||||
* They are decks, not single face-up cards: a discard goes on TOP of the one its owner chooses, so
|
||||
* a pile is a card being offered with a history of cards buried under it. Only the top may be
|
||||
* taken, which makes the depth real information — a deep pile is where cards have been put beyond
|
||||
* reach. Drawn like the hand so they read as cards, dashed and unlit because taking one is a draw
|
||||
* action rather than a click on the card itself.
|
||||
*/
|
||||
const pileCard = (label: string, top: string, depth: number, why: string, tipExtra = ''): string => {
|
||||
const tip = [why, tipExtra].filter(Boolean).join(' · ');
|
||||
return (
|
||||
`<div class="handcard"${tip ? ` data-tip="${esc(tip)}"` : ''} tabindex="0">` +
|
||||
`<div class="pilehd"><span>${esc(label)}</span><span class="depth">${depth}</span></div>` +
|
||||
`<b>${esc(top)}</b></div>`
|
||||
);
|
||||
};
|
||||
|
||||
$('depts').innerHTML =
|
||||
f.departments
|
||||
.map((d, i) => {
|
||||
const depth = f.departmentDepth[i] ?? 0;
|
||||
const under = depth - 1;
|
||||
return pileCard(
|
||||
`Dept ${i + 1}`,
|
||||
d,
|
||||
depth,
|
||||
f.departmentsWhat[i] ?? '',
|
||||
under > 0 ? `${under} card${under === 1 ? '' : 's'} buried beneath it and out of reach` : '',
|
||||
);
|
||||
})
|
||||
.join('') +
|
||||
// The Salvage Yard beside them, because §6.2 sweeps it back into the deck and it is the only
|
||||
// visible sign that the reshuffle is coming.
|
||||
pileCard(
|
||||
'Salvage',
|
||||
f.salvage.top,
|
||||
f.salvage.depth,
|
||||
'',
|
||||
'Played cards that did not stay on the board. Swept back into the Home Office deck, with the Departments, when the deck runs out.',
|
||||
);
|
||||
|
||||
renderYards(f);
|
||||
|
||||
const total = f.trackSupply.reduce((n, t) => n + t.left, 0);
|
||||
$('supply').innerHTML =
|
||||
`<div class="dim">${total} pieces left · one may be laid per turn, during the DRAW option</div>` +
|
||||
f.trackSupply
|
||||
.map(
|
||||
(t) =>
|
||||
`<span class="card ${t.left === 0 ? 'gone' : ''}">${esc(t.piece)} <b>${t.left}</b></span>`,
|
||||
)
|
||||
.join(' ');
|
||||
|
||||
$('blocked').innerHTML =
|
||||
f.blocked.length === 0
|
||||
? '<li class="dim">nothing blocked</li>'
|
||||
@@ -541,6 +566,29 @@ installTooltips();
|
||||
const saveBtn = document.getElementById('savefile');
|
||||
if (saveBtn) saveBtn.onclick = downloadSave;
|
||||
|
||||
/**
|
||||
* Forget the saved game and deal a fresh one.
|
||||
*
|
||||
* The only way out used to be finishing the game — `start()` restores from localStorage on every
|
||||
* load, so a game you no longer wanted followed you across reloads, and the "new game" button
|
||||
* appeared solely on the game-over screen. Confirmed because the save is the game: there is no undo,
|
||||
* and the replay download is right beside it.
|
||||
*
|
||||
* `location.search = ''` rather than a direct re-render, so a `?seed=` in the URL goes too — leaving
|
||||
* it would deal the same game again and look like the button had done nothing.
|
||||
*/
|
||||
const newBtn = document.getElementById('newgame');
|
||||
if (newBtn) {
|
||||
newBtn.onclick = () => {
|
||||
const day = game.state.clock.day;
|
||||
const started = game.state.status === 'active' && (day > 1 || game.state.clock.stage > 1);
|
||||
if (started && !confirm(`Forget this game (seed ${game.seed}, Day ${day}) and deal a new one?`)) return;
|
||||
clearSave();
|
||||
if (location.search === '') location.reload();
|
||||
else location.search = '';
|
||||
};
|
||||
}
|
||||
|
||||
const soundBtn = document.getElementById('sound');
|
||||
if (soundBtn) {
|
||||
const paint = (): void => {
|
||||
|
||||
Reference in New Issue
Block a user