/*
   * (non-Javadoc)
   *
   * @see
   * forge.card.cost.CostPart#canPay(forge.card.spellability.SpellAbility,
   * forge.Card, forge.Player, forge.card.cost.Cost)
   */
  @Override
  public final boolean canPay(final SpellAbility ability) {
    final Player activator = ability.getActivatingPlayer();
    final Card source = ability.getHostCard();
    CardCollectionView validCards = activator.getCardsIn(ZoneType.Battlefield);
    validCards = CardLists.getValidCards(validCards, this.getType().split(";"), activator, source);
    validCards =
        CardLists.filter(
            validCards,
            new Predicate<Card>() {
              @Override
              public boolean apply(final Card c) {
                return c.hasCounters();
              }
            });
    if (validCards.isEmpty()) {
      return false;
    }
    Integer i = this.convertAmount();

    if (i == null) {
      i = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
    }
    int allCounters = 0;
    for (Card c : validCards) {
      final Map<CounterType, Integer> tgtCounters = c.getCounters();
      for (Integer value : tgtCounters.values()) {
        allCounters += value;
      }
    }

    return i <= allCounters;
  }
示例#2
0
  @Override
  public void resolve(SpellAbility sa) {
    final int numTurns =
        AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("NumTurns"), sa);

    List<Player> tgtPlayers = getTargetPlayers(sa);

    for (final Player p : tgtPlayers) {
      if ((sa.getTargetRestrictions() == null) || p.canBeTargetedBy(sa)) {
        for (int i = 0; i < numTurns; i++) {
          ExtraTurn extra = p.getGame().getPhaseHandler().addExtraTurn(p);
          if (sa.hasParam("LoseAtEndStep")) {
            extra.setLoseAtEndStep(true);
          }
          if (sa.hasParam("SkipUntap")) {
            extra.setSkipUntap(true);
          }
          if (sa.hasParam("NoSchemes")) {
            extra.setCantSetSchemesInMotion(true);
          }
          if (sa.hasParam("ShowMessage")) {
            p.getGame().getAction().nofityOfValue(sa, p, p + " takes an extra turn.", null);
          }
        }
      }
    }
  }
  /** {@inheritDoc} */
  @Override
  public final void showMessage() {
    final Game game = player.getGame();

    final StringBuilder sb = new StringBuilder();
    if (startingPlayer == player) {
      sb.append(player).append(", you are going first!\n\n");
    } else {
      sb.append(startingPlayer.getName()).append(" is going first.\n");
      sb.append(player)
          .append(", you are going ")
          .append(Lang.getOrdinal(game.getPosition(player, startingPlayer)))
          .append(".\n\n");
    }

    if (isCommander) {
      getController().getGui().updateButtons(getOwner(), "Keep", "Exile", true, false, true);
      sb.append(
          "Will you keep your hand or choose some cards to exile those and draw one less card?");
    } else {
      getController().getGui().updateButtons(getOwner(), "Keep", "Mulligan", true, true, true);
      sb.append("Do you want to keep your hand?");
    }

    showMessage(sb.toString());
  }
示例#4
0
 @Override
 public void selectButtonCancel() {
   // cancel auto pass for all players
   for (final Player player : game.getPlayers()) {
     player.getController().autoPassCancel();
   }
 }
