Search in sources :

Example 31 with StackObject

use of mage.game.stack.StackObject in project mage by magefree.

the class SharkTyphoonTriggeredAbility method checkTrigger.

@Override
public boolean checkTrigger(GameEvent event, Game game) {
    if (!event.getSourceId().equals(this.getSourceId())) {
        return false;
    }
    StackObject object = game.getStack().getStackObject(event.getSourceId());
    if (object == null || !(object.getStackAbility() instanceof CyclingAbility)) {
        return false;
    }
    this.getEffects().clear();
    this.addEffect(new CreateTokenEffect(new SharkToken(object.getStackAbility().getManaCostsToPay().getX())));
    return true;
}
Also used : CyclingAbility(mage.abilities.keyword.CyclingAbility) StackObject(mage.game.stack.StackObject) CreateTokenEffect(mage.abilities.effects.common.CreateTokenEffect) SharkToken(mage.game.permanent.token.SharkToken)

Example 32 with StackObject

use of mage.game.stack.StackObject in project mage by magefree.

the class SwiftSilenceEffect method apply.

@Override
public boolean apply(Game game, Ability source) {
    List<Spell> spellsToCounter = new LinkedList<>();
    for (StackObject stackObject : game.getStack()) {
        if (stackObject instanceof Spell && !stackObject.getId().equals(source.getSourceObject(game).getId())) {
            spellsToCounter.add((Spell) stackObject);
        }
    }
    int toDraw = 0;
    for (Spell spell : spellsToCounter) {
        if (game.getStack().counter(spell.getId(), source, game)) {
            toDraw++;
        }
    }
    Player controller = game.getPlayer(source.getControllerId());
    if (toDraw > 0 && controller != null) {
        controller.drawCards(toDraw, source, game);
    }
    return true;
}
Also used : Player(mage.players.Player) StackObject(mage.game.stack.StackObject) Spell(mage.game.stack.Spell) LinkedList(java.util.LinkedList)

Example 33 with StackObject

use of mage.game.stack.StackObject in project mage by magefree.

the class WildMagicSorcererWatcher method apply.

@Override
public boolean apply(Game game, Ability source) {
    Player controller = game.getPlayer(source.getControllerId());
    if (controller != null) {
        for (StackObject stackObject : game.getStack()) {
            // only spells cast, so no copies of spells
            if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.isControlledBy(source.getControllerId())) {
                Spell spell = (Spell) stackObject;
                WildMagicSorcererWatcher watcher = game.getState().getWatcher(WildMagicSorcererWatcher.class);
                if (watcher != null && FirstSpellCastFromExileEachTurnCondition.instance.apply(game, source)) {
                    game.getState().addOtherAbility(spell.getCard(), cascadeAbility);
                }
            }
        }
        return true;
    }
    return false;
}
Also used : Player(mage.players.Player) StackObject(mage.game.stack.StackObject) Spell(mage.game.stack.Spell)

Example 34 with StackObject

use of mage.game.stack.StackObject in project mage by magefree.

the class TestPlayer method chooseTarget.

