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

86 lines
3.1 KiB
C#
Raw Normal View History

2024-07-27 14:26:45 +00:00
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>
{
2024-08-10 09:18:10 +00:00
/// <inheritdoc cref="TurnChoiceComparer"/>
public static TurnChoiceComparer Instance { get; } = new();
2025-03-02 16:19:57 +00:00
2024-07-27 14:26:45 +00:00
private enum CompareValues
{
XEqualsY = 0,
XLessThanY = -1,
2024-08-23 07:24:00 +00:00
XGreaterThanY = 1,
2024-07-27 14:26:45 +00:00
}
private static CompareValues CompareForSameType(ITurnChoice x, ITurnChoice y)
2024-07-27 14:26:45 +00:00
{
// 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);
}
2025-03-02 16:19:57 +00:00
private static CompareValues CompareImpl(ITurnChoice? x, ITurnChoice? y)
2024-07-27 14:26:45 +00:00
{
// 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),
2024-08-23 07:24:00 +00:00
_ => CompareValues.XGreaterThanY,
2024-07-27 14:26:45 +00:00
};
case ISwitchChoice switchX:
// Switch choices go third
return y switch
{
IMoveChoice or IItemChoice => CompareValues.XLessThanY,
ISwitchChoice switchY => CompareForSameType(switchX, switchY),
2024-08-23 07:24:00 +00:00
_ => CompareValues.XGreaterThanY,
2024-07-27 14:26:45 +00:00
};
case IPassChoice passX:
// Pass choices go last
return y switch
{
IMoveChoice or IItemChoice or ISwitchChoice => CompareValues.XLessThanY,
IPassChoice passY => CompareForSameType(passX, passY),
2024-08-23 07:24:00 +00:00
_ => CompareValues.XGreaterThanY,
2024-07-27 14:26:45 +00:00
};
}
2025-03-02 16:19:57 +00:00
2024-07-27 14:26:45 +00:00
return CompareValues.XLessThanY;
}
/// <inheritdoc />
2025-03-02 16:19:57 +00:00
public int Compare(ITurnChoice? x, ITurnChoice? y) => (int)CompareImpl(x, y);
2024-07-27 14:26:45 +00:00
}