Initial commit: Theriapolis baseline at port/godot branch point
Captures the pre-Godot-port state of the codebase. This is the rollback anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md). All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
namespace Theriapolis.Core.Time;
|
||||
|
||||
public enum Season : byte { Spring, Summer, Autumn, Winter }
|
||||
|
||||
/// <summary>
|
||||
/// Single in-game time counter. Measured in whole seconds so it serializes
|
||||
/// trivially and stays deterministic — no floating-point drift over a long
|
||||
/// playthrough.
|
||||
///
|
||||
/// Phase 4 callers advance the clock from world-map travel and tactical
|
||||
/// stepping. Phase 8 weather/seasons reads from it.
|
||||
/// </summary>
|
||||
public sealed class WorldClock
|
||||
{
|
||||
/// <summary>In-game seconds since world creation. Game time, not real time.</summary>
|
||||
public long InGameSeconds { get; private set; }
|
||||
|
||||
// Calendar constants. A 96-day year (24 days × 4 seasons) keeps the math
|
||||
// tight; a real-world year would mean each season is a 90-hour playthrough.
|
||||
public const int SecondsPerMinute = 60;
|
||||
public const int SecondsPerHour = 3600;
|
||||
public const int SecondsPerDay = SecondsPerHour * 24;
|
||||
public const int DaysPerSeason = 24;
|
||||
public const int DaysPerYear = DaysPerSeason * 4;
|
||||
|
||||
public int Day => (int)(InGameSeconds / SecondsPerDay);
|
||||
public int Hour => (int)((InGameSeconds % SecondsPerDay) / SecondsPerHour);
|
||||
public int Minute => (int)((InGameSeconds % SecondsPerHour) / SecondsPerMinute);
|
||||
public int Year => Day / DaysPerYear;
|
||||
public Season Season => (Season)((Day / DaysPerSeason) % 4);
|
||||
|
||||
public void Advance(long seconds)
|
||||
{
|
||||
if (seconds < 0) throw new ArgumentOutOfRangeException(nameof(seconds));
|
||||
InGameSeconds += seconds;
|
||||
}
|
||||
|
||||
public WorldClockState CaptureState() => new() { InGameSeconds = InGameSeconds };
|
||||
public void RestoreState(WorldClockState s) => InGameSeconds = s.InGameSeconds;
|
||||
|
||||
/// <summary>Pretty-print like "Y0 Spring D5 14:23".</summary>
|
||||
public string Format() => $"Y{Year} {Season} D{Day % DaysPerSeason} {Hour:D2}:{Minute:D2}";
|
||||
}
|
||||
|
||||
public sealed class WorldClockState
|
||||
{
|
||||
public long InGameSeconds;
|
||||
}
|
||||
Reference in New Issue
Block a user