Files

111 lines
3.9 KiB
C#
Raw Permalink Normal View History

using Theriapolis.Core;
using Theriapolis.Core.Data;
using Theriapolis.Core.Rules.Reputation;
using Xunit;
namespace Theriapolis.Tests.Reputation;
/// <summary>
/// Phase 6 M2 — opposition matrix application.
///
/// The plan §I-2 spells out the exact multipliers; this suite verifies
/// the cascade fires in both directions (gains and losses) and stays
/// inside the clamp range.
/// </summary>
public sealed class FactionOppositionTests
{
private static IReadOnlyDictionary<string, FactionDef> LoadFactions()
=> new ContentResolver(new ContentLoader(TestHelpers.DataDirectory)).Factions;
[Fact]
public void GainWithInheritors_CascadesIntoOppositionLosses()
{
var factions = LoadFactions();
var standing = new FactionStanding();
var applied = standing.Apply("inheritors", 10, factions);
// Per the doc: +10 with Inheritors should yield -5 Enforcers,
// -2 Thorn Council, -3 Hybrid Underground, -3 Unsheathed.
Assert.Equal( 10, standing.Get("inheritors"));
Assert.Equal( -5, standing.Get("covenant_enforcers"));
Assert.Equal( -2, standing.Get("thorn_council"));
Assert.Equal( -3, standing.Get("hybrid_underground"));
Assert.Equal( -3, standing.Get("unsheathed"));
Assert.Equal( 0, standing.Get("merchant_guilds")); // multiplier 0
// The applied list reports every actually-changed faction.
Assert.Contains(applied, t => t.FactionId == "inheritors" && t.Delta == 10);
Assert.Contains(applied, t => t.FactionId == "covenant_enforcers" && t.Delta == -5);
}
[Fact]
public void LossWithInheritors_CascadesIntoOppositionGains()
{
var factions = LoadFactions();
var standing = new FactionStanding();
standing.Apply("inheritors", -20, factions);
// -20 × -0.5 = +10 with Enforcers.
Assert.Equal(-20, standing.Get("inheritors"));
Assert.Equal( 10, standing.Get("covenant_enforcers"));
Assert.Equal( 4, standing.Get("thorn_council"));
Assert.Equal( 6, standing.Get("hybrid_underground"));
Assert.Equal( 6, standing.Get("unsheathed"));
}
[Fact]
public void Standing_IsClampedToRepRange()
{
var factions = LoadFactions();
var standing = new FactionStanding();
standing.Apply("inheritors", 200, factions);
Assert.Equal(C.REP_MAX, standing.Get("inheritors"));
// Cascaded -100 is below the floor — verify clamping.
Assert.Equal(C.REP_MIN, standing.Get("covenant_enforcers"));
}
[Fact]
public void ZeroDelta_DoesNothing()
{
var factions = LoadFactions();
var standing = new FactionStanding();
standing.Set("inheritors", 25);
standing.Apply("inheritors", 0, factions);
Assert.Equal(25, standing.Get("inheritors"));
Assert.Equal( 0, standing.Get("covenant_enforcers"));
}
[Fact]
public void UnknownFaction_NoCascade()
{
var factions = LoadFactions();
var standing = new FactionStanding();
// No throw; standing accumulates against the unknown id.
standing.Apply("not_a_real_faction", 10, factions);
Assert.Equal(10, standing.Get("not_a_real_faction"));
Assert.Equal( 0, standing.Get("covenant_enforcers"));
}
[Fact]
public void SubmitEvent_AppliesFactionAndPersonal()
{
var factions = LoadFactions();
var rep = new PlayerReputation();
rep.Submit(new RepEvent
{
Kind = RepEventKind.Quest,
FactionId = "inheritors",
RoleTag = "test.someone",
Magnitude = 10,
Note = "test event",
}, factions);
Assert.Equal(10, rep.Factions.Get("inheritors"));
Assert.Equal(-5, rep.Factions.Get("covenant_enforcers"));
Assert.Equal(10, rep.PersonalFor("test.someone").Score);
Assert.Single(rep.Ledger.Entries);
}
}