From e75c97f5f762b50d11eb504d362376758f05666c Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 26 Apr 2023 19:58:55 +0200 Subject: [PATCH 1/7] Clean up --- forge-game/src/main/java/forge/game/GameAction.java | 2 ++ forge-gui/res/cardsfolder/g/gyruda_doom_of_depths.txt | 2 +- forge-gui/res/cardsfolder/r/riveteers_charm.txt | 4 +--- forge-gui/res/cardsfolder/s/soul_shatter.txt | 4 +--- forge-gui/res/cardsfolder/upcoming/wrenn_and_realmbreaker.txt | 2 +- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index f89eaca73d2..c61f79c7a92 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -1448,7 +1448,9 @@ public class GameAction { if (game.getCombat() != null) { game.getCombat().removeAbsentCombatants(); } + table.triggerChangesZoneAll(game, null); + if (!checkAgain) { break; // do not continue the loop } diff --git a/forge-gui/res/cardsfolder/g/gyruda_doom_of_depths.txt b/forge-gui/res/cardsfolder/g/gyruda_doom_of_depths.txt index 0127b1ee69a..1af3e1a24ae 100644 --- a/forge-gui/res/cardsfolder/g/gyruda_doom_of_depths.txt +++ b/forge-gui/res/cardsfolder/g/gyruda_doom_of_depths.txt @@ -3,7 +3,7 @@ ManaCost:4 U/B U/B Types:Legendary Creature Demon Kraken PT:6/6 K:Companion:Card.cmcM20:Your starting deck contains only cards with even mana value. (If this card is your chosen companion, you may cast it once from outside the game.) -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigMill | TriggerDescription$ When CARDNAME enters the battlefield, each player mills four cards. Put a creature card with an even mana value from those cards onto the battlefield under your control. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigMill | TriggerDescription$ When NICKNAME enters the battlefield, each player mills four cards. Put a creature card with an even mana value from those cards onto the battlefield under your control. SVar:TrigMill:DB$ Mill | NumCards$ 4 | Defined$ Player | RememberMilled$ True | SubAbility$ DBChangeZone SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard,Exile | Destination$ Battlefield | GainControl$ True | Mandatory$ True | Hidden$ True | ChangeNum$ 1 | ChangeType$ Card.Creature+IsRemembered+cmcM20 | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True diff --git a/forge-gui/res/cardsfolder/r/riveteers_charm.txt b/forge-gui/res/cardsfolder/r/riveteers_charm.txt index acf6407ea9f..9a96e14f36e 100644 --- a/forge-gui/res/cardsfolder/r/riveteers_charm.txt +++ b/forge-gui/res/cardsfolder/r/riveteers_charm.txt @@ -3,9 +3,7 @@ ManaCost:B R G Types:Instant A:SP$ Charm | Choices$ DBSac,DBExilePlay,DBExileGrave SVar:DBSac:DB$ Sacrifice | ValidTgts$ Opponent | TgtPrompt$ Choose target opponent | SacValid$ Creature.cmcEQX,Planeswalker.cmcEQX | SacMessage$ creature or planeswalker they control with the highest mana value among creatures and planeswalkers they control | SpellDescription$ Target opponent sacrifices a creature or planeswalker they control with the highest mana value among creatures and planeswalkers they control. -SVar:X:SVar$Y/LimitMin.Z -SVar:Y:Count$Valid Creature.TargetedPlayerCtrl$GreatestCMC -SVar:Z:Count$Valid Planeswalker.TargetedPlayerCtrl$GreatestCMC +SVar:X:Count$Valid Creature.TargetedPlayerCtrl,Planeswalker.TargetedPlayerCtrl$GreatestCMC SVar:DBExilePlay:DB$ Dig | Defined$ You | DigNum$ 3 | ChangeNum$ All | DestinationZone$ Exile | RememberChanged$ True | SubAbility$ DBEffect | SpellDescription$ Exile the top three cards of your library. Until your next end step, you may play those cards. SVar:DBEffect:DB$ Effect | RememberObjects$ RememberedCard | StaticAbilities$ STPlay | SubAbility$ DBCleanup | ForgetOnMoved$ Exile | Duration$ UntilYourNextEndStep SVar:STPlay:Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ Until your next end step, you may play those cards. diff --git a/forge-gui/res/cardsfolder/s/soul_shatter.txt b/forge-gui/res/cardsfolder/s/soul_shatter.txt index 8da5ad65b14..3e620e83a71 100644 --- a/forge-gui/res/cardsfolder/s/soul_shatter.txt +++ b/forge-gui/res/cardsfolder/s/soul_shatter.txt @@ -5,7 +5,5 @@ A:SP$ RepeatEach | RepeatPlayers$ Player.Opponent | RepeatSubAbility$ DBChoose | SVar:DBChoose:DB$ ChooseCard | Defined$ Player.IsRemembered | Choices$ Creature.RememberedPlayerCtrl+cmcEQX,Planeswalker.RememberedPlayerCtrl+cmcEQX | ChoiceTitle$ Choose a creature or planeswalker with the highest mana value to sacrifice | Mandatory$ True | RememberChosen$ True SVar:DBSac:DB$ SacrificeAll | ValidCards$ Card.IsRemembered | SubAbility$ DBCleanup | StackDescription$ sacrifices a creature or planeswalker with the highest mana value among creatures and planeswalkers they control. SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:X:SVar$Y/LimitMin.Z -SVar:Y:Count$Valid Creature.RememberedPlayerCtrl$GreatestCMC -SVar:Z:Count$Valid Planeswalker.RememberedPlayerCtrl$GreatestCMC +SVar:X:Count$Valid Creature.RememberedPlayerCtrl,Planeswalker.RememberedPlayerCtrl$GreatestCMC Oracle:Each opponent sacrifices a creature or planeswalker with the highest mana value among creatures and planeswalkers they control. diff --git a/forge-gui/res/cardsfolder/upcoming/wrenn_and_realmbreaker.txt b/forge-gui/res/cardsfolder/upcoming/wrenn_and_realmbreaker.txt index 6e84ff800d9..5f7c07fc0bb 100644 --- a/forge-gui/res/cardsfolder/upcoming/wrenn_and_realmbreaker.txt +++ b/forge-gui/res/cardsfolder/upcoming/wrenn_and_realmbreaker.txt @@ -6,7 +6,7 @@ S:Mode$ Continuous | Affected$ Land.YouCtrl | AddAbility$ AnyMana | Description$ SVar:AnyMana:AB$ Mana | Cost$ T | Produced$ Any | Amount$ 1 | SpellDescription$ Add one mana of any color. A:AB$ Animate | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Land.YouCtrl | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select up to one target land you control | Power$ 3 | Toughness$ 3 | Types$ Creature,Elemental | Keywords$ Vigilance & Hexproof & Haste | Duration$ UntilYourNextTurn | SpellDescription$ Up to one target land you control becomes a 3/3 Elemental creature with vigilance, hexproof, and haste until your next turn. It's still a land. A:AB$ Mill | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | NumCards$ 3 | RememberMilled$ True | SubAbility$ DBChangeZone | SpellDescription$ Mill three cards. You may put a permanent card from among the milled cards into your hand. -SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | Hidden$ True | ChangeNum$ 1 | ChangeType$ Card.Permanent+IsRemembered | SubAbility$ DBCleanup +SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard,Exile | Destination$ Hand | Hidden$ True | ChangeNum$ 1 | ChangeType$ Card.Permanent+IsRemembered | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True A:AB$ Effect | Cost$ SubCounter<7/LOYALTY> | Planeswalker$ True | Ultimate$ True | Name$ Emblem - Wrenn and Realmbreaker | Image$ emblem_wrenn_and_realmbreaker | StaticAbilities$ PermanentRecycle | Stackable$ False | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "You may play lands and cast permanent spells from your graveyard." SVar:PermanentRecycle:Mode$ Continuous | EffectZone$ Command | Affected$ Card.Permanent+YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands and cast permanent spells from your graveyard. From e907d2e17bf0c0aab6590c04a578af720b4a5b82 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 26 Apr 2023 19:59:30 +0200 Subject: [PATCH 2/7] Fix Omnath --- .../ability/effects/ManaReflectedEffect.java | 20 ++++++++++++++++++- .../upcoming/omnath_locus_of_all.txt | 6 +++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/effects/ManaReflectedEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ManaReflectedEffect.java index 349a94a8d7a..caf78c90520 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ManaReflectedEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ManaReflectedEffect.java @@ -1,6 +1,7 @@ package forge.game.ability.effects; import java.util.Collection; +import java.util.Map; import org.apache.commons.lang3.StringUtils; @@ -54,6 +55,24 @@ public class ManaReflectedEffect extends SpellAbilityEffect { private static String generatedReflectedMana(final SpellAbility sa, final Collection colors, final Player player) { // Calculate generated mana here for stack description and resolving final int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("Amount"), sa) : 1; + final StringBuilder sb = new StringBuilder(); + + if (sa.getManaPart().isComboMana()) { + Map choices = player.getController().specifyManaCombo(sa, ColorSet.fromNames(colors), amount, false); + for (Map.Entry e : choices.entrySet()) { + Byte chosenColor = e.getKey(); + String choice = MagicColor.toShortString(chosenColor); + Integer count = e.getValue(); + while (count > 0) { + if (sb.length() > 0) { + sb.append(" "); + } + sb.append(choice); + --count; + } + } + return sb.toString(); + } String baseMana; @@ -93,7 +112,6 @@ public class ManaReflectedEffect extends SpellAbilityEffect { } } - final StringBuilder sb = new StringBuilder(); if (amount == 0) { sb.append("0"); } else { diff --git a/forge-gui/res/cardsfolder/upcoming/omnath_locus_of_all.txt b/forge-gui/res/cardsfolder/upcoming/omnath_locus_of_all.txt index 94cb5bd75a4..17e388fda54 100644 --- a/forge-gui/res/cardsfolder/upcoming/omnath_locus_of_all.txt +++ b/forge-gui/res/cardsfolder/upcoming/omnath_locus_of_all.txt @@ -4,11 +4,11 @@ Types:Legendary Creature Phyrexian Elemental PT:4/4 R:Event$ LoseMana | ValidPlayer$ You | ReplacementResult$ Replaced | ReplaceWith$ ConvertMana | ActiveZones$ Battlefield | Description$ If you would lose unspent mana, that mana becomes black instead. SVar:ConvertMana:DB$ ReplaceMana | ReplaceType$ Black -T:Mode$ Phase | ValidPlayer$ You | Phase$ Main1 | TriggerZones$ Battlefield | Execute$ TrigPeek | TriggerDescription$ At the beginning of your precombat main phase, look at the top card of your library. You may reveal that card if it has three or more colored mana symbols in its mana cost. If you do, add three mana in any combination of colors and put it into your hand. If you don't reveal it, put it into your hand. +T:Mode$ Phase | ValidPlayer$ You | Phase$ Main1 | TriggerZones$ Battlefield | Execute$ TrigPeek | TriggerDescription$ At the beginning of your precombat main phase, look at the top card of your library. You may reveal that card if it has three or more colored mana symbols in its mana cost. If you do, add three mana in any combination of its colors and put it into your hand. If you don't reveal it, put it into your hand. SVar:TrigPeek:DB$ PeekAndReveal | Defined$ You | NoReveal$ True | RememberPeeked$ True | SubAbility$ DBReveal SVar:DBReveal:DB$ PeekAndReveal | Defined$ You | NoPeek$ True | RevealOptional$ True | ImprintRevealed$ True | ConditionCheckSVar$ ColorAmount | ConditionSVarCompare$ GE3 | SubAbility$ DBMana -SVar:DBMana:DB$ Mana | Produced$ Combo Any | Amount$ 3 | ConditionDefined$ Imprinted | ConditionPresent$ Card | SubAbility$ DBMove +SVar:DBMana:DB$ ManaReflected | Produced$ Combo | ReflectProperty$ Is | ColorOrType$ Color | Amount$ 3 | Valid$ Defined.Imprinted | ConditionDefined$ Imprinted | ConditionPresent$ Card | SubAbility$ DBMove SVar:DBMove:DB$ ChangeZone | Origin$ Library | Destination$ Hand | Defined$ Remembered | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True SVar:ColorAmount:Remembered$ChromaSource -Oracle:If you would lose unspent mana, that mana becomes black instead.\nAt the beginning of your precombat main phase, look at the top card of your library. You may reveal that card if it has three or more colored mana symbols in its mana cost. If you do, add three mana in any combination of colors and put it into your hand. If you don't reveal it, put it into your hand. +Oracle:If you would lose unspent mana, that mana becomes black instead.\nAt the beginning of your precombat main phase, look at the top card of your library. You may reveal that card if it has three or more colored mana symbols in its mana cost. If you do, add three mana in any combination of its colors and put it into your hand. If you don't reveal it, put it into your hand. From 49bf19948efbfd2442c456f6d89c812186f71a44 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 26 Apr 2023 20:03:12 +0200 Subject: [PATCH 3/7] Fix treating Battle as PW --- .../src/main/java/forge/ai/AiAttackController.java | 5 +++++ .../main/java/forge/ai/ability/ChoosePlayerAi.java | 9 ++++++++- forge-game/src/main/java/forge/game/card/Card.java | 2 +- .../src/main/java/forge/game/card/CardFactory.java | 9 +++++++++ .../main/java/forge/game/card/CardFactoryUtil.java | 11 +---------- .../src/main/java/forge/game/combat/Combat.java | 8 +++++++- 6 files changed, 31 insertions(+), 13 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiAttackController.java b/forge-ai/src/main/java/forge/ai/AiAttackController.java index 2857e710e9c..cfd651b39e2 100644 --- a/forge-ai/src/main/java/forge/ai/AiAttackController.java +++ b/forge-ai/src/main/java/forge/ai/AiAttackController.java @@ -722,6 +722,11 @@ public class AiAttackController { return pwNearUlti != null ? pwNearUlti : ComputerUtilCard.getBestPlaneswalkerAI(pwDefending); } + List battleDefending = c.getDefendingBattles(); + if (!battleDefending.isEmpty()) { + // TODO filter for team ones + } + return prefDefender; } diff --git a/forge-ai/src/main/java/forge/ai/ability/ChoosePlayerAi.java b/forge-ai/src/main/java/forge/ai/ability/ChoosePlayerAi.java index 2b5c6af415a..d31fa1ab303 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChoosePlayerAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChoosePlayerAi.java @@ -1,14 +1,18 @@ package forge.ai.ability; +import java.util.Collections; import java.util.List; import java.util.Map; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import forge.ai.AiAttackController; import forge.ai.ComputerUtil; import forge.ai.SpellAbilityAi; import forge.game.player.Player; +import forge.game.player.PlayerCollection; +import forge.game.player.PlayerPredicates; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; @@ -31,7 +35,10 @@ public class ChoosePlayerAi extends SpellAbilityAi { @Override public Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable choices, Map params) { Player chosen = null; - if ("Curse".equals(sa.getParam("AILogic"))) { + if (sa.hasParam("Protect")) { + chosen = new PlayerCollection(choices).min(PlayerPredicates.compareByLife()); + } + else if ("Curse".equals(sa.getParam("AILogic"))) { for (Player pc : choices) { if (pc.isOpponentOf(ai)) { chosen = pc; 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 8a0dccdd1a4..32edbb36d72 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -3160,7 +3160,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { // no Ability for this type yet, make a new one if (sa == null) { - sa = CardFactoryUtil.buildBasicLandAbility(state, c); + sa = CardFactory.buildBasicLandAbility(state, c); basicLandAbilities[i] = sa; } diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java index e4c43590940..618b9eb1bdc 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -380,6 +380,15 @@ public class CardFactory { } } + public static SpellAbility buildBasicLandAbility(final CardState state, byte color) { + String strcolor = MagicColor.toShortString(color); + String abString = "AB$ Mana | Cost$ T | Produced$ " + strcolor + + " | Secondary$ True | SpellDescription$ Add {" + strcolor + "}."; + SpellAbility sa = AbilityFactory.getAbility(abString, state); + sa.setIntrinsic(true); // always intrisic + return sa; + } + private static Card readCard(final CardRules rules, final IPaperCard paperCard, int cardId, Game game) { final Card card = new Card(cardId, paperCard, game); diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 2c6744f7231..0b3863f44c6 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -89,15 +89,6 @@ import io.sentry.Sentry; */ public class CardFactoryUtil { - public static SpellAbility buildBasicLandAbility(final CardState state, byte color) { - String strcolor = MagicColor.toShortString(color); - String abString = "AB$ Mana | Cost$ T | Produced$ " + strcolor + - " | Secondary$ True | SpellDescription$ Add {" + strcolor + "}."; - SpellAbility sa = AbilityFactory.getAbility(abString, state); - sa.setIntrinsic(true); // always intrisic - return sa; - } - /** *

* abilityMorphDown. @@ -3932,7 +3923,7 @@ public class CardFactoryUtil { StringBuilder chooseSB = new StringBuilder(); chooseSB.append("Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplacementResult$ Updated"); chooseSB.append(" | Description$ (As a Siege enters the battlefield, choose an opponent to protect it. You and others can attack it. When it's defeated, exile it, then cast it transformed.)"); - String chooseProtector = "DB$ ChoosePlayer | Defined$ You | Choices$ Opponent | Protect$ True | ChoiceTitle$ Choose an opponent to protect this battle | AILogic$ Curse"; + String chooseProtector = "DB$ ChoosePlayer | Defined$ You | Choices$ Opponent | Protect$ True | ChoiceTitle$ Choose an opponent to protect this battle"; ReplacementEffect re = ReplacementHandler.parseReplacement(chooseSB.toString(), card, true); re.setOverridingAbility(AbilityFactory.getAbility(chooseProtector, card)); diff --git a/forge-game/src/main/java/forge/game/combat/Combat.java b/forge-game/src/main/java/forge/game/combat/Combat.java index 2aa45f163e9..9f706fac6ec 100644 --- a/forge-game/src/main/java/forge/game/combat/Combat.java +++ b/forge-game/src/main/java/forge/game/combat/Combat.java @@ -47,6 +47,8 @@ import forge.game.card.Card; import forge.game.card.CardCollection; import forge.game.card.CardCollectionView; import forge.game.card.CardDamageMap; +import forge.game.card.CardLists; +import forge.game.card.CardPredicates; import forge.game.card.CardUtil; import forge.game.keyword.Keyword; import forge.game.player.Player; @@ -231,7 +233,11 @@ public class Combat { } public final CardCollection getDefendingPlaneswalkers() { - return new CardCollection(Iterables.filter(attackableEntries, Card.class)); + return CardLists.filter(Iterables.filter(attackableEntries, Card.class), CardPredicates.isType("Planeswalker")); + } + + public final CardCollection getDefendingBattles() { + return CardLists.filter(Iterables.filter(attackableEntries, Card.class), CardPredicates.isType("Battle")); } public final Map getAttackersAndDefenders() { From 19510914b4b5d8cad5a716f45cf60faf4d615792 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 26 Apr 2023 20:21:01 +0200 Subject: [PATCH 4/7] Fix ClassCastException when adding attacker --- .../src/main/java/forge/ai/ComputerUtilCombat.java | 11 ++++++++--- forge-ai/src/main/java/forge/ai/SpellAbilityAi.java | 12 ++++++------ .../src/main/java/forge/ai/ability/ChangeZoneAi.java | 4 ++-- .../main/java/forge/ai/ability/ChoosePlayerAi.java | 2 -- .../main/java/forge/ai/ability/CopyPermanentAi.java | 4 ++-- forge-ai/src/main/java/forge/ai/ability/DigAi.java | 4 ++-- forge-ai/src/main/java/forge/ai/ability/TokenAi.java | 4 ++-- .../src/main/java/forge/game/combat/Combat.java | 10 +++++----- 8 files changed, 27 insertions(+), 24 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java index a8008e8a5a5..60b7908160b 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java @@ -2478,10 +2478,15 @@ public class ComputerUtilCombat { public static GameEntity addAttackerToCombat(SpellAbility sa, Card attacker, Iterable defenders) { Combat combat = sa.getHostCard().getGame().getCombat(); if (combat != null) { - // 1. If the card that spawned the attacker was sent at a planeswalker, attack the same. Consider improving. GameEntity def = combat.getDefenderByAttacker(sa.getHostCard()); - if (def instanceof Card && ((Card)def).isPlaneswalker() && Iterables.contains(defenders, def)) { - return def; + // 1. If the card that spawned the attacker was sent at a card, attack the same. Consider improving. + if (def instanceof Card && Iterables.contains(defenders, def)) { + if (((Card)def).isPlaneswalker()) { + return def; + } + if (((Card)def).isBattle()) { + return def; + } } // 2. Otherwise, go through the list of options one by one, choose the first one that can't be blocked profitably. for (GameEntity p : defenders) { diff --git a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java index 671c9867b9b..285c07aca49 100644 --- a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java @@ -314,21 +314,21 @@ public abstract class SpellAbilityAi { public T chooseSingleEntity(Player ai, SpellAbility sa, Collection options, boolean isOptional, Player targetedPlayer, Map params) { boolean hasPlayer = false; boolean hasCard = false; - boolean hasPlaneswalker = false; + boolean hasAttackableCard = false; for (T ent : options) { if (ent instanceof Player) { hasPlayer = true; } else if (ent instanceof Card) { hasCard = true; - if (((Card)ent).isPlaneswalker()) { - hasPlaneswalker = true; + if (((Card)ent).isPlaneswalker() || ((Card)ent).isBattle()) { + hasAttackableCard = true; } } } - if (hasPlayer && hasPlaneswalker) { - return (T) chooseSinglePlayerOrPlaneswalker(ai, sa, (Collection) options, params); + if (hasPlayer && hasAttackableCard) { + return (T) chooseSingleAttackableEntity(ai, sa, (Collection) options, params); } else if (hasCard) { return (T) chooseSingleCard(ai, sa, (Collection) options, isOptional, targetedPlayer, params); } else if (hasPlayer) { @@ -353,7 +353,7 @@ public abstract class SpellAbilityAi { return Iterables.getFirst(options, null); } - protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable options, Map params) { + protected GameEntity chooseSingleAttackableEntity(Player ai, SpellAbility sa, Iterable options, Map params) { System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSinglePlayerOrPlaneswalker is used for " + this.getClass().getName() + ". Consider declaring an overloaded method"); return Iterables.getFirst(options, null); } diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java index bf263a06eed..d0a945d43a2 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java @@ -1760,12 +1760,12 @@ public class ChangeZoneAi extends SpellAbilityAi { } @Override - protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable options, Map params) { + protected GameEntity chooseSingleAttackableEntity(Player ai, SpellAbility sa, Iterable options, Map params) { if (params != null && params.containsKey("Attacker")) { return ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), options); } // should not be reached - return super.chooseSinglePlayerOrPlaneswalker(ai, sa, options, params); + return super.chooseSingleAttackableEntity(ai, sa, options, params); } private boolean doSacAndReturnFromGraveLogic(final Player ai, final SpellAbility sa) { diff --git a/forge-ai/src/main/java/forge/ai/ability/ChoosePlayerAi.java b/forge-ai/src/main/java/forge/ai/ability/ChoosePlayerAi.java index d31fa1ab303..d2e1aed14a1 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChoosePlayerAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChoosePlayerAi.java @@ -1,13 +1,11 @@ package forge.ai.ability; -import java.util.Collections; import java.util.List; import java.util.Map; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import forge.ai.AiAttackController; import forge.ai.ComputerUtil; import forge.ai.SpellAbilityAi; import forge.game.player.Player; diff --git a/forge-ai/src/main/java/forge/ai/ability/CopyPermanentAi.java b/forge-ai/src/main/java/forge/ai/ability/CopyPermanentAi.java index 53fe0518bcf..e17c9926259 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CopyPermanentAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CopyPermanentAi.java @@ -261,12 +261,12 @@ public class CopyPermanentAi extends SpellAbilityAi { } @Override - protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable options, Map params) { + protected GameEntity chooseSingleAttackableEntity(Player ai, SpellAbility sa, Iterable options, Map params) { if (params != null && params.containsKey("Attacker")) { return ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), options); } // should not be reached - return super.chooseSinglePlayerOrPlaneswalker(ai, sa, options, params); + return super.chooseSingleAttackableEntity(ai, sa, options, params); } } diff --git a/forge-ai/src/main/java/forge/ai/ability/DigAi.java b/forge-ai/src/main/java/forge/ai/ability/DigAi.java index cfd4214d834..c8e8e2b8c76 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DigAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DigAi.java @@ -196,12 +196,12 @@ public class DigAi extends SpellAbilityAi { } @Override - protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable options, Map params) { + protected GameEntity chooseSingleAttackableEntity(Player ai, SpellAbility sa, Iterable options, Map params) { if (params != null && params.containsKey("Attacker")) { return ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), options); } // should not be reached - return super.chooseSinglePlayerOrPlaneswalker(ai, sa, options, params); + return super.chooseSingleAttackableEntity(ai, sa, options, params); } /* (non-Javadoc) diff --git a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java index 023ad61cbf6..839d6fbbf00 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java @@ -326,12 +326,12 @@ public class TokenAi extends SpellAbilityAi { * @see forge.card.ability.SpellAbilityAi#chooseSinglePlayerOrPlaneswalker(forge.game.player.Player, forge.card.spellability.SpellAbility, Iterable options) */ @Override - protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable options, Map params) { + protected GameEntity chooseSingleAttackableEntity(Player ai, SpellAbility sa, Iterable options, Map params) { if (params != null && params.containsKey("Attacker")) { return ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), options); } // should not be reached - return super.chooseSinglePlayerOrPlaneswalker(ai, sa, options, params); + return super.chooseSingleAttackableEntity(ai, sa, options, params); } /** diff --git a/forge-game/src/main/java/forge/game/combat/Combat.java b/forge-game/src/main/java/forge/game/combat/Combat.java index 9f706fac6ec..851303f937d 100644 --- a/forge-game/src/main/java/forge/game/combat/Combat.java +++ b/forge-game/src/main/java/forge/game/combat/Combat.java @@ -625,17 +625,17 @@ public class Combat { } } - for (Card pw : getDefendingPlaneswalkers()) { - if (pw.equals(c)) { + for (Card battleOrPW : Iterables.filter(attackableEntries, Card.class)) { + if (battleOrPW.equals(c)) { Multimap attackerBuffer = ArrayListMultimap.create(); Collection bands = attackedByBands.get(c); - for (AttackingBand abPW : bands) { - unregisterDefender(c, abPW); + for (AttackingBand abDef : bands) { + unregisterDefender(c, abDef); // Rule 506.4c workaround to keep creatures in combat Card fake = new Card(-1, c.getGame()); fake.setName(""); fake.setController(c.getController(), 0); - attackerBuffer.put(fake, abPW); + attackerBuffer.put(fake, abDef); } bands.clear(); attackedByBands.putAll(attackerBuffer); From 2924329e574ea20d4f58f3327877a0172d87e32e Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 26 Apr 2023 21:28:08 +0200 Subject: [PATCH 5/7] Fix AI assigning more than 1 dmg with trampling deathtouch attacker --- .../java/forge/ai/ComputerUtilCombat.java | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java index 60b7908160b..69ceee83ac3 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java @@ -2059,31 +2059,23 @@ public class ComputerUtilCombat { if (block.size() == 1) { final Card blocker = block.getFirst(); + int dmgToBlocker = dmgCanDeal; - if (hasTrample) { - int dmgToKill = getEnoughDamageToKill(blocker, dmgCanDeal, attacker, true); + if (hasTrample && isAttacking) { // otherwise no entity to deliver damage via trample + dmgToBlocker = getEnoughDamageToKill(blocker, dmgCanDeal, attacker, true); - if (dmgCanDeal < dmgToKill) { - dmgToKill = Math.min(blocker.getLethalDamage(), dmgCanDeal); - } else { - dmgToKill = Math.max(blocker.getLethalDamage(), dmgToKill); + if (dmgCanDeal < dmgToBlocker) { + // can't kill so just put the lowest legal amount + dmgToBlocker = Math.min(blocker.getLethalDamage(), dmgCanDeal); } - if (!isAttacking) { // no entity to deliver damage via trample - dmgToKill = dmgCanDeal; - } - - final int remainingDmg = dmgCanDeal - dmgToKill; - + final int remainingDmg = dmgCanDeal - dmgToBlocker; // If Extra trample damage, assign to defending player/planeswalker (when there is one) if (remainingDmg > 0) { damageMap.put(null, remainingDmg); } - - damageMap.put(blocker, dmgToKill); - } else { - damageMap.put(blocker, dmgCanDeal); } + damageMap.put(blocker, dmgToBlocker); } // 1 blocker else { // Does the attacker deal lethal damage to all blockers From d609ec7ac60138627499057b7646084b90d96b4e Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 26 Apr 2023 22:03:43 +0200 Subject: [PATCH 6/7] Fix NPE with Hoarding Broodlord and DFC --- forge-game/src/main/java/forge/game/card/CardUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-game/src/main/java/forge/game/card/CardUtil.java b/forge-game/src/main/java/forge/game/card/CardUtil.java index 972c6f67a25..c7b99479eb8 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -203,7 +203,7 @@ public final class CardUtil { newCopy.getCurrentState().copyFrom(in.getState(in.getFaceupCardStateName()), true); if (in.isFaceDown()) { newCopy.turnFaceDownNoUpdate(); - newCopy.setType(new CardType(in.getCurrentState().getType())); + newCopy.setType(new CardType(in.getFaceDownState().getType())); // prevent StackDescription from revealing face newCopy.updateStateForView(); } From e6020a3fdcb839a54348a49dfc92f4de7b587538 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 26 Apr 2023 22:54:56 +0200 Subject: [PATCH 7/7] Remove outdated param --- .../src/main/java/forge/game/ability/effects/PlayEffect.java | 5 +++-- forge-gui/res/cardsfolder/c/coalition_relic.txt | 2 +- forge-gui/res/cardsfolder/d/deathrite_shaman.txt | 2 +- forge-gui/res/cardsfolder/m/manamorphose.txt | 2 +- forge-gui/res/cardsfolder/p/plasm_capture.txt | 2 +- forge-gui/res/cardsfolder/r/regal_behemoth.txt | 2 +- forge-gui/res/cardsfolder/s/sarkhan_unbroken.txt | 2 +- forge-gui/res/cardsfolder/s/smokebraider.txt | 2 +- forge-gui/res/cardsfolder/t/terrarion.txt | 2 +- forge-gui/res/cardsfolder/u/urza_academy_headmaster.txt | 2 +- 10 files changed, 12 insertions(+), 11 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java index f5d1edc79aa..321bb457bb6 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java @@ -25,6 +25,7 @@ import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; import forge.game.card.CardCollection; +import forge.game.card.CardCollectionView; import forge.game.card.CardFactoryUtil; import forge.game.card.CardZoneTable; import forge.game.cost.Cost; @@ -109,13 +110,13 @@ public class PlayEffect extends SpellAbilityEffect { } CardCollection tgtCards; - CardCollection showCards = new CardCollection(); + CardCollectionView showCards = new CardCollection(); if (sa.hasParam("Valid")) { List zones = sa.hasParam("ValidZone") ? ZoneType.listValueOf(sa.getParam("ValidZone")) : ImmutableList.of(ZoneType.Hand); tgtCards = new CardCollection(AbilityUtils.filterListByType(game.getCardsIn(zones), sa.getParam("Valid"), sa)); if (sa.hasParam("ShowCards")) { - showCards = new CardCollection(AbilityUtils.filterListByType(game.getCardsIn(zones), sa.getParam("ShowCards"), sa)); + showCards = AbilityUtils.filterListByType(game.getCardsIn(zones), sa.getParam("ShowCards"), sa); } } else if (sa.hasParam("AnySupportedCard")) { final String valid = sa.getParam("AnySupportedCard"); diff --git a/forge-gui/res/cardsfolder/c/coalition_relic.txt b/forge-gui/res/cardsfolder/c/coalition_relic.txt index 28c65f18e00..25be6a2d91b 100644 --- a/forge-gui/res/cardsfolder/c/coalition_relic.txt +++ b/forge-gui/res/cardsfolder/c/coalition_relic.txt @@ -5,7 +5,7 @@ A:AB$ Mana | Cost$ T | Produced$ Any | Amount$ 1 | SpellDescription$ Add one man A:AB$ PutCounter | Cost$ T | CounterType$ CHARGE | CounterNum$ 1 | SpellDescription$ Put a charge counter on CARDNAME. T:Mode$ Phase | PreCombatMain$ True | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigRemove | TriggerDescription$ At the beginning of your precombat main phase, remove all charge counters from CARDNAME. Add one mana of any color for each charge counter removed this way. SVar:TrigRemove:DB$ RemoveCounter | CounterType$ CHARGE | CounterNum$ All | RememberRemoved$ True | SubAbility$ TrigGetMana -SVar:TrigGetMana:DB$ Mana | Produced$ Combo Any | Amount$ NumRemoved | AILogic$ MostProminentInComputerHand | SubAbility$ DBCleanup +SVar:TrigGetMana:DB$ Mana | Produced$ Combo Any | Amount$ NumRemoved | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:NumRemoved:Count$RememberedSize Oracle:{T}: Add one mana of any color.\n{T}: Put a charge counter on Coalition Relic.\nAt the beginning of your precombat main phase, remove all charge counters from Coalition Relic. Add one mana of any color for each charge counter removed this way. diff --git a/forge-gui/res/cardsfolder/d/deathrite_shaman.txt b/forge-gui/res/cardsfolder/d/deathrite_shaman.txt index f3bba5d7b21..1df2e966d02 100644 --- a/forge-gui/res/cardsfolder/d/deathrite_shaman.txt +++ b/forge-gui/res/cardsfolder/d/deathrite_shaman.txt @@ -3,7 +3,7 @@ ManaCost:BG Types:Creature Elf Shaman PT:1/2 A:AB$ ChangeZone | Cost$ T | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Land | TgtPrompt$ Select target land card in a graveyard | SubAbility$ DBMana | SpellDescription$ Exile target land card from a graveyard. Add one mana of any color. -SVar:DBMana:DB$ Mana | Produced$ Any | Amount$ 1 | AILogic$ MostProminentInComputerHand +SVar:DBMana:DB$ Mana | Produced$ Any | Amount$ 1 A:AB$ ChangeZone | Cost$ B T | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Instant,Sorcery | TgtPrompt$ Select target instant or sorcery card in a graveyard | SubAbility$ DBLoseLife | AITgtOwnCards$ True | SpellDescription$ Exile target instant or sorcery card from a graveyard. Each opponent loses 2 life. SVar:DBLoseLife:DB$ LoseLife | Defined$ Player.Opponent | LifeAmount$ 2 A:AB$ ChangeZone | Cost$ G T | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Creature | TgtPrompt$ Select target creature card in a graveyard | SubAbility$ DBGainLife | AITgtOwnCards$ True | SpellDescription$ Exile target creature card from a graveyard. You gain 2 life. diff --git a/forge-gui/res/cardsfolder/m/manamorphose.txt b/forge-gui/res/cardsfolder/m/manamorphose.txt index 59ff60a8c7e..56b0103258a 100644 --- a/forge-gui/res/cardsfolder/m/manamorphose.txt +++ b/forge-gui/res/cardsfolder/m/manamorphose.txt @@ -1,7 +1,7 @@ Name:Manamorphose ManaCost:1 RG Types:Instant -A:SP$ Mana | Cost$ 1 RG | Produced$ Combo Any | Amount$ 2 | AILogic$ MostProminentInComputerHand | SubAbility$ DBDraw | SpellDescription$ Add two mana in any combination of colors. Draw a card. +A:SP$ Mana | Cost$ 1 RG | Produced$ Combo Any | Amount$ 2 | SubAbility$ DBDraw | SpellDescription$ Add two mana in any combination of colors. Draw a card. SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 1 AI:RemoveDeck:All Oracle:Add two mana in any combination of colors.\nDraw a card. diff --git a/forge-gui/res/cardsfolder/p/plasm_capture.txt b/forge-gui/res/cardsfolder/p/plasm_capture.txt index 4ea253e13d3..24e3b579322 100644 --- a/forge-gui/res/cardsfolder/p/plasm_capture.txt +++ b/forge-gui/res/cardsfolder/p/plasm_capture.txt @@ -4,6 +4,6 @@ Types:Instant A:SP$ Counter | Cost$ G G U U | TargetType$ Spell | RememberCounteredCMC$ True | ValidTgts$ Card | SubAbility$ DBDelTrig | SpellDescription$ Counter target spell. At the beginning of your next precombat main phase, add X mana in any combination of colors, where X is that spell's mana value. SVar:DBDelTrig:DB$ DelayedTrigger | Mode$ Phase | PreCombatMain$ True | ValidPlayer$ You | Execute$ AddMana | TriggerDescription$ At the beginning of your next precombat main phase, add X mana in any combination of colors, where X is that spell's mana value. | RememberNumber$ True | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:AddMana:DB$ Mana | Produced$ Combo Any | Amount$ X | AILogic$ MostProminentInComputerHand +SVar:AddMana:DB$ Mana | Produced$ Combo Any | Amount$ X SVar:X:Count$TriggerRememberAmount Oracle:Counter target spell. At the beginning of your next precombat main phase, add X mana in any combination of colors, where X is that spell's mana value. diff --git a/forge-gui/res/cardsfolder/r/regal_behemoth.txt b/forge-gui/res/cardsfolder/r/regal_behemoth.txt index 0364bf56dda..74e4c022dcc 100644 --- a/forge-gui/res/cardsfolder/r/regal_behemoth.txt +++ b/forge-gui/res/cardsfolder/r/regal_behemoth.txt @@ -6,5 +6,5 @@ K:Trample T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigMonarch | TriggerDescription$ When CARDNAME enters the battlefield, you become the monarch. SVar:TrigMonarch:DB$ BecomeMonarch | Defined$ You T:Mode$ TapsForMana | ValidCard$ Land | Activator$ You | CheckDefinedPlayer$ You.isMonarch | Execute$ TrigMana | TriggerZones$ Battlefield | Static$ True | TriggerDescription$ Whenever you tap a land for mana while you're the monarch, add an additional one mana of any color. -SVar:TrigMana:DB$ Mana | Produced$ Combo Any | Amount$ 1 | AILogic$ MostProminentInComputerHand +SVar:TrigMana:DB$ Mana | Produced$ Combo Any | Amount$ 1 Oracle:Trample\nWhen Regal Behemoth enters the battlefield, you become the monarch.\nWhenever you tap a land for mana while you're the monarch, add an additional one mana of any color. diff --git a/forge-gui/res/cardsfolder/s/sarkhan_unbroken.txt b/forge-gui/res/cardsfolder/s/sarkhan_unbroken.txt index 485ef7d5967..d7020836160 100644 --- a/forge-gui/res/cardsfolder/s/sarkhan_unbroken.txt +++ b/forge-gui/res/cardsfolder/s/sarkhan_unbroken.txt @@ -3,7 +3,7 @@ ManaCost:2 G U R Types:Legendary Planeswalker Sarkhan Loyalty:4 A:AB$ Draw | Cost$ AddCounter<1/LOYALTY> | Defined$ You | SubAbility$ DBMana | Planeswalker$ True | SpellDescription$ Draw a card, then add one mana of any color. -SVar:DBMana:DB$ Mana | Produced$ Any | AILogic$ MostProminentInComputerHand +SVar:DBMana:DB$ Mana | Produced$ Any A:AB$ Token | Cost$ SubCounter<2/LOYALTY> | TokenAmount$ 1 | TokenScript$ r_4_4_dragon_flying | TokenOwner$ You | Planeswalker$ True | SpellDescription$ Create a 4/4 red Dragon creature token with flying. A:AB$ ChangeZone | Cost$ SubCounter<8/LOYALTY> | Origin$ Library | Destination$ Battlefield | ChangeType$ Creature.Dragon | ChangeNum$ XFetch | Planeswalker$ True | Ultimate$ True | StackDescription$ SpellDescription | SpellDescription$ Search your library for any number of Dragon creature cards, put them onto the battlefield, then shuffle. SVar:XFetch:Count$TypeInYourLibrary.Dragon diff --git a/forge-gui/res/cardsfolder/s/smokebraider.txt b/forge-gui/res/cardsfolder/s/smokebraider.txt index e3672b40982..6085b6c3332 100644 --- a/forge-gui/res/cardsfolder/s/smokebraider.txt +++ b/forge-gui/res/cardsfolder/s/smokebraider.txt @@ -2,6 +2,6 @@ Name:Smokebraider ManaCost:1 R Types:Creature Elemental Shaman PT:1/1 -A:AB$ Mana | Cost$ T | Produced$ Combo Any | Amount$ 2 | RestrictValid$ Spell.Elemental,Activated.Elemental+inZoneBattlefield | AILogic$ MostProminentInComputerHand | SpellDescription$ Add two mana in any combination of colors. Spend this mana only to cast Elemental spells or activate abilities of Elementals. +A:AB$ Mana | Cost$ T | Produced$ Combo Any | Amount$ 2 | RestrictValid$ Spell.Elemental,Activated.Elemental+inZoneBattlefield | SpellDescription$ Add two mana in any combination of colors. Spend this mana only to cast Elemental spells or activate abilities of Elementals. AI:RemoveDeck:Random Oracle:{T}: Add two mana in any combination of colors. Spend this mana only to cast Elemental spells or activate abilities of Elementals. diff --git a/forge-gui/res/cardsfolder/t/terrarion.txt b/forge-gui/res/cardsfolder/t/terrarion.txt index 97592d24c27..ea8686bf88c 100644 --- a/forge-gui/res/cardsfolder/t/terrarion.txt +++ b/forge-gui/res/cardsfolder/t/terrarion.txt @@ -1,7 +1,7 @@ Name:Terrarion ManaCost:1 Types:Artifact -A:AB$ Mana | Cost$ 2 T Sac<1/CARDNAME> | Produced$ Combo Any | Amount$ 2 | AILogic$ MostProminentInComputerHand | SpellDescription$ Add two mana in any combination of colors. +A:AB$ Mana | Cost$ 2 T Sac<1/CARDNAME> | Produced$ Combo Any | Amount$ 2 | SpellDescription$ Add two mana in any combination of colors. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME is put into a graveyard from the battlefield, draw a card. SVar:TrigDraw:DB$ Draw | Defined$ TriggeredCardController | NumCards$ 1 K:CARDNAME enters the battlefield tapped. diff --git a/forge-gui/res/cardsfolder/u/urza_academy_headmaster.txt b/forge-gui/res/cardsfolder/u/urza_academy_headmaster.txt index ea9d538e936..ef6cb28fc7c 100644 --- a/forge-gui/res/cardsfolder/u/urza_academy_headmaster.txt +++ b/forge-gui/res/cardsfolder/u/urza_academy_headmaster.txt @@ -23,7 +23,7 @@ SVar:Exile11:DB$ ChangeZone | ValidTgts$ Player | TgtPrompt$ Select target playe SVar:Dig12:DB$ Dig | DigNum$ 1 | Reveal$ True | ChangeNum$ All | ChangeValid$ Land | DestinationZone$ Battlefield | DestinationZone2$ Hand | SpellDescription$ Reveal the top card of your library. If it's a land card, put it onto the battlefield. Otherwise, put it into your hand. SVar:Animate13:DB$ Animate | ValidTgts$ Land.YouCtrl | TgtPrompt$ Select target land you control | Power$ 4 | Toughness$ 4 | Types$ Creature,Elemental | Duration$ Permanent | Keywords$ Trample | SpellDescription$ Target land you control becomes a 4/4 Elemental creature with trample. It's still a land. SVar:Draw14:DB$ Draw | Defined$ You | SubAbility$ DBMana14 | SpellDescription$ Draw a card, then add one mana of any color. -SVar:DBMana14:DB$ Mana | Produced$ Any | AILogic$ MostProminentInComputerHand +SVar:DBMana14:DB$ Mana | Produced$ Any SVar:Animate15:DB$ Animate | Power$ 4 | Toughness$ 4 | Types$ Creature,Legendary,Dragon | Colors$ Red | OverwriteColors$ True | RemoveCardTypes$ True | Keywords$ Flying & Indestructible & Haste | SpellDescription$ Until end of turn, NICKNAME becomes a legendary 4/4 red Dragon creature with flying, indestructible, and haste. (He doesn't lose loyalty while he's not a planeswalker.) SVar:PumpAll16:DB$ PumpAll | ValidCards$ Creature.YouCtrl | NumAtt$ +1 | KW$ Lifelink | Duration$ UntilYourNextTurn | SpellDescription$ Until your next turn, creatures you control get +1/+0 and gain lifelink. SVar:Dig17:DB$ Dig | DigNum$ 5 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Artifact | SpellDescription$ Look at the top five cards of your library. You may reveal an artifact card from among them and put it into your hand. Put the rest on the bottom of your library in any order.