Add season system with tests

This commit is contained in:
Jared Miller 2026-02-14 15:51:17 -05:00
parent 4b0a7315c1
commit 15d141b53e
Signed by: shmup
GPG key ID: 22B5C6D66A38B06C
2 changed files with 155 additions and 0 deletions

68
src/mudlib/seasons.py Normal file
View file

@ -0,0 +1,68 @@
"""Season system derived from game day count."""
from __future__ import annotations
SEASONS: list[str] = ["spring", "summer", "autumn", "winter"]
DAYS_PER_SEASON: int = 7 # 28-day year
def get_season(game_day: int, days_per_season: int = DAYS_PER_SEASON) -> str:
"""Return the current season based on game day count.
Args:
game_day: Current game day (0-based)
days_per_season: Number of days per season (default 7)
Returns:
Current season: "spring", "summer", "autumn", or "winter"
"""
if game_day < 0:
game_day = 0
days_per_year = days_per_season * 4
day_of_year = game_day % days_per_year
season_index = day_of_year // days_per_season
return SEASONS[season_index]
def get_day_of_year(game_day: int, days_per_season: int = DAYS_PER_SEASON) -> int:
"""Return the day within the current year (0 to days_per_season*4 - 1).
Args:
game_day: Current game day (0-based)
days_per_season: Number of days per season (default 7)
Returns:
Day of year (0-based)
"""
if game_day < 0:
game_day = 0
days_per_year = days_per_season * 4
return game_day % days_per_year
def get_season_description(season: str, terrain: str) -> str:
"""Return a seasonal description variant for a terrain type.
Args:
season: Current season
terrain: Terrain type
Returns:
Seasonal description for this terrain, or empty string if no variation
"""
# Only grass and forest have seasonal variation
descriptions = {
("spring", "grass"): "fresh green grass springs up everywhere",
("summer", "grass"): "golden grass waves in the breeze",
("autumn", "grass"): "the grass turns brown and brittle",
("winter", "grass"): "frost clings to brittle brown grass",
("spring", "forest"): "the trees burst with pale blossoms",
("summer", "forest"): "a thick green canopy spreads overhead",
("autumn", "forest"): "the trees blaze with amber and crimson",
("winter", "forest"): "bare branches reach toward the sky",
}
return descriptions.get((season, terrain), "")

87
tests/test_seasons.py Normal file
View file

@ -0,0 +1,87 @@
"""Tests for the season system."""
from mudlib import seasons
def test_get_season_basic():
assert seasons.get_season(0) == "spring"
assert seasons.get_season(6) == "spring"
assert seasons.get_season(7) == "summer"
assert seasons.get_season(13) == "summer"
assert seasons.get_season(14) == "autumn"
assert seasons.get_season(20) == "autumn"
assert seasons.get_season(21) == "winter"
assert seasons.get_season(27) == "winter"
def test_get_season_wraps():
assert seasons.get_season(28) == "spring"
assert seasons.get_season(35) == "summer"
assert seasons.get_season(56) == "spring" # 2 years = 56 days
def test_get_season_negative_day():
assert seasons.get_season(-1) == "spring"
assert seasons.get_season(-100) == "spring"
def test_get_season_custom_days_per_season():
# 10 days per season = 40-day year
assert seasons.get_season(0, days_per_season=10) == "spring"
assert seasons.get_season(9, days_per_season=10) == "spring"
assert seasons.get_season(10, days_per_season=10) == "summer"
assert seasons.get_season(19, days_per_season=10) == "summer"
assert seasons.get_season(20, days_per_season=10) == "autumn"
assert seasons.get_season(30, days_per_season=10) == "winter"
assert seasons.get_season(40, days_per_season=10) == "spring"
def test_get_day_of_year():
assert seasons.get_day_of_year(0) == 0
assert seasons.get_day_of_year(27) == 27
assert seasons.get_day_of_year(28) == 0 # new year
assert seasons.get_day_of_year(29) == 1
assert seasons.get_day_of_year(56) == 0 # 2 years
def test_get_day_of_year_custom_days_per_season():
# 10 days per season = 40-day year
assert seasons.get_day_of_year(0, days_per_season=10) == 0
assert seasons.get_day_of_year(39, days_per_season=10) == 39
assert seasons.get_day_of_year(40, days_per_season=10) == 0
assert seasons.get_day_of_year(80, days_per_season=10) == 0
def test_get_season_description_grass():
assert "green" in seasons.get_season_description("spring", "grass")
assert "golden" in seasons.get_season_description("summer", "grass")
assert "brown" in seasons.get_season_description("autumn", "grass")
assert "frost" in seasons.get_season_description("winter", "grass")
def test_get_season_description_forest():
assert "blossom" in seasons.get_season_description("spring", "forest")
assert "canopy" in seasons.get_season_description("summer", "forest")
assert "amber" in seasons.get_season_description("autumn", "forest")
assert "bare" in seasons.get_season_description("winter", "forest")
def test_get_season_description_minimal_variation():
# sand, mountain, water have minimal/no seasonal variation
assert seasons.get_season_description("spring", "sand") == ""
assert seasons.get_season_description("summer", "mountain") == ""
assert seasons.get_season_description("winter", "water") == ""
def test_get_season_description_unknown_terrain():
# unknown terrain returns empty string
assert seasons.get_season_description("spring", "lava") == ""
assert seasons.get_season_description("summer", "unknown") == ""
def test_seasons_constant():
assert seasons.SEASONS == ["spring", "summer", "autumn", "winter"]
def test_days_per_season_constant():
assert seasons.DAYS_PER_SEASON == 7