Example #1
0
 @Override
 public boolean apply(Game game, Ability source) {
   Player player = getPayingPlayer(game, source);
   MageObject mageObject = game.getObject(source.getSourceId());
   if (player != null && mageObject != null) {
     String message;
     if (chooseUseText == null) {
       message =
           new StringBuilder(getCostText())
               .append(" and ")
               .append(executingEffect.getText(source.getModes().getMode()))
               .append("?")
               .toString();
     } else {
       message = chooseUseText;
     }
     message = CardUtil.replaceSourceName(message, mageObject.getName());
     if (cost.canPay(source, source.getSourceId(), player.getId(), game)
         && player.chooseUse(executingEffect.getOutcome(), message, game)) {
       cost.clearPaid();
       if (cost.pay(source, game, source.getSourceId(), player.getId(), false)) {
         executingEffect.setTargetPointer(this.targetPointer);
         if (executingEffect instanceof OneShotEffect) {
           if (!(executingEffect instanceof PostResolveEffect)) {
             return executingEffect.apply(game, source);
           }
         } else {
           game.addEffect((ContinuousEffect) executingEffect, source);
         }
       }
     }
     return true;
   }
   return false;
 }
 @Override
 public boolean apply(Game game, Ability source) {
   Player player = game.getPlayer(targetPointer.getFirst(game, source));
   MageObject mageObject = game.getObject(source.getSourceId());
   if (player != null && mageObject != null) {
     String message = userMessage;
     if (message == null) {
       message =
           getCostText()
               + " to prevent "
               + executingEffect.getText(source.getModes().getMode())
               + "?";
     }
     message = CardUtil.replaceSourceName(message, mageObject.getLogName());
     cost.clearPaid();
     if (cost.canPay(source, source.getSourceId(), player.getId(), game)
         && player.chooseUse(executingEffect.getOutcome(), message, source, game)) {
       cost.pay(source, game, source.getSourceId(), player.getId(), false, null);
     }
     if (!cost.isPaid()) {
       executingEffect.setTargetPointer(this.targetPointer);
       return executingEffect.apply(game, source);
     }
     return true;
   }
   return false;
 }
Example #3
0
 @Override
 public boolean apply(Game game, Ability source) {
   Cost cost = new GenericManaCost(1);
   cost.clearPaid();
   if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) {
     super.apply(game, source);
   }
   return true;
 }
Example #4
0
 private void checkPaid(UUID uuid, Spell spell) {
   for (Cost cost : spell.getSpellAbility().getManaCostsToPay()) {
     if (!cost.isPaid()) {
       return;
     }
   }
   CardView cardView = stack.get(uuid);
   cardView.paid = true;
 }
Example #5
0
 /**
  * Handles the setting of non mana X costs
  *
  * @param controller
  * @param game
  * @return announce message
  */
 protected String handleOtherXCosts(Game game, Player controller) {
   String announceString = null;
   for (VariableCost variableCost : this.costs.getVariableCosts()) {
     if (!(variableCost instanceof VariableManaCost)) {
       int xValue = variableCost.announceXValue(this, game);
       costs.add(variableCost.getFixedCostsFromAnnouncedValue(xValue));
       // set the xcosts to paid
       variableCost.setAmount(xValue);
       ((Cost) variableCost).setPaid();
       String message =
           controller.getLogName()
               + " announces a value of "
               + xValue
               + " ("
               + variableCost.getActionText()
               + ")";
       if (announceString == null) {
         announceString = message;
       } else {
         announceString = announceString + " " + message;
       }
     }
   }
   return announceString;
 }
 @Override
 public boolean apply(Game game, Ability source) {
   Player player = game.getPlayer(source.getControllerId());
   Permanent permanent = game.getPermanent(source.getSourceId());
   if (player != null && permanent != null) {
     if (player.chooseUse(
         Outcome.Benefit,
         "Pay " + cost.getText() /* + " or sacrifice " + permanent.getName() */ + "?",
         game)) {
       cost.clearPaid();
       if (cost.pay(source, game, source.getId(), source.getControllerId(), false)) return true;
     }
     permanent.sacrifice(source.getSourceId(), game);
     return true;
   }
   return false;
 }
