* Added some trace output for continous effects and triggered abilities. Changed duration of AffinityEffect to WhileOnStack to prevent wrong handling for removement of the effect.

This commit is contained in:
LevelX2 2021-01-13 09:14:29 +01:00
parent 8c85c0dbad
commit 9fc0e2f25a
10 changed files with 323 additions and 48 deletions

View file

@ -1,5 +1,9 @@
package mage.abilities;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import mage.MageIdentifier;
import mage.MageObject;
import mage.abilities.costs.*;
@ -32,11 +36,6 @@ import mage.util.ThreadLocalStringBuilder;
import mage.watchers.Watcher;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -365,7 +364,7 @@ public abstract class AbilityImpl implements Ability {
//20101001 - 601.2e
if (needCostModification && sourceObject != null) {
sourceObject.adjustCosts(this, game); // still needed
sourceObject.adjustCosts(this, game); // still needed for CostAdjuster objects (to handle some types of dynamic costs)
game.getContinuousEffects().costModification(this, game);
}

View file

@ -1,5 +1,9 @@
package mage.abilities.effects;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import mage.ApprovingObject;
import mage.MageObject;
import mage.abilities.Ability;
@ -17,7 +21,6 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardIdPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
@ -26,13 +29,9 @@ import mage.players.ManaPoolItem;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
import mage.util.CardUtil;
import mage.util.trace.TraceInfo;
import org.apache.log4j.Logger;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -1391,4 +1390,85 @@ public class ContinuousEffects implements Serializable {
}
return controllerFound;
}
/**
* Prints out a status of the currently existing continuous effects
* @param game
*/
public void traceContinuousEffects(Game game) {
game.getContinuousEffects().getLayeredEffects(game);
logger.info("-------------------------------------------------------------------------------------------------");
int numberEffects = 0;
for(ContinuousEffectsList list: allEffectsLists) {
numberEffects += list.size();
}
logger.info("Turn: " + game.getTurnNum() + " - currently existing continuous effects: " + numberEffects);
logger.info("layeredEffects ...................: " + layeredEffects.size());
logger.info("continuousRuleModifyingEffects ...: " + continuousRuleModifyingEffects.size());
logger.info("replacementEffects ...............: " + replacementEffects.size());
logger.info("preventionEffects ................: " + preventionEffects.size());
logger.info("requirementEffects ...............: " + requirementEffects.size());
logger.info("restrictionEffects ...............: " + restrictionEffects.size());
logger.info("restrictionUntapNotMoreThanEffects: " + restrictionUntapNotMoreThanEffects.size());
logger.info("costModificationEffects ..........: " + costModificationEffects.size());
logger.info("spliceCardEffects ................: " + spliceCardEffects.size());
logger.info("asThoughEffects:");
for (Map.Entry<AsThoughEffectType, ContinuousEffectsList<AsThoughEffect>> entry : asThoughEffectsMap.entrySet()) {
logger.info("... " + entry.getKey().toString() + ": " + entry.getValue().size());
}
logger.info("applyCounters ....................: " + (applyCounters != null ? "exists":"null"));
logger.info("auraReplacementEffect ............: " + (continuousRuleModifyingEffects != null ? "exists":"null"));
Map<String, TraceInfo> orderedEffects = new TreeMap<>();
traceAddContinuousEffects(orderedEffects, layeredEffects, game, "layeredEffects................");
traceAddContinuousEffects(orderedEffects, continuousRuleModifyingEffects, game, "continuousRuleModifyingEffects");
traceAddContinuousEffects(orderedEffects, replacementEffects, game, "replacementEffects............");
traceAddContinuousEffects(orderedEffects, preventionEffects, game, "preventionEffects.............");
traceAddContinuousEffects(orderedEffects, requirementEffects, game, "requirementEffects............");
traceAddContinuousEffects(orderedEffects, restrictionEffects, game, "restrictionEffects............");
traceAddContinuousEffects(orderedEffects, restrictionUntapNotMoreThanEffects, game, "restrictionUntapNotMore...");
traceAddContinuousEffects(orderedEffects, costModificationEffects, game, "costModificationEffects.......");
traceAddContinuousEffects(orderedEffects, spliceCardEffects, game, "spliceCardEffects.............");
for (Map.Entry<AsThoughEffectType, ContinuousEffectsList<AsThoughEffect>> entry : asThoughEffectsMap.entrySet()) {
traceAddContinuousEffects(orderedEffects, entry.getValue(), game, entry.getKey().toString());
}
String playerName = "";
for (Map.Entry<String, TraceInfo> entry : orderedEffects.entrySet()) {
if (!entry.getValue().getPlayerName().equals(playerName)) {
playerName = entry.getValue().getPlayerName();
logger.info("--- Player: " + playerName + " --------------------------------");
}
logger.info(entry.getValue().getInfo()
+ " " + entry.getValue().getSourceName()
+ " " + entry.getValue().getDuration().name()
+ " " + entry.getValue().getRule()
+ " (Order: "+entry.getValue().getOrder() +")"
);
}
logger.info("---- End trace Continuous effects --------------------------------------------------------------------------");
}
public static void traceAddContinuousEffects(Map orderedEffects, ContinuousEffectsList<?> cel, Game game, String listName) {
for (ContinuousEffect effect : cel) {
Set<Ability> abilities = cel.getAbility(effect.getId());
for (Ability ability : abilities) {
Player controller = game.getPlayer(ability.getControllerId());
MageObject source = game.getObject(ability.getSourceId());
TraceInfo traceInfo = new TraceInfo();
traceInfo.setInfo(listName);
traceInfo.setOrder(effect.getOrder());
if (ability instanceof MageSingleton) {
traceInfo.setPlayerName("Mage Singleton");
traceInfo.setSourceName("Mage Singleton");
} else {
traceInfo.setPlayerName(controller == null ? "no controller": controller.getName());
traceInfo.setSourceName(source == null ? "no source": source.getIdName());
}
traceInfo.setRule(ability.getRule());
traceInfo.setAbilityId(ability.getId());
traceInfo.setEffectId(effect.getId());
traceInfo.setDuration(effect.getDuration());
orderedEffects.put(traceInfo.getPlayerName() + traceInfo.getSourceName() + effect.getId() + ability.getId(), traceInfo);
}
}
}
}

View file

@ -10,12 +10,18 @@ import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.util.CardUtil;
/**
* 702.40. Affinity
702.40a Affinity is a static ability that functions while the spell with affinity is on the stack.
Affinity for [text] means This spell costs you {1} less to cast for each [text] you control.
702.40b If a spell has multiple instances of affinity, each of them applies.
*/
public class AffinityEffect extends CostModificationEffectImpl {
private final FilterControlledPermanent filter;
public AffinityEffect(FilterControlledPermanent affinityFilter) {
super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST);
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
this.filter = affinityFilter;
staticText = "Affinity for " + filter.getMessage();
}

View file

@ -22,7 +22,7 @@ public class SpellCostReductionForEachSourceEffect extends CostModificationEffec
private final int reduceGenericMana;
public SpellCostReductionForEachSourceEffect(int reduceGenericMana, DynamicValue eachAmount) {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
this.eachAmount = eachAmount;
this.reduceManaCosts = null;
this.reduceGenericMana = reduceGenericMana;
@ -36,7 +36,7 @@ public class SpellCostReductionForEachSourceEffect extends CostModificationEffec
}
public SpellCostReductionForEachSourceEffect(ManaCosts<ManaCost> reduceManaCosts, DynamicValue eachAmount) {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
this.eachAmount = eachAmount;
this.reduceManaCosts = reduceManaCosts;
this.reduceGenericMana = 0;