Files
yellow-snow-wars/tools/smoke.mjs
T
2026-07-18 12:17:09 -05:00

71 lines
2.4 KiB
JavaScript

// Smoke test: two bot clients join, aim at each other, and fight.
// Verifies welcome/state flow, phases, hits, deaths, round ends, scoring.
// Usage: start the server first, then `node tools/smoke.mjs`
import WebSocket from 'ws';
const URL = process.env.SMOKE_URL || 'ws://localhost:3000/ws';
const seen = { phases: new Set(), events: new Set(), scores: new Set() };
function bot(name) {
const ws = new WebSocket(URL);
let me = null;
let latest = null;
ws.on('open', () => ws.send(JSON.stringify({ t: 'join', name })));
ws.on('message', (d) => {
const m = JSON.parse(d.toString());
if (m.t === 'welcome') {
me = m.id;
console.log(`[${name}] welcome, id=${m.id}, seed=${m.seed}`);
return;
}
if (m.t !== 'state') return;
latest = m;
seen.phases.add(m.phase);
for (const e of m.events) {
seen.events.add(e.kind);
if (['die', 'roundEnd', 'matchEnd'].includes(e.kind)) {
console.log(`[${name}] event:`, JSON.stringify(e));
}
}
const mine = m.players.find((p) => p.id === me);
if (mine) seen.scores.add(`${name}:${mine.score}/${mine.hp}`);
});
ws.on('error', (e) => { console.error(`[${name}] ws error:`, e.message); });
// aim at nearest opponent, shuffle around, hold fire
setInterval(() => {
if (ws.readyState !== 1 || !latest) return;
const mine = latest.players.find((p) => p.id === me);
if (!mine) return;
const others = latest.players.filter((p) => p.id !== me && p.alive && p.inRound);
let angle = Math.random() * Math.PI * 2;
if (others.length > 0) {
const t = others[0];
angle = Math.atan2(t.y - mine.y, t.x - mine.x);
}
ws.send(JSON.stringify({
t: 'input',
up: Math.random() < 0.3,
down: Math.random() < 0.3,
left: Math.random() < 0.3,
right: Math.random() < 0.3,
angle,
fire: true,
}));
}, 60);
}
bot('Alpha');
setTimeout(() => bot('Bravo'), 400);
setTimeout(() => {
console.log('\n--- smoke summary ---');
console.log('phases seen :', [...seen.phases].join(', '));
console.log('events seen :', [...seen.events].join(', '));
console.log('score/hp samples:', [...seen.scores].slice(0, 12).join(' '));
const ok = seen.phases.has('round') && seen.events.has('throw') && seen.events.has('hit');
console.log(ok ? '✅ SMOKE OK' : '⚠️ smoke inconclusive (check output above)');
process.exit(0);
}, Number(process.env.SMOKE_MS || 25000));