more info on train moves in history. train info added to tooltip on timetable and division map. support for multiple trains in area switching. more info on train7/8 wrt location of coach on initial train build.
This commit is contained in:
+44
-5
@@ -507,12 +507,23 @@ function moveTrain(
|
||||
id: TrayId,
|
||||
tray: CrewTray,
|
||||
events: GameEvent[],
|
||||
/**
|
||||
* Which pass is asking. The Mainline Phase moves every train once; Supervisor Shift then asks the
|
||||
* Expedited arrivals to go again. The train cannot tell the difference, but the player must — see
|
||||
* `trainHighballed.why`.
|
||||
*/
|
||||
pass: 'mainline' | 'expedite' = 'mainline',
|
||||
): MoveOutcome {
|
||||
const dir = step(tray.direction);
|
||||
|
||||
if (tray.position.at === 'divisionPoint') {
|
||||
// Read BEFORE `enterMainline` overwrites `tray.position`: the departure line named the side the
|
||||
// train was leaving FROM, and taking it afterwards read the mainline position instead — so every
|
||||
// train reported leaving the Eastern Division Point, including the eastbound ones that had just
|
||||
// been made up at the Western one.
|
||||
const fromSide = (tray.position as { side: Direction }).side;
|
||||
const dpIndex = s.division.nodes.findIndex(
|
||||
(n) => n.kind === 'divisionPoint' && n.side === (tray.position as { side: Direction }).side,
|
||||
(n) => n.kind === 'divisionPoint' && n.side === fromSide,
|
||||
);
|
||||
const target = dpIndex + dir;
|
||||
const node = s.division.nodes[target];
|
||||
@@ -525,7 +536,15 @@ function moveTrain(
|
||||
enterMainline(s, node, id, tray, target);
|
||||
const dp = s.division.nodes[dpIndex];
|
||||
if (dp?.kind === 'divisionPoint') dp.holding = dp.holding.filter((t) => t !== id);
|
||||
events.push({ type: 'phaseBegan', phase: `train ${tray.trainNumber} highballed` });
|
||||
events.push({
|
||||
type: 'trainHighballed',
|
||||
trainNumber: tray.trainNumber ?? 0,
|
||||
from: `the ${fromSide === 'west' ? 'Western' : 'Eastern'} Division Point`,
|
||||
to: 'the Mainline',
|
||||
// Narrated as a phase marker until now — "▸ train 8 highballed phase" — which is not a phase
|
||||
// and told the player nothing about why the train had started its run.
|
||||
why: 'it was made up and the Subdivision ahead was clear, so its run begins',
|
||||
});
|
||||
return 'moved';
|
||||
}
|
||||
|
||||
@@ -580,6 +599,10 @@ function moveTrain(
|
||||
trainNumber: tray.trainNumber ?? 0,
|
||||
from: 'the Office',
|
||||
to: 'the Mainline',
|
||||
why:
|
||||
pass === 'expedite'
|
||||
? 'its card prints EXPEDITE, so it leaves at the end of the Stage it arrived in — you got the Cargo phase with it, but no Local Operations turn to switch it'
|
||||
: 'it stood a full Stage at the Office, so §8.1 released it this Mainline Phase',
|
||||
});
|
||||
return 'moved';
|
||||
}
|
||||
@@ -1019,9 +1042,25 @@ function shiftChange(s: GameState, events: GameEvent[]): AdvanceResult {
|
||||
.sort(([, a], [, b]) => (a.trainNumber ?? 0) - (b.trainNumber ?? 0));
|
||||
for (const [id, tray] of expedited) {
|
||||
tray.departsThisStage = false;
|
||||
// A clearance question cannot be asked here — the Superintendent's phase is over — so an
|
||||
// expedited train that would need a ruling simply stays, and runs normally next Stage.
|
||||
if (moveTrain(s, id, tray, events) === 'needsClearance') continue;
|
||||
/**
|
||||
* An expedited train that would need a §8.1 ruling STAYS, and runs normally from then on.
|
||||
*
|
||||
* Said in the log, because it is the difference between "this train leaves at the end of the
|
||||
* Stage" and "this train is still here next turn", and a player watching one Expedited train
|
||||
* vanish and the next one linger has no way to tell why. Measured on one seed: with ordinary
|
||||
* traffic running, Train 6 was held this way and collected four Local Operations turns.
|
||||
*/
|
||||
if (moveTrain(s, id, tray, events, 'expedite') === 'needsClearance') {
|
||||
events.push({
|
||||
type: 'trainHeld',
|
||||
trainNumber: tray.trainNumber ?? 0,
|
||||
reason:
|
||||
'it EXPEDITES and was due out at the end of this Stage, but the Subdivision ahead needs a ' +
|
||||
'clearance ruling and Supervisor Shift has no Superintendent to give one. It stays, and ' +
|
||||
'runs like an ordinary train from now on — so you DO get a Local Operations turn with it',
|
||||
});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// §5 — the Fedora passes every three Stages: shift changes at Stages 3, 6, 9 and 12.
|
||||
|
||||
Reference in New Issue
Block a user