mirror of
https://github.com/correl/mage.git
synced 2025-03-29 17:00:07 -09:00
Fix Bolas's Citadel and add test.
This commit is contained in:
parent
b17bf1ac9f
commit
b0bac1f751
2 changed files with 184 additions and 118 deletions
Mage.Sets/src/mage/cards/b
Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue