From 8bd3109c879657f3e391ff1176d74113ba41fe3d Mon Sep 17 00:00:00 2001
From: LevelX2 <ludwig.hirth@online.de>
Date: Thu, 29 May 2014 10:27:52 +0200
Subject: [PATCH] * Fixed some game locking loops if a player concedes while
 resolving an effect (e.g. Scry, Discard). Some changes to game log for info
 about moving cards to library.

---
 .../mage/sets/alarareborn/MaelstromNexus.java |  7 +++++--
 .../journeyintonyx/AjaniMentorOfHeroes.java   |  2 --
 .../src/mage/sets/mirage/PainfulMemories.java |  2 +-
 .../JaceArchitectOfThought.java               |  4 ++--
 .../seventhedition/AgonizingMemories.java     |  3 +--
 Mage.Sets/src/mage/sets/zendikar/Gomazoa.java |  4 ++--
 ...utTopCardOfYourLibraryToGraveyardCost.java |  2 +-
 .../common/LookLibraryControllerEffect.java   |  2 +-
 .../effects/common/ReturnFromExileEffect.java |  2 +-
 .../RevealLibraryPutIntoHandEffect.java       |  2 +-
 .../abilities/effects/common/ScryEffect.java  | 19 +++++++------------
 .../discard/DiscardEachPlayerEffect.java      |  2 +-
 .../abilities/keyword/CascadeAbility.java     | 11 +++++++----
 .../abilities/keyword/HideawayAbility.java    |  2 +-
 .../mage/abilities/keyword/KickerAbility.java |  2 +-
 .../abilities/keyword/ReplicateAbility.java   |  2 +-
 Mage/src/mage/cards/Sets.java                 |  2 +-
 Mage/src/mage/players/Player.java             |  3 ++-
 Mage/src/mage/players/PlayerImpl.java         | 14 +++++++-------
 19 files changed, 43 insertions(+), 44 deletions(-)

diff --git a/Mage.Sets/src/mage/sets/alarareborn/MaelstromNexus.java b/Mage.Sets/src/mage/sets/alarareborn/MaelstromNexus.java
index 748c3d4bb2..22f78ee5d7 100644
--- a/Mage.Sets/src/mage/sets/alarareborn/MaelstromNexus.java
+++ b/Mage.Sets/src/mage/sets/alarareborn/MaelstromNexus.java
@@ -167,6 +167,9 @@ class CascadeEffect extends OneShotEffect<CascadeEffect> {
     public boolean apply(Game game, Ability source) {
         Card card;
         Player player = game.getPlayer(source.getControllerId());
+        if (player == null) {
+            return false;
+        }
         ExileZone exile = game.getExile().createZone(source.getSourceId(), player.getName() + " Cascade");
         Card stackCard = game.getCard(targetPointer.getFirst(game, source));
         if (stackCard == null) {
@@ -179,7 +182,7 @@ class CascadeEffect extends OneShotEffect<CascadeEffect> {
                 break;
             }
                 
-            card.moveToExile(exile.getId(), exile.getName(), source.getId(), game);
+            player.moveCardToExileWithInfo(card, source.getId(), exile.getName(), source.getSourceId(), game, Zone.LIBRARY);
         } while (card.getCardType().contains(CardType.LAND) || card.getManaCost().convertedManaCost() >= sourceCost);
 
         if (card != null) {
@@ -192,7 +195,7 @@ class CascadeEffect extends OneShotEffect<CascadeEffect> {
         while (exile.size() > 0) {
             card = exile.getRandom(game);
             exile.remove(card.getId());
-            card.moveToZone(Zone.LIBRARY, source.getId(), game, false);
+            player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.EXILED, false, false);
         }
 
         return true;
diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/AjaniMentorOfHeroes.java b/Mage.Sets/src/mage/sets/journeyintonyx/AjaniMentorOfHeroes.java
index d0c9bc7835..dc66e7b180 100644
--- a/Mage.Sets/src/mage/sets/journeyintonyx/AjaniMentorOfHeroes.java
+++ b/Mage.Sets/src/mage/sets/journeyintonyx/AjaniMentorOfHeroes.java
@@ -42,12 +42,10 @@ import mage.constants.Rarity;
 import mage.constants.TargetController;
 import mage.constants.Zone;
 import mage.counters.CounterType;
-import mage.filter.Filter;
 import mage.filter.common.FilterCreatureCard;
 import mage.filter.common.FilterCreaturePermanent;
 import mage.filter.predicate.Predicates;
 import mage.filter.predicate.mageobject.CardTypePredicate;
-import mage.filter.predicate.mageobject.PowerPredicate;
 import mage.filter.predicate.mageobject.SubtypePredicate;
 import mage.filter.predicate.permanent.ControllerPredicate;
 import mage.game.Game;
diff --git a/Mage.Sets/src/mage/sets/mirage/PainfulMemories.java b/Mage.Sets/src/mage/sets/mirage/PainfulMemories.java
index e2d6a3f3b8..05fcb32e2f 100644
--- a/Mage.Sets/src/mage/sets/mirage/PainfulMemories.java
+++ b/Mage.Sets/src/mage/sets/mirage/PainfulMemories.java
@@ -98,7 +98,7 @@ class PainfulMemoriesEffect extends OneShotEffect<PainfulMemoriesEffect> {
                 if (you.choose(Outcome.Benefit, targetPlayer.getHand(), target, game)) {
                     Card card = targetPlayer.getHand().get(target.getFirstTarget(), game);
                     if (card != null) {
-                        return targetPlayer.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.HAND, true);
+                        return targetPlayer.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.HAND, true, true);
                     }
                 }
             }
diff --git a/Mage.Sets/src/mage/sets/returntoravnica/JaceArchitectOfThought.java b/Mage.Sets/src/mage/sets/returntoravnica/JaceArchitectOfThought.java
index 4bc6cfcf6e..c15efab1c8 100644
--- a/Mage.Sets/src/mage/sets/returntoravnica/JaceArchitectOfThought.java
+++ b/Mage.Sets/src/mage/sets/returntoravnica/JaceArchitectOfThought.java
@@ -311,13 +311,13 @@ class JaceArchitectOfThoughtEffect2 extends OneShotEffect<JaceArchitectOfThought
                 Card card = cardsToLibrary.get(targetCard.getFirstTarget(), game);
                 if (card != null) {
                     cardsToLibrary.remove(card);
-                    player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.LIBRARY, false);
+                    player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.LIBRARY, false, false);
                 }
                 target.clearChosen();
             }
             if (cardsToLibrary.size() == 1) {
                 Card card = cardsToLibrary.get(cardsToLibrary.iterator().next(), game);
-                player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.LIBRARY, false);
+                player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.LIBRARY, false, false);
             }
             return true;
         }
