forecast
The thirty-day forecast of First Light, as a pure function of the world's forecast seed (`Rules.state.run.seed`). The same seed gives the same thirty days on every load, so a journal line about the weather is true for the next run.
firstlight.forecast
The thirty-day forecast of First Light, as a pure function of the world's
forecast seed (Rules.state.run.seed). The same seed gives the same thirty
days on every load, so a journal line about the weather is true for the next
run.
local Forecast = require("firstlight.forecast")
For the HUD and the journal
-- Tomorrow's barometer reading
local clock = Rules.state.clock
local tomorrow = Forecast.forDay(clock.day + 1)
-- tomorrow.storm 0..1 on the storm scale
-- tomorrow.windMs m/s
-- tomorrow.airC °C at noon, before wind chill
-- tomorrow.aurora 0..1
-- tomorrow.band "calm" | "wind" | "storm" | "blizzard"
-- tomorrow.blizzard true on one of the trapped days
Forecast.words(tomorrow.band) -- "Calm" | "Wind" | "Storm" | "Blizzard"
Days clamp to 1..30, so forDay(31) is day 30. Forecast.blizzardStart()
names the first trapped day; the blizzard runs Rules.BLIZZARD_DAYS days from
there, between Rules.BLIZZARD_EARLIEST_DAY and Rules.BLIZZARD_LATEST_DAY.
The live weather
What the air is doing right now is on the blackboard, written every frame by
the weather component: Rules.state.weather carries storm, windMs,
windDir, visibilityM, airC, chillC, snowing and aurora. Read it
from there rather than recomputing it.
Forecast.at(day, t) is the function behind that: neighbouring days blended
across the day, gusts added from a seed-fixed phase, and the whole moment
derived. Forecast.moment(storm, day, t) derives the same record from one
storm value.
The scale
| band | storm | wind | visibility |
|---|---|---|---|
| calm | below 0.175 | a breath | the horizon |
| wind | 0.175 .. 0.525 | 6 .. 12 m/s | hundreds of metres |
| storm | 0.525 .. 0.85 | 12 .. 22 m/s | tens of metres |
| blizzard | 0.85 and up | up to Rules.WIND_MAX_MS | a few paces |
Forecast.band(storm), Forecast.windMs(storm), Forecast.visibilityM(storm)
and Forecast.snowing(storm) are the curves behind the table.
The wind on the plain always blows toward Forecast.WIND_TOWARD (east-north-east
in xz), the way the snowfield's sastrugi and spindrift stream; Forecast.WIND_DIR
is that as radians.
Scoped to this part · feeds back into the world's score.