From ba885fef91c27554516f505fbe3f8601a5633ecf Mon Sep 17 00:00:00 2001
From: LevelX2 <ludwig.hirth@online.de>
Date: Sun, 15 Jun 2014 11:14:08 +0200
Subject: [PATCH] * Ground Seal - Fixed a problem, that cards that need to
 target cards in graveyard caused a game lock, if ground seal was on the
 battlefield.

---
 Mage/src/mage/target/TargetCard.java          | 120 +++++++++++-------
 Mage/src/mage/target/TargetImpl.java          |   4 +-
 Mage/src/mage/target/TargetStackObject.java   |   5 +-
 .../TargetActivatedOrTriggeredAbility.java    |   2 +-
 .../common/TargetCardInYourGraveyard.java     |  15 ++-
 .../target/common/TargetCreatureOrPlayer.java |   4 +-
 6 files changed, 98 insertions(+), 52 deletions(-)

diff --git a/Mage/src/mage/target/TargetCard.java b/Mage/src/mage/target/TargetCard.java
index cb1c9da64c..aa5015f1f9 100644
--- a/Mage/src/mage/target/TargetCard.java
+++ b/Mage/src/mage/target/TargetCard.java
@@ -38,6 +38,7 @@ import mage.players.Player;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.UUID;
+import mage.game.events.GameEvent;
 
 /**
  *
@@ -87,28 +88,53 @@ public class TargetCard extends TargetObject {
      */
     @Override
     public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
+        int possibleTargets = 0;
         for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) {
             Player player = game.getPlayer(playerId);
             if (player != null) {
                 switch (zone) {
                     case HAND:
-                        if (player.getHand().count(filter, sourceId, sourceControllerId, game) >= this.minNumberOfTargets) {
-                            return true;
+                        for (Card card : player.getHand().getCards(filter, game)) {
+                            if (sourceId == null || isNotTarget() || !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.TARGET, card.getId(), sourceId, sourceControllerId))) {
+                                possibleTargets++;
+                                if (possibleTargets >= this.minNumberOfTargets) {
+                                    return true;
+                                }
+                            }
                         }
                         break;
                     case GRAVEYARD:
-                        if (player.getGraveyard().count(filter, sourceId, sourceControllerId, game) >= this.minNumberOfTargets) {
-                            return true;
+                        for (Card card : player.getGraveyard().getCards(filter, game)) {
+                            if (sourceId == null || isNotTarget() || !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.TARGET, card.getId(), sourceId, sourceControllerId))) {
+                                possibleTargets++;
+                                if (possibleTargets >= this.minNumberOfTargets) {
+                                    return true;
+                                }
+                            }
                         }
                         break;
                     case LIBRARY:
-                        if (player.getLibrary().count(filter, game) >= this.minNumberOfTargets) {
-                            return true;
+                        for (Card card : player.getLibrary().getUniqueCards(game)) {
+                            if (sourceId == null || isNotTarget() || !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.TARGET, card.getId(), sourceId, sourceControllerId))) {
+                                if (filter.match(card, game)) {
+                                    possibleTargets++;
+                                    if (possibleTargets >= this.minNumberOfTargets) {
+                                        return true;
+                                    }
+                                }
+                            }
                         }
                         break;
                     case EXILED:
-                        if (game.getExile().getPermanentExile().count(filter, sourceId, sourceControllerId, game) >= this.minNumberOfTargets) {
-                            return true;
+                        for (Card card : game.getExile().getPermanentExile().getCards(game)) {
+                            if (sourceId == null || isNotTarget() || !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.TARGET, card.getId(), sourceId, sourceControllerId))) {
+                                if (filter.match(card, player.getId(), game)) {
+                                    possibleTargets++;
+                                    if (possibleTargets >= this.minNumberOfTargets) {
+                                        return true;
+                                    }
+                                }
+                            }
                         }
                         break;
                 }
