import { describe, expect, it } from 'vitest'; import { applyWear, freshCondition, repair, SUBSYSTEMS, type CarCondition } from './car'; import { isWrittenOff, KIA_LAND_LOSS, replacementCar } from './kia'; import { createFront, applyMissionImpact, depthAt } from './regions'; import { accept, createQuests, failQuest, type Offer } from './quests'; const at = (chassis: number): CarCondition => ({ level: { engine: 0.5, tires: 0.5, chassis }, ceiling: { engine: 0.8, tires: 0.8, chassis: 0.8 }, }); describe('being written off', () => { it('is the chassis that kills you, not the engine or the tyres', () => { expect(isWrittenOff(at(0))).toBe(true); expect(isWrittenOff(at(0.01))).toBe(false); expect( isWrittenOff({ level: { engine: 0, tires: 0, chassis: 0.4 }, ceiling: { engine: 1, tires: 1, chassis: 1 }, }), ).toBe(false); }); it('is reachable — a car can actually be driven into the ground', () => { let c = freshCondition(); for (let i = 0; i < 400 && !isWrittenOff(c); i++) { c = applyWear(c, { dt: 1 / 60, distance: 3, throttle: 1, impactForce: 2.5e6 }); } expect(isWrittenOff(c)).toBe(true); }); }); describe('the replacement car', () => { it('is handed over running, or it would kill you again immediately', () => { const next = replacementCar(at(0)); expect(isWrittenOff(next)).toBe(false); for (const part of SUBSYSTEMS) { expect(next.level[part]).toBeCloseTo(next.ceiling[part], 9); } }); it('is always worse than the one you wrote off', () => { const before = at(0); const next = replacementCar(before); for (const part of SUBSYSTEMS) { expect(next.ceiling[part]).toBeLessThan(before.ceiling[part]); } }); it('ratchets down over a long campaign without ever becoming undriveable', () => { let c = freshCondition(); let previous = 1; for (let death = 0; death < 40; death++) { c = replacementCar({ ...c, level: { ...c.level, chassis: 0 } }); expect(c.ceiling.chassis).toBeLessThanOrEqual(previous); previous = c.ceiling.chassis; // Whatever else is true, you can always get back on the road. expect(isWrittenOff(c)).toBe(false); expect(repair(c, 99).condition.level.chassis).toBeGreaterThan(0); } // Twenty-odd deaths in and the car is a genuinely miserable thing to drive. expect(previous).toBeLessThan(0.35); }); }); describe('what a death costs', () => { it('gives ground back to the enemy', () => { const front = createFront(11, 400, { x: 0, z: 0 }); const before = front.boundaries.liberated; applyMissionImpact(front, -KIA_LAND_LOSS); expect(front.boundaries.liberated).toBeLessThan(before); }); it('loses the job in hand without counting it as a run', () => { const quests = createQuests(); const offer = { id: 1, type: 'supply', targetNode: 4, novel: true, route: { nodes: [0, 4], segments: [0], length: 900 }, intel: { worst: 'clear', unknownCount: 1, stalest: null }, reward: 0.3, impact: 15, } as unknown as Offer; accept(quests, offer, { nodeId: 0, x: 0, z: 0, hutX: 0, hutZ: 0, name: 'Anvil' }); const lost = failQuest(quests); expect(lost?.type).toBe('supply'); expect(quests.active).toBeNull(); expect(quests.completed).toBe(0); expect(quests.failed).toBe(1); expect(quests.funds).toBe(0); }); it('is a setback, not a campaign reversal', () => { // Sanity on the scale: a death should cost less ground than a couple of // decent missions win, or dying once undoes an evening's work. const front = createFront(3, 400, { x: 0, z: 0 }); const start = depthAt(front, 0, 0); void start; applyMissionImpact(front, 40); const won = front.boundaries.liberated; applyMissionImpact(front, -KIA_LAND_LOSS); expect(front.boundaries.liberated).toBeLessThan(won); expect(front.boundaries.liberated).toBeGreaterThan(won - 40); }); });