v0.3.1 — multiplayer groundwork: 13 engine tests covering 2-4 player games, a seat parameter on snapshot and actionMenu so a player sees their own railroad rather than seat 0's, and the 22 opponent-directed cards held out of every deck until they are built
This commit is contained in:
+16
-11
@@ -314,7 +314,7 @@ export type Menu = {
|
||||
};
|
||||
|
||||
/** The action list as the page shows it: direct actions, plus subject-then-location for the rest. */
|
||||
export function actionMenu(game: Game): Menu {
|
||||
export function actionMenu(game: Game, seat: PlayerIndex = 0): Menu {
|
||||
const { options, groups } = actionGroups(game);
|
||||
const direct: ActionGroup[] = [];
|
||||
const placeableByTitle = new Map<string, Map<string, Placeable>>();
|
||||
@@ -367,7 +367,7 @@ export function actionMenu(game: Game): Menu {
|
||||
* generate options, so changing the stored order would reshuffle its tie-breaks and invalidate
|
||||
* every revenue measurement in TODO.md. `snapshot()` reverses identically for the replay viewers.
|
||||
*/
|
||||
const handIds = [...(game.state.decks.hands.get(0) ?? [])].reverse();
|
||||
const handIds = [...(game.state.decks.hands.get(seat) ?? [])].reverse();
|
||||
const hand: HandAction[] = handIds.map((cardId) => {
|
||||
const place = placeable.flatMap((g) => g.items).find((it) => it.subjectKey === `card:${cardId}`);
|
||||
let playNow: number | null = null;
|
||||
@@ -554,7 +554,8 @@ function joinsNote(
|
||||
): string {
|
||||
const v = variantsFor(geometry, hand)[variant ?? 0];
|
||||
if (!v) return '';
|
||||
const area = areaOf(game.state, 0);
|
||||
// The probe is against the district the placement would be made in, i.e. the actor's own.
|
||||
const area = areaOf(game.state, currentActor(game) ?? 0);
|
||||
const probe = {
|
||||
geometry: { kind: 'track', geometry, ...v, ...(hand !== 'none' ? { hand } : {}) },
|
||||
baseOperationalRail: true, standing: [], facility: null, modifiers: [], enhancements: [],
|
||||
@@ -601,9 +602,9 @@ function consistTitle(game: Game, trayId: string): string | null {
|
||||
* held. The same test the engine applies to `draw.end`, asked here so the page can DISABLE the
|
||||
* button with a reason instead of hiding a move that has simply become illegal.
|
||||
*/
|
||||
export function overHandLimit(game: Game): boolean {
|
||||
const hand = game.state.decks.hands.get(0) ?? [];
|
||||
const limit = game.state.decks.redFlags.get(0) ? HAND_LIMIT + 1 : HAND_LIMIT;
|
||||
export function overHandLimit(game: Game, seat: PlayerIndex = 0): boolean {
|
||||
const hand = game.state.decks.hands.get(seat) ?? [];
|
||||
const limit = game.state.decks.redFlags.get(seat) ? HAND_LIMIT + 1 : HAND_LIMIT;
|
||||
return hand.length > limit;
|
||||
}
|
||||
|
||||
@@ -631,8 +632,8 @@ export function submit(game: Game, intent: Intent): boolean {
|
||||
* Modifier with no Facility to sit beside — looks identical to one where everything is available.
|
||||
* Derived from `legalActions`, so it cannot disagree with what the buttons offer.
|
||||
*/
|
||||
export function handPlayable(game: Game): boolean[] {
|
||||
const hand = game.state.decks.hands.get(0) ?? [];
|
||||
export function handPlayable(game: Game, seat: PlayerIndex = 0): boolean[] {
|
||||
const hand = game.state.decks.hands.get(seat) ?? [];
|
||||
const actor = currentActor(game);
|
||||
if (actor === null) return hand.map(() => false);
|
||||
const playable = new Set(
|
||||
@@ -643,9 +644,13 @@ export function handPlayable(game: Game): boolean[] {
|
||||
return hand.map((id) => playable.has(id));
|
||||
}
|
||||
|
||||
/** The board as the replay draws it, so the live game and the replay agree. */
|
||||
export function view(game: Game): Frame {
|
||||
return snapshot(game.state, [], null);
|
||||
/**
|
||||
* The board as the replay draws it, so the live game and the replay agree.
|
||||
*
|
||||
* `seat` is whose railroad and whose hand to show. Solitaire has one seat and never passes it.
|
||||
*/
|
||||
export function view(game: Game, seat: PlayerIndex = 0): Frame {
|
||||
return snapshot(game.state, [], null, null, null, false, seat);
|
||||
}
|
||||
|
||||
function record(game: Game, events: GameEvent[], actor: PlayerIndex | null = null): void {
|
||||
|
||||
Reference in New Issue
Block a user