@@ -131,11 +157,51 @@ public class TargetCard extends TargetObject {
 
     @Override
     public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
-        return possibleTargets(sourceControllerId, game);
+        Set<UUID> possibleTargets = new HashSet<>();
+        for (UUID playerId : game.getPlayer(sourceControllerId).getInRange()) {
+            Player player = game.getPlayer(playerId);
+            if (player != null) {
+                switch (zone) {
+                    case HAND:
+                        for (Card card : player.getHand().getCards(filter, game)) {
+                            if (sourceId == null || isNotTarget() || !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.TARGET, card.getId(), sourceId, sourceControllerId))) {
+                                possibleTargets.add(card.getId());
+                            }
+                        }
+                        break;
+                    case GRAVEYARD:
+                        for (Card card : player.getGraveyard().getCards(filter, game)) {
+                            if (sourceId == null || isNotTarget() || !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.TARGET, card.getId(), sourceId, sourceControllerId))) {
+                                possibleTargets.add(card.getId());
+                            }
+                        }
+                        break;
+                    case LIBRARY:
+                        for (Card card : player.getLibrary().getUniqueCards(game)) {
+                            if (sourceId == null || isNotTarget() || !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.TARGET, card.getId(), sourceId, sourceControllerId))) {
+                                if (filter.match(card, game)) {
+                                    possibleTargets.add(card.getId());
+                                }
+                            }
+                        }
+                        break;
+                    case EXILED:
+                        for (Card card : game.getExile().getPermanentExile().getCards(game)) {
+                            if (sourceId == null || isNotTarget() || !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.TARGET, card.getId(), sourceId, sourceControllerId))) {
+                                if (filter.match(card, player.getId(), game)) {
+                                    possibleTargets.add(card.getId());
+                                }
+                            }
+                        }
+                        break;
+                }
+            }
+        }
+        return possibleTargets;
     }
 
     public Set<UUID> possibleTargets(UUID sourceControllerId, Cards cards, Game game) {
-        Set<UUID> possibleTargets = new HashSet<UUID>();
+        Set<UUID> possibleTargets = new HashSet<>();
         for (Card card: cards.getCards(filter, game)) {
             possibleTargets.add(card.getId());
         }
@@ -144,39 +210,7 @@ public class TargetCard extends TargetObject {
 
     @Override
     public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
-        Set<UUID> possibleTargets = new HashSet<UUID>();
-        for (UUID playerId : game.getPlayer(sourceControllerId).getInRange()) {
-            Player player = game.getPlayer(playerId);
-            if (player != null) {
-                switch (zone) {
-                    case HAND:
-                        for (Card card : player.getHand().getCards(filter, game)) {
-                            possibleTargets.add(card.getId());
-                        }
-                        break;
-                    case GRAVEYARD:
-                        for (Card card : player.getGraveyard().getCards(filter, game)) {
-                            possibleTargets.add(card.getId());
-                        }
-                        break;
-                    case LIBRARY:
-                        for (Card card : player.getLibrary().getUniqueCards(game)) {
-                            if (filter.match(card, game)) {
-                                possibleTargets.add(card.getId());
-                            }
-                        }
-                        break;
-                    case EXILED:
-                        for (Card card : game.getExile().getPermanentExile().getUniqueCards(game)) {
-                            if (filter.match(card, player.getId(), game)) {
-                                possibleTargets.add(card.getId());
-                            }
-                        }
-                        break;
-                }
-            }
-        }
-        return possibleTargets;
+        return possibleTargets(null, sourceControllerId, game);
     }
 
     public boolean canTarget(UUID id, Cards cards, Game game) {
diff --git a/Mage/src/mage/target/TargetImpl.java b/Mage/src/mage/target/TargetImpl.java
index 18ef3bf515..c115f6861b 100644
--- a/Mage/src/mage/target/TargetImpl.java
+++ b/Mage/src/mage/target/TargetImpl.java
@@ -220,12 +220,12 @@ public abstract class TargetImpl implements Target {
         if (maxNumberOfTargets == 0 || targets.size() < maxNumberOfTargets) {
             if (!targets.containsKey(id)) {
                 if (source != null) {
-                    if (!game.replaceEvent(GameEvent.getEvent(EventType.TARGET, id, source.getId(), source.getControllerId()))) {
+                    if (!game.replaceEvent(GameEvent.getEvent(EventType.TARGET, id, source.getSourceId(), source.getControllerId()))) {
                         targets.put(id, 0);
                         rememberZoneChangeCounter(id, game);
                         chosen = targets.size() >= minNumberOfTargets;
                         if (!skipEvent) {
-                            game.fireEvent(GameEvent.getEvent(EventType.TARGETED, id, source.getId(), source.getControllerId()));
+                            game.fireEvent(GameEvent.getEvent(EventType.TARGETED, id, source.getSourceId(), source.getControllerId()));
                         }
                     }
                 }
diff --git a/Mage/src/mage/target/TargetStackObject.java b/Mage/src/mage/target/TargetStackObject.java
index 064b4807e5..0a8e91a4e9 100644
--- a/Mage/src/mage/target/TargetStackObject.java
+++ b/Mage/src/mage/target/TargetStackObject.java
@@ -96,8 +96,9 @@ public class TargetStackObject extends TargetObject {
         for (StackObject stackObject: game.getStack()) {
             if (game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match(stackObject, game)) {
                 count++;
-                if (count >= this.minNumberOfTargets)
+                if (count >= this.minNumberOfTargets) {
                     return true;
+                }
             }
         }
         return false;
@@ -110,7 +111,7 @@ public class TargetStackObject extends TargetObject {
 
     @Override
     public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
-        Set<UUID> possibleTargets = new HashSet<UUID>();
+        Set<UUID> possibleTargets = new HashSet<>();
         for (StackObject stackObject: game.getStack()) {
             if (game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match(stackObject, game)) {
                 possibleTargets.add(stackObject.getId());
diff --git a/Mage/src/mage/target/common/TargetActivatedOrTriggeredAbility.java b/Mage/src/mage/target/common/TargetActivatedOrTriggeredAbility.java
index d64fc9b461..04f9b48149 100644
--- a/Mage/src/mage/target/common/TargetActivatedOrTriggeredAbility.java
+++ b/Mage/src/mage/target/common/TargetActivatedOrTriggeredAbility.java
@@ -96,7 +96,7 @@ public class TargetActivatedOrTriggeredAbility extends TargetObject {
 
     @Override
     public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
-        Set<UUID> possibleTargets = new HashSet<UUID>();
+        Set<UUID> possibleTargets = new HashSet<>();
         for (StackObject stackObject :  game.getStack()) {
             if (stackObject.getStackAbility() != null && (stackObject.getStackAbility() instanceof ActivatedAbility || stackObject.getStackAbility() instanceof TriggeredAbility) && game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getStackAbility().getControllerId())) {
                 possibleTargets.add(stackObject.getStackAbility().getId());
diff --git a/Mage/src/mage/target/common/TargetCardInYourGraveyard.java b/Mage/src/mage/target/common/TargetCardInYourGraveyard.java
index b70131c375..5553511f69 100644
--- a/Mage/src/mage/target/common/TargetCardInYourGraveyard.java
+++ b/Mage/src/mage/target/common/TargetCardInYourGraveyard.java
@@ -34,6 +34,8 @@ import mage.abilities.Ability;
 import mage.cards.Card;
 import mage.filter.FilterCard;
 import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.players.Player;
 import mage.target.TargetCard;
 
 /**
@@ -101,8 +103,17 @@ public class TargetCardInYourGraveyard extends TargetCard {
     }
     @Override
     public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
-        if (game.getPlayer(sourceControllerId).getGraveyard().count(filter, sourceId, sourceControllerId, game) >= this.minNumberOfTargets) {
-            return true;
+        Player player = game.getPlayer(sourceControllerId);
+        if (player != null) {
+            int possibleTargets = 0;
+            for (Card card : player.getGraveyard().getCards(filter, game)) {
+                if (sourceId == null || isNotTarget() || !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.TARGET, card.getId(), sourceId, sourceControllerId))) {
+                    possibleTargets++;
+                    if (possibleTargets >= this.minNumberOfTargets) {
+                        return true;
+                    }
+                }
+            }
         }
         return false;
     }
diff --git a/Mage/src/mage/target/common/TargetCreatureOrPlayer.java b/Mage/src/mage/target/common/TargetCreatureOrPlayer.java
index 6cda9b0d97..55fe173a99 100644
--- a/Mage/src/mage/target/common/TargetCreatureOrPlayer.java
+++ b/Mage/src/mage/target/common/TargetCreatureOrPlayer.java
@@ -185,7 +185,7 @@ public class TargetCreatureOrPlayer extends TargetImpl {
 
     @Override
     public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
-        Set<UUID> possibleTargets = new HashSet<UUID>();
+        Set<UUID> possibleTargets = new HashSet<>();
         MageObject targetSource = game.getObject(sourceId);
         for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) {
             Player player = game.getPlayer(playerId);
@@ -203,7 +203,7 @@ public class TargetCreatureOrPlayer extends TargetImpl {
 
     @Override
     public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
-        Set<UUID> possibleTargets = new HashSet<UUID>();
+        Set<UUID> possibleTargets = new HashSet<>();
         for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) {
             Player player = game.getPlayer(playerId);
             if (player != null && filter.match(player, game)) {