fuzzyworld

tower / files / test / instruments.test.ts

instruments.test.ts

Blame: the commit that last changed each line · file · history

e5555695 2026-09-07 Pavel Safronov1/**
2 * The sightline probe reproduces the table in design.md §1.8 — the two-horizons
3 * result, which is canon and came out of this calculation in the first place.
4 */
5import { describe, expect, it } from 'vitest'
6import { LENGTH_M, RADIUS_M } from '../src/canon/constants.js'
7import { sightline, travel } from '../src/world/instruments.js'
8import { landStripCentre } from '../src/canon/geometry.js'
9import { setSlatCount } from '../src/canon/slats.js'
10import { SLAT_COUNT_DEFAULT } from '../src/canon/constants.js'
11
12const along = (m: number) => sightline({ theta: 0, z: 0 }, { theta: 0, z: m })
13/** A point `deg` around the cylinder at the same z — a sightline across the interior. */
14const across = (deg: number) =>
15 sightline({ theta: 0, z: 0 }, { theta: (deg * Math.PI) / 180, z: 0 })
16
17describe('§1.8 looking along the axis', () => {
18 it('is 31% clear at 100 km', () => expect(along(100_000).transmission).toBeCloseTo(0.31, 2))
19 it('leaves the far cap a 4% ghost from the midpoint', () => {
20 const s = along(LENGTH_M / 2)
21 expect(s.transmission).toBeCloseTo(0.044, 3)
22 expect(s.clarity).toBe('ghost')
23 })
24 it('closes the horizon between 100 and 150 km', () => {
25 expect(along(100_000).clarity).toBe('hazy')
26 expect(along(150_000).clarity).toBe('ghost')
27 })
28 it('never rises off the floor — the axial floor is flat', () =>
29 expect(along(100_000).apexHeightM).toBeCloseTo(0, 6))
30})
31
32describe('§1.8 looking across the interior', () => {
33 it('is 78% clear to the point directly overhead, 100 km away', () => {
34 const s = across(180)
35 expect(s.directDistanceM).toBeCloseTo(2 * RADIUS_M, 6)
36 expect(s.transmission).toBeCloseTo(0.78, 2)
37 expect(s.clarity).toBe('crisp')
38 })
39 it('stays crisp all the way round', () => {
40 for (const d of [30, 60, 90, 135, 180]) expect(across(d).clarity).toBe('crisp')
41 })
42 it('rises to 14.6 km at 90° — why looking up beats looking along', () =>
43 expect(across(90).apexHeightM / 1000).toBeCloseTo(14.6, 1))
44})
45
46describe('§1.8 the headline: overhead beats ground at the same distance', () => {
47 it('is more than twice as clear across the interior at 100 km', () => {
48 const axial = along(100_000)
49 const overhead = across(180)
50 expect(overhead.directDistanceM).toBeCloseTo(axial.directDistanceM, 0)
51 expect(overhead.transmission).toBeGreaterThan(axial.transmission * 2)
52 })
53 it('gets clearer with distance across, the opposite of along', () => {
54 expect(across(180).transmission).toBeGreaterThan(across(60).transmission)
55 expect(along(150_000).transmission).toBeLessThan(along(50_000).transmission)
56 })
57})
58
59describe('travel', () => {
60 it('reports no slat crossing with the hull sealed (D-017)', () => {
61 const t = travel({ theta: 0, z: 0 }, { theta: Math.PI, z: 0 }, 1.4)
62 expect(t.crossesSlat).toBe(false)
63 })
64
65 it('times a walk and notices slat crossings when slats exist', () => {
66 setSlatCount(8)
67 const t = travel(
68 { theta: landStripCentre(0), z: 0 },
69 { theta: landStripCentre(1), z: 0 },
70 1.4,
71 )
72 expect(t.crossesSlat).toBe(true)
73 expect(t.durationS).toBeCloseTo(t.distanceM / 1.4, 6)
74 setSlatCount(SLAT_COUNT_DEFAULT)
75 })
76})