Merge branch 'exchangeControlTrickster' into 'master'

ExchangeControl: add Optional and two Targets also TargetsWithSameCardType

See merge request core-developers/forge!3705
This commit is contained in:
Michael Kamensky
2021-02-02 17:06:19 +00:00
20 changed files with 163 additions and 54 deletions

View File

@@ -81,7 +81,12 @@ public class ControlExchangeAi extends SpellAbilityAi {
final TargetRestrictions tgt = sa.getTargetRestrictions();
CardCollection list = CardLists.getValidCards(aiPlayer.getGame().getCardsIn(ZoneType.Battlefield),
// for TrigTwoTargets logic, only get the opponents' cards for the first target
CardCollectionView unfilteredList = "TrigTwoTargets".equals(sa.getParam("AILogic")) ?
aiPlayer.getOpponents().getCardsIn(ZoneType.Battlefield) :
aiPlayer.getGame().getCardsIn(ZoneType.Battlefield);
CardCollection list = CardLists.getValidCards(unfilteredList,
tgt.getValidTgts(), aiPlayer, sa.getHostCard(), sa);
// only select the cards that can be targeted
@@ -106,7 +111,51 @@ public class ControlExchangeAi extends SpellAbilityAi {
// add best Target
sa.getTargets().add(best);
// second target needed (the AI's own worst)
if ("TrigTwoTargets".equals(sa.getParam("AILogic"))) {
return doTrigTwoTargetsLogic(aiPlayer, sa, best);
}
return true;
}
private boolean doTrigTwoTargetsLogic(Player ai, SpellAbility sa, Card bestFirstTgt) {
final TargetRestrictions tgt = sa.getTargetRestrictions();
final int creatureThreshold = 100; // TODO: make this configurable from the AI profile
final int nonCreatureThreshold = 2;
CardCollection list = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield),
tgt.getValidTgts(), ai, sa.getHostCard(), sa);
// only select the cards that can be targeted
list = CardLists.getTargetableCards(list, sa);
if (list.isEmpty()) {
return false;
}
Card aiWorst = ComputerUtilCard.getWorstAI(list);
if (aiWorst == null) {
return false;
}
if (aiWorst != null && aiWorst != bestFirstTgt) {
if (bestFirstTgt.isCreature() && aiWorst.isCreature()) {
if ((ComputerUtilCard.evaluateCreature(bestFirstTgt) > ComputerUtilCard.evaluateCreature(aiWorst) + creatureThreshold) || sa.isMandatory()) {
sa.getTargets().add(aiWorst);
return true;
}
} else {
// TODO: compare non-creatures by CMC - can be improved, at least shouldn't give control of things like the Power Nine
if ((bestFirstTgt.getCMC() > aiWorst.getCMC() + nonCreatureThreshold) || sa.isMandatory()) {
sa.getTargets().add(aiWorst);
return true;
}
}
}
sa.clearTargets();
return false;
}
}

View File