diff --git a/Mage.Sets/src/mage/sets/seventhedition/AgonizingMemories.java b/Mage.Sets/src/mage/sets/seventhedition/AgonizingMemories.java
index 6be1dc393e..980ceda6aa 100644
--- a/Mage.Sets/src/mage/sets/seventhedition/AgonizingMemories.java
+++ b/Mage.Sets/src/mage/sets/seventhedition/AgonizingMemories.java
@@ -99,14 +99,13 @@ class AgonizingMemoriesEffect extends OneShotEffect<AgonizingMemoriesEffect> {
     }
     
     private void chooseCardInHandAndPutOnTopOfLibrary(Game game, Ability source, Player you, Player targetPlayer) {
-        MageObject sourceObject = game.getObject(source.getSourceId());
         if (targetPlayer.getHand().size() > 0) {
             TargetCard target = new TargetCard(Zone.PICK, new FilterCard("card to put on the top of library (last chosen will be on top)"));
             target.setRequired(true);
             if (you.choose(Outcome.Benefit, targetPlayer.getHand(), target, game)) {
                 Card card = targetPlayer.getHand().get(target.getFirstTarget(), game);
                 if (card != null) {
-                    targetPlayer.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.HAND, true);
+                    targetPlayer.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.HAND, true, false);
                 }
             }
         }
