Show the whole Division mainline. district now has option for auto hiding on phases where not needed. scaffold for multi-player geometry showing division. regions on mainline cards implemented. bug fix on laying rail cards. optimized replay (carried links forward). Add sounds, first pass
This commit is contained in:
+53
-3
@@ -14,7 +14,7 @@ import { createGame } from '../src/engine/setup.ts';
|
||||
import type { GameConfig } from '../src/engine/state.ts';
|
||||
import { developerBot, playGame } from '../src/sim/bot.ts';
|
||||
import { impediments, isVisible, narrate, phaseLabel } from '../src/sim/narrate.ts';
|
||||
import { record, renderHtml } from '../src/sim/replay.ts';
|
||||
import { compress, rehydrateCells, record, renderHtml } from '../src/sim/replay.ts';
|
||||
import { summarize } from '../src/sim/stats.ts';
|
||||
|
||||
const config: GameConfig = {
|
||||
@@ -189,8 +189,16 @@ describe('replay HTML', () => {
|
||||
assert.deepEqual(externals, [], `external references: ${externals.join(', ')}`);
|
||||
});
|
||||
|
||||
it('embeds the frame data', () => {
|
||||
assert.match(html, /const FRAMES = \[/);
|
||||
it('embeds the frame data and the dictionaries it is packed against', () => {
|
||||
// The frames are packed now: a card's identity and its description are written once into
|
||||
// CARDS/WHATS and referenced by integer. A page with FRAMES but no dictionaries would draw an
|
||||
// empty board rather than fail, so all three are checked.
|
||||
assert.match(html, /const PACKED = \{/);
|
||||
assert.match(html, /FRAMES = PACKED\.frames/);
|
||||
assert.match(html, /CARDS = PACKED\.cards/);
|
||||
assert.match(html, /WHATS = PACKED\.whats/);
|
||||
// And the unpacking function must be emitted, not just referenced.
|
||||
assert.match(html, /const rehydrateCells = function/);
|
||||
});
|
||||
|
||||
it('offers the controls that make it usable', () => {
|
||||
@@ -300,3 +308,45 @@ describe('replay HTML', () => {
|
||||
assert.ok(mb < 5, `replay is ${mb.toFixed(1)} MB`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('the replay wire format is lossless (regression)', () => {
|
||||
it('rebuilds every cell exactly, through the same function the page runs', () => {
|
||||
// The frames are packed before they reach the page: a card's identity and its description are
|
||||
// written once and referenced by integer, and a cell points at its facility instead of carrying
|
||||
// a second copy of it. That is 45% of the file — and it is only safe if unpacking is exact.
|
||||
//
|
||||
// `rehydrateCells` is the function the page itself runs, emitted by toString(), so this checks
|
||||
// the real thing rather than a second implementation of it.
|
||||
const rec = record(880009, 'standard', 4000);
|
||||
const packed = compress(rec.frames);
|
||||
|
||||
let checked = 0;
|
||||
let carried: unknown[] = [];
|
||||
let carriedFacs: unknown[] = [];
|
||||
for (let i = 0; i < rec.frames.length; i++) {
|
||||
const wire = packed.frames[i] as Record<string, unknown>;
|
||||
// null means "unchanged since the last frame that carried it", exactly as the page resolves it
|
||||
if (wire['cells'] !== null) carried = wire['cells'] as unknown[];
|
||||
if (wire['facilities'] !== null) carriedFacs = wire['facilities'] as unknown[];
|
||||
|
||||
const back = rehydrateCells(carried, packed.cards, packed.whats, carriedFacs);
|
||||
assert.deepEqual(back, rec.frames[i]!.cells, `frame ${i} did not survive the round trip`);
|
||||
checked++;
|
||||
}
|
||||
assert.ok(checked > 100, `only ${checked} frames checked`);
|
||||
});
|
||||
|
||||
it('writes each distinct card and description once, not once per frame', () => {
|
||||
const rec = record(880009, 'standard', 4000);
|
||||
const packed = compress(rec.frames);
|
||||
const cellsSeen = rec.frames.reduce((n, f) => n + f.cells.length, 0);
|
||||
assert.ok(
|
||||
packed.cards.length < cellsSeen / 20,
|
||||
`${packed.cards.length} card entries for ${cellsSeen} cell-frames — identity is not interned`,
|
||||
);
|
||||
assert.ok(
|
||||
packed.whats.length < cellsSeen / 20,
|
||||
`${packed.whats.length} descriptions for ${cellsSeen} cell-frames — prose is not interned`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user