Something went wrong. Try again.
a tiny pet with a GPT-2 brain, living in your browser
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899import { FLOOR, W as LW } from "../scene.ts";import { animate } from "./animation.ts";import { petCommand } from "./commands.ts";import { petEngine } from "./engine.ts";import { emit, store, ui, view } from "./store.ts";import { clamp } from "./utils.ts";import { isRemote } from "./hosting.ts";
// ---------- catch minigame (after the pet said yes) ----------// The engine records the accepted game; this module plays it and reports the// score once, by the game's id.export function gameId() { return isRemote() ? ui.remoteGameId : petEngine().game?.id || null;}let starting = 0;/** Starts the game the pet accepted, after its answer has had a moment on screen. */export function startAcceptedGame() { if (view.game || starting || !gameId()) return; starting = setTimeout(() => { starting = 0; if (gameId()) startGame(); }, 600);}export function startGame() { if (!store.tabOwned || !store.state.pet || store.state.asleep || view.game) return; view.game = { stars: [], score: 0, timeLeft: 20, last: performance.now(), spawn: 0, dir: 0, held: new Map(), }; view.target = view.x; emit();}export function gameControl(id: string, dir: number) { const g = view.game; if (!g) return; g.held.delete(id); if (dir) g.held.set(id, dir); // The newest held input wins; releasing another finger/key cannot stop it. g.dir = [...g.held.values()].at(-1) || 0; view.target = view.x;}export function stopGameControls() { if (!view.game) return; view.game.held.clear(); view.game.dir = 0; view.target = view.x;}export function stepGame(now: number) { const g = view.game!; const dt = Math.min(0.05, (now - g.last) / 1000); g.last = now; g.timeLeft -= dt; g.spawn -= dt; if (g.spawn <= 0) { g.stars.push({ x: 8 + Math.random() * (LW - 16), y: -4, v: 18 + Math.random() * 14 + (20 - g.timeLeft), bad: Math.random() < 0.18, }); g.spawn = 0.55 + Math.random() * 0.5; } if (g.dir) view.target = clamp(view.x + g.dir * 70 * dt, 10, LW - 10); const dx = view.target - view.x; if (dx) { view.facing = Math.sign(dx); view.x += Math.sign(dx) * Math.min(Math.abs(dx), 70 * dt); view.walking = true; } else view.walking = false; for (const s of g.stars) { s.y += s.v * dt; if (!s.done && s.y > FLOOR - 16 && s.y < FLOOR - 4 && Math.abs(s.x - view.x) < 10) { s.done = true; if (s.bad) { g.score = Math.max(0, g.score - 1); animate("wow", 400, true); } else { g.score++; animate("happy", 400, true); } } } g.stars = g.stars.filter((s) => !s.done && s.y < FLOOR + 4); if (g.timeLeft <= 0) endGame();}export function endGame() { const score = view.game!.score, id = gameId(); view.game = null; view.target = view.x; emit(); if (id) void petCommand({ type: "gameComplete", gameId: id, score });}