Search in sources :

Example 51 with Ability

use of mage.abilities.Ability in project mage by magefree.

the class BalanceEffect method choosePermanentsToKeep.

private void choosePermanentsToKeep(Game game, Ability source, Player controller, FilterControlledPermanent filterPermanent) {
    int lowestPermanentsCount = Integer.MAX_VALUE;
    for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
        Player player = game.getPlayer(playerId);
        if (player == null) {
            continue;
        }
        lowestPermanentsCount = Math.min(lowestPermanentsCount, game.getBattlefield().countAll(filterPermanent, player.getId(), game));
    }
    List<Permanent> permanentsToSacrifice = new ArrayList<>();
    for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
        Player player = game.getPlayer(playerId);
        if (player == null) {
            continue;
        }
        List<Permanent> allPermanentsOfType = game.getBattlefield().getActivePermanents(filterPermanent, player.getId(), source.getSourceId(), game);
        List<Permanent> permanentsToKeep = new ArrayList<>();
        if (lowestPermanentsCount > 0) {
            TargetControlledPermanent target = new TargetControlledPermanent(lowestPermanentsCount, lowestPermanentsCount, filterPermanent, true);
            if (target.choose(Outcome.Protect, player.getId(), source.getSourceId(), game)) {
                for (Permanent permanent : allPermanentsOfType) {
                    if (permanent != null && target.getTargets().contains(permanent.getId())) {
                        permanentsToKeep.add(permanent);
                    }
                }
            // Prevent possible cheat by disconnecting.  If no targets are chosen, just pick the first in the list.
            // https://github.com/magefree/mage/issues/4263
            } else {
                int numPermanents = 0;
                for (Permanent permanent : allPermanentsOfType) {
                    if (numPermanents >= lowestPermanentsCount) {
                        break;
                    }
                    if (permanent != null) {
                        permanentsToKeep.add(permanent);
                        numPermanents++;
                    }
                }
            }
        }
        List<Permanent> playerPermanentsToSacrifice = allPermanentsOfType.stream().filter(e -> !permanentsToKeep.contains(e)).collect(Collectors.toList());
        permanentsToSacrifice.addAll(playerPermanentsToSacrifice);
        if (!playerPermanentsToSacrifice.isEmpty()) {
            game.informPlayers(player.getLogName() + " chose permanents to be sacrificed: " + playerPermanentsToSacrifice.stream().map(Permanent::getLogName).collect(Collectors.joining(", ")));
        }
    }
    for (Permanent permanent : permanentsToSacrifice) {
        if (permanent != null) {
            permanent.sacrifice(source, game);
        }
    }
}
Also used : FilterCard(mage.filter.FilterCard) java.util(java.util) TargetCardInHand(mage.target.common.TargetCardInHand) Cards(mage.cards.Cards) Outcome(mage.constants.Outcome) OneShotEffect(mage.abilities.effects.OneShotEffect) CardsImpl(mage.cards.CardsImpl) Collectors(java.util.stream.Collectors) Player(mage.players.Player) Game(mage.game.Game) FilterControlledPermanent(mage.filter.common.FilterControlledPermanent) Permanent(mage.game.permanent.Permanent) FilterControlledCreaturePermanent(mage.filter.common.FilterControlledCreaturePermanent) TargetControlledPermanent(mage.target.common.TargetControlledPermanent) Card(mage.cards.Card) FilterControlledLandPermanent(mage.filter.common.FilterControlledLandPermanent) Ability(mage.abilities.Ability) TargetControlledPermanent(mage.target.common.TargetControlledPermanent) Player(mage.players.Player) FilterControlledPermanent(mage.filter.common.FilterControlledPermanent) Permanent(mage.game.permanent.Permanent) FilterControlledCreaturePermanent(mage.filter.common.FilterControlledCreaturePermanent) TargetControlledPermanent(mage.target.common.TargetControlledPermanent) FilterControlledLandPermanent(mage.filter.common.FilterControlledLandPermanent)

