* Fixed a lot of cards where order of card discarding/hand,graveyard,permanents into library shuffling and card draw order was not correctly implemented. This could cause bugs for draw replacement effects (e.g. Notion Thief).

This commit is contained in:
LevelX2 2015-08-19 03:31:44 +02:00
parent 72c4f458ce
commit bd6fa770aa
17 changed files with 329 additions and 215 deletions

View file

@ -30,7 +30,10 @@ package mage.sets.avacynrestored;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardAllEffect;
import mage.abilities.effects.common.discard.DiscardHandAllEffect;
import mage.abilities.keyword.MiracleAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
@ -50,9 +53,11 @@ public class ReforgeTheSoul extends CardImpl {
super(ownerId, 151, "Reforge the Soul", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{R}{R}");
this.expansionSetCode = "AVR";
// Each player discards his or her hand, then draws seven cards.
this.getSpellAbility().addEffect(new ReforgeTheSoulEffect());
this.getSpellAbility().addEffect(new DiscardHandAllEffect());
Effect effect = new DrawCardAllEffect(7);
effect.setText(", then draws seven cards");
this.getSpellAbility().addEffect(effect);
// Miracle {1}{R}
this.addAbility(new MiracleAbility(this, new ManaCostsImpl("{1}{R}")));
@ -94,7 +99,6 @@ class ReforgeTheSoulEffect extends OneShotEffect {
for (Card card : player.getHand().getCards(game)) {
player.discard(card, source, game);
}
player.drawCards(7, game);
}
}

View file

@ -28,14 +28,18 @@
package mage.sets.betrayersofkamigawa;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardAllEffect;
import mage.abilities.effects.common.SetPlayerLifeAllEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.filter.FilterPermanent;
import mage.filter.predicate.other.OwnerIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@ -50,9 +54,12 @@ public class SwayOfTheStars extends CardImpl {
super(ownerId, 54, "Sway of the Stars", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{8}{U}{U}");
this.expansionSetCode = "BOK";
// Each player shuffles his or her hand, graveyard, and permanents he or she owns into his or her library, then draws seven cards. Each player's life total becomes 7.
this.getSpellAbility().addEffect(new SwayOfTheStarsEffect());
Effect effect = new DrawCardAllEffect(7);
effect.setText(", then draws seven cards");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addEffect(new SetPlayerLifeAllEffect(7));
}
@ -66,7 +73,6 @@ public class SwayOfTheStars extends CardImpl {
}
}
class SwayOfTheStarsEffect extends OneShotEffect {
public SwayOfTheStarsEffect() {
@ -80,24 +86,19 @@ class SwayOfTheStarsEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player sourcePlayer = game.getPlayer(source.getControllerId());
Player controller = game.getPlayer(source.getControllerId());
for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
permanent.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
for (UUID playerId: sourcePlayer.getInRange()) {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
for (Card card: player.getHand().getCards(game)) {
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
for (Card card: player.getGraveyard().getCards(game)) {
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
player.moveCards(player.getHand(), Zone.HAND, Zone.LIBRARY, source, game);
player.moveCards(player.getGraveyard(), Zone.GRAVEYARD, Zone.LIBRARY, source, game);
FilterPermanent filter = new FilterPermanent();
filter.add(new OwnerIdPredicate(playerId));
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, controller.getId(), source.getSourceId(), game)) {
permanent.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
player.shuffleLibrary(game);
player.drawCards(7, game);
player.setLife(7, game);
}
}
return true;
@ -108,4 +109,4 @@ class SwayOfTheStarsEffect extends OneShotEffect {
return new SwayOfTheStarsEffect(this);
}
}
}

View file

@ -27,6 +27,8 @@
*/
package mage.sets.commander2013;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
@ -54,8 +56,7 @@ public class IncendiaryCommand extends CardImpl {
super(ownerId, 113, "Incendiary Command", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{R}{R}");
this.expansionSetCode = "C13";
// Choose two -
// Choose two -
this.getSpellAbility().getModes().setMinModes(2);
this.getSpellAbility().getModes().setMaxModes(2);
// Incendiary Command deals 4 damage to target player;
@ -107,16 +108,23 @@ class IncendiaryCommandDrawEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
for (UUID playerId : controller.getInRange()) {
Map<UUID, Integer> cardsToDraw = new HashMap<>();
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
int cards = player.getHand().size();
if (cards > 0) {
player.discard(cards, source, game);
player.drawCards(cards, game);
int cardsInHand = player.getHand().size();
player.discard(cardsInHand, false, source, game);
if (cardsInHand > 0) {
cardsToDraw.put(playerId, cardsInHand);
}
}
}
for (UUID playerId : cardsToDraw.keySet()) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.drawCards(cardsToDraw.get(playerId), game);
}
}
return true;
}
return false;

