Tests: the lock fixtures carry munition parts; the migration and item-read tests read the stat the way the engine does
LockWarningTests builds launcher designs, which the new gate (ValidateMunitionParts) refuses without parts. The golden test selects the role's Quality term among the stat's heat and durability terms, and the item-read test settles the ship at the item's optimal temperature so only role quality moves the stat. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d24135a075
commit
a249f86cef
2 changed files with 28 additions and 13 deletions
|
|
@ -68,7 +68,7 @@ public sealed class LockWarningTests : IDisposable
|
|||
|
||||
private static PerformanceStat Const(float v) => new PerformanceStat { Min = v, Max = v };
|
||||
|
||||
private static GearData Launcher(string name, float lockSpeed, float sensorImpact, float lockAngle, float directionImpact) => new GearData
|
||||
private static GearData Launcher(string name, float lockSpeed, float sensorImpact, float lockAngle, float directionImpact) => WithMunitionParts(new GearData
|
||||
{
|
||||
Name = name, Hardpoint = HardpointType.Sensors, Shape = new Shape(), Durability = 1,
|
||||
MinimumTemperature = -1000, MaximumTemperature = 1000, OptimalTemperature = 0, PlateauWidth = 2000,
|
||||
|
|
@ -84,7 +84,14 @@ public sealed class LockWarningTests : IDisposable
|
|||
DirectionImpact = Const(directionImpact), Decay = Const(.1f)
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// A launcher design carries the five munition parts (StatValidation.ValidateMunitionParts); these fixtures are about the lock.
|
||||
private static GearData WithMunitionParts(GearData launcher)
|
||||
{
|
||||
launcher.Behaviors.AddRange(MunitionPartsTests.Parts(0));
|
||||
return launcher;
|
||||
}
|
||||
|
||||
private int _nextLot = 2;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,16 +30,18 @@ public sealed class MunitionPartsTests : IDisposable
|
|||
|
||||
private static PerformanceStat Flat(float value) => new PerformanceStat { Min = value, Max = value };
|
||||
|
||||
private static PerformanceStat Ranged(float min, float max, string role) => new PerformanceStat
|
||||
private static PerformanceStat Ranged(float min, float max, string role) => role == null ? Flat(max) : new PerformanceStat
|
||||
{
|
||||
Min = min, Max = max, Terms = new List<StatTerm> { new StatTerm { Source = StatSource.Quality, Exponent = 1.5f, Role = role } },
|
||||
};
|
||||
|
||||
// Every field set to a distinct value, so a field read from the wrong slot or dropped on the way is seen.
|
||||
private static List<BehaviorData> Parts(int group) => new List<BehaviorData>
|
||||
// The five parts a munition design carries, every field set to a distinct value so a field read from the wrong slot or
|
||||
// dropped on the way is seen. The thruster's stats vary with the given role's quality when one is named; the design
|
||||
// that carries them declares it. Fixtures that only need a valid munition pass none.
|
||||
internal static List<BehaviorData> Parts(int group, string role = null) => new List<BehaviorData>
|
||||
{
|
||||
new MunitionHullData { Group = group, Durability = Flat(21), Radius = Flat(4.5f) },
|
||||
new MunitionThrusterData { Group = group, Acceleration = Ranged(300, 400, "motor"), Lateral = Ranged(150, 200, "motor"), MaxSpeed = Ranged(250, 350, "motor"), Visibility = Flat(11) },
|
||||
new MunitionThrusterData { Group = group, Acceleration = Ranged(300, 400, role), Lateral = Ranged(150, 200, role), MaxSpeed = Ranged(250, 350, role), Visibility = Flat(11) },
|
||||
new MunitionSeekerData { Group = group, Sensitivity = Flat(.8f), BeamWidth = Flat(55), Range = Flat(900) },
|
||||
new MunitionControlData { Group = group, Navigation = Flat(3.5f), Evasion = Flat(.4f), EvasionFrequency = Flat(.6f), Lifetime = Flat(12), Cognition = Flat(.35f) },
|
||||
new MunitionFuelData { Group = group, DeltaV = Flat(700) },
|
||||
|
|
@ -57,7 +59,7 @@ public sealed class MunitionPartsTests : IDisposable
|
|||
launcher.Group = group;
|
||||
var design = new WeaponItemData { Name = name, Roles = new List<ItemRole> { new ItemRole { Name = "motor" } } };
|
||||
design.Behaviors.Add(launcher);
|
||||
design.Behaviors.AddRange(Parts(group));
|
||||
design.Behaviors.AddRange(Parts(group, "motor"));
|
||||
return design;
|
||||
}
|
||||
|
||||
|
|
@ -102,12 +104,10 @@ public sealed class MunitionPartsTests : IDisposable
|
|||
Assert.Equal((thrustMin, thrustMax), (thruster.Acceleration.Min, thruster.Acceleration.Max));
|
||||
Assert.Equal((thrustMin / 2f, thrustMax / 2f), (thruster.Lateral.Min, thruster.Lateral.Max));
|
||||
Assert.Equal((speedMin, speedMax), (thruster.MaxSpeed.Min, thruster.MaxSpeed.Max));
|
||||
// The terms come across whole: the role's Quality term and whatever heat or durability terms the stat carried.
|
||||
Assert.Equal(Describe(thruster.Acceleration).Split('[')[1], Describe(thruster.Lateral).Split('[')[1]);
|
||||
foreach (var stat in new[] { thruster.Acceleration, thruster.Lateral, thruster.MaxSpeed })
|
||||
{
|
||||
var term = Assert.Single(stat.Terms);
|
||||
Assert.Equal((StatSource.Quality, "thruster"), (term.Source, term.Role));
|
||||
}
|
||||
Assert.Equal(thruster.Acceleration.Terms.Single().Exponent, thruster.Lateral.Terms.Single().Exponent);
|
||||
Assert.Equal("thruster", Assert.Single(stat.Terms, t => t.Source == StatSource.Quality).Role);
|
||||
|
||||
var evasion = Part<MunitionControlData>(design).EvasionFrequency;
|
||||
Assert.Equal((dodge, dodge), (evasion.Min, evasion.Max));
|
||||
|
|
@ -183,7 +183,15 @@ public sealed class MunitionPartsTests : IDisposable
|
|||
var zone = new Zone(items, new PlanetSettings(), new ZonePack(), new GalaxyZone { Name = "Test", Owner = null }, null);
|
||||
ship = new Ship(items, zone, new EquippableItem { Data = cache.RefOf<ItemData>(hull), Durability = hull.Durability, Lot = 1 }, settings.DefaultEntitySettings);
|
||||
Assert.True(ship.TryEquip(new EquippableItem { Data = cache.RefOf<ItemData>(gt), Durability = gt.Durability, Lot = 2 }, hardpoint.Position));
|
||||
return ship.Equipment.Single(e => e.Data.Name == "GT 3K");
|
||||
zone.Entities.Add(ship);
|
||||
ship.Activate();
|
||||
// Settle at the item's optimal temperature, as ConditionRatioTests does, so heat and wear read their identity and only
|
||||
// the role's quality moves a stat.
|
||||
var item = ship.Equipment.Single(e => e.Data.Name == "GT 3K");
|
||||
foreach (var cell in item.InsetShape.Coordinates) ship.Temperature[cell.x, cell.y] = gt.OptimalTemperature;
|
||||
item.UpdatePerformance();
|
||||
item.UpdatePerformance();
|
||||
return item;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
Loading…
Reference in a new issue