diff --git a/Mage.Sets/src/mage/cards/a/AberrantResearcher.java b/Mage.Sets/src/mage/cards/a/AberrantResearcher.java
index 54c1bd42d4d..c83c8588673 100644
--- a/Mage.Sets/src/mage/cards/a/AberrantResearcher.java
+++ b/Mage.Sets/src/mage/cards/a/AberrantResearcher.java
@@ -1,22 +1,22 @@
package mage.cards.a;
-import java.util.UUID;
-
import mage.MageInt;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.TransformAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.players.Player;
+import java.util.UUID;
+
/**
* @author fireshoes
*/
@@ -54,7 +54,7 @@ class AberrantResearcherEffect extends OneShotEffect {
public AberrantResearcherEffect() {
super(Outcome.Benefit);
- staticText = "put the top card of your library into your graveyard. If it's an instant or sorcery card, transform {this}";
+ staticText = "mill a card. If an instant or sorcery card was milled this way, transform {this}";
}
public AberrantResearcherEffect(final AberrantResearcherEffect effect) {
@@ -64,15 +64,16 @@ class AberrantResearcherEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null && controller.getLibrary().hasCards()) {
- Card card = controller.getLibrary().getFromTop(game);
- controller.moveCards(card, Zone.GRAVEYARD, source, game);
- if (card.isInstant() || card.isSorcery()) {
- new TransformSourceEffect(true).apply(game, source);
- }
- return true;
+ if (controller == null
+ || controller
+ .millCards(1, source, game)
+ .getCards(game)
+ .stream()
+ .noneMatch(MageObject::isInstantOrSorcery)) {
+ return false;
}
- return false;
+ new TransformSourceEffect(true).apply(game, source);
+ return true;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/a/AcolyteOfAffliction.java b/Mage.Sets/src/mage/cards/a/AcolyteOfAffliction.java
index 3a158f77787..58791c6deb2 100644
--- a/Mage.Sets/src/mage/cards/a/AcolyteOfAffliction.java
+++ b/Mage.Sets/src/mage/cards/a/AcolyteOfAffliction.java
@@ -53,8 +53,7 @@ class AcolyteOfAfflictionEffect extends OneShotEffect {
AcolyteOfAfflictionEffect() {
super(Outcome.Benefit);
- staticText = "put the top two cards of your library into your graveyard, " +
- "then you may return a permanent card from your graveyard to your hand.";
+ staticText = "mill two cards, then you may return a permanent card from your graveyard to your hand.";
}
private AcolyteOfAfflictionEffect(final AcolyteOfAfflictionEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/a/AltarOfDementia.java b/Mage.Sets/src/mage/cards/a/AltarOfDementia.java
index 0413e9b9605..339134c9b42 100644
--- a/Mage.Sets/src/mage/cards/a/AltarOfDementia.java
+++ b/Mage.Sets/src/mage/cards/a/AltarOfDementia.java
@@ -48,7 +48,7 @@ class AltarOfDementiaEffect extends OneShotEffect {
public AltarOfDementiaEffect() {
super(Outcome.Damage);
- staticText = "Target player puts a number of cards equal to the sacrificed creature's power from the top of their library into their graveyard";
+ staticText = "Target player mills cards equal to the sacrificed creature's power";
}
public AltarOfDementiaEffect(final AltarOfDementiaEffect effect) {
@@ -67,7 +67,7 @@ class AltarOfDementiaEffect extends OneShotEffect {
}
}
if (amount > 0) {
- player.moveCards(player.getLibrary().getTopCards(game, amount), Zone.GRAVEYARD, source, game);
+ player.millCards(amount, source, game);
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/b/BelltowerSphinx.java b/Mage.Sets/src/mage/cards/b/BelltowerSphinx.java
index 4ef63a42815..ed65fe16d84 100644
--- a/Mage.Sets/src/mage/cards/b/BelltowerSphinx.java
+++ b/Mage.Sets/src/mage/cards/b/BelltowerSphinx.java
@@ -85,6 +85,6 @@ class BelltowerSphinxEffect extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever a source deals damage to {this}, that source's controller puts that many cards from the top of their library into their graveyard.";
+ return "Whenever a source deals damage to {this}, that source's controller mills that many cards.";
}
}
diff --git a/Mage.Sets/src/mage/cards/b/BrokenAmbitions.java b/Mage.Sets/src/mage/cards/b/BrokenAmbitions.java
index b22f48055d2..297b9d1c58b 100644
--- a/Mage.Sets/src/mage/cards/b/BrokenAmbitions.java
+++ b/Mage.Sets/src/mage/cards/b/BrokenAmbitions.java
@@ -11,7 +11,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player;
@@ -45,7 +44,7 @@ public final class BrokenAmbitions extends CardImpl {
class BrokenAmbitionsEffect extends OneShotEffect {
- private static final String effectText = "Counter target spell unless its controller pays {X}. Clash with an opponent. If you win, that spell's controller puts the top four cards of their library into their graveyard";
+ private static final String effectText = "Counter target spell unless its controller pays {X}. Clash with an opponent. If you win, that spell's controller mills four cards";
protected Cost cost;
protected DynamicValue genericMana;
@@ -107,7 +106,7 @@ class BrokenAmbitionsEffect extends OneShotEffect {
game.informPlayers(player.getLogName() + " chooses to pay " + costValueMessage + " to prevent the counter effect");
if (ClashEffect.getInstance().apply(game, source)) {
- player.moveCards(player.getLibrary().getTopCards(game, 4), Zone.GRAVEYARD, source, game);
+ player.millCards(4, source, game);
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/c/CauldronsGift.java b/Mage.Sets/src/mage/cards/c/CauldronsGift.java
index 923e9568a8d..6d936425fff 100644
--- a/Mage.Sets/src/mage/cards/c/CauldronsGift.java
+++ b/Mage.Sets/src/mage/cards/c/CauldronsGift.java
@@ -47,8 +47,7 @@ class CauldronsGiftEffect extends OneShotEffect {
CauldronsGiftEffect() {
super(Outcome.Benefit);
staticText = "Adamant — If at least three black mana was spent to cast this spell, " +
- "put the top four cards of your library into your graveyard." +
- "
You may choose a creature card in your graveyard. " +
+ "mill four cards.
You may choose a creature card in your graveyard. " +
"If you do, return it to the battlefield with an additional +1/+1 counter on it.";
}
@@ -68,7 +67,7 @@ class CauldronsGiftEffect extends OneShotEffect {
return false;
}
if (AdamantCondition.BLACK.apply(game, source)) {
- player.moveCards(player.getLibrary().getTopCards(game, 4), Zone.GRAVEYARD, source, game);
+ player.millCards(4, source, game);
}
if (player.getGraveyard().count(StaticFilters.FILTER_CARD_CREATURE, game) == 0
|| !player.chooseUse(outcome, "Choose a creature card in your graveyard to return to the battlefield?", source, game)) {
diff --git a/Mage.Sets/src/mage/cards/c/CephalidVandal.java b/Mage.Sets/src/mage/cards/c/CephalidVandal.java
index 780863a404a..627b3c11a98 100644
--- a/Mage.Sets/src/mage/cards/c/CephalidVandal.java
+++ b/Mage.Sets/src/mage/cards/c/CephalidVandal.java
@@ -54,7 +54,7 @@ class CephalidVandalEffect extends OneShotEffect {
public CephalidVandalEffect() {
super(Outcome.Neutral);
- staticText = "Then put the top card of your library into your graveyard for each shred counter on {this}";
+ staticText = "Then mill a card for each shred counter on {this}";
}
public CephalidVandalEffect(final CephalidVandalEffect effect) {
@@ -72,7 +72,7 @@ class CephalidVandalEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null && controller != null) {
int amount = permanent.getCounters(game).getCount(CounterType.SHRED);
- controller.moveCards(controller.getLibrary().getTopCards(game, amount), Zone.GRAVEYARD, source, game);
+ controller.millCards(amount, source, game);
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java b/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java
index 97210ba99b0..d1e26d77506 100644
--- a/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java
+++ b/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java
@@ -43,7 +43,7 @@ class ChainsOfMephistophelesReplacementEffect extends ReplacementEffectImpl {
public ChainsOfMephistophelesReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
- staticText = "If a player would draw a card except the first one they draw in their draw step each turn, that player discards a card instead. If the player discards a card this way, they draw a card. If the player doesn't discard a card this way, they put the top card of their library into their graveyard";
+ staticText = "If a player would draw a card except the first one they draw in their draw step each turn, that player discards a card instead. If the player discards a card this way, they draw a card. If the player doesn't discard a card this way, they mill a card";
}
public ChainsOfMephistophelesReplacementEffect(final ChainsOfMephistophelesReplacementEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/c/ChancellorOfTheSpires.java b/Mage.Sets/src/mage/cards/c/ChancellorOfTheSpires.java
index 689fd0bf190..d575eb23c70 100644
--- a/Mage.Sets/src/mage/cards/c/ChancellorOfTheSpires.java
+++ b/Mage.Sets/src/mage/cards/c/ChancellorOfTheSpires.java
@@ -1,36 +1,33 @@
-
package mage.cards.c;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.ChancellorAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.PlayTargetWithoutPayingManaEffect;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.TargetController;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
-import mage.players.Player;
import mage.target.common.TargetCardInOpponentsGraveyard;
+import java.util.UUID;
+
/**
- *
* @author BetaSteward
*/
public final class ChancellorOfTheSpires extends CardImpl {
- private static final String abilityText = "at the beginning of the first upkeep, each opponent puts the top seven cards of their library into their graveyard";
+ private static final String abilityText = "at the beginning of the first upkeep, each opponent mills seven cards";
private static final FilterCard filter = new FilterCard("instant or sorcery card from an opponent's graveyard");
@@ -41,7 +38,7 @@ public final class ChancellorOfTheSpires extends CardImpl {
}
public ChancellorOfTheSpires(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}{U}");
this.subtype.add(SubType.SPHINX);
this.power = new MageInt(5);
@@ -58,7 +55,7 @@ public final class ChancellorOfTheSpires extends CardImpl {
this.addAbility(ability);
}
- public ChancellorOfTheSpires(final ChancellorOfTheSpires card) {
+ private ChancellorOfTheSpires(final ChancellorOfTheSpires card) {
super(card);
}
@@ -70,11 +67,11 @@ public final class ChancellorOfTheSpires extends CardImpl {
class ChancellorOfTheSpiresDelayedTriggeredAbility extends DelayedTriggeredAbility {
- ChancellorOfTheSpiresDelayedTriggeredAbility () {
- super(new ChancellorOfTheSpiresEffect());
+ ChancellorOfTheSpiresDelayedTriggeredAbility() {
+ super(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(7, TargetController.OPPONENT));
}
- ChancellorOfTheSpiresDelayedTriggeredAbility(ChancellorOfTheSpiresDelayedTriggeredAbility ability) {
+ private ChancellorOfTheSpiresDelayedTriggeredAbility(ChancellorOfTheSpiresDelayedTriggeredAbility ability) {
super(ability);
}
@@ -82,43 +79,14 @@ class ChancellorOfTheSpiresDelayedTriggeredAbility extends DelayedTriggeredAbili
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.UPKEEP_STEP_PRE;
}
-
+
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return true;
}
+
@Override
public ChancellorOfTheSpiresDelayedTriggeredAbility copy() {
return new ChancellorOfTheSpiresDelayedTriggeredAbility(this);
}
}
-
-class ChancellorOfTheSpiresEffect extends OneShotEffect {
-
- ChancellorOfTheSpiresEffect () {
- super(Outcome.Benefit);
- staticText = "each opponent puts the top seven cards of their library into their graveyard";
- }
-
- ChancellorOfTheSpiresEffect(ChancellorOfTheSpiresEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- for (UUID opponentId : game.getOpponents(source.getControllerId())) {
- Player opponent = game.getPlayer(opponentId);
- if (opponent != null) {
- opponent.moveCards(opponent.getLibrary().getTopCards(game, 7), Zone.GRAVEYARD, source, game);
- }
- }
- return true;
- }
-
- @Override
- public ChancellorOfTheSpiresEffect copy() {
- return new ChancellorOfTheSpiresEffect(this);
- }
-
-}
-
diff --git a/Mage.Sets/src/mage/cards/c/ChillOfForeboding.java b/Mage.Sets/src/mage/cards/c/ChillOfForeboding.java
index 5f7d4323eb7..98f9bbc67d2 100644
--- a/Mage.Sets/src/mage/cards/c/ChillOfForeboding.java
+++ b/Mage.Sets/src/mage/cards/c/ChillOfForeboding.java
@@ -1,36 +1,32 @@
-
package mage.cards.c;
-import java.util.UUID;
-import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
import mage.abilities.keyword.FlashbackAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.constants.TimingRule;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.players.Player;
+
+import java.util.UUID;
/**
- *
* @author North
*/
public final class ChillOfForeboding extends CardImpl {
public ChillOfForeboding(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}");
// Each player puts the top five cards of their library into their graveyard.
- this.getSpellAbility().addEffect(new ChillOfForebodingEffect());
+ this.getSpellAbility().addEffect(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(5, TargetController.ANY));
+
// Flashback {7}{U}
this.addAbility(new FlashbackAbility(new ManaCostsImpl("{7}{U}"), TimingRule.SORCERY));
}
- public ChillOfForeboding(final ChillOfForeboding card) {
+ private ChillOfForeboding(final ChillOfForeboding card) {
super(card);
}
@@ -39,32 +35,3 @@ public final class ChillOfForeboding extends CardImpl {
return new ChillOfForeboding(this);
}
}
-
-class ChillOfForebodingEffect extends OneShotEffect {
-
- public ChillOfForebodingEffect() {
- super(Outcome.Detriment);
- this.staticText = "Each player puts the top five cards of their library into their graveyard";
- }
-
- public ChillOfForebodingEffect(final ChillOfForebodingEffect effect) {
- super(effect);
- }
-
- @Override
- public ChillOfForebodingEffect copy() {
- return new ChillOfForebodingEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player sourcePlayer = game.getPlayer(source.getControllerId());
- for (UUID playerId : game.getState().getPlayersInRange(sourcePlayer.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, 5), Zone.GRAVEYARD, source, game);
- }
- }
- return true;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/c/ChronicFlooding.java b/Mage.Sets/src/mage/cards/c/ChronicFlooding.java
index 62f452388d3..131327bd244 100644
--- a/Mage.Sets/src/mage/cards/c/ChronicFlooding.java
+++ b/Mage.Sets/src/mage/cards/c/ChronicFlooding.java
@@ -91,6 +91,6 @@ class ChronicFloodingAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever enchanted land becomes tapped, its controller puts the top three cards of their library into their graveyard.";
+ return "Whenever enchanted land becomes tapped, its controller mills three cards.";
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/c/CloudhoofKirin.java b/Mage.Sets/src/mage/cards/c/CloudhoofKirin.java
index c0fc199a8c7..ea015a23d3c 100644
--- a/Mage.Sets/src/mage/cards/c/CloudhoofKirin.java
+++ b/Mage.Sets/src/mage/cards/c/CloudhoofKirin.java
@@ -1,7 +1,6 @@
package mage.cards.c;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
@@ -9,11 +8,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Outcome;
-import mage.constants.SuperType;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.stack.Spell;
@@ -21,8 +16,9 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPlayer;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class CloudhoofKirin extends CardImpl {
@@ -44,7 +40,7 @@ public final class CloudhoofKirin extends CardImpl {
this.addAbility(ability);
}
- public CloudhoofKirin(final CloudhoofKirin card) {
+ private CloudhoofKirin(final CloudhoofKirin card) {
super(card);
}
@@ -56,12 +52,12 @@ public final class CloudhoofKirin extends CardImpl {
class CloudhoofKirinEffect extends OneShotEffect {
- public CloudhoofKirinEffect() {
+ CloudhoofKirinEffect() {
super(Outcome.Detriment);
- this.staticText = "you may have target player put the top X cards of their library into their graveyard, where X is that spell's converted mana cost";
+ this.staticText = "have target player mill X cards, where X is that spell's converted mana cost";
}
- public CloudhoofKirinEffect(final CloudhoofKirinEffect effect) {
+ private CloudhoofKirinEffect(final CloudhoofKirinEffect effect) {
super(effect);
}
@@ -80,8 +76,10 @@ class CloudhoofKirinEffect extends OneShotEffect {
targetPlayer = game.getPlayer(target.getFirstTarget());
}
}
- if (targetPlayer != null) {
- return targetPlayer.moveCards(targetPlayer.getLibrary().getTopCards(game, spell.getConvertedManaCost()), Zone.GRAVEYARD, source, game);
+ int cmc = spell.getConvertedManaCost();
+ if (targetPlayer != null && cmc > 0) {
+ targetPlayer.millCards(cmc, source, game);
+ return true;
}
}
return false;
diff --git a/Mage.Sets/src/mage/cards/c/CoercedConfession.java b/Mage.Sets/src/mage/cards/c/CoercedConfession.java
index 128ddb264f7..db453582136 100644
--- a/Mage.Sets/src/mage/cards/c/CoercedConfession.java
+++ b/Mage.Sets/src/mage/cards/c/CoercedConfession.java
@@ -1,10 +1,10 @@
-
package mage.cards.c;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.*;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@@ -12,22 +12,23 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class CoercedConfession extends CardImpl {
public CoercedConfession(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{U/B}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{U/B}");
// Target player puts the top four cards of their library into their graveyard. You draw a card for each creature card put into a graveyard this way.
getSpellAbility().addEffect(new CoercedConfessionMillEffect());
getSpellAbility().addTarget(new TargetPlayer());
}
- public CoercedConfession(final CoercedConfession card) {
+ private CoercedConfession(final CoercedConfession card) {
super(card);
}
@@ -39,12 +40,12 @@ public final class CoercedConfession extends CardImpl {
class CoercedConfessionMillEffect extends OneShotEffect {
- public CoercedConfessionMillEffect() {
+ CoercedConfessionMillEffect() {
super(Outcome.DrawCard);
- this.staticText = "Target player puts the top four cards of their library into their graveyard. You draw a card for each creature card put into a graveyard this way";
+ this.staticText = "Target player mills four cards. You draw a card for each creature card put into their graveyard this way";
}
- public CoercedConfessionMillEffect(final CoercedConfessionMillEffect effect) {
+ private CoercedConfessionMillEffect(final CoercedConfessionMillEffect effect) {
super(effect);
}
@@ -56,24 +57,26 @@ class CoercedConfessionMillEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
- if (player != null) {
- int foundCreatures = 0;
- Cards cards = new CardsImpl();
- for(Card card: player.getLibrary().getTopCards(game, 4)) {
- cards.add(card);
- if (card.isCreature()) {
- ++foundCreatures;
- }
- }
- player.moveCards(cards, Zone.GRAVEYARD, source, game);
- if (foundCreatures > 0) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- controller.drawCards(foundCreatures, source.getSourceId(), game);
- }
- }
+ if (player == null) {
+ return false;
+ }
+ int creaturesMilled = player
+ .millCards(4, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(card -> game.getState().getZone(card.getId()) == Zone.GRAVEYARD)
+ .filter(MageObject::isCreature)
+ .mapToInt(x -> 1)
+ .sum();
+ if (creaturesMilled < 1) {
return true;
}
- return false;
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller == null) {
+ return true;
+ }
+ controller.drawCards(creaturesMilled, source.getSourceId(), game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/c/CombustibleGearhulk.java b/Mage.Sets/src/mage/cards/c/CombustibleGearhulk.java
index f8d33deabeb..dbc8f48801c 100644
--- a/Mage.Sets/src/mage/cards/c/CombustibleGearhulk.java
+++ b/Mage.Sets/src/mage/cards/c/CombustibleGearhulk.java
@@ -1,24 +1,22 @@
package mage.cards.c;
import mage.MageInt;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.FirstStrikeAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetOpponent;
-import java.util.Set;
import java.util.UUID;
/**
@@ -97,7 +95,7 @@ class CombustibleGearhulkMillAndDamageEffect extends OneShotEffect {
public CombustibleGearhulkMillAndDamageEffect() {
super(Outcome.Damage);
- staticText = "put the top three cards of your library into your graveyard, then {this} deals damage to that player equal to the total converted mana cost of those cards.";
+ staticText = "mill three cards, then {this} deals damage to that player equal to the total converted mana cost of those cards.";
}
public CombustibleGearhulkMillAndDamageEffect(final CombustibleGearhulkMillAndDamageEffect effect) {
@@ -108,13 +106,12 @@ class CombustibleGearhulkMillAndDamageEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- int sumCMC = 0;
- Set cardList = controller.getLibrary().getTopCards(game, 3);
- for (Card card : cardList) {
- int test = card.getConvertedManaCost();
- sumCMC += test;
- }
- controller.moveCards(cardList, Zone.GRAVEYARD, source, game);
+ int sumCMC = controller
+ .millCards(3, source, game)
+ .getCards(game)
+ .stream()
+ .mapToInt(MageObject::getConvertedManaCost)
+ .sum();
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
if (targetPlayer != null) {
targetPlayer.damage(sumCMC, source.getSourceId(), game);
diff --git a/Mage.Sets/src/mage/cards/c/Countermand.java b/Mage.Sets/src/mage/cards/c/Countermand.java
index 5c20b25a40f..d2dcff87401 100644
--- a/Mage.Sets/src/mage/cards/c/Countermand.java
+++ b/Mage.Sets/src/mage/cards/c/Countermand.java
@@ -1,28 +1,27 @@
package mage.cards.c;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.TargetSpell;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class Countermand extends CardImpl {
public Countermand(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{U}");
// Counter target spell. Its controller puts the top four cards of their library into their graveyard.
@@ -39,6 +38,7 @@ public final class Countermand extends CardImpl {
return new Countermand(this);
}
}
+
class CountermandEffect extends OneShotEffect {
public CountermandEffect() {
@@ -65,7 +65,7 @@ class CountermandEffect extends OneShotEffect {
if (stackObject != null) {
Player controller = game.getPlayer(stackObject.getControllerId());
if (controller != null) {
- controller.moveCards(controller.getLibrary().getTopCards(game, 4), Zone.GRAVEYARD, source, game);
+ controller.millCards(4, source, game);
}
}
return countered;
diff --git a/Mage.Sets/src/mage/cards/c/CrosstownCourier.java b/Mage.Sets/src/mage/cards/c/CrosstownCourier.java
index 093357a261d..bb29e3e6986 100644
--- a/Mage.Sets/src/mage/cards/c/CrosstownCourier.java
+++ b/Mage.Sets/src/mage/cards/c/CrosstownCourier.java
@@ -80,7 +80,7 @@ public final class CrosstownCourier extends CardImpl {
@Override
public String getRule() {
- return "Whenever {this} deals combat damage to a player, that player puts that many cards from the top of their library into their graveyard.";
+ return "Whenever {this} deals combat damage to a player, that player mills that many cards.";
}
}
}
diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java b/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java
index 1d12b1daf59..b1c0bd8ba66 100644
--- a/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java
+++ b/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java
@@ -88,6 +88,6 @@ class CurseOfTheBloodyTomeAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "At the beginning of enchanted player's upkeep, that player puts the top two cards of their library into their graveyard.";
+ return "At the beginning of enchanted player's upkeep, that player mills two cards.";
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DeepSpawn.java b/Mage.Sets/src/mage/cards/d/DeepSpawn.java
index 1c54645f9c6..3a78baa9fb0 100644
--- a/Mage.Sets/src/mage/cards/d/DeepSpawn.java
+++ b/Mage.Sets/src/mage/cards/d/DeepSpawn.java
@@ -39,7 +39,7 @@ public final class DeepSpawn extends CardImpl {
this.addAbility(TrampleAbility.getInstance());
// At the beginning of your upkeep, sacrifice Deep Spawn unless you put the top two cards of your library into your graveyard.
Effect effect = new SacrificeSourceUnlessPaysEffect(new PutTopCardOfYourLibraryToGraveyardCost(2));
- effect.setText("sacrifice {this} unless you put the top two cards of your library into your graveyard");
+ effect.setText("sacrifice {this} unless you mill two cards");
this.addAbility(new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, false));
// {U}: Deep Spawn gains shroud until end of turn and doesn't untap during your next untap step. Tap Deep Spawn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(
diff --git a/Mage.Sets/src/mage/cards/d/DidntSayPlease.java b/Mage.Sets/src/mage/cards/d/DidntSayPlease.java
index f4e6a186b51..96f5edc3635 100644
--- a/Mage.Sets/src/mage/cards/d/DidntSayPlease.java
+++ b/Mage.Sets/src/mage/cards/d/DidntSayPlease.java
@@ -8,7 +8,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetSpell;
@@ -44,8 +43,7 @@ class DidntSayPleaseEffect extends OneShotEffect {
DidntSayPleaseEffect() {
super(Outcome.Benefit);
- staticText = "Counter target spell. Its controller puts " +
- "the top three cards of their library into their graveyard.";
+ staticText = "Counter target spell. Its controller mills three cards.";
}
private DidntSayPleaseEffect(final DidntSayPleaseEffect effect) {
@@ -63,7 +61,7 @@ class DidntSayPleaseEffect extends OneShotEffect {
if (player == null) {
return false;
}
- player.moveCards(player.getLibrary().getTopCards(game, 3), Zone.GRAVEYARD, source, game);
+ player.millCards(3, source, game);
return effect.apply(game, source);
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DreadSummons.java b/Mage.Sets/src/mage/cards/d/DreadSummons.java
index 0367d259c09..8a2812efbfa 100644
--- a/Mage.Sets/src/mage/cards/d/DreadSummons.java
+++ b/Mage.Sets/src/mage/cards/d/DreadSummons.java
@@ -1,23 +1,22 @@
-
package mage.cards.d;
-import java.util.Set;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.CreateTokenEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
+import mage.game.permanent.token.Token;
import mage.game.permanent.token.ZombieToken;
import mage.players.Player;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class DreadSummons extends CardImpl {
@@ -26,10 +25,10 @@ public final class DreadSummons extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{B}");
// Each player puts the top X cards of their library into their graveyard. For each creature card put into a graveyard this way, you create a tapped 2/2 black Zombie creature token.
- getSpellAbility().addEffect(new DreadSummonsEffect());
+ this.getSpellAbility().addEffect(new DreadSummonsEffect());
}
- public DreadSummons(final DreadSummons card) {
+ private DreadSummons(final DreadSummons card) {
super(card);
}
@@ -41,12 +40,15 @@ public final class DreadSummons extends CardImpl {
class DreadSummonsEffect extends OneShotEffect {
- public DreadSummonsEffect() {
+ private static final Token token = new ZombieToken();
+
+ DreadSummonsEffect() {
super(Outcome.PutCreatureInPlay);
- this.staticText = "Each player puts the top X cards of their library into their graveyard. For each creature card put into a graveyard this way, you create a tapped 2/2 black Zombie creature token";
+ this.staticText = "each player mills X cards. For each creature card put into a graveyard this way, " +
+ "you create a tapped 2/2 black Zombie creature token";
}
- public DreadSummonsEffect(final DreadSummonsEffect effect) {
+ private DreadSummonsEffect(final DreadSummonsEffect effect) {
super(effect);
}
@@ -57,28 +59,24 @@ class DreadSummonsEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- int numberOfCards = source.getManaCostsToPay().getX();
- if (numberOfCards > 0) {
- int numberOfCreatureCards = 0;
- for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- Set movedCards = player.moveCardsToGraveyardWithInfo(player.getLibrary().getTopCards(game, numberOfCards), source, game, Zone.LIBRARY);
- for (Card card : movedCards) {
- if (card.isCreature()) {
- numberOfCreatureCards++;
- }
- }
- }
- }
- if (numberOfCreatureCards > 0) {
- return new CreateTokenEffect(new ZombieToken(), numberOfCreatureCards, true, false).apply(game, source);
- }
+ int creatureCount = 0;
+ for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player == null) {
+ continue;
}
- return true;
+ creatureCount += player
+ .millCards(source.getManaCostsToPay().getX(), source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(card -> game.getState().getZone(card.getId()) == Zone.GRAVEYARD)
+ .filter(MageObject::isCreature)
+ .count();
}
- return false;
+ if (creatureCount > 0) {
+ token.putOntoBattlefield(creatureCount, game, source.getSourceId(), source.getControllerId());
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DreambornMuse.java b/Mage.Sets/src/mage/cards/d/DreambornMuse.java
index 169107a55c2..1ea48de2e1e 100644
--- a/Mage.Sets/src/mage/cards/d/DreambornMuse.java
+++ b/Mage.Sets/src/mage/cards/d/DreambornMuse.java
@@ -1,7 +1,5 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.dynamicvalue.common.CardsInTargetPlayerHandCount;
@@ -12,26 +10,26 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
+import java.util.UUID;
+
/**
- *
* @author cbrianhill
*/
public final class DreambornMuse extends CardImpl {
public DreambornMuse(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}");
this.subtype.add(SubType.SPIRIT);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
-
+
// At the beginning of each player's upkeep, that player puts the top X cards of their library into their graveyard, where X is the number of cards in their hand.
PutLibraryIntoGraveTargetEffect effect = new PutLibraryIntoGraveTargetEffect(CardsInTargetPlayerHandCount.instance);
- effect.setText("that player puts the top X cards of their library into their graveyard, where X is the number of cards in their hand.");
+ effect.setText("that player mills X cards, where X is the number of cards in their hand");
this.addAbility(new BeginningOfUpkeepTriggeredAbility(effect, TargetController.ANY, false));
-
}
- public DreambornMuse(final DreambornMuse card) {
+ private DreambornMuse(final DreambornMuse card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/d/DrownInFilth.java b/Mage.Sets/src/mage/cards/d/DrownInFilth.java
index c9befad3dd2..55138284192 100644
--- a/Mage.Sets/src/mage/cards/d/DrownInFilth.java
+++ b/Mage.Sets/src/mage/cards/d/DrownInFilth.java
@@ -28,7 +28,7 @@ public final class DrownInFilth extends CardImpl {
// Choose target creature. Put the top four cards of your library into your graveyard, then that creature gets -1/-1 until end of turn for each land card in your graveyard.
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
Effect effect = new PutTopCardOfLibraryIntoGraveControllerEffect(4);
- effect.setText("Choose target creature. Put the top four cards of your library into your graveyard");
+ effect.setText("Choose target creature. Mill four cards");
this.getSpellAbility().addEffect(effect);
DynamicValue landCards = new SignInversionDynamicValue(new CardsInControllerGraveyardCount(new FilterLandCard()));
this.getSpellAbility().addEffect(new BoostTargetEffect(landCards, landCards, Duration.EndOfTurn));
diff --git a/Mage.Sets/src/mage/cards/e/EnterTheGodEternals.java b/Mage.Sets/src/mage/cards/e/EnterTheGodEternals.java
index fe6bdebf9b1..5db22b3b0bb 100644
--- a/Mage.Sets/src/mage/cards/e/EnterTheGodEternals.java
+++ b/Mage.Sets/src/mage/cards/e/EnterTheGodEternals.java
@@ -46,7 +46,7 @@ class EnterTheGodEternalsEffect extends OneShotEffect {
EnterTheGodEternalsEffect() {
super(Outcome.Benefit);
staticText = "{this} deals 4 damage to target creature and you gain life equal to the damage dealt this way. " +
- "Target player puts the top four cards of their library into their graveyard. Amass 4.";
+ "Target player mills four cards. Amass 4.";
}
private EnterTheGodEternalsEffect(final EnterTheGodEternalsEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/e/ExtractFromDarkness.java b/Mage.Sets/src/mage/cards/e/ExtractFromDarkness.java
index 60fa0cc6823..92e77183b56 100644
--- a/Mage.Sets/src/mage/cards/e/ExtractFromDarkness.java
+++ b/Mage.Sets/src/mage/cards/e/ExtractFromDarkness.java
@@ -1,12 +1,13 @@
package mage.cards.e;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
@@ -14,8 +15,9 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCardInGraveyard;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class ExtractFromDarkness extends CardImpl {
@@ -24,12 +26,13 @@ public final class ExtractFromDarkness extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}{B}");
// Each player puts the top two cards of their library into their graveyard.
- this.getSpellAbility().addEffect(new ExtractFromDarknessMillEffect());
+ this.getSpellAbility().addEffect(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(2, TargetController.ANY));
+
// Then put a creature card from a graveyard onto the battlefield under your control.
- this.getSpellAbility().addEffect(new ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect());
+ this.getSpellAbility().addEffect(new ExtractFromDarknessEffect());
}
- public ExtractFromDarkness(final ExtractFromDarkness card) {
+ private ExtractFromDarkness(final ExtractFromDarkness card) {
super(card);
}
@@ -39,48 +42,20 @@ public final class ExtractFromDarkness extends CardImpl {
}
}
-class ExtractFromDarknessMillEffect extends OneShotEffect {
+class ExtractFromDarknessEffect extends OneShotEffect {
- ExtractFromDarknessMillEffect() {
- super(Outcome.Detriment);
- staticText = "Each player puts the top two cards of their library into their graveyard";
- }
-
- ExtractFromDarknessMillEffect(final ExtractFromDarknessMillEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, 2), Zone.GRAVEYARD, source, game);
- }
- }
- return true;
- }
-
- @Override
- public ExtractFromDarknessMillEffect copy() {
- return new ExtractFromDarknessMillEffect(this);
- }
-}
-
-class ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect extends OneShotEffect {
-
- public ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect() {
+ ExtractFromDarknessEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "Put a creature card from a graveyard onto the battlefield under your control";
}
- public ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect(final ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect effect) {
+ private ExtractFromDarknessEffect(final ExtractFromDarknessEffect effect) {
super(effect);
}
@Override
- public ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect copy() {
- return new ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect(this);
+ public ExtractFromDarknessEffect copy() {
+ return new ExtractFromDarknessEffect(this);
}
@Override
diff --git a/Mage.Sets/src/mage/cards/e/EyeCollector.java b/Mage.Sets/src/mage/cards/e/EyeCollector.java
index 708c9bec082..757aa987571 100644
--- a/Mage.Sets/src/mage/cards/e/EyeCollector.java
+++ b/Mage.Sets/src/mage/cards/e/EyeCollector.java
@@ -1,22 +1,16 @@
package mage.cards.e;
import mage.MageInt;
-import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.cards.CardsImpl;
import mage.constants.CardType;
-import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.players.Player;
+import mage.constants.TargetController;
import java.util.UUID;
-import java.util.stream.Collectors;
/**
* @author TheElk801
@@ -34,7 +28,7 @@ public final class EyeCollector extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever Eye Collector deals combat damage to a player, each player puts the top card of their library into their graveyard.
- this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new EyeCollectorEffect(), false));
+ this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(1, TargetController.ANY), false));
}
private EyeCollector(final EyeCollector card) {
@@ -46,37 +40,3 @@ public final class EyeCollector extends CardImpl {
return new EyeCollector(this);
}
}
-
-class EyeCollectorEffect extends OneShotEffect {
-
- EyeCollectorEffect() {
- super(Outcome.Benefit);
- staticText = "each player puts the top card of their library into their graveyard";
- }
-
- private EyeCollectorEffect(final EyeCollectorEffect effect) {
- super(effect);
- }
-
- @Override
- public EyeCollectorEffect copy() {
- return new EyeCollectorEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller == null) {
- return false;
- }
- return controller.moveCards(new CardsImpl(game.getState()
- .getPlayersInRange(controller.getId(), game)
- .stream()
- .map(game::getPlayer)
- .filter(player -> player != null)
- .map(Player::getLibrary)
- .map(library -> library.getFromTop(game))
- .collect(Collectors.toSet())
- ), Zone.GRAVEYARD, source, game);
- }
-}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/f/FlintGolem.java b/Mage.Sets/src/mage/cards/f/FlintGolem.java
index f78c9e2e67b..53fd61c3aed 100644
--- a/Mage.Sets/src/mage/cards/f/FlintGolem.java
+++ b/Mage.Sets/src/mage/cards/f/FlintGolem.java
@@ -46,7 +46,7 @@ class FlintGolemEffect extends OneShotEffect {
public FlintGolemEffect() {
super(Outcome.Detriment);
- this.staticText = "defending player puts the top three cards of their library into their graveyard";
+ this.staticText = "defending player mills three cards";
}
public FlintGolemEffect(final FlintGolemEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/f/FolioOfFancies.java b/Mage.Sets/src/mage/cards/f/FolioOfFancies.java
index 191fe2c06d0..1f81cc0be1c 100644
--- a/Mage.Sets/src/mage/cards/f/FolioOfFancies.java
+++ b/Mage.Sets/src/mage/cards/f/FolioOfFancies.java
@@ -9,18 +9,16 @@ import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardAllEffect;
import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.game.Game;
import mage.players.Player;
-import java.util.Collection;
-import java.util.Objects;
-import java.util.Set;
import java.util.UUID;
-import java.util.stream.Collectors;
/**
* @author TheElk801
@@ -63,8 +61,7 @@ class FolioOfFanciesEffect extends OneShotEffect {
FolioOfFanciesEffect() {
super(Outcome.Benefit);
- staticText = "Each opponent puts a number of cards equal to the number of cards in their hand " +
- "from the top of their library into their graveyard.";
+ staticText = "each opponent mills cards equal to the number of cards in their hand";
}
private FolioOfFanciesEffect(final FolioOfFanciesEffect effect) {
@@ -82,14 +79,13 @@ class FolioOfFanciesEffect extends OneShotEffect {
if (controller == null) {
return false;
}
- Set cards = game.getOpponents(source.getControllerId())
- .stream()
- .map(game::getPlayer)
- .filter(Objects::nonNull)
- .filter(player -> !player.getHand().isEmpty())
- .map(player -> player.getLibrary().getTopCards(game, player.getHand().size()))
- .flatMap(Collection::stream)
- .collect(Collectors.toSet());
- return controller.moveCards(cards, Zone.GRAVEYARD, source, game);
+ for (UUID playerId : game.getOpponents(source.getControllerId())) {
+ Player player = game.getPlayer(playerId);
+ if (player == null) {
+ continue;
+ }
+ player.millCards(player.getHand().size(), source, game);
+ }
+ return true;
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/f/Foreshadow.java b/Mage.Sets/src/mage/cards/f/Foreshadow.java
index b3f778e9b3d..2ac311b6f3d 100644
--- a/Mage.Sets/src/mage/cards/f/Foreshadow.java
+++ b/Mage.Sets/src/mage/cards/f/Foreshadow.java
@@ -11,7 +11,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
@@ -49,12 +48,12 @@ public final class Foreshadow extends CardImpl {
class ForeshadowEffect extends OneShotEffect {
- public ForeshadowEffect() {
+ ForeshadowEffect() {
super(Outcome.DrawCard);
- this.staticText = "target opponent puts the top card of their library into their graveyard. If that card has the chosen name, you draw a card";
+ this.staticText = "target opponent mills a card. If that card has the chosen name, you draw a card";
}
- public ForeshadowEffect(final ForeshadowEffect effect) {
+ private ForeshadowEffect(final ForeshadowEffect effect) {
super(effect);
}
@@ -68,17 +67,16 @@ class ForeshadowEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(source.getFirstTarget());
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) {
- Card card = targetPlayer.getLibrary().getFromTop(game);
- if (card != null) {
- controller.moveCards(card, Zone.GRAVEYARD, source, game);
- if (CardUtil.haveSameNames(card, cardName, game)) {
- controller.drawCards(1, source.getSourceId(), game);
- }
- }
- return true;
+ if (controller == null || targetPlayer == null || cardName == null || cardName.isEmpty()) {
+ return false;
}
- return false;
+ for (Card card : targetPlayer.millCards(1, source, game).getCards(game)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
+ controller.drawCards(1, source.getSourceId(), game);
+ break;
+ }
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/f/FrayingSanity.java b/Mage.Sets/src/mage/cards/f/FrayingSanity.java
index 56f444ed24d..92ea0d99339 100644
--- a/Mage.Sets/src/mage/cards/f/FrayingSanity.java
+++ b/Mage.Sets/src/mage/cards/f/FrayingSanity.java
@@ -83,7 +83,7 @@ class FrayingSanityTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "At the beginning of each end step, enchanted player puts the top X cards of their library into their graveyard, where X is the total number of cards put into their graveyard from anywhere this turn.";
+ return "At the beginning of each end step, enchanted player mills X cards, where X is the total number of cards put into their graveyard from anywhere this turn.";
}
}
@@ -117,8 +117,8 @@ class FrayingSanityEffect extends OneShotEffect {
if (watcher != null) {
xAmount = watcher.getAmountCardsPutToGraveyard(enchantedPlayer.getId());
}
- Set topXCardsFromLibrary = enchantedPlayer.getLibrary().getTopCards(game, xAmount);
- return enchantedPlayer.moveCards(topXCardsFromLibrary, Zone.GRAVEYARD, source, game, false, false, true, null);
+ enchantedPlayer.millCards(xAmount, source, game);
+ return true;
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/g/GethLordOfTheVault.java b/Mage.Sets/src/mage/cards/g/GethLordOfTheVault.java
index 3db2f0e8b7d..6d96b9f29fe 100644
--- a/Mage.Sets/src/mage/cards/g/GethLordOfTheVault.java
+++ b/Mage.Sets/src/mage/cards/g/GethLordOfTheVault.java
@@ -1,6 +1,5 @@
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -10,12 +9,7 @@ import mage.abilities.keyword.IntimidateAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Outcome;
-import mage.constants.SuperType;
-import mage.constants.TargetController;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.game.Game;
@@ -23,6 +17,8 @@ import mage.players.Player;
import mage.target.common.TargetCardInGraveyard;
import mage.target.targetadjustment.XCMCGraveyardAdjuster;
+import java.util.UUID;
+
/**
* @author nantuko
*/
@@ -70,7 +66,7 @@ class GethLordOfTheVaultEffect extends OneShotEffect {
public GethLordOfTheVaultEffect() {
super(Outcome.Benefit);
- staticText = "Put target artifact or creature card with converted mana cost X from an opponent's graveyard onto the battlefield under your control tapped. Then that player puts the top X cards of their library into their graveyard";
+ staticText = "Put target artifact or creature card with converted mana cost X from an opponent's graveyard onto the battlefield under your control tapped. Then that player mills X cards";
}
public GethLordOfTheVaultEffect(final GethLordOfTheVaultEffect effect) {
@@ -80,18 +76,19 @@ class GethLordOfTheVaultEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Card card = game.getCard(getTargetPointer().getFirst(game, source));
- if (card != null) {
- controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null);
- Player player = game.getPlayer(card.getOwnerId());
- if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, card.getConvertedManaCost()), Zone.GRAVEYARD, source, game);
- }
- }
+ if (controller == null) {
+ return false;
+ }
+ Card card = game.getCard(getTargetPointer().getFirst(game, source));
+ if (card == null) {
return true;
}
- return false;
+ controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null);
+ Player player = game.getPlayer(card.getOwnerId());
+ if (player != null) {
+ player.millCards(card.getConvertedManaCost(), source, game);
+ }
+ return true;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/g/GhoulcallersBell.java b/Mage.Sets/src/mage/cards/g/GhoulcallersBell.java
index 6ad15678fbf..e7638cd5de8 100644
--- a/Mage.Sets/src/mage/cards/g/GhoulcallersBell.java
+++ b/Mage.Sets/src/mage/cards/g/GhoulcallersBell.java
@@ -1,22 +1,16 @@
-
package mage.cards.g;
-import java.util.UUID;
-import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
-import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.players.Player;
+import mage.constants.TargetController;
+
+import java.util.UUID;
/**
- *
* @author North
*/
public final class GhoulcallersBell extends CardImpl {
@@ -25,10 +19,10 @@ public final class GhoulcallersBell extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
// {T}: Each player puts the top card of their library into their graveyard.
- this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GhoulcallersBellEffect(), new TapSourceCost()));
+ this.addAbility(new SimpleActivatedAbility(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(1, TargetController.ANY), new TapSourceCost()));
}
- public GhoulcallersBell(final GhoulcallersBell card) {
+ private GhoulcallersBell(final GhoulcallersBell card) {
super(card);
}
@@ -37,34 +31,3 @@ public final class GhoulcallersBell extends CardImpl {
return new GhoulcallersBell(this);
}
}
-
-class GhoulcallersBellEffect extends OneShotEffect {
-
- public GhoulcallersBellEffect() {
- super(Outcome.Discard);
- this.staticText = "Each player puts the top card of their library into their graveyard";
- }
-
- public GhoulcallersBellEffect(final GhoulcallersBellEffect effect) {
- super(effect);
- }
-
- @Override
- public GhoulcallersBellEffect copy() {
- return new GhoulcallersBellEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- Card card = player.getLibrary().getFromTop(game);
- if (card != null) {
- player.moveCards(card, Zone.GRAVEYARD, source, game);
- }
- }
- }
- return true;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/g/GorgingVulture.java b/Mage.Sets/src/mage/cards/g/GorgingVulture.java
index 5f042ced902..1c35c788b6c 100644
--- a/Mage.Sets/src/mage/cards/g/GorgingVulture.java
+++ b/Mage.Sets/src/mage/cards/g/GorgingVulture.java
@@ -5,7 +5,9 @@ import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
-import mage.cards.*;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
@@ -48,8 +50,7 @@ class GorgingVultureEffect extends OneShotEffect {
GorgingVultureEffect() {
super(Outcome.Benefit);
- staticText = "put the top four cards of your library into your graveyard. " +
- "You gain 1 life for each creature card put into your graveyard this way.";
+ staticText = "mill four cards. You gain 1 life for each creature card put into your graveyard this way.";
}
private GorgingVultureEffect(final GorgingVultureEffect effect) {
@@ -67,9 +68,8 @@ class GorgingVultureEffect extends OneShotEffect {
if (player == null) {
return false;
}
- Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 4));
- player.moveCards(cards, Zone.GRAVEYARD, source, game);
- int lifeToGain = cards
+ int lifeToGain = player
+ .millCards(4, source, game)
.getCards(game)
.stream()
.filter(Card::isCreature)
diff --git a/Mage.Sets/src/mage/cards/g/GraveStrength.java b/Mage.Sets/src/mage/cards/g/GraveStrength.java
index 229eef94cbb..84bdb9d4106 100644
--- a/Mage.Sets/src/mage/cards/g/GraveStrength.java
+++ b/Mage.Sets/src/mage/cards/g/GraveStrength.java
@@ -24,7 +24,7 @@ public final class GraveStrength extends CardImpl {
// Choose target creature. Put the top three cards of your library into your graveyard, then put a +1/+1 counter on that creature for each creature card in your graveyard.
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
Effect effect = new PutTopCardOfLibraryIntoGraveControllerEffect(3);
- effect.setText("Choose target creature. Put the top three cards of your library into your graveyard");
+ effect.setText("Choose target creature. Mill three cards");
this.getSpellAbility().addEffect(effect);
effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(0), new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE));
effect.setText(", then put a +1/+1 counter on that creature for each creature card in your graveyard");
diff --git a/Mage.Sets/src/mage/cards/g/Grindclock.java b/Mage.Sets/src/mage/cards/g/Grindclock.java
index 0a873bff095..26b5840587b 100644
--- a/Mage.Sets/src/mage/cards/g/Grindclock.java
+++ b/Mage.Sets/src/mage/cards/g/Grindclock.java
@@ -1,7 +1,6 @@
package mage.cards.g;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
@@ -18,8 +17,9 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.UUID;
+
/**
- *
* @author Loki
*/
public final class Grindclock extends CardImpl {
@@ -62,7 +62,7 @@ class GrindclockEffect extends OneShotEffect {
int amount = sourceObject.getCounters(game).getCount(CounterType.CHARGE);
Player targetPlayer = game.getPlayer(source.getFirstTarget());
if (targetPlayer != null) {
- targetPlayer.moveCards(targetPlayer.getLibrary().getTopCards(game, amount), Zone.GRAVEYARD, source, game);
+ targetPlayer.millCards(amount, source, game);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/g/Grindstone.java b/Mage.Sets/src/mage/cards/g/Grindstone.java
index 1b7c1e738d7..2e5d271aacc 100644
--- a/Mage.Sets/src/mage/cards/g/Grindstone.java
+++ b/Mage.Sets/src/mage/cards/g/Grindstone.java
@@ -1,22 +1,25 @@
-
package mage.cards.g;
-import java.util.UUID;
+import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.*;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
/**
- *
* @author LevelX2
*/
public final class Grindstone extends CardImpl {
@@ -25,11 +28,10 @@ public final class Grindstone extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
// {3}, {T}: Target player puts the top two cards of their library into their graveyard. If both cards share a color, repeat this process.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GrindstoneEffect(), new ManaCostsImpl("{3}"));
+ Ability ability = new SimpleActivatedAbility(new GrindstoneEffect(), new ManaCostsImpl("{3}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
-
}
public Grindstone(final Grindstone card) {
@@ -44,12 +46,12 @@ public final class Grindstone extends CardImpl {
class GrindstoneEffect extends OneShotEffect {
- public GrindstoneEffect() {
+ GrindstoneEffect() {
super(Outcome.Benefit);
- this.staticText = "Target player puts the top two cards of their library into their graveyard. If both cards share a color, repeat this process";
+ this.staticText = "target player mills two cards. If two cards that share a color were milled this way, repeat this process.";
}
- public GrindstoneEffect(final GrindstoneEffect effect) {
+ private GrindstoneEffect(final GrindstoneEffect effect) {
super(effect);
}
@@ -77,18 +79,33 @@ class GrindstoneEffect extends OneShotEffect {
return true;
}
colorShared = false;
- Card card1 = null;
- Cards toGraveyard = new CardsImpl();
- for (Card card : targetPlayer.getLibrary().getCards(game)) {
- toGraveyard.add(card);
- if (card1 == null) {
- card1 = card;
- } else {
- colorShared = card1.getColor(game).shares(card.getColor(game));
+ List cards = targetPlayer
+ .millCards(2, source, game)
+ .getCards(game)
+ .stream()
+ .collect(Collectors.toList());
+ if (cards.size() < 2) {
+ break;
+ }
+ for (int i = 0; i < cards.size(); i++) {
+ if (colorShared) {
break;
}
+ ObjectColor color1 = cards.get(i).getColor(game);
+ if (color1.isColorless()) {
+ continue;
+ }
+ for (int j = 0; j < cards.size(); j++) {
+ if (i >= j) {
+ continue;
+ }
+ ObjectColor color2 = cards.get(j).getColor(game);
+ if (color1.shares(color2)) {
+ colorShared = true;
+ break;
+ }
+ }
}
- targetPlayer.moveCards(toGraveyard, Zone.GRAVEYARD, source, game);
} while (colorShared);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/g/GrislySpectacle.java b/Mage.Sets/src/mage/cards/g/GrislySpectacle.java
index 074d37f0f30..c2d21bb0d59 100644
--- a/Mage.Sets/src/mage/cards/g/GrislySpectacle.java
+++ b/Mage.Sets/src/mage/cards/g/GrislySpectacle.java
@@ -54,7 +54,7 @@ class GrislySpectacleEffect extends OneShotEffect {
public GrislySpectacleEffect() {
super(Outcome.DestroyPermanent);
- this.staticText = "Its controller puts a number of cards equal to that creature's power from the top of their library into their graveyard";
+ this.staticText = "Its controller mills cards equal to that creature's power";
}
public GrislySpectacleEffect(final GrislySpectacleEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/g/GrizzledAngler.java b/Mage.Sets/src/mage/cards/g/GrizzledAngler.java
index b1715bac1f4..4726349725a 100644
--- a/Mage.Sets/src/mage/cards/g/GrizzledAngler.java
+++ b/Mage.Sets/src/mage/cards/g/GrizzledAngler.java
@@ -1,7 +1,6 @@
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -12,22 +11,23 @@ import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.ColorlessPredicate;
import mage.game.Game;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class GrizzledAngler extends CardImpl {
public GrizzledAngler(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.HUMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
@@ -60,7 +60,7 @@ class GrizzledAnglerEffect extends OneShotEffect {
public GrizzledAnglerEffect() {
super(Outcome.Benefit);
- staticText = "Put the top two cards of your library into your graveyard. Then if there is a colorless creature card in your graveyard, transform {this}";
+ staticText = "Mill two cards. Then if there is a colorless creature card in your graveyard, transform {this}";
}
public GrizzledAnglerEffect(final GrizzledAnglerEffect effect) {
@@ -76,7 +76,7 @@ class GrizzledAnglerEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- controller.moveCards(controller.getLibrary().getTopCards(game, 2), Zone.GRAVEYARD, source, game);
+ controller.millCards(2, source, game);
if (controller.getGraveyard().count(filter, source.getSourceId(), source.getControllerId(), game) >= 1) {
return new TransformSourceEffect(true).apply(game, source);
}
diff --git a/Mage.Sets/src/mage/cards/g/GyrudaDoomOfDepths.java b/Mage.Sets/src/mage/cards/g/GyrudaDoomOfDepths.java
index f96ad330fa3..effc47bf9a7 100644
--- a/Mage.Sets/src/mage/cards/g/GyrudaDoomOfDepths.java
+++ b/Mage.Sets/src/mage/cards/g/GyrudaDoomOfDepths.java
@@ -17,7 +17,6 @@ import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInGraveyard;
-import java.util.Collection;
import java.util.Set;
import java.util.UUID;
@@ -81,9 +80,8 @@ class GyrudaDoomOfDepthsEffect extends OneShotEffect {
GyrudaDoomOfDepthsEffect() {
super(Outcome.Benefit);
- staticText = "each player puts the top four cards of the library into their graveyard. " +
- "Put a creature card with an even converted mana cost from among those cards " +
- "onto the battlefield under your control.";
+ staticText = "each player mills four cards. Put a creature card with an even converted mana cost " +
+ "from among the milled cards onto the battlefield under your control";
}
private GyrudaDoomOfDepthsEffect(final GyrudaDoomOfDepthsEffect effect) {
@@ -102,15 +100,13 @@ class GyrudaDoomOfDepthsEffect extends OneShotEffect {
return false;
}
Cards cards = new CardsImpl();
- game.getState()
- .getPlayersInRange(source.getControllerId(), game)
- .stream()
- .map(game::getPlayer)
- .map(Player::getLibrary)
- .map(library -> library.getTopCards(game, 4))
- .flatMap(Collection::stream)
- .forEach(cards::add);
- controller.moveCards(cards, Zone.GRAVEYARD, source, game);
+ for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player == null) {
+ continue;
+ }
+ cards.addAll(player.millCards(4, source, game));
+ }
cards.removeIf(cardId -> game.getState().getZone(cardId) != Zone.GRAVEYARD
&& game.getState().getZone(cardId) != Zone.EXILED);
if (cards.isEmpty()) {
diff --git a/Mage.Sets/src/mage/cards/h/HeedTheMists.java b/Mage.Sets/src/mage/cards/h/HeedTheMists.java
index 105251cecb2..bc92038248d 100644
--- a/Mage.Sets/src/mage/cards/h/HeedTheMists.java
+++ b/Mage.Sets/src/mage/cards/h/HeedTheMists.java
@@ -1,21 +1,20 @@
package mage.cards.h;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class HeedTheMists extends CardImpl {
@@ -41,7 +40,7 @@ public final class HeedTheMists extends CardImpl {
public HeedTheMistsEffect() {
super(Outcome.DrawCard);
- staticText = "Put the top card of your library into your graveyard, then draw cards equal to that card's converted mana cost";
+ staticText = "Mill a card, then draw cards equal to that card's converted mana cost";
}
public HeedTheMistsEffect(HeedTheMistsEffect effect) {
@@ -52,15 +51,14 @@ public final class HeedTheMists extends CardImpl {
public boolean apply(Game game, Ability source) {
boolean result = false;
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Card card = controller.getLibrary().getFromTop(game);
- if (card != null) {
- int cmc = card.getConvertedManaCost();
- controller.moveCards(card, Zone.GRAVEYARD, source, game);
- controller.drawCards(cmc, source.getSourceId(), game);
- }
- }
- return result;
+ int totalCMC = controller
+ .millCards(1, source, game)
+ .getCards(game)
+ .stream()
+ .mapToInt(MageObject::getConvertedManaCost)
+ .sum();
+ controller.millCards(totalCMC, source, game);
+ return true;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/h/HelmOfObedience.java b/Mage.Sets/src/mage/cards/h/HelmOfObedience.java
index bad8be25926..cfa04ab0036 100644
--- a/Mage.Sets/src/mage/cards/h/HelmOfObedience.java
+++ b/Mage.Sets/src/mage/cards/h/HelmOfObedience.java
@@ -1,7 +1,6 @@
-
package mage.cards.h;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
@@ -11,6 +10,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@@ -19,8 +19,12 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetOpponent;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
/**
- *
* @author Plopman
*/
public final class HelmOfObedience extends CardImpl {
@@ -31,13 +35,13 @@ public final class HelmOfObedience extends CardImpl {
// {X}, {T}: Target opponent puts cards from the top of their library into their graveyard until a creature card or X cards are put into that graveyard this way, whichever comes first. If a creature card is put into that graveyard this way, sacrifice Helm of Obedience and put that card onto the battlefield under your control. X can't be 0.
VariableManaCost xCosts = new VariableManaCost();
xCosts.setMinX(1);
- SimpleActivatedAbility abilitiy = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HelmOfObedienceEffect(), xCosts);
+ SimpleActivatedAbility abilitiy = new SimpleActivatedAbility(new HelmOfObedienceEffect(), xCosts);
abilitiy.addCost(new TapSourceCost());
abilitiy.addTarget(new TargetOpponent());
this.addAbility(abilitiy);
}
- public HelmOfObedience(final HelmOfObedience card) {
+ private HelmOfObedience(final HelmOfObedience card) {
super(card);
}
@@ -51,12 +55,15 @@ class HelmOfObedienceEffect extends OneShotEffect {
private static final ManacostVariableValue amount = ManacostVariableValue.instance;
- public HelmOfObedienceEffect() {
+ HelmOfObedienceEffect() {
super(Outcome.Detriment);
- staticText = "Target opponent puts cards from the top of their library into their graveyard until a creature card or X cards are put into that graveyard this way, whichever comes first. If a creature card is put into that graveyard this way, sacrifice {this} and put that card onto the battlefield under your control. X can't be 0";
+ staticText = "Target opponent mills a card, then repeats this process until a creature card " +
+ "or X cards have been put into their graveyard this way, whichever comes first. " +
+ "If one or more creature cards were put into that graveyard this way, " +
+ "sacrifice {this} and put one of them onto the battlefield under your control. X can't be 0";
}
- public HelmOfObedienceEffect(final HelmOfObedienceEffect effect) {
+ private HelmOfObedienceEffect(final HelmOfObedienceEffect effect) {
super(effect);
}
@@ -70,32 +77,32 @@ class HelmOfObedienceEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Player targetOpponent = game.getPlayer(targetPointer.getFirst(game, source));
int max = amount.calculate(game, source, this);
- if (targetOpponent != null && controller != null && max > 0) {
- int numberOfCard = 0;
- for (Card card : targetOpponent.getLibrary().getCards(game)) {
- if (card != null) {
- if (targetOpponent.moveCards(card, Zone.GRAVEYARD, source, game)) {
- if (card.isCreature()) {
- // If a creature card is put into that graveyard this way, sacrifice Helm of Obedience
- // and put that card onto the battlefield under your control.
- Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
- if (sourcePermanent != null) {
- sourcePermanent.sacrifice(source.getSourceId(), game);
- }
- controller.moveCards(card, Zone.BATTLEFIELD, source, game);
- break;
- } else {
- numberOfCard++;
- if (numberOfCard >= max) {
- break;
- }
- }
- }
- }
- }
- return true;
+ if (targetOpponent == null || controller == null || max <= 0) {
+ return false;
}
- return false;
+ int numberOfCard = 0;
+ while (targetOpponent.getLibrary().hasCards()) {
+ Cards cards = targetOpponent.millCards(1, source, game);
+ cards.removeIf(uuid -> game.getState().getZone(uuid) != Zone.GRAVEYARD);
+ numberOfCard += cards.size();
+ Set creatures = cards
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(MageObject::isCreature)
+ .collect(Collectors.toSet());
+ if (!creatures.isEmpty()) {
+ controller.moveCards(creatures, Zone.BATTLEFIELD, source, game);
+ }
+ if (!creatures.isEmpty() || numberOfCard >= max) {
+ Permanent permanent = game.getPermanent(source.getSourceId());
+ if (permanent != null) {
+ permanent.sacrifice(source.getSourceId(), game);
+ }
+ break;
+ }
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/h/HereticsPunishment.java b/Mage.Sets/src/mage/cards/h/HereticsPunishment.java
index 71c4bbe179f..87439fa4df6 100644
--- a/Mage.Sets/src/mage/cards/h/HereticsPunishment.java
+++ b/Mage.Sets/src/mage/cards/h/HereticsPunishment.java
@@ -1,21 +1,20 @@
package mage.cards.h;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetAnyTarget;
-import java.util.Set;
+import java.util.Objects;
import java.util.UUID;
/**
@@ -27,7 +26,7 @@ public final class HereticsPunishment extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{R}");
// {3}{R}: Choose any target, then put the top three cards of your library into your graveyard. Heretic's Punishment deals damage to that creature or player equal to the highest converted mana cost among those cards.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HereticsPunishmentEffect(), new ManaCostsImpl("{3}{R}"));
+ Ability ability = new SimpleActivatedAbility(new HereticsPunishmentEffect(), new ManaCostsImpl("{3}{R}"));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
@@ -46,7 +45,7 @@ class HereticsPunishmentEffect extends OneShotEffect {
public HereticsPunishmentEffect() {
super(Outcome.Damage);
- staticText = "Choose any target, then put the top three cards of your library into your graveyard. {this} deals damage to that permanent or player equal to the highest converted mana cost among those cards";
+ staticText = "Choose any target, then mill three cards. {this} deals damage to that permanent or player equal to the highest converted mana cost among the milled cards";
}
public HereticsPunishmentEffect(final HereticsPunishmentEffect effect) {
@@ -56,26 +55,26 @@ class HereticsPunishmentEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- int maxCost = 0;
- Set cardList = controller.getLibrary().getTopCards(game, 3);
- for (Card card : cardList) {
- int test = card.getConvertedManaCost();
- if (test > maxCost) {
- maxCost = test;
- }
- }
- controller.moveCards(cardList, Zone.GRAVEYARD, source, game);
- Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
- if (permanent != null) {
- permanent.damage(maxCost, source.getSourceId(), game, false, true);
- return true;
- }
- Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
- if (targetPlayer != null) {
- targetPlayer.damage(maxCost, source.getSourceId(), game);
- return true;
- }
+ if (controller == null) {
+ return false;
+ }
+ int maxCost = controller
+ .millCards(3, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .mapToInt(MageObject::getConvertedManaCost)
+ .max()
+ .orElse(0);
+ Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
+ if (permanent != null) {
+ permanent.damage(maxCost, source.getSourceId(), game, false, true);
+ return true;
+ }
+ Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
+ if (targetPlayer != null) {
+ targetPlayer.damage(maxCost, source.getSourceId(), game);
+ return true;
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/i/IcebergCancrix.java b/Mage.Sets/src/mage/cards/i/IcebergCancrix.java
index c0a59ad7b72..0f2cb53c504 100644
--- a/Mage.Sets/src/mage/cards/i/IcebergCancrix.java
+++ b/Mage.Sets/src/mage/cards/i/IcebergCancrix.java
@@ -40,7 +40,7 @@ public final class IcebergCancrix extends CardImpl {
Ability ability = new EntersBattlefieldControlledTriggeredAbility(
Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect(2), filter,
true, "Whenever another snow permanent enters the battlefield under your control, " +
- "you may have target player put the top two cards of their library into their graveyard."
+ "you may have target player mill two cards."
);
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java b/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java
index 909f4ec7c0c..3e9ca55f5fb 100644
--- a/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java
+++ b/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java
@@ -46,7 +46,7 @@ class IncreasingConfusionEffect extends OneShotEffect {
public IncreasingConfusionEffect() {
super(Outcome.Detriment);
- staticText = "Target player puts the top X cards of their library into their graveyard. If this spell was cast from a graveyard, that player puts twice that many cards into their graveyard instead";
+ staticText = "Target player mills X cards. If this spell was cast from a graveyard, that player mills twice that many cards";
}
public IncreasingConfusionEffect(final IncreasingConfusionEffect effect) {
@@ -63,7 +63,7 @@ class IncreasingConfusionEffect extends OneShotEffect {
if (spell.getFromZone() == Zone.GRAVEYARD) {
amount *= 2;
}
- player.moveCards(player.getLibrary().getTopCards(game, amount), Zone.GRAVEYARD, source, game);
+ player.millCards(amount, source, game);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/i/InduceParanoia.java b/Mage.Sets/src/mage/cards/i/InduceParanoia.java
index d8862fa168b..eb699cc84e0 100644
--- a/Mage.Sets/src/mage/cards/i/InduceParanoia.java
+++ b/Mage.Sets/src/mage/cards/i/InduceParanoia.java
@@ -51,7 +51,7 @@ class InduceParanoiaEffect extends OneShotEffect {
InduceParanoiaEffect() {
super(Outcome.Detriment);
- this.staticText = "Counter target spell. If {B} was spent to cast this spell, that spell's controller puts the top X cards of their library into their graveyard, where X is the spell's converted mana cost.";
+ this.staticText = "Counter target spell. If {B} was spent to cast this spell, that spell's controller mills X cards, where X is the spell's converted mana cost.";
}
InduceParanoiaEffect(final InduceParanoiaEffect effect) {
@@ -71,7 +71,7 @@ class InduceParanoiaEffect extends OneShotEffect {
int spellCMC = spell.getConvertedManaCost();
Player player = game.getPlayer(spell.getControllerId());
if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, spellCMC), Zone.GRAVEYARD, source, game);
+ player.millCards(spellCMC, source, game);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/i/InfernalGenesis.java b/Mage.Sets/src/mage/cards/i/InfernalGenesis.java
index daa9e51bfd3..2fac7913476 100644
--- a/Mage.Sets/src/mage/cards/i/InfernalGenesis.java
+++ b/Mage.Sets/src/mage/cards/i/InfernalGenesis.java
@@ -1,20 +1,23 @@
-
package mage.cards.i;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.game.Game;
import mage.game.permanent.token.MinionToken2;
+import mage.game.permanent.token.Token;
import mage.players.Player;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author jeffwadsworth
*/
public final class InfernalGenesis extends CardImpl {
@@ -39,28 +42,30 @@ public final class InfernalGenesis extends CardImpl {
class InfernalGenesisEffect extends OneShotEffect {
+ private static final Token token = new MinionToken2();
+
InfernalGenesisEffect() {
super(Outcome.PutCreatureInPlay);
- staticText = "that player puts the top card of their library into their graveyard. " +
- "Then they create X 1/1 black Minion creature tokens, where X is that card's converted mana cost";
+ staticText = "that player mills a card. Then they create X 1/1 black Minion creature tokens, " +
+ "where X is the milled card's converted mana cost.";
}
- InfernalGenesisEffect(final InfernalGenesisEffect effect) {
+ private InfernalGenesisEffect(final InfernalGenesisEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
- if (player != null) {
- Card card = player.getLibrary().getFromTop(game);
- if (card != null) {
- if (player.moveCards(card, Zone.GRAVEYARD, source, game)) {
- int cmc = card.getConvertedManaCost();
- MinionToken2 token = new MinionToken2();
- token.putOntoBattlefield(cmc, game, source.getSourceId(), player.getId());
- }
- }
+ int totalCMC = player
+ .millCards(1, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .mapToInt(MageObject::getConvertedManaCost)
+ .sum();
+ if (totalCMC > 0) {
+ token.putOntoBattlefield(totalCMC, game, source.getSourceId(), player.getId());
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/j/JacesMindseeker.java b/Mage.Sets/src/mage/cards/j/JacesMindseeker.java
index dd0f2354fe6..cc4e59d68f7 100644
--- a/Mage.Sets/src/mage/cards/j/JacesMindseeker.java
+++ b/Mage.Sets/src/mage/cards/j/JacesMindseeker.java
@@ -1,19 +1,12 @@
package mage.cards.j;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
-import mage.cards.Card;
-import mage.cards.CardImpl;
-import mage.cards.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
+import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
@@ -25,8 +18,10 @@ import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetOpponent;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class JacesMindseeker extends CardImpl {
@@ -65,9 +60,8 @@ class JaceMindseekerEffect extends OneShotEffect {
public JaceMindseekerEffect() {
super(Outcome.PlayForFree);
- this.staticText = "target opponent puts the top five cards of their "
- + "library into their graveyard. You may cast an instant or "
- + "sorcery card from among them without paying its mana cost";
+ this.staticText = "target opponent mills five cards. You may cast an instant or sorcery spell " +
+ "from among them without paying its mana cost.";
}
public JaceMindseekerEffect(final JaceMindseekerEffect effect) {
@@ -84,10 +78,7 @@ class JaceMindseekerEffect extends OneShotEffect {
Cards cardsToCast = new CardsImpl();
Player targetOpponent = game.getPlayer(targetPointer.getFirst(game, source));
if (targetOpponent != null) {
- Set allCards = targetOpponent.getLibrary().getTopCards(game, 5);
- Set toMove = new HashSet<>();
- toMove.addAll(allCards);
- targetOpponent.moveCards(toMove, Zone.GRAVEYARD, source, game);
+ Set allCards = targetOpponent.millCards(5, source, game).getCards(game);
for (Card card : allCards) {
if (filter.match(card, game)) {
Zone zone = game.getState().getZone(card.getId());
diff --git a/Mage.Sets/src/mage/cards/k/KeeningStone.java b/Mage.Sets/src/mage/cards/k/KeeningStone.java
index 9ed4d7fbec9..11a4de0547c 100644
--- a/Mage.Sets/src/mage/cards/k/KeeningStone.java
+++ b/Mage.Sets/src/mage/cards/k/KeeningStone.java
@@ -1,7 +1,6 @@
package mage.cards.k;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
@@ -11,22 +10,22 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class KeeningStone extends CardImpl {
public KeeningStone(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{6}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}");
// {5}, {tap}: Target player puts the top X cards of their library into their graveyard, where X is the number of cards in that player's graveyard.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new KeeningStoneEffect(), new GenericManaCost(5));
+ Ability ability = new SimpleActivatedAbility(new KeeningStoneEffect(), new GenericManaCost(5));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
@@ -46,7 +45,7 @@ class KeeningStoneEffect extends OneShotEffect {
public KeeningStoneEffect() {
super(Outcome.Neutral);
- this.staticText = "Target player puts the top X cards of their library into their graveyard, where X is the number of cards in that player's graveyard";
+ this.staticText = "Target player mills X cards, where X is the number of cards in that player's graveyard";
}
public KeeningStoneEffect(final KeeningStoneEffect effect) {
@@ -62,7 +61,7 @@ class KeeningStoneEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getFirstTarget());
if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, player.getGraveyard().size()), Zone.GRAVEYARD, source, game);
+ player.millCards(player.getGraveyard().size(), source, game);
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/l/LammastideWeave.java b/Mage.Sets/src/mage/cards/l/LammastideWeave.java
index b8f979f472c..fc9365efdbc 100644
--- a/Mage.Sets/src/mage/cards/l/LammastideWeave.java
+++ b/Mage.Sets/src/mage/cards/l/LammastideWeave.java
@@ -9,7 +9,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
@@ -35,7 +34,7 @@ public final class LammastideWeave extends CardImpl {
}
- public LammastideWeave(final LammastideWeave card) {
+ private LammastideWeave(final LammastideWeave card) {
super(card);
}
@@ -47,13 +46,13 @@ public final class LammastideWeave extends CardImpl {
class LammastideWeaveEffect extends OneShotEffect {
- public LammastideWeaveEffect() {
+ LammastideWeaveEffect() {
super(Outcome.DrawCard);
- this.staticText = ", then target player puts the top card of their library into their graveyard. "
- + "If that card has the chosen name, you gain life equal to its converted mana cost.";
+ this.staticText = ", then target player mills a card. If a card with the chosen name was milled this way, " +
+ "you gain life equal to its converted mana cost.";
}
- public LammastideWeaveEffect(final LammastideWeaveEffect effect) {
+ private LammastideWeaveEffect(final LammastideWeaveEffect effect) {
super(effect);
}
@@ -67,17 +66,14 @@ class LammastideWeaveEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(source.getFirstTarget());
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) {
- Card card = targetPlayer.getLibrary().getFromTop(game);
- if (card != null) {
- controller.moveCards(card, Zone.GRAVEYARD, source, game);
- if (CardUtil.haveSameNames(card, cardName, game)) {
- controller.gainLife(card.getConvertedManaCost(), game, source);
- }
- }
- return true;
+ if (controller == null || targetPlayer == null || cardName == null || cardName.isEmpty()) {
+ return false;
}
- return false;
+ for (Card card : targetPlayer.millCards(1, source, game).getCards(game)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
+ controller.gainLife(card.getConvertedManaCost(), game, source);
+ }
+ }
+ return true;
}
-
}
diff --git a/Mage.Sets/src/mage/cards/l/LilianaUntouchedByDeath.java b/Mage.Sets/src/mage/cards/l/LilianaUntouchedByDeath.java
index f131e898ac6..dde813dd580 100644
--- a/Mage.Sets/src/mage/cards/l/LilianaUntouchedByDeath.java
+++ b/Mage.Sets/src/mage/cards/l/LilianaUntouchedByDeath.java
@@ -1,7 +1,5 @@
package mage.cards.l;
-import java.util.Set;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
@@ -12,22 +10,17 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.Card;
-import mage.constants.SubType;
-import mage.constants.SuperType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AsThoughEffectType;
-import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class LilianaUntouchedByDeath extends CardImpl {
@@ -73,8 +66,7 @@ class LilianaUntouchedByDeathEffect extends OneShotEffect {
public LilianaUntouchedByDeathEffect() {
super(Outcome.Benefit);
- this.staticText = "put the top three cards of your library into your graveyard. "
- + "If at least one of them is a Zombie card, each opponent loses 2 life and you gain 2 life";
+ this.staticText = "mill three cards. If at least one of them is a Zombie card, each opponent loses 2 life and you gain 2 life";
}
public LilianaUntouchedByDeathEffect(final LilianaUntouchedByDeathEffect effect) {
@@ -92,15 +84,11 @@ class LilianaUntouchedByDeathEffect extends OneShotEffect {
if (player == null) {
return false;
}
- boolean doEffect = false;
- Set top3 = player.moveCardsToGraveyardWithInfo(player.getLibrary().getTopCards(game, 3), source, game, Zone.LIBRARY);
- for (Card card : top3) {
- if (card != null && card.hasSubtype(SubType.ZOMBIE, game)) {
- doEffect = true;
- break;
- }
- }
- if (doEffect) {
+ if (player
+ .millCards(3, source, game)
+ .getCards(game)
+ .stream()
+ .anyMatch(card -> card.hasSubtype(SubType.ZOMBIE, game))) {
new LoseLifeOpponentsEffect(2).apply(game, source);
player.gainLife(2, game, source);
}
diff --git a/Mage.Sets/src/mage/cards/l/LilianasIndignation.java b/Mage.Sets/src/mage/cards/l/LilianasIndignation.java
index 67d0d59c1c7..3456d56f29f 100644
--- a/Mage.Sets/src/mage/cards/l/LilianasIndignation.java
+++ b/Mage.Sets/src/mage/cards/l/LilianasIndignation.java
@@ -1,24 +1,21 @@
package mage.cards.l;
-import java.util.Set;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
-import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class LilianasIndignation extends CardImpl {
@@ -45,7 +42,7 @@ class LilianasIndignationEffect extends OneShotEffect {
public LilianasIndignationEffect() {
super(Outcome.LoseLife);
- this.staticText = "Put the top X cards of your library into your graveyard. Target player loses 2 life for each creature card put into your graveyard this way";
+ this.staticText = "Mill X cards. Target player loses 2 life for each creature card put into your graveyard this way";
}
public LilianasIndignationEffect(final LilianasIndignationEffect effect) {
@@ -60,27 +57,28 @@ class LilianasIndignationEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- int x = source.getManaCostsToPay().getX();
- if (x > 0) {
- Cards cardsToGraveyard = new CardsImpl();
- cardsToGraveyard.addAll(controller.getLibrary().getTopCards(game, x));
- if (!cardsToGraveyard.isEmpty()) {
- Set movedCards = controller.moveCardsToGraveyardWithInfo(cardsToGraveyard.getCards(game), source, game, Zone.LIBRARY);
- Cards cardsMoved = new CardsImpl();
- cardsMoved.addAll(movedCards);
- int creatures = cardsMoved.count(StaticFilters.FILTER_CARD_CREATURE, game);
- if (creatures > 0) {
- Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
- if (targetPlayer != null) {
- targetPlayer.loseLife(creatures * 2, game, false);
- }
-
- }
- }
- }
+ if (controller == null) {
+ return false;
+ }
+ int xValue = source.getManaCostsToPay().getX();
+ if (xValue < 1) {
return true;
}
- return false;
+ int creatures = controller
+ .millCards(xValue, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(card -> game.getState().getZone(card.getId()) == Zone.GRAVEYARD)
+ .filter(MageObject::isCreature)
+ .mapToInt(x -> 2)
+ .sum();
+ if (creatures > 0) {
+ Player targetPlayer = game.getPlayer(source.getFirstTarget());
+ if (targetPlayer != null) {
+ targetPlayer.loseLife(creatures, game, false);
+ }
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/l/LoafingGiant.java b/Mage.Sets/src/mage/cards/l/LoafingGiant.java
index 0bffafbc682..2cd86e58f72 100644
--- a/Mage.Sets/src/mage/cards/l/LoafingGiant.java
+++ b/Mage.Sets/src/mage/cards/l/LoafingGiant.java
@@ -1,29 +1,31 @@
package mage.cards.l;
-import java.util.UUID;
import mage.MageInt;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.AttacksOrBlocksTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.PreventCombatDamageBySourceEffect;
-import mage.abilities.effects.common.combat.CantBeBlockedByAllSourceEffect;
-import mage.cards.Card;
-import mage.constants.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.filter.StaticFilters;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.game.Game;
import mage.players.Player;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author noahg
*/
public final class LoafingGiant extends CardImpl {
public LoafingGiant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}");
-
+
this.subtype.add(SubType.GIANT);
this.power = new MageInt(4);
this.toughness = new MageInt(6);
@@ -46,7 +48,7 @@ class LoafingGiantEffect extends OneShotEffect {
public LoafingGiantEffect() {
super(Outcome.UnboostCreature);
- this.staticText = "Put the top card of your library into your graveyard. If that card is a land card, prevent all combat damage {this} would deal this turn.";
+ this.staticText = "Mill a card. If a land card was milled this way, prevent all combat damage {this} would deal this turn.";
}
public LoafingGiantEffect(final LoafingGiantEffect effect) {
@@ -61,14 +63,14 @@ class LoafingGiantEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
- Card card = player.getLibrary().getFromTop(game);
- if (card != null) {
- player.moveCards(card, Zone.GRAVEYARD, source, game);
- if (card.isLand()) {
- game.addEffect(new PreventCombatDamageBySourceEffect(Duration.EndOfTurn), source);
- }
- }
+ if (player != null
+ && player
+ .millCards(1, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .anyMatch(MageObject::isLand)) {
+ game.addEffect(new PreventCombatDamageBySourceEffect(Duration.EndOfTurn), source);
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/m/ManicScribe.java b/Mage.Sets/src/mage/cards/m/ManicScribe.java
index 26db45a69da..775f264a519 100644
--- a/Mage.Sets/src/mage/cards/m/ManicScribe.java
+++ b/Mage.Sets/src/mage/cards/m/ManicScribe.java
@@ -1,7 +1,5 @@
package mage.cards.m;
-import java.util.UUID;
-
import mage.MageInt;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@@ -17,6 +15,8 @@ import mage.constants.SubType;
import mage.constants.TargetController;
import mage.constants.Zone;
+import java.util.UUID;
+
/**
* @author fireshoes
*/
@@ -30,19 +30,22 @@ public final class ManicScribe extends CardImpl {
this.toughness = new MageInt(3);
// When Manic Scribe enters the battlefield, each opponent puts the top three cards of their library into their graveyard.
- this.addAbility(new EntersBattlefieldTriggeredAbility(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(3, TargetController.OPPONENT), false));
+ this.addAbility(new EntersBattlefieldTriggeredAbility(
+ new PutTopCardOfLibraryIntoGraveEachPlayerEffect(3, TargetController.OPPONENT), false
+ ));
// Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard,
// that player puts the top three cards of their library into their graveyard.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
- new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new PutTopCardOfLibraryIntoGraveTargetEffect(3), TargetController.OPPONENT, false, true),
- DeliriumCondition.instance,
- "Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, "
- + "that player puts the top three cards of their library into their graveyard.")
- .addHint(DeliriumHint.instance));
+ new BeginningOfUpkeepTriggeredAbility(
+ Zone.BATTLEFIELD, new PutTopCardOfLibraryIntoGraveTargetEffect(3),
+ TargetController.OPPONENT, false, true
+ ), DeliriumCondition.instance, "Delirium — At the beginning of each opponent's upkeep, " +
+ "if there are four or more card types among cards in your graveyard, that player mills three cards."
+ ).addHint(DeliriumHint.instance));
}
- public ManicScribe(final ManicScribe card) {
+ private ManicScribe(final ManicScribe card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/m/MemoryErosion.java b/Mage.Sets/src/mage/cards/m/MemoryErosion.java
index dc6bfd720c8..5aa6273b58d 100644
--- a/Mage.Sets/src/mage/cards/m/MemoryErosion.java
+++ b/Mage.Sets/src/mage/cards/m/MemoryErosion.java
@@ -68,7 +68,7 @@ class SpellCastTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever an opponent casts a spell, that player puts the top two cards of their library into their graveyard";
+ return "Whenever an opponent casts a spell, that player mills two cards";
}
@Override
diff --git a/Mage.Sets/src/mage/cards/m/MesmericOrb.java b/Mage.Sets/src/mage/cards/m/MesmericOrb.java
index 6b8608259b9..9dae5bf385f 100644
--- a/Mage.Sets/src/mage/cards/m/MesmericOrb.java
+++ b/Mage.Sets/src/mage/cards/m/MesmericOrb.java
@@ -1,9 +1,7 @@
package mage.cards.m;
-import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -15,22 +13,21 @@ import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class MesmericOrb extends CardImpl {
public MesmericOrb(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// Whenever a permanent becomes untapped, that permanent's controller puts the top card of their library into their graveyard.
- Effect effect = new PutTopCardOfLibraryIntoGraveTargetEffect(1);
- effect.setText("that permanent's controller puts the top card of their library into their graveyard");
- this.addAbility(new BecomesUntappedPermanentTriggeredAbility(effect, false));
+ this.addAbility(new MesmericOrbTriggeredAbility());
}
- public MesmericOrb(final MesmericOrb card) {
+ private MesmericOrb(final MesmericOrb card) {
super(card);
}
@@ -40,19 +37,19 @@ public final class MesmericOrb extends CardImpl {
}
}
-class BecomesUntappedPermanentTriggeredAbility extends TriggeredAbilityImpl{
+class MesmericOrbTriggeredAbility extends TriggeredAbilityImpl {
- public BecomesUntappedPermanentTriggeredAbility(Effect effect, boolean optional) {
- super(Zone.BATTLEFIELD, effect, optional);
+ MesmericOrbTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new PutTopCardOfLibraryIntoGraveTargetEffect(1), false);
}
- public BecomesUntappedPermanentTriggeredAbility(final BecomesUntappedPermanentTriggeredAbility ability) {
+ private MesmericOrbTriggeredAbility(final MesmericOrbTriggeredAbility ability) {
super(ability);
}
@Override
- public BecomesUntappedPermanentTriggeredAbility copy() {
- return new BecomesUntappedPermanentTriggeredAbility(this);
+ public MesmericOrbTriggeredAbility copy() {
+ return new MesmericOrbTriggeredAbility(this);
}
@Override
@@ -72,7 +69,7 @@ class BecomesUntappedPermanentTriggeredAbility extends TriggeredAbilityImpl{
@Override
public String getRule() {
- return "Whenever a permanent becomes untapped, " + super.getRule();
+ return "Whenever a permanent becomes untapped, that permanent's controller mills a card.";
}
}
diff --git a/Mage.Sets/src/mage/cards/m/Mindcrank.java b/Mage.Sets/src/mage/cards/m/Mindcrank.java
index 435ee718a66..f2610c32dc5 100644
--- a/Mage.Sets/src/mage/cards/m/Mindcrank.java
+++ b/Mage.Sets/src/mage/cards/m/Mindcrank.java
@@ -104,7 +104,7 @@ class MindcrankEffect extends OneShotEffect {
if (amount == null) {
amount = 0;
}
- targetPlayer.moveCards(targetPlayer.getLibrary().getTopCards(game, amount), Zone.GRAVEYARD, source, game);
+ targetPlayer.millCards(amount, source, game);
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/m/Mindshrieker.java b/Mage.Sets/src/mage/cards/m/Mindshrieker.java
index b8effb0479e..ad0be568073 100644
--- a/Mage.Sets/src/mage/cards/m/Mindshrieker.java
+++ b/Mage.Sets/src/mage/cards/m/Mindshrieker.java
@@ -1,20 +1,24 @@
package mage.cards.m;
import mage.MageInt;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
-import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.FlyingAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.Objects;
import java.util.UUID;
/**
@@ -34,10 +38,9 @@ public final class Mindshrieker extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// {2}: Target player puts the top card of their library into their graveyard. Mindshrieker gets +X/+X until end of turn, where X is that card's converted mana cost.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MindshriekerEffect(), new ManaCostsImpl("{2}"));
+ Ability ability = new SimpleActivatedAbility(new MindshriekerEffect(), new GenericManaCost(2));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
-
}
public Mindshrieker(final Mindshrieker card) {
@@ -52,30 +55,31 @@ public final class Mindshrieker extends CardImpl {
class MindshriekerEffect extends OneShotEffect {
- public MindshriekerEffect() {
+ MindshriekerEffect() {
super(Outcome.Detriment);
- staticText = "Target player puts the top card of their library into their graveyard. {this} gets +X/+X until end of turn, where X is that card's converted mana cost";
+ staticText = "Target player mills a card. {this} gets +X/+X until end of turn, " +
+ "where X is the milled card's converted mana cost";
}
- public MindshriekerEffect(final MindshriekerEffect effect) {
+ private MindshriekerEffect(final MindshriekerEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(source.getFirstTarget());
- if (targetPlayer != null) {
- if (targetPlayer.getLibrary().hasCards()) {
- Card card = targetPlayer.getLibrary().getFromTop(game);
- if (card != null) {
- targetPlayer.moveCards(card, Zone.GRAVEYARD, source, game);
- int amount = card.getConvertedManaCost();
- if (amount > 0) {
- game.addEffect(new BoostSourceEffect(amount, amount, Duration.EndOfTurn), source);
- }
- }
- }
- return true;
+ if (targetPlayer == null) {
+ return false;
+ }
+ int totalCMC = targetPlayer
+ .millCards(1, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .mapToInt(MageObject::getConvertedManaCost)
+ .sum();
+ if (totalCMC > 0) {
+ game.addEffect(new BoostSourceEffect(totalCMC, totalCMC, Duration.EndOfTurn), source);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java b/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java
index 2b3ecb389c3..d9fe043d271 100644
--- a/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java
+++ b/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java
@@ -1,7 +1,5 @@
-
package mage.cards.n;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.condition.common.RaidCondition;
@@ -14,8 +12,9 @@ import mage.constants.TargetController;
import mage.target.common.TargetOpponent;
import mage.watchers.common.PlayerAttackedWatcher;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class NavigatorsRuin extends CardImpl {
@@ -25,14 +24,16 @@ public final class NavigatorsRuin extends CardImpl {
// Raid - At the beginning of your end step, if you attacked with a creature this turm, target opponent puts the top four cards of their library into their graveyard.
Ability ability = new ConditionalInterveningIfTriggeredAbility(
- new BeginningOfEndStepTriggeredAbility(new PutLibraryIntoGraveTargetEffect(4), TargetController.YOU, false),
- RaidCondition.instance,
- "Raid — At the beginning of your end step, if you attacked this turn, target opponent puts the top four cards of their library into their graveyard.");
+ new BeginningOfEndStepTriggeredAbility(
+ new PutLibraryIntoGraveTargetEffect(4), TargetController.YOU, false
+ ), RaidCondition.instance, "Raid — At the beginning of your end step, " +
+ "if you attacked this turn, target opponent mills four cards."
+ );
ability.addTarget(new TargetOpponent());
this.addAbility(ability, new PlayerAttackedWatcher());
}
- public NavigatorsRuin(final NavigatorsRuin card) {
+ private NavigatorsRuin(final NavigatorsRuin card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/n/NemesisOfReason.java b/Mage.Sets/src/mage/cards/n/NemesisOfReason.java
index e3dd3529c90..bb8296c7b67 100644
--- a/Mage.Sets/src/mage/cards/n/NemesisOfReason.java
+++ b/Mage.Sets/src/mage/cards/n/NemesisOfReason.java
@@ -2,7 +2,6 @@
package mage.cards.n;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
@@ -16,27 +15,26 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.targetpointer.FixedTarget;
+import java.util.UUID;
+
/**
- *
* @author Loki
*/
public final class NemesisOfReason extends CardImpl {
- public NemesisOfReason (UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{B}");
+ public NemesisOfReason(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{B}");
this.subtype.add(SubType.LEVIATHAN);
this.subtype.add(SubType.HORROR);
-
+
this.power = new MageInt(3);
this.toughness = new MageInt(7);
-
+
// Whenever Nemesis of Reason attacks, defending player puts the top ten cards of their library into their graveyard.
- Effect effect = new PutLibraryIntoGraveTargetEffect(10);
- effect.setText("defending player puts the top ten cards of their library into their graveyard");
- this.addAbility(new NemesisOfReasonTriggeredAbility(effect));
+ this.addAbility(new NemesisOfReasonTriggeredAbility(new PutLibraryIntoGraveTargetEffect(10)));
}
- public NemesisOfReason (final NemesisOfReason card) {
+ public NemesisOfReason(final NemesisOfReason card) {
super(card);
}
@@ -47,12 +45,12 @@ public final class NemesisOfReason extends CardImpl {
}
class NemesisOfReasonTriggeredAbility extends TriggeredAbilityImpl {
-
+
NemesisOfReasonTriggeredAbility(Effect effect) {
super(Zone.BATTLEFIELD, effect);
}
- NemesisOfReasonTriggeredAbility(final NemesisOfReasonTriggeredAbility ability) {
+ private NemesisOfReasonTriggeredAbility(final NemesisOfReasonTriggeredAbility ability) {
super(ability);
}
@@ -68,9 +66,9 @@ class NemesisOfReasonTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
- if (event.getSourceId().equals(this.getSourceId()) ) {
+ if (event.getSourceId().equals(this.getSourceId())) {
UUID defenderId = game.getCombat().getDefendingPlayerId(this.getSourceId(), game);
- for (Effect effect : this.getEffects()) {
+ for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(defenderId));
}
return true;
@@ -80,6 +78,6 @@ class NemesisOfReasonTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever {this} attacks, defending player puts the top ten cards of their library into their graveyard.";
+ return "Whenever {this} attacks, defending player mills ten cards.";
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/p/PatientRebuilding.java b/Mage.Sets/src/mage/cards/p/PatientRebuilding.java
index 130c1182c36..9f4b2ee7bc4 100644
--- a/Mage.Sets/src/mage/cards/p/PatientRebuilding.java
+++ b/Mage.Sets/src/mage/cards/p/PatientRebuilding.java
@@ -1,7 +1,5 @@
package mage.cards.p;
-import java.util.Set;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@@ -11,13 +9,14 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class PatientRebuilding extends CardImpl {
@@ -49,7 +48,7 @@ class PatientRebuildingEffect extends OneShotEffect {
public PatientRebuildingEffect() {
super(Outcome.DrawCard);
- this.staticText = "target opponent puts the top three cards of their library into their graveyard, "
+ this.staticText = "target opponent mills three cards, "
+ "then you draw a card for each land card put into that graveyard this way";
}
@@ -70,7 +69,7 @@ class PatientRebuildingEffect extends OneShotEffect {
return false;
}
int numberOfLandCards = 0;
- Set movedCards = player.moveCardsToGraveyardWithInfo(player.getLibrary().getTopCards(game, 3), source, game, Zone.LIBRARY);
+ Set movedCards = player.millCards(3, source, game).getCards(game);
for (Card card : movedCards) {
if (card.isLand()) {
numberOfLandCards++;
diff --git a/Mage.Sets/src/mage/cards/p/PhenaxGodOfDeception.java b/Mage.Sets/src/mage/cards/p/PhenaxGodOfDeception.java
index ec36c25ab34..decaf844f26 100644
--- a/Mage.Sets/src/mage/cards/p/PhenaxGodOfDeception.java
+++ b/Mage.Sets/src/mage/cards/p/PhenaxGodOfDeception.java
@@ -45,14 +45,12 @@ public final class PhenaxGodOfDeception extends CardImpl {
// Creatures you control have "{T}: Target player puts the top X cards of their library into their graveyard, where X is this creature's toughness."
Ability ability = new SimpleActivatedAbility(
new PutTopCardOfLibraryIntoGraveTargetEffect(SourcePermanentToughnessValue.getInstance())
- .setText("Target player puts the top X cards of their library into their graveyard, " +
- "where X is this creature's toughness"), new TapSourceCost());
+ .setText("Target player mills X cards, where X is this creature's toughness"), new TapSourceCost());
ability.addTarget(new TargetPlayer());
this.addAbility(new SimpleStaticAbility(
new GainAbilityControlledEffect(
ability, Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES, false
- ).setText("Creatures you control have \"{T}: Target player puts the top X cards of their library " +
- "into their graveyard, where X is this creature's toughness.\"")
+ ).setText("Creatures you control have \"{T}: Target player mills X cards, where X is this creature's toughness.\"")
));
}
diff --git a/Mage.Sets/src/mage/cards/p/Predict.java b/Mage.Sets/src/mage/cards/p/Predict.java
index e4f98c5a954..d53aa652fd6 100644
--- a/Mage.Sets/src/mage/cards/p/Predict.java
+++ b/Mage.Sets/src/mage/cards/p/Predict.java
@@ -8,7 +8,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
@@ -30,7 +29,7 @@ public final class Predict extends CardImpl {
this.getSpellAbility().addTarget(new TargetPlayer());
}
- public Predict(final Predict card) {
+ private Predict(final Predict card) {
super(card);
}
@@ -42,13 +41,13 @@ public final class Predict extends CardImpl {
class PredictEffect extends OneShotEffect {
- public PredictEffect() {
+ PredictEffect() {
super(Outcome.DrawCard);
- this.staticText = ", then target player puts the top card of their library into their graveyard. "
- + "If that card has the chosen name, you draw two cards. Otherwise, you draw a card.";
+ this.staticText = ", then target player mills a card. If a card with the chosen name was milled this way, " +
+ "you draw two cards. Otherwise, you draw a card.";
}
- public PredictEffect(final PredictEffect effect) {
+ private PredictEffect(final PredictEffect effect) {
super(effect);
}
@@ -62,19 +61,17 @@ class PredictEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(source.getFirstTarget());
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) {
- int amount = 1;
- Card card = targetPlayer.getLibrary().getFromTop(game);
- if (card != null) {
- controller.moveCards(card, Zone.GRAVEYARD, source, game);
- if (CardUtil.haveSameNames(card, cardName, game)) {
- amount = 2;
- }
- }
- controller.drawCards(amount, source.getSourceId(), game);
- return true;
+ if (controller == null || targetPlayer == null || cardName == null || cardName.isEmpty()) {
+ return false;
}
- return false;
+ int toDraw = 1;
+ for (Card card : targetPlayer.millCards(1, source, game).getCards(game)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
+ toDraw = 2;
+ break;
+ }
+ }
+ controller.drawCards(toDraw, source.getSourceId(), game);
+ return true;
}
-
}
diff --git a/Mage.Sets/src/mage/cards/p/PsychicSpiral.java b/Mage.Sets/src/mage/cards/p/PsychicSpiral.java
index f142d790429..6595fa697ee 100644
--- a/Mage.Sets/src/mage/cards/p/PsychicSpiral.java
+++ b/Mage.Sets/src/mage/cards/p/PsychicSpiral.java
@@ -63,7 +63,7 @@ class PsychicSpiralEffect extends OneShotEffect {
if (cardsInGraveyard > 0) {
Player targetPlayer = game.getPlayer(source.getFirstTarget());
if (targetPlayer != null) {
- targetPlayer.moveCards(targetPlayer.getLibrary().getTopCards(game, cardsInGraveyard), Zone.GRAVEYARD, source, game);
+ targetPlayer.millCards(cardsInGraveyard, source, game);
}
}
return true;
diff --git a/Mage.Sets/src/mage/cards/p/PsychicStrike.java b/Mage.Sets/src/mage/cards/p/PsychicStrike.java
index f5c63b1c1f4..344c345efed 100644
--- a/Mage.Sets/src/mage/cards/p/PsychicStrike.java
+++ b/Mage.Sets/src/mage/cards/p/PsychicStrike.java
@@ -66,7 +66,7 @@ class PsychicStrikeEffect extends OneShotEffect {
if (stackObject != null) {
Player controller = game.getPlayer(stackObject.getControllerId());
if (controller != null) {
- controller.moveCards(controller.getLibrary().getTopCards(game, 2), Zone.GRAVEYARD, source, game);
+ controller.millCards(2, source, game);
}
}
return countered;
diff --git a/Mage.Sets/src/mage/cards/r/RakshasasSecret.java b/Mage.Sets/src/mage/cards/r/RakshasasSecret.java
index 0b62846b48c..2f2ea93bdae 100644
--- a/Mage.Sets/src/mage/cards/r/RakshasasSecret.java
+++ b/Mage.Sets/src/mage/cards/r/RakshasasSecret.java
@@ -1,8 +1,5 @@
-
package mage.cards.r;
-import java.util.UUID;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.cards.CardImpl;
@@ -10,25 +7,23 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author emerald000
*/
public final class RakshasasSecret extends CardImpl {
public RakshasasSecret(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}");
// Target opponent discards two cards. Put the top two cards of your library into your graveyard.
this.getSpellAbility().addEffect(new DiscardTargetEffect(2));
this.getSpellAbility().addTarget(new TargetOpponent());
- Effect effect = new PutTopCardOfLibraryIntoGraveControllerEffect(2);
- effect.setText("Put the top two cards of your library into your graveyard");
- this.getSpellAbility().addEffect(effect);
+ this.getSpellAbility().addEffect(new PutTopCardOfLibraryIntoGraveControllerEffect(2).setText("Mill two cards."));
}
- public RakshasasSecret(final RakshasasSecret card) {
+ private RakshasasSecret(final RakshasasSecret card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/r/ReefPirates.java b/Mage.Sets/src/mage/cards/r/ReefPirates.java
index 970faaf4adc..b74cbde8fe4 100644
--- a/Mage.Sets/src/mage/cards/r/ReefPirates.java
+++ b/Mage.Sets/src/mage/cards/r/ReefPirates.java
@@ -26,7 +26,7 @@ public final class ReefPirates extends CardImpl {
// Whenever Reef Pirates deals damage to an opponent, that player puts the top card of their library into their graveyard.
Effect effect = new PutLibraryIntoGraveTargetEffect(1);
- effect.setText("that player puts the top card of their library into their graveyard");
+ effect.setText("that player mills a card");
this.addAbility(new DealsDamageToAPlayerTriggeredAbility(effect, false, true));
}
diff --git a/Mage.Sets/src/mage/cards/r/Riddlekeeper.java b/Mage.Sets/src/mage/cards/r/Riddlekeeper.java
index 2310fa20ee5..d6d08f9799d 100644
--- a/Mage.Sets/src/mage/cards/r/Riddlekeeper.java
+++ b/Mage.Sets/src/mage/cards/r/Riddlekeeper.java
@@ -28,7 +28,7 @@ public final class Riddlekeeper extends CardImpl {
// Whenever a creature attacks you or a planeswalker you control, that creature's controller puts the top two cards of their library into their graveyard.
Effect effect = new PutTopCardOfLibraryIntoGraveTargetEffect(2);
- effect.setText("that creature's controller puts the top two cards of their library into their graveyard");
+ effect.setText("that creature's controller mills two cards");
this.addAbility(new AttacksAllTriggeredAbility(effect, false, StaticFilters.FILTER_PERMANENT_CREATURE, SetTargetPointer.PLAYER, true, true));
}
diff --git a/Mage.Sets/src/mage/cards/s/SanityGrinding.java b/Mage.Sets/src/mage/cards/s/SanityGrinding.java
index a63afd36f95..ae141fcb70d 100644
--- a/Mage.Sets/src/mage/cards/s/SanityGrinding.java
+++ b/Mage.Sets/src/mage/cards/s/SanityGrinding.java
@@ -1,33 +1,26 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
-import mage.cards.CardImpl;
-import mage.cards.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
+import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author jeffwadsworth
- *
*/
public final class SanityGrinding extends CardImpl {
public SanityGrinding(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{U}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}{U}{U}");
// Chroma - Reveal the top ten cards of your library. For each blue mana symbol in the mana costs of the revealed cards, target opponent puts the top card of their library into their graveyard. Then put the cards you revealed this way on the bottom of your library in any order.
this.getSpellAbility().addEffect(new SanityGrindingEffect());
@@ -49,7 +42,9 @@ class SanityGrindingEffect extends OneShotEffect {
public SanityGrindingEffect() {
super(Outcome.Neutral);
- staticText = "Chroma — Reveal the top ten cards of your library. For each blue mana symbol in the mana costs of the revealed cards, target opponent puts the top card of their library into their graveyard. Then put the cards you revealed this way on the bottom of your library in any order";
+ staticText = "Chroma — Reveal the top ten cards of your library. " +
+ "For each blue mana symbol in the mana costs of the revealed cards, target opponent mills a card. " +
+ "Then put the cards you revealed this way on the bottom of your library in any order";
}
public SanityGrindingEffect(final SanityGrindingEffect effect) {
@@ -68,8 +63,7 @@ class SanityGrindingEffect extends OneShotEffect {
controller.revealCards(sourceObject.getIdName(), revealed, game);
Player targetOpponent = game.getPlayer(source.getFirstTarget());
if (targetOpponent != null) {
- targetOpponent.moveCards(targetOpponent.getLibrary().getTopCards(game, new ChromaSanityGrindingCount(revealed).calculate(game, source, this)),
- Zone.GRAVEYARD, source, game);
+ targetOpponent.millCards(new ChromaSanityGrindingCount(revealed).calculate(game, source, this), source, game);
}
return controller.putCardsOnBottomOfLibrary(revealed, game, source, true);
}
diff --git a/Mage.Sets/src/mage/cards/s/SaprazzanBreaker.java b/Mage.Sets/src/mage/cards/s/SaprazzanBreaker.java
index df66369b2ed..336099b0710 100644
--- a/Mage.Sets/src/mage/cards/s/SaprazzanBreaker.java
+++ b/Mage.Sets/src/mage/cards/s/SaprazzanBreaker.java
@@ -1,27 +1,24 @@
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.combat.CantBeBlockedByAllSourceEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author L_J
*/
public final class SaprazzanBreaker extends CardImpl {
@@ -36,7 +33,7 @@ public final class SaprazzanBreaker extends CardImpl {
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new SaprazzanBreakerEffect(), new ManaCostsImpl("{U}")));
}
- public SaprazzanBreaker(final SaprazzanBreaker card) {
+ private SaprazzanBreaker(final SaprazzanBreaker card) {
super(card);
}
@@ -48,12 +45,12 @@ public final class SaprazzanBreaker extends CardImpl {
class SaprazzanBreakerEffect extends OneShotEffect {
- public SaprazzanBreakerEffect() {
+ SaprazzanBreakerEffect() {
super(Outcome.Benefit);
- this.staticText = "Put the top card of your library into your graveyard. If that card is a land card, {this} can't be blocked this turn";
+ this.staticText = "Mill a card. If a land card was milled this way, {this} can't be blocked this turn";
}
- public SaprazzanBreakerEffect(final SaprazzanBreakerEffect effect) {
+ private SaprazzanBreakerEffect(final SaprazzanBreakerEffect effect) {
super(effect);
}
@@ -65,16 +62,12 @@ class SaprazzanBreakerEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
- Card card = player.getLibrary().getFromTop(game);
- if (card != null) {
- player.moveCards(card, Zone.GRAVEYARD, source, game);
- if (card.isLand()) {
- game.addEffect(new CantBeBlockedByAllSourceEffect(StaticFilters.FILTER_PERMANENT_CREATURES, Duration.EndOfTurn), source);
- }
- }
- return true;
+ if (player == null) {
+ return false;
}
- return false;
+ if (player.millCards(1, source, game).getCards(game).stream().filter(Objects::nonNull).anyMatch(MageObject::isLand)) {
+ game.addEffect(new CantBeBlockedByAllSourceEffect(StaticFilters.FILTER_PERMANENT_CREATURES, Duration.EndOfTurn), source);
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/s/ScreamingShield.java b/Mage.Sets/src/mage/cards/s/ScreamingShield.java
index a31cb67e01a..0e37473c597 100644
--- a/Mage.Sets/src/mage/cards/s/ScreamingShield.java
+++ b/Mage.Sets/src/mage/cards/s/ScreamingShield.java
@@ -37,7 +37,7 @@ public final class ScreamingShield extends CardImpl {
Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(0, 3));
ability.addEffect(new GainAbilityAttachedEffect(
toAdd, AttachmentType.EQUIPMENT
- ).setText("and has \"{2}, {T}: Target player puts the top three cards of their library into their graveyard.\""));
+ ).setText("and has \"{2}, {T}: Target player mills three cards.\""));
this.addAbility(ability);
// Equip {3}
diff --git a/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java b/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java
index da04611f60d..87a8f4c538c 100644
--- a/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java
+++ b/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java
@@ -1,7 +1,6 @@
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
@@ -14,16 +13,15 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
+import java.util.UUID;
+
/**
- *
* @author ayratn
*/
public final class ScreechingSilcaw extends CardImpl {
- private static final String rule = "Metalcraft — Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard.";
-
public ScreechingSilcaw(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.BIRD);
this.power = new MageInt(1);
@@ -33,8 +31,11 @@ public final class ScreechingSilcaw extends CardImpl {
//"Metalcraft — Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard.
TriggeredAbility conditional = new ConditionalInterveningIfTriggeredAbility(
- new DealsCombatDamageToAPlayerTriggeredAbility(new PutLibraryIntoGraveTargetEffect(4), false, true),
- MetalcraftCondition.instance, rule);
+ new DealsCombatDamageToAPlayerTriggeredAbility(
+ new PutLibraryIntoGraveTargetEffect(4), false, true
+ ), MetalcraftCondition.instance, "Metalcraft — Whenever {this} " +
+ "deals combat damage to a player, if you control three or more artifacts, that player mills four cards."
+ );
this.addAbility(conditional);
}
diff --git a/Mage.Sets/src/mage/cards/s/ScreechingSliver.java b/Mage.Sets/src/mage/cards/s/ScreechingSliver.java
index 908ef9eda5e..c91946e029b 100644
--- a/Mage.Sets/src/mage/cards/s/ScreechingSliver.java
+++ b/Mage.Sets/src/mage/cards/s/ScreechingSliver.java
@@ -37,7 +37,7 @@ public final class ScreechingSliver extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield,
- allSliversFilter, "All Slivers have \"{T}: Target player puts the top card of their library into their graveyard.\"")));
+ allSliversFilter, "All Slivers have \"{T}: Target player mills a card.\"")));
}
public ScreechingSliver(final ScreechingSliver card) {
diff --git a/Mage.Sets/src/mage/cards/s/SewerNemesis.java b/Mage.Sets/src/mage/cards/s/SewerNemesis.java
index 7bfc1fa2fca..612a44b550f 100644
--- a/Mage.Sets/src/mage/cards/s/SewerNemesis.java
+++ b/Mage.Sets/src/mage/cards/s/SewerNemesis.java
@@ -114,7 +114,7 @@ class SewerNemesisTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever the chosen player casts a spell, that player puts the top card of their library into their graveyard.";
+ return "Whenever the chosen player casts a spell, that player mills a card.";
}
@Override
diff --git a/Mage.Sets/src/mage/cards/s/SharedTrauma.java b/Mage.Sets/src/mage/cards/s/SharedTrauma.java
index 915bbbeeb15..2f82c35a9bd 100644
--- a/Mage.Sets/src/mage/cards/s/SharedTrauma.java
+++ b/Mage.Sets/src/mage/cards/s/SharedTrauma.java
@@ -43,7 +43,7 @@ class SharedTraumaEffect extends OneShotEffect {
public SharedTraumaEffect() {
super(Outcome.Detriment);
- this.staticText = "Join forces — Starting with you, each player may pay any amount of mana. Each player puts the top X cards of their library into their graveyard, where X is the total amount of mana paid this way";
+ this.staticText = "Join forces — Starting with you, each player may pay any amount of mana. Each player mills X cards, where X is the total amount of mana paid this way";
}
public SharedTraumaEffect(final SharedTraumaEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/s/Shriekgeist.java b/Mage.Sets/src/mage/cards/s/Shriekgeist.java
index fb41104d802..9c0b1c8c0d6 100644
--- a/Mage.Sets/src/mage/cards/s/Shriekgeist.java
+++ b/Mage.Sets/src/mage/cards/s/Shriekgeist.java
@@ -80,6 +80,6 @@ class ShriekgeistTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever {this} deals combat damage to a player, that player puts the top two cards of their library into their graveyard.";
+ return "Whenever {this} deals combat damage to a player, that player mills two cards.";
}
}
diff --git a/Mage.Sets/src/mage/cards/s/SirenOfTheSilentSong.java b/Mage.Sets/src/mage/cards/s/SirenOfTheSilentSong.java
index 9bb077784a8..9bde3310b1e 100644
--- a/Mage.Sets/src/mage/cards/s/SirenOfTheSilentSong.java
+++ b/Mage.Sets/src/mage/cards/s/SirenOfTheSilentSong.java
@@ -34,7 +34,7 @@ public final class SirenOfTheSilentSong extends CardImpl {
// Inspired — Whenever Siren of the Silent Song becomes untapped, each opponent discards a card, then puts the top card of their library into their graveyard.
Ability ability = new InspiredAbility(new DiscardEachPlayerEffect(TargetController.OPPONENT));
Effect effect = new PutTopCardOfLibraryIntoGraveEachPlayerEffect(1, TargetController.OPPONENT);
- effect.setText(", then puts the top card of their library into their graveyard");
+ effect.setText(", then mills a card");
ability.addEffect(effect);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/s/SongOfBlood.java b/Mage.Sets/src/mage/cards/s/SongOfBlood.java
index d786f476dda..9838614994a 100644
--- a/Mage.Sets/src/mage/cards/s/SongOfBlood.java
+++ b/Mage.Sets/src/mage/cards/s/SongOfBlood.java
@@ -1,22 +1,17 @@
package mage.cards.s;
-import java.util.Set;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
-import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
@@ -24,8 +19,10 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author spjspj
*/
public final class SongOfBlood extends CardImpl {
@@ -38,7 +35,7 @@ public final class SongOfBlood extends CardImpl {
this.getSpellAbility().addEffect(new SongOfBloodEffect());
}
- public SongOfBlood(final SongOfBlood card) {
+ private SongOfBlood(final SongOfBlood card) {
super(card);
}
@@ -50,13 +47,14 @@ public final class SongOfBlood extends CardImpl {
class SongOfBloodEffect extends OneShotEffect {
- public SongOfBloodEffect() {
+ SongOfBloodEffect() {
super(Outcome.LoseLife);
- this.staticText = "Put the top four cards of your library into your graveyard.";
+ this.staticText = "Mill four cards. Whenever a creature attacks this turn, " +
+ "it gets +1/+0 until end of turn for each creature card put into your graveyard this way.";
}
- public SongOfBloodEffect(final SongOfBloodEffect effect) {
+ private SongOfBloodEffect(final SongOfBloodEffect effect) {
super(effect);
}
@@ -68,36 +66,35 @@ class SongOfBloodEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Cards cardsToGraveyard = new CardsImpl();
- cardsToGraveyard.addAll(controller.getLibrary().getTopCards(game, 4));
- if (!cardsToGraveyard.isEmpty()) {
- Set movedCards = controller.moveCardsToGraveyardWithInfo(cardsToGraveyard.getCards(game), source, game, Zone.LIBRARY);
- Cards cardsMoved = new CardsImpl();
- cardsMoved.addAll(movedCards);
- int creatures = cardsMoved.count(StaticFilters.FILTER_CARD_CREATURE, game);
- if (creatures > 0) {
- // Setup a delayed trigger to give +X/+0 to any creature attacking this turn..
- DelayedTriggeredAbility delayedAbility = new SongOfBloodTriggeredAbility(creatures);
- game.addDelayedTriggeredAbility(delayedAbility, source);
- }
- }
- return true;
+ if (controller == null) {
+ return false;
}
- return false;
+ int creatures = controller
+ .millCards(4, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(card -> game.getState().getZone(card.getId()) == Zone.GRAVEYARD)
+ .filter(MageObject::isCreature)
+ .mapToInt(x -> 1)
+ .sum();
+ // Setup a delayed trigger to give +X/+0 to any creature attacking this turn..
+ DelayedTriggeredAbility delayedAbility = new SongOfBloodTriggeredAbility(creatures);
+ game.addDelayedTriggeredAbility(delayedAbility, source);
+ return true;
}
}
class SongOfBloodTriggeredAbility extends DelayedTriggeredAbility {
- int booster;
+ private final int booster;
- public SongOfBloodTriggeredAbility(int booster) {
+ SongOfBloodTriggeredAbility(int booster) {
super(new BoostTargetEffect(booster, 0, Duration.EndOfTurn), Duration.EndOfTurn, false);
this.booster = booster;
}
- public SongOfBloodTriggeredAbility(SongOfBloodTriggeredAbility ability) {
+ private SongOfBloodTriggeredAbility(SongOfBloodTriggeredAbility ability) {
super(ability);
this.booster = ability.booster;
}
@@ -126,6 +123,6 @@ class SongOfBloodTriggeredAbility extends DelayedTriggeredAbility {
@Override
public String getRule() {
- return "Whenever a creature attacks this turn, it gets +1/+0 (+" + booster + "/0) until end of turn for each creature card put into your graveyard this way.";
+ return "Whenever a creature attacks this turn, it gets +" + booster + "/0 until end of turn.";
}
}
diff --git a/Mage.Sets/src/mage/cards/s/SphinxsTutelage.java b/Mage.Sets/src/mage/cards/s/SphinxsTutelage.java
index 1b5868ca4e0..372f47facf9 100644
--- a/Mage.Sets/src/mage/cards/s/SphinxsTutelage.java
+++ b/Mage.Sets/src/mage/cards/s/SphinxsTutelage.java
@@ -1,7 +1,7 @@
package mage.cards.s;
-import java.util.UUID;
+import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.DrawCardControllerTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@@ -11,8 +11,6 @@ import mage.abilities.effects.common.DrawDiscardControllerEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@@ -20,8 +18,11 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
/**
- *
* @author LevelX2
*/
public final class SphinxsTutelage extends CardImpl {
@@ -52,7 +53,7 @@ class SphinxsTutelageEffect extends OneShotEffect {
public SphinxsTutelageEffect() {
super(Outcome.Benefit);
- this.staticText = "target opponent puts the top two cards of their library into their graveyard. If they're both nonland cards that share a color, repeat this process";
+ this.staticText = "target opponent mills two cards. If two nonland cards that share a color were milled this way, repeat this process.";
}
public SphinxsTutelageEffect(final SphinxsTutelageEffect effect) {
@@ -67,10 +68,11 @@ class SphinxsTutelageEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source));
- boolean colorShared;
+
if (targetPlayer != null) {
int possibleIterations = targetPlayer.getLibrary().size() / 2;
int iteration = 0;
+ boolean colorShared;
do {
iteration++;
if (iteration > possibleIterations + 20) {
@@ -82,20 +84,35 @@ class SphinxsTutelageEffect extends OneShotEffect {
return true;
}
colorShared = false;
- Cards cards = new CardsImpl(targetPlayer.getLibrary().getTopCards(game, 2));
- Card card1 = null;
- for (Card card : cards.getCards(game)) {
- if (card.isLand()) {
+ List cards = targetPlayer
+ .millCards(2, source, game)
+ .getCards(game)
+ .stream()
+ .filter(card -> !card.isLand())
+ .collect(Collectors.toList());
+ if (cards.size() < 2) {
+ break;
+ }
+ for (int i = 0; i < cards.size(); i++) {
+ if (colorShared) {
break;
}
- if (card1 == null) {
- card1 = card;
- } else {
- colorShared = card1.getColor(game).shares(card.getColor(game));
+ ObjectColor color1 = cards.get(i).getColor(game);
+ if (color1.isColorless()) {
+ continue;
+ }
+ for (int j = 0; j < cards.size(); j++) {
+ if (i >= j) {
+ continue;
+ }
+ ObjectColor color2 = cards.get(j).getColor(game);
+ if (color1.shares(color2)) {
+ colorShared = true;
+ break;
+ }
}
}
- targetPlayer.moveCards(cards, Zone.GRAVEYARD, source, game);
- } while (colorShared && targetPlayer.isInGame());
+ } while (colorShared);
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/s/SternMentor.java b/Mage.Sets/src/mage/cards/s/SternMentor.java
index f920d8448ea..997d6be1487 100644
--- a/Mage.Sets/src/mage/cards/s/SternMentor.java
+++ b/Mage.Sets/src/mage/cards/s/SternMentor.java
@@ -22,7 +22,8 @@ import mage.target.TargetPlayer;
*/
public final class SternMentor extends CardImpl {
- private static final String ruleText = "As long as {this} is paired with another creature, each of those creatures has \"{T}: Target player puts the top two cards of their library into their graveyard.\"";
+ private static final String ruleText = "As long as {this} is paired with another creature, " +
+ "each of those creatures has \"{T}: Target player mills two cards.\"";
public SternMentor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}");
diff --git a/Mage.Sets/src/mage/cards/s/StitcherGeralf.java b/Mage.Sets/src/mage/cards/s/StitcherGeralf.java
index 9c84a668d3c..bbfc44d0d0d 100644
--- a/Mage.Sets/src/mage/cards/s/StitcherGeralf.java
+++ b/Mage.Sets/src/mage/cards/s/StitcherGeralf.java
@@ -56,7 +56,7 @@ class StitcherGeralfEffect extends OneShotEffect {
public StitcherGeralfEffect() {
super(Outcome.PutCreatureInPlay);
- this.staticText = "Each player puts the top three cards of their library into their graveyard. Exile up to two creature cards put into graveyards this way. Create an X/X blue Zombie creature token, where X is the total power of the cards exiled this way";
+ this.staticText = "Each player mills three cards. Exile up to two creature cards put into graveyards this way. Create an X/X blue Zombie creature token, where X is the total power of the cards exiled this way";
}
public StitcherGeralfEffect(final StitcherGeralfEffect effect) {
@@ -76,10 +76,10 @@ class StitcherGeralfEffect extends OneShotEffect {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
- cards.addAll(player.getLibrary().getTopCards(game, 3));
+ cards.addAll(player.millCards(3,source,game));
}
}
- controller.moveCards(cards, Zone.GRAVEYARD, source, game);
+ cards.removeIf(uuid -> game.getState().getZone(uuid)!=Zone.GRAVEYARD);
TargetCard target = new TargetCard(0, 2, Zone.GRAVEYARD, new FilterCreatureCard("creature cards to exile"));
controller.chooseTarget(outcome, cards, target, source, game);
int power = 0;
diff --git a/Mage.Sets/src/mage/cards/s/SwordOfBodyAndMind.java b/Mage.Sets/src/mage/cards/s/SwordOfBodyAndMind.java
index e412f9e57a6..ead24ed4389 100644
--- a/Mage.Sets/src/mage/cards/s/SwordOfBodyAndMind.java
+++ b/Mage.Sets/src/mage/cards/s/SwordOfBodyAndMind.java
@@ -100,6 +100,6 @@ class SwordOfBodyAndMindAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever equipped creature deals combat damage to a player, you create a 2/2 green Wolf creature token and that player puts the top ten cards of their library into their graveyard.";
+ return "Whenever equipped creature deals combat damage to a player, you create a 2/2 green Wolf creature token and that player mills ten cards.";
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/s/SzadekLordOfSecrets.java b/Mage.Sets/src/mage/cards/s/SzadekLordOfSecrets.java
index 893008fa811..7feea17314e 100644
--- a/Mage.Sets/src/mage/cards/s/SzadekLordOfSecrets.java
+++ b/Mage.Sets/src/mage/cards/s/SzadekLordOfSecrets.java
@@ -54,7 +54,7 @@ class SzadekLordOfSecretsEffect extends ReplacementEffectImpl {
SzadekLordOfSecretsEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
- staticText = "If {this} would deal combat damage to a player, instead put that many +1/+1 counters on {this} and that player puts that many cards from the top of their library into their graveyard";
+ staticText = "If {this} would deal combat damage to a player, instead put that many +1/+1 counters on {this} and that player mills that many cards";
}
SzadekLordOfSecretsEffect(final SzadekLordOfSecretsEffect effect) {
@@ -71,7 +71,7 @@ class SzadekLordOfSecretsEffect extends ReplacementEffectImpl {
if (permanent != null) {
permanent.addCounters(CounterType.P1P1.createInstance(damageEvent.getAmount()), source, game);
if (damagedPlayer != null) {
- damagedPlayer.moveCards(damagedPlayer.getLibrary().getTopCards(game, damageEvent.getAmount()), Zone.GRAVEYARD, source, game);
+ damagedPlayer.millCards(damageEvent.getAmount(), source, game);
}
}
}
diff --git a/Mage.Sets/src/mage/cards/t/TheMendingOfDominaria.java b/Mage.Sets/src/mage/cards/t/TheMendingOfDominaria.java
index bfd4f42c4d4..3438e2374b0 100644
--- a/Mage.Sets/src/mage/cards/t/TheMendingOfDominaria.java
+++ b/Mage.Sets/src/mage/cards/t/TheMendingOfDominaria.java
@@ -56,7 +56,7 @@ class TheMendingOfDominariaFirstEffect extends OneShotEffect {
public TheMendingOfDominariaFirstEffect() {
super(Outcome.ReturnToHand);
- this.staticText = "Put the top two cards of your library into your graveyard, then you may return a creature card from your graveyard to your hand";
+ this.staticText = "Mill two cards, then you may return a creature card from your graveyard to your hand";
}
public TheMendingOfDominariaFirstEffect(final TheMendingOfDominariaFirstEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/t/ThoughtCollapse.java b/Mage.Sets/src/mage/cards/t/ThoughtCollapse.java
index ed4faf06f7a..dae6de61490 100644
--- a/Mage.Sets/src/mage/cards/t/ThoughtCollapse.java
+++ b/Mage.Sets/src/mage/cards/t/ThoughtCollapse.java
@@ -8,7 +8,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetSpell;
@@ -44,8 +43,7 @@ class ThoughtCollapseEffect extends OneShotEffect {
ThoughtCollapseEffect() {
super(Outcome.Benefit);
- staticText = "Counter target spell. Its controller puts " +
- "the top three cards of their library into their graveyard.";
+ staticText = "Counter target spell. Its controller mills three cards";
}
private ThoughtCollapseEffect(final ThoughtCollapseEffect effect) {
@@ -63,7 +61,7 @@ class ThoughtCollapseEffect extends OneShotEffect {
if (player == null) {
return false;
}
- player.moveCards(player.getLibrary().getTopCards(game, 3), Zone.GRAVEYARD, source, game);
+ player.millCards(3, source, game);
return effect.apply(game, source);
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/t/ToweringWaveMystic.java b/Mage.Sets/src/mage/cards/t/ToweringWaveMystic.java
index ba686dda8fd..e6efedf261b 100644
--- a/Mage.Sets/src/mage/cards/t/ToweringWaveMystic.java
+++ b/Mage.Sets/src/mage/cards/t/ToweringWaveMystic.java
@@ -76,7 +76,6 @@ class ToweringWaveMysticTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever {this} deals damage, target player puts that many cards " +
- "from the top of their library into their graveyard.";
+ return "Whenever {this} deals damage, target player mills that many cards.";
}
}
diff --git a/Mage.Sets/src/mage/cards/t/TymaretCallsTheDead.java b/Mage.Sets/src/mage/cards/t/TymaretCallsTheDead.java
index 8ed90c07f24..9086b580838 100644
--- a/Mage.Sets/src/mage/cards/t/TymaretCallsTheDead.java
+++ b/Mage.Sets/src/mage/cards/t/TymaretCallsTheDead.java
@@ -71,8 +71,7 @@ class TymaretCallsTheDeadFirstEffect extends OneShotEffect {
TymaretCallsTheDeadFirstEffect() {
super(Benefit);
- staticText = "put the top three cards of your library into your graveyard. " +
- "Then you may exile a creature or enchantment card from your graveyard. " +
+ staticText = "mill three cards. Then you may exile a creature or enchantment card from your graveyard. " +
"If you do, create a 2/2 black Zombie creature token";
}
diff --git a/Mage.Sets/src/mage/cards/u/UndeadAlchemist.java b/Mage.Sets/src/mage/cards/u/UndeadAlchemist.java
index 2953587af90..a61b5fd197c 100644
--- a/Mage.Sets/src/mage/cards/u/UndeadAlchemist.java
+++ b/Mage.Sets/src/mage/cards/u/UndeadAlchemist.java
@@ -24,13 +24,12 @@ import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
- *
* @author BetaSteward
*/
public final class UndeadAlchemist extends CardImpl {
public UndeadAlchemist(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add(SubType.ZOMBIE);
this.power = new MageInt(4);
@@ -97,10 +96,10 @@ class UndeadAlchemistEffect extends ReplacementEffectImpl {
UndeadAlchemistEffect() {
super(Duration.WhileOnBattlefield, Outcome.RedirectDamage);
- staticText = "If a Zombie you control would deal combat damage to a player, instead that player puts that many cards from the top of their library into their graveyard";
+ staticText = "If a Zombie you control would deal combat damage to a player, instead that player mills that many cards";
}
- UndeadAlchemistEffect(final UndeadAlchemistEffect effect) {
+ private UndeadAlchemistEffect(final UndeadAlchemistEffect effect) {
super(effect);
}
@@ -108,7 +107,8 @@ class UndeadAlchemistEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player player = game.getPlayer(event.getTargetId());
if (player != null) {
- return player.moveCards(player.getLibrary().getTopCards(game, event.getAmount()), Zone.GRAVEYARD, source, game);
+ player.millCards(event.getAmount(), source, game);
+ return true;
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/u/UrzaAcademyHeadmaster.java b/Mage.Sets/src/mage/cards/u/UrzaAcademyHeadmaster.java
index 48d020b4d2c..137e2b46535 100644
--- a/Mage.Sets/src/mage/cards/u/UrzaAcademyHeadmaster.java
+++ b/Mage.Sets/src/mage/cards/u/UrzaAcademyHeadmaster.java
@@ -268,7 +268,7 @@ class UrzaAcademyHeadmasterRandomEffect extends OneShotEffect {
effects.add(new UrzaAcademyHeadmasterBrainstormEffect());
break;
case 8: // JACE MEMORY ADEPT 2
- sb.append("Target player puts the top ten cards of their library into their graveyard.");
+ sb.append("Target player mills ten cards.");
effects.add(new PutLibraryIntoGraveTargetEffect(10));
target = new TargetPlayer();
break;
diff --git a/Mage.Sets/src/mage/cards/v/ViciousRumors.java b/Mage.Sets/src/mage/cards/v/ViciousRumors.java
index 245ce9a78e9..34e937b1740 100644
--- a/Mage.Sets/src/mage/cards/v/ViciousRumors.java
+++ b/Mage.Sets/src/mage/cards/v/ViciousRumors.java
@@ -31,8 +31,7 @@ public final class ViciousRumors extends CardImpl {
this.getSpellAbility().addEffect(
new PutTopCardOfLibraryIntoGraveEachPlayerEffect(
1, TargetController.OPPONENT
- ).setText(", then puts the top card of their library "
- + "into their graveyard")
+ ).setText(", then mills a card")
);
this.getSpellAbility().addEffect(new GainLifeEffect(1));
}
diff --git a/Mage.Sets/src/mage/cards/w/Whetstone.java b/Mage.Sets/src/mage/cards/w/Whetstone.java
index b151b288e26..84f564588ee 100644
--- a/Mage.Sets/src/mage/cards/w/Whetstone.java
+++ b/Mage.Sets/src/mage/cards/w/Whetstone.java
@@ -1,34 +1,30 @@
-
package mage.cards.w;
-import java.util.UUID;
-import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
-import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.players.Player;
+import mage.constants.TargetController;
+
+import java.util.UUID;
/**
- *
* @author Backfir3
*/
public final class Whetstone extends CardImpl {
public Whetstone(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
//{3}: Each player puts the top two cards of their library into their graveyard.
- SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new WhetstoneEffect(), new ManaCostsImpl("{3}"));
- this.addAbility(ability);
+ this.addAbility(new SimpleActivatedAbility(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(
+ 2, TargetController.ANY
+ ), new GenericManaCost(3)));
}
- public Whetstone(final Whetstone card) {
+ private Whetstone(final Whetstone card) {
super(card);
}
@@ -37,31 +33,3 @@ public final class Whetstone extends CardImpl {
return new Whetstone(this);
}
}
-
-class WhetstoneEffect extends OneShotEffect {
-
- WhetstoneEffect() {
- super(Outcome.Detriment);
- staticText = "Each player puts the top two cards of their library into their graveyard";
- }
-
- WhetstoneEffect(final WhetstoneEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, 2), Zone.GRAVEYARD, source, game);
- }
- }
- return true;
- }
-
- @Override
- public WhetstoneEffect copy() {
- return new WhetstoneEffect(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/w/WorryBeads.java b/Mage.Sets/src/mage/cards/w/WorryBeads.java
index 47423bd82f5..6f206e45f4c 100644
--- a/Mage.Sets/src/mage/cards/w/WorryBeads.java
+++ b/Mage.Sets/src/mage/cards/w/WorryBeads.java
@@ -1,7 +1,5 @@
-
package mage.cards.w;
-import java.util.UUID;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect;
import mage.cards.CardImpl;
@@ -10,8 +8,9 @@ import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.Zone;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class WorryBeads extends CardImpl {
@@ -20,12 +19,13 @@ public final class WorryBeads extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// At the beginning of each player's upkeep, that player puts the top card of their library into their graveyard.
- this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD,
- new PutLibraryIntoGraveTargetEffect(1).setText("that player puts the top card of their library into their graveyard"),
- TargetController.ANY, false, true));
+ this.addAbility(new BeginningOfUpkeepTriggeredAbility(
+ Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect(1).setText("that player mills a card"),
+ TargetController.ANY, false, true
+ ));
}
- public WorryBeads(final WorryBeads card) {
+ private WorryBeads(final WorryBeads card) {
super(card);
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/GrindstoneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/GrindstoneTest.java
index db664d3bf50..604df87eebe 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/GrindstoneTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/GrindstoneTest.java
@@ -8,7 +8,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class GrindstoneTest extends CardTestPlayerBase {
@@ -34,7 +33,7 @@ public class GrindstoneTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Painter's Servant");
setChoice(playerA, "Blue");
- activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{3}, {T}: Target player puts the top two cards of their library into their graveyard. If both cards share a color, repeat this process.");
+ activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{3}, {T}: Target player mills");
addTarget(playerA, playerB);
setStopAt(1, PhaseStep.END_TURN);
@@ -65,7 +64,7 @@ public class GrindstoneTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Painter's Servant");
setChoice(playerA, "Blue");
- activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{3}, {T}: Target player puts the top two cards of their library into their graveyard. If both cards share a color, repeat this process.");
+ activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{3}, {T}: Target player mills");
addTarget(playerA, playerB);
setStopAt(1, PhaseStep.END_TURN);
@@ -98,7 +97,7 @@ public class GrindstoneTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Painter's Servant");
setChoice(playerA, "Blue");
- activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{3}, {T}: Target player puts the top two cards of their library into their graveyard. If both cards share a color, repeat this process.");
+ activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{3}, {T}: Target player mills");
addTarget(playerA, playerB);
setStopAt(1, PhaseStep.END_TURN);
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/LeylineOfTheVoidTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/LeylineOfTheVoidTest.java
index b35f8571c05..627877016a1 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/LeylineOfTheVoidTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/LeylineOfTheVoidTest.java
@@ -33,7 +33,7 @@ public class LeylineOfTheVoidTest extends CardTestPlayerBase {
// {X}, {T}: Target opponent puts cards from the top of their library into their graveyard until a creature card or X cards are put into that graveyard this way, whichever comes first. If a creature card is put into that graveyard this way, sacrifice Helm of Obedience and put that card onto the battlefield under your control. X can't be 0.
addCard(Zone.BATTLEFIELD, playerA, "Helm of Obedience");
- activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{X}, {T}: Target opponent puts cards", playerB);
+ activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{X}, {T}: Target opponent mills", playerB);
setChoice(playerA, "X=1");
setStopAt(1, PhaseStep.END_TURN);
diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
index e4cf1bae82e..7e424803a8c 100644
--- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
+++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
@@ -3421,6 +3421,11 @@ public class TestPlayer implements Player {
return computerPlayer.moveCardToCommandWithInfo(card, sourceId, game, fromZone);
}
+ @Override
+ public Cards millCards(int toMill, Ability source, Game game) {
+ return computerPlayer.millCards(toMill, source, game);
+ }
+
@Override
public boolean hasOpponent(UUID playerToCheckId, Game game) {
return computerPlayer.hasOpponent(playerToCheckId, game);
diff --git a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java
index 652a654636c..358d9ee6211 100644
--- a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java
+++ b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java
@@ -896,7 +896,7 @@ public class PlayerStub implements Player {
public boolean putCardsOnTopOfLibrary(Card card, Game game, Ability source, boolean anyOrder) {
return false;
}
-
+
@Override
public boolean shuffleCardsToLibrary(Cards cards, Game game, Ability source) {
return false;
@@ -906,7 +906,7 @@ public class PlayerStub implements Player {
public boolean shuffleCardsToLibrary(Card card, Game game, Ability source) {
return false;
}
-
+
@Override
public boolean putCardOnTopXOfLibrary(Card card, Game game, Ability source, int xFromTheTop) {
return true;
@@ -1202,6 +1202,11 @@ public class PlayerStub implements Player {
return false;
}
+ @Override
+ public Cards millCards(int toMill, Ability source, Game game) {
+ return null;
+ }
+
@Override
public boolean hasOpponent(UUID playerToCheckId, Game game) {
return false;
diff --git a/Mage/src/main/java/mage/abilities/costs/common/PutTopCardOfYourLibraryToGraveyardCost.java b/Mage/src/main/java/mage/abilities/costs/common/PutTopCardOfYourLibraryToGraveyardCost.java
index ecefd2df465..821e46283f2 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/PutTopCardOfYourLibraryToGraveyardCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/PutTopCardOfYourLibraryToGraveyardCost.java
@@ -4,7 +4,6 @@ import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
import mage.cards.Card;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
@@ -38,8 +37,7 @@ public class PutTopCardOfYourLibraryToGraveyardCost extends CostImpl {
Player player = game.getPlayer(controllerId);
if (player != null && player.getLibrary().size() >= numberOfCards) {
paid = true;
- this.cardsMovedToGraveyard.addAll(player.getLibrary().getTopCards(game, numberOfCards));
- player.moveCards(player.getLibrary().getTopCards(game, numberOfCards), Zone.GRAVEYARD, ability, game);
+ this.cardsMovedToGraveyard.addAll(player.millCards(numberOfCards, ability, game).getCards(game));
}
return paid;
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java
index 06c3743a183..fe775591343 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java
@@ -6,7 +6,6 @@ import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
@@ -45,7 +44,7 @@ public class PutLibraryIntoGraveTargetEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, amount.calculate(game, source, this)), Zone.GRAVEYARD, source, game);
+ player.millCards(amount.calculate(game, source, this), source, game);
return true;
}
return false;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveControllerEffect.java
index b944fba65bd..423daa126e0 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveControllerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveControllerEffect.java
@@ -3,7 +3,6 @@ package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
@@ -36,7 +35,7 @@ public class PutTopCardOfLibraryIntoGraveControllerEffect extends OneShotEffect
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- return controller.moveCards(controller.getLibrary().getTopCards(game, numberCards), Zone.GRAVEYARD, source, game);
+ return !controller.millCards(numberCards, source, game).isEmpty();
}
return false;
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java
index 0809aedfae6..fb29279aa98 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java
@@ -6,7 +6,6 @@ import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.constants.TargetController;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
@@ -76,7 +75,7 @@ public class PutTopCardOfLibraryIntoGraveEachPlayerEffect extends OneShotEffect
private void putCardsToGravecard(UUID playerId, Ability source, Game game) {
Player player = game.getPlayer(playerId);
if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, numberCards.calculate(game, source, this)), Zone.GRAVEYARD, source, game);
+ player.millCards(numberCards.calculate(game, source, this), source, game);
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveTargetEffect.java
index 9af46672ac2..5c33b2f9361 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveTargetEffect.java
@@ -5,7 +5,6 @@ import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
@@ -41,7 +40,7 @@ public class PutTopCardOfLibraryIntoGraveTargetEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, numberCards.calculate(game, source, this)), Zone.GRAVEYARD, source, game);
+ player.millCards(numberCards.calculate(game, source, this), source, game);
return true;
}
return false;
diff --git a/Mage/src/main/java/mage/abilities/keyword/DredgeAbility.java b/Mage/src/main/java/mage/abilities/keyword/DredgeAbility.java
index c2f2b79f2d8..ff67e00c504 100644
--- a/Mage/src/main/java/mage/abilities/keyword/DredgeAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/DredgeAbility.java
@@ -4,8 +4,6 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.Card;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
@@ -13,6 +11,7 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.players.Player;
+import mage.util.CardUtil;
/**
* If you would draw a card, instead you may put exactly X cards from the top of
@@ -44,9 +43,9 @@ class DredgeEffect extends ReplacementEffectImpl {
public DredgeEffect(int value) {
super(Duration.WhileInGraveyard, Outcome.AIDontUseIt);
this.amount = value;
- this.staticText = ("Dredge ") + Integer.toString(value) + " (If you would draw a card, instead you may put exactly "
- + value + " card(s) from the top of your library into your graveyard. If you do, return this card from "
- + "your graveyard to your hand. Otherwise, draw a card.)";
+ this.staticText = "Dredge " + value + " (If you would draw a card, you may mill "
+ + CardUtil.numberToText(value, "a") + (value > 1 ? " cards" : " card")
+ + " instead. If you do, return this card from your graveyard to your hand.)";
}
public DredgeEffect(final DredgeEffect effect) {
@@ -74,13 +73,11 @@ class DredgeEffect extends ReplacementEffectImpl {
if (owner != null
&& owner.getLibrary().size() >= amount
&& owner.chooseUse(outcome, new StringBuilder("Dredge ").append(sourceCard.getLogName()).
- append("? (").append(amount).append(" cards go from top of library to graveyard)").toString(), source, game)) {
+ append("? (").append(amount).append(" cards go from top of library to graveyard)").toString(), source, game)) {
if (!game.isSimulation()) {
game.informPlayers(new StringBuilder(owner.getLogName()).append(" dredges ").append(sourceCard.getLogName()).toString());
}
- Cards cardsToGrave = new CardsImpl();
- cardsToGrave.addAll(owner.getLibrary().getTopCards(game, amount));
- owner.moveCards(cardsToGrave, Zone.GRAVEYARD, source, game);
+ owner.millCards(amount, source, game);
owner.moveCards(sourceCard, Zone.HAND, source, game);
return true;
}
diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java
index cbf313bc28a..e01ab4f6cef 100644
--- a/Mage/src/main/java/mage/players/Player.java
+++ b/Mage/src/main/java/mage/players/Player.java
@@ -531,10 +531,10 @@ public interface Player extends MageItem, Copyable {
* @param cards - list of cards that have to be moved
* @param game - game
* @param anyOrder - true = if player can determine the order of the cards
- * else false = random order
- * 401.4. If an effect puts two or more cards in a specific position in a library
- * at the same time, the owner of those cards may arrange them in any order.
- * That library’s owner doesn’t reveal the order in which the cards go into the library.
+ * else false = random order
+ * 401.4. If an effect puts two or more cards in a specific position in a library
+ * at the same time, the owner of those cards may arrange them in any order.
+ * That library’s owner doesn’t reveal the order in which the cards go into the library.
* @param source - source ability
* @return
*/
@@ -563,13 +563,13 @@ public interface Player extends MageItem, Copyable {
* @return
*/
boolean putCardsOnTopOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder);
-
+
boolean putCardsOnTopOfLibrary(Card card, Game game, Ability source, boolean anyOrder);
boolean shuffleCardsToLibrary(Cards cards, Game game, Ability source);
-
+
boolean shuffleCardsToLibrary(Card card, Game game, Ability source);
-
+
// set the value for X mana spells and abilities
default int announceXMana(int min, int max, String message, Game game, Ability ability) {
return announceXMana(min, max, 1, message, game, ability);
@@ -840,6 +840,8 @@ public interface Player extends MageItem, Copyable {
*/
boolean moveCardToCommandWithInfo(Card card, UUID sourceId, Game game, Zone fromZone);
+ Cards millCards(int toMill, Ability source, Game game);
+
/**
* Checks if the playerToCheckId is from an opponent in range
*
diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java
index 55125a4602d..696e98884e3 100644
--- a/Mage/src/main/java/mage/players/PlayerImpl.java
+++ b/Mage/src/main/java/mage/players/PlayerImpl.java
@@ -4193,6 +4193,17 @@ public abstract class PlayerImpl implements Player, Serializable {
return result;
}
+ @Override
+ public Cards millCards(int toMill, Ability source, Game game) {
+ GameEvent event = GameEvent.getEvent(EventType.MILL_CARDS, getId(), source.getSourceId(), getId(), toMill);
+ if (game.replaceEvent(event)) {
+ return new CardsImpl();
+ }
+ Cards cards = new CardsImpl(this.getLibrary().getTopCards(game, event.getAmount()));
+ this.moveCards(cards, Zone.GRAVEYARD, source, game);
+ return cards;
+ }
+
@Override
public boolean hasOpponent(UUID playerToCheckId, Game game) {
return !this.getId().equals(playerToCheckId)