diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 7614a0737a7..9b49a7b2313 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -35,6 +35,7 @@ import java.util.Map; import java.util.Set; import java.util.UUID; +import mage.Constants; import mage.Constants.Outcome; import mage.Constants.RangeOfInfluence; import mage.Constants.TargetController; @@ -351,6 +352,11 @@ public class HumanPlayer extends PlayerImpl { break; case GRAVEYARD: useableAbilities = getUseableAbilities(object.getAbilities().getActivatedAbilities(Zone.GRAVEYARD), game); + playAsThoughInYourHand(game, object, useableAbilities); + break; + case LIBRARY: + useableAbilities = getUseableAbilities(object.getAbilities().getActivatedAbilities(Zone.LIBRARY), game); + playAsThoughInYourHand(game, object, useableAbilities); break; } if (useableAbilities != null && useableAbilities.size() > 0) { @@ -361,6 +367,15 @@ public class HumanPlayer extends PlayerImpl { } } + // not sure it is the best to implement such stuff this way + private void playAsThoughInYourHand(Game game, MageObject object, Map useableAbilities) { + if (game.getContinuousEffects().asThough(object.getId(), Constants.AsThoughEffectType.CAST, game)) { + for (Map.Entry entry : getUseableAbilities(object.getAbilities().getActivatedAbilities(Zone.HAND), game).entrySet()) { + useableAbilities.put(entry.getKey(), entry.getValue()); + } + } + } + @Override public TriggeredAbility chooseTriggeredAbility(TriggeredAbilities abilities, Game game) { game.getState().setPriorityPlayerId(getId()); diff --git a/Mage.Server/plugins/mage-player-ai-ma.jar b/Mage.Server/plugins/mage-player-ai-ma.jar index 3662240a460..847bef09a16 100644 Binary files a/Mage.Server/plugins/mage-player-ai-ma.jar and b/Mage.Server/plugins/mage-player-ai-ma.jar differ diff --git a/Mage.Server/plugins/mage-player-ai.jar b/Mage.Server/plugins/mage-player-ai.jar index dc176a0c093..21077f24fc5 100644 Binary files a/Mage.Server/plugins/mage-player-ai.jar and b/Mage.Server/plugins/mage-player-ai.jar differ diff --git a/Mage.Server/plugins/mage-player-aiminimax.jar b/Mage.Server/plugins/mage-player-aiminimax.jar index e731a156d9b..f2b225362ae 100644 Binary files a/Mage.Server/plugins/mage-player-aiminimax.jar and b/Mage.Server/plugins/mage-player-aiminimax.jar differ diff --git a/Mage.Server/plugins/mage-player-human.jar b/Mage.Server/plugins/mage-player-human.jar index de5629a4475..3bbbda04793 100644 Binary files a/Mage.Server/plugins/mage-player-human.jar and b/Mage.Server/plugins/mage-player-human.jar differ diff --git a/Mage/src/mage/abilities/effects/common/continious/PlayTheTopCardEffect.java b/Mage/src/mage/abilities/effects/common/continious/PlayTheTopCardEffect.java new file mode 100644 index 00000000000..aa8b43cde19 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/continious/PlayTheTopCardEffect.java @@ -0,0 +1,81 @@ +/* + * Copyright 2011 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.abilities.effects.common.continious; + +import mage.abilities.Ability; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.cards.Card; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +import static mage.Constants.*; + +/** + * @author nantuko + */ +public class PlayTheTopCardEffect extends AsThoughEffectImpl { + + private FilterCard filter; + + public PlayTheTopCardEffect(FilterCard filter) { + super(AsThoughEffectType.CAST, Duration.WhileOnBattlefield, Outcome.Benefit); + this.filter = filter; + staticText = "You may play the top card of your library if it's a " + filter.getMessage(); + } + + public PlayTheTopCardEffect(final PlayTheTopCardEffect effect) { + super(effect); + this.filter = effect.filter; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public PlayTheTopCardEffect copy() { + return new PlayTheTopCardEffect(this); + } + + @Override + public boolean applies(UUID sourceId, Ability source, Game game) { + Card card = game.getCard(sourceId); + if (card != null && filter.match(card)) { + Player player = game.getPlayer(card.getOwnerId()); + if (player != null && card.equals(player.getLibrary().getFromTop(game))) { + return true; + } + } + return false; + } + +} \ No newline at end of file diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java index 4ff64b602d3..ac2ee672127 100644 --- a/Mage/src/mage/cards/CardImpl.java +++ b/Mage/src/mage/cards/CardImpl.java @@ -278,6 +278,9 @@ public abstract class CardImpl> extends MageObjectImpl case GRAVEYARD: game.getPlayer(ownerId).removeFromGraveyard(this, game); break; + case LIBRARY: + game.getPlayer(ownerId).removeFromLibrary(this, game); + break; default: //logger.warning("moveToZone, not fully implemented: from="+event.getFromZone() + ", to="+event.getToZone()); } diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index d31cd6d921a..2c8fbcc1319 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -103,6 +103,7 @@ public abstract class PlayerImpl> implements Player, Ser protected boolean isGameUnderControl = true; protected UUID turnController; protected Set playersUnderYourControl = new HashSet(); + protected boolean topCardRevealed = false; @Override public abstract T copy(); @@ -440,7 +441,20 @@ public abstract class PlayerImpl> implements Player, Ser if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, ability.getId(), ability.getSourceId(), playerId))) { int bookmark = game.bookmarkState(); card.cast(game, game.getZone(card.getId()), ability, playerId); - removeFromHand(card, game); + + Zone zone = game.getZone(card.getId()); + switch (zone) { + case HAND: + removeFromHand(card, game); + break; + case LIBRARY: + removeFromLibrary(card, game); + break; + case GRAVEYARD: + removeFromGraveyard(card, game); + break; + } + Ability spellAbility = game.getStack().getSpell(ability.getId()).getSpellAbility(); if (spellAbility.activate(game, noMana)) { for (KickerAbility kicker: card.getAbilities().getKickerAbilities()) { @@ -462,8 +476,20 @@ public abstract class PlayerImpl> implements Player, Ser //20091005 - 305.1 if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, card.getId(), playerId))) { int bookmark = game.bookmarkState(); - removeFromHand(card, game); - if (card.putOntoBattlefield(game, Zone.HAND, null, playerId)) { + Zone zone = game.getZone(card.getId()); + switch (zone) { + case HAND: + removeFromHand(card, game); + break; + case LIBRARY: + removeFromLibrary(card, game); + break; + case GRAVEYARD: + removeFromGraveyard(card, game); + break; + } + + if (card.putOntoBattlefield(game, zone, null, playerId)) { landsPlayed++; game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LAND_PLAYED, card.getId(), playerId)); game.fireInformEvent(name + " plays " + card.getName()); @@ -531,7 +557,11 @@ public abstract class PlayerImpl> implements Player, Ser return true; } else if (ability instanceof PlayLandAbility) { - result = playLand(hand.get(ability.getSourceId(), game), game); + Card card = hand.get(ability.getSourceId(), game); + if (card == null) { + card = game.getCard(ability.getSourceId()); + } + result = playLand(card, game); } else if (ability instanceof SpecialAction) { result = specialAction((SpecialAction)ability.copy(), game); @@ -1121,4 +1151,14 @@ public abstract class PlayerImpl> implements Player, Ser public void setTestMode(boolean value) { this.isTestMode = value; } + + @Override + public boolean isTopCardRevealed() { + return topCardRevealed; + } + + @Override + public void setTopCardRevealed(boolean topCardRevealed) { + this.topCardRevealed = topCardRevealed; + } }