using Arch.Core; using HSchool.Ai; using HSchool.Content; namespace HSchool.Simulation.Tests; public class NeedDecayTests { [Fact] public void Hunger_DropsByDecayPerHourOnCampus() { var catalog = VanillaCatalog(); var hunger = catalog.Needs["Hunger"]; var world = World.Create(); try { world.Create( new PersonNeeds(new Dictionary(StringComparer.Ordinal) { ["Hunger"] = hunger.Initial }), new Presence("cafeteria", 0f, "cafeteria", false, [])); NeedDecay.Apply(world, catalog, gameMinutes: 60); var query = new QueryDescription().WithAll(); world.Query( in query, (ref PersonNeeds needs) => Assert.Equal(hunger.Initial - hunger.DecayPerHour, needs.Values["Hunger"], precision: 4)); } finally { World.Destroy(world); } } [Fact] public void Sleep_ReturnsToMaxOffCampus() { var catalog = VanillaCatalog(); var world = World.Create(); try { world.Create( new PersonNeeds(new Dictionary(StringComparer.Ordinal) { ["Sleep"] = 0.2f, ["Hunger"] = 0.4f, }), Presence.OffCampus); NeedDecay.Apply(world, catalog, gameMinutes: 60); var query = new QueryDescription().WithAll(); world.Query(in query, (ref PersonNeeds needs) => { Assert.Equal(catalog.Needs["Sleep"].Max, needs.Values["Sleep"]); Assert.Equal(0.4f, needs.Values["Hunger"]); }); } finally { World.Destroy(world); } } [Fact] public void SameInputs_LeaveTheSameNeedValues() { var catalog = VanillaCatalog(); var first = HungerAfterHour(catalog); var second = HungerAfterHour(catalog); Assert.Equal(first, second); } private static float HungerAfterHour(DefCatalog catalog) { var world = World.Create(); try { world.Create( new PersonNeeds(new Dictionary(StringComparer.Ordinal) { ["Hunger"] = 1f }), new Presence("cafeteria", 0f, "cafeteria", false, [])); NeedDecay.Apply(world, catalog, gameMinutes: 60); var value = 0f; var query = new QueryDescription().WithAll(); world.Query(in query, (ref PersonNeeds needs) => value = needs.Values["Hunger"]); return value; } finally { World.Destroy(world); } } private static DefCatalog VanillaCatalog() { var root = Path.Combine(AppContext.BaseDirectory, "vanilla"); var documents = new List(); foreach (var path in Directory.EnumerateFiles(root, "*.*", SearchOption.AllDirectories)) { if (!path.EndsWith(".jsonc", StringComparison.OrdinalIgnoreCase) && !path.EndsWith(".json", StringComparison.OrdinalIgnoreCase)) { continue; } var relative = Path.GetRelativePath(root, path).Replace('\\', '/'); documents.Add(new ContentDocument(CatalogLoader.CorePackId, relative, File.ReadAllText(path))); } return new CatalogLoader().Load([CatalogLoader.CorePackId], documents); } }