diff --git a/Mage.Game.FreeForAll/src/mage/game/FreeForAll.java b/Mage.Game.FreeForAll/src/mage/game/FreeForAll.java index 39d20ac0bd2..478dcb5b933 100644 --- a/Mage.Game.FreeForAll/src/mage/game/FreeForAll.java +++ b/Mage.Game.FreeForAll/src/mage/game/FreeForAll.java @@ -96,7 +96,7 @@ public class FreeForAll extends GameImpl { numCards += 1; mulliganed.add(playerId); } - player.getLibrary().addAll(player.getHand().getCards(this)); + player.getLibrary().addAll(player.getHand().getCards(this), this); player.getHand().clear(); player.shuffleLibrary(this); player.drawCards(numCards - 1, this); diff --git a/Mage.Player.AI/src/mage/player/ai/ComputerPlayer.java b/Mage.Player.AI/src/mage/player/ai/ComputerPlayer.java index c2ecd4873b8..8bb239904ef 100644 --- a/Mage.Player.AI/src/mage/player/ai/ComputerPlayer.java +++ b/Mage.Player.AI/src/mage/player/ai/ComputerPlayer.java @@ -641,6 +641,22 @@ public class ComputerPlayer> extends PlayerImpl i return true; } + @Override + public boolean choose(Cards cards, TargetCard target, Game game) { + logger.fine("choose"); + //TODO: improve this + //return first match + if (!target.doneChosing()) { + for (Card card: cards.getCards(target.getFilter(), game)) { + target.add(card.getId(), game); + if (target.doneChosing()) + return true; + } + return false; + } + return true; + } + @Override public void selectAttackers(Game game) { logger.fine("selectAttackers"); diff --git a/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java b/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java index 0f1161b0d79..6b145ff62c3 100644 --- a/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java +++ b/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java @@ -474,6 +474,23 @@ public class ComputerPlayer2 extends ComputerPlayer implements return true; } + @Override + public boolean choose(Cards cards, TargetCard target, Game game) { + if (targets.size() == 0) + return super.choose(cards, target, game); + if (!target.doneChosing()) { + for (UUID targetId: targets) { + target.add(targetId, game); + if (target.doneChosing()) { + targets.clear(); + return true; + } + } + return false; + } + return true; + } + public void playNext(Game game, UUID activePlayerId, SimulationNode node) { boolean skip = false; while (true) { diff --git a/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index d62c29862d9..c3a0ad9d447 100644 --- a/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -50,6 +50,7 @@ import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.VariableManaCost; import mage.cards.decks.Deck; +import mage.choices.ChoiceImpl; import mage.filter.common.FilterCreatureForCombat; import mage.game.Game; import mage.game.permanent.Permanent; @@ -72,8 +73,11 @@ public class HumanPlayer extends PlayerImpl { private boolean abort; protected static FilterCreatureForCombat filter = new FilterCreatureForCombat(); + protected static Choice replacementEffectChoice = new ChoiceImpl(true); + static { filter.setTargetController(TargetController.YOU); + replacementEffectChoice.setMessage("Choose replacement effect"); } protected transient TargetCreaturePermanent targetCombat = new TargetCreaturePermanent(filter); @@ -140,7 +144,23 @@ public class HumanPlayer extends PlayerImpl { @Override public int chooseEffect(List rEffects, Game game) { - //TODO: implement this + replacementEffectChoice.getChoices().clear(); + for (ReplacementEffect effect: rEffects) { + replacementEffectChoice.getChoices().add(effect.getText(null)); + } + if (replacementEffectChoice.getChoices().size() == 1) + return 0; + while (!abort) { + game.fireChooseEvent(playerId, replacementEffectChoice); + waitForResponse(); + if (response.getString() != null) { + replacementEffectChoice.setChoice(response.getString()); + for (int i = 0; i < rEffects.size(); i++) { + if (replacementEffectChoice.getChoice().equals(rEffects.get(i).getText(null))) + return i; + } + } + } return 0; } @@ -194,9 +214,26 @@ public class HumanPlayer extends PlayerImpl { } @Override - public boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game) { - game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired()); + public boolean choose(Cards cards, TargetCard target, Game game) { while (!abort) { + game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired()); + waitForResponse(); + if (response.getUUID() != null) { + if (target.canTarget(response.getUUID(), cards, game)) { + target.add(response.getUUID(), game); + return true; + } + } else if (!target.isRequired()) { + return false; + } + } + return false; + } + + @Override + public boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game) { + while (!abort) { + game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired()); waitForResponse(); if (response.getUUID() != null) { if (target.canTarget(response.getUUID(), cards, game)) { @@ -210,11 +247,10 @@ public class HumanPlayer extends PlayerImpl { return false; } - @Override public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) { - game.fireSelectTargetEvent(playerId, target.getMessage() + "\n Amount remaining:" + target.getAmountRemaining(), target.isRequired()); while (!abort) { + game.fireSelectTargetEvent(playerId, target.getMessage() + "\n Amount remaining:" + target.getAmountRemaining(), target.isRequired()); waitForResponse(); if (response.getUUID() != null) { if (target.canTarget(response.getUUID(), source, game)) { @@ -251,7 +287,7 @@ public class HumanPlayer extends PlayerImpl { MageObject object = game.getObject(response.getUUID()); if (object != null) { Map useableAbilities = null; - switch (object.getZone()) { + switch (game.getZone(object.getId())) { case HAND: useableAbilities = getUseableAbilities(object.getAbilities().getActivatedAbilities(Zone.HAND), game); break; @@ -314,7 +350,7 @@ public class HumanPlayer extends PlayerImpl { protected void playManaAbilities(Game game) { MageObject object = game.getObject(response.getUUID()); Map useableAbilities; - switch (object.getZone()) { + switch (game.getZone(object.getId())) { case HAND: useableAbilities = getUseableAbilities(object.getAbilities().getManaAbilities(Zone.HAND), game); if (useableAbilities.size() > 0) { @@ -399,17 +435,19 @@ public class HumanPlayer extends PlayerImpl { int remainingDamage = damage; while (remainingDamage > 0) { Target target = new TargetCreatureOrPlayer(); - chooseTarget(Outcome.Damage, target, null, game); + choose(Outcome.Damage, target, game); if (targets.size() == 0 || targets.contains(target.getFirstTarget())) { int damageAmount = getAmount(0, remainingDamage, "Select amount", game); Permanent permanent = game.getPermanent(target.getFirstTarget()); if (permanent != null) { permanent.damage(damageAmount, sourceId, game, true); + remainingDamage -= damageAmount; } else { Player player = game.getPlayer(target.getFirstTarget()); if (player != null) { player.damage(damageAmount, sourceId, game, false, true); + remainingDamage -= damageAmount; } } } diff --git a/Mage.Server/plugins/mage-deck-constructed.jar b/Mage.Server/plugins/mage-deck-constructed.jar index d27c8faaee5..8a11731b1e0 100644 Binary files a/Mage.Server/plugins/mage-deck-constructed.jar and b/Mage.Server/plugins/mage-deck-constructed.jar differ diff --git a/Mage.Server/plugins/mage-game-freeforall.jar b/Mage.Server/plugins/mage-game-freeforall.jar index 51ed106cf9b..24f9d2e89f4 100644 Binary files a/Mage.Server/plugins/mage-game-freeforall.jar and b/Mage.Server/plugins/mage-game-freeforall.jar differ diff --git a/Mage.Server/plugins/mage-game-twoplayerduel.jar b/Mage.Server/plugins/mage-game-twoplayerduel.jar index d8a23746b2f..cf7a4305be1 100644 Binary files a/Mage.Server/plugins/mage-game-twoplayerduel.jar and b/Mage.Server/plugins/mage-game-twoplayerduel.jar differ diff --git a/Mage.Server/plugins/mage-player-ai.jar b/Mage.Server/plugins/mage-player-ai.jar index c036e2c1caa..5eb2e70c8ad 100644 Binary files a/Mage.Server/plugins/mage-player-ai.jar and b/Mage.Server/plugins/mage-player-ai.jar differ diff --git a/Mage.Server/plugins/mage-player-aiminimax.jar b/Mage.Server/plugins/mage-player-aiminimax.jar index 4ffc7bee3d7..8f800429c12 100644 Binary files a/Mage.Server/plugins/mage-player-aiminimax.jar and b/Mage.Server/plugins/mage-player-aiminimax.jar differ diff --git a/Mage.Server/plugins/mage-player-human.jar b/Mage.Server/plugins/mage-player-human.jar index f18a79a3630..8c98d5ef01e 100644 Binary files a/Mage.Server/plugins/mage-player-human.jar and b/Mage.Server/plugins/mage-player-human.jar differ diff --git a/Mage.Server/src/mage/server/game/GameController.java b/Mage.Server/src/mage/server/game/GameController.java index 8dda07aa665..82b9ee5e1cf 100644 --- a/Mage.Server/src/mage/server/game/GameController.java +++ b/Mage.Server/src/mage/server/game/GameController.java @@ -479,7 +479,7 @@ public class GameController implements GameCallback { if (zone.equals(Zone.BATTLEFIELD)) { card.putOntoBattlefield(game, Zone.OUTSIDE, player.getId()); } else { - card.moveToZone(zone, game, false); + card.moveToZone(zone, null, game, false); } logger.info("Added card to player's " + zone.toString() + ": " + card.getName() +", player = " + player.getName()); } diff --git a/Mage.Sets/src/mage/sets/alarareborn/VengefulRebirth.java b/Mage.Sets/src/mage/sets/alarareborn/VengefulRebirth.java index 470e80831f4..17676d23c5b 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/VengefulRebirth.java +++ b/Mage.Sets/src/mage/sets/alarareborn/VengefulRebirth.java @@ -98,7 +98,7 @@ class VengefulRebirthEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); Card card = (Card)game.getObject(source.getFirstTarget()); if (player.removeFromGraveyard(card, game)) { - card.moveToZone(Zone.HAND, game, false); + card.moveToZone(Zone.HAND, source.getId(), game, false); int damage = card.getManaCost().convertedManaCost(); if (!card.getCardType().contains(CardType.LAND)) { Permanent permanent = game.getPermanent(source.getTargets().get(1).getTargets().get(0)); diff --git a/Mage.Sets/src/mage/sets/conflux/PathToExile.java b/Mage.Sets/src/mage/sets/conflux/PathToExile.java index eccf9d50762..2d29204c158 100644 --- a/Mage.Sets/src/mage/sets/conflux/PathToExile.java +++ b/Mage.Sets/src/mage/sets/conflux/PathToExile.java @@ -94,7 +94,7 @@ class PathToExileEffect extends OneShotEffect { Permanent permanent = game.getPermanent(source.getFirstTarget()); if (permanent != null) { Player player = game.getPlayer(permanent.getControllerId()); - if (permanent.moveToZone(Zone.EXILED, game, false)) { + if (permanent.moveToZone(Zone.EXILED, source.getId(), game, false)) { if (player.chooseUse(Outcome.PutCardInPlay, "Use Path to Exile effect?", game)) { TargetCardInLibrary target = new TargetCardInLibrary(new FilterBasicLandCard()); player.searchLibrary(target, game); diff --git a/Mage.Sets/src/mage/sets/conflux/SigilOfTheEmptyThrone.java b/Mage.Sets/src/mage/sets/conflux/SigilOfTheEmptyThrone.java index ad2c092d0b1..d8f4abb2e0f 100644 --- a/Mage.Sets/src/mage/sets/conflux/SigilOfTheEmptyThrone.java +++ b/Mage.Sets/src/mage/sets/conflux/SigilOfTheEmptyThrone.java @@ -33,7 +33,6 @@ import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; import mage.MageInt; -import mage.MageObject; import mage.ObjectColor; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.CreateTokenEffect; @@ -43,6 +42,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.permanent.token.Token; +import mage.game.stack.Spell; /** * @@ -90,13 +90,13 @@ class SigilOfTheEmptyThroneAbility extends TriggeredAbilityImpl { Player you = game.getPlayer(source.getControllerId()); if (you != null) { TargetCard target = new TargetCard(Zone.PICK, filter); - if (you.chooseTarget(player.getHand(), target, source, game)) { + if (you.choose(player.getHand(), target, game)) { Card card = player.getHand().get(target.getFirstTarget(), game); if (card != null) { return player.discard(card, source, game); diff --git a/Mage.Sets/src/mage/sets/magic2010/MasterOfTheWildHunt.java b/Mage.Sets/src/mage/sets/magic2010/MasterOfTheWildHunt.java index c43f600715e..2ed7826de80 100644 --- a/Mage.Sets/src/mage/sets/magic2010/MasterOfTheWildHunt.java +++ b/Mage.Sets/src/mage/sets/magic2010/MasterOfTheWildHunt.java @@ -116,15 +116,17 @@ class MasterOfTheWildHuntEffect extends OneShotEffect public boolean apply(Game game, Ability source) { List wolves = new ArrayList(); Permanent target = game.getPermanent(source.getFirstTarget()); - if (target != null) { + if (target != null && game.getBattlefield().countAll(filter, source.getControllerId()) > 0) { for (Permanent permanent: game.getBattlefield().getAllActivePermanents(filter, source.getControllerId())) { permanent.tap(game); target.damage(permanent.getToughness().getValue(), permanent.getId(), game, true); + wolves.add(permanent.getId()); } Player player = game.getPlayer(target.getControllerId()); player.assignDamage(target.getPower().getValue(), wolves, target.getId(), game); + return true; } - return true; + return false; } @Override diff --git a/Mage.Sets/src/mage/sets/magic2011/CallToMind.java b/Mage.Sets/src/mage/sets/magic2011/CallToMind.java index 1c345e622a0..a1ed3e9b0e2 100644 --- a/Mage.Sets/src/mage/sets/magic2011/CallToMind.java +++ b/Mage.Sets/src/mage/sets/magic2011/CallToMind.java @@ -37,6 +37,7 @@ import mage.cards.CardImpl; import mage.filter.Filter.ComparisonScope; import mage.filter.FilterCard; import mage.target.TargetCard; +import mage.target.common.TargetCardInYourGraveyard; /** * @@ -44,10 +45,9 @@ import mage.target.TargetCard; */ public class CallToMind extends CardImpl { - private static FilterCard filter = new FilterCard("instant or sorcery card from your graveyard"); + private static FilterCard filter = new FilterCard("instant or sorcery card"); static { - filter.setZone(Zone.GRAVEYARD); filter.getCardType().add(CardType.INSTANT); filter.getCardType().add(CardType.SORCERY); filter.setScopeCardType(ComparisonScope.Any); @@ -59,7 +59,7 @@ public class CallToMind extends CardImpl { this.color.setBlue(true); this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); - this.getSpellAbility().addTarget(new TargetCard(Zone.GRAVEYARD, filter)); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(filter)); } public CallToMind(final CallToMind card) { diff --git a/Mage.Sets/src/mage/sets/magic2011/ConundrumSphinx.java b/Mage.Sets/src/mage/sets/magic2011/ConundrumSphinx.java index bdb42da5799..203df70bc9c 100644 --- a/Mage.Sets/src/mage/sets/magic2011/ConundrumSphinx.java +++ b/Mage.Sets/src/mage/sets/magic2011/ConundrumSphinx.java @@ -106,10 +106,10 @@ class ConundrumSphinxEffect extends OneShotEffect { cards.add(card); player.revealCards(cards, game); if (card.getName().equals(cardChoice.getChoice())) { - card.moveToZone(Zone.HAND, game, true); + card.moveToZone(Zone.HAND, source.getId(), game, true); } else { - card.moveToZone(Zone.LIBRARY, game, false); + card.moveToZone(Zone.LIBRARY, source.getId(), game, false); } } diff --git a/Mage.Sets/src/mage/sets/magic2011/Cultivate.java b/Mage.Sets/src/mage/sets/magic2011/Cultivate.java index d32e61520c8..7b5984429f2 100644 --- a/Mage.Sets/src/mage/sets/magic2011/Cultivate.java +++ b/Mage.Sets/src/mage/sets/magic2011/Cultivate.java @@ -110,7 +110,7 @@ class CultivateEffect extends OneShotEffect { if (target.getTargets().size() == 2) { TargetCard target2 = new TargetCard(Zone.PICK, filter); target2.setRequired(true); - player.chooseTarget(revealed, target2, source, game); + player.choose(revealed, target2, game); Card card = revealed.get(target2.getFirstTarget(), game); card.putOntoBattlefield(game, Zone.LIBRARY, source.getControllerId()); revealed.remove(card); @@ -118,7 +118,7 @@ class CultivateEffect extends OneShotEffect { if (permanent != null) permanent.setTapped(true); card = revealed.getCards(game).iterator().next(); - card.moveToZone(Zone.HAND, game, false); + card.moveToZone(Zone.HAND, source.getId(), game, false); } else if (target.getTargets().size() == 1) { Card card = revealed.getCards(game).iterator().next(); diff --git a/Mage.Sets/src/mage/sets/magic2011/DarkTutelage.java b/Mage.Sets/src/mage/sets/magic2011/DarkTutelage.java index d9c1ab3c4c4..c43301ec716 100644 --- a/Mage.Sets/src/mage/sets/magic2011/DarkTutelage.java +++ b/Mage.Sets/src/mage/sets/magic2011/DarkTutelage.java @@ -88,8 +88,7 @@ class DarkTutelageEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); Card card = player.getLibrary().removeFromTop(game); if (card != null) { - card.moveToZone(Zone.HAND, game, false); -// player.putInHand(card, game); + card.moveToZone(Zone.HAND, source.getId(), game, false); player.loseLife(card.getManaCost().convertedManaCost(), game); Cards cards = new CardsImpl(); cards.add(card); diff --git a/Mage.Sets/src/mage/sets/magic2011/ElixirOfImmortality.java b/Mage.Sets/src/mage/sets/magic2011/ElixirOfImmortality.java index 1dad133f8e0..a08d9c14575 100644 --- a/Mage.Sets/src/mage/sets/magic2011/ElixirOfImmortality.java +++ b/Mage.Sets/src/mage/sets/magic2011/ElixirOfImmortality.java @@ -95,8 +95,8 @@ class ElixerOfImmortalityEffect extends OneShotEffect player.gainLife(5, game); player.removeFromBattlefield(game.getPermanent(source.getSourceId()), game); Card card = game.getCard(source.getSourceId()); - card.moveToZone(Zone.LIBRARY, game, true); - player.getLibrary().addAll(player.getGraveyard().getCards(game)); + card.moveToZone(Zone.LIBRARY, source.getId(), game, true); + player.getLibrary().addAll(player.getGraveyard().getCards(game), game); player.getGraveyard().clear(); player.getLibrary().shuffle(); return true; diff --git a/Mage.Sets/src/mage/sets/magic2011/LeylineOfTheVoid.java b/Mage.Sets/src/mage/sets/magic2011/LeylineOfTheVoid.java index 90a4f6a1800..d4319daed42 100644 --- a/Mage.Sets/src/mage/sets/magic2011/LeylineOfTheVoid.java +++ b/Mage.Sets/src/mage/sets/magic2011/LeylineOfTheVoid.java @@ -38,11 +38,13 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.LeylineAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; /** * @@ -96,14 +98,26 @@ class LeylineOfTheVoidEffect extends ReplacementEffectImpl { List creatures = game.getBattlefield().getAllActivePermanents(FilterCreaturePermanent.getDefault(), source.getControllerId()); count = creatures.size(); for (Permanent creature: creatures) { - creature.moveToExile(null, null, game); + creature.moveToExile(null, null, source.getId(), game); } Cards revealed = new CardsImpl(); Cards creatureCards = new CardsImpl(); @@ -107,7 +107,7 @@ class MassPolymorphEffect extends OneShotEffect { for (Card creatureCard: creatureCards.getCards(game)) { creatureCard.putOntoBattlefield(game, Zone.LIBRARY, source.getControllerId()); } - player.getLibrary().addAll(nonCreatureCards.getCards(game)); + player.getLibrary().addAll(nonCreatureCards.getCards(game), game); player.getLibrary().shuffle(); return true; } diff --git a/Mage.Sets/src/mage/sets/magic2011/MystifyingMaze.java b/Mage.Sets/src/mage/sets/magic2011/MystifyingMaze.java index 658592c225b..0c0ce58c715 100644 --- a/Mage.Sets/src/mage/sets/magic2011/MystifyingMaze.java +++ b/Mage.Sets/src/mage/sets/magic2011/MystifyingMaze.java @@ -101,7 +101,7 @@ class MystifyingMazeEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getFirstTarget()); if (permanent != null) { - if (permanent.moveToExile(source.getSourceId(), "Mystifying Maze Exile", game)) { + if (permanent.moveToExile(source.getSourceId(), "Mystifying Maze Exile", source.getId(), game)) { //create delayed triggered ability MystifyingMazeDelayedTriggeredAbility delayedAbility = new MystifyingMazeDelayedTriggeredAbility(source.getSourceId()); delayedAbility.setSourceId(source.getSourceId()); diff --git a/Mage.Sets/src/mage/sets/magic2011/ObstinateBaloth.java b/Mage.Sets/src/mage/sets/magic2011/ObstinateBaloth.java index 6a4518c8a52..19b46ee203d 100644 --- a/Mage.Sets/src/mage/sets/magic2011/ObstinateBaloth.java +++ b/Mage.Sets/src/mage/sets/magic2011/ObstinateBaloth.java @@ -100,10 +100,13 @@ class ObstinateBalothEffect extends ReplacementEffectImpl @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.DISCARD_CARD && event.getTargetId().equals(source.getSourceId())) { - StackObject spell = game.getStack().getStackObject(event.getSourceId()); - if (spell != null && game.getOpponents(source.getControllerId()).contains(spell.getControllerId())) { - return true; + if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(source.getSourceId())) { + ZoneChangeEvent zcEvent = (ZoneChangeEvent) event; + if (zcEvent.getFromZone() == Zone.HAND && zcEvent.getToZone() == Zone.GRAVEYARD) { + StackObject spell = game.getStack().getStackObject(event.getSourceId()); + if (spell != null && game.getOpponents(source.getControllerId()).contains(spell.getControllerId())) { + return true; + } } } return false; @@ -115,7 +118,6 @@ class ObstinateBalothEffect extends ReplacementEffectImpl if (card != null) { Player player = game.getPlayer(card.getOwnerId()); if (player != null) { - player.removeFromHand(card, game); if (card.putOntoBattlefield(game, Zone.HAND, player.getId())) { game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DISCARDED_CARD, card.getId(), source.getId(), player.getId())); return true; diff --git a/Mage.Sets/src/mage/sets/magic2011/TimeReversal.java b/Mage.Sets/src/mage/sets/magic2011/TimeReversal.java index 66ea729ac14..e2707e4df5e 100644 --- a/Mage.Sets/src/mage/sets/magic2011/TimeReversal.java +++ b/Mage.Sets/src/mage/sets/magic2011/TimeReversal.java @@ -84,8 +84,8 @@ class TimeReversalEffect extends OneShotEffect { for (UUID playerId: sourcePlayer.getInRange()) { Player player = game.getPlayer(playerId); if (player != null) { - player.getLibrary().addAll(player.getHand().getCards(game)); - player.getLibrary().addAll(player.getGraveyard().getCards(game)); + player.getLibrary().addAll(player.getHand().getCards(game), game); + player.getLibrary().addAll(player.getGraveyard().getCards(game), game); player.getLibrary().shuffle(); player.getHand().clear(); player.getGraveyard().clear(); diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeaGateOracle.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeaGateOracle.java index 702d3977cde..b880119c42a 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeaGateOracle.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeaGateOracle.java @@ -97,23 +97,24 @@ class SeaGateOracleEffect extends OneShotEffect { if (player.getLibrary().size() > 0) { if (player.getLibrary().size() == 1) { Card card = player.getLibrary().removeFromTop(game); - card.moveToZone(Zone.HAND, game, false); -// player.putInHand(player.getLibrary().removeFromTop(game), game); + card.moveToZone(Zone.HAND, source.getId(), game, false); } else { Cards cards = new CardsImpl(Zone.PICK); - cards.add(player.getLibrary().removeFromTop(game)); - cards.add(player.getLibrary().removeFromTop(game)); + Card card = player.getLibrary().removeFromTop(game); + cards.add(card); + game.setZone(card.getId(), Zone.PICK); + card = player.getLibrary().removeFromTop(game); + cards.add(card); + game.setZone(card.getId(), Zone.PICK); TargetCard target = new TargetCard(Zone.PICK, filter); target.setRequired(true); player.lookAtCards(cards, game); - player.chooseTarget(cards, target, source, game); - Card card = cards.get(target.getFirstTarget(), game); - card.moveToZone(Zone.HAND, game, false); -// player.putInHand(cards.get(target.getFirstTarget(), game), game); + player.choose(cards, target, game); + card = cards.get(target.getFirstTarget(), game); + card.moveToZone(Zone.HAND, source.getId(), game, false); for (Card card1: cards.getCards(game)) { - card1.moveToZone(Zone.LIBRARY, game, false); -// player.getLibrary().putOnBottom(cards.get(cardId, game), game); + card1.moveToZone(Zone.LIBRARY, source.getId(), game, false); } } return true; diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeeBeyond.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeeBeyond.java index c652a953274..0e15afba98c 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeeBeyond.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SeeBeyond.java @@ -90,12 +90,11 @@ class SeeBeyondEffect extends OneShotEffect { if (player.getHand().size() > 0) { TargetCard target = new TargetCard(Zone.HAND, filter); target.setRequired(true); - player.chooseTarget(player.getHand(), target, source, game); + player.choose(player.getHand(), target, game); Card card = player.getHand().get(target.getFirstTarget(), game); if (card != null) { player.removeFromHand(card, game); - card.moveToZone(Zone.LIBRARY, game, true); -// player.getLibrary().putOnTop(card, game); + card.moveToZone(Zone.LIBRARY, source.getId(), game, true); player.getLibrary().shuffle(); return true; } diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/Vengevine.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/Vengevine.java index a19fa45f949..a751ebfdd6d 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/Vengevine.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/Vengevine.java @@ -134,7 +134,7 @@ class VengevineWatcher extends WatcherImpl { @Override public void watch(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST && event.getPlayerId().equals(controllerId)) { - Spell spell = (Spell)game.getStack().getStackObject(event.getTargetId()); + Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getCardType().contains(CardType.CREATURE)) { creatureSpellCount++; if (creatureSpellCount == 2) diff --git a/Mage.Sets/src/mage/sets/tenth/AngelsFeather.java b/Mage.Sets/src/mage/sets/tenth/AngelsFeather.java index f3ef9665efe..72fc30db1fa 100644 --- a/Mage.Sets/src/mage/sets/tenth/AngelsFeather.java +++ b/Mage.Sets/src/mage/sets/tenth/AngelsFeather.java @@ -32,13 +32,13 @@ import java.util.UUID; import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; -import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; /** * @@ -86,7 +86,7 @@ class AngelsFeatherAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST) { - MageObject spell = game.getObject(event.getTargetId()); + Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getColor().isWhite()) { trigger(game, event.getPlayerId()); return true; diff --git a/Mage.Sets/src/mage/sets/tenth/DemonsHorn.java b/Mage.Sets/src/mage/sets/tenth/DemonsHorn.java index 5f7529f2c9b..5e8135a22f2 100644 --- a/Mage.Sets/src/mage/sets/tenth/DemonsHorn.java +++ b/Mage.Sets/src/mage/sets/tenth/DemonsHorn.java @@ -32,13 +32,13 @@ import java.util.UUID; import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; -import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; /** * @@ -86,7 +86,7 @@ class DemonsHornAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST) { - MageObject spell = game.getObject(event.getTargetId()); + Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getColor().isBlack()) { trigger(game, event.getPlayerId()); return true; diff --git a/Mage.Sets/src/mage/sets/tenth/DragonsClaw.java b/Mage.Sets/src/mage/sets/tenth/DragonsClaw.java index bc69ae4a264..fca944816bb 100644 --- a/Mage.Sets/src/mage/sets/tenth/DragonsClaw.java +++ b/Mage.Sets/src/mage/sets/tenth/DragonsClaw.java @@ -32,13 +32,13 @@ import java.util.UUID; import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; -import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; /** * @@ -86,7 +86,7 @@ class DragonsClawAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST) { - MageObject spell = game.getObject(event.getTargetId()); + Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getColor().isRed()) { trigger(game, event.getPlayerId()); return true; diff --git a/Mage.Sets/src/mage/sets/tenth/KrakensEye.java b/Mage.Sets/src/mage/sets/tenth/KrakensEye.java index 613c5b3eaa7..c2cdf0520d0 100644 --- a/Mage.Sets/src/mage/sets/tenth/KrakensEye.java +++ b/Mage.Sets/src/mage/sets/tenth/KrakensEye.java @@ -32,13 +32,13 @@ import java.util.UUID; import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; -import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; /** * @@ -86,7 +86,7 @@ class KrakensEyeAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST) { - MageObject spell = game.getObject(event.getTargetId()); + Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getColor().isBlue()) { trigger(game, event.getPlayerId()); return true; diff --git a/Mage.Sets/src/mage/sets/tenth/WurmsTooth.java b/Mage.Sets/src/mage/sets/tenth/WurmsTooth.java index d21441472ae..e0c02bc783a 100644 --- a/Mage.Sets/src/mage/sets/tenth/WurmsTooth.java +++ b/Mage.Sets/src/mage/sets/tenth/WurmsTooth.java @@ -32,13 +32,13 @@ import java.util.UUID; import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; -import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; /** * @@ -86,7 +86,7 @@ class WurmsToothAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST) { - MageObject spell = game.getObject(event.getTargetId()); + Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getColor().isGreen()) { trigger(game, event.getPlayerId()); return true; diff --git a/Mage.Sets/src/mage/sets/worldwake/JaceTheMindSculptor.java b/Mage.Sets/src/mage/sets/worldwake/JaceTheMindSculptor.java index fb9f02f42cd..0f58fe86139 100644 --- a/Mage.Sets/src/mage/sets/worldwake/JaceTheMindSculptor.java +++ b/Mage.Sets/src/mage/sets/worldwake/JaceTheMindSculptor.java @@ -122,8 +122,7 @@ class JaceTheMindSculptorEffect1 extends OneShotEffect { defender.revealCards(cards, game); if (card.getCardType().contains(CardType.LAND)) { defender.getLibrary().removeFromTop(game); - card.moveToZone(Zone.HAND, game, true); -// defender.putInHand(card, game); + card.moveToZone(Zone.HAND, source.getId(), game, true); } } } diff --git a/Mage/src/mage/Constants.java b/Mage/src/mage/Constants.java index 2bb5436697c..572feb24ffd 100644 --- a/Mage/src/mage/Constants.java +++ b/Mage/src/mage/Constants.java @@ -139,6 +139,27 @@ public final class Constants { } } + public enum EffectType { + + ONESHOT("One Shot Effect"), + CONTINUOUS("Continuous Effect"), + REPLACEMENT("Replacement Effect"), + PREVENTION("Prevention Effect"), + REDIRECTION("Redirection Effect"), + ASTHOUGH("As Though Effect"); + + private String text; + + EffectType(String text) { + this.text = text; + } + + @Override + public String toString() { + return text; + } + } + public enum AsThoughEffectType { BLOCK, BE_BLOCKED, diff --git a/Mage/src/mage/MageObject.java b/Mage/src/mage/MageObject.java index c9f0323ea2b..0c41f4629f9 100644 --- a/Mage/src/mage/MageObject.java +++ b/Mage/src/mage/MageObject.java @@ -27,8 +27,8 @@ public interface MageObject extends MageItem, Serializable { public MageInt getToughness(); public MageInt getLoyalty(); - public Zone getZone(); - public void setZone(Zone zone); +// public Zone getZone(); +// public void setZone(Zone zone); public void adjustCosts(Ability ability, Game game); diff --git a/Mage/src/mage/MageObjectImpl.java b/Mage/src/mage/MageObjectImpl.java index 30133e742db..49ac4b7edc3 100644 --- a/Mage/src/mage/MageObjectImpl.java +++ b/Mage/src/mage/MageObjectImpl.java @@ -57,7 +57,7 @@ public abstract class MageObjectImpl> implements Mag protected MageInt power; protected MageInt toughness; protected MageInt loyalty; - protected Zone zone; +// protected Zone zone; @Override public abstract T copy(); @@ -81,7 +81,7 @@ public abstract class MageObjectImpl> implements Mag name = object.name; manaCost = object.manaCost.copy(); text = object.text; - zone = object.zone; +// zone = object.zone; color = object.color.copy(); power = object.power.copy(); toughness = object.toughness.copy(); @@ -158,15 +158,15 @@ public abstract class MageObjectImpl> implements Mag return manaCost; } - @Override - public Zone getZone() { - return zone; - } - - @Override - public void setZone(Zone zone) { - this.zone = zone; - } +// @Override +// public Zone getZone() { +// return zone; +// } +// +// @Override +// public void setZone(Zone zone) { +// this.zone = zone; +// } @Override public void adjustCosts(Ability ability, Game game) {} diff --git a/Mage/src/mage/abilities/Ability.java b/Mage/src/mage/abilities/Ability.java index f7485df3f13..89eb2a9db82 100644 --- a/Mage/src/mage/abilities/Ability.java +++ b/Mage/src/mage/abilities/Ability.java @@ -32,6 +32,7 @@ import java.io.Serializable; import java.util.List; import java.util.UUID; import mage.Constants.AbilityType; +import mage.Constants.EffectType; import mage.Constants.Zone; import mage.abilities.costs.AlternativeCost; import mage.abilities.costs.Cost; @@ -61,6 +62,7 @@ public interface Ability extends Serializable { public Costs getOptionalCosts(); public void addOptionalCost(Cost cost); public Effects getEffects(); + public Effects getEffects(EffectType effectType); public void addEffect(Effect effect); public Targets getTargets(); public UUID getFirstTarget(); diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index c851e32d3bf..f8bda1ad99b 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -33,6 +33,7 @@ import java.util.List; import java.util.UUID; import java.util.logging.Logger; import mage.Constants.AbilityType; +import mage.Constants.EffectType; import mage.Constants.Outcome; import mage.Constants.Zone; import mage.abilities.costs.AlternativeCost; @@ -46,8 +47,6 @@ import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.Effects; import mage.abilities.effects.OneShotEffect; -import mage.abilities.keyword.EnchantAbility; -import mage.cards.Card; import mage.choices.Choice; import mage.choices.Choices; import mage.game.Game; @@ -235,6 +234,17 @@ public abstract class AbilityImpl> implements Ability { return effects; } + @Override + public Effects getEffects(EffectType effectType) { + Effects typedEffects = new Effects(); + for (Effect effect: effects) { + if (effect.getEffectType() == effectType) { + typedEffects.add(effect); + } + } + return typedEffects; + } + @Override public Choices getChoices() { return choices; diff --git a/Mage/src/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/mage/abilities/ActivatedAbilityImpl.java index 9f139a59f5d..e220b8e32f5 100644 --- a/Mage/src/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/mage/abilities/ActivatedAbilityImpl.java @@ -154,7 +154,7 @@ public abstract class ActivatedAbilityImpl> ex return true; else { Card card = (Card)game.getObject(this.sourceId); - if (card != null && card.getZone() != Zone.BATTLEFIELD) + if (card != null && game.getZone(this.sourceId) != Zone.BATTLEFIELD) return card.getOwnerId().equals(playerId); } return false; diff --git a/Mage/src/mage/abilities/costs/common/ExileSourceCost.java b/Mage/src/mage/abilities/costs/common/ExileSourceCost.java index 26e19163b47..c1c50f08b02 100644 --- a/Mage/src/mage/abilities/costs/common/ExileSourceCost.java +++ b/Mage/src/mage/abilities/costs/common/ExileSourceCost.java @@ -29,7 +29,6 @@ package mage.abilities.costs.common; import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.game.Game; import mage.game.permanent.Permanent; @@ -52,7 +51,7 @@ public class ExileSourceCost extends CostImpl { public boolean pay(Game game, UUID sourceId, UUID controllerId, boolean noMana) { Permanent permanent = game.getPermanent(sourceId); if (permanent != null) { - paid = permanent.moveToExile(null, "", game); + paid = permanent.moveToExile(null, "", sourceId, game); } return paid; } diff --git a/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java b/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java index 0de197a4730..725e4382f4e 100644 --- a/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/ReturnToHandTargetCost.java @@ -58,7 +58,7 @@ public class ReturnToHandTargetCost extends CostImpl { Permanent permanent = game.getPermanent(targetId); if (permanent == null) return false; - paid |= permanent.moveToZone(Zone.HAND, game, false); + paid |= permanent.moveToZone(Zone.HAND, sourceId, game, false); } } return paid; diff --git a/Mage/src/mage/abilities/effects/AsThoughEffectImpl.java b/Mage/src/mage/abilities/effects/AsThoughEffectImpl.java index 46ce0996b0d..251843d4ee7 100644 --- a/Mage/src/mage/abilities/effects/AsThoughEffectImpl.java +++ b/Mage/src/mage/abilities/effects/AsThoughEffectImpl.java @@ -30,6 +30,7 @@ package mage.abilities.effects; import mage.Constants.AsThoughEffectType; import mage.Constants.Duration; +import mage.Constants.EffectType; import mage.Constants.Outcome; /** @@ -43,6 +44,7 @@ public abstract class AsThoughEffectImpl> extend public AsThoughEffectImpl(AsThoughEffectType type, Duration duration, Outcome outcome) { super(duration, outcome); this.type = type; + this.effectType = EffectType.ASTHOUGH; } public AsThoughEffectImpl(final AsThoughEffectImpl effect) { diff --git a/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java b/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java index e661647ce40..9ed1ee404a4 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java @@ -30,6 +30,7 @@ package mage.abilities.effects; import java.util.Date; import mage.Constants.Duration; +import mage.Constants.EffectType; import mage.Constants.Layer; import mage.Constants.Outcome; import mage.Constants.SubLayer; @@ -52,6 +53,7 @@ public abstract class ContinuousEffectImpl> ex super(outcome); this.duration = duration; this.timestamp = new Date(); + this.effectType = EffectType.CONTINUOUS; } public ContinuousEffectImpl(Duration duration, Layer layer, SubLayer sublayer, Outcome outcome) { diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index ebd007c8b9c..11555f95a3c 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -40,9 +40,12 @@ import java.util.Map.Entry; import java.util.UUID; import mage.Constants.AsThoughEffectType; import mage.Constants.Duration; +import mage.Constants.EffectType; import mage.Constants.Layer; import mage.Constants.SubLayer; +import mage.Constants.Zone; import mage.abilities.Ability; +import mage.cards.Card; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; @@ -54,10 +57,15 @@ import mage.players.Player; */ public class ContinuousEffects implements Serializable { - private final Map layeredEffects = new HashMap(); - private final Map replacementEffects = new HashMap(); - private final Map preventionEffects = new HashMap(); - private final Map asThoughEffects = new HashMap(); + //transient Continuous effects + private final List layeredEffects = new ArrayList(); + private final List replacementEffects = new ArrayList(); + private final List preventionEffects = new ArrayList(); + private final List asThoughEffects = new ArrayList(); + + //map Abilities to Continuous effects + private final Map abilityMap = new HashMap(); + private final ApplyCountersEffect applyCounters; private final PlaneswalkerRedirectionEffect planeswalkerRedirectionEffect; @@ -69,17 +77,20 @@ public class ContinuousEffects implements Serializable { public ContinuousEffects(final ContinuousEffects effect) { this.applyCounters = effect.applyCounters.copy(); this.planeswalkerRedirectionEffect = effect.planeswalkerRedirectionEffect.copy(); - for (Entry entry: effect.layeredEffects.entrySet()) { - layeredEffects.put((ContinuousEffect)entry.getKey().copy(), entry.getValue().copy()); + for (ContinuousEffect entry: effect.layeredEffects) { + layeredEffects.add((ContinuousEffect) entry.copy()); } - for (Entry entry: effect.replacementEffects.entrySet()) { - replacementEffects.put((ReplacementEffect)entry.getKey().copy(), entry.getValue().copy()); + for (ReplacementEffect entry: effect.replacementEffects) { + replacementEffects.add((ReplacementEffect)entry.copy()); } - for (Entry entry: effect.preventionEffects.entrySet()) { - preventionEffects.put((PreventionEffect)entry.getKey().copy(), entry.getValue().copy()); + for (PreventionEffect entry: effect.preventionEffects) { + preventionEffects.add((PreventionEffect)entry.copy()); } - for (Entry entry: effect.asThoughEffects.entrySet()) { - asThoughEffects.put((AsThoughEffect)entry.getKey().copy(), entry.getValue().copy()); + for (AsThoughEffect entry: effect.asThoughEffects) { + asThoughEffects.add((AsThoughEffect)entry.copy()); + } + for (Entry entry: effect.abilityMap.entrySet()) { + abilityMap.put((ContinuousEffect)entry.getKey().copy(), entry.getValue().copy()); } } @@ -88,22 +99,22 @@ public class ContinuousEffects implements Serializable { } public void removeEndOfTurnEffects() { - for (Iterator i = layeredEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = layeredEffects.iterator(); i.hasNext();) { ContinuousEffect entry = i.next(); if (entry.getDuration() == Duration.EndOfTurn) i.remove(); } - for (Iterator i = replacementEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = replacementEffects.iterator(); i.hasNext();) { ContinuousEffect entry = i.next(); if (entry.getDuration() == Duration.EndOfTurn) i.remove(); } - for (Iterator i = preventionEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = preventionEffects.iterator(); i.hasNext();) { ContinuousEffect entry = i.next(); if (entry.getDuration() == Duration.EndOfTurn) i.remove(); } - for (Iterator i = asThoughEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = asThoughEffects.iterator(); i.hasNext();) { ContinuousEffect entry = i.next(); if (entry.getDuration() == Duration.EndOfTurn) i.remove(); @@ -111,40 +122,40 @@ public class ContinuousEffects implements Serializable { } public void removeInactiveEffects(Game game) { - for (Iterator i = layeredEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = layeredEffects.iterator(); i.hasNext();) { ContinuousEffect entry = i.next(); if (entry.getDuration() == Duration.WhileOnBattlefield) { - Permanent permanent = game.getPermanent(layeredEffects.get(entry).getSourceId()); + Permanent permanent = game.getPermanent(abilityMap.get(entry).getSourceId()); if (permanent == null || !permanent.isPhasedIn()) i.remove(); } else if (entry.getDuration() == Duration.OneUse && entry.isUsed()) i.remove(); } - for (Iterator i = replacementEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = replacementEffects.iterator(); i.hasNext();) { ReplacementEffect entry = i.next(); if (entry.getDuration() == Duration.WhileOnBattlefield) { - Permanent permanent = game.getPermanent(replacementEffects.get(entry).getSourceId()); + Permanent permanent = game.getPermanent(abilityMap.get(entry).getSourceId()); if (permanent == null || !permanent.isPhasedIn()) i.remove(); } else if (entry.getDuration() == Duration.OneUse && entry.isUsed()) i.remove(); } - for (Iterator i = preventionEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = preventionEffects.iterator(); i.hasNext();) { PreventionEffect entry = i.next(); if (entry.getDuration() == Duration.WhileOnBattlefield) { - Permanent permanent = game.getPermanent(preventionEffects.get(entry).getSourceId()); + Permanent permanent = game.getPermanent(abilityMap.get(entry).getSourceId()); if (permanent == null || !permanent.isPhasedIn()) i.remove(); } else if (entry.getDuration() == Duration.OneUse && entry.isUsed()) i.remove(); } - for (Iterator i = asThoughEffects.keySet().iterator(); i.hasNext();) { + for (Iterator i = asThoughEffects.iterator(); i.hasNext();) { AsThoughEffect entry = i.next(); if (entry.getDuration() == Duration.WhileOnBattlefield) { - Permanent permanent = game.getPermanent(asThoughEffects.get(entry).getSourceId()); + Permanent permanent = game.getPermanent(abilityMap.get(entry).getSourceId()); if (permanent == null || !permanent.isPhasedIn()) i.remove(); } @@ -153,31 +164,93 @@ public class ContinuousEffects implements Serializable { } } - private List getLayeredEffects() { - List layerEffects = new ArrayList(layeredEffects.keySet()); + private List getLayeredEffects(Game game) { + List layerEffects = new ArrayList(layeredEffects); + for (Card card: game.getCards()) { + if (game.getZone(card.getId()) == Zone.HAND || game.getZone(card.getId()) == Zone.GRAVEYARD) { + for (Ability ability: card.getAbilities().getStaticAbilities(game.getZone(card.getId()))) { + for (Effect effect: ability.getEffects(EffectType.CONTINUOUS)) { + layerEffects.add((ContinuousEffect) effect); + abilityMap.put((ContinuousEffect) effect, ability); + } + } + } + } + for (Permanent permanent: game.getBattlefield().getAllPermanents()) { + for (Ability ability: permanent.getAbilities().getStaticAbilities(Zone.BATTLEFIELD)) { + for (Effect effect: ability.getEffects(EffectType.CONTINUOUS)) { + layerEffects.add((ContinuousEffect) effect); + abilityMap.put((ContinuousEffect) effect, ability); + } + } + } Collections.sort(layerEffects, new TimestampSorter()); return layerEffects; } + /** + * + * @param event + * @param game + * @return a list of all {@link ReplacementEffect} that apply to the current event + */ private List getApplicableReplacementEffects(GameEvent event, Game game) { List replaceEffects = new ArrayList(); if (planeswalkerRedirectionEffect.applies(event, null, game)) replaceEffects.add(planeswalkerRedirectionEffect); - for (ReplacementEffect effect: replacementEffects.keySet()) { - if (effect.applies(event, replacementEffects.get(effect), game)) { - if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) + //get all applicable Replacement effects in each players hand and graveyard + for (Card card: game.getCards()) { + if (game.getZone(card.getId()) == Zone.HAND || game.getZone(card.getId()) == Zone.GRAVEYARD) { + for (Ability ability: card.getAbilities().getStaticAbilities(game.getZone(card.getId()))) { + for (Effect effect: ability.getEffects(EffectType.REPLACEMENT)) { + ReplacementEffect rEffect = (ReplacementEffect) effect; + if (rEffect.applies(event, ability, game)) { + replaceEffects.add(rEffect); + abilityMap.put(rEffect, ability); + } + } + } + } + } + //get all applicable Replacement effects on the battlefield + for (Permanent permanent: game.getBattlefield().getAllPermanents()) { + for (Ability ability: permanent.getAbilities().getStaticAbilities(Zone.BATTLEFIELD)) { + for (Effect effect: ability.getEffects(EffectType.REPLACEMENT)) { + ReplacementEffect rEffect = (ReplacementEffect) effect; + if (rEffect.applies(event, ability, game)) { + replaceEffects.add(rEffect); + abilityMap.put(rEffect, ability); + } + } + } + } + //get all applicable transient Replacement effects + for (ReplacementEffect effect: replacementEffects) { + if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { + if (effect.applies(event, abilityMap.get(effect), game)) { replaceEffects.add(effect); + } } } return replaceEffects; } public boolean asThough(UUID objectId, AsThoughEffectType type, Game game) { - for (Entry entry: asThoughEffects.entrySet()) { - AsThoughEffect effect = entry.getKey(); + for (Permanent permanent: game.getBattlefield().getAllPermanents()) { + for (Ability ability: permanent.getAbilities().getStaticAbilities(Zone.BATTLEFIELD)) { + for (Effect effect: ability.getEffects(EffectType.ASTHOUGH)) { + AsThoughEffect rEffect = (AsThoughEffect) effect; + if (rEffect.applies(objectId, ability, game)) { + return true; + } + } + } + } + for (AsThoughEffect entry: asThoughEffects) { + AsThoughEffect effect = entry; if (effect.getAsThoughEffectType() == type) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { - if (effect.applies(objectId, entry.getValue(), game)) { + if (effect.applies(objectId, abilityMap.get(entry), game)) { return true; } } @@ -195,10 +268,12 @@ public class ContinuousEffects implements Serializable { index = 0; } else { + //20100716 - 616.1c Player player = game.getPlayer(event.getPlayerId()); index = player.chooseEffect(rEffects, game); } - caught = rEffects.get(index).replaceEvent(event, replacementEffects.get(rEffects.get(index)), game); + ReplacementEffect rEffect = rEffects.get(index); + caught = rEffect.replaceEvent(event, abilityMap.get(rEffect), game); } return caught; @@ -207,84 +282,90 @@ public class ContinuousEffects implements Serializable { //20091005 - 613 public void apply(Game game) { removeInactiveEffects(game); - List layerEffects = getLayeredEffects(); + List layerEffects = getLayeredEffects(game); for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.CopyEffects_1, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.CopyEffects_1, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.CopyEffects_1, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.CopyEffects_1, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.ControlChangingEffects_2, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.ControlChangingEffects_2, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.ControlChangingEffects_2, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.ControlChangingEffects_2, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.TextChangingEffects_3, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.TextChangingEffects_3, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.TextChangingEffects_3, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.TextChangingEffects_3, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.TypeChangingEffects_4, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.TypeChangingEffects_4, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.TypeChangingEffects_4, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.TypeChangingEffects_4, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.ColorChangingEffects_5, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.ColorChangingEffects_5, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.ColorChangingEffects_5, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.ColorChangingEffects_5, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.AbilityAddingRemovingEffects_6, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.AbilityAddingRemovingEffects_6, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.PTChangingEffects_7, SubLayer.CharacteristicDefining_7a, layeredEffects.get(effect), game); + effect.apply(Layer.PTChangingEffects_7, SubLayer.CharacteristicDefining_7a, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.PTChangingEffects_7, SubLayer.SetPT_7b, layeredEffects.get(effect), game); + effect.apply(Layer.PTChangingEffects_7, SubLayer.SetPT_7b, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, layeredEffects.get(effect), game); + effect.apply(Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, abilityMap.get(effect), game); } applyCounters.apply(Layer.PTChangingEffects_7, SubLayer.Counters_7d, null, game); for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.PTChangingEffects_7, SubLayer.SwitchPT_e, layeredEffects.get(effect), game); + effect.apply(Layer.PTChangingEffects_7, SubLayer.SwitchPT_e, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.PlayerEffects, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.PlayerEffects, SubLayer.NA, abilityMap.get(effect), game); } for (ContinuousEffect effect: layerEffects) { - effect.apply(Layer.RulesEffects, SubLayer.NA, layeredEffects.get(effect), game); + effect.apply(Layer.RulesEffects, SubLayer.NA, abilityMap.get(effect), game); } } public void addEffect(ContinuousEffect effect, Ability source) { - if (effect instanceof ReplacementEffect) { - ReplacementEffect newEffect = (ReplacementEffect)effect.copy(); - newEffect.setTimestamp(); - replacementEffects.put(newEffect, source); - } - else if (effect instanceof PreventionEffect) { - PreventionEffect newEffect = (PreventionEffect)effect.copy(); - newEffect.setTimestamp(); - preventionEffects.put(newEffect, source); - } - else if (effect instanceof AsThoughEffect) { - AsThoughEffect newEffect = (AsThoughEffect)effect.copy(); - newEffect.setTimestamp(); - asThoughEffects.put(newEffect,source); - } - else { - ContinuousEffect newEffect = (ContinuousEffect)effect.copy(); - newEffect.setTimestamp(); - layeredEffects.put(newEffect, source); + switch (effect.getEffectType()) { + case REPLACEMENT: + ReplacementEffect newReplacementEffect = (ReplacementEffect)effect.copy(); + newReplacementEffect.setTimestamp(); + replacementEffects.add(newReplacementEffect); + abilityMap.put(newReplacementEffect, source); + break; + case PREVENTION: + PreventionEffect newPreventionEffect = (PreventionEffect)effect.copy(); + newPreventionEffect.setTimestamp(); + preventionEffects.add(newPreventionEffect); + abilityMap.put(newPreventionEffect, source); + break; + case ASTHOUGH: + AsThoughEffect newAsThoughEffect = (AsThoughEffect)effect.copy(); + newAsThoughEffect.setTimestamp(); + asThoughEffects.add(newAsThoughEffect); + abilityMap.put(newAsThoughEffect, source); + break; + default: + ContinuousEffect newEffect = (ContinuousEffect)effect.copy(); + newEffect.setTimestamp(); + layeredEffects.add(newEffect); + abilityMap.put(newEffect, source); + break; } } diff --git a/Mage/src/mage/abilities/effects/Effect.java b/Mage/src/mage/abilities/effects/Effect.java index 6765b2e3612..cf44c0105ce 100644 --- a/Mage/src/mage/abilities/effects/Effect.java +++ b/Mage/src/mage/abilities/effects/Effect.java @@ -29,6 +29,7 @@ package mage.abilities.effects; import java.io.Serializable; +import mage.Constants.EffectType; import mage.Constants.Outcome; import mage.abilities.Ability; import mage.game.Game; @@ -42,6 +43,7 @@ public interface Effect> extends Serializable { public String getText(Ability source); public boolean apply(Game game, Ability source); public Outcome getOutcome(); + public EffectType getEffectType(); public T copy(); diff --git a/Mage/src/mage/abilities/effects/EffectImpl.java b/Mage/src/mage/abilities/effects/EffectImpl.java index ed31d6294fc..856334f0150 100644 --- a/Mage/src/mage/abilities/effects/EffectImpl.java +++ b/Mage/src/mage/abilities/effects/EffectImpl.java @@ -28,6 +28,7 @@ package mage.abilities.effects; +import mage.Constants.EffectType; import mage.Constants.Outcome; import mage.abilities.Ability; @@ -38,6 +39,7 @@ import mage.abilities.Ability; public abstract class EffectImpl> implements Effect { protected final Outcome outcome; + protected EffectType effectType; public EffectImpl(Outcome outcome) { this.outcome = outcome; @@ -45,6 +47,7 @@ public abstract class EffectImpl> implements Effect { public EffectImpl(final EffectImpl effect) { this.outcome = effect.outcome; + this.effectType = effect.effectType; } @Override @@ -56,4 +59,9 @@ public abstract class EffectImpl> implements Effect { public Outcome getOutcome() { return outcome; } + + @Override + public EffectType getEffectType() { + return effectType; + } } diff --git a/Mage/src/mage/abilities/effects/OneShotEffect.java b/Mage/src/mage/abilities/effects/OneShotEffect.java index 6640e252ea0..608bd7c0b8f 100644 --- a/Mage/src/mage/abilities/effects/OneShotEffect.java +++ b/Mage/src/mage/abilities/effects/OneShotEffect.java @@ -28,6 +28,7 @@ package mage.abilities.effects; +import mage.Constants.EffectType; import mage.Constants.Outcome; /** @@ -38,6 +39,7 @@ public abstract class OneShotEffect> extends EffectIm public OneShotEffect(Outcome outcome) { super(outcome); + this.effectType = EffectType.ONESHOT; } public OneShotEffect(final OneShotEffect effect) { diff --git a/Mage/src/mage/abilities/effects/PreventionEffectImpl.java b/Mage/src/mage/abilities/effects/PreventionEffectImpl.java index d31159d8427..c3fc4f78c17 100644 --- a/Mage/src/mage/abilities/effects/PreventionEffectImpl.java +++ b/Mage/src/mage/abilities/effects/PreventionEffectImpl.java @@ -29,6 +29,7 @@ package mage.abilities.effects; import mage.Constants.Duration; +import mage.Constants.EffectType; import mage.Constants.Outcome; import mage.abilities.Ability; import mage.game.Game; @@ -43,6 +44,7 @@ public abstract class PreventionEffectImpl> ex public PreventionEffectImpl(Duration duration) { super(duration, Outcome.PreventDamage); + this.effectType = EffectType.PREVENTION; } public PreventionEffectImpl(final PreventionEffectImpl effect) { diff --git a/Mage/src/mage/abilities/effects/RedirectionEffect.java b/Mage/src/mage/abilities/effects/RedirectionEffect.java index 3e1e9734dea..99ead53d869 100644 --- a/Mage/src/mage/abilities/effects/RedirectionEffect.java +++ b/Mage/src/mage/abilities/effects/RedirectionEffect.java @@ -30,6 +30,7 @@ package mage.abilities.effects; import java.util.UUID; import mage.Constants.Duration; +import mage.Constants.EffectType; import mage.Constants.Outcome; import mage.abilities.Ability; import mage.game.Game; @@ -51,6 +52,7 @@ public abstract class RedirectionEffect> extends public RedirectionEffect(Duration duration) { super(duration, Outcome.RedirectDamage); + this.effectType = EffectType.REDIRECTION; } public RedirectionEffect(final RedirectionEffect effect) { diff --git a/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java b/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java index fcb5512f999..956e7cf30da 100644 --- a/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java +++ b/Mage/src/mage/abilities/effects/ReplacementEffectImpl.java @@ -29,6 +29,7 @@ package mage.abilities.effects; import mage.Constants.Duration; +import mage.Constants.EffectType; import mage.Constants.Outcome; /** @@ -39,6 +40,7 @@ public abstract class ReplacementEffectImpl> public ReplacementEffectImpl(Duration duration, Outcome outcome) { super(duration, outcome); + this.effectType = EffectType.REPLACEMENT; } public ReplacementEffectImpl(final ReplacementEffectImpl effect) { diff --git a/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java b/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java index 1b4bdc01140..9c66181a0d5 100644 --- a/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java @@ -61,8 +61,10 @@ public class CantCounterControlledEffect extends ReplacementEffectImpl { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - return permanent.moveToExile(null, "", game); + return permanent.moveToExile(null, "", source.getId(), game); } return false; } diff --git a/Mage/src/mage/abilities/effects/common/ExileTargetEffect.java b/Mage/src/mage/abilities/effects/common/ExileTargetEffect.java index 06cd20a3a11..19fdc8ad145 100644 --- a/Mage/src/mage/abilities/effects/common/ExileTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/ExileTargetEffect.java @@ -69,7 +69,7 @@ public class ExileTargetEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getFirstTarget()); if (permanent != null) { - return permanent.moveToExile(exileId, exileZone, game); + return permanent.moveToExile(exileId, exileZone, source.getId(), game); } return false; } diff --git a/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java b/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java index 46f0de402b2..14e6fad02df 100644 --- a/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java @@ -66,19 +66,14 @@ public class PutOnLibraryTargetEffect extends OneShotEffect if (exile != null) { for (UUID cardId: exile) { Card card = game.getCard(cardId); - card.moveToZone(zone, game, tapped); + card.moveToZone(zone, source.getId(), game, tapped); } exile.clear(); return true; diff --git a/Mage/src/mage/abilities/effects/common/ReturnSourceFromGraveyardToHandEffect.java b/Mage/src/mage/abilities/effects/common/ReturnSourceFromGraveyardToHandEffect.java index 6a9791612db..3c5e5f68562 100644 --- a/Mage/src/mage/abilities/effects/common/ReturnSourceFromGraveyardToHandEffect.java +++ b/Mage/src/mage/abilities/effects/common/ReturnSourceFromGraveyardToHandEffect.java @@ -61,7 +61,7 @@ public class ReturnSourceFromGraveyardToHandEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); Cards cards = new CardsImpl(Zone.PICK); for (int i = 0; i < scryNumber; i++) { - cards.add(player.getLibrary().removeFromTop(game)); + Card card = player.getLibrary().removeFromTop(game); + cards.add(card); + game.setZone(card.getId(), Zone.PICK); } TargetCard target1 = new TargetCard(Zone.PICK, filter1); - while (cards.size() > 0 && player.chooseTarget(cards, target1, source, game)) { + while (cards.size() > 0 && player.choose(cards, target1, game)) { Card card = cards.get(target1.getFirstTarget(), game); cards.remove(card); - card.moveToZone(Zone.LIBRARY, game, false); -// player.getLibrary().putOnBottom(card, game); + card.moveToZone(Zone.LIBRARY, source.getId(), game, false); target1.clearChosen(); } if (cards.size() > 1) { TargetCard target2 = new TargetCard(Zone.PICK, filter2); target2.setRequired(true); while (cards.size() > 1) { - player.chooseTarget(cards, target2, source, game); + player.choose(cards, target2, game); Card card = cards.get(target2.getFirstTarget(), game); cards.remove(card); - card.moveToZone(Zone.LIBRARY, game, true); -// player.getLibrary().putOnTop(card, game); + card.moveToZone(Zone.LIBRARY, source.getId(), game, true); target2.clearChosen(); } } if (cards.size() == 1) { Card card = cards.get(cards.iterator().next(), game); - card.moveToZone(Zone.LIBRARY, game, true); -// player.getLibrary().putOnTop(cards.get(cards.iterator().next(), game), game); + card.moveToZone(Zone.LIBRARY, source.getId(), game, true); } return true; } diff --git a/Mage/src/mage/abilities/effects/common/SearchLibraryPutInHandEffect.java b/Mage/src/mage/abilities/effects/common/SearchLibraryPutInHandEffect.java index d89c7aec0b8..7dec267e349 100644 --- a/Mage/src/mage/abilities/effects/common/SearchLibraryPutInHandEffect.java +++ b/Mage/src/mage/abilities/effects/common/SearchLibraryPutInHandEffect.java @@ -66,7 +66,7 @@ public class SearchLibraryPutInHandEffect extends SearchEffect)target.getTargets()) { Card card = player.getLibrary().remove(cardId, game); if (card != null){ - card.moveToZone(Zone.HAND, game, false); + card.moveToZone(Zone.HAND, source.getId(), game, false); } } player.shuffleLibrary(game); diff --git a/Mage/src/mage/abilities/effects/common/SearchLibraryPutOnLibraryEffect.java b/Mage/src/mage/abilities/effects/common/SearchLibraryPutOnLibraryEffect.java index c09b8076206..15697fe22d4 100644 --- a/Mage/src/mage/abilities/effects/common/SearchLibraryPutOnLibraryEffect.java +++ b/Mage/src/mage/abilities/effects/common/SearchLibraryPutOnLibraryEffect.java @@ -72,7 +72,7 @@ public class SearchLibraryPutOnLibraryEffect extends SearchEffect)target.getTargets()) { Card card = player.getLibrary().remove(cardId, game); if (card != null) { - card.moveToZone(Zone.HAND, game, false); + card.moveToZone(Zone.HAND, source.getId(), game, false); revealed.add(card); } } diff --git a/Mage/src/mage/abilities/keyword/CascadeAbility.java b/Mage/src/mage/abilities/keyword/CascadeAbility.java index 720d202ce97..b04cac62948 100644 --- a/Mage/src/mage/abilities/keyword/CascadeAbility.java +++ b/Mage/src/mage/abilities/keyword/CascadeAbility.java @@ -31,6 +31,7 @@ package mage.abilities.keyword; import mage.Constants.CardType; import mage.Constants.Outcome; import mage.Constants.Zone; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.OneShotEffect; @@ -39,6 +40,7 @@ import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.Spell; import mage.players.Player; /** @@ -58,9 +60,12 @@ public class CascadeAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == EventType.SPELL_CAST && event.getTargetId().equals(this.getSourceId()) ) { - trigger(game, event.getPlayerId()); - return true; + if (event.getType() == EventType.SPELL_CAST) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null && spell.getSourceId().equals(this.getSourceId())) { + trigger(game, event.getPlayerId()); + return true; + } } return false; } @@ -96,7 +101,7 @@ class CascadeEffect extends OneShotEffect { card = player.getLibrary().removeFromTop(game); if (card == null) break; - card.moveToExile(exile.getId(), exile.getName(), game); + card.moveToExile(exile.getId(), exile.getName(), source.getId(), game); } while (card.getCardType().contains(CardType.LAND) || card.getManaCost().convertedManaCost() >= sourceCost); if (card != null) { @@ -109,7 +114,7 @@ class CascadeEffect extends OneShotEffect { while (exile.size() > 0) { card = exile.getRandom(game); exile.remove(card.getId()); - card.moveToZone(Zone.LIBRARY, game, false); + card.moveToZone(Zone.LIBRARY, source.getId(), game, false); } return true; diff --git a/Mage/src/mage/cards/Card.java b/Mage/src/mage/cards/Card.java index 00622c4b60c..6839fcda5f2 100644 --- a/Mage/src/mage/cards/Card.java +++ b/Mage/src/mage/cards/Card.java @@ -55,8 +55,8 @@ public interface Card extends MageObject { public String getExpansionSetCode(); public void setExpansionSetCode(String expansionSetCode); - public boolean moveToZone(Zone zone, Game game, boolean flag); - public boolean moveToExile(UUID exileId, String name, Game game); + public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag); + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game); public boolean putOntoBattlefield(Game game, Zone fromZone, UUID controllerId); public void checkTriggers(Zone zone, GameEvent event, Game game); diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java index 1941d8d88fd..e5355efa44e 100644 --- a/Mage/src/mage/cards/CardImpl.java +++ b/Mage/src/mage/cards/CardImpl.java @@ -45,6 +45,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.PermanentCard; +import mage.game.stack.Spell; import mage.util.Logging; import mage.watchers.Watchers; @@ -96,7 +97,7 @@ public abstract class CardImpl> extends MageObjectImpl Class theClass = Class.forName(name); Constructor con = theClass.getConstructor(new Class[]{UUID.class}); Card card = (Card) con.newInstance(new Object[] {null}); - card.setZone(Zone.OUTSIDE); +// card.setZone(Zone.OUTSIDE); return card; } catch (Exception e) { @@ -182,9 +183,10 @@ public abstract class CardImpl> extends MageObjectImpl this.expansionSetCode = expansionSetCode; } - public boolean moveToZone(Zone toZone, UUID controllerId, Game game, boolean flag) { - Zone fromZone = zone; - ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, controllerId, fromZone, toZone); + @Override + public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) { + Zone fromZone = game.getZone(objectId); + ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone); if (!game.replaceEvent(event)) { switch (event.getToZone()) { case GRAVEYARD: @@ -193,6 +195,9 @@ public abstract class CardImpl> extends MageObjectImpl case HAND: game.getPlayer(ownerId).getHand().add(this); break; + case STACK: + game.getStack().push(new Spell(this, this.getSpellAbility().copy(), ownerId)); + break; case EXILED: game.getExile().getPermanentExile().add(this); break; @@ -211,22 +216,17 @@ public abstract class CardImpl> extends MageObjectImpl permanent.setTapped(true); break; } - zone = event.getToZone(); + game.setZone(objectId, event.getToZone()); game.fireEvent(event); - return zone == toZone; + return game.getZone(objectId) == toZone; } return false; } @Override - public boolean moveToZone(Zone toZone, Game game, boolean flag) { - return moveToZone(toZone, ownerId, game, flag); - } - - @Override - public boolean moveToExile(UUID exileId, String name, Game game) { - Zone fromZone = zone; - ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, ownerId, fromZone, Zone.EXILED); + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { + Zone fromZone = game.getZone(objectId); + ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, Zone.EXILED); if (!game.replaceEvent(event)) { if (exileId == null) { game.getExile().getPermanentExile().add(this); @@ -234,8 +234,8 @@ public abstract class CardImpl> extends MageObjectImpl else { game.getExile().createZone(exileId, name).add(this); } - zone = event.getToZone(); - game.fireEvent(new ZoneChangeEvent(this.objectId, ownerId, fromZone, Zone.EXILED)); + game.setZone(objectId, event.getToZone()); + game.fireEvent(event); return true; } return false; @@ -245,7 +245,7 @@ public abstract class CardImpl> extends MageObjectImpl public boolean putOntoBattlefield(Game game, Zone fromZone, UUID controllerId) { PermanentCard permanent = new PermanentCard(this, controllerId); game.getBattlefield().addPermanent(permanent); - zone = Zone.BATTLEFIELD; + game.setZone(objectId, Zone.BATTLEFIELD); permanent.entersBattlefield(game); game.applyEffects(); game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD)); diff --git a/Mage/src/mage/cards/CardsImpl.java b/Mage/src/mage/cards/CardsImpl.java index 6e7e566d543..27c17f1f81c 100644 --- a/Mage/src/mage/cards/CardsImpl.java +++ b/Mage/src/mage/cards/CardsImpl.java @@ -81,8 +81,8 @@ public class CardsImpl extends LinkedHashSet implements Cards, Serializabl @Override public void add(Card card) { this.add(card.getId()); - if (zone != null) - card.setZone(zone); +// if (zone != null) +// card.setZone(zone); } @Override diff --git a/Mage/src/mage/choices/Choice.java b/Mage/src/mage/choices/Choice.java index 3d8c5381a8d..9be4d1d9735 100644 --- a/Mage/src/mage/choices/Choice.java +++ b/Mage/src/mage/choices/Choice.java @@ -40,6 +40,7 @@ public interface Choice { public boolean isRequired(); public void clearChoice(); public String getMessage(); + public void setMessage(String message); public void setChoice(String choice); public Set getChoices(); public void setChoices(Set choices); diff --git a/Mage/src/mage/choices/ChoiceImpl.java b/Mage/src/mage/choices/ChoiceImpl.java index a391881eeb6..eb32181e1a0 100644 --- a/Mage/src/mage/choices/ChoiceImpl.java +++ b/Mage/src/mage/choices/ChoiceImpl.java @@ -78,6 +78,11 @@ public class ChoiceImpl> implements Choice, Serializable return message; } + @Override + public void setMessage(String message) { + this.message = message; + } + @Override public Set getChoices() { return choices; diff --git a/Mage/src/mage/filter/Filter.java b/Mage/src/mage/filter/Filter.java index ec7430e7550..c3e866fe207 100644 --- a/Mage/src/mage/filter/Filter.java +++ b/Mage/src/mage/filter/Filter.java @@ -29,7 +29,6 @@ package mage.filter; import java.io.Serializable; -import java.util.UUID; /** * diff --git a/Mage/src/mage/filter/FilterObject.java b/Mage/src/mage/filter/FilterObject.java index 30658051bc4..ef80f89bfde 100644 --- a/Mage/src/mage/filter/FilterObject.java +++ b/Mage/src/mage/filter/FilterObject.java @@ -63,8 +63,6 @@ public class FilterObject> ex protected List supertype = new ArrayList(); protected ComparisonScope scopeSupertype = ComparisonScope.All; protected boolean notSupertype; - protected Zone zone; - protected boolean notZone; protected int convertedManaCost; protected ComparisonType convertedManaCostComparison; protected int power; @@ -114,8 +112,6 @@ public class FilterObject> ex } this.scopeSupertype = filter.scopeSupertype; this.notSupertype = filter.notSupertype; - this.zone = filter.zone; - this.notZone = filter.notZone; this.convertedManaCost = filter.convertedManaCost; this.convertedManaCostComparison = filter.convertedManaCostComparison; this.power = filter.power; @@ -139,11 +135,6 @@ public class FilterObject> ex return notFilter; } - if (zone != null) { - if (object.getZone().match(zone) == notZone) - return notFilter; - } - if (useColor) { if (scopeColor == ComparisonScope.All) { if (object.getColor().equals(color) == notColor) { @@ -314,12 +305,4 @@ public class FilterObject> ex this.notId = notId; } - public void setZone(Zone zone) { - this.zone = zone; - } - - public void setNotZone(boolean notZone) { - this.notZone = notZone; - } - } diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index 8bd87a0b790..7ecb3b88a28 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -37,6 +37,7 @@ import java.util.Set; import java.util.UUID; import mage.Constants.MultiplayerAttackOption; import mage.Constants.RangeOfInfluence; +import mage.Constants.Zone; import mage.MageItem; import mage.abilities.Ability; import mage.abilities.ActivatedAbility; @@ -46,7 +47,6 @@ import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffects; import mage.cards.Cards; import mage.choices.Choice; -import mage.choices.ChoiceImpl; import mage.game.combat.Combat; import mage.game.events.GameEvent; import mage.game.events.TableEvent; @@ -71,11 +71,14 @@ public interface Game extends MageItem, Serializable { //game data methods public void loadCards(Set cards, UUID ownerId); + public Collection getCards(); public Object getCustomData(); public void setCustomData(Object data); public MageObject getObject(UUID objectId); public Permanent getPermanent(UUID permanentId); public Card getCard(UUID cardId); + public Zone getZone(UUID objectId); + public void setZone(UUID objectId, Zone zone); public void addPlayer(Player player) throws GameException; public Player getPlayer(UUID playerId); public Players getPlayers(); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 2757c932f71..68e52aedcbb 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -164,6 +164,11 @@ public abstract class GameImpl> implements Game, Serializa } } + @Override + public Collection getCards() { + return gameCards.values(); + } + @Override public void addPlayer(Player player) throws GameException { state.addPlayer(player); @@ -189,7 +194,7 @@ public abstract class GameImpl> implements Game, Serializa MageObject object; if (state.getBattlefield().containsPermanent(objectId)) { object = state.getBattlefield().getPermanent(objectId); - object.setZone(Zone.BATTLEFIELD); + state.setZone(objectId, Zone.BATTLEFIELD); return object; } object = getCard(objectId); @@ -197,7 +202,7 @@ public abstract class GameImpl> implements Game, Serializa return object; for (StackObject item: state.getStack()) { if (item.getId().equals(objectId)) { - item.setZone(Zone.STACK); + state.setZone(objectId, Zone.STACK); return item; } } @@ -215,6 +220,16 @@ public abstract class GameImpl> implements Game, Serializa return gameCards.get(cardId); } + @Override + public Zone getZone(UUID objectId) { + return state.getZone(objectId); + } + + @Override + public void setZone(UUID objectId, Zone zone) { + state.setZone(objectId, zone); + } + @Override public GameStates getGameStates() { return gameStates; @@ -404,7 +419,7 @@ public abstract class GameImpl> implements Game, Serializa public void mulligan(UUID playerId) { Player player = getPlayer(playerId); int numCards = player.getHand().size(); - player.getLibrary().addAll(player.getHand().getCards(this)); + player.getLibrary().addAll(player.getHand().getCards(this), this); player.getHand().clear(); player.shuffleLibrary(this); player.drawCards(numCards - 1, this); @@ -546,20 +561,20 @@ public abstract class GameImpl> implements Game, Serializa for (Permanent perm: getBattlefield().getAllActivePermanents(CardType.CREATURE)) { //20091005 - 704.5f if (perm.getToughness().getValue() == 0) { - perm.moveToZone(Zone.GRAVEYARD, this, false); - somethingHappened = true; + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; } //20091005 - 704.5g/704.5h else if (perm.getToughness().getValue() <= perm.getDamage() || perm.isDeathtouched()) { - perm.destroy(null, this, false); - somethingHappened = true; + if (perm.destroy(null, this, false)) + somethingHappened = true; } } //20091005 - 704.5i for (Permanent perm: getBattlefield().getAllActivePermanents(CardType.PLANESWALKER)) { if (perm.getLoyalty().getValue() == 0) { - perm.moveToZone(Zone.GRAVEYARD, this, false); - return true; + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + return true; } } //20091005 - 704.5j, 801.14 @@ -571,7 +586,7 @@ public abstract class GameImpl> implements Game, Serializa filterPlaneswalker.setScopeSubtype(ComparisonScope.Any); if (getBattlefield().count(filterPlaneswalker, planeswalker.getControllerId(), this) > 1) { for (Permanent perm: getBattlefield().getActivePermanents(filterPlaneswalker, planeswalker.getControllerId(), this)) { - perm.moveToZone(Zone.GRAVEYARD, this, false); + perm.moveToZone(Zone.GRAVEYARD, null, this, false); } return true; } @@ -581,18 +596,21 @@ public abstract class GameImpl> implements Game, Serializa //20091005 - 704.5n for (Permanent perm: getBattlefield().getAllActivePermanents(filterAura)) { if (perm.getAttachedTo() == null) { - perm.moveToZone(Zone.GRAVEYARD, this, false); + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; } else { //TODO: handle player auras Permanent attachedTo = getPermanent(perm.getAttachedTo()); if (attachedTo == null) { - perm.moveToZone(Zone.GRAVEYARD, this, false); + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; } else { Filter auraFilter = perm.getSpellAbility().getTargets().get(0).getFilter(); if (!auraFilter.match(attachedTo)) { - perm.moveToZone(Zone.GRAVEYARD, this, false); + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; } } } @@ -604,7 +622,7 @@ public abstract class GameImpl> implements Game, Serializa filterLegendName.getName().add(legend.getName()); if (getBattlefield().count(filterLegendName, legend.getControllerId(), this) > 1) { for (Permanent dupLegend: getBattlefield().getActivePermanents(filterLegendName, legend.getControllerId(), this)) { - dupLegend.moveToZone(Zone.GRAVEYARD, this, false); + dupLegend.moveToZone(Zone.GRAVEYARD, null, this, false); } return true; } @@ -618,8 +636,8 @@ public abstract class GameImpl> implements Game, Serializa perm.attachTo(null); } else if (!creature.getCardType().contains(CardType.CREATURE)) { - creature.removeAttachment(perm.getId(), this); - somethingHappened = true; + if (creature.removeAttachment(perm.getId(), this)) + somethingHappened = true; } } } @@ -630,8 +648,8 @@ public abstract class GameImpl> implements Game, Serializa perm.attachTo(null); } else if (!land.getCardType().contains(CardType.LAND)) { - land.removeAttachment(perm.getId(), this); - somethingHappened = true; + if (land.removeAttachment(perm.getId(), this)) + somethingHappened = true; } } } @@ -643,8 +661,8 @@ public abstract class GameImpl> implements Game, Serializa if (!(attachment.getSubtype().contains("Aura") || attachment.getSubtype().contains("Equipment") || attachment.getSubtype().contains("Fortification"))) { - perm.removeAttachment(id, this); - return true; + if (perm.removeAttachment(id, this)) + return true; } } } diff --git a/Mage/src/mage/game/GameState.java b/Mage/src/mage/game/GameState.java index 69310671d47..7e4f45536d9 100644 --- a/Mage/src/mage/game/GameState.java +++ b/Mage/src/mage/game/GameState.java @@ -88,6 +88,7 @@ public class GameState implements Serializable, Copyable { private TurnMods turnMods; private Watchers watchers; private Map values = new HashMap(); + private Map zones = new HashMap(); public GameState() { players = new Players(); @@ -127,6 +128,9 @@ public class GameState implements Serializable, Copyable { values.put(key, state.values.get(key)); //TODO: might have to change value to Copyable } + for (UUID key: state.zones.keySet()) { + zones.put(key, state.zones.get(key)); + } } @Override @@ -140,11 +144,6 @@ public class GameState implements Serializable, Copyable { } public int getValue() { -// final int prime = 31; -// int result = 1; -// result *= prime + turnNum; -// result *= prime + turn.getPhaseType().toString().hashCode(); - StringBuilder sb = new StringBuilder(1024); sb.append(turnNum).append(turn.getPhaseType()).append(turn.getStepType()).append(activePlayerId).append(priorityPlayerId); @@ -275,12 +274,22 @@ public class GameState implements Serializable, Copyable { Permanent permanent; if (battlefield.containsPermanent(permanentId)) { permanent = battlefield.getPermanent(permanentId); - permanent.setZone(Zone.BATTLEFIELD); + setZone(permanent.getId(), Zone.BATTLEFIELD); return permanent; } return null; } + public Zone getZone(UUID id) { + if (zones.containsKey(id)) + return zones.get(id); + return null; + } + + public void setZone(UUID id, Zone zone) { + zones.put(id, zone); + } + public void restore(GameState state) { this.stack = state.stack; this.effects = state.effects; @@ -288,6 +297,7 @@ public class GameState implements Serializable, Copyable { this.combat = state.combat; this.exile = state.exile; this.battlefield = state.battlefield; + this.zones = state.zones; for (Player copyPlayer: state.players.values()) { Player origPlayer = players.get(copyPlayer.getId()); origPlayer.restore(copyPlayer); diff --git a/Mage/src/mage/game/events/GameEvent.java b/Mage/src/mage/game/events/GameEvent.java index 36f35575f05..d5ed35b85b1 100644 --- a/Mage/src/mage/game/events/GameEvent.java +++ b/Mage/src/mage/game/events/GameEvent.java @@ -75,8 +75,8 @@ public class GameEvent { //player events ZONE_CHANGE, - DRAW_CARD, DREW_CARD, - DISCARD_CARD, DISCARDED_CARD, + DREW_CARD, + DISCARDED_CARD, CYCLE_CARD, CYCLED_CARD, DAMAGE_PLAYER, DAMAGED_PLAYER, COMBAT_DAMAGE_PLAYER, COMBAT_DAMAGED_PLAYER, diff --git a/Mage/src/mage/game/permanent/PermanentCard.java b/Mage/src/mage/game/permanent/PermanentCard.java index afce2ba4fc6..53128a23e7c 100644 --- a/Mage/src/mage/game/permanent/PermanentCard.java +++ b/Mage/src/mage/game/permanent/PermanentCard.java @@ -125,12 +125,12 @@ public class PermanentCard extends PermanentImpl { // } @Override - public boolean moveToZone(Zone toZone, Game game, boolean flag) { - Zone fromZone = zone; - ZoneChangeEvent event = new ZoneChangeEvent(this, controllerId, fromZone, toZone); - if (!game.replaceEvent(event)) { - Player controller = game.getPlayer(controllerId); - if (controller != null && controller.removeFromBattlefield(this, game)) { + public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) { + Zone fromZone = game.getZone(objectId); + Player controller = game.getPlayer(controllerId); + if (controller != null && controller.removeFromBattlefield(this, game)) { + ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, controllerId, fromZone, toZone); + if (!game.replaceEvent(event)) { Card card = game.getCard(objectId); Player owner = game.getPlayer(ownerId); if (owner != null) { @@ -154,9 +154,9 @@ public class PermanentCard extends PermanentImpl { //should never happen break; } - zone = event.getToZone(); + game.setZone(objectId, event.getToZone()); game.fireEvent(event); - return zone == toZone; + return game.getZone(objectId) == toZone; } } } @@ -165,9 +165,23 @@ public class PermanentCard extends PermanentImpl { @Override - public boolean moveToExile(UUID exileId, String name, Game game) { - if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) { - return game.getCard(objectId).moveToExile(exileId, name, game); + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { + Zone fromZone = game.getZone(objectId); + Player controller = game.getPlayer(controllerId); + if (controller != null && controller.removeFromBattlefield(this, game)) { + ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, ownerId, fromZone, Zone.EXILED); + if (!game.replaceEvent(event)) { + Card card = game.getCard(this.objectId); + if (exileId == null) { + game.getExile().getPermanentExile().add(card); + } + else { + game.getExile().createZone(exileId, name).add(card); + } + game.setZone(objectId, event.getToZone()); + game.fireEvent(event); + return true; + } } return false; } diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index ebe889b20c4..6af049fe47d 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -499,12 +499,22 @@ public abstract class PermanentImpl> extends CardImpl } protected void addEffects(Game game) { - for (StaticAbility ability: abilities.getStaticAbilities(Zone.BATTLEFIELD)) { - if (ability.activate(game, false)) { +// for (StaticAbility ability: abilities.getStaticAbilities(Zone.BATTLEFIELD)) { +// if (ability.activate(game, false)) { +// for (Effect effect: ability.getEffects()) { +// if (effect instanceof ContinuousEffect) +// game.addEffect((ContinuousEffect)effect, ability); +// else if (ability instanceof EntersBattlefieldStaticAbility && effect instanceof OneShotEffect) { +// //20100423 - 603.6e +// effect.apply(game, ability); +// } +// } +// } +// } + for (Ability ability: abilities.getStaticAbilities(Zone.BATTLEFIELD)) { + if (ability instanceof EntersBattlefieldStaticAbility) { for (Effect effect: ability.getEffects()) { - if (effect instanceof ContinuousEffect) - game.addEffect((ContinuousEffect)effect, ability); - else if (ability instanceof EntersBattlefieldStaticAbility && effect instanceof OneShotEffect) { + if (effect instanceof OneShotEffect) { //20100423 - 603.6e effect.apply(game, ability); } @@ -519,7 +529,7 @@ public abstract class PermanentImpl> extends CardImpl //TODO: handle noRegen if (!game.replaceEvent(GameEvent.getEvent(EventType.DESTROY_PERMANENT, objectId, sourceId, controllerId, noRegen?1:0))) { if (!this.getAbilities().containsKey(IndestructibleAbility.getInstance().getId())) { - if (moveToZone(Zone.GRAVEYARD, game, false)) { + if (moveToZone(Zone.GRAVEYARD, sourceId, game, false)) { game.fireEvent(GameEvent.getEvent(EventType.DESTROYED_PERMANENT, objectId, sourceId, controllerId)); return true; } @@ -532,7 +542,7 @@ public abstract class PermanentImpl> extends CardImpl public boolean sacrifice(UUID sourceId, Game game) { //20091005 - 701.13 if (!game.replaceEvent(GameEvent.getEvent(EventType.SACRIFICE_PERMANENT, objectId, sourceId, controllerId))) { - if (moveToZone(Zone.GRAVEYARD, game, true)) { + if (moveToZone(Zone.GRAVEYARD, sourceId, game, true)) { game.fireEvent(GameEvent.getEvent(EventType.SACRIFICED_PERMANENT, objectId, sourceId, controllerId)); return true; } diff --git a/Mage/src/mage/game/permanent/PermanentToken.java b/Mage/src/mage/game/permanent/PermanentToken.java index 323e1af5e42..c73099b531a 100644 --- a/Mage/src/mage/game/permanent/PermanentToken.java +++ b/Mage/src/mage/game/permanent/PermanentToken.java @@ -75,7 +75,7 @@ public class PermanentToken extends PermanentImpl { } @Override - public boolean moveToZone(Zone zone, Game game, boolean flag) { + public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag) { if (!game.replaceEvent(new ZoneChangeEvent(this, this.getControllerId(), Zone.BATTLEFIELD, zone))) { if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) { game.fireEvent(new ZoneChangeEvent(this, this.getControllerId(), Zone.BATTLEFIELD, zone)); @@ -86,10 +86,10 @@ public class PermanentToken extends PermanentImpl { } @Override - public boolean moveToExile(UUID exileId, String name, Game game) { - if (!game.replaceEvent(new ZoneChangeEvent(this, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED))) { + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { + if (!game.replaceEvent(new ZoneChangeEvent(this, sourceId, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED))) { if (game.getPlayer(controllerId).removeFromBattlefield(this, game)) { - game.fireEvent(new ZoneChangeEvent(this, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED)); + game.fireEvent(new ZoneChangeEvent(this, sourceId, this.getControllerId(), Zone.BATTLEFIELD, Zone.EXILED)); return true; } } diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 61ff7b757f7..d768bf3102a 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -86,11 +86,11 @@ public class Spell> implements StackObject, Card { if (ability.getEffects().contains(ExileSpellEffect.getInstance())) game.getExile().getPermanentExile().add(card); else - card.moveToZone(Zone.GRAVEYARD, game, false); + card.moveToZone(Zone.GRAVEYARD, ability.getId(), game, false); return result; } //20091005 - 608.2b - counter(game); + counter(null, game); return false; } else if (card.getCardType().contains(CardType.ENCHANTMENT) && card.getSubtype().contains("Aura")) { @@ -101,7 +101,7 @@ public class Spell> implements StackObject, Card { return false; } //20091005 - 608.2b - counter(game); + counter(null, game); return false; } else { @@ -145,8 +145,8 @@ public class Spell> implements StackObject, Card { } @Override - public void counter(Game game) { - card.moveToZone(Zone.GRAVEYARD, game, false); + public void counter(UUID sourceId, Game game) { + card.moveToZone(Zone.GRAVEYARD, sourceId, game, false); } @Override @@ -220,14 +220,6 @@ public class Spell> implements StackObject, Card { return card.getLoyalty(); } - @Override - public Zone getZone() { - return Zone.STACK; - } - - @Override - public void setZone(Zone zone) {} - @Override public UUID getId() { return ability.getId(); @@ -296,12 +288,12 @@ public class Spell> implements StackObject, Card { public void adjustCosts(Ability ability, Game game) {} @Override - public boolean moveToZone(Zone zone, Game game, boolean flag) { + public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public boolean moveToExile(UUID exileId, String name, Game game) { + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { throw new UnsupportedOperationException("Not supported yet."); } diff --git a/Mage/src/mage/game/stack/SpellStack.java b/Mage/src/mage/game/stack/SpellStack.java index 990cf59eb3c..6e23e68798f 100644 --- a/Mage/src/mage/game/stack/SpellStack.java +++ b/Mage/src/mage/game/stack/SpellStack.java @@ -74,7 +74,7 @@ public class SpellStack extends Stack { if (stackObject != null) { if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) { this.remove(stackObject); - stackObject.counter(game); + stackObject.counter(sourceId, game); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, objectId, sourceId, stackObject.getControllerId())); return true; } diff --git a/Mage/src/mage/game/stack/StackAbility.java b/Mage/src/mage/game/stack/StackAbility.java index 4730bedce98..6d46ecd8e01 100644 --- a/Mage/src/mage/game/stack/StackAbility.java +++ b/Mage/src/mage/game/stack/StackAbility.java @@ -42,6 +42,7 @@ import mage.game.*; import java.util.List; import java.util.UUID; import mage.Constants.CardType; +import mage.Constants.EffectType; import mage.Constants.Zone; import mage.MageInt; import mage.ObjectColor; @@ -86,7 +87,7 @@ public class StackAbility implements StackObject, Ability { if (ability.getTargets().stillLegal(ability, game)) { return ability.resolve(game); } - counter(game); + counter(null, game); return false; } @@ -94,7 +95,7 @@ public class StackAbility implements StackObject, Ability { public void reset(Game game) { } @Override - public void counter(Game game) { + public void counter(UUID sourceId, Game game) { //20100716 - 603.8 if (ability instanceof StateTriggeredAbility) { ((StateTriggeredAbility)ability).counter(); @@ -153,12 +154,9 @@ public class StackAbility implements StackObject, Ability { @Override public Zone getZone() { - return Zone.STACK; + return this.ability.getZone(); } - @Override - public void setZone(Zone zone) {} - @Override public UUID getId() { return this.ability.getId(); @@ -184,6 +182,11 @@ public class StackAbility implements StackObject, Ability { return ability.getEffects(); } + @Override + public Effects getEffects(EffectType effectType) { + return ability.getEffects(effectType); + } + @Override public String getRule() { return ability.getRule(); diff --git a/Mage/src/mage/game/stack/StackObject.java b/Mage/src/mage/game/stack/StackObject.java index 365fb64d703..b81d86a7b49 100644 --- a/Mage/src/mage/game/stack/StackObject.java +++ b/Mage/src/mage/game/stack/StackObject.java @@ -40,7 +40,7 @@ public interface StackObject extends MageObject { public UUID getSourceId(); public UUID getControllerId(); public void checkTriggers(GameEvent event, Game game); - public void counter(Game game); + public void counter(UUID sourceId, Game game); @Override public StackObject copy(); } diff --git a/Mage/src/mage/players/Library.java b/Mage/src/mage/players/Library.java index 36121b60118..d0c92ca2b8e 100644 --- a/Mage/src/mage/players/Library.java +++ b/Mage/src/mage/players/Library.java @@ -114,7 +114,7 @@ public class Library implements Serializable { public void putOnTop(Card card, Game game) { if (card.getOwnerId().equals(playerId)) { - card.setZone(Zone.LIBRARY); + game.setZone(card.getId(), Zone.LIBRARY); library.addFirst(card.getId()); } else { @@ -124,7 +124,7 @@ public class Library implements Serializable { public void putOnBottom(Card card, Game game) { if (card.getOwnerId().equals(playerId)) { - card.setZone(Zone.LIBRARY); + game.setZone(card.getId(), Zone.LIBRARY); library.add(card.getId()); } else { @@ -195,9 +195,9 @@ public class Library implements Serializable { } } - public void addAll(Set cards) { + public void addAll(Set cards, Game game) { for (Card card: cards) { - card.setZone(Zone.LIBRARY); + game.setZone(card.getId(), Zone.LIBRARY); library.add(card.getId()); } } diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index 0f85ba8c93c..2955ee1204d 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -128,6 +128,7 @@ public interface Player extends MageItem, Copyable { public abstract void priority(Game game); public abstract boolean choose(Outcome outcome, Target target, Game game); + public abstract boolean choose(Cards cards, TargetCard target, Game game); public abstract boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game); public abstract boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game); public abstract boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 5892044058a..b1477f36ea4 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -70,12 +70,10 @@ import mage.game.Game; import mage.game.combat.CombatGroup; import mage.game.permanent.Permanent; import mage.game.events.GameEvent; -import mage.game.stack.Spell; import mage.game.stack.StackAbility; import mage.game.stack.StackObject; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetDiscard; -import mage.watchers.Watcher; public abstract class PlayerImpl> implements Player, Serializable { @@ -99,6 +97,7 @@ public abstract class PlayerImpl> implements Player, Ser protected boolean left; protected RangeOfInfluence range; protected Set inRange = new HashSet(); + protected Deck deck; @Override public abstract T copy(); @@ -107,13 +106,13 @@ public abstract class PlayerImpl> implements Player, Ser this(UUID.randomUUID()); this.name = name; this.range = range; + this.deck = deck; hand = new CardsImpl(Zone.HAND); graveyard = new CardsImpl(Zone.GRAVEYARD); abilities = new AbilitiesImpl(); counters = new Counters(); manaPool = new ManaPool(); library = new Library(playerId); - library.addAll(deck.getCards()); } protected PlayerImpl(UUID id) { @@ -147,6 +146,7 @@ public abstract class PlayerImpl> implements Player, Ser @Override public void init(Game game) { + library.addAll(deck.getCards(), game); this.hand.clear(); this.graveyard.clear(); this.abilities.clear(); @@ -246,14 +246,14 @@ public abstract class PlayerImpl> implements Player, Ser } protected boolean drawCard(Game game) { - if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DRAW_CARD, null, playerId))) { +// if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DRAW_CARD, null, playerId))) { Card card = getLibrary().removeFromTop(game); if (card != null) { - card.moveToZone(Zone.HAND, game, false); + card.moveToZone(Zone.HAND, null, game, false); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DREW_CARD, card.getId(), playerId)); return true; } - } +// } return false; } @@ -315,15 +315,11 @@ public abstract class PlayerImpl> implements Player, Ser @Override public boolean discard(Card card, Ability source, Game game) { - //20091005 - 701.1 - if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DISCARD_CARD, card.getId(), source==null?null:source.getId(), playerId))) { - removeFromHand(card, game); - if (card.moveToZone(Zone.GRAVEYARD, game, false)) { - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DISCARDED_CARD, card.getId(), source==null?null:source.getId(), playerId)); - return true; - } - } - return false; + //20100716 - 701.7 + removeFromHand(card, game); + card.moveToZone(Zone.GRAVEYARD, source==null?null:source.getId(), game, false); + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DISCARDED_CARD, card.getId(), source==null?null:source.getId(), playerId)); + return true; } @Override @@ -362,12 +358,13 @@ public abstract class PlayerImpl> implements Player, Ser if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, ability.getId(), playerId))) { game.bookmarkState(); removeFromHand(card, game); - game.getStack().push(new Spell(card, ability, playerId)); - if (ability.activate(game, noMana)) { + card.moveToZone(Zone.STACK, ability.getId(), game, false); + Ability spellAbility = game.getStack().getSpell(ability.getId()).getSpellAbility(); + if (spellAbility.activate(game, noMana)) { for (KickerAbility kicker: card.getAbilities().getKickerAbilities()) { kicker.activate(game, false); } - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.SPELL_CAST, ability.getId(), playerId)); + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.SPELL_CAST, spellAbility.getId(), playerId)); game.fireInformEvent(name + " casts " + card.getName()); game.removeLastBookmark(); return true; @@ -460,7 +457,7 @@ public abstract class PlayerImpl> implements Player, Ser result = playManaAbility((ManaAbility)ability.copy(), game); } else if (ability instanceof SpellAbility) { - result = cast((SpellAbility)ability.copy(), game, false); + result = cast((SpellAbility)ability, game, false); } else { result = playAbility((ActivatedAbility)ability.copy(), game); @@ -733,7 +730,7 @@ public abstract class PlayerImpl> implements Player, Ser for (Iterator it = game.getBattlefield().getAllPermanents().iterator(); it.hasNext();) { Permanent perm = it.next(); if (perm.getControllerId().equals(playerId)) { - perm.moveToExile(null, "", game); + perm.moveToExile(null, "", null, game); } } } diff --git a/Mage/src/mage/target/TargetObject.java b/Mage/src/mage/target/TargetObject.java index fb01cb9bb84..b7be81f5fc3 100644 --- a/Mage/src/mage/target/TargetObject.java +++ b/Mage/src/mage/target/TargetObject.java @@ -74,7 +74,7 @@ public abstract class TargetObject> extends TargetImpl @Override public boolean canTarget(UUID id, Game game) { MageObject object = game.getObject(id); - if (object != null && object.getZone().match(zone)) + if (object != null && game.getZone(id).match(zone)) return getFilter().match(object); return false; } diff --git a/Mage/src/mage/target/common/TargetCardInGraveyard.java b/Mage/src/mage/target/common/TargetCardInGraveyard.java index d35db3b3543..ffbddf046f4 100644 --- a/Mage/src/mage/target/common/TargetCardInGraveyard.java +++ b/Mage/src/mage/target/common/TargetCardInGraveyard.java @@ -66,7 +66,7 @@ public class TargetCardInGraveyard extends TargetCard { @Override public boolean canTarget(UUID id, Ability source, Game game) { Card card = game.getCard(id); - if (card != null && card.getZone() == Zone.GRAVEYARD) + if (card != null && game.getZone(card.getId()) == Zone.GRAVEYARD) return filter.match(card); return false; } diff --git a/Mage/src/mage/target/common/TargetCardInLibrary.java b/Mage/src/mage/target/common/TargetCardInLibrary.java index 017cbfb2fd0..02676100f11 100644 --- a/Mage/src/mage/target/common/TargetCardInLibrary.java +++ b/Mage/src/mage/target/common/TargetCardInLibrary.java @@ -70,13 +70,13 @@ public class TargetCardInLibrary extends TargetCard { Player player = game.getPlayer(playerId); while (!isChosen() && !doneChosing()) { chosen = targets.size() >= minNumberOfTargets; - if (!player.chooseTarget(new CardsImpl(Zone.LIBRARY, player.getLibrary().getCards(game)), this, null, game)) { + if (!player.choose(new CardsImpl(Zone.LIBRARY, player.getLibrary().getCards(game)), this, game)) { return chosen; } chosen = targets.size() >= minNumberOfTargets; } while (!doneChosing()) { - if (!player.chooseTarget(new CardsImpl(Zone.LIBRARY, player.getLibrary().getCards(game)), this, null, game)) { + if (!player.choose(new CardsImpl(Zone.LIBRARY, player.getLibrary().getCards(game)), this, game)) { break; } } diff --git a/Mage/src/mage/target/common/TargetCardInYourGraveyard.java b/Mage/src/mage/target/common/TargetCardInYourGraveyard.java index e4697ed3e1a..4c49904e457 100644 --- a/Mage/src/mage/target/common/TargetCardInYourGraveyard.java +++ b/Mage/src/mage/target/common/TargetCardInYourGraveyard.java @@ -66,7 +66,7 @@ public class TargetCardInYourGraveyard extends TargetCard