various fixes. added version#s and added a playable browser build of the solitaire game (including deploy to filebrowser script)
This commit is contained in:
+87
-4
@@ -27,12 +27,14 @@ import {
|
||||
modifierProfile,
|
||||
nextOfficeTier,
|
||||
officeProfile,
|
||||
trainProfile,
|
||||
} from './content.ts';
|
||||
import type { CarType, FreightKind, Hand, MainlineKind, ModifierKind, TrackGeometry } from './content.ts';
|
||||
import type { GameEvent } from './events.ts';
|
||||
import type { Intent, RejectionCode } from './intents.ts';
|
||||
import type {
|
||||
CardId,
|
||||
CrewTray,
|
||||
Facility,
|
||||
GameState,
|
||||
GridCoord,
|
||||
@@ -468,7 +470,15 @@ export function check(s: GameState, player: PlayerIndex, i: Intent): RejectionCo
|
||||
if (!s.yards.divisionYard.some((c) => c.type === i.carType && c.loaded === i.loaded)) {
|
||||
return 'NO_SUITABLE_CAR';
|
||||
}
|
||||
return null;
|
||||
|
||||
// §8.2 — "the train must be in the order listed on the train's card (engine on the front,
|
||||
// Rolling Stock, and possibly a Caboose). It may depart with FEWER Rolling Stock than listed,
|
||||
// but not out of order."
|
||||
//
|
||||
// This was not enforced at all: any car could be added in any quantity, so Train 9 "Heavy
|
||||
// Freight" — a card calling for 3 freight AND a caboose — was made up with four hoppers and
|
||||
// no caboose. Fewer is allowed; more, or of the wrong category, is not.
|
||||
return acceptsCar(tray, i.carType) ? null : 'NO_SUITABLE_CAR';
|
||||
}
|
||||
|
||||
case 'newTrain.secondSection': {
|
||||
@@ -613,8 +623,15 @@ function checkPlay(
|
||||
// nothing, which is exactly the bug that made Modifiers dead weight for weeks.
|
||||
return 'NOT_IMPLEMENTED';
|
||||
|
||||
case 'timetabledTrain':
|
||||
case 'extraTrain':
|
||||
// A train card goes to the TIMETABLE, not onto the board. Accepting a placement made the UI
|
||||
// offer the same play at six different grid squares with six rotations apiece — all identical,
|
||||
// because the placement was then ignored. Same reasoning as the Office upgrade above: silently
|
||||
// discarding a placement makes the event log claim the card was laid somewhere it was not.
|
||||
return placement ? 'NO_PLACEMENT' : null;
|
||||
|
||||
default:
|
||||
// Train cards go to the timetable; the phase driver schedules them.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1528,10 +1545,76 @@ function applyModifier(area: OfficeArea, coord: GridCoord, modifier: ModifierKin
|
||||
}
|
||||
|
||||
/** §2.1, Gap 4a — extending the Running Track pushes the Limits sign outward. */
|
||||
/**
|
||||
* §2.1 Gap 4a — "when you extend your Running Track, the Limits sign MOVES outwards with it".
|
||||
*
|
||||
* The sign is a physical card, not just a recorded column. Moving only the coordinate left the
|
||||
* Limits card stranded mid-track: a district grew to
|
||||
* (0,-5) (0,-4) (0,-3) (0,-2)=Power Plant [LIMITS] (0,0)=Office [LIMITS] (0,2)=Freight House …
|
||||
* with everything beyond (0,-2) built OUTSIDE a sign that never moved. That is not cosmetic —
|
||||
* §8.1 and §10 both reason about "the track between the train and the Limits", Interlocking holds
|
||||
* an arrival AT the Limits, and running past a player's Limits is what makes a collision his fault.
|
||||
*/
|
||||
function extendLimitsIfNeeded(area: OfficeArea, placed: GridCoord): void {
|
||||
if (placed.row !== area.runningRow) return;
|
||||
if (placed.col <= area.limitsWest.col) area.limitsWest = { row: placed.row, col: placed.col - 1 };
|
||||
if (placed.col >= area.limitsEast.col) area.limitsEast = { row: placed.row, col: placed.col + 1 };
|
||||
|
||||
if (placed.col <= area.limitsWest.col) {
|
||||
area.limitsWest = { row: placed.row, col: placed.col - 1 };
|
||||
area.grid.set(coordKey(area.limitsWest), limitsCard());
|
||||
}
|
||||
if (placed.col >= area.limitsEast.col) {
|
||||
area.limitsEast = { row: placed.row, col: placed.col + 1 };
|
||||
area.grid.set(coordKey(area.limitsEast), limitsCard());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* §8.2 — may this car be coupled onto this train right now?
|
||||
*
|
||||
* "The train must be in the order listed on the train's card (engine on the front, Rolling Stock,
|
||||
* and possibly a Caboose). It may depart with FEWER Rolling Stock than listed, but not out of
|
||||
* order." Fewer is allowed; more, or of the wrong category, is not.
|
||||
*
|
||||
* SHARED. Both `check` and the New Train Phase's "is there a suitable car in the yard" test call
|
||||
* this. A second copy stalled the game outright: the phase believed a car could be added while
|
||||
* `check` rejected every option, so the Stage never completed.
|
||||
*/
|
||||
export function acceptsCar(tray: CrewTray, carType: CarType): boolean {
|
||||
const profile = trainProfile(tray.trainNumber ?? 0, tray.trainIsExtra);
|
||||
if (!profile) return true;
|
||||
|
||||
const cat = (t: CarType): 'coach' | 'caboose' | 'freight' =>
|
||||
t === 'coach' ? 'coach' : t === 'caboose' ? 'caboose' : 'freight';
|
||||
const adding = cat(carType);
|
||||
const already = tray.consist.filter((c) => cat(c.type) === adding).length;
|
||||
const allowed =
|
||||
adding === 'coach'
|
||||
? profile.consist.coach
|
||||
: adding === 'caboose'
|
||||
? profile.consist.caboose
|
||||
: profile.consist.freight;
|
||||
if (already >= allowed) return false;
|
||||
|
||||
// The caboose rides last (§A.3), so nothing may be coupled behind one.
|
||||
if (adding !== 'caboose' && tray.consist.some((c) => c.type === 'caboose')) return false;
|
||||
|
||||
// The card also narrows WHICH freight types it will take.
|
||||
const types = profile.consist.freightTypes;
|
||||
if (adding === 'freight' && types && !types.includes(carType)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** A fresh Limits sign. The set is "2N + spares" (§12), so relocating one is not a supply question. */
|
||||
function limitsCard(): TrackCard {
|
||||
return {
|
||||
geometry: { kind: 'limits' },
|
||||
baseOperationalRail: true,
|
||||
standing: [],
|
||||
facility: null,
|
||||
modifiers: [],
|
||||
enhancements: [],
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user