Example #7
0
 @Override
 public boolean apply(Game game, Ability source) {
   Cost cost = new GenericManaCost(1);
   cost.clearPaid();
   if (cost.pay(source, game, source.getId(), source.getControllerId(), false)) {
     Permanent permanent = game.getPermanent(source.getFirstTarget());
     if (permanent != null) {
       permanent.damage(1, source.getId(), game, true, false);
       return true;
     }
     Player player = game.getPlayer(source.getFirstTarget());
     if (player != null) {
       player.damage(1, source.getSourceId(), game, false, true);
       return true;
     }
     return false;
   }
   return false;
 }
Example #8
0
 protected String getCostText() {
   StringBuilder sb = new StringBuilder();
   String costText = cost.getText();
   if (costText != null
       && !costText.toLowerCase().startsWith("discard")
       && !costText.toLowerCase().startsWith("sacrifice")
       && !costText.toLowerCase().startsWith("remove")) {
     sb.append("pay ");
   }
   return sb.append(costText).toString();
 }
Example #9
0
 protected static int playerPaysXGenericMana(Player player, Ability source, Game game) {
   int xValue = 0;
   boolean payed = false;
   while (player.canRespond() && !payed) {
     xValue =
         player.announceXMana(0, Integer.MAX_VALUE, "How much mana will you pay?", game, source);
     if (xValue > 0) {
       Cost cost = new GenericManaCost(xValue);
       payed = cost.pay(source, game, source.getSourceId(), player.getId(), false, null);
     } else {
       payed = true;
     }
   }
   game.informPlayers(
       new StringBuilder(player.getLogName())
           .append(" pays {")
           .append(xValue)
           .append("}.")
           .toString());
   return xValue;
 }
Example #10
0
 @Override
 public boolean apply(Game game, Ability source) {
   Player controller = game.getPlayer(source.getControllerId());
   if (controller != null) {
     boolean costPaid = false;
     for (UUID playerId : controller.getInRange()) {
       Cost cost =
           new SacrificeTargetCost(
               new TargetControlledPermanent(new FilterControlledLandPermanent()));
       Player player = game.getPlayer(playerId);
       if (player != null
           && cost.canPay(source, source.getSourceId(), playerId, game)
           && player.chooseUse(Outcome.Sacrifice, "Sacrifice a land?", game)
           && cost.pay(source, game, source.getSourceId(), playerId, true)) {
         costPaid = true;
       }
     }
     if (costPaid) {
       super.apply(game, source);
     }
     return true;
   }
   return false;
 }
  @Override
  public String getText(Mode mode) {
    StringBuilder sb = new StringBuilder("sacrifice {this} unless you ");
    String costText = cost.getText();
    if (costText.toLowerCase().startsWith("discard")
        || costText.toLowerCase().startsWith("remove")
        || costText.toLowerCase().startsWith("return")) {
      sb.append(costText.substring(0, 1).toLowerCase());
      sb.append(costText.substring(1));
    } else {
      sb.append("pay ").append(costText);
    }

    return sb.toString();
  }
Example #12
0
 /**
  * As we have ability in the stack, we need to update optional costs in original card. This
  * information will be used later by effects, e.g. to determine whether card was kicked or not.
  * E.g. Desolation Angel
  */
 private void updateOptionalCosts(int index) {
   Ability abilityOrig =
       spellCards.get(index).getAbilities().get(spellAbilities.get(index).getId());
   if (abilityOrig != null) {
     for (Object object : spellAbilities.get(index).getOptionalCosts()) {
       Cost cost = (Cost) object;
       for (Cost costOrig : abilityOrig.getOptionalCosts()) {
         if (cost.getId().equals(costOrig.getId())) {
           if (cost.isPaid()) {
             costOrig.setPaid();
           } else {
             costOrig.clearPaid();
           }
           break;
         }
       }
     }
   }
 }
