1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
using System.Globalization;
namespace Godosa.Core.Runs;
/// <summary>Shared run flags: <c>--deterministic [seed]</c> (fixed step, seeded streams), <c>--digest [every=N]</c>
/// (state hash lines), <c>--headless</c> (no window; implies deterministic). <see cref="Seed"/> null = the game's default.</summary>
public sealed record RunFlags(bool Deterministic = false, ulong? Seed = null, bool Digest = false, int DigestEvery = 0, bool Headless = false)
{
public ulong SeedOr(ulong fallback) => Seed ?? fallback;
/// <summary>Consumes the run flag at <paramref name="i"/> (and its optional value, advancing <paramref name="i"/>);
/// false when <c>args[i]</c> is no run flag.</summary>
public static bool TryTake(IReadOnlyList<string> args, ref int i, ref RunFlags flags)
{
string? next = i + 1 < args.Count ? args[i + 1] : null;
switch (args[i])
{
case "--deterministic":
flags = flags with { Deterministic = true };
if (next != null && ulong.TryParse(next, NumberStyles.None, CultureInfo.InvariantCulture, out var seed))
(flags, i) = (flags with { Seed = seed }, i + 1);
return true;
case "--digest":
flags = flags with { Digest = true };
if (next != null && next.StartsWith("every=", StringComparison.Ordinal))
{
if (!int.TryParse(next.AsSpan(6), NumberStyles.None, CultureInfo.InvariantCulture, out var every) || every < 1)
throw new ArgumentException($"--digest {next}: every=N needs N ≥ 1");
(flags, i) = (flags with { DigestEvery = every }, i + 1);
}
return true;
case "--headless":
flags = flags with { Headless = true, Deterministic = true };
return true;
default:
return false;
}
}
}
|