diff --git a/Mage/src/mage/abilities/common/GainLifeControllerTriggeredAbility.java b/Mage/src/mage/abilities/common/GainLifeControllerTriggeredAbility.java
index f280c3cad1..44632666c8 100644
--- a/Mage/src/mage/abilities/common/GainLifeControllerTriggeredAbility.java
+++ b/Mage/src/mage/abilities/common/GainLifeControllerTriggeredAbility.java
@@ -33,6 +33,7 @@ import mage.abilities.effects.Effect;
 import mage.constants.Zone;
 import mage.game.Game;
 import mage.game.events.GameEvent;
+import mage.target.targetpointer.FixedTarget;
 
 /**
  *
@@ -40,13 +41,20 @@ import mage.game.events.GameEvent;
  */
 
 public class GainLifeControllerTriggeredAbility extends TriggeredAbilityImpl<GainLifeControllerTriggeredAbility> {
+    private boolean setTargetPointer;
 
     public GainLifeControllerTriggeredAbility(Effect effect, boolean optional) {
+        this(effect, optional, false);
+    }
+    
+    public GainLifeControllerTriggeredAbility(Effect effect, boolean optional, boolean setTargetPointer) {
         super(Zone.BATTLEFIELD, effect, optional);
+        this.setTargetPointer = setTargetPointer;
     }
 
     public GainLifeControllerTriggeredAbility(final GainLifeControllerTriggeredAbility ability) {
         super(ability);
+        this.setTargetPointer = ability.setTargetPointer;
     }
 
     @Override
@@ -56,7 +64,16 @@ public class GainLifeControllerTriggeredAbility extends TriggeredAbilityImpl<Gai
 
     @Override
     public boolean checkTrigger(GameEvent event, Game game) {
-        return event.getType() == GameEvent.EventType.GAINED_LIFE && event.getPlayerId().equals(this.getControllerId());
+        if (event.getType() == GameEvent.EventType.GAINED_LIFE && event.getPlayerId().equals(this.getControllerId())) {
+            if (setTargetPointer) {
+                for (Effect effect : this.getEffects()) {
+                        effect.setTargetPointer(new FixedTarget(event.getPlayerId()));
+                        effect.setValue("gainedLife", event.getAmount());
+                }
+                return true;
+            }
+        }
+        return false;
     }
 
     @Override
diff --git a/Mage/src/mage/abilities/effects/common/continious/GainControlTargetEffect.java b/Mage/src/mage/abilities/effects/common/continious/GainControlTargetEffect.java
index d8505ade03..4680330041 100644
--- a/Mage/src/mage/abilities/effects/common/continious/GainControlTargetEffect.java
+++ b/Mage/src/mage/abilities/effects/common/continious/GainControlTargetEffect.java
@@ -45,22 +45,41 @@ import mage.game.permanent.Permanent;
  */
 public class GainControlTargetEffect extends ContinuousEffectImpl<GainControlTargetEffect> {
 
-    private UUID fixedControllerId;
-    private boolean fixedController;
+    private UUID controllingPlayerId;
+    private boolean fixedControl;
 
     public GainControlTargetEffect(Duration duration) {
-        this(duration, false);
+        this(duration, false, null);
     }
 
-    public GainControlTargetEffect(Duration duration, boolean fixedController) {
+    /**
+     *
+     * @param duration
+     * @param fixedControl Controlling player is fixed even if the controller of the ability chnages
+     */
+    public GainControlTargetEffect(Duration duration, boolean fixedControl) {
+        this(duration, fixedControl, null);
+    }
+
+    /**
+     *
+     * @param duration
+     * @param controllingPlayerId Player that controlls the target creature
+     */
+    public GainControlTargetEffect(Duration duration, UUID controllingPlayerId) {
+        this(duration, true, controllingPlayerId);
+
+    }
+    public GainControlTargetEffect(Duration duration, boolean fixedControl, UUID controllingPlayerId) {
         super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
-        this.fixedController = fixedController;
+        this.controllingPlayerId = controllingPlayerId;
+        this.fixedControl = fixedControl;
     }
 
     public GainControlTargetEffect(final GainControlTargetEffect effect) {
         super(effect);
-        this.fixedControllerId = effect.fixedControllerId;
-        this.fixedController = effect.fixedController;
+        this.controllingPlayerId = effect.controllingPlayerId;
+        this.fixedControl = effect.fixedControl;
     }
 
     @Override
@@ -70,8 +89,8 @@ public class GainControlTargetEffect extends ContinuousEffectImpl<GainControlTar
 
     @Override
     public void init(Ability source, Game game) {
-        if (fixedController) {
-            this.fixedControllerId = source.getControllerId();
+        if (this.controllingPlayerId == null && fixedControl) {
+            this.controllingPlayerId = source.getControllerId();
         }
     }
 
@@ -79,18 +98,21 @@ public class GainControlTargetEffect extends ContinuousEffectImpl<GainControlTar
     public boolean apply(Game game, Ability source) {
         Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
         if (permanent != null) {
-            if (fixedController) {
-                return permanent.changeControllerId(fixedControllerId, game);
+            if (controllingPlayerId != null) {
+                return permanent.changeControllerId(controllingPlayerId, game);
             } else {
                 return permanent.changeControllerId(source.getControllerId(), game);
             }
-        
         }
+        this.discard();
         return false;
     }
 
     @Override
     public String getText(Mode mode) {
+        if (!staticText.isEmpty()) {
+            return staticText;
+        }
         return "Gain control of target " + mode.getTargets().get(0).getTargetName() + " " + duration.toString();
     }
 }
diff --git a/Mage/src/mage/game/combat/Combat.java b/Mage/src/mage/game/combat/Combat.java
index 9703399b5b..afa94cb982 100644
--- a/Mage/src/mage/game/combat/Combat.java
+++ b/Mage/src/mage/game/combat/Combat.java
@@ -53,6 +53,7 @@ import mage.game.permanent.Permanent;
 import mage.players.Player;
 import mage.players.PlayerList;
 import mage.target.common.TargetDefender;
+import mage.util.CardUtil;
 import mage.util.Copyable;
 import mage.util.trace.TraceUtil;
 
@@ -70,10 +71,15 @@ public class Combat implements Serializable, Copyable<Combat> {
     protected List<CombatGroup> groups = new ArrayList<CombatGroup>();
     protected Map<UUID, CombatGroup> blockingGroups = new HashMap<UUID, CombatGroup>();
     protected Set<UUID> defenders = new HashSet<UUID>();
+    // how many creatures attack defending player
+    protected Map<UUID, Set<UUID>> numberCreaturesDefenderAttackedBy = new HashMap<UUID, Set<UUID>>();
     protected UUID attackerId; //the player that is attacking
     // <creature that can block, <all attackers that force the creature to block it>>
     protected Map<UUID, Set<UUID>> creaturesForcedToBlockAttackers = new HashMap<UUID, Set<UUID>>();
 
+    // which creature is forced to attack which defender(s). If set is empty, the creature can attack every possible defender
+    private final Map<UUID, Set<UUID>> creaturesForcedToAttack = new HashMap<UUID, Set<UUID>>();
+    private int maxAttackers = Integer.MIN_VALUE;
 
 
     public Combat() {
@@ -138,6 +144,9 @@ public class Combat implements Serializable, Copyable<Combat> {
         defenders.clear();
         attackerId = null;
         creaturesForcedToBlockAttackers.clear();
+        numberCreaturesDefenderAttackedBy.clear();
+        creaturesForcedToAttack.clear();
+        maxAttackers = Integer.MIN_VALUE;
     }
 
     public String getValue() {
@@ -207,27 +216,38 @@ public class Combat implements Serializable, Copyable<Combat> {
     protected void checkAttackRequirements(Player player, Game game) {
         //20101001 - 508.1d
         for (Permanent creature : player.getAvailableAttackers(game)) {
+            boolean mustAttack = false;
+            Set <UUID> defendersForcedToAttack = new HashSet<UUID>();
             for (Map.Entry entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
                 RequirementEffect effect = (RequirementEffect)entry.getKey();
                 if (effect.mustAttack(game)) {
+                    mustAttack = true;
                     for (Ability ability: (HashSet<Ability>)entry.getValue()) {
                         UUID defenderId = effect.mustAttackDefender(ability, game);
-                        if (defenderId == null) {
-                            if (defenders.size() == 1) {
-                                player.declareAttacker(creature.getId(), defenders.iterator().next(), game);
-                            } else {
-                                TargetDefender target = new TargetDefender(defenders, creature.getId());
-                                target.setRequired(true);
-                                if (player.chooseTarget(Outcome.Damage, target, null, game)) {
-                                    player.declareAttacker(creature.getId(), target.getFirstTarget(), game);
-                                }
-                            }
-                        } else {
-                            player.declareAttacker(creature.getId(), defenderId, game);
+                        if(defenderId != null) {
+                            defendersForcedToAttack.add(defenderId);
                         }
+                        break;
                     }
                 }
             }
+            if (mustAttack) {
+                creaturesForcedToAttack.put(creature.getId(),defendersForcedToAttack);
+                if (defendersForcedToAttack.isEmpty()) {
+                    if (defenders.size() == 1) {
+                        player.declareAttacker(creature.getId(), defenders.iterator().next(), game);
+                    } else {
+                        TargetDefender target = new TargetDefender(defenders, creature.getId());
+                        target.setRequired(true);
+                        if (player.chooseTarget(Outcome.Damage, target, null, game)) {
+                            player.declareAttacker(creature.getId(), target.getFirstTarget(), game);
+                        }
+                    }
+                } else {
+                    player.declareAttacker(creature.getId(), defendersForcedToAttack.iterator().next(), game);
+                }                
+            }
+
         }
     }
 
@@ -300,35 +320,42 @@ public class Combat implements Serializable, Copyable<Combat> {
                 game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, defenderId, defenderId));
 
                 // add info about attacker blocked by blocker to the game log
+                boolean shownDefendingPlayer = false;
                 for (CombatGroup group :this.getGroups()) {
-                    StringBuilder sb = new StringBuilder();
-                    for(UUID attackingCreatureId : group.getAttackers()) {
-                        Permanent attackingCreature = game.getPermanent(attackingCreatureId);
-                        if (attackingCreature != null) {
-                            sb.append(attackingCreature.getName()).append(" (");
-                            sb.append(attackingCreature.getPower().getValue()).append("/").append(attackingCreature.getToughness().getValue()).append(") ");
-                        } else {
-                            // creature left battlefield
-                            attackingCreature = (Permanent) game.getLastKnownInformation(attackingCreatureId, Zone.BATTLEFIELD);
+                    if (group.defendingPlayerId.equals(defenderId)) {
+                        if (!shownDefendingPlayer && defender != null) {
+                            game.informPlayers(new StringBuilder("Attacked player: ").append(defender.getName()).toString());
+                            shownDefendingPlayer = true;
+                        }
+                        StringBuilder sb = new StringBuilder();
+                        for(UUID attackingCreatureId : group.getAttackers()) {
+                            Permanent attackingCreature = game.getPermanent(attackingCreatureId);
                             if (attackingCreature != null) {
-                                sb.append(attackingCreature.getName()).append(" [left battlefield)] ");
+                                sb.append(attackingCreature.getName()).append(" (");
+                                sb.append(attackingCreature.getPower().getValue()).append("/").append(attackingCreature.getToughness().getValue()).append(") ");
+                            } else {
+                                // creature left battlefield
+                                attackingCreature = (Permanent) game.getLastKnownInformation(attackingCreatureId, Zone.BATTLEFIELD);
+                                if (attackingCreature != null) {
+                                    sb.append(attackingCreature.getName()).append(" [left battlefield)] ");
+                                }
                             }
                         }
-                    }
-                    if (group.getBlockers().size() > 0) {
-                        sb.append("blocked by ");
-                        for(UUID blockingCreatureId : group.getBlockers()) {
-                            Permanent blockingCreature = game.getPermanent(blockingCreatureId);
-                            if (blockingCreature != null) {
-                                sb.append(blockingCreature.getName()).append(" (");
-                                sb.append(blockingCreature.getPower().getValue()).append("/").append(blockingCreature.getToughness().getValue()).append(") ");
+                        if (group.getBlockers().size() > 0) {
+                            sb.append("blocked by ");
+                            for(UUID blockingCreatureId : group.getBlockers()) {
+                                Permanent blockingCreature = game.getPermanent(blockingCreatureId);
+                                if (blockingCreature != null) {
+                                    sb.append(blockingCreature.getName()).append(" (");
+                                    sb.append(blockingCreature.getPower().getValue()).append("/").append(blockingCreature.getToughness().getValue()).append(") ");
+                                }
                             }
-                        }
 
-                    } else{
-                        sb.append("unblocked");
+                        } else{
+                            sb.append("unblocked");
+                        }
+                        game.informPlayers(sb.toString());
                     }
-                    game.informPlayers(sb.toString());
                 }
 
             }
@@ -647,17 +674,38 @@ public class Combat implements Serializable, Copyable<Combat> {
     }
 
     private void addDefender(UUID defenderId, Game game) {
-        defenders.add(defenderId);
-        for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filterPlaneswalker, defenderId, game)) {
-            defenders.add(permanent.getId());
+        if (!defenders.contains(defenderId)) {
+            if (maxAttackers < Integer.MAX_VALUE) {
+                Player defendingPlayer = game.getPlayer(defenderId);
+                if (defendingPlayer != null) {
+                    if (defendingPlayer.getMaxAttackedBy() == Integer.MAX_VALUE) {
+                        maxAttackers = Integer.MAX_VALUE;
+                    } else {
+                        if (maxAttackers == Integer.MIN_VALUE) {
+                            maxAttackers = defendingPlayer.getMaxAttackedBy();
+                        } else {
+                            maxAttackers += defendingPlayer.getMaxAttackedBy();
+                        }
+                    }
+                }
+            }
+            defenders.add(defenderId);
+            for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filterPlaneswalker, defenderId, game)) {
+                defenders.add(permanent.getId());
+            }
         }
     }
 
-    public void declareAttacker(UUID attackerId, UUID defenderId, Game game) {
+    public boolean declareAttacker(UUID attackerId, UUID defenderId, Game game) {
         if (!defenders.contains(defenderId)) {
-            return;
+            return false;
         }
         Permanent defender = game.getPermanent(defenderId);
+        // Check if defending player can be attacked with another creature
+        if (!canDefenderBeAttacked(attackerId, defenderId, game)) {
+            return false;
+        }
+
         CombatGroup newGroup = new CombatGroup(defenderId, defender != null, defender != null ? defender.getControllerId(): defenderId);
         newGroup.attackers.add(attackerId);
         Permanent attacker = game.getPermanent(attackerId);
@@ -666,6 +714,39 @@ public class Combat implements Serializable, Copyable<Combat> {
         }
         attacker.setAttacking(true);
         groups.add(newGroup);
+        return true;
+    }
+
+    public boolean canDefenderBeAttacked(UUID attackerId, UUID defenderId, Game game) {
+        Permanent defender = game.getPermanent(defenderId);
+        // Check if defending player can be attacked with another creature
+        if (defender != null) {
+            // a planeswalker is attacked, there exits no restriction yet for attacking planeswalker
+            return true;
+        }
+        Player defendingPlayer = game.getPlayer(defenderId);
+        if (defendingPlayer == null) {
+            return false;
+        }
+        Set<UUID> defenderAttackedBy;
+        if (numberCreaturesDefenderAttackedBy.containsKey(defendingPlayer.getId())) {
+            defenderAttackedBy = numberCreaturesDefenderAttackedBy.get(defendingPlayer.getId());
+        } else {
+            defenderAttackedBy = new HashSet<UUID>();
+            numberCreaturesDefenderAttackedBy.put(defendingPlayer.getId(), defenderAttackedBy);
+        }
+        if (defenderAttackedBy.size() >= defendingPlayer.getMaxAttackedBy()) {
+            Player attackingPlayer = game.getPlayer(game.getControllerId(attackerId));
+            if (attackingPlayer != null) {
+                game.informPlayer(attackingPlayer, new StringBuilder("No more than ")
+                        .append(CardUtil.numberToText(defendingPlayer.getMaxAttackedBy()))
+                        .append(" creatures can attack ")
+                        .append(defendingPlayer.getName()).toString());
+            }
+            return false;
+        }
+        defenderAttackedBy.add(attackerId);
+        return true;
     }
 
     // add blocking group for creatures that block more than one creature
@@ -757,10 +838,7 @@ public class Combat implements Serializable, Copyable<Combat> {
     }
 
     public boolean noAttackers() {
-        if (groups.isEmpty() || getAttackers().isEmpty()) {
-            return true;
-        }
-        return false;
+        return groups.isEmpty() || getAttackers().isEmpty();
     }
 
     public boolean isAttacked(UUID defenderId, Game game) {
@@ -845,6 +923,9 @@ public class Combat implements Serializable, Copyable<Combat> {
             if (group.attackers.contains(attackerId)) {
                 group.attackers.remove(attackerId);
                 group.attackerOrder.remove(attackerId);
+                for (Set<UUID> attackingCreatures : numberCreaturesDefenderAttackedBy.values()) {
+                    attackingCreatures.remove(attackerId);
+                }
                 Permanent creature = game.getPermanent(attackerId);
                 if (creature != null) {
                     creature.setAttacking(false);
@@ -878,6 +959,15 @@ public class Combat implements Serializable, Copyable<Combat> {
         return attackerId;
     }
 
+    public Map<UUID, Set<UUID>> getCreaturesForcedToAttack() {
+        return creaturesForcedToAttack;
+    }
+
+    public int getMaxAttackers() {
+        return maxAttackers;
+    }
+
+
     @Override
     public Combat copy() {
         return new Combat(this);
diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java
index 8de3200beb..75513deb61 100644
--- a/Mage/src/mage/players/Player.java
+++ b/Mage/src/mage/players/Player.java
@@ -102,6 +102,8 @@ public interface Player extends MageItem, Copyable<Player> {
     void setLandsPerTurn(int landsPerTurn);
     int getMaxHandSize();
     void setMaxHandSize(int maxHandSize);
+    int getMaxAttackedBy();
+    void setMaxAttackedBy(int maxAttackedBy);
     boolean isPassed();
     boolean isEmptyDraw();
     void pass(Game game);
diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java
index f1b010a418..b74f08d073 100644
--- a/Mage/src/mage/players/PlayerImpl.java
+++ b/Mage/src/mage/players/PlayerImpl.java
@@ -139,6 +139,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
     protected int landsPlayed;
     protected int landsPerTurn = 1;
     protected int maxHandSize = 7;
+    protected int maxAttackedBy = Integer.MAX_VALUE;
     protected ManaPool manaPool;
     protected boolean passed;
     protected boolean passedTurn;
@@ -219,6 +220,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
         this.landsPlayed = player.landsPlayed;
         this.landsPerTurn = player.landsPerTurn;
         this.maxHandSize = player.maxHandSize;
+        this.maxAttackedBy = player.maxAttackedBy;
         this.manaPool = player.manaPool.copy();
         this.turns = player.turns;
 
@@ -269,6 +271,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
         this.landsPlayed = player.getLandsPlayed();
         this.landsPerTurn = player.getLandsPerTurn();
         this.maxHandSize = player.getMaxHandSize();
+        this.maxAttackedBy = player.getMaxAttackedBy();
         this.manaPool = player.getManaPool().copy();
         this.turns = player.getTurns();
 
@@ -345,6 +348,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
         this.abilities.clear();
         this.landsPerTurn = 1;
         this.maxHandSize = 7;
+        this.maxAttackedBy = Integer.MAX_VALUE;
         this.canGainLife = true;
         this.canLoseLife = true;
         this.canPayLifeCost = true;
@@ -1386,6 +1390,16 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
         this.maxHandSize = maxHandSize;
     }
 
+    @Override
+    public void setMaxAttackedBy(int maxAttackedBy) {
+        this.maxAttackedBy = maxAttackedBy;
+    }
+
+    @Override
+    public int getMaxAttackedBy() {
+        return maxAttackedBy;
+    }
+
     @Override
     public void setResponseString(String responseString) {}
 
@@ -1604,6 +1618,8 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
     }
     
     /**
+     * @param game
+     * @param appliedEffects
      *
      * @return true if player won the toss
      */
diff --git a/Mage/src/mage/target/Target.java b/Mage/src/mage/target/Target.java
index b5b7ea92de..25061549ec 100644
--- a/Mage/src/mage/target/Target.java
+++ b/Mage/src/mage/target/Target.java
@@ -50,9 +50,10 @@ public interface Target extends Serializable {
     void clearChosen();
     boolean isNotTarget();
 
-    // controlls if it will be checked, if the target can be targeted from source
-    // true = check for protection
-    // false = do not check for protection
+    /**
+     * controlls if it will be checked, if the target can be targeted from source
+     * @param notTarget true = check for protection, false = do not check for protection
+     */
     void setNotTarget(boolean notTarget);
 
     // methods for targets