Move goal weights into BehaviorDef so a pack can rebalance decisions without a fork.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -34,7 +34,7 @@ public sealed class CatalogLoader
|
||||
var resolved = ResolveInheritance(defs);
|
||||
ApplyPatches(resolved, patches);
|
||||
var catalog = Materialize(order, resolved, localesRu, localesEn);
|
||||
ResolveReferences(catalog);
|
||||
ResolveReferences(catalog, log);
|
||||
return catalog;
|
||||
}
|
||||
|
||||
@@ -398,7 +398,7 @@ public sealed class CatalogLoader
|
||||
en);
|
||||
}
|
||||
|
||||
private static void ResolveReferences(DefCatalog catalog)
|
||||
private static void ResolveReferences(DefCatalog catalog, IContentLog log)
|
||||
{
|
||||
foreach (var thing in catalog.Things.Values)
|
||||
{
|
||||
@@ -488,7 +488,7 @@ public sealed class CatalogLoader
|
||||
}
|
||||
}
|
||||
|
||||
PeopleDefValidator.Validate(catalog);
|
||||
PeopleDefValidator.Validate(catalog, log);
|
||||
}
|
||||
|
||||
private sealed record RawDef(string PackId, DefKind Kind, string DefName, JsonObject Json, string Source);
|
||||
|
||||
@@ -2,8 +2,9 @@ namespace HSchool.Content;
|
||||
|
||||
internal static class PeopleDefValidator
|
||||
{
|
||||
public static void Validate(DefCatalog catalog)
|
||||
public static void Validate(DefCatalog catalog, IContentLog? log = null)
|
||||
{
|
||||
log ??= NullContentLog.Instance;
|
||||
foreach (var body in catalog.BodyAttributes.Values)
|
||||
{
|
||||
ValidateBody(body);
|
||||
@@ -56,7 +57,7 @@ internal static class PeopleDefValidator
|
||||
|
||||
foreach (var behavior in catalog.Behavior.Values)
|
||||
{
|
||||
ValidateBehavior(behavior);
|
||||
ValidateBehavior(behavior, log);
|
||||
}
|
||||
|
||||
if (catalog.Staffing.Values.Count(def => !def.Abstract) > 1)
|
||||
@@ -476,7 +477,7 @@ internal static class PeopleDefValidator
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateBehavior(BehaviorDef behavior)
|
||||
private static void ValidateBehavior(BehaviorDef behavior, IContentLog log)
|
||||
{
|
||||
if (behavior.Abstract)
|
||||
{
|
||||
@@ -503,6 +504,22 @@ internal static class PeopleDefValidator
|
||||
throw new ContentLoadException(
|
||||
$"BehaviorDef '{behavior.DefName}' commute slack must be a non-negative range with min ≤ max.");
|
||||
}
|
||||
|
||||
if (behavior.DutyLessonWeight < 0f
|
||||
|| behavior.DutyTravelWeight < 0f
|
||||
|| behavior.NeedWeightAtZero < 0f
|
||||
|| behavior.LunchWeight < 0f)
|
||||
{
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' goal weights cannot be negative.");
|
||||
}
|
||||
|
||||
// A pack may invert this on purpose — lunch then pulls the class out of the lesson.
|
||||
// The warning is the catch; refusing to load would make the number unmoddable.
|
||||
if (behavior.LunchWeight > behavior.DutyLessonWeight)
|
||||
{
|
||||
log.Warning(
|
||||
$"BehaviorDef '{behavior.DefName}' lunchWeight {behavior.LunchWeight} is above dutyLessonWeight {behavior.DutyLessonWeight}; pupils will leave class for lunch.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateHoliday(HolidayDef holiday)
|
||||
|
||||
@@ -215,12 +215,13 @@ public sealed class StaffingDef : Def
|
||||
|
||||
/// <summary>
|
||||
/// One school's behaviour numbers: when a need is urgent, how fast lessons teach, commute slack,
|
||||
/// and how much a new goal must beat the current one before a person switches. A catalog may have
|
||||
/// only one concrete ruleset.
|
||||
/// how much a new goal must beat the current one before a person switches, and the four goal
|
||||
/// weights the decision planner compares. A catalog may have only one concrete ruleset. Missing
|
||||
/// weights keep today's numbers so a pack without them does not empty the classrooms.
|
||||
/// </summary>
|
||||
public sealed class BehaviorDef : Def
|
||||
{
|
||||
/// <summary>A need at or below this value is urgent. Phase 21 turns that into a goal weight.</summary>
|
||||
/// <summary>A need at or below this value is urgent. The planner turns that into a goal weight.</summary>
|
||||
public float NeedThreshold { get; init; }
|
||||
|
||||
/// <summary>Skill points a lesson adds per game hour, before traits and need state.</summary>
|
||||
@@ -233,6 +234,22 @@ public sealed class BehaviorDef : Def
|
||||
|
||||
/// <summary>A new goal must beat the current one by this much before the person switches.</summary>
|
||||
public float SwitchMargin { get; init; }
|
||||
|
||||
/// <summary>Lesson or posted work. Beats leisure and a need that only just crossed the threshold.</summary>
|
||||
public float DutyLessonWeight { get; init; } = 10f;
|
||||
|
||||
/// <summary>Walk to the next room on a break. Beats chatting in the corridor you are standing in.</summary>
|
||||
public float DutyTravelWeight { get; init; } = 5f;
|
||||
|
||||
/// <summary>Need at zero. Beats a lesson so a desperate toilet trip leaves class.</summary>
|
||||
public float NeedWeightAtZero { get; init; } = 20f;
|
||||
|
||||
/// <summary>
|
||||
/// A sitting during this parallel's own lunch break. Above <see cref="DutyTravelWeight"/> so
|
||||
/// lunch beats walking on to the next room, below <see cref="DutyLessonWeight"/> so it never
|
||||
/// pulls anybody out of a lesson.
|
||||
/// </summary>
|
||||
public float LunchWeight { get; init; } = 6f;
|
||||
}
|
||||
|
||||
public enum BodyAttributeKind
|
||||
|
||||
Reference in New Issue
Block a user