diff --git a/Mage.Sets/src/mage/cards/b/BolassCitadel.java b/Mage.Sets/src/mage/cards/b/BolassCitadel.java index b66b461f2b..32da651d46 100644 --- a/Mage.Sets/src/mage/cards/b/BolassCitadel.java +++ b/Mage.Sets/src/mage/cards/b/BolassCitadel.java @@ -1,118 +1,122 @@ -package mage.cards.b; - -import mage.abilities.Ability; -import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.Costs; -import mage.abilities.costs.CostsImpl; -import mage.abilities.costs.common.PayLifeCost; -import mage.abilities.costs.common.SacrificeTargetCost; -import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.AsThoughEffectImpl; -import mage.abilities.effects.common.LoseLifeOpponentsEffect; -import mage.abilities.effects.common.continuous.LookAtTopCardOfLibraryAnyTimeEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.common.FilterControlledPermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.game.Game; -import mage.players.Player; -import mage.target.common.TargetControlledPermanent; - -import java.util.UUID; -import mage.abilities.costs.Cost; - -/** - * @author jeffwadsworth - */ -public final class BolassCitadel extends CardImpl { - - private static final FilterControlledPermanent filter = new FilterControlledPermanent("nonland permanents"); - - static { - filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); - } - - public BolassCitadel(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}{B}{B}{B}"); - - this.addSuperType(SuperType.LEGENDARY); - - // You may look at the top card of your library any time. - this.addAbility(new SimpleStaticAbility(new LookAtTopCardOfLibraryAnyTimeEffect())); - - // You may play the top card of your library. If you cast a spell this way, pay life equal to its converted mana cost rather than pay its mana cost. - this.addAbility(new SimpleStaticAbility(new BolassCitadelPlayTheTopCardEffect())); - - // {T}, Sacrifice ten nonland permanents: Each opponent loses 10 life. - Ability ability = new SimpleActivatedAbility(new LoseLifeOpponentsEffect(10), new TapSourceCost()); - ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent( - 10, 10, filter, true - ))); - this.addAbility(ability); - } - - private BolassCitadel(final BolassCitadel card) { - super(card); - } - - @Override - public BolassCitadel copy() { - return new BolassCitadel(this); - } -} - -class BolassCitadelPlayTheTopCardEffect extends AsThoughEffectImpl { - - BolassCitadelPlayTheTopCardEffect() { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, - Duration.WhileOnBattlefield, Outcome.AIDontUseIt); // AI will need help with this - staticText = "You may play the top card of your library. If you cast a spell this way, " - + "pay life equal to its converted mana cost rather than pay its mana cost."; - } - - private BolassCitadelPlayTheTopCardEffect(final BolassCitadelPlayTheTopCardEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public BolassCitadelPlayTheTopCardEffect copy() { - return new BolassCitadelPlayTheTopCardEffect(this); - } - - @Override - public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - Card cardOnTop = game.getCard(objectId); - if (cardOnTop == null) { - return false; - } - if (affectedControllerId.equals(source.getControllerId()) - && cardOnTop.isOwnedBy(source.getControllerId())) { - Player controller = game.getPlayer(cardOnTop.getOwnerId()); - if (controller != null - && cardOnTop.equals(controller.getLibrary().getFromTop(game))) { - // add the life cost first - PayLifeCost cost = new PayLifeCost(cardOnTop.getManaCost().convertedManaCost()); - Costs costs = new CostsImpl(); - costs.add(cost); - // check for additional costs that must be paid - if (cardOnTop.getSpellAbility() != null) { - for (Cost additionalCost : cardOnTop.getSpellAbility().getCosts()) { - costs.add(additionalCost); - } - } - controller.setCastSourceIdWithAlternateMana(cardOnTop.getId(), null, costs); - return true; - } - } - return false; - } -} +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.ActivatedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.Costs; +import mage.abilities.costs.CostsImpl; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.abilities.effects.common.continuous.LookAtTopCardOfLibraryAnyTimeEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; +import mage.abilities.costs.Cost; + +/** + * @author jeffwadsworth + */ +public final class BolassCitadel extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("nonland permanents"); + + static { + filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); + } + + public BolassCitadel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}{B}{B}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + + // You may look at the top card of your library any time. + this.addAbility(new SimpleStaticAbility(new LookAtTopCardOfLibraryAnyTimeEffect())); + + // You may play the top card of your library. If you cast a spell this way, pay life equal to its converted mana cost rather than pay its mana cost. + this.addAbility(new SimpleStaticAbility(new BolassCitadelPlayTheTopCardEffect())); + + // {T}, Sacrifice ten nonland permanents: Each opponent loses 10 life. + Ability ability = new SimpleActivatedAbility(new LoseLifeOpponentsEffect(10), new TapSourceCost()); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent( + 10, 10, filter, true + ))); + this.addAbility(ability); + } + + private BolassCitadel(final BolassCitadel card) { + super(card); + } + + @Override + public BolassCitadel copy() { + return new BolassCitadel(this); + } +} + +class BolassCitadelPlayTheTopCardEffect extends AsThoughEffectImpl { + + BolassCitadelPlayTheTopCardEffect() { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, + Duration.WhileOnBattlefield, Outcome.AIDontUseIt); // AI will need help with this + staticText = "You may play the top card of your library. If you cast a spell this way, " + + "pay life equal to its converted mana cost rather than pay its mana cost."; + } + + private BolassCitadelPlayTheTopCardEffect(final BolassCitadelPlayTheTopCardEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public BolassCitadelPlayTheTopCardEffect copy() { + return new BolassCitadelPlayTheTopCardEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + return applies(objectId, null, source, game, affectedControllerId); + } + + @Override + public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID playerId) { + Card cardOnTop = game.getCard(objectId); + if (cardOnTop == null) { + return false; + } + if (playerId.equals(source.getControllerId()) + && cardOnTop.isOwnedBy(source.getControllerId())) { + Player controller = game.getPlayer(cardOnTop.getOwnerId()); + if (controller != null + && cardOnTop.equals(controller.getLibrary().getFromTop(game))) { + if (affectedAbility instanceof ActivatedAbility) { + ActivatedAbility activatedAbility = (ActivatedAbility) affectedAbility; + // add the life cost first + PayLifeCost cost = new PayLifeCost(activatedAbility.getManaCosts().convertedManaCost()); + Costs costs = new CostsImpl(); + costs.add(cost); + costs.addAll(activatedAbility.getCosts()); + controller.setCastSourceIdWithAlternateMana(activatedAbility.getSourceId(), null, costs); + return true; + } + } + } + return false; + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/BolassCitadelTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/BolassCitadelTest.java new file mode 100644 index 0000000000..18445242f5 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/BolassCitadelTest.java @@ -0,0 +1,62 @@ +package org.mage.test.cards.cost.alternate; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +public class BolassCitadelTest extends CardTestPlayerBase { + @Test + public void testCastEagerCadet() { + /* + * Eager Cadet + * Creature — Human Soldier + * 1/1 + */ + setStrictChooseMode(true); + addCard(Zone.BATTLEFIELD, playerA, "Forest"); + addCard(Zone.BATTLEFIELD, playerA, "Bolas's Citadel"); + removeAllCardsFromLibrary(playerA); + addCard(Zone.LIBRARY, playerA, "Eager Cadet"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Eager Cadet"); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertAllCommandsUsed(); + assertHandCount(playerA, 0); + assertPermanentCount(playerA, "Eager Cadet", 1); + assertGraveyardCount(playerA,0); + assertLife(playerA, 19); + } + + @Test + public void testCastTreatsToShare() { + /* + * Curious Pair {1}{G} + * Creature — Human Peasant + * 1/3 + * ---- + * Treats to Share {G} + * Sorcery — Adventure + * Create a Food token. + */ + setStrictChooseMode(true); + addCard(Zone.BATTLEFIELD, playerA, "Forest"); + addCard(Zone.BATTLEFIELD, playerA, "Bolas's Citadel"); + removeAllCardsFromLibrary(playerA); + addCard(Zone.LIBRARY, playerA, "Curious Pair"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Treats to Share"); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertAllCommandsUsed(); + assertTapped("Forest", false); + assertHandCount(playerA, 0); + assertPermanentCount(playerA, "Food", 1); + assertExileCount(playerA, "Curious Pair", 1); + assertGraveyardCount(playerA,0); + assertLife(playerA, 19); + } +}