fix tracks to all be EW. no more NS tracks
This commit is contained in:
+49
-31
@@ -282,24 +282,32 @@ describe('Red Flags protect a stopped train', () => {
|
||||
});
|
||||
|
||||
describe('Flying Switch rolls a cut into an industry', () => {
|
||||
/** A crew on a straight with a facility next door, mid-switch. */
|
||||
/** A crew on a siding below the main, with a facility next door along the same track. */
|
||||
function setup(s: GameState) {
|
||||
const area = areaOf(s, 0);
|
||||
// A flying switch rolls the cut ALONG THE TRACK, so the spur and the industry must be joined
|
||||
// north-south. Built east-west, they are two unconnected cards that merely look adjacent.
|
||||
const spur: TrackCard = {
|
||||
geometry: { kind: 'track', geometry: 'straight', axis: 'ns' },
|
||||
// A flying switch rolls the cut ALONG THE TRACK, so the crew and the industry must be joined by
|
||||
// rail. Every run is east-west now, and the siding gets down off the main the only way there is:
|
||||
//
|
||||
// row 0: [office] [turnout, leg south] <- Running Track
|
||||
// row -1: [curve ne] [straight, crew] [industry] <- the siding
|
||||
//
|
||||
const plain = (): TrackCard => ({
|
||||
geometry: { kind: 'track', geometry: 'straight' },
|
||||
baseOperationalRail: true,
|
||||
standing: [],
|
||||
facility: null,
|
||||
modifiers: [],
|
||||
enhancements: [],
|
||||
};
|
||||
area.grid.set(coordKey(at(-1, 0)), spur);
|
||||
});
|
||||
area.grid.set(coordKey(at(0, 1)), {
|
||||
...plain(),
|
||||
geometry: { kind: 'track', geometry: 'turnout', turnout: { stem: 'w', through: 'e', diverge: 's' }, hand: 'left' },
|
||||
baseOperationalRail: false,
|
||||
});
|
||||
area.grid.set(coordKey(at(-1, 1)), { ...plain(), geometry: { kind: 'track', geometry: 'curved', arc: 'ne', hand: 'left' } });
|
||||
area.grid.set(coordKey(at(-1, 2)), plain());
|
||||
const industry: TrackCard = {
|
||||
geometry: { kind: 'track', geometry: 'straight', axis: 'ns' },
|
||||
baseOperationalRail: true,
|
||||
standing: [],
|
||||
...plain(),
|
||||
facility: {
|
||||
kind: 'freight', subtype: 'mineTipple',
|
||||
allows: { outbound: true, inbound: false },
|
||||
@@ -310,19 +318,14 @@ describe('Flying Switch rolls a cut into an industry', () => {
|
||||
laborers: 1, porters: 0,
|
||||
usedThisStage: { laborers: 0, porters: 0 },
|
||||
},
|
||||
modifiers: [],
|
||||
enhancements: [],
|
||||
};
|
||||
area.grid.set(coordKey(at(-2, 0)), industry);
|
||||
area.grid.set(coordKey(at(-1, 3)), industry);
|
||||
|
||||
s.trays.set('crew', {
|
||||
id: 'crew', trainNumber: 1, trainIsExtra: false, engineAt: 0,
|
||||
consist: [{ type: 'hopper', loaded: false }, { type: 'boxcar', loaded: false }],
|
||||
// Facing SOUTH, down the spur. `direction` only carries east/west, so a crew on north-south
|
||||
// track needs its actual port — without it the engine looks for an east exit the card has not
|
||||
// got, and the crew has no legal moves at all.
|
||||
direction: 'east', facing: 's',
|
||||
position: { at: 'grid', owner: 0, coord: at(-1, 0) }, movesUsed: 0,
|
||||
direction: 'east', facing: 'e',
|
||||
position: { at: 'grid', owner: 0, coord: at(-1, 2) }, movesUsed: 0,
|
||||
});
|
||||
s.clock.phase = 'localOps';
|
||||
s.clock.currentActor = 0;
|
||||
@@ -337,7 +340,7 @@ describe('Flying Switch rolls a cut into an industry', () => {
|
||||
const cardId = hand(s, 'maneuver', 'flyingSwitch');
|
||||
|
||||
const r = applyIntent(s, 0, {
|
||||
type: 'maneuver.flyingSwitch', cardId, trayId: 'crew', count: 1, to: at(-2, 0),
|
||||
type: 'maneuver.flyingSwitch', cardId, trayId: 'crew', count: 1, to: at(-1, 3),
|
||||
});
|
||||
assert.ok(r.ok, 'the flying switch should be accepted');
|
||||
|
||||
@@ -346,7 +349,7 @@ describe('Flying Switch rolls a cut into an industry', () => {
|
||||
assert.equal(s.trays.get('crew')!.consist.length, 1, 'the cut leaves the consist');
|
||||
assert.deepEqual(
|
||||
s.trays.get('crew')!.position,
|
||||
{ at: 'grid', owner: 0, coord: at(-1, 0) },
|
||||
{ at: 'grid', owner: 0, coord: at(-1, 2) },
|
||||
'the engine never enters the industry',
|
||||
);
|
||||
assert.equal(s.turn.movesRemaining, 5, 'the manoeuvre costs a Move');
|
||||
@@ -366,7 +369,8 @@ describe('Flying Switch rolls a cut into an industry', () => {
|
||||
const s = game();
|
||||
setup(s);
|
||||
const cardId = hand(s, 'maneuver', 'flyingSwitch');
|
||||
// (0,0) is the Office — track-connected to the crew, but not a freight industry.
|
||||
// (0,0) is the Office — track-connected to the crew back up through the turnout, but not a
|
||||
// freight industry.
|
||||
assert.equal(
|
||||
check(s, 0, { type: 'maneuver.flyingSwitch', cardId, trayId: 'crew', count: 1, to: at(0, 0) }),
|
||||
'CANNOT_DROP_HERE',
|
||||
@@ -377,13 +381,13 @@ describe('Flying Switch rolls a cut into an industry', () => {
|
||||
const s = game();
|
||||
setup(s);
|
||||
const area = areaOf(s, 0);
|
||||
// An industry sitting beside the crew, but joined east-west while the spur runs north-south.
|
||||
const stranded = { ...area.grid.get(coordKey(at(-2, 0)))! };
|
||||
stranded.geometry = { kind: 'track', geometry: 'straight', axis: 'ew' };
|
||||
area.grid.set(coordKey(at(-1, 1)), stranded);
|
||||
// An industry sitting directly beneath the crew. Both cards are plain east-west track, so
|
||||
// nothing crosses the edge between them: adjacency is not a rail.
|
||||
const stranded = { ...area.grid.get(coordKey(at(-1, 3)))! };
|
||||
area.grid.set(coordKey(at(-2, 2)), stranded);
|
||||
const cardId = hand(s, 'maneuver', 'flyingSwitch');
|
||||
assert.equal(
|
||||
check(s, 0, { type: 'maneuver.flyingSwitch', cardId, trayId: 'crew', count: 1, to: at(-1, 1) }),
|
||||
check(s, 0, { type: 'maneuver.flyingSwitch', cardId, trayId: 'crew', count: 1, to: at(-2, 2) }),
|
||||
'NOT_CONNECTED',
|
||||
);
|
||||
});
|
||||
@@ -393,7 +397,7 @@ describe('Flying Switch rolls a cut into an industry', () => {
|
||||
setup(s);
|
||||
const cardId = hand(s, 'maneuver', 'flyingSwitch');
|
||||
assert.equal(
|
||||
check(s, 0, { type: 'maneuver.flyingSwitch', cardId, trayId: 'crew', count: 5, to: at(-2, 0) }),
|
||||
check(s, 0, { type: 'maneuver.flyingSwitch', cardId, trayId: 'crew', count: 5, to: at(-1, 3) }),
|
||||
'CONSIST_EMPTY',
|
||||
);
|
||||
});
|
||||
@@ -454,14 +458,28 @@ describe('the Limits sign moves with the Running Track (§2.1, Gap 4a)', () => {
|
||||
'laying on the Limits sign must be how the track extends',
|
||||
);
|
||||
|
||||
// The district hangs below the Running Track and is not bounded by the Limits at all.
|
||||
// A district opens with a TURNOUT on the Running Track — no office or industry card carries a
|
||||
// stub of its own — so extend onto the east sign with one.
|
||||
s.turn.laidThisTurn = false;
|
||||
const turnoutCol = area.limitsEast.col;
|
||||
assert.ok(
|
||||
applyIntent(s, 0, {
|
||||
type: 'track.lay', geometry: 'turnout', hand: 'left',
|
||||
placement: { row: area.runningRow, col: turnoutCol }, variant: 0,
|
||||
}).ok,
|
||||
'a turnout must be layable on the Limits sign',
|
||||
);
|
||||
|
||||
// The district hangs off that turnout and is not bounded by the Limits at all. Variant 1 of a
|
||||
// left-hand curve is the `ne` arc — the one on the same diagonal as the turnout's leg.
|
||||
s.turn.laidThisTurn = false;
|
||||
assert.equal(
|
||||
check(s, 0, {
|
||||
type: 'track.lay', geometry: 'straight', hand: 'none',
|
||||
placement: { row: area.runningRow - 1, col: 0 }, variant: 1,
|
||||
type: 'track.lay', geometry: 'curved', hand: 'left',
|
||||
placement: { row: area.runningRow - 1, col: turnoutCol }, variant: 1,
|
||||
}),
|
||||
null,
|
||||
'Secondary Track below the Office must stay legal',
|
||||
'Secondary Track below the turnout must stay legal',
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user