From fcee03d4f4d96890cc5df6fef5abdc9a5cbea1d6 Mon Sep 17 00:00:00 2001
From: Hans Mackowiak <hanmac@gmx.de>
Date: Sat, 29 Jul 2023 12:21:17 +0200
Subject: [PATCH] Card: add Table for SwitchPT

---
 .../main/java/forge/ai/ComputerUtilCard.java  |  5 ++++
 .../main/java/forge/ai/ability/PumpAi.java    | 28 +++++++++---------
 .../java/forge/ai/simulation/GameCopier.java  |  1 +
 .../game/ability/effects/PumpAllEffect.java   |  7 ++++-
 .../game/ability/effects/PumpEffect.java      |  8 +++--
 .../src/main/java/forge/game/card/Card.java   | 29 ++++++++++++++++---
 .../main/java/forge/game/card/CardUtil.java   |  1 +
 forge-gui/res/cardsfolder/a/about_face.txt    |  3 +-
 forge-gui/res/cardsfolder/a/aeromoeba.txt     |  2 +-
 forge-gui/res/cardsfolder/a/aquamoeba.txt     |  3 +-
 .../res/cardsfolder/c/calcite_snapper.txt     |  3 +-
 forge-gui/res/cardsfolder/c/crag_puca.txt     |  3 +-
 .../cardsfolder/c/crookclaw_transmuter.txt    |  2 +-
 .../res/cardsfolder/d/djinn_of_wishes.txt     |  2 +-
 .../cardsfolder/d/dwarven_thaumaturgist.txt   |  2 +-
 forge-gui/res/cardsfolder/f/fluxcharger.txt   |  3 +-
 forge-gui/res/cardsfolder/h/hatchet_bully.txt |  2 +-
 forge-gui/res/cardsfolder/i/inside_out.txt    |  3 +-
 forge-gui/res/cardsfolder/i/invert_invent.txt |  4 +--
 .../m/mannichi_the_fevered_dream.txt          |  3 +-
 .../cardsfolder/m/merfolk_thaumaturgist.txt   |  3 +-
 forge-gui/res/cardsfolder/m/myr_quadropod.txt |  3 +-
 .../res/cardsfolder/p/phantasmal_fiend.txt    |  2 +-
 .../res/cardsfolder/s/strange_inversion.txt   |  3 +-
 forge-gui/res/cardsfolder/t/transmutation.txt |  3 +-
 .../cardsfolder/t/turtleshell_changeling.txt  |  3 +-
 .../res/cardsfolder/v/valakut_fireboar.txt    |  2 +-
 .../res/cardsfolder/w/wandering_fumarole.txt  |  2 +-
 forge-gui/res/cardsfolder/w/windreaver.txt    |  2 +-
 29 files changed, 82 insertions(+), 55 deletions(-)

diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java
index 850c8f4f5cf..ae0e90961be 100644
--- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java
+++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java
@@ -1780,6 +1780,11 @@ public static Card getPumpedCreature(final Player ai, final SpellAbility sa,
         pumped.setPTBoost(c.getPTBoostTable());
         pumped.addPTBoost(power + berserkPower, toughness, timestamp, 0);
 
+        pumped.setSwitchPTTable(c.getSwitchPTTable());
+        if (sa.hasParam("SwitchPT")) {
+            pumped.addSwitchPT(timestamp, 0);
+        }
+
         if (!kws.isEmpty()) {
             pumped.addChangedCardKeywords(kws, null, false, timestamp, 0, false);
         }
diff --git a/forge-ai/src/main/java/forge/ai/ability/PumpAi.java b/forge-ai/src/main/java/forge/ai/ability/PumpAi.java
index 6cd32fd1b21..7041cf23160 100644
--- a/forge-ai/src/main/java/forge/ai/ability/PumpAi.java
+++ b/forge-ai/src/main/java/forge/ai/ability/PumpAi.java
@@ -67,12 +67,6 @@ protected boolean checkAiLogic(final Player ai, final SpellAbility sa, final Str
             return SpecialAiLogic.doAristocratLogic(ai, sa);
         } else if (aiLogic.startsWith("AristocratCounters")) {
             return SpecialAiLogic.doAristocratWithCountersLogic(ai, sa);
-        } else if (aiLogic.equals("SwitchPT")) {
-            // Some more AI would be even better, but this is a good start to prevent spamming
-            if (sa.isActivatedAbility() && sa.getActivationsThisTurn() > 0 && !sa.usesTargeting()) {
-                // Will prevent flipping back and forth
-                return false;
-            }
         }
 
         return super.checkAiLogic(ai, sa, aiLogic);
@@ -93,11 +87,6 @@ protected boolean checkPhaseRestrictions(final Player ai, final SpellAbility sa,
             if (!ph.is(PhaseType.COMBAT_DECLARE_BLOCKERS) && !isThreatened) {
                 return false;
             }
-        } else if (logic.equals("SwitchPT")) {
-            // Some more AI would be even better, but this is a good start to prevent spamming
-            if (ph.getPhase().isAfter(PhaseType.COMBAT_FIRST_STRIKE_DAMAGE) || !ph.inCombat()) {
-                return false;
-            }
         }
         return super.checkPhaseRestrictions(ai, sa, ph);
     }
