v0.4.9h — a leg that is part of the row, the deck the sheet prints, and regions not miles per hour
The 0.4.9 line's port of v0.7.2, minus Gitea#18: the Division map redraw is a multiplayer redesign and does not belong in a build people are mid-playtest on. Gitea#17 — a 45° leg is an end of the west-to-east row, so backing into a cut through a curve's south leg no longer couples it back to front, and a crew pulling out through a leg takes its own cut with it. Gitea#14 — every count is docs/Deck cards5.xlsx, including removing the Q12 office doubling and the Gap 12 industry tripling. Gitea#15 — RAR reversed it: the placement is legal; what must hold is that no train crosses the gap. Gitea#3 — the printed speeds are scenery. One Stage per printed region, and where a train starts is what varies.
This commit is contained in:
@@ -540,6 +540,100 @@ describe('placement and drop-off', () => {
|
||||
assert.ok(!canPlaceAt(area, at(-1, 1), straight()), 'an east-west straight cannot meet a 45° leg');
|
||||
});
|
||||
|
||||
describe('a rail that stops dead against its neighbour (Gitea#15)', () => {
|
||||
/**
|
||||
* REPORTED, THEN REVERSED. The issue first read "if a card is placed in that space, it MUST
|
||||
* connect", against a right-hand curve laid at (1,-1) with an Ice House above it and a turnout
|
||||
* with a north-facing leg below. **RAR reviewed it and ruled the other way (2026-08-26): the
|
||||
* placement is fine, and a stub like that has a use — a siding to park cars on.**
|
||||
*
|
||||
* "We need to confirm, however, that trains are not allowed to traverse from the turnout below
|
||||
* to that right-hand curve since the tracks do not connect." That is what these tests are: the
|
||||
* rule lives in MOVEMENT, not in placement.
|
||||
*
|
||||
* The save cannot carry this any more — Gitea#14 took the deck from 206 cards to 121, so its
|
||||
* card ids no longer exist and the history stops at the first `card.play`. The geometry is what
|
||||
* mattered, and it is rebuilt here directly.
|
||||
*/
|
||||
/** A Modifier card — an Ice House. Not track: no ports on any edge. */
|
||||
const modifierCard = (): TrackCard => ({
|
||||
geometry: { kind: 'modifier', modifier: 'iceHouse' },
|
||||
baseOperationalRail: false,
|
||||
standing: [],
|
||||
standingWest: 0,
|
||||
facility: null,
|
||||
modifiers: [],
|
||||
enhancements: [],
|
||||
});
|
||||
|
||||
/** A Grocer's Warehouse — a Facility, so a plain east-west through track. */
|
||||
const warehouse = (): TrackCard => ({
|
||||
geometry: { kind: 'facility', facility: 'grocersWarehouse' },
|
||||
baseOperationalRail: true,
|
||||
standing: [],
|
||||
standingWest: 0,
|
||||
facility: null,
|
||||
modifiers: [],
|
||||
enhancements: [],
|
||||
});
|
||||
|
||||
/**
|
||||
* The reported district. `withCurve` puts the disputed right-hand curve on the square; without
|
||||
* it, the square is empty and the placement itself is under test.
|
||||
*
|
||||
* The turnout's leg goes NORTH on the `nw_se` diagonal; the curve is `ne`, which is `ne_sw` and
|
||||
* has no south port at all. Two reasons the two do not join, either of which is enough.
|
||||
*/
|
||||
const board = (withCurve: boolean): OfficeArea =>
|
||||
areaFrom(
|
||||
{
|
||||
[coordKey(at(0, -1))]: turnout({ stem: 'w', through: 'e', diverge: 'n' }),
|
||||
[coordKey(at(0, 0))]: officeCard(),
|
||||
[coordKey(at(1, 0))]: warehouse(),
|
||||
[coordKey(at(2, -1))]: modifierCard(),
|
||||
...(withCurve ? { [coordKey(at(1, -1))]: curve('ne') } : {}),
|
||||
},
|
||||
at(0, 0),
|
||||
);
|
||||
|
||||
it('allows the reported placement, which connects on one side and nothing else', () => {
|
||||
// RAR's ruling. The curve joins the warehouse to its east; its north leg faces an Ice House
|
||||
// that carries no rail, and the turnout below faces its portless south edge. All legal.
|
||||
assert.ok(canPlaceAt(board(false), at(1, -1), curve('ne')), 'the reported play was refused');
|
||||
});
|
||||
|
||||
it('will not let a train cross from the turnout below onto that curve', () => {
|
||||
// The confirmation the issue actually asks for. Running west out of the Office and into the
|
||||
// turnout, the 45° leg goes north — and stops at the curve's blank south edge.
|
||||
const dests = reachableDestinations(ctxFor(board(true)), at(0, 0), 'w');
|
||||
assert.ok(!has(dests, 1, -1), 'a train drove across rails that do not meet');
|
||||
});
|
||||
|
||||
it('still reaches the curve from the side that DOES join', () => {
|
||||
// Otherwise the test above would pass on a card that is simply unreachable, which proves
|
||||
// nothing. East of the curve is the warehouse, and east-west edges always meet.
|
||||
const dests = reachableDestinations(ctxFor(board(true)), at(1, 0), 'w');
|
||||
assert.ok(has(dests, 1, -1), 'the curve was unreachable from the side that joins');
|
||||
});
|
||||
|
||||
it('will not let a train cross a north edge onto a card with no rail at all', () => {
|
||||
// The Ice House above. A Modifier is scenery beside the rails — Jesse confirmed a rail may
|
||||
// point at a building — so what stops a train is the same `joins` test, not a placement rule.
|
||||
const dests = reachableDestinations(ctxFor(board(true)), at(1, 0), 'w');
|
||||
assert.ok(!has(dests, 2, -1), 'a train drove into an Ice House');
|
||||
});
|
||||
|
||||
it('still allows an exit that faces a BLANK square', () => {
|
||||
// Unchanged by the reversal, and the reason a district can grow at all: a turnout laid on the
|
||||
// Running Track with nothing yet beside its diverging leg is a perfectly good play.
|
||||
const area = areaFrom({ [coordKey(at(0, 0))]: officeCard() }, at(0, 0));
|
||||
assert.ok(
|
||||
canPlaceAt(area, at(0, 1), turnout({ stem: 'w', through: 'e', diverge: 'n' })),
|
||||
'a turnout whose leg faces open space was refused',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('refuses a card that connects to nothing', () => {
|
||||
const area = areaFrom({ [coordKey(at(0, 0))]: officeCard() }, at(0, 0));
|
||||
assert.ok(!canPlaceAt(area, at(3, 3), straight()), 'orphaned track is never legal');
|
||||
|
||||
Reference in New Issue
Block a user