Files
waving-hands/src/lib/game/view.ts
T

61 lines
2.4 KiB
TypeScript

// What one wizard is allowed to know. Gestures made while they were blind, or
// while the other wizard was invisible, are unknown to them; the log lines that
// describe those gestures are withheld too. Spells cast are always visible, as
// the rules say.
import { hiddenFromViewer, visibleHistory, type GameState, type WizardId } from './state';
export function viewFor(state: GameState, viewer: WizardId): GameState {
const view = structuredClone(state);
for (const id of view.seats) {
if (id === viewer) continue;
view.wizards[id].history = visibleHistory(state, viewer, id);
}
view.log = view.log.filter((l) => !hiddenFromViewer(l.hiddenFrom, viewer));
return view;
}
/** One line of table talk: from a seat, or from the Peanut Gallery when the host allows it (id SPECTATOR, signed with `name`), or from the keeper of the site. */
export interface ChatLine {
id: WizardId;
text: string;
at: number;
name?: string;
keeper?: true;
}
/** What a seated player, or the gallery, is told by the server. Other seats' moves and tokens never leave it. */
export interface RoomView {
roomId: string;
seq: number;
/** The most seats the table will take. */
size: number;
/** The viewer's seat, or SPECTATOR for the gallery. */
me: WizardId;
/** The wizard who opened the table and may begin the duel. */
host: WizardId;
/** Who sits where; `standIn` marks a wizard's seat the host gave to a bot, which duels in it until they take it back. */
seats: { id: WizardId; name: string; bot: boolean; standIn?: true }[];
/** Seats that still have to move before the turn resolves. */
waitingOn: WizardId[];
/** Turns played so far, time stops included; gestures are sent with the count they were made against. */
resolved: number;
state: GameState | null;
chat: ChatLine[];
/** How many watch from the Peanut Gallery. */
audience: number;
/** The host lets the gallery talk. */
galleryTalk: boolean;
/** The keeper of the site was called to a seat, and by whom. */
challenge: { by: WizardId; at: number } | null;
/** Names with a seat held who have not yet sat: the last table's wizards, or the keeper. */
expected: string[];
/** A finished table's rematch: where it went, and who called. */
rematch: { to: string; by: WizardId } | null;
/** The table this one is the rematch of. */
rematchOf: string | null;
/** The keeper of the site, and where they live, for a table that calls them. */
keeper: string;
keeperZone: string;
}