Search in sources :

Example 1 with RestrictionEffect

use of mage.abilities.effects.RestrictionEffect in project mage by magefree.

the class FightOrFlightEffect method apply.

@Override
public boolean apply(Game game, Ability source) {
    Player player = game.getPlayer(source.getControllerId());
    Player targetPlayer = game.getPlayer(game.getCombat().getAttackingPlayerId());
    if (player != null && targetPlayer != null) {
        int count = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURES, targetPlayer.getId(), game);
        TargetCreaturePermanent creatures = new TargetCreaturePermanent(0, count, new FilterCreaturePermanent("creatures to put in the first pile"), true);
        List<Permanent> pile1 = new ArrayList<>();
        creatures.setRequired(false);
        if (player.choose(Outcome.Neutral, creatures, source.getSourceId(), game)) {
            List<UUID> targets = creatures.getTargets();
            for (UUID targetId : targets) {
                Permanent p = game.getPermanent(targetId);
                if (p != null) {
                    pile1.add(p);
                }
            }
        }
        List<Permanent> pile2 = new ArrayList<>();
        for (Permanent p : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, targetPlayer.getId(), game)) {
            if (!pile1.contains(p)) {
                pile2.add(p);
            }
        }
        boolean choice = targetPlayer.choosePile(outcome, "Choose which pile can attack this turn.", pile1, pile2, game);
        List<Permanent> chosenPile = choice ? pile2 : pile1;
        List<Permanent> otherPile = choice ? pile1 : pile2;
        for (Permanent permanent : chosenPile) {
            if (permanent != null) {
                RestrictionEffect effect = new CantAttackTargetEffect(Duration.EndOfTurn);
                effect.setText("");
                effect.setTargetPointer(new FixedTarget(permanent, game));
                game.addEffect(effect, source);
            }
        }
        game.informPlayers("Creatures that can attack this turn: " + otherPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", ")));
        return true;
    }
    return false;
}
Also used : FixedTarget(mage.target.targetpointer.FixedTarget) Player(mage.players.Player) Permanent(mage.game.permanent.Permanent) TargetCreaturePermanent(mage.target.common.TargetCreaturePermanent) FilterCreaturePermanent(mage.filter.common.FilterCreaturePermanent) ArrayList(java.util.ArrayList) CantAttackTargetEffect(mage.abilities.effects.common.combat.CantAttackTargetEffect) TargetCreaturePermanent(mage.target.common.TargetCreaturePermanent) FilterCreaturePermanent(mage.filter.common.FilterCreaturePermanent) UUID(java.util.UUID) RestrictionEffect(mage.abilities.effects.RestrictionEffect)

Example 2 with RestrictionEffect

use of mage.abilities.effects.RestrictionEffect in project mage by magefree.

the class MasterWarcraftChooseAttackersEffect method applies.

@Override
public boolean applies(GameEvent event, Ability source, Game game) {
    if (!ControlCombatRedundancyWatcher.checkAttackingController(source.getControllerId(), game)) {
        game.informPlayers(source.getSourceObject(game).getIdName() + " didn't apply");
        return false;
    }
    Player controller = game.getPlayer(source.getControllerId());
    Player attackingPlayer = game.getPlayer(game.getCombat().getAttackingPlayerId());
    if (controller == null || attackingPlayer == null || attackingPlayer.getAvailableAttackers(game).isEmpty()) {
        // the attack declaration resumes for the active player as normal
        return false;
    }
    Target target = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true);
    if (!controller.chooseTarget(Outcome.Benefit, target, source, game)) {
        // the attack declaration resumes for the active player as normal
        return false;
    }
    for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) {
        // Choose creatures that will be attacking this combat
        if (target.getTargets().contains(permanent.getId())) {
            RequirementEffect effect = new AttacksIfAbleTargetEffect(Duration.EndOfCombat);
            effect.setText("");
            effect.setTargetPointer(new FixedTarget(permanent, game));
            game.addEffect(effect, source);
            game.informPlayers(controller.getLogName() + " has decided that " + permanent.getLogName() + " attacks this combat if able");
        // All other creatures can't attack (unless they must attack)
        } else {
            boolean hasToAttack = false;
            for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(permanent, false, game).entrySet()) {
                RequirementEffect effect2 = entry.getKey();
                if (effect2.mustAttack(game)) {
                    hasToAttack = true;
                }
            }
            if (!hasToAttack) {
                RestrictionEffect effect = new CantAttackTargetEffect(Duration.EndOfCombat);
                effect.setText("");
                effect.setTargetPointer(new FixedTarget(permanent, game));
                game.addEffect(effect, source);
            }
        }
    }
    // the attack declaration resumes for the active player as normal
    return false;
}
Also used : FixedTarget(mage.target.targetpointer.FixedTarget) Player(mage.players.Player) Set(java.util.Set) FilterCreaturePermanent(mage.filter.common.FilterCreaturePermanent) Permanent(mage.game.permanent.Permanent) TargetCreaturePermanent(mage.target.common.TargetCreaturePermanent) AttacksIfAbleTargetEffect(mage.abilities.effects.common.combat.AttacksIfAbleTargetEffect) CantAttackTargetEffect(mage.abilities.effects.common.combat.CantAttackTargetEffect) TargetCreaturePermanent(mage.target.common.TargetCreaturePermanent) RequirementEffect(mage.abilities.effects.RequirementEffect) Target(mage.target.Target) FixedTarget(mage.target.targetpointer.FixedTarget) FilterCreaturePermanent(mage.filter.common.FilterCreaturePermanent) Map(java.util.Map) RestrictionEffect(mage.abilities.effects.RestrictionEffect)

