Fixed cost modification order (Rule 601.2e) and added CostModificationType

This commit is contained in:
Plopman 2013-09-24 19:52:58 +02:00
parent d2f83b1ade
commit 3144409c2c
27 changed files with 222 additions and 28 deletions

View file

@ -50,6 +50,7 @@ import mage.abilities.keyword.SpliceOntoArcaneAbility;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.AsThoughEffectType;
import mage.constants.CostModificationType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
@ -453,6 +454,20 @@ public class ContinuousEffects implements Serializable {
return asThoughEffectsList;
}
/**
* 601.2e The player determines the total cost of the spell. Usually this is
* just the mana cost. Some spells have additional or alternative costs. Some
* effects may increase or reduce the cost to pay, or may provide other alternative costs.
* Costs may include paying mana, tapping permanents, sacrificing permanents,
* discarding cards, and so on. The total cost is the mana cost or alternative
* cost (as determined in rule 601.2b), plus all additional costs and cost increases,
* and minus all cost reductions. If the mana component of the total cost is reduced
* to nothing by cost reduction effects, it is considered to be {0}.
* It cant be reduced to less than {0}. Once the total cost is determined,
* any effects that directly affect the total cost are applied.
* Then the resulting total cost becomes locked in.
* If effects would change the total cost after this time, they have no effect.
*/
/**
* Inspects all {@link Permanent permanent's} {@link Ability abilities} on the battlefield
* for {@link CostModificationEffect cost modification effects} and applies them if necessary.
@ -465,10 +480,34 @@ public class ContinuousEffects implements Serializable {
List<CostModificationEffect> costEffects = getApplicableCostModificationEffects(game);
for ( CostModificationEffect effect : costEffects) {
HashSet<Ability> abilities = costModificationEffects.getAbility(effect.getId());
for (Ability ability : abilities) {
if ( effect.applies(abilityToModify, ability, game) ) {
effect.apply(game, ability, abilityToModify);
if(effect.getModificationType() == CostModificationType.INCREASE_COST){
HashSet<Ability> abilities = costModificationEffects.getAbility(effect.getId());
for (Ability ability : abilities) {
if ( effect.applies(abilityToModify, ability, game) ) {
effect.apply(game, ability, abilityToModify);
}
}
}
}
for ( CostModificationEffect effect : costEffects) {
if(effect.getModificationType() == CostModificationType.REDUCE_COST){
HashSet<Ability> abilities = costModificationEffects.getAbility(effect.getId());
for (Ability ability : abilities) {
if ( effect.applies(abilityToModify, ability, game) ) {
effect.apply(game, ability, abilityToModify);
}
}
}
}
for ( CostModificationEffect effect : costEffects) {
if(effect.getModificationType() == CostModificationType.SET_COST){
HashSet<Ability> abilities = costModificationEffects.getAbility(effect.getId());
for (Ability ability : abilities) {
if ( effect.applies(abilityToModify, ability, game) ) {
effect.apply(game, ability, abilityToModify);
}
}
}
}

View file

@ -29,6 +29,7 @@
package mage.abilities.effects;
import mage.abilities.Ability;
import mage.constants.CostModificationType;
import mage.game.Game;
/**
@ -64,4 +65,10 @@ public interface CostModificationEffect<T extends CostModificationEffect<T>> ext
* @return
*/
boolean applies(Ability abilityToModify, Ability source, Game game);
/**
* Return the type of modification
* @return
*/
CostModificationType getModificationType();
}

View file

