fuzzyworld

nordic-skating / mistral-medium-35-littlejs / files / src / settings.ts

Branch mistral-medium-35-littlejs · default branch · all branches

settings.ts

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

a8fd3f13 2026-10-10 Pavel Safronov1import { TIME_NAMES, type TimeName } from './render/sky.js'
1ee103b4 2026-10-11 Pavel Safronov2import { PACE_NAMES, type Pace } from './skater.js'
a8fd3f13 2026-10-10 Pavel Safronov3import { mulberry32 } from './world/lake.js'
4
236f7d03 2026-10-10 Pavel Safronov5/** The weathers a lake can have. */
6export const WEATHERS = ['clear', 'snow', 'blizzard'] as const
7export type Weather = (typeof WEATHERS)[number]
8
9/**
10 * What a weather is: how much snow is falling, from 0 to 1; how far the eye can see
11 * through it, metres; how much of the sky is cloud; and how hard the wind blows, m/s,
12 * at its lulls and in its gusts.
13 */
14export const WEATHER: Record<Weather, { snow: number; sight: number; overcast: number; wind: readonly [number, number] }> = {
15 clear: { snow: 0, sight: 600, overcast: 0, wind: [0, 0] },
16 snow: { snow: 0.35, sight: 420, overcast: 0.7, wind: [0.5, 3] },
17 blizzard: { snow: 1, sight: 200, overcast: 0.95, wind: [7, 16] },
18}
19
a8fd3f13 2026-10-10 Pavel Safronov20/** What the skater has chosen in the settings box, kept from one visit to the next. */
21export interface Settings {
22 /** A time of day, or `surprise` for whichever the lake comes with. */
23 time: TimeName | 'surprise'
236f7d03 2026-10-10 Pavel Safronov24 /** The weather, or `surprise` for whichever the lake comes with. */
25 weather: Weather | 'surprise'
1ee103b4 2026-10-11 Pavel Safronov26 /** The pace the skater keeps (skater.ts). */
27 pace: Pace
a8fd3f13 2026-10-10 Pavel Safronov28 /** Whether the lake has ice thinner than any ice could be (world/lake.ts). */
29 impossibleIce: boolean
8876a48d 2026-10-10 Pavel Safronov30 /** Whether tilting the phone steers (input.ts). */
31 tilt: boolean
a8fd3f13 2026-10-10 Pavel Safronov32}
33
1ee103b4 2026-10-11 Pavel Safronov34const DEFAULTS: Settings = { time: 'surprise', weather: 'surprise', pace: 'cruise', impossibleIce: false, tilt: false }
a8fd3f13 2026-10-10 Pavel Safronov35const KEY = 'settings'
36
37export function loadSettings(): Settings {
38 try {
39 const kept = JSON.parse(localStorage.getItem(KEY) ?? '{}') as Partial<Settings>
40 return {
41 time: kept.time === 'surprise' || TIME_NAMES.includes(kept.time as TimeName) ? kept.time! : DEFAULTS.time,
236f7d03 2026-10-10 Pavel Safronov42 weather: kept.weather === 'surprise' || WEATHERS.includes(kept.weather as Weather) ? kept.weather! : DEFAULTS.weather,
1ee103b4 2026-10-11 Pavel Safronov43 pace: PACE_NAMES.includes(kept.pace as Pace) ? kept.pace! : DEFAULTS.pace,
a8fd3f13 2026-10-10 Pavel Safronov44 impossibleIce: kept.impossibleIce === true,
8876a48d 2026-10-10 Pavel Safronov45 tilt: kept.tilt === true,
a8fd3f13 2026-10-10 Pavel Safronov46 }
47 } catch {
48 // No storage, or nonsense in it: the settings last for this visit only.
49 return { ...DEFAULTS }
50 }
51}
52
53export function saveSettings(settings: Settings): void {
54 try {
55 localStorage.setItem(KEY, JSON.stringify(settings))
56 } catch {
57 // As above.
58 }
59}
60
61/** A lake to skate that nobody has asked for by number: one of a million. */
62export function anyLake(): number {
63 return 1 + Math.floor(Math.random() * 999_999)
64}
65
66/**
67 * The time of day lake number `seed` comes with. Part of the lake, so that a link to a
68 * lake is a link to the same water under the same sky. Day is the likeliest, and the
69 * aurora, as it should be, the least.
70 */
71export function timeOf(seed: number): TimeName {
72 const r = mulberry32(seed ^ 0x5bd1e995)()
73 return r < 0.35 ? 'day' : r < 0.55 ? 'dusk' : r < 0.82 ? 'night' : 'aurora'
74}
236f7d03 2026-10-10 Pavel Safronov75
76/**
77 * The weather lake number `seed` comes with. Most days are clear; snow falls on a
78 * quarter of them, and a blizzard blows on one in ten.
79 */
80export function weatherOf(seed: number): Weather {
81 const r = mulberry32(seed ^ 0x3c6ef372)()
82 return r < 0.64 ? 'clear' : r < 0.9 ? 'snow' : 'blizzard'
83}
84
85/** Which way the wind blows over lake number `seed`, radians: 0 is down the lake, a quarter turn is across it to the right. */
86export function windOf(seed: number): number {
87 return mulberry32(seed ^ 0x1b873593)() * Math.PI * 2
88}