Begin Mairsil fix

This commit is contained in:
Evan Kranzler 2017-09-11 16:26:30 -04:00
parent cea3291775
commit 650f184ee6
4 changed files with 203 additions and 241 deletions

View file

@ -27,21 +27,14 @@
*/
package mage.cards.m;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
@ -54,7 +47,6 @@ import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.SuperType;
import mage.constants.TargetController;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.FilterCard;
@ -63,15 +55,11 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.other.CounterCardPredicate;
import mage.filter.predicate.other.OwnerPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.StackAbility;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetCardInYourGraveyard;
import mage.watchers.Watcher;
/**
*
@ -93,8 +81,9 @@ public class MairsilThePretender extends CardImpl {
// Mairsil, the Pretender has all activated abilities of all cards you own in exile with cage counters on them. You may activate each of those abilities only once each turn.
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new MairsilThePretenderGainAbilitiesEffect());
ability.addEffect(new MairsilThePretenderRuleModifyingEffect());
this.addAbility(ability, new MairsilThePretenderWatcher());
this.addAbility(ability);
// ability.addEffect(new MairsilThePretenderRuleModifyingEffect());
// this.addAbility(ability, new MairsilThePretenderWatcher());
}
public MairsilThePretender(final MairsilThePretender card) {
@ -182,11 +171,8 @@ class MairsilThePretenderGainAbilitiesEffect extends ContinuousEffectImpl {
if (filter.match(card, game)) {
for (Ability ability : card.getAbilities()) {
if (ability instanceof ActivatedAbility) {
UUID originaId = ability.getId();
ActivatedAbility copyAbility = (ActivatedAbility) ability.copy();
Effect effect = new DoNothingEffect();
effect.setValue("key", originaId);
copyAbility.addEffect(effect);
ActivatedAbilityImpl copyAbility = (ActivatedAbilityImpl) ability.copy();
copyAbility.setMaxActivationsPerTurn(1);
perm.addAbility(copyAbility, card.getId(), game);
}
}
@ -203,134 +189,134 @@ class MairsilThePretenderGainAbilitiesEffect extends ContinuousEffectImpl {
}
}
class MairsilThePretenderWatcher extends Watcher {
public final Map<UUID, Set<UUID>> activatedThisTurnAbilities = new HashMap<>();
public MairsilThePretenderWatcher() {
super(MairsilThePretenderWatcher.class.getSimpleName(), WatcherScope.GAME);
}
public MairsilThePretenderWatcher(final MairsilThePretenderWatcher watcher) {
super(watcher);
for (Entry<UUID, Set<UUID>> entry : watcher.activatedThisTurnAbilities.entrySet()) {
activatedThisTurnAbilities.put(entry.getKey(), entry.getValue());
}
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event instanceof ZoneChangeEvent) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.getFromZone() == Zone.BATTLEFIELD) {
Permanent permanent = zEvent.getTarget();
if (permanent != null) {
this.activatedThisTurnAbilities.remove(permanent.getId());
}
}
}
if (event.getType() == GameEvent.EventType.ACTIVATED_ABILITY) {
Set<UUID> permAbilities;
if (activatedThisTurnAbilities.keySet().contains(event.getSourceId())) {
permAbilities = activatedThisTurnAbilities.get(event.getSourceId());
} else {
permAbilities = new HashSet<>();
}
StackAbility ability = (StackAbility) game.getStack().getStackObject(event.getSourceId());
if (ability != null && ability.getStackAbility().isActivated()) {
for (Effect effect : ability.getAllEffects()) {
if (effect instanceof DoNothingEffect) {
permAbilities.add((UUID) effect.getValue("key"));
this.activatedThisTurnAbilities.put(event.getSourceId(), permAbilities);
}
}
}
}
}
@Override
public void reset() {
activatedThisTurnAbilities.clear();
}
public Map<UUID, Set<UUID>> getActivatedThisTurnAbilities() {
return this.activatedThisTurnAbilities;
}
@Override
public MairsilThePretenderWatcher copy() {
return new MairsilThePretenderWatcher(this);
}
}
class MairsilThePretenderRuleModifyingEffect extends ContinuousRuleModifyingEffectImpl {
public MairsilThePretenderRuleModifyingEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
}
public MairsilThePretenderRuleModifyingEffect(final MairsilThePretenderRuleModifyingEffect effect) {
super(effect);
}
@Override
public MairsilThePretenderRuleModifyingEffect copy() {
return new MairsilThePretenderRuleModifyingEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ACTIVATE_ABILITY;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Optional<Ability> ability = game.getAbility(event.getTargetId(), event.getSourceId());
MairsilThePretenderWatcher watcher = (MairsilThePretenderWatcher) game.getState().getWatchers().get(MairsilThePretenderWatcher.class.getSimpleName());
if (watcher != null && ability != null && ability.isPresent()) {
for (Effect effect : ability.get().getAllEffects()) {
if (effect instanceof DoNothingEffect) {
UUID originalID = (UUID) effect.getValue("key");
if (watcher.getActivatedThisTurnAbilities().keySet().contains(event.getSourceId())) {
if (watcher.getActivatedThisTurnAbilities().get(event.getSourceId()).contains(originalID)) {
return true;
}
}
}
}
}
return false;
}
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
return "This ability can only be activated once each turn.";
}
}
class DoNothingEffect extends OneShotEffect {
DoNothingEffect() {
super(Outcome.Neutral);
}
DoNothingEffect(final DoNothingEffect effect) {
super(effect);
}
@Override
public DoNothingEffect copy() {
return new DoNothingEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
}
//class MairsilThePretenderWatcher extends Watcher {
//
// public final Map<UUID, Set<UUID>> activatedThisTurnAbilities = new HashMap<>();
//
// public MairsilThePretenderWatcher() {
// super(MairsilThePretenderWatcher.class.getSimpleName(), WatcherScope.GAME);
// }
//
// public MairsilThePretenderWatcher(final MairsilThePretenderWatcher watcher) {
// super(watcher);
// for (Entry<UUID, Set<UUID>> entry : watcher.activatedThisTurnAbilities.entrySet()) {
// activatedThisTurnAbilities.put(entry.getKey(), entry.getValue());
// }
// }
//
// @Override
// public void watch(GameEvent event, Game game) {
// if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event instanceof ZoneChangeEvent) {
// ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
// if (zEvent.getFromZone() == Zone.BATTLEFIELD) {
// Permanent permanent = zEvent.getTarget();
// if (permanent != null) {
// this.activatedThisTurnAbilities.remove(permanent.getId());
// }
// }
// }
// if (event.getType() == GameEvent.EventType.ACTIVATED_ABILITY) {
// Set<UUID> permAbilities;
// if (activatedThisTurnAbilities.keySet().contains(event.getSourceId())) {
// permAbilities = activatedThisTurnAbilities.get(event.getSourceId());
// } else {
// permAbilities = new HashSet<>();
// }
// StackAbility ability = (StackAbility) game.getStack().getStackObject(event.getSourceId());
// if (ability != null && ability.getStackAbility().isActivated()) {
// for (Effect effect : ability.getAllEffects()) {
// if (effect instanceof DoNothingEffect) {
// permAbilities.add((UUID) effect.getValue("key"));
// this.activatedThisTurnAbilities.put(event.getSourceId(), permAbilities);
// }
// }
// }
// }
// }
//
// @Override
// public void reset() {
// activatedThisTurnAbilities.clear();
// }
//
// public Map<UUID, Set<UUID>> getActivatedThisTurnAbilities() {
// return this.activatedThisTurnAbilities;
// }
//
// @Override
// public MairsilThePretenderWatcher copy() {
// return new MairsilThePretenderWatcher(this);
// }
//
//}
//
//class MairsilThePretenderRuleModifyingEffect extends ContinuousRuleModifyingEffectImpl {
//
// public MairsilThePretenderRuleModifyingEffect() {
// super(Duration.WhileOnBattlefield, Outcome.Detriment);
// }
//
// public MairsilThePretenderRuleModifyingEffect(final MairsilThePretenderRuleModifyingEffect effect) {
// super(effect);
// }
//
// @Override
// public MairsilThePretenderRuleModifyingEffect copy() {
// return new MairsilThePretenderRuleModifyingEffect(this);
// }
//
// @Override
// public boolean apply(Game game, Ability source) {
// return true;
// }
//
// @Override
// public boolean checksEventType(GameEvent event, Game game) {
// return event.getType() == GameEvent.EventType.ACTIVATE_ABILITY;
// }
//
// @Override
// public boolean applies(GameEvent event, Ability source, Game game) {
// Optional<Ability> ability = game.getAbility(event.getTargetId(), event.getSourceId());
// MairsilThePretenderWatcher watcher = (MairsilThePretenderWatcher) game.getState().getWatchers().get(MairsilThePretenderWatcher.class.getSimpleName());
// if (watcher != null && ability != null && ability.isPresent()) {
// for (Effect effect : ability.get().getAllEffects()) {
// if (effect instanceof DoNothingEffect) {
// UUID originalID = (UUID) effect.getValue("key");
// if (watcher.getActivatedThisTurnAbilities().keySet().contains(event.getSourceId())) {
// if (watcher.getActivatedThisTurnAbilities().get(event.getSourceId()).contains(originalID)) {
// return true;
// }
// }
// }
// }
// }
// return false;
// }
//
// @Override
// public String getInfoMessage(Ability source, GameEvent event, Game game) {
// return "This ability can only be activated once each turn.";
// }
//}
//
//class DoNothingEffect extends OneShotEffect {
//
// DoNothingEffect() {
// super(Outcome.Neutral);
// }
//
// DoNothingEffect(final DoNothingEffect effect) {
// super(effect);
// }
//
// @Override
// public DoNothingEffect copy() {
// return new DoNothingEffect(this);
// }
//
// @Override
// public boolean apply(Game game, Ability source) {
// return true;
// }
//}

View file

@ -29,6 +29,7 @@ package mage.abilities;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.condition.Condition;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.mana.ManaCosts;
@ -45,6 +46,7 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.game.command.Emblem;
import mage.game.permanent.Permanent;
import mage.util.CardUtil;
/**
*
@ -52,6 +54,19 @@ import mage.game.permanent.Permanent;
*/
public abstract class ActivatedAbilityImpl extends AbilityImpl implements ActivatedAbility {
static class ActivationInfo {
public int turnNum;
public int activationCounter;
public ActivationInfo(int turnNum, int activationCounter) {
this.turnNum = turnNum;
this.activationCounter = activationCounter;
}
}
protected int maxActivationsPerTurn = Integer.MAX_VALUE;
protected Condition condition;
protected TimingRule timing = TimingRule.INSTANT;
protected TargetController mayActivate = TargetController.YOU;
protected UUID activatorId;
@ -68,6 +83,8 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
mayActivate = ability.mayActivate;
activatorId = ability.activatorId;
checkPlayableMode = ability.checkPlayableMode;
maxActivationsPerTurn = ability.maxActivationsPerTurn;
condition = ability.condition;
}
public ActivatedAbilityImpl(Zone zone) {
@ -161,6 +178,9 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
@Override
public boolean canActivate(UUID playerId, Game game) {
//20091005 - 602.2
if (!(hasMoreActivationsThisTurn(game) && (condition == null || condition.apply(game, this)))) {
return false;
}
switch (mayActivate) {
case ANY:
break;
@ -255,4 +275,46 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
return checkPlayableMode;
}
private boolean hasMoreActivationsThisTurn(Game game) {
ActivationInfo activationInfo = getActivationInfo(game);
return activationInfo == null || activationInfo.turnNum != game.getTurnNum() || activationInfo.activationCounter < maxActivationsPerTurn;
}
@Override
public boolean activate(Game game, boolean noMana) {
if (hasMoreActivationsThisTurn(game)) {
if (super.activate(game, noMana)) {
ActivationInfo activationInfo = getActivationInfo(game);
if (activationInfo == null) {
activationInfo = new ActivationInfo(game.getTurnNum(), 1);
} else if (activationInfo.turnNum != game.getTurnNum()) {
activationInfo.turnNum = game.getTurnNum();
activationInfo.activationCounter = 1;
} else {
activationInfo.activationCounter++;
}
setActivationInfo(activationInfo, game);
return true;
}
}
return false;
}
public void setMaxActivationsPerTurn(int maxActivationsPerTurn) {
this.maxActivationsPerTurn = maxActivationsPerTurn;
}
private ActivationInfo getActivationInfo(Game game) {
Integer turnNum = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game));
Integer activationCount = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsCount", sourceId, game));
if (turnNum == null || activationCount == null) {
return null;
}
return new ActivationInfo(turnNum, activationCount);
}
private void setActivationInfo(ActivationInfo activationInfo, Game game) {
game.getState().setValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game), activationInfo.turnNum);
game.getState().setValue(CardUtil.getCardZoneString("activationsCount", sourceId, game), activationInfo.activationCounter);
}
}

