From d91b180824f53e566d959654b648b300b95f0f67 Mon Sep 17 00:00:00 2001 From: Jared Miller Date: Sat, 14 Feb 2026 15:54:21 -0500 Subject: [PATCH] Add game day tracking to game time system --- src/mudlib/gametime.py | 25 +++++++++++++ tests/test_gametime.py | 81 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 tests/test_gametime.py diff --git a/src/mudlib/gametime.py b/src/mudlib/gametime.py index 7059ce6..ea8144e 100644 --- a/src/mudlib/gametime.py +++ b/src/mudlib/gametime.py @@ -42,6 +42,17 @@ class GameTime: return hour, minute + def get_game_day(self) -> int: + """Get current game day (0-based). + + Returns: + Current game day since epoch + """ + elapsed_real_seconds = time.time() - self.epoch + elapsed_real_minutes = elapsed_real_seconds / 60 + elapsed_game_hours = elapsed_real_minutes / self.real_minutes_per_game_hour + return int(elapsed_game_hours) // 24 + # Global game time instance (initialized at server startup) _game_time: GameTime | None = None @@ -88,3 +99,17 @@ def get_game_time() -> tuple[int, int]: if _game_time is None: raise RuntimeError("Game time not initialized. Call init_game_time() first.") return _game_time.get_game_time() + + +def get_game_day() -> int: + """Get current game day from global instance. + + Returns: + Current game day (0-based) + + Raises: + RuntimeError: If game time not initialized + """ + if _game_time is None: + raise RuntimeError("Game time not initialized. Call init_game_time() first.") + return _game_time.get_game_day() diff --git a/tests/test_gametime.py b/tests/test_gametime.py new file mode 100644 index 0000000..916c01b --- /dev/null +++ b/tests/test_gametime.py @@ -0,0 +1,81 @@ +"""Tests for the game time system.""" + +import time + +import pytest + +from mudlib.gametime import GameTime, get_game_day, get_game_hour, init_game_time + + +def test_get_game_hour_at_epoch(): + """Game hour should be 0 at epoch.""" + epoch = time.time() + gt = GameTime(epoch, real_minutes_per_game_hour=1.0) + assert gt.get_game_hour() == 0 + + +def test_get_game_hour_after_one_hour(): + """Game hour should advance after one real minute.""" + epoch = time.time() - 60 # one real minute ago + gt = GameTime(epoch, real_minutes_per_game_hour=1.0) + assert gt.get_game_hour() == 1 + + +def test_get_game_hour_wraps_at_24(): + """Game hour should wrap from 23 back to 0.""" + epoch = time.time() - (24 * 60) # 24 real minutes ago + gt = GameTime(epoch, real_minutes_per_game_hour=1.0) + assert gt.get_game_hour() == 0 + + +def test_get_game_day_at_epoch(): + """Game day should be 0 at epoch.""" + epoch = time.time() + gt = GameTime(epoch, real_minutes_per_game_hour=1.0) + assert gt.get_game_day() == 0 + + +def test_get_game_day_after_24_hours(): + """Game day should be 1 after 24 game hours.""" + epoch = time.time() - (24 * 60) # 24 real minutes ago = 24 game hours + gt = GameTime(epoch, real_minutes_per_game_hour=1.0) + assert gt.get_game_day() == 1 + + +def test_get_game_day_after_48_hours(): + """Game day should be 2 after 48 game hours.""" + epoch = time.time() - (48 * 60) # 48 real minutes ago + gt = GameTime(epoch, real_minutes_per_game_hour=1.0) + assert gt.get_game_day() == 2 + + +def test_get_game_day_partial_day(): + """Game day should not increment until 24 hours have passed.""" + epoch = time.time() - (12 * 60) # 12 real minutes ago = 12 game hours + gt = GameTime(epoch, real_minutes_per_game_hour=1.0) + assert gt.get_game_day() == 0 + + +def test_global_get_game_hour(): + """Global get_game_hour should work after init.""" + init_game_time(epoch=time.time(), real_minutes_per_game_hour=1.0) + hour = get_game_hour() + assert 0 <= hour <= 23 + + +def test_global_get_game_day(): + """Global get_game_day should work after init.""" + init_game_time(epoch=time.time(), real_minutes_per_game_hour=1.0) + day = get_game_day() + assert day >= 0 + + +def test_global_get_game_day_raises_if_not_initialized(): + """Global get_game_day should raise if not initialized.""" + import mudlib.gametime + + # reset global state + mudlib.gametime._game_time = None + + with pytest.raises(RuntimeError, match="Game time not initialized"): + get_game_day()