public static boolean destroyAllCanPlayAI(
      final AbilityFactory af, final SpellAbility sa, final boolean noRegen) {
    // AI needs to be expanded, since this function can be pretty complex based on what the expected
    // targets could be
    Random r = MyRandom.random;
    Cost abCost = sa.getPayCosts();
    final Card source = sa.getSourceCard();
    final HashMap<String, String> params = af.getMapParams();
    String Valid = "";

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

    if (Valid.contains("X") && source.getSVar("X").equals("Count$xPaid")) {
      // Set PayX here to maximum value.
      int xPay = ComputerUtil.determineLeftoverMana(sa);
      source.setSVar("PayX", Integer.toString(xPay));
      Valid = Valid.replace("X", Integer.toString(xPay));
    }

    CardList humanlist = AllZoneUtil.getPlayerCardsInPlay(AllZone.HumanPlayer);
    CardList computerlist = AllZoneUtil.getPlayerCardsInPlay(AllZone.ComputerPlayer);

    humanlist = humanlist.getValidCards(Valid.split(","), source.getController(), source);
    computerlist = computerlist.getValidCards(Valid.split(","), source.getController(), source);

    humanlist = humanlist.getNotKeyword("Indestructible");
    computerlist = computerlist.getNotKeyword("Indestructible");

    if (abCost != null) {
      // AI currently disabled for some costs
      if (abCost.getSacCost()) {
        // OK
      }
      if (abCost.getLifeCost()) {
        if (AllZone.ComputerPlayer.getLife() - abCost.getLifeAmount() < 4) return false;
      }
      if (abCost.getDiscardCost()) ; // OK

      if (abCost.getSubCounter()) {
        // OK
      }
    }

    if (!ComputerUtil.canPayCost(sa)) return false;

    // prevent run-away activations - first time will always return true
    boolean chance = r.nextFloat() <= Math.pow(.6667, source.getAbilityUsed());

    // if only creatures are affected evaluate both lists and pass only if human creatures are more
    // valuable
    if (humanlist.getNotType("Creature").size() == 0
        && computerlist.getNotType("Creature").size() == 0) {
      if (CardFactoryUtil.evaluateCreatureList(computerlist) + 200
          >= CardFactoryUtil.evaluateCreatureList(humanlist)) return false;
    } // only lands involved
    else if (humanlist.getNotType("Land").size() == 0
        && computerlist.getNotType("Land").size() == 0) {
      if (CardFactoryUtil.evaluatePermanentList(computerlist) + 1
          >= CardFactoryUtil.evaluatePermanentList(humanlist)) return false;
    } // otherwise evaluate both lists by CMC and pass only if human permanents are more valuable
    else if (CardFactoryUtil.evaluatePermanentList(computerlist) + 3
        >= CardFactoryUtil.evaluatePermanentList(humanlist)) return false;

    Ability_Sub subAb = sa.getSubAbility();
    if (subAb != null) chance &= subAb.chkAI_Drawback();

    return ((r.nextFloat() < .9667) && chance);
  }
  public static boolean destroyCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
    // AI needs to be expanded, since this function can be pretty complex based on what the expected
    // targets could be
    Random r = MyRandom.random;
    Cost abCost = sa.getPayCosts();
    Target abTgt = sa.getTarget();
    final Card source = sa.getSourceCard();
    final boolean noRegen = af.getMapParams().containsKey("NoRegen");

    CardList list;
    list = AllZoneUtil.getPlayerCardsInPlay(AllZone.HumanPlayer);
    list = list.getTargetableCards(source);

    if (abTgt != null) {
      list = list.getValidCards(abTgt.getValidTgts(), source.getController(), source);
      list = list.getNotKeyword("Indestructible");

      // 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?
        list =
            list.filter(
                new CardListFilter() {
                  public boolean addCard(Card c) {
                    return (c.getShield() == 0 && !ComputerUtil.canRegenerate(c));
                  }
                });
      }

      if (list.size() == 0) return false;
    }

    if (abCost != null) {
      // AI currently disabled for some costs
      if (abCost.getSacCost() && !abCost.getSacThis()) {
        // only sacrifice something that's supposed to be sacrificed
        String sacType = abCost.getSacType();
        CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.ComputerPlayer);
        typeList = typeList.getValidCards(sacType.split(","), source.getController(), source);
        if (ComputerUtil.getCardPreference(source, "SacCost", typeList) == null) return false;
      }
      if (abCost.getLifeCost()) {
        if (AllZone.ComputerPlayer.getLife() - abCost.getLifeAmount() < 4) return false;
      }
      if (abCost.getDiscardCost()) return false;

      if (abCost.getSubCounter()) {
        // OK
      }
    }

    if (!ComputerUtil.canPayCost(sa)) return false;

    // prevent run-away activations - first time will always return true
    boolean chance = r.nextFloat() <= Math.pow(.6667, source.getAbilityUsed());

    // Targeting
    if (abTgt != null) {
      abTgt.resetTargets();
      // target loop
      while (abTgt.getNumTargeted() < abTgt.getMaxTargets(sa.getSourceCard(), sa)) {
        if (list.size() == 0) {
          if (abTgt.getNumTargeted() < abTgt.getMinTargets(sa.getSourceCard(), sa)
              || abTgt.getNumTargeted() == 0) {
            abTgt.resetTargets();
            return false;
          } else {
            // TODO is this good enough? for up to amounts?
            break;
          }
        }

        Card choice = null;
        if (list.getNotType("Creature").size() == 0)
          choice =
              CardFactoryUtil.AI_getBestCreature(
                  list); // if the targets are only creatures, take the best
        else choice = CardFactoryUtil.AI_getMostExpensivePermanent(list, af.getHostCard(), true);

        if (choice == null) { // can't find anything left
          if (abTgt.getNumTargeted() < abTgt.getMinTargets(sa.getSourceCard(), sa)
              || abTgt.getNumTargeted() == 0) {
            abTgt.resetTargets();
            return false;
          } else {
            // TODO is this good enough? for up to amounts?
            break;
          }
        }
        list.remove(choice);
        abTgt.addTarget(choice);
      }

    } else {
      return false;
    }

    Ability_Sub subAb = sa.getSubAbility();
    if (subAb != null) chance &= subAb.chkAI_Drawback();

    return ((r.nextFloat() < .6667) && chance);
  }