Example 52 with Ability

use of mage.abilities.Ability in project mage by magefree.

the class PlayTheTopCardEffect method applies.

@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
    // main card and all parts are checks in different calls.
    // two modes:
    // * can play cards (must check main card and allows any parts)
    // * can play lands/spells (must check specific part and allows specific part)
    // current card's part
    Card cardToCheck = game.getCard(objectId);
    if (cardToCheck == null) {
        return false;
    }
    if (this.canPlayCardOnly) {
        // check whole card instead part
        cardToCheck = cardToCheck.getMainCard();
    }
    // must be you
    if (!affectedControllerId.equals(source.getControllerId())) {
        return false;
    }
    Player cardOwner = game.getPlayer(cardToCheck.getOwnerId());
    Player controller = game.getPlayer(source.getControllerId());
    if (cardOwner == null || controller == null) {
        return false;
    }
    // must be your or opponents library
    switch(this.targetLibrary) {
        case YOU:
            {
                Card topCard = controller.getLibrary().getFromTop(game);
                if (topCard == null || !topCard.getId().equals(cardToCheck.getMainCard().getId())) {
                    return false;
                }
                break;
            }
        case OPPONENT:
            {
                if (!game.getOpponents(controller.getId()).contains(cardOwner.getId())) {
                    return false;
                }
                Card topCard = cardOwner.getLibrary().getFromTop(game);
                if (topCard == null || !topCard.getId().equals(cardToCheck.getMainCard().getId())) {
                    return false;
                }
                break;
            }
        case SOURCE_TARGETS:
            {
                UUID needCardId = cardToCheck.getMainCard().getId();
                if (CardUtil.getAllSelectedTargets(source, game).stream().map(game::getPlayer).filter(Objects::nonNull).noneMatch(player -> {
                    Card topCard = player.getLibrary().getFromTop(game);
                    return topCard != null && topCard.getId().equals(needCardId);
                })) {
                    return false;
                }
                break;
            }
        default:
            {
                return false;
            }
    }
    // can't cast without mana cost
    if (!cardToCheck.isLand(game) && cardToCheck.getManaCost().isEmpty()) {
        return false;
    }
    // must be correct card
    return filter.match(cardToCheck, source.getSourceId(), affectedControllerId, game);
}
Also used : FilterCard(mage.filter.FilterCard) Outcome(mage.constants.Outcome) CardUtil(mage.util.CardUtil) UUID(java.util.UUID) TargetController(mage.constants.TargetController) Player(mage.players.Player) Objects(java.util.Objects) Duration(mage.constants.Duration) Game(mage.game.Game) AsThoughEffectImpl(mage.abilities.effects.AsThoughEffectImpl) Locale(java.util.Locale) Card(mage.cards.Card) Ability(mage.abilities.Ability) AsThoughEffectType(mage.constants.AsThoughEffectType) Player(mage.players.Player) Objects(java.util.Objects) UUID(java.util.UUID) FilterCard(mage.filter.FilterCard) Card(mage.cards.Card)

Example 53 with Ability

use of mage.abilities.Ability in project mage by magefree.

the class GainAbilityWithAttachmentEffect method apply.

@Override
public boolean apply(Game game, Ability source) {
    Permanent permanent = null;
    if (affectedObjectsSet) {
        permanent = game.getPermanent(targetPointer.getFirst(game, source));
        if (permanent == null) {
            discard();
            return true;
        }
    } else {
        Permanent equipment = game.getPermanent(source.getSourceId());
        if (equipment != null && equipment.getAttachedTo() != null) {
            permanent = game.getPermanentOrLKIBattlefield(equipment.getAttachedTo());
        }
    }
    if (permanent == null) {
        return true;
    }
    Ability ability = makeAbility(game, source);
    ability.getEffects().setValue("attachedPermanent", game.getPermanent(source.getSourceId()));
    permanent.addAbility(ability, source.getSourceId(), game);
    return true;
}
Also used : SimpleActivatedAbility(mage.abilities.common.SimpleActivatedAbility) Ability(mage.abilities.Ability) Permanent(mage.game.permanent.Permanent)

