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,53 @@
|
||||
using Theriapolis.Core.World.Generation;
|
||||
|
||||
namespace Theriapolis.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Class-level fixture that memoizes worldgen pipeline runs so multiple tests
|
||||
/// in the same class (all hitting e.g. seed 0xCAFEBABE) share one expensive run.
|
||||
///
|
||||
/// Each test class gets its own WorldCache via <see cref="Xunit.IClassFixture{T}"/>,
|
||||
/// which keeps cross-class parallelism intact while collapsing within-class duplicate
|
||||
/// runs. A full pipeline takes ~30s; a test class that previously did 9 runs now does 1.
|
||||
///
|
||||
/// Cache key is (seed, stageThroughIndex, variant):
|
||||
/// - stageThroughIndex = -1 means RunAll; otherwise RunThrough(ctx, idx).
|
||||
/// - variant is used by determinism tests that intentionally want TWO independent
|
||||
/// runs of the same seed to compare: pass variant 0 and variant 1.
|
||||
/// </summary>
|
||||
public sealed class WorldCache : IDisposable
|
||||
{
|
||||
private readonly Dictionary<(ulong Seed, int Stage, int Variant), WorldGenContext> _cache = new();
|
||||
private readonly object _lock = new();
|
||||
|
||||
/// <summary>Full pipeline run for <paramref name="seed"/>, memoized.</summary>
|
||||
public WorldGenContext Get(ulong seed, int variant = 0) =>
|
||||
GetInternal(seed, stageThroughIndex: -1, variant);
|
||||
|
||||
/// <summary>
|
||||
/// Partial pipeline run through stage index (0-based), memoized.
|
||||
/// E.g. <c>GetThrough(seed, 9)</c> runs stages 1–10 (HydrologyGen).
|
||||
/// </summary>
|
||||
public WorldGenContext GetThrough(ulong seed, int stageThroughIndex, int variant = 0) =>
|
||||
GetInternal(seed, stageThroughIndex, variant);
|
||||
|
||||
private WorldGenContext GetInternal(ulong seed, int stageThroughIndex, int variant)
|
||||
{
|
||||
var key = (seed, stageThroughIndex, variant);
|
||||
lock (_lock)
|
||||
{
|
||||
if (_cache.TryGetValue(key, out var cached)) return cached;
|
||||
|
||||
var ctx = new WorldGenContext(seed, TestHelpers.DataDirectory);
|
||||
if (stageThroughIndex < 0)
|
||||
WorldGenerator.RunAll(ctx);
|
||||
else
|
||||
WorldGenerator.RunThrough(ctx, stageThroughIndex);
|
||||
|
||||
_cache[key] = ctx;
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() => _cache.Clear();
|
||||
}
|
||||
Reference in New Issue
Block a user