/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.keyword;
import java.util.List;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.SpecialAction;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.ExileFromGraveCost;
import mage.abilities.costs.mana.AlternateManaPaymentAbility;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.AbilityType;
import mage.constants.ManaType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.ManaPool;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
import mage.util.CardUtil;
/**
* 702.65. Delve 702.65a Delve is a static ability that functions while the
* spell with delve is on the stack. “Delve” means “For each generic mana in
* this spell’s total cost, you may exile a card from your graveyard rather than
* pay that mana.” The delve ability isn't an additional or alternative cost and
* applies only after the total cost of the spell with delve is determined.
* 702.65b Multiple instances of delve on the same spell are redundant.
*
* The rules for delve have changed slightly since it was last in an expansion.
* Previously, delve reduced the cost to cast a spell. Under the current rules,
* you exile cards from your graveyard at the same time you pay the spell’s
* cost. Exiling a card this way is simply another way to pay that cost. * Delve
* doesn't change a spell’s mana cost or converted mana cost. For example, Dead
* Drop’s converted mana cost is 10 even if you exiled three cards to cast it. *
* You can’t exile cards to pay for the colored mana requirements of a spell
* with delve. * You can’t exile more cards than the generic mana requirement of
* a spell with delve. For example, you can’t exile more than nine cards from
* your graveyard to cast Dead Drop. * Because delve isn't an alternative cost,
* it can be used in conjunction with alternative costs.
*
* @author LevelX2
*
* TODO: Change card exiling to a way to pay mana costs, now it's maybe not
* possible to pay costs from effects that increase the mana costs.
*/
public class DelveAbility extends SimpleStaticAbility implements AlternateManaPaymentAbility {
public DelveAbility() {
super(Zone.STACK, null);
this.setRuleAtTheTop(true);
}
public DelveAbility(final DelveAbility ability) {
super(ability);
}
@Override
public DelveAbility copy() {
return new DelveAbility(this);
}
@Override
public String getRule() {
return "Delve <i>(Each card you exile from your graveyard while casting this spell pays for {1}.)</i>";
}
@Override
public void addSpecialAction(Ability source, Game game, ManaCost unpaid) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null && !controller.getGraveyard().isEmpty()) {
if (unpaid.getMana().getGeneric() > 0 && source.getAbilityType() == AbilityType.SPELL) {
SpecialAction specialAction = new DelveSpecialAction();
specialAction.setControllerId(source.getControllerId());
specialAction.setSourceId(source.getSourceId());
int unpaidAmount = unpaid.getMana().getGeneric();
if (!controller.getManaPool().isAutoPayment() && unpaidAmount > 1) {
unpaidAmount = 1;
}
specialAction.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(
0, Math.min(controller.getGraveyard().size(), unpaidAmount), new FilterCard(), true)));
if (specialAction.canActivate(source.getControllerId(), game)) {
game.getState().getSpecialActions().add(specialAction);
}
}
}
}
}
class DelveSpecialAction extends SpecialAction {
public DelveSpecialAction() {
super(Zone.ALL, true);
this.addEffect(new DelveEffect());
}
public DelveSpecialAction(final DelveSpecialAction ability) {
super(ability);
}
@Override
public DelveSpecialAction copy() {
return new DelveSpecialAction(this);
}
}
class DelveEffect extends OneShotEffect {
public DelveEffect() {
super(Outcome.Benefit);
this.staticText = "Delve (Each card you exile from your graveyard while casting this spell pays for {1}.)";
}
public DelveEffect(final DelveEffect effect) {
super(effect);
}
@Override
public DelveEffect copy() {
return new DelveEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
ExileFromGraveCost exileFromGraveCost = (ExileFromGraveCost) source.getCosts().get(0);
List<Card> exiledCards = exileFromGraveCost.getExiledCards();
if (!exiledCards.isEmpty()) {
Cards toDelve = new CardsImpl();
for (Card card : exiledCards) {
toDelve.add(card);
}
ManaPool manaPool = controller.getManaPool();
manaPool.addMana(new Mana(0, 0, 0, 0, 0, 0, 0, toDelve.size()), game, source);
manaPool.unlockManaType(ManaType.COLORLESS);
String keyString = CardUtil.getCardZoneString("delvedCards", source.getSourceId(), game);
@SuppressWarnings("unchecked")
Cards delvedCards = (Cards) game.getState().getValue(keyString);
if (delvedCards == null) {
game.getState().setValue(keyString, toDelve);
} else {
delvedCards.addAll(toDelve);
}
}
return true;
}
return false;
}
}