Search in sources :

Example 81 with ApprovingObject

use of mage.ApprovingObject in project mage by magefree.

the class WordOfCommandTestFlashEffect method apply.

@Override
public boolean apply(Game game, Ability source) {
    Player sourceController = game.getPlayer(source.getControllerId());
    Player targetPlayer = game.getPlayer(source.getFirstTarget());
    MageObject sourceObject = game.getObject(source.getSourceId());
    Card card = null;
    if (sourceController != null && targetPlayer != null && sourceObject != null) {
        Player controller = null;
        Spell wordOfCommand = game.getSpell(source.getSourceId());
        if (wordOfCommand != null) {
            if (wordOfCommand.getCommandedBy() != null) {
                controller = game.getPlayer(wordOfCommand.getCommandedBy());
            } else {
                controller = game.getPlayer(sourceController.getTurnControlledBy());
            }
        }
        if (controller == null) {
            // reset the controller to avoid NPE
            controller = sourceController;
        }
        // Look at target opponent's hand and choose a card from it
        TargetCard targetCard = new TargetCard(Zone.HAND, new FilterCard());
        if (controller.choose(Outcome.Discard, targetPlayer.getHand(), targetCard, game)) {
            card = game.getCard(targetCard.getFirstTarget());
        }
        // You control that player until Word of Command finishes resolving
        CardUtil.takeControlUnderPlayerStart(game, controller, targetPlayer, true);
        // The player plays that card if able
        if (card != null) {
            // While doing so, the player can activate mana abilities only if they're from lands that player controls
            RestrictionEffect effect = new WordOfCommandCantActivateEffect();
            effect.setTargetPointer(new FixedTarget(targetPlayer.getId()));
            game.addEffect(effect, source);
            // and only if mana they produce is spent to activate other mana abilities of lands they control and/or play that card
            ManaPool manaPool = targetPlayer.getManaPool();
            manaPool.setForcedToPay(true);
            manaPool.storeMana();
            int bookmark = game.bookmarkState();
            boolean canPlay = checkPlayability(card, targetPlayer, game, source);
            while (canPlay && targetPlayer.canRespond() && !targetPlayer.playCard(card, game, false, new ApprovingObject(source, game))) {
                SpellAbility spellAbility = card.getSpellAbility();
                if (spellAbility != null) {
                    spellAbility.getManaCostsToPay().clear();
                    spellAbility.getManaCostsToPay().addAll(spellAbility.getManaCosts());
                    // force rollback if card was deemed playable
                    ((ManaCostsImpl) spellAbility.getManaCostsToPay()).forceManaRollback(game, manaPool);
                    canPlay = checkPlayability(card, targetPlayer, game, source);
                } else {
                    break;
                }
            }
            if (!canPlay) {
                game.informPlayers(targetPlayer.getLogName() + " didn't play " + card.getLogName() + " (card can't be played)");
            }
            // duplicate in case of a new mana pool existing - probably not necessary, but just in case
            manaPool.setForcedToPay(false);
            // a rollback creates a new mana pool for the player, so it's necessary to find it again
            manaPool = targetPlayer.getManaPool();
            manaPool.setForcedToPay(false);
            game.removeBookmark(bookmark);
            targetPlayer.resetStoredBookmark(game);
            for (RestrictionEffect eff : game.getContinuousEffects().getRestrictionEffects()) {
                if (eff instanceof WordOfCommandCantActivateEffect) {
                    eff.discard();
                    break;
                }
            }
            game.getContinuousEffects().removeInactiveEffects(game);
            Spell spell = game.getSpell(card.getId());
            if (spell != null) {
                // If the chosen card is cast as a spell, you control the player while that spell is resolving
                spell.setCommandedBy(controller.getId());
            }
        }
        wordOfCommand = game.getSpell(source.getSourceId());
        if (wordOfCommand != null) {
            // You control the player until Word of Command finishes resolving
            wordOfCommand.setCommandedBy(controller.getId());
        } else {
            CardUtil.takeControlUnderPlayerEnd(game, controller, targetPlayer);
        }
        return true;
    }
    return false;
}
Also used : FixedTarget(mage.target.targetpointer.FixedTarget) Player(mage.players.Player) ApprovingObject(mage.ApprovingObject) MageObject(mage.MageObject) TargetCard(mage.target.TargetCard) SpellAbility(mage.abilities.SpellAbility) ManaPool(mage.players.ManaPool) ManaCostsImpl(mage.abilities.costs.mana.ManaCostsImpl) Spell(mage.game.stack.Spell) TargetCard(mage.target.TargetCard) Card(mage.cards.Card) FilterCard(mage.filter.FilterCard) FilterCard(mage.filter.FilterCard) RestrictionEffect(mage.abilities.effects.RestrictionEffect)

