diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index b4b3293d108..cbbc8867b77 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -1986,6 +1986,35 @@ public class AiController { return MyRandom.getRandom().nextBoolean(); } + public boolean chooseEvenOdd(SpellAbility sa) { + String aiLogic = sa.getParamOrDefault("AILogic", ""); + + if (aiLogic.equals("AlwaysEven")) { + return false; // false is Even + } else if (aiLogic.equals("AlwaysOdd")) { + return true; // true is Odd + } else if (aiLogic.equals("Random")) { + return MyRandom.getRandom().nextBoolean(); + } else if (aiLogic.equals("CMCInHand")) { + CardCollectionView hand = sa.getActivatingPlayer().getCardsIn(ZoneType.Hand); + int numEven = CardLists.filter(hand, CardPredicates.evenCMC()).size(); + int numOdd = CardLists.filter(hand, CardPredicates.oddCMC()).size(); + return numOdd > numEven; + } else if (aiLogic.equals("CMCOppControls")) { + CardCollectionView hand = sa.getActivatingPlayer().getOpponents().getCardsIn(ZoneType.Battlefield); + int numEven = CardLists.filter(hand, CardPredicates.evenCMC()).size(); + int numOdd = CardLists.filter(hand, CardPredicates.oddCMC()).size(); + return numOdd > numEven; + } else if (aiLogic.equals("CMCOppControlsByPower")) { + // TODO: improve this to check for how dangerous those creatures actually are relative to host card + CardCollectionView hand = sa.getActivatingPlayer().getOpponents().getCardsIn(ZoneType.Battlefield); + int powerEven = Aggregates.sum(CardLists.filter(hand, CardPredicates.evenCMC()), Accessors.fnGetNetPower); + int powerOdd = Aggregates.sum(CardLists.filter(hand, CardPredicates.oddCMC()), Accessors.fnGetNetPower); + return powerOdd > powerEven; + } + return MyRandom.getRandom().nextBoolean(); // outside of any specific logic, choose randomly + } + public Card chooseCardToHiddenOriginChangeZone(ZoneType destination, List origin, SpellAbility sa, CardCollection fetchList, Player player2, Player decider) { if (useSimulation) { diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index 497cb7a0b43..9fe6d72ace7 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -755,6 +755,7 @@ public class PlayerControllerAi extends PlayerController { return defaultVal != null && defaultVal.booleanValue(); case UntapTimeVault: return false; // TODO Should AI skip his turn for time vault? case LeftOrRight: return brains.chooseDirection(sa); + case OddsOrEvens: return brains.chooseEvenOdd(sa); // false is Odd, true is Even default: return MyRandom.getRandom().nextBoolean(); } diff --git a/forge-ai/src/main/java/forge/ai/SpellApiToAi.java b/forge-ai/src/main/java/forge/ai/SpellApiToAi.java index d204f5bcbb1..ff719f144b3 100644 --- a/forge-ai/src/main/java/forge/ai/SpellApiToAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellApiToAi.java @@ -42,6 +42,7 @@ public enum SpellApiToAi { .put(ApiType.ChooseCard, ChooseCardAi.class) .put(ApiType.ChooseColor, ChooseColorAi.class) .put(ApiType.ChooseDirection, ChooseDirectionAi.class) + .put(ApiType.ChooseEvenOdd, ChooseEvenOddAi.class) .put(ApiType.ChooseNumber, ChooseNumberAi.class) .put(ApiType.ChoosePlayer, ChoosePlayerAi.class) .put(ApiType.ChooseSource, ChooseSourceAi.class) diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseEvenOddAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseEvenOddAi.java new file mode 100644 index 00000000000..e5ac8a99d6d --- /dev/null +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseEvenOddAi.java @@ -0,0 +1,36 @@ +package forge.ai.ability; + +import forge.ai.SpellAbilityAi; +import forge.game.player.Player; +import forge.game.spellability.SpellAbility; +import forge.game.spellability.TargetRestrictions; +import forge.util.MyRandom; + +public class ChooseEvenOddAi extends SpellAbilityAi { + + @Override + protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) { + if (!sa.hasParam("AILogic")) { + return false; + } + TargetRestrictions tgt = sa.getTargetRestrictions(); + if (tgt != null) { + sa.resetTargets(); + Player opp = aiPlayer.getWeakestOpponent(); + if (sa.canTarget(opp)) { + sa.getTargets().add(opp); + } else { + return false; + } + } + boolean chance = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn()); + return chance; + } + + @Override + protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) { + return mandatory || canPlayAI(ai, sa); + } + +} + diff --git a/forge-game/src/main/java/forge/game/EvenOdd.java b/forge-game/src/main/java/forge/game/EvenOdd.java new file mode 100644 index 00000000000..89f759d0109 --- /dev/null +++ b/forge-game/src/main/java/forge/game/EvenOdd.java @@ -0,0 +1,6 @@ +package forge.game; + +public enum EvenOdd { + Even, + Odd +} diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index e3bba438b9d..018172dbf0c 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -204,6 +204,17 @@ public class AbilityUtils { cards.add((Card) o); } } + } else if (defined.equals("DelayTriggerRememberedLKI")) { + SpellAbility trigSa = sa.getTriggeringAbility(); + if (trigSa != null) { + for (Object o : trigSa.getTriggerRemembered()) { + if (o instanceof Card) { + cards.add((Card)o); + } + } + } else { + System.err.println("Warning: couldn't find trigger SA in the chain of SpellAbility " + sa); + } } else if (defined.equals("DelayTriggerRemembered")) { SpellAbility trigSa = sa.getTriggeringAbility(); if (trigSa != null) { diff --git a/forge-game/src/main/java/forge/game/ability/ApiType.java b/forge-game/src/main/java/forge/game/ability/ApiType.java index e058a41c2c0..c7fa2c0915f 100644 --- a/forge-game/src/main/java/forge/game/ability/ApiType.java +++ b/forge-game/src/main/java/forge/game/ability/ApiType.java @@ -40,6 +40,7 @@ public enum ApiType { ChooseCard (ChooseCardEffect.class), ChooseColor (ChooseColorEffect.class), ChooseDirection (ChooseDirectionEffect.class), + ChooseEvenOdd (ChooseEvenOddEffect.class), ChooseNumber (ChooseNumberEffect.class), ChoosePlayer (ChoosePlayerEffect.class), ChooseSource (ChooseSourceEffect.class), diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChooseEvenOddEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChooseEvenOddEffect.java new file mode 100644 index 00000000000..6d7388ddfd4 --- /dev/null +++ b/forge-game/src/main/java/forge/game/ability/effects/ChooseEvenOddEffect.java @@ -0,0 +1,43 @@ +package forge.game.ability.effects; + +import forge.game.EvenOdd; +import forge.game.ability.SpellAbilityEffect; +import forge.game.card.Card; +import forge.game.player.Player; +import forge.game.player.PlayerController.BinaryChoiceType; +import forge.game.spellability.SpellAbility; +import forge.util.Localizer; + +public class ChooseEvenOddEffect extends SpellAbilityEffect { + + /* (non-Javadoc) + * @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility) + */ + @Override + protected String getStackDescription(SpellAbility sa) { + final StringBuilder sb = new StringBuilder(); + + for (final Player p : getTargetPlayers(sa)) { + sb.append(p).append(" "); + } + sb.append("chooses even or odd."); + + return sb.toString(); + } + + @Override + public void resolve(SpellAbility sa) { + final Card card = sa.getHostCard(); + + for (final Player p : getTargetPlayers(sa)) { + if ((!sa.usesTargeting()) || p.canBeTargetedBy(sa)) { + EvenOdd chosen = p.getController().chooseBinary(sa, "odd or even", BinaryChoiceType.OddsOrEvens) ? EvenOdd.Odd : EvenOdd.Even; + card.setChosenEvenOdd(chosen); + if (sa.hasParam("Notify")) { + p.getGame().getAction().nofityOfValue(sa, card, Localizer.getInstance().getMessage("lblPlayerPickedChosen", p.getName(), chosen), p); + } + } + } + card.updateStateForView(); + } +} \ No newline at end of file diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index d16459266bb..e4b9a06bb40 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -238,6 +238,7 @@ public class Card extends GameEntity implements Comparable { private String chosenName = ""; private Integer chosenNumber; private Player chosenPlayer; + private EvenOdd chosenEvenOdd = null; private Direction chosenDirection = null; private String chosenMode = ""; @@ -1597,6 +1598,19 @@ public class Card extends GameEntity implements Comparable { view.updateNamedCard(this); } + public boolean hasChosenEvenOdd() { + return chosenEvenOdd != null; + } + + public EvenOdd getChosenEvenOdd() { + return chosenEvenOdd; + } + public void setChosenEvenOdd(EvenOdd chosenEvenOdd0) { + if (chosenEvenOdd == chosenEvenOdd0) { return; } + chosenEvenOdd = chosenEvenOdd0; + view.updateChosenEvenOdd(this); + } + // used for cards like Meddling Mage... public final String getNamedCard() { return getChosenName(); diff --git a/forge-game/src/main/java/forge/game/card/CardPredicates.java b/forge-game/src/main/java/forge/game/card/CardPredicates.java index 4f4d00b2010..3994c04e3e7 100644 --- a/forge-game/src/main/java/forge/game/card/CardPredicates.java +++ b/forge-game/src/main/java/forge/game/card/CardPredicates.java @@ -299,6 +299,24 @@ public final class CardPredicates { }; } + public static final Predicate evenCMC() { + return new Predicate() { + @Override + public boolean apply(final Card c) { + return c.getCMC() % 2 == 0; + } + }; + } + + public static final Predicate oddCMC() { + return new Predicate() { + @Override + public boolean apply(final Card c) { + return c.getCMC() % 2 == 1; + } + }; + } + public static final Predicate hasCounters() { return new Predicate() { @Override diff --git a/forge-game/src/main/java/forge/game/card/CardProperty.java b/forge-game/src/main/java/forge/game/card/CardProperty.java index b67cd9771f6..4940533f5fe 100644 --- a/forge-game/src/main/java/forge/game/card/CardProperty.java +++ b/forge-game/src/main/java/forge/game/card/CardProperty.java @@ -4,6 +4,7 @@ import com.google.common.collect.Iterables; import forge.card.ColorSet; import forge.card.MagicColor; import forge.game.Direction; +import forge.game.EvenOdd; import forge.game.Game; import forge.game.GameEntity; import forge.game.GameObject; @@ -1372,6 +1373,27 @@ public class CardProperty { if (card.getNetPower() >= card.getNetToughness()) { return false; } + } else if (property.equals("cmcEven")) { + if (card.getCMC() % 2 != 0) { + return false; + } + } else if (property.equals("cmcOdd")) { + if (card.getCMC() % 2 != 1) { + return false; + } + } else if (property.equals("cmcChosenEvenOdd")) { + if (!source.hasChosenEvenOdd()) { + return false; + } + if ((card.getCMC() % 2 == 0) != (source.getChosenEvenOdd() == EvenOdd.Even)) { + return false; + } + } else if (property.equals("cmcNotChosenEvenOdd")) { + if (source.hasChosenEvenOdd()) { + if ((card.getCMC() % 2 == 0) == (source.getChosenEvenOdd() == EvenOdd.Even)) { + return false; + } + } } else if (property.startsWith("power") || property.startsWith("toughness") || property.startsWith("cmc") || property.startsWith("totalPT")) { int x; diff --git a/forge-game/src/main/java/forge/game/card/CardView.java b/forge-game/src/main/java/forge/game/card/CardView.java index 40933837039..4d7dee6b3a1 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -8,6 +8,7 @@ import forge.ImageKeys; import forge.card.*; import forge.card.mana.ManaCost; import forge.game.Direction; +import forge.game.EvenOdd; import forge.game.GameEntityView; import forge.game.GameType; import forge.game.combat.Combat; @@ -304,6 +305,12 @@ public class CardView extends GameEntityView { void updateChosenDirection(Card c) { set(TrackableProperty.ChosenDirection, c.getChosenDirection()); } + public EvenOdd getChosenEvenOdd() { + return get(TrackableProperty.ChosenEvenOdd); + } + void updateChosenEvenOdd(Card c) { + set(TrackableProperty.ChosenEvenOdd, c.getChosenEvenOdd()); + } public String getChosenMode() { return get(TrackableProperty.ChosenMode); @@ -627,6 +634,13 @@ public class CardView extends GameEntityView { sb.append("]\r\n"); } + EvenOdd chosenEvenOdd = getChosenEvenOdd(); + if (chosenEvenOdd != null) { + sb.append("\r\n[Chosen value: "); + sb.append(chosenEvenOdd); + sb.append("]\r\n"); + } + CardView pairedWith = getPairedWith(); if (pairedWith != null) { sb.append("\r\n \r\nPaired With: ").append(pairedWith); diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java index f6d8a9b6984..457f3c3cf8e 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -220,6 +220,9 @@ public final class StaticAbilityContinuous { if (!hostCard.hasChosenName() && input.contains("ChosenName")) { return true; } + if (!hostCard.hasChosenEvenOdd() && (input.contains("ChosenEvenOdd") || input.contains("chosenEvenOdd"))) { + return true; + } // two variants for Red vs. red in keyword if (input.contains("ColorsYouCtrl") || input.contains("colorsYouCtrl")) { @@ -261,6 +264,10 @@ public final class StaticAbilityContinuous { final String chosenName = hostCard.getChosenName().replace(",", ";"); input = input.replaceAll("ChosenName", "Card.named" + chosenName); } + if (hostCard.hasChosenEvenOdd()) { + input = input.replaceAll("ChosenEvenOdd", hostCard.getChosenEvenOdd().toString()); + input = input.replaceAll("chosenEvenOdd", hostCard.getChosenEvenOdd().toString().toLowerCase()); + } input = input.replace("HostCardUID", hostCardUID); return input; } diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityETBTapped.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityETBTapped.java index 43dd0cb64df..589053aee89 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityETBTapped.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityETBTapped.java @@ -17,9 +17,9 @@ */ package forge.game.staticability; +import forge.game.CardTraitBase; import forge.game.card.Card; -import java.util.Map; /** * The Class StaticAbility_CantBeCast. @@ -36,11 +36,15 @@ public class StaticAbilityETBTapped { * @return true, if successful */ public static boolean applyETBTappedAbility(final StaticAbility stAb, final Card card) { - final Map params = stAb.getMapParams(); final Card hostCard = stAb.getHostCard(); - return !params.containsKey("ValidCard") - || card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard, null); + if (stAb.hasParam("ValidCard")) { + if (!CardTraitBase.matchesValid(card, stAb.getParam("ValidCard").split(","), hostCard)) { + return false; + } + } + + return true; } } diff --git a/forge-game/src/main/java/forge/trackable/TrackableProperty.java b/forge-game/src/main/java/forge/trackable/TrackableProperty.java index ac3f6a17347..9c543d55a19 100644 --- a/forge-game/src/main/java/forge/trackable/TrackableProperty.java +++ b/forge-game/src/main/java/forge/trackable/TrackableProperty.java @@ -1,7 +1,9 @@ package forge.trackable; + import forge.card.CardRarity; import forge.game.Direction; +import forge.game.EvenOdd; import forge.game.GameType; import forge.game.phase.PhaseType; import forge.game.zone.ZoneType; @@ -46,6 +48,7 @@ public enum TrackableProperty { ChosenCards(TrackableTypes.CardViewCollectionType), ChosenPlayer(TrackableTypes.PlayerViewType), ChosenDirection(TrackableTypes.EnumType(Direction.class)), + ChosenEvenOdd(TrackableTypes.EnumType(EvenOdd.class)), ChosenMode(TrackableTypes.StringType), Remembered(TrackableTypes.StringType), NamedCard(TrackableTypes.StringType), diff --git a/forge-gui/res/cardsfolder/a/ashlings_prerogative.txt b/forge-gui/res/cardsfolder/a/ashlings_prerogative.txt index acc6955dbd7..1f518377d6b 100644 --- a/forge-gui/res/cardsfolder/a/ashlings_prerogative.txt +++ b/forge-gui/res/cardsfolder/a/ashlings_prerogative.txt @@ -1,15 +1,10 @@ Name:Ashling's Prerogative ManaCost:1 R Types:Enchantment -K:ETBReplacement:Other:ChooseMode -SVar:ChooseMode:DB$ ChooseNumber | Defined$ You | Min$ 0 | Max$ 1 | ListTitle$ Choose ODD or EVEN (0=Even; 1=Odd) | SpellDescription$ As CARDNAME enters the battlefield, choose odd or even. (Zero is even.) -S:Mode$ Continuous | Affected$ Creature.cmcM2X | AddKeyword$ Haste | Description$ Each creature with converted mana cost of the chosen value has haste. -S:Mode$ ETBTapped | ValidCard$ Creature.cmcM2Y | Description$ Each creature without converted mana cost of the chosen value enters the battlefield tapped. -# The next 2 static abilities add text to the card panel for convenience indicating choice. -S:Mode$ Continuous | Affected$ Card.Self | AddHiddenKeyword$ Chosen:EVEN | CheckSVar$ X | SVarCompare$ EQ0 -S:Mode$ Continuous | Affected$ Card.Self | AddHiddenKeyword$ Chosen:ODD | CheckSVar$ X | SVarCompare$ EQ1 -SVar:X:Count$ChosenNumber -SVar:Y:Number$ChosenNumber/Plus.1 +K:ETBReplacement:Other:ChooseEvenOdd +SVar:ChooseEvenOdd:DB$ ChooseEvenOdd | Defined$ You | ListTitle$ Choose ODD or EVEN | AILogic$ CMCInHand | SpellDescription$ As CARDNAME enters the battlefield, choose odd or even. (Zero is even.) +S:Mode$ Continuous | Affected$ Creature.cmcChosenEvenOdd | AddKeyword$ Haste | Description$ Each creature with converted mana cost of the chosen value has haste. +S:Mode$ ETBTapped | ValidCard$ Creature.cmcNotChosenEvenOdd | Description$ Each creature without converted mana cost of the chosen value enters the battlefield tapped. AI:RemoveDeck:All SVar:Picture:http://www.wizards.com/global/images/magic/general/ashlings_prerogative.jpg Oracle:As Ashling's Prerogative enters the battlefield, choose odd or even. (Zero is even.)\nEach creature with converted mana cost of the chosen value has haste.\nEach creature without converted mana cost of the chosen value enters the battlefield tapped. diff --git a/forge-gui/res/cardsfolder/e/extinction_event.txt b/forge-gui/res/cardsfolder/e/extinction_event.txt index 64b009483b4..3f9ed6d3385 100755 --- a/forge-gui/res/cardsfolder/e/extinction_event.txt +++ b/forge-gui/res/cardsfolder/e/extinction_event.txt @@ -2,8 +2,6 @@ Name:Extinction Event ManaCost:3 B Types:Sorcery A:SP$ GenericChoice | Cost$ 3 B | Choices$ Odd,Even | Defined$ You | StackDescription$ SpellDescription | SpellDescription$ Choose odd or even. Exile each creature with converted mana cost of the chosen value. (Zero is even.) -SVar:Odd:DB$ ChangeZoneAll | ChangeType$ Creature.cmcM2Y | References$ Y | Origin$ Battlefield | Destination$ Exile | SpellDescription$ Odd -SVar:Even:DB$ ChangeZoneAll | ChangeType$ Creature.cmcM2X | References$ X | Origin$ Battlefield | Destination$ Exile | SpellDescription$ Even -SVar:X:Count$0 -SVar:Y:Count$1 +SVar:Odd:DB$ ChangeZoneAll | ChangeType$ Creature.cmcOdd | Origin$ Battlefield | Destination$ Exile | SpellDescription$ Odd +SVar:Even:DB$ ChangeZoneAll | ChangeType$ Creature.cmcEven | Origin$ Battlefield | Destination$ Exile | SpellDescription$ Even Oracle:Choose odd or even. Exile each creature with converted mana cost of the chosen value. (Zero is even.) diff --git a/forge-gui/res/cardsfolder/f/foe_razer_regent.txt b/forge-gui/res/cardsfolder/f/foe_razer_regent.txt index b145fb85135..4b343ed3092 100644 --- a/forge-gui/res/cardsfolder/f/foe_razer_regent.txt +++ b/forge-gui/res/cardsfolder/f/foe_razer_regent.txt @@ -6,8 +6,8 @@ K:Flying T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigFight | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may have it fight target creature you don't control. SVar:TrigFight:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Choose target creature you don't control T:Mode$ Fight | ValidCard$ Creature.YouCtrl | TriggerZones$ Battlefield | Execute$ DelTrigPutCounter | TriggerDescription$ Whenever a creature you control fights, put two +1/+1 counters on it at the beginning of the next end step. -SVar:DelTrigPutCounter:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigPutCounter | RememberObjects$ TriggeredFighter | TriggerDescription$ Put two +1/+1 counters on it at the beginning of the next end step. -SVar:TrigPutCounter:DB$ PutCounter | Defined$ DelayTriggerRemembered | CounterType$ P1P1 | CounterNum$ 2 +SVar:DelTrigPutCounter:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigPutCounter | RememberObjects$ TriggeredFighterLKICopy | TriggerDescription$ Put two +1/+1 counters on it at the beginning of the next end step. +SVar:TrigPutCounter:DB$ PutCounter | Defined$ DelayTriggerRememberedLKI | CounterType$ P1P1 | CounterNum$ 2 DeckHas:Ability$Counters SVar:Picture:http://www.wizards.com/global/images/magic/general/foe_razer_regent.jpg Oracle:Flying\nWhen Foe-Razer Regent enters the battlefield, you may have it fight target creature you don't control.\nWhenever a creature you control fights, put two +1/+1 counters on it at the beginning of the next end step. diff --git a/forge-gui/res/cardsfolder/h/haktos_the_unscarred.txt b/forge-gui/res/cardsfolder/h/haktos_the_unscarred.txt index a287e3381e4..2158b338716 100644 --- a/forge-gui/res/cardsfolder/h/haktos_the_unscarred.txt +++ b/forge-gui/res/cardsfolder/h/haktos_the_unscarred.txt @@ -5,5 +5,5 @@ PT:6/1 K:CARDNAME attacks each combat if able. K:ETBReplacement:Other:ChooseNum SVar:ChooseNum:DB$ ChooseNumber | Min$ 2 | Max$ 4 | Defined$ You | Random$ True | SpellDescription$ As Haktos enters the battlefield, choose 2, 3, or 4 at random. -S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection:Card.cmcNEChosenNumber:Protection from each converted mana cost other than ChosenNumber | Description$ CARDNAME has protection from each converted mana cost other than the chosen number. +S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection:Card.cmcNEChosenNumber,Emblem:Protection from each converted mana cost other than ChosenNumber | Description$ CARDNAME has protection from each converted mana cost other than the chosen number. Oracle:Haktos the Unscarred attacks each combat if able.\nAs Haktos enters the battlefield, choose 2, 3, or 4 at random.\nHaktos has protection from each converted mana cost other than the chosen number. diff --git a/forge-gui/res/cardsfolder/l/lavabrink_venturer.txt b/forge-gui/res/cardsfolder/l/lavabrink_venturer.txt new file mode 100644 index 00000000000..f9c7be9f5de --- /dev/null +++ b/forge-gui/res/cardsfolder/l/lavabrink_venturer.txt @@ -0,0 +1,8 @@ +Name:Lavabrink Venturer +ManaCost:2 W +Types:Creature Human Soldier +PT:3/3 +K:ETBReplacement:Other:ChooseEvenOdd +SVar:ChooseEvenOdd:DB$ ChooseEvenOdd | Defined$ You | AILogic$ CMCOppControlsByPower | SpellDescription$ As CARDNAME enters the battlefield, choose odd or even. (Zero is even.) +S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection:Card.cmcChosenEvenOdd,Emblem.cmcChosenEvenOdd:Protection from each converted mana cost of chosenEvenOdd. | Description$ CARDNAME has protection from each converted mana cost of the chosen value. +Oracle:As Lavabrink Venturer enters the battlefield, choose odd or even. (Zero is even.)\nLavabrink Venturer has protection from each converted mana cost of the chosen value. diff --git a/forge-gui/res/cardsfolder/p/protean_hydra.txt b/forge-gui/res/cardsfolder/p/protean_hydra.txt index 324446f554b..6706bcc64eb 100644 --- a/forge-gui/res/cardsfolder/p/protean_hydra.txt +++ b/forge-gui/res/cardsfolder/p/protean_hydra.txt @@ -8,7 +8,7 @@ R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Card.Self | Replac SVar:Counters:DB$ RemoveCounter | Defined$ ReplacedTarget | CounterType$ P1P1 | CounterNum$ Y | References$ Y SVar:Y:ReplaceCount$DamageAmount T:Mode$ CounterRemoved | ValidCard$ Card.Self | TriggerZones$ Battlefield | CounterType$ P1P1 | Execute$ ProteanPutCounter | TriggerDescription$ Whenever a +1/+1 counter is removed from CARDNAME, put two +1/+1 counters on it at the beginning of the next end step. -SVar:ProteanPutCounter:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ DBPutCounters | TriggerDescription$ Put two +1/+1 counters on it at the beginning of the next end step. -SVar:DBPutCounters:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 +SVar:ProteanPutCounter:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ DBPutCounters | RememberObjects$ TriggeredCardLKICopy | TriggerDescription$ Put two +1/+1 counters on it at the beginning of the next end step. +SVar:DBPutCounters:DB$ PutCounter | Defined$ DelayTriggerRememberedLKI | CounterType$ P1P1 | CounterNum$ 2 SVar:Picture:http://www.wizards.com/global/images/magic/general/protean_hydra.jpg Oracle:Protean Hydra enters the battlefield with X +1/+1 counters on it.\nIf damage would be dealt to Protean Hydra, prevent that damage and remove that many +1/+1 counters from it.\nWhenever a +1/+1 counter is removed from Protean Hydra, put two +1/+1 counters on it at the beginning of the next end step. diff --git a/forge-gui/res/cardsfolder/s/simic_ascendancy.txt b/forge-gui/res/cardsfolder/s/simic_ascendancy.txt index 087d3fcee62..4e908a80aba 100644 --- a/forge-gui/res/cardsfolder/s/simic_ascendancy.txt +++ b/forge-gui/res/cardsfolder/s/simic_ascendancy.txt @@ -2,10 +2,10 @@ Name:Simic Ascendancy ManaCost:G U Types:Enchantment A:AB$ PutCounter | Cost$ 1 G U | CounterType$ P1P1 | CounterNum$ 1 | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | SpellDescription$ Put a +1/+1 counter on target creature you control. -T:Mode$ CounterAddedOnce | ValidCard$ Creature.YouCtrl | TriggerZones$ Battlefield | CounterType$ P1P1 | Execute$ TrigPutCounter | TriggerDescription$ Whenever one or more +1/+1 counters are put on a creature you control, put that many growth counters on CARDNAME. +T:Mode$ CounterAddedOnce | ValidCard$ Creature.YouCtrl+inZoneBattlefield | TriggerZones$ Battlefield | CounterType$ P1P1 | Execute$ TrigPutCounter | TriggerDescription$ Whenever one or more +1/+1 counters are put on a creature you control, put that many growth counters on CARDNAME. SVar:TrigPutCounter:DB$ PutCounter | CounterType$ GROWTH | CounterNum$ X | References$ X T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | IsPresent$ Card.Self+counters_GE20_GROWTH | Execute$ TrigWinGame | TriggerDescription$ At the beginning of your upkeep, if CARDNAME has twenty or more growth counters on it, you win the game. -SVar:TrigWinGame:DB$WinsGame | Defined$ You +SVar:TrigWinGame:DB$ WinsGame | Defined$ You SVar:X:TriggerCount$Amount DeckHints:Ability$Counters DeckHas:Ability$Counters diff --git a/forge-gui/res/cardsfolder/v/void_winnower.txt b/forge-gui/res/cardsfolder/v/void_winnower.txt index abeefa44e58..1973ad26816 100644 --- a/forge-gui/res/cardsfolder/v/void_winnower.txt +++ b/forge-gui/res/cardsfolder/v/void_winnower.txt @@ -2,9 +2,8 @@ Name:Void Winnower ManaCost:9 Types:Creature Eldrazi PT:11/9 -S:Mode$ CantBeCast | ValidCard$ Card.cmcM2X | Caster$ Opponent | Description$ Your opponents can't cast spells with even converted mana costs. (Zero is even.) -S:Mode$ Continuous | Affected$ Creature.OppCtrl+cmcM2X | AddHiddenKeyword$ CARDNAME can't block. | Description$ Your opponents can't block with creatures with even converted mana costs. -SVar:X:Count$0 +S:Mode$ CantBeCast | ValidCard$ Card.cmcEven | Caster$ Opponent | Description$ Your opponents can't cast spells with even converted mana costs. (Zero is even.) +S:Mode$ Continuous | Affected$ Creature.OppCtrl+cmcEven | AddHiddenKeyword$ CARDNAME can't block. | Description$ Your opponents can't block with creatures with even converted mana costs. SVar:PlayMain1:TRUE SVar:Picture:http://www.wizards.com/global/images/magic/general/void_winnower.jpg Oracle:Your opponents can't cast spells with even converted mana costs. (Zero is even.)\nYour opponents can't block with creatures with even converted mana costs. diff --git a/forge-gui/res/cardsfolder/y/yennett_cryptic_sovereign.txt b/forge-gui/res/cardsfolder/y/yennett_cryptic_sovereign.txt index 6a94848f570..425e948d922 100644 --- a/forge-gui/res/cardsfolder/y/yennett_cryptic_sovereign.txt +++ b/forge-gui/res/cardsfolder/y/yennett_cryptic_sovereign.txt @@ -7,8 +7,7 @@ K:Vigilance K:Menace T:Mode$ Attacks | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigReveal | TriggerDescription$ Whenever CARDNAME attacks, reveal the top card of your library. If that card's converted mana cost is odd, you may cast it without paying its mana cost. Otherwise, draw a card. SVar:TrigReveal:DB$ PeekAndReveal | PeekAmount$ 1 | RevealValid$ Card | RememberRevealed$ True | SubAbility$ DBMayCast -SVar:DBMayCast:DB$ Play | Defined$ Remembered | ForgetRemembered$ True | WithoutManaCost$ True | Optional$ True | ConditionDefined$ Remembered | ConditionCheckSVar$ X | ConditionSVarCompare$ M21 | References$ X | SubAbility$ DBDraw +SVar:DBMayCast:DB$ Play | Defined$ Remembered | ForgetRemembered$ True | WithoutManaCost$ True | Optional$ True | ConditionDefined$ Remembered | ConditionPresent$ Card.cmcOdd | SubAbility$ DBDraw SVar:DBDraw:DB$ Draw | ConditionDefined$ Remembered | ConditionPresent$ Card | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:X:Remembered$CardManaCost Oracle:Flying,vigilance,menace\nWhenever Yennett, Cryptic Sovereign attacks, reveal the top card of your library. If that card's converted mana cost is odd, you may cast it without paying its mana cost. Otherwise, draw a card.