Fix turn choice ordering not functioning properly

This commit is contained in:
2025-11-02 22:57:46 +01:00
parent 7e537c4003
commit f00453448f
3 changed files with 76 additions and 19 deletions

View File

@@ -25,6 +25,7 @@ public class BattleChoiceQueue : IDeepCloneable
/// <inheritdoc cref="BattleChoiceQueue"/> /// <inheritdoc cref="BattleChoiceQueue"/>
public BattleChoiceQueue(ITurnChoice[] choices) public BattleChoiceQueue(ITurnChoice[] choices)
{ {
Array.Sort(choices, TurnChoiceComparer.Instance!);
_choices = choices; _choices = choices;
} }

View File

@@ -18,12 +18,12 @@ public class TurnChoiceComparer : IComparer<ITurnChoice>
private static CompareValues CompareForSameType(ITurnChoice x, ITurnChoice y) private static CompareValues CompareForSameType(ITurnChoice x, ITurnChoice y)
{ {
// Higher speed goes first // Higher speed goes first
var speedComparison = x.Speed.CompareTo(y.Speed); var speedComparison = y.Speed.CompareTo(x.Speed);
if (speedComparison != 0) if (speedComparison != 0)
return (CompareValues)speedComparison; return (CompareValues)speedComparison;
// If speed is equal, we use the random values we've given to each choice to tiebreak. // 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. // This is to ensure that the order of choices is deterministic.
return (CompareValues)x.RandomValue.CompareTo(y.RandomValue); return (CompareValues)y.RandomValue.CompareTo(x.RandomValue);
} }
private static CompareValues CompareImpl(ITurnChoice? x, ITurnChoice? y) private static CompareValues CompareImpl(ITurnChoice? x, ITurnChoice? y)
@@ -46,7 +46,7 @@ public class TurnChoiceComparer : IComparer<ITurnChoice>
if (y is IMoveChoice moveY) if (y is IMoveChoice moveY)
{ {
// Higher priority goes first // Higher priority goes first
var priorityComparison = moveX.Priority.CompareTo(moveY.Priority); var priorityComparison = moveY.Priority.CompareTo(moveX.Priority);
if (priorityComparison != 0) if (priorityComparison != 0)
return (CompareValues)priorityComparison; return (CompareValues)priorityComparison;
return CompareForSameType(moveX, moveY); return CompareForSameType(moveX, moveY);

View File

@@ -5,6 +5,46 @@ namespace PkmnLib.Tests.Dynamic;
public class ChoiceQueueTests public class ChoiceQueueTests
{ {
[Test]
public async Task ChoiceQueue_HighSpeedFirstWhenPriorityEqual()
{
var pokemon1 = Substitute.For<IPokemon>();
var pokemon2 = Substitute.For<IPokemon>();
var choice1 = Substitute.For<IMoveChoice>();
choice1.User.Returns(pokemon1);
choice1.Priority.Returns((sbyte)0);
choice1.Speed.Returns((uint)100);
var choice2 = Substitute.For<IMoveChoice>();
choice2.User.Returns(pokemon2);
choice2.Priority.Returns((sbyte)0);
choice2.Speed.Returns((uint)50);
var queue = new BattleChoiceQueue([choice1, choice2]);
await Assert.That(queue.Dequeue()).IsEqualTo(choice1);
await Assert.That(queue.Dequeue()).IsEqualTo(choice2);
}
[Test]
public async Task ChoiceQueue_HighPriorityFirst()
{
var pokemon1 = Substitute.For<IPokemon>();
var pokemon2 = Substitute.For<IPokemon>();
var choice1 = Substitute.For<IMoveChoice>();
choice1.User.Returns(pokemon1);
choice1.Priority.Returns((sbyte)0);
choice1.Speed.Returns((uint)100);
var choice2 = Substitute.For<IMoveChoice>();
choice2.User.Returns(pokemon2);
choice2.Priority.Returns((sbyte)1);
choice2.Speed.Returns((uint)50);
var queue = new BattleChoiceQueue([choice1, choice2]);
await Assert.That(queue.Dequeue()).IsEqualTo(choice2);
await Assert.That(queue.Dequeue()).IsEqualTo(choice1);
}
[Test] [Test]
public async Task ChoiceQueue_MovePokemonChoiceNext() public async Task ChoiceQueue_MovePokemonChoiceNext()
{ {
@@ -13,14 +53,18 @@ public class ChoiceQueueTests
var pokemon3 = Substitute.For<IPokemon>(); var pokemon3 = Substitute.For<IPokemon>();
var pokemon4 = Substitute.For<IPokemon>(); var pokemon4 = Substitute.For<IPokemon>();
var choice1 = Substitute.For<ITurnChoice>(); var choice1 = Substitute.For<IMoveChoice>();
choice1.User.Returns(pokemon1); choice1.User.Returns(pokemon1);
var choice2 = Substitute.For<ITurnChoice>(); choice1.Speed.Returns((uint)4);
var choice2 = Substitute.For<IMoveChoice>();
choice2.User.Returns(pokemon2); choice2.User.Returns(pokemon2);
var choice3 = Substitute.For<ITurnChoice>(); choice2.Speed.Returns((uint)3);
var choice3 = Substitute.For<IMoveChoice>();
choice3.User.Returns(pokemon3); choice3.User.Returns(pokemon3);
var choice4 = Substitute.For<ITurnChoice>(); choice3.Speed.Returns((uint)2);
var choice4 = Substitute.For<IMoveChoice>();
choice4.User.Returns(pokemon4); choice4.User.Returns(pokemon4);
choice4.Speed.Returns((uint)1);
var queue = new BattleChoiceQueue([choice1, choice2, choice3, choice4]); var queue = new BattleChoiceQueue([choice1, choice2, choice3, choice4]);
var result = queue.MovePokemonChoiceNext(pokemon3); var result = queue.MovePokemonChoiceNext(pokemon3);
@@ -36,14 +80,18 @@ public class ChoiceQueueTests
var pokemon3 = Substitute.For<IPokemon>(); var pokemon3 = Substitute.For<IPokemon>();
var pokemon4 = Substitute.For<IPokemon>(); var pokemon4 = Substitute.For<IPokemon>();
var choice1 = Substitute.For<ITurnChoice>(); var choice1 = Substitute.For<IMoveChoice>();
choice1.User.Returns(pokemon1); choice1.User.Returns(pokemon1);
var choice2 = Substitute.For<ITurnChoice>(); choice1.Speed.Returns((uint)4);
var choice2 = Substitute.For<IMoveChoice>();
choice2.User.Returns(pokemon2); choice2.User.Returns(pokemon2);
var choice3 = Substitute.For<ITurnChoice>(); choice2.Speed.Returns((uint)3);
var choice3 = Substitute.For<IMoveChoice>();
choice3.User.Returns(pokemon3); choice3.User.Returns(pokemon3);
var choice4 = Substitute.For<ITurnChoice>(); choice3.Speed.Returns((uint)2);
var choice4 = Substitute.For<IMoveChoice>();
choice4.User.Returns(pokemon4); choice4.User.Returns(pokemon4);
choice4.Speed.Returns((uint)1);
var queue = new BattleChoiceQueue([choice1, choice2, choice3, choice4]); var queue = new BattleChoiceQueue([choice1, choice2, choice3, choice4]);
queue.Dequeue(); queue.Dequeue();
@@ -60,14 +108,18 @@ public class ChoiceQueueTests
var pokemon3 = Substitute.For<IPokemon>(); var pokemon3 = Substitute.For<IPokemon>();
var pokemon4 = Substitute.For<IPokemon>(); var pokemon4 = Substitute.For<IPokemon>();
var choice1 = Substitute.For<ITurnChoice>(); var choice1 = Substitute.For<IMoveChoice>();
choice1.User.Returns(pokemon1); choice1.User.Returns(pokemon1);
var choice2 = Substitute.For<ITurnChoice>(); choice1.Speed.Returns((uint)4);
var choice2 = Substitute.For<IMoveChoice>();
choice2.User.Returns(pokemon2); choice2.User.Returns(pokemon2);
var choice3 = Substitute.For<ITurnChoice>(); choice2.Speed.Returns((uint)3);
var choice3 = Substitute.For<IMoveChoice>();
choice3.User.Returns(pokemon3); choice3.User.Returns(pokemon3);
var choice4 = Substitute.For<ITurnChoice>(); choice3.Speed.Returns((uint)2);
var choice4 = Substitute.For<IMoveChoice>();
choice4.User.Returns(pokemon4); choice4.User.Returns(pokemon4);
choice4.Speed.Returns((uint)1);
var queue = new BattleChoiceQueue([choice1, choice2, choice3, choice4]); var queue = new BattleChoiceQueue([choice1, choice2, choice3, choice4]);
var result = queue.MovePokemonChoiceLast(pokemon2); var result = queue.MovePokemonChoiceLast(pokemon2);
@@ -86,14 +138,18 @@ public class ChoiceQueueTests
var pokemon3 = Substitute.For<IPokemon>(); var pokemon3 = Substitute.For<IPokemon>();
var pokemon4 = Substitute.For<IPokemon>(); var pokemon4 = Substitute.For<IPokemon>();
var choice1 = Substitute.For<ITurnChoice>(); var choice1 = Substitute.For<IMoveChoice>();
choice1.User.Returns(pokemon1); choice1.User.Returns(pokemon1);
var choice2 = Substitute.For<ITurnChoice>(); choice1.Speed.Returns((uint)4);
var choice2 = Substitute.For<IMoveChoice>();
choice2.User.Returns(pokemon2); choice2.User.Returns(pokemon2);
var choice3 = Substitute.For<ITurnChoice>(); choice2.Speed.Returns((uint)3);
var choice3 = Substitute.For<IMoveChoice>();
choice3.User.Returns(pokemon3); choice3.User.Returns(pokemon3);
var choice4 = Substitute.For<ITurnChoice>(); choice3.Speed.Returns((uint)2);
var choice4 = Substitute.For<IMoveChoice>();
choice4.User.Returns(pokemon4); choice4.User.Returns(pokemon4);
choice4.Speed.Returns((uint)1);
var queue = new BattleChoiceQueue([choice1, choice2, choice3, choice4]); var queue = new BattleChoiceQueue([choice1, choice2, choice3, choice4]);
queue.Dequeue(); queue.Dequeue();