* Fixed problems with LockedInCondition() that did not work as intended if spells were reused because conditions have no deep copy.

This commit is contained in:
LevelX2 2014-08-30 00:46:29 +02:00
parent c1fd249c97
commit fbc2a7258f
36 changed files with 309 additions and 219 deletions

View file

@ -31,8 +31,14 @@ import mage.abilities.Ability;
import mage.game.Game;
/**
* A simple {@link Condition} to check the condition only one time at the start (result locked in).
* All subsequent checks return the first result.
* The use of this class must be handled carefully because conditions don't
* have a copy method, the condition state is kept when the effect or ability
* is copied that uses the condition.
* So if you use this class, you have to do it like in ConditionalContinuousEffect,
* where always a new FixedCondition(condition.apply(...)) is used if a
* LockedInCondition is given.
*
* Needs probably some redesign, don't like it the way it's done now.
*
* @author LevelX2
*/
@ -40,7 +46,7 @@ public class LockedInCondition implements Condition {
private boolean conditionChecked = false;
private boolean result;
private Condition condition;
private final Condition condition;
public LockedInCondition ( Condition condition ) {
this.condition = condition;
@ -58,4 +64,8 @@ public class LockedInCondition implements Condition {
return result;
}
public Condition getBaseCondition() {
return condition;
}
}

View file

@ -37,7 +37,7 @@ import mage.watchers.Watcher;
*/
public class MorbidCondition implements Condition {
private static MorbidCondition fInstance = new MorbidCondition();
private static final MorbidCondition fInstance = new MorbidCondition();
public static Condition getInstance() {
return fInstance;
@ -48,4 +48,5 @@ public class MorbidCondition implements Condition {
Watcher watcher = game.getState().getWatchers().get("Morbid");
return watcher.conditionMet();
}
}

View file

@ -45,19 +45,17 @@ public class ConditionalAsThoughEffect extends AsThoughEffectImpl {
protected AsThoughEffect effect;
protected AsThoughEffect otherwiseEffect;
protected Condition condition;
protected boolean lockedInCondition;
protected boolean conditionState;
public ConditionalAsThoughEffect(AsThoughEffect effect, Condition condition, boolean lockedInCondition) {
this(effect, condition, null, lockedInCondition);
public ConditionalAsThoughEffect(AsThoughEffect effect, Condition condition) {
this(effect, condition, null);
}
public ConditionalAsThoughEffect(AsThoughEffect effect, Condition condition, AsThoughEffect otherwiseEffect, boolean lockedInCondition) {
public ConditionalAsThoughEffect(AsThoughEffect effect, Condition condition, AsThoughEffect otherwiseEffect) {
super(effect.getAsThoughEffectType(), effect.getDuration(), effect.getOutcome());
this.effect = effect;
this.condition = condition;
this.otherwiseEffect = otherwiseEffect;
this.lockedInCondition = lockedInCondition;
}
public ConditionalAsThoughEffect(final ConditionalAsThoughEffect effect) {
@ -67,7 +65,6 @@ public class ConditionalAsThoughEffect extends AsThoughEffectImpl {
this.otherwiseEffect = (AsThoughEffect) effect.otherwiseEffect.copy();
}
this.condition = effect.condition;
this.lockedInCondition = effect.lockedInCondition;
this.conditionState = effect.conditionState;
}
@ -78,9 +75,6 @@ public class ConditionalAsThoughEffect extends AsThoughEffectImpl {
@Override
public boolean apply(Game game, Ability source) {
if (lockedInCondition && !(condition instanceof FixedCondition)) {
condition = new FixedCondition(condition.apply(game, source));
}
conditionState = condition.apply(game, source);
if (conditionState) {
effect.setTargetPointer(this.targetPointer);
@ -100,9 +94,6 @@ public class ConditionalAsThoughEffect extends AsThoughEffectImpl {
@Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
if (lockedInCondition && !(condition instanceof FixedCondition)) {
condition = new FixedCondition(condition.apply(game, source));
}
conditionState = condition.apply(game, source);
if (conditionState) {
effect.setTargetPointer(this.targetPointer);

View file

@ -4,6 +4,7 @@ import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.condition.Condition;
import mage.abilities.condition.FixedCondition;
import mage.abilities.condition.LockedInCondition;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.Duration;
@ -20,18 +21,15 @@ public class ConditionalContinousEffect extends ContinuousEffectImpl {
protected ContinuousEffect effect;
protected ContinuousEffect otherwiseEffect;
protected Condition baseCondition;
protected Condition condition;
protected boolean lockedInCondition;
protected boolean initDone = false;
public ConditionalContinousEffect(ContinuousEffect effect, Condition condition, String text) {
this(effect, null, condition, text);
}
public ConditionalContinousEffect(ContinuousEffect effect, Condition condition, String text, boolean lockedInCondition) {
this(effect, null, condition, text, lockedInCondition);
}
/**
* Only use this if both effects have the same layers
*
@ -41,25 +39,11 @@ public class ConditionalContinousEffect extends ContinuousEffectImpl {
* @param text
*/
public ConditionalContinousEffect(ContinuousEffect effect, ContinuousEffect otherwiseEffect, Condition condition, String text) {
this(effect, otherwiseEffect, condition, text, false);
}
/**
* Only use this if both effects have the same layers
*
* @param effect
* @param otherwiseEffect
* @param condition
* @param text
* @param lockedInCondition
*/
public ConditionalContinousEffect(ContinuousEffect effect, ContinuousEffect otherwiseEffect, Condition condition, String text, boolean lockedInCondition) {
super(effect.getDuration(), effect.getLayer(), effect.getSublayer(), effect.getOutcome());
this.effect = effect;
this.otherwiseEffect = otherwiseEffect;
this.condition = condition;
this.baseCondition = condition;
this.staticText = text;
this.lockedInCondition = lockedInCondition;
}
public ConditionalContinousEffect(final ConditionalContinousEffect effect) {
@ -69,7 +53,7 @@ public class ConditionalContinousEffect extends ContinuousEffectImpl {
this.otherwiseEffect = (ContinuousEffect) effect.otherwiseEffect.copy();
}
this.condition = effect.condition;
this.lockedInCondition = effect.lockedInCondition;
this.baseCondition = effect.baseCondition;
this.initDone = effect.initDone;
}
@ -80,8 +64,10 @@ public class ConditionalContinousEffect extends ContinuousEffectImpl {
@Override
public void init(Ability source, Game game) {
if (lockedInCondition) {
condition = new FixedCondition(condition.apply(game, source));
if (baseCondition instanceof LockedInCondition) {
condition = new FixedCondition(((LockedInCondition) baseCondition).getBaseCondition().apply(game, source));
} else {
condition = baseCondition;
}
effect.setTargetPointer(this.targetPointer);
effect.init(source, game);

View file

@ -31,6 +31,7 @@ import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.condition.Condition;
import mage.abilities.condition.FixedCondition;
import mage.abilities.condition.LockedInCondition;
import mage.abilities.effects.ContinuousRuleModifiyingEffect;
import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl;
import mage.game.Game;
@ -45,19 +46,18 @@ public class ConditionalContinuousRuleModifyingEffect extends ContinuousRuleModi
protected ContinuousRuleModifiyingEffect effect;
protected ContinuousRuleModifiyingEffect otherwiseEffect;
protected Condition condition;
protected boolean lockedInCondition;
protected boolean conditionState;
protected Condition baseCondition;
protected boolean initDone = false;
public ConditionalContinuousRuleModifyingEffect(ContinuousRuleModifiyingEffect effect, Condition condition, boolean lockedInCondition) {
this(effect, condition, null, lockedInCondition);
public ConditionalContinuousRuleModifyingEffect(ContinuousRuleModifiyingEffect effect, Condition condition) {
this(effect, condition, null);
}
public ConditionalContinuousRuleModifyingEffect(ContinuousRuleModifiyingEffect effect, Condition condition, ContinuousRuleModifiyingEffect otherwiseEffect, boolean lockedInCondition) {
public ConditionalContinuousRuleModifyingEffect(ContinuousRuleModifiyingEffect effect, Condition condition, ContinuousRuleModifiyingEffect otherwiseEffect) {
super(effect.getDuration(), effect.getOutcome());
this.effect = effect;
this.condition = condition;
this.baseCondition = condition;
this.otherwiseEffect = otherwiseEffect;
this.lockedInCondition = lockedInCondition;
}
public ConditionalContinuousRuleModifyingEffect(final ConditionalContinuousRuleModifyingEffect effect) {
@ -67,10 +67,28 @@ public class ConditionalContinuousRuleModifyingEffect extends ContinuousRuleModi
this.otherwiseEffect = (ContinuousRuleModifiyingEffect) effect.otherwiseEffect.copy();
}
this.condition = effect.condition;
this.lockedInCondition = effect.lockedInCondition;
this.conditionState = effect.conditionState;
this.baseCondition = effect.baseCondition;
this.initDone = effect.initDone;
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
if (baseCondition instanceof LockedInCondition) {
condition = new FixedCondition(((LockedInCondition) baseCondition).getBaseCondition().apply(game, source));
} else {
condition = baseCondition;
}
effect.setTargetPointer(this.targetPointer);
effect.init(source, game);
if (otherwiseEffect != null) {
otherwiseEffect.setTargetPointer(this.targetPointer);
otherwiseEffect.init(source, game);
}
initDone = true;
}
@Override
public boolean isDiscarded() {
return effect.isDiscarded() || (otherwiseEffect != null && otherwiseEffect.isDiscarded());
@ -83,11 +101,10 @@ public class ConditionalContinuousRuleModifyingEffect extends ContinuousRuleModi
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (lockedInCondition && !(condition instanceof FixedCondition)) {
condition = new FixedCondition(condition.apply(game, source));
if (!initDone) { // if simpleStaticAbility, init won't be called
init(source, game);
}
conditionState = condition.apply(game, source);
if (conditionState) {
if (condition.apply(game, source)) {
effect.setTargetPointer(this.targetPointer);
return effect.applies(event, source, game);
} else if (otherwiseEffect != null) {

View file

@ -31,6 +31,7 @@ import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.condition.Condition;
import mage.abilities.condition.FixedCondition;
import mage.abilities.condition.LockedInCondition;
import mage.abilities.effects.ReplacementEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.constants.Duration;
@ -45,20 +46,20 @@ public class ConditionalReplacementEffect extends ReplacementEffectImpl {
protected ReplacementEffect effect;
protected ReplacementEffect otherwiseEffect;
protected Condition baseCondition;
protected Condition condition;
protected boolean lockedInCondition;
protected boolean conditionState;
protected boolean initDone = false;
public ConditionalReplacementEffect(ReplacementEffect effect, Condition condition, boolean lockedInCondition) {
this(effect, condition, null, lockedInCondition);
public ConditionalReplacementEffect(ReplacementEffect effect, Condition condition) {
this(effect, condition, null);
}
public ConditionalReplacementEffect(ReplacementEffect effect, Condition condition, ReplacementEffect otherwiseEffect, boolean lockedInCondition) {
public ConditionalReplacementEffect(ReplacementEffect effect, Condition condition, ReplacementEffect otherwiseEffect) {
super(effect.getDuration(), effect.getOutcome());
this.effect = effect;
this.condition = condition;
this.baseCondition = condition;
this.otherwiseEffect = otherwiseEffect;
this.lockedInCondition = lockedInCondition;
}
public ConditionalReplacementEffect(final ConditionalReplacementEffect effect) {
@ -68,8 +69,9 @@ public class ConditionalReplacementEffect extends ReplacementEffectImpl {
this.otherwiseEffect = (ReplacementEffect) effect.otherwiseEffect.copy();
}
this.condition = effect.condition;
this.lockedInCondition = effect.lockedInCondition;
this.conditionState = effect.conditionState;
this.baseCondition = effect.baseCondition;
this.initDone = effect.initDone;
}
@Override
@ -77,6 +79,23 @@ public class ConditionalReplacementEffect extends ReplacementEffectImpl {
return effect.isDiscarded() || (otherwiseEffect != null && otherwiseEffect.isDiscarded());
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
if (baseCondition instanceof LockedInCondition) {
condition = new FixedCondition(((LockedInCondition) baseCondition).getBaseCondition().apply(game, source));
} else {
condition = baseCondition;
}
effect.setTargetPointer(this.targetPointer);
effect.init(source, game);
if (otherwiseEffect != null) {
otherwiseEffect.setTargetPointer(this.targetPointer);
otherwiseEffect.init(source, game);
}
initDone = true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
if (conditionState) {
@ -102,8 +121,8 @@ public class ConditionalReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (lockedInCondition && !(condition instanceof FixedCondition)) {
condition = new FixedCondition(condition.apply(game, source));
if (!initDone) { // if simpleStaticAbility, init won't be called
init(source, game);
}
conditionState = condition.apply(game, source);
if (conditionState) {

View file

@ -31,6 +31,7 @@ import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.abilities.condition.FixedCondition;
import mage.abilities.condition.LockedInCondition;
import mage.abilities.effects.RequirementEffect;
import mage.constants.Duration;
import mage.constants.EffectType;
@ -47,8 +48,9 @@ public class ConditionalRequirementEffect extends RequirementEffect {
protected RequirementEffect effect;
protected RequirementEffect otherwiseEffect;
protected Condition condition;
protected boolean lockedInCondition;
protected boolean conditionState;
protected Condition baseCondition;
protected boolean initDone = false;
public ConditionalRequirementEffect(RequirementEffect effect, Condition condition) {
this(Duration.WhileOnBattlefield, effect, condition, null, false);
@ -58,9 +60,8 @@ public class ConditionalRequirementEffect extends RequirementEffect {
super(duration);
this.effectType = EffectType.REQUIREMENT;
this.effect = effect;
this.condition = condition;
this.baseCondition = condition;
this.otherwiseEffect = otherwiseEffect;
this.lockedInCondition = lockedInCondition;
}
public ConditionalRequirementEffect(final ConditionalRequirementEffect effect) {
@ -70,14 +71,32 @@ public class ConditionalRequirementEffect extends RequirementEffect {
this.otherwiseEffect = (RequirementEffect) effect.otherwiseEffect.copy();
}
this.condition = effect.condition;
this.lockedInCondition = effect.lockedInCondition;
this.conditionState = effect.conditionState;
this.baseCondition = effect.baseCondition;
this.initDone = effect.initDone;
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
if (baseCondition instanceof LockedInCondition) {
condition = new FixedCondition(((LockedInCondition) baseCondition).getBaseCondition().apply(game, source));
} else {
condition = baseCondition;
}
effect.setTargetPointer(this.targetPointer);
effect.init(source, game);
if (otherwiseEffect != null) {
otherwiseEffect.setTargetPointer(this.targetPointer);
otherwiseEffect.init(source, game);
}
initDone = true;
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
if (lockedInCondition && !(condition instanceof FixedCondition)) {
condition = new FixedCondition(condition.apply(game, source));
if (!initDone) { // if simpleStaticAbility, init won't be called
init(source, game);
}
conditionState = condition.apply(game, source);
if (conditionState) {

View file

@ -31,6 +31,7 @@ package mage.abilities.decorator;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.abilities.condition.FixedCondition;
import mage.abilities.condition.LockedInCondition;
import mage.abilities.effects.RestrictionEffect;
import mage.constants.Duration;
import mage.constants.EffectType;
@ -47,20 +48,20 @@ public class ConditionalRestrictionEffect extends RestrictionEffect {
protected RestrictionEffect effect;
protected RestrictionEffect otherwiseEffect;
protected Condition condition;
protected boolean lockedInCondition;
protected boolean conditionState;
protected Condition baseCondition;
protected boolean initDone = false;
public ConditionalRestrictionEffect(RestrictionEffect effect, Condition condition) {
this(Duration.WhileOnBattlefield, effect, condition, null, false);
this(Duration.WhileOnBattlefield, effect, condition, null);
}
public ConditionalRestrictionEffect(Duration duration, RestrictionEffect effect, Condition condition, RestrictionEffect otherwiseEffect, boolean lockedInCondition) {
public ConditionalRestrictionEffect(Duration duration, RestrictionEffect effect, Condition condition, RestrictionEffect otherwiseEffect) {
super(duration);
this.effectType = EffectType.RESTRICTION;
this.effect = effect;
this.condition = condition;
this.baseCondition = condition;
this.otherwiseEffect = otherwiseEffect;
this.lockedInCondition = lockedInCondition;
}
public ConditionalRestrictionEffect(final ConditionalRestrictionEffect effect) {
@ -70,14 +71,33 @@ public class ConditionalRestrictionEffect extends RestrictionEffect {
this.otherwiseEffect = (RestrictionEffect) effect.otherwiseEffect.copy();
}
this.condition = effect.condition;
this.lockedInCondition = effect.lockedInCondition;
this.conditionState = effect.conditionState;
this.baseCondition = effect.baseCondition;
this.initDone = effect.initDone;
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
if (baseCondition instanceof LockedInCondition) {
condition = new FixedCondition(((LockedInCondition) baseCondition).getBaseCondition().apply(game, source));
} else {
condition = baseCondition;
}
effect.setTargetPointer(this.targetPointer);
effect.init(source, game);
if (otherwiseEffect != null) {
otherwiseEffect.setTargetPointer(this.targetPointer);
otherwiseEffect.init(source, game);
}
initDone = true;
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
if (lockedInCondition && !(condition instanceof FixedCondition)) {
condition = new FixedCondition(condition.apply(game, source));
if (!initDone) { // if simpleStaticAbility, init won't be called
init(source, game);
}
conditionState = condition.apply(game, source);
if (conditionState) {

View file

@ -31,13 +31,14 @@ public class ConditionalTriggeredAbility extends TriggeredAbilityImpl {
this.text = text;
}
public ConditionalTriggeredAbility(ConditionalTriggeredAbility triggered) {
public ConditionalTriggeredAbility(final ConditionalTriggeredAbility triggered) {
super(triggered);
this.ability = triggered.ability;
this.condition = triggered.condition;
this.text = triggered.text;
}
@Override
public boolean checkInterveningIfClause(Game game) {
return condition.apply(game, this);

View file

@ -1957,6 +1957,11 @@ public abstract class PlayerImpl implements Player, Serializable {
playable.add(ability);
}
}
LinkedHashMap<UUID, ActivatedAbility> useable = new LinkedHashMap<>();
getOtherUseableActivatedAbilities(card, Zone.GRAVEYARD, game, useable);
for (Ability ability: useable.values()) {
playable.add(ability);
}
}
for (ExileZone exile : game.getExile().getExileZones()) {
for (Card card : exile.getCards(game)) {