Example 54 with Ability

use of mage.abilities.Ability in project mage by magefree.

the class Commander method validate.

@Override
public boolean validate(Deck deck) {
    boolean valid = true;
    errorsList.clear();
    FilterMana colorIdentity = new FilterMana();
    Set<Card> commanders = new HashSet<>();
    Card companion;
    int sbsize = deck.getSideboard().size();
    Card card1;
    Card card2;
    Card card3;
    Iterator<Card> iter;
    switch(deck.getSideboard().size()) {
        case 1:
            companion = null;
            commanders.add(deck.getSideboard().iterator().next());
            break;
        case 2:
            iter = deck.getSideboard().iterator();
            card1 = iter.next();
            card2 = iter.next();
            if (card1.getAbilities().stream().anyMatch(CompanionAbility.class::isInstance)) {
                companion = card1;
                commanders.add(card2);
            } else if (card2.getAbilities().stream().anyMatch(CompanionAbility.class::isInstance)) {
                companion = card2;
                commanders.add(card1);
            } else {
                companion = null;
                commanders.add(card1);
                commanders.add(card2);
            }
            break;
        case 3:
            iter = deck.getSideboard().iterator();
            card1 = iter.next();
            card2 = iter.next();
            card3 = iter.next();
            if (card1.getAbilities().stream().anyMatch(CompanionAbility.class::isInstance)) {
                companion = card1;
                commanders.add(card2);
                commanders.add(card3);
            } else if (card2.getAbilities().stream().anyMatch(CompanionAbility.class::isInstance)) {
                companion = card2;
                commanders.add(card1);
                commanders.add(card3);
            } else if (card3.getAbilities().stream().anyMatch(CompanionAbility.class::isInstance)) {
                companion = card3;
                commanders.add(card1);
                commanders.add(card2);
            } else {
                companion = null;
                addError(DeckValidatorErrorType.PRIMARY, "Commander", "Sideboard must contain only the commander(s) and up to 1 companion");
                valid = false;
            }
            break;
        default:
            companion = null;
            addError(DeckValidatorErrorType.PRIMARY, "Commander", "Sideboard must contain only the commander(s) and up to 1 companion");
            valid = false;
    }
    if (companion != null && deck.getCards().size() + deck.getSideboard().size() != 101) {
        addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + 101 + " cards (companion doesn't count for deck size): has " + (deck.getCards().size() + deck.getSideboard().size()) + " cards");
        valid = false;
    } else if (companion == null && deck.getCards().size() + deck.getSideboard().size() != 100) {
        addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + 100 + " cards: has " + (deck.getCards().size() + deck.getSideboard().size()) + " cards");
        valid = false;
    }
    Map<String, Integer> counts = new HashMap<>();
    countCards(counts, deck.getCards());
    countCards(counts, deck.getSideboard());
    valid = checkCounts(1, counts) && valid;
    for (String bannedCard : banned) {
        if (counts.containsKey(bannedCard)) {
            addError(DeckValidatorErrorType.BANNED, bannedCard, "Banned", true);
            valid = false;
        }
    }
    Set<String> commanderNames = new HashSet<>();
    for (Card commander : commanders) {
        commanderNames.add(commander.getName());
    }
    if (commanders.size() == 2 && commanders.stream().map(MageObject::getAbilities).filter(abilities -> abilities.contains(PartnerAbility.getInstance())).count() != 2 && commanders.stream().map(MageObject::getAbilities).filter(abilities -> abilities.contains(FriendsForeverAbility.getInstance())).count() != 2 && !CardUtil.castStream(commanders.stream().map(MageObject::getAbilities), PartnerWithAbility.class).map(PartnerWithAbility::getPartnerName).allMatch(commanderNames::contains)) {
        for (Card commander : commanders) {
            addError(DeckValidatorErrorType.PRIMARY, commander.getName(), "Commander with invalid Partner (" + commander.getName() + ')', true);
            valid = false;
        }
    }
    for (Card commander : commanders) {
        if (bannedCommander.contains(commander.getName())) {
            addError(DeckValidatorErrorType.PRIMARY, commander.getName(), "Commander banned (" + commander.getName() + ')', true);
            valid = false;
        }
        if ((!commander.hasCardTypeForDeckbuilding(CardType.CREATURE) || !commander.isLegendary()) && !commander.getAbilities().contains(CanBeYourCommanderAbility.getInstance())) {
            addError(DeckValidatorErrorType.PRIMARY, commander.getName(), "Commander invalid (" + commander.getName() + ')', true);
            valid = false;
        }
        if (commanders.size() == 2 && bannedPartner.contains(commander.getName())) {
            addError(DeckValidatorErrorType.PRIMARY, commander.getName(), "Commander Partner banned (" + commander.getName() + ')', true);
            valid = false;
        }
        ManaUtil.collectColorIdentity(colorIdentity, commander.getColorIdentity());
    }
    // no needs in cards check on wrong commanders
    if (!valid) {
        return false;
    }
    for (Card card : deck.getCards()) {
        if (!ManaUtil.isColorIdentityCompatible(colorIdentity, card.getColorIdentity())) {
            addError(DeckValidatorErrorType.OTHER, card.getName(), "Invalid color (" + colorIdentity.toString() + ')', true);
            valid = false;
        }
    }
    for (Card card : deck.getSideboard()) {
        if (!ManaUtil.isColorIdentityCompatible(colorIdentity, card.getColorIdentity())) {
            addError(DeckValidatorErrorType.OTHER, card.getName(), "Invalid color (" + colorIdentity.toString() + ')', true);
            valid = false;
        }
    }
    for (Card card : deck.getCards()) {
        if (!isSetAllowed(card.getExpansionSetCode())) {
            if (!legalSets(card)) {
                addError(DeckValidatorErrorType.WRONG_SET, card.getName(), "Not allowed Set: " + card.getExpansionSetCode(), true);
                valid = false;
            }
        }
    }
    for (Card card : deck.getSideboard()) {
        if (!isSetAllowed(card.getExpansionSetCode())) {
            if (!legalSets(card)) {
                addError(DeckValidatorErrorType.WRONG_SET, card.getName(), "Not allowed Set: " + card.getExpansionSetCode(), true);
                valid = false;
            }
        }
    }
    // Check for companion legality
    if (companion != null) {
        Set<Card> cards = new HashSet<>(deck.getCards());
        cards.addAll(commanders);
        for (Ability ability : companion.getAbilities()) {
            if (ability instanceof CompanionAbility) {
                CompanionAbility companionAbility = (CompanionAbility) ability;
                if (!companionAbility.isLegal(cards, getDeckMinSize())) {
                    addError(DeckValidatorErrorType.PRIMARY, companion.getName(), "Commander Companion (deck invalid for companion)", true);
                    valid = false;
                }
                break;
            }
        }
    }
    return valid;
}
Also used : PartnerAbility(mage.abilities.keyword.PartnerAbility) java.util(java.util) DeckValidatorErrorType(mage.cards.decks.DeckValidatorErrorType) FriendsForeverAbility(mage.abilities.keyword.FriendsForeverAbility) PartnerWithAbility(mage.abilities.keyword.PartnerWithAbility) Deck(mage.cards.decks.Deck) CanBeYourCommanderAbility(mage.abilities.common.CanBeYourCommanderAbility) Sets(mage.cards.Sets) CardUtil(mage.util.CardUtil) Constructed(mage.cards.decks.Constructed) ManaUtil(mage.util.ManaUtil) ExpansionSet(mage.cards.ExpansionSet) CardType(mage.constants.CardType) MageObject(mage.MageObject) CompanionAbility(mage.abilities.keyword.CompanionAbility) ObjectColor(mage.ObjectColor) Card(mage.cards.Card) Ability(mage.abilities.Ability) FilterMana(mage.filter.FilterMana) PartnerAbility(mage.abilities.keyword.PartnerAbility) FriendsForeverAbility(mage.abilities.keyword.FriendsForeverAbility) PartnerWithAbility(mage.abilities.keyword.PartnerWithAbility) CanBeYourCommanderAbility(mage.abilities.common.CanBeYourCommanderAbility) CompanionAbility(mage.abilities.keyword.CompanionAbility) Ability(mage.abilities.Ability) FilterMana(mage.filter.FilterMana) CompanionAbility(mage.abilities.keyword.CompanionAbility) MageObject(mage.MageObject) Card(mage.cards.Card)