Example 3 with RestrictionEffect

use of mage.abilities.effects.RestrictionEffect in project mage by magefree.

the class UrbanBurgeoningUntapEffect method apply.

@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
    boolean applied = Boolean.TRUE.equals(game.getState().getValue(source.getSourceId() + "applied"));
    if (!applied && layer == Layer.RulesEffects) {
        if (!game.isActivePlayer(source.getControllerId()) && game.getStep().getType() == PhaseStep.UNTAP) {
            game.getState().setValue(source.getSourceId() + "applied", true);
            Permanent land = game.getPermanent(source.getSourceId());
            boolean untap = true;
            for (RestrictionEffect effect : game.getContinuousEffects().getApplicableRestrictionEffects(land, game).keySet()) {
                untap &= effect.canBeUntapped(land, source, game, true);
            }
            if (untap) {
                land.untap(game);
            }
        }
    } else if (applied && layer == Layer.RulesEffects) {
        if (game.getStep().getType() == PhaseStep.END_TURN) {
            game.getState().setValue(source.getSourceId() + "applied", false);
        }
    }
    return true;
}
Also used : TargetLandPermanent(mage.target.common.TargetLandPermanent) Permanent(mage.game.permanent.Permanent) TargetPermanent(mage.target.TargetPermanent) RestrictionEffect(mage.abilities.effects.RestrictionEffect)

Example 4 with RestrictionEffect

use of mage.abilities.effects.RestrictionEffect in project mage by magefree.

the class PlayerImpl method untap.

