| 1 |
import { expect, test } from "bun:test"; |
| 2 |
import { applyDamage, damage, isLethal, shotSpread, WEAPONS, zoneFromMiss } from "./weapons.ts"; |
| 3 |
|
| 4 |
test("a Vandal head shot kills through full armour at any range, a Phantom's does not", () => { |
| 5 |
for (const distance of [100, 800, 2000]) expect(isLethal(100, 50, damage("vandal", "head", distance))).toBe(true); |
| 6 |
|
| 7 |
|
| 8 |
expect(isLethal(100, 50, damage("phantom", "head", 300))).toBe(true); |
| 9 |
expect(isLethal(100, 50, damage("phantom", "head", 900))).toBe(false); |
| 10 |
expect(isLethal(100, 50, damage("phantom", "head", 2000))).toBe(false); |
| 11 |
|
| 12 |
expect(isLethal(100, 0, damage("phantom", "head", 2000))).toBe(true); |
| 13 |
}); |
| 14 |
|
| 15 |
test("the Phantom falls off with range and the Vandal does not", () => { |
| 16 |
expect(damage("phantom", "body", 100)).toBe(39); |
| 17 |
expect(damage("phantom", "body", 1600)).toBe(31); |
| 18 |
expect(damage("vandal", "body", 100)).toBe(damage("vandal", "body", 2300)); |
| 19 |
}); |
| 20 |
|
| 21 |
test("armour is absorbed point for point but empties first", () => { |
| 22 |
const hit = applyDamage(100, 50, 40); |
| 23 |
expect(hit.armour).toBe(50 - 27); |
| 24 |
expect(hit.hp).toBe(87); |
| 25 |
|
| 26 |
let hp = 100; |
| 27 |
let armour = 50; |
| 28 |
let shots = 0; |
| 29 |
while (hp > 0) { |
| 30 |
({ hp, armour } = applyDamage(hp, armour, 40)); |
| 31 |
shots++; |
| 32 |
} |
| 33 |
expect(shots).toBe(4); |
| 34 |
}); |
| 35 |
|
| 36 |
test("body shots never kill in one, whatever the gun, except the Operator", () => { |
| 37 |
expect(isLethal(100, 0, damage("operator", "body", 500))).toBe(true); |
| 38 |
for (const id of ["classic", "ghost", "sheriff", "spectre", "phantom", "vandal"] as const) |
| 39 |
expect(isLethal(100, 0, damage(id, "body", 500))).toBe(false); |
| 40 |
}); |
| 41 |
|
| 42 |
test("where the ray passes decides the hit location", () => { |
| 43 |
expect(zoneFromMiss(0, 16)).toBe("head"); |
| 44 |
expect(zoneFromMiss(8, 16)).toBe("body"); |
| 45 |
expect(zoneFromMiss(15, 16)).toBe("legs"); |
| 46 |
}); |
| 47 |
|
| 48 |
test("running widens the cone and standing still does not", () => { |
| 49 |
expect(shotSpread("vandal", 0)).toBe(WEAPONS.vandal.spread); |
| 50 |
expect(shotSpread("vandal", 1)).toBeGreaterThan(shotSpread("vandal", 0)); |
| 51 |
|
| 52 |
expect(shotSpread("operator", 0)).toBeLessThan(shotSpread("spectre", 0)); |
| 53 |
}); |