示例#5
0
  /* (non-Javadoc)
   * @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
   */
  @Override
  protected boolean canPlayAI(Player ai, SpellAbility sa) {
    final TargetRestrictions tgt = sa.getTargetRestrictions();

    if (tgt != null && sa.canTarget(ai.getOpponent())) {
      sa.resetTargets();
      sa.getTargets().add(ai.getOpponent());
    }

    final String damage = sa.getParam("NumDmg");
    final int iDmg = AbilityUtils.calculateAmount(sa.getHostCard(), damage, sa);
    return this.shouldTgtP(ai, sa, iDmg, false);
  }
  /* (non-Javadoc)
   * @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, forge.card.spellability.SpellAbility)
   */
  @Override
  protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
    String logic = sa.getParam("AILogic");
    Game game = aiPlayer.getGame();

    if ("ZeroToughness".equals(logic)) {
      // If Creature has Zero Toughness, make sure some static ability is in play
      // That will grant a toughness bonus

      final List<Card> list = aiPlayer.getCardsIn(ZoneType.Battlefield);
      if (!Iterables.any(
          list,
          Predicates.or(
              CardPredicates.nameEquals("Glorious Anthem"),
              CardPredicates.nameEquals("Gaea's Anthem")))) {
        return false;
      }

      // TODO See if card ETB will survive after Static Effects
      /*
      List<Card> cards = game.getCardsIn(ZoneType.Battlefield);

      for(Card c : cards) {
          ArrayList<StaticAbility> statics = c.getStaticAbilities();
          for(StaticAbility s : statics) {
              final Map<String, String> stabMap = s.parseParams();

              if (!stabMap.get("Mode").equals("Continuous")) {
                  continue;
              }

              final String affected = stabMap.get("Affected");

              if (affected == null) {
                  continue;
              }
          }
      }
      */
    }

    // Wait for Main2 if possible
    if (game.getPhaseHandler().is(PhaseType.MAIN1)
        && !ComputerUtil.castPermanentInMain1(aiPlayer, sa)) {
      return false;
    }

    // AI shouldn't be retricted all that much for Creatures for now
    return true;
  }
  @Override
  public void resolve(SpellAbility sa) {
    Game game = sa.getActivatingPlayer().getGame();

    for (Player p : game.getPlayers()) {
      p.leaveCurrentPlane();
    }
    if (sa.hasParam("Defined")) {
      CardCollectionView destinations =
          AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
      sa.getActivatingPlayer().planeswalkTo(destinations);
    } else {
      sa.getActivatingPlayer().planeswalk();
    }
  }
示例#8
0
  @Override
  public PaymentDecision visit(CostGainLife cost) {
    final List<Player> oppsThatCanGainLife = new ArrayList<Player>();

    for (final Player opp : cost.getPotentialTargets(player, source)) {
      if (opp.canGainLife()) {
        oppsThatCanGainLife.add(opp);
      }
    }

    if (oppsThatCanGainLife.size() == 0) {
      return null;
    }

    return PaymentDecision.players(oppsThatCanGainLife);
  }
  /*
   * (non-Javadoc)
   *
   * @see
   * forge.card.cost.CostPart#canPay(forge.card.spellability.SpellAbility,
   * forge.Card, forge.Player, forge.card.cost.Cost)
   */
  @Override
  public final boolean canPay(final SpellAbility ability) {
    final Player activator = ability.getActivatingPlayer();
    final Card source = ability.getHostCard();
    CardCollectionView typeList = activator.getGame().getCardsIn(ZoneType.Battlefield);
    typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source);

    Integer amount = this.convertAmount();
    if (amount == null) {
      amount = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
    }
    if (typeList.size() < amount) {
      return false;
    }
    return true;
  }
示例#10
0
 @Override
 protected boolean allowAwaitNextInput() {
   return chosenSa == null
       && !player
           .getController()
           .mayAutoPass(); // don't allow awaiting next input if player chose to end the turn or if
                           // a spell/ability is chosen
 }
