diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 02f19fc12f2..a1f0ffd1fcc 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -432,7 +432,7 @@ public class ComputerUtilCard { * @param list * @return a {@link forge.game.card.Card} object. */ - public static Card getBestCreatureToBounceAI(final CardCollectionView list) { + public static Card getBestCreatureToBounceAI(final Iterable list) { if (Iterables.size(list) == 1) { return Iterables.get(list, 0); } diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index f420cecf3e8..2458dcf3613 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -86,7 +86,7 @@ public class PlayerControllerAi extends PlayerController { @Override public SpellAbility getAbilityToPlay(Card hostCard, List abilities, ITriggerEvent triggerEvent) { - if (abilities.size() == 0) { + if (abilities.isEmpty()) { return null; } return abilities.get(0); diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java index fd02a6cb98e..bf263a06eed 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java @@ -1216,7 +1216,7 @@ public class ChangeZoneAi extends SpellAbilityAi { } } if (choice == null) { // can't find anything left - if (sa.getTargets().size() == 0 || !sa.isTargetNumberValid()) { + if (sa.getTargets().isEmpty() || !sa.isTargetNumberValid()) { if (!mandatory) { sa.resetTargets(); } @@ -1432,7 +1432,7 @@ public class ChangeZoneAi extends SpellAbilityAi { final ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination")); final TargetRestrictions tgt = sa.getTargetRestrictions(); - CardCollection list = new CardCollection(CardUtil.getValidCardsToTarget(tgt, sa)); + List list = CardUtil.getValidCardsToTarget(tgt, sa); if (list.isEmpty()) { return false; diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java index 07fc3bbaf96..010b8f0fd9c 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java @@ -5,7 +5,6 @@ import java.util.Map; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; import forge.ai.AiController; import forge.ai.AiPlayerPredicates; @@ -197,8 +196,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi { // mass zone change for creatures: if in dire danger, do it; otherwise, only do it if the opponent's // creatures are better in value - if ((CardLists.getNotType(oppType, "Creature").size() == 0) - && (CardLists.getNotType(computerType, "Creature").size() == 0)) { + if (CardLists.getNotType(oppType, "Creature").isEmpty() && CardLists.getNotType(computerType, "Creature").isEmpty()) { if (game.getCombat() != null && ComputerUtilCombat.lifeInSeriousDanger(ai, game.getCombat())) { if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS) && game.getPhaseHandler().getPlayerTurn().isOpponentOf(ai)) { @@ -225,17 +223,15 @@ public class ChangeZoneAllAi extends SpellAbilityAi { } else if (origin.equals(ZoneType.Graveyard)) { if (sa.usesTargeting()) { // search targetable Opponents - final Iterable oppList = Iterables.filter(ai.getOpponents(), - PlayerPredicates.isTargetableBy(sa)); + final PlayerCollection oppList = ai.getOpponents().filter(PlayerPredicates.isTargetableBy(sa)); - if (Iterables.isEmpty(oppList)) { + if (oppList.isEmpty()) { return false; } // get the one with the most in graveyard // zone is visible so evaluate which would be hurt the most - Player oppTarget = Collections.max(Lists.newArrayList(oppList), - AiPlayerPredicates.compareByZoneValue(sa.getParam("ChangeType"), origin, sa)); + Player oppTarget = Collections.max(oppList, AiPlayerPredicates.compareByZoneValue(sa.getParam("ChangeType"), origin, sa)); // set the target if (!oppTarget.getCardsIn(ZoneType.Graveyard).isEmpty()) { @@ -270,18 +266,14 @@ public class ChangeZoneAllAi extends SpellAbilityAi { return (curHandSize + minAdv - 1 < numExiledWithSrc) || (!noDiscard && numExiledWithSrc >= ai.getMaxHandSize()); } } else if (origin.equals(ZoneType.Stack)) { - // time stop can do something like this: - // Origin$ Stack | Destination$ Exile | SubAbility$ DBSkip - // DBSKipToPhase | DB$SkipToPhase | Phase$ Cleanup - // otherwise, this situation doesn't exist + // TODO return false; } if (destination.equals(ZoneType.Battlefield)) { if (sa.hasParam("GainControl")) { // Check if the cards are valuable enough - if (CardLists.getNotType(oppType, "Creature").size() == 0 - && CardLists.getNotType(computerType, "Creature").size() == 0) { + if (CardLists.getNotType(oppType, "Creature").isEmpty() && CardLists.getNotType(computerType, "Creature").isEmpty()) { if ((ComputerUtilCard.evaluateCreatureList(computerType) + ComputerUtilCard .evaluateCreatureList(oppType)) < 400) { return false; @@ -294,8 +286,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi { } } else { // don't activate if human gets more back than AI does - if ((CardLists.getNotType(oppType, "Creature").size() == 0) - && (CardLists.getNotType(computerType, "Creature").size() == 0)) { + if (CardLists.getNotType(oppType, "Creature").isEmpty() && CardLists.getNotType(computerType, "Creature").isEmpty()) { if (ComputerUtilCard.evaluateCreatureList(computerType) <= (ComputerUtilCard .evaluateCreatureList(oppType) + 100)) { return false; @@ -354,8 +345,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi { return true; // if AI creature is better than Human Creature - return ComputerUtilCard.evaluateCreatureList(aiCards) >= ComputerUtilCard - .evaluateCreatureList(humanCards); + return ComputerUtilCard.evaluateCreatureList(aiCards) >= ComputerUtilCard.evaluateCreatureList(humanCards); } return true; } @@ -416,15 +406,13 @@ public class ChangeZoneAllAi extends SpellAbilityAi { // if the AI is using it defensively, then something else needs to occur // if only creatures are affected evaluate both lists and pass only // if human creatures are more valuable - if ((CardLists.getNotType(humanType, "Creature").isEmpty()) && (CardLists.getNotType(computerType, "Creature").isEmpty())) { - if (ComputerUtilCard.evaluateCreatureList(computerType) >= ComputerUtilCard - .evaluateCreatureList(humanType)) { + if (CardLists.getNotType(humanType, "Creature").isEmpty() && CardLists.getNotType(computerType, "Creature").isEmpty()) { + if (ComputerUtilCard.evaluateCreatureList(computerType) >= ComputerUtilCard.evaluateCreatureList(humanType)) { return false; } } // otherwise evaluate both lists by CMC and pass only if human // permanents are more valuable - else if (ComputerUtilCard.evaluatePermanentList(computerType) >= ComputerUtilCard - .evaluatePermanentList(humanType)) { + else if (ComputerUtilCard.evaluatePermanentList(computerType) >= ComputerUtilCard.evaluatePermanentList(humanType)) { return false; } } else if (origin.equals(ZoneType.Graveyard)) { @@ -457,11 +445,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi { } else if (origin.equals(ZoneType.Exile)) { } else if (origin.equals(ZoneType.Stack)) { - // time stop can do something like this: - // Origin$ Stack | Destination$ Exile | SubAbility$ DBSkip - // DBSKipToPhase | DB$SkipToPhase | Phase$ Cleanup - // otherwise, this situation doesn't exist - return false; + // currently only exists indirectly (e.g. Summary Dismissal via PlayAi) } if (destination.equals(ZoneType.Battlefield)) { @@ -469,25 +453,22 @@ public class ChangeZoneAllAi extends SpellAbilityAi { if (mandatory) { return true; } - if (sa.getParam("GainControl") != null) { + if (sa.hasParam("GainControl")) { // Check if the cards are valuable enough - if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) { - return (ComputerUtilCard.evaluateCreatureList(computerType) + ComputerUtilCard - .evaluateCreatureList(humanType)) >= 1; + if (CardLists.getNotType(humanType, "Creature").isEmpty() && CardLists.getNotType(computerType, "Creature").isEmpty()) { + return (ComputerUtilCard.evaluateCreatureList(computerType) + ComputerUtilCard.evaluateCreatureList(humanType)) >= 1; } // otherwise evaluate both lists by CMC and pass only if human // permanents are less valuable - else return (ComputerUtilCard.evaluatePermanentList(computerType) + ComputerUtilCard + return (ComputerUtilCard.evaluatePermanentList(computerType) + ComputerUtilCard .evaluatePermanentList(humanType)) >= 1; - } else { - // don't activate if human gets more back than AI does - if ((CardLists.getNotType(humanType, "Creature").isEmpty()) && (CardLists.getNotType(computerType, "Creature").isEmpty())) { - return ComputerUtilCard.evaluateCreatureList(computerType) > ComputerUtilCard - .evaluateCreatureList(humanType); - } // otherwise evaluate both lists by CMC and pass only if human - // permanents are less valuable - else return ComputerUtilCard.evaluatePermanentList(computerType) > ComputerUtilCard - .evaluatePermanentList(humanType); } + + // don't activate if human gets more back than AI does + if (CardLists.getNotType(humanType, "Creature").isEmpty() && CardLists.getNotType(computerType, "Creature").isEmpty()) { + return ComputerUtilCard.evaluateCreatureList(computerType) > ComputerUtilCard.evaluateCreatureList(humanType); + } // otherwise evaluate both lists by CMC and pass only if human + // permanents are less valuable + return ComputerUtilCard.evaluatePermanentList(computerType) > ComputerUtilCard.evaluatePermanentList(humanType); } return true; diff --git a/forge-ai/src/main/java/forge/ai/ability/ClashAi.java b/forge-ai/src/main/java/forge/ai/ability/ClashAi.java index 8541efdb2f7..e360b6863da 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ClashAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ClashAi.java @@ -59,7 +59,7 @@ public class ClashAi extends SpellAbilityAi { @Override protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable options, Map params) { for (Player p : options) { - if (p.getCardsIn(ZoneType.Library).size() == 0) + if (p.getCardsIn(ZoneType.Library).isEmpty()) return p; } diff --git a/forge-ai/src/main/java/forge/ai/ability/CounterAi.java b/forge-ai/src/main/java/forge/ai/ability/CounterAi.java index a13b1dbfe96..1c175905e1f 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CounterAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CounterAi.java @@ -64,8 +64,7 @@ public class CounterAi extends SpellAbilityAi { if (sa.usesTargeting()) { final SpellAbility topSA = ComputerUtilAbility.getTopSpellAbilityOnStack(game, sa); - if ((topSA.isSpell() && !CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa)) || topSA.getActivatingPlayer() == ai - || ai.getAllies().contains(topSA.getActivatingPlayer())) { + if ((topSA.isSpell() && !CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa)) || ai.getYourTeam().contains(topSA.getActivatingPlayer())) { // might as well check for player's friendliness return false; } else if (sa.hasParam("ConditionWouldDestroy") && !CounterEffect.checkForConditionWouldDestroy(sa, topSA)) { diff --git a/forge-ai/src/main/java/forge/ai/ability/RegenerateAi.java b/forge-ai/src/main/java/forge/ai/ability/RegenerateAi.java index 2cffe2688bd..b9b8108471f 100644 --- a/forge-ai/src/main/java/forge/ai/ability/RegenerateAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/RegenerateAi.java @@ -89,7 +89,7 @@ public class RegenerateAi extends SpellAbilityAi { // filter AIs battlefield by what I can target List targetables = CardLists.getTargetableCards(ai.getCardsIn(ZoneType.Battlefield), sa); - if (targetables.size() == 0) { + if (targetables.isEmpty()) { return false; } @@ -153,11 +153,11 @@ public class RegenerateAi extends SpellAbilityAi { CardCollectionView targetables = CardLists.getTargetableCards(game.getCardsIn(ZoneType.Battlefield), sa); final List compTargetables = CardLists.filterControlledBy(targetables, ai); - if (targetables.size() == 0) { + if (targetables.isEmpty()) { return false; } - if (!mandatory && compTargetables.size() == 0) { + if (!mandatory && compTargetables.isEmpty()) { return false; } diff --git a/forge-ai/src/main/java/forge/ai/ability/RegenerateAllAi.java b/forge-ai/src/main/java/forge/ai/ability/RegenerateAllAi.java index 909fe257786..3508b96ed1e 100644 --- a/forge-ai/src/main/java/forge/ai/ability/RegenerateAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/RegenerateAllAi.java @@ -32,7 +32,7 @@ public class RegenerateAllAi extends SpellAbilityAi { list = CardLists.getValidCards(list, valid, hostCard.getController(), hostCard, sa); list = CardLists.filter(list, CardPredicates.isController(ai)); - if (list.size() == 0) { + if (list.isEmpty()) { return false; } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index 6068a34149a..20e245d35dc 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -339,7 +339,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { final String fromGraveyard = " from the graveyard"; if (destination.equals(ZoneType.Battlefield)) { - final boolean attacking = (sa.hasParam("Attacking")); + final boolean attacking = sa.hasParam("Attacking"); if (ZoneType.Graveyard.equals(origin)) { sb.append("Return").append(targetname).append(fromGraveyard).append(" to the battlefield"); } else { @@ -565,6 +565,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { // If a card is moved to library from the stack, remove its spells from the stack if (sa.hasParam("Fizzle")) { + // TODO only AI still targets as card, try to remove it if (gameCard.isInZone(ZoneType.Exile) || gameCard.isInZone(ZoneType.Hand) || gameCard.isInZone(ZoneType.Stack)) { // This only fizzles spells, not anything else. game.getStack().remove(gameCard); diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 10b77d3ee63..2c6744f7231 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -1318,8 +1318,8 @@ public class CardFactoryUtil { // Second, create the trigger that runs when the haunted creature dies final StringBuilder sbDies = new StringBuilder(); - sbDies.append("Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | TriggerZones$ Exile |"); - sbDies.append("ValidCard$ Creature.HauntedBy | Execute$ ").append(hauntSVarName); + sbDies.append("Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | TriggerZones$ Exile"); + sbDies.append(" | ValidCard$ Creature.HauntedBy | Execute$ ").append(hauntSVarName); sbDies.append(" | TriggerDescription$ ").append(hauntDescription); final Trigger hauntedDies = TriggerHandler.parseTrigger(sbDies.toString(), card, intrinsic); @@ -1369,7 +1369,7 @@ public class CardFactoryUtil { // First, create trigger that runs when the haunter goes to the graveyard final StringBuilder sbHaunter = new StringBuilder(); sbHaunter.append("Mode$ ChangesZone | Origin$ "); - sbHaunter.append(card.isCreature() ? "Battlefield" : "Stack | ResolvedCard$ True"); + sbHaunter.append(card.isCreature() ? "Battlefield" : "Stack | Fizzle$ False"); sbHaunter.append(" | Destination$ Graveyard | ValidCard$ Card.Self"); sbHaunter.append(" | Secondary$ True | TriggerDescription$ Haunt (").append(inst.getReminderText()).append(")"); diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerChangesZone.java b/forge-game/src/main/java/forge/game/trigger/TriggerChangesZone.java index 11a27e60e2e..413d2eca648 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerChangesZone.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerChangesZone.java @@ -135,10 +135,14 @@ public class TriggerChangesZone extends Trigger { } } - if (hasParam("ResolvedCard")) { + if (hasParam("Fizzle")) { if (!runParams.containsKey(AbilityKey.Fizzle)) { return false; } + Boolean val = (Boolean) runParams.get(AbilityKey.Fizzle); + if ("True".equals(getParam("Fizzle")) != val) { + return false; + } } // Check number of lands ETB this turn on triggered card's controller