=============================
time and weather system
=============================

the game simulates passing time, seasons, weather, and their effect on visibility. all together these create atmospheric descriptions in the look command and influence how far you can see.

game time
=========

time flows faster in the game world than in reality. by default, 1 real minute = 1 game hour, so a full game day passes in 24 real minutes.

the ``GameTime`` class converts real timestamps to game time using an epoch (when the game started) and a ratio. methods::

    get_game_hour() -> int       # 0-23
    get_game_time() -> tuple     # (hour, minute)
    get_game_day() -> int        # days since epoch, 0-based

``init_game_time()`` is called at server startup to establish the global game clock. all other systems query this clock to determine current conditions.

time of day
===========

game hours map to periods: dawn (5-6), day (7-17), dusk (18-19), night (20-4).

``get_sky_description(hour)`` picks variant descriptions for each period. the selection is deterministic using ``hour % len(variants)`` so the same hour always shows the same description within that day. examples::

    dawn:  "pale light seeps across the horizon"
    day:   "the sun hangs high overhead"
    dusk:  "the day's light begins to soften"
    night: "stars wheel slowly overhead"

there are 3-4 variants per period to add variety across different hours.

seasons
=======

the game year is 28 days long with 4 seasons of 7 days each: spring, summer, autumn, winter. seasons cycle infinitely.

``get_season(game_day)`` returns the current season name. ``get_season_description(season, terrain)`` returns descriptive text, but only for grass and forest terrain. other terrain types return empty strings. examples::

    spring + grass:  "fresh green grass springs up everywhere"
    winter + forest: "bare branches reach toward the sky"
    summer + forest: "a thick green canopy spreads overhead"

this is layered into the atmosphere line when looking at the world.

weather
=======

weather is a global simulation that evolves each game hour.

conditions
----------

``WeatherCondition`` enum: clear, cloudy, rain, storm, snow, fog.

``WeatherState`` tracks the current condition plus intensity (0.0-1.0). intensity affects descriptions::

    rain < 0.3:  "a light drizzle falls"
    rain 0.3-0.6: "rain patters steadily"
    rain >= 0.6: "rain hammers down relentlessly"

similar tiers exist for snow, fog, and storm.

climate profiles
----------------

``advance_weather()`` is probabilistic with three climate profiles:

- **temperate**: balanced transitions between all conditions
- **arid**: 90% chance clear stays clear, rare rain, no snow
- **arctic**: heavy emphasis on snow and fog

season filtering prevents snow in spring/summer.

global state
------------

``init_weather()`` sets up the initial condition. ``get_current_weather()`` returns the current state. ``tick_weather()`` is called each game hour to advance the simulation.

visibility
==========

weather and time of day affect how far you can see.

``get_visibility(hour, weather, base_width=21, base_height=11)`` calculates effective viewport dimensions by applying stacking penalties::

    night:           -6 width, -2 height
    dawn/dusk:       -2 width
    thick fog (>=0.7): -8 width, -4 height
    fog (0.4-0.7):   -4 width, -2 height
    storm:           -4 width, -2 height

minimum viewport is 7x5. effects stack: a stormy night with thick fog applies all three penalties.

integration
===========

the look command pulls current hour, day, weather, and season. it calculates effective viewport via ``get_visibility()`` and builds the atmosphere line with ``render_atmosphere()``.

example outputs::

    "the sun hangs high overhead. [day, summer]"

    "the day's light begins to soften. rain patters steadily. [day, autumn]"

    "stars wheel slowly overhead. snow drifts down softly. [night, winter]"

the atmosphere line appears at the top of the world view, followed by the terrain map clipped to effective visibility.

code
====

relevant files::

    src/mudlib/gametime.py
    src/mudlib/timeofday.py
    src/mudlib/seasons.py
    src/mudlib/weather.py
    src/mudlib/visibility.py
    src/mudlib/commands/look.py
