From f9a268c62529d240a27c701cd3f27740adc5506f Mon Sep 17 00:00:00 2001 From: Samuel Gaus Date: Thu, 18 Aug 2022 20:32:33 +0100 Subject: [PATCH] Remove GearChangeFrame code duplication (#989) * Some KoLCharacter tidying I did while reading through it * Reuse code that speculates gear mods in GearChangeFrame * Add tests for GearChangeFrame * Remove unused import * Update test * Formatting * Simplify gear change frame cell renderers * Remove reliance on render layer to test GearChangeFrame modifier formatting * Further simplify slot-related things * Make method that avoids huge switch statements Co-authored-by: Jamie Adams <82782908+jaadams5@users.noreply.github.com> --- .../sourceforge/kolmafia/KoLCharacter.java | 303 +++++++----------- .../kolmafia/maximizer/Maximizer.java | 2 +- .../kolmafia/request/EquipmentRequest.java | 40 +-- .../kolmafia/session/ChoiceControl.java | 2 +- .../kolmafia/session/EquipmentManager.java | 21 +- .../kolmafia/swingui/GearChangeFrame.java | 188 +++-------- .../widget/ListCellRendererFactory.java | 75 ++--- .../textui/command/ConditionalStatement.java | 14 +- .../kolmafia/webui/ValhallaDecorator.java | 2 +- .../kolmafia/swingui/GearChangeFrameTest.java | 107 +++++++ 10 files changed, 334 insertions(+), 420 deletions(-) create mode 100644 test/net/sourceforge/kolmafia/swingui/GearChangeFrameTest.java diff --git a/src/net/sourceforge/kolmafia/KoLCharacter.java b/src/net/sourceforge/kolmafia/KoLCharacter.java index f93964987e9..0a5503454a2 100644 --- a/src/net/sourceforge/kolmafia/KoLCharacter.java +++ b/src/net/sourceforge/kolmafia/KoLCharacter.java @@ -1,6 +1,7 @@ package net.sourceforge.kolmafia; import java.awt.Taskbar; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -4570,70 +4571,55 @@ public static final LockableListModel getFamiliarList() { * Pasta Thralls */ - public static final LockableListModel getPastaThrallList() { + public static LockableListModel getPastaThrallList() { return KoLCharacter.pastaThralls; } - public static final PastaThrallData currentPastaThrall() { + public static PastaThrallData currentPastaThrall() { return KoLCharacter.currentPastaThrall; } - public static final PastaThrallData findPastaThrall(final String type) { + public static PastaThrallData findPastaThrall(final String type) { if (ascensionClass != AscensionClass.PASTAMANCER) { return null; } - if (PastaThrallData.NO_THRALL.getType().equals(type)) { - return PastaThrallData.NO_THRALL; - } - - // Don't even look if you are an Avatar - if (KoLCharacter.inAxecore() - || KoLCharacter.isJarlsberg() - || KoLCharacter.inZombiecore() - || KoLCharacter.inNuclearAutumn() - || KoLCharacter.inNoobcore()) { + // Some paths don't allow the Pastamancer access to their normal skills + if (KoLCharacter.inNuclearAutumn()) { return null; } - for (PastaThrallData thrall : KoLCharacter.pastaThralls) { - if (thrall.getType().equals(type)) { - return thrall; - } + if (PastaThrallData.NO_THRALL.getType().equals(type)) { + return PastaThrallData.NO_THRALL; } - return null; + return KoLCharacter.pastaThralls.stream() + .filter(t -> t.getType().equals(type)) + .findFirst() + .orElse(null); } - public static final PastaThrallData findPastaThrall(final int thrallId) { + public static PastaThrallData findPastaThrall(final int thrallId) { if (ascensionClass != AscensionClass.PASTAMANCER) { return null; } - if (thrallId == 0) { - return PastaThrallData.NO_THRALL; - } - - // Don't even look if you are an Avatar - if (KoLCharacter.inAxecore() - || KoLCharacter.isJarlsberg() - || KoLCharacter.inZombiecore() - || KoLCharacter.inNuclearAutumn() - || KoLCharacter.inNoobcore() - || KoLCharacter.isVampyre()) { + // Some paths don't allow the Pastamancer access to their normal skills + if (KoLCharacter.inNuclearAutumn()) { return null; } - for (PastaThrallData thrall : KoLCharacter.pastaThralls) { - if (thrall.getId() == thrallId) { - return thrall; - } + if (thrallId == 0) { + return PastaThrallData.NO_THRALL; } - return null; + return KoLCharacter.pastaThralls.stream() + .filter(t -> t.getId() == thrallId) + .findAny() + .orElse(null); } - public static final void setPastaThrall(final PastaThrallData thrall) { + public static void setPastaThrall(final PastaThrallData thrall) { if (KoLCharacter.currentPastaThrall == thrall) { return; } @@ -4707,169 +4693,102 @@ public static final AdventureResult getZapper() { return KoLCharacter.findWand(); } - public static final AdventureResult findWand() { - for (int i = 0; i < KoLCharacter.WANDS.length; ++i) { - if (KoLConstants.inventory.contains(KoLCharacter.WANDS[i])) { - Preferences.setInteger("lastZapperWand", KoLCharacter.getAscensions()); - return KoLCharacter.WANDS[i]; - } - } - - return null; + public static AdventureResult findWand() { + return Arrays.stream(KoLCharacter.WANDS) + .filter(KoLConstants.inventory::contains) + .peek((w) -> Preferences.setInteger("lastZapperWand", KoLCharacter.getAscensions())) + .findAny() + .orElse(null); } - public static final boolean hasEquipped(final AdventureResult item, final int equipmentSlot) { + public static boolean hasEquipped(final AdventureResult item, final int equipmentSlot) { return EquipmentManager.getEquipment(equipmentSlot).getItemId() == item.getItemId(); } - public static final boolean hasEquipped(final int itemId, final int equipmentSlot) { + public static boolean hasEquipped(final int itemId, final int equipmentSlot) { return EquipmentManager.getEquipment(equipmentSlot).getItemId() == itemId; } - public static final boolean hasEquipped(final AdventureResult item) { + public static boolean hasEquipped(final AdventureResult item) { return KoLCharacter.equipmentSlot(item) != EquipmentManager.NONE; } - public static final boolean hasEquipped(final int itemId) { + public static boolean hasEquipped(final int itemId) { return KoLCharacter.hasEquipped(ItemPool.get(itemId, 1)); } - public static final boolean hasEquipped( + public static boolean hasEquipped( AdventureResult[] equipment, final AdventureResult item, final int equipmentSlot) { AdventureResult current = equipment[equipmentSlot]; - return (current == null) ? false : (current.getItemId() == item.getItemId()); - } - - public static final boolean hasEquipped(AdventureResult[] equipment, final AdventureResult item) { - switch (ItemDatabase.getConsumptionType(item.getItemId())) { - case KoLConstants.EQUIP_WEAPON: - return KoLCharacter.hasEquipped(equipment, item, EquipmentManager.WEAPON) - || KoLCharacter.hasEquipped(equipment, item, EquipmentManager.OFFHAND); - - case KoLConstants.EQUIP_OFFHAND: - return KoLCharacter.hasEquipped(equipment, item, EquipmentManager.OFFHAND) - || KoLCharacter.hasEquipped(equipment, item, EquipmentManager.FAMILIAR); - - case KoLConstants.EQUIP_HAT: - return KoLCharacter.hasEquipped(equipment, item, EquipmentManager.HAT); - - case KoLConstants.EQUIP_SHIRT: - return KoLCharacter.hasEquipped(equipment, item, EquipmentManager.SHIRT); - - case KoLConstants.EQUIP_PANTS: - return KoLCharacter.hasEquipped(equipment, item, EquipmentManager.PANTS); - - case KoLConstants.EQUIP_CONTAINER: - return KoLCharacter.hasEquipped(equipment, item, EquipmentManager.CONTAINER); - - case KoLConstants.EQUIP_ACCESSORY: - return KoLCharacter.hasEquipped(equipment, item, EquipmentManager.ACCESSORY1) - || KoLCharacter.hasEquipped(equipment, item, EquipmentManager.ACCESSORY2) - || KoLCharacter.hasEquipped(equipment, item, EquipmentManager.ACCESSORY3); - - case KoLConstants.CONSUME_STICKER: - return KoLCharacter.hasEquipped(equipment, item, EquipmentManager.STICKER1) - || KoLCharacter.hasEquipped(equipment, item, EquipmentManager.STICKER2) - || KoLCharacter.hasEquipped(equipment, item, EquipmentManager.STICKER3); - - case KoLConstants.CONSUME_CARD: - return KoLCharacter.hasEquipped(equipment, item, EquipmentManager.CARDSLEEVE); - - case KoLConstants.CONSUME_FOLDER: - return KoLCharacter.hasEquipped(equipment, item, EquipmentManager.FOLDER1) - || KoLCharacter.hasEquipped(equipment, item, EquipmentManager.FOLDER2) - || KoLCharacter.hasEquipped(equipment, item, EquipmentManager.FOLDER3) - || KoLCharacter.hasEquipped(equipment, item, EquipmentManager.FOLDER4) - || KoLCharacter.hasEquipped(equipment, item, EquipmentManager.FOLDER5); - - case KoLConstants.EQUIP_FAMILIAR: - return KoLCharacter.hasEquipped(equipment, item, EquipmentManager.FAMILIAR); - } - - return false; + return current != null && (current.getItemId() == item.getItemId()); + } + + public static boolean hasEquipped( + AdventureResult[] equipment, final AdventureResult item, int[] equipmentSlots) { + return Arrays.stream(equipmentSlots) + .anyMatch(s -> KoLCharacter.hasEquipped(equipment, item, s)); + } + + public static boolean hasEquipped(AdventureResult[] equipment, final AdventureResult item) { + return switch (ItemDatabase.getConsumptionType(item.getItemId())) { + case KoLConstants.EQUIP_WEAPON -> KoLCharacter.hasEquipped( + equipment, item, new int[] {EquipmentManager.WEAPON, EquipmentManager.OFFHAND}); + case KoLConstants.EQUIP_OFFHAND -> KoLCharacter.hasEquipped( + equipment, item, new int[] {EquipmentManager.OFFHAND, EquipmentManager.FAMILIAR}); + case KoLConstants.EQUIP_HAT -> KoLCharacter.hasEquipped( + equipment, item, EquipmentManager.HAT); + case KoLConstants.EQUIP_SHIRT -> KoLCharacter.hasEquipped( + equipment, item, EquipmentManager.SHIRT); + case KoLConstants.EQUIP_PANTS -> KoLCharacter.hasEquipped( + equipment, item, EquipmentManager.PANTS); + case KoLConstants.EQUIP_CONTAINER -> KoLCharacter.hasEquipped( + equipment, item, EquipmentManager.CONTAINER); + case KoLConstants.EQUIP_ACCESSORY -> KoLCharacter.hasEquipped( + equipment, item, EquipmentManager.ACCESSORY_SLOTS); + case KoLConstants.CONSUME_STICKER -> KoLCharacter.hasEquipped( + equipment, item, EquipmentManager.STICKER_SLOTS); + case KoLConstants.CONSUME_CARD -> KoLCharacter.hasEquipped( + equipment, item, EquipmentManager.CARDSLEEVE); + case KoLConstants.CONSUME_FOLDER -> KoLCharacter.hasEquipped( + equipment, item, EquipmentManager.FOLDER_SLOTS); + case KoLConstants.EQUIP_FAMILIAR -> KoLCharacter.hasEquipped( + equipment, item, EquipmentManager.FAMILIAR); + default -> false; + }; + } + + private static int equipmentSlotFromSubset(final AdventureResult item, final int[] slots) { + return Arrays.stream(slots) + .filter(s -> KoLCharacter.hasEquipped(item, s)) + .findFirst() + .orElse(EquipmentManager.NONE); + } + + private static int equipmentSlotFromSubset(final AdventureResult item, final int slot) { + return KoLCharacter.hasEquipped(item, slot) ? slot : EquipmentManager.NONE; } public static final int equipmentSlot(final AdventureResult item) { - switch (ItemDatabase.getConsumptionType(item.getItemId())) { - case KoLConstants.EQUIP_WEAPON: - return KoLCharacter.hasEquipped(item, EquipmentManager.WEAPON) - ? EquipmentManager.WEAPON - : KoLCharacter.hasEquipped(item, EquipmentManager.OFFHAND) - ? EquipmentManager.OFFHAND - : EquipmentManager.NONE; - - case KoLConstants.EQUIP_OFFHAND: - return KoLCharacter.hasEquipped(item, EquipmentManager.OFFHAND) - ? EquipmentManager.OFFHAND - : - // Left-Hand Man gives usual powers when holding an off-hand item - KoLCharacter.hasEquipped(item, EquipmentManager.FAMILIAR) - ? EquipmentManager.FAMILIAR - : EquipmentManager.NONE; - - case KoLConstants.EQUIP_HAT: - return KoLCharacter.hasEquipped(item, EquipmentManager.HAT) - ? EquipmentManager.HAT - : EquipmentManager.NONE; - - case KoLConstants.EQUIP_SHIRT: - return KoLCharacter.hasEquipped(item, EquipmentManager.SHIRT) - ? EquipmentManager.SHIRT - : EquipmentManager.NONE; - - case KoLConstants.EQUIP_PANTS: - return KoLCharacter.hasEquipped(item, EquipmentManager.PANTS) - ? EquipmentManager.PANTS - : EquipmentManager.NONE; - - case KoLConstants.EQUIP_CONTAINER: - return KoLCharacter.hasEquipped(item, EquipmentManager.CONTAINER) - ? EquipmentManager.CONTAINER - : EquipmentManager.NONE; - - case KoLConstants.EQUIP_ACCESSORY: - return KoLCharacter.hasEquipped(item, EquipmentManager.ACCESSORY1) - ? EquipmentManager.ACCESSORY1 - : KoLCharacter.hasEquipped(item, EquipmentManager.ACCESSORY2) - ? EquipmentManager.ACCESSORY2 - : KoLCharacter.hasEquipped(item, EquipmentManager.ACCESSORY3) - ? EquipmentManager.ACCESSORY3 - : EquipmentManager.NONE; - - case KoLConstants.CONSUME_STICKER: - return KoLCharacter.hasEquipped(item, EquipmentManager.STICKER1) - ? EquipmentManager.STICKER1 - : KoLCharacter.hasEquipped(item, EquipmentManager.STICKER2) - ? EquipmentManager.STICKER2 - : KoLCharacter.hasEquipped(item, EquipmentManager.STICKER3) - ? EquipmentManager.STICKER3 - : EquipmentManager.NONE; - - case KoLConstants.CONSUME_CARD: - return KoLCharacter.hasEquipped(item, EquipmentManager.CARDSLEEVE) - ? EquipmentManager.CARDSLEEVE - : EquipmentManager.NONE; - - case KoLConstants.CONSUME_FOLDER: - return KoLCharacter.hasEquipped(item, EquipmentManager.FOLDER1) - ? EquipmentManager.FOLDER1 - : KoLCharacter.hasEquipped(item, EquipmentManager.FOLDER2) - ? EquipmentManager.FOLDER2 - : KoLCharacter.hasEquipped(item, EquipmentManager.FOLDER3) - ? EquipmentManager.FOLDER3 - : KoLCharacter.hasEquipped(item, EquipmentManager.FOLDER4) - ? EquipmentManager.FOLDER4 - : KoLCharacter.hasEquipped(item, EquipmentManager.FOLDER5) - ? EquipmentManager.FOLDER5 - : EquipmentManager.NONE; - - case KoLConstants.EQUIP_FAMILIAR: - return KoLCharacter.hasEquipped(item, EquipmentManager.FAMILIAR) - ? EquipmentManager.FAMILIAR - : EquipmentManager.NONE; - } - - return EquipmentManager.NONE; + return switch (ItemDatabase.getConsumptionType(item.getItemId())) { + case KoLConstants.EQUIP_WEAPON -> equipmentSlotFromSubset( + item, new int[] {EquipmentManager.WEAPON, EquipmentManager.OFFHAND}); + case KoLConstants.EQUIP_OFFHAND -> equipmentSlotFromSubset( + item, new int[] {EquipmentManager.OFFHAND, EquipmentManager.FAMILIAR}); + case KoLConstants.EQUIP_HAT -> equipmentSlotFromSubset(item, EquipmentManager.HAT); + case KoLConstants.EQUIP_SHIRT -> equipmentSlotFromSubset(item, EquipmentManager.SHIRT); + case KoLConstants.EQUIP_PANTS -> equipmentSlotFromSubset(item, EquipmentManager.PANTS); + case KoLConstants.EQUIP_CONTAINER -> equipmentSlotFromSubset( + item, EquipmentManager.CONTAINER); + case KoLConstants.EQUIP_ACCESSORY -> equipmentSlotFromSubset( + item, EquipmentManager.ACCESSORY_SLOTS); + case KoLConstants.CONSUME_STICKER -> equipmentSlotFromSubset( + item, EquipmentManager.STICKER_SLOTS); + case KoLConstants.CONSUME_CARD -> equipmentSlotFromSubset(item, EquipmentManager.CARDSLEEVE); + case KoLConstants.CONSUME_FOLDER -> equipmentSlotFromSubset( + item, EquipmentManager.FOLDER_SLOTS); + case KoLConstants.EQUIP_FAMILIAR -> equipmentSlotFromSubset(item, EquipmentManager.FAMILIAR); + default -> EquipmentManager.NONE; + }; } public static final void updateStatus() { @@ -5411,7 +5330,7 @@ public static final Modifiers recalculateAdjustments( return newModifiers; } - private static void addItemAdjustment( + public static void addItemAdjustment( Modifiers newModifiers, int slot, AdventureResult item, @@ -5494,12 +5413,11 @@ private static void addItemAdjustment( case ItemPool.STICKER_SWORD: case ItemPool.STICKER_CROSSBOW: // Apply stickers - for (int i = EquipmentManager.STICKER1; i <= EquipmentManager.STICKER3; ++i) { - AdventureResult sticker = equipment[i]; - if (sticker != null && sticker != EquipmentRequest.UNEQUIP) { - newModifiers.add(Modifiers.getItemModifiers(sticker.getItemId())); - } - } + Arrays.stream(EquipmentManager.STICKER_SLOTS) + .mapToObj(i -> equipment[i]) + .filter(s -> s != null && s != EquipmentRequest.UNEQUIP) + .map(AdventureResult::getItemId) + .forEach((id) -> newModifiers.add(Modifiers.getItemModifiers(id))); break; case ItemPool.CARD_SLEEVE: @@ -5514,12 +5432,11 @@ private static void addItemAdjustment( case ItemPool.FOLDER_HOLDER: // Apply folders - for (int i = EquipmentManager.FOLDER1; i <= EquipmentManager.FOLDER5; ++i) { - AdventureResult folder = equipment[i]; - if (folder != null && folder != EquipmentRequest.UNEQUIP) { - newModifiers.add(Modifiers.getItemModifiers(folder.getItemId())); - } - } + Arrays.stream(EquipmentManager.FOLDER_SLOTS) + .mapToObj(EquipmentManager::getEquipment) + .filter(f -> f != null && f != EquipmentRequest.UNEQUIP) + .map(AdventureResult::getItemId) + .forEach((id) -> newModifiers.add(Modifiers.getItemModifiers(id))); break; case ItemPool.COWBOY_BOOTS: diff --git a/src/net/sourceforge/kolmafia/maximizer/Maximizer.java b/src/net/sourceforge/kolmafia/maximizer/Maximizer.java index be8a18a2268..4a5b0e75157 100644 --- a/src/net/sourceforge/kolmafia/maximizer/Maximizer.java +++ b/src/net/sourceforge/kolmafia/maximizer/Maximizer.java @@ -169,7 +169,7 @@ public static void maximize( boolean[] alreadyDone = new boolean[EquipmentManager.ALL_SLOTS]; - for (int slot = EquipmentManager.ACCESSORY1; slot <= EquipmentManager.ACCESSORY3; ++slot) { + for (int slot : EquipmentManager.ACCESSORY_SLOTS) { if (Maximizer.best.equipment[slot].getItemId() == ItemPool.SPECIAL_SAUCE_GLOVE && EquipmentManager.getEquipment(slot).getItemId() != ItemPool.SPECIAL_SAUCE_GLOVE) { equipScope = Maximizer.emitSlot(slot, equipScope, maxPrice, priceLevel, current); diff --git a/src/net/sourceforge/kolmafia/request/EquipmentRequest.java b/src/net/sourceforge/kolmafia/request/EquipmentRequest.java index 0cc6e91845f..7d6cfa24d93 100644 --- a/src/net/sourceforge/kolmafia/request/EquipmentRequest.java +++ b/src/net/sourceforge/kolmafia/request/EquipmentRequest.java @@ -1,5 +1,6 @@ package net.sourceforge.kolmafia.request; +import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sourceforge.kolmafia.AdventureResult; @@ -442,11 +443,12 @@ private void initializeFolderData(final AdventureResult folder, final int slot) return; } - for (int i = EquipmentManager.FOLDER1; i <= EquipmentManager.FOLDER5; i++) { - if (i != slot && folder.equals(EquipmentManager.getEquipment(i))) { - this.error = "You can't equip two of the same folder"; - return; - } + if (Arrays.stream(EquipmentManager.FOLDER_SLOTS) + .filter(s -> s != slot) + .mapToObj(EquipmentManager::getEquipment) + .anyMatch(folder::equals)) { + this.error = "You can't equip two of the same folder"; + return; } // Find out what item is being equipped @@ -749,17 +751,9 @@ private static int availableSticker() { return EquipmentRequest.availableSlot(STICKER_SLOTS); } - public static final int[] FOLDER_SLOTS = - new int[] { - EquipmentManager.FOLDER1, - EquipmentManager.FOLDER2, - EquipmentManager.FOLDER3, - EquipmentManager.FOLDER4, - EquipmentManager.FOLDER5, - }; - - public static final int availableFolder() { - return EquipmentRequest.availableSlot(FOLDER_SLOTS, KoLCharacter.inHighschool() ? 5 : 3); + public static int availableFolder() { + return EquipmentRequest.availableSlot( + EquipmentManager.FOLDER_SLOTS, KoLCharacter.inHighschool() ? 5 : 3); } public String getOutfitName() { @@ -1171,7 +1165,7 @@ private static boolean switchItem(final AdventureResult oldItem, final Adventure public static final void parseBedazzlements(final String responseText) { Matcher matcher = EquipmentRequest.STICKER_PATTERN.matcher(responseText); - for (int slot = EquipmentManager.STICKER1; slot <= EquipmentManager.STICKER3; ++slot) { + for (int slot : EquipmentManager.STICKER_SLOTS) { if (!matcher.find()) { return; // presumably doesn't have a sticker weapon } @@ -1830,16 +1824,12 @@ private static void donOutfit(final String responseText) { } // Calculate accessory fill order - int[] accessories = - new int[] { - EquipmentManager.ACCESSORY1, EquipmentManager.ACCESSORY2, EquipmentManager.ACCESSORY3 - }; int accessoryIndex = 0; // Consume unfilled slots from 1 to 3 - for (int slot = EquipmentManager.ACCESSORY1; slot <= EquipmentManager.ACCESSORY3; slot++) { + for (int slot : EquipmentManager.ACCESSORY_SLOTS) { if (oldEquipment[slot] == EquipmentRequest.UNEQUIP) { - accessories[accessoryIndex++] = slot; + EquipmentManager.ACCESSORY_SLOTS[accessoryIndex++] = slot; } } // Consume filled slots from 3 to 1 @@ -1848,7 +1838,7 @@ private static void donOutfit(final String responseText) { slot--) { if (oldEquipment[slot] != EquipmentRequest.UNEQUIP && newEquipment[slot] == EquipmentRequest.UNEQUIP) { - accessories[accessoryIndex++] = slot; + EquipmentManager.ACCESSORY_SLOTS[accessoryIndex++] = slot; } } @@ -1889,7 +1879,7 @@ private static void donOutfit(final String responseText) { // KoL error: four accessories continue; } - slot = accessories[accessoryIndex++]; + slot = EquipmentManager.ACCESSORY_SLOTS[accessoryIndex++]; break; case EquipmentManager.WEAPON: diff --git a/src/net/sourceforge/kolmafia/session/ChoiceControl.java b/src/net/sourceforge/kolmafia/session/ChoiceControl.java index f3c0bccd18b..a0093761770 100644 --- a/src/net/sourceforge/kolmafia/session/ChoiceControl.java +++ b/src/net/sourceforge/kolmafia/session/ChoiceControl.java @@ -6259,7 +6259,7 @@ else if (text.contains("pretty good understanding")) { // If you change the mode with the item equipped, you need to un-equip and re-equip it to // get the modifiers if (ChoiceManager.lastDecision >= 1 && ChoiceManager.lastDecision <= 3) { - for (int i = EquipmentManager.ACCESSORY1; i <= EquipmentManager.ACCESSORY3; ++i) { + for (int i : EquipmentManager.ACCESSORY_SLOTS) { AdventureResult item = EquipmentManager.getEquipment(i); if (item != null && item.getItemId() == ItemPool.BACKUP_CAMERA) { RequestThread.postRequest(new EquipmentRequest(EquipmentRequest.UNEQUIP, i)); diff --git a/src/net/sourceforge/kolmafia/session/EquipmentManager.java b/src/net/sourceforge/kolmafia/session/EquipmentManager.java index dd67d129bee..8b42480e991 100644 --- a/src/net/sourceforge/kolmafia/session/EquipmentManager.java +++ b/src/net/sourceforge/kolmafia/session/EquipmentManager.java @@ -89,6 +89,23 @@ public class EquipmentManager { private static final List> historyLists = new ArrayList<>(EquipmentManager.ALL_SLOTS); + public static final int[] FOLDER_SLOTS = + new int[] { + EquipmentManager.FOLDER1, + EquipmentManager.FOLDER2, + EquipmentManager.FOLDER3, + EquipmentManager.FOLDER4, + EquipmentManager.FOLDER5, + }; + + public static int[] ACCESSORY_SLOTS = + new int[] { + EquipmentManager.ACCESSORY1, EquipmentManager.ACCESSORY2, EquipmentManager.ACCESSORY3 + }; + + public static int[] STICKER_SLOTS = + new int[] {EquipmentManager.STICKER1, EquipmentManager.STICKER2, EquipmentManager.STICKER3}; + private static int fakeHandCount = 0; private static int stinkyCheeseLevel = 0; @@ -225,7 +242,7 @@ public static final void processResult(AdventureResult item) { // Make sure the current sticker in each slot remains in the list, even if // there are no more of that type in inventory. - for (int slot = EquipmentManager.STICKER1; slot <= EquipmentManager.STICKER3; ++slot) { + for (int slot : EquipmentManager.STICKER_SLOTS) { AdventureResult current = EquipmentManager.getEquipment(slot); AdventureResult.addResultToList(EquipmentManager.equipmentLists.get(slot), item); if (!EquipmentManager.equipmentLists.get(slot).contains(current)) { @@ -235,7 +252,7 @@ public static final void processResult(AdventureResult item) { } else if (consumeType == KoLConstants.CONSUME_FOLDER) { // Folders are similar to stickers - for (int slot = EquipmentManager.FOLDER1; slot <= EquipmentManager.FOLDER5; ++slot) { + for (int slot : EquipmentManager.FOLDER_SLOTS) { AdventureResult current = EquipmentManager.getEquipment(slot); AdventureResult.addResultToList(EquipmentManager.equipmentLists.get(slot), item); if (!EquipmentManager.equipmentLists.get(slot).contains(current)) { diff --git a/src/net/sourceforge/kolmafia/swingui/GearChangeFrame.java b/src/net/sourceforge/kolmafia/swingui/GearChangeFrame.java index 8566c842ef6..f0e4980d22c 100644 --- a/src/net/sourceforge/kolmafia/swingui/GearChangeFrame.java +++ b/src/net/sourceforge/kolmafia/swingui/GearChangeFrame.java @@ -27,6 +27,7 @@ import net.sourceforge.kolmafia.KoLCharacter; import net.sourceforge.kolmafia.KoLConstants; import net.sourceforge.kolmafia.KoLmafia; +import net.sourceforge.kolmafia.Modeable; import net.sourceforge.kolmafia.Modifiers; import net.sourceforge.kolmafia.RequestThread; import net.sourceforge.kolmafia.SpecialOutfit; @@ -36,7 +37,6 @@ import net.sourceforge.kolmafia.objectpool.ItemPool; import net.sourceforge.kolmafia.persistence.EquipmentDatabase; import net.sourceforge.kolmafia.persistence.ItemDatabase; -import net.sourceforge.kolmafia.preferences.Preferences; import net.sourceforge.kolmafia.request.EquipmentRequest; import net.sourceforge.kolmafia.request.FamiliarRequest; import net.sourceforge.kolmafia.session.EquipmentManager; @@ -138,139 +138,34 @@ public GearChangeFrame() { RequestThread.executeMethodAfterInitialization(this, "validateSelections"); } - public static void showModifiers(Object value, boolean isFamiliarItem) { - if (GearChangeFrame.INSTANCE == null) { - return; - } - - EquipmentTabPanel pane = - (EquipmentTabPanel) GearChangeFrame.INSTANCE.tabs.getSelectedComponent(); - + public static StringBuffer getModifiers( + Object value, final int slot, final boolean isCustomizablePanel, final int width) { + StringBuffer buff = new StringBuffer(); Modifiers mods; - if (value instanceof AdventureResult) { - AdventureResult item = (AdventureResult) value; - int itemId = item.getItemId(); - int familiarId = KoLCharacter.getFamiliar().getId(); - int consumption = ItemDatabase.getConsumptionType(itemId); - - if (itemId == -1) { - // Nothing for (none) - mods = null; - } - if (isFamiliarItem - && consumption != KoLConstants.EQUIP_FAMILIAR - && (familiarId == FamiliarPool.HATRACK || (familiarId == FamiliarPool.SCARECROW))) { - // Mad Hat Racks can equip hats. - // Fancypants Scarecrows can equip pants. - // - // In each case, there is a special familiar - // effect; the standard item modifiers are - // meaningless. - // - // Disembodied Hands can equip one-handed weapons. - // Left Mand Man can equip off-hand items. - // - // In each case, the standard item modifiers - // are in force. - mods = null; - } else { - Modifiers newMods = new Modifiers(); - newMods.add(Modifiers.getItemModifiers(itemId)); - - switch (itemId) { - case ItemPool.CROWN_OF_ED: - { - newMods.add(Modifiers.getModifiers("Edpiece", Preferences.getString("edPiece"))); - break; - } - case ItemPool.SNOW_SUIT: - { - newMods.add(Modifiers.getModifiers("Snowsuit", Preferences.getString("snowsuit"))); - break; - } - case ItemPool.KNOCK_OFF_RETRO_SUPERHERO_CAPE: - { - newMods.add( - Modifiers.getModifiers( - "RetroCape", - Preferences.getString("retroCapeSuperhero") - + " " - + Preferences.getString("retroCapeWashingInstructions"))); - break; - } - case ItemPool.BACKUP_CAMERA: - { - newMods.add( - Modifiers.getModifiers( - "BackupCamera", Preferences.getString("backupCameraMode"))); - break; - } - case ItemPool.COWBOY_BOOTS: - { - AdventureResult skin = EquipmentManager.getEquipment(EquipmentManager.BOOTSKIN); - AdventureResult spur = EquipmentManager.getEquipment(EquipmentManager.BOOTSPUR); - if (skin != null && skin != EquipmentRequest.UNEQUIP) { - newMods.add(Modifiers.getItemModifiers(skin.getItemId())); - } - if (spur != null && spur != EquipmentRequest.UNEQUIP) { - newMods.add(Modifiers.getItemModifiers(spur.getItemId())); - } - break; - } - case ItemPool.FOLDER_HOLDER: - { - for (int i = EquipmentManager.FOLDER1; i <= EquipmentManager.FOLDER5; ++i) { - AdventureResult folder = EquipmentManager.getEquipment(i); - if (folder != null && folder != EquipmentRequest.UNEQUIP) { - newMods.add(Modifiers.getItemModifiers(folder.getItemId())); - } - } - break; - } - case ItemPool.STICKER_CROSSBOW: - case ItemPool.STICKER_SWORD: - { - for (int i = EquipmentManager.STICKER1; i <= EquipmentManager.STICKER3; ++i) { - AdventureResult sticker = EquipmentManager.getEquipment(i); - if (sticker != null && sticker != EquipmentRequest.UNEQUIP) { - newMods.add(Modifiers.getItemModifiers(sticker.getItemId())); - } - } - break; - } - case ItemPool.CARD_SLEEVE: - { - AdventureResult card = EquipmentManager.getEquipment(EquipmentManager.CARDSLEEVE); - if (card != null && card != EquipmentRequest.UNEQUIP) { - newMods.add(Modifiers.getItemModifiers(card.getItemId())); - } - break; - } - case ItemPool.UNBREAKABLE_UMBRELLA: - { - newMods.add( - Modifiers.getModifiers( - "UnbreakableUmbrella", Preferences.getString("umbrellaState"))); - break; - } - case ItemPool.VAMPYRIC_CLOAKE: - newMods.applyVampyricCloakeModifiers(); - } - mods = newMods; - } - } else if (value instanceof SpecialOutfit) { - mods = Modifiers.getModifiers("Outfit", ((SpecialOutfit) value).getName()); - } else if (value instanceof FamiliarData - && pane == GearChangeFrame.INSTANCE.customizablePanel) { - mods = Modifiers.getModifiers("Throne", ((FamiliarData) value).getRace()); + if (value instanceof AdventureResult item) { + mods = new Modifiers(); + var taoFactor = KoLCharacter.hasSkill("Tao of the Terrapin") ? 2 : 1; + KoLCharacter.addItemAdjustment( + mods, + slot, + item, + EquipmentManager.allEquipment(), + KoLCharacter.getEnthroned(), + KoLCharacter.getBjorned(), + Modeable.getStateMap(), + true, + taoFactor); + } else if (value instanceof SpecialOutfit outfit) { + mods = Modifiers.getModifiers("Outfit", outfit.getName()); + } else if (value instanceof FamiliarData familiar && isCustomizablePanel) { + mods = Modifiers.getModifiers("Throne", familiar.getRace()); } else { - return; + return null; } if (mods == null) { - pane.getModifiersLabel().setText(""); - return; + return buff; } String name = mods.getString(Modifiers.INTRINSIC_EFFECT); @@ -281,9 +176,8 @@ public static void showModifiers(Object value, boolean isFamiliarItem) { mods = newMods; } - StringBuilder buff = new StringBuilder(); buff.append("
"); for (int i = 0; i < Modifiers.DOUBLE_MODIFIERS; ++i) { @@ -341,7 +235,32 @@ public static void showModifiers(Object value, boolean isFamiliarItem) { } buff.append("
"); - pane.getModifiersLabel().setText(buff.toString()); + return buff; + } + + public static void showModifiers(Object value) { + var slot = + (value instanceof AdventureResult item) + ? EquipmentManager.consumeFilterToEquipmentType(ItemDatabase.getConsumptionType(item)) + : -1; + showModifiers(value, slot); + } + + public static void showModifiers(Object value, final int slot) { + if (GearChangeFrame.INSTANCE == null) { + return; + } + + EquipmentTabPanel pane = + (EquipmentTabPanel) GearChangeFrame.INSTANCE.tabs.getSelectedComponent(); + + var isCustomizablePanel = pane == GearChangeFrame.INSTANCE.customizablePanel; + + StringBuffer buff = getModifiers(value, slot, isCustomizablePanel, pane.getModifiersWidth()); + + if (buff != null) { + pane.getModifiersLabel().setText(buff.toString()); + } } private abstract class EquipmentTabPanel extends GenericPanel { @@ -537,7 +456,7 @@ private void changeItems() { // Start with accessories - for (int i = EquipmentManager.ACCESSORY1; i <= EquipmentManager.ACCESSORY3; ++i) { + for (int i : EquipmentManager.ACCESSORY_SLOTS) { if (pieces[i] != null) { RequestThread.postRequest(new EquipmentRequest(pieces[i], i, true)); pieces[i] = null; @@ -844,10 +763,7 @@ private class EquipmentComboBox extends JComboBox { public EquipmentComboBox(final LockableListModel model, final int slot) { super(model); - DefaultListCellRenderer renderer = - (slot == EquipmentManager.FAMILIAR) - ? ListCellRendererFactory.getFamiliarEquipmentRenderer() - : ListCellRendererFactory.getUsableEquipmentRenderer(); + DefaultListCellRenderer renderer = ListCellRendererFactory.getUsableEquipmentRenderer(slot); this.setRenderer(renderer); this.addPopupMenuListener(new ChangeItemListener()); diff --git a/src/net/sourceforge/kolmafia/swingui/widget/ListCellRendererFactory.java b/src/net/sourceforge/kolmafia/swingui/widget/ListCellRendererFactory.java index e44e7e3b7e6..a1e3fc7f38a 100644 --- a/src/net/sourceforge/kolmafia/swingui/widget/ListCellRendererFactory.java +++ b/src/net/sourceforge/kolmafia/swingui/widget/ListCellRendererFactory.java @@ -74,7 +74,7 @@ public final Component getListCellRendererComponent( } if (isSelected) { - GearChangeFrame.showModifiers(value, false); + GearChangeFrame.showModifiers(value); } if (toHTMLFunction != null) { @@ -760,12 +760,15 @@ public Component getListCellRendererComponent( } } - public static final DefaultListCellRenderer getUsableEquipmentRenderer() { - return new UsableEquipmentRenderer(); + public static final DefaultListCellRenderer getUsableEquipmentRenderer(final int slot) { + return new UsableEquipmentRenderer(slot); } private static class UsableEquipmentRenderer extends DefaultListCellRenderer { - public UsableEquipmentRenderer() { + private int slot; + + public UsableEquipmentRenderer(final int slot) { + this.slot = slot; this.setOpaque(true); } @@ -781,23 +784,28 @@ public Component getListCellRendererComponent( } if (isSelected) { - GearChangeFrame.showModifiers(value, false); + GearChangeFrame.showModifiers(value, slot); } AdventureResult ar = (AdventureResult) value; int equipmentType = ItemDatabase.getConsumptionType(ar.getItemId()); int power = EquipmentDatabase.getPower(ar.getItemId()); - String stringForm = null; + String stringForm; - if (equipmentType == KoLConstants.EQUIP_FAMILIAR || ar.equals(EquipmentRequest.UNEQUIP)) { - if (ar.equals(EquipmentRequest.UNEQUIP)) { - stringForm = ar.getName(); - } else if (KoLCharacter.getFamiliar() != null && KoLCharacter.getFamiliar().canEquip(ar)) { - stringForm = ar.getName(); - } else { - stringForm = "" + ar.getName() + ""; + if (equipmentType == KoLConstants.EQUIP_FAMILIAR) { + stringForm = ar.getName(); + + String effect = Modifiers.getFamiliarEffect(ar.getName()); + if (effect != null) { + stringForm += " (" + effect + ")"; } + + if (KoLCharacter.getFamiliar() == null || !KoLCharacter.getFamiliar().canEquip(ar)) { + stringForm = "" + stringForm + ""; + } + } else if (ar.equals(EquipmentRequest.UNEQUIP)) { + stringForm = ar.getName(); } else { if (equipmentType == KoLConstants.EQUIP_ACCESSORY) { int count; @@ -838,45 +846,6 @@ public Component getListCellRendererComponent( } } - public static final DefaultListCellRenderer getFamiliarEquipmentRenderer() { - return new FamiliarEquipmentRenderer(); - } - - private static class FamiliarEquipmentRenderer extends DefaultListCellRenderer { - @Override - public Component getListCellRendererComponent( - final JList list, - final Object value, - final int index, - final boolean isSelected, - final boolean cellHasFocus) { - if (!(value instanceof AdventureResult)) { - return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - } - - if (isSelected) { - GearChangeFrame.showModifiers(value, true); - } - - AdventureResult ar = (AdventureResult) value; - String stringForm = ar.getName(); - - String effect = Modifiers.getFamiliarEffect(ar.getName()); - if (effect != null) { - stringForm += " (" + effect + ")"; - } - - if (KoLCharacter.getFamiliar() == null || !KoLCharacter.getFamiliar().canEquip(ar)) { - stringForm = "" + stringForm + ""; - } - - JLabel defaultComponent = - (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - defaultComponent.setText(stringForm); - return defaultComponent; - } - } - public static final DefaultListCellRenderer getFamiliarRenderer() { return new FamiliarRenderer(); } @@ -898,7 +867,7 @@ public Component getListCellRendererComponent( } if (isSelected) { - GearChangeFrame.showModifiers(value, false); + GearChangeFrame.showModifiers(value); } return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); diff --git a/src/net/sourceforge/kolmafia/textui/command/ConditionalStatement.java b/src/net/sourceforge/kolmafia/textui/command/ConditionalStatement.java index 9f2e8592016..eca2f46e987 100644 --- a/src/net/sourceforge/kolmafia/textui/command/ConditionalStatement.java +++ b/src/net/sourceforge/kolmafia/textui/command/ConditionalStatement.java @@ -1,5 +1,7 @@ package net.sourceforge.kolmafia.textui.command; +import java.util.Arrays; +import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sourceforge.kolmafia.AdventureResult; @@ -179,14 +181,10 @@ static final long lvalue(final String left) { } if (left.equals("stickers")) { - int count = 0; - for (int i = EquipmentManager.STICKER1; i <= EquipmentManager.STICKER3; ++i) { - AdventureResult item = EquipmentManager.getEquipment(i); - if (!EquipmentRequest.UNEQUIP.equals(item)) { - ++count; - } - } - return count; + return Arrays.stream(EquipmentManager.STICKER_SLOTS) + .mapToObj(EquipmentManager::getEquipment) + .filter(Predicate.not(EquipmentRequest.UNEQUIP::equals)) + .count(); } AdventureResult item = AbstractCommand.itemParameter(left); diff --git a/src/net/sourceforge/kolmafia/webui/ValhallaDecorator.java b/src/net/sourceforge/kolmafia/webui/ValhallaDecorator.java index c4d4edfc73c..3490e8aaa68 100644 --- a/src/net/sourceforge/kolmafia/webui/ValhallaDecorator.java +++ b/src/net/sourceforge/kolmafia/webui/ValhallaDecorator.java @@ -597,7 +597,7 @@ private static void switchFolderHolder(StringBuffer buffer) { } folderHolderBuffer.append("Folder Holder: "); - for (int slot = EquipmentManager.FOLDER1; slot <= EquipmentManager.FOLDER3; ++slot) { + for (int slot : EquipmentManager.FOLDER_SLOTS) { AdventureResult folder = EquipmentManager.getEquipment(slot); if (folder != null) { String name = folder.getName(); diff --git a/test/net/sourceforge/kolmafia/swingui/GearChangeFrameTest.java b/test/net/sourceforge/kolmafia/swingui/GearChangeFrameTest.java new file mode 100644 index 00000000000..be774a7cff9 --- /dev/null +++ b/test/net/sourceforge/kolmafia/swingui/GearChangeFrameTest.java @@ -0,0 +1,107 @@ +package net.sourceforge.kolmafia.swingui; + +import static internal.helpers.Player.withEquipped; +import static internal.helpers.Player.withFamiliar; +import static internal.helpers.Player.withProperty; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +import internal.helpers.Cleanups; +import net.sourceforge.kolmafia.KoLCharacter; +import net.sourceforge.kolmafia.objectpool.FamiliarPool; +import net.sourceforge.kolmafia.objectpool.ItemPool; +import net.sourceforge.kolmafia.session.EquipmentManager; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class GearChangeFrameTest { + @BeforeEach + void beforeEach() { + // Simulate logging out and back in again. + KoLCharacter.reset(""); + KoLCharacter.reset("GearChangeFrameTest"); + } + + @Nested + class ShowModifiers { + private static String modifierText(String text) { + return text.length() > 54 ? text.substring(29, text.length() - 25) : ""; + } + + @Test + void canShowBasicItemModifiers() { + var mods = + GearChangeFrame.getModifiers( + ItemPool.get(ItemPool.RAVIOLI_HAT), EquipmentManager.HAT, false, 1); + assertThat( + modifierText(mods.toString()), + equalTo( + "Dmg Absorption:
+10.00
Spell Dmg:
+1.00
")); + } + + @Test + void doesntShowItemModifiersForHatOnHatrack() { + var cleanups = new Cleanups(withFamiliar(FamiliarPool.HATRACK)); + try (cleanups) { + var mods = + GearChangeFrame.getModifiers( + ItemPool.get(ItemPool.RAVIOLI_HAT), EquipmentManager.FAMILIAR, false, 1); + assertThat(modifierText(mods.toString()), equalTo("")); + } + } + + @Test + void weaponsInOffhandSlotGetPowerDamage() { + var mods = + GearChangeFrame.getModifiers( + ItemPool.get(ItemPool.SEAL_CLUB), EquipmentManager.WEAPON, false, 1); + assertThat(modifierText(mods.toString()), equalTo("Weapon Dmg:
+1.50
")); + } + + @Test + void offhandsInOffhandSlotDoNotGetPowerDamage() { + var mods = + GearChangeFrame.getModifiers( + ItemPool.get(ItemPool.BONERDAGON_SKULL), EquipmentManager.OFFHAND, false, 1); + assertThat(modifierText(mods.toString()), equalTo("Spooky Dmg:
+5.00
")); + } + + @ParameterizedTest + @CsvSource({ + ",, Maximum HP:
+25.00
Maximum MP:
+25.00
", + "diamondback skin, nicksilver spurs, Monster Level:
+20.00
Item Drop:
+20.00
Maximum HP:
+25.00
Maximum MP:
+25.00
", + }) + void canShowCowboyBootsModifiers(String skin, String spurs, String expectedMods) { + var cleanups = new Cleanups(); + + if (skin != null) cleanups.add(withEquipped(EquipmentManager.BOOTSKIN, skin)); + if (spurs != null) cleanups.add(withEquipped(EquipmentManager.BOOTSPUR, spurs)); + + try (cleanups) { + var mods = + GearChangeFrame.getModifiers( + ItemPool.get(ItemPool.COWBOY_BOOTS), EquipmentManager.ACCESSORY1, false, 1); + assertThat(modifierText(mods.toString()), equalTo(expectedMods)); + } + } + + @ParameterizedTest + @CsvSource({ + ", Maximum HP:
+20.00
Maximum MP:
+20.00
Single Equip", + "meat, Meat Drop:
+50.00
Maximum HP:
+20.00
Maximum MP:
+20.00
Single Equip" + }) + void canShowBackupCameraModifiers(String setting, String expectedMods) { + var cleanups = new Cleanups(withProperty("backupCameraMode", setting == null ? "" : setting)); + + try (cleanups) { + var mods = + GearChangeFrame.getModifiers( + ItemPool.get(ItemPool.BACKUP_CAMERA), EquipmentManager.ACCESSORY1, false, 1); + assertThat(modifierText(mods.toString()), equalTo(expectedMods)); + } + } + } +}