From fb159a6261cad854dc724c90c06b8923043f43b9 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Fri, 11 Oct 2019 19:03:15 +0000 Subject: [PATCH] verifyTransitivity on saComparator --- .../src/main/java/forge/ai/AiController.java | 5 +- .../main/java/forge/util/ComparatorUtil.java | 67 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 forge-core/src/main/java/forge/util/ComparatorUtil.java diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 391d83cdcdd..35dd572ec1d 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -59,6 +59,7 @@ import forge.item.PaperCard; import forge.util.Aggregates; import forge.util.Expressions; import forge.util.MyRandom; +import forge.util.ComparatorUtil; import forge.util.collect.FCollectionView; import io.sentry.Sentry; import io.sentry.event.BreadcrumbBuilder; @@ -609,6 +610,7 @@ public class AiController { ComputerUtilAbility.getAvailableCards(game, player); List all = ComputerUtilAbility.getSpellAbilities(cards, player); + ComparatorUtil.verifyTransitivity(saComparator, all); Collections.sort(all, saComparator); // put best spells first for (final SpellAbility sa : ComputerUtilAbility.getOriginalAndAltCostAbilities(all, player)) { @@ -1572,8 +1574,9 @@ public class AiController { if (all == null || all.isEmpty()) return null; + ComparatorUtil.verifyTransitivity(saComparator, all); Collections.sort(all, saComparator); // put best spells first - + for (final SpellAbility sa : ComputerUtilAbility.getOriginalAndAltCostAbilities(all, player)) { // Don't add Counterspells to the "normal" playcard lookups if (skipCounter && sa.getApi() == ApiType.Counter) { diff --git a/forge-core/src/main/java/forge/util/ComparatorUtil.java b/forge-core/src/main/java/forge/util/ComparatorUtil.java new file mode 100644 index 00000000000..7e0d6f584c5 --- /dev/null +++ b/forge-core/src/main/java/forge/util/ComparatorUtil.java @@ -0,0 +1,67 @@ +package forge.util; + +import java.util.*; + +/** + * @author Gili Tzabari + */ +public final class ComparatorUtil +{ + /** + * Verify that a comparator is transitive. + * + * @param the type being compared + * @param comparator the comparator to test + * @param elements the elements to test against + * @throws AssertionError if the comparator is not transitive + */ + public static void verifyTransitivity(Comparator comparator, Collection elements) + { + for (T first: elements) + { + for (T second: elements) + { + int result1 = comparator.compare(first, second); + int result2 = comparator.compare(second, first); + if (result1 != -result2) + { + // Uncomment the following line to step through the failed case + //comparator.compare(first, second); + throw new AssertionError("compare(" + first + ", " + second + ") == " + result1 + + " but swapping the parameters returns " + result2); + } + } + } + for (T first: elements) + { + for (T second: elements) + { + int firstGreaterThanSecond = comparator.compare(first, second); + if (firstGreaterThanSecond <= 0) + continue; + for (T third: elements) + { + int secondGreaterThanThird = comparator.compare(second, third); + if (secondGreaterThanThird <= 0) + continue; + int firstGreaterThanThird = comparator.compare(first, third); + if (firstGreaterThanThird <= 0) + { + // Uncomment the following line to step through the failed case + //comparator.compare(first, third); + throw new AssertionError("compare(" + first + ", " + second + ") > 0, " + + "compare(" + second + ", " + third + ") > 0, but compare(" + first + ", " + third + ") == " + + firstGreaterThanThird); + } + } + } + } + } + + /** + * Prevent construction. + */ + private ComparatorUtil() + { + } +} \ No newline at end of file