Example 82 with ApprovingObject

use of mage.ApprovingObject in project mage by magefree.

the class WizardsSpellbookEffect method apply.

@Override
public boolean apply(Game game, Ability source) {
    Player player = game.getPlayer(source.getControllerId());
    Card card = game.getCard(getTargetPointer().getFirst(game, source));
    if (player == null || card == null) {
        return false;
    }
    UUID exileId = CardUtil.getExileZoneId(game, source);
    player.moveCardsToExile(card, source, game, true, exileId, CardUtil.getSourceName(game, source));
    if (level < 3) {
        Card copiedCard = game.copyCard(card, source, source.getControllerId());
        if (!player.chooseUse(Outcome.Benefit, "Cast " + copiedCard.getName() + (level == 1 ? "?" : " by paying {1}?"), source, game)) {
            return false;
        }
        SpellAbility spellAbility = player.chooseAbilityForCast(copiedCard, game, level == 2);
        if (spellAbility == null) {
            return false;
        }
        game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), Boolean.TRUE);
        if (level == 2) {
            player.setCastSourceIdWithAlternateMana(copiedCard.getId(), new ManaCostsImpl<>("{1}"), null);
        }
        player.cast(spellAbility, game, false, new ApprovingObject(source, game));
        game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), null);
        return true;
    }
    ExileZone exile = game.getExile().getExileZone(exileId);
    if (exile == null || exile.isEmpty()) {
        return true;
    }
    Set<Card> cards = new HashSet<>();
    for (Card exiledCard : exile.getCards(game)) {
        cards.add(game.copyCard(exiledCard, source, source.getControllerId()));
    }
    while (!cards.isEmpty()) {
        for (Card copiedCard : cards) {
            if (!player.chooseUse(Outcome.PlayForFree, "Cast " + copiedCard.getName() + " without paying its mana cost?", source, game)) {
                continue;
            }
            game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), Boolean.TRUE);
            player.cast(player.chooseAbilityForCast(copiedCard, game, true), game, true, new ApprovingObject(source, game));
            game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), null);
        }
        if (!player.chooseUse(Outcome.Neutral, "Continue casting exiled cards?", source, game)) {
            break;
        }
        cards.removeIf(c -> game.getState().getZone(c.getId()) != Zone.EXILED);
    }
    return true;
}
Also used : Player(mage.players.Player) ApprovingObject(mage.ApprovingObject) ExileZone(mage.game.ExileZone) SpellAbility(mage.abilities.SpellAbility) UUID(java.util.UUID) Card(mage.cards.Card) HashSet(java.util.HashSet)

Example 83 with ApprovingObject

use of mage.ApprovingObject in project mage by magefree.

the class ActivatedAbilityImpl method canActivate.

/**
 * Activated ability check, not spells. It contains costs and targets legality too.
 * <p>
 * WARNING, don't forget to call super.canActivate on override in card's code in most cases.
 *
 * @param playerId
 * @param game
 * @return
 */
@Override
public ActivationStatus canActivate(UUID playerId, Game game) {
    // 20091005 - 602.2
    if (!(hasMoreActivationsThisTurn(game) && (condition == null || condition.apply(game, this)))) {
        return ActivationStatus.getFalse();
    }
    if (!this.checkTargetController(playerId, game)) {
        return ActivationStatus.getFalse();
    }
    // timing check
    // 20091005 - 602.5d/602.5e
    boolean asInstant;
    ApprovingObject approvingObject = game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game);
    asInstant = approvingObject != null;
    asInstant |= (timing == TimingRule.INSTANT);
    if (!asInstant && !game.canPlaySorcery(playerId)) {
        return ActivationStatus.getFalse();
    }
    // targets and costs check
    if (!costs.canPay(this, this, playerId, game) || !canChooseTarget(game, playerId)) {
        return ActivationStatus.getFalse();
    }
    // all fine, can be activated
    // TODO: WTF, must be rework to remove data change in canActivate call
    // (it can be called from any place by any player or card).
    // game.inCheckPlayableState() can't be a help here cause some cards checking activating status,
    // activatorId must be removed
    this.activatorId = playerId;
    return new ActivationStatus(true, approvingObject);
}
Also used : ApprovingObject(mage.ApprovingObject)

