From d8a78f2de6fba6d67f912da095927c53708a7c65 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Thu, 20 Aug 2020 22:16:12 +1000 Subject: [PATCH] Geometric mean for AI considerations (#1812) * Geometric mean for AI cons More forgiving for having more considerations for an action. * You had 1 job Co-authored-by: Metal Gear Sloth --- .../AI/Utility/Actions/UtilityAction.cs | 13 ++++--------- .../AI/Utility/Considerations/Consideration.cs | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Content.Server/AI/Utility/Actions/UtilityAction.cs b/Content.Server/AI/Utility/Actions/UtilityAction.cs index f8be97abaa..b79fa0955a 100644 --- a/Content.Server/AI/Utility/Actions/UtilityAction.cs +++ b/Content.Server/AI/Utility/Actions/UtilityAction.cs @@ -112,19 +112,14 @@ namespace Content.Server.AI.Utility.Actions UpdateBlackboard(context); var considerations = GetConsiderations(context); DebugTools.Assert(considerations.Count > 0); - // I used the IAUS video although I did have some confusion on how to structure it overall - // as some of the slides seemed contradictory - // Ideally we should early-out each action as cheaply as possible if it's not valid - - // We also need some way to tell if the action isn't going to - // have a better score than the current action (if applicable) and early-out that way as well. - - // 23:00 Building a better centaur + // Overall structure is based on Building a better centaur + // Ideally we should early-out each action as cheaply as possible if it's not valid, thus + // the finalScore can only go down over time. + var finalScore = 1.0f; var minThreshold = min / Bonus; context.GetState().SetValue(considerations.Count); - // See 10:09 for this and the adjustments foreach (var consideration in considerations) { diff --git a/Content.Server/AI/Utility/Considerations/Consideration.cs b/Content.Server/AI/Utility/Considerations/Consideration.cs index 67b76ae559..39d125941f 100644 --- a/Content.Server/AI/Utility/Considerations/Consideration.cs +++ b/Content.Server/AI/Utility/Considerations/Consideration.cs @@ -13,10 +13,19 @@ namespace Content.Server.AI.Utility.Considerations private float GetAdjustedScore(Blackboard context) { var score = GetScore(context); + /* + * Now using the geometric mean + * for n scores you take the n-th root of the scores multiplied + * e.g. a, b, c scores you take Math.Pow(a * b * c, 1/3) + * To get the ACTUAL geometric mean at any one stage you'd need to divide by the running consideration count + * however, the downside to this is it will fluctuate up and down over time. + * For our purposes if we go below the minimum threshold we want to cut it off, thus we take a + * "running geometric mean" which can only ever go down (and by the final value will equal the actual geometric mean). + */ + + // Previously we used a makeupvalue method although the geometric mean is less punishing for more considerations var considerationsCount = context.GetState().GetValue(); - var modificationFactor = 1.0f - 1.0f / considerationsCount; - var makeUpValue = (1.0f - score) * modificationFactor; - var adjustedScore = score + makeUpValue * score; + var adjustedScore = MathF.Pow(score, 1 / (float) considerationsCount); return FloatMath.Clamp(adjustedScore, 0.0f, 1.0f); }