diff --git a/Mage.Sets/src/mage/sets/zendikar/Gomazoa.java b/Mage.Sets/src/mage/sets/zendikar/Gomazoa.java
index 65d5356785..678a73c11a 100644
--- a/Mage.Sets/src/mage/sets/zendikar/Gomazoa.java
+++ b/Mage.Sets/src/mage/sets/zendikar/Gomazoa.java
@@ -110,7 +110,7 @@ class GomazoaEffect extends OneShotEffect<GomazoaEffect> {
             List<UUID> players = new ArrayList<>();
             Permanent gomazoa = game.getPermanent(source.getSourceId());
             if (gomazoa != null) {
-                controller.moveCardToLibraryWithInfo(gomazoa, source.getSourceId(), game, Zone.BATTLEFIELD, true);
+                controller.moveCardToLibraryWithInfo(gomazoa, source.getSourceId(), game, Zone.BATTLEFIELD, true, true);
                 players.add(gomazoa.getOwnerId());
             }
 
@@ -123,7 +123,7 @@ class GomazoaEffect extends OneShotEffect<GomazoaEffect> {
                     players.add(blockedByGomazoa.getOwnerId());
                     Player owner = game.getPlayer(blockedByGomazoa.getOwnerId());
                     if (owner != null) {
-                        owner.moveCardToLibraryWithInfo(blockedByGomazoa, source.getSourceId(), game, Zone.BATTLEFIELD, true);
+                        owner.moveCardToLibraryWithInfo(blockedByGomazoa, source.getSourceId(), game, Zone.BATTLEFIELD, true, true);
                     }
                 }
             }