@@ -352,6 +352,9 @@ public final class AbilityFactory {
if (mapParams.containsKey("TargetsWithSameCreatureType")) {
abTgt.setWithSameCreatureType(true);
}
if (mapParams.containsKey("TargetsWithSameCardType")) {
abTgt.setWithSameCardType(true);
}
if (mapParams.containsKey("TargetsWithSameController")) {
abTgt.setSameController(true);
}

View File

@@ -1,14 +1,16 @@
package forge.game.ability.effects;
import com.google.common.collect.Lists;
import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.util.CardTranslation;
import forge.util.Localizer;
import java.util.ArrayList;
import java.util.List;
@@ -21,21 +23,27 @@ public class ControlExchangeEffect extends SpellAbilityEffect {
protected String getStackDescription(SpellAbility sa) {
Card object1 = null;
Card object2 = null;
final TargetRestrictions tgt = sa.getTargetRestrictions();
List<Card> tgts = tgt == null ? new ArrayList<>() : Lists.newArrayList(sa.getTargets().getTargetCards());
if (tgts.size() > 0) {
object1 = tgts.get(0);
List<Card> tgts = null;
if (sa.usesTargeting()) {
tgts = Lists.newArrayList(sa.getTargets().getTargetCards());
if (tgts.size() > 0) {
object1 = tgts.get(0);
}
}
if (sa.hasParam("Defined")) {
List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
object2 = cards.isEmpty() ? null : cards.get(0);
if (cards.size() > 1 && sa.hasParam("BothDefined")) {
if (cards.size() > 1 && !sa.usesTargeting()) {
object1 = cards.get(1);
}
} else if (tgts.size() > 1) {
object2 = tgts.get(1);
}
if (object1 == null || object2 == null) {
return "";
}
return object1 + " exchanges controller with " + object2;
}
@@ -44,17 +52,22 @@ public class ControlExchangeEffect extends SpellAbilityEffect {
*/
@Override
public void resolve(SpellAbility sa) {
Card host = sa.getHostCard();
Game game = host.getGame();
Card object1 = null;
Card object2 = null;
final TargetRestrictions tgt = sa.getTargetRestrictions();
List<Card> tgts = tgt == null ? new ArrayList<>() : Lists.newArrayList(sa.getTargets().getTargetCards());
if (tgts.size() > 0) {
object1 = tgts.get(0);
List<Card> tgts = null;
if (sa.usesTargeting()) {
tgts = Lists.newArrayList(sa.getTargets().getTargetCards());
if (tgts.size() > 0) {
object1 = tgts.get(0);
}
}
if (sa.hasParam("Defined")) {
final List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
final List<Card> cards = AbilityUtils.getDefinedCards(host, sa.getParam("Defined"), sa);
object2 = cards.isEmpty() ? null : cards.get(0);
if (cards.size() > 1 && sa.hasParam("BothDefined")) {
if (cards.size() > 1 && !sa.usesTargeting()) {
object1 = cards.get(1);
}
} else if (tgts.size() > 1) {
@@ -73,7 +86,16 @@ public class ControlExchangeEffect extends SpellAbilityEffect {
return;
}
final long tStamp = sa.getActivatingPlayer().getGame().getNextTimestamp();
if (sa.hasParam("Optional")) {
if (!sa.getActivatingPlayer().getController().confirmAction(sa, null,
Localizer.getInstance().getMessage("lblExchangeControl",
CardTranslation.getTranslatedName(object1.getName()),
CardTranslation.getTranslatedName(object2.getName())))) {
return;
}
}
final long tStamp = game.getNextTimestamp();
object2.setController(player1, tStamp);
object1.setController(player2, tStamp);
if (sa.hasParam("RememberExchanged")) {

View File

@@ -1056,29 +1056,26 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
final Card c = (Card) entity;
CardCollection pl = AbilityUtils.getDefinedCards(getHostCard(), getParam("TargetsWithSharedCardType"), this);
for (final Card crd : pl) {
if (!c.sharesCardTypeWith(crd)) {
return false;
// one of those types
if (hasParam("TargetsWithSharedTypes")) {
boolean flag = false;
for (final String type : getParam("TargetsWithSharedTypes").split(",")) {
if (c.getType().hasStringType(type) && crd.getType().hasStringType(type)) {
flag = true;
break;
}
}
if (!flag) {
return false;
}
} else {
if (!c.sharesCardTypeWith(crd)) {
return false;
}
}
}
}
if (hasParam("TargetsWithSharedTypes") && entity instanceof Card) {
final Card c = (Card) entity;
final SpellAbility parent = getParentTargetingCard();
final Card parentTargeted = parent != null ? parent.getTargetCard() : null;
if (parentTargeted == null) {
return false;
}
boolean flag = false;
for (final String type : getParam("TargetsWithSharedTypes").split(",")) {
if (c.getType().hasStringType(type) && parentTargeted.getType().hasStringType(type)) {
flag = true;
break;
}
}
if (!flag) {
return false;
}
}
if (hasParam("TargetsWithControllerProperty") && entity instanceof Card) {
final String prop = getParam("TargetsWithControllerProperty");
final Card c = (Card) entity;
@@ -1172,6 +1169,16 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
}
}
if (tr.isWithSameCardType()) {
if (entity instanceof Card) {
for (final Card c : targetChosen.getTargetCards()) {
if (entity != c && !c.sharesCardTypeWith((Card) entity)) {
return false;
}
}
}
}
String[] validTgt = tr.getValidTgts();
if (entity instanceof GameEntity) {
GameEntity e = (GameEntity)entity;

View File

@@ -65,6 +65,7 @@ public class TargetRestrictions {
private boolean sameController = false;
private boolean withoutSameCreatureType = false;
private boolean withSameCreatureType = false;
private boolean withSameCardType = false;
private boolean singleTarget = false;
private boolean randomTarget = false;
@@ -108,6 +109,7 @@ public class TargetRestrictions {
this.sameController = target.isSameController();
this.withoutSameCreatureType = target.isWithoutSameCreatureType();
this.withSameCreatureType = target.isWithSameCreatureType();
this.withSameCardType = target.isWithSameCardType();
this.singleTarget = target.isSingleTarget();
this.randomTarget = target.isRandomTarget();
}
@@ -622,6 +624,20 @@ public class TargetRestrictions {
this.withSameCreatureType = b;
}
/**
* @return the withSameCardType
*/
public boolean isWithSameCardType() {
return withSameCardType;
}
/**
* @param b the withSameCardType to set
*/
public void setWithSameCardType(boolean b) {
this.withSameCardType = b;
}
/**
* <p>
* copy.

View File

@@ -5,9 +5,7 @@ T:Mode$ PlaneswalkedTo | ValidCard$ Card.Self | Execute$ TrigLife | OptionalDeci
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigLife | TriggerZones$ Command | Secondary$ True | OptionalDecider$ You | TriggerDescription$ When you planeswalk to CARDNAME or at the beginning of your upkeep, you may exchange life totals with target player.
SVar:TrigLife:DB$ ExchangeLife | Optional$ True | ValidTgts$ Player | TgtPrompt$ Select target player to exchange life totals with
T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll {CHAOS}, exchange control of two target permanents that share a card type.
SVar:RolledChaos:DB$ Pump | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | SubAbility$ DBExchange
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent | TgtPrompt$ Select target permanent card | TargetsWithSharedTypes$ Creature,Artifact,Enchantment,Planeswalker,Land,Tribal | TargetUnique$ True
SVar:RolledChaos:DB$ ExchangeControl | TargetMin$ 2 | TargetMax$ 2 | ValidTgts$ Permanent | TgtPrompt$ Select target permanents that share a permanent type | TargetsWithSameCardType$ True
AI:RemoveDeck:All
AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/cliffside_market.jpg
Oracle:When you planeswalk to Cliffside Market or at the beginning of your upkeep, you may exchange life totals with target player.\nWhenever you roll {CHAOS}, exchange control of two target permanents that share a card type.

View File

@@ -4,5 +4,4 @@ Types:Enchantment
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Artifact,Creature,Enchantment | TriggerZones$ Battlefield | Execute$ TrigExchangeControl | TriggerDescription$ Whenever an artifact, creature, or enchantment enters the battlefield, its controller chooses target permanent another player controls that shares a card type with it. Exchange control of those permanents.
SVar:TrigExchangeControl:DB$ ExchangeControl | Defined$ TriggeredCard | TargetingPlayer$ TriggeredCardController | TargetsWithDefinedController$ NonTriggeredCardController | ValidTgts$ Permanent | TargetsWithSharedCardType$ TriggeredCard
AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/confusion_in_the_ranks.jpg
Oracle:Whenever an artifact, creature, or enchantment enters the battlefield, its controller chooses target permanent another player controls that shares a card type with it. Exchange control of those permanents.

View File

@@ -4,8 +4,7 @@ Types:Creature Human Rogue
PT:2/3
T:Mode$ Untaps | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigExchangeControl | OptionalDecider$ You | TriggerDescription$ Inspired — Whenever CARDNAME becomes untapped, you may exchange control of target nonland permanent you control and target permanent an opponent controls that shares a card type with it.
SVar:TrigExchangeControl:DB$ Pump | ValidTgts$ Permanent.YouCtrl+nonLand | TgtPrompt$ Select target nonland permanent you control | SubAbility$ DBExchange
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent.OppCtrl | TgtPrompt$ Select target permanent an opponent controls that shares a card type with it | TargetsWithSharedTypes$ Creature,Artifact,Enchantment,Planeswalker,Tribal
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent.OppCtrl | TgtPrompt$ Select target permanent an opponent controls that shares a card type with it | TargetsWithSharedCardType$ ParentTarget
AI:RemoveDeck:All
AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/daring_thief.jpg
Oracle:Inspired — Whenever Daring Thief becomes untapped, you may exchange control of target nonland permanent you control and target permanent an opponent controls that shares a card type with it.

View File

@@ -2,9 +2,8 @@ Name:Gauntlets of Chaos
ManaCost:5
Types:Artifact
A:AB$ Pump | Cost$ 5 Sac<1/CARDNAME> | ValidTgts$ Artifact.YouCtrl,Creature.YouCtrl,Land.YouCtrl | TgtPrompt$ target artifact, creature, or land you control | StackDescription$ None | SubAbility$ DBExchange | SpellDescription$ Exchange control of target artifact, creature, or land you control and target permanent an opponent controls that shares one of those types with it. If those permanents are exchanged this way, destroy all Auras attached to them.
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent.OppCtrl | TgtPrompt$ Select target permanent an opponent controls that shares one of those types | TargetsWithSharedTypes$ Artifact,Creature,Land | RememberExchanged$ True | SubAbility$ DBDestroyAll
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent.OppCtrl | TgtPrompt$ Select target permanent an opponent controls that shares one of those types | TargetsWithSharedCardType$ ParentTarget | TargetsWithSharedTypes$ Artifact,Creature,Land | RememberExchanged$ True | SubAbility$ DBDestroyAll
SVar:DBDestroyAll:DB$ DestroyAll | ValidCards$ Aura.AttachedTo Card.IsRemembered | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/gauntlets_of_chaos.jpg
Oracle:{5}, Sacrifice Gauntlets of Chaos: Exchange control of target artifact, creature, or land you control and target permanent an opponent controls that shares one of those types with it. If those permanents are exchanged this way, destroy all Auras attached to them.

View File

@@ -3,16 +3,15 @@ ManaCost:3 U
Types:Sorcery
A:SP$ ChooseCard | Cost$ 3 U | ValidTgts$ Player | Choices$ Creature.cmcEQY | TargetControls$ True | References$ Y | Mandatory$ True | AILogic$ WorstCard | RememberChosen$ True | SubAbility$ DBChooseCreatureYou | SpellDescription$ You and target player exchange control of the creature you each control with the highest converted mana cost. Then exchange control of artifacts the same way. If two or more permanents a player controls are tied for highest cost, their controller chooses one of them.
SVar:DBChooseCreatureYou:DB$ ChooseCard | Choices$ Creature.YouCtrl+cmcEQX | References$ X | Mandatory$ True | RememberChosen$ True | SubAbility$ DBExchangeCreature
SVar:DBExchangeCreature:DB$ ExchangeControl | BothDefined$ True | Defined$ Remembered | SubAbility$ DBCleanCreature
SVar:DBExchangeCreature:DB$ ExchangeControl | Defined$ Remembered | SubAbility$ DBCleanCreature
SVar:DBCleanCreature:DB$ Cleanup | ClearRemembered$ True | SubAbility$ DBChooseArtifactYou
SVar:DBChooseArtifactYou:DB$ ChooseCard | Choices$ Artifact.YouCtrl+cmcEQZ | References$ Z | Mandatory$ True | RememberChosen$ True | SubAbility$ DBChooseArtifactOpp
SVar:DBChooseArtifactOpp:DB$ ChooseCard | Defined$ ParentTarget | Choices$ Artifact.cmcEQW | TargetControls$ True | References$ W | Mandatory$ True | AILogic$ WorstCard | RememberChosen$ True | SubAbility$ DBExchangeArtifact
SVar:DBExchangeArtifact:DB$ ExchangeControl | BothDefined$ True | Defined$ Remembered | SubAbility$ DBCleanup
SVar:DBExchangeArtifact:DB$ ExchangeControl | Defined$ Remembered | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Count$HighestCMC_Creature.YouCtrl+inZoneBattlefield
SVar:Y:Count$HighestCMC_Creature.TargetedPlayerCtrl+inZoneBattlefield
SVar:Z:Count$HighestCMC_Artifact.YouCtrl+inZoneBattlefield
SVar:W:Count$HighestCMC_Artifact.TargetedPlayerCtrl+inZoneBattlefield
AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/juxtapose.jpg
Oracle:You and target player exchange control of the creature you each control with the highest converted mana cost. Then exchange control of artifacts the same way. If two or more permanents a player controls are tied for highest cost, their controller chooses one of them.

View File

@@ -5,7 +5,7 @@ HandLifeModifier:-1/+8
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ TrigExchangeChoose | TriggerDescription$ At the beginning of your upkeep, exchange control of a permanent you control chosen at random and a permanent target opponent controls chosen at random.
SVar:TrigExchangeChoose:DB$ ChooseCard | ValidTgts$ Opponent | Choices$ Permanent.TargetedPlayerCtrl | AtRandom$ True | Amount$ 1 | RememberChosen$ True | SubAbility$ ChooseYou
SVar:ChooseYou:DB$ ChooseCard | Choices$ Permanent.YouCtrl | Amount$ 1 | AtRandom$ True | RememberChosen$ True | SubAbility$ DBExchange
SVar:DBExchange:DB$ ExchangeControl | Defined$ Remembered | BothDefined$ True | SubAbility$ DBCleanup
SVar:DBExchange:DB$ ExchangeControl | Defined$ Remembered | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:Picture:https://downloads.cardforge.org/images/cards/VAN/Karona, False God Avatar.full.jpg
Oracle:Hand -1, life +8\nAt the beginning of your upkeep, exchange control of a permanent you control chosen at random and a permanent target opponent controls chosen at random.

View File

@@ -2,7 +2,7 @@ Name:Legerdemain
ManaCost:2 U U
Types:Sorcery
A:SP$ Pump | Cost$ 2 U U | ValidTgts$ Artifact,Creature | TgtPrompt$ target artifact or creature | StackDescription$ None | SubAbility$ DBExchange | SpellDescription$ Exchange control of target artifact or creature and another target permanent that shares one of those types with it. (This effect lasts indefinitely.)
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent | TgtPrompt$ Select target permanent that shares one of those types | TargetsWithSharedTypes$ Artifact,Creature | TargetUnique$ True
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent | TgtPrompt$ Select target permanent that shares one of those types | TargetsWithSharedCardType$ ParentTarget | TargetsWithSharedTypes$ Artifact,Creature | TargetUnique$ True
AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/legerdemain.jpg
Oracle:Exchange control of target artifact or creature and another target permanent that shares one of those types with it. (This effect lasts indefinitely.)

View File

@@ -1,8 +1,7 @@
Name:Role Reversal
ManaCost:U U R
Types:Sorcery
A:SP$ Pump | Cost$ U U R | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | SubAbility$ DBExchange | StackDescription$ None | SpellDescription$ Exchange control of two target permanents that share a permanent type.
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent | TgtPrompt$ Select target permanent shares a card type with it | TargetsWithSharedTypes$ Creature,Artifact,Enchantment,Planeswalker,Land | TargetUnique$ True
A:SP$ ExchangeControl | Cost$ U U R | TargetMin$ 2 | TargetMax$ 2 | ValidTgts$ Permanent | TgtPrompt$ Select target permanents that share a permanent type | TargetsWithSameCardType$ True | SpellDescription$ Exchange control of two target permanents that share a permanent type.
AI:RemoveDeck:All
AI:RemoveDeck:Random
Oracle:Exchange control of two target permanents that share a permanent type.

View File

@@ -1,9 +1,7 @@
Name:Shifting Loyalties
ManaCost:5 U
Types:Sorcery
A:SP$ Pump | Cost$ 5 U | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | SubAbility$ DBExchange | StackDescription$ None | SpellDescription$ Exchange control of two target permanents that share a card type.
SVar:DBExchange:DB$ ExchangeControl | Defined$ ParentTarget | ValidTgts$ Permanent | TgtPrompt$ Select target permanent shares a card type with it | TargetsWithSharedTypes$ Creature,Artifact,Enchantment,Planeswalker,Land,Tribal | TargetUnique$ True
A:SP$ ExchangeControl | Cost$ 5 U | TargetMin$ 2 | TargetMax$ 2 | ValidTgts$ Permanent | TgtPrompt$ Select target permanents that share a permanent type | TargetsWithSameCardType$ True | SpellDescription$ Exchange control of two target permanents that share a card type.
AI:RemoveDeck:All
AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/shifting_loyalties.jpg
Oracle:Exchange control of two target permanents that share a card type. (Artifact, creature, enchantment, land, and planeswalker are card types.)

View File

@@ -0,0 +1,11 @@
Name:The Trickster-God's Heist
ManaCost:2 U B
Types:Enchantment Saga
K:Saga:3:DBCreature,DBNonCreature,DBDrain
SVar:DBCreature:DB$ ExchangeControl | ValidTgts$ Creature | TargetMin$ 2 | TargetMax$ 2 | TgtPrompt$ Choose two target creatures | Optional$ True | AILogic$ TrigTwoTargets | StackDescription$ SpellDescription | SpellDescription$ You may exchange control of two target creatures.
SVar:DBNonCreature:DB$ ExchangeControl | ValidTgts$ Card.nonBasic+nonCreature | TargetMin$ 2 | TargetMax$ 2 | ValidTgts$ Permanent | TgtPrompt$ Choose two target nonbasic, noncreature permanent | TargetsWithSameCardType$ True | Optional$ True | AILogic$ TrigTwoTargets | StackDescription$ SpellDescription | SpellDescription$ You may exchange control of two target nonbasic, noncreature permanents that share a card type.
SVar:DBDrain:DB$ LoseLife | ValidTgts$ Player | TgtPrompt$ Select a player | LifeAmount$ 3 | SubAbility$ DBGainLife | SpellDescription$ Target player loses 3 life and you gain 3 life.
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 3
DeckHas:Ability$LifeGain
AI:RemoveDeck:Random
Oracle:I - You may exchange control of two target creatures.\nII - You may exchange control of two target nonbasic, noncreature permanents that share a card type.\nIII - Target player loses 3 life and you gain 3 life.

View File

@@ -1769,6 +1769,8 @@ lblWinsClash=gewinnt Fehde
lblLosesClash=verliert Fehde
#CloneEffect.java
lblDoYouWantCopy=Möchtest du {0} kopieren?
#ControlExchangeEffect.java
lblExchangeControl=Do you want to exchange control of {0} and {1}?
#ControlExchangeVariantEffect.java
lblChooseCards=Wähle Karten
#CopyPermanentEffect.java

View File

@@ -1769,6 +1769,8 @@ lblWinsClash=wins clash
lblLosesClash=loses clash
#CloneEffect.java
lblDoYouWantCopy=Do you want to copy {0}?
#ControlExchangeEffect.java
lblExchangeControl=Do you want to exchange control of {0} and {1}?
#ControlExchangeVariantEffect.java
lblChooseCards=Choose cards
#CopyPermanentEffect.java

View File

@@ -1769,6 +1769,8 @@ lblWinsClash=gana el enfrentamiento
lblLosesClash=pierde el enfrentamiento
#CloneEffect.java
lblDoYouWantCopy=¿Quieres copiar {0}?
#ControlExchangeEffect.java
lblExchangeControl=¿Quieres intercambiar de {0} y {1}?
#ControlExchangeVariantEffect.java
lblChooseCards=Elige las cartas
#CopyPermanentEffect.java

View File

@@ -1769,6 +1769,8 @@ lblWinsClash=wins clash
lblLosesClash=loses clash
#CloneEffect.java
lblDoYouWantCopy=Do you want to copy {0}?
#ControlExchangeEffect.java
lblExchangeControl=Do you want to exchange control of {0} and {1}?
#ControlExchangeVariantEffect.java
lblChooseCards=Choose cards
#CopyPermanentEffect.java

View File

@@ -1769,6 +1769,8 @@ lblWinsClash=比点赢了
lblLosesClash=比点输了
#CloneEffect.java
lblDoYouWantCopy=你想要复制{0}吗?
#ControlExchangeEffect.java
lblExchangeControl=Do you want to exchange control of {0} and {1}?
#ControlExchangeVariantEffect.java
lblChooseCards=选择牌
#CopyPermanentEffect.java