View file

@ -25,10 +25,8 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.common;
import java.util.UUID;
import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.condition.Condition;
import mage.abilities.condition.InvertCondition;
@ -43,8 +41,6 @@ import mage.game.Game;
*/
public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl {
private final Condition condition;
public ActivateIfConditionActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition) {
super(zone, effect, cost);
this.condition = condition;
@ -52,31 +48,11 @@ public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl {
public ActivateIfConditionActivatedAbility(ActivateIfConditionActivatedAbility ability) {
super(ability);
this.condition = ability.condition;
}
@Override
public boolean canActivate(UUID playerId, Game game) {
if (condition.apply(game, this)) {
return super.canActivate(playerId, game);
}
return false;
}
@Override
public boolean activate(Game game, boolean noMana) {
if (canActivate(this.controllerId, game)) {
return super.activate(game, noMana);
}
return false;
}
@Override
public boolean resolve(Game game) {
if (super.resolve(game)) {
return true;
}
return false;
return super.resolve(game);
}
@Override
@ -88,15 +64,15 @@ public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl {
sb.append(" Activate this ability only ");
}
if (condition.toString() != null) {
if (!condition.toString().startsWith("during") &&
!condition.toString().startsWith("before")) {
if (!condition.toString().startsWith("during")
&& !condition.toString().startsWith("before")) {
sb.append("if ");
}
sb.append(condition.toString()).append('.');
} else {
sb.append(" [Condition toString() == null] ");
}
return sb.toString() ;
return sb.toString();
}
@Override

View file

@ -36,28 +36,12 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class LimitedTimesPerTurnActivatedAbility extends ActivatedAbilityImpl {
static class ActivationInfo {
public int turnNum;
public int activationCounter;
public ActivationInfo(int turnNum, int activationCounter) {
this.turnNum = turnNum;
this.activationCounter = activationCounter;
}
}
private int maxActivationsPerTurn;
private Condition condition;
public LimitedTimesPerTurnActivatedAbility(Zone zone, Effect effect, Cost cost) {
this(zone, effect, cost, 1);
}
@ -78,38 +62,6 @@ public class LimitedTimesPerTurnActivatedAbility extends ActivatedAbilityImpl {
this.condition = ability.condition;
}
@Override
public boolean canActivate(UUID playerId, Game game) {
return super.canActivate(playerId, game)
&& hasMoreActivationsThisTurn(game)
&& (condition == null || condition.apply(game, this));
}
private boolean hasMoreActivationsThisTurn(Game game) {
ActivationInfo activationInfo = getActivationInfo(game);
return activationInfo == null || activationInfo.turnNum != game.getTurnNum() || activationInfo.activationCounter < maxActivationsPerTurn;
}
@Override
public boolean activate(Game game, boolean noMana) {
if (hasMoreActivationsThisTurn(game)) {
if (super.activate(game, noMana)) {
ActivationInfo activationInfo = getActivationInfo(game);
if (activationInfo == null) {
activationInfo = new ActivationInfo(game.getTurnNum(), 1);
} else if (activationInfo.turnNum != game.getTurnNum()) {
activationInfo.turnNum = game.getTurnNum();
activationInfo.activationCounter = 1;
} else {
activationInfo.activationCounter++;
}
setActivationInfo(activationInfo, game);
return true;
}
}
return false;
}
@Override
public boolean resolve(Game game) {
return super.resolve(game);
@ -142,18 +94,4 @@ public class LimitedTimesPerTurnActivatedAbility extends ActivatedAbilityImpl {
public LimitedTimesPerTurnActivatedAbility copy() {
return new LimitedTimesPerTurnActivatedAbility(this);
}
private ActivationInfo getActivationInfo(Game game) {
Integer turnNum = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game));
Integer activationCount = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsCount", sourceId, game));
if (turnNum == null || activationCount == null) {
return null;
}
return new ActivationInfo(turnNum, activationCount);
}
private void setActivationInfo(ActivationInfo activationInfo, Game game) {
game.getState().setValue(CardUtil.getCardZoneString("activationsTurn", sourceId, game), activationInfo.turnNum);
game.getState().setValue(CardUtil.getCardZoneString("activationsCount", sourceId, game), activationInfo.activationCounter);
}
}