This commit is contained in:
Jeff 2019-03-07 18:11:21 -06:00
parent e08fe53672
commit 697706748a

View file

@ -1,15 +1,11 @@
package mage.cards.a; package mage.cards.a;
import java.util.EnumSet;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
import mage.abilities.costs.Costs;
import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.cards.*; import mage.cards.*;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.*; import mage.constants.*;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.game.ExileZone; import mage.game.ExileZone;
@ -18,11 +14,9 @@ import mage.players.Player;
import mage.target.TargetCard; import mage.target.TargetCard;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
/** /**
* *
@ -50,20 +44,19 @@ public class AminatousAugury extends CardImpl {
} }
class AminatousAuguryEffect extends OneShotEffect{ class AminatousAuguryEffect extends OneShotEffect {
public AminatousAuguryEffect() { public AminatousAuguryEffect() {
super(Outcome.PlayForFree); super(Outcome.PlayForFree);
staticText = "Exile the top eight cards of your library. You may put a land card from among them onto the" + staticText = "Exile the top eight cards of your library. You may put a land card from among them onto the"
" battlefield. Until end of turn, for each nonland card type, you may cast a card of that type from" + + " battlefield. Until end of turn, for each nonland card type, you may cast a card of that type from"
" among the exiled cards without paying its mana cost."; + " among the exiled cards without paying its mana cost.";
} }
public AminatousAuguryEffect(final AminatousAuguryEffect effect) { public AminatousAuguryEffect(final AminatousAuguryEffect effect) {
super(effect); super(effect);
} }
@Override @Override
public AminatousAuguryEffect copy() { public AminatousAuguryEffect copy() {
return new AminatousAuguryEffect(this); return new AminatousAuguryEffect(this);
@ -97,9 +90,8 @@ class AminatousAuguryEffect extends OneShotEffect{
} }
} }
} }
AminatousAuguryExileHandler exileHandler = new AminatousAuguryExileHandler(cardsToCast, source, game); for (Card card : cardsToCast.getCards(StaticFilters.FILTER_CARD_NON_LAND, game)) {
for (Card card:cardsToCast.getCards(StaticFilters.FILTER_CARD_NON_LAND,game)) { AminatousAuguryCastFromExileEffect effect = new AminatousAuguryCastFromExileEffect();
AminatousAuguryCastFromExileEffect effect = new AminatousAuguryCastFromExileEffect(card.getCardType(), exileHandler);
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
game.addEffect(effect, source); game.addEffect(effect, source);
} }
@ -109,20 +101,14 @@ class AminatousAuguryEffect extends OneShotEffect{
} }
class AminatousAuguryCastFromExileEffect extends AsThoughEffectImpl { class AminatousAuguryCastFromExileEffect extends AsThoughEffectImpl {
private final AminatousAuguryExileHandler cardTypeHandler;
private final EnumSet<CardType> cardType;
public AminatousAuguryCastFromExileEffect(EnumSet<CardType> cardType, AminatousAuguryExileHandler cardTypeTracker) { public AminatousAuguryCastFromExileEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.PlayForFree); super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.PlayForFree);
this.cardTypeHandler = cardTypeTracker;
this.cardType = cardType;
staticText = "Cast this card without paying its mana cost"; staticText = "Cast this card without paying its mana cost";
} }
public AminatousAuguryCastFromExileEffect(final AminatousAuguryCastFromExileEffect effect) { public AminatousAuguryCastFromExileEffect(final AminatousAuguryCastFromExileEffect effect) {
super(effect); super(effect);
this.cardTypeHandler = effect.cardTypeHandler;
this.cardType = effect.cardType;
} }
@Override @Override
@ -137,117 +123,33 @@ class AminatousAuguryCastFromExileEffect extends AsThoughEffectImpl {
@Override @Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
if (!cardTypeHandler.atLeastOneAvailable(cardType)){ Player player = game.getPlayer(affectedControllerId);
return false; EnumSet<CardType> cardTypes = EnumSet.noneOf(CardType.class);
Boolean checkType = false;
if (game.getState().getValue(source.getSourceId().toString() + "cardTypes") != null) {
cardTypes = (EnumSet<CardType>) game.getState().getValue(source.getSourceId().toString() + "cardTypes");
} }
if (sourceId != null && sourceId.equals(getTargetPointer().getFirst(game, source)) //TODO add code for choosing from multiple card types and adding additional costs to the card
if (player != null
&& sourceId != null
&& sourceId.equals(getTargetPointer().getFirst(game, source))
&& affectedControllerId.equals(source.getControllerId())) { && affectedControllerId.equals(source.getControllerId())) {
Card card = game.getCard(sourceId); Card card = game.getCard(sourceId);
if (card != null && game.getState().getZone(sourceId) == Zone.EXILED) { if (card != null
Player player = game.getPlayer(affectedControllerId); && game.getState().getZone(sourceId) == Zone.EXILED) {
Costs costs = card.getSpellAbility().getCosts().copy(); for (CardType cardT : cardTypes) {
costs.add(new ConsumeCardTypeCost(cardType, cardTypeHandler)); if (card.getCardType().contains(cardT)) {
player.setCastSourceIdWithAlternateMana(sourceId, null, costs); checkType = true;
}
}
if (!checkType) {
player.setCastSourceIdWithAlternateMana(sourceId, null, null);
cardTypes.addAll(card.getCardType());
game.getState().setValue(source.getSourceId().toString() + "cardTypes", cardTypes);
return true; return true;
} }
} }
}
return false; return false;
} }
} }
/**
* Tracks which card types have already been cast, and provides utility functions for confirming used types.
* (one ExileHandler is shared between all cards from a single cast of Animatou's Augury)
*/
class AminatousAuguryExileHandler {
private final EnumSet<CardType> usedCardTypes;
public AminatousAuguryExileHandler(Cards cards, Ability source, Game game){
usedCardTypes = EnumSet.noneOf(CardType.class);
}
public EnumSet<CardType> availableTypes(EnumSet<CardType> types){
EnumSet<CardType> available = EnumSet.copyOf(types);
available.removeAll(usedCardTypes);
return available;
}
public boolean atLeastOneAvailable(EnumSet<CardType> types){
EnumSet<CardType> available = availableTypes(types);
return !available.isEmpty();
}
public boolean useCardType(CardType type){
if (usedCardTypes.contains(type)){
return false;
}
usedCardTypes.add(type);
return true;
}
}
/**
* Allows the user to choose one of the given card types
*/
class CardTypeChoice extends ChoiceImpl{
public CardTypeChoice (EnumSet<CardType> types){
super(false);
for (CardType type:types){
this.choices.add(type+"");
}
this.message = "Choose card type to cast as";
}
}
class ConsumeCardTypeCost extends CostImpl{
final private AminatousAuguryExileHandler exileHandler;
final private EnumSet<CardType> types;
public ConsumeCardTypeCost (EnumSet<CardType> types, AminatousAuguryExileHandler exileHandler){
this.exileHandler = exileHandler;
this.types = types;
this.text = "Cast as "+types;
}
@Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
return exileHandler.atLeastOneAvailable(types);
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
if (isPaid()){
return true;
}
CardType choiceType;
EnumSet<CardType> availableChoices = exileHandler.availableTypes(types);
if (availableChoices.size()==1){
// if there is only one possibility, don't need to prompt for a choice
choiceType = availableChoices.iterator().next();
}else {
Choice choice = new CardTypeChoice(availableChoices);
if (!game.getPlayer(controllerId).choose(Outcome.Neutral, choice, game)) {
return false;
}
Optional<CardType> optionalChoice = Arrays.stream(CardType.values()).filter(type -> type.toString().equals(choice.getChoice())).findAny();
if (optionalChoice.isPresent()){
choiceType = optionalChoice.get();
}else{
return false;
}
}
paid = exileHandler.useCardType(choiceType);
return paid;
}
@Override
public Cost copy() {
return new ConsumeCardTypeCost(types, exileHandler);
}
}