From 23875bcc16a3b2f06ae01534b0d154ab2676a460 Mon Sep 17 00:00:00 2001 From: tool4ever Date: Sat, 25 Mar 2023 11:23:02 +0100 Subject: [PATCH] Support Supertype for Deckhints (#2750) --- .../src/main/java/forge/card/DeckHints.java | 6 +++- .../ability/effects/ChooseCardEffect.java | 5 +-- .../ability/effects/ChooseSourceEffect.java | 5 +-- .../game/ability/effects/SetStateEffect.java | 8 ++--- .../cardsfolder/t/tyvar_jubilant_brawler.txt | 2 +- .../src/main/java/forge/player/HumanPlay.java | 36 +++++-------------- .../forge/player/PlayerControllerHuman.java | 3 +- 7 files changed, 19 insertions(+), 46 deletions(-) diff --git a/forge-core/src/main/java/forge/card/DeckHints.java b/forge-core/src/main/java/forge/card/DeckHints.java index e6ce28f9fea..6af5a15dfad 100644 --- a/forge-core/src/main/java/forge/card/DeckHints.java +++ b/forge-core/src/main/java/forge/card/DeckHints.java @@ -201,7 +201,11 @@ public class DeckHints { Predicate op; if (t.contains(".")) { String[] typeParts = t.split("\\."); - op = Predicates.and(CardRulesPredicates.coreType(true, typeParts[0]), CardRulesPredicates.subType(typeParts[1])); + if (CardType.isASupertype(typeParts[0])) { + op = Predicates.and(CardRulesPredicates.superType(true, typeParts[0]), CardRulesPredicates.coreType(true, typeParts[1])); + } else { + op = Predicates.and(CardRulesPredicates.coreType(true, typeParts[0]), CardRulesPredicates.subType(typeParts[1])); + } } else { op = CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, t); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChooseCardEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChooseCardEffect.java index 263df8d86f3..c40b0273535 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChooseCardEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChooseCardEffect.java @@ -7,7 +7,6 @@ import com.google.common.collect.Sets; import forge.game.player.DelayedReveal; import forge.game.player.PlayerView; import forge.util.CardTranslation; -import org.apache.commons.lang3.StringUtils; import forge.card.CardType; import forge.game.Game; @@ -86,9 +85,7 @@ public class ChooseCardEffect extends SpellAbilityEffect { final String amountValue = sa.getParamOrDefault("Amount", "1"); int validAmount; - if (StringUtils.isNumeric(amountValue)) { - validAmount = Integer.parseInt(amountValue); - } else if (amountValue.equals("Random")) { + if (amountValue.equals("Random")) { validAmount = Aggregates.randomInt(0, choices.size()); } else { validAmount = AbilityUtils.calculateAmount(host, amountValue, sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChooseSourceEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChooseSourceEffect.java index 5f3ea984730..27668d41797 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChooseSourceEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChooseSourceEffect.java @@ -2,8 +2,6 @@ package forge.game.ability.effects; import java.util.List; -import org.apache.commons.lang3.StringUtils; - import forge.game.Game; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; @@ -125,8 +123,7 @@ public class ChooseSourceEffect extends SpellAbilityEffect { return; } - final String numericAmount = sa.getParamOrDefault("Amount", "1"); - final int validAmount = StringUtils.isNumeric(numericAmount) ? Integer.parseInt(numericAmount) : AbilityUtils.calculateAmount(host, numericAmount, sa); + final int validAmount = AbilityUtils.calculateAmount(host, sa.getParamOrDefault("Amount", "1"), sa); for (final Player p : tgtPlayers) { if (!p.isInGame()) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/SetStateEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SetStateEffect.java index f0c5f9cb494..ad1085d9abc 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SetStateEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SetStateEffect.java @@ -18,7 +18,6 @@ import forge.game.zone.ZoneType; import forge.util.Lang; import forge.util.Localizer; import forge.util.TextUtil; -import org.apache.commons.lang3.StringUtils; import java.util.Map; @@ -63,11 +62,8 @@ public class SetStateEffect extends SpellAbilityEffect { CardCollectionView choices = game.getCardsIn(ZoneType.Battlefield); choices = CardLists.getValidCards(choices, sa.getParam("Choices"), p, host, sa); - final String numericAmount = sa.getParamOrDefault("Amount", "1"); - final int validAmount = StringUtils.isNumeric(numericAmount) ? Integer.parseInt(numericAmount) : - AbilityUtils.calculateAmount(host, numericAmount, sa); - final int minAmount = sa.hasParam("MinAmount") ? Integer.parseInt(sa.getParam("MinAmount")) : - validAmount; + final int validAmount = AbilityUtils.calculateAmount(host, sa.getParamOrDefault("Amount", "1"), sa); + final int minAmount = sa.hasParam("MinAmount") ? Integer.parseInt(sa.getParam("MinAmount")) : validAmount; if (validAmount <= 0) { return; diff --git a/forge-gui/res/cardsfolder/t/tyvar_jubilant_brawler.txt b/forge-gui/res/cardsfolder/t/tyvar_jubilant_brawler.txt index 58afcd1bf85..d2377628c35 100644 --- a/forge-gui/res/cardsfolder/t/tyvar_jubilant_brawler.txt +++ b/forge-gui/res/cardsfolder/t/tyvar_jubilant_brawler.txt @@ -4,7 +4,7 @@ Types:Legendary Planeswalker Tyvar Loyalty:3 S:Mode$ ActivateAbilityAsIfHaste | ValidCard$ Creature.YouCtrl | Description$ You may activate abilities of creatures you control as though those creatures had haste. A:AB$ Untap | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature | TargetMin$ 0 | TargetMax$ 1 | SpellDescription$ Untap up to one target creature. -A:AB$ Mill | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | NumCards$ 3 | Defined$ You | SubAbility$ DBChange | SpellDescription$ Mill three cards, then you may return a creature card with mana value 2 or less from your graveyard to the battlefield. +A:AB$ Mill | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | NumCards$ 3 | Defined$ You | SubAbility$ DBChange | SpellDescription$ Mill three cards, then you may return a creature card with mana value 2 or less from your graveyard to the battlefield. SVar:DBChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | SelectPrompt$ Choose a creature card with mana value 2 or less | Hidden$ True | ChangeType$ Creature.YouOwn+cmcLE2 DeckHas:Ability$Graveyard|Mill DeckHints:Ability$Graveyard diff --git a/forge-gui/src/main/java/forge/player/HumanPlay.java b/forge-gui/src/main/java/forge/player/HumanPlay.java index 31566a9ebdd..5228ade69dd 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlay.java +++ b/forge-gui/src/main/java/forge/player/HumanPlay.java @@ -1,13 +1,11 @@ package forge.player; - import java.util.ArrayList; import java.util.List; import forge.ImageKeys; import forge.game.cost.*; import forge.game.spellability.SpellAbilityStackInstance; -import org.apache.commons.lang3.StringUtils; import com.google.common.collect.Iterables; @@ -198,24 +196,6 @@ public class HumanPlay { req.playAbility(!useOldTargets, false, true); } - private static int getAmountFromPart(CostPart part, Card source, SpellAbility sourceAbility) { - String amountString = part.getAmount(); - return StringUtils.isNumeric(amountString) ? Integer.parseInt(amountString) : AbilityUtils.calculateAmount(source, amountString, sourceAbility); - } - - /** - * TODO: Write javadoc for this method. - * @param part - * @param source - * @param sourceAbility - * @return - */ - private static int getAmountFromPartX(CostPart part, Card source, SpellAbility sourceAbility) { - String amountString = part.getAmount(); - // Probably should just be - - return AbilityUtils.calculateAmount(source, amountString, sourceAbility); - } - /** *

* payCostDuringAbilityResolve. @@ -327,7 +307,7 @@ public class HumanPlay { list = new CardCollection(p.getCardsIn(from)); } list = CardLists.getValidCards(list, part.getType().split(";"), p, source, sourceAbility); - final int nNeeded = getAmountFromPart(part, source, sourceAbility); + final int nNeeded = part.getAbilityAmount(sourceAbility); if (list.size() < nNeeded) { return false; } @@ -380,7 +360,7 @@ public class HumanPlay { if (part.getType().equals("All")) { payList.addAll(saList); } else { - final int c = getAmountFromPart(part, source, sourceAbility); + final int c = part.getAbilityAmount(sourceAbility); if (saList.size() < c) { return false; @@ -466,12 +446,12 @@ public class HumanPlay { } else if (part instanceof CostReturn) { CardCollectionView list = CardLists.getValidCards(p.getCardsIn(ZoneType.Battlefield), part.getType(), p, source, sourceAbility); - int amount = getAmountFromPartX(part, source, sourceAbility); + int amount = part.getAbilityAmount(sourceAbility); boolean hasPaid = payCostPart(controller, p, sourceAbility, hcd.isEffect(), (CostPartWithList)part, amount, list, Localizer.getInstance().getMessage("lblReturnToHand") + orString); if (!hasPaid) { return false; } } else if (part instanceof CostDiscard) { - int amount = getAmountFromPartX(part, source, sourceAbility); + int amount = part.getAbilityAmount(sourceAbility); if ("Hand".equals(part.getType())) { if (!p.getController().confirmPayment(part, Localizer.getInstance().getMessage("lblDoYouWantDiscardYourHand"), sourceAbility)) { return false; @@ -493,14 +473,14 @@ public class HumanPlay { else if (part instanceof CostReveal) { CostReveal costReveal = (CostReveal) part; CardCollectionView list = CardLists.getValidCards(p.getCardsIn(costReveal.getRevealFrom()), part.getType(), p, source, sourceAbility); - int amount = getAmountFromPartX(part, source, sourceAbility); + int amount = part.getAbilityAmount(sourceAbility); boolean hasPaid = payCostPart(controller, p, sourceAbility, hcd.isEffect(), (CostPartWithList)part, amount, list, Localizer.getInstance().getMessage("lblReveal") + orString); if (!hasPaid) { return false; } } else if (part instanceof CostTapType) { CardCollectionView list = CardLists.getValidCards(p.getCardsIn(ZoneType.Battlefield), part.getType(), p, source, sourceAbility); list = CardLists.filter(list, Presets.UNTAPPED); - int amount = getAmountFromPartX(part, source, sourceAbility); + int amount = part.getAbilityAmount(sourceAbility); boolean hasPaid = payCostPart(controller, p, sourceAbility, hcd.isEffect(), (CostPartWithList)part, amount, list, Localizer.getInstance().getMessage("lblTap") + orString); if (!hasPaid) { return false; } } @@ -511,7 +491,7 @@ public class HumanPlay { } else if (part instanceof CostPayEnergy) { CounterType counterType = CounterType.get(CounterEnumType.ENERGY); - int amount = getAmountFromPartX(part, source, sourceAbility); + int amount = part.getAbilityAmount(sourceAbility); if (!mandatory && !p.getController().confirmPayment(part, Localizer.getInstance().getMessage("lblDoYouWantSpendNTargetTypeCounter", String.valueOf(amount), counterType.getName()), sourceAbility)) { return false; @@ -525,7 +505,7 @@ public class HumanPlay { else if (part instanceof CostPayShards) { CounterType counterType = CounterType.get(CounterEnumType.MANASHARDS); - int amount = getAmountFromPartX(part, source, sourceAbility); + int amount = part.getAbilityAmount(sourceAbility); if (!mandatory && !p.getController().confirmPayment(part, Localizer.getInstance().getMessage("lblDoYouWantSpendNTargetTypeCounter", String.valueOf(amount), counterType.getName()), sourceAbility)) { return false; diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 0389e02ccaf..01c3339e071 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -1850,8 +1850,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } @Override - public ReplacementEffect chooseSingleReplacementEffect(final String prompt, - final List possibleReplacers) { + public ReplacementEffect chooseSingleReplacementEffect(final String prompt, final List possibleReplacers) { final ReplacementEffect first = possibleReplacers.get(0); if (possibleReplacers.size() == 1) { return first;