diff --git a/Mage.Sets/src/mage/cards/g/GisaAndGeralf.java b/Mage.Sets/src/mage/cards/g/GisaAndGeralf.java
index 53c0cb9314..ba9f3e14d4 100644
--- a/Mage.Sets/src/mage/cards/g/GisaAndGeralf.java
+++ b/Mage.Sets/src/mage/cards/g/GisaAndGeralf.java
@@ -57,7 +57,7 @@ public final class GisaAndGeralf extends CardImpl {
class GisaAndGeralfCastFromGraveyardEffect extends AsThoughEffectImpl {
GisaAndGeralfCastFromGraveyardEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.PutCreatureInPlay);
+ super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.PutCreatureInPlay, true);
staticText = "During each of your turns, you may cast a Zombie creature card from your graveyard";
}
diff --git a/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java b/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java
index 958ce26958..185018949c 100644
--- a/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java
+++ b/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java
@@ -98,7 +98,7 @@ class KaradorGhostChieftainCostReductionEffect extends CostModificationEffectImp
class KaradorGhostChieftainCastFromGraveyardEffect extends AsThoughEffectImpl {
KaradorGhostChieftainCastFromGraveyardEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.PutCreatureInPlay);
+ super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.PutCreatureInPlay, true);
staticText = "During each of your turns, you may cast one creature card from your graveyard";
}
diff --git a/Mage.Sets/src/mage/cards/k/KessDissidentMage.java b/Mage.Sets/src/mage/cards/k/KessDissidentMage.java
index af71d68ec9..a5d2a732a1 100644
--- a/Mage.Sets/src/mage/cards/k/KessDissidentMage.java
+++ b/Mage.Sets/src/mage/cards/k/KessDissidentMage.java
@@ -71,7 +71,7 @@ public final class KessDissidentMage extends CardImpl {
class KessDissidentMageCastFromGraveyardEffect extends AsThoughEffectImpl {
KessDissidentMageCastFromGraveyardEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit);
+ super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit, true);
staticText = "During each of your turns, you may cast an instant or sorcery card from your graveyard";
}
diff --git a/Mage.Sets/src/mage/cards/l/LurrusOfTheDreamDen.java b/Mage.Sets/src/mage/cards/l/LurrusOfTheDreamDen.java
index ccbfd97635..2bc0fa566f 100644
--- a/Mage.Sets/src/mage/cards/l/LurrusOfTheDreamDen.java
+++ b/Mage.Sets/src/mage/cards/l/LurrusOfTheDreamDen.java
@@ -79,7 +79,7 @@ enum LurrusOfTheDreamDenCompanionCondition implements CompanionCondition {
class LurrusOfTheDreamDenCastFromGraveyardEffect extends AsThoughEffectImpl {
LurrusOfTheDreamDenCastFromGraveyardEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit);
+ super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit, true);
staticText = "During each of your turns, you may cast one permanent spell with converted mana cost 2 or less from your graveyard";
}
diff --git a/Mage.Sets/src/mage/cards/m/MuldrothaTheGravetide.java b/Mage.Sets/src/mage/cards/m/MuldrothaTheGravetide.java
index 7cd525cb39..a0db30df28 100644
--- a/Mage.Sets/src/mage/cards/m/MuldrothaTheGravetide.java
+++ b/Mage.Sets/src/mage/cards/m/MuldrothaTheGravetide.java
@@ -66,7 +66,7 @@ public final class MuldrothaTheGravetide extends CardImpl {
class MuldrothaTheGravetideCastFromGraveyardEffect extends AsThoughEffectImpl {
public MuldrothaTheGravetideCastFromGraveyardEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit);
+ super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit, true);
staticText = "During each of your turns, you may play up to one permanent card of each permanent type from your graveyard. "
+ "(If a card has multiple permanent types, choose one as you play it.)";
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/KaradorGhostChieftainTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/KaradorGhostChieftainTest.java
index 216a9d4faf..4049c98290 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/KaradorGhostChieftainTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/KaradorGhostChieftainTest.java
@@ -67,7 +67,7 @@ public class KaradorGhostChieftainTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
- addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion", 7);
// Exile target creature you control, then return that card to the battlefield under your control.
@@ -96,7 +96,7 @@ public class KaradorGhostChieftainTest extends CardTestPlayerBase {
}
@Test
- @Ignore // It's not possible yet to select which ability to use to allow a asThoughtAs effect
+ // @Ignore // It's not possible yet to select which ability to use to allow a asThoughtAs effect
public void test_castFromGraveyardWithDifferentApprovers() {
setStrictChooseMode(true);
@@ -125,6 +125,8 @@ public class KaradorGhostChieftainTest extends CardTestPlayerBase {
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Accursed Horde");
+ setChoice(playerA, "During each of your turns, you may cast a Zombie creature card from your graveyard"); // Choose the permitting object
+
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion");
diff --git a/Mage/src/main/java/mage/abilities/effects/AsThoughEffect.java b/Mage/src/main/java/mage/abilities/effects/AsThoughEffect.java
index 1c58869db3..2933328297 100644
--- a/Mage/src/main/java/mage/abilities/effects/AsThoughEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/AsThoughEffect.java
@@ -20,4 +20,6 @@ public interface AsThoughEffect extends ContinuousEffect {
@Override
AsThoughEffect copy();
+
+ boolean isConsumable();
}
diff --git a/Mage/src/main/java/mage/abilities/effects/AsThoughEffectImpl.java b/Mage/src/main/java/mage/abilities/effects/AsThoughEffectImpl.java
index 52bf7f4436..8397a6e718 100644
--- a/Mage/src/main/java/mage/abilities/effects/AsThoughEffectImpl.java
+++ b/Mage/src/main/java/mage/abilities/effects/AsThoughEffectImpl.java
@@ -17,16 +17,23 @@ import mage.players.Player;
public abstract class AsThoughEffectImpl extends ContinuousEffectImpl implements AsThoughEffect {
protected AsThoughEffectType type;
+ boolean consumable;
public AsThoughEffectImpl(AsThoughEffectType type, Duration duration, Outcome outcome) {
+ this(type, duration, outcome, false);
+ }
+
+ public AsThoughEffectImpl(AsThoughEffectType type, Duration duration, Outcome outcome, boolean consumable) {
super(duration, outcome);
this.type = type;
this.effectType = EffectType.ASTHOUGH;
+ this.consumable = consumable;
}
public AsThoughEffectImpl(final AsThoughEffectImpl effect) {
super(effect);
this.type = effect.type;
+ this.consumable = effect.consumable;
}
@Override
@@ -93,4 +100,9 @@ public abstract class AsThoughEffectImpl extends ContinuousEffectImpl implements
return true;
}
+ @Override
+ public boolean isConsumable() {
+ return consumable;
+ }
+
}
diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java
index 9e1d89bd8f..db27aea89c 100644
--- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java
+++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java
@@ -1,7 +1,6 @@
package mage.abilities.effects;
import mage.MageObject;
-import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.MageSingleton;
import mage.abilities.StaticAbility;
@@ -31,6 +30,8 @@ import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import mage.ApprovingObject;
+import mage.choices.Choice;
+import mage.choices.ChoiceImpl;
/**
* @author BetaSteward_at_googlemail.com
@@ -333,7 +334,7 @@ public class ContinuousEffects implements Serializable {
* @param event
* @param game
* @return a list of all {@link ReplacementEffect} that apply to the current
- * event
+ * event
*/
private Map> getApplicableReplacementEffects(GameEvent event, Game game) {
Map> replaceEffects = new HashMap<>();
@@ -342,7 +343,7 @@ public class ContinuousEffects implements Serializable {
}
// boolean checkLKI = event.getType().equals(EventType.ZONE_CHANGE) || event.getType().equals(EventType.DESTROYED_PERMANENT);
//get all applicable transient Replacement effects
- for (Iterator iterator = replacementEffects.iterator(); iterator.hasNext(); ) {
+ for (Iterator iterator = replacementEffects.iterator(); iterator.hasNext();) {
ReplacementEffect effect = iterator.next();
if (!effect.checksEventType(event, game)) {
continue;
@@ -375,7 +376,7 @@ public class ContinuousEffects implements Serializable {
}
}
- for (Iterator iterator = preventionEffects.iterator(); iterator.hasNext(); ) {
+ for (Iterator iterator = preventionEffects.iterator(); iterator.hasNext();) {
PreventionEffect effect = iterator.next();
if (!effect.checksEventType(event, game)) {
continue;
@@ -506,7 +507,7 @@ public class ContinuousEffects implements Serializable {
* @param controllerId
* @param game
* @return sourceId of the permitting effect if any exists otherwise returns
- * null
+ * null
*/
public ApprovingObject asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
List asThoughEffectsList = getApplicableAsThoughEffects(type, game);
@@ -531,13 +532,18 @@ public class ContinuousEffects implements Serializable {
}
}
+ Set possibleApprovingObjects = new HashSet<>();
for (AsThoughEffect effect : asThoughEffectsList) {
Set abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
for (Ability ability : abilities) {
if (affectedAbility == null) {
// applies to own ability (one effect can be used in multiple abilities)
if (effect.applies(idToCheck, ability, controllerId, game)) {
- return new ApprovingObject(ability, game);
+ if (effect.isConsumable() && !game.inCheckPlayableState()) {
+ possibleApprovingObjects.add(new ApprovingObject(ability, game));
+ } else {
+ return new ApprovingObject(ability, game);
+ }
}
} else {
// applies to affected ability
@@ -548,11 +554,38 @@ public class ContinuousEffects implements Serializable {
}
if (effect.applies(idToCheck, affectedAbility, ability, game, controllerId)) {
- return new ApprovingObject(ability, game);
+ if (effect.isConsumable() && !game.inCheckPlayableState()) {
+ possibleApprovingObjects.add(new ApprovingObject(ability, game));
+ } else {
+ return new ApprovingObject(ability, game);
+ }
}
}
}
}
+ if (possibleApprovingObjects.size() == 1) {
+ return possibleApprovingObjects.iterator().next();
+ } else if (possibleApprovingObjects.size() > 1) {
+ // Select the ability that you use to permit the action
+ Map keyChoices = new HashMap<>();
+ for(ApprovingObject approvingObject :possibleApprovingObjects) {
+ MageObject mageObject = game.getObject(approvingObject.getApprovingAbility().getSourceId());
+ keyChoices.put(approvingObject.getApprovingAbility().getId().toString(),
+ (approvingObject.getApprovingAbility().getRule(mageObject == null ? "" : mageObject.getName()))
+ + (mageObject == null ? "" : " (" + mageObject.getIdName() + ")"));
+ }
+ Choice choicePermitting = new ChoiceImpl(true);
+ choicePermitting.setMessage("Choose the permitting object");
+ choicePermitting.setKeyChoices(keyChoices);
+ Player player = game.getPlayer(controllerId);
+ player.choose(Outcome.Detriment, choicePermitting, game);
+ for(ApprovingObject approvingObject: possibleApprovingObjects) {
+ if (approvingObject.getApprovingAbility().getId().toString().equals(choicePermitting.getChoiceKey())) {
+ return approvingObject;
+ }
+ }
+ }
+
}
return null;
@@ -800,7 +833,7 @@ public class ContinuousEffects implements Serializable {
do {
Map> rEffects = getApplicableReplacementEffects(event, game);
// Remove all consumed effects (ability dependant)
- for (Iterator it1 = rEffects.keySet().iterator(); it1.hasNext(); ) {
+ for (Iterator it1 = rEffects.keySet().iterator(); it1.hasNext();) {
ReplacementEffect entry = it1.next();
if (consumed.containsKey(entry.getId()) /*&& !(entry instanceof CommanderReplacementEffect) */) { // 903.9.
Set consumedAbilitiesIds = consumed.get(entry.getId());
@@ -985,7 +1018,7 @@ public class ContinuousEffects implements Serializable {
.entrySet()
.stream()
.filter(entry -> dependentTo.contains(entry.getKey().getId())
- && entry.getValue().contains(effect.getId()))
+ && entry.getValue().contains(effect.getId()))
.forEach(entry -> {
entry.getValue().remove(effect.getId());
dependentTo.remove(entry.getKey().getId());
@@ -1019,7 +1052,7 @@ public class ContinuousEffects implements Serializable {
continue;
}
// check if waiting effects can be applied now
- for (Iterator>> iterator = waitingEffects.entrySet().iterator(); iterator.hasNext(); ) {
+ for (Iterator>> iterator = waitingEffects.entrySet().iterator(); iterator.hasNext();) {
Map.Entry> entry = iterator.next();
if (!appliedEffects.containsAll(entry.getValue())) { // all dependent to effects are applied now so apply the effect itself
continue;
diff --git a/Mage/src/main/java/mage/choices/ChoiceImpl.java b/Mage/src/main/java/mage/choices/ChoiceImpl.java
index 66ea9d37c1..0809bea419 100644
--- a/Mage/src/main/java/mage/choices/ChoiceImpl.java
+++ b/Mage/src/main/java/mage/choices/ChoiceImpl.java
@@ -215,6 +215,17 @@ public class ChoiceImpl implements Choice, Serializable {
answers.remove(needChoice);
return true;
}
+
+ }
+ }
+ // no key answer found, try to macht by text starting with
+ for (String needChoice : answers) {
+ for (Map.Entry currentChoice : this.getKeyChoices().entrySet()) {
+ if (currentChoice.getValue().startsWith(needChoice)) {
+ this.setChoiceByKey(currentChoice.getKey());
+ answers.remove(needChoice);
+ return true;
+ }
}
}
} else {
@@ -231,4 +242,4 @@ public class ChoiceImpl implements Choice, Serializable {
}
return false; // can't find answer
}
-}
\ No newline at end of file
+}