54 lines
2 KiB
C#
54 lines
2 KiB
C#
using Outnumbered.Domain;
|
|
using Xunit;
|
|
|
|
namespace Outnumbered.Tests;
|
|
|
|
// ProgressionModel: XP curve + prestige boost. Expected XP values are INDEPENDENT literals (computed offline from the
|
|
// documented formula), so these catch an implementation typo, not just lock current output.
|
|
public class ProgressionModelTests
|
|
{
|
|
// XpToNext = LevelXpBase + round(LevelXpStep * (max(0,L-1))^LevelXpExponent); defaults Base=100, Step=8, Exp=1.7.
|
|
[Theory]
|
|
[InlineData(1, 100)] // (L-1)=0 -> 0 -> just the base
|
|
[InlineData(2, 108)]
|
|
[InlineData(3, 126)]
|
|
[InlineData(5, 184)]
|
|
[InlineData(10, 435)]
|
|
[InlineData(25, 1876)]
|
|
[InlineData(50, 6076)]
|
|
[InlineData(100, 19855)]
|
|
public void XpToNext_matches_curve(int level, long expected) =>
|
|
Assert.Equal(expected, ProgressionModel.XpToNext(level, T.Prog()));
|
|
|
|
[Theory]
|
|
[InlineData(0)]
|
|
[InlineData(-5)]
|
|
public void XpToNext_floors_negative_level_at_base(int level) =>
|
|
Assert.Equal(100L, ProgressionModel.XpToNext(level, T.Prog())); // Math.Max(0, L-1) guards the Pow base
|
|
|
|
[Fact]
|
|
public void XpToNext_is_strictly_increasing_above_level_one()
|
|
{
|
|
var c = T.Prog();
|
|
long prev = ProgressionModel.XpToNext(1, c);
|
|
for (int l = 2; l <= c.LevelCap; l++)
|
|
{
|
|
long cur = ProgressionModel.XpToNext(l, c);
|
|
Assert.True(cur > prev, $"XpToNext({l})={cur} should exceed XpToNext({l - 1})={prev}");
|
|
prev = cur;
|
|
}
|
|
}
|
|
|
|
// PrestigeXpMultiplier = 1 + prestige * (PrestigeXpBoostPercent/100); default 10% per prestige.
|
|
[Theory]
|
|
[InlineData(0, 1.00)]
|
|
[InlineData(1, 1.10)]
|
|
[InlineData(5, 1.50)]
|
|
[InlineData(10, 2.00)]
|
|
public void PrestigeXpMultiplier_matches(int prestige, double expected) =>
|
|
T.Close(expected, ProgressionModel.PrestigeXpMultiplier(prestige, T.Prog()));
|
|
|
|
[Fact]
|
|
public void Retune_pinned_prestige_boost_is_ten_percent() =>
|
|
Assert.Equal(10, T.Prog().PrestigeXpBoostPercent); // pins the balance-retune knob
|
|
}
|