Example 84 with ApprovingObject

use of mage.ApprovingObject in project mage by magefree.

the class ContinuousEffects method asThough.

/**
 * @param objectId        object to check
 * @param type
 * @param affectedAbility null if check full object or ability if check only one ability from that object
 * @param controllerId
 * @param game
 * @return sourceId of the permitting effect if any exists otherwise returns null
 */
public ApprovingObject asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
    // usage check: effect must apply for specific ability only, not to full object (example: PLAY_FROM_NOT_OWN_HAND_ZONE)
    if (type.needAffectedAbility() && affectedAbility == null) {
        throw new IllegalArgumentException("ERROR, you can't call asThough check to whole object, call it with affected ability instead: " + type);
    }
    // need it then disable that check or add extra param to AsThoughEffectType like needAffectedAbilityOrFullObject
    if (!type.needAffectedAbility() && affectedAbility != null) {
        throw new IllegalArgumentException("ERROR, you can't call AsThough check to affected ability, call it with empty affected ability instead: " + type);
    }
    List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(type, game);
    if (!asThoughEffectsList.isEmpty()) {
        MageObject objectToCheck;
        if (affectedAbility != null) {
            objectToCheck = affectedAbility.getSourceObject(game);
        } else {
            objectToCheck = game.getCard(objectId);
        }
        UUID idToCheck;
        if (!type.needPlayCardAbility() && objectToCheck instanceof SplitCardHalf) {
            // each split side uses own characteristics to check for playing, all other cases must use main card
            // rules:
            // 708.4. In every zone except the stack, the characteristics of a split card are those of its two halves combined.
            idToCheck = ((SplitCardHalf) objectToCheck).getMainCard().getId();
        } else if (!type.needPlayCardAbility() && objectToCheck instanceof AdventureCardSpell) {
            // adventure spell uses alternative characteristics for spell/stack, all other cases must use main card
            idToCheck = ((AdventureCardSpell) objectToCheck).getMainCard().getId();
        } else if (!type.needPlayCardAbility() && objectToCheck instanceof ModalDoubleFacesCardHalf) {
            // each mdf side uses own characteristics to check for playing, all other cases must use main card
            // rules:
            // "If an effect allows you to play a land or cast a spell from among a group of cards,
            // you may play or cast a modal double-faced card with any face that fits the criteria
            // of that effect. For example, if Sejiri Shelter / Sejiri Glacier is in your graveyard
            // and an effect allows you to play lands from your graveyard, you could play Sejiri Glacier.
            // That effect doesn't allow you to cast Sejiri Shelter."
            idToCheck = ((ModalDoubleFacesCardHalf) objectToCheck).getMainCard().getId();
        } else {
            idToCheck = objectId;
        }
        Set<ApprovingObject> possibleApprovingObjects = new HashSet<>();
        for (AsThoughEffect effect : asThoughEffectsList) {
            Set<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
            for (Ability ability : abilities) {
                if (affectedAbility == null) {
                    // applies to full object (one effect can be used in multiple abilities)
                    if (effect.applies(idToCheck, ability, controllerId, game)) {
                        if (effect.isConsumable() && !game.inCheckPlayableState()) {
                            possibleApprovingObjects.add(new ApprovingObject(ability, game));
                        } else {
                            return new ApprovingObject(ability, game);
                        }
                    }
                } else {
                    // filter play abilities (no need to check it in every effect's code)
                    if (type.needPlayCardAbility() && !affectedAbility.getAbilityType().isPlayCardAbility()) {
                        continue;
                    }
                    if (effect.applies(idToCheck, affectedAbility, ability, game, controllerId)) {
                        if (effect.isConsumable() && !game.inCheckPlayableState()) {
                            possibleApprovingObjects.add(new ApprovingObject(ability, game));
                        } else {
                            return new ApprovingObject(ability, game);
                        }
                    }
                }
            }
        }
        if (possibleApprovingObjects.size() == 1) {
            return possibleApprovingObjects.iterator().next();
        } else if (possibleApprovingObjects.size() > 1) {
            // Select the ability that you use to permit the action
            Map<String, String> keyChoices = new HashMap<>();
            for (ApprovingObject approvingObject : possibleApprovingObjects) {
                MageObject mageObject = game.getObject(approvingObject.getApprovingAbility().getSourceId());
                String choiceKey = approvingObject.getApprovingAbility().getId().toString();
                String choiceValue;
                if (mageObject == null) {
                    choiceValue = approvingObject.getApprovingAbility().getRule();
                } else {
                    choiceValue = mageObject.getIdName() + ": " + approvingObject.getApprovingAbility().getRule(mageObject.getName());
                }
                keyChoices.put(choiceKey, choiceValue);
            }
            Choice choicePermitting = new ChoiceImpl(true);
            choicePermitting.setMessage("Choose the permitting object");
            choicePermitting.setKeyChoices(keyChoices);
            Player player = game.getPlayer(controllerId);
            player.choose(Outcome.Detriment, choicePermitting, game);
            for (ApprovingObject approvingObject : possibleApprovingObjects) {
                if (approvingObject.getApprovingAbility().getId().toString().equals(choicePermitting.getChoiceKey())) {
                    return approvingObject;
                }
            }
        }
    }
    return null;
}
Also used : StaticAbility(mage.abilities.StaticAbility) Ability(mage.abilities.Ability) Player(mage.players.Player) ApprovingObject(mage.ApprovingObject) Choice(mage.choices.Choice) MageObject(mage.MageObject) ChoiceImpl(mage.choices.ChoiceImpl)

