diff --git a/Mage.Server.Plugins/Mage.Game.CommanderDuel/src/mage/game/CommanderDuel.java b/Mage.Server.Plugins/Mage.Game.CommanderDuel/src/mage/game/CommanderDuel.java index 2b5515a54ac..cb063489aa0 100644 --- a/Mage.Server.Plugins/Mage.Game.CommanderDuel/src/mage/game/CommanderDuel.java +++ b/Mage.Server.Plugins/Mage.Game.CommanderDuel/src/mage/game/CommanderDuel.java @@ -28,36 +28,12 @@ package mage.game; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.common.EmptyEffect; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.continious.CommanderReplacementEffect; -import mage.abilities.effects.common.cost.CommanderCostModification; -import mage.cards.Card; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.MultiplayerAttackOption; -import mage.constants.Outcome; -import mage.constants.PhaseStep; import mage.constants.RangeOfInfluence; -import mage.constants.Zone; -import mage.filter.FilterCard; import mage.game.match.MatchType; -import mage.game.turn.TurnMod; -import mage.players.Player; -import mage.target.common.TargetCardInHand; -import mage.watchers.Watcher; -import mage.watchers.common.CommanderCombatDamageWatcher; -public class CommanderDuel extends GameImpl { - - private final Map mulliganedCards = new HashMap(); - +public class CommanderDuel extends GameCommanderImpl { + public CommanderDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans) { super(attackOption, range, freeMulligans); } @@ -76,159 +52,9 @@ public class CommanderDuel extends GameImpl { return 2; } - // MTG Rules 20121001 - // 903.7. Once the starting player has been determined, each player sets his or her life total to 40 and - // draws a hand of seven cards. - @Override - public int getLife() { - return 40; - } - - @Override - protected void init(UUID choosingPlayerId, GameOptions gameOptions) { - super.init(choosingPlayerId, gameOptions); - Ability ability = new SimpleStaticAbility(Zone.COMMAND, new EmptyEffect("Commander effects")); - //Move commender to commande zone - for (UUID playerId: state.getPlayerList(startingPlayerId)) { - Player player = getPlayer(playerId); - if (player != null){ - if (player.getSideboard().size() > 0){ - Card commander = getCard((UUID)player.getSideboard().toArray()[0]); - if (commander != null) { - player.setCommanderId(commander.getId()); - commander.moveToZone(Zone.COMMAND, null, this, true); - ability.addEffect(new CommanderReplacementEffect(commander.getId())); - ability.addEffect(new CommanderCostModification(commander.getId())); - getState().setValue(commander.getId() + "_castCount", new Integer(0)); - getState().getWatchers().add(new CommanderCombatDamageWatcher(commander.getId())); - } - } - } - - } - this.getState().addAbility(ability, this.getId(), null); - state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW)); - } - - - //20130711 - /*903.8. The Commander variant uses an alternate mulligan rule. - * Each time a player takes a mulligan, rather than shuffling his or her entire hand of cards into his or her library, that player exiles any number of cards from his or her hand face down. - * Then the player draws a number of cards equal to one less than the number of cards he or she exiled this way. - * That player may look at all cards exiled this way while taking mulligans. - * Once a player keeps an opening hand, that player shuffles all cards he or she exiled this way into his or her library. - * */ - //TODO implement may look at exile cards - @Override - public void mulligan(UUID playerId) { - Player player = getPlayer(playerId); - TargetCardInHand target = new TargetCardInHand(1, player.getHand().size(), new FilterCard("card to mulligan")); - target.setNotTarget(true); - //target.setRequired(true); - if(player.choose(Outcome.Exile, player.getHand(), target, this)){ - int numCards = target.getTargets().size(); - for(UUID uuid : target.getTargets()){ - Card card = player.getHand().get(uuid, this); - if(card != null){ - if(!mulliganedCards.containsKey(playerId)){ - mulliganedCards.put(playerId, new CardsImpl()); - } - card.setFaceDown(true); - card.moveToExile(null, "", null, this); - mulliganedCards.get(playerId).add(card); - } - } - int deduction = 1; - if (freeMulligans > 0) { - if (usedFreeMulligans != null && usedFreeMulligans.containsKey(player.getId())) { - int used = usedFreeMulligans.get(player.getId()).intValue(); - if (used < freeMulligans ) { - deduction = 0; - usedFreeMulligans.put(player.getId(), new Integer(used+1)); - } - } else { - deduction = 0;{ - - } - usedFreeMulligans.put(player.getId(), new Integer(1)); - } - } - player.drawCards(numCards - deduction, this); - fireInformEvent(new StringBuilder(player.getName()) - .append(" mulligans ") - .append(numCards) - .append(numCards == 1? " card":" cards") - .append(deduction == 0 ? " for free and draws ":" down to ") - .append(Integer.toString(player.getHand().size())) - .append(player.getHand().size() <= 1? " card":" cards").toString()); - } - } - - @Override - public void endMulligan(UUID playerId){ - //return cards to - Player player = getPlayer(playerId); - if(player != null && mulliganedCards.containsKey(playerId)){ - for(Card card : mulliganedCards.get(playerId).getCards(this)){ - if(card != null){ - card.setFaceDown(false); - card.moveToZone(Zone.LIBRARY, null, this, false); - } - } - if(mulliganedCards.get(playerId).size() > 0){ - player.shuffleLibrary(this); - } - } - } - - /* 20130711 - *903.14a A player that’s been dealt 21 or more combat damage by the same commander - * over the course of the game loses the game. (This is a state-based action. See rule 704.) - * - */ - @Override - protected boolean checkStateBasedActions() { - for(Watcher watcher : getState().getWatchers().values()){ - if(watcher instanceof CommanderCombatDamageWatcher){ - CommanderCombatDamageWatcher damageWatcher = (CommanderCombatDamageWatcher)watcher; - for(UUID playerUUID : damageWatcher.getDamageToPlayer().keySet()){ - Player player = getPlayer(playerUUID); - if(player != null && damageWatcher.getDamageToPlayer().get(playerUUID) >= 21){ - player.lost(this); - } - } - } - } - return super.checkStateBasedActions(); - } - - - - @Override - public void quit(UUID playerId) { - super.quit(playerId); - } - - @Override - public Set getOpponents(UUID playerId) { - Set opponents = new HashSet(); - for (UUID opponentId: this.getPlayer(playerId).getInRange()) { - if (!opponentId.equals(playerId)) { - opponents.add(opponentId); - } - } - return opponents; - } - - @Override - public void leave(UUID playerId) { - super.leave(playerId); - } - @Override public CommanderDuel copy() { return new CommanderDuel(this); } - } diff --git a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml new file mode 100644 index 00000000000..acd42b6ecef --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + + org.mage + mage-server-plugins + 1.2.0 + + + mage-game-commanderfreeforall + jar + Mage Game Commander Free For All + + + + ${project.groupId} + mage + ${project.version} + + + + + src + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.6 + 1.6 + + + + maven-resources-plugin + + UTF-8 + + + + + + mage-game-freeforall + + + + + diff --git a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAll.java b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAll.java new file mode 100644 index 00000000000..1abd447f035 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAll.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game; + +import mage.constants.MultiplayerAttackOption; +import mage.constants.RangeOfInfluence; +import mage.game.match.MatchType; + +/** + * + * @author LevelX2 + */ +public class CommanderFreeForAll extends GameCommanderImpl { + + private int numPlayers; + + public CommanderFreeForAll(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans) { + super(attackOption, range, freeMulligans); + } + + public CommanderFreeForAll(final CommanderFreeForAll game) { + super(game); + this.numPlayers = game.numPlayers; + } + + @Override + public MatchType getGameType() { + return new CommanderFreeForAllType(); + } + + @Override + public int getNumPlayers() { + return numPlayers; + } + + public void setNumPlayers(int numPlayers) { + this.numPlayers = numPlayers; + } + + @Override + public CommanderFreeForAll copy() { + return new CommanderFreeForAll(this); + } + +} diff --git a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAllMatch.java b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAllMatch.java new file mode 100644 index 00000000000..261ad6ecfc2 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAllMatch.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game; + +import mage.game.match.MatchImpl; +import mage.game.match.MatchOptions; + +/** + * + * @author LevelX2 + */ +public class CommanderFreeForAllMatch extends MatchImpl { + + public CommanderFreeForAllMatch(MatchOptions options) { + super(options); + } + + @Override + public void startGame() throws GameException { + CommanderFreeForAll game = new CommanderFreeForAll(options.getAttackOption(), options.getRange(), options.getFreeMulligans()); + game.setStartMessage(this.createGameStartMessage()); + initGame(game); + games.add(game); + } + +} diff --git a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAllType.java b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAllType.java new file mode 100644 index 00000000000..b71d11dc5f5 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAllType.java @@ -0,0 +1,57 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game; + +import mage.game.match.MatchType; + + +/** + * + * @author LevelX2 + */ +public class CommanderFreeForAllType extends MatchType { + + public CommanderFreeForAllType() { + this.name = "Commander Free For All"; + this.maxPlayers = 10; + this.minPlayers = 3; + this.numTeams = 0; + this.useAttackOption = true; + this.useRange = true; + } + + protected CommanderFreeForAllType(final CommanderFreeForAllType matchType) { + super(matchType); + } + + @Override + public CommanderFreeForAllType copy() { + return new CommanderFreeForAllType(this); + } +} diff --git a/Mage.Server.Plugins/pom.xml b/Mage.Server.Plugins/pom.xml index e9c1ca09152..56e8e52b9f1 100644 --- a/Mage.Server.Plugins/pom.xml +++ b/Mage.Server.Plugins/pom.xml @@ -17,7 +17,8 @@ Mage.Deck.Constructed Mage.Deck.Limited - Mage.Game.CommanderDuel + Mage.Game.CommanderDuel + Mage.Game.CommanderFreeForAll Mage.Game.FreeForAll Mage.Game.TwoPlayerDuel Mage.Player.AI diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml index c20474563c2..e202f839a23 100644 --- a/Mage.Server/config/config.xml +++ b/Mage.Server/config/config.xml @@ -22,6 +22,7 @@ + diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml index 76dbefcce07..3b7d51735fb 100644 --- a/Mage.Server/pom.xml +++ b/Mage.Server/pom.xml @@ -69,6 +69,12 @@ ${project.version} runtime + + ${project.groupId} + mage-game-commanderfreeforall + ${project.version} + runtime + ${project.groupId} mage-game-freeforall diff --git a/Mage.Server/release/config/config.xml b/Mage.Server/release/config/config.xml index 1a75e62f9cd..61e13f824d1 100644 --- a/Mage.Server/release/config/config.xml +++ b/Mage.Server/release/config/config.xml @@ -11,6 +11,7 @@ + diff --git a/Mage.Sets/src/mage/sets/fifthedition/EvilEyeOfOrmsByGore.java b/Mage.Sets/src/mage/sets/fifthedition/EvilEyeOfOrmsByGore.java index febfb2947d5..28d2fcd1456 100644 --- a/Mage.Sets/src/mage/sets/fifthedition/EvilEyeOfOrmsByGore.java +++ b/Mage.Sets/src/mage/sets/fifthedition/EvilEyeOfOrmsByGore.java @@ -125,4 +125,4 @@ class EvilEyeOfOrmsByGoreEffect extends ReplacementEffectImpl { } else if (mode.getTargets().get(0).getNumberOfTargets() == 1) { sb.append("Destroy target ").append(mode.getTargets().get(0).getTargetName()); } else { - sb.append("Destroy ").append(mode.getTargets().get(0).getNumberOfTargets()).append(" target ").append(mode.getTargets().get(0).getTargetName()); + sb.append("Destroy ").append(CardUtil.numberToText(mode.getTargets().get(0).getNumberOfTargets())).append(" target ").append(mode.getTargets().get(0).getTargetName()); } if (noRegen) { sb.append(". It can't be regenerated"); diff --git a/Mage/src/mage/abilities/effects/common/continious/CommanderReplacementEffect.java b/Mage/src/mage/abilities/effects/common/continious/CommanderReplacementEffect.java index a5e4c12884e..93a6c6961f8 100644 --- a/Mage/src/mage/abilities/effects/common/continious/CommanderReplacementEffect.java +++ b/Mage/src/mage/abilities/effects/common/continious/CommanderReplacementEffect.java @@ -28,6 +28,7 @@ package mage.abilities.effects.common.continious; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.ReplacementEffectImpl; import mage.cards.Card; @@ -39,6 +40,7 @@ import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.watchers.common.CommanderCombatDamageWatcher; /** * @@ -83,15 +85,18 @@ public class CommanderReplacementEffect extends ReplacementEffectImpl { + + private final Map mulliganedCards = new HashMap(); + + public GameCommanderImpl(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans) { + super(attackOption, range, freeMulligans); + } + + public GameCommanderImpl(final GameCommanderImpl game) { + super(game); + } + + // MTG Rules 20121001 + // 903.7. Once the starting player has been determined, each player sets his or her life total to 40 and + // draws a hand of seven cards. + @Override + public int getLife() { + return 40; + } + + @Override + protected void init(UUID choosingPlayerId, GameOptions gameOptions) { + super.init(choosingPlayerId, gameOptions); + Ability ability = new SimpleStaticAbility(Zone.COMMAND, new EmptyEffect("Commander effects")); + //Move commander to command zone + for (UUID playerId: state.getPlayerList(startingPlayerId)) { + Player player = getPlayer(playerId); + if (player != null){ + if (player.getSideboard().size() > 0){ + Card commander = getCard((UUID)player.getSideboard().toArray()[0]); + if (commander != null) { + player.setCommanderId(commander.getId()); + commander.moveToZone(Zone.COMMAND, null, this, true); + ability.addEffect(new CommanderReplacementEffect(commander.getId())); + ability.addEffect(new CommanderCostModification(commander.getId())); + getState().setValue(commander.getId() + "_castCount", new Integer(0)); + CommanderCombatDamageWatcher watcher = new CommanderCombatDamageWatcher(commander.getId()); + getState().getWatchers().add(watcher); + watcher.addCardInfoToCommander(this); + } + } + } + + } + this.getState().addAbility(ability, this.getId(), null); + state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW)); + } + + + //20130711 + /*903.8. The Commander variant uses an alternate mulligan rule. + * Each time a player takes a mulligan, rather than shuffling his or her entire hand of cards into his or her library, that player exiles any number of cards from his or her hand face down. + * Then the player draws a number of cards equal to one less than the number of cards he or she exiled this way. + * That player may look at all cards exiled this way while taking mulligans. + * Once a player keeps an opening hand, that player shuffles all cards he or she exiled this way into his or her library. + * */ + //TODO implement may look at exile cards + @Override + public void mulligan(UUID playerId) { + Player player = getPlayer(playerId); + TargetCardInHand target = new TargetCardInHand(1, player.getHand().size(), new FilterCard("card to mulligan")); + target.setNotTarget(true); + //target.setRequired(true); + if(player.choose(Outcome.Exile, player.getHand(), target, this)){ + int numCards = target.getTargets().size(); + for(UUID uuid : target.getTargets()){ + Card card = player.getHand().get(uuid, this); + if(card != null){ + if(!mulliganedCards.containsKey(playerId)){ + mulliganedCards.put(playerId, new CardsImpl()); + } + card.setFaceDown(true); + card.moveToExile(null, "", null, this); + mulliganedCards.get(playerId).add(card); + } + } + int deduction = 1; + if (freeMulligans > 0) { + if (usedFreeMulligans != null && usedFreeMulligans.containsKey(player.getId())) { + int used = usedFreeMulligans.get(player.getId()).intValue(); + if (used < freeMulligans ) { + deduction = 0; + usedFreeMulligans.put(player.getId(), new Integer(used+1)); + } + } else { + deduction = 0;{ + + } + usedFreeMulligans.put(player.getId(), new Integer(1)); + } + } + player.drawCards(numCards - deduction, this); + fireInformEvent(new StringBuilder(player.getName()) + .append(" mulligans ") + .append(numCards) + .append(numCards == 1? " card":" cards") + .append(deduction == 0 ? " for free and draws ":" down to ") + .append(Integer.toString(player.getHand().size())) + .append(player.getHand().size() <= 1? " card":" cards").toString()); + } + } + + @Override + public void endMulligan(UUID playerId){ + //return cards to + Player player = getPlayer(playerId); + if(player != null && mulliganedCards.containsKey(playerId)){ + for(Card card : mulliganedCards.get(playerId).getCards(this)){ + if(card != null){ + card.setFaceDown(false); + card.moveToZone(Zone.LIBRARY, null, this, false); + } + } + if(mulliganedCards.get(playerId).size() > 0){ + player.shuffleLibrary(this); + } + } + } + + /* 20130711 + *903.14a A player that’s been dealt 21 or more combat damage by the same commander + * over the course of the game loses the game. (This is a state-based action. See rule 704.) + * + */ + @Override + protected boolean checkStateBasedActions() { + for(Watcher watcher : getState().getWatchers().values()){ + if(watcher instanceof CommanderCombatDamageWatcher){ + CommanderCombatDamageWatcher damageWatcher = (CommanderCombatDamageWatcher)watcher; + for(UUID playerUUID : damageWatcher.getDamageToPlayer().keySet()){ + Player player = getPlayer(playerUUID); + if(player != null && damageWatcher.getDamageToPlayer().get(playerUUID) >= 21){ + player.lost(this); + } + } + } + } + return super.checkStateBasedActions(); + } + + + + @Override + public void quit(UUID playerId) { + super.quit(playerId); + } + + @Override + public Set getOpponents(UUID playerId) { + Set opponents = new HashSet(); + for (UUID opponentId: this.getPlayer(playerId).getInRange()) { + if (!opponentId.equals(playerId)) { + opponents.add(opponentId); + } + } + return opponents; + } + + @Override + public void leave(UUID playerId) { + super.leave(playerId); + } + +} diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 5f9906e5b14..d23459516f3 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -51,7 +51,6 @@ import mage.abilities.Ability; import mage.abilities.ActivatedAbility; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.TriggeredAbility; -import mage.abilities.common.CastCommanderAbility; import mage.abilities.common.ChancellorAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffects; diff --git a/Mage/src/mage/watchers/common/CommanderCombatDamageWatcher.java b/Mage/src/mage/watchers/common/CommanderCombatDamageWatcher.java index 8cd1ec259d6..d44de7b6161 100644 --- a/Mage/src/mage/watchers/common/CommanderCombatDamageWatcher.java +++ b/Mage/src/mage/watchers/common/CommanderCombatDamageWatcher.java @@ -31,11 +31,13 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; import mage.MageObject; +import mage.cards.Card; import mage.constants.WatcherScope; import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; import mage.players.Player; import mage.watchers.WatcherImpl; @@ -43,9 +45,6 @@ import mage.watchers.WatcherImpl; *903.14a A player that’s been dealt 21 or more combat damage by the same commander * over the course of the game loses the game. (This is a state-based action. See rule 704.) * - */ - -/** * * @author Plopman */ @@ -74,20 +73,57 @@ public class CommanderCombatDamageWatcher extends WatcherImplCommander"); + Integer castCount = (Integer)game.getState().getValue(sourceId + "_castCount"); + if (castCount != null) { + sb.append(" was ").append(castCount).append(castCount.intValue() == 1 ? " time":" times").append(" casted from the command zone."); + } + this.addInfo(object, "Commander",sb.toString()); + for (Map.Entry entry : damageToPlayer.entrySet()) { + Player damagedPlayer = game.getPlayer(entry.getKey()); + sb.setLength(0); + sb.append("Commander did ").append(entry.getValue()).append(" combat damage to player ").append(damagedPlayer.getName()).append("."); + this.addInfo(object, new StringBuilder("Commander").append(entry.getKey()).toString(),sb.toString()); + } + } + } + + private void addInfo(MageObject object, String key, String value) { + if (object instanceof Card) { + ((Card) object).addInfo(key, value); + } else if (object instanceof Permanent) { + ((Permanent) object).addInfo(key, value); + } } public Map getDamageToPlayer() {