@ -32,6 +32,7 @@ import mage.constants.Duration;
import mage.constants.EffectType;
import mage.constants.Outcome;
import mage.abilities.Ability;
import mage.constants.CostModificationType;
import mage.game.Game;
/**
@ -42,14 +43,18 @@ import mage.game.Game;
*/
public abstract class CostModificationEffectImpl<T extends CostModificationEffectImpl<T>> extends ContinuousEffectImpl<T> implements CostModificationEffect<T> {
public CostModificationEffectImpl ( Duration duration, Outcome outcome ) {
private CostModificationType modificationType;
public CostModificationEffectImpl ( Duration duration, Outcome outcome, CostModificationType type) {
super(duration, outcome);
this.effectType = EffectType.COSTMODIFICATION;
this.modificationType = type;
}
public CostModificationEffectImpl(final CostModificationEffectImpl<T> effect) {
super(effect);
this.effectType = effect.effectType;
this.modificationType = effect.modificationType;
}
/**
@ -63,4 +68,10 @@ public abstract class CostModificationEffectImpl<T extends CostModificationEffec
*/
@Override
public final boolean apply ( Game game, Ability source ) { return false; }
@Override
public CostModificationType getModificationType(){
return this.modificationType;
}
}

View file

@ -4,6 +4,7 @@ import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.effects.CostModificationEffectImpl;
import mage.constants.CostModificationType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.common.FilterControlledPermanent;
@ -13,7 +14,7 @@ public class AffinityEffect extends CostModificationEffectImpl<AffinityEffect> {
private FilterControlledPermanent filter;
public AffinityEffect(FilterControlledPermanent affinityFilter) {
super(Duration.Custom, Outcome.Benefit);
super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST);
this.filter = affinityFilter;
staticText = "Affinity for " + filter.getMessage();
}

View file

@ -32,6 +32,7 @@ import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.CastCommanderAbility;
import mage.abilities.effects.CostModificationEffectImpl;
import mage.constants.CostModificationType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
@ -50,7 +51,7 @@ public class CommanderCostModification extends CostModificationEffectImpl<Comman
private UUID commander;
public CommanderCostModification(UUID commander) {
super(Duration.Custom, Outcome.Neutral);
super(Duration.Custom, Outcome.Neutral, CostModificationType.INCREASE_COST);
this.commander = commander;
}

View file

@ -0,0 +1,87 @@
/*
* 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.abilities.effects.common.cost;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.effects.CostModificationEffectImpl;
import mage.abilities.keyword.FlashbackAbility;
import mage.cards.Card;
import mage.constants.CostModificationType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.util.CardUtil;
/**
*
* @author Plopman
*/
public class SpellsCostIncreasementAllEffect extends CostModificationEffectImpl<SpellsCostIncreasementAllEffect> {
private FilterCard filter;
private int amount;
public SpellsCostIncreasementAllEffect(int amount) {
this(new FilterCard("All Spells "), amount);
}
public SpellsCostIncreasementAllEffect(FilterCard filter, int amount) {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
this.filter = filter;
this.amount = amount;
this.staticText = new StringBuilder(filter.getMessage()).append(" cost {").append(amount).append("} more to cast").toString();
}
protected SpellsCostIncreasementAllEffect(SpellsCostIncreasementAllEffect effect) {
super(effect);
this.filter = effect.filter;
this.amount = effect.amount;
}
@Override
public boolean apply(Game game, Ability source, Ability abilityToModify) {
CardUtil.increaseCost(abilityToModify, this.amount);
return true;
}
@Override
public boolean applies(Ability abilityToModify, Ability source, Game game) {
if ((abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility)) {
Card sourceCard = game.getCard(abilityToModify.getSourceId());
return sourceCard != null && this.filter.match(sourceCard, game);
}
return false;
}
@Override
public SpellsCostIncreasementAllEffect copy() {
return new SpellsCostIncreasementAllEffect(this);
}
}

View file

@ -32,6 +32,7 @@ import mage.abilities.SpellAbility;
import mage.abilities.effects.CostModificationEffectImpl;
import mage.abilities.keyword.FlashbackAbility;
import mage.cards.Card;
import mage.constants.CostModificationType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.FilterCard;
@ -52,7 +53,7 @@ public class SpellsCostReductionAllEffect extends CostModificationEffectImpl<Spe
}
public SpellsCostReductionAllEffect(FilterCard filter, int amount) {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
this.filter = filter;
this.amount = amount;
this.staticText = new StringBuilder(filter.getMessage()).append(" cost {").append(amount).append("} less to cast").toString();

View file

@ -34,6 +34,7 @@ import mage.abilities.SpellAbility;
import mage.abilities.effects.CostModificationEffectImpl;
import mage.abilities.keyword.FlashbackAbility;
import mage.cards.Card;
import mage.constants.CostModificationType;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.util.CardUtil;
@ -48,7 +49,7 @@ public class SpellsCostReductionEffect extends CostModificationEffectImpl<Spells
private int amount;
public SpellsCostReductionEffect(FilterCard filter, int amount) {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
this.filter = filter;
this.amount = amount;

View file

@ -0,0 +1,38 @@
/*
* 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.constants;
/**
*
* @author Plopman
*/
public enum CostModificationType {
INCREASE_COST,
REDUCE_COST,
SET_COST
}