@Override
public void untap(Game game) {
    // create list of all "notMoreThan" effects to track which one are consumed
    Map<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffectsUsage = new HashMap<>();
    for (Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>> restrictionEffect : game.getContinuousEffects().getApplicableRestrictionUntapNotMoreThanEffects(this, game).entrySet()) {
        notMoreThanEffectsUsage.put(restrictionEffect, restrictionEffect.getKey().getNumber());
    }
    if (!notMoreThanEffectsUsage.isEmpty()) {
        // create list of all permanents that can be untapped generally
        List<Permanent> canBeUntapped = new ArrayList<>();
        for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) {
            boolean untap = true;
            for (RestrictionEffect effect : game.getContinuousEffects().getApplicableRestrictionEffects(permanent, game).keySet()) {
                untap &= effect.canBeUntapped(permanent, null, game, true);
            }
            if (untap) {
                canBeUntapped.add(permanent);
            }
        }
        // selected permanents to untap
        List<Permanent> selectedToUntap = new ArrayList<>();
        // player can cancel the selection of an effect to use a preferred order of restriction effects
        boolean playerCanceledSelection;
        do {
            playerCanceledSelection = false;
            // select permanents to untap to consume the "notMoreThan" effects
            for (Map.Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> handledEntry : notMoreThanEffectsUsage.entrySet()) {
                // select a permanent to untap for this entry
                int numberToUntap = handledEntry.getValue();
                if (numberToUntap > 0) {
                    List<Permanent> leftForUntap = getPermanentsThatCanBeUntapped(game, canBeUntapped, handledEntry.getKey().getKey(), notMoreThanEffectsUsage);
                    FilterControlledPermanent filter = handledEntry.getKey().getKey().getFilter().copy();
                    String message = filter.getMessage();
                    // omit already from other untap effects selected permanents
                    for (Permanent permanent : selectedToUntap) {
                        filter.add(Predicates.not(new PermanentIdPredicate(permanent.getId())));
                    }
                    // while targets left and there is still allowed to untap
                    while (canRespond() && !leftForUntap.isEmpty() && numberToUntap > 0) {
                        // player has to select the permanent they want to untap for this restriction
                        Ability ability = handledEntry.getKey().getValue().iterator().next();
                        if (ability != null) {
                            StringBuilder sb = new StringBuilder(message).append(" to untap").append(" (").append(Math.min(leftForUntap.size(), numberToUntap)).append(" in total");
                            MageObject effectSource = game.getObject(ability.getSourceId());
                            if (effectSource != null) {
                                sb.append(" from ").append(effectSource.getLogName());
                            }
                            sb.append(')');
                            filter.setMessage(sb.toString());
                            Target target = new TargetPermanent(1, 1, filter, true);
                            if (!this.chooseTarget(Outcome.Untap, target, ability, game)) {
                                // player canceled, go on with the next effect (if no other effect available, this effect will be active again)
                                playerCanceledSelection = true;
                                break;
                            }
                            Permanent selectedPermanent = game.getPermanent(target.getFirstTarget());
                            if (leftForUntap.contains(selectedPermanent)) {
                                selectedToUntap.add(selectedPermanent);
                                numberToUntap--;
                                // don't allow to select same permanent twice
                                filter.add(Predicates.not(new PermanentIdPredicate(selectedPermanent.getId())));
                                // reduce available untap numbers from other "UntapNotMoreThan" effects if selected permanent applies to their filter too
                                for (Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
                                    if (notMoreThanEffect.getValue() > 0 && notMoreThanEffect.getKey().getKey().getFilter().match(selectedPermanent, game)) {
                                        notMoreThanEffect.setValue(notMoreThanEffect.getValue() - 1);
                                    }
                                }
                                // update the left for untap list
                                leftForUntap = getPermanentsThatCanBeUntapped(game, canBeUntapped, handledEntry.getKey().getKey(), notMoreThanEffectsUsage);
                                // remove already selected permanents
                                for (Permanent permanent : selectedToUntap) {
                                    leftForUntap.remove(permanent);
                                }
                            } else {
                                // player selected an permanent that is restricted by another effect, disallow it (so AI can select another one)
                                filter.add(Predicates.not(new PermanentIdPredicate(selectedPermanent.getId())));
                                if (this.isHuman() && !game.isSimulation()) {
                                    game.informPlayer(this, "This permanent can't be untapped because of other restricting effect.");
                                }
                            }
                        }
                    }
                }
            }
        } while (canRespond() && playerCanceledSelection);
        if (!game.isSimulation()) {
            // show in log which permanents were selected to untap
            for (Permanent permanent : selectedToUntap) {
                game.informPlayers(this.getLogName() + " untapped " + permanent.getLogName());
            }
        }
        // untap if permanent is not concerned by notMoreThan effects or is included in the selectedToUntapList
        for (Permanent permanent : canBeUntapped) {
            boolean doUntap = true;
            if (!selectedToUntap.contains(permanent)) {
                // if the permanent is covered by one of the restriction effects, don't untap it
                for (Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
                    if (notMoreThanEffect.getKey().getKey().getFilter().match(permanent, game)) {
                        doUntap = false;
                        break;
                    }
                }
            }
            if (permanent != null && doUntap) {
                permanent.untap(game);
            }
        }
    } else {
        for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) {
            boolean untap = true;
            for (RestrictionEffect effect : game.getContinuousEffects().getApplicableRestrictionEffects(permanent, game).keySet()) {
                untap &= effect.canBeUntapped(permanent, null, game, true);
            }
            if (untap) {
                permanent.untap(game);
            }
        }
    }
}
Also used : AlternateManaPaymentAbility(mage.abilities.costs.mana.AlternateManaPaymentAbility) StackAbility(mage.game.stack.StackAbility) WhileSearchingPlayFromLibraryAbility(mage.abilities.common.WhileSearchingPlayFromLibraryAbility) AtTheEndOfTurnStepPostDelayedTriggeredAbility(mage.abilities.common.delayed.AtTheEndOfTurnStepPostDelayedTriggeredAbility) PassAbility(mage.abilities.common.PassAbility) PlayLandAsCommanderAbility(mage.abilities.common.PlayLandAsCommanderAbility) PermanentIdPredicate(mage.filter.predicate.permanent.PermanentIdPredicate) Permanent(mage.game.permanent.Permanent) FilterPermanent(mage.filter.FilterPermanent) FilterControlledPermanent(mage.filter.common.FilterControlledPermanent) TargetPermanent(mage.target.TargetPermanent) FilterControlledPermanent(mage.filter.common.FilterControlledPermanent) RestrictionUntapNotMoreThanEffect(mage.abilities.effects.RestrictionUntapNotMoreThanEffect) Entry(java.util.Map.Entry) Target(mage.target.Target) TargetPermanent(mage.target.TargetPermanent) RestrictionEffect(mage.abilities.effects.RestrictionEffect) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 5 with RestrictionEffect