@Override
public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) {
    UUID abilityControllerId = computerPlayer.getId();
    if (target.getTargetController() != null && target.getAbilityController() != null) {
        abilityControllerId = target.getAbilityController();
    }
    UUID sourceId = source != null ? source.getSourceId() : null;
    assertAliasSupportInTargets(true);
    if (!targets.isEmpty()) {
        // skip targets
        if (targets.get(0).equals(TARGET_SKIP)) {
            Assert.assertTrue("found skip target, but it require more targets, needs " + (target.getMinNumberOfTargets() - target.getTargets().size()) + " more", target.getTargets().size() >= target.getMinNumberOfTargets());
            targets.remove(0);
            return true;
        }
        // control miss implementation
        Set<Zone> targetCardZonesChecked = new HashSet<>();
        // player
        if (target.getOriginalTarget() instanceof TargetPlayer || target.getOriginalTarget() instanceof TargetAnyTarget || target.getOriginalTarget() instanceof TargetCreatureOrPlayer || target.getOriginalTarget() instanceof TargetPermanentOrPlayer || target.getOriginalTarget() instanceof TargetDefender) {
            for (String targetDefinition : targets) {
                if (!targetDefinition.startsWith("targetPlayer=")) {
                    continue;
                }
                checkTargetDefinitionMarksSupport(target, targetDefinition, "=");
                String playerName = targetDefinition.substring(targetDefinition.indexOf("targetPlayer=") + 13);
                for (Player player : game.getPlayers().values()) {
                    if (player.getName().equals(playerName) && target.canTarget(abilityControllerId, player.getId(), source, game)) {
                        target.addTarget(player.getId(), source, game);
                        targets.remove(targetDefinition);
                        return true;
                    }
                }
            }
        }
        // permanent in battlefield
        if ((target.getOriginalTarget() instanceof TargetPermanent) || (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) || (target.getOriginalTarget() instanceof TargetAnyTarget) || (target.getOriginalTarget() instanceof TargetCreatureOrPlayer) || (target.getOriginalTarget() instanceof TargetDefender) || (target.getOriginalTarget() instanceof TargetPermanentOrSuspendedCard)) {
            for (String targetDefinition : targets) {
                if (targetDefinition.startsWith("targetPlayer=")) {
                    continue;
                }
                checkTargetDefinitionMarksSupport(target, targetDefinition, "^[]");
                String[] targetList = targetDefinition.split("\\^");
                boolean targetFound = false;
                for (String targetName : targetList) {
                    // must have all valid targets from list
                    targetFound = false;
                    boolean originOnly = false;
                    boolean copyOnly = false;
                    if (targetName.endsWith("]")) {
                        if (targetName.endsWith("[no copy]")) {
                            originOnly = true;
                            targetName = targetName.substring(0, targetName.length() - 9);
                        }
                        if (targetName.endsWith("[only copy]")) {
                            copyOnly = true;
                            targetName = targetName.substring(0, targetName.length() - 11);
                        }
                    }
                    Filter filter = target.getOriginalTarget().getFilter();
                    if (filter instanceof FilterCreatureOrPlayer) {
                        filter = ((FilterCreatureOrPlayer) filter).getCreatureFilter();
                    }
                    if (filter instanceof FilterPermanentOrPlayer) {
                        filter = ((FilterPermanentOrPlayer) filter).getPermanentFilter();
                    }
                    if (filter instanceof FilterPlaneswalkerOrPlayer) {
                        filter = ((FilterPlaneswalkerOrPlayer) filter).getFilterPermanent();
                    }
                    if (filter instanceof FilterPermanentOrSuspendedCard) {
                        filter = ((FilterPermanentOrSuspendedCard) filter).getPermanentFilter();
                    }
                    for (Permanent permanent : game.getBattlefield().getActivePermanents((FilterPermanent) filter, abilityControllerId, sourceId, game)) {
                        if (hasObjectTargetNameOrAlias(permanent, targetName) || (permanent.getName() + '-' + permanent.getExpansionSetCode()).equals(targetName)) {
                            // TODO: remove exp code search?
                            if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.getTargets().contains(permanent.getId())) {
                                if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly)) {
                                    target.addTarget(permanent.getId(), source, game);
                                    targetFound = true;
                                    // return to next targetName
                                    break;
                                }
                            }
                        }
                    }
                }
                if (targetFound) {
                    targets.remove(targetDefinition);
                    return true;
                }
            }
        }
        // cards from non-own hand must be targeted through revealed cards
        if (target.getOriginalTarget() instanceof TargetCardInHand || target.getOriginalTarget() instanceof TargetDiscard || (target.getOriginalTarget() instanceof TargetCard && target.getOriginalTarget().getZone() == Zone.HAND)) {
            targetCardZonesChecked.add(Zone.HAND);
            for (String targetDefinition : targets) {
                checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
                String[] targetList = targetDefinition.split("\\^");
                boolean targetFound = false;
                for (String targetName : targetList) {
                    for (Card card : computerPlayer.getHand().getCards(((TargetCard) target.getOriginalTarget()).getFilter(), game)) {
                        if (hasObjectTargetNameOrAlias(card, targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
                            // TODO: remove set code search?
                            if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
                                target.addTarget(card.getId(), source, game);
                                targetFound = true;
                                // return to next targetName
                                break;
                            }
                        }
                    }
                }
                if (targetFound) {
                    targets.remove(targetDefinition);
                    return true;
                }
            }
        }
        // card in exile
        if (target.getOriginalTarget() instanceof TargetCardInExile || target.getOriginalTarget() instanceof TargetPermanentOrSuspendedCard || (target.getOriginalTarget() instanceof TargetCard && target.getOriginalTarget().getZone() == Zone.EXILED)) {
            targetCardZonesChecked.add(Zone.EXILED);
            FilterCard filter = null;
            if (target.getOriginalTarget().getFilter() instanceof FilterCard) {
                filter = (FilterCard) target.getOriginalTarget().getFilter();
            } else if (target.getOriginalTarget().getFilter() instanceof FilterPermanentOrSuspendedCard) {
                filter = ((FilterPermanentOrSuspendedCard) target.getOriginalTarget().getFilter()).getCardFilter();
            }
            if (filter == null) {
                Assert.fail("Unsupported exile target filter in TestPlayer: " + target.getOriginalTarget().getClass().getCanonicalName());
            }
            for (String targetDefinition : targets) {
                checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
                String[] targetList = targetDefinition.split("\\^");
                boolean targetFound = false;
                for (String targetName : targetList) {
                    for (Card card : game.getExile().getCards(filter, game)) {
                        if (hasObjectTargetNameOrAlias(card, targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
                            // TODO: remove set code search?
                            if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
                                target.addTarget(card.getId(), source, game);
                                targetFound = true;
                                // return to next targetName
                                break;
                            }
                        }
                    }
                }
                if (targetFound) {
                    targets.remove(targetDefinition);
                    return true;
                }
            }
        }
        // card in battlefield
        if (target instanceof TargetCardInGraveyardOrBattlefield) {
            TargetCard targetFull = (TargetCard) target;
            for (String targetDefinition : targets) {
                checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
                String[] targetList = targetDefinition.split("\\^");
                boolean targetFound = false;
                for (String targetName : targetList) {
                    for (Card card : game.getBattlefield().getAllActivePermanents()) {
                        if (hasObjectTargetNameOrAlias(card, targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
                            // TODO: remove set code search?
                            if (targetFull.canTarget(abilityControllerId, card.getId(), source, game) && !targetFull.getTargets().contains(card.getId())) {
                                targetFull.add(card.getId(), game);
                                targetFound = true;
                                // return to next targetName
                                break;
                            }
                        }
                    }
                }
                if (targetFound) {
                    targets.remove(targetDefinition);
                    return true;
                }
            }
        }
        // card in graveyard
        if (target.getOriginalTarget() instanceof TargetCardInOpponentsGraveyard || target.getOriginalTarget() instanceof TargetCardInYourGraveyard || target.getOriginalTarget() instanceof TargetCardInGraveyard || target.getOriginalTarget() instanceof TargetCardInGraveyardOrBattlefield || (target.getOriginalTarget() instanceof TargetCard && target.getOriginalTarget().getZone() == Zone.GRAVEYARD)) {
            targetCardZonesChecked.add(Zone.GRAVEYARD);
            TargetCard targetFull = (TargetCard) target.getOriginalTarget();
            List<UUID> needPlayers = game.getState().getPlayersInRange(getId(), game).toList();
            // fix for opponent graveyard
            if (target.getOriginalTarget() instanceof TargetCardInOpponentsGraveyard) {
                // current player remove
                Assert.assertTrue(needPlayers.contains(getId()));
                needPlayers.remove(getId());
                Assert.assertFalse(needPlayers.contains(getId()));
            }
            // fix for your graveyard
            if (target.getOriginalTarget() instanceof TargetCardInYourGraveyard) {
                // only current player
                Assert.assertTrue(needPlayers.contains(getId()));
                needPlayers.clear();
                needPlayers.add(getId());
                Assert.assertEquals(1, needPlayers.size());
            }
            for (String targetDefinition : targets) {
                checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
                String[] targetList = targetDefinition.split("\\^");
                boolean targetFound = false;
                for (String targetName : targetList) {
                    IterateGraveyards: for (UUID playerId : needPlayers) {
                        Player player = game.getPlayer(playerId);
                        for (Card card : player.getGraveyard().getCards(targetFull.getFilter(), game)) {
                            if (hasObjectTargetNameOrAlias(card, targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
                                // TODO: remove set code search?
                                if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
                                    target.addTarget(card.getId(), source, game);
                                    targetFound = true;
                                    // return to next targetName
                                    break IterateGraveyards;
                                }
                            }
                        }
                    }
                }
                if (targetFound) {
                    targets.remove(targetDefinition);
                    return true;
                }
            }
        }
        // stack
        if (target.getOriginalTarget() instanceof TargetSpell) {
            for (String targetDefinition : targets) {
                checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
                String[] targetList = targetDefinition.split("\\^");
                boolean targetFound = false;
                for (String targetName : targetList) {
                    for (StackObject stackObject : game.getStack()) {
                        if (hasObjectTargetNameOrAlias(stackObject, targetName)) {
                            if (target.canTarget(abilityControllerId, stackObject.getId(), source, game) && !target.getTargets().contains(stackObject.getId())) {
                                target.addTarget(stackObject.getId(), source, game);
                                targetFound = true;
                                // return to next targetName
                                break;
                            }
                        }
                    }
                }
                if (targetFound) {
                    targets.remove(targetDefinition);
                    return true;
                }
            }
        }
        // library
        if (target.getOriginalTarget() instanceof TargetCardInLibrary || (target.getOriginalTarget() instanceof TargetCard && target.getOriginalTarget().getZone() == Zone.LIBRARY)) {
            // user don't have access to library, so it must be targeted through list/revealed cards
            Assert.fail("Library zone is private, you must target through cards list, e.g. revealed: " + target.getOriginalTarget().getClass().getCanonicalName());
        }
        // uninplemented TargetCard's zone
        if (target.getOriginalTarget() instanceof TargetCard && !targetCardZonesChecked.contains(target.getOriginalTarget().getZone())) {
            Assert.fail("Found unimplemented TargetCard's zone or TargetCard's extented class: " + target.getOriginalTarget().getClass().getCanonicalName() + ", zone " + target.getOriginalTarget().getZone() + ", from " + (source == null ? "unknown source" : source.getSourceObject(game)));
        }
    }
    // how to fix: implement target class processing above
    if (!targets.isEmpty()) {
        String message;
        if (source != null) {
            message = this.getName() + " - Targets list was setup by addTarget with " + targets + ", but not used" + "\nCard: " + source.getSourceObject(game) + "\nAbility: " + source.getClass().getSimpleName() + " (" + source.getRule() + ")" + "\nTarget: " + target.getClass().getSimpleName() + " (" + target.getMessage() + ")" + "\nYou must implement target class support in TestPlayer or setup good targets";
        } else {
            message = this.getName() + " - Targets list was setup by addTarget with " + targets + ", but not used" + "\nCard: unknown source" + "\nAbility: unknown source" + "\nTarget: " + target.getClass().getSimpleName() + " (" + target.getMessage() + ")" + "\nYou must implement target class support in TestPlayer or setup good targets";
        }
        Assert.fail(message);
    }
    this.chooseStrictModeFailed("target", game, getInfo(source, game) + "\n" + getInfo(target));
    return computerPlayer.chooseTarget(outcome, target, source, game);
}
Also used : Permanent(mage.game.permanent.Permanent) StackObject(mage.game.stack.StackObject) MatchPlayer(mage.game.match.MatchPlayer) ComputerPlayer(mage.player.ai.ComputerPlayer) Card(mage.cards.Card)

