/** Headless example: plays the game for many ticks with no browser/DOM involved at all — proves * GameStore/its entities (see src/game/entities) can run standalone, and demonstrates measuring * how often a player would need to act (pick a new target) per unit of simulated time. * * Run with: npx tsx scripts/simulate.ts [ticks] [tickSeconds] */ import { Rabbit } from '../src/game/entities/Rabbit'; import { ResourceNode } from '../src/game/entities/ResourceNode'; import { GameStore } from '../src/game/GameStore'; const totalTicks = Number(process.argv[2] ?? 1_000_000); const tickSeconds = Number(process.argv[3] ?? 0.1); const mapWidth = 1200; const mapHeight = 800; const store = new GameStore(); store.initialize(mapWidth, mapHeight); // A minimal bot policy standing in for a player: keep whatever target is currently held as long // as it still exists; otherwise pick the nearest node or rabbit and hold it. Each such pick is // counted as one "user action" — a mouse click choosing a new thing to interact with. let actionCount = 0; for (let i = 0; i < totalTicks; i++) { if (store.isDead) break; const stillHoldingNode = store.heldNodeId !== null && store.nodes.some((node) => node.id === store.heldNodeId); const stillHoldingRabbit = store.heldRabbitId !== null && store.rabbits.some((rabbit) => rabbit.id === store.heldRabbitId); if (!stillHoldingNode && !stillHoldingRabbit) { const nearestNode = ResourceNode.findNearestToPosition(store.nodes, store.character); const nearestRabbit = Rabbit.findNearestToPosition(store.rabbits, store.character); const nodeDistance = nearestNode ? Math.hypot(nearestNode.x - store.character.x, nearestNode.y - store.character.y) : Infinity; const rabbitDistance = nearestRabbit ? Math.hypot(nearestRabbit.x - store.character.x, nearestRabbit.y - store.character.y) : Infinity; if (nearestNode && nodeDistance <= rabbitDistance) { store.holdNode(nearestNode.id); actionCount++; } else if (nearestRabbit) { store.holdRabbit(nearestRabbit.id); actionCount++; } } store.tick(tickSeconds); } const simulatedSeconds = totalTicks * tickSeconds; console.log(JSON.stringify({ ticks: totalTicks, simulatedDay: Number((store.day + store.hour / 24).toFixed(2)), isDead: store.isDead, inventory: store.inventory, actionCount, actionsPerSimulatedMinute: Number((actionCount / (simulatedSeconds / 60)).toFixed(3)), }, null, 2));