Example #13
0
  @Override
  public boolean activate(Game game, boolean noMana) {
    Player controller = game.getPlayer(this.getControllerId());
    if (controller == null) {
      return false;
    }
    game.applyEffects();

    /* 20130201 - 601.2b
     * If the spell is modal the player announces the mode choice (see rule 700.2).
     */
    if (!getModes().choose(game, this)) {
      return false;
    }
    if (controller.isTestMode()) {
      if (!controller.addTargets(this, game)) {
        return false;
      }
    }

    getSourceObject(game);

    /* 20130201 - 601.2b
     * If the player wishes to splice any cards onto the spell (see rule 702.45), he
     * or she reveals those cards in his or her hand.
     */
    if (this.abilityType.equals(AbilityType.SPELL)) {
      game.getContinuousEffects().applySpliceEffects(this, game);
    }

    // if ability can be cast for no mana, clear the mana costs now, because additional mana costs
    // must be paid.
    // For Flashback ability can be set X before, so the X costs have to be restored for the
    // flashbacked ability
    if (noMana) {
      if (this.getManaCostsToPay().getVariableCosts().size() > 0) {
        int xValue = this.getManaCostsToPay().getX();
        this.getManaCostsToPay().clear();
        VariableManaCost xCosts = new VariableManaCost();
        xCosts.setAmount(xValue);
        this.getManaCostsToPay().add(xCosts);
      } else {
        this.getManaCostsToPay().clear();
      }
    }
    // 20130201 - 601.2b
    // If the spell has alternative or additional costs that will be paid as it's being cast such
    // as buyback, kicker, or convoke costs (see rules 117.8 and 117.9), the player announces his
    // or her intentions to pay any or all of those costs (see rule 601.2e).
    // A player can't apply two alternative methods of casting or two alternative costs to a single
    // spell.
    if (!activateAlternateOrAdditionalCosts(sourceObject, noMana, controller, game)) {
      if (getAbilityType().equals(AbilityType.SPELL)
          && ((SpellAbility) this)
              .getSpellAbilityType()
              .equals(SpellAbilityType.FACE_DOWN_CREATURE)) {
        return false;
      }
    }

    // 20121001 - 601.2b
    // If the spell has a variable cost that will be paid as it's being cast (such as an {X} in
    // its mana cost; see rule 107.3), the player announces the value of that variable.
    VariableManaCost variableManaCost = handleManaXCosts(game, noMana, controller);
    String announceString = handleOtherXCosts(game, controller);
    // For effects from cards like Void Winnower x costs have to be set
    if (this.getAbilityType().equals(AbilityType.SPELL)
        && game.replaceEvent(
            GameEvent.getEvent(
                GameEvent.EventType.CAST_SPELL_LATE, getId(), getSourceId(), getControllerId()),
            this)) {
      return false;
    }
    for (Mode mode : this.getModes().getSelectedModes()) {
      this.getModes().setActiveMode(mode);
      // 20121001 - 601.2c
      // 601.2c The player announces his or her choice of an appropriate player, object, or zone for
      // each target the spell requires. A spell may require some targets only if an alternative or
      // additional cost (such as a buyback or kicker cost), or a particular mode, was chosen for
      // it;
      // otherwise, the spell is cast as though it did not require those targets. If the spell has a
      // variable number of targets, the player announces how many targets he or she will choose
      // before
      // he or she announces those targets. The same target can't be chosen multiple times for any
      // one
      // instance of the word "target" on the spell. However, if the spell uses the word "target" in
      // multiple places, the same object, player, or zone can be chosen once for each instance of
      // the
      // word "target" (as long as it fits the targeting criteria). If any effects say that an
      // object
      // or player must be chosen as a target, the player chooses targets so that he or she obeys
      // the
      // maximum possible number of such effects without violating any rules or effects that say
      // that
      // an object or player can't be chosen as a target. The chosen players, objects, and/or zones
      // each become a target of that spell. (Any abilities that trigger when those players,
      // objects,
      // and/or zones become the target of a spell trigger at this point; they'll wait to be put on
      // the stack until the spell has finished being cast.)

      if (sourceObject != null
          && !this.getAbilityType()
              .equals(AbilityType.TRIGGERED)) { // triggered abilities check this already in
        // playerImpl.triggerAbility
        sourceObject.adjustTargets(this, game);
      }
      if (mode.getTargets().size() > 0
          && mode.getTargets()
                  .chooseTargets(
                      getEffects().get(0).getOutcome(), this.controllerId, this, noMana, game)
              == false) {
        if ((variableManaCost != null || announceString != null) && !game.isSimulation()) {
          game.informPlayer(
              controller,
              (sourceObject != null ? sourceObject.getIdName() : "")
                  + ": no valid targets with this value of X");
        }
        return false; // when activation of ability is canceled during target selection
      }
    } // end modes

    // TODO: Handle optionalCosts at the same time as already OptionalAdditionalSourceCosts are
    // handled.
    for (Cost cost : optionalCosts) {
      if (cost instanceof ManaCost) {
        cost.clearPaid();
        if (controller.chooseUse(
            Outcome.Benefit, "Pay optional cost " + cost.getText() + "?", this, game)) {
          manaCostsToPay.add((ManaCost) cost);
        }
      }
    }
    // 20100716 - 601.2e
    if (sourceObject != null) {
      sourceObject.adjustCosts(this, game);
      if (sourceObject instanceof Card) {
        for (Ability ability : ((Card) sourceObject).getAbilities(game)) {
          if (ability instanceof AdjustingSourceCosts) {
            ((AdjustingSourceCosts) ability).adjustCosts(this, game);
          }
        }
      } else {
        for (Ability ability : sourceObject.getAbilities()) {
          if (ability instanceof AdjustingSourceCosts) {
            ((AdjustingSourceCosts) ability).adjustCosts(this, game);
          }
        }
      }
    }

    // this is a hack to prevent mana abilities with mana costs from causing endless loops - pay
    // other costs first
    if (this instanceof ManaAbility
        && !costs.pay(this, game, sourceId, controllerId, noMana, null)) {
      logger.debug("activate mana ability failed - non mana costs");
      return false;
    }

    // 20101001 - 601.2e
    if (costModificationActive) {
      game.getContinuousEffects().costModification(this, game);
    } else {
      costModificationActive = true;
    }

    UUID activatorId = controllerId;
    if ((this instanceof ActivatedAbilityImpl)
        && ((ActivatedAbilityImpl) this).getActivatorId() != null) {
      activatorId = ((ActivatedAbilityImpl) this).getActivatorId();
    }

    // 20100716 - 601.2f  (noMana is not used here, because mana costs were cleared for this ability
    // before adding additional costs and applying cost modification effects)
    if (!manaCostsToPay.pay(this, game, sourceId, activatorId, false, null)) {
      return false; // cancel during mana payment
    }

    // 20100716 - 601.2g
    if (!costs.pay(this, game, sourceId, activatorId, noMana, null)) {
      logger.debug("activate failed - non mana costs");
      return false;
    }
    if (!game.isSimulation()) {
      // inform about x costs now, so canceled announcements are not shown in the log
      if (announceString != null) {
        game.informPlayers(announceString);
      }
      if (variableManaCost != null) {
        int xValue = getManaCostsToPay().getX();
        game.informPlayers(
            controller.getLogName()
                + " announces a value of "
                + xValue
                + " for "
                + variableManaCost.getText());
      }
    }
    activated = true;
    // fire if tapped for mana (may only fire now because else costs of ability itself can be payed
    // with mana of abilities that trigger for that event
    if (this.getAbilityType().equals(AbilityType.MANA)) {
      for (Cost cost : costs) {
        if (cost instanceof TapSourceCost) {
          Mana mana = null;
          Effect effect = getEffects().get(0);
          if (effect instanceof DynamicManaEffect) {
            mana = ((DynamicManaEffect) effect).getMana(game, this);
          } else if (effect instanceof BasicManaEffect) {
            mana = ((BasicManaEffect) effect).getMana(game, this);
          }
          if (mana != null
              && mana.getAny()
                  == 0) { // if mana == null or Any > 0 the event has to be fired in the mana effect
            // to know which mana was produced
            ManaEvent event =
                new ManaEvent(
                    GameEvent.EventType.TAPPED_FOR_MANA, sourceId, sourceId, controllerId, mana);
            if (!game.replaceEvent(event)) {
              game.fireEvent(event);
            }
          }
          break;
        }
      }
    }
    return true;
  }