View file

@ -27,6 +27,8 @@
*/
package mage.sets.fatereforged;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@ -81,16 +83,23 @@ class DarkDealEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
for (UUID playerId : controller.getInRange()) {
Map<UUID, Integer> cardsToDraw = new LinkedHashMap<>();
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
int cardsInHand = player.getHand().size();
player.discard(cardsInHand, false, source, game);
if (cardsInHand > 1) {
player.drawCards(cardsInHand - 1, game);
cardsToDraw.put(playerId, cardsInHand - 1);
}
}
}
for (UUID playerId : cardsToDraw.keySet()) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.drawCards(cardsToDraw.get(playerId), game);
}
}
return true;
}
return false;

View file

@ -29,8 +29,9 @@ package mage.sets.limitedalpha;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.abilities.effects.common.DrawCardAllEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
@ -49,9 +50,11 @@ public class Timetwister extends CardImpl {
super(ownerId, 85, "Timetwister", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{2}{U}");
this.expansionSetCode = "LEA";
// Each player shuffles his or her hand and graveyard into his or her library, then draws seven cards.
this.getSpellAbility().addEffect(new TimetwisterEffect());
Effect effect = new DrawCardAllEffect(7);
effect.setText(", then draws seven cards");
this.getSpellAbility().addEffect(effect);
}
@ -69,7 +72,7 @@ class TimetwisterEffect extends OneShotEffect {
public TimetwisterEffect() {
super(Outcome.Neutral);
staticText = "Each player shuffles his or her hand and graveyard into his or her library, then draws seven cards";
staticText = "Each player shuffles his or her hand and graveyard into his or her library";
}
public TimetwisterEffect(final TimetwisterEffect effect) {
@ -78,27 +81,14 @@ class TimetwisterEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player sourcePlayer = game.getPlayer(source.getControllerId());
for (UUID playerId: sourcePlayer.getInRange()) {
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
for (Card card: player.getHand().getCards(game)) {
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
for (Card card: player.getGraveyard().getCards(game)) {
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
player.moveCards(player.getHand(), Zone.HAND, Zone.LIBRARY, source, game);
player.moveCards(player.getGraveyard(), Zone.GRAVEYARD, Zone.LIBRARY, source, game);
player.shuffleLibrary(game);
}
}
game.getState().handleSimultaneousEvent(game); // needed here so state based triggered effects
for (UUID playerId: sourcePlayer.getInRange()) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.drawCards(7, game);
}
}
return true;
}

View file

@ -1,16 +1,16 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
@ -20,23 +20,23 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.magic2011;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardAllEffect;
import mage.abilities.effects.common.ExileSpellEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSpellEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
@ -51,7 +51,11 @@ public class TimeReversal extends CardImpl {
super(ownerId, 75, "Time Reversal", Rarity.MYTHIC, new CardType[]{CardType.SORCERY}, "{3}{U}{U}");
this.expansionSetCode = "M11";
// Each player shuffles his or her hand and graveyard into his or her library, then draws seven cards
this.getSpellAbility().addEffect(new TimeReversalEffect());
Effect effect = new DrawCardAllEffect(7);
effect.setText(", then draws seven cards");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addEffect(ExileSpellEffect.getInstance());
}
@ -78,18 +82,13 @@ class TimeReversalEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player sourcePlayer = game.getPlayer(source.getControllerId());
for (UUID playerId: sourcePlayer.getInRange()) {
Player controller = game.getPlayer(source.getControllerId());
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
for (Card card: player.getHand().getCards(game)) {
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
for (Card card: player.getGraveyard().getCards(game)) {
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
player.moveCards(player.getHand(), Zone.HAND, Zone.LIBRARY, source, game);
player.moveCards(player.getGraveyard(), Zone.GRAVEYARD, Zone.LIBRARY, source, game);
player.shuffleLibrary(game);
player.drawCards(7, game);
}
}
return true;
@ -100,4 +99,4 @@ class TimeReversalEffect extends OneShotEffect {
return new TimeReversalEffect(this);
}
}
}

View file