use of mage.abilities.effects.RestrictionEffect in project mage by magefree.

the class Combat method checkAttackRestrictions.

/**
 * @param player
 * @param game
 * @return true if the attack with that set of creatures and attacked
 * players/planeswalkers is possible
 */
protected boolean checkAttackRestrictions(Player player, Game game) {
    boolean check = true;
    int numberOfChecks = 0;
    UUID attackerToRemove = null;
    Player attackingPlayer = game.getPlayer(attackingPlayerId);
    Check: while (check) {
        check = false;
        numberOfChecks++;
        int numberAttackers = 0;
        for (CombatGroup group : groups) {
            numberAttackers += group.getAttackers().size();
        }
        if (attackerToRemove != null) {
            removeAttacker(attackerToRemove, game);
        }
        for (UUID attackingCreatureId : this.getAttackers()) {
            Permanent attackingCreature = game.getPermanent(attackingCreatureId);
            for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(attackingCreature, game).entrySet()) {
                RestrictionEffect effect = entry.getKey();
                for (Ability ability : entry.getValue()) {
                    if (effect.canAttackCheckAfter(numberAttackers, ability, game, true)) {
                        continue;
                    }
                    MageObject sourceObject = ability.getSourceObject(game);
                    if (attackingPlayer.isHuman()) {
                        attackingPlayer.resetPlayerPassedActions();
                        game.informPlayer(attackingPlayer, attackingCreature.getIdName() + " can't attack this way (" + (sourceObject == null ? "null" : sourceObject.getIdName()) + ')');
                        return false;
                    }
                    // can create possible not allowed attack scenarios, but not sure how to solve this
                    if (this.getGroups().stream().map(CombatGroup::getAttackers).flatMap(Collection::stream).anyMatch(attackingCreatureId::equals)) {
                        attackerToRemove = attackingCreatureId;
                    }
                    // do the check again
                    check = true;
                    if (numberOfChecks > 50) {
                        logger.error("Seems to be an AI declare attacker lock (reached 50 check iterations) " + (sourceObject == null ? "null" : sourceObject.getIdName()));
                        // break the check
                        return true;
                    }
                    continue Check;
                }
            }
        }
    }
    return true;
}
Also used : JohanVigilanceAbility(mage.abilities.keyword.special.JohanVigilanceAbility) VigilanceAbility(mage.abilities.keyword.VigilanceAbility) BandingAbility(mage.abilities.keyword.BandingAbility) BandsWithOtherAbility(mage.abilities.keyword.BandsWithOtherAbility) Ability(mage.abilities.Ability) Player(mage.players.Player) FilterControlledCreaturePermanent(mage.filter.common.FilterControlledCreaturePermanent) FilterCreaturePermanent(mage.filter.common.FilterCreaturePermanent) Permanent(mage.game.permanent.Permanent) TargetControlledPermanent(mage.target.common.TargetControlledPermanent) MageObject(mage.MageObject) RestrictionEffect(mage.abilities.effects.RestrictionEffect)

Aggregations

RestrictionEffect (mage.abilities.effects.RestrictionEffect)16 Permanent (mage.game.permanent.Permanent)11 FilterCreaturePermanent (mage.filter.common.FilterCreaturePermanent)8 Ability (mage.abilities.Ability)7 Player (mage.players.Player)7 MageObject (mage.MageObject)5 FixedTarget (mage.target.targetpointer.FixedTarget)5 FilterControlledCreaturePermanent (mage.filter.common.FilterControlledCreaturePermanent)4 ArrayList (java.util.ArrayList)3 UUID (java.util.UUID)3 RequirementEffect (mage.abilities.effects.RequirementEffect)3 BandingAbility (mage.abilities.keyword.BandingAbility)3 BandsWithOtherAbility (mage.abilities.keyword.BandsWithOtherAbility)3 FlyingAbility (mage.abilities.keyword.FlyingAbility)3 VigilanceAbility (mage.abilities.keyword.VigilanceAbility)3 JohanVigilanceAbility (mage.abilities.keyword.special.JohanVigilanceAbility)3 TargetControlledPermanent (mage.target.common.TargetControlledPermanent)3 SpellAbility (mage.abilities.SpellAbility)2 StaticAbility (mage.abilities.StaticAbility)2 TriggeredAbility (mage.abilities.TriggeredAbility)2