示例#11
0
  /** {@inheritDoc} */
  @Override
  public boolean canPlay() {
    final Card card = this.getHostCard();
    Player activator = this.getActivatingPlayer();
    if (activator == null) {
      activator = card.getController();
      if (activator == null) {
        return false;
      }
    }

    final Game game = activator.getGame();
    if (game.getStack().isSplitSecondOnStack()) {
      return false;
    }

    if (!(card.isInstant()
        || activator.canCastSorcery()
        || card.hasKeyword("Flash")
        || this.getRestrictions().isInstantSpeed()
        || activator.hasKeyword("You may cast nonland cards as though they had flash.")
        || card.hasStartOfKeyword("You may cast CARDNAME as though it had flash."))) {
      return false;
    }

    if (!this.getRestrictions().canPlay(card, this)) {
      return false;
    }

    // for uncastables like lotus bloom, check if manaCost is blank (except for morph spells)
    if (!isCastFaceDown()
        && isBasicSpell()
        && card.getState(card.isFaceDown() ? CardStateName.Original : card.getCurrentStateName())
            .getManaCost()
            .isNoCost()) {
      return false;
    }

    if (this.getPayCosts() != null) {
      if (!CostPayment.canPayAdditionalCosts(this.getPayCosts(), this)) {
        return false;
      }
    }

    return checkOtherRestrictions();
  } // canPlay()
 @Override
 protected boolean canPlayAI(Player ai, SpellAbility sa) {
   final String svarName = sa.getParam("Execute");
   final SpellAbility trigsa = AbilityFactory.getAbility(sa.getSVar(svarName), sa.getHostCard());
   trigsa.setActivatingPlayer(ai);
   return AiPlayDecision.WillPlay
       == ((PlayerControllerAi) ai.getController()).getAi().canPlaySa(trigsa);
 }
示例#13
0
 public boolean checkOtherRestrictions() {
   final Card source = this.getHostCard();
   Player activator = getActivatingPlayer();
   final Game game = activator.getGame();
   // CantBeCast static abilities
   final CardCollection allp =
       new CardCollection(game.getCardsIn(ZoneType.listValueOf("Battlefield,Command")));
   allp.add(source);
   for (final Card ca : allp) {
     final FCollectionView<StaticAbility> staticAbilities = ca.getStaticAbilities();
     for (final StaticAbility stAb : staticAbilities) {
       if (stAb.applyAbility("CantBeCast", source, activator)) {
         return false;
       }
     }
   }
   return true;
 }
  @Override
  public Card chooseSingleCard(
      final Player aiChoser,
      SpellAbility sa,
      Iterable<Card> options,
      boolean isOptional,
      Player targetedPlayer) {
    if ("NeedsPrevention".equals(sa.getParam("AILogic"))) {
      final Player ai = sa.getActivatingPlayer();
      final Game game = ai.getGame();
      if (!game.getStack().isEmpty()) {
        Card choseCard = chooseCardOnStack(sa, ai, game);
        if (choseCard != null) {
          return choseCard;
        }
      }

      final Combat combat = game.getCombat();

      List<Card> permanentSources =
          CardLists.filter(
              options,
              new Predicate<Card>() {
                @Override
                public boolean apply(final Card c) {
                  if (c == null
                      || c.getZone() == null
                      || c.getZone().getZoneType() != ZoneType.Battlefield
                      || combat == null
                      || !combat.isAttacking(c, ai)
                      || !combat.isUnblocked(c)) {
                    return false;
                  }
                  return ComputerUtilCombat.damageIfUnblocked(c, ai, combat, true) > 0;
                }
              });
      return ComputerUtilCard.getBestCreatureAI(permanentSources);

    } else {
      return ComputerUtilCard.getBestAI(options);
    }
  }
示例#15
0
  @Override
  protected String getStackDescription(SpellAbility sa) {
    final Card host = sa.getHostCard();
    final StringBuilder sb = new StringBuilder();
    final int numToDig = AbilityUtils.calculateAmount(host, sa.getParam("DigNum"), sa);
    final List<Player> tgtPlayers = getTargetPlayers(sa);

    sb.append(host.getController()).append(" looks at the top ");
    sb.append(Lang.nounWithAmount(numToDig, "card")).append(" of ");

    if (tgtPlayers.contains(host.getController())) {
      sb.append("his or her ");
    } else {
      for (final Player p : tgtPlayers) {
        sb.append(Lang.getPossesive(p.getName())).append(" ");
      }
    }
    sb.append("library.");
    return sb.toString();
  }
