Exact source used by this build. SHA-256: 4d1d452253f221967b69ba18a14ef9b90795c4c2874895f81123bb80b541d5c9.
1 import type { Season, SimRules, Weather } from "../../types";
2 import { createRng } from "../../rng";
3 import { defineSystem } from "../registry";
4 /** Odds are content; a fixed type order makes serialized seeds reproducible. */
5 export function rollWeather(seed: number, season: Season, odds: NonNullable<SimRules["weatherOdds"]>): { weather: Weather; rngState: number } {
6 const weatherTypes: readonly Weather[] = ["sunny", "rain", "storm", "wind", "snow"];
7 const weights = odds[season];
8 const total = weatherTypes.reduce((sum, type) => sum + Math.max(0, weights[type]), 0);
9 if (!Number.isFinite(total) || total <= 0) throw new Error("Weather odds must have positive finite total weight");
10 const rng = createRng(seed);
11 let at = rng.next() * total;
12 for (const weather of weatherTypes) { at -= Math.max(0, weights[weather]); if (at < 0) return { weather, rngState: rng.state }; }
13 return { weather: "sunny", rngState: rng.state };
14 }
15 export function isRainy(weather: Weather): boolean { return weather === "rain" || weather === "storm"; }
16 export const weatherSystem = defineSystem({
17 id: "weather", worldDefaults: () => ({}), playerDefaults: () => ({}), intents: [], events: ["weatherChanged"],
18 initializeWorld: () => ({ weather: "sunny" }),
19 onOvernight: ({ state, rules, weatherOverride }) => {
20 if (!rules.weatherOdds) return { state, events: [] };
21 const rolled = rollWeather(state.rngState, state.clock.season, rules.weatherOdds);
22 const roll = { ...rolled, weather: weatherOverride ?? rolled.weather };
23 const areas = isRainy(roll.weather) ? Object.fromEntries(Object.entries(state.areas).map(([id, area]) => [id, area.outdoor ? { ...area, tiles: area.tiles.map((tile) => tile.tilled ? { ...tile, watered: true } : tile) } : area])) : state.areas;
24 return { state: { ...state, ...roll, areas, revision: state.revision + 1 }, events: [{ type: "weatherChanged", data: { weather: roll.weather } }] };
25 },
26 });
27