PkmnLib.NET/PkmnLib.Dynamic/Models/Choices/TurnChoiceComparer.cs

86 lines
3.1 KiB
C#

namespace PkmnLib.Dynamic.Models.Choices;
/// <summary>
/// Comparer for turnchoices, to determine the order in which they should be executed.
/// </summary>
public class TurnChoiceComparer : IComparer<ITurnChoice>
{
/// <inheritdoc cref="TurnChoiceComparer"/>
public static TurnChoiceComparer Instance { get; } = new();
private enum CompareValues
{
XEqualsY = 0,
XLessThanY = -1,
XGreaterThanY = 1,
}
private static CompareValues CompareForSameType(ITurnChoice x, ITurnChoice y)
{
// Higher speed goes first
var speedComparison = x.Speed.CompareTo(y.Speed);
if (speedComparison != 0)
return (CompareValues)speedComparison;
// If speed is equal, we use the random values we've given to each choice to tiebreak.
// This is to ensure that the order of choices is deterministic.
return (CompareValues)x.RandomValue.CompareTo(y.RandomValue);
}
private static CompareValues CompareImpl(ITurnChoice? x, ITurnChoice? y)
{
// Deal with possible null values
switch (x)
{
case null when y is null:
return CompareValues.XEqualsY;
case null:
return CompareValues.XLessThanY;
}
if (y is null)
return CompareValues.XGreaterThanY;
switch (x)
{
case IMoveChoice moveX:
// Move choices go first
if (y is IMoveChoice moveY)
{
// Higher priority goes first
var priorityComparison = moveX.Priority.CompareTo(moveY.Priority);
if (priorityComparison != 0)
return (CompareValues)priorityComparison;
return CompareForSameType(moveX, moveY);
}
return CompareValues.XGreaterThanY;
case IItemChoice itemX:
// Item choices go second
return y switch
{
IMoveChoice => CompareValues.XLessThanY,
IItemChoice itemY => CompareForSameType(itemX, itemY),
_ => CompareValues.XGreaterThanY,
};
case ISwitchChoice switchX:
// Switch choices go third
return y switch
{
IMoveChoice or IItemChoice => CompareValues.XLessThanY,
ISwitchChoice switchY => CompareForSameType(switchX, switchY),
_ => CompareValues.XGreaterThanY,
};
case IPassChoice passX:
// Pass choices go last
return y switch
{
IMoveChoice or IItemChoice or ISwitchChoice => CompareValues.XLessThanY,
IPassChoice passY => CompareForSameType(passX, passY),
_ => CompareValues.XGreaterThanY,
};
}
return CompareValues.XLessThanY;
}
/// <inheritdoc />
public int Compare(ITurnChoice? x, ITurnChoice? y) => (int)CompareImpl(x, y);
}