@ -31,9 +31,10 @@ import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.condition.common.MyTurnCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardAllEffect;
import mage.abilities.effects.common.EndTurnEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
@ -54,6 +55,9 @@ public class DaysUndoing extends CardImpl {
// Each player shuffles his or her hand and graveyard into his or her library, then draws seven cards. If it's your turn, end the turn.
this.getSpellAbility().addEffect(new DaysUndoingEffect());
Effect effect = new DrawCardAllEffect(7);
effect.setText(", then draws seven cards");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new EndTurnEffect(), MyTurnCondition.getInstance(), "If it's your turn, end the turn"));
}
@ -71,7 +75,7 @@ class DaysUndoingEffect extends OneShotEffect {
public DaysUndoingEffect() {
super(Outcome.Neutral);
staticText = "Each player shuffles his or her hand and graveyard into his or her library, then draws seven cards";
staticText = "Each player shuffles his or her hand and graveyard into his or her library";
}
public DaysUndoingEffect(final DaysUndoingEffect effect) {
@ -80,28 +84,16 @@ class DaysUndoingEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player sourcePlayer = game.getPlayer(source.getControllerId());
for (UUID playerId : sourcePlayer.getInRange()) {
Player controller = game.getPlayer(source.getControllerId());
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
for (Card card : player.getHand().getCards(game)) {
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
for (Card card : player.getGraveyard().getCards(game)) {
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
game.informPlayers(player.getLogName() + " puts his or her hand and graveyard into his or her library");
player.moveCards(player.getHand(), Zone.HAND, Zone.LIBRARY, source, game);
player.moveCards(player.getGraveyard(), Zone.GRAVEYARD, Zone.LIBRARY, source, game);
player.shuffleLibrary(game);
}
}
game.getState().handleSimultaneousEvent(game); // needed here so state based triggered effects
for (UUID playerId : sourcePlayer.getInRange()) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.drawCards(7, game);
}
}
return true;
}

View file

