feat(progression): remaining slice 1 value objects
Lives (floors at zero, exhaustion observable), LevelId, SkillId, PlaythroughId (never self-generates, keeps tests deterministic), StatName enum, LevelTime rejects NaN/infinity. 14 tests. Arithmetic/comparison members deferred to the slices whose behaviour needs them rather than added speculatively.
This commit is contained in:
24
progression/Lives.cs
Normal file
24
progression/Lives.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace Mr.BrickAdventures.Progression;
|
||||
|
||||
/// <summary>
|
||||
/// Lives remaining in a Playthrough. Never negative.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Decrementing at zero floors rather than failing — unlike <see cref="Coins"/>, where a shortfall
|
||||
/// is a game rule the caller must handle. Flooring here is purely defensive; the invariant that one
|
||||
/// death costs exactly one life is enforced by the Attempt's outcome, not by this type.
|
||||
/// </remarks>
|
||||
public readonly struct Lives
|
||||
{
|
||||
public int Value { get; }
|
||||
|
||||
private Lives(int value) => Value = value;
|
||||
|
||||
public static Lives Of(int value) => value < 0
|
||||
? throw new ArgumentOutOfRangeException(nameof(value), value, "Lives cannot be negative.")
|
||||
: new Lives(value);
|
||||
|
||||
public bool IsExhausted => Value == 0;
|
||||
|
||||
public Lives Decrement() => new(Value == 0 ? 0 : Value - 1);
|
||||
}
|
||||
Reference in New Issue
Block a user