private Card chooseCardOnStack(SpellAbility sa, Player ai, Game game) { for (SpellAbilityStackInstance si : game.getStack()) { final Card source = si.getSourceCard(); final SpellAbility abilityOnStack = si.getSpellAbility(true); if (sa.hasParam("Choices") && !abilityOnStack.getHostCard().isValid(sa.getParam("Choices"), ai, sa.getHostCard())) { continue; } final ApiType threatApi = abilityOnStack.getApi(); if (threatApi != ApiType.DealDamage && threatApi != ApiType.DamageAll) { continue; } List<? extends GameObject> objects = getTargets(abilityOnStack); if (!abilityOnStack.usesTargeting() && !abilityOnStack.hasParam("Defined") && abilityOnStack.hasParam("ValidPlayers")) objects = AbilityUtils.getDefinedPlayers( source, abilityOnStack.getParam("ValidPlayers"), abilityOnStack); if (!objects.contains(ai) || abilityOnStack.hasParam("NoPrevention")) { continue; } int dmg = AbilityUtils.calculateAmount(source, abilityOnStack.getParam("NumDmg"), abilityOnStack); if (ComputerUtilCombat.predictDamageTo(ai, dmg, source, false) <= 0) { continue; } return source; } return null; }
/** {@inheritDoc} */ @Override public final void setTriggeringObjects(final SpellAbility sa) { final SpellAbility castSA = (SpellAbility) this.getRunParams().get("CastSA"); final SpellAbilityStackInstance si = sa.getHostCard().getGame().getStack().getInstanceFromSpellAbility(castSA); sa.setTriggeringObject("Card", castSA.getHostCard()); sa.setTriggeringObject("SpellAbility", castSA); sa.setTriggeringObject( "SpellAbilityTargetingCards", (si != null ? si.getSpellAbility(true) : castSA).getTargets().getTargetCards()); sa.setTriggeringObject("Player", this.getRunParams().get("Player")); sa.setTriggeringObject("Activator", this.getRunParams().get("Activator")); sa.setTriggeringObject("CurrentStormCount", this.getRunParams().get("CurrentStormCount")); sa.setTriggeringObject("CastSACMC", this.getRunParams().get("CastSACMC")); }
@Override public PaymentDecision visit(CostExileFromStack cost) { Integer c = cost.convertAmount(); if (c == null) { final String sVar = ability.getSVar(cost.getAmount()); // Generalize cost if (sVar.equals("XChoice")) { return null; } c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); } List<SpellAbility> chosen = new ArrayList<SpellAbility>(); for (SpellAbilityStackInstance si : source.getGame().getStack()) { SpellAbility sp = si.getSpellAbility().getRootAbility(); if (si.getSourceCard().isValid(cost.getType().split(";"), source.getController(), source)) { chosen.add(sp); } } return chosen.isEmpty() ? null : PaymentDecision.spellabilities(chosen); }
/** {@inheritDoc} */ @Override public final boolean performTest(final java.util.Map<String, Object> runParams2) { final SpellAbility spellAbility = (SpellAbility) runParams2.get("CastSA"); if (spellAbility == null) { System.out.println( "TriggerSpellAbilityCast performTest encountered spellAbility == null. runParams2 = " + runParams2); return false; } final Card cast = spellAbility.getHostCard(); final Game game = cast.getGame(); final SpellAbilityStackInstance si = game.getStack().getInstanceFromSpellAbility(spellAbility); if (this.getMode() == TriggerType.SpellCast) { if (!spellAbility.isSpell()) { return false; } } else if (this.getMode() == TriggerType.AbilityCast) { if (!spellAbility.isAbility()) { return false; } } else if (this.getMode() == TriggerType.SpellAbilityCast) { // Empty block for readability. } if (this.mapParams.containsKey("ActivatedOnly")) { if (spellAbility.isTrigger()) { return false; } } if (this.mapParams.containsKey("ValidControllingPlayer")) { if (!matchesValid( cast.getController(), this.mapParams.get("ValidControllingPlayer").split(","), this.getHostCard())) { return false; } } if (this.mapParams.containsKey("ValidActivatingPlayer")) { if (si == null || !matchesValid( si.getSpellAbility(true).getActivatingPlayer(), this.mapParams.get("ValidActivatingPlayer").split(","), this.getHostCard())) { return false; } if (this.mapParams.containsKey("ActivatorThisTurnCast")) { String compare = this.mapParams.get("ActivatorThisTurnCast"); List<Card> thisTurnCast = CardUtil.getThisTurnCast( this.mapParams.containsKey("ValidCard") ? this.mapParams.get("ValidCard") : "Card", this.getHostCard()); thisTurnCast = CardLists.filterControlledBy( thisTurnCast, si.getSpellAbility(true).getActivatingPlayer()); int left = thisTurnCast.size(); int right = Integer.parseInt(compare.substring(2)); if (!Expressions.compare(left, compare, right)) { return false; } } } if (this.mapParams.containsKey("ValidCard")) { if (!matchesValid(cast, this.mapParams.get("ValidCard").split(","), this.getHostCard())) { return false; } } if (this.mapParams.containsKey("TargetsValid")) { SpellAbility sa = spellAbility; if (si != null) { sa = si.getSpellAbility(true); } boolean validTgtFound = false; while (sa != null && !validTgtFound) { for (final Card tgt : sa.getTargets().getTargetCards()) { if (tgt.isValid( this.mapParams.get("TargetsValid").split(","), this.getHostCard().getController(), this.getHostCard())) { validTgtFound = true; break; } } for (final Player p : sa.getTargets().getTargetPlayers()) { if (matchesValid(p, this.mapParams.get("TargetsValid").split(","), this.getHostCard())) { validTgtFound = true; break; } } sa = sa.getSubAbility(); } if (!validTgtFound) { return false; } } if (this.mapParams.containsKey("NonTapCost")) { final Cost cost = (Cost) (runParams2.get("Cost")); if (cost.hasTapCost()) { return false; } } if (this.mapParams.containsKey("Conspire")) { if (!spellAbility.isOptionalCostPaid(OptionalCost.Conspire)) { return false; } if (spellAbility.getConspireInstances() == 0) { return false; } else { spellAbility.subtractConspireInstance(); // System.out.println("Conspire instances left = " + spellAbility.getConspireInstances()); } } if (this.mapParams.containsKey("Outlast")) { if (!spellAbility.isOutlast()) { return false; } } if (this.mapParams.containsKey("IsSingleTarget")) { int numTargeted = 0; for (TargetChoices tc : spellAbility.getAllTargetChoices()) { numTargeted += tc.getNumTargeted(); } if (numTargeted != 1) { return false; } } if (this.mapParams.containsKey("SpellSpeed")) { if (this.mapParams.get("SpellSpeed").equals("NotSorcerySpeed")) { if (this.getHostCard().getController().couldCastSorcery(spellAbility)) { return false; } if (this.getHostCard() .hasKeyword( "You may cast CARDNAME as though it had flash. If you cast it any time a " + "sorcery couldn't have been cast, the controller of the permanent it becomes sacrifices it at the beginning" + " of the next cleanup step.")) { // for these cards the trigger must only fire if using their own ability to cast at // instant speed if (this.getHostCard().hasKeyword("Flash") || this.getHostCard() .getController() .hasKeyword("You may cast nonland cards as though they had flash.")) { return false; } } return true; } } return true; }