Different names rework (#8823)

* turn CardChangedName into record

* Add CardLists.getDifferentNamesCount

* CostDiscard: rename to +WithDifferentNames

* CostSacrifice: use getDifferentNamesCount

* Refactor DifferentCardNames_
This commit is contained in:
Hans Mackowiak
2025-10-04 15:36:17 +02:00
committed by GitHub
parent 66a8e1f04f
commit 7acfe6c240
27 changed files with 80 additions and 87 deletions

View File

@@ -113,7 +113,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
randomSubset = ability.getActivatingPlayer().getController().orderMoveToZoneList(randomSubset, ZoneType.Graveyard, ability);
}
return PaymentDecision.card(randomSubset);
} else if (type.equals("DifferentNames")) {
} else if (type.contains("+WithDifferentNames")) {
CardCollection differentNames = new CardCollection();
CardCollection discardMe = CardLists.filter(hand, CardPredicates.hasSVar("DiscardMe"));
while (c > 0) {

View File

@@ -43,7 +43,6 @@ import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AbilityUtils {
private final static ImmutableList<String> cmpList = ImmutableList.of("LT", "LE", "EQ", "GE", "GT", "NE");
@@ -2889,21 +2888,6 @@ public class AbilityUtils {
return max;
}
if (sq[0].startsWith("DifferentCardNames_")) {
final List<String> crdname = Lists.newArrayList();
final String restriction = l[0].substring(19);
CardCollection list = CardLists.getValidCards(game.getCardsInGame(), restriction, player, c, ctb);
// TODO rewrite with sharesName to respect Spy Kit
for (final Card card : list) {
String name = card.getName();
// CR 201.2b Those objects have different names only if each of them has at least one name and no two objects in that group have a name in common
if (!crdname.contains(name) && !name.isEmpty()) {
crdname.add(name);
}
}
return doXMath(crdname.size(), expr, c, ctb);
}
if (sq[0].startsWith("MostProminentCreatureType")) {
String restriction = l[0].split(" ")[1];
CardCollection list = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), restriction, player, c, ctb);
@@ -3760,6 +3744,10 @@ public class AbilityUtils {
return CardUtil.getColorsFromCards(paidList).countColors();
}
if (string.equals("DifferentCardNames")) {
return CardLists.getDifferentNamesCount(paidList);
}
if (string.equals("DifferentColorPair")) {
final Set<ColorSet> diffPair = new HashSet<>();
for (final Card card : paidList) {

View File

@@ -965,7 +965,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
String name = state.getName();
for (CardChangedName change : this.changedCardNames.values()) {
if (change.isOverwrite()) {
name = change.getNewName();
name = change.newName();
}
}
return alt ? StaticData.instance().getCommonCards().getName(name, true) : name;
@@ -980,7 +980,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
for (CardChangedName change : this.changedCardNames.values()) {
if (change.isOverwrite()) {
result = false;
} else if (change.isAddNonLegendaryCreatureNames()) {
} else if (change.addNonLegendaryCreatureNames()) {
result = true;
}
}
@@ -1013,6 +1013,12 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
currentState.getView().updateName(currentState);
}
private record CardChangedName(String newName, boolean addNonLegendaryCreatureNames) {
public boolean isOverwrite() {
return newName != null;
}
}
public void setGamePieceType(GamePieceType gamePieceType) {
this.gamePieceType = gamePieceType;
this.view.updateGamePieceType(this);

View File

@@ -1,24 +0,0 @@
package forge.game.card;
public class CardChangedName {
protected String newName;
protected boolean addNonLegendaryCreatureNames = false;
public CardChangedName(String newName, boolean addNonLegendaryCreatureNames) {
this.newName = newName;
this.addNonLegendaryCreatureNames = addNonLegendaryCreatureNames;
}
public String getNewName() {
return newName;
}
public boolean isOverwrite() {
return newName != null;
}
public boolean isAddNonLegendaryCreatureNames() {
return addNonLegendaryCreatureNames;
}
}

View File

@@ -26,12 +26,17 @@ import forge.game.spellability.TargetRestrictions;
import forge.game.staticability.StaticAbilityTapPowerValue;
import forge.util.IterableUtil;
import forge.util.MyRandom;
import forge.util.StreamUtil;
import forge.util.collect.FCollectionView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collector;
import java.util.stream.Collectors;
/**
* <p>
@@ -480,4 +485,26 @@ public class CardLists {
// (b) including the last element
return isSubsetSum(numList, sum) || isSubsetSum(numList, sum - last);
}
public static int getDifferentNamesCount(Iterable<Card> cardList) {
// first part the ones with SpyKit, and already collect them via
Map<Boolean, List<Card>> parted = StreamUtil.stream(cardList).collect(Collectors
.partitioningBy(Card::hasNonLegendaryCreatureNames, Collector.of(ArrayList::new, (list, c) -> {
if (!c.hasNoName() && list.stream().noneMatch(c2 -> c.sharesNameWith(c2))) {
list.add(c);
}
}, (l1, l2) -> {
l1.addAll(l2);
return l1;
})));
List<Card> preList = parted.get(Boolean.FALSE);
// then try to apply the SpyKit ones
for (Card c : parted.get(Boolean.TRUE)) {
if (preList.stream().noneMatch(c2 -> c.sharesNameWith(c2))) {
preList.add(c);
}
}
return preList.size();
}
}

View File

@@ -18,7 +18,6 @@
package forge.game.cost;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import forge.game.ability.AbilityKey;
import forge.game.card.*;
import forge.game.player.Player;
@@ -29,7 +28,6 @@ import forge.util.TextUtil;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* The Class CostDiscard.
@@ -63,11 +61,20 @@ public class CostDiscard extends CostPartWithList {
public Integer getMaxAmountX(SpellAbility ability, Player payer, final boolean effect) {
final Card source = ability.getHostCard();
String type = this.getType();
boolean differentNames = false;
if (type.contains("+WithDifferentNames")) {
type = type.replace("+WithDifferentNames", "");
differentNames = true;
}
CardCollectionView handList = payer.canDiscardBy(ability, effect) ? payer.getCardsIn(ZoneType.Hand) : CardCollection.EMPTY;
if (!type.equals("Random")) {
handList = CardLists.getValidCards(handList, type.split(";"), payer, source, ability);
}
if (differentNames) {
return CardLists.getDifferentNamesCount(handList);
}
return handList.size();
}
@@ -92,7 +99,7 @@ public class CostDiscard extends CostPartWithList {
else if (this.getType().equals("LastDrawn")) {
sb.append("the last card you drew this turn");
}
else if (this.getType().equals("DifferentNames")) {
else if (this.getType().contains("+WithDifferentNames")) {
sb.append(Cost.convertAmountTypeToWords(i, this.getAmount(), "Card")).append(" with different names");
}
else {
@@ -145,21 +152,17 @@ public class CostDiscard extends CostPartWithList {
final Card c = payer.getLastDrawnCard();
return handList.contains(c);
}
else if (type.equals("DifferentNames")) {
Set<String> cardNames = Sets.newHashSet();
for (Card c : handList) {
if (!c.hasNoName()) {
cardNames.add(c.getName());
}
}
return cardNames.size() >= amount;
}
else {
boolean sameName = false;
boolean differentNames = false;
if (type.contains("+WithSameName")) {
sameName = true;
type = TextUtil.fastReplace(type, "+WithSameName", "");
}
if (type.contains("+WithDifferentNames")) {
type = type.replace("+WithDifferentNames", "");
differentNames = true;
}
if (type.contains("ChosenColor") && !source.hasChosenColor()) {
//color hasn't been chosen yet, so skip getValidCards
} else if (!type.equals("Random") && !type.contains("X")) {
@@ -173,6 +176,10 @@ public class CostDiscard extends CostPartWithList {
}
}
return false;
} else if (differentNames) {
if (CardLists.getDifferentNamesCount(handList) < amount) {
return false;
}
}
int adjustment = 0;
if (source.isInZone(ZoneType.Hand) && payer.equals(source.getOwner())) {

View File

@@ -17,7 +17,6 @@
*/
package forge.game.cost;
import com.google.common.collect.Sets;
import forge.card.CardType;
import forge.game.Game;
import forge.game.ability.AbilityKey;
@@ -31,7 +30,6 @@ import forge.game.zone.ZoneType;
import forge.util.Lang;
import java.util.Map;
import java.util.Set;
/**
* The Class CostSacrifice.
@@ -74,16 +72,7 @@ public class CostSacrifice extends CostPartWithList {
}
typeList = CardLists.filter(typeList, CardPredicates.canBeSacrificedBy(ability, effect));
if (differentNames) {
// TODO rewrite with sharesName to respect Spy Kit
final Set<String> crdname = Sets.newHashSet();
for (final Card card : typeList) {
String name = card.getName();
// CR 201.2b Those objects have different names only if each of them has at least one name and no two objects in that group have a name in common
if (!card.hasNoName()) {
crdname.add(name);
}
}
return crdname.size();
return CardLists.getDifferentNamesCount(typeList);
}
return typeList.size();
}

View File

@@ -3,5 +3,5 @@ ManaCost:3
Types:Artifact
A:AB$ Mana | Cost$ T | Produced$ Any | SpellDescription$ Add one mana of any color.
A:AB$ Draw | Cost$ 7 T Sac<1/CARDNAME> | NumCards$ X | SpellDescription$ Draw X cards, where X is the number of differently named lands you control.
SVar:X:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield
SVar:X:Count$Valid Land.YouCtrl$DifferentCardNames
Oracle:{T}: Add one mana of any color.\n{7}, {T}, Sacrifice this artifact: Draw X cards, where X is the number of differently named lands you control.

View File

@@ -3,7 +3,7 @@ ManaCost:2 G
Types:Sorcery
A:SP$ Token | TokenScript$ g_0_1_plant | SubAbility$ DBDraw | SpellDescription$ Create a 0/1 green Plant creature token, then draw cards equal to the number of differently named creature tokens you control.
SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ X | StackDescription$ None
SVar:X:Count$DifferentCardNames_Creature.YouCtrl+token+inZoneBattlefield
SVar:X:Count$Valid Creature.YouCtrl+token$DifferentCardNames
DeckHas:Ability$Token & Type$Plant
DeckHints:Ability$Token
Oracle:Create a 0/1 green Plant creature token, then draw cards equal to the number of differently named creature tokens you control.

View File

@@ -3,5 +3,5 @@ ManaCost:4
Types:Artifact Creature Golem
PT:*/*
S:Mode$ Continuous | CharacteristicDefining$ True | SetPower$ X | SetToughness$ X | Description$ CARDNAME's power and toughness are each equal to the number of differently named lands you control.
SVar:X:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield
SVar:X:Count$Valid Land.YouCtrl$DifferentCardNames
Oracle:Awakened Amalgam's power and toughness are each equal to the number of differently named lands you control.

View File

@@ -2,7 +2,7 @@ Name:Eerie Ultimatum
ManaCost:W W B B B G G
Types:Sorcery
A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Permanent.YouOwn | ChangeNumDesc$ any number of | ChangeTypeDesc$ permanent cards with different names | DifferentNames$ True | ChangeNum$ X | Hidden$ True | SpellDescription$ Return any number of permanent cards with different names from your graveyard to the battlefield.
SVar:X:Count$DifferentCardNames_Permanent.YouOwn+inZoneGraveyard
SVar:X:Count$ValidGraveyard Permanent.YouOwn$DifferentCardNames
SVar:IsReanimatorCard:TRUE
DeckHas:Ability$Graveyard
Oracle:Return any number of permanent cards with different names from your graveyard to the battlefield.

View File

@@ -4,7 +4,7 @@ Types:Legendary Creature Treefolk Wizard
PT:6/6
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters, create a number of 1/1 blue Human Wizard creature tokens equal to the number of differently named lands you control.
SVar:TrigToken:DB$ Token | TokenAmount$ X | TokenScript$ u_1_1_human_wizard
SVar:X:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield
SVar:X:Count$Valid Land.YouCtrl$DifferentCardNames
A:AB$ Draw | Cost$ 4 G U | NumCards$ Y | SubAbility$ PumpAll | SpellDescription$ Draw a card for each Wizard you control. They each get +1/+1 until end of turn for each card in your hand.
SVar:Y:Count$Valid Wizard.YouCtrl
SVar:PumpAll:DB$ PumpAll | ValidCards$ Wizard.YouCtrl | NumAtt$ +Z | NumDef$ +Z

View File

@@ -6,6 +6,6 @@ SVar:ETBTapped:DB$ Tap | Defined$ Self | ETB$ True
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self,Land.Other+YouCtrl | CheckSVar$ X | SVarCompare$ GE7 | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME or another land you control enters, if you control seven or more lands with different names, create a 2/2 black Zombie creature token.
SVar:TrigToken:DB$ Token | TokenScript$ b_2_2_zombie | TokenOwner$ You | TokenAmount$ 1
SVar:X:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield
SVar:X:Count$Valid Land.YouCtrl$DifferentCardNames
DeckHas:Ability$Token
Oracle:Field of the Dead enters tapped.\n{T}: Add {C}.\nWhenever Field of the Dead or another land you control enters, if you control seven or more lands with different names, create a 2/2 black Zombie creature token.

View File

@@ -3,5 +3,5 @@ ManaCost:6 G
Types:Creature Fungus Beast
PT:5/5
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ X | EffectZone$ All | Description$ This spell costs {X} less to cast, where X is the number of differently named lands you control.
SVar:X:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield
SVar:X:Count$Valid Land.YouCtrl$DifferentCardNames
Oracle:This spell costs {X} less to cast, where X is the number of differently named lands you control.

View File

@@ -7,7 +7,7 @@ T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefiel
SVar:TrigToken:DB$ Token | TokenScript$ r_0_0_a_gremlin | RememberTokens$ True | SubAbility$ DBCounters
SVar:DBCounters:DB$ PutCounter | Defined$ Remembered | CounterType$ P1P1 | CounterNum$ X | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Count$DifferentCardNames_Artifact.YouCtrl+inZoneBattlefield+token
SVar:X:Count$Valid Artifact.YouCtrl+token$DifferentCardNames
DeckHas:Ability$Token|Counters
DeckHints:Type$Artifact & Ability$Token
Oracle:Artifact creatures you control have trample.\nAt the beginning of your end step, create a 0/0 red Gremlin artifact creature token. Put X +1/+1 counters on it, where X is the number of differently named artifact tokens you control.

View File

@@ -3,7 +3,7 @@ ManaCost:3 B B
Types:Enchantment
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ DBWin | TriggerZones$ Battlefield | CheckSVar$ Contractors | SVarCompare$ GE4 | TriggerDescription$ At the beginning of your upkeep, if you control four or more Demons with different names, you win the game.
SVar:DBWin:DB$ WinsGame | Defined$ You | ConditionCheckSVar$ Contractors | ConditionSVarCompare$ GE4
SVar:Contractors:Count$DifferentCardNames_Demon.YouCtrl+inRealZoneBattlefield
SVar:Contractors:Count$Valid Demon.YouCtrl$DifferentCardNames
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME enters, you draw four cards and you lose 4 life.
SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 4 | SubAbility$ DBLoseLife
SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ 4

View File

@@ -6,6 +6,6 @@ SVar:ETBTapped:DB$ Tap | Defined$ Self | ETB$ True
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
A:AB$ ChangeZone | Cost$ 3 T Return<1/CARDNAME> | ChangeType$ Gate | ChangeNum$ 1 | Origin$ Library | Destination$ Battlefield | AILogic$ MazesEnd | SubAbility$ DBWin | SpellDescription$ Search your library for a Gate card, put it onto the battlefield, then shuffle. If you control ten or more Gates with different names, you win the game.
SVar:DBWin:DB$ WinsGame | Defined$ You | ConditionCheckSVar$ MazeGate | ConditionSVarCompare$ GE10
SVar:MazeGate:Count$DifferentCardNames_Gate.YouCtrl+inZoneBattlefield
SVar:X:Count$Valid Gate.YouCtrl$DifferentCardNames
AI:RemoveDeck:Random
Oracle:Maze's End enters tapped.\n{T}: Add {C}.\n{3}, {T}, Return Maze's End to its owner's hand: Search your library for a Gate card, put it onto the battlefield, then shuffle. If you control ten or more Gates with different names, you win the game.

View File

@@ -3,7 +3,7 @@ ManaCost:2
Types:Artifact
A:AB$ ChangeZone | Cost$ 3 T | Origin$ Library | Destination$ Hand | ChangeType$ Land.Basic,Land.Locus,Land.Sphere | ChangeTypeDesc$ basic, Sphere, or Locus land card | SpellDescription$ Search your library for a basic, Sphere, or Locus land card, reveal it, put it into your hand, then shuffle.
A:AB$ Animate | Cost$ 3 | CheckSVar$ CountAll | SVarCompare$ GE9 | Power$ 9 | Toughness$ 9 | Types$ Artifact,Creature,Phyrexian,Construct | RemoveCreatureTypes$ True | RemoveAllAbilities$ True | Defined$ Self | Keywords$ Indestructible & Toxic:9 | Duration$ Permanent | SpellDescription$ CARDNAME becomes a 9/9 Phyrexian Construct artifact creature, loses all abilities, and gains indestructible and toxic 9. Activate only if there are nine or more lands with different names among the basic, Sphere, and Locus lands you control.
SVar:CountAll:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield+Basic,Sphere.YouCtrl+inZoneBattlefield,Locus.YouCtrl+inZoneBattlefield
SVar:CountAll:Count$Valid Land.YouCtrl+Basic,Sphere.YouCtrl,Locus.YouCtrl$DifferentCardNames
DeckHas:Type$Phyrexian|Construct|Artifact
DeckNeeds:Type$Locus|Sphere
Oracle:{3}, {T}: Search your library for a basic, Sphere, or Locus land card, reveal it, put it into your hand, then shuffle.\n{3}: Monument to Perfection becomes a 9/9 Phyrexian Construct artifact creature, loses all abilities, and gains indestructible and toxic 9. Activate only if there are nine or more lands with different names among the basic, Sphere, and Locus lands you control.

View File

@@ -11,7 +11,7 @@ SVar:TrigExile:DB$ Dig | Defined$ You | DigNum$ X | ChangeNum$ All | Destination
SVar:DBEffectYou:DB$ Effect | RememberObjects$ Remembered | StaticAbilities$ STPlay | SubAbility$ DBCleanup | ForgetOnMoved$ Exile | Duration$ Permanent
SVar:STPlay:Mode$ Continuous | MayPlay$ True | Affected$ Card.IsRemembered | AffectedZone$ Exile | CheckSVar$ Y | Description$ During any turn you attacked with a commander, you may play those cards.
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Count$DifferentCardNames_Permanent.token+YouCtrl+inZoneBattlefield
SVar:X:Count$Valid Permanent.YouCtrl+token$DifferentCardNames
SVar:Y:Count$CreaturesAttackedThisTurn Creature.IsCommander+YouCtrl
SVar:HasAttackEffect:TRUE
Oracle:Flying,deathtouch\nWhen Neriv enters, create two 1/1 red Goblin creature tokens.\nWhenever Neriv attacks, exile a number of cards from the top of your library equal to the number of differently named tokens you control. During any turn you attacked with a commander, you may play those cards.

View File

@@ -5,6 +5,6 @@ PT:5/5
K:Flying
R:Event$ Draw | ActiveZones$ Battlefield | ValidPlayer$ You | IsPresent$ Card.YouOwn | PresentZone$ Library | PresentCompare$ EQ0 | ReplaceWith$ AddCounters | Description$ If you would draw a card while your library has no cards in it, instead put five +1/+1 counters on CARDNAME.
SVar:AddCounters:DB$ PutCounter | CounterType$ P1P1 | CounterNum$ 5 | Defined$ Self
A:AB$ Draw | Cost$ 1 U U Discard<3/DifferentNames> | NumCards$ 5 | SpellDescription$ Draw five cards.
A:AB$ Draw | Cost$ 1 U U Discard<3/Card+WithDifferentNames> | NumCards$ 5 | SpellDescription$ Draw five cards.
AI:RemoveDeck:All
Oracle:Flying\nIf you would draw a card while your library has no cards in it, instead put five +1/+1 counters on Ormos, Archive Keeper.\n{1}{U}{U}, Discard three cards with different names: Draw five cards.

View File

@@ -5,6 +5,6 @@ PT:4/4
K:Trample
T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ At the beginning of combat on your turn, bolster X, where X is the number of differently named artifact tokens you control. (Choose a creature with the least toughness among creatures you control and put X +1/+1 counters on it.)
SVar:TrigPutCounter:DB$ PutCounter | CounterType$ P1P1 | CounterNum$ X | Bolster$ True
SVar:X:Count$DifferentCardNames_Artifact.YouCtrl+token+inZoneBattlefield
SVar:X:Count$Valid Artifact.YouCtrl+token$DifferentCardNames
DeckHas:Ability$Counters
Oracle:Trample\nAt the beginning of combat on your turn, bolster X, where X is the number of differently named artifact tokens you control. (Choose a creature with the least toughness among creatures you control and put X +1/+1 counters on it.)

View File

@@ -8,6 +8,6 @@ SVar:TrigExile:DB$ Repeat | RepeatSubAbility$ DBExileCleanup | RepeatCheckSVar$
SVar:DBExileCleanup:DB$ Cleanup | ClearRemembered$ True | SubAbility$ DBExile
SVar:DBExile:DB$ Dig | Defined$ TriggeredTarget | DigNum$ 4 | ChangeNum$ All | DestinationZone$ Exile | RememberChanged$ True
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Count$DifferentCardNames_Card.IsRemembered
SVar:X:Remembered$DifferentCardNames
SVar:Y:Count$RememberedSize
Oracle:Flying (This creature can't be blocked except by creatures with flying or reach.)\nWhenever Scalpelexis deals combat damage to a player, that player exiles the top four cards of their library. If two or more of those cards have the same name, repeat this process.

View File

@@ -6,6 +6,6 @@ SVar:DBChoose:DB$ ChooseCard | Defined$ You | Amount$ 1 | AtRandom$ True | Choic
SVar:DBChange:DB$ ChangeZone | Origin$ Library | Destination$ Hand | Defined$ ChosenCard | StackDescription$ None | SubAbility$ DBShuffle | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ3
SVar:DBShuffle:DB$ Shuffle | Defined$ You | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Count$DifferentCardNames_Creature.IsRemembered
SVar:X:Remembered$DifferentCardNames
AI:RemoveDeck:All
Oracle:Search your library for three creature cards and reveal them. If you reveal three cards with different names, choose one of them at random and put that card into your hand. Shuffle the rest into your library.

View File

@@ -7,5 +7,5 @@ K:Hexproof
A:AB$ DealDamage | Cost$ 10 Sac<1/CARDNAME> | ValidTgts$ Any | NumDmg$ 3 | ReduceCost$ X | SubAbility$ DBDraw | SpellDescription$ It deals 3 damage to any target. Target player draws three cards and gains 3 life. This ability costs {X} less to activate, where X is the number of differently named lands you control.
SVar:DBDraw:DB$ Draw | NumCards$ 3 | ValidTgts$ Player | SubAbility$ DBGainLife
SVar:DBGainLife:DB$ GainLife | Defined$ ParentTarget | LifeAmount$ 3
SVar:X:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield
SVar:X:Count$Valid Land.YouCtrl$DifferentCardNames
Oracle:Flying\nHexproof (This creature can't be the target of spells or abilities your opponents control.)\n{10}, Sacrifice this creature: It deals 3 damage to any target. Target player draws three cards and gains 3 life. This ability costs {X} less to activate, where X is the number of differently named lands you control.

View File

@@ -6,7 +6,7 @@ SVar:DBConjureAll:DB$ MakeCard | Conjure$ True | Names$ First Little Pig,Second
SVar:DBConjureTwo:DB$ MakeCard | Conjure$ True | SpellbookName$ the Three Pigs | Spellbook$ First Little Pig,Second Little Pig,Third Little Pig | SpellbookAmount$ 2 | RememberMade$ True | Zone$ Hand | SubAbility$ DBPutBattlefield
SVar:DBPutBattlefield:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | ChangeType$ Card.IsRemembered | ChangeNum$ 1 | Mandatory$ True | SelectPrompt$ Select a card to put onto the battlefield | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Count$DifferentCardNames_Boar.YouCtrl+inRealZoneBattlefield
SVar:X:Count$Valid Boar.YouCtrl$DifferentCardNames
DeckHints:Type$Boar
DeckHas:Type$Boar
Oracle:If you control three or more Boars with different names, conjure each card from the Three Pigs spellbook onto the battlefield.\nIf you control two or fewer Boars with different names, conjure two cards of your choice from the Three Pigs spellbook into your hand, then put one of them onto the battlefield.

View File

@@ -6,7 +6,7 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.Y
SVar:TrigBranch:DB$ Branch | BranchConditionSVar$ X | BranchConditionSVarCompare$ GE7 | TrueSubAbility$ DBZombie | FalseSubAbility$ DBPlant
SVar:DBPlant:DB$ Token | TokenAmount$ 1 | TokenScript$ g_0_1_plant | TokenOwner$ You
SVar:DBZombie:DB$ Token | TokenAmount$ 1 | TokenScript$ b_2_2_zombie | TokenOwner$ You
SVar:X:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield
SVar:X:Count$Valid Land.YouCtrl$DifferentCardNames
S:Mode$ Continuous | AffectedZone$ Graveyard | Affected$ Land.YouOwn | AddKeyword$ Dredge:2 | Description$ Land cards in your graveyard have dredge 2. (You may return a land card from your graveyard to your hand and mill two cards instead of drawing a card.)
DeckHas:Ability$Token & Type$Zombie
DeckHints:Ability$Mill

View File

@@ -113,7 +113,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
}
return PaymentDecision.card(randomSubset);
}
if (discardType.equals("DifferentNames")) {
if (discardType.contains("+WithDifferentNames")) {
final CardCollection discarded = new CardCollection();
while (c > 0) {
final InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 1, 1, hand, ability);