b451f83174
Captures the pre-Godot-port state of the codebase. This is the rollback anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md). All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
106 lines
4.5 KiB
C#
106 lines
4.5 KiB
C#
using Theriapolis.Core;
|
|
using Theriapolis.Core.Data;
|
|
using Theriapolis.Core.Persistence;
|
|
using Theriapolis.Core.Rules.Reputation;
|
|
using Xunit;
|
|
|
|
namespace Theriapolis.Tests.Reputation;
|
|
|
|
/// <summary>
|
|
/// Phase 6 M2 — round-trip <see cref="PlayerReputation"/> through the
|
|
/// codec. Every field must survive Capture → Restore identically. Plus
|
|
/// the SaveCodec serialization path itself: write a SaveBody with rep
|
|
/// data, parse it back, compare.
|
|
/// </summary>
|
|
public sealed class ReputationRoundTripTests
|
|
{
|
|
[Fact]
|
|
public void CaptureRestore_FactionStandings_RoundTrips()
|
|
{
|
|
var factions = new ContentResolver(new ContentLoader(TestHelpers.DataDirectory)).Factions;
|
|
var rep = new PlayerReputation();
|
|
rep.Factions.Apply("inheritors", 30, factions);
|
|
rep.Factions.Apply("merchant_guilds", 50, factions);
|
|
|
|
var snap = ReputationCodec.Capture(rep);
|
|
var restored = ReputationCodec.Restore(snap);
|
|
|
|
Assert.Equal(rep.Factions.Get("inheritors"), restored.Factions.Get("inheritors"));
|
|
Assert.Equal(rep.Factions.Get("covenant_enforcers"), restored.Factions.Get("covenant_enforcers"));
|
|
Assert.Equal(rep.Factions.Get("merchant_guilds"), restored.Factions.Get("merchant_guilds"));
|
|
}
|
|
|
|
[Fact]
|
|
public void CaptureRestore_PersonalDispositions_RoundTrip()
|
|
{
|
|
var rep = new PlayerReputation();
|
|
var pd = rep.PersonalFor("millhaven.innkeeper");
|
|
pd.Score = 25;
|
|
pd.Trust = TrustLevel.Familiar;
|
|
pd.Betrayed = false;
|
|
pd.Memory.Add("saved-her-kit");
|
|
pd.Memory.Add("paid-for-the-window");
|
|
pd.Log.Add(new RepEvent { Kind = RepEventKind.Aid, RoleTag = "millhaven.innkeeper",
|
|
Magnitude = 10, Note = "first" });
|
|
|
|
var snap = ReputationCodec.Capture(rep);
|
|
var restored = ReputationCodec.Restore(snap);
|
|
|
|
Assert.True(restored.Personal.ContainsKey("millhaven.innkeeper"));
|
|
var rPd = restored.Personal["millhaven.innkeeper"];
|
|
Assert.Equal(25, rPd.Score);
|
|
Assert.Equal(TrustLevel.Familiar, rPd.Trust);
|
|
Assert.Contains("saved-her-kit", rPd.Memory);
|
|
Assert.Contains("paid-for-the-window", rPd.Memory);
|
|
Assert.Single(rPd.Log);
|
|
Assert.Equal("first", rPd.Log[0].Note);
|
|
}
|
|
|
|
[Fact]
|
|
public void CaptureRestore_Ledger_RoundTrips()
|
|
{
|
|
var factions = new ContentResolver(new ContentLoader(TestHelpers.DataDirectory)).Factions;
|
|
var rep = new PlayerReputation();
|
|
rep.Submit(new RepEvent { Kind = RepEventKind.Quest, FactionId = "inheritors", Magnitude = 10, Note = "a" }, factions);
|
|
rep.Submit(new RepEvent { Kind = RepEventKind.Betrayal, FactionId = "thorn_council", Magnitude = -25, Note = "b" }, factions);
|
|
|
|
var snap = ReputationCodec.Capture(rep);
|
|
var restored = ReputationCodec.Restore(snap);
|
|
|
|
Assert.Equal(rep.Ledger.Count, restored.Ledger.Count);
|
|
Assert.Equal(rep.Ledger.Entries[0].Note, restored.Ledger.Entries[0].Note);
|
|
Assert.Equal(rep.Ledger.Entries[1].Kind, restored.Ledger.Entries[1].Kind);
|
|
}
|
|
|
|
[Fact]
|
|
public void SaveCodec_RoundTripsReputationState()
|
|
{
|
|
var factions = new ContentResolver(new ContentLoader(TestHelpers.DataDirectory)).Factions;
|
|
|
|
var body = new SaveBody();
|
|
body.Player.Name = "Tester";
|
|
body.Player.PositionX = 100;
|
|
body.Player.PositionY = 200;
|
|
|
|
// Populate reputation state.
|
|
var rep = new PlayerReputation();
|
|
rep.Submit(new RepEvent { Kind = RepEventKind.Quest, FactionId = "inheritors", Magnitude = 10 }, factions);
|
|
var pd = rep.PersonalFor("millhaven.constable_fenn");
|
|
pd.Score = 7;
|
|
pd.Memory.Add("met-at-the-magistrate");
|
|
body.ReputationState = ReputationCodec.Capture(rep);
|
|
|
|
var header = new SaveHeader { Version = C.SAVE_SCHEMA_VERSION, WorldSeedHex = "0xCAFE" };
|
|
var bytes = SaveCodec.Serialize(header, body);
|
|
var (h2, b2) = SaveCodec.Deserialize(bytes);
|
|
|
|
Assert.Equal(C.SAVE_SCHEMA_VERSION, h2.Version);
|
|
Assert.Equal( 10, b2.ReputationState.FactionStandings["inheritors"]);
|
|
Assert.Equal( -5, b2.ReputationState.FactionStandings["covenant_enforcers"]);
|
|
Assert.Single(b2.ReputationState.Personal);
|
|
Assert.Equal("millhaven.constable_fenn", b2.ReputationState.Personal[0].RoleTag);
|
|
Assert.Contains("met-at-the-magistrate", b2.ReputationState.Personal[0].MemoryTags);
|
|
Assert.Single(b2.ReputationState.Ledger);
|
|
}
|
|
}
|