@adatechnology/game-player 0.0.0-stage → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/data/defaults.json","../src/rng.ts","../src/player.ts","../src/locales/index.ts","../src/bench/locale.ts","../src/bench/module.ts"],"sourcesContent":["export { PLAYER_DEFAULTS, createPlayer, deriveVitals, drawWound } from './player'\nexport type { Player, PlayerOptions } from './player'\nexport { createRng } from './rng'\nexport { PLAYER_TEXT, playerTextOf } from './locales'\nexport type { PlayerText } from './locales'\nexport { createPlayerTestModule } from './bench/module'\nexport type { PlayerTestModule, PlayerTestModuleOptions } from './bench/module'\nexport type * from './types'\n","{\n \"sources\": {\n \"game\": \"specs/001-migracao-entregas-dos-times/artefatos/2UG1Mhe9LqJkQKKVsJkTWR/jogo.js\",\n \"attributes\": \"G 62004 FICHA (Personagens 3.2: every attribute 5, no traits)\",\n \"derived\": \"G 62005-62012 DERIV\",\n \"wounds\": \"G 62016 FERIDA (Personagens 3.7): share of each wound kind, and its infection chance (used only when an infection rule is on)\",\n \"infection\": \"G 62015 INFEC (the slice's accelerated clock: fever 30 s, delirium 70 s, death 120 s, reanimation 8 s after); G 68509 fever noise\",\n \"numbers\": \"G 68427-68640 player, playerUpdate, frontZombies, shove, knife; G 68678-68681 the aim spread modifiers; G 65507 walkCad\"\n },\n \"attributes\": { \"strength\": 5, \"vigor\": 5, \"agility\": 5, \"perception\": 5, \"intellect\": 5, \"presence\": 5 },\n \"derived\": {\n \"maxHealth\": { \"base\": 70, \"terms\": [[\"vigor\", 6]] },\n \"maxStamina\": { \"base\": 40, \"terms\": [[\"vigor\", 6], [\"agility\", 4]] },\n \"runSpeed\": { \"base\": 5.2, \"terms\": [[\"agility\", 0.12]] },\n \"walkSpeed\": { \"base\": 1.6, \"terms\": [] },\n \"footstepNoise\": { \"base\": 100, \"terms\": [[\"agility\", -4]], \"divide\": 100 },\n \"composure\": { \"base\": 20, \"terms\": [[\"vigor\", 3], [\"presence\", 4]] }\n },\n \"wounds\": {\n \"scratch\": { \"share\": 0.6, \"infectionChance\": 0.06, \"bleeds\": false },\n \"laceration\": { \"share\": 0.3, \"infectionChance\": 0.22, \"bleeds\": true },\n \"bite\": { \"share\": 0.1, \"infectionChance\": 1, \"bleeds\": true }\n },\n \"infection\": {\n \"feverSeconds\": 30,\n \"deliriumSeconds\": 70,\n \"deathSeconds\": 120,\n \"reanimateSeconds\": 8,\n \"feverNoiseEvery\": 2,\n \"feverNoiseChance\": 0.5,\n \"feverNoiseRadius\": 10,\n \"feverNoiseVolume\": 2,\n \"feverSpeed\": 0.85,\n \"feverSpread\": 1.5\n },\n \"numbers\": {\n \"hurtFlash\": 0.4,\n \"hurtVolume\": 0.8,\n \"biteDamage\": 25,\n \"biteFlash\": 0.8,\n \"biteVolume\": 1.2,\n \"burnPerSecond\": 3,\n \"bleedPerSecond\": 0.15,\n \"grabSeconds\": 3,\n \"grabVolume\": 1,\n \"grabFollow\": 12,\n \"grabOffset\": 0.55,\n \"grabPushCost\": 6,\n \"grabPushMinStamina\": 5,\n \"grabPushVolume\": 1.5,\n \"grabPushes\": 6,\n \"grabPushStun\": 1.2,\n \"grabPushSpeed\": 3,\n \"grabKnifeChance\": 0.7,\n \"grabKnifeRegion\": 0,\n \"grabKnifeDamage\": 22,\n \"grabKnifeDistance\": 0.5,\n \"grabKnifeCut\": 0.7,\n \"drownDamage\": 30,\n \"drownFlash\": 0.8,\n \"noJawDamage\": 8,\n \"grabAttackCooldown\": 2,\n \"vaultSeconds\": 0.7,\n \"vaultCost\": 15,\n \"vaultHeight\": 1.9,\n \"vaultScanFrom\": 0.3,\n \"vaultScanTo\": 1.0,\n \"vaultScanStep\": 0.1,\n \"vaultLandFrom\": 0.4,\n \"vaultLandTo\": 1.4,\n \"vaultClearance\": 0.3,\n \"vaultCheckHeight\": 0.4,\n \"vaultNoise\": 6,\n \"vaultStartVolume\": 0.8,\n \"vaultLandVolume\": 1,\n \"crouchSpeed\": 1.0,\n \"walkFactor\": 1.35,\n \"aimSpeedCap\": 1.4,\n \"waterSpeed\": 0.55,\n \"runMinStamina\": 1,\n \"runDrain\": 12,\n \"regenMoving\": 4,\n \"regenStill\": 8,\n \"acceleration\": 10,\n \"radius\": 0.3,\n \"blockHeight\": 0.4,\n \"pushApartRadius\": 0.55,\n \"pushApartHeight\": 1.2,\n \"hipFollow\": 10,\n \"hipMinSpeed\": 0.3,\n \"hipLimit\": 0.9,\n \"backwardsBelow\": -0.1,\n \"cadenceBase\": 0.5,\n \"cadencePerSpeed\": 0.3,\n \"cadenceMinSpeed\": 0.05,\n \"turnFollow\": 12,\n \"stepEvery\": 0.75,\n \"stepMinSpeed\": 0.3,\n \"stepNoiseRun\": 8,\n \"stepNoiseWalk\": 3,\n \"stepNoiseCrouch\": 1,\n \"stepNoiseWater\": 2,\n \"stepVolumeRun\": 0.6,\n \"stepVolumeWalk\": 0.3,\n \"shoveCost\": 10,\n \"shoveVolume\": 1.2,\n \"shoveRange\": 1.6,\n \"shoveCone\": 0.3,\n \"shoveStun\": 0.9,\n \"shoveSpeed\": 2.5,\n \"meleeMinStamina\": 5,\n \"meleeCostLight\": 5,\n \"meleeCostHeavy\": 12,\n \"meleeHeavyKg\": 1.5,\n \"meleeVolume\": 0.6,\n \"meleeRangeBase\": 0.9,\n \"meleeCone\": 0.5,\n \"meleeHeadChance\": 0.35,\n \"meleeArmChance\": 0.5,\n \"meleeStrengthPerPoint\": 0.06,\n \"meleeStrengthBase\": 5,\n \"meleeCritToCut\": 60,\n \"panicGain\": 1.2,\n \"panicDecay\": 3,\n \"panicMax\": 100,\n \"panicSpreadAt\": 0.6,\n \"panicSpread\": 1.4,\n \"moveSpread\": 0.4\n },\n \"fist\": { \"damage\": 8, \"crit\": 0, \"reach\": 0.5, \"noise\": 1 }\n}\n","const FNV_OFFSET = 0x811c9dc5\nconst FNV_PRIME = 0x01000193\nconst MIX = 0x9e3779b1\n\n/** Deterministic mulberry32 generator; returns floats in [0, 1). */\nexport function createRng(seed: number): () => number {\n let state = seed >>> 0\n return () => {\n state = (state + 0x6d2b79f5) >>> 0\n let mixed = Math.imul(state ^ (state >>> 15), state | 1)\n mixed ^= mixed + Math.imul(mixed ^ (mixed >>> 7), mixed | 61)\n return ((mixed ^ (mixed >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/** A seed for the stream called `name`: the same seed gives each name its own sequence, so lightning never shifts the schedule. */\nexport function streamSeed(seed: number, name: string): number {\n let hash = FNV_OFFSET\n for (let index = 0; index < name.length; index++) hash = Math.imul(hash ^ name.charCodeAt(index), FNV_PRIME) >>> 0\n return Math.imul((seed >>> 0) ^ hash, MIX) >>> 0\n}\n\nexport function createStream(seed: number, name: string): () => number {\n return createRng(streamSeed(seed, name))\n}\n\nexport function drawBetween(rng: () => number, range: readonly [min: number, max: number]): number {\n return range[0] + rng() * (range[1] - range[0])\n}\n","import defaults from './data/defaults.json'\nimport { createRng } from './rng'\nimport type {\n Attributes,\n DeathCause,\n Derived,\n DerivedFormulas,\n DerivedId,\n InfectionRule,\n LinearFormula,\n MeleeItem,\n PlayerAction,\n PlayerCrowd,\n PlayerEventMap,\n PlayerEventName,\n PlayerInput,\n PlayerMessageId,\n PlayerNumbers,\n PlayerSave,\n PlayerSoundId,\n PlayerState,\n PlayerWorld,\n WoundTable,\n} from './types'\n\nexport const PLAYER_DEFAULTS = defaults as unknown as {\n readonly sources: Readonly<Record<string, string>>\n readonly attributes: Attributes\n readonly derived: DerivedFormulas\n readonly wounds: WoundTable\n readonly infection: InfectionRule\n readonly numbers: PlayerNumbers\n readonly fist: MeleeItem\n}\n\nexport type PlayerOptions = {\n /** The random stream (the game passes its single stream). Default `createRng(seed)`. */\n readonly random?: () => number\n readonly seed?: number\n /** The sheet: every attribute 5 by default. */\n readonly attributes?: Partial<Attributes>\n readonly derived?: Partial<DerivedFormulas>\n readonly wounds?: WoundTable\n /** An individual infection (`true` uses the defaults; an object patches them). Off by default: the normal world comes first. */\n readonly infection?: boolean | Partial<InfectionRule>\n readonly numbers?: Partial<PlayerNumbers>\n readonly fist?: MeleeItem\n readonly position?: { readonly x?: number; readonly z?: number; readonly yaw?: number }\n readonly world?: PlayerWorld\n}\n\nexport type Player = {\n readonly state: PlayerState\n readonly attributes: Attributes\n readonly derived: Derived\n readonly numbers: PlayerNumbers\n readonly infection: InfectionRule | null\n update(dt: number, input?: PlayerInput, world?: PlayerWorld): void\n /** A hit that opens a wound (drawn from the wound table) and may infect. `by` is the agent that hit, if any. */\n hurt(amount: number, by?: number): void\n /** A bite: damage, bleeding, a bite wound and (with an infection rule) the infection. */\n bite(by?: number): void\n grab(by: number, noJaw?: boolean, drown?: boolean): void\n release(): void\n knock(seconds: number): void\n infect(source: string): void\n /** Kills the player with a cause (the host's deaths: a fall, a fire). */\n die(cause: DeathCause): void\n /** Infection stage: `none`, `malaise`, `fever`, `delirium`. */\n stage(): 'none' | 'malaise' | 'fever' | 'delirium'\n /** Seconds the infection has left, or null. */\n timeLeft(): number | null\n /** What the player's state does to aim spread (panic, fever, moving); the weapon multiplies its own spread by it. */\n spreadFactor(): number\n /** The agents in front (nearest first) within `range` m and a cone of `cosMin`, as `[distance, index]`. */\n front(range: number, cosMin: number, yaw: number, crowd?: PlayerCrowd): [number, number][]\n on<K extends PlayerEventName>(event: K, listener: (event: PlayerEventMap[K]) => void): () => void\n save(): PlayerSave\n load(save: PlayerSave): void\n /** The world `update` uses when it is given none. */\n setWorld(world: PlayerWorld): void\n}\n\nconst TAU_APPROX = 6.2832\n\nconst evaluate = (formula: LinearFormula, attributes: Attributes): number => {\n let value = formula.base\n for (const [attribute, coefficient] of formula.terms) value += coefficient * attributes[attribute]\n return formula.divide === undefined ? value : value / formula.divide\n}\n\n/** The derived values of a sheet (the game's `DERIV`). */\nexport const deriveVitals = (attributes: Attributes, formulas: DerivedFormulas = PLAYER_DEFAULTS.derived): Derived => {\n const out = {} as Record<DerivedId, number>\n for (const id of Object.keys(formulas) as DerivedId[]) out[id] = evaluate(formulas[id], attributes)\n return out\n}\n\n/** Which wound a hit opens: one draw, the kinds in the listed order, the last one takes the rest (the game's `FERIDA` draw). */\nexport const drawWound = (wounds: WoundTable, random: () => number): string => {\n const kinds = Object.keys(wounds)\n const draw = random()\n let acc = 0\n for (let k = 0; k < kinds.length - 1; k++) {\n acc += wounds[kinds[k]!]!.share\n if (draw < acc) return kinds[k]!\n }\n return kinds[kinds.length - 1]!\n}\n\nconst clamp = (v: number, a: number, b: number): number => (v < a ? a : v > b ? b : v)\nconst lerp = (a: number, b: number, t: number): number => a + (b - a) * t\n\nconst freshState = (derived: Derived, position: PlayerOptions['position']): PlayerState => ({\n x: position?.x ?? 0,\n z: position?.z ?? 0,\n y: 0,\n vx: 0,\n vz: 0,\n yaw: position?.yaw ?? 0,\n floor: 0,\n alive: true,\n turned: false,\n health: derived.maxHealth,\n stamina: derived.maxStamina,\n crouch: false,\n running: false,\n stepTimer: 0,\n phase: 0,\n hip: 0,\n grabbedBy: -1,\n grabTimer: 0,\n grabPushes: 0,\n grabNoJaw: false,\n grabDrown: false,\n infected: false,\n infectionTime: 0,\n infectionSource: '',\n wounds: [],\n bleeding: 0,\n blind: 0,\n screamBoost: 0,\n panic: 0,\n hurtFlash: 0,\n deathTime: 0,\n cause: '',\n downTimer: 0,\n burnTimer: 0,\n scentTimer: 0,\n vaultTimer: 0,\n vault: null,\n})\n\n/**\n * The player body: a literal port of the team game's `player` and `playerUpdate` (G 68427-68640) with the world, the crowd and the input as\n * arguments instead of globals. The draws on `random` happen in the game's order (wound kind, infection, the fever cough, the knife when grabbed,\n * the melee region), so a game that passes its own stream keeps its sequence.\n */\nexport function createPlayer(options: PlayerOptions = {}): Player {\n const random = options.random ?? createRng(options.seed ?? 1)\n const attributes: Attributes = { ...PLAYER_DEFAULTS.attributes, ...options.attributes }\n const formulas: DerivedFormulas = { ...PLAYER_DEFAULTS.derived, ...options.derived }\n const derived = deriveVitals(attributes, formulas)\n const numbers: PlayerNumbers = { ...PLAYER_DEFAULTS.numbers, ...options.numbers }\n const wounds = options.wounds ?? PLAYER_DEFAULTS.wounds\n const infection: InfectionRule | null =\n options.infection === undefined || options.infection === false ? null : options.infection === true ? PLAYER_DEFAULTS.infection : { ...PLAYER_DEFAULTS.infection, ...options.infection }\n const fist = options.fist ?? PLAYER_DEFAULTS.fist\n const listeners = new Map<PlayerEventName, Set<(event: never) => void>>()\n let P = freshState(derived, options.position)\n let defaultWorld: PlayerWorld = options.world ?? {}\n let world: PlayerWorld = defaultWorld\n\n const emit = <K extends PlayerEventName>(event: K, payload: PlayerEventMap[K]): void => {\n const set = listeners.get(event)\n if (set) for (const listener of set) (listener as (event: PlayerEventMap[K]) => void)(payload)\n }\n const sound = (id: PlayerSoundId, volume: number): void => emit('sound', { sound: id, volume, position: [P.x, P.y, P.z] })\n const noise = (x: number, z: number, radius: number): void => emit('noise', { x, z, radius })\n const message = (id: PlayerMessageId | DeathCause, seconds: number): void => emit('message', { id, seconds })\n const inWater = (x: number, z: number): boolean => world.inWater?.(x, z) ?? false\n const solidAt = (x: number, z: number, y: number): boolean => world.solidAt?.(x, z, y) ?? false\n const cellKind = (x: number, z: number): number => world.cellKind?.(x, z) ?? 0\n const blocked = (x: number, z: number): boolean => (world.blocked ? world.blocked(x, z) : solidAt(x, z, numbers.blockHeight))\n const chanceOf = (kind: string): number => infection?.chances?.[kind] ?? wounds[kind]?.infectionChance ?? 0\n\n const die = (cause: DeathCause): void => {\n if (!P.alive) return\n P.alive = false\n P.cause = cause\n P.deathTime = 0\n P.grabbedBy = -1\n message(cause, 6)\n emit('died', { cause })\n }\n const infect = (source: string): void => {\n if (P.infected || !infection) return\n P.infected = true\n P.infectionTime = 0\n P.infectionSource = source\n emit('infected', { source })\n }\n const release = (how: PlayerEventMap['released']['how'] = 'free'): void => {\n const by = P.grabbedBy\n P.grabbedBy = -1\n if (by >= 0) emit('released', { by, how })\n }\n const hurt = (amount: number): void => {\n if (!P.alive) return\n P.health -= amount\n P.hurtFlash = numbers.hurtFlash\n sound('flesh', numbers.hurtVolume)\n const kind = drawWound(wounds, random)\n P.wounds.push(kind)\n if (wounds[kind]?.bleeds) P.bleeding = 1\n emit('hurt', { amount, wound: kind })\n if (infection && !P.infected && random() < chanceOf(kind)) infect(kind)\n if (P.health <= 0) die(P.infected ? 'infected' : 'killed')\n }\n const bite = (): void => {\n P.health -= numbers.biteDamage\n P.hurtFlash = numbers.biteFlash\n P.bleeding = 1\n P.wounds.push('bite')\n sound('flesh', numbers.biteVolume)\n emit('hurt', { amount: numbers.biteDamage, wound: 'bite' })\n infect('bite')\n message('bitten', 5)\n if (P.health <= 0) die('bitten_to_death')\n }\n const grab = (by: number, noJaw = false, drown = false): void => {\n P.grabbedBy = by\n P.grabTimer = numbers.grabSeconds\n P.grabPushes = 0\n P.grabNoJaw = noJaw\n P.grabDrown = drown\n message(drown ? 'grabbed_drown' : 'grabbed', 3)\n sound('flesh', numbers.grabVolume)\n emit('grabbed', { by, noJaw, drown })\n }\n\n const front = (range: number, cosMin: number, yaw: number, crowd: PlayerCrowd | undefined = world.crowd): [number, number][] => {\n const out: [number, number][] = []\n if (!crowd) return out\n const fx = -Math.sin(yaw)\n const fz = -Math.cos(yaw)\n const n = crowd.count()\n for (let i = 0; i < n; i++) {\n if (!crowd.active(i) || crowd.floor(i) !== P.floor) continue\n const ex = crowd.x(i) - P.x\n const ez = crowd.z(i) - P.z\n const d = Math.hypot(ex, ez)\n if (d < range && (ex * fx + ez * fz) / (d || 1) > cosMin) out.push([d, i])\n }\n return out.sort((a, b) => a[0] - b[0])\n }\n\n const shove = (yaw: number): void => {\n sound('step', numbers.shoveVolume)\n const crowd = world.crowd\n const targets: number[] = []\n for (const [d, i] of front(numbers.shoveRange, numbers.shoveCone, yaw)) {\n crowd!.stun(i, numbers.shoveStun, ((crowd!.x(i) - P.x) / d) * numbers.shoveSpeed, ((crowd!.z(i) - P.z) / d) * numbers.shoveSpeed)\n targets.push(i)\n }\n emit('shove', { targets })\n }\n\n const melee = (item: MeleeItem, yaw: number): void => {\n const t = front(numbers.meleeRangeBase + (item.reach ?? 0), numbers.meleeCone, yaw)[0]\n sound('flesh', numbers.meleeVolume)\n noise(P.x, P.z, item.noise || 1)\n if (!t) return\n const crowd = world.crowd!\n const i = t[1]\n // a blow to the head is x3 in melee; on the ground or crawling it is an execution\n const region = crowd.down(i) ? 0 : random() < numbers.meleeHeadChance ? 0 : random() < numbers.meleeArmChance ? 1 : 2 + Math.floor(random() * 2)\n const damage = item.damage * (1 + (attributes.strength - numbers.meleeStrengthBase) * numbers.meleeStrengthPerPoint)\n const cut = Math.min(1, (item.crit || 0) / numbers.meleeCritToCut)\n crowd.damage(i, { region, amount: damage, distance: t[0], cut })\n emit('melee', { target: i, region, damage, distance: t[0], cut })\n }\n\n const update = (dt: number, input: PlayerInput = {}, frameWorld?: PlayerWorld): void => {\n world = frameWorld ?? defaultWorld\n if (!P.alive) {\n P.deathTime += dt\n if (P.infected && infection && !P.turned && P.deathTime >= infection.reanimateSeconds) {\n P.turned = true\n emit('turned', { x: P.x, z: P.z, floor: P.floor })\n }\n return\n }\n const pressed: Partial<Record<PlayerAction, boolean>> = { ...input.pressed }\n const wasPressed = (action: PlayerAction): boolean => {\n const v = pressed[action] === true\n pressed[action] = false\n return v\n }\n const viewYaw = input.yaw ?? 0\n const crowd = world.crowd\n P.screamBoost = Math.max(0, P.screamBoost - dt)\n P.blind = Math.max(0, P.blind - dt)\n P.hurtFlash = Math.max(0, P.hurtFlash - dt)\n // infection on its own clock\n if (P.infected && infection) {\n const before = P.infectionTime\n P.infectionTime += dt\n if (before <= infection.feverSeconds && P.infectionTime > infection.feverSeconds) emit('stage', { stage: 'fever' })\n if (before <= infection.deliriumSeconds && P.infectionTime > infection.deliriumSeconds) emit('stage', { stage: 'delirium' })\n const every = 1 / infection.feverNoiseEvery\n if (P.infectionTime > infection.feverSeconds && Math.floor(P.infectionTime * every) !== Math.floor((P.infectionTime - dt) * every) && random() < infection.feverNoiseChance) {\n noise(P.x, P.z, infection.feverNoiseRadius)\n sound('step', infection.feverNoiseVolume)\n }\n if (P.infectionTime > infection.deathSeconds) {\n P.health = 0\n die('infection')\n return\n }\n }\n if (P.burnTimer > 0) {\n P.burnTimer -= dt\n P.health -= numbers.burnPerSecond * dt\n if (inWater(P.x, P.z)) P.burnTimer = 0\n }\n P.scentTimer = Math.max(0, P.scentTimer - dt)\n if (P.bleeding) {\n P.health -= dt * numbers.bleedPerSecond\n if (input.bandage && P.bleeding) {\n P.bleeding = 0\n message('bandaged', 2)\n }\n }\n if (P.health <= 0) {\n die(P.infected ? 'infected' : P.bleeding ? 'bled_out' : 'hunger_thirst')\n return\n }\n // grabbed: seconds to react\n if (P.grabbedBy >= 0) {\n const i = P.grabbedBy\n P.grabTimer -= dt\n if (crowd) {\n const k = 1 - Math.exp(-dt * numbers.grabFollow) // glued to the body without a jump\n crowd.hold(i, P.x - Math.sin(P.yaw) * numbers.grabOffset, P.z - Math.cos(P.yaw) * numbers.grabOffset, k, P.x, P.z)\n }\n if (wasPressed('push') && P.stamina > numbers.grabPushMinStamina) {\n P.grabPushes++\n P.stamina -= numbers.grabPushCost\n sound('step', numbers.grabPushVolume)\n }\n if (wasPressed('knife')) {\n if (random() < numbers.grabKnifeChance) {\n crowd?.damage(i, { region: numbers.grabKnifeRegion, amount: numbers.grabKnifeDamage, distance: numbers.grabKnifeDistance, cut: numbers.grabKnifeCut })\n message('knife_head', 1.5)\n release('knife')\n return\n } else message('knife_miss', 1)\n }\n if (P.grabPushes >= numbers.grabPushes) {\n crowd?.stun(i, numbers.grabPushStun, -Math.sin(viewYaw) * numbers.grabPushSpeed, -Math.cos(viewYaw) * numbers.grabPushSpeed)\n release('push')\n message('pushed_off', 1.2)\n return\n }\n if (P.grabTimer <= 0) {\n if (P.grabDrown) {\n P.health -= numbers.drownDamage\n P.hurtFlash = numbers.drownFlash\n message('drowning', 2)\n if (P.health <= 0) {\n die('drowned')\n return\n }\n P.grabTimer = numbers.grabSeconds\n P.grabPushes = 0\n return\n }\n if (P.grabNoJaw) {\n hurt(numbers.noJawDamage)\n message('no_jaw', 2)\n } else bite()\n crowd?.chase(i, numbers.grabAttackCooldown)\n release(P.grabNoJaw ? 'scratch' : 'bite')\n }\n return\n }\n // knocked down\n if (P.downTimer > 0) {\n P.downTimer -= dt\n P.vx = P.vz = 0\n if (P.downTimer <= 0) message('stood_up', 0.8)\n return\n }\n if (world.busy?.(dt)) return\n // vaulting a low wall\n if (P.vaultTimer > 0 && P.vault) {\n P.vaultTimer -= dt\n const k = 1 - P.vaultTimer / numbers.vaultSeconds\n P.x = lerp(P.vault[0], P.vault[2], k)\n P.z = lerp(P.vault[1], P.vault[3], k)\n P.y = Math.sin(k * Math.PI) * numbers.vaultHeight\n if (P.vaultTimer <= 0) {\n P.y = 0\n noise(P.x, P.z, numbers.vaultNoise)\n sound('step', numbers.vaultLandVolume)\n }\n return\n }\n if (wasPressed('vault') && P.stamina > numbers.vaultCost && (world.canVault?.() ?? !P.floor)) {\n const fx0 = -Math.sin(viewYaw)\n const fz0 = -Math.cos(viewYaw)\n for (let a = numbers.vaultScanFrom; a <= numbers.vaultScanTo; a += numbers.vaultScanStep) {\n const c = cellKind(P.x + fx0 * a, P.z + fz0 * a)\n if (c === 2) {\n for (let e = a + numbers.vaultLandFrom; e <= a + numbers.vaultLandTo; e += numbers.vaultScanStep) {\n const ex = P.x + fx0 * e\n const ez = P.z + fz0 * e\n if (!solidAt(ex, ez, numbers.vaultCheckHeight) && !solidAt(ex + fx0 * numbers.vaultClearance, ez + fz0 * numbers.vaultClearance, numbers.vaultCheckHeight)) {\n P.vault = [P.x, P.z, ex, ez]\n P.vaultTimer = numbers.vaultSeconds\n P.stamina -= numbers.vaultCost\n sound('step', numbers.vaultStartVolume)\n emit('vault', { from: [P.x, P.z], to: [ex, ez] })\n return\n }\n }\n break\n }\n if (c > 0 && c !== 3) break\n }\n }\n // movement\n const f = input.forward ?? 0\n const s = input.right ?? 0\n if (wasPressed('crouch')) P.crouch = !P.crouch\n const want = f || s\n P.running = !!(input.run && want && P.stamina > numbers.runMinStamina && !input.aim && !P.crouch)\n const fever = P.infected && infection !== null && P.infectionTime > infection.feverSeconds\n let sp = P.running ? derived.runSpeed : P.crouch ? numbers.crouchSpeed : derived.walkSpeed * numbers.walkFactor\n if (fever) sp *= infection!.feverSpeed\n if (input.aim) sp = Math.min(sp, numbers.aimSpeedCap)\n const wet = inWater(P.x, P.z)\n if (wet) sp *= numbers.waterSpeed\n if (P.running) P.stamina = Math.max(0, P.stamina - numbers.runDrain * dt)\n else P.stamina = Math.min(derived.maxStamina, P.stamina + (want ? numbers.regenMoving : numbers.regenStill) * dt)\n const fx = -Math.sin(viewYaw)\n const fz = -Math.cos(viewYaw)\n const mx = fx * f - fz * s\n const mz = fz * f + fx * s\n const ml = Math.hypot(mx, mz) || 1\n const tvx = want ? (mx / ml) * sp : 0\n const tvz = want ? (mz / ml) * sp : 0\n P.vx = lerp(P.vx, tvx, Math.min(1, dt * numbers.acceleration))\n P.vz = lerp(P.vz, tvz, Math.min(1, dt * numbers.acceleration))\n const r = numbers.radius\n const nx = P.x + P.vx * dt\n const nz = P.z + P.vz * dt\n if (!blocked(nx + Math.sign(P.vx) * r, P.z)) P.x = nx\n if (!blocked(P.x, nz + Math.sign(P.vz) * r)) P.z = nz\n world.afterMove?.(P)\n // the player does not walk through the crowd: agents pressed against the body push it out\n if (crowd) {\n const n = crowd.count()\n const rr = numbers.pushApartRadius\n for (let i = 0; i < n; i++) {\n if (!crowd.active(i) || Math.abs(crowd.y(i) - P.y) > numbers.pushApartHeight) continue\n const ex = P.x - crowd.x(i)\n const ez = P.z - crowd.z(i)\n const e2 = ex * ex + ez * ez\n if (e2 < rr * rr && e2 > 1e-5) {\n const e = Math.sqrt(e2)\n const k = ((rr - e) / e) * 0.5\n if (!solidAt(P.x + ex * k, P.z + ez * k, numbers.blockHeight)) {\n P.x += ex * k\n P.z += ez * k\n }\n }\n }\n }\n const spd = Math.hypot(P.vx, P.vz)\n // the legs follow the move even with the torso on the aim; walking backwards flips the stride\n {\n const cy = Math.cos(P.yaw)\n const sy = Math.sin(P.yaw)\n const lx = P.vx * cy - P.vz * sy\n const lz = P.vx * sy + P.vz * cy\n const back = lz < numbers.backwardsBelow ? -1 : 1\n const hip = spd > numbers.hipMinSpeed ? clamp(Math.atan2(lx * back, lz * back), -numbers.hipLimit, numbers.hipLimit) : 0\n P.hip = P.hip + (hip - P.hip) * Math.min(1, dt * numbers.hipFollow)\n P.phase += dt * (spd < numbers.cadenceMinSpeed ? 0 : numbers.cadenceBase + numbers.cadencePerSpeed * spd) * back\n }\n // the body follows the view (fast, no snap); aiming or firing, at once\n {\n const target = viewYaw + Math.PI\n let dy = target - P.yaw\n dy -= Math.round(dy / TAU_APPROX) * TAU_APPROX\n P.yaw += input.aim || input.firing ? dy : dy * Math.min(1, dt * numbers.turnFollow)\n }\n // footsteps make noise: walk 3 m, run 8 m, crouched 1 m (x the sheet's footstep noise, x2 in water)\n P.stepTimer -= dt * spd\n if (P.stepTimer <= 0 && spd > numbers.stepMinSpeed) {\n P.stepTimer = numbers.stepEvery\n noise(P.x, P.z, (P.running ? numbers.stepNoiseRun : P.crouch ? numbers.stepNoiseCrouch : numbers.stepNoiseWalk) * derived.footstepNoise * (wet ? numbers.stepNoiseWater : 1))\n sound('step', P.running ? numbers.stepVolumeRun : numbers.stepVolumeWalk)\n emit('step', { x: P.x, z: P.z, yaw: P.yaw })\n }\n // shove and melee\n if (wasPressed('push') && P.stamina > numbers.shoveCost) {\n P.stamina -= numbers.shoveCost\n shove(viewYaw)\n }\n if (wasPressed('throw')) emit('throw', {})\n if (wasPressed('knife') && P.stamina > numbers.meleeMinStamina) {\n const item = input.melee ?? fist\n P.stamina -= (item.kg ?? 0) > numbers.meleeHeavyKg ? numbers.meleeCostHeavy : numbers.meleeCostLight\n melee(item, viewYaw)\n }\n // panic: chasing agents in sight nearby\n let near = 0\n if (crowd) {\n const n = crowd.count()\n for (let i = 0; i < n; i++) if (crowd.active(i) && crowd.chasing(i)) near += crowd.panicWeight?.(i) ?? 1\n }\n P.panic = clamp(P.panic + (near * numbers.panicGain - (near ? 0 : numbers.panicDecay)) * dt, 0, numbers.panicMax)\n }\n\n return {\n get state() {\n return P\n },\n attributes,\n derived,\n numbers,\n infection,\n update,\n hurt: (amount) => hurt(amount),\n bite: () => bite(),\n grab,\n release: () => release('free'),\n knock(seconds) {\n if (!P.alive) return\n P.downTimer = Math.max(P.downTimer, seconds)\n P.crouch = false\n },\n infect,\n die,\n stage() {\n if (!P.infected || !infection) return 'none'\n return P.infectionTime > infection.deliriumSeconds ? 'delirium' : P.infectionTime > infection.feverSeconds ? 'fever' : 'malaise'\n },\n timeLeft: () => (P.infected && infection ? Math.max(0, infection.deathSeconds - P.infectionTime) : null),\n spreadFactor() {\n const panic = P.panic > derived.composure * numbers.panicSpreadAt ? numbers.panicSpread : 1\n const fever = P.infected && infection && P.infectionTime > infection.feverSeconds ? infection.feverSpread : 1\n return panic * fever * (1 + Math.hypot(P.vx, P.vz) * numbers.moveSpread)\n },\n front,\n on(event, listener) {\n let set = listeners.get(event)\n if (!set) listeners.set(event, (set = new Set()))\n set.add(listener as (event: never) => void)\n return () => void set.delete(listener as (event: never) => void)\n },\n save: () => ({ state: structuredClone(P), attributes }),\n load(save) {\n P = structuredClone(save.state)\n },\n setWorld(next) {\n defaultWorld = next\n },\n }\n}\n","import type { KnownDeathCause, PlayerMessageId } from '../types'\n\nexport type PlayerText = Readonly<Record<PlayerMessageId | KnownDeathCause, string>>\n\n/** The game's own words (G 68434, 68452, 68518, 68525-68541, 68547) and the death causes it shows (G 68448, 68454, 68510, 68519, 68539). */\nconst PT_BR: PlayerText = {\n grabbed: 'AGARRADO! Aperte E várias vezes para empurrar ou F para a faca',\n grabbed_drown: 'O AFOGADO TE PUXA PARA O FUNDO! E várias vezes ou F para a faca',\n bitten: 'Você foi mordido. Não há cura.',\n bandaged: 'Curativo feito',\n knife_head: 'Faca na cabeça!',\n knife_miss: 'Errou a facada',\n pushed_off: 'Empurrou!',\n drowning: 'Afogando! Solte-se!',\n no_jaw: 'Sem mandíbula: só arranhou',\n stood_up: 'De pé!',\n infected: 'Morreu infectado',\n killed: 'Morto pela horda',\n bitten_to_death: 'Mordido',\n infection: 'A infecção venceu',\n bled_out: 'Sangrou até a morte',\n hunger_thirst: 'Fome e sede',\n drowned: 'Afogado',\n burned: 'Queimado',\n}\n\nconst EN: PlayerText = {\n grabbed: 'GRABBED! Press E repeatedly to push or F for the knife',\n grabbed_drown: 'THE DROWNED PULLS YOU UNDER! E repeatedly or F for the knife',\n bitten: 'You were bitten. There is no cure.',\n bandaged: 'Wound dressed',\n knife_head: 'Knife to the head!',\n knife_miss: 'The stab missed',\n pushed_off: 'Pushed off!',\n drowning: 'Drowning! Break free!',\n no_jaw: 'No jaw: only a scratch',\n stood_up: 'Back on your feet!',\n infected: 'Died infected',\n killed: 'Killed by the horde',\n bitten_to_death: 'Bitten',\n infection: 'The infection won',\n bled_out: 'Bled to death',\n hunger_thirst: 'Hunger and thirst',\n drowned: 'Drowned',\n burned: 'Burned',\n}\n\nexport const PLAYER_TEXT: Readonly<Record<'en' | 'pt-BR', PlayerText>> = { en: EN, 'pt-BR': PT_BR }\n\n/** The text of a message or death cause id in a locale (`pt-BR` or `en`, the language part is enough); unknown ids come back as they are. */\nexport const playerTextOf = (id: string, locale = 'pt-BR'): string => {\n const table = locale.toLowerCase().startsWith('en') ? EN : PT_BR\n return (table as Readonly<Record<string, string>>)[id] ?? id\n}\n","export type PlayerBenchText = {\n readonly group: string\n readonly name: string\n readonly controls: Readonly<Record<'infection' | 'agility' | 'vigor' | 'seed' | 'hurt' | 'bite' | 'grab' | 'push' | 'knife' | 'bandage' | 'knock' | 'crouch' | 'reset', string>>\n readonly hints: Readonly<Record<'infection' | 'agility' | 'vigor' | 'seed' | 'grab' | 'push', string>>\n readonly metrics: Readonly<Record<'health' | 'stamina' | 'bleeding' | 'wounds' | 'stage' | 'time_left' | 'panic' | 'spread' | 'grab' | 'noise' | 'steps' | 'message', string>>\n readonly stages: Readonly<Record<'none' | 'malaise' | 'fever' | 'delirium' | 'dead', string>>\n readonly scenarios: Readonly<Record<'stamina' | 'bleed_bandage' | 'normal_world' | 'infection_kills' | 'grab_break_free' | 'determinism', string>>\n readonly yes: string\n readonly no: string\n}\n\nconst EN: PlayerBenchText = {\n group: 'Player',\n name: 'Player area',\n controls: {\n infection: 'Individual infection',\n agility: 'Agility',\n vigor: 'Vigor',\n seed: 'Seed',\n hurt: 'Take a hit (10)',\n bite: 'Bite',\n grab: 'Get grabbed',\n push: 'Push (E)',\n knife: 'Knife (F)',\n bandage: 'Bandage (B)',\n knock: 'Knocked down 1.5 s',\n crouch: 'Crouch (C)',\n reset: 'Start again',\n },\n hints: {\n infection: 'Off: a normal world, wounds never infect. On: the game rule (scratch 6%, laceration 22%, bite 100%; fever at 30 s, death at 120 s).',\n agility: 'The sheet: stamina, run speed and footstep noise come from it.',\n vigor: 'The sheet: health, stamina and composure come from it.',\n seed: 'The same seed gives the same wounds and the same knife rolls.',\n grab: 'Something grabs you from behind: 3 s to push it off (6 pushes) or to land the knife (70%).',\n push: 'Shoves what is in front, or pushes off what holds you.',\n },\n metrics: {\n health: 'Health',\n stamina: 'Stamina',\n bleeding: 'Bleeding',\n wounds: 'Wounds',\n stage: 'Infection',\n time_left: 'Time left',\n panic: 'Panic',\n spread: 'Aim spread x',\n grab: 'Grab timer',\n noise: 'Last noise',\n steps: 'Footsteps',\n message: 'Message',\n },\n stages: { none: 'None', malaise: 'Malaise', fever: 'Fever', delirium: 'Delirium', dead: 'Dead' },\n scenarios: {\n stamina: 'Running drains stamina and resting gives it back',\n bleed_bandage: 'A laceration bleeds until it is dressed',\n normal_world: 'In a normal world a bite hurts and bleeds but never infects',\n infection_kills: 'With the infection on, a bite brings fever and kills at its time',\n grab_break_free: 'Six pushes break a grab before the bite',\n determinism: 'The same seed gives the same wounds',\n },\n yes: 'yes',\n no: 'no',\n}\n\nconst PT_BR: PlayerBenchText = {\n group: 'Jogador',\n name: 'Área do jogador',\n controls: {\n infection: 'Infecção individual',\n agility: 'Agilidade',\n vigor: 'Vigor',\n seed: 'Semente',\n hurt: 'Levar um golpe (10)',\n bite: 'Mordida',\n grab: 'Ser agarrado',\n push: 'Empurrar (E)',\n knife: 'Faca (F)',\n bandage: 'Curativo (B)',\n knock: 'Derrubado 1,5 s',\n crouch: 'Agachar (C)',\n reset: 'Recomeçar',\n },\n hints: {\n infection: 'Desligada: mundo normal, ferida nunca infecta. Ligada: a regra do jogo (arranhão 6%, laceração 22%, mordida 100%; febre aos 30 s, morte aos 120 s).',\n agility: 'A ficha: fôlego, velocidade de corrida e ruído dos passos saem dela.',\n vigor: 'A ficha: vida, fôlego e compostura saem dela.',\n seed: 'A mesma semente dá as mesmas feridas e os mesmos golpes de faca.',\n grab: 'Algo te agarra por trás: 3 s para empurrar (6 empurrões) ou acertar a faca (70%).',\n push: 'Empurra o que está na frente, ou se solta do que te segura.',\n },\n metrics: {\n health: 'Vida',\n stamina: 'Fôlego',\n bleeding: 'Sangrando',\n wounds: 'Feridas',\n stage: 'Infecção',\n time_left: 'Tempo restante',\n panic: 'Pânico',\n spread: 'Dispersão x',\n grab: 'Agarrão',\n noise: 'Último ruído',\n steps: 'Passos',\n message: 'Mensagem',\n },\n stages: { none: 'Nenhuma', malaise: 'Mal-estar', fever: 'Febre', delirium: 'Delírio', dead: 'Morto' },\n scenarios: {\n stamina: 'Correr gasta fôlego e descansar devolve',\n bleed_bandage: 'Uma laceração sangra até o curativo',\n normal_world: 'No mundo normal a mordida machuca e sangra, mas não infecta',\n infection_kills: 'Com a infecção ligada, a mordida dá febre e mata no tempo dela',\n grab_break_free: 'Seis empurrões soltam o agarrão antes da mordida',\n determinism: 'A mesma semente dá as mesmas feridas',\n },\n yes: 'sim',\n no: 'não',\n}\n\nexport const playerBenchTextOf = (locale: string): PlayerBenchText => (locale.toLowerCase().startsWith('en') ? EN : PT_BR)\n","import type { BenchChange, ModuleControl, ModuleHost, ModuleMetric, ModuleScenario, TestableModule } from '@adatechnology/game-contracts'\n\nimport { playerTextOf } from '../locales'\nimport { createPlayer } from '../player'\nimport type { Player, PlayerOptions } from '../player'\nimport type { PlayerAction, PlayerCrowd, PlayerInput } from '../types'\nimport { playerBenchTextOf } from './locale'\n\nexport type PlayerTestModuleOptions = PlayerOptions & { readonly locale?: string }\n\n/** What the scenarios use of the context the test room passes. */\nexport interface PlayerScenarioLike {\n expect(condition: boolean, label: string, data?: Record<string, unknown>): void\n}\n\nexport type PlayerTestModule = TestableModule<PlayerScenarioLike> & {\n /** The player in use (replaced when the bench changes the sheet, the seed or the infection). */\n readonly player: Player\n}\n\ntype CameraLike = { position: { x: number; y: number; z: number }; rotation?: { y: number }; getWorldDirection?(target: unknown): { x: number; z: number } }\ntype ThreeLike = { Vector3?: new () => { x: number; y: number; z: number } }\n\nconst MOVING_SPEED = 0.2\nconst SPRINT_SPEED = 3.4\nconst FRAME = 1 / 30\n\n/**\n * One agent standing behind the player for the grab test: the bench has no crowd, so this is the hand that holds. It follows `hold`, takes\n * the shove and the knife, and leaves the count once it lets go.\n */\nconst createGrabber = () => {\n const agent = { x: 0, z: 0, on: false, stunned: 0, hits: 0 }\n const crowd: PlayerCrowd = {\n count: () => (agent.on ? 1 : 0),\n active: () => agent.on,\n x: () => agent.x,\n z: () => agent.z,\n y: () => 0,\n floor: () => 0,\n chasing: () => agent.on,\n down: () => agent.stunned > 0,\n hold(_i, x, z, k) {\n agent.x += (x - agent.x) * k\n agent.z += (z - agent.z) * k\n },\n stun(_i, seconds) {\n agent.stunned = seconds\n agent.on = false\n },\n chase() {\n agent.on = false\n },\n damage() {\n agent.hits += 1\n agent.on = false\n },\n }\n return { agent, crowd }\n}\n\n/**\n * The player area of a test room, against the generic contracts only. The room's camera is the player: where it walks, the player walks; its speed\n * decides walking or running, so stamina, footsteps and their noise follow the viewer. The bench hurts, bites, grabs and knocks the player down,\n * switches the individual infection (off by default: a normal world) and sets the sheet. Footsteps and flesh sounds go to `host.audio`.\n */\nexport function createPlayerTestModule(options: PlayerTestModuleOptions = {}): PlayerTestModule {\n const locale = options.locale ?? 'pt-BR'\n const text = playerBenchTextOf(locale)\n const { locale: _locale, ...playerOptions } = options\n void _locale\n const settings = { infection: options.infection === undefined ? false : options.infection !== false, agility: options.attributes?.agility ?? 5, vigor: options.attributes?.vigor ?? 5, seed: options.seed ?? 1 }\n let host: ModuleHost | null = null\n const grabber = createGrabber()\n let lastNoise = 0\n let steps = 0\n let lastMessage = ''\n let pending: Partial<Record<PlayerAction, boolean>> = {}\n let bandage = false\n let last: { x: number; z: number } | null = null\n const offs: (() => void)[] = []\n\n const build = (): Player => {\n for (const off of offs.splice(0)) off()\n const made = createPlayer({ ...playerOptions, seed: settings.seed, infection: settings.infection, attributes: { ...playerOptions.attributes, agility: settings.agility, vigor: settings.vigor } })\n offs.push(made.on('noise', (e) => void (lastNoise = e.radius)))\n offs.push(made.on('step', () => void (steps += 1)))\n offs.push(made.on('message', (e) => void (lastMessage = playerTextOf(e.id, locale))))\n offs.push(made.on('sound', (e) => void host?.audio?.play({ sound: e.sound, volume: e.volume, position: e.position })))\n offs.push(made.on('died', (e) => host?.log(`player died: ${e.cause}`, { cause: e.cause })))\n lastNoise = 0\n steps = 0\n lastMessage = ''\n return made\n }\n let player = build()\n\n const view = (): { x: number; z: number; yaw: number } | null => {\n const camera = host?.camera as CameraLike | undefined\n if (!camera?.position) return null\n const Vector3 = (host?.THREE as ThreeLike | undefined)?.Vector3\n if (camera.getWorldDirection && Vector3) {\n const look = camera.getWorldDirection(new Vector3())\n return { x: camera.position.x, z: camera.position.z, yaw: Math.atan2(-look.x, -look.z) }\n }\n return { x: camera.position.x, z: camera.position.z, yaw: camera.rotation?.y ?? 0 }\n }\n\n const frame = (dt: number): void => {\n const here = view()\n const speed = here && last && dt > 0 ? Math.hypot(here.x - last.x, here.z - last.z) / dt : 0\n if (here) {\n player.state.x = here.x\n player.state.z = here.z\n }\n const input: PlayerInput = { forward: speed > MOVING_SPEED ? 1 : 0, run: speed > SPRINT_SPEED, yaw: here?.yaw ?? 0, bandage, pressed: pending }\n pending = {}\n bandage = false\n player.update(dt, input, { crowd: grabber.crowd })\n if (here) {\n player.state.x = here.x\n player.state.z = here.z\n last = { x: here.x, z: here.z }\n }\n if (grabber.agent.stunned > 0) grabber.agent.stunned = Math.max(0, grabber.agent.stunned - dt)\n }\n\n const grab = (): void => {\n const P = player.state\n grabber.agent.on = true\n grabber.agent.x = P.x - Math.sin(P.yaw) * player.numbers.grabOffset\n grabber.agent.z = P.z - Math.cos(P.yaw) * player.numbers.grabOffset\n player.grab(0)\n }\n\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'action') {\n const id = change.id\n if (id === 'hurt') player.hurt(10)\n else if (id === 'bite') player.bite()\n else if (id === 'grab') grab()\n else if (id === 'knock') player.knock(1.5)\n else if (id === 'bandage') bandage = true\n else if (id === 'push' || id === 'knife' || id === 'crouch') pending = { ...pending, [id]: true }\n else if (id === 'reset') player = build()\n return\n }\n if (change.kind !== 'control') return\n const { id, value } = change\n if (id === 'infection' && typeof value === 'boolean' && value !== settings.infection) settings.infection = value\n else if ((id === 'agility' || id === 'vigor' || id === 'seed') && typeof value === 'number' && value !== settings[id]) settings[id] = value\n else return\n player = build()\n }\n\n const controls = (): ModuleControl[] => [\n { kind: 'boolean', id: 'infection', name: text.controls.infection, hint: text.hints.infection, default: settings.infection },\n { kind: 'number', id: 'agility', name: text.controls.agility, hint: text.hints.agility, min: 1, max: 8, step: 1, default: settings.agility },\n { kind: 'number', id: 'vigor', name: text.controls.vigor, hint: text.hints.vigor, min: 1, max: 8, step: 1, default: settings.vigor },\n { kind: 'number', id: 'seed', name: text.controls.seed, hint: text.hints.seed, min: 1, max: 9999, step: 1, default: settings.seed },\n { kind: 'action', id: 'hurt', name: text.controls.hurt },\n { kind: 'action', id: 'bite', name: text.controls.bite },\n { kind: 'action', id: 'grab', name: text.controls.grab, hint: text.hints.grab },\n { kind: 'action', id: 'push', name: text.controls.push, hint: text.hints.push },\n { kind: 'action', id: 'knife', name: text.controls.knife },\n { kind: 'action', id: 'bandage', name: text.controls.bandage },\n { kind: 'action', id: 'knock', name: text.controls.knock },\n { kind: 'action', id: 'crouch', name: text.controls.crouch },\n { kind: 'action', id: 'reset', name: text.controls.reset },\n ]\n\n const stageName = (): string => (player.state.alive ? text.stages[player.stage()] : text.stages.dead)\n const metrics = (): ModuleMetric[] => [\n { id: 'health', name: text.metrics.health, digits: 1, max: player.derived.maxHealth, read: () => Math.max(0, player.state.health) },\n { id: 'stamina', name: text.metrics.stamina, digits: 1, max: player.derived.maxStamina, read: () => player.state.stamina },\n { id: 'bleeding', name: text.metrics.bleeding, read: () => (player.state.bleeding ? text.yes : text.no) },\n { id: 'wounds', name: text.metrics.wounds, digits: 0, read: () => player.state.wounds.length },\n { id: 'stage', name: text.metrics.stage, read: stageName },\n { id: 'time_left', name: text.metrics.time_left, unit: 's', digits: 0, read: () => player.timeLeft() ?? 0 },\n { id: 'panic', name: text.metrics.panic, digits: 1, read: () => player.state.panic },\n { id: 'spread', name: text.metrics.spread, digits: 2, read: () => player.spreadFactor() },\n { id: 'grab_timer', name: text.metrics.grab, unit: 's', digits: 1, read: () => (player.state.grabbedBy >= 0 ? player.state.grabTimer : 0) },\n { id: 'noise', name: text.metrics.noise, unit: 'm', digits: 1, read: () => lastNoise },\n { id: 'steps', name: text.metrics.steps, digits: 0, read: () => steps },\n { id: 'message', name: text.metrics.message, read: () => lastMessage },\n ]\n\n // each scenario runs its own player, so the bench's live one is not touched\n const fresh = (extra: PlayerOptions = {}): Player => createPlayer({ ...playerOptions, ...extra })\n const run = (made: Player, seconds: number, input: PlayerInput = {}, crowd?: PlayerCrowd): void => {\n for (let t = 0; t < seconds; t += FRAME) made.update(FRAME, input, crowd ? { crowd } : undefined)\n }\n const scenarios = (): Array<ModuleScenario<PlayerScenarioLike>> => [\n {\n id: 'player_stamina',\n name: text.scenarios.stamina,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n const full = made.state.stamina\n run(made, 4, { forward: 1, run: true })\n const tired = made.state.stamina\n expect(tired < full - 40, 'four seconds of running spend 48 of stamina', { full, tired })\n run(made, 3)\n expect(made.state.stamina > tired, 'standing still gives it back', { tired, rested: made.state.stamina })\n },\n },\n {\n id: 'player_bleed_bandage',\n name: text.scenarios.bleed_bandage,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n made.bite()\n const after = made.state.health\n run(made, 2)\n expect(made.state.bleeding === 1 && made.state.health < after, 'the wound bleeds', { health: made.state.health })\n run(made, FRAME, { bandage: true })\n const dressed = made.state.health\n run(made, 2)\n expect(made.state.bleeding === 0 && made.state.health === dressed, 'dressed, it stops', { health: made.state.health })\n },\n },\n {\n id: 'player_normal_world',\n name: text.scenarios.normal_world,\n run: ({ expect }) => {\n const made = fresh({ seed: 1, infection: false })\n made.bite()\n run(made, 10)\n expect(!made.state.infected && made.state.health < made.derived.maxHealth, 'bitten, hurt, not infected', { health: made.state.health })\n },\n },\n {\n id: 'player_infection_kills',\n name: text.scenarios.infection_kills,\n run: ({ expect }) => {\n const made = fresh({ seed: 1, infection: true })\n made.bite()\n run(made, FRAME, { bandage: true })\n run(made, 40)\n expect(made.stage() === 'fever', 'fever after 30 s', { stage: made.stage() })\n run(made, 90)\n expect(!made.state.alive && made.state.cause === 'infection', 'dead at 120 s', { cause: made.state.cause })\n },\n },\n {\n id: 'player_grab_break_free',\n name: text.scenarios.grab_break_free,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n const { agent, crowd } = createGrabber()\n agent.on = true\n made.grab(0)\n for (let push = 0; push < 6; push++) {\n made.update(FRAME, { pressed: { push: true } }, { crowd })\n made.update(FRAME, {}, { crowd })\n }\n expect(made.state.grabbedBy === -1 && made.state.wounds.length === 0, 'free, and no bite', { grabbedBy: made.state.grabbedBy })\n },\n },\n {\n id: 'player_determinism',\n name: text.scenarios.determinism,\n run: ({ expect }) => {\n const wounds = (seed: number): string => {\n const made = fresh({ seed })\n for (let k = 0; k < 12; k++) made.hurt(1)\n return made.state.wounds.join(',')\n }\n expect(wounds(4) === wounds(4), 'the same seed gives the same wounds')\n expect(wounds(4) !== wounds(5), 'another seed gives others')\n },\n },\n ]\n\n const module: PlayerTestModule = {\n id: 'player_area',\n name: text.name,\n group: text.group,\n get player() {\n return player\n },\n items: () => [],\n controls: () => controls(),\n metrics: () => metrics(),\n scenarios: () => scenarios(),\n attach(lent) {\n host = lent\n last = null\n const off = lent.bench?.onChange(onChange)\n const offFrame = lent.onFrame(frame)\n return () => {\n off?.()\n offFrame()\n host = null\n }\n },\n }\n return module\n}\n"],"mappings":"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","names":["EN","PT_BR","id"]}