示例#16
0
 /** {@inheritDoc} */
 @Override
 public final void showMessage() {
   showMessage(getTurnPhasePriorityMessage(player.getGame()));
   chosenSa = null;
   if (getController()
       .canUndoLastAction()) { // allow undoing with cancel button if can undo last action
     ButtonUtil.update(getOwner(), "OK", "Undo", true, true, true);
   } else { // otherwise allow ending turn with cancel button
     ButtonUtil.update(getOwner(), "OK", "End Turn", true, true, true);
   }
 }
示例#17
0
 void setPlayerMayLook(Player p, boolean mayLook, boolean temp) {
   TrackableProperty prop =
       temp ? TrackableProperty.PlayerMayLookTemp : TrackableProperty.PlayerMayLook;
   TrackableCollection<PlayerView> col = get(prop);
   if (mayLook) {
     if (col == null) {
       col = new TrackableCollection<PlayerView>(p.getView());
       set(prop, col);
     } else if (col.add(p.getView())) {
       flagAsChanged(prop);
     }
   } else if (col != null) {
     if (col.remove(p.getView())) {
       if (col.isEmpty()) {
         set(prop, null);
       } else {
         flagAsChanged(prop);
       }
     }
   }
 }
示例#18
0
  /*
   * (non-Javadoc)
   *
   * @see
   * forge.card.cost.CostPart#canPay(forge.card.spellability.SpellAbility,
   * forge.Card, forge.Player, forge.card.cost.Cost)
   */
  @Override
  public final boolean canPay(final SpellAbility ability) {
    final Player activator = ability.getActivatingPlayer();
    final Card source = ability.getHostCard();
    if (!this.payCostFromSource()) {
      boolean needsAnnoucement =
          ability.hasParam("Announce") && this.getType().contains(ability.getParam("Announce"));

      CardCollectionView typeList = activator.getCardsIn(ZoneType.Battlefield);
      typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source);

      final Integer amount = this.convertAmount();
      if (!needsAnnoucement && amount != null && typeList.size() < amount) {
        return false;
      }
    } else if (!source.isInPlay()) {
      return false;
    }

    return true;
  }
示例#19
0
  @Override
  public void resolve(SpellAbility sa) {
    final Card host = sa.getHostCard();
    final String[] choices = sa.getParam("Choices").split(",");
    final List<SpellAbility> abilities = new ArrayList<SpellAbility>();

    for (String s : choices) {
      abilities.add(AbilityFactory.getAbility(host.getSVar(s), host));
    }

    final List<Player> tgtPlayers = getDefinedPlayersOrTargeted(sa);
    final TargetRestrictions tgt = sa.getTargetRestrictions();

    for (final Player p : tgtPlayers) {
      if (tgt != null && !p.canBeTargetedBy(sa)) {
        continue;
      }

      int idxChosen = 0;
      String chosenName;
      if (sa.hasParam("AtRandom")) {
        idxChosen = MyRandom.getRandom().nextInt(choices.length);
        chosenName = choices[idxChosen];
      } else {
        SpellAbility saChosen =
            p.getController().chooseSingleSpellForEffect(abilities, sa, "Choose one");
        idxChosen = abilities.indexOf(saChosen);
        chosenName = choices[idxChosen];
      }
      SpellAbility chosenSA = AbilityFactory.getAbility(host.getSVar(chosenName), host);
      if (sa.hasParam("ShowChoice")) {
        p.getGame()
            .getAction()
            .nofityOfValue(sa, p, abilities.get(idxChosen).getDescription(), null);
      }
      chosenSA.setActivatingPlayer(sa.getActivatingPlayer());
      ((AbilitySub) chosenSA).setParent(sa);
      AbilityUtils.resolve(chosenSA);
    }
  }
