public static void destroyAllResolve(
      final AbilityFactory af, final SpellAbility sa, final boolean noRegen) {
    HashMap<String, String> params = af.getMapParams();
    String DrawBack = params.get("SubAbility");
    Card card = sa.getSourceCard();

    if (!AbilityFactory.checkConditional(params, sa)) {
      AbilityFactory.resolveSubAbility(sa);
      return;
    }

    String Valid = "";

    if (params.containsKey("ValidCards")) Valid = params.get("ValidCards");

    // Ugh. If calculateAmount needs to be called with DestroyAll it _needs_ to use the X variable
    // We really need a better solution to this
    if (Valid.contains("X"))
      Valid = Valid.replace("X", Integer.toString(AbilityFactory.calculateAmount(card, "X", sa)));

    CardList list = AllZoneUtil.getCardsInPlay();

    list = list.getValidCards(Valid.split(","), card.getController(), card);

    boolean remDestroyed = params.containsKey("RememberDestroyed");
    if (remDestroyed) card.clearRemembered();

    if (noRegen) {
      for (int i = 0; i < list.size(); i++)
        if (AllZone.GameAction.destroyNoRegeneration(list.get(i)) && remDestroyed)
          card.addRemembered(list.get(i));
    } else {
      for (int i = 0; i < list.size(); i++)
        if (AllZone.GameAction.destroy(list.get(i)) && remDestroyed)
          card.addRemembered(list.get(i));
    }

    if (af.hasSubAbility()) {
      Ability_Sub abSub = sa.getSubAbility();
      if (abSub != null) {
        abSub.resolve();
      } else
        CardFactoryUtil.doDrawBack(
            DrawBack,
            0,
            card.getController(),
            card.getController().getOpponent(),
            card.getController(),
            card,
            null,
            sa);
    }
  }
  public static boolean destroyDoTriggerAI(
      final AbilityFactory af, SpellAbility sa, boolean mandatory) {
    if (!ComputerUtil.canPayCost(sa)) return false;

    Target tgt = sa.getTarget();
    final Card source = sa.getSourceCard();
    final boolean noRegen = af.getMapParams().containsKey("NoRegen");

    if (tgt != null) {
      CardList list;
      list = AllZoneUtil.getCardsInPlay();
      list = list.getTargetableCards(source);
      list = list.getValidCards(tgt.getValidTgts(), source.getController(), source);

      if (list.size() == 0 || list.size() < tgt.getMinTargets(sa.getSourceCard(), sa)) return false;

      tgt.resetTargets();

      CardList preferred = list.getNotKeyword("Indestructible");
      preferred = list.getController(AllZone.HumanPlayer);

      // If NoRegen is not set, filter out creatures that have a regeneration shield
      if (!noRegen) {
        // TODO: filter out things that could regenerate in response? might be tougher?
        preferred =
            preferred.filter(
                new CardListFilter() {
                  public boolean addCard(Card c) {
                    return c.getShield() == 0;
                  }
                });
      }

      for (Card c : preferred) list.remove(c);

      while (tgt.getNumTargeted() < tgt.getMaxTargets(sa.getSourceCard(), sa)) {
        if (preferred.size() == 0) {
          if (tgt.getNumTargeted() == 0
              || tgt.getNumTargeted() < tgt.getMinTargets(sa.getSourceCard(), sa)) {
            if (!mandatory) {
              tgt.resetTargets();
              return false;
            } else break;
          } else {
            break;
          }
        } else {
          Card c;
          if (preferred.getNotType("Creature").size() == 0) {
            c = CardFactoryUtil.AI_getBestCreature(preferred);
          } else if (preferred.getNotType("Land").size() == 0) {
            c = CardFactoryUtil.AI_getBestLand(preferred);
          } else {
            c = CardFactoryUtil.AI_getMostExpensivePermanent(preferred, source, false);
          }
          tgt.addTarget(c);
          preferred.remove(c);
        }
      }

      while (tgt.getNumTargeted() < tgt.getMinTargets(sa.getSourceCard(), sa)) {
        if (list.size() == 0) {
          break;
        } else {
          Card c;
          if (list.getNotType("Creature").size() == 0) {
            c = CardFactoryUtil.AI_getWorstCreature(list);
          } else {
            c = CardFactoryUtil.AI_getCheapestPermanent(list, source, false);
          }
          tgt.addTarget(c);
          list.remove(c);
        }
      }

      if (tgt.getNumTargeted() < tgt.getMinTargets(sa.getSourceCard(), sa)) return false;
    } else {
      if (!mandatory) return false;
    }

    Ability_Sub subAb = sa.getSubAbility();
    if (subAb != null) return subAb.doTrigger(mandatory);

    return true;
  }