Example 55 with Ability

use of mage.abilities.Ability in project mage by magefree.

the class Oathbreaker method validate.

@Override
public boolean validate(Deck deck) {
    boolean valid = true;
    errorsList.clear();
    if (deck.getCards().size() + deck.getSideboard().size() != 60) {
        addError(DeckValidatorErrorType.DECK_SIZE, "Deck", "Must contain " + 60 + " cards: has " + (deck.getCards().size() + deck.getSideboard().size()) + " cards");
        valid = false;
    }
    Map<String, Integer> counts = new HashMap<>();
    countCards(counts, deck.getCards());
    countCards(counts, deck.getSideboard());
    for (String bannedCard : banned) {
        if (counts.containsKey(bannedCard)) {
            addError(DeckValidatorErrorType.BANNED, bannedCard, "Banned", true);
            valid = false;
        }
    }
    valid = checkCounts(1, counts) && valid;
    Set<String> commanderNames = new HashSet<>();
    Set<String> signatureSpells = new HashSet<>();
    FilterMana allCommandersColor = new FilterMana();
    if (deck.getSideboard().size() < 2 || deck.getSideboard().size() > 4) {
        addError(DeckValidatorErrorType.PRIMARY, "Oathbreaker", "Sideboard must contain only 2 or 4 cards (oathbreaker + signature spell)");
        valid = false;
    } else {
        // collect data
        for (Card commander : deck.getSideboard()) {
            if (commander.isInstantOrSorcery()) {
                signatureSpells.add(commander.getName());
            } else {
                if (commander.hasCardTypeForDeckbuilding(CardType.PLANESWALKER)) {
                    commanderNames.add(commander.getName());
                    // color identity from commanders only, not spell
                    ManaUtil.collectColorIdentity(allCommandersColor, commander.getColorIdentity());
                } else {
                    addError(DeckValidatorErrorType.PRIMARY, commander.getName(), "Oathbreaker (only planeswalker can be Oathbreaker, not " + commander.getName(), true);
                    valid = false;
                }
            }
        }
        // check size (1+1 or 2+2 allows)
        if (commanderNames.isEmpty() || commanderNames.size() > 2) {
            addError(DeckValidatorErrorType.PRIMARY, "Oathbreaker", "Sideboard must contains 1 or 2 oathbreakers, but found: " + commanderNames.size());
            valid = false;
        }
        if (signatureSpells.isEmpty() || signatureSpells.size() > 2) {
            addError(DeckValidatorErrorType.PRIMARY, "Signature Spell", "Sideboard must contains 1 or 2 signature spells, but found: " + signatureSpells.size());
            valid = false;
        }
        if (signatureSpells.size() != commanderNames.size()) {
            addError(DeckValidatorErrorType.PRIMARY, "Oathbreaker", "Sideboard must contains 1 + 1 or 2 + 2 cards, but found: " + commanderNames.size() + " + " + signatureSpells.size());
            valid = false;
        }
        // check partners
        for (Card commander : deck.getSideboard()) {
            if (commanderNames.contains(commander.getName())) {
                // partner checks
                if (commanderNames.size() == 2 && !commander.getAbilities().contains(PartnerAbility.getInstance())) {
                    boolean partnersWith = false;
                    for (Ability ability : commander.getAbilities()) {
                        if (ability instanceof PartnerWithAbility && commanderNames.contains(((PartnerWithAbility) ability).getPartnerName())) {
                            partnersWith = true;
                            break;
                        }
                    }
                    if (!partnersWith) {
                        addError(DeckValidatorErrorType.PRIMARY, commander.getName(), "Oathbreaker without Partner (" + commander.getName() + ')', true);
                        valid = false;
                    }
                }
            }
        }
        // xmage doesn't allows to select pairs of spell + oathbreaker, what's why it requires one color combo minimum
        for (Card spell : deck.getSideboard()) {
            if (signatureSpells.contains(spell.getName())) {
                FilterMana spellColor = spell.getColorIdentity();
                boolean haveSameColor = false;
                for (Card commander : deck.getSideboard()) {
                    if (commanderNames.contains(commander.getName())) {
                        FilterMana commanderColor = commander.getColorIdentity();
                        if (ManaUtil.isColorIdentityCompatible(commanderColor, spellColor)) {
                            haveSameColor = true;
                        }
                    }
                }
                if (!haveSameColor) {
                    addError(DeckValidatorErrorType.PRIMARY, spell.getName(), "Signature Spell (can't find oathbreaker with compatible color identity: " + spell.getName() + " - " + spellColor + ")", true);
                    valid = false;
                }
            }
        }
    }
    // no needs in cards check on wrong commanders
    if (!valid) {
        return false;
    }
    for (Card card : deck.getCards()) {
        if (!ManaUtil.isColorIdentityCompatible(allCommandersColor, card.getColorIdentity())) {
            addError(DeckValidatorErrorType.OTHER, card.getName(), "Invalid color (" + card.getColorIdentity() + ')', true);
            valid = false;
        }
    }
    for (Card card : deck.getSideboard()) {
        if (!isSetAllowed(card.getExpansionSetCode())) {
            if (!legalSets(card)) {
                addError(DeckValidatorErrorType.WRONG_SET, card.getName(), "Not allowed Set: " + card.getExpansionSetCode(), true);
                valid = false;
            }
        }
    }
    return valid;
}
Also used : PartnerAbility(mage.abilities.keyword.PartnerAbility) PartnerWithAbility(mage.abilities.keyword.PartnerWithAbility) Ability(mage.abilities.Ability) PartnerWithAbility(mage.abilities.keyword.PartnerWithAbility) FilterMana(mage.filter.FilterMana) Card(mage.cards.Card)

Aggregations

Ability (mage.abilities.Ability)359 Player (mage.players.Player)173 Permanent (mage.game.permanent.Permanent)134 UUID (java.util.UUID)126 Game (mage.game.Game)123 OneShotEffect (mage.abilities.effects.OneShotEffect)98 SimpleStaticAbility (mage.abilities.common.SimpleStaticAbility)87 CardSetInfo (mage.cards.CardSetInfo)87 CardImpl (mage.cards.CardImpl)85 CardType (mage.constants.CardType)78 Outcome (mage.constants.Outcome)76 Card (mage.cards.Card)72 SimpleActivatedAbility (mage.abilities.common.SimpleActivatedAbility)64 MageObject (mage.MageObject)57 MageInt (mage.MageInt)47 SpellAbility (mage.abilities.SpellAbility)43 Objects (java.util.Objects)38 Zone (mage.constants.Zone)38 mage.constants (mage.constants)37 FilterCard (mage.filter.FilterCard)35