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:
Christopher Wiebe
2026-04-30 20:40:51 -07:00
commit b451f83174
525 changed files with 75786 additions and 0 deletions
+48
View File
@@ -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;
}