Something went wrong. Try again.
A Social Deduction / Deception Game
Something went wrong. Try again.
2.4 kB · 48 lines
TypeScript
at main
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849// The PUBLIC projection of a deduction case — what the server sends a client at connect (PURE shapes,// no secret truth). The server holds the full `DeductionCase` (with `condition`/`trueSource`/// `incriminating`/`culpritDid`); the view leaks NONE of it (DEDUCTION.md §6). Crucially the CLUES are// NOT shipped here: a station's stack is revealed one slot at a time over #inspect→#revealed, so the// client can't see how deep a station goes (and can't tell working from sabotaged) until it earns each// reveal. The view just says who to question and which stations can be walked up to and investigated.
import type { SuspectAttributes, Trait } from './types.js'
/** A suspect as the client sees them: identity + visible attire (the only thing fragments quantify * over) + body facts. No secret state. `did` doubles as the key into the streamed world players, * whose `spriteRef` (`at://<did>/actor.rpg.sprite/self`) renders them on the map. */export interface SuspectView { did: string name: string bodyType?: string skinBucket?: string eyeBucket?: string worn: Trait[] held: Trait[]}
/** The whole public case: who to question, which stations to investigate, where interviews happen. */export interface DeductionCaseView { suspects: SuspectView[] /** Station ids the player can walk up to and `#inspect`. Includes clean (working) stations — the * client can't tell which bear clues; it asks the server, which reveals at most the frontier slot. */ inspectableStationIds: string[] /** Human labels for stations that authored one (`town.deception.stationName`, e.g. "Chicken coop"), * keyed by station id — used to make prompts read naturally. Absent id ⟹ fall back to generic wording. */ stationNames: Record<string, string> /** The interview hub (the meeting/voting station); null when the map authors none. */ meetingStationId: string | null}
/** Strip a suspect's attributes down to the public view (drops nothing secret today — attire is all * public — but centralizes the shape so the wire payload stays intentional). */export function suspectView(s: SuspectAttributes): SuspectView { return { did: s.did, name: s.name, ...(s.bodyType ? { bodyType: s.bodyType } : {}), ...(s.skinBucket ? { skinBucket: s.skinBucket } : {}), ...(s.eyeBucket ? { eyeBucket: s.eyeBucket } : {}), worn: s.worn, held: s.held, }}