示例#20
0
  @Override
  protected boolean onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
    // remove unplayable unless triggerEvent specified, in which case unplayable may be shown as
    // disabled options
    List<SpellAbility> abilities = card.getAllPossibleAbilities(player, triggerEvent == null);
    if (abilities.isEmpty()) {
      flashIncorrectAction();
      return false;
    }

    selectAbility(player.getController().getAbilityToPlay(abilities, triggerEvent));
    return true;
  }
  @Override
  protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
    final String svarName = sa.getParam("Execute");
    final SpellAbility trigsa =
        AbilityFactory.getAbility(sa.getHostCard().getSVar(svarName), sa.getHostCard());
    AiController aic = ((PlayerControllerAi) ai.getController()).getAi();
    trigsa.setActivatingPlayer(ai);

    if (!sa.hasParam("OptionalDecider")) {
      return aic.doTrigger(trigsa, true);
    } else {
      return aic.doTrigger(trigsa, !sa.getParam("OptionalDecider").equals("You"));
    }
  }
示例#22
0
  protected boolean revealHandTargetAI(final Player ai, final SpellAbility sa) {
    final TargetRestrictions tgt = sa.getTargetRestrictions();

    Player opp = ai.getOpponent();
    final int humanHandSize = opp.getCardsIn(ZoneType.Hand).size();

    if (tgt != null) {
      // ability is targeted
      sa.resetTargets();

      final boolean canTgtHuman = opp.canBeTargetedBy(sa);

      if (!canTgtHuman || (humanHandSize == 0)) {
        return false;
      } else {
        sa.getTargets().add(opp);
      }
    } else {
      // if it's just defined, no big deal
    }

    return true;
  } // revealHandTargetAI()
示例#23
0
 private void passPriority(final Runnable runnable) {
   if (FModel.getPreferences().getPrefBoolean(FPref.UI_MANA_LOST_PROMPT)) {
     // if gui player has mana floating that will be lost if phase ended right now, prompt before
     // passing priority
     final Game game = player.getGame();
     if (game.getStack().isEmpty()) { // phase can't end right now if stack isn't empty
       Player player = game.getPhaseHandler().getPriorityPlayer();
       if (player != null
           && player.getManaPool().willManaBeLostAtEndOfPhase()
           && player.getLobbyPlayer() == GamePlayerUtil.getGuiPlayer()) {
         ThreadUtil.invokeInGameThread(
             new Runnable() { // must invoke in game thread so dialog can be shown on mobile game
               @Override
               public void run() {
                 String message =
                     "You have mana floating in your mana pool that could be lost if you pass priority now.";
                 if (FModel.getPreferences().getPrefBoolean(FPref.UI_MANABURN)) {
                   message +=
                       " You will take mana burn damage equal to the amount of floating mana lost this way.";
                 }
                 if (SOptionPane.showOptionDialog(
                         message,
                         "Mana Floating",
                         SOptionPane.WARNING_ICON,
                         new String[] {"OK", "Cancel"})
                     == 0) {
                   runnable.run();
                 }
               }
             });
         return;
       }
     }
   }
   runnable.run(); // just pass priority immediately if no mana floating that would be lost
 }
 @Override
 public Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> choices) {
   Player chosen = null;
   if ("Curse".equals(sa.getParam("AILogic"))) {
     for (Player pc : choices) {
       if (pc.isOpponentOf(ai)) {
         chosen = pc;
         break;
       }
     }
     if (chosen == null) {
       chosen = Iterables.getFirst(choices, null);
       System.out.println("No good curse choices. Picking first available: " + chosen);
     }
   } else if ("Pump".equals(sa.getParam("AILogic"))) {
     chosen = Iterables.contains(choices, ai) ? ai : Iterables.getFirst(choices, null);
   } else if ("BestAllyBoardPosition".equals(sa.getParam("AILogic"))) {
     List<Player> prefChoices = Lists.newArrayList(choices);
     prefChoices.removeAll(ai.getOpponents());
     if (!prefChoices.isEmpty()) {
       chosen = ComputerUtil.evaluateBoardPosition(prefChoices);
     }
     if (chosen == null) {
       chosen = Iterables.getFirst(choices, null);
       System.out.println("No good curse choices. Picking first available: " + chosen);
     }
   } else if ("MostCardsInHand".equals(sa.getParam("AILogic"))) {
     int cardsInHand = 0;
     for (final Player p : choices) {
       int hand = p.getCardsIn(ZoneType.Hand).size();
       if (hand >= cardsInHand) {
         chosen = p;
         cardsInHand = hand;
       }
     }
   } else if ("LeastCreatures".equals(sa.getParam("AILogic"))) {
     int creats = 50;
     for (final Player p : choices) {
       int curr = p.getCreaturesInPlay().size();
       if (curr <= creats) {
         chosen = p;
         creats = curr;
       }
     }
   } else {
     System.out.println("Default player choice logic.");
     chosen = Iterables.contains(choices, ai) ? ai : Iterables.getFirst(choices, null);
   }
   return chosen;
 }
