using MrGameEng.AI; using Xunit; namespace MrGameEng.AI.Tests; public class ResponseCurveTests { [Fact] public void Identity_ReturnsInputUnchanged() { var curve = ResponseCurve.Identity; Assert.Equal(0f, curve.Evaluate(0f)); Assert.Equal(0.5f, curve.Evaluate(0.5f), 5); Assert.Equal(1f, curve.Evaluate(1f)); } [Fact] public void Default_HasZeroSlope_SoIdentityMustBeUsedExplicitly() { // Guards the gotcha that default(ResponseCurve) is NOT the identity curve. var zero = default(ResponseCurve); Assert.Equal(0f, zero.Evaluate(0.5f)); } [Fact] public void Evaluate_ClampsInputAndOutputToUnitRange() { var curve = ResponseCurve.Linear(); Assert.Equal(0f, curve.Evaluate(-2f)); Assert.Equal(1f, curve.Evaluate(5f)); } [Fact] public void Linear_NegativeSlope_InvertsTheInput() { var curve = ResponseCurve.Linear(slope: -1f, yShift: 1f); Assert.Equal(1f, curve.Evaluate(0f), 5); Assert.Equal(0.75f, curve.Evaluate(0.25f), 5); Assert.Equal(0f, curve.Evaluate(1f), 5); } [Fact] public void Polynomial_Quadratic_EasesInFromZero() { var curve = ResponseCurve.Polynomial(exponent: 2f); Assert.Equal(0.25f, curve.Evaluate(0.5f), 5); Assert.True(curve.Evaluate(0.25f) < 0.25f); // below the linear line: slow start } [Fact] public void Logistic_IsMonotonicAndCentredOnMidpoint() { var curve = ResponseCurve.Logistic(steepness: 12f, midpoint: 0.5f); Assert.Equal(0.5f, curve.Evaluate(0.5f), 2); Assert.True(curve.Evaluate(0.2f) < 0.5f); Assert.True(curve.Evaluate(0.8f) > 0.5f); Assert.True(curve.Evaluate(0.6f) > curve.Evaluate(0.4f)); } [Fact] public void SmoothStep_IsFlatAtTheEnds() { var curve = ResponseCurve.SmoothStep(); Assert.Equal(0f, curve.Evaluate(0f), 5); Assert.Equal(1f, curve.Evaluate(1f), 5); Assert.Equal(0.5f, curve.Evaluate(0.5f), 5); } }