Added the possibility to handle the enteres_the_battlefield event according to rule 614.12 (issue #164).

This commit is contained in:
LevelX2 2013-03-22 15:00:06 +01:00
parent e14886ffda
commit b46bdef429
6 changed files with 58 additions and 2 deletions

View file

@ -261,8 +261,10 @@ public class ContinuousEffects implements Serializable {
Ability ability = replacementEffects.getAbility(effect.getId());
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, false)) {
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
if (effect.applies(event, ability, game)) {
replaceEffects.add(effect);
if (!game.getScopeRelevant() || effect.hasSelfScope() || !event.getTargetId().equals(this.replacementEffects.getAbility(effect.getId()).getSourceId())) {
if (effect.applies(event, ability, game)) {
replaceEffects.add(effect);
}
}
}
}

View file

@ -41,4 +41,6 @@ public interface ReplacementEffect<T extends ReplacementEffect<T>> extends Conti
boolean replaceEvent(GameEvent event, Ability source, Game game);
boolean applies(GameEvent event, Ability source, Game game);
boolean hasSelfScope();
}

View file

@ -38,13 +38,36 @@ import mage.Constants.Outcome;
*/
public abstract class ReplacementEffectImpl<T extends ReplacementEffectImpl<T>> extends ContinuousEffectImpl<T> implements ReplacementEffect<T> {
// 614.12
// Some replacement effects modify how a permanent enters the battlefield. (See rules 614.1c-d.)
// Such effects may come from the permanent itself if they affect only that permanent (as opposed
// to a general subset of permanents that includes it). They may also come from other sources. To
// determine which replacement effects apply and how they apply, check the characteristics of the
// permanent as it would exist on the battlefield, taking into account replacement effects that have
// already modified how it enters the battlefield (see rule 616.1), continuous effects generated by
// the resolution of spells or abilities that changed the permanent's characteristics on the stack
// (see rule 400.7a), and continuous effects from the permanent's own static abilities, but ignoring
// continuous effects from any other source that would affect it.
protected boolean selfScope;
public ReplacementEffectImpl(Duration duration, Outcome outcome) {
this(duration, outcome, true);
}
public ReplacementEffectImpl(Duration duration, Outcome outcome, boolean selfScope) {
super(duration, outcome);
this.effectType = EffectType.REPLACEMENT;
this.selfScope = selfScope;
}
public ReplacementEffectImpl(final ReplacementEffectImpl effect) {
super(effect);
this.selfScope = effect.selfScope;
}
@Override
public boolean hasSelfScope() {
return selfScope;
}
}

View file

@ -317,8 +317,10 @@ public abstract class CardImpl<T extends CardImpl<T>> extends MageObjectImpl<T>
game.resetForSourceId(permanent.getId());
game.addPermanent(permanent);
game.setZone(objectId, Zone.BATTLEFIELD);
game.setScopeRelevant(true);
game.applyEffects();
permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
game.setScopeRelevant(false);
game.applyEffects();
if (flag) {
permanent.setTapped(true);
@ -446,8 +448,10 @@ public abstract class CardImpl<T extends CardImpl<T>> extends MageObjectImpl<T>
game.resetForSourceId(permanent.getId());
game.addPermanent(permanent);
game.setZone(objectId, Zone.BATTLEFIELD);
game.setScopeRelevant(true);
game.applyEffects(); // magenoxx: this causes bugs - LevelX2: but it's neccessary for casting e.g. Kird Ape which must trigger evolve
permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
game.setScopeRelevant(false);
game.applyEffects();
game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD));
return true;

View file

@ -206,4 +206,8 @@ public interface Game extends MageItem, Serializable {
// game cheats (for tests only)
void cheat(UUID ownerId, Map<Zone, String> commands);
void cheat(UUID ownerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard);
// controlling the behaviour of replacement effects
void setScopeRelevant(boolean scopeRelevant);
public boolean getScopeRelevant();
}

View file

@ -145,6 +145,9 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
private Player losingPlayer;
private boolean stateCheckRequired = false;
// used to indicate that currently applied replacement effects have to check for scope relevance (614.12 13/01/18)
private boolean scopeRelevant = false;
@Override
public abstract T copy();
@ -184,6 +187,7 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
this.actions = new LinkedList<MageAction>();
this.stateCheckRequired = game.stateCheckRequired;
this.scorePlayer = game.scorePlayer;
this.scopeRelevant = game.scopeRelevant;
}
@Override
@ -1721,4 +1725,21 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
stateCheckRequired = true;
}
/**
* If true, only self scope replacement effects are applied
*
* @param scopeRelevant
*/
@Override
public void setScopeRelevant(boolean scopeRelevant) {
this.scopeRelevant = scopeRelevant;
}
/**
* @return - true if only self scope replacement effects have to be applied
*/
@Override
public boolean getScopeRelevant() {
return this.scopeRelevant;
}
}