示例#25
0
  @Override
  protected boolean onCardSelected(
      final Card c0,
      final List<Card> otherCardsToSelect,
      final ITriggerEvent
          triggerEvent) { // the only place that would cause troubles - input is supposed only to
                          // confirm, not to fire abilities
    final boolean fromHand = player.getZone(ZoneType.Hand).contains(c0);
    final boolean isSerumPowder = c0.getName().equals("Serum Powder");
    final boolean isLegalChoice = fromHand && (isCommander || isSerumPowder);
    if (!isLegalChoice || cardSelectLocked) {
      return false;
    }

    final CardView cView = c0.getView();
    if (isSerumPowder && getController().getGui().confirm(cView, "Use " + cView + "'s ability?")) {
      cardSelectLocked = true;
      ThreadUtil.invokeInGameThread(
          new Runnable() {
            @Override
            public void run() {
              final CardCollection hand =
                  new CardCollection(c0.getController().getCardsIn(ZoneType.Hand));
              for (final Card c : hand) {
                player.getGame().getAction().exile(c);
              }
              c0.getController().drawCards(hand.size());
              cardSelectLocked = false;
            }
          });
      return true;
    }

    if (isCommander) { // allow to choose cards for partial paris
      if (selected.contains(c0)) {
        getController().getGui().setUsedToPay(c0.getView(), false);
        selected.remove(c0);
      } else {
        getController().getGui().setUsedToPay(c0.getView(), true);
        selected.add(c0);
      }
      getController()
          .getGui()
          .updateButtons(getOwner(), "Keep", "Exile", true, !selected.isEmpty(), true);
    }
    return true;
  }
示例#26
0
  @Override
  protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
    final TargetRestrictions tgt = sa.getTargetRestrictions();

    if (tgt == null) {
      return mandatory;
    }

    if (phasesPrefTargeting(tgt, sa, mandatory)) {
      return true;
    } else if (mandatory) {
      // not enough preferred targets, but mandatory so keep going:
      return phasesUnpreferredTargeting(aiPlayer.getGame(), sa, mandatory);
    }

    return false;
  }
  @Override
  public boolean chkAIDrawback(SpellAbility sa, Player ai) {
    if ("Always".equals(sa.getParam("AILogic"))) {
      // TODO: improve ai
      return true;
    }
    final String svarName = sa.getParam("Execute");
    final SpellAbility trigsa =
        AbilityFactory.getAbility(sa.getHostCard().getSVar(svarName), sa.getHostCard());
    trigsa.setActivatingPlayer(ai);

    if (trigsa instanceof AbilitySub) {
      return SpellApiToAi.Converter.get(((AbilitySub) trigsa).getApi())
          .chkDrawbackWithSubs(ai, (AbilitySub) trigsa);
    } else {
      return AiPlayDecision.WillPlay
          == ((PlayerControllerAi) ai.getController()).getAi().canPlaySa(trigsa);
    }
  }