@ -94,7 +94,7 @@ class TheGreatAuroraEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Map<UUID, List<Permanent>> permanentsOwned = new HashMap<>();
Collection<Permanent> permanents = game.getBattlefield().getAllPermanents();
Collection<Permanent> permanents = game.getBattlefield().getActivePermanents(source.getControllerId(), game);
for (Permanent permanent : permanents) {
List<Permanent> list = permanentsOwned.get(permanent.getOwnerId());
if (list == null) {

View file

@ -27,25 +27,22 @@
*/
package mage.sets.ninthedition;
import mage.constants.*;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfDrawTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.filter.FilterCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import java.util.UUID;
/**
*
* @author noxx
*
*/
public class TeferisPuzzleBox extends CardImpl {
@ -87,30 +84,7 @@ class TeferisPuzzleBoxEffect extends OneShotEffect {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
if (player != null) {
int count = player.getHand().size();
// puts the cards in his or her hand on the bottom of his or her library in any order
Cards cards = new CardsImpl();
for (Card card : player.getHand().getCards(game)) {
cards.add(card.getId());
}
TargetCard target = new TargetCard(Zone.PICK, new FilterCard("card to put on the bottom of your library"));
while (player.canRespond() && cards.size() > 1) {
player.choose(Outcome.Neutral, cards, target, game);
Card card = cards.get(target.getFirstTarget(), game);
if (card != null) {
cards.remove(card);
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false);
}
target.clearChosen();
}
if (cards.size() == 1) {
Card card = cards.get(cards.iterator().next(), game);
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false);
}
player.getHand().clear();
// draws that many cards
player.putCardsOnBottomOfLibrary(player.getHand(), game, source, true);
player.drawCards(count, game);
}
return true;

View file

@ -27,11 +27,9 @@
*/
package mage.sets.planechase2012;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -41,7 +39,10 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
@ -99,16 +100,23 @@ class WhirlpoolWarriorTriggeredEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int cardsHand = controller.getHand().size();
if (cardsHand > 0){
for (Card card: controller.getHand().getCards(game)) {
if (card != null) {
controller.removeFromHand(card, game);
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
Map<UUID, Integer> cardsToDraw = new LinkedHashMap<>();
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
int cardsInHand = player.getHand().size();
if (cardsInHand > 0) {
cardsToDraw.put(playerId, cardsInHand);
}
player.moveCards(player.getHand(), Zone.HAND, Zone.LIBRARY, source, game);
player.shuffleLibrary(game);
}
}
for (UUID playerId : cardsToDraw.keySet()) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.drawCards(cardsToDraw.get(playerId), game);
}
controller.shuffleLibrary(game);
controller.drawCards(cardsHand, game);
}
return true;
}
@ -141,8 +149,8 @@ class WhirlpoolWarriorActivatedEffect extends OneShotEffect {
Player player = game.getPlayer(playerId);
if (player != null) {
int cardsHand = player.getHand().size();
if (cardsHand > 0){
for (Card card: player.getHand().getCards(game)) {
if (cardsHand > 0) {
for (Card card : player.getHand().getCards(game)) {
if (card != null) {
player.removeFromHand(card, game);
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);

View file

@ -1,16 +1,16 @@
/*
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
@ -28,18 +28,18 @@
package mage.sets.scarsofmirrodin;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.WatcherScope;
import mage.abilities.Ability;
import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -56,7 +56,6 @@ public class MoltenPsyche extends CardImpl {
super(ownerId, 98, "Molten Psyche", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{1}{R}{R}");
this.expansionSetCode = "SOM";
// Each player shuffles the cards from his or her hand into his or her library, then draws that many cards.
// Metalcraft - If you control three or more artifacts, Molten Psyche deals damage to each opponent equal to the number of cards that player has drawn this turn.
this.getSpellAbility().addEffect(new MoltenPsycheEffect());
@ -78,8 +77,8 @@ class MoltenPsycheEffect extends OneShotEffect {
public MoltenPsycheEffect() {
super(Outcome.Neutral);
staticText = "Each player shuffles the cards from his or her hand into his or her library, then draws that many cards.\n" +
"<i>Metalcraft<i/> - If you control three or more artifacts, {this} deals damage to each opponent equal to the number of cards that player has drawn this turn.";
staticText = "Each player shuffles the cards from his or her hand into his or her library, then draws that many cards.\n"
+ "<i>Metalcraft<i/> - If you control three or more artifacts, {this} deals damage to each opponent equal to the number of cards that player has drawn this turn.";
}
public MoltenPsycheEffect(final MoltenPsycheEffect effect) {
@ -88,27 +87,43 @@ class MoltenPsycheEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player sourcePlayer = game.getPlayer(source.getControllerId());
for (UUID playerId: sourcePlayer.getInRange()) {
Player player = game.getPlayer(playerId);
if (player != null) {
int count = player.getHand().size();
for (Card card: player.getHand().getCards(game)) {
if (card != null) {
player.removeFromHand(card, game);
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Map<UUID, Integer> cardsToDraw = new LinkedHashMap<>();
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
int cardsInHand = player.getHand().size();
if (cardsInHand > 0) {
cardsToDraw.put(playerId, cardsInHand);
}
}
game.informPlayers(player.getLogName() + " shuffles the cards from his or her hand into his or her library");
player.shuffleLibrary(game);
player.drawCards(count, game);
if (MetalcraftCondition.getInstance().apply(game, source) && !playerId.equals(source.getControllerId())) {
MoltenPsycheWatcher watcher = (MoltenPsycheWatcher) game.getState().getWatchers().get("CardsDrawn");
player.damage(watcher.getDraws(playerId), source.getSourceId(), game, false, true);
player.moveCards(player.getHand(), Zone.HAND, Zone.LIBRARY, source, game);
player.shuffleLibrary(game);
}
}
for (UUID playerId : cardsToDraw.keySet()) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.drawCards(cardsToDraw.get(playerId), game);
if (MetalcraftCondition.getInstance().apply(game, source) && !playerId.equals(source.getControllerId())) {
MoltenPsycheWatcher watcher = (MoltenPsycheWatcher) game.getState().getWatchers().get("CardsDrawn");
player.damage(watcher.getDraws(playerId), source.getSourceId(), game, false, true);
}
}
}
if (MetalcraftCondition.getInstance().apply(game, source)) {
MoltenPsycheWatcher watcher = (MoltenPsycheWatcher) game.getState().getWatchers().get("CardsDrawn");
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.damage(watcher.getDraws(playerId), source.getSourceId(), game, false, true);
}
}
}
return true;
}
return true;
return false;
}
@Override
@ -128,7 +143,7 @@ class MoltenPsycheWatcher extends Watcher {
public MoltenPsycheWatcher(final MoltenPsycheWatcher watcher) {
super(watcher);
for (Entry<UUID, Integer> entry: watcher.draws.entrySet()) {
for (Entry<UUID, Integer> entry : watcher.draws.entrySet()) {
draws.put(entry.getKey(), entry.getValue());
}
}

View file

@ -28,15 +28,17 @@
package mage.sets.urzassaga;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardAllEffect;
import mage.abilities.effects.common.ExileSpellEffect;
import mage.abilities.effects.common.UntapLandsEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
@ -51,12 +53,15 @@ public class TimeSpiral extends CardImpl {
super(ownerId, 103, "Time Spiral", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{U}{U}");
this.expansionSetCode = "USG";
// Exile Time Spiral. Each player shuffles his or her graveyard and hand into his or her library, then draws seven cards. You untap up to six lands.
this.getSpellAbility().addEffect(ExileSpellEffect.getInstance());
this.getSpellAbility().addEffect(new TimeSpiralEffect());
Effect effect = new DrawCardAllEffect(7);
effect.setText(", then draws seven cards");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addEffect(new UntapLandsEffect(6));
}
public TimeSpiral(final TimeSpiral card) {
super(card);
}
@ -71,7 +76,7 @@ class TimeSpiralEffect extends OneShotEffect {
public TimeSpiralEffect() {
super(Outcome.Neutral);
staticText = "Each player shuffles his or her hand and graveyard into his or her library, then draws seven cards";
staticText = "Each player shuffles his or her hand and graveyard into his or her library";
}
public TimeSpiralEffect(final TimeSpiralEffect effect) {
@ -81,17 +86,16 @@ class TimeSpiralEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player sourcePlayer = game.getPlayer(source.getControllerId());
for (UUID playerId: sourcePlayer.getInRange()) {
for (UUID playerId : sourcePlayer.getInRange()) {
Player player = game.getPlayer(playerId);
if (player != null) {
for (Card card: player.getHand().getCards(game)) {
for (Card card : player.getHand().getCards(game)) {
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
for (Card card: player.getGraveyard().getCards(game)) {
}
for (Card card : player.getGraveyard().getCards(game)) {
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
}
player.shuffleLibrary(game);
player.drawCards(7, game);
}
}
return true;
@ -102,4 +106,4 @@ class TimeSpiralEffect extends OneShotEffect {
return new TimeSpiralEffect(this);
}
}
}

View file

@ -48,7 +48,6 @@ public class Windfall extends CardImpl {
super(ownerId, 111, "Windfall", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{U}");
this.expansionSetCode = "USG";
// Each player discards his or her hand, then draws cards equal to the greatest number of cards a player discarded this way.
this.getSpellAbility().addEffect(new WindfallEffect());
}
@ -64,6 +63,7 @@ public class Windfall extends CardImpl {
}
class WindfallEffect extends OneShotEffect {
WindfallEffect() {
super(Outcome.Discard);
staticText = "Each player discards his or her hand, then draws cards equal to the greatest number of cards a player discarded this way.";
@ -76,11 +76,11 @@ class WindfallEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
int maxDiscarded = 0;
Player sourcePlayer = game.getPlayer(source.getControllerId());
if (sourcePlayer == null) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
for (UUID playerId : sourcePlayer.getInRange()) {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
int discarded = 0;
@ -94,7 +94,7 @@ class WindfallEffect extends OneShotEffect {
}
}
}
for (UUID playerId : sourcePlayer.getInRange()) {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.drawCards(maxDiscarded, game);
@ -107,4 +107,4 @@ class WindfallEffect extends OneShotEffect {
public WindfallEffect copy() {
return new WindfallEffect(this);
}
}
}

View file

@ -33,6 +33,7 @@ import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardAllEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
@ -65,7 +66,6 @@ public class ChandraAblaze extends CardImpl {
this.expansionSetCode = "ZEN";
this.subtype.add("Chandra");
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(5)), false));
// +1: Discard a card. If a red card is discarded this way, Chandra Ablaze deals 4 damage to target creature or player.
@ -75,7 +75,9 @@ public class ChandraAblaze extends CardImpl {
this.addAbility(ability);
// -2: Each player discards his or her hand, then draws three cards.
ability = new LoyaltyAbility(new DiscardHandAllEffect(), -2);
ability.addEffect(new ChandraAblazeEffect4());
Effect effect = new DrawCardAllEffect(3);
effect.setText(", then draws three cards");
ability.addEffect(effect);
this.addAbility(ability);
// -7: Cast any number of red instant and/or sorcery cards from your graveyard without paying their mana costs.
ability = new LoyaltyAbility(new ChandraAblazeEffect5(), -7);
@ -162,23 +164,6 @@ class ChandraAblazeEffect2 extends OneShotEffect {
}
}
class ChandraAblazeEffect4 extends DrawCardAllEffect {
public ChandraAblazeEffect4() {
super(3);
this.staticText = "Then draws three cards";
}
public ChandraAblazeEffect4(final ChandraAblazeEffect4 effect) {
super(effect);
}
@Override
public ChandraAblazeEffect4 copy() {
return new ChandraAblazeEffect4(this);
}
}
class ChandraAblazeEffect5 extends OneShotEffect {
public ChandraAblazeEffect5() {

View file

@ -82,4 +82,32 @@ public class DrawEffectsTest extends CardTestPlayerBase {
assertHandCount(playerB, 1);
}
/**
* Notion thief and Reforge the Soul - opponent got 0 cards - ok but I got
* only 7 cards (should be 14)
*/
@Test
public void testNotionThief2() {
addCard(Zone.LIBRARY, playerA, "Silvercoat Lion", 3);
skipInitShuffling();
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
// Flash
// If an opponent would draw a card except the first one he or she draws in each of his or her draw steps, instead that player skips that draw and you draw a card.
addCard(Zone.BATTLEFIELD, playerA, "Notion Thief", 1);
// Each player discards his or her hand, then draws seven cards.
// Miracle {1}{R}
addCard(Zone.HAND, playerA, "Reforge the Soul", 1);
addCard(Zone.HAND, playerB, "Mountain", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reforge the Soul");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Reforge the Soul", 1);
assertGraveyardCount(playerB, "Mountain", 1);
assertHandCount(playerA, 14);
assertHandCount(playerB, 0);
}
}

View file

@ -0,0 +1,99 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.effects.common;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.constants.TargetController;
import static mage.constants.TargetController.ANY;
import static mage.constants.TargetController.OPPONENT;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author LevelX2
*/
public class SetPlayerLifeAllEffect extends OneShotEffect {
private TargetController targetController;
protected DynamicValue amount;
public SetPlayerLifeAllEffect(int amount) {
this(amount, TargetController.ANY);
}
public SetPlayerLifeAllEffect(DynamicValue amount) {
this(amount, TargetController.ANY);
}
public SetPlayerLifeAllEffect(int amount, TargetController targetController) {
this(new StaticValue(amount), targetController);
}
public SetPlayerLifeAllEffect(DynamicValue amount, TargetController targetController) {
super(Outcome.DrawCard);
this.amount = amount;
this.targetController = targetController;
staticText = setText();
}
public SetPlayerLifeAllEffect(final SetPlayerLifeAllEffect effect) {
super(effect);
this.amount = effect.amount;
this.targetController = effect.targetController;
}
@Override
public SetPlayerLifeAllEffect copy() {
return new SetPlayerLifeAllEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player sourcePlayer = game.getPlayer(source.getControllerId());
switch (targetController) {
case ANY:
for (UUID playerId : sourcePlayer.getInRange()) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.setLife(amount.calculate(game, source, this), game);
}
}
break;
case OPPONENT:
for (UUID playerId : game.getOpponents(sourcePlayer.getId())) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.setLife(amount.calculate(game, source, this), game);
}
}
break;
}
return true;
}
private String setText() {
StringBuilder sb = new StringBuilder("Each ");
switch (targetController) {
case ANY:
sb.append("player");
break;
case OPPONENT:
sb.append("opponent");
break;
default:
throw new UnsupportedOperationException("Not supported value for targetController");
}
sb.append(" 's life total becomes ");
sb.append(amount.toString());
return sb.toString();
}
}

View file

@ -1,7 +1,8 @@
package mage.actions;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.actions.impl.MageAction;
import mage.actions.score.ArtificialScoringSystem;
import mage.cards.Card;
@ -9,9 +10,6 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import java.util.List;
import java.util.UUID;
import mage.util.CardUtil;
/**
@ -39,7 +37,7 @@ public class MageDrawAction extends MageAction {
* Draw and set action score.
*
* @param game Game context.
* @return
* @return
*/
@Override
public int doAction(Game game) {
@ -70,8 +68,8 @@ public class MageDrawAction extends MageAction {
}
/**
* Draw a card if possible (there is no replacement effect that prevent us from drawing).
* Fire event about card drawn.
* Draw a card if possible (there is no replacement effect that prevent us
* from drawing). Fire event about card drawn.
*
* @param game
* @return