Expand game engine, replay, tests, and documentation

This commit is contained in:
Jesse
2026-07-31 08:10:54 -04:00
parent e7bc07df85
commit 401b879140
30 changed files with 2253 additions and 552 deletions
+12 -8
View File
@@ -239,8 +239,10 @@ describe('Mainline Phase (§8)', () => {
s.clock.phase = 'mainline';
s.movedThisPhase = new Set();
advance(s);
// Q1/Q2 — crossing time is counted in Stages by card speed and Fast/Slow class, so the train
// stays on the card until its transit expires rather than stepping through printed cells.
const pos2 = s.trays.get(id)!.position;
assert.ok(pos2.at === 'mainline' && pos2.region === 1, 'one region per Stage');
assert.equal(pos2.at, 'mainline', 'still crossing');
});
it('orders movement by train number, Timetabled before Extra on a tie (Gap 5)', () => {
@@ -288,11 +290,11 @@ describe('collisions are automatic (Gap 2)', () => {
engineFront: true,
consist: [{ type: 'coach', loaded: true }],
direction: 'east',
position: { at: 'mainline', index: 1, region: 1 },
position: { at: 'mainline', index: 1 },
movesUsed: 0,
});
const ml = s.division.nodes[1];
if (ml?.kind === 'mainline') ml.regions[1]!.occupant = id;
if (ml?.kind === 'mainline') ml.transits.push({ tray: id, stagesRemaining: 1, direction: 'east' });
s.clock.phase = 'mainline';
s.movedThisPhase = new Set();
@@ -308,6 +310,8 @@ describe('collisions are automatic (Gap 2)', () => {
s.officeAreas.get(0)!.adOccupancy = ['blocker'];
const classBefore = s.yards.classificationYard.length;
const mlx = s.division.nodes[1];
if (mlx?.kind === 'mainline') mlx.transits.push({ tray: 'x', stagesRemaining: 1, direction: 'east' });
s.trays.set('x', {
id: 'x',
trainNumber: 8,
@@ -318,7 +322,7 @@ describe('collisions are automatic (Gap 2)', () => {
{ type: 'caboose', loaded: true },
],
direction: 'east',
position: { at: 'mainline', index: 1, region: 1 },
position: { at: 'mainline', index: 1 },
movesUsed: 0,
});
s.clock.phase = 'mainline';
@@ -346,11 +350,11 @@ describe('the Superintendent clearance interrupt (§8.1)', () => {
engineFront: true,
consist: [],
direction: 'east',
position: { at: 'mainline', index: 1, region: 1 },
position: { at: 'mainline', index: 1 },
movesUsed: 0,
});
const ml = s.division.nodes[1];
if (ml?.kind === 'mainline') ml.regions[1]!.occupant = 'ahead';
if (ml?.kind === 'mainline') ml.transits.push({ tray: 'ahead', stagesRemaining: 2, direction: 'east' });
// A second train at the Western Division Point wanting to follow it.
s.trays.set('behind', {
@@ -383,11 +387,11 @@ describe('the Superintendent clearance interrupt (§8.1)', () => {
engineFront: true,
consist: [],
direction: 'west',
position: { at: 'mainline', index: 1, region: 0 },
position: { at: 'mainline', index: 1 },
movesUsed: 0,
});
const ml = s.division.nodes[1];
if (ml?.kind === 'mainline') ml.regions[0]!.occupant = 'oncoming';
if (ml?.kind === 'mainline') ml.transits.push({ tray: 'oncoming', stagesRemaining: 2, direction: 'west' });
s.trays.set('waiting', {
id: 'waiting',