I have now gotten two crash reports from players that have me puzzled:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeLo(ComparableTimSort.java:744)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:481)
at java.util.ComparableTimSort.mergeForceCollapse(ComparableTimSort.java:422)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:222)
at java.util.Arrays.sort(Arrays.java:1312)
at java.util.Arrays.sort(Arrays.java:1506)
at java.util.ArrayList.sort(ArrayList.java:1462)
at java.util.Collections.sort(Collections.java:143)
This is the place in my code that the crash has occurred:
public Unit chooseDropUnit(ArrayList<Unit> units) {
ArrayList<Unit> temp = new ArrayList<Unit>(units.size());
temp.addAll(units);
// This is where the crash occurs
Collections.sort(temp);
// The rest of the code takes the lowest ranking unit that
// isn't artillery. If none, it takes the lowest ranking unit.
}
The CompareTo method of my class Unit is involved here:
public int compareTo(Unit u) {
int cr_one = u.getCombatRating();
int cr_two = this.getCombatRating();
// Make allowance for rifled musket or artillery.
boolean b = u.isInfantry();
b &= this.isInfantry();
if (b && u.isRifledInfantry())
cr_one++;
if (b && this.isRifledInfantry())
cr_two++;
// Same for repeating rifles.
if (b && u.hasRepeatingRifles())
cr_one++;
if (b && this.hasRepeatingRifles())
cr_two++;
// Artillery.
b = u.isArtillery();
b &= this.isArtillery();
if (b && u.isRifledArtillery())
cr_one++;
if (b && this.isRifledArtillery())
cr_two++;
return (cr_one - cr_two);
}
I don’t see any possible violation of transitivity. Could I be getting this error because one of the elements in the ArrayList is null? I assume NO, and it must be an error in the CompareTo method. But I am suspicious because both crashes occurred in “chooseDropUnit” and that is NOT the only place that sorts objects of the Unit class.
I tested this empirically by sorting every army in the game 100,000 times, and I could not duplicate this error. Of course the game state when I happened to chose to do this is not exactly the same as the player’s when this crash occurred. I shuffled the units before each sort, of course. But this error never came up.
I just don’t see what could be wrong.