Example 85 with ApprovingObject

use of mage.ApprovingObject in project mage by magefree.

the class MadWizardsLairEffect method apply.

@Override
public boolean apply(Game game, Ability source) {
    Player player = game.getPlayer(source.getControllerId());
    if (player == null) {
        return false;
    }
    Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 3));
    if (player.drawCards(3, source, game) != cards.size()) {
        return true;
    }
    player.revealCards(source, cards, game);
    TargetCardInHand target = new TargetCardInHand(0, 1, StaticFilters.FILTER_CARD_NON_LAND);
    player.choose(Outcome.PlayForFree, cards, target, game);
    Card card = player.getHand().get(target.getFirstTarget(), game);
    if (card == null) {
        return true;
    }
    game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
    player.cast(player.chooseAbilityForCast(card, game, true), game, true, new ApprovingObject(source, game));
    game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
    return true;
}
Also used : Player(mage.players.Player) ApprovingObject(mage.ApprovingObject) TargetCardInHand(mage.target.common.TargetCardInHand) Cards(mage.cards.Cards) CardsImpl(mage.cards.CardsImpl) Card(mage.cards.Card)

Aggregations

ApprovingObject (mage.ApprovingObject)111 Player (mage.players.Player)109 Card (mage.cards.Card)77 FilterCard (mage.filter.FilterCard)53 TargetCard (mage.target.TargetCard)30 MageObject (mage.MageObject)20 FilterInstantOrSorceryCard (mage.filter.common.FilterInstantOrSorceryCard)17 CardsImpl (mage.cards.CardsImpl)16 Permanent (mage.game.permanent.Permanent)16 UUID (java.util.UUID)15 TargetCardInHand (mage.target.common.TargetCardInHand)13 ManaValuePredicate (mage.filter.predicate.mageobject.ManaValuePredicate)11 FilterNonlandCard (mage.filter.common.FilterNonlandCard)10 TargetCardInExile (mage.target.common.TargetCardInExile)10 ExileZone (mage.game.ExileZone)9 TargetCardInLibrary (mage.target.common.TargetCardInLibrary)9 Cards (mage.cards.Cards)8 Spell (mage.game.stack.Spell)8 Target (mage.target.Target)7 FixedTarget (mage.target.targetpointer.FixedTarget)7