From f00453448fb7259fbe35bd1bfa7f3017fe1c7e28 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sun, 2 Nov 2025 22:57:46 +0100 Subject: [PATCH] Fix turn choice ordering not functioning properly --- PkmnLib.Dynamic/Models/BattleChoiceQueue.cs | 1 + .../Models/Choices/TurnChoiceComparer.cs | 6 +- PkmnLib.Tests/Dynamic/ChoiceQueueTests.cs | 88 +++++++++++++++---- 3 files changed, 76 insertions(+), 19 deletions(-) diff --git a/PkmnLib.Dynamic/Models/BattleChoiceQueue.cs b/PkmnLib.Dynamic/Models/BattleChoiceQueue.cs index 9ad8420..94ced8e 100644 --- a/PkmnLib.Dynamic/Models/BattleChoiceQueue.cs +++ b/PkmnLib.Dynamic/Models/BattleChoiceQueue.cs @@ -25,6 +25,7 @@ public class BattleChoiceQueue : IDeepCloneable /// public BattleChoiceQueue(ITurnChoice[] choices) { + Array.Sort(choices, TurnChoiceComparer.Instance!); _choices = choices; } diff --git a/PkmnLib.Dynamic/Models/Choices/TurnChoiceComparer.cs b/PkmnLib.Dynamic/Models/Choices/TurnChoiceComparer.cs index 27a7139..7b39bc6 100644 --- a/PkmnLib.Dynamic/Models/Choices/TurnChoiceComparer.cs +++ b/PkmnLib.Dynamic/Models/Choices/TurnChoiceComparer.cs @@ -18,12 +18,12 @@ public class TurnChoiceComparer : IComparer private static CompareValues CompareForSameType(ITurnChoice x, ITurnChoice y) { // Higher speed goes first - var speedComparison = x.Speed.CompareTo(y.Speed); + var speedComparison = y.Speed.CompareTo(x.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); + return (CompareValues)y.RandomValue.CompareTo(x.RandomValue); } private static CompareValues CompareImpl(ITurnChoice? x, ITurnChoice? y) @@ -46,7 +46,7 @@ public class TurnChoiceComparer : IComparer if (y is IMoveChoice moveY) { // Higher priority goes first - var priorityComparison = moveX.Priority.CompareTo(moveY.Priority); + var priorityComparison = moveY.Priority.CompareTo(moveX.Priority); if (priorityComparison != 0) return (CompareValues)priorityComparison; return CompareForSameType(moveX, moveY); diff --git a/PkmnLib.Tests/Dynamic/ChoiceQueueTests.cs b/PkmnLib.Tests/Dynamic/ChoiceQueueTests.cs index c57acfb..6631622 100644 --- a/PkmnLib.Tests/Dynamic/ChoiceQueueTests.cs +++ b/PkmnLib.Tests/Dynamic/ChoiceQueueTests.cs @@ -5,6 +5,46 @@ namespace PkmnLib.Tests.Dynamic; public class ChoiceQueueTests { + [Test] + public async Task ChoiceQueue_HighSpeedFirstWhenPriorityEqual() + { + var pokemon1 = Substitute.For(); + var pokemon2 = Substitute.For(); + + var choice1 = Substitute.For(); + choice1.User.Returns(pokemon1); + choice1.Priority.Returns((sbyte)0); + choice1.Speed.Returns((uint)100); + var choice2 = Substitute.For(); + 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(); + var pokemon2 = Substitute.For(); + + var choice1 = Substitute.For(); + choice1.User.Returns(pokemon1); + choice1.Priority.Returns((sbyte)0); + choice1.Speed.Returns((uint)100); + var choice2 = Substitute.For(); + 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] public async Task ChoiceQueue_MovePokemonChoiceNext() { @@ -13,14 +53,18 @@ public class ChoiceQueueTests var pokemon3 = Substitute.For(); var pokemon4 = Substitute.For(); - var choice1 = Substitute.For(); + var choice1 = Substitute.For(); choice1.User.Returns(pokemon1); - var choice2 = Substitute.For(); + choice1.Speed.Returns((uint)4); + var choice2 = Substitute.For(); choice2.User.Returns(pokemon2); - var choice3 = Substitute.For(); + choice2.Speed.Returns((uint)3); + var choice3 = Substitute.For(); choice3.User.Returns(pokemon3); - var choice4 = Substitute.For(); + choice3.Speed.Returns((uint)2); + var choice4 = Substitute.For(); choice4.User.Returns(pokemon4); + choice4.Speed.Returns((uint)1); var queue = new BattleChoiceQueue([choice1, choice2, choice3, choice4]); var result = queue.MovePokemonChoiceNext(pokemon3); @@ -36,14 +80,18 @@ public class ChoiceQueueTests var pokemon3 = Substitute.For(); var pokemon4 = Substitute.For(); - var choice1 = Substitute.For(); + var choice1 = Substitute.For(); choice1.User.Returns(pokemon1); - var choice2 = Substitute.For(); + choice1.Speed.Returns((uint)4); + var choice2 = Substitute.For(); choice2.User.Returns(pokemon2); - var choice3 = Substitute.For(); + choice2.Speed.Returns((uint)3); + var choice3 = Substitute.For(); choice3.User.Returns(pokemon3); - var choice4 = Substitute.For(); + choice3.Speed.Returns((uint)2); + var choice4 = Substitute.For(); choice4.User.Returns(pokemon4); + choice4.Speed.Returns((uint)1); var queue = new BattleChoiceQueue([choice1, choice2, choice3, choice4]); queue.Dequeue(); @@ -60,14 +108,18 @@ public class ChoiceQueueTests var pokemon3 = Substitute.For(); var pokemon4 = Substitute.For(); - var choice1 = Substitute.For(); + var choice1 = Substitute.For(); choice1.User.Returns(pokemon1); - var choice2 = Substitute.For(); + choice1.Speed.Returns((uint)4); + var choice2 = Substitute.For(); choice2.User.Returns(pokemon2); - var choice3 = Substitute.For(); + choice2.Speed.Returns((uint)3); + var choice3 = Substitute.For(); choice3.User.Returns(pokemon3); - var choice4 = Substitute.For(); + choice3.Speed.Returns((uint)2); + var choice4 = Substitute.For(); choice4.User.Returns(pokemon4); + choice4.Speed.Returns((uint)1); var queue = new BattleChoiceQueue([choice1, choice2, choice3, choice4]); var result = queue.MovePokemonChoiceLast(pokemon2); @@ -86,14 +138,18 @@ public class ChoiceQueueTests var pokemon3 = Substitute.For(); var pokemon4 = Substitute.For(); - var choice1 = Substitute.For(); + var choice1 = Substitute.For(); choice1.User.Returns(pokemon1); - var choice2 = Substitute.For(); + choice1.Speed.Returns((uint)4); + var choice2 = Substitute.For(); choice2.User.Returns(pokemon2); - var choice3 = Substitute.For(); + choice2.Speed.Returns((uint)3); + var choice3 = Substitute.For(); choice3.User.Returns(pokemon3); - var choice4 = Substitute.For(); + choice3.Speed.Returns((uint)2); + var choice4 = Substitute.For(); choice4.User.Returns(pokemon4); + choice4.Speed.Returns((uint)1); var queue = new BattleChoiceQueue([choice1, choice2, choice3, choice4]); queue.Dequeue();