package mage.cards; import mage.MageObject; import mage.Mana; import mage.abilities.Abilities; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.SubType; import mage.constants.Zone; import mage.counters.Counter; import mage.counters.Counters; import mage.filter.FilterMana; import mage.game.Game; import mage.game.GameState; import mage.game.Ownerable; import mage.game.permanent.Permanent; import mage.util.ManaUtil; import mage.watchers.common.CommanderPlaysCountWatcher; import java.util.List; import java.util.UUID; public interface Card extends MageObject, Ownerable { Rarity getRarity(); // null for tokens void setRarity(Rarity rarity); void setOwnerId(UUID ownerId); /** * For cards: return all basic and dynamic abilities * For permanents: return all basic and dynamic abilities * * @param game * @return */ Abilities getAbilities(Game game); void setSpellAbility(SpellAbility ability); SpellAbility getSpellAbility(); List getRules(); // gets base card rules List getRules(Game game); // gets card rules + in game modifications /** * Find ETB counters and apply it to permanent. * Warning, it's one time action, use it before a put to battlefield only. */ void applyEnterWithCounters(Permanent permanent, Ability source, Game game); void setFaceDown(boolean value, Game game); boolean isFaceDown(Game game); boolean turnFaceUp(Ability source, Game game, UUID playerId); // TODO: need research, is it lost morph and other face down statuses? boolean turnFaceDown(Ability source, Game game, UUID playerId); boolean isFlipCard(); String getFlipCardName(); boolean isTransformable(); Card getSecondCardFace(); SpellAbility getSecondFaceSpellAbility(); boolean isNightCard(); default boolean meldsWith(Card card) { return false; } default Class getMeldsToClazz() { return null; } default MeldCard getMeldsToCard() { return null; } /** * Is this an extra deck card? (such as contraptions and attractions) * * @return true if this is an extra deck card, false otherwise */ default boolean isExtraDeckCard() { return false; } void assignNewId(); void addInfo(String key, String value, Game game); // WARNING, don't add new move/remove methods (if you add then you must override it in all multi-part cards like Split or MDF) /** * Moves the card to the specified zone * * @param zone * @param source ability which calls that move, can be null * @param game * @param flag If zone *
    *
  • LIBRARY:
    • true - put on top
    • false - put on * bottom
  • *
  • BATTLEFIELD:
    • true - tapped
    • false - * untapped
  • *
* @return true if card was moved to zone */ boolean moveToZone(Zone zone, Ability source, Game game, boolean flag); boolean moveToZone(Zone zone, Ability source, Game game, boolean flag, List appliedEffects); /** * Moves the card to an exile zone * * @param exileId set to null for generic exile zone * @param name used for exile zone with the specified exileId * @param source * @param game * @return true if card was moved to zone */ boolean moveToExile(UUID exileId, String name, Ability source, Game game); boolean moveToExile(UUID exileId, String name, Ability source, Game game, List appliedEffects); boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId); // WARNING, don't add new move/remove methods (if you add then you must override it in all multi-parts card like Split Half or MDF Half) boolean removeFromZone(Game game, Zone fromZone, Ability source); boolean putOntoBattlefield(Game game, Zone fromZone, Ability source, UUID controllerId); boolean putOntoBattlefield(Game game, Zone fromZone, Ability source, UUID controllerId, boolean tapped); boolean putOntoBattlefield(Game game, Zone fromZone, Ability source, UUID controllerId, boolean tapped, boolean facedown); boolean putOntoBattlefield(Game game, Zone fromZone, Ability source, UUID controllerId, boolean tapped, boolean facedown, List appliedEffects); void setZone(Zone zone, Game game); List getMana(); Counters getCounters(Game game); Counters getCounters(GameState state); void addAbility(Ability ability); void looseAllAbilities(Game game); boolean addCounters(Counter counter, Ability source, Game game); boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game); boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, boolean isEffect); boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List appliedEffects); boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List appliedEffects, boolean isEffect); boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List appliedEffects, boolean isEffect, int maxCounters); /** * Remove {@param amount} counters of the specified kind. */ default void removeCounters(String counterName, int amount, Ability source, Game game) { removeCounters(counterName, amount, source, game, false); } /** * Remove {@param amount} counters of the specified kind. * * @param isDamage if the counter removal is a result of being damaged (e.g. for Deification to work) * @return amount of counters removed */ int removeCounters(String counterName, int amount, Ability source, Game game, boolean isDamage); default int removeCounters(Counter counter, Ability source, Game game) { return removeCounters(counter, source, game, false); } /** * Remove all counters of any kind. * * @param isDamage if the counter removal is a result of being damaged (e.g. for Deification to work) * @return amount of counters removed */ int removeCounters(Counter counter, Ability source, Game game, boolean isDamage); /** * Remove all counters of any kind. * * @return the amount of counters removed this way. */ default int removeAllCounters(Ability source, Game game) { return removeAllCounters(source, game, false); } /** * Remove all counters of any kind. * * @param isDamage if the counter removal is a result of being damaged (e.g. for Deification to work) * @return the amount of counters removed this way. */ int removeAllCounters(Ability source, Game game, boolean isDamage); /** * Remove all counters of a specific kind. Return the amount of counters removed this way. * * @return the amount of counters removed this way. */ default int removeAllCounters(String counterName, Ability source, Game game) { return removeAllCounters(counterName, source, game, false); } /** * Remove all counters of a specific kind. Return the amount of counters removed this way. * * @param isDamage if the counter removal is a result of being damaged (e.g. for Deification to work) * @return the amount of counters removed this way. */ int removeAllCounters(String counterName, Ability source, Game game, boolean isDamage); @Override Card copy(); /** * @return The main card of a split half card or adventure spell card, * otherwise the card itself is returned */ Card getMainCard(); /** * Gets the colors that are in the casting cost but also in the rules text * as far as not included in reminder text. * * @return */ FilterMana getColorIdentity(); List getAttachments(); /** * @param attachment can be any object: card, permanent, token * @param source can be null for default checks like state base * @param game * @param silentMode - use it to ignore warning message for users (e.g. for * checking only) * @return */ boolean cantBeAttachedBy(MageObject attachment, Ability source, Game game, boolean silentMode); boolean addAttachment(UUID permanentId, Ability source, Game game); boolean removeAttachment(UUID permanentId, Ability source, Game game); default boolean isOwnedBy(UUID controllerId) { return getOwnerId().equals(controllerId); } /** * Commander tax calculation. Tax logic can be changed (example: from {2} to life cost, see Liesa, Shroud of Dusk) * * @param game * @param source * @param abilityToModify * @return */ default boolean commanderCost(Game game, Ability source, Ability abilityToModify) { CommanderPlaysCountWatcher watcher = game.getState().getWatcher(CommanderPlaysCountWatcher.class); int castCount = watcher.getPlaysCount(getMainCard().getId()); if (castCount > 0) { abilityToModify.addManaCostsToPay(ManaUtil.createManaCost(2 * castCount, false)); } return true; } List getCardTypeForDeckbuilding(); boolean hasCardTypeForDeckbuilding(CardType cardType); /** * Checking subtype in cards for deck and companion validation * * @param subType * @return */ boolean hasSubTypeForDeckbuilding(SubType subType); }