diff --git a/Mage/src/mage/abilities/costs/common/PutTopCardOfYourLibraryToGraveyardCost.java b/Mage/src/mage/abilities/costs/common/PutTopCardOfYourLibraryToGraveyardCost.java
index c4868044f1..0409e43427 100644
--- a/Mage/src/mage/abilities/costs/common/PutTopCardOfYourLibraryToGraveyardCost.java
+++ b/Mage/src/mage/abilities/costs/common/PutTopCardOfYourLibraryToGraveyardCost.java
@@ -67,7 +67,7 @@ public class PutTopCardOfYourLibraryToGraveyardCost extends CostImpl<PutTopCardO
         if (player != null && player.getLibrary().size() >= numberOfCards) {
             int i = 0;
             paid = true;
-            while (i < numberOfCards) {
+            while (player.isInGame() && i < numberOfCards) {
                 Card card = player.getLibrary().removeFromTop(game);
                 if (card != null) {
                     // all cards must reach the graveyard to pay the costs
diff --git a/Mage/src/mage/abilities/effects/common/LookLibraryControllerEffect.java b/Mage/src/mage/abilities/effects/common/LookLibraryControllerEffect.java
index 0dea2dc95f..882ed8cc42 100644
--- a/Mage/src/mage/abilities/effects/common/LookLibraryControllerEffect.java
+++ b/Mage/src/mage/abilities/effects/common/LookLibraryControllerEffect.java
@@ -165,7 +165,7 @@ public class LookLibraryControllerEffect extends OneShotEffect<LookLibraryContro
             case LIBRARY: 
                 TargetCard target = new TargetCard(Zone.PICK, new FilterCard(this.getPutBackText()));
                 target.setRequired(true);
-                while (cards.size() > 1) {
+                while (player.isInGame() && cards.size() > 1) {
                     player.choose(Outcome.Neutral, cards, target, game);
                     Card card = cards.get(target.getFirstTarget(), game);
                     if (card != null) {
diff --git a/Mage/src/mage/abilities/effects/common/ReturnFromExileEffect.java b/Mage/src/mage/abilities/effects/common/ReturnFromExileEffect.java
index 9c0c1fefd3..f657a615e2 100644
--- a/Mage/src/mage/abilities/effects/common/ReturnFromExileEffect.java
+++ b/Mage/src/mage/abilities/effects/common/ReturnFromExileEffect.java
@@ -102,7 +102,7 @@ public class ReturnFromExileEffect extends OneShotEffect<ReturnFromExileEffect>
                             controller.moveCardToGraveyardWithInfo(card, source.getSourceId(), game, Zone.EXILED);
                             break;
                         case LIBRARY:
-                            controller.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.EXILED, true);
+                            controller.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.EXILED, true, true);
                             break;
                         default:
                             card.moveToZone(zone, source.getSourceId(), game, tapped);
diff --git a/Mage/src/mage/abilities/effects/common/RevealLibraryPutIntoHandEffect.java b/Mage/src/mage/abilities/effects/common/RevealLibraryPutIntoHandEffect.java
index 8626531f07..e9d08be89d 100644
--- a/Mage/src/mage/abilities/effects/common/RevealLibraryPutIntoHandEffect.java
+++ b/Mage/src/mage/abilities/effects/common/RevealLibraryPutIntoHandEffect.java
@@ -98,7 +98,7 @@ public class RevealLibraryPutIntoHandEffect extends OneShotEffect<RevealLibraryP
             }
         }
 
-        while (cards.size() > 1) {
+        while (player.isInGame() && cards.size() > 1) {
             Card card;
             if (anyOrder) {
                 TargetCard target = new TargetCard(Zone.PICK, new FilterCard("card to put on the bottom of your library"));
diff --git a/Mage/src/mage/abilities/effects/common/ScryEffect.java b/Mage/src/mage/abilities/effects/common/ScryEffect.java
index d4b1da613a..afafd87ddd 100644
--- a/Mage/src/mage/abilities/effects/common/ScryEffect.java
+++ b/Mage/src/mage/abilities/effects/common/ScryEffect.java
@@ -28,13 +28,13 @@
 
 package mage.abilities.effects.common;
 
-import mage.constants.Outcome;
-import mage.constants.Zone;
 import mage.abilities.Ability;
 import mage.abilities.effects.OneShotEffect;
 import mage.cards.Card;
 import mage.cards.Cards;
 import mage.cards.CardsImpl;
+import mage.constants.Outcome;
+import mage.constants.Zone;
 import mage.filter.FilterCard;
 import mage.game.Game;
 import mage.game.events.GameEvent;
@@ -81,37 +81,32 @@ public class ScryEffect extends OneShotEffect<ScryEffect> {
             }
             TargetCard target1 = new TargetCard(Zone.LIBRARY, filter1);
             // move cards to the bottom of the library
-            while (cards.size() > 0 && player.choose(Outcome.Detriment, cards, target1, game)) {
+            while (player.isInGame() && cards.size() > 0 && player.choose(Outcome.Detriment, cards, target1, game)) {
                 Card card = cards.get(target1.getFirstTarget(), game);
                 if (card != null) {
                     cards.remove(card);
-                    card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false);
+                    player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.LIBRARY, false, false);
                 }
                 target1.clearChosen();
             }
             // move cards to the top of the library
-            int onBottom = scryNumber - cards.size();
             if (cards.size() > 1) {
                 TargetCard target2 = new TargetCard(Zone.LIBRARY, filter2);
                 target2.setRequired(true);
-                while (cards.size() > 1) {
+                while (player.isInGame() && cards.size() > 1) {
                     player.choose(Outcome.Benefit, cards, target2, game);
                     Card card = cards.get(target2.getFirstTarget(), game);
                     if (card != null) {
                         cards.remove(card);
-                        card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
+                        player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.LIBRARY, true, false);
                     }
                     target2.clearChosen();
                 }
             }
             if (cards.size() == 1) {
                 Card card = cards.get(cards.iterator().next(), game);
-                card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
+                player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.LIBRARY, true, false);
             }
-            game.informPlayers(new StringBuilder(player.getName()).append(" puts ")
-                    .append(onBottom).append(onBottom == 1 ?" card":" cards")
-                    .append(" on the bottom of his or her library (scry ")
-                    .append(scryNumber).append(")").toString());
             game.fireEvent(new GameEvent(GameEvent.EventType.SCRY, source.getControllerId(), source.getSourceId(), source.getControllerId()));
             player.setTopCardRevealed(revealed);
             return true;
diff --git a/Mage/src/mage/abilities/effects/common/discard/DiscardEachPlayerEffect.java b/Mage/src/mage/abilities/effects/common/discard/DiscardEachPlayerEffect.java
index b8b1d020dc..072eeed643 100644
--- a/Mage/src/mage/abilities/effects/common/discard/DiscardEachPlayerEffect.java
+++ b/Mage/src/mage/abilities/effects/common/discard/DiscardEachPlayerEffect.java
@@ -82,7 +82,7 @@ public class DiscardEachPlayerEffect extends OneShotEffect<DiscardEachPlayerEffe
                     int numberOfCardsToDiscard = Math.min(amount.calculate(game, source), player.getHand().size());
                     Cards cards = new CardsImpl();
                     if (randomDiscard) {
-                        while (cards.size() < numberOfCardsToDiscard) {
+                        while (player.isInGame() && cards.size() < numberOfCardsToDiscard) {
                             Card card = player.getHand().getRandom(game);
                             if (!cards.contains(card.getId())) {
                                 cards.add(card);
diff --git a/Mage/src/mage/abilities/keyword/CascadeAbility.java b/Mage/src/mage/abilities/keyword/CascadeAbility.java
index 9de7ef91de..491f3e75c2 100644
--- a/Mage/src/mage/abilities/keyword/CascadeAbility.java
+++ b/Mage/src/mage/abilities/keyword/CascadeAbility.java
@@ -110,15 +110,18 @@ class CascadeEffect extends OneShotEffect<CascadeEffect> {
     public boolean apply(Game game, Ability source) {
         Card card;
         Player player = game.getPlayer(source.getControllerId());
+        if (player == null) {
+            return false;
+        }
         ExileZone exile = game.getExile().createZone(source.getSourceId(), player.getName() + " Cascade");
         int sourceCost = game.getCard(source.getSourceId()).getManaCost().convertedManaCost();
         do {
             card = player.getLibrary().getFromTop(game);
             if (card == null) {
                 break;
-            }                
-            card.moveToExile(exile.getId(), exile.getName(), source.getId(), game);
-        } while (card.getCardType().contains(CardType.LAND) || card.getManaCost().convertedManaCost() >= sourceCost);
+            }
+            player.moveCardToExileWithInfo(card, source.getId(), exile.getName(), source.getSourceId(), game, Zone.LIBRARY);
+        } while (player.isInGame() && card.getCardType().contains(CardType.LAND) || card.getManaCost().convertedManaCost() >= sourceCost);
 
         if (card != null) {
             if (player.chooseUse(outcome, "Use cascade effect on " + card.getName() + "?", game)) {
@@ -130,7 +133,7 @@ class CascadeEffect extends OneShotEffect<CascadeEffect> {
         while (exile.size() > 0) {
             card = exile.getRandom(game);
             exile.remove(card.getId());
-            card.moveToZone(Zone.LIBRARY, source.getId(), game, false);
+            player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.EXILED, false, false);
         }
 
         return true;
diff --git a/Mage/src/mage/abilities/keyword/HideawayAbility.java b/Mage/src/mage/abilities/keyword/HideawayAbility.java
index e9e54af982..27698060ca 100644
--- a/Mage/src/mage/abilities/keyword/HideawayAbility.java
+++ b/Mage/src/mage/abilities/keyword/HideawayAbility.java
@@ -141,7 +141,7 @@ class HideawayExileEffect extends OneShotEffect<HideawayExileEffect> {
         if (cards.size() > 0) {
             TargetCard target2 = new TargetCard(Zone.PICK, filter2);
             target2.setRequired(true);
-            while (cards.size() > 1) {
+            while (player.isInGame() && cards.size() > 1) {
                 player.choose(Outcome.Benefit, cards, target2, game);
                 Card card = cards.get(target2.getFirstTarget(), game);
                 if (card != null) {
diff --git a/Mage/src/mage/abilities/keyword/KickerAbility.java b/Mage/src/mage/abilities/keyword/KickerAbility.java
index b5ce4e9214..84b4a26d4d 100644
--- a/Mage/src/mage/abilities/keyword/KickerAbility.java
+++ b/Mage/src/mage/abilities/keyword/KickerAbility.java
@@ -201,7 +201,7 @@ public class KickerAbility extends StaticAbility<KickerAbility> implements Optio
                 this.resetKicker();
                 for (OptionalAdditionalCost kickerCost: kickerCosts) {
                     boolean again = true;
-                    while (again) {
+                    while (player.isInGame() && again) {
                         String times = "";
                         if (kickerCost.isRepeatable()) {
                             int activated = kickerCost.getActivateCount();
diff --git a/Mage/src/mage/abilities/keyword/ReplicateAbility.java b/Mage/src/mage/abilities/keyword/ReplicateAbility.java
index 3c00d57fd2..86e0ea75a5 100644
--- a/Mage/src/mage/abilities/keyword/ReplicateAbility.java
+++ b/Mage/src/mage/abilities/keyword/ReplicateAbility.java
@@ -114,7 +114,7 @@ public class ReplicateAbility extends StaticAbility<ReplicateAbility> implements
                 this.resetReplicate();
 
                 boolean again = true;
-                while (again) {
+                while (player.isInGame() && again) {
                     String times = "";
                     if (additionalCost.isRepeatable()) {
                         int activated = additionalCost.getActivateCount();
diff --git a/Mage/src/mage/cards/Sets.java b/Mage/src/mage/cards/Sets.java
index cf547560cf..3b894e9347 100644
--- a/Mage/src/mage/cards/Sets.java
+++ b/Mage/src/mage/cards/Sets.java
@@ -104,7 +104,7 @@ public class Sets extends HashMap<String, ExpansionSet> {
 
         int count = 0;
         int tries = 0;
-        List<Card> cardPool = new ArrayList<Card>();
+        List<Card> cardPool = new ArrayList<>();
         while (count < cardsCount) {
             CardInfo cardInfo = cards.get(rnd.nextInt(cards.size()));
             Card card = cardInfo != null ? cardInfo.getCard() : null;
diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java
index fc822b4200..c3b5e4e6b1 100644
--- a/Mage/src/mage/players/Player.java
+++ b/Mage/src/mage/players/Player.java
@@ -439,9 +439,10 @@ public interface Player extends MageItem, Copyable<Player> {
      * @param game
      * @param fromZone if null, this info isn't postet
      * @param toTop to the top of the library else to the bottom
+     * @param withName show the card name in the log
      * @return
      */
-    boolean moveCardToLibraryWithInfo(Card card, UUID sourceId, Game game, Zone fromZone, boolean toTop);
+    boolean moveCardToLibraryWithInfo(Card card, UUID sourceId, Game game, Zone fromZone, boolean toTop, boolean withName);
 
     
     /**
diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java
index 48620159ca..dee922208f 100644
--- a/Mage/src/mage/players/PlayerImpl.java
+++ b/Mage/src/mage/players/PlayerImpl.java
@@ -563,7 +563,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
     public void discardToMax(Game game) {
         if (hand.size() > this.maxHandSize) {
             game.informPlayers(new StringBuilder(getName()).append(" discards down to ").append(this.maxHandSize).append(this.maxHandSize == 1?" hand card":" hand cards").toString());
-            while (hand.size() > this.maxHandSize) {
+            while (isInGame() && hand.size() > this.maxHandSize) {
                 TargetDiscard target = new TargetDiscard(playerId);
                 target.setTargetName(new StringBuilder(" card to discard (").append(hand.size() - this.maxHandSize).append(" in total)").toString());
                 choose(Outcome.Discard, target, null, game);
@@ -607,7 +607,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
             return;
         }
         int numDiscarded = 0;
-        while (numDiscarded < amount) {
+        while (isInGame() && numDiscarded < amount) {
             if (hand.size() == 0) {
                 break;
             }
@@ -713,7 +713,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
             } else {
                 TargetCard target = new TargetCard(Zone.PICK, new FilterCard("card to put on the bottom of your library"));
                 target.setRequired(true);
-                while (cards.size() > 1) {
+                while (isInGame() && cards.size() > 1) {
                     this.choose(Outcome.Neutral, cards, target, game);
                     Card chosenCard = cards.get(target.getFirstTarget(), game);
                     if (chosenCard != null) {
@@ -1130,7 +1130,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
                               filter.add(Predicates.not(new PermanentIdPredicate(permanent.getId())));
                         }
                         // while targets left and there is still allowed to untap
-                        while (leftForUntap.size() > 0 && numberToUntap > 0) {
+                        while (isInGame() && leftForUntap.size() > 0 && numberToUntap > 0) {
                             // player has to select the permanent he wants to untap for this restriction
                             Ability ability = handledEntry.getKey().getValue().iterator().next();
                             if (ability != null) {
@@ -1180,7 +1180,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
                     }
                 }
 
-            } while (playerCanceledSelection);
+            } while (isInGame() && playerCanceledSelection);
 
             // show in log which permanents were selected to untap
             for(Permanent permanent :selectedToUntap) {
@@ -2237,11 +2237,11 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
     }
 
     @Override 
-    public boolean moveCardToLibraryWithInfo(Card card, UUID sourceId, Game game, Zone fromZone, boolean toTop) {
+    public boolean moveCardToLibraryWithInfo(Card card, UUID sourceId, Game game, Zone fromZone, boolean toTop, boolean withName) {
         boolean result = false;
         if (card.moveToZone(Zone.LIBRARY, sourceId, game, toTop)) {
             game.informPlayers(new StringBuilder(this.getName())
-                    .append(" puts ").append(card.getName()).append(" ")
+                    .append(" puts ").append(withName ? card.getName():"a card").append(" ")
                     .append(fromZone != null ? new StringBuilder("from ").append(fromZone.toString().toLowerCase(Locale.ENGLISH)).append(" "):"")
                     .append("to the ").append(toTop ? "top":"bottom").append(" of his or her library").toString());
             result = true;