@@ -114,6 +103,12 @@ protected boolean checkPhaseRestrictions(final Player ai, final SpellAbility sa,
                 return false;
             }
         }
+        if (sa.hasParam("SwitchPT")) {
+            // Some more AI would be even better, but this is a good start to prevent spamming
+            if (ph.getPhase().isAfter(PhaseType.COMBAT_FIRST_STRIKE_DAMAGE) || !ph.inCombat()) {
+                return false;
+            }
+        }
         if (game.getStack().isEmpty() && (ph.getPhase().isBefore(PhaseType.COMBAT_BEGIN)
                 || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS))) {
             // Instant-speed pumps should not be cast outside of combat when the
@@ -128,7 +123,6 @@ protected boolean checkApiLogic(Player ai, SpellAbility sa) {
         final Game game = ai.getGame();
         final Card source = sa.getHostCard();
         final SpellAbility root = sa.getRootAbility();
-        final String sourceName = ComputerUtilAbility.getAbilitySourceName(sa);
         final List<String> keywords = sa.hasParam("KW") ? Arrays.asList(sa.getParam("KW").split(" & "))
                 : Lists.newArrayList();
         final String numDefense = sa.getParamOrDefault("NumDef", "");
@@ -267,6 +261,14 @@ public boolean apply(Card card) {
             }
         }
 
+        if (sa.hasParam("SwitchPT")) {
+            // Some more AI would be even better, but this is a good start to prevent spamming
+            if (sa.isActivatedAbility() && sa.getActivationsThisTurn() > 0 && !sa.usesTargeting()) {
+                // Will prevent flipping back and forth
+                return false;
+            }
+        }
+
         if (ComputerUtil.preventRunAwayActivations(sa)) {
             return false;
         }
@@ -391,7 +393,7 @@ public boolean apply(Card card) {
     } // pumpPlayAI()
 
     private boolean pumpTgtAI(final Player ai, final SpellAbility sa, final int defense, final int attack, final boolean mandatory,
-    		boolean immediately) {
+                boolean immediately) {
         final List<String> keywords = sa.hasParam("KW") ? Arrays.asList(sa.getParam("KW").split(" & "))
                 : Lists.newArrayList();
         final Game game = ai.getGame();
diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java
index 361441090fc..b3e316f5022 100644
--- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java
+++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java
@@ -351,6 +351,7 @@ private void addCard(Game newGame, ZoneType zone, Card c) {
             newCard.setPTCharacterDefiningTable(c.getSetPTCharacterDefiningTable());
 
             newCard.setPTBoost(c.getPTBoostTable());
+            newCard.setSwitchPTTable(c.getSwitchPTTable());
             // TODO copy by map
             newCard.setDamage(c.getDamage());
             newCard.setDamageReceivedThisTurn(c.getDamageReceivedThisTurn());
diff --git a/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java
index 79132dd1c50..4c9eb1da800 100644
--- a/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java
+++ b/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java
@@ -49,7 +49,11 @@ private static void applyPumpAll(final SpellAbility sa,
                 continue;
             }
 
-            boolean redrawPT = false;
+            boolean redrawPT = sa.hasParam("SwitchPT");
+
+            if (sa.hasParam("SwitchPT")) {
+                tgtC.addSwitchPT(timestamp, 0);
+            }
 
             if (a != 0 || d != 0) {
                 tgtC.addPTBoost(a, d, timestamp, 0);
@@ -78,6 +82,7 @@ private static void applyPumpAll(final SpellAbility sa,
 
                     @Override
                     public void run() {
+                        tgtC.removeSwitchPT(timestamp, 0);
                         tgtC.removePTBoost(timestamp, 0);
                         tgtC.removeChangedCardKeywords(timestamp, 0);
                         tgtC.removeHiddenExtrinsicKeywords(timestamp, 0);
diff --git a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java
index c40f2295d6a..6ad59faee0a 100644
--- a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java
+++ b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java
@@ -59,16 +59,19 @@ private static void applyPump(final SpellAbility sa, final Card applyTo,
         final List<String> kws = Lists.newArrayList();
         final List<String> hiddenKws = Lists.newArrayList();
 
-        boolean redrawPT = false;
+        boolean redrawPT = sa.hasParam("SwitchPT");
         for (String kw : keywords) {
             if (kw.startsWith("HIDDEN")) {
                 hiddenKws.add(kw.substring(7));
-                redrawPT |= kw.contains("CARDNAME's power and toughness are switched");
             } else {
                 kws.add(kw);
             }
         }
 
+        if (sa.hasParam("SwitchPT")) {
+            gameCard.addSwitchPT(timestamp, 0);
+        }
+
         if (a != 0 || d != 0) {
             gameCard.addPTBoost(a, d, timestamp, 0);
             redrawPT = true;
@@ -104,6 +107,7 @@ private static void applyPump(final SpellAbility sa, final Card applyTo,
                 @Override
                 public void run() {
                     gameCard.removePTBoost(timestamp, 0);
+                    gameCard.removeSwitchPT(timestamp, 0);
                     boolean updateText = gameCard.removeCanBlockAny(timestamp);
                     updateText |= gameCard.removeCanBlockAdditional(timestamp);
 
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 e6558d2288a..9d4ffee7bcb 100644
--- a/forge-game/src/main/java/forge/game/card/Card.java
+++ b/forge-game/src/main/java/forge/game/card/Card.java
@@ -260,6 +260,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
     private Table<Long, Long, Pair<Integer,Integer>> newPTCharacterDefining = TreeBasedTable.create(); // Layer 7a
     private Table<Long, Long, Pair<Integer,Integer>> newPT = TreeBasedTable.create(); // Layer 7b
     private Table<Long, Long, Pair<Integer,Integer>> boostPT = TreeBasedTable.create(); // Layer 7c
+    private Table<Long, Long, Boolean> switchPT = TreeBasedTable.create(); // Layer 7d
 
     private String oracleText = "";
 
@@ -4247,13 +4248,13 @@ public final int getPowerBonusFromCounters() {
     }
 
     public final StatBreakdown getNetPowerBreakdown() {
-        if (getAmountOfKeyword("CARDNAME's power and toughness are switched") % 2 != 0) {
+        if (isSwitchPT()) {
             return getUnswitchedToughnessBreakdown();
         }
         return getUnswitchedPowerBreakdown();
     }
     public final int getNetPower() {
-        if (getAmountOfKeyword("CARDNAME's power and toughness are switched") % 2 != 0) {
+        if (isSwitchPT()) {
             return getUnswitchedToughness();
         }
         return getUnswitchedPower();
@@ -4311,7 +4312,7 @@ public final int getToughnessBonusFromCounters() {
     }
 
     public final StatBreakdown getNetToughnessBreakdown() {
-        if (getAmountOfKeyword("CARDNAME's power and toughness are switched") % 2 != 0) {
+        if (isSwitchPT()) {
             return getUnswitchedPowerBreakdown();
         }
         return getUnswitchedToughnessBreakdown();
@@ -4406,10 +4407,30 @@ public Table<Long, Long, Pair<Integer, Integer>> getPTBoostTable() {
     }
 
     public void setPTBoost(Table<Long, Long, Pair<Integer, Integer>> table) {
-        this.boostPT.clear();
+        boostPT.clear();
         boostPT.putAll(table);
     }
 
+    public boolean isSwitchPT() {
+        return switchPT.values().size() % 2 != 0;
+    }
+
+    public void addSwitchPT(final long timestamp, final long staticId) {
+        switchPT.put(timestamp, staticId, Boolean.TRUE);
+    }
+
+    public void removeSwitchPT(final long timestamp, final long staticId) {
+        switchPT.remove(timestamp, staticId);
+    }
+
+    public Table<Long, Long, Boolean> getSwitchPTTable() {
+        return ImmutableTable.copyOf(switchPT);
+    }
+    public void setSwitchPTTable(Table<Long, Long, Boolean> table) {
+        switchPT.clear();
+        switchPT.putAll(table);
+    }
+
     public final boolean isUntapped() {
         return !tapped;
     }
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 9a26ae6a8b2..2fce6f9a70e 100644
--- a/forge-game/src/main/java/forge/game/card/CardUtil.java
+++ b/forge-game/src/main/java/forge/game/card/CardUtil.java
@@ -259,6 +259,7 @@ public static Card getLKICopy(final Card in, Map<Integer, Card> cachedMap) {
 
         // extra copy PT boost
         newCopy.setPTBoost(in.getPTBoostTable());
+        newCopy.setSwitchPTTable(in.getSwitchPTTable());
 
         newCopy.setCounters(Maps.newHashMap(in.getCounters()));
 
diff --git a/forge-gui/res/cardsfolder/a/about_face.txt b/forge-gui/res/cardsfolder/a/about_face.txt
index 861f4516ce0..8e4a8064d48 100644
--- a/forge-gui/res/cardsfolder/a/about_face.txt
+++ b/forge-gui/res/cardsfolder/a/about_face.txt
@@ -1,6 +1,5 @@
 Name:About Face
 ManaCost:R
 Types:Instant
-A:SP$ Pump | Cost$ R | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch target creature's power and toughness until end of turn.
-AI:RemoveDeck:All
+A:SP$ Pump | ValidTgts$ Creature | SwitchPT$ True | SpellDescription$ Switch target creature's power and toughness until end of turn.
 Oracle:Switch target creature's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/a/aeromoeba.txt b/forge-gui/res/cardsfolder/a/aeromoeba.txt
index 030f6708b09..173705dcd27 100644
--- a/forge-gui/res/cardsfolder/a/aeromoeba.txt
+++ b/forge-gui/res/cardsfolder/a/aeromoeba.txt
@@ -3,5 +3,5 @@ ManaCost:3 U
 Types:Creature Elemental Beast
 PT:2/4
 K:Flying
-A:AB$ Pump | Cost$ Discard<1/Card> | Defined$ Self | AILogic$ SwitchPT | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
+A:AB$ Pump | Cost$ Discard<1/Card> | Defined$ Self | SwitchPT$ True | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
 Oracle:Flying\nDiscard a card: Switch Aeromoeba's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/a/aquamoeba.txt b/forge-gui/res/cardsfolder/a/aquamoeba.txt
index d0980e285e2..67dfdb2edde 100644
--- a/forge-gui/res/cardsfolder/a/aquamoeba.txt
+++ b/forge-gui/res/cardsfolder/a/aquamoeba.txt
@@ -2,6 +2,5 @@ Name:Aquamoeba
 ManaCost:1 U
 Types:Creature Elemental Beast
 PT:1/3
-A:AB$ Pump | Cost$ Discard<1/Card> | Defined$ Self | AILogic$ SwitchPT | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
-AI:RemoveDeck:All
+A:AB$ Pump | Cost$ Discard<1/Card> | Defined$ Self | SwitchPT$ True | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
 Oracle:Discard a card: Switch Aquamoeba's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/c/calcite_snapper.txt b/forge-gui/res/cardsfolder/c/calcite_snapper.txt
index 79cc70d0801..89bfcc9b4b8 100644
--- a/forge-gui/res/cardsfolder/c/calcite_snapper.txt
+++ b/forge-gui/res/cardsfolder/c/calcite_snapper.txt
@@ -4,6 +4,5 @@ Types:Creature Turtle
 PT:1/4
 K:Shroud
 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPump | TriggerDescription$ Landfall — Whenever a land enters the battlefield under your control, you may switch CARDNAME power and toughness until end of turn.
-SVar:TrigPump:DB$ Pump | Defined$ Self | KW$ HIDDEN CARDNAME's power and toughness are switched
-AI:RemoveDeck:All
+SVar:TrigPump:DB$ Pump | Defined$ Self | SwitchPT$ True
 Oracle:Shroud (This creature can't be the target of spells or abilities.)\nLandfall — Whenever a land enters the battlefield under your control, you may switch Calcite Snapper's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/c/crag_puca.txt b/forge-gui/res/cardsfolder/c/crag_puca.txt
index fe34a798126..100a6f718c5 100644
--- a/forge-gui/res/cardsfolder/c/crag_puca.txt
+++ b/forge-gui/res/cardsfolder/c/crag_puca.txt
@@ -2,6 +2,5 @@ Name:Crag Puca
 ManaCost:UR UR UR
 Types:Creature Shapeshifter
 PT:2/4
-A:AB$ Pump | Cost$ UR | Defined$ Self | | AILogic$ SwitchPT | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
-AI:RemoveDeck:All
+A:AB$ Pump | Cost$ UR | Defined$ Self | SwitchPT$ True | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
 Oracle:{U/R}: Switch Crag Puca's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/c/crookclaw_transmuter.txt b/forge-gui/res/cardsfolder/c/crookclaw_transmuter.txt
index daf68f87730..d269a0d1929 100644
--- a/forge-gui/res/cardsfolder/c/crookclaw_transmuter.txt
+++ b/forge-gui/res/cardsfolder/c/crookclaw_transmuter.txt
@@ -5,6 +5,6 @@ PT:3/1
 K:Flash
 K:Flying
 T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigPump | TriggerDescription$ When CARDNAME enters the battlefield, switch target creature's power and toughness until end of turn.
-SVar:TrigPump:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ HIDDEN CARDNAME's power and toughness are switched
+SVar:TrigPump:DB$ Pump | ValidTgts$ Creature | SwitchPT$ True
 AI:RemoveDeck:All
 Oracle:Flash\nFlying\nWhen Crookclaw Transmuter enters the battlefield, switch target creature's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/d/djinn_of_wishes.txt b/forge-gui/res/cardsfolder/d/djinn_of_wishes.txt
index 3df0eb823e9..cc9f096e2b1 100644
--- a/forge-gui/res/cardsfolder/d/djinn_of_wishes.txt
+++ b/forge-gui/res/cardsfolder/d/djinn_of_wishes.txt
@@ -4,7 +4,7 @@ Types:Creature Djinn
 PT:4/4
 K:Flying
 K:etbCounter:WISH:3
-A:AB$ PeekAndReveal | Cost$ 2 U U SubCounter<1/WISH> | NoPeek$ True | ImprintRevealed$ True | SubAbility$ DBPlay |  | SpellDescription$ Reveal the top card of your library.
+A:AB$ PeekAndReveal | Cost$ 2 U U SubCounter<1/WISH> | NoPeek$ True | ImprintRevealed$ True | SubAbility$ DBPlay | SpellDescription$ Reveal the top card of your library.
 SVar:DBPlay:DB$ Play | Defined$ Imprinted | Controller$ You | WithoutManaCost$ True | Optional$ True | RememberPlayed$ True | SubAbility$ DBExileIfNotPlayed | StackDescription$ {p:You} may play that card without paying its mana cost. | SpellDescription$ You may play that card without paying its mana cost.
 SVar:DBExileIfNotPlayed:DB$ ChangeZone | Origin$ Library | Destination$ Exile | Defined$ Imprinted | DefinedPlayer$ You | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0 | SubAbility$ DBCleanup | StackDescription$ If they don't, they exile it. | SpellDescription$ If you don't, exile it.
 SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True
diff --git a/forge-gui/res/cardsfolder/d/dwarven_thaumaturgist.txt b/forge-gui/res/cardsfolder/d/dwarven_thaumaturgist.txt
index c4063a1c442..644b84c512d 100644
--- a/forge-gui/res/cardsfolder/d/dwarven_thaumaturgist.txt
+++ b/forge-gui/res/cardsfolder/d/dwarven_thaumaturgist.txt
@@ -2,6 +2,6 @@ Name:Dwarven Thaumaturgist
 ManaCost:2 R
 Types:Creature Dwarf Shaman
 PT:1/2
-A:AB$ Pump | Cost$ T | ValidTgts$ Creature | KW$ HIDDEN CARDNAME's power and toughness are switched | TgtPrompt$ Select target creature. | SpellDescription$ Switch target creature's power and toughness until end of turn.
+A:AB$ Pump | Cost$ T | ValidTgts$ Creature | SwitchPT$ True | SpellDescription$ Switch target creature's power and toughness until end of turn.
 AI:RemoveDeck:All
 Oracle:{T}: Switch target creature's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/f/fluxcharger.txt b/forge-gui/res/cardsfolder/f/fluxcharger.txt
index 731374caad8..5b8979f4c5c 100644
--- a/forge-gui/res/cardsfolder/f/fluxcharger.txt
+++ b/forge-gui/res/cardsfolder/f/fluxcharger.txt
@@ -4,7 +4,6 @@ Types:Creature Weird
 PT:1/5
 K:Flying
 T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigChangePT | OptionalDecider$ You | TriggerDescription$ Whenever you cast a instant or sorcery spell, you may switch CARDNAME's power and toughness until end of turn.
-SVar:TrigChangePT:DB$ Pump | KW$ HIDDEN CARDNAME's power and toughness are switched | Defined$ Self
-AI:RemoveDeck:All
+SVar:TrigChangePT:DB$ Pump | Defined$ Self | SwitchPT$ True
 DeckHints:Type$Instant|Sorcery
 Oracle:Flying\nWhenever you cast an instant or sorcery spell, you may switch Fluxcharger's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/h/hatchet_bully.txt b/forge-gui/res/cardsfolder/h/hatchet_bully.txt
index bf79d7a869a..dabf07043bc 100644
--- a/forge-gui/res/cardsfolder/h/hatchet_bully.txt
+++ b/forge-gui/res/cardsfolder/h/hatchet_bully.txt
@@ -2,5 +2,5 @@ Name:Hatchet Bully
 ManaCost:3 R
 Types:Creature Goblin Warrior
 PT:3/3
-A:AB$ DealDamage | Cost$ 2 R T AddCounter<1/M1M1/Creature.YouCtrl/a creature you control> | | ValidTgts$ Any | NumDmg$ 2 | SpellDescription$ CARDNAME deals 2 damage to any target.
+A:AB$ DealDamage | Cost$ 2 R T AddCounter<1/M1M1/Creature.YouCtrl/a creature you control> | ValidTgts$ Any | NumDmg$ 2 | SpellDescription$ CARDNAME deals 2 damage to any target.
 Oracle:{2}{R}, {T}, Put a -1/-1 counter on a creature you control: Hatchet Bully deals 2 damage to any target.
diff --git a/forge-gui/res/cardsfolder/i/inside_out.txt b/forge-gui/res/cardsfolder/i/inside_out.txt
index 0ba2a582332..e79016797ca 100644
--- a/forge-gui/res/cardsfolder/i/inside_out.txt
+++ b/forge-gui/res/cardsfolder/i/inside_out.txt
@@ -1,7 +1,6 @@
 Name:Inside Out
 ManaCost:1 UR
 Types:Instant
-A:SP$ Pump | Cost$ 1 UR | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch target creature's power and toughness until end of turn. | SubAbility$ DBDraw
+A:SP$ Pump | ValidTgts$ Creature | SwitchPT$ True | SpellDescription$ Switch target creature's power and toughness until end of turn. | SubAbility$ DBDraw
 SVar:DBDraw:DB$ Draw | NumCards$ 1 | SpellDescription$ Draw a card.
-AI:RemoveDeck:All
 Oracle:Switch target creature's power and toughness until end of turn.\nDraw a card.
diff --git a/forge-gui/res/cardsfolder/i/invert_invent.txt b/forge-gui/res/cardsfolder/i/invert_invent.txt
index a726e53f127..d8503315f2b 100644
--- a/forge-gui/res/cardsfolder/i/invert_invent.txt
+++ b/forge-gui/res/cardsfolder/i/invert_invent.txt
@@ -1,7 +1,7 @@
 Name:Invert
 ManaCost:U/R
 Types:Instant
-A:SP$ Pump | Cost$ U/R | ValidTgts$ Creature | TargetMin$ 0 | TargetMax$ 2 | TgtPrompt$ Select target creature | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch the power and toughness of each of up to two target creatures until end of turn.
+A:SP$ Pump | ValidTgts$ Creature | TargetMin$ 0 | TargetMax$ 2 | SwitchPT$ True | SpellDescription$ Switch the power and toughness of each of up to two target creatures until end of turn.
 AlternateMode:Split
 Oracle:Switch the power and toughness of each of up to two target creatures until end of turn.
 
@@ -10,7 +10,7 @@ ALTERNATE
 Name:Invent
 ManaCost:4 U R
 Types:Instant
-A:SP$ ChangeZone | Cost$ 4 U R | Origin$ Library | Destination$ Hand | ChangeType$ Instant | ChangeNum$ 1 | SubAbility$ DBChange | SpellDescription$ Search your library for and instant permanent and/or a sorcery card, reveal them, put them into your hand, then shuffle.
+A:SP$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Instant | ChangeNum$ 1 | SubAbility$ DBChange | SpellDescription$ Search your library for and instant permanent and/or a sorcery card, reveal them, put them into your hand, then shuffle.
 SVar:DBChange:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Sorcery | ChangeNum$ 1 | Shuffle$ True
 AI:RemoveDeck:Random
 DeckHints:Type$Instant|Sorcery
diff --git a/forge-gui/res/cardsfolder/m/mannichi_the_fevered_dream.txt b/forge-gui/res/cardsfolder/m/mannichi_the_fevered_dream.txt
index b7c6850009b..800cdba8716 100644
--- a/forge-gui/res/cardsfolder/m/mannichi_the_fevered_dream.txt
+++ b/forge-gui/res/cardsfolder/m/mannichi_the_fevered_dream.txt
@@ -2,6 +2,5 @@ Name:Mannichi, the Fevered Dream
 ManaCost:2 R
 Types:Legendary Creature Spirit
 PT:1/2
-A:AB$ PumpAll | Cost$ 1 R | ValidCards$ Creature | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch each creature's power and toughness until end of turn.
-AI:RemoveDeck:All
+A:AB$ PumpAll | Cost$ 1 R | ValidCards$ Creature | SwitchPT$ True | SpellDescription$ Switch each creature's power and toughness until end of turn.
 Oracle:{1}{R}: Switch each creature's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/m/merfolk_thaumaturgist.txt b/forge-gui/res/cardsfolder/m/merfolk_thaumaturgist.txt
index e50591f0223..5b0d0a5cf8d 100644
--- a/forge-gui/res/cardsfolder/m/merfolk_thaumaturgist.txt
+++ b/forge-gui/res/cardsfolder/m/merfolk_thaumaturgist.txt
@@ -2,6 +2,5 @@ Name:Merfolk Thaumaturgist
 ManaCost:2 U
 Types:Creature Merfolk Wizard
 PT:1/2
-A:AB$ Pump | Cost$ T | ValidTgts$ Creature | KW$ HIDDEN CARDNAME's power and toughness are switched | TgtPrompt$ Select target creature. | SpellDescription$ Switch target creature's power and toughness until end of turn.
-AI:RemoveDeck:All
+A:AB$ Pump | Cost$ T | ValidTgts$ Creature | SwitchPT$ True | SpellDescription$ Switch target creature's power and toughness until end of turn.
 Oracle:{T}: Switch target creature's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/m/myr_quadropod.txt b/forge-gui/res/cardsfolder/m/myr_quadropod.txt
index 02379169222..cce8bfc433e 100644
--- a/forge-gui/res/cardsfolder/m/myr_quadropod.txt
+++ b/forge-gui/res/cardsfolder/m/myr_quadropod.txt
@@ -2,6 +2,5 @@ Name:Myr Quadropod
 ManaCost:4
 Types:Artifact Creature Myr
 PT:1/4
-A:AB$ Pump | Cost$ 3 | Defined$ Self | | AILogic$ SwitchPT | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
-AI:RemoveDeck:All
+A:AB$ Pump | Cost$ 3 | Defined$ Self | SwitchPT$ True | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
 Oracle:{3}: Switch Myr Quadropod's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/p/phantasmal_fiend.txt b/forge-gui/res/cardsfolder/p/phantasmal_fiend.txt
index 6df528e2b10..b890d885f25 100644
--- a/forge-gui/res/cardsfolder/p/phantasmal_fiend.txt
+++ b/forge-gui/res/cardsfolder/p/phantasmal_fiend.txt
@@ -3,5 +3,5 @@ ManaCost:3 B
 Types:Creature Illusion
 PT:1/5
 A:AB$ Pump | Cost$ B | Defined$ Self | NumAtt$ +1 | NumDef$ -1 | SpellDescription$ CARDNAME gets +1/-1 until end of turn.
-A:AB$ Pump | Cost$ 1 U | Defined$ Self | AILogic$ SwitchPT | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
+A:AB$ Pump | Cost$ 1 U | Defined$ Self | SwitchPT$ True | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
 Oracle:{B}: Phantasmal Fiend gets +1/-1 until end of turn.\n{1}{U}: Switch Phantasmal Fiend's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/s/strange_inversion.txt b/forge-gui/res/cardsfolder/s/strange_inversion.txt
index a1720fd2aa2..bf406d5dff1 100644
--- a/forge-gui/res/cardsfolder/s/strange_inversion.txt
+++ b/forge-gui/res/cardsfolder/s/strange_inversion.txt
@@ -2,7 +2,6 @@ Name:Strange Inversion
 ManaCost:2 R
 Types:Instant Arcane
 K:Splice:Arcane:1 R
-A:SP$ Pump | Cost$ 2 R | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch target creature's power and toughness until end of turn.
-AI:RemoveDeck:All
+A:SP$ Pump | ValidTgts$ Creature | SwitchPT$ True | SpellDescription$ Switch target creature's power and toughness until end of turn.
 DeckHints:Type$Arcane
 Oracle:Switch target creature's power and toughness until end of turn.\nSplice onto Arcane {1}{R} (As you cast an Arcane 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.)
diff --git a/forge-gui/res/cardsfolder/t/transmutation.txt b/forge-gui/res/cardsfolder/t/transmutation.txt
index 983780a4b84..83096aa4729 100644
--- a/forge-gui/res/cardsfolder/t/transmutation.txt
+++ b/forge-gui/res/cardsfolder/t/transmutation.txt
@@ -1,6 +1,5 @@
 Name:Transmutation
 ManaCost:1 B
 Types:Instant
-A:SP$ Pump | Cost$ 1 B | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch target creature's power and toughness until end of turn.
-AI:RemoveDeck:All
+A:SP$ Pump | ValidTgts$ Creature | SwitchPT$ True | SpellDescription$ Switch target creature's power and toughness until end of turn.
 Oracle:Switch target creature's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/t/turtleshell_changeling.txt b/forge-gui/res/cardsfolder/t/turtleshell_changeling.txt
index 36e0838cc46..20828bc9fee 100644
--- a/forge-gui/res/cardsfolder/t/turtleshell_changeling.txt
+++ b/forge-gui/res/cardsfolder/t/turtleshell_changeling.txt
@@ -3,6 +3,5 @@ ManaCost:3 U
 Types:Creature Shapeshifter
 PT:1/4
 K:Changeling
-A:AB$ Pump | Cost$ 1 U | Defined$ Self | AILogic$ SwitchPT | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
-AI:RemoveDeck:All
+A:AB$ Pump | Cost$ 1 U | Defined$ Self | SwitchPT$ True | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
 Oracle:Changeling (This card is every creature type.)\n{1}{U}: Switch Turtleshell Changeling's power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/v/valakut_fireboar.txt b/forge-gui/res/cardsfolder/v/valakut_fireboar.txt
index b8c2c4cf299..7df54b35f26 100644
--- a/forge-gui/res/cardsfolder/v/valakut_fireboar.txt
+++ b/forge-gui/res/cardsfolder/v/valakut_fireboar.txt
@@ -3,6 +3,6 @@ ManaCost:4 R
 Types:Creature Elemental Boar
 PT:1/7
 T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigPump | TriggerDescription$ Whenever CARDNAME attacks, switch its power and toughness until end of turn.
-SVar:TrigPump:DB$ Pump | Defined$ Self | KW$ HIDDEN CARDNAME's power and toughness are switched
+SVar:TrigPump:DB$ Pump | Defined$ Self | SwitchPT$ True
 AI:RemoveDeck:Random
 Oracle:Whenever Valakut Fireboar attacks, switch its power and toughness until end of turn.
diff --git a/forge-gui/res/cardsfolder/w/wandering_fumarole.txt b/forge-gui/res/cardsfolder/w/wandering_fumarole.txt
index c81de280388..5815feb792f 100644
--- a/forge-gui/res/cardsfolder/w/wandering_fumarole.txt
+++ b/forge-gui/res/cardsfolder/w/wandering_fumarole.txt
@@ -4,5 +4,5 @@ Types:Land
 K:CARDNAME enters the battlefield tapped.
 A:AB$ Mana | Cost$ T | Produced$ Combo U R | SpellDescription$ Add {U} or {R}.
 A:AB$ Animate | Cost$ 2 U R | Defined$ Self | Power$ 1 | Toughness$ 4 | Types$ Creature,Elemental | Colors$ Blue,Red | Abilities$ ABPump | SpellDescription$ Until end of turn, CARDNAME becomes a 1/4 blue and red Elemental creature with "{0}: Switch this creature's power and toughness until end of turn." It's still a land.
-SVar:ABPump:AB$ Pump | Cost$ 0 | Defined$ Self | AILogic$ SwitchPT | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch this creature's power and toughness until end of turn.
+SVar:ABPump:AB$ Pump | Cost$ 0 | Defined$ Self | SwitchPT$ True | SpellDescription$ Switch this creature's power and toughness until end of turn.
 Oracle:Wandering Fumarole enters the battlefield tapped.\n{T}: Add {U} or {R}.\n{2}{U}{R}: Until end of turn, Wandering Fumarole becomes a 1/4 blue and red Elemental creature with "{0}: Switch this creature's power and toughness until end of turn." It's still a land.
diff --git a/forge-gui/res/cardsfolder/w/windreaver.txt b/forge-gui/res/cardsfolder/w/windreaver.txt
index 60385b032e7..f0482ddaee3 100644
--- a/forge-gui/res/cardsfolder/w/windreaver.txt
+++ b/forge-gui/res/cardsfolder/w/windreaver.txt
@@ -5,6 +5,6 @@ PT:1/3
 K:Flying
 A:AB$ Pump | Cost$ W | Defined$ Self | KW$ Vigilance | SpellDescription$ Windreaver gains vigilance until end of turn.
 A:AB$ Pump | Cost$ W | Defined$ Self | NumDef$ +1 | SpellDescription$ Windreaver gets +0/+1 until end of turn.
-A:AB$ Pump | Cost$ U | Defined$ Self | AILogic$ SwitchPT | KW$ HIDDEN CARDNAME's power and toughness are switched | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
+A:AB$ Pump | Cost$ U | Defined$ Self | SwitchPT$ True | SpellDescription$ Switch CARDNAME's power and toughness until end of turn.
 A:AB$ ChangeZone | Cost$ U | Origin$ Battlefield | Destination$ Hand | SpellDescription$ Return CARDNAME to its owner's hand.
 Oracle:Flying\n{W}: Windreaver gains vigilance until end of turn.\n{W}: Windreaver gets +0/+1 until end of turn.\n{U}: Switch Windreaver's power and toughness until end of turn.\n{U}: Return Windreaver to its owner's hand.