* returned UUID of used THOUGHT AS effect instead of boolean.

This commit is contained in:
LevelX2 2018-04-21 22:32:45 +02:00
parent 968b10bd79
commit 92793327f3
19 changed files with 351 additions and 318 deletions

View file

@ -108,16 +108,16 @@ public class DeckGeneratorDialog {
mainPanel.add(formatSetText, c);
// Format/set dropdown with search button
JPanel setPanel = new JPanel();
JPanel setPanel = new JPanel();
setPanel.setLayout(new javax.swing.BoxLayout(setPanel, javax.swing.BoxLayout.LINE_AXIS));
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 1;
c.gridy = 1;
c.ipadx = 30;
c.insets = new Insets(5, 10, 0, 10);
c.weightx = 0.80;
c.weightx = 0.80;
mainPanel.add(setPanel, c);
cbSets = new JComboBox<>(ConstructedFormats.getTypes());
cbSets.setSelectedIndex(0);
cbSets.setAlignmentX(0.0F);
@ -127,13 +127,14 @@ public class DeckGeneratorDialog {
if (prefSet != null) {
cbSets.setSelectedItem(prefSet);
}
JButton btn = new JButton();
btn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/search_32.png")));
btn.setToolTipText(FastSearchUtil.DEFAULT_EXPANSION_TOOLTIP_MESSAGE);
btn.setAlignmentX(1.0F);
btn.setPreferredSize(new java.awt.Dimension(32, 32));
btn.setAlignmentX(1.0F);
btn.setPreferredSize(new java.awt.Dimension(32, 32));
btn.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
FastSearchUtil.showFastSearchForStringComboBox(cbSets, FastSearchUtil.DEFAULT_EXPANSION_SEARCH_MESSAGE);
}

View file

@ -1243,7 +1243,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
protected boolean playManaHandling(Ability ability, ManaCost unpaid, Game game) {
// log.info("paying for " + unpaid.getText());
boolean spendAnyMana = game.getContinuousEffects().asThough(ability.getSourceId(), AsThoughEffectType.SPEND_OTHER_MANA, ability, ability.getControllerId(), game);
UUID spendAnyManaId = game.getContinuousEffects().asThough(ability.getSourceId(), AsThoughEffectType.SPEND_OTHER_MANA, ability, ability.getControllerId(), game);
ManaCost cost;
List<MageObject> producers;
if (unpaid instanceof ManaCosts) {
@ -1285,7 +1285,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
if (cost instanceof ColoredManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || spendAnyMana) {
if (cost.testPay(netMana) || spendAnyManaId != null) {
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1297,7 +1297,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
if (cost instanceof SnowManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || spendAnyMana) {
if (cost.testPay(netMana) || spendAnyManaId != null) {
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1309,7 +1309,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
if (cost instanceof HybridManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || spendAnyMana) {
if (cost.testPay(netMana) || spendAnyManaId != null) {
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1321,7 +1321,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
if (cost instanceof MonoHybridManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || spendAnyMana) {
if (cost.testPay(netMana) || spendAnyManaId != null) {
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1333,7 +1333,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
if (cost instanceof ColorlessManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || spendAnyMana) {
if (cost.testPay(netMana) || spendAnyManaId != null) {
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1345,7 +1345,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
if (cost instanceof GenericManaCost) {
for (Mana netMana : manaAbility.getNetMana(game)) {
if (cost.testPay(netMana) || spendAnyMana) {
if (cost.testPay(netMana) || spendAnyManaId != null) {
if (activateAbility(manaAbility, game)) {
return true;
}
@ -1356,7 +1356,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
// pay phyrexian life costs
if (cost instanceof PhyrexianManaCost) {
if (cost.pay(null, game, null, playerId, false, null) || spendAnyMana) {
if (cost.pay(null, game, null, playerId, false, null) || spendAnyManaId != null) {
return true;
}
}

View file

@ -29,6 +29,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@ -46,7 +47,7 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent;
import mage.target.Target;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
@ -76,8 +77,8 @@ public class AdarkarValkyrie extends CardImpl {
this.addAbility(VigilanceAbility.getInstance());
// {T}: When target creature other than Adarkar Valkyrie dies this turn, return that card to the battlefield under your control.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AdarkarValkyrieEffect(), new TapSourceCost());
Target target = new TargetCreaturePermanent(filter);
ability.addTarget(target);
ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability);
}
@ -109,25 +110,28 @@ class AdarkarValkyrieEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
DelayedTriggeredAbility delayedAbility = new AdarkarValkyrieDelayedTriggeredAbility(getTargetPointer().getFixedTarget(game, source));
game.addDelayedTriggeredAbility(delayedAbility, source);
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) {
DelayedTriggeredAbility delayedAbility = new AdarkarValkyrieDelayedTriggeredAbility(new MageObjectReference(permanent, game));
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
return false;
}
}
class AdarkarValkyrieDelayedTriggeredAbility extends DelayedTriggeredAbility {
protected FixedTarget fixedTarget;
protected MageObjectReference mor;
public AdarkarValkyrieDelayedTriggeredAbility(FixedTarget fixedTarget) {
public AdarkarValkyrieDelayedTriggeredAbility(MageObjectReference mor) {
super(new ReturnToBattlefieldUnderYourControlTargetEffect(), Duration.EndOfTurn);
this.getEffects().get(0).setTargetPointer(fixedTarget);
this.fixedTarget = fixedTarget;
this.mor = mor;
}
public AdarkarValkyrieDelayedTriggeredAbility(final AdarkarValkyrieDelayedTriggeredAbility ability) {
super(ability);
this.fixedTarget = ability.fixedTarget;
this.mor = ability.mor;
}
@Override
@ -142,10 +146,11 @@ class AdarkarValkyrieDelayedTriggeredAbility extends DelayedTriggeredAbility {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (((ZoneChangeEvent) event).isDiesEvent()) {
if (fixedTarget.getFirst(game, this).equals(event.getTargetId())) {
return true;
}
if (((ZoneChangeEvent) event).isDiesEvent()
&& mor.refersTo(((ZoneChangeEvent) event).getTarget(), game)) {
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
return true;
}
return false;
}

View file

@ -1,230 +1,240 @@
/*
* 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.cards.m;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.watchers.Watcher;
/**
*
* @author LevelX2
*/
public class MuldrothaTheGravetide extends CardImpl {
public MuldrothaTheGravetide(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{G}{U}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.AVATAR);
this.power = new MageInt(6);
this.toughness = new MageInt(6);
// During each of your turns, you may play up to one permanent card of each permanent type from your graveyard.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MuldrothaTheGravetideCastFromGraveyardEffect()), new MuldrothaTheGravetideWatcher());
}
public MuldrothaTheGravetide(final MuldrothaTheGravetide card) {
super(card);
}
@Override
public MuldrothaTheGravetide copy() {
return new MuldrothaTheGravetide(this);
}
}
class MuldrothaTheGravetideCastFromGraveyardEffect extends AsThoughEffectImpl {
public MuldrothaTheGravetideCastFromGraveyardEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "During each of your turns, you may play up to one permanent card of each permanent type from your graveyard. "
+ "<i>(If a card has multiple permanent types, choose one as you play it.)</i>";
}
public MuldrothaTheGravetideCastFromGraveyardEffect(final MuldrothaTheGravetideCastFromGraveyardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public MuldrothaTheGravetideCastFromGraveyardEffect copy() {
return new MuldrothaTheGravetideCastFromGraveyardEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (source.getControllerId().equals(affectedControllerId) && Zone.GRAVEYARD.equals(game.getState().getZone(objectId))) {
MuldrothaTheGravetideWatcher watcher = (MuldrothaTheGravetideWatcher) game.getState().getWatchers().get(MuldrothaTheGravetideWatcher.class.getSimpleName());
MageObject mageObject = game.getObject(objectId);
if (mageObject != null && watcher != null) {
for (CardType cardType : mageObject.getCardType()) {
if (cardType.isPermanentType()) {
if (!watcher.permanentTypePlayedFromGraveyard(affectedControllerId, cardType)) {
return true;
}
}
}
}
}
return false;
}
}
class MuldrothaTheGravetideWatcher extends Watcher {
final HashMap<UUID, Set<CardType>> playerPlayedPermanentTypes = new HashMap<>(); // player that played permanent types from graveyard
private Zone fromZone;
public MuldrothaTheGravetideWatcher() {
super(MuldrothaTheGravetideWatcher.class.getSimpleName(), WatcherScope.GAME);
}
public MuldrothaTheGravetideWatcher(final MuldrothaTheGravetideWatcher watcher) {
super(watcher);
playerPlayedPermanentTypes.putAll(watcher.playerPlayedPermanentTypes);
}
@Override
public MuldrothaTheGravetideWatcher copy() {
return new MuldrothaTheGravetideWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.PLAY_LAND) {
fromZone = game.getState().getZone(event.getTargetId()); // Remember the Zone the land came from
}
if (event.getType() == GameEvent.EventType.LAND_PLAYED && fromZone.equals(Zone.GRAVEYARD)) {
addPermanentTypes(game.getPermanentOrLKIBattlefield(event.getTargetId()), game);
}
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
Spell spell = (Spell) game.getObject(event.getTargetId());
if (spell.getFromZone().equals(Zone.GRAVEYARD)) {
addPermanentTypes(spell, game);
}
}
}
private void addPermanentTypes(Card mageObject, Game game) {
if (mageObject != null) {
UUID playerId = null;
if (mageObject instanceof Spell) {
playerId = ((Spell) mageObject).getControllerId();
} else if (mageObject instanceof Permanent) {
playerId = ((Permanent) mageObject).getControllerId();
}
if (playerId != null) {
Set<CardType> permanentTypes = playerPlayedPermanentTypes.get(playerId);
if (permanentTypes == null) {
permanentTypes = EnumSet.noneOf(CardType.class);
playerPlayedPermanentTypes.put(playerId, permanentTypes);
}
Set<CardType> typesNotCast = EnumSet.noneOf(CardType.class);
for (CardType cardType : mageObject.getCardType()) {
if (cardType.isPermanentType()) {
if (!permanentTypes.contains(cardType)) {
typesNotCast.add(cardType);
}
}
}
if (typesNotCast.size() <= 1) {
permanentTypes.addAll(typesNotCast);
} else {
Player player = game.getPlayer(playerId);
if (player != null) {
Choice typeChoice = new ChoiceImpl(true);
typeChoice.setMessage("Choose permanent type you consume for casting from graveyard.");
for (CardType cardType : typesNotCast) {
typeChoice.getChoices().add(cardType.toString());
}
if (player.choose(Outcome.Detriment, typeChoice, game)) {
String typeName = typeChoice.getChoice();
CardType chosenType = null;
for (CardType cardType : CardType.values()) {
if (cardType.toString().equals(typeName)) {
chosenType = cardType;
break;
}
}
if (chosenType != null) {
permanentTypes.add(chosenType);
}
}
}
}
}
}
}
@Override
public void reset() {
playerPlayedPermanentTypes.clear();
super.reset();
}
public boolean permanentTypePlayedFromGraveyard(UUID playerId, CardType cardType) {
Set<CardType> permanentTypes = playerPlayedPermanentTypes.get(playerId);
if (permanentTypes != null) {
return permanentTypes.contains(cardType);
}
return false;
}
}
/*
* 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.cards.m;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.watchers.Watcher;
/**
*
* @author LevelX2
*/
public class MuldrothaTheGravetide extends CardImpl {
public MuldrothaTheGravetide(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{G}{U}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.ELEMENTAL);
this.subtype.add(SubType.AVATAR);
this.power = new MageInt(6);
this.toughness = new MageInt(6);
// During each of your turns, you may play up to one permanent card of each permanent type from your graveyard.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MuldrothaTheGravetideCastFromGraveyardEffect()), new MuldrothaTheGravetideWatcher());
}
public MuldrothaTheGravetide(final MuldrothaTheGravetide card) {
super(card);
}
@Override
public MuldrothaTheGravetide copy() {
return new MuldrothaTheGravetide(this);
}
}
class MuldrothaTheGravetideCastFromGraveyardEffect extends AsThoughEffectImpl {
public MuldrothaTheGravetideCastFromGraveyardEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "During each of your turns, you may play up to one permanent card of each permanent type from your graveyard. "
+ "<i>(If a card has multiple permanent types, choose one as you play it.)</i>";
}
public MuldrothaTheGravetideCastFromGraveyardEffect(final MuldrothaTheGravetideCastFromGraveyardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public MuldrothaTheGravetideCastFromGraveyardEffect copy() {
return new MuldrothaTheGravetideCastFromGraveyardEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (source.getControllerId().equals(affectedControllerId)
&& affectedControllerId.equals(game.getActivePlayerId()) // only during your turns (e.g. prevent flash creatures)
&& Zone.GRAVEYARD.equals(game.getState().getZone(objectId))) {
MuldrothaTheGravetideWatcher watcher = (MuldrothaTheGravetideWatcher) game.getState().getWatchers().get(MuldrothaTheGravetideWatcher.class.getSimpleName());
MageObject mageObject = game.getObject(objectId);
if (mageObject != null && watcher != null) {
for (CardType cardType : mageObject.getCardType()) {
if (cardType.isPermanentType()) {
if (!watcher.permanentTypePlayedFromGraveyard(affectedControllerId, cardType)) {
return true;
}
}
}
}
}
return false;
}
}
/**
* Holds track of the consumed types of each permission giving source
*
* @author LevelX2
*/
class MuldrothaTheGravetideWatcher extends Watcher {
// final HashMap<MageObjectReference, Set<CardType>> playerPlayedPermanentTypes = new HashMap<>(); // source that played permanent types from graveyard
final HashMap<UUID, Set<CardType>> playerPlayedPermanentTypes = new HashMap<>(); // player that played permanent types from graveyard
// 4/27/2018 If multiple effects allow you to play a card from your graveyard, such as those of Gisa and Geralf and Karador,
// Ghost Chieftain, you must announce which permission youre using as you begin to play the card.
private Zone fromZone;
public MuldrothaTheGravetideWatcher() {
super(MuldrothaTheGravetideWatcher.class.getSimpleName(), WatcherScope.GAME);
}
public MuldrothaTheGravetideWatcher(final MuldrothaTheGravetideWatcher watcher) {
super(watcher);
playerPlayedPermanentTypes.putAll(watcher.playerPlayedPermanentTypes);
}
@Override
public MuldrothaTheGravetideWatcher copy() {
return new MuldrothaTheGravetideWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.PLAY_LAND) {
fromZone = game.getState().getZone(event.getTargetId()); // Remember the Zone the land came from
}
if (event.getType() == GameEvent.EventType.LAND_PLAYED && fromZone.equals(Zone.GRAVEYARD)) {
addPermanentTypes(event, game.getPermanentOrLKIBattlefield(event.getTargetId()), game);
}
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
Spell spell = (Spell) game.getObject(event.getTargetId());
if (spell.getFromZone().equals(Zone.GRAVEYARD)) {
addPermanentTypes(event, spell, game);
}
}
}
private void addPermanentTypes(GameEvent event, Card mageObject, Game game) {
if (mageObject != null) {
UUID playerId = null;
if (mageObject instanceof Spell) {
playerId = ((Spell) mageObject).getControllerId();
} else if (mageObject instanceof Permanent) {
playerId = ((Permanent) mageObject).getControllerId();
}
if (playerId != null) {
Set<CardType> permanentTypes = playerPlayedPermanentTypes.get(playerId);
if (permanentTypes == null) {
permanentTypes = EnumSet.noneOf(CardType.class);
playerPlayedPermanentTypes.put(playerId, permanentTypes);
}
Set<CardType> typesNotCast = EnumSet.noneOf(CardType.class);
for (CardType cardType : mageObject.getCardType()) {
if (cardType.isPermanentType()) {
if (!permanentTypes.contains(cardType)) {
typesNotCast.add(cardType);
}
}
}
if (typesNotCast.size() <= 1) {
permanentTypes.addAll(typesNotCast);
} else {
Player player = game.getPlayer(playerId);
if (player != null) {
Choice typeChoice = new ChoiceImpl(true);
typeChoice.setMessage("Choose permanent type you consume for casting from graveyard.");
for (CardType cardType : typesNotCast) {
typeChoice.getChoices().add(cardType.toString());
}
if (player.choose(Outcome.Detriment, typeChoice, game)) {
String typeName = typeChoice.getChoice();
CardType chosenType = null;
for (CardType cardType : CardType.values()) {
if (cardType.toString().equals(typeName)) {
chosenType = cardType;
break;
}
}
if (chosenType != null) {
permanentTypes.add(chosenType);
}
}
}
}
}
}
}
@Override
public void reset() {
playerPlayedPermanentTypes.clear();
super.reset();
}
public boolean permanentTypePlayedFromGraveyard(UUID playerId, CardType cardType) {
Set<CardType> permanentTypes = playerPlayedPermanentTypes.get(playerId);
if (permanentTypes != null) {
return permanentTypes.contains(cardType);
}
return false;
}
}

View file

@ -108,7 +108,7 @@ class CantBeBlockedUnlessAllEffect extends RestrictionEffect {
// check if all creatures of defender are able to block this permanent
// permanent.canBlock() can't be used because causing recursive call
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, blocker.getControllerId(), game)) {
if (permanent.isTapped() && !game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, source, blocker.getControllerId(), game)) {
if (permanent.isTapped() && null == game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, source, blocker.getControllerId(), game)) {
return false;
}
// check blocker restrictions

View file

@ -220,7 +220,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
}
//20091005 - 602.5d/602.5e
if (timing == TimingRule.INSTANT || game.canPlaySorcery(playerId)
|| game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
|| null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
if (costs.canPay(this, sourceId, playerId, game) && canChooseTarget(game)) {
this.activatorId = playerId;
return true;

View file

@ -52,7 +52,7 @@ public class PlayLandAbility extends ActivatedAbilityImpl {
@Override
public boolean canActivate(UUID playerId, Game game) {
if (!controlsAbility(playerId, game)
&& !game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, playerId, game)) {
&& null == game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, playerId, game)) {
return false;
}
//20091005 - 114.2a

View file

@ -92,13 +92,13 @@ public class SpellAbility extends ActivatedAbilityImpl {
@Override
public boolean canActivate(UUID playerId, Game game) {
if (game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game) // check this first to allow Offering in main phase
if (null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game) // check this first to allow Offering in main phase
|| this.spellCanBeActivatedRegularlyNow(playerId, game)) {
if (spellAbilityType == SpellAbilityType.SPLIT || spellAbilityType == SpellAbilityType.SPLIT_AFTERMATH) {
return false;
}
// fix for Gitaxian Probe and casting opponent's spells
if (!game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, playerId, game)) {
if (null == game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, playerId, game)) {
Card card = game.getCard(sourceId);
if (!(card != null && card.getOwnerId().equals(playerId))) {
return false;

View file

@ -24,8 +24,7 @@
* 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.costs.common;
import java.util.UUID;
@ -63,8 +62,8 @@ public class TapSourceCost extends CostImpl {
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
Permanent permanent = game.getPermanent(sourceId);
if (permanent != null) {
return !permanent.isTapped() &&
(permanent.canTap() || game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_HASTE, controllerId, game));
return !permanent.isTapped()
&& (permanent.canTap() || null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_HASTE, controllerId, game));
}
return false;
}

View file

@ -62,7 +62,7 @@ public class UntapSourceCost extends CostImpl {
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
Permanent permanent = game.getPermanent(sourceId);
if (permanent != null) {
return permanent.isTapped() && (permanent.canTap() || game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_HASTE, controllerId, game));
return permanent.isTapped() && (permanent.canTap() || null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_HASTE, controllerId, game));
}
return false;
}

View file

@ -500,25 +500,44 @@ public class ContinuousEffects implements Serializable {
return spliceEffects;
}
public boolean asThough(UUID objectId, AsThoughEffectType type, UUID controllerId, Game game) {
/**
*
* @param objectId
* @param type
* @param controllerId
* @param game
* @return sourceId of the permitting effect if any exists otherwise returns
* null
*/
public UUID asThough(UUID objectId, AsThoughEffectType type, UUID controllerId, Game game) {
return asThough(objectId, type, null, controllerId, game);
}
public boolean asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
/**
*
* @param objectId
* @param type
* @param affectedAbility
* @param controllerId
* @param game
* @return sourceId of the permitting effect if any exists otherwise returns
* null
*/
public UUID asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(type, game);
for (AsThoughEffect effect : asThoughEffectsList) {
Set<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
for (Ability ability : abilities) {
if (affectedAbility == null) {
if (effect.applies(objectId, ability, controllerId, game)) {
return true;
return ability.getSourceId();
}
} else if (effect.applies(objectId, affectedAbility, ability, game)) {
return true;
return ability.getSourceId();
}
}
}
return false;
return null;
}
@ -754,7 +773,7 @@ public class ContinuousEffects implements Serializable {
// Remove all consumed effects (ability dependant)
for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext();) {
ReplacementEffect entry = it1.next();
if (consumed.containsKey(entry.getId()) /*&& !(entry instanceof CommanderReplacementEffect) */) { // 903.9.
if (consumed.containsKey(entry.getId()) /*&& !(entry instanceof CommanderReplacementEffect) */) { // 903.9.
Set<UUID> consumedAbilitiesIds = consumed.get(entry.getId());
if (rEffects.get(entry) == null || consumedAbilitiesIds.size() == rEffects.get(entry).size()) {
it1.remove();

View file

@ -27,6 +27,7 @@
*/
package mage.abilities.keyword;
import java.io.ObjectStreamException;
import mage.abilities.Ability;
import mage.abilities.EvasionAbility;
import mage.abilities.MageSingleton;
@ -37,8 +38,6 @@ import mage.constants.SubType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.io.ObjectStreamException;
/**
*
* @author BetaSteward_at_googlemail.com
@ -90,7 +89,8 @@ class FlyingEffect extends RestrictionEffect implements MageSingleton {
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) {
return blocker.getAbilities().containsKey(FlyingAbility.getInstance().getId())
|| blocker.getAbilities().containsKey(ReachAbility.getInstance().getId())
|| (game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_DRAGON, source, blocker.getControllerId(), game) && attacker.hasSubtype(SubType.DRAGON, game));
|| (null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_DRAGON, source, blocker.getControllerId(), game)
&& attacker.hasSubtype(SubType.DRAGON, game));
}
@Override

View file

@ -88,21 +88,21 @@ class LandwalkEffect extends RestrictionEffect {
@Override
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) {
if (game.getBattlefield().contains(filter, blocker.getControllerId(), 1, game)
&& !game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_LANDWALK, source, blocker.getControllerId(), game)) {
&& null == game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_LANDWALK, source, blocker.getControllerId(), game)) {
switch (filter.getMessage()) {
case "plains":
return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_PLAINSWALK, source, blocker.getControllerId(), game);
return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_PLAINSWALK, source, blocker.getControllerId(), game);
case "island":
return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_ISLANDWALK, source, blocker.getControllerId(), game);
return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_ISLANDWALK, source, blocker.getControllerId(), game);
case "swamp":
return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SWAMPWALK, source, blocker.getControllerId(), game);
return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SWAMPWALK, source, blocker.getControllerId(), game);
case "mountain":
return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_MOUNTAINWALK, source, blocker.getControllerId(), game);
return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_MOUNTAINWALK, source, blocker.getControllerId(), game);
case "forest":
return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_FORESTWALK, source, blocker.getControllerId(), game);
return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_FORESTWALK, source, blocker.getControllerId(), game);
default:
return false;
}
}
return true;

View file

@ -66,7 +66,7 @@ class ShadowEffect extends RestrictionEffect implements MageSingleton {
@Override
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) {
return blocker.getAbilities().containsKey(ShadowAbility.getInstance().getId())
|| game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SHADOW, source, blocker.getControllerId(), game);
|| null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SHADOW, source, blocker.getControllerId(), game);
}
@Override

View file

@ -27,6 +27,9 @@
*/
package mage.abilities.keyword;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.SpecialAction;
@ -50,10 +53,6 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
* 502.59. Suspend
@ -120,10 +119,10 @@ import java.util.UUID;
* card involves an additional cost, the card's owner must pay that cost if
* able. If he or she can't, the card remains removed from the game. If the
* additional cost includes mana, the situation is more complex. If the player
* has enough mana in their mana pool to pay the cost, that player must do
* so. If the player can't possibly pay the cost, the card remains removed from
* the game. However, if the player has the means to produce enough mana to pay
* the cost, then he or she has a choice: The player may play the spell, produce
* has enough mana in their mana pool to pay the cost, that player must do so.
* If the player can't possibly pay the cost, the card remains removed from the
* game. However, if the player has the means to produce enough mana to pay the
* cost, then he or she has a choice: The player may play the spell, produce
* mana, and pay the cost. Or the player may choose to play no mana abilities,
* thus making the card impossible to play because the additional mana can't be
* paid.
@ -237,7 +236,7 @@ public class SuspendAbility extends SpecialAction {
MageObject object = game.getObject(sourceId);
return (object.isInstant()
|| object.hasAbility(FlashAbility.getInstance().getId(), game)
|| game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game)
|| null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game)
|| game.canPlaySorcery(playerId));
}

View file

@ -77,7 +77,7 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
}
if (timing == TimingRule.SORCERY
&& !game.canPlaySorcery(playerId)
&& !game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
&& null == game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
return false;
}
// check if player is in the process of playing spell costs and he is no longer allowed to use activated mana abilities (e.g. because he started to use improvise)

View file

@ -24,8 +24,7 @@
* 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.filter.common;
import mage.constants.AsThoughEffectType;
@ -61,8 +60,8 @@ public class FilterCreatureForCombatBlock extends FilterCreatureForCombatBase {
class BlockTappedPredicate implements Predicate<Permanent> {
@Override
public boolean apply(Permanent input, Game game) {
return !input.isTapped() || game.getState().getContinuousEffects().asThough(input.getId(), AsThoughEffectType.BLOCK_TAPPED, input.getControllerId(), game);
public boolean apply(Permanent input, Game game) {
return !input.isTapped() || null != game.getState().getContinuousEffects().asThough(input.getId(), AsThoughEffectType.BLOCK_TAPPED, input.getControllerId(), game);
}
@Override

View file

@ -935,20 +935,20 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
public boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, Game game) {
if (source != null) {
if (abilities.containsKey(ShroudAbility.getInstance().getId())) {
if (!game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.SHROUD, sourceControllerId, game)) {
if (null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.SHROUD, sourceControllerId, game)) {
return false;
}
}
if (abilities.containsKey(HexproofAbility.getInstance().getId())) {
if (game.getPlayer(this.getControllerId()).hasOpponent(sourceControllerId, game)
&& !game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, sourceControllerId, game)) {
&& null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, sourceControllerId, game)) {
return false;
}
}
if (abilities.containsKey(HexproofFromBlackAbility.getInstance().getId())) {
if (game.getPlayer(this.getControllerId()).hasOpponent(sourceControllerId, game)
&& !game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, sourceControllerId, game)
&& null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, sourceControllerId, game)
&& source.getColor(game).isBlack()) {
return false;
}
@ -956,7 +956,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
if (abilities.containsKey(HexproofFromWhiteAbility.getInstance().getId())) {
if (game.getPlayer(this.getControllerId()).hasOpponent(sourceControllerId, game)
&& !game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, sourceControllerId, game)
&& null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, sourceControllerId, game)
&& source.getColor(game).isWhite()) {
return false;
}
@ -1095,7 +1095,8 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
@Override
public boolean canAttackInPrinciple(UUID defenderId, Game game) {
if (hasSummoningSickness() && !game.getContinuousEffects().asThough(this.objectId, AsThoughEffectType.ATTACK_AS_HASTE, this.getControllerId(), game)) {
if (hasSummoningSickness()
&& null == game.getContinuousEffects().asThough(this.objectId, AsThoughEffectType.ATTACK_AS_HASTE, this.getControllerId(), game)) {
return false;
}
//20101001 - 508.1c
@ -1115,7 +1116,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
}
return !abilities.containsKey(DefenderAbility.getInstance().getId())
|| game.getContinuousEffects().asThough(this.objectId, AsThoughEffectType.ATTACK, this.getControllerId(), game);
|| null != game.getContinuousEffects().asThough(this.objectId, AsThoughEffectType.ATTACK, this.getControllerId(), game);
}
private boolean canAttackCheckRestrictionEffects(UUID defenderId, Game game) {
@ -1135,7 +1136,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
@Override
public boolean canBlock(UUID attackerId, Game game) {
if (tapped && !game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, this.getControllerId(), game)) {
if (tapped && null == game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, this.getControllerId(), game)) {
return false;
}
Permanent attacker = game.getPermanent(attackerId);
@ -1168,7 +1169,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
@Override
public boolean canBlockAny(Game game) {
if (tapped && !game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, this.getControllerId(), game)) {
if (tapped && null == game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, this.getControllerId(), game)) {
return false;
}

View file

@ -31,7 +31,6 @@ import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
import static jdk.nashorn.internal.objects.NativeRegExp.source;
import mage.ConditionalMana;
import mage.MageObject;
import mage.Mana;
@ -610,7 +609,7 @@ public abstract class PlayerImpl implements Player, Serializable {
}
if (abilities.containsKey(HexproofAbility.getInstance().getId())) {
if (sourceControllerId != null && this.hasOpponent(sourceControllerId, game)
&& !game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, this.getId(), game)) {
&& null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, this.getId(), game)) {
return false;
}
}
@ -1356,7 +1355,8 @@ public abstract class PlayerImpl implements Player, Serializable {
}
}
}
if (zone != Zone.BATTLEFIELD && game.getContinuousEffects().asThough(object.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
if (zone != Zone.BATTLEFIELD
&& null != game.getContinuousEffects().asThough(object.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
for (Ability ability : candidateAbilites) {
if (canUse || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
ability.setControllerId(this.getId());
@ -2706,10 +2706,10 @@ public abstract class PlayerImpl implements Player, Serializable {
if (available == null) {
return true;
}
boolean spendAnyMana = game.getContinuousEffects().asThough(ability.getSourceId(), AsThoughEffectType.SPEND_OTHER_MANA, ability, ability.getControllerId(), game);
UUID spendAnyManaSourceId = game.getContinuousEffects().asThough(ability.getSourceId(), AsThoughEffectType.SPEND_OTHER_MANA, ability, ability.getControllerId(), game);
for (Mana mana : abilityOptions) {
for (Mana avail : available) {
if (spendAnyMana && mana.count() <= avail.count()) {
if (spendAnyManaSourceId != null && mana.count() <= avail.count()) {
return true;
}
if (mana.enough(avail)) { // here we need to check if spend mana as though allow to pay the mana cost
@ -2834,13 +2834,13 @@ public abstract class PlayerImpl implements Player, Serializable {
}
private void getPlayableFromGraveyardCard(Game game, Card card, Abilities<Ability> candidateAbilities, ManaOptions availableMana, List<Ability> output) {
boolean asThoughtCast = game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game);
UUID asThoughtCastSourceId = game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game);
for (ActivatedAbility ability : candidateAbilities.getActivatedAbilities(Zone.ALL)) {
boolean possible = false;
if (ability.getZone().match(Zone.GRAVEYARD)) {
possible = true;
} else if (ability.getZone().match(Zone.HAND) && (ability instanceof SpellAbility || ability instanceof PlayLandAbility)) {
if (asThoughtCast || canPlayCardsFromGraveyard()) {
if (asThoughtCastSourceId != null || canPlayCardsFromGraveyard()) {
possible = true;
}
}
@ -2909,7 +2909,7 @@ public abstract class PlayerImpl implements Player, Serializable {
}
for (ExileZone exile : game.getExile().getExileZones()) {
for (Card card : exile.getCards(game)) {
if (game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
for (Ability ability : card.getAbilities()) {
if (ability.getZone().match(Zone.HAND)) {
ability.setControllerId(this.getId()); // controller must be set for case owner != caster
@ -2927,7 +2927,7 @@ public abstract class PlayerImpl implements Player, Serializable {
// Check to play revealed cards
for (Cards cards : game.getState().getRevealed().values()) {
for (Card card : cards.getCards(game)) {
if (game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
if (ability instanceof SpellAbility || ability instanceof PlayLandAbility) {
playable.add(ability);
@ -2942,7 +2942,7 @@ public abstract class PlayerImpl implements Player, Serializable {
if (player != null) {
if (/*player.isTopCardRevealed() &&*/player.getLibrary().hasCards()) {
Card card = player.getLibrary().getFromTop(game);
if (game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, getId(), game)) {
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, getId(), game)) {
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
if (ability instanceof SpellAbility || ability instanceof PlayLandAbility) {
playable.add(ability);
@ -3295,7 +3295,7 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override
public boolean lookAtFaceDownCard(Card card, Game game
) {
if (game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.LOOK_AT_FACE_DOWN, this.getId(), game)) {
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.LOOK_AT_FACE_DOWN, this.getId(), game)) {
if (chooseUse(Outcome.Benefit, "Look at that card?", null, game)) {
Cards cards = new CardsImpl(card);
this.lookAtCards(getName() + " - " + sdf.format(System.currentTimeMillis()), cards, game);