示例#28
0
 @Override
 protected int evaluate(Player player, Game game) {
   if (player.getOutcome().hasWon()) {
     for (Player p : game.getRegisteredPlayers()) {
       if (p.isOpponentOf(player) && p.getOutcome().lossState == GameLossReason.CommanderDamage) {
         Integer damage = p.getCommanderDamage(player.getCommander());
         if (damage != null && damage >= THRESHOLD) {
           return damage;
         }
       }
     }
   }
   return 0;
 }
示例#29
0
  boolean pumpAgainstRemoval(Player ai, SpellAbility sa) {
    final List<GameObject> objects =
        ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa);
    final List<Card> threatenedTargets = new ArrayList<Card>();
    final TargetRestrictions tgt = sa.getTargetRestrictions();

    if (tgt == null) {
      // For pumps without targeting restrictions, just return immediately until this is fleshed
      // out.
      return false;
    }

    List<Card> targetables =
        CardLists.getValidCards(
            ai.getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, sa.getHostCard());
    targetables = CardLists.getTargetableCards(targetables, sa);
    targetables = ComputerUtil.getSafeTargets(ai, sa, targetables);
    for (final Card c : targetables) {
      if (objects.contains(c)) {
        threatenedTargets.add(c);
      }
    }
    if (!threatenedTargets.isEmpty()) {
      ComputerUtilCard.sortByEvaluateCreature(threatenedTargets);
      for (Card c : threatenedTargets) {
        sa.getTargets().add(c);
        if (sa.getTargets().getNumTargeted() >= tgt.getMaxTargets(sa.getHostCard(), sa)) {
          break;
        }
      }
      if (sa.getTargets().getNumTargeted() > tgt.getMaxTargets(sa.getHostCard(), sa)
          || sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) {
        sa.resetTargets();
        return false;
      }
      return true;
    }
    return false;
  }
示例#30
0
  /* (non-Javadoc)
   * @see forge.card.ability.SpellAbilityEffect#resolve(forge.card.spellability.SpellAbility)
   */
  @Override
  public void resolve(SpellAbility sa) {
    Player activator = sa.getActivatingPlayer();
    Card source = sa.getHostCard();
    Game game = activator.getGame();
    String valid = sa.hasParam("Valid") ? sa.getParam("Valid") : "Card";
    ZoneType zone =
        sa.hasParam("Zone") ? ZoneType.smartValueOf(sa.getParam("Zone")) : ZoneType.Battlefield;

    int min = Integer.MAX_VALUE;

    final FCollectionView<Player> players = game.getPlayersInTurnOrder();
    final List<CardCollection> validCards = new ArrayList<CardCollection>(players.size());

    for (int i = 0; i < players.size(); i++) {
      // Find the minimum of each Valid per player
      validCards.add(
          CardLists.getValidCards(players.get(i).getCardsIn(zone), valid, activator, source));
      min = Math.min(min, validCards.get(i).size());
    }

    for (int i = 0; i < players.size(); i++) {
      Player p = players.get(i);
      int numToBalance = validCards.get(i).size() - min;
      if (numToBalance == 0) {
        continue;
      }
      if (zone.equals(ZoneType.Hand)) {
        for (Card card :
            p.getController()
                .chooseCardsToDiscardFrom(p, sa, validCards.get(i), numToBalance, numToBalance)) {
          if (null == card) continue;
          p.discard(card, sa);
        }
      } else { // Battlefield
        // TODO: "can'e be sacrificed"
        for (Card card :
            p.getController()
                .choosePermanentsToSacrifice(
                    sa, numToBalance, numToBalance, validCards.get(i), valid)) {
          if (null == card) continue;
          game.getAction().sacrifice(card, sa);
        }
      }
    }
  }