Merge remote-tracking branch 'upstream/master'

This commit is contained in:
CCTV-1
2020-02-03 18:40:13 +08:00
63 changed files with 462 additions and 300 deletions

View File

@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.commons.lang3.StringUtils;
@@ -35,10 +36,8 @@ import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import forge.util.EnumUtil;
import forge.util.Settable;
/**
@@ -47,7 +46,6 @@ import forge.util.Settable;
* </p>
*
* @author Forge
* @version $Id: java 9708 2011-08-09 19:34:12Z jendave $
*/
public final class CardType implements Comparable<CardType>, CardTypeView {
private static final long serialVersionUID = 4629853583167022151L;
@@ -71,7 +69,8 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
Vanguard(false);
public final boolean isPermanent;
private static final ImmutableList<String> allCoreTypeNames = EnumUtil.getNames(CoreType.class);
private static Map<String, CoreType> stringToCoreType = EnumUtils.getEnumMap(CoreType.class);
private static final Set<String> allCoreTypeNames = stringToCoreType.keySet();
CoreType(final boolean permanent) {
isPermanent = permanent;
@@ -86,19 +85,8 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
Ongoing,
World;
private static final ImmutableList<String> allSuperTypeNames = EnumUtil.getNames(Supertype.class);
}
// This will be useful for faster parses
private static Map<String, CoreType> stringToCoreType = Maps.newHashMap();
private static Map<String, Supertype> stringToSupertype = Maps.newHashMap();
static {
for (final Supertype st : Supertype.values()) {
stringToSupertype.put(st.name(), st);
}
for (final CoreType ct : CoreType.values()) {
stringToCoreType.put(ct.name(), ct);
}
private static Map<String, Supertype> stringToSupertype = EnumUtils.getEnumMap(Supertype.class);
private static final Set<String> allSuperTypeNames = stringToSupertype.keySet();
}
private final Set<CoreType> coreTypes = EnumSet.noneOf(CoreType.class);
@@ -120,12 +108,12 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
public boolean add(final String t) {
boolean changed;
final CoreType ct = stringToCoreType.get(t);
final CoreType ct = EnumUtils.getEnum(CoreType.class, t);
if (ct != null) {
changed = coreTypes.add(ct);
}
else {
final Supertype st = stringToSupertype.get(t);
final Supertype st = EnumUtils.getEnum(Supertype.class, t);
if (st != null) {
changed = supertypes.add(st);
}
@@ -190,13 +178,21 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
public boolean remove(final String str) {
boolean changed = false;
if (CardType.isASupertype(str) && supertypes.remove(stringToSupertype.get(str))) {
// try to remove sub type first if able
if (subtypes.remove(str)) {
changed = true;
} else if (CardType.isACardType(str) && coreTypes.remove(stringToCoreType.get(str))) {
changed = true;
} else if (subtypes.remove(str)) {
} else {
Supertype st = EnumUtils.getEnum(Supertype.class, str);
if (st != null && supertypes.remove(st)) {
changed = true;
}
CoreType ct = EnumUtils.getEnum(CoreType.class, str);
if (ct != null && coreTypes.remove(ct)) {
changed = true;
}
}
if (changed) {
calculatedType = null;
}
@@ -267,15 +263,13 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
if (hasSubtype(t)) {
return true;
}
final char firstChar = t.charAt(0);
if (Character.isLowerCase(firstChar)) {
t = Character.toUpperCase(firstChar) + t.substring(1); //ensure string is proper case for enum types
}
final CoreType type = stringToCoreType.get(t);
t = StringUtils.capitalize(t);
final CoreType type = EnumUtils.getEnum(CoreType.class, t);
if (type != null) {
return hasType(type);
}
final Supertype supertype = stringToSupertype.get(t);
final Supertype supertype = EnumUtils.getEnum(Supertype.class, t);
if (supertype != null) {
return hasSupertype(supertype);
}
@@ -307,18 +301,18 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
return subtypes.contains(creatureType) || subtypes.contains("AllCreatureTypes");
}
private static String toMixedCase(final String s) {
if (s.equals("")) {
if (s.isEmpty()) {
return s;
}
final StringBuilder sb = new StringBuilder();
// to handle hyphenated Types
// TODO checkout WordUtils for this
final String[] types = s.split("-");
for (int i = 0; i < types.length; i++) {
if (i != 0) {
sb.append("-");
}
sb.append(types[i].substring(0, 1).toUpperCase());
sb.append(types[i].substring(1).toLowerCase());
sb.append(StringUtils.capitalize(types[i]));
}
return sb.toString();
}
@@ -666,10 +660,10 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
///////// Utility methods
public static boolean isACardType(final String cardType) {
return getAllCardTypes().contains(cardType);
return EnumUtils.isValidEnum(CoreType.class, cardType);
}
public static ImmutableList<String> getAllCardTypes() {
public static Set<String> getAllCardTypes() {
return CoreType.allCoreTypeNames;
}
@@ -714,7 +708,7 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
}
public static boolean isASupertype(final String cardType) {
return (Supertype.allSuperTypeNames.contains(cardType));
return EnumUtils.isValidEnum(Supertype.class, cardType);
}
public static boolean isASubType(final String cardType) {

View File

@@ -242,6 +242,9 @@ public class StaticEffect {
p.setUnlimitedHandSize(false);
p.setMaxHandSize(p.getStartingHandSize());
p.removeChangedKeywords(getTimestamp());
p.removeMaxLandPlays(getTimestamp());
p.removeMaxLandPlaysInfinite(getTimestamp());
}
// modify the affected card

View File

@@ -52,23 +52,27 @@ public class ChooseCardNameEffect extends SpellAbilityEffect {
final List<Player> tgtPlayers = getTargetPlayers(sa);
String valid = "Card";
String validDesc = "card";
String validDesc = null;
String message = null;
if (sa.hasParam("ValidCards")) {
valid = sa.getParam("ValidCards");
validDesc = sa.getParam("ValidDesc");
}
String message;
boolean randomChoice = sa.hasParam("AtRandom");
boolean chooseFromDefined = sa.hasParam("ChooseFromDefinedCards");
if (!randomChoice) {
if (sa.hasParam("SelectPrompt")) {
message = sa.getParam("SelectPrompt");
} else if (validDesc.equals("card")) {
} else if (null == validDesc) {
message = Localizer.getInstance().getMessage("lblChooseACardName");
} else {
message = Localizer.getInstance().getMessage("lblChooseASpecificCard", validDesc);
}
}
boolean randomChoice = sa.hasParam("AtRandom");
boolean chooseFromDefined = sa.hasParam("ChooseFromDefinedCards");
for (final Player p : tgtPlayers) {
if ((tgt == null) || p.canBeTargetedBy(sa)) {
String chosen = "";

View File

@@ -1477,6 +1477,10 @@ public class Card extends GameEntity implements Comparable<Card> {
view.updateChosenType(this);
}
public final boolean hasChosenType() {
return chosenType != null && !chosenType.isEmpty();
}
public final String getChosenColor() {
if (hasChosenColor()) {
return chosenColors.get(0);
@@ -3084,7 +3088,7 @@ public class Card extends GameEntity implements Comparable<Card> {
}
}
public final void addChangedCardTypes(final String[] types, final String[] removeTypes,
public final void addChangedCardTypes(final Iterable<String> types, final Iterable<String> removeTypes,
final boolean removeSuperTypes, final boolean removeCardTypes, final boolean removeSubTypes,
final boolean removeLandTypes, final boolean removeCreatureTypes, final boolean removeArtifactTypes,
final boolean removeEnchantmentTypes,
@@ -3094,7 +3098,7 @@ public class Card extends GameEntity implements Comparable<Card> {
timestamp, true);
}
public final void addChangedCardTypes(final String[] types, final String[] removeTypes,
public final void addChangedCardTypes(final Iterable<String> types, final Iterable<String> removeTypes,
final boolean removeSuperTypes, final boolean removeCardTypes, final boolean removeSubTypes,
final boolean removeLandTypes, final boolean removeCreatureTypes, final boolean removeArtifactTypes,
final boolean removeEnchantmentTypes,
@@ -3102,11 +3106,11 @@ public class Card extends GameEntity implements Comparable<Card> {
CardType addType = null;
CardType removeType = null;
if (types != null) {
addType = new CardType(Arrays.asList(types));
addType = new CardType(types);
}
if (removeTypes != null) {
removeType = new CardType(Arrays.asList(removeTypes));
removeType = new CardType(removeTypes);
}
addChangedCardTypes(addType, removeType, removeSuperTypes, removeCardTypes, removeSubTypes,

View File

@@ -15,12 +15,15 @@ import forge.util.TextUtil;
public class GameEventPlayerStatsChanged extends GameEvent {
public final Collection<Player> players;
public GameEventPlayerStatsChanged(Player affected) {
public final boolean updateCards;
public GameEventPlayerStatsChanged(Player affected, boolean updateCards) {
players = Arrays.asList(affected);
this.updateCards = updateCards;
}
public GameEventPlayerStatsChanged(Collection<Player> affected) {
public GameEventPlayerStatsChanged(Collection<Player> affected, boolean updateCards) {
players = affected;
this.updateCards = updateCards;
}
/* (non-Javadoc)

View File

@@ -2,162 +2,158 @@ package forge.game.keyword;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import forge.StaticData;
import forge.game.card.Card;
import forge.item.PaperCard;
import forge.util.EnumUtil;
import forge.util.TextUtil;
public enum Keyword {
UNDEFINED(SimpleKeyword.class, false, ""),
ABSORB(KeywordWithAmount.class, false, "If a source would deal damage to this creature, prevent %d of that damage."),
ADAPT(KeywordWithCostAndAmount.class, false, "If this creature has no +1/+1 counters on it, put {%2$d:+1/+1 counter} on it."),
AFFINITY(KeywordWithType.class, false, "This spell costs you {1} less to cast for each %s you control."),
AFFLICT(KeywordWithAmount.class, false, "Whenever this creature becomes blocked, defending player loses %d life."),
AFTERLIFE(KeywordWithAmount.class, false, "When this creature dies, create {%1$d:1/1 white and black Spirit creature token} with flying."),
AFTERMATH(SimpleKeyword.class, false, "Cast this spell only from your graveyard. Then exile it."),
AMPLIFY(KeywordWithAmountAndType.class, false, "As this creature enters the battlefield, put {%d:+1/+1 counter} on it for each %s card you reveal in your hand."),
ANNIHILATOR(KeywordWithAmount.class, false, "Whenever this creature attacks, defending player sacrifices {%d:permanent}."),
ASCEND(SimpleKeyword.class, true, "If you control ten or more permanents, you get the city's blessing for the rest of the game."),
ASSIST(SimpleKeyword.class, true, "Another player can pay up to %s of this spell's cost."),
AURA_SWAP(KeywordWithCost.class, false, "%s: You may exchange this Aura with an Aura card in your hand."),
AWAKEN(KeywordWithCostAndAmount.class, false, "If you cast this spell for %s, also put {%d:+1/+1 counter} on target land you control and it becomes a 0/0 Elemental creature with haste. It's still a land."),
BANDING(SimpleKeyword.class, true, "Any creatures with banding, and up to one without, can attack in a band. Bands are blocked as a group. If any creatures with banding you control are blocking or being blocked by a creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking."),
BATTLE_CRY(SimpleKeyword.class, false, "Whenever this creature attacks, each other attacking creature gets +1/+0 until end of turn."),
BESTOW(KeywordWithCost.class, true, "If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature."),
BLOODTHIRST(KeywordWithAmount.class, false, "If an opponent was dealt damage this turn, this creature enters the battlefield with {%d:+1/+1 counter} on it."),
BUSHIDO(KeywordWithAmount.class, false, "Whenever this creature blocks or becomes blocked, it gets +%1$d/+%1$d until end of turn."),
BUYBACK(KeywordWithCost.class, false, "You may pay an additional %s as you cast this spell. If you do, put it into your hand instead of your graveyard as it resolves."),
CASCADE(SimpleKeyword.class, false, "When you cast this spell, exile cards from the top of your library until you exile a nonland card that costs less. You may cast it without paying its mana cost. Put the exiled cards on the bottom of your library in a random order."),
CHAMPION(KeywordWithType.class, false, "When this enters the battlefield, sacrifice it unless you exile another %s you control. When this leaves the battlefield, that card returns to the battlefield."),
CHANGELING(SimpleKeyword.class, true, "This card is every creature type."),
CIPHER(SimpleKeyword.class, true, "Then you may exile this spell card encoded on a creature you control. Whenever that creature deals combat damage to a player, its controller may cast a copy of the encoded card without paying its mana cost."),
CONSPIRE(SimpleKeyword.class, false, "As an additional cost to cast this spell, you may tap two untapped creatures you control that each share a color with it. If you do, copy it."),
CONVOKE(SimpleKeyword.class, true, "Your creatures can help cast this spell. Each creature you tap while playing this spell reduces its cost by {1} or by one mana of that creature's color."),
CREW(KeywordWithAmount.class, false, "Tap any number of creatures you control with total power %1$d or more: This Vehicle becomes an artifact creature until end of turn."),
CUMULATIVE_UPKEEP(KeywordWithCost.class, false, "At the beginning of your upkeep, put an age counter on this permanent, then sacrifice it unless you pay its upkeep cost for each age counter on it."),
CYCLING(KeywordWithCost.class, false, "%s, Discard this card: Draw a card."), //Typecycling reminder text handled by Cycling class
DASH(KeywordWithCost.class, true, "You may cast this spell for its dash cost. If you do, it gains haste, and it's returned from the battlefield to its owner's hand at the beginning of the next end step."),
DEATHTOUCH(SimpleKeyword.class, true, "Any amount of damage this deals to a creature is enough to destroy it."),
DEFENDER(SimpleKeyword.class, true, "This creature can't attack."),
DELVE(SimpleKeyword.class, true, "As an additional cost to cast this spell, you may exile any number of cards from your graveyard. Each card exiled this way reduces the cost to cast this spell by {1}."),
DETHRONE(SimpleKeyword.class, false, "Whenever this creature attacks the player with the most life or tied for the most life, put a +1/+1 counter on it."),
DEVOUR(KeywordWithAmount.class, false, "As this creature enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with {%d:+1/+1 counter} on it for each creature sacrificed this way."),
DEVOID(SimpleKeyword.class, true, "This card has no color."),
DOUBLE_STRIKE(SimpleKeyword.class, true, "This creature deals both first-strike and regular combat damage."),
DREDGE(KeywordWithAmount.class, true, "If you would draw a card, instead you may put exactly {%d:card} from the top of your library into your graveyard. If you do, return this card from your graveyard to your hand. Otherwise, draw a card."),
ECHO(KeywordWithCost.class, false, "At the beginning of your upkeep, if this permanent came under your control since the beginning of your last upkeep, sacrifice it unless you pay %s."),
EMBALM(KeywordWithCost.class, false, "Create a token that's a copy of this card, except it's white, it has no mana cost, and it's a Zombie in addition to its other types. Embalm only as a sorcery."),
EMERGE(KeywordWithCost.class, true, "You may cast this spell by sacrificing a creature and paying the emerge cost reduced by that creature's converted mana cost."),
ENCHANT(KeywordWithType.class, false, "Target a %s as you cast this. This card enters the battlefield attached to that %s."),
ENTWINE(KeywordWithCost.class, true, "You may choose all modes of this spell instead of just one. If you do, you pay an additional %s."),
EPIC(SimpleKeyword.class, true, "For the rest of the game, you can't cast spells. At the beginning of each of your upkeeps for the rest of the game, copy this spell except for its epic ability. If the spell has any targets, you may choose new targets for the copy."),
EQUIP(Equip.class, false, "%s: Attach to target %s you control. Equip only as a sorcery."),
ESCAPE(KeywordWithCost.class, false, "You may cast this card from your graveyard for its escape cost."),
ESCALATE(KeywordWithCost.class, true, "Pay this cost for each mode chosen beyond the first."),
ETERNALIZE(KeywordWithCost.class, false, "Create a token that's a copy of this card, except it's black, it's 4/4, it has no mana cost, and it's a Zombie in addition to its other types. Eternalize only as a sorcery."),
EVOKE(KeywordWithCost.class, false, "You may cast this spell for its evoke cost. If you do, it's sacrificed when it enters the battlefield."),
EVOLVE(SimpleKeyword.class, false, "Whenever a creature enters the battlefield under your control, if that creature has greater power or toughness than this creature, put a +1/+1 counter on this creature."),
EXALTED(SimpleKeyword.class, false, "Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn."),
EXERTED(SimpleKeyword.class, true, "This creature won't untap during your next untap step."),
EXPLOIT(SimpleKeyword.class, false, "When this creature enters the battlefield, you may sacrifice a creature."),
EXTORT(SimpleKeyword.class, false, "Whenever you cast a spell, you may pay {W/B}. If you do, each opponent loses 1 life and you gain that much life."),
FABRICATE(KeywordWithAmount.class, false, "When this creature enters the battlefield, put {%1$d:+1/+1 counter} on it, or create {%1$d:1/1 colorless Servo artifact creature token}."),
FADING(KeywordWithAmount.class, false, "This permanent enters the battlefield with {%d:fade counter} on it. At the beginning of your upkeep, remove a fade counter from it. If you can't, sacrifice it."),
FATESEAL(KeywordWithAmount.class, false, "Look at the top {%d:card} of an opponent's library, then put any number of them on the bottom of that player's library and the rest on top in any order."),
FEAR(SimpleKeyword.class, true, "This creature can't be blocked except by artifact creatures and/or black creatures."),
FIRST_STRIKE(SimpleKeyword.class, true, "This creature deals combat damage before creatures without first strike."),
FLANKING(SimpleKeyword.class, false, "Whenever this creature becomes blocked by a creature without flanking, the blocking creature gets -1/-1 until end of turn."),
FLASH(SimpleKeyword.class, true, "You may cast this spell any time you could cast an instant."),
FLASHBACK(KeywordWithCost.class, false, "You may cast this card from your graveyard by paying %s rather than paying its mana cost. If you do, exile it as it resolves."),
FLYING(SimpleKeyword.class, true, "This creature can't be blocked except by creatures with flying or reach."),
FORECAST(KeywordWithCost.class, false, "Activate this ability only during your upkeep and only once each turn."),
FORTIFY(KeywordWithCost.class, false, "%s: Attach to target land you control. Fortify only as a sorcery."),
FRENZY(KeywordWithAmount.class, false, "Whenever this creature attacks and isn't blocked, it gets +%d/+0 until end of turn."),
GRAFT(KeywordWithAmount.class, false, "This permanent enters the battlefield with {%d:+1/+1 counter} on it. Whenever another creature enters the battlefield, you may move a +1/+1 counter from this permanent onto it."),
GRAVESTORM(SimpleKeyword.class, false, "When you cast this spell, copy it for each permanent that was put into a graveyard from the battlefield this turn. You may choose new targets for the copies."),
HASTE(SimpleKeyword.class, true, "This creature can attack and {T} as soon as it comes under your control."),
HAUNT(SimpleKeyword.class, false, "When this is put into a graveyard, exile it haunting target creature."),
HEXPROOF(Hexproof.class, false, "This can't be the target of %s spells or abilities your opponents control."),
HIDEAWAY(SimpleKeyword.class, false, "This land enters the battlefield tapped. When it does, look at the top four cards of your library, exile one face down, then put the rest on the bottom of your library."),
HORSEMANSHIP(SimpleKeyword.class, true, "This creature can't be blocked except by creatures with horsemanship."),
IMPROVISE(SimpleKeyword.class, true, "Your artifacts can help cast this spell. Each artifact you tap after you're done activating mana abilities pays for {1}."),
INDESTRUCTIBLE(SimpleKeyword.class, true, "Effects that say \"destroy\" dont destroy this."),
INFECT(SimpleKeyword.class, true, "This creature deals damage to creatures in the form of -1/-1 counters and to players in the form of poison counters."),
INGEST(SimpleKeyword.class, false, "Whenever this creature deals combat damage to a player, that player exiles the top card of their library."),
INTIMIDATE(SimpleKeyword.class, true, "This creature can't be blocked except by artifact creatures and/or creatures that share a color with it."),
KICKER(Kicker.class, false, "You may pay an additional %s as you cast this spell."),
JUMP_START(SimpleKeyword.class, false, "You may cast this card from your graveyard by discarding a card in addition to paying its other costs. Then exile this card."),
LANDWALK(KeywordWithType.class, false, "This creature is unblockable as long as defending player controls a %s."),
LEVEL_UP(KeywordWithCost.class, false, "%s: Put a level counter on this. Level up only as a sorcery."),
LIFELINK(SimpleKeyword.class, true, "Damage dealt by this creature also causes its controller to gain that much life."),
LIVING_WEAPON(SimpleKeyword.class, true, "When this Equipment enters the battlefield, create a 0/0 black Germ creature token, then attach this to it."),
MADNESS(KeywordWithCost.class, true, "If you discard this card, discard it into exile. When you do, cast it for %s or put it into your graveyard."),
MELEE(SimpleKeyword.class, false, "Whenever this creature attacks, it gets +1/+1 until end of turn for each opponent you attacked with a creature this combat."),
MENTOR(SimpleKeyword.class, false, "Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power."),
MENACE(SimpleKeyword.class, true, "This creature can't be blocked except by two or more creatures."),
MEGAMORPH(KeywordWithCost.class, false, "You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its megamorph cost and put a +1/+1 counter on it."),
MIRACLE(KeywordWithCost.class, false, "You may cast this card for its miracle cost when you draw it if it's the first card you drew this turn."),
MONSTROSITY(KeywordWithCostAndAmount.class, false, "If this creature isn't monstrous, put {%2$d:+1/+1 counter} on it and it becomes monstrous."),
MODULAR(Modular.class, false, "This creature enters the battlefield with {%d:+1/+1 counter} on it. When it dies, you may put its +1/+1 counters on target artifact creature."),
MORPH(KeywordWithCost.class, false, "You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost."),
MULTIKICKER(KeywordWithCost.class, false, "You may pay an additional %s any number of times as you cast this spell."),
MYRIAD(SimpleKeyword.class, false, "Whenever this creature attacks, for each opponent other than defending player, you may create a token that's a copy of this creature that's tapped and attacking that player or a planeswalker they control. Exile the tokens at end of combat."),
NINJUTSU(Ninjutsu.class, false, "%s, Return an unblocked attacker you control to hand: Put this card onto the battlefield from your %s tapped and attacking."),
OUTLAST(KeywordWithCost.class, false, "%s, {T}: Put a +1/+1 counter on this creature. Outlast only as a sorcery."),
OFFERING(KeywordWithType.class, false, "You may cast this card any time you could cast an instant by sacrificing a %1$s and paying the difference in mana costs between this and the sacrificed %1$s. Mana cost includes color."),
PARTNER(Partner.class, true, "You can have two commanders if both have partner."),
PERSIST(SimpleKeyword.class, true, "When this creature dies, if it had no -1/-1 counters on it, return it to the battlefield under its owner's control with a -1/-1 counter on it."),
PHASING(SimpleKeyword.class, true, "This phases in or out before you untap during each of your untap steps. While it's phased out, it's treated as though it doesn't exist."),
POISONOUS(KeywordWithAmount.class, false, "Whenever this creature deals combat damage to a player, that player gets {%d:poison counter}."),
PRESENCE(KeywordWithType.class, false, "As an additional cost to cast CARDNAME, you may reveal a %s card from your hand."),
PROTECTION(Protection.class, false, "This creature can't be blocked, targeted, dealt damage, or equipped/enchanted by %s."),
PROVOKE(SimpleKeyword.class, false, "Whenever this creature attacks, you may have target creature defending player controls untap and block it if able."),
PROWESS(SimpleKeyword.class, false, "Whenever you cast a noncreature spell, this creature gets +1/+1 until end of turn."),
PROWL(KeywordWithCost.class, false, "You may pay %s rather than pay this spells mana cost if a player was dealt combat damage this turn by a source that, at the time it dealt that damage, was under your control and had any of this spells creature types."),
RAMPAGE(KeywordWithAmount.class, false, "Whenever this creature becomes blocked, it gets +%1$d/+%1$d until end of turn for each creature blocking it beyond the first."),
REACH(SimpleKeyword.class, true, "This creature can block creatures with flying."),
REBOUND(SimpleKeyword.class, true, "If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost."),
RECOVER(KeywordWithCost.class, false, "When a creature is put into your graveyard from the battlefield, you may pay %s. If you do, return this card from your graveyard to your hand. Otherwise, exile this card."),
REINFORCE(KeywordWithCostAndAmount.class, false, "%s, Discard this card: Put {%d:+1/+1 counter} on target creature."),
RENOWN(KeywordWithAmount.class, true, "When this creature deals combat damage to a player, if it isn't renowned, put {%d:+1/+1 counter} on it and it becomes renowned."),
REPLICATE(KeywordWithCost.class, false, "As an additional cost to cast this spell, you may pay %s any number of times. If you do, copy it that many times. You may choose new targets for the copies."),
RETRACE(SimpleKeyword.class, true, "You may cast this card from your graveyard by discarding a land card in addition to paying its other costs."),
RIOT(SimpleKeyword.class, false, "This creature enters the battlefield with your choice of a +1/+1 counter or haste."),
RIPPLE(KeywordWithAmount.class, false, "When you cast this spell, you may reveal the top {%d:card} of your library. You may cast any of those cards with the same name as this spell without paying their mana costs. Put the rest on the bottom of your library in any order."),
SHADOW(SimpleKeyword.class, true, "This creature can block or be blocked by only creatures with shadow."),
SHROUD(SimpleKeyword.class, true, "This can't be the target of spells or abilities."),
SKULK(SimpleKeyword.class, true, "This creature can't be blocked by creatures with greater power."),
SCAVENGE(KeywordWithCost.class, false, "%s, Exile this card from your graveyard: Put a number of +1/+1 counters equal to this card's power on target creature. Scavenge only as a sorcery."),
SOULBOND(SimpleKeyword.class, true, "You may pair this creature with another unpaired creature when either enters the battlefield. They remain paired for as long as you control both of them"),
SOULSHIFT(KeywordWithAmount.class, false, "When this creature dies, you may return target Spirit card with converted mana cost %d or less from your graveyard to your hand."),
SPECTACLE(KeywordWithCost.class, true, "You may cast this spell for its spectacle cost rather than its mana cost if an opponent lost life this turn."),
SPLICE(KeywordWithCostAndType.class, false, "As you cast an %2$s spell, you may reveal this card from your hand and pay its splice cost. If you do, add this card's effects to that spell."),
SPLIT_SECOND(SimpleKeyword.class, true, "As long as this spell is on the stack, players can't cast other spells or activate abilities that aren't mana abilities."),
STORM(SimpleKeyword.class, false, "When you cast this spell, copy it for each other spell that was cast before it this turn. You may choose new targets for the copies."),
STRIVE(KeywordWithCost.class, false, "CARDNAME costs %s more to cast for each target beyond the first."),
SUNBURST(SimpleKeyword.class, false, "This enters the battlefield with either a +1/+1 or charge counter on it for each color of mana spent to cast it based on whether it's a creature."),
SURGE(KeywordWithCost.class, true, "You may cast this spell for its surge cost if you or a teammate has cast another spell this turn."),
SUSPEND(Suspend.class, false, "Rather than cast this card from your hand, you may pay %s and exile it with {%d:time counter} on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost."),
TOTEM_ARMOR(SimpleKeyword.class, true, "If enchanted permanent would be destroyed, instead remove all damage marked on it and destroy this Aura."),
TRAMPLE(SimpleKeyword.class, true, "This creature can deal excess combat damage to the player or planeswalker it's attacking."),
TRANSFIGURE(KeywordWithCost.class, false, "%s, Sacrifice this creature: Search your library for a creature card with the same converted mana cost as this creature and put that card onto the battlefield. Then shuffle your library. Transfigure only as a sorcery."),
TRANSMUTE(KeywordWithCost.class, false, "%s, Discard this card: Search your library for a card with the same converted mana cost as this card, reveal it, and put it into your hand. Then shuffle your library. Transmute only as a sorcery."),
TRIBUTE(KeywordWithAmount.class, false, "As this creature enters the battlefield, an opponent of your choice may put {%d:+1/+1 counter} on it."),
TYPECYCLING(KeywordWithCostAndType.class, false, "%s, Discard this card: Search your library for a %s card, reveal it, put it into your hand, then shuffle your library."),
UNDAUNTED(SimpleKeyword.class, false, "This spell costs {1} less to cast for each opponent."),
UNDYING(SimpleKeyword.class, true, "When this creature dies, if it had no +1/+1 counters on it, return it to the battlefield under its owner's control with a +1/+1 counter on it."),
UNEARTH(KeywordWithCost.class, false, "%s: Return this card from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step or if it would leave the battlefield. Unearth only as a sorcery."),
UNLEASH(SimpleKeyword.class, true, "You may have this creature enter the battlefield with a +1/+1 counter on it. It can't block as long as it has a +1/+1 counter on it."),
VANISHING(KeywordWithAmount.class, false, "This permanent enters the battlefield with {%d:time counter} on it. At the beginning of your upkeep, remove a time counter from it. When the last is removed, sacrifice it."),
VIGILANCE(SimpleKeyword.class, true, "Attacking doesn't cause this creature to tap."),
WITHER(SimpleKeyword.class, true, "This deals damage to creatures in the form of -1/-1 counters."),
UNDEFINED("", SimpleKeyword.class, false, ""),
ABSORB("Absorb", KeywordWithAmount.class, false, "If a source would deal damage to this creature, prevent %d of that damage."),
ADAPT("Adapt", KeywordWithCostAndAmount.class, false, "If this creature has no +1/+1 counters on it, put {%2$d:+1/+1 counter} on it."),
AFFINITY("Affinity", KeywordWithType.class, false, "This spell costs you {1} less to cast for each %s you control."),
AFFLICT("Afflict", KeywordWithAmount.class, false, "Whenever this creature becomes blocked, defending player loses %d life."),
AFTERLIFE("Afterlife", KeywordWithAmount.class, false, "When this creature dies, create {%1$d:1/1 white and black Spirit creature token} with flying."),
AFTERMATH("Aftermath", SimpleKeyword.class, false, "Cast this spell only from your graveyard. Then exile it."),
AMPLIFY("Amplify", KeywordWithAmountAndType.class, false, "As this creature enters the battlefield, put {%d:+1/+1 counter} on it for each %s card you reveal in your hand."),
ANNIHILATOR("Annihilator", KeywordWithAmount.class, false, "Whenever this creature attacks, defending player sacrifices {%d:permanent}."),
ASCEND("Ascend", SimpleKeyword.class, true, "If you control ten or more permanents, you get the city's blessing for the rest of the game."),
ASSIST("Assist", SimpleKeyword.class, true, "Another player can pay up to %s of this spell's cost."),
AURA_SWAP("Aura swap", KeywordWithCost.class, false, "%s: You may exchange this Aura with an Aura card in your hand."),
AWAKEN("Awaken", KeywordWithCostAndAmount.class, false, "If you cast this spell for %s, also put {%d:+1/+1 counter} on target land you control and it becomes a 0/0 Elemental creature with haste. It's still a land."),
BANDING("Banding", SimpleKeyword.class, true, "Any creatures with banding, and up to one without, can attack in a band. Bands are blocked as a group. If any creatures with banding you control are blocking or being blocked by a creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking."),
BATTLE_CRY("Battle cry", SimpleKeyword.class, false, "Whenever this creature attacks, each other attacking creature gets +1/+0 until end of turn."),
BESTOW("Bestow", KeywordWithCost.class, false, "If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature."),
BLOODTHIRST("Bloodthrist", KeywordWithAmount.class, false, "If an opponent was dealt damage this turn, this creature enters the battlefield with {%d:+1/+1 counter} on it."),
BUSHIDO("Bushido", KeywordWithAmount.class, false, "Whenever this creature blocks or becomes blocked, it gets +%1$d/+%1$d until end of turn."),
BUYBACK("Buyback", KeywordWithCost.class, false, "You may pay an additional %s as you cast this spell. If you do, put it into your hand instead of your graveyard as it resolves."),
CASCADE("Cascade", SimpleKeyword.class, false, "When you cast this spell, exile cards from the top of your library until you exile a nonland card that costs less. You may cast it without paying its mana cost. Put the exiled cards on the bottom of your library in a random order."),
CHAMPION("Champion", KeywordWithType.class, false, "When this enters the battlefield, sacrifice it unless you exile another %s you control. When this leaves the battlefield, that card returns to the battlefield."),
CHANGELING("Changeling", SimpleKeyword.class, true, "This card is every creature type."),
CIPHER("Cipher", SimpleKeyword.class, true, "Then you may exile this spell card encoded on a creature you control. Whenever that creature deals combat damage to a player, its controller may cast a copy of the encoded card without paying its mana cost."),
CONSPIRE("Conspire", SimpleKeyword.class, false, "As an additional cost to cast this spell, you may tap two untapped creatures you control that each share a color with it. If you do, copy it."),
CONVOKE("Convoke", SimpleKeyword.class, true, "Your creatures can help cast this spell. Each creature you tap while playing this spell reduces its cost by {1} or by one mana of that creature's color."),
CREW("Crew", KeywordWithAmount.class, false, "Tap any number of creatures you control with total power %1$d or more: This Vehicle becomes an artifact creature until end of turn."),
CUMULATIVE_UPKEEP("Cumulative upkeep", KeywordWithCost.class, false, "At the beginning of your upkeep, put an age counter on this permanent, then sacrifice it unless you pay its upkeep cost for each age counter on it."),
CYCLING("Cycling", KeywordWithCost.class, false, "%s, Discard this card: Draw a card."), //Typecycling reminder text handled by Cycling class
DASH("Dash", KeywordWithCost.class, false, "You may cast this spell for its dash cost. If you do, it gains haste, and it's returned from the battlefield to its owner's hand at the beginning of the next end step."),
DEATHTOUCH("Deathtouch", SimpleKeyword.class, true, "Any amount of damage this deals to a creature is enough to destroy it."),
DEFENDER("Defender", SimpleKeyword.class, true, "This creature can't attack."),
DELVE("Delve", SimpleKeyword.class, true, "As an additional cost to cast this spell, you may exile any number of cards from your graveyard. Each card exiled this way reduces the cost to cast this spell by {1}."),
DETHRONE("Dethrone", SimpleKeyword.class, false, "Whenever this creature attacks the player with the most life or tied for the most life, put a +1/+1 counter on it."),
DEVOUR("Devour", KeywordWithAmount.class, false, "As this creature enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with {%d:+1/+1 counter} on it for each creature sacrificed this way."),
DEVOID("Devoid", SimpleKeyword.class, true, "This card has no color."),
DOUBLE_STRIKE("Double Strike", SimpleKeyword.class, true, "This creature deals both first-strike and regular combat damage."),
DREDGE("Dredge", KeywordWithAmount.class, false, "If you would draw a card, instead you may put exactly {%d:card} from the top of your library into your graveyard. If you do, return this card from your graveyard to your hand. Otherwise, draw a card."),
ECHO("Echo", KeywordWithCost.class, false, "At the beginning of your upkeep, if this permanent came under your control since the beginning of your last upkeep, sacrifice it unless you pay %s."),
EMBALM("Embalm", KeywordWithCost.class, false, "Create a token that's a copy of this card, except it's white, it has no mana cost, and it's a Zombie in addition to its other types. Embalm only as a sorcery."),
EMERGE("Emerge", KeywordWithCost.class, false, "You may cast this spell by sacrificing a creature and paying the emerge cost reduced by that creature's converted mana cost."),
ENCHANT("Enchant", KeywordWithType.class, false, "Target a %s as you cast this. This card enters the battlefield attached to that %s."),
ENTWINE("Entwine", KeywordWithCost.class, true, "You may choose all modes of this spell instead of just one. If you do, you pay an additional %s."),
EPIC("Epic", SimpleKeyword.class, true, "For the rest of the game, you can't cast spells. At the beginning of each of your upkeeps for the rest of the game, copy this spell except for its epic ability. If the spell has any targets, you may choose new targets for the copy."),
EQUIP("Equip", Equip.class, false, "%s: Attach to target %s you control. Equip only as a sorcery."),
ESCAPE("Escape", KeywordWithCost.class, false, "You may cast this card from your graveyard for its escape cost."),
ESCALATE("Escalate", KeywordWithCost.class, true, "Pay this cost for each mode chosen beyond the first."),
ETERNALIZE("Eternalize", KeywordWithCost.class, false, "Create a token that's a copy of this card, except it's black, it's 4/4, it has no mana cost, and it's a Zombie in addition to its other types. Eternalize only as a sorcery."),
EVOKE("Evoke", KeywordWithCost.class, false, "You may cast this spell for its evoke cost. If you do, it's sacrificed when it enters the battlefield."),
EVOLVE("Evolve", SimpleKeyword.class, false, "Whenever a creature enters the battlefield under your control, if that creature has greater power or toughness than this creature, put a +1/+1 counter on this creature."),
EXALTED("Exalted", SimpleKeyword.class, false, "Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn."),
EXERTED("Exerted", SimpleKeyword.class, true, "This creature won't untap during your next untap step."),
EXPLOIT("Exploit", SimpleKeyword.class, false, "When this creature enters the battlefield, you may sacrifice a creature."),
EXTORT("Extort", SimpleKeyword.class, false, "Whenever you cast a spell, you may pay {W/B}. If you do, each opponent loses 1 life and you gain that much life."),
FABRICATE("Fabricate", KeywordWithAmount.class, false, "When this creature enters the battlefield, put {%1$d:+1/+1 counter} on it, or create {%1$d:1/1 colorless Servo artifact creature token}."),
FADING("Fading", KeywordWithAmount.class, false, "This permanent enters the battlefield with {%d:fade counter} on it. At the beginning of your upkeep, remove a fade counter from it. If you can't, sacrifice it."),
FEAR("Fear", SimpleKeyword.class, true, "This creature can't be blocked except by artifact creatures and/or black creatures."),
FIRST_STRIKE("First Strike", SimpleKeyword.class, true, "This creature deals combat damage before creatures without first strike."),
FLANKING("Flanking", SimpleKeyword.class, false, "Whenever this creature becomes blocked by a creature without flanking, the blocking creature gets -1/-1 until end of turn."),
FLASH("Flash", SimpleKeyword.class, true, "You may cast this spell any time you could cast an instant."),
FLASHBACK("Flashback", KeywordWithCost.class, false, "You may cast this card from your graveyard by paying %s rather than paying its mana cost. If you do, exile it as it resolves."),
FLYING("Flying", SimpleKeyword.class, true, "This creature can't be blocked except by creatures with flying or reach."),
FORECAST("Forecast", KeywordWithCost.class, false, "Activate this ability only during your upkeep and only once each turn."),
FORTIFY("Fortify", KeywordWithCost.class, false, "%s: Attach to target land you control. Fortify only as a sorcery."),
FRENZY("Frenzy", KeywordWithAmount.class, false, "Whenever this creature attacks and isn't blocked, it gets +%d/+0 until end of turn."),
GRAFT("Graft", KeywordWithAmount.class, false, "This permanent enters the battlefield with {%d:+1/+1 counter} on it. Whenever another creature enters the battlefield, you may move a +1/+1 counter from this permanent onto it."),
GRAVESTORM("Gravestorm", SimpleKeyword.class, false, "When you cast this spell, copy it for each permanent that was put into a graveyard from the battlefield this turn. You may choose new targets for the copies."),
HASTE("Haste", SimpleKeyword.class, true, "This creature can attack and {T} as soon as it comes under your control."),
HAUNT("Haunt", SimpleKeyword.class, false, "When this is put into a graveyard, exile it haunting target creature."),
HEXPROOF("Hexproof", Hexproof.class, false, "This can't be the target of %s spells or abilities your opponents control."),
HIDEAWAY("Hideaway", SimpleKeyword.class, false, "This land enters the battlefield tapped. When it does, look at the top four cards of your library, exile one face down, then put the rest on the bottom of your library."),
HORSEMANSHIP("Horsemanship", SimpleKeyword.class, true, "This creature can't be blocked except by creatures with horsemanship."),
IMPROVISE("Improvise", SimpleKeyword.class, true, "Your artifacts can help cast this spell. Each artifact you tap after you're done activating mana abilities pays for {1}."),
INDESTRUCTIBLE("Indestructible", SimpleKeyword.class, true, "Effects that say \"destroy\" dont destroy this."),
INFECT("Infect", SimpleKeyword.class, true, "This creature deals damage to creatures in the form of -1/-1 counters and to players in the form of poison counters."),
INGEST("Ingest", SimpleKeyword.class, false, "Whenever this creature deals combat damage to a player, that player exiles the top card of their library."),
INTIMIDATE("Intimidate", SimpleKeyword.class, true, "This creature can't be blocked except by artifact creatures and/or creatures that share a color with it."),
KICKER("Kicker", Kicker.class, false, "You may pay an additional %s as you cast this spell."),
JUMP_START("Jump-start", SimpleKeyword.class, false, "You may cast this card from your graveyard by discarding a card in addition to paying its other costs. Then exile this card."),
LANDWALK("Landwalk", KeywordWithType.class, false, "This creature is unblockable as long as defending player controls a %s."),
LEVEL_UP("Level up", KeywordWithCost.class, false, "%s: Put a level counter on this. Level up only as a sorcery."),
LIFELINK("Lifelink", SimpleKeyword.class, true, "Damage dealt by this creature also causes its controller to gain that much life."),
LIVING_WEAPON("Living weapon", SimpleKeyword.class, true, "When this Equipment enters the battlefield, create a 0/0 black Germ creature token, then attach this to it."),
MADNESS("Madness", KeywordWithCost.class, false, "If you discard this card, discard it into exile. When you do, cast it for %s or put it into your graveyard."),
MELEE("Melee", SimpleKeyword.class, false, "Whenever this creature attacks, it gets +1/+1 until end of turn for each opponent you attacked with a creature this combat."),
MENTOR("Mentor", SimpleKeyword.class, false, "Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power."),
MENACE("Menace", SimpleKeyword.class, true, "This creature can't be blocked except by two or more creatures."),
MEGAMORPH("Megamorph", KeywordWithCost.class, false, "You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its megamorph cost and put a +1/+1 counter on it."),
MIRACLE("Miracle", KeywordWithCost.class, false, "You may cast this card for its miracle cost when you draw it if it's the first card you drew this turn."),
// technically not a keyword but easier this way
MONSTROSITY("Monstrosity", KeywordWithCostAndAmount.class, false, "If this creature isn't monstrous, put {%2$d:+1/+1 counter} on it and it becomes monstrous."),
MODULAR("Modular", Modular.class, false, "This creature enters the battlefield with {%d:+1/+1 counter} on it. When it dies, you may put its +1/+1 counters on target artifact creature."),
MORPH("Morph", KeywordWithCost.class, false, "You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost."),
MULTIKICKER("Multikicker", KeywordWithCost.class, false, "You may pay an additional %s any number of times as you cast this spell."),
MYRIAD("Myriad", SimpleKeyword.class, false, "Whenever this creature attacks, for each opponent other than defending player, you may create a token that's a copy of this creature that's tapped and attacking that player or a planeswalker they control. Exile the tokens at end of combat."),
NINJUTSU("Ninjutsu", Ninjutsu.class, false, "%s, Return an unblocked attacker you control to hand: Put this card onto the battlefield from your %s tapped and attacking."),
OUTLAST("Outlast", KeywordWithCost.class, false, "%s, {T}: Put a +1/+1 counter on this creature. Outlast only as a sorcery."),
OFFERING("Offering", KeywordWithType.class, false, "You may cast this card any time you could cast an instant by sacrificing a %1$s and paying the difference in mana costs between this and the sacrificed %1$s. Mana cost includes color."),
PARTNER("Partner", Partner.class, true, "You can have two commanders if both have partner."),
PERSIST("Persist", SimpleKeyword.class, false, "When this creature dies, if it had no -1/-1 counters on it, return it to the battlefield under its owner's control with a -1/-1 counter on it."),
PHASING("Phasing", SimpleKeyword.class, true, "This phases in or out before you untap during each of your untap steps. While it's phased out, it's treated as though it doesn't exist."),
POISONOUS("Poisonous", KeywordWithAmount.class, false, "Whenever this creature deals combat damage to a player, that player gets {%d:poison counter}."),
PRESENCE("Presence", KeywordWithType.class, false, "As an additional cost to cast CARDNAME, you may reveal a %s card from your hand."),
PROTECTION("Protection", Protection.class, false, "This creature can't be blocked, targeted, dealt damage, or equipped/enchanted by %s."),
PROVOKE("Provoke", SimpleKeyword.class, false, "Whenever this creature attacks, you may have target creature defending player controls untap and block it if able."),
PROWESS("Prowess", SimpleKeyword.class, false, "Whenever you cast a noncreature spell, this creature gets +1/+1 until end of turn."),
PROWL("Prowl", KeywordWithCost.class, false, "You may pay %s rather than pay this spells mana cost if a player was dealt combat damage this turn by a source that, at the time it dealt that damage, was under your control and had any of this spells creature types."),
RAMPAGE("Rampage", KeywordWithAmount.class, false, "Whenever this creature becomes blocked, it gets +%1$d/+%1$d until end of turn for each creature blocking it beyond the first."),
REACH("Reach", SimpleKeyword.class, true, "This creature can block creatures with flying."),
REBOUND("Rebound", SimpleKeyword.class, true, "If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost."),
RECOVER("Recover", KeywordWithCost.class, false, "When a creature is put into your graveyard from the battlefield, you may pay %s. If you do, return this card from your graveyard to your hand. Otherwise, exile this card."),
REINFORCE("Reinforce", KeywordWithCostAndAmount.class, false, "%s, Discard this card: Put {%d:+1/+1 counter} on target creature."),
RENOWN("Renown", KeywordWithAmount.class, false, "When this creature deals combat damage to a player, if it isn't renowned, put {%d:+1/+1 counter} on it and it becomes renowned."),
REPLICATE("Replicate", KeywordWithCost.class, false, "As an additional cost to cast this spell, you may pay %s any number of times. If you do, copy it that many times. You may choose new targets for the copies."),
RETRACE("Retrace", SimpleKeyword.class, false, "You may cast this card from your graveyard by discarding a land card in addition to paying its other costs."),
RIOT("Riot", SimpleKeyword.class, false, "This creature enters the battlefield with your choice of a +1/+1 counter or haste."),
RIPPLE("Ripple", KeywordWithAmount.class, false, "When you cast this spell, you may reveal the top {%d:card} of your library. You may cast any of those cards with the same name as this spell without paying their mana costs. Put the rest on the bottom of your library in any order."),
SHADOW("Shadow", SimpleKeyword.class, true, "This creature can block or be blocked by only creatures with shadow."),
SHROUD("Shroud", SimpleKeyword.class, true, "This can't be the target of spells or abilities."),
SKULK("Skulk", SimpleKeyword.class, true, "This creature can't be blocked by creatures with greater power."),
SCAVENGE("Scavenge", KeywordWithCost.class, false, "%s, Exile this card from your graveyard: Put a number of +1/+1 counters equal to this card's power on target creature. Scavenge only as a sorcery."),
SOULBOND("Souldbond", SimpleKeyword.class, true, "You may pair this creature with another unpaired creature when either enters the battlefield. They remain paired for as long as you control both of them"),
SOULSHIFT("Soulshift", KeywordWithAmount.class, false, "When this creature dies, you may return target Spirit card with converted mana cost %d or less from your graveyard to your hand."),
SPECTACLE("Spectacle", KeywordWithCost.class, false, "You may cast this spell for its spectacle cost rather than its mana cost if an opponent lost life this turn."),
SPLICE("Splice", KeywordWithCostAndType.class, false, "As you cast an %2$s spell, you may reveal this card from your hand and pay its splice cost. If you do, add this card's effects to that spell."),
SPLIT_SECOND("Split second", SimpleKeyword.class, true, "As long as this spell is on the stack, players can't cast other spells or activate abilities that aren't mana abilities."),
STORM("Storm", SimpleKeyword.class, false, "When you cast this spell, copy it for each other spell that was cast before it this turn. You may choose new targets for the copies."),
STRIVE("Strive", KeywordWithCost.class, false, "CARDNAME costs %s more to cast for each target beyond the first."),
SUNBURST("Sunburst", SimpleKeyword.class, false, "This enters the battlefield with either a +1/+1 or charge counter on it for each color of mana spent to cast it based on whether it's a creature."),
SURGE("Surge", KeywordWithCost.class, false, "You may cast this spell for its surge cost if you or a teammate has cast another spell this turn."),
SUSPEND("Suspend", Suspend.class, false, "Rather than cast this card from your hand, you may pay %s and exile it with {%d:time counter} on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost."),
TOTEM_ARMOR("Totem armor", SimpleKeyword.class, true, "If enchanted permanent would be destroyed, instead remove all damage marked on it and destroy this Aura."),
TRAMPLE("Trample", SimpleKeyword.class, true, "This creature can deal excess combat damage to the player or planeswalker it's attacking."),
TRANSFIGURE("Transfigure", KeywordWithCost.class, false, "%s, Sacrifice this creature: Search your library for a creature card with the same converted mana cost as this creature and put that card onto the battlefield. Then shuffle your library. Transfigure only as a sorcery."),
TRANSMUTE("Transmute", KeywordWithCost.class, false, "%s, Discard this card: Search your library for a card with the same converted mana cost as this card, reveal it, and put it into your hand. Then shuffle your library. Transmute only as a sorcery."),
TRIBUTE("Tribute", KeywordWithAmount.class, false, "As this creature enters the battlefield, an opponent of your choice may put {%d:+1/+1 counter} on it."),
TYPECYCLING("TypeCycling", KeywordWithCostAndType.class, false, "%s, Discard this card: Search your library for a %s card, reveal it, put it into your hand, then shuffle your library."),
UNDAUNTED("Undaunted", SimpleKeyword.class, false, "This spell costs {1} less to cast for each opponent."),
UNDYING("Undying", SimpleKeyword.class, false, "When this creature dies, if it had no +1/+1 counters on it, return it to the battlefield under its owner's control with a +1/+1 counter on it."),
UNEARTH("Unearth", KeywordWithCost.class, false, "%s: Return this card from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step or if it would leave the battlefield. Unearth only as a sorcery."),
UNLEASH("Unleash", SimpleKeyword.class, false, "You may have this creature enter the battlefield with a +1/+1 counter on it. It can't block as long as it has a +1/+1 counter on it."),
VANISHING("Vanishing", KeywordWithAmount.class, false, "This permanent enters the battlefield with {%d:time counter} on it. At the beginning of your upkeep, remove a time counter from it. When the last is removed, sacrifice it."),
VIGILANCE("Vigilance", SimpleKeyword.class, true, "Attacking doesn't cause this creature to tap."),
WITHER("Wither", SimpleKeyword.class, true, "This deals damage to creatures in the form of -1/-1 counters."),
// mayflash additional cast
MAYFLASHCOST(KeywordWithCost.class, false, "You may cast CARDNAME as though it had flash if you pay %s more to cast it."),
MAYFLASHSAC(SimpleKeyword.class, false, "You may cast CARDNAME as though it had flash. If you cast it any time a sorcery couldn't have been cast, the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step."),
MAYFLASHCOST("MayFlashCost", KeywordWithCost.class, false, "You may cast CARDNAME as though it had flash if you pay %s more to cast it."),
MAYFLASHSAC("MayFlashSac", SimpleKeyword.class, false, "You may cast CARDNAME as though it had flash. If you cast it any time a sorcery couldn't have been cast, the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step."),
;
@@ -165,11 +161,11 @@ public enum Keyword {
protected final boolean isMultipleRedundant;
protected final String reminderText, displayName;
Keyword(Class<? extends KeywordInstance<?>> type0, boolean isMultipleRedundant0, String reminderText0) {
Keyword(String displayName0, Class<? extends KeywordInstance<?>> type0, boolean isMultipleRedundant0, String reminderText0) {
type = type0;
isMultipleRedundant = isMultipleRedundant0;
reminderText = reminderText0;
displayName = EnumUtil.getEnumDisplayName(this);
displayName = displayName0;
}
public static KeywordInterface getInstance(String k) {
@@ -205,7 +201,7 @@ public enum Keyword {
if (keyword == Keyword.UNDEFINED) {
//check for special keywords that have a prefix before the keyword enum name
int idx = k.indexOf(' ');
String enumName = k.replace(" ", "_").toUpperCase();
String enumName = k.replace(" ", "_").toUpperCase(Locale.ROOT);
String firstWord = idx == -1 ? enumName : enumName.substring(0, idx);
if (firstWord.endsWith("WALK")) {
keyword = Keyword.LANDWALK;
@@ -214,11 +210,11 @@ public enum Keyword {
else if (idx != -1) {
idx = k.indexOf(' ', idx + 1);
String secondWord = idx == -1 ? enumName.substring(firstWord.length() + 1) : enumName.substring(firstWord.length() + 1, idx);
if (secondWord.equals("OFFERING")) {
if (secondWord.equalsIgnoreCase("OFFERING")) {
keyword = Keyword.OFFERING;
details = firstWord;
}
else if (secondWord.equals("LANDWALK")) {
else if (secondWord.equalsIgnoreCase("LANDWALK")) {
keyword = Keyword.LANDWALK;
details = firstWord;
}
@@ -240,10 +236,6 @@ public enum Keyword {
return displayName;
}
public String getDescription() {
return TextUtil.concatWithSpace(displayName,TextUtil.enclosedParen(reminderText));
}
public static List<Keyword> getAllKeywords() {
Keyword[] values = values();
List<Keyword> keywords = new ArrayList<>();
@@ -287,9 +279,8 @@ public enum Keyword {
}
public static Keyword smartValueOf(String value) {
final String valToCompate = StringUtils.replaceChars(value, " -", "__").toUpperCase();
for (final Keyword v : Keyword.values()) {
if (valToCompate.equals(v.name())) {
if (v.displayName.equalsIgnoreCase(value)) {
return v;
}
}

View File

@@ -910,7 +910,7 @@ public class PhaseHandler implements java.io.Serializable {
}
// fireEvent to update the Details
game.fireEvent(new GameEventPlayerStatsChanged(toUpdate));
game.fireEvent(new GameEventPlayerStatsChanged(toUpdate, false));
return result;
}

View File

@@ -137,6 +137,8 @@ public class Player extends GameEntity implements Comparable<Player> {
private PlayerCollection attackedOpponentsThisTurn = new PlayerCollection();
private final Map<ZoneType, PlayerZone> zones = Maps.newEnumMap(ZoneType.class);
private final Map<Long, Integer> adjustLandPlays = Maps.newHashMap();
private final Set<Long> adjustLandPlaysInfinite = Sets.newHashSet();
private CardCollection currentPlanes = new CardCollection();
private Set<String> prowl = Sets.newHashSet();
@@ -175,6 +177,7 @@ public class Player extends GameEntity implements Comparable<Player> {
view = new PlayerView(id0, game.getTracker());
view.updateMaxHandSize(this);
view.updateKeywords(this);
view.updateMaxLandPlay(this);
setName(chooseName(name0));
if (id0 >= 0) {
game.addPlayer(id, this);
@@ -1030,25 +1033,31 @@ public class Player extends GameEntity implements Comparable<Player> {
// if the key already exists - merge entries
KeywordsChange cks = null;
if (changedKeywords.containsKey(timestamp)) {
if (keywordEffect != null) {
getKeywordCard().removeChangedCardTraits(timestamp);
}
cks = changedKeywords.get(timestamp).merge(addKeywords, removeKeywords, false, false);
} else {
cks = new KeywordsChange(addKeywords, removeKeywords, false, false);
}
cks.addKeywordsToPlayer(this);
if (!cks.getAbilities().isEmpty() || !cks.getTriggers().isEmpty() || !cks.getReplacements().isEmpty() || !cks.getStaticAbilities().isEmpty()) {
getKeywordCard().addChangedCardTraits(cks.getAbilities(), null, cks.getTriggers(), cks.getReplacements(), cks.getStaticAbilities(), false, false, false, timestamp);
}
changedKeywords.put(timestamp, cks);
updateKeywords();
game.fireEvent(new GameEventPlayerStatsChanged(this));
game.fireEvent(new GameEventPlayerStatsChanged(this, true));
}
public final KeywordsChange removeChangedKeywords(final Long timestamp) {
KeywordsChange change = changedKeywords.remove(timestamp);
if (change != null) {
if (keywordEffect != null) {
getKeywordCard().removeChangedCardTraits(timestamp);
}
updateKeywords();
game.fireEvent(new GameEventPlayerStatsChanged(this));
game.fireEvent(new GameEventPlayerStatsChanged(this, true));
}
return change;
}
@@ -1111,7 +1120,7 @@ public class Player extends GameEntity implements Comparable<Player> {
if (keywordRemoved) {
updateKeywords();
game.fireEvent(new GameEventPlayerStatsChanged(this));
game.fireEvent(new GameEventPlayerStatsChanged(this, true));
}
}
@@ -1744,19 +1753,55 @@ public class Player extends GameEntity implements Comparable<Player> {
// **** Check for land play limit per turn ****
// Dev Mode
if (getController().canPlayUnlimitedLands() || hasKeyword("You may play any number of additional lands on each of your turns.")) {
if (getMaxLandPlaysInfinite()) {
return true;
}
// check for adjusted max lands play per turn
return getLandsPlayedThisTurn() < getMaxLandPlays();
}
public final int getMaxLandPlays() {
int adjMax = 1;
for (String keyword : keywords) {
if (keyword.startsWith("AdjustLandPlays")) {
final String[] k = keyword.split(":");
adjMax += Integer.valueOf(k[1]);
for (Integer i : adjustLandPlays.values()) {
adjMax += i;
}
return adjMax;
}
return landsPlayedThisTurn < adjMax;
public final void addMaxLandPlays(long timestamp, int value) {
adjustLandPlays.put(timestamp, value);
getView().updateMaxLandPlay(this);
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
}
public final boolean removeMaxLandPlays(long timestamp) {
boolean changed = adjustLandPlays.remove(timestamp) != null;
if (changed) {
getView().updateMaxLandPlay(this);
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
}
return changed;
}
public final void addMaxLandPlaysInfinite(long timestamp) {
adjustLandPlaysInfinite.add(timestamp);
getView().updateUnlimitedLandPlay(this);
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
}
public final boolean removeMaxLandPlaysInfinite(long timestamp) {
boolean changed = adjustLandPlaysInfinite.remove(timestamp);
if (changed) {
getView().updateUnlimitedLandPlay(this);
getGame().fireEvent(new GameEventPlayerStatsChanged(this, false));
}
return changed;
}
public final boolean getMaxLandPlaysInfinite() {
if (getController().canPlayUnlimitedLands()) {
return true;
}
return !adjustLandPlaysInfinite.isEmpty();
}
public final ManaPool getManaPool() {
@@ -2119,13 +2164,17 @@ public class Player extends GameEntity implements Comparable<Player> {
public final void addLandPlayedThisTurn() {
landsPlayedThisTurn++;
achievementTracker.landsPlayed++;
view.updateNumLandThisTurn(this);
}
public final void resetLandsPlayedThisTurn() {
landsPlayedThisTurn = 0;
view.updateNumLandThisTurn(this);
}
public final void setLandsPlayedThisTurn(int num) {
// This method should only be used directly when setting up the game state.
landsPlayedThisTurn = num;
view.updateNumLandThisTurn(this);
}
public final void setLandsPlayedLastTurn(int num) {
landsPlayedLastTurn = num;

View File

@@ -7,7 +7,6 @@ import forge.game.staticability.StaticAbility;
public class PlayerFactoryUtil {
public static void addStaticAbility(final KeywordInterface inst, final Player player) {
final Card card = player.getKeywordCard();
String keyword = inst.getOriginal();
String effect = null;
if (keyword.startsWith("Hexproof")) {
@@ -29,6 +28,7 @@ public class PlayerFactoryUtil {
+ "| EffectZone$ Command | Description$ Shroud (" + inst.getReminderText() + ")";
}
if (effect != null) {
final Card card = player.getKeywordCard();
StaticAbility st = new StaticAbility(effect, card);
st.setIntrinsic(false);
inst.addStaticAbility(st);

View File

@@ -236,6 +236,31 @@ public class PlayerView extends GameEntityView {
return hasUnlimitedHandSize() ? Localizer.getInstance().getMessage("lblUnlimited") : String.valueOf(getMaxHandSize());
}
public int getMaxLandPlay() {
return get(TrackableProperty.MaxLandPlay);
}
void updateMaxLandPlay(Player p) {
set(TrackableProperty.MaxLandPlay, p.getMaxLandPlays());
}
public boolean hasUnlimitedLandPlay() {
return get(TrackableProperty.HasUnlimitedLandPlay);
}
void updateUnlimitedLandPlay(Player p) {
set(TrackableProperty.HasUnlimitedLandPlay, p.getMaxLandPlaysInfinite());
}
public String getMaxLandString() {
return hasUnlimitedLandPlay() ? "unlimited" : String.valueOf(getMaxLandPlay());
}
public int getNumLandThisTurn() {
return get(TrackableProperty.NumLandThisTurn);
}
void updateNumLandThisTurn(Player p) {
set(TrackableProperty.NumLandThisTurn, p.getLandsPlayedThisTurn());
}
public int getNumDrawnThisTurn() {
return get(TrackableProperty.NumDrawnThisTurn);
}
@@ -449,6 +474,7 @@ public class PlayerView extends GameEntityView {
}
details.add(Localizer.getInstance().getMessage("lblCardInHandHas", String.valueOf(getHandSize()), getMaxHandString()));
details.add(TextUtil.concatNoSpace("lblLandsPlayed", String.valueOf(getNumLandThisTurn()), this.getMaxLandString()));
details.add(Localizer.getInstance().getMessage("lblCardDrawnThisTurnHas", String.valueOf(getNumDrawnThisTurn())));
details.add(Localizer.getInstance().getMessage("lblDamagepreventionHas", String.valueOf(getPreventNextDamage())));

View File

@@ -192,6 +192,10 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone
layers.add(StaticAbilityLayer.RULES);
}
if (hasParam("AdjustLandPlays")) {
layers.add(StaticAbilityLayer.RULES);
}
if (layers.isEmpty()) {
layers.add(StaticAbilityLayer.RULES);
}

View File

@@ -17,10 +17,12 @@
*/
package forge.game.staticability;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.GameCommand;
import forge.card.CardType;
import forge.card.MagicColor;
import forge.game.Game;
import forge.game.GlobalRuleChange;
@@ -117,8 +119,8 @@ public final class StaticAbilityContinuous {
String[] addAbilities = null;
String[] addReplacements = null;
String[] addSVars = null;
String[] addTypes = null;
String[] removeTypes = null;
List<String> addTypes = null;
List<String> removeTypes = null;
String addColors = null;
String[] addTriggers = null;
String[] addStatics = null;
@@ -266,24 +268,44 @@ public final class StaticAbilityContinuous {
}
if (layer == StaticAbilityLayer.TYPE && params.containsKey("AddType")) {
addTypes = params.get("AddType").split(" & ");
if (addTypes[0].equals("ChosenType")) {
final String chosenType = hostCard.getChosenType();
addTypes[0] = chosenType;
} else if (addTypes[0].equals("ImprintedCreatureType")) {
addTypes = Lists.newArrayList(Arrays.asList(params.get("AddType").split(" & ")));
List<String> newTypes = Lists.newArrayList();
Iterables.removeIf(addTypes, new Predicate<String>() {
@Override
public boolean apply(String input) {
if (input.equals("ChosenType") && !hostCard.hasChosenType()) {
return true;
}
if (input.equals("ImprintedCreatureType")) {
if (hostCard.hasImprintedCard()) {
final Set<String> imprinted = hostCard.getImprintedCards().getFirst().getType().getCreatureTypes();
addTypes = imprinted.toArray(new String[imprinted.size()]);
newTypes.addAll(hostCard.getImprintedCards().getLast().getType().getCreatureTypes());
}
return true;
}
if (input.equals("AllBasicLandType")) {
newTypes.addAll(CardType.getBasicTypes());
return true;
}
return false;
}
});
addTypes.addAll(newTypes);
}
if (layer == StaticAbilityLayer.TYPE && params.containsKey("RemoveType")) {
removeTypes = params.get("RemoveType").split(" & ");
if (removeTypes[0].equals("ChosenType")) {
final String chosenType = hostCard.getChosenType();
removeTypes[0] = chosenType;
removeTypes = Lists.newArrayList(Arrays.asList(params.get("RemoveType").split(" & ")));
Iterables.removeIf(removeTypes, new Predicate<String>() {
@Override
public boolean apply(String input) {
if (input.equals("ChosenType") && !hostCard.hasChosenType()) {
return true;
}
return false;
}
});
}
if (layer == StaticAbilityLayer.TYPE) {
@@ -419,6 +441,16 @@ public final class StaticAbilityContinuous {
}
}
if (params.containsKey("AdjustLandPlays")) {
String mhs = params.get("AdjustLandPlays");
if (mhs.equals("Unlimited")) {
p.addMaxLandPlaysInfinite(se.getTimestamp());
} else {
int add = AbilityUtils.calculateAmount(hostCard, mhs, stAb);
p.addMaxLandPlays(se.getTimestamp(), add);
}
}
if (params.containsKey("RaiseMaxHandSize")) {
String rmhs = params.get("RaiseMaxHandSize");
int rmax = AbilityUtils.calculateAmount(hostCard, rmhs, stAb);

View File

@@ -128,6 +128,9 @@ public enum TrackableProperty {
PoisonCounters(TrackableTypes.IntegerType),
MaxHandSize(TrackableTypes.IntegerType),
HasUnlimitedHandSize(TrackableTypes.BooleanType),
MaxLandPlay(TrackableTypes.IntegerType),
HasUnlimitedLandPlay(TrackableTypes.BooleanType),
NumLandThisTurn(TrackableTypes.IntegerType),
NumDrawnThisTurn(TrackableTypes.IntegerType),
Keywords(TrackableTypes.KeywordCollectionViewType, FreezeMode.IgnoresFreeze),
Commander(TrackableTypes.CardViewCollectionType, FreezeMode.IgnoresFreeze),

View File

@@ -3,7 +3,7 @@ ManaCost:1 W B
Types:Legendary Enchantment Creature God
PT:5/4
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to white and black is less than seven, CARDNAME isn't a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to white and black is less than seven, CARDNAME isn't a creature.
SVar:X:Count$DevotionDual.White.Black
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.YouOwn+Other | TriggerZones$ Battlefield | Execute$ TrigReturn | TriggerDescription$ Whenever another creature you own dies, return it to your hand unless target opponent pays 3 life.
SVar:TrigReturn:DB$ Pump | ValidTgts$ Opponent | IsCurse$ True | SubAbility$ DBReturn

View File

@@ -3,7 +3,7 @@ ManaCost:4 W B
Types:Legendary Enchantment Creature God
PT:4/7
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to white and black is less than seven, CARDNAME isn't a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to white and black is less than seven, CARDNAME isn't a creature.
SVar:X:Count$DevotionDual.White.Black
SVar:BuffedBy:Permanent.Black,Permanent.White
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your end step, put a coin counter on another target creature.

View File

@@ -1,7 +1,7 @@
Name:Azusa, Lost but Seeking
ManaCost:2 G
Types:Legendary Creature Human Monk
S:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:2 | Description$ You may play two additional lands on each of your turns.
S:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 2 | Description$ You may play two additional lands on each of your turns.
PT:1/2
SVar:Picture:http://www.wizards.com/global/images/magic/general/azusa_lost_but_seeking.jpg
Oracle:You may play two additional lands on each of your turns.

View File

@@ -2,6 +2,6 @@ Name:Dryad of the Ilysian Grove
ManaCost:2 G
Types:Enchantment Creature Nymph
PT:2/4
S:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:1 | Description$ You may play an additional land on each of your turns.
S:Mode$ Continuous | Affected$ Land.YouCtrl | AddType$ Plains & Island & Swamp & Mountain & Forest | Description$ Lands you control are every basic land type in addition to their other types.
S:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 1 | Description$ You may play an additional land on each of your turns.
S:Mode$ Continuous | Affected$ Land.YouCtrl | AddType$ AllBasicLandType | Description$ Lands you control are every basic land type in addition to their other types.
Oracle:You may play an additional land on each of your turns.\nLands you control are every basic land type in addition to their other types.

View File

@@ -3,7 +3,7 @@ ManaCost:G
Types:Sorcery
A:SP$ Explore | Cost$ G | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | SubAbility$ TrigEffect | SpellDescription$ Target creature you control explores.
SVar:TrigEffect:DB$ Effect | Name$ Explore Effect | StaticAbilities$ Exploration | AILogic$ Always | SpellDescription$ You may play an additional land this turn.
SVar:Exploration:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:1 | EffectZone$ Command | Description$ You may play an additional land this turn.
SVar:Exploration:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 1 | EffectZone$ Command | Description$ You may play an additional land this turn.
SVar:NeedsToPlayVar:ZZ GE1
SVar:ZZ:Count$ValidHand Land.YouOwn
DeckHas:Ability$Counters

View File

@@ -3,7 +3,7 @@ ManaCost:2 W U
Types:Legendary Enchantment Creature God
PT:6/5
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to white and blue is less than seven, CARDNAME isn't a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to white and blue is less than seven, CARDNAME isn't a creature.
SVar:X:Count$DevotionDual.White.Blue
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player | CheckSVar$ Y | Execute$ TrigDraw | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of each upkeep, if you had another creature enter the battlefield under your control last turn, draw a card.
SVar:TrigDraw:DB$ Draw | NumCards$ 1

View File

@@ -3,7 +3,7 @@ ManaCost:3 B
Types:Legendary Enchantment Creature God
PT:5/6
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to black is less than five, CARDNAME is not a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to black is less than five, CARDNAME is not a creature.
SVar:X:Count$Devotion.Black
SVar:BuffedBy:Permanent.Black
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.YouCtrl | TriggerZones$ Battlefield | Execute$ ABDraw | TriggerDescription$ Whenever another creature you control dies, you may pay 2 life. If you do, draw a card.

View File

@@ -3,7 +3,7 @@ ManaCost:3 B
Types:Legendary Enchantment Creature God
PT:5/7
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to black is less than 5, CARDNAME isn't a creature. (Each {B} in the mana costs of permanents you control counts towards your devotion to black.)
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to black is less than 5, CARDNAME isn't a creature. (Each {B} in the mana costs of permanents you control counts towards your devotion to black.)
SVar:X:Count$Devotion.Black
S:Mode$ Continuous | Affected$ Player.Opponent | AddKeyword$ You can't gain life. | Description$ Your opponents can't gain life.
A:AB$ Draw | Cost$ 1 B PayLife<2> | NumCards$ 1 | SpellDescription$ Draw a card.

View File

@@ -5,7 +5,7 @@ A:SP$ Mill | Cost$ 3 R G | Destination$ Exile | NumCards$ 5 | RememberMilled$ Tr
SVar:DBEffect:DB$ Effect | RememberObjects$ RememberedCard | ForgetOnMoved$ Exile | StaticAbilities$ Play | Duration$ UntilTheEndOfYourNextTurn | SubAbility$ DBEffect2
SVar:Play:Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ You may play cards exiled this the end of your next turn.
SVar:DBEffect2:DB$ Effect | Name$ Escape to the Wilds Exploration Effect | StaticAbilities$ Exploration | AILogic$ Always | SubAbility$ DBCleanup
SVar:Exploration:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:1 | EffectZone$ Command | Description$ You may play an additional land this turn.
SVar:Exploration:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 1 | EffectZone$ Command | Description$ You may play an additional land this turn.
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:NeedsToPlayVar:ZZ GE1
SVar:ZZ:Count$ValidHand Land.YouOwn

View File

@@ -1,6 +1,6 @@
Name:Exploration
ManaCost:G
Types:Enchantment
S:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:1 | Description$ You may play an additional land on each of your turns.
S:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 1 | Description$ You may play an additional land on each of your turns.
SVar:Picture:http://www.wizards.com/global/images/magic/general/exploration.jpg
Oracle:You may play an additional land on each of your turns.

View File

@@ -2,7 +2,7 @@ Name:Explore
ManaCost:1 G
Types:Sorcery
A:SP$ Effect | Cost$ 1 G | Name$ Explore Effect | StaticAbilities$ Exploration | AILogic$ Always | SubAbility$ DBDraw | SpellDescription$ You may play an additional land this turn. Draw a card.
SVar:Exploration:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:1 | EffectZone$ Command | Description$ You may play an additional land this turn.
SVar:Exploration:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 1 | EffectZone$ Command | Description$ You may play an additional land this turn.
SVar:NeedsToPlayVar:ZZ GE1
SVar:ZZ:Count$ValidHand Land.YouOwn
SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 1

View File

@@ -1,7 +1,7 @@
Name:Fastbond
ManaCost:G
Types:Enchantment
S:Mode$ Continuous | Affected$ You | AddKeyword$ You may play any number of additional lands on each of your turns. | Description$ You may play any number of lands on each of your turns.
S:Mode$ Continuous | Affected$ You | AdjustLandPlays$ Unlimited | Description$ You may play any number of lands on each of your turns.
T:Mode$ LandPlayed | ValidCard$ Land.YouCtrl | NotFirstLand$ True | Execute$ DBPain | TriggerZones$ Battlefield | TriggerDescription$ Whenever you play a land, if it wasn't the first land you played this turn, CARDNAME deals 1 damage to you.
SVar:DBPain:DB$ DealDamage | NumDmg$ 1 | Defined$ You
SVar:NonStackingEffect:True

View File

@@ -1,7 +1,7 @@
Name:Ghirapur Orrery
ManaCost:4
Types:Artifact
S:Mode$ Continuous | Affected$ Player | AddKeyword$ AdjustLandPlays:1 | Description$ Each player may play an additional land on each of their turns.
S:Mode$ Continuous | Affected$ Player | AdjustLandPlays$ 1 | Description$ Each player may play an additional land on each of their turns.
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player | TriggerZones$ Battlefield | CheckSVar$ TrigCount | SVarCompare$ EQ0 | Execute$ TrigDraw | TriggerDescription$ At the beginning of each player's upkeep, if that player has no cards in hand, that player draws three cards.
SVar:TrigDraw:DB$Draw | NumCards$ 3 | Defined$ TriggeredPlayer
SVar:TrigCount:Count$ValidHand Card.ActivePlayerCtrl

View File

@@ -3,7 +3,7 @@ ManaCost:3 W
Types:Legendary Enchantment Creature God
PT:5/6
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to white is less than 5, CARDNAME isn't a creature. (Each {W} in the mana costs of permanents you control counts towards your devotion to white.)
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to white is less than 5, CARDNAME isn't a creature. (Each {W} in the mana costs of permanents you control counts towards your devotion to white.)
SVar:X:Count$Devotion.White
S:Mode$ Continuous | Affected$ Creature.Other+YouCtrl | AddKeyword$ Vigilance | Description$ Other creatures you control have vigilance.
A:AB$ Token | Cost$ 2 W W | TokenAmount$ 1 | TokenScript$ w_2_1_e_cleric | TokenOwner$ You | LegacyImage$ w 2 1 e cleric ths | SpellDescription$ Create a 2/1 white Cleric enchantment creature token.

View File

@@ -3,7 +3,7 @@ ManaCost:2 W
Types:Legendary Enchantment Creature God
PT:5/5
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to white is less than five, CARDNAME is not a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to white is less than five, CARDNAME is not a creature.
SVar:X:Count$Devotion.White
SVar:BuffedBy:Permanent.White
T:Mode$ LifeGained | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever you gain life, put a +1/+1 counter on target creature or enchantment you control.

View File

@@ -3,7 +3,7 @@ ManaCost:2 R W
Types:Legendary Enchantment Creature God
PT:7/4
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to red and white is less than seven, CARDNAME isn't a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to red and white is less than seven, CARDNAME isn't a creature.
SVar:X:Count$DevotionDual.Red.White
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ Menace | Description$ Creatures you control have menace.
R:Event$ DamageDone | ActiveZones$ Battlefield | Prevent$ True | ValidTarget$ Creature.attacking+YouCtrl | Description$ Prevent all damage that would be dealt to attacking creatures you control.

View File

@@ -5,7 +5,7 @@ K:Entwine:2 G
A:SP$ Charm | Cost$ 2 G | Choices$ DBChangeZone,DBEffect | CharmNum$ 1
SVar:DBChangeZone:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Land.Basic | ChangeNum$ 2 | SpellDescription$ Search your library for up to two basic land cards, reveal them, put them into your hand, then shuffle your library.
SVar:DBEffect:DB$ Effect | Name$ Journey of Discovery Effect | StaticAbilities$ JourneyOfDis | AILogic$ Always | SpellDescription$ You may play up to two additional lands this turn.
SVar:JourneyOfDis:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:2 | EffectZone$ Command | Description$ You may play two additional lands this turn.
SVar:JourneyOfDis:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 2 | EffectZone$ Command | Description$ You may play two additional lands this turn.
AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/journey_of_discovery.jpg
Oracle:Choose one —\n• Search your library for up to two basic land cards, reveal them, put them into your hand, then shuffle your library.\n• You may play up to two additional lands this turn.\nEntwine {2}{G} (Choose both if you pay the entwine cost.)

View File

@@ -3,7 +3,7 @@ ManaCost:3 G W
Types:Legendary Enchantment Creature God
PT:6/7
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to green and white is less than seven, CARDNAME isn't a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to green and white is less than seven, CARDNAME isn't a creature.
SVar:X:Count$DevotionDual.Green.White
T:Mode$ SpellCast | ValidCard$ Creature | ValidActivatingPlayer$ You | Execute$ TrigSearch | TriggerZones$ Battlefield | OptionalDecider$ You | TriggerDescription$ Whenever you cast a creature spell, you may search your library for a Forest or Plains card, put it onto the battlefield tapped, then shuffle your library.
SVar:TrigSearch:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Forest,Plains | ChangeNum$ 1 | Tapped$ True | ShuffleNonMandatory$ True

View File

@@ -3,7 +3,7 @@ ManaCost:3 U R
Types:Legendary Enchantment Creature God
PT:6/5
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to blue and red is less than seven, CARDNAME isn't a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to blue and red is less than seven, CARDNAME isn't a creature.
SVar:X:Count$DevotionDual.Blue.Red
T:Mode$ Drawn | ValidCard$ Card.YouOwn | Number$ 1 | Static$ True | Execute$ DBReveal | TriggerZones$ Battlefield | PlayerTurn$ True | TriggerDescription$ Reveal the first card you draw on each of your turns. Whenever you reveal a land card this way, draw a card. Whenever you reveal a nonland card this way, CARDNAME deals 3 damage to any target.
SVar:DBReveal:DB$ Reveal | Defined$ You | RevealDefined$ TriggeredCard | RememberRevealed$ True | SubAbility$ DBTriggerLand

View File

@@ -5,7 +5,7 @@ Loyalty:2
A:AB$ Pump | Cost$ AddCounter<1/LOYALTY> | ValidTgts$ Permanent.OppCtrl | TgtPrompt$ Select target permanent an opponent controls | Planeswalker$ True | KW$ Prevent all damage that would be dealt to and dealt by CARDNAME. | IsCurse$ True | UntilYourNextTurn$ True | SpellDescription$ Until your next turn, prevent all damage that would be dealt to and dealt by target permanent an opponent controls.
A:AB$ Draw | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | SubAbility$ DBEffect | SpellDescription$ Draw a card. You may play an additional land this turn.
SVar:DBEffect:DB$ Effect | StaticAbilities$ Exploration
SVar:Exploration:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:1 | EffectZone$ Command | Description$ You may play an additional land this turn.
SVar:Exploration:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 1 | EffectZone$ Command | Description$ You may play an additional land this turn.
A:AB$ Effect | Cost$ SubCounter<5/LOYALTY> | Planeswalker$ True | Ultimate$ True | Name$ Emblem - Kiora, the Crashing Wave | Triggers$ EOTTrig | SVars$ KioraToken | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "At the beginning of your end step, create a 9/9 blue Kraken creature token."
SVar:EOTTrig:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Command | Execute$ KioraToken | TriggerDescription$ At the beginning of your end step, create a 9/9 blue Kraken creature token.
SVar:KioraToken:DB$ Token | TokenAmount$ 1 | TokenScript$ u_9_9_kraken | TokenOwner$ You | LegacyImage$ u 9 9 kraken bng

View File

@@ -3,7 +3,7 @@ ManaCost:1 R G
Types:Legendary Enchantment Creature God
PT:4/5
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to red and green is less than seven, CARDNAME isn't a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to red and green is less than seven, CARDNAME isn't a creature.
SVar:X:Count$DevotionDual.Red.Green
T:Mode$ Phase | PreCombatMain$ True | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigChangeZone | TriggerDescription$ At the beginning of your precombat main phase, exile target card from a graveyard. If it was a land card, add {R} or {G}. Otherwise, you gain 2 life and CARDNAME deals 2 damage to each opponent.
SVar:TrigChangeZone:DB$ChangeZone | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Card | TgtPrompt$ Select target card in a graveyard | RememberChanged$ True | SubAbility$ DBMana

View File

@@ -3,7 +3,7 @@ ManaCost:3 G U
Types:Legendary Enchantment Creature God
PT:4/7
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to green and blue is less than seven, CARDNAME isn't a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to green and blue is less than seven, CARDNAME isn't a creature.
SVar:X:Count$DevotionDual.Green.Blue
S:Mode$ Continuous | Affected$ You | SetMaxHandSize$ Unlimited | Description$ You have no maximum hand size.
S:Mode$ Continuous | Affected$ You | AddKeyword$ Convert unused mana to Colorless | Description$ If you would lose unspent mana, that mana becomes colorless instead.

View File

@@ -2,7 +2,7 @@ Name:Mina and Denn, Wildborn
ManaCost: 2 R G
Types:Legendary Creature Elf Ally
PT:4/4
S:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:1 | Description$ You may play an additional land on each of your turns.
S:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 1 | Description$ You may play an additional land on each of your turns.
A:AB$ Pump | Cost$ R G Return<1/Land> | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ Trample | SpellDescription$ Target creature gains trample until end of turn.
SVar:Picture:http://www.wizards.com/global/images/magic/general/mina_and_denn_wildborn.jpg
Oracle:You may play an additional land during each of your turns.\n{R}{G}, Return a land you control to its owner's hand: Target creature gains trample until end of turn.

View File

@@ -3,7 +3,7 @@ ManaCost:2 B R
Types:Legendary Enchantment Creature God
PT:7/5
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to black and red is less than seven, CARDNAME isn't a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to black and red is less than seven, CARDNAME isn't a creature.
SVar:X:Count$DevotionDual.Black.Red
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player.Opponent | Execute$ TrigDmg | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of each opponent's upkeep, CARDNAME deals 2 damage to that player unless they sacrifice a creature.
SVar:TrigDmg:DB$ DealDamage | NumDmg$ 2 | Defined$ TriggeredPlayer | UnlessCost$ Sac<1/Creature> | UnlessAI$ LifeLE2 | UnlessPayer$ TriggeredPlayer

View File

@@ -1,7 +1,7 @@
Name:Naya
ManaCost:no cost
Types:Plane Alara
S:Mode$ Continuous | Affected$ You | EffectZone$ Command | AddKeyword$ You may play any number of additional lands on each of your turns. | Description$ You may play any number of lands on each of your turns.
S:Mode$ Continuous | Affected$ You | EffectZone$ Command | AdjustLandPlays$ Unlimited | Description$ You may play any number of lands on each of your turns.
T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll {CHAOS}, target red, green, or white creature you control gets +1/+1 until end of turn for each land you control.
SVar:RolledChaos:DB$ Pump | ValidTgts$ Creature.Red+YouCtrl,Creature.Green+YouCtrl,Creature.White+YouCtrl | TgtPrompt$ Select target red, green, or white creature you control | NumAtt$ Y | NumDef$ Y | References$ Y
SVar:Y:Count$Valid Land.YouCtrl

View File

@@ -3,7 +3,7 @@ ManaCost:3 G
Types:Legendary Enchantment Creature God
PT:6/6
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to green is less than 5, CARDNAME isn't a creature. (Each {G} in the mana costs of permanents you control counts towards your devotion to green.)
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to green is less than 5, CARDNAME isn't a creature. (Each {G} in the mana costs of permanents you control counts towards your devotion to green.)
SVar:X:Count$Devotion.Green
S:Mode$ Continuous | Affected$ Creature.Other+YouCtrl | AddKeyword$ Trample | Description$ Other creatures you control have trample.
A:AB$ Pump | Cost$ 3 G | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +2 | NumDef$ +2 | SpellDescription$ Target creature gets +2/+2 until end of turn.

View File

@@ -3,7 +3,7 @@ ManaCost:3 G
Types:Legendary Enchantment Creature God
PT:5/6
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to green is less than five, CARDNAME is not a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to green is less than five, CARDNAME is not a creature.
SVar:X:Count$Devotion.Green
SVar:BuffedBy:Permanent.Green
S:Mode$ ReduceCost | ValidCard$ Creature | Type$ Spell | Activator$ You | Amount$ 1 | Description$ Creature spells you cast cost {1} less to cast.

View File

@@ -5,6 +5,5 @@ K:Enchant land
A:SP$ Attach | Cost$ 1 G | ValidTgts$ Land | AILogic$ Pump
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME enters the battlefield, draw a card.
SVar:TrigDraw:DB$ Draw | NumCards$ 1
S:Mode$ Continuous | Affected$ Land.EnchantedBy | AddType$ Plains & Island & Swamp & Mountain & Forest | Description$ Enchanted land is every basic land type in addition to its other types.
SVar:Picture:http://www.wizards.com/global/images/magic/general/nyleas_presence.jpg
S:Mode$ Continuous | Affected$ Land.EnchantedBy | AddType$ AllBasicLandType | Description$ Enchanted land is every basic land type in addition to its other types.
Oracle:Enchant land\nWhen Nylea's Presence enters the battlefield, draw a card.\nEnchanted land is every basic land type in addition to its other types.

View File

@@ -2,7 +2,7 @@ Name:Oracle of Mul Daya
ManaCost:3 G
Types:Creature Elf Shaman
PT:2/2
S:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:1 | Description$ You may play an additional land on each of your turns.
S:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 1 | Description$ You may play an additional land on each of your turns.
S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl | AffectedZone$ Library | MayLookAt$ Player | Description$ Play with the top card of your library revealed.
S:Mode$ Continuous | Affected$ Land.TopLibrary+YouCtrl | AffectedZone$ Library | MayPlay$ True | Description$ You may play the top card of your library if it's a land card.
SVar:Picture:http://www.wizards.com/global/images/magic/general/oracle_of_mul_daya.jpg

View File

@@ -3,7 +3,7 @@ ManaCost:1 B G
Types:Legendary Enchantment Creature God
PT:5/5
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to black and green is less than seven, CARDNAME isn't a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to black and green is less than seven, CARDNAME isn't a creature.
SVar:X:Count$DevotionDual.Black.Green
A:AB$ ChangeZone | Cost$ B G | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Creature | AITgts$ Card.YouOwn | AILogic$ AtOppEOT | AITgtOwnCards$ True | SubAbility$ DBToken | SpellDescription$ Exile target creature card from a graveyard. Its owner creates a 1/1 black and green Snake enchantment creature token with deathtouch.
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ bg_1_1_e_snake_deathtouch | TokenOwner$ TargetedController | LegacyImage$ bg 1 1 e snake deathtouch jou

View File

@@ -3,7 +3,7 @@ ManaCost:3 U B
Types:Legendary Enchantment Creature God
PT:4/7
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to blue and black is less than seven, CARDNAME isn't a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to blue and black is less than seven, CARDNAME isn't a creature.
SVar:X:Count$DevotionDual.Blue.Black
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddAbility$ PhenaxMill | AddSVar$ PhenaxToughness | Description$ Creatures you control have "{T}: Target player puts the top X cards of their library into their graveyard, where X is this creature's toughness."
SVar:PhenaxMill:AB$ Mill | Cost$ T | ValidTgts$ Player | NumCards$ PhenaxToughness | References$ PhenaxToughness | SpellDescription$ Target player puts the top X cards of their library into their graveyard, where X is CARDNAME's toughness.

View File

@@ -1,8 +1,7 @@
Name:Prismatic Omen
ManaCost:1 G
Types:Enchantment
S:Mode$ Continuous | Affected$ Land.YouCtrl | AddType$ Plains & Island & Swamp & Mountain & Forest | Description$ Lands you control are every basic land type in addition to their other types.
S:Mode$ Continuous | Affected$ Land.YouCtrl | AddType$ AllBasicLandType | Description$ Lands you control are every basic land type in addition to their other types.
SVar:NonStackingEffect:True
AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/prismatic_omen.jpg
Oracle:Lands you control are every basic land type in addition to their other types.

View File

@@ -3,7 +3,7 @@ ManaCost:4 R
Types:Legendary Enchantment Creature God
PT:7/6
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to red is less than five, CARDNAME is not a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to red is less than five, CARDNAME is not a creature.
SVar:X:Count$Devotion.Red
SVar:BuffedBy:Permanent.Red
S:Mode$ Continuous | Affected$ Creature.YouCtrl+Other | AddKeyword$ Haste | Description$ Other creatures you control have haste.

View File

@@ -3,7 +3,7 @@ ManaCost:3 R
Types:Legendary Enchantment Creature God
PT:6/5
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to red is less than 5, CARDNAME isn't a creature. (Each {R} in the mana costs of permanents you control counts towards your devotion to red.)
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to red is less than 5, CARDNAME isn't a creature. (Each {R} in the mana costs of permanents you control counts towards your devotion to red.)
SVar:X:Count$Devotion.Red
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Other+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDmg | TriggerDescription$ Whenever another creature enters the battlefield under your control, CARDNAME deals 2 damage to each opponent.
SVar:TrigDmg:DB$ DealDamage | Defined$ Player.Opponent | NumDmg$ 2

View File

@@ -1,7 +1,7 @@
Name:Rites of Flourishing
ManaCost:2 G
Types:Enchantment
S:Mode$ Continuous | Affected$ Player | AddKeyword$ AdjustLandPlays:1 | Description$ Each player may play an additional land on each of their turns.
S:Mode$ Continuous | Affected$ Player | AdjustLandPlays$ 1 | Description$ Each player may play an additional land on each of their turns.
T:Mode$ Phase | Phase$ Draw | ValidPlayer$ Player | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ At the beginning of each player's draw step, that player draws an additional card.
SVar:TrigDraw:DB$Draw | NumCards$ 1 | Defined$ TriggeredPlayer
SVar:Picture:http://www.wizards.com/global/images/magic/general/rites_of_flourishing.jpg

View File

@@ -1,7 +1,7 @@
Name:Storm Cauldron
ManaCost:5
Types:Artifact
S:Mode$ Continuous | Affected$ Player | AddKeyword$ AdjustLandPlays:1 | Description$ Each player may play an additional land during each of their turns.
S:Mode$ Continuous | Affected$ Player | AdjustLandPlays$ 1 | Description$ Each player may play an additional land during each of their turns.
T:Mode$ TapsForMana | ValidCard$ Land | Execute$ TrigBounce | TriggerZones$ Battlefield | TriggerDescription$ Whenever a land is tapped for mana, return it to its owner's hand.
SVar:TrigBounce:DB$ChangeZone | Origin$ Battlefield | Destination$ Hand | Defined$ TriggeredCard
AI:RemoveDeck:Random

View File

@@ -2,7 +2,7 @@ Name:Summer Bloom
ManaCost:1 G
Types:Sorcery
A:SP$ Effect | Cost$ 1 G | Name$ Bloom Effect | StaticAbilities$ BloomingLand | AILogic$ Always | SpellDescription$ You may play up to three additional lands this turn.
SVar:BloomingLand:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:3 | EffectZone$ Command | Description$ You may play up to three additional lands this turn.
SVar:BloomingLand:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 3 | EffectZone$ Command | Description$ You may play up to three additional lands this turn.
SVar:NeedsToPlayVar:LandInHand GE1
SVar:HandInLand:Count$InYourHand.Land
SVar:PlayMain1:TRUE

View File

@@ -3,7 +3,7 @@ ManaCost:3 U
Types:Legendary Enchantment Creature God
PT:6/5
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to blue is less than five, CARDNAME is not a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to blue is less than five, CARDNAME is not a creature.
SVar:X:Count$Devotion.Blue
SVar:BuffedBy:Permanent.Blue
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigExile | TriggerDescription$ At the beginning of your end step, exile up to one other target creature you control, then return that card to the battlefield under your control.

View File

@@ -3,7 +3,7 @@ ManaCost:2 U
Types:Legendary Enchantment Creature God
PT:5/5
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to blue is less than 5, CARDNAME isn't a creature. (Each {U} in the mana costs of permanents you control counts towards your devotion to blue.)
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT5 | References$ X | Description$ As long as your devotion to blue is less than 5, CARDNAME isn't a creature. (Each {U} in the mana costs of permanents you control counts towards your devotion to blue.)
SVar:X:Count$Devotion.Blue
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigScry | TriggerDescription$ At the beginning of your upkeep, scry 1.
SVar:TrigScry:DB$ Scry | ScryNum$ 1

View File

@@ -4,7 +4,7 @@ Types:Legendary Creature Frog Horror
PT:6/6
K:Deathtouch
K:UpkeepCost:Sac<1/Land>
S:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:1 | Description$ You may play an additional land on each of your turns.
S:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 1 | Description$ You may play an additional land on each of your turns.
T:Mode$ ChangesZoneAll | ValidCards$ Land.YouOwn | Origin$ Any | Destination$ Graveyard | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever one or more land cards are put into your graveyard from anywhere, draw a card.
SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1
DeckHas:Ability$Graveyard

View File

@@ -4,6 +4,6 @@ Types:Scheme
T:Mode$ SetInMotion | ValidCard$ Card.Self | Execute$ DBDraw | TriggerZones$ Command | TriggerDescription$ When you set this scheme in motion, draw two cards. You may play an additional land this turn.
SVar:DBDraw:DB$ Draw | NumCards$ 2 | SubAbility$ DBEffect
SVar:DBEffect:DB$ Effect | Name$ This World Belongs to Me Effect | StaticAbilities$ Exploration | AILogic$ Always
SVar:Exploration:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:1 | EffectZone$ Command | Description$ You may play an additional land this turn.
SVar:Exploration:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 1 | EffectZone$ Command | Description$ You may play an additional land this turn.
SVar:Picture:https://downloads.cardforge.org/images/cards/ARC/This World Belongs to Me.full.jpg
Oracle:When you set this scheme in motion, draw two cards. You may play an additional land this turn.

View File

@@ -2,6 +2,6 @@ Name:Titania
ManaCost:no cost
Types:Vanguard
HandLifeModifier:+2/-5
S:Mode$ Continuous | EffectZone$ Command | Affected$ You | AddKeyword$ AdjustLandPlays:1 | Description$ You may play an additional land on each of your turns.
S:Mode$ Continuous | EffectZone$ Command | Affected$ You | AdjustLandPlays$ 1 | Description$ You may play an additional land on each of your turns.
SVar:Picture:https://downloads.cardforge.org/images/cards/VAN/Titania.full.jpg
Oracle:Hand +2, life -5\nYou may play an additional land on each of your turns.

View File

@@ -2,7 +2,7 @@ Name:Urban Evolution
ManaCost:3 G U
Types:Sorcery
A:SP$ Effect | Cost$ 3 G U | Name$ Explore Effect | StaticAbilities$ Exploration | AILogic$ Always | SubAbility$ DBDraw | SpellDescription$ Draw three cards. You may play an additional land this turn.
SVar:Exploration:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:1 | EffectZone$ Command | Description$ You may play an additional land this turn.
SVar:Exploration:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 1 | EffectZone$ Command | Description$ You may play an additional land this turn.
SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 3
SVar:Picture:http://www.wizards.com/global/images/magic/general/urban_evolution.jpg
Oracle:Draw three cards. You may play an additional land this turn.

View File

@@ -3,7 +3,7 @@ ManaCost:2 G
Types:Creature Dinosaur
PT:5/5
K:Ascend
S:Mode$ Continuous | Affected$ You | AddKeyword$ AdjustLandPlays:1 | Description$ You may play an additional land on each of your turns.
S:Mode$ Continuous | Affected$ You | AdjustLandPlays$ 1 | Description$ You may play an additional land on each of your turns.
S:Mode$ Continuous | Affected$ Card.Self | AddHiddenKeyword$ CARDNAME can't attack or block. | CheckSVar$ X | SVarCompare$ EQ0 | References$ X | Description$ CARDNAME can't attack or block unless you have the city's blessing.
SVar:X:Count$Blessing.1.0
SVar:Picture:http://www.wizards.com/global/images/magic/general/wayward_swordtooth.jpg

View File

@@ -3,7 +3,7 @@ ManaCost:3 R G
Types:Legendary Enchantment Creature God
PT:6/5
K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | RemoveCreatureTypes$ True | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to red and green is less than seven, CARDNAME isn't a creature.
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | References$ X | Description$ As long as your devotion to red and green is less than seven, CARDNAME isn't a creature.
SVar:X:Count$DevotionDual.Red.Green
T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of combat on your turn, another target creature you control gains haste and gets +X/+X until end of turn, where X is that creature's power.
SVar:TrigPump:DB$ Pump | ValidTgts$ Creature.Other+YouCtrl | TgtPrompt$ Select another target creature you control | NumAtt$ +Y | NumDef$ +Y | KW$ Haste | References$ Y

View File

@@ -0,0 +1,21 @@
[metadata]
Name:Possibility Storm - Theros Beyond Death #01 (as Player A)
URL:https://i1.wp.com/www.possibilitystorm.com/wp-content/uploads/2020/01/144.-THB1-scaled.jpg
Goal:Win
Turns:1
Difficulty:Rare
Description:Win this turn. Remember that all blocking scenarios must be accounted for. Stonecoil Serpent is owned by you and entered the battlefield for your opponent using Unholy Indenture. 'Blue' was chosen for Diamond Knight. Assume that cards starting in each player's library are not known, and therefore will not be relevant to the puzzle if drawn.
[state]
ailife=11
humanlife=20
turn=1
activeplayer=human
activephase=MAIN1
humanhand=Mystic Sanctuary;Connive // Concoct
humanlibrary=Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt
humangraveyard=Sweet Oblivion;Drown in the Loch;Rankle, Master of Pranks;Pharika's Spawn
humanbattlefield=Ashiok, Sculptor of Fears|Counters:LOYALTY=5;Devourer of Memory;Vantress Gargoyle;Diamond Knight|ChosenColor:blue|NoETBTrigs;Swamp;Swamp;Swamp;Island;Island;Island;Island
aihand=Rise to Glory;Inspiring Unicorn;All That Glitters;Severed Strands
ailibrary=Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt
aigraveyard=Meteor Golem;Gauntlets of Light;Gray Merchant of Asphodel;Unholy Indenture
aibattlefield=Elspeth, Sun's Nemesis|Counters:LOYALTY=2;Stonecoil Serpent|Owner:Human|Counters:P1P1=1;Crashing Drawbridge;Ob Nixilis, the Hate-Twisted|Counters:LOYALTY=4;Nyx Lotus|NoETBTrigs;Plains;Plains;Plains;Swamp;Swamp;Swamp

View File

@@ -0,0 +1,21 @@
[metadata]
Name:Possibility Storm - Theros Beyond Death #01 (as Player B)
URL:https://i1.wp.com/www.possibilitystorm.com/wp-content/uploads/2020/01/144.-THB1-scaled.jpg
Goal:Win
Turns:1
Difficulty:Rare
Description:Win this turn. Remember that all blocking scenarios must be accounted for. Stonecoil Serpent is owned by your opponent and entered the battlefield for you using Unholy Indenture. 'Blue' was chosen for Diamond Knight. Assume that cards starting in each player's library are not known, and therefore will not be relevant to the puzzle if drawn.
[state]
humanlife=11
ailife=20
turn=1
activeplayer=human
activephase=MAIN1
humanhand=Rise to Glory;Inspiring Unicorn;All That Glitters;Severed Strands
humanlibrary=Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt
humangraveyard=Meteor Golem;Gauntlets of Light;Gray Merchant of Asphodel;Unholy Indenture
humanbattlefield=Elspeth, Sun's Nemesis|Counters:LOYALTY=2;Stonecoil Serpent|Owner:AI|Counters:P1P1=1;Crashing Drawbridge;Ob Nixilis, the Hate-Twisted|Counters:LOYALTY=4;Nyx Lotus|NoETBTrigs;Plains;Plains;Plains;Swamp;Swamp;Swamp
aihand=Mystic Sanctuary;Connive // Concoct
ailibrary=Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt
aigraveyard=Sweet Oblivion;Drown in the Loch;Rankle, Master of Pranks;Pharika's Spawn
aibattlefield=Ashiok, Sculptor of Fears|Counters:LOYALTY=5;Devourer of Memory;Vantress Gargoyle;Diamond Knight|ChosenColor:blue|NoETBTrigs;Swamp;Swamp;Swamp;Island;Island;Island;Island

View File

@@ -18,7 +18,7 @@ Image=elspeth_undaunted_hero.jpg
2 Elspeth's Devotee|THB
1 Elspeth, Undaunted Hero+|THB
2 Hero of the Winds|THB
3 Indomitable Will|CHK
3 Indomitable Will|THB
3 Karametra's Blessing|THB
4 Leonin of the Lost Pride|THB
2 Phalanx Tactics|THB

View File

@@ -377,13 +377,20 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
public Void visit(final GameEventPlayerStatsChanged event) {
final CardCollection cards = new CardCollection();
for (final Player p : event.players) {
if (event.updateCards) {
cards.addAll(p.getAllCards());
}
processPlayer(p, livesUpdate);
}
return processCards(cards, cardsRefreshDetails);
}
public Void visit(final GameEventLandPlayed event) {
processPlayer(event.player, livesUpdate);
return processCard(event.land, cardsRefreshDetails);
}
@Override
public Void visit(final GameEventTokenStateUpdate event) {
processCards(event.cards, cardsRefreshDetails);

View File

@@ -30,6 +30,7 @@ import forge.game.combat.CombatUtil;
import forge.game.cost.Cost;
import forge.game.cost.CostPart;
import forge.game.cost.CostPartMana;
import forge.game.event.GameEventPlayerStatsChanged;
import forge.game.keyword.Keyword;
import forge.game.keyword.KeywordInterface;
import forge.game.mana.Mana;
@@ -1993,6 +1994,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override
public void setCanPlayUnlimitedLands(final boolean canPlayUnlimitedLands0) {
canPlayUnlimitedLands = canPlayUnlimitedLands0;
getGame().fireEvent(new GameEventPlayerStatsChanged(player, false));
}
/*