Files
tbd-station-14/Content.Server/AI/Utility/Considerations/Consideration.cs
Pieter-Jan Briers f182ff5613 Remove CannyFastMath.
2020-08-12 21:19:34 +02:00

134 lines
4.4 KiB
C#

using System;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States.Utility;
using JetBrains.Annotations;
using Robust.Shared.Maths;
namespace Content.Server.AI.Utility.Considerations
{
public abstract class Consideration
{
protected abstract float GetScore(Blackboard context);
private float GetAdjustedScore(Blackboard context)
{
var score = GetScore(context);
var considerationsCount = context.GetState<ConsiderationState>().GetValue();
var modificationFactor = 1.0f - 1.0f / considerationsCount;
var makeUpValue = (1.0f - score) * modificationFactor;
var adjustedScore = score + makeUpValue * score;
return FloatMath.Clamp(adjustedScore, 0.0f, 1.0f);
}
[Pure]
private static float BoolCurve(float x)
{
// ReSharper disable once CompareOfFloatsByEqualityOperator
return x == 1.0f ? 1.0f : 0.0f;
}
public Func<float> BoolCurve(Blackboard context)
{
float Result()
{
var adjustedScore = GetAdjustedScore(context);
return BoolCurve(adjustedScore);
}
return Result;
}
[Pure]
private static float InverseBoolCurve(float x)
{
// ReSharper disable once CompareOfFloatsByEqualityOperator
return x == 1.0f ? 0.0f : 1.0f;
}
public Func<float> InverseBoolCurve(Blackboard context)
{
float Result()
{
var adjustedScore = GetAdjustedScore(context);
return InverseBoolCurve(adjustedScore);
}
return Result;
}
[Pure]
private static float LogisticCurve(float x, float slope, float exponent, float yOffset, float xOffset)
{
return FloatMath.Clamp(
exponent * (1 / (1 + (float) Math.Pow(Math.Log(1000) * slope, -1 * x + xOffset))) + yOffset, 0.0f, 1.0f);
}
public Func<float> LogisticCurve(Blackboard context, float slope, float exponent, float yOffset, float xOffset)
{
float Result()
{
var adjustedScore = GetAdjustedScore(context);
return LogisticCurve(adjustedScore, slope, exponent, yOffset, xOffset);
}
return Result;
}
[Pure]
private static float QuadraticCurve(float x, float slope, float exponent, float yOffset, float xOffset)
{
return FloatMath.Clamp(slope * (float) Math.Pow(x - xOffset, exponent) + yOffset, 0.0f, 1.0f);
}
public Func<float> QuadraticCurve(Blackboard context, float slope, float exponent, float yOffset, float xOffset)
{
float Result()
{
var adjustedScore = GetAdjustedScore(context);
return QuadraticCurve(adjustedScore, slope, exponent, yOffset, xOffset);
}
return Result;
}
/// <summary>
/// For any curves that are re-used across actions so you only need to update it once.
/// </summary>
/// <param name="context"></param>
/// <param name="preset"></param>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public Func<float> PresetCurve(Blackboard context, PresetCurve preset)
{
float Result()
{
var adjustedScore = GetAdjustedScore(context);
switch (preset)
{
case Considerations.PresetCurve.Distance:
return QuadraticCurve(adjustedScore, -1.0f, 1.0f, 1.0f, 0.02f);
case Considerations.PresetCurve.Nutrition:
return QuadraticCurve(adjustedScore, 2.0f, 1.0f, -1.0f, -0.2f);
case Considerations.PresetCurve.TargetHealth:
return QuadraticCurve(adjustedScore, 1.0f, 0.4f, 0.0f, -0.02f);
default:
throw new ArgumentOutOfRangeException(nameof(preset), preset, null);
}
}
return Result;
}
}
/// <summary>
/// Preset response curves for considerations
/// </summary>
public enum PresetCurve
{
Distance,
Nutrition,
TargetHealth,
}
}