diff --git a/forge-ai/src/main/java/forge/ai/AiBlockController.java b/forge-ai/src/main/java/forge/ai/AiBlockController.java index 9d24670da02..d8750635803 100644 --- a/forge-ai/src/main/java/forge/ai/AiBlockController.java +++ b/forge-ai/src/main/java/forge/ai/AiBlockController.java @@ -185,7 +185,7 @@ public class AiBlockController { List currentAttackers = new ArrayList<>(attackersLeft); for (final Card attacker : attackersLeft) { - if (StaticAbilityCantAttackBlock.getMinMaxBlocker(attacker, combat.getDefenderPlayerByAttacker(attacker)).getLeft() > 1) { + if (CombatUtil.getMinNumBlockersForAttacker(attacker, combat.getDefenderPlayerByAttacker(attacker)) > 1) { continue; } @@ -296,7 +296,7 @@ public class AiBlockController { // 6. Blockers that don't survive until the next turn anyway for (final Card attacker : attackersLeft) { - if (StaticAbilityCantAttackBlock.getMinMaxBlocker(attacker, combat.getDefenderPlayerByAttacker(attacker)).getLeft() > 1) { + if (CombatUtil.getMinNumBlockersForAttacker(attacker, combat.getDefenderPlayerByAttacker(attacker)) > 1) { continue; } @@ -537,7 +537,7 @@ public class AiBlockController { // Try to block a Menace attacker with two blockers, neither of which will die for (final Card attacker : attackersLeft) { - if (StaticAbilityCantAttackBlock.getMinMaxBlocker(attacker, combat.getDefenderPlayerByAttacker(attacker)).getLeft() <= 1) { + if (CombatUtil.getMinNumBlockersForAttacker(attacker, combat.getDefenderPlayerByAttacker(attacker)) <= 1) { continue; } @@ -593,7 +593,7 @@ public class AiBlockController { List killingBlockers; for (final Card attacker : attackersLeft) { - if (StaticAbilityCantAttackBlock.getMinMaxBlocker(attacker, combat.getDefenderPlayerByAttacker(attacker)).getLeft() > 1) { + if (CombatUtil.getMinNumBlockersForAttacker(attacker, combat.getDefenderPlayerByAttacker(attacker)) > 1) { continue; } if (ComputerUtilCombat.attackerHasThreateningAfflict(attacker, ai)) { @@ -642,7 +642,7 @@ public class AiBlockController { Card attacker = attackers.get(0); - if (StaticAbilityCantAttackBlock.getMinMaxBlocker(attacker, combat.getDefenderPlayerByAttacker(attacker)).getLeft() > 1 + if (CombatUtil.getMinNumBlockersForAttacker(attacker, combat.getDefenderPlayerByAttacker(attacker)) > 1 || attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.") || ComputerUtilCombat.attackerHasThreateningAfflict(attacker, ai)) { attackers.remove(0); @@ -691,7 +691,7 @@ public class AiBlockController { List currentAttackers = new ArrayList<>(attackersLeft); for (final Card attacker : currentAttackers) { - if (StaticAbilityCantAttackBlock.getMinMaxBlocker(attacker, combat.getDefenderPlayerByAttacker(attacker)).getLeft() <= 1) { + if (CombatUtil.getMinNumBlockersForAttacker(attacker, combat.getDefenderPlayerByAttacker(attacker)) <= 1) { continue; } List possibleBlockers = getPossibleBlockers(combat, attacker, blockersLeft, true); @@ -729,8 +729,7 @@ public class AiBlockController { // "Whenever CARDNAME becomes blocked, it gets +1/+1 until end of turn for each creature blocking it." for (final Card attacker : tramplingAttackers) { - - if (((StaticAbilityCantAttackBlock.getMinMaxBlocker(attacker, combat.getDefenderPlayerByAttacker(attacker)).getLeft() > 1) && !combat.isBlocked(attacker)) + if (CombatUtil.getMinNumBlockersForAttacker(attacker, combat.getDefenderPlayerByAttacker(attacker)) > combat.getBlockers(attacker).size() || attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.") || attacker.hasKeyword("CARDNAME can't be blocked unless all creatures defending player controls block it.")) { continue; @@ -829,7 +828,7 @@ public class AiBlockController { AiController aic = ((PlayerControllerAi) ai.getController()).getAi(); final int evalThresholdToken = aic.getIntProperty(AiProps.THRESHOLD_TOKEN_CHUMP_TO_SAVE_PLANESWALKER); - final int evalThresholdNonToken = aic.getIntProperty(AiProps.THRESHOLD_TOKEN_CHUMP_TO_SAVE_PLANESWALKER); + final int evalThresholdNonToken = aic.getIntProperty(AiProps.THRESHOLD_NONTOKEN_CHUMP_TO_SAVE_PLANESWALKER); final boolean onlyIfLethal = aic.getBooleanProperty(AiProps.CHUMP_TO_SAVE_PLANESWALKER_ONLY_ON_LETHAL); if (evalThresholdToken > 0 || evalThresholdNonToken > 0) { diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java index 0cbd29fb9ed..24628dd7044 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java @@ -1776,8 +1776,7 @@ public class ComputerUtilCombat { return true; } - // Attacker may kill the blocker before he can deal normal - // (secondary) damage + // Attacker may kill the blocker before he can deal normal (secondary) damage if (dealsFirstStrikeDamage(attacker, withoutAbilities, combat) && !blocker.hasKeyword(Keyword.INDESTRUCTIBLE)) { if (attackerDamage >= defenderLife) { @@ -1828,7 +1827,7 @@ public class ComputerUtilCombat { * @return a boolean. */ public static boolean blockerWouldBeDestroyed(Player ai, final Card blocker, Combat combat) { - // TODO THis function only checks if a single attacker at a time would destroy a blocker + // TODO This function only checks if a single attacker at a time would destroy a blocker // This needs to expand to tally up damage final List attackers = combat.getAttackersBlockedBy(blocker); @@ -2010,8 +2009,7 @@ public class ComputerUtilCombat { return true; } - // Attacker may kill the blocker before he can deal normal - // (secondary) damage + // Attacker may kill the blocker before he can deal normal (secondary) damage if (dealsFirstStrikeDamage(blocker, withoutAbilities, combat) && !attacker.hasKeyword(Keyword.INDESTRUCTIBLE)) { if (defenderDamage >= attackerLife) { diff --git a/forge-ai/src/main/java/forge/ai/SpecialCardAi.java b/forge-ai/src/main/java/forge/ai/SpecialCardAi.java index b7cd65bbd4e..2a95b1cda4f 100644 --- a/forge-ai/src/main/java/forge/ai/SpecialCardAi.java +++ b/forge-ai/src/main/java/forge/ai/SpecialCardAi.java @@ -413,7 +413,7 @@ public class SpecialCardAi { if (!isBlocking && combat.getDefenderByAttacker(source) instanceof Card) { int loyalty = combat.getDefenderByAttacker(source).getCounters(CounterEnumType.LOYALTY); int totalDamageToPW = 0; - for (Card atk : (combat.getAttackersOf(combat.getDefenderByAttacker(source)))) { + for (Card atk :combat.getAttackersOf(combat.getDefenderByAttacker(source))) { if (combat.isUnblocked(atk)) { totalDamageToPW += atk.getNetCombatDamage(); } diff --git a/forge-ai/src/main/java/forge/ai/ability/PlayAi.java b/forge-ai/src/main/java/forge/ai/ability/PlayAi.java index 8b57bfd3f92..b5fd974fca8 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PlayAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PlayAi.java @@ -26,7 +26,7 @@ public class PlayAi extends SpellAbilityAi { @Override protected boolean checkApiLogic(final Player ai, final SpellAbility sa) { - final String logic = sa.hasParam("AILogic") ? sa.getParam("AILogic") : ""; + final String logic = sa.getParamOrDefault("AILogic", ""); final Game game = ai.getGame(); final Card source = sa.getHostCard(); diff --git a/forge-ai/src/main/java/forge/ai/ability/SacrificeAi.java b/forge-ai/src/main/java/forge/ai/ability/SacrificeAi.java index 579f5564b19..5a94167b7bf 100644 --- a/forge-ai/src/main/java/forge/ai/ability/SacrificeAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/SacrificeAi.java @@ -121,7 +121,7 @@ public class SacrificeAi extends SpellAbilityAi { // Only cast it if Human has the full amount of valid // Only cast it if AI doesn't have the full amount of Valid // TODO: Cast if the type is favorable: my "worst" valid is worse than his "worst" valid - final String num = sa.hasParam("Amount") ? sa.getParam("Amount") : "1"; + final String num = sa.getParamOrDefault("Amount", "1"); int amount = AbilityUtils.calculateAmount(source, num, sa); if (num.equals("X") && sa.getSVar(num).equals("Count$xPaid")) { diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 0427cb86e2f..e0969ec98a9 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -1482,7 +1482,7 @@ public class AbilityUtils { final Card source = sa.getHostCard(); // The player who has the chance to cancel the ability - final String pays = sa.hasParam("UnlessPayer") ? sa.getParam("UnlessPayer") : "TargetedController"; + final String pays = sa.getParamOrDefault("UnlessPayer", "TargetedController"); final FCollectionView allPayers = getDefinedPlayers(sa.getHostCard(), pays, sa); final String resolveSubs = sa.getParam("UnlessResolveSubs"); // no value means 'Always' final boolean execSubsWhenPaid = "WhenPaid".equals(resolveSubs) || StringUtils.isBlank(resolveSubs); @@ -1565,7 +1565,7 @@ public class AbilityUtils { " ", ""), sa); //Check for XColor ManaCostBeingPaid toPay = new ManaCostBeingPaid(ManaCost.ZERO); - byte xColor = ManaAtom.fromName(sa.hasParam("UnlessXColor") ? sa.getParam("UnlessXColor") : "1"); + byte xColor = ManaAtom.fromName(sa.getParamOrDefault("UnlessXColor", "1")); toPay.increaseShard(ManaCostShard.valueOf(xColor), xCost); cost = new Cost(toPay.toManaCost(), true); } diff --git a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java index fe26fa04952..5935f0d8053 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -261,7 +261,7 @@ public abstract class SpellAbilityEffect { boolean your = location.startsWith("Your"); boolean combat = location.endsWith("Combat"); - String desc = sa.hasParam("AtEOTDesc") ? sa.getParam("AtEOTDesc") : ""; + String desc = sa.getParamOrDefault("AtEOTDesc", ""); if (your) { location = location.substring("Your".length()); diff --git a/forge-game/src/main/java/forge/game/ability/effects/BalanceEffect.java b/forge-game/src/main/java/forge/game/ability/effects/BalanceEffect.java index 25666653d33..c473fa857c7 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/BalanceEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/BalanceEffect.java @@ -33,7 +33,7 @@ public class BalanceEffect extends SpellAbilityEffect { Player activator = sa.getActivatingPlayer(); Card source = sa.getHostCard(); Game game = activator.getGame(); - String valid = sa.hasParam("Valid") ? sa.getParam("Valid") : "Card"; + String valid = sa.getParamOrDefault("Valid", "Card"); ZoneType zone = sa.hasParam("Zone") ? ZoneType.smartValueOf(sa.getParam("Zone")) : ZoneType.Battlefield; int min = Integer.MAX_VALUE; diff --git a/forge-game/src/main/java/forge/game/ability/effects/DiscardEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DiscardEffect.java index adeb96ef12b..cc7eb1f02ab 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DiscardEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DiscardEffect.java @@ -182,7 +182,7 @@ public class DiscardEffect extends SpellAbilityEffect { boolean runDiscard = !sa.hasParam("Optional") || p.getController().confirmAction(sa, PlayerActionConfirmMode.Random, message); if (runDiscard) { - final String valid = sa.hasParam("DiscardValid") ? sa.getParam("DiscardValid") : "Card"; + final String valid = sa.getParamOrDefault("DiscardValid", "Card"); List list = CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), valid, source.getController(), source, sa); list = CardLists.filter(list, Presets.NON_TOKEN); CardCollection toDiscard = new CardCollection(); @@ -250,7 +250,7 @@ public class DiscardEffect extends SpellAbilityEffect { dPHand = p.getController().chooseCardsToRevealFromHand(amount, amount, dPHand); } - final String valid = sa.hasParam("DiscardValid") ? sa.getParam("DiscardValid") : "Card"; + final String valid = sa.getParamOrDefault("DiscardValid", "Card"); String[] dValid = valid.split(","); CardCollection validCards = CardLists.getValidCards(dPHand, dValid, source.getController(), source, sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/FlipCoinEffect.java b/forge-game/src/main/java/forge/game/ability/effects/FlipCoinEffect.java index 19b06893824..89324718c2a 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/FlipCoinEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/FlipCoinEffect.java @@ -220,7 +220,7 @@ public class FlipCoinEffect extends SpellAbilityEffect { * @return a boolean. */ public static boolean flipCoinCall(final Player caller, final SpellAbility sa, final int multiplier) { - String varName = sa.hasParam("SaveNumFlipsToSVar") ? sa.getParam("SaveNumFlipsToSVar") : "X"; + String varName = sa.getParamOrDefault("SaveNumFlipsToSVar", "X"); return flipCoinCall(caller, sa, multiplier, varName); } public static boolean flipCoinCall(final Player caller, final SpellAbility sa, final int multiplier, final String varName) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/MakeCardEffect.java b/forge-game/src/main/java/forge/game/ability/effects/MakeCardEffect.java index af07f8984ef..d7f49216730 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/MakeCardEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/MakeCardEffect.java @@ -15,7 +15,7 @@ public class MakeCardEffect extends SpellAbilityEffect { final Player player = sa.getActivatingPlayer(); final Game game = player.getGame(); - String name = sa.hasParam("Name") ? sa.getParam("Name") : sa.getHostCard().getName(); + String name = sa.getParamOrDefault("Name", sa.getHostCard().getName()); if (name.equals("ChosenName")) { name = sa.getHostCard().getChosenName(); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java index 4c5c49909b6..a706196bc7b 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java @@ -292,7 +292,7 @@ public class PumpEffect extends SpellAbilityEffect { } } if (sa.hasParam("RandomKeyword")) { - final String num = sa.hasParam("RandomKWNum") ? sa.getParam("RandomKWNum") : "1"; + final String num = sa.getParamOrDefault("RandomKWNum", "1"); final int numkw = AbilityUtils.calculateAmount(host, num, sa); List choice = Lists.newArrayList(); List total = Lists.newArrayList(keywords); diff --git a/forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java index 53ce96f4059..2c949fa94dd 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java @@ -32,7 +32,7 @@ public class RestartGameEffect extends SpellAbilityEffect { ZoneType leaveZone = ZoneType.smartValueOf(sa.hasParam("RestrictFromZone") ? sa.getParam("RestrictFromZone") : null); restartZones.remove(leaveZone); - String leaveRestriction = sa.hasParam("RestrictFromValid") ? sa.getParam("RestrictFromValid") : "Card"; + String leaveRestriction = sa.getParamOrDefault("RestrictFromValid", "Card"); //Card.resetUniqueNumber(); // need this code here, otherwise observables fail diff --git a/forge-game/src/main/java/forge/game/combat/AttackingBand.java b/forge-game/src/main/java/forge/game/combat/AttackingBand.java index c2ffa3cb808..e509c577361 100644 --- a/forge-game/src/main/java/forge/game/combat/AttackingBand.java +++ b/forge-game/src/main/java/forge/game/combat/AttackingBand.java @@ -12,11 +12,11 @@ import forge.game.keyword.Keyword; public class AttackingBand { private CardCollection attackers = new CardCollection(); private Boolean blocked = null; // even if all blockers were killed before FS or CD, band remains blocked - + public AttackingBand(final List band) { attackers.addAll(band); } - + public AttackingBand(final Card card) { attackers.add(card); } @@ -25,14 +25,13 @@ public class AttackingBand { public void addAttacker(Card card) { attackers.add(card); } public void removeAttacker(Card card) { attackers.remove(card); } - public static boolean isValidBand(List band, boolean shareDamage) { if (band.isEmpty()) { // An empty band is not a valid band return false; } - + int bandingCreatures = CardLists.getKeyword(band, Keyword.BANDING).size(); int neededBandingCreatures = shareDamage ? 1 : band.size() - 1; if (neededBandingCreatures <= bandingCreatures) { @@ -40,19 +39,19 @@ public class AttackingBand { // For sharing damage, only one needs to be Banding return true; } - + // Legends lands, Master of the Hunt, Old Fogey (just in case) // Since Bands With Other is a dead keyword, no major reason to make this more generic // But if someone is super motivated, feel free to do it. Just make sure you update Tolaria and Shelkie Brownie String[] bandsWithString = { "Bands with Other Legendary Creatures", "Bands with Other Creatures named Wolves of the Hunt", "Bands with Other Dinosaurs" }; String[] validString = { "Legendary.Creature", "Creature.namedWolves of the Hunt", "Dinosaur" }; - + Card source = band.get(0); for (int i = 0; i < bandsWithString.length; i++) { String keyword = bandsWithString[i]; String valid = validString[i]; - + // Check if a bands with other keyword exists in band, and each creature in the band fits the valid quality if (!CardLists.getKeyword(band, keyword).isEmpty() && CardLists.getValidCards(band, valid, source.getController(), source, null).size() == band.size()) { @@ -69,10 +68,9 @@ public class AttackingBand { if (card != null) { newBand.add(card); } - + return isValidBand(newBand, false); } - public boolean contains(Card c) { return attackers.contains(c); @@ -89,7 +87,7 @@ public class AttackingBand { // TODO Auto-generated method stub return attackers.isEmpty(); } - + /* (non-Javadoc) * @see java.lang.Object#toString() */ @@ -97,5 +95,5 @@ public class AttackingBand { public String toString() { return String.format("%s %s", attackers.toString(), blocked == null ? " ? " : blocked.booleanValue() ? ">||" : ">>>" ); } - + } diff --git a/forge-game/src/main/java/forge/game/combat/Combat.java b/forge-game/src/main/java/forge/game/combat/Combat.java index 88f41887e1c..75eddb8aea7 100644 --- a/forge-game/src/main/java/forge/game/combat/Combat.java +++ b/forge-game/src/main/java/forge/game/combat/Combat.java @@ -345,13 +345,6 @@ public class Combat { return result; } - public final CardCollection getBlockers(final Card card) { - // If requesting the ordered blocking list pass true, directly. - AttackingBand band = getBandOfAttacker(card); - Collection blockers = blockedBands.get(band); - return blockers == null ? new CardCollection() : new CardCollection(blockers); - } - public final boolean isBlocked(final Card attacker) { AttackingBand band = getBandOfAttacker(attacker); return band != null && Boolean.TRUE.equals(band.isBlocked()); @@ -408,6 +401,10 @@ public class Combat { return result; } + public final CardCollection getBlockers(final Card card) { + // If requesting the ordered blocking list pass true, directly. + return getBlockers(getBandOfAttacker(card)); + } public final CardCollection getBlockers(final AttackingBand band) { Collection blockers = blockedBands.get(band); return blockers == null ? new CardCollection() : new CardCollection(blockers); @@ -512,8 +509,7 @@ public class Combat { final CardCollection oldBlockers = blockersOrderedForDamageAssignment.get(attacker); if (oldBlockers == null || oldBlockers.isEmpty()) { blockersOrderedForDamageAssignment.put(attacker, new CardCollection(blocker)); - } - else { + } else { CardCollection orderedBlockers = playerWhoAttacks.getController().orderBlocker(attacker, blocker, oldBlockers); blockersOrderedForDamageAssignment.put(attacker, orderedBlockers); } diff --git a/forge-game/src/main/java/forge/game/combat/CombatUtil.java b/forge-game/src/main/java/forge/game/combat/CombatUtil.java index 156f3686426..ea49ca6afd5 100644 --- a/forge-game/src/main/java/forge/game/combat/CombatUtil.java +++ b/forge-game/src/main/java/forge/game/combat/CombatUtil.java @@ -501,7 +501,7 @@ public class CombatUtil { return true; } - if ( combat != null ) { + if (combat != null) { if (StaticAbilityCantAttackBlock.getMinMaxBlocker(attacker, defendingPlayer).getRight() == combat.getBlockers(attacker).size()) { return false; } @@ -763,7 +763,7 @@ public class CombatUtil { for (final Card attacker : attackers) { if (canBlock(attacker, blocker, combat)) { boolean must = true; - if (StaticAbilityCantAttackBlock.getMinMaxBlocker(attacker, defending).getLeft() > 1) { + if (getMinNumBlockersForAttacker(attacker, defending) > 1) { final List possibleBlockers = Lists.newArrayList(defendersArmy); possibleBlockers.remove(blocker); if (!canBeBlocked(attacker, possibleBlockers, combat)) { @@ -875,7 +875,7 @@ public class CombatUtil { Player defendingPlayer = combat.getDefenderPlayerByAttacker(attacker); - if (StaticAbilityCantAttackBlock.getMinMaxBlocker(attacker, defendingPlayer).getLeft() > 1) { + if (getMinNumBlockersForAttacker(attacker, defendingPlayer) > 1) { final List blockers = defendingPlayer.getCreaturesInPlay(); blockers.remove(blocker); if (!canBeBlocked(attacker, blockers, combat)) { @@ -894,7 +894,7 @@ public class CombatUtil { && combat.isAttacking(attacker)) { boolean canBe = true; Player defendingPlayer = combat.getDefenderPlayerByAttacker(attacker); - if (StaticAbilityCantAttackBlock.getMinMaxBlocker(attacker, defendingPlayer).getLeft() > 1) { + if (getMinNumBlockersForAttacker(attacker, defendingPlayer) > 1) { final List blockers = freeBlockers != null ? new CardCollection(freeBlockers) : defendingPlayer.getCreaturesInPlay(); blockers.remove(blocker); if (!canBeBlocked(attacker, blockers, combat)) { @@ -1099,4 +1099,4 @@ public class CombatUtil { public static int getMinNumBlockersForAttacker(Card attacker, Player defender) { return StaticAbilityCantAttackBlock.getMinMaxBlocker(attacker, defender).getLeft(); } -} // end class CombatUtil +}