import { describe, expect, test } from 'bun:test'; import { createSimulation, stepSimulation } from './simulation'; import { SIMULATION_CONFIG } from './types'; import { generateObservation, observationToInputs } from './sensors'; // Mock Genome that implements Perfect Tracking Logic const perfectTrackerGenome = { id: 9999, nodes: [], connections: [], fitness: 0 }; // Strafer Bot (Same as in selfPlay.ts) const straferGenome = { id: -3, nodes: [], connections: [], fitness: 0 }; describe('Aim Mechanics Verification', () => { test('Perfect Tracker should defeat Strafer', () => { // Setup Simulation const sim = createSimulation(12345, 2); // Pair 2 (Strafer pair) let trackerHits = 0; let straferHits = 0; // Run Match let currentSim = sim; const maxTicks = 300; for (let t = 0; t < maxTicks; t++) { const obsTracker = generateObservation(0, currentSim); // --- PERFECT LOGIC --- // 1. Get Target Relative Angle from Sensor (Index 54 in 0-based array of 56 inputs) // But we can just read it from observation directly const targetAngle = obsTracker.targetRelativeAngle; // [-1, 1] const targetVisible = obsTracker.targetVisible; // 2. Control Logic // If angle > 0 (Left), Turn Left (-1). If angle < 0 (Right), Turn Right (1). // P-Controller: turn = angle * K const K = 5.0; // Strong gain let turn = -targetAngle * K; // Note: Sign depends on coordinate system. // In setup: Angle is Aim - Target. // If Target is to Left (Positive relative?), we need to turn Left (Positive/Negative?) // Let's verify sign: // If target is at angle 0.1 (Left), we want to Increase Aim Angle? // Usually turn +1 adds to angle. // So turn = +1 * K. // Note: targetRelativeAngle = (Target - Aim) / PI. // If Target > Aim (Positive), we need to Turn Positive. turn = targetAngle * 20.0; // Max turn // Clamp if (turn > 1) turn = 1; if (turn < -1) turn = -1; // Shoot if locked on const shoot = (Math.abs(targetAngle) < 0.05 && targetVisible > 0.5) ? 1.0 : 0.0; const actionTracker = { moveX: 0, moveY: 0, turn: turn, shoot: shoot }; // --- STRAFER LOGIC --- const straferMoveY = Math.sin(t * 0.2); const actionStrafer = { moveX: 0, moveY: straferMoveY, turn: 0, shoot: 0 // Strafer is passive to isolate aim test }; // Step currentSim = stepSimulation(currentSim, [actionTracker, actionStrafer]); // Count hits if (currentSim.agents[1].hits > trackerHits) { trackerHits = currentSim.agents[1].hits; // Agent 1 is Strafer // console.log(`Hit at tick ${t}! Total: ${trackerHits}`); } } console.log(`Perfect Tracker Result: ${trackerHits} Hits on Strafer in ${maxTicks} ticks.`); // Assert Feasibility // We expect at least 3-5 hits to prove it's possible. expect(trackerHits).toBeGreaterThan(3); }); });