v0.3.0 — playtest fixes, two new rules, and §7 enforced

This commit is contained in:
Jesse
2026-08-12 21:08:28 -04:00
parent 6ead39c530
commit 1bf1e95058
38 changed files with 8514 additions and 5989 deletions
+18 -6
View File
@@ -204,7 +204,7 @@ export function compress(frames: Frame[]): Packed {
const fi = c.facility ? f.facilities.indexOf(c.facility) : -1;
// `train` rides whole rather than being interned: it changes almost every frame, so a table
// of them would be as long as the frames are and buy nothing.
return [ci, wi, c.enhancements, c.tray, c.cars, fi, c.train, c.ad];
return [ci, wi, c.enhancements, c.tray, c.cars, fi, c.train, c.ad, c.enhancementsWhat];
});
return { ...f, cells } as unknown as Frame;
});
@@ -238,7 +238,7 @@ export function rehydrateCells(
facs: unknown[],
): unknown[] {
return packed.map((row) => {
const p = row as [number, number, string[], string | null, string[], number, unknown, unknown];
const p = row as [number, number, string[], string | null, string[], number, unknown, unknown, string[]];
const c = cards[p[0]] as [number, number, string, string, boolean, string[]];
return {
row: c[0], col: c[1], kind: c[2], label: c[3], running: c[4], links: c[5],
@@ -246,6 +246,9 @@ export function rehydrateCells(
facility: p[5] < 0 ? null : facs[p[5]],
train: p[6] ?? null,
ad: p[7] ?? null,
// Carried rather than recomputed: this function is emitted into the page by toString() and so
// cannot reach the card catalogue that produced the text.
enhancementsWhat: p[8] ?? [],
};
});
}
@@ -293,7 +296,7 @@ margin-top:5px;font-size:11px;line-height:1.35}
.fac{border:1px solid var(--line);border-radius:5px;padding:8px;margin-bottom:8px;background:#20252c}
.boxes{display:flex;gap:6px;flex-wrap:wrap;margin-top:6px;align-items:center}
.box{border-radius:3px;padding:3px 7px;font-size:11px;border:1px solid var(--line)}
.box.g{background:var(--green)}.box.r{background:var(--red)}.box.m{background:var(--maw)}
.box.g{background:var(--green)}.box.r{background:var(--red)}.box.m{background:var(--maw)}.box.s{background:#3a4450}
.box.empty{background:transparent;color:var(--dim)}
.log{max-height:230px;overflow:auto}
/* Auto-hide, the same as the playable page. Folded leaves a summary rather than nothing, because a
@@ -519,10 +522,19 @@ function render() {
'<div class="fac"><b>' + esc(x.name) + '</b> <span class="dim">' + esc(x.commodity) + ' · ' + esc(x.flow) +
' · laborers ' + esc(x.laborers) + ' · porters ' + esc(x.porters) + '</span>' +
'<div class="boxes"><span class="dim">green</span>' + boxes(x.green, x.greenCap, 'g') + '</div>' +
'<div class="boxes"><span class="dim">MEN|AT|WORK</span>' +
x.maw.map((m) => '<span class="box ' + (m ? 'm' : 'empty') + '">' + (m ? esc(m) : '·') + '</span>').join('') + '</div>' +
// No sign and no siding on a Passenger Facility: maw is empty for one, but the LABEL was
// printed before the loop, so a Depot showed the caption over nothing. The mini card above
// gates on trackCap and was already right; this copy was not.
// (No backticks in here — this whole block is inside a template literal.)
(x.maw.length > 0
? '<div class="boxes"><span class="dim">MEN|AT|WORK</span>' +
x.maw.map((m) => '<span class="box ' + (m ? 'm' : 'empty') + '">' + (m ? esc(m) : '·') + '</span>').join('') + '</div>'
: '') +
'<div class="boxes"><span class="dim">red</span>' + boxes(x.red, x.redCap, 'r') + '</div>' +
'<div class="boxes"><span class="dim">siding</span>' + boxes(x.track, x.trackCap, 'g') + '</div>' +
// 's', not 'g': the siding is a place, not a direction, and green is reserved for outbound.
(x.trackCap > 0 || x.track.length > 0
? '<div class="boxes"><span class="dim">siding</span>' + boxes(x.track, x.trackCap, 's') + '</div>'
: '') +
'<div class="fstat ' + (x.jammed ? 'bad' : (x.canFinish ? 'good' : 'idle')) + '">' +
(x.jammed
? 'JAMMED — a load is on WORK with no car spotted to receive it; the industry track is locked'