Example 35 with StackObject

use of mage.game.stack.StackObject in project mage by magefree.

the class TestPlayer method choose.

@Override
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map<String, Serializable> options) {
    UUID abilityControllerId = computerPlayer.getId();
    if (target.getTargetController() != null && target.getAbilityController() != null) {
        abilityControllerId = target.getAbilityController();
    }
    // ignore player select
    if (target.getMessage().equals("Select a starting player")) {
        return computerPlayer.choose(outcome, target, sourceId, game, options);
    }
    assertAliasSupportInChoices(true);
    if (!choices.isEmpty()) {
        // skip choices
        if (choices.get(0).equals(CHOICE_SKIP)) {
            Assert.assertTrue("found skip choice, but it require more choices, needs " + (target.getMinNumberOfTargets() - target.getTargets().size()) + " more", target.getTargets().size() >= target.getMinNumberOfTargets());
            choices.remove(0);
            return true;
        }
        List<Integer> usedChoices = new ArrayList<>();
        List<UUID> usedTargets = new ArrayList<>();
        Ability source = null;
        StackObject stackObject = game.getStack().getStackObject(sourceId);
        if (stackObject != null) {
            source = stackObject.getStackAbility();
        }
        if ((target.getOriginalTarget() instanceof TargetPermanent) || (target.getOriginalTarget() instanceof TargetPermanentOrPlayer)) {
            // player target not implemted yet
            FilterPermanent filterPermanent;
            if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) {
                filterPermanent = ((TargetPermanentOrPlayer) target.getOriginalTarget()).getFilterPermanent();
            } else {
                filterPermanent = ((TargetPermanent) target.getOriginalTarget()).getFilter();
            }
            for (String choiceRecord : choices) {
                String[] targetList = choiceRecord.split("\\^");
                boolean targetFound = false;
                for (String targetName : targetList) {
                    boolean originOnly = false;
                    boolean copyOnly = false;
                    if (targetName.endsWith("]")) {
                        if (targetName.endsWith("[no copy]")) {
                            originOnly = true;
                            targetName = targetName.substring(0, targetName.length() - 9);
                        }
                        if (targetName.endsWith("[only copy]")) {
                            copyOnly = true;
                            targetName = targetName.substring(0, targetName.length() - 11);
                        }
                    }
                    for (Permanent permanent : game.getBattlefield().getActivePermanents(filterPermanent, abilityControllerId, sourceId, game)) {
                        if (target.getTargets().contains(permanent.getId())) {
                            continue;
                        }
                        if (hasObjectTargetNameOrAlias(permanent, targetName)) {
                            if (target.isNotTarget() || target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
                                if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly)) {
                                    target.add(permanent.getId(), game);
                                    targetFound = true;
                                    break;
                                }
                            }
                        } else if ((permanent.getName() + '-' + permanent.getExpansionSetCode()).equals(targetName)) {
                            // TODO: remove search by exp code?
                            if (target.isNotTarget() || target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
                                if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly)) {
                                    target.add(permanent.getId(), game);
                                    targetFound = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                if (targetFound) {
                    choices.remove(choiceRecord);
                    return true;
                }
            }
        }
        if (target instanceof TargetPlayer) {
            for (Player player : game.getPlayers().values()) {
                for (String choose2 : choices) {
                    if (player.getName().equals(choose2)) {
                        if (target.canTarget(abilityControllerId, player.getId(), null, game) && !target.getTargets().contains(player.getId())) {
                            target.add(player.getId(), game);
                            choices.remove(choose2);
                            return true;
                        }
                    }
                }
            }
        }
        // TODO: add same choices fixes for other target types (one choice must uses only one time for one target)
        if (target.getOriginalTarget() instanceof TargetCard) {
            // one choice per target
            // only unique targets
            // TargetCard targetFull = ((TargetCard) target);
            usedChoices.clear();
            usedTargets.clear();
            boolean targetCompleted = false;
            CheckAllChoices: for (int choiceIndex = 0; choiceIndex < choices.size(); choiceIndex++) {
                String choiceRecord = choices.get(choiceIndex);
                if (targetCompleted) {
                    break CheckAllChoices;
                }
                boolean targetFound = false;
                String[] possibleChoices = choiceRecord.split("\\^");
                CheckOneChoice: for (String possibleChoice : possibleChoices) {
                    Set<UUID> possibleCards = target.possibleTargets(sourceId, abilityControllerId, game);
                    CheckTargetsList: for (UUID targetId : possibleCards) {
                        MageObject targetObject = game.getCard(targetId);
                        if (hasObjectTargetNameOrAlias(targetObject, possibleChoice)) {
                            if (target.canTarget(targetObject.getId(), game)) {
                                // only unique targets
                                if (usedTargets.contains(targetObject.getId())) {
                                    continue;
                                }
                                // OK, can use it
                                target.add(targetObject.getId(), game);
                                targetFound = true;
                                usedTargets.add(targetObject.getId());
                                // break on full targets list
                                if (target.getTargets().size() >= target.getMaxNumberOfTargets()) {
                                    targetCompleted = true;
                                    break CheckOneChoice;
                                }
                                // restart search
                                break CheckTargetsList;
                            }
                        }
                    }
                }
                if (targetFound) {
                    usedChoices.add(choiceIndex);
                }
            }
            // apply only on ALL targets or revert
            if (usedChoices.size() > 0) {
                if (target.isChosen()) {
                    // remove all used choices
                    for (int i = choices.size(); i >= 0; i--) {
                        if (usedChoices.contains(i)) {
                            choices.remove(i);
                        }
                    }
                    return true;
                } else {
                    Assert.fail("Not full targets list.");
                    target.clearChosen();
                }
            }
        }
        if (target.getOriginalTarget() instanceof TargetSource) {
            Set<UUID> possibleTargets;
            TargetSource t = ((TargetSource) target.getOriginalTarget());
            possibleTargets = t.possibleTargets(sourceId, abilityControllerId, game);
            for (String choiceRecord : choices) {
                String[] targetList = choiceRecord.split("\\^");
                boolean targetFound = false;
                for (String targetName : targetList) {
                    for (UUID targetId : possibleTargets) {
                        MageObject targetObject = game.getObject(targetId);
                        if (targetObject != null) {
                            if (hasObjectTargetNameOrAlias(targetObject, targetName)) {
                                List<UUID> alreadyTargetted = target.getTargets();
                                if (t.canTarget(targetObject.getId(), game)) {
                                    if (alreadyTargetted != null && !alreadyTargetted.contains(targetObject.getId())) {
                                        target.add(targetObject.getId(), game);
                                        choices.remove(choiceRecord);
                                        targetFound = true;
                                    }
                                }
                            }
                        }
                        if (targetFound) {
                            choices.remove(choiceRecord);
                            return true;
                        }
                    }
                }
            }
        }
    // TODO: enable fail checks and fix tests
    /*
            if (!target.getTargetName().equals("starting player")) {
                Assert.fail("Wrong choice");
            }
             */
    }
    this.chooseStrictModeFailed("choice", game, getInfo(game.getObject(sourceId)) + ";\n" + getInfo(target));
    return computerPlayer.choose(outcome, target, sourceId, game, options);
}
Also used : SimpleStaticAbility(mage.abilities.common.SimpleStaticAbility) MatchPlayer(mage.game.match.MatchPlayer) ComputerPlayer(mage.player.ai.ComputerPlayer) Permanent(mage.game.permanent.Permanent) StackObject(mage.game.stack.StackObject)

Aggregations

StackObject (mage.game.stack.StackObject)130 Player (mage.players.Player)63 Permanent (mage.game.permanent.Permanent)57 Spell (mage.game.stack.Spell)41 MageObject (mage.MageObject)37 UUID (java.util.UUID)36 Card (mage.cards.Card)29 Target (mage.target.Target)17 TargetPermanent (mage.target.TargetPermanent)15 FilterCard (mage.filter.FilterCard)14 Ability (mage.abilities.Ability)13 FilterPermanent (mage.filter.FilterPermanent)13 StackAbility (mage.game.stack.StackAbility)13 FixedTarget (mage.target.targetpointer.FixedTarget)12 FilterCreaturePermanent (mage.filter.common.FilterCreaturePermanent)11 HashSet (java.util.HashSet)10 Effect (mage.abilities.effects.Effect)9 Game (mage.game.Game)9 MageObjectReference (mage.MageObjectReference)8 Cost (mage.abilities.costs.Cost)8